From d6c486408662a597300c7498f9e7efb197edce10 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 22 Dec 2020 14:12:01 +0100 Subject: [PATCH 0001/2059] Fix omr-update --- omr-update/files/etc/init.d/omr-update | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/omr-update/files/etc/init.d/omr-update b/omr-update/files/etc/init.d/omr-update index 0199bb214..6f79dae88 100755 --- a/omr-update/files/etc/init.d/omr-update +++ b/omr-update/files/etc/init.d/omr-update @@ -2,7 +2,7 @@ # Copyright (C) 2018 Ycarus (Yannick Chabanois) # Released under GPL 3. See LICENSE for the full terms. -START=9 +START=1 STOP=98 boot() { @@ -24,15 +24,15 @@ boot() { return 0 } if [ "$(uci -q get openmptcprouter.settings.version)" != "${OMRVERSION}" ]; then + uci -q set openmptcprouter.settings=settings + uci -q set openmptcprouter.settings.version=${OMRVERSION} + uci commit cd /rom/etc/uci-defaults || cd /usr/share/omr-update || return 0 files="$(ls)" [ -z "$files" ] && return 0 for file in $files; do ( . "./$(basename $file)" ) done - uci -q set openmptcprouter.settings=settings - uci -q set openmptcprouter.settings.version=${OMRVERSION} - uci commit fi # temporary hack until configd exists /sbin/reload_config From c0b5bb46524b277d6d8010296a67e7a223abc762 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 22 Dec 2020 14:15:34 +0100 Subject: [PATCH 0002/2059] Fix socket path --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 0acd9fd6f..70beaade9 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -12,6 +12,13 @@ uci -q batch <<-EOF >/dev/null commit fstab EOF +if [ "$(uci -q get rpcd.@rpcd[0].socket)" != "/var/run/ubus/ubus.sock" ]; then + uci -q batch <<-EOF >/dev/null + set rpcd.@rpcd[0].socket='/var/run/ubus/ubus.sock' + commit rpcd + EOF +fi + /sbin/block detect > /etc/config/fstab [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep raspberry)" ] && [ "$(uci -q get openmptcprouter.settings.scaling_governor)" != "performance" ] && { From db0ba4af80a29bb7bef22ce44b29052625399703 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 24 Dec 2020 08:48:48 +0100 Subject: [PATCH 0003/2059] Try to fix glorytun udp backup --- .../files/usr/share/omr/post-tracking.d/post-tracking | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index b3ce9fa8e..d1f74cffd 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -580,22 +580,22 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate pref 1 auto tx $((upload*1000/8)) rx $((download*1000/8)) > /dev/null 2>&1 else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate fixed tx $((upload*1000/8)) rx $((download*1000/8)) > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate pref 1 fixed tx $((upload*1000/8)) rx $((download*1000/8)) > /dev/null 2>&1 fi else if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate auto tx 12500000 rx 12500000 > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up pref 1 rate auto tx 12500000 rx 12500000 > /dev/null 2>&1 else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate fixed tx 12500000 rx 12500000 > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up pref 1 rate fixed tx 12500000 rx 12500000 > /dev/null 2>&1 fi fi fi # if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp set | grep 'kxtimeout 7d')" = "" ]; then # glorytun-udp set dev tun0 kxtimeout 7d > /dev/null 2>&1 # fi - [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set pref 500 > /dev/null 2>&1 + [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set pref 200 > /dev/null 2>&1 fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { From 66f8f2b2fec37dfcc99dfb2464c2297f55c7898e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 28 Dec 2020 14:45:13 +0100 Subject: [PATCH 0004/2059] Add option to enable/disable interface rename --- .../luasrc/controller/openmptcprouter.lua | 4 ++++ .../luasrc/view/openmptcprouter/settings.htm | 10 ++++++++++ .../root/etc/hotplug.d/net/99-omr-rename | 8 +++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 5de2cda24..f30be2a41 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -864,6 +864,10 @@ function settings_add() local disablegwping = luci.http.formvalue("disablegwping") or "0" ucic:set("openmptcprouter","settings","disablegwping",disablegwping) + -- Enable/disable renaming intf + local disableintfrename = luci.http.formvalue("disableintfrename") or "0" + ucic:set("openmptcprouter","settings","disableintfrename",disableintfrename) + -- Enable/disable default gateway local disabledefaultgw = luci.http.formvalue("disabledefaultgw") or "1" ucic:set("openmptcprouter","settings","defaultgw",disabledefaultgw) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index 50c4ccce3..5ec0b3c2c 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -244,6 +244,16 @@ +
+ +
+ checked<% end %>> +
+
+ <%:Disable renaming interfaces%> +
+
+
diff --git a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename index ad256bae9..19fcf1b1e 100644 --- a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename +++ b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename @@ -58,6 +58,8 @@ _set_intf_name() { } } -config_load network -config_foreach _set_intf_name interface -config_foreach _set_intf_name interface +if [ "$(uci -q get openmptcprouter.settings.disableintfrename)" != "0" ]; then + config_load network + config_foreach _set_intf_name interface + config_foreach _set_intf_name interface +fi \ No newline at end of file From 1882a94f45cbb6babb06661bd2360f878fcfcd1f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 29 Dec 2020 14:52:44 +0100 Subject: [PATCH 0005/2059] Fix DNS check --- omr-tracker/files/bin/omr-tracker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index d2211fcb5..2e7b3d96a 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -150,8 +150,8 @@ _dns() { -b "${deviceip}" \ +time="$OMR_TRACKER_TIMEOUT" \ +tries=1 \ - openmptcprouter.com - ) && echo "$ret" | grep -sq "94.23.252.192" && { + one.one.one.one + ) && echo "$ret" | grep -sq "1.1.1.1" && { OMR_TRACKER_LATENCY=$(echo "$ret" | awk '/Query time/{print $4}') _update_rto "$OMR_TRACKER_LATENCY" return From 0cc5f3622a574f21ddb005e9d8a02478f61ceb41 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 29 Dec 2020 14:53:10 +0100 Subject: [PATCH 0006/2059] Add GRE tracker --- omr-tracker/files/bin/omr-tracker-gre | 46 ++++++++++++++++++++++++ omr-tracker/files/etc/init.d/omr-tracker | 31 ++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100755 omr-tracker/files/bin/omr-tracker-gre diff --git a/omr-tracker/files/bin/omr-tracker-gre b/omr-tracker/files/bin/omr-tracker-gre new file mode 100755 index 000000000..b169d21d8 --- /dev/null +++ b/omr-tracker/files/bin/omr-tracker-gre @@ -0,0 +1,46 @@ +#!/bin/sh +# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : + +name=$0 +basename="$(basename $0)" + +_log() { + logger -p daemon.info -t "${basename}" "$@" +} + +_ping_server() { + local host=$1 + ret=$(ping \ + -w "$OMR_TRACKER_TIMEOUT" \ + -c 1 \ + -q \ + "${host}" + ) && echo "$ret" | grep -sq " 0% packet loss" && { + server_ping=true + } +} + +_ping_tunnel() { + local name=$1 + config_get gateway $1 gateway + config_get ifname $1 ifname + config_get disabled $1 disabled + [ "$(echo $ifname | grep omrip)" != "" ] && [ -n "$gateway" ] && [ "$disabled" != "1" ] && { + _ping_server $gateway + } +} + +. /lib/functions.sh + +timeout=${OMR_TRACKER_TIMEOUT:-5} +interval=${OMR_TRACKER_INTERVAL:-10} +intervaltries=${OMR_TRACKER_INTERVAL_TRIES:-2} +retry=${OMR_TRACKER_TRIES:-4} +waittest=${OMR_TRACKER_WAIT_TEST:-0} + +while true; do + server_ping=false + config_load network + config_foreach _ping_tunnel interface + sleep "${interval}" +done diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index e7bf920a7..3612c57ee 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -103,6 +103,28 @@ _launch_server_tracker() { procd_close_instance } +_launch_gre_tracker() { + local hosts timeout tries interval interval_tries options type enabled wait_test + _validate_section "defaults" "defaults" + _validate_section "gre" "gre" + + [ "${enabled}" = "0" ] && return + [ -z "${interval_tries}" ] && interval_tries=1 + + procd_open_instance + # shellcheck disable=SC2086 + procd_set_param command /bin/omr-tracker-gre "$1" $options + procd_append_param env "OMR_TRACKER_TIMEOUT=$timeout" + procd_append_param env "OMR_TRACKER_TRIES=$tries" + procd_append_param env "OMR_TRACKER_INTERVAL=$interval" + procd_append_param env "OMR_TRACKER_INTERVAL_TRIES=$interval_tries" + procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" + procd_set_param limits nofile="51200 51200" + procd_set_param respawn 0 10 0 + procd_set_param stderr 1 + procd_close_instance +} + _initialize_shadowsocks_tracker() { local redir_tcp server tracker_server config_get redir_tcp ss_rules redir_tcp @@ -199,6 +221,11 @@ _multi_server() { [ "$backup" = "1" ] && multiserver=true } +_gre_tunnel() { + config_get proto $1 proto + [ "$proto" = "gre" ] && gretunnel=true +} + start_service() { local ss_disabled logger -t "omr-tracker" "Launching..." @@ -224,6 +251,10 @@ start_service() { config_load openmptcprouter config_foreach _multi_server server [ "$multiserver" = true ] && _launch_server_tracker + gretunnel=false + config_load network + config_foreach _gre_tunnel interface + [ "$gretunnel" = true ] && _launch_gre_tracker logger -t "omr-tracker" "Launched" } From 60343492d6bf3d1a376efaa6cf2eff5426bef46b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 30 Dec 2020 10:39:57 +0100 Subject: [PATCH 0007/2059] Fix glorytun-udp backup mode --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index d1f74cffd..855c6d7f5 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -595,7 +595,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then # if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp set | grep 'kxtimeout 7d')" = "" ]; then # glorytun-udp set dev tun0 kxtimeout 7d > /dev/null 2>&1 # fi - [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set pref 200 > /dev/null 2>&1 + [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set pref 125 > /dev/null 2>&1 fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { From c64efb08bc5d974d691560ef90f76cf8a0b6c01c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 30 Dec 2020 16:44:22 +0100 Subject: [PATCH 0008/2059] Fix BBRv2 for ARM64 --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 9625904b5..d3b617dd3 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -78,7 +78,7 @@ MY_DEPENDS := \ !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 \ - luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||TARGET_arm64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ + luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||TARGET_aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-wolfssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status From 543cab8d20984b5c646dfb9c66d8ad167efd0811 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Jan 2021 10:58:42 +0100 Subject: [PATCH 0009/2059] Install BBRv2 package on AMR64 (really) --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index d3b617dd3..defb4d7b4 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -78,7 +78,7 @@ MY_DEPENDS := \ !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 \ - luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||TARGET_aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ + luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-wolfssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status From 2960b6b5d7ce3e1436fbb0ddd88d836404315d44 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Jan 2021 10:59:07 +0100 Subject: [PATCH 0010/2059] Force ubus path fix --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 63d4d3a3a..2348fa8b0 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -104,6 +104,15 @@ start_service() { # remove sysctl already defined in /etc/sysctl.d/ sed -i -e '/tcp_fin_timeout/d' -e '/tcp_keepalive_time/d' -e '/nf_conntrack_max/d' -e '/tcp_syn_retries/d' -e '/tcp_fastopen/d' -e '/tcp_retries2/d' -e '/tcp_retries1/d' -e '/ip_default_ttl/d' /etc/sysctl.conf sed -i -e '/tcp_fin_timeout/d' -e '/tcp_keepalive_time/d' -e '/nf_conntrack_max/d' -e '/tcp_syn_retries/d' -e '/tcp_fastopen/d' -e '/tcp_retries2/d' -e '/tcp_retries1/d' -e '/ip_default_ttl/d' /etc/sysctl.d/10-default.conf + + if [ "$(uci -q get rpcd.@rpcd[0].socket)" != "/var/run/ubus/ubus.sock" ]; then + uci -q batch <<-EOF >/dev/null + set rpcd.@rpcd[0].socket='/var/run/ubus/ubus.sock' + commit rpcd + EOF + /etc/init.d/rpcd restart 2>&1 >/dev/null + fi + } reload_service() { From 517b93f4362b32de8eb9e75907f6e5d69f62762e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Jan 2021 11:00:19 +0100 Subject: [PATCH 0011/2059] Fix omr-update --- omr-update/files/etc/init.d/omr-update | 1 + .../files/etc/uci-defaults/000-omr-update | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100755 openmptcprouter/files/etc/uci-defaults/000-omr-update diff --git a/omr-update/files/etc/init.d/omr-update b/omr-update/files/etc/init.d/omr-update index 6f79dae88..59c131e95 100755 --- a/omr-update/files/etc/init.d/omr-update +++ b/omr-update/files/etc/init.d/omr-update @@ -16,6 +16,7 @@ boot() { [ -n "$files" ] && { mkdir -p /usr/share/omr-update if [ "$(grep rom /etc/mtab)" = "" ]; then + rm /usr/share/omr-update/* cp /etc/uci-defaults/* /usr/share/omr-update fi uci -q set openmptcprouter.settings=settings diff --git a/openmptcprouter/files/etc/uci-defaults/000-omr-update b/openmptcprouter/files/etc/uci-defaults/000-omr-update new file mode 100755 index 000000000..6e16cc6b0 --- /dev/null +++ b/openmptcprouter/files/etc/uci-defaults/000-omr-update @@ -0,0 +1,18 @@ +#!/bin/sh + +cd /etc/uci-defaults || exit 0 +source /etc/os-release + +OMRVERSION=$(echo $VERSION | sed 's/v//') +files="$(ls /etc/uci-defaults/)" +[ -n "$files" ] && { + mkdir -p /usr/share/omr-update + if [ "$(grep rom /etc/mtab)" = "" ]; then + rm /usr/share/omr-update/* + cp /etc/uci-defaults/* /usr/share/omr-update + fi + uci -q set openmptcprouter.settings=settings + uci -q set openmptcprouter.settings.version=${OMRVERSION} + uci -q commit +} +exit 0 From e092f1b2d1a40e15b4bf6923420e2770711884db Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Jan 2021 16:40:03 +0100 Subject: [PATCH 0012/2059] Start omr-update after boot script --- omr-update/files/etc/init.d/omr-update | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-update/files/etc/init.d/omr-update b/omr-update/files/etc/init.d/omr-update index 59c131e95..d69c779f8 100755 --- a/omr-update/files/etc/init.d/omr-update +++ b/omr-update/files/etc/init.d/omr-update @@ -2,7 +2,7 @@ # Copyright (C) 2018 Ycarus (Yannick Chabanois) # Released under GPL 3. See LICENSE for the full terms. -START=1 +START=11 STOP=98 boot() { From 956dbdaffb80d61393b4ec8e4c87c03b574854dd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Jan 2021 07:57:34 +0100 Subject: [PATCH 0013/2059] Fix glorytun tcp interface --- .../luci-static/resources/view/services/glorytun-tcp.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js b/luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js index c8929e0fb..4b336e339 100644 --- a/luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js +++ b/luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js @@ -32,7 +32,6 @@ return L.view.extend({ s.tab('advanced', _('Advanced Settings')); o = s.taboption('general', form.Flag, 'enable', _('Enabled')); - o.default = o.enabled; o = s.taboption('general',form.Value, 'label', _('Label')); o.rmempty = true; @@ -65,11 +64,9 @@ return L.view.extend({ o.rmempty = false; o = s.taboption('advanced', form.Flag, 'mptcp', _('MPTCP')); - o.default = o.enabled; o.modalonly = true; o = s.taboption('advanced', form.Flag, 'chacha20', _('chacha'), _('Force fallback cipher')); - o.default = o.enabled; o.modalonly = true; o = s.taboption('advanced', form.Value, 'timeout', _('Timeout')); @@ -78,7 +75,6 @@ return L.view.extend({ o.modalonly = true; o = s.taboption('advanced', form.Flag, 'multiqueue', _('Multiqueue')); - o.default = o.enabled; o.rmempty = false; o.modalonly = true; From c0f4def8eab723641fc6601228dbd9cf5a80f269 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Jan 2021 07:57:46 +0100 Subject: [PATCH 0014/2059] Fix glorytun udp interface --- .../htdocs/luci-static/resources/view/services/glorytun-udp.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js b/luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js index 762332468..b14b4fb4a 100644 --- a/luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js +++ b/luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js @@ -40,7 +40,6 @@ return L.view.extend({ s.tab('advanced', _('Advanced Settings')); o = s.taboption('general', form.Flag, 'enable', _('Enabled')); - o.default = o.enabled; o = s.taboption('general',form.Value, 'label', _('Label')); o.rmempty = true; @@ -74,11 +73,9 @@ return L.view.extend({ o.rmempty = false; o = s.taboption('advanced', form.Flag, 'persist', _('Persist'), _('Keep the tunnel device after exiting')); - o.default = o.enabled; o.modalonly = true; o = s.taboption('advanced', form.Flag, 'chacha', _('chacha'), _('Force fallback cipher')); - o.default = o.enabled; o.modalonly = true; o = s.taboption('advanced', form.Value, 'kxtimeout', _('Key rotation timeout')); From dd7a0481de39d667ada71f43c8982ec4dd4cd023 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Jan 2021 07:58:03 +0100 Subject: [PATCH 0015/2059] Fix omr rename in some case --- .../root/etc/hotplug.d/net/99-omr-rename | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename index 19fcf1b1e..02d204117 100644 --- a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename +++ b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename @@ -27,14 +27,14 @@ _set_intf_name() { if [ "$modalias" = "$chk_modalias" ] && [ "$INTERFACE" != "$ifname" ]; then logger -t "OMR-Rename" "Rename ${INTERFACE} to ${ifname}" existif=0 - ip link set ${INTERFACE} down + ip link set ${INTERFACE} down 2>&1 >/dev/null [ "$(ip link show ${ifname} 2>/dev/null)" != "" ] && { - ip link set ${ifname} name ${ifname}tmp + ip link set ${ifname} name ${ifname}tmp 2>&1 >/dev/null existif=1 } - ip link set ${INTERFACE} name ${ifname} - ip link set ${ifname} up - [ "$existif" = "1" ] && ip link set ${ifname}tmp ${$INTERFACE} + ip link set ${INTERFACE} name ${ifname} 2>&1 >/dev/null + ip link set ${ifname} up 2>&1 >/dev/null + [ "$existif" = "1" ] && ip link set ${ifname}tmp ${$INTERFACE} 2>&1 >/dev/null fi fi elif [ -f /dev/${DEVICE_NAME} ] && [ -n "$MODALIAS" ] && [ "$modalias" = "$MODALIAS" ]; then @@ -46,15 +46,15 @@ _set_intf_name() { } [ -z "$modalias" ] && [ -n "$device" ] && [ -n "$ifname" ] && [ "/sys${DEVPATH}" = "$device" ] && [ "$INTERFACE" != "$ifname" ] && { logger -t "OMR-Rename" "Rename ${INTERFACE} to ${ifname}" - ip link set ${INTERFACE} down + ip link set ${INTERFACE} down 2>&1 >/dev/null existif=0 [ "$(ip link show ${ifname} 2>/dev/null)" != "" ] && { - ip link set ${ifname} name ${ifname}tmp + ip link set ${ifname} name ${ifname}tmp 2>&1 >/dev/null existif=1 } - ip link set ${INTERFACE} name ${ifname} - ip link set ${ifname} up - [ "$existif" = "1" ] && ip link set ${ifname}tmp ${$INTERFACE} + ip link set ${INTERFACE} name ${ifname} 2>&1 >/dev/null + ip link set ${ifname} up 2>&1 >/dev/null + [ "$existif" = "1" ] && ip link set ${ifname}tmp ${$INTERFACE} 2>&1 >/dev/null } } From 296dde429b8cfac954cbaf7d9e63894472b02a91 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Jan 2021 14:24:18 +0100 Subject: [PATCH 0016/2059] Change some luci-app-openmptcprouter strings --- .../luasrc/view/openmptcprouter/settings.htm | 6 +- .../po/templates/openmptcprouter.pot | 689 +++++++++--------- 2 files changed, 355 insertions(+), 340 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index 5ec0b3c2c..c23724f44 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -17,9 +17,9 @@ %>
-

<%:Update VPS%>

+

<%:Update server%>

-
<%:Update remotly the server to latest version when needed.%> <%:Beta%>
+
<%:Update remotly servers to latest version and reboot them.%> <%:Beta%>
@@ -40,7 +40,7 @@

<%:Advanced Settings%>

- <%:VPS settings%> + <%:Server settings%> <% uci:foreach("openmptcprouter","server", function(s) servername = s[".name"] diff --git a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot index 44d2aae48..4daf598a7 100644 --- a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot +++ b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot @@ -1,41 +1,41 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:255 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:256 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:250 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:253 msgid "A Dead Simple VPN key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:72 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 msgid "API username to retrieve personnalized settings from the server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:650 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:654 msgid "APN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:117 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 msgid "Add a new server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:819 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 msgid "Add an interface" msgstr "" -#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:19 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:39 +#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:18 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:41 msgid "Advanced Settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:125 msgid "Advanced settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:329 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:333 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -45,250 +45,262 @@ msgstr "" msgid "All router settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:224 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:225 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:676 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:680 msgid "Authentication Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:714 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:726 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 msgid "Backup" msgstr "" -#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:22 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:8 +#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:21 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:10 msgid "Backup on server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 msgid "Balancing" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:20 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:22 msgid "Beta" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:288 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:296 msgid "Big time difference between the server and the router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:474 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:478 msgid "Bridge" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:235 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:236 msgid "By default VPN is used for any traffic that is not TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:170 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:681 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:685 msgid "CHAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:257 msgid "Can\\'t access and use server part" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:275 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:283 msgid "Can\\'t contact Server Admin Script" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:273 msgid "Can\\'t get public IP address from ShadowSocks" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:265 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:276 +msgid "Can\\'t get public IP address from V2Ray" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:270 msgid "Can\\'t ping server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:478 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:482 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:412 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:498 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:544 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:548 msgid "Choose physical interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:122 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:123 msgid "Common server settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:135 msgid "Core temp:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:364 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:509 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:368 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:513 msgid "DHCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:183 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:188 msgid "DNS issue: can\\'t resolve hostname" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:294 msgid "Debug" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:172 msgid "Default Proxy" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:285 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "Default VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:51 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:52 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 msgid "Delete" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:624 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:580 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:628 msgid "Device" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:201 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:203 msgid "Disable TCP Fast Open" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:206 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:208 msgid "Disable TCP Fast Open on Linux and Shadowsocks configuration" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:246 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 msgid "Disable default gateway" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 msgid "Disable default gateway, no internet if VPS are down" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:191 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:193 msgid "Disable external check" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:236 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 msgid "Disable gateway ping" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 msgid "Disable gateway ping status check" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:271 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 +msgid "Disable interfaces auto rename" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 msgid "Disable multipath test using tracebox" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:61 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:63 msgid "" "Disable ports redirection defined in firewall from server to this router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 +msgid "Disable renaming interfaces" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 msgid "Disable server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:256 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 msgid "Disable server ping" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:261 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Disable server ping status check" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:266 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 msgid "Disable tracebox test" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:712 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:724 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:716 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:732 msgid "Disabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:770 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:778 msgid "Download speed (Kb/s)" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:308 msgid "Dynamic change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:185 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:147 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:148 msgid "Enable IPv6" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:760 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 msgid "Enable SQM" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:77 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:79 msgid "Enable ShadowSocks Obfuscating" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:211 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:213 msgid "Enable TCP Low Latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:281 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:299 msgid "Enable debug logs" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:711 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:731 msgid "Enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:208 msgid "Encryption" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:176 msgid "Filesystem is readonly" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:139 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:140 msgid "Force retrieve all keys from server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:134 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 msgid "Force retrieve settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:670 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 msgid "GPRS only" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:657 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:665 msgid "Gateway DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:243 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:238 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "Glorytun key" msgstr "" @@ -296,763 +308,766 @@ msgstr "" msgid "Grant UCI access for luci-app-openmptcprouter" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:128 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:130 msgid "How often TCP sends out keepalive messages when keepalive is enabled." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:179 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:181 msgid "IPv4 IP default TTL" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:133 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:135 msgid "IPv4 TCP FIN timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:173 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:175 msgid "IPv4 TCP Fast Open" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:123 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:125 msgid "IPv4 TCP Keepalive time" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:143 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:145 msgid "IPv4 TCP SYN retries" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:153 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:155 msgid "IPv4 TCP SYN retries1" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:165 msgid "IPv4 TCP SYN retries2" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:420 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:550 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:424 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 msgid "IPv4 address" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:566 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 msgid "IPv4 gateway" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:426 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:560 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:430 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 msgid "IPv4 netmask" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:157 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:158 msgid "IPv6 Prefix" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:536 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:697 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:544 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:705 msgid "IPv6 route received" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:145 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:146 msgid "IPv6 settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:204 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:209 msgid "IPv6 tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:328 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:336 msgid "IPv6:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:439 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:443 msgid "Interfaces settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:243 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:255 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:193 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:203 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:256 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 msgid "Key is retrieved from server API by default." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:82 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:341 msgid "LAN interfaces settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:668 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:672 msgid "LTE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:348 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:352 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 msgid "Label" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:354 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:464 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:358 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:468 msgid "Label for the interface" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:20 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:22 msgid "Last available backup on server:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:119 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:305 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:313 msgid "Latest available version" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:125 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:311 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:319 msgid "Load:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:268 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:264 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:263 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 msgid "MLVPN password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:292 msgid "MPTCP is not enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:330 msgid "MPTCP may not be enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:750 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:758 msgid "MPTCP over VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:473 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:477 msgid "MacVLAN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:713 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:717 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 msgid "Master" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:304 msgid "Master interface selection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:308 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:326 msgid "Maximum scaling CPU frequency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:302 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 msgid "Minimum scaling CPU frequency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:665 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 msgid "Modem default" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:699 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:703 msgid "Modem init timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:514 msgid "ModemManager" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:175 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:180 msgid "More than one default VPN is enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:708 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:712 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 msgid "Multipath TCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:519 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:525 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:680 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:686 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:527 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:533 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:688 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:694 msgid "Multipath current state is" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:675 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:683 msgid "Multipath master already defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:499 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:660 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:507 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:668 msgid "Multipath seems to be blocked on the connection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:511 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:515 msgid "NCM" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:679 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 msgid "NONE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:531 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:692 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:539 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:700 msgid "Network interface duplicated" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:792 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:794 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:800 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:802 msgid "Network overview" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:120 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:122 msgid "Networks settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:489 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:650 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:497 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 msgid "No IP defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:207 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:212 msgid "No IPv6 access" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:503 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:664 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:511 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:672 msgid "No Server ping response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:279 msgid "No WAN IP address detected in less than 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:24 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:26 msgid "No available backup on server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:291 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:309 msgid "No change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:712 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:720 msgid "No data" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:493 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:654 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:501 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:662 msgid "No gateway defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:243 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:249 msgid "No output" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:253 msgid "No server IP address, No WAN IP address" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:261 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:266 msgid "No server defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:213 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 msgid "None" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:472 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:476 msgid "Normal" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:148 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:150 msgid "" "Number of times initial SYNs for an active TCP connection attempt will be " "retransmitted." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:87 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:89 msgid "Obfuscating plugin" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:106 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:108 msgid "Obfuscating type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:82 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:84 msgid "Obfuscating will be enabled on both side" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 msgid "On wizard change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:182 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:96 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:722 +msgid "" +"Only one interface must be set as \"Master\", this should be the most stable " +"interface." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 msgid "Only one server can be master, else all servers are set as backup." msgstr "" -#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:14 #: luci-app-openmptcprouter/root/usr/share/luci/menu.d/luci-app-openmptcprouter.json:3 msgid "OpenMPTCProuter" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:329 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:333 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:216 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:218 msgid "Optimize for latency instead of bandwidth" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:365 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 msgid "Other" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:223 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 msgid "Other settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:680 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:684 msgid "PAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:686 msgid "PAP/CHAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:693 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 msgid "PAP/CHAP password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:687 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 msgid "PAP/CHAP username" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:656 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:660 msgid "PIN code" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:512 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 msgid "PPPoE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:377 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:483 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:523 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:487 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:527 msgid "Physical interface" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:670 msgid "Prefer LTE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:667 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 msgid "Prefer UMTS" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:359 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:363 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:508 msgid "Protocol" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:199 msgid "Proxy is DISABLED" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:168 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 msgid "Proxy settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "Proxy traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:513 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:517 msgid "QMI" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:50 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:52 msgid "Redirects all ports from server to this router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:30 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:32 msgid "Restore backup" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:132 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:133 msgid "Retrieve settings from server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:334 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:836 msgid "Save & Apply" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 msgid "Save vnstats statistics on disk" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:226 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 msgid "Save vnstats stats" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:314 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 msgid "Scaling governor" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:822 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "Select the device you want to base the interface on." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:31 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:33 msgid "Send backup" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:57 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:59 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:58 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:60 msgid "Server IP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:61 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:62 msgid "Server IP will be set for proxy and VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:79 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:78 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:80 msgid "Server key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:41 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:42 msgid "Server settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:69 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:68 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:70 msgid "Server username" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:662 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 msgid "Service Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:555 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 msgid "Set an IP in the same network as the modem" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:575 msgid "Set here IP of the modem" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 msgid "Set server as master" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:180 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:329 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:333 msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " "for all traffic if proxy is disabled." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:780 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:788 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:796 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:804 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" -#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:15 +#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:14 msgid "Settings Wizard" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:153 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:158 msgid "ShadowSocks is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:193 msgid "ShadowSocks is used for TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:188 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 msgid "ShadowSocks key" msgstr "" -#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:24 +#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:23 msgid "Show all settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:363 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:508 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:367 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:512 msgid "Static address" msgstr "" -#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:17 +#: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:16 msgid "Status" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:299 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 msgid "Systems settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:138 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:140 msgid "" "The length of time an orphaned (no longer referenced by any application) " "connection will remain in the FIN_WAIT_2 state before it is aborted at the " "local end." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:226 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:227 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:158 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:160 msgid "" "This value influences the time, after which TCP decides, that something is " "wrong due to unacknowledged RTO retransmissions, and reports this suspicion " "to the network layer." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:168 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:170 msgid "" "This value influences the timeout of an alive TCP connection, when RTO " "retransmissions remain unacknowledged." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:343 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:351 msgid "Total traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:469 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:473 msgid "Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:274 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:275 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 msgid "UBOND password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:673 msgid "UMTS/GPRS" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:27 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:29 msgid "Update" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:18 -msgid "Update VPS" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:22 +msgid "Update remotly servers to latest version and reboot them." msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:20 -msgid "Update remotly the server to latest version when needed." -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:22 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:24 msgid "Update server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:786 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 msgid "Upload speed (Kb/s)" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:136 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:317 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:325 msgid "Uptime:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:775 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:791 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:783 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:799 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:165 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:170 msgid "V2Ray is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:203 msgid "V2Ray is used for TCP and UDP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:200 msgid "V2Ray user" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 msgid "V2Ray user id" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:179 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:184 msgid "VPN is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:234 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:235 msgid "VPN settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:338 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 msgid "VPN traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:203 msgid "VPN tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:41 -msgid "VPS settings" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:298 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:306 msgid "Version" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:507 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:668 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:515 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:676 msgid "Wan IP and gateway are identical" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:196 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:198 msgid "" "When enable check are done on external sites to get each WAN IP and the IP " "used to go outside." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:39 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 +msgid "When proxy shadowsocks is used, use it for UDP if proxy down" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:40 msgid "Wizard" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:75 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:80 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:85 msgid "You" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:755 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:763 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:373 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:522 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:162 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:440 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:153 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:765 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:773 msgid "You should disable SQM for LTE or any interfaces with variable speed." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:56 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:58 msgid "You shouldn't do that and you should redirect only needed ports" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:78 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:83 msgid "Your IP was not leased by this router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:144 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:149 msgid "address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:675 msgid "auto" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:156 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:161 msgid "empty key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:439 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 -msgid "ip address:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:451 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:642 -msgid "latency:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 -msgid "mtu:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:543 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:699 -msgid "multipath:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:459 -msgid "operator:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 -msgid "other" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:463 -msgid "phone number:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:145 -msgid "range:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:467 -msgid "state:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:546 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:702 -msgid "traffic control:" -msgstr "" - -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:443 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 -msgid "wan address:" -msgstr "" - #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:447 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:638 +msgid "ip address:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:650 +msgid "latency:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:654 +msgid "mtu:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:551 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:707 +msgid "multipath:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:467 +msgid "operator:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:218 +msgid "other" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:471 +msgid "phone number:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:150 +msgid "range:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:475 +msgid "state:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:710 +msgid "traffic control:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:451 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:642 +msgid "wan address:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:455 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 msgid "whois:" msgstr "" From d4fae6f54a595efd9d4ac71a4dc929b46d200e9c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Jan 2021 14:24:47 +0100 Subject: [PATCH 0017/2059] Alphabetical order for TCP Congestion control --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index 5c32389fb..a69f69e3e 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -38,7 +38,7 @@ local mtcpsyn = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SY mtcpsyn.datatype = "uinteger" mtcpsyn.rmempty = false local congestion = s:option(ListValue, "congestion", translate("Congestion Control"),translate("Default is bbr")) -local availablecong = sys.exec("sysctl net.ipv4.tcp_available_congestion_control | awk -F'= ' '{print $NF}'") +local availablecong = sys.exec("sysctl -n net.ipv4.tcp_available_congestion_control | xargs -n1 | sort | xargs") for cong in string.gmatch(availablecong, "[^%s]+") do congestion:value(cong, translate(cong)) end From 1fe72710b373b41c83480c26d2450fc87334967a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Jan 2021 14:25:43 +0100 Subject: [PATCH 0018/2059] Fix for VPS update and some rpcd changes --- .../root/usr/libexec/rpcd/openmptcprouter | 124 ++++++++++-------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 5df98b004..633b47394 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -116,14 +116,14 @@ function add_interface(add_interface_ifname) ucic:save("sqm") ucic:commit("sqm") - luci.sys.call("uci -q add_list vnstat.@vnstat[-1].interface=" .. wanif) - luci.sys.call("uci -q commit vnstat") + sys.exec("uci -q add_list vnstat.@vnstat[-1].interface=" .. wanif) + sys.exec("uci -q commit vnstat") -- Dirty way to add new interface to firewall... - luci.sys.call("uci -q add_list firewall.@zone[1].network=wan" .. i) - luci.sys.call("uci -q commit firewall") + sys.exec("uci -q add_list firewall.@zone[1].network=wan" .. i) + sys.exec("uci -q commit firewall") - luci.sys.call("/etc/init.d/macvlan restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/macvlan restart >/dev/null 2>/dev/null") end function remove_interface(intf) @@ -140,11 +140,11 @@ function remove_interface(intf) ucic:save("qos") ucic:commit("qos") if defif ~= nil and defif ~= "" then - luci.sys.call("uci -q del_list vnstat.@vnstat[-1].interface=" .. defif) + sys.exec("uci -q del_list vnstat.@vnstat[-1].interface=" .. defif) end - luci.sys.call("uci -q commit vnstat") - luci.sys.call("uci -q del_list firewall.@zone[1].network=" .. intf) - luci.sys.call("uci -q commit firewall") + sys.exec("uci -q commit vnstat") + sys.exec("uci -q del_list firewall.@zone[1].network=" .. intf) + sys.exec("uci -q commit firewall") end function set_interface(intf,proto,ipaddr,netmask,gateway,sqmenabled,downloadspeed,uploadspeed) @@ -321,24 +321,30 @@ function server_settings(server,server_ip,openmptcprouter_vps_key) ucic:set("openmptcprouter",server,"ip",server_ip) ucic:set("openmptcprouter",server,"port","65500") ucic:save("openmptcprouter") - ucic:set("shadowsocks-libev","sss0","server",server_ip) - ucic:set("glorytun","vpn","host",server_ip) - ucic:set("dsvpn","vpn","host",server_ip) - ucic:set("mlvpn","general","host",server_ip) - luci.sys.call("uci -q del openvpn.omr.remote") - luci.sys.call("uci -q add_list openvpn.omr.remote=" .. server_ip) - ucic:set("qos","serverin","srchost",server_ip) - ucic:set("qos","serverout","dsthost",server_ip) - ucic:save("qos") - ucic:commit("qos") - ucic:save("mlvpn") - ucic:commit("mlvpn") - ucic:save("dsvpn") - ucic:commit("dsvpn") - ucic:save("glorytun") - ucic:commit("glorytun") - ucic:save("shadowsocks-libev") - ucic:commit("shadowsocks-libev") + if ucic:get("openmptcprouter",server,"master") == "1" then + ucic:set("shadowsocks-libev","sss0","server",server_ip) + ucic:set("glorytun","vpn","host",server_ip) + ucic:set("dsvpn","vpn","host",server_ip) + ucic:set("mlvpn","general","host",server_ip) + sys.exec("uci -q del openvpn.omr.remote") + sys.exec("uci -q add_list openvpn.omr.remote=" .. server_ip) + ucic:set("qos","serverin","srchost",server_ip) + ucic:set("qos","serverout","dsthost",server_ip) + ucic:set("v2ray","omrout","s_vmess_address",server_ip) + ucic:set("v2ray","omrout","s_vless_address",server_ip) + ucic:save("qos") + ucic:commit("qos") + ucic:save("mlvpn") + ucic:commit("mlvpn") + ucic:save("dsvpn") + ucic:commit("dsvpn") + ucic:save("v2ray") + ucic:commit("v2ray") + ucic:save("glorytun") + ucic:commit("glorytun") + ucic:save("shadowsocks-libev") + ucic:commit("shadowsocks-libev") + end end function set_shadowsocks(shadowsocks_key) @@ -404,18 +410,22 @@ end function restart_all() -- Restart all - luci.sys.call("(env -i /bin/ubus call network reload) >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/mptcp restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null") - os.execute("sleep 2") - luci.sys.call("/etc/init.d/v2ray restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/glorytun restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null") - --luci.sys.call("/etc/init.d/mlvpn restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/openvpn restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/omr-tracker restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/macvlan restart >/dev/null 2>/dev/null") + sys.exec("(env -i /bin/ubus call network reload) >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/omr-tracker stop >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/mptcp restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/glorytun restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/mlvpn restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/openvpn restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/openvpnbonding restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/dsvpn restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/omr-tracker start >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/mptcpovervpn restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/vnstat restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/v2ray restart >/dev/null 2>/dev/null") end function redirectports(server,redirect_ports) @@ -425,26 +435,26 @@ end function tcpkeepalivetime(tcp_keepalive_time) -- Set tcp_keepalive_time - luci.sys.exec("sysctl -w net.ipv4.tcp_keepalive_time=%s" % tcp_keepalive_time) - luci.sys.exec("sed -i 's:^net.ipv4.tcp_keepalive_time=[0-9]*:net.ipv4.tcp_keepalive_time=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_keepalive_time) + sys.exec("sysctl -w net.ipv4.tcp_keepalive_time=%s" % tcp_keepalive_time) + sys.exec("sed -i 's:^net.ipv4.tcp_keepalive_time=[0-9]*:net.ipv4.tcp_keepalive_time=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_keepalive_time) end function tcpfintimeout(tcp_fin_timeout) -- Set tcp_fin_timeout - luci.sys.exec("sysctl -w net.ipv4.tcp_fin_timeout=%s" % tcp_fin_timeout) - luci.sys.exec("sed -i 's:^net.ipv4.tcp_fin_timeout=[0-9]*:net.ipv4.tcp_fin_timeout=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_fin_timeout) + sys.exec("sysctl -w net.ipv4.tcp_fin_timeout=%s" % tcp_fin_timeout) + sys.exec("sed -i 's:^net.ipv4.tcp_fin_timeout=[0-9]*:net.ipv4.tcp_fin_timeout=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_fin_timeout) end function tcpsynretries(tcp_syn_retries) -- Set tcp_syn_retries - luci.sys.exec("sysctl -w net.ipv4.tcp_syn_retries=%s" % tcp_syn_retries) - luci.sys.exec("sed -i 's:^net.ipv4.tcp_syn_retries=[0-9]*:net.ipv4.tcp_syn_retries=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_syn_retries) + sys.exec("sysctl -w net.ipv4.tcp_syn_retries=%s" % tcp_syn_retries) + sys.exec("sed -i 's:^net.ipv4.tcp_syn_retries=[0-9]*:net.ipv4.tcp_syn_retries=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_syn_retries) end function tcpfastopen(tcp_fastopen) -- Set tcp_fastopen - luci.sys.exec("sysctl -w net.ipv4.tcp_fastopen=%s" % tcp_fastopen) - luci.sys.exec("sed -i 's:^net.ipv4.tcp_fastopen=[0-3]*:net.ipv4.tcp_fastopen=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_fastopen) + sys.exec("sysctl -w net.ipv4.tcp_fastopen=%s" % tcp_fastopen) + sys.exec("sed -i 's:^net.ipv4.tcp_fastopen=[0-3]*:net.ipv4.tcp_fastopen=%s:' /etc/sysctl.d/zzz_openmptcprouter.conf" % tcp_fastopen) end function disableipv6(disable_ipv6) @@ -452,7 +462,7 @@ function disableipv6(disable_ipv6) ucic:set("openmptcprouter","settings","disable_ipv6",disable_ipv6) ucic:save("openmptcprouter") ucic:commit("openmptcprouter") - luci.sys.call("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") end function externalcheck(externalcheck) @@ -463,7 +473,7 @@ end function savevnstat(savevnstat) -- Enable/disable save vnstat - luci.sys.exec("uci -q set vnstat.@vnstat[0].backup=%s" % savevnstat) + sys.exec("uci -q set vnstat.@vnstat[0].backup=%s" % savevnstat) ucic:commit("vnstat") end @@ -522,17 +532,17 @@ end function update_vps() -- Update VPS - ucic:foreach("openmptcprouter", "server", function(s) - local serverip = ucic:get("openmptcprouter",s[".name"],"ip") - local adminport = ucic:get("openmptcprouter",s[".name"],"port") or "65500" - local token = ucic:get("openmptcprouter",s[".name"],"token") or "" + local vpsgettoken = sys.exec("/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null") + ucic:foreach("openmptcprouter", "server", function(section) + local servername = section[".name"] + local serverip = section["ip"] or "" + local adminport = section["port"] or "65500" + local token = section["token"] or "" if token ~= "" then - sys.exec('curl -4 --max-time 20 -s -k -H "Authorization: Bearer ' .. token .. '" https://' .. serverip .. ":" .. adminport .. "/update") - luci.sys.call("/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null") - luci.http.redirect(luci.dispatcher.build_url("admin/system/openmptcprouter/status")) - return + local updatevps = sys.exec('curl -4 --max-time 20 -s -k -H "Authorization: Bearer ' .. token .. '" https://' .. serverip .. ":" .. adminport .. "/update") end end) + local vpsgettoken = sys.exec("/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null") end function get_ip(interface) From 117cb3bf974910623ad08a81ec82e5c8f1bc598f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Jan 2021 17:06:56 +0100 Subject: [PATCH 0019/2059] Fix omr-bypass with VLAN interfaces --- .../root/etc/init.d/omr-bypass | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 3708a0fce..8c1bf2aeb 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -90,7 +90,8 @@ _bypass_mac() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - local intfid="$(uci -q get omr-bypass.$intf.id)" + intfuci=$(echo $intf | sed 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intfuci.id)" [ -z "$intf" ] && intf="all" [ -z "$mac" ] && return @@ -131,7 +132,8 @@ _bypass_lan_ip() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - local intfid="$(uci -q get omr-bypass.$intf.id)" + intfuci=$(echo $intf | sed 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intfuci.id)" [ -z "$intf" ] && intf="all" [ -z "$ip" ] && return @@ -188,7 +190,8 @@ _bypass_dest_port() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - local intfid="$(uci -q get omr-bypass.$intf.id)" + intfuci=$(echo $intf | sed 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intfuci.id)" [ -z "$intf" ] && intf="all" [ -z "$dport" ] && return @@ -243,7 +246,8 @@ _bypass_src_port() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - local intfid="$(uci -q get omr-bypass.$intf.id)" + intfuci=$(echo $intf | sed 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intfuci.id)" [ -z "$intf" ] && intf="all" [ -z "$sport" ] && return @@ -296,7 +300,8 @@ _bypass_proto() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - local intfid="$(uci -q get omr-bypass.$intf.id)" + intfuci=$(echo $intf | sed 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intfuci.id)" [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return @@ -493,8 +498,9 @@ _intf_rule() { config_foreach _intf_rule_ss_rules ss_rules _intf_rule_v2ray_rules - uci -q set omr-bypass.$intf=interface - uci -q set omr-bypass.$intf.id=$count + intfuci=$(echo $intf | sed 's/\./_/') + uci -q set omr-bypass.$intfuci=interface + uci -q set omr-bypass.$intfuci.id=$count } _bypass_ip_set() { From dc70866c2906a54d7d741a7e3f4a7952584a844e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Jan 2021 17:07:26 +0100 Subject: [PATCH 0020/2059] Restart vnstart when interface added --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index f30be2a41..23d5fc5f7 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -179,6 +179,7 @@ function wizard_add() luci.sys.call("uci -q commit firewall") luci.sys.call("/etc/init.d/macvlan restart >/dev/null 2>/dev/null") + luci.sys.call("/etc/init.d/vnstat restart >/dev/null 2>/dev/null") gostatus = false end From 49db48e3dc8e25ab7c0ab209e0d2d08e3c7f37e8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Jan 2021 17:08:12 +0100 Subject: [PATCH 0021/2059] Fix iperf on VPS when using web interface --- luci-app-iperf/luasrc/controller/iperf.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-iperf/luasrc/controller/iperf.lua b/luci-app-iperf/luasrc/controller/iperf.lua index e6cb2ec3a..cbc3f1e12 100644 --- a/luci-app-iperf/luasrc/controller/iperf.lua +++ b/luci-app-iperf/luasrc/controller/iperf.lua @@ -40,7 +40,7 @@ function run_test(server,proto,mode,updown,omit,parallel,transmit,bitrate) end local port = t[ math.random( #t ) ] if password ~= "" then - iperf = io.popen("omr-iperf -P %s -%s -O %s -t %s -J -Z %s" % {parallel,ipv,omit,transmit,options}) + iperf = io.popen("omr-iperf %s -P %s -%s -O %s -t %s -J -Z %s" % {server,parallel,ipv,omit,transmit,options}) else iperf = io.popen("iperf3 -c %s -P %s -%s -p %s -O %s -t %s -J -Z %s" % {ut.shellquote(addr),parallel,ipv,port,omit,transmit,options}) end From 0504af4db6810f57dffaa39a868336c6a8bbf00b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 7 Jan 2021 17:33:17 +0100 Subject: [PATCH 0022/2059] Fix omr-rename --- luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename index 02d204117..9d741c683 100644 --- a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename +++ b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename @@ -34,7 +34,7 @@ _set_intf_name() { } ip link set ${INTERFACE} name ${ifname} 2>&1 >/dev/null ip link set ${ifname} up 2>&1 >/dev/null - [ "$existif" = "1" ] && ip link set ${ifname}tmp ${$INTERFACE} 2>&1 >/dev/null + [ "$existif" = "1" ] && ip link set ${ifname}tmp ${INTERFACE} 2>&1 >/dev/null fi fi elif [ -f /dev/${DEVICE_NAME} ] && [ -n "$MODALIAS" ] && [ "$modalias" = "$MODALIAS" ]; then @@ -54,7 +54,7 @@ _set_intf_name() { } ip link set ${INTERFACE} name ${ifname} 2>&1 >/dev/null ip link set ${ifname} up 2>&1 >/dev/null - [ "$existif" = "1" ] && ip link set ${ifname}tmp ${$INTERFACE} 2>&1 >/dev/null + [ "$existif" = "1" ] && ip link set ${ifname}tmp ${INTERFACE} 2>&1 >/dev/null } } From 29f0b61c7b8d465a864533eaa53ca246f5603371 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 7 Jan 2021 17:33:51 +0100 Subject: [PATCH 0023/2059] Change DNS over HTTPS config only when needed --- openmptcprouter/files/etc/uci-defaults/1940-omr-dns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index 73508e900..93471310a 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -40,7 +40,7 @@ if [ "$(uci -q get dhcp.lan.dhcp_options)" = "" ]; then EOF fi -if [ "$(uci -q get https-dns-proxy.@https-dns-proxy[0].listen_port)" = "5053" ]; then +if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ] && [ "$(uci -q get https-dns-proxy.@https-dns-proxy[0].listen_port)" = "5053" ]; then # uci -q batch <<-EOF >/dev/null # delete https-dns-proxy.@https-dns-proxy[-1] # delete https-dns-proxy.@https-dns-proxy[-1] From acf29d0bb75c4ebdce8264832b5cad4647a88075 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 7 Jan 2021 20:00:01 +0100 Subject: [PATCH 0024/2059] Fix omr-rename disable --- .../root/etc/hotplug.d/net/99-omr-rename | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename index 9d741c683..f2c19dc55 100644 --- a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename +++ b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename @@ -23,7 +23,7 @@ _set_intf_name() { chk_modalias=$MODALIAS [ -z "$chk_modalias" ] && chk_modalias="$(cat /sys/class/net/${INTERFACE}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')" if [ -n "$chk_modalias" ]; then - logger -t "OMR-Rename" "dir: $i - modalias: $modalias - chk_modalias: $chk_modalias - ifname: $ifname - INTERFACE: $INTERFACE" + logger -t "OMR-Rename" "modalias: $modalias - chk_modalias: $chk_modalias - ifname: $ifname - INTERFACE: $INTERFACE" if [ "$modalias" = "$chk_modalias" ] && [ "$INTERFACE" != "$ifname" ]; then logger -t "OMR-Rename" "Rename ${INTERFACE} to ${ifname}" existif=0 @@ -45,6 +45,7 @@ _set_intf_name() { fi } [ -z "$modalias" ] && [ -n "$device" ] && [ -n "$ifname" ] && [ "/sys${DEVPATH}" = "$device" ] && [ "$INTERFACE" != "$ifname" ] && { + logger -t "OMR-Rename" "device: $device - devpath: $DEVPATH - ifname: $ifname - INTERFACE: $INTERFACE" logger -t "OMR-Rename" "Rename ${INTERFACE} to ${ifname}" ip link set ${INTERFACE} down 2>&1 >/dev/null existif=0 @@ -58,7 +59,7 @@ _set_intf_name() { } } -if [ "$(uci -q get openmptcprouter.settings.disableintfrename)" != "0" ]; then +if [ "$(uci -q get openmptcprouter.settings.disableintfrename)" != "1" ]; then config_load network config_foreach _set_intf_name interface config_foreach _set_intf_name interface From bc7fb24b223ed792249d06ceebec7f70e5a6f9c0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 8 Jan 2021 10:46:06 +0100 Subject: [PATCH 0025/2059] Get interface info on stop --- .../root/etc/init.d/openmptcprouter | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 2348fa8b0..adde64a8f 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -56,8 +56,13 @@ omr_intf_set() { elif [ "$type" != "macvlan" ] && [ -n "$device" ] && [ -f /sys/bus/usb-serial/devices/${devicename}/device/uevent ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" != "" ]; then uci -q set network.$1.modalias="$(cat /sys/bus/usb-serial/devices/${devicename}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')" uci -q set network.$1.product="$(cat /sys/bus/usb-serial/devices/${devicename}/device/uevent | grep PRODUCT | cut -d '=' -f2 | tr -d '\n')" + else + uci -q delete network.$1.modalias + uci -q delete network.$1.product fi +} +omr_set_settings() { [ -z "$multipath" ] || [ "$multipath" = "off" ] && [ "$1" != "omrvpn" ] && [ "$1" != "glorytun" ] && return uci -q set openmptcprouter.$1=interface @@ -76,7 +81,7 @@ start_service() { config_load openmptcprouter config_foreach omr_intf_check interface config_load network - config_foreach omr_intf_set interface + config_foreach omr_set_settings interface uci -q commit network uci -q commit openmptcprouter @@ -112,7 +117,13 @@ start_service() { EOF /etc/init.d/rpcd restart 2>&1 >/dev/null fi +} +stop_service() { + config_load network + config_foreach omr_intf_set interface + uci -q commit network + uci -q commit openmptcprouter } reload_service() { From 4535f2ad44430092d077e54aa6bf5e76fbe1d8bb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 8 Jan 2021 10:46:21 +0100 Subject: [PATCH 0026/2059] Disable interface rename by default --- .../root/etc/uci-defaults/openmptcprouter | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter index 24cbccb20..b267d6f21 100755 --- a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter @@ -114,6 +114,13 @@ if [ "$(uci -q get openmptcprouter.settings.menu)" = "" ]; then EOF fi +if [ "$(uci -q get openmptcprouter.settings.disableintfrename)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set openmptcprouter.settings.disableintfrename='1' + commit openmptcprouter + EOF +fi + sed -i 's/net.ipv4.tcp_retries2=3$/net.ipv4.tcp_retries2=15/' /etc/sysctl.d/zzz_openmptcprouter.conf exit 0 From 57debb668140f62a4982afe469b9d0d3f33c2b00 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 9 Jan 2021 08:42:19 +0100 Subject: [PATCH 0027/2059] Rename omr-update script to be executed after all others --- .../files/etc/uci-defaults/{000-omr-update => zzzzz-omr-update} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openmptcprouter/files/etc/uci-defaults/{000-omr-update => zzzzz-omr-update} (100%) diff --git a/openmptcprouter/files/etc/uci-defaults/000-omr-update b/openmptcprouter/files/etc/uci-defaults/zzzzz-omr-update similarity index 100% rename from openmptcprouter/files/etc/uci-defaults/000-omr-update rename to openmptcprouter/files/etc/uci-defaults/zzzzz-omr-update From 0be1a3b11979c29c17e2e5bd90e136558a52fea6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 16 Jan 2021 08:11:03 +0100 Subject: [PATCH 0028/2059] Changes for WAN IPv6 support in status page --- .../luasrc/view/openmptcprouter/wanstatus.htm | 70 +++++- luci-app-openmptcprouter/root/bin/omr-ip-intf | 12 +- .../root/bin/omr-ip6-intf | 37 +++ .../root/bin/omr-tracebox-mptcp | 15 +- .../root/usr/libexec/rpcd/openmptcprouter | 216 ++++++++++++++++-- 5 files changed, 309 insertions(+), 41 deletions(-) create mode 100755 luci-app-openmptcprouter/root/bin/omr-ip6-intf diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index b35f3344f..16caf5a59 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -231,14 +231,25 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm if ((mArray.openmptcprouter.wan_addr == mArray.openmptcprouter.service_addr || mArray.openmptcprouter.wan_addr == mArray.openmptcprouter.service_addr_ip) && mArray.openmptcprouter.wan_addr != "") { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr); + } else if ((mArray.openmptcprouter.wan_addr6 == mArray.openmptcprouter.service_addr || mArray.openmptcprouter.wan_addr6 == mArray.openmptcprouter.service_addr_ip) && mArray.openmptcprouter.wan_addr6 != "") + { + var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_6addr); } else if (mArray.openmptcprouter.wan_addr != "" && mArray.openmptcprouter.service_addr == "127.0.0.1") { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr); + } else if (mArray.openmptcprouter.wan_addr6 != "" && mArray.openmptcprouter.service_addr == "127.0.0.1") + { + var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr6); } else if (mArray.openmptcprouter.wan_addr != "") { var title = String.format("%s (%s)", _('Direct output'), mArray.openmptcprouter.wan_addr); statusMessageClass = "warning"; statusIcon = "<%=resource%>/openmptcprouter/images/statusWarning.png"; + } else if (mArray.openmptcprouter.wan_addr6 != "") + { + var title = String.format("%s (%s)", _('Direct output'), mArray.openmptcprouter.wan_addr6); + statusMessageClass = "warning"; + statusIcon = "<%=resource%>/openmptcprouter/images/statusWarning.png"; } else if (mArray.openmptcprouter.ss_addr != "" && mArray.openmptcprouter.vps_status != "DOWN") { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.ss_addr); @@ -248,11 +259,11 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm var title = '<%:No output%>'; statusMessage += '<%:No output%>' + '
'; } - if (mArray.openmptcprouter.wan_addr == "" && mArray.openmptcprouter.ss_addr == "" && mArray.openmptcprouter.external_check == true) + if (mArray.openmptcprouter.wan_addr == "" && mArray.openmptcprouter.wan_addr6 == "" && mArray.openmptcprouter.ss_addr == "" && mArray.openmptcprouter.external_check == true) { statusMessage += '<%:No server IP address, No WAN IP address%>' + '
'; } - if (mArray.openmptcprouter.service_addr !== "" && mArray.openmptcprouter.wan_addr !== "" && mArray.openmptcprouter.vps_status == "DOWN") + if (mArray.openmptcprouter.service_addr !== "" && (mArray.openmptcprouter.wan_addr !== "" || mArray.openmptcprouter.wan_addr6 !== "") && mArray.openmptcprouter.vps_status == "DOWN") { statusMessage += '<%:Can\'t access and use server part%>' + '
'; } @@ -274,7 +285,10 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm } else if (mArray.openmptcprouter.v2ray_enabled == true && mArray.openmptcprouter.ss_addr == "" && mArray.openmptcprouter.external_check == true) { statusMessage += '<%:Can\'t get public IP address from V2Ray%>' + '
'; - } else if (mArray.openmptcprouter.wan_addr == "" && mArray.openmptcprouter.external_check == true) + } else if (mArray.openmptcprouter.wan_addr == "" && mArray.openmptcprouter.wan_addr6 !== "" && mArray.openmptcprouter.external_check == true) + { + statusMessage += '<%:No WAN IP address detected in less than 1 second%>' + '
'; + } else if (mArray.openmptcprouter.wan_addr6 == "" && mArray.openmptcprouter.wan_addr !== "" && mArray.openmptcprouter.external_check == true) { statusMessage += '<%:No WAN IP address detected in less than 1 second%>' + '
'; } @@ -392,18 +406,21 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm statusMessage = ""; } // Populate info - var wanip = mArray.wans[i].wanip; + var wanip = mArray.wans[i].wanip; + var wanip6 = mArray.wans[i].wanip6; if (anonymize == "true" && testPrivateIP(wanip) == false) { wanip=replaceLastNChars(wanip,"x",6); } - var ipaddr = mArray.wans[i].ipaddr; + var ipaddr = mArray.wans[i].ipaddr; + var ip6addr = mArray.wans[i].ip6addr; if (anonymize == "true" && testPrivateIP(ipaddr) == false) { ipaddr=replaceLastNChars(ipaddr,"x",6); } - var whois = mArray.wans[i].whois; - var signal = mArray.wans[i].signal; + var whois = mArray.wans[i].whois; + var whois6 = mArray.wans[i].whois6; + var signal = mArray.wans[i].signal; var multipath = mArray.wans[i].multipath; if(multipath == 'master') { @@ -420,7 +437,13 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { gateway=replaceLastNChars(gateway,"x",6); } + var gateway6 = mArray.wans[i].gateway6; + if (anonymize == "true" && testPrivateIP(gateway6) == false) + { + gateway6=replaceLastNChars(gateway6,"x",10); + } var gw_ping = mArray.wans[i].gw_ping; + var gw_ping6 = mArray.wans[i].gw_ping6; var server_ping = mArray.wans[i].server_ping; var ipv6_discover = mArray.wans[i].ipv6_discover; var multipath_available = mArray.wans[i].multipath_available; @@ -438,6 +461,9 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm if (mArray.wans[i].gateway !== "") { var title = mArray.wans[i].label + " (" + gateway + ")"; + } else if (mArray.wans[i].gateway6 !== "") + { + var title = mArray.wans[i].label + " (" + gateway6 + ")"; } else { var title = mArray.wans[i].label; } @@ -446,14 +472,26 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { content += String.format('%s %s
','<%:ip address:%>', ipaddr); } + if(ip6addr !== '') + { + content += String.format('%s %s
','<%:ipv6 address:%>', ip6addr); + } if(wanip !== '') { content += String.format('%s %s
','<%:wan address:%>', wanip); } + if(wanip6 !== '') + { + content += String.format('%s %s
','<%:wan ipv6 address:%>', wanip6); + } if(whois !== '') { content += String.format('%s %s
','<%:whois:%>', whois); } + if(whois6 !== '') + { + content += String.format('%s %s
','<%:whois:%>', whois6); + } if(latency !== '') { content += String.format('%s %s ms
','<%:latency:%>', latency); @@ -492,14 +530,17 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { title += String.format(' %s',networktype); } - if(ipaddr == '') + if(ipaddr == '' && ip6addr == '') { statusMessage += '<%:No IP defined%>' + '
'; } - if(gateway == '') + if(gateway == '' && gateway6 == '') { statusMessage += '<%:No gateway defined%>' + '
'; } else if(gw_ping == 'DOWN') + { + statusMessage += '<%:Gateway DOWN%>' + '
'; + } else if(gw_ping6 == 'DOWN') { statusMessage += '<%:Gateway DOWN%>' + '
'; } else if(multipath_available == 'ERROR') @@ -515,6 +556,11 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm statusMessage += '<%:Wan IP and gateway are identical%>' + '
'; statusMessageClass = "error"; } + if (stat == 'Offline' && ip6addr != '' && ipaddr == mArray.wans[i].gateway6) + { + statusMessage += '<%:Wan IP and gateway are identical%>' + '
'; + statusMessageClass = "error"; + } if(multipath == 'master') { if (master > 1) @@ -557,6 +603,12 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm temp += ''; } + if (mArray.wans.length == 0) + { + temp += '
  • '; + temp += '<%:No WAN with multipath enabled:%>'; + temp += '
  • '; + } for( var i = 0; i < mArray.tunnels.length; i++ ) { // Get link color diff --git a/luci-app-openmptcprouter/root/bin/omr-ip-intf b/luci-app-openmptcprouter/root/bin/omr-ip-intf index 4c87b4256..16434c5a4 100755 --- a/luci-app-openmptcprouter/root/bin/omr-ip-intf +++ b/luci-app-openmptcprouter/root/bin/omr-ip-intf @@ -28,8 +28,10 @@ get_ip_from_website() { } [ -z "$intf" ] && return -ip="" -config_load openmptcprouter -config_foreach get_ip_from_server server -[ -z "$ip" ] && get_ip_from_website -echo $ip \ No newline at end of file +if [ -n "$(ip -4 a show dev $intf)" ]; then + ip="" + config_load openmptcprouter + config_foreach get_ip_from_server server + [ -z "$ip" ] && get_ip_from_website + echo $ip +fi \ No newline at end of file diff --git a/luci-app-openmptcprouter/root/bin/omr-ip6-intf b/luci-app-openmptcprouter/root/bin/omr-ip6-intf new file mode 100755 index 000000000..c096503ea --- /dev/null +++ b/luci-app-openmptcprouter/root/bin/omr-ip6-intf @@ -0,0 +1,37 @@ +#!/bin/sh +. /lib/functions.sh + +intf=$1 + +get_ip_from_server() { + serverip=$(uci -q get openmptcprouter.$1.ip) + serverport=$(uci -q get openmptcprouter.$1.port) + getip="$(curl -s -k -6 -m 2 --interface $intf https://$serverip:$serverport/clienthost)" + [ -n "$getip" ] && getip=$(echo $getip | jsonfilter -e '@.client_host') + if [ -n "$(echo "$getip" | grep :)" ]; then + ip=$getip + break + fi +} + +get_ip_from_website() { + check_ipv6_website="$(uci -q get openmptcprouter.settings.check_ipv6_website)" + [ -z "$check_ipv6_website" ] && check_ipv6_website="http://ipv6.openmptcprouter.com" + checkip=$(echo $check_ipv6_website | sed -e 's/https:\/\///' -e 's/http:\/\///' | xargs dig +short AAAA | tr -d "\n") + ipset add ss_rules6_dst_bypass_all $checkip > /dev/null 2>&1 + getip="$(curl -s -6 -m 2 --interface $intf $check_ipv6_website)" + ipset del ss_rules6_dst_bypass_all $checkip > /dev/null 2>&1 + if [ -n "$(echo "$getip" | grep :)" ]; then + ip=$getip + break + fi +} + +[ -z "$intf" ] && return +if [ -n "$(ip -6 a show dev $intf)" ]; then + ip="" + config_load openmptcprouter + config_foreach get_ip_from_server server + [ -z "$ip" ] && get_ip_from_website + echo $ip +fi \ No newline at end of file diff --git a/luci-app-openmptcprouter/root/bin/omr-tracebox-mptcp b/luci-app-openmptcprouter/root/bin/omr-tracebox-mptcp index 0c28829e1..932364d19 100755 --- a/luci-app-openmptcprouter/root/bin/omr-tracebox-mptcp +++ b/luci-app-openmptcprouter/root/bin/omr-tracebox-mptcp @@ -1,7 +1,16 @@ #!/bin/sh INTERFACE=$2 -if [ -z "$INTERFACE" ]; then - tracebox -m 20 -l "pkt = ip{dst=to} / tcp{dst=65101} / MPCAPABLE / MSS / WSCALE if string.find(tostring(tracebox(pkt)),'-TCPOptionMPTCPCapable') then print 'MPTCP disabled' elseif string.find(tostring(tracebox(pkt)),'MPTCP') then print 'MPTCP enabled' end" $1 +SERVER=$1 +if [ -n "$(resolveip -4 $SERVER)" ]; then + if [ -z "$INTERFACE" ]; then + tracebox -m 20 -l "pkt = ip{dst=to} / tcp{dst=65101} / MPCAPABLE / MSS / WSCALE if string.find(tostring(tracebox(pkt)),'-TCPOptionMPTCPCapable') then print 'MPTCP disabled' elseif string.find(tostring(tracebox(pkt)),'MPTCP') then print 'MPTCP enabled' end" $SERVER + else + tracebox -m 20 -l "pkt = ip{dst=to} / tcp{dst=65101} / MPCAPABLE / MSS / WSCALE if string.find(tostring(tracebox(pkt)),'-TCPOptionMPTCPCapable') then print 'MPTCP disabled' elseif string.find(tostring(tracebox(pkt)),'MPTCP') then print 'MPTCP enabled' end" -i $INTERFACE $SERVER + fi else - tracebox -m 20 -l "pkt = ip{dst=to} / tcp{dst=65101} / MPCAPABLE / MSS / WSCALE if string.find(tostring(tracebox(pkt)),'-TCPOptionMPTCPCapable') then print 'MPTCP disabled' elseif string.find(tostring(tracebox(pkt)),'MPTCP') then print 'MPTCP enabled' end" -i $INTERFACE $1 + if [ -z "$INTERFACE" ]; then + tracebox -6 -m 20 -l "pkt = ip{dst=to} / tcp{dst=65101} / MPCAPABLE / MSS / WSCALE if string.find(tostring(tracebox(pkt)),'-TCPOptionMPTCPCapable') then print 'MPTCP disabled' elseif string.find(tostring(tracebox(pkt)),'MPTCP') then print 'MPTCP enabled' end" $SERVER + else + tracebox -6 -m 20 -l "pkt = ip{dst=to} / tcp{dst=65101} / MPCAPABLE / MSS / WSCALE if string.find(tostring(tracebox(pkt)),'-TCPOptionMPTCPCapable') then print 'MPTCP disabled' elseif string.find(tostring(tracebox(pkt)),'MPTCP') then print 'MPTCP enabled' end" -i $INTERFACE $SERVER + fi fi \ No newline at end of file diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 633b47394..bb9700d29 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -545,7 +545,14 @@ function update_vps() local vpsgettoken = sys.exec("/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null") end +function get_rootfs() + local rootfs = {} + rootfs['format'] = ut.trim(sys.exec("mount | awk 'NR==1{print $5}'")) + return rootfs +end + function get_ip(interface) + local ut = require "luci.util" local dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {}) local ip = "" if dump and dump['ipv4-address'] then @@ -563,6 +570,42 @@ function get_ip(interface) end end end + if ip == "" then + local dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {}) + if dump and dump['l3_device'] then + local ifname = dump['l3_device'] + ip = ut.trim(sys.exec("ip -4 -br addr ls dev %s | awk -F'[ /]+' '{print $3}'" % ifname)) + end + end + return ip +end + +function get_ip6(interface) + local ut = require "luci.util" + local dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {}) + local ip = "" + if dump and dump['ipv6-address'] then + local _, ipv6address + for _, ipv6address in ipairs(dump['ipv6-address']) do + ip = dump['ipv6-address'][_].address + end + end + if ip == "" then + local dump = require("luci.util").ubus("network.interface.%s_6" % interface, "status", {}) + if dump and dump['ipv6-address'] then + local _, ipv6address + for _, ipv6address in ipairs(dump['ipv6-address']) do + ip = dump['ipv6-address'][_].address + end + end + end + if ip == "" then + local dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {}) + if dump and dump['l3_device'] then + local ifname = dump['l3_device'] + ip = ut.trim(sys.exec("ip -6 -br addr ls dev %s | awk -F'[ /]+' '{print $3}'" % ifname)) + end + end return ip end @@ -625,6 +668,56 @@ function get_gateway(interface) return gateway end +function get_gateway6(interface) + local gateway = "" + local dump = nil + + dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {}) + + if dump and dump.route then + local _, route + for _, route in ipairs(dump.route) do + if dump.route[_].target == "::" then + gateway = dump.route[_].nexthop + end + end + end + if gateway == "" then + if dump and dump.inactive and dump.inactive.route then + local _, route + for _, route in ipairs(dump.inactive.route) do + if dump.inactive.route[_].target == "::" then + gateway = dump.inactive.route[_].nexthop + end + end + end + end + + if gateway == "" then + dump = require("luci.util").ubus("network.interface.%s_6" % interface, "status", {}) + + if dump and dump.route then + local _, route + for _, route in ipairs(dump.route) do + if dump.route[_].target == "::" then + gateway = dump.route[_].nexthop + end + end + end + if gateway == "" then + if dump and dump.inactive and dump.inactive.route then + local _, route + for _, route in ipairs(dump.inactive.route) do + if dump.inactive.route[_].target == "::" then + gateway = dump.inactive.route[_].nexthop + end + end + end + end + end + return gateway +end + -- This function come from OverTheBox by OVH with many changes -- Copyright 2015 OVH -- Simon Lelievre (simon.lelievre@corp.ovh.com) @@ -689,16 +782,25 @@ function interfaces_status() if mArray.openmptcprouter["dns"] == true then -- wanaddr --mArray.openmptcprouter["wan_addr"] = uci:get("openmptcprouter","omr","public_detected_ipv4") or "" + if mArray.openmptcprouter["service_addr"] ~= "" then + mArray.openmptcprouter["service_addr_ip"] = ut.trim(sys.exec("resolveip -4 -t 1 " .. mArray.openmptcprouter["service_addr"] .. " | head -n 1")) + mArray.openmptcprouter["service_addr_ip6"] = ut.trim(sys.exec("resolveip -6 -t 1 " .. mArray.openmptcprouter["service_addr"] .. " | head -n 1")) + end if uci:get("openmptcprouter","settings","external_check") ~= "0" and mArray.openmptcprouter["dns"] == true then - mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("curl -4 -s -m " .. timeout .. " " .. check_ipv4_website)) - if mArray.openmptcprouter["wan_addr"] == "" then - mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("dig TXT +timeout=" .. timeout .. " +tries=1 +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'\"' '{print $2}'")) + if mArray.openmptcprouter["service_addr_ip"] ~= "" then + mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("curl -4 -s -m " .. timeout .. " " .. check_ipv4_website)) + if mArray.openmptcprouter["wan_addr"] == "" then + mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("dig -4 TXT +timeout=" .. timeout .. " +tries=1 +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'\"' '{print $2}'")) + end end - if mArray.openmptcprouter["ipv6"] == "enabled" then + if mArray.openmptcprouter["ipv6"] == "enabled" or mArray.openmptcprouter["service_addr_ip6"] ~= "" then mArray.openmptcprouter["wan_addr6"] = uci:get("openmptcprouter","omr","public_detected_ipv6") or "" if mArray.openmptcprouter["wan_addr6"] == "" then mArray.openmptcprouter["wan_addr6"] = ut.trim(sys.exec("curl -6 -s -m " .. timeout .. " " .. check_ipv6_website)) + if mArray.openmptcprouter["wan_addr"] == "" then + mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("dig -6 TXT +timeout=" .. timeout .. " +tries=1 +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'\"' '{print $2}'")) + end end end mArray.openmptcprouter["external_check"] = true @@ -720,9 +822,6 @@ function interfaces_status() end end end - if mArray.openmptcprouter["service_addr"] ~= "" then - mArray.openmptcprouter["service_addr_ip"] = ut.trim(sys.exec("resolveip -4 -t 1 " .. mArray.openmptcprouter["service_addr"] .. " | head -n 1")) - end end if mArray.openmptcprouter["service_addr"] ~= "" and mArray.openmptcprouter["service_addr"] ~= "127.0.0.1" then @@ -751,7 +850,13 @@ function interfaces_status() local adminport = uci:get("openmptcprouter",s[".name"],"port") or "65500" local token = uci:get("openmptcprouter",s[".name"],"token") or "" if token ~= "" then - local vpsinfo_json = sys.exec('curl -4 --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://' .. serverip .. ':' .. adminport .. '/status') + local vpsinfo_json = "" + if mArray.openmptcprouter["service_addr_ip"] ~= "" then + vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://' .. serverip .. ':' .. adminport .. '/status') + end + if mArray.openmptcprouter["service_addr_ip6"] ~= "" then + vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://[' .. serverip .. ']:' .. adminport .. '/status') + end if vpsinfo_json ~= "" and vpsinfo_json ~= nil then local status, vpsinfo = pcall(function() return json.decode(vpsinfo_json) @@ -821,7 +926,11 @@ function interfaces_status() mArray.openmptcprouter["vps_admin_error_msg"] = "No token yet available" end if mArray.openmptcprouter["vps_admin"] == false then - local vpstest = sys.exec('curl -4 --max-time ' .. timeout .. ' -s -k https://' .. serverip .. ':' .. adminport .. '/') + if mArray.openmptcprouter["service_addr_ip"] ~= "" then + local vpstest = sys.exec('curl --max-time ' .. timeout .. ' -s -k https://' .. serverip .. ':' .. adminport .. '/') + elseif mArray.openmptcprouter["service_addr_ip6"] ~= "" then + local vpstest = sys.exec('curl --max-time ' .. timeout .. ' -s -k https://[' .. serverip .. ']:' .. adminport .. '/') + end if vpstest == "" then mArray.openmptcprouter["vps_admin_error_msg"] = mArray.openmptcprouter["vps_admin_error_msg"] .. " - No API script answer" end @@ -859,7 +968,7 @@ function interfaces_status() else mArray.openmptcprouter["tun_state"] = "DOWN" end - if mArray.openmptcprouter["ipv6"] == "enabled" then + if mArray.openmptcprouter["ipv6"] == "enabled" or mArray.openmptcprouter["service_addr_ip6"] ~= "" then local tunnel_ipv6_gw = uci:get("network","omr6in4","gateway") local tunnel_ping6_test = ut.trim(sys.exec("ping6 -w 1 -c 1 " .. tunnel_ipv6_gw .. "%6in4-omr6in4 | grep '100% packet loss'")) if tunnel_ping6_test == "" then @@ -996,7 +1105,9 @@ function interfaces_status() local interface = section[".name"] local net = ntm:get_network(interface) local ipaddr = net:ipaddr() or "" + local ip6addr = net:ip6addr() or "" local gateway = section["gateway"] or "" + local gateway6 = section["ip6gw"] or "" local multipath = section["multipath"] local enabled = section["auto"] @@ -1034,7 +1145,13 @@ function interfaces_status() if ipaddr == "" and ifname ~= nil and ifname ~= "" then ipaddr = ut.trim(sys.exec("ip -4 addr show dev " .. ifname .. " | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1 | tr -d '\n'")) end - if ipaddr == "" then + if ip6addr == "" and ifname ~= nil and ifname ~= "" then + ip6addr = ut.trim(sys.exec("ip -6 -br addr ls dev " .. ifname .. " | awk -F'[ /]+' '{print $3}' | tr -d '\n'")) + end + if ip6addr == "" and ifname ~= nil and ifname ~= "" then + ip6addr = ut.trim(sys.exec("ip -6 addr show dev " .. ifname .. " | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1 | tr -d '\n'")) + end + if ipaddr == "" and ip6addr == "" then connectivity = "ERROR" end @@ -1071,8 +1188,10 @@ function interfaces_status() -- Detect WAN gateway status local gw_ping = "UP" - if ifname ~= nil and ifname:match("^tun.*") and interface:match("^ovpn.*") then + local gw_ping6 = "UP" + if ifname ~= nil and not (ifname:match("^tun.*") or interface:match("^ovpn.*")) then gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) + gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) end if gateway == "" then @@ -1086,18 +1205,40 @@ function interfaces_status() end end end + if gateway6 == "" then + gateway6 = get_gateway6(interface) + end + if gateway6 == "" and ifname ~= nil and ifname ~= "" then + if fs.access("/sys/class/net/" .. ifname) then + gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep kernel | awk '/proto kernel/ {print $1}' | grep -v / | tr -d '\n'")) + if gateway6 == "" then + gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep default | awk '{print $3}' | tr -d '\n'")) + end + end + end local signal = "" local operator = "" local phonenumber = "" local donglestate = "" local networktype = "" - if gateway ~= "" then + if gateway ~= "" or gateway6 ~= "" then if uci:get("openmptcprouter", "settings", "disablegwping") ~= "1" and connectivity ~= "ERROR" then - local gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway .. " | grep '100% packet loss'")) - if gw_ping_test ~= "" then - gw_ping = "DOWN" - if connectivity == "OK" then - connectivity = "WARNING" + if gateway ~= "" then + local gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway .. " | grep '100% packet loss'")) + if gw_ping_test ~= "" then + gw_ping = "DOWN" + if connectivity == "OK" then + connectivity = "WARNING" + end + end + end + if gateway6 ~= "" then + local gw_ping6_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway6 .. " | grep '100% packet loss'")) + if gw_ping6_test ~= "" then + gw_ping6 = "DOWN" + if connectivity == "OK" then + connectivity = "WARNING" + end end end end @@ -1111,7 +1252,7 @@ function interfaces_status() networktype = ut.trim(sys.exec("echo '".. intfdata .. "' | awk -F';' '{print $5}'")) end end - elseif gateway == "" then + elseif gateway == "" and gateway6 == "" then gw_ping = "DOWN" connectivity = "ERROR" end @@ -1147,7 +1288,7 @@ function interfaces_status() local latency = "" local server_ping = "" --if connectivity ~= "ERROR" and ifname ~= "" and gateway ~= "" and gw_ping ~= "DOWN" and ifname ~= nil and mArray.openmptcprouter["service_addr"] ~= "" and ipaddr ~= "" then - if ifname ~= "" and gateway ~= "" and gw_ping ~= "DOWN" and ifname ~= nil and mArray.openmptcprouter["service_addr"] ~= "" and ipaddr ~= "" and connectivity ~= "ERROR" then + if ifname ~= "" and (gateway ~= "" or gateway6 ~= "") and gw_ping ~= "DOWN" and ifname ~= nil and mArray.openmptcprouter["service_addr"] ~= "" and (ipaddr ~= "" or ip6addr ~= "") and connectivity ~= "ERROR" then local serverip = mArray.openmptcprouter["service_addr"] if serverip == "127.0.0.1" then serverip = mArray.openmptcprouter["wan_addr"] @@ -1170,7 +1311,7 @@ function interfaces_status() local multipath_available = "" local multipath_available_state = "" - if connectivity ~= "ERROR" and mArray.openmptcprouter["dns"] == true and ifname ~= nil and ifname ~= "" and gateway ~= "" and gw_ping == "UP" then + if connectivity ~= "ERROR" and mArray.openmptcprouter["dns"] == true and ifname ~= nil and ifname ~= "" and (gateway ~= "" or gateway6 ~= "") and (gw_ping == "UP" or gw_ping6 == "UP") then -- Test if multipath can work on the connection local multipath_available_state = uci:get("openmptcprouter",interface,"mptcp_status") or "" if multipath_available_state == "" then @@ -1207,7 +1348,9 @@ function interfaces_status() -- end local mtu = "" local whois = "" + local whois6 = "" local publicIP = "" + local publicIP6 = "" if connectivity ~= "ERROR" then if ifname ~= nil and ifname:match("^tun.*") and interface:match("^ovpn.*") then @@ -1215,24 +1358,39 @@ function interfaces_status() if ifname ~= nil and publicIP == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then publicIP = ut.trim(sys.exec("omr-ip-intf " .. get_device(interface:sub(5)))) end + publicIP6 = uci:get("openmptcprouter",interface:sub(5),"publicip6") or "" + if ifname ~= nil and publicIP6 == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then + publicIP6 = ut.trim(sys.exec("omr-ip6-intf " .. get_device(interface:sub(5)))) + end else publicIP = uci:get("openmptcprouter",interface,"publicip") or "" if ifname ~= nil and publicIP == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then publicIP = ut.trim(sys.exec("omr-ip-intf " .. ifname)) end + publicIP6 = uci:get("openmptcprouter",interface,"publicip6") or "" + if ifname ~= nil and publicIP6 == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then + publicIP6 = ut.trim(sys.exec("omr-ip6-intf " .. ifname)) + end end if publicIP ~= "" then whois = uci:get("openmptcprouter",interface,"asn") or "" if whois == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then - --whois = ut.trim(sys.exec("whois " .. publicIP .. " | grep -i 'netname' | awk '{print $2}'")) - whois = ut.trim(sys.exec("wget -4 -qO- -T 1 'http://api.iptoasn.com/v1/as/ip/" .. publicIP .. "' | jsonfilter -q -e '@.as_description'")) + whois = ut.trim(sys.exec("whois " .. publicIP .. " | grep -i 'netname' | awk '{print $2}'")) + --whois = ut.trim(sys.exec("wget -4 -qO- -T 1 'http://api.iptoasn.com/v1/as/ip/" .. publicIP .. "' | jsonfilter -q -e '@.as_description'")) + end + end + if publicIP6 ~= "" then + whois6 = uci:get("openmptcprouter",interface,"asn") or "" + if whois6 == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then + whois6 = ut.trim(sys.exec("whois " .. publicIP6 .. " | grep -i 'netname' | awk '{print $2}'")) + --whois6 = ut.trim(sys.exec("wget -6 -qO- -T 1 'http://api.iptoasn.com/v1/as/ip/" .. publicIP6 .. "' | jsonfilter -q -e '@.as_description'")) end end if ifname ~= "" and ifname ~= nil then if fs.access("/sys/class/net/" .. ifname) then mtu = ut.trim(sys.exec("cat /sys/class/net/" .. ifname .. "/mtu | tr -d '\n'")) if mtu == "" and interface ~= nil then - mtu = uci:get("openmptcprouter",interface,"mtu") or "" + mtu = uci:get("openmptcprouter",interface,"mtu") or "" end end end @@ -1249,17 +1407,22 @@ function interfaces_status() --link = net:adminlink() or "", ifname = ifname, ipaddr = ipaddr, + ip6addr = ip6addr, gateway = gateway, + gateway6 = gateway6, multipath = section["multipath"], status = connectivity, wanip = publicIP, + wanip6 = publicIP6, latency = latency, mtu = mtu, whois = whois or "unknown", + whois6 = whois6 or "unknown", qos = section["trafficcontrol"], download = section["download"], upload = section["upload"], gw_ping = gw_ping, + gw_ping6 = gw_ping6, server_ping = server_ping, ipv6_discover = ipv6_discover, multipath_available = multipath_available, @@ -1350,6 +1513,11 @@ function _ipv6_discover(interface) end local methods = { + getrootfs = { + call = function() + return get_rootfs() + end + }, status = { call = function() return interfaces_status() From b25b156436196e81c98c2721418e7ebff8ca2af8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 16 Jan 2021 08:12:03 +0100 Subject: [PATCH 0029/2059] Make omr-tracebox and omr-test-speed compatible with WAN IPv6 --- openmptcprouter/files/bin/omr-test-speedv6 | 29 ++++++++++++++++++---- openmptcprouter/files/bin/omr-tracebox | 3 +++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index ae7634d7c..27fd43e68 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -1,15 +1,34 @@ #!/bin/sh # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : - INTERFACE="$1" -HOST="proof.ovh.net" +echo "Select best test server..." +HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip http://www.ovh.net/files/10Gb.dat https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" +bestping="999" +for pinghost in $HOSTLST; do + domain=$(echo $pinghost | awk -F/ '{print $3}') + if [ -z "$INTERFACE" ]; then + ping=$(ping -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1) + else + ping=$(ping -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1) + fi + echo "host: $domain - ping: $ping" + if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then + bestping=$ping + HOST=$pinghost + fi +done + +[ -z "$HOST" ] && HOST="http://proof.ovh.net/files/10Gio.dat" + +echo "Best server is $HOST, running test:" trap : HUP INT TERM if [ -z "$INTERFACE" ]; then - curl -6 http://$HOST/files/10Gio.dat >/dev/null || echo + curl -6 $HOST >/dev/null || echo else - hostip=$(dig +short AAAA $HOST | tr -d "\n") + domain=$(echo $HOST | awk -F/ '{print $3}') + hostip=$(dig +nocmd +noall +answer AAAA $domain | grep -v CNAME | awk '{print $5}' | tr -d "\n") ipset add ss_rules6_dst_bypass_all $hostip - curl -6 --interface $INTERFACE http://$HOST/files/10Gio.dat >/dev/null || echo + curl -6 --interface $INTERFACE $HOST >/dev/null || echo ipset del ss_rules6_dst_bypass_all $hostip fi diff --git a/openmptcprouter/files/bin/omr-tracebox b/openmptcprouter/files/bin/omr-tracebox index 2342d3b8c..2352b53ea 100755 --- a/openmptcprouter/files/bin/omr-tracebox +++ b/openmptcprouter/files/bin/omr-tracebox @@ -2,9 +2,12 @@ INTERFACE="$1" multipathip=$(dig +short A multipath-tcp.org | tr -d "\n") ipset add ss_rules_dst_bypass_all $multipathip > /dev/null 2>&1 +multipathip6=$(dig +short AAAA multipath-tcp.org | tr -d "\n") +ipset add ss_rules6_dst_bypass_all $multipathip6 > /dev/null 2>&1 if [ -z "$INTERFACE" ]; then tracebox -v -n -p IP/TCP/MSS/MPCAPABLE/WSCALE multipath-tcp.org else tracebox -v -i $INTERFACE -n -p IP/TCP/MSS/MPCAPABLE/WSCALE multipath-tcp.org fi ipset del ss_rules_dst_bypass_all $multipathip > /dev/null 2>&1 +ipset del ss_rules6_dst_bypass_all $multipathip6 > /dev/null 2>&1 From 36351e8548c3cf4878ecab2a97c4ded3d3f0b041 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 16 Jan 2021 08:14:09 +0100 Subject: [PATCH 0030/2059] Make omr-tracker compatible with WAN IPv6 --- .../share/omr/post-tracking.d/post-tracking | 383 +++++++++++++++++- omr-tracker/files/bin/omr-tracker | 115 ++++++ omr-tracker/files/etc/init.d/omr-tracker | 9 +- .../files/etc/init.d/openmptcprouter-vps | 48 ++- .../files/etc/uci-defaults/1980-omr-firewall | 13 + 5 files changed, 546 insertions(+), 22 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 0acb30236..ca23f14cd 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1,5 +1,5 @@ - SETROUTE=false + set_route() { local multipath_config_route interface_gw interface_if INTERFACE=$1 @@ -33,6 +33,39 @@ set_route() { fi } +set_route6() { + local multipath_config_route interface_gw interface_if + INTERFACE=$1 + PREVINTERFACE=$2 + SETDEFAULT=$3 + [ -z "$SETDEFAULT" ] && SETDEFAULT="yes" + multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) + [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") + if [ "$multipath_config_route" != "off" ] && [ "$SETROUTE" != true ] && [ "$INTERFACE" != "$PREVINTERFACE" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + interface_gw="$(uci -q get network.$INTERFACE.gateway)" + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.${INTERFACE}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" + [ "$SETDEFAULT" = "yes" ] && ip -6 route replace default scope global nexthop via $interface_gw dev $interface_if + ip -6 route replace default via $interface_gw dev $interface_if table 991337 && SETROUTE=true + fi + fi +} + set_server_default_route() { local server=$1 local serverip multipath_config_route @@ -52,6 +85,25 @@ set_server_default_route() { fi } +set_server_default_route6() { + local server=$1 + local serverip multipath_config_route + config_get serverip $server ip + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) + [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route via $OMR_TRACKER_DEVICE_GATEWAY6" + if [ "$(ip -6 r show $serverip | grep nexthop)" != "" ]; then + ip -6 r delete $serverip >/dev/null 2>&1 + fi + ip -6 route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric 1 + fi +} + delete_server_default_route() { local server=$1 local serverip @@ -65,6 +117,19 @@ delete_server_default_route() { fi } +delete_server_default_route6() { + local server=$1 + local serverip + config_get serverip $server ip + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + if [ "$serverip" != "" ] && [ "$(ip -6 route show $serverip metric 1)" != "" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Delete server ($serverip) default route" + ip -6 route del $serverip metric 1 >/dev/null 2>&1 + fi +} + set_routes_intf() { local multipath_config_route local INTERFACE=$1 @@ -89,7 +154,7 @@ set_routes_intf() { interface_gw=$(ubus call network.interface.${INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") fi #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ "$(ip route show $serverip | grep $interface_if)" = "" ]; then - if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ]; then + if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then if [ "$multipath_config_route" = "master" ]; then weight=10 else @@ -114,6 +179,55 @@ set_routes_intf() { fi } +set_routes_intf6() { + local multipath_config_route + local INTERFACE=$1 + multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) + [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo 'off')" + interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + #multipath_current_config=$(multipath $interface_if | grep 'deactivated') + interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") + if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_if" != "" ] && [ "$interface_up" = "true" ]; then + interface_gw="$(uci -q get network.$INTERFACE.gateway)" + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.${INTERFACE}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ "$(ip -6 route show $serverip | grep $interface_if)" = "" ]; then + if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then + if [ "$multipath_config_route" = "master" ]; then + weight=10 + else + weight=1 + fi + if [ "$multipath_config_route" = "backup" ]; then + nbintfb=$((nbintfb+1)) + if [ -z "$routesintfbackup6" ]; then + routesintfbackup6="nexthop via $interface_gw dev $interface_if weight $weight" + else + routesintfbackup6="$routesintfbackup6 nexthop via $interface_gw dev $interface_if weight $weight" + fi + else + nbintf=$((nbintf+1)) + if [ -z "$routesintf6" ]; then + routesintf6="nexthop via $interface_gw dev $interface_if weight $weight" + else + routesintf6="$routesintf6 nexthop via $interface_gw dev $interface_if weight $weight" + fi + fi + fi + fi +} + set_route_balancing() { local multipath_config_route interface_gw interface_if INTERFACE=$1 @@ -157,6 +271,49 @@ set_route_balancing() { fi } +set_route_balancing6() { + local multipath_config_route interface_gw interface_if + INTERFACE=$1 + multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) + [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo 'off')" + interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") + if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + interface_gw="$(uci -q get network.$INTERFACE.gateway)" + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.${INTERFACE}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then + if [ "$(uci -q get network.$INTERFACE.weight)" != "" ]; then + weight=$(uci -q get network.$INTERFACE.weight) + elif [ "$(uci -q get openmtpcprouter.$INTERFACE.weight)" != "" ]; then + weight=$(uci -q get openmtpcprouter.$INTERFACE.weight) + elif [ "$multipath_config_route" = "master" ]; then + weight=2 + else + weight=1 + fi + if [ "$multipath_config_route" = "backup" ]; then + nbintfb=$((nbintfb+1)) + routesbalancingbackup6="$routesbalancingbackup6 nexthop via $interface_gw dev $interface_if weight $weight" + else + nbintf=$((nbintf+1)) + routesbalancing6="$routesbalancing6 nexthop via $interface_gw dev $interface_if weight $weight" + fi + fi + fi +} + set_server_all_routes() { local server=$1 local serverip multipath_config_route @@ -195,6 +352,44 @@ set_server_all_routes() { fi } +set_server_all_routes6() { + local server=$1 + local serverip multipath_config_route + config_get serverip $server ip + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then + routesintf="" + routesintfbackup="" + nbintf=0 + nbintfb=0 + config_load network + config_foreach set_routes_intf interface + uintf="$(echo $routesintf | awk '{print $5}')" + uintfb="$(echo $routesintfbackup | awk '{print $5}')" + if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then + while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do + ip -6 r del $serverip + done + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf" + ip -6 route replace $serverip scope global $routesintf + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" + fi + if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" + ip -6 route replace $serverip scope global metric 999 $routesintfbackup + fi + fi +} + set_server_route() { @@ -225,6 +420,34 @@ set_server_route() { fi } +set_server_route6() { + local server=$1 + local serverip multipath_config_route + config_get serverip $server ip + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + local metric=$2 + [ -z "$metric" ] && metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) + [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + #multipath_current_config=$(multipath $interface_if | grep "deactivated") + interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") + #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" + ip -6 route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric + fi + if [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric + fi +} + del_server_route() { local server=$1 local serverip @@ -242,6 +465,23 @@ del_server_route() { fi } +del_server_route6() { + local server=$1 + local serverip + config_get serverip $server ip + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" + local metric + metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + ip -6 route del default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + else + ip -6 route del default dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + fi +} + disable_pihole() { local server=$1 if [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep '#53' | grep '10.2')" ]; then @@ -288,6 +528,7 @@ if [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then fi default_gw=$(ip route show default | grep -v "metric" | awk '/default/ {print $3}') +default_gw6=$(ip -6 route show default | grep -v "metric" | awk '/default/ {print $3}') #current_interface_gw=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway") interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') @@ -320,6 +561,9 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ -n "$OMR_TRACKER_DEVICE_IP" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set down > /dev/null 2>&1 fi + if [ -n "$OMR_TRACKER_DEVICE_IP6" ]; then + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set down > /dev/null 2>&1 + fi if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then VPN_BASE_INTF="$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.baseintf)" VPN_BASE_INTF_IP=$(ubus call network.interface.$VPN_BASE_INTF status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") @@ -331,18 +575,22 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi config_load openmptcprouter config_foreach del_server_route server + config_foreach del_server_route6 server #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then config_foreach set_server_all_routes server + config_foreach set_server_all_routes6 server fi fi - if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then config_load network config_foreach set_route interface $OMR_TRACKER_INTERFACE + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then config_load network config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" fi mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)" [ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" @@ -370,6 +618,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then config_load network config_foreach set_route interface $OMR_TRACKER_INTERFACE + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE fi if [ "$(uci -q get openmptcprouter.settings.shadowsocksudp)" = "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.shadowsocks)" = "up" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "" ] && [ "$(uci -q get shadowsocks-libev.hi2.mode)" = "tcp_and_udp" ] && [ "$(uci -q get shadowsocks-libev.sss0.obfs)" != "1" ]; then _log "Tunnel down use ShadowSocks for UDP" @@ -400,6 +649,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then #if [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ] || [ "$(uci -q get openmptcprouter.settings.vpn)" = "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then config_foreach set_server_default_route server + config_foreach set_server_default_route6 server fi fi dns_flush @@ -525,6 +775,20 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_server_default_route server fi fi + if ([ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$default_gw6" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then + omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") + if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" + ip -6 route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE + fi + config_load openmptcprouter + #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then + # config_foreach set_server_all_routes server + if [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then + config_foreach set_server_default_route server + config_foreach set_server_default_route6 server + fi + fi #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") @@ -534,10 +798,17 @@ if [ "$multipath_config" = "master" ]; then nbintf=0 config_load network config_foreach set_route_balancing interface + config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 0 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show default metric 0 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { _log "Set ip route replace default scope global $routesbalancing" - ip route replace default scope global $routesbalancing + ip route replace default scope global metric 0 $routesbalancing + } + } + [ -n "$routesbalancing6" ] && { + ([ "$nbintf" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" + ip -6 route replace default scope global metric 1 $routesbalancing6 } } [ -n "$routesbalancingbackup" ] && { @@ -546,11 +817,20 @@ if [ "$multipath_config" = "master" ]; then ip route replace default scope global metric 999 $routesbalancingbackup } } + [ -n "$routesbalancingbackup6" ] && { + ([ "$nbintf" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + _log "Set backup ip -6 route replace default scope global $routesbalancingbackup6" + ip -6 route replace default scope global metric 999 $routesbalancingbackup6 + } + } fi fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE " ]; then ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE table 991337 fi + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE " ]; then + ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 991337 + fi if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") + $((10 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]; then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 fi @@ -566,6 +846,15 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then config_foreach set_server_route server fi fi +if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + config_load openmptcprouter + #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then + if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then + config_foreach set_server_all_routes6 server + elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then + config_foreach set_server_route6 server + fi +fi if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then download="$(uci -q get network.$OMR_TRACKER_INTERFACE.downloadspeed)" @@ -577,18 +866,33 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi gtudpst="up" [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" - if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ]; then + if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ] && [ "$OMR_TRACKER_DEVICE_IP" != "" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate pref 1 auto tx $((upload*1000/8)) rx $((download*1000/8)) > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate pref 1 fixed tx $((upload*1000/8)) rx $((download*1000/8)) > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate fixed tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 fi else if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up pref 1 rate auto tx 12500000 rx 12500000 > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate auto tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up pref 1 rate fixed tx 12500000 rx 12500000 > /dev/null 2>&1 + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate fixed tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 + fi + fi + fi + if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6)" = "" ] && [ "$OMR_TRACKER_DEVICE_IP6" != "" ]; then + if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then + if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 + else + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate fixed tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 + fi + else + if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate auto tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 + else + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate fixed tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 fi fi fi @@ -612,6 +916,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Get status and settings for $OMR_TRACKER_INTERFACE..." if [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ]; then local ipaddr="$(omr-ip-intf $OMR_TRACKER_DEVICE)" + local ip6addr="$(omr-ip6-intf $OMR_TRACKER_DEVICE)" else uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state="up" @@ -641,10 +946,10 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( # fi #fi if [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ]; then - local asn="$(wget -4 -qO- -T 4 http://api.iptoasn.com/v1/as/ip/$ipaddr | jsonfilter -q -e '@.as_description')" - [ -z "$asn" ] && { - asn="$(whois $ipaddr 2>/dev/null | grep -m 1 -i 'netname' | awk '{print $2}')" - } + #local asn="$(wget -4 -qO- -T 4 http://api.iptoasn.com/v1/as/ip/$ipaddr | jsonfilter -q -e '@.as_description')" + #[ -z "$asn" ] && { + local asn="$(whois $ipaddr 2>/dev/null | grep -m 1 -i 'netname' | awk '{print $2}')" + #} fi [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE)" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE=interface @@ -694,6 +999,58 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") } + [ -n "$ip6addr" ] && { + if [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ]; then + local asn="$(whois $ip6addr 2>/dev/null | grep -m 1 -i 'netname' | awk '{print $2}')" + fi + [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE)" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE=interface + } + if [ "$(uci -q get openmptcprouter.latest_versions.lc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.latest_versions.lc))) -gt 3600 ]; then + local latestversions="$(curl -6 -s -m 3 https://www.openmptcprouter.com/version/version.json)" + [ -n "$latestversions" ] && { + uci -q set openmptcprouter.latest_versions=latest_versions + uci -q set openmptcprouter.latest_versions.omr=$(echo $latestversions | jsonfilter -q -e '@.omr') + uci -q set openmptcprouter.latest_versions.vps=$(echo $latestversions | jsonfilter -q -e '@.vps') + uci -q set openmptcprouter.latest_versions.lc=$(date +"%s") + } + fi + local serverip=$(uci -q get shadowsocks-libev.sss0.server) + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { + omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" + [ -n "$omrtracebox" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" + } + [ -n "$ipaddr" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip6="$ip6addr" + [ -n "$OMR_TRACKER_LATENCY" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" + [ -n "$asn" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.asn="$asn" + } + if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then + if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then + mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + else + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { + local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + } || { + local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 1.1.1.1) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + } + fi + fi + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") + } if [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get openmptcprouter.settings.external_check)" = "0" ]; then if ping -c 1 $(uci -q get shadowsocks-libev.sss0.server) 2>&1 >/dev/null; then uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 2e7b3d96a..637c27019 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -5,6 +5,7 @@ [ -n "$1" ] || exit . /lib/functions.sh +. /usr/lib/unbound/iptools.sh # retrieve args OMR_TRACKER_INTERFACE="$1" @@ -13,16 +14,20 @@ shift # export vars export OMR_TRACKER_INTERFACE export OMR_TRACKER_HOST +export OMR_TRACKER_HOST6 export OMR_TRACKER_TIMEOUT export OMR_TRACKER_STATUS export OMR_TRACKER_STATUS_MSG export OMR_TRACKER_PREV_STATUS export OMR_TRACKER_DEVICE export OMR_TRACKER_DEVICE_IP +export OMR_TRACKER_DEVICE_IP6 export OMR_TRACKER_DEVICE_GATEWAY +export OMR_TRACKER_DEVICE_GATEWAY6 dscp=56 # set DSCP CS7 (56) in outgoing packets initial_hosts="$OMR_TRACKER_HOSTS" +initial_hosts6="$OMR_TRACKER_HOSTS6" initial_timeout="$OMR_TRACKER_TIMEOUT" wait_test=${OMR_TRACKER_WAIT_TEST:-0} @@ -59,10 +64,15 @@ _update_rto() { _restart() { OMR_TRACKER_HOST="${OMR_TRACKER_HOSTS%% *}" + OMR_TRACKER_HOST6="${OMR_TRACKER_HOSTS6%% *}" [ "$OMR_TRACKER_HOST" = "$OMR_TRACKER_HOSTS" ] || { OMR_TRACKER_HOSTS="${OMR_TRACKER_HOSTS#* } $OMR_TRACKER_HOST" _init_rto } + [ "$OMR_TRACKER_HOST6" = "$OMR_TRACKER_HOSTS6" ] || { + OMR_TRACKER_HOSTS6="${OMR_TRACKER_HOSTS6#* } $OMR_TRACKER_HOST6" + _init_rto + } } _post_tracking() { @@ -170,12 +180,14 @@ OMR_TRACKER_PREV_STATUS="" while true; do # setup tracker variables OMR_TRACKER_DEVICE_IP= + OMR_TRACKER_DEVICE_IP6= OMR_TRACKER_STATUS="ERROR" OMR_TRACKER_STATUS_MSG="" OMR_TRACKER_LATENCY= #OMR_TRACKER_TIMEOUT=$((rto / 1000 + (rto % 1000 ? 1 : 0))) OMR_TRACKER_LIST_HOSTS="" OMR_TRACKER_DEVICE_GATEWAY= + OMR_TRACKER_DEVICE_GATEWAY6= serverip_ping=false if [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then @@ -185,6 +197,10 @@ while true; do if [ -z "$OMR_TRACKER_DEVICE_IP" ]; then OMR_TRACKER_DEVICE_IP=$(ip -4 addr show dev "$OMR_TRACKER_DEVICE" | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) fi + #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') + #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then + OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | grep -v 'inet6 f' | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) + #fi #OMR_TRACKER_DEVICE_IP=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") #if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then # OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") @@ -219,6 +235,15 @@ while true; do if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | awk '/proto kernel/ {print $1}' | tr -d "\n") fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(uci -q get "network.$OMR_TRACKER_INTERFACE.ip6gw") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}\"].nexthop" | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") + fi # execute specific tracker if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then @@ -304,6 +329,89 @@ while true; do sleep "$OMR_TRACKER_INTERVAL_TRIES" done fi + if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + # setup loop variable + tries="$OMR_TRACKER_TRIES" + # loop until tries attempts have been reached + while [ "$tries" -gt 0 ]; do + #if [ -n "$OMR_TRACKER_DEVICE_ROUTE" ]; then + # _ping "$OMR_TRACKER_DEVICE_ROUTE" "$OMR_TRACKER_DEVICE" "no" + # status=$? + #else + _ping "$OMR_TRACKER_DEVICE_GATEWAY6" "$OMR_TRACKER_DEVICE" "no" + status=$? + #fi + if $(exit $status) && [ "$OMR_TRACKER_TYPE" = "none" ]; then + OMR_TRACKER_STATUS_MSG="" + OMR_TRACKER_STATUS="OK" + break + elif [ "$OMR_TRACKER_TYPE" != "none" ]; then + if ! $(exit $status); then + OMR_TRACKER_STATUS_MSG="gateway6 down" + fi + serverip_ping=false + if [ "$OMR_TRACKER_TYPE" = "ping" ]; then + config_load openmptcprouter + config_foreach _ping_server server $OMR_TRACKER_DEVICE + fi + if [ "$serverip_ping" = false ] && [ -n "$OMR_TRACKER_HOST6" ]; then + OMR_TRACKER_HOST6=$(resolveip -6 -t 5 $OMR_TRACKER_HOST6 | head -n 1 | tr -d "\n") + if [ -n "$OMR_TRACKER_HOST6" ]; then + if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "3g" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "qmi" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "ncm" ]; then + # Check if route is not used + while ! ip -6 route add $OMR_TRACKER_HOST6 via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE src $OMR_TRACKER_DEVICE_IP6 > /dev/null 2>&1 + do + logger -t "omr-tracker" "Can't create route to $OMR_TRACKER_HOST6 via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE src $OMR_TRACKER_DEVICE_IP6. waiting..." + sleep 2 + ip -6 route del "$OMR_TRACKER_HOST6" via "$OMR_TRACKER_DEVICE_GATEWAY6" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP6" > /dev/null 2>&1 + _restart + done + fi + if [ "$OMR_TRACKER_TYPE" = "ping" ]; then + _ping "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE" "yes" + statusb=$? + elif [ "$OMR_TRACKER_TYPE" = "httping" ]; then + _httping "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP" "yes" + statusb=$? + elif [ "$OMR_TRACKER_TYPE" = "dns" ]; then + _dns "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP" "yes" + statusb=$? + fi + ip route del "$OMR_TRACKER_HOST6" via "$OMR_TRACKER_DEVICE_GATEWAY6" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP6" > /dev/null 2>&1 + if $(exit $statusb); then + OMR_TRACKER_STATUS_MSG="" + OMR_TRACKER_STATUS="OK" + break + else + if [ "$OMR_TRACKER_LIST_HOSTS6" = "" ]; then + OMR_TRACKER_LIST_HOSTS="$OMR_TRACKER_HOST6" + else + OMR_TRACKER_LIST_HOSTS6="$OMR_TRACKER_LIST_HOSTS6,$OMR_TRACKER_HOST6" + fi + fi + else + OMR_TRACKER_STATUS_MSG="" + OMR_TRACKER_STATUS="OK" + break + fi + else + OMR_TRACKER_STATUS_MSG="" + OMR_TRACKER_STATUS="OK" + break + fi + elif ! $(exit $status); then + OMR_TRACKER_STATUS_MSG="gateway down" + fi + tries=$((tries - 1)) + #_restart + OMR_TRACKER_HOST6="${OMR_TRACKER_HOSTS6%% *}" + [ "$OMR_TRACKER_HOST6" = "$OMR_TRACKER_HOSTS6" ] || { + OMR_TRACKER_HOSTS6="${OMR_TRACKER_HOSTS6#* } $OMR_TRACKER_HOST6" + } + #OMR_TRACKER_TIMEOUT=$((OMR_TRACKER_TIMEOUT * 2)) + sleep "$OMR_TRACKER_INTERVAL_TRIES" + done + fi else OMR_TRACKER_STATUS_MSG="link down" fi @@ -316,6 +424,13 @@ while true; do OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG and $OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS)" fi fi + if [ "$OMR_TRACKER_LIST_HOSTS6" != "" ]; then + if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then + OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS6)" + else + OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG and $OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS6)" + fi + fi #[ "$OMR_TRACKER_HOSTS" = "$initial_hosts" ] || [ "$OMR_TRACKER_STATUS" = "OK" ] && _post_tracking #[ "$OMR_TRACKER_STATUS" = "ERROR" ] && _restart diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 3612c57ee..d5965fe1f 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -11,12 +11,15 @@ USE_PROCD=1 } +. /usr/lib/unbound/iptools.sh + _validate_section() { - local tmp_hosts=$hosts tmp_timeout=$timeout tmp_tries=$tries + local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_tries=$tries local tmp_interval=$interval tmp_interval_tries=$interval_tries tmp_options=$options tmp_type=$type tmp_enabled=$enabled tmp_wait_test=$wait_test uci_validate_section omr-tracker "$1" "$2" \ 'hosts:list(host)' \ + 'hosts6:list(host6)' \ 'timeout:uinteger' \ 'tries:uinteger' \ 'interval:uinteger' \ @@ -27,6 +30,7 @@ _validate_section() { 'options:string' [ -z "$hosts" ] && hosts=$tmp_hosts + [ -z "$hosts6" ] && hosts6=$tmp_hosts6 [ -z "$timeout" ] && timeout=$tmp_timeout [ -z "$tries" ] && tries=$tmp_tries [ -z "$interval" ] && interval=$tmp_interval @@ -42,7 +46,7 @@ _launch_tracker() { loopback|lan*|if0*) return;; esac - local hosts timeout tries interval interval_tries options type enabled wait_test + local hosts hosts6 timeout tries interval interval_tries options type enabled wait_test _validate_section "defaults" "defaults" _validate_section "interface" "$1" @@ -65,6 +69,7 @@ _launch_tracker() { # shellcheck disable=SC2086 procd_set_param command /bin/omr-tracker "$1" $options procd_append_param env "OMR_TRACKER_HOSTS=$hosts" + procd_append_param env "OMR_TRACKER_HOSTS6=$hosts6" procd_append_param env "OMR_TRACKER_TIMEOUT=$timeout" procd_append_param env "OMR_TRACKER_TRIES=$tries" procd_append_param env "OMR_TRACKER_INTERVAL=$interval" diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 0ec6b55de..3c5ca2aaf 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -8,6 +8,8 @@ USE_PROCD=1 EXTRA_COMMANDS="set_pihole backup_send backup_get backup_list set_vps_firewall get_openvpn_key" +. /usr/lib/unbound/iptools.sh + _parse_result() { result=$("echo $1 | jsonfilter -q -e '@.result'") echo $result @@ -22,7 +24,13 @@ _login() { serverport="$(uci -q get openmptcprouter.${servername}.port)" if [ -z "$token" ]; then #auth=`curl --max-time 10 -s -k -H "Content-Type: application/json" -X POST -d '{"username":"'$username'","password":"'$password'"}' https://$server:$serverport/login` - auth=`curl --max-time 10 -s -k -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'username='$username'&password='$password https://$server:$serverport/token` + resolve="$(resolveip $server)" + valid_ip6=$(valid_subnet6 $server) + if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then + auth=`curl --max-time 10 -s -k -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'username='$username'&password='$password https://$server:$serverport/token` + else + auth=`curl --max-time 10 -s -k -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'username='$username'&password='$password https://[$server]:$serverport/token` + fi [ -z "$auth" ] && return token="$(echo "$auth" | jsonfilter -q -e '@.access_token')" uci -q set openmptcprouter.${servername}.token="$token" @@ -41,7 +49,13 @@ _get_json() { route=$1 [ -z "$token" ] && _login [ -n "$token" ] && { - result=`curl --max-time 10 -s -k -H "accept: application/json" -H "Authorization: Bearer $token" https://$server:$serverport/$route` + resolve="$(resolveip $server)" + valid_ip6=$(valid_subnet6 $server) + if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then + result=`curl --max-time 10 -s -k -H "accept: application/json" -H "Authorization: Bearer $token" https://$server:$serverport/$route` + else + result=`curl --max-time 10 -s -k -H "accept: application/json" -H "Authorization: Bearer $token" https://[$server]:$serverport/$route` + fi echo $result } || { echo '' @@ -54,7 +68,13 @@ _set_json() { settings="$2" [ -z "$token" ] && _login [ -n "$token" ] && { - result=`curl --max-time 10 -s -k -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X POST -d "$settings" https://$server:$serverport/$route` + resolve="$(resolveip $server)" + valid_ip6=$(valid_subnet6 $server) + if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then + result=`curl --max-time 10 -s -k -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X POST -d "$settings" https://$server:$serverport/$route` + else + result=`curl --max-time 10 -s -k -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X POST -d "$settings" https://[$server]:$serverport/$route` + fi echo $result } || { echo '' @@ -449,6 +469,7 @@ _get_gre_tunnel() { set network.omrip${i}gre.defaultroute='0' set network.omrip${i}gre.multipath='off' set network.omrip${i}gre.peerdns='0' + set network.omrip${i}gre.ttl='255' set network.omrip${i}gre.ip4table='vpn' set network.omrip${i}gre.peeraddr="$publicaddr" set network.omrip${i}gre.ipaddr="$vpnip_local" @@ -1453,7 +1474,7 @@ _backup_send() { EOF return } - sysupgrade -b /tmp/backup.tar.gz + sysupgrade -k -b /tmp/backup.tar.gz backup_data="$(cat /tmp/backup.tar.gz | base64 | tr -d '\n')" backup_sha256sum="$(sha256sum /tmp/backup.tar.gz | awk '{print $1}')" [ -n "$backup_data" ] && { @@ -1574,10 +1595,20 @@ _config_service() { fi port="$(uci -q get openmptcprouter.${servername}.port)" server="$(uci -q get openmptcprouter.${servername}.ip)" - if [ "$(curl -k -m 3 https://${server}:${port}/)" = "" ]; then - reason="$reason, no server API answer" + resolve="$(resolveip $server)" + valid_ip6=$(valid_subnet6 $server) + if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then + if [ "$(curl -k -m 3 https://${server}:${port}/)" = "" ]; then + reason="$reason, no server API answer" + else + reason="$reason, server API answer" + fi else - reason="$reason, server API answer" + if [ "$(curl -k -m 3 https://[${server}]:${port}/)" = "" ]; then + reason="$reason, no server API answer" + else + reason="$reason, server API answer" + fi fi if [ "$(uci -q get openmptcprouter.${servername}.username)" != "openmptcprouter" ]; then reason="$reason, custom username" @@ -1706,6 +1737,9 @@ start_service() { uci -q batch <<-EOF >/dev/null commit openmptcprouter EOF + if [ "$(ps w | grep sysupgrade)" = "" ]; then + /etc/init.d/sysupgrade restart + fi } service_triggers() { diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index e6f918796..204cb92f3 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -151,6 +151,19 @@ if [ "$(uci -q get firewall.blockquicproxy)" = "" ]; then EOF fi +if [ "$(uci -q get firewall.allowicmpipv6)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set firewall.allowicmpipv6=rule + set firewall.allowicmpipv6.proto='icmp' + set firewall.allowicmpipv6.target='ACCEPT' + set firewall.allowicmpipv6.src='wan' + set firewall.allowicmpipv6.name='Allow IPv6 ICMP' + set firewall.allowicmpipv6.family='ipv6' + set firewall.allowicmpipv6.icmp_type='neighbour-advertisement neighbour-solicitation router-advertisement router-solicitation' + commit firewall + EOF +fi + # Fix firewall config from some old config allintf=$(uci -q get firewall.@zone[1].network) uci -q del firewall.@zone[1].network From 027c4e7c497843af437b2bcfd51bc65604d7038a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 16 Jan 2021 08:14:51 +0100 Subject: [PATCH 0031/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/1524 --- .../luasrc/model/cbi/https-dns-proxy.lua | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/luci-app-https-dns-proxy/luasrc/model/cbi/https-dns-proxy.lua b/luci-app-https-dns-proxy/luasrc/model/cbi/https-dns-proxy.lua index d914bf09a..d4fee9e00 100644 --- a/luci-app-https-dns-proxy/luasrc/model/cbi/https-dns-proxy.lua +++ b/luci-app-https-dns-proxy/luasrc/model/cbi/https-dns-proxy.lua @@ -36,14 +36,16 @@ function create_helper_text() end function get_provider_name(value) - for filename in fs.dir(providers_dir) do - local p_func = loadfile(providers_dir .. filename) - setfenv(p_func, { _ = i18n.translate }) - local p = p_func() - value = value:gsub('[%p%c%s]', '') - p.url_match = p.resolver_url:gsub('[%p%c%s]', '') - if value:match(p.url_match) then - return p.label + if value ~= nil then + for filename in fs.dir(providers_dir) do + local p_func = loadfile(providers_dir .. filename) + setfenv(p_func, { _ = i18n.translate }) + local p = p_func() + value = value:gsub('[%p%c%s]', '') + p.url_match = p.resolver_url:gsub('[%p%c%s]', '') + if value:match(p.url_match) then + return p.label + end end end return translate("Unknown Provider") From 14db6f80fbddb0b399816a497f3a19dcc8428146 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 16 Jan 2021 08:15:14 +0100 Subject: [PATCH 0032/2059] Less log for omr-tracker-gre --- omr-tracker/files/bin/omr-tracker-gre | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker-gre b/omr-tracker/files/bin/omr-tracker-gre index b169d21d8..89041bbc4 100755 --- a/omr-tracker/files/bin/omr-tracker-gre +++ b/omr-tracker/files/bin/omr-tracker-gre @@ -14,7 +14,7 @@ _ping_server() { -w "$OMR_TRACKER_TIMEOUT" \ -c 1 \ -q \ - "${host}" + "${host}" 2>/dev/null ) && echo "$ret" | grep -sq " 0% packet loss" && { server_ping=true } From 34cf70ae30447b6c3ddbf3c5c9e7fa07e32931a2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 16 Jan 2021 08:15:54 +0100 Subject: [PATCH 0033/2059] Add system upgrade via interface --- luci-app-sysupgrade/Makefile | 11 + .../luasrc/view/sysupgrade.htm | 123 ++++++ .../po/templates/attendedsysupgrade.pot | 11 + .../root/etc/init.d/sysupgrade | 20 + .../root/etc/uci-defaults/40_luci-sysupgrade | 20 + .../luci/menu.d/luci-app-sysupgrade.json | 13 + .../root/usr/share/rpcd/acl.d/sysupgrade.json | 34 ++ .../www/luci-static/resources/sysupgrade.js | 386 ++++++++++++++++++ openmptcprouter-full/Makefile | 2 +- 9 files changed, 619 insertions(+), 1 deletion(-) create mode 100644 luci-app-sysupgrade/Makefile create mode 100644 luci-app-sysupgrade/luasrc/view/sysupgrade.htm create mode 100644 luci-app-sysupgrade/po/templates/attendedsysupgrade.pot create mode 100755 luci-app-sysupgrade/root/etc/init.d/sysupgrade create mode 100755 luci-app-sysupgrade/root/etc/uci-defaults/40_luci-sysupgrade create mode 100644 luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json create mode 100644 luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json create mode 100644 luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js diff --git a/luci-app-sysupgrade/Makefile b/luci-app-sysupgrade/Makefile new file mode 100644 index 000000000..3b5ccc6dc --- /dev/null +++ b/luci-app-sysupgrade/Makefile @@ -0,0 +1,11 @@ +# See /LICENSE for more information. +# This is free software, licensed under the GNU General Public License v2. + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI support for sysupgrades +LUCI_DEPENDS:=+luci-base +uhttpd-mod-ubus +rpcd +rpcd-mod-rpcsys +cgi-io + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-sysupgrade/luasrc/view/sysupgrade.htm b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm new file mode 100644 index 000000000..ac91611ad --- /dev/null +++ b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm @@ -0,0 +1,123 @@ +<% +-- all lua code provided by https://github.com/jow-/ +-- thank you very much! + + function apply_acls(filename, session) + local json = require "luci.jsonc" + local util = require "luci.util" + local fs = require "nixio.fs" + + local grants = { } + + local acl = json.parse(fs.readfile(filename)) + if type(acl) ~= "table" then + return + end + + local group, perms + for group, perms in pairs(acl) do + local perm, scopes + for perm, scopes in pairs(perms) do + if type(scopes) == "table" then + local scope, objects + for scope, objects in pairs(scopes) do + if type(objects) == "table" then + if not grants[scope] then + grants[scope] = { } + end + + if next(objects) == 1 then + local _, object + for _, object in ipairs(objects) do + if not grants[scope][object] then + grants[scope][object] = { } + end + table.insert(grants[scope][object], perm) + end + else + local object, funcs + for object, funcs in pairs(objects) do + if type(funcs) == "table" then + local _, func + for _, func in ipairs(funcs) do + if not grants[scope][object] then + grants[scope][object] = { } + end + table.insert(grants[scope][object], func) + end + end + end + end + end + end + end + end + end + + local _, scope, object, func + for scope, _ in pairs(grants) do + local objects = { } + for object, _ in pairs(_) do + for _, func in ipairs(_) do + table.insert(objects, { object, func }) + end + end + + util.ubus("session", "grant", { + ubus_rpc_session = session, + scope = scope, objects = objects + }) + end + end + + apply_acls("/usr/share/rpcd/acl.d/sysupgrade.json", luci.dispatcher.context.authsession) +%> +<%+header%> +

    <%:Sysupgrade%>

    +
    + Easily search and install new releases and package upgrades. Sysupgrade firmware are created on demand based on locally installed packages. +
    + + +

    + +

    +
    + +
    + + + +
    +
    + +
    +
    +
    + +
    + + +<%+footer%> diff --git a/luci-app-sysupgrade/po/templates/attendedsysupgrade.pot b/luci-app-sysupgrade/po/templates/attendedsysupgrade.pot new file mode 100644 index 000000000..c14f0951e --- /dev/null +++ b/luci-app-sysupgrade/po/templates/attendedsysupgrade.pot @@ -0,0 +1,11 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: applications/luci-app-attendedsysupgrade/luasrc/view/attendedsysupgrade.htm:76 +#: applications/luci-app-attendedsysupgrade/root/usr/share/luci/menu.d/luci-app-attendedsysupgrade.json:3 +msgid "Attended Sysupgrade" +msgstr "" + +#: applications/luci-app-attendedsysupgrade/root/usr/share/rpcd/acl.d/attendedsysupgrade.json:3 +msgid "attended sysupgrade via rpcd and luci" +msgstr "" diff --git a/luci-app-sysupgrade/root/etc/init.d/sysupgrade b/luci-app-sysupgrade/root/etc/init.d/sysupgrade new file mode 100755 index 000000000..86eccd349 --- /dev/null +++ b/luci-app-sysupgrade/root/etc/init.d/sysupgrade @@ -0,0 +1,20 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2020 Ycarus (Yannick Chabanois) +# Released under GPL 3. See LICENSE for the full terms. + +{ + START=90 + STOP=10 + USE_PROCD=1 +} + +start_service() +{ + if [ -f /etc/backup/installed_packages.txt ]; then + if [ "$(opkg -V0 update)" = "" ]; then + grep "\toverlay" /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg -V0 install + rm /etc/backup/installed_packages.txt + fi + fi +} + diff --git a/luci-app-sysupgrade/root/etc/uci-defaults/40_luci-sysupgrade b/luci-app-sysupgrade/root/etc/uci-defaults/40_luci-sysupgrade new file mode 100755 index 000000000..a5ef66fe8 --- /dev/null +++ b/luci-app-sysupgrade/root/etc/uci-defaults/40_luci-sysupgrade @@ -0,0 +1,20 @@ +#!/bin/sh + +/etc/init.d/uhttpd restart +/etc/init.d/rpcd reload + +[ -e /etc/config/sysupgrade ] && return 0 + +touch /etc/config/sysupgrade + +uci -q batch < + ubus_call("uci", "get", option, option["option"]) +} + +ubus_counter = 0; +ubus_closed = 0; + +function ubus_call(command, argument, params, variable) { + var request_data = {}; + request_data.jsonrpc = "2.0"; + request_data.id = ubus_counter; + request_data.method = "call"; + request_data.params = [data.ubus_rpc_session, command, argument, params] + var request_json = JSON.stringify(request_data) + ubus_counter++; + var request = new XMLHttpRequest(); + request.open("POST", ubus_url, true); + request.setRequestHeader("Content-type", "application/json"); + request.onload = function(event) { + if (request.status === 200) { + var response = JSON.parse(request.responseText) + if (!("error" in response) && "result" in response) { + if (response.result.length === 2) { + if (command === "uci") { + data[variable] = response.result[1].value + } else { + data[variable] = response.result[1][variable] + } + } + } else { + set_status("danger", "Ubus call failed:
    Request: " + request_json + "
    Response: " + JSON.stringify(response)) + } + ubus_closed++; + } + } + request.send(request_json); +} + +function set_status(type, message, loading, show_log) { + $("#status_box").className = "alert-message " + type; + var loading_image = ''; + if (loading) { + loading_image = 'Loading '; + } + if (data.buildlog_url && show_log) { + message += '

    Build log

    ' + } + $("#status_box").innerHTML = loading_image + message; + show("#status_box") +} + +function upgrade_check() { + var current_version = data.release.version.toLowerCase(); + var current_branch = current_version.split('.').slice(0, 2).join('.') + var candidates = [] + hide("#status_box"); + hide("#server_div"); + set_status("info", "Searching for upgrades", true); + fetch(data.url + "/api/versions") + .then(response => response.json()) + .then(response => { + var branches = response["branches"] + for (i in branches) { + // handle snapshots in a special way - as always + if (current_version == "snapshot" && branches[i]["latest"] == "snapshot") { + candidates.unshift(branches[i]) + break + } + + if (current_version == branches[i]["latest"]) { + break + } + if (current_branch != branches[i]["name"]) { + branches[i]["warn_branch_jump"] = true + } + candidates.unshift(branches[i]) + if (current_branch == branches[i]["name"]) { + // don't offer branches older than the current + break + } + } + + if (candidates.length > 0) { + var info_output = "

    New release " + candidates[0].latest + " available

    " + info_output += "Installed version: " + data.release.version + + // tell server the currently installed version + request_dict.current_version = request_dict.version; + // tell server what version to install + request_dict.version = candidates[0].latest; + // tell server to diff the requested packages with the default packages + // this allows to not automatically re-install default packages which + // where dropped in later releases + request_dict.diff_packages = true; + + set_status("success", info_output) + + if (data.advanced_mode == 1) { + show("#edit_button"); + } + var upgrade_button = $("#upgrade_button") + upgrade_button.value = "Request firmware"; + upgrade_button.style.display = "block"; + upgrade_button.disabled = false; + upgrade_button.onclick = upgrade_request; + + } else { + set_status("success", "No upgrades available") + + } + }); + +} + +function upgrade_request() { + // Request firmware using the following parameters + // distro, version, target, board_name, packages + $("#upgrade_button").disabled = true; + hide("#edit_packages"); + hide("#edit_button"); + hide("#keep_container"); + + // add board info to let server determine profile + request_dict.target = data.release.target + request_dict.profile = data.board_name + request_dict.rootfs = data.format + + if (data.edit_packages == true) { + request_dict.packages = $("#edit_packages").value.split("\n") + } else { + request_dict.packages = Object.keys(data.packages); + } + server_request() +} + +function upgrade_request_callback(response) { + var sysupgrade_file = ""; + console.log(response) + for (i in response.images) { + if (response.images[i].type == "sysupgrade") { + sysupgrade_file = response.images[i].name; + } + } + if (sysupgrade_file != "") { + data.sysupgrade_url = data.url + '/release/' + response.bin_dir + '/' + sysupgrade_file + var info_output = '

    Firmware created

    Created file: ' + sysupgrade_file + '

    ' + set_status("success", info_output, false, true); + + show("#keep_container"); + var upgrade_button = $("#upgrade_button") + upgrade_button.disabled = false; + upgrade_button.style.display = "block"; + upgrade_button.value = "Flash firmware"; + upgrade_button.onclick = download_image; + } else { + set_status("danger", "Firmware build successfull but device not sysupgrade compatible!") + } +} + +function flash_image() { + // Flash image via rpc-sys upgrade_start + set_status("warning", "Flashing firmware. Don't unpower device", true) + ubus_call("rpc-sys", "upgrade_start", { + "keep": $("#keep").checked + }, 'message'); + ping_max = 3600; // in seconds + setTimeout(ping_ubus, 10000) +} + +function ping_ubus() { + // Tries to connect to ubus. If the connection fails the device is likely still rebooting. + // If more time than ping_max passes update may failed + if (ping_max > 0) { + ping_max--; + var request = new XMLHttpRequest(); + request.open("GET", ubus_url, true); + request.addEventListener('error', function(event) { + set_status("warning", "Rebooting device - please wait!", true); + setTimeout(ping_ubus, 5000) + }); + request.addEventListener('load', function(event) { + set_status("success", "Success! Please reload web interface"); + $("#upgrade_button").value = "Reload page"; + show("#upgrade_button"); + $("#upgrade_button").disabled = false; + $("#upgrade_button").onclick = function() { + location.reload(); + } + }); + request.send(); + } else { + set_status("danger", "Web interface could not reconnect to your device. Please reload web interface or check device manually") + } +} + +function upload_image(blob) { + // Uploads received blob data to the server using cgi-io + set_status("info", "Uploading firmware to device", true); + var request = new XMLHttpRequest(); + var form_data = new FormData(); + + form_data.append("sessionid", data.ubus_rpc_session) + form_data.append("filename", "/tmp/firmware.bin") + form_data.append("filemode", 755) // insecure? + form_data.append("filedata", blob) + + request.addEventListener('load', function(event) { + request_json = JSON.parse(request.responseText) + flash_image(); + }); + + request.addEventListener('error', function(event) { + set_status("danger", "Upload of firmware failed, please retry by reloading web interface") + }); + + request.open('POST', origin + '/cgi-bin/cgi-upload'); + request.send(form_data); +} + + +function download_image() { + // Download image from server once the url was received by upgrade_request + hide("#keep_container"); + hide("#upgrade_button"); + var download_request = new XMLHttpRequest(); + download_request.open("GET", data.sysupgrade_url); + download_request.responseType = "arraybuffer"; + + download_request.onload = function() { + if (this.status === 200) { + var blob = new Blob([download_request.response], { + type: "application/octet-stream" + }); + upload_image(blob) + } + }; + set_status("info", "Downloading firmware to web browser memory", true); + download_request.send(); +} + +function server_request() { + fetch(data.url + "/api/build", { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(request_dict) + }) + .then(response => { + switch (response.status) { + case 200: + response.json() + .then(response => { + upgrade_request_callback(response) + }); + break; + case 202: + set_status("info", "Processing request", true); + setTimeout(function() { + server_request() + }, 5000) + break; + case 400: // bad request + case 422: // bad package + case 500: // build failed + console.log('error (' + response.status + ')'); + response.json() + .then(response => { + if (response.buildlog) { + data.buildlog_url = data.url + '/' + response.bin_dir + '/buildlog.txt'; + } + set_status("danger", response.message); + }); + break; + } + }); +} + +request_dict = {} +document.onload = setup() diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index defb4d7b4..74968b5c8 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -80,7 +80,7 @@ MY_DEPENDS := \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 \ luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-wolfssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf \ - hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding + hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status # luci-proto-bonding luci-app-statistics luci-proto-gre # softethervpn5-client softethervpn5-server luci-app-nginx-ha From 995c2018c5770dc7d0cf27a67c4d59a3eb0e9975 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 18 Jan 2021 17:22:27 +0100 Subject: [PATCH 0034/2059] Fix IPv6 wan support --- .../luasrc/view/openmptcprouter/wanstatus.htm | 11 +++----- .../luasrc/view/openmptcprouter/wizard.htm | 27 +++++++++++++++++++ .../root/usr/libexec/rpcd/openmptcprouter | 10 +++---- .../share/omr/post-tracking.d/post-tracking | 21 ++++++++------- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 16caf5a59..cff1dbac6 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -231,9 +231,9 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm if ((mArray.openmptcprouter.wan_addr == mArray.openmptcprouter.service_addr || mArray.openmptcprouter.wan_addr == mArray.openmptcprouter.service_addr_ip) && mArray.openmptcprouter.wan_addr != "") { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr); - } else if ((mArray.openmptcprouter.wan_addr6 == mArray.openmptcprouter.service_addr || mArray.openmptcprouter.wan_addr6 == mArray.openmptcprouter.service_addr_ip) && mArray.openmptcprouter.wan_addr6 != "") + } else if ((mArray.openmptcprouter.wan_addr6 == mArray.openmptcprouter.service_addr || mArray.openmptcprouter.wan_addr6 == mArray.openmptcprouter.service_addr_ip6) && mArray.openmptcprouter.wan_addr6 != "") { - var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_6addr); + var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr6); } else if (mArray.openmptcprouter.wan_addr != "" && mArray.openmptcprouter.service_addr == "127.0.0.1") { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr); @@ -285,10 +285,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm } else if (mArray.openmptcprouter.v2ray_enabled == true && mArray.openmptcprouter.ss_addr == "" && mArray.openmptcprouter.external_check == true) { statusMessage += '<%:Can\'t get public IP address from V2Ray%>' + '
    '; - } else if (mArray.openmptcprouter.wan_addr == "" && mArray.openmptcprouter.wan_addr6 !== "" && mArray.openmptcprouter.external_check == true) - { - statusMessage += '<%:No WAN IP address detected in less than 1 second%>' + '
    '; - } else if (mArray.openmptcprouter.wan_addr6 == "" && mArray.openmptcprouter.wan_addr !== "" && mArray.openmptcprouter.external_check == true) + } else if (mArray.openmptcprouter.wan_addr == "" && mArray.openmptcprouter.wan_addr6 == "" && mArray.openmptcprouter.external_check == true) { statusMessage += '<%:No WAN IP address detected in less than 1 second%>' + '
    '; } @@ -480,7 +477,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { content += String.format('%s %s
    ','<%:wan address:%>', wanip); } - if(wanip6 !== '') + if(wanip6 !== '' && gateway6 != '') { content += String.format('%s %s
    ','<%:wan ipv6 address:%>', wanip6); } diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index da0649831..e213c660c 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -576,6 +576,33 @@
    + <% + ipv6list = uci:get_list("network",ifname,"ip6addr") + for key, value in pairs(ipv6list) do + %> +
    + +
    + +
    +
    + <%:Set an IP in the same network as the modem%> +
    +
    +
    + <% + end + %> +
    + +
    + " data-type="ip6addr"> +
    +
    + <%:Set here IP of the modem%> +
    +
    +
    diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index bb9700d29..f8d83797c 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -788,18 +788,18 @@ function interfaces_status() end if uci:get("openmptcprouter","settings","external_check") ~= "0" and mArray.openmptcprouter["dns"] == true then - if mArray.openmptcprouter["service_addr_ip"] ~= "" then + if mArray.openmptcprouter["service_addr_ip"] ~= "" and mArray.openmptcprouter["service_addr_ip"] ~= nil then mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("curl -4 -s -m " .. timeout .. " " .. check_ipv4_website)) if mArray.openmptcprouter["wan_addr"] == "" then mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("dig -4 TXT +timeout=" .. timeout .. " +tries=1 +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'\"' '{print $2}'")) end end - if mArray.openmptcprouter["ipv6"] == "enabled" or mArray.openmptcprouter["service_addr_ip6"] ~= "" then + if mArray.openmptcprouter["ipv6"] == "enabled" or ( mArray.openmptcprouter["service_addr_ip6"] ~= "" and mArray.openmptcprouter["service_addr_ip6"] ~= nil) then mArray.openmptcprouter["wan_addr6"] = uci:get("openmptcprouter","omr","public_detected_ipv6") or "" if mArray.openmptcprouter["wan_addr6"] == "" then mArray.openmptcprouter["wan_addr6"] = ut.trim(sys.exec("curl -6 -s -m " .. timeout .. " " .. check_ipv6_website)) - if mArray.openmptcprouter["wan_addr"] == "" then - mArray.openmptcprouter["wan_addr"] = ut.trim(sys.exec("dig -6 TXT +timeout=" .. timeout .. " +tries=1 +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'\"' '{print $2}'")) + if mArray.openmptcprouter["wan_addr6"] == "" then + mArray.openmptcprouter["wan_addr6"] = ut.trim(sys.exec("dig -6 TXT +timeout=" .. timeout .. " +tries=1 +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'\"' '{print $2}'")) end end end @@ -839,7 +839,7 @@ function interfaces_status() ucic:foreach("openmptcprouter", "server", function(s) local serverip = uci:get("openmptcprouter",s[".name"],"ip") or "" local master = uci:get("openmptcprouter",s[".name"],"master") or "1" - if serverip ~= "" and (master == "1" or mArray.openmptcprouter["wan_addr"] == serverip) then + if serverip ~= "" and (master == "1" or mArray.openmptcprouter["wan_addr"] == serverip or mArray.openmptcprouter["wan_addr6"] == serverip) then mArray.openmptcprouter["vps_omr_version"] = uci:get("openmptcprouter", s[".name"], "omr_version") or "" mArray.openmptcprouter["vps_kernel"] = uci:get("openmptcprouter",s[".name"],"kernel") or "" mArray.openmptcprouter["vps_machine"] = uci:get("openmptcprouter",s[".name"],"machine") or "" diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index ca23f14cd..77446d653 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -58,7 +58,7 @@ set_route6() { if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.${INTERFACE}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi - if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then + if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep ':')" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" [ "$SETDEFAULT" = "yes" ] && ip -6 route replace default scope global nexthop via $interface_gw dev $interface_if ip -6 route replace default via $interface_gw dev $interface_if table 991337 && SETROUTE=true @@ -697,7 +697,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") - elif [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.mtu)" ]; then + elif [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]; then if [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ]; then local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) #local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 8.8.8.8) @@ -866,7 +866,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi gtudpst="up" [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" - if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ] && [ "$OMR_TRACKER_DEVICE_IP" != "" ]; then + if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 @@ -881,7 +881,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi fi fi - if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6)" = "" ] && [ "$OMR_TRACKER_DEVICE_IP6" != "" ]; then + if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6)" = "" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 @@ -899,7 +899,10 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then # if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp set | grep 'kxtimeout 7d')" = "" ]; then # glorytun-udp set dev tun0 kxtimeout 7d > /dev/null 2>&1 # fi - [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set pref 125 > /dev/null 2>&1 + [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && { + [ -n "$OMR_TRACKER_DEVICE_IP" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set pref 125 > /dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE_IP6" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set pref 125 > /dev/null 2>&1 + } fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { @@ -966,7 +969,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( local serverip=$(uci -q get shadowsocks-libev.sss0.server) [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" - [ -n "$omrtracebox" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" + [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } [ -n "$ipaddr" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ipaddr" [ -n "$OMR_TRACKER_LATENCY" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" @@ -980,7 +983,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 } - else + elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) [ -n "$mtu" ] && { @@ -1018,7 +1021,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( local serverip=$(uci -q get shadowsocks-libev.sss0.server) [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" - [ -n "$omrtracebox" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" + [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } [ -n "$ipaddr" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip6="$ip6addr" [ -n "$OMR_TRACKER_LATENCY" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" @@ -1032,7 +1035,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 } - else + elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) [ -n "$mtu" ] && { From 00f8830d44dbf73d20eaebf8be97ae973539e267 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 19 Jan 2021 14:06:45 +0100 Subject: [PATCH 0035/2059] Fix forward and bypass in case of multiples IPs --- .../files/shadowsocks-libev.init | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 41e48aa4a..c0590eb35 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -225,6 +225,26 @@ ss_rules() { src_ips_bypass6="$(echo "$src_ips_bypass" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" src_ips_forward6="$(echo "$src_ips_forward" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" src_ips_checkdst6="$(echo "$src_ips_checkdst" | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}' | sort -u)" + [ -z "$dst_ips_bypass4" ] && [ -z "$dst_ips_bypass6" ] && { + dst_ips_bypass4="$dst_ips_bypass" + dst_ips_bypass6="$dst_ips_bypass" + } + [ -z "$dst_ips_forward4" ] && [ -z "$dst_ips_forward6" ] && { + dst_ips_forward4="$dst_ips_forward" + dst_ips_forward6="$dst_ips_forward" + } + [ -z "$src_ips_bypass4" ] && [ -z "$src_ips_bypass6" ] && { + src_ips_bypass4="$src_ips_bypass" + src_ips_bypass6="$src_ips_bypass" + } + [ -z "$src_ips_forward4" ] && [ -z "$src_ips_forward6" ] && { + src_ips_forward4="$src_ips_forward" + src_ips_forward6="$src_ips_forward" + } + [ -z "$src_ips_checkdst4" ] && [ -z "$src_ips_checkdst6" ] && { + src_ips_checkdst4="$src_ips_checkdst" + src_ips_checkdst6="$src_ips_checkdst" + } [ "$dst_forward_recentrst" = 0 ] || args="$args --dst-forward-recentrst" ss_rules_call From d29d25b95a25cd5232d0372f94451d279b03e037 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Jan 2021 16:39:16 +0100 Subject: [PATCH 0036/2059] Update wizard for WAN IPv6 support --- .../root/etc/init.d/omr-bypass | 12 +++---- .../luasrc/controller/openmptcprouter.lua | 9 +++++ .../luasrc/view/openmptcprouter/wizard.htm | 33 +++++++++++++++++-- .../root/usr/libexec/rpcd/openmptcprouter | 2 ++ 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 8c1bf2aeb..592d875ac 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -374,7 +374,7 @@ _bypass_proto() { _intf_rule_ss_rules() { rule_name=$1 [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables --wait=40 -t nat -L -n | grep ssr | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep ssr | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -394,7 +394,7 @@ _intf_rule_ss_rules() { COMMIT EOF fi - if [ "$(ip6tables --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables --wait=40 -t nat -L -n | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then + if [ "$(ip6tables --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables-save | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count @@ -413,7 +413,7 @@ _intf_rule_v2ray_rules() { #rule_name=$1 #[ "$rule_name" = "ss_rules" ] && rule_name="def" rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables --wait=40 -t nat -L -n | grep v2r | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep v2r | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -426,14 +426,14 @@ _intf_rule_v2ray_rules() { EOF fi if [ "$disableipv6" = "0" ]; then - if [ "$(ip6tables --wait=40 -t mangle -L -n | grep omr6_dst_bypass_$intf)" = "" ]; then + if [ "$(ip6tables-save | grep omr-bypass6 | grep omr6_dst_bypass_$intf)" = "" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle -I omr-bypass6 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count COMMIT EOF fi - if [ "$(ip6tables --wait=40 -t nat -L -n | grep v2r6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables --wait=40 -t nat -L -n | grep v2r6 | grep omr6_dst_bypass_$intf)" = "" ]; then + if [ "$(ip6tables --wait=40 -t nat -L -n | grep v2r6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables-save | grep v2r6 | grep omr6_dst_bypass_$intf)" = "" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF *nat -I v2r6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count @@ -487,7 +487,7 @@ _intf_rule() { ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count > /dev/null 2>&1 fi } - if [ "$(iptables --wait=40 -t mangle -L -n | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables-save | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *mangle -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 23d5fc5f7..f60c1c82d 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -223,8 +223,10 @@ function wizard_add() local device_qmi = luci.http.formvalue("cbid.network.%s.device.qmi" % intf) or "" local device_modemmanager = luci.http.formvalue("cbid.network.%s.device.modemmanager" % intf) or "" local ipaddr = luci.http.formvalue("cbid.network.%s.ipaddr" % intf) or "" + local ip6addr = luci.http.formvalue("cbid.network.%s.ip6addr" % intf) or "" local netmask = luci.http.formvalue("cbid.network.%s.netmask" % intf) or "" local gateway = luci.http.formvalue("cbid.network.%s.gateway" % intf) or "" + local ip6gw = luci.http.formvalue("cbid.network.%s.ip6gw" % intf) or "" local apn = luci.http.formvalue("cbid.network.%s.apn" % intf) or "" local pincode = luci.http.formvalue("cbid.network.%s.pincode" % intf) or "" local delay = luci.http.formvalue("cbid.network.%s.delay" % intf) or "" @@ -281,6 +283,13 @@ function wizard_add() ucic:set("network",intf,"netmask","") ucic:set("network",intf,"gateway","") end + if ip6addr ~= "" then + ucic:set("network",intf,"ip6addr",ip6addr) + ucic:set("network",intf,"ip6gw",ip6gw) + else + ucic:set("network",intf,"ip6addr","") + ucic:set("network",intf,"ip6gw","") + end ucic:delete("openmptcprouter",intf,"lc") ucic:save("openmptcprouter") diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index e213c660c..f7e5e3c7b 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -147,7 +147,7 @@
    - checked<% end %> /> + checked<% end %> />
    <%:You should disable IPv6 here if server doesn't provide IPv6.%> @@ -580,7 +580,7 @@ ipv6list = uci:get_list("network",ifname,"ip6addr") for key, value in pairs(ipv6list) do %> -
    +
    @@ -592,8 +592,9 @@
    <% end + if ipv6list ~= nil and ipv6list ~= "" then %> -
    +
    " data-type="ip6addr"> @@ -603,6 +604,32 @@
    + <% + else + %> +
    + +
    + +
    +
    + <%:Set an IP in the same network as the modem%> +
    +
    +
    +
    + +
    + " data-type="ip6addr"> +
    +
    + <%:Set here IP of the modem%> +
    +
    +
    + <% + end + %>
    diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index f8d83797c..1a11148c7 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -984,6 +984,8 @@ function interfaces_status() end elseif uci:get("openmptcprouter","settings","vpn") == "none" then mArray.openmptcprouter["tun_service"] = true + mArray.openmptcprouter["tun_state"] = "NONE" + mArray.openmptcprouter["tun6_state"] = "NONE" end mArray.openmptcprouter["multi_vpn"] = false From 6fbc5eed463c736c764f3b9e4ca02b6a95bed3a2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Jan 2021 16:39:38 +0100 Subject: [PATCH 0037/2059] Doesn't add disabled ss-redir in firewall --- shadowsocks-libev/files/shadowsocks-libev.init | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index c0590eb35..7c3056747 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -146,7 +146,8 @@ ss_rules_cb() { ss_redir_ports() { port=$(uci -q get shadowsocks-libev.$1.local_port) server=$(uci -q get shadowsocks-libev.$1.server) - if [ "$server" = "$2" ] || [ "$2" = "" ]; then + disabled=$(uci -q get shadowsocks-libev.$1.disabled) + if [ "$disabled" != "1" ] && ([ "$server" = "$2" ] || [ "$2" = "" ]); then if [ "$port" -lt "$min_ss_redir_ports" ]; then min_ss_redir_ports=$port fi From b350af4207a0e2ed7107126cc13a886da8389353 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Jan 2021 16:39:58 +0100 Subject: [PATCH 0038/2059] Fix mail to alert --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 77446d653..71dd7f0ac 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -598,9 +598,9 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then OMR_SYSNAME="$(uci -q get system.@system[0].hostname)" if [ "$(uci -q get omr-tracker.defaults.mail_down_subject)" != "" ] && [ "$(uci -q get omr-tracker.defaults.mail_down_message)" != "" ]; then mail_subject="$(uci -q get omr-tracker.defaults.mail_down_subject)" - mail_subject=`echo $mail_subject | sed -i -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + mail_subject=`echo $mail_subject | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` mail_message="$(uci -q get omr-tracker.defaults.mail_down_message)" - mail_message=`echo $mail_message | sed -i -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + mail_message=`echo $mail_message | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` echo -e "Subject: ${mail_subject}\n\n${mail_message}" | sendmail $(uci -q get mail.default.to) else echo -e "Subject: $OMR_SYSNAME: $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) is down\n\nConnection failure of $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) detected. The reason is \"$OMR_TRACKER_STATUS_MSG\"." | sendmail $(uci -q get mail.default.to) @@ -740,9 +740,9 @@ if [ "$OMR_TRACKER_PREV_STATUS" != "" ] && [ "$OMR_TRACKER_PREV_STATUS" != "$OMR OMR_SYSNAME="$(uci -q get system.@system[0].hostname)" if [ "$(uci -q get omr-tracker.defaults.mail_up_subject)" != "" ] && [ "$(uci -q get omr-tracker.defaults.mail_up_message)" != "" ]; then mail_subject="$(uci -q get omr-tracker.defaults.mail_up_subject)" - mail_subject=`echo $mail_subject | sed -i -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + mail_subject=`echo $mail_subject | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` mail_message="$(uci -q get omr-tracker.defaults.mail_up_message)" - mail_message=`echo $mail_message | sed -i -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + mail_message=`echo $mail_message | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` echo -e "Subject: ${mail_subject}\n\n${mail_message}" | sendmail $(uci -q get mail.default.to) else echo -e "Subject: $OMR_SYSNAME: $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) is up\n\nDetected that connection $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) is up again." | sendmail $(uci -q get mail.default.to) From bd954b3f78d52155428db2f448ce6376493ec3f1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 11:27:28 +0100 Subject: [PATCH 0039/2059] Fix WAN IPv6 support if WAN IPv4 is also available --- .../share/omr/post-tracking.d/post-tracking | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 71dd7f0ac..9c3a19fb0 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -210,14 +210,14 @@ set_routes_intf6() { weight=1 fi if [ "$multipath_config_route" = "backup" ]; then - nbintfb=$((nbintfb+1)) + nbintfb6=$((nbintfb6+1)) if [ -z "$routesintfbackup6" ]; then routesintfbackup6="nexthop via $interface_gw dev $interface_if weight $weight" else routesintfbackup6="$routesintfbackup6 nexthop via $interface_gw dev $interface_if weight $weight" fi else - nbintf=$((nbintf+1)) + nbintf6=$((nbintf6+1)) if [ -z "$routesintf6" ]; then routesintf6="nexthop via $interface_gw dev $interface_if weight $weight" else @@ -304,10 +304,10 @@ set_route_balancing6() { weight=1 fi if [ "$multipath_config_route" = "backup" ]; then - nbintfb=$((nbintfb+1)) + nbintfb6=$((nbintfb6+1)) routesbalancingbackup6="$routesbalancingbackup6 nexthop via $interface_gw dev $interface_if weight $weight" else - nbintf=$((nbintf+1)) + nbintf6=$((nbintf6+1)) routesbalancing6="$routesbalancing6 nexthop via $interface_gw dev $interface_if weight $weight" fi fi @@ -369,13 +369,13 @@ set_server_all_routes6() { if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then routesintf="" routesintfbackup="" - nbintf=0 - nbintfb=0 + nbintf6=0 + nbintfb6=0 config_load network config_foreach set_routes_intf interface uintf="$(echo $routesintf | awk '{print $5}')" uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then + if [ -n "$routesintf" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip -6 r del $serverip done @@ -383,8 +383,8 @@ set_server_all_routes6() { ip -6 route replace $serverip scope global $routesintf [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" fi - if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" + if [ -n "$routesintfbackup" ] && ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb6" = "1" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb6 $OMR_TRACKER_DEVICE" ip -6 route replace $serverip scope global metric 999 $routesintfbackup fi fi @@ -796,6 +796,7 @@ if [ "$multipath_config" = "master" ]; then routesbalancing="" routesbalancingbackup="" nbintf=0 + nbintf6=0 config_load network config_foreach set_route_balancing interface config_foreach set_route_balancing6 interface @@ -806,7 +807,7 @@ if [ "$multipath_config" = "master" ]; then } } [ -n "$routesbalancing6" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" ip -6 route replace default scope global metric 1 $routesbalancing6 } @@ -818,7 +819,7 @@ if [ "$multipath_config" = "master" ]; then } } [ -n "$routesbalancingbackup6" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { _log "Set backup ip -6 route replace default scope global $routesbalancingbackup6" ip -6 route replace default scope global metric 999 $routesbalancingbackup6 } From a5ecab5e76a6a237209db87bd0655b9b7423a496 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 11:28:29 +0100 Subject: [PATCH 0040/2059] Remove message when device doesn't exist with multipath command --- mptcp/files/usr/bin/multipath | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 567ab99ee..f25706218 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -65,8 +65,8 @@ TYPE="$2" #FLAG_PATH=`find /sys/devices/ -path "*/net/$DEVICE/flags"` [ -d "/sys/class/net/$DEVICE/" ] || { - echo "Device '$DEVICE' can't found!" - echo "Use the hardware name like in ifconfig" + #echo "Device '$DEVICE' can't found!" + #echo "Use the hardware name like in ifconfig" exit 1 } From 842ab954d01c9fdad59471936f864d29c69abaad Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 11:28:53 +0100 Subject: [PATCH 0041/2059] Add glorytun-udp IPv6 wan support --- glorytun-udp/init | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/glorytun-udp/init b/glorytun-udp/init index 5e50d59df..e9f7caf7c 100755 --- a/glorytun-udp/init +++ b/glorytun-udp/init @@ -56,11 +56,15 @@ start_instance() { _log "starting ${PROG_NAME} ${1} instance $*" + if [ "$mode" = "to" ]; then + bind="bind from addr :: port 5000 to addr $host port $port" + else + bind="bind from addr $host port $port to addr :: port 5000" + fi procd_open_instance procd_set_param command ${PROG} \ - ${host:+bind ${mode} addr "$host"} \ - ${port:+port "$port"} \ + ${bind} \ ${dev:+dev "$dev"} \ keyfile /tmp/${PROG_NAME}-${1}.key \ persist From 1bd9c2d824dc8f3e556686a0bacea4262a08e9de Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 11:29:18 +0100 Subject: [PATCH 0042/2059] Fix OpenMPTCProuter status page CSS for IPv6 --- .../resources/openmptcprouter/css/wanstatus.css | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css index 2e90291e6..35ad4be96 100644 --- a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css +++ b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css @@ -71,7 +71,7 @@ ul { -moz-transition: all 0.5s; } .tree ul ul { - padding-left: 85px; + padding-left: 5px; position: relative; } .tree > ul > li:first-child { @@ -152,7 +152,7 @@ right connector from last child*/ top: 50%; left: 0; border-top: 2px solid black; - width: 85px; + width: 7px; height: 100%; } .tree li a { @@ -222,7 +222,7 @@ right connector from last child*/ width: 2px; /*height: 50%;*/ height: 55px; - left: 200px; + left: 240px; /* z-index: -10;*/ } /*Time for some hover effects*/ @@ -243,9 +243,9 @@ Thanks :)*/ .network-node { position: relative; background-color: #f3f3f3; - padding: 12px; - width: 400px; - max-width: 400px; + padding: 8px; + width: 480px; + max-width: 480px; box-sizing: border-box; min-height: 170px; } @@ -282,7 +282,7 @@ Thanks :)*/ .network-node .info { position: relative; float: right; - width: 250px; + width: 330px; text-align: left; font-size: 12px; color: #757575; @@ -319,7 +319,7 @@ Thanks :)*/ width:5px; border-right:2px dotted black; height:70px; - padding-right: 195px; + padding-right: 240px; } #omr { min-height: 190px; From ac0cd9dcd2fe9b421c6a64f9dc01101d5d7ba979 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 18:59:32 +0100 Subject: [PATCH 0043/2059] Add DHCPv6 support in wizard --- .../luasrc/view/openmptcprouter/wizard.htm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index f7e5e3c7b..569ce9b50 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -511,6 +511,7 @@ @@ -592,7 +593,7 @@
    <% end - if ipv6list ~= nil and ipv6list ~= "" then + if table.getn(ipv6list) ~= 0 then %>
    @@ -607,7 +608,7 @@ <% else %> -
    +
    @@ -617,7 +618,7 @@
    -
    +
    " data-type="ip6addr"> From 5bdb3ada85234717700031eec21ba3b596aa4fad Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 18:59:55 +0100 Subject: [PATCH 0044/2059] Add multi IPs server support --- .../share/omr/post-tracking.d/post-tracking | 498 ++++++++++-------- 1 file changed, 270 insertions(+), 228 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 9c3a19fb0..fb01fbdeb 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -68,66 +68,76 @@ set_route6() { set_server_default_route() { local server=$1 - local serverip multipath_config_route - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) - [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route via $OMR_TRACKER_DEVICE_GATEWAY" - if [ "$(ip r show $serverip | grep nexthop)" != "" ]; then - ip r delete $serverip >/dev/null 2>&1 + server_route() { + local serverip multipath_config_route + serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) + [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route via $OMR_TRACKER_DEVICE_GATEWAY" + if [ "$(ip r show $serverip | grep nexthop)" != "" ]; then + ip r delete $serverip >/dev/null 2>&1 + fi + ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric 1 fi - ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric 1 - fi + } + config_list_foreach $server ip server_route } set_server_default_route6() { local server=$1 - local serverip multipath_config_route - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) - [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route via $OMR_TRACKER_DEVICE_GATEWAY6" - if [ "$(ip -6 r show $serverip | grep nexthop)" != "" ]; then - ip -6 r delete $serverip >/dev/null 2>&1 + server_route() { + local serverip multipath_config_route + serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) + [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route via $OMR_TRACKER_DEVICE_GATEWAY6" + if [ "$(ip -6 r show $serverip | grep nexthop)" != "" ]; then + ip -6 r delete $serverip >/dev/null 2>&1 + fi + ip -6 route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric 1 fi - ip -6 route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric 1 - fi + } + config_list_foreach $server ip server_route } delete_server_default_route() { local server=$1 - local serverip - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - if [ "$serverip" != "" ] && [ "$(ip route show $serverip metric 1)" != "" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Delete server ($serverip) default route" - ip route del $serverip metric 1 >/dev/null 2>&1 - fi + delete_route() { + local serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + if [ "$serverip" != "" ] && [ "$(ip route show $serverip metric 1)" != "" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Delete server ($serverip) default route" + ip route del $serverip metric 1 >/dev/null 2>&1 + fi + } + config_list_foreach $server ip delete_route } delete_server_default_route6() { local server=$1 - local serverip - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - if [ "$serverip" != "" ] && [ "$(ip -6 route show $serverip metric 1)" != "" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Delete server ($serverip) default route" - ip -6 route del $serverip metric 1 >/dev/null 2>&1 - fi + delete_route() { + local serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + if [ "$serverip" != "" ] && [ "$(ip -6 route show $serverip metric 1)" != "" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Delete server ($serverip) default route" + ip -6 route del $serverip metric 1 >/dev/null 2>&1 + fi + } + config_list_foreach $server ip delete_route } set_routes_intf() { @@ -316,105 +326,114 @@ set_route_balancing6() { set_server_all_routes() { local server=$1 - local serverip multipath_config_route - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) - [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') - multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then - routesintf="" - routesintfbackup="" - nbintf=0 - nbintfb=0 - config_load network - config_foreach set_routes_intf interface - uintf="$(echo $routesintf | awk '{print $5}')" - uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show $serverip metric 0 | grep $uintf)" = "" ]); then - while [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do - ip r del $serverip - done - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf" - ip route replace $serverip scope global $routesintf - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" + server_route() { + local serverip multipath_config_route + serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then + routesintf="" + routesintfbackup="" + nbintf=0 + nbintfb=0 + config_load network + config_foreach set_routes_intf interface + uintf="$(echo $routesintf | awk '{print $5}')" + uintfb="$(echo $routesintfbackup | awk '{print $5}')" + if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show $serverip metric 0 | grep $uintf)" = "" ]); then + while [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do + ip r del $serverip + done + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf" + ip route replace $serverip scope global $routesintf + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" + fi + if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" + ip route replace $serverip scope global metric 999 $routesintfbackup + fi fi - if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" - ip route replace $serverip scope global metric 999 $routesintfbackup - fi - fi + } + config_list_foreach $server ip server_route } set_server_all_routes6() { local server=$1 - local serverip multipath_config_route - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) - [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') - multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then - routesintf="" - routesintfbackup="" - nbintf6=0 - nbintfb6=0 - config_load network - config_foreach set_routes_intf interface - uintf="$(echo $routesintf | awk '{print $5}')" - uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then - while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do - ip -6 r del $serverip - done - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf" - ip -6 route replace $serverip scope global $routesintf - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" + server_route() { + local serverip multipath_config_route + serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then + routesintf="" + routesintfbackup="" + nbintf6=0 + nbintfb6=0 + config_load network + config_foreach set_routes_intf interface + uintf="$(echo $routesintf | awk '{print $5}')" + uintfb="$(echo $routesintfbackup | awk '{print $5}')" + if [ -n "$routesintf" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then + while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do + ip -6 r del $serverip + done + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf" + ip -6 route replace $serverip scope global $routesintf + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" + fi + if [ -n "$routesintfbackup" ] && ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb6" = "1" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb6 $OMR_TRACKER_DEVICE" + ip -6 route replace $serverip scope global metric 999 $routesintfbackup + fi fi - if [ -n "$routesintfbackup" ] && ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb6" = "1" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb6 $OMR_TRACKER_DEVICE" - ip -6 route replace $serverip scope global metric 999 $routesintfbackup - fi - fi + } + config_list_foreach $server ip server_route } set_server_route() { local server=$1 - local serverip multipath_config_route - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - local metric=$2 - [ -z "$metric" ] && metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) - [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) - [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') - #multipath_current_config=$(multipath $interface_if | grep "deactivated") - interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") - #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" - ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric - fi + server_route() { + local serverip multipath_config_route + serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + local metric=$2 + [ -z "$metric" ] && metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) + [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + #multipath_current_config=$(multipath $interface_if | grep "deactivated") + interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") + #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" + ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric + fi + } + config_list_foreach $server ip server_route if [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric fi @@ -422,27 +441,30 @@ set_server_route() { set_server_route6() { local server=$1 - local serverip multipath_config_route - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" - config_get disabled $server disabled - [ "$disabled" = "1" ] && return - local metric=$2 - [ -z "$metric" ] && metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) - [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) - [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') - interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') - #multipath_current_config=$(multipath $interface_if | grep "deactivated") - interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") - #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" - ip -6 route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric - fi + server_route() { + local serverip multipath_config_route + serverip=$1 + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + config_get disabled $server disabled + [ "$disabled" = "1" ] && return + local metric=$2 + [ -z "$metric" ] && metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) + [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + #multipath_current_config=$(multipath $interface_if | grep "deactivated") + interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") + #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" + ip -6 route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric + fi + } + config_list_foreach $server ip server_route if [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric fi @@ -450,14 +472,16 @@ set_server_route6() { del_server_route() { local server=$1 - local serverip - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" - [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" - local metric - metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 - ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + remove_route() { + local serverip="$1" + [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" + [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + local metric + metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + } + config_list_foreach $server ip remove_route if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then ip route del default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 else @@ -467,14 +491,16 @@ del_server_route() { del_server_route6() { local server=$1 - local serverip - config_get serverip $server ip - [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" - [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" - local metric - metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 - ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + remove_route() { + local serverip="$1" + [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" + [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" + local metric + metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + } + config_list_foreach $server ip remove_route if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then ip -6 route del default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 else @@ -801,25 +827,25 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_route_balancing interface config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 0 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show default metric 0 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 0 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show default metric 0 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Set ip route replace default scope global $routesbalancing" ip route replace default scope global metric 0 $routesbalancing } } [ -n "$routesbalancing6" ] && { - ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" ip -6 route replace default scope global metric 1 $routesbalancing6 } } [ -n "$routesbalancingbackup" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Set backup ip route replace default scope global $routesbalancingbackup" ip route replace default scope global metric 999 $routesbalancingbackup } } [ -n "$routesbalancingbackup6" ] && { - ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ]) && { + ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { _log "Set backup ip -6 route replace default scope global $routesbalancingbackup6" ip -6 route replace default scope global metric 999 $routesbalancingbackup6 } @@ -967,39 +993,47 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( uci -q set openmptcprouter.latest_versions.lc=$(date +"%s") } fi - local serverip=$(uci -q get shadowsocks-libev.sss0.server) - [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { - omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" - [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" - } [ -n "$ipaddr" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ipaddr" [ -n "$OMR_TRACKER_LATENCY" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" [ -n "$asn" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.asn="$asn" } - if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then - if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then - mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) - [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu - ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + local omrtracebox + traceboxmtutest() { + omr_tracebox_mtu() { + local serverip=$1 + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { + omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" + [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } - elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then - [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { - local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) - [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu - ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 - } - } || { - local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 1.1.1.1) - [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu - ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 - } - } - fi - fi + if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then + if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then + mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { + local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + } || { + local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 1.1.1.1) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + } + fi + fi + } + config_list_foreach $1 ip omr_tracebox_mptcp + } + config_load openmptcprouter + config_foreach traceboxmtutest server uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") } @@ -1019,39 +1053,47 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( uci -q set openmptcprouter.latest_versions.lc=$(date +"%s") } fi - local serverip=$(uci -q get shadowsocks-libev.sss0.server) - [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { - omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" - [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" - } [ -n "$ipaddr" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip6="$ip6addr" [ -n "$OMR_TRACKER_LATENCY" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" [ -n "$asn" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.asn="$asn" } - if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then - if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then - mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) - [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu - ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + local omrtracebox + traceboxmtutest() { + omr_tracebox_mtu() { + local serverip=$1 + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { + omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" + [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } - elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then - [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { - local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) - [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu - ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 - } - } || { - local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 1.1.1.1) - [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu - ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 - } - } - fi - fi + if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then + if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then + mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { + local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + } || { + local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 1.1.1.1) + [ -n "$mtu" ] && { + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + } + } + fi + fi + } + config_list_foreach $1 ip omr_tracebox_mptcp + } + config_load openmptcprouter + config_foreach traceboxmtutest server uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") } From 75972e556ef8c04a6d165fe436e83f2ad5af3079 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 19:00:28 +0100 Subject: [PATCH 0045/2059] Add multi IPs server support in VPS contact script --- .../files/etc/init.d/openmptcprouter-vps | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 3c5ca2aaf..be3920ee1 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -17,29 +17,32 @@ _parse_result() { _login() { local username password auth - server="$(uci -q get openmptcprouter.${servername}.ip)" - [ -z "$server" ] && server="$(uci -q get shadowsocks-libev.sss0.server)" + #server="$(uci -q get openmptcprouter.${servername}.ip)" + #[ -z "$server" ] && server="$(uci -q get shadowsocks-libev.sss0.server)" username="$(uci -q get openmptcprouter.${servername}.username)" password="$(uci -q get openmptcprouter.${servername}.password)" serverport="$(uci -q get openmptcprouter.${servername}.port)" if [ -z "$token" ]; then - #auth=`curl --max-time 10 -s -k -H "Content-Type: application/json" -X POST -d '{"username":"'$username'","password":"'$password'"}' https://$server:$serverport/login` - resolve="$(resolveip $server)" - valid_ip6=$(valid_subnet6 $server) - if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then - auth=`curl --max-time 10 -s -k -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'username='$username'&password='$password https://$server:$serverport/token` - else - auth=`curl --max-time 10 -s -k -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'username='$username'&password='$password https://[$server]:$serverport/token` - fi - [ -z "$auth" ] && return - token="$(echo "$auth" | jsonfilter -q -e '@.access_token')" - uci -q set openmptcprouter.${servername}.token="$token" + login_on_server() { + server=$1 + #auth=`curl --max-time 10 -s -k -H "Content-Type: application/json" -X POST -d '{"username":"'$username'","password":"'$password'"}' https://$server:$serverport/login` + resolve="$(resolveip $server)" + valid_ip6=$(valid_subnet6 $server) + if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then + auth=`curl --max-time 10 -s -k -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'username='$username'&password='$password https://$server:$serverport/token` + else + auth=`curl --max-time 10 -s -k -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'username='$username'&password='$password https://[$server]:$serverport/token` + fi + [ -z "$auth" ] && return + token="$(echo "$auth" | jsonfilter -q -e '@.access_token')" + uci -q set openmptcprouter.${servername}.token="$token" + } + config_list_foreach ${servername} ip login_on_server fi } _ping_server() { - server="$(uci -q get openmptcprouter.${servername}.ip)" - [ -z "$server" ] && server="$(uci -q get shadowsocks-libev.sss0.server)" + server="$1" ret=$(ping -c 3 -w 3 -Q 184 $server 2>&1) && echo "$ret" | grep -sq "bytes from" && return false } @@ -1586,30 +1589,36 @@ _config_service() { _login [ -z "$token" ] && { reason="" - _ping_server - status=$? - if $(exit $status); then - reason="can ping server ${servername}" - else - reason="can't ping server ${servername}" - fi + test_ping() { + _ping_server $1 + status=$? + if $(exit $status); then + reason="can ping server ${servername} on $1" + else + reason="can't ping server ${servername} on $1" + fi + } + config_list_foreach "${servername}" ip test_ping port="$(uci -q get openmptcprouter.${servername}.port)" - server="$(uci -q get openmptcprouter.${servername}.ip)" - resolve="$(resolveip $server)" - valid_ip6=$(valid_subnet6 $server) - if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then - if [ "$(curl -k -m 3 https://${server}:${port}/)" = "" ]; then - reason="$reason, no server API answer" + api_test() { + server="$1" + resolve="$(resolveip $server)" + valid_ip6=$(valid_subnet6 $server) + if [ "$resolve" != "$server" ] || [ "$valid_ip6" != "ok" ]; then + if [ "$(curl -k -m 3 https://${server}:${port}/)" = "" ]; then + reason="$reason, no server API answer on $1" + else + reason="$reason, server API answer on $1" + fi else - reason="$reason, server API answer" + if [ "$(curl -k -m 3 https://[${server}]:${port}/)" = "" ]; then + reason="$reason, no server API answer on $1" + else + reason="$reason, server API answer on $1" + fi fi - else - if [ "$(curl -k -m 3 https://[${server}]:${port}/)" = "" ]; then - reason="$reason, no server API answer" - else - reason="$reason, server API answer" - fi - fi + } + config_list_foreach "${servername}" ip api_test if [ "$(uci -q get openmptcprouter.${servername}.username)" != "openmptcprouter" ]; then reason="$reason, custom username" fi From 24efb0ca347f67472382c42e52c484a976a0ac05 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 19:00:49 +0100 Subject: [PATCH 0046/2059] Update mptcpd --- mptcpd/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcpd/Makefile b/mptcpd/Makefile index 34242071d..a23a4a41b 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -8,10 +8,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mptcpd -PKG_VERSION:=0.4 +PKG_VERSION:=0.5.1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/intel/mptcpd/releases/download/v$(PKG_VERSION) -PKG_HASH:=459c45ba86ea574f1ad7a062a9914474ca650229b97375017bd46d0732f985ba +PKG_HASH:=0ee4418880f20a1a2eff5c54c26185a75092cb44cbabe0fa3f25a2c5886459e7 PKG_RELEASE:=1 PKG_MAINTAINER:=Ycarus (Yannick Chabanois) From 32e9f41e253d606b47efc92b97571bb3916346b2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 19:01:30 +0100 Subject: [PATCH 0047/2059] Add DHCPv6 wan firewall rules --- .../files/etc/uci-defaults/1980-omr-firewall | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 204cb92f3..db2fcf39e 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -164,6 +164,28 @@ if [ "$(uci -q get firewall.allowicmpipv6)" = "" ]; then EOF fi +if [ "$(uci -q get firewall.allowdhcpv6546)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set firewall.allowdhcpv6546=rule + set firewall.allowdhcpv6546.target='ACCEPT' + set firewall.allowdhcpv6546.src='wan' + set firewall.allowdhcpv6546.proto='udp' + set firewall.allowdhcpv6546.dest_port='547' + set firewall.allowdhcpv6546.name='Allow DHCPv6 (546-to-547)' + set firewall.allowdhcpv6546.family='ipv6' + set firewall.allowdhcpv6546.src_port='546' + set firewall.allowdhcpv6547=rule + set firewall.allowdhcpv6547.target='ACCEPT' + set firewall.allowdhcpv6547.src='wan' + set firewall.allowdhcpv6547.proto='udp' + set firewall.allowdhcpv6547.dest_port='546' + set firewall.allowdhcpv6547.name='Allow DHCPv6 (547-to-546)' + set firewall.allowdhcpv6547.family='ipv6' + set firewall.allowdhcpv6547.src_port='547' + commit firewall + EOF +fi + # Fix firewall config from some old config allintf=$(uci -q get firewall.@zone[1].network) uci -q del firewall.@zone[1].network From 2bd20232544821276c269e33fc5a2d9599678038 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Jan 2021 21:18:05 +0100 Subject: [PATCH 0048/2059] Fix wizard with new multiples IP by server feature --- .../luasrc/controller/openmptcprouter.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index f60c1c82d..7260b66a9 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -425,7 +425,8 @@ function wizard_add() local disablednb = 0 local servers = luci.http.formvaluetable("server") for server, _ in pairs(servers) do - local server_ip = luci.http.formvalue("%s.server_ip" % server) or "" + local server_ip = {} + server_ip[1] = luci.http.formvalue("%s.server_ip" % server) or "" local master = luci.http.formvalue("master") or "" -- OpenMPTCProuter VPS @@ -453,7 +454,7 @@ function wizard_add() ucic:set("openmptcprouter",server,"username",openmptcprouter_vps_username) ucic:set("openmptcprouter",server,"password",openmptcprouter_vps_key) ucic:set("openmptcprouter",server,"disabled",openmptcprouter_vps_disabled) - ucic:set("openmptcprouter",server,"ip",server_ip) + ucic:set_list("openmptcprouter",server,"ip",server_ip) ucic:set("openmptcprouter",server,"port","65500") ucic:save("openmptcprouter") end From f8f62ee77e9fe0e6f22b09305844deb10fd924bb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Jan 2021 10:40:57 +0100 Subject: [PATCH 0049/2059] Fix for multi IP on server --- .../luasrc/controller/openmptcprouter.lua | 2 +- .../luasrc/view/openmptcprouter/wizard.htm | 2 +- .../root/usr/libexec/rpcd/openmptcprouter | 177 +++++++++--------- .../share/omr/post-tracking.d/post-tracking | 4 +- 4 files changed, 94 insertions(+), 91 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 7260b66a9..29ec07420 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -447,7 +447,7 @@ function wizard_add() if openmptcprouter_vps_disabled == "1" then disablednb = disablednb + 1 end - if server_ip ~= "" then + if server_ip[1] ~= "" then serversnb = serversnb + 1 end ucic:set("openmptcprouter",server,"server") diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 569ce9b50..89da6bc85 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -57,7 +57,7 @@
    - " data-optional="false"> + " data-optional="false">
    <%:Server IP will be set for proxy and VPN%>
    diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 1a11148c7..9f88a0cc4 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -547,7 +547,7 @@ end function get_rootfs() local rootfs = {} - rootfs['format'] = ut.trim(sys.exec("mount | awk 'NR==1{print $5}'")) + rootfs['format'] = luci.util.trim(sys.exec("mount | awk 'NR==1{print $5}'")) return rootfs end @@ -837,102 +837,105 @@ function interfaces_status() mArray.openmptcprouter["vps_hostname"] = "Server" -- Get VPS info ucic:foreach("openmptcprouter", "server", function(s) - local serverip = uci:get("openmptcprouter",s[".name"],"ip") or "" + local serverips = uci:get("openmptcprouter",s[".name"],"ip") or { "" } local master = uci:get("openmptcprouter",s[".name"],"master") or "1" - if serverip ~= "" and (master == "1" or mArray.openmptcprouter["wan_addr"] == serverip or mArray.openmptcprouter["wan_addr6"] == serverip) then - mArray.openmptcprouter["vps_omr_version"] = uci:get("openmptcprouter", s[".name"], "omr_version") or "" - mArray.openmptcprouter["vps_kernel"] = uci:get("openmptcprouter",s[".name"],"kernel") or "" - mArray.openmptcprouter["vps_machine"] = uci:get("openmptcprouter",s[".name"],"machine") or "" - timeout = uci:get("openmptcprouter","settings","status_vps_timeout") or "2" - if uci:get("openmptcprouter",s[".name"],"admin_error") == "1" then - mArray.openmptcprouter["vps_admin_error"] = true - end - local adminport = uci:get("openmptcprouter",s[".name"],"port") or "65500" - local token = uci:get("openmptcprouter",s[".name"],"token") or "" - if token ~= "" then - local vpsinfo_json = "" - if mArray.openmptcprouter["service_addr_ip"] ~= "" then - vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://' .. serverip .. ':' .. adminport .. '/status') + for key, value in pairs(serverips) do + serverip = value + if serverip ~= "" and (master == "1" or mArray.openmptcprouter["wan_addr"] == serverip or mArray.openmptcprouter["wan_addr6"] == serverip) and mArray.openmptcprouter["vps_admin"] == false then + mArray.openmptcprouter["vps_omr_version"] = uci:get("openmptcprouter", s[".name"], "omr_version") or "" + mArray.openmptcprouter["vps_kernel"] = uci:get("openmptcprouter",s[".name"],"kernel") or "" + mArray.openmptcprouter["vps_machine"] = uci:get("openmptcprouter",s[".name"],"machine") or "" + timeout = uci:get("openmptcprouter","settings","status_vps_timeout") or "2" + if uci:get("openmptcprouter",s[".name"],"admin_error") == "1" then + mArray.openmptcprouter["vps_admin_error"] = true end - if mArray.openmptcprouter["service_addr_ip6"] ~= "" then - vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://[' .. serverip .. ']:' .. adminport .. '/status') - end - if vpsinfo_json ~= "" and vpsinfo_json ~= nil then - local status, vpsinfo = pcall(function() - return json.decode(vpsinfo_json) - end) - if status and vpsinfo.vps ~= nil then - mArray.openmptcprouter["vps_loadavg"] = vpsinfo.vps.loadavg or "" - mArray.openmptcprouter["vps_uptime"] = vpsinfo.vps.uptime or "" - mArray.openmptcprouter["vps_mptcp"] = vpsinfo.vps.mptcp.enabled or "" - mArray.openmptcprouter["vps_hostname"] = vpsinfo.vps.hostname or "" - mArray.openmptcprouter["vps_time"] = vpsinfo.vps.time or "" - if vpsinfo.vps.kernel ~= nil then - mArray.openmptcprouter["vps_kernel"] = vpsinfo.vps.kernel or "" - end - if vpsinfo.vps.omr_version ~= nil then - mArray.openmptcprouter["vps_omr_version"] = vpsinfo.vps.omr_version or "" - end - if vpsinfo.vps.time ~= "" then - if math.abs(os.time() - vpsinfo.vps.time) > 10 then - mArray.openmptcprouter["vps_time_accurate"] = false - else - mArray.openmptcprouter["vps_time_accurate"] = true + local adminport = uci:get("openmptcprouter",s[".name"],"port") or "65500" + local token = uci:get("openmptcprouter",s[".name"],"token") or "" + if token ~= "" then + local vpsinfo_json = "" + if mArray.openmptcprouter["service_addr_ip"] ~= "" then + vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://' .. serverip .. ':' .. adminport .. '/status') + end + if mArray.openmptcprouter["service_addr_ip6"] ~= "" then + vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://[' .. serverip .. ']:' .. adminport .. '/status') + end + if vpsinfo_json ~= "" and vpsinfo_json ~= nil then + local status, vpsinfo = pcall(function() + return json.decode(vpsinfo_json) + end) + if status and vpsinfo.vps ~= nil then + mArray.openmptcprouter["vps_loadavg"] = vpsinfo.vps.loadavg or "" + mArray.openmptcprouter["vps_uptime"] = vpsinfo.vps.uptime or "" + mArray.openmptcprouter["vps_mptcp"] = vpsinfo.vps.mptcp.enabled or "" + mArray.openmptcprouter["vps_hostname"] = vpsinfo.vps.hostname or "" + mArray.openmptcprouter["vps_time"] = vpsinfo.vps.time or "" + if vpsinfo.vps.kernel ~= nil then + mArray.openmptcprouter["vps_kernel"] = vpsinfo.vps.kernel or "" end + if vpsinfo.vps.omr_version ~= nil then + mArray.openmptcprouter["vps_omr_version"] = vpsinfo.vps.omr_version or "" + end + if vpsinfo.vps.time ~= "" then + if math.abs(os.time() - vpsinfo.vps.time) > 10 then + mArray.openmptcprouter["vps_time_accurate"] = false + else + mArray.openmptcprouter["vps_time_accurate"] = true + end + end + mArray.openmptcprouter["vps_admin"] = true + mArray.openmptcprouter["vps_status"] = "UP" + mArray.openmptcprouter["vps_admin_error_msg"] = "" + else + uci:set("openmptcprouter",s[".name"],"admin_error","1") + mArray.openmptcprouter["vps_admin_error"] = true + uci:delete("openmptcprouter",s[".name"],"token") + uci:save("openmptcprouter",s[".name"]) + uci:commit("openmptcprouter",s[".name"]) + mArray.openmptcprouter["vps_admin"] = false + mArray.openmptcprouter["vps_admin_error_msg"] = "Answer error" end - mArray.openmptcprouter["vps_admin"] = true - mArray.openmptcprouter["vps_status"] = "UP" - mArray.openmptcprouter["vps_admin_error_msg"] = "" + if status and vpsinfo.vpn ~= nil then + mArray.openmptcprouter["vpn_traffic_rx"] = vpsinfo.vpn.rx or "0" + mArray.openmptcprouter["vpn_traffic_tx"] = vpsinfo.vpn.tx or "0" + mArray.openmptcprouter["vpn_traffic"] = mArray.openmptcprouter["vpn_traffic_tx"] + mArray.openmptcprouter["vpn_traffic_rx"] + else + mArray.openmptcprouter["vpn_traffic_rx"] = "0" + mArray.openmptcprouter["vpn_traffic_tx"] = "0" + mArray.openmptcprouter["vpn_traffic"] = "0" + end + if status and vpsinfo.shadowsocks ~= nil then + mArray.openmptcprouter["ss_traffic"] = vpsinfo.shadowsocks.traffic or "0" + else + mArray.openmptcprouter["ss_traffic"] = "0" + end + if status and vpsinfo.v2ray ~= nil then + mArray.openmptcprouter["v2ray_traffic_rx"] = vpsinfo.v2ray.rx or "0" + mArray.openmptcprouter["v2ray_traffic_tx"] = vpsinfo.v2ray.tx or "0" + mArray.openmptcprouter["v2ray_traffic"] = mArray.openmptcprouter["v2ray_traffic_tx"] + mArray.openmptcprouter["v2ray_traffic_rx"] + else + mArray.openmptcprouter["v2ray_traffic_rx"] = "0" + mArray.openmptcprouter["v2ray_traffic_tx"] = "0" + mArray.openmptcprouter["v2ray_traffic"] = "0" + end + mArray.openmptcprouter["proxy_traffic"] = mArray.openmptcprouter["ss_traffic"] + mArray.openmptcprouter["v2ray_traffic"] + mArray.openmptcprouter["total_traffic"] = mArray.openmptcprouter["proxy_traffic"] + mArray.openmptcprouter["vpn_traffic"] else - uci:set("openmptcprouter",s[".name"],"admin_error","1") - mArray.openmptcprouter["vps_admin_error"] = true - uci:delete("openmptcprouter",s[".name"],"token") - uci:save("openmptcprouter",s[".name"]) - uci:commit("openmptcprouter",s[".name"]) mArray.openmptcprouter["vps_admin"] = false - mArray.openmptcprouter["vps_admin_error_msg"] = "Answer error" + mArray.openmptcprouter["vps_admin_error_msg"] = "No result" end - if status and vpsinfo.vpn ~= nil then - mArray.openmptcprouter["vpn_traffic_rx"] = vpsinfo.vpn.rx or "0" - mArray.openmptcprouter["vpn_traffic_tx"] = vpsinfo.vpn.tx or "0" - mArray.openmptcprouter["vpn_traffic"] = mArray.openmptcprouter["vpn_traffic_tx"] + mArray.openmptcprouter["vpn_traffic_rx"] - else - mArray.openmptcprouter["vpn_traffic_rx"] = "0" - mArray.openmptcprouter["vpn_traffic_tx"] = "0" - mArray.openmptcprouter["vpn_traffic"] = "0" - end - if status and vpsinfo.shadowsocks ~= nil then - mArray.openmptcprouter["ss_traffic"] = vpsinfo.shadowsocks.traffic or "0" - else - mArray.openmptcprouter["ss_traffic"] = "0" - end - if status and vpsinfo.v2ray ~= nil then - mArray.openmptcprouter["v2ray_traffic_rx"] = vpsinfo.v2ray.rx or "0" - mArray.openmptcprouter["v2ray_traffic_tx"] = vpsinfo.v2ray.tx or "0" - mArray.openmptcprouter["v2ray_traffic"] = mArray.openmptcprouter["v2ray_traffic_tx"] + mArray.openmptcprouter["v2ray_traffic_rx"] - else - mArray.openmptcprouter["v2ray_traffic_rx"] = "0" - mArray.openmptcprouter["v2ray_traffic_tx"] = "0" - mArray.openmptcprouter["v2ray_traffic"] = "0" - end - mArray.openmptcprouter["proxy_traffic"] = mArray.openmptcprouter["ss_traffic"] + mArray.openmptcprouter["v2ray_traffic"] - mArray.openmptcprouter["total_traffic"] = mArray.openmptcprouter["proxy_traffic"] + mArray.openmptcprouter["vpn_traffic"] else mArray.openmptcprouter["vps_admin"] = false - mArray.openmptcprouter["vps_admin_error_msg"] = "No result" + mArray.openmptcprouter["vps_admin_error_msg"] = "No token yet available" end - else - mArray.openmptcprouter["vps_admin"] = false - mArray.openmptcprouter["vps_admin_error_msg"] = "No token yet available" - end - if mArray.openmptcprouter["vps_admin"] == false then - if mArray.openmptcprouter["service_addr_ip"] ~= "" then - local vpstest = sys.exec('curl --max-time ' .. timeout .. ' -s -k https://' .. serverip .. ':' .. adminport .. '/') - elseif mArray.openmptcprouter["service_addr_ip6"] ~= "" then - local vpstest = sys.exec('curl --max-time ' .. timeout .. ' -s -k https://[' .. serverip .. ']:' .. adminport .. '/') - end - if vpstest == "" then - mArray.openmptcprouter["vps_admin_error_msg"] = mArray.openmptcprouter["vps_admin_error_msg"] .. " - No API script answer" + if mArray.openmptcprouter["vps_admin"] == false then + if mArray.openmptcprouter["service_addr_ip"] ~= "" then + local vpstest = sys.exec('curl --max-time ' .. timeout .. ' -s -k https://' .. serverip .. ':' .. adminport .. '/') + elseif mArray.openmptcprouter["service_addr_ip6"] ~= "" then + local vpstest = sys.exec('curl --max-time ' .. timeout .. ' -s -k https://[' .. serverip .. ']:' .. adminport .. '/') + end + if vpstest == "" then + mArray.openmptcprouter["vps_admin_error_msg"] = mArray.openmptcprouter["vps_admin_error_msg"] .. " - No API script answer" + end end end end diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index fb01fbdeb..a8ce3ed18 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1030,7 +1030,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( fi fi } - config_list_foreach $1 ip omr_tracebox_mptcp + config_list_foreach $1 ip omr_tracebox_mtu } config_load openmptcprouter config_foreach traceboxmtutest server @@ -1090,7 +1090,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( fi fi } - config_list_foreach $1 ip omr_tracebox_mptcp + config_list_foreach $1 ip omr_tracebox_mtu } config_load openmptcprouter config_foreach traceboxmtutest server From 16ab9a7722f31b8752e59a4c4da1374a31dd8fd5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Jan 2021 20:59:25 +0100 Subject: [PATCH 0050/2059] Fix v2ray proxy setting --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index be3920ee1..49d0b5f29 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1092,7 +1092,7 @@ _set_config_from_vps() { set shadowsocks-libev.sss0.disabled=0 commit shadowsocks-libev set v2ray.main.enabled=0 - commit shadowsocks-libev + commit v2ray set openmptcprouter.settings.shadowsocks_disable=0 commit openmptcprouter EOF @@ -1101,7 +1101,7 @@ _set_config_from_vps() { set shadowsocks-libev.sss0.disabled=1 commit shadowsocks-libev set v2ray.main.enabled=1 - commit shadowsocks-libev + commit v2ray set openmptcprouter.settings.shadowsocks_disable=1 commit openmptcprouter EOF @@ -1110,7 +1110,7 @@ _set_config_from_vps() { set shadowsocks-libev.sss0.disabled=1 commit shadowsocks-libev set v2ray.main.enabled=0 - commit shadowsocks-libev + commit v2ray set openmptcprouter.settings.shadowsocks_disable=1 commit openmptcprouter EOF From 087561e002aefdbc95833eca866b704c93ddec5d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Jan 2021 09:32:23 +0100 Subject: [PATCH 0051/2059] Update omr-tracker for multi IPs server --- omr-tracker/files/bin/omr-tracker-server | 139 +++++++++++++---------- omr-tracker/files/bin/omr-tracker-ss | 15 +-- omr-tracker/files/etc/init.d/omr-tracker | 57 +++++----- 3 files changed, 113 insertions(+), 98 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index e7c759b16..5bd212fdb 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -39,84 +39,103 @@ _check_server() { _check_master() { local name=$1 + local count=0 config_get master $1 master config_get ip $1 ip config_get port $1 port "65500" config_get disabled $1 disabled [ "$master" = "1" ] && [ -n "$ip" ] && [ "$disabled" != "1" ] && { - #_ping_server $ip - _check_server $ip $port - [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss0.server | tr -d '\n')" != "$ip" ] && { - logger -t "OMR-Tracker-Server" "Master server up, set it back" - logger -t "OMR-Tracker-Server" "$(uci -q get shadowsocks-libev.sss0.server | tr -d '\n') - $ip" - uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.sss0.server=$ip - commit shadowsocks-libev - set v2ray.omrout.s_vmess_address=$ip - set v2ray.omrout.s_vless_address=$ip - commit v2ray - set glorytun.vpn.host=$ip - commit glorytun - set dsvpn.vpn.host=$ip - commit dsvpn - set mlvpn.general.host=$ip - commit mlvpn - del openvpn.omr.remote - add_list openvpn.omr.remote=$ip - commit openvpn - EOF - /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null - /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null - /etc/init.d/v2ray restart >/dev/null 2>/dev/null - /etc/init.d/glorytun restart >/dev/null 2>/dev/null - /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null - /etc/init.d/mlvpn restart >/dev/null 2>/dev/null - /etc/init.d/openvpn restart >/dev/null 2>/dev/null - /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + set_ip() { + local ip=$1 + #_ping_server $ip + _check_server $ip $port + [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ] && { + logger -t "OMR-Tracker-Server" "Master server up, set it back" + logger -t "OMR-Tracker-Server" "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n') - $ip" + uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.sss${count}.server=$ip + commit shadowsocks-libev + EOF + if [ "$count" -eq "0" ]; then + uci -q batch <<-EOF >/dev/null + set v2ray.omrout.s_vmess_address=$ip + set v2ray.omrout.s_vless_address=$ip + commit v2ray + set glorytun.vpn.host=$ip + commit glorytun + set dsvpn.vpn.host=$ip + commit dsvpn + set mlvpn.general.host=$ip + commit mlvpn + del openvpn.omr.remote + add_list openvpn.omr.remote=$ip + commit openvpn + EOF + /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null + /etc/init.d/v2ray restart >/dev/null 2>/dev/null + /etc/init.d/glorytun restart >/dev/null 2>/dev/null + /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null + /etc/init.d/mlvpn restart >/dev/null 2>/dev/null + /etc/init.d/openvpn restart >/dev/null 2>/dev/null + /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + fi + /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null + } + count=$((count+1)) } + config_list_foreach $1 ip set_ip break } } _check_backup() { local name=$1 + local count=0 config_get backup $1 backup config_get ip $1 ip config_get port $1 port config_get disabled $1 disabled [ "$backup" = "1" ] && [ -n "$ip" ] && [ "$disabled" != "1" ] && { - #_ping_server $ip - _check_server $ip $port - [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss0.server | tr -d '\n')" = "$ip" ] && break - [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss0.server | tr -d '\n')" != "$ip" ] && { - logger -t "OMR-Tracker-Server" "Use backup server $1 ($ip)" - uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.sss0.server=$ip - commit shadowsocks-libev - set v2ray.omrout.s_vmess_address=$ip - set v2ray.omrout.s_vless_address=$ip - commit v2ray - set glorytun.vpn.host=$ip - commit glorytun - set dsvpn.vpn.host=$ip - commit dsvpn - set mlvpn.general.host=$ip - commit mlvpn - del openvpn.omr.remote - add_list openvpn.omr.remote=$ip - commit openvpn - EOF - /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null - /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null - /etc/init.d/v2ray restart >/dev/null 2>/dev/null - /etc/init.d/glorytun restart >/dev/null 2>/dev/null - /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null - /etc/init.d/mlvpn restart >/dev/null 2>/dev/null - /etc/init.d/openvpn restart >/dev/null 2>/dev/null - /etc/init.d/dsvpn restart >/dev/null 2>/dev/null - sleep $waittest - break + set_ip() { + #_ping_server $ip + _check_server $ip $port + [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" = "$ip" ] && break + [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ] && { + logger -t "OMR-Tracker-Server" "Use backup server $1 ($ip)" + uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.sss${count}.server=$ip + commit shadowsocks-libev + EOF + if [ "$count" -eq "0" ]; then + uci -q batch <<-EOF >/dev/null + set v2ray.omrout.s_vmess_address=$ip + set v2ray.omrout.s_vless_address=$ip + commit v2ray + set glorytun.vpn.host=$ip + commit glorytun + set dsvpn.vpn.host=$ip + commit dsvpn + set mlvpn.general.host=$ip + commit mlvpn + del openvpn.omr.remote + add_list openvpn.omr.remote=$ip + commit openvpn + EOF + /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null + /etc/init.d/v2ray restart >/dev/null 2>/dev/null + /etc/init.d/glorytun restart >/dev/null 2>/dev/null + /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null + /etc/init.d/mlvpn restart >/dev/null 2>/dev/null + /etc/init.d/openvpn restart >/dev/null 2>/dev/null + /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + fi + /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null + sleep $waittest + break + } + count=$((count+1)) } + config_list_foreach $1 ip set_ip } } diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index 525c4a979..e5a2e5ca8 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -49,6 +49,7 @@ retry=${OMR_TRACKER_TRIES:-4} proxy=${OMR_TRACKER_PROXY:-127.0.0.1:1111} hosts=${OMR_TRACKER_HOSTS:-1.1.1.1 1.0.0.1} wait_test=${OMR_TRACKER_WAIT_TEST:-0} +server=${OMR_TRACKER_SERVER:-sss0} nodns=0 @@ -65,9 +66,9 @@ while true; do } if [ "$(curl -s -I -w %{http_code} --socks5 ${proxy} --max-time ${timeout} $host -o /dev/null)" != "000" ]; then nocontact="" - [ "${last}" -ge "${retry}" ] || [ "$(uci -q get openmptcprouter.omr.shadowsocks)" = "" ] && { + [ "${last}" -ge "${retry}" ] || [ "$(uci -q get openmptcprouter.omr.ss_$[name})" = "" ] && { _log "Shadowsocks is up (can contact via http ${host})" - uci -q set openmptcprouter.omr.shadowsocks="up" + uci -q set openmptcprouter.omr.ss_${name}="up" uci -q commit openmptcprouter.omr } if [ -z "$(iptables -t nat -L -n | grep ss_rules)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then @@ -83,15 +84,15 @@ while true; do [ "${last}" -ge "${retry}" ] && { if [ -n "$(iptables -t nat -L -n | grep ssr)" ]; then _log "Shadowsocks is down (can't contact via http ${nocontact})" - uci -q set openmptcprouter.omr.shadowsocks="down" + uci -q set openmptcprouter.omr.ss_${name}="down" uci -q commit openmptcprouter.omr - /etc/init.d/shadowsocks-libev rules_down 2> /dev/null + [ "$(uci show openmptcprouter.omr | grep ss | grep up)" = "" ] && /etc/init.d/shadowsocks-libev rules_down 2> /dev/null _get_ip server_ping=false - server="$(uci -q get shadowsocks-libev.sss0.server)" - _ping_server $server + serverip="$(uci -q get shadowsocks-libev.${server}.server)" + _ping_server $serverip if [ "$server_ping" = false ]; then - _log "Server ($server) seems down, no answer to ping" + _log "Server $server ($serverip) seems down, no answer to ping" fi sleep $wait_test fi diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index d5965fe1f..fa4e4d265 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -132,48 +132,42 @@ _launch_gre_tracker() { _initialize_shadowsocks_tracker() { local redir_tcp server tracker_server - config_get redir_tcp ss_rules redir_tcp - config_get tracker_server "tracker" server - if [ "$redir_tcp" != "all" ]; then - config_get server $redir_tcp server - elif [ "$tracker_server" != "" ]; then - server=$tracker_server - else - server="sss0" - fi + server=$1 + #redir_tcp=$(uci -q get shadowsocks-libev.ss_rules.redir_tcp) + #config_get tracker_server ss_rules server config_get ss_disabled $server disabled 0 - [ -z "$tracker_server" ] && { + [ -z "$(uci -q get shadowsocks-libev.tracker_${server})" ] && [ "$ss_disabled" != "1" ] && { logger -t "omr-tracker" "Create ShadowSock tracker ss_local..." uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.tracker=ss_local - set shadowsocks-libev.tracker.server=$server - set shadowsocks-libev.tracker.local_address="127.0.0.1" - set shadowsocks-libev.tracker.local_port=1111 - set shadowsocks-libev.tracker.mode=tcp_and_udp - set shadowsocks-libev.tracker.timeout=600 - set shadowsocks-libev.tracker.fast_open=1 - set shadowsocks-libev.tracker.syslog=0 - set shadowsocks-libev.tracker.reuse_port=1 - set shadowsocks-libev.tracker.mptcp=1 - set shadowsocks-libev.tracker.verbose=0 - commit shadowsocks-libev - EOF - /etc/init.d/shadowsocks-libev restart - } - [ -n "$tracker_server" ] && [ "$server" = "$tracker_server" ] || { - logger -t "omr-tracker" "Set ShadowSock tracker to current server ($tracker_server -> $server)..." - uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.tracker.server=$server + set shadowsocks-libev.tracker_${server}=ss_local + set shadowsocks-libev.tracker_${server}.server=$server + set shadowsocks-libev.tracker_${server}.local_address="127.0.0.1" + set shadowsocks-libev.tracker_${server}.local_port=1111 + set shadowsocks-libev.tracker_${server}.mode=tcp_and_udp + set shadowsocks-libev.tracker_${server}.timeout=600 + set shadowsocks-libev.tracker_${server}.fast_open=1 + set shadowsocks-libev.tracker_${server}.syslog=0 + set shadowsocks-libev.tracker_${server}.reuse_port=1 + set shadowsocks-libev.tracker_${server}.mptcp=1 + set shadowsocks-libev.tracker_${server}.verbose=0 commit shadowsocks-libev EOF /etc/init.d/shadowsocks-libev restart } +# [ -n "$tracker_server" ] && [ "$server" = "$tracker_server" ] || { +# logger -t "omr-tracker" "Set ShadowSock tracker to current server ($tracker_server -> $server)..." +# uci -q batch <<-EOF >/dev/null +# set shadowsocks-libev.tracker.server=$server +# commit shadowsocks-libev +# EOF +# /etc/init.d/shadowsocks-libev restart +# } } _launch_shadowsocks_tracker() { local hosts timeout tries interval local_port enabled server wait_test - [ "$1" = "tracker" ] || return + [ "$(echo $1 | grep tracker)" != "" ] || return _validate_section "proxy" "proxy" @@ -194,6 +188,7 @@ _launch_shadowsocks_tracker() { procd_append_param env "OMR_TRACKER_INTERVAL=$interval" procd_append_param env "OMR_TRACKER_PROXY=127.0.0.1:$local_port" procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" + procd_append_param env "OMR_TRACKER_SERVER=$server" procd_set_param limits nofile="51200 51200" procd_set_param respawn 0 10 0 procd_set_param stderr 1 @@ -235,7 +230,7 @@ start_service() { local ss_disabled logger -t "omr-tracker" "Launching..." config_load shadowsocks-libev - _initialize_shadowsocks_tracker + config_foreach _initialize_shadowsocks_tracker server config_load network config_foreach _launch_tracker interface From c4cfdcda06ac422ef2d5898b16dc14a030633dd5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Jan 2021 09:33:02 +0100 Subject: [PATCH 0052/2059] Set some settings at startup --- .../root/etc/init.d/openmptcprouter | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index adde64a8f..44188939f 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -18,31 +18,12 @@ omr_intf_check() { omr_intf_set() { local device local ifname - local multipath - config_get multipath "$1" multipath config_get ifname "$1" ifname config_get device "$1" device - config_get proto "$1" proto config_get type "$1" type - config_get addlatency "$1" addlatency - [ -z "$addlatency" ] && addlatency=0 - devicename=$(echo "$device" | cut -d'/' -f3) [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') - if [ -n "$ifname" ]; then - if [ "$addlatency" = "0" ] && [ "$(tc qdisc show dev $ifname | grep delay)" != "" ]; then - tc qdisc del dev ${ifname} root netem - fi - if [ "$addlatency" != "0" ]; then - if [ "$(tc qdisc show dev $ifname | grep delay)" != "" ]; then - tc qdisc add dev ${ifname} root netem delay ${addlatency}ms - elif [ "$(tc qdisc show dev $ifname | awk '/delay/ { print $10 }' | sed 's/ms//')" != "$addlatency" ]; then - tc qdisc replace dev ${ifname} root netem delay ${addlatency}ms - fi - fi - fi - if [ "$type" != "macvlan" ] && [ -n "$ifname" ] && [ -f /sys/class/net/${ifname}/device/uevent ]; then devicepath=$(readlink -f /sys/class/net/${ifname}) if [ -n "$devicepath" ] && [ "$(echo ${devicepath} | grep virtual)" = "" ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" != "" ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PCI_SLOT_NAME)" = "" ]; then @@ -63,6 +44,15 @@ omr_intf_set() { } omr_set_settings() { + local device + local ifname + local multipath + config_get multipath "$1" multipath + config_get ifname "$1" ifname + config_get device "$1" device + config_get proto "$1" proto + config_get type "$1" type + config_get addlatency "$1" addlatency [ -z "$multipath" ] || [ "$multipath" = "off" ] && [ "$1" != "omrvpn" ] && [ "$1" != "glorytun" ] && return uci -q set openmptcprouter.$1=interface @@ -73,6 +63,25 @@ omr_set_settings() { else uci -q set network.$1.ipv6=1 fi + + [ -z "$addlatency" ] && addlatency=0 + devicename=$(echo "$device" | cut -d'/' -f3) + + [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + + if [ -n "$ifname" ]; then + if [ "$addlatency" = "0" ] && [ "$(tc qdisc show dev $ifname | grep delay)" != "" ]; then + tc qdisc del dev ${ifname} root netem + fi + if [ "$addlatency" != "0" ]; then + if [ "$(tc qdisc show dev $ifname | grep delay)" != "" ]; then + tc qdisc add dev ${ifname} root netem delay ${addlatency}ms + elif [ "$(tc qdisc show dev $ifname | awk '/delay/ { print $10 }' | sed 's/ms//')" != "$addlatency" ]; then + tc qdisc replace dev ${ifname} root netem delay ${addlatency}ms + fi + fi + fi + } start_service() { From 13eb40242c41ecd985480289f8c1f39339d4be61 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Jan 2021 10:08:54 +0100 Subject: [PATCH 0053/2059] Fix shadowsocks tracker --- omr-tracker/files/bin/omr-tracker-ss | 6 +++--- omr-tracker/files/etc/init.d/omr-tracker | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index e5a2e5ca8..9a7234c93 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -66,9 +66,9 @@ while true; do } if [ "$(curl -s -I -w %{http_code} --socks5 ${proxy} --max-time ${timeout} $host -o /dev/null)" != "000" ]; then nocontact="" - [ "${last}" -ge "${retry}" ] || [ "$(uci -q get openmptcprouter.omr.ss_$[name})" = "" ] && { + [ "${last}" -ge "${retry}" ] || [ "$(uci -q get openmptcprouter.omr.ss_${server})" = "" ] && { _log "Shadowsocks is up (can contact via http ${host})" - uci -q set openmptcprouter.omr.ss_${name}="up" + uci -q set openmptcprouter.omr.ss_${server}="up" uci -q commit openmptcprouter.omr } if [ -z "$(iptables -t nat -L -n | grep ss_rules)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then @@ -84,7 +84,7 @@ while true; do [ "${last}" -ge "${retry}" ] && { if [ -n "$(iptables -t nat -L -n | grep ssr)" ]; then _log "Shadowsocks is down (can't contact via http ${nocontact})" - uci -q set openmptcprouter.omr.ss_${name}="down" + uci -q set openmptcprouter.omr.ss_${server}="down" uci -q commit openmptcprouter.omr [ "$(uci show openmptcprouter.omr | grep ss | grep up)" = "" ] && /etc/init.d/shadowsocks-libev rules_down 2> /dev/null _get_ip diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index fa4e4d265..77765c19c 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -133,6 +133,9 @@ _launch_gre_tracker() { _initialize_shadowsocks_tracker() { local redir_tcp server tracker_server server=$1 + + [ -n "$(echo $server | grep sss)" ] || return + #redir_tcp=$(uci -q get shadowsocks-libev.ss_rules.redir_tcp) #config_get tracker_server ss_rules server config_get ss_disabled $server disabled 0 From 43fad987993c69612e0b0b80c912504b211c5226 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Jan 2021 10:09:51 +0100 Subject: [PATCH 0054/2059] Fix API contact --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 49d0b5f29..19a7d68bb 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -22,6 +22,7 @@ _login() { username="$(uci -q get openmptcprouter.${servername}.username)" password="$(uci -q get openmptcprouter.${servername}.password)" serverport="$(uci -q get openmptcprouter.${servername}.port)" + #[ -z "$server" ] && server="$(uci -q get openmptcprouter.${servername}.ip)" if [ -z "$token" ]; then login_on_server() { server=$1 @@ -37,6 +38,7 @@ _login() { token="$(echo "$auth" | jsonfilter -q -e '@.access_token')" uci -q set openmptcprouter.${servername}.token="$token" } + config_load openmptcprouter config_list_foreach ${servername} ip login_on_server fi } From becf56df854590ab67265c7d7d4d171683b68638 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Jan 2021 16:42:49 +0100 Subject: [PATCH 0055/2059] Fix issue when VPS have multiples IPs and IPs are redirected to multiples LAN IP --- shadowsocks-libev/files/ss-rules | 46 ++++++++++++------------- shadowsocks-libev/files/ss-rules6 | 48 +++++++++++++-------------- v2ray-core/files/usr/bin/v2ray-rules | 44 ++++++++++++------------ v2ray-core/files/usr/bin/v2ray-rules6 | 40 +++++++++++----------- 4 files changed, 89 insertions(+), 89 deletions(-) diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 732d9d620..74373efc3 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -125,28 +125,28 @@ ss_rules_flush() { iptables-save --counters | grep -v ssr_ | iptables-restore -w --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true - for setname in $(ipset -n list | grep "ss_rules_"); do + for setname in $(ipset -n list | grep "ssr_${rule}"); do ipset destroy "$setname" 2>/dev/null || true done } ss_rules_ipset_init() { ipset --exist restore <<-EOF - create ss_rules_src_bypass hash:net hashsize 64 - create ss_rules_src_forward hash:net hashsize 64 - create ss_rules_src_checkdst hash:net hashsize 64 - create ss_rules_dst_bypass_all hash:net hashsize 64 - create ss_rules_dst_bypass hash:net hashsize 64 - create ss_rules_dst_bypass_ hash:net hashsize 64 - create ss_rules_dst_forward hash:net hashsize 64 + create ssr_${rule}_src_bypass hash:net hashsize 64 + create ssr_${rule}_src_forward hash:net hashsize 64 + create ssr_${rule}_src_checkdst hash:net hashsize 64 + create ssr_rules_dst_bypass_all hash:net hashsize 64 + create ssr_${rule}_dst_bypass hash:net hashsize 64 + create ssr_${rule}_dst_bypass_ hash:net hashsize 64 + create ssr_${rule}_dst_forward hash:net hashsize 64 create ss_rules_dst_forward_recentrst_ hash:ip hashsize 64 timeout 3600 - $(ss_rules_ipset_mkadd ss_rules_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") + $(ss_rules_ipset_mkadd ssr_${rule}_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") $(ss_rules_ipset_mkadd ss_rules_dst_bypass_all "$o_dst_bypass_all") - $(ss_rules_ipset_mkadd ss_rules_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") - $(ss_rules_ipset_mkadd ss_rules_src_bypass "$o_src_bypass") - $(ss_rules_ipset_mkadd ss_rules_src_forward "$o_src_forward") - $(ss_rules_ipset_mkadd ss_rules_src_checkdst "$o_src_checkdst") - $(ss_rules_ipset_mkadd ss_rules_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") + $(ss_rules_ipset_mkadd ssr_${rule}_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") + $(ss_rules_ipset_mkadd ssr_${rule}_src_bypass "$o_src_bypass") + $(ss_rules_ipset_mkadd ssr_${rule}_src_forward "$o_src_forward") + $(ss_rules_ipset_mkadd ssr_${rule}_src_checkdst "$o_src_checkdst") + $(ss_rules_ipset_mkadd ssr_${rule}_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") EOF } @@ -192,9 +192,9 @@ ss_rules_iptchains_init_tcp() { *nat :ssr_${rule}_local_out - -I OUTPUT 1 -p tcp -j ssr_${rule}_local_out - -A ssr_${rule}_local_out -m set --match-set ss_rules_dst_bypass dst -j RETURN + -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN -A ssr_${rule}_local_out -m set --match-set ss_rules_dst_bypass_all dst -j RETURN - -A ssr_${rule}_local_out -m set --match-set ss_rules_dst_bypass_ dst -j RETURN + -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN -A ssr_${rule}_local_out -m mark --mark 0x539 -j RETURN -A ssr_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" COMMIT @@ -250,19 +250,19 @@ ss_rules_iptchains_init_() { :ssr_${rule}_dst - :ssr_${rule}_forward - $(ss_rules_iptchains_mkprerules "$proto") - -A ssr_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_ dst -j RETURN + -A ssr_${rule}_pre_src -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN -A ssr_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 -A ssr_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_all dst -j RETURN - -A ssr_${rule}_pre_src -m set --match-set ss_rules_dst_bypass dst -j RETURN + -A ssr_${rule}_pre_src -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN -A ssr_${rule}_pre_src -m mark --mark 0x539 -j RETURN -A ssr_${rule}_dst -m set --match-set ss_rules_dst_bypass_all dst -j RETURN - -A ssr_${rule}_dst -m set --match-set ss_rules_dst_bypass dst -j RETURN + -A ssr_${rule}_dst -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN -A ssr_${rule}_pre_src -p $proto $o_ipt_extra -j ssr_${rule}_src - -A ssr_${rule}_src -m set --match-set ss_rules_src_bypass src -j RETURN - -A ssr_${rule}_src -m set --match-set ss_rules_src_forward src -j ssr_${rule}_forward - -A ssr_${rule}_src -m set --match-set ss_rules_src_checkdst src -j ssr_${rule}_dst + -A ssr_${rule}_src -m set --match-set ssr_${rule}_src_bypass src -j RETURN + -A ssr_${rule}_src -m set --match-set ssr_${rule}_src_forward src -j ssr_${rule}_forward + -A ssr_${rule}_src -m set --match-set ssr_${rule}_src_checkdst src -j ssr_${rule}_dst -A ssr_${rule}_src -j $src_default_target -m comment --comment "src_default: $o_src_default" - -A ssr_${rule}_dst -m set --match-set ss_rules_dst_forward dst -j ssr_${rule}_forward + -A ssr_${rule}_dst -m set --match-set ssr_${rule}_dst_forward dst -j ssr_${rule}_forward $recentrst_addset_rules -A ssr_${rule}_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default" $forward_rules diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index 1c25b43bf..c114dc268 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -108,28 +108,28 @@ ss_rules6_flush() { ip6tables-save --counters | grep -v ssr6_ | ip6tables-restore -w --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true - for setname in $(ipset -n list | grep "ss_rules6_"); do + for setname in $(ipset -n list | grep "ssr6_${rule}"); do ipset destroy "$setname" 2>/dev/null || true done } ss_rules6_ipset_init() { ipset --exist restore <<-EOF - create ss_rules6_src_bypass hash:net family inet6 hashsize 64 - create ss_rules6_src_forward hash:net family inet6 hashsize 64 - create ss_rules6_src_checkdst hash:net family inet6 hashsize 64 - create ss_rules6_dst_bypass hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_bypass hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_forward hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_checkdst hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_bypass hash:net family inet6 hashsize 64 create ss_rules6_dst_bypass_all hash:net family inet6 hashsize 64 - create ss_rules6_dst_bypass_ hash:net family inet6 hashsize 64 - create ss_rules6_dst_forward hash:net family inet6 hashsize 64 - create ss_rules6_dst_forward_recrst_ hash:ip family inet6 hashsize 64 timeout 3600 - $(ss_rules6_ipset_mkadd ss_rules6_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") + create ssr6_${rule}_dst_bypass_ hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_forward hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_forward_recrst_ hash:ip family inet6 hashsize 64 timeout 3600 + $(ss_rules6_ipset_mkadd ssr6_${rule}_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") $(ss_rules6_ipset_mkadd ss_rules6_dst_bypass_all "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") - $(ss_rules6_ipset_mkadd ss_rules6_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") - $(ss_rules6_ipset_mkadd ss_rules6_src_bypass "$o_src_bypass") - $(ss_rules6_ipset_mkadd ss_rules6_src_forward "$o_src_forward") - $(ss_rules6_ipset_mkadd ss_rules6_src_checkdst "$o_src_checkdst") - $(ss_rules6_ipset_mkadd ss_rules6_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") + $(ss_rules6_ipset_mkadd ssr6_${rule}_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") + $(ss_rules6_ipset_mkadd ssr6_${rule}_src_bypass "$o_src_bypass") + $(ss_rules6_ipset_mkadd ssr6_${rule}_src_forward "$o_src_forward") + $(ss_rules6_ipset_mkadd ssr6_${rule}_src_checkdst "$o_src_checkdst") + $(ss_rules6_ipset_mkadd ssr6_${rule}_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") EOF } @@ -174,9 +174,9 @@ ss_rules6_iptchains_init_tcp() { *nat :ssr6_${rule}_local_out - -I OUTPUT 1 -p tcp -j ssr6_${rule}_local_out - -A ssr6_${rule}_local_out -m set --match-set ss_rules6_dst_bypass dst -j RETURN - -A ssr6_${rule}_local_out -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN - -A ssr6_${rule}_local_out -m set --match-set ss_rules6_dst_bypass_ dst -j RETURN + -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN + -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass_all dst -j RETURN + -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass_ dst -j RETURN -A ssr6_${rule}_local_out -m mark --mark 0x6539 -j RETURN -A ssr6_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" COMMIT @@ -232,19 +232,19 @@ ss_rules6_iptchains_init_() { :ssr6_${rule}_dst - :ssr6_${rule}_forward - $(ss_rules6_iptchains_mkprerules "$proto") - -A ssr6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_ dst -j RETURN + -A ssr6_${rule}_pre_src -m set --match-set ssr6_${rule}_dst_bypass_ dst -j RETURN -A ssr6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 -A ssr6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN - -A ssr6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass dst -j RETURN + -A ssr6_${rule}_pre_src -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN -A ssr6_${rule}_pre_src -m mark --mark 0x6539 -j RETURN -A ssr6_${rule}_dst -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN - -A ssr6_${rule}_dst -m set --match-set ss_rules6_dst_bypass dst -j RETURN + -A ssr6_${rule}_dst -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN -A ssr6_${rule}_pre_src -p $proto $o_ipt_extra -j ssr6_${rule}_src - -A ssr6_${rule}_src -m set --match-set ss_rules6_src_bypass src -j RETURN - -A ssr6_${rule}_src -m set --match-set ss_rules6_src_forward src -j ssr6_${rule}_forward - -A ssr6_${rule}_src -m set --match-set ss_rules6_src_checkdst src -j ssr6_${rule}_dst + -A ssr6_${rule}_src -m set --match-set ssr6_${rule}_src_bypass src -j RETURN + -A ssr6_${rule}_src -m set --match-set ssr6_${rule}_src_forward src -j ssr6_${rule}_forward + -A ssr6_${rule}_src -m set --match-set ssr6_${rule}_src_checkdst src -j ssr6_${rule}_dst -A ssr6_${rule}_src -j $src_default_target -m comment --comment "src_default: $o_src_default" - -A ssr6_${rule}_dst -m set --match-set ss_rules6_dst_forward dst -j ssr6_${rule}_forward + -A ssr6_${rule}_dst -m set --match-set ssr6_${rule}_dst_forward dst -j ssr6_${rule}_forward $recentrst_addset_rules -A ssr6_${rule}_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default" $forward_rules diff --git a/v2ray-core/files/usr/bin/v2ray-rules b/v2ray-core/files/usr/bin/v2ray-rules index 2d6642274..a43b19be7 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules +++ b/v2ray-core/files/usr/bin/v2ray-rules @@ -125,28 +125,28 @@ v2r_rules_flush() { iptables-save --counters | grep -v v2r_ | iptables-restore -w --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true - for setname in $(ipset -n list | grep "ss_rules_"); do + for setname in $(ipset -n list | grep "ssr_${rule}"); do ipset destroy "$setname" 2>/dev/null || true done } v2r_rules_ipset_init() { ipset --exist restore <<-EOF - create ss_rules_src_bypass hash:net hashsize 64 - create ss_rules_src_forward hash:net hashsize 64 - create ss_rules_src_checkdst hash:net hashsize 64 + create ssr_${rule}_src_bypass hash:net hashsize 64 + create ssr_${rule}_src_forward hash:net hashsize 64 + create ssr_${rule}_src_checkdst hash:net hashsize 64 create ss_rules_dst_bypass_all hash:net hashsize 64 - create ss_rules_dst_bypass hash:net hashsize 64 - create ss_rules_dst_bypass_ hash:net hashsize 64 - create ss_rules_dst_forward hash:net hashsize 64 + create ssr_${rule}_dst_bypass hash:net hashsize 64 + create ssr_${rule}_dst_bypass_ hash:net hashsize 64 + create ssr_${rule}_dst_forward hash:net hashsize 64 create ss_rules_dst_forward_recentrst_ hash:ip hashsize 64 timeout 3600 - $(v2r_rules_ipset_mkadd ss_rules_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") + $(v2r_rules_ipset_mkadd ssr_${rule}_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") $(v2r_rules_ipset_mkadd ss_rules_dst_bypass_all "$o_dst_bypass_all") - $(v2r_rules_ipset_mkadd ss_rules_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") - $(v2r_rules_ipset_mkadd ss_rules_src_bypass "$o_src_bypass") - $(v2r_rules_ipset_mkadd ss_rules_src_forward "$o_src_forward") - $(v2r_rules_ipset_mkadd ss_rules_src_checkdst "$o_src_checkdst") - $(v2r_rules_ipset_mkadd ss_rules_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") + $(v2r_rules_ipset_mkadd ssr_${rule}_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") + $(v2r_rules_ipset_mkadd ssr_${rule}_src_bypass "$o_src_bypass") + $(v2r_rules_ipset_mkadd ssr_${rule}_src_forward "$o_src_forward") + $(v2r_rules_ipset_mkadd ssr_${rule}_src_checkdst "$o_src_checkdst") + $(v2r_rules_ipset_mkadd ssr_${rule}_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')") EOF } @@ -192,9 +192,9 @@ v2r_rules_iptchains_init_tcp() { *nat :v2r_${rule}_local_out - -I OUTPUT 1 -p tcp -j v2r_${rule}_local_out - -A v2r_${rule}_local_out -m set --match-set ss_rules_dst_bypass dst -j RETURN + -A v2r_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN -A v2r_${rule}_local_out -m set --match-set ss_rules_dst_bypass_all dst -j RETURN - -A v2r_${rule}_local_out -m set --match-set ss_rules_dst_bypass_ dst -j RETURN + -A v2r_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN -A v2r_${rule}_local_out -m mark --mark 0x539 -j RETURN -A v2r_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" COMMIT @@ -250,19 +250,19 @@ v2r_rules_iptchains_init_() { :v2r_${rule}_dst - :v2r_${rule}_forward - $(v2r_rules_iptchains_mkprerules "$proto") - -A v2r_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_ dst -j RETURN + -A v2r_${rule}_pre_src -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN -A v2r_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 -A v2r_${rule}_pre_src -m set --match-set ss_rules_dst_bypass_all dst -j RETURN - -A v2r_${rule}_pre_src -m set --match-set ss_rules_dst_bypass dst -j RETURN + -A v2r_${rule}_pre_src -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN -A v2r_${rule}_pre_src -m mark --mark 0x539 -j RETURN -A v2r_${rule}_dst -m set --match-set ss_rules_dst_bypass_all dst -j RETURN - -A v2r_${rule}_dst -m set --match-set ss_rules_dst_bypass dst -j RETURN + -A v2r_${rule}_dst -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN -A v2r_${rule}_pre_src -p $proto $o_ipt_extra -j v2r_${rule}_src - -A v2r_${rule}_src -m set --match-set ss_rules_src_bypass src -j RETURN - -A v2r_${rule}_src -m set --match-set ss_rules_src_forward src -j v2r_${rule}_forward - -A v2r_${rule}_src -m set --match-set ss_rules_src_checkdst src -j v2r_${rule}_dst + -A v2r_${rule}_src -m set --match-set ssr_${rule}_src_bypass src -j RETURN + -A v2r_${rule}_src -m set --match-set ssr_${rule}_src_forward src -j v2r_${rule}_forward + -A v2r_${rule}_src -m set --match-set ssr_${rule}_src_checkdst src -j v2r_${rule}_dst -A v2r_${rule}_src -j $src_default_target -m comment --comment "src_default: $o_src_default" - -A v2r_${rule}_dst -m set --match-set ss_rules_dst_forward dst -j v2r_${rule}_forward + -A v2r_${rule}_dst -m set --match-set ssr_${rule}_dst_forward dst -j v2r_${rule}_forward $recentrst_addset_rules -A v2r_${rule}_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default" $forward_rules diff --git a/v2ray-core/files/usr/bin/v2ray-rules6 b/v2ray-core/files/usr/bin/v2ray-rules6 index 14f51e5dd..b05c70c59 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules6 +++ b/v2ray-core/files/usr/bin/v2ray-rules6 @@ -108,28 +108,28 @@ v2ray_rules6_flush() { ip6tables-save --counters | grep -v v2r6_ | ip6tables-restore -w --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true - for setname in $(ipset -n list | grep "ss_rules6_"); do + for setname in $(ipset -n list | grep "ssr6_${rule}"); do ipset destroy "$setname" 2>/dev/null || true done } v2ray_rules6_ipset_init() { ipset --exist restore <<-EOF - create ss_rules6_src_bypass hash:net family inet6 hashsize 64 - create ss_rules6_src_forward hash:net family inet6 hashsize 64 - create ss_rules6_src_checkdst hash:net family inet6 hashsize 64 - create ss_rules6_dst_bypass hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_bypass hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_forward hash:net family inet6 hashsize 64 + create ssr6_${rule}_src_checkdst hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_bypass hash:net family inet6 hashsize 64 create ss_rules6_dst_bypass_all hash:net family inet6 hashsize 64 - create ss_rules6_dst_bypass_ hash:net family inet6 hashsize 64 - create ss_rules6_dst_forward hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_bypass_ hash:net family inet6 hashsize 64 + create ssr6_${rule}_dst_forward hash:net family inet6 hashsize 64 create ss_rules6_dst_forward_recrst_ hash:ip family inet6 hashsize 64 timeout 3600 - $(v2ray_rules6_ipset_mkadd ss_rules6_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") + $(v2ray_rules6_ipset_mkadd ssr6_${rule}_dst_bypass_ "$o_dst_bypass_ $o_remote_servers") $(v2ray_rules6_ipset_mkadd ss_rules6_dst_bypass_all "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") - $(v2ray_rules6_ipset_mkadd ss_rules6_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") - $(v2ray_rules6_ipset_mkadd ss_rules6_src_bypass "$o_src_bypass") - $(v2ray_rules6_ipset_mkadd ss_rules6_src_forward "$o_src_forward") - $(v2ray_rules6_ipset_mkadd ss_rules6_src_checkdst "$o_src_checkdst") - $(v2ray_rules6_ipset_mkadd ss_rules6_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") + $(v2ray_rules6_ipset_mkadd ssr6_${rule}_dst_bypass "$o_dst_bypass $(cat "$o_dst_bypass_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") + $(v2ray_rules6_ipset_mkadd ssr6_${rule}_src_bypass "$o_src_bypass") + $(v2ray_rules6_ipset_mkadd ssr6_${rule}_src_forward "$o_src_forward") + $(v2ray_rules6_ipset_mkadd ssr6_${rule}_src_checkdst "$o_src_checkdst") + $(v2ray_rules6_ipset_mkadd ssr6_${rule}_dst_forward "$o_dst_forward $(cat "$o_dst_forward_file" 2>/dev/null | grep -o '\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}')") EOF } @@ -240,20 +240,20 @@ v2ray_rules6_iptchains_init_() { :v2r6_${rule}_forward - $(v2ray_rules6_iptchains_mkprerules "udp") $(v2ray_rules6_iptchains_mkprerules "tcp") - -A v2r6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_ dst -j RETURN + -A v2r6_${rule}_pre_src -m set --match-set ssr6_${rule}_dst_bypass_ dst -j RETURN -A v2r6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 -A v2r6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN - -A v2r6_${rule}_pre_src -m set --match-set ss_rules6_dst_bypass dst -j RETURN + -A v2r6_${rule}_pre_src -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN -A v2r6_${rule}_pre_src -m mark --mark 0x6539 -j RETURN -A v2r6_${rule}_dst -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN - -A v2r6_${rule}_dst -m set --match-set ss_rules6_dst_bypass dst -j RETURN + -A v2r6_${rule}_dst -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN -A v2r6_${rule}_pre_src -p tcp $o_ipt_extra -j v2r6_${rule}_src -A v2r6_${rule}_pre_src -p udp $o_ipt_extra -j v2r6_${rule}_src - -A v2r6_${rule}_src -m set --match-set ss_rules6_src_bypass src -j RETURN - -A v2r6_${rule}_src -m set --match-set ss_rules6_src_forward src -j v2r6_${rule}_forward - -A v2r6_${rule}_src -m set --match-set ss_rules6_src_checkdst src -j v2r6_${rule}_dst + -A v2r6_${rule}_src -m set --match-set ssr6_${rule}_src_bypass src -j RETURN + -A v2r6_${rule}_src -m set --match-set ssr6_${rule}_src_forward src -j v2r6_${rule}_forward + -A v2r6_${rule}_src -m set --match-set ssr6_${rule}_src_checkdst src -j v2r6_${rule}_dst -A v2r6_${rule}_src -j $src_default_target -m comment --comment "src_default: $o_src_default" - -A v2r6_${rule}_dst -m set --match-set ss_rules6_dst_forward dst -j v2r6_${rule}_forward + -A v2r6_${rule}_dst -m set --match-set ssr6_${rule}_dst_forward dst -j v2r6_${rule}_forward $recentrst_addset_rules -A v2r6_${rule}_dst -j $dst_default_target -m comment --comment "dst_default: $o_dst_default" $forward_rules From a0da499c105c71960b014d36ade9fc5167d7803d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Jan 2021 16:43:15 +0100 Subject: [PATCH 0056/2059] Display IPv6 in status only when gateway exist --- .../luasrc/view/openmptcprouter/wanstatus.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index cff1dbac6..1aa626cd5 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -469,7 +469,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { content += String.format('%s %s
    ','<%:ip address:%>', ipaddr); } - if(ip6addr !== '') + if(ip6addr !== '' && gateway6 != '') { content += String.format('%s %s
    ','<%:ipv6 address:%>', ip6addr); } @@ -477,7 +477,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { content += String.format('%s %s
    ','<%:wan address:%>', wanip); } - if(wanip6 !== '' && gateway6 != '') + if(wanip6 !== '') { content += String.format('%s %s
    ','<%:wan ipv6 address:%>', wanip6); } From b0e38240cc83d4f40f084d51344511d4b0787fe4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 27 Jan 2021 18:18:50 +0100 Subject: [PATCH 0057/2059] Fix shadowsocks iptables rules --- .../files/shadowsocks-libev.init | 5 ++++ shadowsocks-libev/files/ss-rules | 29 ++++++++++--------- shadowsocks-libev/files/ss-rules6 | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 7c3056747..9e15c6241 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -1,6 +1,7 @@ #!/bin/sh /etc/rc.common # # Copyright (C) 2017-2019 Yousong Zhou +# Copyright (C) 2019-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter # # This is free software, licensed under the GNU General Public License v3. # See /LICENSE for more information. @@ -314,6 +315,10 @@ stop_service() { rm -rf "$ss_confdir" } +reload_service() { + restart "$@" +} + rules_exist() { [ -n "$(iptables -t nat -L -n | grep ssr)" ] && return 0 return 1 diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 74373efc3..396de706d 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -1,7 +1,7 @@ #!/bin/sh -e # # Copyright (C) 2017 Yousong Zhou -# Copyright (C) 2018 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) # # The design idea was derived from ss-rules by Jian Chang # @@ -135,7 +135,7 @@ ss_rules_ipset_init() { create ssr_${rule}_src_bypass hash:net hashsize 64 create ssr_${rule}_src_forward hash:net hashsize 64 create ssr_${rule}_src_checkdst hash:net hashsize 64 - create ssr_rules_dst_bypass_all hash:net hashsize 64 + create ss_rules_dst_bypass_all hash:net hashsize 64 create ssr_${rule}_dst_bypass hash:net hashsize 64 create ssr_${rule}_dst_bypass_ hash:net hashsize 64 create ssr_${rule}_dst_forward hash:net hashsize 64 @@ -187,18 +187,19 @@ ss_rules_iptchains_init_tcp() { forward) local_target=ssr_${rule}_forward ;; bypass|*) return 0;; esac - - iptables-restore -w --noflush <<-EOF - *nat - :ssr_${rule}_local_out - - -I OUTPUT 1 -p tcp -j ssr_${rule}_local_out - -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN - -A ssr_${rule}_local_out -m set --match-set ss_rules_dst_bypass_all dst -j RETURN - -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN - -A ssr_${rule}_local_out -m mark --mark 0x539 -j RETURN - -A ssr_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" - COMMIT - EOF + if [ "$(iptables -t nat -L ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then + iptables-restore -w --noflush <<-EOF + *nat + :ssr_${rule}_local_out - + -I OUTPUT 1 -p tcp -j ssr_${rule}_local_out + -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass dst -j RETURN + -A ssr_${rule}_local_out -m set --match-set ss_rules_dst_bypass_all dst -j RETURN + -A ssr_${rule}_local_out -m set --match-set ssr_${rule}_dst_bypass_ dst -j RETURN + -A ssr_${rule}_local_out -m mark --mark 0x539 -j RETURN + -A ssr_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" + COMMIT + EOF + fi } ss_rules_iptchains_init_udp() { diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index c114dc268..84d04beb5 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -1,7 +1,7 @@ #!/bin/sh -e # # Copyright (C) 2017 Yousong Zhou -# Copyright (C) 2018 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) # # The design idea was derived from ss-rules by Jian Chang # From df1f5a791591115b98f19e2c24934804d4709f95 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:41:36 +0100 Subject: [PATCH 0058/2059] Fix omr-bypass with vlan --- .../root/etc/init.d/omr-bypass | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 592d875ac..82a1e68f5 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -50,7 +50,8 @@ _bypass_domains() { _bypass_domain() { local domain=$1 local intf=$2 - + intf=$(echo $intf | sed -e 's/\./_/') + [ -z "$intf" ] && intf="all" if [ -n "$domain" ]; then domain=$(echo $domain | sed 's:^\.::') @@ -68,7 +69,7 @@ _bypass_domain() { fi fi if [ "$(uci -q get dhcp.@dnsmasq[0].ipset | grep /$domain/)" = "" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intfuci,omr6_dst_bypass_$intf" else dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g') for dnsipset in $dnsmasqipset; do @@ -90,8 +91,8 @@ _bypass_mac() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - intfuci=$(echo $intf | sed 's/\./_/') - local intfid="$(uci -q get omr-bypass.$intfuci.id)" + intf=$(echo $intf | sed -e 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$mac" ] && return @@ -132,8 +133,8 @@ _bypass_lan_ip() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - intfuci=$(echo $intf | sed 's/\./_/') - local intfid="$(uci -q get omr-bypass.$intfuci.id)" + intf=$(echo $intf | sed -e 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$ip" ] && return @@ -190,8 +191,8 @@ _bypass_dest_port() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - intfuci=$(echo $intf | sed 's/\./_/') - local intfid="$(uci -q get omr-bypass.$intfuci.id)" + intf=$(echo $intf | sed -e 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$dport" ] && return @@ -246,8 +247,8 @@ _bypass_src_port() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - intfuci=$(echo $intf | sed 's/\./_/') - local intfid="$(uci -q get omr-bypass.$intfuci.id)" + intf=$(echo $intf | sed -e 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$sport" ] && return @@ -300,8 +301,8 @@ _bypass_proto() { config_get intf $1 interface config_get enabled $1 enabled [ "$enabled" = "0" ] && return - intfuci=$(echo $intf | sed 's/\./_/') - local intfid="$(uci -q get omr-bypass.$intfuci.id)" + intf=$(echo $intf | sed -e 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return @@ -459,6 +460,7 @@ _intf_rule() { #[ "$mode" = "off" ] && return [ -z "$count" ] && return [ -z "$intf" ] && return + intf=$(echo $intf | sed -e 's/\./_/') [ "$(echo $1 | grep _dev)" != "" ] && return [ -z "$RELOAD" ] || [ "$(ipset --list | grep omr_dst_bypass_$intf)" = "" ] && { unset RELOAD @@ -498,9 +500,8 @@ _intf_rule() { config_foreach _intf_rule_ss_rules ss_rules _intf_rule_v2ray_rules - intfuci=$(echo $intf | sed 's/\./_/') - uci -q set omr-bypass.$intfuci=interface - uci -q set omr-bypass.$intfuci.id=$count + uci -q set omr-bypass.$intf=interface + uci -q set omr-bypass.$intf.id=$count } _bypass_ip_set() { From 1518776a8be6f8ffc5b9c6cb53e187518c0f55a2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:42:01 +0100 Subject: [PATCH 0059/2059] Fix typo --- .../luasrc/view/openmptcprouter/settings.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index c23724f44..7ae4100b4 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -255,7 +255,7 @@
    - +
    checked<% end %>>
    From 4f6b1d263eb9970ff5798e6e09084e45f467f7c6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:43:01 +0100 Subject: [PATCH 0060/2059] Support 2 IPs on server --- .../luasrc/controller/openmptcprouter.lua | 54 +++++++++++++++---- .../luasrc/view/openmptcprouter/wizard.htm | 26 +++++++-- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 29ec07420..62974d55b 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -66,7 +66,8 @@ function wizard_add() ucic:foreach("openmptcprouter", "server", function(s) local servername = s[".name"] nbserver = nbserver + 1 - server_ip = ucic:get("openmptcprouter",servername,"ip") + server_ips = ucic:get_list("openmptcprouter",servername,"ip") + server_ip = server_ips[1] end) if nbserver == 1 and server_ip ~= "" and server_ip ~= nil then ucic:set("shadowsocks-libev","sss0","server",server_ip) @@ -425,8 +426,14 @@ function wizard_add() local disablednb = 0 local servers = luci.http.formvaluetable("server") for server, _ in pairs(servers) do - local server_ip = {} - server_ip[1] = luci.http.formvalue("%s.server_ip" % server) or "" + local serverips = luci.http.formvaluetable("%s.serverip" % server) or {} + local aserverips = {} + for _, ip in pairs(serverips) do + if ip ~= "" and ip ~= nil then + table.insert(aserverips,ip) + end + end + local master = luci.http.formvalue("master") or "" -- OpenMPTCProuter VPS @@ -447,14 +454,14 @@ function wizard_add() if openmptcprouter_vps_disabled == "1" then disablednb = disablednb + 1 end - if server_ip[1] ~= "" then + if next(aserverips) ~= nil then serversnb = serversnb + 1 end ucic:set("openmptcprouter",server,"server") ucic:set("openmptcprouter",server,"username",openmptcprouter_vps_username) ucic:set("openmptcprouter",server,"password",openmptcprouter_vps_key) ucic:set("openmptcprouter",server,"disabled",openmptcprouter_vps_disabled) - ucic:set_list("openmptcprouter",server,"ip",server_ip) + ucic:set_list("openmptcprouter",server,"ip",aserverips) ucic:set("openmptcprouter",server,"port","65500") ucic:save("openmptcprouter") end @@ -488,6 +495,13 @@ function wizard_add() ucic:save("shadowsocks-libev") ucic:save("v2ray") + ucic:foreach("shadowsocks-libev","server", function(s) + local sectionname = s[".name"] + if sectionname:match("^sss.*") then + ucic:delete("shadowsocks-libev",sectionname,"ip") + ucic:set("shadowsocks-libev",sectionname,"disabled","1") + end + end) local ss_servers_nginx = {} local ss_servers_ha = {} @@ -497,14 +511,20 @@ function wizard_add() for server, _ in pairs(servers) do local master = luci.http.formvalue("master") or "" - local server_ip = luci.http.formvalue("%s.server_ip" % server) or "" + local server_ips = luci.http.formvaluetable("%s.serverip" % server) or {} + local server_ip = "" + for _, ip in pairs(server_ips) do + if server_ip == "" and ip ~= "" and ip ~= nil then + server_ip=ip + end + end -- We have an IP, so set it everywhere - if server_ip ~= "" and luci.http.formvalue("%s.openmptcprouter_vps_disabled" % server) ~= "1" then + if server_ip ~= "" and server_ip ~= nil and luci.http.formvalue("%s.openmptcprouter_vps_disabled" % server) ~= "1" then -- Check if we have more than one IP, in this case use Nginx HA if serversnb > 1 then if master == server then ss_ip=server_ip - ucic:set("shadowsocks-libev","sss0","server",server_ip) + --ucic:set("shadowsocks-libev","sss0","server",server_ip) ucic:set("glorytun","vpn","host",server_ip) ucic:set("glorytun-udp","vpn","host",server_ip) ucic:set("dsvpn","vpn","host",server_ip) @@ -516,6 +536,14 @@ function wizard_add() luci.sys.call("uci -q add_list openvpn.omr.remote=" .. server_ip) ucic:set("qos","serverin","srchost",server_ip) ucic:set("qos","serverout","dsthost",server_ip) + local nbip = 0 + for _, ssip in pairs(server_ips) do + ucic:set("shadowsocks-libev","sss" .. nbip,"server",ssip) + if default_proxy == "shadowsocks" then + ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") + end + nbip = nbip + 1 + end end k = k + 1 ucic:set("nginx-ha","ShadowSocks","enable","0") @@ -526,7 +554,7 @@ function wizard_add() ucic:set("openmptcprouter","settings","ha","0") ucic:set("nginx-ha","ShadowSocks","enable","0") ucic:set("nginx-ha","VPN","enable","0") - ucic:set("shadowsocks-libev","sss0","server",server_ip) + --ucic:set("shadowsocks-libev","sss0","server",server_ip) ucic:set("glorytun","vpn","host",server_ip) ucic:set("glorytun-udp","vpn","host",server_ip) ucic:set("dsvpn","vpn","host",server_ip) @@ -538,6 +566,14 @@ function wizard_add() luci.sys.call("uci -q add_list openvpn.omr.remote=" .. server_ip) ucic:set("qos","serverin","srchost",server_ip) ucic:set("qos","serverout","dsthost",server_ip) + local nbip = 0 + for _, ssip in pairs(server_ips) do + ucic:set("shadowsocks-libev","sss" .. nbip,"server",ssip) + if default_proxy == "shadowsocks" then + ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") + end + nbip = nbip + 1 + end end end end diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 89da6bc85..d966771d9 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -55,9 +55,19 @@

    <%=servername%>

    - +
    - " data-optional="false"> + " data-optional="false"> +
    + <%:Server IP will be set for proxy and VPN%> +
    +
    +
    +
    +
    + +
    + " data-optional="false">
    <%:Server IP will be set for proxy and VPN%>
    @@ -147,7 +157,10 @@
    - checked<% end %> /> +
    <%:You should disable IPv6 here if server doesn't provide IPv6.%> @@ -874,6 +887,13 @@ if not (ifacea == "lo" or ifacea == "6in4-omr6in4" or ifacea == "mlvpn0" or ifacea:match("^ifb.*") or ifacea:match("^sit.*") or ifacea:match("^gre.*") or ifacea:match("^ip6.*") or ifacea:match("^teql.*") or ifacea:match("^erspan.*")) and device_notvirtual(ifacea) then %> + <% + end + end + for _, ifacea in ipairs(net:get_networks()) do + if not (ifacea:name() == "loopback" or ifacea:name() == "omr6in4" or ifacea:name() == "omrvpn" or ifacea:name():match("^omrip.*")) then + %> + <% end end From ea850cea047c99cdec43954b183e4a0c4f367230 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:43:31 +0100 Subject: [PATCH 0061/2059] Support alias interfaces --- .../root/usr/libexec/rpcd/openmptcprouter | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 9f88a0cc4..b80a81a7d 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1115,6 +1115,7 @@ function interfaces_status() local gateway6 = section["ip6gw"] or "" local multipath = section["multipath"] local enabled = section["auto"] + local proto = section["proto"] or "" --if not ipaddr or not gateway then return end -- Don't show if0 in the overview @@ -1130,7 +1131,7 @@ function interfaces_status() duplicateif = false if ifname ~= "" and ifname ~= nil then - if allintf[ifname] then + if allintf[ifname] and not section["ifname"]:match("^@.*") then connectivity = "ERROR" duplicateif = true else @@ -1144,10 +1145,10 @@ function interfaces_status() if enabled == "0" then return end local connectivity = "OK" - if ipaddr == "" and ifname ~= nil and ifname ~= "" then + if ipaddr == "" and ifname ~= nil and ifname ~= "" and proto ~= "dhcpv6" then ipaddr = ut.trim(sys.exec("ip -4 -br addr ls dev " .. ifname .. " | awk -F'[ /]+' '{print $3}' | tr -d '\n'")) end - if ipaddr == "" and ifname ~= nil and ifname ~= "" then + if ipaddr == "" and ifname ~= nil and ifname ~= "" and proto ~= "dhcpv6" then ipaddr = ut.trim(sys.exec("ip -4 addr show dev " .. ifname .. " | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1 | tr -d '\n'")) end if ip6addr == "" and ifname ~= nil and ifname ~= "" then @@ -1195,14 +1196,16 @@ function interfaces_status() local gw_ping = "UP" local gw_ping6 = "UP" if ifname ~= nil and not (ifname:match("^tun.*") or interface:match("^ovpn.*")) then - gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) + if proto ~= "dhcpv6" then + gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) + end gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) end - if gateway == "" then + if gateway == "" and proto ~= "dhcpv6" then gateway = get_gateway(interface) end - if gateway == "" and ifname ~= nil and ifname ~= "" then + if gateway == "" and ifname ~= nil and ifname ~= "" and proto ~= "dhcpv6" then if fs.access("/sys/class/net/" .. ifname) then gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep kernel | awk '/proto kernel/ {print $1}' | grep -v / | tr -d '\n'")) if gateway == "" then @@ -1263,7 +1266,7 @@ function interfaces_status() end if ifname ~= "" and ifname ~= nil then - local proto = section['proto'] + --local proto = section['proto'] if proto == "qmi" then local device = section['device'] intfdata = ut.trim(sys.exec("omr-qmi " .. device .. " all")) @@ -1438,6 +1441,7 @@ function interfaces_status() phonenumber = phonenumber, donglestate = donglestate, networktype = networktype, + proto = proto, rx = rx, tx = tx, } From e05f1b8e02b1e2f494b282cd2fbad359f1ab1eef Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:44:10 +0100 Subject: [PATCH 0062/2059] Update ndpi netfiler2 --- ndpi-netfilter2/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 9f04c4e87..b74ed75c1 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -10,8 +10,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 -PKG_RELEASE:=2 -PKG_REV:=0a03249da911f4033fd2a0d38a97cdba72eee2b6 +PKG_RELEASE:=3 +PKG_REV:=25a5c2e1d619aa2d819b18bed8276b3bd7eb4c5b PKG_VERSION:=3.2-$(PKG_REV) PKG_SOURCE_PROTO:=git From 6ab5f128a943fb2e19c44618314bc17bf8b7b142 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:44:38 +0100 Subject: [PATCH 0063/2059] Support multi servers with glorytun UDP --- .../share/omr/post-tracking.d/post-tracking | 86 +++++++++++-------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index a8ce3ed18..9c51d7b7c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -891,45 +891,55 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then if [ "$(uci -q show | grep mptcpr)" = "" ]; then touch /etc/config/openmptcprouter fi - gtudpst="up" - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" - if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ]; then - if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then - if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 - else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate fixed tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 + glorytunudppath() { + gtudp_port="$(uci -q get glorytun-udp.vpn.port)" + gtudp_dev="$(uci -q get glorytun-udp.vpn.dev)" + addpath() { + serverip=$1 + #gtudpst="up" + #[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" + if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ] && [ -n "$(resolveip -4 $serverip)" ]; then + if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then + if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 + else + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate fixed tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 + fi + else + if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate auto tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 + else + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate fixed tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 + fi + fi fi - else - if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate auto tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 - else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set up rate fixed tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 + if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6)" = "" ] && [ -n "$(resolveip -6 $serverip)" ]; then + if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then + if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 + else + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate fixed tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 + fi + else + if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate auto tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 + else + glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip dev ${gtudp_dev} port ${gtudp_port} set up rate fixed tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 + fi + fi fi - fi - fi - if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6)" = "" ]; then - if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then - if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 - else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate fixed tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 - fi - else - if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate auto tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 - else - glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set up rate fixed tx 12500000 rx 12500000 pref 1 > /dev/null 2>&1 - fi - fi - fi -# if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp set | grep 'kxtimeout 7d')" = "" ]; then -# glorytun-udp set dev tun0 kxtimeout 7d > /dev/null 2>&1 -# fi - [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && { - [ -n "$OMR_TRACKER_DEVICE_IP" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP dev tun0 set pref 125 > /dev/null 2>&1 - [ -n "$OMR_TRACKER_DEVICE_IP6" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set pref 125 > /dev/null 2>&1 +# if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp set | grep 'kxtimeout 7d')" = "" ]; then +# glorytun-udp set dev tun0 kxtimeout 7d > /dev/null 2>&1 + # fi + [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && { + [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$(resolveip -4 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$(resolveip -6 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 + } + } + config_list_foreach $1 ip addpath } + config_load openmptcprouter + config_foreach glorytunudppath server fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { @@ -1230,7 +1240,7 @@ if [ "$(pgrep rpcd)" = "" ] && [ -f /etc/init.d/rpcd ]; then sleep 5 fi -if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ "$(pgrep -f omr-tracker-v2ray)" = "" ]; then +if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ "$(pgrep -f omr-tracker-v2ray)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-v2ray, restart omr-tracker..." /etc/init.d/omr-tracker restart fi @@ -1246,7 +1256,7 @@ if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get uci -q commit openmptcprouter fi -if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ]; then +if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-ss, restart omr-tracker..." /etc/init.d/omr-tracker restart fi From afcb30eb2d23c0d21e672fa686ad85f605250ace Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:45:45 +0100 Subject: [PATCH 0064/2059] Set public IP for uPnP --- omr-tracker/files/bin/omr-tracker-ss | 7 ++++++- omr-tracker/files/bin/omr-tracker-v2ray | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index 9a7234c93..be0074b01 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -27,7 +27,12 @@ _get_ip() { [ -z "$check_ipv4_website" ] && check_ipv4_website="http://ip.openmptcprouter.com" check_ipv6_website="$(uci -q get openmptcprouter.settings.check_ipv6_website)" [ -z "$check_ipv6_website" ] && check_ipv6_website="http://ipv6.openmptcprouter.com" - uci -q set openmptcprouter.omr.detected_public_ipv4="$(curl -s -4 -m 3 $check_ipv4_website)" + public_ipv4="$(curl -s -4 -m 3 $check_ipv4_website)" + uci -q set openmptcprouter.omr.detected_public_ipv4="${public_ipv4}" + [ -n "$public_ipv4" ] && { + uci -q set upnpd.config.external_ip="${public_ipv4}" + uci -q commit upnpd + } if [ "$(uci -q get openmptcprouter.omr.shadowsocks)" != "down" ]; then uci -q set openmptcprouter.omr.detected_ss_ipv4="$(curl -s -4 --socks5 "${proxy}" --max-time 3 $check_ipv4_website)" else diff --git a/omr-tracker/files/bin/omr-tracker-v2ray b/omr-tracker/files/bin/omr-tracker-v2ray index 32ef73c6b..e8e0dcffe 100755 --- a/omr-tracker/files/bin/omr-tracker-v2ray +++ b/omr-tracker/files/bin/omr-tracker-v2ray @@ -27,7 +27,12 @@ _get_ip() { [ -z "$check_ipv4_website" ] && check_ipv4_website="http://ip.openmptcprouter.com" check_ipv6_website="$(uci -q get openmptcprouter.settings.check_ipv6_website)" [ -z "$check_ipv6_website" ] && check_ipv6_website="http://ipv6.openmptcprouter.com" - uci -q set openmptcprouter.omr.detected_public_ipv4="$(curl -s -4 -m 3 $check_ipv4_website)" + public_ipv4="$(curl -s -4 -m 3 $check_ipv4_website)" + uci -q set openmptcprouter.omr.detected_public_ipv4="${public_ipv4}" + [ -n "${public_ipv4}" ] && { + uci -q set upnpd.config.external_ip="${public_ipv4}" + uci -q commit upnpd + } if [ "$(uci -q get openmptcprouter.omr.v2ray)" != "down" ]; then uci -q set openmptcprouter.omr.detected_ss_ipv4="$(curl -s -4 --socks5 "${proxy}" --max-time 3 $check_ipv4_website)" else From 07afc6ce8e80557b0c97f88883de53750cfdc8fa Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:46:36 +0100 Subject: [PATCH 0065/2059] Support multiples IPs on server for MPTCPoverVPN and OpenVPN Bonding --- openmptcprouter/files/etc/init.d/mptcpovervpn | 6 +++--- openmptcprouter/files/etc/init.d/openvpnbonding | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index 870148e5b..a2f7d97e4 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -9,7 +9,7 @@ } _getremoteip() { - [ "$(uci -q get openmptcprouter.$1.master)" = "1" ] && remoteip=$(uci -q get openmptcprouter.$1.ip) + [ "$(uci -q get openmptcprouter.$1.master)" = "1" ] && remoteip=$(uci -q get openmptcprouter.$1.ip | awk '{print $1}') } mptcp_over_vpn() { @@ -139,8 +139,8 @@ start_service() elif [ "$(uci -q get glorytun.vpn.host)" = "10.255.250.1" ] && [ "$nbintf" != "$nbintfvpn" ]; then uci -q batch <<-EOF >/dev/null delete shadowsocks-libev.sss0.disabled - set glorytun.vpn.host="$(uci -q get openmptcprouter.vps.ip)" - set glorytun-udp.vpn.host="$(uci -q get openmptcprouter.vps.ip)" + set glorytun.vpn.host="$(uci -q get openmptcprouter.vps.ip | awk '{print $1}')" + set glorytun-udp.vpn.host="$(uci -q get openmptcprouter.vps.ip | awk '{print $1}')" commit glorytun commit glorytun-udp EOF diff --git a/openmptcprouter/files/etc/init.d/openvpnbonding b/openmptcprouter/files/etc/init.d/openvpnbonding index d36eeb584..87dfdf483 100755 --- a/openmptcprouter/files/etc/init.d/openvpnbonding +++ b/openmptcprouter/files/etc/init.d/openvpnbonding @@ -9,7 +9,7 @@ } _getremoteip() { - [ "$(uci -q get openmptcprouter.$1.master)" = "1" ] && remoteip=$(uci -q get openmptcprouter.$1.ip) + [ "$(uci -q get openmptcprouter.$1.master)" = "1" ] && remoteip=$(uci -q get openmptcprouter.$1.ip | awk '{print $1}') } _openvpnbonding() { From 58eb27a3440b9db5d57db6dd6940f9836da696ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jan 2021 20:47:14 +0100 Subject: [PATCH 0066/2059] Fix on openmptcprouter-vps with multiples IPs --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 19a7d68bb..853891f9d 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -362,10 +362,11 @@ _get_vps_config() { fi fi fi - vpsip="$(uci -q get openmptcprouter.${servername}.ip)" + vpsip="$(uci -q get openmptcprouter.${servername}.ip | awk '{print $1}')" if [ "$(uci -q get shadowsocks-libev.sss0.server)" != "127.0.0.1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then config_foreach _set_ss_server server "server" $vpsip uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.sss0.server="$vpsip" commit shadowsocks-libev EOF if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" = "0" ]; then @@ -1033,7 +1034,9 @@ _set_ss_server() { elif [ "$value" = "false" ]; then value=0 fi - [ "$(echo $1 | grep omr)" != "" ] && uci -q set shadowsocks-libev.$1.$option=$value + if [ "$(echo $1 | grep omr)" != "" ] || [ "$(echo $1 | grep sss)" ]; then + uci -q set shadowsocks-libev.$1.$option=$value + fi } _set_config_from_vps() { @@ -1044,7 +1047,7 @@ _set_config_from_vps() { logger -t "OMR-VPS" "Get config from server ${servername}..." noerror=1 # get VPS ip - vpsip="$(uci -q get openmptcprouter.${servername}.ip)" + vpsip="$(uci -q get openmptcprouter.${servername}.ip | awk '{print $1}')" vps_lastchange="$(echo "$vps_config" | jsonfilter -q -e '@.vps.lastchange')" lastchange="$(uci -q get openmptcprouter.${servername}.lastchange)" [ -z "$lastchange" ] && lastchange=0 From 6a9ec1d08cf728ab56af64e9a6451cb34b487871 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jan 2021 10:50:57 +0100 Subject: [PATCH 0067/2059] Display ipv6 parameters only if IPv6 is enabled --- .../luasrc/view/openmptcprouter/wizard.htm | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index d966771d9..e1fb06c4c 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -57,19 +57,13 @@
    - " data-optional="false"> + " data-optional="false"> + " data-optional="false">
    <%:Server IP will be set for proxy and VPN%>
    -
    -
    -
    -
    - -
    - " data-optional="false">
    - <%:Server IP will be set for proxy and VPN%> + <%:A secondary server IP can be set for dual IPv4/IPv6 server contact if WAN IPv6 are set%>
    @@ -157,7 +151,7 @@
    - @@ -621,7 +615,7 @@ <% else %> -
    +
    @@ -631,7 +625,7 @@
    -
    +
    " data-type="ip6addr"> From 76265b24bd9f5187d24f4a644e0e0e2bdc418af6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jan 2021 10:51:21 +0100 Subject: [PATCH 0068/2059] Add -tt as SSH arg --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8ebdbeb63..a837a7293 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -98,6 +98,7 @@ jobs: user: deploy port: ${{ secrets.OMR_DEPLOY_PORT }} key: ${{ secrets.PRIVATE_KEY }} + args: -tt - if: steps.branch_name.outputs.SOURCE_BRANCH != '' name: Deploy - Create directory uses: ysurac/ssh-action@master @@ -112,6 +113,7 @@ jobs: user: deploy port: ${{ secrets.OMR_DEPLOY_PORT }} key: ${{ secrets.PRIVATE_KEY }} + args: -tt - name: Move binaries for rsync working-directory: ../../omr env: From db48ca879438b59b22a5c07b3db90e18a50a731c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jan 2021 10:52:07 +0100 Subject: [PATCH 0069/2059] Add default ip route for wan --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 9c51d7b7c..eb495ac43 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -872,6 +872,9 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route server fi + if [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + ip r replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 + fi fi if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then config_load openmptcprouter @@ -881,6 +884,9 @@ if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; th elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route6 server fi + if [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 + fi fi if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then From bea2f5f6298b037bddc14aa98f2edf3068d05ad2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jan 2021 14:31:44 +0100 Subject: [PATCH 0070/2059] Add mac address to OMR Rename ident --- .../root/etc/hotplug.d/net/99-omr-rename | 15 ++++++++++----- .../root/etc/init.d/openmptcprouter | 12 ++++++++++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename index f2c19dc55..4ff952d0e 100644 --- a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename +++ b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename @@ -20,17 +20,22 @@ _set_intf_name() { fi [ -n "$modalias" ] && { if [ -f /sys/class/net/${INTERFACE}/device/uevent ]; then + mac="" + if [ -f /sys/class/net/${INTERFACE}/address ]; then + mac="$(cat /sys/class/net/${INTERFACE}/address | tr -d '\n')" + fi chk_modalias=$MODALIAS [ -z "$chk_modalias" ] && chk_modalias="$(cat /sys/class/net/${INTERFACE}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')" if [ -n "$chk_modalias" ]; then + chk_modalias="${chk_modalias}-${mac}" logger -t "OMR-Rename" "modalias: $modalias - chk_modalias: $chk_modalias - ifname: $ifname - INTERFACE: $INTERFACE" if [ "$modalias" = "$chk_modalias" ] && [ "$INTERFACE" != "$ifname" ]; then logger -t "OMR-Rename" "Rename ${INTERFACE} to ${ifname}" - existif=0 + existif="0" ip link set ${INTERFACE} down 2>&1 >/dev/null [ "$(ip link show ${ifname} 2>/dev/null)" != "" ] && { ip link set ${ifname} name ${ifname}tmp 2>&1 >/dev/null - existif=1 + existif="1" } ip link set ${INTERFACE} name ${ifname} 2>&1 >/dev/null ip link set ${ifname} up 2>&1 >/dev/null @@ -48,10 +53,10 @@ _set_intf_name() { logger -t "OMR-Rename" "device: $device - devpath: $DEVPATH - ifname: $ifname - INTERFACE: $INTERFACE" logger -t "OMR-Rename" "Rename ${INTERFACE} to ${ifname}" ip link set ${INTERFACE} down 2>&1 >/dev/null - existif=0 + existif="0" [ "$(ip link show ${ifname} 2>/dev/null)" != "" ] && { ip link set ${ifname} name ${ifname}tmp 2>&1 >/dev/null - existif=1 + existif="1" } ip link set ${INTERFACE} name ${ifname} 2>&1 >/dev/null ip link set ${ifname} up 2>&1 >/dev/null @@ -62,5 +67,5 @@ _set_intf_name() { if [ "$(uci -q get openmptcprouter.settings.disableintfrename)" != "1" ]; then config_load network config_foreach _set_intf_name interface - config_foreach _set_intf_name interface +# config_foreach _set_intf_name interface fi \ No newline at end of file diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 44188939f..decb1fdcc 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -27,7 +27,11 @@ omr_intf_set() { if [ "$type" != "macvlan" ] && [ -n "$ifname" ] && [ -f /sys/class/net/${ifname}/device/uevent ]; then devicepath=$(readlink -f /sys/class/net/${ifname}) if [ -n "$devicepath" ] && [ "$(echo ${devicepath} | grep virtual)" = "" ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" != "" ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PCI_SLOT_NAME)" = "" ]; then - uci -q set network.$1.modalias="$(cat /sys/class/net/${ifname}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')" + mac="" + if [ -f /sys/class/net/${ifname}/address ]; then + mac="$(cat /sys/class/net/${ifname}/address | tr -d '\n')" + fi + uci -q set network.$1.modalias="$(cat /sys/class/net/${ifname}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')-$mac" uci -q set network.$1.product="$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT | cut -d '=' -f2 | tr -d '\n')" elif [ -n "$devicepath" ] && ([ "$(echo ${devicepath} | grep virtual)" != "" ] || [ "$(echo ${devicepath} | grep virtual)" = "" ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" = "" ] || [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PCI_SLOT_NAME)" != "" ] || [ "$(cat /sys/class/net/${ifname}tmp/device/uevent)" != "" ]); then uci -q delete network.$1.device @@ -35,7 +39,11 @@ omr_intf_set() { uci -q delete network.$1.product fi elif [ "$type" != "macvlan" ] && [ -n "$device" ] && [ -f /sys/bus/usb-serial/devices/${devicename}/device/uevent ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" != "" ]; then - uci -q set network.$1.modalias="$(cat /sys/bus/usb-serial/devices/${devicename}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')" + mac="" + if [ -f /sys/class/net/${ifname}/address ]; then + mac="$(cat /sys/class/net/${ifname}/address | tr -d '\n')" + fi + uci -q set network.$1.modalias="$(cat /sys/bus/usb-serial/devices/${devicename}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')-$mac" uci -q set network.$1.product="$(cat /sys/bus/usb-serial/devices/${devicename}/device/uevent | grep PRODUCT | cut -d '=' -f2 | tr -d '\n')" else uci -q delete network.$1.modalias From 51cae2dac9dc6a4eea9e978fbdf110625b649115 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jan 2021 17:28:57 +0100 Subject: [PATCH 0071/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/1547 --- openmptcprouter/files/bin/omr-test-speed | 10 +++++++--- openmptcprouter/files/bin/omr-test-speedv6 | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index b01279773..c38fcd9e4 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -27,8 +27,12 @@ if [ -z "$INTERFACE" ]; then curl -4 $HOST >/dev/null || echo else domain=$(echo $HOST | awk -F/ '{print $3}') - hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr -d "\n") - ipset add ss_rules_dst_bypass_all $hostip + hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ') + for ip in $hostip; do + ipset add ss_rules_dst_bypass_all $ip + done curl -4 --interface $INTERFACE $HOST >/dev/null || echo - ipset del ss_rules_dst_bypass_all $hostip + for ip in $hostip; do + ipset del ss_rules_dst_bypass_all $ip + done fi diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index 27fd43e68..b80399e5c 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -27,8 +27,12 @@ if [ -z "$INTERFACE" ]; then curl -6 $HOST >/dev/null || echo else domain=$(echo $HOST | awk -F/ '{print $3}') - hostip=$(dig +nocmd +noall +answer AAAA $domain | grep -v CNAME | awk '{print $5}' | tr -d "\n") - ipset add ss_rules6_dst_bypass_all $hostip + hostip=$(dig +nocmd +noall +answer AAAA $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ') + for ip in $hostip; do + ipset add ss_rules6_dst_bypass_all $ip + done curl -6 --interface $INTERFACE $HOST >/dev/null || echo - ipset del ss_rules6_dst_bypass_all $hostip + for ip in $hostip; do + ipset del ss_rules6_dst_bypass_all $ip + done fi From 3a28ad66e5e4c39f33ced6e0808c96aeae81e522 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jan 2021 17:29:28 +0100 Subject: [PATCH 0072/2059] Add VLAN support in wizard --- .../luasrc/controller/openmptcprouter.lua | 4 ++++ .../luasrc/view/openmptcprouter/wizard.htm | 24 ++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 62974d55b..4f06cff5b 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -220,6 +220,7 @@ function wizard_add() local typeintf = luci.http.formvalue("cbid.network.%s.type" % intf) or "" local masterintf = luci.http.formvalue("cbid.network.%s.masterintf" % intf) or "" local ifname = luci.http.formvalue("cbid.network.%s.intf" % intf) or "" + local vlan = luci.http.formvalue("cbid.network.%s.vlan" % intf) or "" local device_ncm = luci.http.formvalue("cbid.network.%s.device.ncm" % intf) or "" local device_qmi = luci.http.formvalue("cbid.network.%s.device.qmi" % intf) or "" local device_modemmanager = luci.http.formvalue("cbid.network.%s.device.modemmanager" % intf) or "" @@ -244,6 +245,9 @@ function wizard_add() end ucic:set("network",intf,"type",typeintf) end + if vlan ~= "" then + ifname=ifname .. '.' .. vlan + end if typeintf == "macvlan" and masterintf ~= "" then ucic:set("network",intf,"type","macvlan") ucic:set("network",intf,"masterintf",masterintf) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index e1fb06c4c..ad0762c8d 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -21,6 +21,17 @@ end return true end + function splitstring(inputstr, sep) + if sep == nil then + sep = "%s" + end + local t={} + for str in string.gmatch(inputstr, "([^"..sep.."]+)") do + table.insert(t, str) + end + return t + end + %> @@ -537,20 +548,27 @@ +
    + +
    +
    <%:Choose physical interface.%> @@ -885,7 +903,7 @@ end end for _, ifacea in ipairs(net:get_networks()) do - if not (ifacea:name() == "loopback" or ifacea:name() == "omr6in4" or ifacea:name() == "omrvpn" or ifacea:name():match("^omrip.*")) then + if not (ifacea:name() == "loopback" or ifacea:name() == "lan" or ifacea:name() == "omr6in4" or ifacea:name() == "omrvpn" or ifacea:name():match("^omrip.*")) then %> <% From d2aeaf3c2bbadfa0fffe8fbfaa90e735bd089665 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 Feb 2021 16:21:02 +0100 Subject: [PATCH 0073/2059] Update RPI4 firmware --- bcm27xx-eeprom/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bcm27xx-eeprom/Makefile b/bcm27xx-eeprom/Makefile index 8397130ae..6a4dda9b4 100644 --- a/bcm27xx-eeprom/Makefile +++ b/bcm27xx-eeprom/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-eeprom -PKG_VERSION:=16bb29427f96dc8276a7102c0526154a1084bffd -PKG_RELEASE:=3 +PKG_VERSION:=3d6165304cb04bda4454e460dea791b5f92a122a +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/rpi-eeprom/tar.gz/$(PKG_VERSION)? -PKG_HASH:=9bf42edbcd5ce38538750860c3c788af435206aa441b7d78cf88d094631dbb14 +PKG_HASH:=d6f25e3d962ea3c770ca1af78466371c47970381b48fb7c2acaf838966d327fc PKG_LICENSE:=BSD-3-Clause Custom PKG_LICENSE_FILES:=LICENSE From 9432081ec4a42978155c135709a74bfe1278612f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 Feb 2021 16:21:58 +0100 Subject: [PATCH 0074/2059] Fix wizard --- .../luasrc/controller/openmptcprouter.lua | 5 ++++- .../luasrc/view/openmptcprouter/wizard.htm | 14 ++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 4f06cff5b..d64b41986 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -246,7 +246,7 @@ function wizard_add() ucic:set("network",intf,"type",typeintf) end if vlan ~= "" then - ifname=ifname .. '.' .. vlan + ifname = ifname .. '.' .. vlan end if typeintf == "macvlan" and masterintf ~= "" then ucic:set("network",intf,"type","macvlan") @@ -905,6 +905,9 @@ function settings_add() -- Enable/disable debug local debug = luci.http.formvalue("debug") or "0" ucic:set("openmptcprouter","settings","debug",debug) + ucic:foreach("shadowsocks-libev", "ss_redir", function (section) + ucic:set("shadowsocks-libev",section[".name"],"verbose",debug) + end) -- Enable/disable vnstat backup local savevnstat = luci.http.formvalue("savevnstat") or "0" diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index ad0762c8d..24c67a126 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -549,26 +549,24 @@ <% iffind=0 uciifname=uci:get("network",ifname,"ifname") - ifname=splitstring(uciifname,'.')[1] or "" + realifname=splitstring(uciifname,'.')[1] or "" vlan=splitstring(uciifname,'.')[2] or "" for _, ifacea in ipairs(ifaces) do if not (ifacea == "lo" or ifacea == "6in4-omr6in4" or ifacea == "mlvpn0" or ifacea:match("^ifb.*") or ifacea:match("^sit.*") or ifacea:match("^gre.*") or ifacea:match("^ip6.*") or ifacea:match("^teql.*") or ifacea:match("^erspan.*") or ifacea:match("^tun.*")) and device_notvirtual(ifacea) then %> - + <% end end - if iffind == 0 and uci:get("network",ifname,"ifname") ~= nil then + if iffind == 0 and uciifname ~= nil then %> - + <% end %> -
    - -
    - + +
    <%:Choose physical interface.%> From 499481490bd47d1ade6f325d99ef3b78d073a9ba Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 Feb 2021 16:22:47 +0100 Subject: [PATCH 0075/2059] Separate rules for bypass --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 82a1e68f5..a859b345e 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -375,13 +375,25 @@ _bypass_proto() { _intf_rule_ss_rules() { rule_name=$1 [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep ssr | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$(iptables-save | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I ssr_${rule_name}_dst 2 -m mark --mark 0x539$count -j RETURN + COMMIT + EOF + fi + if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$(iptables-save | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then + iptables-restore -w --wait=60 --noflush <<-EOF + *nat -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539$count -j RETURN + COMMIT + EOF + fi + if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then + iptables-restore -w --wait=60 --noflush <<-EOF + *nat -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539$count -j RETURN COMMIT @@ -493,6 +505,7 @@ _intf_rule() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I omr-bypass-local 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count COMMIT EOF fi From 334fefc2b722b0f3fd0b3c4d870450f986d42c62 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 Feb 2021 16:24:37 +0100 Subject: [PATCH 0076/2059] Add translation option to sysupgrade --- .../luasrc/view/sysupgrade.htm | 12 +++++----- .../www/luci-static/resources/sysupgrade.js | 23 ++++++++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/luci-app-sysupgrade/luasrc/view/sysupgrade.htm b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm index ac91611ad..7cb1efa9d 100644 --- a/luci-app-sysupgrade/luasrc/view/sysupgrade.htm +++ b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm @@ -75,7 +75,7 @@ <%+header%>

    <%:Sysupgrade%>

    - Easily search and install new releases and package upgrades. Sysupgrade firmware are created on demand based on locally installed packages. + <%:Easily search and install new releases and package upgrades.%>
    @@ -87,27 +87,27 @@
    - +
    diff --git a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js index 68d53bf8f..bfb2a83ba 100644 --- a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js +++ b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js @@ -1,3 +1,4 @@ +'require ui'; function $(s) { return document.getElementById(s.substring(1)); } @@ -161,7 +162,7 @@ function upgrade_check() { var candidates = [] hide("#status_box"); hide("#server_div"); - set_status("info", "Searching for upgrades", true); + set_status("info", _("Searching for upgrades"), true); fetch(data.url + "/api/versions") .then(response => response.json()) .then(response => { @@ -188,7 +189,7 @@ function upgrade_check() { if (candidates.length > 0) { var info_output = "

    New release " + candidates[0].latest + " available

    " - info_output += "Installed version: " + data.release.version + info_output += _('Installed version:') + " " + data.release.version // tell server the currently installed version request_dict.current_version = request_dict.version; @@ -205,13 +206,13 @@ function upgrade_check() { show("#edit_button"); } var upgrade_button = $("#upgrade_button") - upgrade_button.value = "Request firmware"; + upgrade_button.value = _("Request firmware"); upgrade_button.style.display = "block"; upgrade_button.disabled = false; upgrade_button.onclick = upgrade_request; } else { - set_status("success", "No upgrades available") + set_status("success", _("No upgrades available")) } }); @@ -265,7 +266,7 @@ function upgrade_request_callback(response) { function flash_image() { // Flash image via rpc-sys upgrade_start - set_status("warning", "Flashing firmware. Don't unpower device", true) + set_status("warning", _("Flashing firmware. Don't unpower device"), true) ubus_call("rpc-sys", "upgrade_start", { "keep": $("#keep").checked }, 'message'); @@ -281,11 +282,11 @@ function ping_ubus() { var request = new XMLHttpRequest(); request.open("GET", ubus_url, true); request.addEventListener('error', function(event) { - set_status("warning", "Rebooting device - please wait!", true); + set_status("warning", _("Rebooting device - please wait!"), true); setTimeout(ping_ubus, 5000) }); request.addEventListener('load', function(event) { - set_status("success", "Success! Please reload web interface"); + set_status("success", _("Success! Please reload web interface")); $("#upgrade_button").value = "Reload page"; show("#upgrade_button"); $("#upgrade_button").disabled = false; @@ -295,13 +296,13 @@ function ping_ubus() { }); request.send(); } else { - set_status("danger", "Web interface could not reconnect to your device. Please reload web interface or check device manually") + set_status("danger", _("Web interface could not reconnect to your device. Please reload web interface or check device manually")) } } function upload_image(blob) { // Uploads received blob data to the server using cgi-io - set_status("info", "Uploading firmware to device", true); + set_status("info", _("Uploading firmware to device"), true); var request = new XMLHttpRequest(); var form_data = new FormData(); @@ -316,7 +317,7 @@ function upload_image(blob) { }); request.addEventListener('error', function(event) { - set_status("danger", "Upload of firmware failed, please retry by reloading web interface") + set_status("danger", _("Upload of firmware failed, please retry by reloading web interface")) }); request.open('POST', origin + '/cgi-bin/cgi-upload'); @@ -340,7 +341,7 @@ function download_image() { upload_image(blob) } }; - set_status("info", "Downloading firmware to web browser memory", true); + set_status("info", _("Downloading firmware to web browser memory"), true); download_request.send(); } From 72f75b823b96863595e920ed44f23fc89b86762b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 2 Feb 2021 10:32:40 +0100 Subject: [PATCH 0077/2059] Add sysupgrade translation template --- .../po/templates/attendedsysupgrade.pot | 11 --- .../po/templates/sysupgrade.pot | 81 +++++++++++++++++++ 2 files changed, 81 insertions(+), 11 deletions(-) delete mode 100644 luci-app-sysupgrade/po/templates/attendedsysupgrade.pot create mode 100644 luci-app-sysupgrade/po/templates/sysupgrade.pot diff --git a/luci-app-sysupgrade/po/templates/attendedsysupgrade.pot b/luci-app-sysupgrade/po/templates/attendedsysupgrade.pot deleted file mode 100644 index c14f0951e..000000000 --- a/luci-app-sysupgrade/po/templates/attendedsysupgrade.pot +++ /dev/null @@ -1,11 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" - -#: applications/luci-app-attendedsysupgrade/luasrc/view/attendedsysupgrade.htm:76 -#: applications/luci-app-attendedsysupgrade/root/usr/share/luci/menu.d/luci-app-attendedsysupgrade.json:3 -msgid "Attended Sysupgrade" -msgstr "" - -#: applications/luci-app-attendedsysupgrade/root/usr/share/rpcd/acl.d/attendedsysupgrade.json:3 -msgid "attended sysupgrade via rpcd and luci" -msgstr "" diff --git a/luci-app-sysupgrade/po/templates/sysupgrade.pot b/luci-app-sysupgrade/po/templates/sysupgrade.pot new file mode 100644 index 000000000..0c4a913f0 --- /dev/null +++ b/luci-app-sysupgrade/po/templates/sysupgrade.pot @@ -0,0 +1,81 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:110 +msgid "Search for upgrades" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:103 +msgid "Server:" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "" From 78799489c88998391e14178bdc8cdd68f69955b1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 11:02:08 +0100 Subject: [PATCH 0078/2059] Fix wizard shadowsocks server enable --- .../luasrc/controller/openmptcprouter.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index d64b41986..859252e71 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -477,7 +477,9 @@ function wizard_add() ucic:set("v2ray","main","enabled","0") ucic:foreach("shadowsocks-libev", "server", function(s) local sectionname = s[".name"] - ucic:set("shadowsocks-libev",sectionname,"disabled","0") + if sectionname:match("^sss.*") then + ucic:set("shadowsocks-libev",sectionname,"disabled","0") + end end) elseif default_proxy == "v2ray" and serversnb > 0 and serversnb > disablednb then --ucic:set("shadowsocks-libev","sss0","disabled","1") @@ -543,7 +545,7 @@ function wizard_add() local nbip = 0 for _, ssip in pairs(server_ips) do ucic:set("shadowsocks-libev","sss" .. nbip,"server",ssip) - if default_proxy == "shadowsocks" then + if default_proxy == "shadowsocks" and serversnb > disablednb then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end nbip = nbip + 1 @@ -573,7 +575,7 @@ function wizard_add() local nbip = 0 for _, ssip in pairs(server_ips) do ucic:set("shadowsocks-libev","sss" .. nbip,"server",ssip) - if default_proxy == "shadowsocks" then + if default_proxy == "shadowsocks" and serversnb > disablednb then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end nbip = nbip + 1 From bdbdc201ec632dbfabdc948b28ecc0eff860c6b8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 11:03:03 +0100 Subject: [PATCH 0079/2059] Fix shadowsocks iptables rules --- shadowsocks-libev/files/shadowsocks-libev.init | 4 +++- shadowsocks-libev/files/ss-rules | 2 +- shadowsocks-libev/files/ss-rules6 | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 9e15c6241..fa1b1602d 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -308,6 +308,7 @@ start_service() { # Add rule to match traffic marked by firewall for bypass ip rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 rules_up + [ -f /etc/firewall.gre-tunnel ] && sh /etc/firewall.gre-tunnel > /dev/null 2>&1 } stop_service() { @@ -320,7 +321,7 @@ reload_service() { } rules_exist() { - [ -n "$(iptables -t nat -L -n | grep ssr)" ] && return 0 + [ -n "$(iptables-save | grep 'A ssr')" ] && return 0 return 1 } @@ -347,6 +348,7 @@ rules_up() { config_foreach ss_rules_restart "$cfgtype" "$cfgtype" done config_foreach ss_rules ss_rules + [ -z "$(iptables-save | grep :ssr)" ] && logger -t "Shadowsocks" "Rules not applied" [ -f /etc/init.d/omr-bypass ] && { logger -t "Shadowsocks" "Reload omr-bypass rules" /etc/init.d/omr-bypass reload_rules diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 396de706d..2f4583e47 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -187,7 +187,7 @@ ss_rules_iptchains_init_tcp() { forward) local_target=ssr_${rule}_forward ;; bypass|*) return 0;; esac - if [ "$(iptables -t nat -L ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then + if [ "$(iptables-save | grep ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then iptables-restore -w --noflush <<-EOF *nat :ssr_${rule}_local_out - diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index 84d04beb5..3225573a1 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -175,7 +175,7 @@ ss_rules6_iptchains_init_tcp() { :ssr6_${rule}_local_out - -I OUTPUT 1 -p tcp -j ssr6_${rule}_local_out -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass dst -j RETURN - -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass_all dst -j RETURN + -A ssr6_${rule}_local_out -m set --match-set ss_rules6_dst_bypass_all dst -j RETURN -A ssr6_${rule}_local_out -m set --match-set ssr6_${rule}_dst_bypass_ dst -j RETURN -A ssr6_${rule}_local_out -m mark --mark 0x6539 -j RETURN -A ssr6_${rule}_local_out -p tcp $o_ipt_extra -j $local_target -m comment --comment "local_default: $o_local_default" From 398d47d1fd20f235502ac15c03896d9b2847dee9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 11:08:05 +0100 Subject: [PATCH 0080/2059] Add nano --- openmptcprouter-full/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 74968b5c8..f5b008643 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -50,6 +50,7 @@ MY_DEPENDS := \ speedtestc \ iftop \ htop \ + nano \ tcpdump \ ethtool \ iputils-ping \ From e90e6eab51a3b1752ff52a355065afcc50522848 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 11:09:33 +0100 Subject: [PATCH 0081/2059] Add sss1 server for secondary server ip and rename ss_redir hi to hi1 --- .../etc/uci-defaults/1930-omr-shadowsocks | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks index 69da0ea91..8460546c3 100755 --- a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks +++ b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks @@ -1,6 +1,13 @@ #!/bin/sh # Copyright (C) 2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter project +if [ "$(uci -q get shadowsocks-libev.hi)" != ""; then + uci -q batch <<-EOF >/dev/null + rename shadowsocks-libev.hi="hi1" + commit shadowsocks-libev + EOF +fi + if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then NBCPU=$(grep -c '^processor' /proc/cpuinfo | tr -d "\n") if [ "$NBCPU" -gt 2 ]; then @@ -26,24 +33,16 @@ if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then fi fi - if [ "$(uci -q get shadowsocks-libev.hi.timeout)" != "1000" ]; then - uci -q batch <<-EOF > /dev/null - set shadowsocks-libev.hi.timeout=1000 - commit shadowsocks-libev - EOF - for c in $(seq 2 $NBCPU); do + if [ "$(uci -q get shadowsocks-libev.hi1.timeout)" != "1000" ]; then + for c in $(seq 1 $NBCPU); do uci -q batch <<-EOF > /dev/null set shadowsocks-libev.hi$c.timeout=1000 commit shadowsocks-libev EOF done fi - if [ "$(uci -q get shadowsocks-libev.hi.mode)" != "tcp" ]; then - uci -q batch <<-EOF > /dev/null - set shadowsocks-libev.hi.mode=tcp_and_udp - commit shadowsocks-libev - EOF - for c in $(seq 2 $NBCPU); do + if [ "$(uci -q get shadowsocks-libev.hi1.mode)" != "tcp" ]; then + for c in $(seq 1 $NBCPU); do uci -q batch <<-EOF > /dev/null set shadowsocks-libev.hi$c.mode=tcp_and_udp commit shadowsocks-libev @@ -51,12 +50,16 @@ if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then done fi fi + if [ "$(uci -q get shadowsocks-libev.hi3)" != "" ]; then - port=1101 - for c in $(seq 3 2 $NBCPU); do + port=1100 + for c in $(seq 1 2 $NBCPU); do uci -q batch <<-EOF >/dev/null set shadowsocks-libev.hi$c.local_port=$port + set shadowsocks-libev.hi$c.server=sss0 set shadowsocks-libev.hi$((c+1)).local_port=$port + set shadowsocks-libev.hi$((c+1)).local_address="::" + set shadowsocks-libev.hi$((c+1)).server=sss1 commit shadowsocks-libev EOF port=$((port+1)) @@ -70,9 +73,9 @@ fi if [ "$(uci -q get shadowsocks-libev.hi.obfs)" = "1" ]; then uci -q batch <<-EOF > /dev/null set shadowsocks-libev.sss0.obfs=1 - set shadowsocks-libev.sss0.obfs_plugin="$(uci -q get shadowsocks-libev.hi.obfs_plugin)" - set shadowsocks-libev.sss0.obfs_host="$(uci -q get shadowsocks-libev.hi.obfs_host)" - set shadowsocks-libev.sss0.obfs_type="$(uci -q get shadowsocks-libev.hi.obfs_type)" + set shadowsocks-libev.sss0.obfs_plugin="$(uci -q get shadowsocks-libev.hi1.obfs_plugin)" + set shadowsocks-libev.sss0.obfs_host="$(uci -q get shadowsocks-libev.hi1.obfs_host)" + set shadowsocks-libev.sss0.obfs_type="$(uci -q get shadowsocks-libev.hi1.obfs_type)" commit shadowsocks-libev EOF fi @@ -85,12 +88,23 @@ if [ "$(uci -q get shadowsocks-libev.ss_rules.server)" = "" ]; then fi -if [ "$(uci -q get ucitrack.@shadowsocks-libev[*1].affects | grep openmptcprouter-vps)" = "" ]; then +if [ "$(uci -q get ucitrack.@shadowsocks-libev[-1].affects | grep openmptcprouter-vps)" = "" ]; then uci -q batch <<-EOF >/dev/null add_list ucitrack.@shadowsocks-libev[-1].affects="openmptcprouter-vps" commit ucitrack EOF fi +if [ "$(uci -q get shadowsocks-libev.sss1)" = "" ]; then + uci -q batch <<-EOF > /dev/null + set shadowsocks-libev.sss1=server + set shadowsocks-libev.sss1.server_port='65101' + set shadowsocks-libev.sss1.method='chacha20-ietf-poly1305' + set shadowsocks-libev.sss1.obfs='0' + set shadowsocks-libev.sss1.disabled='1' + commit shadowsocks-libev + EOF +fi + rm -f /tmp/luci-indexcache exit 0 From 29b20d0e98735673c910c7067b6d16961b58f95f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 11:10:01 +0100 Subject: [PATCH 0082/2059] Set FS check by default --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 70beaade9..787763c26 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -8,8 +8,6 @@ uci -q batch <<-EOF >/dev/null commit rpcd set luci.apply.timeout='20' commit luci - set fstab.@global[0].check_fs='1' - commit fstab EOF if [ "$(uci -q get rpcd.@rpcd[0].socket)" != "/var/run/ubus/ubus.sock" ]; then @@ -20,6 +18,10 @@ if [ "$(uci -q get rpcd.@rpcd[0].socket)" != "/var/run/ubus/ubus.sock" ]; then fi /sbin/block detect > /etc/config/fstab +uci -q batch <<-EOF >/dev/null + set fstab.@global[0].check_fs='1' + commit fstab +EOF [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep raspberry)" ] && [ "$(uci -q get openmptcprouter.settings.scaling_governor)" != "performance" ] && { # force CPU speed for RPI From 4be600968078affff2b01ea6f6d3c48102b3fa9c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 11:10:37 +0100 Subject: [PATCH 0083/2059] Fix routes in post tracking --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index eb495ac43..27031e506 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -164,7 +164,7 @@ set_routes_intf() { interface_gw=$(ubus call network.interface.${INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") fi #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ "$(ip route show $serverip | grep $interface_if)" = "" ]; then - if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then + if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -z "$(echo $interface_gw | grep :)" ]; then if [ "$multipath_config_route" = "master" ]; then weight=10 else @@ -827,7 +827,7 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_route_balancing interface config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 0 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show default metric 0 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { + ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 0 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 0 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Set ip route replace default scope global $routesbalancing" ip route replace default scope global metric 0 $routesbalancing } @@ -839,7 +839,7 @@ if [ "$multipath_config" = "master" ]; then } } [ -n "$routesbalancingbackup" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { + ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Set backup ip route replace default scope global $routesbalancingbackup" ip route replace default scope global metric 999 $routesbalancingbackup } From b4013edd0c88d34449cf7beda0c82f6960469ece Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 14:43:22 +0100 Subject: [PATCH 0084/2059] Display ifname if not same as label --- .../luasrc/view/openmptcprouter/wanstatus.htm | 19 +- .../po/templates/openmptcprouter.pot | 489 ++++++++++-------- 2 files changed, 289 insertions(+), 219 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 1aa626cd5..83f601bbf 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -404,17 +404,26 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm } // Populate info var wanip = mArray.wans[i].wanip; - var wanip6 = mArray.wans[i].wanip6; if (anonymize == "true" && testPrivateIP(wanip) == false) { wanip=replaceLastNChars(wanip,"x",6); } + var wanip6 = mArray.wans[i].wanip6; + if (anonymize == "true") + { + wanip6=replaceLastNChars(wanip6,"x",6); + } var ipaddr = mArray.wans[i].ipaddr; - var ip6addr = mArray.wans[i].ip6addr; if (anonymize == "true" && testPrivateIP(ipaddr) == false) { ipaddr=replaceLastNChars(ipaddr,"x",6); } + var ip6addr = mArray.wans[i].ip6addr; + if (anonymize == "true") + { + ip6addr=replaceLastNChars(ip6addr,"x",6); + } + var ifname = mArray.wans[i].ifname; var whois = mArray.wans[i].whois; var whois6 = mArray.wans[i].whois6; var signal = mArray.wans[i].signal; @@ -469,7 +478,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { content += String.format('%s %s
    ','<%:ip address:%>', ipaddr); } - if(ip6addr !== '' && gateway6 != '') + if(ip6addr !== '' && gateway6 !== '') { content += String.format('%s %s
    ','<%:ipv6 address:%>', ip6addr); } @@ -481,6 +490,10 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { content += String.format('%s %s
    ','<%:wan ipv6 address:%>', wanip6); } + if(ifname !== '' && ifname !== mArray.wans[i].label) + { + content += String.format('%s %s
    ','<%:interface:%>', ifname); + } if(whois !== '') { content += String.format('%s %s
    ','<%:whois:%>', whois); diff --git a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot index 4daf598a7..684de3447 100644 --- a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot +++ b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot @@ -1,28 +1,34 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:256 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:274 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:253 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:271 msgid "A Dead Simple VPN key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 +msgid "" +"A secondary server IP can be set for dual IPv4/IPv6 server contact if WAN " +"IPv6 are set" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:88 msgid "API username to retrieve personnalized settings from the server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:654 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:732 msgid "APN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:133 msgid "Add a new server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:912 msgid "Add an interface" msgstr "" @@ -31,11 +37,11 @@ msgstr "" msgid "Advanced Settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:125 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:140 msgid "Advanced settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:351 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -45,18 +51,18 @@ msgstr "" msgid "All router settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:225 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:243 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:680 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:758 msgid "Authentication Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:796 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:812 msgid "Backup" msgstr "" @@ -73,60 +79,60 @@ msgstr "" msgid "Beta" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:296 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:307 msgid "Big time difference between the server and the router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:478 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:496 msgid "Bridge" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:236 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 msgid "By default VPN is used for any traffic that is not TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:170 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:188 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:685 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:763 msgid "CHAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:257 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:268 msgid "Can\\'t access and use server part" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:283 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:294 msgid "Can\\'t contact Server Admin Script" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:284 msgid "Can\\'t get public IP address from ShadowSocks" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:287 msgid "Can\\'t get public IP address from V2Ray" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:270 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:281 msgid "Can\\'t ping server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:482 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:500 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:548 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:434 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:520 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 msgid "Choose physical interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:123 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 msgid "Common server settings" msgstr "" @@ -134,11 +140,15 @@ msgstr "" msgid "Core temp:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:368 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:513 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:386 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:531 msgid "DHCP" msgstr "" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:532 +msgid "DHCPv6" +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:188 msgid "DNS issue: can\\'t resolve hostname" msgstr "" @@ -147,22 +157,22 @@ msgstr "" msgid "Debug" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:172 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 msgid "Default Proxy" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 msgid "Default VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:52 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:63 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 msgid "Delete" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:580 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:628 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:685 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:706 msgid "Device" msgstr "" @@ -211,7 +221,7 @@ msgstr "" msgid "Disable renaming interfaces" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 msgid "Disable server" msgstr "" @@ -227,12 +237,13 @@ msgstr "" msgid "Disable tracebox test" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:716 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:732 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:166 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:810 msgid "Disabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:778 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:856 msgid "Download speed (Kb/s)" msgstr "" @@ -241,11 +252,11 @@ msgid "Dynamic change" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:148 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 msgid "Enable IPv6" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "Enable SQM" msgstr "" @@ -261,16 +272,17 @@ msgstr "" msgid "Enable debug logs" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:731 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:167 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:793 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 msgid "Enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:208 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:226 msgid "Encryption" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "" @@ -278,29 +290,30 @@ msgstr "" msgid "Filesystem is readonly" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:140 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:155 msgid "Force retrieve all keys from server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:150 msgid "Force retrieve settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:752 msgid "GPRS only" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:665 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:552 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:555 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:727 msgid "Gateway DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "Glorytun key" msgstr "" @@ -340,30 +353,40 @@ msgstr "" msgid "IPv4 TCP SYN retries2" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:424 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:442 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:578 msgid "IPv4 address" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 msgid "IPv4 gateway" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:430 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:448 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 msgid "IPv4 netmask" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:158 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:176 msgid "IPv6 Prefix" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:544 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:705 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:635 +msgid "IPv6 address" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:645 +msgid "IPv6 gateway" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:600 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 msgid "IPv6 route received" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:146 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 msgid "IPv6 settings" msgstr "" @@ -371,44 +394,44 @@ msgstr "" msgid "IPv6 tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:336 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:347 msgid "IPv6:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:443 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 msgid "Interfaces settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:193 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:203 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:256 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:268 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:211 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:274 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 msgid "Key is retrieved from server API by default." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:98 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:341 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:359 msgid "LAN interfaces settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:672 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:750 msgid "LTE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:352 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:370 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:481 msgid "Label" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:358 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:468 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:376 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:486 msgid "Label for the interface" msgstr "" @@ -417,42 +440,42 @@ msgid "Last available backup on server:" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:313 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:324 msgid "Latest available version" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:330 msgid "Load:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:263 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:281 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:283 msgid "MLVPN password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:303 msgid "MPTCP is not enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "MPTCP may not be enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:758 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:836 msgid "MPTCP over VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:477 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:495 msgid "MacVLAN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:717 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:795 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:811 msgid "Master" msgstr "" @@ -468,15 +491,15 @@ msgstr "" msgid "Minimum scaling CPU frequency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:747 msgid "Modem default" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:703 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:781 msgid "Modem init timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:533 msgid "ModemManager" msgstr "" @@ -484,43 +507,43 @@ msgstr "" msgid "More than one default VPN is enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:712 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:790 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:806 msgid "Multipath TCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:527 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:533 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:688 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:694 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:583 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:750 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:756 msgid "Multipath current state is" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:683 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:578 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 msgid "Multipath master already defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:507 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:668 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:730 msgid "Multipath seems to be blocked on the connection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:515 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:534 msgid "NCM" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:761 msgid "NONE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:539 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:700 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:595 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:762 msgid "Network interface duplicated" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:800 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:802 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:862 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:864 msgid "Network overview" msgstr "" @@ -528,8 +551,8 @@ msgstr "" msgid "Networks settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:497 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:545 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:720 msgid "No IP defined" msgstr "" @@ -537,15 +560,19 @@ msgstr "" msgid "No IPv6 access" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:511 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:672 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:734 msgid "No Server ping response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:290 msgid "No WAN IP address detected in less than 1 second" msgstr "" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:619 +msgid "No WAN with multipath enabled:" +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:26 msgid "No available backup on server." msgstr "" @@ -554,33 +581,33 @@ msgstr "" msgid "No change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 msgid "No data" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:501 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:662 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:549 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:724 msgid "No gateway defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:248 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:260 msgid "No output" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:253 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:264 msgid "No server IP address, No WAN IP address" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:266 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:277 msgid "No server defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 msgid "None" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:476 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:494 msgid "Normal" msgstr "" @@ -606,17 +633,17 @@ msgstr "" msgid "On wizard change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:182 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:200 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:722 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:800 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:112 msgid "Only one server can be master, else all servers are set as backup." msgstr "" @@ -624,7 +651,7 @@ msgstr "" msgid "OpenMPTCProuter" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:351 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "" @@ -632,8 +659,8 @@ msgstr "" msgid "Optimize for latency instead of bandwidth" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:369 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:387 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 msgid "Other" msgstr "" @@ -641,46 +668,50 @@ msgstr "" msgid "Other settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:684 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:762 msgid "PAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:686 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:764 msgid "PAP/CHAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:775 msgid "PAP/CHAP password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:769 msgid "PAP/CHAP username" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:660 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:738 msgid "PIN code" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:535 msgid "PPPoE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:381 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:487 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:527 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:505 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:546 msgid "Physical interface" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:670 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:748 msgid "Prefer LTE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 msgid "Prefer UMTS" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:363 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:508 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:71 +msgid "Primary server IP" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:526 msgid "Protocol" msgstr "" @@ -688,15 +719,15 @@ msgstr "" msgid "Proxy is DISABLED" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:187 msgid "Proxy settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 msgid "Proxy traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:517 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:536 msgid "QMI" msgstr "" @@ -708,12 +739,12 @@ msgstr "" msgid "Restore backup" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:133 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:148 msgid "Retrieve settings from server" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:836 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:921 msgid "Save & Apply" msgstr "" @@ -729,7 +760,11 @@ msgstr "" msgid "Scaling governor" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:72 +msgid "Secondary server IP" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:915 msgid "Select the device you want to base the interface on." msgstr "" @@ -737,64 +772,67 @@ msgstr "" msgid "Send backup" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:58 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:60 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:69 msgid "Server IP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:62 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:74 msgid "Server IP will be set for proxy and VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:78 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:80 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 msgid "Server key" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:42 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:53 msgid "Server settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:68 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:70 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 msgid "Server username" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:744 msgid "Service Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:583 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:640 msgid "Set an IP in the same network as the modem" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:575 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:627 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:650 msgid "Set here IP of the modem" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:107 msgid "Set server as master" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:351 msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " "for all traffic if proxy is disabled." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:788 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:866 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:804 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" @@ -807,12 +845,12 @@ msgstr "" msgid "ShadowSocks is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:193 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:211 msgid "ShadowSocks is used for TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:188 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:206 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:208 msgid "ShadowSocks key" msgstr "" @@ -820,8 +858,8 @@ msgstr "" msgid "Show all settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:367 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:512 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:385 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 msgid "Static address" msgstr "" @@ -840,7 +878,7 @@ msgid "" "local end." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:227 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:245 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -859,24 +897,24 @@ msgid "" "retransmissions remain unacknowledged." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:351 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 msgid "Total traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:473 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:491 msgid "Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:275 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:293 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "UBOND password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:673 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:751 msgid "UMTS/GPRS" msgstr "" @@ -893,17 +931,17 @@ msgstr "" msgid "Update server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 msgid "Upload speed (Kb/s)" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:325 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:336 msgid "Uptime:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:783 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:799 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:861 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "" @@ -911,27 +949,32 @@ msgstr "" msgid "V2Ray is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:203 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 msgid "V2Ray is used for TCP and UDP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:200 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:218 msgid "V2Ray user" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:216 msgid "V2Ray user id" msgstr "" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:569 +msgid "VLAN" +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:184 msgid "VPN is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:235 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:253 msgid "VPN settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 msgid "VPN traffic:" msgstr "" @@ -939,12 +982,13 @@ msgstr "" msgid "VPN tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:306 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:317 msgid "Version" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:515 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:676 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:738 msgid "Wan IP and gateway are identical" msgstr "" @@ -955,10 +999,10 @@ msgid "" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 -msgid "When proxy shadowsocks is used, use it for UDP if proxy down" +msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:40 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:51 msgid "Wizard" msgstr "" @@ -967,33 +1011,33 @@ msgstr "" msgid "You" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:763 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:373 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:541 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:153 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:773 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 msgid "You should disable SQM for LTE or any interfaces with variable speed." msgstr "" @@ -1009,7 +1053,7 @@ msgstr "" msgid "address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:675 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:753 msgid "auto" msgstr "" @@ -1017,35 +1061,43 @@ msgstr "" msgid "empty key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:447 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:638 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:495 +msgid "interface:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:479 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:700 msgid "ip address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:459 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:650 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:483 +msgid "ipv6 address:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:507 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:712 msgid "latency:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:463 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:654 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:511 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:716 msgid "mtu:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:551 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:707 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 msgid "multipath:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:467 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:515 msgid "operator:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:218 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:236 msgid "other" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:471 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:519 msgid "phone number:" msgstr "" @@ -1053,21 +1105,26 @@ msgstr "" msgid "range:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:475 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:523 msgid "state:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:610 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:772 msgid "traffic control:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:451 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:642 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:487 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:704 msgid "wan address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:491 +msgid "wan ipv6 address:" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:499 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:503 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:708 msgid "whois:" msgstr "" From 33b9626a33d51f702cb70927ef86a73e7037cfc8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 14:44:00 +0100 Subject: [PATCH 0085/2059] No error if board description not available --- .../luci-static/resources/view/dashboard/include/10_router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js index 5b57f6126..759818be1 100644 --- a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js @@ -368,7 +368,7 @@ return baseclass.extend({ release: { title: _('Firmware Version'), - value: boardinfo.release.description + value: boardinfo.release.description ? boardinfo.release.description : null } }; From 4dd42e32c0ac1d28d3d2f601d1e8432f5bc80327 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 14:44:30 +0100 Subject: [PATCH 0086/2059] Change way to detect if shadowsocks iptables rules applied --- omr-tracker/files/bin/omr-tracker-ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index be0074b01..bffca1732 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -76,7 +76,7 @@ while true; do uci -q set openmptcprouter.omr.ss_${server}="up" uci -q commit openmptcprouter.omr } - if [ -z "$(iptables -t nat -L -n | grep ss_rules)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then + if [ -z "$(iptables-save | grep :ssr)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then _log "Reload Shadowsocks rules" /etc/init.d/shadowsocks-libev rules_up 2> /dev/null _get_ip From c7e9b2aceb4ba7ca630adf4c4930120f396810e1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 14:45:54 +0100 Subject: [PATCH 0087/2059] Set omrvpn as external interface for upnpd --- openmptcprouter/files/etc/uci-defaults/2092-upnpd | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100755 openmptcprouter/files/etc/uci-defaults/2092-upnpd diff --git a/openmptcprouter/files/etc/uci-defaults/2092-upnpd b/openmptcprouter/files/etc/uci-defaults/2092-upnpd new file mode 100755 index 000000000..a89804ab6 --- /dev/null +++ b/openmptcprouter/files/etc/uci-defaults/2092-upnpd @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ "$(uci -q get upnpd.config.external_ifac)" != "omrvpn" ]; then + uci -q batch <<-EOF >/dev/null + set upnpd.config.external_iface=omrvpn + commit upnpd + EOF +fi + +exit 0 From 73f577c515508aa6fb5ff218b2699a9405967bfe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 14:46:30 +0100 Subject: [PATCH 0088/2059] only set dns over https settings on first boot --- openmptcprouter/files/etc/uci-defaults/1940-omr-dns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index 93471310a..662442e18 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -40,7 +40,7 @@ if [ "$(uci -q get dhcp.lan.dhcp_options)" = "" ]; then EOF fi -if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ] && [ "$(uci -q get https-dns-proxy.@https-dns-proxy[0].listen_port)" = "5053" ]; then +if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then # uci -q batch <<-EOF >/dev/null # delete https-dns-proxy.@https-dns-proxy[-1] # delete https-dns-proxy.@https-dns-proxy[-1] From 55d4722aca1dc6877ec24a7a88a1f1c753221ac8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Feb 2021 14:47:12 +0100 Subject: [PATCH 0089/2059] Update copyright --- v2ray-core/files/etc/init.d/v2ray | 2 +- v2ray-core/files/usr/bin/v2ray-rules | 2 +- v2ray-core/files/usr/bin/v2ray-rules6 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index 34acc668b..d7d25942d 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -1,7 +1,7 @@ #!/bin/sh /etc/rc.common # # Copyright 2019-2020 Xingwang Liao -# Copyright 2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Copyright 2020-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter # Licensed to the public under the MIT License. # diff --git a/v2ray-core/files/usr/bin/v2ray-rules b/v2ray-core/files/usr/bin/v2ray-rules index a43b19be7..98978f12e 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules +++ b/v2ray-core/files/usr/bin/v2ray-rules @@ -1,7 +1,7 @@ #!/bin/sh -e # # Copyright (C) 2017 Yousong Zhou -# Copyright (C) 2018-2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter # # The design idea was derived from ss-rules by Jian Chang # diff --git a/v2ray-core/files/usr/bin/v2ray-rules6 b/v2ray-core/files/usr/bin/v2ray-rules6 index b05c70c59..5e1714110 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules6 +++ b/v2ray-core/files/usr/bin/v2ray-rules6 @@ -1,7 +1,7 @@ #!/bin/sh -e # # Copyright (C) 2017 Yousong Zhou -# Copyright (C) 2018-2020 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) # # The design idea was derived from ss-rules by Jian Chang # From 7d9545aa4015567c345f2e7a11534d2c3b4b95eb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Feb 2021 19:47:16 +0100 Subject: [PATCH 0090/2059] Fix for IPv6 in wizard --- .../luasrc/controller/openmptcprouter.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 859252e71..bc7b55188 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -251,7 +251,7 @@ function wizard_add() if typeintf == "macvlan" and masterintf ~= "" then ucic:set("network",intf,"type","macvlan") ucic:set("network",intf,"masterintf",masterintf) - elseif typeintf == "" and ifname ~= "" and (proto == "static" or proto == "dhcp" ) then + elseif typeintf == "" and ifname ~= "" and (proto == "static" or proto == "dhcp" or proto == "dhcpv6") then ucic:set("network",intf,"ifname",ifname) elseif typeintf == "" and device ~= "" and proto == "ncm" then ucic:set("network",intf,"device",device_ncm) @@ -295,6 +295,11 @@ function wizard_add() ucic:set("network",intf,"ip6addr","") ucic:set("network",intf,"ip6gw","") end + + if proto == "dhcpv6" then + ucic:set("network",intf,"reqaddress","try") + ucic:set("network",intf,"reqprefix","auto") + end ucic:delete("openmptcprouter",intf,"lc") ucic:save("openmptcprouter") @@ -437,6 +442,11 @@ function wizard_add() table.insert(aserverips,ip) end end + if disableipv6 == "1" then + if table.getn(aserverips) == 2 then + table.remove(aserverips, 2) + end + end local master = luci.http.formvalue("master") or "" @@ -548,6 +558,9 @@ function wizard_add() if default_proxy == "shadowsocks" and serversnb > disablednb then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end + if disableipv6 == "1" and nbip > 0 then + break + end nbip = nbip + 1 end end @@ -579,6 +592,9 @@ function wizard_add() ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end nbip = nbip + 1 + if disableipv6 == "1" and nbip > 0 then + break + end end end end From f27860f81ffa65a69d9c40498864848633aa59b9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Feb 2021 19:47:47 +0100 Subject: [PATCH 0091/2059] Display only one input for server IP in wizard if IPv6 disabled --- .../luasrc/view/openmptcprouter/wizard.htm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 24c67a126..8ddce55b0 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -65,7 +65,16 @@

    <%=servername%>

    -
    +
    + +
    + " data-optional="false"> +
    + <%:Server IP will be set for proxy and VPN%> +
    +
    +
    +
    " data-optional="false"> From 44b12433567d36c14610e5c5c4eaaab8b8f6d2f6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Feb 2021 19:48:15 +0100 Subject: [PATCH 0092/2059] Add log on omr-tracker-ss --- omr-tracker/files/bin/omr-tracker-ss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index bffca1732..58a17ed5b 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -72,7 +72,7 @@ while true; do if [ "$(curl -s -I -w %{http_code} --socks5 ${proxy} --max-time ${timeout} $host -o /dev/null)" != "000" ]; then nocontact="" [ "${last}" -ge "${retry}" ] || [ "$(uci -q get openmptcprouter.omr.ss_${server})" = "" ] && { - _log "Shadowsocks is up (can contact via http ${host})" + _log "Shadowsocks ${server} is up (can contact via http ${host})" uci -q set openmptcprouter.omr.ss_${server}="up" uci -q commit openmptcprouter.omr } @@ -87,8 +87,8 @@ while true; do last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" [ "${last}" -ge "${retry}" ] && { - if [ -n "$(iptables -t nat -L -n | grep ssr)" ]; then - _log "Shadowsocks is down (can't contact via http ${nocontact})" + if [ -n "$(iptables -w -t nat -L -n | grep ssr)" ]; then + _log "Shadowsocks ${server} is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.ss_${server}="down" uci -q commit openmptcprouter.omr [ "$(uci show openmptcprouter.omr | grep ss | grep up)" = "" ] && /etc/init.d/shadowsocks-libev rules_down 2> /dev/null From a1a7c39923ab4099f4281b6cacbee636e39ae233 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Feb 2021 19:48:56 +0100 Subject: [PATCH 0093/2059] Fix omr-tracker for ss-tracker --- omr-tracker/files/etc/init.d/omr-tracker | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 77765c19c..467817e91 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -139,6 +139,7 @@ _initialize_shadowsocks_tracker() { #redir_tcp=$(uci -q get shadowsocks-libev.ss_rules.redir_tcp) #config_get tracker_server ss_rules server config_get ss_disabled $server disabled 0 + [ "$ss_disabled" = "0" ] && ss_enable="1" [ -z "$(uci -q get shadowsocks-libev.tracker_${server})" ] && [ "$ss_disabled" != "1" ] && { logger -t "omr-tracker" "Create ShadowSock tracker ss_local..." uci -q batch <<-EOF >/dev/null @@ -230,7 +231,7 @@ _gre_tunnel() { } start_service() { - local ss_disabled + local ss_enable=0 logger -t "omr-tracker" "Launching..." config_load shadowsocks-libev config_foreach _initialize_shadowsocks_tracker server @@ -238,7 +239,7 @@ start_service() { config_load network config_foreach _launch_tracker interface - if [ "$ss_disabled" != "1" ]; then + if [ "$ss_enable" = "1" ]; then config_load shadowsocks-libev config_foreach _launch_shadowsocks_tracker ss_local #elif [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ]; then From d77382ac8c7ccb48930aeb64e1ae98c28448313d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Feb 2021 19:49:19 +0100 Subject: [PATCH 0094/2059] Fix openmptcprouter vps login --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 853891f9d..5241b9fbc 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -37,6 +37,7 @@ _login() { [ -z "$auth" ] && return token="$(echo "$auth" | jsonfilter -q -e '@.access_token')" uci -q set openmptcprouter.${servername}.token="$token" + [ -n "$token" ] && break } config_load openmptcprouter config_list_foreach ${servername} ip login_on_server From 9476921bd52050ee1e2ba7454190a041d9007729 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Feb 2021 19:49:59 +0100 Subject: [PATCH 0095/2059] Rename shadowsocks ss-redir from hi to hi1 --- openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks | 4 ++-- shadowsocks-libev/files/shadowsocks-libev.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks index 8460546c3..5880c13b0 100755 --- a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks +++ b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks @@ -3,7 +3,7 @@ if [ "$(uci -q get shadowsocks-libev.hi)" != ""; then uci -q batch <<-EOF >/dev/null - rename shadowsocks-libev.hi="hi1" + rename shadowsocks-libev.hi=hi1 commit shadowsocks-libev EOF fi @@ -70,7 +70,7 @@ if [ "$(uci -q get shadowsocks-libev.hi3)" != "" ]; then EOF fi -if [ "$(uci -q get shadowsocks-libev.hi.obfs)" = "1" ]; then +if [ "$(uci -q get shadowsocks-libev.hi1.obfs)" = "1" ]; then uci -q batch <<-EOF > /dev/null set shadowsocks-libev.sss0.obfs=1 set shadowsocks-libev.sss0.obfs_plugin="$(uci -q get shadowsocks-libev.hi1.obfs_plugin)" diff --git a/shadowsocks-libev/files/shadowsocks-libev.config b/shadowsocks-libev/files/shadowsocks-libev.config index 2bf7def6b..719a9cc85 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.config +++ b/shadowsocks-libev/files/shadowsocks-libev.config @@ -1,4 +1,4 @@ -config ss_redir hi +config ss_redir hi1 option server 'sss0' option local_address '::' option local_port '1100' From d4df42934a426a2acec628fa2f5507c07d765ebc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 6 Feb 2021 08:56:44 +0100 Subject: [PATCH 0096/2059] Fix display when device have a . --- .../luasrc/view/openmptcprouter/wizard.htm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 8ddce55b0..5224df408 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -558,8 +558,13 @@ <% iffind=0 uciifname=uci:get("network",ifname,"ifname") - realifname=splitstring(uciifname,'.')[1] or "" - vlan=splitstring(uciifname,'.')[2] or "" + if uciifname:match("/") then + realifname=uciifname + vlan="" + else + realifname=splitstring(uciifname,'.')[1] or "" + vlan=splitstring(uciifname,'.')[2] or "" + end for _, ifacea in ipairs(ifaces) do if not (ifacea == "lo" or ifacea == "6in4-omr6in4" or ifacea == "mlvpn0" or ifacea:match("^ifb.*") or ifacea:match("^sit.*") or ifacea:match("^gre.*") or ifacea:match("^ip6.*") or ifacea:match("^teql.*") or ifacea:match("^erspan.*") or ifacea:match("^tun.*")) and device_notvirtual(ifacea) then %> From dc66b82252eceb11ad5be31739ded6f46feb99a9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 6 Feb 2021 09:05:02 +0100 Subject: [PATCH 0097/2059] Fix issue with modemmanager in wizard --- .../luasrc/view/openmptcprouter/wizard.htm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 5224df408..ba31c9dd7 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -22,6 +22,9 @@ return true end function splitstring(inputstr, sep) + if inputstr == nil then + return "" + end if sep == nil then sep = "%s" end From e7279f36abc5d8947defe87daf9b3dc2fe91f8f1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Feb 2021 14:34:41 +0100 Subject: [PATCH 0098/2059] Add default information for luci-app-mptcp --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index a69f69e3e..27654e021 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -18,7 +18,7 @@ mtcpck:value(0, translate("disable")) local mtcpck = s:option(ListValue, "mptcp_debug", translate("Multipath Debug")) mtcpck:value(1, translate("enable")) mtcpck:value(0, translate("disable")) -local mtcppm = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager")) +local mtcppm = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager"), translate("Default is fullmesh")) mtcppm:value("default", translate("default")) mtcppm:value("fullmesh", translate("fullmesh")) mtcppm:value("ndiffports", translate("ndiffports")) From 4b68351f4c80b012a36626da9cee9be536779956 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Feb 2021 14:35:14 +0100 Subject: [PATCH 0099/2059] Fix wizard display when IPv6 enabled --- .../luasrc/view/openmptcprouter/wizard.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index ba31c9dd7..317d7051c 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -68,7 +68,7 @@

    <%=servername%>

    -
    +
    " data-optional="false"> @@ -77,7 +77,7 @@
    -
    +
    " data-optional="false"> From 57fff1658e2b6a2179b4a5ea7baa242482b950d3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Feb 2021 14:35:48 +0100 Subject: [PATCH 0100/2059] Track both server IP --- omr-tracker/files/bin/omr-tracker-server | 159 ++++++++++++++--------- 1 file changed, 97 insertions(+), 62 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 5bd212fdb..8c0e7c577 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -37,9 +37,26 @@ _check_server() { done } +_disable_redir() { + local redir=$1 + config_get server $redir server + if [ "$server" = "sss${count}" ]; then + config_set $redir disabled "1" + fi +} + +_enable_redir() { + local redir=$1 + config_get server $redir server + if [ "$server" = "sss${count}" ]; then + config_set $redir disabled "0" + fi +} + _check_master() { local name=$1 local count=0 + local countips=0 config_get master $1 master config_get ip $1 ip config_get port $1 port "65500" @@ -49,39 +66,47 @@ _check_master() { local ip=$1 #_ping_server $ip _check_server $ip $port - [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ] && { - logger -t "OMR-Tracker-Server" "Master server up, set it back" - logger -t "OMR-Tracker-Server" "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n') - $ip" - uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.sss${count}.server=$ip - commit shadowsocks-libev - EOF - if [ "$count" -eq "0" ]; then + if [ "$server_ping" = true ]; then + if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then + logger -t "OMR-Tracker-Server" "Master server ${name} up ($ip), set it back" + #logger -t "OMR-Tracker-Server" "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n') - $ip" uci -q batch <<-EOF >/dev/null - set v2ray.omrout.s_vmess_address=$ip - set v2ray.omrout.s_vless_address=$ip - commit v2ray - set glorytun.vpn.host=$ip - commit glorytun - set dsvpn.vpn.host=$ip - commit dsvpn - set mlvpn.general.host=$ip - commit mlvpn - del openvpn.omr.remote - add_list openvpn.omr.remote=$ip - commit openvpn + set shadowsocks-libev.sss${count}.server=$ip + commit shadowsocks-libev EOF - /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null - /etc/init.d/v2ray restart >/dev/null 2>/dev/null - /etc/init.d/glorytun restart >/dev/null 2>/dev/null - /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null - /etc/init.d/mlvpn restart >/dev/null 2>/dev/null - /etc/init.d/openvpn restart >/dev/null 2>/dev/null - /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + if [ "$count" -eq "0" ]; then + uci -q batch <<-EOF >/dev/null + set v2ray.omrout.s_vmess_address=$ip + set v2ray.omrout.s_vless_address=$ip + commit v2ray + set glorytun.vpn.host=$ip + commit glorytun + set dsvpn.vpn.host=$ip + commit dsvpn + set mlvpn.general.host=$ip + commit mlvpn + del openvpn.omr.remote + add_list openvpn.omr.remote=$ip + commit openvpn + EOF + /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null + /etc/init.d/v2ray restart >/dev/null 2>/dev/null + /etc/init.d/glorytun restart >/dev/null 2>/dev/null + /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null + /etc/init.d/mlvpn restart >/dev/null 2>/dev/null + /etc/init.d/openvpn restart >/dev/null 2>/dev/null + /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + fi + /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null fi - /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null - } - count=$((count+1)) + config_load shadowsocks-libev + config_foreach _enable_redir ss_redir + count=$((count+1)) + else + config_load shadowsocks-libev + config_foreach _disable_redir ss_redir + fi + countips=$((countips+1)) } config_list_foreach $1 ip set_ip break @@ -91,6 +116,7 @@ _check_master() { _check_backup() { local name=$1 local count=0 + local countips=0 config_get backup $1 backup config_get ip $1 ip config_get port $1 port @@ -99,43 +125,52 @@ _check_backup() { set_ip() { #_ping_server $ip _check_server $ip $port - [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" = "$ip" ] && break - [ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ] && { - logger -t "OMR-Tracker-Server" "Use backup server $1 ($ip)" - uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.sss${count}.server=$ip - commit shadowsocks-libev - EOF - if [ "$count" -eq "0" ]; then + #[ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" = "$ip" ] && break + if [ "$server_ping" = true ]; then + if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then + logger -t "OMR-Tracker-Server" "Use backup server $1 ($ip)" uci -q batch <<-EOF >/dev/null - set v2ray.omrout.s_vmess_address=$ip - set v2ray.omrout.s_vless_address=$ip - commit v2ray - set glorytun.vpn.host=$ip - commit glorytun - set dsvpn.vpn.host=$ip - commit dsvpn - set mlvpn.general.host=$ip - commit mlvpn - del openvpn.omr.remote - add_list openvpn.omr.remote=$ip - commit openvpn + set shadowsocks-libev.sss${count}.server=$ip + commit shadowsocks-libev EOF - /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null - /etc/init.d/v2ray restart >/dev/null 2>/dev/null - /etc/init.d/glorytun restart >/dev/null 2>/dev/null - /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null - /etc/init.d/mlvpn restart >/dev/null 2>/dev/null - /etc/init.d/openvpn restart >/dev/null 2>/dev/null - /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + if [ "$count" -eq "0" ]; then + uci -q batch <<-EOF >/dev/null + set v2ray.omrout.s_vmess_address=$ip + set v2ray.omrout.s_vless_address=$ip + commit v2ray + set glorytun.vpn.host=$ip + commit glorytun + set dsvpn.vpn.host=$ip + commit dsvpn + set mlvpn.general.host=$ip + commit mlvpn + del openvpn.omr.remote + add_list openvpn.omr.remote=$ip + commit openvpn + EOF + /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null + /etc/init.d/v2ray restart >/dev/null 2>/dev/null + /etc/init.d/glorytun restart >/dev/null 2>/dev/null + /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null + /etc/init.d/mlvpn restart >/dev/null 2>/dev/null + /etc/init.d/openvpn restart >/dev/null 2>/dev/null + /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + fi + /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null + sleep $waittest fi - /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null - sleep $waittest - break - } - count=$((count+1)) + config_load shadowsocks-libev + config_foreach _enable_redir ss_redir + count=$((count+1)) + else + config_load shadowsocks-libev + config_foreach _disable_redir ss_redir + fi + countips=$((countips+1)) } config_list_foreach $1 ip set_ip + uci -q commit shadowsocks-libev + [ "$server_ping" = true ] && break } } From 5ff2617fcbe04c2bbfdf57ce5c0e2f3b5f1a9322 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Feb 2021 14:36:32 +0100 Subject: [PATCH 0101/2059] omr-test-speed can now work on server side --- openmptcprouter/files/bin/omr-test-speed | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index c38fcd9e4..fa95ff2cc 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -28,11 +28,15 @@ if [ -z "$INTERFACE" ]; then else domain=$(echo $HOST | awk -F/ '{print $3}') hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ') - for ip in $hostip; do - ipset add ss_rules_dst_bypass_all $ip - done + if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then + for ip in $hostip; do + ipset add ss_rules_dst_bypass_all $ip + done + fi curl -4 --interface $INTERFACE $HOST >/dev/null || echo - for ip in $hostip; do - ipset del ss_rules_dst_bypass_all $ip - done + if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then + for ip in $hostip; do + ipset del ss_rules_dst_bypass_all $ip + done + fi fi From bcdd7ac67ba5a26c90cf95d60b8e13b7a8646195 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Feb 2021 14:37:01 +0100 Subject: [PATCH 0102/2059] Fix firewall redirect from public IP to router --- .../files/etc/init.d/openmptcprouter-vps | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 5241b9fbc..f6aee441e 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -804,6 +804,9 @@ _vps_firewall_redirect_port() { config_get src_ip $1 src_ip config_get v2ray $1 v2ray "0" config_get dmz $1 dmz "0" + if [ -z "$src_dport" ] && [ -n "$dest_port" ]; then + src_dport=$dest_port + fi if [ "$dmz" = "1" ] && [ "$src_dport" != "2-64999" ]; then uci -q batch <<-EOF >/dev/null set firewall.${section}.src_dport='2-64999' @@ -971,6 +974,15 @@ _vps_firewall_close_port() { } _set_vps_firewall() { + fw3 -q print | grep 'vpn.* -d' | + while IFS=$"\n" read -r c; do + eval $(echo $c | sed 's/-A/-D/') 2>&1 >/dev/null + newrule=$(echo $c | sed -E -e 's/ -d ([^ ])*//' -e 's/ -s ([^ ])*//') + eval $(echo $newrule | sed 's/-A/-D/') || true + eval $newrule + done + #' + fwservername=$1 [ -z "$servername" ] && servername=$fwservername [ -z "$fwservername" ] && fwservername=$servername @@ -1005,13 +1017,6 @@ _set_vps_firewall() { } set_vps_firewall() { - fw3 -q print | grep 'vpn.* -d' | - while IFS=$"\n" read -r c; do - eval $(echo $c | sed 's/-A/-D/') 2>&1 >/dev/null - newrule=$(echo $c | sed -E -e 's/ -d ([^ ])*//' -e 's/ -s ([^ ])*//') - eval $(echo $newrule | sed 's/-A/-C/') || eval $newrule - done - #' config_load openmptcprouter config_foreach _set_vps_firewall server } From 96283d0252ecab05e3525ed2a6640c9dbc44243a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Feb 2021 15:29:41 +0100 Subject: [PATCH 0103/2059] Force firewall network to be a list --- .../luasrc/controller/openmptcprouter.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index bc7b55188..453b69479 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -36,6 +36,15 @@ end function wizard_add() local gostatus = true + + -- Force WAN zone firewall members to be a list + local fwwan = sys.exec("uci -q get firewall.@zone[1].network") + luci.sys.call("uci -q delete firewall.@zone[1].network") + for interface in fwwan:gmatch("%S+") do + luci.sys.call("uci -q add_list firewall.@zone[1].network=" .. interface) + end + ucic:save("firewall") + -- Add new server local add_server = luci.http.formvalue("add_server") or "" local add_server_name = luci.http.formvalue("add_server_name") or "" @@ -190,7 +199,9 @@ function wizard_add() for intf, _ in pairs(delete_intf) do local defif = ucic:get("network",intf,"ifname") ucic:delete("network",intf) - ucic:delete("network",intf .. "_dev") + if ucic:get("network",intf .. "_dev") ~= "" then + ucic:delete("network",intf .. "_dev") + end ucic:save("network") ucic:commit("network") ucic:delete("sqm",intf) From ed8fa2811538dd2a3a817abe44d2f3792f4c5ebe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Feb 2021 21:12:55 +0100 Subject: [PATCH 0104/2059] Fix wizard display --- .../luasrc/view/openmptcprouter/wizard.htm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 317d7051c..0e7e838a6 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -68,7 +68,7 @@

    <%=servername%>

    -
    +
    " data-optional="false"> @@ -77,7 +77,7 @@
    -
    +
    " data-optional="false"> @@ -86,12 +86,12 @@ <%:Server IP will be set for proxy and VPN%>
    - <%:A secondary server IP can be set for dual IPv4/IPv6 server contact if WAN IPv6 are set%> + <%:A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set%>

    -
    +
    " data-optional="false"> @@ -101,7 +101,7 @@
    -
    +
    " data-optional="false"> @@ -115,7 +115,7 @@ if nbserver > 1 then %>
    -
    +
    checked<% end %>/> @@ -129,7 +129,7 @@ end %>
    -
    +
    checked<% end %>/> From bbc373d1577709eb0cb674498a7075da6bfe9067 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Feb 2021 21:13:57 +0100 Subject: [PATCH 0105/2059] Check gateway using ping from interface --- .../root/usr/libexec/rpcd/openmptcprouter | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index b80a81a7d..bc36f9649 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1232,7 +1232,12 @@ function interfaces_status() if gateway ~= "" or gateway6 ~= "" then if uci:get("openmptcprouter", "settings", "disablegwping") ~= "1" and connectivity ~= "ERROR" then if gateway ~= "" then - local gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway .. " | grep '100% packet loss'")) + local gw_ping_test = "" + if ifname ~= "" and ifname ~= nil then + gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 -I " .. ifname .. " " .. gateway .. " | grep '100% packet loss'")) + else + gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway .. " | grep '100% packet loss'")) + end if gw_ping_test ~= "" then gw_ping = "DOWN" if connectivity == "OK" then @@ -1241,7 +1246,12 @@ function interfaces_status() end end if gateway6 ~= "" then - local gw_ping6_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway6 .. " | grep '100% packet loss'")) + local gw_ping6_test = "" + if ifname ~= "" and ifname ~= nil then + gw_ping6_test = ut.trim(sys.exec("ping -w 1 -c 1 -I " .. ifname .. " " .. gateway6 .. " | grep '100% packet loss'")) + else + gw_ping6_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway6 .. " | grep '100% packet loss'")) + end if gw_ping6_test ~= "" then gw_ping6 = "DOWN" if connectivity == "OK" then From f6cfd19828bc08fd48f4f177ce2c8769937fe945 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Feb 2021 21:15:04 +0100 Subject: [PATCH 0106/2059] Fix omr test speed v6 --- openmptcprouter/files/bin/omr-test-speedv6 | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index b80399e5c..0d5444041 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -3,14 +3,14 @@ INTERFACE="$1" echo "Select best test server..." -HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip http://www.ovh.net/files/10Gb.dat https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" +HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip http://www.ovh.net/files/10Gb.dat https://speed.hetzner.de/10GB.bin http://ipv6.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" bestping="999" for pinghost in $HOSTLST; do domain=$(echo $pinghost | awk -F/ '{print $3}') if [ -z "$INTERFACE" ]; then - ping=$(ping -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1) + ping=$(ping -6 -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1) else - ping=$(ping -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1) + ping=$(ping -6 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1) fi echo "host: $domain - ping: $ping" if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then @@ -28,11 +28,15 @@ if [ -z "$INTERFACE" ]; then else domain=$(echo $HOST | awk -F/ '{print $3}') hostip=$(dig +nocmd +noall +answer AAAA $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ') - for ip in $hostip; do - ipset add ss_rules6_dst_bypass_all $ip - done + if [ -n "$(ipset list 2>/dev/null | grep ss_rules6)" ]; then + for ip in $hostip; do + ipset add ss_rules6_dst_bypass_all $ip + done + fi curl -6 --interface $INTERFACE $HOST >/dev/null || echo - for ip in $hostip; do - ipset del ss_rules6_dst_bypass_all $ip - done + if [ -n "$(ipset list 2>/dev/null | grep ss_rules6)" ]; then + for ip in $hostip; do + ipset del ss_rules6_dst_bypass_all $ip + done + fi fi From 14a3be2bce063fa69a704ff5dad9661fcd17d0e7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Feb 2021 21:15:32 +0100 Subject: [PATCH 0107/2059] Fix firewall rules setting --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index f6aee441e..e299b4a90 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -976,8 +976,8 @@ _vps_firewall_close_port() { _set_vps_firewall() { fw3 -q print | grep 'vpn.* -d' | while IFS=$"\n" read -r c; do - eval $(echo $c | sed 's/-A/-D/') 2>&1 >/dev/null - newrule=$(echo $c | sed -E -e 's/ -d ([^ ])*//' -e 's/ -s ([^ ])*//') + eval $(echo $c | sed 's/iptables/iptables -w/' | sed 's/-A/-D/') 2>&1 >/dev/null + newrule=$(echo $c | sed 's/iptables/iptables -w/' | sed -E -e 's/ -d ([^ ])*//' -e 's/ -s ([^ ])*//') eval $(echo $newrule | sed 's/-A/-D/') || true eval $newrule done From b5f4261207b65ed84b1d0815ae99439304bb0666 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Feb 2021 15:01:18 +0100 Subject: [PATCH 0108/2059] Update and fix bcm27xx eeprom --- bcm27xx-eeprom/Makefile | 4 ++-- .../0001-rpi-eeprom-update-OpenWrt-defaults.patch | 10 ++++++---- ...rpi-eeprom-update-change-default-include-path.patch | 9 --------- .../patches/0004-rpi-eeprom-update-remove-chmod.patch | 4 ++-- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/bcm27xx-eeprom/Makefile b/bcm27xx-eeprom/Makefile index 6a4dda9b4..dec227d51 100644 --- a/bcm27xx-eeprom/Makefile +++ b/bcm27xx-eeprom/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-eeprom -PKG_VERSION:=3d6165304cb04bda4454e460dea791b5f92a122a +PKG_VERSION:=2fec47bd7f981c9cb21b0fb3fdd4fe07f23f9e3b PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/rpi-eeprom/tar.gz/$(PKG_VERSION)? -PKG_HASH:=d6f25e3d962ea3c770ca1af78466371c47970381b48fb7c2acaf838966d327fc +PKG_HASH:=f54c26ec399801dee7d3d0cc0e969c28878b6f42c982e166c863edb91d2d2a21 PKG_LICENSE:=BSD-3-Clause Custom PKG_LICENSE_FILES:=LICENSE diff --git a/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch index a9c8faac7..059426306 100644 --- a/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch +++ b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch @@ -14,22 +14,24 @@ Signed-off-by: Álvaro Fernández Rojas --- a/rpi-eeprom-update +++ b/rpi-eeprom-update -@@ -24,15 +24,15 @@ else +@@ -24,17 +24,17 @@ else fi - # May be used to select beta or stable releases instead of the default critical updates. --FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-critical} + # Selects the release sub-directory +-FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-default} +FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-stable} FIRMWARE_IMAGE_DIR=${FIRMWARE_IMAGE_DIR:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}} -FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup} +FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-${FIRMWARE_ROOT}/backup} ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1} - USE_FLASHROM=${USE_FLASHROM:-0} RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}/recovery.bin} BOOTFS=${BOOTFS:-/boot} -VCMAILBOX=${VCMAILBOX:-/opt/vc/bin/vcmailbox} +VCMAILBOX=${VCMAILBOX:-/usr/bin/vcmailbox} CM4_ENABLE_RPI_EEPROM_UPDATE=${CM4_ENABLE_RPI_EEPROM_UPDATE:-0} + RPI_EEPROM_UPDATE_CONFIG_TOOL="${RPI_EEPROM_UPDATE_CONFIG_TOOL:-raspi-config}" + + DT_BOOTLOADER_TS=${DT_BOOTLOADER_TS:-/proc/device-tree/chosen/bootloader/build-timestamp} EXIT_SUCCESS=0 EXIT_UPDATE_REQUIRED=1 diff --git a/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch b/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch index 6aee93cf2..f24a9c3f1 100644 --- a/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch +++ b/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch @@ -24,12 +24,3 @@ Signed-off-by: Álvaro Fernández Rojas fi LOCAL_MODE=0 -@@ -345,7 +345,7 @@ Options: - -u Install the specified VL805 (USB EEPROM) image file. - - Environment: --Environment variables should be defined in /etc/default/rpi-eeprom-update -+Environment variables should be defined in /etc/bcm27xx-eeprom.conf - - EEPROM_CONFIG_HOOK - diff --git a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch b/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch index cf8cddc40..a79fa89b1 100644 --- a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch +++ b/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch @@ -1,6 +1,6 @@ --- a/rpi-eeprom-update 2020-11-05 21:58:02.247836497 +0100 +++ b/rpi-eeprom-update 2020-11-05 21:58:36.911266307 +0100 -@@ -186,8 +186,8 @@ +@@ -212,8 +212,8 @@ || die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}" # For NFS mounts ensure that the files are readable to the TFTP user @@ -11,7 +11,7 @@ fi if [ -n "${VL805_UPDATE_IMAGE}" ]; then -@@ -198,8 +198,8 @@ +@@ -224,8 +224,8 @@ || die "Failed to copy ${VL805_UPDATE_IMAGE} to ${BOOTFS}/vl805.bin" # For NFS mounts ensure that the files are readable to the TFTP user From 61b651cd4257b61e44840408f9856185c1bba24c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Feb 2021 15:01:56 +0100 Subject: [PATCH 0109/2059] Fix IPv6 for wan in wizard --- .../luasrc/controller/openmptcprouter.lua | 4 +++- .../root/etc/init.d/openmptcprouter | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 453b69479..f9e130e76 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -309,7 +309,9 @@ function wizard_add() if proto == "dhcpv6" then ucic:set("network",intf,"reqaddress","try") - ucic:set("network",intf,"reqprefix","auto") + ucic:set("network",intf,"reqprefix","no") + ucic:set("network",intf,"iface_map","0") + ucic:set("network",intf,"ipv6","1") end ucic:delete("openmptcprouter",intf,"lc") diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index decb1fdcc..73655b167 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -1,5 +1,5 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2018 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter # Released under GPL 3. See LICENSE for the full terms. START=5 @@ -66,7 +66,7 @@ omr_set_settings() { uci -q set openmptcprouter.$1=interface uci -q set openmptcprouter.$1.multipath="$multipath" config_get disable_ipv6 settings disable_ipv6 "0" - if [ "$disable_ipv6" = "1" ] || [ "$1" != "omr6in4" ]; then + if [ "$proto" != "dhcpv6" ] && ([ "$disable_ipv6" = "1" ] || [ "$1" != "omr6in4" ]); then uci -q set network.$1.ipv6=0 else uci -q set network.$1.ipv6=1 @@ -78,6 +78,13 @@ omr_set_settings() { [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') if [ -n "$ifname" ]; then + if [ "$proto" = "dhcpv6" ]; then + # Change interface name for sysctl in case of VLAN (eth0.2 => eth0/2) + ifnamesys=$(echo $ifname | sed 's:\.:/:') + sysctl -qw net.ipv6.conf.${ifnamesys}.disable_ipv6=0 + sysctl -qw net.ipv6.conf.${ifnamesys}.accept_ra=1 + fi + if [ "$addlatency" = "0" ] && [ "$(tc qdisc show dev $ifname | grep delay)" != "" ]; then tc qdisc del dev ${ifname} root netem fi From 313324a35d660f26c879a9e459a44ac4e8370bc4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Feb 2021 15:02:34 +0100 Subject: [PATCH 0110/2059] Fix text for DHCP static help --- .../htdocs/luci-static/resources/view/network/dhcp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js index d51c0b33d..ed2b50866 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js @@ -491,7 +491,7 @@ return view.extend({ so.datatype = 'or(ip4addr,"ignore")'; so.rmempty = true; - so = ss.option(form.Value, 'leasetime', _('Lease time'), _('The lease time is minutes (mini 2m), hours (eg 1h) or "infinite"')); + so = ss.option(form.Value, 'leasetime', _('Lease time'), _('The lease time is in minutes (mini 2m), hours (eg 1h) or "infinite"')); so.placeholder = '12h'; so.rmempty = true; From 0b60a4feecd32b68eb7a0c635f8856b3c3f0c6de Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Feb 2021 15:08:14 +0100 Subject: [PATCH 0111/2059] Add some DNS over TLS server in unbound config --- .../files/etc/uci-defaults/1940-omr-dns | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index 662442e18..e66213732 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -66,6 +66,144 @@ fi # commit unbound #EOF +if [ -z "$(uci -q unbound.auth_icann)" ]; then + uci -q batch <<-EOF >/dev/null + set unbound.auth_icann=zone + set unbound.auth_icann.fallback='1' + set unbound.auth_icann.url_dir='https://www.internic.net/domain/' + set unbound.auth_icann.zone_type='auth_zone' + add_list unbound.auth_icann.server='lax.xfr.dns.icann.org' + add_list unbound.auth_icann.server='iad.xfr.dns.icann.org' + add_list unbound.auth_icann.zone_name='.' + add_list unbound.auth_icann.zone_name='arpa.' + add_list unbound.auth_icann.zone_name='in-addr.arpa.' + add_list unbound.auth_icann.zone_name='ip6.arpa.' + set unbound.auth_icann.enabled='1' + set unbound.fwd_isp=zone + set unbound.fwd_isp.enabled='0' + set unbound.fwd_isp.fallback='1' + set unbound.fwd_isp.resolv_conf='1' + set unbound.fwd_isp.zone_type='forward_zone' + add_list unbound.fwd_isp.zone_name='isp-bill.example.com.' + add_list unbound.fwd_isp.zone_name='isp-mail.example.net.' + set unbound.fwd_google=zone + set unbound.fwd_google.enabled='0' + set unbound.fwd_google.fallback='1' + set unbound.fwd_google.tls_index='dns.google' + set unbound.fwd_google.tls_upstream='1' + set unbound.fwd_google.zone_type='forward_zone' + add_list unbound.fwd_google.server='8.8.4.4' + add_list unbound.fwd_google.server='8.8.8.8' + add_list unbound.fwd_google.server='2001:4860:4860::8844' + add_list unbound.fwd_google.server='2001:4860:4860::8888' + set unbound.fwd_google.zone_name='.' + set unbound.fwd_cloudflare=zone + set unbound.fwd_cloudflare.enabled='0' + set unbound.fwd_cloudflare.fallback='1' + set unbound.fwd_cloudflare.tls_index='cloudflare-dns.com' + set unbound.fwd_cloudflare.tls_upstream='1' + set unbound.fwd_cloudflare.zone_type='forward_zone' + add_list unbound.fwd_cloudflare.server='1.1.1.1' + add_list unbound.fwd_cloudflare.server='1.0.0.1' + add_list unbound.fwd_cloudflare.server='2606:4700:4700::1111' + add_list unbound.fwd_cloudflare.server='2606:4700:4700::1001' + set unbound.fwd_cloudflare.zone_name='.' + EOF +fi + +if [ -z "$(uci -q get unbound.fwd_adguard_family)" ]; then + uci -q batch <<-EOF >/dev/null + set unbound.fwd_adguard_family=zone + set unbound.fwd_adguard_family.enabled='0' + set unbound.fwd_adguard_family.fallback='1' + set unbound.fwd_adguard_family.tls_index='dns-family.adguard.com' + set unbound.fwd_adguard_family.tls_upstream='1' + set unbound.fwd_adguard_family.zone_type='forward_zone' + add_list unbound.fwd_adguard_family.server='176.103.130.132' + add_list unbound.fwd_adguard_family.server='176.103.130.134' + set unbound.fwd_adguard_family.zone_name='.' + set unbound.fwd_adguard_standard=zone + set unbound.fwd_adguard_standard.enabled='0' + set unbound.fwd_adguard_standard.fallback='1' + set unbound.fwd_adguard_standard.tls_index='dns.adguard.com' + set unbound.fwd_adguard_standard.tls_upstream='1' + set unbound.fwd_adguard_standard.zone_type='forward_zone' + add_list unbound.fwd_adguard_standard.server='176.103.130.130' + add_list unbound.fwd_adguard_standard.server='176.103.130.131' + set unbound.fwd_adguard_standard.zone_name='.' + set unbound.fwd_cloudflare_family=zone + set unbound.fwd_cloudflare_family.enabled='0' + set unbound.fwd_cloudflare_family.fallback='1' + set unbound.fwd_cloudflare_family.tls_index='family.cloudflare-dns.com' + set unbound.fwd_cloudflare_family.tls_upstream='1' + set unbound.fwd_cloudflare_family.zone_type='forward_zone' + add_list unbound.fwd_cloudflare_family.server='1.1.1.3' + add_list unbound.fwd_cloudflare_family.server='1.0.0.3' + set unbound.fwd_cloudflare_family.zone_name='.' + set unbound.fwd_cloudflare_malware=zone + set unbound.fwd_cloudflare_malware.enabled='0' + set unbound.fwd_cloudflare_malware.fallback='1' + set unbound.fwd_cloudflare_malware.tls_index='security.cloudflare-dns.com' + set unbound.fwd_cloudflare_malware.tls_upstream='1' + set unbound.fwd_cloudflare_malware.zone_type='forward_zone' + add_list unbound.fwd_cloudflare_malware.server='1.1.1.2' + add_list unbound.fwd_cloudflare_malware.server='1.0.0.2' + set unbound.fwd_cloudflare_malware.zone_name='.' + set unbound.fwd_odvr=zone + set unbound.fwd_odvr.enabled='0' + set unbound.fwd_odvr.fallback='1' + set unbound.fwd_odvr.tls_index='odvr.nic.cz' + set unbound.fwd_odvr.tls_upstream='1' + set unbound.fwd_odvr.zone_type='forward_zone' + add_list unbound.fwd_odvr.server='193.17.47.1' + add_list unbound.fwd_odvr.server='185.43.135.1' + set unbound.fwd_odvr.zone_name='.' + set unbound.fwd_libredns=zone + set unbound.fwd_libredns.enabled='0' + set unbound.fwd_libredns.fallback='1' + set unbound.fwd_libredns.tls_index='doh.libredns.gr' + set unbound.fwd_libredns.tls_upstream='1' + set unbound.fwd_libredns.zone_type='forward_zone' + add_list unbound.fwd_libredns.server='116.202.176.26' + set unbound.fwd_libredns.zone_name='.' + set unbound.fwd_quad9_recommended=zone + set unbound.fwd_quad9_recommended.enabled='0' + set unbound.fwd_quad9_recommended.fallback='1' + set unbound.fwd_quad9_recommended.tls_index='dns.quad9.net' + set unbound.fwd_quad9_recommended.tls_upstream='1' + set unbound.fwd_quad9_recommended.zone_type='forward_zone' + add_list unbound.fwd_quad9_recommended.server='9.9.9.9' + add_list unbound.fwd_quad9_recommended.server='149.112.112.112' + set unbound.fwd_quad9_recommended.zone_name='.' + set unbound.fwd_quad9_unsecured=zone + set unbound.fwd_quad9_unsecured.enabled='0' + set unbound.fwd_quad9_unsecured.fallback='1' + set unbound.fwd_quad9_unsecured.tls_index='dns10.quad9.net' + set unbound.fwd_quad9_unsecured.tls_upstream='1' + set unbound.fwd_quad9_unsecured.zone_type='forward_zone' + add_list unbound.fwd_quad9_unsecured.server='9.9.9.10' + add_list unbound.fwd_quad9_unsecured.server='149.112.112.10' + set unbound.fwd_quad9_unsecured.zone_name='.' + set unbound.fwd_quad9_ecs=zone + set unbound.fwd_quad9_ecs.enabled='0' + set unbound.fwd_quad9_ecs.fallback='1' + set unbound.fwd_quad9_ecs.tls_index='dns11.quad9.net' + set unbound.fwd_quad9_ecs.tls_upstream='1' + set unbound.fwd_quad9_ecs.zone_type='forward_zone' + add_list unbound.fwd_quad9_ecs.server='9.9.9.11' + add_list unbound.fwd_quad9_ecs.server='149.112.112.11' + set unbound.fwd_quad9_ecs.zone_name='.' + set unbound.fwd_quad9_secured=zone + set unbound.fwd_quad9_secured.enabled='0' + set unbound.fwd_quad9_secured.fallback='1' + set unbound.fwd_quad9_secured.tls_index='dns9.quad9.net' + set unbound.fwd_quad9_secured.tls_upstream='1' + set unbound.fwd_quad9_secured.zone_type='forward_zone' + add_list unbound.fwd_quad9_secured.server='9.9.9.9' + add_list unbound.fwd_quad9_secured.server='149.112.112.9' + set unbound.fwd_quad9_secured.zone_name='.' + EOF +fi rm -f /tmp/luci-indexcache From a939f868474c51a761846e83c48c9adcfda9ab8f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Feb 2021 15:08:53 +0100 Subject: [PATCH 0112/2059] Add compilation for Ubiquiti EdgeRouter X --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a837a7293..0fbd63a7c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64] + OMR_TARGET: [bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx] runs-on: ubuntu-latest continue-on-error: true From 94a14ed67ea230d210d4b8380fb49d2c0af9b8ac Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 13 Feb 2021 17:34:08 +0100 Subject: [PATCH 0113/2059] Fix ip -6 route in omr-tracker --- omr-tracker/files/bin/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 637c27019..84a159e84 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -377,7 +377,7 @@ while true; do _dns "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP" "yes" statusb=$? fi - ip route del "$OMR_TRACKER_HOST6" via "$OMR_TRACKER_DEVICE_GATEWAY6" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP6" > /dev/null 2>&1 + ip -6 route del "$OMR_TRACKER_HOST6" via "$OMR_TRACKER_DEVICE_GATEWAY6" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP6" > /dev/null 2>&1 if $(exit $statusb); then OMR_TRACKER_STATUS_MSG="" OMR_TRACKER_STATUS="OK" From 8db989a903f8f28588a11714a8ee352cfdf7ff28 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 14 Feb 2021 20:41:11 +0100 Subject: [PATCH 0114/2059] Fix use shadowsocks UDP when VPN down --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 27031e506..b00a88e6c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -646,9 +646,9 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then config_foreach set_route interface $OMR_TRACKER_INTERFACE config_foreach set_route6 interface $OMR_TRACKER_INTERFACE fi - if [ "$(uci -q get openmptcprouter.settings.shadowsocksudp)" = "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.shadowsocks)" = "up" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "" ] && [ "$(uci -q get shadowsocks-libev.hi2.mode)" = "tcp_and_udp" ] && [ "$(uci -q get shadowsocks-libev.sss0.obfs)" != "1" ]; then + if [ "$(uci -q get openmptcprouter.settings.shadowsocksudp)" = "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.shadowsocks)" = "up" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "" ] && [ "$(uci -q get shadowsocks-libev.hi1.mode)" = "tcp_and_udp" ] && [ "$(uci -q get shadowsocks-libev.sss0.obfs)" != "1" ]; then _log "Tunnel down use ShadowSocks for UDP" - uci -q set shadowsocks-libev.ss_rules.redir_udp='hi2' + uci -q set shadowsocks-libev.ss_rules.redir_udp='hi1' if /etc/init.d/shadowsocks-libev rules_exist ; then /etc/init.d/shadowsocks-libev rules_down /etc/init.d/shadowsocks-libev rules_up @@ -699,7 +699,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 fi - if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "hi2" ]; then + if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "hi1" ]; then _log "Tunnel up disable use of ShadowSocks for UDP" uci -q delete shadowsocks-libev.ss_rules.redir_udp if /etc/init.d/shadowsocks-libev rules_exist ; then From 3112e3c28d41c9449737f576683a191bfd1103b7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 14 Feb 2021 20:41:50 +0100 Subject: [PATCH 0115/2059] Same configuration for shadowsocks sss0 and sss1 --- .../luasrc/controller/openmptcprouter.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index f9e130e76..9369e8514 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -635,11 +635,13 @@ function wizard_add() local encryption = luci.http.formvalue("encryption") if encryption == "none" then ucic:set("shadowsocks-libev","sss0","method","none") + ucic:set("shadowsocks-libev","sss1","method","none") ucic:set("openvpn","omr","cipher","none") ucic:set("v2ray","omrout","s_vmess_user_security","none") ucic:set("v2ray","omrout","s_vless_user_security","none") elseif encryption == "aes-256-gcm" then ucic:set("shadowsocks-libev","sss0","method","aes-256-gcm") + ucic:set("shadowsocks-libev","sss1","method","aes-256-gcm") ucic:set("glorytun","vpn","chacha20","0") ucic:set("glorytun-udp","vpn","chacha","0") ucic:set("openvpn","omr","cipher","AES-256-GCM") @@ -647,6 +649,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_vless_user_security","aes-128-gcm") elseif encryption == "aes-256-cfb" then ucic:set("shadowsocks-libev","sss0","method","aes-256-cfb") + ucic:set("shadowsocks-libev","sss1","method","aes-256-cfb") ucic:set("glorytun","vpn","chacha20","0") ucic:set("glorytun-udp","vpn","chacha","0") ucic:set("openvpn","omr","cipher","AES-256-CFB") @@ -654,6 +657,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_vless_user_security","aes-128-gcm") elseif encryption == "chacha20-ietf-poly1305" then ucic:set("shadowsocks-libev","sss0","method","chacha20-ietf-poly1305") + ucic:set("shadowsocks-libev","sss1","method","chacha20-ietf-poly1305") ucic:set("glorytun","vpn","chacha20","1") ucic:set("glorytun-udp","vpn","chacha","1") ucic:set("openvpn","omr","cipher","AES-256-CBC") @@ -674,6 +678,7 @@ function wizard_add() --end if shadowsocks_key ~= "" then ucic:set("shadowsocks-libev","sss0","key",shadowsocks_key) + ucic:set("shadowsocks-libev","sss1","key",shadowsocks_key) --ucic:set("shadowsocks-libev","sss0","method","chacha20-ietf-poly1305") --ucic:set("shadowsocks-libev","sss0","server_port","65101") --ucic:set("shadowsocks-libev","sss0","disabled",shadowsocks_disable) @@ -685,8 +690,10 @@ function wizard_add() else if serversnb == 0 then ucic:set("shadowsocks-libev","sss0","disabled",shadowsocks_disable) + ucic:set("shadowsocks-libev","sss1","disabled",shadowsocks_disable) end ucic:set("shadowsocks-libev","sss0","key","") + ucic:set("shadowsocks-libev","sss1","key","") ucic:save("shadowsocks-libev") ucic:commit("shadowsocks-libev") luci.sys.call("/etc/init.d/shadowsocks rules_down >/dev/null 2>/dev/null") @@ -965,7 +972,7 @@ function settings_add() local disableserverping = luci.http.formvalue("disableserverping") or "0" ucic:set("openmptcprouter","settings","disableserverping",disableserverping) - -- Enable/disable shadowsocks upd + -- Enable/disable shadowsocks udp local shadowsocksudp = luci.http.formvalue("shadowsocksudp") or "0" ucic:set("openmptcprouter","settings","shadowsocksudp",shadowsocksudp) From 9152cfc85f6402df8c9bffd7aae6c2247b66ac38 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Feb 2021 15:35:04 +0100 Subject: [PATCH 0116/2059] Add IPv6 checkbox for interface in wizard and fix modemmanager support --- .../luasrc/controller/openmptcprouter.lua | 10 ++++++++- .../luasrc/view/openmptcprouter/wizard.htm | 21 +++++++++++++------ .../root/etc/init.d/openmptcprouter | 8 +++---- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 9369e8514..3e81c8e59 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -240,6 +240,7 @@ function wizard_add() local netmask = luci.http.formvalue("cbid.network.%s.netmask" % intf) or "" local gateway = luci.http.formvalue("cbid.network.%s.gateway" % intf) or "" local ip6gw = luci.http.formvalue("cbid.network.%s.ip6gw" % intf) or "" + local ipv6 = luci.http.formvalue("cbid.network.%s.ipv6" % intf) or "0" local apn = luci.http.formvalue("cbid.network.%s.apn" % intf) or "" local pincode = luci.http.formvalue("cbid.network.%s.pincode" % intf) or "" local delay = luci.http.formvalue("cbid.network.%s.delay" % intf) or "" @@ -282,6 +283,7 @@ function wizard_add() ucic:set("network",intf,"auth",auth) ucic:set("network",intf,"mode",mode) ucic:set("network",intf,"label",label) + ucic:set("network",intf,"ipv6",ipv6) if lan == "1" then ucic:set("network",intf,"multipath","off") else @@ -1077,7 +1079,13 @@ end function get_device(interface) local dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {}) if dump ~= nil then - return dump['l3_device'] + if dump['l3_device'] ~= nil then + return dump['l3_device'] + elseif dump['device'] ~= nil then + return dump['device'] + else + return "" + end else return "" end diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 0e7e838a6..363b30852 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -561,12 +561,14 @@ <% iffind=0 uciifname=uci:get("network",ifname,"ifname") - if uciifname:match("/") then - realifname=uciifname - vlan="" - else - realifname=splitstring(uciifname,'.')[1] or "" - vlan=splitstring(uciifname,'.')[2] or "" + if uciifname ~= nil then + if uciifname:match("/") then + realifname=uciifname + vlan="" + else + realifname=splitstring(uciifname,'.')[1] or "" + vlan=splitstring(uciifname,'.')[2] or "" + end end for _, ifacea in ipairs(ifaces) do if not (ifacea == "lo" or ifacea == "6in4-omr6in4" or ifacea == "mlvpn0" or ifacea:match("^ifb.*") or ifacea:match("^sit.*") or ifacea:match("^gre.*") or ifacea:match("^ip6.*") or ifacea:match("^teql.*") or ifacea:match("^erspan.*") or ifacea:match("^tun.*")) and device_notvirtual(ifacea) then @@ -671,6 +673,13 @@ <% end %> +
    + +
    + checked<% end %> /> +
    +
    +
    diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 73655b167..fe110bdfd 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -60,25 +60,25 @@ omr_set_settings() { config_get device "$1" device config_get proto "$1" proto config_get type "$1" type + config_get ipv6 "$1" ipv6 config_get addlatency "$1" addlatency [ -z "$multipath" ] || [ "$multipath" = "off" ] && [ "$1" != "omrvpn" ] && [ "$1" != "glorytun" ] && return uci -q set openmptcprouter.$1=interface uci -q set openmptcprouter.$1.multipath="$multipath" config_get disable_ipv6 settings disable_ipv6 "0" - if [ "$proto" != "dhcpv6" ] && ([ "$disable_ipv6" = "1" ] || [ "$1" != "omr6in4" ]); then + if [ "$disable_ipv6" = "1" ]; then uci -q set network.$1.ipv6=0 - else - uci -q set network.$1.ipv6=1 fi [ -z "$addlatency" ] && addlatency=0 devicename=$(echo "$device" | cut -d'/' -f3) [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $ifname | grep '@')" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') if [ -n "$ifname" ]; then - if [ "$proto" = "dhcpv6" ]; then + if [ "$proto" = "dhcpv6" ] || [ "$ipv6" = "1" ]; then # Change interface name for sysctl in case of VLAN (eth0.2 => eth0/2) ifnamesys=$(echo $ifname | sed 's:\.:/:') sysctl -qw net.ipv6.conf.${ifnamesys}.disable_ipv6=0 From 8f967e09f83786e0a5e51f9216eba3440363c709 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Feb 2021 15:36:31 +0100 Subject: [PATCH 0117/2059] Add log info when IP doesn't exist --- omr-tracker/files/bin/omr-tracker | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 84a159e84..1ca117a82 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -412,6 +412,13 @@ while true; do sleep "$OMR_TRACKER_INTERVAL_TRIES" done fi + if [ -z "$OMR_TRACKER_DEVICE_IP" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ -z "$OMR_TRACKER_DEVICE_IP6" ] || [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + [ -z "$OMR_TRACKER_STATUS_MSG" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_INTERFACE have ip issues" + [ -z "$OMR_TRACKER_DEVICE_IP" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4" + [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4 gateway" + [ -z "$OMR_TRACKER_DEVICE_IP6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6" + [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6 gateway" + fi else OMR_TRACKER_STATUS_MSG="link down" fi From d42ef7fd4b3b211afc718b808ce7e8aa18fb45fe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Feb 2021 19:52:06 +0100 Subject: [PATCH 0118/2059] Add IPv6 in omr-tracker config --- .../luasrc/model/cbi/omr-tracker.lua | 5 +++++ omr-tracker/files/etc/config/omr-tracker | 6 ++++++ omr-tracker/files/etc/uci-defaults/omr-tracker | 12 ++++++++++++ 3 files changed, 23 insertions(+) diff --git a/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua b/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua index f00afe5fd..3484b1afa 100644 --- a/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua +++ b/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua @@ -132,6 +132,11 @@ o.placeholder = "4.2.2.1" o.default = { "4.2.2.1", "8.8.8.8" } o.rmempty = false +o = s:option(DynamicList, "hosts6", translate("Hosts IPv6"),translate("Must be IPs and not domains")) +o.placeholder = "2001:4860:4860::8844" +o.default = { "2001:4860:4860::8888", "2001:4860:4860::8844" } +o.rmempty = false + s = m:section(TypedSection, "interface", translate("Interfaces")) s.template_addremove = "omr-tracker/cbi-select-add" s.addremove = true diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index bf64d41d1..6f9d1c258 100644 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -11,6 +11,12 @@ config defaults 'defaults' list hosts '80.67.169.40' list hosts '114.114.114.114' list hosts '1.1.1.1' + list hosts6 '2606:4700:4700::1111' + list hosts6 '2606:4700:4700::1001' + list hosts6 '2620:fe::fe' + list hosts6 '2620:fe::9' + list hosts6 '2001:4860:4860::8888' + list hosts6 '2001:4860:4860::8844' option timeout '2' option tries '3' option interval '2' diff --git a/omr-tracker/files/etc/uci-defaults/omr-tracker b/omr-tracker/files/etc/uci-defaults/omr-tracker index 30aec42b9..cf2ca0dab 100755 --- a/omr-tracker/files/etc/uci-defaults/omr-tracker +++ b/omr-tracker/files/etc/uci-defaults/omr-tracker @@ -60,6 +60,18 @@ if [ "$(uci -q get omr-tracker.proxy.hosts | grep '103.224.182.242')" != "" ]; t EOF fi +if [ -z "$(uci -q get omr-tracker.defaults.hosts6)" ]; then + uci -q batch <<-EOF >/dev/null + add_list omr-tracker.defaults.hosts6='2606:4700:4700::1111' + add_list omr-tracker.defaults.hosts6='2606:4700:4700::1001' + add_list omr-tracker.defaults.hosts6='2620:fe::fe' + add_list omr-tracker.defaults.hosts6='2620:fe::9' + add_list omr-tracker.defaults.hosts6='2001:4860:4860::8888' + add_list omr-tracker.defaults.hosts6='2001:4860:4860::8844' + commit omr-tracker + EOF +fi + if [ "$(uci -q get omr-tracker.defaults.wait_test)" = "" ]; then uci -q batch <<-EOF >/dev/null set omr-tracker.defaults.wait_test=1 From 35f7ce04decf4e906a7a1df0fbfd496324c70d29 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Feb 2021 19:53:28 +0100 Subject: [PATCH 0119/2059] Disable IPv6 checkbox in wizard --- .../luasrc/view/openmptcprouter/wizard.htm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 363b30852..a0b5851e1 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -673,13 +673,14 @@ <% end %> +
    From 56e032152dd09369768b3c44fac50c4e8d8aa4f7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Feb 2021 19:55:07 +0100 Subject: [PATCH 0120/2059] Support alias interfaces --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 1 + mlvpn/files/etc/init.d/mlvpn | 2 ++ mptcp/files/etc/init.d/mptcp | 3 +++ .../files/usr/share/omr/post-tracking.d/post-tracking | 10 ++++++++++ omr-quota/files/etc/init.d/omr-quota | 1 + omr-tracker/files/etc/init.d/omr-tracker | 1 + openmptcprouter/files/etc/firewall.gre-tunnel | 1 + 7 files changed, 19 insertions(+) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index a859b345e..d1e2d9592 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -465,6 +465,7 @@ _intf_rule() { local intf config_get intf $1 ifname [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') #count=$((count+1)) config_get count $1 metric local mode diff --git a/mlvpn/files/etc/init.d/mlvpn b/mlvpn/files/etc/init.d/mlvpn index 761694f6c..3021f143e 100755 --- a/mlvpn/files/etc/init.d/mlvpn +++ b/mlvpn/files/etc/init.d/mlvpn @@ -15,8 +15,10 @@ interface_multipath_settings() { [ "$mode" = "off" ] || [ "$mode" = "" ] && return 1 config_get ifname "$config" ifname [ -z "$ifname" ] && ifname=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $ifname | grep '@')" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') [ -z "$ifname" ] && return 1 addr=$(ifstatus ${config} | jsonfilter -q -e '@["ipv4-address"][0].address') + [ -z "$addr" ] && return 1 count=$(($count+1)) port=$((firstport+count)) cat >> /tmp/etc/${interface_name}.conf <<-EOF diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 77310f5eb..a405f4bd0 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -84,6 +84,7 @@ interface_multipath_settings() { config_get iface "$config" ifname config_get txqueuelen "$config" txqueuelen [ -z "$iface" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["device"]') if [ "$(uci -q get openmptcprouter.${config}.metric)" = "" ]; then count=$((count+1)) metric=$count @@ -382,6 +383,7 @@ add_route() { [ -n "$table" ] && routeset="table $table" config_get interface "$1" interface iface=$(ifstatus "$interface" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$interface" | jsonfilter -q -e '@["device"]') routeset="$routeset dev $iface" logger -t "MPTCP" "Add route $routeset" ip route replace $routeset @@ -402,6 +404,7 @@ add_route6() { [ -n "$table" ] && routeset="table $table" config_get interface "$1" interface iface=$(ifstatus "$interface" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$interface" | jsonfilter -q -e '@["device"]') routeset="$routeset dev $iface" logger -t "MPTCP" "Add IPv6 route $routeset" ip -6 route replace $routeset diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index b00a88e6c..aaa044cae 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -13,6 +13,7 @@ set_route() { interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "${INTERFACE}" | jsonfilter -q -e '@["device"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") if [ "$multipath_config_route" != "off" ] && [ "$SETROUTE" != true ] && [ "$INTERFACE" != "$PREVINTERFACE" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then interface_gw="$(uci -q get network.$INTERFACE.gateway)" @@ -46,6 +47,7 @@ set_route6() { interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") if [ "$multipath_config_route" != "off" ] && [ "$SETROUTE" != true ] && [ "$INTERFACE" != "$PREVINTERFACE" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then interface_gw="$(uci -q get network.$INTERFACE.gateway)" @@ -149,6 +151,7 @@ set_routes_intf() { interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + [ -n "$(echo $interface_if | grep '@')" ] && ifname=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep 'deactivated') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") @@ -198,6 +201,7 @@ set_routes_intf6() { interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep 'deactivated') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") @@ -247,6 +251,7 @@ set_route_balancing() { interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then @@ -290,6 +295,7 @@ set_route_balancing6() { interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) + [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then @@ -335,6 +341,7 @@ set_server_all_routes() { interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') @@ -376,6 +383,7 @@ set_server_all_routes6() { interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') @@ -424,6 +432,7 @@ set_server_route() { interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep "deactivated") interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") @@ -455,6 +464,7 @@ set_server_route6() { interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep "deactivated") interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") diff --git a/omr-quota/files/etc/init.d/omr-quota b/omr-quota/files/etc/init.d/omr-quota index 4ed95c735..37700ff50 100755 --- a/omr-quota/files/etc/init.d/omr-quota +++ b/omr-quota/files/etc/init.d/omr-quota @@ -19,6 +19,7 @@ _launch_quota() { local txquota rxquota ttquota interval enabled interface _validate_section "interface" "$1" interface=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $interface | grep '@')" ] && interface=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') [ -z "$interface" ] && return diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 467817e91..67e72a3bc 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -54,6 +54,7 @@ _launch_tracker() { ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -z "$ifname" ] && ifname=$(ifstatus "$1_4" | jsonfilter -q -e '@["l3_device"]') [ -z "$ifname" ] && config_get ifname "$1" ifname + [ -n "$(echo $ifname | grep '@')" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') config_get multipath "$1" multipath config_get ifenabled "$1" auto diff --git a/openmptcprouter/files/etc/firewall.gre-tunnel b/openmptcprouter/files/etc/firewall.gre-tunnel index 41b00e664..4d8d450e1 100644 --- a/openmptcprouter/files/etc/firewall.gre-tunnel +++ b/openmptcprouter/files/etc/firewall.gre-tunnel @@ -12,6 +12,7 @@ _setup_routes() { config_get lookup $1 lookup config_get gateway $1 gateway intf=$(ifstatus $1 | jsonfilter -e '@.l3_device' | tr -d "\n") + [ -n "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]' | tr -d "\n") if [ -n "$lookup" ] && [ -n "$intf" ] && [ -n "$gateway" ]; then ip route replace default via $gateway dev $intf table $lookup fi From f60ac82be9ab3327c2c4a067d3709f76967ade82 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Feb 2021 19:55:27 +0100 Subject: [PATCH 0121/2059] Fix IPv6 gateway detection --- omr-tracker/files/bin/omr-tracker | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 1ca117a82..b046c6500 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -241,6 +241,12 @@ while true; do if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}\"].nexthop" | tr -d "\n") fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/64\"].nexthop" | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/56\"].nexthop" | tr -d "\n") + fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") fi From e7a77db59ebd13cea082aa9aed7fcf6f9fcc8ad2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Feb 2021 19:55:54 +0100 Subject: [PATCH 0122/2059] Set first boot is over after settings are set --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index e299b4a90..265446b56 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1675,7 +1675,6 @@ _config_service() { uci -q commit shadowsocks-libev fi } - [ -n "$vps_config" ] && uci -q set openmptcprouter.settings.firstboot=0 fi if [ "$user_permission" != "ro" ]; then #config_load shadowsocks-libev @@ -1711,6 +1710,8 @@ _config_service() { [ "$error" = 0 ] && { #logger -t "OMR-VPS" "No errors" uci -q set openmptcprouter.${servername}.lastchange=$(date "+%s") + [ -n "$vps_config" ] && uci -q set openmptcprouter.settings.firstboot=0 + } #[ "$error" != 0 ] && logger -t "OMR-VPS" "Error !" uci -q batch <<-EOF >/dev/null From 3676a6fde68b4cbe8b2c641896f8b7d271a208af Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Feb 2021 10:46:45 +0100 Subject: [PATCH 0123/2059] Fix obfuscation choice --- .../luasrc/view/openmptcprouter/settings.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index 7ae4100b4..e9d4f52a8 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -97,7 +97,7 @@ end if obfs_installed then %> - + <% end %> From 5b9f6a8ed0e500612340483bb5198e67ffe0f65b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Feb 2021 14:31:40 +0100 Subject: [PATCH 0124/2059] No create _4 interface when DHCPv6 set in wizard --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 3e81c8e59..b71efc888 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -313,6 +313,8 @@ function wizard_add() ucic:set("network",intf,"reqaddress","try") ucic:set("network",intf,"reqprefix","no") ucic:set("network",intf,"iface_map","0") + ucic:set("network",intf,"iface_dslite","0") + ucic:set("network",intf,"iface_464xlate","0") ucic:set("network",intf,"ipv6","1") end From 18f2034668937760994a3b792290c17ac9ee1d80 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Feb 2021 14:32:24 +0100 Subject: [PATCH 0125/2059] Display whois of IPv6 address in status page if not same as IPv4 whois --- .../luasrc/view/openmptcprouter/wanstatus.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 83f601bbf..794dccb31 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -498,7 +498,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm { content += String.format('%s %s
    ','<%:whois:%>', whois); } - if(whois6 !== '') + if(whois6 !== '' && whois6 != whois) { content += String.format('%s %s
    ','<%:whois:%>', whois6); } From c97370d4108ee0e086fc3a6ec7c9667e97eb8ffe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Feb 2021 14:32:45 +0100 Subject: [PATCH 0126/2059] Fix QMI info --- luci-app-openmptcprouter/root/bin/omr-qmi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/bin/omr-qmi b/luci-app-openmptcprouter/root/bin/omr-qmi index 1a73d4f37..8721ffb12 100755 --- a/luci-app-openmptcprouter/root/bin/omr-qmi +++ b/luci-app-openmptcprouter/root/bin/omr-qmi @@ -24,6 +24,6 @@ elif [ "$TYPE" = "lte" ]; then fi [ -z "$INFO" ] && echo $PERCENT && return OPERATOR=$(timeout 1 uqmi -d $MODEM_INTF --get-serving-system | jsonfilter -e '@.plmn_description' | tr -d '\n') -NUMBER=$(timeout 1 uqmi -d $MODEM_INTF --msisdn | jsonfilter -e '@' | tr -d '\n') +NUMBER=$(timeout 1 uqmi -d $MODEM_INTF --get-msisdn | jsonfilter -e '@' | tr -d '\n') STATE=$(timeout 1 uqmi -d $MODEM_INTF --get-data-status | jsonfilter -e '@' | tr -d '\n') [ "$INFO" = "all" ] && echo "$PERCENT;$OPERATOR;$NUMBER;$TATE;$TYPE" \ No newline at end of file From c80f9a017a2b0720f81dc46d78425f997fb19d35 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Feb 2021 14:33:07 +0100 Subject: [PATCH 0127/2059] Get public ip only when needed --- .../root/usr/libexec/rpcd/openmptcprouter | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index bc36f9649..b86f4d287 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1373,20 +1373,20 @@ function interfaces_status() if connectivity ~= "ERROR" then if ifname ~= nil and ifname:match("^tun.*") and interface:match("^ovpn.*") then publicIP = uci:get("openmptcprouter",interface:sub(5),"publicip") or "" - if ifname ~= nil and publicIP == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then + if ifname ~= nil and ipaddr ~= "" and publicIP == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then publicIP = ut.trim(sys.exec("omr-ip-intf " .. get_device(interface:sub(5)))) end publicIP6 = uci:get("openmptcprouter",interface:sub(5),"publicip6") or "" - if ifname ~= nil and publicIP6 == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then + if ifname ~= nil and ip6addr ~= "" and publicIP6 == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then publicIP6 = ut.trim(sys.exec("omr-ip6-intf " .. get_device(interface:sub(5)))) end else publicIP = uci:get("openmptcprouter",interface,"publicip") or "" - if ifname ~= nil and publicIP == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then + if ifname ~= nil and ipaddr ~= "" and publicIP == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then publicIP = ut.trim(sys.exec("omr-ip-intf " .. ifname)) end publicIP6 = uci:get("openmptcprouter",interface,"publicip6") or "" - if ifname ~= nil and publicIP6 == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then + if ifname ~= nil and ip6addr ~= "" and publicIP6 == "" and mArray.openmptcprouter["external_check"] ~= false and mArray.openmptcprouter["dns"] == true then publicIP6 = ut.trim(sys.exec("omr-ip6-intf " .. ifname)) end end From 01d9b7efc1d0a8c50075e2bbadb220c288ac244c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Feb 2021 14:33:46 +0100 Subject: [PATCH 0128/2059] Get public ip only if IPv4/IPv6 set on interface --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index aaa044cae..e00d99fee 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -970,9 +970,11 @@ fi # Save wan settings for status page if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") + $((30 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" = "down" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Get status and settings for $OMR_TRACKER_INTERFACE..." + local ipaddr="" + local ip6addr="" if [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ]; then - local ipaddr="$(omr-ip-intf $OMR_TRACKER_DEVICE)" - local ip6addr="$(omr-ip6-intf $OMR_TRACKER_DEVICE)" + [ -n "$OMR_TRACKER_DEVICE_IP" ] && ipaddr="$(omr-ip-intf $OMR_TRACKER_DEVICE)" + [ -n "$OMR_TRACKER_DEVICE_IP6" ] && ip6addr="$(omr-ip6-intf $OMR_TRACKER_DEVICE)" else uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state="up" From b178e7f4603050048d11261835a1d5229926f191 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Feb 2021 14:34:27 +0100 Subject: [PATCH 0129/2059] Get IPv4 in tracker if DHCPv6 not set --- omr-tracker/files/bin/omr-tracker | 116 ++++++++++++++++-------------- 1 file changed, 61 insertions(+), 55 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index b046c6500..e42a26cab 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -175,6 +175,7 @@ _none() { _restart +OMR_TRACKER_INTERFACE_PROTO="$(uci -q get network.${OMR_TRACKER_INTERFACE_PROTO}.proto)" OMR_TRACKER_PREV_STATUS="" # main loop while true; do @@ -193,63 +194,68 @@ while true; do if [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep UP)" ]; then # retrieve iface ip and gateway - OMR_TRACKER_DEVICE_IP=$(ip -4 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') - if [ -z "$OMR_TRACKER_DEVICE_IP" ]; then - OMR_TRACKER_DEVICE_IP=$(ip -4 addr show dev "$OMR_TRACKER_DEVICE" | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) - fi - #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') - #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then - OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | grep -v 'inet6 f' | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) - #fi - #OMR_TRACKER_DEVICE_IP=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") - #if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - # OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") - #fi - if [ "$OMR_TRACKER_DEVICE" = "bonding-omrvpn" ]; then - OMR_TRACKER_DEVICE_GATEWAY="10.255.248.1" - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.${OMR_TRACKER_INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then - if [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" = "1" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get glorytun.vpn.remoteip) - elif [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" = "1" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get glorytun-udp.vpn.remoteip) - else - OMR_TRACKER_DEVICE_GATEWAY="" + if [ "$OMR_TRACKER_INTERFACE_PROTO" != "dhcpv6" ]; then + OMR_TRACKER_DEVICE_IP=$(ip -4 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') + if [ -z "$OMR_TRACKER_DEVICE_IP" ]; then + OMR_TRACKER_DEVICE_IP=$(ip -4 addr show dev "$OMR_TRACKER_DEVICE" | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) + fi + #OMR_TRACKER_DEVICE_IP=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") + #if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + # OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") + #fi + if [ "$OMR_TRACKER_DEVICE" = "bonding-omrvpn" ]; then + OMR_TRACKER_DEVICE_GATEWAY="10.255.248.1" + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.${OMR_TRACKER_INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then + if [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" = "1" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get glorytun.vpn.remoteip) + elif [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" = "1" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get glorytun-udp.vpn.remoteip) + else + OMR_TRACKER_DEVICE_GATEWAY="" + fi + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + OMR_TRACKER_DEVICE_ROUTE=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep via | grep -v default | grep -v metric | grep -v / | awk '{print $1; exit}' | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | awk '/proto kernel/ {print $1}' | tr -d "\n") fi fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - OMR_TRACKER_DEVICE_ROUTE=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep via | grep -v default | grep -v metric | grep -v / | awk '{print $1; exit}' | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | awk '/proto kernel/ {print $1}' | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then - OMR_TRACKER_DEVICE_GATEWAY6=$(uci -q get "network.$OMR_TRACKER_INTERFACE.ip6gw") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then - OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}\"].nexthop" | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then - OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/64\"].nexthop" | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then - OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/56\"].nexthop" | tr -d "\n") - fi - if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then - OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") - fi + #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') + #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then + OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | grep -v 'inet6 f' | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) + #fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(uci -q get "network.$OMR_TRACKER_INTERFACE.ip6gw") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}\"].nexthop" | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/64\"].nexthop" | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/56\"].nexthop" | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then + OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.nexthop="::"].target' | tr -d "\n") + fi # execute specific tracker if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then From 52841c34c6aa842d6b47a234f5b69eaae83c691b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Feb 2021 17:47:49 +0100 Subject: [PATCH 0130/2059] Add mc because upstream doesn't compile --- mc/Config.in | 59 ++++++++ mc/Makefile | 128 ++++++++++++++++++ mc/patches/010-subshell.patch | 11 ++ ...20-fix-mouse-handling-newer-terminfo.patch | 11 ++ mc/patches/030-fix-gettext-full-0.21.patch | 13 ++ 5 files changed, 222 insertions(+) create mode 100644 mc/Config.in create mode 100644 mc/Makefile create mode 100644 mc/patches/010-subshell.patch create mode 100644 mc/patches/020-fix-mouse-handling-newer-terminfo.patch create mode 100644 mc/patches/030-fix-gettext-full-0.21.patch diff --git a/mc/Config.in b/mc/Config.in new file mode 100644 index 000000000..fcd8fad33 --- /dev/null +++ b/mc/Config.in @@ -0,0 +1,59 @@ +menu "Configuration" + depends on PACKAGE_mc + +config MC_DIFFVIEWER + bool "Enable internal diff viewer" + default n + help + This option enables the built-in diff viewer. + Disabled by default. + +config MC_EDITOR + bool "Enable internal editor" + default y + help + This option enables the built-in file editor. + Enabled by default. + +config MC_SUBSHELL + bool "Enable concurrent subshell" + default y + help + This option enables concurrent subshell support. + Enabled by default. + +config MC_LARGEFILE + bool "Enable largefile support" + default n + help + This option enables support for large files (> 2 GB). + Disabled by default. + +config MC_BACKGROUND + bool "Enable background operations" + default n + help + This option enables support for background operations which + allow to perform some tasks such as copying files in a + separate background process. Background code is known + to be less stable than the rest of the code. + Disabled by default. + +config MC_CHARSET + bool "Enable charset support" + default y + help + This option adds support for selecting character set of the text in + the internal viewer and editor and converting it on the fly. + Enabled by default. + +config MC_VFS + bool "Enable virtual filesystem support" + default y + help + This option enables the Virtual File System switch code to get + transparent access to the following file systems: + cpio, tar, fish, sfs, ftp, sftp, extfs. + Enabled by default. + +endmenu diff --git a/mc/Makefile b/mc/Makefile new file mode 100644 index 000000000..30814afb0 --- /dev/null +++ b/mc/Makefile @@ -0,0 +1,128 @@ +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mc +PKG_VERSION:=4.8.25 +PKG_RELEASE:=2 +PKG_MAINTAINER:=Dirk Brenken +PKG_LICENSE:=GPL-3.0-or-later +PKG_CPE_ID:=cpe:/a:midnight_commander:midnight_commander + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=http://ftp.midnight-commander.org/ +PKG_HASH:=ffc19617f20ebb23330acd3998b7fd559a042d172fa55746d53d246697b2548a +PKG_BUILD_PARALLEL:=1 +PKG_FIXUP:=autoreconf gettext-version +PKG_BUILD_DEPENDS:=MC_VFS:libtirpc + +PKG_CONFIG_DEPENDS := \ + CONFIG_PACKAGE_MC \ + CONFIG_MC_DIFFVIEWER \ + CONFIG_MC_EDITOR \ + CONFIG_MC_SUBSHELL \ + CONFIG_MC_LARGEFILE \ + CONFIG_MC_BACKGROUND \ + CONFIG_MC_CHARSET \ + CONFIG_MC_VFS + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/mc + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+glib2 +libncurses +libmount +MC_VFS:libssh2 $(ICONV_DEPENDS) + TITLE:=Midnight Commander - a powerful visual file manager + URL:=https://www.midnight-commander.org/ + MENU:=1 +endef + +define Package/mc/config + source "$(SOURCE)/Config.in" +endef + +define Package/mc/description +GNU Midnight Commander is a visual file manager. +It's a feature rich full-screen text mode application that allows you to copy, +move and delete files and whole directory trees, search for files and run commands in the subshell. +Internal viewer and editor are included as well. + +endef + +CONFIGURE_ARGS += \ + --enable-silent-rules \ + --disable-tests \ + --disable-doxygen-doc \ + --with-homedir=/etc/mc \ + --with-screen=ncurses \ + --without-x \ + +CONFIGURE_VARS += \ + ac_cv_search_addwstr=no \ + +ifeq ($(CONFIG_MC_DIFFVIEWER),) +CONFIGURE_ARGS += --without-diff-viewer +endif + +ifeq ($(CONFIG_MC_EDITOR),) +CONFIGURE_ARGS += --without-internal-edit +endif + +ifeq ($(CONFIG_MC_SUBSHELL),) +CONFIGURE_ARGS += --without-subshell +endif + +ifeq ($(CONFIG_MC_LARGEFILE),) +CONFIGURE_ARGS += --disable-largefile +endif + +ifeq ($(CONFIG_MC_BACKGROUND),) +CONFIGURE_ARGS += --disable-background +endif + +ifeq ($(CONFIG_MC_CHARSET),) +CONFIGURE_ARGS += --disable-charset +endif + +ifeq ($(CONFIG_MC_VFS),) +CONFIGURE_ARGS += --disable-vfs +else +TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/tirpc +endif + +define Package/mc/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mc $(1)/usr/bin + $(INSTALL_DIR) $(1)/etc/mc + $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.charsets $(1)/etc/mc + $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.ext $(1)/etc/mc + $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.default.keymap $(1)/etc/mc/mc.keymap + $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/filehighlight.ini $(1)/etc/mc + $(INSTALL_DIR) $(1)/usr/share/mc/help + $(INSTALL_DATA) $(PKG_BUILD_DIR)/doc/hlp/mc.hlp $(1)/usr/share/mc/help + $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.menu $(1)/etc/mc + $(INSTALL_DIR) $(1)/etc/mc/skins + $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/skins/default.ini $(1)/etc/mc/skins + $(INSTALL_DIR) $(1)/etc/mc/mcedit/Syntax +ifeq ($(CONFIG_MC_DIFFVIEWER),y) + ln -sf mc $(1)/usr/bin/mcdiff +endif +ifeq ($(CONFIG_MC_EDITOR),y) + ln -sf mc $(1)/usr/bin/mcedit +endif +ifeq ($(CONFIG_MC_VFS),y) + $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/vfs/sfs/sfs.ini $(1)/etc/mc + $(INSTALL_DIR) $(1)/usr/lib/mc/extfs.d +endif +endef + +define Package/mc/conffiles +/etc/mc/mc.menu +/etc/mc/skins/default.ini +endef + +$(eval $(call BuildPackage,mc)) diff --git a/mc/patches/010-subshell.patch b/mc/patches/010-subshell.patch new file mode 100644 index 000000000..73d8ca949 --- /dev/null +++ b/mc/patches/010-subshell.patch @@ -0,0 +1,11 @@ +-- a/src/subshell/common.c ++++ b/src/subshell/common.c +@@ -836,7 +836,7 @@ init_subshell_precmd (char *precmd, size + "else " + "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; " + "fi; " +- "echo \"$USER@$(hostname -s):$MC_PWD\"; " ++ "echo \"$USER@$HOSTNAME:$MC_PWD\"; " + "pwd>&%d; " + "kill -STOP $$; " + "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]); diff --git a/mc/patches/020-fix-mouse-handling-newer-terminfo.patch b/mc/patches/020-fix-mouse-handling-newer-terminfo.patch new file mode 100644 index 000000000..82543379e --- /dev/null +++ b/mc/patches/020-fix-mouse-handling-newer-terminfo.patch @@ -0,0 +1,11 @@ +--- a/lib/tty/tty.c ++++ b/lib/tty/tty.c +@@ -370,7 +370,7 @@ tty_init_xterm_support (gboolean is_xter + if (xmouse_seq != NULL) + { + if (strcmp (xmouse_seq, ESC_STR "[<") == 0) +- xmouse_seq = ESC_STR "[M"; ++ xmouse_seq = NULL; + + xmouse_extended_seq = ESC_STR "[<"; + } diff --git a/mc/patches/030-fix-gettext-full-0.21.patch b/mc/patches/030-fix-gettext-full-0.21.patch new file mode 100644 index 000000000..af44dcf66 --- /dev/null +++ b/mc/patches/030-fix-gettext-full-0.21.patch @@ -0,0 +1,13 @@ +--- a/po/Makefile.in.in 2020-07-13 04:16:44.000000000 +0800 ++++ b/po/Makefile.in.in 2021-02-17 18:04:44.881887192 +0800 +@@ -8,8 +8,8 @@ + # Please note that the actual code of GNU gettext is covered by the GNU + # General Public License and is *not* in the public domain. + # +-# Origin: gettext-0.18 +-GETTEXT_MACRO_VERSION = 0.18 ++# Origin: gettext-0.20 ++GETTEXT_MACRO_VERSION = 0.20 + + PACKAGE = @PACKAGE@ + VERSION = @VERSION@ \ No newline at end of file From 1172142b85be73cfa2e335800ba650e64bbcde05 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Feb 2021 14:35:40 +0100 Subject: [PATCH 0131/2059] Force metric for 6in4 --- omr-6in4/files/bin/omr-6in4 | 3 ++- omr-6in4/files/etc/init.d/omr-6in4 | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/omr-6in4/files/bin/omr-6in4 b/omr-6in4/files/bin/omr-6in4 index c7eba5bfa..8bf094a50 100755 --- a/omr-6in4/files/bin/omr-6in4 +++ b/omr-6in4/files/bin/omr-6in4 @@ -31,6 +31,7 @@ while true; do uci -q batch <<-EOF set network.omr6in4.ipaddr=$addr set network.omr6in4.peeraddr=$peer + set network.omr6in4.metric=1 commit network EOF if [ -n "$(ip tunnel | grep omr6in4)" ]; then @@ -49,7 +50,7 @@ while true; do #[ -z "$ipv6_gw" ] && ipv6_gw='fe80::aff:ff01' ip -6 route add ${ipv6_gw} dev 6in4-omr6in4 > /dev/null 2>&1 ip -6 route 2002::/16 dev 6in4-omr6in4 > /dev/null 2>&1 - ip -6 route replace default via ${ipv6_gw} dev 6in4-omr6in4 > /dev/null 2>&1 + ip -6 route replace default via ${ipv6_gw} dev 6in4-omr6in4 metric 1 > /dev/null 2>&1 if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF set network.omr6in4_route6_default=route6 diff --git a/omr-6in4/files/etc/init.d/omr-6in4 b/omr-6in4/files/etc/init.d/omr-6in4 index 9d22cabb2..e9ef23296 100755 --- a/omr-6in4/files/etc/init.d/omr-6in4 +++ b/omr-6in4/files/etc/init.d/omr-6in4 @@ -64,6 +64,7 @@ set_ipv6_state() { set network.lan.ipv6="1" set network.lan.delegate="0" set network.omr6in4.force_link=1 + set network.omr6in4.metric=1 delete network.omr6in4.auto EOF if [ "$(network.lan.ip6assign)" = "" ]; then From fff416b868c3a0bfeb67f8295acd40870649bf76 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 11:37:00 +0100 Subject: [PATCH 0132/2059] Fix Hosts6 ofr omr-tracker --- omr-tracker/files/etc/init.d/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 67e72a3bc..574f14bec 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -19,7 +19,7 @@ _validate_section() { uci_validate_section omr-tracker "$1" "$2" \ 'hosts:list(host)' \ - 'hosts6:list(host6)' \ + 'hosts6:list(host)' \ 'timeout:uinteger' \ 'tries:uinteger' \ 'interval:uinteger' \ From b974317b37a150ea0a3738bfd4d913fc36291006 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 11:38:03 +0100 Subject: [PATCH 0133/2059] Use httping to ping server if option defined in omr-tracker --- omr-tracker/files/bin/omr-tracker | 96 ++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 21 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index e42a26cab..028d17cb7 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -87,16 +87,45 @@ _post_tracking() { } _ping_server() { - local serverip=$(uci -q get openmptcprouter.$1.ip) + local servername=$1 + local disabled=$(uci -q get openmptcprouter.$1.disabled) local device=$2 - if [ -n "$serverip" ] && [ -n "$device" ]; then - _ping $serverip $device "yes" - statusp=$? - if $(exit $statusp); then - serverip_ping=true - fi - else - serverip_ping=false + if [ -n "$device" ] && [ "$disabled" != "1" ]; then + check_ping() { + serverip=$1 + if [ -n "$serverip" ]; then + _ping $serverip $device "yes" + statusp=$? + if $(exit $statusp); then + serverip_ping=true + break + fi + fi + } + config_load openmptcprouter + config_list_foreach ${servername} ip check_ping + fi +} + +_httping_server() { + local servername=$1 + local disabled=$(uci -q get openmptcprouter.$1.disabled) + local port=$(uci -q get openmptcprouter.$1.port) + local device=$2 + if [ -n "$device" ] && [ "$disabled" != "1" ]; then + check_ping() { + serverip=$1 + if [ -n "$serverip" ]; then + _httping "${serverip}:${port}" $device "yes" true + statusp=$? + if $(exit $statusp); then + serverip_ping=true + break + fi + fi + } + config_load openmptcprouter + config_list_foreach ${servername} ip check_ping fi } @@ -138,18 +167,34 @@ _httping() { local host=$1 local deviceip=$2 local localip=$3 - ret=$(httping "${host}" \ - -y "${deviceip}" \ - -t "$OMR_TRACKER_TIMEOUT" \ - -c 1 \ - -q - ) && echo "$ret" | grep -sq "1 ok" && { - if [ "$localip" = "yes" ]; then - OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1) - _update_rto "$OMR_TRACKER_LATENCY" - fi - return - } + local https=$4 + if [ -z "$https" ] || [ "$https" = false ]; then + ret=$(httping "${host}" \ + -y "${deviceip}" \ + -t "$OMR_TRACKER_TIMEOUT" \ + -c 1 \ + -q + ) && echo "$ret" | grep -sq "1 ok" && { + if [ "$localip" = "yes" ]; then + OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1) + _update_rto "$OMR_TRACKER_LATENCY" + fi + return + } + else + ret=$(httping -l "${host}" \ + -y "${deviceip}" \ + -t "$OMR_TRACKER_TIMEOUT" \ + -c 1 \ + -q + ) && echo "$ret" | grep -sq "1 ok" && { + if [ "$localip" = "yes" ]; then + OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1) + _update_rto "$OMR_TRACKER_LATENCY" + fi + return + } + fi false } @@ -283,6 +328,10 @@ while true; do config_load openmptcprouter config_foreach _ping_server server $OMR_TRACKER_DEVICE fi + if [ "$OMR_TRACKER_TYPE" = "httping" ]; then + config_load openmptcprouter + config_foreach _httping_server server $OMR_TRACKER_DEVICE + fi if [ "$serverip_ping" = false ] && [ -n "$OMR_TRACKER_HOST" ]; then OMR_TRACKER_HOST=$(resolveip -4 -t 5 $OMR_TRACKER_HOST | head -n 1 | tr -d "\n") if [ -n "$OMR_TRACKER_HOST" ]; then @@ -366,6 +415,11 @@ while true; do config_load openmptcprouter config_foreach _ping_server server $OMR_TRACKER_DEVICE fi + if [ "$OMR_TRACKER_TYPE" = "httping" ]; then + config_load openmptcprouter + config_foreach _httping_server server $OMR_TRACKER_DEVICE + fi + if [ "$serverip_ping" = false ] && [ -n "$OMR_TRACKER_HOST6" ]; then OMR_TRACKER_HOST6=$(resolveip -6 -t 5 $OMR_TRACKER_HOST6 | head -n 1 | tr -d "\n") if [ -n "$OMR_TRACKER_HOST6" ]; then From fa9e14e0e8bf0d73bd91fe0617020739634ac10f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 11:38:35 +0100 Subject: [PATCH 0134/2059] Add in Network->MPTCP more info --- luci-app-mptcp/luasrc/controller/mptcp.lua | 17 ++++++++ .../luasrc/view/mptcp/mptcp_monitor.htm | 42 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index 383498a75..eb84bc718 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -17,6 +17,8 @@ function index() entry({"admin", "network", "mptcp", "mptcp_fullmesh_data"}, post("mptcp_fullmesh_data")).leaf = true entry({"admin", "network", "mptcp", "mptcp_connections"}, template("mptcp/mptcp_connections"), _("Established connections"), 6).leaf = true entry({"admin", "network", "mptcp", "mptcp_connections_data"}, post("mptcp_connections_data")).leaf = true + entry({"admin", "network", "mptcp", "mptcp_monitor"}, template("mptcp/mptcp_monitor"), _("MPTCP monitoring"), 6).leaf = true + entry({"admin", "network", "mptcp", "mptcp_monitor_data"}, post("mptcp_monitor_data")).leaf = true end function interface_bandwidth(iface) @@ -206,6 +208,21 @@ function mptcp_fullmesh_data() return end +function mptcp_monitor_data() + luci.http.prepare_content("text/plain") + local fullmesh + fullmesh = io.popen("cat /proc/net/mptcp_net/snmp") + if fullmesh then + while true do + local ln = fullmesh:read("*l") + if not ln then break end + luci.http.write(ln) + luci.http.write("\n") + end + end + return +end + function mptcp_connections_data() luci.http.prepare_content("text/plain") local connections diff --git a/luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm b/luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm new file mode 100644 index 000000000..ec4eb5606 --- /dev/null +++ b/luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm @@ -0,0 +1,42 @@ +<%+header%> + + + + +<% if stderr and #stderr > 0 then %>
    <%=pcdata(stderr)%>
    <% end %> +
    + + +
    +<%+footer%> From f29538776a0da1f4c1ccb4454c54f3bf25cd813b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 15:34:42 +0100 Subject: [PATCH 0135/2059] Fix for DHCPv6 interfaces --- .../root/usr/libexec/rpcd/openmptcprouter | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index b86f4d287..858ae5798 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1116,6 +1116,7 @@ function interfaces_status() local multipath = section["multipath"] local enabled = section["auto"] local proto = section["proto"] or "" + local ipv6 = section["ipv6"] or "0" --if not ipaddr or not gateway then return end -- Don't show if0 in the overview @@ -1130,8 +1131,8 @@ function interfaces_status() --end duplicateif = false - if ifname ~= "" and ifname ~= nil then - if allintf[ifname] and not section["ifname"]:match("^@.*") then + if ifname ~= "" and ifname ~= nil and not (section["ifname"] ~= nil and section["ifname"]:match("^@.*")) then + if allintf[ifname] then connectivity = "ERROR" duplicateif = true else @@ -1151,10 +1152,10 @@ function interfaces_status() if ipaddr == "" and ifname ~= nil and ifname ~= "" and proto ~= "dhcpv6" then ipaddr = ut.trim(sys.exec("ip -4 addr show dev " .. ifname .. " | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1 | tr -d '\n'")) end - if ip6addr == "" and ifname ~= nil and ifname ~= "" then + if ip6addr == "" and ifname ~= nil and ifname ~= "" and (ipv6 == "1" or ipv6 == "auto") then ip6addr = ut.trim(sys.exec("ip -6 -br addr ls dev " .. ifname .. " | awk -F'[ /]+' '{print $3}' | tr -d '\n'")) end - if ip6addr == "" and ifname ~= nil and ifname ~= "" then + if ip6addr == "" and ifname ~= nil and ifname ~= "" and (ipv6 == "1" or ipv6 == "auto") then ip6addr = ut.trim(sys.exec("ip -6 addr show dev " .. ifname .. " | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1 | tr -d '\n'")) end if ipaddr == "" and ip6addr == "" then @@ -1199,13 +1200,15 @@ function interfaces_status() if proto ~= "dhcpv6" then gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) end - gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) + if ipv6 == "1" or ipv6 == "auto" then + gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) + end end if gateway == "" and proto ~= "dhcpv6" then gateway = get_gateway(interface) end - if gateway == "" and ifname ~= nil and ifname ~= "" and proto ~= "dhcpv6" then + if gateway == "" and ifname ~= nil and ifname ~= "" and ipv6 ~= "1" and ipv6 ~= "auto" then if fs.access("/sys/class/net/" .. ifname) then gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep kernel | awk '/proto kernel/ {print $1}' | grep -v / | tr -d '\n'")) if gateway == "" then @@ -1213,10 +1216,10 @@ function interfaces_status() end end end - if gateway6 == "" then + if gateway6 == "" and (ipv6 == "1" or ipv6 == "auto") then gateway6 = get_gateway6(interface) end - if gateway6 == "" and ifname ~= nil and ifname ~= "" then + if gateway6 == "" and ifname ~= nil and ifname ~= "" and (ipv6 == "1" or ipv6 == "auto") then if fs.access("/sys/class/net/" .. ifname) then gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep kernel | awk '/proto kernel/ {print $1}' | grep -v / | tr -d '\n'")) if gateway6 == "" then From 275b9fcc06f39a72420e9afd1f6d0438a08878c8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 15:39:00 +0100 Subject: [PATCH 0136/2059] Fix tracker for DHCPv6 --- omr-tracker/files/bin/omr-tracker | 4 ++++ omr-tracker/files/etc/init.d/omr-tracker | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 028d17cb7..f9e4fa504 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -24,6 +24,8 @@ export OMR_TRACKER_DEVICE_IP export OMR_TRACKER_DEVICE_IP6 export OMR_TRACKER_DEVICE_GATEWAY export OMR_TRACKER_DEVICE_GATEWAY6 +export OMR_TRACKER_IPV6 +export OMR_TRACKER_PROTO dscp=56 # set DSCP CS7 (56) in outgoing packets initial_hosts="$OMR_TRACKER_HOSTS" @@ -279,6 +281,7 @@ while true; do OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | awk '/proto kernel/ {print $1}' | tr -d "\n") fi fi + if [ "$OMR_TRACKER_INTERFACE_IPV6" = "1" ] || [ "$OMR_TRACKER_INTERFACE_IPV6" = "auto" ]; then #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | grep -v 'inet6 f' | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) @@ -301,6 +304,7 @@ while true; do if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.nexthop="::"].target' | tr -d "\n") fi + fi # execute specific tracker if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 574f14bec..31c306a73 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -46,7 +46,7 @@ _launch_tracker() { loopback|lan*|if0*) return;; esac - local hosts hosts6 timeout tries interval interval_tries options type enabled wait_test + local hosts hosts6 timeout tries interval interval_tries options type enabled wait_test ipv6 proto _validate_section "defaults" "defaults" _validate_section "interface" "$1" @@ -59,6 +59,8 @@ _launch_tracker() { config_get multipath "$1" multipath config_get ifenabled "$1" auto config_get gateway "$1" gateway + config_get ipv6 "$1" ipv6 + config_get proto "$1" proto [ -z "$ifname" ] || [ -z "$multipath" ] || [ "$multipath" = "off" ] && [ "$1" != "glorytun" ] && [ "$1" != "omrvpn" ] && [ "$( uci -q get openmptcprouter.$1.multipathvpn)" != "1" ] && return [ "${ifenabled}" = "0" ] && return @@ -79,6 +81,8 @@ _launch_tracker() { procd_append_param env "OMR_TRACKER_DEVICE=$ifname" procd_append_param env "OMR_TRACKER_DEVICE_GATEWAY=$gateway" procd_append_param env "OMR_TRACKER_TYPE=$type" + procd_append_param env "OMR_TRACKER_IPV6=$ipv6" + procd_append_param env "OMR_TRACKER_PROTO=$proto" procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" procd_set_param limits nofile="51200 51200" procd_set_param respawn 0 10 0 From 0cc7e8d3c3f3094eb1dfdbc3d97e3e099c53bae4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 17:13:00 +0100 Subject: [PATCH 0137/2059] Fix IPv6 routes --- .../share/omr/post-tracking.d/post-tracking | 56 +++++++++++++++---- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index e00d99fee..9e839039a 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -206,13 +206,29 @@ set_routes_intf6() { #multipath_current_config=$(multipath $interface_if | grep 'deactivated') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_if" != "" ] && [ "$interface_up" = "true" ]; then - interface_gw="$(uci -q get network.$INTERFACE.gateway)" + interface_gw="$(uci -q get network.$INTERFACE.ip6gw)" + interface_ip6="$(uci -q get network.$INTERFACE.ip6)" + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}\"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/64\"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/56\"].nexthop' | tr -d "\n") + fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.nexthop="::"].target' | tr -d "\n") + fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.nexthop="::"].target' | tr -d "\n") + fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.${INTERFACE}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi @@ -300,12 +316,28 @@ set_route_balancing6() { interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then interface_gw="$(uci -q get network.$INTERFACE.gateway)" + interface_ip6="$(uci -q get network.$INTERFACE.ip6)" + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}\"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/64\"].nexthop' | tr -d "\n") + fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/56\"].nexthop' | tr -d "\n") + fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.nexthop="::"].target' | tr -d "\n") + fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") fi + if [ -z "$interface_gw" ]; then + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.nexthop="::"].target' | tr -d "\n") + fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.${INTERFACE}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi @@ -355,7 +387,7 @@ set_server_all_routes() { config_foreach set_routes_intf interface uintf="$(echo $routesintf | awk '{print $5}')" uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ "$(ip r show $serverip metric 0 | grep $uintf)" = "" ]); then + if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 0 | grep $uintf)" = "" ]); then while [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip r del $serverip done @@ -363,7 +395,7 @@ set_server_all_routes() { ip route replace $serverip scope global $routesintf [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" fi - if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then + if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ -n "$uintfb" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" ip route replace $serverip scope global metric 999 $routesintfbackup fi @@ -394,20 +426,20 @@ set_server_all_routes6() { nbintf6=0 nbintfb6=0 config_load network - config_foreach set_routes_intf interface - uintf="$(echo $routesintf | awk '{print $5}')" - uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then + config_foreach set_routes_intf6 interface + uintf="$(echo $routesintf6 | awk '{print $5}')" + uintfb="$(echo $routesintfbackup6 | awk '{print $5}')" + if [ -n "$routesintf6" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf6 " ]) || ([ "$nbintf6" = "1" ] && [ -n "$uintf" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip -6 r del $serverip done - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf" - ip -6 route replace $serverip scope global $routesintf + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf6" + ip -6 route replace $serverip scope global $routesintf6 [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" fi - if [ -n "$routesintfbackup" ] && ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb6" = "1" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb6 $OMR_TRACKER_DEVICE" - ip -6 route replace $serverip scope global metric 999 $routesintfbackup + if [ -n "$routesintfbackup6" ] && ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup6 " ]) || ([ "$nbintfb6" = "1" ] && [ -n "$uintfb" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup6 nbintfb $nbintfb6 $OMR_TRACKER_DEVICE" + ip -6 route replace $serverip scope global metric 999 $routesintfbackup6 fi fi } From 543a667e2cc891ad1fe2f4538e9611cb01a69591 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 17:13:30 +0100 Subject: [PATCH 0138/2059] Use -o instead of > for omr-test-speed --- openmptcprouter/files/bin/omr-test-speed | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index fa95ff2cc..0521e7bf1 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -24,7 +24,7 @@ done echo "Best server is $HOST, running test:" trap : HUP INT TERM if [ -z "$INTERFACE" ]; then - curl -4 $HOST >/dev/null || echo + curl -4 -o /dev/null $HOST || echo else domain=$(echo $HOST | awk -F/ '{print $3}') hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ') @@ -33,7 +33,7 @@ else ipset add ss_rules_dst_bypass_all $ip done fi - curl -4 --interface $INTERFACE $HOST >/dev/null || echo + curl -4 -o /dev/null --interface $INTERFACE $HOST || echo if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then for ip in $hostip; do ipset del ss_rules_dst_bypass_all $ip From a5e22f45115de48e97d70829b666fb12a49feba5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 17:15:17 +0100 Subject: [PATCH 0139/2059] Fix indentation --- openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks index 5880c13b0..91a0ad9cc 100755 --- a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks +++ b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks @@ -57,8 +57,9 @@ if [ "$(uci -q get shadowsocks-libev.hi3)" != "" ]; then uci -q batch <<-EOF >/dev/null set shadowsocks-libev.hi$c.local_port=$port set shadowsocks-libev.hi$c.server=sss0 + set shadowsocks-libev.hi$((c+1)).local_address="::" set shadowsocks-libev.hi$((c+1)).local_port=$port - set shadowsocks-libev.hi$((c+1)).local_address="::" + set shadowsocks-libev.hi$((c+1)).local_address="::" set shadowsocks-libev.hi$((c+1)).server=sss1 commit shadowsocks-libev EOF From d2658465d07da8a3c42c66a977797d494e74c7e7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Feb 2021 19:43:00 +0100 Subject: [PATCH 0140/2059] Fix IPv6 routes to server --- .../usr/share/omr/post-tracking.d/post-tracking | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 9e839039a..c2724f5fb 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -387,13 +387,13 @@ set_server_all_routes() { config_foreach set_routes_intf interface uintf="$(echo $routesintf | awk '{print $5}')" uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 0 | grep $uintf)" = "" ]); then + if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 1 | grep $uintf)" = "" ]); then while [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip r del $serverip done [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf" - ip route replace $serverip scope global $routesintf - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" + ip route replace $serverip scope global metric 1 $routesintf + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" fi if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ -n "$uintfb" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" @@ -429,13 +429,13 @@ set_server_all_routes6() { config_foreach set_routes_intf6 interface uintf="$(echo $routesintf6 | awk '{print $5}')" uintfb="$(echo $routesintfbackup6 | awk '{print $5}')" - if [ -n "$routesintf6" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf6 " ]) || ([ "$nbintf6" = "1" ] && [ -n "$uintf" ] && [ "$(ip -6 r show $serverip metric 0 | grep $uintf)" = "" ]); then + if [ -n "$routesintf6" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf6 " ]) || ([ "$nbintf6" = "1" ] && [ -n "$uintf" ] && [ "$(ip -6 r show $serverip metric 1 | grep $uintf)" = "" ]); then while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip -6 r del $serverip done [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route $serverip $routesintf6" - ip -6 route replace $serverip scope global $routesintf6 - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip -6 r show $serverip metric 0 | tr -d '\t' | tr -d '\n')" + ip -6 route replace $serverip scope global metric 1 $routesintf6 + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip -6 r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" fi if [ -n "$routesintfbackup6" ] && ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup6 " ]) || ([ "$nbintfb6" = "1" ] && [ -n "$uintfb" ] && [ "$(ip -6 r show $serverip metric 999 | grep $uintfb)" = "" ]); then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup6 nbintfb $nbintfb6 $OMR_TRACKER_DEVICE" From 8f490b9be77789ad3b8f25c4a448f884ca531049 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 20 Feb 2021 18:19:04 +0100 Subject: [PATCH 0141/2059] Fix previous fix --- .../usr/share/omr/post-tracking.d/post-tracking | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index c2724f5fb..ffbd09b41 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -209,13 +209,13 @@ set_routes_intf6() { interface_gw="$(uci -q get network.$INTERFACE.ip6gw)" interface_ip6="$(uci -q get network.$INTERFACE.ip6)" if [ -z "$interface_gw" ]; then - interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}\"].nexthop' | tr -d "\n") + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}\"].nexthop" | tr -d "\n") fi if [ -z "$interface_gw" ]; then - interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/64\"].nexthop' | tr -d "\n") + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/64\"].nexthop" | tr -d "\n") fi if [ -z "$interface_gw" ]; then - interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/56\"].nexthop' | tr -d "\n") + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/56\"].nexthop" | tr -d "\n") fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") @@ -318,13 +318,13 @@ set_route_balancing6() { interface_gw="$(uci -q get network.$INTERFACE.gateway)" interface_ip6="$(uci -q get network.$INTERFACE.ip6)" if [ -z "$interface_gw" ]; then - interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}\"].nexthop' | tr -d "\n") + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}\"].nexthop" | tr -d "\n") fi if [ -z "$interface_gw" ]; then - interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/64\"].nexthop' | tr -d "\n") + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/64\"].nexthop" | tr -d "\n") fi if [ -z "$interface_gw" ]; then - interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/56\"].nexthop' | tr -d "\n") + interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${interface_ip6}/56\"].nexthop" | tr -d "\n") fi if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") From c1cae86176234a0a9322fbe72b103155c137714f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Feb 2021 15:09:56 +0100 Subject: [PATCH 0142/2059] Modify and add some DSCP ports --- luci-app-omr-dscp/root/etc/config/dscp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/luci-app-omr-dscp/root/etc/config/dscp b/luci-app-omr-dscp/root/etc/config/dscp index a48c32232..cf300451f 100644 --- a/luci-app-omr-dscp/root/etc/config/dscp +++ b/luci-app-omr-dscp/root/etc/config/dscp @@ -1,28 +1,35 @@ config classify option direction 'both' option proto 'icmp' - option class 'cs5' + option class 'cs7' option comment 'ICMP' config classify option direction 'both' option proto 'udp' - option class 'cs5' + option class 'cs4' option src_port '53,123,5353' option comment 'DNS udp and NTP' config classify option direction 'both' option proto 'tcp' - option class 'cs5' + option class 'cs4' option src_port '53,5353' option comment 'DNS tcp' +config classify + option direction 'both' + option proto 'tcp' + option class 'cs4' + option src_port '65500' + option comment 'OMR API' + config classify option direction 'both' option proto 'tcp' option class 'cs6' - option dest_port '65001,65301,65011' + option dest_port '65001,65301,65401,65011' option comment 'OMR vpn' config classify @@ -32,6 +39,13 @@ config classify option dest_port '65001,65301' option comment 'OMR vpn' +config classify + option direction 'both' + option proto 'tcp' + option class 'cs6' + option dest_port '65101,65228' + option comment 'OMR proxy' + config domains option name 'googlevideo.com' option class 'cs4' From 06ef8a9353aa740188ff58da6f094ca0d5d33763 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Feb 2021 15:10:34 +0100 Subject: [PATCH 0143/2059] Hide server address for sysupgrade --- luci-app-sysupgrade/luasrc/view/sysupgrade.htm | 3 +++ .../root/www/luci-static/resources/sysupgrade.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/luci-app-sysupgrade/luasrc/view/sysupgrade.htm b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm index 7cb1efa9d..87b3cb85a 100644 --- a/luci-app-sysupgrade/luasrc/view/sysupgrade.htm +++ b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm @@ -99,12 +99,15 @@
    + +
    diff --git a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js index bfb2a83ba..9002d3ee0 100644 --- a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js +++ b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js @@ -98,7 +98,7 @@ function setup_ready() { upgrade_check(); } else { show("#upgrade_button"); - show("#server_div"); + //show("#server_div"); $("#server").value = data.url; } } From 5e502b1cf162d8c3dbaff99f7382a16026f6fd30 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Feb 2021 15:11:13 +0100 Subject: [PATCH 0144/2059] Update v2ray --- v2ray-core/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 206aa724f..4b7cfb71a 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -9,12 +9,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=v2ray-core -PKG_VERSION:=4.31.0 +PKG_VERSION:=4.34.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/v2ray/v2ray-core/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=4e475c700863320b92689cb36ef993133e9c799375bbfc4a2811da2283c3673f +PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/v$(PKG_VERSION) +PKG_HASH:=b250f569cb0369f394f63184e748f1df0c90500feb8a1bf2276257c4c8b81bee PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE From 5bf8b9923a0337938dfa3ff0114b97f1caf7ac2a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Feb 2021 15:12:00 +0100 Subject: [PATCH 0145/2059] Reload custom firewall rules when fw reload --- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index db2fcf39e..dda268ebe 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -201,6 +201,7 @@ done uci -q batch <<-EOF >/dev/null set firewall.@zone[0].mtu_fix='1' set firewall.zone_vpn.mtu_fix='1' + set firewall.@include[0].reload='1' commit firewall EOF From 7c2fd8f2ad7b54ee698f28b57df4afd4dfec101f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 25 Feb 2021 14:25:18 +0100 Subject: [PATCH 0146/2059] Rename zone wan and lan to zone_wan and zone_lan in fw --- .../luasrc/controller/openmptcprouter.lua | 10 ++--- .../luasrc/view/openmptcprouter/wizard.htm | 9 +++-- .../files/etc/uci-defaults/1980-omr-firewall | 37 +++++++++++++------ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index b71efc888..d67470a09 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -38,10 +38,10 @@ function wizard_add() local gostatus = true -- Force WAN zone firewall members to be a list - local fwwan = sys.exec("uci -q get firewall.@zone[1].network") - luci.sys.call("uci -q delete firewall.@zone[1].network") + local fwwan = sys.exec("uci -q get firewall.zone_wan.network") + luci.sys.call("uci -q delete firewall.zone_wan.network") for interface in fwwan:gmatch("%S+") do - luci.sys.call("uci -q add_list firewall.@zone[1].network=" .. interface) + luci.sys.call("uci -q add_list firewall.zone_wan.network=" .. interface) end ucic:save("firewall") @@ -185,7 +185,7 @@ function wizard_add() luci.sys.call("uci -q commit vnstat") -- Dirty way to add new interface to firewall... - luci.sys.call("uci -q add_list firewall.@zone[1].network=wan" .. i) + luci.sys.call("uci -q add_list firewall.zone_wan.network=wan" .. i) luci.sys.call("uci -q commit firewall") luci.sys.call("/etc/init.d/macvlan restart >/dev/null 2>/dev/null") @@ -217,7 +217,7 @@ function wizard_add() luci.sys.call("uci -q del_list vnstat.@vnstat[-1].interface=" .. defif) end luci.sys.call("uci -q commit vnstat") - luci.sys.call("uci -q del_list firewall.@zone[1].network=" .. intf) + luci.sys.call("uci -q del_list firewall.zone_wan.network=" .. intf) luci.sys.call("uci -q commit firewall") gostatus = false end diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index a0b5851e1..02e20ebad 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -372,7 +372,7 @@ <% for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() - local firewall_lan = luci.util.trim(luci.sys.exec("uci -q get firewall.@zone[0].network | grep " .. ifname)) + local firewall_lan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_lan.network | grep " .. ifname)) if firewall_lan ~= "" then %>

    <%=ifname%>

    @@ -475,7 +475,7 @@ <% for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() - local firewall_wan = luci.util.trim(luci.sys.exec("uci -q get firewall.@zone[1].network | grep " .. ifname)) + local firewall_wan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_wan.network | grep " .. ifname)) if firewall_wan ~= "" then -- local multipath = uci:get("network",ifname,"multipath") @@ -943,9 +943,10 @@
    -
    +
    - + +
    diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index dda268ebe..2bd9ba5d3 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -15,6 +15,21 @@ if [ "$(uci -q get firewall.@zone[2].name)" = "vpn" ]; then EOF fi +if [ "$(uci -q get firewall.@zone[1].name)" = "wan" ]; then + uci -q batch <<-EOF >/dev/null + rename firewall.@zone[1]="zone_wan" + del_list firewall.zone_wan.network="wan" + del_list firewall.zone_wan.network="wan6" + commit firewall + EOF +fi +if [ "$(uci -q get firewall.@zone[0].name)" = "lan" ]; then + uci -q batch <<-EOF >/dev/null + rename firewall.@zone[0]="zone_lan" + commit firewall + EOF +fi + if [ "$(uci -q get firewall.zone_vpn)" = "" ]; then uci -q batch <<-EOF >/dev/null set firewall.zone_vpn=zone @@ -91,12 +106,12 @@ if [ "$(uci -q show firewall | grep ICMPv6-Lan-to-OMR)" = "" ]; then EOF fi uci -q batch <<-EOF >/dev/null - del_list firewall.wan.masq_dest='!10.0.0.0/8' - del_list firewall.wan.masq_dest='!172.16.0.0/12' - del_list firewall.wan.masq_dest='!192.168.0.0/16' - add_list firewall.wan.masq_dest='!10.0.0.0/8' - add_list firewall.wan.masq_dest='!172.16.0.0/12' - add_list firewall.wan.masq_dest='!192.168.0.0/16' + del_list firewall.zone_wan.masq_dest='!10.0.0.0/8' + del_list firewall.zone_wan.masq_dest='!172.16.0.0/12' + del_list firewall.zone_wan.masq_dest='!192.168.0.0/16' + add_list firewall.zone_wan.masq_dest='!10.0.0.0/8' + add_list firewall.zone_wan.masq_dest='!172.16.0.0/12' + add_list firewall.zone_wan.masq_dest='!192.168.0.0/16' EOF if [ "$(ubus call system board | jsonfilter -e '@.board_name')" = "bananapi,bpi-r2" ] || [ "$(ubus call system board | jsonfilter -e '@.board_name' | grep -i wrt)" != "" ]; then uci -q batch <<-EOF >/dev/null @@ -124,7 +139,7 @@ if [ "$(uci -q get firewall.gre_tunnel)" = "" ]; then fi if [ "$(uci -q get firewall.fwlantovpn)" = "" ]; then uci -q batch <<-EOF >/dev/null - set firewall.@zone[0].auto_helper='0' + set firewall.zone_lan.auto_helper='0' set firewall.fwlantovpn=forwarding set firewall.fwlantovpn.src='lan' set firewall.fwlantovpn.dest='vpn' @@ -187,10 +202,10 @@ if [ "$(uci -q get firewall.allowdhcpv6546)" = "" ]; then fi # Fix firewall config from some old config -allintf=$(uci -q get firewall.@zone[1].network) -uci -q del firewall.@zone[1].network +allintf=$(uci -q get firewall.zone_wan.network) +uci -q del firewall.zone_wan.network for intf in $allintf; do - uci -q add_list firewall.@zone[1].network=$intf + uci -q add_list firewall.zone_wan.network=$intf done allintf=$(uci -q get firewall.zone_vpn.network) uci -q del firewall.zone_vpn.network @@ -199,7 +214,7 @@ for intf in $allintf; do done uci -q batch <<-EOF >/dev/null - set firewall.@zone[0].mtu_fix='1' + set firewall.zone_lan.mtu_fix='1' set firewall.zone_vpn.mtu_fix='1' set firewall.@include[0].reload='1' commit firewall From a254d4aaed7b9a85216ca13423fcb1ed1b2262bf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 25 Feb 2021 14:25:52 +0100 Subject: [PATCH 0147/2059] Add check for duplicate mac --- .../luasrc/view/openmptcprouter/wanstatus.htm | 14 +++++++--- .../root/usr/libexec/rpcd/openmptcprouter | 26 +++++++++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 794dccb31..4a3421d3b 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -455,6 +455,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm var multipath_available = mArray.wans[i].multipath_available; var multipath_state = mArray.wans[i].multipath_state; var duplicateif = mArray.wans[i].duplicateif; + var duplicatemac = mArray.wans[i].duplicatemac; // Generate template if(mArray.openmptcprouter.remote_from_lease == true && mArray.wans.length == 1) { @@ -547,12 +548,12 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm if(gateway == '' && gateway6 == '') { statusMessage += '<%:No gateway defined%>' + '
    '; - } else if(gw_ping == 'DOWN') + } else if(gateway != '' && gw_ping == 'DOWN') { statusMessage += '<%:Gateway DOWN%>' + '
    '; - } else if(gw_ping6 == 'DOWN') + } else if(gateway6 != '' && gw_ping6 == 'DOWN') { - statusMessage += '<%:Gateway DOWN%>' + '
    '; + statusMessage += '<%:Gateway IPv6 DOWN%>' + '
    '; } else if(multipath_available == 'ERROR') { statusMessage += '<%:Multipath seems to be blocked on the connection%>' + '
    '; @@ -566,7 +567,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm statusMessage += '<%:Wan IP and gateway are identical%>' + '
    '; statusMessageClass = "error"; } - if (stat == 'Offline' && ip6addr != '' && ipaddr == mArray.wans[i].gateway6) + if (stat == 'Offline' && ip6addr != '' && ip6addr == mArray.wans[i].gateway6) { statusMessage += '<%:Wan IP and gateway are identical%>' + '
    '; statusMessageClass = "error"; @@ -595,6 +596,11 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm statusMessage += '<%:Network interface duplicated%>' + '
    '; statusMessageClass = "error"; } + if(duplicatemac) + { + statusMessage += '<%:Network interface MAC address duplicated%>' + '
    '; + statusMessageClass = "error"; + } if(ipv6_discover == 'DETECTED') { statusMessage += '<%:IPv6 route received%>' + '
    ' diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 858ae5798..0708e3f03 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1105,6 +1105,7 @@ function interfaces_status() mArray.wans = {} mArray.tunnels = {} allintf = {} + allmac = {} uci:foreach("network", "interface", function (section) local interface = section[".name"] @@ -1117,6 +1118,7 @@ function interfaces_status() local enabled = section["auto"] local proto = section["proto"] or "" local ipv6 = section["ipv6"] or "0" + local mac = section ["macaddr"] or "" --if not ipaddr or not gateway then return end -- Don't show if0 in the overview @@ -1140,6 +1142,16 @@ function interfaces_status() end end + duplicatemac = false + if mac ~= "" and mac ~= nil and not (section["ifname"] ~= nil and section["ifname"]:match("^@.*")) then + if allmac[mac] then + connectivity = "ERROR" + duplicatemac = true + else + allmac[mac] = true + end + end + --if multipath == "off" and not ifname:match("^tun.*") then return end if multipath == "off" then return end @@ -1237,7 +1249,7 @@ function interfaces_status() if gateway ~= "" then local gw_ping_test = "" if ifname ~= "" and ifname ~= nil then - gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 -I " .. ifname .. " " .. gateway .. " | grep '100% packet loss'")) + gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 -B -I " .. ifname .. " " .. gateway .. " | grep '100% packet loss'")) else gw_ping_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway .. " | grep '100% packet loss'")) end @@ -1247,11 +1259,13 @@ function interfaces_status() connectivity = "WARNING" end end + else + gw_ping = "DOWN" end if gateway6 ~= "" then local gw_ping6_test = "" if ifname ~= "" and ifname ~= nil then - gw_ping6_test = ut.trim(sys.exec("ping -w 1 -c 1 -I " .. ifname .. " " .. gateway6 .. " | grep '100% packet loss'")) + gw_ping6_test = ut.trim(sys.exec("ping -w 1 -c 1 -B -I " .. ifname .. " " .. gateway6 .. " | grep '100% packet loss'")) else gw_ping6_test = ut.trim(sys.exec("ping -w 1 -c 1 " .. gateway6 .. " | grep '100% packet loss'")) end @@ -1261,6 +1275,8 @@ function interfaces_status() connectivity = "WARNING" end end + else + gw_ping6 = "DOWN" end end if uci:get("openmptcprouter", interface, "manufacturer") == "huawei" then @@ -1346,6 +1362,10 @@ function interfaces_status() multipath_available = "NO CHECK" end + local zonewan = "NO" + if ut.trim(sys.exec("uci -q get firewall.zone_wan.networks | grep '" .. interface .. "'")) ~= "" then + zonewan = "OK" + end -- Detect if WAN get an IPv6 local ipv6_discover = "NONE" @@ -1449,6 +1469,7 @@ function interfaces_status() multipath_available = multipath_available, multipath_state = current_multipath_state, duplicateif = duplicateif, + duplicatemac = duplicatemac, signal = signal, operator = operator, phonenumber = phonenumber, @@ -1457,6 +1478,7 @@ function interfaces_status() proto = proto, rx = rx, tx = tx, + zonewan = zonewan, } if ifname ~= nil and ifname:match("^tun.*") then table.insert(mArray.tunnels, data); From 9f809347d2fabb234163b38c2a99e70e45418d5d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 25 Feb 2021 14:26:41 +0100 Subject: [PATCH 0148/2059] Fix duplicate mac address fix --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index a405f4bd0..663c5cc91 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -131,7 +131,7 @@ interface_multipath_settings() { uci -q set openmptcprouter.${config}.multipath="$mode" config_get macaddr "$config" macaddr "" - [ -n "$maccaddr" ] && { + [ -n "$macaddr" ] && { nbmac=0 config_foreach interface_macaddr_count interface $macaddr [ "$nbmac" != "1" ] && { From 519c6f7e4e9c7f78095fae7a8b5594efc82dbdec Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 25 Feb 2021 14:28:07 +0100 Subject: [PATCH 0149/2059] Update theme argon --- luci-theme-argon/Makefile | 15 +- luci-theme-argon/README.md | 75 +- luci-theme-argon/README_ZH.md | 17 +- .../Screenshots/screenshot_pc.jpg | Bin 0 -> 673706 bytes .../Screenshots/screenshot_phone.jpg | Bin 0 -> 467306 bytes .../luci-static/argon/background/README.md | 2 +- .../htdocs/luci-static/argon/css/cascade.css | 899 +++--------- .../htdocs/luci-static/argon/css/dark.css | 65 +- .../htdocs/luci-static/argon/css/fonts.css | 4 +- .../htdocs/luci-static/argon/css/pure-min.css | 2 +- .../htdocs/luci-static/argon/favicon.ico | Bin 0 -> 15406 bytes .../htdocs/luci-static/argon/favicon.png | Bin 535 -> 0 bytes .../luci-static/argon/icon/favicon-16x16.png | Bin 0 -> 1019 bytes .../luci-static/argon/icon/favicon-32x32.png | Bin 0 -> 1720 bytes .../luci-static/argon/icon/favicon-96x96.png | Bin 0 -> 3650 bytes .../htdocs/luci-static/argon/icon/favicon.png | Bin 535 -> 0 bytes .../htdocs/luci-static/argon/js/jquery.min.js | 2 +- .../luci-static/argon/js/polyfill.min.js | 3 + .../htdocs/luci-static/argon/js/script.js | 7 +- .../luci-static/argon/less/cascade.less | 1200 ++++------------- .../htdocs/luci-static/argon/less/dark.less | 68 +- .../luasrc/view/themes/argon/footer.htm | 12 +- .../luasrc/view/themes/argon/footer_login.htm | 46 + .../luasrc/view/themes/argon/header.htm | 235 ++-- .../luasrc/view/themes/argon/header_login.htm | 84 +- .../view/themes/argon/out_footer_login.htm | 27 + .../view/themes/argon/out_header_login.htm | 6 +- .../luasrc/view/themes/argon/sysauth.htm | 38 +- .../root/etc/uci-defaults/30_luci-theme-argon | 17 +- 29 files changed, 909 insertions(+), 1915 deletions(-) create mode 100644 luci-theme-argon/Screenshots/screenshot_pc.jpg create mode 100644 luci-theme-argon/Screenshots/screenshot_phone.jpg create mode 100644 luci-theme-argon/htdocs/luci-static/argon/favicon.ico delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/favicon.png create mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png create mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon-32x32.png create mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon-96x96.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon.png create mode 100644 luci-theme-argon/htdocs/luci-static/argon/js/polyfill.min.js create mode 100644 luci-theme-argon/luasrc/view/themes/argon/footer_login.htm create mode 100644 luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm diff --git a/luci-theme-argon/Makefile b/luci-theme-argon/Makefile index c8833c4cf..1f786223e 100644 --- a/luci-theme-argon/Makefile +++ b/luci-theme-argon/Makefile @@ -8,18 +8,9 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Argon Theme LUCI_DEPENDS:= -PKG_VERSION:=2.2.4 -PKG_RELEASE:=20200821 +PKG_VERSION:=2.2.6 +PKG_RELEASE:=20210215 include $(TOPDIR)/feeds/luci/luci.mk -define Package/luci-theme-argon/postinst -#!/bin/sh -sed -i ":a;$!N;s/tmpl.render.*sysauth_template.*return/local scope = { duser = default_user, fuser = user }\nlocal ok, res = luci.util.copcall\(luci.template.render_string, [[<% include\(\"themes\/\" .. theme .. \"\/sysauth\"\) %>]], scope\)\nif ok then\nreturn res\nend\nreturn luci.template.render\(\"sysauth\", scope\)/;ba" /usr/lib/lua/luci/dispatcher.lua -[ -f /usr/lib/lua/luci/view/themes/argon/out_header_login.htm ] && mv -f /usr/lib/lua/luci/view/themes/argon/out_header_login.htm /usr/lib/lua/luci/view/header_login.htm -rm -Rf /var/luci-modulecache -rm -Rf /var/luci-indexcache -exit 0 -endef - -# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-theme-argon/README.md b/luci-theme-argon/README.md index f55585443..11b84a6f8 100644 --- a/luci-theme-argon/README.md +++ b/luci-theme-argon/README.md @@ -1,36 +1,58 @@ -# luci-theme-argon ([中文](/README_ZH.md)) +
    + +

    + A new LuCI theme for OpenWrt +

    +

    + Argon is a clean HTML5 theme for LuCI. Users may
    setup their own favorite logins, including beautiful
    pics and customized mp4 videos.

    +

    -[1]: https://img.shields.io/badge/license-MIT-brightgreen.svg -[2]: /LICENSE -[3]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg -[4]: https://github.com/jerrykuku/luci-theme-argon/pulls -[5]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg -[6]: https://github.com/jerrykuku/luci-theme-argon/issues/new -[7]: https://img.shields.io/badge/release-v2.2.4-blue.svg? -[8]: https://github.com/jerrykuku/luci-theme-argon/releases -[9]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total -[10]: https://img.shields.io/badge/Contact-telegram-blue -[11]: https://t.me/jerryk6 -[![license][1]][2] -[![PRs Welcome][3]][4] -[![Issue Welcome][5]][6] -[![Release Version][7]][8] -[![Release Count][9]][8] -[![Contact Me][10]][11] + + + -![](/Screenshots/screenshot_pc.jpg) -![](/Screenshots/screenshot_phone.jpg) + + + + + + + + + + + + + + + + + + + +
    +
    +
    + +
    -A new Luci theme for LEDE/OpenWRT -Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template +
    English | [简体中文](README_ZH.md) ## Notice +It is strongly recommended to use the Chrome browser. Some new css3 features are used in the theme, and currently only Chrome has the best compatibility. +The mainline version of IE series currently has bugs to be resolved. +FireFox does not enable the backdrop-filter by default, see here for the opening method: https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter v2.x.x Adapt to official mainline snapshot. You can checkout branch 18.06 for OpenWRT 18.06 or lean 19.07. -## Update log 2020.08.21 v2.2.4 +## Update Log 2020.09.13 v2.2.5 +- 【v2.2.5】New config app for argon theme. You can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.[Chrome is recommended] [Download](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) +- 【v2.2.5】Automatically set as the default theme when compiling. +- 【v2.2.5】Modify the file structure to adapt to luci-app-argon-config. The old method of turning on dark mode is no longer applicable, please use it with luci-app-argon-config. +- 【v2.2.5】Adapt to Koolshare lede 2.3.6。 +- 【v2.2.5】Fix some Bug。 - 【v2.2.4】Fix the problem that the login background cannot be displayed on some phones. - 【v2.2.4】Remove the dependency of luasocket. - 【v2.2.3】Fix Firmware flash page display error in dark mode. @@ -78,16 +100,19 @@ make -j1 V=s ### For Lean openwrt 18.06 LuCI ``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.6.9/luci-theme-argon_1.6.9-20200821_all.ipk +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.0/luci-theme-argon_1.7.0-20200909_all.ipk opkg install luci-theme-argon*.ipk ``` ### For openwrt official 19.07 Snapshots LuCI master ``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.4/luci-theme-argon_2.2.4-20200821_all.ipk +opkg install luci-compat +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.5/luci-theme-argon_2.2.5-20200914_all.ipk opkg install luci-theme-argon*.ipk ``` +![](/Screenshots/screenshot_pc.jpg) +![](/Screenshots/screenshot_phone.jpg) ## Thanks to diff --git a/luci-theme-argon/README_ZH.md b/luci-theme-argon/README_ZH.md index 2998ea726..b229fa4fe 100644 --- a/luci-theme-argon/README_ZH.md +++ b/luci-theme-argon/README_ZH.md @@ -5,7 +5,7 @@ [4]: https://github.com/jerrykuku/luci-theme-argon/pulls [5]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg [6]: https://github.com/jerrykuku/luci-theme-argon/issues/new -[7]: https://img.shields.io/badge/release-v2.2.4-blue.svg? +[7]: https://img.shields.io/badge/release-v2.2.5-blue.svg? [8]: https://github.com/jerrykuku/luci-theme-argon/releases [9]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total [10]: https://img.shields.io/badge/Contact-telegram-blue @@ -23,14 +23,21 @@ 全新的 Openwrt 主题,基于luci-theme-material 和 开源免费的 Argon 模板进行移植。 ## 注意 - +强烈建议使用Chrome 浏览器。主题中使用了一些新的css3特性,目前只有Chrome有最佳的兼容性。 +主线版本 IE 系列目前还有Bug有待解决。 +FireFox 默认不开启backdrop-filter,开启方法见这里:https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter 当前master版本基于官方 OpenWrt 19.07.1 稳定版固件进行移植适配。 v2.x.x 适配主线快照版本。 v1.x.x 适配18.06 和 Lean Openwrt [如果你是lean代码 请选择这个版本] -## 更新日志 2020.08.21 v2.2.4 +## 更新日志 2020.09.13 v2.2.5 +- 【v2.2.5】全新的设置app.你可以设置argon 主题的登录页面的模糊和透明度,并管理背景图片与视频。[建议使用 Chrome][点击下载](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) +- 【v2.2.5】当编译固件时,将自动设置为默认主题。 +- 【v2.2.5】修改文件结构,以适应luci-app-argon-config,旧的开启暗色模式方法将不再适用,请搭配luci-app-argon-config使用。 +- 【v2.2.5】适配Koolshare lede 2.3.6。 +- 【v2.2.5】修复了一些Bug。 - 【v2.2.4】修复了在某些手机下图片背景第一次加载不能显示的问题。 - 【v2.2.4】取消 luasocket 的依赖,无需再担心依赖问题。 - 【v2.2.3】修正了在暗色模式下,固件刷写弹窗内的显示错误。 @@ -78,14 +85,14 @@ make -j1 V=s ### Lean源码 ``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.6.9/luci-theme-argon_1.6.9-20200821_all.ipk +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.0/luci-theme-argon_1.7.0-20200909_all.ipk opkg install luci-theme-argon*.ipk ``` ### For openwrt official 19.07 Snapshots LuCI master ``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.4/luci-theme-argon_2.2.4-20200821_all.ipk +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.5/luci-theme-argon_2.2.5-20200914_all.ipk opkg install luci-theme-argon*.ipk ``` diff --git a/luci-theme-argon/Screenshots/screenshot_pc.jpg b/luci-theme-argon/Screenshots/screenshot_pc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c355449a3aa732fd06f2b69fd6f6bd1f0342647 GIT binary patch literal 673706 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 <9F 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

    3fNN(I!%o6!(io%Ea>{!`= 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 z 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%0A9b24siOI!3$VDy&gqgCsc!e{XLM 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

    CT{pxmNUcw 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

    BW9zrHP>w3I!v}o((L?t| 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�XmH0BX8{7Fo+5_+B0y51fCh=1gyC_ zeXDGwYgHUUY2B>`nY(|p5Lr|Z&k_gB0`RKZrt{$GR&#&7HlmXJ?(=0}j3Id2pjK2ft}>dMx~ z>W}yai=Pg_+G}HdKJktlogUT;b`9NQHB(S=c{-V^8R5$P9T&rtl`H&B``6^XQ~+9o z*$Aq6f3+s)1p}wf)Z5fwY}Oae&vPGjtWy_F^v=FNf9a^;9`)KG63`7#io^EVU%0AU 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π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¨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

    Tr`~umt5;lf?z^s5VIro`H-P%l~ge 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 ZAOB9FaQ^)_;C1{vo%?^F!*c$G{}-XHNrC_X literal 0 HcmV?d00001 diff --git a/luci-theme-argon/Screenshots/screenshot_phone.jpg b/luci-theme-argon/Screenshots/screenshot_phone.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8237a0368813d8d7b9c9db585e088db8c999ed06 GIT binary patch literal 467306 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�+7nJaJ7mB9sLzVyJJZ=+*$74h7n0@`hdg#0= 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

    lOFHKxW{3#(Fx9m%qBfZq)kvVO1c3-Pc^W;%aRL zR}-FneUQ28@74|ue=sG`o0jRT1#%+o($jy*tUybf=3T9US$b%T*j|)Ax?EPwq?!xs3kW;ZSKlaf zj_x;22c{+W)SDPvi{Iz0U;n&Hue@Q#_e!52UC-3UC`!^ zmAI_;aW!E=Q)+L{);#LojW5Dt@vLZ-htD__?1(1%?T0Iek_xOU)8$71r;s4K`*UcZG-k+=gtiUX9Nw4g{bs=2 z;H3Qz-tv7OBjstt_2NDR0O6TCH2#S=TpXw4T*Sgvl)PS4UZDJiDvh>Wu+;bE83X{^ z*gLekJlj{lIvI90JMWj&5q)SL-gtqUjBx&FV^X0(iT*0J*3{OC1KR|A_@JM4IC+G<#nF`RuwvHhQqlu?%g7@q4oPb z*7AAcO=u10Z4y_@slhhQ{#pRPzR()zW1Tn-6EQD*-tD||@~t{64Q}Urc3roKm#GtO zRnmB2@t)ltrbnDP3<~SbG5`X2gRH{-(Eb1V`>AHzZyi65!-_wLSN_qf#e zsj8IHk&7JMJ2|k&^O6RYe)VOmK7Yc~;Kp~UncM6q%At3{w<{|Kb6#Nc==Fd9AYc3a zzd#=SCxHJ$a?!_QhmnsbI3~egK}CbCs3!FW9E>ZU$S?_|Y%&RbkNE{ z!zv^u`nB*Vz_rgqW?=Q^6S%(#C`;6RAKE)h*X;WsnyHp`{6fPOX4uHS&x|ZSo3`8+ zq?TJuLtK}nGn;>6CsBOmnM^Uxfjf0gid0!ai>YtvZ^a7nR6V~f>M*uZl&iPFzEXssg?a+%YXvHjL@<{fLQ#*G5W01a zU723&8L%iTxsh62Agdu_Iwh$WFR(dU~9+-b27ai}6@2Oe>HU)mxB{C!i2sQVkSS z7^2Uq5E)Q1=~_>9Kba~!Mugc(B1Hn_niJ`=x1+}gf@L>x)vOfbAa?(RH+?eQPJJGp z?=RLbUqZxs2u=q#sahUfMnFu%*|fUBJUBqArQ4R@*YKp?Clu*{%9;bO-%puTJH1Y6 z={Y)Z-SiLm?Y;_6W%ta)Nqn?lL01mcc#bYCAYVX z+1AT*4!t%*r~2=*+6+eL;^#pfA2I^XG`yiYFAPBtbHI%H5&?S1)Ck6(OV>a(# z6~oqnShT)EyUYuTQFGriLdDevU_=%9*DX4vg>?ab7gJlf_6cR6v4;x*W?N`u=flxWTzDLn>l6BOq2S zuLrr%K@H|xS0XfkjQfc)W5x?K7U0bL7R7Xs;Jm8q3ex#`_mly46~%=7;ZWnD1!x66IW zP5D3Jz0!PsJO4#ipoek@;6go_tpDwicj$!y#?wOoge9GkB1~#K6LuAp0_*qw`*c0% z&*}P@|HkS1ORuY$)Ah}BJMmkV@Bewae#!D?bZ`7enC&+sJ%5TPpX0_a|B-lgd8@?~ z!XFDQX>1>w%%?3wN7DS=7*O{BC=?h zGU8mJTV`N{4Ez1|4c}v4e+3uU69*mS_f35Hg?f6FA$zw%Ztot(gfHV}8>&cW; zCKk@CK|UZ1PIoG9bjPQ9^n|C zq%NR(S%@3cODcUeUbLwv(fQ%E5vwQyRn(#VOBt2BmZJ#jK2^i4T%U> z?sJqeM|<5{%ay(1PSn!l|5*5`&5s7rTacP{A2h7?9?6XhLKf zJra@+D-ZDHE_k=k)@))uIbmkh#bb~q^a1$6VEu}aR$}gnDGX=zA#OAniG_C8M~FF-TB#bI^aR`emDgIK&!S`zhT zM1Sul-CaDo-!0gOfvtvFi>Ds4w+Ul4^rDWyR>kU-y!3e|(uVCi(F zjp^Vvq-gpVO{2c&#zSK`a+-M13!WNg3CDR+X2qR0%#7QbUN@QC|KkD^v8i_NkDbnZ z{M`TMVGsb&^T!^4+4IkvT;q=jXu|f(y)XNVP038%J%ZBF8=$gBhf&??PSfc&Wgb*rF)A>H%_r_k+ z)(v8w9`EgynZ)ndX$a>&z+)D>X91axKi5zcCeyEi zcUu57xQDnDHxO>-C->l5GS9MbW*MMFB^MP_NehVR|rNmgKo+v={01J3ZhpWADe;_r@I$nV z9v2tC&WV7ls2)>K?RTn}`NPY-FYC;LO(4fDCe}*ndty<>TCahCx=nUL}XScka;f!09D&}>rx@Ds)vhHV?Xnx z4gv_2gP>QjwwIf~`#4;ZvKahKb_iFf@Hok?WJu?kGo|xZ9>36K#QqWbfT()AqaJqr z*!cfU&3ZNO(W-c5ufS>fu(r1QKhgcU?dCa~?9tyJ^^FP0e=C5C7DOI1?WQ|Fznsi_ zA08q##K<*6vliMLKI7Ny3(~ik539C{zNV;4+3)Kq5YjY0KHO~x*^%@JOya0-ZNGl) zM%^JE7>qr>^WVL?d6iDaMa89X2$+hip%28!H(O5q{e@5c^%nmBvifPqqUEigD$&$G zVZqsUml0}$1^rZ4dyXsCqF5(x!qNe+6)}0wK3V8xY&gNOxoa~{zhtR?D1=GO+_UzW zKhM?jiMsu!?gerEike~xkJ^@a7f z6HI7+-*1}v|6tGj*S&+e@H_i){OeOD_dKBcQ0mh^>nwc5m=fnrt=9dEOplu(!#^rl zKRx;n;B#+2)kFk{(nEGkJ!#3iRaRV{p6R!i>r%MbQ#3dWYT4>8lMtUKutaO;@32D} z5J?HXQ_rPR#xISykFt0%=C+VZ10v~J)jU&RaFPSTfuyYuM(OFf-4*V9L+@+0j6s!s zFGL9@`vx`RJSd+Dkqq3hrKD68RVwPs+;p%Xr;$RF-w(SQ_j!KX<|Le5L4l#Lb_zEF z{I?IfVEJ&g7*=W!kIK%9Os@v}3Vb)pcoI`3^8v7%u-K6}*}+v(te3D%2$r3qp8Uk3 zb_aae`FNTK?ktt~MjhgE{QIf)Q){l*5||yWyPw}FXa2mP-AX;abG7i@H$cUg-%nls znfW}e|HkK?0sXBFEx7J3DQ3mfFDYPQANY!LP~1bU*k(ciZoELFhqz!oIC$6e&-A+U77xr!9c%+>*3 zL+La<pSQd7?JMA~Ga$~fwo8gjRt|OxdFBNrU>8BLfRSTmV znFCaLlF-wE;Pw2zK*uJW+n{yF&caBmdpZfox5Z|t(j+~JYw!df261OYchx)!KFhHY3iG z?`4;y5}&lOuaO*ChT(=~GFIasbg!Cz*&Xvsz;Lh8dW*Rt;}bHx-Y zT})(XtSq!?72%FFr9|(!$#}8BVWx_41vTa@ys#D5Sj$B+NPTpf&B$Dp7ULW~80O_F zRd?9@^92bi(_4fSpN`NG=3zXYKj(m7ltd3f@D6Y44tA++b`sE-nTZ?W;4k~)@CB3F zSssbuIDo%5<*YnsTV9LD^-uZ6ch5> z+iL(N@6!kb+y@7&vYMYKVehELsdbP$g8;lz#;h1%B%Uq)-0(KDPjFi&x^3#;{6{YO z&e-v%&B}T5nSH+fZd@lJYlrl^^OgRVnunaC_>mU&BGCfHERp@#i! zA{0TGjrM4IgoG6`x==lkz5w&Gi?DKvlc~MFk{KH4VTE1fMquK9v*NUZqAVA*QE*sc zxd2K8zl)*1huY?%+cHo|P`J2H#z}U>gYoE*DNF`!xG(Zrsfffd9ydseGyCqGhK4l? zrD&Fkr`$CP$oS-_DW~VG@6a_;Z|)*D;F2q`yL|X5nGu~nHK6*k@z|!k0RfB}%aUWAX|JkKO~24*Qr&oqR{cO-#LmS}?Rrv!V-S5;tIhJ`C|?rx z^PK8J{zQU<{Gbd;R}n`RPMb2vBo`%dR+6HlnpkNp#(}V#yiD6zqY2=9#~Qhe*Hh&1 zYDc9=#rH0{%|aue?n{!@3iMI56!TYuOYkK#n~M8e5_?4!)raWYA1yt3j#p0U@JLgZ}$27 zHuZU(rLD$B>|_{u5Q_7D^)5liRWqc@H=pP%*wj#AR7^@IsHrNw2Ge+#xTblK;dpH7 zkj(n&=Kjzy?={vm8!d@!nJ3(}GWxktA~-|X?}}`TM#-;%!fo1_>?$Ahhsw+~5)0s7 z{SzvbxeA%Pvl{}%nZbiyPq2Isc|X6!M!L?z~TwB zPpT7TFSK7oC+m6d$m4ZOEL)^+)C!!{V0$kElbKP@hLKE%HUm>8C>*cav9Qp~co5zT zWJKH(ud0&c(MIlVX^S1&<>b(lf>JlE{8LVU&#m;D0Ha)zxy&U#3qt3?x9YbjuPo5) z`$!;bDwnV1GphpKxaJ`nZ*AuhDcnjE`XIyI{Ha=%2#_TX0KD01AO|-xCE)I$E!1Xx zQ7es`VhVBv(2cxuk+p0IdXw`=?Abn>%jFA5*vb7@U6mXH5otY(@-c}FM`0HLH%CcG zkjqG=SN#uTXPnpSqS}-D*ksDw9g62Nz_r=3O8OYmUXqv{V5wlOBf-Adud4tzEd5n0 zZO(@w+)R^E;hn+N6a?j`tgVa6;koF3F)RIwolg~eO@V8+?gkMF&WQb{+&Lmp_Z6as zNN=QDm`WC`4wJ0?MW7&eLeI?&1TcwUw0kv?G-Q-alrcIzG59|F3cQER`S`bDBu`}b4hbqZ2m@P}ZBzigi+|FC^NPy27Sect~=O#IYq z;HvxZQF9RHbLv*)X3^mBW3n0cBo1m4pD*F?`zgIUe^lzu{>Mt)6^cIsTI;`L`NbXy z)iT`CE}f4!ygS$xa&o>JBw*?;po+yNIdT!KbBQ#>bP=ya-urn~5NFQa3Mm+Pxt3YPZA} zsl+4;I>KjH&sA_DZ>kpr0QCgs1QCtNt6u1o2B*SzMZ&+xYlW%We^6e>d>pUpGtu+X ztWZvtpL9Z$E9bu!2a8p^4`7C5py&eSxgwEDtu#6}y5DWDPfFM2d0yaD{UJd4Fi2;H&&fW3QD(QswBgRr6YK{H%uQxY2?1dk;>b;gw6%oe%8H~0^ z{(~d6(|>fNRulMf==)4sVOsjT&++3+Gj}|*4%VZPn*4bsQE=;2zw6qwVd=U2RK2#5TH#+YulGE!O_%l zEvLC@9if1a-mA=xNuDsiM5@kx?ngrMZgPZZf-KQl2hZ^)qISTx&WYrlBk&CnC@vCw z{v@)gN^X01U!io=aQSi_4^cob;hVtJ?5(~A!;a6sz$mkV3a6rm93#a6-Xh(`>fnO5+58#Y>;t2;C+YF7q% z<$F+nZ<0cS#|&ZM?h4x|6De||&_4iLUzOcu&2-SPntqZN(Nn8S4TV(yjUwD&1`~>^ zrg{WuTbQx{I<>c^kV|{d@QdmW4IK-pki5?q#7yf6O^-1b%q7+fQQj9F{SMWD)e@p% zCU|29X8A}hdna7%L-Qd)r#~HpkJGi*{$X9`r!A_euTXEIF|m8ieZc0}x}ZZM1Etuz z7>D3P$4m7@)wkfIzHw%toU>H7_M9^4on`zAsR4RHc*ict)7o@8-78`sGh8*OpyNNA z@D%?)6B4SAJr3u8ipNgs5017(_`SdBN%TO_-m&tf&p zw!}{)BTo^}gl=c)z`^ibViW^MF~PsH;d?XvIe)4y4R%Mq^G&|(ZKS}qg4@Zp%G0OI z`kJn1c-dUtiT9t8XBb#z@?8CH+Gr&x9Q6@pE>tGzCK8s|$Q^5O>|e`BkBTb#rn`7E zuN}9nMAbT~EzT__00sg+udmM2kG}a|tj_cOshP8#TevT*K09c>b~MP0DGgZ2Y)G<7 zIGu?b{ze9O#~iBVz{o3dryK6wvg14HjWcw(o2&Btl(v^C5Y&6zq>!op^dv z5SwY3A`Lj)SB>mizdoTG6(K$W7i%(tyIVH^SUsl)6daQc_r2mfB{pHe_OPXpjl-Yc z$Sl2g4R|%#TPvg<^FzR}6Z^aZIYAzLES&~<_8SK~`}?BSDE}#AyTdC}wiT*0(7tsQ&T}Io5-~s)MSRw1ORr!{hcA`2Y@CG6+@VqFHx-<9L2{`G|K(1y zTD}9J{Z=R0uoJ}grO#vTrO|JvPMt9pL_mA6as-Da^^xH78jT7&-M?gJmN%P{<>G_6 z9(E!Wbb1ce950qJOo}XV7L|oz0m0GGwG%b5s(Gu_l*dcW?!X%b)~S7?!d8a5dJ?|i zl`?}YGyEqNtDqWSQKr9pKNtq=#Z&BXOLkd4T9}Txpb3BRRxm09i3HK8xr$E$9by%p zKOi!PXb(cZgg1cH7iF_Nl4s&gNKS(fV2*V^aB4W{{M349dS=%g#^nJ%ppUn)OS=&DQOsSBM4m9~>@4(dkwu1kry7v9Nk!a#ug1Gg z0lmGGxQ)y-FZhrGWA?I!$ratC!NSQ=*uJOD1Bi*uEniDHqLg`>nPz3e*)UReTYXA# zth-A$qL{W;()!TITzmP#$}Ai&=|?I|r>ZL*tE2lsXKr7#O(?IE> z{WLq3(rmKh9KIGL8cd50 zW=xS;m(rt)xTa%QR=TgrJPDUyi}|KyPV3Ggc9Z-f$A+;ITQ4_dYjrxf4HS(yF7nsy zplr^m)lYIxMb$FkDH^DFYpiyjN!e_{NYod8OgZ}#-()Dk4ZvZ5sFCBSaF!$k47$(CBtFnT$uTH@us`{B5BnlL(0j)B?JMJU zmxzHny>;iKj7$62!odOynMDiMM?$V83==79W`(59Zl8pTx=g` zB)O!M6b*gk)na*obE|JWcu+I15sK!K9Oncl=qpxgc3}F$PHyv&>=vgURI3JY)DX=T5a*AU4|m7V-|sq0U>`z2ko@6eNL!XljS~pqffV@Lr^QN}B8D88PDi}% zZIsR&IqTAq|MR0Q3D%gM`nT*%R}QWYMbkW39;u0L{n@1)CCUP}WAmB?MrV0uAr+T_ z=V8XV8A$0alwd`K_tB1Dk7C(h(d+*UH2xpW`x7P_e+S#@BGoMN&p14W(TOp2Lxc4D zsf>ko^;tmNAC%nBDzoA*e)!fiDY?2oW!SKZIvs3!mA74=A10}p71G>YSd5iSo(UkY zZ&ld5XBr^$Bm5$e0;r&@esXDRb)8JLlXI@9Y0=PBgP|cx#3>gY)q!+O$`7*0`i^1v zRj1Ydd~q`-rLi%S^(*#;+whVu6DstrS|kV1(3_@w23qCprzeEhjQB&P=-E__P!RPJ z^b+L*bkF@jxo-Cs?M6>pNgLD0gGC*u#(_4bC}M4kACte$W)$NAVIY}ip256RA7AJ; zn|6;W=G%AnHEEQGNWv8Ks(FL=DX&W<&CBNaNw-5Vi!uWTjt69r#V+?T9W6;1%-1icRj>_Z2Qh#L-O3 z&V@Qu{ufKhQuGCl{JMxx=Z?fcanNztjgp|H7H<#`E{VaQ>E?%c$ zy;9`Y!d_fKpGN9rzkELamQ{!LR#0y6Y7|ODH0gYe&%z5|x^&DFDUs&#GZrhga>EXm zEMnk%+U)M3b+e@~kRMmtk=+84j(di}z(Ae9*RJmcBrvAokX$#~X-y0buO&fmYYx#E<145m`rr=G@4&;g!9H#0P17 zPFBdCCm*c}bM?e<^ERXv9G#adCO1&w*rMm(6Eh&_87hwQ3W=aB*u5={tiR(Ys zcH}p|D5u;DXETL( zgLk`IxN}j!YjW&iJcW!m*+mNa?iJ=mu=Re^m0iiO_P7amxUG$VkTPxHgILn6DZjAh zETg}mCQNaTRjVqS%@UjW1r(;>I5HU!@brmhrbe-5E;O(8YLjxFA&ThVR?<~yPU4V+ zT_|Z1u7*WgB>49h5%*QhqBig67r1r#HYbu(Ds48IWpPwUVz?Y*dRIxeTG|&Kc$o^9 z?dhqK&QvH;8{fP|E#acb3#ReA3I3JR{=cR+OTD}OXOcYTeGu{JlbZ+m-y1gO%!bWC zjppvhPus_0Ifp>cD>kOyJkfHhp(w5vRVt%qAyp+fo=Q_Y&OFyI zr-doWh#{>K+|x)~#1K>f_MI4_ym9Ty|d}LI^YYz)3-M?O>>(_`V5fERciWW~b6Bb2)^m?L3fnMwp@f%nDmtrorPpt(hkT^e zCHpo5NX=N9MksI~s)4LC)~dS#>e5FC%M1onMY=q(7x93prMR!CGsMxY6nK% zd-xCotNDrdX|6D{BeOzlouv|=8i-$i%$=d1!u0=goj}N^2Ac@>{L*iPq%&-AeU2jb zfeUslY(5_v3^7kW_03f?g6lTM5Pl0N#I>kCtW%f2V1&1j-K$S^3F}<;Wv*3%Q`OQ< z{vL}x$k>%E>aF~7HM|s6peI&OnE%J1y~CRWR3Q6c#u72BP36t7VS?i*zavwHd+=qs z6?d4P>Ik?&(Y}#jZy9he?XRHduS>$eFS!5gmHkxh`}9T1!@Q>(lRT+Pk`)<$_w!8I zKKC><%z5e97Wm)f=P460+P=H|1>1GAA^cy;rYuj*>DOMB+yjp#5=H2h7!pg4) zjz0eV6eC;coCk*Xz2aW!;8#sY(q3ci?Fb>yLMrsuU5@Zi)g~9-dp1rqqy~C$W{A`? z9XRj0INRA&?JIL-tYQx&$t^}IG~*MH@d1dpn&7!2Qu%5+;j5-+?%8KP5B))A|BJf! z4r?l1_x^P|<5>pIu<;}5b(9@bjdN>=Xsxu5U-{kVYfjKwu>SLe;< zpSnhc%8P+zRs-&Tw-9ddWR}Cdsvusgp!iuO=gslkMy#;nz+4G<>e;u%g^P)AD0Ng= zfnAVgd8A#KD6+K< z!4|F(4OJMqp{18goLVVzvltCkC`KwDAZ~hPb4CjHH!Gfkzf09KyFSwI zB2b2=Pawo{+oKEdyL59!3CUK@#}yw;E_uC&Gw^ z?`=}l04W$vRbnh`Eu#3%#j0CdyI*yxXfmRBP+-ajf=qKE@%4rM`;j={qn|DO(;%@y z!}T2XE-YA+@3yH-K*Hk=?dE&-16Q+d_{ciWf;ZLAsOr%-i30_l3(5`#ta?rR zKmP2FZ}-&7ABoLMGLlK){QXk*b)0b4D>?Ce%b$KL8QJRMcm#|&N^3$4Rwy8)KL0dP z({QA%ApXvY8EceR&G9DMRZ(qnUc_wrMGe)Js)D^qQq1?4spG64i}6zSX?*(b-){IT z`mwTO?W9xXTlNn8E^ZA{991;o|&4o%xlv?Sp%C0j4Wsr+_W^)n|brs zKYY{NaJe|qzc^ZvqgybxRlttV>@sUT=S_aUB+m7mc9S7&oXR}8$nDMfr_aO#%>wEE z$b#q7n;!&mXYI|#xpBO~>#qCoFLPfHkpI}{mEZpbljHv~{gBfERbf8SaqW8`y0pfX z^@jp^-^O{$MER#&xrQUb49B|8M+GP`I;By35tA&IxlryZ?`VU`U>hOeV;bX&5)n-` z#I;1vw|>i%Y!4H82X~C4Q*-XCpU$pWBOTuKP-(IYpU_XpYFVlwO?|cyu-tstSoIKR z2FsLOVHi{)K$SBb>W#s*(N!bwOHFtj4}DIvQjt~pO6gq_-HAy83Vi`QBiHY z5HFBV`}KM!6f87P>X8^o#MK7XS;}LGSG`8dh#hNFu*c&<;;onXv(;1Em%B-$!4wa$ zEzl(6c2IEw`?A=uBRUa5?20Wmx5umQLkWOS+bGMn z<)rnwrI~jb$jk+QLOnV@-X7Gi-I=@Z&SDzmlT9e2+TfH#x#JwOk0aV_P>Udr>SqMy zd2#XetvR*xgsysFkVA@bEdfNf9;hNqVllSAWcSq6^oJsYWBV62qICflZx%_Z4Xu3G z??1$mFkygXe&Aa(KvHs31iz(xpP??Z>+{l$BO*Z0Ivhw-m#Adt==e@tf|gC(eD#og z15!XaY2?(Dp;znqltgX#7G^N^rc~=++BPH_ti0LAT`d6}Dgd-0>0L`?3qNpd@{+Zx z6H)!uQzt*rd%&-WUXG!gOS92Y7#GoO4>?S)8kW3H0ejPhL*q&V(ScoGrwhZ|&+pgW z`C%)L9JkjdWT4)$$6<|;xw+A%<>`s}W1h0{Z`zUD?g68n*kgkjhmQ+C|KrpB$1PQj zj;&xi$UH5-b9#8_KVrB-u|>aM8jr*Z4}gu;$3K|;2HZqN(b-^nknR=t-!Jj~#gviz z2Hw#;jF2Y(F{LD1;iVPl{p&cbwBnSez^tv>NEU=y+#!}9Y&zR>Kvs=B)M@^Zx@E^4 z5pZWc{?!Z7>Bh@Bt!MntNA&~BZ`lg~YhO9Ko?SOS_|m2;@^kO(c~behpz273=HLJG z(%+x_`5%LCZSst9T(p3jUS9e8z{{mSJO_4La*#wW{`4FFXg1jg_fQV*dC@g;crRz| zH}*-5O8N6Qg+bd_|C3X>^#9j^cM1Y7ClhOjJ`g9gaqD~+3p0EcleJw}xgO+*rS^wz zW`-0vu1(%!n`P0{W8XGHzl)2i9EB;mZ9|^R_x>HUZoBRDx3-h{qrXBOU1-;BmIAbV zW*6astuOA3|L{YwQ|NT4^08)0*%{scdS2=>L&|^doPBweRnv9$#OI`a{?24esdC6%Ty=!wGadRK=%y_}+855qi&#b%N%!7#@#J*y>X zB504^ZLzF8zY11xA3|n5KaLA7&Di7vBHhSQKu@J*Vfi|J7364d4UQ}={8n?mFp#2Sj$6^I= zlZgFb^R|l)LHgURcdVt|@KXn$up0l@u06jE?WLpmj#y5{wr-5zG`hoGZbziiaNu-6 zSf!tGOm@B_$FxZMl63x5a^}Z23+-N;U!{Z=b%Ey^o$XhDypt`cyYTy^)3}EW_wsjN zo$LJg!*$aWjf?!dSKbtT%l-Y5Y1HKw^DufmENZ(nE2bg*`=vqqOP*;wbOy_+%q1oL z#O~iO9kBh(`G4BYcOG>QMm=-T25tk%pFQVEB|+W%#uY41=qEKv(WbLEUH^i<{C{2* zAKvLzi|zf}1^TZZRsXAqOZC;?rGDAjwFO=*uARKRT9!gz4qw}bQ>D%hXzwB)6%@Ih z&aJO+qTKJ6r`#<5VPxz4#gRYH-J!Y`IAyXhuDtJ^>tn-ON(%9#+*;i^ZmPjYrbVd? z%d|VH-JniKE+WeKyv%oyeXjm8?ZvObP75YdcAe5cy%xg-ij__I$XF;nG?103aU#7c zuGK>$qSN215-TRZEdir357NMlAb=-o399I?>0j{t8gZ&ihFKfP2udnL(S@4M)O^q$ z-#QDmLA3>9R~Rfu`yPxGertEn;(e*36`XFr4sX+K<5kJT3CD0z(RrX^3IcH$C?)*_ zGL;$#Rcke|{Ky(Hdq2<(2&z49ijYx>LCoKyxY*BddRkUa<9AsVU8TTm8^naSNye-% zSNQlOv$dzbwW!r#5A%U(eK`4=3=he(vj!a@JVtgRFEewVY8|DM-*pn2od@*h&$7<} zQQA5lq<%sBFX--dPtAbZzBaW+3L%JU`igUoy2Kam`zIY64TCi0Ei|heWhX*WRwkVU zr9;Yt>#iQu&v`}f)hVvvgvUF%+@F}P(-9DGPq%h+%A9gFpXe?>|G3S9Y%f27*?HWi zL+6&Ej*>33nVA(V_|r9zt zSkzpN5FZcoheUN*SzZ=<`#_PYQJV!j0Hg;7f4wRel_0Iu#L0Nk$f20a8n>~F8JiOq z&hT_zrCU;gCg|%nbS;Bt!XM-BU$vXJZU3L+ZxgmCu1d2%wN4IS$m;gNkefIV$! z<$&dQl4PqM1k?B~fSw7u-e`D?=Tep%Uu4OvZ?qy7Z49gqo{)=MaJ6K4_Ns#RcU$K6 z55qLwKhCRsb?UsAhBngDwdu0~H_ND2Z0;QZfq-S#tY`THF!0I{N0V62(_%5GZzl7N zR1ro*abcCoAiyYA=8y+dAACcYM<|)-bXDI@%Ml*yI~4F6uH12d_p3utMo$hRUMpfl zr}|leDSn+p@AR!*;Z@Y-6tnKC?G*TvL}r!VQcZMHL2U^KB%RtejV2IaqEWptA-<4-fmM5PoV}3noAL(#B`bC}*)d`r>c)H=Oj)q&(q+6x z*~!4=f-6IOOO$Q_c$amD_5?$=Z|2G^GBkWxukN?(aOcz%-+ZifOvpIxjgVeo`bTS= zQxdm51PlQ=#eeNpdAd(QGL5cePAWT{KF2*<2_Jr>lw+Y}%+zgEl&YJqqnnw?O=wEl zwI|^7TZ}$X+me1A?16%dgzqbI2*+Asm@A)O8@Z*8mXE5geM3S}bc7Q^Deb1}HEE@{ zu}GCU4);oauTJyy3AecZ)U{H&ae^p9pn%3_R>K05F*Jf4*4x9HXRxSQikF^~IJ6`E z=@@Ko+RR!rxalkDwunbyAiqR)EQok}YT}#F|<<*JuaIqw3P3K`|7H5TLfe)+&%x*GoZ$DYIz{{ zjk3yCO(LB{_~q`3+|U1MWaRqASK%X1hDNsCgL8_=Kl`}UX3>3ILcg~<-{1K&148KE zL9!mwB)_!vDx>x`7am}4y$Rd^(67ux1mDb;Dcb0D0-smE+;-HsR^URQ+eBwZBwUHI z9k+j{zMBjpOW8?nZv4WSN%7{<(+cZ7a_n*p{p0Debs^cgk)cH-B$soUmLu$C+RG#W zJ4d1_;<6u}f7le}gi2xuxPxL{*ifxhE~QGRYW9L;N2BC;Ej>lnBy6Qc5RS+8`N-lx`AH7Vaoc_*sMD0}|!?;I(5|7%Bzf5G(f zzsyzS{+z4)e(9TN&XKfdyshxtRrirEG_>tuLbx7YOjhkI*7I#hLgrqXSH?*C)PmKz zl*ZGJ(&=0vGJ#o(DE7kj9#C?bm~@-mVcsiGnDp2`upTvY0HNaUi=t2^I)X*USp0cX?zy?oANO%=S92jBs%lNLmOc zju8hqa{AQVFXnblDt1N-#@v=CNU{Fk+VD+4knjV-Qi{K_r*#gW!?8mT}0 ztplEd@{b?;`XwhaTF7c=v9no<=4fNRDE>|HUj9r5YvD?qk*Udbck5Lr0Q&KPiQ36x zl2-;j$@3Xsh0X&2LpNJ~0u&@#(tBn4C&lxAzr@mJg{~_q_-*Z0x7zx7*43%vvBPRV z4ma-zesw^SbSYU@b{tCD+1cO{52y`%^=gJeDBp+?mGJU~_o$pSzr-gpkhO(!u34GesVaq6gwn ztuP^|TQP(DQlR6Adr{GP#pm5ex7geG&2A!H$kp%oL4yg^Nf;YD${YN`FqE55vb}S1 z{jg(5{Z=4)Xdjhr{+tJht zPa3X>b94Qu4EN2O$_*+PKy5;_;Aw$x7&5rH|I%o3Y`nR ze%uoO-={I^op*wN(&$h5&&vocp;%&1ELL&A^2(NQzW$Lc}M|uWxFEGHM#V&Kg zyhkMW3J2W?PyE<4zi4}Tu*v`K*G^3th+MBQw({AU;|%G%*yz`1l2&*E@cA!LG3US^z$Q?Z6OUUo9c8UJG>GAKp>gA(W*aGyrZ^%R6#Ed8OyZJ z&8OYGy+PKzwq3u|b|1`*!9#19=>@!44y95=DoWeH4ECcH0r_$vllbc z=DD9EU!L5XIaCu{tahf&S@2EPM*7sb|0x+`p1ZwEX1SKpsjOC2RxRxO>GVF2lz!tGy)ltfP;$is~m0&Gb z!n+6f2^No7j!GLbH^mf#n2)z9-E!_x=&Jn@8H>ZsEwv!If%TQG^G#dyOo?vxTmNh$8m-1GlP?JrKfa_wh%;e#2KpX7dKDRU~*abL1N zK@QQ%C?t#vP1=$dEi)myM*9xYyTyRSt2|DQLl%*wX6i#54yzixXQTc6Se7ln&pWZO z9!w7~m9^OUDaI2bR;X+wD%4ZPgnoIYh+WCnb}hK#wApnrv-dD`U~yrn-D>_YYkDgs z1U7bTS)lXo82-xoI8@7frb1MqSHZF(!71wC##&=pWDi#7Q;7z$+A7~{GZpOoVBVl? z=$VDVqfT6>-*p4BJ{Hyl$x$=6$wU*P3jqlLx+lp_RP$jQYdY&dcA0hLUP!!)*_oAH5;W?!=U-T zVDSs5Z_(x|Q=bqoKa@@|L0&Lhd?VpMEa{;hi6mOE#hB&QajV&xJ6J;lelhc{%F1cC zd3ENvIiDfXdz1kRV}qI-^9O%gIX}%}hVHQ2^|{{OZf22kdtC9t`pC9AYInSBHYD2+ z4`t)H;IseE?Y=9kC~FhPm-k{(Lx0M-A+JfeZH_g|M)ECp49crmT0#JL6cLa!&FM8m zXOpSFQZ!*p6`}dG+2kHO)r=;e6Ct1C7>y8J8Au0t8By2o1tx0Q{h_-RVlAYKh{w)M zam=_r9_@zwO=){I?p&jiCrSMbYBw_EsBJ=+LY3$CLhUN(IT;0bE;l%urg4Lx#tF}0 zVAeT86sq&+lJW^QzhCNH!{kSug66-4+##5+vHCR)opG1m8`3&HlCUnVGsC`I8uy<} zRb&B^!WFXi_*%UGMAgqey&ieHU(%L~nWc2CsO&UV_l!_A>FQ+*$If1O=S)5bz;{Py$ zOgKq54|MzKRush>j>dQx0gIziv|H`UH132FUrJD4;j4tL@V>K?rcJ4V_!s(bQCRrcwLR3Y<8 zPr`y=$q|7vRxuS^jlgH6G_=Z_+zRMx5nYX*&pZUr1nh8%W_zt9kYJ}kTc6EuTqLKi zUv=IOh$M?0hGt29uTZC1V8`-(uDtnuv5P$D2q-#0k|Eyz^ZTm(mjm4Ib`8pfG43vY zHfnBQqvIHO;`Of-cwC3Wn^_``@@%Uv#3B79Y1_5*@0lu)%)g%T=ITv4OMRI~;w_Kj zvs`oJ*aD%<6$_mCs-e?y!TzD)iwx&XERNp2?sfLJ?)BBBI?86$a%)fTUPKE|6$8Uz z&spQC&vvA+?P1^7&JLSDaS8onI`H?y(KqPo=KuR;YCli)eQRcfxnGt?N5NphgV{i# zX&B?C+^oM@RZ=uK{wqyL2*_~T65-o$|K^9ov)YP`dmiD|0LrCk+sz&si2#W)~k_JUi+`Wg9QmR&WgKo-t? zf!?wySXuKto;S@^b{3Xn$%bO;U%ge6B+kz#D^u=Ib1CNHa_RF41Ktc%w7*gt>eeTA zw+xCHAq-24Tg+fJUYZpXHwcX}O?DF66V=zN*pe5ZTNe3^IQw2d&=oUkrJajuQp*&; zHpJn*YpH%m=I9X1Y3)yK4I)+pa_O&b@Q=k0JZRAj6SAL^bG6Vkh@LB{kX(H&YK*2X z{6?9SVzhicuBd9nn7|kp`09(|*?qa;_=x0+{_(Wut!pYvt(=cOk^P6`eaxAnN7Smr zUcSrl9A-91-A86>tIH!CjFj1RB2J$TFZIh|niPl$_&18#(VyIc^BvR<;!{=a-n&_r z8cLUq?Te{V-5@<5hMZOp3OT+I6xEhe7ZeKm7rVabNwOb&G;oghMbc}1iz3-|Y~qgp zck24+jS4kg*eK*q7tfiV;-t5iR)xv_(|oy|FZsL136Lv);O+}crWX0KpSqSNujy~ZSa=ecC@t3f@XvG zIDeVvY#!K^`WpI=iQ3&KN3k;s5lTh9u5<~ru_vIXmGlY0wbWZ5~ z1*MlJb=leK^nE|;ie|s`R=_j%fzY{`LX!@*rbGEt;I@}<5a}P6`|`iy9Vkhck_~10F6vcy+-@RiB9teuG#EJk9bu1}LkF$pbWyu-Nu}?8kb&}QUxO-<_dR3dZwK+|E?nT-MzGyJdET|Hem8hIb53U5A z@&6LkG=?GN4NPn#F@iEk_-Her5KUHUIb8N`b&yX?VYv4aI;vwsCKr0QXuvR@UJ9;L zSkle>I@Yl0f2*?Qk>8q(XOa>#RHW9i@sY$mw7)#&m_P@3( z*=jEqT}X~78L;pIrI{w7lQEk7W24J+93*97WQ@yVcgmwjOUY_yXXm}V_<&CtkK2Lq zD{$Z8&sIr=UVy{OZ>_OKQ89&_ISov6{G63t{doclHWPIL+TV|u$ds*nsz*+ytb%mAS6!$OFxUEQ&|8sy7qtm*wa#3)$Ai3$dY={*)@KbM0_IHOB1KdRvD_F( ztG9hmZ9qDxJ@cxr5@6Sl7}4)nvU7L&MjbK#O_ov`-F0YI;fyAcM+ws>zsKRYC~q${!8KT*RV)6Z=L z1ML1ZXocgK;bhBtODL)HKcaYOgE{$A(&}zM0g*}XQXv+BSsw@z)dqYE-_HBIfq=Wi z@ypcJTOUduu|mhl>Z8AvyT!sC507-TgPj^ruHH+~(_wcp<%TMrDcovh7Ri~Xh4pT3 zT}t(K9RVz&xtCKG9wAFKbllTYq^WHZ|h8{IsMgp**zTs4G!GeipRRe#1-JO$6w7j^0-Y&nOVp6Rnfr6D*3v*A>t+rUeO$`6VP>c^Z7OFX={P3RtqhZqk*7D~?UC`zTpJO%K`zkbnngV%(j!JgnRR37)M6hD{t!+s-!GSE$W{9M*Jx2S!6zDq+4wiNHaG80ANdak|jVyJ(w`Om*f99nQT;*)*Tum5G`)t zqHoEk8G*2-#Jif(86_|v#1GPer_5qpjE>@U^8MOH`aYpkt3{}d6zWwN9DR%Cf|Rl8 zGjWfdv|sRTqXg$i)`qS`QXOaOXKRz?u&{i20QWBcOj5M&4O|)OFjyJTBE+A%=b~t1 zx+aP+t1}Pk2);!Gf+#e8vf9Zl3WWk0xTR&UNEfVB)&;jcAaB;wA1;@b+3j3%EzW3s z_~-ZV?$!V7$=lXF^OD&eS4<^^Kb+h;+)Z+$W9Hb4xvt#K%w7fFNju8*leWXjPERPR6B3y@G!P+&^xu-}!U9NOqH6{xJU(V{$-3MGQt>!6(Ng3M zp;yVrZ)RRK!HlcEm{`IYh_w_uj`y~EuzqIv0h9F8uyereh4T>wYFkW|ji%9r4|mmD zT|}`-Smv4$R+(21sJG$YBh2Y=4c06kDieNdKks8vCd#?}gIjS&w2wU`Dfq<(a;@1V z6+i5k`zXW7VsR8KiiHn3;WQy)x7q{;^#dCh;U!Kby5@9hLWc@J_baiN(aQ{vzG(Ba zjI}#7w-mg$ zY7gg-H9S3>;1iV8fx){Z35yVL-KmInJzwc@!b$Cz8(p?p*KUW@Yn%=?MWjCS%Ine7 z(X$Y=Q|abcgE+ZA1f@b#t9f82{7|Ni0r z?w;D*QLpgP!k-m~yHGPLN1K)dB&YAgkdo>|kc1N5<{ILIQMrfxjq9d{xys{nks$5! z&9y&Sdo)7#SB_g*KXx?hgfU1ZT73EYJ}+tf-uJI4Ao%${^FJ|BpHx261`cxGEeY5`oC(t0Dbczxi@J^7xV2Fi_q1)KPwQ zQ61LKnLkJ?!t9$U^Ek&v-iLHgeDFn_u4s3h`n3$EtOldu_+~;| zys7c2`1=9efjm-_Gu4iqEV{F9(8f_+!ZQayHi10577*Em-Dk&#;cZq5V{69NrjH*B ztjv%hN%Jx~oMH2#cysa7Zk|1?+uZADfD5^RbJC1@5xGc_WgCPqz#|{OzX~;oJC|sm*sq2OL7XRw$G1GT zZ?(1UK6c<7iZ7rXc}QY^h6)I}Es-W^ceZ)>#Fn+ky$32z-@@C1t+x(c5W} zAkNeJS;6Lp+mFi(T(c6h23T|j>HZIry)#7;iAvgYTZeZ}-$Sot&JH@cC(j~ji2)a%pUkat2TQ_uC;^72kgxxx2ikq_Dr&0LZxg^$(8Q5`T5vF8uEuw`nq6 zBQzam< z=5brXym}FGm|OJyH+x;LTysU&JAWBnOC#K`j*M}B#g;S)AG$r>+AgON_hb{e8nN+W z4$adc5Ws$*>Hk3-!_LvvCoX9dD|J)iq?-KWWYL#D93fO3!yCv_z$(>IbHwzh&O9;F zr+wbAUt{xWUxw>c0asbMa8<~T3F936^lH;fRogHV=a+@iJHYcRc8y$R&B9e6aN9BJ z;+JwehLPtfpY##gqb|4zl#JMM%u!F&`CfD*A!%4uk)L_|r zxS_7>UNzi-xN$|}UU@MexELIv-CkPTprs%hoq!mrf3d6pxM;x5FX=YMMm&t~J&kUa zp&r*d(9&6XK4wmOp6%G?8;6KmFTwvWrI$RKj=P;}e`dUdEiwIb)9@Hoc1Oc({ZT1v zmI{2nAJMD z|ChQ{7%W_h7FnwzDfBb5A-yZF!**8NRx&0~Q$5dJj(dJ#^W_h$^jJSOrS5+;F|Ga4 z>7{Pwuun!=-+6Z6Vy#=DRn;CVTrE5FQx6HWWQ&jM11y;uBv@f6Wd6BDT5c55s`$ZB zgRZUtW6pOqD3)NFzg<}%Lk(tqlg7aA<1rpRpTN^x5u^XwG5Ff9y3~x&dc=Xe)@)Cm zE3?S6(-@!rdfxoaqu`J?GTH#n6A6>w000)P5ctX4(M*gOa`$Psiwe#vDBpi( zZfR;|Pv#_EAc{6dkKFEi2g(5}TOlQ0y8py z-A=BA38qIXvT6`pq)4+t@5+-Wms)5Q8N_<&1f!sn)AY_7)S>KQz`w}}{Pv56g99V1 z*L(`c=C)6NmDnn(*;w4#Il5#u1sV+25&o2xJ{XZb=rp#y!DRF-TN;PT1=2Kh$R+Jm z&Ked9_eVt@sUHsHpUIrtMuN_`}^_CTENmlaBJ+W{H0-GnN1MOiuW-<*km( z=b}NN^9@PUMR|>vbt^+V8DX?h`tr)Bb>O(w-r?u{BJxsk_)$vhrz~#HlaGcY-77g$ z?QOv(YG+Mm_w|QI%=OmNK9JnUas#BEvW&3A;}CpfL>C_Q`I#!15PxQYB2;o!;b+Mf40-p%07a*Ops4Ed7}yZS<>|z->hC` z9c$j-k7#(s@_gyyu17z|zdiS;`H3rO$LYdj_Ubur*-U%JN%Nck|Y^Sx{QCZhGODXty>h2#y*tb5E+exP?TJ=R!r&8vZFpZiGL;sRMFVA)pi zaYp*>lT@5Su~mxt9FJ|tNVR!A2T!8=H0Mr*{q$lFx*W>7bZPixM*HMv`Hum8VL#pW z$k~6MdF8);;qrbWkX%Y1_p>?6+_-L%(+76Lv5l@+wX8i!l!w%p7O!rz6v;97#cTFu z#%%k4m}FY|Ge!b-&3hxZN#K9 zt8WCh?9jol`gyoI{8vSOx4DBm?`n@DAK~)A`uua3RV6nhvwUb{y&}cf3KJ37z7~7w z{eZ>Eu|_XHyPHJfQov3hZEmvL?|K!Qmt2Tayjil3~!nb^UU3@#Yi1Tll# z=F3Y7A+Pfv8$AXL4brEBRi0E`exbhd7NsXrn1&B!9SZT*Dm7Pe(eZ`4F8wwY%tQI* zwmKUsv6i?EwU4oKHf578tL;D;2-qLr;qc0+s-`T($SxNOs~dDF+p;O!?_)Nq!vFw? z5*VK_r^?GkBj7y;dHEju730*}MOn^j&evZYCb^VRAH;!=OX5OCqlZp>~5)9;Gcb2>A&8DHt>beGI*T;afRY<-{D)Zs057rD_ zSZO1UTV>@M3w*Ca7_@Vd%4vS@nkBaH?Ef+E96vDNFVDK!jwc2+_^&oFJD(XsYzAzQ z6BpKW=P(LI%ienE&=#@m)_|ZK#vpL~xuML4U`(jb!UAzn>LM*kp6(#b)UIxbb}P)^ z-%W)medrT(6}H1x8`H)4N=Ab4A2H-|uvQ$UO5*%Jw7Ft`>Ye{tje=dC2w@7+W<dEaOOg0Ayn1Ogmok6oEUp#1q7udZO~2NjP-bfa>H*X7(|V7>u0iUlr;gP(K3X zw@iUDEJt4KRGX#R%!5ia#4KMH>#n0j$GZ+O6hcyNeWv5%l)22?wI4NXlKk|d$4Uj_ zV?iVayXK1coV?MTq*eE+tPFp3q9zVkiz5^hq^FvY4OQB5RCa=7+fg4=Cj+3J1g9_N z7d|oqD!{F@dzRU#OnpogA4))@v`1s4ZjOeg+7rF@n4jM#G!X zF4;@)rrDO#=Z+lig1rj~Q?`@yuNr^9^m@@UX!chvXyw}eDKXLD*AIQn+*~rl_j9dc zuewqcT9+n1=O+HxqcUtDr(BF4$?RWu)gIk)oG@{6A&jN1?6dM)PDllujVBBhHbVe0 z#hJ0GHhJjPHdEt8U>xmw|9F-rG=Gc;i6u!P#Ojbm1pBxF!x2M>A+kfJ0TWmpx3f?& zxanfPmPazqoG>V;Fu)!NO3JyDA>LpHJsV+8dCx>bki1!s`5Tsc<|K@xf-29thSLTu zZz_i*cQAQ+v{q`XQe44xZY|D;fP16jDb{&}r8=~|mrQhVf_(KEVo@~!f~z(h$d6Ym z8!^$cw7A$`#=x7Fft<<@hNYDwx!+MuqbhM-=FWcbFOr8~j(l0iBFeU#kj$rq)=)`| zahH2L36&1hQA-#-70(Z_EFV27bm|DNFR_~+7bR(#8ugSfE7p!!I8+aSga>EG*3*kk z5!02ZvPB4l5t9v(;jHNEcCqaQqr_6lPv2{K8yU_Iz6X87QtVaV@nnt(GCXuKs!#n; zR-24tDp-hQiW@XvRZl#$2-mLO^jMW1FNC|ubBOmb&EcC%sddG8Ft2DL{5xO3sFNXxRJ=cmmEg@fRtSTCJ(%c_0DA-j~YobgghhrNfP zvCN{?!6Jm}ztJJSvEOG%6SGHj5+@{16y?y4qf7ZmhGKf=j%|-WkC_t~5rCroP_yJ~~_0UGDJ!D!!5tsC4VgQ(5J=k{&*0Q*$GIgsPVwa>gXwXJ3C zH480@BqrmOIhXSC_0Z=k!;#P9B@a}MVOC5IDO>jhM2%StsA6kDXrBDuwslvrhGN3` zMQ7Q%YfulN31Cb#YAz`@03fr1YY+s&N}PvBhgbrboNwu9ot0|Ip!4oEY)m7#l zbkPChrshM7ne$4Eoz#e~o>EJK@#CMtiBbj=%5V8mM?`4-i z&OM#wv1Kk}<&(b`IiyhN&=l(?9@In%)@>s6wP&&VzuHZK#b%UlO$>Ty+t$0ZGb$b- zAxu+sF`_YEfce#N>r%V?+F-{%8M;v@vdt@jYgsfQ+xzSCNSvRUpHY@q?PljMLiMNw zRZ$5cs08k&6h{xEbkVz2oTSQEVWyx`c6NB<>ctHg1%{ysw5>6w)Sa4$pqg7Zqd5f%-X0|(iUxD?+X?3+;XsFqjNHMPqM8+NW^cF4~t7e}n6-79=p{C?Q1PnnDG z#-CS6%PD!)_Q%D?TJ*BkC#?EwAl&q(HKr?3&YeqA!~Q<2X|+NEoubz4U5vg-TAwWD zA{luPF;8YGED1?a$7PIEFcVG2n_JGPVv(8QRTq-I`;f)A$vm+Rr8c@>E3UXBGqVTyk(E>#P2b$aZ+&~*D}+X`4y z4yjCAu05;5oVqHSZ9BLM!;BfpGy%rvsOC$tNod77_m%Qh#IPl+XoCVD9FX-gp)9-9 zteB2Zuy{9F>!Dw$gEi-GR!HlQ>nfzaTNTtWMo7HfKUdRp5lPsKF+iV=6?8?>#@*E0 zf*B`H<8zCe5R37GX8|j9MsaPXw#BSSFl)Z4>Ull=rnxXt2sR(+d=gdbO#;2Q9* zEoYfS;e-R;K)lgP$bGMs=Qj1D;X=P2JO)zwuPw`K`TfA9U(~Gk{0ey3%vSh4-YoTr zlN7Ir9H3aXD{zCgZz$N{g>&)P$i@&!*aSPc`n66q#lxfs1EhcFj1!7YjeH>VjI8yI ziRj0RK?2osg9>cY_CbQupqSIpz{Fjv`Kjto{IUS<;cQQ+@psx_Q3T<);$b>j9pP8+ z!Rxxh^~6}vR;J|jOQH`{s_MMA?^I#^70mtIt~VB9Sy@z#Eo;bFO&BZepR8b&=UDTC zm5$@4z{VT$+E%z)YF+kxj>X`xksMXEk5h#=$DA+#=&#`I$kNYHslFN)ePA7ItohRd zNp#unXADY#faKB3GV**AF<5vvsIc~O$=&<|q^%Sd;0e7w(T>s%p-)L;Zk&uTr zS~Nc>MhxR+>($KI&?M8xK(&sop2!j(RZ8_5CIDs=+zl+^9}jh=HfMVF2sDuaKcBem zsHO4@aEUxbB#sg_4^e^G8%ZqmcgOe!Rt@K?WKw$*c~4T7fMs*o%2lX=Q&B1a2J@esG9FC13)Z&#my>Fc?29C zUOqZY19WDjKl@~t(0Go$h8^htwpVZvl0FXgJAkZgeQY(y$q%P{2Noz*udyp++?^i6 zYhgBizm!+ppixoUJZ5AeKIFVVTpDnj$r2$PP&1A`V8s*a5ed754MXs$Rc1aLp4wdP z(Whc915|{6#C!y9KEYR;t*))rj*8jJ55G9j8~={ai;>OpI#|T8)8}=%`}>ahnhg2) z?(a&?*SmZ~$5ii_zH<6nJT?ffkv}^sUGW|8CaewE;8eBAME^Qmmj9A?+2MwljVWUt zqXn-xNuC+n>@8)an!(2>!$~A(mFz(xW5K|r;|vLRb0qz)|G zW2sDpjuDpX6-V_n9blk`9+P&|HqiGnKy5`Kq0BNMQ!mgE&X(=@l@chV;=M*?ngfv; zH`&*`JPrdM#gCichctpAK5tg?+w})jmWgmcE)k|_P1vEK&wL?qpxu2BjxQAfI)mH; z77WkDHqv=3p(k-2Y2&!MJq11#PIdW)^B>l56b~(@g+J%U$yNWi5R~;b&hz8nG_caT zxlLHYe}JGwoEa#lG3qDc2zRDU?&!F^q~kD1(Ldmp51cs%?9$am{1cpE;o$Q~YLX@7; zTN5`r;oDb*iXyx&KMHSW5FTE?xRh!`c%>g&Vh@VcdpvP!COybLcJWi24ME7qoEWvL zqR-lu6h?w?U#S@a@!=0EqEO}elh%J7*GWu7R z|B}rTP7OCqzp+HQem)(HTadR`MK_qhMYze*CgXXbNNBv!vh2yZ|4$qkE40iSe(pW9O1J)~@6&&; z-P0(9#O+vL=PsV>&@5Kj?%@m#Y|Nyc{Gu zvEzLl6!pbXuL^2Y1%r!0E9~qWG?_it9v=l=Za*Ed$5>vjMJ;H8&6BBD0H3Bj`*ZVO zZ7LW3P5kMh%oKn27in^p{U2xA{E$mz8pAfu0GOFJ4*#5KlSTQJ+xSh1EpPs>D|db= zz5GRg>W6H9q2sQBpFE=eCI-fGSy^z<{6z^H2r4EfCDNMtvGcW7Uhf({d^{Be2XX@1 zuV(a+{Z!JxwZ{WPgJ0c+o&lRJtw~e)@Y!Km4B*l#glAkXd>0LfAd`>~sC|;;YTfH?XstfbvfLr#VG1>YFgz&M5K_rc+9%5vA((T>0IaK$Om?Xmmf4YF@A9d z@5hE`-??hPKQg>XdEeH*JpS*k_`|ose`RjRPC}EJaXjL)7xT-fe?-{+pp~D#ua$|m z_~qGyz3gEV`LQm9&FI?nHUAZ?6jq(wkl&O8{J4^2oDy~Pu1~nR$-vCJkT5cDwc1-H z+B3+y4DL=6F0YH~+!GQ`^4^f0#xJ~}+&gr5?OUxc>Qp{4Fs(7_HkvWL9M~=pcBxHC zZ5_L9Dx$+og4271J9oeLfxe(o1ILbEN~uN?FMQ_m^)yTun{1f}kvZfVAFx^DwyCZk zlZcKT!FxgY4vtiDy%3#^Fivwgu!XkdzOQ`+q>8E>S5kx7xRWiF7R#llY#=d+DSmNG zm25v*7AaS#|NQ6l@2LZcJ+3dHH_|x{e-clRIy+)$E{&H?jD15ySEX2U0%xR@s z0qn(XG;7RE5d$bQc{6@em^@Ri?SWK-U+awq^MDHYCW7OdSY^=f_$*Zu*#TN{a!7XXJ|%WXwgGf1UF4qFo$II-nlS2I#@N~l z`W3Y}tzV_|1+jcy--t7YAA^dtRwa&^p+ITM{7oNzelS`+|);NnIW>dhD4 zK`gpQhnF*$DbFR`HuVs%xOurRUI1!F0!-Ql>L2+X%Il5kFYSpM=RAC52~|)RcSA9h zjc|jn`&CwOO%MP(7I7C$~I0ThFTCJe7`Z#JLCNFEpAxk11*&lp&SzXx+_t@#d z%hh>%oqJS3hLPg*^#&Y2Fk5b#Pn=lt+*95yR=(%S{n3-jfwfq^Cy0r`HCd;U00b2_ z2vI5mL&p5* zM_eiak(vLI5523$6&#G@&>IN%G)QIy$@4BD5Ps4?7n-8VV-I9O@|05rW^1W`)Y*yX z>$_S^M`xlhxK3i*Ec0Aqsi?d)#e;SUbpDgq&N)|+Hlt%wWLRFdU>XiRoweSfnh)Bf z$mo8Gh!Ly*j%dafZ4_r}@nLe%Ww3~wcSkRASh+yl$TKnwbz>nC86m4y_v|^$Wru>Mj<6MrC z?W6BUYL?{6?|*hs-I~)%E3!dc42Uec(QlmcK``jSGaWd+E~>pYr%Ho_CDK8v3|QIs zCjKa@c5gq|vLu6M#>vinomx%U!F{13^8L-u29S|KLtXb?=SXe!W*$-T$a~PTPRO+^ z&$r>rcHiLQvUQ=+=x` zTM&4Y{h;!9M9XUKEjTu%(qJX3WhJF}Mz%%|$i#b=rqyQdVN31(98*SC#x~lcahNDX zdrYhUC^lnl7Zy{@j1d?)Xc~*GKE9fbCn(RbVL_c*+X$ytJZLsot|M4<(O;%`$?N;& zAFI?;J3|a|szbzw+@wL!k7Jp^(BLEMsF?iV1_h7_3}jmkAdx&`kmVWKqcH(_N?+Q8 z_kAt=U(gA*0TR`)hPwTcdUH$5ux^*$Kz81C<|1fK9jX0|PW^O%*o(Zu+KS{|1nXN=+Z+v-+s8PLOFNKLQycf~J^`hPK zLXGgWBU+(gXe&#%Vf&t*l)j&_s9q9ED0g7bb<}soW6iaJ;SM#zOB2Bp48DF3JZahC zr9ERbs=PrJ8Pz+_A4>w>^)c8DgMbw!v%i!}W|3{>R9d|->UA>mI8eQ$7aKJfSCsZ) z+>K5%YJ|r}^>{v0BolPw;1ex05JpQ2de&DXbq`WN;8}Cma3|3ouK8JNcSU2>9Ea(P zQy;SWcDAE?J2b6dFS)}=&A}pQuWsdcyW;4TBv^0`EAr)QERXxq>I>e-?i^u2U0SI$!+n>8fF?E;4s`?(`52l zbUiw#RrgZIrIWAJ7Gm+{>#$q;FW*b5F;UN9ZVgj4ZUsA9P&dFNH_XaAuVFXO9~zw=RtaKO_oujjT0k zEF6@ZxR@8OcE+_S@|nz|A(A!3WLprXL65ww7_9?;eG_t?=?G=#;tv}&B3bUHRUps2MT#fncjGZa0Sd!zN^mL>nCu&4`}>4THlpJzQTSL(fr# zFs)ZtjbH1S!o_N^_YW}0@qG6@uQ2cEGwW@BJwQMSZj2ds>>*axW-BQiouYyE$^@2| z@HBM3#xVduQqW}`jfyjLP5>Ll8pC>s;u+-b`MRAF%r}JWY8-k!DdC+Oi zS%cM6kTNVYThZ4_m4*3liCrbHcPbuR$U$_<7yQ9oW7x*N9Xg{GiVt>&V$tqoex*DS zdwXG+wFby4#)Wya?_mwt@$BRA3NM}71I)7?&BFVW{R?xav6M+8VxJZm72;%+Sv zp8seK=|>VZ37#mAAr{lDPy}z9na-LSQd}G_nSn0Om;pAKFL1Uf`R@7g9Hs4tcraDo z#WSEyrp`Fg`sv}BCfVZ3!k?EY?Jww~F)gbp@wcgwnZ3yzE;lp6v`h1RY~uUsItQ&= zN(xtdsN$@o0dk>Lgn1Nn?HwYOqbWE;vf_=KS;0U!JyoDMO81L#G~h6E!InUNRW z+NR(DjH@(CV7voKI!VK!6xl{-Vt_M{pU%ueR_^nnwmWEWsuu}x3S5my;nqF>&`!Ry zCxhfz`t>vr0_2>3lv}e>992hxR(+latsAxmK@~;dyfPBjha_ggvzF7_1D|!)i$t#u zU;@f_)r#EfkRa%Hs9MkCQU0Ri=LH~uxLxw+@$_UC@40eg0c zSg$28s(0&YySun=dabWh-c+GQlk)^|&fqE_uj4m^3&U^w-MFobqB5S5VJluJswZDs z{~MFVo@Gv4lI#J_K&QYDs{@BxyUPY=9}wgEJzPsPW$bTK`jmO2=2yJmFBVRV5pU_Q zv^>ZbtjM@}{{ zixYeg1)gfOf(52~?}meWg6%QvQ+tADpLyEBis8!k7irz|*QrPzg6Tl)!)S0mch|K< zz0zU00((6iDXIa>sg_yx9rjD5ftK9u#qCk32~nsX zJsJjw*WCNBNJo!nOsNstL#Y6Ena>MsZt=dq{riCXpO^l$oUc)Ea)RQooDg%4Im6lO z9o{qDO(9G*zmSg3iNI;4P!5&mE9wEa_F9%sh3Xc-m3aN1RIrXKNG%-gmigTItKf;o`|y7h@U!f(y3PZ~u!}#+7?{Lj#o4CYu57dKx`CbCyrk zBUKaG)YrOZcRaSg4}~QFBiK{Y* zU+t~EQM)(y*%9)y-7TZ14TN@(N6M|&FTdr{DZWe@*`++Q-{@6)Z478qkw6N+WS z9bVugAH~8*f<=U4{lho6J@9_#V+?k+CG!k*f*X3H&F9T-FuIJh9?maQONNB?#%g>^ z+sq+`W6_hn_99+D4HH27%^o&mkF`79t*v17z^$paL|_0k`4>5?A5ZT6<=DYmOmR}H zIZD=VEz2SiHYy8FaGbeTm>H%1B`$=NqpOi+R#Ds-O!d|}uZNJV9ZT&aCWS=$9OAWRI*hZthW(n{QpuOFN%h9o=N>hT6Y`2Bl7S_jgq zInzV4TUj?l-}@%d7Su%AJXXVoR#z=>5%$7Azz3<5R+dz=+*FSuK+yAeT!&#Fl7Y!+ zZC3_utYxRNqX`Yx`6?MGY}Ns=Pb3Jg;`7t-B!}9@Ti-(xxzfcoZJv6Z(Dy|2IJyf96vssmPuf=B<3>#Ht%RuYBGlTKv;}iH;c2A!W zwHh*D(z&T!wT_<9xo1dm#|~j#66b)(gi+T6&HXhc+*AkVG^uP~7#n19Jxf9PW&Ctt z)%|XFwiJC4FJ;Al3V?%VP%-)ki#p80M%$Q6N?j)jck@x{apY~~=u ze8UJ+k_75Fmxr8~%EIS+xRH_o@DkrPU~~*}VkT~XoQRxh$7qI2=@B(}L^}i_w%-SI zgCkl&5D|d9nFMG7uG$1+dlmCkYYR1fc<3S>F)uN%wiD!wzJTVpy-eMO3sLCo zL3txBc-eD1`#rT9k~kB5AzOmxvlc)VHR)6xuP~T=P3)|7xeQ~xBph8*6db+5ocv<% zzEy(g$5PGks2S6}*t~2G0YUqrqj*caIb8w3S`{iyxKQoU#LWgOOsW|()bZy~Wrt?a$`YZ*ruqty>{>Fd zA(ts$+>NkQu+})Ehn&XuOUm{Ye1s`4rp+jvXETZwJGh;zoL->7it@NUnpV$_y8%+u z3Di~C#uxF^MJM(m;BR)N()~Un6|Syoh<)*rVwIeqX@6AD!GpBTKU=)2Y9uS^rSG0E zR+^kpSDHub4w*y{LSZyQS`Bs7BSWWj**7`15GxF zp1H(YC%!ZPZHm`&+&O*U3~1MlTzS(1A@(da7>%^|6+`okrSqjR2)+XjLvm7KqnarO z#OaTps&&(zV8ZzcuJNE7snTGXQbWPy)Mh^P` z+wAVXV}3~sTBENKjJ+YZOI}+_zcK;CXL9)y(xk|jCB6BRetuDD>964W0ZiCuq-z&15%Qi{FTb}l>_I;N$`JY2bunc7-dcC{9{E`g;>U=| z@APL5)+q7|8_tdGy@ss{QuBpoqe&=7-R2-67YF%ajCY|Qbu5S1d%ry(!&=C~(YYhN zIzu1zDc*cTzi$d&c8pny>;0@tIDmYF4w*=cbS7%{ds5zlDlEzMMS1XY{>(((mqr|_ z6wx#&(=G3Sr@x&BYX|mRzMEIsl4bcx%yJ&a1@=TCZ`m5IVWEkTS zoRYl^uMo9!9b@3dRl>jc&HPncF!876Z(DVvGST33I#)+n*IznHe_izVN(i~}Npj2O zck;o&@ZTx^a^O*Dvvl!P^KUGT7@@N{EjdbEQU@Bh-UZzxtbS%CfZJ;lRd0Cyj%d2- z>tgqLp|2@Ldf*NVb}t0%#lLSAX(hlJ3Ti85GGjHcztH3wcB$@5OTP|>j+I9v0||){ zHP>L5f1K89gQiWIce@1*HKm&2w3B3svu|6P9E@aMRg12<30UNSEwBncd<2(etcWuo zRV_;-v<{;_1+zK!r~%b3I=+8jV#ivReRU3T>&c9q+_cem`U8p@av$;Ibyfx0WX~lH z2m3ZkfyXN)he16H#jEzR=xs>-=7Mf9^#;k{72|gDj^e|6A(5r=a?@^ z`t=f5OI*kICN4c{zhd90Qp?bY?M~jL;zxJQjCKR^ zN_%NW4*cR?Q$|5>2lk;hbHiSUdfjJJUy!eQ`?y@QZ|s1vkkpkkoa~jE0+o`75b@8| zHQ^x~a-}Tx3TIKzfAl;eU6!R6T6AmI#)KA4(?J)uE!I@@r-IEfuTE+dC#VAxMaBjF zRBcc{GNZ$-f^U2o9Z*TB@P|7W;eDyYPx1dcp`G} z0>a_1|KQzc|H-?L{d?a1zu@fuzZ^wK-@7L|Fm`HNb~wynU3HFsWS-F;s3D?0;RuIT z^<<7XIERU(?D zA~XC9b3+|fsQ=9?_Mv5;-WZDX$VMdlET~sc_9+vKWAcHQEep!C;3^A|sSSe%T8Ob$ zt*{TmADTUsn{?24I36B6Gx#p03&dWqJ(||%LHTiTyrnV&W1wEJvceJjkSUB?ts|~Z z3%lc;LxNy*DZJVQxEfq7b%U?6#=Hklbh0SnG z7A>Y$-efA;8C(`wE3=wiQb13az|JoDDVDF(y32=|6RM3VaR!lPqsKJ+`ScKPxqgtR zFO^%XeZNHI;iFMQsVt=P&9zE`!d$a)5jp>T5{HBPT?vNlDR|!TAi?!| zn!b8x*d6FjA)mu9E1+wP?1E8x?4WJ6eXNoK=M^_Q(pb3}%+IF0!G5kYrpO-;$C#5r zpMzXAVr=_uGn?L(fxqBmW|R{S8GNseL?q+d)Kwd{)gR_9DyVGPo88E>(bu>j+a~yZ z{m=HUIC^jKz#~a{RN9fBV`lG4ogPw^rz?bH6@)q@!7^7_6W^}8gT)SS?LlhX%$!X; z@Z}!#toCCj;Y=Gq{{kJK83Qz3?X5GZBoK_|S055R0uWf`&%J#<7CW0LOzJSsG}T)B zy=gY@A&MmI>04u#_~U@NGXjv@W7HMoUW`imAgQke6zOEzG~JTMuMUIXj68YI8iCwd zwIXRBDp;13G^jZ#c-rLE=hbgGbF~#?0UG;mi*D3P4>P`92;a_TbgNGS>?$->d+_;y zwt{#fM>+IHO}orixWNFs1btY;NzpijvdeT10AN>#jXhRvGgSyi{nQl^RPXTw*&oRy z!k6Rsw=tnu(dR}d-Q^n*wmybb+6Nrjq=mgbu#6z>Hb?d-7;hCZ09<|X;#Ltyhko97 zX0TzHYMAOh42T2Vm_?%_Ou=HWcA%U~x^`827WqyO>n#K9${A+fUJx_-x>-QBm-#fJ zD1bdC6opEASz^BrUM$~frE$%aOhxS;(KFxVCW~jjeo=+0ogL6?*FP^wyej^4|B7UA zSF)DANbeU>jrv&-!R|pNZg6F{VPce_O3Kt(rGd?iBsDP~WDY5*XiD z3fKIs`79;yZpekZ*PvWfuJwsF5LJK#PxeX_w z;C6ZQsAzX_)N%rmA6wQjh`izZoKn`?O95K6Oy80o*>|cv;#>7G8(FW)J}$H&)1NFV zK#U zzgmisTQpK@C_!J}&`IG&v}{^A{*}QTB|vxd9XdPT6IPPvZ1Mz7D;yk8ywJ2P9s>s| zW0~IstaudGN8LG1VV6(bCB7TE@WDFNNb+(1`=#Q$As}_wU)BUR zN&@?g0Z9N(l{mM|{W7znCL0=DRoQ{T3!CoO<8ZgM!K`Ks)u=wzj#<${rkG@M-_ED_ zZQJIV7(er?Z>bnWep7GnGy;1w z(Xdb1K_FW^v)vrgZF)axLNGHVCl9y!*I zpzb#VQ`A?n5wZ~6c3FcjN}&Z^yd}IV6^t=%;7t;PgVo=izj1GQmuJ7R$&KE>V|Z)t zgs(|ARj0VSL@T&RufB{vrNN3m>X3}JjkL_W8$nfK4R2Oej}R#(o_87bd7)E#bcr8Sx`uvFTiQG1gpyiw~VB{whkQBf=z{Bv(Frt!fu$7XN@LK%hDZ zi=nyFe`cnBv2!^?1zbg)O}M_OKYmA74lnU3gr&p0%hXzBEe1+x!FTJbmkFw6UUZuE zf_~TN8P!R+>;2Or{azy$ zE50K{ezoW=m`Dwtd{5i@%??QNz!mK&yCqhdrsXcx$Iwx7z}_Cl(|~}e8O}M+3$y6K z!da(M!UDSPzHEJRZ|ANdlMCOYAQ87^G<9{VE3>*=Rfx5hio%e`&IT;6AR!uCqCPpA zAJdNYozZ71)O!-+jL>-xe^!QvH62eeUF9N9QBezRZ>!e6oPLwwN&wtI-k59bB<1Tu z47GV*&ST(m9TrgHPmXb~!cJ^IZXb4KFKvh4vdY7X)L~T&8z+x`c5s|fT+B`K{H;{$ zXaP_Mt43x)1las1v&WLyyPbv@r@Mdf2~$ebok--2Ec|oavSt0hGj73r{pHrbIj#Tw zu%+k^qY~qzuBk8axD344U}`8PU1&>c)hXSRX{`f9`$%ObxrClh+|g>DVqCNQs~GxKxXPQd7`6T36E-@Q$R@zIkyB)7JFO4Uf!X~b29VR?GOL9ulvW3 z2)iWB;TLDgw0CTf@VGmle#gX0RiJB=;Xb+WCu5aQUb?|Ip0%k@#=iT1V!%t-zGFr( ze&ee7N6KU`>lgiBzOiI`{GKz(;_>S5YI0fGcF^o|UB3@SeCG&V^y~H`qy5Y$s=vtn z`j@>Wi;m``kA@3ArV4U$v_VD2=sRt__WUZ$nSt&O%k2*>3A+|95q%~La8b6ucRBs> z?_Ey+1s=tJ(!-W*u=%7PfG$5oIelXRuG`MHX3Ph{E+9}D%faBFd=YgLRJlpM*GL?n zkESmrm~|x@h{|lws2@cV>l9^;)|5*y)_znKhg%ru5#Y`-z}HJh<-qiQ;K!}+W zkGyE2wPEBCJFs-Cbw=P4UcIr084%!c%Alb|vBDFT0U>ek8t1DFt4Ar-DYby;m^uf) zdRR!KDEi~U0%l!v;y!#(Tfxl6IE<6C9VqnKWgJbc2B3pOOVqGdJVBdt<8yq9rQ`U9 zGO9mAH3Y*&ZooS9x0xh{q%f6OL>=~yg&Gi+LABHN z;xXb3GrnpP*vy>P#5Ej~|H3}7Zg{%vV2vo=&~P(R46UPE8pPwA9;xa6;rNbktBIu> zhB4XJH~JNOtQ_Atm2ikrOX=`;R`!vz1YD&A6N|TcnS{sruQQ&t!`$8Ow-GvR!>##Jg=2_BB;oB_CiJ_F5W9@yZc~Ysuy9-Ri@V zywFJWQi7Mt9COS_1e?_j}91ZMqP7{A3c&--$oahtg-Jql+*7n@__-Ml< z1+%N4@iY8V2>|w$CFh#4j17F&J9ZSW;JU}%YseTih&h!V#+-ypi0ccPz+rsUeQvs9 zRUopCd$=@bV&Z7mTNA~ywgxYD!!~t$CaYRKo}O1~rcx;C0Wa-kvcWo!_?g{u?D%7f z5YWH(@m2|6XXjD7!b*N_6H=DbQBOiw%Q^s=s->afa?$jAD5wG4nW)h&lP3{1pC=-Y>d|Az1o2Es#sIR4@xX=9 zLE!3zyawxik)YkPDKfE$)mhG%YJt_yNE*M-$D^dJfR_RI6;~Q3M>GORx9$6_f#IX+ zt&HQzsvb>qN_S&2LmUzn#eSM{bgq8#_UM__ONT7E!3wb)NvCm{Mp0wPC&g0Tt(t?m zM#W`s1E+4=jP1h)I1ZIiR5oDfPxm3uuh1hd%6Rn4^z4psMs+aSc+|g_9qo_8^{qaS z?{?0YBm7ljp&{3O)OyId8JRpB78h*yq7JLJ{`U+=mebX7zWX!Zg}=@g)Z9y}`wy0{ z+-tHwV3;8@l!u1YQU_g~vt{#QI9DN)Yd-un<{)-}?{%P5A$ly{!cxz1id>|?Kk@p3 z`pOM^xeSzpOqG3U1UrD^NPQG@%+iR>Cc*Uv;?32FDyhz`Qq~cbHp9{f|EP1T8F{P zz1vy3*-;rNMuKOd;FJdKg3;>9na-JSEa}leYC`(N-#25Z@;*Czj=7}DT(zoAe9UOl z5i^7H7sY`*qg2~G<1#{{Y12sUEBD$$q$uzn7m<}oKyF`)fNa}HYJOw+?NCl>^TnCT zvk!|hHv>DK$jIFZ0|YYmr%5lfHdFuau(8TAo(x_{v}biW+77$>I~^)KG z*_L$?IGgh4u67k?cX+q-4xh|MHA5?gp9fz$xN&@EOUtfoc;$W5+0f+hoCA?tLo2(V zCZ22Rh5q{{c1}wz9p_%>zVMvMmiC@S=2h6wb<0BY)_f*xF#G(@qkS4~t%c8NGk1`6e`&>j68gfWJRp<1f4D1hkgqdtYg|VM13Oq- zW6dZDmhUHVf*)c6?M*qGYn{o>a_{5uLHD7_5z?Srl{vSZ0{~GF9p~|ZL^C*VfE!3r34!kQbr|!Ng zEIg~5!(&6b=;7S;Y98Xri~(t!MQ`v^HkNI<7NE_fp7dWMpygTP6LDpfibt4`ul!g= ziTo6cxjwIpW+lB*RpZV{3rqew$7sNNa+9t43Ml)y^a$(VE!@?lMhi|O{tS1XTy;7= z?J=n&zXQLWYX*nP_mZ-!t|&+o0TguB*sT2go>#P)?dl^NGeG|fq)wfH;o=mynTaRBBh5}?s>I;JnxoRBAGaFZSE=X6|YKTPxKf3EmY)g!uF2^!ep=pe;6gq*dX@Yp2F7P0AHt zJL6~6in!Jrodj=6Y|3bz(iBrl-2DZdWK|vvdBYr$;L$W+JK0mdi~qE zUTS+G7h|hJ&XW0Gl{bxkc?emXAv_Mvpg0Wll zlE-dikQhd@hUk+Zn4fA4%`Z`sOwX)9a((f4Nm;lYH5t11eeDy;?fb@_fhG%IVTh0F zZvvF4L5^XIo65o9KLFmBMgKQUvaT*|w4XYbR8 zcdnH-a6gA+>ZzszcH1!Hk`-#Krq+p)g-Rbd9V5_&ACY=VIpd0VW;b>!h&!sV!fHiN zH|lb646e^7dZi86F)SxA(WPjcR-d;Uh*!^zxmIU|5huQXO@FG@_JMc z34ZEtDgN7w)uNy21+vc)y3=%~KVs?{sR+_1P(^2s>xa|uxMNHyzxV;QYglJT~* zQ*gRD`9(;({p9vj>4{4x$LFZzFO3e(X`Djg8I2xH%g+|=f0{o${x6z8gs1slNQASx zkha52{^;+lzIVGWXDIhpb9U*v(%*G>&SvdzXS6{aA`O&-V)n57x`fXw7k$B*zG@~2 zbehB@yMur##_zO}6=A8b&gkaLUp`us5&?sw&?|_wOscb!b!_2bbyj+gf2aSYR_3pRM7dyIy(gM67U?xPAmGri$9@4dCR zuCt{4y|)`Pqn9ZC3vkp?w%|9G5i>PAFlQWwQO+8g?i)TN@HOy`QZ_og==YbpY=_}Y zbbW3o#tM;!iJL7GIW-@jhW!(i)w6cds5F7Zen3zzQikHMjXgDA(XIQpR# zMt(3}=CfA^FQPs`|MhlnhmL!$6&@S==)*g!-7=Q2HEx0O zjh zW?K?t%`X#|tYh^)b>s}QXUEJl4cS3+F!M|wR{tCKUD>PX8%t_J1yeA4#~mKC?wzRe zPq8bGKM6hmli1b2;ClX-*wxG5^|Fm-i@NPF_sb)c!aL_Y_MQT=(y=cSy)xWARd<)n z@5&FD6Zz$<)(N~~=S5A>dMX(0x85a~t>DkgOU}V_0L$kY!B2~!yIO^gzFo6Un2D5> zG1;&GKZ`v*r`b!(!gAI!?nczVSjii;@M2jJp1Kfi4e z>tEJ_!;G^#-iaR7eq(7`2N1PQqE>uX5~8fe3(YUy8Q}E4(pj;uv5>YYS&qUe+l#Wd zBHS!H#>&IhRigEOYM+i%x4YnOOYrBvpUPLfk{07oUSJ;w6j4uId2 z8%&}%(ozScMx_rkO=J(8FBtQD=wU#0@6k9pqkYzgb#8KRMu;pDoZO{g_cd)(QpWdR z(HRLvnhnJXe4`kG$YQDk@T73?vS+91gU*wJn@0B5N^k%rIklVB60s|nU;T~6G_~U! z%axjlH7h)FJ{QJQn)QtZ=f_VBnY-D%{zmtiW-cVITFOb+e?2*cn8|>im73Fhbo#Xv zZsFLVSmTnkRJ*p|=TeVt={We(24%~2Zk#7v5JA^n|cs5;Lk%tyW9 zHWPiVe!C8+RpM7*-tclfc2ZKaMhY*2NZW02iCV@7Tc)`{nD&C{Klj%4T}sg$ZfIvl zSF(I-SE=mnt`^wI(&gR3h6J6ELmiWS1?y{@+`19uCc}Pyr5VOnDC|^4n*nZBrf26x zxopSAb+>+yLrX+cPk1GY*)(_^ZPeORY0`$UI`t9_!hhu4GFzm2#xB4VsRN6WKUS<} zU0fI#s0SI&gaeKaxMjz7vrSJ524e&EUSyBSpR{GXwp7mro6{GXdG-B|9iu2Xh)}86 zm-D&V-CyxuTHEzP%{Ze50mnplxqMQL=_csxa@{GJu$^==fF1N%ChXPaWE}U zpWnkRF52+Du`ouMN`*Wi{`C9J=6(f+IK0@rR~-GaNS5A*Lk%FE8=E#$tKr{Rg05Vz zB}1G!3X$QHr98{phKb>w9EoqC%EBM>@b-WK>>4-3!Xb?-hFGGKzAIkXcAP6+=k(rD ztl2op&b6N3OZv5Rcui`-VT!3pZ*z@Upt79$OTxiqoUh`}CV+i7ZQ-MfLe*e*qB*1O z)bB4{6Pxy-xDPwOZN9Tzj4RoPX=&g|V7s4rk#FaL)<|+LuJ>%KpCZbHk>DYwoX`Kd zfV22+ndA&W<4hCXIRvLOP6E?$Yd%!A>c2+Q)QTDxub5zi!CO(y;%=={Efxkx_0oZdYSEQ zX~M;!2-o%kEB`(Ip_}6z<(5}YT?(qMRQOW6+pPcVCf|nsl(HF3JULYoA=(V)qG3ka z0nr#Bpr^OIiOF}*3gP#Cf7JXSvx4jGA*&DfhD6$I+GcfISz^GH5oca$%={%=MZZj@ zL~iDhe!AYK8Z^aMdD*F5p>qg}MyX1?mq=GQRbm)vgq5e+&#IUo3M;9!;xq3Y zHdf#BpHGjxzr1$K6}1%GZ@d%;gszWNSw*ZeOg{SbMn&c`XuA_>*q9Vvex<&xdGB#?hQwE(YlpP zYzyTLeM0K-$wG;ZIp0u?MLY-57a~G1t0{Y7l8L3c3W&`5TdLH~-#&8OOwmHluE=Pk zE45}+vV2?N_8N7b)@Xbj?N0N?;Oru`NO^|ra^v^GoN$nM0WZ^2De_$17VvJ8+X9!} zRU4@arZcOdvvJsk=-I z^pMUT`28dBjwi0)RgGn&8r%a~c3&+4nv(-DV~UF?ycdACmvYG=QLcgl^&iSpEHfX5 zm!wszE1z((5|;h$2R!JRU$Sgw3F)N{I~@6*P}Aw2%(*7ZZ!7`iGEmowso8*cGScM6 z>*BuL8q`VsFl*zh(Hn_h9b{ixMQ~e_fkzYEyD@c)iTH~3bsAB3)_4@-v*+I#&drn zJ$;D)aJXa&)2z}>-Hk6!)Q^ST7kpTy)Nv{cNy)-K0x-WpRvReYVpPHxPR`L zvTvhq1wFv#++%K$@>5U~NtFM?iELkE`k(zLrvVts5woO!DiJjdJ23|n<(A?;U->=~H^ z=u|ydZ|nX@342CVf|r7kh)AH;c9z%uPzMHESEDqKngtg#?k*$MrOljy+;~YHVMiSv-v3rJVy9%8Zuc>(lk~Knfb%8-SI- zUL!Q~OR8AG_?kV5dMEhA&wScYKt zFy}IxtHm70Y;{Go_f(B%ESVl5@(dyc6I2u$^YOsXHEu_R;kXS7M?m|TaDJU(^s98P zXMIg_+5s5$1P!Z13s%kt;>!RVkMxLrciXwRfJ^xJ3jO-h3vmyIj&Uv@ zH_*G`XZ8haOH^xj41(t(kBy_nd@k4ze(2)AmL(WIIpE(#!cMHS`dy2)I12N}&Zl|M zJW3%9skI-}&Q3rEjF(-vwTb;HJ7-cNawlO%e(*WJUjG zSLld;&EXh?K~S>aa2t5c3^Fr1+;T2*^4o`gePq50WmG&-B<6X=!M1j`7AdHR{+gtk zk_<93cj{1aMj5NkE{Dr8Z}S;^Qtd#|;>IoF)u zTx(9^7=tY0*1iMg@jUKt6*~f>3=1pWizeShS6XaGHb}AGUmRf*EY#>)lq6b3u<7AK zV!xKzqmR`sd}LCX1RcH?t89D^-K@(kV5xIBPAoA^iW?E=5AeT1Re7MeFyK*Xx-^5Dl<&F$evUc&6c zq4g$Vlx-8RGh`@(>+HbreU0A;WJ=GtB};;7vf$Ns`wjY(%?UuBz@pCzULEhQlnf?G zR5J^io!OlxYt)60tF?u!`Oi46hc&Kc21))@6|$G2?=9A{iYwx3X6R}l^LM9c5iPYC zG@IA9QkSuJ^OvnM=)L=O!%|tB-2aiDsBuqqnE+*^QWD$f*cJ1u;v`^O^LO`nyHN+V zRFA`yLM{8?(82~=QXdNvpipW-#-(AM4mgyppf(|lbwY?+D@mXoBgbzw@mh_3Ecmz=ZP zs=44$?5o760li80zEX=$b6vKy0%mS-2j)u9ss^sJmbRxBa-> z()fXcPo;O#L*dEcRoGO-?JS6&qDFL;i_9rK6Py`arvj4?opcZpm)R^1&xx*BCx~z)dn&$eo73hV8u9cdb_eu zpj}6SMvvy}$d)<{T?-gzH*b$Yg6Sl`>@Fw7x--QUu9I7Aj+lZX%4MxJQsv7SEgN{x zEVc~0Zb2JEE`(d{)XcfK*SNnNW5ns$?Qa(2T7`GqEX2z7=5Y!;*`ppEA|6&9F{ZvAi#*_B`yp1fA;o zqpVxD(2teY6p=UvBr(u|N;9gtI3^|W2zDg|M4>X=nneXw7e7dO>ZL#DI3aud`t$tc zbB{DNf4r5=<|zpv6}m|BS`R>pRJMn3uG)t2L4`go$N@jhCPJ)?iNn)35Z89FCW~q*O zBJ0Uy)kEcN#nep0m7@0qHFvRKN)ujw9N(vP98{~g-Fslgn_7=Uf)kdgT=03n#yUAw zHx-mvFDAo;GW?}lwA$G%=n~ru9^Kwp>3+-iDSL}KQ~oVoaG}#^VF^8)>9BH2F#@{p zbC+565X;tedZb;jF#H$DAZ^OaduuiXr6JbblJqD5|C>VOK_{drTf=hvr5L%*dZh;; z^)&3>5!*YLWhU+}zxpIg5;C%$kI{Wxh+!_V*^iS|?hP6_BPv?j9UfbYPU5HIy*c2{ zd)AXjKxS)kdNT>hfc<@L#fDR_;19Py=pctRH!7#(f|PP(9kS`Y0v(H5Rxk=1YRaCJlw<51p zM~FR#t54SjEU%@qYT7iT(iuT5FY(m~NKoDoBu46;-K>#5JsJ{;g5?z8%f+Z_jL)Qx zP~_-DywT1QQG$u*K2UNt$)J3RtHBr^!ct6OpPy_vY-1ZWunYL6Y!bW@mu4Q#sZn=w za{}~6gO@tTzpiZ@a5*{gMKFy|J2Or&5qJNwEJCltyRT}4ue4ybHx)(KnUmfhr$O&b z@Q0BHWA>M^uEODC^$Ly#ox(WN0+^{OfIqVgCt-BbTY*>S8Nx0{dm%umnfXP#Qm4(1 z#%%D?JsoN;`!vR6mc$g|&T#@;wr?S-+2_775HGUmX(tXYWWkC{iy3G(a8jI zV;x;w?4s&E(ym3wk6OC_K6ScND+?*OQ#NL`Y>;o_W5e6kRnE;@Q_x^qXmBOqBsW#6 zq`T#yj$8J{m$M=_W2M;06dCGgf08w9BO$=RO6a$;xG`QZBam0TUh1%ytkCLgv-2^lDvF3}P zAN@%*ifbqRsppDLXfA-hrEC0RqCO#9?r`Bf`>bes&0%;y&$eZQ)Xd$7)8XTIjh5^#gdbW(ceh` zlmDqFa_86oslbyATH22er?#x-p?cK_+uOHQ{(I`_r@h7L7i5RI3lH+51l>fPS%x-< zag9z(YPXMomlHtb!JmV-q@aoh^ig__hK{kt__C94@cn8%zo#R^c`b!Vv zqu@I&_H}4$b?`{7qCi_5nhM$;I zV&gXFQHGe_zd}3w^fmr~JO&qTaXXpo1$ROpYq9S))$SH<9h0Sc6c2f=`~tOiHGB~p zbt`|Z7q^Y*T|MWly)>LP_i}z!xJ?&=O!bAQd{3o>pVl--E93`1eisSmpZ9R)TOBPz zSkBxHF5uN;Ds!$4e+m$kcwt?pYD_FVA#KW|l+%R9bkAKT_kD03o=1vx#RYqQRDdt~ zvlRXUjmhuJ$J6}+>GeK|U`|Zs75D8G%hg!wK|XsO+~McWyl8o*&@AM9NzI!&Y{T-z zLoKs2AGh>Uj_Wi&1ZLDMJYJXTo8sof^~JDk6gOx4Y)PPBd$aAnd@qdI)Id3=li*k! zU1h?x&@SpG8p?n#B3JaZ&5SdQV2{Urri|biEvfml6rq3n;r9mKb~WIB@M}EROr4I2 zgKNs*?#kyajTR4Q-PAl^2j?~r^77OK$JZR3ex5GLFa}bsHYj(33Bi&)l*-dQHQ(Gf z^B(?eGtOQ@hIp-{eI+=VJq~a*75%h5uD#LX^oYBGpp5nS^3Pq>po#u^%SM>6<6Hmw zS~UN?7GA90;x=DJ)X6W95ywCj;6YRF8-FzO&Ra@leR$bMkLFZrYdoPjYHPaJtn=p) zc-o#}&o9^~pv0azH;i#nU`zh^hcI~BR@(Dza8T;Aq>ve}03)CIs`w+<^84WFoqgm2 zD{1hv7=($)=_f-MbSLxa&Z|=R7CP3Eu2YZ!k8Q;+^9B`J*~T{(GmNI8jfVit_wY zcBt4rhokOh7x9+UpHHVa<7~Lm?Ae%QgalFUtc!3OveT94ENQ<$&uO=%Zq^PoH?IlKgcdxQkR72=xhk`9!;yW9?MFW$PR=5-70 zs=U0ukMLtte^wxeTkq!CsWM;W;liCrZYBp#jdso67{bytwZ{AO;)-pT=<|)mGCPT& zkdt+M7knc|X?hdJMgM>YuK;d?opk59D{aTN1k{q3hA{kiF^7X}|8#A>p-xJhfmcUk z$W#=5x@7vCn$0wQA9$vlCsOsabA?51lAcSZ_CCDo#EK1%)BI1Qw3%vXk%_q>_)%i| zrn+n_U8eoqj6e#Jb|YzZ-xAI)=0uoh(RNkm+t21jGaeFMTh^o!!>+T=bmg@J%d<5S z{_Am=98r#&Vd`*`JhVHdB_mmVC4bI94NioT2EvS@a`;Q?GojVm-77Vde_xZ}TKzj0 zv&i}XW{rAX%;~*0g$zg(Q;))xot^2Z1`J}QyVTXSKV$yi$(aQg-v*cxXX2mg!Wd1B z;h08mkb+6(rc9f#;Z-%}fzN75xD%zCrs!miX<1*fF2lAdC9Gn(Y$js?`&{0*nY~=f zC~LDZNz2Jjaf8WUpzYUdvxM8J5TTa`oh{T9T#&;zL-^(NoY8aQiqIRn*q}X+~gT9rZV+EQzllH-&FW40D>j7g31LWo`gk z5SA(qldJ=Wk zs5@3$=|$Gnk5@zYY4(#X_Y>(56k>e^Mv_EvKDsbb( zD$y&cMX2tqZoBD-eYfunyVoQ}%8LlW=f4P`aB7~-5nL)2P_A)GBVyGaQH(w)&+b+g zjdT0*Zu)?!xh6%QcE)X#9Fa|i3|7n7Mpp*+OwlKr;i74b{Cj(evnGck){^}`Slp_Haa!^~)(J56tFIJg0v(5okqA=ygQn%$ zIs%^FW0enMxzA&mPwJO@K5j$_QO7Wyf0_GuQ81NV)Mq1+V>YZc`2pr?B^ISnRcf7| zVb_jNF^sRuZ|bEkxAXxTTIsDc;yzhJEO*cY_W<&*pVu@U%%7Lnbv1bDR6PDkdi?x~ zr}XE(KlEqm;4hF6lz4U=X}4$RgCv1?nZ!dq$jI=?bPgECx_V#kkPJ@7!}y1Fc&pv^ zS zj3X&Ji7;u<@jgWRh@A#UMto05+136k z@wH+zc{FFZ^9p^S+3>8Gb4GLXXk1v2WV6?~Ov|k^#oI-I?U87%MX_4_k*=5vQ59LS zCem(L62CGpo$BNErXIJ7jcr|%4HpW%-lhi-b%f{qXg?Ko_Vv)l5RI&1IaBM%=Z#)) z5u?(E$LV#BGitIT+^X8797k@g>nFOKCEB43F}j`Fv+lA5MsJ@sZ$@&pb0RXqDgE6( z3@MD$xrQG8wjEojK5SGY^lWMbU@Q^!H90Q) z9iDqKO%Eeiwm0%4M)tW2>yE0ol6v-IH~qk$o0zw1&Bc3Ql{qXqVx=R=PH$4EZ0we^ z4SSk;FfZQJJEC^p{7_sDQ#k6Q$xSn`Ae>+61rF%I-t*0*h}-{o@& z!m{xR!ciwyTbT~+8@3U!5@e`T6RC&-_2W)PpXkm5cd0Tdf!adioM~lMJ=;FMpyJgD zn>t-P#GHX35jhocyYP?|a?MWpfB@4E!6}%CWDl&xV^;$}q5!|_ctAHuwinYv_*(lTqU85#HZT~AJatV~`XH?=Yw z_k)w6coL{%ReP2D(@6oB%aV~%qjn!Suth>g(5xjmBLD*1rB3zwVvJ7joaLXN_yyt@ zAfI(F(!_sOYfnC80j6fm8r!V$u2cR%qG>7f;Yk4@Q}*c}ITuY2SP}1+VVl-0eEP7G z?goxJo0WP&L=Hy_Z;SCp&XH#>SVdKPXIGUFESO8Rq9x$e%WJ8sqGC{HGv~Df0k0jn zvLzJiEEG5|=-U24tZSE3crWN#e!HhWz>(qs2qg^jN$ay7$)Q#eggsnqgLmTMY*qjCK1(~Gh!{o=w z@E@806#%!(N=l!XHh6DuWH1P^hvv|Wn3~f2X@RLUC|&Hrbc>#a>8^*GGJCl}bJRYP z%PLz;>{mt%@hLyTXIf=6Tjg%-?S2|P{DtpmdDA{oJ9?CfM9$|-S>AfP!GEHoSJlxFh)=-ut#FZe3#P?xrXqzN%v(c`6ocG0hQt)B zgo_I`mgcwC8`@pqpj;F7#r62FN#tHpkITRg4(;k>EA1a~ z;zAQ@VO~p;{77WhcA2Irz zA&(nE*tkq5ORPDPV~X^*CQR~tbvey$8#ovd9n7y#;!h*J=Ea=gl4HOqN z<4HsTV*^Abrv1D;#V+J~b=F|C&a=Ky+^5KG)KKA{`;r5=F6}Bt4B}-;LemYRp%fMuIo7vpl zSK((*)XNXA3cFrn?&*=buZ2&HWb&^hmW2_ZMxv);i!Qac8Iky;bhob{L_NUuI4e3- zEa!sEJwJ!Q6bfu~3&KmH!Ah(L++7YMFUf(Qh;oRM7O7;r6<7i0B7F#AvT}K}HJ8n@y!x zj`lP_CH7E~%@GaAc2eAAsXq&UKMS>gzL|USsu>4eceFi4iU8|a)&|>9^uCF~U4u5L zhtX`;2rN^rIzJE9DYG*?Wpjj3Yv-5}BA z=b+%Je%DNE#;W@>ni*9EaZI;I%)pUDUCA1-*sMMd-5HerQRLv2gVt5czFFPYnMA0F z9N?$dF@`9*$=M4qhRUj&o42@UA2!AlD9bpHLq`mI8R&WCy$eq^`ZEf4)Q$*~Vp>wi z#YXnq+EflAORTkED0Lz$%?XQY24oqz=+Ls~;8^Y6lJHP1BsGF8PO#16j|Es99b-|i z*WHeR@%GfE3g-qvkAebbUve@2yNdEmCac9OA5>b7(yB6;@a*LD*)U_K7iR~gvNo+IPH}V?zRpdH9 z%NrPag#@EXzvgKZSnFvQm}eo`M61ZMtofM8wciS%nPRda3Kg6c3@F2+{^^nxLKl6L zt?5MD1@Y4}&yoTl#~87eiYW`nn_Y?#)JWmZ`Izn~M|;(Hm1Pw~Vboc?s)Dz>MrF`G zkv(N2gEzH>eJY1JKVc<~erK}_;Xt+R%l7pt_zTsFi{rbFn!BwrDZ1m#556!Zx=by= zn7^urQJ_Oln|l*a>Xm3)brMkU};taGFtKVB}a(Hzi z6ft=D12fXje<@!-ln ztp2MEilCdn>T~f@oK+$1wZ=0P7Kg46-;6&9Po#bNFi^TFDD6dW!xe~5q7&s0B3i3G z3&#S{J&%?g55&4RXVgk(vbct!wz{}>7>-3tC$ZN5f-O+4X$6IeO|8(M9H>=vT0Uoz zwu*tDDxZM!$QrpH7qEMwEW`wDlcd;2u|Xk;97Vw zYxo7WHVmcwX=QnU)hWwgzLej zEFWi^-VzUcf`?r7`hDxPCYN>K-EE9}$;K^;*rKNmFX(Ru2oIEtfqMx*ZUnK7FGp2< z!ys=AIc}t7i?6L~mBUQNy6uAloEMm@vFf#gXvOFJYjkigZ;l#YR|PAbtWzCgH8s1sl6W)=?gp>Ea;5IRrg6t7PiRmOW~kD2Fh3>S23~A zxJ@sACg8+3RAZ*}wWHS`;{*aD=E5O^9)0++1xgJM@TqTY_^T3;p3j!;q2;&5???9k zAm`Tqtr8Ja?lkTY6&bu(c=&xk8Bj>&drU8w>%4%kSCV_;AEES%1*(4wx}myZM&7Fm zv*Mk+_5X+rtp*ag)@Jz;$7m4)AL!8!Q0|S$T>oQ39ZbETH`!msP^%C})wVprF`6;@ z2?wMGVdy-ie*g-;mb{$b(sez8M4NyB)8AxHzSv@lyiwa73#*7%lTnXfn2OI3Z2+uP08cvH$u zJ(K2kN8Tme*__QF$Y1Wl1dnJ#JQx)ygNf}R>4<-$-n2@?sxh&V2z{ru1e`!E>ZR2u zcw}pptuif)ex)EBZGXjz<*r8B8?55tIud0Z*9+4M5 z67&vR80he$eDpg@t}9-eQ}*z0(DIU`bnKWdM_gxdE|9!yz)qdFOO#y|v2G)i^^htZDaBl0VL>uLft;%

    LbJBnHBkCS(MnfH%;q;vFt4N4&R_0L**tzAkJ^;md*r&x#^$am0r&tA%;;2ty-zTgZrL+4TpZ6swZr)A7u@ia%eO>TtEHN@H@NS<2!}d%JZ)m z&9DDMj&9O{%RyJGy&P_u>^bs6^8PBGY5#<|@mXV%Y89h6wc6pH7(#Mc)~;gbqQyEeL@%4>sEJ>`OSRh2%WoI)4WE5K3%RPmQ~kbSZWjZ8 z_OR&SiZ4L?efgHf&ej1&*3OjXNVH@ECn^jq>;29sM{Y4L)i;ob)h&051?iY#ZSGyd z7-hZBv8ZhXtXjc(@s~xzA@R=0r&an|;r%ryNXuMLC|cK8aF{&1Xh$YIe5tKRKRqz~ zFmFfnb4|#^sQa7+A^+iw_QGrp$y*Z5!PFL|QL{y6I}yO&{nE`0o9dSEi%}0S_S3)z z3ZTACD=lowN#hO(uno_wT>Tqm|Mf0L-85%Y^NyTlPUC27W{bY`nGPH7L`?0UKhH`u z`%{zm!P;V)#Jn?MeDu)@=Zk2Rt@X^P9+gX)1F4Iu?op^^ca)j6Ui+WD{#VIK%72>a zcoUxyZhJ~=-E5Y_yd_?pfTRA8m4S(h;_i4s`|m~u=*9q<@4C%o((v8=Vg_q`#;8xO zG~0|e*{QOSv(|zv`#y3HKNWV1LR`HX&7kZ?m8FjaKd!Cu*|+?&72=s>PiFC1+dup9 zFVHTCzmQ;iiGd6HdaVcL&;gPuQv5{jJOXSoQE}){#8Ldy8nOH4V@04)nSI6a3TqO#3TguS>00 z%f=Z2RydaigO9wFz$=1D=u=00s&%CmgkK8eN~l%NBZ%>UbH(By!ZLm|5TfVDS)1iP z?I79VC5~xTgU#oXj7#N|o!6`Nff1kcC*xQUxiWZV3B%dtC7kTKesy@Ah_u{|Qlka* zJs8XbYsKUFH;s;8*p*fhjtx!=rhWb4bQA}>?9`SMmJ~`1{4XH={`k=HP;xVN zLl7aXPf{iD#L7dizAE#X7sT9NwsbHTq5`RM(acgqAduFK`uUv%@{Ly8v@6h#sXj)Z>$THso)H+{RI-nQFl6^3B(pjHB`Z3X*>f|_rcl|{A=Sr=LUT@ z`dqWNQgAv_xUzcMN^{1^vf%vyP}^%Pb0QXw_n;vrM7PaDHJ01_9f`Sp`Io!dc@>=S zFZF}@?0gf&9he{YL}w)Ww4E2ZafPxOXvrTDa?KntZ!lFX@kagJ2hbI3v6WuuL>>%QQl;M#?DUxX#?OA5$q{N|7^Pnwj;{TwPeY5-f0(f{ z78{#J7GuSgoO&V=NT;)=#5d0~AQ0~``;A^_9x7hlBiWIu@9uKq{*9d2LlafrqhO}< zfYd`sr5wX0M3U=ig*!*$8NO|`b+;WrZ>Cyr?VxT~%=xZjvIsZ$0|v4e{;@LcwfeuA z1EX32Kf@OAjZ|)omeySKdGarS-TC#uPdh8( z_i2oNsOSM*ae|OoH>|Ur-0k_D-3+JOOLrVhZ#@{AgtJvHFAcKkVbbi+3eb2Z;9ZXFu?r&Gj)Ym&m*i%BotnV}F=F8u>dtaiK+$pgy{(0U2AUNsm5>)w+ z0@op@@CmUF3HmUOhgwDzk^%YtC!t#u?H(o#~SQ8>1= zOZ8)XuG_majcS+#T>!0n+l=U;DU8ph5%&)7oCVr^GnVKp>RnR_d=THv-@Fhw__?8D zD6A?i@Xp)=bVTVu;Rwdb8;>R1L)_j5#5WpYA!Q$^RLcCf8I0EY;=W=rWt-qI2DHDA zI7mos+EkW*W)7?*yxJg_+0}RVY4t`oBLq6`;yyHidFXTP7fE0HMZ`Cbfh1>*cUm$Q zw>@`&Vyg@$;q_o808bvnmxFMa~i;Hwr zzpwCyTuKEnpRfTNTvk!8^%O{=jA^HHqbpN}UaF@i}8 z=lZp#kuMjp8yNSfrugI_r<0A!qcwdy>DDBPbB)+L1&*E z_Nv@NOcE7uX`mxSzDxUkn>n4jx*K?Qji4zMy6)qnMgUdM)AjOh?cQz)b{Tm5sPWc3 z@Wm5y)!Z;1H;%fGcW$py*fN|A0}0`!DG7mtKk4ORd=>+KxNCR@RUPPPPjZ|L-XcMR za3}E1>)5g?gKYDLVsq(HBbH-i2+J~dKFQCZIWQ9wD>SaiJeD9z;?-Cz6E|6^e7sT2 zWF?leco=65Jn$Vh?+rz9H`VfQ9s}S(fMwEJBDHl_3>bKTIqrIa-FSiBUU^5@o90+R zv?fw@(QX3LPxXT8c5WDHyJC`TamR;OU)-}v#N;-#zs9g@K30J|bFDJ3qvPbzPLm1a z9~RId8eULY2uT3wyp@Ndi`XlgZOR+_ErmE1iP`HezCcfGVho%v9g=BJ zDGUG17k=I`5W7RSX*Wo+J!~%`_p-I5_v`@=2T${mBMc-LvYpxe;& zaW3c;^>U^%^p7g}f`JYE4c9X^WUs#>Z>i;lZ(?Ha@iY)(ny$NSq$hx>ewEpXA`)yWwQ%zv>VfD0rA0!TB$V2ZFRSjg&ppY{@g7l)w}=}SRZ{FmGg_HSwBW;^tLMyXG(RL677H~9QQ3)* zQtNMFv}Kp?>z4BiXJ?^eV<7qP=yE|n6?aT<*<4vAN)zCFNZUVEBjUL^Vs3^!~O zK$u{VpBx8j-B@n7fIMuEfDPWr9VPNun0fRlR25>d!3R~@U+M}DzVl=g9{=8(Tc5-? zi^wO5VrQPpyW-x{8m=(v;Rx;Otg9X7oG=$SOD4QG|Q#M?tbStLnMU~ii3X_hJAcS1? zSTrh%UbouZT>pX2cVZ-dT7|zfEe6IlM?`UB>=N}ZZU=@K1&Ed^{>`%iUb(bo>hKLq z8K_kot!u485S^8%8;8%v0d0)dje|j-uGAjTk|Z6fdcqH8|y2flVC zCnM<*;0fpg?h%9~@ig5lLixNssuhE5kTnY?ub6{SKyBd!q~1S3rlR-Y6a9t`2daz4 zpyHI4PKO%-vly8W!QYd&YP`#UficWhmv$sda`1D^VFW|Xb;{lHTn6|wYWX!EU<}oA z5&AO0hQB~nQX(cOd(;3saL;aKnG;al{RZF2e+wP9RsMoEFve|ZhR zdF`_sUi*eJ#}*Cms&)5FzgIIBBJP~MG>gaA;;UD2=d>A%5 zEl(Nv*tuB4K7Q)tITVqWsV9B}=FZgIpS;SX`2m6yJh&f>${Q({`UEiBcqL&F`bni6 z#2o9ZQvp7VM;fei=EKdEmOrGQj@U>cwSR$%4FDifQGb+E7%A|#Oby5;n?~%81qQh$ zYEbu>KbWVlI;CaMVMoZpw0}dE)|eX!Pt*FeR^bW@YgFpOx|cKTrhcAwFYH3U#H2?h zPqYJM$5zO@MDd^q$09a~B!{ag%5RB7=!3m8YypxtNlTB+JK5iL)I2nj17+dT* zl!5hvEz0TOF%IZ229(GW8ISi5i-xTunI>8$O2r;SJQW1ZX3G16u9HElJX^9@H&HF0 zwJW@7#LGWK74QrpM3y9P=(7W&a;CV>)mDvsWsPI|f z8tXw75+AS8#~r4C>doihYJO)Kvj!lQ>v0%g)^N?`wUP|dwvj|{=tx<^Y1Sbg-gx*a z)No|H=K2|+3C&vuG45#Qo4};cN7FuIkgvOzi-#uNV&H-6UsASel^|6ZCe?x(mff$U z@wk)JP%ZgCYJ5YxPycv9uOphOB>t(5+iL442uCdq6pYTwSd~Z8fX2SAa97^0Ovj;z z;=N<6VPb=78Yc$_S76}pN;(qVgdc6MC+wRD(eH@bHLV*cb3LT@Zp`c<(5+Q~Ee?|i zLU-Nr{gVPWb5V7eIn$+A=ia?nim7aS-0NJA=Bw6lM!W3^&<;#Q&cl-IDTM3}r=WlF+; z$DlIJXgWkTkH2<`NPE5vk}+>vIx3-AJvvo1-lTqMbkOi)2;DAbk{(&lRYhNBo~WbI zPD#BG!+!M{x3bSNr|28YTla6}=G~g-(5xxdT)Y&W{M>FUDFOfXJ_(he>6rJqmrQMPdp zaI3vBKCyYPp-ynaE7G|D^v=8A&d^PK_iy&BG{6e$9^Y(dS{5eu4!0xTTD-%H8(I<< zi0*m00LzZ9gIU*nHq#AzDT8_I+7V5@j$;ME6c9%GfWHcycx`{2OaC2#4e{wsz~;LN z!qS;6oh@E{$07aqAfK=1P)OV7Wk$2Rtd6^nhD>1sw(uhUv;u%7!i zN&Z~nPflf$J>A04@%uJ!2N(>;`dZX%=E{nCY(tIN2dWl@m*Cd$WUW^PuImr$>j-nW zaGcF+bXNv92p>EygGevcLU)rYa)z$UK`>41# zVmJI$sm$5ma#&5rJ=nMVj%MmGlI2NPB~2|z%qy@i;nfx+8YPAtffMYe-+51~GJ4^s z&eSYtAuXFYm|)2jsCW9(nSCsO_A>NZTh#UjA1?!u*lT85+7dB*9d~rZZGNAM~v?8 zPXUVxu0vEer~F1G;mu5^zr+2l#E@7Q6wP2WL$AH(g_ zK%s}K2~~^TQ0_Q~%bYA;zV^gUH{v3)R712lou%N7UbM!t($bVUgeu-}EH3jC6>r$k z`G&w+_NYPZNEpil6Io(*!Fy#Ik?}8$YeT5amn@TrFoNy1es`o&}H&XnW)0=i6!kOB|^~6HS3XGor5%U;(uwBbe@M#DBx*@6V*TI=b01`NM_U z*8A&j-g4ioM2(@hcI1=P^Pc+EJy~sw9*W*1FzvGDkQp-1%4am^)!`pk8PBM>2Gl3ii^t%x+SNmJdMs~ zWB2DHfx1 zz;^fv(T)SRgEkgBP*XeVATY>8?krIHf7Bz}fv+KQ3Tb52(zG`*^}m*({5IEbLP9sI z5>7~kflzT^kR|ef1X#rYXeeA%Ip5Odx0}T)Y;pg-h6CXh&%2D7auYizcDmeX`VX2G z1iH1U44#nhgl{c_`6l!O=Nc(nlUm4_mE*9Tijy9``;2aMVqbW!wasA?8t1) z`;rFM7o4^h5MJ7pwM*}eeXqxET~MEqXeOXctV7gsq!s*r(KLr?s?YGr6TRC>$a{C~ zHs08{k&hgUYPN*x89u20Y#g_$67tJ5p0NPUq4* zqNPY_wDOXM8`SSP?K*w?5B81b*Z)4F90&wX7Hum$xNBeUw)=rpUU#sb4OS9YF!cNz zqS}c6#}7*dCvLfXEv9HCp7xK^WpnBVm8{h`MpgDlV(|?8x$Be61xdw|x<$JY#EhRXgSWXOAmUkU%6d#_Fg#@|ldoa4g^qlh;QOSxG@XAYC z&KtZ=0P}j$zKigYf)0lP>&s{vOv3Bssr7;HkO3PbyKB^~IB19jJu1A>qBJ7Aog~#C zHyB49LdEciZx7KdB5{=KDVmw^0C&(uaVF}#ckaU7E=-;0fgF~}R6qRk8Ly9@E$EUM z8xJQgqa&Kx=ZV4b^2yZg`STw*QSz#csDnL3lYjNw(;vVuC@aZMJmc~9v%9nR4L>#H z97_Fs%;a#w-2dX~rOylC0I-tZ%9|7Ts!#1>nkdlQY3Ptq%Z$mv`MX=cKrNsM14e6p zOXQ2((#ED6$Wml%#fSH^&t&h#jQLS-yg7K+>Ytc z_w1RY(aQZPiU}S#Q959t|7`o!;bP`dXP}%nm9=d9n-dSaTAIkf;6tIIFoz>VL&fw} zB|?`#!}LLPuR;f2vS~qnAhFoQ+m?<#cfI8j8NIGIhQEa zDB25zn*Q!*+E+WTZl<#obb43S0;UNM9*<*3Isv-}?SHUV&bpR(7=L_+(SE!FtQ^rYBKSvTsxo3|pF1uh-q^^Ye_KKWy|QO*Jg!B_1+gqm??6G?HrGh( znPy41z2%+rG^XF)ZN}xt)geKANj9?KYLd+blSDZTnih}d*M6L^c$aUZTT&jIxiwv7 z-zSDxBB~o5*XgM#Ozy=bl>U3V`G3D-v?K^+8K1m;HIj!nnK75(F-<(H&DWzQuM_Ab9vdi=2?Nb$4;zkaMY0!T-obpsJWw+R zD{F76D4kwX2vCnnt5}JL&Xte)vhUjL?;n>}S-s9;Jf=We81VZVWp~-;nCbj@zm-0( zF&Bc|=!cU>2)Z05>@taD^Uc^T$H&Nc9>NmylXVCQrb0r(+g2aPob#Ot?3x~hx+e?E{V(uQvVfjxB!ll^4<~MCT4glsV zlNqj`3Wze&;bbc1av4+LdwbSPgg@VSKl(~D4M_ag2B;FAb@G-I(&l?SSGuV_X9W_0 z_&oAW3{h7dJa)-t`R#L}fS*6$&ACnoh*KGm9sk8oaZJKNLnQ{zFziy}?0tSf+!VI+ z*ID-Ce`^FBv^*8l{e!*uCdry>1#u_CJvtY-4X^E9Ur#2)^Zo5l^tvJ5%Bf#I`}C&0 zetin46uDw%;Xe)b!OMcQ@d3HgvfG*Kg3ot2Jg=Y_zd-ZSGT!v-BJFQ#0Oz%>_0ko~ zf9he(Je%Ry4cA|wPH8LM4^!%7YfD_7B@=CEGKm7oG+ZM}fbpZ5|a$U|M zKD=sr%KlESFcx%R8erVRuuFFOt!}O_Ys?0od^7Ga^6gy98ROF-?@+?=Y40p@-{$F$ z!|ymzGP7)G_j|L($-`I;X}KVorhBe=;NA|C^~s6Xz&LVYeL_Wbm~3!X%nxB1 z`bY@=KkU7ASX5ox_dkFLVu6&P(%mwkNQ-nzONTJyfOJWtg3>Vb2n&1B`Sd z(%m8HZx49oecjJ{-S6=n?{PfO@8S>H+s)p4t-a25o-4l}z$wMcr*M_wt~%N8e7VSd z(B>01Lf@S~!|v!NKphP7-KOoX(fgn_*A8Tn#_Kk6f{6Y87)S6H2XO^Db}ZccIu_CV z-8A?t^o5H|AB~;&XONj==xZ+ozjGgJHBtGbx*p&9PQa@!HIsKmQL>~j+)hou{^)Xxt|nV&L3XaG((b-3n`ioz8pj^HJX1z#gSSTflmQs3QJxV!~ zV^V1}Z}b6B-_5y)wwsE+@qV9*kCl^$$wCR#*`LOE8i=;1BM**d-BM!T>)v%L5?RS? zblNUw7xh@oU5FM;9dcremQVop2Qs(0nJx4%3TC9D5L^}qA5H5zyRmSU#OA!U5iMjr>Cch3kX)Z4#)~P+#EeF<7+Fi1BOgW9IHPtObQjxuZX8iIYk}G zlkusV@7+W>4PkD%8ih)O4E0nJvY@doz3^=+ z!nRWVX9rU=20dSkcB9&5jATmcq?WXW36iz4k^XL~J-QkhwxXNy%JjX~71GwXl%KP7 zyX!yK{+2AA@Hx!>4Vv@NkNtXgu|@ZF^taodF?v@8c<_sssWnP{{B*$!gwXzpj&<|c zo4T&gENJ-Hr48s5gR3Fj-g&UEoiud2gWEy-3SaR$$PzGZgy;jfOo+7lj_=cAYfHcJ)L2Ipb}N%M9H-I=cn~t z{W5&#*t%}W6>(IX+i)hWoi!L9bUR7Gjnk%3C7HNCK%PJaz2EIV!~V=uIqCa6{&CS5 zbFJFI>s~--B@Bqcw_xJ#3b?B)8O^8eBJT>{JMeb}gOT$1=L?-csgbHw(@DlY}u zE!A`U04*_L^FNVEgXr;S&5sm~hu`(I#isw_Ex$GPB34w#d`*@r%7+m7vQlS-n}R)w zGi^=wMr}FPMh&iGsVfYYd#$2(>2<_4>z;$D?-8By4yrMeQ&z zg3|RlNyTeAsJh!^&JhE?q=(r}4W(l#CW|vASrL|TaQzG>q3w(tI-Gcl8GTVDj8@z) zI=EwY5)-}VC=Wk-R39e^^IKbTsx}}G@|n49j`S3Q1OTmB)7(d7!^vIC!FS))#;&yA zE=&-{`+IXYxr@6hNMJkj!;lXc~ck&aNq}065Xq zC@8U*O{~gRW{bn%2FtEY8*%KWEDk!PsQ zk;bnhfB8Vn+juZ<`*TuIb79K2k4o*pyZb=M6?}b`h1QjUYKxk}Kjh9uB9j&-C@w+yq)S zhXCUq`?E#0P4xtupDYQ)9=cb0CqAfHeir3UKkd9!%WpWOw|G4xpie6#FrD5gnn`mS zk!i4Zt~o5Rf|Q)lz2dxSQ{0S{XsfC97}7~|CFaUfXYC}?bAZYT`ew|@!mcTaEvAT{ zWxrjAh^XNnP4M;Kxq-hr)cTmE0SjH<9@>JfJ>7GpP-%35tU2>cSq^pH=Ihb+BjRXm zw@*;G_xQSv)FPzq!C%p=w__d>KwjXc~6!pltinaGch{*d)?AnU?z1(7o)0ZC=3jQw6AWJ`cd zp{R^?&6MU!WJ^AUm)^7ZLyyY3-+iyMn>J!+$^z=jP&t49CJ&(8#9}&`yuNZJ%{^Ro zr(&dP-M@93LY2QrJbWbo*;!%#ciseiiw#VE|FfhEyZ!g(_y15L|JBPx^&b6oiTqbZ z{QvZU|HfvnQWk{oP4+WUi|jiBVk|Yk)j*6z{c0TJtN&^o!KQ#^|2t3cHRvy^w6L39 z*h~>%*HwSE>liW3I_|*LGOabC_XWAq(N0>EIlcT5?rjElZ!fpD%5&;wd`yqqkpSCQ z%xR$W0s`LtRVDuY|9xI?8QXZ!%f>n5)YVoTp~q(MNjqZ^m^Zw|dOJ}gmKI;rqR)_& z4~?W1sIb4Md3(uBROF|d!UR70p8-?hXAtfIVnD)Q#emxHJ5$UkOJZ-ESnaLMKLtK5 zUb1D~#s)wo2NU!EbkUIasC47*?!J@vpF`=+6gSG|-#wA)NVgH_-zNRb>$s7>&%mD= z5&t&*|5rBwnSM+SWcsWv^WTxL|Kejjrd?~wRTA6(*AKN1gpdECSh)XPvHYK2rU<<3 zFIqU5V)-`({r~id|IRv24WOWDc*0MEsM1QYLb<}G%fE~7l_oRUOolN2Nl`_ohKSDLK z`R_h+i`p;2+dZsw%$TVv^RA+{Yg$1?>5%lO5SY>tA`nx;=90Yizpu!^g15iFTlo(+ z{tr44`wzB*{twF5ACfBeA8dyE!;SxgPQ?C$eGUJEvh|0giv1W^%pbK8W^^9Y^peOCK@A35dPmAoG!<|rL#6w7n)Np9*ed;eBj=7#6SmPqqfiqsaR z*L(;`9hb?@tH_o;%}t?5)yc!DS@)1R>7ZG@<1R{8Fa1wTmzl#>bEaLGQkwQ!+V^gB zhLE?z4wL!Rjw)WC<*)Uh?EO=E{}|^#b?+b7@{i~ICoudI*8gd>{L?7=r_K3Kllq?? z!$18!Oh@>i?(9Fk^?wE<{uyieXDI2Pk+OeA%KjNC`~TBOS>2B>d+UFgDEMD?g7c&6 ze|rYI|F>tb=YM+!d;hm*u5W7QluTZRpe61hb=X~n|ZmKi>e9@~N4xN@!>9Y0V zmW(W-xFp^1l3p&#;uqR-BU&MKmymg515zr$#(q&`V}LRRM7E8|jLM?8cz%6~6QDwm zl4a;pQkXcV#uw|WwHycwt;rttCs?Y(*_}l}#Y_D&aDwE9@Jv+st%Q^%lF~O4A+lG6 z2S0UTyOYed!aYU>RTh-)ebU*nytNTi^mIsBK*7#zg&i;N^~9s4vY9*8p-F7)p)#o4 z@NX7~^Y!jd_K%iWDh1}3YZZI z?=%Tq*1s~%5ozZ(cv*CO#bxHg^OINKjzE;2wQNJ)vNzB_-!@ za_JYA3n9hNS@a|q8y$#E#9B7tr3V995M08olQ|+@9YCG5);|#uvSdUY+6*$ooh?sF zvB5pfMO&g18Oiz7$8b>3%6{Jobd*HYTsx@Y3qD%K?IT5O>E4U@tCKn7#W?pDcC@*V zsd?0^40qmAs;GRfu<2UDtt$Ci59~Mk0m_0~b$!JxYTaGZzLUfqjzvBHTvNfObnQjc z3BS!c$m5t$7h%&ig4;LL|K56f6GV4R7>IP|bNc8}^gVlgEo&BMvXa(`?+0jp<>h&g z1V)D*OB%|H$s`$Mve{2QJ@0!I$W_bHr?33MLuXwzRoqS<72P0vd9J}aKq<(q@3AJ! zt{3n8n4Yzq=vYtkF7Mc&HyN@x#wtpIkyOwx>mHk9fQ@W+kw_29^iq4tgD?^%mU6+uj@&4w|=IWzaC? zGT@T;Z_8rm%k;nJ4S)gY>4aNR+9J)ln|*T2t$S8n4@qrn_HB;5Cwj4u{!P;Xha5C+ zCRN<)$`AxdbOD;JSpBaMo+JsNE~?60j&$|a%e0P>@XN#|^LxHF^$4SP(ylj!G!-9J zr3pHZ6OM#R-LJLLB<+zmVVY7+y#K~uxB+I~mD4S~o7tH%KCHz5LL)k#&zS2)_&1Gw zN#3E#7k)0VTh0#v9xJY2!=gSb4?ZHfeMrDUC{W4y<)w8k*<@396 zyMsaen(D- ztzLMJh^6D=*2PNQ9?d87?kC16wOO*}L;xsSV7rTr_C+u33GcUnSHMHt1eR_3e59KB z2q+Zo?&nBVfq0}0a(nxIGl{DUX$=U?^|7Br=tT-dWbDF(bl;!YG$ zMGjv;NAk&!;lQ@tXZ;s{fMiCAxyC$xfR=q=TF4T6dNHdlTu)N>eqbZ8ht@^d{N4*> zU=85$4!t$K5o@^aC2M-XF2Ca(vSTXSM~4&xVxV&t^FA8ii=97O3-1D_=OgEz_W_bv zDa{vSzxSc*vECUFy1~h#dvLcVmvX#)aPB)wSePT-gp4b^!}Pduq;cf7A6S@S>T@KQ z;kB}blDNx?j^bAPuU=F*Du0B{D##^D<7q2Tghq(Dt3%qd8#5%{j2kXG4m!Nll5cJI z#}nPQov-}-DKMDnLy8j5#*5Yjq4+_L*o~9ln4w z6hSiNbJPtZ37$&D?7V}>i3GOpf?6FWmx;FE8?mg=q6FN<#5G)RPwh2A?CQU+zPPwD z0P^7=X`BN$4mZ8V@a=G~U`>bP04rHXkxhNHMmd-KvD&R`eiCU7=4wp6OQeA>yWaM& zu1~$~pXw}s^(CUc9S@nuTq)EWV>$pkARQ_#8G71n2v^C1*@gA6X=#NKW$-GKM49*% zeoi)w8{n*Q6zu7WR!Ps@aWb?kp@mRAEq*?qVKi7H=o0D`;id@VD%0=U$mSaubxgFpbgJPRvC)t>zpn5l$`>iwMEbf>uns=I-Z z!O+SF4M0f4& z?A>$E`@s?o#-@m#r@OA+S>@KlN*Vc*pK;v4!xMBk*0N+wFT%IvSBGT_#Ga<|(jTBM zV85@Ww*8P#+>H^XPgTWVE>n&7Io6Gm5~(;G7s|-y`JHk})4u0%`GD zy)dD+aindmjRn4shls$ERPj3Axu6nTFD#$n?YTViLm%TXChz5!Hv2yGB7!-Ln5Ycw zZ=3l6f*A856Qhxw)axo$Mmx!XXZiMMKgm`-Nw;QV!sp5E5hjEKVfk^sn-$Pr5Xm{` zN*4Bvwd!Y7-qPkg5H-$l#?)`BBq#fkl^WxG=PFFPl6E9Eb%l)!s|5Qx=fbflw#6+f zmVqc;wtQNLRpwvxUGxh5&h@^z#K9Yg*_4&Eq{6#TmR_6$meqX$efK2HexqO=I(WOv z#BxBOyk-Ut3NRoXe$`1XeMIJ2BpibZ)4otf-29sV+Q_SyQw&+mLs&7xo`eY^8Jc=o z=&sLP)GAN?hbwsS2-ikg%2UL0rPWghGRZ0Qon+{e^xI9{gq>I_kN3k}43ep(r*7p9 z_0C^cPg^QaRJM|p|3I$%okKGX6&lk+QBGDXHgZY4iX}gbl~+cY$;|oc%lql-fvTw@ zvQJ=LruBKO?=8Hp8ac}M2OlVQhAKb!Sgn|-1ea|jvC`?aeL$SGWZm0DAe2XGXccpX zU$HxlBRQ)$KK)iYw7L*1k`^O_$YL@pCNf9l5pV>T!I!bN!-Rvw3Z=z)eSWLb)Ia+F zejB{fyM}ph39Di3j$_v+PJEt#+y}LEN>%ynrSIdpao3$kTuTfGn*y#4>xFX$;;>5` z$VXnjz{>BI@sdJi*7cgS8&(|wM1$#Bk4Tdl z$#mS`f2uz;8DRK`aPAqAq=#+_sJl1$Zsa&+h7f0q79`V6tFG~+wU^D5S#O~^_K*cTvk-`TJ6=7d_P;P` zXfVn^tYH`(`~g6QjQ~wIH#GK}L<>MVqB~PCk3LleVm?!g9{AwDf5}H8&Ag0r7Jz!N z?1Tvy4g$K#D`$FD*G^eJrxG%(?VB9+;-|2pQ$g0>w9RO>rnpyCYL02n{tj(Iu}O%p zxFuXKUdPyOl+=SojFc%`xPBq4PcZt5JE;Y~gcVa3MgLgX!;Dsa9V^x%MtWvFlzzOL zgB(kgq`P7m&8^xeh^`Co6Sp2~+$JW>{;m|(f4ch5 z_w$Q4rU9YPz;_;?tJFS?MD<6Z0+p+eujzjI)SN1GYwl&qpy5&3iP*X&me+4q_J<>^ zpbfY=5+W5#G3!dEcd30#q+a;@wuT_<*7~M3&6B$1T^jY=_{!Fd(h!#IcMnvv9cyl7 zImuSDKXQ1@;%-R#DOIF}sCSW`nX>GL9hU$yey>+p$@CSxL=Sn{zNH~bJ6D(|S0i2H zJ=^GF?wc6)DJfmWDB0*|lX(lQ1D5>qiCQ}AZvtJ$%yJ{5QoldAaz`e#QNz}5*eZ%* ziIp=o!a|1%rWXpypwgjoebbwZwyq~e>Kn$4cS^xQ-?141S!_aX=+kPvq+jGDf3g%n zgcu2X!rU$43K5<&JxO&y)Nk8I8aoc7dFJy|ANsjWi4-dK8GyPvLp5Cs(C`8MHwFwnk?NUY95Z@5&)A3P5>?Y`m7Bb7 z%!BFgzf(d&bEBajM0g!}+}Oy;@KhpQ=C|bF8U^}MRbg_Txbmiy>Ah2ea`yAhO5~jy zQDv~NU-TqqlvDVU)BAPg{d;niYDh%B86){k(&3L(O{XAN4S3ds?>1UovV1X+-zXoa zzG0v?6iJYR+grvKZIr5HWyi*oN?SpgUO2_|j$PjWrQ5>zy7pe5*9M5a{ts63>&Zh6 z&xxe9tmDagD`zHCgO@KKxw}r*vW_{r-?(DC`8COLT-(Z7MWKf!O3;$cSu)n?VVP0* zr2m_+TdD6QGk`9J#F#GO+x3|)@p`6;Jm>Ad%uc6tkLjAf+7 zAB#CH9F+6ZV2%Wr99w)FANi&{fTa6(OBFEaX9lPw{hCeD`1d?By0 zlPcAYGXYS#2-&^#{bFrT1tVEU$MwfE@c{{`p=NC2zpGe}kNsZLvzvCY56z~O$=MWr9O6OSU$TcC z7rn@)idh9RUYLvWwZdoQUE^D>EN&zy6d&eaeGd`KE?uz*V!hz{`Y}rg+kMLJLVDh- z4k84GK~h@Za!hJNDHSHcj}k2=1L4wL3JPukEg^Rfvw1#i1mm@I!A9Jt_(M4;k zmX0-8y(`I5ziHKGvS4XF)gD~R66VTM$`W12NEFjO$wMLjtJ#3A{uuaskq+lljkVzA zB*}b(0Zl{FI!oP{W9gZSoE>ttCc)P>U#8@^Xy$s{WjY)73nVo3)C4x0=45oRy6A0-B0F{kPP zc?yBJmltl=OXSlT)1DQnB1TM90uU2jrtk?k#Q_mG{p48zq>bwY4jA$jqn*bBC__6! z3`&TfaLNQb70pw|h?>!m)C0H!=pZJ70WOXM?LuZ4hmR3~B{2WJ=preVnWvu_Hr^?6 z;`H+AqZ9t%;-JMrK^*lGHDe!0R>>O1^%P(fsk>AKRvf{Fszke&@LUY8aB^?(^S6to z3=hz%6~}k=TkbUnYwHhP`Jf$)zas47g)_eOaEV#7z>X_0BWv}OowS_irrkNe%&72V zwrz=SwU+KZ(0Y;VQ?Uo(^W_0H36&u=w|f%}KUXbSi^>#VXfZxHI^D`fG8iXAb-kdKdx1Sw#OjE#>x5+dg5AnuW2Hxc zb|{agj$`-GNSw&ir9Nu)A!&_I{-{?lC&>N%@db)Njl<;ZM|zL@*_`y*KID|h_30kV z>m!`>pESuw^~AfGrcLp0v6krO8Rjm1zAvaJ*dN4@)?qvapF>(~O2H}M@D*kA0=Xs4 zI#(MYU07HM$|;@X*R-5&si z%4aCEvtkDTiU3bXT;0b9gKs-kS!Kn<9?4U+L;@!&Nr*W8@01d+0bs*36~?oFF%p{q zpHcZ#*}EEpIpjSOYE-DYu;zB2=24%VMo`2^rgRdvq;@YF|EYlTO=uyne4OJR91f=% zSL4~O`l3GXuWGwQ%rSMZy@wCl!@C{;``SO8q@my~Gj=;&%7PPnE=An7lfUZm)K`$k z!UCPSZ@+F}As>R<@2XYQCSPGO!VKmL)9MzL2ObB>A>Knn}d>iitY8!X6DCWGY=YtrK@Z`ul1;R6+QTT%-n(5|j(hKTu0a_`T4z>! zc%imDZ(4rZ0-+waBUmM)F!fIN4X!$EUOI_~l4RH%Rb!K_6}zAV5RQC1M)e!Oy`2Vr z^@{3>nun(~@27?-$>%dr-KpB?X~mlv$HM*Tu2^1j320o>dFJE)atYIHIn&(ziK^S=^7J_qF+|&K!XYxvGM{Ct zgMA!a9w^bmb{TcO2qq)9m?j`>b=Tr`6_l$r+1Vx)5F-OMDV%A^Qe@xC7TqEqx5BKl zN*LuBiSB(6lk4<-g&1Iph~u~Yb_J|8)$bVD6{>lqqb_HTk-(7a+l(neQiHymZyFJs zDfgk*?d0?&w|OP&o53CDCLe~civL!QfRgUt^y10ZVPt%=?YVw21w6C+ei3mc)xg6Xhkj3n+r5xjOma;`6*jaOHs1l2a-lPsZc}-8Dz$zrVd|`cm6<0jW|Oi@awIz&+H7k2IQ~8$t9y+QBVbNc zamv!LLD0tK#;@hZ!){!bDQ-vGKTKRw-6WeJ!>OQI`7FFc1RWq|%r-~CD-cg7v9RCE z>Zzoq&m1qDGkmS@qnOd^}y{0!}70z*vS~8XZwaNKh;=(xwo?5;Nj!ArWLk zL3W&=w+9OTwefNW8a?%Gw5roGLma2_`)7JBAif2;#LK!2+ zx7o;Ymx~I^Ea|p0-BCA{QmW(&_yS5`c5UnrtW{!p;W|#KoCe(Q-4@k5MZ(=melzGl z9AQnoPEk#3l0WFaD;GZ-DWZ`2jkx^@bIPvrJJtY0XJLgTIfcoq3atGDqEgNeNQx^E zH$J?h=}yh^D}K9WjJn(eD_@?q;(cMo93!14#S%5yTEs=vH=AZP2o1l0u}*cL4A5_gX;W=ghEf2%WjH#kaIJ1l>hq6WPS;=yciw&e&Q0tbzu; z3#yqRbp!TfJ;W8s71FU@j|olR`*q06rSJ;3=_wQyYc!DlM2-LyoaMy8p%7|>xro8;5eNt-vii|divOVI5NdvzZ>u!5K2R26WLpEd*CNq;<2--_l3 zXyqQ&!c+Spe1$O zEHgBy(2Cc*sG6vAH!_b?TJC=Juz!N#QA7%uZV)@mOLBj61wQS$PI3kY$~Ysd0$qFz z3Js7OR%t(LJ`uQ_Hlpg!c%z^ILlub5Y~o>%a}UZ|66b^0>zd8coZ+=9?v zysTaX%2Ty-pwUeiu3Bh4Z*w=-HobfG4!uAmjNM(2*Q{I{zneNU|ACmC?)w-@Qe!07 z7&I#YPZD8bx~!Q;5P6mCLqi5veO=FO7J0SytiD6fp}?m_OrPZ#f?NID?@j)}8h<^( z2@rIFQ8owY(oJ=Sr}x-r584>_Ws`aGHdlZB#9u zej6K#{%ZS@f%Ov_W~2rsq`n@jzI45~B-*PJ8h^1ZMB(R-)S9 zT?`EVUXcG{7VAWKQ+4`lRhZXu>8?H2HVAay52Fi?fZJffGBuKW;_UYAZ-i0AwAs`# zPT#&2mAP}#*Yy)aYE)iRwa#!(?Pt=o}%RsNuLJA>4gHBx+j>(i4N1mUK!J9ek8V8 zaIJ8rkXzn%1qC>LuOMG=ZGn53Gs4MvTh9^XONyF%wGp4u?Uvz%4~V}Hh2v$djdAz?l9U|JEG%KE>4(e@`8R(vMw{m zV4PUkN8AZ=2T{PzIV<^6_z-ts!zUA>&Z}ne1kGoW)<~&Da6iY6l^L>~QusYx7FS_q<5Wi67N8ongSM!%N#j-s@ zQ`ovCzH^|KQOdz|s?S*M!)6GZPzbWZv2tq=r-i{;P*?cbB1g<8&f;$|lJdIO^y&Ql z{euj;`Kh^#nShj>2}QfyMcAjdmO_hLQO;B26#i4fZ|(9)KAcRIFFjo3do`4FtI~mQ z&P3L;RPf=5`m2l)X8wnz5K5GRnORC7hkr}j(3@kXH|=ZE+f(hxA0T*DX$Y?r<#=lM zbQ`Nm&qA)Gm%LNd>%{w+y-InmoK{8emEZ_#6`F60t9n&lmSqzuU<8Um%U?t~N3to$-?zMieZ(s+ zL)Rc>9;(#o;gs?Z#HehF&66x)D_HN;;@Xc#ks?cSHY*TgT8$V5Ftd7b;gVu--*KlD z(sk1eyD+YM#H5Ln$+z-g)C#W#pR=meJl7Ry*F5@lkoC+avC&`@C$NU$@3Q5sIjh~P zJbkEYJ=4dtcz2sUuOzWvrGs3VbQT-hVeXyW)XaCC9|&?H5P9#*&U?o&PmdtG)^&+< zmZBf6%4BkI`8R|7p`j<4MK+me6tb+YMz*cbV*gicJ3_(`;)YV$qPo>2h1&Yl>5PX zU-hguRfs6;!310i$bcB#L}OFOr(DiQ*`oiM_s=Dawwa znw~rFN(PKFt@NYpQa8U&D~1)c;#keW8!|f=65u^oiPLGsT;=^1u8-oVdWDVKYFt-DAOGlBz5Sdg@5dh?bDJ(A(9KuR zkTzYhb66@pmyTTDFL)8+DHck4t=?bVWaB#7#JbQ1ysC)4wD`oB1f7}6$ieGD|Ekzx zan+JBbtgm$`M$IB3&l16?g+UR;fP34bvZKV2tWop10sR3m|--mQ`+5Gx10CqPQ~odqcGF4-hFvLuCb~ons*@d7L&H>2rK&t z9XQL>orOFGcmCEg3ZihYj9WPJCgNRHw`QA}>AT+7u&pYrj-{1Pjx9=2?$>uvucoI^ z4n*{B??-EA)TS)O(mf6o$>zD$cYy@M=0 ztM1$-G1A*=5fzv7$E+o-cRn4+kINtQz}T?%dkpWA1T}xJ-e|Oojl$C zw2m;XJ0p>z$%ud#DBn#QzE=YD>OpexFfUWIf#gfxr3aQ4%NFmYv{J4$_Qfnyi@MHw zZtdXFk|+QXo1ibIy)4!j_YJ^VXN}Y`3m(;z1P3GQ)83dU z-w2ZKB8jeS9ac8Em<~gcxAgZople!X6#G1c+3M%LcAxIrv5U$2cr3gU75B2nstj?Cv8PYI4>WsIjb3qxW=N{T||gk6mMif7oh|k~SY2 z*YmOPiN1Hc4WE7@qVrwmu5AuKm9*YPUJjJ?7jknORCwVWKzjn{LZ?_=@n5D3fS?-; zP<5r^@UOxUn`f->5RCWZ{f=S8Mwg=wBiFoTPsamsil|<#sF}k$XnEiWZrr7q-DTKJ85WVr76o`tdhcnc_6NlnBwl z9XdR5v$x7``DpBv>p;p2?JQ+mZieOuTJ^QaA?#*`gg>>aq4{(7HQpN^d4txo}CPq^baJ=ZvqdJV%id zBYED#Gh!_+{CDHo;7zFytveBBW-kp8e)TsBM>Y}|*h5(N}2AV~^OXB83Bk<5aY&+Ge`VC!>b3z4Z(vS?Yl7YUv~-L#R}1P@x5CHLRCGh8?$&nTet1LSBdCJDgl{_=-9 z>I$Nb$u4Fjc*sH~>_xfr(_%xZlz5qR1&^*+_&20#mVQRNxIi{=^RGi*Vns#6BGX`! z5yW`@TZz&UdPYWkIRphogqi_txo?JHSHPG3edAt{7!mf~4^U97_tph`&GP-AhM$-i z^&Asu8+`8)z!V&@VF=%{s*Gq4;G$)xLwo7OwAVk(Cb@~;jxu;%G=@JpsArEh0r|D^ zID16|wH*6VrPq@zy}Sr{I2m)?p3;j&@a+>vVZe>BLjn^1v;OQJP?I}I68gw>8eLA8+qk}MyH9N-))b?|rpU`>&uzZ_T zb%OC>7@w<)EZ*YY7e3v@F0v&+MYAu6&ny#|Y1QJh>KX>KqT!c#d}ED$T=@R7JV7|= z)}caA3SW>Hx3`qI5A{H)d;cJd-i z>P0gGX^2&RP6aS{3XG)%JR6%4F>BrgaJw)w48#nXg{q8FjnaBWz@&HK5b~(>f}~E_ zjiCfIb=*r$*1@PW2I<@Y21zO8k$)jaDM7N8rq&KIqCR8S&D4|>Gk5X4W2R#fz_XYo zqds^Rf>90FA@f}Z9oEgEle;@8^Yibkyr40o^=jL})Zxjyi2H8hG#c0MB`vU2p%1Zv z!n?_$le8c(g2t3IA=^zbm@6s-PTj1!2nwWU5 zH|^@4Erqp9r9vAST%9axOZ@@hoc{82^~c{_K#$Y>x~tmxli6$zYNF&s*XBF<4)0B~gl=OLt+DF(cF!Z~(c@K7r@Ic9)}z#Pat z5%+0h6i2u;4nOvEsQ+xnua?URU}l{y8K~v@nu<+7>H&22KmZLsGq_d&z1{&jHWb7? z(YTR=wog1t-1fv8{Wm*%uDlTxsMT0vM!(8CisuW$+W*i~vt>Cq4PZ|^aGwCV|2fBS zZ4WRzk|lu8M+>GK2hz%1yobmBVToDNOJ0L&zLvb3NWxA>HGZY+V$mh%wezM^F(I&A}S#bnT zXS6Uc#4~XT%-pB?pQkZ0H|dvS#D#F@A^WE6C-#H!yKn2gKEC~}lmVT-zd4uimlc4h z#b1>~Q6uU@M zQLMK>i)R;wFC;S*vu?m!LxJ>hF!T7%hB)BHc^WW2>U1dcS1KR)v_=|A9vTv{_#^FU zDc(HJ#f&{Po;&Z3I!pnEz=Y8pWx!kkQYuCdXvY9el~1+v!GV~W!;a z^-ve)A;dyuKWMUdPZ6t09JoqJUS3iEplxu6cNWTqCoK!3~fE+xvq@SyJ z2nq8~TSsx2Ivj8c?82pzj+{GV!h#4KgwZ^NIj4V;c;>b+9iTH1JfTkp&_TcZ=Q{hd z1DU7S7t7SSPT(*M@pw!7%gPGO0wMK$Odrzk=Q#rxb_#Ev#vien$F6-^zfsx^CnPj-n4xrmk_`VZ-0siV|u1Hts z#1yz?&t1g8HAhcZ0Qds!2c21u5h0&bhS@1)5hzczbr70|_GO(9geXvH~o% znV4l@-9S?(&IjvPkTE*T<6yGJuf?;*V#b(k{QRN*@i%u4{Y&Ty%TAMEq$8<}+Q}<_ z*d0slRI0VvJ)EFm_8ym_9Ht(cb}u}dq{B&y>X_SLfIKOwaM4g{xg`Wx?+U zs3C*gulm(mpIhr3r&umu*z1589h*!g?h{f#X8#Lu2E?MEiJ%l2!HjLk+pdEkm9Rc4 z?M`3$0RkJx_PHUx-JH2TTq!$+l&iK~!J*?r$L{h%(<6uvB6S814=E1TouZz@L&6-Z`JxtXBv)SAOjJdD*$%I&mo?8pkREU!QDQ~%{M_Nb zZlv>`bg-r{tx1=UE#Z%_+X6_6P||6y{d;x+(v5vG z7o^>3y7j(&bTnn(M2)ek`J+T@G8$G2bfYY?5oN#8X7^As^(p_}a`}$!}Ac9Np~OLERo=YD4vG zdy%oknr}%H{k_Orn_>+HkvE|?g+Hg8D8LbXT{)uslxjLulfy9H@dsibMREpMyf2oD z0q-}^E#|s#kC=!)N0k0e!&UB$D3hb>!^O6f-WQ!Q*R{xQ8WM1op5sLaFNPO#p= z-ERy>HA4mbnF~AMpXqClkFvGbHvSs1q1bG}!ax5PK#L1hWhSqrkn4Ci^u0Dc-wd@K%TR8gGkD`ZLLm`+bXAqhD>S zgfG^aB`xbPcQ z7XdGm%7xEN&qMV0iG!$iiJo8o7ccDOFQ7AcX!B3J? zl3aHoF4h69Ge)vgd~-fqw8Ubhtd(7KBGy66MM}g(`15WWv@9w(Obq10FXJeqH=FJ* z+qyMukR9EEP93}eZdOY_dYnbv!CBO19#eQ(PK*%&{ZOd9l8~HLqDf_T=qa3RSmc?Og2I99 zZ;u19*Zq3qH81~(U!2sRev7ei@)d3@zopnPF1?P_fhHZ^Onv4+?qo+Jb7KN64|w`$afWHUPNS zto7(LO>5h^R4<)#Fu;q-U;td&&}MMq3d8q$$(+?ek;HopKS19d>ps#DCT>|l3-uG~ zK6d*^yVR6=kEnrX7A_dR#V2Mt!~%Zm*jMeQWL5;CwZ-iRi-S zNwj-+`#FpE>K7gIoy8O?b@mi^hp~xsd;Dvb>oP08Ghq|w^wjAdRNX6{OP9kUSX@^; zUd|12sU%nKj=^Hv*c)oPK1I z0FH1Cy6E%8o{~-^V??5A$Oa3m`X!iG$Ox$&GB^LIXfF z9|>RyDi%eCFfgJ{o+?hSu1sMjCk8NkWn7%4V$lrMLgEs3<0EkUnE`sPH5&X*j+djp z@LesL2|6sIj}g#mqWK@7)N@d!H~Gs?cqjKP6rc{_=Pc4X!KfE&tZP~7 zWwvshNmQ0SK&#WyEnrr%!CttvX1vR0dDa!wxca8?B7dMqykFBNi}WM^^}buLp|+jP zR$SH5w88x?=Z1sYTsi7Z0-J6ypeKB%W>Y)4FG8^Cn=Y~dr>hbtDd_b@Gi*jvr#Oh2 z=7rbr)kVcsF5w+s9-^FUPiMSs+Ub6PaN9X+O55utpTVJ4pHn!(tc`jr;!iTd@rCX3 zsMvg)sF~Gf_M8E>TqC>UQSgwN(L|g3p;;u>wF2yZVRS|sHLVk`D)n6&d`)jXyh{B- zvDK_@UR1F-o#x(C#Ni&xu4@tlKxlub-B)a0sDb2OxnM9>Pp7$IH3OXWiRv7P({I46 z*SnZYc?71S~b&;)`KEbO?-l38a%iB>&N)(_soL-S?;i|N< zt}Ri+qkZ~N$~MjzNS-;cR7Bia=*#DkRHct|oB>B>-uu_TqfC5`U;6xJhTea7KgrLQ zS?Vu?3M_|4s@l(&o{iM)4wGYfXsDqI4TOk$Z(WYQFcT2V5FY}5q~`1fZCRcgOmA;5$?5G`GE-%-bl6EN-W2`tz16SB+Ek-C zJHY|P`1&bDjJ%C?du7k`Nb7CB-q0h(=6erlgPumnRyLr$R_R2JOoOVwnYr}%&$cFa zg||^mBk9oelV68PIf67D*Q56%B|RIZhQ>P0T%S@vtW+dRM0A*XVk(yDIf~F9bewTx zzV|I^-bokcC=m2}>9<`BFQM8T)mam%a&5QP zOQ!FRiAEjYjOw`mO$DsH#W_=CLuR@@FBDNjL8g&wXI@t;(HbmGs;y-TZEa`mRlA?MqbAkAK}~e2Lsb!?yRA1q*Onk2 ztjJK*3hXTj;u7t5z20Btp7O59qH)_?ht7oeC8yb3r_KSe)8L*ly)tM_S6hv{*R%DB z)rI0db&8gor7!XYMpaiht05jbEA17sc59s$s0v6xI+BA|ekTUn1Z>R~=+BQ>P`kFf zGB&Xz^`w^5Jf>q5f}PM0alb=u*@LxZpkFfyk`G4P6xpP6gq_z3m2<}}Ze-0!dE0En zPuljC)?V(~c(+JJjP&E%9RV|<=JIN;G3G@>{~vpA9oE*?^@~<^X-f-~;@TE1+Cp&M z#odDiXt4mny?6yDK+&L~NC*T1g#@=2mjHzjT#CCpR1SN;=X`tb^L^)@_ul6`&%J-# z{IQ-fSLR$RnRCst#vEh(eshXOm{5u|V(CjBtiG`@L}xobI5Br!>~q+57tVq_0g_N7 z(`h?BHGkdCH^ljOuEZVn84Pb2@K8DRTy6M*p^V5PMr6{rW5;rk9`JHW_c*^LYRBX2^EtH<9Fj zRQ+ESZZ%n`%Fbo{q`M|-)ciIgg=qb7s_@q}PUlD0d?o(tMmG!N;+~~Q^c>EYgmCn; zd=7TsP5SQll@><#{h%fA)qmMgY_%Zda|z(PF!0id_BQqBe^#;?jrdai^L_ed z`?YP~T-b6{t<-Xb4xW^ zSbyp+>xGB-^2Dr!Bt^?4WvA>a>%xk2-SosU;fHFxXWX{JXrJIVxqm7DXPEC}bcQI;Nze}+1 zl@5tQTuqX6gW$wG&SWxgj&VhIE~6G>FGQJ8aO~^h!g}(cY)M&sb);WtK>Vl@?657O zpp?j4{aWNSyvf_8tGG%Nm7l!t=zbroTwA#`2$*R2B!nvQYka}_s} z43l64QpbVkg!-DD_@~)4u4>yZQ5*&g0(ci;#R-e z8GzoKE#BbRQ>sT2*Ov_Kv)sS8SMt1nUQZvTq$(93LS3euur=-X+fEm0A`7av)2)Z@ zU8oJ%Bz@n*N0Ox&l~r9-h@Mtk8`c?C83cpW?Kr7_yf-}V?jq{Q6m|=bSQVLI20KXA z-Dwi&ZSZI9-CW<&l6K-R2fbidQ0{<*yk4GZ87yIPA;faHM|Ck5;zvs$JwfiyqvOGC zj4?G}R{oh7F?jX(2t?haq>Qg2fH5ocw#@Qmp=TEiR1TRD&?c>Z#7=l7U3XgjGcZgT z*jP`EyfX+`<*freNW)QdXgSDe&dh!*vwjH0(t(vgp$fM@;p(mh@|`nJ57u&0t_b3k z^x4Ii6Fk7dX<16F_uDP?LhUdW*mJ-3HR#|64b82Y9J?nH#keJn@N@Ox1-|#>%8biV zi?o_wmM>;yLM-pjlMHhE;IVzdfq~iZZ%+iGTB{gv2NPR6ZwK6xp10~Nv5L!`EUrAe z^BCLgXZKSy#4hw!>Wh6E@-rn4cRFg^p!5ni%CkfE>oMvIjAt0&0igFU)0x4ak(vG+ z{u;9V4x@gx38iS)fko#d0|${ud4HQnf6b^X>3?!tOAK^AdY}AgkKxxfr@8CckN>Fq zp9>6;xD#^n^qhw()#*9R7HJ9^2TRuB`l9sKOLojTy2;7KD*6drc-!adN+)Npw^MuxKe^d&XgVR{zGk;b0Vpa@hjS39NS5tW_jw!)F`P}i(a zp9Nr5#Q?*yp=sZ*q+p^8iNNAwSbuPv*ue+7ahoUJ!d49@r*^3vobei-O0FhRou^b> zbm?Fl+m_&iZd`T3Qb9VMGb@XrbhtdYel0Voy8Wa#C`T9*7u7A;I*sX3{dqBQ%KSSS zVfW+98U+UApiB1b(46w{zwi65zy}>$!?pKUf44HTJM8_j|K>k;*43Fs_*LfejnbAq zg3-2(8zbniN)s4|ZNb^3MO~yNr!lTy@l)j_K#L;-Ro)cINxrK3xdmHqXknW=keq~# zhc*!sKIGSXHDpfh_mfd5e@o77ayOF4QrUVB5`4XO|Fb%9^UBQ zA*a*#K`nT9-(4Ajp{-y*68!zVA3{q#}aMs$?ScEZ{va6+j6L~%r*GT;e-ntwOBJ zb2_AN@16MWlQ^bWN2t4S&9@cDY83GZKhzGk@!OuLiOJHb9^K7$WILb$kXTh z1GQKm)Ns|90oYQ1ga?KOkY#l{4Y>-$U8(XxMwvV~f^G@qfjc{#>cAc_R6EOO`X4Ql z^TY@x;h>QRa~Rge*#O@qdEY91e&;DnW6xu~yBsDT4*`62G<3dwud;j_C-E7LTf@Ko z_AwHAl}#v}sV$?WQAs&nCxldjL-t?=dzz1{;^VLIvW~CtCHe+?Ud|5S$QeCpUFTa% z!)5^|2dUPEO&Ujs;WJIb;?RS16E>qvCBG}Am2^f|Pow9~1~RL!#7sw6=jg)J7vwAR z5t)oe!d|x66HxUisJct0WMf@L%~+{j>fs4>P=#XP5A}7Z67_Nc?sS`P;qGIQU5gz@ zU^D!c&>q;K&vJX=`$GMBKDQBlpM&qEl-&KR!An2b-Z^*^qjMZ1-LdZ5f%Qei0*>|Tnh}6mO?Z9P8nVsVX<}^$mx`#6ne~kIg?Jm z+mr=voBh=zN=zS_-%1n9{<<~@e?V;u56S&eaDidj^kmsLQ&51gF5`$=9eDD}-o921 zqf*CTtLO0{N*zymh<1HZ_^PTZPeyE>NvlG;m|zkELT4WanE@GGVAPWczMc|?QG>cb znrjnDactcZi`ToEDBLWP3WAd}B-TzXY9ZArG>q;!WP7M$Z=JjsMTY2F(W);Gqd4l+ zkt2sl&1@|fqdQaD36)jUYO_i&CU&H~?jOYrDQh>;V|BaEtJuF0B^zHlT9Pt4ScfP3 z6zZU`F@@#B&NbXH69trWLX6NFhgMk_(0lxVGJ-MusC!+wKx}h}Va=OxB)%59!0}Fu zXyw^DKo`SXD&FYukgL}JM^BXZimSQ=AHh_V@4i5;I-n4=k*LXj@?;~COw>S)1wcy4 zsoekAC^A@x?;DY135{0Va(fp0er9`K$1M<=LaBb=ayQD`f+r6P`{1If!3uqEs;Z_{ z0jA`C6)r05IM8hN#pxBet8nIC1;hw*1`4VH<9Cw{GpYxAa=iINqwnAAr@6O=%x0gs zn?s-~6sT&Wd)(R+Ic^s<{=$&Qmuhd2{1a-`CpBXlWKFT zjA~I$;^v91;kutm403$IJDS4wezfpGfM#K+5uDT>=w}5}cuBpNNhvhf79+FN+9;K6 zKhI)q=DQt2%Jn+TZNkS2JY<$*>@pRrV?-2TTd2POA!%%$D&e-V^h1|$cziZlBe6$c zY7?IeTG%P}F`J3+PmU3{yscb&Bj0%v=ZxbvD}qzZf_HVvlgwcRSUuNmWZZ~EuBgMd zzQA{aV=-}mSeezX}(i^X~5Rct20tY$^o>JpQ?tdOZo#LBv~H<20MJDF5MD zkrx6x;Y;el1_W7dRS}1ICU3=z(Ex3~_&%m|N1xcB6heN5SqI&wUv{oXEy|sLZm&k3 z`_`{(ik}^-Du+ErbD&1RUC7w4YvVIzUX2nw+$qd?1cDyd$)=}~vxQ4zfnLv{rOi9l z;xSCOuaBMOA=crmSxlxrO)<(YtU2h{HU3}MV5H1SGxX{hB~S6Ls?VFl@E>*FMo*nS zH?8RwW6WadVIhJe40UM*Ss&_`>^~J(h&jj{J59w+1wOn|hAa7du$>JrVY7U7Pa|Ov z!7Q(As)2lVfz{UsReLz#zI5PGHslktPhrGZ&)wC%zpxn0s}$WPU|r>JAV#}CCC@9| zDnL$1a(&+JxgPdoF9|iaU=gYxopZ^>%$r-rTp#5!8?u_f!`}VMidOH(? zP%EW}Gwx*(G^`5gMh5VACoRC6lv= zumx#qJnAa7D6m#+h|u}O&vUS(%k86Sy5YaA5x|f3hu~4k^~c=O&*AYZ1~zW7vYB!0 zZJR2?H_`rqVFp&he384g>b5YrhT)^Mw8FzXA2g*lN%)?c(woq2+W0w7-&DtZ`xKrX z?4$$=5wz^G5u9We9Jd)BtyB+JZs9$+Ub@`QbvM!@Ke;N=AhPh%_KB*VccOzGC{&k= zJ>3SRay`nOovU3bg;^d7*UF8^2y*5Duy8&IOE186_p$a#RbHRuc*8_OTn0B3;h#$o zSRj1K@OfZP3GylG@3$G*N#%A&jZSaEf!>n^JQ;IQ3P{~~c_UKShfyR6r6USS&l$4g znQq5)5p8YWq_L;h`DXa^6$#<>q)63#EY>BvU{cIhrD2EmWZF!zw28jl3(qrpi@)f? zBu9klcNlp`eyHBp||1u77&`=b-*;rTy%Wm9`1v-&fkUB9hK^ucw~6 zbGhFusZ^KiGvQ{jJw^&j^`T8w`aX0!Y(qBkHMTWTh>mtbRs@AZ%!BZ|Q*NARPf znM%?0007!DdE=6+ zLA8;XqfYdWMX~c#K5dt2O;`_yIkYdvj^>p;;agwuSl9-rKus$ClL=fEAZ=kDmP3nr zIx^Nex-@lwQ&=4nXd|h&67TJKvS_lLu-f2$QoS?HZk|2f(aX2mBaman9Hd@cr%5?T zJ1C48O+_%z2J?^3yfZL~LVm9MfeKcGjOs&iSB_x1mB5HD81sO~^s~Yd+|G{KAVRyR z*szcjYUu&K;W3qJ3!|f<_DgW>QDx9AtWlP5985(8eW$OQi(04^CcgzU>9*)^@LZ%( z4&dfk1`O9%(A|Q8Fs{tgmjN0F0?`|hP*fp7U&_emHAf|HqS=bciFkPIjDqsr)a7h8 zfKHL9pCHCEdwqFaJzEeFbtG_-H4 z&Bm3w#qp9NJ(f!Y`GXZsc=%KBRt>2TTc%&Cy912b~9`HMzI@42a za2-n+3gNYLPM0cLK%n%?Psbh$QYX8!X8B6TYZ>{BduwHExzoq?B? zl>Oby!!w1`9a4ULq!JLB!8d$|$E;6pl?u_{Ih+-cLgM;f!wO;Trd(Dzk|vjmY;)Yk>h;Go8dfmsx(z))V?3Hs$nd7dO|*;om6U zWHT!?WxZ-Y$N?Bfr!e%+D)zPHeD=E^!?4M35!^Y4yV1L!p1#@%_PdZ1e$8^@Kyh*} zTK~r*(~4W8C76ch|8B4{V}JZ?08STk+Gr3_(y0xKX4820()#dDq;COP`|ZN z)<+ZO)~0`|7{Q%w7;7rA=|P%#*U?fnLdIH9IP+VrLIl#)Ri5DxAPZq$Q%;?3{5TqJ zl90{}_96OyDOoA=obkb0k^^g$aeAKOru~dGEonq^npZJQiAmk!=GtW*@FsDE-m-s= zzaEEj>DTgTTclco>U;afVTdqgX14;$%Qrs*I-^F->;f2c<(~rw{O*~b8yr?Q#PyY= z`a=z)1+4Z#@)K;aqh3nzuwF8Pixr?-)W`Cec~_`rZE?OZ{09|Jxg3))FN8{4(X^xH zta8c`i*}$Np$C$e5B98jNm9_^^+HCU)R#}e6mfY?aSYb)h%*`%+jjI*XkEYTl`#K zr%iHD36oTwaH!wgC4+ojGAv03*0!5wy4RycV8ogd5^-{O+MbjiaUMa7y(B6EaV;=1e3w5=AR_KUN!?aMV{3Z z9@g-6aA)2!$nPN@?Ek7*GjO&7rI=SN_h!H4*2@E^e!)ddg;R0kKN!L=MZJ*x?tvdniA~wv(23JNw zrcKB=i}Q}B=%cZQyLj^%1A^iA_PundH9772Vg~}?Uy{5cVa{oNG3CoxVcVG{k47EC zRlKVnPFWP#t61dWGYnMRIg+}+C(yZ*5rU$9dbV7Z3tDJPJeV<>a00{hl#(>@F?x_A zM1l3p=W}rRkN=}~>9v3dUjtMoNuz>p^FHe8L(P@UP@}V7mf`vRg|96hdwcO<7^mos%k16qgQ2U_4UJ)?JM)=mZModz=5<$>YGTBei`q|ZO%f3Dj?rqD|^*xeO=#VLV`H$qs`A`%T_;xt*3)Qf?(d7vH13#TjUU_P*2=|UyR#@gKq1z27uyu!uLMBr!_AeLiM;{d;58WD?lnAFpo~y})=+{WLItgY&u@B#FWa`60>z z%5<#_RRcQ`Su>aouTB3ą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

    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 * https://github.com/LuttyYang/luci-theme-material/ * @@ -89,6 +89,11 @@ document.addEventListener('luci-loaded', function(ev) { $(".main > .main-left > .nav > .slide > .menu").click(function () { var ul = $(this).next(".slide-menu"); var menu = $(this); + $(".main > .main-left > .nav > .slide > .menu").each(function () { + var ulNode = $(this); + ulNode.removeClass("active"); + ulNode.next(".slide-menu").stop(true).slideUp("fast") + }); if (!ul.is(":visible")) { menu.addClass("active"); ul.addClass("active"); diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less b/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less index 96e3864be..54969b3b7 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less +++ b/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less @@ -8,7 +8,7 @@ * Have a bug? Please create an issue here on GitHub! * https://github.com/jerrykuku/luci-theme-argon/issues * - * luci-theme-material: + * luci-theme-material: * Copyright 2015 Lutty Yang * https://github.com/LuttyYang/luci-theme-material/ * @@ -30,6 +30,8 @@ @import url("pure-min.css?v=1"); :root { + --primary: #5e72e4; + --dark-primary: #483d8b; --main-color: #09c; --header-bg: #09c; --header-color: #fff; @@ -40,7 +42,6 @@ --main-menu-color: #202124; --submenu-bg-hover: #d4d4d4; --submenu-bg-hover-active: #09c; - --blue: #5e72e4; --indigo: #5603ad; --purple: #8965e0; @@ -56,7 +57,6 @@ --gray-dark: #32325d; --light: #ced4da; --lighter: #e9ecef; - --primary: #5e72e4; --secondary: #f7fafc; --success: #2dce89; --info: #11cdef; @@ -333,6 +333,7 @@ abbr { cursor: help; text-decoration: underline; color: #5e72e4; + color: var(--primary); } hr { @@ -352,11 +353,6 @@ hr { .login-page { height: 100%; - background-image: url(../img/blank.png); - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all 0.5s; .video { position: absolute; @@ -368,15 +364,13 @@ hr { background-color: #000; background-color: var(--darker); overflow: hidden; - pointer-events: none; - video { width: 100%; height: auto; } } - .volume-control { + .volume-control{ position: fixed; right: 1rem; top: 1rem; @@ -386,8 +380,7 @@ hr { cursor: pointer; background-size: contain; background-image: url(../img/volume_high.svg); - - &.mute { + &.mute{ background-image: url(../img/volume_off.svg); } } @@ -432,7 +425,8 @@ hr { width: 100%; min-height: 100%; max-width: 420px; - background-color: rgb(255, 255, 255); + background-color: #fff; + background-color: var(--white); .brand { display: flex; @@ -440,6 +434,7 @@ hr { align-items: center; margin: 50px auto 100px 50px; color: #525461; + color: var(--default); .icon { width: 50px; @@ -485,6 +480,7 @@ hr { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #525461; + color: var(--default); font-size: 1.5rem; position: absolute; z-index: 100; @@ -498,6 +494,7 @@ hr { height: 1px; bottom: 0; border-bottom: 1px #5e72e4 solid; + border-bottom: 1px var(--primary) solid; transform: scaleX(0); transition: transform 0.3s; } @@ -512,9 +509,11 @@ hr { box-sizing: border-box; transition: all .3s cubic-bezier(.68, -.55, .265, 1.55); color: #525461; + color:var(--default); border: 0; border-radius: 0; border-bottom: 1px solid #fff; + border-bottom: 1px solid var(--white); background-color: transparent; background-clip: padding-box; box-shadow: 0 3px 2px rgba(233, 236, 239, .05); @@ -546,12 +545,14 @@ hr { box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 50px 0px; font-weight: 600; font-size: 15px; - color: rgb(255, 255, 255); + color: #fff; + color: var(--white); text-align: center; width: 100%; cursor: pointer; min-height: 50px; background-color: #5e72e4 !important; + background-color: var(--primary) !important; border-radius: 6px; outline: none; border-width: initial; @@ -560,12 +561,12 @@ hr { border-image: initial; padding: 10px 0px; margin: 30px 0px 100px; - transition: all 0.3s; + transition: all 0.3s !important; letter-spacing: 0.8rem; &:hover, :focus { - background-color: #5065d8 !important; + opacity: 0.9; } } } @@ -579,10 +580,12 @@ hr { justify-content: space-evenly; margin-top: auto; padding: 0px 0px 30px; - color: #525461; z-index: 10; - - .ftc { + color: #525461; + color: var(--default); + position: absolute; + bottom: 0; + .ftc{ position: absolute; bottom: 30px; width: 100%; @@ -595,7 +598,6 @@ hr { } } - @supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) { .login-page .login-container .login-form { -webkit-backdrop-filter: blur(var(--blur-radius)); @@ -663,6 +665,7 @@ small { .brand { font-size: 1.8rem; color: #5e72e4; + color: var(--primary); font-family: "TypoGraphica"; text-decoration: none; text-align: center; @@ -732,6 +735,7 @@ header { height: 2rem; width: 100%; background-color: #5e72e4 !important; + background-color: var(--primary) !important; } .fill { @@ -776,11 +780,12 @@ header { right: 1.25rem; float: right; - span[data-indicator="poll-status"] { - display: block; + span[data-indicator] { + display: inline-block; font-size: 0.8rem; font-weight: bold; padding: 0.3rem 0.8rem; + margin: 0 0.5rem; white-space: nowrap; text-decoration: none; text-transform: uppercase; @@ -895,6 +900,62 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { .nav { margin-top: 0.5rem; + >li>a:first-child { + display: block; + margin: 0.1rem .5rem 0.1rem .5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .375rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; + + &.active { + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + + &::after { + transform: rotate(90deg); + color: #fff !important; + } + } + + &:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + } + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); + } + } + li { padding: 0.5rem 1rem; cursor: pointer; @@ -902,6 +963,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { -moz-user-select: none; -ms-user-select: none; user-select: none; + padding: 0; a { display: block; @@ -916,140 +978,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { display: none; } - .menu { - display: block; - margin: 0.1rem .5rem 0.1rem .5rem; - padding: .675rem 0 .675rem 2.5rem; - border-radius: .375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; - &.active { - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - - &::after { - transform: rotate(90deg); - color: #fff !important; - } - } - - &:hover { - cursor: pointer; - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - } - - &::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e915"; - color: #5e72e4; - } - - &::after { - position: absolute; - right: 0.5rem; - top: 0.8rem; - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: '\e90f'; - transition: all .15s ease; - color: #ced4da; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - transition: all 0.3s; - } - } - - .menu[data-title=Status]:before { - content: "\e906"; - color: #5e72e4; - } - - .menu[data-title=System]:before { - content: "\e90a"; - color: #fb6340; - } - - .menu[data-title=Services]:before { - content: "\e909"; - color: #11cdef; - } - - .menu[data-title=NAS]:before { - content: "\e90c"; - color: #f3a4b5; - } - - .menu[data-title=VPN]:before { - content: "\e90b"; - color: #8965e0; - } - - .menu[data-title=Network]:before { - content: "\e908"; - color: #8965e0; - } - - .menu[data-title=Bandwidth_Monitor]:before { - content: "\e90d"; - color: #2dce89; - } - - .menu[data-title=Docker]:before { - content: "\e911"; - color: #6699ff; - } - - .menu[data-title=Statistics]:before { - content: "\e913"; - color: #8965e0; - } - - .menu[data-title=Control]:before { - content: "\e912"; - color: #5e72e4; - } - - .menu[data-title=Asterisk]:before { - content: "\e914"; - color: #fb6340; - } - - .menu[data-title=Logout]:before { - content: "\e907"; - color: #adb5bd; - } &:hover { background: none; @@ -1062,9 +991,10 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { li { position: relative; border-radius: 0.375rem; - margin: 0.2rem 0; + margin: 0; padding: 0.5rem 0rem; background: none; + list-style: none; a { white-space: nowrap; @@ -1079,6 +1009,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { width: 0; height: 2px; background-color: #5e72e4; + background-color: var(--primary); transition: all 0.2s; } @@ -1109,6 +1040,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { width: 100%; height: 2px; background-color: #5e72e4; + background-color: var(--primary); transition: all 0.2s; } @@ -1124,6 +1056,147 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { } } + + + + .menu { + display: block; + margin: 0.1rem .5rem 0.1rem .5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .375rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; + + &.active { + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + + &::after { + transform: rotate(90deg); + color: #fff !important; + } + } + + &:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + } + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); + } + + &::after { + position: absolute; + right: 0.5rem; + top: 0.8rem; + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: '\e90f'; + transition: all .15s ease; + color: #ced4da; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; + } + } + + + .menu[data-title=Status]:before { + content: "\e906"; + color: #5e72e4; + color: var(--primary); + } + + .menu[data-title=System]:before { + content: "\e90a"; + color: #fb6340; + } + + .menu[data-title=Services]:before { + content: "\e909"; + color: #11cdef; + } + + .menu[data-title=NAS]:before { + content: "\e90c"; + color: #f3a4b5; + } + + .menu[data-title=VPN]:before { + content: "\e90b"; + color: #8965e0; + } + + .menu[data-title=Network]:before { + content: "\e908"; + color: #8965e0; + } + + .menu[data-title=Bandwidth_Monitor]:before { + content: "\e90d"; + color: #2dce89; + } + + .menu[data-title=Docker]:before { + content: "\e911"; + color: #6699ff; + } + + .menu[data-title=Statistics]:before { + content: "\e913"; + color: #8965e0; + } + + .menu[data-title=Control]:before { + content: "\e912"; + color: #5e72e4; + color: var(--primary); + } + + .menu[data-title=Asterisk]:before { + content: "\e914"; + color: #fb6340; + } + + a[data-title=Logout]:before { + content: "\e907"; + color: #adb5bd; + } } } } @@ -1687,13 +1760,16 @@ td>table>tbody>tr>td, li:hover { cursor: pointer; border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); color: #5e72e4; + color: var(--primary); background-color: #dce1fe; margin-bottom: 0; border-radius: 0; a { color: #5e72e4; + color: var(--primary); } } @@ -1712,6 +1788,7 @@ td>table>tbody>tr>td, &:hover { border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); } } } @@ -1757,7 +1834,9 @@ td>table>tbody>tr>td, &:hover { cursor: pointer; border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); color: #5e72e4; + color: var(--primary); background-color: #dce1fe; margin-bottom: 0; @@ -1769,12 +1848,15 @@ td>table>tbody>tr>td, li[class~="cbi-tab"] { border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); color: #5e72e4; + color: var(--primary); background-color: #dce1fe; margin-bottom: 0; a { color: #5e72e4; + color: var(--primary); } } } @@ -2080,6 +2162,7 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child { margin: 0.25rem 0.1rem 0.25rem 0; color: #fff; border: 1px solid #5e72e4; + border: 1px solid var(--primary); border-radius: 0.25rem; outline: 0; background-image: none; @@ -2334,8 +2417,8 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child { width: 0; height: 100%; transition: width .25s ease-in; - background: #5bc0de; - background: var(--bar-bg); + background: #5e72e4; + background: var(--primary); } .cbi-progressbar::after { @@ -2421,7 +2504,7 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child { } .modal p { - + word-break: break-word; } @@ -2605,10 +2688,10 @@ td>.ifacebadge, min-height: 15rem; padding: 1rem; resize: none; - color: #eee; + color: #242424; border: 0; border-radius: 0.375rem; - background-color: #242424; + background-color: #ffffff; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); } @@ -2718,7 +2801,7 @@ td>.ifacebadge, .ifacebox-head.active { background: #5e72e4; - background: var(--bar-bg); + background: var(--primary); * { color: #fff; @@ -3082,7 +3165,7 @@ input[name="nslookup"] { } .modal { - + label>input[type="checkbox"] { top: -0.35rem; @@ -3284,8 +3367,10 @@ input[type="checkbox"] { input[type="checkbox"]:checked { border: 1px solid #5e72e4; + border: 1px solid var(--primary); background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; background-color: #5e72e4; + background-color: var(--primary); background-size: 70%; background-repeat: no-repeat; background-position: center; @@ -3430,7 +3515,8 @@ pre.command-output { } .main>.main-left>.nav>li, - .main>.main-left>.nav>li a, + .main>.main-left>.nav>li>a, + .main .main-left .nav>li>a:first-child, .main>.main-left>.nav>.slide>.menu, .main>.main-left>.nav>li>[data-title="Logout"] { font-size: .9rem; @@ -3728,10 +3814,7 @@ pre.command-output { display: inline-block; } - .main>.main-left>.nav>.slide>.menu, - .main>.main-left>.nav>li>[data-title="Logout"] { - font-size: 1.2rem; - } + .main>.main-left>.nav>.slide>.slide-menu>li>a { font-size: 0.8rem; @@ -3897,782 +3980,3 @@ pre.command-output { } - -@media (prefers-color-scheme: dark) { - body { - background: #1e1e1e; - color: #cccccc; - } - - .login-page .login-container { - - .login-form { - background-color: #1e1e1e; - - .brand { - color: #adb5bd; - } - - .form-login { - .input-group { - &::before { - color: #adb5bd; - } - - input { - background-color: transparent !important; - color: #adb5bd; - border-bottom: #adb5bd 1px solid !important; - border-radius: 0 !important; - border-top: none !important; - border-left: none !important; - border-right: none !important; - box-shadow: none; - } - - } - - .cbi-button-apply { - background-image: linear-gradient(-135deg, #6c61ab 0%, #594ca9 100%); - - &:hover, - &:focus { - background-image: linear-gradient(-135deg, rgb(85, 76, 138) 0%, rgb(72, 61, 139) 100%); - } - } - } - } - - } - - header::after { - background-color: #1e1e1e !important; - } - - - .main { - .main-left { - - background-color: #333333 !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .15); - - .sidenav-header .brand { - color: #ccc; - } - - .nav { - .slide { - .slide-menu { - .active { - a { - color: #cccccc; - - &::after { - background-color: #cccccc !important; - } - } - } - - li { - a { - color: #cccccc; - } - - a:hover { - background: none !important; - } - } - } - - .menu.active { - background-color: darkslateblue !important; - color: #cccccc !important; - - a::after { - background-color: #cccccc !important; - } - } - } - - li { - a { - color: #cccccc !important; - } - - a:hover { - background-color: darkslateblue !important; - color: #cccccc !important; - - - } - } - } - - - &::-webkit-scrollbar-thumb { - background-color: #252526 !important; - } - - &::-webkit-scrollbar-track { - background-color: #333; - } - } - - .main-right { - background-color: #1e1e1e; - } - } - - h2 { - color: #ccc; - background: #333333; - } - - h3 { - color: #ccc; - border-bottom: 0; - background: #333333; - } - - a:-webkit-any-link { - color: -webkit-link; - cursor: pointer; - color: darkslateblue; - } - - - input:-webkit-autofill { - background-color: #3c3c3c !important; - } - - .cbi-value-field .cbi-input-apply, - .cbi-button-apply, - .cbi-button-edit { - color: #fff !important; - background-color: darkslateblue !important; - border-color: darkslateblue !important; - } - - - .cbi-section em { - color: #ccc; - } - - - - header.bg-primary { - background-color: #1e1e1e !important; - } - - - - .cbi-map-descr { - color: #ccc; - } - - .cbi-section { - background: none; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) - } - - .panel-title { - color: #ccc; - background-color: #333333; - border-bottom: 0px; - } - - div>table>tbody>tr:nth-of-type(2n), - div>.table>.tr:nth-of-type(2n) { - background-color: #252526; - } - - table>tbody>tr>td, - table>tfoot>tr>td, - table>thead>tr>td { - color: #ccc; - } - - fieldset>table>tbody>tr:nth-of-type(2n) { - background-color: #252526; - } - - table>tbody>tr>td, - table>tfoot>tr>td, - table>thead>tr>td { - border-top: 1px solid #252526; - } - - #swaptotal>div>div, - #swapfree>div>div, - #memfree>div>div, - #membuff>div>div, - #conns>div>div, - #memtotal>div>div { - background-color: #32325d !important; - } - - #swaptotal>div>div>div>small, - #swapfree>div>div>div>small, - #memfree>div>div>div>small, - #membuff>div>div>div>small, - #conns>div>div>div>small, - #memtotal>div>div>div>small { - - color: #ccc !important; - } - - .node-system-packages>.main .cbi-section-node:first-child .cbi-value-last { - line-height: 1.8em; - - div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] { - border: 1px solid #999999 !important; - background-color: transparent !important; - - div { - background-color: #32325d !important; - } - } - - } - - - table>tbody>tr>th, - table>tfoot>tr>th, - table>thead>tr>th { - - background-color: #252526; - border-bottom: black 1px solid !important; - } - - tr>td, - tr>th, - .tr>.td, - .tr>.th, - .cbi-section-table-row::before, - #cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { - border-top: 0; - } - - .cbi-rowstyle-2 { - background-color: #1e1e1e; - } - - .cbi-rowstyle-1 { - background-color: #252526; - } - - .cbi-section>h3:first-child, - .panel-title, - h3 { - color: #ccc; - border-bottom: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } - - h4 { - background-color: #1e1e1f; - } - - .cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - margin: 6px 0; - border: thin solid #999; - background: transparent; - border-radius: 0.2rem; - overflow: hidden; - - div { - background-color: #32325d !important; - } - } - - .cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - background-color: #1e1e1f; - } - - .cbi-button { - color: #ccc !important; - background-color: darkslateblue; - } - - .cbi-section-node { - background: none; - border-radius: 0 0 .375rem .375rem; - padding: 0rem; - } - - abbr { - color: #5e72e4; - - } - - div>table>tbody>tr:nth-of-type(2n), - div>.table>.tbody>.tr:nth-of-type(2n) { - background-color: #252526; - } - - #content_syslog { - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) - } - - #syslog { - color: #ccc; - background-color: #1e1e1e; - } - - #iwsvg, - #iwsvg2, - #bwsvg { - overflow: hidden; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - background-color: #1e1e1e !important; - } - - .tabs { - background-color: #252526; - } - - .tabs>li[class~="active"]>a { - color: #ccc; - } - - .tabs>li[class~="active"], - .tabs>li:hover { - border-bottom: 0.18751rem solid darkslateblue; - color: #ccc; - background-color: #181819; - } - - .cbi-tabmenu>li>a, - .tabs>li>a { - color: #ccc; - - &:hover { - color: #ccc; - } - } - - .cbi-tabmenu>li { - background: #2d2d2d; - } - - .cbi-tabmenu li[class~="cbi-tab"] a { - color: #ccc; - } - - .cbi-tabmenu>li:hover { - color: #ccc; - background: #2d2d2d; - } - - .cbi-tabmenu>li[class~="cbi-tab"] { - background-color: #181819; - } - - .cbi-tabcontainer>.cbi-value:nth-of-type(2n) { - background-color: #252526; - } - - .cbi-value-title { - color: #ccc; - } - - select, - input { - color: #ccc; - background-color: transparent !important; - border: 1px solid #252526; - box-shadow: none; - } - - select:not([multiple="multiple"]):focus, - input:focus { - border-color: darkslateblue !important; - outline: 0; - - } - - select { - background-color: #1e1e1e !important; - } - - #cbi-dropbear h2, - #cbi-dropbear .cbi-map-descr, - #cbi-dropbear .cbi-map-descr abbr, - #cbi-rc h2, - #cbi-rc .cbi-map-descr, - #cbi-distfeedconf h2, - #cbi-distfeedconf .cbi-map-descr, - #cbi-customfeedconf h2, - #cbi-customfeedconf .cbi-map-descr, - #cbi-download h2, - #cbi-filelist h2 { - color: #ccc !important; - } - - .cbi-value-field>ul>li .ifacebadge { - background-color: #3c3c3c; - } - - .cbi-section-descr { - color: #ccc; - } - - .cbi-input-textarea { - background-color: #1e1e1e; - color: #ccc; - } - - - - .cbi-section-remove:nth-of-type(2n), - .cbi-section-node:nth-of-type(2n) { - background-color: #1e1e1e; - } - - .node-system-packages>.main table tr td:nth-last-child(1) { - color: #ccc; - - } - - .cbi-section-node .cbi-value { - padding: 1rem 1rem 0.3rem 1rem; - } - - .ifacebox { - background-color: none; - border: 1px solid #1e1e1e; - } - - .ifacebox-head { - color: #666; - } - - .ifacebox-body { - background-color: #333; - } - - .zonebadge strong { - color: #333; - } - - .zonebadge>.ifacebadge { - background-color: #3c3c3c; - } - - div.cbi-value var, - td.cbi-value-field var { - color: #5e72e4; - } - - #diag-rc-output>pre { - color: #ccc; - background-color: #1e1e1e; - } - - .node-services-vssr .block { - background-color: #3c3c3c !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - } - - .node-services-vssr .block h4 { - color: #ccc !important; - } - - .node-services-vssr .status-bar { - color: #ccc; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - background-color: #1e1e1e; - } - - .node-services-vssr .cbi-section-table-row { - color: #ccc; - background-color: #3c3c3c !important; - box-shadow: 0 0 5px 0 rgba(0, 0, 0, .35) - } - - .node-services-vssr .cbi-section-table-row.fast { - background: darkslateblue !important; - color: #fff; - } - - .node-services-vssr .ssr-button { - color: #ccc; - - } - - .node-services-vssr .incon:nth-child(2) { - border-right: #1e1e1e 1px solid; - } - - #xhr_poll_status>.label.success { - color: #ccc !important; - - background-color: darkolivegreen !important; - } - - .notice { - background-color: darkslateblue !important; - } - - .cbi-input-find, - .cbi-input-save, - .cbi-button-add, - .cbi-button-save, - .cbi-button-find, - .cbi-input-reload, - .cbi-button-reload { - color: #fff !important; - background-color: darkseagreen !important; - border-color: darkseagreen !important; - } - - .cbi-button-reset, - .cbi-input-remove { - color: #fff !important; - background-color: darkorange !important; - border-color: darkorange !important; - } - - .cbi-page-actions .cbi-button-apply, - .cbi-section-actions .cbi-button-edit, - .cbi-button-edit.important, - .cbi-button-apply.important, - .cbi-button-reload.important, - .cbi-button-action.important { - border: 1px darkslateblue solid !important; - } - - - - fieldset[id^="cbi-apply-"] { - background-color: #333333; - } - - #detail-bubble>div { - border: 1px solid #ccc; - border-radius: 2px; - padding: 5px; - background: #252525; - } - - .ifacebox-head.active { - background-color: #32325d !important; - } - - header .fill .status span[data-style="active"] { - color: #ccc !important; - background-color: darkolivegreen !important; - } - - #cbi-wireless .td, - #cbi-network .tr:first-child>.td, - .table[width="100%"]>.tr:first-child>.td, - [data-page="admin-network-diagnostics"] .tr>.td, - .tr.table-titles>.th, - .tr.cbi-section-table-titles>.th { - background-color: #252526; - border-bottom: black 1px solid !important; - - } - - .network-status-table .ifacebox-body .ifacebadge { - background-color: #252526; - border-bottom: 0; - box-shadow: none; - } - - td>.ifacebadge, - .td>.ifacebadge { - - background-color: darkslateblue; - border: 0; - } - - .btn.danger, - .cbi-section-remove>.cbi-button, - .cbi-button-remove, - .cbi-button-reset, - .cbi-button-negative, - .cbi-button[value="Stop"], - .cbi-button[value="Kill"], - .cbi-button[onclick="reboot(this)"], - .cbi-button-neutral[value="Restart"] { - border: thin solid darkorange !important; - background-color: darkorange !important; - } - - .cbi-section, - .cbi-section-error, - #iptables, - .Firewall form, - #cbi-network>.cbi-section-node, - #cbi-wireless>.cbi-section-node, - #cbi-wireless>#wifi_assoclist_table, - [data-tab-title], - [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), - [data-page="admin-system-opkg"] #maincontent>.container { - background: #1e1e1e !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - } - - div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - background: transparent !important; - } - - [data-page="admin-system-admin"] .cbi-map h2, - [data-page="admin-system-admin-password"] .cbi-map h2, - [data-page="admin-system-admin"] .cbi-map .cbi-map-descr, - [data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - color: #ccc; - } - - [data-page="admin-system-flash"] { - .modal { - label>input[type="checkbox"] { - top: -0.35rem; - } - - .btn { - white-space: normal !important; - background-color: darkseagreen; - } - - .alert-message { - background-color: transparent !important; - } - - .danger { - border: thin solid darkorange !important; - background-color: darkorange !important; - } - } - } - - .cbi-value input[type="password"]+.cbi-button-neutral { - background-color: darkslateblue !important; - } - - .btn, - button, - select, - input, - .cbi-dropdown { - border: 1px solid #3c3c3c !important; - } - - - .cbi-dropdown .preview { - color: #ccc; - } - - .cbi-section-table-row { - background-color: #1e1e1e !important; - } - - .modal { - background-color: #1e1e1e; - } - - .cbi-button-positive { - color: #fff !important; - background-color: darkseagreen !important; - } - - [data-page="admin-system-flash"] legend { - color: #ccc; - } - - .logout:before { - color: #adb5bd !important; - } - - .cbi-dropdown[open] { - border-color: darkslateblue !important; - } - - .cbi-dropdown[open]>ul.dropdown { - background: #252526 !important; - color: #ccc !important; - box-shadow: none; - border: 1px solid #3c3c3c !important; - - - } - - .cbi-dropdown[open]>ul.dropdown li { - color: #ccc; - border-bottom: 1px solid #3c3c3c !important; - } - - .cbi-dropdown[open]>ul.dropdown>li[selected] { - background-color: darkslateblue !important; - border-bottom: 1px solid #3c3c3c !important; - } - - .cbi-dropdown[open]>ul.dropdown>li.focus { - background: darkslateblue; - outline: none; - } - - .ifacebadge { - background-color: #333333; - } - - .cbi-dynlist>.item>span { - border: 1px solid #3c3c3c !important; - } - - .cbi-page-actions .cbi-button-apply, - .cbi-section-actions .cbi-button-edit, - .cbi-button-edit, - .cbi-button-apply, - .cbi-button-reload, - .cbi-button-action, - .cbi-button[value="Submit"], - .cbi-button[value="Upload"], - .cbi-button[value$="Apply"], - .cbi-button[onclick="addKey(event)"] { - background: darkslateblue !important; - } - - .btn.primary, - .cbi-page-actions .cbi-button-save, - .cbi-page-actions .cbi-button-apply+.cbi-button-save, - .cbi-button-add, - .cbi-button-save, - .cbi-button-positive, - .cbi-button-link, - .cbi-button[value="Enable"], - .cbi-button[value="Scan"], - .cbi-button[value^="Back"], - .cbi-button-neutral[onclick="handleConfig(event)"] { - background: darkslateblue !important; - } - - [data-page="admin-system-opkg"] h2 { - - color: #ccc !important; - } - - @supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) { - .login-page .login-container .login-form { - -webkit-backdrop-filter: blur(var(--blur-radius-dark)); - backdrop-filter: blur(var(--blur-radius-dark)); - background-color: rgba(0, 0, 0, var(--blur-opacity-dark)); - - } - } -} - -@media (prefers-color-scheme: dark) and (max-width: 480px) { - .node-status-iptables>.main div>.cbi-map>form { - background-color: #1e1e1e; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - } - - -} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/dark.less b/luci-theme-argon/htdocs/luci-static/argon/less/dark.less index c1285dd4a..8143723e5 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/less/dark.less +++ b/luci-theme-argon/htdocs/luci-static/argon/less/dark.less @@ -1,3 +1,4 @@ +// compress: false , sourceMap: false /** * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template * @@ -24,7 +25,7 @@ * Login background * https://unsplash.com/ * - * Licensed to the public under the Apache License 2.0 + * Licensed to the public under the Apache License 2.0 */ body { @@ -61,11 +62,12 @@ body { } .cbi-button-apply { - background-image: linear-gradient(-135deg, #6c61ab 0%, #594ca9 100%); + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; &:hover, &:focus { - background-image: linear-gradient(-135deg, rgb(85, 76, 138) 0%, rgb(72, 61, 139) 100%); + opacity: 0.9; } } } @@ -113,7 +115,8 @@ header::after { } .menu.active { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; color: #cccccc !important; a::after { @@ -128,7 +131,8 @@ header::after { } a:hover { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; color: #cccccc !important; } } @@ -163,7 +167,8 @@ h3 { a:-webkit-any-link { color: -webkit-link; cursor: pointer; - color: darkslateblue; + color: #483d8b; + color: var(--dark-primary); } @@ -175,8 +180,10 @@ input:-webkit-autofill { .cbi-button-apply, .cbi-button-edit { color: #fff !important; - background-color: darkslateblue !important; - border-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; } @@ -316,7 +323,8 @@ h4 { .cbi-button { color: #ccc !important; - background-color: darkslateblue; + background-color: #483d8b; + background-color: var(--dark-primary); } .cbi-section-node { @@ -361,7 +369,8 @@ div>.table>.tbody>.tr:nth-of-type(2n) { .tabs>li[class~="active"], .tabs>li:hover { - border-bottom: 0.18751rem solid darkslateblue; + border-bottom: 0.18751rem solid #483d8b; + border-bottom: 0.18751rem solid var(--dark-primary); color: #ccc; background-color: #181819; } @@ -410,7 +419,8 @@ input { select:not([multiple="multiple"]):focus, input:focus { - border-color: darkslateblue !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; outline: 0; } @@ -515,7 +525,8 @@ td.cbi-value-field var { } .node-services-vssr .cbi-section-table-row.fast { - background: darkslateblue !important; + background: #483d8b !important; + background: var(--dark-primary) !important; color: #fff; } @@ -535,7 +546,8 @@ td.cbi-value-field var { } .notice { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; } .cbi-input-find, @@ -563,7 +575,8 @@ td.cbi-value-field var { .cbi-button-apply.important, .cbi-button-reload.important, .cbi-button-action.important { - border: 1px darkslateblue solid !important; + border: 1px #483d8b solid !important; + border: 1px var(--dark-primary) solid !important; } .btn[value="Dismiss"], @@ -575,8 +588,8 @@ td.cbi-value-field var { .cbi-button-neutral[value="Disable"] { font-weight: normal; color: #fff; - border: thin solid darkorange!important; - background-color: darkorange!important; + border: thin solid darkorange !important; + background-color: darkorange !important; } fieldset[id^="cbi-apply-"] { @@ -619,7 +632,8 @@ header .fill .status span[data-style="active"] { td>.ifacebadge, .td>.ifacebadge { - background-color: darkslateblue; + background-color: #483d8b; + background-color: var(--dark-primary); border: 0; } @@ -684,7 +698,8 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { } .cbi-value input[type="password"]+.cbi-button-neutral { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; } .btn, @@ -722,7 +737,8 @@ input, } .cbi-dropdown[open] { - border-color: darkslateblue !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; } .cbi-dropdown[open]>ul.dropdown { @@ -740,12 +756,14 @@ input, } .cbi-dropdown[open]>ul.dropdown>li[selected] { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; border-bottom: 1px solid #3c3c3c !important; } .cbi-dropdown[open]>ul.dropdown>li.focus { - background: darkslateblue; + background: #483d8b; + background: var(--dark-primary); outline: none; } @@ -767,7 +785,8 @@ input, .cbi-button[value="Upload"], .cbi-button[value$="Apply"], .cbi-button[onclick="addKey(event)"] { - background: darkslateblue !important; + background: #483d8b !important; + background: var(--dark-primary) !important; } .btn.primary, @@ -781,7 +800,8 @@ input, .cbi-button[value="Scan"], .cbi-button[value^="Back"], .cbi-button-neutral[onclick="handleConfig(event)"] { - background: darkslateblue; + background: #483d8b; + background: var(--dark-primary); } [data-page="admin-system-opkg"] h2 { @@ -805,4 +825,4 @@ input, } -} \ No newline at end of file +} diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer.htm b/luci-theme-argon/luasrc/view/themes/argon/footer.htm index cdb46bb85..a4e1df4b2 100644 --- a/luci-theme-argon/luasrc/view/themes/argon/footer.htm +++ b/luci-theme-argon/luasrc/view/themes/argon/footer.htm @@ -7,13 +7,13 @@ Have a bug? Please create an issue here on GitHub! https://github.com/jerrykuku/luci-theme-argon/issues - luci-theme-material: + luci-theme-material: Copyright 2015 Lutty Yang - - Agron Theme - https://demos.creative-tim.com/argon-dashboard/index.html - Licensed to the public under the Apache License 2.0 + Agron Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 -%> <% local ver = require "luci.version" %> @@ -43,4 +43,4 @@ - \ No newline at end of file + diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm new file mode 100644 index 000000000..a4e1df4b2 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm @@ -0,0 +1,46 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Agron Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% local ver = require "luci.version" %> +

    52_`cE(zZMEpNgo`EY*4G)I09>a1 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 ?@Ps4J#L1b@yTXJK07_F;-CIu>*o89f zLyi=bkPUxL^;+L)%-2 zwb8Zv!u07=+9GW!u6>FXcel2iP9CD{D@0%(a{ zC$Ukc-Cc2O*JbmU15M`ETKJ*$tmHN(x1!gzky$OoeEpQ>ha7r8A~hKWloNBTzMuVXJrFUtcX zT!c+tIf+|alUS86=StjLD?R#Kfj(#FnCzZZxg7uMa<@*Q+Bw)r@5`SN6ZkKD%j9q-VUT#`+F4rwiRh3&|WS}9d z^$+Ku6!e0~WblY~{l`h$kcB8fI*D8g9oQG(GiA4zNO$M!l1I5^#LH6imgvH@zLX}I zSIqKNyO@;*DT0Volnw0^a}#mIyNk%}!mbD(g`tq)YvBWlWrn5}53EWL9A(RqjH{cQ zMb{hsrV5r{L>cz?MEdkxK5qE_ejU;rOS7<;g<+)H)p8dB+#AdBO~no7`3&K3EEhuL z;zqc;EFTFL>9Gg)csQoz;-wP3bI8PP*2D0(@t4%80QQTxAWayxwdX|Ir<}(-+%vHE& z=!pcY-8by(r$blUFBEydN-lnip7)jQJGhj)JM&L5>zn^Rd+I+;g9$>~LObpsJ5K(5 z{UDl0D~coFQEIfCyX0(W(~+n)#Kyu%DtzRy|0-wMJQxc~G!S%&6J8y@hzH{rjdJ0} zawBE%ql~qk+r<4g?Y-4&Qo(yOBdU{uO31W&bRZ*IH+YmWVGT8Tg^Y$|%V+TFI9 zhH1lA13tKi12#NZU!ALV1q3MTElnUp?3CM+FEJ6czLM$3#2kAT_;#&?^3U9^WeFPO zl~S>N-jqOOA;>xTf&A`wYU>lJ%YHP##v*8c)WtfdndDMi=eGxzYjDLaCrR%~L2QzQ zS2PCl(GN>PP1S>mW&~tVRSkg~7J3@0C{NAbaeuzv)2(C@?*6U+$BmtR3UH4f(@G9b z@Xx7JzEjA~W$XLbMn?Kv7Q7FYe)C^8!68B&+bBC*lz|Iq~koW6ZXcCzt^d%g^ zzN^d}op~tNk_QzVNQA>z8{O7PWT&Bk3S;@@;V#SwLp{uG6f^WXr}w8O%UN(ATy@)} z-v#|))P?3W5+J-+|4l_iMZZ}Cc5(Tk%>8BC1%va42BpU)lyvXAP7%=q4)y;WEV=aC3y*7!(WX8Z(z`!7l9~DRiM=q@7!r&{aTDsYSFh0k-ZIX2j zKNQ0S!Z$VnvfRy~VQuX`3gB+uCW#A=Ie30lCdgBhRjSvuFWKMCx+j?flBqo)UfR1cmMo=|5N$jArB-27yd{+Hmh39 zxfb&Gs@D*9sEeg*rKBIOd(kkjSmmjMg8djkp=S(VsTy2*u(Q}YkaOez#1-7+?dl&D zI-JSp4Fh6p@`gzPGzo0i))6xZD7(8txc==wn!U*!cKAB%iI|n$4X~Z&>w*s~e+wQ` z1$UkKykuB7C}J$Weqw%_|C>y}T;in^eLl%XuCVmZ@tgms|F7Tw&LW8HdfJbdso12n zLy`S!JN-jgv%>-Fp7Lba&!g!SA+(ARHtptYd{caU0=IK-s>KHq6fwcdL-?Ci-cWrs zRyhLhMN0il>!uZOO3uGfS%+shp}Cg&Q*@O(W|MbU`Y*^7vq?I>Lj%t>)N>t1xs>8R z|MNNe{3g>DearCr+@bKa<_((**|js_87C*_YOHS($jwNgKR!wLg6VGFh;mVAe3B1B zqpAPz)&IPIb^Ln$Zs!|@|CMd~MI{qv`{@5$KO{XtkJ8m}ji{cg>})-`JM&MFtp5u? z+y6W)dZ-HRl&2~WhQI6Y=%g{-yluSLmm9OP^j3DtCHaVBZ-dy(CJ~{8+Xwn#F+J1k zEGMQTh|~3trrgeOPh#FHnlf9toRi8}Nqv0!^@{aw8%$faA{QMVBdau##j?lMz~z*<-=!mgCo@jOy2wiDl8BsxB~BH1?*Y6UbC#_>+Lij3A%P zydvB1pGwF|_&omAR#xQgwF$o5EUZY67CBlv;&^amx=2ZG-c~BUkAR!h%f(IQvZEYlTaaGdM;J2b`q0 znrY|zB80buhPoZB=v*n4;#2#rI7WVx$*n%0m_f!=!gC3a=r5GUE}yThxFJWl;vMJP zr46lUpa>Wc>*b!~SG8SXT_6g0+z$}PnC-{JbPJ0H1k^O$78xQG zV5i@N6@}WuvS%HP&!m*tE zL;Kb|+MJWywOpg1;RtwQLOImHcr_hrL@q92#St37;4+Z+n~ZG7vR>TGA&3v@(}jpJ zdM%-XnW+o#FqP`%WXUL&@8h82Eh6zUP#D_AeDRICW6d4tk@t6eCj3x5&>ZAsb+}Gk zV%M{b#>V)?*LlrkFs>1MJ`ms$^y*Ve3S4(1$MQlOV9)ge#hrUbxH7lHWd%&y9!Sh# zs$Jl(jhuvMm$9EH%B<{M;~txK5LxL)T!Mkjna}mmbyqo|w`>#66XW%)t4NS}@p2xx z4`l!HsU0tmB^J&MnYC$se(e^(Lgp#W>>+WWy1~bj**;bMdFL9}?!960aZx@$dkE(q zmN&V6Dk1(fYGLd5VFA5-|ms(tdH$ zvc7t~v*qyeuZBo3RA!_syy_*ubH`?6Rmbn3ju!NrHwDE`P z--V&Ch5huwUT`}EE%@aZ{qH;@{%iLRk&El6K1@`x^XGK=1&G&F-zdNSef*&oxbhmk zNBxAY?VaQv!wdNy(I-m&<%A%eFnj2|19C!-kWwcx97!t(qfZ?VN{=-IpS;R=Ke?k< zd{{i;C7A1vq?iql_Ndf&GW0c4#|Y$q7#|~+7si_>5SHB^^Gj7PdL)Kxw{TKrg}4GMywII?giZQJ(8p8u z=jqe2P5gJ%BOVS4-Y=5b)^m+{*jqt2CX6L)jR#D0mt~gSuPRuPOR#C^O$vI^D{D6e z?W`~r5-P)?Lanyn5jHdF1~zTFf<@()mJ9nC@b@en1K!H*zMq=g2IDq%7tGvA5_@Uj z3f%6~*0jOq-Cg>vcmVm564NHcXiHO1vDR7Va$2RR^bLJ1&RB0w)IQ{8@T9r;# zC7D^wsp<7qoZB2m{fo12iL z-+|NB(v>*sr>?^ITX)9_qu({!Vl*me>%yEI@4AW!7}dC&mfeg!PgPh=^0btJn%r0f zI-Go(Cr!+c*@)FrY11C8GQM%TuM-yuNK~c6wIGmZ_83;eg&VRZ0WNV zni;@WNP%1luH++b)U}#P&71brk10KJY{wrni?RuSa+nKQF0$uAMKak_(pQDdk@uDM z6fQ7j2XrHCPn`wuHT=@e{Uu)@qNFhUY7N&rduo~V3i$_7ZFk)*?pG7$TT$^gJuKOc zh~~tMgz{J7Z|*OpYzHD z!~dF#qkKXE`)kJf!NNqCzT2QmiiM4y(f!SMp!!MIn?B!pMhGG*(6|#|)!-$la0Uk% z#LgDl&})`U`Ix8jNYzIw8jM-o9M!s6ms;icoV%-D2-`4KSL0GPtw_QP>Fy3&R+to9 z2I*LoJ5VuCzl~v#vNYb32CbOG=jFx$}cUjYd)`UTrb^JZSYkwqVSQv6OB*M$Ro-!>&}Pb&JW!wxw); z8>L@j8uXmLr+YC5K@)Z3$4oK@@Ghrvk*0I&AsN}SXr9scXmU!yZz#Qu(PNYAR$d~$ z*Ag+`ovs+B4tn3bLjJ=2CR^3*H7b6G{+WLay*B^9i9FrOQjlvm+kP|}iTar>6?g5T z2KVyBG0*5={fUE(%hBM~!5h*jx)K@Fqy|}Tmm^GDL6yBVisx>nv&RHrWX-mS^yE#C zI16sD40P_;HVclg(eT3@B=y|tTk6VY^c&LMZwmW|e;w)UoJosQA$%HXT(LV}a9_MZ zNna!Lqr)?($s5^hQapiJq91Tw^kj0q0NI$iq77&vEful5FNzc*vu$LvtZ&JF8HvnI zP$`KXGTmR$xpRLN!@XE}^Xty$q-~#JHTd{WMmb)zRkPjGy%v5g+UV=%o*LW;Rje#e zKe#Bamvba_R#YUHs{I+mlJU+=v8&fQCe*f`%Ck>jsj4w4OFa}~LEWL-S`xE1;#2!EIN5O8N@s(S_pXOv~lo`sk%Jyu2%(r zw}7z9Qah@k)V7uU;W9{Q#(%J$UOK%lE4aIK^von9Yv4~ku{eDLW--U>f|=pwJX*8^ zah`>)U-|u!5d&|g5*Tib0UG%Zx1_dVfa^@|K~>ZxNP)b%rk493biDuw0hVW%@2mcH zGyd1-t_xadhzvU?I8CAw3a!GiP-tSCbF( zjnAFbUkLKN_{FX9Zda|Fz@w>eQQT)nvD;yy5Nlc5o^bc9=tCXyIolxb6P|79Y+o%40CWO;8p{GX$LdyPJ1havHc3V)1ZxQ4h9*hB z^=YuHZc29oAS>;?am37!O4o_S@{D(lK#9!0#;{iX+Ll$U214SKMD;L7ZFUF-@0a;Q z%EHFv!_TIg>5MNzDQ+{FPJz$=?EOdt{3vD*SOW{+&RWt<4Vu}kFHc?hx<{c*9B}4n%WPDMdAj$=r<;;yK1vb8kW=k1XNO_Q}0mZ&bZ6e zXEvr80@=oI&5P4wAZkbxuy?L~cij=HiqnM7DfBue*|k4AUOu?!+W&Z??tjw9lHQeG z-uEKW$7b%lwWAi&K1ynPoMiIk)xhWf=)+`WkN?}e--OmDI_$YVkA!mtQud6ZofpIf zl;n=OXa{-<+}%7>7LKX^25h%g!aGgw+0^c=c4U$ukP__+Qn^BfMviWK%DL^IahMTS z*f}nOwkGgYa&;OcXw|H&ORu5aOtD?*mg5cLQ$5yVPk7icG`<|KL}0`Kdg={6S6Mu7X$qW+_lYeQwUyZvfSgpGPUsVbP#ALN$k#z$4-2lFs@&zPgl9HpL~l81$idQJ zX#`tIsPGmKdE~sLPs2pG`@{MMLUgT>wK`Dd?#)nBq9C$#BS-lPBiE?zmrKI_89}qc z*5OlX6nC7>aEtlQcid2{$V zyCj3xPlam#fZ8oa6`F5z8G-gE@xwntq0v z+zCoEX6~vyQ}!Eko=bOYEZzWL=Aqbr-!m--o=km{yZmC)(H00G45m3PV0j zq8+~2oOn4{BW%No6Q$Zu{EYT;ZFny9;;M7kVAI6&M;Em#y&`Az>Qa-evqCd<>>MLy zl`Qv|Wgcur)4T15-Zt;7KGffJcbY(NjT8mT?yije!50qIb$0|jF+}6D-JS>ca?%gs6N$BgMgIr#?lr_F4y1tT1 z=VyU&57`G`!!n!2ITv&ygPf9Bdxm+HMXwb`0$RF!H|@eaYU@v@P*d!b&zhCqU8aDgQ6QgOz6PFR z>noiOG3HnE1{mgw04zQt^4o<}y*-5~5(a zGm-4h-ImwMYX0*9(4^8s)5i%cqAIaZ9jnAp|D5h(`bRd^=z6Q7;+nV}xAQ@Lo|}r@ zoyA)g7Sg}CFs8ju&OO6~C1#CuRX=5$(GPYS;=>WUf`&G^I7WazP7Zdjr9jzJIRf^} zxXMD_S)(c${(ygvWs1Zq@judzq6EgbW%q+EMki_+OFh@>PK|^k1~BMWH;XQnhE=wi zdTDE{)_L<~?k5Dmb}xiA0GO&3$oX_{NqKIuJiw2m#JVqH`zMo#NR>6Tu{`;;Nil4B z=IWX2>3ZGiz1f+CB0NE9dFVKQS4_ov=*H1OpXf?*OjqgJV{Ng2jAZ{(dXUDDWp`)r zW=;ds%MnvDXm0%Dn|zPI$^M#YzwT;#cynh-jG4Y|pZ~Fj?l0!gj357AnFVmUkoOnM zn=r{)s}#ZDbBy%{B?8nMF9~=73q2iOx-_|`FPfxQ%a?CZ z{HhjjnXul8SMQ8>?INI_kD;an&vI27Upw4jW!yj9u*d$Y5kvAs2DX(OAxfgsn(vp2 z_FGWE{|x_NGlLs>#bp~1XRT@ZOJE<_*GWbYlD~_0`%viJ)e00)4is zUl20Ks#K@e3F!AxTMcUcMSymv-#?4b-CVs8-!Ds;*@$&y?}%bBh`u5{@(y3nWtM?Y z+QYoRBX1flo^Wh|)<6l+88b$!0$U5(`2FKXK}nvhB9j$n?Wl*xGK-OqUED@PX3jjY zEh^0RSGLjyk7|r`S>`&-khTUmB>Euq?sk()kbUq-41X*_ValN1M_Ud6N`tx{-jB%Z zW+ofhg{UMh6xa*rTa2Yri3;Amw$1d^cabO8qFdjvSQ;|hBxupjOQ08M3y9-XHaRGn z;6KBB5HP#Yg}{YB#~+$UnVmMhkZp%gAue0>14>?4`7p*>i`%jY;^|q+y$1yhs{9;s z)fjl6`==?GdIqXntY&S)zRP^;cJyP-_5%3>+S2&d}agD8CX%(a;cD7QX? zhFlhmwD`vcYAF=QGQdO!%JoY}nyO)Ym3;!;KdpUhw*#t=RM1Q6XBE0X$K#T>rrHGwFzO_h486{5wYyGBLb0~F;V0QG z^VKe*_k3>bXt?Ir+v~?!l&B@S+0Zk?@|aDwr+8GPpOjqdX@ zKzarU3$+Q_yC)7$*p-KE0W5tc24gBYRAH=k?rslXeLXl`8dqrQQMu?AY%t`XsHB^8 zHY)iHH|fcKzE&@gvfQj~!qWwskMI{J03mRh_t9PQ-p01BDIIy3*>2P}OvD*e0)=#>+sa>6eSR&UU3E(T&Nq!k*&GlNYF@Teb4NwEPd;FEP-cpO0Ra3J)Ki_J;-p8Dn0 z+|!IF=py<1$;@T6hLS1ViVrV5`=?yRC`)urT1pLxP-^z$uxt%OJ_it=@kg79Sc%~|XB$4e44^O-Wd7S=BT zi~16!-HFv40(aJd#>yslHwDmPvrO2KC2G!Dg@^XL982w@myXh|bUEB{s-#u)y=S4$30ovTIUW znE>I=F8MT{QpBqcO-(TwV3z0MH<6Zpp63oqkN zZJKfJ_YDd~?m*ZtvML^SK!s9l9-my z25(Hc%im`mc&{?pG+2D_qcv7feMt`m4EZMJ9(fplrP5V6v%gBLBmRX1L|bXgI;*#o z<0rT4AC-+WG;$-;)#aWoJu%&u9d7z5fU7{Os&PLT`MlK;8&F-)?Qjs#s8cmjsfn-w zZ*HY4lrYo?Km-=#=QJC6Ef75_@Bj%L-Dg_^x1N@gKi2I=wz8bytjg6j77SZA@v#Oy zo;LL0?&y@#`j}OKLKwxDL4b9lw*ZyQiba+=8vOJmc2YvD>@}@R;?PIwBnHwbN}kCpGP-C|h%v)G&?nRyn+$(Goh%DtYc2J9)rE6`!V$sS`U zuzGd~5&elbU#99=wr(BdG7Y&%+$^1#vuPfl-1d#t&zRqy-3%aVYU>nr3Tn{{m`B{& z4gb1H-$DmJql?{@DdYS&C?WtE(0H$ztDaVRN9I^vYs+0?x!+}OS6eewPv|`>rgBPT z(?5eE)u3^c;p)C{vls9<%30^V9-EF3tx-vk=SaU zPfIb)xXf+Zg>&$3e$~<4G`CgBd#R&WZ18cw1dSY@LGrG@%~SD&6*uZ3+vFP;M@1j2 zby(YJy#5qyP|MzVshMbjP^9Ko=#HxXC6mPDJ6FhQN{xudt&Q8XK1h}(Bw{GCO&{DnmrJgZS(%G12!3_tnOFA(<*E^F5z!I6VejC;z^GO#DWCJC ziwK*EdRpsf@KkD71mmCy-e`V+@IT0!$u^wg>n>0m&N9%`IZr@U;htkU3NQ@2dk0A( z!9V1b8wSU>cPz7{O&5l(PVD;>oVmDRPMRPc$!Rb)Afz|cZ=Hk77S+)vb*An(a-#5( zejplIp|2&kna{=RN$G(QP)aEtf)N^0QtEbj9s&n|0nAR0seoM#Cb}we4BDBrKl)5OQDP4%4xK%j}6%A)5X&bIq>H_?)Wb9a?n%5Y6yy2HxatpsNI3= z?=YMR1(kZ)Y=gHx(YRDp#3f0p{8D2d)*q1#LK8)_Zl#F=u$N3Pkp@&^UtV++4nO*Y6_xD&EHfr!a z8i8KEgE&r2H)RASdOS2>hgHfL=czbv5K=jpxhV9?6rN}GeTR8x$77XUQ5rzE%zj7X zqD@lLX1_DHXsuv0z{V*w05&p>mWE1;v%6z%3pFO^1@F!bU}285(omri8m7UIXFi^* zqU6Eh239LW%M@DpWQK)X?J?y_!S(LNFj--s-_oSyDv5hK$DFxTNQb4%)WHUW!mJJs z&iZxb>$i&&rJWP{xhBm=WB2bhn>(Vk=iRJ4)=zz})9V`u?f_Piq0xt=>}Vuv#Q$Q( ziN}MJlMu|H0neLjKI?&92&M1VLorEBVLx+|9sd|bEid%H`q+I)M=8lA$vMg;sdVZg zT+%wO`7%+w1i&26{ne0pt2DkT$%UC?qWp1;F^BUs9YDR?Fj%P3498@<*gQp(!5-DygbKu%Aj1=RgN8S$)?rc^FqMFc2!Udz)}U z%Qh*;TO(BG$Ex+Htls-JQtpyBN^2m^G@IrL^u9%sr}A36$;=L zjR464_si2ZA5&^42f-$H{RmwQb9FfizZas!lG`YAfgE3I7*8}evhjEu{D7(6(*`g?!^7E`q94br;0CN?ZmiQvk6M?Eh-k7^^8I;OZmmB z;(gOkbCkEmYJc=x$XP_8`GTh6LX78vn4kCBJnMB=P4*_#8?f!(O2B*nYI|WU0G;F- zFVKy8_NwM~lx>DELQZ|!CiCmMR^}9n{D$d02&g>f>wQdo`p;{NKJGm^J9Zym*be)Q zwlCQwZ=?v_N;9vbcxu*?met&ArfC2pa#wt?|59P`Iopx4`aQXi1cy|8h>aZX4zx$T zbFhH{?@jnwVkyR1Hxc%%TnipD_hAMtLb$+Cyzff00;Kf@0QHNRAG%Y^`4!gv^ytIh zB-=N?d>cJ38hy-f>eWJz2zXjTpaDS65#1SUM5wlb4M1a&T|uc%2O62y^IYA@|5KT0 z!xMSOB97>3-`*S+CD*ekDJs3sIbwZ+idqw2@?$418{;NR=93ljLuXAt&aQQviy#x8 z^KXq2OdL$XwOMa!4Uy4Zp6~{-D(wo*+(Ou`jao~tKoilBBJQQ(zIY~tKVHb4_O4aa zd z4wa^7f}icws&YoTSFuSBc;ORi3Y~am?!=JGBz*N??d&zTLhE;3k<={d7fNyU zmg({S6zKtTeaPX-VNkuuTd(;K!c7_M7?ybKvqV9mzMv$l6_?~UEmQv2s<);zMP>s? zp>_k>KfMWOk5}p;B{RkUXp008UgBIe zJ6T7jNm_;*- z=c9qE1F|p9Vf1A$nSaGTasQiUuz2BFd8l@Wf$ZhDIWD+vPdQRERYF3AYlrO0M&S>C zo-rw{?kNlTfp$Krh*UqGJ2GiddHR7VM6k&*W=JL!f^n-@we%!a;_^z~#G9!VvKK5bm<`P6XCVq*CwqBROU zo&qyjihJjZuRwDO^$Ri4gi}2~0G}xjc+EnAVVM=cV+ts_^iyYrZP08kDMX|D$w;-u zI{67u2%#f+r7V70SOS!$A-~}?=1Q|u-f>R^%-U!agG|RjYTS`wml`V4s_mxd?(f#& z20#GF?E}4$nd{C&16JIeE}M4@wCVlWCa>bHDbwn# zSE0ve45jI}7`lWN2C~053+n)jajrorpbyyju|Whykr^{1N~lr+iagnde*N|pDaqDQ z3Nc94iTh%fUyA!^u|<-(L6q)DHL!lmS!DC6gQ+vo#q%~L-FFMJ)5|uhm~983O#^Y_gbIo=dIg71bSC9b%nGwEjXVfF%R3h>5m!8E_~Wm1SHYd zW_M-{3^98px|)Ca*Gz1dXr)>P)81}}%M|9f;E^_*Fx{shhU;U4A>g`fpTN04_hRRK zcZ*G36UM-UAOn{EiI5H-WeYQyLr-*;Z_FtdKgEabfp11!!<`g-A&<>g@eW;{E4pR4 zZ)0ofGPsEm7`(p8EPJcu3dqI$zkXi1FVlt@$b%^lx=bn5@U z-dDnpIeEg#(rB0&qp#y1W`=@Ea?2P4SZKrE`pOW*2FV*1=axv>9iV4_aOkx{oMGEW zXQ7p{N%kNgG-Gu+hnnJEzj3u`?gfS9>dByKCYyQ5U8mnGXUD~%honTnTqUU?b1~&P z2PEwRYe2dh_+xe>g_~u{P9v8{-j(5xZc1@8b%`ilH7aRG{HB2!PQK?8*rvdm@GV9- z%LI|U6$ot+81~mNUGKZ=l;IyJTj<;Bz4e<+Mjg{gZlaYJ2diPu1HDoS`jLlQxI|$k z#ZiH7md$e6#+b*G8>fmonW)zhSOmOnT@a~vGa=CN(2X1#2q zR;tiCtvQ!LZ9>z2ll@R%C+#icql*!HGt8UIBAn)u?6N$T7>DKhwYQ`EKB;ulW2+=F zUr8zW3U-ytQQR~fxCS1L`{l73hrLY{cG_5llt>I=`;u6x8V(o&RY3BLqB{fob@2St z)E^@4`D$g+3yrTF9GSiczdqwHUO0a?Zgf={FtY-rUG7VO2Uhwjy~7V@Sa2-&k<3S4 zJ43NRy_2fnWNfc+eC!@(aBmBy7&!W9Ao!;*vK(KPYMNi@VGEViNq68nidaK? z>a+Wsj2oP*|C?-N6#a8T#KDt_12<-le@wFSWl?pWZjdAtCFvnh1U-=hymj8 za-6A^F$N?YE2O^eH;)VrBOTC)bU-5q&D&dRA$-;@qa^Il>q_TpG=oOK=Ar?|Z?Z#E zTiK)DmG$9Y?vhRE@3_&U>KGl(VA!k2ml_!l9>qzDh@Z;y0POeTNob$$W$vo?Sq;=Fy)G$s74# z=HOp$_kkp>dDvo&hOu0{KzV465k1V1`$f`F23U|3ez>mPz24!&d(>~&w&D(G)4G-Z z&XDJYuivP;qC8M$+woU2a&JAvCm!@D>VXF`s~o=0@%&z`a;zm&1aqiMgKATfQrNg) z!|QUIyeSSlkDueqE5C;LenR(!(pME~8dvu(#|2xomat;GKC7pr!y@sZ$7qUEao}}^ zV1}p$6FsGt+1KM@wKF~GYm$Uz>~4NmOMy$gzV|PbPznd{3*SSmdg#;ELxSaRvLgFE zta4NciS@E@yR#YTQa(d@6qNjq94Mt%*RYEvJuccKi?7jYv%(q&L)xEzlfgyCr-84l zPLo|QagP~-lc}`3D=`Zc+jR01L_aNe-`#Qw;*>>HYmTmd{Z{4)_ssZnoOuIoXlPVuXfzlOEh7$ZI@=tAOPNn!?A*vP`?v{{^LSJ6-PSXi|n>g+8Rv*FQ*Mk7NeCM;D znd0%D()k76|Cj;(rSyLdd#0ZKg0aS9_9)tTcMJ3@dkvZuoJg3o0Ol7gOs^D(dgaN% zOZ5!(UV2k%-QitsLW9FjhjayQ>Q84h(+N_GJdbF^DzhPrP|5O)_WQ0a$k+_TNYZIf zxmlAJ(E9Ctv~_cZAjQI`=Ywx28mR}{x*$V{&e9wgfr@P260?tMBiu7h?Dme`?rOJD zY?Tq{M;(miLI#6i!~m6^rYFh*Z~ z7NK*2^&M6QzLV&(Qc}u0bqV<;!QQaQ zL74^PwP1V<>ijUh*s#j40~Uj(b6Kz1^TZ6$mSH{;T)uGMH6 z-G2hen^?<@#b!v(^uADe^B-Y_YsnnJyIevTP3OGfUMCH-GW>AwT6@|Yj}I>chgxS$ za`oX(<1WF5AYEqG>apg|c*^mt{LUbJB3t4x!lDr1mKN)=o)6b`2mw-#V&JQg^KI*(Xo3q1)?ZQB8g>u9laeRR zf>!=0+cJr}smsc{k{W0&H|G1ylNpA{a2!adNOl$xJRM;dRixnDNQK0h9{_}Djnh>~ ze#sSDCd1mWbbej2df=t$COdeVQImmqjt?{SzC1||>~AS`O*c$g1wEfE9%Kh0RUemHo0f@O!K+4vKa2^VYYj0%}!~u~+f-AGErq;YK8Om+BrV8c6fs;U99uL$j_6p>pdd-EZG|;)JQBW~C@=mxaUlA<$y3ksy;iem zEb1@ZUWs6;0I$0wuw`4C7u}h`O}?GzVo|7oHX`P?j+{LGT}OuP}rzv)6>)FTJ;$eR-MTKlV@$F`_3~ z+E6GBPEdWTwRMA|&~KhDi;lAMBwzPaIfARd(hMx}DY2enNvzLJE<5^|)#SK_?`#)O zKGdxp@RM~3Z{Q1@P=ryJoB7szs>AO9ljvOiv$7+9xWz&q;w1IL>u7i$O4r27MLCYm zeIzg@ST7VPht4qNoJia?9aN~fNo|+==&s1J{Ienj0MPled@BLDs5R+-4w_2wrAkhC zDBi+OaZ?!=>OJD9GvE%ML_n!Q%e&P6wu?^!Q;nE5;`)xNgUO3!}e3p#NCu8){S@-oD>HFr0 zW0y<*YZZTU;qC=|*ZdXda^Cgiu@%SLq;!gZ*l^4J%cS%7jsL=i`=2C9WhJS_3Kn|+ zcJ2ih9(vESBb#1Zc5jcYbi2nw>pjLG6l|9O5&!k#@eKeshf`>ydr2{3*oaGyg%k~&l#e9mG(s-Y+k6QkS^`)MHj0x9SYgsgN zHL?_6Su4!HDM@ zM|5I`iXkHQP+58iQ=W`4@eywg?^;tiL;91Msy6R3@%t@dFP(a&A(I0SRXAPqdEdUK z&js1he8n|Aj%aG1RdQ_ba@YJ3bCYE5Hq{bkTIW4D+Ec=*(_s5lGwleQm})ZalruE` z^h|sBp5Udjxkv-gl0lr0v2ZaYic4-+k=B(_IQR$by;_AddB%N2WQCQHp<2CjssS_z zb_|kJ!v|W0N8Nk#_q#<#=8-3DzBTz%(FDriTQ@%MC0mj*ZGAw^)Oo3q5&g_mH zkMUtQ1=SVh=m<)cJ*s=3ASD>v;f@7Cn}KCx&eapeRsmE~tP@}x3%5h#&!w}mb^TF1 z2D_TgEdAqd=DL5CHB@G&jArfXPFG+Hhf-<$H$BB>-CVPce6*!CN5M=GiWni}dIav85`x(!OOd&Zy0WOJr-=4!l3BW~-v ze5&n2@qo0IO(m~68=M5En@D^0(4B!lY?OG`OMvYs`Zp*a4fqF-6>Fs4LFtDUvrTyd zjZ!8SvyP0p`-Skjcx$vtNR4UUHlCTf+E5=t{aNL9Bru7-m{43m7gV#X<;4csvn~4!P{!oHq zU@BqsS(0&#O0$HMbp>k(+}L?SOPAMl=a`3K!X-LOEult@Q{*}ik1n=S68jh9?WTyZ z31l5|PIa?fx7-+HSZac#Ff%XuoNn$@Kj9?%MJ)0G;HgJZzFLe4L&}8I7Qgm03-ulw z^*7s9br<0=^`QCz6Dscg^;+vv1deSANq+6ie|KRN{pxWHl zc2QbZX-k0?cUrW#6P&gb*CN4!l;9RTI5pfgI1~s0f)xS;r-k5F+@ZL;7HLn`K4 z*Z+?*?!M#x<1$9bocYH0=F6D&zVCeI^IYuGi0)*YP8P{@LW!iOjl3}81B-bAq5VjcX z&E=w8R~Q11vqQStI!GTXrYR6I2vMMen;u|l_OeM-4rdGjH29pNtTC3CS7U=}e`*vXE?TZOp2JM;GZ2av?1LKn`QxH3 zG^yMnlN~P$$*ldLzNT^W`RZ!I5dALV0fmz^>UikI!C`7+{Z^k*NosKO;95GD`4l^!J;_GG%E{A01g?xc34s;!V83KJK_UG-d3yYEeete%OONi@6ubT1)EPt!Y0R53WN{is zL^OVT?MTjMddQ2v^I3jQv5VsgcdaAu1)tc^AIK60XmWkFd|fSN5ixNxxmxj@mKE%m z*&9bKIk#YuNrArfv7;RCCZ_orU6?pASR*A5zAzsDTs2yq5gF)3e*YqnSjdz%&zgcn%L_iaB)RjRQ}9P&9j*K87y z3a&qyYH@5V_}N)woB+Z+PaxNC)K!$NkLpqGi;KDzw-nx9p)yqWUT^92?+zEwmY-*y zpQE{8AId^O%434prSe%x+;{hX#TU3`!^TDWHFU>Ay@3jSK7gwAfzJNED5tHW4k77> zb0vaj@q5^C`*9=RP}TJ>HL6Z-^Q(Wyi2OA+u%-Wm_OH9_;DhoNr~cs}PBYFRx8tj_ zrQLKml9jUqSzbw;szcp!xX^}4wKWgb+XiZWdIv(2N$7?WwyVY}yw+$~P%=tNV0t#U zt27cz;R;OwB!`umTXl!mdI~*G)ONpfsFC5SCLDR;jpB894>a}yd>rb zx={uZ8O+D+W&oz9>{4W(&~+rqW5@Z>DLpPTu7IVTz455wrkMw?^kH{p*({?dx8I<8 zS*RE&qzCZ%eaxCxIot32{a@R> zD$#PuG&<$*0)-^&q=YeLsRRctcwFMzko7O-J9E3VMA5IlW*Ak5h&{Kq(BN3o2y2iA z!=4&=5hh}l{lbB<@Q!h>vFhj%qd?kBE1&=*-*Rm4O1%W1>{R2EL#OQeX+1OR6URic z2fw)9R36X?$9^r<`Q}?ovZVK5zM774SQD@8My3Q@Ci;Z8H#*KBSiACo3fN5{XGhq! zWR`q46$6wSaSKcE&bpJa?EIRBr#K7%Om&^~>m|DOcOg zpP%aXKGDlsOJ{l8DTf0Bsl-1VaZU7Tr0G(3g4~I7>b6w@4W%}Ps&6C$-Wnaw ze^aWaNk-|E^n5aG&IEZHq!u%&F$HERtIExu)-D7n*efU#?ecpOZ9;xD2SdRzAND5> zN~tm2GWO7?MpT40Aol|)iKZ{iPc~+1N*MO*OMnf~)a1T(W21msm)A(K3vE(j)xwSd z>Q4Tu8G{$b!7*DH5!IQFKG%>+%Ui%`VhfeGrSrwM@c7gDIq?Ml$s<<d8g2S<_9;v+7M@@inFrf7+{~S}!N}XDXJn z>5ZY4g&OhDeu#Z+djj@z%vi-?4EMr-a2``d^a>`KU4 zY6#BsiDZOW+A62*6eSeIm&nw0M}zt!`AM;}%>U0ZnK*4eOmyUn$gXX%E{_UuL#x$A zVW~YsFWl`rqX~s}d3xEft=?AEL8PyfN@_$inz#WMsq;r+c#jmmu~nx!Ce=AwRDBj< z`WP&%rc}|>k!fG&AWRLTS2=H|)h@m}9WIZtS70LNU2Tn6i8QSHG9tAtONTJr&Lg9d z!hBxtw&x_LYllrfl~0HSRQl+%8F|-45H5Pbsde@mk53V!cBeZ;()jc6zF3ta)}6FI z&yBfIam+A#l=jvciH?)*T7O}~4K5MIM0HTxb_|1JB}0=3#@>yJ&6K z@w_+S1MD>MUJ4!oCi9n)OAHDZL@u*l7Y#4Zr&t9x-Abs5I}a6pUXe8-o7Ip|edz=c z-Qs|N?}h82O-sN;LW?QO9FG_4Qo;$xzMQAME;nS)$DnviW!in&n8D=4jWdme$drhm z3E9?!Uw7B%+2a?ZLSb}l*dFlDzdN;JA@lM;F2ZfAs)3ms4m91y*5hGfchWb^-$A-p z?SR>YCA4Ys>nQt#IbgART{T66`X8mA1hQ;q2ld!y$x6jC6y^6iW??OzkZ4V4{E|;T5`8d4!Kn zp*}0p^1BmfCnFoV;sfwJh2&WuUbM5o8#ADl3fd@U46uadNzh$Mw#>c!4(pE&*ABNO z$PQPpabS>OM}OHSi=?m+OEhgS$y5Iv?t&cUnTl3Ua;xYeL8w>R2~%sS_gaa5ycG*g zzy$N~GV^~K+diG~T>4lW-4S}}rQ48!)UwxKrQit@#&=b1fq%6Rwj28l>IojTa{OM% zWL#9iqhzA+s=6s0Pl1{Tniv{vXTm4&GEYFMU``&avx%%tzI%)o!NDa&aa z?L-BU?n0#WPT%vsio{!kB-dbu$CgsrD3H8}X2wNm{>V&PSjdW8Au&sG{2t313evW+ z!pxuwDnTF%=T40rbQ)LXCBzvyrLz@z7Z#+~zSx7BN!xQhW|u;6wH-(DnRrdz`!CKF zjmEGtQ5v38$jkv5GB?8nYnASX-4kAP`IKUO8VPhQ%~7ghpS#OwK7(AR`N?PmuW|HM zVN37;+FL4Ca300en!$(Dp;uh5=hXG!M;0Yly1Q4VKUvkb5!_NCuRB(%-voleoRwwC zOD1X>t3J-r5z>PBH~A5qUvzsoZfy@5ZP9r07PKR+agC|ldh@D%=-xjSYRpXMi>hErtm4)ujVlf%+wd?JN-cV+ir zD6^A{ZKW6iqelA+pL0l~T zL>_{?Bg>f&?`0FmN?LPn`*xhedIx0i;x8?fV8`(?%biWw$y%;2^7&wFUM+WjF)M_X zQ!Wrss&mX}J;QFkYT)lc#^#!pc>Z(0kb=V;a#Kk+3O_6OZ`{T{>0`NKK1!1v0_>7ZYpf_6l zs!^NHI(=RXBd2qm&}XZ%@G97(9v&hzGe)Ne*FKo70hXHQgbI~6DJ6QFI&_4c@b?zK zL4raRFnaq6yhFk{0muO_T!Taqt;JFH+WO>rLPLjRHP67NSGbgISfJg(~ z;CV0NCQm=Tr%E8td>;`VkL`&XAtPykX@G#n+e`LA!B4`e)+zS}VgbPtAM8v-vxPuO zM$sg}fir*_ohN+W=VN`)<+!zPP7BaIYEj&z=jOnTF5}JPWk51n=frZ7CcOXC!$|1- zq2=o|yrag?eT5SUj>i%7H=mZL@hY7=2qs!4D;*N1&T zOP}{mI!CcI>}M(iZn4o+eTo&viTPvYMrThcD)CZG>XC2q>BL01vQe6KdDxGGs7yD_ zf0j4x@T?}$XeTfe5DRVd^py77=j%YMdND1lIjUz<$sAF+ zKe_urd(x~AeA+<4Y4@gQtM&p!Nm%C5mT*(WCl%JKb7#{Jnn&-gTeclpwQCrf*ab65 zYILc~3no%ej3ADMKaV`1bXroYkZt5hNnTWKERO23Pw^Usl!RnKN8(9nIF5`8<_?hr zlg~tHG7}=&r~|46$ijnGhiTNFmCSjuwxP4@%0aMY&#MlFr8uv9-wZ0~GCqFkQv>cC zoPj;s0+&jJh?7(@m&$dM07(tYJrBkoM;TL+85}Nk*7LG|-x}sT#qO!1?^z3TIz9>; z^J1ZK)Uy^IkjZkV8S|vtEg&4!jtzaTgiT>W8f#OWC-yki=bE}8q`IN=Gn#c{eID7ncECrlm11qJulCyZqW4Ta zSs#X(!80IfoS?&S{^OqNZ4!`%T-NN}5A}&O=EO#6;&ovWyDV~Q)AVeqf(#tmc0G}8 zWFBqFJS;nVBqXyH6jk90a+W0Jg*t|vOPrpf_$>Fdmr0O1bYdPUBr6bYFm^Y7x{xPj zjz_?dir&@|CXPeq)Nz3w|FHR|-9PzGM*dTW?OlzOV;%hGfbGS_#E9Dcn8-@DMrd^uO33PA zUtEK=K>UTg$mBx5MXpnXpH;6#KL1p;Lifoy_sMv-n+PR1?6|Sk$s)$kghAjCOZ~}` z!)w|fnmMrz2751q>77LCV;J;KK}R|XP#d(2+hY9jW87+yfE$d*v2QbLYC5T48+70q)U#!Wz3k(sWc$L?zI#DgO~` zg_Zsh#d!_?uknbvoxJmU_SynG=5iOcM%{9a*t<{F8j0);6gHp})_=6)QX7Mqh#8od|JhNZw~e%B7K#8{yV47_f2!=Q#XS`~ zye6T{Yk9U@8<)&&9qcOiWq*LF=n4B9e)~R*GCnwM3|1y?%#F;-q4;ua80d%eQDdk@ zVG=|N7riJth8>u#?9a$_iq^1#I2_rf>o4wyMeEH^+R4;>-`dHdJ3>4c5K*l1rFU3? z(&)K}k{{iF;BXc}{!O?2I>G7AY|La)R|!a;PEVar$Kh1`2z&l-ACM`6 z-4bW%|LGe|uyrsFDMIkr2&;?O_-02G!k(9l{hXg?Ylyba&ZzFta$_d%&}s#SFp$&HWHl7fzVHp0FFW_n(<>h zR^qknlf9$pu&@|))fUQPQn=wc>fnHSLkuWY*q`SS7KQ~xc?pv41p=v!p87Eho?ce< z)zoQ3xIO^tJ;!GtjTP}VrEj|(;xe^g2^}@J5#~(mc>R;@0Z{~ zP7&58J>eS$!i>{=v(uv3%~mRe*DyAXiBsS{|8V0cJ}GSSDK5qXWyWBt{?OAPK~6_Wh&}-G+KMD_!VsD&zM_O@53Zy zT9#|_?R2Pz_uJs$_R&Ly%{JIUQ6+@7gk(|+gZOe~&7xB#%FH&RZd$2a zqFY=(&ZZXT`CvHxS@T$AZmT133${}WB{l}Io*^V*5GF8z#QcGanb_+OPY%0??Dd&b zd9VwmYfE(*qb*((o)7as{^p3n`IR1i$DDJ|~KWDuHu@e8sv;lu)ks$T@9d zdGUu2cb6zwKyjsykRQNuosZD?oEJ4D<0f+R_Km*7NOB}Tz8f=2&o;wDEDLeV(1%s5 zR-lu_B4y^kaV{pq*S=Ye^Muu0o_2XankyUBU*7>L9cck_T@_HAPI6^KpF2~pW7+;l zaOHF@%<%lW^Y!noi5u18^P=S$6?etQ8ovA&!%Bo!P4(S)!ZwLzYpsY>88;3!>%?6y z>CZ2Knsz^9`U6NROFk$UB7}=7RJ=rNGLHH0D*~I~H!8X)A*SU!3;)IZKfmlhWAmHO zB>4u~P*QshUoxd-OJO>z5Mk_Pl_(mYxZ;fI7}NQ(jJ7fIO4dg_Or{M%Goi_A<7y;M zEagjS3&R?i%nZzxihIiD0k@N`s4(49E_B%(XH6yNPc$U*xPmb?z6@4rly5tIF3dSP z)D*yr0Rpucxf@hGlb`Fh^Lf3T(*jg}43M~K!w<%N_%v8K(ruu{X;v>K9PN?Tfv=uo zUFo6EQDfu;gyjMY+EaAQBdknwUMF*Me=>J0GmoB~#wPsAf` zXO(l2cgzVMCaXmAW^tBje^PE?pEQ23*QnOOPJ#sVzBwLe193!MB~W(=YA#SsgghqXze7X>`=gH}}ddAlu2z6rw!^!Au$gF|)__4Z3YMjSN!?Nn_+mWIT4`3M zYr1TNI4xW*LF!ZR%YU{M_FW7Mfu;N!`Qk=E>)PNekM^>EyS3QbEI<0f{o&-0uT>zy4+H#eXg?fOR>3 z75(XQoLx+gs6G2B z_gl_}z`CbbVdTUNs;jqqtBgisw{|r%_Jy@yX!3-<$oe})qJj)v3|b>-Tk9LVFL3C- zcUR2BY+8x0=_gGo0jb%j(I6)Z`Bt8+va}N-9-s8JQIs1v`_VnMS}cDSWMR-S`sGT$0bK~=h>Uz1Za`S1x z^UcLPLTAkg-dKI!(6TupR~V+TvTdo8w8Jki`(u$H2OXb*H9+es6SF3cOc}oSbVU<>D$+-O?B{0-&r~u&s)GJU=e8}6O^04iB zGzx%HQR?r%ymq&mo=)%efaR6yK-j?ENBuu-a_4s4?M-K9XwFj5?xHqSQ7&OI{)}Tu z^>{u<&I^hiQ_^t7tr#b=b&Cq#8c#LMN+MP2zR$6xrF;iks=nL9Hs33DOBezaXcIpz z^X*-Gfishr>9XaZZldl~VsNp?lXj_E#~0zPAlb}}W$`lovQPB~bJM_KAb zrn|X9NT}0{Y>Cpr24G5@x*m0$BRI=3cQQ0RG)pNmwVR@pyt|v?p^^+dIpa_s-MwP0 z4?s<@5LVn#VWL z(>c!pUn$VZ>CM>#Ki}u#kyQJz*8`rqe8oyWnNn#{Q`%nVq=u03Ir1^_{>Jf+GF0TC z)Jx6=`MB?{8eTjwXj>lMnCq*L!%xEM2v{n90o#SI%apOmr%_VL6KB(Pa5V-zMv@N? zkGO$Mq+(y}2M8#L`H@_6 z;d!)m`{}2@2JYWV|DV+laLo^xq_2OHDI`-0CRi)>D&Q`~Q>U#O<~(Is<_T?eeS#+s zGo(-`b3O_?VP5Nx`YOnKULgTJE9}i~^rGHdz_C+~k1t?T88V3G5Kdz_O;?MSDC|i= z+_hO%PTFeaHLkD7a1?4EOkr|ZW8h+sCgC(q+8IR9u@4j=sF~SPomgNaN%6#gy!_kG z`tK(W?S=Z7d9@GY2&_yml-*REFIQN9JbQ}VsQ!)fQ@b*8>vQREoaeXnFTLP@H}uci ze*{>h^$v@=L`g-;a1U93rHdL4`C0j;izgohu@u?&mu6Atu zH+VeC9?R3QO-f2r%|?!Ft0@Ns3ov8>409h4y#wo|i#-na4!4~<+b-n{9ta^?;#sp@ z!FM$FDd0XZA}3k^U&GC7JWJ(F`OSejM4miTNqzyn4$zb8e73XV5$$k$g0q$|#1rMl zBAwMatz=%^%r_Vs8AcNtG3{-EY7b1q0)x1{;bEDor(zgo);F2}@6^OMZY(pIV#3~0 zqv_DsTuDKA3p%G+!^rO19bE#EPOmk+qEoeZwO{rtqtXEr_Nh+J!@`kS>Oj{>?Qe)T z0)l7AC1N z(a3zFFYo`^pxF2Srakd**ZvFbXe&rD*^oYUM78NXef;L*!|#}PV%L+Gw^+p5=fCd4 z{XO?V;mbfs+g$Tjl;(!B)jHaye|G2hz=-Nl&GB}szV(4AQ*$nt(zF2c@6wiz1 z%!<}U`lmOg2XNH%xQ11xfqJ!a5hIpCzw&qAZK_tPmwoY&)X^%MA=?&_kQB9#a6plD z=<|%4XsM}(ry|&Fh=qh=+@;0`+)1Vu-ONWD*VOYg_eiN)`Iswye%zHj%PPEGi@mLH z$ie8RP_$=a27E#mA7e`|7ghRM1(FAcFr)AB)Hrebn-w^FCZ%DcS7kD{a4Q=9N^vmEvl@^$Lh|&Rl+Ww#kE{10T;-9^ z#SsEsbeEnA=?I(0D!4zk-v8Cfq-_0khPFdAGZ$jt1vs&^iMNwo1{TJq_qfDaGe?cc z8A9o8hakJhH0i%69CBD{&y8*L)ja$C4HAWK!OX(hHYl%mGHwi{I#4$Li`vqDl^Xs_ zCT5m2Vv2?8i#2r9>+ry$a&LEMc~Ux?^dpTV$6^+r_=KpR;&td`YkEs7;0+3-jPJGi#RZLe>kdwzpgL_Iz#`#*LkQ zgoMI|j1OZ{?mHQb?ltpr?dbx;v00I*E|}O5)uy{_!EkUzck9+vrKs%fQ^ayIO;Q8- zb7J@epFSUr39(~uOoJN!H+fNm_q8@MpBy90U-v4nrJf5+;~`2KM^T#_t3R8{q$9S# z69--ncW}s?!5vt;m@pkRqM?ev}D2BMFOb>|}y1#JeH%?Sj zK+L_s&r^tK%`I>C&OFQ@E8ibiO0B9bHeafKWZn>Gs*)Rz+Rzi?h4x(={+fkcK4j8T z>oelDtIU=f+du78@W-8fWbUG2Gs9!taXKu9VMjItE{IfBivtYPzWjWLk@5>5@_Euf zY$P%_a=<-=dKT4Ju=(>f=HJShd;@txXv_|D)654(41 zIaotqKT12-?2arhWbh;hruCN&i99=tEm(Ek{b4MPJ$`A#!m}^%?4(z6BW>+~(g$$x z692x@JHCKb$YuNN?foZ@9HP2~1h?#HRabangC<3H6pD^@eUiM6moId3KHgQBPEauH zdKYMlMe=^$#U<_a?`tGf>f=p$7wPvHyC#KCQN3vt9LtQHCz1KQf4nlJ6UUs|#6K1l zc4e~9x2xfvvg1xm!23t&n`kc@&j%XFqyp^mI`JbXP3nDKA?hHm)#6tSl_}KL3LpS` z6jqF>Ki2$QE|1NJ)833y2CSuSXs*&6A=Bgg$}3mWe*!%oU&37_#LPR`##o>q$`d=R zd`AH;V{GU8hw*Bn;C?irV$i~9Ku+2A$;?|#X|8|ym4wjt)1bfRrN5Q_^ef?pD^|FJ zAOe{Ujv(C9UGSy2EU#d0a}EUlGsPS4AM%r!x4a$^iLRdul5@w?&EkAl^SV#m1^c5; z=I*YIhsX#Y{LBfu^FLj{T^gUd>>bL{IeCBmKW+Pe{9*q?gMg=Zw^n^p;uhqrLF2Ig z_uzerl#M|j@p$p)1~p+}=LJ$BR!#5K{2Hy6o>7g|$|!b>s$)-!+ur<( zKbyGwkmR9bLxKuQn3x5%su%Ea?j=VgmS5q~8T!z$H5dNt?D>yp|M2dHF>WhIvCZ#d zwKc!KePQ))zv$_|6U*bC;EkU2%_GpGPVje&5ywxzYqb5wS%vmsV?^QBpJW`_Zs&II zv+l`+0Czrk^Y|Fg2%o8}Ho9aGK^#8juk^tGkSWsJnFwGg*2@_2xB*7q;HYsBU2knMN1Ys|(Bsk4D&)W2vR4(=z4U)6z6Jq6Gam zK0p56->@mf0oZ?HGG(D1PopYO?k7a)Dp9Ea{<@n5C6JmL>Ana(8EiLnVC4M-RTHx353%yq*ODZD7!esi*aQq@74En3`1y)hf@rXthU(#kDJ&c1!8A2s?hf|92` zr(o7+nWL)657v&ioNxegKr~9{pyc)h#bWL*6Ra;Xj_oZwm;yL9GIc7HB(!9<$9DPz ze&%n5R!T}opDWWe6A~-*PwI$rAehO9-PoA+$S^Kp{iDWmU?#5lFpO;PbN&MY|Kw-? zr*-dZ2hj8V#=*bkcyX)zj=hQbsmj%}-#7-1lD~1V#0rR}XwydnUDXTkEDaEFmw)va24U&q6{ilC)(esR#YK=ZfA)FSZyXNI z&}|=_bfZ0qDD>Wtj6N|6wW<&@R^p{q7zOlgD z{jcZ2keZf!nUogsuzhSINfx~P1$<1Y^G2U}1|)EIgSiiNtGzfw|476P;STil zvsoWQc4k{dH-cJ%U$8NYDn~OWmgaRin(#WxHmIgZj|(ymk52kpMC(MI9@)*Kt=Tvb z5nzE~;-`2*%*yjv0=>!&DpIs7SY*Q3-)vkxJ8lszG9+%Nub!4E&nY|NpmdhgzC$$v z>hB}opKp%+m~YQjo(*e;@>nE*NA#7}oVa~E`HthESh9)jcIk!i{)oG>#c!OE`_z#e zu57z}g!=q@EecHiI&{Ra#B^2v?*^m4v>^u@j=}MLoScQ3EnLcbtV*c!AC>tx@cGuk zd~skyfoYPjs`L4eqtB7hew9Y7%G;SXK}H$-NUXBO?A|vEMaGmElXi;^p_BWRadwur2pp&LhtdONFGy)L1#s58;Y=(fU%g3-zjpPWM@wgm zU&MgKS{`k{zJm4fsw+nPtbOHHoPTOGc^&&xN=4dsKAAf%@3+&3FRj|ZWkj+;D9mho zPDD9KkVt8q>PJ&$flMNP-|ZLgQ8eF$T9YI-Rzu10e4Q^wAc+i3ByADB^*Y7LRIEK5 ztzNIKYo*JsfA7EzxJ9Z#hCs;cB0a8>!V<_SKo30gjmW<>1QpfBKOCmcWHkFYOL6l7 zGX14$N=|u4+YtJoYMu9MOKMxnsG-v=dXzewI9{n{ZFhxCU+=ijf1>!&EGn!O5HMV3 z3@)v}CJ%j$P!N@RdQE4Rr$M&cc3aMNH}^|^dAo80$sWzOSoFW>81Wy??VJs>c#$-o#oCtxXi zCgQ)`-)`P}@k_VV^2(O$1$L=cd_%wWcPsy@ZRO`ju4z>HU)nGBpp?Em%^;Ut)RW{) zzVTc+eGm5kmylK6D0|J-N_iK$tTB5%g+5v4hRbNS-1sETTmqxL5d5-m%u0Y*g}Y|r zd;rcV!G!L5VX)Bug66GNtQ0K_IM^K1cpe0V_|!?FaOmb z*qq&v(r=s(dS;jQCFfOQL_F{R?HbNV>$8e1{rC6(l!L_*B0Kq0IB)uxeZ$!eeHlfwMhuz0|_Sao6{+)RFKk(>opH+j7t8BM6h=a`huDt`F%(iX~*xW)cep#tn zB>80Qi>ozl_-XG&GSuY4NX(*jGU9=i)uDMhDQ|?LLhUBT*UZfv#}k63;4&-j4yO_l zy0b>TLMnRj?ayO5b+>mNBsHzlqgjFA$Qc?0b1cnfJ;b7?Ev+KzXZ;`>`LSouoZ8**mtw1+CCbjL2Y{9z{CX{+PXEQp-4L>Ew1^%Hxh;w z=C&eJOV0X0?DS&?vB%Om4fr)pbwyW~)Vk8$z$MFX%_qLnIJ@m}%)k2Cr zXvpqw1C{$?3DZbcJ*vfav;dg&(_OZ@F%ZMJY=})lC<_V-GbtN%FP_v+1e?J_9>3$qxh=tBbZ(b%4oh=QUVS z_8s118fY3FPyMKbPp;}|WeK;UQ;XjLgJ=ZeH;xtM{@etRSjfJ=Ls;k5u-q=aBs)Ca zi#c1U4LIQbedo43mQS9rp=X>NPENncc3nYUw@>gkS1VyQ%t(tY$L8^Lo%e(FJZ*xF z41^tzRS}B$eDqZGGyveIYr7MfdUzdhdmtley>9cpOIJ}r6bWU_3$0;a4ghQxfEvt~ z%1Yd)PS%AeAWTc@0HtbSW%Ud$mQ>YBIQ{%P zZ%CQ6{x#*8alXEqHIHd3GGYVC6^5`)+gylPw#gi&PVLv1<};%RSaby6D|T800Npa& zr!RtuQru=K$r)r>M|M1D#sKzYNccnc9n(kvS&-PLDPQD_oKJk9_1IPojkG*gB}Ye(J}28RB^p*#$^=&?Ys#;L7`zBHJ?}++zsgnRoUeBt zC?0Ldy&wE`t$izXYl)Wi^H^q|0XhX#8J$%)a~r=2HLdWg_oOL-?#yRu?0I$wg|CET z4l`A;>CdK|&DK4+E5#C8C*YP2+gH;+ItmsO50s|fh3v~WAqBUld_0G$w#Xh5&1rOj zovd%8Rm02A^B=zM71f*d9ejTJ&ho{pS)!~&_e;rn(pt6>SLa%j@H{5SF!{J1dw2(6 zy`j!^sg2EBjj4WXb;jTKJfBeX2(J;yO&S{7@M4D3Pdf-hYnmLEl27~uCFoXT*2*|u zR(xVQRKDfQq7WCApsXD>r>_dW#e+W2tC8FDt=RE2IB5J?1F^ZPp6zfYUaJ?9(a;Jn z2i4?0R&3X}{zSD)$BBuO&fhW^KQk(vb=`zo6)0A@LezSsXdQB#RceP7E3>wguxUgc zovqZpwZfi}cs z`nnhmaIsg<@PJX~CeTi1dB!!Er|Gd#s>h6|p>}n68z~?YVC<9Vijs=ea?r5)(qAQX z`5R~W@ng724&AS#KZB2CZ1A!8UxJT{{~CPsns@>0EkL68HoWzUC)SGXhqp!Vb(xhY z%c)q=L@Gz@ZYQgFq!7gQ8@N(yPvkH23QfIW+B&^B^V%HQDnd5P_vWSBA%sMLLRbV> zTAI-jeL<^YyPBi&2va?-Y{_{b-H(~)?bZD2a}M}lmX8|wwv<((z- ziSPpct@xy2A*xg-wbS9If?udzn@xwx0K7KDhE=UyYmKONV-0ktTFYJ_t2@Js9RUuD z8aLh$Y8H^J1Bz&PyZIJu1{kH=Xt{7^xY`Xz9xMZd7j8LRq-|@gmy!!q+w3L3&+1A_ zce(5j*Y>u0tZ!$QDEmwkr@hk?)*d%^vkLUs9o3nt*{cL*V}vU$EN2D;OmAn_PccXJ zH)WoX(P23`xs{fZs1D(2>MjO|XDn0q|5*zD>roc2Yd*8?!uB(%Ap4A%g0j^DC*E)3 zX_OvrwPX8^*U6qnIiCtES0t`nZ&v+5p^63Z@TfSeRj(t*!`K+JF?COCADLYH)ImlQ zokD8S`1q$rRw#4F`KkU8+j@6uA#U_j_mpaj%EGYn%)T^ew)p1T z^44!feKJz@?>;+^I!O7F4H)PkKl>t#W*^1f+-vF>E<`*JVw|P$(LwRC_(8q=I=*=D z7)Ds6kONJ&U?PGVqf*Dq8%#W1{jZ^sQZ8fVdnR;KO=zW))nD*l`~;V0n3s6sSIMAXrnyqdlE{TNsB)K6!cUshML3 z?HrIH@QE+^mLoXVs-_{u79EHmJ}M;Cf5FAH-fdib2i>bOjhg;)zuiWvmca_`{N;VX z4^5u>i&inx9yLUjkQCacYl&9iM^{?0*+;a}jyv=2h1)zTlbpw)dwk#vNM1mo1HZl{ zKhW6FnpJo-TtOT;;!}uDaRD!~@p=n>U!vZZ&dkcJSLl#=WF*dEtYBy}H8efQ(mQwM zwg`c8q4jE$9Q9e73&I%H$V`U`4`Lvit-e~52uy6zrRf(^>rIJ6g6%aMtt*njsdG!07(% z4Ecz=7D8F}KZ$)cq%a#g^%)Tx5P+ z7NtEXbPlq!_os5+y18Ha)GqLN{4HNjh}gS79c|S`_`mkF{&G+LQF`1ruCgg|Po%O{ta^Qj^%kGZz zYL{$56aaH#cD^E6J}%&;4q@iE{Wc+b1#PxW9X8kl2KKAHvDB)cLIB=c$Xzi zU!ES#5+P)xy_DDO*sCL`NeH@DIzEqHRgalBKiB)EAvUU(b|0|ugD9NJ{GA?8BQ253 zuRYYJ*h+!tVxX~DR;cUFkxN_IM}rcuc|ds3#BG<4zHz?vC+Gm+$UH5g6se=n<7>E@ z$nq?Tzfn<9nsz^$-4ro)XhD?KF1KkDc_lZC;y7Qa&d_LvY76jAeI6+SCBk7)D^IY~-*QAmKJUzyZ{K+TE`O|IuY)IzI?YxKud!ChZrvVmY0R>>dZLh1noVn9 z4R6L`jzA*#V*}qCo6Vu%OD#B*e=vWAuz%tqI($$y*Y?OnhoXf>%OQ!jtJ{!8?NpWYkMEm81W0PEoeuKg^X1X5jo zvhCkgIfpgL)BhNrDF;oSIyoRnC*@ zw$@SDZ6Sg)OGt65UFpjEb##=-m1!<$Jr2s_JK1*oloy{KoOddLC!<)goD?)Q#+Iug zPxAu~M%DQv|Bx+WJY!i5|Hku}N0ondyd#$_@;s2p5O%vol4H4Sl9NXiKZzGl^^LXZ zWpkqA7A<(;>P4?EjN1?LS-TKMGFqu2UpYbyt{qv;9amP3P+@qsf+>6K;oay!!!t9{ zBG^;AC)p~mGAO*P5r4$rl26kK6rAn2k^O9PSswxW^?X@6T(2ETSotcy9nl$00DobW z8g{g-U>weF)E??9^@C7Sna;UziKj4$qDb#b?@I5W^o|fh=tzfz(0f&p-lRilN(hk9O9&7UrAu$27wH`Y zY0{kdzO&!=*~gywzCAPh&#WI|9pS!LR<4zMt*f4=S$p=qvLV->#9S2TMD%=kfc>jB ztTz30kQyvc8^`tv(x+#~FOST z@be^`(rfQ#&14{^8RJ2ke1R!A0Y-2nv zY6&<4xQ{&U9xd7PKYcyU#ZGD^bPlz({5nZ>%6pu1HR@|@_^JM`qDU?nv+ zW6%POs5~8J%N?b=I5v;e{g9jPrbh!kmYj|oLl_~RLjJLh-#Dso_)Rcm_~1^^F3ZIM zLB&5%(3JwFL72B=d=@Ft~7{Ekkyv`LE^9>A-;K*Ws(ZOy8Sg%ZCEhM zX7Pd7WUsCADag_D*FbNfdUMedJIkanEw0K@e_9JDJi#(cq~%pkqR1j2^;%*n26M~7 zH~rmN%zIiW5G9&R)eKe~d5~_0V>dpT!|4Q2GBuW$&d9?9-e`%4hqK`;_NV~ODVIEPhu^dmPl zUYK4}+V-o_v8MJg$wBM6NTxzFpV7(*i`fKD&rC2H+bTp_MxAygnP3g+M}pMjb!`lu zDr;!7wFNz`gIQQVh2CO2+4k>?CZNj=s6?WJmbA6L%WN| zjLZ={)->Sa2Y_*R_KH|LEs^9xnQD6U1#Aw2;~y656qW6i6_cOS>!YU9b_nlheFG_W zdr6jgoy+_+nx`1buyv~1{bA0#NTpb%-md#V!a3Q&X|0)}R^vlCalVj7_=jOCyeVeI ze94nP1~BJB9+A~eqe}O<9;B16d1f0TW0xq*{R(y7y-`LqP1no2RH^TxpbfyDF;8Uv212MQ=xXF6tteNNjvAhWaeIcC4#Pd-(e+mz*cW6#r3k_ z%j=^+F}QZenXCN>T(uf9-r+;GtImKGEFT3ily^{;7-RS{s=;OX4S1;iX}x7tXL$gh zDOuqZ4K2APa+6wzu@B>N5kW$xni~Ad`5Y)a^--e)6-9!CXgdp01+k%UwiJ?{#*JX& z+M@Bxaai!p#;S?dOi^;NQbMbq60J6Iap2>PWZKc9KJZoWCokXPavkKWrxV%D8)0fm zC_>Rv>m+y_b$)%%;>R-(`loRC*CMd$Pc|n$ME%catfodh!HV`Jxyk_qLH~TB5y3Al zBr6CWBI+9=Z(mQJ@h%JZy|4@bwD-vr%b0xDwl>Bf#H*|uvle(6~z+W0!YW$oG}EfUdX2#fj*p8W4m>soQh zjOz0++zNRpNeFwexR)e0pGdsu#l4|4;>IyUt>g`GOl@LsgM@Vzbk{??n~{P%l}y~F zVS+2-$&W6LxkuL3p4KAYE1&aYH+5==y<2N4*8#wKOa|(hOn4rvEubYbL6&f^-($~j((yJm^NL$(XTpi1?;plqi8*ciGY)V! zJ99a)ra~l!xRR#4j_UG0rJzlECJ?$6Md5TB__i^t;XC<(b-8QNn@;2z<7}t1*pvf@I zSPf(I^q%pDFxt_J(CWAb73-jct&=&={Zknvifg;vjw_!d))lr@$Zj30Y$qhmUc4+G z9A_x-F)gzGe#EOEZ4X`V6479c3x%{wH7cg+j{Dur*~7)}QxHxsmH}+X%KhIj>BV)Z z8E2{SggO$}szT+$PAY7hlb~guyTrjYx(4t7;iX1oVZ1~~qhm%ivm|r2*MNQW?qpa3 z!8zkJ^F~LEVN{$iTj=;zV&IaLz~X>^Zm6VEiG~8yOFk~5);95L)dp@Vj$Lzd=<%qI zWXh8$-r7-Btka3(l$Z^jXlKv#c}aS$H@h9PA5MnCv?Qko8BgAClo5N>*O#9W)f?OV zpQFEw5gVabRy+IGE!VK06u!^I7)Skn6D-|!58^wEJGBnC-doUNI^>_Y3ZA$&Tj5-r zb&l6jvX}{N;68u){q~ocNgCVnEM@lj6r*i#etvUdBUP_P*1OA`aLu+0`4R?x(M7It zR4O~*=^dx8*yTnhML88Yz+_Q%99pq+9IJ9Dx)m?#fRdJoTBhQO>J)d@70(sX)I*j2 zh}ZV^BswSK2q)im(UM_>mT9V$y#$xMH4HM2wK;w(k5u&HU1Dpy-$nkeiT{CTHBgYJ zENPPz)K(g8U99h9Mo z%+2(F%ak|zuYJpR@T4dYM_zgjFqXMGu1%(x(ClmPk}lHW@}n#gX#-kTE9KU#C9%wv zp_UR{1~OK>&D=SsK;VrS5uM)z5O}4vl=^Ilxh&sN0ias`;j<{dx!A#m1*SYWNK2PG z9k&6GKPp1C@)I5EknS=w^BykqTVe~FX_iuZxCi{*zEz#F>M^@k_wt`yO}QT?0N{P? zn!3v9Jp06jG zM|$Y}0#HU{7Z_;s*Ap_4>-3s0f9*3Ef$?x1`?i}z>Zo58iMYgcdzRh9Q+bJx*t+WO zy47!6-my;4OVrT~S6MH>)a2XJ$FU7EPZOO#7^OP^EW)-lj)K52^UeY)rh7@h37+@1 zTIUr1$eIqhv3+;i;u7skyuKVS_l=GWPiAp0|K?vm#{b;8{OCD06Q|F-EKSiy)B+i+ z`SFOP<{;wxG2P{Z{TZ$oqG1b9f(KY`kjwdobYd^QQ#=vurM>!G`FStj;>^)^*8BE> zv+PPV@tot>T){-~UJFCFdyjAdMD$W^Xoat6>2ritx1+j3Ss4e)vfd{=SyFk4!WeG; zxvGnFud&0t6}6}&uVqk|6uUV8;?7WRLo+sdH$Fin5(SjYvS6if?Cb;@l-Rh62zgY!v zx(=o5#YVpSX}zhEAP#ZLAE~Ms_@qbr;JE1VTpb@_e1TgP?IzmAWa=9Q;pZ?{2}z*) zO10w%`ObUEZT69Gh$p$8eM0(dseCBbn{U(zY2+VlbY z)9Ira=X9m!jjEg$?oIJgBNGy4bFkC+s5YyB)Pj1TV+(Y1Ja((23Nnq3_8W1AQ8F5y z%%wA)7d~y&@SOBnsn=!2?Va$ozshHh&rC{zG1G!n+2!tS@`@h?m7eAzZH#iS-YY82 z&NSWq@@ECfPM#I2)s8H}E0(Zv&zh0^Uo)5sGU(aJ?tZfctv1WvLU4|c zrR&$Qm9RW%(dsI7M*?_K{L`LU;AnvZ15Z^NkUt^dl#VY0e5U$YSaKM$TtT}#BU=H> z`5X)sGJy^DL{2x3;8DkkGZFkrzHZ9knaYF4lR9V})ZZ(%|8uVa&gxwZd!nbli?LGi zD(%Y0@z>oSNA@2yHP#4Z%MV4r5A^{@-FY*$UM>}O@eVlYh02B$+N#@vmD+StJi$dk z6rr1kol2^_67S}qy4Xb72-5aeDw2y8Vf<0-ui>t2x3=xa2dy)NR0n?zw3)tC>~w)J z&Q~p7;xY8w>&JRPa3UI}Uf0rQ!}8V{c383{ zEb#|-6>rgV7mcr+uKA;umI9d_R~*)DZ;1=DVyNDT&N#BB+8K9JIcbfsFdbAULtY6a z&2c62N0rm*N5=A0mZ8E*s3tD@R5# z@lKy+rr;-jpz%RA#6$0+7!9NiR>-WUo6@GVm9_6!WK7**^<0d0y&nUBnuC zDF~+r|0MQc(um2sy8Y&({rrer%cBQ}e-KG1K+U>G8X=uoH_j_A@P}_I4~;DB!Qf%Y z@Yr4d7k{3-|Jo!SHkN(?O7moCF^5hgym!~W-dqrs_18IAe`D43uSAEqPFMgS%n{=& z0)fAm2NhRe`HMsz>l?Z7eH7ukXY@%!-T+!+cBddIj&QCtRJxzLH@5E0&@yjxNt^I! zV?=2@={@uO&s>u2c+_M+f-&evT)D%`3PBkUHHe*>aN@RYu1zWp)$1>T04>gJ^(?5G z4+N?A*k*Gz&6zY!W6}sZ_?nnc#WK$MMw-!hH}0!w_;D1D}43qR7!#56~%`IUEZ zkdW%)l%gZQvXL0-=g3lRTAsD7s4`8;!)gyp9Kq4v}-+Ox_dN&!(#7J zR^8|0>%FgxNGij9?+c43h>v-)0Mn-2R9W}?_&^jmk9iStVEOcw`Vxv+%5^43KQPzS zSCh|KfJ8`3xX%d3M&ml(kB5j z9&`vt_u_)~jbd+71u-kH@2#0=V>9q=_RjXk9c1ZaJqIH+|1AT3b-`^LJEP2p=%8DU zg{O8PmxE}h4QJqbW;u?Ov8OOd74!|KQu}S@vF)Z;{3*;}QSqb0qUdB$bu7fz-FZi= zt)~=NZvP<3vU9rHoK>V4?wNvsaD)nihCk;W3lC4u$Ed`guVF(ZHZb5-p|+x3mUv(5 zB5Ay(T~%t^aVh(Sm+!McIt9y3XK?Xuc04?2_QfXaH^uDS60*GrZ6s8pN=Bo zQ3H%1KF??+mN~LqHscXEFiyLKQqSyl#Y8aM(GErB_T~2P@qQp=E-9&y^izp!H{ZRk z7O>DrFIk1xj6cUBqAXmrZ|X_|t!sp#iaM)uQw??$(ec~p@#;08pN>(J2WZA`Hr>PRI~( z#fixj&uj30i*t0eW|j`m3W}HzKk7KorIi~dfG?rhkuO6%Yr^k$(BCV39WeN%SoIVC zwxlrFnPKslDO8M^m4pGJ36HjW$Kvu{(4t{S%+~v1^~RWrrI#ZrzX6W%&QaVF?>t#M zah{!9H;}MTkalffM{My-+c)Kl*Bs4Qg!s+gVaolS7qS|kb=`;gO^{cNx2T63+2pR7 z8f~xm&d{d}`b<(gWY@+{73Wt8mpw)$$?cdIU+;P3=jBhE${QpZi0~%WCPk)=$Dh?L zLztzzQ)VLBSWlB8W9vR#IUcnLF{zlSFdZ?SXK?}+3u0&ZEyuX@nT zmE`-nX4?r-0A!9u6q!C+$P4NC8hdSgRYRGg@2$sY=)r=LV{7M0Z?nT+fw_}imI!$f z#H4`z9#5su&H8LaV^bNe9tx_)__Wz8Hg7r$%c~DKyLKHMZR~6n2q>{%_G`Cq8K3t9 z-fTC~T$3&zix~VjzR5pLQ=&YHX2y%jvVx2OH{mYR!A8Lx23h+gh-0<)O2Ly}t2J?D zlb@#wcm#Oe)c~>bkayE%_FBUI)Z2pr*%t>9DzCLg5iM+P2kzdPx4E2>Y}1rY8**(c z6JmqyN5SlNT75;X1v=CC6k#%FEM5e&%b;blO(v0QY)EZ4-N2QOAo|;4l%4lz) zrJ+86AsmOTW zC6wPsJwMf6!PO%SA+r@rI=P(?bs%$Z?4X?y%?=)ZW?z{mo?5>S&iu@7K--c8w`x}| zSS(u~+aS-k(vLEA6egvOYZ(DdomE%k>U=S%?*>N^~)Wdnp~k1 z9_}$lYlGX=;LJjU&A&P#ainB}?=o>ogppTSSb6>7<_^t)!#1|QzMoUIml7F`T56wdD*{ScH+x<2CwS#tj%}*Y49_~K+r)A1F z$XmV8u`|=hG5D@wRn|81IB^>~s~k|@d#-q4k*aLarCEnB*vE736-Zg6a$ECw{?Czxzo@YM zqCsQpng~exw(7U* zeBn$UDPI`umLGmS7ds;ztaE<@CHws1BKYPFK3Vdj{N&hbh^fgo{cj_ojmnUz%5!@kr+n!UdIFTnLQl|RYBz~EE<_O#vxuA0HmH;-Tczb}Rg zzWX`$go@*AyJ+)GNB!V>>cujC{ZHKAocEX}audr6J?le`6<|oRG~Tt| znvtq{QQV8>YLCZKez7p$urre_98H?^PX>XNWKzBrcljsl#$WMspOJx~W<~j*rWNld zvcWZ@xS+|4S>NniSqz`rMm!n8v4QZUl*Hi}x(ir$w9S2p2tC@nM0`ZG7mB(fA_2W#Uc=NZXLwvhH zk9?QA562>1A_C~H%lp#3+LcJKv{`+?s5qP_QGlI#^XseJ0sKgf;CtTL@Hy)nSDj0T ztH&?IIj)6+qn^-{{U)H5Q~W@3AD?Z`l&^aC)^CE&gkjd3??RSUHj-}qukMusG$46=Ev0hfg6nTz z;O~IR{{y;gOyCkf(_+{i+u(r5NH{D-93zA%cq?3c548 zw0*eoHB&@xZn9G8#C)7=IIed(x{#SGKNHWavPw$cK46<3W*+yOKryLr)PsDdN%Skt z;Z_FSJ8&76a?@XEh-HcGm+7VA&W|JCox}Ro5CT5(q$xJDK*Q0dMK1n!UY{*N}XlIE-_oNDr6>XLt#{X89v$8+a z@T_dnP1|2O$~2U^9e~Cx7%FHRRpR7;{uV`&2}^Gm=tIcnL~2T;sq{qZAC8)_jM9GI zT#AeW{~n;M=q{o^vfYAJL&ElGOGAmIQ=b^TOyGwys)Zlf=f+j zYyYEGV)?KW)NT}~3#1J)n{jgy5D-zSuMko88x=C&(a{_QfoMx|`3Hjv1A16uH}U#MSa`l}f&ZQYyW;Wj zYkoYnV?g0*vz0Xw2trAbXfx|up^v^-9qO-!279lHraO(#aXeb~q@kdTLXtgtr`uyC z2xml@>y4h9Y+6)n!6yf;fLkY~dyr@5g?*q=XP&~wLR3guw1DQ3=DrGbm}jT$jzWIL zM_U%Heli{dkqXr!rH*Xg_~Z4rf;7-aumn@YOAVn?yKnF7M#&-55p>9v;jJz^E6Z+O zTN+lmXF&|!);?8?-#Et?P{=9FI(myG*D-U^0^wYKA-yJsyy7y_x09|Qm3asi*msUt zOHCVRFXwZ_S~lz(`Yu@3kN#L2cZ%|uj&pkvoX&$7!wrJ9Vl#g{+P_t+{}hoVePVW!LcFN`+B4lZnupsS~B86wb#9(!a+89?X6^(*P8XIiSUa zVJL145^XwaCZfy^LuPAgdTMG~da(XW1$jtwJ@)hbQ}X(s`a_V~^DAx{uHOW$sWN!Y z7^|z8l^c`y4I+~zht6XJ)u_(z2!V9W27eQnASy#fysyO18jRG9wWMNXF)TBgPE46) zn`=CWUZ1O65PbTP%cX})sz)$&yKKd}&DAX@;+1!&jwez^UUSWD;~TOg3DTUoddpfp zHmTx)D!GAyN*_)nRc?X?Omy{RoBiAv&6efvKRSZ>=6u`g9h_U=GNd=y#p)z9DL6CR ziHo2X$<~w-bAPf?u`A6{4J*sAf4-7&iPpAFw4J2XwB*b{3Ek7WV_RF(jionj<*iN9 zh{WtH(>z8nk(+j05pe6pn_Vgr0lyDs^5-{5-=qQ8!UWYa(^PVUhM{oV&Pis}XybN=}da(NLCiatE*(LwqeDFxC%(Ql8pdUx%nLix_}T-pM`AH^2W zErnPo8pPy5BC&piEU?A~olK~oqTh)()im5 zgkd4|Bbv-JZ|!_`q6mn@Q>pejBj^J{_OramFwrWbNx07Xd$QfWAwd=gv^td zuF$?iL7AqYq#w}73n)KTl>Axu&)%3y4$ZzUQUTrsyJ2=(3_+pi&%TS>ixi+m|4aiw zQ)tTq-PQg&{jN^?l(bg%P;T`Iy`_>NRlXf9KO&$>~Dwl-@E?>K&rm&M{wNr zEsx#ok93OrALQ&w-*iKlSP)P8BKr^;%!Ad3SMoRfyBi4WU(irJ^|^PGd4+$Gz{WIe z_6bqU2kiSBiSAUcZv^?}_wdkB-Da%>|GxBY+Z0|cPb9eb$0Z^f!Agm?9X)X zKGeBP)!)>Q;Th!20tULOb6CGaOw^ItvxD!b20)PepUoFMyrYT-_qtS2>#6P z%l~51v`Fa~=I(yh0C9BW9b%sEWjb#5&j;=L3sc^l|FaUm@oN7!0guW-+MD2#>ruQV zq28%e_^#$M@5t-M{NH?Kf0y`wL1V0ZaoV4dn|$dtL|s91dDs&88XsCYT}@}SPxN`= zJvtOr(u=Szu;oLpaJa7w~x6Dwx)t$ zfqu~`&Xp;3A6B)wUX}PLN4O>`mRCgymN%kr5|?G}S;?4hHy)IU>NnaRJAI#L8+P>A znAG+D4yTZ6u5Bwc_B5s#YJ|!%5x)wIBK|0rOG0l1Vrz>&aUx=?g9y_rxe>n`ppA#115_k|q})UywGgd>P}iBwt{ z7R$=3 z5Cat{(JPU2>Ix)CT-lAh#Y{a{@5{G7ud19E(EM30FC?#pzm_g)6OEOc3Up*e4>vtC z<}sWLF{-7Lj00j!DxvD3w`ns;(xTf^YwHTt9Ku>9>7F6@R;`8dbMi!H?K{+{QxiUH zW3-y(%V(z*4WNVxBv87JUT}>DazsFfh%5EJ546KoK`aXew9{h|Uj0diVe`Z#0_{zVJMi~<)z zqN4My@Qs~afV+@`|9QY`f1kh(Nt2Mn#aN3iha;vo?Y0&~o&5zaVaA$lti>dUgjlW| zmc*ssPvn^q!_|&Z^Ira1ayVF+$ge;enQnx2NKuypbFku_jlXD3*u?#w66!gOdHYS8 zr!7Dm(4J&E$Ina}qzeP-ynrATkhF?KWEux@HvE0?Xi;2xPOm~!?MRMxYqn%4JD#eH z(gb)O)Da~H;gf3PkJB$R8L>ApFyr=6QedfR;pL?zy;Te$-|FXDuJ0#lu|_@2+YGVXW~`ZSmN) z_Y{URk@l@>zAl%5ahO&i;8SG^nvqq!6md_Da%ou_Up3AT_L7XV%WpO>Z!8BpgG4|; z01Smf_Tl|4nYn^hbug9h#Gwerdsd=1TJJo-j_0pU9z0p*eZtxXB8Cp=?ce6s#%=1}?ON!KJNi zqhdQ5X@uWyFdgB!d0O(a!o2w`Xv>VXfI_8x+Fu(B?Dkm6ggg-6vK&$k`1YZux`3~e zo1I{NWlB4!rsoF)$MJZ_x!Dej^M;QoV%ifHjqKe-GD;9^g+pm0`#Vb8}CfS z*fu}zr5U8=xQy@hqL#nV>%dLM`_XE7X7xNc|F9Chguhai;d;wGNFX=BMm%lGGCXZN zMwg9CNbu=$0O6S7$cb5vmn3QfQ-mq20RnLXTEe3gqe4KSHZwCzY+s+E5QyW0d8llp zv5}>ZVwMWwHkq)+2n$JRG*iM|gMGT~+XCFfXooAn7gJsMs6WzmViy*~oQHeREH7;! z4oYnO7F3rE8&ApGTtLWvyP%tvdAofSAm`xVvbDWSS8LJ&Zrtk3?+4&PO~BazGNH&t zQlTD-QL=Pw)!Bi=%~HnLj<-Qe2@3YA7gR($B^Xi{|Ml441iHN2lryDf6F_TZ#&H-f zI$dvf>lSyI`KPgSC0WIyGj`BdWy>yL(jx@bP;iV$qfE}!TBuPi|8!LW9J3E{M>*tY zZ|(zVP{?R&5luxq-@bN_4CQj|H*fGTCF6TQEV)@!iFb6N8<_x^co+4yaz=J@ZbHvCqhO=>6(NzXwW{H?iUT?nbIm?8 zxpn!gKGkkfDaw8R*hGPBi4C)bkwz(%{Z%3<^6*iH=W5xq4a~W84DRMA!HWkg0R%m| zV#d3^koK=nlu$KA&G5)w&@rf=a+|FDjJ;vp|5mqAU^rg9hd>@PvS31iJ4jyAj#E}Hj$49vKcQRzYgJ&iZh&uEcnAJfOO0*;9hR~`8O zO}Ugm&JQzQ7*n63;u_wOd=8jb+aZ=)a?xu- z$CUF|8jc}Y{QQV%S`<5({1Z%g2aACVm1rG2QBIHwCPZ)AV(+x24KiCE887rzb(OiX zZ0x~d15q(rf%liF;-pbrj7-9A58S_ua(Gd$g zG;CQ3RItm5!rPts({i)s`0J2ne%U=^yR@I-awl@Gwza+Ip#}?6R~(%j$NaNbDvlv; z0hhvJpP>GsZj62=7@D82xGzGsO!IZC>SjHLc9~8C@cQ@V5XwWE60^IV&eAi}pxNE@ zrPN2}aHd{cRCH!=);r>l+$LLxb{jl0^Dd|x@Rrv2s>8`oa+axDoh_}J^LTuryHE2q zbr>aXFq0`N0DjV7ymEd^zAUcJ%5By};g9I75LkCStWA5zaBp5z&-m3;z!D1`lT+VS zufsoNN2Imny>S&g+coHHpmDuiYjn&%d8OeH;^uQH^p1*eJG=Wg!DPo!fH(f`fu-LB z9}Z)2d;L zYcf6t-w5=bzj zR<0g9)EprlTA$-(6i6s@l35gz%$_Pn6?}AhyZ$+j)@QAeg zq>TjRd9g0LZ9TXB5(LfMaU;^Sji8)YX^QL)qm7Yl&Z7HSvpqV4*9J2#pE4|PG!&%Q z)=XuRChpE;z|ng?Qv<&Vg4Pa&NZ)@mTE}c2M@*P`_NGK|4G#8W?@lVdFVP%xSWUQ7Y2LlyI*@a{zRShUi^tV z{WsVi#PNXugM4{f`E27s=?_y>SbBVg@tE3r*IakE1n!}7Gb5CSTH&>Io#awnLR@_> z#PHOUlahqS_%xT?l30$?IQE3%YsXfz_6ox6I6B8XN0v{yKFcdiOgU5}Uw!3s*vC-1 z_T9fcv%a343ZY>Y;fK`yQP#z+_EEo_D>fkn~Yb)`sPqzhthjqez zm)JFkN@u-t^h7?WX%F4ic!2hgfB;<2=QG`LsBakXm}r&Ym#uKx*}W-16)i(qY`5g5 z$oo@b?QX=kJX#S;C%SL(+s5tZv9Ar5&gfrx|GcO^m{^thm5bNUp{Dx$o)JDnnaIim z=DF4x3^DM%SlN_O+m2xMfyQnA-us3zeoI%QZnIuJQ0B2X+Y#HBP*Us0b)ucm^*>qq z#I0i_C4tYw)8VVeMUj)%J^}^AaK^m|+O|eV4E+p083t$G5iDZ)yil@VkBLytq+dUC zEc{}n{@b`)1W{;)@e2o*x6{()MP@AmV(J>SUFa&<_f}eLeb~D+8Oh5|yN|{ckfa#j z4YX#_tnQ+@=&^FMwpFU6nQq(&c z@HTIA0@d!RDyGalIXc|ZGAzabvrAz`mQXed+djsQAZ3XR>V-SLJC-vxR7i)ib~Mv( zpD^-nYFQe&+nA^2Mx()1W)n~|PZ+V;jBJkE@GhqhQ8Y7K{TM8^an3P(g5<9}<4150 zKE={*F#%()Xv-$k6ZgcQe}Vc6xa%n~44N>6QCIG0r)9PPXgg zlqaG40RmIfCI`p@WQ}Yp@Ck3f5ygW|gTL0e7Lf>qkO(lZwDZ`L37F73J>Z$3NG0j| z5PgS?B4d@knLnxD3d7D2T<2q5rWIW@L6fSe4lkZDS0j;l^T)m5mOjXF+J5tP>JJ0N zk^MQ>jp94pEx`{r3R~ht|3Ak}FE8_!o%7zjvFd8N_Otl>M>nK+RW!!so+z363aMvb zJC;UUtj8_nC_)Jzh~1Is6OzrnbabkbB-^%KVe_vLT$(YWCAYCeQK%PbD~X_>dPsF} zg1$Re**P7MccYP^^(UXQ_fo#l14TOr945aqJUf$=w->LDHv%PXXWS?FqiTBqci?u(TIm)!dWjE`I;(!@8tYLz zjg@{dA-Wy=XAS?^?v5-p#Z(8xwlo(Vpt6;vELHH;`N*Na$?1RlsRu3YF<1FvF5<}qhu`|*T zi#*X=Hcc_~e4u4sd`!NDi_SqxAd^_-6ly>8WTCJE#Py?g5h?j>TLpYnYm8OUC03~i zW2LA=?(6_1PycU9ilSRd&XcYM&x@<3y!yTiUsibX2pTVE@*Wx}60F9lna)~R-S#)# zptjUX<bq#D(s z#KHt_%RZ)0d;!-8rvK$%F8R*(1kqvqxGg*ko7O5Q^C=xv8Y_tb>y_P4FT*jP7Y-Ea zu5(k=XeC-UxVA{r8|OU8lj$i4c#pgBm;oweW|QG|LTMcJ@?+m~jh=UNNMAGW8o}J` zezY5~SaaaRsFP|2PS83rk?Vv;FVk@%X^L|sR5&ew!20!{1%Hyh5C2Ud9!yS9m$tO_ zglfj)J4!Yz^PVUpo*V*2k>yWr`6b3y;eyt+Q0Ry)rZ z!9}~R+GXxz{1;b5A0Kmc88ND~Zj&C`MG*4kyrYl*<}lEMl{*3kGRQ>D@6vLd9~`*E zwa5v7Jg!SDicOI2O*wt|ZXs^6?=VOp;y#0MSQN)t1aVeg4;^)R_nSS1`l3lc#95<&yVj)9l1b+(>Y<_ zjSQ4Dy{DD$dc2?I_mkD0-97+WtK+5Vp2k3C;&v{MvcG5n4}KCnoHZeZS_7AObH*xa zwksd$D0)P8@u%nI^P9k>MkVx<%PEiT2Ta0b>Q3YKj9NfOZ9K8PL+L1a3Ue%3r&W;h zm6>}+jtBF0osFr*$kUl}udd34k}_s9qkY}=>El}g&;`0#7tnaIMsKg<`t0#7?q+|E zF!L2KYRy-}h&I7F;AD^Ajd3BQ^OS|cbik*%-)1?i!D6k*McjM)S~!3Pg<40H=6SZ5 zs$6qxjI2;+O&mm)FcvuWd9Dgb@0n{jruB!_B-eAJnw5R>*Pk&P^=_(qwwRZ1LU(Nh z<|OkNQZ|w{ubX`D4;) z{NKrpmR!3BMFimPN1eu8Fk|gh7FnqGa_oO5?+7LeG6+sD?q9Euk!<`KUUu-OC6}6K z^{G{CjJGjjX0Db4P#QVtlxP2|I#Do3sQ113p58Onj-aX1KQp(|?{=-riXN;<%yT&Q zzUvK<%RZ%6*JD^Hx6k7uUC-n1?|doQY-_eN(dz5o{T-xeF!d4WddF-+GM!>3db**k zaFfCvdJop_kAC@lP0?gi=UzR^z8fy1pBJ#&q9F;vqmeZfqhQQf-C<4TpzK7Hk2Qa! zUeh@qGa#vWSdA%=7vtZm{;N8nl_$Gtjc%%HK}h`df7p?}!qW zqLVtHiMhqtEpZ)3os^QDIMx_tx-sN5OSVqjQK7Zqt6U%g$Gw-{K z?3CJ#TJ3+}-4I33pONR~BSMJ26At}r6k_fxm%&HGFNBe-1u%U@8=HJV-N#9O1-)P$ ztH_$!0HV9kcAKAX3rEW`^6z|Uy5F&*{xzCGa^`ESU3(93QS_*4!(c4ke(_keMkU|O zGk}FGF$~8sw)+_yo+siuq*cAx)XVquX`^^^5sMF(F*=L67qjKt#-T(9x#4zKjjlS+ zy|p9q*cf}v9nLQxUxabRS_7Go0~v*m6Fe!0d9>t3nU;KT{Uj!Sk|=YrS)5(DadVl2 zMkDH8z1e5(>b)k5;$atKL~r=3rY&W1?f}gF2pu81d{1jn!-d8w0>o}W)yqCPwij=lDy2e9e9AlS@UC(_xIRc2Dbl^l6&nXp3!l;R zthUN|)p1Wmi_tasS8J?MV;PZZeWeO1KaqJ8pQ>Sl9e+UOfp)sDzRNy6hF@|y)i0`~ zD;=2lR}mv1R(cpytVReiHZi}Js@s#(sIEM;6CT;S)NkU)ZvqHsYQ6pSD*2f_M`a8o z#W%HcL)b)zaQ8g9sw~4Z`O2Ny*KJ$oQImvA3UtVmu*XNC zI`vhkY1A34)?w%)Y9zwrRn-HTz+H{H#jvGt%#E%A8TsmbvBz%4V8Oqpd^TGOf}eiR z!M*Vf^H*qg>di-l4;CVf(7bj0CI0iRFdLLikg{c@rLCAzB$KG+-3g+po=P@`QXm5Dd z-A;uPwKbk?D9bqf-kpynH7@arh#Ci>USMmt>JLPlgQQ|Ih~H*pMTj9foXqu0X-Zfg z?OrGlJ|i^f`e@lk(Z|yO)#yo%r2HvzAvhEBpyI|>O0mdaP!eRdU#I`%N@zC?HQy=E z`#izJ3mLkhYQALiMn7yOeykMfWZf1a3n#)yq?W37~S^Xt}Qz%Rf2{M8dMSnqdU z?q2(D?MGSSPkR;d0&+cqeUGogQ{(_%T*L2xFw`pR zJiKPfQGeQf=X*p=u2`;Z1Zy+^2&y0*SZ=No^>=>g46Bi$(t-@6kQp-x}B$1+C}!MP-2`&?!Ez+I`D$aHV17? zI9{2?e+*XzG7(T15Rk}Slp4evyQCfMtQx5I=qZlIF4(6{=Fp{Ps&~6-`Upv1r+V?< zuAg2ps)mSjxW&jAF08t6KNrx))|R4EHeeKWDa)?`Si7r8=k`=9fPPQp<6y3bY@LeI zd+F}mJsquGRdt4~Nzn0a0}kzCbW*1eIVC&N7m5EY@o2P$yH`v`c%^&L@|%V5m;jB1 zUTSv%k!iEgeL?;f_E=C&l8w>&XCRWhr|)(u1o0#iQe=?F63Sc*hZUyi_cW4LA@8XG z+BB14J0BDjXhi_@&-#g{6QJ6*`nN1bav4!drABxlle(Jw2~r8J`{wf`St-SB5VEA% z$Fh~VkkPCAu#;Oj2(9Pru~IrCEd2`Jn%jc}4Mw=LXMTUF&h5>ertXqOSG@0bmE=91 z@?cqG$^PfWM+J=n-gxbg?G6+5n>TBX0^Y0Et&V6sDi(oTyJ#4(3Reclpuib}5*>bfnw z+f6t(5#ZOux=C=5`mNMoH~crU%Y(pWlBOW4Ke=?zVSbd#KPnpuLJiTj^lZhc3E}Z( z!|X=i&c7uU8{u>s0J+MVa1RGHWDzKiBb8*#_ODiR=kKCee-++Lh3SeCk^P|WpAt8ldtGW*~lKR#8aC>sg(_L0w^4K<1oQ1YR7bV)0D#v;pG zPeAh@^&m^&lKVtk0Gjp$KDkNW?8?0b0|}eUn-eSc+ZAVg?4=1G)1MaUYCf@Pi@2U+ zyA0iqot%l!>|XV#KX4rPJFX-ll3{M`zO<$?WCF#GrCz$rd1J16V?Wd;967H6KP&m- zBL%LPwGxyGuhTkoN1_^s9+AZ-dYq z@bb-8aVa$M{HA;6VI0m^L8qtuG0Z+dxo&9rNUMLu;v8geG+L)2id8W=})hSl9`DS2uqC}`xWvLW4p6E0!PwrAnRPz~@luZaweBh=?b zUh(OfBO`~T)hg{$8YI^-d9B5XgL1cH^8!Aeyr;|J&SD!yJ*jbjg9e(8ly;a8QdL^K z_S8|*C@p8R-p?vHh^<6Z^)=>>tRg3|8ezz^!o_q;@(~U90iaN3i$WV%y#3yXx#*Q{ zt-3cy@##_~<9rr+()pg~c2fKsFpt9Y>B31s$z&_2fzrZNKyPQZudgo=EWjK5DhhA6 zOQP51R@{MRrpa9nUQ+`8!kO!TyP=Rq3YC4HisQN;hRY0LfBZU_HhW<15#2XcHJ&i^ z77GnQN|LT)Z~WDV`22kyeBy5(?7HiwH844zPg0j}hA=(?K0Pq2!^vcGZDbyANshnv z+g{bWQeLa?+VYaEdBIC-l`Z(Rh-HI%nK^2+yER>gxy@*=l!bMw9XnQQ)?IUC^wBOm(KElbfdf$k?b4G+15Y~_6OnL0|25RnXsOSRNb z{N5lr(^jt~DgEBvsyNH2&yvbQ&wcz=e~P%*&V-76e6@;1vJ%)Pe>5N}=${Y$pDA*j z4~4%n4w6WyKR?eZytXb!BTK9!_btZ1GXAD**4~|sx#zT$4Le+NimF$%->5$^{QTid z%#*2zu!Qj6XBqnn5j~=shwOXD=Y_Z=HZ1#~h2 z8hc{KfEe?R7OsaGS`)p1HK%CqXn^-%f&GKz?H~7*LhMu96|2jPoiRnARQpKHamsq0 zruE_DO1r8|*-x`QD9b5+Ij5;%2cx5p;z@2;P@QB3lR~=B@0wtiF0L>6sm42MpLg?M zPk#2^7~rR8U&x(vKXkDu5G*poq_;4Lm1yNyJ)@nU5MAQ!MMG*LoFX(Vpk#!##@9cX zyhkZYG%C2Xio?In9=a-EUt#?wMB{gsP|8)HCTk1n^Mq?0rur^la!7ufjIbe`%_Ox) z4vL#`@tftwf@>Zv)f4IiC3>BdVJ+RZ6>O4g8c)oMrX#$_-&fN&?e|?Z_wxnNwLN2s z8XD3`fdF>)ACz|$l)`}d<0l!`Jt(U=kz3gGBnisbgI+NZ7#-X>Bp>b@t$v&Jrcbn;ZK#l?d20|Q< zR2Hr(qCmW$cl2?ST2I1anU;Sa!Yh0>6n77&Y0yF=9CV_?5|=r>>_a@e?IG^^hwW$4k-D6R6ne%{m)b?$Z)ulR@@p0Pf)!w)*}EDDE(%|aWBts zK`w)ap*y52G*I=L0<3YhC5rDy>Cm%^;a2@P7J#c^dUJPuJVecw=-%Z62D5y$ZOO--JYF7esC-uQ}+V;?w9Z_;Cz7*Kutr{fH?@iqb@ZUFaw_DmBSSw3wL&2u{ zCYvs!#|<9gTHwh7X3`dtvfiUkRY7u zm`t^T$lH=Nk`!%6ucYR^6VrS?Uyv3;0YV?PNLsH8y{6|&u+z7vQ?hs%9TJucuzaIe zFHzptr%_Y*vZ)(C3 zb5<(AxE~zi`f9vc#aDgk(!C0vmdK%V?@dvpOU6t>=Z>(v)%SZn~oC4PMNB zcO!iJu(laQQgmg2zB+sg#eggd>&O3$UygFSzaU|xwmx-wc zKIF}#C=*9I#HK7`9~{~l?JfnIuCyI}38+9uDd(FE*a|PD8G9ucL^?8p5k?tLh`Ynn z^D09UgE@JtOn%!`n^76<7O^jJMsK;{fgJ?mCWlSZ1LU1t~F_Y?|%&T?Vs0 z`-i@(XK~Uj@%p_dAd7CHy^H<1?8R*#^mrP?Aw7acL5++Y`DHDBv-!b`<~3lAenW8; z+{(U^%vy&y%WrmZbfak%3@%=LQGuLDFMt;3sl1A=BRC~h)|aGZ$%!EkXMTB;dH!sz z?XcVT33zL@75stjP3;Fj>&*CZ>oe!Fs94@2HYp0<@Y{wNDgH^?{>iBz$`IV~f+6th%L7u<=>8$?o@egTW`^0U(^wU+j zwgN&3n)iMxNro#6OZT8vVw{yy0cS^iypSM^kb#YK&3zuAN3?ZhRV$_4Dwf=XyH`q| zdwOvolMTje;4_6C9C4W=u(bA7WjT%Wj&|{-$SWzGaw!!AxQ=D0p#t+Y zU?b%fmqmqrM?#-QU}H$TQXl&ssj6-dc#$W$rfYL-);Y?o@+u^dgSZtfia*oX@HD8F z{fPeBn!8l4rJ>htS2l(9n7$P8RHPUJiYV&!a>HGf@6D5qUJ}@2Mw^MMLtSR0CF^=g z=76yZ<%UW2F?FpLMY=it1ewhUdFkKm4wfyeB?U9(OF;JCL-cBcJzU3uN)1WtShl`R z#<=RjbaY#!q02BF?nj&9t_~F537hIxS7MRIM+NB0DNInW{BaGk!RTo|F?h+eITcrc z{S;9swsg>^0R*@Ri6{(d;D7{xtmgo2w;DxX21#*hMKoHU-k73`Q7Ol>D^5)pNp!^V z!)~x9I?uZ<7x3Prbw2EvQt_SL>u}|w7tZcn#B9~P`Ab!ok_#~7-0&SSxr75&+T%tU zjV`_(_tmQ=?g+57(Q1)LaqQD>^@HY$1{Puc?+!Gm-R$ZQG*Fm{U>Ut+hJLvrH4vN6 zCpGUMvw-2#oqT%4amU=CQ=xk4RVZXfX8+U|;#d1tg+WO>pez_GAS1 zM=gjk5>wd4<}E(E2J;2NO~M1r=M64Yv+#48+btV%tu#mX3u}>DP4_6DiB5eUT1{!A zZIq}zd8jkP3$Zw3U4N62>Pp?QyJz*L(!_bI>@~fb{%A{CboCMkDL=P!p}OS zV$;H=pnxas(%`6)Yn>ur^H7c)nxOWNju0&n+-th9XqL>V;iH^;$nJOBMui~gsuuky z0`tmw>$U^O1axm`_K_-7MH}UjUC3ZG>gONTujEUJ&G>@1g{R2zI6 z-ts~kaDRDI!#f_qRSh44xwF3gq&u(5UhtZ|KvUHV*k-=0@|zt`qSbSO`w_S%9B*mY zIvh}XEP_?QY@Bn;lqfgQL|szNmriVrAW!zT?+%{6MzV~%aL>x?8bL8GA}5N}zvW(s z`V#Yk!1HZvlg~v#qJ8A!-zd(+ThCYyhwV2Kmm6&)lEuaxGw??0U*{s z#Ve=X)^VI|qZllwQ@r5{JQ>_jL?h0TT@uGGT-6{SHjgCU5kzg=Xl}=|twTk-#2T%b z-4+Wyc{X0Fn!915i=v0ATa@}Ro0S^2+l`8Gn)ywbwZkQ%1h47)rF9XTC2CbZKt?XA zV8_S#aw38h#pSHPJwDRkUOJ-@Wg-akYCI@?Du8zg+&^c)U8Gfx;>G}q;8;2tB@@23 z1a(LjQ-7#pTs%Cc8_@%Jaqk%`G*z?1z{u`;IqCD5G_4{~KhK$Ji3s;*z)Ddc z*M0@dP#ufuu>04r&GwdbDD*Tj-Gqu~Y+cV<(WtYAk&RqIslWebZ2VlqZR29W_(avP zwb75`%+Xv`;=$JOPn&(zm2rHcnMP8NxxNva>`VR`>wlMh{44pN*1y&;*u1+}E{})$6%5S8_fg8@KG`oArK?Y(5>=O2^%ea4@Eh+h zY0W+xeD52R^N-cqwb7&Y8QeU{xfA541|S4*7Vca^TcC!Ona68qmcjjNpv84__k+V2 z=(KkVRX=aO6uqpMau(2E7Tq#3F$@TfgAR9K>GwBDd{OY|Zf^#t*1MS=O7aqx%SGWI zm3$^B@Hz1JN_aZAr-gU$%_5;&P4Dd80}i=n*W(MI34 z*83xOz8v2b;2_@elWd{SdjubbQf=lRLgLsJEA*=w%SET~rZpu=wF*EZMRo;`g4zpr zoXC^>d_Tw44D0Ff45IFht<6$LyDh~Y87inTMqx;ZVnhT65biV95z(NW%nmP1?QWWI zS9dzzbHS4Bj<@I8>O>#i`kc@7+ngzvMfIU-js5W9tlv+d;;<8lWC35|4vSVnOM;_a z^~%S-qbSg^Jhb^C1sxI)Y03lnmfJwh#b3&p}Jouvy*i+cunNWvk+r!o2d zkPTY{1$ww8XhOpOxR#FOI1ji}o?yy2xl$VLPaOYc1LyfVO1!VG#00fdxmz+bG6z+I zjb=FMFX~!!Rc^ExQMcZsHszl?km$>@UdtjcIojp*K~YOA8@e-RNb&!;@iqAnIyn+w&%SOmPhbIp}Wb0ci38!y-z;LpWk20xkpJ zmkUatMAj+E7B*RNhM{w41d}+bIa#12CHz!I!9YEzj&=SY3M?=ldOB!LaFN4 zqKQDvD_xm3OrVkK`Qft0edGnOrED^_3s^za%;_AS?7P zQWcs8$q2}fX&EK~tZRgpF6MCV3cGJjyI#i=z_GJ*V~EqOl{-&_ef#N3^SZm0vs5b)>-|bBh7{`(9L~dha4FHMF5Xi+3re!h zLJW8aaW)7aV#3(8i+6DKWxOn#)J?QieIRDEKM;S`@{EIYqqMCfcVr+eSz`vAyMVBO zeWZ?Vwc)FyP(a187fQ0Le#NjDOrBx(w(Bnw6i=u)V%yml02 zUOkVZ@eSRc^#h6Bfq{50M617)m5cxj%syWDLPlKH0u*W!xTu2}Plnd}CVD>sPwxq8 z=#Z3DvpuBy_-WkOus?^cB6$IFhCz0E^gdOSzvX2iN;wEq=dZ0GgR&KI9r*|By|)gt8MSHMi@5NnLcHd z9mF`z6MacLCXw1+zR#J;?_? zH46(4V;3;&4A)z__3C#cZZm&t@uo03osEvvXa?z*4V63UY$=y@2|2Xo0$|v83AcGw zcT-*!wSu2=xl?w;QL(C6-yg(3p2D81NBOoC?kujy7ybUC_IcQb8U3@Zt|kY$FBL3Z zmJjdUvL3MYoGMW&)SuNUi4oP3cu2@K(D=9V4F z{mMkOS01iyY***A%Bxm7ne;lzfk&Obh`8j9G9S+O#+T2NVtKRv>=^FlXGHzY3lsMU z%(7sFi1%!aA>ZmUZ3O#Pxg}KW zHN17usd#H-O&qKCX%PCl=KkK)yTaZ?j{;Lgt~HjAaN)4~KaFDwJGmYwFZVaTR!d&0 zfu)`#={K)Z1&cnU8?15CLGP#$Z=Pw$V%gWY{T@g*-vUv=bM^SVHMPY{@EM6T^wmKN*X77Gp-UIXEhn7M zU4Peg@=W(k=#nC67=+6VvM`&tdnV90uX6pY+wFm0v4KJMqSUF>%GpiKw?F;BKRy_R z-JJbO&;~gV0jFZCWH2|6EP5|<*K1CkIymV0X&5#Eck1M=#65*R`K`e^uK3dCcmEK;sHde-1DlwXJFX61 zI+N|be6ZZVbb4oiqdyB@DBJCJ?yFN&lON60QBxQxx;wrJ0|<#C<{;5sgm^H_onx!26Y$Xdn@jOERip zN7;=Xwepi})*w3i2E9D(I?(xpPxwAxYJ(2h60((rh&lh(P^}UKM^uyF3F`g`)d;Rl zEa3)m`F)&A1$3~gh^y#)!oP_WB!vsbN{T31hKflER}GjOy?o;(l6OThn5u0-F=i>LvNw=jiI(cx6v;JaNa`6iEpF-8KOquPVRU{-|PTJ$0CL3^=|VJuI2thV)0 zhWD_Z?W|7m8d=_uj!g{@nk*y2)19tBzob9TL4kXX%b%cf+l$VuHcL`)4apxOw{O(+ zi6*PL-pZ?iv#WGU&XbNx%zb`(pOQaJkn%ZP?{seg>(pT2Q{mXh-R^o)`mrT_!ya4o zS#B<#bN+F zAS!DU9+cjK^1)~8Q|~$RJhA=~&hhbnCWCp4q~GcxyFJD6;vlukM;q-LTX&_BLvBiu zI$kEst4Qsj3!jJIZzMO-aaB|^IX_jZA2ba5qTE>SH5jpZ9a}l?67Bj*L$vw^6p|+s zI?L{?r%~LI#MUx!VyMFEtWNfDsYgRRNfgC$Uj|a6S39C*0@hLGR;0^t)J;|Q+MOF% zNlZ?j8gG#vNay_g=28Bmey??M+9fsRDDzuD^QXVs>VHW5{+0Ys>n{X??TKk5WmP=i zPOv}uA}0Zb(7upl-E^dzJ*?@-u+<^H(bYiol{mTce8b0iH^lsfr-ho#IQF#0g(Q3} zk7D-VQY>^GCa+2Q1r!KMdGu4g_lQMYGWpbJ6ya?6>HM~_?_vGT3e*M7KD;~;9}nU+ z(K61P6V&g<%BCKj^GS8A{hXhPs+m_@Aa`+mFS8WEVcCJyH!155*tv*L#66{XIgO~!I}IOK;$$%AQt#^4@}wa}!_7+hB?q{9?~#T z!MM>12+PhK=t44}y1d$Ho~K3~s$pOA0Bi8TIgcLu$F+k@NIS8%g>(tvOC*vI$?AX)r?s+W(d>={ z8yg0@Pq%gyLKW-Q!dvD_qBLzhO6F=r`mTHGZ^D2l}={LWU!ijDgZGz3U9+pDu$uxg$k z3?_I_2G4bV4kwIN;iOOSLyzDVB|Spw?OEAOdg0R`H3Gp9trXtgk?KH@&p6MKZvp69B z&hY-#*v7=@R9sx#=BS@HN$c<~m0b;`j{dfWh@)~j+%MXvh=E$vAT5QxX_J{I+RY}$ z`&G$&tLb~*N$&_6{U=;94NZ%iN4L;xEn6re^hNmo$t}s$9_@(%SD%feq?yp3q~#I+ zK=ua~6#vtVTmGsckzc}CP)^YiAbss$lkR|4#=&E5l1&0}lkL<$AqW5NEa-q|Gue*` z{L;twzKc7cH6@cLML*`Ts7?ygfi!Judmwz+!{GEt4=cun0jF$Az=KV-C*pumVZf#UUh$;EJK9Kzx6g`WW&KEukXt~C1gYq|5ks|C>YlFOc1O~ z=hC2A6DRw#Nbk_@J}5p*J}!#abFtheIo?O%&By1g4~n-fX5?kwR1gKQzY(UFr`Un- z6qzrm^ur?SdOznfG5%!dFs^Qfxc5$R6Vbfaie+4ZDJz8k_Nl`1i0FHB=Hnldak&)g z4;#zju(;H>@Aa>^jfRZ5+9bx6EEJpV-rP@fnWFGC#5@^<-ZhYceF{sI{NPPMKb-4W zb;|Rr=yr<<;>xCIqGP;1I~mrpeyGjMMMnhEJ?1Y!ipV@18SlEo_o$fI_Pq%F&in5~qC z40!v1wW*u#?t~4N0zK!_9-x0u)>AL@)mR5C1f-$2=AkCot(!e~Xm65YRb) z^Nm<2=Ejv5OfspzQhbm}6o#D)&p#U8}zaSegfEZp=Eyd5ISB5Y0QSc zimbpf{_}Q$eU2hlf2&*vve=UVkM275^qxN(U~pdZMpU4-)_Ge!P8H@ydcH>VD}Bg} zLKw|b8M~}5#(Ahm;c6`p@&kY}Z|#t+I7!A*A>kgG4ZB@(1LBM?KSxH7kZ`+FxE|6@ z4knO>94LRrr!qKw1mQWpFBeU1er!qld3?G@?gS2Vhz4d$Q}C@i+6$#|_hKI4;@vs; z&eI}`FAB~dwfRQcw&0_wT(>X+Az4OheKLPs6M3>4XD9Z@wKN0S9?ZceGY`%?1?%ZR zb|p9!h9{mMao!`aZIj*`0EPtHmDm*dC%9!Ro{d%c9l2tXUtUy4W$c1iDW7`6w z94!J%)*F%oTflZdPdAU>tO~Jy;U}NtA2<;F;~IM0{KC?g>{83**C`n2WEw$~5-HJ# zbACBPboVwkzsi%JDiVhCO!FhYJXd2&kfT4Y5mwo}e7%=Iglqe>8`yR8q{V~dEE_v! zbD`vwJ#+Yeuc7|x>!+*d%x$a{T7!qvIJr5278$vX8>3#{KD30bUKu~toG$tb$vl~M z`l{&9(n*Ps8bUEdo|2D` zZc6Q}?HeXfqw`)(q)5#Poxb!C6Np(L+ycYPDqpCnqQHUT&M8ODL&x_^C7_AG)g$ne z)AJ4cLyf@7_RWe3?zK>SA479vQuN_?326C`YcS@V-nK@)k#nAaF~YAZXRMqmPeNrw^tm+6QJVopCCJYq_kh8WK^aP+dtg?-In{-)<(*X6tQ! zomL$9&HrakQE$6Iy9%;B9lx0$cE;gln;^Fi3d}Y(0icgv&Uaqr;Fm3ON}wdxIlDAX za(#-;PnlGkGGEAk2SRgqI-Xx#d594BAo51$3DqqhxxA7;`<5v{geDXPGXbK-F+vHo za&iqZE~U!9PI2-9fAava)4Zq^7HAE1YzvW-lL@~nD*tsmNwpkuSap54MlAxjw8FeS zAj54}gYWrHS}vtM1Y~a~n8k|Z>=KX3D!%gJO0_|q4O-j=i47q#vEFjo^2|9gzbaH2 zjz5WN?UfN9TMltg}2jxnS4D&=w8YCXI`dNG!EXH=;@{Z`qFqHLr~WEh-*aT|_qHd<$$;>m|Gl^U*LOLN zDUq*?gwc=me<3a9sbeKKSucoJk0B&MDmcwp;Vtx>I9LFp>1Gb*N zuJ2BiTLRC8SAc-GTzv|$PU}DbIz?{|&NnHMC2yi0h2pxyFwHuFNWK5QMrQn6cyxQZ z2DiJ?z&j|8pB@49t#I4|Z`}GpB|!6HVxOh^RXpAyG5qP_Mgu`E$V<&iDKT}eV&-KfBb z#k~F?l`9lj+@c|A{J}{VJU~tdP}IocihnA3&Onbu8sRV_O5NQXy|L(SCI;Oa%55DY5Fo{x8woh5 zNeUqpW9g==S%BQ`O$9G47`%FDyOH_@Jt=HW#u(I7-c{n-+4V;jLI1AIU&cSeRP6th z1LoiS;7>ENn;&!uCMZzrJuAh#WL;z(_+Ov=`5%Y>`^!K0AQ6DrgAB7hLNE$a*7O$5 z1Bc`PQUty^mzcN!5!8gJs>!6|4A(y2<6Scv^d_Ymkoit3)Fh7AbI!3O2MV_xx>5{` z2$9mPch3ndE}VH6s6y>PFf>A$*8RTqQgUFKdx~zTktv=fmz6dhQWUHsj8A6gm-mV}2eGLTT z4*%~c+3zknPY4LEtB+cJy)2h5_c}=|c@7ZqL3pkV851oB+-|m;vjDJl45$lS# z-1neOv(Mg(k(l~L0sc*ipv%w~e;pP0ccq!XlK*M_Ye@1mhyCHd#w1^3C4TMR%Pez- z6T*$aDlE&hVlG=c!~rw2ggs2|6G_ms?TXc=RV7au<4T;cH9ngpQhl>1a zrw(acwtvFH!s7Iew03t~AT=rs^Fp`essH=ypMLm(e7~{kx{mt2XkvSclRoy93gSwB zH+paGszki`F-sAo0&Ml`C4%Qfp4eIe?NIx;Mu{93j1bi z3t&ZQs%h4~Hhdjl7L|n2M5xGo@a_Md?@~K-_u!23>h2xACl~&*!GZ6t58Vx9*7|Jr zGsyiFbNj%G!O3IB|GP{#R|lW0EjAa)Sje$7OnSA6?1jylVV@ zZS8|xY|)SMofndyN#<7%o?Sd5{{K&|>pN?YaICWf^|2l0Vf%8!dygK-EI-;*`ZRA- z7K|HK#i#+<+H1V8rT%}K)%~TBR;_v5Q+{f&JMzNP@4qzC`m5RQiSQh1D}YgRPvgK4 z!AYNd!(?9}qCzR4+lUMA7(5f0nw|^yGb|JzA{U=!d_7t1au}Hm9Z&=fT6os>2rsci z3Wdl;l*ARlHbP+@_IcnaF(n4z?A#VR%3SVY>5awO1oPKP;OS$36m%Fmx(9vWm}ZYJ zZ+*Af@S+Tnf`11X068bTqSgOe8K~%S=fD%W0V!on-Q1Mzo!$1y2 z){hv0CjH%@jI-Am#{g^`%-5gNIfl}KIK^Np&fgd-|vlXgkMg`T8k9rXtN$l)=pJ-{NG?c65|Wlyoj-$zeS zaAsoc;_3la4H?ixuNAV04@oa?<;2feFs2+aj&6-c7oZL^NGeP;bJLHMaE-_c#957^ z)I>VhCdB~#FxOO}r$xGVi;{$us-dD_qP>;d=8>bQ7KT+2uGCnfiG znTa>8aAm9y%`A4(`?*q{7HSW=80oMLiqDd1L$tcKMl7&Z%iGS%%wk#%XX!R-utg6$ z6eMy01Ed_FNz3I7!;sUawTwut{oKgC{84`0A)==&f3k!$2*ba#eV}_l-|(Ez7r~L;V={@=vP+%skwV2_a0MCw;oT@_OQ6l3 zYGhav4#kT9sw9P#4NIL`4XN(z#yN2FFV&;B_4hZnmYJGgYI3#%QanH4DWyF<;+UCH zj?@RlNy3gwE`x0biA!C3a&_mE-eOMA~vq7|zoV3M!3K*vBQgOxt&t!5j<(ydJb|D0zu& z>BP{2vhcC)bSv39=LyZ-4>j^EGUrMb z&mRj4N=I3}s1%{y;^V!%Y|#1Cg*J{~ zKt!>(#-$rxJmNyJ%2rE2g*K>NZHe5Ub{tVz`G5U!H*tii*P3c(<+|oPs1g_HDMwu_ zAe|QDgzm5jXqu-eH_Uc8+Su@wh`LoU2*qb!>TceEBbG(1HHlu3Ki=nq%}^Kq{%mXp zD>H@cXa!(tC6o+809bJUk%w1{l*6Hufrz!~hi9zPHQC$X%ef9XyWmqC|5N4UjiVID zN)F1FFQ)`rxUr3yQSyiiS%pUB;jg+$Wdjqg#};xve*SNZO3H=)49C0tkM(c5=+Kqy ze>Si`Q*Q404_MBQz1&Y|`r{g=?stMtvgglV6Tt0>JKvzs{-guE!D+n}FB4+5j#Wp= zoI1=srZn95ygzsipHXZ2>9*fg)8RFtr7h~>>p5ah4KE&?VuRPN+4M~EYu}WG&H4n< z{*{@eu6?7s{pNdb{3v4;)L13^#Rl0h=H?2*ZN&Jz+OpFYD z?P`yJ0SWuBRo-?)ct)IhE4&7#Zo%CKmabSll1SlD$Au_d^ zbd^nDC|6de(|I(rp{?|TlW_Zt0plS9B55K?)#IxXV2hIJRHq>>7FCc+8XKo7c^Sg8lP&(CCcmL_ z^8Q5CQMToL1$c^LKs3)~Lzy-PAR|PvSIF+ensB&P2tU*>?=v3In5bcaa~Gx-LU+^P z0!&m#mO?@db*{}xXKZ$Npth?{Gb5CyqU>V8dW4!!SAns(2_O%!e$@K7{M>Y-flY7< zR-_EkFhwX;XB0NEsauCF^Dcf>?c@YzRM`YridBS{BBgQ98a%cqJTNT)if&M0dM*n= zDyQ9FK<{{f0W}hZ$qAbxbKq@+b_J(SlUcNi#s(PHJWTR4Hs#@&$3AbmrCIGI4PT1c z@ln-ai+s0%=D(S5VgvG!gnTqyWjCN@*Nx?#)UQ71sC|Cb@%{siTfH&rITDbV!e64N z?t=K%YL6DF4b4U)N`2NLL6@I{Jt$eetP%(Z5?=ZPnDp~I6UYXhy>>v#&fl|)K31(K zn(~a-J5*$}$k#mG_hwe^w*js~QD@MuL? z&n6YARqo*KI`w|U8W4TCiq?Ej$B+V@uq?DLs6*I|wj7jbBHE*kieJT#lf}7B5xm9S zR`JZ*uQqARJrlA*vYn{~91K;lCzRm85O||K>$SPjzy8j(YY&O32#~vgP{;h6I{%AV z`QLO0{$ARDxBuoD@iS&B0w(@UZY8Vx(mps|k1Sx0Mu*#}HrhBC zc|>bi^-_9`O`91vvm6^%+vSy(xf`Hm>8I)49mnZmSevnNnV68&$$bfG`=93z!4MYN zfKwkUNg;9uHbsI+k*oAxmt~P43-1`UXY5x2p|I?F_6Pv&au2Riny^K)VKC62dnnaM zE}d%qO7t?*CT-6_8tqE60?_IL>;+u?2;`gs#M z?_##`3*j|tD?^6&fREk35vkZz?a54Z+>(rBm6aFj&`{V82DSHx(zZFhUdE5;4Cf_(F>_q97c)W_`8!d$4ZxnCa5Mt(3d17t9PB}9eVUk$T z9DGZETmyfvR%kUguYkBJBfRo9>|G5 zhFah0)w+MR^e6s$=6zM{j#Q%q^Ytp^pF~r4Kc6>WiOkGgE4kk2b^pDagURk(j*BTJ z?$!JEwE|8Smx?(3uJFJqYEqpoHQkYLd(iO4d0}tRrD=(F-I!?N#=+AQA*GV^ek+Eh zeyz{jp`%be>?+!1BwFA2od3>&>(_jRmPzJk? zNbwf80KvV2yK8{9IKka1ZE<%e6b%G|hX8@n;*bEvB}j3X;)T-vWuJ5IIcMK-zcbFg z<9@%sj6w2dgtgvez3W|b%{ia>JQGcv6vWKmWg<_vy+Gi04{W34+;^6T?z)#9fS5P_btgYPjk%Gzzvbwuvyf>hYK^>`jRYH?{7sP3O~dpBIL6ky06XX?JCdl`$DN zp3YCjQfEA#1d`5w5;(qWXv{C2-Y2r%X$Dk1?`gAdaWoiWFt5d3 z@u-hZkBaxQDZEA@gkd1e&sD2Chw;%jeRNR;BguNS5r#0=ZB-vU(pmIO#5%)7r%5@9 zvR;_`%N2XpocK3_C$E~p_-GWmGpwk9anWyq{)AD}lR!FW6=^I10Z?;Zd3U=@=5JKn9Tj-yGV zeQP&*&_92SUmEh_m1GUxgVH}_AFQw&VBvN^bZY$zN@c_RU?@@I4#9M2{n_Md0k zU-ngg9R;duwV+YoFh4-A03$v$H0x~*>-`tLeKlixix+KqXvB&jEVO<~69+&lj(z)Z zDaOvn(tjPUfC=E8qrvgk@HS=GZEyBvgpg@?d5wrJh}dPaIS$$8=hknmoZT_}$-0?J zRsn>m{#cb|ky)ri*;c8k-UvxsWzc!*JE33M&c~)^Iu!VM^G?!4orwFck^wj0=rxfy ztUl8^A&svg4H_0%k3J)_HTj--r~to%50STghVwy=N_nE2RhSdWu(6NPBrZD z=uHV$`UE|TuKf+Hxe(s)gq9*c8)tLpfjCoStIuO4B$F%nY->iuajib_zGH~2$=;E# zR1u<5IOT5|p9YVPUp{yZ8ABcYsBgPEtXcaKCudN5^XT(G zX562SLbO_)f}}WQJ^Wr>h^hY(g)TVrN&a=$cR%j^Y3Scwy^tf^E$DmknftlxdE%Ag zQme>N5BCPG_&VP~cNI&`GB42}iKzzTx2~oG!UdGE&nbdcF`hNApJI#Aug~}=L7(a-tk>Vg_DwfbJ zSuuB!C(W!d<1hk^C#~dre@K%5ewTH6RJSL<*=4nrH;DEN>g7h;clOjMWV#`gJa}tz zu$6&!sZf{8TUo0Qxd=1Z)-FHf282MFp?Xjm-lftrQ4nBI0EUp{Nae+X+pWHyIv`d| zJOQdUb#{7lebPEETU{+ABi)4I)86AiitQS6gX^YWzU1J0x!PIvd0ngt_^16hf-ma) zTAku!cBKYL!KzQBThqSfT9IiIZ%(kOo?~ep zw*g~~c2aBZXik1EnusdN)WzX`i9x^xF1B$N8`9TJ=#A277AT4rebl7he?G}L^NwaP zR;6&f#1PCs2{+_+)<{vy#^0p36oU8ZCe^My1LDwnZBg~}pw_XKnZK?@LAojq!j(8> zrF0H=F79I$5i*)m?*0Zr9J0gt3H=~a_;M^HHG)-vQlL#)jT<3kq)583muod3LE;_5%*UDf zJ)BvquRbm#`r^I|e<fbwnnG{{*N(7ubf&nePRktP1rMMynC|LQm8(dmc9 zO=&9M##HcA=2|^0_n~0T#MvvV+Ly`k4Ljbv&x_ue54N5N zx2lV68bYNs4PNH!B`ca;WZvJP*Wvw;NcmH(xmsPgla~|H^RyE5+v?J2RUfl_aBJ7l zio%ppe7EnN7uz0W`tGnga!W3NfK%Ttbtg{^KJw$A?jAhZOzLM>MEK7~+DqPsJfU1~ zYw0IoyQxhqru!wF#8lPyyl*hv+y6kXBlT0_N2$C&H~x=z_~Tkij|K~@e;gV7j+bhY z9QsToz&%;s@mXy0Pwz=T^4Gw1f3~3G#Ma_xcn`91r6iaX6&1LuP=7QRF9vf#M&=Wn z>tiWY0Hid~(4o-ehPg8$S$WM#8c{t&J`78dw1TTL>tKCdDAzOz`&WOMxk3q}IS_xR zB*tT-+pVeTT1AhvWI)+8#o7*TQB3J_k_j6>Cz*9=>IVCSq*OMJ@X9wu+;rv1cUHzI z6vR+5U?YvJ6~CUwdVDV&Dx4%AJf2KK3u0B-yXF+S`ao4FiAEsfxR^OUh2e{e&N+~n z^Pc3jVuyx7?zqgk)nk}{?fk{&$PDwU&>HjM!@Q$BFNBnVzD~ROR&~V-n6z4n1Q9Sy<45Q=0yE zbt-da|9piQhqu?41s-T8@(Hpz^P*z~@$ma(Sbp6xdAkg&nd|>1-t-^W;E&hasz2X< z^0vTZQgiowNVJbS(qWPt_(gmdd_y$CYd*Be75&x$b9YbjA8l^`w@B-L{xxj71X2Og z!VZ0dDs-f63t0NvGQ|b;BK*l8bhgEQvPzw0Xy4EFO#Hckv*VU4@x=;yqh>)ytzM@& z_s-6}p%4tx<27qamKox%-lyimE-Amfk3oYH8wvuS?s_$#7L_#dW|hC|Oz>XBCiu9qw#edm4Gr{CQq5le^3f&~$291;vPPi4t7vTp z*~6%DZzOnpbZ56KpsF_O_$mmOZ`>C;^a%LKqC#a2Y7ktQy}wM{ZR=L;EJb{B=ipTxmx_BMskY|JtQ=uBH6OG%!rqYlj>k+XhV%(e85yHd&BoZ2 zpzwq4k@342@!E_?tltjH|?FfJX|oXS59o}Z#WY=4;1S* zHBUtP@{@%kn|l}g1PG02&@Fvv>^!jnjvZNqbu0vzt%j95&m-+J8}bZ13o4?a(njnB z3mKif4cLO(I6VWJy!Cj@%L;zG-rypZGeJU!1;a}y(X(kLi4affxs5bG*(SA@(yRS4 zKcr`EhV#(PJf9ZFFBy@wu7ASzRL%S=Y|p+3TH5&|^{=&~jstMk?J5iiYhL1GU-?Wy zJE;m~`dKu8=}E}&6WXV2ioM;uH*@D}oc+f-WNS9rj7OA`v6t8aJzSa@%)jaqtbt2B zmv_XsoQeFpM^N-jbaP_*@(Jz#PlQLjF}D*s>V?SJPx{ZD$K;cTiPC3BX(6e-xH zoY@Qg=oBx=TGHP?_Dk`PhxrF)0m`2LEi+-vcqMi+_BL)1|Fz8K@M|txszw#A%ko1G z7R?s#p$b;p_!vXQY8JkM^{jMh*r{=ht?O*>0rS3)&|kP_A^bLyz?CxIXQ6&djL|0T zHOl()boE1Ny3V{*Ju`+ArojmHsGiy$w0sY*KuhspOoXR8T}(!_TmR)<*5-^cgd6vW z>-OekK`&DyiV_Tf<`cy-^^d9{!{hBV?aKe$0LJ4$>#(HIT(yBw!W%4&{$KUfgy-6qka zFRL|B=9g9cX42F~hugV?S!nYqa-vkANCgxO3{)~_s@c;YTr|XwTf4CXv%KfFN^4q8auyuG z^aDu;`cz3A*#%9eAq>^Dzhmw4G`XkUAV~G*R=XVDq)|8jSDuOgSFiYmm;oXom1HpF zSjSbyyamdPfBIKp+<&WVZ1UphALIIeKl)36`k(dygjdpgqsvzi$x6*f`ai0JUg|&= zg}m!k&IK{{&NIXB%ORkKBQGEQRgf0+5}r2qZil0K5u}yrqcF$B)eeoSOx?<;UI~i% zAwt@CwX)EF13YIn?A`N;GmGj9d@KCpv5c;5$Gre7xqP4$N{HcxEo&K_7ie~)pclQ{ zUF)E=QR<`Ry2+TTA#X>@aCP}cn2Q#s^4(?cyH7oXGBh&1M!}OTYi*v;3m%SgAj|gg zv9(#CFjDk8eS=gmgBIsLm0K%u`IWd$;i5aYUpL7k^TN6@n{ibdg(XU}WuZ@>Z^`QR zaK2HG8&c@DX9i$}mS*WrJKW#t+O%|*$!iM=1yuJ59t27~2P8BkLjuKH{EiRsN8T^)n$R2^ zUEd?y_wwdaM`*b+E-Bk`WgD0SAH`UG*fE>jkjZWF`E68um7a1LD3h@&cyP}}Zz5rz zL*1s`#PiqdGG^{>k1s$ndYaPOjW&Nfh`)5NdDB$z&u}qp&fD8l=X8Gto#p;3(An>J zWi?%`?>0Fim^}5rGT2xyeHnaq`RLcx5lQ)9A!pWx+c=TF++Q2&^?YCGc4il!P`8bw zU4Nu0;JSD&B&&B2>d5$Wgn2H|7tc1(2hxc-hjcPyFhA}^-4^kH>|H?i8b)$i@G$4j zGA%ZZ=bI=#v(F-lA$H080MzHdw6_g{F5u(1jzxbphdN?@Xtm;JA7D=UM|dw|{ZAee z*d;^kl3k_GsU;4c5dY=Oka5g0GiF4lXD}!XKl`}A>$dUVTP5;dCc2+ICa~)e>Thyg zMN6YXX&^sGSTHA;OXLNfkl_%t@fZMY{6W;v__t=b4sP6>Wvhu7POLjkR1@pbD`HT81Hd>8YLpZ^RI`6&q zHz46l3YfwxGB>`_7QU(N#^$&$#p65Ftkj(3yDFuh6QaH^! z70*t26LdAgVW8t_Np)^E9MwxSB~iZ2={g2j=(4a9Z#Pv@x& zOoIiXy2v${wF#e6EMG9AP>hE}{SP`;6}J>Hn-*GnUIhWpLD>LZo2+P}tL+#a4&66a z4_!3qRH_1z`+?k;63gHK5k$l}gmWhAt%g|u?+95_h;U;DP;vWE#=b8^j^H{>!ig^-qN;RKM6(rl&oyjmz3jFSTrS7gU zI8QQN(uAO+Bs%pI~4>$PHzIYS#kb-1P`>0|O03dcC9 z*4cQty$KeY_F>Mn^T=&r+RpT6xu{O6-B@?)(h5}p>_0)GnRH8^Dw|T+gTSg-Qy(s( zm(lj7TG7h7%Kevd5$u9uYBcU0)Ls#vjG~PfqQt1!mIzC9ozHhKSfh3W*hs_4n)Pww zU=)wPR(SOTv+U!Q6T0Mg%b@hr?y4rkE*d&56LC5e!#_PUCX=mAs8-0}Xh<+$*={b_Jfk2CAZfvp^HD0=OCyLXLlxWTLL`bFgMDOw&B zDA}cE-|J+SkUx7V+Ng&rFRF$WhU!7B-^(~h!c59fR@N7#DHlX^Xd+wc%FFB+4Zi%i z>X&UsS}PU2zC3?8Q8u-=!a!Ty-Ftd$InK7(H`0ej+0I9*4pl4z0y9~Bf-n~9aT9^c zKYXsmNEdSwB(^;G4M=oK$vC4%Vv|NfLj-1)iahNRCf zlu?PV709C(CAjbObD^;AQ99-LSgGyaVz+<=dt0U{37Ylbjy zqQ?jfFVxtmKyj!QZP?~B-CP#5`vIkvNTXLkN^$@Fv7X^{t3a(r(Yb-~I*?xjz8Ht~ z9XWeGixJ1M+rH9n9#dB@( z(EyaF&-IhC!)Ln5&N*6jeKUNzd$&p@Pi6;jCh_^bM7JU78HoDMuwf%O+MS}TBj%Vy z#!mbMDZEHD)6rP{Q`V_Q7Pb3B!0KUX;HlRCWgm$D>rW;qW(06)jXkQaSyz4g##571cBWhoR_ zL-C#QL&VogLH7P_<3?17chErVka=JIu+VQ%-EcM&M(gJiCMA5K#$Cnmak=_~N-X{k zQe(u@1X+r35Q;NYAiYGD;(R9q?wLloDZ-o&Coo96l2=-7q%Mfb%+d?fVC|0++vxcE zZp>maKbot2zS&W&XqKXKxY*U)H#i{KTH7^S)C(gWr4B1JZze3T|5_dGyIrSQDZyUI zpvUFf8{B-*!N5b3Sm`D0ewAxwP;D=GboH$bfC_l$GcT^7+QKf^R(?tp`H-(oI9djs zu~Gb0pvWqjuadne+kK`v&%b%7aH7z9hy0Ca&8eh&%5;l^;ZT4j8FNRtu}sj{yu#7K z1q5x+Sv3ms!X3YA}IC4Tw{nQE27K(=_TzS?Z{agg^vRLP-Vj3Ncbt6K}$Yk1AILvY9;{<{cq@Thp zjXB5LG)Vqf`Xy>Afo37YB1uwqim|7~H=U{n(Hcm}ykJ0AL%L7Jul~G|O^Aa?Pc72T z6vsPVaiU+H;Xh5TA-&CcOv*6nlzY6WUO;gf{C3XeMXX}3PNMfLwM+wZCh3al9MZ;s zrfO_CUlh=JtpV*mYG$o{{}+zKiWdv z^S$HZ`Opez`azV%n;RrBtRllXZ^MqUhIjF%+!pNpd8<3`c8`-%r`llNq)T0d_mu)+ zgZJ!R*{xdc9#34xbk;jJWH=O=xPkJ0KHDbM$)4}ol z_kp%hEhH3OYNofH^(I*VDHZ|t@ZQnS`B^@7J!+p0wz5@ArPa;xkyKAx(N(Zi};7adDY$v2uCgehLWA-_WoXP8Qe#_v|j*Gtt1 z{kb%@6&SXwELe$^3sR}AJwOKPAM9~gEQo4AUoT} z{9(CcgqmS zUhc_j&vX^4t4zyIwM6YL1J!tTc|Q-ZW{+8sW26I7T&f$v+=?vSw7}v{H_E~~26wIQ zA4EE#=Pql9OFiFU=-xf(py}6GR39(?BATfk$rY6#?nH56DK)mS^QijGfXW=9CA?1e z%b+cnMV8u!L@ULI6W{AY7oW`g5_wCKAa9{=EqrjA-jB7MY(7X|3GY196pqTcktBKP z|I%y08}LZ86d&0jY}USC1?s3RepHQ-=zKi$N^%>zXj~Iz0K-V*_N!x1Jsw>yFVJA3 zt07ZswaRJEo{D?<#AON(`$WD?uLA%Dqbqc@XYrdCNBDhH(4uuCAMD9hbT;YT2Nj`0 z_(aC-b@w9bxQr`Y=Y7r@rky9=T%WU4l;;hGMe+42f!H$Ate=Y};x~F$I^1hXa&FW4 zf|6ZJcf)DS{z7+yJ{3N1tplIKbinCz&dA8dR-0RmF4flDa`BXkWiW36s5mBsflmtd zBFE4R&_hcZ%eS8Ev-~RdiZb2CGWe|c%JuGS?@x(N?0KD5iS~Db!y@$}rN)&}2Ut~S zwy~{gsPpx|3i7w2kGR(kR0) zx)V|$KMDAR#|Loch|UzuWH)Em(9L`ae_rv`(QEc0x7UxOH$xu)scP}8X{p-If7pY& zG(pF2gPseRyt)H^rTDfei5873ZzEQ_e#4|F_S50XGn0gOiRpwpC-cy^9KlS_eZ~K4 zD{{LGlE9HJJ8<%?lG;~sh`ArNar?yZ!{7Xc(7*Z%|7A>qpmPU^9xh9bM=-TAZ^p+XCV${re5?FupUaF?y%$&QAY9xP|2Y9(kC z_9(BJd7N|deUUn3g%pxw?bRX1g1b>n)2@}OBRl}_j`PDa?`UGHrf2fyT?*x64GOdy z*xF^;R%x>p{4=0xscHd`oM2#g3mXTObOoywoRmkjZiH1)xO9|#`)ztnJugV?EO;|N!RT#7{eX2nlEq|--v78$w@ws`2abxv> zNb4ExZ04HIRg!ict)bu$NH`lZy6M)+LUURqccp^+Wrm z4oM*hyE+Tco^g?Zb;r(JXRa_q&IZF)LGCShQ?@f8YQM__ZDYNvSVA86{%n=VR}A2_ zeOAextdnb;`m*uOL}j&L<*#C@Tyl7N(aICa@uW5RawT?#tY&-nisY`_z6L}6f`tRf5{^zA$)MvRC@fE5 z*5ORCR?0q?5OaOH!8a2iCFU+3J=i{%O-mfDGGwxUMv&;)>zSz=ukLcH1h-6;lG&Lz zQ_4JzkKyX&O0d_M>0YtoAv!+KX~2x+&enQY>7is5)4g5QxgIL}RsuwNmnz`4X z3_h2VN42hwB>j|<=RrV#fLPycnD~*NbYpqk$%t)Gw(lJw7yp+xTfK%f4s3P}D^0GC zisFYe+P6oTco@=#KiOp{f@E@$@hD#)eX}s14t)j(XwNQ_pV7?hgHOz*yf=bRC$2NR z_Z*^-`L@x@lC9D}{Kc>kkZj=Ln-9Dfcs3bFwA2|U>y0!CLg7NW2$TtNowQ(~uIGp# z%i7-6y8&X??=LDdy4F^o(z_4#FDE`Rp;E}OK_#g^rQM9om(+6bTodKW>(%EVf1{l^ zbslOY))@D)^}_D4xnm~$sT0Md;pw`SYAR&@GEDKk<8{i>FUu#{syUuCK_Ceamz8re zr-y2ugGlLFoa`sTks{2kQF_36-`!6<*1nTR4YS!(z{L1Vc816?ZeJ$PV%P)!d6VZz z)D6G-Ls%c03x2I1jqKkMzH8!#IC4n}YV`dB!~p z`<7~v(Tc}JzLPwcjXB;m0n4Q)r7{q&dBuuv<^fbs3Ut>&ZtG@g0TD#IYDkOdTX7W$ z4b0C>#|FMOS{}-yh!5r{$6vqRXQ4mZN!Qb))84OKedGdW=a~`ir)mN&iAM)7`YI-F zst0>df0vC6?2ndwpfwnxZ)Bk5oiXPCrJ^&77ZUhD>dt7e8gY7sIPJ-g%)y_Vk`~*) zKcn-!y)uA%!jZhD)8`h{h)3KCjEUBDrqF$*fl+x9&1FB9_kpb4>kHz$kW$bKgiH2V z1@)vF$uthv7~!=g-v0I(L9S6B)|ZZtXXjVno=FE^xIt0tBw*(BN?1{Qk6c*TI&I@4 zgQwHVLJy>Cw!y(wb8J2kw@^74?S}Y;g7J^~;}T^Bh1Wvl2S5)@q|!`$KYJD{4eLg= z;7AxI)Vk?cR+g{Z)~>7lenJ|(XUj+6Ym-x=hKEkroKcvC2nzY2F}fAlx|GyebM@Xh z)lQ>mp}s;_6||rYMKfnI5IKrwP$`{uA&ML_69X*2)-G1?eM2QjQ^J{?1J`%h(CW3{ z2``H4z&dFi}qpe2-zWxFG_n* z14#(is74U-jN9nx-B%Xa=}^qG8ojvd=K6?BOrb8}w4J49jy0Ejsn3kdlZe}CxtGeo z-kinF^gNvVXN8`%_JQL;ksV>3sbfS|3~eU)(^}-BSCJ87-ak^DoumU zE30!?=sqx`-MD2xx|v6@bZn+kCt8e=R{NWr%Sp1EWwdcxy?y{}E?QxkmEJ1QgtpN3 z>+g8#s(i8fL^+w<7!>yzDw6`f`?Y#k5b3JJ2VzfrbpJaCF*o&{c1)3K1Y)izGT2?GFv;4gc0artW*k05-ABte6Lfx&bEM^d{B&=r`#>w;sT^B9n;L5r!e^32qTKFwUiV%f^~t8t6+4x{ve0DHy-%9&v!XwD z#&$J1*VL+*5Ar@$+%013bQ2|A9TQyQwoMM^u$Vd83N>d z+1cmP?-@EK>b{=O%Jh{BC)7(@7t*kteIFI22KJtKXk`B-K0x+$dqGS+KS+x{HPNV4 z&^$GAW+Dchft=64n| zXV~2M_PVpP-o(}kNA%=9X!LULi8+(qs*`psTK=h=QJNi1{fkbgq%&ao`$RXdNPW?G zcBJuev~q>`&y0y<5%L$w^K-WLdyA~v*e-Q}K0?vByP=n<#Uz1Bt!HvX+x)XL&))WZ z;F=qzHg7r|>@)oCp|E*}`VP3pgX0Pz(=@A_{4ibNX_n}Lvo}u@Bo%?IH zgRN6%^RsKd4-95HUN5Ac+m%n4?0NKvp<(zp(;pA?fa>$SAaQ_vX&N~{BW+05jJ^wf{Ks~cn3 z0+w@foLgMxjTAJL^>B=W_LR9fFsEXx#Io#{AGGtzOhu^bF9l!FB-6$U4htK#4?7=v zE0`2W_sKDcTYCs}Q5NQ19)q!dBU7DV}t%$#JT2KxeGT*|jIqO>cY5 zx_&%D#q?|XQ$iU78lKlg%DBt__eUR-HgST?HfaKRtOJX!W2FJPV%3@Qq^gZXc~lxs zbMxF^G!)f6#vC^9mt256nEEz4t`#CfdPg&As69aCou!`B^fyZ<6M*d6APc|Vg!`k% z^QO$LD->Z8sbP;b3gRfRqSX^c$Q`k8QENw%nCt0uut&9W)tug3WxEo>W(<~W)q@}` zdawW3<5Hj8#DO&VW11p42L;YAmAYaOoNePelR6VQhklJ&vvdyi;PxJ_7<1`!I3ZQA zKEQ^MM`z8&a;~#BYf^FwJtxsv@lGem3|0!)?A{sDJT0B(9H&7Y3_2UW^D6o{VOt?4 zv(0eN19Tx%m7!it&#X(&DjKl0JMbbF7b{9~??lP}?F-aD`Z+6fgxOWL$ir4J8N!k)^wS8;9OC;}U8v^gv54g)5WT_<^r z!u$+!;u{3vx*Z$}k?Ms~dJ*Z0g&kni({hI!Ud`PhZ<>y&@~^kx;wampT=|Om)3)a* z@Hqf$jN-j28H`7&XPSf{*a6-!o2v}mx7drg>Gs-#@XS_Rh)SpOOdGgIkDu~U4;O^zp-hd81f@em5Uri_)1C)8Nq zZ$+|^sXrf+PF_(%j8VD6dgQ;xvmVTN{e33k-Tn9ZWPA}aj7G#Y5^zQ|D&|VX?i>Cp z6FEKmUS;-MGLixT0wzf6NW*pka{FJsbYT4fL;+%9_z2t>mG4ie{4+rQVwvn934$Kr zVqbQJfoFyad6BgO#thVOM&Q=xlzt_BEZuP6aleNKD#N8P?`G!bVK^o`QjsZM1Pgf6 zpt0R2dyn4Ge{+_3KW1v2p}v~OYG~JP7CTZg2zbe4* z3;yBxjU+vY1%w3!hT?n+kfQSDJ*vD|mU(LiUZb&6Va6I)yK?e)`m|kMwCszpuZ+h( zR%pU_*0QD0d0{IR396|ZLLEBcFCX;(ju*p*WsBo^Sk*u|Ej6Cr^dn%LO}@s~l8C(N zgU%*ob#4AuZSK6yKwmGAhjT4@4TsQFn%bOuY~0Wqf75xmW<_58Dg4$fChi!E%H_X@ zd5LJB62hW)HZva%KLIURy>;pk2t|tbj?Z??CJ~Am&t_7YCs@peHa%lv7V5u~zHvO# z(Aa{Td+E}17aauVc6;&9_$1=(u(6E}J3l#3n*K;X^!+LQQ24LX53&w5NIK5n0^4kA zJ33tTh_B0V06^1A31vR!qJj{svfv{+-9I@=ua0){1Mu)Kj88^{MlxkeYoqGd`f-2w zP-e6dACj53xn3)o8PHRiG5nm#Ulf8lmL3rt2~lc8H2+Yu{YEX?R?IHK$nzmAsbqD4>DZ4Zr?JP#w>m#^a*NCOb%Fy&u1?fC)4=F_YIK zqI^5kXG~CbfF`-}8AJz{f^Yo%zyYVP!5eo$lle3oH|O^^v42$bIJnbnE{)i+FJ3;# zvktOWH2J;;k71G7Pz9_7660MRvLP+igy#G?z-ltr4?f-ArpYjIr%h}sW-$y>f+yRd zlOBXO__CY7=f$OdkV&_tk6DjiNny`cKp+IB#0sMNLkh)hfNAr66j&Is~ra={Z4 zTC}xRR7DG+1$m<|NSb6uv(NO3W=b6m=mNf=ppW$ado0+-sHpREU&zWn6)03Has_dS+)(=v_A8WrZLtoc_BAobyV^>mmB9d{u`Q<d8cfg z>*d(q-T0+`qqlcx-C*`N35|I47v8E)+eBYpohRMR{_dXO7`YoU)z}c83txfkb zsi29R_D=niFOY2F!rA`qJFVE9K|yAwqClcOM{6G;3t0E>c=x=neRs@uoM)g~Euzeo zx!6<>_)d$#d7k7#fU}Un%8$B>Z|5d3{$FrAxHF`hivK|<7HQ{Y7N%eF<<%V_74#6h#lkY*S+LU>5JVsY_o1DFUh zz>?%L5p8GooPavf)st|2$H&25+DDp{{Peg)eD3s1NliMVC&-epSXHD^(kkuq^y696 zOrp8CkxW9lV@T{&#d^2X@I#AZhsSmil-$l;@?AU5iA6HEPI?G!>WcF<N@gw9v0}L zg)AL+9XKyfwccU>lqkuZajwVq;_N=yo19WFO;weS zwE6Qtrdg1X;DBi!7weeqVnfvOqpCdYv<*)%!LoOWJsWS_)tFF!7&y;r7~}OLAATx- zs`n-DY3BlEBd&zgvZmO(uf#l)%6Ya>=Gr*ZyuBgFhoF8OKjd$$}I zS9Y)v8@HTuax)r~3Fr}R=mLOz*(utz`*$gXPh|Y%7h$s%AkgW?K z9kM7<>bLglz1NR+&rlQ;$5<=X_Q%EYHt-(zN5%4=yyQMdagdBBulGCohP8y9%U4s*)C^ebw`jYe5dT;>`$Hf6^|ldZ%L2?{0e zbGM5Z{p4Y`wf}7r?)jkJTk)MNo6L)Bgu9zNy1Y%v-<|j_F~#)DP$L%Hvd(00WW=`b zuxPdh)Osp$Ap1s?Bke~Di+j*E@gPj%D*e96hJ4WM_b9lk!Zevr5Z>TMr{w$vqyI@# zH&p4FZgY|el?}2<0HOTdStc8&(AO4mYhpvOm@lZ8%^+x^QfcFva(Bhr`)p;F&DG7- zku+ad#M5!l@4V;s=n3n)?znZW}xA7^@L`k0zSIa-u2)>Ny`WKJ| zneDm;I?lV@#yk-czoxc(mIWAWSB3`{IDV2=pHBB*N8ARR|G|ZhucJ|}V#!VCprZP4 z?>)0FIatQ`K92qm@R8@LMr>vDO!z94!6^5;{Z&rzbJEJ8%f?_0*^hS(Hh!AQmKA8< zhMj}}nDn&D@hAN|s1hrn6L>pqOR-85<2!iX7Op+TI}T@flK($+WSC=Z)A^)!U|Udyb(dvOyxQYqKTB4~BFfd>Z{7 z@00Q`ktcVeE(#<-ImonR^l-$*#c?gfrcH{Rx2}}u*jn$*=Zd)raGAH5uuySJ_PQnf=dVn~pCb?nv1&&!EPj#q)^;~)>g=OQ24cuq zLGeT6#A3;uKup0cuCZ_Q_M;>plBuNlhi~}rr0uqq@>gLn7=OM2DKTttn$tqT%*GT9 zJcAWdbJVc(TSb_ZaTb@oRg^5O2{ba_)t}ocW0r|EM+Pirn3%EInol!)^bKy%sXu@M zTB}-xE=UTDJ$Mj-mKE%e;syd@^?c}5gVW%whXg8y4ni!)>7zai?kda<_R(MDRs zNID(cR2CLCGHdHVWg*;_B1pcc5@vo8Grcey?b~)K+-i;fbOA><^U(+o@``Ssf~^qu zWAwraQtzY*4?ap!Vav{_!vzRK#ScqBG2nDtu+uQoP)IuJVw{C>b+!!|x{9wF=xPDd zT6r{(vH0ylyXXZ@*Dx!IG&gYNcRY;pU5)ndZ#P(Pmn~j)oRH&>y9T}b5skNv{KWsW zJJbuiME%S1xuo-9?C*HMCk+3x?Jeq8-pXn_QaJeuTFl&h;zX` zld*Faiyao>*P-+sLV1c9JpMNDt@w@0h+R;V%c3y2l1$c4cL*pklAJ7;$ z8^S=RJ~=DI_}V%9oKiL;NIYVw@&wpd12;#zj}Do2L6fPP7W!saWWUW9iJ|ryD~rR< z_{kxVNHO8+{yScrARq<+1K_k)W@m9ad}dx1m?p-+K!!qYgO4(O z7}oA%o$_e&1kKMW;SwcHxZU6qdRXq!eLcgcx5j7CF27j#@p{SkAquT>fyC%czVlyZ z^^fO|^Bekm*^yJ(>qvfeTpjHF{2kAUR?{0N|7)=UtIInaH)N%itNKdmHc`t3JTq_q zeWzZ=q2Xw!(0}kv%~v>4N>VL?n0Yj+Ds4jcQ3MF^9PZ#VW0=lhQ3)|h%Gu(?#KXJi=xD9_hldX0YR zVCWWCf|YF0=@{47}-rOly@!XH?kDyX~{XzFNcR2Tl1lE25iNH7r4n z_G1%0y8r^^DM7&}9l$U@IC~k4)k(CS30~A)x{^GaQ>5$xYXia&vcGKuJ=wu0V zU~Ob{5L&$D!zo75+8}x=WxJK@q3Ydyv>#0>i4C1PC~$qNaB1wqyWEu_#}=Au>#Pw)9iE=0;?)z7)e5vjpxbD6!<3p;nI zQUy>g_KQwBR`bVujt7(#z?r=-DBD?TGd0z~vFR^8mUkwZ6Baroez=eoh5^}nWS7CB zs)pY_!bW#}ey-~tsNU&vGSD6;r!QWhAnZXJgM~}z>TIM`s^y>)xzTL(Lr9Gj=LtwX ziM&#hHkA^NP#4{h5yCiiL`_|ue%ZKVV`+}?>@GH9@?pEx!aY~rTWE&UuI5GIP(1Bg z3fwC>*qHvgu-${rsh!Q*_X+Y2Zfi26UJ_|P>dZmp-}K)MKqsE|JDXPb=4<7Q{~zw& zGpwn7UHb){qS6$Q5~_qI2q>W=paP*6Aq1osMsPoNQd+)i{I`6smS!=!fd^qRZ;JPx#l?=wejOV%U-_3Bh4+c)2^}dO?{-GyC z>CgA!tD6W<5)k{t9qP+jweQRSK11*?*^ZNX`7~zdQZS~gM}}|rYG3aqKaNu;xBiRS zQ!zm5dk}XPY;3U4X?*M>SUfX!B|)uYt`Z}JiK=7Jk^N=R(vugfvi#~`iNbs>UjUnE zEE6Mr4{ta~NLz<*&L4;oSB86XG1jgl);|q9H}R6%`i~A6=wu@E08yEd!x>2f;K6+C z%RE<|)(Np63E#S7IOy_nyh}$Hs!Qwa;e)JA8BPTletC}G$RWRjf&C7f>#u%tvr2Ck zdcX$(LtW`; zc?QX(YOi9lO5!7eKMY{Sd$1;SYkhVdS1Pi+jg%(m{1vRVD!K&A5?GTUDcrY>;(WGf zYdX|8T(6??%DVDys+c6l;z9~}G?D;uRv;&%dAKGTsGV#zHQ<2d5mhg8J|skJeeP0 zt>WzhO9r-|Z=O6T^#v{yFU-QRE(hHp5toR1TmZF+D`KHqq9d-i*JJ}5lbL{%W5VnO zR`?S;I)*h5SglBJG71y} z1nqEzuo%cT;Wt_I_zkyAczf!PdWey0IWL?GTO$R(XGr zL15oiJcYYuELinS)duW#HpJ342l>IsSV}eZ#$A`3b<5HoTxo1-P_q1Ygd2C1QmdwS z`q)m!I(3&QB+M%gHiPB+TY$Hq3{+CM7@(x*nU-OaZ3>UY{ zK3TUt$Ue=}M>a^lL*R4h%BR%h-?9Li<~2MSKUurd%RZk}R(~DN-MRmdthvhn&YoW( z70hAyKvw%dqBkBh{h~E^{AuWCP4ZPZ$6pi2=#;-l{BZi%N^Wp9Z~j)9!D_?7EhgQ! zPiwd!GJxPOn;8|`<`J&a_RG)>)lx#eBp9WOoSFB_Q%4exu@Sb`1d3!L`n%q7U zm%JytR}{=*!bFo12(4)3xDxV?q++&q?sJ)0}ha!i~N-2Z&QlmaJpkn4NhCcIv@#agyG%VW3j*Ct|R-aA@I zyYf7V?23a_gT9ols7jbI|3oXJ=hC#!i}0dm9|}{)#D8ZqkmITO;^xh!o+F(0{v-`B z={~txIXA1|SZ32R(topBl&1GJ1Y>Y;c?YG1`#`FS$Ev@L%ydyJvs!_M-@mPEc;&u ztq9*CUX3weU%dzwd;w!|>iyR6qi8fZ3P71WdUr!t8UB=Y*3JAasv=uGhE)BU=oc|h z5Ux=`)&6DHp-2NH0Z?*X$&)>?$tWa}Ph=aJjt1n})kdbP1ez(gG+(J)j-6*DmW$hH zQ{QO6%-SsfHX@+v{IWqJI!1Cw4nA3b-wnFoh_<0e!@>zc8HFM#(XW%&UittWn~0;E*X^ckY=+pz_8!IaKU{GY zu$Dx{+>sM`4Tut_Dm_gzTD1q`oz#V+%`<6|KaWHrc&#_US}bXy{?ANakvomMz=J?b z-DS$mF5gCAuk7^NVioawWzrO4^bMv(s*P2wHR$fA?^uQCY~_}3cH2tKay_FtFR=li z7&c0@G>b_y?)&$CeuTe;nC#EC8yXEJmHO&MjFNu8lPxv;aaUNlZd-J^(b?K3Y24Hf z$R0g*qk>Vf)nJtwf)XqLu$+f9R=r|fC!le$N)!KXN?OZZqm;Xa^^@Et6M0F^RO-$Gt*%I1B^Tsj-#pwxx4{f;mYR7yJ1(<@QZFrl zu~3C4PHZzJ2;6?R0;z|g0*P#1x=6i|DTeB7wtMyO&AN9i8WF$3p0(~>3I6Fq-zoaT9Zg<(kY0h!gV{{K=l(*&H zOKVU|qAl-e8;;QKk4*03tACHxZsz+^(R*TQ@q(Hz#Mj16X(Vls!zF8A1!HVhI5uHw z!j0<5B!#J8(YB~PHtVER&8>f{Z$zQqp&2i^Y2#;hcI3XiCbxwi&ntnV#rIpIz_pt! zzq`C(TC*l1Hu@GawBK8Lu_YN;Sb*K53M3-bbxJ2g1=S&N1NuUx!>Ol8x-3SFeXcEX z)sNF8WcfzzjvWtaU70_4@QB@; z_8}&g*c2AZIz7A1X;}SDk9^7&d|B~xHH=!~9O;c*LzLr%0%I;k+c^`u- zwv2K9Vvb1THYj2>;Y%utJsjAp6!VM_RvcbbS^iiXnGk5#Qg!^;t3Ae9uW6wTeuy?C zNTmg7#I`A(_<6~-Y|6F8QSjY-m?mm5#@V2Q*fcy2z)6a@3>s-SrjRs_K{Us?9mbsY z3vJttH`C&tcc|Z*A8$Byz8_5}c(PT9f(=(G#nHD|VxA6qP2VtuLV**pb;6^X)UrR> zt1ral*Oad#C_>wf?40PB`B(7vW{CJUT=AG-2Hz4r*sq=jDk!z4i>E`PsEYG#SEaM$ zc6!9OhQj=H^$VeEg;ekiEiZY^riXbpMyzv9>#{!6Up5abO&(g0^2n_AD_z0Fb_(I2 zx1TT=dL_vaLKA1QTp6vQu0HHz_a=4xvClfE5ABwU{FUi2R83Z&o9v#8m#EwuHOex) zXIv+FVOBY=E5w>U+N;USRDCUdx28&7u^xV!`_s|F2t4u>Jy2*=D(&(Sir;!DRJ)PE z8OT^|7{g{Uo$#*L98jOzbO$zJ@RserhQskdWCO|dz9CM|_CTDkwuNJI5oX$vVPb0G zVj3;+0O}~od%~ouhPO(*sgO5-3nA<%-`C!Bd+cN2a?uFGO>CRvd8SGR-VpG1^!Yl$ z5#(WQ`Q)DZQ0er6$WX1#+PjgdlbF=22`4fvI?PNi--Y(TB}*M;9wQBvH<-31sovyu zy1G>D4o$51rY%hcmo;>v44ssJw(bUrWu(__n_P~9_ebSYAjBij5%-ZVg zlfO|pM?c=J$~6wTK00UKapltW#~rmVhp*p~&wf-o>Sy-!>$83_>q&k|8}eUwmW=G5 zXLh;ODg1|v;SaL!6Qe51$3NASJBuFznAj|f1ERA=xLnKhdYorBwv|3o1P*;nEx){0 z-_S*P@|W_{3#Yad4D~58gS4w45v0Z|s$hTv#8I4oGeA?evO1%zY@6ee?yF z=bX&5kv`v7Qgjh7t zT1>&I;1wxC!G=eq9v)j#7Bw6p{Q%Zen_Kp+LpsjwzP-E9kC3OW zVHwH7*xgW7`PebpvIK}e0N^YJ^^888#eWS?2K7HArui{_pV#z$hX)Xs0Wm3KHzr)2 zRz^cc17h(zJDxsWos!=x{41b04Brm)#N;H{TawE;4c|1jK(7g@nThJ|JqUP(7YZ<) z+oEoWJfhiUfk<`W6jmRAi>?|D$5@@7dQuAH6cr;1 z+MXFW0>U~k-{WBr#H$!Fn;_&@wJXyfe%bCWEBE0HTT-r`;N9- zKc-NKQ8N7Zd;L}puLrWul9&0YknKlIiZr7iKarlcsZTCi|CzGzH}s|>qByrF*9Cu* z-#!^}(-KXRyqI?Q0TO9cQj^v-Gytw3AP;%T8#lwGw!&w)WJv~$T16F7Kscs~Fm!c~ zVgZLMki;6))j=xCYj`V6*7D#Qbbx~-va|GTUDJy9a>aE5(3`@k8!dNCnA%?e4ni&* zpQ42%ipFyWg(Q;D{B{`olm(Nb!*%k~zmBHgG~++V!6DRWT_#;Yop*zuXR7V(vSO^< z$V*T*^fICuHg6}VzMk=)NFMgTfEXK_iOOTi(b^A-dr_d#ES`aEh@(``DUlZdPa-Pb zNMqVrmyEXlj^ho2jH z(X^c=Les7gf*$u)ou$#`SvD6Jp3KcoczG+XJASG;)2=zK(wt3QRSP&Vxou$KgI>$~ z5dzn8DKUoD3Oq|qg}>)3)smmo=!r2*4LDpN(~;0J3nkdDge6a^YlztO)RBHp&h?>d zxwa2}cd{s$a4~0<%+_$#WK4GiuHL2p+njP?ZvF?^H{okn6;G3Xo`o3ypU8Dw(l*)+ zf9YJPg!~vUAmv7U@6GR8BdZRXoQoR#BRrBmVPSO?YZaSF; za7W*3g^5+HfAerG*Q^>D4bPR#9^-CxQMVE_@ZS?FB~I?@^hE3v>@9XOzO8^2Vts6; zyM`v6iC|wI{gO#2T+%;F5Yt$DGU3tqExN*N94vV{G$8@iX(-4d#Ye?AU+`uOvCT>B zFxKwGYN~Qi2=``;x=IdKs8?E~j%GDJ)~fSSPocd^92S^1v(=T#xQUArdI|uf{~D@> zGM>&hOmxrw%s9X8BRxaWHSPnhlUnb`W4#_3RdDoM6z3AyQgtrSG2#qRaX4_*RYwxa zR^Kr!yVCXMONvqVmN)-zkKosqJIh`zGO6;J$1m=2(nH;GvzX;;Mw=vsvG=Rzq={y& z?3ts7U^PoHn)N5%ljUIH)Q%JV<48i+VUfW%pU!qUiQ;12&Ei=V^gVHPS5bwpG*eL{ zwQrH0_ypshN_e<6BkLT_jf3sOQOC6g=;uI=cO+byc{_MEvG9eDEoQAf@`Un{0jy47 z0b^vE<;n2Opf~;Ptzzr6-56zMc~GgJ5iU8kk@Kc8La5vR zdv`D6`n~A}_tC9`dj?|kq+K8ACsqY%S@7j~aG6ksm`0h%WIiH%Todu>>+Sy>mE`n; z8vMyx-kM6RN{NIh#1vDi#BAaLD(!t|X>w6{FC|Z}YVtsDj<)(Pq@V%za)M%JB)J-4 zcIFmtahr0T;#*O1Zu;8l)V4VI_t0wwyWnyZ)`owZb#Zzrp)_ii^58I-GooE$; z?jx*4&^ph13$aDg!ltOJlN*;4peKw!hN~f1!=}PlL)xZOmV#d?fqke{6hg*gfQpR{(3_8Qo`cj|tDO5WKBR z6NDts#Mix#;gbq$)52Zbs#(4zG%#bj(}dA$$74+_(85aK%ADF}G`yjmWgVC0QLY5) zcd!xF{!UqzKVmjp-D%lJ-6W7loXaJ?iJ#F{r7xCQ^R}|j{bAyR-Cvcggy@)*$(xPa z^H5>62KkbRK-RgbF{7PT(}WB+=CZ_iHmN;TnU#A?yH(o>ib3sSsrR$&bL{V|pC|1R z^Hc(tw}W&v-())e^ii8tJX@%XDv9lotkecun)7ZY?ezLN&(G|UypUNo?4~Cwx(-6& z#b~uWyF75-d`X{K*yZs#)PK##+8`}`6u8PW{221GfH-s+>cywBJ8b@d`cXL;x${8l zld@&QFc**iB!ZIE^hw$Q4M6gRam)O#yrQ2XT@~iC!%4VQNkV3GCMO8ep>M*pq-o?kXTR zu-L?=(1Y+?M5mLfPyWlMkE7ymJ^PZdig^3gwWSl~+pd1lNTb0S|DdEiij6dbHzGMD z=?m`2-q|0RBBs%v8sKp_J*i3S?iSfk3OQHE`IIMPXY`g-j78k;r?I(mT}%FwS8ZpP zIvOmHAkxY;^f0!|hSDzGZ>JyBbAAcb@3k;oQYl)sSNq8;Tl;@~QHKVtMfsn}wgdxHtIz`bA#%|#`0j6M{J2Z|?|q2;_*;?2aB*5*HFI-Hy4o+9 zTe;u|$!RCNziwaG*IGpdX*>=kA2&D`d|{xsMCN^`RnvGpIP%~@SEca5p$zPte5tdhfcqv;G&9~=I z5M#bF(_Be_Urp9^N_5%IY5<2e6o(TG>pDyH;`fpz0T!Y&4=TaJ#nY&DZ=Z`5L+I#>ED(huOsj zo1ijpjXM}`F(k;oPUo$TkLlOW5-iAOm^)P}ee|fzgsCRgA>8Pke!V}1$+_X=rsvCU zmFEn6dPsgdMG!j#op1#*+yJEZYOJtU)>QKDSA1D!0dHK{5bS^R)jW+mJzjqbvvF_6 zYKS9qLlB~K6hDw6{cHhOz^-2!BR+8bbA@q?Ve_*&6^*Ya8q(LSc$4kg5e2&CqZ9n& zb*$<&Bw#AfEp&zPv(*T*swskxnIl}Qv~uFhYIqhOcX2*~!C+;ec6L1Vy?qgBy9*rn zq|9Fk$q6^hH^dm4#^ye+Fob(2=6=+2RHnSqTzMW<8`C69fbTat0qY zd<}&}4ZR2=Ih;Q~%ubL~kB_9ntaG1MGoBAL|af!_9eW1zr8&^?O%ft0gIPSe*3i?d;|9Dc=*(!myq1*xU zb|&3qSL6?}6|&-gAyx99hM)akR{ZPH%?|n{)NXGdh?@-8Juk@!(M+I~-;WFa?Ho0g zB#d1V?OBA)?zd=+V#Nu)8P3d=V&^h-p1_?Q(V%vNRxQ|SYt0C&`r)jtTJzz|c~^zE z-dmb7{f{zfZFF-B;JiS)udFRKa%>8ff_bNWVxS_TqLMt06i1@do7u$-(O!w*Q({sV zPIxV_F?-+Yy$47UFS0PiZ6^WNM_R)pkI>_rWo|YOcT>&Y`XjfMO!5L9nuQ{Z#r34_ ze^V_&9-PVZNX%zhRe4PQG&#IsHGy!*Tbbz|>=Gxez3?2^9}ulxZo>LGi|RD_ol^T; zOz(o%GPiU|2)oyTs&3lDoKD0|ba9@76IQTi)MQ7#X7|S6P8ai-irNiJq@Jm{pC4y1 zx6v_7 zeg!<@K;lJCm-Osj9L|I(pc%+GB{9T;{EQN@HIsH*JP);A9axGjQS#*?sjsMz(7QOF zwlp()|K^2~4LZH|&vU~~5J-EFHG{1(1$WV?8eXKqZf6v^Ne4H(`746yks8aOIZ%j(27=0QRqJ`0CG~l9;Ju@0;hxKDnG??U za_0hPP6z%Vd)TdqPHQk5&gsf4Y&TI8sC@koNb<`6vn3qB*s?G97_9jV@QL}|ozdd< zH!})y=8i6cwzC$gm-+-qL~Wv$pQA=O>1JnA8r?U9>Eb#}>p)t&NL2Cje8vrPeWvOZ z7u;4lmNz|s%AK-SGkU2eeYM-P2sP2gD?b~r#9~y|XB(yJib`|VF9B)nkppvKRIs}G zS@VDwzq@E@h%DS>=V_*=?$vd7IqB<30M5RoZ5$KHu96{$FqzbEjS}p#qWH4LZIcHz zfs4(bRHO9GgL+C+I6O>wAk|-v;6X*CqWYX|s_Wgz$=p@5{?w4ar1hN@%174MMPC0x zMveFJ$#Ad_koCF!A2Ih1=?*<6A^s)~(*q)}wGD889i{s#!#5@X#Wp?L&2Dv%3{Q$Q&k~xp zLdy$sr$4VS21E|W;tukbN<8BjXrlcAK{8SP4ZG9eg_G-Yjd+{B%}vLgnquqZnrT1M zHb#7pNm;e2nz6&n=KJziXLC12hLvy(NVFE)bE2K_z|ceoA-2XpX$AMIfPg0E%w+uz z8H&qwO}$OCcw|k@O_S}_@_sq@XNX}L-BhirUOa{<8P6)}8r+QSqJv7-p5gtivkGAA z={uDoYE$y~qv*0Kx>en5Z)lr;gbp8)WS^T3kijSI4GV|I4eIXbsVp_QX-H~2q?-uC z4b-s`JU&AohR3FDAWdc4u0LOBzIQ*9*htnA6%L1u`}7W)FHzR!R;9W_Y*U>$iOt#A zo!fK84xhtw`}i|6^H4TgJpFFmrz9ieuv-~AOCb4#L#1G*MNReJ0QqvpvfUAY_vz1Q6tpMlQX(@dDg(p81fx;zGW5Qc3wvJUPn7S{ zk)7Yk;)~w5Ea6#hBl3SYME?Hp`szvXRC{IEhDi8F&*Kjq4%WkMje2KXzb?*b(Eo*i z{{E@xC*%Dy2QteLj~JDKC-0W>xTi#83h7{Her^i(lOnVIeXfVD>*!CFAY2mYbNTEm zSai}o-yoEJ94Cqc8f`{`l5kyFw&2S$qisK4>S!|HsDFhJVE$JB`|~DuJ#bTTMZ~`2 z6fw4GYw1l@0A+HDEkuB+^Cx|=0&3{lU| z!>hg2u^+Y=3DK{ZgU74P{mbi^uODz`bzYgOb$n$JK4pRR`bu1S^W7%lxB|6%!4;c3KW$I*qcFBb7%fANVmBN zzFO^;yDxirj)KdMSjP`=mG!k09@TBrj(7UohA|!$4h6ih8Y_9jzHa@|A~;6#OIrB# z5-{58nU{9Wn&~veY4oLfl+XYkjjIrHp|t~@e%5}{Ko|KuU#)I4({k!rIh*Qali-IE zBYqIH>Rsb_gihWZlsQ~8SK8c}y`^7R?at5@<;p#UG;LSSxZoIh zxZGLy@?{06j1+)W7vpdZ5ski2`5*v((KX=KVFoXZO4Hh-tpxO=yE^AY@k^gP^3|*p zm_Vhq&j-iZwZrXmlBva2sjNBft5NQXn)pjk&ze}zD{D4Ow`J8u1zQmzcVLs803#Q{ zv{_?_h@5=!ssZM#-z$3@x68A=X~B)@`?3=LQre8lOY*~(sh16nq*1?daNHSBRGn;k zU5bb0B(acz>qSK5oqkQ)o3k0-#OL@W%i~7|E2X_r-o3?-g$(`eI9!lI=3SBPp6H8P zGvd`(wS{;IJ{)Yf4;VC?l}4z*O`5sklFeG}!c>`I1wSy$qz(NtWu@1Sn2V9&^qp)| z=QV8|np?U#J8F=dLm9L!$C_~W)g6Y(| zxo~}kXLScko9`sm(?%Mqw0;9 zzZjO{+QTK-H9t3Tdgp^gR*XNSA4iBpPPQB%6zp{ClS`}Zvj~vAoN%3XT8(9N$&S3yIxqtlqlrJtaBWAq6Z>dDc!{tKf2v{2B z-7vu*8&~6QT+aUFTf!2Gjk30(nYe96N&LZBi#b)jJwMsSGFvAEwG49xH@Gh>W*bCM zzSlrQS+i=5A;Nj-+fg0?k%l!qu+#JpU%&i0kNwYa6yxI`q)GK1En!~s{{%h>hKnhj zI&F~BW7(6h^jtMysKgP3Bj>$~BPZ&3UF*|(#!Uc7y3!`T4nA#r_l_ZsaKmG#FQ*al z49DITE9;5JW)~^u&}=zk`O+^sh_Y zn^sbIWcox)In&p*+D*4aHoP`a6PnLdJS462kp+XLtju%}Bv{l(r}pK7wB%wQPE*;a zn#F(3wgZESy3j5c89GAi9kbdE-c?#~RRv>#Blsg0wfwSf03g}FxS(Y_n0)h$%6 zLkg(wq*YQblpjl_fLLB=ChCOkEq3esodCI%z^RIvJ1K>uWfH!wLV@<%kVd5n!$*iT zdQ2r~&Ih1c&1x#h+DEdpBw^D6U`&(3#xIJkmJCIvQ=fZo9~-;Key`xUCB$gT!G!Ya z3{x@urehA;K}zzBhwp^(g(~I&c-46xE|?iph#;T0`Sk^l7V5mKGlWOLp3}p}>tS%6 z;69-hypGaL{qh@D*YsTp*>2rnzOQwMycI-6HQPVPLiRroTRGw0USOg#LOhF!V7&L62EQumwxN_+8ntF6UCeHW(1y} zt5Fbpqp_oVvvr)mS$PC!YO1QF2$PZ{nu30}%N`T&Mps*A+&OpXrPd6RA3-KD1^9R( zd}6zPHf4`=XJ^0Gqtkorc^e5(fh#Ht$Kpuw5RoopmOQjN{o>l^4{-nh=L!#SnSjg) zd65~fK#7Qgb`P8l`;cr>kE~v>w!!YWl4tX0HWAxc|VNHCh=TWD&A!pqreOw)Q8G!hdZ|a zwyfTt7#WlAGyg-`QYg!>QEIbTa62eTcTgZpI}*1u3{q(Rq15jmg(X%bns(^^JjwXA-y_zm|9;MiX zeA1Px=q5KNv{m*s)3$B>?9vC%H)iN#a{Rc(+6>IJ9y@#p?{+@qu17m#Cy2f=V)2Ak z)k=miYbtT^etho$gQr+5$y}u5v3Rl5WI533Bv>X?o9-|`Ra)o|!hB7c+1=Uopza2= zi#yTf6iTG4eQ0{KW#g@K5Oy_6c;M{BbN8kmpX8zGg6`q!g#5Wr3~c50c-3cp;hITe zzE{}sSmT>C&7LNpw%}xWOz@)p7`f6>)9IzGUno4b{k~^{+s58SD|yxZ($!0rlc=%b zlfj)o$nJDilGHZG9{z`?X^RnqX&X~PulcF1Sz#Yl_WvAj|9HTaGMOD9Ruf`g{~+9M zFtpKM#2i7^+Rgnh6j_PylsR>&+q@b^=yBmbA6M?rG6ML~@BTelL%$X}78{+bZN zn@)%_U<&hNd~b&-$}{2A)L6YLTV`#^Jyls2d{J(RXD3XK70pVpSrfrey|%*_3a0N& zk2{f=Vd&9l>S%uvA#Hw}HgBwUdg7?|ya84}%#~|-oqq{B+ENMu)lT$gPyi zlnQ69>A=pZq|7Ewwgm1rJ*y2Ng*l?FCt)&eQR<~uL7+O-cBo!UrDlirW7M3_DnS!Z z**0lNsYtXdtAxk##u+H7zr9t1pt}8G6sqLIw)lOBbEs?#qE@C;{eUWd z2nj7hnXYM}`*2%c-CGjJa{k}!PGmx>TuqScOz<%O7NZi=RR21EykXIE4*|_;7*wcE z>Ag;k9aKnoQmBS_L)=z9#zhBXREU?-`jXh5F!)pv3klV{+p{T?A2oTt;NZ4w1T@=- zB=$McF)FoIHfru2>ut8@WH0r2hvzh1xNm`EpoY4dIfAs?fc@wJ!OEN`EqgGj*e1+I znGx@_R1oT=$%Drtr}K5?{d8E@Vf?qsnibbi5pKxrq}18uEe?Z>it@sT%+Zr#D>S{& z(R0%LqRSPXFDhn-pHEWEvKShzPl%wFaEG!;(};4GF~{@S=nKR!|( zrNZ*_53+!T=?^~@jqY1!1mDvv8l#NUOp5#t_P+?uP}dxUp&)sU7)IZhV`h>7RCt_- z6K8eNup^bECfcwi@9(rziwL%tk;s1Tc&&D}{@ z0!J~yIXRU#@?KEh;HN)l19rQk-k%3#ZFUY5@C*T+(xY|Fz(-G>N2C*z2 z6ove>m!nWLyk9o#k^3X}IEZ}i>!0WU!vSrUoJ^CKE~#cG)Iwydjef|L6$lN^aIE>& z`>?5IH3UmGKAIe{LedqbYQ!$5`mLtoE}ab0lJ521)Bu#8MTVlIkV`VEmAYpx0r%CZ zACIN59#jq%zx3btWLfWVEsUCe>#?M8;__vG$%|DXNIHiNyrY6LV!k_Hlx;stP%a)# zkl-|-$r8%qsWd%u6VGX!8@r`_KU@1zL09Ee`K9iclBJUj`Y{x6vAD}V$XbJho`j-L zf-G}g7qTHR-BCf_x(<}8L=tPBcc)Mbcwv5F#rNiP-E1)&xiE|l`U01<)Y*)UJ*&m- zH0iF9Xa;xOTkCz(PAI?ND+BhJg}3IBZ%$h@6*M7Y_fz1~t6gysFEk4cjH^Ie)og=p zUx$Q+K#z!0K4Pu|MSwd13)@jLi^bWama&NS zX*$p{#oget*zkvn?q|8UCa2GMgwNNvYDM6rw_?@=c(AkVb-|;+_^0*jU`*)NZFjG~ z`{&o4WPhFKXBRM)T9oFnEv(PD?b5T9sa#cym;;&!-ZU61%QA3CV!gMR)X0Y~d@uEnB*>Qjgi-C;oS|9*AM+mu_4=zgodpb?KxJ`(3? z&xhKoCJIENE1tGe2I;q6F|*BzJylQQJ`|-pPNE;^w+gE&DL#3&T_R;QWq33SHQ#Kw zW+Dr^Io_Kxp?iCM|B%g3W%=YJ1G#RmTJW%lq`yg4N!GB{(4aRk;Z2z=s^Lus*EfzT zbbym?2mN^u$$$G8#C6`j|L$7tzYq%ePxE_T*C_;&f`K0t9+1Q~W*YSSEVu4VkL*{q zd~A#TSs%iu7Qy+-+E4C)ZR-hx*lNND)u0;CiE3TYeZke?(g1Tk*;i^@CS&V9$DE8J zdj(QysOFvoiFCiyNWWa@^Nq1v7N`QDVM`NuA$?MPY)?X6hK>6eHrO-a{(FmZWfnA~ zr`H1J3Ys>>Ss5V<_teT{** zjl7hi*}mg`X!rg_*nOS@9kmQ*EYEIyU86M+v~Iq6R6!4b_!E5SE@df();M&7z7_K* z+?#&&rA9X>U#po1TA#TzK85#yl?g9IJ?z!c9b21E9}*jGf%EeR#t-G~-RS1u9p%sp zjSFkxyk&@}@@?ix8U3~{R4h^GeSi$rQKaydGe8rO9WZc%Gu&M(r4E)&G>_*dkN z23oP-nM3Uv3QP*F*`+&RdDuRT=V>|R zyneJ5+n04NGR!o#Q_}YH%B&n~+L=~B&TBa-Xlc4x+Dw0b?6ta1_z?+6bY<=ke|lNc zR4-=yR=A=}AHapRLVQ=Ptt?Egq!^cfJukhe5$B@!rZwUE)C0?3qfPtgHO&`$RjX~W z${Nz&^8Oqu|9Eiq(0|NxX~xZOz$)MWckKt{WZMrITWLsc#=c+j`!rShPQ0WZm^sW_ zio4qo#$U^KU;6fvbY;qt_Q27E{8uu4Jd3zuaHGV$*L|X|_)OcJfLq5^x&?|6qolLGl`<(aJyRX-c1@n3H z$Jzh9grc`==4*lg)~%U?{QJLung4-r^6y>({;1^ZEa`^^li;hMe%|6oQTkOUp{mU> zutaJ%^Ti~fe#x^{nGzZ+4A71yWvi zP}&dIXH-wFW7G&5>nR&N!u^R|u-ut`27p;(lE&1M98zydvhGYbCE>GE@=34%4^CWz z@Da~2h=G{gwIgbh=eNPvu~Mb{U2l&-I-MQ0DChjdowB?P|q+> zgU*BL6W#mbY)GXP!4YvnzlgY@X>^gCtZ8`I6Q!F)Z^Bfa2d@7uA&NV@2plBOeE8(BYrv0bM zH4b%(!KM6u{r@5P)V>}aYflLKUZB;>ArhB!;&^?q{_hkZ$fABfTj{y)pX_B(wh1rf zakfE+tS85K*!u7{OC5m@)x7g~sj8BJT}OE#t5&aDz_-g2PkrzBC5WN-R|ZZl9#94n zKf!9u_-1s6W}Ihb=gNlDW;V_EyGej?%OnLL~ZU3tw6-fC}UmDN|Cf+(SPGi^M3ph+QKw42`=a}Svh zoa5Vc?jhOlUt<-;npCVA=Smd5C#nCi=3VQ~e*oZGXG`^n0G%-8lrsQ?)24Y&xkTIQ zoKOQTsz%oYL@pyqk9mSyh_maSKF!UjsO74XUI~#$9`m!Hy**ZD*anAadi*X?X47@8 z>6vKlc+uMAM(6ZQ-a*Ht$+wj#f0}F4$YE`11D;Jp%><~Y=ZMh187~Zx(B)gm!k?9U zznO0B(?g`MaF1d~HegP&{@K#zKtAE`&c-&ck8eFKUNY1}Zg}f7C00O@2fL!1@u*hF z20|?7#O~(3wDkD~*PW=b&!tDDm9hJ&-#`*;d84Ag0;q7xb}!(0br4&-jF-66o}Uk` zT_(QNOLk5VE1ro-KshKUhburUlFT7$!KsXKNl06>o|dQ3-l#kdt%}1FOc<=tvnSu_ zvuIr()O;PMzW7UEiKZ#AWN0$a4+N0I}rmp)9<~Fx;TZ2*br=>@PrcaVbNb`yil~j52K%nf8 z1eUS!Gt0VK5C5}&D6ZV${cplSbZ1?DJQ7)yb(Xr!A^C087=Kag|3UVt`$w=kO(iLm zc7}vOI_mimua=awhW87J({hRe&urK1uV2+|3PgP)ap;`zeU@>G?1jD}kJW(3~kw{Cu z6HGh}7Keefd9O;qa6(atB`_ab^%)aio-aSbFr}B^f zY3j%SHk&rT&?uv+0`-HSpvV4YS6`-avinV!#cKPpUqOTg>M;dX4hzzpmXJKPG&RF; zy}G<7;BqgN9Y^r!4jmWQ-KnbB0V%=wbWdgB)MVg_h9@Fk5u0KOb=ExnHC2Zdfr@#oNepE7ow`;T%Z~%qw+w0X70}v4$Pa(GIkl5@Np-6^# zxUpXC=uIs<-nwL?Jo8W=ytOGYA5#gm&t->IEEJa=%(_lV3ua;Jz^xZT4XVK0`JF)s zos5t0mSZJ<nd6F&eX4nXXX*89p&H(nN&2W!c2z6tw8}Q<&28L)S46HJ4ZZN1d zcZO)#DJIUaXpdkQ&)k?Fhgk;-cW3{YE{`$5;LeO}fT}fL)UAaxJ@{nCYBbrz&7$Yt z26=Vc1yq1E`1{ftlu<8i%v`e^bNQHD_ja{aro<%meRo_5k;T5msV;a`I8i2ZVVFj! zjtPihKt3V92T5f8=11EuAPU$UTgmaA$(u8_8HyrzZQ-Y?tT}=O8=I$c*4z}xn}2Kl z2bm3PQ-HF=&Uup)o_G^;Z?6FghJX?5GRvizC-;eekWGXpn4UbRxR{IYALv%Dd;}CO zO<`5C>2tl4AN0a&eAQ1+D#G-8nd-8R22j2$E-0RO-*Z77(Mz?Aa9mOx~A2TW=#g5XBxMJviKh!-xb1vg{9%F^QIziiWQr9nO zXPNaeWXr)}tIiiw5T_cymL+P2T(juI6k|MNzo(FNoSZpQHu|m(3<>ZJiUssQqW)}r z`nYyS@^+QnC?JL&Zn*0Apk5WG1?IpaRC8^3Genh${GVnU%aXuM@aTd@Yjl~Iwm$R` z;lM~{z`es7=s75~2jRTMXbQW%DieNpvY_9XTy|sdnS-*SXBf>)INW8~V9siCMxW0X zj7;Cb#iMe6FPwrCVLq-k^Jb^p7Igi9D&$ z`?89O(=D&5m5)ZLLKW&GH5={4V-?!oPyIpm9EZA>hAy?Ybu3@Y;-*Y0GA+s)Lx_*5>^xIz-if3^&A6GNJme&9uU(&#I*tu^hXqzUMSogx} zhLue0rg+De6l;fq88i~#N*m0kVEhgeH;J?zr^VrtjGJYn3wVb*ZSDE_h2lmarWm2U z;(?yu99Cq{+1i81zY?1w3KhB-vnK&l=)73{hBMnwOkY!0Xu!gc*|SoYGfP2-hlr9J zsk4!ZcICAW4GPgjHmN#&|Mm2&W8AkY2G6*`3v|J~!j`?VL49#;n>z=?%BpMnefHdH ztRoHPiQ4#^@pK~UJ_b-j)H`&pAV)(opuECkG)sllbraq9cqO^-muCiIHGae}i}e{W zFVoOz!tG92Sm47j2l`$}?LtC#RZFWFC1+YQz4E4e!ks>Dt z-E|q2-u*B3-aD$vt>5>>Nht7R*vTmVm(<0zmN|<4T+B{AO_o`k23P0}Zjc<%{~kv`s^|2L~t7 z=G(P-^uA}yfdS30{66r~8+u6u9lI#*=xX!=#R~ItmF#9FR-DtyC@DFqvS8#%b+%Pm z&L8HN89-{mLSh+R`31cvukrxo{-i%Vsyd=(LSkQ<0$|fSluGw$1lY@SIRe7>YNNgl zZJ9iw+<``+T-<7lbt6rrF1M}57~~ihh}in%!!m|0p#vnjE+TkOg)fW0d?4y>)$`KR z_yekqw3+A%QC_Wz$n4lioOWW1pwC4_q%9Kx?W`X5^az5m1R#ZgREdSyURg!QTjW)q z5^?~nzSW6ea8Yo=nttH-8`Fr!+~5L{B*RM8mVE1sBBC9sSYbuFfCUX(m{M zIPSW0Cc`}Wk`W1CAipXS3-Xa>RTqe9&;w-`%@q~?!+{jKtz{z3!sLyE1}|xY*BIx{ zz{^4>VZti@uA~M&c(A;gy6Ss~@1W{zohu|ijkr7{nY1me)AP$MKvNFWN0}R^b4gBY(F>PrI5@7o z$2=%o(2qRBq=lJyXR>GP2kgOGGa>oEslNdqV=R(dVN$>3k}M(&Y@-y3;8K2@bpV*I zw6a{s)nY$rlkFD0^?1lOJ&mNJ$Jo7C(!2rk8ueQOoGwTrh|sXw1@*MZR$}?OD`6TT z{TwCgr#Mm4rr>tDK-T=@gzEz-1yFV3uqfW?4Pi8hZaHWNwy)RTKkO<2*VLGpwC(#) zd+db8o#Zu7xclW}-6!4e=P5e}>^y$Gt`>U_s7{(Rfw>T}6VWf@n2lphF~&$CgtvzC zT=6zSw(i@=#mOuOPDDM(!5z0_6DdyejY z;jbnVzYH$OnHYYUy&n{W|I$smt}?J^7oDP%D^%3;!opw=H223;aO{#C+`lSkWxkMlb#zE|TFJSjH z5e~p4UPBw+0cDiO<-rwlY$16N)BECf#zZUH>dX=>Z!J5XEj<+;&5&%G^zlHQ`z2*s zh?X~e$!UHUC6x8f>L895w}|f>c#iuokBmGt%B%Je5=CxD-NTu5W9U#p7m%lZ!Dd}W z9*tgyl3*}gO|53J#QNz4dk7Gsw&fHJ+;yK77ekazl=Rz%7$;4pzJp}uSVECk?mr6b zkg;4DU^fEzvGlyIau;ec8uMd*Nj(BpD!T;nOZe(SM>OE>^tAR6wMmBcgRL+;^}198 zZQ+T9ipQ)lb@vb@-&T^3Tf_wna)jd>1hoZn5k!nvc|-XYo4*#AO&19m2CNJE>wtx> z3}&k?y?-xTU`<4(#twjJmzV0b$Lmj;E-Y}74{tXfdGim% z(c;wqB(jGY^qd((eeHfinOu;$XscSf?HKo+S!ZtdH>6{qD0Y{7YAgRd+M`fC(Kh$M zw&;yZ`oQBjUUfmJ?A;bP=U9Hv#}pzrgSm64)_ixTuHv-Yf9)&2_S~F5{AiIJfLViwHGpB|I4I_nJH3F3TpLO}Z_jdKdW*_sFLrCtBK zAl%=!e##R3GrH*}mHlElXjuqJ?}ZrdS`sPP5VV*P=gO*n@KfThLPOCO>D!Ew|L>W(t{<)XhU1r2fy9=6Cz`uwRu9-`EJz1`SS9d2? zt;8HiJH>ZYSCa)o<|ew%8+*(bXPkz_ZjTf;B`58|lJxpsnZvDhF3qh4c9&Kxy*gNE zRE}ogW`vDJ6Mbj9qhBi3j*-E$bu1%q$>p}(-6&jwvvc6vMK?^Y2NGHAN0RL=5nhl7 zD76OEpbF8^W}CMeVXB=O&AFE&uCvkv**+7>{bWnbt!vw5wwb~*$=xrd9_&V12BO$6 zx88Z-uNJd74$0rNkrgfK(O}KY8e=9p9%gC}e1;AqP49S=(ASbjrbe2O^l-vFu+@jn zlCel*i#BEJ3Yxa2>gnj`dGF{ygo)h!Jme(qR=!ePpPyUQ>s^J-C>L2{n3+o=^PICq zQwmb_oG5|@XNllkf~;*eZFyj-LNB|>R7JyYw9bBf7NFG+%TKowza1&uyANsSDOsde z-6dPf)$9tFXhf6C?W`R;Z0EbcC?PM1Dbh8fNnBBay&qR$=BC89=qA!}V%-pb*yG!8 zGG66aG*ZL0L#jn&yA_g6HTv1wU@9;PRd=)AGV{yZ^=ns9Cq)K#zmNyv1F}kNshNqY zW8PO4SaxF%>Q8Sz+}6% zf^^XUQ*h>SECjd%vg#}2t10pv=AFrx{zLbr8EiUP*x5CvQQ5-TAW=bcVSleYYlgE^ zPEAObo8)&@M2i3~3@%@z4?00|s|bVr6^n=}1bzadR-&Mhg2Q_^eE>ZDCVi||ZY#Y&DIOn41tB`~ zJL8lNv>swF>|$>bIm5(`;Ui)+GusrSJHrdrUX__|b&IpCh)_cM$YD}HrbJVCfkVlA zDsG^Vz_!U-J2Faf>Q8gc`R&C}3*aXa+O_#=Z^yv{Z0y7byTH3xB-&m%OY|E})JQW4 z8fs}kDXXmo-p+2cEdZ?YtzRDNoB!K%f5#sii%VXPn}k|9F#P) z)dT4j7x&M;offkkd$ZTIBxdt&CB?@$jHTA+ny&I#6exClQo^(i&%ll zsxvX1HtdG?p(5q{4!!-La+$FzjXTD?5z$+)+O0toy(7V|wFNyI^#F~rFH3ZaW;r1- zlxiXst!VKDG4!PG6-C|A`!DT=Fb%G~moJu}dgB>$B=7W~5bmd++eD-mT2Wma$J z29v02@(-(bMw*0pc-(meV8e$lB--Or2)9g6;qY=~HEn9Pnoh!NbMFJqd~VLY&ciIJ zQPKAxEr?cI%{DPz_(=h?9dA@*K15V`EfE^sJSg;Ayb#EZ(B+gnFz8%)s}O|OjlaBF zr$B>N+1KHMHTDm`fiu^w?JZkX+)Lxay4>iDh{a94+i4k#sz$-;vyLfa_fwnRC((HF z$*VR%@&x)AHLx1p8IEeVYZDt3^>lMZv*r|Q?)Jr$V+iR_KqmGB5C~2QQ%d8o^fUqM zg47tR_l9pN{$;Uz6Nd%qiD{?=)UwyaA6H%s`9v@)DqAe(>B>rWR1w#HHm$PoA?7L= zKmK`kia}9YG!Pc<)q0D$hZ>p~n5aTjm%XO|$9mAFer5#sjd(?>+2RJsOeMQ$P-|1Q z4{nUArbJ}yJT$7lG%wrQX8iWX9U^~ry|QD$=C`_67>%xBH)EsJVO(@XkAs3h=;G(7 zVA$e7y0Y*jLWMws*r#)WxzH4oRmsptH-WC&t?Q`)3-GMX%?xLq81_ zUgs3_eZziTx328gPP@4YrXW0xO3NHSy*)owrcD+-=Y4GIDvk@5*8UB1CWFx0ol~{fvd7$p=N;(3w59BIV zZewv#B4at_(3Cs&gzvqBgQYc??+YONNj-dit6vE54@G!Yn|MiJ_)G>0*yVOG>L&_L zXILCxwXF4C@fweNRHVg{q}od~Ykw&=_hljJ*f{^T`l`J8r#Squ&%VL7G-yEzN+`Ptjtv z2@<9peUSl2_IkHmEpKkmSgK07b4cZj8DZYh#C43pm%E-e#hbiFj{>L@o+_4sSYk&; z_TL~K8Y4&WyMg_Lw})% z{=q&Ou(FI2k&fcZd7_XW!9#vzLc!X;H5QF0hvC5SY-~t(4XN>K#xRY6I* zO-zrL@-l(6f-5`C3)%4Ph2>M*gWI?^`!vxHe=F8up)oub!%tOK287I#WjhL=Fa1R1 zadUlqmCd6><0CStSu-yukvoS0W zR?ukLc@NlczafjO#05+aPE6OGW|&_h!KA6J@)39?GvNSpGYz1=KyuAm7$WaLEe$jZ z?rjZne$|OvGHblhZXdb(M0IuMPd|hYz4Wf_0K0CHOCfoAJrTrt7zsCKYiyjtbk1ck zjJtpbIo{E2fyVRcvmfRlm}~ES^BlFTRE$YKU%bIosDR6qJx=70_F-vN9Yb(LDZ;XK zM3Yvxo?XKv)3r9lY8}^CVG_|`9vnIn&SuVfq#06dRK^h-Ez`f5tXtGvSZ6>q)>Sy~ zC0R-9NNZ6?>p91BJNuDc#K74fXQz6CI%ZN3ir9D;vp40^Lx_SQL=jlSB4%SvCr9^& z2!=El3*g*Y(#(1Dz(G9)m+2rH&e{^ivK&h-ZnVy7Ho;_92s^!q;^J_|5sXAt=Xx9F zaJ5^q>bZeelv74B&8V$v>Gh3*XNI^slOIfQMzWTfiSm82z|&xZdb>B;3zjqtDSuns zNuZ;z@irB>_b5y2EV_>z{7T#)QdbR)lC^?^(REF`AB z5%#IC4kJmDj1BNr9QI%0=##?62ic8@$iyHEY|!gk*l1no=eF`mTavK)6uJKI6^yTN zrT>Y7af7hbTstKv{E30h%OnInSO47V^u5^PDkD%XeZ2QQpQY%pLPqAVPZ}n)ulLiy z8yT&K$A7|qRnfSz4dp_&l|FtqBg=5*AlZ^Ltxjs@^a`Ov%D1^)SVoJ7ZXKe7*C|@vJ9Wl?&Q_72jS}5-km@dZV}& zO0G(IyVE`sC#F86OCGkVt|YoKPX?== zX-5BTYxTdB&PO-4oy|T+XD)4mfWyCwkKbY2bE|GVTJj5`Nwv|L;Sf8F& zom!x3bqX zMV^*2j(z0W2Bq3<*MjxO4q==D(i-+A7)Mjlz?8k&rMV8zK|3JIw~#d1IyI)nIfG36 z2_Y|ds3cLwg)vg7MQOw~Wmk+yq1+*_a-_95p!pFV3cplC4H$i=0J9q^zN#Csh@4!*Ew zRuT!A@Qcr<_G^))aTS_w*qCv672}_{@Y6zjNyF8kp;txS_M&dW01*oxGZ@fFVG0P# zp0dFQGdtE$((B0)*$6t(+i}u~|JI;JKfWYIoaB_H9GiiZR4Qm;w}3M!kORUpQ2;F$ zfhHO1S8_@#=Qwq=WZkqnW@T$u*in^=+UrYAh)R`=$na@e4o`-QWZOzAsR(PtSIO4; zwu`70%_zjO?B6A1NC;>FSFvl-Pgob@oHy)U@T;GfNu`E;LAP;r%QGgPK&MZ$OZG$h z+R2%nD~8fGu0|FifkmA^$8F)p5DW3xRJI%b)(oqP$ZzREvOqKrCSD@1ZQ>Mn&77Nv zB;-@6vRl1|?qX&_Qfn1PDKD&?fq4Q2c$h6|3VO{(X{Cy*Rf~+R1NJ<^Nwxi8TG7|8 zo*gM!U=x63E)7)N!}X_!r3XriyHAkxV!!~a^62pLK7azZX;1`S-l^(fvu{Juy>z^y zA$zTYfv2JNDQG5S17xBQaSD?_8@%JH`&NFAF(>9*GHNlc1r{WcCHPo8vooSlekdpK z%~(KMVCr~?UW^sL%W!URo%M^JH@~DB(8Y+B<O|Nfc5oK-WwznVL zzo52a@77P~NO+j@AXWH@WQ&w&Kxs!(m_m+(!Q6+5*v0VyH>>7OU5ZfgWKgkh?;9S{ z>$9jbK6s*BUKuEblJ#!uvrVa*ueEVwR{FnHOp z0Aa}Og!QKT(v%CMAt?Wl*i7E=v{e`1bnUZR*DC1iu@75?c=~&7xAsCQbYE9L zZqPfZ44ONzFt8FL`%BD-s(-rpxQIn`V&#LXx%c>$Sn`M#C_)G}p)gxpeysi#~-v-JOHdqkjjPGRROGmiE8J61X}ezHQ|I#cLlGK-%_dX1k7 zUP>0Qf#W}^X6G;UJ|d9BHO5|>Uzw<0;=20<>d*JRcmTn5a>wAa)Si09Z#nz@!|s)i zF)V|m&&w+>zEZJ#88Mt#FS@M~SBjH-r|fd9+Uu|u?6u`iEVHk!oxBYeMX;0v_0GN# zhJFw+p&VO*XdMY8HhSz}nX0qg1B7ezq+xEEH|c907uZ^W$A$Bj`fjbXIh4CT-QVs= z(;{=ws-EIL;yxl{k*5hFElEx1{+VhWiPKE{vXEZ%F1u#9h7^3kSJy{dFL>Okqo%j{ z^j@AtVe)E;!1O+er4+m>+h0{xD#c&ooJH>MI&#On|3l(tsbIQuj)(UyeP))l5}5%H(rKH4X6Ozmb@8u%yx*5PUG@^CaX_=Ciwg@eY<#IINa860nG1v=%KFS=whW~{q^rPy=Lt5rXmiXs!+HDc8;|Y}CWmK3=c;1Ao4DjGejAo!?XkeL@RMJhz*(K2`oS`QJppGkCLAtJ7%kUG4UT z>c4n&9{KT$w*T|NBZ5EA5|$bUr@I{q3&zzYa_PmkDD3 zv~IdnCV0T+ea753ar1Y5p5}1Y97TLj-lPJ(r`m=C&@4kUTkR3!&24BeXsnha6pyy- zSjVi`@M%G~ZF~+}7@|rx9+F5`{QzFH_#!q?cr>_t9X+qdz(b~W=jGLmZ~ARF2P`Wj zl3t8`NC;dSo1Ghd5LTEI`!voxwJ1v|F?|cagd)#>U-4fMVcd@*!+oc98@xdqS{-+nj7q zOB8-AA6k9=b*0pZ>DZ_rOv|EHLR_X}o!UY*D$((E1QbMxYk1!nN-F~AZ`8gjPK8{z zsrW*rp2_u;>hez9P#W9h^#rL1tD5w40Y}*6+r*tTgZKpcy(cG0sx*i~6G=sv*TnF^ zfVI;!P+pLD-;weYAF)e#sWth+cwl+NwuqlL`@F6Mr}GTk5=l2cj<9;z)-g1JBg3-O z>+aW!ZRj9NXaX0yD@Rbpow$N222OB1vI3W*WYR*D*K8OG)x4c{(6Rd-NYFgf&5y|8 zT!VBe>KE?;BcJ-1B%7$@a>7{iKWVy#3|s8KGC-=g7tCMH@n1ES!?{mb`Br)ql>T6P zRiRtxqg>*ssWDMGg288wAEWX7zV_+;Rw4zF2Gw()qJ&&C4fE-)Q5W(cv!GFX^?L_s zO2Ezjc`)xQi)>IrrTWT;uB0$tgJEYQZNDC3?tl&H&iLoa^;*}A5nd?g_~uhIu~Jv7 z^qIeWW6UyM?aK&BP8R^kxc`TWm~2F}WQ0C%TCa#+No5kj807TX=x5*bFhQAg7otUO z-YahB1jh4*m*q`Zw$FG=$|M+5!DH6>;xNZ$fUr6)_w(fa81dkA9nbZX zeKvn<;sB(8gmde2qi{^wPg8q05x8s>7(7-YV~&M)56@mHyq*V)`*YBipch-MlA92{ zz>ke|B%OX|AF#;GWEn~F0AS0F9dd%%XJC5wyOeu7(nk&;j|SR3>I!P=xHpc? z7>Tbk{uNDdQnHUOSPhqFBR*H*kZ1a(-^3D|bVM&vUNh5E&vbxD@#rUCkygAcKCulW z&kmS$6P3eYuvB)Kt~0Ve>fjk7Mh@>zZ$q1fq!;wvY`%~SS?))6ZW@U*SO`g#&}BR2 zY00&sHk8Jm;9FC^Q1+?7WbKj5Sa$r{rSgtysNDCin(_nw^4pYx3erX;#8jRqX57h# zEjF$9NLv$kFv!`f@KMd~54p9VMekCR#E16E(uzkVmuPBbywx_8g5nB`;yfA60?tDh zj*Z+2FioHNtEr zRPKyLqRa>gLXXl>nNq)%oNj0IVXb3zT6TUUrJxnexy0rRs_P2q_D0G8DYDX!4SCPh zD|e>T;(&QGvhk+36M2&8$pO~5qS@B2b;8(f52c|fZzXXJ)&h2Z;2y(=EXAoADSe^^ ztKBSp0GLdb#uDWt+9jzlbep(Z-=&C^7AS`utsOD# z_74w;Q`GWUU4JlQtJ6siPRwW6R<$F*xhg3Flva~HWCX^_)sa{5Dn14C&U5Rwe zr*3x!lffJ&`aE$_iO0>6#3n$hXg+X@u+E*HH zeyLld90=2LtF&VmZ#Amn(!)!-cJA>yDYm`8YeKkxr?g5J+OH)gGf}U&x#%@vXFMQy zp&;3KYPDSS3*DGQ_;=;Ipu4LF??=5*qn`GVQz7f+@Sx0Swly6a267gYI9M@_wJX&9l+;dC&w1o=M9CNC5{5>!kr#|A#_QyT zA@}XNeEl6w62+Wn2VM^u|3W$-)$GBBQ#LeJ^4>JJPcSFuS*45?22FBOttxjku9aoS z-O~t#^gn59Y1@i=JxGEoYX;R9->=xbrQ9e-f4#?QV(GdZqbzj{&lMe_ETJ~?BdEYO zD|!Vcz+}7Gck8Kd)A9DsW44VVzbdpIa+R*oQE^vbGc}6)R7Rmc;VQStL6p!MtPEkt zo&19-j*_Q744V!ulp}zg4%Ajj3pxs5KGsPGN=<*XBB{(jgGzpLOP+%j&6*sZ5?T4` zk044MuW?ITo%Vdqa=`Nq4Sfx6mO^j6pooCMrH6SCx71{p@s_J-%P5!HWVPxfE75{E z{h!BgZ&do_v03U#MB>&PWITe}uJN~AT{2ej`n>W;;>D;-NeQa7uIuliJeD+WhCzd-K3#RJ#y{olx#Anm;Jl)DQsAR3t3gAw9=+L$x#=^I2o}^ zaeVbj+WHByBbu_=9apXzgxyl9#Wy~a{*t&BFFv%WzlzpThcW=WkdVLzAz6VAK; zoBQ9brPn{0@{bwGV9#P@n7z+~WZn8e?NBAr&#=J~6`aYQ1tdRrO~{7ZO>>~Ac2;5Z zyp3T>T5l7|V|d2ED>ME=O+q@c11(8=knnru9(o$;3@|*d$*USH~?)>{TD5I>}ed;-N`ywyOljhg+{ie^c@^fg^|E8$mpYTm?znmTE zAFT+si!o6I_LlAn{?o1h?a~9Ue9Bt&gQ_ z{+!Dlm?b{d?l038vns4whgrhihr0Gtj44V1#B82CrjMxIJhvq z*jOL)^qjX#JUcSn@r;4NacCqv=EF5yoPw{CHn7EgjR$L3hnzZML;R7MHQ)kviDNu-o{OeXUn zW!r-N7v;@1)Ce%2yDjJ>Bb)em?&h^PSkJfXWvkb~n5bu+)LxFsSIqSf`cSZ-lNOkM zaYadAXc^XXO11!ARETMDh=E1#tc#^u)tKF1xjjM;1ZC!zvp{9yU0Hy zf!$lCoZ&anL6!)0iAM>G&?{gei8s4?x-&JiEOKPJ8J>ahn`71AY>t>gI9KBPJJ*2l z_)?t_p4)p?r=9RD2YvkHnQ)ioman(FUAqkWw<>&-R&Hjl{=7kr3592&0x&Bq+hSvH zb_Co;jMOFR6&=Ro2Ne1M00o7PJr!9`228d8{7SDVDqf8ZB@+V-WaDm{nB9fRa50XAl7(=n0`O8b4(t|H5YfEYZs)N5q`W&pI}H07rFA2 zfcm4OA!nI8*uPLlOF3tc+_={%80A!wT5TLNoJt=IK+aMu^z-#>;(1(Vv{%w*RvX$J z>U0mYj;#1VW9rj#a(P|f)fhmkvN<+uoZa`1kLpji!2cL5D%mstPtMp@2s;Zg3Ex{gq zpk9o%GglA`@$D;q{ri86$OCY0E|r5C@z@@)_T<04ap%9?=WiYSr|IMpx7r;Wyq4bw zpp6Z)rP%(dj3=rosc*n?U)?gud}#MdIY&%V(&8ad&l&i*_}n{6sv1*EBbjaA=~-LC z`Gd6On_nN6lxlVP@A~)eU-WtY_bBNPy0R#jX(8% zcoqGBf4bM?G(Z0*!PW?h@Chq|SR}pch@*S)OpKtB=h_81SxzIja(=s+*n0k%aNY7} zX3?GBraMYb6wgIyK2+J2Zir!WH2>eOH1e00m;&Cp&s&G^GHE_k`fG!d@Zt1CW)tt& z%Jd$bQqru#7^xU5Kz}YHR$UW*;gEiOJMR7b4<_dGRiR-^DRPT@NiB_)i{}sd|27rp ze*DY$yZ=}K{9yXa@uFj(rsHFmQpCvT;AF0HnW%$SW%;xiJ4x)Wvf@YgaI}Mok0B3_ zvmL|B{;4phHQOR`Dm%o(0`WAZXED%c=bM^d4+lV-sGQ$2dov?x9`=-^SyL12gup8X zTJ|YvusWCb2`gyT$C`}}*O=@v;%iu>xZAsq=&vg9?ujY2lc=XY=HSxY8cwkMLSId- zB`zU3AL!Di--zmUkUO4Pm2reQB@VgCwTTS%&2}lp^XwpwRmm8=FiV*H=Y3vxMkYg8 zD=MX=SKiz`b4w%#GK$xdcIuX`Z}`4bVJd4|IHN$;%vMlX===1cZVuDRXSY_h=p(I& zuhX)xyV|6#JcqeE$4HQfOWd)UGK2Ru)^#bb%rDqQQ`<9nxD84sZfump zF;IK^&FEIN)MUY)9rftOQ*~|-2j9sc1+Uu$Uk!3{c*?VbY?w5;sbGuN=s)b1|6|qM{d0q#8aj3zA;5IRKS_!rnvu6_z5X%t06(vqh_rk0&Iy#fsr^Jjt!c$fc=%qb z{NY6n>o4Y+^@PH&27Q{8*HbbPBj5n(tRZ--%W0|sC#PuXBz8T)Tu`C4<@yzir?@ArnLuL zp)3}SpDv!FzubDX^;QSY_B>MXqt2ZD+4hyUtXp1vaJeR}=h~Yx)B)WJluHUd-5kwL zU;6O;XTZ@z&Pm z^%2E8yToG!oX>yx>u>XVBuF&INHZZp>GpAiqzC}8&TY5&LhGi>v`D+No zZHHLnHN#aspOj~m?eM4=Iew(c;+vSSYx{?0uZt2*p|a@hl6`(9b^-r@;$GHM6Rdkf z5v`H-<<&GH_Gzjhvi$H2@A~z-y~huxhvvsxWF5;a_*W4+Cw{_Z|8Aw2pT1hQ(_rzgf&eB)EinHIovu?!EB*wn$`&tAeQz`3v`hB}=@RL7I`6mQP z<`t*0%ejXWcRa@yY zJn9?aIPGVtP@SRcUp7Y>=ObD3{<;$6vEa}?#iu`*0|NqPg4*z`wcZfMIo6x5Yu19~JZRTxanQ6V{VTSo*W36(Xz%X3sMXLhO z{bFOzebh^dm&nc3#5nGB)VA507YdPRw00vuQ1Ex}DqC61i|WC(!1g=s+eWzT5+kMG z>$^@7FNdx+GH(@Bc6ppo3xlth!NzMhDUzINt61y&!Hwm%mhl|UeA9xJ%W+MbDG3Ns zX_0Ol@%}tR3qwN%3rk>bew>1ZNreal#;y08(v2HBCs)t?)>ohVEc92dg^x8I%wlIB z;&N_%S9~j2)c#w0SD0VmCb%)NA?}?<#^2r~e_uK`sIPycE8QhFF+j9G#{}Jq)og+5Kkr|G2rr|Jht0?PT3N?cZ*@+N&1=ExS|>0BH0k0f9g` zrSd-aA*z-hNz!o9a`%t0)^Sk{{DvXGzfmhTVx%1N3Brx6YF`I>1M(4-Jo~S+J442u zmpQDy$xHd#X4uv%t;h!elCKkHv57u69~4-m+lbjligCMC=F0r3SlS`I1o?7q|G$uY z^e@A}7$T1pzm<%~!;kehrwh-I|PD(RFR@`&9Qlrw1C2I}mLDd#L?siUi(bHG((S=(n*>3Hua*)*$pjTYb zA1&CFo{vyXjkfh*zKKNd{OxDY93wmy^;3m5PRC+!j$ZvGk+VLQlH7fg$c5?2c^+#` z%P6?aSM#x~UxiHB*oKM9HF2r12OLcb)IpA$;lO#HZVWXp{4gjRKcV%ou&Uj5bk8|K zYmy!vcDQLW*rpC5MLMFfU4Q7t&&x#asW#sv7Uw?dUC>rkdKWze)lpj%f;{>X-2&Xs zC}GKY)SVF?Ui0j3cAz=7-t-n-(;9|d=fQ7=exE4@e5!**C0d%PHdUr;*_BUpK|}5p z`ox$ev)Sp%xA%S~)c7naY+oAey~Wm8*TxyAgx^RH)R<^p?g2=FU5~@R8J^C`LWfCH z(fap&6%oQ?DY}(4-g1XdTC!3blfCH9{IPCS!C|zy_9JV>5uKcHymXGI-bA#O5%A^X%z|nJ{Xhgx}PjZG^*RVl+1Sj7~Yk0IC7U0 z>ZkZ9?mFSZOku&{nE} zm^K*8&7ij4&QJBOAIz*Ns<>^GCC70l!Ih^p$p=!8LmhR~)g_`K%`c71d9&RKZgXt{ zgn!5*ePg&ZogMJ+e~%J$&s z&8d51!#Rud@#Bg!J$VtSVqZ-^-i{{@$gJP3DZ5{6N19!y3cMRTY>j=LXLnFrY?1tO zbi}sWbU9%hrgh$RihdeczcTtR+M#AUa=h8Lo{*AI$WWEC-$`vJAcM~9&jW{t(C27d(7$@Ri@Z>qkrZdR_>vWn1E z{qC90`e8jE6c4)tWG}}ie#SCzbZ*z#*;5CS-f;fgqp$=X9pZzpOT}o&9L|Sm-4f~8 z6H(}n`yGlC0egl5c<$G6Pa$e_q6QoGlDh3PT;>! z)LFF>WWeTkRK6@akn-_-yX^q&zTj9e;ZJs}2@ezHQS>O3*>fV)L_49rk( zkd2dz~f7%xBzfZhjlP;peww0X-3N zJQ$0L`MtGRs<~P&63=SdUT0NiRy$Ov{I!`INs$Y3ar|7|XyEA471qp?-13syPSwJ` z;Mck86qBl$Q}KZid-b!E?EDg(Ka4KV2j}Sx(ribRmhgH_15NB&)&bdb7nG52+@EZC zSB3ApR@JR8Wa(nm@8Y|YL#CC+hPqtp?DHv}VAt)eClnm=C@cTNystt~q!%%NJ<8Y# zG%mcjkJ7c7B&fBRseQF!bo#@{_LbwEvE~f^oS~vM(wEkJjF|QHlBUZk zr)kkTfm*9AQW{HEcX=N{)?@FElRL--yF;QXev!j$Xas)qj*`5b`LHS(6hd)^;7wf7 zqi8Mfsh;e%Qk3lgrv7AaLXzsA^i8dTdkvrBReu#N|7wtAv2*^XcQ#y<{G_^PoKiQ# zATQq>d?U})7gh%vd{{|z9y7IzsLQ2W4K2phC{}-l#_)J2-_DtzS%r*gl&C zmeF6Xa7YxuTBVr+qbZ$69u*qJhxc^-*D5USV!C|rG;_hg@zu50?ke}Mg%Icbz)Yg| zD^Be|+aZ&fOiR?N*l1_-YmWm5eGqJU736imb4|!{(J{#z?e|Jbj#~Yol|O!kRCa@r zlqQ8caulb_JzCc7PDZM8dm88+JyHFXRT&1d4i6n$-F5mS3I zlQCF%r^Pm%n-~0a2EtwO>{Ijde(i-hZ*y{Pz>H&+RG!bwAuAYOrCWTjWL62)5hhT6 za%pzZEuIA8O_d~0(imwRmn&bK^udD z5#xnxj+Q+)hub<_LnMo)&=r<(8sw{hXV8FBe|dD-60~M^zte|EsC~- zlN3<~8p)CunYWr(!y>a4+kqT$qA;*b-{+vaXBxm~&tc6f$pJs;|B#su@l#Q7=ew!Ll7k*K!o;Rw(gE%k*he z;LabV-99LKKHo3h_7I#c_TIRALt%F52h+XZZ}S{g#%;Cy^zpwb02s$H?aaVJCjKP? z==D!8+rM63&!}r`qfhj~?sEo&n#9z#NMj)VLsy(H?^jo`Cqq-2xy+#3xmLaWGK)r0 zCf3GUJm85aemxf;@%+k>JL$+rr`r!Cx) zrA&qPz+FJ%k`+&~xW?TaoQ_F4+e|ej%0~P}x3E@CkZK)p7d)OG{Yb(;DQ(Buyh>Qk z?v|soer9zoj1PMwVNnIuKb~qDp;l4YX?M|L)q4eInUVDUv}%>ss${BBxt%rrK9+VB zdJMIH!)jR@<3J-wrE(`ftp44k*vQ^&ByYsQTZ^~wafCU+O!-$!Q6b5D?P_N6>f^(& z-aEsH)~4XLwD7aj=)-)=s#iBG>%un>9<>)NN~{3KuT7gsU0+VkE4Vn)V@uMBz@#3G zvkDX{&+k&jqaNcT@hB{FP~VcDq&}3yCtD+ZICQn9z*ow?9)wzc+j_qWoXqhu%oRLQ zV1;0JZ2jY5(xhm4j7-3T!Q zX=|Yn9y&s==Bhb(&w33E0y5t4rt}w^Y#Y3Fm%Xot(DT<_4K}e)i+!550UEB>3QMl; zrzcBMT$>#^hRE*qI*+}t4wDL#j-)DeI5*TTgorO#akzY{;#{mv9ZpF}DmpOJVssub zo>Pp*zOZi5dsm(KzDGUX^6UQoJyOH!JTzH9r~OSp*5wPY=f)=iU)A>_AFQ*RnkgiS zQvc_$M@0+K!?O9-mO-!7W7JJUbC5v+{f_rbYLmi&P|FQK3^E^r<|weY{S5Z z!l-2Kjg~-6dmjo;hTsEJ&KfJC_nL3t8M@l~gXv>H+tZZ_q6FF*S{Jy4#Z%v<-#nKW zdhfA%Dbw}5|3bj{U*>W?X2?+lQy6v-|E5PVW>Z|4OL)&yP-GAxn&P3eNnua?G7^6~ zLs*O(1}wfm@zK#q{%$62kq&}rb9y_PKRR5ScP1|h1X~(r%=jN%6=6hbae?~GJwazC z`#UzGPyFz^6?Q=-bYh_uS^~S(T_h~~N{#}7R)Z#_Yo_hCQz&;aZ9Y$Jd+q9>!P-x& zW#3eqhvsqgT1tI_o-bzz+oW*B29A~IKEptwFq9TSnA zY_gdmfQfHH`mc;0KXGjy?^ZHRuUajssd#%fq)X>bl?6T4wwH}mQtFSH@@fEh3<$?_ z+)l7T$_5(wVAgA?6};2dD~M$jxaz>yJNYr#NwnO^ek|+of#we;YPV2ap<<@71ZoYQ zk)M%!-$%>2uFdEOovL=@k=}jK`$14s*46(}-Ft^MxomCYp^AV?SCATdM*>o$ZKOz- zZYYWZfzYHYJr@R#7WWV zFHm#IhfdadEnS9*lPz6==^T53tAA{rY?omg?ouj3fb5)Z-uDlavSSzLX}q?>XTC2; zRfRa{j&Qmk$#5lB=e;fMV}q_-oM{_E5&KAs*E$_Gvsk$ z*yA0`qqdWGo{gEl*FyS(`R`78doaDWs#z)uD|R!rad}(;cydj=NMlytI(5q$ z+vJB-tgbS)#VS{nPg}NmiMQ4)C>pEjLq0vvfEGAKsyTQ;FwJeZCY?KmCEry-8k9SL z_^#`g!V_Jf2RI2sXk{p-#sF(F^w=3&Z^9}=F zS4Uh;*SF`2g0|N3b!Tpj9@};}k00JNfe#`Mfhttex^p(FapK zI)*I`&w)nsTXapW?t4RO`Nm;`Y@*ckcv0ZbmW{fG_?6`3gtqSHv7BFBJ$rEXigk zNm(*7-4VvoKiN!Fd}lhw4I(S4m5WU7e;H=iCcke(AQKn6))wz@Ba+8qZ9;?ggNuG< zN`r2=MRj)k^E2NWhM^Y+>;}D_Ee)2YB|}kH(P6|hK|Kdvq5+2XGX8h+pXx5(DnLSr zdUfwpo51kkfsCo$MDj$pfwVd5^{#2{s>P7mwTdpWMwq{iailK%gZo4ks}A31dRzC` zJ;DfGn}C<)ISQ)t{M8!5Fzyb$=%RMIR~DK*sj*fcde^N)TQ|vX<3cL9Bu;vtjRfuX z#SsClrtw{iGfBx&$JFL4;Zjyww;zwCnDRcO@v$Zvvh53~qWUPC9&^YHzGD;lXmo)| zBrs~1&u?~_fa`rZw4>b;T1(`nwp2jxPDw;^LHN$J z!u?0G0Sb3V7PT&0#w zv-;pX+*0@RUDc2gdlGrj9tml2pguh2XO@1Dk-mBZkDcLS`|3wg3wm13ve#@OXcqx@ zXk~Wcs(^Ni*e}p{2Rz$TT#T`xkG5aO5_hV4g;IE{5Et*Th= zmk|&$d_R4q)oQ?rrWSUulx#!bW2UaX*OOk)81)Q=^aoWTmuNG`9j(c%*Ey2W^0#NX zd3Ek*7@-Yw*9&a*OS1!m9A?kxYt&)pJ(yt!oo=wJO2zvuZlAj)k9%rf?>)^cG#<6r z$SQY`cABX6e{Y1c7p2QOyO)dc_Z?!-8>Aa{nP=Y-{+95Eoy`gBc#Q4b5myKNUEFFI z_xOtag0jXGIKO(YC@97&XsmEnBk4`ajP&ip{IS6?Lw2P}&#y&BXafPB7b^D8sL#}@ z3%(nX+GNXzW2kAFH(N5{kBA* zWUzEIPtX6^sK`k+Nx5V3isFoUym=3j;j%-LGlfN-1V4q|=gUT!%1OsRyWKw(^C`OL zeYfw>dIW5AI-te)W>aAq1rMWHOq-^B+AY6YyR0{t*{I(n)Z5p9bn6Iq87#4dug$Wz zQrOwP$$9%s5qcC`@ew9chdXIR>+(uFb=SfDk4mxUMj?Ql>f!Hn`nlL|e7$(>YSbGf zfkTYUaMm<3nN?=y{f)$Ura*I}I zETC@JIjiwHIh(fw34X-Qy%1UgF#h$CM?L#EPi9$W!n}P!c5(5S!kyD`x+uJ*CYFE4Xq{{_8 z*{_z+q_&p?>=#uG7t$?A&1u4nqBm>FS4sR{pBNr}mQI;>uX!B%GtpBO>dGer?4Z+| zV$t_wxb{))3VK{m*_u-DX7YyclethEcecn$hAtHc|BhUHDVe5hO`c zl#Ma%EIr7w;pdEw>DHxCSjI_YhBVLGMh&&Ds~`-va~H2>*~+_hhDpCx z?zRlxD}0OAt%XA}v1}req`ZZuckYePH>%4JU3BhtkIn-~XBl6w zJn8;ZKJ=wE(J!~Q(@YLtRNzvMDtW)g6&3fe0}Cck zA#It-5_+vl2gX@tFC)G@tx@n&`*MS*4&FbfvXdcrIg`*|!-qpbX&UM+ul2DUhaz8? z!uU#tRJ9H3Q!x`<*1Ya+EBs^(Va&5YGqAqF6F-x#b<8yTp&WR%VX}PYhEz=reymRz zn{kVRTipw${aW`cnFrpe8$=_fx#ZVP>1#9Ao^=l5vexie9v@DH_2*4=8tW&Uf$zL4 zK<#aH!+eifYnz`F^)3`x_;||;OO=V|LeBP~pny%!KC6+to#j7=l)fwAvep$Sco~ug z^P}2SHa57zn8_I?j9GAc%oAFX&Moka= zd7#^UR8F;05@Wn;r@pt%}y?z)hJoATqTu&!YCHusz*GRg$)N|9>; zQs@bfAqiBjvmW!=d|LM>Kv?3QfwMfQs&7JKK-kX|N~@Muqdm1R*Id*U42{8mv(Jt$9M zXGXg^ot{^`iTfO;mRTnaN!aFL3$1zurKq-K{GK~$DBm6;m(yL`4V#NT4SsP%kq!3M zeGtk4wUNwMr-bUR5Pyq|&e6`0H-cwoNsvd>H)S{l4{Zij+6STG9hY9!6#jWfP_7n0yal?m(PsQc*#Ej~@C&qtkrJwqH%q?ei?_nMnG&Wdx_$Lc6~H&7tSI znBGJlYL$Ta$9p z>qyjlyMdV-1LS)oiUoF@w;72^U0G(#2%k zf=lpSz>KWK$pw+);^cCygiA)249x1MY5_moUc|u-W0mL`H}JO!P?s7!l1NHKOM;gu^VsTCiyCy zJR~DSAh6Bw!uQ_ELl7BX=XQ6nREylw^{4$fH;B#u+Pp~@rxbQSV+1x|2OkN*TZBaQ??!Yxh^e+-JHJs^F$C(Gjz!23S4$ta#|-8 zDCbdx%*bo}OZ7EAt!RACh9fk=E$nPj9PA&;MAPPb_#~4i-&mwO&_FLb?JyyLcOC(* zN1fM}9NP>pOdd(ev1muorjW-GJCYT4Vyu{nt~b;obW1#3K!F#{0N_c8YSF`9=mIoL zz?1N8fje^}+b4Dr3Pr!~e}f1lmw`rikCoz+Y@4Q%3qG?WxRVf^(l11g?b-FGX&wu~ zwG9ivri&7Yv$t~CFE2iR|2%gmK!;PNM8A{RzTNtVlE*4A?*!2E73h4%SR>42ERN_J zK#L3D5hPp18kggcBm^`j$Y$az*Bphl;3gh0-9jMt$x~QB2n+;`&pU0>!aeK_b=Z>? zCo-8d`5A#gVEF1e!->MMH!>p^1ezfSOA^h-1wfx4VF4uPMT7|l2%wIM#=nGZ3=$~} zUo{Mu9e_Snuao;3Gx>RwEtQ5G5dmPuNR^G^5_n*NsL(jMx?8pjG%uEmSU!;f58>L8 zu}3ifg(R2_-XIKPVc8s?T~qh_1+z~wLQLra|7x!P@&C210nICM0}j`JE|g*_d^z(_ zNP*T-ytk{;K?3Ua-tqG0E6 zT^dZ*6!trAdpa|LbKK)fswGW^oksn1+r96{C70Cy(Ez^>vD2tMbOGA% z_GK{D5pDnM0;m(FPFQI#yvR(o`BdPk9zKZ-Uo|r42q9k-DD(7c3)zLRW5!B67U-gf zWxddaxcuEToEPXh2Tq`udRVC(_sD!$iS z#CxCYzgpHWuqb%eHTxI{hr7AA__lugvpr;g{p0LRT9y2CYlkSGi4c_S_%Y)*7&HH+ z#sm6(5=Q$tjf}9{Bm5)OKllBu+QXl(8wJ8_S<%t3S*_@>Vilx0D-O{G$r7;wGO$k_z zMm2wTko!`8y2Sg=E@O9EZkV?Tg1fg`apz&&qwPg$N5WS{+9CTx@VCD}g71u_X+baa zgCtPDK>FM{UB{j>n_8T0xQVN~{*f+y?8LhEG7Ui=GG50ZByl2{ms z5SC%}T+D@9WN_^3?i0%%86}^u1DTgj~DrE45r3f(rHpeDwcfgK7-v%o)8SPR< zi+s5hx~A$mNWQVX7dOc(I1!%&0v`Je=#z7ey$JJa@do<4TRO4+_R|f}-qD5t*?{UN zJB}!!7>4eWn_D!B1h%6=AvPQ#54I>8CLU4EbCbNu5De5#5%+zI_!BCBE6H+f+@i@Z z>VAp*Kzq}06L+HWc0hGSk8t|lRVp_p$1Iw6IoHCpt>>oc6&{&~`B~%hZgYSug z%;&sehHi96J#)n8o!tP;jNs}OPzb@TO&N0>5TFsUT)E4mXB{YJ+4ThCCAo5qC9^=P zDz+@rrt=77Y-pUmHMH`!W_x9M0>an1FY(DVoGi&9H1=~NL^dPi*tQejrm(L}D!<~R zOxxkoPZT0YANEdVOfNg)jDcyug_(@OAgWz2C*`zQwipqpZ==0*rjwIwEPZMvyeV$R ztgnNtKF+`kgQIPqal4&>Jv3&rZ`Ymt;a&<8$ zzAWy<3N8XCD1^U07cFXc9xR(~wD*N->He$g-FdzvPs_sEvt{61Iq4m6ipU%14YzM1 zS^I3Zl-EkPa{TaD4I`W*Xa>gdRMFi6y=LHZMU37VH)DAeDKml~kUWjpZvb%*TcMCN z7!c9Wyw=z!+$5NVv4osF&^x$u%7{IKa;0o#`9$9=!>oZ(`DaBdQFEpJBqv$?77BQK zVap6fFZ(oqzUeRXj0&atEUhXTHWhBGH$}JW9Bll0#ZIJH8hVZ95oN>{V$lMkOCmiWj+(b47BJrv_?~Wnh)bXkhtlYCG315X{{l&2g#qf69Pw!T zQ~lXC$_Sr&MFx?2fGvCt+RN9*~;i6>L6I)R;W zV6hWVq%hE0$H1QkZltHm?(V|Z{hUY-2J?9(g-|FL?iP^R!MTj(ktWvU)=kE$Qmmv< zXgo`$T7#gwgRKyR2%tk5kgftOln;gi4%o_cUE>Lfp4_Cq-0?nF*tY6SmEm$nv=_z1 zP(|sqw?ZmY>HU8r0CerwKTS>3jZyvu!kfPqjEN}(HMIa z%1K^oWd2Kfdjadyn54u&(6re3&7R6b_b@Sc^v? z)%>yyqWM3n<=bme=qaVMa}%?6J19_nJC`ZvqmK(!BPMoTHq#7ibK;N#t?>hdz~>c) zjCBIW`ni2B7*eytx?zcYP1rZvcGL%tUVa~4HP_>-tYJf&@%r0+f056_#_BP}StuqW z3pw$9hZ^Ndn37kS0Xn$Un8dFupq@Dnq#@-OF2NCi9~hdq~flLQ}kaEm8Pz zQrl(mVfZD|?`tNaz_J^Iv-+}WJlBodYt0%m^r035nXkE_xqEuk@6&j@i|(q9RS+!y zYj`7vwKxe-4s)1(9K3Ton(Sg+mJM_r&JKHS*A>p!Zm?*P>46zW$L+hu5GnKllKGm; z&w&j@rHy-J9kibnUnc~zE0>;pLT_G{M8%;9NOi00`&qV>6DY%kfq-L?q==w_PY zY0DYV%*a;juAIz|UT-JUFHGWAGWHBm3{fn$U#RRYqxAR5rcTokfIxRF zOru5>d(9+_(>Q1jH{pVBVt2E3>aOq<%x158EZn@sGBHRKBa^>=L>CNXS;48Mp9u*i z<>zwpT~kHB+C5ypZZs4(PN8?pw+f|En?-o%Nw!R1e0-FRVZeCgvbe2TcjSk(CPMuu zpIUib4+0`pbo*l~7Gucco^kvqL;&_^oD*`)JStH`(?7kp{T}%SRPrcL+zDu8+U=4Nec3{Ad zbwR8F_BJb^V0}S=Hv;P@AUYok{wEJf*$+^=z){)C{*;jktB8ujEed)Sx1Owy`xC_x z-vusbp%#tZ5wp4_GPXL2M&%Gut{#uvL92?v61EJ8bheidb6;!8T#$@8rUeIE5OC@K zh%LNbM)=Gm3XT*snbAYu0>J3R^LLpYn!-8ocWr*?8!QXDmUxbvD^ij>-LDP2YFcb& zOb#ob$%$WJ4vRq3)8aJ!+PN#LwTE)lJhzt4>+fPhW{2l z>#Q>Jfd9!V4jA^<2Jal3@rxQ+&^0JC>#?RQSlvVSdr^(=u&Nc7z$>=hyd$0pFyA1F zGj)L3s130JIk;!QxxuoVF;v4|wQ_QWLe=-mXI43XN@=yrDbJZdJ&n-bz5feDjg$Ig z_$z;+$WAwGNO3oVj414?wUm~YmKl<1m zt@`8>#20sJayE}U5CQc$&z37PEY@EcP*b6YHAMR6ebtmvx0&cNQoLR;lO;tdu?mmG zl$UiBB0|>3RcIr4G+W22#Ae41T9oSLqoHp7*OJtaJFhUZbK7sQdUp%2xg~(ds-^n- zc$;wd2lzWIP{8DcG!7LNXWBKcL9gK~CR)Uo-##~r1EdhK<+TEj)^~P4aABy<-Ybk02Kd&mdpdE~2}3ED{Nk z41dtHCI4}3xl7~vq{OT@%&pM5t=q$W8Uput^deaF#92-Ci38(|9kHN}kQhly*!*Kz zd+0T)F{l1}YLNV}+xJwMBf~fU;}lAuGM8eD!#IL=Yhu=n)grU#el$}Si5u~)z`=Z$ z4M7BwCHfLKE{9g)!3DTG-9_hE^n!vr^0UW~q=PW^%uXqZNBaa_{)UxZZ^c|)o;2EM ziW7S%7cu6ki~8xT{>aLiqDWH@nWaLK7lvTK+7X#(p%L-wt?ztcRVGTxZMaER?Xlat zzd%A*e<9#S`Mch0tn~|>mO|*(VqI)<<(*~S9yf@zuuI z(6JJpbME4J6-5oVAJHzfQMt#?V(oDc1BQU55av7|*IYw@9WnH@%52`QD1vb)Nmi9;JyK7qz z!JoGMx5gSrr%UmaL-$An!u%7egT*I+ooAyEUkWHfqPqR#ykz&DKEO#c5Ty#1p@3mF zGmvKpEc}8YGwl04uVlXC%7OKf%3uh)DkfPr`vdYhzAtN@iE7kxoZxiFJ)(DCvS411 zHu6%SI8wI0Nmu6UUf0Y{42j&#SILY{4CN7FzpPp&b4ZeZScUrj^|KXfzg&oF^W5cz z$i|MZm~n{DM^!93)v*tIzA<0WnHdD4)AP)O%=7KDt4SROL`Fh%LJnw*TRg$b53Low zzN(KtS5^w;i3u6E>ovvCS9$tSlhV4`p(rn|H3;%hJ~H3SN6u))b-|W-LC=cP$C+M) zPgYY(qMScb{C$y>R9T+-m-V%)Q)y#WMGPTb@uu~5IxN~;U$jx=D5aba_OuHXz@nhV z$MFaNb^qa0IysoH?-{6_YM8f`zbm=RU7^~;VGj3XH;B^r=eVMZ;`W~pB-LY)snYYe z(-sskJDv7qtD`m*XKiUz%$1W7zt=JcnrV=Dk1) zSo2FacSmZw+lVU=)fqapk<3&+@lR9L| zHRYpnTwx>|{j4&K8Kq4;oU^H{Qn#vWQgV@peb;`j;{7p`)s&PdDtEY_&zVJqP$(2n zC7;*C2mt%>_>F=>AGpc$H;By5j^{3Y{RUEc?sb>1aY78f&?LrmDtASOnJW;|HC7vo zM$a(;$UK$rYm$J}-`sK}&;OJj+e-oKKg>OPCVr)bSwBLFwfmtqu+aGVUMhJ$I+Jai zU1ciya5~Wq^rb*1TEWLPMFErffsCj@MQ5NQhB+kQ;N~5#OPh(E2vZi_Io&VzpZ>^< zDJah3h1v{3L}IHHBZ)9hptyq+@rwbC=-=GM*oe)jGT;zQEid6!0ES=4SZ0f%SNlA~htlHaeZAkGMm@jRLO^2HNa z?-32|O1z?Do1orca3p+&UzPUt`G|>)h&}VICrG5RFv{+uD*togP>!skF_n?7X!g>* zx<9dr_fIo1;Pz-A)ZMv~rZ_5W1Y}jRz(apkvQ7JPrsTGlO+z*6QZhkzl&X-u((%%u zLO06EWRS!?dGL;{3ZHmpg}>uy=$qZc0EcSomui)gci1-bhr8RBpND@!Q|Eu1T-8_N z*H0KB7PLOoX(iRog6&bvW{7)kJsz|`8mkoz#JgQlfhpJDbgZP;rX|n4tH2nc2ANvNk8i}t*d1rSfe-kRz>G;-ni z#zt3ipeV~RAT)FCJO-V|5-uz;eBMbvsYi`CxCibna^=GOiK#3g(1w%OwHiFHAJ>%| zl=}sCLaj%sDr@?$w;FD8E5!}oaX`{{b?p%+9&88F=Asv~ihS3sgT+Y8!S}t?mqmAl zi`3oSdyCzu2bZN^Tz4ftEqLil8RTgP$FuI4F$eRyB&ef~rDlBWo2U;={!lK_>qcl1 zz3%3CHG!{4mzAd6Xf!qtwPTaWhdOgU=&U6%BU%0v41X(K$!xQeDtqtT(pXwezA^4L zW%fk01X?br1}hAGPTlR?jC1U!iMPtC7BM&vC%!#pf6oo6!YdzH5g8yw>Z)9K^Lp>) zue+0^O+3Pj`r|xNo>Xvh=#U2G&C*X-U2e9JsuuEJ4#cCg6IWe<9h(ajDBRVmfT^j7 zF#4|P#kbc&^C!gkIoukZ@3Ylv6>0NCOoa*K*LU9oP_YA`Zan!vAXx!uf%YgeHIFM{SJ5 zEEG(mAi`h)h!6wP+9#bP>TC6_=9@*IPloB%c2{L?JPu{V&l~lBSL1(Mo^@i_G~#LL zzz}hCUD6+I?6#^JWD`9O7G?58vdYQ+4-u6~RO|Jx=x#N!Gw&93sEQIwuiVSX=S#4~ z6&eppX6)`;{TOj$>YeM_V-il=vQeY>d;=0;-H?uVOVY=_gSZ;jJ1yo{6b_K0_MMUY+HR$MfE#r9QI4I_z#;ssU?< z;>t_0)kD#0@W-}sS1O?#Mzz2kJ+ih)u)L|-i=&+ti446p9s7lVsw+t6@xl6s^QfnD z$(KgHHH66ZO;FIe-7D%V(0c_zg2xiLKRS~R57ul$jcB5D%0%B1QOr583y4(IOau(e zM~#qY4j0C%@ds%Zt4M!lkH}I`0*LG-wmv&i&N>ybRMQD~)y};x5esb=xYQn$`%XX* znCZ4pPZJs0g%CK8ii6Mn+b_I;;MuuX7aO@D0-}4swSS4Oo(K4F(VgXU5Wu`6MIRvi z0k0^5Bp^hHkQbq|bH83jXGkXyeLD~7kJQw*=t^L%KKWwVB*RSXIPTNMpG1r_;QGP+ z1+q0lvTr%++8Zl{-fnap$`qwbQOl{A!!)e*Qu46v6s;48J zviF{MEbI96T_c+#7CExf_b-OObC`|A6A)$Vc%Iq|~6>_~5XrCDK_8sG~#2S6al z0mHqDMXMA6beIqsw_?S%_M*3n5P1p<`d`ins#cC7zyt!>0H%SGGN+CQL{(k(0C^lwY;L7GB zpRap>`&)JUAS5)w=OCiJYcrKEOv*FX5>m{jkP9_ZV0io zPwOgXrMntU4d;CJ-m@m@G_O+)I+ZFFxJ6tXLV35+)E7tERQeT_*N>hOqg6xXe1#R$p4&Rh# zi7%E97fIM8ZbhW4MMOu<;0-NQI~WgJHp^EO9uv?ESMqzB&@oinO$>Ir+FZd6R(}^z zF|GlQ(Sk|QSqh}kR-|P^?INQiXg)I2vI+Vc1DQ?_MG?(^q2J$%?JaiM;p0+fKV!r- zT+H4{LQ4g`rRx&l&SomQ5jJ|NZLGS{US$JC?ILh>O^wRU^CcegC zN;duK6Q9|-gv)ml=Y#&Ypxj%NiW!-U*R><``~3))^Q?PC?=Y4wMo&1uH~N~{ZasGA z<+}k4C6QVgYk7o7>CTXgbyQ%eJkt3wyV8qH_K@yC)q+u5e&J0XcTN8ES58ov{YYMn z165#_P|b?blxm=4TMXZ;5YY$vbd>#IL%66XY3_G^6nOzvUd6&Kmh!IUP5xm`!K+=! zhmlUIS~p0*`9f4tpIsrWlRm<|sscJ|`w_r|1xcE`pNYZkXGz76QgE(meK-;j8%j83 zCgbr2YyV6LZJyiM+Bi%l7jWf&JK$91*IYgNa~YpF;R@7}=hni{)2}n27hMszuWKle z0SD$MspN?@Srzk;J%!^`?jZpI<>SXmnSLcI$7U=maX=5)_T>!W5NCEkAe;%iik-OZ zG8og%;r#`qiHRJu$r~}pT#RhcIw)XXSP@khQoHlR9!G0{^wf!&yJuhRaZNaxV~;oV z*_j-9(J*?Ss~Y6*z`WggVAW>EtQ#mSz0j+KOI;*kS+O(Eii1-a9H@+r!l8(U!7Th2 zcHVxQ#wD<|`Yv`2BHdFkh(q$G$p1rq`PqigyB4C5n0T#Mj@uX)O(rixA+kJP@c6*Q zz3%C2OfLv=85B?LzZYTY1@H-d$az@hT7Lw@eQ*h~EIfV)-~I(!?H6yJMaX4}!>m5Y z?p1^t;b>n?(#e&I`@tQ8E>8kcOrbec_$56 zEnQeq@u1*C2cL8C#OO>GTt{Cy-Bj;0llG5t9RBKz=x2QPjO$|oZd63Y$~vf|M?RMe z2Kx%3O7JD<1NS-927iKj2s)T=oBy>jx-(!O$k}TqDDwR|@5yTOa|HFbzY*%+2V6Wd zKeP@8e{PxawMdo^oTR-lhrhaSPAjy!XpUF$zM4xlt?#{oC`(;sR$$c*X<^3W-f#mO z71BrhcLTLcyBB?QvRORQMW6be1{t|3I+ve~lzQ&RD11_5-?(;5Gw;@}?y4xeN^OPm zC-_rtj`(8QS+r7Ojob!P;f5gGfk!J-oSk=Zsz29qGN)#o0chI{kr7>Y@8KIk4lWi3pdkwzn zcIn%Fq7eZBsB5dl_k(nw`&4Vl8{1v`RaVEl$EmCm+S{_vD(h$aaq+?dMKOH9wAMX@ zLy-w7pUNFgYIJe}<>;=XP*J&9o^i4XL9Y`f9(>2ZroRBns|(pkS#FIj#CA|Nm*L9L zmIMm`$)9l<$(g9+05YL5@Qqnk9OB_98R4-{O1K2MAv=8g*I70eamY&^?-h(gJqSQA zpbN3-XSiV>;)v7-p(jOCDc^0*^_JCU^|O?7y(LoExotnN7P2ogv%bLzXiHv5_bV@$ z-zd{=f)F`3FId*CvD&H$&|}1I>|Sawy>|q-um>)x`$#<2kjDLpH93~sQ{aP;SL;+( zJKrme5f;&Rc(!V%ZKUgMOhl`bovz%z&kdos*A!1zQ<30>*A)H87iL@IXM>qZRKA_M zdip5;18nV6zJFuJB16_7*s?WXNPN&UAwDyif*KsmR#zZXRMGeaZ8aQeM3c@D_L_M& z?aS!0^pl4i3a?mkH;8|RJr}zVZ>FY$&oN}r^BFd;Xi~8DzQ`b?9uX&Q=g$vOriwd| zHh&R%quj)`E|Ze?n$@`Qa_vh==EsV>ggZvC-5<2h9#} zYYok{hJs+b7_dpqYHHvW;Wu&c>~Q**XpFC7X)t(FK{4VwjR!gC^S`MC0{Q*=hwFQB zQOiY5=|(*k7D*2)`W1m0jdWTeEq4bOWw^g8gc*ZYU1(|P5@j@UN4-@A%AZ7fA?)0x zmWwi~qHjlxj^8yq3k}}yzx>gkVmIw>Zf^$n5R01Ubjj_B>jc$Yhr$AM__^P0)`z>z zu2$-P;p)>t-S=zr6q@Ur0 z5=#xYzg*-a7bGMCogCvyQXRbyesmUj8i4Rc^!m%#JsJ50vS$wz%PY=89&bRFLh43hbY81|R3 zoyEAEA7N|DX#1oi?E_OM;#za6Xqt*c!EBd%sq!{6&M}@5wa5ElX*Bt10LT}(?xEe2 zi|d$x6Acq?luu$WyR>}8T7U5q-+|EYi>Q*1oA^>}u@AtW_`lteN$#n9#@7e!B|p1- z6+qr+I7P&2zd(FXFhJ9V{Q@mx>m!!-C_%h>>Vxd1kau!S=Z6of{N^tne)JJRdZxmL6KGDj~5#CJQ`oGj=Vi& zupP-Q;g+^Z%JYwbAl*);Zm7{3!aN zA^#KWRG2{tw<7b7acFd#a5d?mHM+(5+sb(Z*%#Vzd)Z4-%oy^`~^B@#{0fZx~#j{#JAsI5&WA}%JHM`mmM!aBT3~^6wLVc z0-TVv|MjN}+KgUDjT#;=A|_5Dout6#A2Q zN9WR|H8NNilu2g6g~m?siCScVvm44* zd-+lhYgmrRa2}4x4JZT@3W(fny`EZ824;V+*4N%un8#-E7CdCRyv0#;Wq4;zZ(v#b z`P~hYRKv8OHF&}7USFm`q+`6XS{U5ifKS*!SQS`Yl*Em8M6fJ9a#~0q|f92PKT%5uu)5^m?rGX@St>7;X&@f}b?`~OlxRI#f~e8_Ws zB6F@@ZD%hO)+K<5I>z~jr2s_3=H)JZ{X+MppeF>nX$BktFIK?=h!C&13-x)H+L3*0YjMk%b z96?t_R#+c*>GA|^C|{fGtLsnVq3Fw9=kCt79-pATvB?%J!%$75q+pRQ%*s4HiLVpkU z3qxc+iJH`4wH6%Z)-|f+5lK>b5Pz*Rc76*q@E0TQTz7o~mHbJjf4r9J&rANhN_hWt zb * https://github.com/LuttyYang/luci-theme-material/ * @@ -26,6 +26,8 @@ @import url("fonts.css?v=3"); @import url("pure-min.css?v=1"); :root { + --primary: #5e72e4; + --dark-primary: #483d8b; --main-color: #09c; --header-bg: #09c; --header-color: #fff; @@ -50,7 +52,6 @@ --gray-dark: #32325d; --light: #ced4da; --lighter: #e9ecef; - --primary: #5e72e4; --secondary: #f7fafc; --success: #2dce89; --info: #11cdef; @@ -281,6 +282,7 @@ abbr { cursor: help; text-decoration: underline; color: #5e72e4; + color: var(--primary); } hr { margin: 1rem 0; @@ -294,11 +296,6 @@ hr { ***************************/ .login-page { height: 100%; - background-image: url(../img/blank.png); - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all 0.5s; } .login-page .video { position: absolute; @@ -310,7 +307,6 @@ hr { background-color: #000; background-color: var(--darker); overflow: hidden; - pointer-events: none; } .login-page .video video { width: 100%; @@ -369,7 +365,8 @@ hr { width: 100%; min-height: 100%; max-width: 420px; - background-color: #ffffff; + background-color: #fff; + background-color: var(--white); } .login-page .login-container .login-form .brand { display: flex; @@ -377,6 +374,7 @@ hr { align-items: center; margin: 50px auto 100px 50px; color: #525461; + color: var(--default); } .login-page .login-container .login-form .brand .icon { width: 50px; @@ -416,6 +414,7 @@ hr { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #525461; + color: var(--default); font-size: 1.5rem; position: absolute; z-index: 100; @@ -428,6 +427,7 @@ hr { height: 1px; bottom: 0; border-bottom: 1px #5e72e4 solid; + border-bottom: 1px var(--primary) solid; transform: scaleX(0); transition: transform 0.3s; } @@ -441,9 +441,11 @@ hr { box-sizing: border-box; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); color: #525461; + color: var(--default); border: 0; border-radius: 0; border-bottom: 1px solid #fff; + border-bottom: 1px solid var(--white); background-color: transparent; background-clip: padding-box; box-shadow: 0 3px 2px rgba(233, 236, 239, 0.05); @@ -467,12 +469,14 @@ hr { box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 50px 0px; font-weight: 600; font-size: 15px; - color: #ffffff; + color: #fff; + color: var(--white); text-align: center; width: 100%; cursor: pointer; min-height: 50px; background-color: #5e72e4 !important; + background-color: var(--primary) !important; border-radius: 6px; outline: none; border-width: initial; @@ -481,12 +485,12 @@ hr { border-image: initial; padding: 10px 0px; margin: 30px 0px 100px; - transition: all 0.3s; + transition: all 0.3s !important; letter-spacing: 0.8rem; } .login-page .login-container .login-form .cbi-button-apply:hover, .login-page .login-container .login-form .cbi-button-apply :focus { - background-color: #5065d8 !important; + opacity: 0.9; } .login-page .login-container footer { box-sizing: border-box; @@ -497,8 +501,11 @@ hr { justify-content: space-evenly; margin-top: auto; padding: 0px 0px 30px; - color: #525461; z-index: 10; + color: #525461; + color: var(--default); + position: absolute; + bottom: 0; } .login-page .login-container footer .ftc { position: absolute; @@ -547,7 +554,7 @@ small { top: 0; float: left; width: 15%; - width: calc(0% + 20rem); + width: calc(0% + 15rem); height: 100%; background-color: #fff; background-color: var(--menu-bg-color); @@ -563,6 +570,7 @@ small { .main-left .sidenav-header .brand { font-size: 1.8rem; color: #5e72e4; + color: var(--primary); font-family: "TypoGraphica"; text-decoration: none; text-align: center; @@ -583,7 +591,7 @@ small { .main-right { float: right; width: 85%; - width: calc(100% - 20rem); + width: calc(100% - 15rem); height: 100%; transition: all 0.2s; } @@ -619,6 +627,7 @@ header::after { height: 2rem; width: 100%; background-color: #5e72e4 !important; + background-color: var(--primary) !important; } header .fill { padding: 0.8rem 0; @@ -657,11 +666,12 @@ header .fill .status { right: 1.25rem; float: right; } -header .fill .status span[data-indicator="poll-status"] { - display: block; +header .fill .status span[data-indicator] { + display: inline-block; font-size: 0.8rem; font-weight: bold; padding: 0.3rem 0.8rem; + margin: 0 0.5rem; white-space: nowrap; text-decoration: none; text-transform: uppercase; @@ -750,26 +760,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { .main .main-left .nav { margin-top: 0.5rem; } -.main .main-left .nav li { - padding: 0.5rem 1rem; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.main .main-left .nav li a { - display: block; - color: #5f6368; - color: var(--menu-color); -} -.main .main-left .nav li.slide { - padding: 0; -} -.main .main-left .nav li.slide ul { - display: none; -} -.main .main-left .nav li.slide .menu { +.main .main-left .nav > li > a:first-child { display: block; margin: 0.1rem 0.5rem 0.1rem 0.5rem; padding: 0.675rem 0 0.675rem 2.5rem; @@ -780,28 +771,28 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { transition: all 0.2s; position: relative; } -.main .main-left .nav li.slide .menu.active { +.main .main-left .nav > li > a:first-child.active { color: #fff; background: #5e72e4; background: var(--primary); } -.main .main-left .nav li.slide .menu.active::before { +.main .main-left .nav > li > a:first-child.active::before { color: #fff !important; } -.main .main-left .nav li.slide .menu.active::after { +.main .main-left .nav > li > a:first-child.active::after { transform: rotate(90deg); color: #fff !important; } -.main .main-left .nav li.slide .menu:hover { +.main .main-left .nav > li > a:first-child:hover { cursor: pointer; color: #fff; background: #5e72e4; background: var(--primary); } -.main .main-left .nav li.slide .menu:hover::before { +.main .main-left .nav > li > a:first-child:hover::before { color: #fff !important; } -.main .main-left .nav li.slide .menu::before { +.main .main-left .nav > li > a:first-child::before { font-family: 'argon' !important; font-style: normal; font-weight: normal; @@ -816,72 +807,27 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { transition: all 0.3s; content: "\e915"; color: #5e72e4; + color: var(--primary); } -.main .main-left .nav li.slide .menu::after { - position: absolute; - right: 0.5rem; - top: 0.8rem; - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -moz-osx-font-smoothing: grayscale; - content: '\e90f'; - transition: all 0.15s ease; - color: #ced4da; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - transition: all 0.3s; +.main .main-left .nav li { + padding: 0.5rem 1rem; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0; } -.main .main-left .nav li.slide .menu[data-title=Status]:before { - content: "\e906"; - color: #5e72e4; +.main .main-left .nav li a { + display: block; + color: #5f6368; + color: var(--menu-color); } -.main .main-left .nav li.slide .menu[data-title=System]:before { - content: "\e90a"; - color: #fb6340; +.main .main-left .nav li.slide { + padding: 0; } -.main .main-left .nav li.slide .menu[data-title=Services]:before { - content: "\e909"; - color: #11cdef; -} -.main .main-left .nav li.slide .menu[data-title=NAS]:before { - content: "\e90c"; - color: #f3a4b5; -} -.main .main-left .nav li.slide .menu[data-title=VPN]:before { - content: "\e90b"; - color: #8965e0; -} -.main .main-left .nav li.slide .menu[data-title=Network]:before { - content: "\e908"; - color: #8965e0; -} -.main .main-left .nav li.slide .menu[data-title=Bandwidth_Monitor]:before { - content: "\e90d"; - color: #2dce89; -} -.main .main-left .nav li.slide .menu[data-title=Docker]:before { - content: "\e911"; - color: #6699ff; -} -.main .main-left .nav li.slide .menu[data-title=Statistics]:before { - content: "\e913"; - color: #8965e0; -} -.main .main-left .nav li.slide .menu[data-title=Control]:before { - content: "\e912"; - color: #5e72e4; -} -.main .main-left .nav li.slide .menu[data-title=Asterisk]:before { - content: "\e914"; - color: #fb6340; -} -.main .main-left .nav li.slide .menu[data-title=Logout]:before { - content: "\e907"; - color: #adb5bd; +.main .main-left .nav li.slide ul { + display: none; } .main .main-left .nav li.slide:hover { background: none; @@ -893,9 +839,10 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { .main .main-left .nav li.slide .slide-menu li { position: relative; border-radius: 0.375rem; - margin: 0.2rem 0; + margin: 0; padding: 0.5rem 0rem; background: none; + list-style: none; } .main .main-left .nav li.slide .slide-menu li a { white-space: nowrap; @@ -909,6 +856,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { width: 0; height: 2px; background-color: #5e72e4; + background-color: var(--primary); transition: all 0.2s; } .main .main-left .nav li.slide .slide-menu li:hover { @@ -932,6 +880,7 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { width: 100%; height: 2px; background-color: #5e72e4; + background-color: var(--primary); transition: all 0.2s; } .main .main-left .nav li.slide .slide-menu .active:hover { @@ -940,6 +889,123 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { .main .main-left .nav li.slide .slide-menu .active:hover::after { width: 100%; } +.main .main-left .nav li .menu { + display: block; + margin: 0.1rem 0.5rem 0.1rem 0.5rem; + padding: 0.675rem 0 0.675rem 2.5rem; + border-radius: 0.375rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; +} +.main .main-left .nav li .menu.active { + color: #fff; + background: #5e72e4; + background: var(--primary); +} +.main .main-left .nav li .menu.active::before { + color: #fff !important; +} +.main .main-left .nav li .menu.active::after { + transform: rotate(90deg); + color: #fff !important; +} +.main .main-left .nav li .menu:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); +} +.main .main-left .nav li .menu:hover::before { + color: #fff !important; +} +.main .main-left .nav li .menu::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); +} +.main .main-left .nav li .menu::after { + position: absolute; + right: 0.5rem; + top: 0.8rem; + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -moz-osx-font-smoothing: grayscale; + content: '\e90f'; + transition: all 0.15s ease; + color: #ced4da; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} +.main .main-left .nav li .menu[data-title=Status]:before { + content: "\e906"; + color: #5e72e4; + color: var(--primary); +} +.main .main-left .nav li .menu[data-title=System]:before { + content: "\e90a"; + color: #fb6340; +} +.main .main-left .nav li .menu[data-title=Services]:before { + content: "\e909"; + color: #11cdef; +} +.main .main-left .nav li .menu[data-title=NAS]:before { + content: "\e90c"; + color: #f3a4b5; +} +.main .main-left .nav li .menu[data-title=VPN]:before { + content: "\e90b"; + color: #8965e0; +} +.main .main-left .nav li .menu[data-title=Network]:before { + content: "\e908"; + color: #8965e0; +} +.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before { + content: "\e90d"; + color: #2dce89; +} +.main .main-left .nav li .menu[data-title=Docker]:before { + content: "\e911"; + color: #6699ff; +} +.main .main-left .nav li .menu[data-title=Statistics]:before { + content: "\e913"; + color: #8965e0; +} +.main .main-left .nav li .menu[data-title=Control]:before { + content: "\e912"; + color: #5e72e4; + color: var(--primary); +} +.main .main-left .nav li .menu[data-title=Asterisk]:before { + content: "\e914"; + color: #fb6340; +} +.main .main-left .nav li a[data-title=Logout]:before { + content: "\e907"; + color: #adb5bd; +} .lg { margin: 0; padding: 0 !important; @@ -1023,9 +1089,8 @@ h4 { font-size: 0.7rem; font-weight: 600; color: #525f7f; -/* background-color: #e9ecef; + background-color: #e9ecef; background-color: var(--lighter); - */ } h4 em { padding: 0 0.5rem; @@ -1424,7 +1489,9 @@ td > table > tbody > tr > td, .tabs li:hover { cursor: pointer; border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); color: #5e72e4; + color: var(--primary); background-color: #dce1fe; margin-bottom: 0; border-radius: 0; @@ -1432,6 +1499,7 @@ td > table > tbody > tr > td, .tabs li[class~="active"] a, .tabs li:hover a { color: #5e72e4; + color: var(--primary); } .tabs li { font-size: 0.875rem; @@ -1447,6 +1515,7 @@ td > table > tbody > tr > td, } .tabs li:hover { border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); } .cbi-tabmenu { color: white; @@ -1482,7 +1551,9 @@ td > table > tbody > tr > td, .cbi-tabmenu li:hover { cursor: pointer; border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); color: #5e72e4; + color: var(--primary); background-color: #dce1fe; margin-bottom: 0; } @@ -1491,12 +1562,15 @@ td > table > tbody > tr > td, } .cbi-tabmenu li[class~="cbi-tab"] { border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); color: #5e72e4; + color: var(--primary); background-color: #dce1fe; margin-bottom: 0; } .cbi-tabmenu li[class~="cbi-tab"] a { color: #5e72e4; + color: var(--primary); } .cbi-tab-descr { padding: 0.5rem 1.5rem; @@ -1754,6 +1828,7 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child { margin: 0.25rem 0.1rem 0.25rem 0; color: #fff; border: 1px solid #5e72e4; + border: 1px solid var(--primary); border-radius: 0.25rem; outline: 0; background-image: none; @@ -1960,8 +2035,8 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child { width: 0; height: 100%; transition: width 0.25s ease-in; - background: #5bc0de; - background: var(--bar-bg); + background: #5e72e4; + background: var(--primary); } .cbi-progressbar::after { font-family: monospace; @@ -2189,10 +2264,10 @@ td > .ifacebadge, min-height: 15rem; padding: 1rem; resize: none; - color: #eee; + color: #242424; border: 0; border-radius: 0.375rem; - background-color: #242424; + background-color: #ffffff; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); } #syslog:focus { @@ -2286,7 +2361,7 @@ td > .ifacebadge, } .ifacebox-head.active { background: #5e72e4; - background: var(--bar-bg); + background: var(--primary); } .ifacebox-head.active * { color: #fff; @@ -2745,8 +2820,10 @@ input[type="checkbox"] { } input[type="checkbox"]:checked { border: 1px solid #5e72e4; + border: 1px solid var(--primary); background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; background-color: #5e72e4; + background-color: var(--primary); background-size: 70%; background-repeat: no-repeat; background-position: center; @@ -2855,7 +2932,8 @@ pre.command-output { min-width: 4rem; } .main > .main-left > .nav > li, - .main > .main-left > .nav > li a, + .main > .main-left > .nav > li > a, + .main .main-left .nav > li > a:first-child, .main > .main-left > .nav > .slide > .menu, .main > .main-left > .nav > li > [data-title="Logout"] { font-size: 0.9rem; @@ -3092,10 +3170,6 @@ pre.command-output { header > .fill > .container > .brand { display: inline-block; } - .main > .main-left > .nav > .slide > .menu, - .main > .main-left > .nav > li > [data-title="Logout"] { - font-size: 1.2rem; - } .main > .main-left > .nav > .slide > .slide-menu > li > a { font-size: 0.8rem; } @@ -3209,592 +3283,3 @@ pre.command-output { border-radius: 0; } } -@media (prefers-color-scheme: dark) { - body { - background: #1e1e1e; - color: #cccccc; - } - .login-page .login-container .login-form { - background-color: #1e1e1e; - } - .login-page .login-container .login-form .brand { - color: #adb5bd; - } - .login-page .login-container .login-form .form-login .input-group::before { - color: #adb5bd; - } - .login-page .login-container .login-form .form-login .input-group input { - background-color: transparent !important; - color: #adb5bd; - border-bottom: #adb5bd 1px solid !important; - border-radius: 0 !important; - border-top: none !important; - border-left: none !important; - border-right: none !important; - box-shadow: none; - } - .login-page .login-container .login-form .form-login .cbi-button-apply { - background-image: linear-gradient(-135deg, #6c61ab 0%, #594ca9 100%); - } - .login-page .login-container .login-form .form-login .cbi-button-apply:hover, - .login-page .login-container .login-form .form-login .cbi-button-apply:focus { - background-image: linear-gradient(-135deg, #554c8a 0%, #483d8b 100%); - } - header::after { - background-color: #1e1e1e !important; - } - .main .main-left { - background-color: #333333 !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.15); - } - .main .main-left .sidenav-header .brand { - color: #ccc; - } - .main .main-left .nav .slide .slide-menu .active a { - color: #cccccc; - } - .main .main-left .nav .slide .slide-menu .active a::after { - background-color: #cccccc !important; - } - .main .main-left .nav .slide .slide-menu li a { - color: #cccccc; - } - .main .main-left .nav .slide .slide-menu li a:hover { - background: none !important; - } - .main .main-left .nav .slide .menu.active { - background-color: darkslateblue !important; - color: #cccccc !important; - } - .main .main-left .nav .slide .menu.active a::after { - background-color: #cccccc !important; - } - .main .main-left .nav li a { - color: #cccccc !important; - } - .main .main-left .nav li a:hover { - background-color: darkslateblue !important; - color: #cccccc !important; - } - .main .main-left::-webkit-scrollbar-thumb { - background-color: #252526 !important; - } - .main .main-left::-webkit-scrollbar-track { - background-color: #333; - } - .main .main-right { - background-color: #1e1e1e; - } - h2 { - color: #ccc; - background: #333333; - } - h3 { - color: #ccc; - border-bottom: 0; - background: #333333; - } - a:-webkit-any-link { - color: -webkit-link; - cursor: pointer; - color: darkslateblue; - } - input:-webkit-autofill { - background-color: #3c3c3c !important; - } - .cbi-value-field .cbi-input-apply, - .cbi-button-apply, - .cbi-button-edit { - color: #fff !important; - background-color: darkslateblue !important; - border-color: darkslateblue !important; - } - .cbi-section em { - color: #ccc; - } - header.bg-primary { - background-color: #1e1e1e !important; - } - .cbi-map-descr { - color: #ccc; - } - .cbi-section { - background: none; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - } - .panel-title { - color: #ccc; - background-color: #333333; - border-bottom: 0px; - } - div > table > tbody > tr:nth-of-type(2n), - div > .table > .tr:nth-of-type(2n) { - background-color: #252526; - } - table > tbody > tr > td, - table > tfoot > tr > td, - table > thead > tr > td { - color: #ccc; - } - fieldset > table > tbody > tr:nth-of-type(2n) { - background-color: #252526; - } - table > tbody > tr > td, - table > tfoot > tr > td, - table > thead > tr > td { - border-top: 1px solid #252526; - } - #swaptotal > div > div, - #swapfree > div > div, - #memfree > div > div, - #membuff > div > div, - #conns > div > div, - #memtotal > div > div { - background-color: #32325d !important; - } - #swaptotal > div > div > div > small, - #swapfree > div > div > div > small, - #memfree > div > div > div > small, - #membuff > div > div > div > small, - #conns > div > div > div > small, - #memtotal > div > div > div > small { - color: #ccc !important; - } - .node-system-packages > .main .cbi-section-node:first-child .cbi-value-last { - line-height: 1.8em; - } - .node-system-packages > .main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] { - border: 1px solid #999999 !important; - background-color: transparent !important; - } - .node-system-packages > .main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div { - background-color: #32325d !important; - } - table > tbody > tr > th, - table > tfoot > tr > th, - table > thead > tr > th { - background-color: #252526; - border-bottom: black 1px solid !important; - } - tr > td, - tr > th, - .tr > .td, - .tr > .th, - .cbi-section-table-row::before, - #cbi-wireless > #wifi_assoclist_table > .tr:nth-child(2) { - border-top: 0; - } - .cbi-rowstyle-2 { - background-color: #1e1e1e; - } - .cbi-rowstyle-1 { - background-color: #252526; - } - .cbi-section > h3:first-child, - .panel-title, - h3 { - color: #ccc; - border-bottom: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } - h4 { - background-color: #1e1e1f; - } - .cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - margin: 6px 0; - border: thin solid #999; - background: transparent; - border-radius: 0.2rem; - overflow: hidden; - } - .cbi-progressbar div { - background-color: #32325d !important; - } - .cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - background-color: #1e1e1f; - } - .cbi-button { - color: #ccc !important; - background-color: darkslateblue; - } - .cbi-section-node { - background: none; - border-radius: 0 0 0.375rem 0.375rem; - padding: 0rem; - } - abbr { - color: #5e72e4; - } - div > table > tbody > tr:nth-of-type(2n), - div > .table > .tbody > .tr:nth-of-type(2n) { - background-color: #252526; - } - #content_syslog { - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - } - #syslog { - color: #ccc; - background-color: #1e1e1e; - } - #iwsvg, - #iwsvg2, - #bwsvg { - overflow: hidden; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - background-color: #1e1e1e !important; - } - .tabs { - background-color: #252526; - } - .tabs > li[class~="active"] > a { - color: #ccc; - } - .tabs > li[class~="active"], - .tabs > li:hover { - border-bottom: 0.18751rem solid darkslateblue; - color: #ccc; - background-color: #181819; - } - .cbi-tabmenu > li > a, - .tabs > li > a { - color: #ccc; - } - .cbi-tabmenu > li > a:hover, - .tabs > li > a:hover { - color: #ccc; - } - .cbi-tabmenu > li { - background: #2d2d2d; - } - .cbi-tabmenu li[class~="cbi-tab"] a { - color: #ccc; - } - .cbi-tabmenu > li:hover { - color: #ccc; - background: #2d2d2d; - } - .cbi-tabmenu > li[class~="cbi-tab"] { - background-color: #181819; - } - .cbi-tabcontainer > .cbi-value:nth-of-type(2n) { - background-color: #252526; - } - .cbi-value-title { - color: #ccc; - } - select, - input { - color: #ccc; - background-color: transparent !important; - border: 1px solid #252526; - box-shadow: none; - } - select:not([multiple="multiple"]):focus, - input:focus { - border-color: darkslateblue !important; - outline: 0; - } - select { - background-color: #1e1e1e !important; - } - #cbi-dropbear h2, - #cbi-dropbear .cbi-map-descr, - #cbi-dropbear .cbi-map-descr abbr, - #cbi-rc h2, - #cbi-rc .cbi-map-descr, - #cbi-distfeedconf h2, - #cbi-distfeedconf .cbi-map-descr, - #cbi-customfeedconf h2, - #cbi-customfeedconf .cbi-map-descr, - #cbi-download h2, - #cbi-filelist h2 { - color: #ccc !important; - } - .cbi-value-field > ul > li .ifacebadge { - background-color: #3c3c3c; - } - .cbi-section-descr { - color: #ccc; - } - .cbi-input-textarea { - background-color: #1e1e1e; - color: #ccc; - } - .cbi-section-remove:nth-of-type(2n), - .cbi-section-node:nth-of-type(2n) { - background-color: #1e1e1e; - } - .node-system-packages > .main table tr td:nth-last-child(1) { - color: #ccc; - } - .cbi-section-node .cbi-value { - padding: 1rem 1rem 0.3rem 1rem; - } - .ifacebox { - background-color: none; - border: 1px solid #1e1e1e; - } - .ifacebox-head { - color: #666; - } - .ifacebox-body { - background-color: #333; - } - .zonebadge strong { - color: #333; - } - .zonebadge > .ifacebadge { - background-color: #3c3c3c; - } - div.cbi-value var, - td.cbi-value-field var { - color: #5e72e4; - } - #diag-rc-output > pre { - color: #ccc; - background-color: #1e1e1e; - } - .node-services-vssr .block { - background-color: #3c3c3c !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - } - .node-services-vssr .block h4 { - color: #ccc !important; - } - .node-services-vssr .status-bar { - color: #ccc; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - background-color: #1e1e1e; - } - .node-services-vssr .cbi-section-table-row { - color: #ccc; - background-color: #3c3c3c !important; - box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.35); - } - .node-services-vssr .cbi-section-table-row.fast { - background: darkslateblue !important; - color: #fff; - } - .node-services-vssr .ssr-button { - color: #ccc; - } - .node-services-vssr .incon:nth-child(2) { - border-right: #1e1e1e 1px solid; - } - #xhr_poll_status > .label.success { - color: #ccc !important; - background-color: darkolivegreen !important; - } - .notice { - background-color: darkslateblue !important; - } - .cbi-input-find, - .cbi-input-save, - .cbi-button-add, - .cbi-button-save, - .cbi-button-find, - .cbi-input-reload, - .cbi-button-reload { - color: #fff !important; - background-color: darkseagreen !important; - border-color: darkseagreen !important; - } - .cbi-button-reset, - .cbi-input-remove { - color: #fff !important; - background-color: darkorange !important; - border-color: darkorange !important; - } - .cbi-page-actions .cbi-button-apply, - .cbi-section-actions .cbi-button-edit, - .cbi-button-edit.important, - .cbi-button-apply.important, - .cbi-button-reload.important, - .cbi-button-action.important { - border: 1px darkslateblue solid !important; - } - fieldset[id^="cbi-apply-"] { - background-color: #333333; - } - #detail-bubble > div { - border: 1px solid #ccc; - border-radius: 2px; - padding: 5px; - background: #252525; - } - .ifacebox-head.active { - background-color: #32325d !important; - } - header .fill .status span[data-style="active"] { - color: #ccc !important; - background-color: darkolivegreen !important; - } - #cbi-wireless .td, - #cbi-network .tr:first-child > .td, - .table[width="100%"] > .tr:first-child > .td, - [data-page="admin-network-diagnostics"] .tr > .td, - .tr.table-titles > .th, - .tr.cbi-section-table-titles > .th { - background-color: #252526; - border-bottom: black 1px solid !important; - } - .network-status-table .ifacebox-body .ifacebadge { - background-color: #252526; - border-bottom: 0; - box-shadow: none; - } - td > .ifacebadge, - .td > .ifacebadge { - background-color: darkslateblue; - border: 0; - } - .btn.danger, - .cbi-section-remove > .cbi-button, - .cbi-button-remove, - .cbi-button-reset, - .cbi-button-negative, - .cbi-button[value="Stop"], - .cbi-button[value="Kill"], - .cbi-button[onclick="reboot(this)"], - .cbi-button-neutral[value="Restart"] { - border: thin solid darkorange !important; - background-color: darkorange !important; - } - .cbi-section, - .cbi-section-error, - #iptables, - .Firewall form, - #cbi-network > .cbi-section-node, - #cbi-wireless > .cbi-section-node, - #cbi-wireless > #wifi_assoclist_table, - [data-tab-title], - [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), - [data-page="admin-system-opkg"] #maincontent > .container { - background: #1e1e1e !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - } - div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - background: transparent !important; - } - [data-page="admin-system-admin"] .cbi-map h2, - [data-page="admin-system-admin-password"] .cbi-map h2, - [data-page="admin-system-admin"] .cbi-map .cbi-map-descr, - [data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - color: #ccc; - } - [data-page="admin-system-flash"] .modal label > input[type="checkbox"] { - top: -0.35rem; - } - [data-page="admin-system-flash"] .modal .btn { - white-space: normal !important; - background-color: darkseagreen; - } - [data-page="admin-system-flash"] .modal .alert-message { - background-color: transparent !important; - } - [data-page="admin-system-flash"] .modal .danger { - border: thin solid darkorange !important; - background-color: darkorange !important; - } - .cbi-value input[type="password"] + .cbi-button-neutral { - background-color: darkslateblue !important; - } - .btn, - button, - select, - input, - .cbi-dropdown { - border: 1px solid #3c3c3c !important; - } - .cbi-dropdown .preview { - color: #ccc; - } - .cbi-section-table-row { - background-color: #1e1e1e !important; - } - .modal { - background-color: #1e1e1e; - } - .cbi-button-positive { - color: #fff !important; - background-color: darkseagreen !important; - } - [data-page="admin-system-flash"] legend { - color: #ccc; - } - .logout:before { - color: #adb5bd !important; - } - .cbi-dropdown[open] { - border-color: darkslateblue !important; - } - .cbi-dropdown[open] > ul.dropdown { - background: #252526 !important; - color: #ccc !important; - box-shadow: none; - border: 1px solid #3c3c3c !important; - } - .cbi-dropdown[open] > ul.dropdown li { - color: #ccc; - border-bottom: 1px solid #3c3c3c !important; - } - .cbi-dropdown[open] > ul.dropdown > li[selected] { - background-color: darkslateblue !important; - border-bottom: 1px solid #3c3c3c !important; - } - .cbi-dropdown[open] > ul.dropdown > li.focus { - background: darkslateblue; - outline: none; - } - .ifacebadge { - background-color: #333333; - } - .cbi-dynlist > .item > span { - border: 1px solid #3c3c3c !important; - } - .cbi-page-actions .cbi-button-apply, - .cbi-section-actions .cbi-button-edit, - .cbi-button-edit, - .cbi-button-apply, - .cbi-button-reload, - .cbi-button-action, - .cbi-button[value="Submit"], - .cbi-button[value="Upload"], - .cbi-button[value$="Apply"], - .cbi-button[onclick="addKey(event)"] { - background: darkslateblue !important; - } - .btn.primary, - .cbi-page-actions .cbi-button-save, - .cbi-page-actions .cbi-button-apply + .cbi-button-save, - .cbi-button-add, - .cbi-button-save, - .cbi-button-positive, - .cbi-button-link, - .cbi-button[value="Enable"], - .cbi-button[value="Scan"], - .cbi-button[value^="Back"], - .cbi-button-neutral[onclick="handleConfig(event)"] { - background: darkslateblue !important; - } - [data-page="admin-system-opkg"] h2 { - color: #ccc !important; - } - @supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) { - .login-page .login-container .login-form { - -webkit-backdrop-filter: blur(var(--blur-radius-dark)); - backdrop-filter: blur(var(--blur-radius-dark)); - background-color: rgba(0, 0, 0, var(--blur-opacity-dark)); - } - } -} -@media (prefers-color-scheme: dark) and (max-width: 480px) { - .node-status-iptables > .main div > .cbi-map > form { - background-color: #1e1e1e; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - } -} diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/dark.css b/luci-theme-argon/htdocs/luci-static/argon/css/dark.css index 6a1cc074b..2b52701c3 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/css/dark.css +++ b/luci-theme-argon/htdocs/luci-static/argon/css/dark.css @@ -24,7 +24,7 @@ * Login background * https://unsplash.com/ * - * Licensed to the public under the Apache License 2.0 + * Licensed to the public under the Apache License 2.0 */ body { background: #1e1e1e; @@ -50,11 +50,12 @@ body { box-shadow: none; } .login-page .login-container .login-form .form-login .cbi-button-apply { - background-image: linear-gradient(-135deg, #6c61ab 0%, #594ca9 100%); + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; } .login-page .login-container .login-form .form-login .cbi-button-apply:hover, .login-page .login-container .login-form .form-login .cbi-button-apply:focus { - background-image: linear-gradient(-135deg, #554c8a 0%, #483d8b 100%); + opacity: 0.9; } header::after { background-color: #1e1e1e !important; @@ -79,7 +80,8 @@ header::after { background: none !important; } .main .main-left .nav .slide .menu.active { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; color: #cccccc !important; } .main .main-left .nav .slide .menu.active a::after { @@ -89,7 +91,8 @@ header::after { color: #cccccc !important; } .main .main-left .nav li a:hover { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; color: #cccccc !important; } .main .main-left::-webkit-scrollbar-thumb { @@ -113,7 +116,8 @@ h3 { a:-webkit-any-link { color: -webkit-link; cursor: pointer; - color: darkslateblue; + color: #483d8b; + color: var(--dark-primary); } input:-webkit-autofill { background-color: #3c3c3c !important; @@ -122,8 +126,10 @@ input:-webkit-autofill { .cbi-button-apply, .cbi-button-edit { color: #fff !important; - background-color: darkslateblue !important; - border-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; } .cbi-section em { color: #ccc; @@ -235,7 +241,8 @@ h4 { } .cbi-button { color: #ccc !important; - background-color: darkslateblue; + background-color: #483d8b; + background-color: var(--dark-primary); } .cbi-section-node { background: none; @@ -271,7 +278,8 @@ div > .table > .tbody > .tr:nth-of-type(2n) { } .tabs > li[class~="active"], .tabs > li:hover { - border-bottom: 0.18751rem solid darkslateblue; + border-bottom: 0.18751rem solid #483d8b; + border-bottom: 0.18751rem solid var(--dark-primary); color: #ccc; background-color: #181819; } @@ -311,7 +319,8 @@ input { } select:not([multiple="multiple"]):focus, input:focus { - border-color: darkslateblue !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; outline: 0; } select { @@ -392,7 +401,8 @@ td.cbi-value-field var { box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.35); } .node-services-vssr .cbi-section-table-row.fast { - background: darkslateblue !important; + background: #483d8b !important; + background: var(--dark-primary) !important; color: #fff; } .node-services-vssr .ssr-button { @@ -406,7 +416,8 @@ td.cbi-value-field var { background-color: darkolivegreen !important; } .notice { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; } .cbi-input-find, .cbi-input-save, @@ -431,7 +442,8 @@ td.cbi-value-field var { .cbi-button-apply.important, .cbi-button-reload.important, .cbi-button-action.important { - border: 1px darkslateblue solid !important; + border: 1px #483d8b solid !important; + border: 1px var(--dark-primary) solid !important; } .btn[value="Dismiss"], .cbi-button[value="Terminate"], @@ -442,8 +454,8 @@ td.cbi-value-field var { .cbi-button-neutral[value="Disable"] { font-weight: normal; color: #fff; - border: thin solid darkorange!important; - background-color: darkorange!important; + border: thin solid darkorange !important; + background-color: darkorange !important; } fieldset[id^="cbi-apply-"] { background-color: #333333; @@ -477,7 +489,8 @@ header .fill .status span[data-style="active"] { } td > .ifacebadge, .td > .ifacebadge { - background-color: darkslateblue; + background-color: #483d8b; + background-color: var(--dark-primary); border: 0; } .btn.danger, @@ -529,7 +542,8 @@ div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { background-color: darkorange !important; } .cbi-value input[type="password"] + .cbi-button-neutral { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; } .btn, button, @@ -558,7 +572,8 @@ input, color: #adb5bd !important; } .cbi-dropdown[open] { - border-color: darkslateblue !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; } .cbi-dropdown[open] > ul.dropdown { background: #252526 !important; @@ -571,11 +586,13 @@ input, border-bottom: 1px solid #3c3c3c !important; } .cbi-dropdown[open] > ul.dropdown > li[selected] { - background-color: darkslateblue !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; border-bottom: 1px solid #3c3c3c !important; } .cbi-dropdown[open] > ul.dropdown > li.focus { - background: darkslateblue; + background: #483d8b; + background: var(--dark-primary); outline: none; } .ifacebadge { @@ -594,7 +611,8 @@ input, .cbi-button[value="Upload"], .cbi-button[value$="Apply"], .cbi-button[onclick="addKey(event)"] { - background: darkslateblue !important; + background: #483d8b !important; + background: var(--dark-primary) !important; } .btn.primary, .cbi-page-actions .cbi-button-save, @@ -607,7 +625,8 @@ input, .cbi-button[value="Scan"], .cbi-button[value^="Back"], .cbi-button-neutral[onclick="handleConfig(event)"] { - background: darkslateblue; + background: #483d8b; + background: var(--dark-primary); } [data-page="admin-system-opkg"] h2 { color: #ccc !important; diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/fonts.css b/luci-theme-argon/htdocs/luci-static/argon/css/fonts.css index 1c24f7082..87667288b 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/css/fonts.css +++ b/luci-theme-argon/htdocs/luci-static/argon/css/fonts.css @@ -24,7 +24,7 @@ * Login background * https://unsplash.com/ * - * Licensed to the public under the Apache License 2.0 + * Licensed to the public under the Apache License 2.0 */ @@ -183,4 +183,4 @@ .icon-app:before { content: "\e915"; -} \ No newline at end of file +} diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css b/luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css index 81dbb1509..31d891db3 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css +++ b/luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css @@ -8,4 +8,4 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md normalize.css v | MIT License | git.io/normalize Copyright (c) Nicolas Gallagher and Jonathan Neal */ -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear,left top,left bottom,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0} \ No newline at end of file +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear,left top,left bottom,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0} diff --git a/luci-theme-argon/htdocs/luci-static/argon/favicon.ico b/luci-theme-argon/htdocs/luci-static/argon/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4611336803d49af0896adf2698cfaec54e96b800 GIT binary patch literal 15406 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 BLQ((# literal 0 HcmV?d00001 diff --git a/luci-theme-argon/htdocs/luci-static/argon/favicon.png b/luci-theme-argon/htdocs/luci-static/argon/favicon.png deleted file mode 100644 index 7c3f3acb1f0c7c142d0dbd3f42a4926b07f8eb38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 535 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]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="

    + +
    +
    + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/header.htm b/luci-theme-argon/luasrc/view/themes/argon/header.htm index fe238b7ba..1da2486b6 100644 --- a/luci-theme-argon/luasrc/view/themes/argon/header.htm +++ b/luci-theme-argon/luasrc/view/themes/argon/header.htm @@ -5,19 +5,19 @@ Copyright 2020 Jerrykuku Have a bug? Please create an issue here on GitHub! - https://github.com/jerrykuku/luci-theme-argon/issues + https://github.com/jerrykuku/luci-theme-argon/issues - luci-theme-material: + luci-theme-material: Copyright 2015 Lutty Yang - - Agron Theme - https://demos.creative-tim.com/argon-dashboard/index.html + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html Licensed to the public under the Apache License 2.0 -%> <% - local sys = require "luci.sys" + local sys = require "luci.sys" local util = require "luci.util" local http = require "luci.http" local disp = require "luci.dispatcher" @@ -25,42 +25,87 @@ local boardinfo = util.ubus("system", "board") local node = disp.context.dispatched - - local fs = require "nixio.fs" + + local fs = require "nixio.fs" local nutil = require "nixio.util" - + local uci = require 'luci.model.uci'.cursor() + -- send as HTML5 http.prepare_content("text/html") - math.randomseed(os.time()) + + math.randomseed(os.time()) + + -- Custom settings + local mode = 'normal' + local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') + local bar_color = '#5e72e4' + local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity + if fs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bar_color = mode == 'dark' and dark_primary or primary + end + + -- Brand name + local brand_name = boardinfo.hostname or "?" -%> - - - <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - - LuCI - - - - - - - - - - - - LuCI"> - - LuCI"> - - - - - - <% if nixio.fs.access("/etc/dark") then %> - - <% end -%> + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + <% if node and node.css then %> <% end -%> @@ -69,136 +114,110 @@ <%=css %> <% end -%> - - - - - + + + + + @@ -209,7 +228,7 @@
    diff --git a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot index 585f7876f..dc5f04605 100644 --- a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot +++ b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot @@ -74,7 +74,7 @@ msgstr "" msgid "Backup on server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 msgid "Balancing" msgstr "" @@ -168,7 +168,7 @@ msgstr "" msgid "DNS issue: can\\'t resolve hostname" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:314 msgid "Debug" msgstr "" @@ -195,6 +195,11 @@ msgstr "" msgid "Disable HTTP test on Server API in status page" msgstr "" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:309 +msgid "Disable ModemManager" +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:203 msgid "Disable TCP Fast Open" msgstr "" @@ -270,11 +275,11 @@ msgstr "" msgid "Download speed (Kb/s)" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:318 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:328 msgid "Dynamic change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:349 msgid "Enable Bridge Acceleration" msgstr "" @@ -282,7 +287,7 @@ msgstr "" msgid "Enable DNS64" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:343 msgid "Enable Fast Patch offloading for connections" msgstr "" @@ -303,7 +308,7 @@ msgstr "" msgid "Enable TCP Low Latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:309 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:319 msgid "Enable debug logs" msgstr "" @@ -536,15 +541,15 @@ msgstr "" msgid "Master" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:314 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:324 msgid "Master interface selection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:358 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 msgid "Maximum scaling CPU frequency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 msgid "Minimum scaling CPU frequency" msgstr "" @@ -642,7 +647,7 @@ msgstr "" msgid "No available backup on server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:329 msgid "No change" msgstr "" @@ -699,7 +704,7 @@ msgstr "" msgid "Obfuscating will be enabled on both side" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 msgid "On wizard change" msgstr "" @@ -801,7 +806,7 @@ msgstr "" msgid "QMI" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 msgid "Qualcomm Shortcut FE driver" msgstr "" @@ -821,7 +826,7 @@ msgstr "" msgid "Retrieve settings from server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:394 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 msgid "Save & Apply" msgstr "" @@ -834,7 +839,7 @@ msgstr "" msgid "Save vnstats stats" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:364 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:374 msgid "Scaling governor" msgstr "" @@ -960,7 +965,7 @@ msgstr "" msgid "Status" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:349 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:359 msgid "Systems settings" msgstr "" diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index f5db32ac9..01d331b65 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -181,7 +181,7 @@ start_service() { EOF /etc/init.d/rpcd restart 2>&1 >/dev/null fi - if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ]; then + if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ] && [ "$(uci -q openmptcprouter.settings.modemanager)" != "0" ]; then _log "Can't find ModemManager, start it..." /etc/init.d/modemmanager restart fi diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common index 624ca1f8d..8de8f2946 100644 --- a/modemmanager/files/modemmanager.common +++ b/modemmanager/files/modemmanager.common @@ -6,6 +6,7 @@ # If there is no interface that use modemmanager, exit #[ -z "$(uci -q show network | grep modemmanager)" ] && exit +[ "$(uci -q get openmptcprouter.settings.modemmanager)" = "0" ] && exit . /lib/functions.sh . /lib/netifd/netifd-proto.sh @@ -23,7 +24,7 @@ MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" # Common logging mm_log() { - [ -n "$(uci -q show network | grep modemmanager)" ] && logger -t "ModemManager" "hotplug: $*" + logger -t "ModemManager" "hotplug: $*" } ################################################################################ diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index ec4512260..6f92acf93 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1313,7 +1313,7 @@ if [ "$(pgrep rpcd)" = "" ] && [ -f /etc/init.d/rpcd ]; then sleep 5 fi -if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ]; then +if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ] && [ "$(uci -q get openmptcprouter.settings.modemmanager)" != "0" ]; then _log "Can't find ModemManager, restart it..." /etc/init.d/modemmanager restart sleep 5 From 3a867d452530e5b1118c079ad47b9641c9e5b6ca Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 23 Apr 2021 07:26:15 +0200 Subject: [PATCH 0323/2059] Fix Typo --- .../luasrc/view/openmptcprouter/settings.htm | 2 +- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index f78cd0f4b..cdcd3c958 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -303,7 +303,7 @@
    - checked<% end %>> + checked<% end %>>
    <%:Disable ModemManager%> diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 01d331b65..9c547bff8 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -181,7 +181,7 @@ start_service() { EOF /etc/init.d/rpcd restart 2>&1 >/dev/null fi - if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ] && [ "$(uci -q openmptcprouter.settings.modemanager)" != "0" ]; then + if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ] && [ "$(uci -q openmptcprouter.settings.modemmanager)" != "0" ]; then _log "Can't find ModemManager, start it..." /etc/init.d/modemmanager restart fi From 1c6549240e7f945fc7558b07befbc4e1d4c79a93 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 23 Apr 2021 19:05:18 +0200 Subject: [PATCH 0324/2059] Fix disable modemmanager --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index a033260f0..2231db3d0 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1011,7 +1011,7 @@ function settings_add() ucic:set("openmptcprouter","settings","tracebox",tracebox) -- Enable/disable ModemManager - local modemamanger = luci.http.formvalue("disablemodemmanager") or "1" + local modemmanager = luci.http.formvalue("disablemodemmanager") or "1" ucic:set("openmptcprouter","settings","modemmanager",modemmanager) -- Enable/disable server ping From 9def92c7d1c7115eefc20012af7fa4d6c4112984 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 23 Apr 2021 19:24:08 +0200 Subject: [PATCH 0325/2059] Delete conntrack when VPN up --- .../usr/share/omr/post-tracking.d/post-tracking | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 6f92acf93..7dc724d84 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -746,13 +746,6 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ]; then - if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then - _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" - ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null - if [ "$(pgrep openmptcprouter-vps)" = "" ]; then - /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 - fi - fi if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "hi1" ]; then _log "Tunnel up disable use of ShadowSocks for UDP" uci -q delete shadowsocks-libev.ss_rules.redir_udp @@ -761,6 +754,14 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om /etc/init.d/shadowsocks-libev rules_up >/dev/null 2>&1 fi fi + if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then + _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null + if [ "$(pgrep openmptcprouter-vps)" = "" ]; then + /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 + fi + [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp + fi # Set VPN MTU if [ -n "$OMR_TRACKER_LATENCY" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ]); then From 8d449e920363f242e2d545740d9d916b17b7ac72 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 23 Apr 2021 19:24:31 +0200 Subject: [PATCH 0326/2059] Add conntrack dependency --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index eab020f97..5f24f8029 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -30,7 +30,7 @@ MY_DEPENDS := \ bind-dig \ libnetfilter-conntrack ebtables ebtables-utils ip-full \ iptables-mod-iface iptables-mod-ipmark iptables-mod-hashlimit iptables-mod-condition iptables-mod-trace iptables-mod-conntrack-extra iptables-mod-account \ - kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra \ + kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra conntrack \ iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 kmod-ipt-ipsec \ wireless-tools \ libiwinfo-lua \ From 55259576815195606098d637d190c3d2d4609901 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 23 Apr 2021 22:24:36 +0200 Subject: [PATCH 0327/2059] Only get modem list one time --- .../luasrc/view/openmptcprouter/wizard.htm | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 7796370ed..8b2f191a2 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -35,6 +35,17 @@ return t end + alltty = {} + iftty = luci.sys.exec("timeout 1 /usr/bin/mmcli -L") + for listtty in iftty:gmatch("([^\r\n]*)[\r\n]") do + modemid = luci.util.trim(luci.sys.exec("echo '" .. listtty .. "' | awk -F' ' '{print $1}' | awk -F/ '{print $6}'")) + if modemid ~= '' then + modeminfo = luci.sys.exec("timeout 1 /usr/bin/mmcli -m " .. modemid .. " --output-keyvalue") + tty = luci.util.trim(luci.sys.exec("echo '" .. modeminfo .. "' | grep 'modem.generic.device ' | awk -F': ' '{print $2}'")) + table.insert(alltty, tty) + end + end + %> @@ -780,16 +791,10 @@ "> +
    +
    + <%:Timeout for VPS checks on status pages%> +
    +
    +
    +
    + +
    + "> +
    +
    + <%:Timeout for retrieving WANs IP on status pages%> +
    +
    +
    +
    @@ -290,6 +311,16 @@
    +
    + +
    + checked<% end %>> +
    +
    + <%:Disable route loop detection%> +
    +
    +
    diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 73beda8bf..5f248ab31 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -463,6 +463,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm var multipath_state = mArray.wans[i].multipath_state; var duplicateif = mArray.wans[i].duplicateif; var duplicatemac = mArray.wans[i].duplicatemac; + var loop = mArray.wans[i].loop; // Generate template if(mArray.openmptcprouter.remote_from_lease == true && mArray.wans.length == 1) { @@ -622,6 +623,10 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm statusMessage += '<%:Network interface MAC address duplicated%>' + '
    '; statusMessageClass = "error"; } + if(loop) + { + statusMessage += '<%:Looping route detected%>' + '
    '; + } if(ipv6_discover == 'DETECTED') { statusMessage += '<%:IPv6 route received%>' + '
    ' diff --git a/luci-app-openmptcprouter/root/bin/omr-ip-intf b/luci-app-openmptcprouter/root/bin/omr-ip-intf index d09dfa07d..1fffd1036 100755 --- a/luci-app-openmptcprouter/root/bin/omr-ip-intf +++ b/luci-app-openmptcprouter/root/bin/omr-ip-intf @@ -3,11 +3,14 @@ intf=$1 +timeout=$(uci -q get openmptcprouter.settings.status_getip_timeout) +[ -z "$timeout" ] && timeout="1" + get_ip_from_server() { serverport=$(uci -q get openmptcprouter.$1.port) get_ip() { serverip=$1 - getip="$(curl -s -k -4 -m 2 --interface $intf https://$serverip:$serverport/clienthost)" + getip="$(curl -s -k -4 -m ${timeout} --interface $intf https://$serverip:$serverport/clienthost)" [ -n "$getip" ] && getip=$(echo $getip | jsonfilter -e '@.client_host') if expr "$getip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then ip=$getip @@ -23,7 +26,7 @@ get_ip_from_website() { [ -z "$check_ipv4_website" ] && check_ipv4_website="http://ip.openmptcprouter.com" checkip=$(echo $check_ipv4_website | sed -e 's/https:\/\///' -e 's/http:\/\///' | xargs dig +short A | tr -d "\n") ipset add ss_rules_dst_bypass_all $checkip > /dev/null 2>&1 - getip="$(curl -s -4 -m 2 --interface $intf $check_ipv4_website)" + getip="$(curl -s -4 -m ${timeout} --interface $intf $check_ipv4_website)" ipset del ss_rules_dst_bypass_all $checkip > /dev/null 2>&1 if expr "$getip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then ip=$getip diff --git a/luci-app-openmptcprouter/root/bin/omr-ip6-intf b/luci-app-openmptcprouter/root/bin/omr-ip6-intf index 12e3bdbc3..2166441d9 100755 --- a/luci-app-openmptcprouter/root/bin/omr-ip6-intf +++ b/luci-app-openmptcprouter/root/bin/omr-ip6-intf @@ -3,10 +3,13 @@ intf=$1 +timeout=$(uci -q get openmptcprouter.settings.status_getip_timeout) +[ -z "$timeout" ] && timeout="1" + get_ip_from_server() { serverport=$(uci -q get openmptcprouter.$1.port) get_ip() { - getip="$(curl -s -k -6 -m 2 --interface $intf https://$serverip:$serverport/clienthost)" + getip="$(curl -s -k -6 -m ${timeout} --interface $intf https://$serverip:$serverport/clienthost)" [ -n "$getip" ] && getip=$(echo $getip | jsonfilter -e '@.client_host') if [ -n "$(echo "$getip" | grep :)" ]; then ip=$getip @@ -22,7 +25,7 @@ get_ip_from_website() { [ -z "$check_ipv6_website" ] && check_ipv6_website="http://ipv6.openmptcprouter.com" checkip=$(echo $check_ipv6_website | sed -e 's/https:\/\///' -e 's/http:\/\///' | xargs dig +short AAAA | tr -d "\n") ipset add ss_rules6_dst_bypass_all $checkip > /dev/null 2>&1 - getip="$(curl -s -6 -m 2 --interface $intf $check_ipv6_website)" + getip="$(curl -s -6 -m ${timeout} --interface $intf $check_ipv6_website)" ipset del ss_rules6_dst_bypass_all $checkip > /dev/null 2>&1 if [ -n "$(echo "$getip" | grep :)" ]; then ip=$getip diff --git a/luci-app-openmptcprouter/root/bin/omr-mptcp-intf b/luci-app-openmptcprouter/root/bin/omr-mptcp-intf index 9df22c688..d2a74b245 100755 --- a/luci-app-openmptcprouter/root/bin/omr-mptcp-intf +++ b/luci-app-openmptcprouter/root/bin/omr-mptcp-intf @@ -2,6 +2,8 @@ . /lib/functions.sh intf=$1 +timeout="$(uci -q get openmptcprouter.settings.status_vps_timeout)" +[ -z "$timeout" ] && timeout="1" [ -z "$intf" ] && return @@ -10,9 +12,9 @@ get_mptcp_from_server() { get_mptcp() { serverip=$1 if [ "$(echo $serverip | grep :)" ]; then - support="$(curl -s -k -6 -m 2 --interface $intf https://[$serverip]:$serverport/mptcpsupport)" + support="$(curl -s -k -6 -m ${timeout} --interface $intf https://[$serverip]:$serverport/mptcpsupport)" else - support="$(curl -s -k -4 -m 2 --interface $intf https://$serverip:$serverport/mptcpsupport)" + support="$(curl -s -k -4 -m ${timeout} --interface $intf https://$serverip:$serverport/mptcpsupport)" fi [ -n "$support" ] && { support=$(echo $support | jsonfilter -e '@.mptcp') @@ -26,7 +28,7 @@ get_mptcp_from_server() { get_mptcp_from_website() { multipathip=$(dig +short A multipath-tcp.org | tr -d "\n") ipset add ss_rules_dst_bypass_all $multipathip > /dev/null 2>&1 - support="$(curl -s -4 -m 2 --interface $intf http://www.multipath-tcp.org)" + support="$(curl -s -4 -m ${timeout} --interface $intf http://www.multipath-tcp.org)" ipset del ss_rules_dst_bypass_all $multipathip > /dev/null 2>&1 [ -n "$support" ] && { if [ "$support" = "Yay, you are MPTCP-capable! You can now rest in peace." ]; then @@ -40,7 +42,7 @@ get_mptcp_from_website() { get_mptcp_from_website6() { multipathip=$(dig +short AAAA multipath-tcp.org | tr -d "\n") ipset add ss_rules6_dst_bypass_all $multipathip > /dev/null 2>&1 - support="$(curl -s -6 -m 2 --interface $intf http://www.multipath-tcp.org)" + support="$(curl -s -6 -m ${timeout} --interface $intf http://www.multipath-tcp.org)" ipset del ss_rules6_dst_bypass_all $multipathip > /dev/null 2>&1 [ -n "$support" ] && { if [ "$support" = "Yay, you are MPTCP-capable! You can now rest in peace." ]; then diff --git a/luci-app-openmptcprouter/root/bin/omr-routing-loop b/luci-app-openmptcprouter/root/bin/omr-routing-loop new file mode 100755 index 000000000..396498470 --- /dev/null +++ b/luci-app-openmptcprouter/root/bin/omr-routing-loop @@ -0,0 +1,9 @@ +#!/bin/sh +VPS=$1 +LANIP=$2 + +if [ -n "$(traceroute -q 1 -i eth1 -w 1 -n -m 5 ${VPS} | grep ${LANIP})" ]; then + echo "detected" +else + echo "no loop" +fi \ No newline at end of file diff --git a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter index fbcc9968e..f8a0dc21c 100755 --- a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter @@ -88,13 +88,13 @@ if [ "$(uci -q get openmptcprouter.settings.check_ipv6_website)" = "" ]; then fi if [ "$(uci -q get openmptcprouter.settings.status_vps_timeout)" = "" ]; then uci -q batch <<-EOF >/dev/null - set openmptcprouter.settings.status_vps_timeout=2 + set openmptcprouter.settings.status_vps_timeout=1 commit openmptcprouter EOF fi if [ "$(uci -q get openmptcprouter.settings.status_getip_timeout)" = "" ]; then uci -q batch <<-EOF >/dev/null - set openmptcprouter.settings.status_getip_timeout=2 + set openmptcprouter.settings.status_getip_timeout=1 commit openmptcprouter EOF fi diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index cdd3308df..350172aad 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -763,7 +763,7 @@ function interfaces_status() mArray.openmptcprouter["omr_time"] = os.time() -- dns mArray.openmptcprouter["dns"] = false - local timeout = uci:get("openmptcprouter","settings","status_getip_timeout") or "2" + local timeout = uci:get("openmptcprouter","settings","status_getip_timeout") or "1" local dns_test = sys.exec("dig +timeout=" .. timeout .. " +tries=1 openmptcprouter.com | grep 'ANSWER: 0'") if dns_test == "" then mArray.openmptcprouter["dns"] = true @@ -848,7 +848,7 @@ function interfaces_status() mArray.openmptcprouter["vps_omr_version"] = uci:get("openmptcprouter", s[".name"], "omr_version") or "" mArray.openmptcprouter["vps_kernel"] = uci:get("openmptcprouter",s[".name"],"kernel") or "" mArray.openmptcprouter["vps_machine"] = uci:get("openmptcprouter",s[".name"],"machine") or "" - timeout = uci:get("openmptcprouter","settings","status_vps_timeout") or "2" + timeout = uci:get("openmptcprouter","settings","status_vps_timeout") or "1" if uci:get("openmptcprouter",s[".name"],"admin_error") == "1" then mArray.openmptcprouter["vps_admin_error"] = true end @@ -1484,6 +1484,10 @@ function interfaces_status() end end end + loop = false + if uci:get("openmptcprouter", interface, "loop") == "1" then + loop = true + end end local rx = "" local tx = "" @@ -1536,6 +1540,7 @@ function interfaces_status() zonewan = zonewan, iftype = itype, state = state, + loop = loop, } if ifname ~= nil and ifname:match("^tun.*") then table.insert(mArray.tunnels, data); diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index f660a6089..7e79ebc43 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1124,6 +1124,35 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ -n "$asn" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.asn="$asn" } + + # Routing loop detection + local lanip="$(uci -q network.lan.ipaddr)" + local masterip + get_master_ip() { + if [ "$(openmptcprouter.$1.multipath)" = "master" ]; then + masterip="$(uci -q get openmptcprouter.$1.publicip)" + fi + } + config_load openmptcprouter + config_foreach get_master_ip interface + if [ -n "$lanip" ] && [ -n "$masterip" ] && [ -n "$ipaddr" ] && [ "$ipaddr" = "$masterip" ] && [ "$(uci -q get openmptcprouter.settings.disableloopdetection)" != "1" ]; then + loop=0 + routingloop() { + if [ "$(omr-routing-loop $1 $lanip)" = "detected" ]; then + loop=1 + fi + } + config_load openmptcprouter + config_foreach routingloop server + if [ "$loop" = "1" ]; then + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.loop='1' + else + uci -q delete openmptcprouter.$OMR_TRACKER_INTERFACE.loop + fi + else + uci -q delete openmptcprouter.$OMR_TRACKER_INTERFACE.loop + fi + local omrtracebox traceboxmtutest() { omr_tracebox_mtu() { From 6bcc87535597864260dbda0031db348126744548 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 19 May 2021 19:37:36 +0200 Subject: [PATCH 0449/2059] Fix on macvlan --- macvlan/files/etc/init.d/macvlan | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macvlan/files/etc/init.d/macvlan b/macvlan/files/etc/init.d/macvlan index 01a6ee47c..2832e5133 100755 --- a/macvlan/files/etc/init.d/macvlan +++ b/macvlan/files/etc/init.d/macvlan @@ -66,7 +66,7 @@ _setup_interface() { uci -q set network.$1_dev.mtu=$(uci -q get network.$1.mtu) [ -z "$(uci -q get network.$1.masterintf)" ] && uci -q set network.$1.masterintf=$(uci -q get network.$1_dev.ifname) [ -n "$(uci -q get network.$1.masterintf)" ] && uci -q set network.$1_dev.ifname=$(uci -q get network.$1.masterintf) - [ -z "$(uci -q get network.$1.macaddr)" ] && uci -q set network.$1_dev.macaddr=$(uci -q get network.$1.macaddr) + [ -n "$(uci -q get network.$1.macaddr)" ] && uci -q set network.$1_dev.macaddr=$(uci -q get network.$1.macaddr) uci set network.$1.ifname=$1 uci -q commit network return 0 @@ -83,7 +83,7 @@ _setup_interface() { set network.$1.defaultroute=0 EOF - _macaddr=$(uci -q get "network.$1.macaddr") + #_macaddr=$(uci -q get "network.$1.macaddr") _setup_macaddr "$1" "${_macaddr:-auto$(date +%s)}" uci -q set network.$1_dev.mtu=$(uci -q get network.$1.mtu) uci -q commit network From 01f6b5732f63f072cfeb9d39b24d2b78a23a4d05 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 19 May 2021 19:39:01 +0200 Subject: [PATCH 0450/2059] Fix IPv6 6in4 --- omr-6in4/files/etc/init.d/omr-6in4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/omr-6in4/files/etc/init.d/omr-6in4 b/omr-6in4/files/etc/init.d/omr-6in4 index 757ee609c..5bec94c02 100755 --- a/omr-6in4/files/etc/init.d/omr-6in4 +++ b/omr-6in4/files/etc/init.d/omr-6in4 @@ -61,7 +61,8 @@ set_ipv6_state() { set dhcp.lan.ra_default="1" set dhcp.lan.ra_preference="high" set dhcp.lan.ra_management="1" - set dhcp.lan.ra_flags='managed-config' + delete dhcp.lan.ra_flags + add_list dhcp.lan.ra_flags='managed-config' set dhcp.lan.ra_slaac='1' add_list dhcp.lan.ra_flags='other-config' set network.lan.ipv6="1" From bdd71c20109a034243dc33a67ae93ea334988e87 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 May 2021 08:26:56 +0200 Subject: [PATCH 0451/2059] Fix error on loop detection --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 7e79ebc43..4ecbe2310 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1129,7 +1129,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( local lanip="$(uci -q network.lan.ipaddr)" local masterip get_master_ip() { - if [ "$(openmptcprouter.$1.multipath)" = "master" ]; then + if [ "$(uci -q get openmptcprouter.$1.multipath)" = "master" ]; then masterip="$(uci -q get openmptcprouter.$1.publicip)" fi } @@ -1445,6 +1445,11 @@ if [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep omr-bypass)" = "" /etc/init.d/omr-bypass fi +if [ -f /etc/backup/installed_packages.txt ]; then + _log "Reinstall packages..." + /etc/init.d/sysupgrade restart +fi + if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 sleep 5 From a24ef0b9840e9279a098831984ebe1061d94129f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 May 2021 08:40:49 +0200 Subject: [PATCH 0452/2059] Another fix for loop detection --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 4ecbe2310..bccd15eca 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1126,7 +1126,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( } # Routing loop detection - local lanip="$(uci -q network.lan.ipaddr)" + local lanip="$(uci -q get network.lan.ipaddr)" local masterip get_master_ip() { if [ "$(uci -q get openmptcprouter.$1.multipath)" = "master" ]; then From de42eabfcad24d638be0dd558fd20be6d31bc208 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 May 2021 08:52:40 +0200 Subject: [PATCH 0453/2059] Run sysupgrade after all init --- luci-app-sysupgrade/root/etc/init.d/sysupgrade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-sysupgrade/root/etc/init.d/sysupgrade b/luci-app-sysupgrade/root/etc/init.d/sysupgrade index 86eccd349..377c67944 100755 --- a/luci-app-sysupgrade/root/etc/init.d/sysupgrade +++ b/luci-app-sysupgrade/root/etc/init.d/sysupgrade @@ -1,9 +1,9 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2020 Ycarus (Yannick Chabanois) +# Copyright (C) 2020-2021 Ycarus (Yannick Chabanois) # Released under GPL 3. See LICENSE for the full terms. { - START=90 + START=99 STOP=10 USE_PROCD=1 } From 9973a836878176d34d3662be478735b159b09d76 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 May 2021 19:55:39 +0200 Subject: [PATCH 0454/2059] Force distfeeds and customfeeds --- .../files/etc/uci-defaults/2093-opkg | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 openmptcprouter/files/etc/uci-defaults/2093-opkg diff --git a/openmptcprouter/files/etc/uci-defaults/2093-opkg b/openmptcprouter/files/etc/uci-defaults/2093-opkg new file mode 100755 index 000000000..3e61ee56a --- /dev/null +++ b/openmptcprouter/files/etc/uci-defaults/2093-opkg @@ -0,0 +1,19 @@ +#!/bin/sh +source /etc/os-release +if [ "$ID" = "openmptcprouter" ]; then + cat > "/etc/opkg/customfeeds.conf" <<-EOF + src/gz openwrt_luci http://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/luci + src/gz openwrt_packages http://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/packages + src/gz openwrt_base http://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/base + src/gz openwrt_routing http://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/routing + src/gz openwrt_telephony http://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/telephony + EOF + TARGET="$(cat /etc/banner | awk '/TARGET/ {print $2}')" + cat > "/etc/opkg/distfeeds.conf" <<-EOF + src/gz openmptcprouter_core http://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/targets/${OPENWRT_BOARD}/packages + src/gz openmptcprouter_base http://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/base + src/gz openmptcprouter_luci http://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/luci + src/gz openmptcprouter_openmptcprouter http://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/openmptcprouter + src/gz openmptcprouter_packages http://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/packages + EOF +fi \ No newline at end of file From 8ab764a890f7bfecfc470c124859a1a0631f0de6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 May 2021 20:37:31 +0200 Subject: [PATCH 0455/2059] Add dashboard translation template --- luci-mod-dashboard/po/templates/dashboard.pot | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 luci-mod-dashboard/po/templates/dashboard.pot diff --git a/luci-mod-dashboard/po/templates/dashboard.pot b/luci-mod-dashboard/po/templates/dashboard.pot new file mode 100644 index 000000000..018a75101 --- /dev/null +++ b/luci-mod-dashboard/po/templates/dashboard.pot @@ -0,0 +1,214 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "" From 22be274027211b081e376d003ecc95376a11be1f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 22 May 2021 08:42:49 +0200 Subject: [PATCH 0456/2059] Forward port using v2ray doesn't work on range --- .../htdocs/luci-static/resources/view/firewall/forwards.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js index 6c0c7ae73..b30d57c76 100644 --- a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js +++ b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js @@ -282,7 +282,7 @@ return view.extend({ fwtool.addLimitBurstOption(s); o = s.taboption('advanced', form.Flag, 'v2ray', _('Use V2Ray'), - _('Forwards ports from server using V2Ray proxy (if enabled) instead of VPN')); + _('Forward a port (not a range) from server using V2Ray proxy (if enabled) instead of VPN')); o.modalonly = true; o.editable = true; o.depends({ src: 'vpn', '!contains': true }); From 77045a786d642f0b401595398bf86717d2c1c413 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 22 May 2021 08:43:10 +0200 Subject: [PATCH 0457/2059] Add a -w for v2ray iptables --- v2ray-core/files/etc/init.d/v2ray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index 72ca71c15..30ac37ec8 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -2081,7 +2081,7 @@ start_instance() { } rules_exist() { - [ -n "$(iptables -t nat -L -n | grep v2r_)" ] && return 0 + [ -n "$(iptables -w -t nat -L -n | grep v2r_)" ] && return 0 return 1 } From c73fa3a692adb891a619193b7636688120ea268c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 22 May 2021 08:43:36 +0200 Subject: [PATCH 0458/2059] Fix loop detection --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index bccd15eca..cf6b21703 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -799,7 +799,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om if [ "$(pgrep openmptcprouter-vps)" = "" ]; then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 fi - [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp + [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp 2>&1 >/dev/null fi # Set VPN MTU @@ -1138,7 +1138,8 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( if [ -n "$lanip" ] && [ -n "$masterip" ] && [ -n "$ipaddr" ] && [ "$ipaddr" = "$masterip" ] && [ "$(uci -q get openmptcprouter.settings.disableloopdetection)" != "1" ]; then loop=0 routingloop() { - if [ "$(omr-routing-loop $1 $lanip)" = "detected" ]; then + vpsip="$(uci -q get openmptcprouter.$1.ip)" + if [ -n "$vpsip" ] && [ "$(omr-routing-loop $vpsip $lanip)" = "detected" ]; then loop=1 fi } From b40823e54809d74f5ae9cdcd32d800ab1f44e7b2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 22 May 2021 17:29:46 +0200 Subject: [PATCH 0459/2059] Fix loop detection --- luci-app-openmptcprouter/root/bin/omr-routing-loop | 3 ++- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/bin/omr-routing-loop b/luci-app-openmptcprouter/root/bin/omr-routing-loop index 396498470..4cc716602 100755 --- a/luci-app-openmptcprouter/root/bin/omr-routing-loop +++ b/luci-app-openmptcprouter/root/bin/omr-routing-loop @@ -1,8 +1,9 @@ #!/bin/sh VPS=$1 LANIP=$2 +INTF=$3 -if [ -n "$(traceroute -q 1 -i eth1 -w 1 -n -m 5 ${VPS} | grep ${LANIP})" ]; then +if [ -n "$(traceroute -q 1 -i ${INTF} -w 1 -n -m 5 ${VPS} | grep ${LANIP})" ]; then echo "detected" else echo "no loop" diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index cf6b21703..bc87d4f55 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1139,7 +1139,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( loop=0 routingloop() { vpsip="$(uci -q get openmptcprouter.$1.ip)" - if [ -n "$vpsip" ] && [ "$(omr-routing-loop $vpsip $lanip)" = "detected" ]; then + if [ -n "$vpsip" ] && [ "$(omr-routing-loop $vpsip $lanip $OMR_TRACKER_DEVICE)" = "detected" ]; then loop=1 fi } From c2d5dc3e0890f5fc2b151ad8c626eb788301f924 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 26 May 2021 13:13:22 +0200 Subject: [PATCH 0460/2059] Fix disable http test --- .../luasrc/controller/openmptcprouter.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 9aef3a1f7..7c354b690 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1013,6 +1013,10 @@ function settings_add() local disableloopdetection = luci.http.formvalue("disableloopdetection") or "0" ucic:set("openmptcprouter","settings","disableloopdetection",disableloopdetection) + -- Enable/disable http test + local disableserverhttptest = luci.http.formvalue("disableserverhttptest") or "0" + ucic:set("openmptcprouter","settings","disableserverhttptest",disableserverhttptest) + -- Enable/disable renaming intf local disableintfrename = luci.http.formvalue("disableintfrename") or "0" ucic:set("openmptcprouter","settings","disableintfrename",disableintfrename) From 0aa234d36baeff38755ed0e4bfdede472b4c4d33 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 27 May 2021 07:35:23 +0200 Subject: [PATCH 0461/2059] Delete old mac when setting macvlan --- macvlan/files/etc/init.d/macvlan | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/macvlan/files/etc/init.d/macvlan b/macvlan/files/etc/init.d/macvlan index 2832e5133..b38597eff 100755 --- a/macvlan/files/etc/init.d/macvlan +++ b/macvlan/files/etc/init.d/macvlan @@ -81,10 +81,12 @@ _setup_interface() { set network.$1.masterintf=$_ifname set network.$1.type=macvlan set network.$1.defaultroute=0 + delete network.$1.macaddr EOF #_macaddr=$(uci -q get "network.$1.macaddr") - _setup_macaddr "$1" "${_macaddr:-auto$(date +%s)}" + #_setup_macaddr "$1" "${_macaddr:-auto$(date +%s)}" + _setup_macaddr "$1" "auto$(date +%s)" uci -q set network.$1_dev.mtu=$(uci -q get network.$1.mtu) uci -q commit network } From d5fd515873098434fcc2e7b6f918ca4c266db146 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 May 2021 17:47:33 +0200 Subject: [PATCH 0462/2059] Initialize resolv.conf --- openmptcprouter/files/etc/uci-defaults/1940-omr-dns | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index 21efcdfee..705c30225 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -199,6 +199,10 @@ if [ -z "$(uci -q get unbound.fwd_adguard_family)" ]; then EOF fi +if [ -z "$(grep nameserver /etc/resolv.conf)" ]; then + echo "nameserver 127.0.0.1" > /etc/resolv.conf +fi + rm -f /tmp/luci-indexcache exit 0 From 7840a05a8a0480e139dac39bdfcc66f00b666b3d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 May 2021 17:48:24 +0200 Subject: [PATCH 0463/2059] Add option to enable/disable nDPI --- .../root/etc/init.d/omr-bypass | 40 ++++++++++--------- .../luasrc/controller/openmptcprouter.lua | 4 ++ .../luasrc/view/openmptcprouter/settings.htm | 10 +++++ 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 164f6e42e..2b8f56972 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -341,31 +341,33 @@ _bypass_proto() { [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return - if [ "$intf" = "all" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ]; then + if [ "$intf" = "all" ]; then + iptables-restore -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 COMMIT EOF - fi - else - iptables-restore -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$disableipv6" = "0" ]; then + ip6tables-restore -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 + COMMIT + EOF + fi + else + iptables-restore -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid COMMIT EOF + if [ "$disableipv6" = "0" ]; then + ip6tables-restore -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid + COMMIT + EOF + fi fi fi # Use dnsmasq ipset to bypass domains of the proto diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 7c354b690..3d243b210 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1041,6 +1041,10 @@ function settings_add() local shadowsocksudp = luci.http.formvalue("shadowsocksudp") or "0" ucic:set("openmptcprouter","settings","shadowsocksudp",shadowsocksudp) + -- Enable/disable nDPI + local ndpi = luci.http.formvalue("ndpi") or "1" + ucic:set("openmptcprouter","settings","ndpi",ndpi) + -- Enable/disable fast open local disablefastopen = luci.http.formvalue("disablefastopen") or "0" if disablefastopen == "0" then diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index 67bfa50c1..c866f921e 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -331,6 +331,16 @@
    +
    + +
    + checked<% end %>> +
    +
    + <%:Disable nDPI, used for protocols in OMR-ByPass%> +
    +
    +
    From da3834c40702789f58dc55114953427a3ed311c9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 May 2021 17:48:51 +0200 Subject: [PATCH 0464/2059] Remove bond0 in interface choice --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index c921dca30..2c33cfa2d 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -971,7 +971,7 @@ <% iffind=0 - uciifname=uci:get("network",ifname,"ifname") + uciifname=uci:get("network",ifname,"device") if uciifname ~= nil then if uciifname:match("/") then realifname=uciifname diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 9c547bff8..42ed7d1b9 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -18,7 +18,8 @@ omr_intf_check() { omr_intf_set() { local device local ifname - config_get ifname "$1" ifname + config_get ifname "$1" device + [ -z "$ifname" ] && config_get ifname "$1" ifname config_get device "$1" device config_get type "$1" type @@ -56,7 +57,8 @@ omr_set_settings() { local ifname local multipath config_get multipath "$1" multipath - config_get ifname "$1" ifname + config_get ifname "$1" device + [ -z "$ifname" ] && config_get ifname "$1" ifname config_get device "$1" device config_get proto "$1" proto config_get type "$1" type diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index effce068c..977f67372 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -11,7 +11,7 @@ local jsonc = require "luci.jsonc" function interface_from_device(dev) for _, iface in ipairs(net:get_networks()) do local ifacen = iface:name() - local ifacename = ucic:get("network",ifacen,"ifname") + local ifacename = ucic:get("network",ifacen,"device") if ifacename == dev then return ifacen end @@ -72,7 +72,7 @@ function add_interface(add_interface_ifname) end ucic:set("network","wan" .. i,"interface") - ucic:set("network","wan" .. i,"ifname",defif) + ucic:set("network","wan" .. i,"device",defif) ucic:set("network","wan" .. i,"proto","static") if ointf ~= "" then ucic:set("network","wan" .. i,"type","macvlan") @@ -128,7 +128,7 @@ end function remove_interface(intf) -- Remove existing interface - local defif = ucic:get("network",intf,"ifname") + local defif = ucic:get("network",intf,"device") ucic:delete("network",intf) ucic:delete("network",intf .. "_dev") ucic:save("network") @@ -170,7 +170,7 @@ function set_interface(intf,proto,ipaddr,netmask,gateway,sqmenabled,downloadspee if not ucic:get("sqm",intf) ~= "" then local defif = get_device(intf) if defif == "" then - defif = ucic:get("network",intf,"ifname") or "" + defif = ucic:get("network",intf,"device") or "" end ucic:set("sqm",intf,"queue") ucic:set("sqm",intf,"interface",defif) @@ -268,7 +268,7 @@ function default_vpn(default_vpn) ucic:set("network","omrvpn","proto","dhcp") end if vpn_intf ~= "" then - ucic:set("network","omrvpn","ifname",vpn_intf) + ucic:set("network","omrvpn","device",vpn_intf) ucic:save("network") ucic:commit("network") end @@ -961,7 +961,10 @@ function interfaces_status() if string.find(sys.exec("/usr/bin/pgrep '^(/usr/sbin/)?glorytun(-udp)?$'"), "%d+") or string.find(sys.exec("/usr/bin/pgrep '^(/usr/sbin/)?dsvpn?$'"), "%d+") or string.find(sys.exec("/usr/bin/pgrep '^(/usr/sbin/)?mlvpn?$'"), "%d+") or string.find(sys.exec("/usr/bin/pgrep '^(/usr/sbin/)?openvpn?$'"), "%d+") then mArray.openmptcprouter["tun_service"] = true mArray.openmptcprouter["tun_ip"] = get_ip("omrvpn") - local tun_dev = uci:get("network","omrvpn","ifname") + local tun_dev = uci:get("network","omrvpn","device") + if tun_dev == "" then + tun_dev = uci:get("network","omrvpn","ifname") + end if tun_dev == "" then tun_dev = get_device("omrvpn") end @@ -1139,14 +1142,14 @@ function interfaces_status() local ifname = get_device(interface) if ifname == "" or ifname == nil then - ifname = section["ifname"] or "" + ifname = section["device"] or "" end --if ifname ~= nil and ifname:match("^tun.*") and interface:match("^ovpn.*") then --ifname = get_device(interface:sub(5)) --end duplicateif = false - if ifname ~= "" and ifname ~= nil and not (section["ifname"] ~= nil and section["ifname"]:match("^@.*")) then + if ifname ~= "" and ifname ~= nil and not (section["device"] ~= nil and section["device"]:match("^@.*")) then if allintf[ifname] then connectivity = "ERROR" duplicateif = true @@ -1156,7 +1159,7 @@ function interfaces_status() end duplicatemac = false - if mac ~= "" and mac ~= nil and not (section["ifname"] ~= nil and section["ifname"]:match("^@.*")) then + if mac ~= "" and mac ~= nil and not (section["device"] ~= nil and section["device"]:match("^@.*")) then if allmac[mac] then connectivity = "ERROR" duplicatemac = true From 490133cea7dd96c5397b27a349e3f9b42d69a77d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Jun 2021 19:43:45 +0200 Subject: [PATCH 0525/2059] Fix dashboard error --- .../luci-static/resources/view/dashboard/include/10_router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js index b5892cff2..ad9278c53 100644 --- a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js @@ -371,7 +371,7 @@ return baseclass.extend({ release: { title: _('Firmware Version'), - value: boardinfo.release.description ? boardinfo.release.description : null + value: (typeof boardinfo.release.description !== "undefined") ? boardinfo.release.description : null } }; From 94f2c90ad45077d5548c49d5a5bff23fe1042f48 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Jun 2021 19:45:23 +0200 Subject: [PATCH 0526/2059] Update luci-mod-network to upstream and add multipath and latency support --- luci-mod-network/Makefile | 4 +- .../luci-static/resources/tools/network.js | 913 ++++++++++++++ .../resources/view/network/dhcp.js | 63 +- .../resources/view/network/hosts.js | 17 +- .../resources/view/network/interfaces.js | 1061 ++++++++++++----- .../resources/view/network/routes.js | 5 + .../resources/view/network/wireless.js | 172 ++- .../share/rpcd/acl.d/luci-mod-network.json | 6 +- 8 files changed, 1859 insertions(+), 382 deletions(-) create mode 100644 luci-mod-network/htdocs/luci-static/resources/tools/network.js diff --git a/luci-mod-network/Makefile b/luci-mod-network/Makefile index 71e847f31..6148f98b4 100644 --- a/luci-mod-network/Makefile +++ b/luci-mod-network/Makefile @@ -1,10 +1,10 @@ # # Copyright (C) 2008-2014 The LuCI Team -# Copyright (C) 2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Copyright (C) 2020-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter # # This is free software, licensed under the Apache License, Version 2.0 . # -# From https://github.com/openwrt/luci/commit/f5c04e1a2e173f536597f220db0380cc08869e8e +# From https://github.com/openwrt/luci/commit/b88157e69a060ade618e48b30947729310935d61 include $(TOPDIR)/rules.mk diff --git a/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/luci-mod-network/htdocs/luci-static/resources/tools/network.js new file mode 100644 index 000000000..8efbd89d4 --- /dev/null +++ b/luci-mod-network/htdocs/luci-static/resources/tools/network.js @@ -0,0 +1,913 @@ +'use strict'; +'require ui'; +'require dom'; +'require uci'; +'require form'; +'require network'; +'require baseclass'; +'require validation'; +'require tools.widgets as widgets'; + +function validateAddr(section_id, value) { + if (value == '') + return true; + + var ipv6 = /6$/.test(this.section.formvalue(section_id, 'mode')), + addr = ipv6 ? validation.parseIPv6(value) : validation.parseIPv4(value); + + return addr ? true : (ipv6 ? _('Expecting a valid IPv6 address') : _('Expecting a valid IPv4 address')); +} + +function validateQoSMap(section_id, value) { + if (value == '') + return true; + + var m = value.match(/^(\d+):(\d+)$/); + + if (!m || +m[1] > 0xFFFFFFFF || +m[2] > 0xFFFFFFFF) + return _('Expecting two priority values separated by a colon'); + + return true; +} + +function deviceSectionExists(section_id, devname) { + var exists = false; + + uci.sections('network', 'device', function(ss) { + exists = exists || ( + ss['.name'] != section_id && + ss.name == devname + ); + }); + + return exists; +} + +function isBridgePort(dev) { + if (!dev) + return false; + + if (dev.isBridgePort()) + return true; + + var isPort = false; + + uci.sections('network', null, function(s) { + if (s['.type'] != 'interface' && s['.type'] != 'device') + return; + + if (s.type == 'bridge' && L.toArray(s.ifname).indexOf(dev.getName()) > -1) + isPort = true; + }); + + return isPort; +} + +function updateDevBadge(node, dev) { + var type = dev.getType(), + up = dev.getCarrier(); + + dom.content(node, [ + E('img', { + 'class': 'middle', + 'src': L.resource('icons/%s%s.png').format(type, up ? '' : '_disabled') + }), + '\x0a', dev.getName() + ]); + + return node; +} + +function renderDevBadge(dev) { + return updateDevBadge(E('span', { + 'class': 'ifacebadge port-status-device', + 'style': 'font-weight:normal', + 'data-device': dev.getName() + }), dev); +} + +function updatePortStatus(node, dev) { + var carrier = dev.getCarrier(), + duplex = dev.getDuplex(), + speed = dev.getSpeed(), + desc, title; + + if (carrier && speed > 0 && duplex != null) { + desc = '%d%s'.format(speed, duplex == 'full' ? 'FD' : 'HD'); + title = '%s, %d MBit/s, %s'.format(_('Connected'), speed, duplex == 'full' ? _('full-duplex') : _('half-duplex')); + } + else if (carrier) { + desc = _('Connected'); + } + else { + desc = _('no link'); + } + + dom.content(node, [ + E('img', { + 'class': 'middle', + 'src': L.resource('icons/port_%s.png').format(carrier ? 'up' : 'down') + }), + '\x0a', desc + ]); + + if (title) + node.setAttribute('data-tooltip', title); + else + node.removeAttribute('data-tooltip'); + + return node; +} + +function renderPortStatus(dev) { + return updatePortStatus(E('span', { + 'class': 'ifacebadge port-status-link', + 'data-device': dev.getName() + }), dev); +} + +function updatePlaceholders(opt, section_id) { + var dev = network.instantiateDevice(opt.getUIElement(section_id).getValue()); + + for (var i = 0, co; (co = opt.section.children[i]) != null; i++) { + if (co !== opt) { + switch (co.option) { + case 'mtu': + case 'mtu6': + co.getUIElement(section_id).setPlaceholder(dev.getMTU()); + break; + + case 'macaddr': + co.getUIElement(section_id).setPlaceholder(dev.getMAC()); + break; + + case 'txqueuelen': + co.getUIElement(section_id).setPlaceholder(dev._devstate('qlen')); + break; + } + } + } +} + + +var cbiTagValue = form.Value.extend({ + renderWidget: function(section_id, option_index, cfgvalue) { + var widget = new ui.Dropdown(cfgvalue || ['-'], { + '-': E([], [ + E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ '—' ]), + E('span', { 'class': 'hide-close' }, [ _('Do not participate', 'VLAN port state') ]) + ]), + 'u': E([], [ + E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ 'u' ]), + E('span', { 'class': 'hide-close' }, [ _('Egress untagged', 'VLAN port state') ]) + ]), + 't': E([], [ + E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ 't' ]), + E('span', { 'class': 'hide-close' }, [ _('Egress tagged', 'VLAN port state') ]) + ]), + '*': E([], [ + E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ '*' ]), + E('span', { 'class': 'hide-close' }, [ _('Primary VLAN ID', 'VLAN port state') ]) + ]) + }, { + id: this.cbid(section_id), + sort: [ '-', 'u', 't', '*' ], + optional: false, + multiple: true + }); + + var field = this; + + widget.toggleItem = function(sb, li, force_state) { + var lis = li.parentNode.querySelectorAll('li'), + toggle = ui.Dropdown.prototype.toggleItem; + + toggle.apply(this, [sb, li, force_state]); + + if (force_state != null) + return; + + switch (li.getAttribute('data-value')) + { + case '-': + if (li.hasAttribute('selected')) { + for (var i = 0; i < lis.length; i++) { + switch (lis[i].getAttribute('data-value')) { + case '-': + break; + + case '*': + toggle.apply(this, [sb, lis[i], false]); + lis[i].setAttribute('unselectable', ''); + break; + + default: + toggle.apply(this, [sb, lis[i], false]); + } + } + } + break; + + case 't': + case 'u': + if (li.hasAttribute('selected')) { + for (var i = 0; i < lis.length; i++) { + switch (lis[i].getAttribute('data-value')) { + case li.getAttribute('data-value'): + break; + + case '*': + lis[i].removeAttribute('unselectable'); + break; + + default: + toggle.apply(this, [sb, lis[i], false]); + } + } + } + else { + toggle.apply(this, [sb, li, true]); + } + break; + + case '*': + if (li.hasAttribute('selected')) { + var section_ids = field.section.cfgsections(); + + for (var i = 0; i < section_ids.length; i++) { + var other_widget = field.getUIElement(section_ids[i]), + other_value = L.toArray(other_widget.getValue()); + + if (other_widget === this) + continue; + + var new_value = other_value.filter(function(v) { return v != '*' }); + + if (new_value.length == other_value.length) + continue; + + other_widget.setValue(new_value); + break; + } + } + } + }; + + var node = widget.render(); + + node.style.minWidth = '4em'; + + if (cfgvalue == '-') + node.querySelector('li[data-value="*"]').setAttribute('unselectable', ''); + + return E('div', { 'style': 'display:inline-block' }, node); + }, + + cfgvalue: function(section_id) { + var ports = L.toArray(uci.get('network', section_id, 'ports')); + + for (var i = 0; i < ports.length; i++) { + var s = ports[i].split(/:/); + + if (s[0] != this.port) + continue; + + var t = /t/.test(s[1] || '') ? 't' : 'u'; + + return /\*/.test(s[1] || '') ? [t, '*'] : [t]; + } + + return ['-']; + }, + + write: function(section_id, value) { + var ports = []; + + for (var i = 0; i < this.section.children.length; i++) { + var opt = this.section.children[i]; + + if (opt.port) { + var val = L.toArray(opt.formvalue(section_id)).join(''); + + switch (val) { + case '-': + break; + + case 'u': + ports.push(opt.port); + break; + + default: + ports.push('%s:%s'.format(opt.port, val)); + break; + } + } + } + + uci.set('network', section_id, 'ports', ports); + }, + + remove: function() {} +}); + +return baseclass.extend({ + replaceOption: function(s, tabName, optionClass, optionName, optionTitle, optionDescription) { + var o = s.getOption(optionName); + + if (o) { + if (o.tab) { + s.tabs[o.tab].children = s.tabs[o.tab].children.filter(function(opt) { + return opt.option != optionName; + }); + } + + s.children = s.children.filter(function(opt) { + return opt.option != optionName; + }); + } + + return s.taboption(tabName, optionClass, optionName, optionTitle, optionDescription); + }, + + addDeviceOptions: function(s, dev, isNew) { + var parent_dev = dev ? dev.getParent() : null, + o, ss; + + s.tab('devgeneral', _('General device options')); + s.tab('devadvanced', _('Advanced device options')); + s.tab('brport', _('Bridge port specific options')); + s.tab('bridgevlan', _('Bridge VLAN filtering')); + + o = this.replaceOption(s, 'devgeneral', form.ListValue, 'type', _('Device type')); + o.readonly = !isNew; + o.value('', _('Network device')); + o.value('bridge', _('Bridge device')); + o.value('8021q', _('VLAN (802.1q)')); + o.value('8021ad', _('VLAN (802.1ad)')); + o.value('macvlan', _('MAC VLAN')); + o.value('veth', _('Virtual Ethernet')); + o.validate = function(section_id, value) { + if (value == 'bridge' || value == 'veth') + updatePlaceholders(this.section.getOption('name_complex'), section_id); + + return true; + }; + + o = this.replaceOption(s, 'devgeneral', widgets.DeviceSelect, 'name_simple', _('Existing device')); + o.readonly = !isNew; + o.rmempty = false; + o.noaliases = true; + o.default = (dev ? dev.getName() : ''); + o.ucioption = 'name'; + o.filter = function(section_id, value) { + var dev = network.instantiateDevice(value); + return !deviceSectionExists(section_id, value) && (dev.getType() != 'wifi' || dev.isUp()); + }; + o.validate = function(section_id, value) { + updatePlaceholders(this, section_id); + + return deviceSectionExists(section_id, value) + ? _('A configuration for the device "%s" already exists').format(value) : true; + }; + o.onchange = function(ev, section_id, values) { + updatePlaceholders(this, section_id); + }; + o.depends('type', ''); + + o = this.replaceOption(s, 'devgeneral', widgets.DeviceSelect, 'ifname_single', _('Base device')); + o.readonly = !isNew; + o.rmempty = false; + o.noaliases = true; + o.default = (dev ? dev.getName() : '').match(/^.+\.\d+$/) ? dev.getName().replace(/\.\d+$/, '') : ''; + o.ucioption = 'ifname'; + o.filter = function(section_id, value) { + var dev = network.instantiateDevice(value); + return (dev.getType() != 'wifi' || dev.isUp()); + }; + o.validate = function(section_id, value) { + updatePlaceholders(this, section_id); + + if (isNew) { + var type = this.section.formvalue(section_id, 'type'), + name = this.section.getUIElement(section_id, 'name_complex'); + + if (type == 'macvlan' && value && name && !name.isChanged()) { + var i = 0; + + while (deviceSectionExists(section_id, '%smac%d'.format(value, i))) + i++; + + name.setValue('%smac%d'.format(value, i)); + name.triggerValidation(); + } + } + + return true; + }; + o.onchange = function(ev, section_id, values) { + updatePlaceholders(this, section_id); + }; + o.depends('type', '8021q'); + o.depends('type', '8021ad'); + o.depends('type', 'macvlan'); + + o = this.replaceOption(s, 'devgeneral', form.Value, 'vid', _('VLAN ID')); + o.readonly = !isNew; + o.datatype = 'range(1, 4094)'; + o.rmempty = false; + o.default = (dev ? dev.getName() : '').match(/^.+\.\d+$/) ? dev.getName().replace(/^.+\./, '') : ''; + o.validate = function(section_id, value) { + var base = this.section.formvalue(section_id, 'ifname_single'), + vid = this.section.formvalue(section_id, 'vid'), + name = this.section.getUIElement(section_id, 'name_complex'); + + if (base && vid && name && !name.isChanged()) { + name.setValue('%s.%d'.format(base, vid)); + name.triggerValidation(); + } + + return true; + }; + o.depends('type', '8021q'); + o.depends('type', '8021ad'); + + o = this.replaceOption(s, 'devgeneral', form.ListValue, 'mode', _('Mode')); + o.value('vepa', _('VEPA (Virtual Ethernet Port Aggregator)', 'MACVLAN mode')); + o.value('private', _('Private (Prevent communication between MAC VLANs)', 'MACVLAN mode')); + o.value('bridge', _('Bridge (Support direct communication between MAC VLANs)', 'MACVLAN mode')); + o.value('passthru', _('Pass-through (Mirror physical device to single MAC VLAN)', 'MACVLAN mode')); + o.depends('type', 'macvlan'); + + o = this.replaceOption(s, 'devgeneral', form.Value, 'name_complex', _('Device name')); + o.rmempty = false; + o.datatype = 'maxlength(15)'; + o.readonly = !isNew; + o.ucioption = 'name'; + o.validate = function(section_id, value) { + var dev = network.instantiateDevice(value); + + if (deviceSectionExists(section_id, value) || (isNew && (dev.dev || {}).idx)) + return _('The device name "%s" is already taken').format(value); + + return true; + }; + o.depends({ type: '', '!reverse': true }); + + o = this.replaceOption(s, 'devadvanced', form.DynamicList, 'ingress_qos_mapping', _('Ingress QoS mapping'), _('Defines a mapping of VLAN header priority to the Linux internal packet priority on incoming frames')); + o.rmempty = true; + o.validate = validateQoSMap; + o.depends('type', '8021q'); + o.depends('type', '8021ad'); + + o = this.replaceOption(s, 'devadvanced', form.DynamicList, 'egress_qos_mapping', _('Egress QoS mapping'), _('Defines a mapping of Linux internal packet priority to VLAN header priority but for outgoing frames')); + o.rmempty = true; + o.validate = validateQoSMap; + o.depends('type', '8021q'); + o.depends('type', '8021ad'); + + o = this.replaceOption(s, 'devgeneral', widgets.DeviceSelect, 'ifname_multi', _('Bridge ports')); + o.size = 10; + o.rmempty = true; + o.multiple = true; + o.noaliases = true; + o.nobridges = true; + o.ucioption = 'ports'; + o.default = L.toArray(dev ? dev.getPorts() : null).filter(function(p) { return p.getType() != 'wifi' }).map(function(p) { return p.getName() }); + o.filter = function(section_id, device_name) { + var bridge_name = uci.get('network', section_id, 'name'), + choice_dev = network.instantiateDevice(device_name), + parent_dev = choice_dev.getParent(); + + /* only show wifi networks which are already present in "option ifname" */ + if (choice_dev.getType() == 'wifi') { + var ifnames = L.toArray(uci.get('network', section_id, 'ports')); + + for (var i = 0; i < ifnames.length; i++) + if (ifnames[i] == device_name) + return true; + + return false; + } + + return (!parent_dev || parent_dev.getName() != bridge_name); + }; + o.description = _('Specifies the wired ports to attach to this bridge. In order to attach wireless networks, choose the associated interface as network in the wireless settings.') + o.onchange = function(ev, section_id, values) { + ss.updatePorts(values); + + return ss.parse().then(function() { + ss.redraw(); + }); + }; + o.depends('type', 'bridge'); + + o = this.replaceOption(s, 'devgeneral', form.Flag, 'bridge_empty', _('Bring up empty bridge'), _('Bring up the bridge interface even if no ports are attached')); + o.default = o.disabled; + o.depends('type', 'bridge'); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'priority', _('Priority')); + o.placeholder = '32767'; + o.datatype = 'range(0, 65535)'; + o.depends('type', 'bridge'); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'ageing_time', _('Ageing time'), _('Timeout in seconds for learned MAC addresses in the forwarding database')); + o.placeholder = '30'; + o.datatype = 'uinteger'; + o.depends('type', 'bridge'); + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'stp', _('Enable STP'), _('Enables the Spanning Tree Protocol on this bridge')); + o.default = o.disabled; + o.depends('type', 'bridge'); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'hello_time', _('Hello interval'), _('Interval in seconds for STP hello packets')); + o.placeholder = '2'; + o.datatype = 'range(1, 10)'; + o.depends({ type: 'bridge', stp: '1' }); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'forward_delay', _('Forward delay'), _('Time in seconds to spend in listening and learning states')); + o.placeholder = '15'; + o.datatype = 'range(2, 30)'; + o.depends({ type: 'bridge', stp: '1' }); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'max_age', _('Maximum age'), _('Timeout in seconds until topology updates on link loss')); + o.placeholder = '20'; + o.datatype = 'range(6, 40)'; + o.depends({ type: 'bridge', stp: '1' }); + + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'igmp_snooping', _('Enable IGMP snooping'), _('Enables IGMP snooping on this bridge')); + o.default = o.disabled; + o.depends('type', 'bridge'); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'hash_max', _('Maximum snooping table size')); + o.placeholder = '512'; + o.datatype = 'uinteger'; + o.depends({ type: 'bridge', igmp_snooping: '1' }); + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'multicast_querier', _('Enable multicast querier')); + o.defaults = { '1': [{'igmp_snooping': '1'}], '0': [{'igmp_snooping': '0'}] }; + o.depends('type', 'bridge'); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'robustness', _('Robustness'), _('The robustness value allows tuning for the expected packet loss on the network. If a network is expected to be lossy, the robustness value may be increased. IGMP is robust to (Robustness-1) packet losses')); + o.placeholder = '2'; + o.datatype = 'min(1)'; + o.depends({ type: 'bridge', multicast_querier: '1' }); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'query_interval', _('Query interval'), _('Interval in centiseconds between multicast general queries. By varying the value, an administrator may tune the number of IGMP messages on the subnet; larger values cause IGMP Queries to be sent less often')); + o.placeholder = '12500'; + o.datatype = 'uinteger'; + o.depends({ type: 'bridge', multicast_querier: '1' }); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'query_response_interval', _('Query response interval'), _('The max response time in centiseconds inserted into the periodic general queries. By varying the value, an administrator may tune the burstiness of IGMP messages on the subnet; larger values make the traffic less bursty, as host responses are spread out over a larger interval')); + o.placeholder = '1000'; + o.datatype = 'uinteger'; + o.validate = function(section_id, value) { + var qiopt = L.toArray(this.map.lookupOption('query_interval', section_id))[0], + qival = qiopt ? (qiopt.formvalue(section_id) || qiopt.placeholder) : ''; + + if (value != '' && qival != '' && +value >= +qival) + return _('The query response interval must be lower than the query interval value'); + + return true; + }; + o.depends({ type: 'bridge', multicast_querier: '1' }); + + o = this.replaceOption(s, 'devadvanced', form.Value, 'last_member_interval', _('Last member interval'), _('The max response time in centiseconds inserted into group-specific queries sent in response to leave group messages. It is also the amount of time between group-specific query messages. This value may be tuned to modify the "leave latency" of the network. A reduced value results in reduced time to detect the loss of the last member of a group')); + o.placeholder = '100'; + o.datatype = 'uinteger'; + o.depends({ type: 'bridge', multicast_querier: '1' }); + + o = this.replaceOption(s, 'devgeneral', form.Value, 'mtu', _('MTU')); + o.datatype = 'range(576, 9200)'; + o.validate = function(section_id, value) { + var parent_mtu = (dev && dev.getType() == 'vlan') ? (parent_dev ? parent_dev.getMTU() : null) : null; + + if (parent_mtu !== null && +value > parent_mtu) + return _('The MTU must not exceed the parent device MTU of %d bytes').format(parent_mtu); + + return true; + }; + + o = this.replaceOption(s, 'devgeneral', form.Value, 'macaddr', _('MAC address')); + o.datatype = 'macaddr'; + + o = this.replaceOption(s, 'devgeneral', form.Value, 'peer_name', _('Peer device name')); + o.rmempty = true; + o.datatype = 'maxlength(15)'; + o.depends('type', 'veth'); + o.load = function(section_id) { + var sections = uci.sections('network', 'device'), + idx = 0; + + for (var i = 0; i < sections.length; i++) + if (sections[i]['.name'] == section_id) + break; + else if (sections[i].type == 'veth') + idx++; + + this.placeholder = 'veth%d'.format(idx); + + return form.Value.prototype.load.apply(this, arguments); + }; + + o = this.replaceOption(s, 'devgeneral', form.Value, 'peer_macaddr', _('Peer MAC address')); + o.rmempty = true; + o.datatype = 'macaddr'; + o.depends('type', 'veth'); + + o = this.replaceOption(s, 'devgeneral', form.Value, 'txqueuelen', _('TX queue length')); + o.placeholder = dev ? dev._devstate('qlen') : ''; + o.datatype = 'uinteger'; + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'promisc', _('Enable promiscuous mode')); + o.default = o.disabled; + + o = this.replaceOption(s, 'devadvanced', form.ListValue, 'rpfilter', _('Reverse path filter')); + o.default = ''; + o.value('', _('disabled')); + o.value('loose', _('Loose filtering')); + o.value('strict', _('Strict filtering')); + o.cfgvalue = function(section_id) { + var val = form.ListValue.prototype.cfgvalue.apply(this, [section_id]); + + switch (val || '') { + case 'loose': + case '1': + return 'loose'; + + case 'strict': + case '2': + return 'strict'; + + default: + return ''; + } + }; + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'acceptlocal', _('Accept local'), _('Accept packets with local source addresses')); + o.default = o.disabled; + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'sendredirects', _('Send ICMP redirects')); + o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', form.Value, 'neighreachabletime', _('Neighbour cache validity'), _('Time in milliseconds')); + o.placeholder = '30000'; + o.datatype = 'uinteger'; + + o = this.replaceOption(s, 'devadvanced', form.Value, 'neighgcstaletime', _('Stale neighbour cache timeout'), _('Timeout in seconds')); + o.placeholder = '60'; + o.datatype = 'uinteger'; + + o = this.replaceOption(s, 'devadvanced', form.Value, 'neighlocktime', _('Minimum ARP validity time'), _('Minimum required time in seconds before an ARP entry may be replaced. Prevents ARP cache thrashing.')); + o.placeholder = '0'; + o.datatype = 'uinteger'; + + o = this.replaceOption(s, 'devgeneral', form.Flag, 'ipv6', _('Enable IPv6')); + o.migrate = false; + o.default = o.enabled; + + o = this.replaceOption(s, 'devgeneral', form.Value, 'mtu6', _('IPv6 MTU')); + o.datatype = 'max(9200)'; + o.depends('ipv6', '1'); + + o = this.replaceOption(s, 'devgeneral', form.Value, 'dadtransmits', _('DAD transmits'), _('Amount of Duplicate Address Detection probes to send')); + o.placeholder = '1'; + o.datatype = 'uinteger'; + o.depends('ipv6', '1'); + + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'multicast', _('Enable multicast support')); + o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', form.ListValue, 'igmpversion', _('Force IGMP version')); + o.value('', _('No enforcement')); + o.value('1', _('Enforce IGMPv1')); + o.value('2', _('Enforce IGMPv2')); + o.value('3', _('Enforce IGMPv3')); + o.depends('multicast', '1'); + + o = this.replaceOption(s, 'devadvanced', form.ListValue, 'mldversion', _('Force MLD version')); + o.value('', _('No enforcement')); + o.value('1', _('Enforce MLD version 1')); + o.value('2', _('Enforce MLD version 2')); + o.depends('multicast', '1'); + + if (isBridgePort(dev)) { + o = this.replaceOption(s, 'brport', form.Flag, 'learning', _('Enable MAC address learning')); + o.default = o.enabled; + + o = this.replaceOption(s, 'brport', form.Flag, 'unicast_flood', _('Enable unicast flooding')); + o.default = o.enabled; + + o = this.replaceOption(s, 'brport', form.Flag, 'isolated', _('Port isolation'), _('Only allow communication with non-isolated bridge ports when enabled')); + o.default = o.disabled; + + o = this.replaceOption(s, 'brport', form.ListValue, 'multicast_router', _('Multicast routing')); + o.value('', _('Never')); + o.value('1', _('Learn')); + o.value('2', _('Always')); + o.depends('multicast', '1'); + + o = this.replaceOption(s, 'brport', form.Flag, 'multicast_to_unicast', _('Multicast to unicast'), _('Forward multicast packets as unicast packets on this device.')); + o.default = o.disabled; + o.depends('multicast', '1'); + + o = this.replaceOption(s, 'brport', form.Flag, 'multicast_fast_leave', _('Enable multicast fast leave')); + o.default = o.disabled; + o.depends('multicast', '1'); + } + + o = this.replaceOption(s, 'bridgevlan', form.Flag, 'vlan_filtering', _('Enable VLAN filtering')); + o.depends('type', 'bridge'); + o.updateDefaultValue = function(section_id) { + var device = uci.get('network', s.section, 'name'), + uielem = this.getUIElement(section_id), + has_vlans = false; + + uci.sections('network', 'bridge-vlan', function(bvs) { + has_vlans = has_vlans || (bvs.device == device); + }); + + this.default = has_vlans ? this.enabled : this.disabled; + + if (uielem && !uielem.isChanged()) + uielem.setValue(this.default); + }; + + o = this.replaceOption(s, 'bridgevlan', form.SectionValue, 'bridge-vlan', form.TableSection, 'bridge-vlan'); + o.depends('type', 'bridge'); + + ss = o.subsection; + ss.addremove = true; + ss.anonymous = true; + + ss.renderHeaderRows = function(/* ... */) { + var node = form.TableSection.prototype.renderHeaderRows.apply(this, arguments); + + node.querySelectorAll('.th').forEach(function(th) { + th.classList.add('left'); + th.classList.add('middle'); + }); + + return node; + }; + + ss.filter = function(section_id) { + var devname = uci.get('network', s.section, 'name'); + return (uci.get('network', section_id, 'device') == devname); + }; + + ss.render = function(/* ... */) { + return form.TableSection.prototype.render.apply(this, arguments).then(L.bind(function(node) { + node.style.overflow = 'auto hidden'; + node.style.paddingTop = '1em'; + + if (this.node) + this.node.parentNode.replaceChild(node, this.node); + + this.node = node; + + return node; + }, this)); + }; + + ss.redraw = function() { + return this.load().then(L.bind(this.render, this)); + }; + + ss.updatePorts = function(ports) { + var devices = ports.map(function(port) { + return network.instantiateDevice(port) + }).filter(function(dev) { + return dev.getType() != 'wifi' || dev.isUp(); + }); + + this.children = this.children.filter(function(opt) { return !opt.option.match(/^port_/) }); + + for (var i = 0; i < devices.length; i++) { + o = ss.option(cbiTagValue, 'port_%s'.format(sfh(devices[i].getName())), renderDevBadge(devices[i]), renderPortStatus(devices[i])); + o.port = devices[i].getName(); + } + + var section_ids = this.cfgsections(), + device_names = devices.reduce(function(names, dev) { names[dev.getName()] = true; return names }, {}); + + for (var i = 0; i < section_ids.length; i++) { + var old_spec = L.toArray(uci.get('network', section_ids[i], 'ports')), + new_spec = old_spec.filter(function(spec) { return device_names[spec.replace(/:[ut*]+$/, '')] }); + + if (old_spec.length != new_spec.length) + uci.set('network', section_ids[i], 'ports', new_spec.length ? new_spec : null); + } + }; + + ss.handleAdd = function(ev) { + return s.parse().then(L.bind(function() { + var device = uci.get('network', s.section, 'name'), + section_ids = this.cfgsections(), + section_id = null, + max_vlan_id = 0; + + if (!device) + return; + + for (var i = 0; i < section_ids.length; i++) { + var vid = +uci.get('network', section_ids[i], 'vlan'); + + if (vid > max_vlan_id) + max_vlan_id = vid; + } + + section_id = uci.add('network', 'bridge-vlan'); + uci.set('network', section_id, 'device', device); + uci.set('network', section_id, 'vlan', max_vlan_id + 1); + + s.children.forEach(function(opt) { + switch (opt.option) { + case 'type': + case 'name_complex': + var input = opt.map.findElement('id', 'widget.%s'.format(opt.cbid(s.section))); + if (input) + input.disabled = true; + break; + } + }); + + s.getOption('vlan_filtering').updateDefaultValue(s.section); + + s.map.addedVLANs = s.map.addedVLANs || []; + s.map.addedVLANs.push(section_id); + + return this.redraw(); + }, this)); + }; + + o = ss.option(form.Value, 'vlan', _('VLAN ID')); + o.datatype = 'range(1, 4094)'; + + o.renderWidget = function(/* ... */) { + var node = form.Value.prototype.renderWidget.apply(this, arguments); + + node.style.width = '5em'; + + return node; + }; + + o.validate = function(section_id, value) { + var section_ids = this.section.cfgsections(); + + for (var i = 0; i < section_ids.length; i++) { + if (section_ids[i] == section_id) + continue; + + if (uci.get('network', section_ids[i], 'vlan') == value) + return _('The VLAN ID must be unique'); + } + + return true; + }; + + o = ss.option(form.Flag, 'local', _('Local')); + o.default = o.enabled; + + var ports = []; + + var seen_ports = {}; + + L.toArray(uci.get('network', s.section, 'ports')).forEach(function(port) { + seen_ports[port] = true; + }); + + uci.sections('network', 'bridge-vlan', function(bvs) { + if (uci.get('network', s.section, 'name') != bvs.device) + return; + + L.toArray(bvs.ports).forEach(function(portspec) { + var m = portspec.match(/^([^:]+)(?::[ut*]+)?$/); + + if (m) + seen_ports[m[1]] = true; + }); + }); + + for (var port_name in seen_ports) + ports.push(port_name); + + ports.sort(function(a, b) { + var m1 = a.match(/^(.+?)([0-9]*)$/), + m2 = b.match(/^(.+?)([0-9]*)$/); + + if (m1[1] < m2[1]) + return -1; + else if (m1[1] > m2[1]) + return 1; + else + return +(m1[2] || 0) - +(m2[2] || 0); + }); + + ss.updatePorts(ports); + }, + + updateDevBadge: updateDevBadge, + updatePortStatus: updatePortStatus +}); diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js index ed2b50866..4dd90cc32 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js @@ -34,8 +34,8 @@ CBILeaseStatus = form.DummyValue.extend({ E('table', { 'id': 'lease_status_table', 'class': 'table' }, [ E('tr', { 'class': 'tr table-titles' }, [ E('th', { 'class': 'th' }, _('Hostname')), - E('th', { 'class': 'th' }, _('IPv4-Address')), - E('th', { 'class': 'th' }, _('MAC-Address')), + E('th', { 'class': 'th' }, _('IPv4 address')), + E('th', { 'class': 'th' }, _('MAC address')), E('th', { 'class': 'th' }, _('Lease time remaining')) ]), E('tr', { 'class': 'tr placeholder' }, [ @@ -53,7 +53,7 @@ CBILease6Status = form.DummyValue.extend({ E('table', { 'id': 'lease6_status_table', 'class': 'table' }, [ E('tr', { 'class': 'tr table-titles' }, [ E('th', { 'class': 'th' }, _('Host')), - E('th', { 'class': 'th' }, _('IPv6-Address')), + E('th', { 'class': 'th' }, _('IPv6 address')), E('th', { 'class': 'th' }, _('DUID')), E('th', { 'class': 'th' }, _('Lease time remaining')) ]), @@ -279,7 +279,8 @@ return view.extend({ o.optional = true; o.placeholder = '/example.org/10.1.2.3'; - // o.validate = validateServerSpec; + o.validate = validateServerSpec; + o = s.taboption('general', form.DynamicList, 'address', _('Addresses'), _('List of domains to force to an IP address.')); @@ -287,6 +288,7 @@ return view.extend({ o.optional = true; o.placeholder = '/router.local/192.168.0.1'; + o = s.taboption('general', form.Flag, 'rebind_protection', _('Rebind protection'), _('Discard upstream RFC1918 responses')); @@ -407,7 +409,7 @@ return view.extend({ o = s.taboption('leases', form.SectionValue, '__leases__', form.GridSection, 'host', null, _('Static leases are used to assign fixed IP addresses and symbolic hostnames to DHCP clients. They are also required for non-dynamic interface configurations where only hosts with a corresponding lease are served.') + '
    ' + - _('Use the Add Button to add a new lease entry. The MAC-Address identifies the host, the IPv4-Address specifies the fixed address to use, and the Hostname is assigned as a symbolic name to the requesting host. The optional Lease time can be used to set non-standard host-specific lease time, e.g. 12h, 3d or infinite.')); + _('Use the Add Button to add a new lease entry. The MAC address identifies the host, the IPv4 address specifies the fixed address to use, and the Hostname is assigned as a symbolic name to the requesting host. The optional Lease time can be used to set non-standard host-specific lease time, e.g. 12h, 3d or infinite.')); ss = o.subsection; @@ -448,7 +450,11 @@ return view.extend({ node.addEventListener('cbi-dropdown-change', L.bind(function(ipopt, section_id, ev) { var mac = ev.detail.value.value; - if (mac == null || mac == '' || !hosts[mac] || !hosts[mac].ipv4) + if (mac == null || mac == '' || !hosts[mac]) + return; + + var iphint = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0]; + if (iphint == null) return; var ip = ipopt.formvalue(section_id); @@ -457,16 +463,35 @@ return view.extend({ var node = ipopt.map.findElement('id', ipopt.cbid(section_id)); if (node) - dom.callClassMethod(node, 'setValue', hosts[mac].ipv4); + dom.callClassMethod(node, 'setValue', iphint); }, this, ipopt, section_id)); return node; }; Object.keys(hosts).forEach(function(mac) { - var hint = hosts[mac].name || hosts[mac].ipv4; + var hint = hosts[mac].name || L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0]; so.value(mac, hint ? '%s (%s)'.format(mac, hint) : mac); }); + so.write = function(section, value) { + var ip = this.map.lookupOption('ip', section)[0].formvalue(section); + var hosts = uci.sections('dhcp', 'host'); + var section_removed = false; + + for (var i = 0; i < hosts.length; i++) { + if (ip == hosts[i].ip) { + uci.set('dhcp', hosts[i]['.name'], 'mac', [hosts[i].mac, value].join(' ')); + uci.remove('dhcp', section); + section_removed = true; + break; + } + } + + if (!section_removed) { + uci.set('dhcp', section, 'mac', value); + } + } + so = ss.option(form.Value, 'ip', _('IPv4-Address')); so.datatype = 'or(ip4addr,"ignore")'; so.validate = function(section, value) { @@ -480,19 +505,21 @@ return view.extend({ return true; }; + + var ipaddrs = {}; + Object.keys(hosts).forEach(function(mac) { - if (hosts[mac].ipv4) { - var hint = hosts[mac].name; - so.value(hosts[mac].ipv4, hint ? '%s (%s)'.format(hosts[mac].ipv4, hint) : hosts[mac].ipv4); - } + var addrs = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4); + + for (var i = 0; i < addrs.length; i++) + ipaddrs[addrs[i]] = hosts[mac].name; }); - so = ss.option(form.Value, 'gw', _('Gateway')); - so.datatype = 'or(ip4addr,"ignore")'; - so.rmempty = true; + L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ipv4) { + so.value(ipv4, ipaddrs[ipv4] ? '%s (%s)'.format(ipv4, ipaddrs[ipv4]) : ipv4); + }); - so = ss.option(form.Value, 'leasetime', _('Lease time'), _('The lease time is in minutes (mini 2m), hours (eg 1h) or "infinite"')); - so.placeholder = '12h'; + so = ss.option(form.Value, 'leasetime', _('Lease time')); so.rmempty = true; so = ss.option(form.Value, 'duid', _('DUID')); @@ -547,7 +574,7 @@ return view.extend({ exp = '%t'.format(lease.expires); var hint = lease.macaddr ? hosts[lease.macaddr] : null, - name = hint ? (hint.name || hint.ipv4 || hint.ipv6) : null, + name = hint ? (hint.name || L.toArray(hint.ipaddrs || hint.ipv4)[0] || L.toArray(hint.ip6addrs || hint.ipv6)[0]) : null, host = null; if (name && lease.hostname && lease.hostname != name && lease.ip6addr != name) diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js b/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js index cd0dacbf6..93ebf5ba6 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js @@ -31,11 +31,18 @@ return view.extend({ o = s.option(form.Value, 'ip', _('IP address')); o.datatype = 'ipaddr'; o.rmempty = true; - L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) { - o.value(hosts[mac].ipv4, '%s (%s)'.format( - hosts[mac].ipv4, - hosts[mac].name || mac - )); + + var ipaddrs = {}; + + Object.keys(hosts).forEach(function(mac) { + var addrs = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4); + + for (var i = 0; i < addrs.length; i++) + ipaddrs[addrs[i]] = hosts[mac].name || mac; + }); + + L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ipv4) { + o.value(ipv4, '%s (%s)'.format(ipv4, ipaddrs[ipv4])); }); return m.render(); diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js index 9944c0920..6f0b2ec96 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js @@ -9,6 +9,7 @@ 'require network'; 'require firewall'; 'require tools.widgets as widgets'; +'require tools.network as nettools'; var isReadonlyView = !L.hasViewPermission() || null; @@ -76,7 +77,6 @@ function render_status(node, ifc, with_device) { macaddr = maindev ? maindev.getMAC() : null; return L.itemlist(node, [ - _('Label'), ifc.get('label'), _('Protocol'), with_device ? null : (desc || '?'), _('Device'), with_device ? (maindev ? maindev.getShortName() : E('em', _('Not present'))) : null, _('Uptime'), (!changecount && ifc.isUp()) ? '%t'.format(ifc.getUptime()) : null, @@ -128,7 +128,7 @@ function render_modal_status(node, ifc) { function render_ifacebox_status(node, ifc) { var dev = ifc.getL3Device() || ifc.getDevice(), - subdevs = ifc.getDevices(), + subdevs = dev ? dev.getPorts() : null, c = [ render_iface(dev, ifc.isAlias()) ]; if (subdevs && subdevs.length) { @@ -228,6 +228,39 @@ function get_netmask(s, use_cfgvalue) { return subnetmask; } +var cbiRichListValue = form.ListValue.extend({ + renderWidget: function(section_id, option_index, cfgvalue) { + var choices = this.transformChoices(); + var widget = new ui.Dropdown((cfgvalue != null) ? cfgvalue : this.default, choices, { + id: this.cbid(section_id), + sort: this.keylist, + optional: true, + select_placeholder: this.select_placeholder || this.placeholder, + custom_placeholder: this.custom_placeholder || this.placeholder, + validate: L.bind(this.validate, this, section_id), + disabled: (this.readonly != null) ? this.readonly : this.map.readonly + }); + + return widget.render(); + }, + + value: function(value, title, description) { + if (description) { + form.ListValue.prototype.value.call(this, value, E([], [ + E('span', { 'class': 'hide-open' }, [ title ]), + E('div', { 'class': 'hide-close', 'style': 'min-width:25vw' }, [ + E('strong', [ title ]), + E('br'), + E('span', { 'style': 'white-space:normal' }, description) + ]) + ])); + } + else { + form.ListValue.prototype.value.call(this, value, title); + } + } +}); + return view.extend({ poll_status: function(map, networks) { var resolveZone = null; @@ -286,20 +319,142 @@ return view.extend({ btn2.disabled = isReadonlyView || btn1.classList.contains('spinning') || btn2.classList.contains('spinning') || dynamic || disabled; } + document.querySelectorAll('.port-status-device[data-device]').forEach(function(node) { + nettools.updateDevBadge(node, network.instantiateDevice(node.getAttribute('data-device'))); + }); + + document.querySelectorAll('.port-status-link[data-device]').forEach(function(node) { + nettools.updatePortStatus(node, network.instantiateDevice(node.getAttribute('data-device'))); + }); + return Promise.all([ resolveZone, network.flushCache() ]); }, load: function() { return Promise.all([ network.getDSLModemType(), + network.getDevices(), + fs.lines('/etc/iproute2/rt_tables'), + L.resolveDefault(fs.read('/usr/lib/opkg/info/netifd.control')), uci.changes() ]); }, + interfaceBridgeWithIfnameSections: function() { + return uci.sections('network', 'interface').filter(function(ns) { + return ns.type == 'bridge' && !ns.ports && ns.ifname; + }); + }, + + deviceWithIfnameSections: function() { + return uci.sections('network', 'device').filter(function(ns) { + return ns.type == 'bridge' && !ns.ports && ns.ifname; + }); + }, + + interfaceWithIfnameSections: function() { + return uci.sections('network', 'interface').filter(function(ns) { + return !ns.device && ns.ifname; + }); + }, + + handleBridgeMigration: function(ev) { + var tasks = []; + + this.interfaceBridgeWithIfnameSections().forEach(function(ns) { + var device_name = 'br-' + ns['.name']; + + tasks.push(uci.callAdd('network', 'device', null, { + 'name': device_name, + 'type': 'bridge', + 'ports': L.toArray(ns.ifname), + 'mtu': ns.mtu, + 'macaddr': ns.macaddr, + 'igmp_snooping': ns.igmp_snooping + })); + + tasks.push(uci.callSet('network', ns['.name'], { + 'type': '', + 'ifname': '', + 'mtu': '', + 'macaddr': '', + 'igmp_snooping': '', + 'device': device_name + })); + }); + + return Promise.all(tasks) + .then(L.bind(ui.changes.init, ui.changes)) + .then(L.bind(ui.changes.apply, ui.changes)); + }, + + renderBridgeMigration: function() { + ui.showModal(_('Network bridge configuration migration'), [ + E('p', _('The existing network configuration needs to be changed for LuCI to function properly.')), + E('p', _('Upon pressing "Continue", bridges configuration will be updated and the network will be restarted to apply the updated configuration.')), + E('div', { 'class': 'right' }, + E('button', { + 'class': 'btn cbi-button-action important', + 'click': ui.createHandlerFn(this, 'handleBridgeMigration') + }, _('Continue'))) + ]); + }, + + handleIfnameMigration: function(ev) { + var tasks = []; + + this.deviceWithIfnameSections().forEach(function(ds) { + tasks.push(uci.callSet('network', ds['.name'], { + 'ifname': '', + 'ports': L.toArray(ds.ifname) + })); + }); + + this.interfaceWithIfnameSections().forEach(function(ns) { + tasks.push(uci.callSet('network', ns['.name'], { + 'ifname': '', + 'device': ns.ifname + })); + }); + + return Promise.all(tasks) + .then(L.bind(ui.changes.init, ui.changes)) + .then(L.bind(ui.changes.apply, ui.changes)); + }, + + renderIfnameMigration: function() { + ui.showModal(_('Network ifname configuration migration'), [ + E('p', _('The existing network configuration needs to be changed for LuCI to function properly.')), + E('p', _('Upon pressing "Continue", ifname options will get renamed and the network will be restarted to apply the updated configuration.')), + E('div', { 'class': 'right' }, + E('button', { + 'class': 'btn cbi-button-action important', + 'click': ui.createHandlerFn(this, 'handleIfnameMigration') + }, _('Continue'))) + ]); + }, + render: function(data) { + var netifdVersion = (data[3] || '').match(/Version: ([^\n]+)/); + + if (netifdVersion && netifdVersion[1] >= "2021-05-26") { + if (this.interfaceBridgeWithIfnameSections().length) + return this.renderBridgeMigration(); + else if (this.deviceWithIfnameSections().length || this.interfaceWithIfnameSections().length) + return this.renderIfnameMigration(); + } + var dslModemType = data[0], + netDevs = data[1], m, s, o; + var rtTables = data[2].map(function(l) { + var m = l.trim().match(/^(\d+)\s+(\S+)$/); + return m ? [ +m[1], m[2] ] : null; + }).filter(function(e) { + return e && e[0] > 0; + }); + m = new form.Map('network'); m.tabbed = true; m.chain('dhcp'); @@ -322,6 +477,8 @@ return view.extend({ s.tab('general', _('General Settings')); s.tab('advanced', _('Advanced Settings')); s.tab('physical', _('Physical Settings')); + s.tab('brport', _('Bridge port specific options')); + s.tab('bridgevlan', _('Bridge VLAN filtering')); s.tab('firewall', _('Firewall Settings')); s.tab('dhcp', _('DHCP Server')); @@ -369,7 +526,7 @@ return view.extend({ s.addModalOptions = function(s) { var protoval = uci.get('network', s.section, 'proto'), protoclass = protoval ? network.getProtocol(protoval) : null, - o, ifname_single, ifname_multi, ifname_master, proto_select, proto_switch, type, stp, igmp, ss, so; + o, proto_select, proto_switch, type, stp, igmp, ss, so; if (!protoval) return; @@ -393,9 +550,6 @@ return view.extend({ }, this); o.write = function() {}; - o = s.taboption('general', form.Value, 'label', _('Label')); - o.modalonly = true; - o.optional = true; proto_select = s.taboption('general', form.ListValue, 'proto', _('Protocol')); proto_select.modalonly = true; @@ -412,170 +566,16 @@ return view.extend({ .then(L.bind(this.renderMoreOptionsModal, this, s.section)); }, this); + o = s.taboption('general', widgets.DeviceSelect, '_net_device', _('Device')); + o.ucioption = 'device'; + o.nobridges = false; + o.optional = false; + o.network = ifc.getName(); + o = s.taboption('general', form.Flag, 'auto', _('Bring up on boot')); o.modalonly = true; o.default = o.enabled; - type = s.taboption('physical', form.ListValue, 'type', _('Type')); - type.value('',_('Normal')); - type.value('bridge',_('Bridge')); - type.value('macvlan',_('MacVLAN')); - type.write = type.remove = function(section_id, value) { - var protocol = network.getProtocol(proto_select.formvalue(section_id)), - ifnameopt = this.section.children.filter(function(o) { - if (value == 'bridge') - return o.option == 'ifname_multi'; - else if (value == 'macvlan') - return o.option == 'ifname_master'; - else - return o.option == 'ifname_single'; - })[0]; - - if (!protocol.isVirtual() && !this.isActive(section_id)) - return; - - var old_ifnames = [], - devs = ifc.getDevices() || L.toArray(ifc.getDevice()); - - for (var i = 0; i < devs.length; i++) - old_ifnames.push(devs[i].getName()); - - var new_ifnames = L.toArray(ifnameopt.formvalue(section_id)); - - if (!value) - new_ifnames.length = Math.max(new_ifnames.length, 1); - - old_ifnames.sort(); - new_ifnames.sort(); - - for (var i = 0; i < Math.max(old_ifnames.length, new_ifnames.length); i++) { - if (old_ifnames[i] != new_ifnames[i]) { - // backup_ifnames() - for (var j = 0; j < old_ifnames.length; j++) - ifc.deleteDevice(old_ifnames[j]); - - for (var j = 0; j < new_ifnames.length; j++) - ifc.addDevice(new_ifnames[j]); - - break; - } - } - - if (value) - uci.set('network', section_id, 'type', value); - else - uci.unset('network', section_id, 'type'); - }; - - o = s.taboption('advanced', form.Value, 'ip6assign', _('IPv6 assignment length'), _('Assign a part of given length of every public IPv6-prefix to this interface')); - o.value('', _('disabled')); - o.value('64'); - o.datatype = 'max(64)'; - - o = s.taboption('advanced', form.Value, 'ip6hint', _('IPv6 assignment hint'), _('Assign prefix parts using this hexadecimal subprefix ID for this interface.')); - o.placeholder = '0'; - o.validate = function(section_id, value) { - if (value == null || value == '') - return true; - var n = parseInt(value, 16); - if (!/^(0x)?[0-9a-fA-F]+$/.test(value) || isNaN(n) || n >= 0xffffffff) - return _('Expecting a hexadecimal assignment hint'); - return true; - }; - - for (var i = 33; i <= 64; i++) - o.depends('ip6assign', String(i)); - - o = s.taboption('advanced', form.DynamicList, 'ip6addr', _('IPv6 address')); - o.datatype = 'ip6addr'; - o.placeholder = _('Add IPv6 address…'); - o.depends('ip6assign', ''); - - o = s.taboption('advanced', form.Value, 'ip6gw', _('IPv6 gateway')); - o.datatype = 'ip6addr("nomask")'; - o.depends('ip6assign', ''); - - o = s.taboption('advanced', form.Value, 'ip6prefix', _('IPv6 routed prefix'), _('Public prefix routed to this device for distribution to clients.')); - o.datatype = 'ip6addr'; - o.depends('ip6assign', ''); - - o = s.taboption('advanced', form.Value, 'ip6ifaceid', _('IPv6 suffix'), _("Optional. Allowed values: 'eui64', 'random', fixed value like '::1' or '::1:2'. When IPv6 prefix (like 'a:b:c:d::') is received from a delegating server, use the suffix (like '::1') to form the IPv6 address ('a:b:c:d::1') for the interface.")); - o.datatype = 'ip6hostid'; - o.placeholder = '::1'; - - stp = s.taboption('physical', form.Flag, 'stp', _('Enable STP'), _('Enables the Spanning Tree Protocol on this bridge')); - - igmp = s.taboption('physical', form.Flag, 'igmp_snooping', _('Enable IGMP snooping'), _('Enables IGMP snooping on this bridge')); - - ifname_master = s.taboption('physical', widgets.DeviceSelect, 'ifname_master', _('Base interface')); - ifname_master.nobridges = true; - ifname_master.noaliases = true; - ifname_master.optional = false; - ifname_master.modalonly = true; - ifname_master.network = ifc.getName(); - //ifname_master.write = ifname_master.remove = function() {}; - ifname_master.ucioption = 'masterintf'; - //ifname_master.cfgvalue = function(section_id) { - // return uci.get('network', section_id, 'masterintf'); - //}; - //ifname_master.write = function(section_id, value) { - // uci.set('network', section_id, 'masterintf', value); - //}; - - ifname_single = s.taboption('physical', widgets.DeviceSelect, 'ifname_single', _('Interface')); - ifname_single.nobridges = ifc.isBridge(); - ifname_single.noaliases = false; - ifname_single.optional = false; - ifname_single.network = ifc.getName(); - ifname_single.write = ifname_single.remove = function() {}; - - ifname_multi = s.taboption('physical', widgets.DeviceSelect, 'ifname_multi', _('Interface')); - ifname_multi.nobridges = ifc.isBridge(); - ifname_multi.noaliases = true; - ifname_multi.multiple = true; - ifname_multi.optional = true; - ifname_multi.network = ifc.getName(); - ifname_multi.display_size = 6; - ifname_multi.write = ifname_multi.remove = function(section_id, value) { - var old_ifnames = [], - devs = ifc.getDevices() || L.toArray(ifc.getDevice()); - - for (var i = 0; i < devs.length; i++) - old_ifnames.push(devs[i].getName()); - - var new_ifnames = L.toArray(value); - - if (value == null) - return; - - old_ifnames.sort(); - new_ifnames.sort(); - - for (var i = 0; i < Math.max(old_ifnames.length, new_ifnames.length); i++) { - if (old_ifnames[i] != new_ifnames[i]) { - // backup_ifnames() - for (var j = 0; j < old_ifnames.length; j++) - ifc.deleteDevice(old_ifnames[j]); - - for (var j = 0; j < new_ifnames.length; j++) - ifc.addDevice(new_ifnames[j]); - - break; - } - } - }; - - - ifname_single.cfgvalue = ifname_multi.cfgvalue = function(section_id) { - var devs = ifc.getDevices() || L.toArray(ifc.getDevice()), - ifnames = []; - - for (var i = 0; i < devs.length; i++) - ifnames.push(devs[i].getName()); - - return ifnames; - }; - if (L.hasSystemFeature('firewall')) { o = s.taboption('firewall', widgets.ZoneSelect, '_zone', _('Create / Assign firewall-zone'), _('Choose the firewall zone you want to assign to this interface. Select unspecified to remove the interface from the associated zone or fill out the custom field to define a new zone and attach the interface to it.')); o.network = ifc.getName(); @@ -619,31 +619,10 @@ return view.extend({ if (protocols[i].getProtocol() != uci.get('network', s.section, 'proto')) proto_switch.depends('proto', protocols[i].getProtocol()); - - if (!protocols[i].isVirtual()) { - type.depends('proto', protocols[i].getProtocol()); - stp.depends({ type: 'bridge', proto: protocols[i].getProtocol() }); - igmp.depends({ type: 'bridge', proto: protocols[i].getProtocol() }); - ifname_single.depends({ type: '', proto: protocols[i].getProtocol() }); - ifname_master.depends({ type: 'macvlan', proto: protocols[i].getProtocol() }); - ifname_multi.depends({ type: 'bridge', proto: protocols[i].getProtocol() }); - } } - o = s.taboption('advanced', form.ListValue, 'multipath', _('Multipath setting'), _('Only one interface must be set as Master.')); - o.value('on',_('Enabled')); - o.value('off',_('Disabled')); - o.value('master',_('Master')); - o.value('backup',_('Backup')); - o.default = 'off'; - - o = s.taboption('advanced', form.Value, 'addlatency', _('Additional latency')); - o.datatype = 'uinteger'; - o.default = '0'; - if (L.hasSystemFeature('dnsmasq') || L.hasSystemFeature('odhcpd')) { o = s.taboption('dhcp', form.SectionValue, '_dhcp', form.TypedSection, 'dhcp'); - o.depends('proto', 'static'); ss = o.subsection; ss.uciconfig = 'dhcp'; @@ -653,6 +632,7 @@ return view.extend({ ss.tab('general', _('General Setup')); ss.tab('advanced', _('Advanced Settings')); ss.tab('ipv6', _('IPv6 Settings')); + ss.tab('ipv6-ra', _('IPv6 RA Settings')); ss.filter = function(section_id) { return (uci.get('dhcp', section_id, 'interface') == ifc.getName()); @@ -668,9 +648,15 @@ return view.extend({ this.map.save(function() { uci.add('dhcp', 'dhcp', section_id); uci.set('dhcp', section_id, 'interface', section_id); - uci.set('dhcp', section_id, 'start', 100); - uci.set('dhcp', section_id, 'limit', 150); - uci.set('dhcp', section_id, 'leasetime', '12h'); + + if (protoval == 'static') { + uci.set('dhcp', section_id, 'start', 100); + uci.set('dhcp', section_id, 'limit', 150); + uci.set('dhcp', section_id, 'leasetime', '12h'); + } + else { + uci.set('dhcp', section_id, 'ignore', 1); + } }); }, ifc.getName()) }, _('Setup DHCP Server')) @@ -679,108 +665,389 @@ return view.extend({ ss.taboption('general', form.Flag, 'ignore', _('Ignore interface'), _('Disable DHCP for this interface.')); - so = ss.taboption('general', form.Value, 'start', _('Start'), _('Lowest leased address as offset from the network address.')); - so.optional = true; - so.datatype = 'or(uinteger,ip4addr("nomask"))'; - so.default = '100'; + if (protoval == 'static') { + so = ss.taboption('general', form.Value, 'start', _('Start'), _('Lowest leased address as offset from the network address.')); + so.optional = true; + so.datatype = 'or(uinteger,ip4addr("nomask"))'; + so.default = '100'; - so = ss.taboption('general', form.Value, 'limit', _('Limit'), _('Maximum number of leased addresses.')); - so.optional = true; - so.datatype = 'uinteger'; - so.default = '150'; + so = ss.taboption('general', form.Value, 'limit', _('Limit'), _('Maximum number of leased addresses.')); + so.optional = true; + so.datatype = 'uinteger'; + so.default = '150'; - so = ss.taboption('general', form.Value, 'leasetime', _('Lease time'), _('Expiry time of leased addresses, minimum is 2 minutes (2m).')); - so.optional = true; - so.default = '12h'; + so = ss.taboption('general', form.Value, 'leasetime', _('Lease time'), _('Expiry time of leased addresses, minimum is 2 minutes (2m).')); + so.optional = true; + so.default = '12h'; - so = ss.taboption('advanced', form.Flag, 'dynamicdhcp', _('Dynamic DHCP'), _('Dynamically allocate DHCP addresses for clients. If disabled, only clients having static leases will be served.')); - so.default = so.enabled; + so = ss.taboption('advanced', form.Flag, 'dynamicdhcp', _('Dynamic DHCP'), _('Dynamically allocate DHCP addresses for clients. If disabled, only clients having static leases will be served.')); + so.default = so.enabled; - ss.taboption('advanced', form.Flag, 'force', _('Force'), _('Force DHCP on this network even if another server is detected.')); + ss.taboption('advanced', form.Flag, 'force', _('Force'), _('Force DHCP on this network even if another server is detected.')); - // XXX: is this actually useful? - //ss.taboption('advanced', form.Value, 'name', _('Name'), _('Define a name for this network.')); + // XXX: is this actually useful? + //ss.taboption('advanced', form.Value, 'name', _('Name'), _('Define a name for this network.')); - so = ss.taboption('advanced', form.Value, 'netmask', _('IPv4-Netmask'), _('Override the netmask sent to clients. Normally it is calculated from the subnet that is served.')); - so.optional = true; - so.datatype = 'ip4addr'; + so = ss.taboption('advanced', form.Value, 'netmask', _('IPv4-Netmask'), _('Override the netmask sent to clients. Normally it is calculated from the subnet that is served.')); + so.optional = true; + so.datatype = 'ip4addr'; - so.render = function(option_index, section_id, in_table) { - this.placeholder = get_netmask(s, true); - return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]); - }; + so.render = function(option_index, section_id, in_table) { + this.placeholder = get_netmask(s, true); + return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]); + }; + + so.validate = function(section_id, value) { + var uielem = this.getUIElement(section_id); + if (uielem) + uielem.setPlaceholder(get_netmask(s, false)); + return form.Value.prototype.validate.apply(this, [ section_id, value ]); + }; + + ss.taboption('advanced', form.DynamicList, 'dhcp_option', _('DHCP-Options'), _('Define additional DHCP options, for example "6,192.168.2.1,192.168.2.2" which advertises different DNS servers to clients.')); + } + + + var has_other_master = uci.sections('dhcp', 'dhcp').filter(function(s) { + return (s.interface != ifc.getName() && s.master == '1'); + })[0]; + + so = ss.taboption('ipv6', form.Flag , 'master', _('Designated master')); + so.readonly = has_other_master ? true : false; + so.description = has_other_master + ? _('Interface "%h" is already marked as designated master.').format(has_other_master.interface || has_other_master['.name']) + : _('Set this interface as master for RA and DHCPv6 relaying as well as NDP proxying.') + ; so.validate = function(section_id, value) { - var uielem = this.getUIElement(section_id); - if (uielem) - uielem.setPlaceholder(get_netmask(s, false)); - return form.Value.prototype.validate.apply(this, [ section_id, value ]); + var hybrid_downstream_desc = _('Operate in relay mode if a designated master interface is configured and active, otherwise fall back to server mode.'), + ndp_downstream_desc = _('Operate in relay mode if a designated master interface is configured and active, otherwise disable NDP proxying.'), + hybrid_master_desc = _('Operate in relay mode if an upstream IPv6 prefix is present, otherwise disable service.'), + checked = this.formvalue(section_id), + dhcpv6 = this.section.getOption('dhcpv6').getUIElement(section_id), + ndp = this.section.getOption('ndp').getUIElement(section_id), + ra = this.section.getOption('ra').getUIElement(section_id); + + if (checked == '1' || protoval != 'static') { + dhcpv6.node.querySelector('li[data-value="server"]').setAttribute('unselectable', ''); + + if (dhcpv6.getValue() == 'server') + dhcpv6.setValue('hybrid'); + + ra.node.querySelector('li[data-value="server"]').setAttribute('unselectable', ''); + + if (ra.getValue() == 'server') + ra.setValue('hybrid'); + } + + if (checked == '1') { + dhcpv6.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_master_desc; + ra.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_master_desc; + ndp.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_master_desc; + } + else { + if (protoval == 'static') { + dhcpv6.node.querySelector('li[data-value="server"]').removeAttribute('unselectable'); + ra.node.querySelector('li[data-value="server"]').removeAttribute('unselectable'); + } + + dhcpv6.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_downstream_desc; + ra.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_downstream_desc; + ndp.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = ndp_downstream_desc ; + } + + return true; }; - ss.taboption('advanced', form.DynamicList, 'dhcp_option', _('DHCP-Options'), _('Define additional DHCP options, for example "6,192.168.2.1,192.168.2.2" which advertises different DNS servers to clients.')); - for (var i = 0; i < ss.children.length; i++) - if (ss.children[i].option != 'ignore') - ss.children[i].depends('ignore', '0'); + so = ss.taboption('ipv6', cbiRichListValue, 'ra', _('RA-Service'), + _('Configures the operation mode of the RA service on this interface.')); + so.value('', _('disabled'), + _('Do not send any RA messages on this interface.')); + so.value('server', _('server mode'), + _('Send RA messages advertising this device as IPv6 router.')); + so.value('relay', _('relay mode'), + _('Forward RA messages received on the designated master interface to downstream interfaces.')); + so.value('hybrid', _('hybrid mode'), ' '); - so = ss.taboption('ipv6', form.ListValue, 'ra', _('Router Advertisement-Service')); - so.value('', _('disabled')); - so.value('server', _('server mode')); - so.value('relay', _('relay mode')); - so.value('hybrid', _('hybrid mode')); - so = ss.taboption('ipv6', form.ListValue, 'dhcpv6', _('DHCPv6-Service')); - so.value('', _('disabled')); - so.value('server', _('server mode')); - so.value('relay', _('relay mode')); - so.value('hybrid', _('hybrid mode')); - - so = ss.taboption('ipv6', form.ListValue, 'ndp', _('NDP-Proxy')); - so.value('', _('disabled')); - so.value('relay', _('relay mode')); - so.value('hybrid', _('hybrid mode')); - - so = ss.taboption('ipv6', form.Flag , 'master', _('Master'), _('Set this interface as master for the dhcpv6 relay.')); - so.depends('dhcpv6', 'relay'); - so.depends('dhcpv6', 'hybrid'); - - so = ss.taboption('ipv6', form.ListValue, 'ra_management', _('DHCPv6-Mode'), _('Default is stateless + stateful')); - so.value('0', _('stateless')); - so.value('1', _('stateless + stateful')); - so.value('2', _('stateful-only')); - so.depends('dhcpv6', 'server'); - so.depends('dhcpv6', 'hybrid'); - so.default = '1'; - - so = ss.taboption('ipv6', form.Flag, 'ra_default', _('Always announce default router'), _('Announce as default router even if no public prefix is available.')); + so = ss.taboption('ipv6-ra', cbiRichListValue, 'ra_default', _('Default router'), + _('Configures the default router advertisement in RA messages.')); + so.value('', _('automatic'), + _('Announce this device as default router if a local IPv6 default route is present.')); + so.value('1', _('on available prefix'), + _('Announce this device as default router if a public IPv6 prefix is available, regardless of local default route availability.')); + so.value('2', _('forced'), + _('Announce this device as default router regardless of whether a prefix or default route is present.')); so.depends('ra', 'server'); - so.depends('ra', 'hybrid'); + so.depends({ ra: 'hybrid', master: '0' }); - ss.taboption('ipv6', form.DynamicList, 'dns', _('Announced DNS servers')); - ss.taboption('ipv6', form.DynamicList, 'domain', _('Announced DNS domains')); + so = ss.taboption('ipv6-ra', form.Flag, 'ra_slaac', _('Enable SLAAC'), + _('Set the autonomous address-configuration flag in the prefix information options of sent RA messages. When enabled, clients will perform stateless IPv6 address autoconfiguration.')); + so.default = so.enabled; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + + so = ss.taboption('ipv6-ra', cbiRichListValue, 'ra_flags', _('RA Flags'), + _('Specifies the flags sent in RA messages, for example to instruct clients to request further information via stateful DHCPv6.')); + so.value('managed-config', _('managed config (M)'), + _('The Managed address configuration (M) flag indicates that IPv6 addresses are available via DHCPv6.')); + so.value('other-config', _('other config (O)'), + _('The Other configuration (O) flag indicates that other information, such as DNS servers, is available via DHCPv6.')); + so.value('home-agent', _('mobile home agent (H)'), + _('The Mobile IPv6 Home Agent (H) flag indicates that the device is also acting as Mobile IPv6 home agent on this link.')); + so.multiple = true; + so.select_placeholder = _('none'); + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + so.cfgvalue = function(section_id) { + var flags = L.toArray(uci.get('dhcp', section_id, 'ra_flags')); + return flags.length ? flags : [ 'other-config' ]; + }; + so.remove = function(section_id) { + uci.set('dhcp', section_id, 'ra_flags', [ 'none' ]); + }; + + so = ss.taboption('ipv6-ra', form.Value, 'ra_maxinterval', _('Max RA interval'), _('Maximum time allowed between sending unsolicited RA. Default is 600 seconds.')); + so.optional = true; + so.datatype = 'uinteger'; + so.placeholder = '600'; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + + so = ss.taboption('ipv6-ra', form.Value, 'ra_mininterval', _('Min RA interval'), _('Minimum time allowed between sending unsolicited RA. Default is 200 seconds.')); + so.optional = true; + so.datatype = 'uinteger'; + so.placeholder = '200'; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + + so = ss.taboption('ipv6-ra', form.Value, 'ra_lifetime', _('RA Lifetime'), _('Router Lifetime published in RA messages. Maximum is 9000 seconds.')); + so.optional = true; + so.datatype = 'range(0, 9000)'; + so.placeholder = '1800'; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + + so = ss.taboption('ipv6-ra', form.Value, 'ra_mtu', _('RA MTU'), _('The MTU to be published in RA messages. Minimum is 1280 bytes.')); + so.optional = true; + so.datatype = 'range(1280, 65535)'; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + so.load = function(section_id) { + var dev = ifc.getL3Device(); + + if (dev) { + var path = "/proc/sys/net/ipv6/conf/%s/mtu".format(dev.getName()); + + return L.resolveDefault(fs.read(path), dev.getMTU()).then(L.bind(function(data) { + this.placeholder = data; + }, this)); + } + }; + + so = ss.taboption('ipv6-ra', form.Value, 'ra_hoplimit', _('RA Hop Limit'), _('The maximum hops to be published in RA messages. Maximum is 255 hops.')); + so.optional = true; + so.datatype = 'range(0, 255)'; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + so.load = function(section_id) { + var dev = ifc.getL3Device(); + + if (dev) { + var path = "/proc/sys/net/ipv6/conf/%s/hop_limit".format(dev.getName()); + + return L.resolveDefault(fs.read(path), 64).then(L.bind(function(data) { + this.placeholder = data; + }, this)); + } + }; + + + so = ss.taboption('ipv6', cbiRichListValue, 'dhcpv6', _('DHCPv6-Service'), + _('Configures the operation mode of the DHCPv6 service on this interface.')); + so.value('', _('disabled'), + _('Do not offer DHCPv6 service on this interface.')); + so.value('server', _('server mode'), + _('Provide a DHCPv6 server on this interface and reply to DHCPv6 solicitations and requests.')); + so.value('relay', _('relay mode'), + _('Forward DHCPv6 messages between the designated master interface and downstream interfaces.')); + so.value('hybrid', _('hybrid mode'), ' '); + + + so = ss.taboption('ipv6', form.DynamicList, 'dns', _('Announced IPv6 DNS servers'), + _('Specifies a fixed list of IPv6 DNS server addresses to announce via DHCPv6. If left unspecified, the device will announce itself as IPv6 DNS server unless the Local IPv6 DNS server option is disabled.')); + so.datatype = 'ip6addr("nomask")'; /* restrict to IPv6 only for now since dnsmasq (DHCPv4) does not honour this option */ + so.depends('dhcpv6', 'server'); + so.depends({ dhcpv6: 'hybrid', master: '0' }); + + so = ss.taboption('ipv6', form.Flag, 'dns_service', _('Local IPv6 DNS server'), + _('Announce this device as IPv6 DNS server.')); + so.default = so.enabled; + so.depends({ dhcpv6: 'server', dns: /^$/ }); + so.depends({ dhcpv6: 'hybrid', dns: /^$/, master: '0' }); + + so = ss.taboption('ipv6', form.DynamicList, 'domain', _('Announced DNS domains'), + _('Specifies a fixed list of DNS search domains to announce via DHCPv6. If left unspecified, the local device DNS search domain will be announced.')); + so.datatype = 'hostname'; + so.depends('dhcpv6', 'server'); + so.depends({ dhcpv6: 'hybrid', master: '0' }); + + + so = ss.taboption('ipv6', cbiRichListValue, 'ndp', _('NDP-Proxy'), + _('Configures the operation mode of the NDP proxy service on this interface.')); + so.value('', _('disabled'), + _('Do not proxy any NDP packets.')); + so.value('relay', _('relay mode'), + _('Forward NDP NS and NA messages between the designated master interface and downstream interfaces.')); + so.value('hybrid', _('hybrid mode'), ' '); + + + so = ss.taboption('ipv6', form.Flag, 'ndproxy_routing', _('Learn routes'), _('Setup routes for proxied IPv6 neighbours.')); + so.default = so.enabled; + so.depends('ndp', 'relay'); + so.depends('ndp', 'hybrid'); + + so = ss.taboption('ipv6', form.Flag, 'ndproxy_slave', _('NDP-Proxy slave'), _('Set interface as NDP-Proxy external slave. Default is off.')); + so.depends({ ndp: 'relay', master: '0' }); + so.depends({ ndp: 'hybrid', master: '0' }); } ifc.renderFormOptions(s); + // Common interface options + o = nettools.replaceOption(s, 'advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured')); + o.default = o.enabled; + + if (protoval != 'static') { + o = nettools.replaceOption(s, 'advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored')); + o.default = o.enabled; + } + + o = nettools.replaceOption(s, 'advanced', form.DynamicList, 'dns', _('Use custom DNS servers')); + if (protoval != 'static') + o.depends('peerdns', '0'); + o.datatype = 'ipaddr'; + + o = nettools.replaceOption(s, 'advanced', form.DynamicList, 'dns_search', _('DNS search domains')); + if (protoval != 'static') + o.depends('peerdns', '0'); + o.datatype = 'hostname'; + + o = nettools.replaceOption(s, 'advanced', form.Value, 'dns_metric', _('DNS weight'), _('The DNS server entries in the local resolv.conf are primarily sorted by the weight specified here')); + o.datatype = 'uinteger'; + o.placeholder = '0'; + + o = nettools.replaceOption(s, 'advanced', form.Value, 'metric', _('Use gateway metric')); + o.datatype = 'uinteger'; + o.placeholder = '0'; + + o = nettools.replaceOptions(s,'advanced', form.ListValue, 'multipath', _('Multipath setting'), _('Only one interface must be set as Master.')); + o.value('on',_('Enabled')); + o.value('off',_('Disabled')); + o.value('master',_('Master')); + o.value('backup',_('Backup')); + o.default = 'off'; + + o = nettools.replaceOptions(s,'advanced', form.Value, 'addlatency', _('Additional latency')); + o.datatype = 'uinteger'; + o.default = '0'; + + o = nettools.replaceOption(s, 'advanced', form.Value, 'ip4table', _('Override IPv4 routing table')); + o.datatype = 'or(uinteger, string)'; + for (var i = 0; i < rtTables.length; i++) + o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0])); + + o = nettools.replaceOption(s, 'advanced', form.Value, 'ip6table', _('Override IPv6 routing table')); + o.datatype = 'or(uinteger, string)'; + for (var i = 0; i < rtTables.length; i++) + o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][0], rtTables[i][1])); + + o = nettools.replaceOption(s, 'advanced', form.Flag, 'delegate', _('Delegate IPv6 prefixes'), _('Enable downstream delegation of IPv6 prefixes available on this interface')); + o.default = o.enabled; + + o = nettools.replaceOption(s, 'advanced', form.Value, 'ip6assign', _('IPv6 assignment length'), _('Assign a part of given length of every public IPv6-prefix to this interface')); + o.value('', _('disabled')); + o.value('64'); + o.datatype = 'max(128)'; + + o = nettools.replaceOption(s, 'advanced', form.Value, 'ip6hint', _('IPv6 assignment hint'), _('Assign prefix parts using this hexadecimal subprefix ID for this interface.')); + o.placeholder = '0'; + o.validate = function(section_id, value) { + if (value == null || value == '') + return true; + + var n = parseInt(value, 16); + + if (!/^(0x)?[0-9a-fA-F]+$/.test(value) || isNaN(n) || n >= 0xffffffff) + return _('Expecting a hexadecimal assignment hint'); + + return true; + }; + for (var i = 33; i <= 64; i++) + o.depends('ip6assign', String(i)); + + + o = nettools.replaceOption(s, 'advanced', form.DynamicList, 'ip6class', _('IPv6 prefix filter'), _('If set, downstream subnets are only allocated from the given IPv6 prefix classes.')); + o.value('local', 'local (%s)'.format(_('Local ULA'))); + + var prefixClasses = {}; + + this.networks.forEach(function(net) { + var prefixes = net._ubus('ipv6-prefix'); + if (Array.isArray(prefixes)) { + prefixes.forEach(function(pfx) { + if (L.isObject(pfx) && typeof(pfx['class']) == 'string') { + prefixClasses[pfx['class']] = prefixClasses[pfx['class']] || {}; + prefixClasses[pfx['class']][net.getName()] = true; + } + }); + } + }); + + Object.keys(prefixClasses).sort().forEach(function(c) { + var networks = Object.keys(prefixClasses[c]).sort().join(', '); + o.value(c, (c != networks) ? '%s (%s)'.format(c, networks) : c); + }); + + + o = nettools.replaceOption(s, 'advanced', form.Value, 'ip6ifaceid', _('IPv6 suffix'), _("Optional. Allowed values: 'eui64', 'random', fixed value like '::1' or '::1:2'. When IPv6 prefix (like 'a:b:c:d::') is received from a delegating server, use the suffix (like '::1') to form the IPv6 address ('a:b:c:d::1') for the interface.")); + o.datatype = 'ip6hostid'; + o.placeholder = '::1'; + + o = nettools.replaceOption(s, 'advanced', form.Value, 'ip6weight', _('IPv6 preference'), _('When delegating prefixes to multiple downstreams, interfaces with a higher preference value are considered first when allocating subnets.')); + o.datatype = 'uinteger'; + o.placeholder = '0'; + for (var i = 0; i < s.children.length; i++) { o = s.children[i]; switch (o.option) { case 'proto': - case 'delegate': case 'auto': - case 'type': - case 'stp': - case 'igmp_snooping': - case 'ifname_single': - case 'ifname_multi': - case 'ifname_master': case '_dhcp': case '_zone': case '_switch_proto': case '_ifacestat_modal': continue; + case 'igmp_snooping': + case 'stp': + case 'type': + case '_net_device': + var deps = []; + for (var j = 0; j < protocols.length; j++) { + if (!protocols[j].isVirtual()) { + if (o.deps.length) + for (var k = 0; k < o.deps.length; k++) + deps.push(Object.assign({ proto: protocols[j].getProtocol() }, o.deps[k])); + else + deps.push({ proto: protocols[j].getProtocol() }); + } + } + o.deps = deps; + break; + default: if (o.deps.length) for (var j = 0; j < o.deps.length; j++) @@ -789,14 +1056,28 @@ return view.extend({ o.depends('proto', protoval); } } + + this.activeSection = s.section; }, this)); }; + s.handleModalCancel = function(/* ... */) { + var type = uci.get('network', this.activeSection || this.addedSection, 'type'), + device = (type == 'bridge') ? 'br-%s'.format(this.activeSection || this.addedSection) : null; + + uci.sections('network', 'bridge-vlan', function(bvs) { + if (device != null && bvs.device == device) + uci.remove('network', bvs['.name']); + }); + + return form.GridSection.prototype.handleModalCancel.apply(this, arguments); + }; + s.handleAdd = function(ev) { var m2 = new form.Map('network'), s2 = m2.section(form.NamedSection, '_new_'), protocols = network.getProtocols(), - proto, name, type, ifname_single, ifname_multi, ifname_master; + proto, name, device; protocols.sort(function(a, b) { return a.getProtocol() > b.getProtocol(); @@ -829,35 +1110,15 @@ return view.extend({ proto = s2.option(form.ListValue, 'proto', _('Protocol')); proto.validate = name.validate; - type = s2.option(form.ListValue, 'type', _('Interface type')); - type.value('',_('Normal')); - type.value('bridge',_('Bridge')); - type.value('macvlan',_('MacVLAN')); - - ifname_single = s2.option(widgets.DeviceSelect, 'ifname_single', _('Interface')); - ifname_single.noaliases = false; - ifname_single.optional = false; - - ifname_master = s2.option(widgets.DeviceSelect, 'ifname_master', _('Base interface')); - ifname_master.noaliases = false; - ifname_master.optional = false; - - ifname_multi = s2.option(widgets.DeviceSelect, 'ifname_multi', _('Interface')); - ifname_multi.nobridges = true; - ifname_multi.noaliases = true; - ifname_multi.multiple = true; - ifname_multi.optional = true; - ifname_multi.display_size = 6; + device = s2.option(widgets.DeviceSelect, 'device', _('Device')); + device.noaliases = false; + device.optional = false; for (var i = 0; i < protocols.length; i++) { proto.value(protocols[i].getProtocol(), protocols[i].getI18n()); - if (!protocols[i].isVirtual()) { - type.depends({ proto: protocols[i].getProtocol() }); - ifname_single.depends({ type: '', proto: protocols[i].getProtocol() }); - ifname_multi.depends({ type: 'bridge', proto: protocols[i].getProtocol() }); - ifname_master.depends({ type: 'macvlan', proto: protocols[i].getProtocol() }); - } + if (!protocols[i].isVirtual()) + device.depends('proto', protocols[i].getProtocol()); } m2.render().then(L.bind(function(nodes) { @@ -873,7 +1134,7 @@ return view.extend({ 'click': ui.createHandlerFn(this, function(ev) { var nameval = name.isValid('_new_') ? name.formvalue('_new_') : null, protoval = proto.isValid('_new_') ? proto.formvalue('_new_') : null, - protoclass = protoval ? network.getProtocol(protoval) : null; + protoclass = protoval ? network.getProtocol(protoval, nameval) : null; if (nameval == null || protoval == null || nameval == '' || protoval == '') return; @@ -889,22 +1150,11 @@ return view.extend({ return m.save(function() { var section_id = uci.add('network', 'interface', nameval); - uci.set('network', section_id, 'proto', protoval); + protoclass.set('proto', protoval); + protoclass.addDevice(device.formvalue('_new_')); - if (ifname_single.isActive('_new_')) { - uci.set('network', section_id, 'ifname', ifname_single.formvalue('_new_')); - } - else if (ifname_multi.isActive('_new_')) { - uci.set('network', section_id, 'type', 'bridge'); - uci.set('network', section_id, 'ifname', L.toArray(ifname_multi.formvalue('_new_')).join(' ')); - } - else if (ifname_master.isActive('_new_')) { - uci.set('network', section_id, 'type', 'macvlan'); - uci.set('network', section_id, 'ifname', section_id); - uci.set('network', section_id, 'masterintf', L.toArray(ifname_master.formvalue('_new_')).join(' ')); - } + m.children[0].addedSection = section_id; }).then(L.bind(m.children[0].renderMoreOptionsModal, m.children[0], nameval)); - }); }) }, _('Create interface')) @@ -981,11 +1231,218 @@ return view.extend({ }; + // Device configuration + s = m.section(form.GridSection, 'device', _('Devices')); + s.addremove = true; + s.anonymous = true; + s.addbtntitle = _('Add device configuration…'); + + s.cfgsections = function() { + var sections = uci.sections('network', 'device'), + section_ids = sections.sort(function(a, b) { return a.name > b.name }).map(function(s) { return s['.name'] }); + + for (var i = 0; i < netDevs.length; i++) { + if (sections.filter(function(s) { return s.name == netDevs[i].getName() }).length) + continue; + + if (netDevs[i].getType() == 'wifi' && !netDevs[i].isUp()) + continue; + + /* Unless http://lists.openwrt.org/pipermail/openwrt-devel/2020-July/030397.html is implemented, + we cannot properly redefine bridges as devices, so filter them away for now... */ + + var m = netDevs[i].isBridge() ? netDevs[i].getName().match(/^br-([A-Za-z0-9_]+)$/) : null, + s = m ? uci.get('network', m[1]) : null; + + if (s && s['.type'] == 'interface' && s.type == 'bridge') + continue; + + section_ids.push('dev:%s'.format(netDevs[i].getName())); + } + + return section_ids; + }; + + s.renderMoreOptionsModal = function(section_id, ev) { + var m = section_id.match(/^dev:(.+)$/); + + if (m) { + var devtype = getDevType(section_id); + + section_id = uci.add('network', 'device'); + + uci.set('network', section_id, 'name', m[1]); + uci.set('network', section_id, 'type', (devtype != 'ethernet') ? devtype : null); + + this.addedSection = section_id; + } + + return this.super('renderMoreOptionsModal', [section_id, ev]); + }; + + s.renderRowActions = function(section_id) { + var trEl = this.super('renderRowActions', [ section_id, _('Configure…') ]), + deleteBtn = trEl.querySelector('button:last-child'); + + deleteBtn.firstChild.data = _('Reset'); + deleteBtn.setAttribute('title', _('Remove related device settings from the configuration')); + deleteBtn.disabled = section_id.match(/^dev:/) ? true : null; + + return trEl; + }; + + s.modaltitle = function(section_id) { + var m = section_id.match(/^dev:(.+)$/), + name = m ? m[1] : uci.get('network', section_id, 'name'); + + return name ? '%s: %q'.format(getDevTypeDesc(section_id), name) : _('Add device configuration'); + }; + + s.addModalOptions = function(s) { + var isNew = (uci.get('network', s.section, 'name') == null), + dev = getDevice(s.section); + + nettools.addDeviceOptions(s, dev, isNew); + }; + + s.handleModalCancel = function(map /*, ... */) { + var name = uci.get('network', this.addedSection, 'name') + + uci.sections('network', 'bridge-vlan', function(bvs) { + if (name != null && bvs.device == name) + uci.remove('network', bvs['.name']); + }); + + if (map.addedVLANs) + for (var i = 0; i < map.addedVLANs.length; i++) + uci.remove('network', map.addedVLANs[i]); + + return form.GridSection.prototype.handleModalCancel.apply(this, arguments); + }; + + function getDevice(section_id) { + var m = section_id.match(/^dev:(.+)$/), + name = m ? m[1] : uci.get('network', section_id, 'name'); + + return netDevs.filter(function(d) { return d.getName() == name })[0]; + } + + function getDevType(section_id) { + var dev = getDevice(section_id), + cfg = uci.get('network', section_id), + type = cfg ? (uci.get('network', section_id, 'type') || 'ethernet') : (dev ? dev.getType() : ''); + + switch (type) { + case '': + return null; + + case 'vlan': + case '8021q': + return '8021q'; + + case '8021ad': + return '8021ad'; + + case 'bridge': + return 'bridge'; + + case 'tunnel': + return 'tunnel'; + + case 'macvlan': + return 'macvlan'; + + case 'veth': + return 'veth'; + + case 'wifi': + case 'alias': + case 'switch': + case 'ethernet': + default: + return 'ethernet'; + } + } + + function getDevTypeDesc(section_id) { + switch (getDevType(section_id) || '') { + case '': + return E('em', [ _('Device not present') ]); + + case '8021q': + return _('VLAN (802.1q)'); + + case '8021ad': + return _('VLAN (802.1ad)'); + + case 'bridge': + return _('Bridge device'); + + case 'tunnel': + return _('Tunnel device'); + + case 'macvlan': + return _('MAC VLAN'); + + case 'veth': + return _('Virtual Ethernet'); + + default: + return _('Network device'); + } + } + + o = s.option(form.DummyValue, 'name', _('Device')); + o.modalonly = false; + o.textvalue = function(section_id) { + var dev = getDevice(section_id), + ext = section_id.match(/^dev:/), + icon = render_iface(dev); + + if (ext) + icon.querySelector('img').style.opacity = '.5'; + + return E('span', { 'class': 'ifacebadge' }, [ + icon, + E('span', { 'style': ext ? 'opacity:.5' : null }, [ + dev ? dev.getName() : (uci.get('network', section_id, 'name') || '?') + ]) + ]); + }; + + o = s.option(form.DummyValue, 'type', _('Type')); + o.textvalue = getDevTypeDesc; + o.modalonly = false; + + o = s.option(form.DummyValue, 'macaddr', _('MAC Address')); + o.modalonly = false; + o.textvalue = function(section_id) { + var dev = getDevice(section_id), + val = uci.get('network', section_id, 'macaddr'), + mac = dev ? dev.getMAC() : null; + + return val ? E('strong', { + 'data-tooltip': _('The value is overridden by configuration. Original: %s').format(mac || _('unknown')) + }, [ val.toUpperCase() ]) : (mac || '-'); + }; + + o = s.option(form.DummyValue, 'mtu', _('MTU')); + o.modalonly = false; + o.textvalue = function(section_id) { + var dev = getDevice(section_id), + val = uci.get('network', section_id, 'mtu'), + mtu = dev ? dev.getMTU() : null; + + return val ? E('strong', { + 'data-tooltip': _('The value is overridden by configuration. Original: %s').format(mtu || _('unknown')) + }, [ val ]) : (mtu || '-').toString(); + }; + s = m.section(form.TypedSection, 'globals', _('Global network options')); s.addremove = false; s.anonymous = true; - o = s.option(form.Value, 'ula_prefix', _('IPv6 ULA-Prefix')); + o = s.option(form.Value, 'ula_prefix', _('IPv6 ULA-Prefix'), _('Unique Local Address - in the range fc00::/7. Typically only within the ‘local’ half fd00::/8. ULA for IPv6 is analogous to IPv4 private network addressing. This prefix is randomly generated at first install.')); o.datatype = 'cidr6'; o = s.option(form.Flag, 'packet_steering', _('Packet Steering'), _('Enable packet steering across all CPUs. May help or hinder network speed.')); diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js b/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js index b218daac3..7e11a3cb4 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js @@ -20,6 +20,7 @@ return view.extend({ s.anonymous = true; s.addremove = true; s.sortable = true; + s.nodescriptions = true; s.tab('general', _('General Settings')); s.tab('advanced', _('Advanced Settings')); @@ -28,6 +29,10 @@ return view.extend({ o.rmempty = false; o.nocreate = true; + o = s.taboption('general', form.Flag, 'disabled', _('Disable'), _('Disable this route')); + o.rmempty = true; + o.default = o.disabled; + o = s.taboption('general', form.Value, 'target', _('Target'), (i == 4) ? _('Host-IP or Network') : _('IPv6-Address or Network (CIDR)')); o.datatype = (i == 4) ? 'ip4addr' : 'ip6addr'; o.rmempty = false; diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js b/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js index d19b025e3..5115a69eb 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js @@ -199,7 +199,9 @@ function format_wifirate(rate) { var s = '%.1f\xa0%s, %d\xa0%s'.format(rate.rate / 1000, _('Mbit/s'), rate.mhz, _('MHz')), ht = rate.ht, vht = rate.vht, mhz = rate.mhz, nss = rate.nss, - mcs = rate.mcs, sgi = rate.short_gi; + mcs = rate.mcs, sgi = rate.short_gi, + he = rate.he, he_gi = rate.he_gi, + he_dcm = rate.he_dcm; if (ht || vht) { if (vht) s += ', VHT-MCS\xa0%d'.format(mcs); @@ -208,6 +210,13 @@ function format_wifirate(rate) { if (sgi) s += ', ' + _('Short GI').replace(/ /g, '\xa0'); } + if (he) { + s += ', HE-MCS\xa0%d'.format(mcs); + if (nss) s += ', HE-NSS\xa0%d'.format(nss); + if (he_gi) s += ', HE-GI\xa0%d'.format(he_gi); + if (he_dcm) s += ', HE-DCM\xa0%d'.format(he_dcm); + } + return s; } @@ -303,16 +312,32 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.callFrequencyList(section_id) ]).then(L.bind(function(data) { this.channels = { - '11g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], - '11a': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [] + '2g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], + '5g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], + '6g': [], + '60g': [] }; - for (var i = 0; i < data[1].length; i++) - this.channels[(data[1][i].mhz > 2484) ? '11a' : '11g'].push( + for (var i = 0; i < data[1].length; i++) { + var band; + + if (data[1][i].mhz >= 2412 && data[1][i].mhz <= 2484) + band = '2g'; + else if (data[1][i].mhz >= 5160 && data[1][i].mhz <= 5885) + band = '5g'; + else if (data[1][i].mhz >= 5925 && data[1][i].mhz <= 7125) + band = '6g'; + else if (data[1][i].mhz >= 58329 && data[1][i].mhz <= 69120) + band = '60g'; + else + continue; + + this.channels[band].push( data[1][i].channel, '%d (%d Mhz)'.format(data[1][i].channel, data[1][i].mhz), !data[1][i].restricted ); + } var hwmodelist = L.toArray(data[0] ? data[0].getHWModes() : null) .reduce(function(o, v) { o[v] = true; return o }, {}); @@ -320,7 +345,8 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.modes = [ '', 'Legacy', true, 'n', 'N', hwmodelist.n, - 'ac', 'AC', hwmodelist.ac + 'ac', 'AC', hwmodelist.ac, + 'ax', 'AX', hwmodelist.ax ]; var htmodelist = L.toArray(data[0] ? data[0].getHTModes() : null) @@ -337,20 +363,30 @@ var CBIWifiFrequencyValue = form.Value.extend({ 'VHT40', '40 MHz', htmodelist.VHT40, 'VHT80', '80 MHz', htmodelist.VHT80, 'VHT160', '160 MHz', htmodelist.VHT160 + ], + 'ax': [ + 'HE20', '20 MHz', htmodelist.HE20, + 'HE40', '40 MHz', htmodelist.HE40, + 'HE80', '80 MHz', htmodelist.HE80, + 'HE160', '160 MHz', htmodelist.HE160 ] }; this.bands = { '': [ - '11g', '2.4 GHz', this.channels['11g'].length > 3, - '11a', '5 GHz', this.channels['11a'].length > 3 + '2g', '2.4 GHz', this.channels['2g'].length > 3, + '5g', '5 GHz', this.channels['5g'].length > 3 ], 'n': [ - '11g', '2.4 GHz', this.channels['11g'].length > 3, - '11a', '5 GHz', this.channels['11a'].length > 3 + '2g', '2.4 GHz', this.channels['2g'].length > 3, + '5g', '5 GHz', this.channels['5g'].length > 3 ], 'ac': [ - '11a', '5 GHz', true + '5g', '5 GHz', true + ], + 'ax': [ + '2g', '2.4 GHz', this.channels['2g'].length > 3, + '5g', '5 GHz', this.channels['5g'].length > 3 ] }; }, this)); @@ -392,6 +428,8 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.setValues(band, this.bands[mode.value]); this.toggleWifiChannel(elem); + + this.map.checkDepends(); }, toggleWifiChannel: function(elem) { @@ -408,11 +446,14 @@ var CBIWifiFrequencyValue = form.Value.extend({ bwdt = elem.querySelector('.htmode'), htval = uci.get('wireless', section_id, 'htmode'), hwval = uci.get('wireless', section_id, 'hwmode'), - chval = uci.get('wireless', section_id, 'channel'); + chval = uci.get('wireless', section_id, 'channel'), + bandval = uci.get('wireless', section_id, 'band'); this.setValues(mode, this.modes); - if (/VHT20|VHT40|VHT80|VHT160/.test(htval)) + if (/HE20|HE40|HE80|HE160/.test(htval)) + mode.value = 'ax'; + else if (/VHT20|VHT40|VHT80|VHT160/.test(htval)) mode.value = 'ac'; else if (/HT20|HT40/.test(htval)) mode.value = 'n'; @@ -421,15 +462,24 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.toggleWifiMode(elem); - if (/a/.test(hwval)) - band.value = '11a'; - else - band.value = '11g'; + if (hwval != null) { + this.useBandOption = false; + + if (/a/.test(hwval)) + band.value = '5g'; + else + band.value = '2g'; + } + else { + this.useBandOption = true; + + band.value = bandval; + } this.toggleWifiBand(elem); bwdt.value = htval; - chan.value = chval; + chan.value = chval || chan.options[0].value; return elem; }, @@ -461,6 +511,7 @@ var CBIWifiFrequencyValue = form.Value.extend({ E('select', { 'class': 'channel', 'style': 'width:auto', + 'change': L.bind(this.map.checkDepends, this.map), 'disabled': (this.disabled != null) ? this.disabled : this.map.readonly }) ]), @@ -469,6 +520,7 @@ var CBIWifiFrequencyValue = form.Value.extend({ E('select', { 'class': 'htmode', 'style': 'width:auto', + 'change': L.bind(this.map.checkDepends, this.map), 'disabled': (this.disabled != null) ? this.disabled : this.map.readonly }) ]), @@ -481,7 +533,7 @@ var CBIWifiFrequencyValue = form.Value.extend({ cfgvalue: function(section_id) { return [ uci.get('wireless', section_id, 'htmode'), - uci.get('wireless', section_id, 'hwmode'), + uci.get('wireless', section_id, 'hwmode') || uci.get('wireless', section_id, 'band'), uci.get('wireless', section_id, 'channel') ]; }, @@ -498,7 +550,12 @@ var CBIWifiFrequencyValue = form.Value.extend({ write: function(section_id, value) { uci.set('wireless', section_id, 'htmode', value[0] || null); - uci.set('wireless', section_id, 'hwmode', value[1]); + + if (this.useBandOption) + uci.set('wireless', section_id, 'band', value[1]); + else + uci.set('wireless', section_id, 'hwmode', (value[1] == '2g') ? '11g' : '11a'); + uci.set('wireless', section_id, 'channel', value[2]); } }); @@ -883,6 +940,9 @@ return view.extend({ o.ucisection = s.section; if (hwtype == 'mac80211') { + o = ss.taboption('general', form.Flag, 'legacy_rates', _('Allow legacy 802.11b rates'), _('Legacy or badly behaving devices may require legacy 802.11b rates to interoperate. Airtime efficiency may be significantly reduced where these are used. It is recommended to not allow 802.11b rates where possible.')); + o.depends({'_freq': '11g', '!contains': true}); + o = ss.taboption('general', CBIWifiTxPowerValue, 'txpower', _('Maximum transmit power'), _('Specifies the maximum transmit power the wireless radio may use. Depending on regulatory requirements and wireless usage, the actual transmit power may be reduced by the driver.')); o.wifiNetwork = radioNet; @@ -895,9 +955,6 @@ return view.extend({ o.value('2', _('High')); o.value('3', _('Very High')); - o = ss.taboption('advanced', form.Flag, 'legacy_rates', _('Allow legacy 802.11b rates')); - o.default = o.enabled; - o = ss.taboption('advanced', form.Value, 'distance', _('Distance Optimization'), _('Distance to farthest network member in meters.')); o.datatype = 'or(range(0,114750),"auto")'; o.placeholder = 'auto'; @@ -983,8 +1040,17 @@ return view.extend({ return net || network.addNetwork(name, { proto: 'none' }); }, this, values[i])).then(L.bind(function(dev, net) { if (net) { - if (!net.isEmpty()) - net.set('type', 'bridge'); + if (!net.isEmpty()) { + var target_dev = net.getDevice(); + + /* Resolve parent interface of vlan */ + while (target_dev && target_dev.getType() == 'vlan') + target_dev = target_dev.getParent(); + + if (!target_dev || target_dev.getType() != 'bridge') + net.set('type', 'bridge'); + } + net.addDevice(dev); } }, this, dev))); @@ -1014,7 +1080,7 @@ return view.extend({ bssid.depends('mode', 'sta'); bssid.depends('mode', 'sta-wds'); - o = ss.taboption('macfilter', form.ListValue, 'macfilter', _('MAC-Address Filter')); + o = ss.taboption('macfilter', form.ListValue, 'macfilter', _('MAC Address Filter')); o.depends('mode', 'ap'); o.depends('mode', 'ap-wds'); o.value('', _('disable')); @@ -1069,11 +1135,11 @@ return view.extend({ return mode; }; - o = ss.taboption('general', form.Flag, 'hidden', _('Hide ESSID')); + o = ss.taboption('general', form.Flag, 'hidden', _('Hide ESSID'), _('Where the ESSID is hidden, clients may fail to roam and airtime efficiency may be significantly reduced.')); o.depends('mode', 'ap'); o.depends('mode', 'ap-wds'); - o = ss.taboption('general', form.Flag, 'wmm', _('WMM Mode')); + o = ss.taboption('general', form.Flag, 'wmm', _('WMM Mode'), _('Where Wi-Fi Multimedia (WMM) Mode QoS is disabled, clients may be limited to 802.11a/802.11g rates.')); o.depends('mode', 'ap'); o.depends('mode', 'ap-wds'); o.default = o.enabled; @@ -1609,34 +1675,32 @@ return view.extend({ if (hwtype == 'mac80211') { // ieee802.11w options - if (L.hasSystemFeature('hostapd', '11w')) { - o = ss.taboption('encryption', form.ListValue, 'ieee80211w', _('802.11w Management Frame Protection'), _("Requires the 'full' version of wpad/hostapd and support from the wifi driver
    (as of Jan 2019: ath9k, ath10k, mwlwifi and mt76)")); - o.value('', _('Disabled')); - o.value('1', _('Optional')); - o.value('2', _('Required')); - add_dependency_permutations(o, { mode: ['ap', 'ap-wds', 'sta', 'sta-wds'], encryption: ['owe', 'psk2', 'psk-mixed', 'sae', 'sae-mixed', 'wpa2', 'wpa3', 'wpa3-mixed'] }); + o = ss.taboption('encryption', form.ListValue, 'ieee80211w', _('802.11w Management Frame Protection'), _("Note: Some wireless drivers do not fully support 802.11w. E.g. mwlwifi may have problems")); + o.value('', _('Disabled')); + o.value('1', _('Optional')); + o.value('2', _('Required')); + add_dependency_permutations(o, { mode: ['ap', 'ap-wds', 'sta', 'sta-wds'], encryption: ['owe', 'psk2', 'psk-mixed', 'sae', 'sae-mixed', 'wpa2', 'wpa3', 'wpa3-mixed'] }); - o.defaults = { - '2': [{ encryption: 'sae' }, { encryption: 'owe' }, { encryption: 'wpa3' }, { encryption: 'wpa3-mixed' }], - '1': [{ encryption: 'sae-mixed'}], - '': [] - }; - - o = ss.taboption('encryption', form.Value, 'ieee80211w_max_timeout', _('802.11w maximum timeout'), _('802.11w Association SA Query maximum timeout')); - o.depends('ieee80211w', '1'); - o.depends('ieee80211w', '2'); - o.datatype = 'uinteger'; - o.placeholder = '1000'; - o.rmempty = true; - - o = ss.taboption('encryption', form.Value, 'ieee80211w_retry_timeout', _('802.11w retry timeout'), _('802.11w Association SA Query retry timeout')); - o.depends('ieee80211w', '1'); - o.depends('ieee80211w', '2'); - o.datatype = 'uinteger'; - o.placeholder = '201'; - o.rmempty = true; + o.defaults = { + '2': [{ encryption: 'sae' }, { encryption: 'owe' }, { encryption: 'wpa3' }, { encryption: 'wpa3-mixed' }], + '1': [{ encryption: 'sae-mixed'}], + '': [] }; + o = ss.taboption('encryption', form.Value, 'ieee80211w_max_timeout', _('802.11w maximum timeout'), _('802.11w Association SA Query maximum timeout')); + o.depends('ieee80211w', '1'); + o.depends('ieee80211w', '2'); + o.datatype = 'uinteger'; + o.placeholder = '1000'; + o.rmempty = true; + + o = ss.taboption('encryption', form.Value, 'ieee80211w_retry_timeout', _('802.11w retry timeout'), _('802.11w Association SA Query retry timeout')); + o.depends('ieee80211w', '1'); + o.depends('ieee80211w', '2'); + o.datatype = 'uinteger'; + o.placeholder = '201'; + o.rmempty = true; + o = ss.taboption('encryption', form.Flag, 'wpa_disable_eapol_key_retries', _('Enable key reinstallation (KRACK) countermeasures'), _('Complicates key reinstallation attacks on the client side by disabling retransmission of EAPOL-Key frames that are used to install keys. This workaround might cause interoperability issues and reduced robustness of key negotiation especially in environments with heavy traffic load.')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['psk2', 'psk-mixed', 'sae', 'sae-mixed', 'wpa2', 'wpa3', 'wpa3-mixed'] }); @@ -2082,7 +2146,7 @@ return view.extend({ var table = E('table', { 'class': 'table assoclist', 'id': 'wifi_assoclist_table' }, [ E('tr', { 'class': 'tr table-titles' }, [ E('th', { 'class': 'th nowrap' }, _('Network')), - E('th', { 'class': 'th hide-xs' }, _('MAC-Address')), + E('th', { 'class': 'th hide-xs' }, _('MAC address')), E('th', { 'class': 'th' }, _('Host')), E('th', { 'class': 'th' }, _('Signal / Noise')), E('th', { 'class': 'th' }, _('RX Rate / TX Rate')) diff --git a/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json b/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json index d6c84bab2..6943d9563 100644 --- a/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json +++ b/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json @@ -4,7 +4,11 @@ "read": { "cgi-io": [ "exec" ], "file": { - "/usr/libexec/luci-peeraddr": [ "exec" ] + "/etc/iproute2/rt_tables": [ "read" ], + "/proc/sys/net/ipv6/conf/*/mtu": [ "read" ], + "/proc/sys/net/ipv6/conf/*/hop_limit": [ "read" ], + "/usr/libexec/luci-peeraddr": [ "exec" ], + "/usr/lib/opkg/info/netifd.control": [ "read" ] }, "ubus": { "file": [ "exec" ], From b7db6b215f9f2e86ebfd9764ffdaeb84b4b908bf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Jun 2021 19:45:45 +0200 Subject: [PATCH 0527/2059] Update mlvpn config file to use device setting --- mlvpn/files/etc/uci-defaults/4100-mlvpn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlvpn/files/etc/uci-defaults/4100-mlvpn b/mlvpn/files/etc/uci-defaults/4100-mlvpn index 45d4f57ee..8aa0a6139 100644 --- a/mlvpn/files/etc/uci-defaults/4100-mlvpn +++ b/mlvpn/files/etc/uci-defaults/4100-mlvpn @@ -11,7 +11,7 @@ if [ "$(uci -q get network.omrvpn)" = "" ] && [ "$(uci -q get network.mlvpn)" = uci -q batch <<-EOF >/dev/null delete network.mlvpn=interface set network.mlvpn=interface - set network.mlvpn.ifname=mlvpn0 + set network.mlvpn.device=mlvpn0 set network.mlvpn.proto=dhcp set network.mlvpn.ip4table=vpn set network.mlvpn.multipath=off From a65e032215fd02d93db33db1db74e8075c2c32be Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Jun 2021 19:46:51 +0200 Subject: [PATCH 0528/2059] Update MPTCP init and interface tracking for device setting --- mptcp/files/etc/init.d/mptcp | 6 +++-- .../share/omr/post-tracking.d/post-tracking | 27 ++++++++++++++----- omr-tracker/files/bin/omr-tracker-gre | 3 ++- omr-tracker/files/etc/init.d/omr-tracker | 2 +- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 334cc0632..432268ff2 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -85,7 +85,8 @@ interface_multipath_settings() { local enabled config_get enabled "$config" auto "1" - config_get iface "$config" ifname + config_get iface "$config" device + [ -z "$iface" ] && config_get iface "$config" ifname config_get txqueuelen "$config" txqueuelen [ -z "$iface" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["device"]') @@ -349,7 +350,8 @@ interface_multipath_settings() { } load_interfaces() { - config_get ifname "$1" ifname + config_get ifname "$1" device + [ -z "$ifname" ] && config_get ifname "$1" ifname config_get multipath "$1" multipath "" [ -z "$multipath" ] && multipath="$(uci -q get openmptcprouter.$1.multipath)" [ "$multipath" != "off" ] && [ "$multipath" != "" ] && interfaces=" ${ifname} ${interfaces}" diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index c764e794d..e26091d45 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -15,6 +15,7 @@ set_route() { interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "${INTERFACE}" | jsonfilter -q -e '@["device"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") @@ -52,6 +53,7 @@ set_route6() { interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") @@ -165,6 +167,7 @@ set_routes_intf() { } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && ifname=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') @@ -219,6 +222,7 @@ set_routes_intf6() { } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') @@ -289,6 +293,7 @@ set_route_balancing() { } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') @@ -337,6 +342,7 @@ set_route_balancing6() { } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') @@ -398,10 +404,11 @@ set_server_all_routes() { [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') @@ -443,10 +450,11 @@ set_server_all_routes6() { [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { @@ -497,10 +505,11 @@ set_server_route() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" } - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep "deactivated") interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") @@ -532,10 +541,11 @@ set_server_route6() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" } - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) + interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep "deactivated") interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") @@ -895,7 +905,8 @@ multipath_config=$(uci -q get "openmtpcprouter.$OMR_TRACKER_INTERFACE.multipath" if [ "$multipath_config" = "master" ]; then #if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && ([ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ] || [ "$(uci -q get openmptcprouter.settings.vpn)" = "mlvpn" ]); then if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then - omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") + omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun") + [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null @@ -908,7 +919,8 @@ if [ "$multipath_config" = "master" ]; then fi fi if ([ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$default_gw6" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then - omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") + omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun") + [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" ip -6 route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null @@ -923,7 +935,8 @@ if [ "$multipath_config" = "master" ]; then fi #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then - omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") + omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun") + [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then routesbalancing="" routesbalancingbackup="" diff --git a/omr-tracker/files/bin/omr-tracker-gre b/omr-tracker/files/bin/omr-tracker-gre index 5c19e43cc..78fa1aef0 100755 --- a/omr-tracker/files/bin/omr-tracker-gre +++ b/omr-tracker/files/bin/omr-tracker-gre @@ -23,7 +23,8 @@ _ping_server() { _ping_tunnel() { local name=$1 config_get gateway $1 gateway - config_get ifname $1 ifname + config_get ifname $1 device + [ -z "$ifname" ] && config_get ifname $1 ifname config_get disabled $1 disabled [ "$(echo $ifname | grep oip)" != "" ] && [ -n "$gateway" ] && [ "$disabled" != "1" ] && { _ping_server $gateway diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 3276316e9..7a09ef82d 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -55,7 +55,7 @@ _launch_tracker() { local ifname ip4table ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -z "$ifname" ] && ifname=$(ifstatus "$1_4" | jsonfilter -q -e '@["l3_device"]') - [ -z "$ifname" ] && config_get ifname "$1" ifname + [ -z "$ifname" ] && config_get ifname "$1" device [ -n "$(echo $ifname | grep '@')" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') config_get multipath "$1" multipath From c5945ec6836331d5feba5ff77df682a7c037a94f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Jun 2021 19:47:18 +0200 Subject: [PATCH 0529/2059] Remove the need of macvlan package --- openmptcprouter-full/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 31282b251..4432da893 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -44,7 +44,6 @@ MY_DEPENDS := \ luci-app-uhttpd \ luci-mod-rpc rpcd-mod-rpcsys rpcd-mod-file rpcd-mod-iwinfo \ luci-app-openvpn \ - macvlan \ shadowsocks-libev-ss-server shadowsocks-libev-ss-tunnel \ omr-6in4 ip6tables-mod-nat luci-proto-ipv6 6to4 6in4 6rd ip6tables \ speedtestc \ From ea3a4840c4194303e68d00f2e030c36262c3b5d4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Jun 2021 19:48:43 +0200 Subject: [PATCH 0530/2059] Update openmptcprouter script and config to use device setting instead of ifname --- openmptcprouter/files/etc/init.d/mptcpovervpn | 2 +- .../files/etc/init.d/openmptcprouter-vps | 6 ++-- .../files/etc/init.d/openvpnbonding | 2 +- .../files/etc/uci-defaults/1920-omr-network | 36 ++++++++++--------- .../files/etc/uci-defaults/1970-omr-vnstat | 8 ++--- .../files/etc/uci-defaults/2020-omr-vpn | 2 +- .../files/etc/uci-defaults/2040-omr-sqm | 8 ++--- 7 files changed, 33 insertions(+), 31 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index b36425041..0bb30c0dd 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -68,7 +68,7 @@ mptcp_over_vpn() { uci -q batch <<-EOF >/dev/null set network.ovpn${interface}=interface - set network.ovpn${interface}.ifname="tun${id}" + set network.ovpn${interface}.device="tun${id}" set network.ovpn${interface}.defaultroute='0' set network.ovpn${interface}.peerdns='0' set network.ovpn${interface}.proto='none' diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 73eb6d623..71350104c 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -539,7 +539,7 @@ _get_gre_tunnel() { set network.oip${i}.label="Tunnel for $publicaddr" set network.oip${i}.proto=static set network.oip${i}.nohostroute='1' - set network.oip${i}.ifname="@oip${i}gre" + set network.oip${i}.device="@oip${i}gre" set network.oip${i}.ipv6='0' set network.oip${i}.defaultroute='0' set network.oip${i}.multipath='off' @@ -823,7 +823,7 @@ _set_vpn_ip() { local settings [ -z "$vps_config" ] && vps_config=$(_get_json "config") [ -z "$vps_config" ] && return - vpnifname="$(uci -q get network.omrvpn.ifname)" + vpnifname="$(uci -q get network.omrvpn.device)" vpnip_local_current="$(echo "$vps_config" | jsonfilter -q -e '@.vpn.remoteip')" vpnip_local=$(ip -4 -br addr ls dev ${vpnifname} | awk -F'[ /]+' '{print $3}') vpnip_remote_current="$(echo "$vps_config" | jsonfilter -q -e '@.vpn.localip')" @@ -850,7 +850,7 @@ _set_client2client() { [ -z "$vps_config" ] && vps_config=$(_get_json "config") [ -z "$vps_config" ] && return c2cips="$(echo "$vps_config" | jsonfilter -q -e '@.client2client.lanips[0]')" - vpnifname="$(uci -q get network.omrvpn.ifname)" + vpnifname="$(uci -q get network.omrvpn.device)" vpnip_local=$(ip -4 -br addr ls dev ${vpnifname} | awk -F'[ /]+' '{print $3}' | tr -d "\n") vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep via | grep -v default | grep -v / | grep -v metric | awk '{print $1}' | tr -d "\n") for lanip in $c2cips; do diff --git a/openmptcprouter/files/etc/init.d/openvpnbonding b/openmptcprouter/files/etc/init.d/openvpnbonding index adad30b5b..f3c085802 100755 --- a/openmptcprouter/files/etc/init.d/openvpnbonding +++ b/openmptcprouter/files/etc/init.d/openvpnbonding @@ -77,7 +77,7 @@ start_service() set network.omrvpn.updelay='20' set network.omrvpn.use_carrier='1' set network.omrvpn.mtu='1440' - set network.omrvpn.ifname= 'bonding-omrvpn' + set network.omrvpn.device= 'bonding-omrvpn' set network.omrvpn.force_link='1' commit network EOF diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 4a4710df9..fca553290 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -11,7 +11,7 @@ _setup_macvlan() { # do not create macvlan for vlan local _ifname - _ifname=$(uci -q get "network.$1.ifname") + _ifname=$(uci -q get "network.$1.device") case "$_ifname" in eth*.*) return ;; esac @@ -21,26 +21,24 @@ _setup_macvlan() { set network.$1_dev.name=$1 set network.$1_dev.type=macvlan set network.$1_dev.ifname=$_ifname - set network.$1.ifname=$1 + set network.$1_dev.mode='vepa' + set network.$1.device=$1 set network.$1.type=macvlan set network.$1.masterintf=$_ifname - set macvlan.$1=macvlan - set macvlan.$1.name=$1 - set macvlan.$1.ifname=$_ifname EOF _macaddr=$(uci -q get "network.$1.macaddr") _setup_macaddr "$1_dev" "${_macaddr:-auto$(date +%s)}" } -_setup_macvlan_update() { - uci -q get "network.$1_dev.ifname" >/dev/null || return - - uci -q batch <<-EOF - set macvlan.$1=macvlan - set macvlan.$1.ifname=$_ifname - commit macvlan - EOF -} +#_setup_macvlan_update() { +# uci -q get "network.$1_dev.device" >/dev/null || return +# +# uci -q batch <<-EOF +# set macvlan.$1=macvlan +# set macvlan.$1.device=$_ifname +# commit macvlan +# EOF +#} _setup_mptcp_handover_to_on() { if [ "$(uci -q get network.$1.multipath)" = "handover" ]; then @@ -59,7 +57,7 @@ _setup_multipath_off() { _setup_wan_interface() { uci -q batch <<-EOF set network.$1=interface - set network.$1.ifname=$2 + set network.$1.device=$2 set network.$1.proto=static set network.$1.ip4table=wan set network.$1.multipath=$3 @@ -72,7 +70,7 @@ _setup_wan_interface() { } config_load network -config_foreach _setup_macvlan_update interface +#config_foreach _setup_macvlan_update interface config_foreach _setup_mptcp_handover_to_on interface if [ "$(uci -q show network.lan | grep multipath)" != "" ]; then @@ -128,7 +126,7 @@ set network.lan=interface set network.lan.proto=static set network.lan.ipaddr=192.168.100.1 set network.lan.netmask=255.255.255.0 -set network.lan.ifname=${lanif} +set network.lan.device=${lanif} set network.lan.metric=2048 set network.lan.ipv6=0 set network.lan.delegate=0 @@ -295,6 +293,10 @@ fi # Replace omrip to oip in config for old config sed -i 's/omrip/oip/g' /etc/config/* +# Fix config from ifname to device for loopback +uci -q delete network.loopback.ifname +uci -q set network.loopback.device='lo' + uci -q commit macvlan uci -q commit network rm -f /tmp/luci-indexcache diff --git a/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat b/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat index 2cef43a28..749b10680 100755 --- a/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat +++ b/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat @@ -1,24 +1,24 @@ #!/bin/sh if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then - wanintf="$(uci -q get network.wan1.ifname)" + wanintf="$(uci -q get network.wan1.device)" if [ "$(uci -q get vnstat.@vnstat[-1].interface | grep $wanintf)" = "" ]; then uci -q batch <<-EOF >/dev/null delete vnstat.@vnstat[-1] add vnstat vnstat set vnstat.@vnstat[-1].interface=$wanintf EOF - wanintf="$(uci -q get network.wan2.ifname)" + wanintf="$(uci -q get network.wan2.device)" uci -q batch <<-EOF >/dev/null add_list vnstat.@vnstat[-1].interface=$wanintf EOF if [ "$(uci -q get network.wan3)" != "" ]; then - wanintf="$(uci -q get network.wan3.ifname)" + wanintf="$(uci -q get network.wan3.device)" uci -q batch <<-EOF >/dev/null add_list vnstat.@vnstat[-1].interface=$wanintf EOF fi if [ "$(uci -q get network.wan4)" != "" ]; then - wanintf="$(uci -q get network.wan4.ifname)" + wanintf="$(uci -q get network.wan4.device)" uci -q batch <<-EOF >/dev/null add_list vnstat.@vnstat[-1].interface=$wanintf EOF diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index d1f5d8b86..4cb5a524c 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -5,7 +5,7 @@ if [ "$(uci -q get network.omrvpn)" = "" ]; then delete network.glorytun delete network.omrvpn set network.omrvpn=interface - set network.omrvpn.ifname=tun0 + set network.omrvpn.device=tun0 set network.omrvpn.proto=dhcp set network.omrvpn.ip4table=vpn set network.omrvpn.multipath=off diff --git a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm index d8c232752..030400bb9 100755 --- a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm +++ b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm @@ -1,8 +1,8 @@ #!/bin/sh if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then if [ "$(uci -q get sqm.wan1)" = "" ]; then - wan1="$(uci -q get network.wan1.ifname)" - wan2="$(uci -q get network.wan2.ifname)" + wan1="$(uci -q get network.wan1.device)" + wan2="$(uci -q get network.wan2.device)" uci -q batch <<-EOF >/dev/null delete sqm.eth1 set sqm.wan1=queue @@ -34,7 +34,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then commit sqm EOF if [ "$(uci -q get network.wan3)" != "" ]; then - wan3="$(uci -q get network.wan3.ifname)" + wan3="$(uci -q get network.wan3.device)" uci -q batch <<-EOF >/dev/null set sqm.wan3=queue set sqm.wan3.qdisc="fq_codel" @@ -53,7 +53,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then EOF fi if [ "$(uci -q get network.wan4)" != "" ]; then - wan4="$(uci -q get network.wan4.ifname)" + wan4="$(uci -q get network.wan4.device)" uci -q batch <<-EOF >/dev/null set sqm.wan4=queue set sqm.wan4.qdisc="fq_codel" From 2a6d5b341caee2738d882a94bdf2252c6119899f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 26 Jun 2021 08:15:14 +0200 Subject: [PATCH 0531/2059] Fix some firewall warnings --- luci-app-glorytun-tcp/root/etc/uci-defaults/1200-luci-glorytun | 1 + openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/luci-app-glorytun-tcp/root/etc/uci-defaults/1200-luci-glorytun b/luci-app-glorytun-tcp/root/etc/uci-defaults/1200-luci-glorytun index a15f491be..e78973fe0 100644 --- a/luci-app-glorytun-tcp/root/etc/uci-defaults/1200-luci-glorytun +++ b/luci-app-glorytun-tcp/root/etc/uci-defaults/1200-luci-glorytun @@ -48,6 +48,7 @@ if [ "$(uci -q show firewall | grep Allow-All-LAN-to-VPN)" = "" ]; then set firewall.@rule[-1].name='Allow-All-LAN-to-VPN' set firewall.@rule[-1].dest='vpn' set firewall.@rule[-1].src='lan' + set firewall.@rule[-1].proto='all' commit firewall EOF fi diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 133e1d293..b31b5dbb9 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -45,7 +45,7 @@ if [ "$(uci -q get firewall.zone_vpn)" = "" ]; then uci -q batch <<-EOF >/dev/null set firewall.zone_vpn=zone set firewall.zone_vpn.name=vpn - set firewall.zone_vpn.network=glorytun + set firewall.zone_vpn.network=omrvpn set firewall.zone_vpn.masq=1 set firewall.zone_vpn.input=REJECT set firewall.zone_vpn.forward=ACCEPT @@ -98,6 +98,7 @@ if [ "$(uci -q show firewall | grep Allow-Lan-to-Wan)" = "" ]; then set firewall.@rule[-1].name='Allow-Lan-to-Wan' set firewall.@rule[-1].dest='wan' set firewall.@rule[-1].src='lan' + set firewall.@rule[-1].proto='all' commit firewall EOF fi From 0383e51b2981ce0598a72cbb81b63fa3ffe3ef95 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 26 Jun 2021 08:26:01 +0200 Subject: [PATCH 0532/2059] Fix typo --- .../htdocs/luci-static/resources/view/network/interfaces.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js index 6f0b2ec96..ff179d404 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js @@ -942,14 +942,14 @@ return view.extend({ o.datatype = 'uinteger'; o.placeholder = '0'; - o = nettools.replaceOptions(s,'advanced', form.ListValue, 'multipath', _('Multipath setting'), _('Only one interface must be set as Master.')); + o = nettools.replaceOption(s,'advanced', form.ListValue, 'multipath', _('Multipath setting'), _('Only one interface must be set as Master.')); o.value('on',_('Enabled')); o.value('off',_('Disabled')); o.value('master',_('Master')); o.value('backup',_('Backup')); o.default = 'off'; - o = nettools.replaceOptions(s,'advanced', form.Value, 'addlatency', _('Additional latency')); + o = nettools.replaceOption(s,'advanced', form.Value, 'addlatency', _('Additional latency')); o.datatype = 'uinteger'; o.default = '0'; From 65dc14592d48af3b3e9c19e5bf49cf51dbf9b6fd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 27 Jun 2021 19:44:17 +0200 Subject: [PATCH 0533/2059] Use device instead of ifname for mptcp --- luci-app-mptcp/luasrc/controller/mptcp.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index 249179514..33f39fcc6 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -63,7 +63,10 @@ function multipath_bandwidth() local label = s["label"] local dev = get_device(intname) if dev == "" then - dev = get_device(s["ifname"]) + dev = get_device(s["device"]) + if dev == "" then + dev = get_device(s["ifname"]) + end end local multipath = s["multipath"] or "" if dev ~= "lo" and dev ~= "" then From 7e183cfc07a0d4c17b20d75eb8990ba8769b6c40 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 28 Jun 2021 19:29:07 +0200 Subject: [PATCH 0534/2059] Remove modemmanger custom release --- luci-proto-modemmanager/Makefile | 15 --- .../resources/protocol/modemmanager.js | 121 ------------------ .../rpcd/acl.d/luci-proto-modemmanager.json | 12 -- 3 files changed, 148 deletions(-) delete mode 100644 luci-proto-modemmanager/Makefile delete mode 100644 luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js delete mode 100644 luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json diff --git a/luci-proto-modemmanager/Makefile b/luci-proto-modemmanager/Makefile deleted file mode 100644 index 8d968ff7e..000000000 --- a/luci-proto-modemmanager/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (C) 2008-2014 The LuCI Team -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Support for ModemManager -LUCI_DEPENDS:=+modemmanager -PKG_VERSION:=omr-202103 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js b/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js deleted file mode 100644 index 33cf6dce4..000000000 --- a/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js +++ /dev/null @@ -1,121 +0,0 @@ -'use strict'; -'require fs'; -'require form'; -'require network'; - -function getModemList() { - return fs.exec_direct('/usr/bin/mmcli', [ '-L' ]).then(function(res) { - var lines = (res || '').split(/\n/), - tasks = []; - - for (var i = 0; i < lines.length; i++) { - var m = lines[i].match(/\/Modem\/(\d+)/); - if (m) - tasks.push(fs.exec_direct('/usr/bin/mmcli', [ '-m', m[1] ])); - } - - return Promise.all(tasks).then(function(res) { - var modems = []; - - for (var i = 0; i < res.length; i++) { - var man = res[i].match(/manufacturer: ([^\n]+)/), - mod = res[i].match(/model: ([^\n]+)/), - dev = res[i].match(/device: ([^\n]+)/); - - if (dev) { - modems.push({ - device: dev[1].trim(), - manufacturer: (man ? man[1].trim() : '') || '?', - model: (mod ? mod[1].trim() : '') || dev[1].trim() - }); - } - } - - return modems; - }); - }); -} - -network.registerPatternVirtual(/^mobiledata-.+$/); -network.registerErrorCode('CALL_FAILED', _('Call failed')); -network.registerErrorCode('NO_CID', _('Unable to obtain client ID')); -network.registerErrorCode('PLMN_FAILED', _('Setting PLMN failed')); - -return network.registerProtocol('modemmanager', { - getI18n: function() { - return _('ModemManager'); - }, - - getIfname: function() { - return this._ubus('l3_device') || 'modemmanager-%s'.format(this.sid); - }, - - getOpkgPackage: function() { - return 'modemmanager'; - }, - - isFloating: function() { - return true; - }, - - isVirtual: function() { - return true; - }, - - getDevices: function() { - return null; - }, - - containsDevice: function(ifname) { - return (network.getIfnameOf(ifname) == this.getIfname()); - }, - - renderFormOptions: function(s) { - var dev = this.getL3Device() || this.getDevice(), o; - - o = s.taboption('general', form.ListValue, 'device', _('Modem device')); - o.rmempty = false; - o.load = function(section_id) { - return getModemList().then(L.bind(function(devices) { - for (var i = 0; i < devices.length; i++) - this.value(devices[i].device, - '%s - %s (%s)'.format(devices[i].manufacturer, devices[i].model, devices[i].device)); - return form.Value.prototype.load.apply(this, [section_id]); - }, this)); - }; - - s.taboption('general', form.Value, 'apn', _('APN')); - s.taboption('general', form.Value, 'pincode', _('PIN')); - - o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type')); - o.value('both', _('PAP/CHAP (both)')); - o.value('pap', 'PAP'); - o.value('chap', 'CHAP'); - o.value('none', _('None')); - o.default = 'none'; - - o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username')); - o.depends('auth', 'pap'); - o.depends('auth', 'chap'); - o.depends('auth', 'both'); - - o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password')); - o.depends('auth', 'pap'); - o.depends('auth', 'chap'); - o.depends('auth', 'both'); - o.password = true; - - o = s.taboption('general', form.ListValue, 'iptype', _('IP Type')); - o.value('ipv4v6', _('IPv4/IPv6 (both - defaults to IPv4)')) - o.value('ipv4', _('IPv4 only')); - o.value('ipv6', _('IPv6 only')); - o.default = 'ipv4v6'; - - o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU')); - o.placeholder = dev ? (dev.getMTU() || '1500') : '1500'; - o.datatype = 'max(9200)'; - - s.taboption('general', form.Value, 'metric', _('Gateway metric')); - - } -}); diff --git a/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json b/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json deleted file mode 100644 index 716f4c465..000000000 --- a/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "luci-proto-modemmanager": { - "description": "Grant access to mmcli", - "read": { - "cgi-io": [ "exec" ], - "file": { - "/usr/bin/mmcli -L": [ "exec" ], - "/usr/bin/mmcli -m [0-9]": [ "exec" ] - } - } - } -} From ec6cdb8209bb17dacc745f757c6f4cbdd430a354 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 28 Jun 2021 19:32:36 +0200 Subject: [PATCH 0535/2059] Fix modem device --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 42ed7d1b9..351cac58b 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -20,7 +20,7 @@ omr_intf_set() { local ifname config_get ifname "$1" device [ -z "$ifname" ] && config_get ifname "$1" ifname - config_get device "$1" device + config_get devicename "$1" _modem_device config_get type "$1" type [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') @@ -39,7 +39,7 @@ omr_intf_set() { uci -q delete network.$1.modalias uci -q delete network.$1.product fi - elif [ "$type" != "macvlan" ] && [ -n "$device" ] && [ -f /sys/bus/usb-serial/devices/${devicename}/device/uevent ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" != "" ]; then + elif [ "$type" != "macvlan" ] && [ -n "$devicename" ] && [ -f /sys/bus/usb-serial/devices/${devicename}/device/uevent ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" != "" ]; then mac="" if [ -f /sys/class/net/${ifname}/address ]; then mac="$(cat /sys/class/net/${ifname}/address | tr -d '\n')" From 18a6613650f9237b17a54c126f0e92af794024da Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 4 Jul 2021 07:20:55 +0200 Subject: [PATCH 0536/2059] Use network_get_device to get device --- .../root/etc/init.d/omr-bypass | 4 +- .../root/etc/init.d/openmptcprouter | 16 ++++-- mptcp/files/etc/init.d/mptcp | 8 ++- .../share/omr/post-tracking.d/post-tracking | 52 +++++++++++++------ omr-tracker/files/etc/init.d/omr-tracker | 10 +++- 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 2b8f56972..70eda0529 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -501,9 +501,9 @@ _intf_rule_v2ray_rules() { _intf_rule() { local intf - config_get intf $1 ifname - [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') + [ -z "$intf" ] && config_get intf $1 device #count=$((count+1)) config_get count $1 metric local mode diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 351cac58b..87b908344 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -6,6 +6,8 @@ START=5 USE_PROCD=1 +. /lib/functions/network.sh + omr_intf_del() { [ -z "$1" ] && return uci -q delete openmptcprouter.$1 @@ -18,12 +20,14 @@ omr_intf_check() { omr_intf_set() { local device local ifname - config_get ifname "$1" device + network_get_device ifname $1 + [ -z "$ifname" ] && network_get_physdev ifname $1 + [ -z "$ifname" ] && config_get ifname "$1" device [ -z "$ifname" ] && config_get ifname "$1" ifname - config_get devicename "$1" _modem_device - config_get type "$1" type - [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + #config_get devicename "$1" _modem_device + devicename=${ifname} + config_get type "$1" type if [ "$type" != "macvlan" ] && [ -n "$ifname" ] && [ -f /sys/class/net/${ifname}/device/uevent ]; then devicepath=$(readlink -f /sys/class/net/${ifname}) @@ -57,7 +61,9 @@ omr_set_settings() { local ifname local multipath config_get multipath "$1" multipath - config_get ifname "$1" device + network_get_device ifname $1 + [ -z "$ifname" ] && network_get_physdev ifname $1 + [ -z "$ifname" ] && config_get ifname "$1" device [ -z "$ifname" ] && config_get ifname "$1" ifname config_get device "$1" device config_get proto "$1" proto diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 432268ff2..8936596a0 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -85,7 +85,9 @@ interface_multipath_settings() { local enabled config_get enabled "$config" auto "1" - config_get iface "$config" device + network_get_device iface $config + [ -z "$iface" ] && network_get_physdev iface $config + [ -z "$iface" ] && config_get iface "$config" device [ -z "$iface" ] && config_get iface "$config" ifname config_get txqueuelen "$config" txqueuelen [ -z "$iface" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') @@ -350,7 +352,9 @@ interface_multipath_settings() { } load_interfaces() { - config_get ifname "$1" device + network_get_device ifname $1 + [ -z "$ifname" ] && network_get_physdev ifname $1 + [ -z "$ifname" ] && config_get ifname "$1" device [ -z "$ifname" ] && config_get ifname "$1" ifname config_get multipath "$1" multipath "" [ -z "$multipath" ] && multipath="$(uci -q get openmptcprouter.$1.multipath)" diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index e26091d45..a637c43d7 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1,5 +1,7 @@ SETROUTE=false +. /lib/functions/network.sh + set_route() { local multipath_config_route interface_gw interface_if INTERFACE=$1 @@ -12,8 +14,9 @@ set_route() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" } - interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + network_get_device interface_if $INTERFACE interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -50,8 +53,9 @@ set_route6() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" } - interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + network_get_device interface_if $INTERFACE interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + [ -z "$interface_if" ] && interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -165,7 +169,8 @@ set_routes_intf() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" } - interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + network_get_device interface_if $INTERFACE + [ -z "$interface_if" ] && interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -220,7 +225,8 @@ set_routes_intf6() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" } - interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + network_get_device interface_if $INTERFACE + [ -z "$interface_if" ] && interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -291,7 +297,8 @@ set_route_balancing() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" } - interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + network_get_device interface_if $INTERFACE + [ -z "$interface_if" ] && interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -340,7 +347,8 @@ set_route_balancing6() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" } - interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') + network_get_device interface_if $INTERFACE + [ -z "$interface_if" ] && interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -404,7 +412,8 @@ set_server_all_routes() { [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) + network_get_device interface_if $OMR_TRACKER_INTERFACE + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') @@ -450,7 +459,8 @@ set_server_all_routes6() { [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) + network_get_device interface_if $OMR_TRACKER_INTERFACE + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') @@ -505,7 +515,8 @@ set_server_route() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" } - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) + network_get_device interface_if $OMR_TRACKER_INTERFACE + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') @@ -541,7 +552,8 @@ set_server_route6() { [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" } - interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) + network_get_device interface_if $OMR_TRACKER_INTERFACE + [ -z "$interface_if" ] && interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.device) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') @@ -660,7 +672,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then sleep 5 _log "Set $OMR_TRACKER_INTERFACE up" ifup $OMR_TRACKER_INTERFACE - sleep 10 + sleep 20 fi if [ "$OMR_TRACKER_PREV_STATUS" = "$OMR_TRACKER_STATUS" ]; then @@ -905,8 +917,8 @@ multipath_config=$(uci -q get "openmtpcprouter.$OMR_TRACKER_INTERFACE.multipath" if [ "$multipath_config" = "master" ]; then #if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && ([ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ] || [ "$(uci -q get openmptcprouter.settings.vpn)" = "mlvpn" ]); then if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then - omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun") - [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") + omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") + [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null @@ -919,8 +931,8 @@ if [ "$multipath_config" = "master" ]; then fi fi if ([ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$default_gw6" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then - omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun") - [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") + omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") + [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" ip -6 route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null @@ -935,8 +947,8 @@ if [ "$multipath_config" = "master" ]; then fi #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then - omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun") - [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun") + omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") + [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then routesbalancing="" routesbalancingbackup="" @@ -1408,6 +1420,12 @@ if [ "$(pgrep rpcd)" = "" ] && [ -f /etc/init.d/rpcd ]; then sleep 5 fi +if [ "$(pgrep uhttpd)" = "" ] && [ -f /etc/init.d/uhttpd ]; then + _log "Can't find uhttpd, restart it..." + /etc/init.d/uhttpd restart + sleep 5 +fi + #if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ] && [ "$(uci -q get openmptcprouter.settings.modemmanager)" != "0" ]; then # _log "Can't find ModemManager, restart it..." # /etc/init.d/modemmanager restart diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 7a09ef82d..479ce2d5e 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -1,7 +1,7 @@ #!/bin/sh /etc/rc.common # shellcheck disable=SC2039 # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : -# Copyright (C) 2018 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) # Released under GPL 3. See LICENSE for the full terms. # shellcheck disable=SC2034 @@ -12,6 +12,7 @@ } . /usr/lib/unbound/iptools.sh +. /lib/functions/network.sh _validate_section() { local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_tries=$tries @@ -53,7 +54,9 @@ _launch_tracker() { _validate_section "interface" "$1" local ifname ip4table - ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + network_get_device ifname $1 + [ -z "$ifname" ] && network_get_physdev ifname $1 + [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -z "$ifname" ] && ifname=$(ifstatus "$1_4" | jsonfilter -q -e '@["l3_device"]') [ -z "$ifname" ] && config_get ifname "$1" device [ -n "$(echo $ifname | grep '@')" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') @@ -69,6 +72,9 @@ _launch_tracker() { [ "${ifenabled}" = "0" ] && return [ "${enabled}" = "0" ] && return [ -z "${hosts}" ] && [ "$type" != "none" ] && return + ifstatus=$(ifstatus "$1" | jsonfilter -q -e '@["up"]') + ifdevice=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') + [ "${ifstatus}" = "false" ] && [ -z "${ifdevice}" ] && return [ -z "${interval_tries}" ] && interval_tries=1 procd_open_instance From c40aad6baf211e57b33c9dc30bbc78f4c1f42f77 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 4 Jul 2021 07:21:22 +0200 Subject: [PATCH 0537/2059] Add omr6in4 in vpn firewall zone --- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index b31b5dbb9..9fb334602 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -45,7 +45,8 @@ if [ "$(uci -q get firewall.zone_vpn)" = "" ]; then uci -q batch <<-EOF >/dev/null set firewall.zone_vpn=zone set firewall.zone_vpn.name=vpn - set firewall.zone_vpn.network=omrvpn + add_list firewall.zone_vpn.network=omrvpn + add_list firewall.zone_vpn.network=omr6in4 set firewall.zone_vpn.masq=1 set firewall.zone_vpn.input=REJECT set firewall.zone_vpn.forward=ACCEPT From a275eedf452c9818f79816a1463433f50eca3263 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Jul 2021 12:14:09 +0200 Subject: [PATCH 0538/2059] Update mptcpd --- libell/Makefile | 6 +- mptcpd/Makefile | 11 ++- mptcpd/patches/log.patch | 24 ----- mptcpd/patches/remove_log.patch | 167 ++++++++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 31 deletions(-) delete mode 100644 mptcpd/patches/log.patch create mode 100644 mptcpd/patches/remove_log.patch diff --git a/libell/Makefile b/libell/Makefile index 99ac29e1f..8b12f4b51 100644 --- a/libell/Makefile +++ b/libell/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2020 Ycarus (Yannick Chabanois) +# Copyright (C) 2020-2021 Ycarus (Yannick Chabanois) # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -8,10 +8,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ell -PKG_VERSION:=0.30 +PKG_VERSION:=0.41 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_HASH:=51cf8cc66a9d1038e41f7d619ea5660aa4476904496562b2d45ca79370ca4a5e +PKG_HASH:=4e8dba6c53cf152dbd0fd1dc3d4c7b04abf79e20a948895f85943e586870505c PKG_SOURCE_URL:=@KERNEL/linux/libs/ell PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=GPL diff --git a/mptcpd/Makefile b/mptcpd/Makefile index a23a4a41b..47f0de339 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -8,13 +8,15 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mptcpd -PKG_VERSION:=0.5.1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/intel/mptcpd/releases/download/v$(PKG_VERSION) -PKG_HASH:=0ee4418880f20a1a2eff5c54c26185a75092cb44cbabe0fa3f25a2c5886459e7 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/intel/mptcpd.git +PKG_SOURCE_VERSION:=0e7175adf721c95a3bd742be77cb85e0b47138cd +PKG_VERSION:=0.7-$(PKG_SOURCE_VERSION) PKG_RELEASE:=1 PKG_MAINTAINER:=Ycarus (Yannick Chabanois) +PKG_FIXUP:=autoreconf + PKG_FORTIFY_SOURCE:=2 PKG_INSTALL:=1 PKG_BUILD_PARALLEL:=1 @@ -43,6 +45,7 @@ endef define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/bin $(CP) $(PKG_INSTALL_DIR)/usr/bin/mptcpd $(1)/usr/bin/mptcpd + $(CP) $(PKG_INSTALL_DIR)/usr/bin/mptcpize $(1)/usr/bin/mptcpize $(INSTALL_DIR) $(1)/usr/include/mptcpd $(CP) $(PKG_INSTALL_DIR)/usr/include/mptcpd/*.h $(1)/usr/include/ $(INSTALL_DIR) $(1)/usr/lib/mptcpd diff --git a/mptcpd/patches/log.patch b/mptcpd/patches/log.patch deleted file mode 100644 index c0bc52e3c..000000000 --- a/mptcpd/patches/log.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/src/configuration.c 2020-04-14 21:31:22.057292953 +0200 -+++ b/src/configuration.c 2020-04-14 21:32:13.712364449 +0200 -@@ -35,10 +35,10 @@ - */ - //@{ - /// Underlying string concatenation macro. --#define MPTCPD_CONCAT_IMPL(x, ...) x ## __VA_ARGS__ -+//#define MPTCPD_CONCAT_IMPL(x, ...) x ## __VA_ARGS__ - - /// Concatenate strings using the preprocessor. --#define MPTCPD_CONCAT(x, ...) MPTCPD_CONCAT_IMPL(x, __VA_ARGS__) -+//#define MPTCPD_CONCAT(x, ...) MPTCPD_CONCAT_IMPL(x, __VA_ARGS__) - //@} - - // Compile-time default logging choice -@@ -47,7 +47,7 @@ - # error Problem configuring default log message destination. - #endif - /// Name of the default logging function determined at compile-time. --#define MPTCPD_SET_LOG_FUNCTION MPTCPD_CONCAT(l_log_set_, MPTCPD_LOGGER) -+#define MPTCPD_SET_LOG_FUNCTION l_log_set_stderr - - /** - * @brief Get the function that sets the log message destination. diff --git a/mptcpd/patches/remove_log.patch b/mptcpd/patches/remove_log.patch new file mode 100644 index 000000000..ed077f859 --- /dev/null +++ b/mptcpd/patches/remove_log.patch @@ -0,0 +1,167 @@ +--- a/src/configuration.c 2021-06-29 17:44:20.481179981 +0200 ++++ b/src/configuration.c 2021-06-29 17:44:52.580655950 +0200 +@@ -37,21 +37,12 @@ + * Preprocessor concatenation that expands preprocessor tokens as + * needed by leveraging the usual indirection technique. + */ +-///@{ +-/// Underlying string concatenation macro. +-#define MPTCPD_CONCAT_IMPL(x, ...) x ## __VA_ARGS__ +- +-/// Concatenate strings using the preprocessor. +-#define MPTCPD_CONCAT(x, ...) MPTCPD_CONCAT_IMPL(x, __VA_ARGS__) +-///@} + + // Compile-time default logging choice + #ifndef MPTCPD_LOGGER + // This should never occur! + # error Problem configuring default log message destination. + #endif +-/// Name of the default logging function determined at compile-time. +-#define MPTCPD_SET_LOG_FUNCTION MPTCPD_CONCAT(l_log_set_, MPTCPD_LOGGER) + + /** + * @brief Get the function that sets the log message destination. +@@ -474,7 +465,6 @@ + + struct mptcpd_config *mptcpd_config_create(int argc, char *argv[]) + { +- MPTCPD_SET_LOG_FUNCTION(); // For early logging. + + struct mptcpd_config *const config = + l_new(struct mptcpd_config, 1); +--- a/src/mptcpize.c 2021-06-29 19:29:57.810281053 +0200 ++++ b/src/mptcpize.c 2021-06-29 19:29:29.942701557 +0200 +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -79,7 +78,7 @@ + nr++; + envp = calloc(nr + 3, sizeof(char *)); + if (!envp) +- error(1, errno, "can't allocate env list"); ++ fprintf(stderr, "can't allocate env list"); + + // ... filtering out any 'LD_PRELOAD' ... + nr = 0; +@@ -103,7 +102,7 @@ + // build the NULL terminated arg list + argv = calloc(argc + 1, sizeof(char *)); + if (!argv) +- error(1, errno, "can't allocate argument list"); ++ fprintf(stderr, "can't allocate argument list"); + + memcpy(argv, av, argc * sizeof(char*)); + return execvpe(argv[0], argv, envp); +@@ -124,33 +123,33 @@ + len = strlen(name) + 1 + strlen(SYSTEMCTL_SHOW); + cmd = malloc(len); + if (!cmd) +- error(1, 0, "can't allocate systemctl command string"); ++ fprintf(stderr, "can't allocate systemctl command string"); + + sprintf(cmd, SYSTEMCTL_SHOW"%s", name); + systemctl = popen(cmd, "r"); + if (!systemctl) +- error(1, errno, "can't execute %s", cmd); ++ fprintf(stderr, "can't execute %s", cmd); + + free(cmd); + while ((read = getline(&line, &len, systemctl)) != -1) { + if (strncmp(line, SYSTEMD_UNIT_VAR, strlen(SYSTEMD_UNIT_VAR)) == 0) { + char *ret = strdup(&line[strlen(SYSTEMD_UNIT_VAR)]); + if (!ret) +- error(1, errno, "failed to duplicate string"); ++ fprintf(stderr, "failed to duplicate string"); + + // trim trailing newline, if any + len = strlen(ret); + if (len > 0 && ret[len - 1] == '\n') + ret[--len] = 0; + if (len == 0) +- error(1, 0, "can't find unit file for service %s", name); ++ fprintf(stderr, "can't find unit file for service %s", name); + free(line); + pclose(systemctl); + return ret; + } + } + +- error(1, 0, "can't find FragmentPath attribute for unit %s", name); ++ fprintf(stderr, "can't find FragmentPath attribute for unit %s", name); + + // never reached: just silence gcc + return NULL; +@@ -175,12 +174,12 @@ + unit = locate_unit(argv[0]); + src = fopen(unit, "r"); + if (!src) +- error(1, errno, "can't open file %s", unit); ++ fprintf(stderr, "can't open file %s", unit); + + strcpy(dst_path, "/tmp/unit_XXXXXX"); + dst = mkstemp(dst_path); + if (dst < 0) +- error(1, errno, "can't create tmp file"); ++ fprintf(stderr, "can't create tmp file"); + + // reset any prior error, to allow later check on errno + errno = 0; +@@ -194,27 +193,27 @@ + + if (!is_env) { + if (write(dst, line, read) < 0) +- error(1, errno, "can't write '%s' into %s", line, dst_path); ++ fprintf(stderr, "can't write '%s' into %s", line, dst_path); + } + + if (append_env && + (is_env || strncmp(line, SYSTEMD_SERVICE_TAG, strlen(SYSTEMD_SERVICE_TAG)) == 0)) { + if (dprintf(dst, "%s%s\n", SYSTEMD_ENV_VAR, MPTCPWRAP_ENV) < 0) +- error(1, errno, "can't write to env string into %s", dst_path); ++ fprintf(stderr, "can't write to env string into %s", dst_path); + append_env = 0; + } + } + if (errno != 0) +- error(1, errno, "can't read from %s", unit); ++ fprintf(stderr, "can't read from %s", unit); + free(line); + fclose(src); + close(dst); + + if (rename(dst_path, unit) < 0) +- error(1, errno, "can't rename %s to %s", dst_path, unit); ++ fprintf(stderr, "can't rename %s to %s", dst_path, unit); + + if (system("systemctl daemon-reload") != 0) +- error(1, errno, "can't reload unit, manual 'systemctl daemon-reload' is required"); ++ fprintf(stderr, "can't reload unit, manual 'systemctl daemon-reload' is required"); + + printf("mptcp successfully %s on unit %s\n", + enable ? "enabled" : "disabled", unit); +@@ -239,7 +238,7 @@ + argp_program_version = "mptcpize "VERSION; + argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; + if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, &idx, 0) < 0) +- error(1, errno, "can't parse arguments"); ++ fprintf(stderr, "can't parse arguments"); + + argc -= idx; + argv += idx; +--- a/src/mptcpize.c 2021-07-05 20:06:07.035838944 +0200 ++++ b/src/mptcpize.c 2021-07-05 20:06:26.875505617 +0200 +@@ -7,8 +7,6 @@ + * Copyright (c) 2021, Red Hat, Inc. + */ + +-#define _GNU_SOURCE +- + #include + + #include From aa2dbb8c741269c3310730bcf98ca0d36cdffd63 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Jul 2021 12:14:50 +0200 Subject: [PATCH 0539/2059] Keep mac for vlan --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 8936596a0..1f3f4eed4 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -47,7 +47,7 @@ interface_macaddr_count() { local intf="$1" local dmacaddr="$2" config_get macaddr "$intf" macaddr - [ "$macaddr" = "$dmacaddr" ] && nbmac=$((nbmac+1)) + [ "$macaddr" = "$dmacaddr" ] && [ -z "$(echo $intf | grep '\.')" ] && nbmac=$((nbmac+1)) } interface_max_metric() { From 1cafd546c41384836111d5d8a25efade28f0c2ea Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Jul 2021 12:15:16 +0200 Subject: [PATCH 0540/2059] doesn't add mac for vlan --- macvlan/files/etc/init.d/macvlan | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macvlan/files/etc/init.d/macvlan b/macvlan/files/etc/init.d/macvlan index b38597eff..a09988504 100755 --- a/macvlan/files/etc/init.d/macvlan +++ b/macvlan/files/etc/init.d/macvlan @@ -25,7 +25,7 @@ _save_macaddr() { } [ -z "$(uci -q get network.$1.macaddr)" ] && { _ifname=$(uci -q get "network.$1.ifname") - [ -n "$_ifname" ] && { + [ -n "$_ifname" ] && [ -z "$(echo $_ifname | grep '\.')" ] && { _macaddr=$(ip link show dev $_ifname 2>/dev/null | grep link | awk '{print $2}') [ -n "$_macaddr" ] && { uci -q set network.$1.macaddr=$_macaddr From 50462b99802a89427de8f82a7fdcede76aec1e09 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Jul 2021 12:15:40 +0200 Subject: [PATCH 0541/2059] No error of same mac for vlan in status page --- luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 977f67372..74543d056 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1159,7 +1159,7 @@ function interfaces_status() end duplicatemac = false - if mac ~= "" and mac ~= nil and not (section["device"] ~= nil and section["device"]:match("^@.*")) then + if mac ~= "" and mac ~= nil and not (section["device"] ~= nil and section["device"]:match("^@.*")) and not (ifname ~= nil and ifname:match("%.")) then if allmac[mac] then connectivity = "ERROR" duplicatemac = true From 276acb2db61ece680392be762fc76bab9e74655c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Jul 2021 12:14:50 +0200 Subject: [PATCH 0542/2059] Keep mac for vlan --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 334cc0632..604c54fe8 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -47,7 +47,7 @@ interface_macaddr_count() { local intf="$1" local dmacaddr="$2" config_get macaddr "$intf" macaddr - [ "$macaddr" = "$dmacaddr" ] && nbmac=$((nbmac+1)) + [ "$macaddr" = "$dmacaddr" ] && [ -z "$(echo $intf | grep '\.')" ] && nbmac=$((nbmac+1)) } interface_max_metric() { From 8aa3927d7c2e95d67bb9f6e7cbc4b86737bfa642 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Jul 2021 12:15:16 +0200 Subject: [PATCH 0543/2059] doesn't add mac for vlan --- macvlan/files/etc/init.d/macvlan | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macvlan/files/etc/init.d/macvlan b/macvlan/files/etc/init.d/macvlan index b38597eff..a09988504 100755 --- a/macvlan/files/etc/init.d/macvlan +++ b/macvlan/files/etc/init.d/macvlan @@ -25,7 +25,7 @@ _save_macaddr() { } [ -z "$(uci -q get network.$1.macaddr)" ] && { _ifname=$(uci -q get "network.$1.ifname") - [ -n "$_ifname" ] && { + [ -n "$_ifname" ] && [ -z "$(echo $_ifname | grep '\.')" ] && { _macaddr=$(ip link show dev $_ifname 2>/dev/null | grep link | awk '{print $2}') [ -n "$_macaddr" ] && { uci -q set network.$1.macaddr=$_macaddr From ae8371b2cc7c0fa8e0dcacba1a66e3677be4e1a9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 9 Jul 2021 18:40:16 +0200 Subject: [PATCH 0544/2059] Always use device in priority --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 4 ++-- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 8 ++++---- .../root/usr/libexec/rpcd/openmptcprouter | 2 +- mptcp/files/etc/init.d/mptcp | 7 ++++--- omr-tracker/files/etc/init.d/omr-tracker | 3 +++ 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 2b8f56972..c69c1ce62 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -501,8 +501,8 @@ _intf_rule_v2ray_rules() { _intf_rule() { local intf - config_get intf $1 ifname - [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -z "$intf" ] && config_get intf $1 ifname [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') #count=$((count+1)) config_get count $1 metric diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 9c547bff8..8a1a5ab3c 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -18,11 +18,11 @@ omr_intf_check() { omr_intf_set() { local device local ifname - config_get ifname "$1" ifname config_get device "$1" device config_get type "$1" type - [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -z "$ifname" ] && config_get ifname "$1" ifname if [ "$type" != "macvlan" ] && [ -n "$ifname" ] && [ -f /sys/class/net/${ifname}/device/uevent ]; then devicepath=$(readlink -f /sys/class/net/${ifname}) @@ -56,7 +56,6 @@ omr_set_settings() { local ifname local multipath config_get multipath "$1" multipath - config_get ifname "$1" ifname config_get device "$1" device config_get proto "$1" proto config_get type "$1" type @@ -76,7 +75,8 @@ omr_set_settings() { [ -z "$addlatency" ] && addlatency=0 devicename=$(echo "$device" | cut -d'/' -f3) - [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -z "$ifname" ] && config_get ifname "$1" ifname [ -n "$(echo $ifname | grep '@')" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') if [ -n "$ifname" ]; then diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index effce068c..00b151e38 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1156,7 +1156,7 @@ function interfaces_status() end duplicatemac = false - if mac ~= "" and mac ~= nil and not (section["ifname"] ~= nil and section["ifname"]:match("^@.*")) then + if mac ~= "" and mac ~= nil and not (section["ifname"] ~= nil and section["ifname"]:match("^@.*")) and not (ifname ~= nil and ifname:match("%.")) then if allmac[mac] then connectivity = "ERROR" duplicatemac = true diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 604c54fe8..a4d83ea99 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -85,9 +85,9 @@ interface_multipath_settings() { local enabled config_get enabled "$config" auto "1" - config_get iface "$config" ifname + iface=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') + [ -z "$iface" ] && config_get iface "$config" ifname config_get txqueuelen "$config" txqueuelen - [ -z "$iface" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["device"]') if [ "$(uci -q get openmptcprouter.${config}.metric)" = "" ]; then count=$((count+1)) @@ -349,7 +349,8 @@ interface_multipath_settings() { } load_interfaces() { - config_get ifname "$1" ifname + ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -z "$ifname" ] && config_get ifname "$1" ifname config_get multipath "$1" multipath "" [ -z "$multipath" ] && multipath="$(uci -q get openmptcprouter.$1.multipath)" [ "$multipath" != "off" ] && [ "$multipath" != "" ] && interfaces=" ${ifname} ${interfaces}" diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 3276316e9..dc9fb4cb7 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -69,6 +69,9 @@ _launch_tracker() { [ "${ifenabled}" = "0" ] && return [ "${enabled}" = "0" ] && return [ -z "${hosts}" ] && [ "$type" != "none" ] && return + ifstatus=$(ifstatus "$1" | jsonfilter -q -e '@["up"]') + ifdevice=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') + [ "${ifstatus}" = "false" ] && [ -z "${ifdevice}" ] && return [ -z "${interval_tries}" ] && interval_tries=1 procd_open_instance From bc498724ff749639d87a9c79c669c10770f2ffcd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 10 Jul 2021 15:38:16 +0200 Subject: [PATCH 0545/2059] Fix get device --- mptcp/files/etc/init.d/mptcp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index a4d83ea99..bb5297dc7 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -85,7 +85,9 @@ interface_multipath_settings() { local enabled config_get enabled "$config" auto "1" - iface=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') + network_get_device iface $config + [ -z "$iface" ] && network_get_physdev iface $config + [ -z "$iface" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["l3_device"]') [ -z "$iface" ] && config_get iface "$config" ifname config_get txqueuelen "$config" txqueuelen [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["device"]') @@ -176,7 +178,7 @@ interface_multipath_settings() { config_get gateway $config gateway config_get netmask $config netmask [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr $netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` - [ -n "$îpaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` elif [ "$proto" != "gre" ]; then network_get_ipaddr ipaddr $config [ -z "$ipaddr" ] && ipaddr=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") From f557cb00804fbb4fef3f3086b689c0f10cf2084e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Jun 2021 19:43:45 +0200 Subject: [PATCH 0546/2059] Fix dashboard error --- .../luci-static/resources/view/dashboard/include/10_router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js index b5892cff2..ad9278c53 100644 --- a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js @@ -371,7 +371,7 @@ return baseclass.extend({ release: { title: _('Firmware Version'), - value: boardinfo.release.description ? boardinfo.release.description : null + value: (typeof boardinfo.release.description !== "undefined") ? boardinfo.release.description : null } }; From c6d6552d763c8642aad6740b91225e036849b306 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 12 Jul 2021 18:06:01 +0200 Subject: [PATCH 0547/2059] Restart dnsmasq by omr-bypass only if needed --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 70eda0529..ed267449d 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -100,12 +100,14 @@ _bypass_domain() { fi if [ "$(uci -q get dhcp.@dnsmasq[0].ipset | grep /$domain/)" = "" ]; then uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + add_domains="true" else dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g') for dnsipset in $dnsmasqipset; do if [ "$(echo $dnsipset | cut -d/ -f2)" = "$domain" ]; then uci -q del_list dhcp.@dnsmasq[0].ipset=$dnsipset uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + add_domains="true" fi done fi @@ -680,6 +682,7 @@ boot() { start_service() { #local count logger -t "omr-bypass" "Starting OMR-ByPass..." + add_domains="false" config_load omr-bypass config_foreach _add_proto proto disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" @@ -797,11 +800,11 @@ start_service() { config_foreach _bypass_proto dpis uci -q commit omr-bypass - [ -z "$RELOAD" ] && { + [ -z "$RELOAD" ] && [ "$add_domains" = "true" ] && { logger -t "omr-bypass" "Restart dnsmasq..." /etc/init.d/dnsmasq restart } - [ -n "$RELOAD" ] && { + [ -n "$RELOAD" ] && [ "$add_domains" = "true" ] && { logger -t "omr-bypass" "Reload dnsmasq..." /etc/init.d/dnsmasq reload } From f7136422ca8b14bde360689046d778ed539a796b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 12 Jul 2021 18:06:41 +0200 Subject: [PATCH 0548/2059] Fix wifi --- .../files/etc/uci-defaults/2091-omr-wifi | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi b/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi index f2e65c52e..1a6712a95 100755 --- a/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi +++ b/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi @@ -1,18 +1,22 @@ #!/bin/sh -if [ "$(uci -q get wireless.radio0)" != "" ]; then - if [ "$(uci -q get wireless.radio0.country)" = "" ]; then +if [ "$(uci -q get wifi-iface.radio0)" != "" ] && [ "$(uci -q get wifi-iface.default_radio0.key)" = "12345678" ]; then + if [ "$(uci -q get wifi-device.radio0.country)" = "" ]; then uci -q batch <<-EOF >/dev/null - set wireless.radio0.country='00' - set wireless.default_radio0.skip_inactivity_poll='1' - commit wireless + set wifi-device.radio0.country='00' + commit wifi-device EOF fi - if [ "$(uci -q get wireless.default_radio0.network)" = "lan" ]; then + if [ -n "$(uci -q get wifi-iface.radio0.network | grep lan)" ]; then uci -q batch <<-EOF >/dev/null - set wireless.default_radio0.network='wifi' - commit wireless + set wifi-iface.default_radio0.network='wifi' + commit wifi-iface + EOF + fi + if [ -n "$(uci -q get wifi-device.radio0.cell_density)" ]; then + uci -q batch <<-EOF >/dev/null + delete wifi-device.radio0.cell_density + commit wifi-device EOF - fi fi From f45d3eec96f53b71cc8600574bc94acd9f3d02d1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 16 Jul 2021 13:05:39 +0200 Subject: [PATCH 0549/2059] Remove ovh as test site --- openmptcprouter/files/bin/omr-test-speed | 12 ++++++------ openmptcprouter/files/bin/omr-test-speedv6 | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 863232f9e..47fd65cb9 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -1,8 +1,8 @@ #!/bin/sh # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : -OVH=false -if [ "$1" = "ovh" ]; then - OVH=true +HETZNER=false +if [ "$1" = "hetzner" ]; then + hetzner=true INTERFACE="$2" else INTERFACE="$1" @@ -13,9 +13,9 @@ fi exit 0 } -if [ "$OVH" = false ]; then +if [ "$HETZNER" = false ]; then echo "Select best test server..." - HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip http://proof.ovh.net/files/10Gb.dat https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" + HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" bestping="9999" for pinghost in $HOSTLST; do domain=$(echo $pinghost | awk -F/ '{print $3}') @@ -32,7 +32,7 @@ if [ "$OVH" = false ]; then done fi -[ -z "$HOST" ] && HOST="http://proof.ovh.net/files/10Gio.dat" +[ -z "$HOST" ] && HOST="https://speed.hetzner.de/10GB.bin" echo "Best server is $HOST, running test:" trap : HUP INT TERM diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index ca3d64d9a..3db10fee9 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -1,8 +1,8 @@ #!/bin/sh # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : -OVH=false -if [ "$1" = "ovh" ]; then - OVH=true +HETZNER=false +if [ "$1" = "hetzner" ]; then + HETZNER=true INTERFACE="$2" else INTERFACE="$1" @@ -14,9 +14,9 @@ fi } -if [ "$OVH" = false ]; then +if [ "$HETZNER" = false ]; then echo "Select best test server..." - HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip http://www.ovh.net/files/10Gb.dat https://speed.hetzner.de/10GB.bin http://ipv6.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" + HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip https://speed.hetzner.de/10GB.bin http://ipv6.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" bestping="9999" for pinghost in $HOSTLST; do domain=$(echo $pinghost | awk -F/ '{print $3}') @@ -33,7 +33,7 @@ if [ "$OVH" = false ]; then done fi -[ -z "$HOST" ] && HOST="http://proof.ovh.net/files/10Gio.dat" +[ -z "$HOST" ] && HOST="https://speed.hetzner.de/10GB.bin" echo "Best server is $HOST, running test:" trap : HUP INT TERM From 24a55685e1b080f37323b32ca2dc915c86c24c13 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Jul 2021 19:32:38 +0200 Subject: [PATCH 0550/2059] Fix defaults settings --- glorytun/glorytun.config | 3 ++- luci-app-glorytun-udp/root/etc/config/glorytun-udp | 4 ++++ mlvpn/files/etc/config/mlvpn | 1 + omr-tracker/files/etc/config/omr-tracker | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/glorytun/glorytun.config b/glorytun/glorytun.config index 33c93f36f..78f97090c 100644 --- a/glorytun/glorytun.config +++ b/glorytun/glorytun.config @@ -11,4 +11,5 @@ config glorytun 'vpn' option localip '10.255.255.2' option remoteip '10.255.255.1' option multiqueue '1' - option label 'Default VPN' \ No newline at end of file + option label 'Default VPN' + option timeout '10000' \ No newline at end of file diff --git a/luci-app-glorytun-udp/root/etc/config/glorytun-udp b/luci-app-glorytun-udp/root/etc/config/glorytun-udp index d5d356dd6..6a526ddea 100644 --- a/luci-app-glorytun-udp/root/etc/config/glorytun-udp +++ b/luci-app-glorytun-udp/root/etc/config/glorytun-udp @@ -8,3 +8,7 @@ config glorytun-udp 'vpn' option localip '10.255.254.2' option remoteip '10.255.254.1' option mode 'to' + option mode kxtimeout '7d' + option mode timetolerance '10m' + option mode keepalive '25s' + option mode rateauto '0' \ No newline at end of file diff --git a/mlvpn/files/etc/config/mlvpn b/mlvpn/files/etc/config/mlvpn index 53085dc48..1122794be 100644 --- a/mlvpn/files/etc/config/mlvpn +++ b/mlvpn/files/etc/config/mlvpn @@ -8,3 +8,4 @@ config mlvpn 'general' option host '128.128.128.128' option firstport '65201' option interface_name 'mlvpn0' + option loss_tolerance '50' \ No newline at end of file diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index df54c8416..93aaf1674 100644 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -25,7 +25,7 @@ config defaults 'defaults' option wait_test '0' option server_http_test '1' option restart_down '0' - option options '' + option mail_alert '0' config proxy 'proxy' option enabled '1' From 55995713e3119532399291a8a9a96376eb498261 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Jul 2021 19:33:38 +0200 Subject: [PATCH 0551/2059] Remove DNSSEC on dnsmasq --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 4 +--- openmptcprouter/files/etc/uci-defaults/1940-omr-dns | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 87b908344..79dbead91 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -152,15 +152,13 @@ start_service() { del_list dhcp.@dnsmasq[0].server='127.0.0.1#5353' add_list dhcp.@dnsmasq[0].server='114.114.114.114' set dhcp.@dnsmasq[0].dnsseccheckunsigned='0' - delete dhcp.@dnsmasq[0].dnssec='1' + delete dhcp.@dnsmasq[0].dnssec commit dhcp EOF elif [ "$(uci -q get openmptcprouter.settings.country)" = "world" ] && [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep '114.114.114.114')" ]; then uci -q batch <<-EOF > /dev/null add_list dhcp.@dnsmasq[0].server='127.0.0.1#5353' del_list dhcp.@dnsmasq[0].server='114.114.114.114' - set dhcp.@dnsmasq[0].dnsseccheckunsigned='1' - set dhcp.@dnsmasq[0].dnssec='1' commit dhcp EOF fi diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index 705c30225..2d4e3cbd9 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -15,7 +15,6 @@ if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then uci -q batch <<-EOF >/dev/null add_list dhcp.@dnsmasq[-1].server="127.0.0.1#5353" add_list dhcp.@dnsmasq[-1].server="/lan/" - set dhcp.@dnsmasq[-1].dnssec='1' commit dhcp EOF fi From 180b5a02cde95051e4273f566f53c1a7e85e500e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Jul 2021 19:34:00 +0200 Subject: [PATCH 0552/2059] Fix omr-tracker defaults settings --- openmptcprouter/files/etc/uci-defaults/1990-omr-tracker | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker b/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker index 00fbf4002..882e4b0a7 100755 --- a/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker +++ b/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker @@ -10,6 +10,11 @@ if [ "$(uci -q get omr-tracker.omrvpn)" = "" ]; then set omr-tracker.omrvpn.interval=5 set omr-tracker.omrvpn.mail_alert=0 set omr-tracker.omrvpn.enabled=1 + set omr-tracker.omrvpn.wait-test=0 + set omr-tracker.omrvpn.server_http_test=1 + set omr-tracker.omrvpn.restart_down=0 + add_list omr-tracker.omrvpn.hosts='4.2.2.1' + add_list omr-tracker.omrvpn.hosts='8.8.8.8' commit omr-tracker EOF fi From cbbbea76ac935d28e69eb8f75f535e014bfa1b3d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Jul 2021 19:35:31 +0200 Subject: [PATCH 0553/2059] Fix mptcp init script --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 1f3f4eed4..64bb51d51 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -179,7 +179,7 @@ interface_multipath_settings() { config_get gateway $config gateway config_get netmask $config netmask [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr $netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` - [ -n "$îpaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` elif [ "$proto" != "gre" ]; then network_get_ipaddr ipaddr $config [ -z "$ipaddr" ] && ipaddr=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") From 397d89b87f7fb6e27710b7f1835cb210e3d11234 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Jul 2021 09:22:49 +0200 Subject: [PATCH 0554/2059] Make multipath script work for kernel upstream MPTCP --- mptcp/files/usr/bin/multipath | 113 ++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 33 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index f25706218..709be048e 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -6,9 +6,8 @@ # Released under GPL 3 or later if [ -d "/proc/sys/net/mptcp" ]; then - if [ `cat /proc/sys/net/mptcp/mptcp_enabled` = 0 ]; then + if ([ -f /proc/sys/net/mptcp/mptcp_enabled ] && [ `cat /proc/sys/net/mptcp/mptcp_enabled` = 0 ]) || ([ -f /proc/sys/net/mptcp/enabled ] && [ `cat /proc/sys/net/mptcp/enabled` = 0 ]); then echo "MPTCP is disabled!" - echo "Please set net.mptcp.mptcp_enabled = 1" exit 1 fi else @@ -43,12 +42,28 @@ case $1 in cat /proc/net/mptcp_fullmesh exit 0;; "-k") - echo Enabled: `cat /proc/sys/net/mptcp/mptcp_enabled` - echo Path Manager: `cat /proc/sys/net/mptcp/mptcp_path_manager` - echo Use checksum: `cat /proc/sys/net/mptcp/mptcp_checksum` - echo Scheduler: `cat /proc/sys/net/mptcp/mptcp_scheduler` - echo Syn retries: `cat /proc/sys/net/mptcp/mptcp_syn_retries` - echo Debugmode: `cat /proc/sys/net/mptcp/mptcp_debug` + if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then + echo Enabled: `cat /proc/sys/net/mptcp/mptcp_enabled` + elif [ -f /proc/sys/net/mptcp/enabled ]; then + echo Enabled: `cat /proc/sys/net/mptcp/enabled` + fi + if [ -f /proc/sys/net/mptcp/mptcp_path_manager ]; then + echo Path Manager: `cat /proc/sys/net/mptcp/mptcp_path_manager` + fi + if [ -f /proc/sys/net/mptcp/mptcp_checksum ]; then + echo Use checksum: `cat /proc/sys/net/mptcp/mptcp_checksum` + else + echo Use checksum: `cat /proc/sys/net/mptcp/checksum_enabled` + fi + if [ -f /proc/sys/net/mptcp/mptcp_scheduler ]; then + echo Scheduler: `cat /proc/sys/net/mptcp/mptcp_scheduler` + fi + if [ -f /proc/sys/net/mptcp/mptcp_syn_retries ]; then + echo Syn retries: `cat /proc/sys/net/mptcp/mptcp_syn_retries` + fi + if [ -f /proc/sys/net/mptcp/mptcp_debug ]; then + echo Debugmode: `cat /proc/sys/net/mptcp/mptcp_debug` + fi echo echo See http://multipath-tcp.org/ for details exit 0 ;; @@ -70,33 +85,65 @@ TYPE="$2" exit 1 } -FLAG_PATH="/sys/class/net/$DEVICE/flags" -IFF=`cat $FLAG_PATH` +if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then + FLAG_PATH="/sys/class/net/$DEVICE/flags" + IFF=`cat $FLAG_PATH` -IFF_OFF="0x80000" -IFF_ON="0x00" -IFF_BACKUP="0x100000" -IFF_HANDOVER="0x200000" -IFF_MASK="0x380000" + IFF_OFF="0x80000" + IFF_ON="0x00" + IFF_BACKUP="0x100000" + IFF_HANDOVER="0x200000" + IFF_MASK="0x380000" -case $TYPE in - "off") FLAG=$IFF_OFF;; - "on") FLAG=$IFF_ON;; - "backup") FLAG=$IFF_BACKUP;; - "handover") FLAG=$IFF_HANDOVER;; - "") - IFF=`printf "0x%02x" $(($IFF&$IFF_MASK))` - case "$IFF" in - $IFF_OFF) echo $DEVICE is deactivated;; - $IFF_ON) echo $DEVICE is in default mode;; - $IFF_BACKUP) echo $DEVICE is in backup mode;; - $IFF_HANDOVER) echo $DEVICE is in handover mode;; - *) echo "Unkown state!" && exit 1;; - esac - exit 0;; - *) echo "Unkown flag! Use 'multipath -h' for help" && exit 1;; -esac + case $TYPE in + "off") FLAG=$IFF_OFF;; + "on") FLAG=$IFF_ON;; + "backup") FLAG=$IFF_BACKUP;; + "handover") FLAG=$IFF_HANDOVER;; + "") + IFF=`printf "0x%02x" $(($IFF&$IFF_MASK))` + case "$IFF" in + $IFF_OFF) echo $DEVICE is deactivated;; + $IFF_ON) echo $DEVICE is in default mode;; + $IFF_BACKUP) echo $DEVICE is in backup mode;; + $IFF_HANDOVER) echo $DEVICE is in handover mode;; + *) echo "Unkown state!" && exit 1;; + esac + exit 0;; + *) echo "Unkown flag! Use 'multipath -h' for help" && exit 1;; + esac -printf "0x%02x" $(($(($IFF^$(($IFF&$IFF_MASK))))|$FLAG)) > $FLAG_PATH + printf "0x%02x" $(($(($IFF^$(($IFF&$IFF_MASK))))|$FLAG)) > $FLAG_PATH +else + ID=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $3}') + IFF=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $4}') + case $TYPE in + "off") + [ -n "$ID" ] && ip mptcp endpoint delete id $ID + exit 0;; + "on") + [ -n "$ID" ] && ip mptcp endpoint delete id $ID + ip mptcp endpoint add $IP dev $DEVICE subflow + exit 0;; + "signal") + [ -n "$ID" ] && ip mptcp endpoint delete id $ID + ip mptcp endpoint add $IP dev $DEVICE signal subflow + exit 0;; + "backup") + [ -n "$ID" ] && ip mptcp endpoint delete id $ID + ip mptcp endpoint add $IP dev $DEVICE backup + exit 0;; + "") + case "$IFF" in + "") echo $DEVICE is deactivated;; + "subflow") echo $DEVICE is in default mode;; + "backup") echo $DEVICE is in backup mode;; + "signal") echo $DEVICE is in signal mode;; + *) echo "$DEVICE Unkown state!" && exit 1;; + esac + exit 0;; + *) echo "Unkown flag! Use 'multipath -h' for help" && exit 1;; + esac +fi From 7a549a66284c38404df09e3e80503fafca708ed5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Jul 2021 09:24:11 +0200 Subject: [PATCH 0555/2059] Set country default for wifi --- openmptcprouter/files/etc/uci-defaults/2091-omr-wifi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi b/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi index 1a6712a95..2925bb104 100755 --- a/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi +++ b/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi @@ -2,7 +2,7 @@ if [ "$(uci -q get wifi-iface.radio0)" != "" ] && [ "$(uci -q get wifi-iface.default_radio0.key)" = "12345678" ]; then if [ "$(uci -q get wifi-device.radio0.country)" = "" ]; then uci -q batch <<-EOF >/dev/null - set wifi-device.radio0.country='00' + set wifi-device.radio0.country='FR' commit wifi-device EOF fi From a7bfd7cac712c2144117c6d2193ad807bfffe76c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Jul 2021 09:26:07 +0200 Subject: [PATCH 0556/2059] Fix for IPv6 fw --- .../files/etc/init.d/openmptcprouter-vps | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 71350104c..3104f2f74 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -884,6 +884,7 @@ _vps_firewall_redirect_port() { config_get v2ray $1 v2ray "0" config_get name $1 name config_get dmz $1 dmz "0" + config_get target $1 target "REDIRECT" if [ -z "$src_dport" ] && [ -n "$dest_port" ]; then src_dport=$dest_port fi @@ -918,42 +919,74 @@ _vps_firewall_redirect_port() { iptables-save --counters | sed "s:-d $src_dip/32::g" | iptables-restore -w } [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfwlist" | grep "# OMR $username redirect router $src_dport port $protoi${comment}") + if [ "$target" = "ACCEPT" ]; then + checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port $protoi${comment}") + else + checkfw=$(echo "$vpsfwlist" | grep "# OMR $username redirect router $src_dport port $protoi${comment}") + fi fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username redirect router $src_dport port $protoi") + if [ "$target" = "ACCEPT" ]; then + checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port $protoi") + else + checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username redirect router $src_dport port $protoi") + fi else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfw6list" | grep "# OMR $username redirect router $src_dport port $protoi${comment}") + if [ "$target" = "ACCEPT" ]; then + checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port $protoi${comment}") + else + checkfw=$(echo "$vpsfw6list" | grep "# OMR $username redirect router $src_dport port $protoi${comment}") + fi fi fi if [ "$checkfw" = "" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'$protoi'","fwtype" : "DNAT","ipproto" : "'$family'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'$protoi'","fwtype" : "'$target'","ipproto" : "'$family'"}' _set_json "shorewallopen" "$settings" fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi") + if [ "$target" = "ACCEPT" ]; then + vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port $protoi") + else + vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi") + fi else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username redirect router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR redirect router $src_dport port $protoi${comment}") + if [ "$target" = "ACCEPT" ]; then + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port $protoi${comment}") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port $protoi${comment}") + else + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username redirect router $src_dport port $protoi${comment}") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR redirect router $src_dport port $protoi${comment}") + fi fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi") + if [ "$target" = "ACCEPT" ]; then + vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port $protoi") + else + vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi") + fi else [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username redirect router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR redirect router $src_dport port $protoi${comment}") + if [ "$target" = "ACCEPT" ]; then + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port $protoi${comment}") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port $protoi${comment}") + else + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username redirect router $src_dport port $protoi${comment}") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR redirect router $src_dport port $protoi${comment}") + fi fi fi else From 950644e56a0995fe49230405a9cd5924acff4080 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Jul 2021 12:46:17 +0200 Subject: [PATCH 0557/2059] Increase iperf3 package release --- iperf3/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iperf3/Makefile b/iperf3/Makefile index 1d0d891ef..6cdb6b8a9 100644 --- a/iperf3/Makefile +++ b/iperf3/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iperf PKG_VERSION:=3.10.1 -PKG_RELEASE:=1 +PKG_RELEASE:=10 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://downloads.es.net/pub/iperf From 02d18da7bb9b6196a8d47204d950916a4ab83578 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Jul 2021 20:21:24 +0200 Subject: [PATCH 0558/2059] Create device via wizard, need more work --- .../luasrc/controller/openmptcprouter.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index cca82d950..1f04b4b88 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -292,12 +292,24 @@ function wizard_add() ucic:set("network",intf,"masterintf",masterintf) elseif typeintf == "" and ifname ~= "" and (proto == "static" or proto == "dhcp" or proto == "dhcpv6") then ucic:set("network",intf,"device",ifname) + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",ifname) elseif typeintf == "" and device ~= "" and proto == "ncm" then ucic:set("network",intf,"device",device_ncm) + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",device_ncm) elseif typeintf == "" and device ~= "" and proto == "qmi" then ucic:set("network",intf,"device",device_qmi) + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",device_qmi) elseif typeintf == "" and device ~= "" and proto == "modemmanager" then ucic:set("network",intf,"device",device_manager) + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",device_manager) + elseif typeintf == "" and ifname ~= "" and proto == "static" then + ucic:set("network",intf,"device",ifname) + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",ifname) end if proto == "pppoe" then ucic:set("network",intf,"pppd_options","persist maxfail 0") From 3d37fa3d0721545da998fb9ba7db44b95a492ed1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Jul 2021 20:21:47 +0200 Subject: [PATCH 0559/2059] Fix mtu support --- .../share/omr/post-tracking.d/post-tracking | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index a637c43d7..403c7bbea 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -834,17 +834,17 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE="interface" uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then - if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + if [ -n "$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + mtu=$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu) + uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu [ -n "$mtu" ] && ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") - elif [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + elif [ -z "$(uci -q get openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then if [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ]; then local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) #local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 8.8.8.8) [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") } @@ -1188,8 +1188,8 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then - mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) + if [ -n "$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu)" ]; then + mtu=$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu) [ -n "$mtu" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 @@ -1252,10 +1252,10 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then - mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) + if [ -n "$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu)" ]; then + mtu=$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu) [ -n "$mtu" ] && { - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu + uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 } elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then From 9a264e50ef6792a14307046807d5e54a41d8f3b8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Jul 2021 20:22:28 +0200 Subject: [PATCH 0560/2059] Fix default device creation --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index fca553290..869ac62dd 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -62,6 +62,8 @@ _setup_wan_interface() { set network.$1.ip4table=wan set network.$1.multipath=$3 set network.$1.defaultroute=0 + set network.$1_dev=device + set network.$1_dev.name=$2 commit network add_list firewall.@zone[1].network=$1 commit firewall From 356ae6494fdf96ff738881d77edda912af4db6e9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Jul 2021 20:22:41 +0200 Subject: [PATCH 0561/2059] Update libqmi --- libqmi/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libqmi/Makefile b/libqmi/Makefile index a10ea0121..fb131b45d 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -10,10 +10,10 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_SOURCE_VERSION:=29fab8a1d4496ca5a1d32bb486013b1868a718ba +PKG_SOURCE_VERSION:=311af7e04cd16a732ec799969b1e8d9c5334ac27 PKG_NAME:=libqmi PKG_VERSION:=1.29.3-$(PKG_SOURCE_VERSION) -PKG_RELEASE:=10 +PKG_RELEASE:=11 PKG_FIXUP:=autoreconf PKG_MAINTAINER:=Nicholas Smith From 61f781aa5d6b796ed36d01222f52169f61c9240a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 1 Aug 2021 08:28:11 +0200 Subject: [PATCH 0562/2059] Better way to use UCI device, still need some work --- .../luasrc/controller/openmptcprouter.lua | 41 ++++++++++++++----- .../share/omr/post-tracking.d/post-tracking | 32 ++++++++++++--- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 1f04b4b88..a0999557d 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -38,6 +38,17 @@ function interface_from_device(dev) return "" end +function uci_device_from_interface(intf) + intfname = ucic:get("network",intf,"device") + deviceuci = "" + ucic:foreach("network", "device", function(s) + if intfname == ucic:get("network",s[".name"],"name") then + deviceuci = s[".name"] + end + end) + return deviceuci +end + function wizard_add() local gostatus = true @@ -292,24 +303,34 @@ function wizard_add() ucic:set("network",intf,"masterintf",masterintf) elseif typeintf == "" and ifname ~= "" and (proto == "static" or proto == "dhcp" or proto == "dhcpv6") then ucic:set("network",intf,"device",ifname) - ucic:set("network",intf .. "_dev","device") - ucic:set("network",intf .. "_dev","name",ifname) + if uci_device_from_interface(intf) == "" then + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",ifname) + end elseif typeintf == "" and device ~= "" and proto == "ncm" then ucic:set("network",intf,"device",device_ncm) - ucic:set("network",intf .. "_dev","device") - ucic:set("network",intf .. "_dev","name",device_ncm) + if uci_device_from_interface(intf) == "" then + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",device_ncm) + end elseif typeintf == "" and device ~= "" and proto == "qmi" then ucic:set("network",intf,"device",device_qmi) - ucic:set("network",intf .. "_dev","device") - ucic:set("network",intf .. "_dev","name",device_qmi) + if uci_device_from_interface(intf) == "" then + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",device_qmi) + end elseif typeintf == "" and device ~= "" and proto == "modemmanager" then ucic:set("network",intf,"device",device_manager) - ucic:set("network",intf .. "_dev","device") - ucic:set("network",intf .. "_dev","name",device_manager) + if uci_device_from_interface(intf) == "" then + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",device_manager) + end elseif typeintf == "" and ifname ~= "" and proto == "static" then ucic:set("network",intf,"device",ifname) - ucic:set("network",intf .. "_dev","device") - ucic:set("network",intf .. "_dev","name",ifname) + if uci_device_from_interface(intf) == "" then + ucic:set("network",intf .. "_dev","device") + ucic:set("network",intf .. "_dev","name",ifname) + end end if proto == "pppoe" then ucic:set("network",intf,"pppd_options","persist maxfail 0") diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 403c7bbea..52de1cfa7 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -2,6 +2,25 @@ SETROUTE=false . /lib/functions/network.sh +find_network_device() { + local device="${1}" + local device_section="" + + check_device() { + local cfg="${1}" + local device="${2}" + + local type name + config_get name "${cfg}" name + + [ "${name}" = "${device}" ] && device_section="${cfg}" + } + + config_load network + config_foreach check_device device "$(uci -q netwok.${device}.device)" + echo "${device_section}" +} + set_route() { local multipath_config_route interface_gw interface_if INTERFACE=$1 @@ -834,8 +853,8 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE="interface" uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then - if [ -n "$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - mtu=$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu) + if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu [ -n "$mtu" ] && ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") @@ -1188,8 +1207,8 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - if [ -n "$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu)" ]; then - mtu=$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu) + if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ]; then + mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) [ -n "$mtu" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 @@ -1252,8 +1271,8 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - if [ -n "$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu)" ]; then - mtu=$(uci -q get network.${OMR_TRACKER_INTERFACE}_dev.mtu) + if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ]; then + mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) [ -n "$mtu" ] && { uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 @@ -1487,6 +1506,7 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter sleep 5 fi + if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then _log "Set firewall on server" /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 From e3a936117fe57baa0114ec7d905f5ffe5c820855 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 7 Aug 2021 18:36:01 +0200 Subject: [PATCH 0563/2059] Update multipath for upstream MPTCP with fullmesh support --- mptcp/files/usr/bin/multipath | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 709be048e..896b169d2 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -117,21 +117,22 @@ if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then else ID=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $3}') IFF=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $4}') + IP=$(ifconfig $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') case $TYPE in "off") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID + [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null exit 0;; "on") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID - ip mptcp endpoint add $IP dev $DEVICE subflow + [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null + ip mptcp endpoint add $IP dev $DEVICE subflow fullmesh exit 0;; "signal") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID - ip mptcp endpoint add $IP dev $DEVICE signal subflow + [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null + ip mptcp endpoint add $IP dev $DEVICE signal subflow fullmesh exit 0;; "backup") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID - ip mptcp endpoint add $IP dev $DEVICE backup + [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null + ip mptcp endpoint add $IP dev $DEVICE backup fullmesh exit 0;; "") case "$IFF" in @@ -139,6 +140,7 @@ else "subflow") echo $DEVICE is in default mode;; "backup") echo $DEVICE is in backup mode;; "signal") echo $DEVICE is in signal mode;; + "fullmesh") echo $DEVICE is in fullmesh mode;; *) echo "$DEVICE Unkown state!" && exit 1;; esac exit 0;; From 898f2f5cad53eee424e4f9ed54190ff51ca28e1d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 7 Aug 2021 18:36:30 +0200 Subject: [PATCH 0564/2059] Support upstream MPTCP --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 52de1cfa7..5fb98c4b4 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1101,7 +1101,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { - if [ "$(sysctl -n net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ]; then + if [ "$(sysctl -qn net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ] || [ "$(sysctl -qn net.mptcp.enabled | tr -d '\n')" = "1" ]; then _log "Multipath $OMR_TRACKER_DEVICE switched to $multipath_config" multipath "$OMR_TRACKER_DEVICE" "$multipath_config" fi From df77ebad4b9de34c66b3f8fd7984b0528d604269 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 10 Aug 2021 14:08:57 +0200 Subject: [PATCH 0565/2059] Fix glorytun-udp default conf --- luci-app-glorytun-udp/root/etc/config/glorytun-udp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-glorytun-udp/root/etc/config/glorytun-udp b/luci-app-glorytun-udp/root/etc/config/glorytun-udp index 6a526ddea..431da357a 100644 --- a/luci-app-glorytun-udp/root/etc/config/glorytun-udp +++ b/luci-app-glorytun-udp/root/etc/config/glorytun-udp @@ -8,7 +8,7 @@ config glorytun-udp 'vpn' option localip '10.255.254.2' option remoteip '10.255.254.1' option mode 'to' - option mode kxtimeout '7d' - option mode timetolerance '10m' - option mode keepalive '25s' - option mode rateauto '0' \ No newline at end of file + option kxtimeout '7d' + option timetolerance '10m' + option keepalive '25s' + option rateauto '0' \ No newline at end of file From d71f338f40989972a72e2963b21e8cec18933f7a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 12 Aug 2021 14:51:07 +0200 Subject: [PATCH 0566/2059] Fix omr-test-speed --- openmptcprouter/files/bin/omr-test-speed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 47fd65cb9..15666e1e9 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -2,7 +2,7 @@ # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : HETZNER=false if [ "$1" = "hetzner" ]; then - hetzner=true + HETZNER=true INTERFACE="$2" else INTERFACE="$1" From 79d39b06b991abe8f26c6f3508f5a1faae184b12 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 19 Aug 2021 14:34:52 +0200 Subject: [PATCH 0567/2059] Update libmbim --- libmbim/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index b9563219e..dcc49e4ac 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -10,10 +10,10 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -PKG_SOURCE_VERSION:=c90c7c5b877de6e413b4833aaf1a42d2d128b051 +PKG_SOURCE_VERSION:=2cc7444cad59fcadd017905235d876367478ec9b PKG_NAME:=libmbim -PKG_VERSION:=1.25.3-$(PKG_SOURCE_VERSION) +PKG_VERSION:=1.26.0-$(PKG_SOURCE_VERSION) PKG_RELEASE:=10 PKG_MAINTAINER:=Nicholas Smith From 4c745f76a1039a21300bbf38f386dac9d6738004 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 19 Aug 2021 14:35:03 +0200 Subject: [PATCH 0568/2059] Update libqmi --- libqmi/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libqmi/Makefile b/libqmi/Makefile index fb131b45d..ecbc6075d 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -10,9 +10,9 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_SOURCE_VERSION:=311af7e04cd16a732ec799969b1e8d9c5334ac27 +PKG_SOURCE_VERSION:=d3bafc485f9a70ea469c0b815d33171a2a88e08a PKG_NAME:=libqmi -PKG_VERSION:=1.29.3-$(PKG_SOURCE_VERSION) +PKG_VERSION:=1.30.0-$(PKG_SOURCE_VERSION) PKG_RELEASE:=11 PKG_FIXUP:=autoreconf From 6318eb9181247464b27a3f4b5f693db9519479d1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 19 Aug 2021 14:35:24 +0200 Subject: [PATCH 0569/2059] Update modemmanager --- modemmanager/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index d16b72d12..52d62b243 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -10,9 +10,9 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_SOURCE_VERSION:=d77d8dff420dc70d6191b67e172e1df5c4e009bf +PKG_SOURCE_VERSION:=a20f2c052329a0d32ea3fee08e13d92b951f84fc PKG_NAME:=modemmanager -PKG_VERSION:=1.16.3-$(PKG_SOURCE_VERSION) +PKG_VERSION:=1.18.0-$(PKG_SOURCE_VERSION) PKG_RELEASE:=10 #PKG_BUILD_DIR:=$(BUILD_DIR)/modemamanager-$ From 57948ddd0342f5299ac9753777bfd31e164188b3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 22 Aug 2021 22:38:50 +0200 Subject: [PATCH 0570/2059] Downgrade libmbim --- libmbim/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index dcc49e4ac..b3d2f3f66 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -PKG_SOURCE_VERSION:=2cc7444cad59fcadd017905235d876367478ec9b +PKG_SOURCE_VERSION:=af15f1cd3c1e586a35c3ff439312b2ae8edbf35e PKG_NAME:=libmbim PKG_VERSION:=1.26.0-$(PKG_SOURCE_VERSION) @@ -25,6 +25,8 @@ PKG_BUILD_PARALLEL:=1 include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk +MESON_BUILD_DIR:=$(PKG_BUILD_DIR)/contrib/meson/openwrt-build + CONFIGURE_ARGS += \ --disable-static \ --disable-gtk-doc \ From ac8c81718b907bacd1689b1ff98039645a873086 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 22 Aug 2021 23:45:03 +0200 Subject: [PATCH 0571/2059] Downgrade libqmi --- libqmi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libqmi/Makefile b/libqmi/Makefile index ecbc6075d..f82556c6e 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_SOURCE_VERSION:=d3bafc485f9a70ea469c0b815d33171a2a88e08a +PKG_SOURCE_VERSION:=45894158da3c55988cef62c5d1afc50f5ef4349a PKG_NAME:=libqmi PKG_VERSION:=1.30.0-$(PKG_SOURCE_VERSION) PKG_RELEASE:=11 From 806bc409808e88031ddd8e214dbc4b77fc727ca4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 Aug 2021 21:35:27 +0200 Subject: [PATCH 0572/2059] Add ttl setting support --- openmptcprouter/files/etc/firewall.ttl | 14 ++++++++++++++ .../files/etc/uci-defaults/1980-omr-firewall | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 openmptcprouter/files/etc/firewall.ttl diff --git a/openmptcprouter/files/etc/firewall.ttl b/openmptcprouter/files/etc/firewall.ttl new file mode 100644 index 000000000..e241dbfca --- /dev/null +++ b/openmptcprouter/files/etc/firewall.ttl @@ -0,0 +1,14 @@ +#!/bin/sh + +. /lib/functions.sh + +_set_ttl() { + device=$(uci -q get network.$1.name) + ttl=$(uci -q get network.$1.ttl) + if [ -n "$ttl" ] && [ -z "$(iptables-save | grep TTL | grep $device)" ]; then + iptables -w -t mangle -I POSTROUTING -o $device -j TTL --ttl-set $ttl 2>&1 >/dev/null + fi +} + +config_load network +config_foreach _set_ttl device \ No newline at end of file diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 9fb334602..fe0cbdf61 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -150,6 +150,14 @@ if [ "$(uci -q get firewall.gre_tunnel)" = "" ]; then commit firewall EOF fi +if [ "$(uci -q get firewall.ttl)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set firewall.ttl=include + set firewall.ttl.path=/etc/firewall.ttl + set firewall.ttl.reload=1 + commit firewall + EOF +fi if [ "$(uci -q get firewall.fwlantovpn)" = "" ]; then uci -q batch <<-EOF >/dev/null set firewall.zone_lan.auto_helper='0' From 8ec66fc304eb83f26813521c9ba6a0467207282d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 Aug 2021 21:46:18 +0200 Subject: [PATCH 0573/2059] little var syntax change --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 869ac62dd..8e27a8332 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -62,8 +62,8 @@ _setup_wan_interface() { set network.$1.ip4table=wan set network.$1.multipath=$3 set network.$1.defaultroute=0 - set network.$1_dev=device - set network.$1_dev.name=$2 + set network.${1}_dev=device + set network.${1}_dev.name=$2 commit network add_list firewall.@zone[1].network=$1 commit firewall From b0e34172050819f48a6ac7662a9fafccc67efa4d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 Aug 2021 21:46:52 +0200 Subject: [PATCH 0574/2059] Add timeout on block lan fw --- openmptcprouter/files/bin/blocklanfw | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/openmptcprouter/files/bin/blocklanfw b/openmptcprouter/files/bin/blocklanfw index cf507eba4..a35694dac 100755 --- a/openmptcprouter/files/bin/blocklanfw +++ b/openmptcprouter/files/bin/blocklanfw @@ -1,6 +1,6 @@ #!/bin/sh ss_rules_fw_drop() { - fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then @@ -8,18 +8,18 @@ ss_rules_fw_drop() { fw=$((fw+1)) fi done - fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done } ss_rules6_fw_drop() { - fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then @@ -27,18 +27,18 @@ ss_rules6_fw_drop() { fw=$((fw+1)) fi done - fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done } v2r_rules_fw_drop() { - fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then @@ -46,33 +46,35 @@ v2r_rules_fw_drop() { fw=$((fw+1)) fi done - fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" + eval "iptables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done } v2ray_rules6_fw_drop() { - fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "ip6tables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fi done - fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" + eval "ip6tables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fi done } +[ -n "$(pgrep blocklanfw)" ] && exit 0 +[ -z "$(iptables-save | grep zone_lan)" ] && exit 0 fw=0 if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then ss_rules6_fw_drop @@ -81,7 +83,7 @@ elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ]; then v2r_rules_fw_drop v2ray_rules6_fw_drop fi -rule=$(fw3 -4 print | grep 'A PREROUTING' | grep zone_lan_prerouting | sed 's/-A PREROUTING/-D PREROUTING/') +rule=$(timeout 1 fw3 -4 print | grep 'A PREROUTING' | grep zone_lan_prerouting | sed 's/-A PREROUTING/-D PREROUTING/') eval "$rule 2>&1 >/dev/null" newrule=$(echo "$rule" | sed 's/-D PREROUTING/-I PREROUTING 1/') eval "$newrule 2>&1 >/dev/null" From 93b673395b974a034310f2fdd34cfab332636aa8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 Aug 2021 21:47:24 +0200 Subject: [PATCH 0575/2059] Add ttl parameter --- .../htdocs/luci-static/resources/tools/network.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/luci-mod-network/htdocs/luci-static/resources/tools/network.js index 8efbd89d4..b08f84058 100644 --- a/luci-mod-network/htdocs/luci-static/resources/tools/network.js +++ b/luci-mod-network/htdocs/luci-static/resources/tools/network.js @@ -662,6 +662,10 @@ return baseclass.extend({ o.placeholder = '0'; o.datatype = 'uinteger'; + o = this.replaceOption(s, 'devadvanced', form.Value, 'ttl', _('Force TTL'), _('Some LTE providers detect tethering by inspecting packet TTL values')); + o.placeholder = '65'; + o.datatype = 'uinteger'; + o = this.replaceOption(s, 'devgeneral', form.Flag, 'ipv6', _('Enable IPv6')); o.migrate = false; o.default = o.enabled; From f7db29485793f1a76313d05f064bd7e56be8cb67 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 Aug 2021 21:48:23 +0200 Subject: [PATCH 0576/2059] Add TTL setting support --- .../luasrc/controller/openmptcprouter.lua | 8 ++++++++ .../luasrc/view/openmptcprouter/wizard.htm | 18 ++++++++++++++---- .../root/usr/libexec/rpcd/openmptcprouter | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index a0999557d..da45601df 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -284,6 +284,7 @@ function wizard_add() local sqmenabled = luci.http.formvalue("cbid.sqm.%s.enabled" % intf) or "0" local multipath = luci.http.formvalue("cbid.network.%s.multipath" % intf) or "on" local lan = luci.http.formvalue("cbid.network.%s.lan" % intf) or "0" + local ttl = luci.http.formvalue("cbid.network.%s.ttl" % intf) or "" if typeintf ~= "" then if typeintf == "normal" then typeintf = "" @@ -338,6 +339,13 @@ function wizard_add() if proto ~= "other" then ucic:set("network",intf,"proto",proto) end + + uci_device = uci_device_from_interface(intf) + if uci_device == "" then + uci_device = intf .. "_dev" + end + ucic:set("network",uci_device,"ttl",ttl) + ucic:set("network",intf,"apn",apn) ucic:set("network",intf,"pincode",pincode) ucic:set("network",intf,"delay",delay) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 13cbffcf2..d3610bd36 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -893,6 +893,16 @@ <% end %> +
    + +
    + +
    +
    + <%:You can force a TTL. Some LTE provider detect tethering by inpecting packet TTL value, setting it to 65 often solve the issue.%> +
    +
    +
    <% local download = "0" @@ -909,7 +919,7 @@ -- end --end %> -
    +
    checked<% end %> /> @@ -919,7 +929,7 @@
    -
    +
    checked<% end %> /> @@ -929,7 +939,7 @@
    -
    +
    @@ -945,7 +955,7 @@ -->
    -
    +
    diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 74543d056..8ebf2905b 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -824,7 +824,7 @@ function interfaces_status() if mArray.openmptcprouter["external_check"] ~= false then mArray.openmptcprouter["proxy_addr"] = ut.trim(sys.exec("curl -s -4 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m " .. timeout .. " " .. check_ipv4_website)) if mArray.openmptcprouter["proxy_addr"] == "" then - mArray.openmptcprouter["proxy_addr"] = ut.trim(sys.exec("curl -s -4 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m " .. timeout .. " ifconfig.co")) + mArray.openmptcprouter["proxy_addr"] = ut.trim(sys.exec("curl -s -4 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m " .. timeout .. " ifconfig.me")) end --mArray.openmptcprouter["ss_addr6"] = sys.exec("curl -s -6 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m 3 http://ipv6.openmptcprouter.com") end From d2d21d7d68878a2b24d7d3babd4f5ff327a360bc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 Aug 2021 21:51:02 +0200 Subject: [PATCH 0577/2059] Add MPTCP upstream support --- dsvpn/files/init | 14 ++++ glorytun/Makefile | 9 +- luci-app-mptcp/luasrc/controller/mptcp.lua | 14 +++- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 84 +++++++++++-------- mptcp/files/etc/init.d/mptcp | 32 ++++--- mptcp/files/usr/bin/multipath | 25 ++++-- openmptcprouter-full/Makefile | 2 +- .../files/etc/init.d/openmptcprouter-vps | 21 +++-- 8 files changed, 137 insertions(+), 64 deletions(-) diff --git a/dsvpn/files/init b/dsvpn/files/init index 1d78ed4be..ca25fd3f0 100755 --- a/dsvpn/files/init +++ b/dsvpn/files/init @@ -29,6 +29,16 @@ validate_section() { 'externalip:string:auto' } +version_over_5_4() { + MAJOR_VERSION=$(uname -r | awk -F '.' '{print $1}') + MINOR_VERSION=$(uname -r | awk -F '.' '{print $2}') + if [ $MAJOR_VERSION -ge 5 ] && [ $MINOR_VERSION -gt 13 ] || [ $MAJOR_VERSION -gt 5 ] ; then + return 0 + else + return 1 + fi +} + start_instance() { local enable key host port dev @@ -58,6 +68,10 @@ start_instance() { _log "starting ${PROG_NAME} ${1} instance $*" + if version_over_5_4; then + PROG="mptcpize run ${PROG}" + fi + procd_open_instance procd_set_param command ${PROG} ${mode} \ diff --git a/glorytun/Makefile b/glorytun/Makefile index 6cd00b7ae..95d7ed3aa 100644 --- a/glorytun/Makefile +++ b/glorytun/Makefile @@ -9,11 +9,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=glorytun -PKG_VERSION:=0.0.35 PKG_RELEASE:=6 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=6d58536f4232fea8eaa10fb60aace8ba11f29ed6 PKG_SOURCE:=glorytun-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/angt/glorytun/releases/download/v$(PKG_VERSION) -PKG_HASH:=49e4d8ea4ff2990300b37947b0bd0da3c8e0985bc6eddf29f4146306188fff64 +PKG_SOURCE_URL:=https://github.com/Ysurac/glorytun.git +PKG_VERSION:=0.0.35-$(PKG_SOURCE_VERSION) + +PKG_FIXUP:=autoreconf include $(INCLUDE_DIR)/package.mk diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index 33f39fcc6..c81458f80 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -210,13 +210,23 @@ function mptcp_monitor_data() luci.http.prepare_content("text/plain") local fullmesh fullmesh = io.popen("cat /proc/net/mptcp_net/snmp") - if fullmesh then + if fullmesh:read() ~= nil then while true do local ln = fullmesh:read("*l") if not ln then break end luci.http.write(ln) luci.http.write("\n") end + else + fullmesh = io.popen("nstat -z") + if fullmesh then + while true do + local ln = fullmesh:read("*l") + if not ln then break end + luci.http.write(ln) + luci.http.write("\n") + end + end end return end @@ -225,7 +235,7 @@ function mptcp_connections_data() luci.http.prepare_content("text/plain") local connections connections = io.popen("multipath -c") - if connections then + if connections:read() ~= nil then while true do local ln = connections:read("*l") if not ln then break end diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index 4b3bdb2b7..b9e7d0630 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -21,56 +21,74 @@ o:value(0, translate("disable")) o = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager"), translate("Default is fullmesh")) o:value("default", translate("default")) o:value("fullmesh", "fullmesh") -o:value("ndiffports", "ndiffports") -o:value("binder", "binder") -if uname.release:sub(1,4) ~= "4.14" then +if uname.release:sub(1,4) ~= "5.14" then + o:value("ndiffports", "ndiffports") + o:value("binder", "binder") + if uname.release:sub(1,4) ~= "4.14" then o:value("netlink", translate("Netlink")) + end end o = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler")) o:value("default", translate("default")) -o:value("roundrobin", "round-robin") -o:value("redundant", "redundant") -if uname.release:sub(1,4) ~= "4.14" then +if uname.release:sub(1,4) ~= "5.14" then + o:value("roundrobin", "round-robin") + o:value("redundant", "redundant") + if uname.release:sub(1,4) ~= "4.14" then o:value("blest", "BLEST") o:value("ecf", "ECF") + end +end +if uname.release:sub(1,4) ~= "5.14" then + o = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) + o.datatype = "uinteger" + o.rmempty = false end -o = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) -o.datatype = "uinteger" -o.rmempty = false o = s:option(ListValue, "congestion", translate("Congestion Control"),translate("Default is cubic")) local availablecong = sys.exec("sysctl -n net.ipv4.tcp_available_congestion_control | xargs -n1 | sort | xargs") for cong in string.gmatch(availablecong, "[^%s]+") do o:value(cong, translate(cong)) end -o = s:option(Value, "mptcp_fullmesh_num_subflows", translate("Fullmesh subflows for each pair of IP addresses")) -o.datatype = "uinteger" -o.rmempty = false -o.default = 1 ---o:depends("mptcp_path_manager","fullmesh") +if uname.release:sub(1,4) == "5.14" then + o = s:option(Value, "mptcp_subflows", translate("specifies the maximum number of additional subflows allowed for each MPTCP connection")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 3 + + o = s:option(Value, "mptcp_add_addr_accepted", translate("specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP connection")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 1 +else + o = s:option(Value, "mptcp_fullmesh_num_subflows", translate("Fullmesh subflows for each pair of IP addresses")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 1 + --o:depends("mptcp_path_manager","fullmesh") -o = s:option(ListValue, "mptcp_fullmesh_create_on_err", translate("Re-create fullmesh subflows after a timeout")) -o:value(1, translate("enable")) -o:value(0, translate("disable")) ---o:depends("mptcp_path_manager","fullmesh") + o = s:option(ListValue, "mptcp_fullmesh_create_on_err", translate("Re-create fullmesh subflows after a timeout")) + o:value(1, translate("enable")) + o:value(0, translate("disable")) + --o:depends("mptcp_path_manager","fullmesh") -o = s:option(Value, "mptcp_ndiffports_num_subflows", translate("ndiffports subflows number")) -o.datatype = "uinteger" -o.rmempty = false -o.default = 1 ---o:depends("mptcp_path_manager","ndiffports") + o = s:option(Value, "mptcp_ndiffports_num_subflows", translate("ndiffports subflows number")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 1 + --o:depends("mptcp_path_manager","ndiffports") -o = s:option(ListValue, "mptcp_rr_cwnd_limited", translate("Fill the congestion window on all subflows for round robin")) -o:value("Y", translate("enable")) -o:value("N", translate("disable")) -o.default = "Y" ---o:depends("mptcp_scheduler","roundrobin") + o = s:option(ListValue, "mptcp_rr_cwnd_limited", translate("Fill the congestion window on all subflows for round robin")) + o:value("Y", translate("enable")) + o:value("N", translate("disable")) + o.default = "Y" + --o:depends("mptcp_scheduler","roundrobin") -o = s:option(Value, "mptcp_rr_num_segments", translate("Consecutive segments that should be sent for round robin")) -o.datatype = "uinteger" -o.rmempty = false -o.default = 1 ---o:depends("mptcp_scheduler","roundrobin") + o = s:option(Value, "mptcp_rr_num_segments", translate("Consecutive segments that should be sent for round robin")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 1 + --o:depends("mptcp_scheduler","roundrobin") +end s = m:section(TypedSection, "interface", translate("Interfaces Settings")) o = s:option(ListValue, "multipath", translate("Multipath TCP"), translate("One interface must be set as master")) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 64bb51d51..7dd629733 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -16,6 +16,9 @@ global_multipath_settings() { config_get multipath globals multipath config_get mptcp_path_manager globals mptcp_path_manager config_get mptcp_scheduler globals mptcp_scheduler + config_get mptcp_subflows globals mptcp_subflows "3" + config_get mptcp_add_addr_accepted globals mptcp_add_addr_accepted "1" + config_get mptcp_add_addr_timeout globals mptcp_add_addr_timeout "120" config_get mptcp_debug globals mptcp_debug config_get congestion globals congestion config_get mptcp_checksum globals mptcp_checksum @@ -29,18 +32,25 @@ global_multipath_settings() { [ "$multipath" = "enable" ] && multipath_status=1 # Global MPTCP configuration - sysctl -qw net.mptcp.mptcp_enabled="$multipath_status" - [ -z "$mptcp_path_manager" ] || sysctl -qw net.mptcp.mptcp_path_manager="$mptcp_path_manager" - [ -z "$mptcp_scheduler" ] || sysctl -qw net.mptcp.mptcp_scheduler="$mptcp_scheduler" + if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then + sysctl -qw net.mptcp.mptcp_enabled="$multipath_status" + [ -z "$mptcp_path_manager" ] || sysctl -qw net.mptcp.mptcp_path_manager="$mptcp_path_manager" + [ -z "$mptcp_scheduler" ] || sysctl -qw net.mptcp.mptcp_scheduler="$mptcp_scheduler" + [ -z "$mptcp_checksum" ] || sysctl -qw net.mptcp.mptcp_checksum="$mptcp_checksum" + [ -z "$mptcp_debug" ] || sysctl -qw net.mptcp.mptcp_debug="$mptcp_debug" + [ -z "$mptcp_syn_retries" ] || sysctl -qw net.mptcp.mptcp_syn_retries="$mptcp_syn_retries" + [ -z "$mptcp_fullmesh_num_subflows" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/num_subflows="$mptcp_fullmesh_num_subflows" + [ -z "$mptcp_fullmesh_create_on_err" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/create_on_err="$mptcp_fullmesh_create_on_err" + [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qw /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" + [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qw /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" + [ -z "$mptcp_rr_num_segments" ] || sysctl -qw /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" + else + sysctl -qw net.mptcp.enabled="$multipath_status" + ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null + [ -z "$mptcp_add_addr_timeout" ] || sysctl -qw net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" + [ -z "$mptcp_checksum" ] || sysctl -qw net.mptcp.checksum_enabled="$mptcp_checksum" + fi [ -z "$congestion" ] || sysctl -qw net.ipv4.tcp_congestion_control="$congestion" - [ -z "$mptcp_checksum" ] || sysctl -qw net.mptcp.mptcp_checksum="$mptcp_checksum" - [ -z "$mptcp_debug" ] || sysctl -qw net.mptcp.mptcp_debug="$mptcp_debug" - [ -z "$mptcp_syn_retries" ] || sysctl -qw net.mptcp.mptcp_syn_retries="$mptcp_syn_retries" - [ -z "$mptcp_fullmesh_num_subflows" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/num_subflows="$mptcp_fullmesh_num_subflows" - [ -z "$mptcp_fullmesh_create_on_err" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/create_on_err="$mptcp_fullmesh_create_on_err" - [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qw /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" - [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qw /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" - [ -z "$mptcp_rr_num_segments" ] || sysctl -qw /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" } interface_macaddr_count() { diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 896b169d2..62e029da5 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -12,8 +12,6 @@ if [ -d "/proc/sys/net/mptcp" ]; then fi else echo "Your device don't support multipath-TCP." - echo "You have to install the pached kernel to use MPTCP." - echo "See http://multipath-tcp.org/ for details" exit 1 fi @@ -22,7 +20,11 @@ case $1 in echo " Multipath-TCP configuration tool" echo "show/update flags:" echo " multipath [device]" - echo " multipath device {on | off | backup | handover}" + if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then + echo " multipath device {on | off | backup }" + else + echo " multipath device {on | off | signal | backup }" + fi echo echo "show established conections: -c" echo "show fullmesh info: -f" @@ -32,14 +34,21 @@ case $1 in echo "will allow a subflow to be established across this interface, but only be used" echo "as backup. Handover-flag indicates that his interface is not used at all (even " echo "no subflow being established), as long as there are other interfaces available." - echo "See http://multipath-tcp.org/ for details" echo exit 0 ;; "-c") - cat /proc/net/mptcp_net/mptcp + if [ -f /proc/net/mptcp_net/mptcp ]; then + cat /proc/net/mptcp_net/mptcp + else + ss -M + fi exit 0;; "-f") - cat /proc/net/mptcp_fullmesh + if [ -f /proc/net/mptcp_fullmesh ]; then + cat /proc/net/mptcp_fullmesh + else + ip mptcp endpoint | grep fullmesh + fi exit 0;; "-k") if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then @@ -65,7 +74,6 @@ case $1 in echo Debugmode: `cat /proc/sys/net/mptcp/mptcp_debug` fi echo - echo See http://multipath-tcp.org/ for details exit 0 ;; "") for ifpath in /sys/class/net/*; do @@ -128,7 +136,8 @@ else exit 0;; "signal") [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null - ip mptcp endpoint add $IP dev $DEVICE signal subflow fullmesh + #ip mptcp endpoint add $IP dev $DEVICE signal subflow fullmesh + ip mptcp endpoint add $IP dev $DEVICE signal exit 0;; "backup") [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 4432da893..022951ded 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -28,7 +28,7 @@ MY_DEPENDS := \ iperf3-ssl luci-app-iperf \ arptables \ bind-dig \ - libnetfilter-conntrack ebtables ebtables-utils ip-full \ + libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ iptables-mod-iface iptables-mod-ipmark iptables-mod-hashlimit iptables-mod-condition iptables-mod-trace iptables-mod-conntrack-extra iptables-mod-account \ kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra conntrack \ iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 kmod-ipt-ipsec \ diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 3104f2f74..2206fe064 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -221,6 +221,8 @@ _get_ss_redir() { [ "$cf_fast_open" = "1" ] && fast_open="true" config_get cf_no_delay $1 no_delay [ "$cf_no_delay" = "1" ] && no_delay="true" + config_get cf_mptcp $1 mptcp + [ "$cf_mptcp" = "1" ] && mptcp="true" } _get_ss_server() { @@ -253,10 +255,12 @@ _set_ss_server_vps() { current_obfs_type="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.obfs_type')" current_fast_open="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.fast_open')" current_no_delay="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.no_delay')" + current_mptcp="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.mptcp')" ebpf="false" fast_open="false" no_delay="false" + mptcp="false" obfs="false" obfs_plugin="v2ray" obfs_type="http" @@ -264,9 +268,9 @@ _set_ss_server_vps() { config_foreach _get_ss_redir ss_redir config_foreach _get_ss_server server - if [ "$current_obfs_plugin" != "$obfs_plugin" ] || [ "$current_obfs_type" != "$obfs_type" ] || [ "$current_port" != "$port" ] || [ "$current_method" != "$method" ] || [ "$current_key" != "$key" ] || [ "$current_ebpf" != "$ebpf" ] || [ "$current_obfs" != "$obfs" ] || [ "$current_fast_open" != "$fast_open" ] || [ "$current_no_delay" != "$no_delay" ]; then + if [ "$current_mptcp" != "$mptcp" ] || [ "$current_obfs_plugin" != "$obfs_plugin" ] || [ "$current_obfs_type" != "$obfs_type" ] || [ "$current_port" != "$port" ] || [ "$current_method" != "$method" ] || [ "$current_key" != "$key" ] || [ "$current_ebpf" != "$ebpf" ] || [ "$current_obfs" != "$obfs" ] || [ "$current_fast_open" != "$fast_open" ] || [ "$current_no_delay" != "$no_delay" ]; then local settings - settings='{"port": '$port',"method":"'$method'","fast_open":'$fast_open',"reuse_port":true,"no_delay":'$no_delay',"mptcp":true,"key":"'$key'","ebpf":'$ebpf',"obfs":'$obfs',"obfs_plugin":"'$obfs_plugin'","obfs_type":"'$obfs_type'"}' + settings='{"port": '$port',"method":"'$method'","fast_open":'$fast_open',"reuse_port":true,"no_delay":'$no_delay',"mptcp":'$mptcp',"key":"'$key'","ebpf":'$ebpf',"obfs":'$obfs',"obfs_plugin":"'$obfs_plugin'","obfs_type":"'$obfs_type'"}' _set_json "shadowsocks" "$settings" fi } @@ -736,7 +740,7 @@ _set_mptcp_vps() { syn_retries="$(uci -q get network.globals.mptcp_syn_retries)" congestion="$(uci -q get network.globals.congestion)" [ -z "$congestion" ] && congestion="bbr" - if [ "$mptcp_enabled_current" != "$mptcp_enabled" ] || [ "$checksum_current" != "$checksum" ] || [ "$path_manager_current" != "$path_manager" ] || [ "$scheduler_current" != "$scheduler" ] || [ "$syn_retries_current" != "$syn_retries" ] || [ "$congestion_control_current" != "$congestion" ]; then + if [ "$mptcp_enabled_current" != "$mptcp_enabled" ] || [ "$checksum_current" != "$checksum" ] || ([ "$path_manager_current" != "" ] && [ "$path_manager_current" != "$path_manager" ]) || ([ "$scheduler_current" != "" ] && [ "$scheduler_current" != "$scheduler" ]) || ([ "$syn_retries_current" != "" ] && [ "$syn_retries_current" != "$syn_retries" ]) || [ "$congestion_control_current" != "$congestion" ]; then settings='{"enabled" : "'$mptcp_enabled'", "checksum": "'$checksum'","path_manager": "'$path_manager'","scheduler": "'$scheduler'","syn_retries": "'$syn_retries'","congestion_control": "'$congestion'"}' echo $(_set_json "mptcp" "$settings") else @@ -1542,13 +1546,18 @@ _set_config_from_vps() { congestion="$(echo "$vps_config" | jsonfilter -q -e '@.network.congestion_control')" uci -q batch <<-EOF >/dev/null set network.globals.multipath=$mptcp_enabled - set network.globals.mptcp_path_manager=$mptcp_path_manager - set network.globals.mptcp_scheduler=$mptcp_scheduler set network.globals.mptcp_checksum=$mptcp_checksum - set network.globals.mptcp_syn_retries=$mptcp_syn_retries set network.globals.congestion=$congestion commit network EOF + if [ "$mptcp_path_manager" != "" ] && [ "$mptcp_scheduler" != "" ] && [ "$mptcp_syn_retries" != "" ]; then + uci -q batch <<-EOF >/dev/null + set network.globals.mptcp_path_manager=$mptcp_path_manager + set network.globals.mptcp_scheduler=$mptcp_scheduler + set network.globals.mptcp_syn_retries=$mptcp_syn_retries + commit network + EOF + fi # Check if server get an IPv6, if not disable IPv6 on OMR vps_ipv6_addr="$(echo "$vps_config" | jsonfilter -q -e '@.network.ipv6')" From 9719abac16ad8350248eddd9c94c19f3fdf9f0b1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 Aug 2021 21:51:28 +0200 Subject: [PATCH 0578/2059] Fix error on dashboard when no data --- .../luci-static/resources/view/dashboard/include/10_router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js index ad9278c53..cf69d4d0e 100644 --- a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js @@ -371,7 +371,7 @@ return baseclass.extend({ release: { title: _('Firmware Version'), - value: (typeof boardinfo.release.description !== "undefined") ? boardinfo.release.description : null + value: (typeof boardinfo.release !== "undefined") ? ((typeof boardinfo.release.description !== "undefined") ? boardinfo.release.description : null) : null } }; From 16dd1b400fdc40da610643d5b294f085893a1504 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Sep 2021 19:50:29 +0200 Subject: [PATCH 0579/2059] Add check fs on each partition --- .../files/etc/uci-defaults/2030-omr-fstab | 17 +++++++++++++++++ .../files/etc/uci-defaults/2060-omr-system | 6 ------ 2 files changed, 17 insertions(+), 6 deletions(-) create mode 100755 openmptcprouter/files/etc/uci-defaults/2030-omr-fstab diff --git a/openmptcprouter/files/etc/uci-defaults/2030-omr-fstab b/openmptcprouter/files/etc/uci-defaults/2030-omr-fstab new file mode 100755 index 000000000..575d0e238 --- /dev/null +++ b/openmptcprouter/files/etc/uci-defaults/2030-omr-fstab @@ -0,0 +1,17 @@ +#!/bin/sh +. /lib/functions.sh + +_set_fsck() { + uci -q batch <<-EOF >/dev/null + set "fstab.$1.enabled=1" + set "fstab.$1.enable_fsck=1" + EOF +} + +/sbin/block detect > /etc/config/fstab +uci -q set fstab.@global[0].check_fs='1' +config_load fstab +config_foreach _set_fsck mount +uci -q commit fstab + +exit 0 diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 787763c26..902dae6dc 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -17,12 +17,6 @@ if [ "$(uci -q get rpcd.@rpcd[0].socket)" != "/var/run/ubus/ubus.sock" ]; then EOF fi -/sbin/block detect > /etc/config/fstab -uci -q batch <<-EOF >/dev/null - set fstab.@global[0].check_fs='1' - commit fstab -EOF - [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep raspberry)" ] && [ "$(uci -q get openmptcprouter.settings.scaling_governor)" != "performance" ] && { # force CPU speed for RPI uci -q set openmptcprouter.settings.scaling_min_freq=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq | tr -d "\n") From 3389d09c23f07853f5be888cb840668aa4c15e6c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Sep 2021 19:51:18 +0200 Subject: [PATCH 0580/2059] Add MPTCP upstream support to MPTCP support detection --- .../root/bin/omr-mptcp-intf | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/luci-app-openmptcprouter/root/bin/omr-mptcp-intf b/luci-app-openmptcprouter/root/bin/omr-mptcp-intf index d2a74b245..8fac4468b 100755 --- a/luci-app-openmptcprouter/root/bin/omr-mptcp-intf +++ b/luci-app-openmptcprouter/root/bin/omr-mptcp-intf @@ -12,9 +12,17 @@ get_mptcp_from_server() { get_mptcp() { serverip=$1 if [ "$(echo $serverip | grep :)" ]; then - support="$(curl -s -k -6 -m ${timeout} --interface $intf https://[$serverip]:$serverport/mptcpsupport)" + if [ -f /proc/sys/net/mptcp/enabled ]; then + support="$(mptcpize run curl -s -k -6 -m ${timeout} --interface $intf https://[$serverip]:$serverport/mptcpsupport)" + else + support="$(curl -s -k -6 -m ${timeout} --interface $intf https://[$serverip]:$serverport/mptcpsupport)" + fi else - support="$(curl -s -k -4 -m ${timeout} --interface $intf https://$serverip:$serverport/mptcpsupport)" + if [ -f /proc/sys/net/mptcp/enabled ]; then + support="$(mptcpize run curl -s -k -4 -m ${timeout} --interface $intf https://$serverip:$serverport/mptcpsupport)" + else + support="$(curl -s -k -4 -m ${timeout} --interface $intf https://$serverip:$serverport/mptcpsupport)" + fi fi [ -n "$support" ] && { support=$(echo $support | jsonfilter -e '@.mptcp') @@ -56,8 +64,10 @@ get_mptcp_from_website6() { support="" config_load openmptcprouter config_foreach get_mptcp_from_server server -[ -z "$support" ] && [ -n "$(ip -4 a show dev $intf)" ] && get_mptcp_from_website -[ -z "$support" ] && [ -n "$(ip -6 a show dev $intf)" ] && get_mptcp_from_website6 +if [ ! -f /proc/sys/net/mptcp/enabled ] && [ -z "$support" ]; then + [ -n "$(ip -4 a show dev $intf)" ] && get_mptcp_from_website + [ -n "$(ip -6 a show dev $intf)" ] && get_mptcp_from_website6 +fi if [ "$support" = "working" ]; then echo "MPTCP enabled" elif [ "$support" = "not working" ]; then From fb3a2958babd5e5c09d34e783527196603be7f79 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Sep 2021 19:52:33 +0200 Subject: [PATCH 0581/2059] Use OpenMPTCProuter Shadowsocks fork --- shadowsocks-libev/Makefile | 11 +- shadowsocks-libev/patches/020-NOCRYPTO.patch | 632 ------------------- 2 files changed, 5 insertions(+), 638 deletions(-) delete mode 100644 shadowsocks-libev/patches/020-NOCRYPTO.patch diff --git a/shadowsocks-libev/Makefile b/shadowsocks-libev/Makefile index 00c12c7f5..78fdf4c30 100644 --- a/shadowsocks-libev/Makefile +++ b/shadowsocks-libev/Makefile @@ -14,12 +14,11 @@ include $(TOPDIR)/rules.mk # - check if default mode has changed from being tcp_only # PKG_NAME:=shadowsocks-libev -PKG_VERSION:=3.3.5 -PKG_RELEASE:=10 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$(PKG_VERSION) -PKG_HASH:=cfc8eded35360f4b67e18dc447b0c00cddb29cc57a3cec48b135e5fb87433488 +PKG_RELEASE:=11 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/Ysurac/shadowsocks-libev.git +PKG_SOURCE_VERSION:=bf44f710b4a0c451809279383acc847995c35ead +PKG_VERSION:=3.3.5-$(PKG_SOURCE_VERSION) PKG_MAINTAINER:=Ycarus (Yannick Chabanois) diff --git a/shadowsocks-libev/patches/020-NOCRYPTO.patch b/shadowsocks-libev/patches/020-NOCRYPTO.patch deleted file mode 100644 index fbe0cc883..000000000 --- a/shadowsocks-libev/patches/020-NOCRYPTO.patch +++ /dev/null @@ -1,632 +0,0 @@ -From e9fc31e06453cacf662448663f0c79ae4878fed5 Mon Sep 17 00:00:00 2001 -From: Fejes Ferenc -Date: Mon, 31 Jul 2017 12:08:11 +0200 -Subject: [PATCH 01/17] No encryption initial implementation - -Set cipher az "none" to disable encryption. ---- - completions/bash/ss-local | 2 +- - completions/bash/ss-manager | 2 +- - completions/bash/ss-redir | 2 +- - completions/bash/ss-server | 4 ++-- - completions/bash/ss-tunnel | 2 +- - completions/zsh/_ss-local | 2 +- - completions/zsh/_ss-manager | 2 +- - completions/zsh/_ss-redir | 2 +- - completions/zsh/_ss-server | 2 +- - completions/zsh/_ss-tunnel | 2 +- - doc/shadowsocks-libev.asciidoc | 4 +++- - doc/ss-local.asciidoc | 4 +++- - doc/ss-manager.asciidoc | 4 +++- - doc/ss-redir.asciidoc | 4 +++- - doc/ss-server.asciidoc | 4 +++- - doc/ss-tunnel.asciidoc | 4 +++- - src/Makefile.am | 3 ++- - src/crypto.c | 15 +++++++++++++++ - src/noencrypt.c | 25 +++++++++++++++++++++++++ - src/noencrypt.h | 11 +++++++++++ - src/server.c | 2 +- - src/stream.c | 17 ++++++++--------- - src/utils.c | 2 +- - 27 files changed, 100 insertions(+), 37 deletions(-) - create mode 100644 src/noencrypt.c - create mode 100644 src/noencrypt.h - -diff --git a/completions/bash/ss-local b/completions/bash/ss-local -index 0186ccc4..57fa318b 100644 ---- a/completions/bash/ss-local -+++ b/completions/bash/ss-local -@@ -2,7 +2,7 @@ _ss_local() - { - local cur prev opts ciphers - opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -v -h --reuse-port --fast-open --acl --mtu --mptcp --no-delay --key --plugin --plugin-opts --help' -- ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' -+ ciphers='none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' - cur=${COMP_WORDS[COMP_CWORD]} - prev="${COMP_WORDS[COMP_CWORD-1]}" - case "$prev" in -diff --git a/completions/bash/ss-manager b/completions/bash/ss-manager -index d3168a3b..de13c9e9 100644 ---- a/completions/bash/ss-manager -+++ b/completions/bash/ss-manager -@@ -2,7 +2,7 @@ _ss_manager() - { - local cur prev opts ciphers - opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -v -h --reuse-port --manager-address --executable --mtu --mptcp --plugin --plugin-opts --help' -- ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' -+ ciphers='none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' - cur=${COMP_WORDS[COMP_CWORD]} - prev="${COMP_WORDS[COMP_CWORD-1]}" - case "$prev" in -diff --git a/completions/bash/ss-redir b/completions/bash/ss-redir -index 9a14efe8..fdc7b21e 100644 ---- a/completions/bash/ss-redir -+++ b/completions/bash/ss-redir -@@ -2,7 +2,7 @@ _ss_redir() - { - local cur prev opts ciphers - opts='-s -p -l -k -m -a -f -t -c -n -b -u -U -T -v -h --reuse-port --mtu --mptcp --key --plugin --plugin-opts --help' -- ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' -+ ciphers='none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' - cur=${COMP_WORDS[COMP_CWORD]} - prev="${COMP_WORDS[COMP_CWORD-1]}" - case "$prev" in -diff --git a/completions/bash/ss-server b/completions/bash/ss-server -index cec983ce..d8f3c298 100644 ---- a/completions/bash/ss-server -+++ b/completions/bash/ss-server -@@ -1,8 +1,8 @@ - _ss_server() - { - local cur prev opts ciphers -- opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -6 -d -v -h --reuse-port --fast-open --acl --manager-address --mtu --mptcp --no-delay --key --plugin --plugin-opts --help' -- ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' -+ opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -6 -d -v -h --reuse-port --fast-open --acl --manager-address --mtu --mptcp --key --plugin --plugin-opts --help' -+ ciphers='none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' - COMPREPLY=() - cur=${COMP_WORDS[COMP_CWORD]} - prev="${COMP_WORDS[COMP_CWORD-1]}" -diff --git a/completions/bash/ss-tunnel b/completions/bash/ss-tunnel -index 707dc7a9..2e119098 100644 ---- a/completions/bash/ss-tunnel -+++ b/completions/bash/ss-tunnel -@@ -2,7 +2,7 @@ _ss_tunnel() - { - local cur prev opts ciphers - opts='-s -p -l -k -m -a -f -t -c -n -i -b -u -U -L -v -h --reuse-port --mtu --mptcp --key --plugin --plugin-opts --help' -- ciphers='rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' -+ ciphers='none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf' - cur=${COMP_WORDS[COMP_CWORD]} - prev="${COMP_WORDS[COMP_CWORD-1]}" - compopt +o nospace -diff --git a/completions/zsh/_ss-local b/completions/zsh/_ss-local -index c56ed521..8b12b767 100644 ---- a/completions/zsh/_ss-local -+++ b/completions/zsh/_ss-local -@@ -1,7 +1,7 @@ - #compdef ss-local - - local ciphers --ciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' -+ciphers='(none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' - - _arguments "-h::" \ - "-s:server host:_hosts" \ -diff --git a/completions/zsh/_ss-manager b/completions/zsh/_ss-manager -index 3e65f6c8..66c101a1 100644 ---- a/completions/zsh/_ss-manager -+++ b/completions/zsh/_ss-manager -@@ -1,7 +1,7 @@ - #compdef ss-manager - - local ciphers --ciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' -+ciphers='(none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' - - _arguments "-h::" \ - "-s:server host:_hosts" \ -diff --git a/completions/zsh/_ss-redir b/completions/zsh/_ss-redir -index 4f3b065e..6ef867f3 100644 ---- a/completions/zsh/_ss-redir -+++ b/completions/zsh/_ss-redir -@@ -1,7 +1,7 @@ - #compdef ss-redir - - local ciphers --ciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' -+ciphers='(none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' - - _arguments "-h::" \ - "-s:server host:_hosts" \ -diff --git a/completions/zsh/_ss-server b/completions/zsh/_ss-server -index 8d9f4316..76bae33c 100644 ---- a/completions/zsh/_ss-server -+++ b/completions/zsh/_ss-server -@@ -1,7 +1,7 @@ - #compdef ss-server - - local ciphers --ciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' -+ciphers='(none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' - - _arguments "-h::" \ - "-s:server host:_hosts" \ -diff --git a/completions/zsh/_ss-tunnel b/completions/zsh/_ss-tunnel -index 5a269900..248451f9 100644 ---- a/completions/zsh/_ss-tunnel -+++ b/completions/zsh/_ss-tunnel -@@ -1,7 +1,7 @@ - #compdef ss-tunnel - - local ciphers --ciphers='(rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' -+ciphers='(none rc4-md5 aes-128-gcm aes-192-gcm aes-256-gcm aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr camellia-128-cfb camellia-192-cfb camellia-256-cfb bf-cfb chacha20-ietf-poly1305 xchacha20-ietf-poly1305 salsa20 chacha20 chacha20-ietf)' - - _arguments "-h::" \ - "-s:server host:_hosts" \ -diff --git a/doc/shadowsocks-libev.asciidoc b/doc/shadowsocks-libev.asciidoc -index 5a62f669..f0844a3f 100644 ---- a/doc/shadowsocks-libev.asciidoc -+++ b/doc/shadowsocks-libev.asciidoc -@@ -54,7 +54,9 @@ Set the key directly. The key should be encoded with URL-safe Base64. - Not available in manager mode. - - -m :: --Set the cipher. -+Set the cipher or turn off the encryption. -++ -+To disable encryption use `none` as cipher. - + - *Shadowsocks-libev* accepts 18 different ciphers: - + -diff --git a/doc/ss-local.asciidoc b/doc/ss-local.asciidoc -index 931fcd54..82439e0f 100644 ---- a/doc/ss-local.asciidoc -+++ b/doc/ss-local.asciidoc -@@ -49,7 +49,9 @@ Set the password. The server and the client should use the same password. - Set the key directly. The key should be encoded with URL-safe Base64. - - -m :: --Set the cipher. -+Set the cipher or turn off the encryption. -++ -+To disable encryption use `none` as cipher. - + - *Shadowsocks-libev* accepts 18 different ciphers: - + -diff --git a/doc/ss-manager.asciidoc b/doc/ss-manager.asciidoc -index f344cffa..bc00cac0 100644 ---- a/doc/ss-manager.asciidoc -+++ b/doc/ss-manager.asciidoc -@@ -41,7 +41,9 @@ Set the server's hostname or IP. - Set the password. The server and the client should use the same password. - - -m :: --Set the cipher. -+Set the cipher or turn off the encryption. -++ -+To disable encryption use `none` as cipher. - + - *Shadowsocks-libev* accepts 18 different ciphers: - + -diff --git a/doc/ss-redir.asciidoc b/doc/ss-redir.asciidoc -index f9195b31..6a0207f0 100644 ---- a/doc/ss-redir.asciidoc -+++ b/doc/ss-redir.asciidoc -@@ -48,7 +48,9 @@ Set the password. The server and the client should use the same password. - Set the key directly. The key should be encoded with URL-safe Base64. - - -m :: --Set the cipher. -+Set the cipher or turn off the encryption. -++ -+To disable encryption use `none` as cipher. - + - *Shadowsocks-libev* accepts 18 different ciphers: - + -diff --git a/doc/ss-server.asciidoc b/doc/ss-server.asciidoc -index 866f0605..0fbacb0c 100644 ---- a/doc/ss-server.asciidoc -+++ b/doc/ss-server.asciidoc -@@ -46,7 +46,9 @@ Set the password. The server and the client should use the same password. - Set the key directly. The key should be encoded with URL-safe Base64. - - -m :: --Set the cipher. -+Set the cipher or turn off the encryption. -++ -+To disable encryption use `none` as cipher. - + - *Shadowsocks-libev* accepts 18 different ciphers: - + -diff --git a/doc/ss-tunnel.asciidoc b/doc/ss-tunnel.asciidoc -index b4b3e6ec..96ab1d5e 100644 ---- a/doc/ss-tunnel.asciidoc -+++ b/doc/ss-tunnel.asciidoc -@@ -48,7 +48,9 @@ Set the password. The server and the client should use the same password. - Set the key directly. The key should be encoded with URL-safe Base64. - - -m :: --Set the cipher. -+Set the cipher or turn off the encryption. -++ -+To disable encryption use `none` as cipher. - + - *Shadowsocks-libev* accepts 18 different ciphers: - + -diff --git a/src/Makefile.am b/src/Makefile.am -index dcc5fd9b..2e689b7a 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -31,7 +31,8 @@ crypto_src = crypto.c \ - aead.c \ - stream.c \ - ppbloom.c \ -- base64.c -+ base64.c \ -+ noencrypt.c - - plugin_src = plugin.c - -diff --git a/src/crypto.c b/src/crypto.c -index df608cea..8c9044f6 100644 ---- a/src/crypto.c -+++ b/src/crypto.c -@@ -41,6 +41,7 @@ - #include "aead.h" - #include "utils.h" - #include "ppbloom.h" -+#include "noencrypt.h" - - int - balloc(buffer_t *ptr, size_t capacity) -@@ -144,6 +145,20 @@ crypto_init(const char *password, const char *key, const char *method) - #endif - - if (method != NULL) { -+ if (strncmp(method, "none", 4) == 0) { -+ crypto_t *crypto = (crypto_t *) malloc(sizeof(crypto_t)); -+ crypto_t temp = { -+ .chiper = NULL, -+ .encrypt_all = &none_stream_all, -+ .decrypt_all = &none_stream_all, -+ .encrypt = &none_stream, -+ .decrypt = &none_stream, -+ .ctx_init = &none_stream_ctx_init, -+ .ctx_release = &none_stream_ctx_release, -+ }; -+ memcpy(crypto, &temp, sizeof(crypto_t)); -+ return crypto; -+ } - for (i = 0; i < STREAM_CIPHER_NUM; i++) - if (strcmp(method, supported_stream_ciphers[i]) == 0) { - m = i; -diff --git a/src/noencrypt.c b/src/noencrypt.c -new file mode 100644 -index 00000000..1804aaa5 ---- /dev/null -+++ b/src/noencrypt.c -@@ -0,0 +1,25 @@ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include "noencrypt.h" -+ -+int -+none_stream (buffer_t *chipertext, chiper_ctx_t *chiper_ctx, size_t capacity) { -+ return CRYPTO_OK; -+} -+ -+int -+none_stream_all (buffer_t *plaintext, chiper_t *chiper, size_t capacity) { -+ return CRYPTO_OK; -+} -+ -+void -+none_stream_ctx_init (chiper_t *chiper, chiper_ctx_t *chiper_ctx, int enc) { -+ ; -+} -+ -+void -+plain_stream_ctx_release (chiper_ctx_t *chiper_ctx) { -+ ; -+} -\ No newline at end of file -diff --git a/src/noencrypt.h b/src/noencrypt.h -new file mode 100644 -index 00000000..38057da7 ---- /dev/null -+++ b/src/noencrypt.h -@@ -0,0 +1,11 @@ -+#ifndef _NOENCRYPT_H -+#define _NOENCRYPT_H -+ -+#include "noencrypt.h" -+ -+int none_stream_all(buffer_t *, cipher_t *, size_t); -+int none_stream(buffer_t *, cipher_ctx_t *, size_t); -+int none_stream_ctx_init(cipher_t *, cipher_ctx_t *, int); -+int none_stream_ctx_release(cipher_ctx_t *); -+ -+#endif _NOENCRYPT_H -\ No newline at end of file -diff --git a/src/server.c b/src/server.c -index 3132c4d4..5fa87c28 100644 ---- a/src/server.c -+++ b/src/server.c -@@ -1710,7 +1710,7 @@ main(int argc, char **argv) - } - - if (server_num == 0 || server_port == NULL -- || (password == NULL && key == NULL)) { -+ || (strncmp(method, "none", 4) && password == NULL && key == NULL)) { - usage(); - exit(EXIT_FAILURE); - } -diff --git a/src/stream.c b/src/stream.c -index 5196c9ef..12c8be33 100644 ---- a/src/stream.c -+++ b/src/stream.c -@@ -72,8 +72,7 @@ - * - */ - --#define NONE -1 --#define TABLE 0 -+#define NONE 0 - #define RC4 1 - #define RC4_MD5 2 - #define AES_128_CFB 3 -@@ -96,7 +95,7 @@ - #define CHACHA20IETF 20 - - const char *supported_stream_ciphers[STREAM_CIPHER_NUM] = { -- "table", -+ "none", - "rc4", - "rc4-md5", - "aes-128-cfb", -@@ -198,7 +197,7 @@ cipher_key_size(const cipher_t *cipher) - const cipher_kt_t * - stream_get_cipher_type(int method) - { -- if (method <= TABLE || method >= STREAM_CIPHER_NUM) { -+ if (method <= NONE || method >= STREAM_CIPHER_NUM) { - LOGE("stream_get_cipher_type(): Illegal method"); - return NULL; - } -@@ -224,7 +223,7 @@ stream_get_cipher_type(int method) - void - stream_cipher_ctx_init(cipher_ctx_t *ctx, int method, int enc) - { -- if (method <= TABLE || method >= STREAM_CIPHER_NUM) { -+ if (method <= NONE || method >= STREAM_CIPHER_NUM) { - LOGE("stream_ctx_init(): Illegal method"); - return; - } -@@ -622,7 +621,7 @@ stream_ctx_init(cipher_t *cipher, cipher_ctx_t *cipher_ctx, int enc) - cipher_t * - stream_key_init(int method, const char *pass, const char *key) - { -- if (method <= TABLE || method >= STREAM_CIPHER_NUM) { -+ if (method <= NONE || method >= STREAM_CIPHER_NUM) { - LOGE("cipher->key_init(): Illegal method"); - return NULL; - } -@@ -666,9 +665,9 @@ stream_key_init(int method, const char *pass, const char *key) - cipher_t * - stream_init(const char *pass, const char *key, const char *method) - { -- int m = TABLE; -+ int m = NONE; - if (method != NULL) { -- for (m = TABLE; m < STREAM_CIPHER_NUM; m++) -+ for (m = NONE; m < STREAM_CIPHER_NUM; m++) - if (strcmp(method, supported_stream_ciphers[m]) == 0) { - break; - } -@@ -677,7 +676,7 @@ stream_init(const char *pass, const char *key, const char *method) - m = RC4_MD5; - } - } -- if (m == TABLE) { -+ if (m == NONE) { - LOGE("Table is deprecated"); - return NULL; - } -diff --git a/src/utils.c b/src/utils.c -index b9142e7e..70bc99bb 100644 ---- a/src/utils.c -+++ b/src/utils.c -@@ -289,7 +289,7 @@ usage() - printf( - " -k Password of your remote server.\n"); - printf( -- " -m Encrypt method: rc4-md5, \n"); -+ " -m Encrypt method: none, rc4-md5, \n"); - printf( - " aes-128-gcm, aes-192-gcm, aes-256-gcm,\n"); - printf( - -From 4cbca114514b06a5cbc6c2bab21929fe861852fb Mon Sep 17 00:00:00 2001 -From: Fejes Ferenc -Date: Mon, 31 Jul 2017 12:39:58 +0200 -Subject: [PATCH 06/17] Fixes - ---- - src/crypto.c | 2 +- - src/noencrypt.h | 6 +++--- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/crypto.c b/src/crypto.c -index 8c9044f6..98edee4f 100644 ---- a/src/crypto.c -+++ b/src/crypto.c -@@ -148,7 +148,7 @@ crypto_init(const char *password, const char *key, const char *method) - if (strncmp(method, "none", 4) == 0) { - crypto_t *crypto = (crypto_t *) malloc(sizeof(crypto_t)); - crypto_t temp = { -- .chiper = NULL, -+ .cipher = NULL, - .encrypt_all = &none_stream_all, - .decrypt_all = &none_stream_all, - .encrypt = &none_stream, -diff --git a/src/noencrypt.h b/src/noencrypt.h -index 38057da7..206c18de 100644 ---- a/src/noencrypt.h -+++ b/src/noencrypt.h -@@ -5,7 +5,7 @@ - - int none_stream_all(buffer_t *, cipher_t *, size_t); - int none_stream(buffer_t *, cipher_ctx_t *, size_t); --int none_stream_ctx_init(cipher_t *, cipher_ctx_t *, int); --int none_stream_ctx_release(cipher_ctx_t *); -+void none_stream_ctx_init(cipher_t *, cipher_ctx_t *, int); -+void none_stream_ctx_release(cipher_ctx_t *); - --#endif _NOENCRYPT_H -\ No newline at end of file -+#endif //_NOENCRYPT_H -\ No newline at end of file - -From 07607127317804319b0cb358080516ee99cf30e0 Mon Sep 17 00:00:00 2001 -From: Fejes Ferenc -Date: Mon, 31 Jul 2017 12:57:46 +0200 -Subject: [PATCH 08/17] fixed typenames - ---- - src/noencrypt.c | 8 ++++---- - src/noencrypt.h | 2 +- - 3 files changed, 7 insertions(+), 6 deletions(-) - -diff --git a/src/noencrypt.c b/src/noencrypt.c -index 1804aaa5..114c908d 100644 ---- a/src/noencrypt.c -+++ b/src/noencrypt.c -@@ -5,21 +5,21 @@ - #include "noencrypt.h" - - int --none_stream (buffer_t *chipertext, chiper_ctx_t *chiper_ctx, size_t capacity) { -+none_stream (buffer_t *chipertext, cipher_ctx_t *chiper_ctx, size_t capacity) { - return CRYPTO_OK; - } - - int --none_stream_all (buffer_t *plaintext, chiper_t *chiper, size_t capacity) { -+none_stream_all (buffer_t *plaintext, cipher_t *chiper, size_t capacity) { - return CRYPTO_OK; - } - - void --none_stream_ctx_init (chiper_t *chiper, chiper_ctx_t *chiper_ctx, int enc) { -+none_stream_ctx_init (chiper_t *chiper, cipher_ctx_t *chiper_ctx, int enc) { - ; - } - - void --plain_stream_ctx_release (chiper_ctx_t *chiper_ctx) { -+plain_stream_ctx_release (cipher_ctx_t *chiper_ctx) { - ; - } -\ No newline at end of file -diff --git a/src/noencrypt.h b/src/noencrypt.h -index 206c18de..48954115 100644 ---- a/src/noencrypt.h -+++ b/src/noencrypt.h -@@ -1,7 +1,7 @@ - #ifndef _NOENCRYPT_H - #define _NOENCRYPT_H - --#include "noencrypt.h" -+#include "crypto.h" - - int none_stream_all(buffer_t *, cipher_t *, size_t); - int none_stream(buffer_t *, cipher_ctx_t *, size_t); - -From 4d1c15ba49a58359234174e775b509efa07bbb95 Mon Sep 17 00:00:00 2001 -From: Fejes Ferenc -Date: Mon, 31 Jul 2017 13:14:53 +0200 -Subject: [PATCH 09/17] small fix - ---- - src/noencrypt.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/noencrypt.c b/src/noencrypt.c -index 114c908d..8ddcaabb 100644 ---- a/src/noencrypt.c -+++ b/src/noencrypt.c -@@ -15,7 +15,7 @@ none_stream_all (buffer_t *plaintext, cipher_t *chiper, size_t capacity) { - } - - void --none_stream_ctx_init (chiper_t *chiper, cipher_ctx_t *chiper_ctx, int enc) { -+none_stream_ctx_init (cipher_t *chiper, cipher_ctx_t *chiper_ctx, int enc) { - ; - } - - -From 01294c25e8e02c399a9df17a13758e7f9f16ed8f Mon Sep 17 00:00:00 2001 -From: Fejes Ferenc -Date: Mon, 31 Jul 2017 13:22:44 +0200 -Subject: [PATCH 11/17] Do not optimize away the unused variablas - ---- - src/noencrypt.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/noencrypt.c b/src/noencrypt.c -index 8ddcaabb..e9bf017d 100644 ---- a/src/noencrypt.c -+++ b/src/noencrypt.c -@@ -6,20 +6,22 @@ - - int - none_stream (buffer_t *chipertext, cipher_ctx_t *chiper_ctx, size_t capacity) { -+ (void) chipertext; (void) chiper_ctx; (void) capacity; - return CRYPTO_OK; - } - - int - none_stream_all (buffer_t *plaintext, cipher_t *chiper, size_t capacity) { -+ (void) plaintext; (void) chiper; (void) capacity; - return CRYPTO_OK; - } - - void - none_stream_ctx_init (cipher_t *chiper, cipher_ctx_t *chiper_ctx, int enc) { -- ; -+ (void) chiper; (void) chiper_ctx; (void) enc; - } - - void - plain_stream_ctx_release (cipher_ctx_t *chiper_ctx) { -- ; -+ (void) chiper_ctx; - } -\ No newline at end of file - -From 1b0c88066515ea496c00049cb5aff92decdbe05a Mon Sep 17 00:00:00 2001 -From: Fejes Ferenc -Date: Mon, 31 Jul 2017 13:39:57 +0200 -Subject: [PATCH 13/17] code fix - ---- - src/noencrypt.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/noencrypt.c b/src/noencrypt.c -index e9bf017d..76253647 100644 ---- a/src/noencrypt.c -+++ b/src/noencrypt.c -@@ -22,6 +22,6 @@ none_stream_ctx_init (cipher_t *chiper, cipher_ctx_t *chiper_ctx, int enc) { - } - - void --plain_stream_ctx_release (cipher_ctx_t *chiper_ctx) { -+none_stream_ctx_release (cipher_ctx_t *chiper_ctx) { - (void) chiper_ctx; - } -\ No newline at end of file From 1121b870ee9980c2555d7f2632d443ee23872201 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Sep 2021 19:53:25 +0200 Subject: [PATCH 0582/2059] Only set mptcp defaults when needed --- mptcp/files/etc/uci-defaults/mptcp-defaults | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mptcp/files/etc/uci-defaults/mptcp-defaults b/mptcp/files/etc/uci-defaults/mptcp-defaults index 9dddade8f..97235fb8d 100755 --- a/mptcp/files/etc/uci-defaults/mptcp-defaults +++ b/mptcp/files/etc/uci-defaults/mptcp-defaults @@ -8,6 +8,9 @@ if [ "$(uci -q get network.globals.mptcp_path_manager)" = "" ]; then set network.globals.mptcp_checksum=0 set network.globals.mptcp_debug=0 set network.globals.mptcp_syn_retries=2 + set network.globals.mptcp_subflows=3 + set network.globals.mptcp_add_addr_accepted=1 + set network.globals.mptcp_add_addr_timeout=120 commit network EOF fi @@ -53,6 +56,15 @@ if [ "$(uci -q show network.globals | grep mptcp_fullmesh)" = "" ]; then commit network EOF fi +if [ "$(uci -q get network.globals.mptcp_subflows)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set network.globals.mptcp_subflows=3 + set network.globals.mptcp_add_addr_accepted=1 + set network.globals.mptcp_add_addr_timeout=120 + commit network + EOF +fi + uci -q batch <<-EOF >/dev/null delete ucitrack.@mptcp[-1] add ucitrack mptcp From 478f9274c3ca0b435ecf55a143acfa0850a916e7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 3 Sep 2021 12:58:22 +0200 Subject: [PATCH 0583/2059] Try to fix compilation patch for bpi-r2 --- iperf3/patches/remove-in6_flowlabel_req.patch | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/iperf3/patches/remove-in6_flowlabel_req.patch b/iperf3/patches/remove-in6_flowlabel_req.patch index 3d2be694f..539f9c3c8 100644 --- a/iperf3/patches/remove-in6_flowlabel_req.patch +++ b/iperf3/patches/remove-in6_flowlabel_req.patch @@ -1,24 +1,25 @@ --- a/src/flowlabel.h 2021-06-24 13:26:33.142463630 +0200 +++ b/src/flowlabel.h 2021-06-24 13:27:45.669235179 +0200 -@@ -37,21 +37,6 @@ +@@ -37,21 +37,21 @@ conflicts with "netinet/in.h" . */ -#ifndef __ANDROID__ --struct in6_flowlabel_req --{ -- struct in6_addr flr_dst; -- __u32 flr_label; -- __u8 flr_action; -- __u8 flr_share; -- __u16 flr_flags; -- __u16 flr_expires; -- __u16 flr_linger; -- __u32 __flr_pad; -- /* Options in format of IPV6_PKTOPTIONS */ --}; --#endif -- ++#ifndef _LINUX_IN6_H + struct in6_flowlabel_req + { + struct in6_addr flr_dst; + __u32 flr_label; + __u8 flr_action; + __u8 flr_share; + __u16 flr_flags; + __u16 flr_expires; + __u16 flr_linger; + __u32 __flr_pad; + /* Options in format of IPV6_PKTOPTIONS */ + }; + #endif + #define IPV6_FL_A_GET 0 #define IPV6_FL_A_PUT 1 #define IPV6_FL_A_RENEW 2 From d4c66ce49a16c7a19c14531384d32c45fc4cb436 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 14 Sep 2021 09:44:57 +0200 Subject: [PATCH 0584/2059] Fix DSVPN port --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index da45601df..27bae5b7f 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -880,7 +880,7 @@ function wizard_add() local dsvpn_key = luci.http.formvalue("dsvpn_key") if dsvpn_key ~= "" then - ucic:set("dsvpn","vpn","port","65011") + ucic:set("dsvpn","vpn","port","65401") ucic:set("dsvpn","vpn","key",dsvpn_key) ucic:set("dsvpn","vpn","localip","10.255.251.2") ucic:set("dsvpn","vpn","remoteip","10.255.251.1") From 33c697447acb12bc4fa749c616e372d619299f05 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 14 Sep 2021 09:45:22 +0200 Subject: [PATCH 0585/2059] adb not installed by default anymore --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 022951ded..8ef0aaaf7 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -69,7 +69,7 @@ MY_DEPENDS := \ ca-bundle openssl-util \ dejavu-fonts-ttf-DejaVuSerif dejavu-fonts-ttf-DejaVuSerif-Bold dejavu-fonts-ttf-DejaVuSerif-Italic dejavu-fonts-ttf-DejaVuSerif-BoldItalic \ luci-app-snmpd \ - iputils-tracepath v2ray-plugin netcat adb-enablemodem simple-obfs \ + iputils-tracepath v2ray-plugin netcat simple-obfs \ (TARGET_x86||TARGET_x86_64):kmod-iwlwifi (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl1000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl100 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl105 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl135 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl2000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl2030 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl3160 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl3168 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl5000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl5150 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2a (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2b (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6050 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7260 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7265 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7265d (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl8260c (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl8265 \ (TARGET_x86||TARGET_x86_64):kmod-e1000 (TARGET_x86||TARGET_x86_64):kmod-e1000e (TARGET_x86||TARGET_x86_64):kmod-igb (TARGET_x86||TARGET_x86_64):kmod-ne2k-pci (TARGET_x86||TARGET_x86_64):kmod-r8169 (TARGET_x86||TARGET_x86_64):kmod-8139too (TARGET_x86||TARGET_x86_64):kmod-bnx2 \ TARGET_mvebu:kmod-mwlwifi TARGET_mvebu:mwlwifi-firmware-88w8864 TARGET_mvebu:mwlwifi-firmware-88w8897 TARGET_mvebu:mwlwifi-firmware-88w8964 TARGET_mvebu:mwlwifi-firmware-88w8997 \ From 30752f970a47df9ec50baf7546df2ea0916a34fa Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 14 Sep 2021 09:45:45 +0200 Subject: [PATCH 0586/2059] Fix issue on GRE tunnel creation --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 2206fe064..9c581ea92 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -524,7 +524,7 @@ _get_gre_tunnel() { peeraddr="$(echo $tunnel | jsonfilter -q -e '@.remote_ip')" ipaddr="$(echo $tunnel | jsonfilter -q -e '@.local_ip')" publicaddr="$(echo $tunnel | jsonfilter -q -e '@.public_ip')" - if [ "$peeraddr" != "" ] && [ "$ipaddr" != "" ] && [ "$publicaddr" != "" ] && [ "$vpnip_local" != "" ] && ([ "$(uci -q get network.oip${i}.ipaddr)" != "$peeraddr" ] || [ "$(uci -q get network.oip${i}.ipaddr)" != "$ipaddr" ] || [ "$(uci -q get network.oip${i}gre.ipaddr)" != "$vpnip_local" ]); then + if [ "$peeraddr" != "" ] && [ "$ipaddr" != "" ] && [ "$publicaddr" != "" ] && [ "$vpnip_local" != "" ] && ([ "$(uci -q get network.oip${i}.ipaddr)" != "$peeraddr" ] || [ "$(uci -q get network.oip${i}.gateway)" != "$ipaddr" ] || [ "$(uci -q get network.oip${i}gre.ipaddr)" != "$vpnip_local" ]); then uci -q batch <<-EOF >/dev/null set network.oip${i}gre=interface set network.oip${i}gre.label="GRE tunnel for $publicaddr" @@ -559,10 +559,10 @@ _get_gre_tunnel() { for intf in $allintf; do uci -q add_list firewall.zone_vpn.network=$intf done - uci -q batch <<-EOF >/dev/null - add_list firewall.zone_vpn.network="oip${i}gre" - add_list firewall.zone_vpn.network="oip${i}" - EOF + [ -z "$(uci -q get firewall.zone_vpn.network | grep oip${i}gre)" ] && { + uci -q add_list firewall.zone_vpn.network="oip${i}gre" + uci -q add_list firewall.zone_vpn.network="oip${i}" + } ssport="$(echo $tunnel | jsonfilter -q -e '@.shadowsocks_port')" uci -q batch <<-EOF >/dev/null set shadowsocks-libev.oip${i}server=server @@ -1121,7 +1121,7 @@ _set_vps_firewall() { #' fwservername=$1 - [ -z "$servername" ] && servername=$fwservername + [ -n "$fwservername" ] && servername=$fwservername [ -z "$fwservername" ] && fwservername=$servername [ "$(uci -q get openmptcprouter.${fwservername}.nofwredirect)" = "1" ] && return [ -z "$(uci -q get openmptcprouter.${fwservername}.username)" ] && return From ac2c51ff13a10050fd3fdbb056246d4d515bc731 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 14 Sep 2021 09:46:07 +0200 Subject: [PATCH 0587/2059] Use latest shadowsocks-libev fork --- shadowsocks-libev/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-libev/Makefile b/shadowsocks-libev/Makefile index 78fdf4c30..1cef501f0 100644 --- a/shadowsocks-libev/Makefile +++ b/shadowsocks-libev/Makefile @@ -17,7 +17,7 @@ PKG_NAME:=shadowsocks-libev PKG_RELEASE:=11 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/Ysurac/shadowsocks-libev.git -PKG_SOURCE_VERSION:=bf44f710b4a0c451809279383acc847995c35ead +PKG_SOURCE_VERSION:=410950d87d8cdf8502d8f59a79dc0ff4c7677543 PKG_VERSION:=3.3.5-$(PKG_SOURCE_VERSION) PKG_MAINTAINER:=Ycarus (Yannick Chabanois) From ed0132f80753c9a492e6e50256eeadbc2ca0ce7d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 15 Sep 2021 20:21:08 +0200 Subject: [PATCH 0588/2059] Disable httping test in status page --- luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 8ebf2905b..e42883f1a 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1374,7 +1374,8 @@ function interfaces_status() if adminport == "" then adminport = "65500" end - if server_ping == "UP" and uci:get("openmptcprouter", "settings", "disableserverhttptest") ~= "1" and ipaddr ~= "" and adminport ~= "" then + -- httping disable for now, with -l (ssl) timeout is ignored + if false and server_ping == "UP" and uci:get("openmptcprouter", "settings", "disableserverhttptest") ~= "1" and ipaddr ~= "" and adminport ~= "" then local server_http_result = "" local server_http_test = "" if mArray.openmptcprouter["service_addr_ip"] ~= "" then From 63e3df3bec40b9b4b5b73c59cc3ce34a1ae2b790 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 15 Sep 2021 20:21:26 +0200 Subject: [PATCH 0589/2059] Disable cache of pages --- .../luasrc/view/themes/openmptcprouter/header.htm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/header.htm b/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/header.htm index d45dd088c..c661b0ccc 100644 --- a/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/header.htm +++ b/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/header.htm @@ -29,6 +29,9 @@ <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - LuCI + + + From 6ff98da550e74d85ba4bde405aace18eb3f29404 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 24 Sep 2021 21:07:39 +0200 Subject: [PATCH 0590/2059] Update speedtestc --- speedtestc/Makefile | 2 +- speedtestc/patches/compile-fix.patch | 38 ---------------------------- speedtestc/patches/user-agent.patch | 22 ---------------- 3 files changed, 1 insertion(+), 61 deletions(-) delete mode 100644 speedtestc/patches/compile-fix.patch delete mode 100644 speedtestc/patches/user-agent.patch diff --git a/speedtestc/Makefile b/speedtestc/Makefile index 7e13f6e67..c08427fad 100644 --- a/speedtestc/Makefile +++ b/speedtestc/Makefile @@ -12,7 +12,7 @@ PKG_RELEASE:=3 PKG_SOURCE_URL:=https://github.com/mobrembski/SpeedTestC.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=64f8d8288cbbaa596a408fd3051a2b5bc831faa9 +PKG_SOURCE_VERSION:=5bd807bc32269321e500a7e7d36b8ec3fefa5f47 PKG_MAINTAINER:=Ycarus (Yannick Chabanois) PKG_LICENSE:=GPL-2.0 PKG_BUILD_PARALLEL:=0 diff --git a/speedtestc/patches/compile-fix.patch b/speedtestc/patches/compile-fix.patch deleted file mode 100644 index 689e433a9..000000000 --- a/speedtestc/patches/compile-fix.patch +++ /dev/null @@ -1,38 +0,0 @@ -diff --git a/src/SpeedtestConfig.c b/SpeedTestC/src/SpeedtestConfig.c -index 7b60a59..d9f58c9 100644 ---- a/src/SpeedtestConfig.c -+++ b/src/SpeedtestConfig.c -@@ -50,7 +50,7 @@ static void parseClient(const char *configline, SPEEDTESTCONFIG_T **result_p) - char lat[16] = {0}; - char lon[16] = {0}; - -- if(sscanf(configline,"%*[^\"]\"%15[^\"]\"%*[^\"]\"%15[^\"]\"%*[^\"]\"%15[^\"]\"%*[^\"]\"%255[^\"]\"", -+ if(sscanf(configline,"%*[^\"]\"%15[^\"]\"%*[^\"]\"%20[^\"]\"%*[^\"]\"%20[^\"]\"%*[^\"]\"%255[^\"]\"", - result->ip, lat, lon, result->isp)!=4) - { - fprintf(stderr,"Cannot parse all fields! Config line: %s", configline); -diff --git a/src/SpeedtestDownloadTest.c b/src/SpeedtestDownloadTest.c -index 54ed45d..545582a 100644 ---- a/src/SpeedtestDownloadTest.c -+++ b/src/SpeedtestDownloadTest.c -@@ -32,7 +32,7 @@ static void *__downloadThread(void *arg) - return NULL; - } - --void testDownload(const char *url) -+void testDownload(char *url) - { - size_t numOfThreads = speedTestConfig->downloadThreadConfig.count * - speedTestConfig->downloadThreadConfig.sizeLength; -diff --git a/src/SpeedtestDownloadTest.h b/src/SpeedtestDownloadTest.h -index e341f31..45e9d9a 100644 ---- a/src/SpeedtestDownloadTest.h -+++ b/src/SpeedtestDownloadTest.h -@@ -1,6 +1,6 @@ - #ifndef _SPEEDTEST_DOWNLOAD_TEST_ - #define _SPEEDTEST_DOWNLOAD_TEST_ - --void testDownload(const char *url); -+void testDownload(char *url); - - #endif diff --git a/speedtestc/patches/user-agent.patch b/speedtestc/patches/user-agent.patch deleted file mode 100644 index d5390c0f6..000000000 --- a/speedtestc/patches/user-agent.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/src/http.c b/src/http.c -index 45d7281..99f9cfd 100644 ---- a/src/http.c -+++ b/src/http.c -@@ -88,7 +88,7 @@ sock_t httpPut(char* pAddress, int pPort, char* pRequest, unsigned long contentS - Leaving it uninitialized gives us random high value.*/ - sprintf(buffer, "POST %s HTTP/1.1\r\n" - "Host: %s\r\n" -- "User-Agent: SPEEDTEST_CLIENT\r\n" -+ "User-Agent: OMR_SPEEDTEST_CLIENT\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Connection: keep-alive\r\n" - "Content-Length: %lu\r\n" -@@ -131,7 +131,7 @@ sock_t httpGet(char* pAddress, int pPort, char* pRequest, int ssl) - - sprintf(buffer, "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" -- "User-Agent: SPEEDTEST_CLIENT\r\n" -+ "User-Agent: OMR_SPEEDTEST_CLIENT\r\n" - "Connection: close\r\n" - "\r\n", pRequest, pAddress); - From 86d725b8680a07fadd640471ed9a02192b27eb34 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 24 Sep 2021 21:08:05 +0200 Subject: [PATCH 0591/2059] Update xtables-addons --- xtables-addons/Makefile | 200 + .../001-fix-kernel-version-detection.patch | 11 + .../patches/100-add-rtsp-conntrack.patch | 1742 ++ .../patches/200-add-lua-packetscript.patch | 18158 ++++++++++++++++ .../patches/201-fix-lua-packetscript.patch | 136 + .../patches/210-freebsd-build-fix.patch | 11 + 6 files changed, 20258 insertions(+) create mode 100644 xtables-addons/Makefile create mode 100644 xtables-addons/patches/001-fix-kernel-version-detection.patch create mode 100644 xtables-addons/patches/100-add-rtsp-conntrack.patch create mode 100644 xtables-addons/patches/200-add-lua-packetscript.patch create mode 100644 xtables-addons/patches/201-fix-lua-packetscript.patch create mode 100644 xtables-addons/patches/210-freebsd-build-fix.patch diff --git a/xtables-addons/Makefile b/xtables-addons/Makefile new file mode 100644 index 000000000..fa7587589 --- /dev/null +++ b/xtables-addons/Makefile @@ -0,0 +1,200 @@ +# +# Copyright (C) 2009-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=xtables-addons +PKG_VERSION:=3.18 +PKG_RELEASE:=4 +PKG_HASH:=a77914a483ff381663f52120577e5e9355ca07cca73958b038e09d91247458d5 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://inai.de/files/xtables-addons/ +PKG_BUILD_DEPENDS:=iptables +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +PKG_MAINTAINER:=Jo-Philipp Wich +PKG_LICENSE:=GPL-2.0 + +PKG_FIXUP:=autoreconf +PKG_ASLR_PIE:=0 + +include $(INCLUDE_DIR)/package.mk + +define Package/xtables-addons + SECTION:=net + CATEGORY:=Network + SUBMENU:=Firewall + TITLE:=Extensions not distributed in the main Xtables + URL:=https://inai.de/projects/xtables-addons/ +endef + +# uses GNU configure + +CONFIGURE_ARGS+= \ + --with-kbuild="$(LINUX_DIR)" \ + --with-xtlibdir="/usr/lib/iptables" + +ifdef CONFIG_EXTERNAL_TOOLCHAIN +MAKE_FLAGS:= \ + $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ + DEPMOD="/bin/true" + +MAKE_INSTALL_FLAGS:= \ + $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ + DEPMOD="/bin/true" +else +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + $(KERNEL_MAKE_FLAGS) \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + DEPMOD="/bin/true" \ + all +endef + +define Build/Install + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(KERNEL_MAKE_FLAGS) \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + DEPMOD="/bin/true" \ + install +endef +endif + +# 1: extension/module suffix used in package name +# 2: extension/module display name used in package title/description +# 3: list of extensions to package +# 4: list of modules to package +# 5: module load priority +# 6: module depends +define BuildTemplate + + ifneq ($(3),) + define Package/iptables-mod-$(1) + $$(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=$(2) iptables extension + DEPENDS:=iptables $(if $(4),+kmod-ipt-$(1)) + endef + + define Package/iptables-mod-$(1)/install + $(INSTALL_DIR) $$(1)/usr/lib/iptables + for m in $(3); do \ + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so \ + $$(1)/usr/lib/iptables/ ; \ + done + endef + + $$(eval $$(call BuildPackage,iptables-mod-$(1))) + endif + + ifneq ($(4),) + define KernelPackage/ipt-$(1) + SUBMENU:=Netfilter Extensions + TITLE:=$(2) netfilter module + DEPENDS:=+kmod-ipt-core $(5) + FILES:=$(foreach mod,$(4),$(PKG_BUILD_DIR)/extensions/$(mod).$(LINUX_KMOD_SUFFIX)) + AUTOLOAD:=$(call AutoProbe,$(notdir $(4))) + endef + + $$(eval $$(call KernelPackage,ipt-$(1))) + endif + +endef + + +define Package/iptaccount + $(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=iptables-mod-account control utility + DEPENDS:=iptables +iptables-mod-account +endef + +define Package/iptaccount/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libxt_ACCOUNT_cl.so* \ + $(1)/usr/lib/ + $(CP) \ + $(PKG_INSTALL_DIR)/usr/sbin/iptaccount \ + $(1)/usr/sbin/ +endef + + +define Package/iptgeoip + $(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=iptables-mod-geoip support scripts for MaxMind GeoIP databases + DEPENDS:=iptables +iptables-mod-geoip \ + +perl +perlbase-getopt +perlbase-io +perl-text-csv_xs \ + +perl-net-cidr-lite \ + +wget-ssl +!BUSYBOX_CONFIG_ZCAT:gzip +endef + +define Package/iptgeoip/config + menu "Select iptgeoip options" + config IPTGEOIP_PRESERVE + bool "Preserve across sysupgrades" + default n + help + Backup and restore during sysupgrade (requires >7MB) + endmenu +endef + +ifeq ($(CONFIG_IPTGEOIP_PRESERVE),y) +define Package/iptgeoip/conffiles +/usr/share/xt_geoip/ +endef +endif + +define Package/iptgeoip/install + $(INSTALL_DIR) $(1)/usr/lib/xtables-addons + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/xtables-addons/xt_geoip_{build,dl} \ + $(1)/usr/lib/xtables-addons/ + $(INSTALL_DIR) $(1)/usr/bin + $(CP) \ + $(PKG_INSTALL_DIR)/usr/bin/xt_geoip_fetch \ + $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/usr/share/xt_geoip + touch $(1)/usr/share/xt_geoip/.keep +endef + + +#$(eval $(call BuildTemplate,SUFFIX,DESCRIPTION,EXTENSION,MODULE,PRIORITY,DEPENDS)) + +$(eval $(call BuildTemplate,compat-xtables,API compatibilty layer,,compat_xtables,+IPV6:kmod-ip6tables)) +$(eval $(call BuildTemplate,nathelper-rtsp,RTSP Conntrack and NAT,,rtsp/nf_conntrack_rtsp rtsp/nf_nat_rtsp,+kmod-ipt-conntrack-extra +kmod-ipt-nat)) + +$(eval $(call BuildTemplate,account,ACCOUNT,xt_ACCOUNT,ACCOUNT/xt_ACCOUNT,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,chaos,CHAOS,xt_CHAOS,xt_CHAOS,+kmod-ipt-compat-xtables +kmod-ipt-delude +kmod-ipt-tarpit)) +$(eval $(call BuildTemplate,condition,Condition,xt_condition,xt_condition,)) +$(eval $(call BuildTemplate,delude,DELUDE,xt_DELUDE,xt_DELUDE,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,dhcpmac,DHCPMAC,xt_DHCPMAC,xt_DHCPMAC,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,dnetmap,DNETMAP,xt_DNETMAP,xt_DNETMAP,+kmod-ipt-compat-xtables +kmod-ipt-nat)) +$(eval $(call BuildTemplate,fuzzy,fuzzy,xt_fuzzy,xt_fuzzy,)) +$(eval $(call BuildTemplate,geoip,geoip,xt_geoip,xt_geoip,)) +$(eval $(call BuildTemplate,iface,iface,xt_iface,xt_iface,)) +$(eval $(call BuildTemplate,ipmark,IPMARK,xt_IPMARK,xt_IPMARK,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,ipp2p,IPP2P,xt_ipp2p,xt_ipp2p,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,ipv4options,ipv4options,xt_ipv4options,xt_ipv4options,)) +$(eval $(call BuildTemplate,length2,length2,xt_length2,xt_length2,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,logmark,LOGMARK,xt_LOGMARK,xt_LOGMARK,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,lscan,lscan,xt_lscan,xt_lscan,)) +$(eval $(call BuildTemplate,lua,Lua PacketScript,xt_LUA,LUA/xt_LUA,+kmod-ipt-conntrack-extra)) +$(eval $(call BuildTemplate,proto,PROTO,xt_PROTO,xt_PROTO,)) +$(eval $(call BuildTemplate,psd,psd,xt_psd,xt_psd,)) +$(eval $(call BuildTemplate,quota2,quota2,xt_quota2,xt_quota2,)) +$(eval $(call BuildTemplate,sysrq,SYSRQ,xt_SYSRQ,xt_SYSRQ,+kmod-ipt-compat-xtables +kmod-crypto-hash)) +$(eval $(call BuildTemplate,tarpit,TARPIT,xt_TARPIT,xt_TARPIT,+kmod-ipt-compat-xtables)) + +$(eval $(call BuildPackage,iptaccount)) +$(eval $(call BuildPackage,iptgeoip)) diff --git a/xtables-addons/patches/001-fix-kernel-version-detection.patch b/xtables-addons/patches/001-fix-kernel-version-detection.patch new file mode 100644 index 000000000..775ccf657 --- /dev/null +++ b/xtables-addons/patches/001-fix-kernel-version-detection.patch @@ -0,0 +1,11 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -44,7 +44,7 @@ regular_CFLAGS="-Wall -Waggregate-return + + if test -n "$kbuilddir"; then + AC_MSG_CHECKING([kernel version that we will build against]) +- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" ++ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" + save_IFS="$IFS" + IFS='.' + set x $krel diff --git a/xtables-addons/patches/100-add-rtsp-conntrack.patch b/xtables-addons/patches/100-add-rtsp-conntrack.patch new file mode 100644 index 000000000..dbdc52e94 --- /dev/null +++ b/xtables-addons/patches/100-add-rtsp-conntrack.patch @@ -0,0 +1,1742 @@ +--- /dev/null ++++ b/extensions/rtsp/Kbuild +@@ -0,0 +1,4 @@ ++# -*- Makefile -*- ++ ++obj-m += nf_nat_rtsp.o ++obj-m += nf_conntrack_rtsp.o +--- /dev/null ++++ b/extensions/rtsp/netfilter_helpers.h +@@ -0,0 +1,144 @@ ++/* ++ * Helpers for netfiler modules. This file provides implementations for basic ++ * functions such as strncasecmp(), etc. ++ * ++ * gcc will warn for defined but unused functions, so we only include the ++ * functions requested. The following macros are used: ++ * NF_NEED_STRNCASECMP nf_strncasecmp() ++ * NF_NEED_STRTOU16 nf_strtou16() ++ * NF_NEED_STRTOU32 nf_strtou32() ++ */ ++#ifndef _NETFILTER_HELPERS_H ++#define _NETFILTER_HELPERS_H ++ ++/* Only include these functions for kernel code. */ ++#ifdef __KERNEL__ ++ ++#include ++ ++#include ++#define iseol(c) ( (c) == '\r' || (c) == '\n' ) ++ ++/* ++ * The standard strncasecmp() ++ */ ++#ifdef NF_NEED_STRNCASECMP ++static int ++nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) ++{ ++ if (s1 == NULL || s2 == NULL) ++ { ++ if (s1 == NULL && s2 == NULL) ++ { ++ return 0; ++ } ++ return (s1 == NULL) ? -1 : 1; ++ } ++ while (len > 0 && tolower(*s1) == tolower(*s2)) ++ { ++ len--; ++ s1++; ++ s2++; ++ } ++ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); ++} ++#endif /* NF_NEED_STRNCASECMP */ ++ ++/* ++ * Parse a string containing a 16-bit unsigned integer. ++ * Returns the number of chars used, or zero if no number is found. ++ */ ++#ifdef NF_NEED_STRTOU16 ++static int ++nf_strtou16(const char* pbuf, u_int16_t* pval) ++{ ++ int n = 0; ++ ++ *pval = 0; ++ while (isdigit(pbuf[n])) ++ { ++ *pval = (*pval * 10) + (pbuf[n] - '0'); ++ n++; ++ } ++ ++ return n; ++} ++#endif /* NF_NEED_STRTOU16 */ ++ ++/* ++ * Parse a string containing a 32-bit unsigned integer. ++ * Returns the number of chars used, or zero if no number is found. ++ */ ++#ifdef NF_NEED_STRTOU32 ++static int ++nf_strtou32(const char* pbuf, u_int32_t* pval) ++{ ++ int n = 0; ++ ++ *pval = 0; ++ while (pbuf[n] >= '0' && pbuf[n] <= '9') ++ { ++ *pval = (*pval * 10) + (pbuf[n] - '0'); ++ n++; ++ } ++ ++ return n; ++} ++#endif /* NF_NEED_STRTOU32 */ ++ ++/* ++ * Given a buffer and length, advance to the next line and mark the current ++ * line. ++ */ ++#ifdef NF_NEED_NEXTLINE ++static int ++nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) ++{ ++ uint off = *poff; ++ uint physlen = 0; ++ ++ if (off >= len) ++ { ++ return 0; ++ } ++ ++ while (p[off] != '\n') ++ { ++ if (len-off <= 1) ++ { ++ return 0; ++ } ++ ++ physlen++; ++ off++; ++ } ++ ++ /* if we saw a crlf, physlen needs adjusted */ ++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') ++ { ++ physlen--; ++ } ++ ++ /* advance past the newline */ ++ off++; ++ ++ *plineoff = *poff; ++ *plinelen = physlen; ++ *poff = off; ++ ++ return 1; ++} ++#endif /* NF_NEED_NEXTLINE */ ++ ++static inline int rtsp_nf_ct_expect_related(struct nf_conntrack_expect *expect) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) ++ return nf_ct_expect_related(expect, 0); ++#else ++ return nf_ct_expect_related(expect); ++#endif ++} ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _NETFILTER_HELPERS_H */ +--- /dev/null ++++ b/extensions/rtsp/netfilter_mime.h +@@ -0,0 +1,89 @@ ++/* ++ * MIME functions for netfilter modules. This file provides implementations ++ * for basic MIME parsing. MIME headers are used in many protocols, such as ++ * HTTP, RTSP, SIP, etc. ++ * ++ * gcc will warn for defined but unused functions, so we only include the ++ * functions requested. The following macros are used: ++ * NF_NEED_MIME_NEXTLINE nf_mime_nextline() ++ */ ++#ifndef _NETFILTER_MIME_H ++#define _NETFILTER_MIME_H ++ ++/* Only include these functions for kernel code. */ ++#ifdef __KERNEL__ ++ ++#include ++ ++/* ++ * Given a buffer and length, advance to the next line and mark the current ++ * line. If the current line is empty, *plinelen will be set to zero. If ++ * not, it will be set to the actual line length (including CRLF). ++ * ++ * 'line' in this context means logical line (includes LWS continuations). ++ * Returns 1 on success, 0 on failure. ++ */ ++#ifdef NF_NEED_MIME_NEXTLINE ++static int ++nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) ++{ ++ uint off = *poff; ++ uint physlen = 0; ++ int is_first_line = 1; ++ ++ if (off >= len) ++ { ++ return 0; ++ } ++ ++ do ++ { ++ while (p[off] != '\n') ++ { ++ if (len-off <= 1) ++ { ++ return 0; ++ } ++ ++ physlen++; ++ off++; ++ } ++ ++ /* if we saw a crlf, physlen needs adjusted */ ++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') ++ { ++ physlen--; ++ } ++ ++ /* advance past the newline */ ++ off++; ++ ++ /* check for an empty line */ ++ if (physlen == 0) ++ { ++ break; ++ } ++ ++ /* check for colon on the first physical line */ ++ if (is_first_line) ++ { ++ is_first_line = 0; ++ if (memchr(p+(*poff), ':', physlen) == NULL) ++ { ++ return 0; ++ } ++ } ++ } ++ while (p[off] == ' ' || p[off] == '\t'); ++ ++ *plineoff = *poff; ++ *plinelen = (physlen == 0) ? 0 : (off - *poff); ++ *poff = off; ++ ++ return 1; ++} ++#endif /* NF_NEED_MIME_NEXTLINE */ ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _NETFILTER_MIME_H */ +--- /dev/null ++++ b/extensions/rtsp/nf_conntrack_rtsp.c +@@ -0,0 +1,756 @@ ++/* ++ * RTSP extension for IP connection tracking ++ * (C) 2003 by Tom Marshall ++ * ++ * 2005-02-13: Harald Welte ++ * - port to 2.6 ++ * - update to recent post-2.6.11 api changes ++ * 2006-09-14: Steven Van Acker ++ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack ++ * 2007-04-18: Michael Guntsche ++ * - Port to new NF API ++ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd ++ * - fixed rtcp nat mapping and other port mapping fixes ++ * - simple TEARDOWN request handling ++ * - codestyle fixes and other less significant bug fixes ++ * 2018-04-17: Alin Nastac ++ * Hans Dedecker ++ * - use IP address read from SETUP URI in expected connections ++ * 2018-04-18: Hans Dedecker ++ * - update RTP expected connection source IP based on SOURCE ++ * in the SETUP reply message ++ * 2018-08-03: Alin Nastac ++ * Hans Dedecker ++ * - parse non-standard destination=address:port format ++ * ++ * based on ip_conntrack_irc.c ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Module load syntax: ++ * insmod nf_conntrack_rtsp.o ports=port1,port2,...port ++ * max_outstanding=n setup_timeout=secs ++ * ++ * If no ports are specified, the default will be port 554. ++ * ++ * With max_outstanding you can define the maximum number of not yet ++ * answered SETUP requests per RTSP session (default 8). ++ * With setup_timeout you can specify how long the system waits for ++ * an expected data channel (default 300 seconds). ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "nf_conntrack_rtsp.h" ++ ++#define NF_NEED_STRNCASECMP ++#define NF_NEED_STRTOU16 ++#define NF_NEED_STRTOU32 ++#define NF_NEED_NEXTLINE ++#include "netfilter_helpers.h" ++#define NF_NEED_MIME_NEXTLINE ++#include "netfilter_mime.h" ++ ++#include ++ ++#define MAX_PORTS 8 ++static int ports[MAX_PORTS]; ++static int num_ports = 0; ++static int max_outstanding = 8; ++static unsigned int setup_timeout = 300; ++ ++MODULE_AUTHOR("Tom Marshall "); ++MODULE_DESCRIPTION("RTSP connection tracking module"); ++MODULE_LICENSE("GPL"); ++module_param_array(ports, int, &num_ports, 0400); ++MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); ++module_param(max_outstanding, int, 0400); ++MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); ++module_param(setup_timeout, uint, 0400); ++MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); ++ ++static char *rtsp_buffer; ++static DEFINE_SPINLOCK(rtsp_buffer_lock); ++ ++static struct nf_conntrack_expect_policy rtsp_exp_policy; ++ ++unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, ++ enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect *rtp_exp, ++ struct nf_conntrack_expect *rtcp_exp); ++ ++EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); ++ ++/* ++ * Max mappings we will allow for one RTSP connection (for RTP, the number ++ * of allocated ports is twice this value). Note that SMIL burns a lot of ++ * ports so keep this reasonably high. If this is too low, you will see a ++ * lot of "no free client map entries" messages. ++ */ ++#define MAX_PORT_MAPS 16 ++ ++/*** default port list was here in the masq code: 554, 3030, 4040 ***/ ++ ++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } ++ ++/* ++ * Parse an RTSP packet. ++ * ++ * Returns zero if parsing failed. ++ * ++ * Parameters: ++ * IN ptcp tcp data pointer ++ * IN tcplen tcp data len ++ * IN/OUT ptcpoff points to current tcp offset ++ * OUT phdrsoff set to offset of rtsp headers ++ * OUT phdrslen set to length of rtsp headers ++ * OUT pcseqoff set to offset of CSeq header ++ * OUT pcseqlen set to length of CSeq header ++ */ ++static int ++rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, ++ uint* phdrsoff, uint* phdrslen, ++ uint* pcseqoff, uint* pcseqlen, ++ uint* transoff, uint* translen) ++{ ++ uint entitylen = 0; ++ uint lineoff; ++ uint linelen; ++ ++ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) ++ return 0; ++ ++ *phdrsoff = *ptcpoff; ++ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) { ++ if (linelen == 0) { ++ if (entitylen > 0) ++ *ptcpoff += min(entitylen, tcplen - *ptcpoff); ++ break; ++ } ++ if (lineoff+linelen > tcplen) { ++ pr_info("!! overrun !!\n"); ++ break; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { ++ *pcseqoff = lineoff; ++ *pcseqlen = linelen; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { ++ *transoff = lineoff; ++ *translen = linelen; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) { ++ uint off = lineoff+15; ++ SKIP_WSPACE(ptcp+lineoff, linelen, off); ++ nf_strtou32(ptcp+off, &entitylen); ++ } ++ } ++ *phdrslen = (*ptcpoff) - (*phdrsoff); ++ ++ return 1; ++} ++ ++/* ++ * Find lo/hi client ports and/or source (if any) in transport header ++ * In: ++ * ptcp, tcplen = packet ++ * tranoff, tranlen = buffer to search ++ * ++ * Out: ++ * pport_lo, pport_hi = lo/hi ports (host endian) ++ * srvaddr ++ * ++ * Returns nonzero if any client ports found ++ * ++ * Note: it is valid (and expected) for the client to request multiple ++ * transports, so we need to parse the entire line. ++ */ ++static int ++rtsp_parse_transport(char* ptran, uint tranlen, ++ struct ip_ct_rtsp_expect* prtspexp) ++{ ++ int rc = 0; ++ uint off = 0; ++ ++ if (tranlen < 10 || !iseol(ptran[tranlen-1]) || ++ nf_strncasecmp(ptran, "Transport:", 10) != 0) { ++ pr_info("sanity check failed\n"); ++ return 0; ++ } ++ ++ pr_debug("tran='%.*s'\n", (int)tranlen, ptran); ++ off += 10; ++ SKIP_WSPACE(ptran, tranlen, off); ++ ++ /* Transport: tran;field;field=val,tran;field;field=val,... */ ++ while (off < tranlen) { ++ const char* pparamend; ++ uint nextparamoff; ++ ++ pparamend = memchr(ptran+off, ',', tranlen-off); ++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; ++ nextparamoff = pparamend-ptran; ++ ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ ++ if (strncmp(ptran+off, "client_port=", 12) == 0) { ++ u_int16_t port; ++ uint numlen; ++ ++ off += 12; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ if (prtspexp->loport != 0 && prtspexp->loport != port) ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ else { ++ pr_debug("lo port found : %hu\n", port); ++ prtspexp->loport = prtspexp->hiport = port; ++ if (ptran[off] == '-') { ++ off++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ prtspexp->pbtype = pb_range; ++ prtspexp->hiport = port; ++ ++ // If we have a range, assume rtp: ++ // loport must be even, hiport must be loport+1 ++ if ((prtspexp->loport & 0x0001) != 0 || ++ prtspexp->hiport != prtspexp->loport+1) { ++ pr_debug("incorrect range: %hu-%hu, correcting\n", ++ prtspexp->loport, prtspexp->hiport); ++ prtspexp->loport &= 0xfffe; ++ prtspexp->hiport = prtspexp->loport+1; ++ } ++ } else if (ptran[off] == '/') { ++ off++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ prtspexp->pbtype = pb_discon; ++ prtspexp->hiport = port; ++ } ++ rc = 1; ++ } ++ } else if (strncmp(ptran+off, "source=", 7) == 0) { ++ uint srcaddrlen; ++ ++ off += 7; ++ srcaddrlen = nextfieldoff - off - 1; ++ ++ if (in4_pton(ptran + off, srcaddrlen, ++ (u8 *)&prtspexp->srvaddr.in, ++ -1, NULL)) ++ pr_debug("source found : %pI4\n", ++ &prtspexp->srvaddr.ip); ++ } else if (nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { ++ const char *psep; ++ u_int16_t port; ++ ++ off += 12; ++ ++ if (in4_pton(ptran+off, nextfieldoff - off - 1, (u8 *)&prtspexp->cltaddr.in, -1, NULL)) { ++ pr_debug("destination found : %pI4\n", &prtspexp->cltaddr.ip); ++ ++ /* ++ * Some RTSP clients(mostly STBs) use non-standard destination parameters: ++ * destination=address:port ++ */ ++ psep = memchr(ptran+off, ':', nextfieldoff-off); ++ if (psep != NULL && nf_strtou16(psep + 1, &port)) { ++ if (prtspexp->loport != 0 && prtspexp->loport != port) ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ else { ++ pr_debug("lo port found : %hu\n", port); ++ prtspexp->loport = prtspexp->hiport = port; ++ } ++ } ++ } ++ } ++ ++ /* ++ * Note we don't look for the destination parameter here. ++ * If we are using NAT, the NAT module will handle it. If not, ++ * and the client is sending packets elsewhere, the expectation ++ * will quietly time out. ++ */ ++ ++ off = nextfieldoff; ++ } ++ ++ off = nextparamoff; ++ } ++ ++ return rc; ++} ++ ++ ++/*** conntrack functions ***/ ++ ++/* outbound packet: client->server */ ++ ++static inline int ++help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo, ++ unsigned int protoff) ++#else ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++#endif ++{ ++ struct ip_ct_rtsp_expect expinfo; ++ ++ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ ++ //struct tcphdr* tcph = (void*)iph + iph->ihl * 4; ++ //uint tcplen = pktlen - iph->ihl * 4; ++ char* pdata = rb_ptr; ++ //uint datalen = tcplen - tcph->doff * 4; ++ uint dataoff = 0; ++ int ret = NF_ACCEPT; ++ ++ struct nf_conntrack_expect *rtp_exp; ++ struct nf_conntrack_expect *rtcp_exp = NULL; ++ ++ __be16 be_loport; ++ __be16 be_hiport; ++ ++ typeof(nf_nat_rtsp_hook) nf_nat_rtsp; ++ ++ memset(&expinfo, 0, sizeof(expinfo)); ++ ++ while (dataoff < datalen) { ++ uint cmdoff = dataoff; ++ uint hdrsoff = 0; ++ uint hdrslen = 0; ++ uint cseqoff = 0; ++ uint cseqlen = 0; ++ uint transoff = 0; ++ uint translen = 0; ++ uint off; ++ union nf_inet_addr srvaddr; ++ ++ if (!rtsp_parse_message(pdata, datalen, &dataoff, ++ &hdrsoff, &hdrslen, ++ &cseqoff, &cseqlen, ++ &transoff, &translen)) ++ break; /* not a valid message */ ++ ++ if (strncmp(pdata+cmdoff, "TEARDOWN ", 9) == 0) { ++ pr_debug("teardown handled\n"); ++ nf_ct_remove_expectations(ct); /* FIXME must be session id aware */ ++ break; ++ } ++ ++ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) ++ continue; /* not a SETUP message */ ++ ++ srvaddr = ct->tuplehash[!dir].tuple.src.u3; ++ ++ /* try to get RTP media source from SETUP URI */ ++ off = cmdoff + 6; ++ while (off < datalen) { ++ if (strncmp(pdata+off, "://", 3) == 0) { ++ off += 3; ++ cmdoff = off; ++ ++ while (off < datalen) { ++ if (pdata[off] == ':' || ++ pdata[off] == '/' || ++ pdata[off] == ' ') { ++ in4_pton(pdata + cmdoff, ++ off - cmdoff, ++ (u8 *)&srvaddr.in, ++ -1, NULL); ++ break; ++ } ++ off++; ++ } ++ break; ++ } ++ off++; ++ } ++ ++ pr_debug("found a setup message\n"); ++ ++ off = 0; ++ if(translen) ++ rtsp_parse_transport(pdata+transoff, translen, &expinfo); ++ ++ if (expinfo.loport == 0) { ++ pr_debug("no udp transports found\n"); ++ continue; /* no udp transports found */ ++ } ++ ++ pr_debug("udp transport found, ports=(%d,%hu,%hu)\n", ++ (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); ++ ++ ++ be_loport = htons(expinfo.loport); ++ ++ rtp_exp = nf_ct_expect_alloc(ct); ++ if (rtp_exp == NULL) { ++ ret = NF_DROP; ++ goto out; ++ } ++ ++ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, ++ nf_ct_l3num(ct), NULL, ++ &ct->tuplehash[!dir].tuple.dst.u3, ++ IPPROTO_UDP, NULL, &be_loport); ++ ++ rtp_exp->flags = 0; ++ ++ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { ++ pr_debug("setup expectation for rtcp\n"); ++ ++ be_hiport = htons(expinfo.hiport); ++ rtcp_exp = nf_ct_expect_alloc(ct); ++ if (rtcp_exp == NULL) { ++ ret = NF_DROP; ++ goto out1; ++ } ++ ++ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, ++ nf_ct_l3num(ct), NULL, ++ &ct->tuplehash[!dir].tuple.dst.u3, ++ IPPROTO_UDP, NULL, &be_hiport); ++ ++ rtcp_exp->flags = 0; ++ ++ pr_debug("expect_related %pI4:%u-%u-%pI4:%u-%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ ntohs(rtcp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port), ++ ntohs(rtcp_exp->tuple.dst.u.udp.port)); ++ } else { ++ pr_debug("expect_related %pI4:%u-%pI4:%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port)); ++ } ++ ++ nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook); ++ if (nf_nat_rtsp && ct->status & IPS_NAT_MASK) ++ /* pass the request off to the nat helper */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen, ++ &expinfo, rtp_exp, rtcp_exp); ++#else ++ ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, ++ &expinfo, rtp_exp, rtcp_exp); ++#endif ++ else { ++ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { ++ if (rtcp_exp && rtsp_nf_ct_expect_related(rtcp_exp) != 0) { ++ nf_ct_unexpect_related(rtp_exp); ++ pr_info("nf_conntrack_expect_related failed for rtcp\n"); ++ ret = NF_DROP; ++ } ++ } else { ++ pr_info("nf_conntrack_expect_related failed for rtp\n"); ++ ret = NF_DROP; ++ } ++ } ++ if (rtcp_exp) { ++ nf_ct_expect_put(rtcp_exp); ++ } ++out1: ++ nf_ct_expect_put(rtp_exp); ++ goto out; ++ } ++out: ++ ++ return ret; ++} ++ ++ ++static inline int ++help_in(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo, ++ unsigned int protoff) ++#else ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++#endif ++ { ++ struct ip_ct_rtsp_expect expinfo; ++ union nf_inet_addr srvaddr; ++ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ ++ int len; ++ char* pdata = rb_ptr; ++ uint dataoff = 0; ++ int ret = NF_ACCEPT; ++ u_int8_t family; ++ struct nf_conntrack_expect *exp_ct = NULL; ++ struct nf_conntrack_tuple t; ++ struct net *net = nf_ct_net(ct); ++ ++ memset(&expinfo, 0, sizeof(expinfo)); ++ ++ while (dataoff < datalen) { ++ uint cmdoff = dataoff; ++ uint hdrsoff = 0; ++ uint hdrslen = 0; ++ uint cseqoff = 0; ++ uint cseqlen = 0; ++ uint transoff = 0; ++ uint translen = 0; ++ ++ if (!rtsp_parse_message(pdata, datalen, &dataoff, ++ &hdrsoff, &hdrslen, ++ &cseqoff, &cseqlen, ++ &transoff, &translen)) ++ break; /* not a valid message */ ++ ++ if (strncmp(pdata+cmdoff, "RTSP/", 5) == 0 && translen) { ++ union nf_inet_addr zeroaddr; ++ ++ memset(&zeroaddr, 0, sizeof(zeroaddr)); ++ ++ if (!rtsp_parse_transport(pdata+transoff, translen, &expinfo)) ++ continue; ++ ++ srvaddr = expinfo.srvaddr; ++ ++ if (nf_inet_addr_cmp(&srvaddr, &ct->tuplehash[dir].tuple.src.u3) || ++ nf_inet_addr_cmp(&srvaddr, &zeroaddr)) ++ continue; ++ } else ++ continue; /* not valid RTSP reply */ ++ ++ if (expinfo.loport == 0) { ++ pr_debug("no udp transports found\n"); ++ continue; /* no udp transports found */ ++ } ++ ++ family = nf_ct_l3num(ct); ++ if (family == AF_INET) ++ len = 4; ++ else ++ len = 16; ++ ++ /* replace rtp expect src addr */ ++ t.src.l3num = family; ++ t.dst.protonum = IPPROTO_UDP; ++ ++ memcpy(&t.src.u3, &ct->tuplehash[dir].tuple.src.u3, len); ++ if (sizeof(t.src.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&t.src.u3 + len, 0, sizeof(t.src.u3) - len); ++ ++ t.src.u.all = 0; ++ ++ memcpy(&t.dst.u3, &ct->tuplehash[dir].tuple.dst.u3, len); ++ if (sizeof(t.dst.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&t.dst.u3 + len, 0, sizeof(t.dst.u3) - len); ++ ++ t.dst.u.all = htons(expinfo.loport); ++ ++ /* get the rtp expect and replace the srcaddr with RTP server addr */ ++ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); ++ if (exp_ct) { ++ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); ++ if (sizeof(exp_ct->tuple.src.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&exp_ct->tuple.src.u3 + len, 0, ++ sizeof(exp_ct->tuple.src.u3) - len); ++ } else ++ goto out; ++ ++ /* replace rtcp expect src addr */ ++ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { ++ t.dst.u.all = htons(expinfo.hiport); ++ ++ /* get the rtcp expect and replace the srcaddr with RTP server addr */ ++ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); ++ if (exp_ct) { ++ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); ++ if (sizeof(exp_ct->tuple.src.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&exp_ct->tuple.src.u3 + len, 0, ++ sizeof(exp_ct->tuple.src.u3) - len); ++ } else ++ goto out; ++ } ++ ++ goto out; ++ } ++out: ++ return ret; ++ } ++ ++static int help(struct sk_buff *skb, unsigned int protoff, ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++{ ++ struct tcphdr _tcph, *th; ++ unsigned int dataoff, datalen; ++ char *rb_ptr; ++ int ret = NF_DROP; ++ ++ /* Until there's been traffic both ways, don't look in packets. */ ++ if (ctinfo != IP_CT_ESTABLISHED && ++ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { ++ pr_debug("conntrackinfo = %u\n", ctinfo); ++ return NF_ACCEPT; ++ } ++ ++ /* Not whole TCP header? */ ++ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); ++ ++ if (!th) ++ return NF_ACCEPT; ++ ++ /* No data ? */ ++ dataoff = protoff + th->doff*4; ++ datalen = skb->len - dataoff; ++ if (dataoff >= skb->len) ++ return NF_ACCEPT; ++ ++ spin_lock_bh(&rtsp_buffer_lock); ++ rb_ptr = skb_header_pointer(skb, dataoff, ++ skb->len - dataoff, rtsp_buffer); ++ BUG_ON(rb_ptr == NULL); ++ ++#if 0 ++ /* Checksum invalid? Ignore. */ ++ /* FIXME: Source route IP option packets --RR */ ++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, ++ csum_partial((char*)tcph, tcplen, 0))) ++ { ++ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", ++ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); ++ return NF_ACCEPT; ++ } ++#endif ++ ++ switch (CTINFO2DIR(ctinfo)) { ++ case IP_CT_DIR_ORIGINAL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff); ++#else ++ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo); ++#endif ++ break; ++ case IP_CT_DIR_REPLY: ++ pr_debug("IP_CT_DIR_REPLY\n"); ++ /* inbound packet: server->client */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo, protoff); ++#else ++ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo); ++#endif ++ break; ++ default: ++ break; ++ } ++ ++ spin_unlock_bh(&rtsp_buffer_lock); ++ ++ return ret; ++} ++ ++static struct nf_conntrack_helper rtsp_helpers[MAX_PORTS]; ++static char rtsp_names[MAX_PORTS][10]; ++ ++/* This function is intentionally _NOT_ defined as __exit */ ++static void ++fini(void) ++{ ++ int i; ++ for (i = 0; i < num_ports; i++) { ++ pr_debug("unregistering port %d\n", ports[i]); ++ nf_conntrack_helper_unregister(&rtsp_helpers[i]); ++ } ++ kfree(rtsp_buffer); ++} ++ ++static int __init ++init(void) ++{ ++ int i, ret; ++ struct nf_conntrack_helper *hlpr; ++ char *tmpname; ++ ++ printk("nf_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); ++ ++ if (max_outstanding < 1) { ++ printk("nf_conntrack_rtsp: max_outstanding must be a positive integer\n"); ++ return -EBUSY; ++ } ++ ++ rtsp_exp_policy.max_expected = max_outstanding; ++ rtsp_exp_policy.timeout = setup_timeout; ++ ++ rtsp_buffer = kmalloc(65536, GFP_KERNEL); ++ if (!rtsp_buffer) ++ return -ENOMEM; ++ ++ /* If no port given, default to standard rtsp port */ ++ if (ports[0] == 0) { ++ ports[0] = RTSP_PORT; ++ num_ports = 1; ++ } ++ ++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { ++ hlpr = &rtsp_helpers[i]; ++ memset(hlpr, 0, sizeof(struct nf_conntrack_helper)); ++ hlpr->tuple.src.l3num = AF_INET; ++ hlpr->tuple.src.u.tcp.port = htons(ports[i]); ++ hlpr->tuple.dst.protonum = IPPROTO_TCP; ++ hlpr->expect_policy = &rtsp_exp_policy; ++ hlpr->me = THIS_MODULE; ++ hlpr->help = help; ++ ++ tmpname = &rtsp_names[i][0]; ++ if (ports[i] == RTSP_PORT) { ++ sprintf(tmpname, "rtsp"); ++ } else { ++ sprintf(tmpname, "rtsp-%d", i); ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ strlcpy(hlpr->name, tmpname, sizeof(hlpr->name)); ++#else ++ hlpr->name = tmpname; ++#endif ++ pr_debug("port #%d: %d\n", i, ports[i]); ++ ++ ret = nf_conntrack_helper_register(hlpr); ++ ++ if (ret) { ++ printk("nf_conntrack_rtsp: ERROR registering port %d\n", ports[i]); ++ fini(); ++ return -EBUSY; ++ } ++ } ++ return 0; ++} ++ ++module_init(init); ++module_exit(fini); +--- /dev/null ++++ b/extensions/rtsp/nf_conntrack_rtsp.h +@@ -0,0 +1,74 @@ ++/* ++ * RTSP extension for IP connection tracking. ++ * (C) 2003 by Tom Marshall ++ * based on ip_conntrack_irc.h ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd ++ * - conditional compilation for kernel 3.7 ++ * - port mapping improvements ++*/ ++#ifndef _IP_CONNTRACK_RTSP_H ++#define _IP_CONNTRACK_RTSP_H ++ ++#include ++ ++//#define IP_NF_RTSP_DEBUG 1 ++#define IP_NF_RTSP_VERSION "0.7" ++ ++#ifdef __KERNEL__ ++/* port block types */ ++typedef enum { ++ pb_single, /* client_port=x */ ++ pb_range, /* client_port=x-y */ ++ pb_discon /* client_port=x/y (rtspbis) */ ++} portblock_t; ++ ++/* We record seq number and length of rtsp headers here, all in host order. */ ++ ++/* ++ * This structure is per expected connection. It is a member of struct ++ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored ++ * there and we are expected to only store the length of the data which ++ * needs replaced. If a packet contains multiple RTSP messages, we create ++ * one expected connection per message. ++ * ++ * We use these variables to mark the entire header block. This may seem ++ * like overkill, but the nature of RTSP requires it. A header may appear ++ * multiple times in a message. We must treat two Transport headers the ++ * same as one Transport header with two entries. ++ */ ++struct ip_ct_rtsp_expect ++{ ++ u_int32_t len; /* length of header block */ ++ portblock_t pbtype; /* Type of port block that was requested */ ++ u_int16_t loport; /* Port that was requested, low or first */ ++ u_int16_t hiport; /* Port that was requested, high or second */ ++ union nf_inet_addr srvaddr; /* src address in SETUP reply */ ++ union nf_inet_addr cltaddr; /* destination address */ ++#if 0 ++ uint method; /* RTSP method */ ++ uint cseq; /* CSeq from request */ ++#endif ++}; ++ ++extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, ++ enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, ++ unsigned int matchlen, ++ struct ip_ct_rtsp_expect *prtspexp, ++ struct nf_conntrack_expect *rtp_exp, ++ struct nf_conntrack_expect *rtcp_exp); ++ ++#define RTSP_PORT 554 ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _IP_CONNTRACK_RTSP_H */ +--- /dev/null ++++ b/extensions/rtsp/nf_nat_rtsp.c +@@ -0,0 +1,640 @@ ++/* ++ * RTSP extension for TCP NAT alteration ++ * (C) 2003 by Tom Marshall ++ * ++ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd ++ * - fixed rtcp nat mapping and other port mapping fixes ++ * - fixed system hard lock because of bug in the parser ++ * - codestyle fixes and less significant fixes ++ * ++ * based on ip_nat_irc.c ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Module load syntax: ++ * insmod nf_nat_rtsp.o ports=port1,port2,...port ++ * stunaddr=
    ++ * destaction=[auto|strip|none] ++ * ++ * If no ports are specified, the default will be port 554 only. ++ * ++ * stunaddr specifies the address used to detect that a client is using STUN. ++ * If this address is seen in the destination parameter, it is assumed that ++ * the client has already punched a UDP hole in the firewall, so we don't ++ * mangle the client_port. If none is specified, it is autodetected. It ++ * only needs to be set if you have multiple levels of NAT. It should be ++ * set to the external address that the STUN clients detect. Note that in ++ * this case, it will not be possible for clients to use UDP with servers ++ * between the NATs. ++ * ++ * If no destaction is specified, auto is used. ++ * destaction=auto: strip destination parameter if it is not stunaddr. ++ * destaction=strip: always strip destination parameter (not recommended). ++ * destaction=none: do not touch destination parameter (not recommended). ++ */ ++ ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++# include ++#else ++# include ++#endif ++#include ++#include "nf_conntrack_rtsp.h" ++ ++#include ++#include ++#define NF_NEED_STRNCASECMP ++#define NF_NEED_STRTOU16 ++#include "netfilter_helpers.h" ++#define NF_NEED_MIME_NEXTLINE ++#include "netfilter_mime.h" ++ ++#define MAX_PORTS 8 ++#define DSTACT_AUTO 0 ++#define DSTACT_STRIP 1 ++#define DSTACT_NONE 2 ++ ++static char* stunaddr = NULL; ++static char* destaction = NULL; ++ ++static u_int32_t extip = 0; ++static int dstact = 0; ++ ++static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp); ++ ++MODULE_AUTHOR("Tom Marshall "); ++MODULE_DESCRIPTION("RTSP network address translation module"); ++MODULE_LICENSE("GPL"); ++module_param(stunaddr, charp, 0644); ++MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); ++module_param(destaction, charp, 0644); ++MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); ++ ++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } ++ ++/*** helper functions ***/ ++ ++static void ++get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) ++{ ++ struct iphdr* iph = ip_hdr(skb); ++ struct tcphdr* tcph = (void *)iph + ip_hdrlen(skb); ++ ++ *pptcpdata = (char*)tcph + tcph->doff*4; ++ *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++/* copy of sip_sprintf_addr */ ++static int rtsp_sprintf_addr(const struct nf_conn *ct, char *buffer, ++ const union nf_inet_addr *addr, bool delim) ++{ ++ if (nf_ct_l3num(ct) == NFPROTO_IPV4) { ++ return sprintf(buffer, "%pI4", &addr->ip); ++ } else { ++ if (delim) ++ return sprintf(buffer, "[%pI6c]", &addr->ip6); ++ else ++ return sprintf(buffer, "%pI6c", &addr->ip6); ++ } ++} ++#endif ++ ++/*** nat functions ***/ ++ ++/* ++ * Mangle the "Transport:" header: ++ * - Replace all occurences of "client_port=" ++ * - Handle destination parameter ++ * ++ * In: ++ * ct, ctinfo = conntrack context ++ * skb = packet ++ * tranoff = Transport header offset from TCP data ++ * tranlen = Transport header length (incl. CRLF) ++ * rport_lo = replacement low port (host endian) ++ * rport_hi = replacement high port (host endian) ++ * ++ * Returns packet size difference. ++ * ++ * Assumes that a complete transport header is present, ending with CR or LF ++ */ ++static int ++rtsp_mangle_tran(enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct sk_buff* skb, uint tranoff, uint tranlen) ++{ ++ char* ptcp; ++ uint tcplen; ++ char* ptran; ++ char rbuf1[16]; /* Replacement buffer (one port) */ ++ uint rbuf1len; /* Replacement len (one port) */ ++ char rbufa[16]; /* Replacement buffer (all ports) */ ++ uint rbufalen; /* Replacement len (all ports) */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ union nf_inet_addr newip; ++#else ++ u_int32_t newip; ++#endif ++ u_int16_t loport, hiport; ++ uint off = 0; ++ uint diff; /* Number of bytes we removed */ ++ ++ struct nf_conn *ct = rtp_exp->master; ++ /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */ ++ struct nf_conntrack_tuple *rtp_t; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ char szextaddr[INET6_ADDRSTRLEN + 16]; ++#else ++ char szextaddr[INET_ADDRSTRLEN + 16]; ++#endif ++ uint extaddrlen; ++ int is_stun; ++ ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ ++ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || ++ tranlen < 10 || !iseol(ptran[tranlen-1]) || ++ nf_strncasecmp(ptran, "Transport:", 10) != 0) { ++ pr_info("sanity check failed\n"); ++ return 0; ++ } ++ off += 10; ++ SKIP_WSPACE(ptcp+tranoff, tranlen, off); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3; ++ rtp_t = &rtp_exp->tuple; ++ rtp_t->dst.u3 = newip; ++ if (rtcp_exp) { ++ rtcp_exp->tuple.dst.u3 = newip; ++ } ++ extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip ++ pr_debug("stunaddr=%s (auto)\n", szextaddr); ++#else ++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; ++ rtp_t = &rtp_exp->tuple; ++ rtp_t->dst.u3.ip = newip; ++ if (rtcp_exp) { ++ rtcp_exp->tuple.dst.u3.ip = newip; ++ } ++ extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) ++ : sprintf(szextaddr, "%pI4", &newip); ++ pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); ++#endif ++ hiport = 0; ++ rbuf1len = rbufalen = 0; ++ switch (prtspexp->pbtype) { ++ case pb_single: ++ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { ++ pr_debug("using port %hu\n", loport); ++ break; ++ } ++ } ++ if (loport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, "%hu", loport); ++ } ++ break; ++ case pb_range: ++ for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (rtsp_nf_ct_expect_related(rtp_exp) != 0) { ++ continue; ++ } ++ hiport = loport + 1; ++ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); ++ if (rtsp_nf_ct_expect_related(rtcp_exp) != 0) { ++ nf_ct_unexpect_related(rtp_exp); ++ continue; ++ } ++ ++ /* FIXME: invalid print in case of ipv6 */ ++ pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ ntohs(rtcp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port), ++ ntohs(rtcp_exp->tuple.dst.u.udp.port)); ++ break; ++ } ++ if (loport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); ++ } ++ break; ++ case pb_discon: ++ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { ++ pr_debug("using port %hu (1 of 2)\n", loport); ++ break; ++ } ++ } ++ for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */ ++ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); ++ if (rtsp_nf_ct_expect_related(rtcp_exp) == 0) { ++ pr_debug("using port %hu (2 of 2)\n", hiport); ++ break; ++ } ++ } ++ if (loport != 0 && hiport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, hiport == loport+1 ? ++ "%hu-%hu":"%hu/%hu", loport, hiport); ++ } else { ++ if (loport != 0) ++ nf_ct_unexpect_related(rtp_exp); ++ if (hiport != 0) ++ nf_ct_unexpect_related(rtcp_exp); ++ } ++ break; ++ } ++ ++ if (rbuf1len == 0) ++ return 0; /* cannot get replacement port(s) */ ++ ++ /* Transport: tran;field;field=val,tran;field;field=val,... ++ `off` is set to the start of Transport value from start of line ++ */ ++ while (off < tranlen) { ++ uint saveoff; ++ const char* pparamend; ++ uint nextparamoff; ++ ++ pparamend = memchr(ptran+off, ',', tranlen-off); ++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; ++ nextparamoff = pparamend-ptran; ++ ++ /* ++ * We pass over each param twice. On the first pass, we look for a ++ * destination= field. It is handled by the security policy. If it ++ * is present, allowed, and equal to our external address, we assume ++ * that STUN is being used and we leave the client_port= field alone. ++ */ ++ is_stun = 0; ++ saveoff = off; ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ SKIP_WSPACE(ptran, nextfieldoff, off); ++ ++ if (dstact != DSTACT_NONE && nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { ++ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) ++ is_stun = 1; ++ ++ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { ++ uint dstoff = (ptran-ptcp)+off; ++ uint dstlen = nextfieldoff-off; ++ char* pdstrep = NULL; ++ uint dstreplen = 0; ++ diff = dstlen; ++ if (dstact == DSTACT_AUTO && !is_stun) { ++ const char* psep = memchr(ptran+off, ':', dstlen); ++ u_int16_t port; ++ ++ dstoff += 12; ++ dstlen -= 13; ++ pdstrep = szextaddr; ++ ++ if (psep != NULL && nf_strtou16(psep + 1, &port)) { ++ pr_debug("RTSP: replace dst addr&port\n"); ++ ++ if (port != prtspexp->loport) { ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ dstreplen = extaddrlen; ++ } else { ++ sprintf(szextaddr+extaddrlen, ":%s", rbuf1); ++ dstreplen = extaddrlen+1+rbuf1len; ++ } ++ } else { ++ pr_debug("RTSP: replace dst addr\n"); ++ dstreplen = extaddrlen; ++ } ++ diff = nextfieldoff-off-13-dstreplen; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, ++ dstoff, dstlen, pdstrep, dstreplen)) { ++#else ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, ++ dstoff, dstlen, pdstrep, dstreplen)) { ++#endif ++ /* mangle failed, all we can do is bail */ ++ nf_ct_unexpect_related(rtp_exp); ++ if (rtcp_exp) ++ nf_ct_unexpect_related(rtcp_exp); ++ return 0; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ tranlen -= diff; ++ nextparamoff -= diff; ++ nextfieldoff -= diff; ++ } ++ } ++ ++ off = nextfieldoff; ++ } ++ ++ if (is_stun) ++ continue; ++ ++ off = saveoff; ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ ++ if (nextfieldoff - off > 12 && strncmp(ptran+off, "client_port=", 12) == 0) { ++ u_int16_t port; ++ uint numlen; ++ uint origoff; ++ uint origlen; ++ char* rbuf = rbuf1; ++ uint rbuflen = rbuf1len; ++ ++ off += 12; ++ origoff = (ptran-ptcp)+off; ++ origlen = 0; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ origlen += numlen; ++ if (port != prtspexp->loport) { ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ } else { ++ if (ptran[off] == '-' || ptran[off] == '/') { ++ off++; ++ origlen++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ origlen += numlen; ++ rbuf = rbufa; ++ rbuflen = rbufalen; ++ } ++ ++ /* ++ * note we cannot just memcpy() if the sizes are the same. ++ * the mangle function does skb resizing, checks for a ++ * cloned skb, and updates the checksums. ++ * ++ * parameter 4 below is offset from start of tcp data. ++ */ ++ diff = origlen-rbuflen; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, ++ origoff, origlen, rbuf, rbuflen)) { ++#else ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, ++ origoff, origlen, rbuf, rbuflen)) { ++#endif ++ /* mangle failed, all we can do is bail */ ++ nf_ct_unexpect_related(rtp_exp); ++ if (rtcp_exp) ++ nf_ct_unexpect_related(rtcp_exp); ++ return 0; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ tranlen -= diff; ++ nextparamoff -= diff; ++ nextfieldoff -= diff; ++ } ++ } ++ ++ off = nextfieldoff; ++ } ++ ++ off = nextparamoff; ++ } ++ ++ return 1; ++} ++ ++static uint ++help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp) ++{ ++ char* ptcp; ++ uint tcplen; ++ uint hdrsoff; ++ uint hdrslen; ++ uint lineoff; ++ uint linelen; ++ uint off; ++ int dir = CTINFO2DIR(ctinfo); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3; ++#else ++ __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip; ++#endif ++ ++ //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; ++ //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); ++ ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); ++ hdrslen = matchlen; ++ off = hdrsoff; ++ pr_debug("NAT rtsp help_out\n"); ++ ++ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) { ++ if (linelen == 0) ++ break; ++ ++ if (off > hdrsoff+hdrslen) { ++ pr_info("!! overrun !!"); ++ break; ++ } ++ pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { ++ uint oldtcplen = tcplen; ++ pr_debug("hdr: Transport\n"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp, ++ prtspexp, skb, lineoff, linelen)) { ++#else ++ if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp, ++ skb, lineoff, linelen)) { ++#endif ++ pr_debug("hdr: Transport mangle failed"); ++ break; ++ } ++ rtp_exp->expectfn = nf_nat_rtsp_expected; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rtp_exp->saved_addr = saddr; ++#else ++ rtp_exp->saved_ip = saddr; ++#endif ++ rtp_exp->saved_proto.udp.port = htons(prtspexp->loport); ++ rtp_exp->dir = !dir; ++ if (rtcp_exp) { ++ rtcp_exp->expectfn = nf_nat_rtsp_expected; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rtcp_exp->saved_addr = saddr; ++#else ++ rtcp_exp->saved_ip = saddr; ++#endif ++ rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport); ++ rtcp_exp->dir = !dir; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ hdrslen -= (oldtcplen-tcplen); ++ off -= (oldtcplen-tcplen); ++ lineoff -= (oldtcplen-tcplen); ++ linelen -= (oldtcplen-tcplen); ++ pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); ++ } ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static unsigned int ++nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp) ++{ ++ int dir = CTINFO2DIR(ctinfo); ++ int rc = NF_ACCEPT; ++ ++ switch (dir) { ++ case IP_CT_DIR_ORIGINAL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, ++ rtp_exp, rtcp_exp); ++#else ++ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, ++ rtp_exp, rtcp_exp); ++#endif ++ break; ++ case IP_CT_DIR_REPLY: ++ pr_debug("unmangle ! %u\n", ctinfo); ++ /* XXX: unmangle */ ++ rc = NF_ACCEPT; ++ break; ++ } ++ //UNLOCK_BH(&ip_rtsp_lock); ++ ++ return rc; ++} ++ ++static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0) ++ struct nf_nat_range2 range; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_nat_range range; ++#else ++ struct nf_nat_ipv4_range range; ++#endif ++ ++ /* This must be a fresh one. */ ++ BUG_ON(ct->status & IPS_NAT_DONE_MASK); ++ ++ /* For DST manip, map port here to where it's expected. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ range.min_proto = range.max_proto = exp->saved_proto; ++ range.min_addr = range.max_addr = exp->saved_addr; ++#else ++ range.min = range.max = exp->saved_proto; ++ range.min_ip = range.max_ip = exp->saved_ip; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); ++ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); ++#else ++ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); ++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); ++#endif ++ ++ /* Change src to where master sends to, but only if the connection ++ * actually came from the same source. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, ++ &ct->master->tuplehash[exp->dir].tuple.src.u3)) { ++ range.min_addr = range.max_addr ++ = ct->master->tuplehash[!exp->dir].tuple.dst.u3; ++#else ++ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == ++ ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { ++ range.min_ip = range.max_ip ++ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ range.flags = NF_NAT_RANGE_MAP_IPS; ++ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); ++#else ++ range.flags = IP_NAT_RANGE_MAP_IPS; ++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); ++#endif ++ } ++} ++ ++ ++static void __exit fini(void) ++{ ++ rcu_assign_pointer(nf_nat_rtsp_hook, NULL); ++ synchronize_net(); ++} ++ ++static int __init init(void) ++{ ++ printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); ++ ++ BUG_ON(nf_nat_rtsp_hook); ++ rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp); ++ ++ if (stunaddr != NULL) ++ extip = in_aton(stunaddr); ++ ++ if (destaction != NULL) { ++ if (strcmp(destaction, "auto") == 0) ++ dstact = DSTACT_AUTO; ++ ++ if (strcmp(destaction, "strip") == 0) ++ dstact = DSTACT_STRIP; ++ ++ if (strcmp(destaction, "none") == 0) ++ dstact = DSTACT_NONE; ++ } ++ ++ return 0; ++} ++ ++module_init(init); ++module_exit(fini); +--- a/extensions/Kbuild ++++ b/extensions/Kbuild +@@ -27,6 +27,7 @@ obj-${build_lscan} += xt_lscan.o + obj-${build_pknock} += pknock/ + obj-${build_psd} += xt_psd.o + obj-${build_quota2} += xt_quota2.o ++obj-${build_rtsp} += rtsp/ + + -include ${M}/*.Kbuild + -include ${M}/Kbuild.* +--- a/mconfig ++++ b/mconfig +@@ -23,3 +23,4 @@ build_lscan=m + build_pknock=m + build_psd=m + build_quota2=m ++build_rtsp=m diff --git a/xtables-addons/patches/200-add-lua-packetscript.patch b/xtables-addons/patches/200-add-lua-packetscript.patch new file mode 100644 index 000000000..8dd926712 --- /dev/null +++ b/xtables-addons/patches/200-add-lua-packetscript.patch @@ -0,0 +1,18158 @@ +--- /dev/null ++++ b/extensions/LUA/byte_array.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++#include "controller.h" ++ ++/* Initialization helper function. This function should be used whenever ++ * a new byte array need to be initialized. Depending on the arguments it ++ * initializes the array in a different way. Have a look at the inline ++ * comments */ ++lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy) ++{ ++ lua_packet_segment *array; ++ ++ if (length < 0) ++ luaL_error(L, "init_byte_array, requested size < 0"); ++ ++ if (start && do_copy) { ++ /* we have a start address where we copy from */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); ++ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ ++ memcpy(array->start, start, length); ++ }else if (start && !do_copy) { ++ /* just link the start pointer, in this case you have to free the memory yourself */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment)); ++ array->start = start; ++ }else{ ++ /* create an empty array, fully managed by Lua */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); ++ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ ++ memset(array->start, 0, length); ++ } ++ ++ array->length = length; ++ array->offset = 0; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ ++ return array; ++} ++ ++ ++ ++/* LUA_API: get one byte of the given byte array ++ * access-pattern: array[] */ ++static int32_t get_byte_array(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ ++ ++ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); ++ lua_pushinteger(L, (array->start + array->offset)[index]); ++ ++ return 1; ++} ++ ++/* LUA_API: set one byte of the given byte array ++ * access-pattern: array[]= 0xFF */ ++static int32_t set_byte_array(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ uint8_t byte; ++ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ ++ int32_t val = luaL_checkinteger(L, 3); ++ uint32_t nob = 1 << CHAR_BIT; /* we should use something like 1 << CHAR_BIT */ ++ ++ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); ++ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); ++ ++ byte = (uint8_t)val; ++ ++ (array->start + array->offset)[index] = byte; ++ ++ return 0; ++} ++ ++/* LUA_API: get size of the given byte array ++ * access-pattern: #array (__length meta-method) */ ++static int32_t get_byte_array_size(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ ++ lua_pushnumber(L, array->length); ++ ++ return 1; ++} ++ ++ ++/* LUA_API: converts a given byte array to a string. ++ * access-pattern: implicit through functions calling the ++ * __to_string() metamethod , e.g. print32_t */ ++static int32_t byte_array_to_string(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ uint8_t buf[(array->length * 3) + 255]; ++ uint8_t hexval[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; ++ char res[255 + (array->length * 3)]; /* make sure the buffer is big enough*/ ++ int32_t i, n; ++ uint8_t *ptr = array->start + array->offset; ++ ++ for (i = 0; i < array->length; i++) { ++ buf[i * 3] = hexval[(ptr[i] >> 4) & 0xF]; ++ buf[(i * 3) + 1] = hexval[ptr[i] & 0x0F]; ++ buf[(i * 3) + 2] = ' '; /* seperator */ ++ } ++ ++ buf[array->length * 3] = '\0'; ++ n = sprintf(res, "byte_array: length: %d value: %s", array->length, buf); ++ ++ lua_pushlstring(L, res, n); ++ ++ return 1; ++} ++ ++static const struct luaL_Reg bytearray_lib_m [] = { ++ { "__len", get_byte_array_size }, ++ { "__newindex", set_byte_array }, ++ { "__index", get_byte_array }, ++ { "__tostring", byte_array_to_string }, ++ { NULL, NULL } ++}; ++ ++void luaopen_bytearraylib(lua_State *L) ++{ ++ luaL_newmetatable(L, LUA_BYTE_ARRAY); ++ luaL_register(L, NULL, bytearray_lib_m); ++ lua_pop(L, 1); ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/controller.c +@@ -0,0 +1,604 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++#endif ++#include "controller.h" ++ ++/* the array 'supported_protocols' holds all pointers to the ++ * static and dynamic protocol buffers. It is filled by the ++ * call to register_protbuf */ ++static struct protocol_buf * supported_protocols[MAX_NR_OF_PROTOCOLS]; ++ ++/* C_API: the function 'get_protocol_buf' returns the pointer ++ * to the protocol buffer of a given protocol id. */ ++struct protocol_buf * get_protocol_buf(uint32_t protocol_id) ++{ ++ return (struct protocol_buf *)supported_protocols[protocol_id]; ++} ++ ++ ++/* LUA_INT: the function 'gc_packet_segment' is triggered by the ++ * garbage collector whenever a userdata annotated with one of ++ * the protocol buffer metatable should be collected. */ ++static int32_t gc_packet_segment(lua_State *L) ++{ ++ lua_packet_segment * seg = (lua_packet_segment *)lua_touserdata(L, 1); ++ if (seg && seg->changes) { ++ seg->changes->ref_count--; ++ if (seg->changes->ref_count <= 0) { ++ kfree(seg->changes->field_length_changes); ++ kfree(seg->changes->field_offset_changes); ++ kfree(seg->changes); ++ seg->changes = NULL; ++ } ++ } ++ return 0; ++} ++ ++ ++/* LUA_API: the function 'set_raw' is used to set the bytes of a segment ++ * in 'raw' mode. The function is per default available in each protocol ++ * buffer until it gets overridden by a specific setter function inside ++ * a protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * 2. int32_t byte_value ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: void ++ */ ++static int32_t set_raw(lua_State *L) ++{ ++ int32_t i; ++ uint32_t nob; ++ uint8_t byte; ++ uint8_t *ptr; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t val = luaL_checkinteger(L, 2); ++ ++ nob = 1 << CHAR_BIT; ++ ++ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); ++ ++ byte = (uint8_t)val; ++ ptr = seg->start + seg->offset; ++ ++ for (i = 0; i < seg->length; i++) ++ ptr[i] = byte; ++ ++ return 0; ++} ++ ++/* LUA_API: the function 'get_raw' is used to get the bytes of a segment ++ * in 'raw' mode. The function is per default available in each protocol ++ * buffer until it gets overridden by a specific getter function inside ++ * a protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * 2. uint32_t offset ++ * 3. uint32_t length ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * the byte array representing the given array ++ */ ++static int32_t get_raw(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ init_byte_array(L, seg->start + seg->offset, seg->length, 1); ++ ++ return 1; ++} ++/* LUA_API: The function 'get_segment' is used to get a new segment in 'raw' mode. ++ * Typically this function is applied on another raw segment in order ++ * to extract a part of the segment as new segment. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * 2. uint32_t offset, this indicates where to start the new segment, see e.g below. ++ * 3. uint32_t length, this indicates the size of the new segment ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. A lua_packet_segment annotated with the according metatable or False in ++ * case the input data is not valid ++ * ++ * Example: ++ * ++ * +------------------------+---------------------------------------+ ++ * | function call | resulting lua_packet_segment | ++ * +========================+===+===+===+===+===+===+===+===+===+===+ ++ * | seg = packet:raw(0,10) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ++ * +------------------------+---+---+---+---+---+---+---+---+---+---+ ++ * | 1st_half = seg:raw(0,5)| 0 | 1 | 2 | 3 | 4 | | ++ * +------------------------+---+---+---+---+---+---+---+---+---+---+ ++ * | 2nd_half = seg:raw(5,5)| | 5 | 6 | 7 | 8 | 9 | ++ * +------------------------+-------------------+---+---+---+---+---+ ++ */ ++static int32_t get_segment(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint32_t offset = luaL_checkinteger(L, 2); ++ uint32_t length = luaL_checkinteger(L, 3); ++ lua_packet_segment * new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ ++ new->start = seg->start; ++ new->offset = seg->offset + offset; ++ new->changes = NULL; ++ /* we allow a seg->length == 0 , this enables processing packets where the packetsize is not fixed (0 = not fixed)*/ ++ if (seg->length != 0 && length > seg->length) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ new->length = length; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ ++ return 1; ++} ++ ++/* LUA_API: the function 'get_segment_size' is used to get the size of a segment. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. Size as lua_Number ++ */ ++static int32_t get_segment_size(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushnumber(L, seg->length); ++ return 1; ++} ++ ++/* LUA_API: the function 'get_segment_offset' is used to get the real offset ++ * of a segment. This function returns the offset of the segment to the start ++ * of the buffer. This means the following ++ * seg1 = packet:raw(2,10) ++ * seg2 = seg1:raw(3,5) ++ * offset = seg2:get_offset() ++ * ++ * will give an offset of 5, since the seg1 starts at offset 2, and seg2 starts ++ * at offset (seg1:get_offset() + 3). ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. Offset as lua_Number ++ */ ++static int32_t get_segment_offset(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushnumber(L, seg->offset); ++ return 1; ++} ++ ++/* LUA_API: overwrites the __tostring function of a lua_packet_segment. ++ * this will print32_t a nicely formated string, including length, ++ * offset and name of the protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * ++ * Returns: ++ * 1. the representing string ++ */ ++static int32_t packet_segment_tostring(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ int32_t n; ++ char buf[128]; ++ ++ n = sprintf(buf, "type: %s, offset: %d, length: %d", prot_buf->name, seg->offset, seg->length); ++ lua_pushlstring(L, buf, n); ++ ++ return 1; ++} ++ ++ ++static const struct luaL_Reg seg_access_functions [] = { ++ { "set", set_raw }, ++ { "get", get_raw }, ++ { "raw", get_segment }, ++ { "get_offset", get_segment_offset }, ++ { "get_size", get_segment_size }, ++ { "to_bytes", get_raw }, ++ { "__tostring", packet_segment_tostring }, ++ { "__gc", gc_packet_segment }, ++ { NULL, NULL } ++}; ++ ++/* C_API: the function 'get_metatable_from_protocol_type' is a helper ++ * used in controller.c as well as it may find usage in the static ++ * protocol buffers and byte array implementation. */ ++void get_metatable_from_protocol_type(lua_State *L, int32_t type) ++{ ++ char * table; ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ lua_rawgeti(L, -1, type); ++ table = (char *)luaL_checkstring(L, -1); ++ lua_pop(L, 2); /* pop the table SUPPORTED_PROTOCOL_TABLE and the string pushed by lua_gettable */ ++ luaL_getmetatable(L, table); ++ return; ++} ++ ++/* C_INT: the function 'payload_contains_protocol' is used internally. ++ * Depending if static or dynamic protocol buffer it calls the right ++ * validation function. */ ++static int32_t payload_contains_protocol(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment *seg, uint32_t prot_type) ++{ ++ if (prot_buf->is_dynamic) ++ return has_protocol_dynamic(L, prot_buf, seg, prot_type); ++ else ++ return prot_buf->has_protocol(L, prot_buf, seg, prot_type); ++} ++ ++/* C_INT: the function 'protocol_get_field_changes' is used interally. ++ * It requests the field_changes struct calling the protocol buffers ++ * 'get_field_changes' function. This funciton is called, whenever ++ * the payload field with a given protocol type is requested inside ++ * the function 'get_protocol_field' */ ++static struct field_changes * protocol_get_field_changes(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) ++{ ++ struct field_changes * changes = NULL; ++ ++ if (prot_buf->get_field_changes) { ++ if (prot_buf->is_dynamic) ++ changes = get_field_changes_dynamic(L, prot_buf, seg); ++ else ++ changes = prot_buf->get_field_changes(L, seg); ++ /* is already 1 when set by helper 'get_allocated_field_changes, ++ * since not every prot_buf may use this function we enforce it. */ ++ changes->ref_count = 1; ++ } ++ return changes; ++} ++ ++/* C_INT: the function 'get_field_offset_in_bytes' wrapps the logic of ++ * calculating the new length with considering the optional field_changes. */ ++static int32_t get_field_offset_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) ++{ ++ uint32_t nr_of_bits, nr_of_bytes, field_offset; ++ ++ field_offset = field->offset; ++ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ ++ if (seg->changes) ++ field_offset += seg->changes->field_offset_changes[field_index]; ++ /* how many bits remain */ ++ nr_of_bits = field_offset & (CHAR_BIT - 1); ++ /* assuming CHAR_BIT == 2 ^ 3 */ ++ nr_of_bytes = (field_offset - nr_of_bits) >> 3; ++ ++ return seg->offset + nr_of_bytes; ++} ++ ++/* C_INT: the function 'get_field_length_in_bytes' wrapps the logic of ++ * calculating the new offset with considering the optional field_changes. */ ++static int32_t get_field_length_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) ++{ ++ uint32_t nr_of_bits, nr_of_bytes, field_length; ++ ++ field_length = field->length; ++ /* if the field length is smaller than 1 byte, we take the size of one byte ++ * we treat the case where field_length == 0 in a special way ...*/ ++ if (field_length < CHAR_BIT && field_length > 0) ++ field_length = CHAR_BIT; ++ ++ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ ++ if (seg->changes) ++ field_length += seg->changes->field_length_changes[field_index]; ++ /* how many bits remain */ ++ nr_of_bits = field_length & (CHAR_BIT - 1); ++ /* assuming CHAR_BIT == 2 ^ 3 */ ++ nr_of_bytes = (field_length - nr_of_bits) >> 3; ++ return nr_of_bytes; ++} ++ ++/* C_INT: the function 'initialize_field_getter_and_setter' initializes ++ * the setter and getter function of the field, considering the optional ++ * field manipulator functions defined inside the protocol buffers. */ ++static void initialize_field_getter_and_setter(lua_State *L, struct protocol_buf *prot_buf, int32_t field_index) ++{ ++ /* lets check if there is a metatable on top of the stack */ ++ struct protocol_field * f = (struct protocol_field *)&prot_buf->protocol_fields[field_index]; ++ ++ if (!lua_istable(L, -1)) luaL_error(L, "cannot initialize getter and setter for field %s->%s, " ++ "not a table on top of the stack, is '%s'", prot_buf->name, f->name, lua_typename(L, lua_type(L, -1))); ++ ++ /* is there a 'getter' to initialize ? */ ++ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ ++ lua_pushinteger(L, field_index); /* push upvalue 2 */ ++ if (f->get) { ++ if (prot_buf->is_dynamic) ++ lua_pushcclosure(L, field_dynamic_getter, 2); ++ else ++ lua_pushcclosure(L, f->get, 2); ++ }else ++ /* there is no specific getter defined - fall back to 'get_raw' */ ++ lua_pushcclosure(L, get_raw, 2); ++ /* set the metatable field 'get' */ ++ lua_setfield(L, -2, "get"); ++ ++ /* is there a 'setter' to initialize ? */ ++ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ ++ lua_pushinteger(L, field_index); /* push upvalue 2 */ ++ if (f->set) { ++ if (prot_buf->is_dynamic) ++ lua_pushcclosure(L, field_dynamic_setter, 2); ++ else ++ lua_pushcclosure(L, f->set, 2); ++ }else ++ /* there is no specific setter defined - fall back to 'set_raw' */ ++ lua_pushcclosure(L, set_raw, 2); ++ /* set the metatable field 'set' */ ++ lua_setfield(L, -2, "set"); ++} ++ ++/* LUA_API: 'get_protocol_field' is used in Lua as a closure for each field of a protocol ++ * buffer. E.g a call to ip = packet:data(packet_ip) will go to this function, ++ * and trigger the conversion of the raw packet to a ip packet. Each call ++ * to a field function of an IP packet, like ip:daddr() uses this function ++ * to to return the right data. In each case you will end up either with a ++ * new packet segment (annotated with the proper metatable) or a boolean ++ * value (False) if something went wrong. In the case everything went fine, ++ * the newly created lua_packet_segment is annotated with the proper ++ * metatable where the fields get and set also contain the specific getter ++ * and setter functions given by the protocol buffer. E.g. the function call ++ * ip:daddr():get() or ip:daddr():set(...) will call the proper function ++ * defined inside the corresponding field definition. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * 2. type of the protocol buffer, optional, and only used if the accessed ++ * field is the payload field. If a type is provided for the access of the ++ * payload field, the function tries to convert the data pointed to by the ++ * payload field to the given type. To check if such a conversion is ++ * possible, it calls the function pointed to by the protocol buffer member ++ * has_protocol. If this function returns True, the conversion takes place. ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index ++ * ++ * Return: ++ * 1. A lua_packet_segment annotated with the according metatable or False in ++ * case the input data is not valid ++ */ ++static int32_t get_protocol_field(lua_State *L) ++{ ++ int32_t prot_type; ++ lua_packet_segment * seg, *new; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ struct protocol_field * field = &prot_buf->protocol_fields[field_index]; ++ ++ /* get the current packet segment */ ++ seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ /* initialize the new packet segment */ ++ new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ new->start = seg->start; /* the start is unchanged */ ++ new->offset = get_field_offset_in_bytes(field, seg, field_index); ++ new->length = get_field_length_in_bytes(field, seg, field_index); ++ ++ /* if new->length == 0 then no configuration was done, we guess the size by subtracting the ++ * new offset from the packet length. since the old length is getting initialized by the ++ * netfilter extension this assumption holds for the very last field of the protocol. ++ * this 'feature' should be used by protocol buffers containing a payload, whereas the ++ * payload field is the last field of the buffer. However, at compile-time unknown field ++ * sizes (and offsets) of fields not being placed at the end of the protocol should be ++ * initialized using the 'get_field_changes' hook system. */ ++ if (new->length == 0) ++ new->length = (seg->length + seg->offset) - (new->offset); ++ /* ++ printf("%s->%s:: seg->offset %i, seg->length %i, new->offset %i, new->length %i\n", ++ prot_buf->name, field->name, seg->offset, seg->length, new->offset, new->length); ++ */ ++ /* special care for packet payload requests */ ++ if (prot_buf->payload_field != NULL && strcmp(prot_buf->payload_field, field->name) == 0) { ++ /* we know the payload field is requested */ ++ /* the requested payload can be delivered either as a common segment or as ++ * an other packet type, such a conversion needs an extra protocol parameter ++ * ... so lets check */ ++ ++ if (lua_isnumber(L, 2)) { ++ /* we have an extra parameter, ... lets see if it is a valid protocol ++ * the parameter is the index of the 'supported_protocols'-array member */ ++ prot_type = lua_tointeger(L, 2); ++ if (prot_type >= 0 && prot_type < PACKET_SENTINEL) { ++ /* we are sure the purpose of the request is to get the payload data, ++ * converted to the given protocol. lets check if the payload contains ++ * data of the given protocol */ ++ if (payload_contains_protocol(L, prot_buf, seg, prot_type)) { ++ /* success, we can push the metatable for the given protocol */ ++ get_metatable_from_protocol_type(L, prot_type); ++ if (!lua_isnil(L, -1)) /* check if the metatable was found */ ++ /* perhaps the field offsets and lengths of the containing protocol ++ * are not set correctly. request the optional 'field_changes' structure ++ * holding the changes for lengths and offsets. */ ++ new->changes = protocol_get_field_changes(L, get_protocol_buf(prot_type), new); ++ else{ ++ /* failed, the requested protocol is not available ++ * we push false and return */ ++ lua_pop(L, 1); /* pop the userdata */ ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ }else{ ++ /* payload does not carry the provided protocol */ ++ /* we push false and return */ ++ lua_pop(L, 1); /* pop the userdata */ ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ }else{ ++ /* unknown protocol */ ++ lua_pop(L, 1); /* pop the userdata */ ++ luaL_error(L, "provided protocol is unknown"); ++ } ++ } ++ } ++ ++ /* if there is still the 'new' userdata on the top, we push our own metatable */ ++ if (lua_isuserdata(L, -1)) { ++ luaL_getmetatable(L, prot_buf->name); ++ new->changes = seg->changes; ++ if (seg->changes) ++ new->changes->ref_count++; ++ } ++ ++ /* a new packet segment is at index -2 , and the proper metatable at index -1 of the stack ++ * lets set the propper setter and getter function for the requested field */ ++ initialize_field_getter_and_setter(L, prot_buf, field_index); ++ ++ lua_setmetatable(L, -2); ++ return 1; ++} ++ ++/* C_API: 'register_protbuf' is only used internally. This function takes a ++ * pointer to a fully initialized protocol buffer struct and registers it ++ * inside the Lua state. Registering means: ++ * ++ * 1. it creates a new metatable with the name of the protocol buffer. ++ * 2. it registers the default functions which are stored in the luaL_Reg ++ * array seg_access_functions. ++ * 3. it loops over the protocol fields stored at prot_buf->protocol_fields ++ * and registers a new function (using the field name) inside the ++ * metatable. Each field points to the function 'get_protocol_field' ++ * which acts as a closure taking a pointer to the protocol buffer as ++ * well as the index of the field as upvalues. ++ * 4. The protocol index, serves as numerical identifier of this protocol ++ * buffer or even of the protocol itself. This index is stored as a ++ * global value inside the Lua state as well as inside the Lua table ++ * 'supported_protocols'. Assuming the name of a procotol buffer is ++ * "packet_ip" the following statements are true: ++ * ++ * supported_protocols[protocol_index] == "packet_ip" ++ * packet_ip == protocol_index ++ * ++ * This allows you to get all registered protocols from within Lua. This ++ * is especially usefull for the dynamic protocol buffers where you have ++ * to provide your own "has_protocol"-function, which probably needs the ++ * information on which protocols it is able to contain. ++ */ ++void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, uint32_t protocol_index) ++{ ++ int32_t field_index; ++ luaL_Reg *reg = (struct luaL_Reg *)seg_access_functions; ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ luaL_newmetatable(L, prot_buf->name); ++ ++ /* metatable.__index = metatable */ ++ lua_pushvalue(L, -1); /* duplicates the metatable */ ++ lua_setfield(L, -2, "__index"); ++ ++ /* pushing default functions */ ++ for (; reg->name; reg++) { ++ lua_pushlightuserdata(L, (void *)prot_buf); ++ lua_pushcclosure(L, reg->func, 1); ++ lua_setfield(L, -2, reg->name); ++ } ++ ++ /* pushing functions specific to the protocol buffer */ ++ for (field_index = 0; field->name; field++, field_index++) { ++ lua_pushlightuserdata(L, (void *)prot_buf); /* upvalue: prot_buf */ ++ lua_pushinteger(L, field_index); /* upvalue: index of protocol field */ ++ lua_pushcclosure(L, get_protocol_field, 2); ++ lua_setfield(L, -2, field->name); ++ } ++ /* pop the metatable */ ++ lua_pop(L, 1); ++ ++ /* registering the array-index as the protocol_id*/ ++ lua_getglobal(L, "_G"); ++ lua_pushinteger(L, protocol_index); ++ lua_setfield(L, -2, prot_buf->name); ++ lua_pop(L, 1); /* pop _G */ ++ ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ lua_pushstring(L, prot_buf->name); ++ lua_rawseti(L, -2, protocol_index); ++ ++ lua_pop(L, 1); /* pop SUPPORTED_PROTOCOL_TABLE */ ++ ++ supported_protocols[protocol_index] = prot_buf; ++} ++ ++void luaopen_controller(lua_State *L) ++{ ++ /* registering a table inside the _G with table[protocol_index] = prot_buf->name */ ++ lua_getglobal(L, "_G"); ++ lua_newtable(L); ++ lua_setfield(L, -2, SUPPORTED_PROTOCOL_TABLE); ++ lua_pop(L, 1); /* pop _G */ ++ ++ luaopen_protbuf_raw(L); ++ luaopen_protbuf_eth(L); ++ luaopen_protbuf_ip(L); ++ luaopen_protbuf_icmp(L); ++ luaopen_protbuf_tcp(L); ++ luaopen_protbuf_tcp_options(L); ++ luaopen_protbuf_udp(L); ++ luaopen_protbuf_tftp(L); ++ luaopen_protbuf_dynamic(L); ++ /* should follow all other static buffers */ ++#if defined(__KERNEL__) ++ luaopen_nflib(L); ++#endif ++ ++ luaopen_bytearraylib(L); ++} ++ ++ ++ ++ +--- /dev/null ++++ b/extensions/LUA/controller.h +@@ -0,0 +1,264 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#ifndef CONTROLLER_H_ ++#define CONTROLLER_H_ ++ ++#include "stdlib.h" /* wrapper */ ++#include "string.h" /* wrapper */ ++#include "lua.h" ++#include "lualib.h" ++#include "lauxlib.h" ++ ++#if defined(__KERNEL__) ++#include ++#include ++#include ++#endif ++ ++ ++/* to compile the stuff in userspace (for testing)*/ ++#if !defined(__KERNEL__) ++#include ++#define pr_debug printf; ++ ++#define kmalloc(size, type) malloc(size) ++#define kfree(ptr) free(ptr) ++ ++#endif ++ ++ ++/**********************************************************************/ ++/* nf Lua configuration */ ++/**********************************************************************/ ++#define MAX_NR_OF_PROTOCOLS 16 ++#define SUPPORTED_PROTOCOL_TABLE "supported_protocols" ++ ++#define MAX_NR_OF_FIELDS_IN_DYN_PROT_BUF 32 ++ ++ ++/**********************************************************************/ ++/* Static Protocol Buffer configuration */ ++/**********************************************************************/ ++ ++/* the definitions of the stringified expression of the prot_bufs... ++ * make sure all static prot_bufs are listed and are unique */ ++#define LUA_PACKET_SEG_RAW "packet_raw" ++#define LUA_PACKET_SEG_ETH "packet_eth" ++#define LUA_PACKET_SEG_ICMP "packet_icmp" ++#define LUA_PACKET_SEG_IP "packet_ip" ++#define LUA_PACKET_SEG_TCP "packet_tcp" ++#define LUA_PACKET_SEG_TCP_OPT "packet_tcp_opt" ++#define LUA_PACKET_SEG_UDP "packet_udp" ++#define LUA_PACKET_SEG_TFTP "packet_tftp" ++ ++/* the enum holding all static prot_bufs... make sure it contains all ++ * static prot_bufs */ ++enum PROT_BUF { ++ PACKET_RAW, ++ PACKET_ETH, ++ PACKET_IP, ++ PACKET_ICMP, ++ PACKET_TCP, ++ PACKET_TCP_OPTIONS, ++ PACKET_UDP, ++ PACKET_TFTP, ++ PACKET_DYNAMIC, ++ PACKET_SENTINEL ++}; ++ ++/* the luaopen-function of the prot_bufs... make sure it is called ++ * inside luaopen_controller */ ++void luaopen_protbuf_raw(lua_State *L); ++void luaopen_protbuf_eth(lua_State *L); ++void luaopen_protbuf_ip(lua_State *L); ++void luaopen_protbuf_icmp(lua_State *L); ++void luaopen_protbuf_tcp(lua_State *L); ++void luaopen_protbuf_tcp_options(lua_State *L); ++void luaopen_protbuf_udp(lua_State *L); ++void luaopen_protbuf_tftp(lua_State *L); ++void luaopen_protbuf_dynamic(lua_State *L); ++ ++/**********************************************************************/ ++/* field changes */ ++/**********************************************************************/ ++struct field_changes { ++ int ref_count; ++ int *field_length_changes; ++ int *field_offset_changes; ++}; ++ ++/**********************************************************************/ ++/* lua packet segment */ ++/* ------------------ */ ++/* The struct lua_packet_segment is the integral part of a Lua packet.*/ ++/* At the very beginning, when a new packet arrives in `lua_tg`_ such */ ++/* a struct is initialized. The field start then points to the lowest */ ++/* available header inside the sk_buff structure. During packet */ ++/* processing the start pointer remains the same, only the offset and */ ++/* length value change. */ ++/**********************************************************************/ ++#define checkpacketseg(L, i, seg_type) \ ++ (lua_packet_segment *)luaL_checkudata(L, i, seg_type) ++ ++typedef struct lua_packet_segment { ++ unsigned int offset; ++ unsigned int length; ++ struct field_changes * changes; ++ unsigned char * start; /* need to be at the end because of the memory alignment */ ++} lua_packet_segment; ++ ++/**********************************************************************/ ++/* protocol field */ ++/* -------------- */ ++/* This structure is a container for the field definitions used by the*/ ++/* protocol buffer. Each protocol field is expressed using this struct*/ ++/* Have a look at the protocol buffers to see how the struct gets */ ++/* initialized. */ ++/* */ ++/* name: */ ++/* This member expresses the name of the field, ending */ ++/* in its own Lua function to access the field. */ ++/* offset / length: */ ++/* These members do specify the position inside the protocol header */ ++/* in bits (not bytes!). */ ++/* get / set: */ ++/* The get and set functions take a function pointer pointing to the*/ ++/* specific getter and setter function for this field. */ ++/**********************************************************************/ ++struct protocol_field { ++ const char * name; ++ uint32_t offset; ++ uint32_t length; ++ lua_CFunction get; ++ lua_CFunction set; ++}; ++#define PROT_FIELD_SENTINEL { NULL, 0, 0, NULL, NULL } ++ ++ ++/**********************************************************************/ ++/* protocol_buf */ ++/**********************************************************************/ ++/* This structure is a container for all the information needed for a ++ * protocol buffer. It gets initialized in each protocol buffer header ++ * file or for the dynamic protocol buffers on runtime using the ++ * 'register_dynamic_protocol_buffer' function. ++ * ++ * name: ++ * This member is used throughout the system. It is also exported ++ * to Lua as a variable name holding the index of the 'supported_protocols' ++ * array. The name is also used as the name of the generated Lua ++ * metatable, that is why inside the macro checkpacketseg_ it ++ * is always the name of a protocol buffer that is passed as the ++ * second parameter. ++ * payload_field: ++ * This member holds the string of the field responsible for payload ++ * data. The payload field of a protocol has an extra property, since ++ * it can be used to invoke another protocol buffer that is applied to ++ * the payload content. ++ * has_protocol: ++ * This member is used together with the payload_field. Since we must ++ * be sure that the payload content does really contain a protocol ++ * of type X. The function pointed to by has_protocol checks if the ++ * protocol buffer X can be applied on the payload_data. ++ * protocol_fields: ++ * This member points to the array of 'protocol_field' structures ++ * get_field_changes: ++ * This member is optional. It is used to return a pointer to an initialized ++ * field_changes struct. The function is called, whenever the payload field ++ * is requested with a given protocol type. Usually this function will ++ * initialize the field_changes struct depending on the content of the ++ * payload data. e.g. ++ * tcp = ip:data(packet_tcp) ++ * such a request will call the 'get_field_changes' function of the tcp ++ * protocol buffer. This enables, that the tcp options field have the proper ++ * length as well as the tcp data start at the right offset. ++ */ ++struct protocol_buf { ++ int is_dynamic; ++ const char * name; ++ char * payload_field; ++ int (*has_protocol)(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg, int type); ++ struct protocol_field * protocol_fields; ++ struct field_changes * (*get_field_changes)(lua_State *L, lua_packet_segment * seg); ++}; ++ ++/**********************************************************************/ ++/* lua byte array library */ ++/**********************************************************************/ ++#define LUA_BYTE_ARRAY "byte_array" ++#define checkbytearray(L, i) \ ++ (lua_packet_segment *)luaL_checkudata(L, i, LUA_BYTE_ARRAY) ++lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy); ++void luaopen_bytearraylib(lua_State *L); ++ ++ ++/**********************************************************************/ ++/* lua netfilter environment library */ ++/**********************************************************************/ ++#define NETFILTER_LIB "nf" ++#if defined(__KERNEL__) ++ struct lua_env { ++ lua_State *L; ++ /* perhaps more to come here (e.g. a state per CPU) */ ++ }; ++ #define LUA_ENV "lua_env" ++ #define checkluaenv(L, i) \ ++ (struct lua_env *)luaL_checkudata(L, i, LUA_ENV) ++ ++ void luaopen_nflib(lua_State *L); ++#endif ++ ++void cleanup_dynamic_prot_bufs(void); /* freeing all dynamic prot bufs */ ++/**********************************************************************/ ++/* lua protbuf helpers */ ++/**********************************************************************/ ++int get_1_bit_generic(lua_State *L); ++int set_1_bit_generic(lua_State *L); ++int get_lower_4_bit_generic(lua_State *L); ++int set_lower_4_bit_generic(lua_State *L); ++int get_upper_4_bit_generic(lua_State *L); ++int set_upper_4_bit_generic(lua_State *L); ++int get_8_bit_generic(lua_State *L); ++int set_8_bit_generic(lua_State *L); ++int get_16_bit_generic(lua_State *L); ++int set_16_bit_generic(lua_State *L); ++int get_32_bit_generic(lua_State *L); ++int set_32_bit_generic(lua_State *L); ++int set_data_generic(lua_State *L); ++int get_string_generic(lua_State *L); ++int get_byte_generic_str(lua_State *L); ++struct field_changes * get_allocated_field_changes(lua_State *L, int nr_of_fields); ++ ++/* only used by the dynamic prot buf subsystem */ ++#define MAX_NR_OF_DYN_PROT_BUFS 16 ++int field_dynamic_setter(lua_State *L); ++int field_dynamic_getter(lua_State *L); ++int has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int type); ++struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg); ++ ++/**********************************************************************/ ++/* lua controller API */ ++/**********************************************************************/ ++void luaopen_controller(lua_State *L); ++struct protocol_buf * get_protocol_buf(unsigned int protocol_id); ++void get_metatable_from_protocol_type(lua_State *L, int type); ++void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, unsigned int protocol_index); ++ ++ ++#endif /* CONTROLLER_H_ */ +--- /dev/null ++++ b/extensions/LUA/Kbuild +@@ -0,0 +1,49 @@ ++# -*- Makefile -*- ++ ++# Adding debug options ++EXTRA_CFLAGS += -DDEBUG ++ ++obj-m += xt_LUA.o ++ ++EXTRA_CFLAGS += -I$(src)/prot_buf_new ++xt_LUA-y += xt_LUA_target.o \ ++ ++xt_LUA-y += nf_lua.o \ ++ prot_buf_helpers.o \ ++ byte_array.o \ ++ controller.o \ ++ prot_buf_ethernet.o \ ++ prot_buf_icmp.o \ ++ prot_buf_ip.o \ ++ prot_buf_raw.o \ ++ prot_buf_tcp.o \ ++ prot_buf_udp.o \ ++ prot_buf_tftp.o \ ++ prot_buf_dynamic.o \ ++ ++ ++# Adding Lua Support ++EXTRA_CFLAGS += -I$(src)/lua -I$(src)/lua/include ++xt_LUA-y += lua/lapi.o \ ++ lua/lbaselib.o \ ++ lua/lcode.o \ ++ lua/ldebug.o \ ++ lua/ldo.o \ ++ lua/ldump.o \ ++ lua/lfunc.o \ ++ lua/lgc.o \ ++ lua/llex.o \ ++ lua/lmem.o \ ++ lua/lobject.o \ ++ lua/lopcodes.o \ ++ lua/lparser.o \ ++ lua/lstate.o \ ++ lua/lstring.o \ ++ lua/lstrlib.o \ ++ lua/ltable.o \ ++ lua/ltablib.o \ ++ lua/ltm.o \ ++ lua/lundump.o \ ++ lua/lvm.o \ ++ lua/lzio.o \ ++ lua/lauxlib.o \ +--- /dev/null ++++ b/extensions/LUA/libxt_LUA.c +@@ -0,0 +1,191 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "xt_LUA.h" ++ ++enum { ++ FLAG_SCRIPT = 1 << 0, ++ FLAG_STATE = 1 << 1, ++ FLAG_FUNCTION = 1 << 2, ++}; ++ ++static const struct option lua_tg_opts[] = { ++ { .name = "script", .has_arg = true, .val = 's' }, ++ { .name = "state", .has_arg = true, .val = 'l' }, ++ { .name = "function", .has_arg = true, .val = 'f' }, ++ { NULL }, ++}; ++ ++ ++static void lua_tg_help(void) ++{ ++ printf( ++ "LUA target options:\n" ++ " --script SCRIPT Process packet with the Lua script given by SCRIPT\n" ++ " \n" ++ " --state ID Process packet within the Lua state given by ID.\n" ++ " Omitting --state infers the ID 0, which can be\n" ++ " refered to the 'global' state.\n" ++ " \n" ++ " --function FUNCTION Name of the function that processes the Lua packet\n" ++ "\n"); ++} ++ ++static void ++lua_tg_init(struct xt_entry_target *target) ++{ ++ struct xt_lua_tginfo *info = (void *)target->data; ++ ++ info->state_id = 0; ++ strncpy(info->function, "process_packet\0", sizeof("process_packet\0")); ++} ++ ++static int ++lua_tg_parse(int32_t c, char **argv, int32_t invert, uint32_t *flags, ++ const void *entry, struct xt_entry_target **target) ++{ ++ struct xt_lua_tginfo *info = (void *)(*target)->data; ++ char buf[MAX_SCRIPT_SIZE]; ++ long script_size; ++ uint32_t state_id; ++ FILE *file; ++ ++ switch (c) { ++ case 's': ++ if (*flags & FLAG_SCRIPT) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --script more than once"); ++ ++ if (strlen(optarg) > sizeof(info->filename)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Maximum script length is %zu", ++ sizeof(info->filename)); ++ ++ if (strchr(optarg, '\n')) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Newlines not allowed in script name"); ++ file = fopen(optarg, "rb"); ++ if (file != NULL) { ++ fseek(file, 0, SEEK_END); ++ script_size = ftell(file); ++ if (script_size > MAX_SCRIPT_SIZE) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: The size of the script is too big"); ++ ++ fseek(file, 0, SEEK_SET); ++ fread(buf, script_size, 1, file); ++ fclose(file); ++ } else ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot open script %s", optarg); ++ ++ strncpy(info->filename, optarg, sizeof(info->filename)); ++ strncpy(info->buf, buf, sizeof(info->buf)); ++ info->script_size = script_size; ++ ++ *flags |= FLAG_SCRIPT; ++ return true; ++ ++ case 'l': ++ if (*flags & FLAG_STATE) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --state more than once"); ++ ++ if (!xtables_strtoui(optarg, NULL, &state_id, 0, 8)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Invalid --state %s", optarg); ++ ++ info->state_id = state_id; ++ *flags |= FLAG_STATE; ++ return true; ++ ++ case 'f': ++ if (*flags & FLAG_FUNCTION) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --function more than once"); ++ if (strlen(optarg) > sizeof(info->function)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Maximum function length is %zu", ++ sizeof(info->function)); ++ ++ if (strchr(optarg, '\n')) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Newlines not allowed in function name"); ++ ++ strncpy(info->function, optarg, sizeof(info->function)); ++ ++ *flags |= FLAG_FUNCTION; ++ return true; ++ } ++ ++ return false; ++} ++ ++static void ++lua_tg_check(uint32_t flags) ++{ ++ if (flags == 0) ++ xtables_error(PARAMETER_PROBLEM, "LUA: --script parameter required"); ++} ++ ++static void ++lua_tg_print(const void *entry, const struct xt_entry_target *target, ++ int32_t numeric) ++{ ++ const struct xt_lua_tginfo *info = (const void *)target->data; ++ ++ printf("LUA script: %s ", info->filename); ++} ++ ++static void ++lua_tg_save(const void *entry, const struct xt_entry_target *target) ++{ ++ const struct xt_lua_tginfo *info = (const void *)target->data; ++ ++ printf("--script %s ", info->filename); ++} ++ ++static struct xtables_target lua_tg_reg = { ++ .name = "LUA", ++ .version = XTABLES_VERSION, ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .size = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .help = lua_tg_help, ++ .init = lua_tg_init, ++ .parse = lua_tg_parse, ++ .final_check = lua_tg_check, ++ .print = lua_tg_print, ++ .save = lua_tg_save, ++ .extra_opts = lua_tg_opts, ++}; ++ ++static __attribute__((constructor)) void lua_tg_ldr(void) ++{ ++ xtables_register_target(&lua_tg_reg); ++} ++ +--- /dev/null ++++ b/extensions/LUA/libxt_LUA.man +@@ -0,0 +1 @@ ++Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +--- /dev/null ++++ b/extensions/LUA/lua/include/ctype.h +@@ -0,0 +1,11 @@ ++#include ++#undef isalnum ++#define isalnum(c) (((__ismask(c)&(_U|_L|_D)) != 0) && (c > 0)) ++#undef isalpha ++#define isalpha(c) (((__ismask(c)&(_U|_L)) != 0) && (c > 0)) ++#undef iscntrl ++#define iscntrl(c) (((__ismask(c)&(_C)) != 0) && (c > 0)) ++#undef isdigit ++#define isdigit(c) (((__ismask(c)&(_D)) != 0) && (c > 0)) ++#undef isspace ++#define isspace(c) (((__ismask(c)&(_S)) != 0) && (c > 0)) +--- /dev/null ++++ b/extensions/LUA/lua/include/errno.h +@@ -0,0 +1 @@ ++#include +--- /dev/null ++++ b/extensions/LUA/lua/include/locale.h +@@ -0,0 +1,5 @@ ++struct lconv { ++ char * decimal_point ; ++} ; ++ ++#define localeconv() NULL +--- /dev/null ++++ b/extensions/LUA/lua/include/setjmp.h +@@ -0,0 +1,26 @@ ++/* ++ * arch/um/include/sysdep-i386/archsetjmp.h ++ */ ++ ++#ifndef _KLIBC_ARCHSETJMP_H ++#define _KLIBC_ARCHSETJMP_H ++ ++struct __jmp_buf { ++ unsigned int __ebx; ++ unsigned int __esp; ++ unsigned int __ebp; ++ unsigned int __esi; ++ unsigned int __edi; ++ unsigned int __eip; ++}; ++ ++typedef struct __jmp_buf jmp_buf[1]; ++ ++#define JB_IP __eip ++#define JB_SP __esp ++ ++int setjmp(jmp_buf); ++void longjmp(jmp_buf, int); ++ ++#endif /* _SETJMP_H */ ++ +--- /dev/null ++++ b/extensions/LUA/lua/include/stdio.h +@@ -0,0 +1 @@ ++#include +--- /dev/null ++++ b/extensions/LUA/lua/include/stdlib.h +@@ -0,0 +1,7 @@ ++#include ++ ++#define exit(E) return ++#define strtoul simple_strtoul ++#define strcoll strcmp ++ ++#define CHAR_BIT 8 +--- /dev/null ++++ b/extensions/LUA/lua/include/string.h +@@ -0,0 +1 @@ ++#include +--- /dev/null ++++ b/extensions/LUA/lua/lapi.c +@@ -0,0 +1,1086 @@ ++/* ++** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ ++** Lua API ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#define lapi_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lapi.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lundump.h" ++#include "lvm.h" ++ ++ ++ ++const char lua_ident[] = ++ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" ++ "$Authors: " LUA_AUTHORS " $\n" ++ "$URL: www.lua.org $\n"; ++ ++ ++ ++#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) ++ ++#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) ++ ++#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} ++ ++ ++ ++static TValue *index2adr (lua_State *L, int idx) { ++ if (idx > 0) { ++ TValue *o = L->base + (idx - 1); ++ api_check(L, idx <= L->ci->top - L->base); ++ if (o >= L->top) return cast(TValue *, luaO_nilobject); ++ else return o; ++ } ++ else if (idx > LUA_REGISTRYINDEX) { ++ api_check(L, idx != 0 && -idx <= L->top - L->base); ++ return L->top + idx; ++ } ++ else switch (idx) { /* pseudo-indices */ ++ case LUA_REGISTRYINDEX: return registry(L); ++ case LUA_ENVIRONINDEX: { ++ Closure *func = curr_func(L); ++ sethvalue(L, &L->env, func->c.env); ++ return &L->env; ++ } ++ case LUA_GLOBALSINDEX: return gt(L); ++ default: { ++ Closure *func = curr_func(L); ++ idx = LUA_GLOBALSINDEX - idx; ++ return (idx <= func->c.nupvalues) ++ ? &func->c.upvalue[idx-1] ++ : cast(TValue *, luaO_nilobject); ++ } ++ } ++} ++ ++ ++static Table *getcurrenv (lua_State *L) { ++ if (L->ci == L->base_ci) /* no enclosing function? */ ++ return hvalue(gt(L)); /* use global table as environment */ ++ else { ++ Closure *func = curr_func(L); ++ return func->c.env; ++ } ++} ++ ++ ++void luaA_pushobject (lua_State *L, const TValue *o) { ++ setobj2s(L, L->top, o); ++ api_incr_top(L); ++} ++ ++ ++LUA_API int lua_checkstack (lua_State *L, int size) { ++ int res = 1; ++ lua_lock(L); ++ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) ++ res = 0; /* stack overflow */ ++ else if (size > 0) { ++ luaD_checkstack(L, size); ++ if (L->ci->top < L->top + size) ++ L->ci->top = L->top + size; ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { ++ int i; ++ if (from == to) return; ++ lua_lock(to); ++ api_checknelems(from, n); ++ api_check(from, G(from) == G(to)); ++ api_check(from, to->ci->top - to->top >= n); ++ from->top -= n; ++ for (i = 0; i < n; i++) { ++ setobj2s(to, to->top++, from->top + i); ++ } ++ lua_unlock(to); ++} ++ ++ ++LUA_API void lua_setlevel (lua_State *from, lua_State *to) { ++ to->nCcalls = from->nCcalls; ++} ++ ++ ++LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { ++ lua_CFunction old; ++ lua_lock(L); ++ old = G(L)->panic; ++ G(L)->panic = panicf; ++ lua_unlock(L); ++ return old; ++} ++ ++ ++LUA_API lua_State *lua_newthread (lua_State *L) { ++ lua_State *L1; ++ lua_lock(L); ++ luaC_checkGC(L); ++ L1 = luaE_newthread(L); ++ setthvalue(L, L->top, L1); ++ api_incr_top(L); ++ lua_unlock(L); ++ luai_userstatethread(L, L1); ++ return L1; ++} ++ ++ ++ ++/* ++** basic stack manipulation ++*/ ++ ++ ++LUA_API int lua_gettop (lua_State *L) { ++ return cast_int(L->top - L->base); ++} ++ ++ ++LUA_API void lua_settop (lua_State *L, int idx) { ++ lua_lock(L); ++ if (idx >= 0) { ++ api_check(L, idx <= L->stack_last - L->base); ++ while (L->top < L->base + idx) ++ setnilvalue(L->top++); ++ L->top = L->base + idx; ++ } ++ else { ++ api_check(L, -(idx+1) <= (L->top - L->base)); ++ L->top += idx+1; /* `subtract' index (index is negative) */ ++ } ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_remove (lua_State *L, int idx) { ++ StkId p; ++ lua_lock(L); ++ p = index2adr(L, idx); ++ api_checkvalidindex(L, p); ++ while (++p < L->top) setobjs2s(L, p-1, p); ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_insert (lua_State *L, int idx) { ++ StkId p; ++ StkId q; ++ lua_lock(L); ++ p = index2adr(L, idx); ++ api_checkvalidindex(L, p); ++ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); ++ setobjs2s(L, p, L->top); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_replace (lua_State *L, int idx) { ++ StkId o; ++ lua_lock(L); ++ /* explicit test for incompatible code */ ++ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) ++ luaG_runerror(L, "no calling environment"); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ if (idx == LUA_ENVIRONINDEX) { ++ Closure *func = curr_func(L); ++ api_check(L, ttistable(L->top - 1)); ++ func->c.env = hvalue(L->top - 1); ++ luaC_barrier(L, func, L->top - 1); ++ } ++ else { ++ setobj(L, o, L->top - 1); ++ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ ++ luaC_barrier(L, curr_func(L), L->top - 1); ++ } ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushvalue (lua_State *L, int idx) { ++ lua_lock(L); ++ setobj2s(L, L->top, index2adr(L, idx)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++ ++/* ++** access functions (stack -> C) ++*/ ++ ++ ++LUA_API int lua_type (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); ++} ++ ++ ++LUA_API const char *lua_typename (lua_State *L, int t) { ++ UNUSED(L); ++ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; ++} ++ ++ ++LUA_API int lua_iscfunction (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return iscfunction(o); ++} ++ ++ ++LUA_API int lua_isnumber (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ return tonumber(o, &n); ++} ++ ++ ++LUA_API int lua_isstring (lua_State *L, int idx) { ++ int t = lua_type(L, idx); ++ return (t == LUA_TSTRING || t == LUA_TNUMBER); ++} ++ ++ ++LUA_API int lua_isuserdata (lua_State *L, int idx) { ++ const TValue *o = index2adr(L, idx); ++ return (ttisuserdata(o) || ttislightuserdata(o)); ++} ++ ++ ++LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { ++ StkId o1 = index2adr(L, index1); ++ StkId o2 = index2adr(L, index2); ++ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 ++ : luaO_rawequalObj(o1, o2); ++} ++ ++ ++LUA_API int lua_equal (lua_State *L, int index1, int index2) { ++ StkId o1, o2; ++ int i; ++ lua_lock(L); /* may call tag method */ ++ o1 = index2adr(L, index1); ++ o2 = index2adr(L, index2); ++ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); ++ lua_unlock(L); ++ return i; ++} ++ ++ ++LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { ++ StkId o1, o2; ++ int i; ++ lua_lock(L); /* may call tag method */ ++ o1 = index2adr(L, index1); ++ o2 = index2adr(L, index2); ++ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 ++ : luaV_lessthan(L, o1, o2); ++ lua_unlock(L); ++ return i; ++} ++ ++ ++ ++LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) ++ return nvalue(o); ++ else ++ return 0; ++} ++ ++ ++LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) { ++ lua_Integer res; ++ lua_Number num = nvalue(o); ++ lua_number2integer(res, num); ++ return res; ++ } ++ else ++ return 0; ++} ++ ++ ++LUA_API int lua_toboolean (lua_State *L, int idx) { ++ const TValue *o = index2adr(L, idx); ++ return !l_isfalse(o); ++} ++ ++ ++LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { ++ StkId o = index2adr(L, idx); ++ if (!ttisstring(o)) { ++ lua_lock(L); /* `luaV_tostring' may create a new string */ ++ if (!luaV_tostring(L, o)) { /* conversion failed? */ ++ if (len != NULL) *len = 0; ++ lua_unlock(L); ++ return NULL; ++ } ++ luaC_checkGC(L); ++ o = index2adr(L, idx); /* previous call may reallocate the stack */ ++ lua_unlock(L); ++ } ++ if (len != NULL) *len = tsvalue(o)->len; ++ return svalue(o); ++} ++ ++ ++LUA_API size_t lua_objlen (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TSTRING: return tsvalue(o)->len; ++ case LUA_TUSERDATA: return uvalue(o)->len; ++ case LUA_TTABLE: return luaH_getn(hvalue(o)); ++ case LUA_TNUMBER: { ++ size_t l; ++ lua_lock(L); /* `luaV_tostring' may create a new string */ ++ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); ++ lua_unlock(L); ++ return l; ++ } ++ default: return 0; ++ } ++} ++ ++ ++LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; ++} ++ ++ ++LUA_API void *lua_touserdata (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TUSERDATA: return (rawuvalue(o) + 1); ++ case LUA_TLIGHTUSERDATA: return pvalue(o); ++ default: return NULL; ++ } ++} ++ ++ ++LUA_API lua_State *lua_tothread (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (!ttisthread(o)) ? NULL : thvalue(o); ++} ++ ++ ++LUA_API const void *lua_topointer (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TTABLE: return hvalue(o); ++ case LUA_TFUNCTION: return clvalue(o); ++ case LUA_TTHREAD: return thvalue(o); ++ case LUA_TUSERDATA: ++ case LUA_TLIGHTUSERDATA: ++ return lua_touserdata(L, idx); ++ default: return NULL; ++ } ++} ++ ++ ++ ++/* ++** push functions (C -> stack) ++*/ ++ ++ ++LUA_API void lua_pushnil (lua_State *L) { ++ lua_lock(L); ++ setnilvalue(L->top); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { ++ lua_lock(L); ++ setnvalue(L->top, n); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { ++ lua_lock(L); ++ setnvalue(L->top, cast_num(n)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { ++ lua_lock(L); ++ luaC_checkGC(L); ++ setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushstring (lua_State *L, const char *s) { ++ if (s == NULL) ++ lua_pushnil(L); ++ else ++ lua_pushlstring(L, s, strlen(s)); ++} ++ ++ ++LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, ++ va_list argp) { ++ const char *ret; ++ lua_lock(L); ++ luaC_checkGC(L); ++ ret = luaO_pushvfstring(L, fmt, argp); ++ lua_unlock(L); ++ return ret; ++} ++ ++ ++LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { ++ const char *ret; ++ va_list argp; ++ lua_lock(L); ++ luaC_checkGC(L); ++ va_start(argp, fmt); ++ ret = luaO_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ lua_unlock(L); ++ return ret; ++} ++ ++ ++LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { ++ Closure *cl; ++ lua_lock(L); ++ luaC_checkGC(L); ++ api_checknelems(L, n); ++ cl = luaF_newCclosure(L, n, getcurrenv(L)); ++ cl->c.f = fn; ++ L->top -= n; ++ while (n--) ++ setobj2n(L, &cl->c.upvalue[n], L->top+n); ++ setclvalue(L, L->top, cl); ++ lua_assert(iswhite(obj2gco(cl))); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushboolean (lua_State *L, int b) { ++ lua_lock(L); ++ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { ++ lua_lock(L); ++ setpvalue(L->top, p); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_pushthread (lua_State *L) { ++ lua_lock(L); ++ setthvalue(L, L->top, L); ++ api_incr_top(L); ++ lua_unlock(L); ++ return (G(L)->mainthread == L); ++} ++ ++ ++ ++/* ++** get functions (Lua -> stack) ++*/ ++ ++ ++LUA_API void lua_gettable (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ luaV_gettable(L, t, L->top - 1, L->top - 1); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { ++ StkId t; ++ TValue key; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ setsvalue(L, &key, luaS_new(L, k)); ++ luaV_gettable(L, t, &key, L->top); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawget (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { ++ StkId o; ++ lua_lock(L); ++ o = index2adr(L, idx); ++ api_check(L, ttistable(o)); ++ setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { ++ lua_lock(L); ++ luaC_checkGC(L); ++ sethvalue(L, L->top, luaH_new(L, narray, nrec)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_getmetatable (lua_State *L, int objindex) { ++ const TValue *obj; ++ Table *mt = NULL; ++ int res; ++ lua_lock(L); ++ obj = index2adr(L, objindex); ++ switch (ttype(obj)) { ++ case LUA_TTABLE: ++ mt = hvalue(obj)->metatable; ++ break; ++ case LUA_TUSERDATA: ++ mt = uvalue(obj)->metatable; ++ break; ++ default: ++ mt = G(L)->mt[ttype(obj)]; ++ break; ++ } ++ if (mt == NULL) ++ res = 0; ++ else { ++ sethvalue(L, L->top, mt); ++ api_incr_top(L); ++ res = 1; ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++LUA_API void lua_getfenv (lua_State *L, int idx) { ++ StkId o; ++ lua_lock(L); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ switch (ttype(o)) { ++ case LUA_TFUNCTION: ++ sethvalue(L, L->top, clvalue(o)->c.env); ++ break; ++ case LUA_TUSERDATA: ++ sethvalue(L, L->top, uvalue(o)->env); ++ break; ++ case LUA_TTHREAD: ++ setobj2s(L, L->top, gt(thvalue(o))); ++ break; ++ default: ++ setnilvalue(L->top); ++ break; ++ } ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++/* ++** set functions (stack -> Lua) ++*/ ++ ++ ++LUA_API void lua_settable (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ api_checknelems(L, 2); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ luaV_settable(L, t, L->top - 2, L->top - 1); ++ L->top -= 2; /* pop index and value */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { ++ StkId t; ++ TValue key; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ setsvalue(L, &key, luaS_new(L, k)); ++ luaV_settable(L, t, &key, L->top - 1); ++ L->top--; /* pop value */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawset (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ api_checknelems(L, 2); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); ++ luaC_barriert(L, hvalue(t), L->top-1); ++ L->top -= 2; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawseti (lua_State *L, int idx, int n) { ++ StkId o; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_check(L, ttistable(o)); ++ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); ++ luaC_barriert(L, hvalue(o), L->top-1); ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_setmetatable (lua_State *L, int objindex) { ++ TValue *obj; ++ Table *mt; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ obj = index2adr(L, objindex); ++ api_checkvalidindex(L, obj); ++ if (ttisnil(L->top - 1)) ++ mt = NULL; ++ else { ++ api_check(L, ttistable(L->top - 1)); ++ mt = hvalue(L->top - 1); ++ } ++ switch (ttype(obj)) { ++ case LUA_TTABLE: { ++ hvalue(obj)->metatable = mt; ++ if (mt) ++ luaC_objbarriert(L, hvalue(obj), mt); ++ break; ++ } ++ case LUA_TUSERDATA: { ++ uvalue(obj)->metatable = mt; ++ if (mt) ++ luaC_objbarrier(L, rawuvalue(obj), mt); ++ break; ++ } ++ default: { ++ G(L)->mt[ttype(obj)] = mt; ++ break; ++ } ++ } ++ L->top--; ++ lua_unlock(L); ++ return 1; ++} ++ ++ ++LUA_API int lua_setfenv (lua_State *L, int idx) { ++ StkId o; ++ int res = 1; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ api_check(L, ttistable(L->top - 1)); ++ switch (ttype(o)) { ++ case LUA_TFUNCTION: ++ clvalue(o)->c.env = hvalue(L->top - 1); ++ break; ++ case LUA_TUSERDATA: ++ uvalue(o)->env = hvalue(L->top - 1); ++ break; ++ case LUA_TTHREAD: ++ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); ++ break; ++ default: ++ res = 0; ++ break; ++ } ++ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); ++ L->top--; ++ lua_unlock(L); ++ return res; ++} ++ ++ ++/* ++** `load' and `call' functions (run Lua code) ++*/ ++ ++ ++#define adjustresults(L,nres) \ ++ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } ++ ++ ++#define checkresults(L,na,nr) \ ++ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) ++ ++ ++LUA_API void lua_call (lua_State *L, int nargs, int nresults) { ++ StkId func; ++ lua_lock(L); ++ api_checknelems(L, nargs+1); ++ checkresults(L, nargs, nresults); ++ func = L->top - (nargs+1); ++ luaD_call(L, func, nresults); ++ adjustresults(L, nresults); ++ lua_unlock(L); ++} ++ ++ ++ ++/* ++** Execute a protected call. ++*/ ++struct CallS { /* data to `f_call' */ ++ StkId func; ++ int nresults; ++}; ++ ++ ++static void f_call (lua_State *L, void *ud) { ++ struct CallS *c = cast(struct CallS *, ud); ++ luaD_call(L, c->func, c->nresults); ++} ++ ++ ++ ++LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { ++ struct CallS c; ++ int status; ++ ptrdiff_t func; ++ lua_lock(L); ++ api_checknelems(L, nargs+1); ++ checkresults(L, nargs, nresults); ++ if (errfunc == 0) ++ func = 0; ++ else { ++ StkId o = index2adr(L, errfunc); ++ api_checkvalidindex(L, o); ++ func = savestack(L, o); ++ } ++ c.func = L->top - (nargs+1); /* function to be called */ ++ c.nresults = nresults; ++ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); ++ adjustresults(L, nresults); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++/* ++** Execute a protected C call. ++*/ ++struct CCallS { /* data to `f_Ccall' */ ++ lua_CFunction func; ++ void *ud; ++}; ++ ++ ++static void f_Ccall (lua_State *L, void *ud) { ++ struct CCallS *c = cast(struct CCallS *, ud); ++ Closure *cl; ++ cl = luaF_newCclosure(L, 0, getcurrenv(L)); ++ cl->c.f = c->func; ++ setclvalue(L, L->top, cl); /* push function */ ++ api_incr_top(L); ++ setpvalue(L->top, c->ud); /* push only argument */ ++ api_incr_top(L); ++ luaD_call(L, L->top - 2, 0); ++} ++ ++ ++LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { ++ struct CCallS c; ++ int status; ++ lua_lock(L); ++ c.func = func; ++ c.ud = ud; ++ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, ++ const char *chunkname) { ++ ZIO z; ++ int status; ++ lua_lock(L); ++ if (!chunkname) chunkname = "?"; ++ luaZ_init(L, &z, reader, data); ++ status = luaD_protectedparser(L, &z, chunkname); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { ++ int status; ++ TValue *o; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = L->top - 1; ++ if (isLfunction(o)) ++ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); ++ else ++ status = 1; ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_status (lua_State *L) { ++ return L->status; ++} ++ ++ ++/* ++** Garbage-collection function ++*/ ++ ++LUA_API int lua_gc (lua_State *L, int what, int data) { ++ int res = 0; ++ global_State *g; ++ lua_lock(L); ++ g = G(L); ++ switch (what) { ++ case LUA_GCSTOP: { ++ g->GCthreshold = MAX_LUMEM; ++ break; ++ } ++ case LUA_GCRESTART: { ++ g->GCthreshold = g->totalbytes; ++ break; ++ } ++ case LUA_GCCOLLECT: { ++ luaC_fullgc(L); ++ break; ++ } ++ case LUA_GCCOUNT: { ++ /* GC values are expressed in Kbytes: #bytes/2^10 */ ++ res = cast_int(g->totalbytes >> 10); ++ break; ++ } ++ case LUA_GCCOUNTB: { ++ res = cast_int(g->totalbytes & 0x3ff); ++ break; ++ } ++ case LUA_GCSTEP: { ++ lu_mem a = (cast(lu_mem, data) << 10); ++ if (a <= g->totalbytes) ++ g->GCthreshold = g->totalbytes - a; ++ else ++ g->GCthreshold = 0; ++ while (g->GCthreshold <= g->totalbytes) { ++ luaC_step(L); ++ if (g->gcstate == GCSpause) { /* end of cycle? */ ++ res = 1; /* signal it */ ++ break; ++ } ++ } ++ break; ++ } ++ case LUA_GCSETPAUSE: { ++ res = g->gcpause; ++ g->gcpause = data; ++ break; ++ } ++ case LUA_GCSETSTEPMUL: { ++ res = g->gcstepmul; ++ g->gcstepmul = data; ++ break; ++ } ++ default: res = -1; /* invalid option */ ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++ ++/* ++** miscellaneous functions ++*/ ++ ++ ++LUA_API int lua_error (lua_State *L) { ++ lua_lock(L); ++ api_checknelems(L, 1); ++ luaG_errormsg(L); ++ lua_unlock(L); ++ return 0; /* to avoid warnings */ ++} ++ ++ ++LUA_API int lua_next (lua_State *L, int idx) { ++ StkId t; ++ int more; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ more = luaH_next(L, hvalue(t), L->top - 1); ++ if (more) { ++ api_incr_top(L); ++ } ++ else /* no more elements */ ++ L->top -= 1; /* remove key */ ++ lua_unlock(L); ++ return more; ++} ++ ++ ++LUA_API void lua_concat (lua_State *L, int n) { ++ lua_lock(L); ++ api_checknelems(L, n); ++ if (n >= 2) { ++ luaC_checkGC(L); ++ luaV_concat(L, n, cast_int(L->top - L->base) - 1); ++ L->top -= (n-1); ++ } ++ else if (n == 0) { /* push empty string */ ++ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); ++ api_incr_top(L); ++ } ++ /* else n == 1; nothing to do */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { ++ lua_Alloc f; ++ lua_lock(L); ++ if (ud) *ud = G(L)->ud; ++ f = G(L)->frealloc; ++ lua_unlock(L); ++ return f; ++} ++ ++ ++LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { ++ lua_lock(L); ++ G(L)->ud = ud; ++ G(L)->frealloc = f; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void *lua_newuserdata (lua_State *L, size_t size) { ++ Udata *u; ++ lua_lock(L); ++ luaC_checkGC(L); ++ u = luaS_newudata(L, size, getcurrenv(L)); ++ setuvalue(L, L->top, u); ++ api_incr_top(L); ++ lua_unlock(L); ++ return u + 1; ++} ++ ++ ++ ++ ++static const char *aux_upvalue (StkId fi, int n, TValue **val) { ++ Closure *f; ++ if (!ttisfunction(fi)) return NULL; ++ f = clvalue(fi); ++ if (f->c.isC) { ++ if (!(1 <= n && n <= f->c.nupvalues)) return NULL; ++ *val = &f->c.upvalue[n-1]; ++ return ""; ++ } ++ else { ++ Proto *p = f->l.p; ++ if (!(1 <= n && n <= p->sizeupvalues)) return NULL; ++ *val = f->l.upvals[n-1]->v; ++ return getstr(p->upvalues[n-1]); ++ } ++} ++ ++ ++LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { ++ const char *name; ++ TValue *val; ++ lua_lock(L); ++ name = aux_upvalue(index2adr(L, funcindex), n, &val); ++ if (name) { ++ setobj2s(L, L->top, val); ++ api_incr_top(L); ++ } ++ lua_unlock(L); ++ return name; ++} ++ ++ ++LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { ++ const char *name; ++ TValue *val; ++ StkId fi; ++ lua_lock(L); ++ fi = index2adr(L, funcindex); ++ api_checknelems(L, 1); ++ name = aux_upvalue(fi, n, &val); ++ if (name) { ++ L->top--; ++ setobj(L, val, L->top); ++ luaC_barrier(L, clvalue(fi), L->top); ++ } ++ lua_unlock(L); ++ return name; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lapi.h +@@ -0,0 +1,16 @@ ++/* ++** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions from Lua API ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lapi_h ++#define lapi_h ++ ++ ++#include "lobject.h" ++ ++ ++LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lauxlib.c +@@ -0,0 +1,674 @@ ++/* ++** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ ++** Auxiliary functions for building Lua libraries ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#if !defined(__KERNEL__) ++#include ++#include ++#include ++#include ++#include ++#else ++#include ++#include ++#include ++#include ++#include ++#endif ++ ++/* This file uses only the official API of Lua. ++** Any function declared here could be written as an application function. ++*/ ++ ++#define lauxlib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++ ++ ++#define FREELIST_REF 0 /* free list of references */ ++ ++ ++/* convert a stack index to positive */ ++#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ ++ lua_gettop(L) + (i) + 1) ++ ++ ++/* ++** {====================================================== ++** Error-report functions ++** ======================================================= ++*/ ++ ++ ++LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { ++ lua_Debug ar; ++ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ ++ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); ++ lua_getinfo(L, "n", &ar); ++ if (strcmp(ar.namewhat, "method") == 0) { ++ narg--; /* do not count `self' */ ++ if (narg == 0) /* error is in the self argument itself? */ ++ return luaL_error(L, "calling " LUA_QS " on bad self (%s)", ++ ar.name, extramsg); ++ } ++ if (ar.name == NULL) ++ ar.name = "?"; ++ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", ++ narg, ar.name, extramsg); ++} ++ ++ ++LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { ++ const char *msg = lua_pushfstring(L, "%s expected, got %s", ++ tname, luaL_typename(L, narg)); ++ return luaL_argerror(L, narg, msg); ++} ++ ++ ++static void tag_error (lua_State *L, int narg, int tag) { ++ luaL_typerror(L, narg, lua_typename(L, tag)); ++} ++ ++ ++LUALIB_API void luaL_where (lua_State *L, int level) { ++ lua_Debug ar; ++ if (lua_getstack(L, level, &ar)) { /* check function at level */ ++ lua_getinfo(L, "Sl", &ar); /* get info about it */ ++ if (ar.currentline > 0) { /* is there info? */ ++ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); ++ return; ++ } ++ } ++ lua_pushliteral(L, ""); /* else, no information available... */ ++} ++ ++ ++LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { ++ va_list argp; ++ va_start(argp, fmt); ++ luaL_where(L, 1); ++ lua_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ lua_concat(L, 2); ++ return lua_error(L); ++} ++ ++/* }====================================================== */ ++ ++ ++LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, ++ const char *const lst[]) { ++ const char *name = (def) ? luaL_optstring(L, narg, def) : ++ luaL_checkstring(L, narg); ++ int i; ++ for (i=0; lst[i]; i++) ++ if (strcmp(lst[i], name) == 0) ++ return i; ++ return luaL_argerror(L, narg, ++ lua_pushfstring(L, "invalid option " LUA_QS, name)); ++} ++ ++ ++LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { ++ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ ++ if (!lua_isnil(L, -1)) /* name already in use? */ ++ return 0; /* leave previous value on top, but return 0 */ ++ lua_pop(L, 1); ++ lua_newtable(L); /* create metatable */ ++ lua_pushvalue(L, -1); ++ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ ++ return 1; ++} ++ ++ ++LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { ++ void *p = lua_touserdata(L, ud); ++ if (p != NULL) { /* value is a userdata? */ ++ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ ++ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ ++ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ ++ lua_pop(L, 2); /* remove both metatables */ ++ return p; ++ } ++ } ++ } ++ luaL_typerror(L, ud, tname); /* else error */ ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { ++ if (!lua_checkstack(L, space)) ++ luaL_error(L, "stack overflow (%s)", mes); ++} ++ ++ ++LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { ++ if (lua_type(L, narg) != t) ++ tag_error(L, narg, t); ++} ++ ++ ++LUALIB_API void luaL_checkany (lua_State *L, int narg) { ++ if (lua_type(L, narg) == LUA_TNONE) ++ luaL_argerror(L, narg, "value expected"); ++} ++ ++ ++LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { ++ const char *s = lua_tolstring(L, narg, len); ++ if (!s) tag_error(L, narg, LUA_TSTRING); ++ return s; ++} ++ ++ ++LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, ++ const char *def, size_t *len) { ++ if (lua_isnoneornil(L, narg)) { ++ if (len) ++ *len = (def ? strlen(def) : 0); ++ return def; ++ } ++ else return luaL_checklstring(L, narg, len); ++} ++ ++ ++LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { ++ lua_Number d = lua_tonumber(L, narg); ++ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return d; ++} ++ ++ ++LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { ++ return luaL_opt(L, luaL_checknumber, narg, def); ++} ++ ++ ++LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { ++ lua_Integer d = lua_tointeger(L, narg); ++ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return d; ++} ++ ++ ++LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, ++ lua_Integer def) { ++ return luaL_opt(L, luaL_checkinteger, narg, def); ++} ++ ++ ++LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { ++ if (!lua_getmetatable(L, obj)) /* no metatable? */ ++ return 0; ++ lua_pushstring(L, event); ++ lua_rawget(L, -2); ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 2); /* remove metatable and metafield */ ++ return 0; ++ } ++ else { ++ lua_remove(L, -2); /* remove only metatable */ ++ return 1; ++ } ++} ++ ++ ++LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { ++ obj = abs_index(L, obj); ++ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ ++ return 0; ++ lua_pushvalue(L, obj); ++ lua_call(L, 1, 1); ++ return 1; ++} ++ ++ ++LUALIB_API void (luaL_register) (lua_State *L, const char *libname, ++ const luaL_Reg *l) { ++ luaI_openlib(L, libname, l, 0); ++} ++ ++ ++static int libsize (const luaL_Reg *l) { ++ int size = 0; ++ for (; l->name; l++) size++; ++ return size; ++} ++ ++ ++LUALIB_API void luaI_openlib (lua_State *L, const char *libname, ++ const luaL_Reg *l, int nup) { ++ if (libname) { ++ int size = libsize(l); ++ /* check whether lib already exists */ ++ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); ++ lua_getfield(L, -1, libname); /* get _LOADED[libname] */ ++ if (!lua_istable(L, -1)) { /* not found? */ ++ lua_pop(L, 1); /* remove previous result */ ++ /* try global variable (and create one if it does not exist) */ ++ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) ++ luaL_error(L, "name conflict for module " LUA_QS, libname); ++ lua_pushvalue(L, -1); ++ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ ++ } ++ lua_remove(L, -2); /* remove _LOADED table */ ++ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ ++ } ++ for (; l->name; l++) { ++ int i; ++ for (i=0; ifunc, nup); ++ lua_setfield(L, -(nup+2), l->name); ++ } ++ lua_pop(L, nup); /* remove upvalues */ ++} ++ ++ ++ ++/* ++** {====================================================== ++** getn-setn: size for arrays ++** ======================================================= ++*/ ++ ++#if defined(LUA_COMPAT_GETN) ++ ++static int checkint (lua_State *L, int topop) { ++ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; ++ lua_pop(L, topop); ++ return n; ++} ++ ++ ++static void getsizes (lua_State *L) { ++ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); ++ if (lua_isnil(L, -1)) { /* no `size' table? */ ++ lua_pop(L, 1); /* remove nil */ ++ lua_newtable(L); /* create it */ ++ lua_pushvalue(L, -1); /* `size' will be its own metatable */ ++ lua_setmetatable(L, -2); ++ lua_pushliteral(L, "kv"); ++ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ ++ lua_pushvalue(L, -1); ++ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ ++ } ++} ++ ++ ++LUALIB_API void luaL_setn (lua_State *L, int t, int n) { ++ t = abs_index(L, t); ++ lua_pushliteral(L, "n"); ++ lua_rawget(L, t); ++ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ ++ lua_pushliteral(L, "n"); /* use it */ ++ lua_pushinteger(L, n); ++ lua_rawset(L, t); ++ } ++ else { /* use `sizes' */ ++ getsizes(L); ++ lua_pushvalue(L, t); ++ lua_pushinteger(L, n); ++ lua_rawset(L, -3); /* sizes[t] = n */ ++ lua_pop(L, 1); /* remove `sizes' */ ++ } ++} ++ ++ ++LUALIB_API int luaL_getn (lua_State *L, int t) { ++ int n; ++ t = abs_index(L, t); ++ lua_pushliteral(L, "n"); /* try t.n */ ++ lua_rawget(L, t); ++ if ((n = checkint(L, 1)) >= 0) return n; ++ getsizes(L); /* else try sizes[t] */ ++ lua_pushvalue(L, t); ++ lua_rawget(L, -2); ++ if ((n = checkint(L, 2)) >= 0) return n; ++ return (int)lua_objlen(L, t); ++} ++ ++#endif ++ ++/* }====================================================== */ ++ ++ ++ ++LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, ++ const char *r) { ++ const char *wild; ++ size_t l = strlen(p); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "luaL_gsub: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while ((wild = strstr(s, p)) != NULL) { ++ luaL_addlstring(b, s, wild - s); /* push prefix */ ++ luaL_addstring(b, r); /* push replacement in place of pattern */ ++ s = wild + l; /* continue after `p' */ ++ } ++ luaL_addstring(b, s); /* push last suffix */ ++ luaL_pushresult(b); ++ kfree(b); ++ return lua_tostring(L, -1); ++} ++ ++ ++LUALIB_API const char *luaL_findtable (lua_State *L, int idx, ++ const char *fname, int szhint) { ++ const char *e; ++ lua_pushvalue(L, idx); ++ do { ++ e = strchr(fname, '.'); ++ if (e == NULL) e = fname + strlen(fname); ++ lua_pushlstring(L, fname, e - fname); ++ lua_rawget(L, -2); ++ if (lua_isnil(L, -1)) { /* no such field? */ ++ lua_pop(L, 1); /* remove this nil */ ++ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ ++ lua_pushlstring(L, fname, e - fname); ++ lua_pushvalue(L, -2); ++ lua_settable(L, -4); /* set new table into field */ ++ } ++ else if (!lua_istable(L, -1)) { /* field has a non-table value? */ ++ lua_pop(L, 2); /* remove table and value */ ++ return fname; /* return problematic part of the name */ ++ } ++ lua_remove(L, -2); /* remove previous table */ ++ fname = e + 1; ++ } while (*e == '.'); ++ return NULL; ++} ++ ++ ++ ++/* ++** {====================================================== ++** Generic Buffer manipulation ++** ======================================================= ++*/ ++ ++ ++#define bufflen(B) ((B)->p - (B)->buffer) ++#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) ++ ++#define LIMIT (LUA_MINSTACK/2) ++ ++ ++static int emptybuffer (luaL_Buffer *B) { ++ size_t l = bufflen(B); ++ if (l == 0) return 0; /* put nothing on stack */ ++ else { ++ lua_pushlstring(B->L, B->buffer, l); ++ B->p = B->buffer; ++ B->lvl++; ++ return 1; ++ } ++} ++ ++ ++static void adjuststack (luaL_Buffer *B) { ++ if (B->lvl > 1) { ++ lua_State *L = B->L; ++ int toget = 1; /* number of levels to concat */ ++ size_t toplen = lua_strlen(L, -1); ++ do { ++ size_t l = lua_strlen(L, -(toget+1)); ++ if (B->lvl - toget + 1 >= LIMIT || toplen > l) { ++ toplen += l; ++ toget++; ++ } ++ else break; ++ } while (toget < B->lvl); ++ lua_concat(L, toget); ++ B->lvl = B->lvl - toget + 1; ++ } ++} ++ ++ ++LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { ++ if (emptybuffer(B)) ++ adjuststack(B); ++ return B->buffer; ++} ++ ++ ++LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { ++ while (l--) ++ luaL_addchar(B, *s++); ++} ++ ++ ++LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { ++ luaL_addlstring(B, s, strlen(s)); ++} ++ ++ ++LUALIB_API void luaL_pushresult (luaL_Buffer *B) { ++ emptybuffer(B); ++ lua_concat(B->L, B->lvl); ++ B->lvl = 1; ++} ++ ++ ++LUALIB_API void luaL_addvalue (luaL_Buffer *B) { ++ lua_State *L = B->L; ++ size_t vl; ++ const char *s = lua_tolstring(L, -1, &vl); ++ if (vl <= bufffree(B)) { /* fit into buffer? */ ++ memcpy(B->p, s, vl); /* put it there */ ++ B->p += vl; ++ lua_pop(L, 1); /* remove from stack */ ++ } ++ else { ++ if (emptybuffer(B)) ++ lua_insert(L, -2); /* put buffer before new value */ ++ B->lvl++; /* add new value into B stack */ ++ adjuststack(B); ++ } ++} ++ ++ ++LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { ++ B->L = L; ++ B->p = B->buffer; ++ B->lvl = 0; ++} ++ ++/* }====================================================== */ ++ ++ ++LUALIB_API int luaL_ref (lua_State *L, int t) { ++ int ref; ++ t = abs_index(L, t); ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* remove from stack */ ++ return LUA_REFNIL; /* `nil' has a unique fixed reference */ ++ } ++ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ ++ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ ++ lua_pop(L, 1); /* remove it from stack */ ++ if (ref != 0) { /* any free element? */ ++ lua_rawgeti(L, t, ref); /* remove it from list */ ++ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ ++ } ++ else { /* no free elements */ ++ ref = (int)lua_objlen(L, t); ++ ref++; /* create new reference */ ++ } ++ lua_rawseti(L, t, ref); ++ return ref; ++} ++ ++ ++LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { ++ if (ref >= 0) { ++ t = abs_index(L, t); ++ lua_rawgeti(L, t, FREELIST_REF); ++ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ ++ lua_pushinteger(L, ref); ++ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ ++ } ++} ++ ++ ++ ++/* ++** {====================================================== ++** Load functions ++** ======================================================= ++*/ ++ ++#if !defined(__KERNEL__) ++typedef struct LoadF { ++ int extraline; ++ FILE *f; ++ char buff[LUAL_BUFFERSIZE]; ++} LoadF; ++ ++ ++static const char *getF (lua_State *L, void *ud, size_t *size) { ++ LoadF *lf = (LoadF *)ud; ++ (void)L; ++ if (lf->extraline) { ++ lf->extraline = 0; ++ *size = 1; ++ return "\n"; ++ } ++ if (feof(lf->f)) return NULL; ++ *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); ++ return (*size > 0) ? lf->buff : NULL; ++} ++ ++ ++static int errfile (lua_State *L, const char *what, int fnameindex) { ++ const char *serr = strerror(errno); ++ const char *filename = lua_tostring(L, fnameindex) + 1; ++ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); ++ lua_remove(L, fnameindex); ++ return LUA_ERRFILE; ++} ++ ++ ++LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { ++ LoadF lf; ++ int status, readstatus; ++ int c; ++ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ ++ lf.extraline = 0; ++ if (filename == NULL) { ++ lua_pushliteral(L, "=stdin"); ++ lf.f = stdin; ++ } ++ else { ++ lua_pushfstring(L, "@%s", filename); ++ lf.f = fopen(filename, "r"); ++ if (lf.f == NULL) return errfile(L, "open", fnameindex); ++ } ++ c = getc(lf.f); ++ if (c == '#') { /* Unix exec. file? */ ++ lf.extraline = 1; ++ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ ++ if (c == '\n') c = getc(lf.f); ++ } ++ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ ++ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ ++ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); ++ /* skip eventual `#!...' */ ++ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; ++ lf.extraline = 0; ++ } ++ ungetc(c, lf.f); ++ status = lua_load(L, getF, &lf, lua_tostring(L, -1)); ++ readstatus = ferror(lf.f); ++ if (filename) fclose(lf.f); /* close file (even in case of errors) */ ++ if (readstatus) { ++ lua_settop(L, fnameindex); /* ignore results from `lua_load' */ ++ return errfile(L, "read", fnameindex); ++ } ++ lua_remove(L, fnameindex); ++ return status; ++} ++#endif ++ ++typedef struct LoadS { ++ const char *s; ++ size_t size; ++} LoadS; ++ ++ ++static const char *getS (lua_State *L, void *ud, size_t *size) { ++ LoadS *ls = (LoadS *)ud; ++ (void)L; ++ if (ls->size == 0) return NULL; ++ *size = ls->size; ++ ls->size = 0; ++ return ls->s; ++} ++ ++ ++LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, ++ const char *name) { ++ LoadS ls; ++ ls.s = buff; ++ ls.size = size; ++ return lua_load(L, getS, &ls, name); ++} ++ ++ ++LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { ++ return luaL_loadbuffer(L, s, strlen(s), s); ++} ++ ++ ++ ++/* }====================================================== */ ++ ++ ++static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { ++ (void)ud; ++ (void)osize; ++ if (nsize == 0) { ++#if !defined(__KERNEL__) ++ free(ptr); ++#else ++ kfree(ptr); ++#endif ++ return NULL; ++ } ++ else ++#if !defined(__KERNEL__) ++ return realloc(ptr, nsize); ++#else ++ return krealloc(ptr, nsize, GFP_ATOMIC); ++#endif ++} ++ ++ ++static int lpanic (lua_State *L) { ++ (void)L; /* to avoid warnings */ ++#if !defined(__KERNEL__) ++ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", ++#else ++ printk( "PANIC: unprotected error in call to Lua API (%s)\n", ++#endif ++ lua_tostring(L, -1)); ++ return 0; ++} ++ ++ ++LUALIB_API lua_State *luaL_newstate (void) { ++ lua_State *L = lua_newstate(l_alloc, NULL); ++ if (L) lua_atpanic(L, &lpanic); ++ return L; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lauxlib.h +@@ -0,0 +1,184 @@ ++/* ++** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions for building Lua libraries ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lauxlib_h ++#define lauxlib_h ++ ++ ++#include ++#include /* for kmalloc and kfree when allocating luaL_Buffer */ ++ ++#if !defined(__KERNEL__) ++#include ++#endif ++ ++#include "lua.h" ++ ++ ++#if defined(LUA_COMPAT_GETN) ++LUALIB_API int (luaL_getn) (lua_State *L, int t); ++LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); ++#else ++#define luaL_getn(L,i) ((int)lua_objlen(L, i)) ++#define luaL_setn(L,i,j) ((void)0) /* no op! */ ++#endif ++ ++#if defined(LUA_COMPAT_OPENLIB) ++#define luaI_openlib luaL_openlib ++#endif ++ ++ ++/* extra error code for `luaL_load' */ ++#define LUA_ERRFILE (LUA_ERRERR+1) ++ ++ ++typedef struct luaL_Reg { ++ const char *name; ++ lua_CFunction func; ++} luaL_Reg; ++ ++ ++ ++LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, ++ const luaL_Reg *l, int nup); ++LUALIB_API void (luaL_register) (lua_State *L, const char *libname, ++ const luaL_Reg *l); ++LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); ++LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); ++LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); ++LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); ++LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, ++ size_t *l); ++LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, ++ const char *def, size_t *l); ++LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); ++LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); ++ ++LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); ++LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, ++ lua_Integer def); ++ ++LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); ++LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); ++LUALIB_API void (luaL_checkany) (lua_State *L, int narg); ++ ++LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); ++LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); ++ ++LUALIB_API void (luaL_where) (lua_State *L, int lvl); ++LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); ++ ++LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, ++ const char *const lst[]); ++ ++LUALIB_API int (luaL_ref) (lua_State *L, int t); ++LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); ++ ++#if !defined(__KERNEL__) ++LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); ++#endif ++ ++LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, ++ const char *name); ++LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); ++ ++LUALIB_API lua_State *(luaL_newstate) (void); ++ ++ ++LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, ++ const char *r); ++ ++LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, ++ const char *fname, int szhint); ++ ++ ++ ++ ++/* ++** =============================================================== ++** some useful macros ++** =============================================================== ++*/ ++ ++#define luaL_argcheck(L, cond,numarg,extramsg) \ ++ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) ++#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) ++#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) ++#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) ++#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) ++#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) ++#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) ++ ++#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) ++ ++#if !defined(__KERNEL__) ++#define luaL_dofile(L, fn) \ ++ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) ++#endif ++ ++#define luaL_dostring(L, s) \ ++ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) ++ ++#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) ++ ++#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) ++ ++/* ++** {====================================================== ++** Generic Buffer manipulation ++** ======================================================= ++*/ ++ ++ ++ ++typedef struct luaL_Buffer { ++ char *p; /* current position in buffer */ ++ int lvl; /* number of strings in the stack (level) */ ++ lua_State *L; ++ char buffer[LUAL_BUFFERSIZE]; ++} luaL_Buffer; ++ ++#define luaL_addchar(B,c) \ ++ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ ++ (*(B)->p++ = (char)(c))) ++ ++/* compatibility only */ ++#define luaL_putchar(B,c) luaL_addchar(B,c) ++ ++#define luaL_addsize(B,n) ((B)->p += (n)) ++ ++ ++LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); ++LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); ++LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); ++LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); ++LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); ++LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); ++ ++ ++/* }====================================================== */ ++ ++ ++/* compatibility with ref system */ ++ ++/* pre-defined references */ ++#define LUA_NOREF (-2) ++#define LUA_REFNIL (-1) ++ ++#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ ++ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) ++ ++#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) ++ ++#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) ++ ++ ++#define luaL_reg luaL_Reg ++ ++#endif ++ ++ +--- /dev/null ++++ b/extensions/LUA/lua/lbaselib.c +@@ -0,0 +1,647 @@ ++/* ++** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ ++** Basic library ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++#include ++#include ++ ++#define lbaselib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++ ++ ++/* ++** If your system does not support `stdout', you can just remove this function. ++** If you need, you can define your own `print' function, following this ++** model but changing `fputs' to put the strings at a proper place ++** (a console window or a log file, for instance). ++*/ ++static int luaB_print (lua_State *L) { ++ int n = lua_gettop(L); /* number of arguments */ ++ int i; ++ lua_getglobal(L, "tostring"); ++ for (i=1; i<=n; i++) { ++ const char *s; ++ lua_pushvalue(L, -1); /* function to be called */ ++ lua_pushvalue(L, i); /* value to print */ ++ lua_call(L, 1, 1); ++ s = lua_tostring(L, -1); /* get result */ ++ if (s == NULL) ++ return luaL_error(L, LUA_QL("tostring") " must return a string to " ++ LUA_QL("print")); ++ printk(KERN_INFO "LUA[print]: %s", s); ++ lua_pop(L, 1); /* pop result */ ++ } ++ return 0; ++} ++ ++ ++static int luaB_tonumber (lua_State *L) { ++ int base = luaL_optint(L, 2, 10); ++ if (base == 10) { /* standard conversion */ ++ luaL_checkany(L, 1); ++ if (lua_isnumber(L, 1)) { ++ lua_pushnumber(L, lua_tonumber(L, 1)); ++ return 1; ++ } ++ } ++ else { ++ const char *s1 = luaL_checkstring(L, 1); ++ char *s2; ++ unsigned long n; ++ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); ++ n = simple_strtoul(s1, &s2, base); ++ if (s1 != s2) { /* at least one valid digit? */ ++ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ ++ if (*s2 == '\0') { /* no invalid trailing characters? */ ++ lua_pushnumber(L, (lua_Number)n); ++ return 1; ++ } ++ } ++ } ++ lua_pushnil(L); /* else not a number */ ++ return 1; ++} ++ ++ ++static int luaB_error (lua_State *L) { ++ int level = luaL_optint(L, 2, 1); ++ lua_settop(L, 1); ++ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ ++ luaL_where(L, level); ++ lua_pushvalue(L, 1); ++ lua_concat(L, 2); ++ } ++ return lua_error(L); ++} ++ ++ ++static int luaB_getmetatable (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (!lua_getmetatable(L, 1)) { ++ lua_pushnil(L); ++ return 1; /* no metatable */ ++ } ++ luaL_getmetafield(L, 1, "__metatable"); ++ return 1; /* returns either __metatable field (if present) or metatable */ ++} ++ ++ ++static int luaB_setmetatable (lua_State *L) { ++ int t = lua_type(L, 2); ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, ++ "nil or table expected"); ++ if (luaL_getmetafield(L, 1, "__metatable")) ++ luaL_error(L, "cannot change a protected metatable"); ++ lua_settop(L, 2); ++ lua_setmetatable(L, 1); ++ return 1; ++} ++ ++ ++static void getfunc (lua_State *L, int opt) { ++ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); ++ else { ++ lua_Debug ar; ++ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); ++ luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); ++ if (lua_getstack(L, level, &ar) == 0) ++ luaL_argerror(L, 1, "invalid level"); ++ lua_getinfo(L, "f", &ar); ++ if (lua_isnil(L, -1)) ++ luaL_error(L, "no function environment for tail call at level %d", ++ level); ++ } ++} ++ ++ ++static int luaB_getfenv (lua_State *L) { ++ getfunc(L, 1); ++ if (lua_iscfunction(L, -1)) /* is a C function? */ ++ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ ++ else ++ lua_getfenv(L, -1); ++ return 1; ++} ++ ++ ++static int luaB_setfenv (lua_State *L) { ++ luaL_checktype(L, 2, LUA_TTABLE); ++ getfunc(L, 0); ++ lua_pushvalue(L, 2); ++ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { ++ /* change environment of current thread */ ++ lua_pushthread(L); ++ lua_insert(L, -2); ++ lua_setfenv(L, -2); ++ return 0; ++ } ++ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) ++ luaL_error(L, ++ LUA_QL("setfenv") " cannot change environment of given object"); ++ return 1; ++} ++ ++ ++static int luaB_rawequal (lua_State *L) { ++ luaL_checkany(L, 1); ++ luaL_checkany(L, 2); ++ lua_pushboolean(L, lua_rawequal(L, 1, 2)); ++ return 1; ++} ++ ++ ++static int luaB_rawget (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checkany(L, 2); ++ lua_settop(L, 2); ++ lua_rawget(L, 1); ++ return 1; ++} ++ ++static int luaB_rawset (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checkany(L, 2); ++ luaL_checkany(L, 3); ++ lua_settop(L, 3); ++ lua_rawset(L, 1); ++ return 1; ++} ++ ++ ++static int luaB_gcinfo (lua_State *L) { ++ lua_pushinteger(L, lua_getgccount(L)); ++ return 1; ++} ++ ++static int luaB_collectgarbage (lua_State *L) { ++ static const char *const opts[] = {"stop", "restart", "collect", ++ "count", "step", "setpause", "setstepmul", NULL}; ++ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, ++ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; ++ int o = luaL_checkoption(L, 1, "collect", opts); ++ int ex = luaL_optint(L, 2, 0); ++ int res = lua_gc(L, optsnum[o], ex); ++ switch (optsnum[o]) { ++ case LUA_GCCOUNT: { ++ int b = lua_gc(L, LUA_GCCOUNTB, 0); ++ lua_pushnumber(L, res + ((lua_Number)b/1024)); ++ return 1; ++ } ++ case LUA_GCSTEP: { ++ lua_pushboolean(L, res); ++ return 1; ++ } ++ default: { ++ lua_pushnumber(L, res); ++ return 1; ++ } ++ } ++} ++ ++ ++static int luaB_type (lua_State *L) { ++ luaL_checkany(L, 1); ++ lua_pushstring(L, luaL_typename(L, 1)); ++ return 1; ++} ++ ++ ++static int luaB_next (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_settop(L, 2); /* create a 2nd argument if there isn't one */ ++ if (lua_next(L, 1)) ++ return 2; ++ else { ++ lua_pushnil(L); ++ return 1; ++ } ++} ++ ++ ++static int luaB_pairs (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ ++ lua_pushvalue(L, 1); /* state, */ ++ lua_pushnil(L); /* and initial value */ ++ return 3; ++} ++ ++ ++static int ipairsaux (lua_State *L) { ++ int i = luaL_checkint(L, 2); ++ luaL_checktype(L, 1, LUA_TTABLE); ++ i++; /* next value */ ++ lua_pushinteger(L, i); ++ lua_rawgeti(L, 1, i); ++ return (lua_isnil(L, -1)) ? 0 : 2; ++} ++ ++ ++static int luaB_ipairs (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ ++ lua_pushvalue(L, 1); /* state, */ ++ lua_pushinteger(L, 0); /* and initial value */ ++ return 3; ++} ++ ++ ++static int load_aux (lua_State *L, int status) { ++ if (status == 0) /* OK? */ ++ return 1; ++ else { ++ lua_pushnil(L); ++ lua_insert(L, -2); /* put before error message */ ++ return 2; /* return nil plus error message */ ++ } ++} ++ ++ ++static int luaB_loadstring (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ const char *chunkname = luaL_optstring(L, 2, s); ++ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); ++} ++ ++/* ++static int luaB_loadfile (lua_State *L) { ++ const char *fname = luaL_optstring(L, 1, NULL); ++ return load_aux(L, luaL_loadfile(L, fname)); ++} ++*/ ++ ++/* ++** Reader for generic `load' function: `lua_load' uses the ++** stack for internal stuff, so the reader cannot change the ++** stack top. Instead, it keeps its resulting string in a ++** reserved slot inside the stack. ++*/ ++static const char *generic_reader (lua_State *L, void *ud, size_t *size) { ++ (void)ud; /* to avoid warnings */ ++ luaL_checkstack(L, 2, "too many nested functions"); ++ lua_pushvalue(L, 1); /* get function */ ++ lua_call(L, 0, 1); /* call it */ ++ if (lua_isnil(L, -1)) { ++ *size = 0; ++ return NULL; ++ } ++ else if (lua_isstring(L, -1)) { ++ lua_replace(L, 3); /* save string in a reserved stack slot */ ++ return lua_tolstring(L, 3, size); ++ } ++ else luaL_error(L, "reader function must return a string"); ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++static int luaB_load (lua_State *L) { ++ int status; ++ const char *cname = luaL_optstring(L, 2, "=(load)"); ++ luaL_checktype(L, 1, LUA_TFUNCTION); ++ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ ++ status = lua_load(L, generic_reader, NULL, cname); ++ return load_aux(L, status); ++} ++ ++/* ++static int luaB_dofile (lua_State *L) { ++ const char *fname = luaL_optstring(L, 1, NULL); ++ int n = lua_gettop(L); ++ if (luaL_loadfile(L, fname) != 0) lua_error(L); ++ lua_call(L, 0, LUA_MULTRET); ++ return lua_gettop(L) - n; ++} ++*/ ++ ++static int luaB_assert (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (!lua_toboolean(L, 1)) ++ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); ++ return lua_gettop(L); ++} ++ ++ ++static int luaB_unpack (lua_State *L) { ++ int i, e, n; ++ luaL_checktype(L, 1, LUA_TTABLE); ++ i = luaL_optint(L, 2, 1); ++ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); ++ if (i > e) return 0; /* empty range */ ++ n = e - i + 1; /* number of elements */ ++ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ ++ return luaL_error(L, "too many results to unpack"); ++ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ ++ while (i++ < e) /* push arg[i + 1...e] */ ++ lua_rawgeti(L, 1, i); ++ return n; ++} ++ ++ ++static int luaB_select (lua_State *L) { ++ int n = lua_gettop(L); ++ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { ++ lua_pushinteger(L, n-1); ++ return 1; ++ } ++ else { ++ int i = luaL_checkint(L, 1); ++ if (i < 0) i = n + i; ++ else if (i > n) i = n; ++ luaL_argcheck(L, 1 <= i, 1, "index out of range"); ++ return n - i; ++ } ++} ++ ++ ++static int luaB_pcall (lua_State *L) { ++ int status; ++ luaL_checkany(L, 1); ++ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); ++ lua_pushboolean(L, (status == 0)); ++ lua_insert(L, 1); ++ return lua_gettop(L); /* return status + all results */ ++} ++ ++ ++static int luaB_xpcall (lua_State *L) { ++ int status; ++ luaL_checkany(L, 2); ++ lua_settop(L, 2); ++ lua_insert(L, 1); /* put error function under function to be called */ ++ status = lua_pcall(L, 0, LUA_MULTRET, 1); ++ lua_pushboolean(L, (status == 0)); ++ lua_replace(L, 1); ++ return lua_gettop(L); /* return status + all results */ ++} ++ ++ ++static int luaB_tostring (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ ++ return 1; /* use its value */ ++ switch (lua_type(L, 1)) { ++ case LUA_TNUMBER: ++ lua_pushstring(L, lua_tostring(L, 1)); ++ break; ++ case LUA_TSTRING: ++ lua_pushvalue(L, 1); ++ break; ++ case LUA_TBOOLEAN: ++ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); ++ break; ++ case LUA_TNIL: ++ lua_pushliteral(L, "nil"); ++ break; ++ default: ++ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); ++ break; ++ } ++ return 1; ++} ++ ++ ++static int luaB_newproxy (lua_State *L) { ++ lua_settop(L, 1); ++ lua_newuserdata(L, 0); /* create proxy */ ++ if (lua_toboolean(L, 1) == 0) ++ return 1; /* no metatable */ ++ else if (lua_isboolean(L, 1)) { ++ lua_newtable(L); /* create a new metatable `m' ... */ ++ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ ++ lua_pushboolean(L, 1); ++ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ ++ } ++ else { ++ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ ++ if (lua_getmetatable(L, 1)) { ++ lua_rawget(L, lua_upvalueindex(1)); ++ validproxy = lua_toboolean(L, -1); ++ lua_pop(L, 1); /* remove value */ ++ } ++ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); ++ lua_getmetatable(L, 1); /* metatable is valid; get it */ ++ } ++ lua_setmetatable(L, 2); ++ return 1; ++} ++ ++ ++static const luaL_Reg base_funcs[] = { ++ {"assert", luaB_assert}, ++ {"collectgarbage", luaB_collectgarbage}, ++// {"dofile", luaB_dofile}, ++ {"error", luaB_error}, ++ {"gcinfo", luaB_gcinfo}, ++ {"getfenv", luaB_getfenv}, ++ {"getmetatable", luaB_getmetatable}, ++// {"loadfile", luaB_loadfile}, ++ {"load", luaB_load}, ++ {"loadstring", luaB_loadstring}, ++ {"next", luaB_next}, ++ {"pcall", luaB_pcall}, ++ {"print", luaB_print}, ++ {"rawequal", luaB_rawequal}, ++ {"rawget", luaB_rawget}, ++ {"rawset", luaB_rawset}, ++ {"select", luaB_select}, ++ {"setfenv", luaB_setfenv}, ++ {"setmetatable", luaB_setmetatable}, ++ {"tonumber", luaB_tonumber}, ++ {"tostring", luaB_tostring}, ++ {"type", luaB_type}, ++ {"unpack", luaB_unpack}, ++ {"xpcall", luaB_xpcall}, ++ {NULL, NULL} ++}; ++ ++ ++/* ++** {====================================================== ++** Coroutine library ++** ======================================================= ++*/ ++ ++#define CO_RUN 0 /* running */ ++#define CO_SUS 1 /* suspended */ ++#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ ++#define CO_DEAD 3 ++ ++static const char *const statnames[] = ++ {"running", "suspended", "normal", "dead"}; ++ ++static int costatus (lua_State *L, lua_State *co) { ++ if (L == co) return CO_RUN; ++ switch (lua_status(co)) { ++ case LUA_YIELD: ++ return CO_SUS; ++ case 0: { ++ lua_Debug ar; ++ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ ++ return CO_NOR; /* it is running */ ++ else if (lua_gettop(co) == 0) ++ return CO_DEAD; ++ else ++ return CO_SUS; /* initial state */ ++ } ++ default: /* some error occured */ ++ return CO_DEAD; ++ } ++} ++ ++ ++static int luaB_costatus (lua_State *L) { ++ lua_State *co = lua_tothread(L, 1); ++ luaL_argcheck(L, co, 1, "coroutine expected"); ++ lua_pushstring(L, statnames[costatus(L, co)]); ++ return 1; ++} ++ ++ ++static int auxresume (lua_State *L, lua_State *co, int narg) { ++ int status = costatus(L, co); ++ if (!lua_checkstack(co, narg)) ++ luaL_error(L, "too many arguments to resume"); ++ if (status != CO_SUS) { ++ lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); ++ return -1; /* error flag */ ++ } ++ lua_xmove(L, co, narg); ++ lua_setlevel(L, co); ++ status = lua_resume(co, narg); ++ if (status == 0 || status == LUA_YIELD) { ++ int nres = lua_gettop(co); ++ if (!lua_checkstack(L, nres + 1)) ++ luaL_error(L, "too many results to resume"); ++ lua_xmove(co, L, nres); /* move yielded values */ ++ return nres; ++ } ++ else { ++ lua_xmove(co, L, 1); /* move error message */ ++ return -1; /* error flag */ ++ } ++} ++ ++ ++static int luaB_coresume (lua_State *L) { ++ lua_State *co = lua_tothread(L, 1); ++ int r; ++ luaL_argcheck(L, co, 1, "coroutine expected"); ++ r = auxresume(L, co, lua_gettop(L) - 1); ++ if (r < 0) { ++ lua_pushboolean(L, 0); ++ lua_insert(L, -2); ++ return 2; /* return false + error message */ ++ } ++ else { ++ lua_pushboolean(L, 1); ++ lua_insert(L, -(r + 1)); ++ return r + 1; /* return true + `resume' returns */ ++ } ++} ++ ++ ++static int luaB_auxwrap (lua_State *L) { ++ lua_State *co = lua_tothread(L, lua_upvalueindex(1)); ++ int r = auxresume(L, co, lua_gettop(L)); ++ if (r < 0) { ++ if (lua_isstring(L, -1)) { /* error object is a string? */ ++ luaL_where(L, 1); /* add extra info */ ++ lua_insert(L, -2); ++ lua_concat(L, 2); ++ } ++ lua_error(L); /* propagate error */ ++ } ++ return r; ++} ++ ++ ++static int luaB_cocreate (lua_State *L) { ++ lua_State *NL = lua_newthread(L); ++ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, ++ "Lua function expected"); ++ lua_pushvalue(L, 1); /* move function to top */ ++ lua_xmove(L, NL, 1); /* move function from L to NL */ ++ return 1; ++} ++ ++ ++static int luaB_cowrap (lua_State *L) { ++ luaB_cocreate(L); ++ lua_pushcclosure(L, luaB_auxwrap, 1); ++ return 1; ++} ++ ++ ++static int luaB_yield (lua_State *L) { ++ return lua_yield(L, lua_gettop(L)); ++} ++ ++ ++static int luaB_corunning (lua_State *L) { ++ if (lua_pushthread(L)) ++ lua_pushnil(L); /* main thread is not a coroutine */ ++ return 1; ++} ++ ++ ++static const luaL_Reg co_funcs[] = { ++ {"create", luaB_cocreate}, ++ {"resume", luaB_coresume}, ++ {"running", luaB_corunning}, ++ {"status", luaB_costatus}, ++ {"wrap", luaB_cowrap}, ++ {"yield", luaB_yield}, ++ {NULL, NULL} ++}; ++ ++/* }====================================================== */ ++ ++ ++static void auxopen (lua_State *L, const char *name, ++ lua_CFunction f, lua_CFunction u) { ++ lua_pushcfunction(L, u); ++ lua_pushcclosure(L, f, 1); ++ lua_setfield(L, -2, name); ++} ++ ++ ++static void base_open (lua_State *L) { ++ /* set global _G */ ++ lua_pushvalue(L, LUA_GLOBALSINDEX); ++ lua_setglobal(L, "_G"); ++ /* open lib into global table */ ++ luaL_register(L, "_G", base_funcs); ++ lua_pushliteral(L, LUA_VERSION); ++ lua_setglobal(L, "_VERSION"); /* set global _VERSION */ ++ /* `ipairs' and `pairs' need auxliliary functions as upvalues */ ++ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); ++ auxopen(L, "pairs", luaB_pairs, luaB_next); ++ /* `newproxy' needs a weaktable as upvalue */ ++ lua_createtable(L, 0, 1); /* new table `w' */ ++ lua_pushvalue(L, -1); /* `w' will be its own metatable */ ++ lua_setmetatable(L, -2); ++ lua_pushliteral(L, "kv"); ++ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ ++ lua_pushcclosure(L, luaB_newproxy, 1); ++ lua_setglobal(L, "newproxy"); /* set global `newproxy' */ ++} ++ ++ ++LUALIB_API int luaopen_base (lua_State *L) { ++ base_open(L); ++ luaL_register(L, LUA_COLIBNAME, co_funcs); ++ return 2; ++} +--- /dev/null ++++ b/extensions/LUA/lua/lcode.c +@@ -0,0 +1,838 @@ ++/* ++** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Code generator for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lcode_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lgc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "ltable.h" ++ ++ ++#define hasjumps(e) ((e)->t != (e)->f) ++ ++ ++static int isnumeral(expdesc *e) { ++ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); ++} ++ ++ ++void luaK_nil (FuncState *fs, int from, int n) { ++ Instruction *previous; ++ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ ++ if (fs->pc == 0) { /* function start? */ ++ if (from >= fs->nactvar) ++ return; /* positions are already clean */ ++ } ++ else { ++ previous = &fs->f->code[fs->pc-1]; ++ if (GET_OPCODE(*previous) == OP_LOADNIL) { ++ int pfrom = GETARG_A(*previous); ++ int pto = GETARG_B(*previous); ++ if (pfrom <= from && from <= pto+1) { /* can connect both? */ ++ if (from+n-1 > pto) ++ SETARG_B(*previous, from+n-1); ++ return; ++ } ++ } ++ } ++ } ++ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ ++} ++ ++ ++int luaK_jump (FuncState *fs) { ++ int jpc = fs->jpc; /* save list of jumps to here */ ++ int j; ++ fs->jpc = NO_JUMP; ++ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); ++ luaK_concat(fs, &j, jpc); /* keep them on hold */ ++ return j; ++} ++ ++ ++void luaK_ret (FuncState *fs, int first, int nret) { ++ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); ++} ++ ++ ++static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { ++ luaK_codeABC(fs, op, A, B, C); ++ return luaK_jump(fs); ++} ++ ++ ++static void fixjump (FuncState *fs, int pc, int dest) { ++ Instruction *jmp = &fs->f->code[pc]; ++ int offset = dest-(pc+1); ++ lua_assert(dest != NO_JUMP); ++ if (abs(offset) > MAXARG_sBx) ++ luaX_syntaxerror(fs->ls, "control structure too long"); ++ SETARG_sBx(*jmp, offset); ++} ++ ++ ++/* ++** returns current `pc' and marks it as a jump target (to avoid wrong ++** optimizations with consecutive instructions not in the same basic block). ++*/ ++int luaK_getlabel (FuncState *fs) { ++ fs->lasttarget = fs->pc; ++ return fs->pc; ++} ++ ++ ++static int getjump (FuncState *fs, int pc) { ++ int offset = GETARG_sBx(fs->f->code[pc]); ++ if (offset == NO_JUMP) /* point to itself represents end of list */ ++ return NO_JUMP; /* end of list */ ++ else ++ return (pc+1)+offset; /* turn offset into absolute position */ ++} ++ ++ ++static Instruction *getjumpcontrol (FuncState *fs, int pc) { ++ Instruction *pi = &fs->f->code[pc]; ++ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) ++ return pi-1; ++ else ++ return pi; ++} ++ ++ ++/* ++** check whether list has any jump that do not produce a value ++** (or produce an inverted value) ++*/ ++static int need_value (FuncState *fs, int list) { ++ for (; list != NO_JUMP; list = getjump(fs, list)) { ++ Instruction i = *getjumpcontrol(fs, list); ++ if (GET_OPCODE(i) != OP_TESTSET) return 1; ++ } ++ return 0; /* not found */ ++} ++ ++ ++static int patchtestreg (FuncState *fs, int node, int reg) { ++ Instruction *i = getjumpcontrol(fs, node); ++ if (GET_OPCODE(*i) != OP_TESTSET) ++ return 0; /* cannot patch other instructions */ ++ if (reg != NO_REG && reg != GETARG_B(*i)) ++ SETARG_A(*i, reg); ++ else /* no register to put value or register already has the value */ ++ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); ++ ++ return 1; ++} ++ ++ ++static void removevalues (FuncState *fs, int list) { ++ for (; list != NO_JUMP; list = getjump(fs, list)) ++ patchtestreg(fs, list, NO_REG); ++} ++ ++ ++static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, ++ int dtarget) { ++ while (list != NO_JUMP) { ++ int next = getjump(fs, list); ++ if (patchtestreg(fs, list, reg)) ++ fixjump(fs, list, vtarget); ++ else ++ fixjump(fs, list, dtarget); /* jump to default target */ ++ list = next; ++ } ++} ++ ++ ++static void dischargejpc (FuncState *fs) { ++ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); ++ fs->jpc = NO_JUMP; ++} ++ ++ ++void luaK_patchlist (FuncState *fs, int list, int target) { ++ if (target == fs->pc) ++ luaK_patchtohere(fs, list); ++ else { ++ lua_assert(target < fs->pc); ++ patchlistaux(fs, list, target, NO_REG, target); ++ } ++} ++ ++ ++void luaK_patchtohere (FuncState *fs, int list) { ++ luaK_getlabel(fs); ++ luaK_concat(fs, &fs->jpc, list); ++} ++ ++ ++void luaK_concat (FuncState *fs, int *l1, int l2) { ++ if (l2 == NO_JUMP) return; ++ else if (*l1 == NO_JUMP) ++ *l1 = l2; ++ else { ++ int list = *l1; ++ int next; ++ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ ++ list = next; ++ fixjump(fs, list, l2); ++ } ++} ++ ++ ++void luaK_checkstack (FuncState *fs, int n) { ++ int newstack = fs->freereg + n; ++ if (newstack > fs->f->maxstacksize) { ++ if (newstack >= MAXSTACK) ++ luaX_syntaxerror(fs->ls, "function or expression too complex"); ++ fs->f->maxstacksize = cast_byte(newstack); ++ } ++} ++ ++ ++void luaK_reserveregs (FuncState *fs, int n) { ++ luaK_checkstack(fs, n); ++ fs->freereg += n; ++} ++ ++ ++static void freereg (FuncState *fs, int reg) { ++ if (!ISK(reg) && reg >= fs->nactvar) { ++ fs->freereg--; ++ lua_assert(reg == fs->freereg); ++ } ++} ++ ++ ++static void freeexp (FuncState *fs, expdesc *e) { ++ if (e->k == VNONRELOC) ++ freereg(fs, e->u.s.info); ++} ++ ++ ++static int addk (FuncState *fs, TValue *k, TValue *v) { ++ lua_State *L = fs->L; ++ TValue *idx = luaH_set(L, fs->h, k); ++ Proto *f = fs->f; ++ int oldsize = f->sizek; ++ if (ttisnumber(idx)) { ++ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); ++ return cast_int(nvalue(idx)); ++ } ++ else { /* constant not found; create a new entry */ ++ setnvalue(idx, cast_num(fs->nk)); ++ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, ++ MAXARG_Bx, "constant table overflow"); ++ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); ++ setobj(L, &f->k[fs->nk], v); ++ luaC_barrier(L, f, v); ++ return fs->nk++; ++ } ++} ++ ++ ++int luaK_stringK (FuncState *fs, TString *s) { ++ TValue o; ++ setsvalue(fs->L, &o, s); ++ return addk(fs, &o, &o); ++} ++ ++ ++int luaK_numberK (FuncState *fs, lua_Number r) { ++ TValue o; ++ setnvalue(&o, r); ++ return addk(fs, &o, &o); ++} ++ ++ ++static int boolK (FuncState *fs, int b) { ++ TValue o; ++ setbvalue(&o, b); ++ return addk(fs, &o, &o); ++} ++ ++ ++static int nilK (FuncState *fs) { ++ TValue k, v; ++ setnilvalue(&v); ++ /* cannot use nil as key; instead use table itself to represent nil */ ++ sethvalue(fs->L, &k, fs->h); ++ return addk(fs, &k, &v); ++} ++ ++ ++void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { ++ if (e->k == VCALL) { /* expression is an open function call? */ ++ SETARG_C(getcode(fs, e), nresults+1); ++ } ++ else if (e->k == VVARARG) { ++ SETARG_B(getcode(fs, e), nresults+1); ++ SETARG_A(getcode(fs, e), fs->freereg); ++ luaK_reserveregs(fs, 1); ++ } ++} ++ ++ ++void luaK_setoneret (FuncState *fs, expdesc *e) { ++ if (e->k == VCALL) { /* expression is an open function call? */ ++ e->k = VNONRELOC; ++ e->u.s.info = GETARG_A(getcode(fs, e)); ++ } ++ else if (e->k == VVARARG) { ++ SETARG_B(getcode(fs, e), 2); ++ e->k = VRELOCABLE; /* can relocate its simple result */ ++ } ++} ++ ++ ++void luaK_dischargevars (FuncState *fs, expdesc *e) { ++ switch (e->k) { ++ case VLOCAL: { ++ e->k = VNONRELOC; ++ break; ++ } ++ case VUPVAL: { ++ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VGLOBAL: { ++ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VINDEXED: { ++ freereg(fs, e->u.s.aux); ++ freereg(fs, e->u.s.info); ++ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VVARARG: ++ case VCALL: { ++ luaK_setoneret(fs, e); ++ break; ++ } ++ default: break; /* there is one value available (somewhere) */ ++ } ++} ++ ++ ++static int code_label (FuncState *fs, int A, int b, int jump) { ++ luaK_getlabel(fs); /* those instructions may be jump targets */ ++ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); ++} ++ ++ ++static void discharge2reg (FuncState *fs, expdesc *e, int reg) { ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: { ++ luaK_nil(fs, reg, 1); ++ break; ++ } ++ case VFALSE: case VTRUE: { ++ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); ++ break; ++ } ++ case VK: { ++ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); ++ break; ++ } ++ case VKNUM: { ++ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); ++ break; ++ } ++ case VRELOCABLE: { ++ Instruction *pc = &getcode(fs, e); ++ SETARG_A(*pc, reg); ++ break; ++ } ++ case VNONRELOC: { ++ if (reg != e->u.s.info) ++ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); ++ break; ++ } ++ default: { ++ lua_assert(e->k == VVOID || e->k == VJMP); ++ return; /* nothing to do... */ ++ } ++ } ++ e->u.s.info = reg; ++ e->k = VNONRELOC; ++} ++ ++ ++static void discharge2anyreg (FuncState *fs, expdesc *e) { ++ if (e->k != VNONRELOC) { ++ luaK_reserveregs(fs, 1); ++ discharge2reg(fs, e, fs->freereg-1); ++ } ++} ++ ++ ++static void exp2reg (FuncState *fs, expdesc *e, int reg) { ++ discharge2reg(fs, e, reg); ++ if (e->k == VJMP) ++ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ ++ if (hasjumps(e)) { ++ int final; /* position after whole expression */ ++ int p_f = NO_JUMP; /* position of an eventual LOAD false */ ++ int p_t = NO_JUMP; /* position of an eventual LOAD true */ ++ if (need_value(fs, e->t) || need_value(fs, e->f)) { ++ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); ++ p_f = code_label(fs, reg, 0, 1); ++ p_t = code_label(fs, reg, 1, 0); ++ luaK_patchtohere(fs, fj); ++ } ++ final = luaK_getlabel(fs); ++ patchlistaux(fs, e->f, final, reg, p_f); ++ patchlistaux(fs, e->t, final, reg, p_t); ++ } ++ e->f = e->t = NO_JUMP; ++ e->u.s.info = reg; ++ e->k = VNONRELOC; ++} ++ ++ ++void luaK_exp2nextreg (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ freeexp(fs, e); ++ luaK_reserveregs(fs, 1); ++ exp2reg(fs, e, fs->freereg - 1); ++} ++ ++ ++int luaK_exp2anyreg (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ if (e->k == VNONRELOC) { ++ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ ++ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ ++ exp2reg(fs, e, e->u.s.info); /* put value on it */ ++ return e->u.s.info; ++ } ++ } ++ luaK_exp2nextreg(fs, e); /* default */ ++ return e->u.s.info; ++} ++ ++ ++void luaK_exp2val (FuncState *fs, expdesc *e) { ++ if (hasjumps(e)) ++ luaK_exp2anyreg(fs, e); ++ else ++ luaK_dischargevars(fs, e); ++} ++ ++ ++int luaK_exp2RK (FuncState *fs, expdesc *e) { ++ luaK_exp2val(fs, e); ++ switch (e->k) { ++ case VKNUM: ++ case VTRUE: ++ case VFALSE: ++ case VNIL: { ++ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ ++ e->u.s.info = (e->k == VNIL) ? nilK(fs) : ++ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : ++ boolK(fs, (e->k == VTRUE)); ++ e->k = VK; ++ return RKASK(e->u.s.info); ++ } ++ else break; ++ } ++ case VK: { ++ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ ++ return RKASK(e->u.s.info); ++ else break; ++ } ++ default: break; ++ } ++ /* not a constant in the right range: put it in a register */ ++ return luaK_exp2anyreg(fs, e); ++} ++ ++ ++void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { ++ switch (var->k) { ++ case VLOCAL: { ++ freeexp(fs, ex); ++ exp2reg(fs, ex, var->u.s.info); ++ return; ++ } ++ case VUPVAL: { ++ int e = luaK_exp2anyreg(fs, ex); ++ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); ++ break; ++ } ++ case VGLOBAL: { ++ int e = luaK_exp2anyreg(fs, ex); ++ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); ++ break; ++ } ++ case VINDEXED: { ++ int e = luaK_exp2RK(fs, ex); ++ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); ++ break; ++ } ++ default: { ++ lua_assert(0); /* invalid var kind to store */ ++ break; ++ } ++ } ++ freeexp(fs, ex); ++} ++ ++ ++void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { ++ int func; ++ luaK_exp2anyreg(fs, e); ++ freeexp(fs, e); ++ func = fs->freereg; ++ luaK_reserveregs(fs, 2); ++ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); ++ freeexp(fs, key); ++ e->u.s.info = func; ++ e->k = VNONRELOC; ++} ++ ++ ++static void invertjump (FuncState *fs, expdesc *e) { ++ Instruction *pc = getjumpcontrol(fs, e->u.s.info); ++ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && ++ GET_OPCODE(*pc) != OP_TEST); ++ SETARG_A(*pc, !(GETARG_A(*pc))); ++} ++ ++ ++static int jumponcond (FuncState *fs, expdesc *e, int cond) { ++ if (e->k == VRELOCABLE) { ++ Instruction ie = getcode(fs, e); ++ if (GET_OPCODE(ie) == OP_NOT) { ++ fs->pc--; /* remove previous OP_NOT */ ++ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); ++ } ++ /* else go through */ ++ } ++ discharge2anyreg(fs, e); ++ freeexp(fs, e); ++ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); ++} ++ ++ ++void luaK_goiftrue (FuncState *fs, expdesc *e) { ++ int pc; /* pc of last jump */ ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VK: case VKNUM: case VTRUE: { ++ pc = NO_JUMP; /* always true; do nothing */ ++ break; ++ } ++ case VFALSE: { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ case VJMP: { ++ invertjump(fs, e); ++ pc = e->u.s.info; ++ break; ++ } ++ default: { ++ pc = jumponcond(fs, e, 0); ++ break; ++ } ++ } ++ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ ++ luaK_patchtohere(fs, e->t); ++ e->t = NO_JUMP; ++} ++ ++ ++static void luaK_goiffalse (FuncState *fs, expdesc *e) { ++ int pc; /* pc of last jump */ ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: case VFALSE: { ++ pc = NO_JUMP; /* always false; do nothing */ ++ break; ++ } ++ case VTRUE: { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ case VJMP: { ++ pc = e->u.s.info; ++ break; ++ } ++ default: { ++ pc = jumponcond(fs, e, 1); ++ break; ++ } ++ } ++ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ ++ luaK_patchtohere(fs, e->f); ++ e->f = NO_JUMP; ++} ++ ++ ++static void codenot (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: case VFALSE: { ++ e->k = VTRUE; ++ break; ++ } ++ case VK: case VKNUM: case VTRUE: { ++ e->k = VFALSE; ++ break; ++ } ++ case VJMP: { ++ invertjump(fs, e); ++ break; ++ } ++ case VRELOCABLE: ++ case VNONRELOC: { ++ discharge2anyreg(fs, e); ++ freeexp(fs, e); ++ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); ++ e->k = VRELOCABLE; ++ break; ++ } ++ default: { ++ lua_assert(0); /* cannot happen */ ++ break; ++ } ++ } ++ /* interchange true and false lists */ ++ { int temp = e->f; e->f = e->t; e->t = temp; } ++ removevalues(fs, e->f); ++ removevalues(fs, e->t); ++} ++ ++ ++void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { ++ t->u.s.aux = luaK_exp2RK(fs, k); ++ t->k = VINDEXED; ++} ++ ++ ++static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { ++ lua_Number v1, v2, r; ++ if (!isnumeral(e1) || !isnumeral(e2)) return 0; ++ v1 = e1->u.nval; ++ v2 = e2->u.nval; ++ switch (op) { ++ case OP_ADD: r = luai_numadd(v1, v2); break; ++ case OP_SUB: r = luai_numsub(v1, v2); break; ++ case OP_MUL: r = luai_nummul(v1, v2); break; ++ case OP_DIV: ++ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++ r = luai_numdiv(v1, v2); break; ++ case OP_MOD: ++ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++ r = luai_nummod(v1, v2); break; ++ case OP_POW: r = luai_numpow(v1, v2); break; ++ case OP_UNM: r = luai_numunm(v1); break; ++ case OP_LEN: return 0; /* no constant folding for 'len' */ ++ default: lua_assert(0); r = 0; break; ++ } ++ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ ++ e1->u.nval = r; ++ return 1; ++} ++ ++ ++static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { ++ if (constfolding(op, e1, e2)) ++ return; ++ else { ++ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; ++ int o1 = luaK_exp2RK(fs, e1); ++ if (o1 > o2) { ++ freeexp(fs, e1); ++ freeexp(fs, e2); ++ } ++ else { ++ freeexp(fs, e2); ++ freeexp(fs, e1); ++ } ++ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); ++ e1->k = VRELOCABLE; ++ } ++} ++ ++ ++static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, ++ expdesc *e2) { ++ int o1 = luaK_exp2RK(fs, e1); ++ int o2 = luaK_exp2RK(fs, e2); ++ freeexp(fs, e2); ++ freeexp(fs, e1); ++ if (cond == 0 && op != OP_EQ) { ++ int temp; /* exchange args to replace by `<' or `<=' */ ++ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ ++ cond = 1; ++ } ++ e1->u.s.info = condjump(fs, op, cond, o1, o2); ++ e1->k = VJMP; ++} ++ ++ ++void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { ++ expdesc e2; ++ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; ++ switch (op) { ++ case OPR_MINUS: { ++ if (!isnumeral(e)) ++ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ ++ codearith(fs, OP_UNM, e, &e2); ++ break; ++ } ++ case OPR_NOT: codenot(fs, e); break; ++ case OPR_LEN: { ++ luaK_exp2anyreg(fs, e); /* cannot operate on constants */ ++ codearith(fs, OP_LEN, e, &e2); ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { ++ switch (op) { ++ case OPR_AND: { ++ luaK_goiftrue(fs, v); ++ break; ++ } ++ case OPR_OR: { ++ luaK_goiffalse(fs, v); ++ break; ++ } ++ case OPR_CONCAT: { ++ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ ++ break; ++ } ++ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: ++ case OPR_MOD: case OPR_POW: { ++ if (!isnumeral(v)) luaK_exp2RK(fs, v); ++ break; ++ } ++ default: { ++ luaK_exp2RK(fs, v); ++ break; ++ } ++ } ++} ++ ++ ++void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { ++ switch (op) { ++ case OPR_AND: { ++ lua_assert(e1->t == NO_JUMP); /* list must be closed */ ++ luaK_dischargevars(fs, e2); ++ luaK_concat(fs, &e2->f, e1->f); ++ *e1 = *e2; ++ break; ++ } ++ case OPR_OR: { ++ lua_assert(e1->f == NO_JUMP); /* list must be closed */ ++ luaK_dischargevars(fs, e2); ++ luaK_concat(fs, &e2->t, e1->t); ++ *e1 = *e2; ++ break; ++ } ++ case OPR_CONCAT: { ++ luaK_exp2val(fs, e2); ++ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { ++ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); ++ freeexp(fs, e1); ++ SETARG_B(getcode(fs, e2), e1->u.s.info); ++ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; ++ } ++ else { ++ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ ++ codearith(fs, OP_CONCAT, e1, e2); ++ } ++ break; ++ } ++ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; ++ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; ++ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; ++ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; ++ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; ++ case OPR_POW: codearith(fs, OP_POW, e1, e2); break; ++ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; ++ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; ++ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; ++ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; ++ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; ++ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; ++ default: lua_assert(0); ++ } ++} ++ ++ ++void luaK_fixline (FuncState *fs, int line) { ++ fs->f->lineinfo[fs->pc - 1] = line; ++} ++ ++ ++static int luaK_code (FuncState *fs, Instruction i, int line) { ++ Proto *f = fs->f; ++ dischargejpc(fs); /* `pc' will change */ ++ /* put new instruction in code array */ ++ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, ++ MAX_INT, "code size overflow"); ++ f->code[fs->pc] = i; ++ /* save corresponding line information */ ++ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, ++ MAX_INT, "code size overflow"); ++ f->lineinfo[fs->pc] = line; ++ return fs->pc++; ++} ++ ++ ++int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { ++ lua_assert(getOpMode(o) == iABC); ++ lua_assert(getBMode(o) != OpArgN || b == 0); ++ lua_assert(getCMode(o) != OpArgN || c == 0); ++ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); ++} ++ ++ ++int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { ++ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); ++ lua_assert(getCMode(o) == OpArgN); ++ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); ++} ++ ++ ++void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { ++ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; ++ int b = (tostore == LUA_MULTRET) ? 0 : tostore; ++ lua_assert(tostore != 0); ++ if (c <= MAXARG_C) ++ luaK_codeABC(fs, OP_SETLIST, base, b, c); ++ else { ++ luaK_codeABC(fs, OP_SETLIST, base, b, 0); ++ luaK_code(fs, cast(Instruction, c), fs->ls->lastline); ++ } ++ fs->freereg = base + 1; /* free registers with list values */ ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lcode.h +@@ -0,0 +1,76 @@ ++/* ++** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Code generator for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lcode_h ++#define lcode_h ++ ++#include "llex.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++ ++ ++/* ++** Marks the end of a patch list. It is an invalid value both as an absolute ++** address, and as a list link (would link an element to itself). ++*/ ++#define NO_JUMP (-1) ++ ++ ++/* ++** grep "ORDER OPR" if you change these enums ++*/ ++typedef enum BinOpr { ++ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, ++ OPR_CONCAT, ++ OPR_NE, OPR_EQ, ++ OPR_LT, OPR_LE, OPR_GT, OPR_GE, ++ OPR_AND, OPR_OR, ++ OPR_NOBINOPR ++} BinOpr; ++ ++ ++typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; ++ ++ ++#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) ++ ++#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) ++ ++#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) ++ ++LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); ++LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); ++LUAI_FUNC void luaK_fixline (FuncState *fs, int line); ++LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); ++LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); ++LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); ++LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); ++LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); ++LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); ++LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); ++LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); ++LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); ++LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_jump (FuncState *fs); ++LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); ++LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); ++LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); ++LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); ++LUAI_FUNC int luaK_getlabel (FuncState *fs); ++LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); ++LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); ++LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); ++LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ldebug.c +@@ -0,0 +1,637 @@ ++/* ++** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ ++** Debug Interface ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++#include ++#include ++ ++#define ldebug_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lapi.h" ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lvm.h" ++ ++ ++ ++static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); ++ ++ ++static int currentpc (lua_State *L, CallInfo *ci) { ++ if (!isLua(ci)) return -1; /* function is not a Lua function? */ ++ if (ci == L->ci) ++ ci->savedpc = L->savedpc; ++ return pcRel(ci->savedpc, ci_func(ci)->l.p); ++} ++ ++ ++static int currentline (lua_State *L, CallInfo *ci) { ++ int pc = currentpc(L, ci); ++ if (pc < 0) ++ return -1; /* only active lua functions have current-line information */ ++ else ++ return getline(ci_func(ci)->l.p, pc); ++} ++ ++ ++/* ++** this function can be called asynchronous (e.g. during a signal) ++*/ ++LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { ++ if (func == NULL || mask == 0) { /* turn off hooks? */ ++ mask = 0; ++ func = NULL; ++ } ++ L->hook = func; ++ L->basehookcount = count; ++ resethookcount(L); ++ L->hookmask = cast_byte(mask); ++ return 1; ++} ++ ++ ++LUA_API lua_Hook lua_gethook (lua_State *L) { ++ return L->hook; ++} ++ ++ ++LUA_API int lua_gethookmask (lua_State *L) { ++ return L->hookmask; ++} ++ ++ ++LUA_API int lua_gethookcount (lua_State *L) { ++ return L->basehookcount; ++} ++ ++ ++LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { ++ int status; ++ CallInfo *ci; ++ lua_lock(L); ++ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { ++ level--; ++ if (f_isLua(ci)) /* Lua function? */ ++ level -= ci->tailcalls; /* skip lost tail calls */ ++ } ++ if (level == 0 && ci > L->base_ci) { /* level found? */ ++ status = 1; ++ ar->i_ci = cast_int(ci - L->base_ci); ++ } ++ else if (level < 0) { /* level is of a lost tail call? */ ++ status = 1; ++ ar->i_ci = 0; ++ } ++ else status = 0; /* no such level */ ++ lua_unlock(L); ++ return status; ++} ++ ++ ++static Proto *getluaproto (CallInfo *ci) { ++ return (isLua(ci) ? ci_func(ci)->l.p : NULL); ++} ++ ++ ++static const char *findlocal (lua_State *L, CallInfo *ci, int n) { ++ const char *name; ++ Proto *fp = getluaproto(ci); ++ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) ++ return name; /* is a local variable in a Lua function */ ++ else { ++ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; ++ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ ++ return "(*temporary)"; ++ else ++ return NULL; ++ } ++} ++ ++ ++LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { ++ CallInfo *ci = L->base_ci + ar->i_ci; ++ const char *name = findlocal(L, ci, n); ++ lua_lock(L); ++ if (name) ++ luaA_pushobject(L, ci->base + (n - 1)); ++ lua_unlock(L); ++ return name; ++} ++ ++ ++LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { ++ CallInfo *ci = L->base_ci + ar->i_ci; ++ const char *name = findlocal(L, ci, n); ++ lua_lock(L); ++ if (name) ++ setobjs2s(L, ci->base + (n - 1), L->top - 1); ++ L->top--; /* pop value */ ++ lua_unlock(L); ++ return name; ++} ++ ++ ++static void funcinfo (lua_Debug *ar, Closure *cl) { ++ if (cl->c.isC) { ++ ar->source = "=[C]"; ++ ar->linedefined = -1; ++ ar->lastlinedefined = -1; ++ ar->what = "C"; ++ } ++ else { ++ ar->source = getstr(cl->l.p->source); ++ ar->linedefined = cl->l.p->linedefined; ++ ar->lastlinedefined = cl->l.p->lastlinedefined; ++ ar->what = (ar->linedefined == 0) ? "main" : "Lua"; ++ } ++ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); ++} ++ ++ ++static void info_tailcall (lua_Debug *ar) { ++ ar->name = ar->namewhat = ""; ++ ar->what = "tail"; ++ ar->lastlinedefined = ar->linedefined = ar->currentline = -1; ++ ar->source = "=(tail call)"; ++ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); ++ ar->nups = 0; ++} ++ ++ ++static void collectvalidlines (lua_State *L, Closure *f) { ++ if (f == NULL || f->c.isC) { ++ setnilvalue(L->top); ++ } ++ else { ++ Table *t = luaH_new(L, 0, 0); ++ int *lineinfo = f->l.p->lineinfo; ++ int i; ++ for (i=0; il.p->sizelineinfo; i++) ++ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); ++ sethvalue(L, L->top, t); ++ } ++ incr_top(L); ++} ++ ++ ++static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, ++ Closure *f, CallInfo *ci) { ++ int status = 1; ++ if (f == NULL) { ++ info_tailcall(ar); ++ return status; ++ } ++ for (; *what; what++) { ++ switch (*what) { ++ case 'S': { ++ funcinfo(ar, f); ++ break; ++ } ++ case 'l': { ++ ar->currentline = (ci) ? currentline(L, ci) : -1; ++ break; ++ } ++ case 'u': { ++ ar->nups = f->c.nupvalues; ++ break; ++ } ++ case 'n': { ++ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; ++ if (ar->namewhat == NULL) { ++ ar->namewhat = ""; /* not found */ ++ ar->name = NULL; ++ } ++ break; ++ } ++ case 'L': ++ case 'f': /* handled by lua_getinfo */ ++ break; ++ default: status = 0; /* invalid option */ ++ } ++ } ++ return status; ++} ++ ++ ++LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { ++ int status; ++ Closure *f = NULL; ++ CallInfo *ci = NULL; ++ lua_lock(L); ++ if (*what == '>') { ++ StkId func = L->top - 1; ++ luai_apicheck(L, ttisfunction(func)); ++ what++; /* skip the '>' */ ++ f = clvalue(func); ++ L->top--; /* pop function */ ++ } ++ else if (ar->i_ci != 0) { /* no tail call? */ ++ ci = L->base_ci + ar->i_ci; ++ lua_assert(ttisfunction(ci->func)); ++ f = clvalue(ci->func); ++ } ++ status = auxgetinfo(L, what, ar, f, ci); ++ if (strchr(what, 'f')) { ++ if (f == NULL) setnilvalue(L->top); ++ else setclvalue(L, L->top, f); ++ incr_top(L); ++ } ++ if (strchr(what, 'L')) ++ collectvalidlines(L, f); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++/* ++** {====================================================== ++** Symbolic Execution and code checker ++** ======================================================= ++*/ ++ ++#define check(x) if (!(x)) return 0; ++ ++#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) ++ ++#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) ++ ++ ++ ++static int precheck (const Proto *pt) { ++ check(pt->maxstacksize <= MAXSTACK); ++ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); ++ check(!(pt->is_vararg & VARARG_NEEDSARG) || ++ (pt->is_vararg & VARARG_HASARG)); ++ check(pt->sizeupvalues <= pt->nups); ++ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); ++ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); ++ return 1; ++} ++ ++ ++#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) ++ ++int luaG_checkopenop (Instruction i) { ++ switch (GET_OPCODE(i)) { ++ case OP_CALL: ++ case OP_TAILCALL: ++ case OP_RETURN: ++ case OP_SETLIST: { ++ check(GETARG_B(i) == 0); ++ return 1; ++ } ++ default: return 0; /* invalid instruction after an open call */ ++ } ++} ++ ++ ++static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { ++ switch (mode) { ++ case OpArgN: check(r == 0); break; ++ case OpArgU: break; ++ case OpArgR: checkreg(pt, r); break; ++ case OpArgK: ++ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); ++ break; ++ } ++ return 1; ++} ++ ++ ++static Instruction symbexec (const Proto *pt, int lastpc, int reg) { ++ int pc; ++ int last; /* stores position of last instruction that changed `reg' */ ++ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ ++ check(precheck(pt)); ++ for (pc = 0; pc < lastpc; pc++) { ++ Instruction i = pt->code[pc]; ++ OpCode op = GET_OPCODE(i); ++ int a = GETARG_A(i); ++ int b = 0; ++ int c = 0; ++ check(op < NUM_OPCODES); ++ checkreg(pt, a); ++ switch (getOpMode(op)) { ++ case iABC: { ++ b = GETARG_B(i); ++ c = GETARG_C(i); ++ check(checkArgMode(pt, b, getBMode(op))); ++ check(checkArgMode(pt, c, getCMode(op))); ++ break; ++ } ++ case iABx: { ++ b = GETARG_Bx(i); ++ if (getBMode(op) == OpArgK) check(b < pt->sizek); ++ break; ++ } ++ case iAsBx: { ++ b = GETARG_sBx(i); ++ if (getBMode(op) == OpArgR) { ++ int dest = pc+1+b; ++ check(0 <= dest && dest < pt->sizecode); ++ if (dest > 0) { ++ int j; ++ /* check that it does not jump to a setlist count; this ++ is tricky, because the count from a previous setlist may ++ have the same value of an invalid setlist; so, we must ++ go all the way back to the first of them (if any) */ ++ for (j = 0; j < dest; j++) { ++ Instruction d = pt->code[dest-1-j]; ++ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; ++ } ++ /* if 'j' is even, previous value is not a setlist (even if ++ it looks like one) */ ++ check((j&1) == 0); ++ } ++ } ++ break; ++ } ++ } ++ if (testAMode(op)) { ++ if (a == reg) last = pc; /* change register `a' */ ++ } ++ if (testTMode(op)) { ++ check(pc+2 < pt->sizecode); /* check skip */ ++ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); ++ } ++ switch (op) { ++ case OP_LOADBOOL: { ++ if (c == 1) { /* does it jump? */ ++ check(pc+2 < pt->sizecode); /* check its jump */ ++ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || ++ GETARG_C(pt->code[pc+1]) != 0); ++ } ++ break; ++ } ++ case OP_LOADNIL: { ++ if (a <= reg && reg <= b) ++ last = pc; /* set registers from `a' to `b' */ ++ break; ++ } ++ case OP_GETUPVAL: ++ case OP_SETUPVAL: { ++ check(b < pt->nups); ++ break; ++ } ++ case OP_GETGLOBAL: ++ case OP_SETGLOBAL: { ++ check(ttisstring(&pt->k[b])); ++ break; ++ } ++ case OP_SELF: { ++ checkreg(pt, a+1); ++ if (reg == a+1) last = pc; ++ break; ++ } ++ case OP_CONCAT: { ++ check(b < c); /* at least two operands */ ++ break; ++ } ++ case OP_TFORLOOP: { ++ check(c >= 1); /* at least one result (control variable) */ ++ checkreg(pt, a+2+c); /* space for results */ ++ if (reg >= a+2) last = pc; /* affect all regs above its base */ ++ break; ++ } ++ case OP_FORLOOP: ++ case OP_FORPREP: ++ checkreg(pt, a+3); ++ /* go through */ ++ case OP_JMP: { ++ int dest = pc+1+b; ++ /* not full check and jump is forward and do not skip `lastpc'? */ ++ if (reg != NO_REG && pc < dest && dest <= lastpc) ++ pc += b; /* do the jump */ ++ break; ++ } ++ case OP_CALL: ++ case OP_TAILCALL: { ++ if (b != 0) { ++ checkreg(pt, a+b-1); ++ } ++ c--; /* c = num. returns */ ++ if (c == LUA_MULTRET) { ++ check(checkopenop(pt, pc)); ++ } ++ else if (c != 0) ++ checkreg(pt, a+c-1); ++ if (reg >= a) last = pc; /* affect all registers above base */ ++ break; ++ } ++ case OP_RETURN: { ++ b--; /* b = num. returns */ ++ if (b > 0) checkreg(pt, a+b-1); ++ break; ++ } ++ case OP_SETLIST: { ++ if (b > 0) checkreg(pt, a + b); ++ if (c == 0) { ++ pc++; ++ check(pc < pt->sizecode - 1); ++ } ++ break; ++ } ++ case OP_CLOSURE: { ++ int nup, j; ++ check(b < pt->sizep); ++ nup = pt->p[b]->nups; ++ check(pc + nup < pt->sizecode); ++ for (j = 1; j <= nup; j++) { ++ OpCode op1 = GET_OPCODE(pt->code[pc + j]); ++ check(op1 == OP_GETUPVAL || op1 == OP_MOVE); ++ } ++ if (reg != NO_REG) /* tracing? */ ++ pc += nup; /* do not 'execute' these pseudo-instructions */ ++ break; ++ } ++ case OP_VARARG: { ++ check((pt->is_vararg & VARARG_ISVARARG) && ++ !(pt->is_vararg & VARARG_NEEDSARG)); ++ b--; ++ if (b == LUA_MULTRET) check(checkopenop(pt, pc)); ++ checkreg(pt, a+b-1); ++ break; ++ } ++ default: break; ++ } ++ } ++ return pt->code[last]; ++} ++ ++#undef check ++#undef checkjump ++#undef checkreg ++ ++/* }====================================================== */ ++ ++ ++int luaG_checkcode (const Proto *pt) { ++ return (symbexec(pt, pt->sizecode, NO_REG) != 0); ++} ++ ++ ++static const char *kname (Proto *p, int c) { ++ if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) ++ return svalue(&p->k[INDEXK(c)]); ++ else ++ return "?"; ++} ++ ++ ++static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, ++ const char **name) { ++ if (isLua(ci)) { /* a Lua function? */ ++ Proto *p = ci_func(ci)->l.p; ++ int pc = currentpc(L, ci); ++ Instruction i; ++ *name = luaF_getlocalname(p, stackpos+1, pc); ++ if (*name) /* is a local? */ ++ return "local"; ++ i = symbexec(p, pc, stackpos); /* try symbolic execution */ ++ lua_assert(pc != -1); ++ switch (GET_OPCODE(i)) { ++ case OP_GETGLOBAL: { ++ int g = GETARG_Bx(i); /* global index */ ++ lua_assert(ttisstring(&p->k[g])); ++ *name = svalue(&p->k[g]); ++ return "global"; ++ } ++ case OP_MOVE: { ++ int a = GETARG_A(i); ++ int b = GETARG_B(i); /* move from `b' to `a' */ ++ if (b < a) ++ return getobjname(L, ci, b, name); /* get name for `b' */ ++ break; ++ } ++ case OP_GETTABLE: { ++ int k = GETARG_C(i); /* key index */ ++ *name = kname(p, k); ++ return "field"; ++ } ++ case OP_GETUPVAL: { ++ int u = GETARG_B(i); /* upvalue index */ ++ *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; ++ return "upvalue"; ++ } ++ case OP_SELF: { ++ int k = GETARG_C(i); /* key index */ ++ *name = kname(p, k); ++ return "method"; ++ } ++ default: break; ++ } ++ } ++ return NULL; /* no useful name found */ ++} ++ ++ ++static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { ++ Instruction i; ++ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) ++ return NULL; /* calling function is not Lua (or is unknown) */ ++ ci--; /* calling function */ ++ i = ci_func(ci)->l.p->code[currentpc(L, ci)]; ++ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || ++ GET_OPCODE(i) == OP_TFORLOOP) ++ return getobjname(L, ci, GETARG_A(i), name); ++ else ++ return NULL; /* no useful name can be found */ ++} ++ ++ ++/* only ANSI way to check whether a pointer points to an array */ ++static int isinstack (CallInfo *ci, const TValue *o) { ++ StkId p; ++ for (p = ci->base; p < ci->top; p++) ++ if (o == p) return 1; ++ return 0; ++} ++ ++ ++void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { ++ const char *name = NULL; ++ const char *t = luaT_typenames[ttype(o)]; ++ const char *kind = (isinstack(L->ci, o)) ? ++ getobjname(L, L->ci, cast_int(o - L->base), &name) : ++ NULL; ++ if (kind) ++ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", ++ op, kind, name, t); ++ else ++ luaG_runerror(L, "attempt to %s a %s value", op, t); ++} ++ ++ ++void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { ++ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; ++ lua_assert(!ttisstring(p1) && !ttisnumber(p1)); ++ luaG_typeerror(L, p1, "concatenate"); ++} ++ ++ ++void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { ++ TValue temp; ++ if (luaV_tonumber(p1, &temp) == NULL) ++ p2 = p1; /* first operand is wrong */ ++ luaG_typeerror(L, p2, "perform arithmetic on"); ++} ++ ++ ++int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { ++ const char *t1 = luaT_typenames[ttype(p1)]; ++ const char *t2 = luaT_typenames[ttype(p2)]; ++ if (t1[2] == t2[2]) ++ luaG_runerror(L, "attempt to compare two %s values", t1); ++ else ++ luaG_runerror(L, "attempt to compare %s with %s", t1, t2); ++ return 0; ++} ++ ++ ++static void addinfo (lua_State *L, const char *msg) { ++ CallInfo *ci = L->ci; ++ if (isLua(ci)) { /* is Lua code? */ ++ char buff[LUA_IDSIZE]; /* add file:line information */ ++ int line = currentline(L, ci); ++ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); ++ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); ++ } ++} ++ ++ ++void luaG_errormsg (lua_State *L) { ++ if (L->errfunc != 0) { /* is there an error handling function? */ ++ StkId errfunc = restorestack(L, L->errfunc); ++ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); ++ setobjs2s(L, L->top, L->top - 1); /* move argument */ ++ setobjs2s(L, L->top - 1, errfunc); /* push function */ ++ incr_top(L); ++ luaD_call(L, L->top - 2, 1); /* call it */ ++ } ++ luaD_throw(L, LUA_ERRRUN); ++} ++ ++ ++void luaG_runerror (lua_State *L, const char *fmt, ...) { ++ va_list argp; ++ va_start(argp, fmt); ++ addinfo(L, luaO_pushvfstring(L, fmt, argp)); ++ va_end(argp); ++ luaG_errormsg(L); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldebug.h +@@ -0,0 +1,33 @@ ++/* ++** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions from Debug Interface module ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ldebug_h ++#define ldebug_h ++ ++ ++#include "lstate.h" ++ ++ ++#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) ++ ++#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) ++ ++#define resethookcount(L) (L->hookcount = L->basehookcount) ++ ++ ++LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, ++ const char *opname); ++LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); ++LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, ++ const TValue *p2); ++LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, ++ const TValue *p2); ++LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); ++LUAI_FUNC void luaG_errormsg (lua_State *L); ++LUAI_FUNC int luaG_checkcode (const Proto *pt); ++LUAI_FUNC int luaG_checkopenop (Instruction i); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ldo.c +@@ -0,0 +1,515 @@ ++/* ++** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ ++** Stack and Call structure of Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++ ++#define ldo_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lundump.h" ++#include "lvm.h" ++#include "lzio.h" ++ ++ ++ ++/* ++** {====================================================== ++** Error-recovery functions ++** ======================================================= ++*/ ++ ++ ++/* chain list of long jump buffers */ ++struct lua_longjmp { ++ struct lua_longjmp *previous; ++ luai_jmpbuf b; ++ volatile int status; /* error code */ ++}; ++ ++ ++void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { ++ switch (errcode) { ++ case LUA_ERRMEM: { ++ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); ++ break; ++ } ++ case LUA_ERRERR: { ++ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); ++ break; ++ } ++ case LUA_ERRSYNTAX: ++ case LUA_ERRRUN: { ++ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ ++ break; ++ } ++ } ++ L->top = oldtop + 1; ++} ++ ++ ++static void restore_stack_limit (lua_State *L) { ++ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); ++ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ ++ int inuse = cast_int(L->ci - L->base_ci); ++ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ ++ luaD_reallocCI(L, LUAI_MAXCALLS); ++ } ++} ++ ++ ++static void resetstack (lua_State *L, int status) { ++ L->ci = L->base_ci; ++ L->base = L->ci->base; ++ luaF_close(L, L->base); /* close eventual pending closures */ ++ luaD_seterrorobj(L, status, L->base); ++ L->nCcalls = L->baseCcalls; ++ L->allowhook = 1; ++ restore_stack_limit(L); ++ L->errfunc = 0; ++ L->errorJmp = NULL; ++} ++ ++ ++void luaD_throw (lua_State *L, int errcode) { ++ if (L->errorJmp) { ++ L->errorJmp->status = errcode; ++ LUAI_THROW(L, L->errorJmp); ++ } ++ else { ++ L->status = cast_byte(errcode); ++ if (G(L)->panic) { ++ resetstack(L, errcode); ++ lua_unlock(L); ++ G(L)->panic(L); ++ } ++ exit(EXIT_FAILURE); ++ } ++} ++ ++ ++int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ++ struct lua_longjmp lj; ++ lj.status = 0; ++ lj.previous = L->errorJmp; /* chain new error handler */ ++ L->errorJmp = &lj; ++ LUAI_TRY(L, &lj, ++ (*f)(L, ud); ++ ); ++ L->errorJmp = lj.previous; /* restore old error handler */ ++ return lj.status; ++} ++ ++/* }====================================================== */ ++ ++ ++static void correctstack (lua_State *L, TValue *oldstack) { ++ CallInfo *ci; ++ GCObject *up; ++ L->top = (L->top - oldstack) + L->stack; ++ for (up = L->openupval; up != NULL; up = up->gch.next) ++ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; ++ for (ci = L->base_ci; ci <= L->ci; ci++) { ++ ci->top = (ci->top - oldstack) + L->stack; ++ ci->base = (ci->base - oldstack) + L->stack; ++ ci->func = (ci->func - oldstack) + L->stack; ++ } ++ L->base = (L->base - oldstack) + L->stack; ++} ++ ++ ++void luaD_reallocstack (lua_State *L, int newsize) { ++ TValue *oldstack = L->stack; ++ int realsize = newsize + 1 + EXTRA_STACK; ++ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); ++ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); ++ L->stacksize = realsize; ++ L->stack_last = L->stack+newsize; ++ correctstack(L, oldstack); ++} ++ ++ ++void luaD_reallocCI (lua_State *L, int newsize) { ++ CallInfo *oldci = L->base_ci; ++ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); ++ L->size_ci = newsize; ++ L->ci = (L->ci - oldci) + L->base_ci; ++ L->end_ci = L->base_ci + L->size_ci - 1; ++} ++ ++ ++void luaD_growstack (lua_State *L, int n) { ++ if (n <= L->stacksize) /* double size is enough? */ ++ luaD_reallocstack(L, 2*L->stacksize); ++ else ++ luaD_reallocstack(L, L->stacksize + n); ++} ++ ++ ++static CallInfo *growCI (lua_State *L) { ++ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ ++ luaD_throw(L, LUA_ERRERR); ++ else { ++ luaD_reallocCI(L, 2*L->size_ci); ++ if (L->size_ci > LUAI_MAXCALLS) ++ luaG_runerror(L, "stack overflow"); ++ } ++ return ++L->ci; ++} ++ ++ ++void luaD_callhook (lua_State *L, int event, int line) { ++ lua_Hook hook = L->hook; ++ if (hook && L->allowhook) { ++ ptrdiff_t top = savestack(L, L->top); ++ ptrdiff_t ci_top = savestack(L, L->ci->top); ++ lua_Debug ar; ++ ar.event = event; ++ ar.currentline = line; ++ if (event == LUA_HOOKTAILRET) ++ ar.i_ci = 0; /* tail call; no debug information about it */ ++ else ++ ar.i_ci = cast_int(L->ci - L->base_ci); ++ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ++ L->ci->top = L->top + LUA_MINSTACK; ++ lua_assert(L->ci->top <= L->stack_last); ++ L->allowhook = 0; /* cannot call hooks inside a hook */ ++ lua_unlock(L); ++ (*hook)(L, &ar); ++ lua_lock(L); ++ lua_assert(!L->allowhook); ++ L->allowhook = 1; ++ L->ci->top = restorestack(L, ci_top); ++ L->top = restorestack(L, top); ++ } ++} ++ ++ ++static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { ++ int i; ++ int nfixargs = p->numparams; ++ Table *htab = NULL; ++ StkId base, fixed; ++ for (; actual < nfixargs; ++actual) ++ setnilvalue(L->top++); ++#if defined(LUA_COMPAT_VARARG) ++ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ ++ int nvar = actual - nfixargs; /* number of extra arguments */ ++ lua_assert(p->is_vararg & VARARG_HASARG); ++ luaC_checkGC(L); ++ htab = luaH_new(L, nvar, 1); /* create `arg' table */ ++ for (i=0; itop - nvar + i); ++ /* store counter in field `n' */ ++ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); ++ } ++#endif ++ /* move fixed parameters to final position */ ++ fixed = L->top - actual; /* first fixed argument */ ++ base = L->top; /* final position of first argument */ ++ for (i=0; itop++, fixed+i); ++ setnilvalue(fixed+i); ++ } ++ /* add `arg' parameter */ ++ if (htab) { ++ sethvalue(L, L->top++, htab); ++ lua_assert(iswhite(obj2gco(htab))); ++ } ++ return base; ++} ++ ++ ++static StkId tryfuncTM (lua_State *L, StkId func) { ++ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); ++ StkId p; ++ ptrdiff_t funcr = savestack(L, func); ++ if (!ttisfunction(tm)) ++ luaG_typeerror(L, func, "call"); ++ /* Open a hole inside the stack at `func' */ ++ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); ++ incr_top(L); ++ func = restorestack(L, funcr); /* previous call may change stack */ ++ setobj2s(L, func, tm); /* tag method is the new function to be called */ ++ return func; ++} ++ ++ ++ ++#define inc_ci(L) \ ++ ((L->ci == L->end_ci) ? growCI(L) : \ ++ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) ++ ++ ++int luaD_precall (lua_State *L, StkId func, int nresults) { ++ LClosure *cl; ++ ptrdiff_t funcr; ++ if (!ttisfunction(func)) /* `func' is not a function? */ ++ func = tryfuncTM(L, func); /* check the `function' tag method */ ++ funcr = savestack(L, func); ++ cl = &clvalue(func)->l; ++ L->ci->savedpc = L->savedpc; ++ if (!cl->isC) { /* Lua function? prepare its call */ ++ CallInfo *ci; ++ StkId st, base; ++ Proto *p = cl->p; ++ luaD_checkstack(L, p->maxstacksize); ++ func = restorestack(L, funcr); ++ if (!p->is_vararg) { /* no varargs? */ ++ base = func + 1; ++ if (L->top > base + p->numparams) ++ L->top = base + p->numparams; ++ } ++ else { /* vararg function */ ++ int nargs = cast_int(L->top - func) - 1; ++ base = adjust_varargs(L, p, nargs); ++ func = restorestack(L, funcr); /* previous call may change the stack */ ++ } ++ ci = inc_ci(L); /* now `enter' new function */ ++ ci->func = func; ++ L->base = ci->base = base; ++ ci->top = L->base + p->maxstacksize; ++ lua_assert(ci->top <= L->stack_last); ++ L->savedpc = p->code; /* starting point */ ++ ci->tailcalls = 0; ++ ci->nresults = nresults; ++ for (st = L->top; st < ci->top; st++) ++ setnilvalue(st); ++ L->top = ci->top; ++ if (L->hookmask & LUA_MASKCALL) { ++ L->savedpc++; /* hooks assume 'pc' is already incremented */ ++ luaD_callhook(L, LUA_HOOKCALL, -1); ++ L->savedpc--; /* correct 'pc' */ ++ } ++ return PCRLUA; ++ } ++ else { /* if is a C function, call it */ ++ CallInfo *ci; ++ int n; ++ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ++ ci = inc_ci(L); /* now `enter' new function */ ++ ci->func = restorestack(L, funcr); ++ L->base = ci->base = ci->func + 1; ++ ci->top = L->top + LUA_MINSTACK; ++ lua_assert(ci->top <= L->stack_last); ++ ci->nresults = nresults; ++ if (L->hookmask & LUA_MASKCALL) ++ luaD_callhook(L, LUA_HOOKCALL, -1); ++ lua_unlock(L); ++ n = (*curr_func(L)->c.f)(L); /* do the actual call */ ++ lua_lock(L); ++ if (n < 0) /* yielding? */ ++ return PCRYIELD; ++ else { ++ luaD_poscall(L, L->top - n); ++ return PCRC; ++ } ++ } ++} ++ ++ ++static StkId callrethooks (lua_State *L, StkId firstResult) { ++ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ ++ luaD_callhook(L, LUA_HOOKRET, -1); ++ if (f_isLua(L->ci)) { /* Lua function? */ ++ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ ++ luaD_callhook(L, LUA_HOOKTAILRET, -1); ++ } ++ return restorestack(L, fr); ++} ++ ++ ++int luaD_poscall (lua_State *L, StkId firstResult) { ++ StkId res; ++ int wanted, i; ++ CallInfo *ci; ++ if (L->hookmask & LUA_MASKRET) ++ firstResult = callrethooks(L, firstResult); ++ ci = L->ci--; ++ res = ci->func; /* res == final position of 1st result */ ++ wanted = ci->nresults; ++ L->base = (ci - 1)->base; /* restore base */ ++ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ ++ /* move results to correct place */ ++ for (i = wanted; i != 0 && firstResult < L->top; i--) ++ setobjs2s(L, res++, firstResult++); ++ while (i-- > 0) ++ setnilvalue(res++); ++ L->top = res; ++ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ ++} ++ ++ ++/* ++** Call a function (C or Lua). The function to be called is at *func. ++** The arguments are on the stack, right after the function. ++** When returns, all the results are on the stack, starting at the original ++** function position. ++*/ ++void luaD_call (lua_State *L, StkId func, int nResults) { ++ if (++L->nCcalls >= LUAI_MAXCCALLS) { ++ if (L->nCcalls == LUAI_MAXCCALLS) ++ luaG_runerror(L, "C stack overflow"); ++ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) ++ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ ++ } ++ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ ++ luaV_execute(L, 1); /* call it */ ++ L->nCcalls--; ++ luaC_checkGC(L); ++} ++ ++ ++static void resume (lua_State *L, void *ud) { ++ StkId firstArg = cast(StkId, ud); ++ CallInfo *ci = L->ci; ++ if (L->status == 0) { /* start coroutine? */ ++ lua_assert(ci == L->base_ci && firstArg > L->base); ++ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) ++ return; ++ } ++ else { /* resuming from previous yield */ ++ lua_assert(L->status == LUA_YIELD); ++ L->status = 0; ++ if (!f_isLua(ci)) { /* `common' yield? */ ++ /* finish interrupted execution of `OP_CALL' */ ++ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || ++ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); ++ if (luaD_poscall(L, firstArg)) /* complete it... */ ++ L->top = L->ci->top; /* and correct top if not multiple results */ ++ } ++ else /* yielded inside a hook: just continue its execution */ ++ L->base = L->ci->base; ++ } ++ luaV_execute(L, cast_int(L->ci - L->base_ci)); ++} ++ ++ ++static int resume_error (lua_State *L, const char *msg) { ++ L->top = L->ci->base; ++ setsvalue2s(L, L->top, luaS_new(L, msg)); ++ incr_top(L); ++ lua_unlock(L); ++ return LUA_ERRRUN; ++} ++ ++ ++LUA_API int lua_resume (lua_State *L, int nargs) { ++ int status; ++ lua_lock(L); ++ if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) ++ return resume_error(L, "cannot resume non-suspended coroutine"); ++ if (L->nCcalls >= LUAI_MAXCCALLS) ++ return resume_error(L, "C stack overflow"); ++ luai_userstateresume(L, nargs); ++ lua_assert(L->errfunc == 0); ++ L->baseCcalls = ++L->nCcalls; ++ status = luaD_rawrunprotected(L, resume, L->top - nargs); ++ if (status != 0) { /* error? */ ++ L->status = cast_byte(status); /* mark thread as `dead' */ ++ luaD_seterrorobj(L, status, L->top); ++ L->ci->top = L->top; ++ } ++ else { ++ lua_assert(L->nCcalls == L->baseCcalls); ++ status = L->status; ++ } ++ --L->nCcalls; ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_yield (lua_State *L, int nresults) { ++ luai_userstateyield(L, nresults); ++ lua_lock(L); ++ if (L->nCcalls > L->baseCcalls) ++ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); ++ L->base = L->top - nresults; /* protect stack slots below */ ++ L->status = LUA_YIELD; ++ lua_unlock(L); ++ return -1; ++} ++ ++ ++int luaD_pcall (lua_State *L, Pfunc func, void *u, ++ ptrdiff_t old_top, ptrdiff_t ef) { ++ int status; ++ unsigned short oldnCcalls = L->nCcalls; ++ ptrdiff_t old_ci = saveci(L, L->ci); ++ lu_byte old_allowhooks = L->allowhook; ++ ptrdiff_t old_errfunc = L->errfunc; ++ L->errfunc = ef; ++ status = luaD_rawrunprotected(L, func, u); ++ if (status != 0) { /* an error occurred? */ ++ StkId oldtop = restorestack(L, old_top); ++ luaF_close(L, oldtop); /* close eventual pending closures */ ++ luaD_seterrorobj(L, status, oldtop); ++ L->nCcalls = oldnCcalls; ++ L->ci = restoreci(L, old_ci); ++ L->base = L->ci->base; ++ L->savedpc = L->ci->savedpc; ++ L->allowhook = old_allowhooks; ++ restore_stack_limit(L); ++ } ++ L->errfunc = old_errfunc; ++ return status; ++} ++ ++ ++ ++/* ++** Execute a protected parser. ++*/ ++struct SParser { /* data to `f_parser' */ ++ ZIO *z; ++ Mbuffer buff; /* buffer to be used by the scanner */ ++ const char *name; ++}; ++ ++static void f_parser (lua_State *L, void *ud) { ++ int i; ++ Proto *tf; ++ Closure *cl; ++ struct SParser *p = cast(struct SParser *, ud); ++ int c = luaZ_lookahead(p->z); ++ luaC_checkGC(L); ++ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, ++ &p->buff, p->name); ++ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); ++ cl->l.p = tf; ++ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ ++ cl->l.upvals[i] = luaF_newupval(L); ++ setclvalue(L, L->top, cl); ++ incr_top(L); ++} ++ ++ ++int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { ++ struct SParser p; ++ int status; ++ p.z = z; p.name = name; ++ luaZ_initbuffer(L, &p.buff); ++ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); ++ luaZ_freebuffer(L, &p.buff); ++ return status; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldo.h +@@ -0,0 +1,57 @@ ++/* ++** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Stack and Call structure of Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ldo_h ++#define ldo_h ++ ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lzio.h" ++ ++ ++#define luaD_checkstack(L,n) \ ++ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ ++ luaD_growstack(L, n); \ ++ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); ++ ++ ++#define incr_top(L) {luaD_checkstack(L,1); L->top++;} ++ ++#define savestack(L,p) ((char *)(p) - (char *)L->stack) ++#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) ++ ++#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) ++#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) ++ ++ ++/* results from luaD_precall */ ++#define PCRLUA 0 /* initiated a call to a Lua function */ ++#define PCRC 1 /* did a call to a C function */ ++#define PCRYIELD 2 /* C funtion yielded */ ++ ++ ++/* type of protected functions, to be ran by `runprotected' */ ++typedef void (*Pfunc) (lua_State *L, void *ud); ++ ++LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); ++LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); ++LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); ++LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); ++LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ++ ptrdiff_t oldtop, ptrdiff_t ef); ++LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); ++LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); ++LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); ++LUAI_FUNC void luaD_growstack (lua_State *L, int n); ++ ++LUAI_FUNC void luaD_throw (lua_State *L, int errcode); ++LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); ++ ++LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldump.c +@@ -0,0 +1,164 @@ ++/* ++** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ++** save precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define ldump_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lundump.h" ++ ++typedef struct { ++ lua_State* L; ++ lua_Writer writer; ++ void* data; ++ int strip; ++ int status; ++} DumpState; ++ ++#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) ++#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) ++ ++static void DumpBlock(const void* b, size_t size, DumpState* D) ++{ ++ if (D->status==0) ++ { ++ lua_unlock(D->L); ++ D->status=(*D->writer)(D->L,b,size,D->data); ++ lua_lock(D->L); ++ } ++} ++ ++static void DumpChar(int y, DumpState* D) ++{ ++ char x=(char)y; ++ DumpVar(x,D); ++} ++ ++static void DumpInt(int x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ ++static void DumpNumber(lua_Number x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ ++static void DumpVector(const void* b, int n, size_t size, DumpState* D) ++{ ++ DumpInt(n,D); ++ DumpMem(b,n,size,D); ++} ++ ++static void DumpString(const TString* s, DumpState* D) ++{ ++ if (s==NULL || getstr(s)==NULL) ++ { ++ size_t size=0; ++ DumpVar(size,D); ++ } ++ else ++ { ++ size_t size=s->tsv.len+1; /* include trailing '\0' */ ++ DumpVar(size,D); ++ DumpBlock(getstr(s),size,D); ++ } ++} ++ ++#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) ++ ++static void DumpFunction(const Proto* f, const TString* p, DumpState* D); ++ ++static void DumpConstants(const Proto* f, DumpState* D) ++{ ++ int i,n=f->sizek; ++ DumpInt(n,D); ++ for (i=0; ik[i]; ++ DumpChar(ttype(o),D); ++ switch (ttype(o)) ++ { ++ case LUA_TNIL: ++ break; ++ case LUA_TBOOLEAN: ++ DumpChar(bvalue(o),D); ++ break; ++ case LUA_TNUMBER: ++ DumpNumber(nvalue(o),D); ++ break; ++ case LUA_TSTRING: ++ DumpString(rawtsvalue(o),D); ++ break; ++ default: ++ lua_assert(0); /* cannot happen */ ++ break; ++ } ++ } ++ n=f->sizep; ++ DumpInt(n,D); ++ for (i=0; ip[i],f->source,D); ++} ++ ++static void DumpDebug(const Proto* f, DumpState* D) ++{ ++ int i,n; ++ n= (D->strip) ? 0 : f->sizelineinfo; ++ DumpVector(f->lineinfo,n,sizeof(int),D); ++ n= (D->strip) ? 0 : f->sizelocvars; ++ DumpInt(n,D); ++ for (i=0; ilocvars[i].varname,D); ++ DumpInt(f->locvars[i].startpc,D); ++ DumpInt(f->locvars[i].endpc,D); ++ } ++ n= (D->strip) ? 0 : f->sizeupvalues; ++ DumpInt(n,D); ++ for (i=0; iupvalues[i],D); ++} ++ ++static void DumpFunction(const Proto* f, const TString* p, DumpState* D) ++{ ++ DumpString((f->source==p || D->strip) ? NULL : f->source,D); ++ DumpInt(f->linedefined,D); ++ DumpInt(f->lastlinedefined,D); ++ DumpChar(f->nups,D); ++ DumpChar(f->numparams,D); ++ DumpChar(f->is_vararg,D); ++ DumpChar(f->maxstacksize,D); ++ DumpCode(f,D); ++ DumpConstants(f,D); ++ DumpDebug(f,D); ++} ++ ++static void DumpHeader(DumpState* D) ++{ ++ char h[LUAC_HEADERSIZE]; ++ luaU_header(h); ++ DumpBlock(h,LUAC_HEADERSIZE,D); ++} ++ ++/* ++** dump Lua function as precompiled chunk ++*/ ++int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) ++{ ++ DumpState D; ++ D.L=L; ++ D.writer=w; ++ D.data=data; ++ D.strip=strip; ++ D.status=0; ++ DumpHeader(&D); ++ DumpFunction(f,NULL,&D); ++ return D.status; ++} +--- /dev/null ++++ b/extensions/LUA/lua/lfunc.c +@@ -0,0 +1,174 @@ ++/* ++** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ ++** Auxiliary functions to manipulate prototypes and closures ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lfunc_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++ ++Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { ++ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); ++ luaC_link(L, obj2gco(c), LUA_TFUNCTION); ++ c->c.isC = 1; ++ c->c.env = e; ++ c->c.nupvalues = cast_byte(nelems); ++ return c; ++} ++ ++ ++Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { ++ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); ++ luaC_link(L, obj2gco(c), LUA_TFUNCTION); ++ c->l.isC = 0; ++ c->l.env = e; ++ c->l.nupvalues = cast_byte(nelems); ++ while (nelems--) c->l.upvals[nelems] = NULL; ++ return c; ++} ++ ++ ++UpVal *luaF_newupval (lua_State *L) { ++ UpVal *uv = luaM_new(L, UpVal); ++ luaC_link(L, obj2gco(uv), LUA_TUPVAL); ++ uv->v = &uv->u.value; ++ setnilvalue(uv->v); ++ return uv; ++} ++ ++ ++UpVal *luaF_findupval (lua_State *L, StkId level) { ++ global_State *g = G(L); ++ GCObject **pp = &L->openupval; ++ UpVal *p; ++ UpVal *uv; ++ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { ++ lua_assert(p->v != &p->u.value); ++ if (p->v == level) { /* found a corresponding upvalue? */ ++ if (isdead(g, obj2gco(p))) /* is it dead? */ ++ changewhite(obj2gco(p)); /* ressurect it */ ++ return p; ++ } ++ pp = &p->next; ++ } ++ uv = luaM_new(L, UpVal); /* not found: create a new one */ ++ uv->tt = LUA_TUPVAL; ++ uv->marked = luaC_white(g); ++ uv->v = level; /* current value lives in the stack */ ++ uv->next = *pp; /* chain it in the proper position */ ++ *pp = obj2gco(uv); ++ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ ++ uv->u.l.next = g->uvhead.u.l.next; ++ uv->u.l.next->u.l.prev = uv; ++ g->uvhead.u.l.next = uv; ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ return uv; ++} ++ ++ ++static void unlinkupval (UpVal *uv) { ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ ++ uv->u.l.prev->u.l.next = uv->u.l.next; ++} ++ ++ ++void luaF_freeupval (lua_State *L, UpVal *uv) { ++ if (uv->v != &uv->u.value) /* is it open? */ ++ unlinkupval(uv); /* remove from open list */ ++ luaM_free(L, uv); /* free upvalue */ ++} ++ ++ ++void luaF_close (lua_State *L, StkId level) { ++ UpVal *uv; ++ global_State *g = G(L); ++ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { ++ GCObject *o = obj2gco(uv); ++ lua_assert(!isblack(o) && uv->v != &uv->u.value); ++ L->openupval = uv->next; /* remove from `open' list */ ++ if (isdead(g, o)) ++ luaF_freeupval(L, uv); /* free upvalue */ ++ else { ++ unlinkupval(uv); ++ setobj(L, &uv->u.value, uv->v); ++ uv->v = &uv->u.value; /* now current value lives here */ ++ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ ++ } ++ } ++} ++ ++ ++Proto *luaF_newproto (lua_State *L) { ++ Proto *f = luaM_new(L, Proto); ++ luaC_link(L, obj2gco(f), LUA_TPROTO); ++ f->k = NULL; ++ f->sizek = 0; ++ f->p = NULL; ++ f->sizep = 0; ++ f->code = NULL; ++ f->sizecode = 0; ++ f->sizelineinfo = 0; ++ f->sizeupvalues = 0; ++ f->nups = 0; ++ f->upvalues = NULL; ++ f->numparams = 0; ++ f->is_vararg = 0; ++ f->maxstacksize = 0; ++ f->lineinfo = NULL; ++ f->sizelocvars = 0; ++ f->locvars = NULL; ++ f->linedefined = 0; ++ f->lastlinedefined = 0; ++ f->source = NULL; ++ return f; ++} ++ ++ ++void luaF_freeproto (lua_State *L, Proto *f) { ++ luaM_freearray(L, f->code, f->sizecode, Instruction); ++ luaM_freearray(L, f->p, f->sizep, Proto *); ++ luaM_freearray(L, f->k, f->sizek, TValue); ++ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); ++ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); ++ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); ++ luaM_free(L, f); ++} ++ ++ ++void luaF_freeclosure (lua_State *L, Closure *c) { ++ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : ++ sizeLclosure(c->l.nupvalues); ++ luaM_freemem(L, c, size); ++} ++ ++ ++/* ++** Look for n-th local variable at line `line' in function `func'. ++** Returns NULL if not found. ++*/ ++const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { ++ int i; ++ for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { ++ if (pc < f->locvars[i].endpc) { /* is variable active? */ ++ local_number--; ++ if (local_number == 0) ++ return getstr(f->locvars[i].varname); ++ } ++ } ++ return NULL; /* not found */ ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lfunc.h +@@ -0,0 +1,34 @@ ++/* ++** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions to manipulate prototypes and closures ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lfunc_h ++#define lfunc_h ++ ++ ++#include "lobject.h" ++ ++ ++#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ ++ cast(int, sizeof(TValue)*((n)-1))) ++ ++#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ ++ cast(int, sizeof(TValue *)*((n)-1))) ++ ++ ++LUAI_FUNC Proto *luaF_newproto (lua_State *L); ++LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); ++LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); ++LUAI_FUNC UpVal *luaF_newupval (lua_State *L); ++LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); ++LUAI_FUNC void luaF_close (lua_State *L, StkId level); ++LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); ++LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); ++LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); ++LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, ++ int pc); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lgc.c +@@ -0,0 +1,711 @@ ++/* ++** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Garbage Collector ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lgc_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++#define GCSTEPSIZE 1024u ++#define GCSWEEPMAX 40 ++#define GCSWEEPCOST 10 ++#define GCFINALIZECOST 100 ++ ++ ++#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) ++ ++#define makewhite(g,x) \ ++ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) ++ ++#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) ++#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) ++ ++#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) ++ ++ ++#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) ++#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) ++ ++ ++#define KEYWEAK bitmask(KEYWEAKBIT) ++#define VALUEWEAK bitmask(VALUEWEAKBIT) ++ ++ ++ ++#define markvalue(g,o) { checkconsistency(o); \ ++ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } ++ ++#define markobject(g,t) { if (iswhite(obj2gco(t))) \ ++ reallymarkobject(g, obj2gco(t)); } ++ ++ ++#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) ++ ++ ++static void removeentry (Node *n) { ++ lua_assert(ttisnil(gval(n))); ++ if (iscollectable(gkey(n))) ++ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ ++} ++ ++ ++static void reallymarkobject (global_State *g, GCObject *o) { ++ lua_assert(iswhite(o) && !isdead(g, o)); ++ white2gray(o); ++ switch (o->gch.tt) { ++ case LUA_TSTRING: { ++ return; ++ } ++ case LUA_TUSERDATA: { ++ Table *mt = gco2u(o)->metatable; ++ gray2black(o); /* udata are never gray */ ++ if (mt) markobject(g, mt); ++ markobject(g, gco2u(o)->env); ++ return; ++ } ++ case LUA_TUPVAL: { ++ UpVal *uv = gco2uv(o); ++ markvalue(g, uv->v); ++ if (uv->v == &uv->u.value) /* closed? */ ++ gray2black(o); /* open upvalues are never black */ ++ return; ++ } ++ case LUA_TFUNCTION: { ++ gco2cl(o)->c.gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TTABLE: { ++ gco2h(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TTHREAD: { ++ gco2th(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TPROTO: { ++ gco2p(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++static void marktmu (global_State *g) { ++ GCObject *u = g->tmudata; ++ if (u) { ++ do { ++ u = u->gch.next; ++ makewhite(g, u); /* may be marked, if left from previous GC */ ++ reallymarkobject(g, u); ++ } while (u != g->tmudata); ++ } ++} ++ ++ ++/* move `dead' udata that need finalization to list `tmudata' */ ++size_t luaC_separateudata (lua_State *L, int all) { ++ global_State *g = G(L); ++ size_t deadmem = 0; ++ GCObject **p = &g->mainthread->next; ++ GCObject *curr; ++ while ((curr = *p) != NULL) { ++ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) ++ p = &curr->gch.next; /* don't bother with them */ ++ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { ++ markfinalized(gco2u(curr)); /* don't need finalization */ ++ p = &curr->gch.next; ++ } ++ else { /* must call its gc method */ ++ deadmem += sizeudata(gco2u(curr)); ++ markfinalized(gco2u(curr)); ++ *p = curr->gch.next; ++ /* link `curr' at the end of `tmudata' list */ ++ if (g->tmudata == NULL) /* list is empty? */ ++ g->tmudata = curr->gch.next = curr; /* creates a circular list */ ++ else { ++ curr->gch.next = g->tmudata->gch.next; ++ g->tmudata->gch.next = curr; ++ g->tmudata = curr; ++ } ++ } ++ } ++ return deadmem; ++} ++ ++ ++static int traversetable (global_State *g, Table *h) { ++ int i; ++ int weakkey = 0; ++ int weakvalue = 0; ++ const TValue *mode; ++ if (h->metatable) ++ markobject(g, h->metatable); ++ mode = gfasttm(g, h->metatable, TM_MODE); ++ if (mode && ttisstring(mode)) { /* is there a weak mode? */ ++ weakkey = (strchr(svalue(mode), 'k') != NULL); ++ weakvalue = (strchr(svalue(mode), 'v') != NULL); ++ if (weakkey || weakvalue) { /* is really weak? */ ++ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ ++ h->marked |= cast_byte((weakkey << KEYWEAKBIT) | ++ (weakvalue << VALUEWEAKBIT)); ++ h->gclist = g->weak; /* must be cleared after GC, ... */ ++ g->weak = obj2gco(h); /* ... so put in the appropriate list */ ++ } ++ } ++ if (weakkey && weakvalue) return 1; ++ if (!weakvalue) { ++ i = h->sizearray; ++ while (i--) ++ markvalue(g, &h->array[i]); ++ } ++ i = sizenode(h); ++ while (i--) { ++ Node *n = gnode(h, i); ++ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); ++ if (ttisnil(gval(n))) ++ removeentry(n); /* remove empty entries */ ++ else { ++ lua_assert(!ttisnil(gkey(n))); ++ if (!weakkey) markvalue(g, gkey(n)); ++ if (!weakvalue) markvalue(g, gval(n)); ++ } ++ } ++ return weakkey || weakvalue; ++} ++ ++ ++/* ++** All marks are conditional because a GC may happen while the ++** prototype is still being created ++*/ ++static void traverseproto (global_State *g, Proto *f) { ++ int i; ++ if (f->source) stringmark(f->source); ++ for (i=0; isizek; i++) /* mark literals */ ++ markvalue(g, &f->k[i]); ++ for (i=0; isizeupvalues; i++) { /* mark upvalue names */ ++ if (f->upvalues[i]) ++ stringmark(f->upvalues[i]); ++ } ++ for (i=0; isizep; i++) { /* mark nested protos */ ++ if (f->p[i]) ++ markobject(g, f->p[i]); ++ } ++ for (i=0; isizelocvars; i++) { /* mark local-variable names */ ++ if (f->locvars[i].varname) ++ stringmark(f->locvars[i].varname); ++ } ++} ++ ++ ++ ++static void traverseclosure (global_State *g, Closure *cl) { ++ markobject(g, cl->c.env); ++ if (cl->c.isC) { ++ int i; ++ for (i=0; ic.nupvalues; i++) /* mark its upvalues */ ++ markvalue(g, &cl->c.upvalue[i]); ++ } ++ else { ++ int i; ++ lua_assert(cl->l.nupvalues == cl->l.p->nups); ++ markobject(g, cl->l.p); ++ for (i=0; il.nupvalues; i++) /* mark its upvalues */ ++ markobject(g, cl->l.upvals[i]); ++ } ++} ++ ++ ++static void checkstacksizes (lua_State *L, StkId max) { ++ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ ++ int s_used = cast_int(max - L->stack); /* part of stack in use */ ++ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ ++ return; /* do not touch the stacks */ ++ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) ++ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ ++ condhardstacktests(luaD_reallocCI(L, ci_used + 1)); ++ if (4*s_used < L->stacksize && ++ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) ++ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ ++ condhardstacktests(luaD_reallocstack(L, s_used)); ++} ++ ++ ++static void traversestack (global_State *g, lua_State *l) { ++ StkId o, lim; ++ CallInfo *ci; ++ markvalue(g, gt(l)); ++ lim = l->top; ++ for (ci = l->base_ci; ci <= l->ci; ci++) { ++ lua_assert(ci->top <= l->stack_last); ++ if (lim < ci->top) lim = ci->top; ++ } ++ for (o = l->stack; o < l->top; o++) ++ markvalue(g, o); ++ for (; o <= lim; o++) ++ setnilvalue(o); ++ checkstacksizes(l, lim); ++} ++ ++ ++/* ++** traverse one gray object, turning it to black. ++** Returns `quantity' traversed. ++*/ ++static l_mem propagatemark (global_State *g) { ++ GCObject *o = g->gray; ++ lua_assert(isgray(o)); ++ gray2black(o); ++ switch (o->gch.tt) { ++ case LUA_TTABLE: { ++ Table *h = gco2h(o); ++ g->gray = h->gclist; ++ if (traversetable(g, h)) /* table is weak? */ ++ black2gray(o); /* keep it gray */ ++ return sizeof(Table) + sizeof(TValue) * h->sizearray + ++ sizeof(Node) * sizenode(h); ++ } ++ case LUA_TFUNCTION: { ++ Closure *cl = gco2cl(o); ++ g->gray = cl->c.gclist; ++ traverseclosure(g, cl); ++ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : ++ sizeLclosure(cl->l.nupvalues); ++ } ++ case LUA_TTHREAD: { ++ lua_State *th = gco2th(o); ++ g->gray = th->gclist; ++ th->gclist = g->grayagain; ++ g->grayagain = o; ++ black2gray(o); ++ traversestack(g, th); ++ return sizeof(lua_State) + sizeof(TValue) * th->stacksize + ++ sizeof(CallInfo) * th->size_ci; ++ } ++ case LUA_TPROTO: { ++ Proto *p = gco2p(o); ++ g->gray = p->gclist; ++ traverseproto(g, p); ++ return sizeof(Proto) + sizeof(Instruction) * p->sizecode + ++ sizeof(Proto *) * p->sizep + ++ sizeof(TValue) * p->sizek + ++ sizeof(int) * p->sizelineinfo + ++ sizeof(LocVar) * p->sizelocvars + ++ sizeof(TString *) * p->sizeupvalues; ++ } ++ default: lua_assert(0); return 0; ++ } ++} ++ ++ ++static size_t propagateall (global_State *g) { ++ size_t m = 0; ++ while (g->gray) m += propagatemark(g); ++ return m; ++} ++ ++ ++/* ++** The next function tells whether a key or value can be cleared from ++** a weak table. Non-collectable objects are never removed from weak ++** tables. Strings behave as `values', so are never removed too. for ++** other objects: if really collected, cannot keep them; for userdata ++** being finalized, keep them in keys, but not in values ++*/ ++static int iscleared (const TValue *o, int iskey) { ++ if (!iscollectable(o)) return 0; ++ if (ttisstring(o)) { ++ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ ++ return 0; ++ } ++ return iswhite(gcvalue(o)) || ++ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); ++} ++ ++ ++/* ++** clear collected entries from weaktables ++*/ ++static void cleartable (GCObject *l) { ++ while (l) { ++ Table *h = gco2h(l); ++ int i = h->sizearray; ++ lua_assert(testbit(h->marked, VALUEWEAKBIT) || ++ testbit(h->marked, KEYWEAKBIT)); ++ if (testbit(h->marked, VALUEWEAKBIT)) { ++ while (i--) { ++ TValue *o = &h->array[i]; ++ if (iscleared(o, 0)) /* value was collected? */ ++ setnilvalue(o); /* remove value */ ++ } ++ } ++ i = sizenode(h); ++ while (i--) { ++ Node *n = gnode(h, i); ++ if (!ttisnil(gval(n)) && /* non-empty entry? */ ++ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { ++ setnilvalue(gval(n)); /* remove value ... */ ++ removeentry(n); /* remove entry from table */ ++ } ++ } ++ l = h->gclist; ++ } ++} ++ ++ ++static void freeobj (lua_State *L, GCObject *o) { ++ switch (o->gch.tt) { ++ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; ++ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; ++ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; ++ case LUA_TTABLE: luaH_free(L, gco2h(o)); break; ++ case LUA_TTHREAD: { ++ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); ++ luaE_freethread(L, gco2th(o)); ++ break; ++ } ++ case LUA_TSTRING: { ++ G(L)->strt.nuse--; ++ luaM_freemem(L, o, sizestring(gco2ts(o))); ++ break; ++ } ++ case LUA_TUSERDATA: { ++ luaM_freemem(L, o, sizeudata(gco2u(o))); ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++ ++#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) ++ ++ ++static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { ++ GCObject *curr; ++ global_State *g = G(L); ++ int deadmask = otherwhite(g); ++ while ((curr = *p) != NULL && count-- > 0) { ++ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ ++ sweepwholelist(L, &gco2th(curr)->openupval); ++ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ ++ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); ++ makewhite(g, curr); /* make it white (for next cycle) */ ++ p = &curr->gch.next; ++ } ++ else { /* must erase `curr' */ ++ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); ++ *p = curr->gch.next; ++ if (curr == g->rootgc) /* is the first element of the list? */ ++ g->rootgc = curr->gch.next; /* adjust first */ ++ freeobj(L, curr); ++ } ++ } ++ return p; ++} ++ ++ ++static void checkSizes (lua_State *L) { ++ global_State *g = G(L); ++ /* check size of string hash */ ++ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && ++ g->strt.size > MINSTRTABSIZE*2) ++ luaS_resize(L, g->strt.size/2); /* table is too big */ ++ /* check size of buffer */ ++ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ ++ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; ++ luaZ_resizebuffer(L, &g->buff, newsize); ++ } ++} ++ ++ ++static void GCTM (lua_State *L) { ++ global_State *g = G(L); ++ GCObject *o = g->tmudata->gch.next; /* get first element */ ++ Udata *udata = rawgco2u(o); ++ const TValue *tm; ++ /* remove udata from `tmudata' */ ++ if (o == g->tmudata) /* last element? */ ++ g->tmudata = NULL; ++ else ++ g->tmudata->gch.next = udata->uv.next; ++ udata->uv.next = g->mainthread->next; /* return it to `root' list */ ++ g->mainthread->next = o; ++ makewhite(g, o); ++ tm = fasttm(L, udata->uv.metatable, TM_GC); ++ if (tm != NULL) { ++ lu_byte oldah = L->allowhook; ++ lu_mem oldt = g->GCthreshold; ++ L->allowhook = 0; /* stop debug hooks during GC tag method */ ++ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ ++ setobj2s(L, L->top, tm); ++ setuvalue(L, L->top+1, udata); ++ L->top += 2; ++ luaD_call(L, L->top - 2, 0); ++ L->allowhook = oldah; /* restore hooks */ ++ g->GCthreshold = oldt; /* restore threshold */ ++ } ++} ++ ++ ++/* ++** Call all GC tag methods ++*/ ++void luaC_callGCTM (lua_State *L) { ++ while (G(L)->tmudata) ++ GCTM(L); ++} ++ ++ ++void luaC_freeall (lua_State *L) { ++ global_State *g = G(L); ++ int i; ++ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ ++ sweepwholelist(L, &g->rootgc); ++ for (i = 0; i < g->strt.size; i++) /* free all string lists */ ++ sweepwholelist(L, &g->strt.hash[i]); ++} ++ ++ ++static void markmt (global_State *g) { ++ int i; ++ for (i=0; imt[i]) markobject(g, g->mt[i]); ++} ++ ++ ++/* mark root set */ ++static void markroot (lua_State *L) { ++ global_State *g = G(L); ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ markobject(g, g->mainthread); ++ /* make global table be traversed before main stack */ ++ markvalue(g, gt(g->mainthread)); ++ markvalue(g, registry(L)); ++ markmt(g); ++ g->gcstate = GCSpropagate; ++} ++ ++ ++static void remarkupvals (global_State *g) { ++ UpVal *uv; ++ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ if (isgray(obj2gco(uv))) ++ markvalue(g, uv->v); ++ } ++} ++ ++ ++static void atomic (lua_State *L) { ++ global_State *g = G(L); ++ size_t udsize; /* total size of userdata to be finalized */ ++ /* remark occasional upvalues of (maybe) dead threads */ ++ remarkupvals(g); ++ /* traverse objects cautch by write barrier and by 'remarkupvals' */ ++ propagateall(g); ++ /* remark weak tables */ ++ g->gray = g->weak; ++ g->weak = NULL; ++ lua_assert(!iswhite(obj2gco(g->mainthread))); ++ markobject(g, L); /* mark running thread */ ++ markmt(g); /* mark basic metatables (again) */ ++ propagateall(g); ++ /* remark gray again */ ++ g->gray = g->grayagain; ++ g->grayagain = NULL; ++ propagateall(g); ++ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ ++ marktmu(g); /* mark `preserved' userdata */ ++ udsize += propagateall(g); /* remark, to propagate `preserveness' */ ++ cleartable(g->weak); /* remove collected objects from weak tables */ ++ /* flip current white */ ++ g->currentwhite = cast_byte(otherwhite(g)); ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ g->gcstate = GCSsweepstring; ++ g->estimate = g->totalbytes - udsize; /* first estimate */ ++} ++ ++ ++static l_mem singlestep (lua_State *L) { ++ global_State *g = G(L); ++ /*lua_checkmemory(L);*/ ++ switch (g->gcstate) { ++ case GCSpause: { ++ markroot(L); /* start a new collection */ ++ return 0; ++ } ++ case GCSpropagate: { ++ if (g->gray) ++ return propagatemark(g); ++ else { /* no more `gray' objects */ ++ atomic(L); /* finish mark phase */ ++ return 0; ++ } ++ } ++ case GCSsweepstring: { ++ lu_mem old = g->totalbytes; ++ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); ++ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ ++ g->gcstate = GCSsweep; /* end sweep-string phase */ ++ lua_assert(old >= g->totalbytes); ++ g->estimate -= old - g->totalbytes; ++ return GCSWEEPCOST; ++ } ++ case GCSsweep: { ++ lu_mem old = g->totalbytes; ++ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); ++ if (*g->sweepgc == NULL) { /* nothing more to sweep? */ ++ checkSizes(L); ++ g->gcstate = GCSfinalize; /* end sweep phase */ ++ } ++ lua_assert(old >= g->totalbytes); ++ g->estimate -= old - g->totalbytes; ++ return GCSWEEPMAX*GCSWEEPCOST; ++ } ++ case GCSfinalize: { ++ if (g->tmudata) { ++ GCTM(L); ++ if (g->estimate > GCFINALIZECOST) ++ g->estimate -= GCFINALIZECOST; ++ return GCFINALIZECOST; ++ } ++ else { ++ g->gcstate = GCSpause; /* end collection */ ++ g->gcdept = 0; ++ return 0; ++ } ++ } ++ default: lua_assert(0); return 0; ++ } ++} ++ ++ ++void luaC_step (lua_State *L) { ++ global_State *g = G(L); ++ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; ++ if (lim == 0) ++ lim = (MAX_LUMEM-1)/2; /* no limit */ ++ g->gcdept += g->totalbytes - g->GCthreshold; ++ do { ++ lim -= singlestep(L); ++ if (g->gcstate == GCSpause) ++ break; ++ } while (lim > 0); ++ if (g->gcstate != GCSpause) { ++ if (g->gcdept < GCSTEPSIZE) ++ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ ++ else { ++ g->gcdept -= GCSTEPSIZE; ++ g->GCthreshold = g->totalbytes; ++ } ++ } ++ else { ++ lua_assert(g->totalbytes >= g->estimate); ++ setthreshold(g); ++ } ++} ++ ++ ++void luaC_fullgc (lua_State *L) { ++ global_State *g = G(L); ++ if (g->gcstate <= GCSpropagate) { ++ /* reset sweep marks to sweep all elements (returning them to white) */ ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ /* reset other collector lists */ ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ g->gcstate = GCSsweepstring; ++ } ++ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); ++ /* finish any pending sweep phase */ ++ while (g->gcstate != GCSfinalize) { ++ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); ++ singlestep(L); ++ } ++ markroot(L); ++ while (g->gcstate != GCSpause) { ++ singlestep(L); ++ } ++ setthreshold(g); ++} ++ ++ ++void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { ++ global_State *g = G(L); ++ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ lua_assert(ttype(&o->gch) != LUA_TTABLE); ++ /* must keep invariant? */ ++ if (g->gcstate == GCSpropagate) ++ reallymarkobject(g, v); /* restore invariant */ ++ else /* don't mind */ ++ makewhite(g, o); /* mark as white just to avoid other barriers */ ++} ++ ++ ++void luaC_barrierback (lua_State *L, Table *t) { ++ global_State *g = G(L); ++ GCObject *o = obj2gco(t); ++ lua_assert(isblack(o) && !isdead(g, o)); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ black2gray(o); /* make table gray (again) */ ++ t->gclist = g->grayagain; ++ g->grayagain = o; ++} ++ ++ ++void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { ++ global_State *g = G(L); ++ o->gch.next = g->rootgc; ++ g->rootgc = o; ++ o->gch.marked = luaC_white(g); ++ o->gch.tt = tt; ++} ++ ++ ++void luaC_linkupval (lua_State *L, UpVal *uv) { ++ global_State *g = G(L); ++ GCObject *o = obj2gco(uv); ++ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ ++ g->rootgc = o; ++ if (isgray(o)) { ++ if (g->gcstate == GCSpropagate) { ++ gray2black(o); /* closed upvalues need barrier */ ++ luaC_barrier(L, uv, uv->v); ++ } ++ else { /* sweep phase: sweep it (turning it into white) */ ++ makewhite(g, o); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ } ++ } ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lgc.h +@@ -0,0 +1,110 @@ ++/* ++** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Garbage Collector ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lgc_h ++#define lgc_h ++ ++ ++#include "lobject.h" ++ ++ ++/* ++** Possible states of the Garbage Collector ++*/ ++#define GCSpause 0 ++#define GCSpropagate 1 ++#define GCSsweepstring 2 ++#define GCSsweep 3 ++#define GCSfinalize 4 ++ ++ ++/* ++** some userful bit tricks ++*/ ++#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) ++#define setbits(x,m) ((x) |= (m)) ++#define testbits(x,m) ((x) & (m)) ++#define bitmask(b) (1<<(b)) ++#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) ++#define l_setbit(x,b) setbits(x, bitmask(b)) ++#define resetbit(x,b) resetbits(x, bitmask(b)) ++#define testbit(x,b) testbits(x, bitmask(b)) ++#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) ++#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) ++#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) ++ ++ ++ ++/* ++** Layout for bit use in `marked' field: ++** bit 0 - object is white (type 0) ++** bit 1 - object is white (type 1) ++** bit 2 - object is black ++** bit 3 - for userdata: has been finalized ++** bit 3 - for tables: has weak keys ++** bit 4 - for tables: has weak values ++** bit 5 - object is fixed (should not be collected) ++** bit 6 - object is "super" fixed (only the main thread) ++*/ ++ ++ ++#define WHITE0BIT 0 ++#define WHITE1BIT 1 ++#define BLACKBIT 2 ++#define FINALIZEDBIT 3 ++#define KEYWEAKBIT 3 ++#define VALUEWEAKBIT 4 ++#define FIXEDBIT 5 ++#define SFIXEDBIT 6 ++#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) ++ ++ ++#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) ++#define isblack(x) testbit((x)->gch.marked, BLACKBIT) ++#define isgray(x) (!isblack(x) && !iswhite(x)) ++ ++#define otherwhite(g) (g->currentwhite ^ WHITEBITS) ++#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) ++ ++#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) ++#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) ++ ++#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) ++ ++#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) ++ ++ ++#define luaC_checkGC(L) { \ ++ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ ++ if (G(L)->totalbytes >= G(L)->GCthreshold) \ ++ luaC_step(L); } ++ ++ ++#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ ++ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } ++ ++#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ ++ luaC_barrierback(L,t); } ++ ++#define luaC_objbarrier(L,p,o) \ ++ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ ++ luaC_barrierf(L,obj2gco(p),obj2gco(o)); } ++ ++#define luaC_objbarriert(L,t,o) \ ++ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } ++ ++LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); ++LUAI_FUNC void luaC_callGCTM (lua_State *L); ++LUAI_FUNC void luaC_freeall (lua_State *L); ++LUAI_FUNC void luaC_step (lua_State *L); ++LUAI_FUNC void luaC_fullgc (lua_State *L); ++LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); ++LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); ++LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); ++LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/llex.c +@@ -0,0 +1,460 @@ ++/* ++** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lexical Analyzer ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++ ++#define llex_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldo.h" ++#include "llex.h" ++#include "lobject.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "lzio.h" ++ ++ ++ ++#define next(ls) (ls->current = zgetc(ls->z)) ++ ++ ++ ++ ++#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') ++ ++ ++/* ORDER RESERVED */ ++const char *const luaX_tokens [] = { ++ "and", "break", "do", "else", "elseif", ++ "end", "false", "for", "function", "if", ++ "in", "local", "nil", "not", "or", "repeat", ++ "return", "then", "true", "until", "while", ++ "..", "...", "==", ">=", "<=", "~=", ++ "", "", "", "", ++ NULL ++}; ++ ++ ++#define save_and_next(ls) (save(ls, ls->current), next(ls)) ++ ++ ++static void save (LexState *ls, int c) { ++ Mbuffer *b = ls->buff; ++ if (b->n + 1 > b->buffsize) { ++ size_t newsize; ++ if (b->buffsize >= MAX_SIZET/2) ++ luaX_lexerror(ls, "lexical element too long", 0); ++ newsize = b->buffsize * 2; ++ luaZ_resizebuffer(ls->L, b, newsize); ++ } ++ b->buffer[b->n++] = cast(char, c); ++} ++ ++ ++void luaX_init (lua_State *L) { ++ int i; ++ for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ ++ } ++} ++ ++ ++#define MAXSRC 80 ++ ++ ++const char *luaX_token2str (LexState *ls, int token) { ++ if (token < FIRST_RESERVED) { ++ lua_assert(token == cast(unsigned char, token)); ++ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : ++ luaO_pushfstring(ls->L, "%c", token); ++ } ++ else ++ return luaX_tokens[token-FIRST_RESERVED]; ++} ++ ++ ++static const char *txtToken (LexState *ls, int token) { ++ switch (token) { ++ case TK_NAME: ++ case TK_STRING: ++ case TK_NUMBER: ++ save(ls, '\0'); ++ return luaZ_buffer(ls->buff); ++ default: ++ return luaX_token2str(ls, token); ++ } ++} ++ ++ ++void luaX_lexerror (LexState *ls, const char *msg, int token) { ++ char buff[MAXSRC]; ++ luaO_chunkid(buff, getstr(ls->source), MAXSRC); ++ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); ++ if (token) ++ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); ++ luaD_throw(ls->L, LUA_ERRSYNTAX); ++} ++ ++ ++void luaX_syntaxerror (LexState *ls, const char *msg) { ++ luaX_lexerror(ls, msg, ls->t.token); ++} ++ ++ ++TString *luaX_newstring (LexState *ls, const char *str, size_t l) { ++ lua_State *L = ls->L; ++ TString *ts = luaS_newlstr(L, str, l); ++ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ ++ if (ttisnil(o)) ++ setbvalue(o, 1); /* make sure `str' will not be collected */ ++ return ts; ++} ++ ++ ++static void inclinenumber (LexState *ls) { ++ int old = ls->current; ++ lua_assert(currIsNewline(ls)); ++ next(ls); /* skip `\n' or `\r' */ ++ if (currIsNewline(ls) && ls->current != old) ++ next(ls); /* skip `\n\r' or `\r\n' */ ++ if (++ls->linenumber >= MAX_INT) ++ luaX_syntaxerror(ls, "chunk has too many lines"); ++} ++ ++ ++void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { ++ ls->decpoint = '.'; ++ ls->L = L; ++ ls->lookahead.token = TK_EOS; /* no look-ahead token */ ++ ls->z = z; ++ ls->fs = NULL; ++ ls->linenumber = 1; ++ ls->lastline = 1; ++ ls->source = source; ++ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ ++ next(ls); /* read first char */ ++} ++ ++ ++ ++/* ++** ======================================================= ++** LEXICAL ANALYZER ++** ======================================================= ++*/ ++ ++ ++ ++static int check_next (LexState *ls, const char *set) { ++ if (!strchr(set, ls->current)) ++ return 0; ++ save_and_next(ls); ++ return 1; ++} ++ ++ ++static void buffreplace (LexState *ls, char from, char to) { ++ size_t n = luaZ_bufflen(ls->buff); ++ char *p = luaZ_buffer(ls->buff); ++ while (n--) ++ if (p[n] == from) p[n] = to; ++} ++ ++ ++static void trydecpoint (LexState *ls, SemInfo *seminfo) { ++ /* format error: try to update decimal point separator */ ++ char old = ls->decpoint; ++ struct lconv *cv = localeconv(); ++ ls->decpoint = (cv ? cv->decimal_point[0] : '.'); ++ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ ++ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { ++ /* format error with correct decimal point: no more options */ ++ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ ++ luaX_lexerror(ls, "malformed number", TK_NUMBER); ++ } ++} ++ ++ ++/* LUA_NUMBER */ ++static void read_numeral (LexState *ls, SemInfo *seminfo) { ++ lua_assert(isdigit(ls->current)); ++ do { ++ save_and_next(ls); ++ } while (isdigit(ls->current) || ls->current == '.'); ++ if (check_next(ls, "Ee")) /* `E'? */ ++ check_next(ls, "+-"); /* optional exponent sign */ ++ while (isalnum(ls->current) || ls->current == '_') ++ save_and_next(ls); ++ save(ls, '\0'); ++ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ ++ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ ++ trydecpoint(ls, seminfo); /* try to update decimal point separator */ ++} ++ ++ ++static int skip_sep (LexState *ls) { ++ int count = 0; ++ int s = ls->current; ++ lua_assert(s == '[' || s == ']'); ++ save_and_next(ls); ++ while (ls->current == '=') { ++ save_and_next(ls); ++ count++; ++ } ++ return (ls->current == s) ? count : (-count) - 1; ++} ++ ++ ++static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { ++ int cont = 0; ++ (void)(cont); /* avoid warnings when `cont' is not used */ ++ save_and_next(ls); /* skip 2nd `[' */ ++ if (currIsNewline(ls)) /* string starts with a newline? */ ++ inclinenumber(ls); /* skip it */ ++ for (;;) { ++ switch (ls->current) { ++ case EOZ: ++ luaX_lexerror(ls, (seminfo) ? "unfinished long string" : ++ "unfinished long comment", TK_EOS); ++ break; /* to avoid warnings */ ++#if defined(LUA_COMPAT_LSTR) ++ case '[': { ++ if (skip_sep(ls) == sep) { ++ save_and_next(ls); /* skip 2nd `[' */ ++ cont++; ++#if LUA_COMPAT_LSTR == 1 ++ if (sep == 0) ++ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); ++#endif ++ } ++ break; ++ } ++#endif ++ case ']': { ++ if (skip_sep(ls) == sep) { ++ save_and_next(ls); /* skip 2nd `]' */ ++#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 ++ cont--; ++ if (sep == 0 && cont >= 0) break; ++#endif ++ goto endloop; ++ } ++ break; ++ } ++ case '\n': ++ case '\r': { ++ save(ls, '\n'); ++ inclinenumber(ls); ++ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ ++ break; ++ } ++ default: { ++ if (seminfo) save_and_next(ls); ++ else next(ls); ++ } ++ } ++ } endloop: ++ if (seminfo) ++ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), ++ luaZ_bufflen(ls->buff) - 2*(2 + sep)); ++} ++ ++ ++static void read_string (LexState *ls, int del, SemInfo *seminfo) { ++ save_and_next(ls); ++ while (ls->current != del) { ++ switch (ls->current) { ++ case EOZ: ++ luaX_lexerror(ls, "unfinished string", TK_EOS); ++ continue; /* to avoid warnings */ ++ case '\n': ++ case '\r': ++ luaX_lexerror(ls, "unfinished string", TK_STRING); ++ continue; /* to avoid warnings */ ++ case '\\': { ++ int c; ++ next(ls); /* do not save the `\' */ ++ switch (ls->current) { ++ case 'a': c = '\a'; break; ++ case 'b': c = '\b'; break; ++ case 'f': c = '\f'; break; ++ case 'n': c = '\n'; break; ++ case 'r': c = '\r'; break; ++ case 't': c = '\t'; break; ++ case 'v': c = '\v'; break; ++ case '\n': /* go through */ ++ case '\r': save(ls, '\n'); inclinenumber(ls); continue; ++ case EOZ: continue; /* will raise an error next loop */ ++ default: { ++ if (!isdigit(ls->current)) ++ save_and_next(ls); /* handles \\, \", \', and \? */ ++ else { /* \xxx */ ++ int i = 0; ++ c = 0; ++ do { ++ c = 10*c + (ls->current-'0'); ++ next(ls); ++ } while (++i<3 && isdigit(ls->current)); ++ if (c > UCHAR_MAX) ++ luaX_lexerror(ls, "escape sequence too large", TK_STRING); ++ save(ls, c); ++ } ++ continue; ++ } ++ } ++ save(ls, c); ++ next(ls); ++ continue; ++ } ++ default: ++ save_and_next(ls); ++ } ++ } ++ save_and_next(ls); /* skip delimiter */ ++ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, ++ luaZ_bufflen(ls->buff) - 2); ++} ++ ++ ++static int llex (LexState *ls, SemInfo *seminfo) { ++ luaZ_resetbuffer(ls->buff); ++ for (;;) { ++ switch (ls->current) { ++ case '\n': ++ case '\r': { ++ inclinenumber(ls); ++ continue; ++ } ++ case '-': { ++ next(ls); ++ if (ls->current != '-') return '-'; ++ /* else is a comment */ ++ next(ls); ++ if (ls->current == '[') { ++ int sep = skip_sep(ls); ++ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ ++ if (sep >= 0) { ++ read_long_string(ls, NULL, sep); /* long comment */ ++ luaZ_resetbuffer(ls->buff); ++ continue; ++ } ++ } ++ /* else short comment */ ++ while (!currIsNewline(ls) && ls->current != EOZ) ++ next(ls); ++ continue; ++ } ++ case '[': { ++ int sep = skip_sep(ls); ++ if (sep >= 0) { ++ read_long_string(ls, seminfo, sep); ++ return TK_STRING; ++ } ++ else if (sep == -1) return '['; ++ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); ++ } ++ case '=': { ++ next(ls); ++ if (ls->current != '=') return '='; ++ else { next(ls); return TK_EQ; } ++ } ++ case '<': { ++ next(ls); ++ if (ls->current != '=') return '<'; ++ else { next(ls); return TK_LE; } ++ } ++ case '>': { ++ next(ls); ++ if (ls->current != '=') return '>'; ++ else { next(ls); return TK_GE; } ++ } ++ case '~': { ++ next(ls); ++ if (ls->current != '=') return '~'; ++ else { next(ls); return TK_NE; } ++ } ++ case '"': ++ case '\'': { ++ read_string(ls, ls->current, seminfo); ++ return TK_STRING; ++ } ++ case '.': { ++ save_and_next(ls); ++ if (check_next(ls, ".")) { ++ if (check_next(ls, ".")) ++ return TK_DOTS; /* ... */ ++ else return TK_CONCAT; /* .. */ ++ } ++ else if (!isdigit(ls->current)) return '.'; ++ else { ++ read_numeral(ls, seminfo); ++ return TK_NUMBER; ++ } ++ } ++ case EOZ: { ++ return TK_EOS; ++ } ++ default: { ++ if (isspace(ls->current)) { ++ lua_assert(!currIsNewline(ls)); ++ next(ls); ++ continue; ++ } ++ else if (isdigit(ls->current)) { ++ read_numeral(ls, seminfo); ++ return TK_NUMBER; ++ } ++ else if (isalpha(ls->current) || ls->current == '_') { ++ /* identifier or reserved word */ ++ TString *ts; ++ do { ++ save_and_next(ls); ++ } while (isalnum(ls->current) || ls->current == '_'); ++ ts = luaX_newstring(ls, luaZ_buffer(ls->buff), ++ luaZ_bufflen(ls->buff)); ++ if (ts->tsv.reserved > 0) /* reserved word? */ ++ return ts->tsv.reserved - 1 + FIRST_RESERVED; ++ else { ++ seminfo->ts = ts; ++ return TK_NAME; ++ } ++ } ++ else { ++ int c = ls->current; ++ next(ls); ++ return c; /* single-char tokens (+ - / ...) */ ++ } ++ } ++ } ++ } ++} ++ ++ ++void luaX_next (LexState *ls) { ++ ls->lastline = ls->linenumber; ++ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ ++ ls->t = ls->lookahead; /* use this one */ ++ ls->lookahead.token = TK_EOS; /* and discharge it */ ++ } ++ else ++ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ ++} ++ ++ ++void luaX_lookahead (LexState *ls) { ++ lua_assert(ls->lookahead.token == TK_EOS); ++ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/llex.h +@@ -0,0 +1,81 @@ ++/* ++** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lexical Analyzer ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef llex_h ++#define llex_h ++ ++#include "lobject.h" ++#include "lzio.h" ++ ++ ++#define FIRST_RESERVED 257 ++ ++/* maximum length of a reserved word */ ++#define TOKEN_LEN (sizeof("function")/sizeof(char)) ++ ++ ++/* ++* WARNING: if you change the order of this enumeration, ++* grep "ORDER RESERVED" ++*/ ++enum RESERVED { ++ /* terminal symbols denoted by reserved words */ ++ TK_AND = FIRST_RESERVED, TK_BREAK, ++ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, ++ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, ++ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, ++ /* other terminal symbols */ ++ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, ++ TK_NAME, TK_STRING, TK_EOS ++}; ++ ++/* number of reserved words */ ++#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) ++ ++ ++/* array with token `names' */ ++LUAI_DATA const char *const luaX_tokens []; ++ ++ ++typedef union { ++ lua_Number r; ++ TString *ts; ++} SemInfo; /* semantics information */ ++ ++ ++typedef struct Token { ++ int token; ++ SemInfo seminfo; ++} Token; ++ ++ ++typedef struct LexState { ++ int current; /* current character (charint) */ ++ int linenumber; /* input line counter */ ++ int lastline; /* line of last token `consumed' */ ++ Token t; /* current token */ ++ Token lookahead; /* look ahead token */ ++ struct FuncState *fs; /* `FuncState' is private to the parser */ ++ struct lua_State *L; ++ ZIO *z; /* input stream */ ++ Mbuffer *buff; /* buffer for tokens */ ++ TString *source; /* current source name */ ++ char decpoint; /* locale decimal point */ ++} LexState; ++ ++ ++LUAI_FUNC void luaX_init (lua_State *L); ++LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, ++ TString *source); ++LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); ++LUAI_FUNC void luaX_next (LexState *ls); ++LUAI_FUNC void luaX_lookahead (LexState *ls); ++LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); ++LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); ++LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/llimits.h +@@ -0,0 +1,125 @@ ++/* ++** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Limits, basic types, and some other `installation-dependent' definitions ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef llimits_h ++#define llimits_h ++ ++#include ++#include ++ ++#include "lua.h" ++ ++typedef LUAI_UINT32 lu_int32; ++ ++typedef LUAI_UMEM lu_mem; ++ ++typedef LUAI_MEM l_mem; ++ ++ ++ ++/* chars used as small naturals (so that `char' is reserved for characters) */ ++typedef unsigned char lu_byte; ++ ++ ++#define MAX_SIZET ((size_t)(~(size_t)0)-2) ++ ++#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) ++ ++ ++#define MAX_INT (LUA_INT_MAX-2) /* maximum value of an int (-2 for safety) */ ++ ++/* ++** conversion of pointer to integer ++** this is for hashing only; there is no problem if the integer ++** cannot hold the whole pointer value ++*/ ++#define IntPoint(p) ((unsigned int)(lu_mem)(p)) ++ ++ ++ ++/* type to ensure maximum alignment */ ++typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; ++ ++ ++/* result of a `usual argument conversion' over lua_Number */ ++typedef LUAI_UACNUMBER l_uacNumber; ++ ++ ++/* internal assertions for in-house debugging */ ++#ifdef lua_assert ++ ++#define check_exp(c,e) (lua_assert(c), (e)) ++#define api_check(l,e) lua_assert(e) ++ ++#else ++ ++#define lua_assert(c) ((void)0) ++#define check_exp(c,e) (e) ++#define api_check luai_apicheck ++ ++#endif ++ ++ ++#ifndef UNUSED ++#define UNUSED(x) ((void)(x)) /* to avoid warnings */ ++#endif ++ ++ ++#ifndef cast ++#define cast(t, exp) ((t)(exp)) ++#endif ++ ++#define cast_byte(i) cast(lu_byte, (i)) ++#define cast_num(i) cast(lua_Number, (i)) ++#define cast_int(i) cast(int, (i)) ++ ++ ++ ++/* ++** type for virtual-machine instructions ++** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) ++*/ ++typedef lu_int32 Instruction; ++ ++ ++ ++/* maximum stack for a Lua function */ ++#define MAXSTACK 250 ++ ++ ++ ++/* minimum size for the string table (must be power of 2) */ ++#ifndef MINSTRTABSIZE ++#define MINSTRTABSIZE 32 ++#endif ++ ++ ++/* minimum size for string buffer */ ++#ifndef LUA_MINBUFFER ++#define LUA_MINBUFFER 32 ++#endif ++ ++ ++#ifndef lua_lock ++#define lua_lock(L) ((void) 0) ++#define lua_unlock(L) ((void) 0) ++#endif ++ ++#ifndef luai_threadyield ++#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} ++#endif ++ ++ ++/* ++** macro to control inclusion of some hard tests on stack reallocation ++*/ ++#ifndef HARDSTACKTESTS ++#define condhardstacktests(x) ((void)0) ++#else ++#define condhardstacktests(x) x ++#endif ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lmem.c +@@ -0,0 +1,86 @@ ++/* ++** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Interface to Memory Manager ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lmem_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++ ++/* ++** About the realloc function: ++** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ++** (`osize' is the old size, `nsize' is the new size) ++** ++** Lua ensures that (ptr == NULL) iff (osize == 0). ++** ++** * frealloc(ud, NULL, 0, x) creates a new block of size `x' ++** ++** * frealloc(ud, p, x, 0) frees the block `p' ++** (in this specific case, frealloc must return NULL). ++** particularly, frealloc(ud, NULL, 0, 0) does nothing ++** (which is equivalent to free(NULL) in ANSI C) ++** ++** frealloc returns NULL if it cannot create or reallocate the area ++** (any reallocation to an equal or smaller size cannot fail!) ++*/ ++ ++ ++ ++#define MINSIZEARRAY 4 ++ ++ ++void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, ++ int limit, const char *errormsg) { ++ void *newblock; ++ int newsize; ++ if (*size >= limit/2) { /* cannot double it? */ ++ if (*size >= limit) /* cannot grow even a little? */ ++ luaG_runerror(L, errormsg); ++ newsize = limit; /* still have at least one free place */ ++ } ++ else { ++ newsize = (*size)*2; ++ if (newsize < MINSIZEARRAY) ++ newsize = MINSIZEARRAY; /* minimum size */ ++ } ++ newblock = luaM_reallocv(L, block, *size, newsize, size_elems); ++ *size = newsize; /* update only when everything else is OK */ ++ return newblock; ++} ++ ++ ++void *luaM_toobig (lua_State *L) { ++ luaG_runerror(L, "memory allocation error: block too big"); ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++ ++/* ++** generic allocation routine. ++*/ ++void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { ++ global_State *g = G(L); ++ lua_assert((osize == 0) == (block == NULL)); ++ block = (*g->frealloc)(g->ud, block, osize, nsize); ++ if (block == NULL && nsize > 0) ++ luaD_throw(L, LUA_ERRMEM); ++ lua_assert((nsize == 0) == (block == NULL)); ++ g->totalbytes = (g->totalbytes - osize) + nsize; ++ return block; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lmem.h +@@ -0,0 +1,49 @@ ++/* ++** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Interface to Memory Manager ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lmem_h ++#define lmem_h ++ ++ ++#include ++ ++#include "llimits.h" ++#include "lua.h" ++ ++#define MEMERRMSG "not enough memory" ++ ++ ++#define luaM_reallocv(L,b,on,n,e) \ ++ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ ++ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ ++ luaM_toobig(L)) ++ ++#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) ++#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) ++#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) ++ ++#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) ++#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) ++#define luaM_newvector(L,n,t) \ ++ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) ++ ++#define luaM_growvector(L,v,nelems,size,t,limit,e) \ ++ if ((nelems)+1 > (size)) \ ++ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) ++ ++#define luaM_reallocvector(L, v,oldn,n,t) \ ++ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) ++ ++ ++LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, ++ size_t size); ++LUAI_FUNC void *luaM_toobig (lua_State *L); ++LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, ++ size_t size_elem, int limit, ++ const char *errormsg); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lobject.c +@@ -0,0 +1,215 @@ ++/* ++** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Some generic functions over Lua objects ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define lobject_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldo.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "lvm.h" ++ ++ ++ ++const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; ++ ++ ++/* ++** converts an integer to a "floating point byte", represented as ++** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if ++** eeeee != 0 and (xxx) otherwise. ++*/ ++int luaO_int2fb (unsigned int x) { ++ int e = 0; /* expoent */ ++ while (x >= 16) { ++ x = (x+1) >> 1; ++ e++; ++ } ++ if (x < 8) return x; ++ else return ((e+1) << 3) | (cast_int(x) - 8); ++} ++ ++ ++/* converts back */ ++int luaO_fb2int (int x) { ++ int e = (x >> 3) & 31; ++ if (e == 0) return x; ++ else return ((x & 7)+8) << (e - 1); ++} ++ ++ ++int luaO_log2 (unsigned int x) { ++ static const lu_byte log_2[256] = { ++ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, ++ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 ++ }; ++ int l = -1; ++ while (x >= 256) { l += 8; x >>= 8; } ++ return l + log_2[x]; ++ ++} ++ ++ ++int luaO_rawequalObj (const TValue *t1, const TValue *t2) { ++ if (ttype(t1) != ttype(t2)) return 0; ++ else switch (ttype(t1)) { ++ case LUA_TNIL: ++ return 1; ++ case LUA_TNUMBER: ++ return luai_numeq(nvalue(t1), nvalue(t2)); ++ case LUA_TBOOLEAN: ++ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: ++ return pvalue(t1) == pvalue(t2); ++ default: ++ lua_assert(iscollectable(t1)); ++ return gcvalue(t1) == gcvalue(t2); ++ } ++} ++ ++ ++int luaO_str2d (const char *s, lua_Number *result) { ++ char *endptr; ++ *result = lua_str2number(s, &endptr); ++ if (endptr == s) return 0; /* conversion failed */ ++ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ ++ *result = cast_num(strtoul(s, &endptr, 16)); ++ if (*endptr == '\0') return 1; /* most common case */ ++ while (isspace(cast(unsigned char, *endptr))) endptr++; ++ if (*endptr != '\0') return 0; /* invalid trailing characters? */ ++ return 1; ++} ++ ++ ++ ++static void pushstr (lua_State *L, const char *str) { ++ setsvalue2s(L, L->top, luaS_new(L, str)); ++ incr_top(L); ++} ++ ++ ++/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ ++const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { ++ int n = 1; ++ pushstr(L, ""); ++ for (;;) { ++ const char *e = strchr(fmt, '%'); ++ if (e == NULL) break; ++ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); ++ incr_top(L); ++ switch (*(e+1)) { ++ case 's': { ++ const char *s = va_arg(argp, char *); ++ if (s == NULL) s = "(null)"; ++ pushstr(L, s); ++ break; ++ } ++ case 'c': { ++ char buff[2]; ++ buff[0] = cast(char, va_arg(argp, int)); ++ buff[1] = '\0'; ++ pushstr(L, buff); ++ break; ++ } ++ case 'd': { ++ setnvalue(L->top, cast_num(va_arg(argp, int))); ++ incr_top(L); ++ break; ++ } ++ case 'f': { ++ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); ++ incr_top(L); ++ break; ++ } ++ case 'p': { ++ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ ++ sprintf(buff, "%p", va_arg(argp, void *)); ++ pushstr(L, buff); ++ break; ++ } ++ case '%': { ++ pushstr(L, "%"); ++ break; ++ } ++ default: { ++ char buff[3]; ++ buff[0] = '%'; ++ buff[1] = *(e+1); ++ buff[2] = '\0'; ++ pushstr(L, buff); ++ break; ++ } ++ } ++ n += 2; ++ fmt = e+2; ++ } ++ pushstr(L, fmt); ++ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); ++ L->top -= n; ++ return svalue(L->top - 1); ++} ++ ++ ++const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { ++ const char *msg; ++ va_list argp; ++ va_start(argp, fmt); ++ msg = luaO_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ return msg; ++} ++ ++ ++void luaO_chunkid (char *out, const char *source, size_t bufflen) { ++ if (*source == '=') { ++ strncpy(out, source+1, bufflen); /* remove first char */ ++ out[bufflen-1] = '\0'; /* ensures null termination */ ++ } ++ else { /* out = "source", or "...source" */ ++ if (*source == '@') { ++ size_t l; ++ source++; /* skip the `@' */ ++ bufflen -= sizeof(" '...' "); ++ l = strlen(source); ++ strcpy(out, ""); ++ if (l > bufflen) { ++ source += (l-bufflen); /* get last part of file name */ ++ strcat(out, "..."); ++ } ++ strcat(out, source); ++ } ++ else { /* out = [string "string"] */ ++ size_t len = strcspn(source, "\n\r"); /* stop at first newline */ ++ bufflen -= sizeof(" [string \"...\"] "); ++ if (len > bufflen) len = bufflen; ++ strcpy(out, "[string \""); ++ if (source[len] != '\0') { /* must truncate? */ ++ strncat(out, source, len); ++ strcat(out, "..."); ++ } ++ else ++ strcat(out, source); ++ strcat(out, "\"]"); ++ } ++ } ++} +--- /dev/null ++++ b/extensions/LUA/lua/lobject.h +@@ -0,0 +1,381 @@ ++/* ++** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ ++** Type definitions for Lua objects ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lobject_h ++#define lobject_h ++ ++ ++#include ++ ++ ++#include "llimits.h" ++#include "lua.h" ++ ++ ++/* tags for values visible from Lua */ ++#define LAST_TAG LUA_TTHREAD ++ ++#define NUM_TAGS (LAST_TAG+1) ++ ++ ++/* ++** Extra tags for non-values ++*/ ++#define LUA_TPROTO (LAST_TAG+1) ++#define LUA_TUPVAL (LAST_TAG+2) ++#define LUA_TDEADKEY (LAST_TAG+3) ++ ++ ++/* ++** Union of all collectable objects ++*/ ++typedef union GCObject GCObject; ++ ++ ++/* ++** Common Header for all collectable objects (in macro form, to be ++** included in other objects) ++*/ ++#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked ++ ++ ++/* ++** Common header in struct form ++*/ ++typedef struct GCheader { ++ CommonHeader; ++} GCheader; ++ ++ ++ ++ ++/* ++** Union of all Lua values ++*/ ++typedef union { ++ GCObject *gc; ++ void *p; ++ lua_Number n; ++ int b; ++} Value; ++ ++ ++/* ++** Tagged Values ++*/ ++ ++#define TValuefields Value value; int tt ++ ++typedef struct lua_TValue { ++ TValuefields; ++} TValue; ++ ++ ++/* Macros to test type */ ++#define ttisnil(o) (ttype(o) == LUA_TNIL) ++#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) ++#define ttisstring(o) (ttype(o) == LUA_TSTRING) ++#define ttistable(o) (ttype(o) == LUA_TTABLE) ++#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) ++#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) ++#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) ++#define ttisthread(o) (ttype(o) == LUA_TTHREAD) ++#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) ++ ++/* Macros to access values */ ++#define ttype(o) ((o)->tt) ++#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) ++#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) ++#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) ++#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) ++#define tsvalue(o) (&rawtsvalue(o)->tsv) ++#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) ++#define uvalue(o) (&rawuvalue(o)->uv) ++#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) ++#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) ++#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) ++#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) ++ ++#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) ++ ++/* ++** for internal debug only ++*/ ++#define checkconsistency(obj) \ ++ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) ++ ++#define checkliveness(g,obj) \ ++ lua_assert(!iscollectable(obj) || \ ++ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) ++ ++ ++/* Macros to set values */ ++#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) ++ ++#define setnvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } ++ ++#define setpvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } ++ ++#define setbvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } ++ ++#define setsvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ ++ checkliveness(G(L),i_o); } ++ ++#define setuvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ ++ checkliveness(G(L),i_o); } ++ ++#define setthvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ ++ checkliveness(G(L),i_o); } ++ ++#define setclvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ ++ checkliveness(G(L),i_o); } ++ ++#define sethvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ ++ checkliveness(G(L),i_o); } ++ ++#define setptvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ ++ checkliveness(G(L),i_o); } ++ ++ ++ ++ ++#define setobj(L,obj1,obj2) \ ++ { const TValue *o2=(obj2); TValue *o1=(obj1); \ ++ o1->value = o2->value; o1->tt=o2->tt; \ ++ checkliveness(G(L),o1); } ++ ++ ++/* ++** different types of sets, according to destination ++*/ ++ ++/* from stack to (same) stack */ ++#define setobjs2s setobj ++/* to stack (not from same stack) */ ++#define setobj2s setobj ++#define setsvalue2s setsvalue ++#define sethvalue2s sethvalue ++#define setptvalue2s setptvalue ++/* from table to same table */ ++#define setobjt2t setobj ++/* to table */ ++#define setobj2t setobj ++/* to new object */ ++#define setobj2n setobj ++#define setsvalue2n setsvalue ++ ++#define setttype(obj, tt) (ttype(obj) = (tt)) ++ ++ ++#define iscollectable(o) (ttype(o) >= LUA_TSTRING) ++ ++ ++ ++typedef TValue *StkId; /* index to stack elements */ ++ ++ ++/* ++** String headers for string table ++*/ ++typedef union TString { ++ L_Umaxalign dummy; /* ensures maximum alignment for strings */ ++ struct { ++ CommonHeader; ++ lu_byte reserved; ++ unsigned int hash; ++ size_t len; ++ } tsv; ++} TString; ++ ++ ++#define getstr(ts) cast(const char *, (ts) + 1) ++#define svalue(o) getstr(rawtsvalue(o)) ++ ++ ++ ++typedef union Udata { ++ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ ++ struct { ++ CommonHeader; ++ struct Table *metatable; ++ struct Table *env; ++ size_t len; ++ } uv; ++} Udata; ++ ++ ++ ++ ++/* ++** Function Prototypes ++*/ ++typedef struct Proto { ++ CommonHeader; ++ TValue *k; /* constants used by the function */ ++ Instruction *code; ++ struct Proto **p; /* functions defined inside the function */ ++ int *lineinfo; /* map from opcodes to source lines */ ++ struct LocVar *locvars; /* information about local variables */ ++ TString **upvalues; /* upvalue names */ ++ TString *source; ++ int sizeupvalues; ++ int sizek; /* size of `k' */ ++ int sizecode; ++ int sizelineinfo; ++ int sizep; /* size of `p' */ ++ int sizelocvars; ++ int linedefined; ++ int lastlinedefined; ++ GCObject *gclist; ++ lu_byte nups; /* number of upvalues */ ++ lu_byte numparams; ++ lu_byte is_vararg; ++ lu_byte maxstacksize; ++} Proto; ++ ++ ++/* masks for new-style vararg */ ++#define VARARG_HASARG 1 ++#define VARARG_ISVARARG 2 ++#define VARARG_NEEDSARG 4 ++ ++ ++typedef struct LocVar { ++ TString *varname; ++ int startpc; /* first point where variable is active */ ++ int endpc; /* first point where variable is dead */ ++} LocVar; ++ ++ ++ ++/* ++** Upvalues ++*/ ++ ++typedef struct UpVal { ++ CommonHeader; ++ TValue *v; /* points to stack or to its own value */ ++ union { ++ TValue value; /* the value (when closed) */ ++ struct { /* double linked list (when open) */ ++ struct UpVal *prev; ++ struct UpVal *next; ++ } l; ++ } u; ++} UpVal; ++ ++ ++/* ++** Closures ++*/ ++ ++#define ClosureHeader \ ++ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ ++ struct Table *env ++ ++typedef struct CClosure { ++ ClosureHeader; ++ lua_CFunction f; ++ TValue upvalue[1]; ++} CClosure; ++ ++ ++typedef struct LClosure { ++ ClosureHeader; ++ struct Proto *p; ++ UpVal *upvals[1]; ++} LClosure; ++ ++ ++typedef union Closure { ++ CClosure c; ++ LClosure l; ++} Closure; ++ ++ ++#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) ++#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) ++ ++ ++/* ++** Tables ++*/ ++ ++typedef union TKey { ++ struct { ++ TValuefields; ++ struct Node *next; /* for chaining */ ++ } nk; ++ TValue tvk; ++} TKey; ++ ++ ++typedef struct Node { ++ TValue i_val; ++ TKey i_key; ++} Node; ++ ++ ++typedef struct Table { ++ CommonHeader; ++ lu_byte flags; /* 1<

    lsizenode)) ++ ++ ++#define luaO_nilobject (&luaO_nilobject_) ++ ++LUAI_DATA const TValue luaO_nilobject_; ++ ++#define ceillog2(x) (luaO_log2((x)-1) + 1) ++ ++LUAI_FUNC int luaO_log2 (unsigned int x); ++LUAI_FUNC int luaO_int2fb (unsigned int x); ++LUAI_FUNC int luaO_fb2int (int x); ++LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); ++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); ++LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, ++ va_list argp); ++LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); ++LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); ++ ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lopcodes.c +@@ -0,0 +1,102 @@ ++/* ++** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#define lopcodes_c ++#define LUA_CORE ++ ++ ++#include "lopcodes.h" ++ ++ ++/* ORDER OP */ ++ ++const char *const luaP_opnames[NUM_OPCODES+1] = { ++ "MOVE", ++ "LOADK", ++ "LOADBOOL", ++ "LOADNIL", ++ "GETUPVAL", ++ "GETGLOBAL", ++ "GETTABLE", ++ "SETGLOBAL", ++ "SETUPVAL", ++ "SETTABLE", ++ "NEWTABLE", ++ "SELF", ++ "ADD", ++ "SUB", ++ "MUL", ++ "DIV", ++ "MOD", ++ "POW", ++ "UNM", ++ "NOT", ++ "LEN", ++ "CONCAT", ++ "JMP", ++ "EQ", ++ "LT", ++ "LE", ++ "TEST", ++ "TESTSET", ++ "CALL", ++ "TAILCALL", ++ "RETURN", ++ "FORLOOP", ++ "FORPREP", ++ "TFORLOOP", ++ "SETLIST", ++ "CLOSE", ++ "CLOSURE", ++ "VARARG", ++ NULL ++}; ++ ++ ++#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) ++ ++const lu_byte luaP_opmodes[NUM_OPCODES] = { ++/* T A B C mode opcode */ ++ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ ++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ ++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ ++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ ++ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ ++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ++ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ ++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ ++ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ ++ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ ++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ ++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ ++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ ++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ ++ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ ++ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ ++ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ ++}; ++ +--- /dev/null ++++ b/extensions/LUA/lua/lopcodes.h +@@ -0,0 +1,268 @@ ++/* ++** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Opcodes for Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lopcodes_h ++#define lopcodes_h ++ ++#include "llimits.h" ++ ++ ++/*=========================================================================== ++ We assume that instructions are unsigned numbers. ++ All instructions have an opcode in the first 6 bits. ++ Instructions can have the following fields: ++ `A' : 8 bits ++ `B' : 9 bits ++ `C' : 9 bits ++ `Bx' : 18 bits (`B' and `C' together) ++ `sBx' : signed Bx ++ ++ A signed argument is represented in excess K; that is, the number ++ value is the unsigned value minus K. K is exactly the maximum value ++ for that argument (so that -max is represented by 0, and +max is ++ represented by 2*max), which is half the maximum for the corresponding ++ unsigned argument. ++===========================================================================*/ ++ ++ ++enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ ++ ++ ++/* ++** size and position of opcode arguments. ++*/ ++#define SIZE_C 9 ++#define SIZE_B 9 ++#define SIZE_Bx (SIZE_C + SIZE_B) ++#define SIZE_A 8 ++ ++#define SIZE_OP 6 ++ ++#define POS_OP 0 ++#define POS_A (POS_OP + SIZE_OP) ++#define POS_C (POS_A + SIZE_A) ++#define POS_B (POS_C + SIZE_C) ++#define POS_Bx POS_C ++ ++ ++/* ++** limits for opcode arguments. ++** we use (signed) int to manipulate most arguments, ++** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) ++*/ ++#if SIZE_Bx < LUAI_BITSINT-1 ++#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ ++#else ++#define MAXARG_Bx MAX_INT ++#define MAXARG_sBx MAX_INT ++#endif ++ ++ ++#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) ++#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ ++ ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) ++#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ ++ ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) ++#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ ++ ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) ++#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ ++ ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) ++#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ ++ ((cast(Instruction, b)< C) then pc++ */ ++OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ ++ ++OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ ++OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ ++OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ ++ ++OP_FORLOOP,/* A sBx R(A)+=R(A+2); ++ if R(A) =) R(A)*/ ++OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ ++ ++OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ ++} OpCode; ++ ++ ++#define NUM_OPCODES (cast(int, OP_VARARG) + 1) ++ ++ ++ ++/*=========================================================================== ++ Notes: ++ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, ++ and can be 0: OP_CALL then sets `top' to last_result+1, so ++ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. ++ ++ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and ++ set top (like in OP_CALL with C == 0). ++ ++ (*) In OP_RETURN, if (B == 0) then return up to `top' ++ ++ (*) In OP_SETLIST, if (B == 0) then B = `top'; ++ if (C == 0) then next `instruction' is real C ++ ++ (*) For comparisons, A specifies what condition the test should accept ++ (true or false). ++ ++ (*) All `skips' (pc++) assume that next instruction is a jump ++===========================================================================*/ ++ ++ ++/* ++** masks for instruction properties. The format is: ++** bits 0-1: op mode ++** bits 2-3: C arg mode ++** bits 4-5: B arg mode ++** bit 6: instruction set register A ++** bit 7: operator is a test ++*/ ++ ++enum OpArgMask { ++ OpArgN, /* argument is not used */ ++ OpArgU, /* argument is used */ ++ OpArgR, /* argument is a register or a jump offset */ ++ OpArgK /* argument is a constant or register/constant */ ++}; ++ ++LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; ++ ++#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) ++#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) ++#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) ++#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) ++#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) ++ ++ ++LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ ++ ++ ++/* number of list items to accumulate before a SETLIST instruction */ ++#define LFIELDS_PER_FLUSH 50 ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lparser.c +@@ -0,0 +1,1339 @@ ++/* ++** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Lua Parser ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lparser_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++ ++ ++ ++#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) ++ ++#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) ++ ++#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) ++ ++ ++/* ++** nodes for block list (list of active blocks) ++*/ ++typedef struct BlockCnt { ++ struct BlockCnt *previous; /* chain */ ++ int breaklist; /* list of jumps out of this loop */ ++ lu_byte nactvar; /* # active locals outside the breakable structure */ ++ lu_byte upval; /* true if some variable in the block is an upvalue */ ++ lu_byte isbreakable; /* true if `block' is a loop */ ++} BlockCnt; ++ ++ ++ ++/* ++** prototypes for recursive non-terminal functions ++*/ ++static void chunk (LexState *ls); ++static void expr (LexState *ls, expdesc *v); ++ ++ ++static void anchor_token (LexState *ls) { ++ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { ++ TString *ts = ls->t.seminfo.ts; ++ luaX_newstring(ls, getstr(ts), ts->tsv.len); ++ } ++} ++ ++ ++static void error_expected (LexState *ls, int token) { ++ luaX_syntaxerror(ls, ++ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); ++} ++ ++ ++static void errorlimit (FuncState *fs, int limit, const char *what) { ++ const char *msg = (fs->f->linedefined == 0) ? ++ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : ++ luaO_pushfstring(fs->L, "function at line %d has more than %d %s", ++ fs->f->linedefined, limit, what); ++ luaX_lexerror(fs->ls, msg, 0); ++} ++ ++ ++static int testnext (LexState *ls, int c) { ++ if (ls->t.token == c) { ++ luaX_next(ls); ++ return 1; ++ } ++ else return 0; ++} ++ ++ ++static void check (LexState *ls, int c) { ++ if (ls->t.token != c) ++ error_expected(ls, c); ++} ++ ++static void checknext (LexState *ls, int c) { ++ check(ls, c); ++ luaX_next(ls); ++} ++ ++ ++#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } ++ ++ ++ ++static void check_match (LexState *ls, int what, int who, int where) { ++ if (!testnext(ls, what)) { ++ if (where == ls->linenumber) ++ error_expected(ls, what); ++ else { ++ luaX_syntaxerror(ls, luaO_pushfstring(ls->L, ++ LUA_QS " expected (to close " LUA_QS " at line %d)", ++ luaX_token2str(ls, what), luaX_token2str(ls, who), where)); ++ } ++ } ++} ++ ++ ++static TString *str_checkname (LexState *ls) { ++ TString *ts; ++ check(ls, TK_NAME); ++ ts = ls->t.seminfo.ts; ++ luaX_next(ls); ++ return ts; ++} ++ ++ ++static void init_exp (expdesc *e, expkind k, int i) { ++ e->f = e->t = NO_JUMP; ++ e->k = k; ++ e->u.s.info = i; ++} ++ ++ ++static void codestring (LexState *ls, expdesc *e, TString *s) { ++ init_exp(e, VK, luaK_stringK(ls->fs, s)); ++} ++ ++ ++static void checkname(LexState *ls, expdesc *e) { ++ codestring(ls, e, str_checkname(ls)); ++} ++ ++ ++static int registerlocalvar (LexState *ls, TString *varname) { ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int oldsize = f->sizelocvars; ++ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, ++ LocVar, SHRT_MAX, "too many local variables"); ++ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; ++ f->locvars[fs->nlocvars].varname = varname; ++ luaC_objbarrier(ls->L, f, varname); ++ return fs->nlocvars++; ++} ++ ++ ++#define new_localvarliteral(ls,v,n) \ ++ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) ++ ++ ++static void new_localvar (LexState *ls, TString *name, int n) { ++ FuncState *fs = ls->fs; ++ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); ++ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); ++} ++ ++ ++static void adjustlocalvars (LexState *ls, int nvars) { ++ FuncState *fs = ls->fs; ++ fs->nactvar = cast_byte(fs->nactvar + nvars); ++ for (; nvars; nvars--) { ++ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; ++ } ++} ++ ++ ++static void removevars (LexState *ls, int tolevel) { ++ FuncState *fs = ls->fs; ++ while (fs->nactvar > tolevel) ++ getlocvar(fs, --fs->nactvar).endpc = fs->pc; ++} ++ ++ ++static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { ++ int i; ++ Proto *f = fs->f; ++ int oldsize = f->sizeupvalues; ++ for (i=0; inups; i++) { ++ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { ++ lua_assert(f->upvalues[i] == name); ++ return i; ++ } ++ } ++ /* new one */ ++ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); ++ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, ++ TString *, MAX_INT, ""); ++ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; ++ f->upvalues[f->nups] = name; ++ luaC_objbarrier(fs->L, f, name); ++ lua_assert(v->k == VLOCAL || v->k == VUPVAL); ++ fs->upvalues[f->nups].k = cast_byte(v->k); ++ fs->upvalues[f->nups].info = cast_byte(v->u.s.info); ++ return f->nups++; ++} ++ ++ ++static int searchvar (FuncState *fs, TString *n) { ++ int i; ++ for (i=fs->nactvar-1; i >= 0; i--) { ++ if (n == getlocvar(fs, i).varname) ++ return i; ++ } ++ return -1; /* not found */ ++} ++ ++ ++static void markupval (FuncState *fs, int level) { ++ BlockCnt *bl = fs->bl; ++ while (bl && bl->nactvar > level) bl = bl->previous; ++ if (bl) bl->upval = 1; ++} ++ ++ ++static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { ++ if (fs == NULL) { /* no more levels? */ ++ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ ++ return VGLOBAL; ++ } ++ else { ++ int v = searchvar(fs, n); /* look up at current level */ ++ if (v >= 0) { ++ init_exp(var, VLOCAL, v); ++ if (!base) ++ markupval(fs, v); /* local will be used as an upval */ ++ return VLOCAL; ++ } ++ else { /* not found at current level; try upper one */ ++ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) ++ return VGLOBAL; ++ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ ++ var->k = VUPVAL; /* upvalue in this level */ ++ return VUPVAL; ++ } ++ } ++} ++ ++ ++static void singlevar (LexState *ls, expdesc *var) { ++ TString *varname = str_checkname(ls); ++ FuncState *fs = ls->fs; ++ if (singlevaraux(fs, varname, var, 1) == VGLOBAL) ++ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ ++} ++ ++ ++static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { ++ FuncState *fs = ls->fs; ++ int extra = nvars - nexps; ++ if (hasmultret(e->k)) { ++ extra++; /* includes call itself */ ++ if (extra < 0) extra = 0; ++ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ ++ if (extra > 1) luaK_reserveregs(fs, extra-1); ++ } ++ else { ++ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ ++ if (extra > 0) { ++ int reg = fs->freereg; ++ luaK_reserveregs(fs, extra); ++ luaK_nil(fs, reg, extra); ++ } ++ } ++} ++ ++ ++static void enterlevel (LexState *ls) { ++ if (++ls->L->nCcalls > LUAI_MAXCCALLS) ++ luaX_lexerror(ls, "chunk has too many syntax levels", 0); ++} ++ ++ ++#define leavelevel(ls) ((ls)->L->nCcalls--) ++ ++ ++static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { ++ bl->breaklist = NO_JUMP; ++ bl->isbreakable = isbreakable; ++ bl->nactvar = fs->nactvar; ++ bl->upval = 0; ++ bl->previous = fs->bl; ++ fs->bl = bl; ++ lua_assert(fs->freereg == fs->nactvar); ++} ++ ++ ++static void leaveblock (FuncState *fs) { ++ BlockCnt *bl = fs->bl; ++ fs->bl = bl->previous; ++ removevars(fs->ls, bl->nactvar); ++ if (bl->upval) ++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); ++ /* a block either controls scope or breaks (never both) */ ++ lua_assert(!bl->isbreakable || !bl->upval); ++ lua_assert(bl->nactvar == fs->nactvar); ++ fs->freereg = fs->nactvar; /* free registers */ ++ luaK_patchtohere(fs, bl->breaklist); ++} ++ ++ ++static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int oldsize = f->sizep; ++ int i; ++ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, ++ MAXARG_Bx, "constant table overflow"); ++ while (oldsize < f->sizep) f->p[oldsize++] = NULL; ++ f->p[fs->np++] = func->f; ++ luaC_objbarrier(ls->L, f, func->f); ++ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); ++ for (i=0; if->nups; i++) { ++ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; ++ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); ++ } ++} ++ ++ ++static void open_func (LexState *ls, FuncState *fs) { ++ lua_State *L = ls->L; ++ Proto *f = luaF_newproto(L); ++ fs->f = f; ++ fs->prev = ls->fs; /* linked list of funcstates */ ++ fs->ls = ls; ++ fs->L = L; ++ ls->fs = fs; ++ fs->pc = 0; ++ fs->lasttarget = -1; ++ fs->jpc = NO_JUMP; ++ fs->freereg = 0; ++ fs->nk = 0; ++ fs->np = 0; ++ fs->nlocvars = 0; ++ fs->nactvar = 0; ++ fs->bl = NULL; ++ f->source = ls->source; ++ f->maxstacksize = 2; /* registers 0/1 are always valid */ ++ fs->h = luaH_new(L, 0, 0); ++ /* anchor table of constants and prototype (to avoid being collected) */ ++ sethvalue2s(L, L->top, fs->h); ++ incr_top(L); ++ setptvalue2s(L, L->top, f); ++ incr_top(L); ++} ++ ++ ++static void close_func (LexState *ls) { ++ lua_State *L = ls->L; ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ removevars(ls, 0); ++ luaK_ret(fs, 0, 0); /* final return */ ++ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); ++ f->sizecode = fs->pc; ++ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); ++ f->sizelineinfo = fs->pc; ++ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); ++ f->sizek = fs->nk; ++ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); ++ f->sizep = fs->np; ++ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); ++ f->sizelocvars = fs->nlocvars; ++ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); ++ f->sizeupvalues = f->nups; ++ lua_assert(luaG_checkcode(f)); ++ lua_assert(fs->bl == NULL); ++ ls->fs = fs->prev; ++ L->top -= 2; /* remove table and prototype from the stack */ ++ /* last token read was anchored in defunct function; must reanchor it */ ++ if (fs) anchor_token(ls); ++} ++ ++ ++Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { ++ struct LexState lexstate; ++ struct FuncState funcstate; ++ lexstate.buff = buff; ++ luaX_setinput(L, &lexstate, z, luaS_new(L, name)); ++ open_func(&lexstate, &funcstate); ++ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ ++ luaX_next(&lexstate); /* read first token */ ++ chunk(&lexstate); ++ check(&lexstate, TK_EOS); ++ close_func(&lexstate); ++ lua_assert(funcstate.prev == NULL); ++ lua_assert(funcstate.f->nups == 0); ++ lua_assert(lexstate.fs == NULL); ++ return funcstate.f; ++} ++ ++ ++ ++/*============================================================*/ ++/* GRAMMAR RULES */ ++/*============================================================*/ ++ ++ ++static void field (LexState *ls, expdesc *v) { ++ /* field -> ['.' | ':'] NAME */ ++ FuncState *fs = ls->fs; ++ expdesc key; ++ luaK_exp2anyreg(fs, v); ++ luaX_next(ls); /* skip the dot or colon */ ++ checkname(ls, &key); ++ luaK_indexed(fs, v, &key); ++} ++ ++ ++static void yindex (LexState *ls, expdesc *v) { ++ /* index -> '[' expr ']' */ ++ luaX_next(ls); /* skip the '[' */ ++ expr(ls, v); ++ luaK_exp2val(ls->fs, v); ++ checknext(ls, ']'); ++} ++ ++ ++/* ++** {====================================================================== ++** Rules for Constructors ++** ======================================================================= ++*/ ++ ++ ++struct ConsControl { ++ expdesc v; /* last list item read */ ++ expdesc *t; /* table descriptor */ ++ int nh; /* total number of `record' elements */ ++ int na; /* total number of array elements */ ++ int tostore; /* number of array elements pending to be stored */ ++}; ++ ++ ++static void recfield (LexState *ls, struct ConsControl *cc) { ++ /* recfield -> (NAME | `['exp1`]') = exp1 */ ++ FuncState *fs = ls->fs; ++ int reg = ls->fs->freereg; ++ expdesc key, val; ++ int rkkey; ++ if (ls->t.token == TK_NAME) { ++ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); ++ checkname(ls, &key); ++ } ++ else /* ls->t.token == '[' */ ++ yindex(ls, &key); ++ cc->nh++; ++ checknext(ls, '='); ++ rkkey = luaK_exp2RK(fs, &key); ++ expr(ls, &val); ++ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); ++ fs->freereg = reg; /* free registers */ ++} ++ ++ ++static void closelistfield (FuncState *fs, struct ConsControl *cc) { ++ if (cc->v.k == VVOID) return; /* there is no list item */ ++ luaK_exp2nextreg(fs, &cc->v); ++ cc->v.k = VVOID; ++ if (cc->tostore == LFIELDS_PER_FLUSH) { ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ ++ cc->tostore = 0; /* no more items pending */ ++ } ++} ++ ++ ++static void lastlistfield (FuncState *fs, struct ConsControl *cc) { ++ if (cc->tostore == 0) return; ++ if (hasmultret(cc->v.k)) { ++ luaK_setmultret(fs, &cc->v); ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); ++ cc->na--; /* do not count last expression (unknown number of elements) */ ++ } ++ else { ++ if (cc->v.k != VVOID) ++ luaK_exp2nextreg(fs, &cc->v); ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); ++ } ++} ++ ++ ++static void listfield (LexState *ls, struct ConsControl *cc) { ++ expr(ls, &cc->v); ++ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); ++ cc->na++; ++ cc->tostore++; ++} ++ ++ ++static void constructor (LexState *ls, expdesc *t) { ++ /* constructor -> ?? */ ++ FuncState *fs = ls->fs; ++ int line = ls->linenumber; ++ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); ++ struct ConsControl cc; ++ cc.na = cc.nh = cc.tostore = 0; ++ cc.t = t; ++ init_exp(t, VRELOCABLE, pc); ++ init_exp(&cc.v, VVOID, 0); /* no value (yet) */ ++ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ ++ checknext(ls, '{'); ++ do { ++ lua_assert(cc.v.k == VVOID || cc.tostore > 0); ++ if (ls->t.token == '}') break; ++ closelistfield(fs, &cc); ++ switch(ls->t.token) { ++ case TK_NAME: { /* may be listfields or recfields */ ++ luaX_lookahead(ls); ++ if (ls->lookahead.token != '=') /* expression? */ ++ listfield(ls, &cc); ++ else ++ recfield(ls, &cc); ++ break; ++ } ++ case '[': { /* constructor_item -> recfield */ ++ recfield(ls, &cc); ++ break; ++ } ++ default: { /* constructor_part -> listfield */ ++ listfield(ls, &cc); ++ break; ++ } ++ } ++ } while (testnext(ls, ',') || testnext(ls, ';')); ++ check_match(ls, '}', '{', line); ++ lastlistfield(fs, &cc); ++ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ ++ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ ++} ++ ++/* }====================================================================== */ ++ ++ ++ ++static void parlist (LexState *ls) { ++ /* parlist -> [ param { `,' param } ] */ ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int nparams = 0; ++ f->is_vararg = 0; ++ if (ls->t.token != ')') { /* is `parlist' not empty? */ ++ do { ++ switch (ls->t.token) { ++ case TK_NAME: { /* param -> NAME */ ++ new_localvar(ls, str_checkname(ls), nparams++); ++ break; ++ } ++ case TK_DOTS: { /* param -> `...' */ ++ luaX_next(ls); ++#if defined(LUA_COMPAT_VARARG) ++ /* use `arg' as default name */ ++ new_localvarliteral(ls, "arg", nparams++); ++ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; ++#endif ++ f->is_vararg |= VARARG_ISVARARG; ++ break; ++ } ++ default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); ++ } ++ } while (!f->is_vararg && testnext(ls, ',')); ++ } ++ adjustlocalvars(ls, nparams); ++ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); ++ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ ++} ++ ++ ++static void body (LexState *ls, expdesc *e, int needself, int line) { ++ /* body -> `(' parlist `)' chunk END */ ++ FuncState new_fs; ++ open_func(ls, &new_fs); ++ new_fs.f->linedefined = line; ++ checknext(ls, '('); ++ if (needself) { ++ new_localvarliteral(ls, "self", 0); ++ adjustlocalvars(ls, 1); ++ } ++ parlist(ls); ++ checknext(ls, ')'); ++ chunk(ls); ++ new_fs.f->lastlinedefined = ls->linenumber; ++ check_match(ls, TK_END, TK_FUNCTION, line); ++ close_func(ls); ++ pushclosure(ls, &new_fs, e); ++} ++ ++ ++static int explist1 (LexState *ls, expdesc *v) { ++ /* explist1 -> expr { `,' expr } */ ++ int n = 1; /* at least one expression */ ++ expr(ls, v); ++ while (testnext(ls, ',')) { ++ luaK_exp2nextreg(ls->fs, v); ++ expr(ls, v); ++ n++; ++ } ++ return n; ++} ++ ++ ++static void funcargs (LexState *ls, expdesc *f) { ++ FuncState *fs = ls->fs; ++ expdesc args; ++ int base, nparams; ++ int line = ls->linenumber; ++ switch (ls->t.token) { ++ case '(': { /* funcargs -> `(' [ explist1 ] `)' */ ++ if (line != ls->lastline) ++ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); ++ luaX_next(ls); ++ if (ls->t.token == ')') /* arg list is empty? */ ++ args.k = VVOID; ++ else { ++ explist1(ls, &args); ++ luaK_setmultret(fs, &args); ++ } ++ check_match(ls, ')', '(', line); ++ break; ++ } ++ case '{': { /* funcargs -> constructor */ ++ constructor(ls, &args); ++ break; ++ } ++ case TK_STRING: { /* funcargs -> STRING */ ++ codestring(ls, &args, ls->t.seminfo.ts); ++ luaX_next(ls); /* must use `seminfo' before `next' */ ++ break; ++ } ++ default: { ++ luaX_syntaxerror(ls, "function arguments expected"); ++ return; ++ } ++ } ++ lua_assert(f->k == VNONRELOC); ++ base = f->u.s.info; /* base register for call */ ++ if (hasmultret(args.k)) ++ nparams = LUA_MULTRET; /* open call */ ++ else { ++ if (args.k != VVOID) ++ luaK_exp2nextreg(fs, &args); /* close last argument */ ++ nparams = fs->freereg - (base+1); ++ } ++ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); ++ luaK_fixline(fs, line); ++ fs->freereg = base+1; /* call remove function and arguments and leaves ++ (unless changed) one result */ ++} ++ ++ ++ ++ ++/* ++** {====================================================================== ++** Expression parsing ++** ======================================================================= ++*/ ++ ++ ++static void prefixexp (LexState *ls, expdesc *v) { ++ /* prefixexp -> NAME | '(' expr ')' */ ++ switch (ls->t.token) { ++ case '(': { ++ int line = ls->linenumber; ++ luaX_next(ls); ++ expr(ls, v); ++ check_match(ls, ')', '(', line); ++ luaK_dischargevars(ls->fs, v); ++ return; ++ } ++ case TK_NAME: { ++ singlevar(ls, v); ++ return; ++ } ++ default: { ++ luaX_syntaxerror(ls, "unexpected symbol"); ++ return; ++ } ++ } ++} ++ ++ ++static void primaryexp (LexState *ls, expdesc *v) { ++ /* primaryexp -> ++ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ ++ FuncState *fs = ls->fs; ++ prefixexp(ls, v); ++ for (;;) { ++ switch (ls->t.token) { ++ case '.': { /* field */ ++ field(ls, v); ++ break; ++ } ++ case '[': { /* `[' exp1 `]' */ ++ expdesc key; ++ luaK_exp2anyreg(fs, v); ++ yindex(ls, &key); ++ luaK_indexed(fs, v, &key); ++ break; ++ } ++ case ':': { /* `:' NAME funcargs */ ++ expdesc key; ++ luaX_next(ls); ++ checkname(ls, &key); ++ luaK_self(fs, v, &key); ++ funcargs(ls, v); ++ break; ++ } ++ case '(': case TK_STRING: case '{': { /* funcargs */ ++ luaK_exp2nextreg(fs, v); ++ funcargs(ls, v); ++ break; ++ } ++ default: return; ++ } ++ } ++} ++ ++ ++static void simpleexp (LexState *ls, expdesc *v) { ++ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | ++ constructor | FUNCTION body | primaryexp */ ++ switch (ls->t.token) { ++ case TK_NUMBER: { ++ init_exp(v, VKNUM, 0); ++ v->u.nval = ls->t.seminfo.r; ++ break; ++ } ++ case TK_STRING: { ++ codestring(ls, v, ls->t.seminfo.ts); ++ break; ++ } ++ case TK_NIL: { ++ init_exp(v, VNIL, 0); ++ break; ++ } ++ case TK_TRUE: { ++ init_exp(v, VTRUE, 0); ++ break; ++ } ++ case TK_FALSE: { ++ init_exp(v, VFALSE, 0); ++ break; ++ } ++ case TK_DOTS: { /* vararg */ ++ FuncState *fs = ls->fs; ++ check_condition(ls, fs->f->is_vararg, ++ "cannot use " LUA_QL("...") " outside a vararg function"); ++ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ ++ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); ++ break; ++ } ++ case '{': { /* constructor */ ++ constructor(ls, v); ++ return; ++ } ++ case TK_FUNCTION: { ++ luaX_next(ls); ++ body(ls, v, 0, ls->linenumber); ++ return; ++ } ++ default: { ++ primaryexp(ls, v); ++ return; ++ } ++ } ++ luaX_next(ls); ++} ++ ++ ++static UnOpr getunopr (int op) { ++ switch (op) { ++ case TK_NOT: return OPR_NOT; ++ case '-': return OPR_MINUS; ++ case '#': return OPR_LEN; ++ default: return OPR_NOUNOPR; ++ } ++} ++ ++ ++static BinOpr getbinopr (int op) { ++ switch (op) { ++ case '+': return OPR_ADD; ++ case '-': return OPR_SUB; ++ case '*': return OPR_MUL; ++ case '/': return OPR_DIV; ++ case '%': return OPR_MOD; ++ case '^': return OPR_POW; ++ case TK_CONCAT: return OPR_CONCAT; ++ case TK_NE: return OPR_NE; ++ case TK_EQ: return OPR_EQ; ++ case '<': return OPR_LT; ++ case TK_LE: return OPR_LE; ++ case '>': return OPR_GT; ++ case TK_GE: return OPR_GE; ++ case TK_AND: return OPR_AND; ++ case TK_OR: return OPR_OR; ++ default: return OPR_NOBINOPR; ++ } ++} ++ ++ ++static const struct { ++ lu_byte left; /* left priority for each binary operator */ ++ lu_byte right; /* right priority */ ++} priority[] = { /* ORDER OPR */ ++ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ ++ {10, 9}, {5, 4}, /* power and concat (right associative) */ ++ {3, 3}, {3, 3}, /* equality and inequality */ ++ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ ++ {2, 2}, {1, 1} /* logical (and/or) */ ++}; ++ ++#define UNARY_PRIORITY 8 /* priority for unary operators */ ++ ++ ++/* ++** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ++** where `binop' is any binary operator with a priority higher than `limit' ++*/ ++static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { ++ BinOpr op; ++ UnOpr uop; ++ enterlevel(ls); ++ uop = getunopr(ls->t.token); ++ if (uop != OPR_NOUNOPR) { ++ luaX_next(ls); ++ subexpr(ls, v, UNARY_PRIORITY); ++ luaK_prefix(ls->fs, uop, v); ++ } ++ else simpleexp(ls, v); ++ /* expand while operators have priorities higher than `limit' */ ++ op = getbinopr(ls->t.token); ++ while (op != OPR_NOBINOPR && priority[op].left > limit) { ++ expdesc v2; ++ BinOpr nextop; ++ luaX_next(ls); ++ luaK_infix(ls->fs, op, v); ++ /* read sub-expression with higher priority */ ++ nextop = subexpr(ls, &v2, priority[op].right); ++ luaK_posfix(ls->fs, op, v, &v2); ++ op = nextop; ++ } ++ leavelevel(ls); ++ return op; /* return first untreated operator */ ++} ++ ++ ++static void expr (LexState *ls, expdesc *v) { ++ subexpr(ls, v, 0); ++} ++ ++/* }==================================================================== */ ++ ++ ++ ++/* ++** {====================================================================== ++** Rules for Statements ++** ======================================================================= ++*/ ++ ++ ++static int block_follow (int token) { ++ switch (token) { ++ case TK_ELSE: case TK_ELSEIF: case TK_END: ++ case TK_UNTIL: case TK_EOS: ++ return 1; ++ default: return 0; ++ } ++} ++ ++ ++static void block (LexState *ls) { ++ /* block -> chunk */ ++ FuncState *fs = ls->fs; ++ BlockCnt bl; ++ enterblock(fs, &bl, 0); ++ chunk(ls); ++ lua_assert(bl.breaklist == NO_JUMP); ++ leaveblock(fs); ++} ++ ++ ++/* ++** structure to chain all variables in the left-hand side of an ++** assignment ++*/ ++struct LHS_assign { ++ struct LHS_assign *prev; ++ expdesc v; /* variable (global, local, upvalue, or indexed) */ ++}; ++ ++ ++/* ++** check whether, in an assignment to a local variable, the local variable ++** is needed in a previous assignment (to a table). If so, save original ++** local value in a safe place and use this safe copy in the previous ++** assignment. ++*/ ++static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { ++ FuncState *fs = ls->fs; ++ int extra = fs->freereg; /* eventual position to save local variable */ ++ int conflict = 0; ++ for (; lh; lh = lh->prev) { ++ if (lh->v.k == VINDEXED) { ++ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ ++ conflict = 1; ++ lh->v.u.s.info = extra; /* previous assignment will use safe copy */ ++ } ++ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ ++ conflict = 1; ++ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ ++ } ++ } ++ } ++ if (conflict) { ++ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ ++ luaK_reserveregs(fs, 1); ++ } ++} ++ ++ ++static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { ++ expdesc e; ++ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, ++ "syntax error"); ++ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ ++ struct LHS_assign nv; ++ nv.prev = lh; ++ primaryexp(ls, &nv.v); ++ if (nv.v.k == VLOCAL) ++ check_conflict(ls, lh, &nv.v); ++ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, ++ "variables in assignment"); ++ assignment(ls, &nv, nvars+1); ++ } ++ else { /* assignment -> `=' explist1 */ ++ int nexps; ++ checknext(ls, '='); ++ nexps = explist1(ls, &e); ++ if (nexps != nvars) { ++ adjust_assign(ls, nvars, nexps, &e); ++ if (nexps > nvars) ++ ls->fs->freereg -= nexps - nvars; /* remove extra values */ ++ } ++ else { ++ luaK_setoneret(ls->fs, &e); /* close last expression */ ++ luaK_storevar(ls->fs, &lh->v, &e); ++ return; /* avoid default */ ++ } ++ } ++ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ ++ luaK_storevar(ls->fs, &lh->v, &e); ++} ++ ++ ++static int cond (LexState *ls) { ++ /* cond -> exp */ ++ expdesc v; ++ expr(ls, &v); /* read condition */ ++ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ ++ luaK_goiftrue(ls->fs, &v); ++ return v.f; ++} ++ ++ ++static void breakstat (LexState *ls) { ++ FuncState *fs = ls->fs; ++ BlockCnt *bl = fs->bl; ++ int upval = 0; ++ while (bl && !bl->isbreakable) { ++ upval |= bl->upval; ++ bl = bl->previous; ++ } ++ if (!bl) ++ luaX_syntaxerror(ls, "no loop to break"); ++ if (upval) ++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); ++ luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); ++} ++ ++ ++static void whilestat (LexState *ls, int line) { ++ /* whilestat -> WHILE cond DO block END */ ++ FuncState *fs = ls->fs; ++ int whileinit; ++ int condexit; ++ BlockCnt bl; ++ luaX_next(ls); /* skip WHILE */ ++ whileinit = luaK_getlabel(fs); ++ condexit = cond(ls); ++ enterblock(fs, &bl, 1); ++ checknext(ls, TK_DO); ++ block(ls); ++ luaK_patchlist(fs, luaK_jump(fs), whileinit); ++ check_match(ls, TK_END, TK_WHILE, line); ++ leaveblock(fs); ++ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ ++} ++ ++ ++static void repeatstat (LexState *ls, int line) { ++ /* repeatstat -> REPEAT block UNTIL cond */ ++ int condexit; ++ FuncState *fs = ls->fs; ++ int repeat_init = luaK_getlabel(fs); ++ BlockCnt bl1, bl2; ++ enterblock(fs, &bl1, 1); /* loop block */ ++ enterblock(fs, &bl2, 0); /* scope block */ ++ luaX_next(ls); /* skip REPEAT */ ++ chunk(ls); ++ check_match(ls, TK_UNTIL, TK_REPEAT, line); ++ condexit = cond(ls); /* read condition (inside scope block) */ ++ if (!bl2.upval) { /* no upvalues? */ ++ leaveblock(fs); /* finish scope */ ++ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ ++ } ++ else { /* complete semantics when there are upvalues */ ++ breakstat(ls); /* if condition then break */ ++ luaK_patchtohere(ls->fs, condexit); /* else... */ ++ leaveblock(fs); /* finish scope... */ ++ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ ++ } ++ leaveblock(fs); /* finish loop */ ++} ++ ++ ++static int exp1 (LexState *ls) { ++ expdesc e; ++ int k; ++ expr(ls, &e); ++ k = e.k; ++ luaK_exp2nextreg(ls->fs, &e); ++ return k; ++} ++ ++ ++static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { ++ /* forbody -> DO block */ ++ BlockCnt bl; ++ FuncState *fs = ls->fs; ++ int prep, endfor; ++ adjustlocalvars(ls, 3); /* control variables */ ++ checknext(ls, TK_DO); ++ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); ++ enterblock(fs, &bl, 0); /* scope for declared variables */ ++ adjustlocalvars(ls, nvars); ++ luaK_reserveregs(fs, nvars); ++ block(ls); ++ leaveblock(fs); /* end of scope for declared variables */ ++ luaK_patchtohere(fs, prep); ++ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : ++ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); ++ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ ++ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); ++} ++ ++ ++static void fornum (LexState *ls, TString *varname, int line) { ++ /* fornum -> NAME = exp1,exp1[,exp1] forbody */ ++ FuncState *fs = ls->fs; ++ int base = fs->freereg; ++ new_localvarliteral(ls, "(for index)", 0); ++ new_localvarliteral(ls, "(for limit)", 1); ++ new_localvarliteral(ls, "(for step)", 2); ++ new_localvar(ls, varname, 3); ++ checknext(ls, '='); ++ exp1(ls); /* initial value */ ++ checknext(ls, ','); ++ exp1(ls); /* limit */ ++ if (testnext(ls, ',')) ++ exp1(ls); /* optional step */ ++ else { /* default step = 1 */ ++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); ++ luaK_reserveregs(fs, 1); ++ } ++ forbody(ls, base, line, 1, 1); ++} ++ ++ ++static void forlist (LexState *ls, TString *indexname) { ++ /* forlist -> NAME {,NAME} IN explist1 forbody */ ++ FuncState *fs = ls->fs; ++ expdesc e; ++ int nvars = 0; ++ int line; ++ int base = fs->freereg; ++ /* create control variables */ ++ new_localvarliteral(ls, "(for generator)", nvars++); ++ new_localvarliteral(ls, "(for state)", nvars++); ++ new_localvarliteral(ls, "(for control)", nvars++); ++ /* create declared variables */ ++ new_localvar(ls, indexname, nvars++); ++ while (testnext(ls, ',')) ++ new_localvar(ls, str_checkname(ls), nvars++); ++ checknext(ls, TK_IN); ++ line = ls->linenumber; ++ adjust_assign(ls, 3, explist1(ls, &e), &e); ++ luaK_checkstack(fs, 3); /* extra space to call generator */ ++ forbody(ls, base, line, nvars - 3, 0); ++} ++ ++ ++static void forstat (LexState *ls, int line) { ++ /* forstat -> FOR (fornum | forlist) END */ ++ FuncState *fs = ls->fs; ++ TString *varname; ++ BlockCnt bl; ++ enterblock(fs, &bl, 1); /* scope for loop and control variables */ ++ luaX_next(ls); /* skip `for' */ ++ varname = str_checkname(ls); /* first variable name */ ++ switch (ls->t.token) { ++ case '=': fornum(ls, varname, line); break; ++ case ',': case TK_IN: forlist(ls, varname); break; ++ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); ++ } ++ check_match(ls, TK_END, TK_FOR, line); ++ leaveblock(fs); /* loop scope (`break' jumps to this point) */ ++} ++ ++ ++static int test_then_block (LexState *ls) { ++ /* test_then_block -> [IF | ELSEIF] cond THEN block */ ++ int condexit; ++ luaX_next(ls); /* skip IF or ELSEIF */ ++ condexit = cond(ls); ++ checknext(ls, TK_THEN); ++ block(ls); /* `then' part */ ++ return condexit; ++} ++ ++ ++static void ifstat (LexState *ls, int line) { ++ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ ++ FuncState *fs = ls->fs; ++ int flist; ++ int escapelist = NO_JUMP; ++ flist = test_then_block(ls); /* IF cond THEN block */ ++ while (ls->t.token == TK_ELSEIF) { ++ luaK_concat(fs, &escapelist, luaK_jump(fs)); ++ luaK_patchtohere(fs, flist); ++ flist = test_then_block(ls); /* ELSEIF cond THEN block */ ++ } ++ if (ls->t.token == TK_ELSE) { ++ luaK_concat(fs, &escapelist, luaK_jump(fs)); ++ luaK_patchtohere(fs, flist); ++ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ ++ block(ls); /* `else' part */ ++ } ++ else ++ luaK_concat(fs, &escapelist, flist); ++ luaK_patchtohere(fs, escapelist); ++ check_match(ls, TK_END, TK_IF, line); ++} ++ ++ ++static void localfunc (LexState *ls) { ++ expdesc v, b; ++ FuncState *fs = ls->fs; ++ new_localvar(ls, str_checkname(ls), 0); ++ init_exp(&v, VLOCAL, fs->freereg); ++ luaK_reserveregs(fs, 1); ++ adjustlocalvars(ls, 1); ++ body(ls, &b, 0, ls->linenumber); ++ luaK_storevar(fs, &v, &b); ++ /* debug information will only see the variable after this point! */ ++ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; ++} ++ ++ ++static void localstat (LexState *ls) { ++ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ ++ int nvars = 0; ++ int nexps; ++ expdesc e; ++ do { ++ new_localvar(ls, str_checkname(ls), nvars++); ++ } while (testnext(ls, ',')); ++ if (testnext(ls, '=')) ++ nexps = explist1(ls, &e); ++ else { ++ e.k = VVOID; ++ nexps = 0; ++ } ++ adjust_assign(ls, nvars, nexps, &e); ++ adjustlocalvars(ls, nvars); ++} ++ ++ ++static int funcname (LexState *ls, expdesc *v) { ++ /* funcname -> NAME {field} [`:' NAME] */ ++ int needself = 0; ++ singlevar(ls, v); ++ while (ls->t.token == '.') ++ field(ls, v); ++ if (ls->t.token == ':') { ++ needself = 1; ++ field(ls, v); ++ } ++ return needself; ++} ++ ++ ++static void funcstat (LexState *ls, int line) { ++ /* funcstat -> FUNCTION funcname body */ ++ int needself; ++ expdesc v, b; ++ luaX_next(ls); /* skip FUNCTION */ ++ needself = funcname(ls, &v); ++ body(ls, &b, needself, line); ++ luaK_storevar(ls->fs, &v, &b); ++ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ ++} ++ ++ ++static void exprstat (LexState *ls) { ++ /* stat -> func | assignment */ ++ FuncState *fs = ls->fs; ++ struct LHS_assign v; ++ primaryexp(ls, &v.v); ++ if (v.v.k == VCALL) /* stat -> func */ ++ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ ++ else { /* stat -> assignment */ ++ v.prev = NULL; ++ assignment(ls, &v, 1); ++ } ++} ++ ++ ++static void retstat (LexState *ls) { ++ /* stat -> RETURN explist */ ++ FuncState *fs = ls->fs; ++ expdesc e; ++ int first, nret; /* registers with returned values */ ++ luaX_next(ls); /* skip RETURN */ ++ if (block_follow(ls->t.token) || ls->t.token == ';') ++ first = nret = 0; /* return no values */ ++ else { ++ nret = explist1(ls, &e); /* optional return values */ ++ if (hasmultret(e.k)) { ++ luaK_setmultret(fs, &e); ++ if (e.k == VCALL && nret == 1) { /* tail call? */ ++ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); ++ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); ++ } ++ first = fs->nactvar; ++ nret = LUA_MULTRET; /* return all values */ ++ } ++ else { ++ if (nret == 1) /* only one single value? */ ++ first = luaK_exp2anyreg(fs, &e); ++ else { ++ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ ++ first = fs->nactvar; /* return all `active' values */ ++ lua_assert(nret == fs->freereg - first); ++ } ++ } ++ } ++ luaK_ret(fs, first, nret); ++} ++ ++ ++static int statement (LexState *ls) { ++ int line = ls->linenumber; /* may be needed for error messages */ ++ switch (ls->t.token) { ++ case TK_IF: { /* stat -> ifstat */ ++ ifstat(ls, line); ++ return 0; ++ } ++ case TK_WHILE: { /* stat -> whilestat */ ++ whilestat(ls, line); ++ return 0; ++ } ++ case TK_DO: { /* stat -> DO block END */ ++ luaX_next(ls); /* skip DO */ ++ block(ls); ++ check_match(ls, TK_END, TK_DO, line); ++ return 0; ++ } ++ case TK_FOR: { /* stat -> forstat */ ++ forstat(ls, line); ++ return 0; ++ } ++ case TK_REPEAT: { /* stat -> repeatstat */ ++ repeatstat(ls, line); ++ return 0; ++ } ++ case TK_FUNCTION: { ++ funcstat(ls, line); /* stat -> funcstat */ ++ return 0; ++ } ++ case TK_LOCAL: { /* stat -> localstat */ ++ luaX_next(ls); /* skip LOCAL */ ++ if (testnext(ls, TK_FUNCTION)) /* local function? */ ++ localfunc(ls); ++ else ++ localstat(ls); ++ return 0; ++ } ++ case TK_RETURN: { /* stat -> retstat */ ++ retstat(ls); ++ return 1; /* must be last statement */ ++ } ++ case TK_BREAK: { /* stat -> breakstat */ ++ luaX_next(ls); /* skip BREAK */ ++ breakstat(ls); ++ return 1; /* must be last statement */ ++ } ++ default: { ++ exprstat(ls); ++ return 0; /* to avoid warnings */ ++ } ++ } ++} ++ ++ ++static void chunk (LexState *ls) { ++ /* chunk -> { stat [`;'] } */ ++ int islast = 0; ++ enterlevel(ls); ++ while (!islast && !block_follow(ls->t.token)) { ++ islast = statement(ls); ++ testnext(ls, ';'); ++ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && ++ ls->fs->freereg >= ls->fs->nactvar); ++ ls->fs->freereg = ls->fs->nactvar; /* free registers */ ++ } ++ leavelevel(ls); ++} ++ ++/* }====================================================================== */ +--- /dev/null ++++ b/extensions/LUA/lua/lparser.h +@@ -0,0 +1,82 @@ ++/* ++** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua Parser ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lparser_h ++#define lparser_h ++ ++#include "llimits.h" ++#include "lobject.h" ++#include "lzio.h" ++ ++ ++/* ++** Expression descriptor ++*/ ++ ++typedef enum { ++ VVOID, /* no value */ ++ VNIL, ++ VTRUE, ++ VFALSE, ++ VK, /* info = index of constant in `k' */ ++ VKNUM, /* nval = numerical value */ ++ VLOCAL, /* info = local register */ ++ VUPVAL, /* info = index of upvalue in `upvalues' */ ++ VGLOBAL, /* info = index of table; aux = index of global name in `k' */ ++ VINDEXED, /* info = table register; aux = index register (or `k') */ ++ VJMP, /* info = instruction pc */ ++ VRELOCABLE, /* info = instruction pc */ ++ VNONRELOC, /* info = result register */ ++ VCALL, /* info = instruction pc */ ++ VVARARG /* info = instruction pc */ ++} expkind; ++ ++typedef struct expdesc { ++ expkind k; ++ union { ++ struct { int info, aux; } s; ++ lua_Number nval; ++ } u; ++ int t; /* patch list of `exit when true' */ ++ int f; /* patch list of `exit when false' */ ++} expdesc; ++ ++ ++typedef struct upvaldesc { ++ lu_byte k; ++ lu_byte info; ++} upvaldesc; ++ ++ ++struct BlockCnt; /* defined in lparser.c */ ++ ++ ++/* state needed to generate code for a given function */ ++typedef struct FuncState { ++ Proto *f; /* current function header */ ++ Table *h; /* table to find (and reuse) elements in `k' */ ++ struct FuncState *prev; /* enclosing function */ ++ struct LexState *ls; /* lexical state */ ++ struct lua_State *L; /* copy of the Lua state */ ++ struct BlockCnt *bl; /* chain of current blocks */ ++ int pc; /* next position to code (equivalent to `ncode') */ ++ int lasttarget; /* `pc' of last `jump target' */ ++ int jpc; /* list of pending jumps to `pc' */ ++ int freereg; /* first free register */ ++ int nk; /* number of elements in `k' */ ++ int np; /* number of elements in `p' */ ++ short nlocvars; /* number of elements in `locvars' */ ++ lu_byte nactvar; /* number of active local variables */ ++ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ ++ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ ++} FuncState; ++ ++ ++LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, ++ const char *name); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lstate.c +@@ -0,0 +1,214 @@ ++/* ++** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ ++** Global State ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lstate_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) ++#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) ++#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) ++ ++ ++/* ++** Main thread combines a thread state and the global state ++*/ ++typedef struct LG { ++ lua_State l; ++ global_State g; ++} LG; ++ ++ ++ ++static void stack_init (lua_State *L1, lua_State *L) { ++ /* initialize CallInfo array */ ++ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); ++ L1->ci = L1->base_ci; ++ L1->size_ci = BASIC_CI_SIZE; ++ L1->end_ci = L1->base_ci + L1->size_ci - 1; ++ /* initialize stack array */ ++ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); ++ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; ++ L1->top = L1->stack; ++ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; ++ /* initialize first ci */ ++ L1->ci->func = L1->top; ++ setnilvalue(L1->top++); /* `function' entry for this `ci' */ ++ L1->base = L1->ci->base = L1->top; ++ L1->ci->top = L1->top + LUA_MINSTACK; ++} ++ ++ ++static void freestack (lua_State *L, lua_State *L1) { ++ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); ++ luaM_freearray(L, L1->stack, L1->stacksize, TValue); ++} ++ ++ ++/* ++** open parts that may cause memory-allocation errors ++*/ ++static void f_luaopen (lua_State *L, void *ud) { ++ global_State *g = G(L); ++ UNUSED(ud); ++ stack_init(L, L); /* init stack */ ++ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ ++ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ ++ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ ++ luaT_init(L); ++ luaX_init(L); ++ luaS_fix(luaS_newliteral(L, MEMERRMSG)); ++ g->GCthreshold = 4*g->totalbytes; ++} ++ ++ ++static void preinit_state (lua_State *L, global_State *g) { ++ G(L) = g; ++ L->stack = NULL; ++ L->stacksize = 0; ++ L->errorJmp = NULL; ++ L->hook = NULL; ++ L->hookmask = 0; ++ L->basehookcount = 0; ++ L->allowhook = 1; ++ resethookcount(L); ++ L->openupval = NULL; ++ L->size_ci = 0; ++ L->nCcalls = L->baseCcalls = 0; ++ L->status = 0; ++ L->base_ci = L->ci = NULL; ++ L->savedpc = NULL; ++ L->errfunc = 0; ++ setnilvalue(gt(L)); ++} ++ ++ ++static void close_state (lua_State *L) { ++ global_State *g = G(L); ++ luaF_close(L, L->stack); /* close all upvalues for this thread */ ++ luaC_freeall(L); /* collect all objects */ ++ lua_assert(g->rootgc == obj2gco(L)); ++ lua_assert(g->strt.nuse == 0); ++ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); ++ luaZ_freebuffer(L, &g->buff); ++ freestack(L, L); ++ lua_assert(g->totalbytes == sizeof(LG)); ++ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); ++} ++ ++ ++lua_State *luaE_newthread (lua_State *L) { ++ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); ++ luaC_link(L, obj2gco(L1), LUA_TTHREAD); ++ preinit_state(L1, G(L)); ++ stack_init(L1, L); /* init stack */ ++ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ ++ L1->hookmask = L->hookmask; ++ L1->basehookcount = L->basehookcount; ++ L1->hook = L->hook; ++ resethookcount(L1); ++ lua_assert(iswhite(obj2gco(L1))); ++ return L1; ++} ++ ++ ++void luaE_freethread (lua_State *L, lua_State *L1) { ++ luaF_close(L1, L1->stack); /* close all upvalues for this thread */ ++ lua_assert(L1->openupval == NULL); ++ luai_userstatefree(L1); ++ freestack(L, L1); ++ luaM_freemem(L, fromstate(L1), state_size(lua_State)); ++} ++ ++ ++LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { ++ int i; ++ lua_State *L; ++ global_State *g; ++ void *l = (*f)(ud, NULL, 0, state_size(LG)); ++ if (l == NULL) return NULL; ++ L = tostate(l); ++ g = &((LG *)L)->g; ++ L->next = NULL; ++ L->tt = LUA_TTHREAD; ++ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); ++ L->marked = luaC_white(g); ++ set2bits(L->marked, FIXEDBIT, SFIXEDBIT); ++ preinit_state(L, g); ++ g->frealloc = f; ++ g->ud = ud; ++ g->mainthread = L; ++ g->uvhead.u.l.prev = &g->uvhead; ++ g->uvhead.u.l.next = &g->uvhead; ++ g->GCthreshold = 0; /* mark it as unfinished state */ ++ g->strt.size = 0; ++ g->strt.nuse = 0; ++ g->strt.hash = NULL; ++ setnilvalue(registry(L)); ++ luaZ_initbuffer(L, &g->buff); ++ g->panic = NULL; ++ g->gcstate = GCSpause; ++ g->rootgc = obj2gco(L); ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ g->tmudata = NULL; ++ g->totalbytes = sizeof(LG); ++ g->gcpause = LUAI_GCPAUSE; ++ g->gcstepmul = LUAI_GCMUL; ++ g->gcdept = 0; ++ for (i=0; imt[i] = NULL; ++ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { ++ /* memory allocation error: free partial state */ ++ close_state(L); ++ L = NULL; ++ } ++ else ++ luai_userstateopen(L); ++ return L; ++} ++ ++ ++static void callallgcTM (lua_State *L, void *ud) { ++ UNUSED(ud); ++ luaC_callGCTM(L); /* call GC metamethods for all udata */ ++} ++ ++ ++LUA_API void lua_close (lua_State *L) { ++ L = G(L)->mainthread; /* only the main thread can be closed */ ++ lua_lock(L); ++ luaF_close(L, L->stack); /* close all upvalues for this thread */ ++ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ ++ L->errfunc = 0; /* no error function during GC metamethods */ ++ do { /* repeat until no more errors */ ++ L->ci = L->base_ci; ++ L->base = L->top = L->ci->base; ++ L->nCcalls = L->baseCcalls = 0; ++ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); ++ lua_assert(G(L)->tmudata == NULL); ++ luai_userstateclose(L); ++ close_state(L); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstate.h +@@ -0,0 +1,169 @@ ++/* ++** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ ++** Global State ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lstate_h ++#define lstate_h ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "ltm.h" ++#include "lzio.h" ++ ++ ++ ++struct lua_longjmp; /* defined in ldo.c */ ++ ++ ++/* table of globals */ ++#define gt(L) (&L->l_gt) ++ ++/* registry */ ++#define registry(L) (&G(L)->l_registry) ++ ++ ++/* extra stack space to handle TM calls and some other extras */ ++#define EXTRA_STACK 5 ++ ++ ++#define BASIC_CI_SIZE 8 ++ ++#define BASIC_STACK_SIZE (2*LUA_MINSTACK) ++ ++ ++ ++typedef struct stringtable { ++ GCObject **hash; ++ lu_int32 nuse; /* number of elements */ ++ int size; ++} stringtable; ++ ++ ++/* ++** informations about a call ++*/ ++typedef struct CallInfo { ++ StkId base; /* base for this function */ ++ StkId func; /* function index in the stack */ ++ StkId top; /* top for this function */ ++ const Instruction *savedpc; ++ int nresults; /* expected number of results from this function */ ++ int tailcalls; /* number of tail calls lost under this entry */ ++} CallInfo; ++ ++ ++ ++#define curr_func(L) (clvalue(L->ci->func)) ++#define ci_func(ci) (clvalue((ci)->func)) ++#define f_isLua(ci) (!ci_func(ci)->c.isC) ++#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) ++ ++ ++/* ++** `global state', shared by all threads of this state ++*/ ++typedef struct global_State { ++ stringtable strt; /* hash table for strings */ ++ lua_Alloc frealloc; /* function to reallocate memory */ ++ void *ud; /* auxiliary data to `frealloc' */ ++ lu_byte currentwhite; ++ lu_byte gcstate; /* state of garbage collector */ ++ int sweepstrgc; /* position of sweep in `strt' */ ++ GCObject *rootgc; /* list of all collectable objects */ ++ GCObject **sweepgc; /* position of sweep in `rootgc' */ ++ GCObject *gray; /* list of gray objects */ ++ GCObject *grayagain; /* list of objects to be traversed atomically */ ++ GCObject *weak; /* list of weak tables (to be cleared) */ ++ GCObject *tmudata; /* last element of list of userdata to be GC */ ++ Mbuffer buff; /* temporary buffer for string concatentation */ ++ lu_mem GCthreshold; ++ lu_mem totalbytes; /* number of bytes currently allocated */ ++ lu_mem estimate; /* an estimate of number of bytes actually in use */ ++ lu_mem gcdept; /* how much GC is `behind schedule' */ ++ int gcpause; /* size of pause between successive GCs */ ++ int gcstepmul; /* GC `granularity' */ ++ lua_CFunction panic; /* to be called in unprotected errors */ ++ TValue l_registry; ++ struct lua_State *mainthread; ++ UpVal uvhead; /* head of double-linked list of all open upvalues */ ++ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ ++ TString *tmname[TM_N]; /* array with tag-method names */ ++} global_State; ++ ++ ++/* ++** `per thread' state ++*/ ++struct lua_State { ++ CommonHeader; ++ lu_byte status; ++ StkId top; /* first free slot in the stack */ ++ StkId base; /* base of current function */ ++ global_State *l_G; ++ CallInfo *ci; /* call info for current function */ ++ const Instruction *savedpc; /* `savedpc' of current function */ ++ StkId stack_last; /* last free slot in the stack */ ++ StkId stack; /* stack base */ ++ CallInfo *end_ci; /* points after end of ci array*/ ++ CallInfo *base_ci; /* array of CallInfo's */ ++ int stacksize; ++ int size_ci; /* size of array `base_ci' */ ++ unsigned short nCcalls; /* number of nested C calls */ ++ unsigned short baseCcalls; /* nested C calls when resuming coroutine */ ++ lu_byte hookmask; ++ lu_byte allowhook; ++ int basehookcount; ++ int hookcount; ++ lua_Hook hook; ++ TValue l_gt; /* table of globals */ ++ TValue env; /* temporary place for environments */ ++ GCObject *openupval; /* list of open upvalues in this stack */ ++ GCObject *gclist; ++ struct lua_longjmp *errorJmp; /* current error recover point */ ++ ptrdiff_t errfunc; /* current error handling function (stack index) */ ++}; ++ ++ ++#define G(L) (L->l_G) ++ ++ ++/* ++** Union of all collectable objects ++*/ ++union GCObject { ++ GCheader gch; ++ union TString ts; ++ union Udata u; ++ union Closure cl; ++ struct Table h; ++ struct Proto p; ++ struct UpVal uv; ++ struct lua_State th; /* thread */ ++}; ++ ++ ++/* macros to convert a GCObject into a specific value */ ++#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) ++#define gco2ts(o) (&rawgco2ts(o)->tsv) ++#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) ++#define gco2u(o) (&rawgco2u(o)->uv) ++#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) ++#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) ++#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) ++#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) ++#define ngcotouv(o) \ ++ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) ++#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) ++ ++/* macro to convert any Lua object into a GCObject */ ++#define obj2gco(v) (cast(GCObject *, (v))) ++ ++ ++LUAI_FUNC lua_State *luaE_newthread (lua_State *L); ++LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstring.c +@@ -0,0 +1,110 @@ ++/* ++** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ++** String table (keeps all strings handled by Lua) ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lstring_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++ ++ ++ ++void luaS_resize (lua_State *L, int newsize) { ++ GCObject **newhash; ++ stringtable *tb; ++ int i; ++ if (G(L)->gcstate == GCSsweepstring) ++ return; /* cannot resize during GC traverse */ ++ newhash = luaM_newvector(L, newsize, GCObject *); ++ tb = &G(L)->strt; ++ for (i=0; isize; i++) { ++ GCObject *p = tb->hash[i]; ++ while (p) { /* for each node in the list */ ++ GCObject *next = p->gch.next; /* save next */ ++ unsigned int h = gco2ts(p)->hash; ++ int h1 = lmod(h, newsize); /* new position */ ++ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); ++ p->gch.next = newhash[h1]; /* chain it */ ++ newhash[h1] = p; ++ p = next; ++ } ++ } ++ luaM_freearray(L, tb->hash, tb->size, TString *); ++ tb->size = newsize; ++ tb->hash = newhash; ++} ++ ++ ++static TString *newlstr (lua_State *L, const char *str, size_t l, ++ unsigned int h) { ++ TString *ts; ++ stringtable *tb; ++ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) ++ luaM_toobig(L); ++ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); ++ ts->tsv.len = l; ++ ts->tsv.hash = h; ++ ts->tsv.marked = luaC_white(G(L)); ++ ts->tsv.tt = LUA_TSTRING; ++ ts->tsv.reserved = 0; ++ memcpy(ts+1, str, l*sizeof(char)); ++ ((char *)(ts+1))[l] = '\0'; /* ending 0 */ ++ tb = &G(L)->strt; ++ h = lmod(h, tb->size); ++ ts->tsv.next = tb->hash[h]; /* chain new entry */ ++ tb->hash[h] = obj2gco(ts); ++ tb->nuse++; ++ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) ++ luaS_resize(L, tb->size*2); /* too crowded */ ++ return ts; ++} ++ ++ ++TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { ++ GCObject *o; ++ unsigned int h = cast(unsigned int, l); /* seed */ ++ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ ++ size_t l1; ++ for (l1=l; l1>=step; l1-=step) /* compute hash */ ++ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); ++ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; ++ o != NULL; ++ o = o->gch.next) { ++ TString *ts = rawgco2ts(o); ++ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { ++ /* string may be dead */ ++ if (isdead(G(L), o)) changewhite(o); ++ return ts; ++ } ++ } ++ return newlstr(L, str, l, h); /* not found */ ++} ++ ++ ++Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { ++ Udata *u; ++ if (s > MAX_SIZET - sizeof(Udata)) ++ luaM_toobig(L); ++ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); ++ u->uv.marked = luaC_white(G(L)); /* is not finalized */ ++ u->uv.tt = LUA_TUSERDATA; ++ u->uv.len = s; ++ u->uv.metatable = NULL; ++ u->uv.env = e; ++ /* chain it on udata list (after main thread) */ ++ u->uv.next = G(L)->mainthread->next; ++ G(L)->mainthread->next = obj2gco(u); ++ return u; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstring.h +@@ -0,0 +1,31 @@ ++/* ++** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ ++** String table (keep all strings handled by Lua) ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lstring_h ++#define lstring_h ++ ++ ++#include "lgc.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) ++ ++#define sizeudata(u) (sizeof(union Udata)+(u)->len) ++ ++#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) ++#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ ++ (sizeof(s)/sizeof(char))-1)) ++ ++#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) ++ ++LUAI_FUNC void luaS_resize (lua_State *L, int newsize); ++LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); ++LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lstrlib.c +@@ -0,0 +1,883 @@ ++/* ++** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ ++** Standard library for string operations and pattern-matching ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define lstrlib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++/* macro to `unsign' a character */ ++#define uchar(c) ((unsigned char)(c)) ++ ++ ++ ++static int str_len (lua_State *L) { ++ size_t l; ++ luaL_checklstring(L, 1, &l); ++ lua_pushinteger(L, l); ++ return 1; ++} ++ ++ ++static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { ++ /* relative string position: negative means back from end */ ++ if (pos < 0) pos += (ptrdiff_t)len + 1; ++ return (pos >= 0) ? pos : 0; ++} ++ ++ ++static int str_sub (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); ++ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); ++ if (start < 1) start = 1; ++ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; ++ if (start <= end) ++ lua_pushlstring(L, s+start-1, end-start+1); ++ else lua_pushliteral(L, ""); ++ return 1; ++} ++ ++ ++static int str_reverse (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_reverse: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while (l--) luaL_addchar(b, s[l]); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int str_lower (lua_State *L) { ++ size_t l; ++ size_t i; ++ const char *s = luaL_checklstring(L, 1, &l); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_lower: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ for (i=0; i 0) ++ luaL_addlstring(b, s, l); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int str_byte (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); ++ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); ++ int n, i; ++ if (posi <= 0) posi = 1; ++ if ((size_t)pose > l) pose = l; ++ if (posi > pose) return 0; /* empty interval; return no values */ ++ n = (int)(pose - posi + 1); ++ if (posi + n <= pose) /* overflow? */ ++ luaL_error(L, "string slice too long"); ++ luaL_checkstack(L, n, "string slice too long"); ++ for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) ++ return luaL_error(ms->L, "invalid capture index"); ++ return l; ++} ++ ++ ++static int capture_to_close (MatchState *ms) { ++ int level = ms->level; ++ for (level--; level>=0; level--) ++ if (ms->capture[level].len == CAP_UNFINISHED) return level; ++ return luaL_error(ms->L, "invalid pattern capture"); ++} ++ ++ ++static const char *classend (MatchState *ms, const char *p) { ++ switch (*p++) { ++ case L_ESC: { ++ if (*p == '\0') ++ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); ++ return p+1; ++ } ++ case '[': { ++ if (*p == '^') p++; ++ do { /* look for a `]' */ ++ if (*p == '\0') ++ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); ++ if (*(p++) == L_ESC && *p != '\0') ++ p++; /* skip escapes (e.g. `%]') */ ++ } while (*p != ']'); ++ return p+1; ++ } ++ default: { ++ return p; ++ } ++ } ++} ++ ++ ++static int match_class (int c, int cl) { ++ int res; ++ switch (tolower(cl)) { ++ case 'a' : res = isalpha(c); break; ++ case 'c' : res = iscntrl(c); break; ++ case 'd' : res = isdigit(c); break; ++ case 'l' : res = islower(c); break; ++ case 'p' : res = ispunct(c); break; ++ case 's' : res = isspace(c); break; ++ case 'u' : res = isupper(c); break; ++ case 'w' : res = isalnum(c); break; ++ case 'x' : res = isxdigit(c); break; ++ case 'z' : res = (c == 0); break; ++ default: return (cl == c); ++ } ++ return (islower(cl) ? res : !res); ++} ++ ++ ++static int matchbracketclass (int c, const char *p, const char *ec) { ++ int sig = 1; ++ if (*(p+1) == '^') { ++ sig = 0; ++ p++; /* skip the `^' */ ++ } ++ while (++p < ec) { ++ if (*p == L_ESC) { ++ p++; ++ if (match_class(c, uchar(*p))) ++ return sig; ++ } ++ else if ((*(p+1) == '-') && (p+2 < ec)) { ++ p+=2; ++ if (uchar(*(p-2)) <= c && c <= uchar(*p)) ++ return sig; ++ } ++ else if (uchar(*p) == c) return sig; ++ } ++ return !sig; ++} ++ ++ ++static int singlematch (int c, const char *p, const char *ep) { ++ switch (*p) { ++ case '.': return 1; /* matches any char */ ++ case L_ESC: return match_class(c, uchar(*(p+1))); ++ case '[': return matchbracketclass(c, p, ep-1); ++ default: return (uchar(*p) == c); ++ } ++} ++ ++ ++static const char *match (MatchState *ms, const char *s, const char *p); ++ ++ ++static const char *matchbalance (MatchState *ms, const char *s, ++ const char *p) { ++ if (*p == 0 || *(p+1) == 0) ++ luaL_error(ms->L, "unbalanced pattern"); ++ if (*s != *p) return NULL; ++ else { ++ int b = *p; ++ int e = *(p+1); ++ int cont = 1; ++ while (++s < ms->src_end) { ++ if (*s == e) { ++ if (--cont == 0) return s+1; ++ } ++ else if (*s == b) cont++; ++ } ++ } ++ return NULL; /* string ends out of balance */ ++} ++ ++ ++static const char *max_expand (MatchState *ms, const char *s, ++ const char *p, const char *ep) { ++ ptrdiff_t i = 0; /* counts maximum expand for item */ ++ while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) ++ i++; ++ /* keeps trying to match with the maximum repetitions */ ++ while (i>=0) { ++ const char *res = match(ms, (s+i), ep+1); ++ if (res) return res; ++ i--; /* else didn't match; reduce 1 repetition to try again */ ++ } ++ return NULL; ++} ++ ++ ++static const char *min_expand (MatchState *ms, const char *s, ++ const char *p, const char *ep) { ++ for (;;) { ++ const char *res = match(ms, s, ep+1); ++ if (res != NULL) ++ return res; ++ else if (ssrc_end && singlematch(uchar(*s), p, ep)) ++ s++; /* try with one more repetition */ ++ else return NULL; ++ } ++} ++ ++ ++static const char *start_capture (MatchState *ms, const char *s, ++ const char *p, int what) { ++ const char *res; ++ int level = ms->level; ++ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); ++ ms->capture[level].init = s; ++ ms->capture[level].len = what; ++ ms->level = level+1; ++ if ((res=match(ms, s, p)) == NULL) /* match failed? */ ++ ms->level--; /* undo capture */ ++ return res; ++} ++ ++ ++static const char *end_capture (MatchState *ms, const char *s, ++ const char *p) { ++ int l = capture_to_close(ms); ++ const char *res; ++ ms->capture[l].len = s - ms->capture[l].init; /* close capture */ ++ if ((res = match(ms, s, p)) == NULL) /* match failed? */ ++ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ ++ return res; ++} ++ ++ ++static const char *match_capture (MatchState *ms, const char *s, int l) { ++ size_t len; ++ l = check_capture(ms, l); ++ len = ms->capture[l].len; ++ if ((size_t)(ms->src_end-s) >= len && ++ memcmp(ms->capture[l].init, s, len) == 0) ++ return s+len; ++ else return NULL; ++} ++ ++ ++static const char *match (MatchState *ms, const char *s, const char *p) { ++ init: /* using goto's to optimize tail recursion */ ++ switch (*p) { ++ case '(': { /* start capture */ ++ if (*(p+1) == ')') /* position capture? */ ++ return start_capture(ms, s, p+2, CAP_POSITION); ++ else ++ return start_capture(ms, s, p+1, CAP_UNFINISHED); ++ } ++ case ')': { /* end capture */ ++ return end_capture(ms, s, p+1); ++ } ++ case L_ESC: { ++ switch (*(p+1)) { ++ case 'b': { /* balanced string? */ ++ s = matchbalance(ms, s, p+2); ++ if (s == NULL) return NULL; ++ p+=4; goto init; /* else return match(ms, s, p+4); */ ++ } ++ case 'f': { /* frontier? */ ++ const char *ep; char previous; ++ p += 2; ++ if (*p != '[') ++ luaL_error(ms->L, "missing " LUA_QL("[") " after " ++ LUA_QL("%%f") " in pattern"); ++ ep = classend(ms, p); /* points to what is next */ ++ previous = (s == ms->src_init) ? '\0' : *(s-1); ++ if (matchbracketclass(uchar(previous), p, ep-1) || ++ !matchbracketclass(uchar(*s), p, ep-1)) return NULL; ++ p=ep; goto init; /* else return match(ms, s, ep); */ ++ } ++ default: { ++ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ ++ s = match_capture(ms, s, uchar(*(p+1))); ++ if (s == NULL) return NULL; ++ p+=2; goto init; /* else return match(ms, s, p+2) */ ++ } ++ goto dflt; /* case default */ ++ } ++ } ++ } ++ case '\0': { /* end of pattern */ ++ return s; /* match succeeded */ ++ } ++ case '$': { ++ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ ++ return (s == ms->src_end) ? s : NULL; /* check end of string */ ++ else goto dflt; ++ } ++ default: dflt: { /* it is a pattern item */ ++ const char *ep = classend(ms, p); /* points to what is next */ ++ int m = ssrc_end && singlematch(uchar(*s), p, ep); ++ switch (*ep) { ++ case '?': { /* optional */ ++ const char *res; ++ if (m && ((res=match(ms, s+1, ep+1)) != NULL)) ++ return res; ++ p=ep+1; goto init; /* else return match(ms, s, ep+1); */ ++ } ++ case '*': { /* 0 or more repetitions */ ++ return max_expand(ms, s, p, ep); ++ } ++ case '+': { /* 1 or more repetitions */ ++ return (m ? max_expand(ms, s+1, p, ep) : NULL); ++ } ++ case '-': { /* 0 or more repetitions (minimum) */ ++ return min_expand(ms, s, p, ep); ++ } ++ default: { ++ if (!m) return NULL; ++ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ ++ } ++ } ++ } ++ } ++} ++ ++ ++ ++static const char *lmemfind (const char *s1, size_t l1, ++ const char *s2, size_t l2) { ++ if (l2 == 0) return s1; /* empty strings are everywhere */ ++ else if (l2 > l1) return NULL; /* avoids a negative `l1' */ ++ else { ++ const char *init; /* to search for a `*s2' inside `s1' */ ++ l2--; /* 1st char will be checked by `memchr' */ ++ l1 = l1-l2; /* `s2' cannot be found after that */ ++ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { ++ init++; /* 1st char is already checked */ ++ if (memcmp(init, s2+1, l2) == 0) ++ return init-1; ++ else { /* correct `l1' and `s1' to try again */ ++ l1 -= init-s1; ++ s1 = init; ++ } ++ } ++ return NULL; /* not found */ ++ } ++} ++ ++ ++static void push_onecapture (MatchState *ms, int i, const char *s, ++ const char *e) { ++ if (i >= ms->level) { ++ if (i == 0) /* ms->level == 0, too */ ++ lua_pushlstring(ms->L, s, e - s); /* add whole match */ ++ else ++ luaL_error(ms->L, "invalid capture index"); ++ } ++ else { ++ ptrdiff_t l = ms->capture[i].len; ++ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); ++ if (l == CAP_POSITION) ++ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); ++ else ++ lua_pushlstring(ms->L, ms->capture[i].init, l); ++ } ++} ++ ++ ++static int push_captures (MatchState *ms, const char *s, const char *e) { ++ int i; ++ int nlevels = (ms->level == 0 && s) ? 1 : ms->level; ++ luaL_checkstack(ms->L, nlevels, "too many captures"); ++ for (i = 0; i < nlevels; i++) ++ push_onecapture(ms, i, s, e); ++ return nlevels; /* number of strings pushed */ ++} ++ ++ ++static int str_find_aux (lua_State *L, int find) { ++ size_t l1, l2; ++ const char *s = luaL_checklstring(L, 1, &l1); ++ const char *p = luaL_checklstring(L, 2, &l2); ++ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; ++ if (init < 0) init = 0; ++ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; ++ if (find && (lua_toboolean(L, 4) || /* explicit request? */ ++ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ ++ /* do a plain search */ ++ const char *s2 = lmemfind(s+init, l1-init, p, l2); ++ if (s2) { ++ lua_pushinteger(L, s2-s+1); ++ lua_pushinteger(L, s2-s+l2); ++ return 2; ++ } ++ } ++ else { ++ MatchState ms; ++ int anchor = (*p == '^') ? (p++, 1) : 0; ++ const char *s1=s+init; ++ ms.L = L; ++ ms.src_init = s; ++ ms.src_end = s+l1; ++ do { ++ const char *res; ++ ms.level = 0; ++ if ((res=match(&ms, s1, p)) != NULL) { ++ if (find) { ++ lua_pushinteger(L, s1-s+1); /* start */ ++ lua_pushinteger(L, res-s); /* end */ ++ return push_captures(&ms, NULL, 0) + 2; ++ } ++ else ++ return push_captures(&ms, s1, res); ++ } ++ } while (s1++ < ms.src_end && !anchor); ++ } ++ lua_pushnil(L); /* not found */ ++ return 1; ++} ++ ++ ++static int str_find (lua_State *L) { ++ return str_find_aux(L, 1); ++} ++ ++ ++static int str_match (lua_State *L) { ++ return str_find_aux(L, 0); ++} ++ ++ ++static int gmatch_aux (lua_State *L) { ++ MatchState ms; ++ size_t ls; ++ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); ++ const char *p = lua_tostring(L, lua_upvalueindex(2)); ++ const char *src; ++ ms.L = L; ++ ms.src_init = s; ++ ms.src_end = s+ls; ++ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); ++ src <= ms.src_end; ++ src++) { ++ const char *e; ++ ms.level = 0; ++ if ((e = match(&ms, src, p)) != NULL) { ++ lua_Integer newstart = e-s; ++ if (e == src) newstart++; /* empty match? go at least one position */ ++ lua_pushinteger(L, newstart); ++ lua_replace(L, lua_upvalueindex(3)); ++ return push_captures(&ms, src, e); ++ } ++ } ++ return 0; /* not found */ ++} ++ ++ ++static int gmatch (lua_State *L) { ++ luaL_checkstring(L, 1); ++ luaL_checkstring(L, 2); ++ lua_settop(L, 2); ++ lua_pushinteger(L, 0); ++ lua_pushcclosure(L, gmatch_aux, 3); ++ return 1; ++} ++ ++ ++static int gfind_nodef (lua_State *L) { ++ return luaL_error(L, LUA_QL("string.gfind") " was renamed to " ++ LUA_QL("string.gmatch")); ++} ++ ++ ++static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, ++ const char *e) { ++ size_t l, i; ++ const char *news = lua_tolstring(ms->L, 3, &l); ++ for (i = 0; i < l; i++) { ++ if (news[i] != L_ESC) ++ luaL_addchar(b, news[i]); ++ else { ++ i++; /* skip ESC */ ++ if (!isdigit(uchar(news[i]))) ++ luaL_addchar(b, news[i]); ++ else if (news[i] == '0') ++ luaL_addlstring(b, s, e - s); ++ else { ++ push_onecapture(ms, news[i] - '1', s, e); ++ luaL_addvalue(b); /* add capture to accumulated result */ ++ } ++ } ++ } ++} ++ ++ ++static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, ++ const char *e) { ++ lua_State *L = ms->L; ++ switch (lua_type(L, 3)) { ++ case LUA_TNUMBER: ++ case LUA_TSTRING: { ++ add_s(ms, b, s, e); ++ return; ++ } ++ case LUA_TFUNCTION: { ++ int n; ++ lua_pushvalue(L, 3); ++ n = push_captures(ms, s, e); ++ lua_call(L, n, 1); ++ break; ++ } ++ case LUA_TTABLE: { ++ push_onecapture(ms, 0, s, e); ++ lua_gettable(L, 3); ++ break; ++ } ++ } ++ if (!lua_toboolean(L, -1)) { /* nil or false? */ ++ lua_pop(L, 1); ++ lua_pushlstring(L, s, e - s); /* keep original text */ ++ } ++ else if (!lua_isstring(L, -1)) ++ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); ++ luaL_addvalue(b); /* add result to accumulator */ ++} ++ ++ ++static int str_gsub (lua_State *L) { ++ size_t srcl; ++ const char *src = luaL_checklstring(L, 1, &srcl); ++ const char *p = luaL_checkstring(L, 2); ++ int tr = lua_type(L, 3); ++ int max_s = luaL_optint(L, 4, srcl+1); ++ int anchor = (*p == '^') ? (p++, 1) : 0; ++ int n = 0; ++ MatchState ms; ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_gsub: cannot allocate memory"); ++ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || ++ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, ++ "string/function/table expected"); ++ luaL_buffinit(L, b); ++ ms.L = L; ++ ms.src_init = src; ++ ms.src_end = src+srcl; ++ while (n < max_s) { ++ const char *e; ++ ms.level = 0; ++ e = match(&ms, src, p); ++ if (e) { ++ n++; ++ add_value(&ms, b, src, e); ++ } ++ if (e && e>src) /* non empty match? */ ++ src = e; /* skip it */ ++ else if (src < ms.src_end) ++ luaL_addchar(b, *src++); ++ else break; ++ if (anchor) break; ++ } ++ luaL_addlstring(b, src, ms.src_end-src); ++ luaL_pushresult(b); ++ lua_pushinteger(L, n); /* number of substitutions */ ++ kfree(b); ++ return 2; ++} ++ ++/* }====================================================== */ ++ ++ ++/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ ++#define MAX_ITEM 512 ++/* valid flags in a format specification */ ++#define FLAGS "-+ #0" ++/* ++** maximum size of each format specification (such as '%-099.99d') ++** (+10 accounts for %99.99x plus margin of error) ++*/ ++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) ++ ++ ++static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { ++ size_t l; ++ const char *s = luaL_checklstring(L, arg, &l); ++ luaL_addchar(b, '"'); ++ while (l--) { ++ switch (*s) { ++ case '"': case '\\': case '\n': { ++ luaL_addchar(b, '\\'); ++ luaL_addchar(b, *s); ++ break; ++ } ++ case '\r': { ++ luaL_addlstring(b, "\\r", 2); ++ break; ++ } ++ case '\0': { ++ luaL_addlstring(b, "\\000", 4); ++ break; ++ } ++ default: { ++ luaL_addchar(b, *s); ++ break; ++ } ++ } ++ s++; ++ } ++ luaL_addchar(b, '"'); ++} ++ ++static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { ++ const char *p = strfrmt; ++ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ ++ if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) ++ luaL_error(L, "invalid format (repeated flags)"); ++ if (isdigit(uchar(*p))) p++; /* skip width */ ++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ ++ if (*p == '.') { ++ p++; ++ if (isdigit(uchar(*p))) p++; /* skip precision */ ++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ ++ } ++ if (isdigit(uchar(*p))) ++ luaL_error(L, "invalid format (width or precision too long)"); ++ *(form++) = '%'; ++ strncpy(form, strfrmt, p - strfrmt + 1); ++ form += p - strfrmt + 1; ++ *form = '\0'; ++ return p; ++} ++ ++ ++static void addintlen (char *form) { ++ size_t l = strlen(form); ++ char spec = form[l - 1]; ++ strcpy(form + l - 1, LUA_INTFRMLEN); ++ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; ++ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; ++} ++ ++ ++static int str_format (lua_State *L) { ++ int arg = 1; ++ size_t sfl; ++ const char *strfrmt = luaL_checklstring(L, arg, &sfl); ++ const char *strfrmt_end = strfrmt+sfl; ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_format: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while (strfrmt < strfrmt_end) { ++ if (*strfrmt != L_ESC) ++ luaL_addchar(b, *strfrmt++); ++ else if (*++strfrmt == L_ESC) ++ luaL_addchar(b, *strfrmt++); /* %% */ ++ else { /* format item */ ++ char form[MAX_FORMAT]; /* to store the format (`%...') */ ++ char buff[MAX_ITEM]; /* to store the formatted item */ ++ arg++; ++ strfrmt = scanformat(L, strfrmt, form); ++ switch (*strfrmt++) { ++ case 'c': { ++ sprintf(buff, form, (int)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'd': case 'i': { ++ addintlen(form); ++ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'o': case 'u': case 'x': case 'X': { ++ addintlen(form); ++ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'q': { ++ addquoted(L, b, arg); ++ continue; /* skip the 'addsize' at the end */ ++ } ++ case 's': { ++ size_t l; ++ const char *s = luaL_checklstring(L, arg, &l); ++ if (!strchr(form, '.') && l >= 100) { ++ /* no precision and string is too long to be formatted; ++ keep original string */ ++ lua_pushvalue(L, arg); ++ luaL_addvalue(b); ++ continue; /* skip the `addsize' at the end */ ++ } ++ else { ++ sprintf(buff, form, s); ++ break; ++ } ++ } ++ default: { /* also treat cases `pnLlh' */ ++ kfree(b); ++ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " ++ LUA_QL("format"), *(strfrmt - 1)); ++ } ++ } ++ luaL_addlstring(b, buff, strlen(buff)); ++ } ++ } ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static const luaL_Reg strlib[] = { ++ {"byte", str_byte}, ++ {"char", str_char}, ++ {"dump", str_dump}, ++ {"find", str_find}, ++ {"format", str_format}, ++ {"gfind", gfind_nodef}, ++ {"gmatch", gmatch}, ++ {"gsub", str_gsub}, ++ {"len", str_len}, ++ {"lower", str_lower}, ++ {"match", str_match}, ++ {"rep", str_rep}, ++ {"reverse", str_reverse}, ++ {"sub", str_sub}, ++ {"upper", str_upper}, ++ {NULL, NULL} ++}; ++ ++ ++static void createmetatable (lua_State *L) { ++ lua_createtable(L, 0, 1); /* create metatable for strings */ ++ lua_pushliteral(L, ""); /* dummy string */ ++ lua_pushvalue(L, -2); ++ lua_setmetatable(L, -2); /* set string metatable */ ++ lua_pop(L, 1); /* pop dummy string */ ++ lua_pushvalue(L, -2); /* string library... */ ++ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ ++ lua_pop(L, 1); /* pop metatable */ ++} ++ ++ ++/* ++** Open string library ++*/ ++LUALIB_API int luaopen_string (lua_State *L) { ++ luaL_register(L, LUA_STRLIBNAME, strlib); ++#if defined(LUA_COMPAT_GFIND) ++ lua_getfield(L, -1, "gmatch"); ++ lua_setfield(L, -2, "gfind"); ++#endif ++ createmetatable(L); ++ return 1; ++} +--- /dev/null ++++ b/extensions/LUA/lua/ltable.c +@@ -0,0 +1,588 @@ ++/* ++** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ ++** Lua tables (hash) ++** See Copyright Notice in lua.h ++*/ ++ ++ ++/* ++** Implementation of tables (aka arrays, objects, or hash tables). ++** Tables keep its elements in two parts: an array part and a hash part. ++** Non-negative integer keys are all candidates to be kept in the array ++** part. The actual size of the array is the largest `n' such that at ++** least half the slots between 0 and n are in use. ++** Hash uses a mix of chained scatter table with Brent's variation. ++** A main invariant of these tables is that, if an element is not ++** in its main position (i.e. the `original' position that its hash gives ++** to it), then the colliding element is in its own main position. ++** Hence even when the load factor reaches 100%, performance remains good. ++*/ ++ ++#include ++#include ++ ++#define ltable_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "ltable.h" ++ ++ ++/* ++** max size of array part is 2^MAXBITS ++*/ ++#if LUAI_BITSINT > 26 ++#define MAXBITS 26 ++#else ++#define MAXBITS (LUAI_BITSINT-2) ++#endif ++ ++#define MAXASIZE (1 << MAXBITS) ++ ++ ++#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) ++ ++#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) ++#define hashboolean(t,p) hashpow2(t, p) ++ ++ ++/* ++** for some types, it is better to avoid modulus by power of 2, as ++** they tend to have many 2 factors. ++*/ ++#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) ++ ++ ++#define hashpointer(t,p) hashmod(t, IntPoint(p)) ++ ++ ++/* ++** number of ints inside a lua_Number ++*/ ++#define numints cast_int(sizeof(lua_Number)/sizeof(int)) ++ ++ ++ ++#define dummynode (&dummynode_) ++ ++static const Node dummynode_ = { ++ {{NULL}, LUA_TNIL}, /* value */ ++ {{{NULL}, LUA_TNIL, NULL}} /* key */ ++}; ++ ++ ++/* ++** hash for lua_Numbers ++*/ ++static Node *hashnum (const Table *t, lua_Number n) { ++ unsigned int a[numints]; ++ int i; ++ if (luai_numeq(n, 0)) /* avoid problems with -0 */ ++ return gnode(t, 0); ++ memcpy(a, &n, sizeof(a)); ++ for (i = 1; i < numints; i++) a[0] += a[i]; ++ return hashmod(t, a[0]); ++} ++ ++ ++ ++/* ++** returns the `main' position of an element in a table (that is, the index ++** of its hash value) ++*/ ++static Node *mainposition (const Table *t, const TValue *key) { ++ switch (ttype(key)) { ++ case LUA_TNUMBER: ++ return hashnum(t, nvalue(key)); ++ case LUA_TSTRING: ++ return hashstr(t, rawtsvalue(key)); ++ case LUA_TBOOLEAN: ++ return hashboolean(t, bvalue(key)); ++ case LUA_TLIGHTUSERDATA: ++ return hashpointer(t, pvalue(key)); ++ default: ++ return hashpointer(t, gcvalue(key)); ++ } ++} ++ ++ ++/* ++** returns the index for `key' if `key' is an appropriate key to live in ++** the array part of the table, -1 otherwise. ++*/ ++static int arrayindex (const TValue *key) { ++ if (ttisnumber(key)) { ++ lua_Number n = nvalue(key); ++ int k; ++ lua_number2int(k, n); ++ if (luai_numeq(cast_num(k), n)) ++ return k; ++ } ++ return -1; /* `key' did not match some condition */ ++} ++ ++ ++/* ++** returns the index of a `key' for table traversals. First goes all ++** elements in the array part, then elements in the hash part. The ++** beginning of a traversal is signalled by -1. ++*/ ++static int findindex (lua_State *L, Table *t, StkId key) { ++ int i; ++ if (ttisnil(key)) return -1; /* first iteration */ ++ i = arrayindex(key); ++ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ ++ return i-1; /* yes; that's the index (corrected to C) */ ++ else { ++ Node *n = mainposition(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ /* key may be dead already, but it is ok to use it in `next' */ ++ if (luaO_rawequalObj(key2tval(n), key) || ++ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && ++ gcvalue(gkey(n)) == gcvalue(key))) { ++ i = cast_int(n - gnode(t, 0)); /* key index in hash table */ ++ /* hash elements are numbered after array ones */ ++ return i + t->sizearray; ++ } ++ else n = gnext(n); ++ } while (n); ++ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ ++ return 0; /* to avoid warnings */ ++ } ++} ++ ++ ++int luaH_next (lua_State *L, Table *t, StkId key) { ++ int i = findindex(L, t, key); /* find original element */ ++ for (i++; i < t->sizearray; i++) { /* try first array part */ ++ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ ++ setnvalue(key, cast_num(i+1)); ++ setobj2s(L, key+1, &t->array[i]); ++ return 1; ++ } ++ } ++ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ ++ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ ++ setobj2s(L, key, key2tval(gnode(t, i))); ++ setobj2s(L, key+1, gval(gnode(t, i))); ++ return 1; ++ } ++ } ++ return 0; /* no more elements */ ++} ++ ++ ++/* ++** {============================================================= ++** Rehash ++** ============================================================== ++*/ ++ ++ ++static int computesizes (int nums[], int *narray) { ++ int i; ++ int twotoi; /* 2^i */ ++ int a = 0; /* number of elements smaller than 2^i */ ++ int na = 0; /* number of elements to go to array part */ ++ int n = 0; /* optimal size for array part */ ++ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { ++ if (nums[i] > 0) { ++ a += nums[i]; ++ if (a > twotoi/2) { /* more than half elements present? */ ++ n = twotoi; /* optimal size (till now) */ ++ na = a; /* all elements smaller than n will go to array part */ ++ } ++ } ++ if (a == *narray) break; /* all elements already counted */ ++ } ++ *narray = n; ++ lua_assert(*narray/2 <= na && na <= *narray); ++ return na; ++} ++ ++ ++static int countint (const TValue *key, int *nums) { ++ int k = arrayindex(key); ++ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ ++ nums[ceillog2(k)]++; /* count as such */ ++ return 1; ++ } ++ else ++ return 0; ++} ++ ++ ++static int numusearray (const Table *t, int *nums) { ++ int lg; ++ int ttlg; /* 2^lg */ ++ int ause = 0; /* summation of `nums' */ ++ int i = 1; /* count to traverse all array keys */ ++ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ ++ int lc = 0; /* counter */ ++ int lim = ttlg; ++ if (lim > t->sizearray) { ++ lim = t->sizearray; /* adjust upper limit */ ++ if (i > lim) ++ break; /* no more elements to count */ ++ } ++ /* count elements in range (2^(lg-1), 2^lg] */ ++ for (; i <= lim; i++) { ++ if (!ttisnil(&t->array[i-1])) ++ lc++; ++ } ++ nums[lg] += lc; ++ ause += lc; ++ } ++ return ause; ++} ++ ++ ++static int numusehash (const Table *t, int *nums, int *pnasize) { ++ int totaluse = 0; /* total number of elements */ ++ int ause = 0; /* summation of `nums' */ ++ int i = sizenode(t); ++ while (i--) { ++ Node *n = &t->node[i]; ++ if (!ttisnil(gval(n))) { ++ ause += countint(key2tval(n), nums); ++ totaluse++; ++ } ++ } ++ *pnasize += ause; ++ return totaluse; ++} ++ ++ ++static void setarrayvector (lua_State *L, Table *t, int size) { ++ int i; ++ luaM_reallocvector(L, t->array, t->sizearray, size, TValue); ++ for (i=t->sizearray; iarray[i]); ++ t->sizearray = size; ++} ++ ++ ++static void setnodevector (lua_State *L, Table *t, int size) { ++ int lsize; ++ if (size == 0) { /* no elements to hash part? */ ++ t->node = cast(Node *, dummynode); /* use common `dummynode' */ ++ lsize = 0; ++ } ++ else { ++ int i; ++ lsize = ceillog2(size); ++ if (lsize > MAXBITS) ++ luaG_runerror(L, "table overflow"); ++ size = twoto(lsize); ++ t->node = luaM_newvector(L, size, Node); ++ for (i=0; ilsizenode = cast_byte(lsize); ++ t->lastfree = gnode(t, size); /* all positions are free */ ++} ++ ++ ++static void resize (lua_State *L, Table *t, int nasize, int nhsize) { ++ int i; ++ int oldasize = t->sizearray; ++ int oldhsize = t->lsizenode; ++ Node *nold = t->node; /* save old hash ... */ ++ if (nasize > oldasize) /* array part must grow? */ ++ setarrayvector(L, t, nasize); ++ /* create new hash part with appropriate size */ ++ setnodevector(L, t, nhsize); ++ if (nasize < oldasize) { /* array part must shrink? */ ++ t->sizearray = nasize; ++ /* re-insert elements from vanishing slice */ ++ for (i=nasize; iarray[i])) ++ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); ++ } ++ /* shrink array */ ++ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); ++ } ++ /* re-insert elements from hash part */ ++ for (i = twoto(oldhsize) - 1; i >= 0; i--) { ++ Node *old = nold+i; ++ if (!ttisnil(gval(old))) ++ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); ++ } ++ if (nold != dummynode) ++ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ ++} ++ ++ ++void luaH_resizearray (lua_State *L, Table *t, int nasize) { ++ int nsize = (t->node == dummynode) ? 0 : sizenode(t); ++ resize(L, t, nasize, nsize); ++} ++ ++ ++static void rehash (lua_State *L, Table *t, const TValue *ek) { ++ int nasize, na; ++ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ ++ int i; ++ int totaluse; ++ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ ++ nasize = numusearray(t, nums); /* count keys in array part */ ++ totaluse = nasize; /* all those keys are integer keys */ ++ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ ++ /* count extra key */ ++ nasize += countint(ek, nums); ++ totaluse++; ++ /* compute new size for array part */ ++ na = computesizes(nums, &nasize); ++ /* resize the table to new computed sizes */ ++ resize(L, t, nasize, totaluse - na); ++} ++ ++ ++ ++/* ++** }============================================================= ++*/ ++ ++ ++Table *luaH_new (lua_State *L, int narray, int nhash) { ++ Table *t = luaM_new(L, Table); ++ luaC_link(L, obj2gco(t), LUA_TTABLE); ++ t->metatable = NULL; ++ t->flags = cast_byte(~0); ++ /* temporary values (kept only if some malloc fails) */ ++ t->array = NULL; ++ t->sizearray = 0; ++ t->lsizenode = 0; ++ t->node = cast(Node *, dummynode); ++ setarrayvector(L, t, narray); ++ setnodevector(L, t, nhash); ++ return t; ++} ++ ++ ++void luaH_free (lua_State *L, Table *t) { ++ if (t->node != dummynode) ++ luaM_freearray(L, t->node, sizenode(t), Node); ++ luaM_freearray(L, t->array, t->sizearray, TValue); ++ luaM_free(L, t); ++} ++ ++ ++static Node *getfreepos (Table *t) { ++ while (t->lastfree-- > t->node) { ++ if (ttisnil(gkey(t->lastfree))) ++ return t->lastfree; ++ } ++ return NULL; /* could not find a free place */ ++} ++ ++ ++ ++/* ++** inserts a new key into a hash table; first, check whether key's main ++** position is free. If not, check whether colliding node is in its main ++** position or not: if it is not, move colliding node to an empty place and ++** put new key in its main position; otherwise (colliding node is in its main ++** position), new key goes to an empty position. ++*/ ++static TValue *newkey (lua_State *L, Table *t, const TValue *key) { ++ Node *mp = mainposition(t, key); ++ if (!ttisnil(gval(mp)) || mp == dummynode) { ++ Node *othern; ++ Node *n = getfreepos(t); /* get a free place */ ++ if (n == NULL) { /* cannot find a free place? */ ++ rehash(L, t, key); /* grow table */ ++ return luaH_set(L, t, key); /* re-insert key into grown table */ ++ } ++ lua_assert(n != dummynode); ++ othern = mainposition(t, key2tval(mp)); ++ if (othern != mp) { /* is colliding node out of its main position? */ ++ /* yes; move colliding node into free position */ ++ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ ++ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ ++ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ ++ gnext(mp) = NULL; /* now `mp' is free */ ++ setnilvalue(gval(mp)); ++ } ++ else { /* colliding node is in its own main position */ ++ /* new node will go into free position */ ++ gnext(n) = gnext(mp); /* chain new position */ ++ gnext(mp) = n; ++ mp = n; ++ } ++ } ++ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; ++ luaC_barriert(L, t, key); ++ lua_assert(ttisnil(gval(mp))); ++ return gval(mp); ++} ++ ++ ++/* ++** search function for integers ++*/ ++const TValue *luaH_getnum (Table *t, int key) { ++ /* (1 <= key && key <= t->sizearray) */ ++ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) ++ return &t->array[key-1]; ++ else { ++ lua_Number nk = cast_num(key); ++ Node *n = hashnum(t, nk); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++ } ++} ++ ++ ++/* ++** search function for strings ++*/ ++const TValue *luaH_getstr (Table *t, TString *key) { ++ Node *n = hashstr(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++} ++ ++ ++/* ++** main search function ++*/ ++const TValue *luaH_get (Table *t, const TValue *key) { ++ switch (ttype(key)) { ++ case LUA_TNIL: return luaO_nilobject; ++ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); ++ case LUA_TNUMBER: { ++ int k; ++ lua_Number n = nvalue(key); ++ lua_number2int(k, n); ++ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ ++ return luaH_getnum(t, k); /* use specialized version */ ++ /* else go through */ ++ } ++ default: { ++ Node *n = mainposition(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (luaO_rawequalObj(key2tval(n), key)) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++ } ++ } ++} ++ ++ ++TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { ++ const TValue *p = luaH_get(t, key); ++ t->flags = 0; ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ if (ttisnil(key)) luaG_runerror(L, "table index is nil"); ++ else if (ttisnumber(key) && luai_numisnan(nvalue(key))) ++ luaG_runerror(L, "table index is NaN"); ++ return newkey(L, t, key); ++ } ++} ++ ++ ++TValue *luaH_setnum (lua_State *L, Table *t, int key) { ++ const TValue *p = luaH_getnum(t, key); ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ TValue k; ++ setnvalue(&k, cast_num(key)); ++ return newkey(L, t, &k); ++ } ++} ++ ++ ++TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { ++ const TValue *p = luaH_getstr(t, key); ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ TValue k; ++ setsvalue(L, &k, key); ++ return newkey(L, t, &k); ++ } ++} ++ ++ ++static int unbound_search (Table *t, unsigned int j) { ++ unsigned int i = j; /* i is zero or a present index */ ++ j++; ++ /* find `i' and `j' such that i is present and j is not */ ++ while (!ttisnil(luaH_getnum(t, j))) { ++ i = j; ++ j *= 2; ++ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ ++ /* table was built with bad purposes: resort to linear search */ ++ i = 1; ++ while (!ttisnil(luaH_getnum(t, i))) i++; ++ return i - 1; ++ } ++ } ++ /* now do a binary search between them */ ++ while (j - i > 1) { ++ unsigned int m = (i+j)/2; ++ if (ttisnil(luaH_getnum(t, m))) j = m; ++ else i = m; ++ } ++ return i; ++} ++ ++ ++/* ++** Try to find a boundary in table `t'. A `boundary' is an integer index ++** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). ++*/ ++int luaH_getn (Table *t) { ++ unsigned int j = t->sizearray; ++ if (j > 0 && ttisnil(&t->array[j - 1])) { ++ /* there is a boundary in the array part: (binary) search for it */ ++ unsigned int i = 0; ++ while (j - i > 1) { ++ unsigned int m = (i+j)/2; ++ if (ttisnil(&t->array[m - 1])) j = m; ++ else i = m; ++ } ++ return i; ++ } ++ /* else must find a boundary in hash part */ ++ else if (t->node == dummynode) /* hash part is empty? */ ++ return j; /* that is easy... */ ++ else return unbound_search(t, j); ++} ++ ++ ++ ++#if defined(LUA_DEBUG) ++ ++Node *luaH_mainposition (const Table *t, const TValue *key) { ++ return mainposition(t, key); ++} ++ ++int luaH_isdummy (Node *n) { return n == dummynode; } ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ltable.h +@@ -0,0 +1,40 @@ ++/* ++** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua tables (hash) ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ltable_h ++#define ltable_h ++ ++#include "lobject.h" ++ ++ ++#define gnode(t,i) (&(t)->node[i]) ++#define gkey(n) (&(n)->i_key.nk) ++#define gval(n) (&(n)->i_val) ++#define gnext(n) ((n)->i_key.nk.next) ++ ++#define key2tval(n) (&(n)->i_key.tvk) ++ ++ ++LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); ++LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); ++LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); ++LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); ++LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); ++LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); ++LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); ++LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); ++LUAI_FUNC void luaH_free (lua_State *L, Table *t); ++LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); ++LUAI_FUNC int luaH_getn (Table *t); ++ ++ ++#if defined(LUA_DEBUG) ++LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); ++LUAI_FUNC int luaH_isdummy (Node *n); ++#endif ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ltablib.c +@@ -0,0 +1,288 @@ ++/* ++** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ ++** Library for Table Manipulation ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define ltablib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) ++ ++ ++static int foreachi (lua_State *L) { ++ int i; ++ int n = aux_getn(L, 1); ++ luaL_checktype(L, 2, LUA_TFUNCTION); ++ for (i=1; i <= n; i++) { ++ lua_pushvalue(L, 2); /* function */ ++ lua_pushinteger(L, i); /* 1st argument */ ++ lua_rawgeti(L, 1, i); /* 2nd argument */ ++ lua_call(L, 2, 1); ++ if (!lua_isnil(L, -1)) ++ return 1; ++ lua_pop(L, 1); /* remove nil result */ ++ } ++ return 0; ++} ++ ++ ++static int foreach (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checktype(L, 2, LUA_TFUNCTION); ++ lua_pushnil(L); /* first key */ ++ while (lua_next(L, 1)) { ++ lua_pushvalue(L, 2); /* function */ ++ lua_pushvalue(L, -3); /* key */ ++ lua_pushvalue(L, -3); /* value */ ++ lua_call(L, 2, 1); ++ if (!lua_isnil(L, -1)) ++ return 1; ++ lua_pop(L, 2); /* remove value and result */ ++ } ++ return 0; ++} ++ ++ ++static int maxn (lua_State *L) { ++ lua_Number max = 0; ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushnil(L); /* first key */ ++ while (lua_next(L, 1)) { ++ lua_pop(L, 1); /* remove value */ ++ if (lua_type(L, -1) == LUA_TNUMBER) { ++ lua_Number v = lua_tonumber(L, -1); ++ if (v > max) max = v; ++ } ++ } ++ lua_pushnumber(L, max); ++ return 1; ++} ++ ++ ++static int getn (lua_State *L) { ++ lua_pushinteger(L, aux_getn(L, 1)); ++ return 1; ++} ++ ++ ++static int setn (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++#ifndef luaL_setn ++ luaL_setn(L, 1, luaL_checkint(L, 2)); ++#else ++ luaL_error(L, LUA_QL("setn") " is obsolete"); ++#endif ++ lua_pushvalue(L, 1); ++ return 1; ++} ++ ++ ++static int tinsert (lua_State *L) { ++ int e = aux_getn(L, 1) + 1; /* first empty element */ ++ int pos; /* where to insert new element */ ++ switch (lua_gettop(L)) { ++ case 2: { /* called with only 2 arguments */ ++ pos = e; /* insert new element at the end */ ++ break; ++ } ++ case 3: { ++ int i; ++ pos = luaL_checkint(L, 2); /* 2nd argument is the position */ ++ if (pos > e) e = pos; /* `grow' array if necessary */ ++ for (i = e; i > pos; i--) { /* move up elements */ ++ lua_rawgeti(L, 1, i-1); ++ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ ++ } ++ break; ++ } ++ default: { ++ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); ++ } ++ } ++ luaL_setn(L, 1, e); /* new size */ ++ lua_rawseti(L, 1, pos); /* t[pos] = v */ ++ return 0; ++} ++ ++ ++static int tremove (lua_State *L) { ++ int e = aux_getn(L, 1); ++ int pos = luaL_optint(L, 2, e); ++ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ ++ return 0; /* nothing to remove */ ++ luaL_setn(L, 1, e - 1); /* t.n = n-1 */ ++ lua_rawgeti(L, 1, pos); /* result = t[pos] */ ++ for ( ;pos= P */ ++ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { ++ if (i>u) luaL_error(L, "invalid order function for sorting"); ++ lua_pop(L, 1); /* remove a[i] */ ++ } ++ /* repeat --j until a[j] <= P */ ++ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { ++ if (j ++ ++#define ltm_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++ ++const char *const luaT_typenames[] = { ++ "nil", "boolean", "userdata", "number", ++ "string", "table", "function", "userdata", "thread", ++ "proto", "upval" ++}; ++ ++ ++void luaT_init (lua_State *L) { ++ static const char *const luaT_eventname[] = { /* ORDER TM */ ++ "__index", "__newindex", ++ "__gc", "__mode", "__eq", ++ "__add", "__sub", "__mul", "__div", "__mod", ++ "__pow", "__unm", "__len", "__lt", "__le", ++ "__concat", "__call" ++ }; ++ int i; ++ for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); ++ luaS_fix(G(L)->tmname[i]); /* never collect these names */ ++ } ++} ++ ++ ++/* ++** function to be used with macro "fasttm": optimized for absence of ++** tag methods ++*/ ++const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { ++ const TValue *tm = luaH_getstr(events, ename); ++ lua_assert(event <= TM_EQ); ++ if (ttisnil(tm)) { /* no tag method? */ ++ events->flags |= cast_byte(1u<metatable; ++ break; ++ case LUA_TUSERDATA: ++ mt = uvalue(o)->metatable; ++ break; ++ default: ++ mt = G(L)->mt[ttype(o)]; ++ } ++ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ltm.h +@@ -0,0 +1,54 @@ ++/* ++** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Tag methods ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ltm_h ++#define ltm_h ++ ++ ++#include "lobject.h" ++ ++ ++/* ++* WARNING: if you change the order of this enumeration, ++* grep "ORDER TM" ++*/ ++typedef enum { ++ TM_INDEX, ++ TM_NEWINDEX, ++ TM_GC, ++ TM_MODE, ++ TM_EQ, /* last tag method with `fast' access */ ++ TM_ADD, ++ TM_SUB, ++ TM_MUL, ++ TM_DIV, ++ TM_MOD, ++ TM_POW, ++ TM_UNM, ++ TM_LEN, ++ TM_LT, ++ TM_LE, ++ TM_CONCAT, ++ TM_CALL, ++ TM_N /* number of elements in the enum */ ++} TMS; ++ ++ ++ ++#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ ++ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) ++ ++#define fasttm(l,et,e) gfasttm(G(l), et, e) ++ ++LUAI_DATA const char *const luaT_typenames[]; ++ ++ ++LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); ++LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, ++ TMS event); ++LUAI_FUNC void luaT_init (lua_State *L); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/luaconf.h +@@ -0,0 +1,797 @@ ++/* ++** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ ++** Configuration file for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lconfig_h ++#define lconfig_h ++ ++#include ++ ++#if !defined(__KERNEL__) ++#include ++#else ++#define UCHAR_MAX 255 ++#define SHRT_MAX 32767 ++#define BUFSIZ 8192 ++#define NO_FPU ++#endif ++ ++/* ++** ================================================================== ++** Search for "@@" to find all configurable definitions. ++** =================================================================== ++*/ ++ ++ ++/* ++@@ LUA_ANSI controls the use of non-ansi features. ++** CHANGE it (define it) if you want Lua to avoid the use of any ++** non-ansi feature or library. ++*/ ++#if defined(__STRICT_ANSI__) ++#define LUA_ANSI ++#endif ++ ++ ++#if !defined(LUA_ANSI) && defined(_WIN32) ++#define LUA_WIN ++#endif ++ ++#if defined(LUA_USE_LINUX) ++#define LUA_USE_POSIX ++#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ ++#define LUA_USE_READLINE /* needs some extra libraries */ ++#endif ++ ++#if defined(LUA_USE_MACOSX) ++#define LUA_USE_POSIX ++#define LUA_DL_DYLD /* does not need extra library */ ++#endif ++ ++ ++ ++/* ++@@ LUA_USE_POSIX includes all functionallity listed as X/Open System ++@* Interfaces Extension (XSI). ++** CHANGE it (define it) if your system is XSI compatible. ++*/ ++#if defined(LUA_USE_POSIX) ++#define LUA_USE_MKSTEMP ++#define LUA_USE_ISATTY ++#define LUA_USE_POPEN ++#define LUA_USE_ULONGJMP ++#endif ++ ++ ++/* ++@@ LUA_PATH and LUA_CPATH are the names of the environment variables that ++@* Lua check to set its paths. ++@@ LUA_INIT is the name of the environment variable that Lua ++@* checks for initialization code. ++** CHANGE them if you want different names. ++*/ ++#define LUA_PATH "LUA_PATH" ++#define LUA_CPATH "LUA_CPATH" ++#define LUA_INIT "LUA_INIT" ++ ++ ++/* ++@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for ++@* Lua libraries. ++@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for ++@* C libraries. ++** CHANGE them if your machine has a non-conventional directory ++** hierarchy or if you want to install your libraries in ++** non-conventional directories. ++*/ ++#if defined(_WIN32) ++/* ++** In Windows, any exclamation mark ('!') in the path is replaced by the ++** path of the directory of the executable file of the current process. ++*/ ++#define LUA_LDIR "!\\lua\\" ++#define LUA_CDIR "!\\" ++#define LUA_PATH_DEFAULT \ ++ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ ++ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" ++#define LUA_CPATH_DEFAULT \ ++ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" ++ ++#else ++#define LUA_ROOT "/usr/local/" ++#define LUA_LDIR LUA_ROOT "share/lua/5.1/" ++#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" ++#define LUA_PATH_DEFAULT \ ++ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ ++ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" ++#define LUA_CPATH_DEFAULT \ ++ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" ++#endif ++ ++ ++/* ++@@ LUA_DIRSEP is the directory separator (for submodules). ++** CHANGE it if your machine does not use "/" as the directory separator ++** and is not Windows. (On Windows Lua automatically uses "\".) ++*/ ++#if defined(_WIN32) ++#define LUA_DIRSEP "\\" ++#else ++#define LUA_DIRSEP "/" ++#endif ++ ++ ++/* ++@@ LUA_PATHSEP is the character that separates templates in a path. ++@@ LUA_PATH_MARK is the string that marks the substitution points in a ++@* template. ++@@ LUA_EXECDIR in a Windows path is replaced by the executable's ++@* directory. ++@@ LUA_IGMARK is a mark to ignore all before it when bulding the ++@* luaopen_ function name. ++** CHANGE them if for some reason your system cannot use those ++** characters. (E.g., if one of those characters is a common character ++** in file/directory names.) Probably you do not need to change them. ++*/ ++#define LUA_PATHSEP ";" ++#define LUA_PATH_MARK "?" ++#define LUA_EXECDIR "!" ++#define LUA_IGMARK "-" ++ ++ ++/* ++@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. ++** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ++** machines, ptrdiff_t gives a good choice between int or long.) ++*/ ++#define LUA_INTEGER ptrdiff_t ++ ++ ++/* ++@@ LUA_API is a mark for all core API functions. ++@@ LUALIB_API is a mark for all standard library functions. ++** CHANGE them if you need to define those functions in some special way. ++** For instance, if you want to create one Windows DLL with the core and ++** the libraries, you may want to use the following definition (define ++** LUA_BUILD_AS_DLL to get it). ++*/ ++#if defined(LUA_BUILD_AS_DLL) ++ ++#if defined(LUA_CORE) || defined(LUA_LIB) ++#define LUA_API __declspec(dllexport) ++#else ++#define LUA_API __declspec(dllimport) ++#endif ++ ++#else ++ ++#define LUA_API extern ++ ++#endif ++ ++/* more often than not the libs go together with the core */ ++#define LUALIB_API LUA_API ++ ++ ++/* ++@@ LUAI_FUNC is a mark for all extern functions that are not to be ++@* exported to outside modules. ++@@ LUAI_DATA is a mark for all extern (const) variables that are not to ++@* be exported to outside modules. ++** CHANGE them if you need to mark them in some special way. Elf/gcc ++** (versions 3.2 and later) mark them as "hidden" to optimize access ++** when Lua is compiled as a shared library. ++*/ ++#if defined(luaall_c) ++#define LUAI_FUNC static ++#define LUAI_DATA /* empty */ ++ ++#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ ++ defined(__ELF__) ++#define LUAI_FUNC __attribute__((visibility("hidden"))) extern ++#define LUAI_DATA LUAI_FUNC ++ ++#else ++#define LUAI_FUNC extern ++#define LUAI_DATA extern ++#endif ++ ++ ++ ++/* ++@@ LUA_QL describes how error messages quote program elements. ++** CHANGE it if you want a different appearance. ++*/ ++#define LUA_QL(x) "'" x "'" ++#define LUA_QS LUA_QL("%s") ++ ++ ++/* ++@@ LUA_IDSIZE gives the maximum size for the description of the source ++@* of a function in debug information. ++** CHANGE it if you want a different size. ++*/ ++#define LUA_IDSIZE 60 ++ ++ ++/* ++** {================================================================== ++** Stand-alone configuration ++** =================================================================== ++*/ ++ ++#if defined(lua_c) || defined(luaall_c) ++ ++/* ++@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that ++@* is, whether we're running lua interactively). ++** CHANGE it if you have a better definition for non-POSIX/non-Windows ++** systems. ++*/ ++#if defined(LUA_USE_ISATTY) ++#include ++#define lua_stdin_is_tty() isatty(0) ++#elif defined(LUA_WIN) ++#include ++#include ++#define lua_stdin_is_tty() _isatty(_fileno(stdin)) ++#else ++#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ ++#endif ++ ++ ++/* ++@@ LUA_PROMPT is the default prompt used by stand-alone Lua. ++@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. ++** CHANGE them if you want different prompts. (You can also change the ++** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) ++*/ ++#define LUA_PROMPT "> " ++#define LUA_PROMPT2 ">> " ++ ++ ++/* ++@@ LUA_PROGNAME is the default name for the stand-alone Lua program. ++** CHANGE it if your stand-alone interpreter has a different name and ++** your system is not able to detect that name automatically. ++*/ ++#define LUA_PROGNAME "lua" ++ ++ ++/* ++@@ LUA_MAXINPUT is the maximum length for an input line in the ++@* stand-alone interpreter. ++** CHANGE it if you need longer lines. ++*/ ++#define LUA_MAXINPUT 512 ++ ++ ++/* ++@@ lua_readline defines how to show a prompt and then read a line from ++@* the standard input. ++@@ lua_saveline defines how to "save" a read line in a "history". ++@@ lua_freeline defines how to free a line read by lua_readline. ++** CHANGE them if you want to improve this functionality (e.g., by using ++** GNU readline and history facilities). ++*/ ++#if defined(LUA_USE_READLINE) ++#include ++#include ++#include ++#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) ++#define lua_saveline(L,idx) \ ++ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ ++ add_history(lua_tostring(L, idx)); /* add it to history */ ++#define lua_freeline(L,b) ((void)L, free(b)) ++#else ++#define lua_readline(L,b,p) \ ++ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ ++ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ ++#define lua_saveline(L,idx) { (void)L; (void)idx; } ++#define lua_freeline(L,b) { (void)L; (void)b; } ++#endif ++ ++#endif ++ ++/* }================================================================== */ ++ ++ ++/* ++@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles ++@* as a percentage. ++** CHANGE it if you want the GC to run faster or slower (higher values ++** mean larger pauses which mean slower collection.) You can also change ++** this value dynamically. ++*/ ++#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ ++ ++ ++/* ++@@ LUAI_GCMUL defines the default speed of garbage collection relative to ++@* memory allocation as a percentage. ++** CHANGE it if you want to change the granularity of the garbage ++** collection. (Higher values mean coarser collections. 0 represents ++** infinity, where each step performs a full collection.) You can also ++** change this value dynamically. ++*/ ++#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ ++ ++ ++ ++/* ++@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. ++** CHANGE it (define it) if you want exact compatibility with the ++** behavior of setn/getn in Lua 5.0. ++*/ ++#undef LUA_COMPAT_GETN ++ ++/* ++@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. ++** CHANGE it to undefined as soon as you do not need a global 'loadlib' ++** function (the function is still available as 'package.loadlib'). ++*/ ++#undef LUA_COMPAT_LOADLIB ++ ++/* ++@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. ++** CHANGE it to undefined as soon as your programs use only '...' to ++** access vararg parameters (instead of the old 'arg' table). ++*/ ++#define LUA_COMPAT_VARARG ++ ++/* ++@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. ++** CHANGE it to undefined as soon as your programs use 'math.fmod' or ++** the new '%' operator instead of 'math.mod'. ++*/ ++#define LUA_COMPAT_MOD ++ ++/* ++@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting ++@* facility. ++** CHANGE it to 2 if you want the old behaviour, or undefine it to turn ++** off the advisory error when nesting [[...]]. ++*/ ++#define LUA_COMPAT_LSTR 1 ++ ++/* ++@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. ++** CHANGE it to undefined as soon as you rename 'string.gfind' to ++** 'string.gmatch'. ++*/ ++#define LUA_COMPAT_GFIND ++ ++/* ++@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' ++@* behavior. ++** CHANGE it to undefined as soon as you replace to 'luaL_register' ++** your uses of 'luaL_openlib' ++*/ ++#define LUA_COMPAT_OPENLIB ++ ++ ++ ++/* ++@@ luai_apicheck is the assert macro used by the Lua-C API. ++** CHANGE luai_apicheck if you want Lua to perform some checks in the ++** parameters it gets from API calls. This may slow down the interpreter ++** a bit, but may be quite useful when debugging C code that interfaces ++** with Lua. A useful redefinition is to use assert.h. ++*/ ++#if defined(LUA_USE_APICHECK) ++#include ++#define luai_apicheck(L,o) { (void)L; assert(o); } ++#else ++#define luai_apicheck(L,o) { (void)L; } ++#endif ++ ++ ++/* ++@@ LUAI_BITSINT defines the number of bits in an int. ++** CHANGE here if Lua cannot automatically detect the number of bits of ++** your machine. Probably you do not need to change this. ++*/ ++/* avoid overflows in comparison */ ++#if !defined(__KERNEL__) ++#include ++#define LUA_INT_MAX INT_MAX ++#else ++#define LUA_INT_MAX (~0U>>1) ++#endif ++ ++#if LUA_INT_MAX-20 < 32760 ++#define LUAI_BITSINT 16 ++#elif LUA_INT_MAX > 2147483640L ++/* int has at least 32 bits */ ++#define LUAI_BITSINT 32 ++#else ++#error "you must define LUA_BITSINT with number of bits in an integer" ++#endif ++ ++ ++/* ++@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. ++@@ LUAI_INT32 is an signed integer with at least 32 bits. ++@@ LUAI_UMEM is an unsigned integer big enough to count the total ++@* memory used by Lua. ++@@ LUAI_MEM is a signed integer big enough to count the total memory ++@* used by Lua. ++** CHANGE here if for some weird reason the default definitions are not ++** good enough for your machine. (The definitions in the 'else' ++** part always works, but may waste space on machines with 64-bit ++** longs.) Probably you do not need to change this. ++*/ ++#if LUAI_BITSINT >= 32 ++#define LUAI_UINT32 unsigned int ++#define LUAI_INT32 int ++#define LUAI_MAXINT32 INT_MAX ++#define LUAI_UMEM size_t ++#define LUAI_MEM ptrdiff_t ++#else ++/* 16-bit ints */ ++#define LUAI_UINT32 unsigned long ++#define LUAI_INT32 long ++#define LUAI_MAXINT32 LONG_MAX ++#define LUAI_UMEM unsigned long ++#define LUAI_MEM long ++#endif ++ ++ ++/* ++@@ LUAI_MAXCALLS limits the number of nested calls. ++** CHANGE it if you need really deep recursive calls. This limit is ++** arbitrary; its only purpose is to stop infinite recursion before ++** exhausting memory. ++*/ ++#define LUAI_MAXCALLS 20000 ++ ++ ++/* ++@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function ++@* can use. ++** CHANGE it if you need lots of (Lua) stack space for your C ++** functions. This limit is arbitrary; its only purpose is to stop C ++** functions to consume unlimited stack space. (must be smaller than ++** -LUA_REGISTRYINDEX) ++*/ ++#define LUAI_MAXCSTACK 8000 ++ ++ ++ ++/* ++** {================================================================== ++** CHANGE (to smaller values) the following definitions if your system ++** has a small C stack. (Or you may want to change them to larger ++** values if your system has a large C stack and these limits are ++** too rigid for you.) Some of these constants control the size of ++** stack-allocated arrays used by the compiler or the interpreter, while ++** others limit the maximum number of recursive calls that the compiler ++** or the interpreter can perform. Values too large may cause a C stack ++** overflow for some forms of deep constructs. ++** =================================================================== ++*/ ++ ++ ++/* ++@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and ++@* syntactical nested non-terminals in a program. ++*/ ++#define LUAI_MAXCCALLS 200 ++ ++ ++/* ++@@ LUAI_MAXVARS is the maximum number of local variables per function ++@* (must be smaller than 250). ++*/ ++#define LUAI_MAXVARS 200 ++ ++ ++/* ++@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function ++@* (must be smaller than 250). ++*/ ++#define LUAI_MAXUPVALUES 60 ++ ++ ++/* ++@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. ++*/ ++#define LUAL_BUFFERSIZE BUFSIZ ++ ++/* }================================================================== */ ++ ++ ++ ++ ++/* ++** {================================================================== ++@@ LUA_NUMBER is the type of numbers in Lua. ++** CHANGE the following definitions only if you want to build Lua ++** with a number type different from double. You may also need to ++** change lua_number2int & lua_number2integer. ++** =================================================================== ++*/ ++#if !defined(NO_FPU) ++#define LUA_NUMBER_DOUBLE ++#define LUA_NUMBER double ++#else ++#define LUA_NUMBER long ++#endif ++ ++/* ++@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' ++@* over a number. ++*/ ++#define LUAI_UACNUMBER LUA_NUMBER ++ ++ ++/* ++@@ LUA_NUMBER_SCAN is the format for reading numbers. ++@@ LUA_NUMBER_FMT is the format for writing numbers. ++@@ lua_number2str converts a number to a string. ++@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. ++@@ lua_str2number converts a string to a number. ++*/ ++#if !defined(NO_FPU) ++#define LUA_NUMBER_SCAN "%lf" ++#define LUA_NUMBER_FMT "%.14g" ++#define lua_str2number(s,p) strtod((s), (p)) ++#else ++#define LUA_NUMBER_SCAN "%ld" ++#define LUA_NUMBER_FMT "%ld" ++#if !defined(__KERNEL__) ++#define lua_str2number(s,p) strtol((s), (p), 10) ++#else ++#define lua_str2number(s,p) simple_strtol((s), (p), 10) ++#endif ++#endif ++ ++#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ ++#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) ++ ++/* ++@@ The luai_num* macros define the primitive operations over numbers. ++*/ ++#if defined(LUA_CORE) ++#define luai_numadd(a,b) ((a)+(b)) ++#define luai_numsub(a,b) ((a)-(b)) ++#define luai_nummul(a,b) ((a)*(b)) ++#define luai_numdiv(a,b) ((a)/(b)) ++#define luai_numunm(a) (-(a)) ++#define luai_numeq(a,b) ((a)==(b)) ++#define luai_numlt(a,b) ((a)<(b)) ++#define luai_numle(a,b) ((a)<=(b)) ++#define luai_numisnan(a) (!luai_numeq((a), (a))) ++#if !defined(NO_FPU) ++#include ++#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) ++#define luai_numpow(a,b) (pow(a,b)) ++#else ++#define luai_nummod(a,b) ((a)%(b)) ++#define luai_numpow(a,b) luai_nummul(a,b) ++#endif ++#endif ++ ++ ++/* ++@@ lua_number2int is a macro to convert lua_Number to int. ++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ++** CHANGE them if you know a faster way to convert a lua_Number to ++** int (with any rounding method and without throwing errors) in your ++** system. In Pentium machines, a naive typecast from double to int ++** in C is extremely slow, so any alternative is worth trying. ++*/ ++ ++/* On a Pentium, resort to a trick */ ++#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ ++ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) ++ ++/* On a Microsoft compiler, use assembler */ ++#if defined(_MSC_VER) ++ ++#define lua_number2int(i,d) __asm fld d __asm fistp i ++#define lua_number2integer(i,n) lua_number2int(i, n) ++ ++/* the next trick should work on any Pentium, but sometimes clashes ++ with a DirectX idiosyncrasy */ ++#else ++ ++union luai_Cast { double l_d; long l_l; }; ++#define lua_number2int(i,d) \ ++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } ++#define lua_number2integer(i,n) lua_number2int(i, n) ++ ++#endif ++ ++ ++/* this option always works, but may be slow */ ++#else ++#define lua_number2int(i,d) ((i)=(int)(d)) ++#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) ++ ++#endif ++ ++/* }================================================================== */ ++ ++ ++/* ++@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. ++** CHANGE it if your system requires alignments larger than double. (For ++** instance, if your system supports long doubles and they must be ++** aligned in 16-byte boundaries, then you should add long double in the ++** union.) Probably you do not need to change this. ++*/ ++#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } ++ ++ ++/* ++@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. ++** CHANGE them if you prefer to use longjmp/setjmp even with C++ ++** or if want/don't to use _longjmp/_setjmp instead of regular ++** longjmp/setjmp. By default, Lua handles errors with exceptions when ++** compiling as C++ code, with _longjmp/_setjmp when asked to use them, ++** and with longjmp/setjmp otherwise. ++*/ ++#if defined(__KERNEL__) ++#undef LUA_USE_ULONGJMP ++#endif ++ ++#if defined(__cplusplus) ++/* C++ exceptions */ ++#define LUAI_THROW(L,c) throw(c) ++#define LUAI_TRY(L,c,a) try { a } catch(...) \ ++ { if ((c)->status == 0) (c)->status = -1; } ++#define luai_jmpbuf int /* dummy variable */ ++ ++#elif defined(LUA_USE_ULONGJMP) ++/* in Unix, try _longjmp/_setjmp (more efficient) */ ++#define LUAI_THROW(L,c) _longjmp((c)->b, 1) ++#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } ++#define luai_jmpbuf jmp_buf ++ ++#else ++/* default handling with long jumps */ ++#define LUAI_THROW(L,c) longjmp((c)->b, 1) ++#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } ++#define luai_jmpbuf jmp_buf ++ ++#endif ++ ++ ++/* ++@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern ++@* can do during pattern-matching. ++** CHANGE it if you need more captures. This limit is arbitrary. ++*/ ++#define LUA_MAXCAPTURES 32 ++ ++ ++/* ++@@ lua_tmpnam is the function that the OS library uses to create a ++@* temporary name. ++@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. ++** CHANGE them if you have an alternative to tmpnam (which is considered ++** insecure) or if you want the original tmpnam anyway. By default, Lua ++** uses tmpnam except when POSIX is available, where it uses mkstemp. ++*/ ++#if defined(loslib_c) || defined(luaall_c) ++ ++#if defined(LUA_USE_MKSTEMP) ++#include ++#define LUA_TMPNAMBUFSIZE 32 ++#define lua_tmpnam(b,e) { \ ++ strcpy(b, "/tmp/lua_XXXXXX"); \ ++ e = mkstemp(b); \ ++ if (e != -1) close(e); \ ++ e = (e == -1); } ++ ++#else ++#define LUA_TMPNAMBUFSIZE L_tmpnam ++#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } ++#endif ++ ++#endif ++ ++ ++/* ++@@ lua_popen spawns a new process connected to the current one through ++@* the file streams. ++** CHANGE it if you have a way to implement it in your system. ++*/ ++#if defined(LUA_USE_POPEN) ++ ++#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) ++#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) ++ ++#elif defined(LUA_WIN) ++ ++#define lua_popen(L,c,m) ((void)L, _popen(c,m)) ++#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) ++ ++#else ++ ++#define lua_popen(L,c,m) ((void)((void)c, m), \ ++ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) ++#define lua_pclose(L,file) ((void)((void)L, file), 0) ++ ++#endif ++ ++/* ++@@ LUA_DL_* define which dynamic-library system Lua should use. ++** CHANGE here if Lua has problems choosing the appropriate ++** dynamic-library system for your platform (either Windows' DLL, Mac's ++** dyld, or Unix's dlopen). If your system is some kind of Unix, there ++** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for ++** it. To use dlopen you also need to adapt the src/Makefile (probably ++** adding -ldl to the linker options), so Lua does not select it ++** automatically. (When you change the makefile to add -ldl, you must ++** also add -DLUA_USE_DLOPEN.) ++** If you do not want any kind of dynamic library, undefine all these ++** options. ++** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. ++*/ ++#if defined(LUA_USE_DLOPEN) ++#define LUA_DL_DLOPEN ++#endif ++ ++#if defined(LUA_WIN) ++#define LUA_DL_DLL ++#endif ++ ++ ++/* ++@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State ++@* (the data goes just *before* the lua_State pointer). ++** CHANGE (define) this if you really need that. This value must be ++** a multiple of the maximum alignment required for your machine. ++*/ ++#define LUAI_EXTRASPACE 0 ++ ++ ++/* ++@@ luai_userstate* allow user-specific actions on threads. ++** CHANGE them if you defined LUAI_EXTRASPACE and need to do something ++** extra when a thread is created/deleted/resumed/yielded. ++*/ ++#define luai_userstateopen(L) ((void)L) ++#define luai_userstateclose(L) ((void)L) ++#define luai_userstatethread(L,L1) ((void)L) ++#define luai_userstatefree(L) ((void)L) ++#define luai_userstateresume(L,n) ((void)L) ++#define luai_userstateyield(L,n) ((void)L) ++ ++ ++/* ++@@ LUA_INTFRMLEN is the length modifier for integer conversions ++@* in 'string.format'. ++@@ LUA_INTFRM_T is the integer type correspoding to the previous length ++@* modifier. ++** CHANGE them if your system supports long long or does not support long. ++*/ ++ ++#if defined(LUA_USELONGLONG) ++ ++#define LUA_INTFRMLEN "ll" ++#define LUA_INTFRM_T long long ++ ++#else ++ ++#define LUA_INTFRMLEN "l" ++#define LUA_INTFRM_T long ++ ++#endif ++ ++/* =================================================================== */ ++ ++/* ++** Local configuration. You can use this space to add your redefinitions ++** without modifying the main part of the file. ++*/ ++ ++ ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lua.h +@@ -0,0 +1,387 @@ ++/* ++** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ ++** Lua - An Extensible Extension Language ++** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ++** See Copyright Notice at the end of this file ++*/ ++ ++ ++#ifndef lua_h ++#define lua_h ++ ++#include ++#include ++ ++#include "luaconf.h" ++ ++ ++#define LUA_VERSION "Lua 5.1" ++#define LUA_RELEASE "Lua 5.1.4" ++#define LUA_VERSION_NUM 501 ++#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" ++#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" ++ ++ ++/* mark for precompiled code (`Lua') */ ++#define LUA_SIGNATURE "\033Lua" ++ ++/* option for multiple returns in `lua_pcall' and `lua_call' */ ++#define LUA_MULTRET (-1) ++ ++ ++/* ++** pseudo-indices ++*/ ++#define LUA_REGISTRYINDEX (-10000) ++#define LUA_ENVIRONINDEX (-10001) ++#define LUA_GLOBALSINDEX (-10002) ++#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) ++ ++ ++/* thread status; 0 is OK */ ++#define LUA_YIELD 1 ++#define LUA_ERRRUN 2 ++#define LUA_ERRSYNTAX 3 ++#define LUA_ERRMEM 4 ++#define LUA_ERRERR 5 ++ ++ ++typedef struct lua_State lua_State; ++ ++typedef int (*lua_CFunction) (lua_State *L); ++ ++ ++/* ++** functions that read/write blocks when loading/dumping Lua chunks ++*/ ++typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); ++ ++typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); ++ ++ ++/* ++** prototype for memory-allocation functions ++*/ ++typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); ++ ++ ++/* ++** basic types ++*/ ++#define LUA_TNONE (-1) ++ ++#define LUA_TNIL 0 ++#define LUA_TBOOLEAN 1 ++#define LUA_TLIGHTUSERDATA 2 ++#define LUA_TNUMBER 3 ++#define LUA_TSTRING 4 ++#define LUA_TTABLE 5 ++#define LUA_TFUNCTION 6 ++#define LUA_TUSERDATA 7 ++#define LUA_TTHREAD 8 ++ ++ ++ ++/* minimum Lua stack available to a C function */ ++#define LUA_MINSTACK 20 ++ ++ ++/* ++** generic extra include file ++*/ ++#if defined(LUA_USER_H) ++#include LUA_USER_H ++#endif ++ ++ ++/* type of numbers in Lua */ ++typedef LUA_NUMBER lua_Number; ++ ++ ++/* type for integer functions */ ++typedef LUA_INTEGER lua_Integer; ++ ++ ++ ++/* ++** state manipulation ++*/ ++LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); ++LUA_API void (lua_close) (lua_State *L); ++LUA_API lua_State *(lua_newthread) (lua_State *L); ++ ++LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); ++ ++ ++/* ++** basic stack manipulation ++*/ ++LUA_API int (lua_gettop) (lua_State *L); ++LUA_API void (lua_settop) (lua_State *L, int idx); ++LUA_API void (lua_pushvalue) (lua_State *L, int idx); ++LUA_API void (lua_remove) (lua_State *L, int idx); ++LUA_API void (lua_insert) (lua_State *L, int idx); ++LUA_API void (lua_replace) (lua_State *L, int idx); ++LUA_API int (lua_checkstack) (lua_State *L, int sz); ++ ++LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); ++ ++ ++/* ++** access functions (stack -> C) ++*/ ++ ++LUA_API int (lua_isnumber) (lua_State *L, int idx); ++LUA_API int (lua_isstring) (lua_State *L, int idx); ++LUA_API int (lua_iscfunction) (lua_State *L, int idx); ++LUA_API int (lua_isuserdata) (lua_State *L, int idx); ++LUA_API int (lua_type) (lua_State *L, int idx); ++LUA_API const char *(lua_typename) (lua_State *L, int tp); ++ ++LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); ++LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); ++LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); ++ ++LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); ++LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); ++LUA_API int (lua_toboolean) (lua_State *L, int idx); ++LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); ++LUA_API size_t (lua_objlen) (lua_State *L, int idx); ++LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); ++LUA_API void *(lua_touserdata) (lua_State *L, int idx); ++LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); ++LUA_API const void *(lua_topointer) (lua_State *L, int idx); ++ ++ ++/* ++** push functions (C -> stack) ++*/ ++LUA_API void (lua_pushnil) (lua_State *L); ++LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); ++LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); ++LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); ++LUA_API void (lua_pushstring) (lua_State *L, const char *s); ++LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, ++ va_list argp); ++LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); ++LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); ++LUA_API void (lua_pushboolean) (lua_State *L, int b); ++LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); ++LUA_API int (lua_pushthread) (lua_State *L); ++ ++ ++/* ++** get functions (Lua -> stack) ++*/ ++LUA_API void (lua_gettable) (lua_State *L, int idx); ++LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); ++LUA_API void (lua_rawget) (lua_State *L, int idx); ++LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); ++LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); ++LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); ++LUA_API int (lua_getmetatable) (lua_State *L, int objindex); ++LUA_API void (lua_getfenv) (lua_State *L, int idx); ++ ++ ++/* ++** set functions (stack -> Lua) ++*/ ++LUA_API void (lua_settable) (lua_State *L, int idx); ++LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); ++LUA_API void (lua_rawset) (lua_State *L, int idx); ++LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); ++LUA_API int (lua_setmetatable) (lua_State *L, int objindex); ++LUA_API int (lua_setfenv) (lua_State *L, int idx); ++ ++ ++/* ++** `load' and `call' functions (load and run Lua code) ++*/ ++LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); ++LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); ++LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); ++LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, ++ const char *chunkname); ++ ++LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); ++ ++ ++/* ++** coroutine functions ++*/ ++LUA_API int (lua_yield) (lua_State *L, int nresults); ++LUA_API int (lua_resume) (lua_State *L, int narg); ++LUA_API int (lua_status) (lua_State *L); ++ ++/* ++** garbage-collection function and options ++*/ ++ ++#define LUA_GCSTOP 0 ++#define LUA_GCRESTART 1 ++#define LUA_GCCOLLECT 2 ++#define LUA_GCCOUNT 3 ++#define LUA_GCCOUNTB 4 ++#define LUA_GCSTEP 5 ++#define LUA_GCSETPAUSE 6 ++#define LUA_GCSETSTEPMUL 7 ++ ++LUA_API int (lua_gc) (lua_State *L, int what, int data); ++ ++ ++/* ++** miscellaneous functions ++*/ ++ ++LUA_API int (lua_error) (lua_State *L); ++ ++LUA_API int (lua_next) (lua_State *L, int idx); ++ ++LUA_API void (lua_concat) (lua_State *L, int n); ++ ++LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); ++LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); ++ ++ ++ ++/* ++** =============================================================== ++** some useful macros ++** =============================================================== ++*/ ++ ++#define lua_pop(L,n) lua_settop(L, -(n)-1) ++ ++#define lua_newtable(L) lua_createtable(L, 0, 0) ++ ++#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) ++ ++#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) ++ ++#define lua_strlen(L,i) lua_objlen(L, (i)) ++ ++#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) ++#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) ++#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) ++#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) ++#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) ++#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) ++#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) ++#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) ++ ++#define lua_pushliteral(L, s) \ ++ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) ++ ++#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) ++#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) ++ ++#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) ++ ++ ++ ++/* ++** compatibility macros and functions ++*/ ++ ++#define lua_open() luaL_newstate() ++ ++#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) ++ ++#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) ++ ++#define lua_Chunkreader lua_Reader ++#define lua_Chunkwriter lua_Writer ++ ++ ++/* hack */ ++LUA_API void lua_setlevel (lua_State *from, lua_State *to); ++ ++ ++/* ++** {====================================================================== ++** Debug API ++** ======================================================================= ++*/ ++ ++ ++/* ++** Event codes ++*/ ++#define LUA_HOOKCALL 0 ++#define LUA_HOOKRET 1 ++#define LUA_HOOKLINE 2 ++#define LUA_HOOKCOUNT 3 ++#define LUA_HOOKTAILRET 4 ++ ++ ++/* ++** Event masks ++*/ ++#define LUA_MASKCALL (1 << LUA_HOOKCALL) ++#define LUA_MASKRET (1 << LUA_HOOKRET) ++#define LUA_MASKLINE (1 << LUA_HOOKLINE) ++#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) ++ ++typedef struct lua_Debug lua_Debug; /* activation record */ ++ ++ ++/* Functions to be called by the debuger in specific events */ ++typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); ++ ++ ++LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); ++LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); ++LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); ++LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); ++LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); ++LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); ++ ++LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); ++LUA_API lua_Hook lua_gethook (lua_State *L); ++LUA_API int lua_gethookmask (lua_State *L); ++LUA_API int lua_gethookcount (lua_State *L); ++ ++ ++struct lua_Debug { ++ int event; ++ const char *name; /* (n) */ ++ const char *namewhat; /* (n) `global', `local', `field', `method' */ ++ const char *what; /* (S) `Lua', `C', `main', `tail' */ ++ const char *source; /* (S) */ ++ int currentline; /* (l) */ ++ int nups; /* (u) number of upvalues */ ++ int linedefined; /* (S) */ ++ int lastlinedefined; /* (S) */ ++ char short_src[LUA_IDSIZE]; /* (S) */ ++ /* private part */ ++ int i_ci; /* active function */ ++}; ++ ++/* }====================================================================== */ ++ ++ ++/****************************************************************************** ++* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. ++* ++* Permission is hereby granted, free of charge, to any person obtaining ++* a copy of this software and associated documentation files (the ++* "Software"), to deal in the Software without restriction, including ++* without limitation the rights to use, copy, modify, merge, publish, ++* distribute, sublicense, and/or sell copies of the Software, and to ++* permit persons to whom the Software is furnished to do so, subject to ++* the following conditions: ++* ++* The above copyright notice and this permission notice shall be ++* included in all copies or substantial portions of the Software. ++* ++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ++* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ++* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ++* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++******************************************************************************/ ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lualib.h +@@ -0,0 +1,55 @@ ++/* ++** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua standard libraries ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lualib_h ++#define lualib_h ++ ++#include "lua.h" ++ ++ ++/* Key to file-handle type */ ++#define LUA_FILEHANDLE "FILE*" ++ ++ ++#define LUA_COLIBNAME "coroutine" ++LUALIB_API int (luaopen_base) (lua_State *L); ++ ++#define LUA_TABLIBNAME "table" ++LUALIB_API int (luaopen_table) (lua_State *L); ++/* ++#define LUA_IOLIBNAME "io" ++LUALIB_API int (luaopen_io) (lua_State *L); ++ ++#define LUA_OSLIBNAME "os" ++LUALIB_API int (luaopen_os) (lua_State *L); ++*/ ++ ++#define LUA_STRLIBNAME "string" ++LUALIB_API int (luaopen_string) (lua_State *L); ++ ++/* ++#define LUA_MATHLIBNAME "math" ++LUALIB_API int (luaopen_math) (lua_State *L); ++ ++#define LUA_DBLIBNAME "debug" ++LUALIB_API int (luaopen_debug) (lua_State *L); ++ ++#define LUA_LOADLIBNAME "package" ++LUALIB_API int (luaopen_package) (lua_State *L); ++*/ ++ ++/* open all previous libraries */ ++LUALIB_API void (luaL_openlibs) (lua_State *L); ++ ++ ++ ++#ifndef lua_assert ++#define lua_assert(x) ((void)0) ++#endif ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lundump.c +@@ -0,0 +1,227 @@ ++/* ++** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ ++** load precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lundump_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstring.h" ++#include "lundump.h" ++#include "lzio.h" ++ ++typedef struct { ++ lua_State* L; ++ ZIO* Z; ++ Mbuffer* b; ++ const char* name; ++} LoadState; ++ ++#ifdef LUAC_TRUST_BINARIES ++#define IF(c,s) ++#define error(S,s) ++#else ++#define IF(c,s) if (c) error(S,s) ++ ++static void error(LoadState* S, const char* why) ++{ ++ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); ++ luaD_throw(S->L,LUA_ERRSYNTAX); ++} ++#endif ++ ++#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) ++#define LoadByte(S) (lu_byte)LoadChar(S) ++#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) ++#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) ++ ++static void LoadBlock(LoadState* S, void* b, size_t size) ++{ ++ size_t r=luaZ_read(S->Z,b,size); ++ IF (r!=0, "unexpected end"); ++} ++ ++static int LoadChar(LoadState* S) ++{ ++ char x; ++ LoadVar(S,x); ++ return x; ++} ++ ++static int LoadInt(LoadState* S) ++{ ++ int x; ++ LoadVar(S,x); ++ IF (x<0, "bad integer"); ++ return x; ++} ++ ++static lua_Number LoadNumber(LoadState* S) ++{ ++ lua_Number x; ++ LoadVar(S,x); ++ return x; ++} ++ ++static TString* LoadString(LoadState* S) ++{ ++ size_t size; ++ LoadVar(S,size); ++ if (size==0) ++ return NULL; ++ else ++ { ++ char* s=luaZ_openspace(S->L,S->b,size); ++ LoadBlock(S,s,size); ++ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ ++ } ++} ++ ++static void LoadCode(LoadState* S, Proto* f) ++{ ++ int n=LoadInt(S); ++ f->code=luaM_newvector(S->L,n,Instruction); ++ f->sizecode=n; ++ LoadVector(S,f->code,n,sizeof(Instruction)); ++} ++ ++static Proto* LoadFunction(LoadState* S, TString* p); ++ ++static void LoadConstants(LoadState* S, Proto* f) ++{ ++ int i,n; ++ n=LoadInt(S); ++ f->k=luaM_newvector(S->L,n,TValue); ++ f->sizek=n; ++ for (i=0; ik[i]); ++ for (i=0; ik[i]; ++ int t=LoadChar(S); ++ switch (t) ++ { ++ case LUA_TNIL: ++ setnilvalue(o); ++ break; ++ case LUA_TBOOLEAN: ++ setbvalue(o,LoadChar(S)!=0); ++ break; ++ case LUA_TNUMBER: ++ setnvalue(o,LoadNumber(S)); ++ break; ++ case LUA_TSTRING: ++ setsvalue2n(S->L,o,LoadString(S)); ++ break; ++ default: ++ error(S,"bad constant"); ++ break; ++ } ++ } ++ n=LoadInt(S); ++ f->p=luaM_newvector(S->L,n,Proto*); ++ f->sizep=n; ++ for (i=0; ip[i]=NULL; ++ for (i=0; ip[i]=LoadFunction(S,f->source); ++} ++ ++static void LoadDebug(LoadState* S, Proto* f) ++{ ++ int i,n; ++ n=LoadInt(S); ++ f->lineinfo=luaM_newvector(S->L,n,int); ++ f->sizelineinfo=n; ++ LoadVector(S,f->lineinfo,n,sizeof(int)); ++ n=LoadInt(S); ++ f->locvars=luaM_newvector(S->L,n,LocVar); ++ f->sizelocvars=n; ++ for (i=0; ilocvars[i].varname=NULL; ++ for (i=0; ilocvars[i].varname=LoadString(S); ++ f->locvars[i].startpc=LoadInt(S); ++ f->locvars[i].endpc=LoadInt(S); ++ } ++ n=LoadInt(S); ++ f->upvalues=luaM_newvector(S->L,n,TString*); ++ f->sizeupvalues=n; ++ for (i=0; iupvalues[i]=NULL; ++ for (i=0; iupvalues[i]=LoadString(S); ++} ++ ++static Proto* LoadFunction(LoadState* S, TString* p) ++{ ++ Proto* f; ++ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); ++ f=luaF_newproto(S->L); ++ setptvalue2s(S->L,S->L->top,f); incr_top(S->L); ++ f->source=LoadString(S); if (f->source==NULL) f->source=p; ++ f->linedefined=LoadInt(S); ++ f->lastlinedefined=LoadInt(S); ++ f->nups=LoadByte(S); ++ f->numparams=LoadByte(S); ++ f->is_vararg=LoadByte(S); ++ f->maxstacksize=LoadByte(S); ++ LoadCode(S,f); ++ LoadConstants(S,f); ++ LoadDebug(S,f); ++ IF (!luaG_checkcode(f), "bad code"); ++ S->L->top--; ++ S->L->nCcalls--; ++ return f; ++} ++ ++static void LoadHeader(LoadState* S) ++{ ++ char h[LUAC_HEADERSIZE]; ++ char s[LUAC_HEADERSIZE]; ++ luaU_header(h); ++ LoadBlock(S,s,LUAC_HEADERSIZE); ++ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); ++} ++ ++/* ++** load precompiled chunk ++*/ ++Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) ++{ ++ LoadState S; ++ if (*name=='@' || *name=='=') ++ S.name=name+1; ++ else if (*name==LUA_SIGNATURE[0]) ++ S.name="binary string"; ++ else ++ S.name=name; ++ S.L=L; ++ S.Z=Z; ++ S.b=buff; ++ LoadHeader(&S); ++ return LoadFunction(&S,luaS_newliteral(L,"=?")); ++} ++ ++/* ++* make header ++*/ ++void luaU_header (char* h) ++{ ++ int x=1; ++ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); ++ h+=sizeof(LUA_SIGNATURE)-1; ++ *h++=(char)LUAC_VERSION; ++ *h++=(char)LUAC_FORMAT; ++ *h++=(char)*(char*)&x; /* endianness */ ++ *h++=(char)sizeof(int); ++ *h++=(char)sizeof(size_t); ++ *h++=(char)sizeof(Instruction); ++ *h++=(char)sizeof(lua_Number); ++ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ ++} +--- /dev/null ++++ b/extensions/LUA/lua/lundump.h +@@ -0,0 +1,36 @@ ++/* ++** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ++** load precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lundump_h ++#define lundump_h ++ ++#include "lobject.h" ++#include "lzio.h" ++ ++/* load one chunk; from lundump.c */ ++LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); ++ ++/* make header; from lundump.c */ ++LUAI_FUNC void luaU_header (char* h); ++ ++/* dump one chunk; from ldump.c */ ++LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); ++ ++#ifdef luac_c ++/* print one chunk; from print.c */ ++LUAI_FUNC void luaU_print (const Proto* f, int full); ++#endif ++ ++/* for header of binary files -- this is Lua 5.1 */ ++#define LUAC_VERSION 0x51 ++ ++/* for header of binary files -- this is the official format */ ++#define LUAC_FORMAT 0 ++ ++/* size of header of binary files */ ++#define LUAC_HEADERSIZE 12 ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lvm.c +@@ -0,0 +1,762 @@ ++/* ++** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++ ++#define lvm_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lvm.h" ++ ++ ++ ++/* limit for table tag-method chains (to avoid loops) */ ++#define MAXTAGLOOP 100 ++ ++ ++const TValue *luaV_tonumber (const TValue *obj, TValue *n) { ++ lua_Number num; ++ if (ttisnumber(obj)) return obj; ++ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { ++ setnvalue(n, num); ++ return n; ++ } ++ else ++ return NULL; ++} ++ ++ ++int luaV_tostring (lua_State *L, StkId obj) { ++ if (!ttisnumber(obj)) ++ return 0; ++ else { ++ char s[LUAI_MAXNUMBER2STR]; ++ lua_Number n = nvalue(obj); ++ lua_number2str(s, n); ++ setsvalue2s(L, obj, luaS_new(L, s)); ++ return 1; ++ } ++} ++ ++ ++static void traceexec (lua_State *L, const Instruction *pc) { ++ lu_byte mask = L->hookmask; ++ const Instruction *oldpc = L->savedpc; ++ L->savedpc = pc; ++ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { ++ resethookcount(L); ++ luaD_callhook(L, LUA_HOOKCOUNT, -1); ++ } ++ if (mask & LUA_MASKLINE) { ++ Proto *p = ci_func(L->ci)->l.p; ++ int npc = pcRel(pc, p); ++ int newline = getline(p, npc); ++ /* call linehook when enter a new function, when jump back (loop), ++ or when enter a new line */ ++ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) ++ luaD_callhook(L, LUA_HOOKLINE, newline); ++ } ++} ++ ++ ++static void callTMres (lua_State *L, StkId res, const TValue *f, ++ const TValue *p1, const TValue *p2) { ++ ptrdiff_t result = savestack(L, res); ++ setobj2s(L, L->top, f); /* push function */ ++ setobj2s(L, L->top+1, p1); /* 1st argument */ ++ setobj2s(L, L->top+2, p2); /* 2nd argument */ ++ luaD_checkstack(L, 3); ++ L->top += 3; ++ luaD_call(L, L->top - 3, 1); ++ res = restorestack(L, result); ++ L->top--; ++ setobjs2s(L, res, L->top); ++} ++ ++ ++ ++static void callTM (lua_State *L, const TValue *f, const TValue *p1, ++ const TValue *p2, const TValue *p3) { ++ setobj2s(L, L->top, f); /* push function */ ++ setobj2s(L, L->top+1, p1); /* 1st argument */ ++ setobj2s(L, L->top+2, p2); /* 2nd argument */ ++ setobj2s(L, L->top+3, p3); /* 3th argument */ ++ luaD_checkstack(L, 4); ++ L->top += 4; ++ luaD_call(L, L->top - 4, 0); ++} ++ ++ ++void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { ++ int loop; ++ for (loop = 0; loop < MAXTAGLOOP; loop++) { ++ const TValue *tm; ++ if (ttistable(t)) { /* `t' is a table? */ ++ Table *h = hvalue(t); ++ const TValue *res = luaH_get(h, key); /* do a primitive get */ ++ if (!ttisnil(res) || /* result is no nil? */ ++ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ ++ setobj2s(L, val, res); ++ return; ++ } ++ /* else will try the tag method */ ++ } ++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) ++ luaG_typeerror(L, t, "index"); ++ if (ttisfunction(tm)) { ++ callTMres(L, val, tm, t, key); ++ return; ++ } ++ t = tm; /* else repeat with `tm' */ ++ } ++ luaG_runerror(L, "loop in gettable"); ++} ++ ++ ++void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { ++ int loop; ++ for (loop = 0; loop < MAXTAGLOOP; loop++) { ++ const TValue *tm; ++ if (ttistable(t)) { /* `t' is a table? */ ++ Table *h = hvalue(t); ++ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ ++ if (!ttisnil(oldval) || /* result is no nil? */ ++ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ ++ setobj2t(L, oldval, val); ++ luaC_barriert(L, h, val); ++ return; ++ } ++ /* else will try the tag method */ ++ } ++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) ++ luaG_typeerror(L, t, "index"); ++ if (ttisfunction(tm)) { ++ callTM(L, tm, t, key, val); ++ return; ++ } ++ t = tm; /* else repeat with `tm' */ ++ } ++ luaG_runerror(L, "loop in settable"); ++} ++ ++ ++static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, ++ StkId res, TMS event) { ++ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ ++ if (ttisnil(tm)) ++ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ ++ if (ttisnil(tm)) return 0; ++ callTMres(L, res, tm, p1, p2); ++ return 1; ++} ++ ++ ++static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, ++ TMS event) { ++ const TValue *tm1 = fasttm(L, mt1, event); ++ const TValue *tm2; ++ if (tm1 == NULL) return NULL; /* no metamethod */ ++ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ ++ tm2 = fasttm(L, mt2, event); ++ if (tm2 == NULL) return NULL; /* no metamethod */ ++ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ ++ return tm1; ++ return NULL; ++} ++ ++ ++static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, ++ TMS event) { ++ const TValue *tm1 = luaT_gettmbyobj(L, p1, event); ++ const TValue *tm2; ++ if (ttisnil(tm1)) return -1; /* no metamethod? */ ++ tm2 = luaT_gettmbyobj(L, p2, event); ++ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ ++ return -1; ++ callTMres(L, L->top, tm1, p1, p2); ++ return !l_isfalse(L->top); ++} ++ ++ ++static int l_strcmp (const TString *ls, const TString *rs) { ++ const char *l = getstr(ls); ++ size_t ll = ls->tsv.len; ++ const char *r = getstr(rs); ++ size_t lr = rs->tsv.len; ++ for (;;) { ++ int temp = strcoll(l, r); ++ if (temp != 0) return temp; ++ else { /* strings are equal up to a `\0' */ ++ size_t len = strlen(l); /* index of first `\0' in both strings */ ++ if (len == lr) /* r is finished? */ ++ return (len == ll) ? 0 : 1; ++ else if (len == ll) /* l is finished? */ ++ return -1; /* l is smaller than r (because r is not finished) */ ++ /* both strings longer than `len'; go on comparing (after the `\0') */ ++ len++; ++ l += len; ll -= len; r += len; lr -= len; ++ } ++ } ++} ++ ++ ++int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { ++ int res; ++ if (ttype(l) != ttype(r)) ++ return luaG_ordererror(L, l, r); ++ else if (ttisnumber(l)) ++ return luai_numlt(nvalue(l), nvalue(r)); ++ else if (ttisstring(l)) ++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; ++ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) ++ return res; ++ return luaG_ordererror(L, l, r); ++} ++ ++ ++static int lessequal (lua_State *L, const TValue *l, const TValue *r) { ++ int res; ++ if (ttype(l) != ttype(r)) ++ return luaG_ordererror(L, l, r); ++ else if (ttisnumber(l)) ++ return luai_numle(nvalue(l), nvalue(r)); ++ else if (ttisstring(l)) ++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; ++ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ ++ return res; ++ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ ++ return !res; ++ return luaG_ordererror(L, l, r); ++} ++ ++ ++int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { ++ const TValue *tm; ++ lua_assert(ttype(t1) == ttype(t2)); ++ switch (ttype(t1)) { ++ case LUA_TNIL: return 1; ++ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); ++ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); ++ case LUA_TUSERDATA: { ++ if (uvalue(t1) == uvalue(t2)) return 1; ++ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, ++ TM_EQ); ++ break; /* will try TM */ ++ } ++ case LUA_TTABLE: { ++ if (hvalue(t1) == hvalue(t2)) return 1; ++ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); ++ break; /* will try TM */ ++ } ++ default: return gcvalue(t1) == gcvalue(t2); ++ } ++ if (tm == NULL) return 0; /* no TM? */ ++ callTMres(L, L->top, tm, t1, t2); /* call TM */ ++ return !l_isfalse(L->top); ++} ++ ++ ++void luaV_concat (lua_State *L, int total, int last) { ++ do { ++ StkId top = L->base + last + 1; ++ int n = 2; /* number of elements handled in this pass (at least 2) */ ++ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { ++ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) ++ luaG_concaterror(L, top-2, top-1); ++ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ ++ (void)tostring(L, top - 2); /* result is first op (as string) */ ++ else { ++ /* at least two string values; get as many as possible */ ++ size_t tl = tsvalue(top-1)->len; ++ char *buffer; ++ int i; ++ /* collect total length */ ++ for (n = 1; n < total && tostring(L, top-n-1); n++) { ++ size_t l = tsvalue(top-n-1)->len; ++ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); ++ tl += l; ++ } ++ buffer = luaZ_openspace(L, &G(L)->buff, tl); ++ tl = 0; ++ for (i=n; i>0; i--) { /* concat all strings */ ++ size_t l = tsvalue(top-i)->len; ++ memcpy(buffer+tl, svalue(top-i), l); ++ tl += l; ++ } ++ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); ++ } ++ total -= n-1; /* got `n' strings to create 1 new */ ++ last -= n-1; ++ } while (total > 1); /* repeat until only 1 result left */ ++} ++ ++ ++static void Arith (lua_State *L, StkId ra, const TValue *rb, ++ const TValue *rc, TMS op) { ++ TValue tempb, tempc; ++ const TValue *b, *c; ++ if ((b = luaV_tonumber(rb, &tempb)) != NULL && ++ (c = luaV_tonumber(rc, &tempc)) != NULL) { ++ lua_Number nb = nvalue(b), nc = nvalue(c); ++ switch (op) { ++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; ++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; ++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; ++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; ++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; ++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; ++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; ++ default: lua_assert(0); break; ++ } ++ } ++ else if (!call_binTM(L, rb, rc, ra, op)) ++ luaG_aritherror(L, rb, rc); ++} ++ ++ ++ ++/* ++** some macros for common tasks in `luaV_execute' ++*/ ++ ++#define runtime_check(L, c) { if (!(c)) break; } ++ ++#define RA(i) (base+GETARG_A(i)) ++/* to be used after possible stack reallocation */ ++#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) ++#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) ++#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ ++ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) ++#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ ++ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) ++#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) ++ ++ ++#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} ++ ++ ++#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } ++ ++ ++#define arith_op(op,tm) { \ ++ TValue *rb = RKB(i); \ ++ TValue *rc = RKC(i); \ ++ if (ttisnumber(rb) && ttisnumber(rc)) { \ ++ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ ++ setnvalue(ra, op(nb, nc)); \ ++ } \ ++ else \ ++ Protect(Arith(L, ra, rb, rc, tm)); \ ++ } ++ ++ ++ ++void luaV_execute (lua_State *L, int nexeccalls) { ++ LClosure *cl; ++ StkId base; ++ TValue *k; ++ const Instruction *pc; ++ reentry: /* entry point */ ++ lua_assert(isLua(L->ci)); ++ pc = L->savedpc; ++ cl = &clvalue(L->ci->func)->l; ++ base = L->base; ++ k = cl->p->k; ++ /* main loop of interpreter */ ++ for (;;) { ++ const Instruction i = *pc++; ++ StkId ra; ++ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && ++ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { ++ traceexec(L, pc); ++ if (L->status == LUA_YIELD) { /* did hook yield? */ ++ L->savedpc = pc - 1; ++ return; ++ } ++ base = L->base; ++ } ++ /* warning!! several calls may realloc the stack and invalidate `ra' */ ++ ra = RA(i); ++ lua_assert(base == L->base && L->base == L->ci->base); ++ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); ++ lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); ++ switch (GET_OPCODE(i)) { ++ case OP_MOVE: { ++ setobjs2s(L, ra, RB(i)); ++ continue; ++ } ++ case OP_LOADK: { ++ setobj2s(L, ra, KBx(i)); ++ continue; ++ } ++ case OP_LOADBOOL: { ++ setbvalue(ra, GETARG_B(i)); ++ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ ++ continue; ++ } ++ case OP_LOADNIL: { ++ TValue *rb = RB(i); ++ do { ++ setnilvalue(rb--); ++ } while (rb >= ra); ++ continue; ++ } ++ case OP_GETUPVAL: { ++ int b = GETARG_B(i); ++ setobj2s(L, ra, cl->upvals[b]->v); ++ continue; ++ } ++ case OP_GETGLOBAL: { ++ TValue g; ++ TValue *rb = KBx(i); ++ sethvalue(L, &g, cl->env); ++ lua_assert(ttisstring(rb)); ++ Protect(luaV_gettable(L, &g, rb, ra)); ++ continue; ++ } ++ case OP_GETTABLE: { ++ Protect(luaV_gettable(L, RB(i), RKC(i), ra)); ++ continue; ++ } ++ case OP_SETGLOBAL: { ++ TValue g; ++ sethvalue(L, &g, cl->env); ++ lua_assert(ttisstring(KBx(i))); ++ Protect(luaV_settable(L, &g, KBx(i), ra)); ++ continue; ++ } ++ case OP_SETUPVAL: { ++ UpVal *uv = cl->upvals[GETARG_B(i)]; ++ setobj(L, uv->v, ra); ++ luaC_barrier(L, uv, ra); ++ continue; ++ } ++ case OP_SETTABLE: { ++ Protect(luaV_settable(L, ra, RKB(i), RKC(i))); ++ continue; ++ } ++ case OP_NEWTABLE: { ++ int b = GETARG_B(i); ++ int c = GETARG_C(i); ++ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); ++ Protect(luaC_checkGC(L)); ++ continue; ++ } ++ case OP_SELF: { ++ StkId rb = RB(i); ++ setobjs2s(L, ra+1, rb); ++ Protect(luaV_gettable(L, rb, RKC(i), ra)); ++ continue; ++ } ++ case OP_ADD: { ++ arith_op(luai_numadd, TM_ADD); ++ continue; ++ } ++ case OP_SUB: { ++ arith_op(luai_numsub, TM_SUB); ++ continue; ++ } ++ case OP_MUL: { ++ arith_op(luai_nummul, TM_MUL); ++ continue; ++ } ++ case OP_DIV: { ++ arith_op(luai_numdiv, TM_DIV); ++ continue; ++ } ++ case OP_MOD: { ++ arith_op(luai_nummod, TM_MOD); ++ continue; ++ } ++ case OP_POW: { ++ arith_op(luai_numpow, TM_POW); ++ continue; ++ } ++ case OP_UNM: { ++ TValue *rb = RB(i); ++ if (ttisnumber(rb)) { ++ lua_Number nb = nvalue(rb); ++ setnvalue(ra, luai_numunm(nb)); ++ } ++ else { ++ Protect(Arith(L, ra, rb, rb, TM_UNM)); ++ } ++ continue; ++ } ++ case OP_NOT: { ++ int res = l_isfalse(RB(i)); /* next assignment may change this value */ ++ setbvalue(ra, res); ++ continue; ++ } ++ case OP_LEN: { ++ const TValue *rb = RB(i); ++ switch (ttype(rb)) { ++ case LUA_TTABLE: { ++ setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); ++ break; ++ } ++ case LUA_TSTRING: { ++ setnvalue(ra, cast_num(tsvalue(rb)->len)); ++ break; ++ } ++ default: { /* try metamethod */ ++ Protect( ++ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) ++ luaG_typeerror(L, rb, "get length of"); ++ ) ++ } ++ } ++ continue; ++ } ++ case OP_CONCAT: { ++ int b = GETARG_B(i); ++ int c = GETARG_C(i); ++ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); ++ setobjs2s(L, RA(i), base+b); ++ continue; ++ } ++ case OP_JMP: { ++ dojump(L, pc, GETARG_sBx(i)); ++ continue; ++ } ++ case OP_EQ: { ++ TValue *rb = RKB(i); ++ TValue *rc = RKC(i); ++ Protect( ++ if (equalobj(L, rb, rc) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_LT: { ++ Protect( ++ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_LE: { ++ Protect( ++ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_TEST: { ++ if (l_isfalse(ra) != GETARG_C(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ pc++; ++ continue; ++ } ++ case OP_TESTSET: { ++ TValue *rb = RB(i); ++ if (l_isfalse(rb) != GETARG_C(i)) { ++ setobjs2s(L, ra, rb); ++ dojump(L, pc, GETARG_sBx(*pc)); ++ } ++ pc++; ++ continue; ++ } ++ case OP_CALL: { ++ int b = GETARG_B(i); ++ int nresults = GETARG_C(i) - 1; ++ if (b != 0) L->top = ra+b; /* else previous instruction set top */ ++ L->savedpc = pc; ++ switch (luaD_precall(L, ra, nresults)) { ++ case PCRLUA: { ++ nexeccalls++; ++ goto reentry; /* restart luaV_execute over new Lua function */ ++ } ++ case PCRC: { ++ /* it was a C function (`precall' called it); adjust results */ ++ if (nresults >= 0) L->top = L->ci->top; ++ base = L->base; ++ continue; ++ } ++ default: { ++ return; /* yield */ ++ } ++ } ++ } ++ case OP_TAILCALL: { ++ int b = GETARG_B(i); ++ if (b != 0) L->top = ra+b; /* else previous instruction set top */ ++ L->savedpc = pc; ++ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); ++ switch (luaD_precall(L, ra, LUA_MULTRET)) { ++ case PCRLUA: { ++ /* tail call: put new frame in place of previous one */ ++ CallInfo *ci = L->ci - 1; /* previous frame */ ++ int aux; ++ StkId func = ci->func; ++ StkId pfunc = (ci+1)->func; /* previous function index */ ++ if (L->openupval) luaF_close(L, ci->base); ++ L->base = ci->base = ci->func + ((ci+1)->base - pfunc); ++ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ ++ setobjs2s(L, func+aux, pfunc+aux); ++ ci->top = L->top = func+aux; /* correct top */ ++ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); ++ ci->savedpc = L->savedpc; ++ ci->tailcalls++; /* one more call lost */ ++ L->ci--; /* remove new frame */ ++ goto reentry; ++ } ++ case PCRC: { /* it was a C function (`precall' called it) */ ++ base = L->base; ++ continue; ++ } ++ default: { ++ return; /* yield */ ++ } ++ } ++ } ++ case OP_RETURN: { ++ int b = GETARG_B(i); ++ if (b != 0) L->top = ra+b-1; ++ if (L->openupval) luaF_close(L, base); ++ L->savedpc = pc; ++ b = luaD_poscall(L, ra); ++ if (--nexeccalls == 0) /* was previous function running `here'? */ ++ return; /* no: return */ ++ else { /* yes: continue its execution */ ++ if (b) L->top = L->ci->top; ++ lua_assert(isLua(L->ci)); ++ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); ++ goto reentry; ++ } ++ } ++ case OP_FORLOOP: { ++ lua_Number step = nvalue(ra+2); ++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ ++ lua_Number limit = nvalue(ra+1); ++ if (luai_numlt(0, step) ? luai_numle(idx, limit) ++ : luai_numle(limit, idx)) { ++ dojump(L, pc, GETARG_sBx(i)); /* jump back */ ++ setnvalue(ra, idx); /* update internal index... */ ++ setnvalue(ra+3, idx); /* ...and external index */ ++ } ++ continue; ++ } ++ case OP_FORPREP: { ++ const TValue *init = ra; ++ const TValue *plimit = ra+1; ++ const TValue *pstep = ra+2; ++ L->savedpc = pc; /* next steps may throw errors */ ++ if (!tonumber(init, ra)) ++ luaG_runerror(L, LUA_QL("for") " initial value must be a number"); ++ else if (!tonumber(plimit, ra+1)) ++ luaG_runerror(L, LUA_QL("for") " limit must be a number"); ++ else if (!tonumber(pstep, ra+2)) ++ luaG_runerror(L, LUA_QL("for") " step must be a number"); ++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); ++ dojump(L, pc, GETARG_sBx(i)); ++ continue; ++ } ++ case OP_TFORLOOP: { ++ StkId cb = ra + 3; /* call base */ ++ setobjs2s(L, cb+2, ra+2); ++ setobjs2s(L, cb+1, ra+1); ++ setobjs2s(L, cb, ra); ++ L->top = cb+3; /* func. + 2 args (state and index) */ ++ Protect(luaD_call(L, cb, GETARG_C(i))); ++ L->top = L->ci->top; ++ cb = RA(i) + 3; /* previous call may change the stack */ ++ if (!ttisnil(cb)) { /* continue loop? */ ++ setobjs2s(L, cb-1, cb); /* save control variable */ ++ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ ++ } ++ pc++; ++ continue; ++ } ++ case OP_SETLIST: { ++ int n = GETARG_B(i); ++ int c = GETARG_C(i); ++ int last; ++ Table *h; ++ if (n == 0) { ++ n = cast_int(L->top - ra) - 1; ++ L->top = L->ci->top; ++ } ++ if (c == 0) c = cast_int(*pc++); ++ runtime_check(L, ttistable(ra)); ++ h = hvalue(ra); ++ last = ((c-1)*LFIELDS_PER_FLUSH) + n; ++ if (last > h->sizearray) /* needs more space? */ ++ luaH_resizearray(L, h, last); /* pre-alloc it at once */ ++ for (; n > 0; n--) { ++ TValue *val = ra+n; ++ setobj2t(L, luaH_setnum(L, h, last--), val); ++ luaC_barriert(L, h, val); ++ } ++ continue; ++ } ++ case OP_CLOSE: { ++ luaF_close(L, ra); ++ continue; ++ } ++ case OP_CLOSURE: { ++ Proto *p; ++ Closure *ncl; ++ int nup, j; ++ p = cl->p->p[GETARG_Bx(i)]; ++ nup = p->nups; ++ ncl = luaF_newLclosure(L, nup, cl->env); ++ ncl->l.p = p; ++ for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; ++ else { ++ lua_assert(GET_OPCODE(*pc) == OP_MOVE); ++ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); ++ } ++ } ++ setclvalue(L, ra, ncl); ++ Protect(luaC_checkGC(L)); ++ continue; ++ } ++ case OP_VARARG: { ++ int b = GETARG_B(i) - 1; ++ int j; ++ CallInfo *ci = L->ci; ++ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; ++ if (b == LUA_MULTRET) { ++ Protect(luaD_checkstack(L, n)); ++ ra = RA(i); /* previous call may change the stack */ ++ b = n; ++ L->top = ra + n; ++ } ++ for (j = 0; j < b; j++) { ++ if (j < n) { ++ setobjs2s(L, ra + j, ci->base - n + j); ++ } ++ else { ++ setnilvalue(ra + j); ++ } ++ } ++ continue; ++ } ++ } ++ } ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lvm.h +@@ -0,0 +1,36 @@ ++/* ++** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lvm_h ++#define lvm_h ++ ++ ++#include "ldo.h" ++#include "lobject.h" ++#include "ltm.h" ++ ++ ++#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) ++ ++#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ ++ (((o) = luaV_tonumber(o,n)) != NULL)) ++ ++#define equalobj(L,o1,o2) \ ++ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) ++ ++ ++LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); ++LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); ++LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); ++LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); ++LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, ++ StkId val); ++LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, ++ StkId val); ++LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); ++LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lzio.c +@@ -0,0 +1,81 @@ ++/* ++** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ++** a generic input stream interface ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lzio_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "llimits.h" ++#include "lmem.h" ++#include "lstate.h" ++#include "lzio.h" ++ ++ ++int luaZ_fill (ZIO *z) { ++ size_t size; ++ lua_State *L = z->L; ++ const char *buff; ++ lua_unlock(L); ++ buff = z->reader(L, z->data, &size); ++ lua_lock(L); ++ if (buff == NULL || size == 0) return EOZ; ++ z->n = size - 1; ++ z->p = buff; ++ return char2int(*(z->p++)); ++} ++ ++ ++int luaZ_lookahead (ZIO *z) { ++ if (z->n == 0) { ++ if (luaZ_fill(z) == EOZ) ++ return EOZ; ++ else { ++ z->n++; /* luaZ_fill removed first byte; put back it */ ++ z->p--; ++ } ++ } ++ return char2int(*z->p); ++} ++ ++ ++void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { ++ z->L = L; ++ z->reader = reader; ++ z->data = data; ++ z->n = 0; ++ z->p = NULL; ++} ++ ++ ++/* --------------------------------------------------------------- read --- */ ++size_t luaZ_read (ZIO *z, void *b, size_t n) { ++ while (n) { ++ size_t m; ++ if (luaZ_lookahead(z) == EOZ) ++ return n; /* return number of missing bytes */ ++ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ ++ memcpy(b, z->p, m); ++ z->n -= m; ++ z->p += m; ++ b = (char *)b + m; ++ n -= m; ++ } ++ return 0; ++} ++ ++/* ------------------------------------------------------------------------ */ ++char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { ++ if (n > buff->buffsize) { ++ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; ++ luaZ_resizebuffer(L, buff, n); ++ } ++ return buff->buffer; ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/lua/lzio.h +@@ -0,0 +1,67 @@ ++/* ++** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Buffered streams ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lzio_h ++#define lzio_h ++ ++#include "lua.h" ++ ++#include "lmem.h" ++ ++ ++#define EOZ (-1) /* end of stream */ ++ ++typedef struct Zio ZIO; ++ ++#define char2int(c) cast(int, cast(unsigned char, (c))) ++ ++#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) ++ ++typedef struct Mbuffer { ++ char *buffer; ++ size_t n; ++ size_t buffsize; ++} Mbuffer; ++ ++#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) ++ ++#define luaZ_buffer(buff) ((buff)->buffer) ++#define luaZ_sizebuffer(buff) ((buff)->buffsize) ++#define luaZ_bufflen(buff) ((buff)->n) ++ ++#define luaZ_resetbuffer(buff) ((buff)->n = 0) ++ ++ ++#define luaZ_resizebuffer(L, buff, size) \ ++ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ ++ (buff)->buffsize = size) ++ ++#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) ++ ++ ++LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); ++LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, ++ void *data); ++LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ ++LUAI_FUNC int luaZ_lookahead (ZIO *z); ++ ++ ++ ++/* --------- Private Part ------------------ */ ++ ++struct Zio { ++ size_t n; /* bytes still unread */ ++ const char *p; /* current position in buffer */ ++ lua_Reader reader; ++ void* data; /* additional data */ ++ lua_State *L; /* Lua state (for reader) */ ++}; ++ ++ ++LUAI_FUNC int luaZ_fill (ZIO *z); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/Makefile +@@ -0,0 +1,389 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# extensions/LUA/Makefile. Generated from Makefile.in by configure. ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++ ++ ++# -*- Makefile -*- ++# AUTOMAKE ++ ++pkgdatadir = $(datadir)/xtables-addons ++pkgincludedir = $(includedir)/xtables-addons ++pkglibdir = $(libdir)/xtables-addons ++pkglibexecdir = $(libexecdir)/xtables-addons ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = i686-pc-linux-gnu ++host_triplet = i686-pc-linux-gnu ++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ ++ $(srcdir)/Makefile.in ++subdir = extensions/LUA ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ ++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ ++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++SOURCES = ++DIST_SOURCES = ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run aclocal-1.11 ++AMTAR = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run tar ++AR = ar ++AUTOCONF = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoconf ++AUTOHEADER = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoheader ++AUTOMAKE = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run automake-1.11 ++AWK = mawk ++CC = gcc ++CCDEPMODE = depmode=gcc3 ++CFLAGS = -g -O2 ++CPP = gcc -E ++CPPFLAGS = ++CYGPATH_W = echo ++DEFS = -DHAVE_CONFIG_H ++DEPDIR = .deps ++DSYMUTIL = ++DUMPBIN = ++ECHO_C = ++ECHO_N = -n ++ECHO_T = ++EGREP = /bin/grep -E ++EXEEXT = ++FGREP = /bin/grep -F ++GREP = /bin/grep ++INSTALL = /usr/bin/install -c ++INSTALL_DATA = ${INSTALL} -m 644 ++INSTALL_PROGRAM = ${INSTALL} ++INSTALL_SCRIPT = ${INSTALL} ++INSTALL_STRIP_PROGRAM = $(install_sh) -c -s ++LD = /usr/bin/ld ++LDFLAGS = ++LIBOBJS = ++LIBS = ++LIBTOOL = $(SHELL) $(top_builddir)/libtool ++LIPO = ++LN_S = ln -s ++LTLIBOBJS = ++MAKEINFO = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run makeinfo ++MKDIR_P = /bin/mkdir -p ++NM = /usr/bin/nm -B ++NMEDIT = ++OBJDUMP = objdump ++OBJEXT = o ++OTOOL = ++OTOOL64 = ++PACKAGE = xtables-addons ++PACKAGE_BUGREPORT = ++PACKAGE_NAME = xtables-addons ++PACKAGE_STRING = xtables-addons 1.21 ++PACKAGE_TARNAME = xtables-addons ++PACKAGE_URL = ++PACKAGE_VERSION = 1.21 ++PATH_SEPARATOR = : ++PKG_CONFIG = /usr/bin/pkg-config ++RANLIB = ranlib ++SED = /bin/sed ++SET_MAKE = ++SHELL = /bin/bash ++STRIP = strip ++VERSION = 1.21 ++abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA ++abs_srcdir = /home/andre/Dropbox/xtables-addons/extensions/LUA ++abs_top_builddir = /home/andre/Dropbox/xtables-addons ++abs_top_srcdir = /home/andre/Dropbox/xtables-addons ++ac_ct_CC = gcc ++ac_ct_DUMPBIN = ++am__include = include ++am__leading_dot = . ++am__quote = ++am__tar = ${AMTAR} chof - "$$tardir" ++am__untar = ${AMTAR} xf - ++bindir = ${exec_prefix}/bin ++build = i686-pc-linux-gnu ++build_alias = ++build_cpu = i686 ++build_os = linux-gnu ++build_vendor = pc ++builddir = . ++datadir = ${datarootdir} ++datarootdir = ${prefix}/share ++docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} ++dvidir = ${docdir} ++exec_prefix = ${prefix} ++host = i686-pc-linux-gnu ++host_alias = ++host_cpu = i686 ++host_os = linux-gnu ++host_vendor = pc ++htmldir = ${docdir} ++includedir = ${prefix}/include ++infodir = ${datarootdir}/info ++install_sh = ${SHELL} /home/andre/Dropbox/xtables-addons/install-sh ++kbuilddir = /lib/modules/2.6.33-020633-generic/build ++kinclude_CFLAGS = -I /lib/modules/2.6.33-020633-generic/build/include ++ksourcedir = ++libdir = ${exec_prefix}/lib ++libexecdir = ${exec_prefix}/libexec ++libxtables_CFLAGS = ++libxtables_LIBS = -L/lib -lxtables ++localedir = ${datarootdir}/locale ++localstatedir = ${prefix}/var ++lt_ECHO = echo ++mandir = ${datarootdir}/man ++mkdir_p = /bin/mkdir -p ++oldincludedir = /usr/include ++pdfdir = ${docdir} ++prefix = /usr/local ++program_transform_name = s,x,x, ++psdir = ${docdir} ++regular_CFLAGS = -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Winline -pipe -DXTABLES_LIBDIR=\"${xtlibdir}\" ++sbindir = ${exec_prefix}/sbin ++sharedstatedir = ${prefix}/com ++srcdir = . ++sysconfdir = ${prefix}/etc ++target_alias = ++top_build_prefix = ../../ ++top_builddir = ../.. ++top_srcdir = ../.. ++xtlibdir = ${libexecdir}/xtables ++XA_SRCDIR = ${srcdir} ++XA_TOPSRCDIR = ${top_srcdir} ++XA_ABSTOPSRCDIR = ${abs_top_srcdir} ++_mcall = -f ${top_builddir}/Makefile.iptrules ++all: all-am ++ ++.SUFFIXES: ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --foreign extensions/LUA/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++tags: TAGS ++TAGS: ++ ++ctags: CTAGS ++CTAGS: ++ ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile all-local ++installdirs: ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-local mostlyclean-am ++ ++distclean: distclean-am ++ -rm -f Makefile ++distclean-am: clean-am distclean-generic ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: install-exec-local ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-generic mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: ++ ++.MAKE: install-am install-strip ++ ++.PHONY: all all-am all-local check check-am clean clean-generic \ ++ clean-libtool clean-local distclean distclean-generic \ ++ distclean-libtool distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am install-dvi \ ++ install-dvi-am install-exec install-exec-am install-exec-local \ ++ install-html install-html-am install-info install-info-am \ ++ install-man install-pdf install-pdf-am install-ps \ ++ install-ps-am install-strip installcheck installcheck-am \ ++ installdirs maintainer-clean maintainer-clean-generic \ ++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ++ ps ps-am uninstall uninstall-am ++ ++export XA_SRCDIR ++export XA_TOPSRCDIR ++export XA_ABSTOPSRCDIR ++ ++all-local: user-all-local ++ ++install-exec-local: user-install-local ++ ++clean-local: user-clean-local ++ ++user-all-local: ++ ${MAKE} ${_mcall} all; ++ ++# Have no user-install-data-local ATM ++user-install-local: user-install-exec-local ++ ++user-install-exec-local: ++ ${MAKE} ${_mcall} install; ++ ++user-clean-local: ++ ${MAKE} ${_mcall} clean; ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: ++ +--- /dev/null ++++ b/extensions/LUA/Makefile.am +@@ -0,0 +1 @@ ++include ../../Makefile.extra +--- /dev/null ++++ b/extensions/LUA/Makefile.in +@@ -0,0 +1,389 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# @configure_input@ ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++@SET_MAKE@ ++ ++# -*- Makefile -*- ++# AUTOMAKE ++VPATH = @srcdir@ ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkglibexecdir = $(libexecdir)/@PACKAGE@ ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = @build@ ++host_triplet = @host@ ++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ ++ $(srcdir)/Makefile.in ++subdir = extensions/LUA ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ ++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ ++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++SOURCES = ++DIST_SOURCES = ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = @ACLOCAL@ ++AMTAR = @AMTAR@ ++AR = @AR@ ++AUTOCONF = @AUTOCONF@ ++AUTOHEADER = @AUTOHEADER@ ++AUTOMAKE = @AUTOMAKE@ ++AWK = @AWK@ ++CC = @CC@ ++CCDEPMODE = @CCDEPMODE@ ++CFLAGS = @CFLAGS@ ++CPP = @CPP@ ++CPPFLAGS = @CPPFLAGS@ ++CYGPATH_W = @CYGPATH_W@ ++DEFS = @DEFS@ ++DEPDIR = @DEPDIR@ ++DSYMUTIL = @DSYMUTIL@ ++DUMPBIN = @DUMPBIN@ ++ECHO_C = @ECHO_C@ ++ECHO_N = @ECHO_N@ ++ECHO_T = @ECHO_T@ ++EGREP = @EGREP@ ++EXEEXT = @EXEEXT@ ++FGREP = @FGREP@ ++GREP = @GREP@ ++INSTALL = @INSTALL@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ ++LD = @LD@ ++LDFLAGS = @LDFLAGS@ ++LIBOBJS = @LIBOBJS@ ++LIBS = @LIBS@ ++LIBTOOL = @LIBTOOL@ ++LIPO = @LIPO@ ++LN_S = @LN_S@ ++LTLIBOBJS = @LTLIBOBJS@ ++MAKEINFO = @MAKEINFO@ ++MKDIR_P = @MKDIR_P@ ++NM = @NM@ ++NMEDIT = @NMEDIT@ ++OBJDUMP = @OBJDUMP@ ++OBJEXT = @OBJEXT@ ++OTOOL = @OTOOL@ ++OTOOL64 = @OTOOL64@ ++PACKAGE = @PACKAGE@ ++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_STRING = @PACKAGE_STRING@ ++PACKAGE_TARNAME = @PACKAGE_TARNAME@ ++PACKAGE_URL = @PACKAGE_URL@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++PATH_SEPARATOR = @PATH_SEPARATOR@ ++PKG_CONFIG = @PKG_CONFIG@ ++RANLIB = @RANLIB@ ++SED = @SED@ ++SET_MAKE = @SET_MAKE@ ++SHELL = @SHELL@ ++STRIP = @STRIP@ ++VERSION = @VERSION@ ++abs_builddir = @abs_builddir@ ++abs_srcdir = @abs_srcdir@ ++abs_top_builddir = @abs_top_builddir@ ++abs_top_srcdir = @abs_top_srcdir@ ++ac_ct_CC = @ac_ct_CC@ ++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ++am__include = @am__include@ ++am__leading_dot = @am__leading_dot@ ++am__quote = @am__quote@ ++am__tar = @am__tar@ ++am__untar = @am__untar@ ++bindir = @bindir@ ++build = @build@ ++build_alias = @build_alias@ ++build_cpu = @build_cpu@ ++build_os = @build_os@ ++build_vendor = @build_vendor@ ++builddir = @builddir@ ++datadir = @datadir@ ++datarootdir = @datarootdir@ ++docdir = @docdir@ ++dvidir = @dvidir@ ++exec_prefix = @exec_prefix@ ++host = @host@ ++host_alias = @host_alias@ ++host_cpu = @host_cpu@ ++host_os = @host_os@ ++host_vendor = @host_vendor@ ++htmldir = @htmldir@ ++includedir = @includedir@ ++infodir = @infodir@ ++install_sh = @install_sh@ ++kbuilddir = @kbuilddir@ ++kinclude_CFLAGS = @kinclude_CFLAGS@ ++ksourcedir = @ksourcedir@ ++libdir = @libdir@ ++libexecdir = @libexecdir@ ++libxtables_CFLAGS = @libxtables_CFLAGS@ ++libxtables_LIBS = @libxtables_LIBS@ ++localedir = @localedir@ ++localstatedir = @localstatedir@ ++lt_ECHO = @lt_ECHO@ ++mandir = @mandir@ ++mkdir_p = @mkdir_p@ ++oldincludedir = @oldincludedir@ ++pdfdir = @pdfdir@ ++prefix = @prefix@ ++program_transform_name = @program_transform_name@ ++psdir = @psdir@ ++regular_CFLAGS = @regular_CFLAGS@ ++sbindir = @sbindir@ ++sharedstatedir = @sharedstatedir@ ++srcdir = @srcdir@ ++sysconfdir = @sysconfdir@ ++target_alias = @target_alias@ ++top_build_prefix = @top_build_prefix@ ++top_builddir = @top_builddir@ ++top_srcdir = @top_srcdir@ ++xtlibdir = @xtlibdir@ ++XA_SRCDIR = ${srcdir} ++XA_TOPSRCDIR = ${top_srcdir} ++XA_ABSTOPSRCDIR = ${abs_top_srcdir} ++_mcall = -f ${top_builddir}/Makefile.iptrules ++all: all-am ++ ++.SUFFIXES: ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --foreign extensions/LUA/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++tags: TAGS ++TAGS: ++ ++ctags: CTAGS ++CTAGS: ++ ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile all-local ++installdirs: ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-local mostlyclean-am ++ ++distclean: distclean-am ++ -rm -f Makefile ++distclean-am: clean-am distclean-generic ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: install-exec-local ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-generic mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: ++ ++.MAKE: install-am install-strip ++ ++.PHONY: all all-am all-local check check-am clean clean-generic \ ++ clean-libtool clean-local distclean distclean-generic \ ++ distclean-libtool distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am install-dvi \ ++ install-dvi-am install-exec install-exec-am install-exec-local \ ++ install-html install-html-am install-info install-info-am \ ++ install-man install-pdf install-pdf-am install-ps \ ++ install-ps-am install-strip installcheck installcheck-am \ ++ installdirs maintainer-clean maintainer-clean-generic \ ++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ++ ps ps-am uninstall uninstall-am ++ ++export XA_SRCDIR ++export XA_TOPSRCDIR ++export XA_ABSTOPSRCDIR ++ ++all-local: user-all-local ++ ++install-exec-local: user-install-local ++ ++clean-local: user-clean-local ++ ++user-all-local: ++ ${MAKE} ${_mcall} all; ++ ++# Have no user-install-data-local ATM ++user-install-local: user-install-exec-local ++ ++user-install-exec-local: ++ ${MAKE} ${_mcall} install; ++ ++user-clean-local: ++ ${MAKE} ${_mcall} clean; ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: ++ +--- /dev/null ++++ b/extensions/LUA/Mbuild +@@ -0,0 +1,3 @@ ++# -*- Makefile -*- ++ ++obj-${build_LUA} += libxt_LUA.so +--- /dev/null ++++ b/extensions/LUA/nf_lua.c +@@ -0,0 +1,64 @@ ++#if defined(__KERNEL__) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#endif ++ ++#include "lua.h" ++#include "lobject.h" /*sizeof(udata) */ ++#include "lauxlib.h" ++#include "controller.h" ++ ++#if defined(__KERNEL__) /* reachs until luaopen_nflib */ ++ ++ ++static int32_t nf_get_random(lua_State *L) ++{ ++ uint32_t rand = 0; ++ ++ get_random_bytes(&rand, sizeof(uint32_t )); ++ lua_pushnumber(L, rand); ++ return 1; ++} ++ ++static int32_t nf_get_time(lua_State *L) ++{ ++ lua_pushnumber(L, jiffies_to_msecs(jiffies_64)); ++ return 1; ++} ++ ++static const struct luaL_Reg nf_lua_lib_f [] = { ++ { "get_random", nf_get_random }, ++ { "get_time", nf_get_time }, ++ { NULL, NULL } ++}; ++ ++void luaopen_nflib(lua_State *L) ++{ ++ int32_t top; ++ ++ luaL_register(L, NETFILTER_LIB, nf_lua_lib_f); ++ lua_pop(L, 1); ++ ++ /* registering verdicts inside the _G */ ++ lua_getglobal(L, "_G"); ++ top = lua_gettop(L); ++ ++ lua_pushinteger(L, XT_CONTINUE); ++ lua_setfield(L, top, "XT_CONTINUE"); /* continiue with next rule */ ++ ++ lua_pushinteger(L, NF_DROP); ++ lua_setfield(L, top, "NF_DROP"); /* stop traversal in the current table hook and drop packet */ ++ ++ lua_pushinteger(L, NF_ACCEPT); ++ lua_setfield(L, top, "NF_ACCEPT"); /* stop traversal in the current table hook and accept packet */ ++ ++ lua_pop(L, 1); /* pop _G */ ++} ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/prot_buf_dynamic.c +@@ -0,0 +1,486 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++ ++ ++ ++struct protocol_buf * dyn_prot_buf_array[MAX_NR_OF_DYN_PROT_BUFS] = { NULL }; ++ ++ ++/* LUA_API: the function 'field_dynamic_setter' acts as a wrapper around ++ * a given Lua field setter function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'set' ++ * member of the protocol_field. We call this function passing the actual ++ * segment as byte array and the set value. ++ * ++ * Paramters: ++ * 1. lua_packet_segment (implicit) ++ * 2. some lua value ++ * ++ * Upvalues: ++ * 1. pointer to the protocol buffer ++ * 2. field index ++ * ++ * Returns: ++ * 1. true or false if the 'set' was successful ++ */ ++int32_t field_dynamic_setter(lua_State *L) ++{ ++ size_t nbytes; ++ lua_packet_segment * array; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].set); ++ if (!lua_isfunction(L, -1)) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); ++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); ++ array->length = seg->length; ++ array->start = seg->start + seg->offset; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ lua_pushvalue(L, 2); /* push value to set */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ pr_debug("Error: %s \n", lua_tostring(L, -1)); ++ lua_pop(L, 1); ++ lua_pushboolean(L, 0); ++ } ++ return 1; ++} ++ ++/* LUA_API: the function 'field_dynamic_getter' acts as a wrapper around ++ * a given Lua field getter function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'get' ++ * member of the protocol_field. We call this function passing the actual ++ * segment as byte array. ++ * ++ * Paramters: ++ * 1. lua_packet_segment (implicit) ++ * ++ * Upvalues: ++ * 1. pointer to the protocol buffer ++ * 2. field index ++ * ++ * Returns: ++ * 1. true or false if the 'get' was successful ++ */ ++int32_t field_dynamic_getter(lua_State *L) ++{ ++ size_t nbytes; ++ lua_packet_segment * array; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].get); ++ if (!lua_isfunction(L, -1)) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); ++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); ++ array->length = seg->length; ++ array->start = seg->start + seg->offset; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ if (lua_pcall(L, 1, 1, 0) != 0) { ++ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); ++ lua_pop(L, 1); ++ lua_pushboolean(L, 0); ++ } ++ return 1; ++} ++ ++/* LUA_API: the function 'has_protocol_dynamic' acts as a wrapper around ++ * a given lua has_protocol function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'has_protocol' ++ * member of the protocol_buffer. We call this function passing the actual ++ * segment. ++ * ++ * Paramters: ++ * 1. lua_packet_segment ++ * 2. protocol type ++ * ++ * Returns: ++ * 1. true or false if the payload field contains the given protocol ++ */ ++int32_t has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t type) ++{ ++ lua_packet_segment *seg_new; ++ int32_t res = 0; ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->has_protocol); ++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ seg_new->start = seg->start; ++ seg_new->offset = seg->offset; ++ seg_new->length = seg->length; ++ seg_new->changes = NULL; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ lua_pushinteger(L, type); /* push the protocol type */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); ++ lua_pop(L, 1); ++ return 0; ++ } ++ res = lua_toboolean(L, -1); ++ lua_pop(L, 1); ++ ++ return res; ++} ++ ++/* LUA_API: the function 'get_field_changes_dynamic' acts as a wrapper around ++ * a given lua get_field_changes function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'get_field_changes' ++ * member of the protocol_buffer. We call this function passing the actual ++ * segment. The lua function must return two lua table containing the offset ++ * and length changes (in bits). ++ * ++ * Paramters: ++ * 1. lua_packet_segment ++ * ++ * Returns: ++ * 1. new allocated field_changes struct ++ */ ++struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) ++{ ++ lua_packet_segment *seg_new; ++ struct field_changes * changes; ++ int32_t nr_of_changes, i; ++ ++ lua_getglobal(L, (char *)prot_buf->get_field_changes); ++ ++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ seg_new->start = seg->start; ++ seg_new->offset = seg->offset; ++ seg_new->length = seg->length; ++ seg_new->changes = NULL; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ ++ if (lua_pcall(L, 1, 2, 0) != 0) ++ luaL_error(L, "inside get_field_changes_dynamic. %s\n", lua_tostring(L, -1)); ++ ++ /* the function call must return a table containing length changes */ ++ luaL_checktype(L, -1, LUA_TTABLE); ++ /* the function call must return a table containing offset changes */ ++ luaL_checktype(L, -2, LUA_TTABLE); ++ /* both tables have to be of same size */ ++ if (lua_objlen(L, -1) != lua_objlen(L, -2)) ++ luaL_error(L, "the provided tables are not of equal size"); ++ ++ nr_of_changes = lua_objlen(L, -1); ++ changes = get_allocated_field_changes(L, nr_of_changes); ++ ++ /* loop over the tables */ ++ for (i = 1; i < nr_of_changes; i++) { ++ lua_rawgeti(L, -1, i); /* push length value of field at index i */ ++ changes->field_length_changes[i - 1] = luaL_checkinteger(L, -1); ++ lua_pop(L, 1); /* pop offset value */ ++ ++ lua_rawgeti(L, -2, i); /* push offset value of field at index i */ ++ changes->field_offset_changes[i - 1] = luaL_checkinteger(L, -1); ++ lua_pop(L, 1); /* pop length value */ ++ } ++ ++ /* pop both tables */ ++ lua_pop(L, 2); ++ ++ return changes; ++} ++ ++/* C_INT: 'get_free_protocol_index' is only used internally. This function ++ * gets a free slot inside the array holding all the protocol buffers. ++ * There are several ways to get to this information. In this case I take ++ * the way over the reflected array SUPPORTED_PROTOCOL_TABLE inside the ++ * Lua state. Since this function is called at laodtime, we do not have ++ * to care about performance. ++ */ ++static int32_t get_free_protocol_index(lua_State *L) ++{ ++ int32_t protocol_index; ++ ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ protocol_index = lua_objlen(L, -1) + 1; ++ lua_pop(L, 1); ++ return protocol_index; ++} ++ ++/* C_API: 'free_dynamic_prot_buf' frees the allocated memory of a given ++ * dynamic protocol buffer. this function is normally called inside a ++ * cleanup routine. Be aware, before running this function you must be ++ * sure that no references to the dynamic protocol buffers were available. ++ * It's recomended to close the Lua state before calling the function. */ ++void free_dynamic_prot_buf(struct protocol_buf * prot_buf) ++{ ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ for (; field->name != NULL; field++) { ++ if (field->get) kfree(field->get); ++ if (field->set) kfree(field->set); ++ if (field->name) kfree((char *)field->name); ++ } ++ ++ if (prot_buf->payload_field) kfree(prot_buf->payload_field); ++ if (prot_buf->has_protocol) kfree(prot_buf->has_protocol); ++ ++ if (prot_buf->get_field_changes) kfree(prot_buf->get_field_changes); ++ kfree((char *)prot_buf->name); ++ kfree(prot_buf); ++ return; ++} ++ ++void cleanup_dynamic_prot_bufs(void) ++{ ++ int32_t i; ++ ++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { ++ if (dyn_prot_buf_array[i]) { ++ free_dynamic_prot_buf(dyn_prot_buf_array[i]); ++ dyn_prot_buf_array[i] = NULL; ++ } ++ } ++ return; ++} ++ ++ ++/* C_INT: 'free_protocol_fields' is used internally as a helper function for ++ * 'register_dynamic_protbuf'. It is used when durin registration an error ++ * occurs and the afore allocated fields needed to be freed. */ ++static inline void free_protocol_fields(struct protocol_field * prot_fields, int32_t i) ++{ ++ struct protocol_field * f; ++ ++ while (i >= 0) { ++ f = &prot_fields[i]; ++ if (f->name) kfree((void *)f->name); ++ if (f->get) kfree((void *)f->get); ++ if (f->set) kfree((void *)f->set); ++ kfree((void *)f); ++ i--; ++ } ++} ++ ++/* LUA_API: 'register_dynamic_protbuf' is called from within the Lua script. ++ * it takes a Lua table representing the dynamic protocol buffer as parameter. ++ * e.g.: ++ * eth_prot_buf = { ++ * name = "packet_eth_dyn", ++ * payload_field = "data", ++ * protocol_fields = { ++ * {"dmac", 0, 48, nil, nil }, ++ * {"smac", 48, 48, nil, nil }, ++ * {"type", 96, 16, nil, nil }, ++ * {"data", 112, 0, nil, nil }, ++ * }, ++ * has_protocol = "eth_dyn_has_protocol", ++ * get_field_changes = "eth_dyn_get_field_changes" ++ * } ++ * register_dynamic_protbuf(eth_prot_buf) ++ * ++ * the table gets parsed and a new protocol_buf struct is allocated and ++ * initialized using 'register_protbuf', which is also used for the static ++ * protocol buffers. This enables an identical behavior like the static ++ * protocol buffers. The dynamic protocol buffers are not garbage collected, ++ * use 'free_dynamic_protbuf' to free them after closing the Lua state. ++ */ ++static int32_t register_dynamic_protbuf(lua_State *L) ++{ ++ struct protocol_buf *prot_buf; ++ struct protocol_field *field, sentinel = PROT_FIELD_SENTINEL; ++ int32_t nr_of_fields, i; ++ ++ prot_buf = (struct protocol_buf *)kmalloc(sizeof(struct protocol_buf), GFP_KERNEL); ++ prot_buf->is_dynamic = 1; ++ ++ /* check if parameter is a table */ ++ luaL_checktype(L, 1, LUA_TTABLE); ++ ++ /* initialize prot_buf.name */ ++ lua_getfield(L, 1, "name"); ++ prot_buf->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->name, luaL_checkstring(L, -1)); ++ lua_pop(L, 1); /* pop res from lua_getfield */ ++ ++ /* check if protocol buffer is already registered */ ++ lua_getglobal(L, prot_buf->name); ++ if (!lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop res from lua_getglobal */ ++ pr_debug("protocol_buf '%s' already registered.\n", prot_buf->name); ++ goto free_prot_buf; ++ } ++ lua_pop(L, 1); /* pop res from lua_getglobal */ ++ ++ /* initialize payload field */ ++ lua_getfield(L, 1, "payload_field"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->payload_field = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy(prot_buf->payload_field, lua_tostring(L, -1)); ++ }else ++ prot_buf->payload_field = NULL; ++ lua_pop(L, 1); /* pop res from lua_getfield */ ++ ++ /* initialize protocol_fields field*/ ++ lua_getfield(L, 1, "protocol_fields"); ++ if (!lua_istable(L, -1)) { ++ pr_debug("invalid protocol_fields table.\n"); ++ goto err2; ++ ++ } ++ ++ nr_of_fields = lua_objlen(L, -1); ++ prot_buf->protocol_fields = (struct protocol_field *)kmalloc((nr_of_fields + 1) * sizeof(struct protocol_field), GFP_KERNEL); ++ ++ for (i = 1; i <= nr_of_fields; i++) { ++ field = &prot_buf->protocol_fields[i - 1]; ++ /* initialize protocol field */ ++ lua_rawgeti(L, -1, i); /* push field-table */ ++ if (!lua_istable(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field at %i.\n", i); ++ goto err; ++ } ++ ++ /* initialize protocol field name */ ++ lua_rawgeti(L, -1, 1); ++ if (!lua_isstring(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field name at %i.\n", i); ++ goto err; ++ } ++ ++ field->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char*)field->name, lua_tostring(L, -1)); ++ lua_pop(L, 1); /* pop field name */ ++ ++ /* initialize protocol field offset */ ++ lua_rawgeti(L, -1, 2); ++ if (!lua_isnumber(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field offset at %i.\n", i); ++ goto err; ++ } ++ field->offset = lua_tointeger(L, -1); ++ lua_pop(L, 1); /* pop field offset */ ++ ++ /* initialize protocol field length */ ++ lua_rawgeti(L, -1, 3); ++ if (!lua_isnumber(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field length at %i.\n", i); ++ goto err; ++ } ++ field->length = lua_tointeger(L, -1); ++ lua_pop(L, 1); /* pop field length */ ++ ++ /* initialize protocol field getter */ ++ lua_rawgeti(L, -1, 4); ++ if (lua_isstring(L, -1)) { ++ field->get = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)field->get, lua_tostring(L, -1)); /* the get-wrapper knows about the piggybacked string */ ++ }else ++ field->get = NULL; ++ lua_pop(L, 1); /* pop field getter */ ++ ++ /* initialize protocol field setter */ ++ lua_rawgeti(L, -1, 5); ++ if (lua_isstring(L, -1)) { ++ field->set = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)field->set, lua_tostring(L, -1)); /* the set-wrapper knows about the piggybacked string */ ++ }else ++ field->set = NULL; ++ lua_pop(L, 1); /* pop field setter */ ++ ++ /* field initialization completed */ ++ lua_pop(L, 1); /* pop field-table */ ++ } ++ ++ /* put sentinel at the end of protocol_fields */ ++ memcpy(&prot_buf->protocol_fields[nr_of_fields], &sentinel, sizeof(sentinel)); ++ lua_pop(L, 1); /* pop protocol-fields-table */ ++ ++ /* initialize has_protocol field */ ++ lua_getfield(L, 1, "has_protocol"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->has_protocol = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->has_protocol, lua_tostring(L, -1)); /* the has_protocol-wrapper knows about the piggybacked string */ ++ }else ++ prot_buf->has_protocol = NULL; ++ lua_pop(L, 1); /* pop has_protocol */ ++ ++ /* initialize get_field_changes field */ ++ lua_getfield(L, 1, "get_field_changes"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->get_field_changes = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->get_field_changes, lua_tostring(L, -1)); /* the get_field_changes-wrapper knows about the piggybacked string */ ++ }else ++ prot_buf->get_field_changes = NULL; ++ lua_pop(L, 1); /* pop get_field_changes */ ++ ++ /* Storing the pointer to the DYNAMIC protbuf within dyn_prot_buf_array, in order to free it at cleanup */ ++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { ++ if (!dyn_prot_buf_array[i]) { ++ dyn_prot_buf_array[i] = prot_buf; ++ break; ++ }else ++ goto err; ++ } ++ ++ /* call the "common" register_protbuf */ ++ register_protbuf(L, prot_buf, get_free_protocol_index(L)); /* register prot_buf as it is done with the static ones */ ++ ++ return 0; ++ ++err: ++ kfree(prot_buf->protocol_fields); ++err2: ++ if (prot_buf->payload_field) kfree(prot_buf->payload_field); ++free_prot_buf: ++ kfree((void *)prot_buf->name); ++ kfree(prot_buf); ++ ++ luaL_error(L, "one or more error happend while registering a dynamic protocol buffer, please consult the debug log"); ++ ++ return 0; ++ ++} ++ ++void luaopen_protbuf_dynamic(lua_State *L) ++{ ++ lua_getglobal(L, "_G"); ++ lua_pushcclosure(L, register_dynamic_protbuf, 0); ++ lua_setfield(L, -2, "register_dynamic_protbuf"); ++ lua_pop(L, 1); /* pop _G */ ++ return; ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_ethernet.c +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++ ++ ++static int32_t eth_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ uint8_t *embedded_protocol = seg->start + seg->offset + 12 /*bytes*/; ++ unsigned short res = (unsigned short)((embedded_protocol[1] << CHAR_BIT) | (embedded_protocol[0] << CHAR_BIT)); ++ ++ switch (res) { ++ case 0x0800: /* 1: Internet Protocol (IP) */ ++ if (protocol_type == PACKET_IP) return 1; ++ break; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static const struct protocol_field eth_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "dmac", 0, 48, NULL, NULL }, ++ { "smac", 48, 48, NULL, NULL }, ++ { "type", 96, 16, NULL, NULL }, ++ { "data", 112, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf eth_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_ETH, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)ð_protocol_fields, ++ .has_protocol = ð_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++ ++void luaopen_protbuf_eth(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)ð_protocol_buf, PACKET_ETH); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_helpers.c +@@ -0,0 +1,216 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++#include ++#include /* kmalloc */ ++#endif ++ ++#include "controller.h" ++ ++int32_t get_header_size(struct protocol_buf * prot_buf) ++{ ++ int32_t bit_counter = 0; ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ for (; field->name; field++) ++ bit_counter += field->length; ++ ++ return bit_counter >> 3; ++} ++ ++ ++int32_t set_32_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint32_t *)(seg->start + seg->offset) = (uint32_t )htonl(luaL_checkinteger(L, 2)); ++ return 0; ++} ++int32_t get_32_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, ntohl(*((uint32_t *)(seg->start + seg->offset)))); ++ return 1; ++} ++ ++int32_t set_16_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint16_t *)(seg->start + seg->offset) = (uint16_t)htons(luaL_checkinteger(L, 2)); ++ return 0; ++} ++int32_t get_16_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, ntohs(*((uint16_t *)(seg->start + seg->offset)))); ++ return 1; ++} ++ ++int32_t set_lower_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; ++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); ++ ++ *pos &= 0x0F; /* reset lower 4 bits*/ ++ *pos |= b; ++ ++ return 0; ++} ++ ++int32_t get_lower_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) >> 4); ++ return 1; ++} ++ ++int32_t set_upper_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; ++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); ++ ++ *pos &= 0xF0; /* reset upper 4 bits*/ ++ *pos |= (b >> 4); ++ ++ return 0; ++} ++ ++int32_t get_upper_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) & 0x0F); ++ return 1; ++} ++ ++ ++int32_t set_8_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint8_t *)(seg->start + seg->offset) = (uint8_t)luaL_checkinteger(L, 2); ++ return 0; ++} ++ ++int32_t get_8_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, *(uint8_t *)(seg->start + seg->offset)); ++ return 1; ++} ++ ++int32_t set_1_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ unsigned long l = 0; ++ ++ memcpy(&l, (seg->start + seg->offset), seg->length); ++ l |= (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); ++ memcpy((seg->start + seg->offset), &l, seg->length); ++ ++ return 0; ++} ++ ++int32_t get_1_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ unsigned long l = 0; ++ uint32_t bit = 0; ++ ++ memcpy(&l, (seg->start + seg->offset), seg->length); ++ bit = l & (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); ++ ++ lua_pushboolean(L, bit); ++ return 1; ++} ++ ++int32_t get_string_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ /* Warning we cast from uchar to char */ ++ lua_pushlstring(L, (char *)seg->start + seg->offset, seg->length); ++ return 1; ++} ++ ++int32_t set_data_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ lua_packet_segment * data = checkbytearray(L, 2); ++ ++ pr_debug("seg->length %u, data->length %u\n", seg->length, data->length); ++ ++ if (seg->length >= data->length) ++ memcpy((seg->start + seg->offset), data->start, data->length); ++ else ++ luaL_error(L, "provided byte array too big for given packet segment"); ++ return 0; ++} ++ ++struct field_changes * get_allocated_field_changes(lua_State *L, int32_t nr_of_fields) ++{ ++ struct field_changes * changes; ++ ++ changes = kmalloc(sizeof(struct field_changes), GFP_ATOMIC); ++ ++ if (!changes) ++ goto failure; ++ ++ changes->field_length_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); ++ if (!changes->field_length_changes) ++ goto free1; ++ ++ changes->field_offset_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); ++ if (!changes->field_offset_changes) ++ goto free2; ++ ++ memset(changes->field_length_changes, 0, nr_of_fields * sizeof(int)); ++ memset(changes->field_offset_changes, 0, nr_of_fields * sizeof(int)); ++ ++ changes->ref_count = 1; ++ ++ return changes; ++ ++free2: kfree(changes->field_length_changes); ++free1: kfree(changes); ++failure: ++ if (!changes) luaL_error(L, "couldnt allocate memory inside 'get_allocated_field_changes'"); ++ return NULL; /* only to omit warnings */ ++} +\ No newline at end of file +--- /dev/null ++++ b/extensions/LUA/prot_buf_icmp.c +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++ ++static int32_t icmp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 0; ++} ++ ++static const struct protocol_field icmp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "type", 0, 8, NULL, NULL }, ++ { "code", 8, 8, NULL, NULL }, ++ { "checksum", 16, 16, NULL, NULL }, ++ { "id", 32, 16, NULL, NULL }, ++ { "sequence", 48, 16, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf icmp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_ICMP, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&icmp_protocol_fields, ++ .has_protocol = &icmp_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_icmp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&icmp_protocol_buf, PACKET_ICMP); ++} ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_ip.c +@@ -0,0 +1,209 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++ #include ++#endif ++ ++#include "controller.h" ++ ++ ++#define IP_FMT "%u.%u.%u.%u" ++#define IP_ACC(buf) buf[0], buf[1], buf[2], buf[3] ++ ++ ++static int32_t ip_version_set(lua_State *L) ++{ ++ uint8_t version_checked; ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *version_seg = seg->start + seg->offset; ++ int32_t version = luaL_checkinteger(L, 2); ++ ++ luaL_argcheck(L, version >= 0 && version <= 15, 1, "version number invalid"); ++ ++ version_checked = (uint8_t)version; ++ ++ version_seg[0] &= (uint8_t)0x0F; /* reset version bits */ ++ version_seg[0] |= version_checked << 4; ++ ++ return 0; ++} ++static int32_t ip_version_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *version_seg = seg->start + seg->offset; ++ uint8_t v = version_seg[0] & 0xF0; ++ ++ v >>= 4; ++ ++ lua_pushinteger(L, v); ++ return 1; ++} ++ ++static int32_t ip_ihl_set(lua_State *L) ++{ ++ uint8_t ihl_checked; ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *ihl_seg = seg->start + seg->offset; ++ int32_t ihl = luaL_checkinteger(L, 2); ++ ++ luaL_argcheck(L, ihl >= 5 && ihl <= 15, 1, "ip header length invalid"); // RFC 791 5x32 = 160 bits ++ ++ ihl_checked = (uint8_t)ihl; ++ ++ ihl_seg[0] &= (uint8_t)0xF0; /* reset ihl bits */ ++ ihl_seg[0] |= ihl_checked; ++ ++ return 0; ++} ++static int32_t ip_ihl_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *ihl_seg = seg->start + seg->offset; ++ uint8_t v = ihl_seg[0] & 0x0F; ++ ++ lua_pushinteger(L, v); ++ return 1; ++} ++ ++static int32_t ip_addr_set(lua_State *L) ++{ ++ int32_t field_id = lua_tointeger(L, lua_upvalueindex(2)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *addr_seg = seg->start + seg->offset; ++ uint32_t old_addr; ++ char *ip = (char *)luaL_checkstring(L, 2); ++ uint32_t a, b, c, d; ++ struct sk_buff * skb = (struct sk_buff *)lua_touserdata(L, 3); ++ ++ /* for tcp / udp checksumming*/ ++ uint32_t prot_offset; ++ uint8_t *check, *protocol_seg; ++ ++ /* end */ ++ ++ sscanf(ip, IP_FMT, &a, &b, &c, &d); ++ ++ luaL_argcheck(L, a < 256 && b < 256 && c < 256 && d < 256, 1, "invalid ip addr"); ++ ++ old_addr = *((uint32_t *)addr_seg); ++ addr_seg[0] = (uint8_t)a; ++ addr_seg[1] = (uint8_t)b; ++ addr_seg[2] = (uint8_t)c; ++ addr_seg[3] = (uint8_t)d; ++ ++#if defined(__KERNEL__) ++ if (old_addr != *(uint32_t *)addr_seg) { ++ int32_t offset = (field_id == 10) ? -2 : -6; /* offset from saddr or daddr */ ++ ++ csum_replace4((uint16_t *)(addr_seg + offset), old_addr, *(uint32_t *)addr_seg); ++ ++ prot_offset = (field_id == 10) ? -3 : -7; /* offset from saddr or daddr */ ++ protocol_seg = seg->start + seg->offset + prot_offset; ++ ++ if (skb && (protocol_seg[0] == 0x06 || protocol_seg[0] == 0x11)) { /* is payload TCP or UDP ? */ ++ ++ check = seg->start + seg->offset; /* tmp res */ ++ check += (field_id == 10) ? 8 : 16; /* the start of the payload, depending saddr or daddr */ ++ check += (protocol_seg[0] == 0x06) ? 16 : 6; /* the start of the checksum, depending on TCP or UDP */ ++ ++ inet_proto_csum_replace4((__sum16 *)check, skb, old_addr, *(uint32_t *)addr_seg, 1); ++ ++ lua_pop(L, 1); ++ } ++ } ++#endif ++ return 0; ++} ++ ++ ++ ++ ++ ++static int32_t ip_addr_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *addr_seg = seg->start + seg->offset; ++ ++ char buf[16]; /*max: 255.255.255.255\0 --> 16 chars */ ++ ++ sprintf(buf, IP_FMT, IP_ACC(addr_seg)); ++ lua_pushstring(L, buf); ++ return 1; ++} ++ ++static int32_t ip_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ uint8_t * embedded_protocol = seg->start + seg->offset + 9 /*bytes*/; ++ ++ switch (embedded_protocol[0]) { ++ case 0x01: /* 1: Internet Control Message Protocol (ICMP) */ ++ if (protocol_type == PACKET_ICMP) return 1; ++ break; ++ case 0x02: /* 2: Internet Group Management Protocol (IGMP) */ ++ break; ++ case 0x06: /* 6: Transmission Control Protocol (TCP) */ ++ if (protocol_type == PACKET_TCP) return 1; ++ break; ++ case 0x11: /* 17: User Datagram Protocol (UDP) */ ++ if (protocol_type == PACKET_UDP) return 1; ++ break; ++ case 0x59: /* 89: Open Shortest Path First (OSPF) */ ++ break; ++ case 0x84: /* 132: Stream Control Transmission Protocol (SCTP) */ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const struct protocol_field ip_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "version", 0, 4, ip_version_get, ip_version_set }, ++ { "ihl", 4, 4, ip_ihl_get, ip_ihl_set }, ++ { "tos", 8, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "tot_len", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "id", 32, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "flags", 48, 3, get_1_bit_generic, set_1_bit_generic }, ++ { "frag_off", 51, 13, NULL, NULL }, ++ { "ttl", 64, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "protocol", 72, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "check", 80, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "saddr", 96, 32, ip_addr_get, ip_addr_set }, ++ { "daddr", 128, 32, ip_addr_get, ip_addr_set }, ++ { "data", 160, 0, NULL, set_data_generic }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf ip_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_IP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&ip_protocol_fields, ++ .has_protocol = &ip_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_ip(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&ip_protocol_buf, PACKET_IP); ++} ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_raw.c +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++static int32_t raw_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static const struct protocol_field raw_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "data", 0, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf raw_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_RAW, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&raw_protocol_fields, ++ .has_protocol = &raw_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_raw(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&raw_protocol_buf, PACKET_RAW); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_tcp.c +@@ -0,0 +1,188 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++ #include ++#endif ++#include "controller.h" ++ ++ ++static int32_t tcp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static int32_t tcp_set_checksum(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++#if defined(__KERNEL__) ++ uint8_t * check_seg = seg->start + seg->offset; ++ uint8_t * tcp_hdr = check_seg - 16; ++ uint8_t * saddr = tcp_hdr - 8; ++ uint8_t * daddr = saddr + 4; ++ uint32_t len = 20 + (seg->changes->field_length_changes[11] / 8) + (seg->changes->field_length_changes[10] / 8); ++ unsigned short checksum = tcp_v4_check(len, *(uint32_t *)saddr, *(uint32_t *)daddr, ++ csum_partial(tcp_hdr, len, 0)); ++ ++ memcpy(check_seg, &checksum, sizeof(unsigned short)); ++#endif ++ return 0; ++} ++ ++ ++static const struct protocol_field tcp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "seq", 32, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "ack", 64, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "data_off", 96, 4, get_lower_4_bit_generic, set_lower_4_bit_generic }, ++ { "reserved", 100, 4, get_upper_4_bit_generic, set_upper_4_bit_generic }, ++ { "flags", 104, 8, get_1_bit_generic, set_1_bit_generic }, ++ { "window_size", 112, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "check", 128, 16, get_16_bit_generic, tcp_set_checksum }, ++ { "urgent", 144, 16, NULL, NULL }, ++ { "options", 160, 0, NULL, set_data_generic }, ++ { "data", 160, 0, NULL, set_data_generic }, /* begin of data depends on options */ ++ PROT_FIELD_SENTINEL, ++}; ++ ++ ++static const struct protocol_field tcp_options_and_data[] = { ++ /* field name offset length getter setter */ ++ { "MSS", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "WS", 0, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "SACK", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "TSVAL", 0, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "TSER", 0, 32, get_32_bit_generic, set_32_bit_generic }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++ ++static struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg); ++ ++static const struct protocol_buf tcp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TCP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&tcp_protocol_fields, ++ .has_protocol = &tcp_has_protocol, ++ .get_field_changes = &tcp_get_field_changes, ++}; ++ ++ ++static struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg); ++ ++static const struct protocol_buf tcp_options_and_data_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TCP_OPT, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&tcp_options_and_data, ++ .has_protocol = NULL, ++ .get_field_changes = &tcp_options_get_field_changes, ++}; ++ ++struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'data_off'-field, the length of ++ * the 'options' field has to be changed, as well as the length and offset ++ * of the 'data' field */ ++ uint8_t *tcp_hdr = seg->start + seg->offset; ++ ++ /* get the pointer to the 'data_off' field */ ++ uint8_t * data_off_field = tcp_hdr + 12; /* 12 bytes offset */ ++ /* extract the stored header length in bits */ ++ uint32_t tcp_hdr_len = ((*(uint8_t *)data_off_field) >> 4) * 32; ++ ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 12); ++ ++ /* depending on the tcp header length, change the length of the options*/ ++ changes->field_length_changes[10] = tcp_hdr_len - 160; ++ /* depending on the options length, change the offset of the data */ ++ changes->field_offset_changes[11] = changes->field_length_changes[10]; ++ changes->field_length_changes[11] = (seg->length * 8) - tcp_hdr_len; ++ ++ return changes; ++ ++} ++ ++struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'data_off'-field, the length of ++ * the 'options' field has to be changed, as well as the length and offset ++ * of the 'data' field */ ++ uint8_t *tcp_opt_hdr = seg->start + seg->offset; ++ ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 5); ++ ++ int32_t MSS = 0, WS = 0, SACK = 0, TS = 0, i; ++ ++ uint8_t b1, b2; ++ ++ for (i = 0; i < seg->length; i++) { ++ b1 = tcp_opt_hdr[i]; ++ b2 = tcp_opt_hdr[i + 1]; ++ ++ if (b1 == 0x00) ++ break; ++ ++ /* test for MSS */ ++ if (!MSS && (b1 == 0x02 && b2 == 0x04)) { ++ changes->field_offset_changes[0] = (i + 2) * CHAR_BIT; ++ MSS = 1; ++ } ++ ++ /* test for WS --- yet buggy somehow */ ++ if (!WS && (b1 == 0x03 && b2 == 0x03)) { ++ changes->field_offset_changes[1] = (i + 2) * CHAR_BIT; ++ WS = 1; ++ } ++ ++ /* test for SACK*/ ++ if (!SACK && (b1 == 0x04 && b2 == 0x02)) { ++ changes->field_offset_changes[2] = i * CHAR_BIT; /* has no value */ ++ SACK = 1; ++ } ++ ++ /* test for TS */ ++ if (!TS && (b1 == 0x08 && b2 == 0x0A)) { ++ changes->field_offset_changes[3] = (i + 2) * CHAR_BIT; ++ changes->field_offset_changes[4] = (i + 2 + 4) * CHAR_BIT; ++ TS = 1; ++ } ++ } ++ ++ return changes; ++ ++} ++ ++void luaopen_protbuf_tcp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tcp_protocol_buf, PACKET_TCP); ++} ++void luaopen_protbuf_tcp_options(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tcp_options_and_data_buf, PACKET_TCP_OPTIONS); ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_tftp.c +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++#include "controller.h" ++ ++static const struct protocol_field tftp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "opcode", 0, 16, get_16_bit_generic, NULL}, ++ { "filename", 0, 0, get_string_generic, NULL}, ++ { "mode", 0, 0, get_string_generic, NULL}, ++ { "block_nr", 0, 16, get_16_bit_generic, NULL}, ++ { "data", 0, 0, NULL, NULL}, ++ PROT_FIELD_SENTINEL, ++}; ++ ++struct field_changes * tftp_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'opcode'-field we have to change ++ * offsets and lengths */ ++ uint8_t *tftp_hdr = seg->start + seg->offset; ++ short opcode = ntohs(*((uint16_t *)tftp_hdr)); ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 5); ++ switch (opcode) { ++ case 1: /* Read Request (RRQ) */ ++ /* setting offset and length of field 'filename' */ ++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; ++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; ++ /* setting offset and length of field 'mode' */ ++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; ++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); ++ break; ++ case 2: /* Write Request (WRQ) */ ++ /* setting offset and length of field 'filename' */ ++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; ++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; ++ /* setting offset and length of field 'mode' */ ++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; ++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); ++ break; ++ case 3: /* Data (DATA) */ ++ /* setting offset of field 'block_nr' */ ++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; ++ /* setting offset of field 'data' */ ++ changes->field_offset_changes[4] = changes->field_offset_changes[3] + (sizeof(unsigned short) << 3); ++ break; ++ case 4: /* Acknowledgment (ACK) */ ++ /* setting offset of field 'block_nr' */ ++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; ++ break; ++ case 5: /* Error (ERROR) */ ++ /* we don't care ... yet */ ++ break; ++ default: ++ break; ++ } ++ ++ return changes; ++} ++ ++static const struct protocol_buf tftp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TFTP, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&tftp_protocol_fields, ++ .has_protocol = NULL, /* we don't need it, since we don't provide a payload field */ ++ .get_field_changes = tftp_get_field_changes, ++}; ++ ++void luaopen_protbuf_tftp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tftp_protocol_buf, PACKET_TFTP); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_udp.c +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++#endif ++ ++#include "controller.h" ++ ++ ++static int32_t udp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static const struct protocol_field udp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "length", 32, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "check", 48, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "data", 64, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf udp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_UDP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&udp_protocol_fields, ++ .has_protocol = &udp_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_udp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&udp_protocol_buf, PACKET_UDP); ++} +--- /dev/null ++++ b/extensions/LUA/xt_LUA.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#ifndef XT_LUA_H_ ++#define XT_LUA_H_ ++ ++#define MAX_FILENAME_SIZE 256 ++#define MAX_FUNCTION_SIZE 256 ++#define MAX_SCRIPT_SIZE 32768 ++#define LUA_STATE_ARRAY_SIZE 128 ++ ++/* the targetsize is stored in a u16, so max size of the xt_lua_tginfo cannot exceed 64K*/ ++struct xt_lua_tginfo { ++ char buf[MAX_SCRIPT_SIZE]; ++ char filename[MAX_FILENAME_SIZE]; ++ char function[MAX_FUNCTION_SIZE]; ++ __u64 script_size; ++ __u32 state_id; ++}; ++ ++#endif /* XT_LUA_H_ */ +--- /dev/null ++++ b/extensions/LUA/xt_LUA_target.c +@@ -0,0 +1,286 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "xt_LUA.h" ++ ++#include "controller.h" ++ ++/*::* ++ * lua_envs ++ * ---------- ++ * This array holds a defined number of `lua_envs`_ structures. ++ * The used array index is also used as the Lua state identifier. ++ * The size of the array is defined in `LUA_STATE_ARRAY_SIZE`_. ++ */ ++struct lua_env * lua_envs[LUA_STATE_ARRAY_SIZE]; ++ ++/*::* ++ * lua_state_refs ++ * -------------- ++ * This array holds the reference counts of the several `lua_nf_state`_s ++ * which are stored inside the array `lua_states`_. ++ */ ++uint32_t lua_state_refs[LUA_STATE_ARRAY_SIZE] = { 0 }; ++ ++/*::* ++ * lua_tg ++ * ------ ++ * This function is called whenever a packet matches all matching conditions ++ * inside a rule. It is the target. It extracts the state identifier comming ++ * inside the *xt_target_param* structure and uses it to access the proper ++ * Lua state inside the `lua_states`_ array. ++ * ++ * It then constructs a new Lua userdata of type *lua_packet_segment* and ++ * initializes it with the lowest network header available. This userdata ++ * is annotated with the Lua metatable `LUA_PACKET_SEG_RAW`_ which converts ++ * the userdata to a raw lua packet having all raw functions available. ++ * This raw packet is the single parameter to the Lua function *process_packet* ++ * which must be defined inside the Lua script provided by the user. So far ++ * hardcoded, may be later configured by Lua - subject to change. ++ * ++ * The process_packet function must return an integer value, the verdict. For ++ * convenience reasons xt_LUA exports the verdicts NF_ACCEPT, NF_DROP and ++ * XT_CONTINUE inside the *register_lua_packet_lib* function. ++ */ ++ ++spinlock_t lock = SPIN_LOCK_UNLOCKED; ++ ++static uint32_t ++lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) ++{ ++ uint32_t verdict; ++ lua_packet_segment *p; ++ const struct xt_lua_tginfo *info = par->targinfo; ++ lua_State * L; ++ ++ /* START critical section on SMP, PacketScript is on the sequential trail at the moment TODO*/ ++ spin_lock_irq(&lock); ++ ++ L = lua_envs[info->state_id]->L; ++ ++ if (!skb_make_writable(pskb, pskb->len)) ++ return NF_DROP; ++ ++ /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ ++ lua_getglobal(L, info->function); ++ ++ /* push the lua_packet_segment as a parameter */ ++ p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ if (pskb->mac_header) ++ p->start = pskb->mac_header; ++ else if (pskb->network_header) ++ p->start = pskb->network_header; ++ else if (pskb->transport_header) ++ p->start = pskb->transport_header; ++ p->offset = 0; ++ p->length = (unsigned long)pskb->tail - (unsigned long)p->start; ++ p->changes = NULL; ++ ++ /* marking userdata 'lua_packet_seg' with the corresponding metatable */ ++ luaL_getmetatable(L, LUA_PACKET_SEG_RAW); ++ lua_setmetatable(L, -2); ++ ++ /* push a reference to the skb as a parameter, needed at the moment for calculating TCP checksum, but I am not happy with it*/ ++ lua_pushlightuserdata(L, (void *)skb_get(pskb)); ++ ++ /* do the function call (2 argument, 1 result) */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ printk(KERN_ERR "LUA [%d]: pcall '%s' failed: %s\n", info->state_id, info->function, lua_tostring(L, -1)); ++ lua_pop(L, 1); ++ return NF_DROP; ++ } ++ ++ if (!lua_isnumber(L, -1)) { ++ printk(KERN_ERR "LUA [%d]: function '%s' must return a verdict\n", info->state_id, info->function); ++ lua_pop(L, 1); ++ return NF_DROP; ++ } ++ ++ verdict = lua_tonumber(L, -1); ++ lua_pop(L, 1); ++ ++ kfree_skb(pskb); ++ ++ /* END critical section on SMP */ ++ spin_unlock_irq(&lock); ++ ++ ++ return verdict; ++ ++} ++/* Helper for checkentry */ ++static bool load_script_into_state(uint32_t state_id, unsigned long script_size, char *script_buf) ++{ ++ char *buf = kmalloc(script_size, GFP_KERNEL); ++ int32_t ret; ++ struct lua_env * env = kmalloc(sizeof(struct lua_env), GFP_KERNEL); ++ ++ if (!script_size > 0) { ++ pr_debug("LUA [%d]: script_size %lu < 0\n", state_id, script_size); ++ return false; ++ } ++ ++ env->L = lua_open(); ++ luaopen_base(env->L); ++ luaopen_controller(env->L); ++ ++ lua_getglobal(env->L, "_G"); ++ lua_pushinteger(env->L, state_id); ++ lua_setfield(env->L, -2, "STATE_ID"); ++ lua_pop(env->L, 1); /* pop _G */ ++ ++ strncpy(buf, script_buf, script_size); ++ ret = luaL_loadbuffer(env->L, buf, script_size, "PacketScript, loadbuffer") || ++ lua_pcall(env->L, 0, 1, 0); ++ ++ if (ret != 0) { ++ printk(KERN_ERR "LUA [%d]: failure loading script, error %s \n", state_id, lua_tostring(env->L, -1)); ++ lua_pop(env->L, 1); ++ kfree(buf); ++ kfree(env); ++ return false; ++ } ++ ++ lua_envs[state_id] = env; ++ ++ kfree(buf); ++ ++ return true; ++} ++/*::* ++ * lua_tg_checkentry ++ * ----------------- ++ * This function is used as a kernel-side sanity check of the data comming ++ * from the iptables userspace program. Since this is the function which is ++ * called everytime a new rule (with -j xt_LUA) is injected, this function ++ * is used to do the bookkeeping work, such as counting the reference of ++ * several Lua states and the initialization of new states if needed. As an ++ * extra initialization step it loads the provided Lua script into the Lua ++ * state. ++ * ++ * Lua state initialization ++ * ~~~~~~~~~~~~~~~~~~~~~~~~ ++ * 1. If a new rule is inserted and there is no existing state for the given ++ * state identifier (default state identifier is 0) a new Lua state is ++ * initialized using *lua_open*. ++ * 2. The Lua base library is registered inside the newly initialized state. ++ * Have a look at *lua/lbaselib.c* to see what functions of the Lua base ++ * library are available inside Lua. ++ * 3. The Lua packet library is registered inside the Lua state using the ++ * function *register_lua_packet_lib*. So far this function only registers ++ * the Netfilter verdicts NF_ACCEPT, NF_DROP and XT_CONTINUE inside the ++ * global environment of the given Lua state. ++ * 4. All the protocol Buffers, and the functions for accessing the bytes are ++ * registered using *register_protocols*. ++ * ++ * Lua state reference counting ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * Bookkeeping of the Lua states inside the *lua_state_refs* array. The ++ * state identifier is mapped to the array index, which holds an integer ++ * counting the several initialized states. ++ * ++ * Loading the Lua script ++ * ~~~~~~~~~~~~~~~~~~~~~~ ++ * Copying the buffer which was initialized by the userspace program to a ++ * buffer with the proper size. The script is then loaded by the function ++ * xt_LUA_loadcode, which wrapps the *luaL_loadbuffer* function and does ++ * some workqueue initialization. So far this is done each time this function ++ * is called, subject to change. ++ */ ++static bool ++lua_tg_checkentry(const struct xt_tgchk_param *par) ++{ ++ const struct xt_lua_tginfo *info = par->targinfo; ++ ++ if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { ++ lua_state_refs[info->state_id]++; ++ return true; ++ } ++ return false; ++} ++ ++/*::* ++ * lua_tg_destroy ++ * -------------- ++ * This function is the counterpart of the `lua_tg_checkentry`_ function. It is ++ * responsible to free all the resources alocated inside the checkentry process. ++ * To be more specific it frees the Lua state using *lua_close* and kfree on all ++ * the dynamically allocated pointers to the registered dynamic protocol buffers. ++ * ++ * Additionally the function cares about decrementing the reference counters ++ * inside the array `lua_states`_. ++ */ ++static void ++lua_tg_destroy(const struct xt_tgdtor_param *par) ++{ ++ const struct xt_lua_tginfo *info = par->targinfo; ++ struct lua_env * env = lua_envs[info->state_id]; ++ ++ if (lua_state_refs[info->state_id] == 1) { ++ lua_close(env->L); ++ cleanup_dynamic_prot_bufs(); /* clean memory allocated by protocols defined in Lua */ ++ kfree(env); ++ pr_debug("LUA [%d]: Rule removed, close Lua state\n", info->state_id); ++ } else ++ pr_debug("LUA [%d]: Rule removed, Lua state stays open, referenced %d time(s)\n", ++ info->state_id, lua_state_refs[info->state_id] - 1); ++ ++ lua_state_refs[info->state_id]--; ++} ++ ++static struct xt_target lua_tg_reg __read_mostly = { ++ .name = "LUA", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .targetsize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .target = lua_tg, ++ .checkentry = lua_tg_checkentry, ++ .destroy = lua_tg_destroy, ++ .me = THIS_MODULE, ++}; ++ ++ ++static int32_t lua_tg_init(void) ++{ ++ return xt_register_target(&lua_tg_reg); ++} ++ ++static void lua_tg_exit(void) ++{ ++ xt_unregister_target(&lua_tg_reg); ++} ++ ++module_init(lua_tg_init); ++module_exit(lua_tg_exit); ++ ++MODULE_AUTHOR("Andre Graf "); ++MODULE_DESCRIPTION("Xtables: Processing of matched packets using the Lua scripting environment"); ++MODULE_ALIAS("ipt_LUA"); ++MODULE_ALIAS("ipt6t_LUA"); ++MODULE_ALIAS("arpt_LUA"); ++MODULE_ALIAS("ebt_LUA"); ++MODULE_LICENSE("GPL"); ++ ++ ++ +--- a/extensions/Kbuild ++++ b/extensions/Kbuild +@@ -28,6 +28,7 @@ obj-${build_pknock} += pknock/ + obj-${build_psd} += xt_psd.o + obj-${build_quota2} += xt_quota2.o + obj-${build_rtsp} += rtsp/ ++obj-${build_LUA} += LUA/ + + -include ${M}/*.Kbuild + -include ${M}/Kbuild.* +--- a/extensions/Mbuild ++++ b/extensions/Mbuild +@@ -23,3 +23,4 @@ obj-${build_pknock} += pknock/ + obj-${build_psd} += libxt_psd.so + obj-${build_quota2} += libxt_quota2.so + obj-${build_gradm} += libxt_gradm.so ++obj-${build_LUA} += LUA/ +--- a/mconfig ++++ b/mconfig +@@ -24,3 +24,4 @@ build_pknock=m + build_psd=m + build_quota2=m + build_rtsp=m ++build_LUA=m diff --git a/xtables-addons/patches/201-fix-lua-packetscript.patch b/xtables-addons/patches/201-fix-lua-packetscript.patch new file mode 100644 index 000000000..5a016e2ae --- /dev/null +++ b/xtables-addons/patches/201-fix-lua-packetscript.patch @@ -0,0 +1,136 @@ +--- a/extensions/LUA/xt_LUA_target.c ++++ b/extensions/LUA/xt_LUA_target.c +@@ -19,7 +19,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include "xt_LUA.h" +@@ -64,10 +64,10 @@ uint32_t lua_state_refs[LUA_STATE_ARRAY + * XT_CONTINUE inside the *register_lua_packet_lib* function. + */ + +-spinlock_t lock = SPIN_LOCK_UNLOCKED; ++DEFINE_SPINLOCK(lock); + + static uint32_t +-lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) ++lua_tg(struct sk_buff *pskb, const struct xt_action_param *par) + { + uint32_t verdict; + lua_packet_segment *p; +@@ -79,7 +79,7 @@ lua_tg(struct sk_buff *pskb, const struc + + L = lua_envs[info->state_id]->L; + +- if (!skb_make_writable(pskb, pskb->len)) ++ if (skb_ensure_writable(pskb, pskb->len)) + return NF_DROP; + + /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ +@@ -88,11 +88,11 @@ lua_tg(struct sk_buff *pskb, const struc + /* push the lua_packet_segment as a parameter */ + p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); + if (pskb->mac_header) +- p->start = pskb->mac_header; ++ p->start = skb_mac_header(pskb); + else if (pskb->network_header) +- p->start = pskb->network_header; ++ p->start = skb_network_header(pskb); + else if (pskb->transport_header) +- p->start = pskb->transport_header; ++ p->start = skb_transport_header(pskb); + p->offset = 0; + p->length = (unsigned long)pskb->tail - (unsigned long)p->start; + p->changes = NULL; +@@ -208,16 +208,16 @@ static bool load_script_into_state(uint3 + * some workqueue initialization. So far this is done each time this function + * is called, subject to change. + */ +-static bool ++static int + lua_tg_checkentry(const struct xt_tgchk_param *par) + { + const struct xt_lua_tginfo *info = par->targinfo; + + if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { + lua_state_refs[info->state_id]++; +- return true; ++ return 0; + } +- return false; ++ return -EINVAL; + } + + /*::* +--- a/extensions/LUA/lua/llimits.h ++++ b/extensions/LUA/lua/llimits.h +@@ -8,7 +8,6 @@ + #define llimits_h + + #include +-#include + + #include "lua.h" + +--- a/extensions/LUA/lua/lapi.c ++++ b/extensions/LUA/lua/lapi.c +@@ -4,9 +4,6 @@ + ** See Copyright Notice in lua.h + */ + +-#include +-#include +-#include + #include + + #define lapi_c +--- a/extensions/LUA/lua/ltable.c ++++ b/extensions/LUA/lua/ltable.c +@@ -18,7 +18,6 @@ + ** Hence even when the load factor reaches 100%, performance remains good. + */ + +-#include + #include + + #define ltable_c +--- a/extensions/LUA/lua/luaconf.h ++++ b/extensions/LUA/lua/luaconf.h +@@ -13,8 +13,12 @@ + #if !defined(__KERNEL__) + #include + #else ++#include ++ ++#undef UCHAR_MAX ++#undef BUFSIZ ++#undef NO_FPU + #define UCHAR_MAX 255 +-#define SHRT_MAX 32767 + #define BUFSIZ 8192 + #define NO_FPU + #endif +@@ -637,6 +641,8 @@ union luai_Cast { double l_d; long l_l; + */ + #if defined(__KERNEL__) + #undef LUA_USE_ULONGJMP ++#define setjmp __builtin_setjmp ++#define longjmp __builtin_longjmp + #endif + + #if defined(__cplusplus) +--- a/extensions/LUA/lua/llex.h ++++ b/extensions/LUA/lua/llex.h +@@ -10,6 +10,8 @@ + #include "lobject.h" + #include "lzio.h" + ++/* prevent conflict with definition from asm/current.h */ ++#undef current + + #define FIRST_RESERVED 257 + diff --git a/xtables-addons/patches/210-freebsd-build-fix.patch b/xtables-addons/patches/210-freebsd-build-fix.patch new file mode 100644 index 000000000..4f05d60eb --- /dev/null +++ b/xtables-addons/patches/210-freebsd-build-fix.patch @@ -0,0 +1,11 @@ +--- a/extensions/LUA/Makefile ++++ b/extensions/LUA/Makefile +@@ -110,7 +110,7 @@ PKG_CONFIG = /usr/bin/pkg-config + RANLIB = ranlib + SED = /bin/sed + SET_MAKE = +-SHELL = /bin/bash ++SHELL = /bin/sh + STRIP = strip + VERSION = 1.21 + abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA From 9011578db9dc0d9fe4658e91477de9220c291205 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 24 Sep 2021 21:08:43 +0200 Subject: [PATCH 0592/2059] Fix legend on multipath bandwidth graph --- luci-app-mptcp/luasrc/view/mptcp/multipath.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-mptcp/luasrc/view/mptcp/multipath.htm b/luci-app-mptcp/luasrc/view/mptcp/multipath.htm index 8d375c359..97ea6e956 100644 --- a/luci-app-mptcp/luasrc/view/mptcp/multipath.htm +++ b/luci-app-mptcp/luasrc/view/mptcp/multipath.htm @@ -238,8 +238,8 @@ labelup_25.parentNode.appendChild(textup); } - labeldn_scale.innerHTML = String.format('<%:(%d minutes window, %d seconds interval)%>', 3, data_wanted / 60); - labelup_scale.innerHTML = String.format('<%:(%d minutes window, %d seconds interval)%>', 3, data_wanted / 60); + labeldn_scale.innerHTML = String.format('<%:(%d minutes window, %d seconds interval)%>', 4, data_wanted / 60); + labelup_scale.innerHTML = String.format('<%:(%d minutes window, %d seconds interval)%>', 4, data_wanted / 60); /* render datasets, start update interval */ XHR.poll(3, '<%=build_url(bandwidthtotalurl, all)%>', null, From 527197973f759d459d26e1e5d21424dbee0d95c7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 24 Sep 2021 21:08:57 +0200 Subject: [PATCH 0593/2059] Set ecn to 2 --- shadowsocks-libev/files/shadowsocks.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-libev/files/shadowsocks.conf b/shadowsocks-libev/files/shadowsocks.conf index 9c6f64727..a80d14c85 100644 --- a/shadowsocks-libev/files/shadowsocks.conf +++ b/shadowsocks-libev/files/shadowsocks.conf @@ -52,5 +52,5 @@ net.ipv4.tcp_mtu_probing = 0 # Default conntrack is too small net.netfilter.nf_conntrack_max = 131072 -net.ipv4.tcp_ecn = 1 +net.ipv4.tcp_ecn = 2 #net.ipv4.tcp_sack = 0 From 63b58f3f763341e20df9b0d0a5a04de4141da79c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 25 Sep 2021 07:21:54 +0200 Subject: [PATCH 0594/2059] Update MLVPN --- .../resources/view/services/mlvpn.js | 6 ++++ mlvpn/Makefile | 6 ++-- mlvpn/files/etc/config/mlvpn | 3 +- mlvpn/files/etc/init.d/mlvpn | 8 +++-- mlvpn/patches/020-remove-cdefs.patch | 33 +++++++++++++++++++ 5 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 mlvpn/patches/020-remove-cdefs.patch diff --git a/luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js b/luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js index e7259c44a..f8bbc58c5 100644 --- a/luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js +++ b/luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js @@ -82,6 +82,12 @@ return L.view.extend({ o.rmempty = false; o.modalonly = true; + o = s.taboption('advanced', form.Value, 'latency_tolerance', _('Latency tolerance')); + o.default = '300'; + o.datatype = "uinteger"; + o.rmempty = false; + o.modalonly = true; + return m.render(); } }); diff --git a/mlvpn/Makefile b/mlvpn/Makefile index f9a356f02..1dbe8573b 100644 --- a/mlvpn/Makefile +++ b/mlvpn/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mlvpn -PKG_VERSION:=2263bab +PKG_VERSION:=8aa1b16 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/zehome/MLVPN.git -PKG_SOURCE_VERSION:=2263bab7e5f983e1daa33887b53120c12646398f -PKG_SOURCE_DATE:=2020-12-16 +PKG_SOURCE_VERSION:=8aa1b16d843ea68734e2520e39a34cb7f3d61b2b +PKG_SOURCE_DATE:=2021-08-14 #PKG_SOURCE_URL:=https://github.com/markfoodyburton/MLVPN.git #PKG_SOURCE_VERSION:=8f9720978b28c1954f9f229525333547283316d2 #PKG_SOURCE_DATE:=2018-09-03 diff --git a/mlvpn/files/etc/config/mlvpn b/mlvpn/files/etc/config/mlvpn index 1122794be..bbd90b5a4 100644 --- a/mlvpn/files/etc/config/mlvpn +++ b/mlvpn/files/etc/config/mlvpn @@ -8,4 +8,5 @@ config mlvpn 'general' option host '128.128.128.128' option firstport '65201' option interface_name 'mlvpn0' - option loss_tolerance '50' \ No newline at end of file + option loss_tolerance '50' + option latency_tolerance '300' diff --git a/mlvpn/files/etc/init.d/mlvpn b/mlvpn/files/etc/init.d/mlvpn index 33f6e75a9..3c11ff633 100755 --- a/mlvpn/files/etc/init.d/mlvpn +++ b/mlvpn/files/etc/init.d/mlvpn @@ -33,14 +33,15 @@ interface_multipath_settings() { } start() { - local enable timeout mode password reorder_buffer_size interface_name host firstport loss_tolerence + local enable timeout mode password reorder_buffer_size interface_name host firstport loss_tolerance latency_tolerance [ "$(uci -q get mlvpn.general.enable)" = "1" ] || return 1 interface_name="$(uci -q get mlvpn.general.interface_name)" timeout="$(uci -q get mlvpn.general.timeout)" mode="$(uci -q get mlvpn.general.mode)" password="$(uci -q get mlvpn.general.password)" reorder_buffer_size="$(uci -q get mlvpn.general.reorder_buffer_size)" - loss_tolerence="$(uci -q get mlvpn.general.loss_tolerence)" + loss_tolerance="$(uci -q get mlvpn.general.loss_tolerance)" + latency_tolerance="$(uci -q get mlvpn.general.latency_tolerance)" cleartext_data="$(uci -q get mlvpn.general.cleartext_data)" [ -z "$cleartext_data" ] && cleartext_data="0" host="$(uci -q get mlvpn.general.host)" @@ -59,7 +60,8 @@ start() { timeout = ${timeout} reorder_buffer = yes reorder_buffer_size = ${reorder_buffer_size} - loss_tolerence = ${loss_tolerence} + loss_tolerence = ${loss_tolerance} + latency_tolerence = ${latency_tolerance} cleartext_data = ${cleartext_data} password = "${password}" mtu = 1452 diff --git a/mlvpn/patches/020-remove-cdefs.patch b/mlvpn/patches/020-remove-cdefs.patch new file mode 100644 index 000000000..9b4bd38a0 --- /dev/null +++ b/mlvpn/patches/020-remove-cdefs.patch @@ -0,0 +1,33 @@ +--- a/src/vis.h.anc 2021-09-24 22:00:03.900321816 +0200 ++++ b/src/vis.h 2021-09-24 22:00:21.500028958 +0200 +@@ -79,7 +79,6 @@ + */ + #define UNVIS_END 1 /* no more characters */ + +-#include + + __BEGIN_DECLS + char *vis(char *, int, int, int); +--- a/src/vis.h.anc 2021-09-24 22:05:19.543069573 +0200 ++++ b/src/vis.h 2021-09-24 22:06:00.430389216 +0200 +@@ -80,7 +80,9 @@ + #define UNVIS_END 1 /* no more characters */ + + +-__BEGIN_DECLS ++#ifdef __cplusplus ++extern "C" { ++#endif + char *vis(char *, int, int, int); + int strvis(char *, const char *, int); + int stravis(char **, const char *, int); +@@ -93,6 +95,8 @@ + ssize_t strnunvis(char *, const char *, size_t) + __attribute__ ((__bounded__(__string__,1,3))); + +-__END_DECLS ++#ifdef __cplusplus ++} ++#endif + + #endif /* !HAVE_STRNVIS || BROKEN_STRNVIS */ From 32cbaf2c1c0ace19eab0565790b94fec5a50db99 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 25 Sep 2021 08:42:08 +0200 Subject: [PATCH 0595/2059] Remove not needed mlvpn patch --- mlvpn/patches/010-musl-fix.patch | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 mlvpn/patches/010-musl-fix.patch diff --git a/mlvpn/patches/010-musl-fix.patch b/mlvpn/patches/010-musl-fix.patch deleted file mode 100644 index 851d3dfca..000000000 --- a/mlvpn/patches/010-musl-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/privsep.c -+++ b/src/privsep.c -@@ -778,7 +778,7 @@ sig_got_chld(int sig) - pid_t pid; - - do { -- pid = waitpid(WAIT_ANY, NULL, WNOHANG); -+ pid = waitpid(-1, NULL, WNOHANG); - if (pid == child_pid && cur_state < STATE_QUIT) - cur_state = STATE_QUIT; - } while (pid > 0 || (pid == -1 && errno == EINTR)); From 0460b9dc5b41871b043eb12be4ad6ce68d2a823f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 25 Sep 2021 08:59:10 +0200 Subject: [PATCH 0596/2059] Update cryptodev --- cryptodev-linux/Makefile | 58 +++++++++++++++++++ .../010-fix-build-for-kernel-v5.9-rc1.patch | 32 ++++++++++ 2 files changed, 90 insertions(+) create mode 100644 cryptodev-linux/Makefile create mode 100644 cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch diff --git a/cryptodev-linux/Makefile b/cryptodev-linux/Makefile new file mode 100644 index 000000000..0c1f63a60 --- /dev/null +++ b/cryptodev-linux/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id$ + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=cryptodev-linux +PKG_VERSION:=1.12 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=https://codeload.github.com/$(PKG_NAME)/$(PKG_NAME)/tar.gz/$(PKG_NAME)-$(PKG_VERSION)? +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_HASH:=f51c2254749233b1b1d7ec9445158bd709f124f88e1c650fe2faac83c3a81938 +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=COPYING + +PKG_MAINTAINER:=Ansuel Smith + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/cryptodev + SUBMENU:=Cryptographic API modules + TITLE:=Driver for cryptographic acceleration + URL:=http://cryptodev-linux.org/ + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + DEPENDS:=+kmod-crypto-authenc +kmod-crypto-hash + FILES:=$(PKG_BUILD_DIR)/cryptodev.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,50,cryptodev) + MODPARAMS.cryptodev:=cryptodev_verbosity=-1 +endef + +define KernelPackage/cryptodev/description + This is a driver for that allows to use the Linux kernel supported + hardware ciphers by user-space applications. +endef + +define Build/Configure +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(KERNEL_MAKE_FLAGS) \ + KERNEL_DIR="$(LINUX_DIR)" +endef + +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR)/usr/include/crypto + $(CP) $(PKG_BUILD_DIR)/crypto/cryptodev.h $(STAGING_DIR)/usr/include/crypto/ +endef + +$(eval $(call KernelPackage,cryptodev)) diff --git a/cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch b/cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch new file mode 100644 index 000000000..09768a1f3 --- /dev/null +++ b/cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch @@ -0,0 +1,32 @@ +From 2f5e08aebf9229599aae7f25db752f74221cd71d Mon Sep 17 00:00:00 2001 +From: Joan Bruguera +Date: Fri, 14 Aug 2020 00:13:38 +0200 +Subject: [PATCH] Fix build for Linux 5.9-rc1 + +See also: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64019a2e467a288a16b65ab55ddcbf58c1b00187 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bce617edecada007aee8610fbe2c14d10b8de2f6 + https://lore.kernel.org/lkml/CAHk-=wj_V2Tps2QrMn20_W0OJF9xqNh52XSGA42s-ZJ8Y+GyKw@mail.gmail.com/ + +Signed-off-by: Joan Bruguera +--- + zc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/zc.c ++++ b/zc.c +@@ -76,10 +76,14 @@ int __get_userbuf(uint8_t __user *addr, + ret = get_user_pages_remote(task, mm, + (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0, + pg, NULL); +-#else ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)) + ret = get_user_pages_remote(task, mm, + (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0, + pg, NULL, NULL); ++#else ++ ret = get_user_pages_remote(mm, ++ (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0, ++ pg, NULL, NULL); + #endif + #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)) + up_read(&mm->mmap_sem); From a7e581c4de7ded0c09f39a8c2fbb6db87eb32b68 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 25 Sep 2021 10:36:37 +0200 Subject: [PATCH 0597/2059] Update tracebox and fix compilation with gcc 11 --- tracebox/Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tracebox/Makefile b/tracebox/Makefile index 59778d4bd..9c8117df7 100644 --- a/tracebox/Makefile +++ b/tracebox/Makefile @@ -14,11 +14,13 @@ PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_URL:=https://github.com/tracebox/tracebox.git +PKG_SOURCE_URL:=https://github.com/dreibh/tracebox.git +#https://github.com/tracebox/tracebox.git PKG_MAINTAINER:=Ycarus PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=v0.4.4 +PKG_SOURCE_VERSION:=4ad40ea43354038a04ad90aedae5874801c223e8 +#v0.4.4 PKG_FIXUP:=autoreconf @@ -43,7 +45,7 @@ CONFIGURE_VARS += \ CONFIGURE_ARGS += --enable-sniffer --enable-curl --with-libpcap="$(STAGING_DIR)/usr/include/" -EXTRA_CPPFLAGS += -fpermissive -Wno-variadic-macros +EXTRA_CPPFLAGS += -fpermissive -Wno-variadic-macros -std=c++14 TARGET_CFLAGS += -D_GNU_SOURCE From 770583c8c0656ed8348b9a4ab8085d97244ccd60 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 25 Sep 2021 16:45:08 +0200 Subject: [PATCH 0598/2059] Remove not needed patche --- .../010-fix-build-for-kernel-v5.9-rc1.patch | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch diff --git a/cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch b/cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch deleted file mode 100644 index 09768a1f3..000000000 --- a/cryptodev-linux/patches/010-fix-build-for-kernel-v5.9-rc1.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 2f5e08aebf9229599aae7f25db752f74221cd71d Mon Sep 17 00:00:00 2001 -From: Joan Bruguera -Date: Fri, 14 Aug 2020 00:13:38 +0200 -Subject: [PATCH] Fix build for Linux 5.9-rc1 - -See also: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64019a2e467a288a16b65ab55ddcbf58c1b00187 - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bce617edecada007aee8610fbe2c14d10b8de2f6 - https://lore.kernel.org/lkml/CAHk-=wj_V2Tps2QrMn20_W0OJF9xqNh52XSGA42s-ZJ8Y+GyKw@mail.gmail.com/ - -Signed-off-by: Joan Bruguera ---- - zc.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/zc.c -+++ b/zc.c -@@ -76,10 +76,14 @@ int __get_userbuf(uint8_t __user *addr, - ret = get_user_pages_remote(task, mm, - (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0, - pg, NULL); --#else -+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)) - ret = get_user_pages_remote(task, mm, - (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0, - pg, NULL, NULL); -+#else -+ ret = get_user_pages_remote(mm, -+ (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0, -+ pg, NULL, NULL); - #endif - #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)) - up_read(&mm->mmap_sem); From e1a07ddc5f01ffede7344e1e251ccaf031fe386f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 26 Sep 2021 19:14:39 +0200 Subject: [PATCH 0599/2059] Update modemmanager --- modemmanager/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 52d62b243..f0f53bfd2 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -10,9 +10,9 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_SOURCE_VERSION:=a20f2c052329a0d32ea3fee08e13d92b951f84fc +PKG_SOURCE_VERSION:=8755e85d13b1170882cd5108cf20a63d94573155 PKG_NAME:=modemmanager -PKG_VERSION:=1.18.0-$(PKG_SOURCE_VERSION) +PKG_VERSION:=1.18.2-$(PKG_SOURCE_VERSION) PKG_RELEASE:=10 #PKG_BUILD_DIR:=$(BUILD_DIR)/modemamanager-$ From 2266e72ae10a01a50d3d3f4765de26055bef7c03 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 26 Sep 2021 19:15:08 +0200 Subject: [PATCH 0600/2059] Remove umbim --- umbim/Makefile | 47 ------ umbim/files/lib/netifd/proto/mbim.sh | 240 --------------------------- 2 files changed, 287 deletions(-) delete mode 100644 umbim/Makefile delete mode 100644 umbim/files/lib/netifd/proto/mbim.sh diff --git a/umbim/Makefile b/umbim/Makefile deleted file mode 100644 index 36763767f..000000000 --- a/umbim/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=umbim -PKG_RELEASE:=2 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL=$(PROJECT_GIT)/project/umbim.git -PKG_SOURCE_DATE:=2019-09-11 -PKG_SOURCE_VERSION:=184b707ddaa0acee84d02e0ffe599cb8b67782bd -PKG_MIRROR_HASH:=482ff69144f81fafed99035840f5a24e772472f2df2f3ac0219d6de791ac5835 -PKG_MAINTAINER:=John Crispin - -PKG_LICENSE:=GPL-2.0 -PKG_LICENSE_FILES:= - -PKG_BUILD_PARALLEL:=1 - -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -define Package/umbim - SECTION:=net - CATEGORY:=Network - SUBMENU:=WWAN - DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim +wwan - TITLE:=Control utility for mobile broadband modems -endef - -define Package/umbim/description - umbim is a command line tool for controlling mobile broadband modems using - the MBIM-protocol. -endef - -TARGET_CFLAGS += \ - -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections - -TARGET_LDFLAGS += -Wl,--gc-sections - -define Package/umbim/install - $(INSTALL_DIR) $(1)/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/ - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,umbim)) diff --git a/umbim/files/lib/netifd/proto/mbim.sh b/umbim/files/lib/netifd/proto/mbim.sh deleted file mode 100644 index 136160997..000000000 --- a/umbim/files/lib/netifd/proto/mbim.sh +++ /dev/null @@ -1,240 +0,0 @@ -#!/bin/sh - -[ -n "$INCLUDE_ONLY" ] || { - . /lib/functions.sh - . ../netifd-proto.sh - init_proto "$@" -} -#DBG=-v - -proto_mbim_init_config() { - available=1 - no_device=1 - proto_config_add_string "device:device" - proto_config_add_string pdptype - proto_config_add_string apn - proto_config_add_string pincode - proto_config_add_string delay - proto_config_add_string auth - proto_config_add_string username - proto_config_add_string password - proto_config_add_defaults -} - -_proto_mbim_setup() { - local interface="$1" - local tid=2 - - local device pdptype apn pincode delay auth username password $PROTO_DEFAULT_OPTIONS - json_get_vars device pdptype apn pincode delay auth username password $PROTO_DEFAULT_OPTIONS - - [ -n "$ctl_device" ] && device=$ctl_device - - pdptype=$(echo "$pdptype" | awk '{print tolower($0)}') - case "$pdptype" in - ip ) - pdptype="ipv4" - ;; - ipv4 | ipv6 | ipv4v6 | ipv4-and-ipv6 ) - ;; - * ) pdptype="default" ;; - esac - - [ -n "$device" ] || { - echo "mbim[$$]" "No control device specified" - proto_notify_error "$interface" NO_DEVICE - proto_set_available "$interface" 0 - return 1 - } - [ -c "$device" ] || { - echo "mbim[$$]" "The specified control device does not exist" - proto_notify_error "$interface" NO_DEVICE - proto_set_available "$interface" 0 - return 1 - } - - devname="$(basename "$device")" - devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" - ifname="$( ls "$devpath"/net )" - - [ -n "$ifname" ] || { - echo "mbim[$$]" "Failed to find matching interface" - proto_notify_error "$interface" NO_IFNAME - proto_set_available "$interface" 0 - return 1 - } - - [ -n "$apn" ] || { - echo "mbim[$$]" "No APN specified" - proto_notify_error "$interface" NO_APN - return 1 - } - - [ -n "$delay" ] && sleep "$delay" - - echo "mbim[$$]" "Reading capabilities" - umbim $DBG -n -d $device caps || { - echo "mbim[$$]" "Failed to read modem caps" - proto_notify_error "$interface" PIN_FAILED - return 1 - } - tid=$((tid + 1)) - - [ "$pincode" ] && { - echo "mbim[$$]" "Sending pin" - umbim $DBG -n -t $tid -d $device unlock "$pincode" || { - echo "mbim[$$]" "Unable to verify PIN" - proto_notify_error "$interface" PIN_FAILED - proto_block_restart "$interface" - return 1 - } - } - tid=$((tid + 1)) - - echo "mbim[$$]" "Checking pin" - local pinstate="/var/run/mbim.$$.pinstate" - umbim $DBG -n -t $tid -d $device pinstate > "$pinstate" 2>&1 || { - local pin - pin=$(awk '$2=="pin:" {print $5}' "$pinstate") - # we only need pin1 (the SIM pin) to connect - [ "$pin" = "pin1" ] && { - echo "mbim[$$]" "PIN required" - proto_notify_error "$interface" PIN_FAILED - proto_block_restart "$interface" - return 1 - } - } - tid=$((tid + 1)) - - echo "mbim[$$]" "Checking subscriber" - umbim $DBG -n -t $tid -d $device subscriber || { - echo "mbim[$$]" "Subscriber init failed" - proto_notify_error "$interface" NO_SUBSCRIBER - return 1 - } - tid=$((tid + 1)) - - echo "mbim[$$]" "Register with network" - umbim $DBG -n -t $tid -d $device registration || { - echo "mbim[$$]" "Subscriber registration failed" - proto_notify_error "$interface" NO_REGISTRATION - return 1 - } - tid=$((tid + 1)) - - echo "mbim[$$]" "Attach to network" - umbim $DBG -n -t $tid -d $device attach || { - echo "mbim[$$]" "Failed to attach to network" - proto_notify_error "$interface" ATTACH_FAILED - return 1 - } - tid=$((tid + 1)) - - echo "mbim[$$]" "Connect to network" - while ! umbim $DBG -n -t $tid -d $device connect "$pdptype:$apn" "$auth" "$username" "$password"; do - tid=$((tid + 1)) - sleep 1; - done - tid=$((tid + 1)) - - echo "mbim[$$]" "Connected, obtain IP address and configure interface" - local config="/var/run/mbim.$$.config" - umbim $DBG -n -t $tid -d $device config > "$config" || { - echo "mbim[$$]" "Failed to obtain IP address" - proto_notify_error "$interface" CONFIG_FAILED - return 1 - } - tid=$((tid + 1)) - - proto_init_update "$ifname" 1 - proto_add_data - json_add_int tid $tid - proto_close_data - proto_send_update "$interface" - - local ip_4 ip_6 - ip_4=$(awk '$1=="ipv4address:" {print $2}' "$config") - ip_6=$(awk '$1=="ipv6address:" {print $2}' "$config") - [ -n "$ip_4" ] || [ -n "$ip_6" ] || { - echo "mbim[$$]" "Failed to obtain IP addresses" - proto_notify_error "$interface" CONFIG_FAILED - return 1 - } - - proto_init_update "$ifname" 1 - proto_set_keep 1 - local ip mask gateway mtu dns dns_servers - - [ -n "$ip_4" ] && { - echo "mbim[$$]" "Configure IPv4 on $ifname" - ip=${ip_4%%/*} - mask=${ip_4##*/} - gateway=$(awk '$1=="ipv4gateway:" {print $2}' "$config") - mtu=$(awk '$1=="ipv4mtu:" {print $2}' "$config") - [ "$mtu" ] && ip link set "$ifname" mtu "$mtu" - - proto_add_ipv4_address "$ip" "$mask" - [ "$defaultroute" = 0 ] || proto_add_ipv4_route 0.0.0.0 0 "$gateway" "$ip_4" "$metric" - [ "$peerdns" = 0 ] || { - dns_servers=$(awk '$1=="ipv4dnsserver:" {printf "%s ",$2}' "$config") - for dns in $dns_servers; do - proto_add_dns_server "$dns" - done - } - - } - [ -n "$ip_6" ] && { - echo "mbim[$$]" "Configure IPv6 on $ifname" - ip=${ip_6%%/*} - mask=${ip_6##*/} - gateway=$(awk '$1=="ipv6gateway:" {print $2}' "$config") - mtu=$(awk '$1=="ipv6mtu:" {print $2}' "$config") - [ "$mtu" ] && ip -6 link set "$ifname" mtu "$mtu" - - proto_add_ipv6_address "$ip" "$mask" - proto_add_ipv6_prefix "$ip_6" - [ "$defaultroute" = 0 ] || proto_add_ipv6_route "::" 0 "$gateway" "$metric" "" "$ip_6" - [ "$peerdns" = 0 ] || { - dns_servers=$(awk '$1=="ipv6dnsserver:" {printf "%s ",$2}' "$config") - for dns in $dns_servers; do - proto_add_dns_server "$dns" - done - } - } - - proto_send_update "$interface" - echo "mbim[$$]" "Connection setup complete" -} - -proto_mbim_setup() { - local ret - - _proto_mbim_setup "$@" - ret=$? - - rm -f "/var/run/mbim.$$."* - - [ "$ret" = 0 ] || { - logger "mbim bringup failed, retry in 15s" - sleep 15 - } - - return $ret -} - -proto_mbim_teardown() { - local interface="$1" - - local device tid - json_get_vars device tid - - [ -n "$ctl_device" ] && device=$ctl_device - - echo "mbim[$$]" "Stopping network" - [ -n "$tid" ] && umbim $DBG -t$tid -d "$device" disconnect - - proto_init_update "*" 0 - proto_send_update "$interface" -} - -[ -n "$INCLUDE_ONLY" ] || add_protocol mbim From 48dcdfa417372e89ac5b5de3675797b3d303559e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 26 Sep 2021 22:14:49 +0200 Subject: [PATCH 0601/2059] Remove momdemmanager --- modemmanager/Config.in | 21 - modemmanager/Makefile | 141 ------- modemmanager/README.md | 40 -- modemmanager/files/25-modemmanager-net | 35 -- modemmanager/files/25-modemmanager-tty | 18 - modemmanager/files/25-modemmanager-usb | 15 - modemmanager/files/modemmanager.common | 336 --------------- modemmanager/files/modemmanager.init | 36 -- modemmanager/files/modemmanager.proto | 550 ------------------------- 9 files changed, 1192 deletions(-) delete mode 100644 modemmanager/Config.in delete mode 100644 modemmanager/Makefile delete mode 100644 modemmanager/README.md delete mode 100644 modemmanager/files/25-modemmanager-net delete mode 100644 modemmanager/files/25-modemmanager-tty delete mode 100644 modemmanager/files/25-modemmanager-usb delete mode 100644 modemmanager/files/modemmanager.common delete mode 100755 modemmanager/files/modemmanager.init delete mode 100755 modemmanager/files/modemmanager.proto diff --git a/modemmanager/Config.in b/modemmanager/Config.in deleted file mode 100644 index 283a9e10a..000000000 --- a/modemmanager/Config.in +++ /dev/null @@ -1,21 +0,0 @@ -menu "Configuration" -depends on PACKAGE_modemmanager - - config MODEMMANAGER_WITH_MBIM - bool "Include MBIM support" - default y - help - Compile ModemManager with MBIM support - - config MODEMMANAGER_WITH_QMI - bool "Include QMI support" - default y - help - Compile ModemManager with QMI support - - config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS - bool "Allow AT commands via DBus" - default n - help - Compile ModemManager allowing AT commands without debug flag -endmenu diff --git a/modemmanager/Makefile b/modemmanager/Makefile deleted file mode 100644 index f0f53bfd2..000000000 --- a/modemmanager/Makefile +++ /dev/null @@ -1,141 +0,0 @@ -# -# Copyright (C) 2016 Velocloud Inc. -# Copyright (C) 2016 Aleksander Morgado -# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter -# -# This is free software, licensed under the GNU General Public License v2. -# - -include $(TOPDIR)/rules.mk - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_SOURCE_VERSION:=8755e85d13b1170882cd5108cf20a63d94573155 -PKG_NAME:=modemmanager -PKG_VERSION:=1.18.2-$(PKG_SOURCE_VERSION) -PKG_RELEASE:=10 - -#PKG_BUILD_DIR:=$(BUILD_DIR)/modemamanager-$ - -PKG_MAINTAINER:=Nicholas Smith -PKG_LICENSE:=GPL-2.0-or-later -PKG_LICENSE_FILES:=COPYING - -PKG_FIXUP:=autoreconf - -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk - -define Package/modemmanager/config - source "$(SOURCE)/Config.in" -endef - -define Package/modemmanager - SECTION:=net - CATEGORY:=Network - TITLE:=Control utility for any kind of mobile broadband modem - URL:=https://www.freedesktop.org/wiki/Software/ModemManager - DEPENDS:= \ - $(INTL_DEPENDS) \ - +glib2 \ - +dbus \ - +ppp \ - +MODEMMANAGER_WITH_MBIM:libmbim \ - +MODEMMANAGER_WITH_QMI:libqmi -endef - -define Package/modemmanager/description - ModemManager is a D-Bus-activated service which allows controlling mobile - broadband modems. Add kernel modules for your modems as needed. - Select Utilities/usb-modeswitch if needed. -endef - -CONFIGURE_ARGS += \ - --without-polkit \ - --without-udev \ - --without-systemdsystemunitdir \ - --disable-rpath \ - --disable-gtk-doc - -ifeq ($(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),y) - CONFIGURE_ARGS += --with-at-command-via-dbus -endif - -ifdef CONFIG_MODEMMANAGER_WITH_MBIM - CONFIGURE_ARGS += --with-mbim -else - CONFIGURE_ARGS += --without-mbim -endif - -ifdef CONFIG_MODEMMANAGER_WITH_QMI - CONFIGURE_ARGS += --with-qmi -else - CONFIGURE_ARGS += --without-qmi -endif - -define Build/Prepare - $(call Build/Prepare/Default) - ( cd "$(PKG_BUILD_DIR)"; \ - printf "all:\ninstall:\n" >po/Makefile.in.in; \ - ) -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/include/ModemManager/*.h $(1)/usr/include/ModemManager - $(INSTALL_DIR) $(1)/usr/include/libmm-glib - $(CP) $(PKG_INSTALL_DIR)/usr/include/libmm-glib/*.h $(1)/usr/include/libmm-glib - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so* $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ModemManager.pc $(1)/usr/lib/pkgconfig - $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mm-glib.pc $(1)/usr/lib/pkgconfig -endef - -define Package/modemmanager/install - $(INSTALL_DIR) $(1)/lib/udev/rules.d - $(INSTALL_DATA) $(PKG_INSTALL_DIR)/lib/udev/rules.d/*.rules $(1)/lib/udev/rules.d - - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin - - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin - - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so.* $(1)/usr/lib - - $(INSTALL_DIR) $(1)/usr/lib/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager - - $(INSTALL_DIR) $(1)/etc/dbus-1/system.d - $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d - - $(INSTALL_DIR) $(1)/usr/share/dbus-1/system-services - $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service $(1)/usr/share/dbus-1/system-services - - $(INSTALL_DIR) $(1)/usr/share/ModemManager - $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager - $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager - - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager - - $(INSTALL_DIR) $(1)/etc/hotplug.d/usb - $(INSTALL_DATA) ./files/25-modemmanager-usb $(1)/etc/hotplug.d/usb - - $(INSTALL_DIR) $(1)/etc/hotplug.d/net - $(INSTALL_DATA) ./files/25-modemmanager-net $(1)/etc/hotplug.d/net - - $(INSTALL_DIR) $(1)/etc/hotplug.d/tty - $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty - - $(INSTALL_DIR) $(1)/lib/netifd/proto - $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh -endef - -$(eval $(call BuildPackage,modemmanager)) diff --git a/modemmanager/README.md b/modemmanager/README.md deleted file mode 100644 index c9d880ea4..000000000 --- a/modemmanager/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# OpenWrt ModemManager - -## Description - -Cellular modem control and connectivity - -Optional libraries libmbim and libqmi are available. -Your modem may require additional kernel modules and/or the usb-modeswitch -package. - -## Usage - -Once installed, you can configure the 2G/3G/4G modem connections directly in -/etc/config/network as in the following example: - - config interface 'broadband' - option device '/sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2.1' - option proto 'modemmanager' - option apn 'ac.vodafone.es' - option allowedauth 'pap chap' - option username 'vodafone' - option password 'vodafone' - option pincode '7423' - option iptype 'ipv4' - option lowpower '1' - option signalrate '30' - -Only 'device' and 'proto' are mandatory options, the remaining ones are all -optional. - -The 'allowedauth' option allows limiting the list of authentication protocols. -It is given as a space-separated list of values, including any of the -following: 'pap', 'chap', 'mschap', 'mschapv2' or 'eap'. It will default to -allowing all protocols. - -The 'iptype' option supports any of these values: 'ipv4', 'ipv6' or 'ipv4v6'. -It will default to 'ipv4' if not given. - -The 'signalrate' option set's the signal refresh rate (in seconds) for the device. -You can call signal info with command: mmcli -m 0 --signal-get diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/25-modemmanager-net deleted file mode 100644 index 504c3d6b6..000000000 --- a/modemmanager/files/25-modemmanager-net +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016 Velocloud Inc -# Copyright (C) 2016 Aleksander Morgado - -# Load common utilities -. /usr/share/ModemManager/modemmanager.common - -# We require a interface name -[ -n "${INTERFACE}" ] || exit - -[ -n "$(echo ${INTERFACE} | grep -i sqm)" ] && exit -[ -d /sys${DEVPATH} ] || exit -[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit - -# Always make sure the rundir exists -mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" - -# Report network interface -mm_log "${ACTION} network interface ${INTERFACE}: event processed" -mm_report_event "${ACTION}" "${INTERFACE}" "net" "/sys${DEVPATH}" - -# Look for an associated cdc-wdm interface - -cdcwdm="" - -case "${ACTION}" in - "add") cdcwdm=$(mm_track_cdcwdm "${INTERFACE}") ;; - "remove") cdcwdm=$(mm_untrack_cdcwdm "${INTERFACE}") ;; -esac - -# Report cdc-wdm device, if any -[ -n "${cdcwdm}" ] && { - mm_log "${ACTION} cdc interface ${cdcwdm}: custom event processed" - mm_report_event "${ACTION}" "${cdcwdm}" "usbmisc" "/sys${DEVPATH}" -} diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/25-modemmanager-tty deleted file mode 100644 index 1d3fb9a35..000000000 --- a/modemmanager/files/25-modemmanager-tty +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016 Velocloud Inc -# Copyright (C) 2016 Aleksander Morgado - -# Load hotplug common utilities -. /usr/share/ModemManager/modemmanager.common - -# We require a device name -[ -n "$DEVNAME" ] || exit -[ -d /sys${DEVPATH} ] || exit -[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit - -# Always make sure the rundir exists -mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" - -# Report TTY -mm_log "${ACTION} serial interface ${DEVNAME}: event processed" -mm_report_event "${ACTION}" "${DEVNAME}" "tty" "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-usb b/modemmanager/files/25-modemmanager-usb deleted file mode 100644 index 565b7b9c9..000000000 --- a/modemmanager/files/25-modemmanager-usb +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# Copyright (C) 2019 Aleksander Morgado - -# We need to process only full USB device removal events, we don't -# want to process specific interface removal events. -[ "$ACTION" = remove ] || exit -[ -z "${INTERFACE}" ] || exit -[ -d /sys${DEVPATH} ] || exit -[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit - -# Load common utilities -. /usr/share/ModemManager/modemmanager.common - -mm_clear_modem_wait_status "/sys${DEVPATH}" -mm_cleanup_interface_by_sysfspath "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common deleted file mode 100644 index 8de8f2946..000000000 --- a/modemmanager/files/modemmanager.common +++ /dev/null @@ -1,336 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016 Velocloud Inc -# Copyright (C) 2016 Aleksander Morgado - -################################################################################ - -# If there is no interface that use modemmanager, exit -#[ -z "$(uci -q show network | grep modemmanager)" ] && exit -[ "$(uci -q get openmptcprouter.settings.modemmanager)" = "0" ] && exit - -. /lib/functions.sh -. /lib/netifd/netifd-proto.sh - -################################################################################ -# Runtime state - -MODEMMANAGER_RUNDIR="/var/run/modemmanager" -MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid" -MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache" -MODEMMANAGER_SYSFS_CACHE="${MODEMMANAGER_RUNDIR}/sysfs.cache" -MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" - -################################################################################ -# Common logging - -mm_log() { - logger -t "ModemManager" "hotplug: $*" -} - -################################################################################ -# Receives as input argument the full sysfs path of the device -# Returns the physical device sysfs path -# -# NOTE: this method only works when the device exists, i.e. it cannot be used -# on removal hotplug events - -mm_find_physdev_sysfs_path() { - local tmp_path="$1" - - while true; do - tmp_path=$(dirname "${tmp_path}") - - # avoid infinite loops iterating - [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return - - # the physical device will be that with a idVendor and idProduct pair of files - [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { - tmp_path=$(readlink -f "$tmp_path") - echo "${tmp_path}" - return - } - done -} - -################################################################################ - -# Returns the cdc-wdm name retrieved from sysfs -mm_track_cdcwdm() { - local wwan="$1" - local cdcwdm - - cdcwdm=$(ls "/sys/class/net/${wwan}/device/usbmisc/") - [ -n "${cdcwdm}" ] || return - - # We have to cache it for later, as we won't be able to get the - # associated cdc-wdm device on a remove event - echo "${wwan} ${cdcwdm}" >> "${MODEMMANAGER_CDCWDM_CACHE}" - - echo "${cdcwdm}" -} - -# Returns the cdc-wdm name retrieved from the cache -mm_untrack_cdcwdm() { - local wwan="$1" - local cdcwdm - - # Look for the cached associated cdc-wdm device - [ -f "${MODEMMANAGER_CDCWDM_CACHE}" ] || return - - cdcwdm=$(awk -v wwan="${wwan}" '!/^#/ && $0 ~ wwan { print $2 }' "${MODEMMANAGER_CDCWDM_CACHE}") - [ -n "${cdcwdm}" ] || return - - # Remove from cache - sed -i "/${wwan} ${cdcwdm}/d" "${MODEMMANAGER_CDCWDM_CACHE}" - - echo "${cdcwdm}" -} - -################################################################################ -# ModemManager needs some time from the ports being added until a modem object -# is exposed in DBus. With the logic here we do an explicit wait of N seconds -# for ModemManager to expose the new modem object, making sure that the wait is -# unique per device (i.e. per physical device sysfs path). - -# Gets the modem wait status as retrieved from the cache -mm_get_modem_wait_status() { - local sysfspath="$1" - - # If no sysfs cache file, we're done - [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return - - # Get status of the sysfs path - awk -v sysfspath="${sysfspath}" '!/^#/ && $0 ~ sysfspath { print $2 }' "${MODEMMANAGER_SYSFS_CACHE}" -} - -# Clear the modem wait status from the cache, if any -mm_clear_modem_wait_status() { - local sysfspath="$1" - - local escaped_sysfspath - - [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] && { - # escape '/', '\' and '&' for sed... - escaped_sysfspath=$(echo "$sysfspath" | sed -e 's/[\/&]/\\&/g') - sed -i "/${escaped_sysfspath}/d" "${MODEMMANAGER_SYSFS_CACHE}" - } -} - -# Sets the modem wait status in the cache -mm_set_modem_wait_status() { - local sysfspath="$1" - local status="$2" - - # Remove sysfs line before adding the new one with the new state - mm_clear_modem_wait_status "${sysfspath}" - - # Add the new status - echo "${sysfspath} ${status}" >> "${MODEMMANAGER_SYSFS_CACHE}" -} - -# Callback for config_foreach() -mm_get_modem_config_foreach_cb() { - local cfg="$1" - local sysfspath="$2" - - local proto - config_get proto "${cfg}" proto - [ "${proto}" = modemmanager ] || return 0 - - local dev - dev=$(uci_get network "${cfg}" device) - [ "${dev}" = "${sysfspath}" ] || return 0 - - echo "${cfg}" -} - -# Returns the name of the interface configured for this device -mm_get_modem_config() { - local sysfspath="$1" - - # Look for configuration for the given sysfs path - config_load network - config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}" -} - -# Wait for a modem in the specified sysfspath -mm_wait_for_modem() { - local cfg="$1" - local sysfspath="$2" - - # TODO: config max wait - local n=45 - local step=5 - - while [ $n -ge 0 ]; do - [ -d "${sysfspath}" ] || { - mm_log "error: ignoring modem detection request: no device at ${sysfspath}" - proto_set_available "${cfg}" 0 - return 1 - } - - # Check if the modem exists at the given sysfs path - if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 - then - mm_log "error: modem not detected at sysfs path" - else - mm_log "modem exported successfully at ${sysfspath}" - mm_log "setting interface '${cfg}' as available" - proto_set_available "${cfg}" 1 - return 0 - fi - - sleep $step - n=$((n-step)) - done - - mm_log "error: timed out waiting for the modem to get exported at ${sysfspath}" - proto_set_available "${cfg}" 0 - return 2 -} - -mm_report_modem_wait() { - local sysfspath=$1 - - local parent_sysfspath status - - parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") - [ -n "${parent_sysfspath}" ] || { - mm_log "error: parent device sysfspath not found" - return - } - - status=$(mm_get_modem_wait_status "${parent_sysfspath}") - case "${status}" in - "") - local cfg - - cfg=$(mm_get_modem_config "${parent_sysfspath}") - if [ -n "${cfg}" ]; then - mm_log "interface '${cfg}' is set to configure device '${parent_sysfspath}'" - mm_log "now waiting for modem at sysfs path ${parent_sysfspath}" - mm_set_modem_wait_status "${parent_sysfspath}" "processed" - # Launch subshell for the explicit wait - ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & - else - mm_log "no need to wait for modem at sysfs path ${parent_sysfspath}" - mm_set_modem_wait_status "${parent_sysfspath}" "ignored" - fi - ;; - "processed") - mm_log "already waiting for modem at sysfs path ${parent_sysfspath}" - ;; - "ignored") - ;; - *) - mm_log "error: unknown status read for device at sysfs path ${parent_sysfspath}" - ;; - esac -} - -################################################################################ -# Cleanup interfaces - -mm_cleanup_interface_cb() { - local cfg="$1" - - local proto - config_get proto "${cfg}" proto - [ "${proto}" = modemmanager ] || return 0 - - proto_set_available "${cfg}" 0 -} - -mm_cleanup_interfaces() { - config_load network - config_foreach mm_cleanup_interface_cb interface -} - -mm_cleanup_interface_by_sysfspath() { - local dev="$1" - - local cfg - cfg=$(mm_get_modem_config "$dev") - [ -n "${cfg}" ] || return - - mm_log "setting interface '$cfg' as unavailable" - proto_set_available "${cfg}" 0 -} - -################################################################################ -# Event reporting - -# Receives as input the action, the device name and the subsystem -mm_report_event() { - local action="$1" - local name="$2" - local subsystem="$3" - local sysfspath="$4" - - # Track/untrack events in cache - case "${action}" in - "add") - # On add events, store event details in cache (if not exists yet) - grep -qs "${name},${subsystem}" "${MODEMMANAGER_EVENTS_CACHE}" || \ - echo "${action},${name},${subsystem},${sysfspath}" >> "${MODEMMANAGER_EVENTS_CACHE}" - ;; - "remove") - # On remove events, remove old events from cache (match by subsystem+name) - sed -i "/${name},${subsystem}/d" "${MODEMMANAGER_EVENTS_CACHE}" - ;; - esac - - # Report the event - mm_log "event reported: action=${action}, name=${name}, subsystem=${subsystem}" - mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 1>/dev/null 2>&1 & - - # Wait for added modem if a sysfspath is given - [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" -} - -mm_report_event_from_cache_line() { - local event_line="$1" - - local action name subsystem sysfspath - action=$(echo "${event_line}" | awk -F ',' '{ print $1 }') - name=$(echo "${event_line}" | awk -F ',' '{ print $2 }') - subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }') - sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }') - - mm_log "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" - mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}" -} - -mm_report_events_from_cache() { - # Remove the sysfs cache - rm -f "${MODEMMANAGER_SYSFS_CACHE}" - - local n=60 - local step=1 - local mmrunning=0 - - # Wait for ModemManager to be available in the bus - while [ $n -ge 0 ]; do - sleep $step - mm_log "checking if ModemManager is available..." - - if ! mmcli -L >/dev/null 2>&1 - then - mm_log "ModemManager not yet available" - else - mmrunning=1 - break - fi - n=$((n-step)) - done - - [ ${mmrunning} -eq 1 ] || { - mm_log "error: couldn't report initial kernel events: ModemManager not running" - return - } - - # Report cached kernel events - while IFS= read -r event_line; do - mm_report_event_from_cache_line "${event_line}" - done < ${MODEMMANAGER_EVENTS_CACHE} -} diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init deleted file mode 100755 index b3f9f9290..000000000 --- a/modemmanager/files/modemmanager.init +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2016 Aleksander Morgado - -USE_PROCD=1 -START=70 - -stop_service() { - # Load common utils - . /usr/share/ModemManager/modemmanager.common - # Set all configured interfaces as unavailable - mm_cleanup_interfaces -} - -start_service() { - # Setup ModemManager service - # - # We will make sure that the rundir always exists, and we initially cleanup - # all interfaces flagging them as unavailable. - # - # The cached events processing will wait for MM to be available in DBus - # and will make sure all ports are re-notified to ModemManager every time - # it starts. - # - # All these commands need to be executed on every MM start, even after - # procd-triggered respawns, which is why they're all included as instance command - # - procd_open_instance - procd_set_param command sh -c ". /usr/share/ModemManager/modemmanager.common; \ - mkdir -m 0755 -p ${MODEMMANAGER_RUNDIR}; \ - mm_cleanup_interfaces; \ - ( mm_report_events_from_cache ) >/dev/null 2>&1 & \ - /usr/sbin/ModemManager" - procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" - procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" - procd_close_instance -} diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto deleted file mode 100755 index d24910b98..000000000 --- a/modemmanager/files/modemmanager.proto +++ /dev/null @@ -1,550 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016-2019 Aleksander Morgado - -[ -x /usr/bin/mmcli ] || exit 0 -[ -x /usr/sbin/pppd ] || exit 0 - -[ -n "$INCLUDE_ONLY" ] || { - . /lib/functions.sh - . ../netifd-proto.sh - . ./ppp.sh - init_proto "$@" -} - -cdr2mask () -{ - # Number of args to shift, 255..255, first non-255 byte, zeroes - set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0 - if [ "$1" -gt 1 ] - then - shift "$1" - else - shift - fi - echo "${1-0}"."${2-0}"."${3-0}"."${4-0}" -} - -# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue -# The second argument must be exactly the name of the field to read -# -# Sample output: -# $ mmcli -m 0 -K -# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 -# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 -# modem.generic.manufacturer : Dell Inc. -# modem.generic.model : DW5821e Snapdragon X20 LTE -# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 -# modem.generic.carrier-configuration : GCF -# modem.generic.carrier-configuration-revision : 08E00009 -# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE -# .... -modemmanager_get_field() { - local list=$1 - local field=$2 - local value="" - - [ -z "${list}" ] || [ -z "${field}" ] && return - - # there is always at least a whitespace after each key, and we use that as part of the - # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result - # when grepping for 'modem.generic.state'. - line=$(echo "${list}" | grep "${field} ") - value=$(echo ${line#*:}) - - # not found? - [ -n "${value}" ] || return 2 - - # only print value if set - [ "${value}" != "--" ] && echo "${value}" - return 0 -} - -# build a comma-separated list of values from the list -modemmanager_get_multivalue_field() { - local list=$1 - local field=$2 - local value="" - local length idx item - - [ -z "${list}" ] || [ -z "${field}" ] && return - - length=$(modemmanager_get_field "${list}" "${field}.length") - [ -n "${length}" ] || return 0 - [ "$length" -ge 1 ] || return 0 - - idx=1 - while [ $idx -le "$length" ]; do - item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") - [ -n "${item}" ] && [ "${item}" != "--" ] && { - [ -n "${value}" ] && value="${value}, " - value="${value}${item}" - } - idx=$((idx + 1)) - done - - # nothing built? - [ -n "${value}" ] || return 2 - - # only print value if set - echo "${value}" - return 0 -} - -modemmanager_cleanup_connection() { - local modemstatus="$1" - - local bearercount idx bearerpath - - bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") - - # do nothing if no bearers reported - [ -n "${bearercount}" ] && [ "$bearercount" -ge 1 ] && { - # explicitly disconnect just in case - mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1 - # and remove all bearer objects, if any found - idx=1 - while [ $idx -le "$bearercount" ]; do - bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[$idx\]") - mmcli --modem "${device}" --delete-bearer="${bearerpath}" >/dev/null 2>&1 - idx=$((idx + 1)) - done - } -} - -modemmanager_connected_method_ppp_ipv4() { - local interface="$1" - local ttyname="$2" - local username="$3" - local password="$4" - local allowedauth="$5" - - # all auth types are allowed unless a user given list is given - local authopts - local pap=1 - local chap=1 - local mschap=1 - local mschapv2=1 - local eap=1 - - [ -n "$allowedauth" ] && { - pap=0 chap=0 mschap=0 mschapv2=0 eap=0 - for auth in $allowedauth; do - case $auth in - "pap") pap=1 ;; - "chap") chap=1 ;; - "mschap") mschap=1 ;; - "mschapv2") mschapv2=1 ;; - "eap") eap=1 ;; - *) ;; - esac - done - } - - [ $pap -eq 1 ] || append authopts "refuse-pap" - [ $chap -eq 1 ] || append authopts "refuse-chap" - [ $mschap -eq 1 ] || append authopts "refuse-mschap" - [ $mschapv2 -eq 1 ] || append authopts "refuse-mschap-v2" - [ $eap -eq 1 ] || append authopts "refuse-eap" - - proto_run_command "${interface}" /usr/sbin/pppd \ - "${ttyname}" \ - 115200 \ - nodetach \ - noaccomp \ - nobsdcomp \ - nopcomp \ - novj \ - noauth \ - $authopts \ - ${username:+ user $username} \ - ${password:+ password $password} \ - lcp-echo-failure 5 \ - lcp-echo-interval 15 \ - lock \ - crtscts \ - nodefaultroute \ - usepeerdns \ - ipparam "${interface}" \ - ip-up-script /lib/netifd/ppp-up \ - ip-down-script /lib/netifd/ppp-down -} - -modemmanager_disconnected_method_ppp_ipv4() { - local interface="$1" - - echo "running disconnection (ppp method)" - - [ -n "${ERROR}" ] && { - local errorstring - errorstring=$(ppp_exitcode_tostring "${ERROR}") - case "$ERROR" in - 0) - ;; - 2) - proto_notify_error "$interface" "$errorstring" - proto_block_restart "$interface" - ;; - *) - proto_notify_error "$interface" "$errorstring" - ;; - esac - } || echo "pppd result code not given" - - proto_kill_command "$interface" -} - -modemmanager_connected_method_dhcp_ipv4() { - local interface="$1" - local wwan="$2" - local metric="$3" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - proto_send_update "${interface}" - - json_init - json_add_string name "${interface}_4" - json_add_string ifname "@${interface}" - json_add_string proto "dhcp" - proto_add_dynamic_defaults - [ -n "$metric" ] && json_add_int metric "${metric}" - json_close_object - ubus call network add_dynamic "$(json_dump)" -} - -modemmanager_connected_method_static_ipv4() { - local interface="$1" - local wwan="$2" - local address="$3" - local prefix="$4" - local gateway="$5" - local mtu="$6" - local dns1="$7" - local dns2="$8" - local metric="$9" - - local mask="" - - [ -n "${address}" ] || { - proto_notify_error "${interface}" ADDRESS_MISSING - return - } - - [ -n "${prefix}" ] || { - proto_notify_error "${interface}" PREFIX_MISSING - return - } - mask=$(cdr2mask "${prefix}") - - [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - echo "adding IPv4 address ${address}, netmask ${mask}" - proto_add_ipv4_address "${address}" "${mask}" - [ -n "${gateway}" ] && { - echo "adding default IPv4 route via ${gateway}" - proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" - } - [ -n "${dns1}" ] && { - echo "adding primary DNS at ${dns1}" - proto_add_dns_server "${dns1}" - } - [ -n "${dns2}" ] && { - echo "adding secondary DNS at ${dns2}" - proto_add_dns_server "${dns2}" - } - [ -n "$metric" ] && json_add_int metric "${metric}" - proto_send_update "${interface}" -} - -modemmanager_connected_method_dhcp_ipv6() { - local interface="$1" - local wwan="$2" - local metric="$3" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - proto_send_update "${interface}" - - json_init - json_add_string name "${interface}_6" - json_add_string ifname "@${interface}" - json_add_string proto "dhcpv6" - proto_add_dynamic_defaults - json_add_string extendprefix 1 # RFC 7278: Extend an IPv6 /64 Prefix to LAN - [ -n "$metric" ] && json_add_int metric "${metric}" - json_close_object - ubus call network add_dynamic "$(json_dump)" -} - -modemmanager_connected_method_static_ipv6() { - local interface="$1" - local wwan="$2" - local address="$3" - local prefix="$4" - local gateway="$5" - local mtu="$6" - local dns1="$7" - local dns2="$8" - local metric="$9" - - [ -n "${address}" ] || { - proto_notify_error "${interface}" ADDRESS_MISSING - return - } - - [ -n "${prefix}" ] || { - proto_notify_error "${interface}" PREFIX_MISSING - return - } - - [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - echo "adding IPv6 address ${address}, prefix ${prefix}" - proto_add_ipv6_address "${address}" "128" - proto_add_ipv6_prefix "${address}/${prefix}" - [ -n "${gateway}" ] && { - echo "adding default IPv6 route via ${gateway}" - proto_add_ipv6_route "${gateway}" "128" - proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}" - } - [ -n "${dns1}" ] && { - echo "adding primary DNS at ${dns1}" - proto_add_dns_server "${dns1}" - } - [ -n "${dns2}" ] && { - echo "adding secondary DNS at ${dns2}" - proto_add_dns_server "${dns2}" - } - [ -n "$metric" ] && json_add_int metric "${metric}" - proto_send_update "${interface}" -} - -modemmanager_disconnected_method_common() { - local interface="$1" - - echo "running disconnection (common)" - proto_notify_error "${interface}" MM_DISCONNECT_IN_PROGRESS - - proto_init_update "*" 0 - proto_send_update "${interface}" -} - -proto_modemmanager_init_config() { - available=1 - no_device=1 - proto_config_add_string device - proto_config_add_string apn - proto_config_add_string 'allowedauth:list(string)' - proto_config_add_string username - proto_config_add_string password - proto_config_add_string pincode - proto_config_add_string iptype - proto_config_add_int signalrate - proto_config_add_boolean lowpower - proto_config_add_defaults -} - -proto_modemmanager_setup() { - local interface="$1" - - local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface - local bearermethod_ipv4 bearermethod_ipv6 auth cliauth - local operatorname operatorid registration accesstech signalquality - - local device apn allowedauth username password pincode iptype metric signalrate - - local address prefix gateway mtu dns1 dns2 - - json_get_vars device apn allowedauth username password pincode iptype metric signalrate - - # validate sysfs path given in config - [ -n "${device}" ] || { - echo "No device specified" - proto_notify_error "${interface}" NO_DEVICE - proto_set_available "${interface}" 0 - return 1 - } - [ -e "${device}" ] || { - echo "Device not found in sysfs" - proto_set_available "${interface}" 0 - return 1 - } - - # validate that ModemManager is handling the modem at the sysfs path - modemstatus=$(mmcli --modem="${device}" --output-keyvalue) - modempath=$(modemmanager_get_field "${modemstatus}" "modem.dbus-path") - [ -n "${modempath}" ] || { - echo "Device not managed by ModemManager" - proto_notify_error "${interface}" DEVICE_NOT_MANAGED - proto_set_available "${interface}" 0 - return 1 - } - echo "modem available at ${modempath}" - - # always cleanup before attempting a new connection, just in case - modemmanager_cleanup_connection "${modemstatus}" - - # if allowedauth list given, build option string - for auth in $allowedauth; do - cliauth="${cliauth}${cliauth:+|}$auth" - done - - # setup connect args; APN mandatory (even if it may be empty) - echo "starting connection with apn '${apn}'..." - proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS - - connectargs="apn=${apn}${iptype:+,ip-type=${iptype}}${cliauth:+,allowed-auth=${cliauth}}${username:+,user=${username}}${password:+,password=${password}}${pincode:+,pin=${pincode}}" - mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { - proto_notify_error "${interface}" MM_CONNECT_FAILED - proto_block_restart "${interface}" - return 1 - } - - # check if Signal refresh rate is set - if [ -n "${signalrate}" ] && [ "${signalrate}" -eq "${signalrate}" ] 2>/dev/null; then - echo "setting signal refresh rate to ${signalrate} seconds" - mmcli --modem="${device}" --signal-setup="${signalrate}" - else - echo "signal refresh rate is not set" - fi - - # log additional useful information - modemstatus=$(mmcli --modem="${device}" --output-keyvalue) - operatorname=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-name") - [ -n "${operatorname}" ] && echo "network operator name: ${operatorname}" - operatorid=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-code") - [ -n "${operatorid}" ] && echo "network operator MCCMNC: ${operatorid}" - registration=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.registration-state") - [ -n "${registration}" ] && echo "registration type: ${registration}" - accesstech=$(modemmanager_get_multivalue_field "${modemstatus}" "modem.generic.access-technologies") - [ -n "${accesstech}" ] && echo "access technology: ${accesstech}" - signalquality=$(modemmanager_get_field "${modemstatus}" "modem.generic.signal-quality.value") - [ -n "${signalquality}" ] && echo "signal quality: ${signalquality}%" - - # we won't like it if there are more than one bearers, as that would mean the - # user manually created them, and that's unsupported by this proto - bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") - [ -n "${bearercount}" ] && [ "$bearercount" -eq 1 ] || { - proto_notify_error "${interface}" INVALID_BEARER_LIST - return 1 - } - - # load connected bearer information - bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") - bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) - - # load network interface and method information - beareriface=$(modemmanager_get_field "${bearerstatus}" "bearer.status.interface") - bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") - bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") - - # setup IPv4 - [ -n "${bearermethod_ipv4}" ] && { - echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}" - case "${bearermethod_ipv4}" in - "dhcp") - modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" - ;; - "static") - address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address") - prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.prefix") - gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.gateway") - mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu") - dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]") - dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]") - modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" - ;; - "ppp") - modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}" - ;; - *) - proto_notify_error "${interface}" UNKNOWN_METHOD - return 1 - ;; - esac - } - - # setup IPv6 - # note: if using ipv4v6, both IPv4 and IPv6 settings will have the same MTU and metric values reported - [ -n "${bearermethod_ipv6}" ] && { - echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}" - case "${bearermethod_ipv6}" in - "dhcp") - modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" - ;; - "static") - address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address") - prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.prefix") - gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.gateway") - mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu") - dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]") - dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]") - modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" - ;; - "ppp") - proto_notify_error "${interface}" "unsupported method" - return 1 - ;; - *) - proto_notify_error "${interface}" UNKNOWN_METHOD - return 1 - ;; - esac - } - - return 0 -} - -proto_modemmanager_teardown() { - local interface="$1" - - local modemstatus bearerpath errorstring - local bearermethod_ipv4 bearermethod_ipv6 - - local device lowpower iptype - json_get_vars device lowpower iptype - - echo "stopping network" - proto_notify_error "${interface}" MM_TEARDOWN_IN_PROGRESS - - # load connected bearer information, just the first one should be ok - modemstatus=$(mmcli --modem="${device}" --output-keyvalue) - bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") - [ -n "${bearerpath}" ] || { - echo "couldn't load bearer path" - return - } - - # load bearer connection methods - bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) - bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") - [ -n "${bearermethod_ipv4}" ] && - echo "IPv4 connection teardown required in interface ${interface}: ${bearermethod_ipv4}" - bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") - [ -n "${bearermethod_ipv6}" ] && - echo "IPv6 connection teardown required in interface ${interface}: ${bearermethod_ipv6}" - - # disconnection handling only requires special treatment in IPv4/PPP - [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}" - modemmanager_disconnected_method_common "${interface}" - - # disconnect - mmcli --modem="${device}" --simple-disconnect || - proto_notify_error "${interface}" DISCONNECT_FAILED - - # disable - mmcli --modem="${device}" --disable - proto_notify_error "${interface}" MM_MODEM_DISABLED - - # low power, only if requested - [ "${lowpower:-0}" -lt 1 ] || - mmcli --modem="${device}" --set-power-state-low -} - -[ -n "$INCLUDE_ONLY" ] || { - add_protocol modemmanager -} From 89f76f19aad658b6614b8bad1bc96dba30a728eb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Sep 2021 08:10:26 +0200 Subject: [PATCH 0602/2059] Revert "Remove momdemmanager" This reverts commit 48dcdfa417372e89ac5b5de3675797b3d303559e. --- modemmanager/Config.in | 21 + modemmanager/Makefile | 141 +++++++ modemmanager/README.md | 40 ++ modemmanager/files/25-modemmanager-net | 35 ++ modemmanager/files/25-modemmanager-tty | 18 + modemmanager/files/25-modemmanager-usb | 15 + modemmanager/files/modemmanager.common | 336 +++++++++++++++ modemmanager/files/modemmanager.init | 36 ++ modemmanager/files/modemmanager.proto | 550 +++++++++++++++++++++++++ 9 files changed, 1192 insertions(+) create mode 100644 modemmanager/Config.in create mode 100644 modemmanager/Makefile create mode 100644 modemmanager/README.md create mode 100644 modemmanager/files/25-modemmanager-net create mode 100644 modemmanager/files/25-modemmanager-tty create mode 100644 modemmanager/files/25-modemmanager-usb create mode 100644 modemmanager/files/modemmanager.common create mode 100755 modemmanager/files/modemmanager.init create mode 100755 modemmanager/files/modemmanager.proto diff --git a/modemmanager/Config.in b/modemmanager/Config.in new file mode 100644 index 000000000..283a9e10a --- /dev/null +++ b/modemmanager/Config.in @@ -0,0 +1,21 @@ +menu "Configuration" +depends on PACKAGE_modemmanager + + config MODEMMANAGER_WITH_MBIM + bool "Include MBIM support" + default y + help + Compile ModemManager with MBIM support + + config MODEMMANAGER_WITH_QMI + bool "Include QMI support" + default y + help + Compile ModemManager with QMI support + + config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS + bool "Allow AT commands via DBus" + default n + help + Compile ModemManager allowing AT commands without debug flag +endmenu diff --git a/modemmanager/Makefile b/modemmanager/Makefile new file mode 100644 index 000000000..f0f53bfd2 --- /dev/null +++ b/modemmanager/Makefile @@ -0,0 +1,141 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git +PKG_SOURCE_VERSION:=8755e85d13b1170882cd5108cf20a63d94573155 +PKG_NAME:=modemmanager +PKG_VERSION:=1.18.2-$(PKG_SOURCE_VERSION) +PKG_RELEASE:=10 + +#PKG_BUILD_DIR:=$(BUILD_DIR)/modemamanager-$ + +PKG_MAINTAINER:=Nicholas Smith +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +PKG_FIXUP:=autoreconf + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/modemmanager/config + source "$(SOURCE)/Config.in" +endef + +define Package/modemmanager + SECTION:=net + CATEGORY:=Network + TITLE:=Control utility for any kind of mobile broadband modem + URL:=https://www.freedesktop.org/wiki/Software/ModemManager + DEPENDS:= \ + $(INTL_DEPENDS) \ + +glib2 \ + +dbus \ + +ppp \ + +MODEMMANAGER_WITH_MBIM:libmbim \ + +MODEMMANAGER_WITH_QMI:libqmi +endef + +define Package/modemmanager/description + ModemManager is a D-Bus-activated service which allows controlling mobile + broadband modems. Add kernel modules for your modems as needed. + Select Utilities/usb-modeswitch if needed. +endef + +CONFIGURE_ARGS += \ + --without-polkit \ + --without-udev \ + --without-systemdsystemunitdir \ + --disable-rpath \ + --disable-gtk-doc + +ifeq ($(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),y) + CONFIGURE_ARGS += --with-at-command-via-dbus +endif + +ifdef CONFIG_MODEMMANAGER_WITH_MBIM + CONFIGURE_ARGS += --with-mbim +else + CONFIGURE_ARGS += --without-mbim +endif + +ifdef CONFIG_MODEMMANAGER_WITH_QMI + CONFIGURE_ARGS += --with-qmi +else + CONFIGURE_ARGS += --without-qmi +endif + +define Build/Prepare + $(call Build/Prepare/Default) + ( cd "$(PKG_BUILD_DIR)"; \ + printf "all:\ninstall:\n" >po/Makefile.in.in; \ + ) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/include/ModemManager/*.h $(1)/usr/include/ModemManager + $(INSTALL_DIR) $(1)/usr/include/libmm-glib + $(CP) $(PKG_INSTALL_DIR)/usr/include/libmm-glib/*.h $(1)/usr/include/libmm-glib + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so* $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ModemManager.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mm-glib.pc $(1)/usr/lib/pkgconfig +endef + +define Package/modemmanager/install + $(INSTALL_DIR) $(1)/lib/udev/rules.d + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/lib/udev/rules.d/*.rules $(1)/lib/udev/rules.d + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin + + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so.* $(1)/usr/lib + + $(INSTALL_DIR) $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager + + $(INSTALL_DIR) $(1)/etc/dbus-1/system.d + $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d + + $(INSTALL_DIR) $(1)/usr/share/dbus-1/system-services + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service $(1)/usr/share/dbus-1/system-services + + $(INSTALL_DIR) $(1)/usr/share/ModemManager + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager + $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager + + $(INSTALL_DIR) $(1)/etc/hotplug.d/usb + $(INSTALL_DATA) ./files/25-modemmanager-usb $(1)/etc/hotplug.d/usb + + $(INSTALL_DIR) $(1)/etc/hotplug.d/net + $(INSTALL_DATA) ./files/25-modemmanager-net $(1)/etc/hotplug.d/net + + $(INSTALL_DIR) $(1)/etc/hotplug.d/tty + $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty + + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh +endef + +$(eval $(call BuildPackage,modemmanager)) diff --git a/modemmanager/README.md b/modemmanager/README.md new file mode 100644 index 000000000..c9d880ea4 --- /dev/null +++ b/modemmanager/README.md @@ -0,0 +1,40 @@ +# OpenWrt ModemManager + +## Description + +Cellular modem control and connectivity + +Optional libraries libmbim and libqmi are available. +Your modem may require additional kernel modules and/or the usb-modeswitch +package. + +## Usage + +Once installed, you can configure the 2G/3G/4G modem connections directly in +/etc/config/network as in the following example: + + config interface 'broadband' + option device '/sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2.1' + option proto 'modemmanager' + option apn 'ac.vodafone.es' + option allowedauth 'pap chap' + option username 'vodafone' + option password 'vodafone' + option pincode '7423' + option iptype 'ipv4' + option lowpower '1' + option signalrate '30' + +Only 'device' and 'proto' are mandatory options, the remaining ones are all +optional. + +The 'allowedauth' option allows limiting the list of authentication protocols. +It is given as a space-separated list of values, including any of the +following: 'pap', 'chap', 'mschap', 'mschapv2' or 'eap'. It will default to +allowing all protocols. + +The 'iptype' option supports any of these values: 'ipv4', 'ipv6' or 'ipv4v6'. +It will default to 'ipv4' if not given. + +The 'signalrate' option set's the signal refresh rate (in seconds) for the device. +You can call signal info with command: mmcli -m 0 --signal-get diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/25-modemmanager-net new file mode 100644 index 000000000..504c3d6b6 --- /dev/null +++ b/modemmanager/files/25-modemmanager-net @@ -0,0 +1,35 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a interface name +[ -n "${INTERFACE}" ] || exit + +[ -n "$(echo ${INTERFACE} | grep -i sqm)" ] && exit +[ -d /sys${DEVPATH} ] || exit +[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report network interface +mm_log "${ACTION} network interface ${INTERFACE}: event processed" +mm_report_event "${ACTION}" "${INTERFACE}" "net" "/sys${DEVPATH}" + +# Look for an associated cdc-wdm interface + +cdcwdm="" + +case "${ACTION}" in + "add") cdcwdm=$(mm_track_cdcwdm "${INTERFACE}") ;; + "remove") cdcwdm=$(mm_untrack_cdcwdm "${INTERFACE}") ;; +esac + +# Report cdc-wdm device, if any +[ -n "${cdcwdm}" ] && { + mm_log "${ACTION} cdc interface ${cdcwdm}: custom event processed" + mm_report_event "${ACTION}" "${cdcwdm}" "usbmisc" "/sys${DEVPATH}" +} diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/25-modemmanager-tty new file mode 100644 index 000000000..1d3fb9a35 --- /dev/null +++ b/modemmanager/files/25-modemmanager-tty @@ -0,0 +1,18 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load hotplug common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a device name +[ -n "$DEVNAME" ] || exit +[ -d /sys${DEVPATH} ] || exit +[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report TTY +mm_log "${ACTION} serial interface ${DEVNAME}: event processed" +mm_report_event "${ACTION}" "${DEVNAME}" "tty" "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-usb b/modemmanager/files/25-modemmanager-usb new file mode 100644 index 000000000..565b7b9c9 --- /dev/null +++ b/modemmanager/files/25-modemmanager-usb @@ -0,0 +1,15 @@ +#!/bin/sh +# Copyright (C) 2019 Aleksander Morgado + +# We need to process only full USB device removal events, we don't +# want to process specific interface removal events. +[ "$ACTION" = remove ] || exit +[ -z "${INTERFACE}" ] || exit +[ -d /sys${DEVPATH} ] || exit +[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +mm_clear_modem_wait_status "/sys${DEVPATH}" +mm_cleanup_interface_by_sysfspath "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common new file mode 100644 index 000000000..8de8f2946 --- /dev/null +++ b/modemmanager/files/modemmanager.common @@ -0,0 +1,336 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +################################################################################ + +# If there is no interface that use modemmanager, exit +#[ -z "$(uci -q show network | grep modemmanager)" ] && exit +[ "$(uci -q get openmptcprouter.settings.modemmanager)" = "0" ] && exit + +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh + +################################################################################ +# Runtime state + +MODEMMANAGER_RUNDIR="/var/run/modemmanager" +MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid" +MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache" +MODEMMANAGER_SYSFS_CACHE="${MODEMMANAGER_RUNDIR}/sysfs.cache" +MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" + +################################################################################ +# Common logging + +mm_log() { + logger -t "ModemManager" "hotplug: $*" +} + +################################################################################ +# Receives as input argument the full sysfs path of the device +# Returns the physical device sysfs path +# +# NOTE: this method only works when the device exists, i.e. it cannot be used +# on removal hotplug events + +mm_find_physdev_sysfs_path() { + local tmp_path="$1" + + while true; do + tmp_path=$(dirname "${tmp_path}") + + # avoid infinite loops iterating + [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return + + # the physical device will be that with a idVendor and idProduct pair of files + [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { + tmp_path=$(readlink -f "$tmp_path") + echo "${tmp_path}" + return + } + done +} + +################################################################################ + +# Returns the cdc-wdm name retrieved from sysfs +mm_track_cdcwdm() { + local wwan="$1" + local cdcwdm + + cdcwdm=$(ls "/sys/class/net/${wwan}/device/usbmisc/") + [ -n "${cdcwdm}" ] || return + + # We have to cache it for later, as we won't be able to get the + # associated cdc-wdm device on a remove event + echo "${wwan} ${cdcwdm}" >> "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +# Returns the cdc-wdm name retrieved from the cache +mm_untrack_cdcwdm() { + local wwan="$1" + local cdcwdm + + # Look for the cached associated cdc-wdm device + [ -f "${MODEMMANAGER_CDCWDM_CACHE}" ] || return + + cdcwdm=$(awk -v wwan="${wwan}" '!/^#/ && $0 ~ wwan { print $2 }' "${MODEMMANAGER_CDCWDM_CACHE}") + [ -n "${cdcwdm}" ] || return + + # Remove from cache + sed -i "/${wwan} ${cdcwdm}/d" "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +################################################################################ +# ModemManager needs some time from the ports being added until a modem object +# is exposed in DBus. With the logic here we do an explicit wait of N seconds +# for ModemManager to expose the new modem object, making sure that the wait is +# unique per device (i.e. per physical device sysfs path). + +# Gets the modem wait status as retrieved from the cache +mm_get_modem_wait_status() { + local sysfspath="$1" + + # If no sysfs cache file, we're done + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return + + # Get status of the sysfs path + awk -v sysfspath="${sysfspath}" '!/^#/ && $0 ~ sysfspath { print $2 }' "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Clear the modem wait status from the cache, if any +mm_clear_modem_wait_status() { + local sysfspath="$1" + + local escaped_sysfspath + + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] && { + # escape '/', '\' and '&' for sed... + escaped_sysfspath=$(echo "$sysfspath" | sed -e 's/[\/&]/\\&/g') + sed -i "/${escaped_sysfspath}/d" "${MODEMMANAGER_SYSFS_CACHE}" + } +} + +# Sets the modem wait status in the cache +mm_set_modem_wait_status() { + local sysfspath="$1" + local status="$2" + + # Remove sysfs line before adding the new one with the new state + mm_clear_modem_wait_status "${sysfspath}" + + # Add the new status + echo "${sysfspath} ${status}" >> "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Callback for config_foreach() +mm_get_modem_config_foreach_cb() { + local cfg="$1" + local sysfspath="$2" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + local dev + dev=$(uci_get network "${cfg}" device) + [ "${dev}" = "${sysfspath}" ] || return 0 + + echo "${cfg}" +} + +# Returns the name of the interface configured for this device +mm_get_modem_config() { + local sysfspath="$1" + + # Look for configuration for the given sysfs path + config_load network + config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}" +} + +# Wait for a modem in the specified sysfspath +mm_wait_for_modem() { + local cfg="$1" + local sysfspath="$2" + + # TODO: config max wait + local n=45 + local step=5 + + while [ $n -ge 0 ]; do + [ -d "${sysfspath}" ] || { + mm_log "error: ignoring modem detection request: no device at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 1 + } + + # Check if the modem exists at the given sysfs path + if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 + then + mm_log "error: modem not detected at sysfs path" + else + mm_log "modem exported successfully at ${sysfspath}" + mm_log "setting interface '${cfg}' as available" + proto_set_available "${cfg}" 1 + return 0 + fi + + sleep $step + n=$((n-step)) + done + + mm_log "error: timed out waiting for the modem to get exported at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 2 +} + +mm_report_modem_wait() { + local sysfspath=$1 + + local parent_sysfspath status + + parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") + [ -n "${parent_sysfspath}" ] || { + mm_log "error: parent device sysfspath not found" + return + } + + status=$(mm_get_modem_wait_status "${parent_sysfspath}") + case "${status}" in + "") + local cfg + + cfg=$(mm_get_modem_config "${parent_sysfspath}") + if [ -n "${cfg}" ]; then + mm_log "interface '${cfg}' is set to configure device '${parent_sysfspath}'" + mm_log "now waiting for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "processed" + # Launch subshell for the explicit wait + ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & + else + mm_log "no need to wait for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "ignored" + fi + ;; + "processed") + mm_log "already waiting for modem at sysfs path ${parent_sysfspath}" + ;; + "ignored") + ;; + *) + mm_log "error: unknown status read for device at sysfs path ${parent_sysfspath}" + ;; + esac +} + +################################################################################ +# Cleanup interfaces + +mm_cleanup_interface_cb() { + local cfg="$1" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + proto_set_available "${cfg}" 0 +} + +mm_cleanup_interfaces() { + config_load network + config_foreach mm_cleanup_interface_cb interface +} + +mm_cleanup_interface_by_sysfspath() { + local dev="$1" + + local cfg + cfg=$(mm_get_modem_config "$dev") + [ -n "${cfg}" ] || return + + mm_log "setting interface '$cfg' as unavailable" + proto_set_available "${cfg}" 0 +} + +################################################################################ +# Event reporting + +# Receives as input the action, the device name and the subsystem +mm_report_event() { + local action="$1" + local name="$2" + local subsystem="$3" + local sysfspath="$4" + + # Track/untrack events in cache + case "${action}" in + "add") + # On add events, store event details in cache (if not exists yet) + grep -qs "${name},${subsystem}" "${MODEMMANAGER_EVENTS_CACHE}" || \ + echo "${action},${name},${subsystem},${sysfspath}" >> "${MODEMMANAGER_EVENTS_CACHE}" + ;; + "remove") + # On remove events, remove old events from cache (match by subsystem+name) + sed -i "/${name},${subsystem}/d" "${MODEMMANAGER_EVENTS_CACHE}" + ;; + esac + + # Report the event + mm_log "event reported: action=${action}, name=${name}, subsystem=${subsystem}" + mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 1>/dev/null 2>&1 & + + # Wait for added modem if a sysfspath is given + [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" +} + +mm_report_event_from_cache_line() { + local event_line="$1" + + local action name subsystem sysfspath + action=$(echo "${event_line}" | awk -F ',' '{ print $1 }') + name=$(echo "${event_line}" | awk -F ',' '{ print $2 }') + subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }') + sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }') + + mm_log "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" + mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}" +} + +mm_report_events_from_cache() { + # Remove the sysfs cache + rm -f "${MODEMMANAGER_SYSFS_CACHE}" + + local n=60 + local step=1 + local mmrunning=0 + + # Wait for ModemManager to be available in the bus + while [ $n -ge 0 ]; do + sleep $step + mm_log "checking if ModemManager is available..." + + if ! mmcli -L >/dev/null 2>&1 + then + mm_log "ModemManager not yet available" + else + mmrunning=1 + break + fi + n=$((n-step)) + done + + [ ${mmrunning} -eq 1 ] || { + mm_log "error: couldn't report initial kernel events: ModemManager not running" + return + } + + # Report cached kernel events + while IFS= read -r event_line; do + mm_report_event_from_cache_line "${event_line}" + done < ${MODEMMANAGER_EVENTS_CACHE} +} diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init new file mode 100755 index 000000000..b3f9f9290 --- /dev/null +++ b/modemmanager/files/modemmanager.init @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2016 Aleksander Morgado + +USE_PROCD=1 +START=70 + +stop_service() { + # Load common utils + . /usr/share/ModemManager/modemmanager.common + # Set all configured interfaces as unavailable + mm_cleanup_interfaces +} + +start_service() { + # Setup ModemManager service + # + # We will make sure that the rundir always exists, and we initially cleanup + # all interfaces flagging them as unavailable. + # + # The cached events processing will wait for MM to be available in DBus + # and will make sure all ports are re-notified to ModemManager every time + # it starts. + # + # All these commands need to be executed on every MM start, even after + # procd-triggered respawns, which is why they're all included as instance command + # + procd_open_instance + procd_set_param command sh -c ". /usr/share/ModemManager/modemmanager.common; \ + mkdir -m 0755 -p ${MODEMMANAGER_RUNDIR}; \ + mm_cleanup_interfaces; \ + ( mm_report_events_from_cache ) >/dev/null 2>&1 & \ + /usr/sbin/ModemManager" + procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" + procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" + procd_close_instance +} diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto new file mode 100755 index 000000000..d24910b98 --- /dev/null +++ b/modemmanager/files/modemmanager.proto @@ -0,0 +1,550 @@ +#!/bin/sh +# Copyright (C) 2016-2019 Aleksander Morgado + +[ -x /usr/bin/mmcli ] || exit 0 +[ -x /usr/sbin/pppd ] || exit 0 + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + . ./ppp.sh + init_proto "$@" +} + +cdr2mask () +{ + # Number of args to shift, 255..255, first non-255 byte, zeroes + set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0 + if [ "$1" -gt 1 ] + then + shift "$1" + else + shift + fi + echo "${1-0}"."${2-0}"."${3-0}"."${4-0}" +} + +# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue +# The second argument must be exactly the name of the field to read +# +# Sample output: +# $ mmcli -m 0 -K +# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 +# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 +# modem.generic.manufacturer : Dell Inc. +# modem.generic.model : DW5821e Snapdragon X20 LTE +# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 +# modem.generic.carrier-configuration : GCF +# modem.generic.carrier-configuration-revision : 08E00009 +# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE +# .... +modemmanager_get_field() { + local list=$1 + local field=$2 + local value="" + + [ -z "${list}" ] || [ -z "${field}" ] && return + + # there is always at least a whitespace after each key, and we use that as part of the + # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result + # when grepping for 'modem.generic.state'. + line=$(echo "${list}" | grep "${field} ") + value=$(echo ${line#*:}) + + # not found? + [ -n "${value}" ] || return 2 + + # only print value if set + [ "${value}" != "--" ] && echo "${value}" + return 0 +} + +# build a comma-separated list of values from the list +modemmanager_get_multivalue_field() { + local list=$1 + local field=$2 + local value="" + local length idx item + + [ -z "${list}" ] || [ -z "${field}" ] && return + + length=$(modemmanager_get_field "${list}" "${field}.length") + [ -n "${length}" ] || return 0 + [ "$length" -ge 1 ] || return 0 + + idx=1 + while [ $idx -le "$length" ]; do + item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") + [ -n "${item}" ] && [ "${item}" != "--" ] && { + [ -n "${value}" ] && value="${value}, " + value="${value}${item}" + } + idx=$((idx + 1)) + done + + # nothing built? + [ -n "${value}" ] || return 2 + + # only print value if set + echo "${value}" + return 0 +} + +modemmanager_cleanup_connection() { + local modemstatus="$1" + + local bearercount idx bearerpath + + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + + # do nothing if no bearers reported + [ -n "${bearercount}" ] && [ "$bearercount" -ge 1 ] && { + # explicitly disconnect just in case + mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1 + # and remove all bearer objects, if any found + idx=1 + while [ $idx -le "$bearercount" ]; do + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[$idx\]") + mmcli --modem "${device}" --delete-bearer="${bearerpath}" >/dev/null 2>&1 + idx=$((idx + 1)) + done + } +} + +modemmanager_connected_method_ppp_ipv4() { + local interface="$1" + local ttyname="$2" + local username="$3" + local password="$4" + local allowedauth="$5" + + # all auth types are allowed unless a user given list is given + local authopts + local pap=1 + local chap=1 + local mschap=1 + local mschapv2=1 + local eap=1 + + [ -n "$allowedauth" ] && { + pap=0 chap=0 mschap=0 mschapv2=0 eap=0 + for auth in $allowedauth; do + case $auth in + "pap") pap=1 ;; + "chap") chap=1 ;; + "mschap") mschap=1 ;; + "mschapv2") mschapv2=1 ;; + "eap") eap=1 ;; + *) ;; + esac + done + } + + [ $pap -eq 1 ] || append authopts "refuse-pap" + [ $chap -eq 1 ] || append authopts "refuse-chap" + [ $mschap -eq 1 ] || append authopts "refuse-mschap" + [ $mschapv2 -eq 1 ] || append authopts "refuse-mschap-v2" + [ $eap -eq 1 ] || append authopts "refuse-eap" + + proto_run_command "${interface}" /usr/sbin/pppd \ + "${ttyname}" \ + 115200 \ + nodetach \ + noaccomp \ + nobsdcomp \ + nopcomp \ + novj \ + noauth \ + $authopts \ + ${username:+ user $username} \ + ${password:+ password $password} \ + lcp-echo-failure 5 \ + lcp-echo-interval 15 \ + lock \ + crtscts \ + nodefaultroute \ + usepeerdns \ + ipparam "${interface}" \ + ip-up-script /lib/netifd/ppp-up \ + ip-down-script /lib/netifd/ppp-down +} + +modemmanager_disconnected_method_ppp_ipv4() { + local interface="$1" + + echo "running disconnection (ppp method)" + + [ -n "${ERROR}" ] && { + local errorstring + errorstring=$(ppp_exitcode_tostring "${ERROR}") + case "$ERROR" in + 0) + ;; + 2) + proto_notify_error "$interface" "$errorstring" + proto_block_restart "$interface" + ;; + *) + proto_notify_error "$interface" "$errorstring" + ;; + esac + } || echo "pppd result code not given" + + proto_kill_command "$interface" +} + +modemmanager_connected_method_dhcp_ipv4() { + local interface="$1" + local wwan="$2" + local metric="$3" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@${interface}" + json_add_string proto "dhcp" + proto_add_dynamic_defaults + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv4() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + + local mask="" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + mask=$(cdr2mask "${prefix}") + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv4 address ${address}, netmask ${mask}" + proto_add_ipv4_address "${address}" "${mask}" + [ -n "${gateway}" ] && { + echo "adding default IPv4 route via ${gateway}" + proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_connected_method_dhcp_ipv6() { + local interface="$1" + local wwan="$2" + local metric="$3" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@${interface}" + json_add_string proto "dhcpv6" + proto_add_dynamic_defaults + json_add_string extendprefix 1 # RFC 7278: Extend an IPv6 /64 Prefix to LAN + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv6() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv6 address ${address}, prefix ${prefix}" + proto_add_ipv6_address "${address}" "128" + proto_add_ipv6_prefix "${address}/${prefix}" + [ -n "${gateway}" ] && { + echo "adding default IPv6 route via ${gateway}" + proto_add_ipv6_route "${gateway}" "128" + proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_disconnected_method_common() { + local interface="$1" + + echo "running disconnection (common)" + proto_notify_error "${interface}" MM_DISCONNECT_IN_PROGRESS + + proto_init_update "*" 0 + proto_send_update "${interface}" +} + +proto_modemmanager_init_config() { + available=1 + no_device=1 + proto_config_add_string device + proto_config_add_string apn + proto_config_add_string 'allowedauth:list(string)' + proto_config_add_string username + proto_config_add_string password + proto_config_add_string pincode + proto_config_add_string iptype + proto_config_add_int signalrate + proto_config_add_boolean lowpower + proto_config_add_defaults +} + +proto_modemmanager_setup() { + local interface="$1" + + local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface + local bearermethod_ipv4 bearermethod_ipv6 auth cliauth + local operatorname operatorid registration accesstech signalquality + + local device apn allowedauth username password pincode iptype metric signalrate + + local address prefix gateway mtu dns1 dns2 + + json_get_vars device apn allowedauth username password pincode iptype metric signalrate + + # validate sysfs path given in config + [ -n "${device}" ] || { + echo "No device specified" + proto_notify_error "${interface}" NO_DEVICE + proto_set_available "${interface}" 0 + return 1 + } + [ -e "${device}" ] || { + echo "Device not found in sysfs" + proto_set_available "${interface}" 0 + return 1 + } + + # validate that ModemManager is handling the modem at the sysfs path + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + modempath=$(modemmanager_get_field "${modemstatus}" "modem.dbus-path") + [ -n "${modempath}" ] || { + echo "Device not managed by ModemManager" + proto_notify_error "${interface}" DEVICE_NOT_MANAGED + proto_set_available "${interface}" 0 + return 1 + } + echo "modem available at ${modempath}" + + # always cleanup before attempting a new connection, just in case + modemmanager_cleanup_connection "${modemstatus}" + + # if allowedauth list given, build option string + for auth in $allowedauth; do + cliauth="${cliauth}${cliauth:+|}$auth" + done + + # setup connect args; APN mandatory (even if it may be empty) + echo "starting connection with apn '${apn}'..." + proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS + + connectargs="apn=${apn}${iptype:+,ip-type=${iptype}}${cliauth:+,allowed-auth=${cliauth}}${username:+,user=${username}}${password:+,password=${password}}${pincode:+,pin=${pincode}}" + mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { + proto_notify_error "${interface}" MM_CONNECT_FAILED + proto_block_restart "${interface}" + return 1 + } + + # check if Signal refresh rate is set + if [ -n "${signalrate}" ] && [ "${signalrate}" -eq "${signalrate}" ] 2>/dev/null; then + echo "setting signal refresh rate to ${signalrate} seconds" + mmcli --modem="${device}" --signal-setup="${signalrate}" + else + echo "signal refresh rate is not set" + fi + + # log additional useful information + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + operatorname=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-name") + [ -n "${operatorname}" ] && echo "network operator name: ${operatorname}" + operatorid=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-code") + [ -n "${operatorid}" ] && echo "network operator MCCMNC: ${operatorid}" + registration=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.registration-state") + [ -n "${registration}" ] && echo "registration type: ${registration}" + accesstech=$(modemmanager_get_multivalue_field "${modemstatus}" "modem.generic.access-technologies") + [ -n "${accesstech}" ] && echo "access technology: ${accesstech}" + signalquality=$(modemmanager_get_field "${modemstatus}" "modem.generic.signal-quality.value") + [ -n "${signalquality}" ] && echo "signal quality: ${signalquality}%" + + # we won't like it if there are more than one bearers, as that would mean the + # user manually created them, and that's unsupported by this proto + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + [ -n "${bearercount}" ] && [ "$bearercount" -eq 1 ] || { + proto_notify_error "${interface}" INVALID_BEARER_LIST + return 1 + } + + # load connected bearer information + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + + # load network interface and method information + beareriface=$(modemmanager_get_field "${bearerstatus}" "bearer.status.interface") + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + + # setup IPv4 + [ -n "${bearermethod_ipv4}" ] && { + echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}" + case "${bearermethod_ipv4}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" + ;; + "ppp") + modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}" + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + # setup IPv6 + # note: if using ipv4v6, both IPv4 and IPv6 settings will have the same MTU and metric values reported + [ -n "${bearermethod_ipv6}" ] && { + echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}" + case "${bearermethod_ipv6}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" + ;; + "ppp") + proto_notify_error "${interface}" "unsupported method" + return 1 + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + return 0 +} + +proto_modemmanager_teardown() { + local interface="$1" + + local modemstatus bearerpath errorstring + local bearermethod_ipv4 bearermethod_ipv6 + + local device lowpower iptype + json_get_vars device lowpower iptype + + echo "stopping network" + proto_notify_error "${interface}" MM_TEARDOWN_IN_PROGRESS + + # load connected bearer information, just the first one should be ok + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + [ -n "${bearerpath}" ] || { + echo "couldn't load bearer path" + return + } + + # load bearer connection methods + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + [ -n "${bearermethod_ipv4}" ] && + echo "IPv4 connection teardown required in interface ${interface}: ${bearermethod_ipv4}" + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + [ -n "${bearermethod_ipv6}" ] && + echo "IPv6 connection teardown required in interface ${interface}: ${bearermethod_ipv6}" + + # disconnection handling only requires special treatment in IPv4/PPP + [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}" + modemmanager_disconnected_method_common "${interface}" + + # disconnect + mmcli --modem="${device}" --simple-disconnect || + proto_notify_error "${interface}" DISCONNECT_FAILED + + # disable + mmcli --modem="${device}" --disable + proto_notify_error "${interface}" MM_MODEM_DISABLED + + # low power, only if requested + [ "${lowpower:-0}" -lt 1 ] || + mmcli --modem="${device}" --set-power-state-low +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol modemmanager +} From 49f0589209b04c912fd708e2f04586cd5d4154a9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Sep 2021 08:11:59 +0200 Subject: [PATCH 0603/2059] Use Modemmanager 1.18.0 --- modemmanager/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index f0f53bfd2..b99ce7737 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -10,9 +10,9 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_SOURCE_VERSION:=8755e85d13b1170882cd5108cf20a63d94573155 +PKG_SOURCE_VERSION:=4ccbfcd0167b5e6134eba5da34c33b8b0b5b1619 PKG_NAME:=modemmanager -PKG_VERSION:=1.18.2-$(PKG_SOURCE_VERSION) +PKG_VERSION:=1.18.0-$(PKG_SOURCE_VERSION) PKG_RELEASE:=10 #PKG_BUILD_DIR:=$(BUILD_DIR)/modemamanager-$ From c05b31e993ada627cfb28d0d8217670cb12a17d5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Sep 2021 08:14:15 +0200 Subject: [PATCH 0604/2059] Update libmbim --- libmbim/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index b3d2f3f66..871c1bcc8 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -PKG_SOURCE_VERSION:=af15f1cd3c1e586a35c3ff439312b2ae8edbf35e +PKG_SOURCE_VERSION:=cd7108e46148869c50ea63e800d63bd85f7202fa PKG_NAME:=libmbim PKG_VERSION:=1.26.0-$(PKG_SOURCE_VERSION) From e57423f46db611d303a80550ae034b0d6e225ef6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Sep 2021 08:14:37 +0200 Subject: [PATCH 0605/2059] Update libqmi --- libqmi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libqmi/Makefile b/libqmi/Makefile index f82556c6e..19119348d 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_SOURCE_VERSION:=45894158da3c55988cef62c5d1afc50f5ef4349a +PKG_SOURCE_VERSION:=1ce9772e7a6f4f94e0ac04c0aee20cef8c8456ff PKG_NAME:=libqmi PKG_VERSION:=1.30.0-$(PKG_SOURCE_VERSION) PKG_RELEASE:=11 From d5cac96482653e163b66f85b272238ebc6e76886 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Sep 2021 13:03:55 +0200 Subject: [PATCH 0606/2059] Remove again modemmanager and libqmi/libmbim --- libmbim/Makefile | 99 ----- libqmi/Config.in | 16 - libqmi/Makefile | 110 ----- modemmanager/Config.in | 21 - modemmanager/Makefile | 141 ------- modemmanager/README.md | 40 -- modemmanager/files/25-modemmanager-net | 35 -- modemmanager/files/25-modemmanager-tty | 18 - modemmanager/files/25-modemmanager-usb | 15 - modemmanager/files/modemmanager.common | 336 --------------- modemmanager/files/modemmanager.init | 36 -- modemmanager/files/modemmanager.proto | 550 ------------------------- 12 files changed, 1417 deletions(-) delete mode 100644 libmbim/Makefile delete mode 100644 libqmi/Config.in delete mode 100644 libqmi/Makefile delete mode 100644 modemmanager/Config.in delete mode 100644 modemmanager/Makefile delete mode 100644 modemmanager/README.md delete mode 100644 modemmanager/files/25-modemmanager-net delete mode 100644 modemmanager/files/25-modemmanager-tty delete mode 100644 modemmanager/files/25-modemmanager-usb delete mode 100644 modemmanager/files/modemmanager.common delete mode 100755 modemmanager/files/modemmanager.init delete mode 100755 modemmanager/files/modemmanager.proto diff --git a/libmbim/Makefile b/libmbim/Makefile deleted file mode 100644 index 871c1bcc8..000000000 --- a/libmbim/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -# -# Copyright (C) 2016 Velocloud Inc. -# Copyright (C) 2016 Aleksander Morgado -# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter -# -# This is free software, licensed under the GNU General Public License v2. -# - -include $(TOPDIR)/rules.mk - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -PKG_SOURCE_VERSION:=cd7108e46148869c50ea63e800d63bd85f7202fa - -PKG_NAME:=libmbim -PKG_VERSION:=1.26.0-$(PKG_SOURCE_VERSION) -PKG_RELEASE:=10 - -PKG_MAINTAINER:=Nicholas Smith - -PKG_FIXUP:=autoreconf -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk - -MESON_BUILD_DIR:=$(PKG_BUILD_DIR)/contrib/meson/openwrt-build - -CONFIGURE_ARGS += \ - --disable-static \ - --disable-gtk-doc \ - --disable-gtk-doc-html \ - --disable-gtk-doc-pdf \ - --disable-silent-rules \ - --enable-more-warnings=yes - -define Package/libmbim - SECTION:=libs - CATEGORY:=Libraries - DEPENDS:=+glib2 - TITLE:=Helper library and utils to talk to MBIM enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libmbim - LICENSE:=LGPL-2.0-or-later - LICENSE_FILES:=COPYING.LIB -endef - -define Package/libmbim/description - Helper library to talk to MBIM enabled modems. - Add mbim-utils for extra utilities. -endef - -define Package/mbim-utils - SECTION:=utils - CATEGORY:=Utilities - DEPENDS:=+libmbim - TITLE:=Utilities to talk to MBIM enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libmbim - LICENSE:=GPL-2.0-or-later - LICENSE_FILES:=COPYING -endef - -CONFIGURE_ARGS += \ - --without-udev \ - --without-udev-base-dir - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include - $(CP) \ - $(PKG_INSTALL_DIR)/usr/include/libmbim-glib \ - $(1)/usr/include/ - - $(INSTALL_DIR) $(1)/usr/lib - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so* \ - $(1)/usr/lib/ - - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mbim-glib.pc \ - $(1)/usr/lib/pkgconfig -endef - -define Package/libmbim/install - $(INSTALL_DIR) $(1)/usr/lib - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so.* \ - $(1)/usr/lib/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/mbim-proxy $(1)/usr/lib/ -endef - -define Package/mbim-utils/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbimcli $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbim-network $(1)/usr/bin/ -endef - -$(eval $(call BuildPackage,libmbim)) -$(eval $(call BuildPackage,mbim-utils)) diff --git a/libqmi/Config.in b/libqmi/Config.in deleted file mode 100644 index 6f35b7453..000000000 --- a/libqmi/Config.in +++ /dev/null @@ -1,16 +0,0 @@ -menu "Configuration" - depends on PACKAGE_libqmi - -config LIBQMI_WITH_MBIM_QMUX - bool "Include MBIM QMUX service support" - default y - help - Compile libqmi with QMI-over-MBIM support - -config LIBQMI_WITH_QRTR_GLIB - bool "Include QRTR support" - default y - help - Compile libqmi with QRTR support - -endmenu diff --git a/libqmi/Makefile b/libqmi/Makefile deleted file mode 100644 index 19119348d..000000000 --- a/libqmi/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -# -# Copyright (C) 2016 Velocloud Inc. -# Copyright (C) 2016 Aleksander Morgado -# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter -# -# This is free software, licensed under the GNU General Public License v2. -# - -include $(TOPDIR)/rules.mk - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_SOURCE_VERSION:=1ce9772e7a6f4f94e0ac04c0aee20cef8c8456ff -PKG_NAME:=libqmi -PKG_VERSION:=1.30.0-$(PKG_SOURCE_VERSION) -PKG_RELEASE:=11 - -PKG_FIXUP:=autoreconf -PKG_MAINTAINER:=Nicholas Smith - -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk - -define Package/libqmi/config - source "$(SOURCE)/Config.in" -endef - -define Package/libqmi - SECTION:=libs - CATEGORY:=Libraries - DEPENDS:= \ - +glib2 \ - +LIBQMI_WITH_MBIM_QMUX:libmbim \ - +LIBQMI_WITH_QRTR_GLIB:libqrtr-glib - TITLE:=Helper library to talk to QMI enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libqmi - LICENSE:=LGPL-2.0-or-later - LICENSE_FILES:=COPYING.LIB -endef - -define Package/libqmi/description - Helper library talk to QMI enabled modems. - Add qmi-utils for extra utilities. -endef - -define Package/qmi-utils - SECTION:=utils - CATEGORY:=Utilities - DEPENDS:=+libqmi - TITLE:=Utilities to talk to QMI enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libqmi - LICENSE:=GPL-2.0-or-later - LICENSE_FILES:=COPYING -endef - -define Package/libqmi-utils/description - Utils to talk to QMI enabled modems -endef - -CONFIGURE_ARGS += \ - --disable-static \ - --disable-gtk-doc \ - --disable-gtk-doc-html \ - --disable-gtk-doc-pdf \ - --disable-silent-rules \ - --enable-firmware-update \ - --$(if $(LIBQMI_WITH_MBIM_QMUX),en,dis)able-mbim-qmux \ - --$(if $(LIBQMI_WITH_QRTR_GLIB),en,dis)able-qrtr \ - --enable-more-warnings=yes \ - --without-udev \ - --without-udev-base-dir - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include - $(CP) \ - $(PKG_INSTALL_DIR)/usr/include/libqmi-glib \ - $(1)/usr/include/ - - $(INSTALL_DIR) $(1)/usr/lib - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so* \ - $(1)/usr/lib/ - - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/qmi-glib.pc \ - $(1)/usr/lib/pkgconfig -endef - -define Package/libqmi/install - $(INSTALL_DIR) $(1)/usr/lib - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so.* \ - $(1)/usr/lib/ - - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/qmi-proxy $(1)/usr/lib/ -endef - -define Package/qmi-utils/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmicli $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-network $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-firmware-update $(1)/usr/bin/ -endef - -$(eval $(call BuildPackage,libqmi)) -$(eval $(call BuildPackage,qmi-utils)) diff --git a/modemmanager/Config.in b/modemmanager/Config.in deleted file mode 100644 index 283a9e10a..000000000 --- a/modemmanager/Config.in +++ /dev/null @@ -1,21 +0,0 @@ -menu "Configuration" -depends on PACKAGE_modemmanager - - config MODEMMANAGER_WITH_MBIM - bool "Include MBIM support" - default y - help - Compile ModemManager with MBIM support - - config MODEMMANAGER_WITH_QMI - bool "Include QMI support" - default y - help - Compile ModemManager with QMI support - - config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS - bool "Allow AT commands via DBus" - default n - help - Compile ModemManager allowing AT commands without debug flag -endmenu diff --git a/modemmanager/Makefile b/modemmanager/Makefile deleted file mode 100644 index b99ce7737..000000000 --- a/modemmanager/Makefile +++ /dev/null @@ -1,141 +0,0 @@ -# -# Copyright (C) 2016 Velocloud Inc. -# Copyright (C) 2016 Aleksander Morgado -# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter -# -# This is free software, licensed under the GNU General Public License v2. -# - -include $(TOPDIR)/rules.mk - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_SOURCE_VERSION:=4ccbfcd0167b5e6134eba5da34c33b8b0b5b1619 -PKG_NAME:=modemmanager -PKG_VERSION:=1.18.0-$(PKG_SOURCE_VERSION) -PKG_RELEASE:=10 - -#PKG_BUILD_DIR:=$(BUILD_DIR)/modemamanager-$ - -PKG_MAINTAINER:=Nicholas Smith -PKG_LICENSE:=GPL-2.0-or-later -PKG_LICENSE_FILES:=COPYING - -PKG_FIXUP:=autoreconf - -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk - -define Package/modemmanager/config - source "$(SOURCE)/Config.in" -endef - -define Package/modemmanager - SECTION:=net - CATEGORY:=Network - TITLE:=Control utility for any kind of mobile broadband modem - URL:=https://www.freedesktop.org/wiki/Software/ModemManager - DEPENDS:= \ - $(INTL_DEPENDS) \ - +glib2 \ - +dbus \ - +ppp \ - +MODEMMANAGER_WITH_MBIM:libmbim \ - +MODEMMANAGER_WITH_QMI:libqmi -endef - -define Package/modemmanager/description - ModemManager is a D-Bus-activated service which allows controlling mobile - broadband modems. Add kernel modules for your modems as needed. - Select Utilities/usb-modeswitch if needed. -endef - -CONFIGURE_ARGS += \ - --without-polkit \ - --without-udev \ - --without-systemdsystemunitdir \ - --disable-rpath \ - --disable-gtk-doc - -ifeq ($(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),y) - CONFIGURE_ARGS += --with-at-command-via-dbus -endif - -ifdef CONFIG_MODEMMANAGER_WITH_MBIM - CONFIGURE_ARGS += --with-mbim -else - CONFIGURE_ARGS += --without-mbim -endif - -ifdef CONFIG_MODEMMANAGER_WITH_QMI - CONFIGURE_ARGS += --with-qmi -else - CONFIGURE_ARGS += --without-qmi -endif - -define Build/Prepare - $(call Build/Prepare/Default) - ( cd "$(PKG_BUILD_DIR)"; \ - printf "all:\ninstall:\n" >po/Makefile.in.in; \ - ) -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/include/ModemManager/*.h $(1)/usr/include/ModemManager - $(INSTALL_DIR) $(1)/usr/include/libmm-glib - $(CP) $(PKG_INSTALL_DIR)/usr/include/libmm-glib/*.h $(1)/usr/include/libmm-glib - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so* $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ModemManager.pc $(1)/usr/lib/pkgconfig - $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mm-glib.pc $(1)/usr/lib/pkgconfig -endef - -define Package/modemmanager/install - $(INSTALL_DIR) $(1)/lib/udev/rules.d - $(INSTALL_DATA) $(PKG_INSTALL_DIR)/lib/udev/rules.d/*.rules $(1)/lib/udev/rules.d - - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin - - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin - - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so.* $(1)/usr/lib - - $(INSTALL_DIR) $(1)/usr/lib/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager - - $(INSTALL_DIR) $(1)/etc/dbus-1/system.d - $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d - - $(INSTALL_DIR) $(1)/usr/share/dbus-1/system-services - $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service $(1)/usr/share/dbus-1/system-services - - $(INSTALL_DIR) $(1)/usr/share/ModemManager - $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager - $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager - - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager - - $(INSTALL_DIR) $(1)/etc/hotplug.d/usb - $(INSTALL_DATA) ./files/25-modemmanager-usb $(1)/etc/hotplug.d/usb - - $(INSTALL_DIR) $(1)/etc/hotplug.d/net - $(INSTALL_DATA) ./files/25-modemmanager-net $(1)/etc/hotplug.d/net - - $(INSTALL_DIR) $(1)/etc/hotplug.d/tty - $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty - - $(INSTALL_DIR) $(1)/lib/netifd/proto - $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh -endef - -$(eval $(call BuildPackage,modemmanager)) diff --git a/modemmanager/README.md b/modemmanager/README.md deleted file mode 100644 index c9d880ea4..000000000 --- a/modemmanager/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# OpenWrt ModemManager - -## Description - -Cellular modem control and connectivity - -Optional libraries libmbim and libqmi are available. -Your modem may require additional kernel modules and/or the usb-modeswitch -package. - -## Usage - -Once installed, you can configure the 2G/3G/4G modem connections directly in -/etc/config/network as in the following example: - - config interface 'broadband' - option device '/sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2.1' - option proto 'modemmanager' - option apn 'ac.vodafone.es' - option allowedauth 'pap chap' - option username 'vodafone' - option password 'vodafone' - option pincode '7423' - option iptype 'ipv4' - option lowpower '1' - option signalrate '30' - -Only 'device' and 'proto' are mandatory options, the remaining ones are all -optional. - -The 'allowedauth' option allows limiting the list of authentication protocols. -It is given as a space-separated list of values, including any of the -following: 'pap', 'chap', 'mschap', 'mschapv2' or 'eap'. It will default to -allowing all protocols. - -The 'iptype' option supports any of these values: 'ipv4', 'ipv6' or 'ipv4v6'. -It will default to 'ipv4' if not given. - -The 'signalrate' option set's the signal refresh rate (in seconds) for the device. -You can call signal info with command: mmcli -m 0 --signal-get diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/25-modemmanager-net deleted file mode 100644 index 504c3d6b6..000000000 --- a/modemmanager/files/25-modemmanager-net +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016 Velocloud Inc -# Copyright (C) 2016 Aleksander Morgado - -# Load common utilities -. /usr/share/ModemManager/modemmanager.common - -# We require a interface name -[ -n "${INTERFACE}" ] || exit - -[ -n "$(echo ${INTERFACE} | grep -i sqm)" ] && exit -[ -d /sys${DEVPATH} ] || exit -[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit - -# Always make sure the rundir exists -mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" - -# Report network interface -mm_log "${ACTION} network interface ${INTERFACE}: event processed" -mm_report_event "${ACTION}" "${INTERFACE}" "net" "/sys${DEVPATH}" - -# Look for an associated cdc-wdm interface - -cdcwdm="" - -case "${ACTION}" in - "add") cdcwdm=$(mm_track_cdcwdm "${INTERFACE}") ;; - "remove") cdcwdm=$(mm_untrack_cdcwdm "${INTERFACE}") ;; -esac - -# Report cdc-wdm device, if any -[ -n "${cdcwdm}" ] && { - mm_log "${ACTION} cdc interface ${cdcwdm}: custom event processed" - mm_report_event "${ACTION}" "${cdcwdm}" "usbmisc" "/sys${DEVPATH}" -} diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/25-modemmanager-tty deleted file mode 100644 index 1d3fb9a35..000000000 --- a/modemmanager/files/25-modemmanager-tty +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016 Velocloud Inc -# Copyright (C) 2016 Aleksander Morgado - -# Load hotplug common utilities -. /usr/share/ModemManager/modemmanager.common - -# We require a device name -[ -n "$DEVNAME" ] || exit -[ -d /sys${DEVPATH} ] || exit -[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit - -# Always make sure the rundir exists -mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" - -# Report TTY -mm_log "${ACTION} serial interface ${DEVNAME}: event processed" -mm_report_event "${ACTION}" "${DEVNAME}" "tty" "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-usb b/modemmanager/files/25-modemmanager-usb deleted file mode 100644 index 565b7b9c9..000000000 --- a/modemmanager/files/25-modemmanager-usb +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# Copyright (C) 2019 Aleksander Morgado - -# We need to process only full USB device removal events, we don't -# want to process specific interface removal events. -[ "$ACTION" = remove ] || exit -[ -z "${INTERFACE}" ] || exit -[ -d /sys${DEVPATH} ] || exit -[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit - -# Load common utilities -. /usr/share/ModemManager/modemmanager.common - -mm_clear_modem_wait_status "/sys${DEVPATH}" -mm_cleanup_interface_by_sysfspath "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common deleted file mode 100644 index 8de8f2946..000000000 --- a/modemmanager/files/modemmanager.common +++ /dev/null @@ -1,336 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016 Velocloud Inc -# Copyright (C) 2016 Aleksander Morgado - -################################################################################ - -# If there is no interface that use modemmanager, exit -#[ -z "$(uci -q show network | grep modemmanager)" ] && exit -[ "$(uci -q get openmptcprouter.settings.modemmanager)" = "0" ] && exit - -. /lib/functions.sh -. /lib/netifd/netifd-proto.sh - -################################################################################ -# Runtime state - -MODEMMANAGER_RUNDIR="/var/run/modemmanager" -MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid" -MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache" -MODEMMANAGER_SYSFS_CACHE="${MODEMMANAGER_RUNDIR}/sysfs.cache" -MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" - -################################################################################ -# Common logging - -mm_log() { - logger -t "ModemManager" "hotplug: $*" -} - -################################################################################ -# Receives as input argument the full sysfs path of the device -# Returns the physical device sysfs path -# -# NOTE: this method only works when the device exists, i.e. it cannot be used -# on removal hotplug events - -mm_find_physdev_sysfs_path() { - local tmp_path="$1" - - while true; do - tmp_path=$(dirname "${tmp_path}") - - # avoid infinite loops iterating - [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return - - # the physical device will be that with a idVendor and idProduct pair of files - [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { - tmp_path=$(readlink -f "$tmp_path") - echo "${tmp_path}" - return - } - done -} - -################################################################################ - -# Returns the cdc-wdm name retrieved from sysfs -mm_track_cdcwdm() { - local wwan="$1" - local cdcwdm - - cdcwdm=$(ls "/sys/class/net/${wwan}/device/usbmisc/") - [ -n "${cdcwdm}" ] || return - - # We have to cache it for later, as we won't be able to get the - # associated cdc-wdm device on a remove event - echo "${wwan} ${cdcwdm}" >> "${MODEMMANAGER_CDCWDM_CACHE}" - - echo "${cdcwdm}" -} - -# Returns the cdc-wdm name retrieved from the cache -mm_untrack_cdcwdm() { - local wwan="$1" - local cdcwdm - - # Look for the cached associated cdc-wdm device - [ -f "${MODEMMANAGER_CDCWDM_CACHE}" ] || return - - cdcwdm=$(awk -v wwan="${wwan}" '!/^#/ && $0 ~ wwan { print $2 }' "${MODEMMANAGER_CDCWDM_CACHE}") - [ -n "${cdcwdm}" ] || return - - # Remove from cache - sed -i "/${wwan} ${cdcwdm}/d" "${MODEMMANAGER_CDCWDM_CACHE}" - - echo "${cdcwdm}" -} - -################################################################################ -# ModemManager needs some time from the ports being added until a modem object -# is exposed in DBus. With the logic here we do an explicit wait of N seconds -# for ModemManager to expose the new modem object, making sure that the wait is -# unique per device (i.e. per physical device sysfs path). - -# Gets the modem wait status as retrieved from the cache -mm_get_modem_wait_status() { - local sysfspath="$1" - - # If no sysfs cache file, we're done - [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return - - # Get status of the sysfs path - awk -v sysfspath="${sysfspath}" '!/^#/ && $0 ~ sysfspath { print $2 }' "${MODEMMANAGER_SYSFS_CACHE}" -} - -# Clear the modem wait status from the cache, if any -mm_clear_modem_wait_status() { - local sysfspath="$1" - - local escaped_sysfspath - - [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] && { - # escape '/', '\' and '&' for sed... - escaped_sysfspath=$(echo "$sysfspath" | sed -e 's/[\/&]/\\&/g') - sed -i "/${escaped_sysfspath}/d" "${MODEMMANAGER_SYSFS_CACHE}" - } -} - -# Sets the modem wait status in the cache -mm_set_modem_wait_status() { - local sysfspath="$1" - local status="$2" - - # Remove sysfs line before adding the new one with the new state - mm_clear_modem_wait_status "${sysfspath}" - - # Add the new status - echo "${sysfspath} ${status}" >> "${MODEMMANAGER_SYSFS_CACHE}" -} - -# Callback for config_foreach() -mm_get_modem_config_foreach_cb() { - local cfg="$1" - local sysfspath="$2" - - local proto - config_get proto "${cfg}" proto - [ "${proto}" = modemmanager ] || return 0 - - local dev - dev=$(uci_get network "${cfg}" device) - [ "${dev}" = "${sysfspath}" ] || return 0 - - echo "${cfg}" -} - -# Returns the name of the interface configured for this device -mm_get_modem_config() { - local sysfspath="$1" - - # Look for configuration for the given sysfs path - config_load network - config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}" -} - -# Wait for a modem in the specified sysfspath -mm_wait_for_modem() { - local cfg="$1" - local sysfspath="$2" - - # TODO: config max wait - local n=45 - local step=5 - - while [ $n -ge 0 ]; do - [ -d "${sysfspath}" ] || { - mm_log "error: ignoring modem detection request: no device at ${sysfspath}" - proto_set_available "${cfg}" 0 - return 1 - } - - # Check if the modem exists at the given sysfs path - if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 - then - mm_log "error: modem not detected at sysfs path" - else - mm_log "modem exported successfully at ${sysfspath}" - mm_log "setting interface '${cfg}' as available" - proto_set_available "${cfg}" 1 - return 0 - fi - - sleep $step - n=$((n-step)) - done - - mm_log "error: timed out waiting for the modem to get exported at ${sysfspath}" - proto_set_available "${cfg}" 0 - return 2 -} - -mm_report_modem_wait() { - local sysfspath=$1 - - local parent_sysfspath status - - parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") - [ -n "${parent_sysfspath}" ] || { - mm_log "error: parent device sysfspath not found" - return - } - - status=$(mm_get_modem_wait_status "${parent_sysfspath}") - case "${status}" in - "") - local cfg - - cfg=$(mm_get_modem_config "${parent_sysfspath}") - if [ -n "${cfg}" ]; then - mm_log "interface '${cfg}' is set to configure device '${parent_sysfspath}'" - mm_log "now waiting for modem at sysfs path ${parent_sysfspath}" - mm_set_modem_wait_status "${parent_sysfspath}" "processed" - # Launch subshell for the explicit wait - ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & - else - mm_log "no need to wait for modem at sysfs path ${parent_sysfspath}" - mm_set_modem_wait_status "${parent_sysfspath}" "ignored" - fi - ;; - "processed") - mm_log "already waiting for modem at sysfs path ${parent_sysfspath}" - ;; - "ignored") - ;; - *) - mm_log "error: unknown status read for device at sysfs path ${parent_sysfspath}" - ;; - esac -} - -################################################################################ -# Cleanup interfaces - -mm_cleanup_interface_cb() { - local cfg="$1" - - local proto - config_get proto "${cfg}" proto - [ "${proto}" = modemmanager ] || return 0 - - proto_set_available "${cfg}" 0 -} - -mm_cleanup_interfaces() { - config_load network - config_foreach mm_cleanup_interface_cb interface -} - -mm_cleanup_interface_by_sysfspath() { - local dev="$1" - - local cfg - cfg=$(mm_get_modem_config "$dev") - [ -n "${cfg}" ] || return - - mm_log "setting interface '$cfg' as unavailable" - proto_set_available "${cfg}" 0 -} - -################################################################################ -# Event reporting - -# Receives as input the action, the device name and the subsystem -mm_report_event() { - local action="$1" - local name="$2" - local subsystem="$3" - local sysfspath="$4" - - # Track/untrack events in cache - case "${action}" in - "add") - # On add events, store event details in cache (if not exists yet) - grep -qs "${name},${subsystem}" "${MODEMMANAGER_EVENTS_CACHE}" || \ - echo "${action},${name},${subsystem},${sysfspath}" >> "${MODEMMANAGER_EVENTS_CACHE}" - ;; - "remove") - # On remove events, remove old events from cache (match by subsystem+name) - sed -i "/${name},${subsystem}/d" "${MODEMMANAGER_EVENTS_CACHE}" - ;; - esac - - # Report the event - mm_log "event reported: action=${action}, name=${name}, subsystem=${subsystem}" - mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 1>/dev/null 2>&1 & - - # Wait for added modem if a sysfspath is given - [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" -} - -mm_report_event_from_cache_line() { - local event_line="$1" - - local action name subsystem sysfspath - action=$(echo "${event_line}" | awk -F ',' '{ print $1 }') - name=$(echo "${event_line}" | awk -F ',' '{ print $2 }') - subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }') - sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }') - - mm_log "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" - mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}" -} - -mm_report_events_from_cache() { - # Remove the sysfs cache - rm -f "${MODEMMANAGER_SYSFS_CACHE}" - - local n=60 - local step=1 - local mmrunning=0 - - # Wait for ModemManager to be available in the bus - while [ $n -ge 0 ]; do - sleep $step - mm_log "checking if ModemManager is available..." - - if ! mmcli -L >/dev/null 2>&1 - then - mm_log "ModemManager not yet available" - else - mmrunning=1 - break - fi - n=$((n-step)) - done - - [ ${mmrunning} -eq 1 ] || { - mm_log "error: couldn't report initial kernel events: ModemManager not running" - return - } - - # Report cached kernel events - while IFS= read -r event_line; do - mm_report_event_from_cache_line "${event_line}" - done < ${MODEMMANAGER_EVENTS_CACHE} -} diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init deleted file mode 100755 index b3f9f9290..000000000 --- a/modemmanager/files/modemmanager.init +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2016 Aleksander Morgado - -USE_PROCD=1 -START=70 - -stop_service() { - # Load common utils - . /usr/share/ModemManager/modemmanager.common - # Set all configured interfaces as unavailable - mm_cleanup_interfaces -} - -start_service() { - # Setup ModemManager service - # - # We will make sure that the rundir always exists, and we initially cleanup - # all interfaces flagging them as unavailable. - # - # The cached events processing will wait for MM to be available in DBus - # and will make sure all ports are re-notified to ModemManager every time - # it starts. - # - # All these commands need to be executed on every MM start, even after - # procd-triggered respawns, which is why they're all included as instance command - # - procd_open_instance - procd_set_param command sh -c ". /usr/share/ModemManager/modemmanager.common; \ - mkdir -m 0755 -p ${MODEMMANAGER_RUNDIR}; \ - mm_cleanup_interfaces; \ - ( mm_report_events_from_cache ) >/dev/null 2>&1 & \ - /usr/sbin/ModemManager" - procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" - procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" - procd_close_instance -} diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto deleted file mode 100755 index d24910b98..000000000 --- a/modemmanager/files/modemmanager.proto +++ /dev/null @@ -1,550 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016-2019 Aleksander Morgado - -[ -x /usr/bin/mmcli ] || exit 0 -[ -x /usr/sbin/pppd ] || exit 0 - -[ -n "$INCLUDE_ONLY" ] || { - . /lib/functions.sh - . ../netifd-proto.sh - . ./ppp.sh - init_proto "$@" -} - -cdr2mask () -{ - # Number of args to shift, 255..255, first non-255 byte, zeroes - set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0 - if [ "$1" -gt 1 ] - then - shift "$1" - else - shift - fi - echo "${1-0}"."${2-0}"."${3-0}"."${4-0}" -} - -# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue -# The second argument must be exactly the name of the field to read -# -# Sample output: -# $ mmcli -m 0 -K -# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 -# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 -# modem.generic.manufacturer : Dell Inc. -# modem.generic.model : DW5821e Snapdragon X20 LTE -# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 -# modem.generic.carrier-configuration : GCF -# modem.generic.carrier-configuration-revision : 08E00009 -# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE -# .... -modemmanager_get_field() { - local list=$1 - local field=$2 - local value="" - - [ -z "${list}" ] || [ -z "${field}" ] && return - - # there is always at least a whitespace after each key, and we use that as part of the - # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result - # when grepping for 'modem.generic.state'. - line=$(echo "${list}" | grep "${field} ") - value=$(echo ${line#*:}) - - # not found? - [ -n "${value}" ] || return 2 - - # only print value if set - [ "${value}" != "--" ] && echo "${value}" - return 0 -} - -# build a comma-separated list of values from the list -modemmanager_get_multivalue_field() { - local list=$1 - local field=$2 - local value="" - local length idx item - - [ -z "${list}" ] || [ -z "${field}" ] && return - - length=$(modemmanager_get_field "${list}" "${field}.length") - [ -n "${length}" ] || return 0 - [ "$length" -ge 1 ] || return 0 - - idx=1 - while [ $idx -le "$length" ]; do - item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") - [ -n "${item}" ] && [ "${item}" != "--" ] && { - [ -n "${value}" ] && value="${value}, " - value="${value}${item}" - } - idx=$((idx + 1)) - done - - # nothing built? - [ -n "${value}" ] || return 2 - - # only print value if set - echo "${value}" - return 0 -} - -modemmanager_cleanup_connection() { - local modemstatus="$1" - - local bearercount idx bearerpath - - bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") - - # do nothing if no bearers reported - [ -n "${bearercount}" ] && [ "$bearercount" -ge 1 ] && { - # explicitly disconnect just in case - mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1 - # and remove all bearer objects, if any found - idx=1 - while [ $idx -le "$bearercount" ]; do - bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[$idx\]") - mmcli --modem "${device}" --delete-bearer="${bearerpath}" >/dev/null 2>&1 - idx=$((idx + 1)) - done - } -} - -modemmanager_connected_method_ppp_ipv4() { - local interface="$1" - local ttyname="$2" - local username="$3" - local password="$4" - local allowedauth="$5" - - # all auth types are allowed unless a user given list is given - local authopts - local pap=1 - local chap=1 - local mschap=1 - local mschapv2=1 - local eap=1 - - [ -n "$allowedauth" ] && { - pap=0 chap=0 mschap=0 mschapv2=0 eap=0 - for auth in $allowedauth; do - case $auth in - "pap") pap=1 ;; - "chap") chap=1 ;; - "mschap") mschap=1 ;; - "mschapv2") mschapv2=1 ;; - "eap") eap=1 ;; - *) ;; - esac - done - } - - [ $pap -eq 1 ] || append authopts "refuse-pap" - [ $chap -eq 1 ] || append authopts "refuse-chap" - [ $mschap -eq 1 ] || append authopts "refuse-mschap" - [ $mschapv2 -eq 1 ] || append authopts "refuse-mschap-v2" - [ $eap -eq 1 ] || append authopts "refuse-eap" - - proto_run_command "${interface}" /usr/sbin/pppd \ - "${ttyname}" \ - 115200 \ - nodetach \ - noaccomp \ - nobsdcomp \ - nopcomp \ - novj \ - noauth \ - $authopts \ - ${username:+ user $username} \ - ${password:+ password $password} \ - lcp-echo-failure 5 \ - lcp-echo-interval 15 \ - lock \ - crtscts \ - nodefaultroute \ - usepeerdns \ - ipparam "${interface}" \ - ip-up-script /lib/netifd/ppp-up \ - ip-down-script /lib/netifd/ppp-down -} - -modemmanager_disconnected_method_ppp_ipv4() { - local interface="$1" - - echo "running disconnection (ppp method)" - - [ -n "${ERROR}" ] && { - local errorstring - errorstring=$(ppp_exitcode_tostring "${ERROR}") - case "$ERROR" in - 0) - ;; - 2) - proto_notify_error "$interface" "$errorstring" - proto_block_restart "$interface" - ;; - *) - proto_notify_error "$interface" "$errorstring" - ;; - esac - } || echo "pppd result code not given" - - proto_kill_command "$interface" -} - -modemmanager_connected_method_dhcp_ipv4() { - local interface="$1" - local wwan="$2" - local metric="$3" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - proto_send_update "${interface}" - - json_init - json_add_string name "${interface}_4" - json_add_string ifname "@${interface}" - json_add_string proto "dhcp" - proto_add_dynamic_defaults - [ -n "$metric" ] && json_add_int metric "${metric}" - json_close_object - ubus call network add_dynamic "$(json_dump)" -} - -modemmanager_connected_method_static_ipv4() { - local interface="$1" - local wwan="$2" - local address="$3" - local prefix="$4" - local gateway="$5" - local mtu="$6" - local dns1="$7" - local dns2="$8" - local metric="$9" - - local mask="" - - [ -n "${address}" ] || { - proto_notify_error "${interface}" ADDRESS_MISSING - return - } - - [ -n "${prefix}" ] || { - proto_notify_error "${interface}" PREFIX_MISSING - return - } - mask=$(cdr2mask "${prefix}") - - [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - echo "adding IPv4 address ${address}, netmask ${mask}" - proto_add_ipv4_address "${address}" "${mask}" - [ -n "${gateway}" ] && { - echo "adding default IPv4 route via ${gateway}" - proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" - } - [ -n "${dns1}" ] && { - echo "adding primary DNS at ${dns1}" - proto_add_dns_server "${dns1}" - } - [ -n "${dns2}" ] && { - echo "adding secondary DNS at ${dns2}" - proto_add_dns_server "${dns2}" - } - [ -n "$metric" ] && json_add_int metric "${metric}" - proto_send_update "${interface}" -} - -modemmanager_connected_method_dhcp_ipv6() { - local interface="$1" - local wwan="$2" - local metric="$3" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - proto_send_update "${interface}" - - json_init - json_add_string name "${interface}_6" - json_add_string ifname "@${interface}" - json_add_string proto "dhcpv6" - proto_add_dynamic_defaults - json_add_string extendprefix 1 # RFC 7278: Extend an IPv6 /64 Prefix to LAN - [ -n "$metric" ] && json_add_int metric "${metric}" - json_close_object - ubus call network add_dynamic "$(json_dump)" -} - -modemmanager_connected_method_static_ipv6() { - local interface="$1" - local wwan="$2" - local address="$3" - local prefix="$4" - local gateway="$5" - local mtu="$6" - local dns1="$7" - local dns2="$8" - local metric="$9" - - [ -n "${address}" ] || { - proto_notify_error "${interface}" ADDRESS_MISSING - return - } - - [ -n "${prefix}" ] || { - proto_notify_error "${interface}" PREFIX_MISSING - return - } - - [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" - - proto_init_update "${wwan}" 1 - proto_set_keep 1 - echo "adding IPv6 address ${address}, prefix ${prefix}" - proto_add_ipv6_address "${address}" "128" - proto_add_ipv6_prefix "${address}/${prefix}" - [ -n "${gateway}" ] && { - echo "adding default IPv6 route via ${gateway}" - proto_add_ipv6_route "${gateway}" "128" - proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}" - } - [ -n "${dns1}" ] && { - echo "adding primary DNS at ${dns1}" - proto_add_dns_server "${dns1}" - } - [ -n "${dns2}" ] && { - echo "adding secondary DNS at ${dns2}" - proto_add_dns_server "${dns2}" - } - [ -n "$metric" ] && json_add_int metric "${metric}" - proto_send_update "${interface}" -} - -modemmanager_disconnected_method_common() { - local interface="$1" - - echo "running disconnection (common)" - proto_notify_error "${interface}" MM_DISCONNECT_IN_PROGRESS - - proto_init_update "*" 0 - proto_send_update "${interface}" -} - -proto_modemmanager_init_config() { - available=1 - no_device=1 - proto_config_add_string device - proto_config_add_string apn - proto_config_add_string 'allowedauth:list(string)' - proto_config_add_string username - proto_config_add_string password - proto_config_add_string pincode - proto_config_add_string iptype - proto_config_add_int signalrate - proto_config_add_boolean lowpower - proto_config_add_defaults -} - -proto_modemmanager_setup() { - local interface="$1" - - local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface - local bearermethod_ipv4 bearermethod_ipv6 auth cliauth - local operatorname operatorid registration accesstech signalquality - - local device apn allowedauth username password pincode iptype metric signalrate - - local address prefix gateway mtu dns1 dns2 - - json_get_vars device apn allowedauth username password pincode iptype metric signalrate - - # validate sysfs path given in config - [ -n "${device}" ] || { - echo "No device specified" - proto_notify_error "${interface}" NO_DEVICE - proto_set_available "${interface}" 0 - return 1 - } - [ -e "${device}" ] || { - echo "Device not found in sysfs" - proto_set_available "${interface}" 0 - return 1 - } - - # validate that ModemManager is handling the modem at the sysfs path - modemstatus=$(mmcli --modem="${device}" --output-keyvalue) - modempath=$(modemmanager_get_field "${modemstatus}" "modem.dbus-path") - [ -n "${modempath}" ] || { - echo "Device not managed by ModemManager" - proto_notify_error "${interface}" DEVICE_NOT_MANAGED - proto_set_available "${interface}" 0 - return 1 - } - echo "modem available at ${modempath}" - - # always cleanup before attempting a new connection, just in case - modemmanager_cleanup_connection "${modemstatus}" - - # if allowedauth list given, build option string - for auth in $allowedauth; do - cliauth="${cliauth}${cliauth:+|}$auth" - done - - # setup connect args; APN mandatory (even if it may be empty) - echo "starting connection with apn '${apn}'..." - proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS - - connectargs="apn=${apn}${iptype:+,ip-type=${iptype}}${cliauth:+,allowed-auth=${cliauth}}${username:+,user=${username}}${password:+,password=${password}}${pincode:+,pin=${pincode}}" - mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { - proto_notify_error "${interface}" MM_CONNECT_FAILED - proto_block_restart "${interface}" - return 1 - } - - # check if Signal refresh rate is set - if [ -n "${signalrate}" ] && [ "${signalrate}" -eq "${signalrate}" ] 2>/dev/null; then - echo "setting signal refresh rate to ${signalrate} seconds" - mmcli --modem="${device}" --signal-setup="${signalrate}" - else - echo "signal refresh rate is not set" - fi - - # log additional useful information - modemstatus=$(mmcli --modem="${device}" --output-keyvalue) - operatorname=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-name") - [ -n "${operatorname}" ] && echo "network operator name: ${operatorname}" - operatorid=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-code") - [ -n "${operatorid}" ] && echo "network operator MCCMNC: ${operatorid}" - registration=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.registration-state") - [ -n "${registration}" ] && echo "registration type: ${registration}" - accesstech=$(modemmanager_get_multivalue_field "${modemstatus}" "modem.generic.access-technologies") - [ -n "${accesstech}" ] && echo "access technology: ${accesstech}" - signalquality=$(modemmanager_get_field "${modemstatus}" "modem.generic.signal-quality.value") - [ -n "${signalquality}" ] && echo "signal quality: ${signalquality}%" - - # we won't like it if there are more than one bearers, as that would mean the - # user manually created them, and that's unsupported by this proto - bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") - [ -n "${bearercount}" ] && [ "$bearercount" -eq 1 ] || { - proto_notify_error "${interface}" INVALID_BEARER_LIST - return 1 - } - - # load connected bearer information - bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") - bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) - - # load network interface and method information - beareriface=$(modemmanager_get_field "${bearerstatus}" "bearer.status.interface") - bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") - bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") - - # setup IPv4 - [ -n "${bearermethod_ipv4}" ] && { - echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}" - case "${bearermethod_ipv4}" in - "dhcp") - modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" - ;; - "static") - address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address") - prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.prefix") - gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.gateway") - mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu") - dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]") - dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]") - modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" - ;; - "ppp") - modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}" - ;; - *) - proto_notify_error "${interface}" UNKNOWN_METHOD - return 1 - ;; - esac - } - - # setup IPv6 - # note: if using ipv4v6, both IPv4 and IPv6 settings will have the same MTU and metric values reported - [ -n "${bearermethod_ipv6}" ] && { - echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}" - case "${bearermethod_ipv6}" in - "dhcp") - modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" - ;; - "static") - address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address") - prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.prefix") - gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.gateway") - mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu") - dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]") - dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]") - modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" - ;; - "ppp") - proto_notify_error "${interface}" "unsupported method" - return 1 - ;; - *) - proto_notify_error "${interface}" UNKNOWN_METHOD - return 1 - ;; - esac - } - - return 0 -} - -proto_modemmanager_teardown() { - local interface="$1" - - local modemstatus bearerpath errorstring - local bearermethod_ipv4 bearermethod_ipv6 - - local device lowpower iptype - json_get_vars device lowpower iptype - - echo "stopping network" - proto_notify_error "${interface}" MM_TEARDOWN_IN_PROGRESS - - # load connected bearer information, just the first one should be ok - modemstatus=$(mmcli --modem="${device}" --output-keyvalue) - bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") - [ -n "${bearerpath}" ] || { - echo "couldn't load bearer path" - return - } - - # load bearer connection methods - bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) - bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") - [ -n "${bearermethod_ipv4}" ] && - echo "IPv4 connection teardown required in interface ${interface}: ${bearermethod_ipv4}" - bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") - [ -n "${bearermethod_ipv6}" ] && - echo "IPv6 connection teardown required in interface ${interface}: ${bearermethod_ipv6}" - - # disconnection handling only requires special treatment in IPv4/PPP - [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}" - modemmanager_disconnected_method_common "${interface}" - - # disconnect - mmcli --modem="${device}" --simple-disconnect || - proto_notify_error "${interface}" DISCONNECT_FAILED - - # disable - mmcli --modem="${device}" --disable - proto_notify_error "${interface}" MM_MODEM_DISABLED - - # low power, only if requested - [ "${lowpower:-0}" -lt 1 ] || - mmcli --modem="${device}" --set-power-state-low -} - -[ -n "$INCLUDE_ONLY" ] || { - add_protocol modemmanager -} From c52826cf6e91f83d731a988b305f9451ec2c7525 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Sep 2021 17:47:30 +0200 Subject: [PATCH 0607/2059] Add igbvf support --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 8ef0aaaf7..dc77a5cfe 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -79,7 +79,7 @@ MY_DEPENDS := \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su kmod-rtl8812au-ct \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 TARGET_r4s:kmod-r8168 (TARGET_x86||TARGET_x86_64):kmod-usb-net-rtl8152 \ luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ - luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-wolfssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf \ + luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-wolfssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status From c5d47067f67560a7494a9334c819381cf37424ee Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Sep 2021 15:09:58 +0200 Subject: [PATCH 0608/2059] Set shortcut-fe as disabled by default --- shortcut-fe/src/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shortcut-fe/src/Kconfig b/shortcut-fe/src/Kconfig index 487f1e065..f45e56b47 100644 --- a/shortcut-fe/src/Kconfig +++ b/shortcut-fe/src/Kconfig @@ -5,7 +5,8 @@ config SHORTCUT_FE tristate "Shortcut Forwarding Engine" depends on NF_CONNTRACK - ---help--- + default n + help Shortcut is a fast in-kernel packet forwarding engine. To compile this code as a module, choose M here: the module will be From 053cb2da1edfdf3660d9e2ed113530e9939d9e2f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Sep 2021 15:11:52 +0200 Subject: [PATCH 0609/2059] Compile for 5.4 and 5.14 kernel --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b25a0147..e976a9a6f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,13 +3,13 @@ on: [push] env: REPO_URL: 'https://github.com/ysurac/openmptcprouter' - OMR_KERNEL: '5.4' jobs: build: strategy: matrix: OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s] + OMR_KERNEL: [5.4, 5.14] runs-on: ubuntu-latest continue-on-error: true @@ -108,7 +108,7 @@ jobs: SOURCE_TAG: ${{ steps.branch_name.outputs.SOURCE_TAG }} with: command: | - mkdir -p deploy/${{env.SOURCE_BRANCH}}/${{env.OMR_KERNEL}}/${{matrix.OMR_TARGET}} + mkdir -p deploy/${{env.SOURCE_BRANCH}}/${{matrix.OMR_KERNEL}}/${{matrix.OMR_TARGET}} host: ${{ secrets.OMR_DEPLOY_HOST }} user: deploy port: ${{ secrets.OMR_DEPLOY_PORT }} @@ -141,7 +141,7 @@ jobs: uses: ysurac/action-rsync@master env: ARGS: -av --delete-after - TARGET: deploy/${{ steps.branch_name.outputs.SOURCE_BRANCH }}/${{env.OMR_KERNEL}}/${{matrix.OMR_TARGET}} + TARGET: deploy/${{ steps.branch_name.outputs.SOURCE_BRANCH }}/${{matrix.OMR_KERNEL}}/${{matrix.OMR_TARGET}} SOURCE: ./bin/ KEY: ${{ secrets.PRIVATE_KEY }} USER: deploy From 45596a198eebaeb7e1bbd46fc28d7a412c14f70c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Sep 2021 17:11:26 +0200 Subject: [PATCH 0610/2059] Fix both kernel compile with github actions --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e976a9a6f..68fafcf46 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,10 +61,11 @@ jobs: OMR_FEED_URL: https://github.com/ysurac/openmptcprouter-feeds SOURCE_NAME: ${{ steps.branch_name.outputs.SOURCE_NAME }} OMR_TARGET: ${{ matrix.OMR_TARGET }} + OMR_KERNELT: ${{ matrix.OMR_KERNEL }} OMR_HOST: ${{ secrets.OMR_HOST }} OMR_PORT: ${{ secrets.OMR_PORT }} run: | - OMR_FEED_SRC="${SOURCE_NAME}" sh build.sh prepare {tools,toolchain}/install -j$(nproc) || OMR_FEED_SRC="${SOURCE_NAME}" sh build.sh prepare {tools,toolchain}/install -j1 V=s + OMR_KERNEL="${OMR_KERNEL}" OMR_FEED_SRC="${SOURCE_NAME}" sh build.sh prepare {tools,toolchain}/install -j$(nproc) || OMR_KERNEL="${OMR_KERNEL}" OMR_FEED_SRC="${SOURCE_NAME}" sh build.sh prepare {tools,toolchain}/install -j1 V=s #echo -e "${{ secrets.OMR_PRIVKEY }}" > $OMR_TARGET/source/key-build #echo -e "${{ secrets.OMR_PUBKEY }}" > $OMR_TARGET/source/key-build.pub - name: Build packages From 66428bd6bc0d94ada0ef4e0910a853d4101c866b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Sep 2021 17:50:55 +0200 Subject: [PATCH 0611/2059] Fix typo --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 68fafcf46..532ed274e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,7 +61,7 @@ jobs: OMR_FEED_URL: https://github.com/ysurac/openmptcprouter-feeds SOURCE_NAME: ${{ steps.branch_name.outputs.SOURCE_NAME }} OMR_TARGET: ${{ matrix.OMR_TARGET }} - OMR_KERNELT: ${{ matrix.OMR_KERNEL }} + OMR_KERNEL: ${{ matrix.OMR_KERNEL }} OMR_HOST: ${{ secrets.OMR_HOST }} OMR_PORT: ${{ secrets.OMR_PORT }} run: | From a42b89fce17972f3f84e9598df9255128abf7d3b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 7 Oct 2021 12:39:28 +0200 Subject: [PATCH 0612/2059] Add Netgear R7800 to build --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 532ed274e..8345ecf8b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800] OMR_KERNEL: [5.4, 5.14] runs-on: ubuntu-latest continue-on-error: true From 18d100f50883986e91d0fb4682323370bfbe076d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 12 Oct 2021 19:56:19 +0200 Subject: [PATCH 0613/2059] Should fix omr-quota --- omr-quota/files/bin/omr-quota | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/omr-quota/files/bin/omr-quota b/omr-quota/files/bin/omr-quota index 69c2d2ba6..6b3f11501 100755 --- a/omr-quota/files/bin/omr-quota +++ b/omr-quota/files/bin/omr-quota @@ -10,8 +10,9 @@ shift # main loop while true; do - rx=`vnstat -i $OMR_QUOTA_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.months[-1].rx' | tr -d "\n"` - tx=`vnstat -i $OMR_QUOTA_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.months[-1].tx' | tr -d "\n"` + OMR_QUOTA_REAL_INTERFACE="$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.l3_device')" + rx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.months[-1].rx' | tr -d "\n"` + tx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.months[-1].tx' | tr -d "\n"` tt=$((rx + tx)) if [ -n "$OMR_QUOTA_RX" ] && [ "$OMR_QUOTA_RX" -gt 0 ] && [ -n "$rx" ] && [ "$OMR_QUOTA_RX" -le "$rx" ]; then if [ "$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.up')" = "true" ]; then From 9b5f1cc35166b46bdcdb095dbfcfe0989307c945 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 12 Oct 2021 19:56:53 +0200 Subject: [PATCH 0614/2059] Use OpenSSL instead of WolfSSL --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index dc77a5cfe..f6e533057 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -79,7 +79,7 @@ MY_DEPENDS := \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su kmod-rtl8812au-ct \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 TARGET_r4s:kmod-r8168 (TARGET_x86||TARGET_x86_64):kmod-usb-net-rtl8152 \ luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ - luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-wolfssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ + luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status From 015e660b0e1b07ec39aa39385cc14a9416a023d8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 17 Oct 2021 19:12:23 +0200 Subject: [PATCH 0615/2059] Try to set network config for r7800 --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 8e27a8332..c88bdde5a 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -117,6 +117,8 @@ elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ -d '/sys/class/net/et set network.@switch_vlan[4].vid=5 set network.@switch_vlan[4].ports='4 6t' EOF +elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ -d /sys/class/net/eth1 ] && [ "$(grep ipq806x /etc/os-release)" != "" ]; then + lanif="eth0.2" elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ -d /sys/class/net/eth1 ]; then lanif="eth1" elif [ ! -d /sys/class/net/eth1 ] && [ -d /sys/class/net/eth0 ]; then @@ -169,6 +171,11 @@ uci -q set network.lan.ip4table='lan' # Create WAN interfaces if [ "$(uci -q show network.wan1 | grep multipath)" = "" ] && [ -z "$(uci -q get network.wan1.multipath)" ]; then + if [ "$(grep ipq806x /etc/os-release)" != "" ]; then + _setup_wan_interface wan1 eth1.1 master + _setup_wan_interface wan2 eth1.2 on + _setup_wan_interface wan3 eth1.3 on + _setup_wan_interface wan4 eth1.4 on if [ "$(grep rockchip /etc/os-release)" != "" ]; then _setup_wan_interface wan1 eth0 master macvlan _setup_wan_interface wan2 eth0 on macvlan From c5889009cb8c37473940370608a690e70cd5c0e9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 18 Oct 2021 19:32:31 +0200 Subject: [PATCH 0616/2059] Add MPTCP IPV6 kernel setting --- mptcp/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/mptcp/Makefile b/mptcp/Makefile index ecfb24e82..95cb91198 100644 --- a/mptcp/Makefile +++ b/mptcp/Makefile @@ -24,6 +24,7 @@ define Package/mptcp DEPENDS:=+ip +iptables +ethtool +ipcalc KCONFIG:=\ CONFIG_MPTCP=y \ + CONFIG_MPTCP_IPV6=y \ CONFIG_MPTCP_BINDER=y \ CONFIG_MPTCP_FULLMESH=y \ CONFIG_MPTCP_NDIFFPORTS=y \ From f7179d54552029b3b800ecb8999cf7802d93f794 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Oct 2021 15:34:45 +0200 Subject: [PATCH 0617/2059] Dirty script to always mount FS as RW --- openmptcprouter/files/etc/init.d/alwaysrw | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 openmptcprouter/files/etc/init.d/alwaysrw diff --git a/openmptcprouter/files/etc/init.d/alwaysrw b/openmptcprouter/files/etc/init.d/alwaysrw new file mode 100755 index 000000000..81be5e4d8 --- /dev/null +++ b/openmptcprouter/files/etc/init.d/alwaysrw @@ -0,0 +1,7 @@ +#!/bin/sh /etc/rc.common + +START=10 + +boot() { + [ "$(mount | grep '/dev/root' | grep 'ext4' | grep '(ro')" != "" ] && mount -o remount,rw /dev/root +} From 6f200e37ddb4f0f6c4a554e929601fbf22c7dc9b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 Nov 2021 10:35:20 +0100 Subject: [PATCH 0618/2059] Fix network file --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index c88bdde5a..ef722926a 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -176,7 +176,7 @@ if [ "$(uci -q show network.wan1 | grep multipath)" = "" ] && [ -z "$(uci -q get _setup_wan_interface wan2 eth1.2 on _setup_wan_interface wan3 eth1.3 on _setup_wan_interface wan4 eth1.4 on - if [ "$(grep rockchip /etc/os-release)" != "" ]; then + elif [ "$(grep rockchip /etc/os-release)" != "" ]; then _setup_wan_interface wan1 eth0 master macvlan _setup_wan_interface wan2 eth0 on macvlan _setup_macvlan wan1 From a48b6d333a4d202871b7bd0a36f74e2e849c3d9b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 8 Nov 2021 20:15:42 +0100 Subject: [PATCH 0619/2059] Doesn't try to set firewall if VPS problem --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 5fb98c4b4..4e2e52212 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1127,7 +1127,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( #[ -z "$check_ipv6_website" ] && check_ipv6_website="http://ipv6.openmptcprouter.com/" #local ip6addr="$(curl -s -6 -m 2 $check_ipv6_website)" #[ -z "$ip6addr" ] && { - # local ip6addr="$(curl -s -6 -m 2 http://ifconfig.co/)" + # local ip6addr="$(curl -s -6 -m 2 http://ifconfig.me/)" #} #if [ "$(uci -q get openmptcprouter.settings.ipv6_disable)" = "0" ]; then # if [ -n "$ip6addr" ] && [ "$(uci -q get dhcp.lan.ra_default)" != 1 ]; then @@ -1507,7 +1507,7 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter fi -if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +if [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then _log "Set firewall on server" /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 From 267430215cf8c867dc004f7765a91c6893b183bf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Nov 2021 09:05:52 +0100 Subject: [PATCH 0620/2059] Remove mc fork --- mc/Config.in | 59 -------- mc/Makefile | 128 ------------------ mc/patches/010-subshell.patch | 11 -- ...20-fix-mouse-handling-newer-terminfo.patch | 11 -- mc/patches/030-fix-gettext-full-0.21.patch | 13 -- 5 files changed, 222 deletions(-) delete mode 100644 mc/Config.in delete mode 100644 mc/Makefile delete mode 100644 mc/patches/010-subshell.patch delete mode 100644 mc/patches/020-fix-mouse-handling-newer-terminfo.patch delete mode 100644 mc/patches/030-fix-gettext-full-0.21.patch diff --git a/mc/Config.in b/mc/Config.in deleted file mode 100644 index fcd8fad33..000000000 --- a/mc/Config.in +++ /dev/null @@ -1,59 +0,0 @@ -menu "Configuration" - depends on PACKAGE_mc - -config MC_DIFFVIEWER - bool "Enable internal diff viewer" - default n - help - This option enables the built-in diff viewer. - Disabled by default. - -config MC_EDITOR - bool "Enable internal editor" - default y - help - This option enables the built-in file editor. - Enabled by default. - -config MC_SUBSHELL - bool "Enable concurrent subshell" - default y - help - This option enables concurrent subshell support. - Enabled by default. - -config MC_LARGEFILE - bool "Enable largefile support" - default n - help - This option enables support for large files (> 2 GB). - Disabled by default. - -config MC_BACKGROUND - bool "Enable background operations" - default n - help - This option enables support for background operations which - allow to perform some tasks such as copying files in a - separate background process. Background code is known - to be less stable than the rest of the code. - Disabled by default. - -config MC_CHARSET - bool "Enable charset support" - default y - help - This option adds support for selecting character set of the text in - the internal viewer and editor and converting it on the fly. - Enabled by default. - -config MC_VFS - bool "Enable virtual filesystem support" - default y - help - This option enables the Virtual File System switch code to get - transparent access to the following file systems: - cpio, tar, fish, sfs, ftp, sftp, extfs. - Enabled by default. - -endmenu diff --git a/mc/Makefile b/mc/Makefile deleted file mode 100644 index 30814afb0..000000000 --- a/mc/Makefile +++ /dev/null @@ -1,128 +0,0 @@ -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=mc -PKG_VERSION:=4.8.25 -PKG_RELEASE:=2 -PKG_MAINTAINER:=Dirk Brenken -PKG_LICENSE:=GPL-3.0-or-later -PKG_CPE_ID:=cpe:/a:midnight_commander:midnight_commander - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=http://ftp.midnight-commander.org/ -PKG_HASH:=ffc19617f20ebb23330acd3998b7fd559a042d172fa55746d53d246697b2548a -PKG_BUILD_PARALLEL:=1 -PKG_FIXUP:=autoreconf gettext-version -PKG_BUILD_DEPENDS:=MC_VFS:libtirpc - -PKG_CONFIG_DEPENDS := \ - CONFIG_PACKAGE_MC \ - CONFIG_MC_DIFFVIEWER \ - CONFIG_MC_EDITOR \ - CONFIG_MC_SUBSHELL \ - CONFIG_MC_LARGEFILE \ - CONFIG_MC_BACKGROUND \ - CONFIG_MC_CHARSET \ - CONFIG_MC_VFS - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk - -define Package/mc - SECTION:=utils - CATEGORY:=Utilities - DEPENDS:=+glib2 +libncurses +libmount +MC_VFS:libssh2 $(ICONV_DEPENDS) - TITLE:=Midnight Commander - a powerful visual file manager - URL:=https://www.midnight-commander.org/ - MENU:=1 -endef - -define Package/mc/config - source "$(SOURCE)/Config.in" -endef - -define Package/mc/description -GNU Midnight Commander is a visual file manager. -It's a feature rich full-screen text mode application that allows you to copy, -move and delete files and whole directory trees, search for files and run commands in the subshell. -Internal viewer and editor are included as well. - -endef - -CONFIGURE_ARGS += \ - --enable-silent-rules \ - --disable-tests \ - --disable-doxygen-doc \ - --with-homedir=/etc/mc \ - --with-screen=ncurses \ - --without-x \ - -CONFIGURE_VARS += \ - ac_cv_search_addwstr=no \ - -ifeq ($(CONFIG_MC_DIFFVIEWER),) -CONFIGURE_ARGS += --without-diff-viewer -endif - -ifeq ($(CONFIG_MC_EDITOR),) -CONFIGURE_ARGS += --without-internal-edit -endif - -ifeq ($(CONFIG_MC_SUBSHELL),) -CONFIGURE_ARGS += --without-subshell -endif - -ifeq ($(CONFIG_MC_LARGEFILE),) -CONFIGURE_ARGS += --disable-largefile -endif - -ifeq ($(CONFIG_MC_BACKGROUND),) -CONFIGURE_ARGS += --disable-background -endif - -ifeq ($(CONFIG_MC_CHARSET),) -CONFIGURE_ARGS += --disable-charset -endif - -ifeq ($(CONFIG_MC_VFS),) -CONFIGURE_ARGS += --disable-vfs -else -TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/tirpc -endif - -define Package/mc/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mc $(1)/usr/bin - $(INSTALL_DIR) $(1)/etc/mc - $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.charsets $(1)/etc/mc - $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.ext $(1)/etc/mc - $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.default.keymap $(1)/etc/mc/mc.keymap - $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/filehighlight.ini $(1)/etc/mc - $(INSTALL_DIR) $(1)/usr/share/mc/help - $(INSTALL_DATA) $(PKG_BUILD_DIR)/doc/hlp/mc.hlp $(1)/usr/share/mc/help - $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.menu $(1)/etc/mc - $(INSTALL_DIR) $(1)/etc/mc/skins - $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/skins/default.ini $(1)/etc/mc/skins - $(INSTALL_DIR) $(1)/etc/mc/mcedit/Syntax -ifeq ($(CONFIG_MC_DIFFVIEWER),y) - ln -sf mc $(1)/usr/bin/mcdiff -endif -ifeq ($(CONFIG_MC_EDITOR),y) - ln -sf mc $(1)/usr/bin/mcedit -endif -ifeq ($(CONFIG_MC_VFS),y) - $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/vfs/sfs/sfs.ini $(1)/etc/mc - $(INSTALL_DIR) $(1)/usr/lib/mc/extfs.d -endif -endef - -define Package/mc/conffiles -/etc/mc/mc.menu -/etc/mc/skins/default.ini -endef - -$(eval $(call BuildPackage,mc)) diff --git a/mc/patches/010-subshell.patch b/mc/patches/010-subshell.patch deleted file mode 100644 index 73d8ca949..000000000 --- a/mc/patches/010-subshell.patch +++ /dev/null @@ -1,11 +0,0 @@ --- a/src/subshell/common.c -+++ b/src/subshell/common.c -@@ -836,7 +836,7 @@ init_subshell_precmd (char *precmd, size - "else " - "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; " - "fi; " -- "echo \"$USER@$(hostname -s):$MC_PWD\"; " -+ "echo \"$USER@$HOSTNAME:$MC_PWD\"; " - "pwd>&%d; " - "kill -STOP $$; " - "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]); diff --git a/mc/patches/020-fix-mouse-handling-newer-terminfo.patch b/mc/patches/020-fix-mouse-handling-newer-terminfo.patch deleted file mode 100644 index 82543379e..000000000 --- a/mc/patches/020-fix-mouse-handling-newer-terminfo.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/lib/tty/tty.c -+++ b/lib/tty/tty.c -@@ -370,7 +370,7 @@ tty_init_xterm_support (gboolean is_xter - if (xmouse_seq != NULL) - { - if (strcmp (xmouse_seq, ESC_STR "[<") == 0) -- xmouse_seq = ESC_STR "[M"; -+ xmouse_seq = NULL; - - xmouse_extended_seq = ESC_STR "[<"; - } diff --git a/mc/patches/030-fix-gettext-full-0.21.patch b/mc/patches/030-fix-gettext-full-0.21.patch deleted file mode 100644 index af44dcf66..000000000 --- a/mc/patches/030-fix-gettext-full-0.21.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/po/Makefile.in.in 2020-07-13 04:16:44.000000000 +0800 -+++ b/po/Makefile.in.in 2021-02-17 18:04:44.881887192 +0800 -@@ -8,8 +8,8 @@ - # Please note that the actual code of GNU gettext is covered by the GNU - # General Public License and is *not* in the public domain. - # --# Origin: gettext-0.18 --GETTEXT_MACRO_VERSION = 0.18 -+# Origin: gettext-0.20 -+GETTEXT_MACRO_VERSION = 0.20 - - PACKAGE = @PACKAGE@ - VERSION = @VERSION@ \ No newline at end of file From 1012645314f96661d167a5f31d9b0165ae309b88 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Nov 2021 18:36:56 +0100 Subject: [PATCH 0621/2059] Update golang --- golang/golang/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 2016dfb8c..1c311d571 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk -GO_VERSION_MAJOR_MINOR:=1.15 +GO_VERSION_MAJOR_MINOR:=1.17 GO_VERSION_PATCH:=2 PKG_NAME:=golang @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=28bf9d0bcde251011caae230a4a05d917b172ea203f2a62f2c2f9533589d4b4d +PKG_HASH:=2255eb3e4e824dd7d5fcdc2e7f84534371c186312e546fb1086a34c17752f431 PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause From e21bc3cfb0b184b42d2672d3ebd7fd325df63c92 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Nov 2021 18:37:16 +0100 Subject: [PATCH 0622/2059] Update v2ray --- v2ray-core/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 7fb4219d3..48f2f8197 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -9,12 +9,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=v2ray-core -PKG_VERSION:=4.35.1 +PKG_VERSION:=4.43.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/v$(PKG_VERSION) -PKG_HASH:=ef469a99c7db8596f8556478b478e2701ce2783af9affb7f3cb28201718e7d35 +PKG_HASH:=f27b8fe8e1e102b0297339ee368c8b650fde0f949e0d90e1229ff6744f99ba0f PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE From 0f938d50807d489db5a2d3ce96de3b234b4ce5ea Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Nov 2021 18:37:31 +0100 Subject: [PATCH 0623/2059] Update mlvpn --- mlvpn/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlvpn/Makefile b/mlvpn/Makefile index 1dbe8573b..455efe415 100644 --- a/mlvpn/Makefile +++ b/mlvpn/Makefile @@ -13,8 +13,8 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/zehome/MLVPN.git -PKG_SOURCE_VERSION:=8aa1b16d843ea68734e2520e39a34cb7f3d61b2b -PKG_SOURCE_DATE:=2021-08-14 +PKG_SOURCE_VERSION:=ddafba3c0bd63e0d733d3d5a4532e275714991b3 +PKG_SOURCE_DATE:=2021-10-28 #PKG_SOURCE_URL:=https://github.com/markfoodyburton/MLVPN.git #PKG_SOURCE_VERSION:=8f9720978b28c1954f9f229525333547283316d2 #PKG_SOURCE_DATE:=2018-09-03 From bf11c19bb40d0ffe2711cd1ea5c54f55ae1f7e7b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Nov 2021 08:30:39 +0100 Subject: [PATCH 0624/2059] Update RPI4 firmware --- bcm27xx-eeprom/Makefile | 4 ++-- .../patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/bcm27xx-eeprom/Makefile b/bcm27xx-eeprom/Makefile index dec227d51..1dcf6883b 100644 --- a/bcm27xx-eeprom/Makefile +++ b/bcm27xx-eeprom/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-eeprom -PKG_VERSION:=2fec47bd7f981c9cb21b0fb3fdd4fe07f23f9e3b +PKG_VERSION:=47976e4409c6999a8e211976c75c60a97c90275c PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/rpi-eeprom/tar.gz/$(PKG_VERSION)? -PKG_HASH:=f54c26ec399801dee7d3d0cc0e969c28878b6f42c982e166c863edb91d2d2a21 +PKG_HASH:=skip PKG_LICENSE:=BSD-3-Clause Custom PKG_LICENSE_FILES:=LICENSE diff --git a/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch index 059426306..7fc10a8a5 100644 --- a/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch +++ b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch @@ -14,7 +14,7 @@ Signed-off-by: Álvaro Fernández Rojas --- a/rpi-eeprom-update +++ b/rpi-eeprom-update -@@ -24,17 +24,17 @@ else +@@ -24,12 +24,12 @@ else fi # Selects the release sub-directory @@ -26,15 +26,9 @@ Signed-off-by: Álvaro Fernández Rojas ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1} RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}/recovery.bin} BOOTFS=${BOOTFS:-/boot} --VCMAILBOX=${VCMAILBOX:-/opt/vc/bin/vcmailbox} -+VCMAILBOX=${VCMAILBOX:-/usr/bin/vcmailbox} CM4_ENABLE_RPI_EEPROM_UPDATE=${CM4_ENABLE_RPI_EEPROM_UPDATE:-0} RPI_EEPROM_UPDATE_CONFIG_TOOL="${RPI_EEPROM_UPDATE_CONFIG_TOOL:-raspi-config}" - DT_BOOTLOADER_TS=${DT_BOOTLOADER_TS:-/proc/device-tree/chosen/bootloader/build-timestamp} - - EXIT_SUCCESS=0 - EXIT_UPDATE_REQUIRED=1 --- a/rpi-eeprom-update-default +++ b/rpi-eeprom-update-default @@ -1,8 +1,9 @@ From 734f9dd8c2b0134c37a716c8f5e9ab4ab90f52be Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Nov 2021 16:24:16 +0100 Subject: [PATCH 0625/2059] Update relatek drivers --- r8125/LICENSE | 21 - r8125/Makefile | 56 - r8125/README.md | 8 - r8125/src/Makefile | 184 - r8125/src/Makefile_linux24x | 75 - r8125/src/r8125.h | 2265 --- r8125/src/r8125_dash.h | 261 - r8125/src/r8125_n.c | 14487 ---------------- r8125/src/r8125_ptp.c | 594 - r8125/src/r8125_ptp.h | 81 - r8125/src/r8125_realwow.h | 118 - r8125/src/r8125_rss.c | 484 - r8125/src/r8125_rss.h | 66 - r8125/src/rtl_eeprom.c | 289 - r8125/src/rtl_eeprom.h | 53 - r8125/src/rtltool.c | 359 - r8125/src/rtltool.h | 86 - r8152/Makefile | 55 + ...not_on_list-was-backported-since-ker.patch | 26 + .../100-add-LED-configuration-from-OF.patch | 74 + r8168/Makefile | 54 + ...-r8168-add-LED-configuration-from-OF.patch | 42 + 22 files changed, 251 insertions(+), 19487 deletions(-) delete mode 100644 r8125/LICENSE delete mode 100644 r8125/Makefile delete mode 100644 r8125/README.md delete mode 100644 r8125/src/Makefile delete mode 100644 r8125/src/Makefile_linux24x delete mode 100644 r8125/src/r8125.h delete mode 100644 r8125/src/r8125_dash.h delete mode 100644 r8125/src/r8125_n.c delete mode 100644 r8125/src/r8125_ptp.c delete mode 100644 r8125/src/r8125_ptp.h delete mode 100644 r8125/src/r8125_realwow.h delete mode 100644 r8125/src/r8125_rss.c delete mode 100644 r8125/src/r8125_rss.h delete mode 100644 r8125/src/rtl_eeprom.c delete mode 100644 r8125/src/rtl_eeprom.h delete mode 100644 r8125/src/rtltool.c delete mode 100644 r8125/src/rtltool.h create mode 100644 r8152/Makefile create mode 100644 r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch create mode 100644 r8152/patches/100-add-LED-configuration-from-OF.patch create mode 100644 r8168/Makefile create mode 100644 r8168/patches/001-r8168-add-LED-configuration-from-OF.patch diff --git a/r8125/LICENSE b/r8125/LICENSE deleted file mode 100644 index f3077e149..000000000 --- a/r8125/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 goldkeyber112 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/r8125/Makefile b/r8125/Makefile deleted file mode 100644 index 02d07644d..000000000 --- a/r8125/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# Come from https://github.com/goldkeyber112/openwrt-r8125 -#Download realtek r8125 linux driver from official site -#Unpack source file -#Replace orginal Makefile with this file -#Put this source to 'package' folder of OpenWRT SDK -#Build(make menuconfig, make defconfig, make) - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=r8125 -PKG_VERSION:=9.005.01 -PKG_RELEASE:=1 - -#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 -#PKG_CAT:=bzcat - -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/r8125 - SUBMENU:=Network Devices - TITLE:=Driver for Realtek r8125 chipsets - VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) - FILES:= $(PKG_BUILD_DIR)/r8125.ko - AUTOLOAD:=$(call AutoProbe,r8125) - DEFAULT:=y -endef - -define Package/r8125/description - This package contains a driver for Realtek r8125 chipsets. -endef - -R8125_MAKEOPTS= -C $(PKG_BUILD_DIR) \ - PATH="$(TARGET_PATH)" \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - TARGET="$(HAL_TARGET)" \ - TOOLPREFIX="$(KERNEL_CROSS)" \ - TOOLPATH="$(KERNEL_CROSS)" \ - KERNELPATH="$(LINUX_DIR)" \ - KERNELDIR="$(LINUX_DIR)" \ - LDOPTS=" " \ - DOMULTI=1 - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR) -endef - -define Build/Compile - $(MAKE) $(R8125_MAKEOPTS) modules -endef - -$(eval $(call KernelPackage,r8125)) diff --git a/r8125/README.md b/r8125/README.md deleted file mode 100644 index a472d859e..000000000 --- a/r8125/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Realtek RTL8125 Driver for Openwrt - -Download realtek r8125 linux driver from official site -https://www.realtek.com/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software -Unpack source file -Replace orginal Makefile with this file -Put this source to 'package' folder of OpenWRT SDK -Build(make menuconfig, make defconfig, make) diff --git a/r8125/src/Makefile b/r8125/src/Makefile deleted file mode 100644 index f49c90676..000000000 --- a/r8125/src/Makefile +++ /dev/null @@ -1,184 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ - -################################################################################ -# This product is covered by one or more of the following patents: -# US6,570,884, US6,115,776, and US6,327,625. -################################################################################ - -CONFIG_SOC_LAN = n -ENABLE_REALWOW_SUPPORT = n -ENABLE_DASH_SUPPORT = n -ENABLE_DASH_PRINTER_SUPPORT = n -CONFIG_DOWN_SPEED_100 = n -CONFIG_ASPM = y -ENABLE_S5WOL = y -ENABLE_S5_KEEP_CURR_MAC = n -ENABLE_EEE = y -ENABLE_S0_MAGIC_PACKET = n -ENABLE_TX_NO_CLOSE = y -ENABLE_MULTIPLE_TX_QUEUE = n -ENABLE_PTP_SUPPORT = n -ENABLE_PTP_MASTER_MODE = n -ENABLE_RSS_SUPPORT = n -ENABLE_LIB_SUPPORT = n - -ifneq ($(KERNELRELEASE),) - obj-m := r8125.o - r8125-objs := r8125_n.o rtl_eeprom.o rtltool.o - ifeq ($(CONFIG_SOC_LAN), y) - EXTRA_CFLAGS += -DCONFIG_SOC_LAN - endif - ifeq ($(ENABLE_REALWOW_SUPPORT), y) - r8125-objs += r8125_realwow.o - EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT - endif - ifeq ($(ENABLE_DASH_SUPPORT), y) - r8125-objs += r8125_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT - endif - ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) - r8125-objs += r8125_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT - endif - EXTRA_CFLAGS += -DCONFIG_R8125_NAPI - EXTRA_CFLAGS += -DCONFIG_R8125_VLAN - ifeq ($(CONFIG_DOWN_SPEED_100), y) - EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 - endif - ifeq ($(CONFIG_ASPM), y) - EXTRA_CFLAGS += -DCONFIG_ASPM - endif - ifeq ($(ENABLE_S5WOL), y) - EXTRA_CFLAGS += -DENABLE_S5WOL - endif - ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) - EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC - endif - ifeq ($(ENABLE_EEE), y) - EXTRA_CFLAGS += -DENABLE_EEE - endif - ifeq ($(ENABLE_S0_MAGIC_PACKET), y) - EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET - endif - ifeq ($(ENABLE_TX_NO_CLOSE), y) - EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE - endif - ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y) - EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE - endif - ifeq ($(ENABLE_PTP_SUPPORT), y) - r8125-objs += r8125_ptp.o - EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT - endif - ifeq ($(ENABLE_PTP_MASTER_MODE), y) - EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE - endif - ifeq ($(ENABLE_RSS_SUPPORT), y) - r8125-objs += r8125_rss.o - EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT - endif - ifeq ($(ENABLE_LIB_SUPPORT), y) - r8125-objs += r8125_lib.o - EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT - endif -else - BASEDIR := /lib/modules/$(shell uname -r) - KERNELDIR ?= $(BASEDIR)/build - PWD :=$(shell pwd) - DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net/ethernet -name realtek -type d) - ifeq ($(DRIVERDIR),) - DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net -name realtek -type d) - endif - ifeq ($(DRIVERDIR),) - DRIVERDIR := $(BASEDIR)/kernel/drivers/net - endif - RTKDIR := $(subst $(BASEDIR)/,,$(DRIVERDIR)) - - KERNEL_GCC_VERSION := $(shell cat /proc/version | sed -n 's/.*gcc version \([[:digit:]]\.[[:digit:]]\.[[:digit:]]\).*/\1/p') - CCVERSION = $(shell $(CC) -dumpversion) - - KVER = $(shell uname -r) - KMAJ = $(shell echo $(KVER) | \ - sed -e 's/^\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*.*/\1/') - KMIN = $(shell echo $(KVER) | \ - sed -e 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*.*/\1/') - KREV = $(shell echo $(KVER) | \ - sed -e 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/') - - kver_ge = $(shell \ - echo test | awk '{if($(KMAJ) < $(1)) {print 0} else { \ - if($(KMAJ) > $(1)) {print 1} else { \ - if($(KMIN) < $(2)) {print 0} else { \ - if($(KMIN) > $(2)) {print 1} else { \ - if($(KREV) < $(3)) {print 0} else { print 1 } \ - }}}}}' \ - ) - -.PHONY: all -all: print_vars clean modules install - -print_vars: - @echo - @echo "CC: " $(CC) - @echo "CCVERSION: " $(CCVERSION) - @echo "KERNEL_GCC_VERSION: " $(KERNEL_GCC_VERSION) - @echo "KVER: " $(KVER) - @echo "KMAJ: " $(KMAJ) - @echo "KMIN: " $(KMIN) - @echo "KREV: " $(KREV) - @echo "BASEDIR: " $(BASEDIR) - @echo "DRIVERDIR: " $(DRIVERDIR) - @echo "PWD: " $(PWD) - @echo "RTKDIR: " $(RTKDIR) - @echo - -.PHONY:modules -modules: -#ifeq ($(call kver_ge,5,0,0),1) - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules -#else -# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules -#endif - -.PHONY:clean -clean: -#ifeq ($(call kver_ge,5,0,0),1) - $(MAKE) -C $(KERNELDIR) M=$(PWD) clean -#else -# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean -#endif - -.PHONY:install -install: -#ifeq ($(call kver_ge,5,0,0),1) - $(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install -#else -# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install -#endif - -endif diff --git a/r8125/src/Makefile_linux24x b/r8125/src/Makefile_linux24x deleted file mode 100644 index d043fb00c..000000000 --- a/r8125/src/Makefile_linux24x +++ /dev/null @@ -1,75 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ - -################################################################################ -# This product is covered by one or more of the following patents: -# US6,570,884, US6,115,776, and US6,327,625. -################################################################################ - -CC := gcc -LD := ld -ARCH := $(shell uname -m | sed 's/i.86/i386/') -KSRC := /lib/modules/$(shell uname -r)/build -CONFIG_FILE := $(KSRC)/include/linux/autoconf.h -KMISC := /lib/modules/$(shell uname -r)/kernel/drivers/net/ - - -ifeq ($(ARCH),x86_64) - MODCFLAGS += -mcmodel=kernel -mno-red-zone -endif - -#standard flags for module builds -MODCFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall -MODCFLAGS += -I$(KSRC)/include -I. -MODCFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h -SOURCE := r8125_n.c rtl_eeprom.c rtltool.c -OBJS := $(SOURCE:.c=.o) - - -SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \ - grep CONFIG_SMP | awk '{print $$3}') - -ifneq ($(SMP),1) - SMP := 0 -endif - -ifeq ($(SMP),1) - MODCFLAGS += -D__SMP__ -endif - -modules: $(OBJS) - $(LD) -r $^ -o r8125.o - strip --strip-debug r8125.o - -%.o: %.c - $(CC) $(MODCFLAGS) -c $< -o $@ - -clean: - rm *.o -f - -install: - install -m 744 -c r8125.o $(KMISC) diff --git a/r8125/src/r8125.h b/r8125/src/r8125.h deleted file mode 100644 index 06893797b..000000000 --- a/r8125/src/r8125.h +++ /dev/null @@ -1,2265 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef __R8125_H -#define __R8125_H - -//#include -#include -#include -#include -#include "r8125_dash.h" -#include "r8125_realwow.h" -#include "r8125_ptp.h" -#include "r8125_rss.h" -#ifdef ENABLE_LIB_SUPPORT -#include "r8125_lib.h" -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)&& !defined(ENABLE_LIB_SUPPORT) -#define RTL_USE_NEW_INTR_API -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define skb_transport_offset(skb) (skb->h.raw - skb->data) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -#define device_set_wakeup_enable(dev, val) do {} while (0) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) -static inline void ether_addr_copy(u8 *dst, const u8 *src) -{ - u16 *a = (u16 *)dst; - const u16 *b = (const u16 *)src; - - a[0] = b[0]; - a[1] = b[1]; - a[2] = b[2]; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) -#define IS_ERR_OR_NULL(ptr) (!ptr) -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) -#define reinit_completion(x) ((x)->done = 0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#define pm_runtime_mark_last_busy(x) -#define pm_runtime_put_autosuspend(x) pm_runtime_put(x) -#define pm_runtime_put_sync_autosuspend(x) pm_runtime_put_sync(x) - -static inline bool pm_runtime_suspended(struct device *dev) -{ - return dev->power.runtime_status == RPM_SUSPENDED - && !dev->power.disable_depth; -} - -static inline bool pm_runtime_active(struct device *dev) -{ - return dev->power.runtime_status == RPM_ACTIVE - || dev->power.disable_depth; -} -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -#define queue_delayed_work(long_wq, work, delay) schedule_delayed_work(work, delay) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netif_printk(priv, type, level, netdev, fmt, args...) \ - do { \ - if (netif_msg_##type(priv)) \ - printk(level "%s: " fmt,(netdev)->name , ##args); \ - } while (0) - -#define netif_emerg(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_EMERG, netdev, fmt, ##args) -#define netif_alert(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ALERT, netdev, fmt, ##args) -#define netif_crit(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_CRIT, netdev, fmt, ##args) -#define netif_err(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ERR, netdev, fmt, ##args) -#define netif_warn(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_WARNING, netdev, fmt, ##args) -#define netif_notice(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_NOTICE, netdev, fmt, ##args) -#define netif_info(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_INFO, (netdev), fmt, ##args) -#endif -#endif -#endif -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -#define setup_timer(_timer, _function, _data) \ -do { \ - (_timer)->function = _function; \ - (_timer)->data = _data; \ - init_timer(_timer); \ -} while (0) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) -#if defined(skb_vlan_tag_present) && !defined(vlan_tx_tag_present) -#define vlan_tx_tag_present skb_vlan_tag_present -#endif -#if defined(skb_vlan_tag_get) && !defined(vlan_tx_tag_get) -#define vlan_tx_tag_get skb_vlan_tag_get -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - -#define RTL_ALLOC_SKB_INTR(napi, length) dev_alloc_skb(length) -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#undef RTL_ALLOC_SKB_INTR -#define RTL_ALLOC_SKB_INTR(napi, length) napi_alloc_skb(napi, length) -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) -#define netdev_features_t u32 -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#else -#ifndef NETIF_F_ALL_CSUM -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#define ENABLE_R8125_PROCFS -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -#define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX -#define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -#define __devinit -#define __devexit -#define __devexit_p(func) func -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define CHECKSUM_PARTIAL CHECKSUM_HW -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define irqreturn_t void -#define IRQ_HANDLED 1 -#define IRQ_NONE 0 -#define IRQ_RETVAL(x) -#endif - -#ifndef NETIF_F_RXALL -#define NETIF_F_RXALL 0 -#endif - -#ifndef NETIF_F_RXFCS -#define NETIF_F_RXFCS 0 -#endif - -#ifndef HAVE_FREE_NETDEV -#define free_netdev(x) kfree(x) -#endif - -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) -#endif - -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) -#endif - -#ifndef SA_SHIRQ -#define SA_SHIRQ IRQF_SHARED -#endif - -#ifndef NETIF_F_GSO -#define gso_size tso_size -#define gso_segs tso_segs -#endif - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -#ifndef dma_mapping_error -#define dma_mapping_error(a,b) 0 -#endif - -#ifndef netif_err -#define netif_err(a,b,c,d) -#endif - -#ifndef AUTONEG_DISABLE -#define AUTONEG_DISABLE 0x00 -#endif - -#ifndef AUTONEG_ENABLE -#define AUTONEG_ENABLE 0x01 -#endif - -#ifndef BMCR_SPEED1000 -#define BMCR_SPEED1000 0x0040 -#endif - -#ifndef BMCR_SPEED100 -#define BMCR_SPEED100 0x2000 -#endif - -#ifndef BMCR_SPEED10 -#define BMCR_SPEED10 0x0000 -#endif - -#ifndef SPEED_UNKNOWN -#define SPEED_UNKNOWN -1 -#endif - -#ifndef DUPLEX_UNKNOWN -#define DUPLEX_UNKNOWN 0xff -#endif - -#ifndef SUPPORTED_Pause -#define SUPPORTED_Pause (1 << 13) -#endif - -#ifndef SUPPORTED_Asym_Pause -#define SUPPORTED_Asym_Pause (1 << 14) -#endif - -#ifndef MDIO_EEE_100TX -#define MDIO_EEE_100TX 0x0002 -#endif - -#ifndef MDIO_EEE_1000T -#define MDIO_EEE_1000T 0x0004 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#ifdef CONFIG_NET_POLL_CONTROLLER -#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8125_netpoll -#else -#define RTL_NET_POLL_CONTROLLER -#endif - -#ifdef CONFIG_R8125_VLAN -#define RTL_SET_VLAN dev->vlan_rx_register=rtl8125_vlan_rx_register -#else -#define RTL_SET_VLAN -#endif - -#define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8125_open; \ - dev->hard_start_xmit=rtl8125_start_xmit; \ - dev->get_stats=rtl8125_get_stats; \ - dev->stop=rtl8125_close; \ - dev->tx_timeout=rtl8125_tx_timeout; \ - dev->set_multicast_list=rtl8125_set_rx_mode; \ - dev->change_mtu=rtl8125_change_mtu; \ - dev->set_mac_address=rtl8125_set_mac_address; \ - dev->do_ioctl=rtl8125_do_ioctl; \ - RTL_NET_POLL_CONTROLLER; \ - RTL_SET_VLAN; -#else -#define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef false -#define false 0 -#endif - -#ifndef true -#define true 1 -#endif - -//Hardware will continue interrupt 10 times after interrupt finished. -#define RTK_KEEP_INTERRUPT_COUNT (10) - -//the low 32 bit address of receive buffer must be 8-byte alignment. -#ifndef NET_IP_ALIGN -#define NET_IP_ALIGN 2 -#endif -#define RTK_RX_ALIGN 8 - -#ifdef CONFIG_R8125_NAPI -#define NAPI_SUFFIX "-NAPI" -#else -#define NAPI_SUFFIX "" -#endif -#if defined(ENABLE_DASH_PRINTER_SUPPORT) -#define DASH_SUFFIX "-PRINTER" -#elif defined(ENABLE_DASH_SUPPORT) -#define DASH_SUFFIX "-DASH" -#else -#define DASH_SUFFIX "" -#endif - -#if defined(ENABLE_REALWOW_SUPPORT) -#define REALWOW_SUFFIX "-REALWOW" -#else -#define REALWOW_SUFFIX "" -#endif - -#if defined(ENABLE_PTP_SUPPORT) -#define PTP_SUFFIX "-PTP" -#else -#define PTP_SUFFIX "" -#endif - -#if defined(ENABLE_RSS_SUPPORT) -#define RSS_SUFFIX "-RSS" -#else -#define RSS_SUFFIX "" -#endif - -#define RTL8125_VERSION "9.005.01" NAPI_SUFFIX DASH_SUFFIX REALWOW_SUFFIX PTP_SUFFIX RSS_SUFFIX -#define MODULENAME "r8125" -#define PFX MODULENAME ": " - -#define GPL_CLAIM "\ -r8125 Copyright (C) 2021 Realtek NIC software team \n \ -This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ -This is free software, and you are welcome to redistribute it under certain conditions; see . \n" - -#ifdef RTL8125_DEBUG -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8125_DEBUG */ - -#define R8125_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#ifdef CONFIG_R8125_NAPI -#define rtl8125_rx_hwaccel_skb vlan_hwaccel_receive_skb -#define rtl8125_rx_quota(count, quota) min(count, quota) -#else -#define rtl8125_rx_hwaccel_skb vlan_hwaccel_rx -#define rtl8125_rx_quota(count, quota) count -#endif - -/* MAC address length */ -#ifndef MAC_ADDR_LEN -#define MAC_ADDR_LEN 6 -#endif - -#ifndef MAC_PROTOCOL_LEN -#define MAC_PROTOCOL_LEN 2 -#endif - -#ifndef ETH_FCS_LEN -#define ETH_FCS_LEN 4 -#endif - -#ifndef NETIF_F_TSO6 -#define NETIF_F_TSO6 0 -#endif - -#define Reserved2_data 7 -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST_unlimited 7 -#define TX_DMA_BURST_1024 6 -#define TX_DMA_BURST_512 5 -#define TX_DMA_BURST_256 4 -#define TX_DMA_BURST_128 3 -#define TX_DMA_BURST_64 2 -#define TX_DMA_BURST_32 1 -#define TX_DMA_BURST_16 0 -#define Reserved1_data 0x3F -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define Jumbo_Frame_1k ETH_DATA_LEN -#define Jumbo_Frame_2k (2*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_3k (3*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_4k (4*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_5k (5*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_6k (6*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_7k (7*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_8k (8*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_9k (9*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -#define RxEarly_off_V1 (0x07 << 11) -#define RxEarly_off_V2 (1 << 11) -#define Rx_Single_fetch_V2 (1 << 14) - -#define R8125_REGS_SIZE (256) -#define R8125_MAC_REGS_SIZE (256) -#define R8125_PHY_REGS_SIZE (16*2) -#define R8125_EPHY_REGS_SIZE (31*2) -#define R8125_ERI_REGS_SIZE (0x100) -#define R8125_REGS_DUMP_SIZE (0x400) -#define R8125_PCI_REGS_SIZE (0x100) -#define R8125_NAPI_WEIGHT 64 - -#define R8125_MAX_MSIX_VEC_8125B 32 -#define R8125_MIN_MSIX_VEC_8125B 17 -#define R8125_MAX_MSIX_VEC 32 -#define R8125_MAX_RX_QUEUES_VEC_V3 (16) - -#define RTL8125_TX_TIMEOUT (6 * HZ) -#define RTL8125_LINK_TIMEOUT (1 * HZ) -#define RTL8125_ESD_TIMEOUT (2 * HZ) - -#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ - -#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ -#define R8125_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8125_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) -#define R8125_MAX_TX_QUEUES (2) -#define R8125_MAX_RX_QUEUES (4) -#define R8125_MAX_QUEUES R8125_MAX_RX_QUEUES - -#ifdef ENABLE_LIB_SUPPORT -#define R8125_MULTI_RX_Q(tp) 1 -#else -#define R8125_MULTI_RX_Q(tp) (tp->num_rx_rings > 1) -#endif - -#define NODE_ADDRESS_SIZE 6 - -#define SHORT_PACKET_PADDING_BUF_SIZE 256 - -#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef - -/* write/read MMIO register */ -#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) -#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) -#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg)) -#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg)) -#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg)) -#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg))) - -#ifndef DMA_64BIT_MASK -#define DMA_64BIT_MASK 0xffffffffffffffffULL -#endif - -#ifndef DMA_32BIT_MASK -#define DMA_32BIT_MASK 0x00000000ffffffffULL -#endif - -#ifndef NETDEV_TX_OK -#define NETDEV_TX_OK 0 /* driver took care of packet */ -#endif - -#ifndef NETDEV_TX_BUSY -#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ -#endif - -#ifndef NETDEV_TX_LOCKED -#define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */ -#endif - -#ifndef ADVERTISED_Pause -#define ADVERTISED_Pause (1 << 13) -#endif - -#ifndef ADVERTISED_Asym_Pause -#define ADVERTISED_Asym_Pause (1 << 14) -#endif - -#ifndef ADVERTISE_PAUSE_CAP -#define ADVERTISE_PAUSE_CAP 0x400 -#endif - -#ifndef ADVERTISE_PAUSE_ASYM -#define ADVERTISE_PAUSE_ASYM 0x800 -#endif - -#ifndef MII_CTRL1000 -#define MII_CTRL1000 0x09 -#endif - -#ifndef ADVERTISE_1000FULL -#define ADVERTISE_1000FULL 0x200 -#endif - -#ifndef ADVERTISE_1000HALF -#define ADVERTISE_1000HALF 0x100 -#endif - -#ifndef ADVERTISED_2500baseX_Full -#define ADVERTISED_2500baseX_Full 0x8000 -#endif - -#define RTK_ADVERTISE_2500FULL 0x80 - -/* Tx NO CLOSE */ -#define MAX_TX_NO_CLOSE_DESC_PTR_V2 0x10000 -#define TX_NO_CLOSE_SW_PTR_MASK_V2 0x1FFFF - -#ifndef ETH_MIN_MTU -#define ETH_MIN_MTU 68 -#endif - -#define D0_SPEED_UP_SPEED_DISABLE 0 -#define D0_SPEED_UP_SPEED_1000 1 -#define D0_SPEED_UP_SPEED_2500 2 - -#ifndef WRITE_ONCE -#define WRITE_ONCE(var, val) (*((volatile typeof(val) *)(&(var))) = (val)) -#endif -#ifndef READ_ONCE -#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) -#endif - -/*****************************************************************************/ - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ - (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ - ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) -/* copied from linux kernel 2.6.20 include/linux/netdev.h */ -#define NETDEV_ALIGN 32 -#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) - -static inline void *netdev_priv(struct net_device *dev) -{ - return (char *)dev + ((sizeof(struct net_device) - + NETDEV_ALIGN_CONST) - & ~NETDEV_ALIGN_CONST); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define RTLDEV tp -#else -#define RTLDEV dev -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -typedef struct net_device *napi_ptr; -typedef int *napi_budget; - -#define napi dev -#define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ - ndev->weight=weig; -#define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) -#define RTL_RX_QUOTA(budget) *budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ - ndev->quota -= work_done; -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) -#define RTL_NAPI_RETURN_VALUE work_done >= work_to_do -#define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) -#define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) -#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) -#else -typedef struct napi_struct *napi_ptr; -typedef int napi_budget; - -#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -#define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; -#define RTL_RX_QUOTA(budget) budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev, napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) -#endif -#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete_done(napi, work_done) -#else -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete(napi) -#endif -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) -#endif -#define RTL_NAPI_RETURN_VALUE work_done -#define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) -#define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -#define RTL_NAPI_DEL(priv) -#else -#define RTL_NAPI_DEL(priv) netif_napi_del(&priv->napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - -/*****************************************************************************/ -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) napi_consume_skb(skb, budget) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); -#else -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) -#else //CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); -#else -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); -#endif -#endif //CONFIG_R8125_NAPI - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -#ifdef __CHECKER__ -#define __iomem __attribute__((noderef, address_space(2))) -extern void __chk_io_ptr(void __iomem *); -#define __bitwise __attribute__((bitwise)) -#else -#define __iomem -#define __chk_io_ptr(x) (void)0 -#define __bitwise -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#else -#define __force -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) - -#ifndef module_param -#define module_param(v,t,p) MODULE_PARM(v, "i"); -#endif - -#ifndef PCI_DEVICE -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif - -/*****************************************************************************/ -/* 2.5.28 => 2.4.23 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) - -static inline void _kc_synchronize_irq(void) -{ - synchronize_irq(); -} -#undef synchronize_irq -#define synchronize_irq(X) _kc_synchronize_irq() - -#include -#define work_struct tq_struct -#undef INIT_WORK -#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) -#undef container_of -#define container_of list_entry -#define schedule_work schedule_task -#define flush_scheduled_work flush_scheduled_tasks -#endif /* 2.5.28 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) -#define MODULE_VERSION(_version) MODULE_INFO(version, _version) -#endif /* 2.6.4 => 2.6.0 */ -/*****************************************************************************/ -/* 2.6.0 => 2.5.28 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -#define MODULE_INFO(version, _version) -#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT -#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 -#endif - -#define pci_set_consistent_dma_mask(dev,mask) 1 - -#undef dev_put -#define dev_put(dev) __dev_put(dev) - -#ifndef skb_fill_page_desc -#define skb_fill_page_desc _kc_skb_fill_page_desc -extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); -#endif - -#ifndef pci_dma_mapping_error -#define pci_dma_mapping_error _kc_pci_dma_mapping_error -static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) -{ - return dma_addr == 0; -} -#endif - -#undef ALIGN -#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) - -#endif /* 2.6.0 => 2.5.28 */ - -/*****************************************************************************/ -/* 2.4.22 => 2.4.17 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -#define pci_name(x) ((x)->slot_name) -#endif /* 2.4.22 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.5 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) -#define pci_dma_sync_single_for_cpu pci_dma_sync_single -#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu -#endif /* 2.6.5 => 2.6.0 */ - -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -/* - * initialize a work-struct's func and data pointers: - */ -#define PREPARE_WORK(_work, _func, _data) \ - do { \ - (_work)->func = _func; \ - (_work)->data = _data; \ - } while (0) - -#endif -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) && \ - LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))) -#define ETHTOOL_OPS_COMPAT -#endif /* 2.6.4 => 2.6.0 */ - -/*****************************************************************************/ -/* Installations with ethtool version without eeprom, adapter id, or statistics - * support */ - -#ifndef ETH_GSTRING_LEN -#define ETH_GSTRING_LEN 32 -#endif - -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x1d -#undef ethtool_drvinfo -#define ethtool_drvinfo k_ethtool_drvinfo -struct k_ethtool_drvinfo { - u32 cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char bus_info[32]; - char reserved1[32]; - char reserved2[16]; - u32 n_stats; - u32 testinfo_len; - u32 eedump_len; - u32 regdump_len; -}; - -struct ethtool_stats { - u32 cmd; - u32 n_stats; - u64 data[0]; -}; -#endif /* ETHTOOL_GSTATS */ - -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x1c -#endif /* ETHTOOL_PHYS_ID */ - -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x1b -enum ethtool_stringset { - ETH_SS_TEST = 0, - ETH_SS_STATS, -}; -struct ethtool_gstrings { - u32 cmd; /* ETHTOOL_GSTRINGS */ - u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ - u32 len; /* number of strings in the string set */ - u8 data[0]; -}; -#endif /* ETHTOOL_GSTRINGS */ - -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x1a -enum ethtool_test_flags { - ETH_TEST_FL_OFFLINE = (1 << 0), - ETH_TEST_FL_FAILED = (1 << 1), -}; -struct ethtool_test { - u32 cmd; - u32 flags; - u32 reserved; - u32 len; - u64 data[0]; -}; -#endif /* ETHTOOL_TEST */ - -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0xb -#undef ETHTOOL_GREGS -struct ethtool_eeprom { - u32 cmd; - u32 magic; - u32 offset; - u32 len; - u8 data[0]; -}; - -struct ethtool_value { - u32 cmd; - u32 data; -}; -#endif /* ETHTOOL_GEEPROM */ - -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0xa -#endif /* ETHTOOL_GLINK */ - -#ifndef ETHTOOL_GREGS -#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ -#define ethtool_regs _kc_ethtool_regs -/* for passing big chunks of data */ -struct _kc_ethtool_regs { - u32 cmd; - u32 version; /* driver-specific, indicates different chips/revs */ - u32 len; /* bytes */ - u8 data[0]; -}; -#endif /* ETHTOOL_GREGS */ - -#ifndef ETHTOOL_GMSGLVL -#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -#endif -#ifndef ETHTOOL_SMSGLVL -#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ -#endif -#ifndef ETHTOOL_NWAY_RST -#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ -#endif -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0x0000000a /* Get link status */ -#endif -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -#endif -#ifndef ETHTOOL_SEEPROM -#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ -#endif -#ifndef ETHTOOL_GCOALESCE -#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -/* for configuring coalescing parameters of chip */ -#define ethtool_coalesce _kc_ethtool_coalesce -struct _kc_ethtool_coalesce { - u32 cmd; /* ETHTOOL_{G,S}COALESCE */ - - /* How many usecs to delay an RX interrupt after - * a packet arrives. If 0, only rx_max_coalesced_frames - * is used. - */ - u32 rx_coalesce_usecs; - - /* How many packets to delay an RX interrupt after - * a packet arrives. If 0, only rx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause RX interrupts to never be - * generated. - */ - u32 rx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 rx_coalesce_usecs_irq; - u32 rx_max_coalesced_frames_irq; - - /* How many usecs to delay a TX interrupt after - * a packet is sent. If 0, only tx_max_coalesced_frames - * is used. - */ - u32 tx_coalesce_usecs; - - /* How many packets to delay a TX interrupt after - * a packet is sent. If 0, only tx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause TX interrupts to never be - * generated. - */ - u32 tx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 tx_coalesce_usecs_irq; - u32 tx_max_coalesced_frames_irq; - - /* How many usecs to delay in-memory statistics - * block updates. Some drivers do not have an in-memory - * statistic block, and in such cases this value is ignored. - * This value must not be zero. - */ - u32 stats_block_coalesce_usecs; - - /* Adaptive RX/TX coalescing is an algorithm implemented by - * some drivers to improve latency under low packet rates and - * improve throughput under high packet rates. Some drivers - * only implement one of RX or TX adaptive coalescing. Anything - * not implemented by the driver causes these values to be - * silently ignored. - */ - u32 use_adaptive_rx_coalesce; - u32 use_adaptive_tx_coalesce; - - /* When the packet rate (measured in packets per second) - * is below pkt_rate_low, the {rx,tx}_*_low parameters are - * used. - */ - u32 pkt_rate_low; - u32 rx_coalesce_usecs_low; - u32 rx_max_coalesced_frames_low; - u32 tx_coalesce_usecs_low; - u32 tx_max_coalesced_frames_low; - - /* When the packet rate is below pkt_rate_high but above - * pkt_rate_low (both measured in packets per second) the - * normal {rx,tx}_* coalescing parameters are used. - */ - - /* When the packet rate is (measured in packets per second) - * is above pkt_rate_high, the {rx,tx}_*_high parameters are - * used. - */ - u32 pkt_rate_high; - u32 rx_coalesce_usecs_high; - u32 rx_max_coalesced_frames_high; - u32 tx_coalesce_usecs_high; - u32 tx_max_coalesced_frames_high; - - /* How often to do adaptive coalescing packet rate sampling, - * measured in seconds. Must not be zero. - */ - u32 rate_sample_interval; -}; -#endif /* ETHTOOL_GCOALESCE */ - -#ifndef ETHTOOL_SCOALESCE -#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -#endif -#ifndef ETHTOOL_GRINGPARAM -#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -/* for configuring RX/TX ring parameters */ -#define ethtool_ringparam _kc_ethtool_ringparam -struct _kc_ethtool_ringparam { - u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ - - /* Read only attributes. These indicate the maximum number - * of pending RX/TX ring entries the driver will allow the - * user to set. - */ - u32 rx_max_pending; - u32 rx_mini_max_pending; - u32 rx_jumbo_max_pending; - u32 tx_max_pending; - - /* Values changeable by the user. The valid values are - * in the range 1 to the "*_max_pending" counterpart above. - */ - u32 rx_pending; - u32 rx_mini_pending; - u32 rx_jumbo_pending; - u32 tx_pending; -}; -#endif /* ETHTOOL_GRINGPARAM */ - -#ifndef ETHTOOL_SRINGPARAM -#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ -#endif -#ifndef ETHTOOL_GPAUSEPARAM -#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -/* for configuring link flow control parameters */ -#define ethtool_pauseparam _kc_ethtool_pauseparam -struct _kc_ethtool_pauseparam { - u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ - - /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the - * pause parameters be auto-negotiated too. In such a case, the - * {rx,tx}_pause values below determine what capabilities are - * advertised. - * - * If 'autoneg' is zero or the link is not being auto-negotiated, - * then {rx,tx}_pause force the driver to use/not-use pause - * flow control. - */ - u32 autoneg; - u32 rx_pause; - u32 tx_pause; -}; -#endif /* ETHTOOL_GPAUSEPARAM */ - -#ifndef ETHTOOL_SPAUSEPARAM -#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -#endif -#ifndef ETHTOOL_GRXCSUM -#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_SRXCSUM -#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GTXCSUM -#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STXCSUM -#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GSG -#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable -* (ethtool_value) */ -#endif -#ifndef ETHTOOL_SSG -#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable -* (ethtool_value). */ -#endif -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ -#endif -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -#endif -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -#endif -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -#endif -#ifndef ETHTOOL_GTSO -#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STSO -#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -#endif - -#ifndef ETHTOOL_BUSINFO_LEN -#define ETHTOOL_BUSINFO_LEN 32 -#endif - -/*****************************************************************************/ - -enum RTL8125_registers { - MAC0 = 0x00, /* Ethernet hardware address. */ - MAC4 = 0x04, - MAR0 = 0x08, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - CustomLED = 0x18, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - INT_CFG0_8125 = 0x34, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - TCTR = 0x48, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - TDFNR = 0x57, - TimeInt0 = 0x58, - TimeInt1 = 0x5C, - PHYAR = 0x60, - CSIDR = 0x64, - CSIAR = 0x68, - PHYstatus = 0x6C, - MACDBG = 0x6D, - GPIO = 0x6E, - PMCH = 0x6F, - ERIDR = 0x70, - ERIAR = 0x74, - INT_CFG1_8125 = 0x7A, - EPHY_RXER_NUM = 0x7C, - EPHYAR = 0x80, - TimeInt2 = 0x8C, - OCPDR = 0xB0, - MACOCP = 0xB0, - OCPAR = 0xB4, - SecMAC0 = 0xB4, - SecMAC4 = 0xB8, - PHYOCP = 0xB8, - DBG_reg = 0xD1, - TwiCmdReg = 0xD2, - MCUCmd_reg = 0xD3, - RxMaxSize = 0xDA, - EFUSEAR = 0xDC, - CPlusCmd = 0xE0, - IntrMitigate = 0xE2, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - MTPS = 0xEC, - FuncEvent = 0xF0, - PPSW = 0xF2, - FuncEventMask = 0xF4, - TimeInt3 = 0xF4, - FuncPresetState = 0xF8, - CMAC_IBCR0 = 0xF8, - CMAC_IBCR2 = 0xF9, - CMAC_IBIMR0 = 0xFA, - CMAC_IBISR0 = 0xFB, - FuncForceEvent = 0xFC, - //8125 - IMR0_8125 = 0x38, - ISR0_8125 = 0x3C, - TPPOLL_8125 = 0x90, - IMR1_8125 = 0x800, - ISR1_8125 = 0x802, - IMR2_8125 = 0x804, - ISR2_8125 = 0x806, - IMR3_8125 = 0x808, - ISR3_8125 = 0x80A, - BACKUP_ADDR0_8125 = 0x19E0, - BACKUP_ADDR1_8125 = 0X19E4, - TCTR0_8125 = 0x0048, - TCTR1_8125 = 0x004C, - TCTR2_8125 = 0x0088, - TCTR3_8125 = 0x001C, - TIMER_INT0_8125 = 0x0058, - TIMER_INT1_8125 = 0x005C, - TIMER_INT2_8125 = 0x008C, - TIMER_INT3_8125 = 0x00F4, - INT_MITI_V2_0_RX = 0x0A00, - INT_MITI_V2_0_TX = 0x0A02, - INT_MITI_V2_1_TX = 0x0A0A, - IMR_V2_CLEAR_REG_8125 = 0x0D00, - ISR_V2_8125 = 0x0D04, - IMR_V2_SET_REG_8125 = 0x0D0C, - TNPDS_Q1_LOW_8125 = 0x2100, - SW_TAIL_PTR0_8125 = 0x2800, - HW_CLO_PTR0_8125 = 0x2802, - RDSAR_Q1_LOW_8125 = 0x4000, - RSS_CTRL_8125 = 0x4500, - Q_NUM_CTRL_8125 = 0x4800, - EEE_TXIDLE_TIMER_8125 = 0x6048, - PTP_CTRL_8125 = 0x6800, - PTP_STATUS_8125 = 0x6802, - PTP_ISR_8125 = 0x6804, - PTP_IMR_8125 = 0x6805, - PTP_TIME_CORRECT_CMD_8125 = 0x6806, - PTP_SOFT_CONFIG_Time_NS_8125 = 0x6808, - PTP_SOFT_CONFIG_Time_S_8125 = 0x680C, - PTP_LOCAL_Time_SUB_NS_8125 = 0x6814, - PTP_LOCAL_Time_NS_8125 = 0x6818, - PTP_LOCAL_Time_S_8125 = 0x681C, - PTP_Time_SHIFTER_S_8125 = 0x6856, - PPS_RISE_TIME_NS_8125 = 0x68A0, - PPS_RISE_TIME_S_8125 = 0x68A4, -}; - -enum RTL8125_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxDescUnavail = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - RxDU1 = 0x0002, - RxOK1 = 0x0001, - - /* RxStatusDesc */ - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - RxRWT_V3 = (1 << 18), - RxRES_V3 = (1 << 20), - RxRUNT_V3 = (1 << 19), - RxCRC_V3 = (1 << 17), - - /* ChipCmdBits */ - StopReq = 0x80, - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, - Cfg9346_EEDO = (1 << 0), - Cfg9346_EEDI = (1 << 1), - Cfg9346_EESK = (1 << 2), - Cfg9346_EECS = (1 << 3), - Cfg9346_EEM0 = (1 << 6), - Cfg9346_EEM1 = (1 << 7), - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* Transmit Priority Polling*/ - HPQ = 0x80, - NPQ = 0x40, - FSWInt = 0x01, - - /* RxConfigBits */ - Reserved2_shift = 13, - RxCfgDMAShift = 8, - EnableRxDescV3 = (1 << 24), - EnableOuterVlan = (1 << 23), - EnableInnerVlan = (1 << 22), - RxCfg_128_int_en = (1 << 15), - RxCfg_fet_multi_en = (1 << 14), - RxCfg_half_refetch = (1 << 13), - RxCfg_9356SEL = (1 << 6), - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - TxMACLoopBack = (1 << 17), /* MAC loopback */ - - /* Config1 register */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register */ - PMSTS_En = (1 << 5), - - /* Config3 register */ - Isolate_en = (1 << 12), /* Isolate enable */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* This bit is reserved in RTL8125B.*/ - /* Wake up when the cable connection is re-established */ - ECRCEN = (1 << 3), /* This bit is reserved in RTL8125B*/ - Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8125B*/ - RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8125B*/ - Beacon_en = (1 << 0), /* This bit is reserved in RTL8125B*/ - - /* Config4 register */ - Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8125B*/ - - /* Config5 register */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* CPlusCmd */ - EnableBist = (1 << 15), - Macdbgo_oe = (1 << 14), - Normal_mode = (1 << 13), - Force_halfdup = (1 << 12), - Force_rxflow_en = (1 << 11), - Force_txflow_en = (1 << 10), - Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8125B - ASF = (1 << 8),//This bit is reserved in RTL8125C - PktCntrDisable = (1 << 7), - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - Macdbgo_sel = 0x001C, - INTT_0 = 0x0000, - INTT_1 = 0x0001, - INTT_2 = 0x0002, - INTT_3 = 0x0003, - - /* rtl8125_PHYstatus */ - PowerSaveStatus = 0x80, - _2500bpsF = 0x400, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* DBG_reg */ - Fix_Nak_1 = (1 << 4), - Fix_Nak_2 = (1 << 3), - DBGPIN_E2 = (1 << 0), - - /* ResetCounterCommand */ - CounterReset = 0x1, - /* DumpCounterCommand */ - CounterDump = 0x8, - - /* PHY access */ - PHYAR_Flag = 0x80000000, - PHYAR_Write = 0x80000000, - PHYAR_Read = 0x00000000, - PHYAR_Reg_Mask = 0x1f, - PHYAR_Reg_shift = 16, - PHYAR_Data_Mask = 0xffff, - - /* EPHY access */ - EPHYAR_Flag = 0x80000000, - EPHYAR_Write = 0x80000000, - EPHYAR_Read = 0x00000000, - EPHYAR_Reg_Mask = 0x3f, - EPHYAR_Reg_Mask_v2 = 0x7f, - EPHYAR_Reg_shift = 16, - EPHYAR_Data_Mask = 0xffff, - - /* CSI access */ - CSIAR_Flag = 0x80000000, - CSIAR_Write = 0x80000000, - CSIAR_Read = 0x00000000, - CSIAR_ByteEn = 0x0f, - CSIAR_ByteEn_shift = 12, - CSIAR_Addr_Mask = 0x0fff, - - /* ERI access */ - ERIAR_Flag = 0x80000000, - ERIAR_Write = 0x80000000, - ERIAR_Read = 0x00000000, - ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ - ERIAR_ExGMAC = 0, - ERIAR_MSIX = 1, - ERIAR_ASF = 2, - ERIAR_OOB = 2, - ERIAR_Type_shift = 16, - ERIAR_ByteEn = 0x0f, - ERIAR_ByteEn_shift = 12, - - /* OCP GPHY access */ - OCPDR_Write = 0x80000000, - OCPDR_Read = 0x00000000, - OCPDR_Reg_Mask = 0xFF, - OCPDR_Data_Mask = 0xFFFF, - OCPDR_GPHY_Reg_shift = 16, - OCPAR_Flag = 0x80000000, - OCPAR_GPHY_Write = 0x8000F060, - OCPAR_GPHY_Read = 0x0000F060, - OCPR_Write = 0x80000000, - OCPR_Read = 0x00000000, - OCPR_Addr_Reg_shift = 16, - OCPR_Flag = 0x80000000, - OCP_STD_PHY_BASE_PAGE = 0x0A40, - - /* MCU Command */ - Now_is_oob = (1 << 7), - Txfifo_empty = (1 << 5), - Rxfifo_empty = (1 << 4), - - /* E-FUSE access */ - EFUSE_WRITE = 0x80000000, - EFUSE_WRITE_OK = 0x00000000, - EFUSE_READ = 0x00000000, - EFUSE_READ_OK = 0x80000000, - EFUSE_WRITE_V3 = 0x40000000, - EFUSE_WRITE_OK_V3 = 0x00000000, - EFUSE_READ_V3 = 0x80000000, - EFUSE_READ_OK_V3 = 0x00000000, - EFUSE_Reg_Mask = 0x03FF, - EFUSE_Reg_Shift = 8, - EFUSE_Check_Cnt = 300, - EFUSE_READ_FAIL = 0xFF, - EFUSE_Data_Mask = 0x000000FF, - - /* GPIO */ - GPIO_en = (1 << 0), - - /* PTP */ - PTP_ISR_TOK = (1 << 1), - PTP_ISR_TER = (1 << 2), - PTP_EXEC_CMD = (1 << 7), - PTP_ADJUST_TIME_NS_NEGATIVE = (1 << 30), - PTP_ADJUST_TIME_S_NEGATIVE = (1ULL << 48), - - /* New Interrupt Bits */ - INT_CFG0_ENABLE_8125 = (1 << 0), - INT_CFG0_TIMEOUT0_BYPASS_8125 = (1 << 1), - INT_CFG0_MITIGATION_BYPASS_8125 = (1 << 2), - ISRIMR_V2_ROK_Q0 = (1 << 0), - ISRIMR_TOK_Q0 = (1 << 16), - ISRIMR_TOK_Q1 = (1 << 18), - ISRIMR_V2_LINKCHG = (1 << 21), - - /* Magic Number */ - RTL8125_MAGIC_NUMBER = 0x0badbadbadbadbadull, -}; - -enum _DescStatusBit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - DescOwn_V3 = (DescOwn), /* Descriptor is owned by NIC */ - RingEnd_V3 = (RingEnd), /* End of descriptor ring */ - FirstFrag_V3 = (1 << 25), /* First segment of a packet */ - LastFrag_V3 = (1 << 24), /* Final segment of a packet */ - - /* Tx private */ - /*------ offset 0 of tx descriptor ------*/ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ - GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ - LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0x7FFU, /* MSS value 11 bits */ - TxIPCS = (1 << 18), /* Calculate IP checksum */ - TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only begin @@@@@@*/ - TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ - TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ - TxIPCS_C = (1 << 29), /* Calculate IP checksum */ - TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */ - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only end @@@@@@*/ - - - /* Rx private */ - /*------ offset 0 of rx descriptor ------*/ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - RxIPF = (1 << 16), /* IP checksum failed */ - RxUDPF = (1 << 15), /* UDP/IP checksum failed */ - RxTCPF = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxUDPT = (1 << 18), - RxTCPT = (1 << 17), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxV6F = (1 << 31), - RxV4F = (1 << 30), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - - PID1_v3 = (1 << 29), /* Protocol ID bit 1/2 */ - PID0_v3 = (1 << 28), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP_v3 (PID1_v3) -#define RxProtoTCP_v3 (PID0_v3) -#define RxProtoIP_v3 (PID1_v3 | PID0_v3) -#define RxProtoMask_v3 RxProtoIP_v3 - - RxIPF_v3 = (1 << 26), /* IP checksum failed */ - RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */ - RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */ - RxSCTPF_v3 = (1 << 23), /* TCP/IP checksum failed */ - RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxUDPT_v3 = (1 << 29), - RxTCPT_v3 = (1 << 28), - RxSCTP_v3 = (1 << 27), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxV6F_v3 = (RxV6F), - RxV4F_v3 = (RxV4F), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ -}; - -enum features { -// RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_MSIX = (1 << 2), -}; - -enum wol_capability { - WOL_DISABLED = 0, - WOL_ENABLED = 1 -}; - -enum bits { - BIT_0 = (1 << 0), - BIT_1 = (1 << 1), - BIT_2 = (1 << 2), - BIT_3 = (1 << 3), - BIT_4 = (1 << 4), - BIT_5 = (1 << 5), - BIT_6 = (1 << 6), - BIT_7 = (1 << 7), - BIT_8 = (1 << 8), - BIT_9 = (1 << 9), - BIT_10 = (1 << 10), - BIT_11 = (1 << 11), - BIT_12 = (1 << 12), - BIT_13 = (1 << 13), - BIT_14 = (1 << 14), - BIT_15 = (1 << 15), - BIT_16 = (1 << 16), - BIT_17 = (1 << 17), - BIT_18 = (1 << 18), - BIT_19 = (1 << 19), - BIT_20 = (1 << 20), - BIT_21 = (1 << 21), - BIT_22 = (1 << 22), - BIT_23 = (1 << 23), - BIT_24 = (1 << 24), - BIT_25 = (1 << 25), - BIT_26 = (1 << 26), - BIT_27 = (1 << 27), - BIT_28 = (1 << 28), - BIT_29 = (1 << 29), - BIT_30 = (1 << 30), - BIT_31 = (1 << 31) -}; - -enum effuse { - EFUSE_NOT_SUPPORT = 0, - EFUSE_SUPPORT_V1, - EFUSE_SUPPORT_V2, - EFUSE_SUPPORT_V3, - EFUSE_SUPPORT_V4, -}; -#define RsvdMask 0x3fffc000 -#define RsvdMaskV3 0x3fff8000 - -struct TxDesc { - u32 opts1; - u32 opts2; - u64 addr; - u32 reserved0; - u32 reserved1; - u32 reserved2; - u32 reserved3; -}; - -struct RxDesc { - u32 opts1; - u32 opts2; - u64 addr; -}; - -struct RxDescV3 { - union { - struct { - u32 rsv1; - u32 rsv2; - } RxDescDDWord1; - }; - - union { - struct { - u32 RSSResult; - u16 HeaderBufferLen; - u16 HeaderInfo; - } RxDescNormalDDWord2; - - struct { - u32 rsv5; - u32 rsv6; - } RxDescDDWord2; - }; - - union { - u64 addr; - - struct { - u32 TimeStampLow; - u32 TimeStampHigh; - } RxDescTimeStamp; - - struct { - u32 rsv8; - u32 rsv9; - } RxDescDDWord3; - }; - - union { - struct { - u32 opts2; - u32 opts1; - } RxDescNormalDDWord4; - - struct { - u16 TimeStampHHigh; - u16 rsv11; - u32 opts1; - } RxDescPTPDDWord4; - }; -}; - -enum rxdesc_type { - RXDESC_TYPE_NORMAL=0, - RXDESC_TYPE_NEXT, - RXDESC_TYPE_PTP, - RXDESC_TYPE_MAX -}; - -//Rx Desc Type -enum rx_desc_ring_type { - RX_DESC_RING_TYPE_UNKNOWN=0, - RX_DESC_RING_TYPE_1, - RX_DESC_RING_TYPE_2, - RX_DESC_RING_TYPE_3, - RX_DESC_RING_TYPE_MAX -}; - -enum rx_desc_len { - RX_DESC_LEN_TYPE_1 = (sizeof(struct RxDesc)), - RX_DESC_LEN_TYPE_3 = (sizeof(struct RxDescV3)) -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -struct pci_resource { - u8 cmd; - u8 cls; - u16 io_base_h; - u16 io_base_l; - u16 mem_base_h; - u16 mem_base_l; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_h; - u16 resv_0x20_l; - u16 resv_0x24_h; - u16 resv_0x24_l; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; -}; - -struct rtl8125_tx_ring { - void* priv; - u32 index; - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - dma_addr_t TxPhyAddr; - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - - u32 NextHwDesCloPtr; - u32 BeginHwDesCloPtr; - - u16 hw_clo_ptr_reg; - u16 sw_tail_ptr_reg; - - u16 tdsar_reg; /* Transmit Descriptor Start Address */ -}; - -struct rtl8125_rx_ring { - void* priv; - u32 index; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - u64 RxDescPhyAddr[NUM_RX_DESC]; /* Rx desc physical address*/ - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - - u16 rdsar_reg; /* Receive Descriptor Start Address */ -}; - -struct r8125_napi { -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - struct napi_struct napi; -#endif -#endif - void* priv; - int index; -}; - -struct r8125_irq { - irq_handler_t handler; - unsigned int vector; - u8 requested; - char name[IFNAMSIZ + 10]; -}; - -/* Flow Control Settings */ -enum rtl8125_fc_mode { - rtl8125_fc_none = 0, - rtl8125_fc_rx_pause, - rtl8125_fc_tx_pause, - rtl8125_fc_full, - rtl8125_fc_default -}; - -struct rtl8125_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct r8125_napi r8125napi[R8125_MAX_MSIX_VEC]; - struct r8125_irq irq_tbl[R8125_MAX_MSIX_VEC]; - unsigned int irq_nvecs; - unsigned int max_irq_nvecs; - unsigned int min_irq_nvecs; - //struct msix_entry msix_entries[R8125_MAX_MSIX_VEC]; - struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - u32 tx_tcp_csum_cmd; - u32 tx_udp_csum_cmd; - u32 tx_ip_csum_cmd; - u32 tx_ipv6_csum_cmd; - int max_jumbo_frame_size; - int chipset; - u32 mcfg; - //u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - //u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - //u32 dirty_rx; - //u32 dirty_tx; - //struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - //struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - //dma_addr_t TxPhyAddr; - //dma_addr_t RxPhyAddr; - //struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - //struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned rx_buf_sz; - u16 HwSuppNumTxQueues; - u16 HwSuppNumRxQueues; - unsigned int num_tx_rings; - unsigned int num_rx_rings; - struct rtl8125_tx_ring tx_ring[R8125_MAX_TX_QUEUES]; - struct rtl8125_rx_ring rx_ring[R8125_MAX_RX_QUEUES]; -#ifdef ENABLE_LIB_SUPPORT - struct atomic_notifier_head lib_nh; - struct rtl8125_ring lib_tx_ring[R8125_MAX_TX_QUEUES]; - struct rtl8125_ring lib_rx_ring[R8125_MAX_RX_QUEUES]; -#endif - struct timer_list esd_timer; - struct timer_list link_timer; - struct pci_resource pci_cfg_space; - unsigned int esd_flag; - unsigned int pci_cfg_is_read; - unsigned int rtl8125_rx_config; - u16 cp_cmd; - u32 intr_mask; - u32 timer_intr_mask; - u16 isr_reg[R8125_MAX_QUEUES]; - u16 imr_reg[R8125_MAX_QUEUES]; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; - int phy_2500_ctrl_reg; - u8 org_mac_addr[NODE_ADDRESS_SIZE]; - struct rtl8125_counters *tally_vaddr; - dma_addr_t tally_paddr; - -#ifdef CONFIG_R8125_VLAN - struct vlan_group *vlgrp; -#endif - u8 wol_enabled; - u32 wol_opts; - u8 efuse_ver; - u8 eeprom_type; - u8 autoneg; - u8 duplex; - u32 speed; - u32 advertising; - enum rtl8125_fc_mode fcpause; - u16 eeprom_len; - u16 cur_page; - u32 bios_setting; - - int (*set_speed)(struct net_device *, u8 autoneg, u32 speed, u8 duplex, u32 adv); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - void (*get_settings)(struct net_device *, struct ethtool_cmd *); -#else - void (*get_settings)(struct net_device *, struct ethtool_link_ksettings *); -#endif - void (*phy_reset_enable)(struct net_device *); - unsigned int (*phy_reset_pending)(struct net_device *); - unsigned int (*link_ok)(struct net_device *); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct task; -#else - struct delayed_work task; -#endif - unsigned features; - - u8 org_pci_offset_99; - u8 org_pci_offset_180; - u8 issue_offset_99_event; - - u8 org_pci_offset_80; - u8 org_pci_offset_81; - u8 use_timer_interrrupt; - - u32 keep_intr_cnt; - - u8 HwIcVerUnknown; - u8 NotWrRamCodeToMicroP; - u8 NotWrMcuPatchCode; - u8 HwHasWrRamCodeToMicroP; - - u16 sw_ram_code_ver; - u16 hw_ram_code_ver; - - u8 rtk_enable_diag; - - u8 ShortPacketSwChecksum; - - u8 UseSwPaddingShortPkt; - - u8 RequireAdcBiasPatch; - u16 AdcBiasPatchIoffset; - - u8 RequireAdjustUpsTxLinkPulseTiming; - u16 SwrCnt1msIni; - - u8 HwSuppNowIsOobVer; - - u8 RequiredSecLanDonglePatch; - - u8 RequirePhyMdiSwapPatch; - - u8 RequireLSOPatch; - - u32 HwFiberModeVer; - u32 HwFiberStat; - u8 HwSwitchMdiToFiber; - - u16 NicCustLedValue; - - u8 HwSuppMagicPktVer; - - u8 HwSuppLinkChgWakeUpVer; - - u8 HwSuppCheckPhyDisableModeVer; - - u8 random_mac; - - u8 HwSuppGigaForceMode; - - u16 phy_reg_anlpar; - - u32 HwPcieSNOffset; - - u8 HwSuppTxNoCloseVer; - u8 EnableTxNoClose; - - u8 HwSuppIsrVer; - u8 HwCurrIsrVer; - - u8 HwSuppIntMitiVer; - - u8 check_keep_link_speed; - u8 resume_not_chg_speed; - - u8 HwSuppD0SpeedUpVer; - u8 D0SpeedUpSpeed; - - //Dash+++++++++++++++++ - u8 HwSuppDashVer; - u8 DASH; - u8 dash_printer_enabled; - u8 HwPkgDet; - void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */ - void __iomem *cmac_ioaddr; /* cmac memory map physical address */ - -#ifdef ENABLE_DASH_SUPPORT - u16 AfterRecvFromFwBufLen; - u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE]; - u16 AfterSendToFwBufLen; - u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE]; - u16 SendToFwBufferLen; - u32 SizeOfSendToFwBuffer; - u32 SizeOfSendToFwBufferMemAlloc; - u32 NumOfSendToFwBuffer; - - u8 OobReq; - u8 OobAck; - u32 OobReqComplete; - u32 OobAckComplete; - - u8 RcvFwReqSysOkEvt; - u8 RcvFwDashOkEvt; - u8 SendFwHostOkEvt; - - u8 DashFwDisableRx; - - void *UnalignedSendToFwBufferVa; - void *SendToFwBuffer; - u64 SendToFwBufferPhy; - u8 SendingToFw; - dma_addr_t UnalignedSendToFwBufferPa; - PTX_DASH_SEND_FW_DESC TxDashSendFwDesc; - u64 TxDashSendFwDescPhy; - u8 *UnalignedTxDashSendFwDescVa; - u32 SizeOfTxDashSendFwDescMemAlloc; - u32 SizeOfTxDashSendFwDesc; - u32 NumTxDashSendFwDesc; - u32 CurrNumTxDashSendFwDesc; - u32 LastSendNumTxDashSendFwDesc; - dma_addr_t UnalignedTxDashSendFwDescPa; - - u32 NumRecvFromFwBuffer; - u32 SizeOfRecvFromFwBuffer; - u32 SizeOfRecvFromFwBufferMemAlloc; - void *RecvFromFwBuffer; - u64 RecvFromFwBufferPhy; - - void *UnalignedRecvFromFwBufferVa; - dma_addr_t UnalignedRecvFromFwBufferPa; - PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc; - u64 RxDashRecvFwDescPhy; - u8 *UnalignedRxDashRecvFwDescVa; - u32 SizeOfRxDashRecvFwDescMemAlloc; - u32 SizeOfRxDashRecvFwDesc; - u32 NumRxDashRecvFwDesc; - u32 CurrNumRxDashRecvFwDesc; - dma_addr_t UnalignedRxDashRecvFwDescPa; - u8 DashReqRegValue; - u16 HostReqValue; - - u32 CmacResetIsrCounter; - u8 CmacResetIntr; - u8 CmacResetting; - u8 CmacOobIssueCmacReset; - u32 CmacResetbyFwCnt; - -#if defined(ENABLE_DASH_PRINTER_SUPPORT) - struct completion fw_ack; - struct completion fw_req; - struct completion fw_host_ok; -#endif - //Dash----------------- -#endif //ENABLE_DASH_SUPPORT - - //Realwow++++++++++++++ - u8 HwSuppKCPOffloadVer; - - u8 EnableDhcpTimeoutWake; - u8 EnableTeredoOffload; - u8 EnableKCPOffload; -#ifdef ENABLE_REALWOW_SUPPORT - u32 DhcpTimeout; - MP_KCP_INFO MpKCPInfo; - //Realwow-------------- -#endif //ENABLE_REALWOW_SUPPORT - - u32 eee_adv_t; - u8 eee_enabled; - -#ifdef ENABLE_R8125_PROCFS - //Procfs support - struct proc_dir_entry *proc_dir; -#endif - u8 InitRxDescType; - u16 RxDescLength; //V1 16 Byte V2 32 Bytes - u32 RxDescRingLength; - - u8 HwSuppPtpVer; - u8 EnablePtp; - u8 ptp_master_mode; - s64 ptp_adjust; -#ifdef ENABLE_PTP_SUPPORT - u32 tx_hwtstamp_timeouts; - u32 tx_hwtstamp_skipped; - struct work_struct ptp_tx_work; - struct sk_buff *ptp_tx_skb; - struct hwtstamp_config hwtstamp_config; - unsigned long ptp_tx_start; - struct ptp_clock_info ptp_clock_info; - struct ptp_clock *ptp_clock; -#endif - - u8 HwSuppRssVer; - u8 EnableRss; - u16 HwSuppIndirTblEntries; -#ifdef ENABLE_RSS_SUPPORT - u32 rss_flags; - /* Receive Side Scaling settings */ -#define RTL8125_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ - u8 rss_key[RTL8125_RSS_KEY_SIZE]; -#define RTL8125_MAX_INDIRECTION_TABLE_ENTRIES 128 - u8 rss_indir_tbl[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; - u32 rss_options; -#endif -}; - -#ifdef ENABLE_LIB_SUPPORT -static inline unsigned int -rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) -{ - int count, i; - - for (count = 0, i = tp->num_tx_rings; i < tp->HwSuppNumTxQueues; i++) - if(tp->lib_tx_ring[i].enabled) - count++; - - return count; -} - -static inline unsigned int -rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) -{ - int count, i; - - for (count = 0, i = tp->num_rx_rings; i < tp->HwSuppNumRxQueues; i++) - if(tp->lib_rx_ring[i].enabled) - count++; - - return count; -} - -#else -static inline unsigned int -rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) -{ - return 0; -} - -static inline unsigned int -rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) -{ - return 0; -} -#endif - -static inline unsigned int -rtl8125_tot_tx_rings(struct rtl8125_private *tp) -{ - return tp->num_tx_rings + rtl8125_num_lib_tx_rings(tp); -} - -static inline unsigned int -rtl8125_tot_rx_rings(struct rtl8125_private *tp) -{ - return tp->num_rx_rings + rtl8125_num_lib_rx_rings(tp); -} - -enum eetype { - EEPROM_TYPE_NONE=0, - EEPROM_TYPE_93C46, - EEPROM_TYPE_93C56, - EEPROM_TWSI -}; - -enum mcfg { - CFG_METHOD_2=2, - CFG_METHOD_3, - CFG_METHOD_4, - CFG_METHOD_5, - CFG_METHOD_MAX, - CFG_METHOD_DEFAULT = 0xFF -}; - -#define LSO_32K 32000 -#define LSO_64K 64000 - -#define NIC_MIN_PHYS_BUF_COUNT (2) -#define NIC_MAX_PHYS_BUF_COUNT_LSO_64K (24) -#define NIC_MAX_PHYS_BUF_COUNT_LSO2 (16*4) - -#define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x7fU -#define GTPKTSIZE_MAX 0x3ffffU -#define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU -#define LSOPKTSIZE_MAX 0xffffU -#define MSS_MAX 0x07ffu /* MSS value */ - -#define OOB_CMD_RESET 0x00 -#define OOB_CMD_DRIVER_START 0x05 -#define OOB_CMD_DRIVER_STOP 0x06 -#define OOB_CMD_SET_IPMAC 0x41 - -#define WAKEUP_MAGIC_PACKET_NOT_SUPPORT (0) -#define WAKEUP_MAGIC_PACKET_V1 (1) -#define WAKEUP_MAGIC_PACKET_V2 (2) -#define WAKEUP_MAGIC_PACKET_V3 (3) - -//Ram Code Version -#define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0b11) -#define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0b33) -#define NIC_RAMCODE_VERSION_CFG_METHOD_4 (0x0b17) -#define NIC_RAMCODE_VERSION_CFG_METHOD_5 (0x0b55) - -//hwoptimize -#define HW_PATCH_SOC_LAN (BIT_0) -#define HW_PATCH_SAMSUNG_LAN_DONGLE (BIT_2) - -static const u16 other_q_intr_mask = (RxOK1 | RxDU1); - -void rtl8125_mdio_write(struct rtl8125_private *tp, u32 RegAddr, u32 value); -void rtl8125_mdio_prot_write(struct rtl8125_private *tp, u32 RegAddr, u32 value); -void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, u32 RegAddr, u32 value); -u32 rtl8125_mdio_read(struct rtl8125_private *tp, u32 RegAddr); -u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, u32 RegAddr); -u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, u32 RegAddr); -void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value); -void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value); -u16 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr); -void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); -void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); -void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 data); -void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd); -void rtl8125_init_ring_indexes(struct rtl8125_private *tp); -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); -void rtl8125_oob_mutex_lock(struct rtl8125_private *tp); -u32 rtl8125_mdio_read(struct rtl8125_private *tp, u32 RegAddr); -u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len); -u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 base_address); -u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, u32 base_address); -u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type); -u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, u32 base_address); -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); -int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, u32 base_address); -u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr); -void rtl8125_wait_txrx_fifo_empty(struct net_device *dev); -void rtl8125_enable_now_is_oob(struct rtl8125_private *tp); -void rtl8125_disable_now_is_oob(struct rtl8125_private *tp); -void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp); -void rtl8125_dash2_disable_tx(struct rtl8125_private *tp); -void rtl8125_dash2_enable_tx(struct rtl8125_private *tp); -void rtl8125_dash2_disable_rx(struct rtl8125_private *tp); -void rtl8125_dash2_enable_rx(struct rtl8125_private *tp); -void rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev); -void rtl8125_mark_to_asic(struct rtl8125_private *tp, struct RxDesc *desc, u32 rx_buf_sz); - -static inline void -rtl8125_make_unusable_by_asic(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { - ((struct RxDescV3 *)desc)->addr = RTL8125_MAGIC_NUMBER; - ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV3); - } else { - desc->addr = RTL8125_MAGIC_NUMBER; - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); - } -} - -static inline struct RxDesc* -rtl8125_get_rxdesc(struct rtl8125_private *tp, struct RxDesc *RxDescBase, u32 const cur_rx) -{ - return (struct RxDesc*)((u8*)RxDescBase + (cur_rx * tp->RxDescLength)); -} - -static inline void -rtl8125_disable_hw_interrupt_v2(struct rtl8125_private *tp, - u32 message_id) -{ - RTL_W32(tp, IMR_V2_CLEAR_REG_8125, BIT(message_id)); -} - -static inline void -rtl8125_enable_hw_interrupt_v2(struct rtl8125_private *tp, u32 message_id) -{ - RTL_W32(tp, IMR_V2_SET_REG_8125, BIT(message_id)); -} - -void rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, u32 message_id, u8 timer_intmiti_val); -void rtl8125_set_rx_q_num(struct rtl8125_private *tp, unsigned int num_rx_queues); -void rtl8125_set_tx_q_num(struct rtl8125_private *tp, unsigned int num_tx_queues); -int rtl8125_set_real_num_queue(struct rtl8125_private *tp); -void rtl8125_hw_start(struct net_device *dev); -void rtl8125_hw_reset(struct net_device *dev); -void rtl8125_tx_clear(struct rtl8125_private *tp); -void rtl8125_rx_clear(struct rtl8125_private *tp); -int rtl8125_init_ring(struct net_device *dev); -void rtl8125_hw_set_rx_packet_filter(struct net_device *dev); - -#ifdef ENABLE_LIB_SUPPORT -void rtl8125_lib_reset_prepare(struct rtl8125_private *tp); -void rtl8125_lib_reset_complete(struct rtl8125_private *tp); -#else -static inline void rtl8125_lib_reset_prepare(struct rtl8125_private *tp) { } -static inline void rtl8125_lib_reset_complete(struct rtl8125_private *tp) { } -#endif - -#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) -#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) -#define HW_SUPPORT_D0_SPEED_UP(_M) ((_M)->HwSuppD0SpeedUpVer > 0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netdev_mc_count(dev) ((dev)->mc_count) -#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) -#define netdev_for_each_mc_addr(mclist, dev) \ - for (mclist = dev->mc_list; mclist; mclist = mclist->next) -#endif - -#endif /* __R8125_H */ diff --git a/r8125/src/r8125_dash.h b/r8125/src/r8125_dash.h deleted file mode 100644 index f86d4255a..000000000 --- a/r8125/src/r8125_dash.h +++ /dev/null @@ -1,261 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8125_DASH_H -#define _LINUX_R8125_DASH_H - -#include - -#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2 - -enum rtl_dash_cmd { - RTL_DASH_ARP_NS_OFFLOAD = 0, - RTL_DASH_SET_OOB_IPMAC, - RTL_DASH_NOTIFY_OOB, - - RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW, - RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE, - RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA, - RTL_DASH_OOB_REQ, - RTL_DASH_OOB_ACK, - RTL_DASH_DETACH_OOB_REQ, - RTL_DASH_DETACH_OOB_ACK, - - RTL_FW_SET_IPV4 = 0x10, - RTL_FW_GET_IPV4, - RTL_FW_SET_IPV6, - RTL_FW_GET_IPV6, - RTL_FW_SET_EXT_SNMP, - RTL_FW_GET_EXT_SNMP, - RTL_FW_SET_WAKEUP_PATTERN, - RTL_FW_GET_WAKEUP_PATTERN, - RTL_FW_DEL_WAKEUP_PATTERN, - - RTLT_DASH_COMMAND_INVALID, -}; - -struct rtl_dash_ip_mac { - struct sockaddr ifru_addr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; -}; - -struct rtl_dash_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -struct settings_ipv4 { - __u32 IPv4addr; - __u32 IPv4mask; - __u32 IPv4Gateway; -}; - -struct settings_ipv6 { - __u32 reserved; - __u32 prefixLen; - __u16 IPv6addr[8]; - __u16 IPv6Gateway[8]; -}; - -struct settings_ext_snmp { - __u16 index; - __u16 oid_get_len; - __u8 oid_for_get[24]; - __u8 reserved0[26]; - __u16 value_len; - __u8 value[256]; - __u8 supported; - __u8 reserved1[27]; -}; - -struct wakeup_pattern { - __u8 index; - __u8 valid; - __u8 start; - __u8 length; - __u8 name[36]; - __u8 mask[16]; - __u8 pattern[128]; - __u32 reserved[2]; -}; - -typedef struct _RX_DASH_FROM_FW_DESC { - u16 length; - u8 statusLowByte; - u8 statusHighByte; - u32 resv; - u64 BufferAddress; -} -RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC; - -typedef struct _TX_DASH_SEND_FW_DESC { - u16 length; - u8 statusLowByte; - u8 statusHighByte; - u32 resv; - u64 BufferAddress; -} -TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC; - -typedef struct _OSOOBHdr { - u32 len; - u8 type; - u8 flag; - u8 hostReqV; - u8 res; -} -OSOOBHdr, *POSOOBHdr; - -typedef struct _RX_DASH_BUFFER_TYPE_2 { - OSOOBHdr oobhdr; - u8 RxDataBuffer[0]; -} -RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2; - -#define ALIGN_8 (0x7) -#define ALIGN_16 (0xf) -#define ALIGN_32 (0x1f) -#define ALIGN_64 (0x3f) -#define ALIGN_256 (0xff) -#define ALIGN_4096 (0xfff) - -#define OCP_REG_CONFIG0 (0x10) -#define OCP_REG_CONFIG0_REV_F (0xB8) -#define OCP_REG_DASH_POLL (0x30) -#define OCP_REG_HOST_REQ (0x34) -#define OCP_REG_DASH_REQ (0x35) -#define OCP_REG_CR (0x36) -#define OCP_REG_DMEMSTA (0x38) -#define OCP_REG_GPHYAR (0x60) - - -#define OCP_REG_CONFIG0_DASHEN BIT_15 -#define OCP_REG_CONFIG0_OOBRESET BIT_14 -#define OCP_REG_CONFIG0_APRDY BIT_13 -#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12 -#define OCP_REG_CONFIG0_DRIVERRDY BIT_11 -#define OCP_REG_CONFIG0_OOB_WDT BIT_9 -#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 -#define OCP_REG_CONFIG0_TLSEN BIT_7 - -#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0 ) -#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1 ) -#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2 ) -#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3 ) - -#define RECV_FROM_FW_BUF_SIZE (1520) -#define SEND_TO_FW_BUF_SIZE (1520) - -#define RX_DASH_FROM_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7 - -#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3) -#define TXS_EXC BIT_4 -#define TXS_LNKF BIT_5 -#define TXS_OWC BIT_6 -#define TXS_TES BIT_7 -#define TXS_UNF BIT_9 -#define TXS_LGSEN BIT_11 -#define TXS_LS BIT_12 -#define TXS_FS BIT_13 -#define TXS_EOR BIT_14 -#define TXS_OWN BIT_15 - -#define TPPool_HRDY 0x20 - -#define HostReqReg (0xC0) -#define SystemMasterDescStartAddrLow (0xF0) -#define SystemMasterDescStartAddrHigh (0xF4) -#define SystemSlaveDescStartAddrLow (0xF8) -#define SystemSlaveDescStartAddrHigh (0xFC) - -//DASH Request Type -#define WSMANREG 0x01 -#define OSPUSHDATA 0x02 - -#define RXS_OWN BIT_15 -#define RXS_EOR BIT_14 -#define RXS_FS BIT_13 -#define RXS_LS BIT_12 - -#define ISRIMR_DP_DASH_OK BIT_15 -#define ISRIMR_DP_HOST_OK BIT_13 -#define ISRIMR_DP_REQSYS_OK BIT_11 - -#define ISRIMR_DASH_INTR_EN BIT_12 -#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15 - -#define ISRIMR_DASH_TYPE2_ROK BIT_0 -#define ISRIMR_DASH_TYPE2_RDU BIT_1 -#define ISRIMR_DASH_TYPE2_TOK BIT_2 -#define ISRIMR_DASH_TYPE2_TDU BIT_3 -#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4 -#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5 -#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6 - -#define CMAC_OOB_STOP 0x25 -#define CMAC_OOB_INIT 0x26 -#define CMAC_OOB_RESET 0x2a - -#define NO_BASE_ADDRESS 0x00000000 -#define RTL8168FP_OOBMAC_BASE 0xBAF70000 -#define RTL8168FP_CMAC_IOBASE 0xBAF20000 -#define RTL8168FP_KVM_BASE 0xBAF80400 -#define CMAC_SYNC_REG 0x20 -#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98 -#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F - -/* cmac write/read MMIO register */ -#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg))) - -int rtl8125_dash_ioctl(struct net_device *dev, struct ifreq *ifr); -void HandleDashInterrupt(struct net_device *dev); -int AllocateDashShareMemory(struct net_device *dev); -void FreeAllocatedDashShareMemory(struct net_device *dev); -void DashHwInit(struct net_device *dev); - - -#endif /* _LINUX_R8125_DASH_H */ diff --git a/r8125/src/r8125_n.c b/r8125/src/r8125_n.c deleted file mode 100644 index 608d8c2ee..000000000 --- a/r8125/src/r8125_n.c +++ /dev/null @@ -1,14487 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -/* - * This driver is modified from r8169.c in Linux kernel 2.6.18 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#include -#include -#endif -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) -#include -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) -#else -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) -#include -#endif - -#include -#include - -#include "r8125.h" -#include "rtl_eeprom.h" -#include "rtltool.h" - -#ifdef ENABLE_R8125_PROCFS -#include -#include -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -#define _R(NAME,MAC,RCR,MASK, JumFrameSz) \ - { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz } - -static const struct { - const char *name; - u8 mcfg; - u32 RCR_Cfg; - u32 RxConfigMask; /* Clears the bits supported by this chip */ - u32 jumbo_frame_sz; -} rtl_chip_info[] = { - _R("RTL8125A", - CFG_METHOD_2, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125A", - CFG_METHOD_3, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125B", - CFG_METHOD_4, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125B", - CFG_METHOD_5, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("Unknown", - CFG_METHOD_DEFAULT, - (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_1k) -}; -#undef _R - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -static struct pci_device_id rtl8125_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x3000), }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8125_pci_tbl); - -static int rx_copybreak = 0; -static int use_dac = 1; -static int timer_count = 0x2600; -static int timer_count_v2 = (0x2600 / 0x100); - -static struct { - u32 msg_enable; -} debug = { -1 }; - -static unsigned int speed_mode = SPEED_2500; -static unsigned int duplex_mode = DUPLEX_FULL; -static unsigned int autoneg_mode = AUTONEG_ENABLE; -static unsigned int advertising_mode = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full; -#ifdef CONFIG_ASPM -static int aspm = 1; -#else -static int aspm = 0; -#endif -#ifdef ENABLE_S5WOL -static int s5wol = 1; -#else -static int s5wol = 0; -#endif -#ifdef ENABLE_S5_KEEP_CURR_MAC -static int s5_keep_curr_mac = 1; -#else -static int s5_keep_curr_mac = 0; -#endif -#ifdef ENABLE_EEE -static int eee_enable = 1; -#else -static int eee_enable = 0; -#endif -#ifdef CONFIG_SOC_LAN -static ulong hwoptimize = HW_PATCH_SOC_LAN; -#else -static ulong hwoptimize = 0; -#endif -#ifdef ENABLE_S0_MAGIC_PACKET -static int s0_magic_packet = 1; -#else -static int s0_magic_packet = 0; -#endif -#ifdef ENABLE_TX_NO_CLOSE -static int tx_no_close_enable = 1; -#else -static int tx_no_close_enable = 0; -#endif -#ifdef ENABLE_PTP_MASTER_MODE -static int enable_ptp_master_mode = 1; -#else -static int enable_ptp_master_mode = 0; -#endif - -MODULE_AUTHOR("Realtek and the Linux r8125 crew "); -MODULE_DESCRIPTION("Realtek RTL8125 2.5Gigabit Ethernet driver"); - -module_param(speed_mode, uint, 0); -MODULE_PARM_DESC(speed_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(duplex_mode, uint, 0); -MODULE_PARM_DESC(duplex_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(autoneg_mode, uint, 0); -MODULE_PARM_DESC(autoneg_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(advertising_mode, uint, 0); -MODULE_PARM_DESC(advertising_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(aspm, int, 0); -MODULE_PARM_DESC(aspm, "Enable ASPM."); - -module_param(s5wol, int, 0); -MODULE_PARM_DESC(s5wol, "Enable Shutdown Wake On Lan."); - -module_param(s5_keep_curr_mac, int, 0); -MODULE_PARM_DESC(s5_keep_curr_mac, "Enable Shutdown Keep Current MAC Address."); - -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); - -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); - -module_param(timer_count, int, 0); -MODULE_PARM_DESC(timer_count, "Timer Interrupt Interval."); - -module_param(eee_enable, int, 0); -MODULE_PARM_DESC(eee_enable, "Enable Energy Efficient Ethernet."); - -module_param(hwoptimize, ulong, 0); -MODULE_PARM_DESC(hwoptimize, "Enable HW optimization function."); - -module_param(s0_magic_packet, int, 0); -MODULE_PARM_DESC(s0_magic_packet, "Enable S0 Magic Packet."); - -module_param(tx_no_close_enable, int, 0); -MODULE_PARM_DESC(tx_no_close_enable, "Enable TX No Close."); - -module_param(enable_ptp_master_mode, int, 0); -MODULE_PARM_DESC(enable_ptp_master_mode, "Enable PTP Master Mode."); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -#endif//LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - -MODULE_LICENSE("GPL"); - -MODULE_VERSION(RTL8125_VERSION); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8125_esd_timer(unsigned long __opaque); -#else -static void rtl8125_esd_timer(struct timer_list *t); -#endif -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8125_link_timer(unsigned long __opaque); -#else -static void rtl8125_link_timer(struct timer_list *t); -#endif -*/ - -static int rtl8125_open(struct net_device *dev); -static int rtl8125_start_xmit(struct sk_buff *skb, struct net_device *dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance); -#endif -void rtl8125_hw_config(struct net_device *dev); -static int rtl8125_close(struct net_device *dev); -static void rtl8125_set_rx_mode(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue); -#else -static void rtl8125_tx_timeout(struct net_device *dev); -#endif -static struct net_device_stats *rtl8125_get_stats(struct net_device *dev); -static int rtl8125_rx_interrupt(struct net_device *, struct rtl8125_private *, struct rtl8125_rx_ring *, napi_budget); -static int rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget); -static int rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, const int message_id, int budget); -static int rtl8125_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8125_down(struct net_device *dev); - -static int rtl8125_set_mac_address(struct net_device *dev, void *p); -static void rtl8125_rar_set(struct rtl8125_private *tp, uint8_t *addr); -static void rtl8125_desc_addr_fill(struct rtl8125_private *); -static void rtl8125_tx_desc_init(struct rtl8125_private *tp); -static void rtl8125_rx_desc_init(struct rtl8125_private *tp); - -static void rtl8125_phy_power_up(struct net_device *dev); -static void rtl8125_phy_power_down(struct net_device *dev); -static int rtl8125_set_speed(struct net_device *dev, u8 autoneg, u32 speed, u8 duplex, u32 adv); -static bool rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp); -static bool rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp); - -#ifdef CONFIG_R8125_NAPI -static int rtl8125_poll(napi_ptr napi, napi_budget budget); -#endif - -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) && \ - LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,00))) -void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, - u32 legacy_u32) -{ - bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); - dst[0] = legacy_u32; -} - -bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, - const unsigned long *src) -{ - bool retval = true; - - /* TODO: following test will soon always be true */ - if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); - - bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_fill(ext, 32); - bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - if (bitmap_intersects(ext, src, - __ETHTOOL_LINK_MODE_MASK_NBITS)) { - /* src mask goes beyond bit 31 */ - retval = false; - } - } - *legacy_u32 = src[0]; - return retval; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#ifndef LPA_1000FULL -#define LPA_1000FULL 0x0800 -#endif - -#ifndef LPA_1000HALF -#define LPA_1000HALF 0x0400 -#endif - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - random_ether_addr(dev->dev_addr); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#undef ethtool_ops -#define ethtool_ops _kc_ethtool_ops - -struct _kc_ethtool_ops { - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - int (*set_settings)(struct net_device *, struct ethtool_cmd *); - void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); - int (*get_regs_len)(struct net_device *); - void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); - void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); - int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); - u32 (*get_msglevel)(struct net_device *); - void (*set_msglevel)(struct net_device *, u32); - int (*nway_reset)(struct net_device *); - u32 (*get_link)(struct net_device *); - int (*get_eeprom_len)(struct net_device *); - int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); - int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); - void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); - int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); - void (*get_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - int (*set_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - u32 (*get_rx_csum)(struct net_device *); - int (*set_rx_csum)(struct net_device *, u32); - u32 (*get_tx_csum)(struct net_device *); - int (*set_tx_csum)(struct net_device *, u32); - u32 (*get_sg)(struct net_device *); - int (*set_sg)(struct net_device *, u32); - u32 (*get_tso)(struct net_device *); - int (*set_tso)(struct net_device *, u32); - int (*self_test_count)(struct net_device *); - void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); - void (*get_strings)(struct net_device *, u32 stringset, u8 *); - int (*phys_id)(struct net_device *, u32); - int (*get_stats_count)(struct net_device *); - void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, - u64 *); -} *ethtool_ops = NULL; - -#undef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) -#ifndef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev,ops) \ - ( (netdev)->ethtool_ops = (ops) ) -#endif //SET_ETHTOOL_OPS -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) -#ifndef netif_msg_init -#define netif_msg_init _kc_netif_msg_init -/* copied from linux kernel 2.6.20 include/linux/netdevice.h */ -static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) -{ - /* use default */ - if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) - return default_msg_enable_bits; - if (debug_value == 0) /* no output */ - return 0; - /* set low N bits */ - return (1 << debug_value) - 1; -} - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) -static inline void eth_copy_and_sum (struct sk_buff *dest, - const unsigned char *src, - int len, int base) -{ - memcpy (dest->data, src, len); -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 /include/linux/time.h */ -/* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L - -/* copied from linux kernel 2.6.20 /include/linux/jiffies.h */ -/* - * Change timeval to jiffies, trying to avoid the - * most obvious overflows.. - * - * And some not so obvious. - * - * Note that we don't want to return MAX_LONG, because - * for various timeout reasons we often end up having - * to wait "jiffies+1" in order to guarantee that we wait - * at _least_ "jiffies" - so "jiffies+1" had better still - * be positive. - */ -#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) - -/* - * Convert jiffies to milliseconds and back. - * - * Avoid unnecessary multiplications/divisions in the - * two most common HZ cases: - */ -static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) -{ -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (MSEC_PER_SEC / HZ) * j; -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); -#else - return (j * MSEC_PER_SEC) / HZ; -#endif -} - -static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) -{ - if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return m * (HZ / MSEC_PER_SEC); -#else - return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; -#endif -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -/* copied from linux kernel 2.6.12.6 /include/linux/pm.h */ -typedef int __bitwise pci_power_t; - -/* copied from linux kernel 2.6.12.6 /include/linux/pci.h */ -typedef u32 __bitwise pm_message_t; - -#define PCI_D0 ((pci_power_t __force) 0) -#define PCI_D1 ((pci_power_t __force) 1) -#define PCI_D2 ((pci_power_t __force) 2) -#define PCI_D3hot ((pci_power_t __force) 3) -#define PCI_D3cold ((pci_power_t __force) 4) -#define PCI_POWER_ERROR ((pci_power_t __force) -1) - -/* copied from linux kernel 2.6.12.6 /drivers/pci/pci.c */ -/** - * pci_choose_state - Choose the power state of a PCI device - * @dev: PCI device to be suspended - * @state: target sleep state for the whole system. This is the value - * that is passed to suspend() function. - * - * Returns PCI power state suitable for given device and given system - * message. - */ - -pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) -{ - if (!pci_find_capability(dev, PCI_CAP_ID_PM)) - return PCI_D0; - - switch (state) { - case 0: - return PCI_D0; - case 3: - return PCI_D3hot; - default: - printk("They asked me for state %d\n", state); -// BUG(); - } - return PCI_D0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -/** - * msleep_interruptible - sleep waiting for waitqueue interruptions - * @msecs: Time in milliseconds to sleep for - */ -#define msleep_interruptible _kc_msleep_interruptible -unsigned long _kc_msleep_interruptible(unsigned int msecs) -{ - unsigned long timeout = _kc_msecs_to_jiffies(msecs); - - while (timeout && !signal_pending(current)) { - set_current_state(TASK_INTERRUPTIBLE); - timeout = schedule_timeout(timeout); - } - return _kc_jiffies_to_msecs(timeout); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 include/linux/sched.h */ -#ifndef __sched -#define __sched __attribute__((__section__(".sched.text"))) -#endif - -/* copied from linux kernel 2.6.20 kernel/timer.c */ -signed long __sched schedule_timeout_uninterruptible(signed long timeout) -{ - __set_current_state(TASK_UNINTERRUPTIBLE); - return schedule_timeout(timeout); -} - -/* copied from linux kernel 2.6.20 include/linux/mii.h */ -#undef if_mii -#define if_mii _kc_if_mii -static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) -{ - return (struct mii_ioctl_data *) &rq->ifr_ifru; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - -struct rtl8125_counters { - u64 tx_packets; - u64 rx_packets; - u64 tx_errors; - u32 rx_errors; - u16 rx_missed; - u16 align_errors; - u32 tx_one_collision; - u32 tx_multi_collision; - u64 rx_unicast; - u64 rx_broadcast; - u32 rx_multicast; - u16 tx_aborted; - u16 tx_underun; -}; - -#ifdef ENABLE_R8125_PROCFS -/**************************************************************************** -* -----------------------------PROCFS STUFF------------------------- -***************************************************************************** -*/ - -static struct proc_dir_entry *rtl8125_proc; -static int proc_init_num = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -static int proc_get_driver_variable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump Driver Variable\n"); - - spin_lock_irqsave(&tp->lock, flags); - seq_puts(m, "Variable\tValue\n----------\t-----\n"); - seq_printf(m, "MODULENAME\t%s\n", MODULENAME); - seq_printf(m, "driver version\t%s\n", RTL8125_VERSION); - seq_printf(m, "mcfg\t%d\n", tp->mcfg); - seq_printf(m, "chipset\t%d\n", tp->chipset); - seq_printf(m, "chipset_name\t%s\n", rtl_chip_info[tp->chipset].name); - seq_printf(m, "mtu\t%d\n", dev->mtu); - seq_printf(m, "NUM_RX_DESC\t0x%x\n", NUM_RX_DESC); - seq_printf(m, "cur_rx0\t0x%x\n", tp->rx_ring[0].cur_rx); - seq_printf(m, "dirty_rx0\t0x%x\n", tp->rx_ring[0].dirty_rx); - seq_printf(m, "cur_rx1\t0x%x\n", tp->rx_ring[1].cur_rx); - seq_printf(m, "dirty_rx1\t0x%x\n", tp->rx_ring[1].dirty_rx); - seq_printf(m, "cur_rx2\t0x%x\n", tp->rx_ring[2].cur_rx); - seq_printf(m, "dirty_rx2\t0x%x\n", tp->rx_ring[2].dirty_rx); - seq_printf(m, "cur_rx3\t0x%x\n", tp->rx_ring[3].cur_rx); - seq_printf(m, "dirty_rx3\t0x%x\n", tp->rx_ring[3].dirty_rx); - seq_printf(m, "NUM_TX_DESC\t0x%x\n", NUM_TX_DESC); - seq_printf(m, "cur_tx0\t0x%x\n", tp->tx_ring[0].cur_tx); - seq_printf(m, "dirty_tx0\t0x%x\n", tp->tx_ring[0].dirty_tx); - seq_printf(m, "cur_tx1\t0x%x\n", tp->tx_ring[1].cur_tx); - seq_printf(m, "dirty_tx1\t0x%x\n", tp->tx_ring[1].dirty_tx); - seq_printf(m, "rx_buf_sz\t0x%x\n", tp->rx_buf_sz); - seq_printf(m, "esd_flag\t0x%x\n", tp->esd_flag); - seq_printf(m, "pci_cfg_is_read\t0x%x\n", tp->pci_cfg_is_read); - seq_printf(m, "rtl8125_rx_config\t0x%x\n", tp->rtl8125_rx_config); - seq_printf(m, "cp_cmd\t0x%x\n", tp->cp_cmd); - seq_printf(m, "intr_mask\t0x%x\n", tp->intr_mask); - seq_printf(m, "timer_intr_mask\t0x%x\n", tp->timer_intr_mask); - seq_printf(m, "wol_enabled\t0x%x\n", tp->wol_enabled); - seq_printf(m, "wol_opts\t0x%x\n", tp->wol_opts); - seq_printf(m, "efuse_ver\t0x%x\n", tp->efuse_ver); - seq_printf(m, "eeprom_type\t0x%x\n", tp->eeprom_type); - seq_printf(m, "autoneg\t0x%x\n", tp->autoneg); - seq_printf(m, "duplex\t0x%x\n", tp->duplex); - seq_printf(m, "speed\t%d\n", tp->speed); - seq_printf(m, "advertising\t0x%x\n", tp->advertising); - seq_printf(m, "eeprom_len\t0x%x\n", tp->eeprom_len); - seq_printf(m, "cur_page\t0x%x\n", tp->cur_page); - seq_printf(m, "bios_setting\t0x%x\n", tp->bios_setting); - seq_printf(m, "features\t0x%x\n", tp->features); - seq_printf(m, "org_pci_offset_99\t0x%x\n", tp->org_pci_offset_99); - seq_printf(m, "org_pci_offset_180\t0x%x\n", tp->org_pci_offset_180); - seq_printf(m, "issue_offset_99_event\t0x%x\n", tp->issue_offset_99_event); - seq_printf(m, "org_pci_offset_80\t0x%x\n", tp->org_pci_offset_80); - seq_printf(m, "org_pci_offset_81\t0x%x\n", tp->org_pci_offset_81); - seq_printf(m, "use_timer_interrrupt\t0x%x\n", tp->use_timer_interrrupt); - seq_printf(m, "HwIcVerUnknown\t0x%x\n", tp->HwIcVerUnknown); - seq_printf(m, "NotWrRamCodeToMicroP\t0x%x\n", tp->NotWrRamCodeToMicroP); - seq_printf(m, "NotWrMcuPatchCode\t0x%x\n", tp->NotWrMcuPatchCode); - seq_printf(m, "HwHasWrRamCodeToMicroP\t0x%x\n", tp->HwHasWrRamCodeToMicroP); - seq_printf(m, "sw_ram_code_ver\t0x%x\n", tp->sw_ram_code_ver); - seq_printf(m, "hw_ram_code_ver\t0x%x\n", tp->hw_ram_code_ver); - seq_printf(m, "rtk_enable_diag\t0x%x\n", tp->rtk_enable_diag); - seq_printf(m, "ShortPacketSwChecksum\t0x%x\n", tp->ShortPacketSwChecksum); - seq_printf(m, "UseSwPaddingShortPkt\t0x%x\n", tp->UseSwPaddingShortPkt); - seq_printf(m, "RequireAdcBiasPatch\t0x%x\n", tp->RequireAdcBiasPatch); - seq_printf(m, "AdcBiasPatchIoffset\t0x%x\n", tp->AdcBiasPatchIoffset); - seq_printf(m, "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n", tp->RequireAdjustUpsTxLinkPulseTiming); - seq_printf(m, "SwrCnt1msIni\t0x%x\n", tp->SwrCnt1msIni); - seq_printf(m, "HwSuppNowIsOobVer\t0x%x\n", tp->HwSuppNowIsOobVer); - seq_printf(m, "HwFiberModeVer\t0x%x\n", tp->HwFiberModeVer); - seq_printf(m, "HwFiberStat\t0x%x\n", tp->HwFiberStat); - seq_printf(m, "HwSwitchMdiToFiber\t0x%x\n", tp->HwSwitchMdiToFiber); - seq_printf(m, "NicCustLedValue\t0x%x\n", tp->NicCustLedValue); - seq_printf(m, "RequiredSecLanDonglePatch\t0x%x\n", tp->RequiredSecLanDonglePatch); - seq_printf(m, "HwSuppDashVer\t0x%x\n", tp->HwSuppDashVer); - seq_printf(m, "DASH\t0x%x\n", tp->DASH); - seq_printf(m, "dash_printer_enabled\t0x%x\n", tp->dash_printer_enabled); - seq_printf(m, "HwSuppKCPOffloadVer\t0x%x\n", tp->HwSuppKCPOffloadVer); - seq_printf(m, "speed_mode\t0x%x\n", speed_mode); - seq_printf(m, "duplex_mode\t0x%x\n", duplex_mode); - seq_printf(m, "autoneg_mode\t0x%x\n", autoneg_mode); - seq_printf(m, "advertising_mode\t0x%x\n", advertising_mode); - seq_printf(m, "aspm\t0x%x\n", aspm); - seq_printf(m, "s5wol\t0x%x\n", s5wol); - seq_printf(m, "s5_keep_curr_mac\t0x%x\n", s5_keep_curr_mac); - seq_printf(m, "eee_enable\t0x%x\n", tp->eee_enabled); - seq_printf(m, "hwoptimize\t0x%lx\n", hwoptimize); - seq_printf(m, "proc_init_num\t0x%x\n", proc_init_num); - seq_printf(m, "s0_magic_packet\t0x%x\n", s0_magic_packet); - seq_printf(m, "HwSuppMagicPktVer\t0x%x\n", tp->HwSuppMagicPktVer); - seq_printf(m, "HwSuppLinkChgWakeUpVer\t0x%x\n", tp->HwSuppLinkChgWakeUpVer); - seq_printf(m, "HwSuppD0SpeedUpVer\t0x%x\n", tp->HwSuppD0SpeedUpVer); - seq_printf(m, "D0SpeedUpSpeed\t0x%x\n", tp->D0SpeedUpSpeed); - seq_printf(m, "HwSuppCheckPhyDisableModeVer\t0x%x\n", tp->HwSuppCheckPhyDisableModeVer); - seq_printf(m, "HwPkgDet\t0x%x\n", tp->HwPkgDet); - seq_printf(m, "HwSuppGigaForceMode\t0x%x\n", tp->HwSuppGigaForceMode); - seq_printf(m, "HwSuppTxNoCloseVer\t0x%x\n", tp->HwSuppTxNoCloseVer); - seq_printf(m, "EnableTxNoClose\t0x%x\n", tp->EnableTxNoClose); - seq_printf(m, "NextHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].NextHwDesCloPtr); - seq_printf(m, "BeginHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].BeginHwDesCloPtr); - seq_printf(m, "NextHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].NextHwDesCloPtr); - seq_printf(m, "BeginHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].BeginHwDesCloPtr); - seq_printf(m, "InitRxDescType\t0x%x\n", tp->InitRxDescType); - seq_printf(m, "RxDescLength\t0x%x\n", tp->RxDescLength); - seq_printf(m, "num_rx_rings\t0x%x\n", tp->num_rx_rings); - seq_printf(m, "num_tx_rings\t0x%x\n", tp->num_tx_rings); - seq_printf(m, "tot_rx_rings\t0x%x\n", rtl8125_tot_rx_rings(tp)); - seq_printf(m, "tot_tx_rings\t0x%x\n", rtl8125_tot_tx_rings(tp)); - seq_printf(m, "EnableRss\t0x%x\n", tp->EnableRss); - seq_printf(m, "EnablePtp\t0x%x\n", tp->EnablePtp); - seq_printf(m, "ptp_master_mode\t0x%x\n", tp->ptp_master_mode); - seq_printf(m, "min_irq_nvecs\t0x%x\n", tp->min_irq_nvecs); - seq_printf(m, "irq_nvecs\t0x%x\n", tp->irq_nvecs); -#ifdef ENABLE_PTP_SUPPORT - seq_printf(m, "tx_hwtstamp_timeouts\t0x%x\n", tp->tx_hwtstamp_timeouts); - seq_printf(m, "tx_hwtstamp_skipped\t0x%x\n", tp->tx_hwtstamp_skipped); -#endif - seq_printf(m, "random_mac\t0x%x\n", tp->random_mac); - seq_printf(m, "org_mac_addr\t%pM\n", tp->org_mac_addr); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - seq_printf(m, "perm_addr\t%pM\n", dev->perm_addr); -#endif - seq_printf(m, "dev_addr\t%pM\n", dev->dev_addr); - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_tally_counter(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - - seq_puts(m, "\nDump Tally Counter\n"); - - //ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - seq_puts(m, "\nDump Tally Counter Fail\n"); - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_puts(m, "Statistics\tValue\n----------\t-----\n"); - seq_printf(m, "tx_packets\t%lld\n", le64_to_cpu(counters->tx_packets)); - seq_printf(m, "rx_packets\t%lld\n", le64_to_cpu(counters->rx_packets)); - seq_printf(m, "tx_errors\t%lld\n", le64_to_cpu(counters->tx_errors)); - seq_printf(m, "rx_missed\t%lld\n", le64_to_cpu(counters->rx_missed)); - seq_printf(m, "align_errors\t%lld\n", le64_to_cpu(counters->align_errors)); - seq_printf(m, "tx_one_collision\t%lld\n", le64_to_cpu(counters->tx_one_collision)); - seq_printf(m, "tx_multi_collision\t%lld\n", le64_to_cpu(counters->tx_multi_collision)); - seq_printf(m, "rx_unicast\t%lld\n", le64_to_cpu(counters->rx_unicast)); - seq_printf(m, "rx_broadcast\t%lld\n", le64_to_cpu(counters->rx_broadcast)); - seq_printf(m, "rx_multicast\t%lld\n", le64_to_cpu(counters->rx_multicast)); - seq_printf(m, "tx_aborted\t%lld\n", le64_to_cpu(counters->tx_aborted)); - seq_printf(m, "tx_underun\t%lld\n", le64_to_cpu(counters->tx_underun)); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - seq_puts(m, "\nDump MAC Registers\n"); - seq_puts(m, "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - seq_printf(m, "%02x ", byte_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pcie_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump PCIE PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_ephy_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_eth_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump Ethernet PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - seq_puts(m, "\n####################page 0##################\n "); - rtl8125_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_mdio_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_extended_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump Extended Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); - seq_printf(m, "%08x ", dword_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pci_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump PCI Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%03x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "%08x ", dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} -#else - -static int proc_get_driver_variable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Driver Driver\n"); - - spin_lock_irqsave(&tp->lock, flags); - len += snprintf(page + len, count - len, - "Variable\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "MODULENAME\t%s\n" - "driver version\t%s\n" - "mcfg\t%d\n" - "chipset\t%d\n" - "chipset_name\t%s\n" - "mtu\t%d\n" - "NUM_RX_DESC\t0x%x\n" - "cur_rx0\t0x%x\n" - "dirty_rx0\t0x%x\n" - "cur_rx1\t0x%x\n" - "dirty_rx1\t0x%x\n" - "cur_rx2\t0x%x\n" - "dirty_rx2\t0x%x\n" - "cur_rx3\t0x%x\n" - "dirty_rx3\t0x%x\n" - "NUM_TX_DESC\t0x%x\n" - "cur_tx0\t0x%x\n" - "dirty_tx0\t0x%x\n" - "cur_tx1\t0x%x\n" - "dirty_tx1\t0x%x\n" - "rx_buf_sz\t0x%x\n" - "esd_flag\t0x%x\n" - "pci_cfg_is_read\t0x%x\n" - "rtl8125_rx_config\t0x%x\n" - "cp_cmd\t0x%x\n" - "intr_mask\t0x%x\n" - "timer_intr_mask\t0x%x\n" - "wol_enabled\t0x%x\n" - "wol_opts\t0x%x\n" - "efuse_ver\t0x%x\n" - "eeprom_type\t0x%x\n" - "autoneg\t0x%x\n" - "duplex\t0x%x\n" - "speed\t%d\n" - "advertising\t0x%x\n" - "eeprom_len\t0x%x\n" - "cur_page\t0x%x\n" - "bios_setting\t0x%x\n" - "features\t0x%x\n" - "org_pci_offset_99\t0x%x\n" - "org_pci_offset_180\t0x%x\n" - "issue_offset_99_event\t0x%x\n" - "org_pci_offset_80\t0x%x\n" - "org_pci_offset_81\t0x%x\n" - "use_timer_interrrupt\t0x%x\n" - "HwIcVerUnknown\t0x%x\n" - "NotWrRamCodeToMicroP\t0x%x\n" - "NotWrMcuPatchCode\t0x%x\n" - "HwHasWrRamCodeToMicroP\t0x%x\n" - "sw_ram_code_ver\t0x%x\n" - "hw_ram_code_ver\t0x%x\n" - "rtk_enable_diag\t0x%x\n" - "ShortPacketSwChecksum\t0x%x\n" - "UseSwPaddingShortPkt\t0x%x\n" - "RequireAdcBiasPatch\t0x%x\n" - "AdcBiasPatchIoffset\t0x%x\n" - "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n" - "SwrCnt1msIni\t0x%x\n" - "HwSuppNowIsOobVer\t0x%x\n" - "HwFiberModeVer\t0x%x\n" - "HwFiberStat\t0x%x\n" - "HwSwitchMdiToFiber\t0x%x\n" - "NicCustLedValue\t0x%x\n" - "RequiredSecLanDonglePatch\t0x%x\n" - "HwSuppDashVer\t0x%x\n" - "DASH\t0x%x\n" - "dash_printer_enabled\t0x%x\n" - "HwSuppKCPOffloadVer\t0x%x\n" - "speed_mode\t0x%x\n" - "duplex_mode\t0x%x\n" - "autoneg_mode\t0x%x\n" - "advertising_mode\t0x%x\n" - "aspm\t0x%x\n" - "s5wol\t0x%x\n" - "s5_keep_curr_mac\t0x%x\n" - "eee_enable\t0x%x\n" - "hwoptimize\t0x%lx\n" - "proc_init_num\t0x%x\n" - "s0_magic_packet\t0x%x\n" - "HwSuppMagicPktVer\t0x%x\n" - "HwSuppLinkChgWakeUpVer\t0x%x\n" - "HwSuppD0SpeedUpVer\t0x%x\n" - "D0SpeedUpSpeed\t0x%x\n" - "HwSuppCheckPhyDisableModeVer\t0x%x\n" - "HwPkgDet\t0x%x\n" - "HwSuppGigaForceMode\t0x%x\n" - "HwSuppTxNoCloseVer\t0x%x\n" - "EnableTxNoClose\t0x%x\n" - "NextHwDesCloPtr0\t0x%x\n" - "BeginHwDesCloPtr0\t0x%x\n" - "NextHwDesCloPtr1\t0x%x\n" - "BeginHwDesCloPtr1\t0x%x\n" - "InitRxDescType\t0x%x\n" - "RxDescLength\t0x%x\n" - "num_rx_rings\t0x%x\n" - "num_tx_rings\t0x%x\n" - "tot_rx_rings\t0x%x\n" - "tot_tx_rings\t0x%x\n" - "EnableRss\t0x%x\n" - "EnablePtp\t0x%x\n" - "ptp_master_mode\t0x%x\n" - "min_irq_nvecs\t0x%x\n" - "irq_nvecs\t0x%x\n" -#ifdef ENABLE_PTP_SUPPORT - "tx_hwtstamp_timeouts\t0x%x\n" - "tx_hwtstamp_skipped\t0x%x\n" -#endif - "random_mac\t0x%x\n" - "org_mac_addr\t%pM\n" -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - "perm_addr\t%pM\n" -#endif - "dev_addr\t%pM\n", - MODULENAME, - RTL8125_VERSION, - tp->mcfg, - tp->chipset, - rtl_chip_info[tp->chipset].name, - dev->mtu, - NUM_RX_DESC, - tp->rx_ring[0].cur_rx, - tp->rx_ring[0].dirty_rx, - tp->rx_ring[1].cur_rx, - tp->rx_ring[1].dirty_rx, - tp->rx_ring[2].cur_rx, - tp->rx_ring[2].dirty_rx, - tp->rx_ring[3].cur_rx, - tp->rx_ring[3].dirty_rx, - NUM_TX_DESC, - tp->tx_ring[0].cur_tx, - tp->tx_ring[0].dirty_tx, - tp->tx_ring[1].cur_tx, - tp->tx_ring[1].dirty_tx, - tp->rx_buf_sz, - tp->esd_flag, - tp->pci_cfg_is_read, - tp->rtl8125_rx_config, - tp->cp_cmd, - tp->intr_mask, - tp->timer_intr_mask, - tp->wol_enabled, - tp->wol_opts, - tp->efuse_ver, - tp->eeprom_type, - tp->autoneg, - tp->duplex, - tp->speed, - tp->advertising, - tp->eeprom_len, - tp->cur_page, - tp->bios_setting, - tp->features, - tp->org_pci_offset_99, - tp->org_pci_offset_180, - tp->issue_offset_99_event, - tp->org_pci_offset_80, - tp->org_pci_offset_81, - tp->use_timer_interrrupt, - tp->HwIcVerUnknown, - tp->NotWrRamCodeToMicroP, - tp->NotWrMcuPatchCode, - tp->HwHasWrRamCodeToMicroP, - tp->sw_ram_code_ver, - tp->hw_ram_code_ver, - tp->rtk_enable_diag, - tp->ShortPacketSwChecksum, - tp->UseSwPaddingShortPkt, - tp->RequireAdcBiasPatch, - tp->AdcBiasPatchIoffset, - tp->RequireAdjustUpsTxLinkPulseTiming, - tp->SwrCnt1msIni, - tp->HwSuppNowIsOobVer, - tp->HwFiberModeVer, - tp->HwFiberStat, - tp->HwSwitchMdiToFiber, - tp->NicCustLedValue, - tp->RequiredSecLanDonglePatch, - tp->HwSuppDashVer, - tp->DASH, - tp->dash_printer_enabled, - tp->HwSuppKCPOffloadVer, - speed_mode, - duplex_mode, - autoneg_mode, - advertising_mode, - aspm, - s5wol, - s5_keep_curr_mac, - tp->eee_enabled, - hwoptimize, - proc_init_num, - s0_magic_packet, - tp->HwSuppMagicPktVer, - tp->HwSuppLinkChgWakeUpVer, - tp->HwSuppD0SpeedUpVer, - tp->D0SpeedUpSpeed, - tp->HwSuppCheckPhyDisableModeVer, - tp->HwPkgDet, - tp->HwSuppGigaForceMode, - tp->HwSuppTxNoCloseVer, - tp->EnableTxNoClose, - tp->tx_ring[0].NextHwDesCloPtr, - tp->tx_ring[0].BeginHwDesCloPtr, - tp->tx_ring[1].NextHwDesCloPtr, - tp->tx_ring[1].BeginHwDesCloPtr, - tp->InitRxDescType, - tp->RxDescLength, - tp->num_rx_rings, - tp->num_tx_rings, - tp->tot_rx_rings, - tp->tot_tx_rings, - tp->EnableRss, - tp->EnablePtp, - tp->ptp_master_mode, - tp->min_irq_nvecs, - tp->irq_nvecs, -#ifdef ENABLE_PTP_SUPPORT - tp->tx_hwtstamp_timeouts, - tp->tx_hwtstamp_skipped, -#endif - tp->random_mac, - tp->org_mac_addr, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - dev->perm_addr, -#endif - dev->dev_addr - ); - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_tally_counter(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Tally Counter\n"); - - //ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - len += snprintf(page + len, count - len, - "\nDump Tally Counter Fail\n"); - goto out; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, - "Statistics\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "tx_packets\t%lld\n" - "rx_packets\t%lld\n" - "tx_errors\t%lld\n" - "rx_missed\t%lld\n" - "align_errors\t%lld\n" - "tx_one_collision\t%lld\n" - "tx_multi_collision\t%lld\n" - "rx_unicast\t%lld\n" - "rx_broadcast\t%lld\n" - "rx_multicast\t%lld\n" - "tx_aborted\t%lld\n" - "tx_underun\t%lld\n", - le64_to_cpu(counters->tx_packets), - le64_to_cpu(counters->rx_packets), - le64_to_cpu(counters->tx_errors), - le64_to_cpu(counters->rx_missed), - le64_to_cpu(counters->align_errors), - le64_to_cpu(counters->tx_one_collision), - le64_to_cpu(counters->tx_multi_collision), - le64_to_cpu(counters->rx_unicast), - le64_to_cpu(counters->rx_broadcast), - le64_to_cpu(counters->rx_multicast), - le64_to_cpu(counters->tx_aborted), - le64_to_cpu(counters->tx_underun) - ); - - len += snprintf(page + len, count - len, "\n"); -out: - *eof = 1; - return len; -} - -static int proc_get_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump MAC Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - len += snprintf(page + len, count - len, - "%02x ", - byte_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_pcie_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCIE PHY\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_ephy_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_eth_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Ethernet PHY\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - len += snprintf(page + len, count - len, - "\n####################page 0##################\n"); - rtl8125_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_mdio_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_extended_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Extended Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); -out: - *eof = 1; - return len; -} - -static int proc_get_pci_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCI Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%03x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} -#endif -static void rtl8125_proc_module_init(void) -{ - //create /proc/net/r8125 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - rtl8125_proc = proc_mkdir(MODULENAME, init_net.proc_net); -#else - rtl8125_proc = proc_mkdir(MODULENAME, proc_net); -#endif - if (!rtl8125_proc) - dprintk("cannot create %s proc entry \n", MODULENAME); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -/* - * seq_file wrappers for procfile show routines. - */ -static int rtl8125_proc_open(struct inode *inode, struct file *file) -{ - struct net_device *dev = proc_get_parent_data(inode); - int (*show)(struct seq_file *, void *) = PDE_DATA(inode); - - return single_open(file, show, dev); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static const struct proc_ops rtl8125_proc_fops = { - .proc_open = rtl8125_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, -}; -#else -static const struct file_operations rtl8125_proc_fops = { - .open = rtl8125_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -#endif - -/* - * Table of proc files we need to create. - */ -struct rtl8125_proc_file { - char name[12]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - int (*show)(struct seq_file *, void *); -#else - int (*show)(char *, char **, off_t, int, int *, void *); -#endif -}; - -static const struct rtl8125_proc_file rtl8125_proc_files[] = { - { "driver_var", &proc_get_driver_variable }, - { "tally", &proc_get_tally_counter }, - { "registers", &proc_get_registers }, - { "pcie_phy", &proc_get_pcie_phy }, - { "eth_phy", &proc_get_eth_phy }, - { "ext_regs", &proc_get_extended_registers }, - { "pci_regs", &proc_get_pci_registers }, - { "", NULL } -}; - -static void rtl8125_proc_init(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - const struct rtl8125_proc_file *f; - struct proc_dir_entry *dir; - - if (rtl8125_proc && !tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - dir = proc_mkdir_data(dev->name, 0, rtl8125_proc, dev); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8125_proc_files; f->name[0]; f++) { - if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, - &rtl8125_proc_fops, f->show)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#else - dir = proc_mkdir(dev->name, rtl8125_proc); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8125_proc_files; f->name[0]; f++) { - if (!create_proc_read_entry(f->name, S_IFREG | S_IRUGO, - dir, f->show, dev)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#endif - } -} - -static void rtl8125_proc_remove(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(dev->name, rtl8125_proc); - proc_init_num--; - -#else - const struct rtl8125_proc_file *f; - struct rtl8125_private *tp = netdev_priv(dev); - - for (f = rtl8125_proc_files; f->name[0]; f++) - remove_proc_entry(f->name, tp->proc_dir); - - remove_proc_entry(dev->name, rtl8125_proc); - proc_init_num--; -#endif - tp->proc_dir = NULL; - } -} - -#endif //ENABLE_R8125_PROCFS - -static inline u16 map_phy_ocp_addr(u16 PageNum, u8 RegNum) -{ - u16 OcpPageNum = 0; - u8 OcpRegNum = 0; - u16 OcpPhyAddress = 0; - - if ( PageNum == 0 ) { - OcpPageNum = OCP_STD_PHY_BASE_PAGE + ( RegNum / 8 ); - OcpRegNum = 0x10 + ( RegNum % 8 ); - } else { - OcpPageNum = PageNum; - OcpRegNum = RegNum; - } - - OcpPageNum <<= 4; - - if ( OcpRegNum < 16 ) { - OcpPhyAddress = 0; - } else { - OcpRegNum -= 16; - OcpRegNum <<= 1; - - OcpPhyAddress = OcpPageNum + OcpRegNum; - } - - - return OcpPhyAddress; -} - -static void mdio_real_direct_write_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - u32 data32; - int i; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 |= OCPR_Write | value; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (!(RTL_R32(tp, PHYOCP) & OCPR_Flag)) - break; - } -} - -static void mdio_direct_write_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -/* -static void rtl8125_mdio_write_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_direct_write_phy_ocp(tp, ocp_addr, value); -} -*/ - -static void rtl8125_mdio_real_write_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_real_direct_write_phy_ocp(tp, ocp_addr, value); -} - -static void mdio_real_write(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - if (RegAddr == 0x1F) { - tp->cur_page = value; - return; - } - rtl8125_mdio_real_write_phy_ocp(tp, tp->cur_page, RegAddr, value); -} - -void rtl8125_mdio_write(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_write(tp, RegAddr, value); -} - -void rtl8125_mdio_prot_write(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_write(tp, RegAddr, value); -} - -void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -static u32 mdio_real_direct_read_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr) -{ - u32 data32; - int i, value = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (RTL_R32(tp, PHYOCP) & OCPR_Flag) - break; - } - value = RTL_R32(tp, PHYOCP) & OCPDR_Data_Mask; - - return value; -} - -static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -/* -static u32 rtl8125_mdio_read_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_direct_read_phy_ocp(tp, ocp_addr); -} -*/ - -static u32 rtl8125_mdio_real_read_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_real_direct_read_phy_ocp(tp, ocp_addr); -} - -static u32 mdio_real_read(struct rtl8125_private *tp, - u32 RegAddr) -{ - return rtl8125_mdio_real_read_phy_ocp(tp, tp->cur_page, RegAddr); -} - -u32 rtl8125_mdio_read(struct rtl8125_private *tp, - u32 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, - u32 RegAddr) -{ - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, - u32 RegAddr) -{ - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -static void ClearAndSetEthPhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - PhyRegValue = rtl8125_mdio_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8125_mdio_write(tp, addr, PhyRegValue); -} - -void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - mask, - 0 - ); -} - -void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - 0, - mask - ); -} - -static void ClearAndSetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - PhyRegValue = mdio_direct_read_phy_ocp(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - mdio_direct_write_phy_ocp(tp, addr, PhyRegValue); -} - -void ClearEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) -{ - ClearAndSetEthPhyOcpBit(tp, - addr, - mask, - 0 - ); -} - -void SetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) -{ - ClearAndSetEthPhyOcpBit(tp, - addr, - 0, - mask - ); -} - -void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value) -{ - u32 data32; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 += value; - data32 |= OCPR_Write; - - RTL_W32(tp, MACOCP, data32); -} - -u16 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr) -{ - u32 data32; - u16 data16 = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, MACOCP, data32); - data16 = (u16)RTL_R32(tp, MACOCP); - - return data16; -} - -static void -ClearAndSetMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 clearmask, - u16 setmask -) -{ - u16 PhyRegValue; - - PhyRegValue = rtl8125_mac_ocp_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8125_mac_ocp_write(tp, addr, PhyRegValue); -} - -static void -ClearMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 mask -) -{ - ClearAndSetMcuAccessRegBit(tp, - addr, - mask, - 0 - ); -} - -static void -SetMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 mask -) -{ - ClearAndSetMcuAccessRegBit(tp, - addr, - 0, - mask - ); -} - -u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, const u32 base_address) -{ - return rtl8125_eri_read_with_oob_base_address(tp, addr, len, ERIAR_OOB, base_address); -} - -u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len) -{ - u32 value = 0; - - if (HW_DASH_SUPPORT_TYPE_2(tp)) - value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, RTL8168FP_OOBMAC_BASE); - - return value; -} - -u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, const u32 base_address) -{ - return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, ERIAR_OOB, base_address); -} - -void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 value) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp)) - rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, RTL8168FP_OOBMAC_BASE); -} - -void rtl8125_oob_mutex_lock(struct rtl8125_private *tp) -{ - u8 reg_16, reg_a0; - u32 wait_cnt_0, wait_Cnt_1; - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); - wait_cnt_0 = 0; - while(reg_16) { - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - if (reg_a0) { - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - wait_Cnt_1 = 0; - while(reg_a0) { - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - - wait_Cnt_1++; - - if (wait_Cnt_1 > 2000) - break; - }; - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - - } - reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); - - wait_cnt_0++; - - if (wait_cnt_0 > 2000) - break; - }; -} - -void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp) -{ - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8125_ocp_write(tp, ocp_reg_mutex_prio, 1, BIT_0); - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); -} - -void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd) -{ - rtl8125_eri_write(tp, 0xE8, 1, cmd, ERIAR_ExGMAC); - - rtl8125_ocp_write(tp, 0x30, 1, 0x01); -} - -static int rtl8125_check_dash(struct rtl8125_private *tp) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - if (rtl8125_ocp_read(tp, 0x128, 1) & BIT_0) - return 1; - } - - return 0; -} - -void rtl8125_dash2_disable_tx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - u16 WaitCnt; - u8 TmpUchar; - - //Disable oob Tx - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) & ~( BIT_0 )); - WaitCnt = 0; - - //wait oob tx disable - do { - TmpUchar = RTL_CMAC_R8(tp, CMAC_IBISR0); - - if ( TmpUchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE ) { - break; - } - - udelay( 50 ); - WaitCnt++; - } while(WaitCnt < 2000); - - //Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0) | ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE); - } -} - -void rtl8125_dash2_enable_tx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) | BIT_0); - } -} - -void rtl8125_dash2_disable_rx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) & ~( BIT_0 )); - } -} - -void rtl8125_dash2_enable_rx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) | BIT_0); - } -} - -static void rtl8125_dash2_disable_txrx(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8125_dash2_disable_tx( tp ); - rtl8125_dash2_disable_rx( tp ); - } -} - -static void rtl8125_driver_start(struct rtl8125_private *tp) -{ - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - int timeout; - u32 tmp_value; - - rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_START); - tmp_value = rtl8125_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8125_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (rtl8125_ocp_read(tp, 0x124, 1) & BIT_0) - break; - } - } -} - -static void rtl8125_driver_stop(struct rtl8125_private *tp) -{ - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - struct net_device *dev = tp->dev; - int timeout; - u32 tmp_value; - - rtl8125_dash2_disable_txrx(dev); - - rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_STOP); - tmp_value = rtl8125_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8125_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (!(rtl8125_ocp_read(tp, 0x124, 1) & BIT_0)) - break; - } - } -} - -void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value) -{ - int i; - - RTL_W32(tp, EPHYAR, - EPHYAR_Write | - (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift | - (value & EPHYAR_Data_Mask)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed EPHY write */ - if (!(RTL_R32(tp, EPHYAR) & EPHYAR_Flag)) - break; - } - - udelay(20); -} - -u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr) -{ - int i; - u16 value = 0xffff; - - RTL_W32(tp, EPHYAR, - EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed EPHY read */ - if (RTL_R32(tp, EPHYAR) & EPHYAR_Flag) { - value = (u16) (RTL_R32(tp, EPHYAR) & EPHYAR_Data_Mask); - break; - } - } - - udelay(20); - - return value; -} - -static void ClearAndSetPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 EphyValue; - - EphyValue = rtl8125_ephy_read(tp, addr); - EphyValue &= ~clearmask; - EphyValue |= setmask; - rtl8125_ephy_write(tp, addr, EphyValue); -} - -static void ClearPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - mask, - 0 - ); -} - -static void SetPCIePhyBit( struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - 0, - mask - ); -} - -static u32 -rtl8125_csi_other_fun_read(struct rtl8125_private *tp, - u8 multi_fun_sel_bit, - u32 addr) -{ - u32 cmd; - int i; - u32 value = 0; - - cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - multi_fun_sel_bit = 0; - - if (multi_fun_sel_bit > 7) - return 0xffffffff; - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed CSI read */ - if (RTL_R32(tp, CSIAR) & CSIAR_Flag) { - value = (u32)RTL_R32(tp, CSIDR); - break; - } - } - - udelay(20); - - return value; -} - -static void -rtl8125_csi_other_fun_write(struct rtl8125_private *tp, - u8 multi_fun_sel_bit, - u32 addr, - u32 value) -{ - u32 cmd; - int i; - - RTL_W32(tp, CSIDR, value); - cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - if (tp->mcfg == CFG_METHOD_DEFAULT) - multi_fun_sel_bit = 0; - - if ( multi_fun_sel_bit > 7 ) - return; - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed CSI write */ - if (!(RTL_R32(tp, CSIAR) & CSIAR_Flag)) - break; - } - - udelay(20); -} - -static u32 -rtl8125_csi_read(struct rtl8125_private *tp, - u32 addr) -{ - u8 multi_fun_sel_bit; - - multi_fun_sel_bit = 0; - - return rtl8125_csi_other_fun_read(tp, multi_fun_sel_bit, addr); -} - -static void -rtl8125_csi_write(struct rtl8125_private *tp, - u32 addr, - u32 value) -{ - u8 multi_fun_sel_bit; - - multi_fun_sel_bit = 0; - - rtl8125_csi_other_fun_write(tp, multi_fun_sel_bit, addr, value); -} - -static u8 -rtl8125_csi_fun0_read_byte(struct rtl8125_private *tp, - u32 addr) -{ - u8 RetVal = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) { - struct pci_dev *pdev = tp->pci_dev; - - pci_read_config_byte(pdev, addr, &RetVal); - } else { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8125_csi_other_fun_read(tp, 0, addr); - TmpUlong >>= (8*ShiftByte); - RetVal = (u8)TmpUlong; - } - - udelay(20); - - return RetVal; -} - -static void -rtl8125_csi_fun0_write_byte(struct rtl8125_private *tp, - u32 addr, - u8 value) -{ - if (tp->mcfg == CFG_METHOD_DEFAULT) { - struct pci_dev *pdev = tp->pci_dev; - - pci_write_config_byte(pdev, addr, value); - } else { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8125_csi_other_fun_read(tp, 0, RegAlignAddr); - TmpUlong &= ~(0xFF << (8*ShiftByte)); - TmpUlong |= (value << (8*ShiftByte)); - rtl8125_csi_other_fun_write( tp, 0, RegAlignAddr, TmpUlong ); - } - - udelay(20); -} - -u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, value2 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - eri_cmd = ERIAR_Read | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed ERI read */ - if (RTL_R32(tp, ERIAR) & ERIAR_Flag) - break; - } - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = RTL_R32(tp, ERIDR) & mask; - value2 |= (value1 >> val_shift * 8) << shift * 8; - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return value2; -} - -u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type) -{ - return rtl8125_eri_read_with_oob_base_address(tp, addr, len, type, 0); -} - -int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = rtl8125_eri_read_with_oob_base_address(tp, addr, 4, type, base_address) & ~mask; - value1 |= ((value << val_shift * 8) >> shift * 8); - - RTL_W32(tp, ERIDR, value1); - - eri_cmd = ERIAR_Write | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed ERI write */ - if (!(RTL_R32(tp, ERIAR) & ERIAR_Flag)) - break; - } - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return 0; -} - -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type) -{ - return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, type, NO_BASE_ADDRESS); -} - -static void -rtl8125_enable_rxdvgate(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_3); - mdelay(2); - break; - } -} - -static void -rtl8125_disable_rxdvgate(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_3); - mdelay(2); - break; - } -} - -static u8 -rtl8125_is_gpio_low(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 gpio_low = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - if (!(rtl8125_mac_ocp_read(tp, 0xDC04) & BIT_13)) - gpio_low = TRUE; - break; - } - - if (gpio_low) - dprintk("gpio is low.\n"); - - return gpio_low; -} - -static u8 -rtl8125_is_phy_disable_mode_enabled(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 phy_disable_mode_enabled = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - if (RTL_R8(tp, 0xF2) & BIT_5) - phy_disable_mode_enabled = TRUE; - break; - } - - if (phy_disable_mode_enabled) - dprintk("phy disable mode enabled.\n"); - - return phy_disable_mode_enabled; -} - -static u8 -rtl8125_is_in_phy_disable_mode(struct net_device *dev) -{ - u8 in_phy_disable_mode = FALSE; - - if (rtl8125_is_phy_disable_mode_enabled(dev) && rtl8125_is_gpio_low(dev)) - in_phy_disable_mode = TRUE; - - if (in_phy_disable_mode) - dprintk("Hardware is in phy disable mode.\n"); - - return in_phy_disable_mode; -} - -static void -rtl8125_enable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_5); - break; - } - - dprintk("enable phy disable mode.\n"); -} - -static void -rtl8125_disable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_5); - break; - } - - mdelay(1); - - dprintk("disable phy disable mode.\n"); -} - -void -rtl8125_wait_txrx_fifo_empty(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - for (i = 0; i < 3000; i++) { - udelay(50); - if ((RTL_R8(tp, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) == (Txfifo_empty | Rxfifo_empty)) - break; - - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - for (i = 0; i < 3000; i++) { - udelay(50); - if ((RTL_R16(tp, IntrMitigate) & (BIT_0 | BIT_1 | BIT_8)) == (BIT_0 | BIT_1 | BIT_8)) - break; - - } - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT - -static inline void -rtl8125_enable_dash2_interrupt(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, ( ISRIMR_DASH_TYPE2_ROK | ISRIMR_DASH_TYPE2_TOK | ISRIMR_DASH_TYPE2_TDU | ISRIMR_DASH_TYPE2_RDU | ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE )); - } -} - -static inline void -rtl8125_disable_dash2_interrupt(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, 0); - } -} -#endif - -static inline void -rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp) -{ - switch (tp->HwCurrIsrVer) { - case 2: - RTL_W32(tp, IMR_V2_SET_REG_8125, ISRIMR_V2_LINKCHG); - break; - case 1: - RTL_W32(tp, tp->imr_reg[0], LinkChg); - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif -} - -static inline void -rtl8125_enable_hw_interrupt(struct rtl8125_private *tp) -{ - switch (tp->HwCurrIsrVer) { - case 2: - RTL_W32(tp, IMR_V2_SET_REG_8125, tp->intr_mask); - break; - case 1: - RTL_W32(tp, tp->imr_reg[0], tp->intr_mask); - - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->imr_reg[i], other_q_intr_mask); - } - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif -} - -static inline void rtl8125_clear_hw_isr_v2(struct rtl8125_private *tp, - u32 message_id) -{ - RTL_W32(tp, ISR_V2_8125, BIT(message_id)); -} - -static inline void -rtl8125_disable_hw_interrupt(struct rtl8125_private *tp) -{ - if (tp->HwCurrIsrVer == 2) { - RTL_W32(tp, IMR_V2_CLEAR_REG_8125, 0xFFFFFFFF); - } else { - RTL_W32(tp, tp->imr_reg[0], 0x0000); - - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->imr_reg[i], 0); - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_disable_dash2_interrupt(tp); -#endif - } -} - -static inline void -rtl8125_switch_to_hw_interrupt(struct rtl8125_private *tp) -{ - RTL_W32(tp, TIMER_INT0_8125, 0x0000); - - rtl8125_enable_hw_interrupt(tp); -} - -static inline void -rtl8125_switch_to_timer_interrupt(struct rtl8125_private *tp) -{ - if (tp->use_timer_interrrupt) { - RTL_W32(tp, TIMER_INT0_8125, timer_count); - RTL_W32(tp, TCTR0_8125, timer_count); - RTL_W32(tp, tp->imr_reg[0], tp->timer_intr_mask); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif - } else { - rtl8125_switch_to_hw_interrupt(tp); - } -} - -static void -rtl8125_irq_mask_and_ack(struct rtl8125_private *tp) -{ - rtl8125_disable_hw_interrupt(tp); - - if (tp->HwCurrIsrVer == 2) { - RTL_W32(tp, ISR_V2_8125, 0xFFFFFFFF); - } else { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (tp->dash_printer_enabled) { - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0]) & - ~(ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } else { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0)); - } - } - } else { - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); - } -#else - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); -#endif - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->isr_reg[i], RTL_R16(tp, tp->isr_reg[i])); - } - } -} - -static void -rtl8125_nic_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8125_enable_rxdvgate(dev); - - rtl8125_wait_txrx_fifo_empty(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - mdelay(2); - break; - } - - /* Soft reset the chip. */ - RTL_W8(tp, ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { - udelay(100); - if ((RTL_R8(tp, ChipCmd) & CmdReset) == 0) - break; - } -} - -static void -rtl8125_hw_set_interrupt_type(struct rtl8125_private *tp, u8 isr_ver) -{ - u8 tmp; - - switch (tp->HwSuppIsrVer) { - case 2: - tmp = RTL_R8(tp, INT_CFG0_8125); - tmp &= ~(INT_CFG0_ENABLE_8125); - if (isr_ver == 2) - tmp |= INT_CFG0_ENABLE_8125; - RTL_W8(tp, INT_CFG0_8125, tmp); - break; - } -} - -static void -rtl8125_hw_clear_timer_int(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W32(tp, TIMER_INT0_8125, 0x0000); - RTL_W32(tp, TIMER_INT1_8125, 0x0000); - RTL_W32(tp, TIMER_INT2_8125, 0x0000); - RTL_W32(tp, TIMER_INT3_8125, 0x0000); - break; - } -} - -static void -rtl8125_hw_clear_int_miti(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - switch (tp->HwSuppIntMitiVer) { - case 3: - //IntMITI_0-IntMITI_31 - for (i=0xA00; i<0xB00; i+=4) - RTL_W32(tp, i, 0x0000); - break; - case 4: - //IntMITI_0-IntMITI_15 - for (i = 0xA00; i < 0xA80; i += 4) - RTL_W32(tp, i, 0x0000); - - RTL_W8(tp, INT_CFG0_8125, RTL_R8(tp, INT_CFG0_8125) & - ~(INT_CFG0_TIMEOUT0_BYPASS_8125 | INT_CFG0_MITIGATION_BYPASS_8125)); - - RTL_W16(tp, INT_CFG1_8125, 0x0000); - break; - } -} - -void -rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, - u32 message_id, - u8 timer_intmiti_val) -{ - switch (tp->HwSuppIntMitiVer) { - case 4: - if (message_id < R8125_MAX_RX_QUEUES_VEC_V3) //ROK - RTL_W8(tp,INT_MITI_V2_0_RX + 8 * message_id, timer_intmiti_val); - else if (message_id == 16) //TOK - RTL_W8(tp,INT_MITI_V2_0_TX, timer_intmiti_val); - else if (message_id == 18) //TOK - RTL_W8(tp,INT_MITI_V2_1_TX, timer_intmiti_val); - break; - } -} - -void -rtl8125_hw_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_lib_reset_prepare(tp); - - /* Disable interrupts */ - rtl8125_irq_mask_and_ack(tp); - - rtl8125_hw_clear_timer_int(dev); - - rtl8125_nic_reset(dev); -} - -static unsigned int -rtl8125_xmii_reset_pending(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int retval; - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - retval = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; - - return retval; -} - -static unsigned int -rtl8125_xmii_link_ok(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int retval; - - retval = (RTL_R16(tp, PHYstatus) & LinkStatus) ? 1 : 0; - - return retval; -} - -static void -rtl8125_xmii_reset_enable(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i, val = 0; - - if (rtl8125_is_in_phy_disable_mode(dev)) { - return; - } - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - rtl8125_mdio_write(tp, MII_ADVERTISE, rtl8125_mdio_read(tp, MII_ADVERTISE) & - ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL)); - rtl8125_mdio_write(tp, MII_CTRL1000, rtl8125_mdio_read(tp, MII_CTRL1000) & - ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL)); - mdio_direct_write_phy_ocp(tp, 0xA5D4, mdio_direct_read_phy_ocp(tp, 0xA5D4) & ~(RTK_ADVERTISE_2500FULL)); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - - for (i = 0; i < 2500; i++) { - val = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; - - if (!val) { - return; - } - - mdelay(1); - } - - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -void -rtl8125_init_ring_indexes(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - ring->dirty_tx = ring->cur_tx = 0; - ring->NextHwDesCloPtr = 0; - ring->BeginHwDesCloPtr = 0; - ring->index = i; - ring->priv = tp; - } - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - ring->dirty_rx = ring->cur_rx = 0; - ring->index = i; - ring->priv = tp; - } - -#ifdef ENABLE_LIB_SUPPORT - for (i = 0; i < tp->HwSuppNumTxQueues; i++) { - struct rtl8125_ring *ring = &tp->lib_tx_ring[i]; - ring->direction = RTL8125_CH_DIR_TX; - ring->queue_num = i; - ring->private = tp; - } - - for (i = 0; i < tp->HwSuppNumRxQueues; i++) { - struct rtl8125_ring *ring = &tp->lib_rx_ring[i]; - ring->direction = RTL8125_CH_DIR_RX; - ring->queue_num = i; - ring->private = tp; - } -#endif -} - -static void -rtl8125_issue_offset_99_event(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE09A, rtl8125_mac_ocp_read(tp, 0xE09A) | BIT_0); - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT -static void -NICChkTypeEnableDashInterrupt(struct rtl8125_private *tp) -{ - if (tp->DASH) { - // - // even disconnected, enable 3 dash interrupt mask bits for in-band/out-band communication - // - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8125_enable_dash2_interrupt(tp); - RTL_W16(tp, IntrMask, (ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } - } -} -#endif - -static int rtl8125_enable_eee_plus(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)|BIT_1); - break; - - default: -// dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Not Support EEEPlus\n"); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static int rtl8125_disable_eee_plus(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)&~BIT_1); - break; - - default: -// dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Not Support EEEPlus\n"); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8125_wakeup_all_tx_queue(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - for (i=0; inum_tx_rings; i++) - netif_start_subqueue(dev, i); -} - -static void -rtl8125_stop_all_tx_queue(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - for (i=0; inum_tx_rings; i++) - netif_stop_subqueue(dev, i); -} - -static void -rtl8125_link_on_patch(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_hw_config(dev); - - if ((tp->mcfg == CFG_METHOD_2) && - netif_running(dev)) { - if (RTL_R16(tp, PHYstatus)&FullDup) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | (BIT_24 | BIT_25)) & ~BIT_19); - else - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_25) & ~(BIT_19 | BIT_24)); - } - - if ((tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) && - (RTL_R8(tp, PHYstatus) & _10bps)) - rtl8125_enable_eee_plus(tp); - - rtl8125_hw_start(dev); - - netif_carrier_on(dev); - - rtl8125_wakeup_all_tx_queue(dev); - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - tp->phy_reg_anlpar = rtl8125_mdio_read(tp, MII_LPA); -} - -static void -rtl8125_link_down_patch(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->phy_reg_anlpar = 0; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_disable_eee_plus(tp); - - rtl8125_stop_all_tx_queue(dev); - - netif_carrier_off(dev); - - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - rtl8125_rx_clear(tp); - - rtl8125_init_ring(dev); - - rtl8125_enable_hw_linkchg_interrupt(tp); - - //rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - NICChkTypeEnableDashInterrupt(tp); - } -#endif -} - -static void -rtl8125_check_link_status(struct net_device *dev, bool force_set) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int link_status_on; - - link_status_on = tp->link_ok(dev); - - if (force_set || (netif_carrier_ok(dev) != link_status_on)) { - if (link_status_on) { - rtl8125_link_on_patch(dev); - - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - - rtl8125_link_down_patch(dev); - } - - if (!force_set) - tp->resume_not_chg_speed = 0; - } -} - -static void -rtl8125_link_option(u8 *aut, - u32 *spd, - u8 *dup, - u32 *adv) -{ - if ((*spd != SPEED_2500) && (*spd != SPEED_1000) && - (*spd != SPEED_100) && (*spd != SPEED_10)) - *spd = SPEED_2500; - - if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) - *dup = DUPLEX_FULL; - - if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) - *aut = AUTONEG_ENABLE; - - *adv &= (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full); - if (*adv == 0) - *adv = (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full); -} - -/* -static void -rtl8125_enable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - val = mdio_direct_read_phy_ocp(tp, 0xC416); - if (val != 0x0050) { - rtl8125_set_phy_mcu_patch_request(tp); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0050); - rtl8125_clear_phy_mcu_patch_request(tp); - } - } -} -*/ - -static void -rtl8125_disable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - val = mdio_direct_read_phy_ocp(tp, 0xC416); - if (val != 0x0500) { - rtl8125_set_phy_mcu_patch_request(tp); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0500); - rtl8125_clear_phy_mcu_patch_request(tp); - } - } -} - -static void -rtl8125_wait_ll_share_fifo_ready(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - for (i = 0; i < 10; i++) { - udelay(100); - if (RTL_R16(tp, 0xD2) & BIT_9) - break; - } -} - -static void -rtl8125_disable_pci_offset_99(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE032, rtl8125_mac_ocp_read(tp, 0xE032) & ~(BIT_0 | BIT_1)); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_csi_fun0_write_byte(tp, 0x99, 0x00); - break; - } -} - -static void -rtl8125_enable_pci_offset_99(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_csi_fun0_write_byte(tp, 0x99, tp->org_pci_offset_99); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); - csi_tmp &= ~(BIT_0 | BIT_1); - if (!(tp->org_pci_offset_99 & (BIT_5 | BIT_6))) - csi_tmp |= BIT_1; - if (!(tp->org_pci_offset_99 & BIT_2)) - csi_tmp |= BIT_0; - rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); - break; - } -} - -static void -rtl8125_init_pci_offset_99(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xCDD0, 0x9003); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE034); - csi_tmp |= (BIT_15 | BIT_14); - rtl8125_mac_ocp_write(tp, 0xE034, csi_tmp); - rtl8125_mac_ocp_write(tp, 0xCDD2, 0x889C); - rtl8125_mac_ocp_write(tp, 0xCDD8, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDD4, 0x8C30); - rtl8125_mac_ocp_write(tp, 0xCDDA, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDD6, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDDC, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDE8, 0x883E); - rtl8125_mac_ocp_write(tp, 0xCDEA, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDEC, 0x889C); - rtl8125_mac_ocp_write(tp, 0xCDEE, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDF0, 0x8C09); - rtl8125_mac_ocp_write(tp, 0xCDF2, 0x9003); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); - csi_tmp |= (BIT_14); - rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE0A2); - csi_tmp |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xE0A2, csi_tmp); - break; - } - - rtl8125_enable_pci_offset_99(tp); -} - -static void -rtl8125_disable_pci_offset_180(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); - csi_tmp &= 0xFF00; - rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); - break; - } -} - -static void -rtl8125_enable_pci_offset_180(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE094); - csi_tmp &= 0x00FF; - rtl8125_mac_ocp_write(tp, 0xE094, csi_tmp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); - csi_tmp &= 0xFF00; - csi_tmp |= BIT_2; - rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); - break; - } -} - -static void -rtl8125_init_pci_offset_180(struct rtl8125_private *tp) -{ - if (tp->org_pci_offset_180 & (BIT_0|BIT_1)) - rtl8125_enable_pci_offset_180(tp); - else - rtl8125_disable_pci_offset_180(tp); -} - -static void -rtl8125_set_pci_99_180_exit_driver_para(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_issue_offset_99_event(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_disable_pci_offset_99(tp); - break; - } - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_disable_pci_offset_180(tp); - break; - } -} - -static void -rtl8125_enable_cfg9346_write(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) | Cfg9346_Unlock); -} - -static void -rtl8125_disable_cfg9346_write(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) & ~Cfg9346_Unlock); -} - -static void -rtl8125_enable_exit_l1_mask(struct rtl8125_private *tp) -{ - //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b111111, L1 Mask - SetMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); -} - -static void -rtl8125_disable_exit_l1_mask(struct rtl8125_private *tp) -{ - //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b000000, L1 Mask - ClearMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); -} - -static void -rtl8125_hw_d3_para(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - RTL_W16(tp, RxMaxSize, RX_BUF_SIZE); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - rtl8125_disable_cfg9346_write(tp); - break; - } - - rtl8125_disable_exit_l1_mask(tp); - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_set_realwow_d3_para(dev); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xEA18, 0x0064); - break; - } - - rtl8125_set_pci_99_180_exit_driver_para(dev); - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_disable_ocp_phy_power_saving(dev); - - rtl8125_disable_rxdvgate(dev); -} - -static void -rtl8125_enable_magic_packet(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) | BIT_0); - break; - } -} -static void -rtl8125_disable_magic_packet(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) & ~BIT_0); - break; - } -} - -static void -rtl8125_enable_linkchg_wakeup(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | LinkUp); - ClearAndSetMcuAccessRegBit(tp, 0xE0C6, (BIT_3 | BIT_2), (BIT_4 | BIT_1 | BIT_0)); - break; - } -} - -static void -rtl8125_disable_linkchg_wakeup(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~LinkUp); - ClearMcuAccessRegBit(tp, 0xE0C6, (BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0)); - break; - } -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 -rtl8125_get_hw_wol(struct rtl8125_private *tp) -{ - u8 options; - u32 csi_tmp; - u32 wol_opts = 0; - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out; - - options = RTL_R8(tp, Config3); - if (options & LinkUp) - wol_opts |= WAKE_PHY; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xC0B6); - if (csi_tmp & BIT_0) - wol_opts |= WAKE_MAGIC; - break; - } - - options = RTL_R8(tp, Config5); - if (options & UWF) - wol_opts |= WAKE_UCAST; - if (options & BWF) - wol_opts |= WAKE_BCAST; - if (options & MWF) - wol_opts |= WAKE_MCAST; - -out: - return wol_opts; -} - -static void -rtl8125_enable_d0_speedup(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_DISABLE) return; - - if (tp->HwSuppD0SpeedUpVer == 1) { - u16 mac_ocp_data; - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_3); - - //speed up speed - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE10A); - mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8 | BIT_7); - if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_2500) { - mac_ocp_data |= BIT_7; - } - rtl8125_mac_ocp_write(tp, 0xE10A, mac_ocp_data); - - //speed up flowcontrol - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE860); - mac_ocp_data |= (BIT_15 | BIT_14); - rtl8125_mac_ocp_write(tp, 0xE860, mac_ocp_data); - } -} - -static void -rtl8125_disable_d0_speedup(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - - if (tp->HwSuppD0SpeedUpVer == 1) - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_7); -} - -static void -rtl8125_set_hw_wol(struct net_device *dev, u32 wolopts) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i,tmp; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake }, - { WAKE_MAGIC, Config3, MagicPacket }, - }; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - default: - tmp = ARRAY_SIZE(cfg) - 1; - - if (wolopts & WAKE_MAGIC) - rtl8125_enable_magic_packet(dev); - else - rtl8125_disable_magic_packet(dev); - break; - } - - rtl8125_enable_cfg9346_write(tp); - - for (i = 0; i < tmp; i++) { - u8 options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(tp, cfg[i].reg, options); - } - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - if (wolopts & WAKE_PHY) - rtl8125_enable_linkchg_wakeup(dev); - else - rtl8125_disable_linkchg_wakeup(dev); - break; - } - - rtl8125_disable_cfg9346_write(tp); -} - -static void -rtl8125_phy_restart_nway(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) return; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); -} - -static void -rtl8125_phy_setup_force_mode(struct net_device *dev, u32 speed, u8 duplex) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 bmcr_true_force = 0; - - if (rtl8125_is_in_phy_disable_mode(dev)) return; - - if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED10; - } else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED100; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX; - } else if ((speed == SPEED_1000) && (duplex == DUPLEX_FULL) && - tp->HwSuppGigaForceMode) { - bmcr_true_force = BMCR_SPEED1000 | BMCR_FULLDPLX; - } else { - netif_err(tp, drv, dev, "Failed to set phy force mode!\n"); - return; - } - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, bmcr_true_force); -} - -static void -rtl8125_set_pci_pme(struct rtl8125_private *tp, int set) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 pmc; - - if (!pdev->pm_cap) - return; - - pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); - pmc |= PCI_PM_CTRL_PME_STATUS; - if (set) - pmc |= PCI_PM_CTRL_PME_ENABLE; - else - pmc &= ~PCI_PM_CTRL_PME_ENABLE; - pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); -} - -static void -rtl8125_set_wol_link_speed(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int auto_nego; - int giga_ctrl; - u16 anlpar; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL - | ADVERTISE_100HALF | ADVERTISE_100FULL); - - if (netif_running(dev)) - anlpar = tp->phy_reg_anlpar; - else - anlpar = rtl8125_mdio_read(tp, MII_LPA); - -#ifdef CONFIG_DOWN_SPEED_100 - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); -#else - if (anlpar & (LPA_10HALF | LPA_10FULL)) - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL); - else - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); -#endif - - if (tp->DASH) - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); - - giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000) & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - int ctrl_2500; - - ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); - ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); - mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); - } - rtl8125_phy_restart_nway(dev); -} - -static bool -rtl8125_keep_wol_link_speed(struct net_device *dev, u8 from_suspend) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if ((from_suspend && !tp->link_ok(dev)) || - (!from_suspend && tp->resume_not_chg_speed)) - return 1; - - return 0; -} -static void -rtl8125_powerdown_pll(struct net_device *dev, u8 from_suspend) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->check_keep_link_speed = 0; - if (tp->wol_enabled == WOL_ENABLED || tp->DASH || tp->EnableKCPOffload) { - rtl8125_set_hw_wol(dev, tp->wol_opts); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | PMSTS_En); - rtl8125_disable_cfg9346_write(tp); - } - - /* Enable the PME and clear the status */ - rtl8125_set_pci_pme(tp, 1); - - if (rtl8125_keep_wol_link_speed(dev, from_suspend)) { - if (tp->wol_opts & WAKE_PHY) - tp->check_keep_link_speed = 1; - } else { - if (HW_SUPPORT_D0_SPEED_UP(tp)) { - rtl8125_enable_d0_speedup(tp); - tp->check_keep_link_speed = 1; - } - - rtl8125_set_wol_link_speed(dev); - } - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - - return; - } - - if (tp->DASH) - return; - - rtl8125_phy_power_down(dev); - - if (!tp->HwIcVerUnknown) { - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~BIT_7); - break; - } - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); - break; - } -} - -static void rtl8125_powerup_pll(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | BIT_7 | BIT_6); - break; - } - - if (tp->resume_not_chg_speed) return; - - rtl8125_phy_power_up(dev); -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8125_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 options; - unsigned long flags; - - wol->wolopts = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) { - wol->supported = 0; - return; - } else { - wol->supported = WAKE_ANY; - } - - spin_lock_irqsave(&tp->lock, flags); - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out_unlock; - - wol->wolopts = tp->wol_opts; - -out_unlock: - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int -rtl8125_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - tp->wol_opts = wol->wolopts; - - tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; - - spin_unlock_irqrestore(&tp->lock, flags); - - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - return 0; -} - -static void -rtl8125_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8125_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = R8125_REGS_DUMP_SIZE; - info->eedump_len = tp->eeprom_len; -} - -static int -rtl8125_get_regs_len(struct net_device *dev) -{ - return R8125_REGS_DUMP_SIZE; -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static void -rtl8125_set_d0_speedup_speed(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - - if (tp->autoneg == AUTONEG_ENABLE || tp->speed == SPEED_2500) - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_2500; - else if(tp->speed == SPEED_1000) - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_1000; - else - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_DISABLE; -} - -static int -rtl8125_set_speed_xmii(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int auto_nego = 0; - int giga_ctrl = 0; - int ctrl_2500 = 0; - int rc = -EINVAL; - - //Disable Giga Lite - ClearEthPhyOcpBit(tp, 0xA428, BIT_9); - ClearEthPhyOcpBit(tp, 0xA5EA, BIT_0); - - if (speed != SPEED_2500 && - (speed != SPEED_1000) && - (speed != SPEED_100) && - (speed != SPEED_10)) { - speed = SPEED_2500; - duplex = DUPLEX_FULL; - } - - giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); - ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); - - if (autoneg == AUTONEG_ENABLE) { - /*n-way force*/ - auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - if (adv & ADVERTISED_10baseT_Half) - auto_nego |= ADVERTISE_10HALF; - if (adv & ADVERTISED_10baseT_Full) - auto_nego |= ADVERTISE_10FULL; - if (adv & ADVERTISED_100baseT_Half) - auto_nego |= ADVERTISE_100HALF; - if (adv & ADVERTISED_100baseT_Full) - auto_nego |= ADVERTISE_100FULL; - if (adv & ADVERTISED_1000baseT_Half) - giga_ctrl |= ADVERTISE_1000HALF; - if (adv & ADVERTISED_1000baseT_Full) - giga_ctrl |= ADVERTISE_1000FULL; - if (adv & ADVERTISED_2500baseX_Full) - ctrl_2500 |= RTK_ADVERTISE_2500FULL; - - //flow control - if (dev->mtu <= ETH_DATA_LEN && tp->fcpause == rtl8125_fc_full) - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - tp->phy_2500_ctrl_reg = ctrl_2500; - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); - mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); - rtl8125_phy_restart_nway(dev); - mdelay(20); - } else { - /*true force*/ - if (speed == SPEED_10 || speed == SPEED_100 || - (speed == SPEED_1000 && duplex == DUPLEX_FULL && - tp->HwSuppGigaForceMode)) { - rtl8125_phy_setup_force_mode(dev, speed, duplex); - } else - goto out; - } - - tp->autoneg = autoneg; - tp->speed = speed; - tp->duplex = duplex; - tp->advertising = adv; - - rtl8125_set_d0_speedup_speed(tp); - - rc = 0; -out: - return rc; -} - -static int -rtl8125_set_speed(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret; - - if (tp->resume_not_chg_speed) return 0; - - ret = tp->set_speed(dev, autoneg, speed, duplex, adv); - - return ret; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8125_set_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - const struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret; - unsigned long flags; - u8 autoneg; - u32 speed; - u8 duplex; - u32 supported, advertising; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - autoneg = cmd->autoneg; - speed = cmd->speed; - duplex = cmd->duplex; - supported = cmd->supported; - advertising = cmd->advertising; -#else - const struct ethtool_link_settings *base = &cmd->base; - autoneg = base->autoneg; - speed = base->speed; - duplex = base->duplex; - ethtool_convert_link_mode_to_legacy_u32(&supported, - cmd->link_modes.supported); - ethtool_convert_link_mode_to_legacy_u32(&advertising, - cmd->link_modes.advertising); -#endif - if (advertising & ~supported) - return -EINVAL; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8125_set_speed(dev, autoneg, speed, duplex, advertising); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -static u32 -rtl8125_get_tx_csum(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 ret; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - ret = ((dev->features & NETIF_F_IP_CSUM) != 0); -#else - ret = ((dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != 0); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 -rtl8125_get_rx_csum(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 ret; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - ret = tp->cp_cmd & RxChkSum; - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int -rtl8125_set_tx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; -#else - if (data) - dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -static int -rtl8125_set_rx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static u32 -rtl8125_rx_desc_opts1(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1; - else - return desc->opts1; -} - -static u32 -rtl8125_rx_desc_opts2(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2; - else - return desc->opts2; -} - -static void -rtl8125_clear_rx_desc_opts2(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2 = 0; - else - desc->opts2 = 0; -} - -#ifdef CONFIG_R8125_VLAN - -static inline u32 -rtl8125_tx_vlan_tag(struct rtl8125_private *tp, - struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - return (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#else - return (skb_vlan_tag_present(skb)) ? - TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; -#endif - - return 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -static void -rtl8125_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - if (tp->vlgrp) { - tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | (EnableInnerVlan | EnableOuterVlan)) - } else { - tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(EnableInnerVlan | EnableOuterVlan)) - } - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -static void -rtl8125_vlan_rx_kill_vid(struct net_device *dev, - unsigned short vid) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; -#else - vlan_group_set_device(tp->vlgrp, vid, NULL); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - spin_unlock_irqrestore(&tp->lock, flags); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - -static int -rtl8125_rx_vlan_skb(struct rtl8125_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); - int ret = -1; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8125_rx_hwaccel_skb(skb, tp->vlgrp, - swab16(opts2 & 0xffff)); - ret = 0; - } -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); -#else - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); -#endif - - rtl8125_clear_rx_desc_opts2(tp, desc); - return ret; -} - -#else /* !CONFIG_R8125_VLAN */ - -static inline u32 -rtl8125_tx_vlan_tag(struct rtl8125_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int -rtl8125_rx_vlan_skb(struct rtl8125_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - -static netdev_features_t rtl8125_fix_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (dev->mtu > MSS_MAX) - features &= ~NETIF_F_ALL_TSO; - if (dev->mtu > ETH_DATA_LEN) { - features &= ~NETIF_F_ALL_TSO; - features &= ~NETIF_F_ALL_CSUM; - } -#ifndef CONFIG_R8125_VLAN - features &= ~NETIF_F_ALL_CSUM; -#endif - spin_unlock_irqrestore(&tp->lock, flags); - - return features; -} - -static int rtl8125_hw_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 rx_config; - - rx_config = RTL_R32(tp, RxConfig); - if (features & NETIF_F_RXALL) - rx_config |= (AcceptErr | AcceptRunt); - else - rx_config &= ~(AcceptErr | AcceptRunt); - - if (dev->features & NETIF_F_HW_VLAN_RX) - rx_config |= (EnableInnerVlan | EnableOuterVlan); - else - rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - - RTL_W32(tp, RxConfig, rx_config); - - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - RTL_R16(tp, CPlusCmd); - - return 0; -} - -static int rtl8125_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX; - - spin_lock_irqsave(&tp->lock, flags); - if (features ^ dev->features) - rtl8125_hw_set_features(dev, features); - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#endif - -static void rtl8125_gset_xmii(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 status; - u8 autoneg, duplex; - u32 speed = 0; - u16 bmcr; - u32 supported, advertising; - unsigned long flags; - - supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_2500baseX_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | - SUPPORTED_Pause | - SUPPORTED_Asym_Pause; - - advertising = ADVERTISED_TP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8125_mdio_read(tp, MII_BMCR); - spin_unlock_irqrestore(&tp->lock, flags); - - if (bmcr & BMCR_ANENABLE) { - advertising |= ADVERTISED_Autoneg; - autoneg = AUTONEG_ENABLE; - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - advertising |= ADVERTISED_1000baseT_Full; - if (tp->phy_2500_ctrl_reg & RTK_ADVERTISE_2500FULL) - advertising |= ADVERTISED_2500baseX_Full; - } else { - autoneg = AUTONEG_DISABLE; - } - - status = RTL_R16(tp, PHYstatus); - - if (status & LinkStatus) { - /*link on*/ - if (status & _2500bpsF) - speed = SPEED_2500; - else if (status & _1000bpsF) - speed = SPEED_1000; - else if (status & _100bps) - speed = SPEED_100; - else if (status & _10bps) - speed = SPEED_10; - - if (status & TxFlowCtrl) - advertising |= ADVERTISED_Asym_Pause; - - if (status & RxFlowCtrl) - advertising |= ADVERTISED_Pause; - - duplex = ((status & (_1000bpsF | _2500bpsF)) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - /*link down*/ - speed = SPEED_UNKNOWN; - duplex = DUPLEX_UNKNOWN; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - cmd->supported = supported; - cmd->advertising = advertising; - cmd->autoneg = autoneg; - cmd->speed = speed; - cmd->duplex = duplex; - cmd->port = PORT_TP; -#else - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, - advertising); - cmd->base.autoneg = autoneg; - cmd->base.speed = speed; - cmd->base.duplex = duplex; - cmd->base.port = PORT_TP; -#endif -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8125_get_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->get_settings(dev, cmd); - - return 0; -} - -static void rtl8125_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - u8 *data = p; - unsigned long flags; - - if (regs->len < R8125_REGS_DUMP_SIZE) - return /* -EINVAL */; - - memset(p, 0, regs->len); - - spin_lock_irqsave(&tp->lock, flags); - for (i = 0; i < R8125_MAC_REGS_SIZE; i++) - *data++ = readb(ioaddr + i); - data = (u8*)p + 256; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - for (i = 0; i < R8125_PHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8125_mdio_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 2; - - for (i = 0; i < R8125_EPHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8125_ephy_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 3; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - for (i = 0; i < R8125_ERI_REGS_SIZE; i+=4) { - *(u32*)data = rtl8125_eri_read(tp, i , 4, ERIAR_ExGMAC); - data += 4; - } - break; - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void rtl8125_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - pause->autoneg = (tp->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - if (tp->fcpause == rtl8125_fc_rx_pause) - pause->rx_pause = 1; - else if (tp->fcpause == rtl8125_fc_tx_pause) - pause->tx_pause = 1; - else if (tp->fcpause == rtl8125_fc_full) { - pause->rx_pause = 1; - pause->tx_pause = 1; - } - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8125_set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct rtl8125_private *tp = netdev_priv(dev); - enum rtl8125_fc_mode newfc; - unsigned long flags; - - if (pause->tx_pause || pause->rx_pause) - newfc = rtl8125_fc_full; - else - newfc = rtl8125_fc_none; - - spin_lock_irqsave(&tp->lock, flags); - - if (tp->fcpause != newfc) { - tp->fcpause = newfc; - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - } - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; - -} - -static u32 -rtl8125_get_msglevel(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void -rtl8125_set_msglevel(struct net_device *dev, - u32 value) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8125_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int rtl8125_get_stats_count(struct net_device *dev) -{ - return ARRAY_SIZE(rtl8125_gstrings); -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -#else -static int rtl8125_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8125_gstrings); - default: - return -EOPNOTSUPP; - } -} -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8125_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, - u64 *data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - - ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) - return; - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underun); -} - -static void -rtl8125_get_strings(struct net_device *dev, - u32 stringset, - u8 *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8125_gstrings, sizeof(rtl8125_gstrings)); - break; - } -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static int rtl_get_eeprom_len(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - return tp->eeprom_len; -} - -static int rtl_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i,j,ret; - int start_w, end_w; - int VPD_addr, VPD_data; - u32 *eeprom_buff; - u16 tmp; - - if (tp->eeprom_type == EEPROM_TYPE_NONE) { - dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Detect none EEPROM\n"); - return -EOPNOTSUPP; - } else if (eeprom->len == 0 || (eeprom->offset+eeprom->len) > tp->eeprom_len) { - dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Invalid parameter\n"); - return -EINVAL; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - VPD_addr = 0xD2; - VPD_data = 0xD4; - break; - } - - start_w = eeprom->offset >> 2; - end_w = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32)*(end_w - start_w + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - rtl8125_enable_cfg9346_write(tp); - ret = -EFAULT; - for (i=start_w; i<=end_w; i++) { - pci_write_config_word(tp->pci_dev, VPD_addr, (u16)i*4); - ret = -EFAULT; - for (j = 0; j < 10; j++) { - udelay(400); - pci_read_config_word(tp->pci_dev, VPD_addr, &tmp); - if (tmp&0x8000) { - ret = 0; - break; - } - } - - if (ret) - break; - - pci_read_config_dword(tp->pci_dev, VPD_data, &eeprom_buff[i-start_w]); - } - rtl8125_disable_cfg9346_write(tp); - - if (!ret) - memcpy(buf, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); - - kfree(eeprom_buff); - - return ret; -} - -#undef ethtool_op_get_link -#define ethtool_op_get_link _kc_ethtool_op_get_link -static u32 _kc_ethtool_op_get_link(struct net_device *dev) -{ - return netif_carrier_ok(dev) ? 1 : 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#undef ethtool_op_get_sg -#define ethtool_op_get_sg _kc_ethtool_op_get_sg -static u32 _kc_ethtool_op_get_sg(struct net_device *dev) -{ -#ifdef NETIF_F_SG - return (dev->features & NETIF_F_SG) != 0; -#else - return 0; -#endif -} - -#undef ethtool_op_set_sg -#define ethtool_op_set_sg _kc_ethtool_op_set_sg -static int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - -#ifdef NETIF_F_SG - if (data) - dev->features |= NETIF_F_SG; - else - dev->features &= ~NETIF_F_SG; -#endif - - return 0; -} -#endif - -static int rtl8125_enable_eee(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - SetMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); - - SetEthPhyOcpBit(tp, 0xA432, BIT_4); - SetEthPhyOcpBit(tp, 0xA5D0, tp->eee_adv_t); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - - SetEthPhyOcpBit(tp, 0xA5D0, tp->eee_adv_t); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - default: -// dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_set_phy_mcu_patch_request(tp); - ClearMcuAccessRegBit(tp, 0xE052, BIT_0); - ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); - ClearEthPhyOcpBit(tp, 0xA430, BIT_15); - rtl8125_clear_phy_mcu_patch_request(tp); - break; - } - - return ret; -} - -static int rtl8125_disable_eee(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - ClearMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); - - ClearEthPhyOcpBit(tp, 0xA432, BIT_4); - ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - - ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - default: -// dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_set_phy_mcu_patch_request(tp); - ClearMcuAccessRegBit(tp, 0xE052, BIT_0); - ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); - ClearEthPhyOcpBit(tp, 0xA430, BIT_15); - rtl8125_clear_phy_mcu_patch_request(tp); - break; - } - - return ret; -} - -static int rtl_nway_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - int ret, bmcr; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - /* if autoneg is off, it's an error */ - rtl8125_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8125_mdio_read(tp, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - rtl8125_mdio_write(tp, MII_BMCR, bmcr); - ret = 0; - } else { - ret = -EINVAL; - } - - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) -static int -rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *eee) -{ - struct rtl8125_private *tp = netdev_priv(net); - u32 lp, adv, supported = 0; - unsigned long flags; - u16 val; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - /* Get Supported EEE */ - val = mdio_direct_read_phy_ocp(tp, 0xA5C4); - supported = mmd_eee_cap_to_ethtool_sup_t(val); - - /* Get advertisement EEE */ - val = mdio_direct_read_phy_ocp(tp, 0xA5D0); - adv = mmd_eee_adv_to_ethtool_adv_t(val); - - /* Get LP advertisement EEE */ - val = mdio_direct_read_phy_ocp(tp, 0xA5D2); - lp = mmd_eee_adv_to_ethtool_adv_t(val); - - val = rtl8125_mac_ocp_read(tp, 0xE040); - val &= BIT_1 | BIT_0; - - spin_unlock_irqrestore(&tp->lock, flags); - - eee->eee_enabled = !!val; - eee->eee_active = !!(supported & adv & lp); - eee->supported = supported; - eee->advertised = adv; - eee->lp_advertised = lp; - - return 0; -} - -static int -rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *eee) -{ - struct rtl8125_private *tp = netdev_priv(net); - unsigned long flags; - - if (!HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp) || - tp->DASH) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - tp->eee_enabled = eee->eee_enabled; - tp->eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - - if (tp->eee_enabled) { - rtl8125_enable_eee(tp); - } else { - rtl8125_disable_eee(tp); - } - - spin_unlock_irqrestore(&tp->lock, flags); - - rtl_nway_reset(net); - - return 0; -} -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static const struct ethtool_ops rtl8125_ethtool_ops = { - .get_drvinfo = rtl8125_get_drvinfo, - .get_regs_len = rtl8125_get_regs_len, - .get_link = ethtool_op_get_link, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - .get_settings = rtl8125_get_settings, - .set_settings = rtl8125_set_settings, -#else - .get_link_ksettings = rtl8125_get_settings, - .set_link_ksettings = rtl8125_set_settings, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .get_pauseparam = rtl8125_get_pauseparam, - .set_pauseparam = rtl8125_set_pauseparam, -#endif - .get_msglevel = rtl8125_get_msglevel, - .set_msglevel = rtl8125_set_msglevel, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - .get_rx_csum = rtl8125_get_rx_csum, - .set_rx_csum = rtl8125_set_rx_csum, - .get_tx_csum = rtl8125_get_tx_csum, - .set_tx_csum = rtl8125_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, -#ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, -#endif -#endif - .get_regs = rtl8125_get_regs, - .get_wol = rtl8125_get_wol, - .set_wol = rtl8125_set_wol, - .get_strings = rtl8125_get_strings, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - .get_stats_count = rtl8125_get_stats_count, -#else - .get_sset_count = rtl8125_get_sset_count, -#endif - .get_ethtool_stats = rtl8125_get_ethtool_stats, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -#ifdef ETHTOOL_GPERMADDR - .get_perm_addr = ethtool_op_get_perm_addr, -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) - .get_eeprom = rtl_get_eeprom, - .get_eeprom_len = rtl_get_eeprom_len, -#ifdef ENABLE_RSS_SUPPORT - .get_rxnfc = rtl8125_get_rxnfc, - .set_rxnfc = rtl8125_set_rxnfc, - .get_rxfh_indir_size = rtl8125_rss_indir_size, - .get_rxfh_key_size = rtl8125_get_rxfh_key_size, - .get_rxfh = rtl8125_get_rxfh, - .set_rxfh = rtl8125_set_rxfh, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#ifdef ENABLE_PTP_SUPPORT - .get_ts_info = rtl8125_get_ts_info, -#else - .get_ts_info = ethtool_op_get_ts_info, -#endif //ENABLE_PTP_SUPPORT -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) - .get_eee = rtl_ethtool_get_eee, - .set_eee = rtl_ethtool_set_eee, -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - .nway_reset = rtl_nway_reset, - -}; -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if 0 - -static int rtl8125_enable_green_feature(struct rtl8125_private *tp) -{ - u16 gphy_val; - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); - SetEthPhyOcpBit(tp, 0xA438, BIT_15); - rtl8125_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Not Support Green Feature\n"); - break; - } - - return 0; -} - -static int rtl8125_disable_green_feature(struct rtl8125_private *tp) -{ - u16 gphy_val; - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); - ClearEthPhyOcpBit(tp, 0xA438, BIT_15); - rtl8125_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, &tp->pci_dev->dev, "Not Support Green Feature\n"); - break; - } - - return 0; -} - -#endif - -static void rtl8125_get_mac_version(struct rtl8125_private *tp) -{ - u32 reg,val32; - u32 ICVerID; - - val32 = RTL_R32(tp, TxConfig); - reg = val32 & 0x7c800000; - ICVerID = val32 & 0x00700000; - - switch (reg) { - case 0x60800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_2; - } else if (ICVerID == 0x100000) { - tp->mcfg = CFG_METHOD_3; - } else { - tp->mcfg = CFG_METHOD_3; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V4; - break; - case 0x64000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_4; - } else if (ICVerID == 0x100000) { - tp->mcfg = CFG_METHOD_5; - } else { - tp->mcfg = CFG_METHOD_5; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V4; - break; - default: - printk("unknown chip version (%x)\n",reg); - tp->mcfg = CFG_METHOD_DEFAULT; - tp->HwIcVerUnknown = TRUE; - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - } -} - -static void -rtl8125_print_mac_version(struct rtl8125_private *tp) -{ - int i; - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) { - dprintk("Realtek PCIe 2.5GbE Family Controller mcfg = %04d\n", - rtl_chip_info[i].mcfg); - return; - } - } - - dprintk("mac_version == Unknown\n"); -} - -static void -rtl8125_tally_counter_addr_fill(struct rtl8125_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, (u64)tp->tally_paddr & (DMA_BIT_MASK(32))); -} - -static void -rtl8125_tally_counter_clear(struct rtl8125_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, ((u64)tp->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); -} - -static void -rtl8125_clear_phy_ups_reg(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - ClearEthPhyOcpBit(tp, 0xA466, BIT_0); - break; - }; - ClearEthPhyOcpBit(tp, 0xA468, BIT_3 | BIT_1); -} - -static int -rtl8125_is_ups_resume(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - return (rtl8125_mac_ocp_read(tp, 0xD42C) & BIT_8); - - return 0; -} - -static void -rtl8125_clear_ups_resume_bit(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_mac_ocp_write(tp, 0xD408, rtl8125_mac_ocp_read(tp, 0xD408) & ~(BIT_8)); -} - -static void -rtl8125_wait_phy_ups_resume(struct net_device *dev, u16 PhyState) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 TmpPhyState; - int i=0; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - do { - TmpPhyState = mdio_direct_read_phy_ocp(tp, 0xA420); - TmpPhyState &= 0x7; - mdelay(1); - i++; - } while ((i < 100) && (TmpPhyState != PhyState)); - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(i == 100); -#endif -} - -void -rtl8125_enable_now_is_oob(struct rtl8125_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | Now_is_oob); - } -} - -void -rtl8125_disable_now_is_oob(struct rtl8125_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) & ~Now_is_oob); - } -} - -static void -rtl8125_exit_oob(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 data16; - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_dash2_disable_txrx(dev); - break; - } - - if (tp->DASH) { - rtl8125_driver_stop(tp); - rtl8125_driver_start(tp); -#ifdef ENABLE_DASH_SUPPORT - DashHwInit(dev); -#endif - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_realwow_hw_init(dev); -#else - //Disable realwow function - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xC0BC, 0x00FF); - break; - } -#endif //ENABLE_REALWOW_SUPPORT - - rtl8125_nic_reset(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_disable_now_is_oob(tp); - - data16 = rtl8125_mac_ocp_read(tp, 0xE8DE) & ~BIT_14; - rtl8125_mac_ocp_write(tp, 0xE8DE, data16); - rtl8125_wait_ll_share_fifo_ready(dev); - - rtl8125_mac_ocp_write(tp, 0xC0AA, 0x07D0); - rtl8125_mac_ocp_write(tp, 0xC0A6, 0x01B5); - rtl8125_mac_ocp_write(tp, 0xC01E, 0x5555); - - rtl8125_wait_ll_share_fifo_ready(dev); - break; - } - - //wait ups resume (phy state 2) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (rtl8125_is_ups_resume(dev)) { - rtl8125_wait_phy_ups_resume(dev, 2); - rtl8125_clear_ups_resume_bit(dev); - rtl8125_clear_phy_ups_reg(dev); - } - break; - }; - - tp->phy_reg_anlpar = 0; -} - -void -rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - rtl8125_disable_cfg9346_write(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xFC38, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xFC28, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC2C, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC34, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC36, 0x0000); - mdelay(3); - rtl8125_mac_ocp_write(tp, 0xFC26, 0x0000); - break; - } -} - -static void -rtl8125_set_mac_mcu_8125a_1(struct net_device *dev) -{ - rtl8125_hw_disable_mac_mcu_bps(dev); -} - -static void -rtl8125_set_mac_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8125a_2[] = { - 0xE008, 0xE01E, 0xE02E, 0xE054, 0xE057, 0xE059, 0xE0C2, 0xE0CB, 0x9996, - 0x49D1, 0xF005, 0x49D4, 0xF10A, 0x49D8, 0xF108, 0xC00F, 0x7100, 0x209C, - 0x249C, 0xC009, 0x9900, 0xE004, 0xC006, 0x1900, 0x9900, 0xC602, 0xBE00, - 0x5A48, 0xE0C2, 0x0004, 0xE10A, 0xC60F, 0x73C4, 0x49B3, 0xF106, 0x73C2, - 0xC608, 0xB406, 0xC609, 0xFF80, 0xC605, 0xB406, 0xC605, 0xFF80, 0x0544, - 0x0568, 0xE906, 0xCDE8, 0xC724, 0xC624, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, - 0x49E0, 0xF1FE, 0x76E6, 0x486D, 0x4868, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, - 0x49E0, 0xF1FE, 0xC615, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, - 0x76E6, 0x486F, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, 0x7196, - 0xC702, 0xBF00, 0x5A44, 0xEB0E, 0x0070, 0x00C3, 0x1BC0, 0xC602, 0xBE00, - 0x0E26, 0xC602, 0xBE00, 0x0EBA, 0x1501, 0xF02A, 0x1500, 0xF15D, 0xC661, - 0x75C8, 0x49D5, 0xF00A, 0x49D6, 0xF008, 0x49D7, 0xF006, 0x49D8, 0xF004, - 0x75D2, 0x49D9, 0xF150, 0xC553, 0x77A0, 0x75C8, 0x4855, 0x4856, 0x4857, - 0x4858, 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, - 0x9DC8, 0x75D2, 0x4859, 0x9DD2, 0xC643, 0x75C0, 0x49D4, 0xF033, 0x49D0, - 0xF137, 0xE030, 0xC63A, 0x75C8, 0x49D5, 0xF00E, 0x49D6, 0xF00C, 0x49D7, - 0xF00A, 0x49D8, 0xF008, 0x75D2, 0x49D9, 0xF005, 0xC62E, 0x75C0, 0x49D7, - 0xF125, 0xC528, 0x77A0, 0xC627, 0x75C8, 0x4855, 0x4856, 0x4857, 0x4858, - 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, 0x9DC8, - 0x75D2, 0x4859, 0x9DD2, 0xC616, 0x75C0, 0x4857, 0x9DC0, 0xC613, 0x75C0, - 0x49DA, 0xF003, 0x49D0, 0xF107, 0xC60B, 0xC50E, 0x48D9, 0x9DC0, 0x4859, - 0x9DC0, 0xC608, 0xC702, 0xBF00, 0x3AE0, 0xE860, 0xB400, 0xB5D4, 0xE908, - 0xE86C, 0x1200, 0xC409, 0x6780, 0x48F1, 0x8F80, 0xC404, 0xC602, 0xBE00, - 0x10AA, 0xC010, 0xEA7C, 0xC602, 0xBE00, 0x0000 - }; - - rtl8125_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125a_2); i++) { - rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125a_2[i]); - } - - rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0540); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0E24); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x0EB8); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x3A5C); - rtl8125_mac_ocp_write(tp, 0xFC34, 0x10A8); - - rtl8125_mac_ocp_write(tp, 0xFC48, 0x007A); -} - -static void -rtl8125_set_mac_mcu_8125b_1(struct net_device *dev) -{ - rtl8125_hw_disable_mac_mcu_bps(dev); -} - -static void -rtl8125_set_mac_mcu_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8125b_2[] = { - 0xE008, 0xE013, 0xE01E, 0xE02F, 0xE035, 0xE04F, 0xE053, 0xE055, 0x740A, - 0x4846, 0x4847, 0x9C0A, 0xC607, 0x74C0, 0x48C6, 0x9CC0, 0xC602, 0xBE00, - 0x13F0, 0xE054, 0x72CA, 0x4826, 0x4827, 0x9ACA, 0xC607, 0x72C0, 0x48A6, - 0x9AC0, 0xC602, 0xBE00, 0x081C, 0xE054, 0xC60F, 0x74C4, 0x49CC, 0xF109, - 0xC60C, 0x74CA, 0x48C7, 0x9CCA, 0xC609, 0x74C0, 0x4846, 0x9CC0, 0xC602, - 0xBE00, 0x2494, 0xE092, 0xE0C0, 0xE054, 0x7420, 0x48C0, 0x9C20, 0x7444, - 0xC602, 0xBE00, 0x12DC, 0x733A, 0x21B5, 0x25BC, 0x1304, 0xF111, 0x1B12, - 0x1D2A, 0x3168, 0x3ADA, 0x31AB, 0x1A00, 0x9AC0, 0x1300, 0xF1FB, 0x7620, - 0x236E, 0x276F, 0x1A3C, 0x22A1, 0x41B5, 0x9EE2, 0x76E4, 0x486F, 0x9EE4, - 0xC602, 0xBE00, 0x4A26, 0x733A, 0x49BB, 0xC602, 0xBE00, 0x47A2, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000 - }; - - rtl8125_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125b_2); i++) { - rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125b_2[i]); - } - - rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8125_mac_ocp_write(tp, 0xFC28, 0x13E6); - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0812); - rtl8125_mac_ocp_write(tp, 0xFC2C, 0x248C); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x12DA); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x4A20); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x47A0); - - rtl8125_mac_ocp_write(tp, 0xFC48, 0x003F); -} - -static void -rtl8125_hw_mac_mcu_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->NotWrMcuPatchCode == TRUE) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_set_mac_mcu_8125a_1(dev); - break; - case CFG_METHOD_3: - rtl8125_set_mac_mcu_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_set_mac_mcu_8125b_1(dev); - break; - case CFG_METHOD_5: - rtl8125_set_mac_mcu_8125b_2(dev); - break; - } -} - -static void -rtl8125_hw_init(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - rtl8125_disable_cfg9346_write(tp); - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - break; - } - - //Disable UPS - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xD40A, rtl8125_mac_ocp_read( tp, 0xD40A) & ~(BIT_4)); - break; - } - - rtl8125_hw_mac_mcu_config(dev); - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_disable_ocp_phy_power_saving(dev); - - //Set PCIE uncorrectable error status mask pcie 0x108 - csi_tmp = rtl8125_csi_read(tp, 0x108); - csi_tmp |= BIT_20; - rtl8125_csi_write(tp, 0x108, csi_tmp); - - rtl8125_enable_cfg9346_write(tp); - rtl8125_disable_linkchg_wakeup(dev); - rtl8125_disable_cfg9346_write(tp); - rtl8125_disable_magic_packet(dev); - rtl8125_disable_d0_speedup(tp); - rtl8125_set_pci_pme(tp, 0); - if (s0_magic_packet == 1) - rtl8125_enable_magic_packet(dev); -} - -static void -rtl8125_hw_ephy_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_ephy_write(tp, 0x01, 0xA812); - rtl8125_ephy_write(tp, 0x09, 0x520C); - rtl8125_ephy_write(tp, 0x04, 0xD000); - rtl8125_ephy_write(tp, 0x0D, 0xF702); - rtl8125_ephy_write(tp, 0x0A, 0x8653); - rtl8125_ephy_write(tp, 0x06, 0x001E); - rtl8125_ephy_write(tp, 0x08, 0x3595); - rtl8125_ephy_write(tp, 0x20, 0x9455); - rtl8125_ephy_write(tp, 0x21, 0x99FF); - rtl8125_ephy_write(tp, 0x02, 0x6046); - rtl8125_ephy_write(tp, 0x29, 0xFE00); - rtl8125_ephy_write(tp, 0x23, 0xAB62); - - rtl8125_ephy_write(tp, 0x41, 0xA80C); - rtl8125_ephy_write(tp, 0x49, 0x520C); - rtl8125_ephy_write(tp, 0x44, 0xD000); - rtl8125_ephy_write(tp, 0x4D, 0xF702); - rtl8125_ephy_write(tp, 0x4A, 0x8653); - rtl8125_ephy_write(tp, 0x46, 0x001E); - rtl8125_ephy_write(tp, 0x48, 0x3595); - rtl8125_ephy_write(tp, 0x60, 0x9455); - rtl8125_ephy_write(tp, 0x61, 0x99FF); - rtl8125_ephy_write(tp, 0x42, 0x6046); - rtl8125_ephy_write(tp, 0x69, 0xFE00); - rtl8125_ephy_write(tp, 0x63, 0xAB62); - break; - case CFG_METHOD_3: - rtl8125_ephy_write(tp, 0x04, 0xD000); - rtl8125_ephy_write(tp, 0x0A, 0x8653); - rtl8125_ephy_write(tp, 0x23, 0xAB66); - rtl8125_ephy_write(tp, 0x20, 0x9455); - rtl8125_ephy_write(tp, 0x21, 0x99FF); - rtl8125_ephy_write(tp, 0x29, 0xFE04); - - rtl8125_ephy_write(tp, 0x44, 0xD000); - rtl8125_ephy_write(tp, 0x4A, 0x8653); - rtl8125_ephy_write(tp, 0x63, 0xAB66); - rtl8125_ephy_write(tp, 0x60, 0x9455); - rtl8125_ephy_write(tp, 0x61, 0x99FF); - rtl8125_ephy_write(tp, 0x69, 0xFE04); - - ClearAndSetPCIePhyBit(tp, - 0x2A, - (BIT_14 | BIT_13 | BIT_12), - (BIT_13 | BIT_12) - ); - ClearPCIePhyBit(tp, 0x19, BIT_6); - SetPCIePhyBit(tp, 0x1B, (BIT_11 | BIT_10 | BIT_9)); - ClearPCIePhyBit(tp, 0x1B, (BIT_14 | BIT_13 | BIT_12)); - rtl8125_ephy_write(tp, 0x02, 0x6042); - rtl8125_ephy_write(tp, 0x06, 0x0014); - - ClearAndSetPCIePhyBit(tp, - 0x6A, - (BIT_14 | BIT_13 | BIT_12), - (BIT_13 | BIT_12) - ); - ClearPCIePhyBit(tp, 0x59, BIT_6); - SetPCIePhyBit(tp, 0x5B, (BIT_11 | BIT_10 | BIT_9)); - ClearPCIePhyBit(tp, 0x5B, (BIT_14 | BIT_13 | BIT_12)); - rtl8125_ephy_write(tp, 0x42, 0x6042); - rtl8125_ephy_write(tp, 0x46, 0x0014); - break; - case CFG_METHOD_4: - rtl8125_ephy_write(tp, 0x06, 0x001F); - rtl8125_ephy_write(tp, 0x0A, 0xB66B); - rtl8125_ephy_write(tp, 0x01, 0xA852); - rtl8125_ephy_write(tp, 0x24, 0x0008); - rtl8125_ephy_write(tp, 0x2F, 0x6052); - rtl8125_ephy_write(tp, 0x0D, 0xF716); - rtl8125_ephy_write(tp, 0x20, 0xD477); - rtl8125_ephy_write(tp, 0x21, 0x4477); - rtl8125_ephy_write(tp, 0x22, 0x0013); - rtl8125_ephy_write(tp, 0x23, 0xBB66); - rtl8125_ephy_write(tp, 0x0B, 0xA909); - rtl8125_ephy_write(tp, 0x29, 0xFF04); - rtl8125_ephy_write(tp, 0x1B, 0x1EA0); - - rtl8125_ephy_write(tp, 0x46, 0x001F); - rtl8125_ephy_write(tp, 0x4A, 0xB66B); - rtl8125_ephy_write(tp, 0x41, 0xA84A); - rtl8125_ephy_write(tp, 0x64, 0x000C); - rtl8125_ephy_write(tp, 0x6F, 0x604A); - rtl8125_ephy_write(tp, 0x4D, 0xF716); - rtl8125_ephy_write(tp, 0x60, 0xD477); - rtl8125_ephy_write(tp, 0x61, 0x4477); - rtl8125_ephy_write(tp, 0x62, 0x0013); - rtl8125_ephy_write(tp, 0x63, 0xBB66); - rtl8125_ephy_write(tp, 0x4B, 0xA909); - rtl8125_ephy_write(tp, 0x69, 0xFF04); - rtl8125_ephy_write(tp, 0x5B, 0x1EA0); - break; - case CFG_METHOD_5: - rtl8125_ephy_write(tp, 0x0B, 0xA908); - rtl8125_ephy_write(tp, 0x22, 0x0023); - rtl8125_ephy_write(tp, 0x1E, 0x28EB); - - rtl8125_ephy_write(tp, 0x4B, 0xA908); - rtl8125_ephy_write(tp, 0x62, 0x0023); - rtl8125_ephy_write(tp, 0x5E, 0x28EB); - break; - } -} - -static int -rtl8125_check_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ram_code_ver_match = 0; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); - tp->hw_ram_code_ver = mdio_direct_read_phy_ocp(tp, 0xA438); - break; - default: - tp->hw_ram_code_ver = ~0; - break; - } - - if ( tp->hw_ram_code_ver == tp->sw_ram_code_ver) { - ram_code_ver_match = 1; - tp->HwHasWrRamCodeToMicroP = TRUE; - } - - return ram_code_ver_match; -} - -static void -rtl8125_write_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); - mdio_direct_write_phy_ocp(tp, 0xA438, tp->sw_ram_code_ver); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - } -} - -static void -rtl8125_acquire_phy_mcu_patch_key_lock(struct rtl8125_private *tp) -{ - u16 PatchKey; - - switch (tp->mcfg) { - case CFG_METHOD_2: - PatchKey = 0x8600; - break; - case CFG_METHOD_3: - PatchKey = 0x8601; - break; - case CFG_METHOD_4: - PatchKey = 0x3700; - break; - case CFG_METHOD_5: - PatchKey = 0x3701; - break; - default: - return; - } - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, PatchKey); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xB82E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); -} - -static void -rtl8125_release_phy_mcu_patch_key_lock(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - ClearEthPhyOcpBit(tp, 0xB82E, BIT_0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - break; - default: - break; - } -} - -static bool -rtl8125_wait_phy_mcu_patch_request_ready(struct rtl8125_private *tp) -{ - u16 gphy_val; - u16 WaitCount; - bool bSuccess = TRUE; - - WaitCount = 0; - do { - gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); - gphy_val &= BIT_6; - udelay(100); - WaitCount++; - } while(gphy_val != BIT_6 && WaitCount < 1000); - - if (gphy_val != BIT_6 && WaitCount == 1000) bSuccess = FALSE; - - if (!bSuccess) - dprintk("rtl8125_wait_phy_mcu_patch_request_ready fail.\n"); - - return bSuccess; -} - -bool -rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp) -{ - SetEthPhyOcpBit(tp, 0xB820, BIT_4); - - return rtl8125_wait_phy_mcu_patch_request_ready(tp); -} - -bool -rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp) -{ - ClearEthPhyOcpBit(tp, 0xB820, BIT_4); - - return rtl8125_wait_phy_mcu_patch_request_ready(tp); -} - -static void -rtl8125_set_phy_mcu_ram_code(struct net_device *dev, const u16 *ramcode, u16 codesize) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 i; - u16 addr; - u16 val; - - if (ramcode == NULL || codesize % 2) { - goto out; - } - - for (i = 0; i < codesize; i += 2) { - addr = ramcode[i]; - val = ramcode[i + 1]; - if (addr == 0xFFFF && val == 0xFFFF) { - break; - } - mdio_direct_write_phy_ocp(tp, addr, val); - } - -out: - return; -} - -static void -rtl8125_real_set_phy_mcu_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_acquire_phy_mcu_patch_key_lock(tp); - - - SetEthPhyOcpBit(tp, 0xB820, BIT_7); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8021); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x802f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x803d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8042); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a50); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a6c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd019); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a84); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8970); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c07); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcf09); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd705); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xceff); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf0a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1213); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8401); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8580); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1253); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd181); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4018); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd706); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2c59); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x804d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc60f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc605); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10fd); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10f4); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1252); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1206); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a78); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a60); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a4f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3f00); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8066); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x807c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8089); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80b2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80c2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62db); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x655c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x653c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0346); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8208); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x609d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x607d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0221); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ce); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0169); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00a6); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000d); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x029f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x007f); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8017); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8029); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8054); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x805a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9430); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9480); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb408); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd120); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd057); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9906); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0567); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb94); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8406); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8dff); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0773); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4045); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07ec); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fa7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0481); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8220); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x078e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd150); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6121); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61a2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6223); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0537); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0642); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0686); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0788); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x047b); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x065c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0769); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0565); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x06f9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ff); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8593); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x85a5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfb0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86d7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xda02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdd02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfd0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86dd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf2f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2cac); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0286); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x65af); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x212b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x022c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86b6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf21); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cd1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8710); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8716); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x871f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x871c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8728); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8725); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbad); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x281c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4902); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2e02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4602); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4f02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf35); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7ff8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfaef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x69bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ec); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x96fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf8fa); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef69); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf802); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef96); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfefc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0420); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x53b5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb9b5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb03a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbac8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb13a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xba77); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2677); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2640); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x28bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa430); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2f71); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x20d9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2109); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x34e7); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000f); - - - ClearEthPhyOcpBit(tp, 0xB820, BIT_7); - - - rtl8125_release_phy_mcu_patch_key_lock(tp); -} - -static void -rtl8125_set_phy_mcu_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125a_1(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_real_set_phy_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_acquire_phy_mcu_patch_key_lock(tp); - - - SetEthPhyOcpBit(tp, 0xB820, BIT_7); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8093); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8097); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x809d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80aa); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x607b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x42da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x615b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa410); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4779); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa420); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4559); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf023); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac44); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa440); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4339); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac88); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa480); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4119); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf001); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fac); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc48f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x141b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x121a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0898); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd18a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa804); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8804); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x053b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0648); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc520); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa201); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x252d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd708); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0307); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1645); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0647); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x053a); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0896); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xff00); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8015); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xad02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02d7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ed); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x008f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x008d); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00eb); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8018); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8055); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8072); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa380); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4085); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd158); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd04d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8380); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd10d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa220); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd130); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbb80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd074); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x604b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa90c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd116); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd119); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6241); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x63e2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6583); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf054); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d50); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf021); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d60); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d70); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ff4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07fb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f6f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f4e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f2d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1f5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd049); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ec); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ea); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x06a9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x078a); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d2); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x067f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0665); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00fc); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x45af); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xee82); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf900); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf03); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7f8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa601); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x58f0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x37a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae16); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa185); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa188); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8902); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03b3); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); - - - ClearEthPhyOcpBit(tp, 0xB820, BIT_7); - - - rtl8125_release_phy_mcu_patch_key_lock(tp); -} - -static void -rtl8125_set_phy_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125a_2(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static const u16 phy_mcu_ram_code_8125b_1[] = { - 0xa436, 0x8024, 0xa438, 0x3700, 0xa436, 0xB82E, 0xa438, 0x0001, - 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x8025, 0xa438, 0x1800, 0xa438, 0x803a, - 0xa438, 0x1800, 0xa438, 0x8044, 0xa438, 0x1800, 0xa438, 0x8083, - 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0x1800, 0xa438, 0x808d, - 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0xd712, 0xa438, 0x4077, - 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, 0xa438, 0x6099, - 0xa438, 0x7f44, 0xa438, 0x1800, 0xa438, 0x1a14, 0xa438, 0x9040, - 0xa438, 0x9201, 0xa438, 0x1800, 0xa438, 0x1b1a, 0xa438, 0xd71e, - 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, 0xa438, 0x3ce5, - 0xa438, 0x1afb, 0xa438, 0x1800, 0xa438, 0x1b00, 0xa438, 0xd712, - 0xa438, 0x4077, 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, - 0xa438, 0x60b9, 0xa438, 0x2421, 0xa438, 0x1c17, 0xa438, 0x1800, - 0xa438, 0x1a14, 0xa438, 0x9040, 0xa438, 0x1800, 0xa438, 0x1c2c, - 0xa438, 0xd71e, 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, - 0xa438, 0x3ce5, 0xa438, 0x1c0f, 0xa438, 0x1800, 0xa438, 0x1c13, - 0xa438, 0xd702, 0xa438, 0xd501, 0xa438, 0x6072, 0xa438, 0x8401, - 0xa438, 0xf002, 0xa438, 0xa401, 0xa438, 0x1000, 0xa438, 0x146e, - 0xa438, 0x1800, 0xa438, 0x0b77, 0xa438, 0xd703, 0xa438, 0x665d, - 0xa438, 0x653e, 0xa438, 0x641f, 0xa438, 0xd700, 0xa438, 0x62c4, - 0xa438, 0x6185, 0xa438, 0x6066, 0xa438, 0x1800, 0xa438, 0x165a, - 0xa438, 0xc101, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, - 0xa438, 0xd700, 0xa438, 0x7fa6, 0xa438, 0x1800, 0xa438, 0x807d, - 0xa438, 0xc102, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, - 0xa438, 0xd700, 0xa438, 0x2569, 0xa438, 0x8058, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc104, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd700, 0xa438, 0x7fa4, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc120, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbf, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc140, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbe, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc180, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbd, 0xa438, 0xc100, - 0xa438, 0xcb00, 0xa438, 0xd708, 0xa438, 0x6018, 0xa438, 0x1800, - 0xa438, 0x165a, 0xa438, 0x1000, 0xa438, 0x14f6, 0xa438, 0xd014, - 0xa438, 0xd1e3, 0xa438, 0x1000, 0xa438, 0x1356, 0xa438, 0xd705, - 0xa438, 0x5fbe, 0xa438, 0x1800, 0xa438, 0x1559, 0xa436, 0xA026, - 0xa438, 0xffff, 0xa436, 0xA024, 0xa438, 0xffff, 0xa436, 0xA022, - 0xa438, 0xffff, 0xa436, 0xA020, 0xa438, 0x1557, 0xa436, 0xA006, - 0xa438, 0x1677, 0xa436, 0xA004, 0xa438, 0x0b75, 0xa436, 0xA002, - 0xa438, 0x1c17, 0xa436, 0xA000, 0xa438, 0x1b04, 0xa436, 0xA008, - 0xa438, 0x1f00, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x817f, 0xa438, 0x1800, 0xa438, 0x82ab, - 0xa438, 0x1800, 0xa438, 0x83f8, 0xa438, 0x1800, 0xa438, 0x8444, - 0xa438, 0x1800, 0xa438, 0x8454, 0xa438, 0x1800, 0xa438, 0x8459, - 0xa438, 0x1800, 0xa438, 0x8465, 0xa438, 0xcb11, 0xa438, 0xa50c, - 0xa438, 0x8310, 0xa438, 0xd701, 0xa438, 0x4076, 0xa438, 0x0c03, - 0xa438, 0x0903, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x1000, 0xa438, 0x0a4d, - 0xa438, 0xcb12, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f84, 0xa438, 0xd102, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd701, - 0xa438, 0x60f3, 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd410, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb13, - 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, - 0xa438, 0xa00a, 0xa438, 0xa910, 0xa438, 0xa780, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x6255, 0xa438, 0xd700, 0xa438, 0x5f74, 0xa438, 0x6326, - 0xa438, 0xd702, 0xa438, 0x5f07, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0xffe2, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5fab, 0xa438, 0xba08, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8b, 0xa438, 0x9a08, - 0xa438, 0x800a, 0xa438, 0xd702, 0xa438, 0x6535, 0xa438, 0xd40d, - 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb14, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa00a, - 0xa438, 0xa780, 0xa438, 0xd14a, 0xa438, 0xd048, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x6206, - 0xa438, 0xd702, 0xa438, 0x5f47, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0x1800, 0xa438, 0x8064, 0xa438, 0x800a, - 0xa438, 0xd40e, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xd701, 0xa438, 0x6073, 0xa438, 0xd701, - 0xa438, 0x4216, 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8004, 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8001, 0xa438, 0xd120, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x8504, - 0xa438, 0xcb21, 0xa438, 0xa301, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, 0xa438, 0xd704, - 0xa438, 0x40e0, 0xa438, 0xd196, 0xa438, 0xd04d, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb22, - 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, - 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8910, 0xa438, 0x8720, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb23, - 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, - 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x5dee, 0xa438, 0xcb24, 0xa438, 0x8f1f, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f6e, 0xa438, 0xa111, - 0xa438, 0xa215, 0xa438, 0xa401, 0xa438, 0x8404, 0xa438, 0xa720, - 0xa438, 0xcb25, 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, - 0xa438, 0x9503, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, - 0xa438, 0x0b86, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xcb26, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x8205, - 0xa438, 0x8404, 0xa438, 0xcb27, 0xa438, 0xd404, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0xa104, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8104, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa120, - 0xa438, 0xaa0f, 0xa438, 0x8110, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0xa00a, 0xa438, 0xd193, 0xa438, 0xd046, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb28, - 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa8, 0xa438, 0x8110, 0xa438, 0x8284, 0xa438, 0xa404, - 0xa438, 0x800a, 0xa438, 0x8710, 0xa438, 0xb804, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, - 0xa438, 0xcb29, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, - 0xa438, 0xcb2a, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0xa00a, 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8149, - 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8151, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, - 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, - 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8404, - 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, - 0xa438, 0x0433, 0xa438, 0xcb15, 0xa438, 0xa508, 0xa438, 0xd700, - 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, - 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, - 0xa438, 0x1000, 0xa438, 0x0a4d, 0xa438, 0xa301, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, - 0xa438, 0xd704, 0xa438, 0x40e0, 0xa438, 0xd115, 0xa438, 0xd04f, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb16, - 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, - 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8720, 0xa438, 0xd17a, - 0xa438, 0xd04c, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb17, - 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, - 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x61ce, 0xa438, 0xd700, 0xa438, 0x5db4, 0xa438, 0xcb18, - 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, - 0xa438, 0xa720, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xffd6, 0xa438, 0x8f1f, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f8e, 0xa438, 0xa131, - 0xa438, 0xaa0f, 0xa438, 0xa2d5, 0xa438, 0xa407, 0xa438, 0xa720, - 0xa438, 0x8310, 0xa438, 0xa308, 0xa438, 0x8308, 0xa438, 0xcb19, - 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, - 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, 0xa438, 0x0b86, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, - 0xa438, 0xcb1a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x82c5, 0xa438, 0xa404, - 0xa438, 0x8402, 0xa438, 0xb804, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, 0xa438, 0xcb1b, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f85, - 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, 0xa438, 0xcb1c, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0xa110, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0x8402, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa8, 0xa438, 0xcb1d, 0xa438, 0xa180, 0xa438, 0xa402, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, - 0xa438, 0xa220, 0xa438, 0xd1f5, 0xa438, 0xd049, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8221, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xb920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fa3, - 0xa438, 0xa504, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa00a, 0xa438, 0x8190, - 0xa438, 0x82a4, 0xa438, 0x8402, 0xa438, 0xa404, 0xa438, 0xb808, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7fa3, - 0xa438, 0x9808, 0xa438, 0xcb2b, 0xa438, 0xcb2c, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f84, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0xa780, 0xa438, 0xcb2d, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f94, 0xa438, 0x6208, - 0xa438, 0xd702, 0xa438, 0x5f27, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xffe9, 0xa438, 0xcb2e, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa406, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, - 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x827d, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, - 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, - 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8406, - 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, - 0xa438, 0x0433, 0xa438, 0xcb30, 0xa438, 0x8380, 0xa438, 0xcb31, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f86, - 0xa438, 0x9308, 0xa438, 0xb204, 0xa438, 0xb301, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x5fa2, 0xa438, 0xb302, - 0xa438, 0x9204, 0xa438, 0xcb32, 0xa438, 0xd408, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd141, 0xa438, 0xd043, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd704, - 0xa438, 0x4ccc, 0xa438, 0xd700, 0xa438, 0x4c81, 0xa438, 0xd702, - 0xa438, 0x609e, 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0xf003, - 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, - 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, 0xa438, 0x0c1f, - 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x8710, - 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, - 0xa438, 0xa203, 0xa438, 0x8120, 0xa438, 0x8a0f, 0xa438, 0xa111, - 0xa438, 0x8204, 0xa438, 0xa140, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8140, 0xa438, 0xd17a, 0xa438, 0xd04b, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xa204, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, - 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0xd404, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0x8101, - 0xa438, 0x8201, 0xa438, 0xa104, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8104, 0xa438, 0xa120, 0xa438, 0xaa0f, 0xa438, 0x8110, - 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0xa00a, 0xa438, 0xd193, - 0xa438, 0xd047, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fa8, 0xa438, 0xa180, 0xa438, 0xd13d, - 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xf024, 0xa438, 0xa710, 0xa438, 0xa00a, - 0xa438, 0x8190, 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, - 0xa438, 0x8710, 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0x800a, - 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0x8406, 0xa438, 0xd700, - 0xa438, 0x4121, 0xa438, 0xd701, 0xa438, 0x60f3, 0xa438, 0xd1e5, - 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x8710, 0xa438, 0xa00a, 0xa438, 0x8190, - 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xcb33, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, - 0xa438, 0x9820, 0xa438, 0xcb34, 0xa438, 0xa00a, 0xa438, 0xa190, - 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fa9, 0xa438, 0xd701, 0xa438, 0x6853, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0xcb35, - 0xa438, 0xd407, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8110, - 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa00a, 0xa438, 0xd704, - 0xa438, 0x4215, 0xa438, 0xa304, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb8, 0xa438, 0xd1c3, 0xa438, 0xd043, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x8304, 0xa438, 0xd700, 0xa438, 0x4109, 0xa438, 0xf01e, - 0xa438, 0xcb36, 0xa438, 0xd412, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd700, 0xa438, 0x6309, 0xa438, 0xd702, 0xa438, 0x42c7, - 0xa438, 0x800a, 0xa438, 0x8180, 0xa438, 0x8280, 0xa438, 0x8404, - 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, - 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, - 0xa438, 0x0c03, 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xcc55, 0xa438, 0xcb37, - 0xa438, 0xa00a, 0xa438, 0xa190, 0xa438, 0xa2a4, 0xa438, 0xa404, - 0xa438, 0xd700, 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd13d, - 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa9, 0xa438, 0xd702, 0xa438, 0x5f71, 0xa438, 0xcb38, - 0xa438, 0x8224, 0xa438, 0xa288, 0xa438, 0x8180, 0xa438, 0xa110, - 0xa438, 0xa404, 0xa438, 0x800a, 0xa438, 0xd700, 0xa438, 0x6041, - 0xa438, 0x8402, 0xa438, 0xd415, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb39, 0xa438, 0xa00a, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xd700, - 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd17a, 0xa438, 0xd047, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x1800, 0xa438, 0x0560, 0xa438, 0xa111, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0xd3f5, - 0xa438, 0xd219, 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, - 0xa438, 0x5fa5, 0xa438, 0xa215, 0xa438, 0xd30e, 0xa438, 0xd21a, - 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x63e9, - 0xa438, 0xd708, 0xa438, 0x5f65, 0xa438, 0xd708, 0xa438, 0x7f36, - 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8004, - 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8001, - 0xa438, 0xd708, 0xa438, 0x4098, 0xa438, 0xd102, 0xa438, 0x9401, - 0xa438, 0xf003, 0xa438, 0xd103, 0xa438, 0xb401, 0xa438, 0x1000, - 0xa438, 0x0c27, 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0c35, - 0xa438, 0x8108, 0xa438, 0x8110, 0xa438, 0x8294, 0xa438, 0xa202, - 0xa438, 0x1800, 0xa438, 0x0bdb, 0xa438, 0xd39c, 0xa438, 0xd210, - 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x5fa5, - 0xa438, 0xd39c, 0xa438, 0xd210, 0xa438, 0x1000, 0xa438, 0x0c31, - 0xa438, 0xd708, 0xa438, 0x5fa5, 0xa438, 0x1000, 0xa438, 0x0c31, - 0xa438, 0xd708, 0xa438, 0x29b5, 0xa438, 0x840e, 0xa438, 0xd708, - 0xa438, 0x5f4a, 0xa438, 0x0c1f, 0xa438, 0x1014, 0xa438, 0x1000, - 0xa438, 0x0c31, 0xa438, 0xd709, 0xa438, 0x7fa4, 0xa438, 0x901f, - 0xa438, 0x1800, 0xa438, 0x0c23, 0xa438, 0xcb43, 0xa438, 0xa508, - 0xa438, 0xd701, 0xa438, 0x3699, 0xa438, 0x844a, 0xa438, 0xa504, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xa00a, - 0xa438, 0xd700, 0xa438, 0x2109, 0xa438, 0x05ea, 0xa438, 0xa402, - 0xa438, 0x1800, 0xa438, 0x05ea, 0xa438, 0xcb90, 0xa438, 0x0cf0, - 0xa438, 0x0ca0, 0xa438, 0x1800, 0xa438, 0x06db, 0xa438, 0xd1ff, - 0xa438, 0xd052, 0xa438, 0xa508, 0xa438, 0x8718, 0xa438, 0xa00a, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0x0cf0, - 0xa438, 0x0c50, 0xa438, 0x1800, 0xa438, 0x09ef, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd704, 0xa438, 0x2e70, 0xa438, 0x06da, - 0xa438, 0xd700, 0xa438, 0x5f55, 0xa438, 0xa90c, 0xa438, 0x1800, - 0xa438, 0x0645, 0xa436, 0xA10E, 0xa438, 0x0644, 0xa436, 0xA10C, - 0xa438, 0x09e9, 0xa436, 0xA10A, 0xa438, 0x06da, 0xa436, 0xA108, - 0xa438, 0x05e1, 0xa436, 0xA106, 0xa438, 0x0be4, 0xa436, 0xA104, - 0xa438, 0x0435, 0xa436, 0xA102, 0xa438, 0x0141, 0xa436, 0xA100, - 0xa438, 0x026d, 0xa436, 0xA110, 0xa438, 0x00ff, 0xa436, 0xb87c, - 0xa438, 0x85fe, 0xa436, 0xb87e, 0xa438, 0xaf86, 0xa438, 0x16af, - 0xa438, 0x8699, 0xa438, 0xaf86, 0xa438, 0xe5af, 0xa438, 0x86f9, - 0xa438, 0xaf87, 0xa438, 0x7aaf, 0xa438, 0x883a, 0xa438, 0xaf88, - 0xa438, 0x58af, 0xa438, 0x8b6c, 0xa438, 0xd48b, 0xa438, 0x7c02, - 0xa438, 0x8644, 0xa438, 0x2c00, 0xa438, 0x503c, 0xa438, 0xffd6, - 0xa438, 0xac27, 0xa438, 0x18e1, 0xa438, 0x82fe, 0xa438, 0xad28, - 0xa438, 0x0cd4, 0xa438, 0x8b84, 0xa438, 0x0286, 0xa438, 0x442c, - 0xa438, 0x003c, 0xa438, 0xac27, 0xa438, 0x06ee, 0xa438, 0x8299, - 0xa438, 0x01ae, 0xa438, 0x04ee, 0xa438, 0x8299, 0xa438, 0x00af, - 0xa438, 0x23dc, 0xa438, 0xf9fa, 0xa438, 0xcefa, 0xa438, 0xfbef, - 0xa438, 0x79fb, 0xa438, 0xc4bf, 0xa438, 0x8b76, 0xa438, 0x026c, - 0xa438, 0x6dac, 0xa438, 0x2804, 0xa438, 0xd203, 0xa438, 0xae02, - 0xa438, 0xd201, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, - 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x648a, - 0xa438, 0x0002, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, - 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x7402, - 0xa438, 0x72cd, 0xa438, 0xac50, 0xa438, 0x02ef, 0xa438, 0x643a, - 0xa438, 0x019f, 0xa438, 0xe4ef, 0xa438, 0x4678, 0xa438, 0x03ac, - 0xa438, 0x2002, 0xa438, 0xae02, 0xa438, 0xd0ff, 0xa438, 0xffef, - 0xa438, 0x97ff, 0xa438, 0xfec6, 0xa438, 0xfefd, 0xa438, 0x041f, - 0xa438, 0x771f, 0xa438, 0x221c, 0xa438, 0x450d, 0xa438, 0x481f, - 0xa438, 0x00ac, 0xa438, 0x7f04, 0xa438, 0x1a94, 0xa438, 0xae08, - 0xa438, 0x1a94, 0xa438, 0xac7f, 0xa438, 0x03d7, 0xa438, 0x0100, - 0xa438, 0xef46, 0xa438, 0x0d48, 0xa438, 0x1f00, 0xa438, 0x1c45, - 0xa438, 0xef69, 0xa438, 0xef57, 0xa438, 0xef74, 0xa438, 0x0272, - 0xa438, 0xe8a7, 0xa438, 0xffff, 0xa438, 0x0d1a, 0xa438, 0x941b, - 0xa438, 0x979e, 0xa438, 0x072d, 0xa438, 0x0100, 0xa438, 0x1a64, - 0xa438, 0xef76, 0xa438, 0xef97, 0xa438, 0x0d98, 0xa438, 0xd400, - 0xa438, 0xff1d, 0xa438, 0x941a, 0xa438, 0x89cf, 0xa438, 0x1a75, - 0xa438, 0xaf74, 0xa438, 0xf9bf, 0xa438, 0x8b79, 0xa438, 0x026c, - 0xa438, 0x6da1, 0xa438, 0x0005, 0xa438, 0xe180, 0xa438, 0xa0ae, - 0xa438, 0x03e1, 0xa438, 0x80a1, 0xa438, 0xaf26, 0xa438, 0x9aac, - 0xa438, 0x284d, 0xa438, 0xe08f, 0xa438, 0xffef, 0xa438, 0x10c0, - 0xa438, 0xe08f, 0xa438, 0xfe10, 0xa438, 0x1b08, 0xa438, 0xa000, - 0xa438, 0x04c8, 0xa438, 0xaf40, 0xa438, 0x67c8, 0xa438, 0xbf8b, - 0xa438, 0x8c02, 0xa438, 0x6c4e, 0xa438, 0xc4bf, 0xa438, 0x8b8f, - 0xa438, 0x026c, 0xa438, 0x6def, 0xa438, 0x74e0, 0xa438, 0x830c, - 0xa438, 0xad20, 0xa438, 0x0302, 0xa438, 0x74ac, 0xa438, 0xccef, - 0xa438, 0x971b, 0xa438, 0x76ad, 0xa438, 0x5f02, 0xa438, 0xae13, - 0xa438, 0xef69, 0xa438, 0xef30, 0xa438, 0x1b32, 0xa438, 0xc4ef, - 0xa438, 0x46e4, 0xa438, 0x8ffb, 0xa438, 0xe58f, 0xa438, 0xfce7, - 0xa438, 0x8ffd, 0xa438, 0xcc10, 0xa438, 0x11ae, 0xa438, 0xb8d1, - 0xa438, 0x00a1, 0xa438, 0x1f03, 0xa438, 0xaf40, 0xa438, 0x4fbf, - 0xa438, 0x8b8c, 0xa438, 0x026c, 0xa438, 0x4ec4, 0xa438, 0xbf8b, - 0xa438, 0x8f02, 0xa438, 0x6c6d, 0xa438, 0xef74, 0xa438, 0xe083, - 0xa438, 0x0cad, 0xa438, 0x2003, 0xa438, 0x0274, 0xa438, 0xaccc, - 0xa438, 0xef97, 0xa438, 0x1b76, 0xa438, 0xad5f, 0xa438, 0x02ae, - 0xa438, 0x04ef, 0xa438, 0x69ef, 0xa438, 0x3111, 0xa438, 0xaed1, - 0xa438, 0x0287, 0xa438, 0x80af, 0xa438, 0x2293, 0xa438, 0xf8f9, - 0xa438, 0xfafb, 0xa438, 0xef59, 0xa438, 0xe080, 0xa438, 0x13ad, - 0xa438, 0x252f, 0xa438, 0xbf88, 0xa438, 0x2802, 0xa438, 0x6c6d, - 0xa438, 0xef64, 0xa438, 0x1f44, 0xa438, 0xe18f, 0xa438, 0xb91b, - 0xa438, 0x64ad, 0xa438, 0x4f1d, 0xa438, 0xd688, 0xa438, 0x2bd7, - 0xa438, 0x882e, 0xa438, 0x0274, 0xa438, 0x73ad, 0xa438, 0x5008, - 0xa438, 0xbf88, 0xa438, 0x3102, 0xa438, 0x737c, 0xa438, 0xae03, - 0xa438, 0x0287, 0xa438, 0xd0bf, 0xa438, 0x882b, 0xa438, 0x0273, - 0xa438, 0x73e0, 0xa438, 0x824c, 0xa438, 0xf621, 0xa438, 0xe482, - 0xa438, 0x4cbf, 0xa438, 0x8834, 0xa438, 0x0273, 0xa438, 0x7cef, - 0xa438, 0x95ff, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, - 0xa438, 0xfafb, 0xa438, 0xef79, 0xa438, 0xbf88, 0xa438, 0x1f02, - 0xa438, 0x737c, 0xa438, 0x1f22, 0xa438, 0xac32, 0xa438, 0x31ef, - 0xa438, 0x12bf, 0xa438, 0x8822, 0xa438, 0x026c, 0xa438, 0x4ed6, - 0xa438, 0x8fba, 0xa438, 0x1f33, 0xa438, 0xac3c, 0xa438, 0x1eef, - 0xa438, 0x13bf, 0xa438, 0x8837, 0xa438, 0x026c, 0xa438, 0x4eef, - 0xa438, 0x96d8, 0xa438, 0x19d9, 0xa438, 0xbf88, 0xa438, 0x2502, - 0xa438, 0x6c4e, 0xa438, 0xbf88, 0xa438, 0x2502, 0xa438, 0x6c4e, - 0xa438, 0x1616, 0xa438, 0x13ae, 0xa438, 0xdf12, 0xa438, 0xaecc, - 0xa438, 0xbf88, 0xa438, 0x1f02, 0xa438, 0x7373, 0xa438, 0xef97, - 0xa438, 0xfffe, 0xa438, 0xfdfc, 0xa438, 0x0466, 0xa438, 0xac88, - 0xa438, 0x54ac, 0xa438, 0x88f0, 0xa438, 0xac8a, 0xa438, 0x92ac, - 0xa438, 0xbadd, 0xa438, 0xac6c, 0xa438, 0xeeac, 0xa438, 0x6cff, - 0xa438, 0xad02, 0xa438, 0x99ac, 0xa438, 0x0030, 0xa438, 0xac88, - 0xa438, 0xd4c3, 0xa438, 0x5000, 0xa438, 0x0000, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x00b4, 0xa438, 0xecee, - 0xa438, 0x8298, 0xa438, 0x00af, 0xa438, 0x1412, 0xa438, 0xf8bf, - 0xa438, 0x8b5d, 0xa438, 0x026c, 0xa438, 0x6d58, 0xa438, 0x03e1, - 0xa438, 0x8fb8, 0xa438, 0x2901, 0xa438, 0xe58f, 0xa438, 0xb8a0, - 0xa438, 0x0049, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x02e5, - 0xa438, 0x8303, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, - 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, - 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, - 0xa438, 0xf728, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0xf628, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6002, - 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, - 0xa438, 0xaf89, 0xa438, 0x96a0, 0xa438, 0x0149, 0xa438, 0xef47, - 0xa438, 0xe483, 0xa438, 0x04e5, 0xa438, 0x8305, 0xa438, 0xbfc2, - 0xa438, 0x5f1a, 0xa438, 0x95f7, 0xa438, 0x05ee, 0xa438, 0xffd2, - 0xa438, 0x00d8, 0xa438, 0xf605, 0xa438, 0x1f11, 0xa438, 0xef60, - 0xa438, 0xbf8b, 0xa438, 0x3002, 0xa438, 0x6c4e, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c6d, 0xa438, 0xf729, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0xf629, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0x0c64, 0xa438, 0xef46, - 0xa438, 0xbf8b, 0xa438, 0x6302, 0xa438, 0x6c4e, 0xa438, 0x0289, - 0xa438, 0x9902, 0xa438, 0x3920, 0xa438, 0xaf89, 0xa438, 0x96a0, - 0xa438, 0x0249, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x06e5, - 0xa438, 0x8307, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, - 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, - 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, - 0xa438, 0xf72a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0xf62a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6602, - 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, - 0xa438, 0xaf89, 0xa438, 0x96ef, 0xa438, 0x47e4, 0xa438, 0x8308, - 0xa438, 0xe583, 0xa438, 0x09bf, 0xa438, 0xc25f, 0xa438, 0x1a95, - 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xd8f6, - 0xa438, 0x051f, 0xa438, 0x11ef, 0xa438, 0x60bf, 0xa438, 0x8b30, - 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x6df7, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x4ef6, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x4e0c, 0xa438, 0x64ef, 0xa438, 0x46bf, 0xa438, 0x8b69, - 0xa438, 0x026c, 0xa438, 0x4e02, 0xa438, 0x8999, 0xa438, 0x0239, - 0xa438, 0x20af, 0xa438, 0x8996, 0xa438, 0xaf39, 0xa438, 0x1ef8, - 0xa438, 0xf9fa, 0xa438, 0xe08f, 0xa438, 0xb838, 0xa438, 0x02ad, - 0xa438, 0x2702, 0xa438, 0xae03, 0xa438, 0xaf8b, 0xa438, 0x201f, - 0xa438, 0x66ef, 0xa438, 0x65bf, 0xa438, 0xc21f, 0xa438, 0x1a96, - 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdaf6, - 0xa438, 0x05bf, 0xa438, 0xc22f, 0xa438, 0x1a96, 0xa438, 0xf705, - 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdbf6, 0xa438, 0x05ef, - 0xa438, 0x021f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b3c, - 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021b, 0xa438, 0x031f, - 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b36, 0xa438, 0x026c, - 0xa438, 0x4eef, 0xa438, 0x021a, 0xa438, 0x031f, 0xa438, 0x110d, - 0xa438, 0x42bf, 0xa438, 0x8b39, 0xa438, 0x026c, 0xa438, 0x4ebf, - 0xa438, 0xc23f, 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, - 0xa438, 0xd200, 0xa438, 0xdaf6, 0xa438, 0x05bf, 0xa438, 0xc24f, - 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, - 0xa438, 0xdbf6, 0xa438, 0x05ef, 0xa438, 0x021f, 0xa438, 0x110d, - 0xa438, 0x42bf, 0xa438, 0x8b45, 0xa438, 0x026c, 0xa438, 0x4eef, - 0xa438, 0x021b, 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, - 0xa438, 0x8b3f, 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021a, - 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b42, - 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x56d0, 0xa438, 0x201f, - 0xa438, 0x11bf, 0xa438, 0x8b4e, 0xa438, 0x026c, 0xa438, 0x4ebf, - 0xa438, 0x8b48, 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b4b, - 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8578, 0xa438, 0xef03, - 0xa438, 0x480a, 0xa438, 0x2805, 0xa438, 0xef20, 0xa438, 0x1b01, - 0xa438, 0xad27, 0xa438, 0x3f1f, 0xa438, 0x44e0, 0xa438, 0x8560, - 0xa438, 0xe185, 0xa438, 0x61bf, 0xa438, 0x8b51, 0xa438, 0x026c, - 0xa438, 0x4ee0, 0xa438, 0x8566, 0xa438, 0xe185, 0xa438, 0x67bf, - 0xa438, 0x8b54, 0xa438, 0x026c, 0xa438, 0x4ee0, 0xa438, 0x856c, - 0xa438, 0xe185, 0xa438, 0x6dbf, 0xa438, 0x8b57, 0xa438, 0x026c, - 0xa438, 0x4ee0, 0xa438, 0x8572, 0xa438, 0xe185, 0xa438, 0x73bf, - 0xa438, 0x8b5a, 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8fb8, - 0xa438, 0x5900, 0xa438, 0xf728, 0xa438, 0xe58f, 0xa438, 0xb8af, - 0xa438, 0x8b2c, 0xa438, 0xe185, 0xa438, 0x791b, 0xa438, 0x21ad, - 0xa438, 0x373e, 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x62e1, - 0xa438, 0x8563, 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, - 0xa438, 0xe085, 0xa438, 0x68e1, 0xa438, 0x8569, 0xa438, 0xbf8b, - 0xa438, 0x5402, 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x6ee1, - 0xa438, 0x856f, 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, - 0xa438, 0xe085, 0xa438, 0x74e1, 0xa438, 0x8575, 0xa438, 0xbf8b, - 0xa438, 0x5a02, 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, - 0xa438, 0x00f7, 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae4a, - 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x64e1, 0xa438, 0x8565, - 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, 0xa438, 0xe085, - 0xa438, 0x6ae1, 0xa438, 0x856b, 0xa438, 0xbf8b, 0xa438, 0x5402, - 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x70e1, 0xa438, 0x8571, - 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, 0xa438, 0xe085, - 0xa438, 0x76e1, 0xa438, 0x8577, 0xa438, 0xbf8b, 0xa438, 0x5a02, - 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, 0xa438, 0x00f7, - 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae0c, 0xa438, 0xe18f, - 0xa438, 0xb839, 0xa438, 0x04ac, 0xa438, 0x2f04, 0xa438, 0xee8f, - 0xa438, 0xb800, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf0ac, - 0xa438, 0x8efc, 0xa438, 0xac8c, 0xa438, 0xf0ac, 0xa438, 0xfaf0, - 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xf6f0, 0xa438, 0xad00, - 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacfc, 0xa438, 0xf0ac, - 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, 0xa438, 0xf0f0, - 0xa438, 0xacb0, 0xa438, 0xf0ac, 0xa438, 0xaef0, 0xa438, 0xacac, - 0xa438, 0xf0ac, 0xa438, 0xaaf0, 0xa438, 0xacee, 0xa438, 0xf0b0, - 0xa438, 0x24f0, 0xa438, 0xb0a4, 0xa438, 0xf0b1, 0xa438, 0x24f0, - 0xa438, 0xb1a4, 0xa438, 0xee8f, 0xa438, 0xb800, 0xa438, 0xd400, - 0xa438, 0x00af, 0xa438, 0x3976, 0xa438, 0x66ac, 0xa438, 0xeabb, - 0xa438, 0xa430, 0xa438, 0x6e50, 0xa438, 0x6e53, 0xa438, 0x6e56, - 0xa438, 0x6e59, 0xa438, 0x6e5c, 0xa438, 0x6e5f, 0xa438, 0x6e62, - 0xa438, 0x6e65, 0xa438, 0xd9ac, 0xa438, 0x70f0, 0xa438, 0xac6a, - 0xa436, 0xb85e, 0xa438, 0x23b7, 0xa436, 0xb860, 0xa438, 0x74db, - 0xa436, 0xb862, 0xa438, 0x268c, 0xa436, 0xb864, 0xa438, 0x3FE5, - 0xa436, 0xb886, 0xa438, 0x2250, 0xa436, 0xb888, 0xa438, 0x140e, - 0xa436, 0xb88a, 0xa438, 0x3696, 0xa436, 0xb88c, 0xa438, 0x3973, - 0xa436, 0xb838, 0xa438, 0x00ff, 0xb820, 0x0010, 0xa436, 0x8464, - 0xa438, 0xaf84, 0xa438, 0x7caf, 0xa438, 0x8485, 0xa438, 0xaf85, - 0xa438, 0x13af, 0xa438, 0x851e, 0xa438, 0xaf85, 0xa438, 0xb9af, - 0xa438, 0x8684, 0xa438, 0xaf87, 0xa438, 0x01af, 0xa438, 0x8701, - 0xa438, 0xac38, 0xa438, 0x03af, 0xa438, 0x38bb, 0xa438, 0xaf38, - 0xa438, 0xc302, 0xa438, 0x4618, 0xa438, 0xbf85, 0xa438, 0x0a02, - 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x1002, 0xa438, 0x54c0, - 0xa438, 0xd400, 0xa438, 0x0fbf, 0xa438, 0x8507, 0xa438, 0x024f, - 0xa438, 0x48bf, 0xa438, 0x8504, 0xa438, 0x024f, 0xa438, 0x6759, - 0xa438, 0xf0a1, 0xa438, 0x3008, 0xa438, 0xbf85, 0xa438, 0x0d02, - 0xa438, 0x54c0, 0xa438, 0xae06, 0xa438, 0xbf85, 0xa438, 0x0d02, - 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x0402, 0xa438, 0x4f67, - 0xa438, 0xa183, 0xa438, 0x02ae, 0xa438, 0x15a1, 0xa438, 0x8502, - 0xa438, 0xae10, 0xa438, 0x59f0, 0xa438, 0xa180, 0xa438, 0x16bf, - 0xa438, 0x8501, 0xa438, 0x024f, 0xa438, 0x67a1, 0xa438, 0x381b, - 0xa438, 0xae0b, 0xa438, 0xe18f, 0xa438, 0xffbf, 0xa438, 0x84fe, - 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x17bf, 0xa438, 0x84fe, - 0xa438, 0x0254, 0xa438, 0xb7bf, 0xa438, 0x84fb, 0xa438, 0x0254, - 0xa438, 0xb7ae, 0xa438, 0x09a1, 0xa438, 0x5006, 0xa438, 0xbf84, - 0xa438, 0xfb02, 0xa438, 0x54c0, 0xa438, 0xaf04, 0xa438, 0x4700, - 0xa438, 0xad34, 0xa438, 0xfdad, 0xa438, 0x0670, 0xa438, 0xae14, - 0xa438, 0xf0a6, 0xa438, 0x00b8, 0xa438, 0xbd32, 0xa438, 0x30bd, - 0xa438, 0x30aa, 0xa438, 0xbd2c, 0xa438, 0xccbd, 0xa438, 0x2ca1, - 0xa438, 0x0705, 0xa438, 0xec80, 0xa438, 0xaf40, 0xa438, 0xf7af, - 0xa438, 0x40f5, 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, - 0xa438, 0x4f48, 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, - 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, - 0xa438, 0x024d, 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, - 0xa438, 0x67bf, 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, - 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, - 0xa438, 0x85b3, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, - 0xa438, 0xddbf, 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, - 0xa438, 0x8ffa, 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, - 0xa438, 0x024f, 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, - 0xa438, 0xad02, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, - 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, - 0xa438, 0xfcdd, 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, - 0xa438, 0xbf8f, 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, - 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, - 0xa438, 0xa702, 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0xa102, - 0xa438, 0x54b7, 0xa438, 0xaf3c, 0xa438, 0x2066, 0xa438, 0xb800, - 0xa438, 0xb8bd, 0xa438, 0x30ee, 0xa438, 0xbd2c, 0xa438, 0xb8bd, - 0xa438, 0x7040, 0xa438, 0xbd86, 0xa438, 0xc8bd, 0xa438, 0x8640, - 0xa438, 0xbd88, 0xa438, 0xc8bd, 0xa438, 0x8802, 0xa438, 0x1929, - 0xa438, 0xa202, 0xa438, 0x02ae, 0xa438, 0x03a2, 0xa438, 0x032e, - 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, - 0xa438, 0xe18f, 0xa438, 0xf7bf, 0xa438, 0x85ad, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ff8, 0xa438, 0xbf85, 0xa438, 0xb002, - 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x85b3, - 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ffa, 0xa438, 0xbf85, - 0xa438, 0xb602, 0xa438, 0x4f48, 0xa438, 0xae2c, 0xa438, 0xd100, - 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0xe18f, - 0xa438, 0xfbbf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x48e1, - 0xa438, 0x8ffc, 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f48, - 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x85b3, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ffe, 0xa438, 0xbf85, 0xa438, 0xb602, - 0xa438, 0x4f48, 0xa438, 0xbf86, 0xa438, 0x7e02, 0xa438, 0x4f67, - 0xa438, 0xa100, 0xa438, 0x02ae, 0xa438, 0x25a1, 0xa438, 0x041d, - 0xa438, 0xe18f, 0xa438, 0xf1bf, 0xa438, 0x8675, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ff2, 0xa438, 0xbf86, 0xa438, 0x7802, - 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf3bf, 0xa438, 0x867b, - 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x29a1, 0xa438, 0x070b, - 0xa438, 0xae24, 0xa438, 0xbf86, 0xa438, 0x8102, 0xa438, 0x4f67, - 0xa438, 0xad28, 0xa438, 0x1be1, 0xa438, 0x8ff4, 0xa438, 0xbf86, - 0xa438, 0x7502, 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf5bf, - 0xa438, 0x8678, 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ff6, - 0xa438, 0xbf86, 0xa438, 0x7b02, 0xa438, 0x4f48, 0xa438, 0xaf09, - 0xa438, 0x8420, 0xa438, 0xbc32, 0xa438, 0x20bc, 0xa438, 0x3e76, - 0xa438, 0xbc08, 0xa438, 0xfda6, 0xa438, 0x1a00, 0xa438, 0xb64e, - 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, 0xa438, 0x4f48, - 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, 0xa438, 0xd10f, - 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0x024d, - 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x67bf, - 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, 0xa438, 0x024f, - 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, 0xa438, 0x85b3, - 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, 0xa438, 0xddbf, - 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ffa, - 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, 0xa438, 0x024f, - 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, 0xa438, 0xad02, - 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, 0xa438, 0xbf85, - 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfcdd, - 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, 0xa438, 0xbf8f, - 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, 0xa438, 0x4f67, - 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, 0xa438, 0xa702, - 0xa438, 0x54b7, 0xa438, 0xaf00, 0xa438, 0x8800, 0xa436, 0xb818, - 0xa438, 0x38b8, 0xa436, 0xb81a, 0xa438, 0x0444, 0xa436, 0xb81c, - 0xa438, 0x40ee, 0xa436, 0xb81e, 0xa438, 0x3C1A, 0xa436, 0xb850, - 0xa438, 0x0981, 0xa436, 0xb852, 0xa438, 0x0085, 0xa436, 0xb878, - 0xa438, 0xffff, 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, - 0xa438, 0x003f, 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, - 0xa438, 0x0000, 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, - 0xa436, 0x801E, 0xa438, 0x0021, 0xFFFF, 0xFFFF -}; - -static const u16 phy_mcu_ram_code_8125b_2[] = { - 0xa436, 0x8024, 0xa438, 0x3701, 0xa436, 0xB82E, 0xa438, 0x0001, - 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x801a, 0xa438, 0x1800, 0xa438, 0x8024, - 0xa438, 0x1800, 0xa438, 0x802f, 0xa438, 0x1800, 0xa438, 0x8051, - 0xa438, 0x1800, 0xa438, 0x8057, 0xa438, 0x1800, 0xa438, 0x8063, - 0xa438, 0x1800, 0xa438, 0x8068, 0xa438, 0xd093, 0xa438, 0xd1c4, - 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd704, 0xa438, 0x5fbc, - 0xa438, 0xd504, 0xa438, 0xc9f1, 0xa438, 0x1800, 0xa438, 0x0fc9, - 0xa438, 0xbb50, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd504, - 0xa438, 0x8c0f, 0xa438, 0xd500, 0xa438, 0x1000, 0xa438, 0x1519, - 0xa438, 0x1800, 0xa438, 0x1548, 0xa438, 0x2f70, 0xa438, 0x802a, - 0xa438, 0x2f73, 0xa438, 0x156a, 0xa438, 0x1800, 0xa438, 0x155c, - 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd500, 0xa438, 0x1800, - 0xa438, 0x1551, 0xa438, 0xc0c1, 0xa438, 0xc0c0, 0xa438, 0xd05a, - 0xa438, 0xd1ba, 0xa438, 0xd701, 0xa438, 0x2529, 0xa438, 0x022a, - 0xa438, 0xd0a7, 0xa438, 0xd1b9, 0xa438, 0xa208, 0xa438, 0x1000, - 0xa438, 0x080e, 0xa438, 0xd701, 0xa438, 0x408b, 0xa438, 0x1000, - 0xa438, 0x0a65, 0xa438, 0xf003, 0xa438, 0x1000, 0xa438, 0x0a6b, - 0xa438, 0xd701, 0xa438, 0x1000, 0xa438, 0x0920, 0xa438, 0x1000, - 0xa438, 0x0915, 0xa438, 0x1000, 0xa438, 0x0909, 0xa438, 0x228f, - 0xa438, 0x8038, 0xa438, 0x9801, 0xa438, 0xd71e, 0xa438, 0x5d61, - 0xa438, 0xd701, 0xa438, 0x1800, 0xa438, 0x022a, 0xa438, 0x2005, - 0xa438, 0x091a, 0xa438, 0x3bd9, 0xa438, 0x0919, 0xa438, 0x1800, - 0xa438, 0x0916, 0xa438, 0x1000, 0xa438, 0x14c5, 0xa438, 0xd703, - 0xa438, 0x3181, 0xa438, 0x8061, 0xa438, 0x60ad, 0xa438, 0x1000, - 0xa438, 0x135c, 0xa438, 0xd703, 0xa438, 0x5fba, 0xa438, 0x1800, - 0xa438, 0x0cc7, 0xa438, 0xd096, 0xa438, 0xd1a9, 0xa438, 0xd503, - 0xa438, 0x1800, 0xa438, 0x0c94, 0xa438, 0xa802, 0xa438, 0xa301, - 0xa438, 0xa801, 0xa438, 0xc004, 0xa438, 0xd710, 0xa438, 0x4000, - 0xa438, 0x1800, 0xa438, 0x1e79, 0xa436, 0xA026, 0xa438, 0x1e78, - 0xa436, 0xA024, 0xa438, 0x0c93, 0xa436, 0xA022, 0xa438, 0x0cc5, - 0xa436, 0xA020, 0xa438, 0x0915, 0xa436, 0xA006, 0xa438, 0x020a, - 0xa436, 0xA004, 0xa438, 0x155b, 0xa436, 0xA002, 0xa438, 0x1542, - 0xa436, 0xA000, 0xa438, 0x0fc7, 0xa436, 0xA008, 0xa438, 0xff00, - 0xa436, 0xA016, 0xa438, 0x0010, 0xa436, 0xA012, 0xa438, 0x0000, - 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, 0xa438, 0x1800, - 0xa438, 0x801d, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, - 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, - 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, - 0xa438, 0x802c, 0xa438, 0xd700, 0xa438, 0x6090, 0xa438, 0x60d1, - 0xa438, 0xc95c, 0xa438, 0xf007, 0xa438, 0x60b1, 0xa438, 0xc95a, - 0xa438, 0xf004, 0xa438, 0xc956, 0xa438, 0xf002, 0xa438, 0xc94e, - 0xa438, 0x1800, 0xa438, 0x00cd, 0xa438, 0xd700, 0xa438, 0x6090, - 0xa438, 0x60d1, 0xa438, 0xc95c, 0xa438, 0xf007, 0xa438, 0x60b1, - 0xa438, 0xc95a, 0xa438, 0xf004, 0xa438, 0xc956, 0xa438, 0xf002, - 0xa438, 0xc94e, 0xa438, 0x1000, 0xa438, 0x022a, 0xa438, 0x1800, - 0xa438, 0x0132, 0xa436, 0xA08E, 0xa438, 0xffff, 0xa436, 0xA08C, - 0xa438, 0xffff, 0xa436, 0xA08A, 0xa438, 0xffff, 0xa436, 0xA088, - 0xa438, 0xffff, 0xa436, 0xA086, 0xa438, 0xffff, 0xa436, 0xA084, - 0xa438, 0xffff, 0xa436, 0xA082, 0xa438, 0x012f, 0xa436, 0xA080, - 0xa438, 0x00cc, 0xa436, 0xA090, 0xa438, 0x0103, 0xa436, 0xA016, - 0xa438, 0x0020, 0xa436, 0xA012, 0xa438, 0x0000, 0xa436, 0xA014, - 0xa438, 0x1800, 0xa438, 0x8010, 0xa438, 0x1800, 0xa438, 0x8020, - 0xa438, 0x1800, 0xa438, 0x802a, 0xa438, 0x1800, 0xa438, 0x8035, - 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0x1800, 0xa438, 0x803c, - 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0x1800, 0xa438, 0x803c, - 0xa438, 0xd107, 0xa438, 0xd042, 0xa438, 0xa404, 0xa438, 0x1000, - 0xa438, 0x09df, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x8280, - 0xa438, 0xd700, 0xa438, 0x6065, 0xa438, 0xd125, 0xa438, 0xf002, - 0xa438, 0xd12b, 0xa438, 0xd040, 0xa438, 0x1800, 0xa438, 0x077f, - 0xa438, 0x0cf0, 0xa438, 0x0c50, 0xa438, 0xd104, 0xa438, 0xd040, - 0xa438, 0x1000, 0xa438, 0x0aa8, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x1800, 0xa438, 0x0a2e, 0xa438, 0xcb9b, 0xa438, 0xd110, - 0xa438, 0xd040, 0xa438, 0x1000, 0xa438, 0x0b7b, 0xa438, 0x1000, - 0xa438, 0x09df, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x1800, - 0xa438, 0x081b, 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd704, - 0xa438, 0x7fb8, 0xa438, 0xa718, 0xa438, 0x1800, 0xa438, 0x074e, - 0xa436, 0xA10E, 0xa438, 0xffff, 0xa436, 0xA10C, 0xa438, 0xffff, - 0xa436, 0xA10A, 0xa438, 0xffff, 0xa436, 0xA108, 0xa438, 0xffff, - 0xa436, 0xA106, 0xa438, 0x074d, 0xa436, 0xA104, 0xa438, 0x0818, - 0xa436, 0xA102, 0xa438, 0x0a2c, 0xa436, 0xA100, 0xa438, 0x077e, - 0xa436, 0xA110, 0xa438, 0x000f, 0xa436, 0xb87c, 0xa438, 0x8625, - 0xa436, 0xb87e, 0xa438, 0xaf86, 0xa438, 0x3daf, 0xa438, 0x8689, - 0xa438, 0xaf88, 0xa438, 0x69af, 0xa438, 0x8887, 0xa438, 0xaf88, - 0xa438, 0x9caf, 0xa438, 0x889c, 0xa438, 0xaf88, 0xa438, 0x9caf, - 0xa438, 0x889c, 0xa438, 0xbf86, 0xa438, 0x49d7, 0xa438, 0x0040, - 0xa438, 0x0277, 0xa438, 0x7daf, 0xa438, 0x2727, 0xa438, 0x0000, - 0xa438, 0x7205, 0xa438, 0x0000, 0xa438, 0x7208, 0xa438, 0x0000, - 0xa438, 0x71f3, 0xa438, 0x0000, 0xa438, 0x71f6, 0xa438, 0x0000, - 0xa438, 0x7229, 0xa438, 0x0000, 0xa438, 0x722c, 0xa438, 0x0000, - 0xa438, 0x7217, 0xa438, 0x0000, 0xa438, 0x721a, 0xa438, 0x0000, - 0xa438, 0x721d, 0xa438, 0x0000, 0xa438, 0x7211, 0xa438, 0x0000, - 0xa438, 0x7220, 0xa438, 0x0000, 0xa438, 0x7214, 0xa438, 0x0000, - 0xa438, 0x722f, 0xa438, 0x0000, 0xa438, 0x7223, 0xa438, 0x0000, - 0xa438, 0x7232, 0xa438, 0x0000, 0xa438, 0x7226, 0xa438, 0xf8f9, - 0xa438, 0xfae0, 0xa438, 0x85b3, 0xa438, 0x3802, 0xa438, 0xad27, - 0xa438, 0x02ae, 0xa438, 0x03af, 0xa438, 0x8830, 0xa438, 0x1f66, - 0xa438, 0xef65, 0xa438, 0xbfc2, 0xa438, 0x1f1a, 0xa438, 0x96f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00da, 0xa438, 0xf605, - 0xa438, 0xbfc2, 0xa438, 0x2f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, - 0xa438, 0xffd2, 0xa438, 0x00db, 0xa438, 0xf605, 0xa438, 0xef02, - 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4202, - 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1b03, 0xa438, 0x1f11, - 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4502, 0xa438, 0x6e7d, - 0xa438, 0xef02, 0xa438, 0x1a03, 0xa438, 0x1f11, 0xa438, 0x0d42, - 0xa438, 0xbf88, 0xa438, 0x4802, 0xa438, 0x6e7d, 0xa438, 0xbfc2, - 0xa438, 0x3f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, - 0xa438, 0x00da, 0xa438, 0xf605, 0xa438, 0xbfc2, 0xa438, 0x4f1a, - 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00db, - 0xa438, 0xf605, 0xa438, 0xef02, 0xa438, 0x1f11, 0xa438, 0x0d42, - 0xa438, 0xbf88, 0xa438, 0x4b02, 0xa438, 0x6e7d, 0xa438, 0xef02, - 0xa438, 0x1b03, 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, - 0xa438, 0x4e02, 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1a03, - 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x5102, - 0xa438, 0x6e7d, 0xa438, 0xef56, 0xa438, 0xd020, 0xa438, 0x1f11, - 0xa438, 0xbf88, 0xa438, 0x5402, 0xa438, 0x6e7d, 0xa438, 0xbf88, - 0xa438, 0x5702, 0xa438, 0x6e7d, 0xa438, 0xbf88, 0xa438, 0x5a02, - 0xa438, 0x6e7d, 0xa438, 0xe185, 0xa438, 0xa0ef, 0xa438, 0x0348, - 0xa438, 0x0a28, 0xa438, 0x05ef, 0xa438, 0x201b, 0xa438, 0x01ad, - 0xa438, 0x2735, 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x88e1, - 0xa438, 0x8589, 0xa438, 0xbf88, 0xa438, 0x5d02, 0xa438, 0x6e7d, - 0xa438, 0xe085, 0xa438, 0x8ee1, 0xa438, 0x858f, 0xa438, 0xbf88, - 0xa438, 0x6002, 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x94e1, - 0xa438, 0x8595, 0xa438, 0xbf88, 0xa438, 0x6302, 0xa438, 0x6e7d, - 0xa438, 0xe085, 0xa438, 0x9ae1, 0xa438, 0x859b, 0xa438, 0xbf88, - 0xa438, 0x6602, 0xa438, 0x6e7d, 0xa438, 0xaf88, 0xa438, 0x3cbf, - 0xa438, 0x883f, 0xa438, 0x026e, 0xa438, 0x9cad, 0xa438, 0x2835, - 0xa438, 0x1f44, 0xa438, 0xe08f, 0xa438, 0xf8e1, 0xa438, 0x8ff9, - 0xa438, 0xbf88, 0xa438, 0x5d02, 0xa438, 0x6e7d, 0xa438, 0xe08f, - 0xa438, 0xfae1, 0xa438, 0x8ffb, 0xa438, 0xbf88, 0xa438, 0x6002, - 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfce1, 0xa438, 0x8ffd, - 0xa438, 0xbf88, 0xa438, 0x6302, 0xa438, 0x6e7d, 0xa438, 0xe08f, - 0xa438, 0xfee1, 0xa438, 0x8fff, 0xa438, 0xbf88, 0xa438, 0x6602, - 0xa438, 0x6e7d, 0xa438, 0xaf88, 0xa438, 0x3ce1, 0xa438, 0x85a1, - 0xa438, 0x1b21, 0xa438, 0xad37, 0xa438, 0x341f, 0xa438, 0x44e0, - 0xa438, 0x858a, 0xa438, 0xe185, 0xa438, 0x8bbf, 0xa438, 0x885d, - 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8590, 0xa438, 0xe185, - 0xa438, 0x91bf, 0xa438, 0x8860, 0xa438, 0x026e, 0xa438, 0x7de0, - 0xa438, 0x8596, 0xa438, 0xe185, 0xa438, 0x97bf, 0xa438, 0x8863, - 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x859c, 0xa438, 0xe185, - 0xa438, 0x9dbf, 0xa438, 0x8866, 0xa438, 0x026e, 0xa438, 0x7dae, - 0xa438, 0x401f, 0xa438, 0x44e0, 0xa438, 0x858c, 0xa438, 0xe185, - 0xa438, 0x8dbf, 0xa438, 0x885d, 0xa438, 0x026e, 0xa438, 0x7de0, - 0xa438, 0x8592, 0xa438, 0xe185, 0xa438, 0x93bf, 0xa438, 0x8860, - 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8598, 0xa438, 0xe185, - 0xa438, 0x99bf, 0xa438, 0x8863, 0xa438, 0x026e, 0xa438, 0x7de0, - 0xa438, 0x859e, 0xa438, 0xe185, 0xa438, 0x9fbf, 0xa438, 0x8866, - 0xa438, 0x026e, 0xa438, 0x7dae, 0xa438, 0x0ce1, 0xa438, 0x85b3, - 0xa438, 0x3904, 0xa438, 0xac2f, 0xa438, 0x04ee, 0xa438, 0x85b3, - 0xa438, 0x00af, 0xa438, 0x39d9, 0xa438, 0x22ac, 0xa438, 0xeaf0, - 0xa438, 0xacf6, 0xa438, 0xf0ac, 0xa438, 0xfaf0, 0xa438, 0xacf8, - 0xa438, 0xf0ac, 0xa438, 0xfcf0, 0xa438, 0xad00, 0xa438, 0xf0ac, - 0xa438, 0xfef0, 0xa438, 0xacf0, 0xa438, 0xf0ac, 0xa438, 0xf4f0, - 0xa438, 0xacf2, 0xa438, 0xf0ac, 0xa438, 0xb0f0, 0xa438, 0xacae, - 0xa438, 0xf0ac, 0xa438, 0xacf0, 0xa438, 0xacaa, 0xa438, 0xa100, - 0xa438, 0x0ce1, 0xa438, 0x8ff7, 0xa438, 0xbf88, 0xa438, 0x8402, - 0xa438, 0x6e7d, 0xa438, 0xaf26, 0xa438, 0xe9e1, 0xa438, 0x8ff6, - 0xa438, 0xbf88, 0xa438, 0x8402, 0xa438, 0x6e7d, 0xa438, 0xaf26, - 0xa438, 0xf520, 0xa438, 0xac86, 0xa438, 0xbf88, 0xa438, 0x3f02, - 0xa438, 0x6e9c, 0xa438, 0xad28, 0xa438, 0x03af, 0xa438, 0x3324, - 0xa438, 0xad38, 0xa438, 0x03af, 0xa438, 0x32e6, 0xa438, 0xaf32, - 0xa438, 0xfb00, 0xa436, 0xb87c, 0xa438, 0x8ff6, 0xa436, 0xb87e, - 0xa438, 0x0705, 0xa436, 0xb87c, 0xa438, 0x8ff8, 0xa436, 0xb87e, - 0xa438, 0x19cc, 0xa436, 0xb87c, 0xa438, 0x8ffa, 0xa436, 0xb87e, - 0xa438, 0x28e3, 0xa436, 0xb87c, 0xa438, 0x8ffc, 0xa436, 0xb87e, - 0xa438, 0x1047, 0xa436, 0xb87c, 0xa438, 0x8ffe, 0xa436, 0xb87e, - 0xa438, 0x0a45, 0xa436, 0xb85e, 0xa438, 0x271E, 0xa436, 0xb860, - 0xa438, 0x3846, 0xa436, 0xb862, 0xa438, 0x26E6, 0xa436, 0xb864, - 0xa438, 0x32E3, 0xa436, 0xb886, 0xa438, 0xffff, 0xa436, 0xb888, - 0xa438, 0xffff, 0xa436, 0xb88a, 0xa438, 0xffff, 0xa436, 0xb88c, - 0xa438, 0xffff, 0xa436, 0xb838, 0xa438, 0x000f, 0xb820, 0x0010, - 0xa436, 0x846e, 0xa438, 0xaf84, 0xa438, 0x86af, 0xa438, 0x8690, - 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, 0xa438, 0xaf86, - 0xa438, 0xa4af, 0xa438, 0x86a4, 0xa438, 0xaf86, 0xa438, 0xa4af, - 0xa438, 0x86a4, 0xa438, 0xee82, 0xa438, 0x5f00, 0xa438, 0x0284, - 0xa438, 0x90af, 0xa438, 0x0441, 0xa438, 0xf8e0, 0xa438, 0x8ff3, - 0xa438, 0xa000, 0xa438, 0x0502, 0xa438, 0x84a4, 0xa438, 0xae06, - 0xa438, 0xa001, 0xa438, 0x0302, 0xa438, 0x84c8, 0xa438, 0xfc04, - 0xa438, 0xf8f9, 0xa438, 0xef59, 0xa438, 0xe080, 0xa438, 0x15ad, - 0xa438, 0x2702, 0xa438, 0xae03, 0xa438, 0xaf84, 0xa438, 0xc3bf, - 0xa438, 0x53ca, 0xa438, 0x0252, 0xa438, 0xc8ad, 0xa438, 0x2807, - 0xa438, 0x0285, 0xa438, 0x2cee, 0xa438, 0x8ff3, 0xa438, 0x01ef, - 0xa438, 0x95fd, 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xfaef, - 0xa438, 0x69bf, 0xa438, 0x53ca, 0xa438, 0x0252, 0xa438, 0xc8ac, - 0xa438, 0x2822, 0xa438, 0xd480, 0xa438, 0x00bf, 0xa438, 0x8684, - 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x8687, 0xa438, 0x0252, - 0xa438, 0xa9bf, 0xa438, 0x868a, 0xa438, 0x0252, 0xa438, 0xa9bf, - 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9ee, 0xa438, 0x8ff3, - 0xa438, 0x00af, 0xa438, 0x8526, 0xa438, 0xe08f, 0xa438, 0xf4e1, - 0xa438, 0x8ff5, 0xa438, 0xe28f, 0xa438, 0xf6e3, 0xa438, 0x8ff7, - 0xa438, 0x1b45, 0xa438, 0xac27, 0xa438, 0x0eee, 0xa438, 0x8ff4, - 0xa438, 0x00ee, 0xa438, 0x8ff5, 0xa438, 0x0002, 0xa438, 0x852c, - 0xa438, 0xaf85, 0xa438, 0x26e0, 0xa438, 0x8ff4, 0xa438, 0xe18f, - 0xa438, 0xf52c, 0xa438, 0x0001, 0xa438, 0xe48f, 0xa438, 0xf4e5, - 0xa438, 0x8ff5, 0xa438, 0xef96, 0xa438, 0xfefd, 0xa438, 0xfc04, - 0xa438, 0xf8f9, 0xa438, 0xef59, 0xa438, 0xbf53, 0xa438, 0x2202, - 0xa438, 0x52c8, 0xa438, 0xa18b, 0xa438, 0x02ae, 0xa438, 0x03af, - 0xa438, 0x85da, 0xa438, 0xbf57, 0xa438, 0x7202, 0xa438, 0x52c8, - 0xa438, 0xe48f, 0xa438, 0xf8e5, 0xa438, 0x8ff9, 0xa438, 0xbf57, - 0xa438, 0x7502, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfae5, - 0xa438, 0x8ffb, 0xa438, 0xbf57, 0xa438, 0x7802, 0xa438, 0x52c8, - 0xa438, 0xe48f, 0xa438, 0xfce5, 0xa438, 0x8ffd, 0xa438, 0xbf57, - 0xa438, 0x7b02, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfee5, - 0xa438, 0x8fff, 0xa438, 0xbf57, 0xa438, 0x6c02, 0xa438, 0x52c8, - 0xa438, 0xa102, 0xa438, 0x13ee, 0xa438, 0x8ffc, 0xa438, 0x80ee, - 0xa438, 0x8ffd, 0xa438, 0x00ee, 0xa438, 0x8ffe, 0xa438, 0x80ee, - 0xa438, 0x8fff, 0xa438, 0x00af, 0xa438, 0x8599, 0xa438, 0xa101, - 0xa438, 0x0cbf, 0xa438, 0x534c, 0xa438, 0x0252, 0xa438, 0xc8a1, - 0xa438, 0x0303, 0xa438, 0xaf85, 0xa438, 0x77bf, 0xa438, 0x5322, - 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x8b02, 0xa438, 0xae03, - 0xa438, 0xaf86, 0xa438, 0x64e0, 0xa438, 0x8ff8, 0xa438, 0xe18f, - 0xa438, 0xf9bf, 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9e0, - 0xa438, 0x8ffa, 0xa438, 0xe18f, 0xa438, 0xfbbf, 0xa438, 0x8687, - 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffc, 0xa438, 0xe18f, - 0xa438, 0xfdbf, 0xa438, 0x868a, 0xa438, 0x0252, 0xa438, 0xa9e0, - 0xa438, 0x8ffe, 0xa438, 0xe18f, 0xa438, 0xffbf, 0xa438, 0x868d, - 0xa438, 0x0252, 0xa438, 0xa9af, 0xa438, 0x867f, 0xa438, 0xbf53, - 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa144, 0xa438, 0x3cbf, - 0xa438, 0x547b, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ff8, - 0xa438, 0xe58f, 0xa438, 0xf9bf, 0xa438, 0x547e, 0xa438, 0x0252, - 0xa438, 0xc8e4, 0xa438, 0x8ffa, 0xa438, 0xe58f, 0xa438, 0xfbbf, - 0xa438, 0x5481, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffc, - 0xa438, 0xe58f, 0xa438, 0xfdbf, 0xa438, 0x5484, 0xa438, 0x0252, - 0xa438, 0xc8e4, 0xa438, 0x8ffe, 0xa438, 0xe58f, 0xa438, 0xffbf, - 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x4448, - 0xa438, 0xaf85, 0xa438, 0xa7bf, 0xa438, 0x5322, 0xa438, 0x0252, - 0xa438, 0xc8a1, 0xa438, 0x313c, 0xa438, 0xbf54, 0xa438, 0x7b02, - 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xf8e5, 0xa438, 0x8ff9, - 0xa438, 0xbf54, 0xa438, 0x7e02, 0xa438, 0x52c8, 0xa438, 0xe48f, - 0xa438, 0xfae5, 0xa438, 0x8ffb, 0xa438, 0xbf54, 0xa438, 0x8102, - 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfce5, 0xa438, 0x8ffd, - 0xa438, 0xbf54, 0xa438, 0x8402, 0xa438, 0x52c8, 0xa438, 0xe48f, - 0xa438, 0xfee5, 0xa438, 0x8fff, 0xa438, 0xbf53, 0xa438, 0x2202, - 0xa438, 0x52c8, 0xa438, 0xa131, 0xa438, 0x03af, 0xa438, 0x85a7, - 0xa438, 0xd480, 0xa438, 0x00bf, 0xa438, 0x8684, 0xa438, 0x0252, - 0xa438, 0xa9bf, 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9bf, - 0xa438, 0x868a, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868d, - 0xa438, 0x0252, 0xa438, 0xa9ef, 0xa438, 0x95fd, 0xa438, 0xfc04, - 0xa438, 0xf0d1, 0xa438, 0x2af0, 0xa438, 0xd12c, 0xa438, 0xf0d1, - 0xa438, 0x44f0, 0xa438, 0xd146, 0xa438, 0xbf86, 0xa438, 0xa102, - 0xa438, 0x52c8, 0xa438, 0xbf86, 0xa438, 0xa102, 0xa438, 0x52c8, - 0xa438, 0xd101, 0xa438, 0xaf06, 0xa438, 0xa570, 0xa438, 0xce42, - 0xa436, 0xb818, 0xa438, 0x043d, 0xa436, 0xb81a, 0xa438, 0x06a3, - 0xa436, 0xb81c, 0xa438, 0xffff, 0xa436, 0xb81e, 0xa438, 0xffff, - 0xa436, 0xb850, 0xa438, 0xffff, 0xa436, 0xb852, 0xa438, 0xffff, - 0xa436, 0xb878, 0xa438, 0xffff, 0xa436, 0xb884, 0xa438, 0xffff, - 0xa436, 0xb832, 0xa438, 0x0003, 0xa436, 0x0000, 0xa438, 0x0000, - 0xa436, 0xB82E, 0xa438, 0x0000, 0xa436, 0x8024, 0xa438, 0x0000, - 0xb820, 0x0000, 0xa436, 0x801E, 0xa438, 0x0019, 0xFFFF, 0xFFFF -}; - -static void -rtl8125_real_set_phy_mcu_8125b_1(struct net_device *dev) -{ - rtl8125_set_phy_mcu_ram_code(dev, - phy_mcu_ram_code_8125b_1, - ARRAY_SIZE(phy_mcu_ram_code_8125b_1) - ); -} - -static void -rtl8125_set_phy_mcu_8125b_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125b_1(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_real_set_phy_mcu_8125b_2(struct net_device *dev) -{ - rtl8125_set_phy_mcu_ram_code(dev, - phy_mcu_ram_code_8125b_2, - ARRAY_SIZE(phy_mcu_ram_code_8125b_2) - ); -} - -static void -rtl8125_set_phy_mcu_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125b_2(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_init_hw_phy_mcu(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 require_disable_phy_disable_mode = FALSE; - - if (tp->NotWrRamCodeToMicroP == TRUE) return; - if (rtl8125_check_hw_phy_mcu_code_ver(dev)) return; - - if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(tp) && rtl8125_is_in_phy_disable_mode(dev)) - require_disable_phy_disable_mode = TRUE; - - if (require_disable_phy_disable_mode) - rtl8125_disable_phy_disable_mode(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_set_phy_mcu_8125a_1(dev); - break; - case CFG_METHOD_3: - rtl8125_set_phy_mcu_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_set_phy_mcu_8125b_1(dev); - break; - case CFG_METHOD_5: - rtl8125_set_phy_mcu_8125b_2(dev); - break; - } - - if (require_disable_phy_disable_mode) - rtl8125_enable_phy_disable_mode(dev); - - rtl8125_write_hw_phy_mcu_code_ver(dev); - - rtl8125_mdio_write(tp,0x1F, 0x0000); - - tp->HwHasWrRamCodeToMicroP = TRUE; -} - -static void -rtl8125_enable_phy_aldps(struct rtl8125_private *tp) -{ - //enable aldps - //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) - SetEthPhyOcpBit(tp, 0xA430, BIT_2); -} - -static void -rtl8125_hw_phy_config_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - 0x03FF, - 0x84 - ); - - SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearAndSetEthPhyOcpBit(tp, - 0xAD16, - 0x03FF, - 0x0006 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD32, - 0x003F, - 0x0006 - ); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xAC8A, - BIT_15|BIT_14|BIT_13|BIT_12, - BIT_14|BIT_13|BIT_12 - ); - SetEthPhyOcpBit(tp, 0xAD18, BIT_10); - SetEthPhyOcpBit(tp, 0xAD1A, 0x3FF); - SetEthPhyOcpBit(tp, 0xAD1C, 0x3FF); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xC400 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EB); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0x0700, - 0x0300 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F8); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F1); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x3000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80FE); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xA500 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8102); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8105); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x3300 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8100); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x7000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8104); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xF000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8106); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6500 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xED00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); - SetEthPhyOcpBit(tp, 0xA438, BIT_8); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80E1); - ClearEthPhyOcpBit(tp, 0xA438, BIT_8); - - ClearAndSetEthPhyOcpBit(tp, - 0xBF06, - 0x003F, - 0x38 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x819F); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xD0B6); - - mdio_direct_write_phy_ocp(tp, 0xBC34, 0x5555); - ClearAndSetEthPhyOcpBit(tp, - 0xBF0A, - BIT_11|BIT_10|BIT_9, - BIT_11|BIT_9 - ); - - ClearEthPhyOcpBit(tp, 0xA5C0, BIT_10); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - //enable aldps - //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearAndSetEthPhyOcpBit(tp, - 0xAD16, - 0x03FF, - 0x03FF - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD32, - 0x003F, - 0x0006 - ); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xACC0, - BIT_1|BIT_0, - BIT_1 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - BIT_7|BIT_6|BIT_5, - BIT_6 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - BIT_2|BIT_1|BIT_0, - BIT_2 - ); - ClearEthPhyOcpBit(tp, 0xAC14, BIT_7); - ClearEthPhyOcpBit(tp, 0xAC80, BIT_9|BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xAC5E, - BIT_2|BIT_1|BIT_0, - BIT_1 - ); - mdio_direct_write_phy_ocp(tp, 0xAD4C, 0x00A8); - mdio_direct_write_phy_ocp(tp, 0xAC5C, 0x01FF); - ClearAndSetEthPhyOcpBit(tp, - 0xAC8A, - BIT_7|BIT_6|BIT_5|BIT_4, - BIT_5|BIT_4 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - 0xFF00, - 0x0500 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8159); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - 0xFF00, - 0x0700 - ); - - - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, dev->mtu + ETH_HLEN + 0x20); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80A2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x809C); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x81B3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0043); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00A7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00D6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00EC); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00F6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FD); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FF); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00BB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0058); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0029); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0009); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8257); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020F); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7843); - - - rtl8125_set_phy_mcu_patch_request(tp); - - ClearEthPhyOcpBit(tp, 0xB896, BIT_0); - ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); - - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC091); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC092); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1214); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC094); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1516); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC096); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x171B); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC098); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1B1C); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1F1F); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2021); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2224); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A0); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A2); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A4); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC018); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0AF2); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0D4A); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0F26); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x118D); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC020); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x14F3); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC022); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x175A); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC024); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x19C0); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC026); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1C26); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC089); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6050); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x5F6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC090); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); - - SetEthPhyOcpBit(tp, 0xB896, BIT_0); - - rtl8125_clear_phy_mcu_patch_request(tp); - - - SetEthPhyOcpBit(tp, 0xD068, BIT_13); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x81A2); - SetEthPhyOcpBit(tp, 0xA438, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xB54C, - 0xFF00, - 0xDB00); - - - ClearEthPhyOcpBit(tp, 0xA454, BIT_0); - - - SetEthPhyOcpBit(tp, 0xA5D4, BIT_5); - ClearEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearEthPhyOcpBit(tp, 0xA86A, BIT_0); - - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - if (tp->RequirePhyMdiSwapPatch) { - u16 adccal_offset_p0; - u16 adccal_offset_p1; - u16 adccal_offset_p2; - u16 adccal_offset_p3; - u16 rg_lpf_cap_xg_p0; - u16 rg_lpf_cap_xg_p1; - u16 rg_lpf_cap_xg_p2; - u16 rg_lpf_cap_xg_p3; - u16 rg_lpf_cap_p0; - u16 rg_lpf_cap_p1; - u16 rg_lpf_cap_p2; - u16 rg_lpf_cap_p3; - - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0007, - 0x0001 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0000 - ); - adccal_offset_p0 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p0 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0008 - ); - adccal_offset_p1 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p1 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0010 - ); - adccal_offset_p2 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p2 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0018 - ); - adccal_offset_p3 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p3 &= 0x07FF; - - - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0000 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p3 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0008 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p2 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0010 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p1 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0018 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p0 - ); - - - rg_lpf_cap_xg_p0 = mdio_direct_read_phy_ocp(tp, 0xBD5A); - rg_lpf_cap_xg_p0 &= 0x001F; - rg_lpf_cap_xg_p1 = mdio_direct_read_phy_ocp(tp, 0xBD5A); - rg_lpf_cap_xg_p1 &= 0x1F00; - rg_lpf_cap_xg_p2 = mdio_direct_read_phy_ocp(tp, 0xBD5C); - rg_lpf_cap_xg_p2 &= 0x001F; - rg_lpf_cap_xg_p3 = mdio_direct_read_phy_ocp(tp, 0xBD5C); - rg_lpf_cap_xg_p3 &= 0x1F00; - rg_lpf_cap_p0 = mdio_direct_read_phy_ocp(tp, 0xBC18); - rg_lpf_cap_p0 &= 0x001F; - rg_lpf_cap_p1 = mdio_direct_read_phy_ocp(tp, 0xBC18); - rg_lpf_cap_p1 &= 0x1F00; - rg_lpf_cap_p2 = mdio_direct_read_phy_ocp(tp, 0xBC1A); - rg_lpf_cap_p2 &= 0x001F; - rg_lpf_cap_p3 = mdio_direct_read_phy_ocp(tp, 0xBC1A); - rg_lpf_cap_p3 &= 0x1F00; - - - ClearAndSetEthPhyOcpBit(tp, - 0xBD5A, - 0x001F, - rg_lpf_cap_xg_p3 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5A, - 0x1F00, - rg_lpf_cap_xg_p2 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5C, - 0x001F, - rg_lpf_cap_xg_p1 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5C, - 0x1F00, - rg_lpf_cap_xg_p0 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC18, - 0x001F, - rg_lpf_cap_p3 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC18, - 0x1F00, - rg_lpf_cap_p2 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC1A, - 0x001F, - rg_lpf_cap_p1 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC1A, - 0x1F00, - rg_lpf_cap_p0 << 8 - ); - } - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125b_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - SetEthPhyOcpBit(tp, 0xBC08, (BIT_3 | BIT_2)); - - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FFF); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x0400 - ); - } - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8560); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8562); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8564); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8566); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8568); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x856A); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FFE); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0907); - } - ClearAndSetEthPhyOcpBit(tp, - 0xACDA, - 0xFF00, - 0xFF00 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xACDE, - 0xF000, - 0xF000 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80D6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x6077); - mdio_direct_write_phy_ocp(tp, 0xB506, 0x01E7); - mdio_direct_write_phy_ocp(tp, 0xAC8C, 0x0FFC); - mdio_direct_write_phy_ocp(tp, 0xAC46, 0xB7B4); - mdio_direct_write_phy_ocp(tp, 0xAC50, 0x0FBC); - mdio_direct_write_phy_ocp(tp, 0xAC3C, 0x9240); - mdio_direct_write_phy_ocp(tp, 0xAC4E, 0x0DB4); - mdio_direct_write_phy_ocp(tp, 0xACC6, 0x0707); - mdio_direct_write_phy_ocp(tp, 0xACC8, 0xA0D3); - mdio_direct_write_phy_ocp(tp, 0xAD08, 0x0007); - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8013); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0700); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FB9); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBA); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBC); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1900); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBE); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0800); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE500); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC8); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0400); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCa); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF300); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCc); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFD00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCe); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFB00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF400); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD8); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF600); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x813D); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x390E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x814F); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x790E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80B0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F31); - SetEthPhyOcpBit(tp, 0xBF4C, BIT_1); - SetEthPhyOcpBit(tp, 0xBCCA, (BIT_9 | BIT_8)); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8141); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x320E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8153); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x720E); - ClearEthPhyOcpBit(tp, 0xA432, BIT_6); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8529); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x050E); - - - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, dev->mtu + ETH_HLEN + 0x20); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x816C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8174); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8178); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0719); - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0400); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0404); - } - mdio_direct_write_phy_ocp(tp, 0xBF4A, 0x001B); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8033); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8037); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803B); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFC32); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803F); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8043); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8047); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8145); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x370E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x770E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8169); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0D0A); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x817B); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1D0A); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8217); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x821A); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DA); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0403); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0384); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BA); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xF009); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BD); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x9F00 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf083); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DD); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03f0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CE); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8009); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80D1); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x8000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x200A); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xF0AD); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x809F); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6073); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000B); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A9); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xC000 - ); - - rtl8125_set_phy_mcu_patch_request(tp); - - ClearEthPhyOcpBit(tp, 0xB896, BIT_0); - ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); - - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC23E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC240); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0103); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC242); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0507); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC244); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x090B); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC246); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0C0E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC248); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1012); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC24A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1416); - - SetEthPhyOcpBit(tp, 0xB896, BIT_0); - - rtl8125_clear_phy_mcu_patch_request(tp); - - - SetEthPhyOcpBit(tp, 0xA86A, BIT_0); - SetEthPhyOcpBit(tp, 0xA6F0, BIT_0); - - - mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); - mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); - mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); - mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); - mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); - ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); - SetEthPhyOcpBit(tp, 0xA438, BIT_12); - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - ClearAndSetEthPhyOcpBit(tp, - 0xAC46, - 0x00F0, - 0x0090 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD30, - 0x0003, - 0x0001 - ); - - - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, dev->mtu + ETH_HLEN + 0x20); - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F5); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x760E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8107); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x360E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8551); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8, - BIT_11 - ); - - ClearAndSetEthPhyOcpBit(tp, - 0xbf00, - 0xE000, - 0xA000 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xbf46, - 0x0F00, - 0x0300 - ); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8044); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x804A); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8050); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8056); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x805C); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8062); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8068); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x806E); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8074); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x807A); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - - - SetEthPhyOcpBit(tp, 0xA4CA, BIT_6); - - - ClearAndSetEthPhyOcpBit(tp, - 0xBF84, - BIT_15 | BIT_14 | BIT_13, - BIT_15 | BIT_13 - ); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - BIT_13 | BIT_10 | BIT_9 | BIT_8, - BIT_15 | BIT_14 | BIT_12 | BIT_11 - ); - - /* - mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); - mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); - mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); - mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); - mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); - ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); - SetEthPhyOcpBit(tp, 0xA438, BIT_12); - */ - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_set_hw_phy_before_init_phy_mcu(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 PhyRegValue; - - switch (tp->mcfg) { - case CFG_METHOD_4: - mdio_direct_write_phy_ocp(tp, 0xBF86, 0x9000); - - SetEthPhyOcpBit(tp, 0xC402, BIT_10); - ClearEthPhyOcpBit(tp, 0xC402, BIT_10); - - PhyRegValue = mdio_direct_read_phy_ocp(tp, 0xBF86); - PhyRegValue &= (BIT_1 | BIT_0); - if (PhyRegValue != 0) - dprintk("PHY watch dog not clear, value = 0x%x \n", PhyRegValue); - - mdio_direct_write_phy_ocp(tp, 0xBD86, 0x1010); - mdio_direct_write_phy_ocp(tp, 0xBD88, 0x1010); - - ClearAndSetEthPhyOcpBit(tp, - 0xBD4E, - BIT_11 | BIT_10, - BIT_11); - ClearAndSetEthPhyOcpBit(tp, - 0xBF46, - BIT_11 | BIT_10 | BIT_9 | BIT_8, - BIT_10 | BIT_9 | BIT_8); - break; - } -} - -static void -rtl8125_hw_phy_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->resume_not_chg_speed) return; - - tp->phy_reset_enable(dev); - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) return; - - rtl8125_set_hw_phy_before_init_phy_mcu(dev); - - rtl8125_init_hw_phy_mcu(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_hw_phy_config_8125a_1(dev); - break; - case CFG_METHOD_3: - rtl8125_hw_phy_config_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_hw_phy_config_8125b_1(dev); - break; - case CFG_METHOD_5: - rtl8125_hw_phy_config_8125b_2(dev); - break; - } - - //legacy force mode(Chap 22) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - rtl8125_mdio_write(tp, 0x1F, 0x0A5B); - rtl8125_clear_eth_phy_bit(tp, 0x12, BIT_15); - rtl8125_mdio_write(tp, 0x1F, 0x0000); - break; - } - - /*ocp phy power saving*/ - /* - if (aspm) { - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) - rtl8125_enable_ocp_phy_power_saving(dev); - } - */ - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - if (tp->eee_enabled == 1) - rtl8125_enable_eee(tp); - else - rtl8125_disable_eee(tp); - } -} - -static inline void rtl8125_delete_esd_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8125_request_esd_timer(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8125_esd_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8125_esd_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8125_ESD_TIMEOUT); -} - -/* -static inline void rtl8125_delete_link_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8125_request_link_timer(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8125_link_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8125_link_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); -} -*/ - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void -rtl8125_netpoll(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - for (i = 0; i < tp->irq_nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - struct r8125_napi *r8125napi = &tp->r8125napi[i]; - - disable_irq(irq->vector); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) - irq->handler(irq->vector, r8125napi); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - irq->handler(irq->vector, r8125napi, NULL); -#else - irq->handler(irq->vector, r8125napi); -#endif - - enable_irq(irq->vector); - } -} -#endif //CONFIG_NET_POLL_CONTROLLER - -static void -rtl8125_get_bios_setting(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->bios_setting = RTL_R32(tp, TimeInt2); - break; - } -} - -static void -rtl8125_set_bios_setting(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W32(tp, TimeInt2, tp->bios_setting); - break; - } -} - -static void -rtl8125_setup_mqs_reg(struct rtl8125_private *tp) -{ - int i; - - //tx - tp->tx_ring[0].tdsar_reg = TxDescStartAddrLow; - for (i = 1; i < R8125_MAX_TX_QUEUES; i++) { - tp->tx_ring[i].tdsar_reg = (u16)(TNPDS_Q1_LOW_8125 + (i - 1) * 8); - } - - for (i = 0; i < R8125_MAX_TX_QUEUES; i++) { - tp->tx_ring[i].hw_clo_ptr_reg = (u16)(HW_CLO_PTR0_8125 + i * 4); - tp->tx_ring[i].sw_tail_ptr_reg = (u16)(SW_TAIL_PTR0_8125 + i * 4); - } - - //rx - tp->rx_ring[0].rdsar_reg = RxDescAddrLow; - for (i = 1; i < R8125_MAX_RX_QUEUES; i++) { - tp->rx_ring[i].rdsar_reg = (u16)(RDSAR_Q1_LOW_8125 + (i - 1) * 8); - } - - tp->isr_reg[0] = ISR0_8125; - for (i = 1; i < R8125_MAX_QUEUES; i++) { - tp->isr_reg[i] = (u16)(ISR1_8125 + (i - 1) * 4); - } - - tp->imr_reg[0] = IMR0_8125; - for (i = 1; i < R8125_MAX_QUEUES; i++) { - tp->imr_reg[i] = (u16)(IMR1_8125 + (i - 1) * 4); - } -} - -static void -rtl8125_init_software_variable(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8125_get_bios_setting(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - //tp->HwSuppDashVer = 3; - break; - default: - tp->HwSuppDashVer = 0; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwPkgDet = rtl8125_mac_ocp_read(tp, 0xDC00); - tp->HwPkgDet = (tp->HwPkgDet >> 3) & 0x07; - break; - } - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) - eee_enable = 0; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppNowIsOobVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwPcieSNOffset = 0x16C; - break; - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_get_realwow_hw_version(dev); -#endif //ENABLE_REALWOW_SUPPORT - - if (HW_DASH_SUPPORT_DASH(tp) && rtl8125_check_dash(tp)) - tp->DASH = 1; - else - tp->DASH = 0; - - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u64 CmacMemPhysAddress; - void __iomem *cmac_ioaddr = NULL; - - //map CMAC IO space - CmacMemPhysAddress = rtl8125_csi_other_fun_read(tp, 0, 0x18); - if (!(CmacMemPhysAddress & BIT_0)) { - if (CmacMemPhysAddress & BIT_2) - CmacMemPhysAddress |= (u64)rtl8125_csi_other_fun_read(tp, 0, 0x1C) << 32; - - CmacMemPhysAddress &= 0xFFFFFFF0; - /* ioremap MMIO region */ - cmac_ioaddr = ioremap(CmacMemPhysAddress, R8125_REGS_SIZE); - } - - if (cmac_ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap CMAC MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - } - - if (cmac_ioaddr == NULL) { - tp->DASH = 0; - } else { - tp->mapped_cmac_ioaddr = cmac_ioaddr; - } - } - - eee_enable = 0; - } - - if (HW_DASH_SUPPORT_TYPE_3(tp)) - tp->cmac_ioaddr = tp->mapped_cmac_ioaddr; - - if (aspm) { - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->org_pci_offset_99 = rtl8125_csi_fun0_read_byte(tp, 0x99); - tp->org_pci_offset_99 &= ~(BIT_5|BIT_6); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x264); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x214); - break; - } - } - - pci_read_config_byte(pdev, 0x80, &tp->org_pci_offset_80); - pci_read_config_byte(pdev, 0x81, &tp->org_pci_offset_81); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - tp->use_timer_interrrupt = TRUE; - break; - } - - if (timer_count == 0 || tp->mcfg == CFG_METHOD_DEFAULT) - tp->use_timer_interrrupt = FALSE; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V3; - break; - default: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_NOT_SUPPORT; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppLinkChgWakeUpVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppD0SpeedUpVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppCheckPhyDisableModeVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppGigaForceMode = TRUE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppTxNoCloseVer = 3; - break; - } - - if (tp->HwSuppTxNoCloseVer > 0 && tx_no_close_enable == 1) - tp->EnableTxNoClose = TRUE; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->RequireLSOPatch = TRUE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_2; - break; - case CFG_METHOD_3: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_3; - break; - case CFG_METHOD_4: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_4; - break; - case CFG_METHOD_5: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_5; - break; - } - - if (tp->HwIcVerUnknown) { - tp->NotWrRamCodeToMicroP = TRUE; - tp->NotWrMcuPatchCode = TRUE; - } - - switch (tp->mcfg) { - case CFG_METHOD_3: - if ((rtl8125_mac_ocp_read(tp, 0xD442) & BIT_5) && - (mdio_direct_read_phy_ocp(tp, 0xD068) & BIT_1) - ) { - tp->RequirePhyMdiSwapPatch = TRUE; - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppNumTxQueues = 2; - tp->HwSuppNumRxQueues = 4; - break; - default: - tp->HwSuppNumTxQueues = 1; - tp->HwSuppNumRxQueues = 1; - break; - } - - tp->num_tx_rings = 1; -#ifdef ENABLE_MULTIPLE_TX_QUEUE -#ifndef ENABLE_LIB_SUPPORT - tp->num_tx_rings = tp->HwSuppNumTxQueues; -#endif -#endif - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppRssVer = 5; - tp->HwSuppIndirTblEntries = 128; - break; - } - - tp->num_rx_rings = 1; -#ifdef ENABLE_RSS_SUPPORT -#ifdef ENABLE_LIB_SUPPORT - if (tp->HwSuppRssVer > 0) - tp->EnableRss = 1; -#else - if (tp->HwSuppRssVer > 0) { - u8 rss_queue_num = netif_get_num_default_rss_queues(); - tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)? - rss_queue_num : tp->HwSuppNumRxQueues; - - if (!(tp->num_rx_rings >= 2 && tp->irq_nvecs >= tp->num_rx_rings)) - tp->num_rx_rings = 1; - - if (tp->num_rx_rings >= 2) - tp->EnableRss = 1; - } -#endif - if (tp->EnableRss) - rtl8125_init_rss(tp); -#endif - - rtl8125_setup_mqs_reg(tp); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppPtpVer = 1; - break; - } -#ifdef ENABLE_PTP_SUPPORT - if (tp->HwSuppPtpVer > 0) - tp->EnablePtp = 1; -#endif - - tp->InitRxDescType = RX_DESC_RING_TYPE_1; - if (tp->EnableRss || tp->EnablePtp) - tp->InitRxDescType = RX_DESC_RING_TYPE_3; - - tp->RxDescLength = RX_DESC_LEN_TYPE_1; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - tp->RxDescLength = RX_DESC_LEN_TYPE_3; - tp->RxDescRingLength = NUM_RX_DESC * tp->RxDescLength; - - tp->rtl8125_rx_config = rtl_chip_info[tp->chipset].RCR_Cfg; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - tp->rtl8125_rx_config |= EnableRxDescV3; - - //init interrupt - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppIsrVer = 2; - break; - default: - tp->HwSuppIsrVer = 1; - break; - } - - tp->HwCurrIsrVer = tp->HwSuppIsrVer; - if (tp->HwSuppIsrVer == 2 && !(tp->features & RTL_FEATURE_MSIX)) - tp->HwCurrIsrVer = 1; - - if (tp->HwCurrIsrVer < 2 || tp->irq_nvecs < 19) - tp->num_tx_rings = 1; - - if (tp->HwCurrIsrVer == 2) { - int i; - - tp->intr_mask = ISRIMR_V2_LINKCHG | ISRIMR_TOK_Q0; - if (tp->num_tx_rings > 1) - tp->intr_mask |= ISRIMR_TOK_Q1; - - for (i = 0; i < tp->num_rx_rings; i++) - tp->intr_mask |= ISRIMR_V2_ROK_Q0 << i; - } else { - tp->intr_mask = LinkChg | RxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = LinkChg | PCSTimeout; - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - tp->timer_intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - tp->intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - } - } -#endif - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->HwSuppIntMitiVer = 3; - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppIntMitiVer = 4; - break; - } - - timer_count_v2 = (timer_count / 0x100); - - tp->NicCustLedValue = RTL_R16(tp, CustomLED); - - tp->wol_opts = rtl8125_get_hw_wol(tp); - tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; - - rtl8125_link_option((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); - - tp->autoneg = autoneg_mode; - tp->speed = speed_mode; - tp->duplex = duplex_mode; - tp->advertising = advertising_mode; - tp->fcpause = rtl8125_fc_full; - - tp->max_jumbo_frame_size = rtl_chip_info[tp->chipset].jumbo_frame_sz; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - /* MTU range: 60 - hw-specific max */ - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - tp->eee_enabled = eee_enable; - tp->eee_adv_t = MDIO_EEE_1000T | MDIO_EEE_100TX; - - tp->ptp_master_mode = enable_ptp_master_mode; -} - -static void -rtl8125_release_board(struct pci_dev *pdev, - struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8125_set_bios_setting(dev); - rtl8125_rar_set(tp, tp->org_mac_addr); - tp->wol_enabled = WOL_DISABLED; - - if (!tp->DASH) - rtl8125_phy_power_down(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - FreeAllocatedDashShareMemory(dev); -#endif - - if (tp->mapped_cmac_ioaddr != NULL) - iounmap(tp->mapped_cmac_ioaddr); - - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static int -rtl8125_get_mac_address(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - u8 mac_addr[MAC_ADDR_LEN]; - - for (i = 0; i < MAC_ADDR_LEN; i++) - mac_addr[i] = RTL_R8(tp, MAC0 + i); - - if(tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - *(u32*)&mac_addr[0] = RTL_R32(tp, BACKUP_ADDR0_8125); - *(u16*)&mac_addr[4] = RTL_R16(tp, BACKUP_ADDR1_8125); - } - - if (!is_valid_ether_addr(mac_addr)) { - netif_err(tp, probe, dev, "Invalid ether addr %pM\n", - mac_addr); - eth_hw_addr_random(dev); - ether_addr_copy(mac_addr, dev->dev_addr); - netif_info(tp, probe, dev, "Random ether addr %pM\n", - mac_addr); - tp->random_mac = 1; - } - - rtl8125_rar_set(tp, mac_addr); - - for (i = 0; i < MAC_ADDR_LEN; i++) { - dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); - tp->org_mac_addr[i] = dev->dev_addr[i]; /* keep the original MAC address */ - } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); -#endif -// memcpy(dev->dev_addr, dev->dev_addr, dev->addr_len); - - return 0; -} - -/** - * rtl8125_set_mac_address - Change the Ethernet Address of the NIC - * @dev: network interface device structure - * @p: pointer to an address structure - * - * Return 0 on success, negative on failure - **/ -static int -rtl8125_set_mac_address(struct net_device *dev, - void *p) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - unsigned long flags; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - spin_lock_irqsave(&tp->lock, flags); - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl8125_rar_set(tp, dev->dev_addr); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -/****************************************************************************** - * rtl8125_rar_set - Puts an ethernet address into a receive address register. - * - * tp - The private data structure for driver - * addr - Address to put into receive address register - *****************************************************************************/ -void -rtl8125_rar_set(struct rtl8125_private *tp, - uint8_t *addr) -{ - uint32_t rar_low = 0; - uint32_t rar_high = 0; - - rar_low = ((uint32_t) addr[0] | - ((uint32_t) addr[1] << 8) | - ((uint32_t) addr[2] << 16) | - ((uint32_t) addr[3] << 24)); - - rar_high = ((uint32_t) addr[4] | - ((uint32_t) addr[5] << 8)); - - rtl8125_enable_cfg9346_write(tp); - RTL_W32(tp, MAC0, rar_low); - RTL_W32(tp, MAC4, rar_high); - - rtl8125_disable_cfg9346_write(tp); -} - -#ifdef ETHTOOL_OPS_COMPAT -static int ethtool_get_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - int err; - - if (!ethtool_ops->get_settings) - return -EOPNOTSUPP; - - err = ethtool_ops->get_settings(dev, &cmd); - if (err < 0) - return err; - - if (copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; -} - -static int ethtool_set_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd; - - if (!ethtool_ops->set_settings) - return -EOPNOTSUPP; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - return ethtool_ops->set_settings(dev, &cmd); -} - -static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) -{ - struct ethtool_drvinfo info; - struct ethtool_ops *ops = ethtool_ops; - - if (!ops->get_drvinfo) - return -EOPNOTSUPP; - - memset(&info, 0, sizeof(info)); - info.cmd = ETHTOOL_GDRVINFO; - ops->get_drvinfo(dev, &info); - - if (ops->self_test_count) - info.testinfo_len = ops->self_test_count(dev); - if (ops->get_stats_count) - info.n_stats = ops->get_stats_count(dev); - if (ops->get_regs_len) - info.regdump_len = ops->get_regs_len(dev); - if (ops->get_eeprom_len) - info.eedump_len = ops->get_eeprom_len(dev); - - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int ethtool_get_regs(struct net_device *dev, char *useraddr) -{ - struct ethtool_regs regs; - struct ethtool_ops *ops = ethtool_ops; - void *regbuf; - int reglen, ret; - - if (!ops->get_regs || !ops->get_regs_len) - return -EOPNOTSUPP; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - - reglen = ops->get_regs_len(dev); - if (regs.len > reglen) - regs.len = reglen; - - regbuf = kmalloc(reglen, GFP_USER); - if (!regbuf) - return -ENOMEM; - - ops->get_regs(dev, ®s, regbuf); - - ret = -EFAULT; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - goto out; - useraddr += offsetof(struct ethtool_regs, data); - if (copy_to_user(useraddr, regbuf, reglen)) - goto out; - ret = 0; - -out: - kfree(regbuf); - return ret; -} - -static int ethtool_get_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - if (!ethtool_ops->get_wol) - return -EOPNOTSUPP; - - ethtool_ops->get_wol(dev, &wol); - - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; -} - -static int ethtool_set_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol; - - if (!ethtool_ops->set_wol) - return -EOPNOTSUPP; - - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - - return ethtool_ops->set_wol(dev, &wol); -} - -static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - - if (!ethtool_ops->get_msglevel) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_msglevel(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_msglevel) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_msglevel(dev, edata.data); - return 0; -} - -static int ethtool_nway_reset(struct net_device *dev) -{ - if (!ethtool_ops->nway_reset) - return -EOPNOTSUPP; - - return ethtool_ops->nway_reset(dev); -} - -static int ethtool_get_link(struct net_device *dev, void *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - if (!ethtool_ops->get_link) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_link(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->get_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - ret = -EFAULT; - if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) - goto out; - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->set_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->set_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - ret = -EFAULT; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - ethtool_ops->get_coalesce(dev, &coalesce); - - if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) - return -EFAULT; - return 0; -} - -static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) - return -EFAULT; - - return ethtool_ops->set_coalesce(dev, &coalesce); -} - -static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - ethtool_ops->get_ringparam(dev, &ringparam); - - if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) - return -EFAULT; - - return ethtool_ops->set_ringparam(dev, &ringparam); -} - -static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - ethtool_ops->get_pauseparam(dev, &pauseparam); - - if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) - return -EFAULT; - - return ethtool_ops->set_pauseparam(dev, &pauseparam); -} - -static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - if (!ethtool_ops->get_rx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_rx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_rx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_rx_csum(dev, edata.data); - return 0; -} - -static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - if (!ethtool_ops->get_tx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tx_csum(dev, edata.data); -} - -static int ethtool_get_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GSG }; - - if (!ethtool_ops->get_sg) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_sg(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_sg) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_sg(dev, edata.data); -} - -static int ethtool_get_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTSO }; - - if (!ethtool_ops->get_tso) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tso(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tso) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tso(dev, edata.data); -} - -static int ethtool_self_test(struct net_device *dev, char *useraddr) -{ - struct ethtool_test test; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->self_test || !ops->self_test_count) - return -EOPNOTSUPP; - - if (copy_from_user(&test, useraddr, sizeof(test))) - return -EFAULT; - - test.len = ops->self_test_count(dev); - data = kmalloc(test.len * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->self_test(dev, &test, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &test, sizeof(test))) - goto out; - useraddr += sizeof(test); - if (copy_to_user(useraddr, data, test.len * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_strings(struct net_device *dev, void *useraddr) -{ - struct ethtool_gstrings gstrings; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_strings) - return -EOPNOTSUPP; - - if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) - return -EFAULT; - - switch (gstrings.string_set) { - case ETH_SS_TEST: - if (!ops->self_test_count) - return -EOPNOTSUPP; - gstrings.len = ops->self_test_count(dev); - break; - case ETH_SS_STATS: - if (!ops->get_stats_count) - return -EOPNOTSUPP; - gstrings.len = ops->get_stats_count(dev); - break; - default: - return -EINVAL; - } - - data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_strings(dev, gstrings.string_set, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) - goto out; - useraddr += sizeof(gstrings); - if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_phys_id(struct net_device *dev, void *useraddr) -{ - struct ethtool_value id; - - if (!ethtool_ops->phys_id) - return -EOPNOTSUPP; - - if (copy_from_user(&id, useraddr, sizeof(id))) - return -EFAULT; - - return ethtool_ops->phys_id(dev, id.data); -} - -static int ethtool_get_stats(struct net_device *dev, void *useraddr) -{ - struct ethtool_stats stats; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->get_ethtool_stats || !ops->get_stats_count) - return -EOPNOTSUPP; - - if (copy_from_user(&stats, useraddr, sizeof(stats))) - return -EFAULT; - - stats.n_stats = ops->get_stats_count(dev); - data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_ethtool_stats(dev, &stats, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &stats, sizeof(stats))) - goto out; - useraddr += sizeof(stats); - if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_ioctl(struct ifreq *ifr) -{ - struct net_device *dev = __dev_get_by_name(ifr->ifr_name); - void *useraddr = (void *) ifr->ifr_data; - u32 ethcmd; - - /* - * XXX: This can be pushed down into the ethtool_* handlers that - * need it. Keep existing behaviour for the moment. - */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!dev || !netif_device_present(dev)) - return -ENODEV; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GSET: - return ethtool_get_settings(dev, useraddr); - case ETHTOOL_SSET: - return ethtool_set_settings(dev, useraddr); - case ETHTOOL_GDRVINFO: - return ethtool_get_drvinfo(dev, useraddr); - case ETHTOOL_GREGS: - return ethtool_get_regs(dev, useraddr); - case ETHTOOL_GWOL: - return ethtool_get_wol(dev, useraddr); - case ETHTOOL_SWOL: - return ethtool_set_wol(dev, useraddr); - case ETHTOOL_GMSGLVL: - return ethtool_get_msglevel(dev, useraddr); - case ETHTOOL_SMSGLVL: - return ethtool_set_msglevel(dev, useraddr); - case ETHTOOL_NWAY_RST: - return ethtool_nway_reset(dev); - case ETHTOOL_GLINK: - return ethtool_get_link(dev, useraddr); - case ETHTOOL_GEEPROM: - return ethtool_get_eeprom(dev, useraddr); - case ETHTOOL_SEEPROM: - return ethtool_set_eeprom(dev, useraddr); - case ETHTOOL_GCOALESCE: - return ethtool_get_coalesce(dev, useraddr); - case ETHTOOL_SCOALESCE: - return ethtool_set_coalesce(dev, useraddr); - case ETHTOOL_GRINGPARAM: - return ethtool_get_ringparam(dev, useraddr); - case ETHTOOL_SRINGPARAM: - return ethtool_set_ringparam(dev, useraddr); - case ETHTOOL_GPAUSEPARAM: - return ethtool_get_pauseparam(dev, useraddr); - case ETHTOOL_SPAUSEPARAM: - return ethtool_set_pauseparam(dev, useraddr); - case ETHTOOL_GRXCSUM: - return ethtool_get_rx_csum(dev, useraddr); - case ETHTOOL_SRXCSUM: - return ethtool_set_rx_csum(dev, useraddr); - case ETHTOOL_GTXCSUM: - return ethtool_get_tx_csum(dev, useraddr); - case ETHTOOL_STXCSUM: - return ethtool_set_tx_csum(dev, useraddr); - case ETHTOOL_GSG: - return ethtool_get_sg(dev, useraddr); - case ETHTOOL_SSG: - return ethtool_set_sg(dev, useraddr); - case ETHTOOL_GTSO: - return ethtool_get_tso(dev, useraddr); - case ETHTOOL_STSO: - return ethtool_set_tso(dev, useraddr); - case ETHTOOL_TEST: - return ethtool_self_test(dev, useraddr); - case ETHTOOL_GSTRINGS: - return ethtool_get_strings(dev, useraddr); - case ETHTOOL_PHYS_ID: - return ethtool_phys_id(dev, useraddr); - case ETHTOOL_GSTATS: - return ethtool_get_stats(dev, useraddr); - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} -#endif //ETHTOOL_OPS_COMPAT - -static int -rtl8125_do_ioctl(struct net_device *dev, - struct ifreq *ifr, - int cmd) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - int ret; - unsigned long flags; - - ret = 0; - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - break; - - case SIOCGMIIREG: - spin_lock_irqsave(&tp->lock, flags); - rtl8125_mdio_write(tp, 0x1F, 0x0000); - data->val_out = rtl8125_mdio_read(tp, data->reg_num); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - spin_lock_irqsave(&tp->lock, flags); - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, data->reg_num, data->val_in); - spin_unlock_irqrestore(&tp->lock, flags); - break; - -#ifdef ETHTOOL_OPS_COMPAT - case SIOCETHTOOL: - ret = ethtool_ioctl(ifr); - break; -#endif - -#ifdef ENABLE_DASH_SUPPORT - case SIOCDEVPRIVATE_RTLDASH: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8125_dash_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_REALWOW_SUPPORT - case SIOCDEVPRIVATE_RTLREALWOW: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - ret = rtl8125_realwow_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_PTP_SUPPORT - case SIOCSHWTSTAMP: - case SIOCGHWTSTAMP: - if (tp->EnablePtp) - ret = rtl8125_ptp_ioctl(dev, ifr, cmd); - else - ret = -EOPNOTSUPP; - break; -#endif - case SIOCRTLTOOL: - ret = rtl8125_tool_ioctl(tp, ifr); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8125_phy_power_up(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) { - return; - } - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE); - - //wait ups resume (phy state 3) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_wait_phy_ups_resume(dev, 3); - break; - }; -} - -static void -rtl8125_phy_power_down(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); -} - -static int __devinit -rtl8125_init_board(struct pci_dev *pdev, - struct net_device **dev_out, - void __iomem **ioaddr_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8125_private *tp; - int rc = -ENOMEM, i, pm_cap; - - assert(ioaddr_out != NULL); - - /* dev zeroed in alloc_etherdev */ - dev = alloc_etherdev_mq(sizeof (*tp), R8125_MAX_QUEUES); - if (dev == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out; - } - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8125_MSG_DEFAULT); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - if (!aspm) - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); -#endif - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_dev; - } - - rc = pci_set_mwi(pdev); - if (rc < 0) - goto err_out_disable; - - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command; - - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - } else { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, "PowerManagement capability not found.\n"); - } -#else - printk("PowerManagement capability not found.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - } - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, 2) < R8125_REGS_SIZE) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_mwi; - } - - if ((sizeof(dma_addr_t) > 4) && - use_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "DMA configuration failed.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_res; - } - } - - pci_set_master(pdev); - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); - if (ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -EIO; - goto err_out_free_res; - } - - tp->mmio_addr = ioaddr; - - /* Identify chip attached to board */ - rtl8125_get_mac_version(tp); - - rtl8125_print_mac_version(tp); - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) - break; - } - - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8125 */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_printk(KERN_DEBUG, &pdev->dev, "unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#else - printk("Realtek unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - i++; - } - - tp->chipset = i; - - *ioaddr_out = ioaddr; - *dev_out = dev; -out: - return rc; - -err_out_free_res: - pci_release_regions(pdev); - -err_out_mwi: - pci_clear_mwi(pdev); - -err_out_disable: - pci_disable_device(pdev); - -err_out_free_dev: - free_netdev(dev); -err_out: - *ioaddr_out = NULL; - *dev_out = NULL; - goto out; -} - -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8125_esd_timer(unsigned long __opaque) -#else -rtl8125_esd_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#else - struct rtl8125_private *tp = from_timer(tp, t, esd_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - struct pci_dev *pdev = tp->pci_dev; - unsigned long timeout = RTL8125_ESD_TIMEOUT; - unsigned long flags; - u8 cmd; - u16 io_base_l; - u16 mem_base_l; - u16 mem_base_h; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_l; - u16 resv_0x20_h; - u16 resv_0x24_l; - u16 resv_0x24_h; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; - - spin_lock_irqsave(&tp->lock, flags); - - tp->esd_flag = 0; - - pci_read_config_byte(pdev, PCI_COMMAND, &cmd); - if (cmd != tp->pci_cfg_space.cmd) { - printk(KERN_ERR "%s: cmd = 0x%02x, should be 0x%02x \n.", dev->name, cmd, tp->pci_cfg_space.cmd); - pci_write_config_byte(pdev, PCI_COMMAND, tp->pci_cfg_space.cmd); - tp->esd_flag |= BIT_0; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); - if (io_base_l != tp->pci_cfg_space.io_base_l) { - printk(KERN_ERR "%s: io_base_l = 0x%04x, should be 0x%04x \n.", dev->name, io_base_l, tp->pci_cfg_space.io_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); - tp->esd_flag |= BIT_1; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); - if (mem_base_l != tp->pci_cfg_space.mem_base_l) { - printk(KERN_ERR "%s: mem_base_l = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_l, tp->pci_cfg_space.mem_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); - tp->esd_flag |= BIT_2; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); - if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { - printk(KERN_ERR "%s: mem_base_h = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_h, tp->pci_cfg_space.mem_base_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); - tp->esd_flag |= BIT_3; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); - if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { - printk(KERN_ERR "%s: resv_0x1c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_l, tp->pci_cfg_space.resv_0x1c_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); - tp->esd_flag |= BIT_4; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); - if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { - printk(KERN_ERR "%s: resv_0x1c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_h, tp->pci_cfg_space.resv_0x1c_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); - tp->esd_flag |= BIT_5; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &resv_0x20_l); - if (resv_0x20_l != tp->pci_cfg_space.resv_0x20_l) { - printk(KERN_ERR "%s: resv_0x20_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_l, tp->pci_cfg_space.resv_0x20_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4, tp->pci_cfg_space.resv_0x20_l); - tp->esd_flag |= BIT_6; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &resv_0x20_h); - if (resv_0x20_h != tp->pci_cfg_space.resv_0x20_h) { - printk(KERN_ERR "%s: resv_0x20_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_h, tp->pci_cfg_space.resv_0x20_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, tp->pci_cfg_space.resv_0x20_h); - tp->esd_flag |= BIT_7; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &resv_0x24_l); - if (resv_0x24_l != tp->pci_cfg_space.resv_0x24_l) { - printk(KERN_ERR "%s: resv_0x24_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_l, tp->pci_cfg_space.resv_0x24_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5, tp->pci_cfg_space.resv_0x24_l); - tp->esd_flag |= BIT_8; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &resv_0x24_h); - if (resv_0x24_h != tp->pci_cfg_space.resv_0x24_h) { - printk(KERN_ERR "%s: resv_0x24_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_h, tp->pci_cfg_space.resv_0x24_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, tp->pci_cfg_space.resv_0x24_h); - tp->esd_flag |= BIT_9; - } - - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); - if (ilr != tp->pci_cfg_space.ilr) { - printk(KERN_ERR "%s: ilr = 0x%02x, should be 0x%02x \n.", dev->name, ilr, tp->pci_cfg_space.ilr); - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); - tp->esd_flag |= BIT_10; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); - if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { - printk(KERN_ERR "%s: resv_0x2c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_l, tp->pci_cfg_space.resv_0x2c_l); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); - tp->esd_flag |= BIT_11; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); - if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { - printk(KERN_ERR "%s: resv_0x2c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_h, tp->pci_cfg_space.resv_0x2c_h); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); - tp->esd_flag |= BIT_12; - } - - if (tp->HwPcieSNOffset > 0) { - pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); - if (pci_sn_l != tp->pci_cfg_space.pci_sn_l) { - printk(KERN_ERR "%s: pci_sn_l = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_l, tp->pci_cfg_space.pci_sn_l); - rtl8125_csi_write(tp, tp->HwPcieSNOffset, tp->pci_cfg_space.pci_sn_l); - tp->esd_flag |= BIT_13; - } - - pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); - if (pci_sn_h != tp->pci_cfg_space.pci_sn_h) { - printk(KERN_ERR "%s: pci_sn_h = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_h, tp->pci_cfg_space.pci_sn_h); - rtl8125_csi_write(tp, tp->HwPcieSNOffset + 4, tp->pci_cfg_space.pci_sn_h); - tp->esd_flag |= BIT_14; - } - } - - if (tp->esd_flag != 0) { - printk(KERN_ERR "%s: esd_flag = 0x%04x\n.\n", dev->name, tp->esd_flag); - rtl8125_stop_all_tx_queue(dev); - netif_carrier_off(dev); - rtl8125_hw_reset(dev); - rtl8125_tx_clear(tp); - rtl8125_rx_clear(tp); - rtl8125_init_ring(dev); - rtl8125_hw_init(dev); - rtl8125_powerup_pll(dev); - rtl8125_hw_ephy_config(dev); - rtl8125_hw_phy_config(dev); - rtl8125_hw_config(dev); - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - tp->esd_flag = 0; - } - spin_unlock_irqrestore(&tp->lock, flags); - - mod_timer(timer, jiffies + timeout); -} - -/* -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8125_link_timer(unsigned long __opaque) -#else -rtl8125_link_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; -#else - struct rtl8125_private *tp = from_timer(tp, t, link_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_check_link_status(dev, 0); - spin_unlock_irqrestore(&tp->lock, flags); - - mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); -} -*/ - -int -rtl8125_enable_msix(struct rtl8125_private *tp) -{ - int i, nvecs = 0; - struct msix_entry msix_ent[R8125_MAX_MSIX_VEC]; - //struct net_device *dev = tp->dev; - //const int len = sizeof(tp->irq_tbl[0].name); - - for (i = 0; i < R8125_MAX_MSIX_VEC; i++) { - msix_ent[i].entry = i; - msix_ent[i].vector = 0; - } - - nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent, - tp->min_irq_nvecs, tp->max_irq_nvecs); - if (nvecs < 0) - goto out; - - for (i = 0; i < nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - irq->vector = msix_ent[i].vector; - //snprintf(irq->name, len, "%s-%d", dev->name, i); - //irq->handler = rtl8125_interrupt_msix; - } - -out: - return nvecs; -} - -void rtl8125_dump_msix_tbl(struct rtl8125_private *tp) -{ - void __iomem *ioaddr; - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(tp->pci_dev, 4), pci_resource_len(tp->pci_dev, 4)); - if (ioaddr) { - int i = 0; - for (i=0; iirq_nvecs; i++) { - printk("entry 0x%d %08X %08X %08X %08X \n", - i, - readl(ioaddr + 16 * i), - readl(ioaddr + 16 * i + 4), - readl(ioaddr + 16 * i + 8), - readl(ioaddr + 16 * i + 12)); - } - iounmap(ioaddr); - } -} - -/* Cfg9346_Unlock assumed. */ -static int rtl8125_try_msi(struct rtl8125_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - unsigned msi = 0; - int nvecs = 1; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->max_irq_nvecs = R8125_MAX_MSIX_VEC_8125B; - tp->min_irq_nvecs = R8125_MIN_MSIX_VEC_8125B; - break; - default: - tp->max_irq_nvecs = 1; - tp->min_irq_nvecs = 1; - break; - } - -#if defined(RTL_USE_NEW_INTR_API) - if ((nvecs = pci_alloc_irq_vectors(pdev, tp->min_irq_nvecs, tp->max_irq_nvecs, PCI_IRQ_MSIX)) > 0) - msi |= RTL_FEATURE_MSIX; - else if ((nvecs = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES)) > 0 && - pci_dev_msi_enabled(pdev)) - msi |= RTL_FEATURE_MSI; -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - if ((nvecs = rtl8125_enable_msix(tp)) > 0) - msi |= RTL_FEATURE_MSIX; - else if (!pci_enable_msi(pdev)) - msi |= RTL_FEATURE_MSI; -#endif - if (!(msi & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) - dev_info(&pdev->dev, "no MSI/MSI-X. Back to INTx.\n"); - - if (!(msi & RTL_FEATURE_MSIX) || nvecs < 1) - nvecs = 1; - - tp->irq_nvecs = nvecs; - - tp->features |= msi; - - return nvecs; -} - -static void rtl8125_disable_msi(struct pci_dev *pdev, struct rtl8125_private *tp) -{ -#if defined(RTL_USE_NEW_INTR_API) - if (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) - pci_free_irq_vectors(pdev); -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - if (tp->features & (RTL_FEATURE_MSIX)) - pci_disable_msix(pdev); - else if (tp->features & (RTL_FEATURE_MSI)) - pci_disable_msi(pdev); -#endif - tp->features &= ~(RTL_FEATURE_MSI | RTL_FEATURE_MSIX); -} - -static int rtl8125_get_irq(struct pci_dev *pdev) -{ -#if defined(RTL_USE_NEW_INTR_API) - return pci_irq_vector(pdev, 0); -#else - return pdev->irq; -#endif -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static const struct net_device_ops rtl8125_netdev_ops = { - .ndo_open = rtl8125_open, - .ndo_stop = rtl8125_close, - .ndo_get_stats = rtl8125_get_stats, - .ndo_start_xmit = rtl8125_start_xmit, - .ndo_tx_timeout = rtl8125_tx_timeout, - .ndo_change_mtu = rtl8125_change_mtu, - .ndo_set_mac_address = rtl8125_set_mac_address, - .ndo_do_ioctl = rtl8125_do_ioctl, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) - .ndo_set_multicast_list = rtl8125_set_rx_mode, -#else - .ndo_set_rx_mode = rtl8125_set_rx_mode, -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) -#ifdef CONFIG_R8125_VLAN - .ndo_vlan_rx_register = rtl8125_vlan_rx_register, -#endif -#else - .ndo_fix_features = rtl8125_fix_features, - .ndo_set_features = rtl8125_set_features, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8125_netpoll, -#endif -}; -#endif - - -#ifdef CONFIG_R8125_NAPI - -static int rtl8125_poll(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - //unsigned long flags; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); - - //spin_lock_irqsave(&tp->lock, flags); - for (i = 0; i < tp->num_tx_rings; i++) - rtl8125_tx_interrupt(&tp->tx_ring[i], budget); - //spin_unlock_irqrestore(&tp->lock, flags); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - struct net_device *dev = tp->dev; - - spin_lock_irqsave(&tp->lock, flags); - HandleDashInterrupt(dev); - spin_unlock_irqrestore(&tp->lock, flags); - } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_switch_to_timer_interrupt(tp); - } - - return RTL_NAPI_RETURN_VALUE; -} - -#if 0 -static int rtl8125_poll_msix_ring(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - unsigned long flags; - const int message_id = r8125napi->index; - - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); - - //spin_lock_irqsave(&tp->lock, flags); - rtl8125_tx_interrupt_with_vector(tp, message_id, budget); - //spin_unlock_irqrestore(&tp->lock, flags); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && message_id == 0) { - struct net_device *dev = tp->dev; - - spin_lock_irqsave(&tp->lock, flags); - HandleDashInterrupt(dev); - spin_unlock_irqrestore(&tp->lock, flags); - } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} -#endif - -static int rtl8125_poll_msix_tx(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - //unsigned long flags; - const int message_id = r8125napi->index; - - //suppress unused variable - (void)(dev); - - //spin_lock_irqsave(&tp->lock, flags); - rtl8125_tx_interrupt_with_vector(tp, message_id, budget); - //spin_unlock_irqrestore(&tp->lock, flags); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} - -static int rtl8125_poll_msix_other(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - const int message_id = r8125napi->index; - - //suppress unused variable - (void)(dev); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); -#endif - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - - return 1; -} - -static int rtl8125_poll_msix_rx(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - const int message_id = r8125napi->index; - - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} - -static void rtl8125_enable_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_ENABLE(tp->dev, &tp->r8125napi[i].napi); -#endif -} - -static void rtl8125_disable_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_DISABLE(tp->dev, &tp->r8125napi[i].napi); -#endif -} - -static void rtl8125_del_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_DEL((&tp->r8125napi[i])); -#endif -} -#endif //CONFIG_R8125_NAPI - -static void rtl8125_init_napi(struct rtl8125_private *tp) -{ - int i; - - for (i=0; iirq_nvecs; i++) { - struct r8125_napi *r8125napi = &tp->r8125napi[i]; -#ifdef CONFIG_R8125_NAPI - int (*poll)(struct napi_struct *, int); - - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) { - if (i < R8125_MAX_RX_QUEUES_VEC_V3) - poll = rtl8125_poll_msix_rx; - else if (i == 16 || i == 18) - poll = rtl8125_poll_msix_tx; - else - poll = rtl8125_poll_msix_other; - } else { - poll = rtl8125_poll; - } - - RTL_NAPI_CONFIG(tp->dev, r8125napi, poll, R8125_NAPI_WEIGHT); -#endif - - r8125napi->priv = tp; - r8125napi->index = i; - } -} - -static int __devinit -rtl8125_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8125_private *tp; - void __iomem *ioaddr = NULL; - static int board_idx = -1; - - int rc; - - assert(pdev != NULL); - assert(ent != NULL); - - board_idx++; - - if (netif_msg_drv(&debug)) - printk(KERN_INFO "%s 2.5Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8125_VERSION); - - rc = rtl8125_init_board(pdev, &dev, &ioaddr); - if (rc) - goto out; - - tp = netdev_priv(dev); - assert(ioaddr != NULL); - - tp->set_speed = rtl8125_set_speed_xmii; - tp->get_settings = rtl8125_gset_xmii; - tp->phy_reset_enable = rtl8125_xmii_reset_enable; - tp->phy_reset_pending = rtl8125_xmii_reset_pending; - tp->link_ok = rtl8125_xmii_link_ok; - - rc = rtl8125_try_msi(tp); - if (rc < 0) { - dev_err(&pdev->dev, "Can't allocate interrupt\n"); - goto err_out_1; - } - - spin_lock_init(&tp->lock); - - rtl8125_init_software_variable(dev); - - RTL_NET_DEVICE_OPS(rtl8125_netdev_ops); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - SET_ETHTOOL_OPS(dev, &rtl8125_ethtool_ops); -#endif - - dev->watchdog_timeo = RTL8125_TX_TIMEOUT; - dev->irq = rtl8125_get_irq(pdev); - dev->base_addr = (unsigned long) ioaddr; - - rtl8125_init_napi(tp); - -#ifdef CONFIG_R8125_VLAN - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - dev->vlan_rx_kill_vid = rtl8125_vlan_rx_kill_vid; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - } -#endif - - /* There has been a number of reports that using SG/TSO results in - * tx timeouts. However for a lot of people SG/TSO works fine. - * Therefore disable both features by default, but allow users to - * enable them. Use at own risk! - */ - tp->cp_cmd |= RTL_R16(tp, CPlusCmd); - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_IP_CSUM; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; - dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_HIGHDMA; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; - dev->features |= NETIF_F_IPV6_CSUM; - netif_set_gso_max_size(dev, LSO_64K); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO2; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) - dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -#ifdef ENABLE_RSS_SUPPORT - if (tp->EnableRss) { - dev->hw_features |= NETIF_F_RXHASH; - dev->features |= NETIF_F_RXHASH; - } -#endif - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - AllocateDashShareMemory(dev); -#endif - -#ifdef ENABLE_LIB_SUPPORT - ATOMIC_INIT_NOTIFIER_HEAD(&tp->lib_nh); -#endif - - rtl8125_exit_oob(dev); - - rtl8125_hw_init(dev); - - rtl8125_hw_reset(dev); - - /* Get production from EEPROM */ - rtl8125_eeprom_type(tp); - - if (tp->eeprom_type == EEPROM_TYPE_93C46 || tp->eeprom_type == EEPROM_TYPE_93C56) - rtl8125_set_eeprom_sel_low(tp); - - rtl8125_get_mac_address(dev); - - tp->tally_vaddr = dma_alloc_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), - &tp->tally_paddr, GFP_KERNEL); - if (!tp->tally_vaddr) { - rc = -ENOMEM; - goto err_out; - } - - rtl8125_tally_counter_clear(tp); - - pci_set_drvdata(pdev, dev); - - rc = register_netdev(dev); - if (rc) - goto err_out; - - printk(KERN_INFO "%s: This product is covered by one or more of the following patents: US6,570,884, US6,115,776, and US6,327,625.\n", MODULENAME); - - rtl8125_disable_rxdvgate(dev); - - device_set_wakeup_enable(&pdev->dev, tp->wol_enabled); - - netif_carrier_off(dev); - - printk("%s", GPL_CLAIM); - -out: - return rc; - -err_out: - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, - tp->tally_paddr); - - tp->tally_vaddr = NULL; - } -#ifdef CONFIG_R8125_NAPI - rtl8125_del_napi(tp); -#endif - rtl8125_disable_msi(pdev, tp); - -err_out_1: - rtl8125_release_board(pdev, dev); - - goto out; -} - -static void __devexit -rtl8125_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8125_private *tp = netdev_priv(dev); - - assert(dev != NULL); - assert(tp != NULL); - -#ifdef CONFIG_R8125_NAPI - rtl8125_del_napi(tp); -#endif - if (tp->DASH) - rtl8125_driver_stop(tp); - - unregister_netdev(dev); - rtl8125_disable_msi(pdev, tp); -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_remove(dev); -#endif - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, tp->tally_paddr); - tp->tally_vaddr = NULL; - } - - rtl8125_release_board(pdev, dev); - pci_set_drvdata(pdev, NULL); -} - -static void -rtl8125_set_rxbufsize(struct rtl8125_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 + 1 : RX_BUF_SIZE; -} - -static void rtl8125_free_irq(struct rtl8125_private *tp) -{ - int i; - - for (i=0; iirq_nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - struct r8125_napi *r8125napi = &tp->r8125napi[i]; - - if (irq->requested) { -#if defined(RTL_USE_NEW_INTR_API) - pci_free_irq(tp->pci_dev, i, r8125napi); -#else - free_irq(irq->vector, r8125napi); -#endif - irq->requested = 0; - } - } -} - -static int rtl8125_alloc_irq(struct rtl8125_private *tp) -{ - struct net_device *dev = tp->dev; - int rc = 0; - struct r8125_irq *irq; - struct r8125_napi *r8125napi; - int i = 0; - const int len = sizeof(tp->irq_tbl[0].name); - -#if defined(RTL_USE_NEW_INTR_API) - for (i=0; iirq_nvecs; i++) { - irq = &tp->irq_tbl[i]; - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) - irq->handler = rtl8125_interrupt_msix; - else - irq->handler = rtl8125_interrupt; - - r8125napi = &tp->r8125napi[i]; - snprintf(irq->name, len, "%s-%d", dev->name, i); - rc = pci_request_irq(tp->pci_dev, i, irq->handler, NULL, r8125napi, - irq->name); - if (rc) - break; - - irq->vector = pci_irq_vector(tp->pci_dev, i); - irq->requested = 1; - } -#else - unsigned long irq_flags = 0; -#ifdef ENABLE_LIB_SUPPORT - irq_flags |= IRQF_NO_SUSPEND; -#endif - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) { - for (i=0; iirq_nvecs; i++) { - irq = &tp->irq_tbl[i]; - irq->handler = rtl8125_interrupt_msix; - r8125napi = &tp->r8125napi[i]; - snprintf(irq->name, len, "%s-%d", dev->name, i); - rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); - - if (rc) - break; - - irq->requested = 1; - } - } else { - irq = &tp->irq_tbl[0]; - irq->handler = rtl8125_interrupt; - r8125napi = &tp->r8125napi[0]; - snprintf(irq->name, len, "%s-0", dev->name); - if (!(tp->features & RTL_FEATURE_MSIX)) - irq->vector = dev->irq; - irq_flags |= (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) ? 0 : SA_SHIRQ; - rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); - - if (rc == 0) - irq->requested = 1; - } -#endif - if (rc) - rtl8125_free_irq(tp); - - return rc; -} - -static int rtl8125_alloc_tx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_tx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - ring = &tp->tx_ring[i]; - ring->TxDescArray = dma_alloc_coherent(&pdev->dev, R8125_TX_RING_BYTES, - &ring->TxPhyAddr, GFP_KERNEL); - - if (!ring->TxDescArray) - return -1; - } - - return 0; -} - -static int rtl8125_alloc_rx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_rx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - ring = &tp->rx_ring[i]; - ring->RxDescArray = dma_alloc_coherent(&pdev->dev, tp->RxDescRingLength, - &ring->RxPhyAddr, GFP_KERNEL); - - if (!ring->RxDescArray) - return -1; - } - - return 0; -} - -static void rtl8125_free_tx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_tx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - ring = &tp->tx_ring[i]; - if (ring->TxDescArray) { - dma_free_coherent(&pdev->dev, R8125_TX_RING_BYTES, ring->TxDescArray, - ring->TxPhyAddr); - ring->TxDescArray = NULL; - } - } -} - -static void rtl8125_free_rx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_rx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - ring = &tp->rx_ring[i]; - if (ring->RxDescArray) { - dma_free_coherent(&pdev->dev, tp->RxDescRingLength, ring->RxDescArray, - ring->RxPhyAddr); - ring->RxDescArray = NULL; - } - } -} - -static void rtl8125_free_alloc_resources(struct rtl8125_private *tp) -{ - rtl8125_free_rx_desc(tp); - - rtl8125_free_tx_desc(tp); -} - -int rtl8125_set_real_num_queue(struct rtl8125_private *tp) -{ - int retval = 0; - - retval = netif_set_real_num_tx_queues(tp->dev, tp->num_tx_rings); - if (retval < 0) - goto exit; - - retval = netif_set_real_num_rx_queues(tp->dev, tp->num_rx_rings); - if (retval < 0) - goto exit; - -exit: - return retval; -} - -static int rtl8125_open(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - int retval; - - retval = -ENOMEM; - -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_init(dev); -#endif - rtl8125_set_rxbufsize(tp, dev); - /* - * Rx and Tx descriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - if (rtl8125_alloc_tx_desc(tp) < 0 || rtl8125_alloc_rx_desc(tp) < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_init_ring(dev); - if (retval < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_set_real_num_queue(tp); - if (retval < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_alloc_irq(tp); - if (retval < 0) - goto err_free_all_allocated_mem; - - if (netif_msg_probe(tp)) { - printk(KERN_INFO "%s: 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&tp->task, NULL, dev); -#else - INIT_DELAYED_WORK(&tp->task, NULL); -#endif - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif - - spin_lock_irqsave(&tp->lock, flags); - - rtl8125_exit_oob(dev); - - rtl8125_hw_init(dev); - - rtl8125_hw_reset(dev); - - rtl8125_powerup_pll(dev); - - rtl8125_hw_ephy_config(dev); - - rtl8125_hw_phy_config(dev); - - rtl8125_hw_config(dev); - -#ifdef ENABLE_PTP_SUPPORT - if (tp->EnablePtp) - rtl8125_ptp_init(tp); -#endif - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - if (tp->resume_not_chg_speed) { - rtl8125_check_link_status(dev, 1); - tp->resume_not_chg_speed = 0; - } - - spin_unlock_irqrestore(&tp->lock, flags); - - if (tp->esd_flag == 0) - rtl8125_request_esd_timer(dev); - - //rtl8125_request_link_timer(dev); - - rtl8125_enable_hw_linkchg_interrupt(tp); - -out: - - return retval; - -err_free_all_allocated_mem: - rtl8125_free_alloc_resources(tp); - - goto out; -} - -static void -set_offset70F(struct rtl8125_private *tp, u8 setting) -{ - u32 csi_tmp; - u32 temp = (u32)setting; - temp = temp << 24; - /*set PCI configuration space offset 0x70F to setting*/ - /*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/ - - csi_tmp = rtl8125_csi_read(tp, 0x70c) & 0x00ffffff; - rtl8125_csi_write(tp, 0x70c, csi_tmp | temp); -} - -static void -set_offset79(struct rtl8125_private *tp, u8 setting) -{ - //Set PCI configuration space offset 0x79 to setting - - struct pci_dev *pdev = tp->pci_dev; - u8 device_control; - - if (hwoptimize & HW_PATCH_SOC_LAN) return; - - pci_read_config_byte(pdev, 0x79, &device_control); - device_control &= ~0x70; - device_control |= setting; - pci_write_config_byte(pdev, 0x79, device_control); -} - -void -rtl8125_hw_set_rx_packet_filter(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#else - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#endif - } - - if (dev->features & NETIF_F_RXALL) - rx_mode |= (AcceptErr | AcceptRunt); - - tmp = mc_filter[0]; - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(tmp); - - tmp = tp->rtl8125_rx_config | rx_mode | (RTL_R32(tp, RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - RTL_W32(tp, RxConfig, tmp); - RTL_W32(tp, MAR0 + 0, mc_filter[0]); - RTL_W32(tp, MAR0 + 4, mc_filter[1]); -} - -static void -rtl8125_set_rx_mode(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - rtl8125_hw_set_rx_packet_filter(dev); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -void -rtl8125_set_rx_q_num(struct rtl8125_private *tp, - unsigned int num_rx_queues) -{ - u16 q_ctrl; - u16 rx_q_num; - - rx_q_num = (u16)ilog2(num_rx_queues); - rx_q_num &= (BIT_0 | BIT_1 | BIT_2); - rx_q_num <<= 2; - q_ctrl = RTL_R16(tp, Q_NUM_CTRL_8125); - q_ctrl &= ~(BIT_2 | BIT_3 | BIT_4); - q_ctrl |= rx_q_num; - RTL_W16(tp, Q_NUM_CTRL_8125, q_ctrl); -} - -void -rtl8125_set_tx_q_num(struct rtl8125_private *tp, - unsigned int num_tx_queues) -{ - u16 mac_ocp_data; - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); - mac_ocp_data &= ~(BIT_11 | BIT_10); - mac_ocp_data |= ((ilog2(num_tx_queues) & 0x03) << 10); - rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); -} - -void -rtl8125_hw_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u16 mac_ocp_data; - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8125_hw_reset(dev); - - rtl8125_enable_cfg9346_write(tp); - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - break; - } - - //clear io_rdy_l23 - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_1); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - //IntMITI_0-IntMITI_31 - for (i=0xA00; i<0xB00; i+=4) - RTL_W32(tp, i, 0x00000000); - break; - } - - //keep magic packet only - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B6); - mac_ocp_data &= BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B6, mac_ocp_data); - break; - } - - rtl8125_tally_counter_addr_fill(tp); - - rtl8125_desc_addr_fill(tp); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(tp, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - if (tp->EnableTxNoClose) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_6)); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - RTL_W16(tp, 0x382, 0x221B); - -#ifdef ENABLE_RSS_SUPPORT - rtl8125_config_rss(tp); -#else - RTL_W32(tp, RSS_CTRL_8125, 0x00); -#endif - rtl8125_set_rx_q_num(tp, rtl8125_tot_rx_rings(tp)); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); - - rtl8125_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8125_mac_ocp_write(tp, 0xC142, 0xFFFF); - - //new tx desc format - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB58); - mac_ocp_data |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xEB58, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE614); - mac_ocp_data &= ~( BIT_10 | BIT_9 | BIT_8); - if (tp->mcfg == CFG_METHOD_4 || tp->mcfg == CFG_METHOD_5) { - mac_ocp_data |= ((2 & 0x07) << 8); - } else { - if (tp->DASH && !(rtl8125_csi_fun0_read_byte(tp, 0x79) & BIT_0)) - mac_ocp_data |= ((3 & 0x07) << 8); - else - mac_ocp_data |= ((4 & 0x07) << 8); - } - rtl8125_mac_ocp_write(tp, 0xE614, mac_ocp_data); - - rtl8125_set_tx_q_num(tp, rtl8125_tot_tx_rings(tp)); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); - mac_ocp_data &= ~(BIT_5 | BIT_4); - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) - mac_ocp_data |= ((0x02 & 0x03) << 4); - rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); - mac_ocp_data &= ~BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - mac_ocp_data |= BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); - mac_ocp_data |= (BIT_3|BIT_2); - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB6A); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= (BIT_5 | BIT_4 | BIT_1 | BIT_0); - rtl8125_mac_ocp_write(tp, 0xEB6A, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB50); - mac_ocp_data &= ~(BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5); - mac_ocp_data |= (BIT_6); - rtl8125_mac_ocp_write(tp, 0xEB50, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE056); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); - mac_ocp_data |= (BIT_4 | BIT_5); - rtl8125_mac_ocp_write(tp, 0xE056, mac_ocp_data); - - RTL_W8(tp, TDFNR, 0x10); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE040); - mac_ocp_data &= ~(BIT_12); - rtl8125_mac_ocp_write(tp, 0xE040, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); - mac_ocp_data &= ~(BIT_1 | BIT_0); - mac_ocp_data |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE0C0); - mac_ocp_data &= ~(BIT_14 | BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= (BIT_14 | BIT_10 | BIT_1 | BIT_0); - rtl8125_mac_ocp_write(tp, 0xE0C0, mac_ocp_data); - - SetMcuAccessRegBit(tp, 0xE052, (BIT_6|BIT_5|BIT_3)); - ClearMcuAccessRegBit(tp, 0xE052, BIT_7); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xD430); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x47F; - rtl8125_mac_ocp_write(tp, 0xD430, mac_ocp_data); - - //rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4F87); - if (!tp->DASH) - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6 | BIT_7); - else - RTL_W8(tp, 0xD0, (RTL_R8(tp, 0xD0) & ~BIT_6) | BIT_7); - - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) - RTL_W8(tp, 0xD3, RTL_R8(tp, 0xD3) | BIT_0); - - rtl8125_disable_eee_plus(tp); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); - mac_ocp_data &= ~(BIT_2); - rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); - - SetMcuAccessRegBit(tp, 0xEB54, BIT_0); - udelay(1); - ClearMcuAccessRegBit(tp, 0xEB54, BIT_0); - RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~(BIT_4 | BIT_5)); - } - - /* csum offload command for RTL8125 */ - tp->tx_tcp_csum_cmd = TxTCPCS_C; - tp->tx_udp_csum_cmd = TxUDPCS_C; - tp->tx_ip_csum_cmd = TxIPCS_C; - tp->tx_ipv6_csum_cmd = TxIPV6F_C; - - /* config interrupt type for RTL8125B */ - if (tp->HwSuppIsrVer == 2) - rtl8125_hw_set_interrupt_type(tp, tp->HwCurrIsrVer); - - //other hw parameters - rtl8125_hw_clear_timer_int(dev); - - rtl8125_hw_clear_int_miti(dev); - - if (tp->use_timer_interrrupt && - (tp->HwCurrIsrVer == 2) && - (tp->HwSuppIntMitiVer == 4) && - (tp->features & RTL_FEATURE_MSIX)) { - int i; - for (i = 0; i < tp->irq_nvecs; i++) - rtl8125_hw_set_timer_int_8125(tp, i, timer_count_v2); - } - - rtl8125_enable_exit_l1_mask(tp); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE098, 0xC302); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (aspm) { - rtl8125_init_pci_offset_99(tp); - } - break; - } - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (aspm) { - rtl8125_init_pci_offset_180(tp); - } - break; - } - - tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | - Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | - ASF | Macdbgo_sel); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - RTL_W16(tp, CPlusCmd, tp->cp_cmd); -#else - rtl8125_hw_set_features(dev, dev->features); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: { - int timeout; - for (timeout = 0; timeout < 10; timeout++) { - if ((rtl8125_mac_ocp_read(tp, 0xE00E) & BIT_13)==0) - break; - mdelay(1); - } - } - break; - } - - RTL_W16(tp, RxMaxSize, tp->rx_buf_sz); - - rtl8125_disable_rxdvgate(dev); - - if (!tp->pci_cfg_is_read) { - pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); - if (tp->HwPcieSNOffset > 0) { - tp->pci_cfg_space.pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); - tp->pci_cfg_space.pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); - } - - tp->pci_cfg_is_read = 1; - } - - /* Set Rx packet filter */ - rtl8125_hw_set_rx_packet_filter(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && !tp->dash_printer_enabled) - NICChkTypeEnableDashInterrupt(tp); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (aspm) { - RTL_W8(tp, Config5, RTL_R8(tp, Config5) | BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | BIT_7); - } else { - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - } - break; - } - - rtl8125_disable_cfg9346_write(tp); - - udelay(10); -} - -void -rtl8125_hw_start(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl8125_enable_hw_interrupt(tp); - - rtl8125_lib_reset_complete(tp); -} - -static int -rtl8125_change_mtu(struct net_device *dev, - int new_mtu) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = 0; - unsigned long flags; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - if (new_mtu < ETH_MIN_MTU) - return -EINVAL; - else if (new_mtu > tp->max_jumbo_frame_size) - new_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - - spin_lock_irqsave(&tp->lock, flags); - dev->mtu = new_mtu; - spin_unlock_irqrestore(&tp->lock, flags); - - if (!netif_running(dev)) - goto out; - - rtl8125_down(dev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8125_set_rxbufsize(tp, dev); - - ret = rtl8125_init_ring(dev); - - if (ret < 0) { - spin_unlock_irqrestore(&tp->lock, flags); - goto err_out; - } - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif//CONFIG_R8125_NAPI - - rtl8125_stop_all_tx_queue(dev); - netif_carrier_off(dev); - rtl8125_hw_config(dev); - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - spin_unlock_irqrestore(&tp->lock, flags); - - mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); - //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); -out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - netdev_update_features(dev); -#endif - -err_out: - return ret; -} - -static void -rtl8125_free_rx_skb(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - struct RxDesc *desc, - const u32 cur_rx) -{ - struct pci_dev *pdev = tp->pci_dev; - - dma_unmap_single(&pdev->dev, ring->RxDescPhyAddr[cur_rx], tp->rx_buf_sz, - DMA_FROM_DEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8125_make_unusable_by_asic(tp, desc); -} - -static inline void -rtl8125_mark_to_asic_v3(struct RxDescV3 *descv3, - u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1) & RingEnd; - - WRITE_ONCE(descv3->RxDescNormalDDWord4.opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); -} - -void -rtl8125_mark_to_asic(struct rtl8125_private *tp, - struct RxDesc *desc, - u32 rx_buf_sz) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_mark_to_asic_v3((struct RxDescV3 *)desc, rx_buf_sz); - else { - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); - } -} - -static inline void -rtl8125_map_to_asic(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct RxDesc *desc, - dma_addr_t mapping, - u32 rx_buf_sz, - const u32 cur_rx) -{ - ring->RxDescPhyAddr[cur_rx] = mapping; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - ((struct RxDescV3 *)desc)->addr = cpu_to_le64(mapping); - else - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8125_mark_to_asic(tp, desc, rx_buf_sz); -} - -static int -rtl8125_alloc_rx_skb(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - struct RxDesc *desc, - int rx_buf_sz, - const u32 cur_rx, - u8 in_intr) -{ - struct sk_buff *skb; - dma_addr_t mapping; - int ret = 0; - - if (in_intr) - skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, rx_buf_sz + RTK_RX_ALIGN); - else - skb = dev_alloc_skb(rx_buf_sz + RTK_RX_ALIGN); - - if (unlikely(!skb)) - goto err_out; - - skb_reserve(skb, RTK_RX_ALIGN); - - mapping = dma_map_single(&tp->pci_dev->dev, skb->data, rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(&tp->pci_dev->dev, mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - *sk_buff = skb; - rtl8125_map_to_asic(tp, ring, desc, mapping, rx_buf_sz, cur_rx); -out: - return ret; - -err_out: - if (skb) - dev_kfree_skb(skb); - ret = -ENOMEM; - rtl8125_make_unusable_by_asic(tp, desc); - goto out; -} - -static void -_rtl8125_rx_clear(struct rtl8125_private *tp, struct rtl8125_rx_ring *ring) -{ - int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (ring->Rx_skbuff[i]) { - rtl8125_free_rx_skb(tp, - ring, - ring->Rx_skbuff + i, - rtl8125_get_rxdesc(tp, ring->RxDescArray, i), - i); - ring->Rx_skbuff[i] = NULL; - } - } -} - -void -rtl8125_rx_clear(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_rx_rings; i++) - _rtl8125_rx_clear(tp, &tp->rx_ring[i]); -} - -static u32 -rtl8125_rx_fill(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct net_device *dev, - u32 start, - u32 end, - u8 in_intr) -{ - u32 cur; - - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % NUM_RX_DESC; - - if (ring->Rx_skbuff[i]) - continue; - - ret = rtl8125_alloc_rx_skb(tp, - ring, - ring->Rx_skbuff + i, - rtl8125_get_rxdesc(tp, ring->RxDescArray, i), - tp->rx_buf_sz, - i, - in_intr - ); - if (ret < 0) - break; - } - return cur - start; -} - -static inline void -rtl8125_mark_as_last_descriptor_8125(struct RxDescV3 *descv3) -{ - descv3->RxDescNormalDDWord4.opts1 |= cpu_to_le32(RingEnd); -} - -static inline void -rtl8125_mark_as_last_descriptor(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_mark_as_last_descriptor_8125((struct RxDescV3 *)desc); - else - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void -rtl8125_desc_addr_fill(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - RTL_W32(tp, ring->tdsar_reg, ((u64)ring->TxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, ring->tdsar_reg + 4, ((u64)ring->TxPhyAddr >> 32)); - } - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - RTL_W32(tp, ring->rdsar_reg, ((u64)ring->RxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, ring->rdsar_reg + 4, ((u64)ring->RxPhyAddr >> 32)); - } -} - -static void -rtl8125_tx_desc_init(struct rtl8125_private *tp) -{ - int i = 0; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - memset(ring->TxDescArray, 0x0, R8125_TX_RING_BYTES); - - ring->TxDescArray[NUM_TX_DESC - 1].opts1 = cpu_to_le32(RingEnd); - } -} - -static void -rtl8125_rx_desc_init(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - memset(ring->RxDescArray, 0x0, tp->RxDescRingLength); - } -} - -int -rtl8125_init_ring(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - rtl8125_init_ring_indexes(tp); - - rtl8125_tx_desc_init(tp); - rtl8125_rx_desc_init(tp); - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - memset(ring->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - } - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - - memset(ring->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - if (rtl8125_rx_fill(tp, ring, dev, 0, NUM_RX_DESC, 0) != NUM_RX_DESC) - goto err_out; - - rtl8125_mark_as_last_descriptor(tp, rtl8125_get_rxdesc(tp, ring->RxDescArray, NUM_RX_DESC - 1)); - } - - return 0; - -err_out: - rtl8125_rx_clear(tp); - return -ENOMEM; -} - -static void -rtl8125_unmap_tx_skb(struct pci_dev *pdev, - struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = cpu_to_le32(RTK_MAGIC_DEBUG_VALUE); - desc->opts2 = 0x00; - desc->addr = RTL8125_MAGIC_NUMBER; - tx_skb->len = 0; -} - -static void -rtl8125_tx_clear_range(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring, - u32 start, - unsigned int n) -{ - unsigned int i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - struct net_device *dev = tp->dev; -#endif - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = ring->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8125_unmap_tx_skb(tp->pci_dev, tx_skb, - ring->TxDescArray + entry); - if (skb) { - RTLDEV->stats.tx_dropped++; - dev_kfree_skb_any(skb); - tx_skb->skb = NULL; - } - } - } -} - -void -rtl8125_tx_clear(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - rtl8125_tx_clear_range(tp, ring, ring->dirty_tx, NUM_TX_DESC); - ring->cur_tx = ring->dirty_tx = 0; - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_schedule_work(struct net_device *dev, void (*task)(void *)) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - struct rtl8125_private *tp = netdev_priv(dev); - - INIT_WORK(&tp->task, task, dev); - schedule_delayed_work(&tp->task, 4); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -#define rtl8125_cancel_schedule_work(a) - -#else -static void rtl8125_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - INIT_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8125_cancel_schedule_work(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct work_struct *work = &tp->task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->task); -} -#endif - -static void -rtl8125_wait_for_irq_complete(struct rtl8125_private *tp) -{ - if (tp->features & RTL_FEATURE_MSIX) { - int i; - for (i = 0; i < tp->irq_nvecs; i++) - synchronize_irq(tp->irq_tbl[i].vector); - } else { - synchronize_irq(tp->dev->irq); - } -} - -static void -_rtl8125_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8125_NAPI - rtl8125_disable_napi(tp); -#endif//CONFIG_R8125_NAPI - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_net(); -#endif - spin_lock_irqsave(&tp->lock, flags); - - rtl8125_irq_mask_and_ack(tp); - - spin_unlock_irqrestore(&tp->lock, flags); - - rtl8125_wait_for_irq_complete(tp); -} - -static void -rtl8125_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - //suppress unused variable - (void)(tp); - - _rtl8125_wait_for_quiescence(dev); - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif//CONFIG_R8125_NAPI -} - -#if 0 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_reinit_task(void *_data) -#else -static void rtl8125_reinit_task(struct work_struct *work) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct net_device *dev = _data; -#else - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, task.work); - struct net_device *dev = tp->dev; -#endif - int ret; - - if (netif_running(dev)) { - rtl8125_wait_for_quiescence(dev); - rtl8125_close(dev); - } - - ret = rtl8125_open(dev); - if (unlikely(ret < 0)) { - if (unlikely(net_ratelimit())) { - struct rtl8125_private *tp = netdev_priv(dev); - - if (netif_msg_drv(tp)) { - printk(PFX KERN_ERR - "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - } - rtl8125_schedule_work(dev, rtl8125_reinit_task); - } -} -#endif - -static int rtl8125_rx_nostuck(struct rtl8125_private *tp) -{ - int i, ret = 1; - for (i = 0; i < tp->num_rx_rings; i++) - ret &= (tp->rx_ring[i].dirty_rx == tp->rx_ring[i].cur_rx); - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_reset_task(void *_data) -{ - struct net_device *dev = _data; - struct rtl8125_private *tp = netdev_priv(dev); -#else -static void rtl8125_reset_task(struct work_struct *work) -{ - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, task.work); - struct net_device *dev = tp->dev; -#endif - u32 budget = ~(u32)0; - unsigned long flags; - int i; - - if (!netif_running(dev)) - return; - - rtl8125_wait_for_quiescence(dev); - - for (i = 0; i < tp->num_rx_rings; i++) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - } - - spin_lock_irqsave(&tp->lock, flags); - - rtl8125_tx_clear(tp); - - if (rtl8125_rx_nostuck(tp)) { - rtl8125_rx_clear(tp); - rtl8125_init_ring(dev); -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_reset(tp); -#endif - rtl8125_enable_hw_linkchg_interrupt(tp); - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - spin_unlock_irqrestore(&tp->lock, flags); - if (unlikely(net_ratelimit())) { - struct rtl8125_private *tp = netdev_priv(dev); - - if (netif_msg_intr(tp)) { - printk(PFX KERN_EMERG - "%s: Rx buffers shortage\n", dev->name); - } - } - rtl8125_schedule_work(dev, rtl8125_reset_task); - } -} -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void -rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue) -#else -static void -rtl8125_tx_timeout(struct net_device *dev) -#endif -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_stop_all_tx_queue(dev); - netif_carrier_off(dev); - rtl8125_hw_reset(dev); - spin_unlock_irqrestore(&tp->lock, flags); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8125_schedule_work(dev, rtl8125_reset_task); -} - -static u32 -rtl8125_get_txd_opts1(u32 opts1, u32 len, unsigned int entry) -{ - u32 status = opts1 | len; - - if (entry == NUM_TX_DESC - 1) - status |= RingEnd; - - return status; -} - -static int -rtl8125_xmit_frags(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring, - struct sk_buff *skb, - const u32 *opts) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc *txd = NULL; - const unsigned char nr_frags = info->nr_frags; - unsigned long PktLenCnt = 0; - bool LsoPatchEnabled = FALSE; - - entry = ring->cur_tx; - for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = ring->TxDescArray + entry; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; -#else - len = skb_frag_size(frag); - addr = skb_frag_address(frag); -#endif - if (tp->RequireLSOPatch && - (cur_frag == nr_frags - 1) && - (opts[0] & (GiantSendv4|GiantSendv6)) && - PktLenCnt < ETH_FRAME_LEN && - len > 1) { - len -= 1; - mapping = dma_map_single(&tp->pci_dev->dev, addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(&tp->pci_dev->dev, mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8125_get_txd_opts1(opts[0], len, entry); - - txd->addr = cpu_to_le64(mapping); - - ring->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - - //second txd - addr += len; - len = 1; - entry = (entry + 1) % NUM_TX_DESC; - txd = ring->TxDescArray + entry; - cur_frag += 1; - - LsoPatchEnabled = TRUE; - } - - mapping = dma_map_single(&tp->pci_dev->dev, addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(&tp->pci_dev->dev, mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8125_get_txd_opts1(opts[0], len, entry); - if (cur_frag == (nr_frags - 1) || LsoPatchEnabled == TRUE) { - //ring->tx_skb[entry].skb = skb; - status |= LastFrag; - } - - txd->addr = cpu_to_le64(mapping); - - ring->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - - PktLenCnt += len; - } - - return cur_frag; - -err_out: - rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, cur_frag); - return -EIO; -} - -static inline -__be16 get_protocol(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) - return vlan_get_protocol(skb); -#else - __be16 protocol; - - if (skb->protocol == htons(ETH_P_8021Q)) - protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; - else - protocol = skb->protocol; - - return protocol; -#endif -} - -static inline -u8 rtl8125_get_l4_protocol(struct sk_buff *skb) -{ - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - ip_protocol = ip_hdr(skb)->protocol; - break; - case __constant_htons(ETH_P_IPV6): - ip_protocol = ipv6_hdr(skb)->nexthdr; - break; - } - - return ip_protocol; -} - -static bool rtl8125_skb_pad_with_len(struct sk_buff *skb, unsigned int len) -{ - if (skb_padto(skb, len)) - return false; - skb_put(skb, len - skb->len); - return true; -} - -static bool rtl8125_skb_pad(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) - return rtl8125_skb_pad_with_len(skb, ETH_ZLEN); -#else - return !eth_skb_pad(skb); -#endif -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -/* msdn_giant_send_check() - * According to the document of microsoft, the TCP Pseudo Header excludes the - * packet length for IPv6 TCP large packets. - */ -static int msdn_giant_send_check(struct sk_buff *skb) -{ - const struct ipv6hdr *ipv6h; - struct tcphdr *th; - int ret; - - ret = skb_cow_head(skb, 0); - if (ret) - return ret; - - ipv6h = ipv6_hdr(skb); - th = tcp_hdr(skb); - - th->check = 0; - th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); - - return ret; -} -#endif - -#define MIN_PATCH_LEN (47) -static u32 -rtl8125_get_patch_pad_len(struct sk_buff *skb) -{ - u32 pad_len = 0; - int trans_data_len; - u32 hdr_len; - u32 pkt_len = skb->len; - u8 ip_protocol; - bool has_trans = skb_transport_header_was_set(skb); - - if (!(has_trans && (pkt_len < 175))) //128 + MIN_PATCH_LEN - goto no_padding; - - ip_protocol = rtl8125_get_l4_protocol(skb); - if (!(ip_protocol == IPPROTO_TCP || ip_protocol == IPPROTO_UDP)) - goto no_padding; - - trans_data_len = pkt_len - - (skb->transport_header - - skb_headroom(skb)); - if (ip_protocol == IPPROTO_UDP) { - if (trans_data_len > 3 && trans_data_len < MIN_PATCH_LEN) { - u16 dest_port = 0; - - skb_copy_bits(skb, skb->transport_header - skb_headroom(skb) + 2, &dest_port, 2); - dest_port = ntohs(dest_port); - - if (dest_port == 0x13f || - dest_port == 0x140) { - pad_len = MIN_PATCH_LEN - trans_data_len; - goto out; - } - } - } - - hdr_len = 0; - if (ip_protocol == IPPROTO_TCP) - hdr_len = 20; - else if (ip_protocol == IPPROTO_UDP) - hdr_len = 8; - if (trans_data_len < hdr_len) - pad_len = hdr_len - trans_data_len; - -out: - if ((pkt_len + pad_len) < ETH_ZLEN) - pad_len = ETH_ZLEN - pkt_len; - - return pad_len; - -no_padding: - - return 0; -} - -static bool -rtl8125_tso_csum(struct sk_buff *skb, - struct net_device *dev, - u32 *opts) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long large_send = 0; - u32 csum_cmd = 0; - u8 sw_calc_csum = false; - u8 check_patch_required = true; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - u32 mss = skb_shinfo(skb)->tso_size; -#else - u32 mss = skb_shinfo(skb)->gso_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - - /* TCP Segmentation Offload (or TCP Large Send) */ - if (mss) { - u32 transport_offset = (u32)skb_transport_offset(skb); - assert((transport_offset%2) == 0); - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv4; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - case __constant_htons(ETH_P_IPV6): -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - if (msdn_giant_send_check(skb)) - return false; -#endif - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv6; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("tso proto=%x!\n", skb->protocol); - break; - } - - if (large_send == 0) - return false; - - return true; - } - } -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - const struct iphdr *ip = skb->nh.iph; - - if (dev->features & NETIF_F_IP_CSUM) { - if (ip->protocol == IPPROTO_TCP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_tcp_csum_cmd; - else if (ip->protocol == IPPROTO_UDP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_udp_csum_cmd; - else if (ip->protocol == IPPROTO_IP) - csum_cmd = tp->tx_ip_csum_cmd; - } -#else - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (dev->features & NETIF_F_IP_CSUM) { - ip_protocol = ip_hdr(skb)->protocol; - csum_cmd = tp->tx_ip_csum_cmd; - } - break; - case __constant_htons(ETH_P_IPV6): - if (dev->features & NETIF_F_IPV6_CSUM) { - u32 transport_offset = (u32)skb_transport_offset(skb); - if (transport_offset > 0 && transport_offset <= TCPHO_MAX) { - ip_protocol = ipv6_hdr(skb)->nexthdr; - csum_cmd = tp->tx_ipv6_csum_cmd; - csum_cmd |= transport_offset << TCPHO_SHIFT; - } - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("checksum_partial proto=%x!\n", skb->protocol); - break; - } - - if (ip_protocol == IPPROTO_TCP) - csum_cmd |= tp->tx_tcp_csum_cmd; - else if (ip_protocol == IPPROTO_UDP) - csum_cmd |= tp->tx_udp_csum_cmd; -#endif - if (csum_cmd == 0) { - sw_calc_csum = true; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - WARN_ON(1); /* we need a WARN() */ -#endif - } - - if (ip_protocol == IPPROTO_TCP) - check_patch_required = false; - } - - if (check_patch_required) { - u32 pad_len = rtl8125_get_patch_pad_len(skb); - - if (pad_len > 0) { - if (!rtl8125_skb_pad_with_len(skb, skb->len + pad_len)) - return false; - - if (csum_cmd != 0) - sw_calc_csum = true; - } - } - - if (skb->len < ETH_ZLEN) { - if (tp->UseSwPaddingShortPkt || - (tp->ShortPacketSwChecksum && csum_cmd != 0)) { - if (!rtl8125_skb_pad(skb)) - return false; - - if (csum_cmd != 0) - sw_calc_csum = true; - } - } - - if (sw_calc_csum) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) - skb_checksum_help(&skb, 0); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - skb_checksum_help(skb, 0); -#else - skb_checksum_help(skb); -#endif - } else - opts[1] |= csum_cmd; - - return true; -} - -static bool rtl8125_tx_slots_avail(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring) -{ - unsigned int slots_avail = READ_ONCE(ring->dirty_tx) + NUM_TX_DESC - - READ_ONCE(ring->cur_tx); - - /* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ - return slots_avail > MAX_SKB_FRAGS; -} - -static int -rtl8125_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int entry; - struct TxDesc *txd; - dma_addr_t mapping; - u32 len; - u32 opts[2]; - int ret = NETDEV_TX_OK; - //unsigned long flags; - int frags; - u8 EnableTxNoClose = tp->EnableTxNoClose; - const u16 queue_mapping = skb_get_queue_mapping(skb); - struct rtl8125_tx_ring *ring; - bool stop_queue; - - assert(queue_mapping < tp->num_tx_queues); - - ring = &tp->tx_ring[queue_mapping]; - - //spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(!rtl8125_tx_slots_avail(tp, ring))) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring[%d] full when queue awake!\n", - dev->name, - queue_mapping); - } - goto err_stop; - } - - entry = ring->cur_tx % NUM_TX_DESC; - txd = ring->TxDescArray + entry; - - if (!EnableTxNoClose) { - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Desc is own by hardware!\n", - dev->name); - } - goto err_stop; - } - } - - opts[0] = DescOwn; - opts[1] = rtl8125_tx_vlan_tag(tp, skb); - - if (unlikely(!rtl8125_tso_csum(skb, dev, opts))) - goto err_dma_0; - - frags = rtl8125_xmit_frags(tp, ring, skb, opts); - if (unlikely(frags < 0)) - goto err_dma_0; - if (frags) { - len = skb_headlen(skb); - opts[0] |= FirstFrag; - } else { - len = skb->len; - - //ring->tx_skb[entry].skb = skb; - - opts[0] |= FirstFrag | LastFrag; - } - - opts[0] = rtl8125_get_txd_opts1(opts[0], len, entry); - mapping = dma_map_single(&tp->pci_dev->dev, skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(&tp->pci_dev->dev, mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_1; - } - ring->tx_skb[entry].len = len; -#ifdef ENABLE_PTP_SUPPORT - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { - if (tp->hwtstamp_config.tx_type == HWTSTAMP_TX_ON && - !tp->ptp_tx_skb) { - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - - tp->ptp_tx_skb = skb_get(skb); - tp->ptp_tx_start = jiffies; - schedule_work(&tp->ptp_tx_work); - } else { - tp->tx_hwtstamp_skipped++; - } - } -#endif - ring->tx_skb[entry].skb = skb; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(opts[0]); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - dev->trans_start = jiffies; -#else - skb_tx_timestamp(skb); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - - /* rtl_tx needs to see descriptor changes before updated tp->cur_tx */ - smp_wmb(); - - WRITE_ONCE(ring->cur_tx, ring->cur_tx + frags + 1); - - stop_queue = !rtl8125_tx_slots_avail(tp, ring); - if (unlikely(stop_queue)) { - /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must - * not miss a ring update when it notices a stopped queue. - */ - smp_wmb(); - netif_stop_subqueue(dev, queue_mapping); - } - - if (EnableTxNoClose) - RTL_W16(tp, ring->sw_tail_ptr_reg, ring->cur_tx % MAX_TX_NO_CLOSE_DESC_PTR_V2); - else - RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); /* set polling bit */ - - if (unlikely(stop_queue)) { - /* Sync with rtl_tx: - * - publish queue status and cur_tx ring index (write barrier) - * - refresh dirty_tx ring index (read barrier). - * May the current thread have a pessimistic view of the ring - * status and forget to wake up queue, a racing rtl_tx thread - * can't. - */ - smp_mb(); - if (rtl8125_tx_slots_avail(tp, ring)) - netif_start_subqueue(dev, queue_mapping); - } - - //spin_unlock_irqrestore(&tp->lock, flags); -out: - return ret; -err_dma_1: - ring->tx_skb[entry].skb = NULL; - rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, frags); -err_dma_0: - RTLDEV->stats.tx_dropped++; - //spin_unlock_irqrestore(&tp->lock, flags); - dev_kfree_skb_any(skb); - ret = NETDEV_TX_OK; - goto out; -err_stop: - netif_stop_subqueue(dev, queue_mapping); - ret = NETDEV_TX_BUSY; - RTLDEV->stats.tx_dropped++; - - //spin_unlock_irqrestore(&tp->lock, flags); - goto out; -} - -static inline u32 -rtl8125_fast_mod(const u32 input, const u32 ceil) -{ - return input >= ceil ? input % ceil : input; -} - -static int -rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget) -{ - struct rtl8125_private *tp = ring->priv; - struct net_device *dev = tp->dev; - unsigned int dirty_tx, tx_left; - unsigned int count = 0; - u8 EnableTxNoClose = tp->EnableTxNoClose; - - dirty_tx = ring->dirty_tx; - if (EnableTxNoClose) { - u32 NextHwDesCloPtr = RTL_R16(tp, ring->hw_clo_ptr_reg); - ring->NextHwDesCloPtr = NextHwDesCloPtr; - smp_rmb(); - tx_left = rtl8125_fast_mod(NextHwDesCloPtr - ring->BeginHwDesCloPtr, MAX_TX_NO_CLOSE_DESC_PTR_V2); - ring->BeginHwDesCloPtr = NextHwDesCloPtr; - } else { - smp_rmb(); - tx_left = READ_ONCE(ring->cur_tx) - dirty_tx; - } - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = ring->tx_skb + entry; - - if (!EnableTxNoClose && - (le32_to_cpu(ring->TxDescArray[entry].opts1) & DescOwn)) - break; - - RTLDEV->stats.tx_bytes += tx_skb->len; - RTLDEV->stats.tx_packets++; - - rtl8125_unmap_tx_skb(tp->pci_dev, - tx_skb, - ring->TxDescArray + entry); - - if (tx_skb->skb != NULL) { - RTL_NAPI_CONSUME_SKB_ANY(tx_skb->skb, budget); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (ring->dirty_tx != dirty_tx) { - count = dirty_tx - ring->dirty_tx; - WRITE_ONCE(ring->dirty_tx, dirty_tx); - smp_wmb(); - if (__netif_subqueue_stopped(dev, ring->index) && - (rtl8125_tx_slots_avail(tp, ring))) { - netif_start_subqueue(dev, ring->index); - } - smp_rmb(); - if (!EnableTxNoClose && (ring->cur_tx != dirty_tx)) { - RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); - } - } - - return count; -} - -static int -rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, - const int message_id, - int budget) -{ - int count = 0; - if (message_id == 16) - count += rtl8125_tx_interrupt(&tp->tx_ring[0], budget); - else if (message_id == 18) - count += rtl8125_tx_interrupt(&tp->tx_ring[1], budget); - - return count; -} - -static inline int -rtl8125_fragmented_frame(struct rtl8125_private *tp, u32 status) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return (status & (FirstFrag_V3 | LastFrag_V3)) != (FirstFrag_V3 | LastFrag_V3); - else - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline int -rtl8125_rx_desc_type(u32 status) -{ - return ((status >> 26) & 0x0F); -} - -static inline void -rtl8125_rx_v3_csum(struct rtl8125_private *tp, - struct sk_buff *skb, - struct RxDescV3 *descv3) -{ - //u32 opts1 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1); - u32 opts2 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts2); - - /* rx csum offload for RTL8125 */ - if (((opts2 & RxV4F_v3) && !(opts2 & RxIPF_v3)) || (opts2 & RxV6F_v3)) { - if (((opts2 & RxTCPT_v3) && !(opts2 & RxTCPF_v3)) || - ((opts2 & RxUDPT_v3) && !(opts2 & RxUDPF_v3))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline void -rtl8125_rx_csum(struct rtl8125_private *tp, - struct sk_buff *skb, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_rx_v3_csum(tp, skb, (struct RxDescV3 *)desc); - else { - u32 opts1 = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); - u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); - - /* rx csum offload for RTL8125 */ - if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) { - if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) || - ((opts1 & RxUDPT) && !(opts1 & RxUDPF))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; - } -} - -static inline int -rtl8125_try_rx_copy(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - int pkt_size, - struct RxDesc *desc, - int rx_buf_sz) -{ - int ret = -1; - - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; - - skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, pkt_size + RTK_RX_ALIGN); - if (skb) { - u8 *data; - - data = sk_buff[0]->data; - skb_reserve(skb, RTK_RX_ALIGN); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(data - RTK_RX_ALIGN); -#endif - eth_copy_and_sum(skb, data, pkt_size, 0); - *sk_buff = skb; - rtl8125_mark_to_asic(tp, desc, rx_buf_sz); - ret = 0; - } - } - return ret; -} - -static inline void -rtl8125_rx_skb(struct rtl8125_private *tp, - struct sk_buff *skb, - u32 ring_index) -{ -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - netif_receive_skb(skb); -#else - napi_gro_receive(&tp->r8125napi[ring_index].napi, skb); -#endif -#else - netif_rx(skb); -#endif -} - -static int -rtl8125_check_rx_desc_error(struct net_device *dev, - struct rtl8125_private *tp, - u32 status) -{ - int ret = 0; - - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { - if (unlikely(status & RxRES_V3)) { - if (status & (RxRWT_V3 | RxRUNT_V3)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC_V3) - RTLDEV->stats.rx_crc_errors++; - - ret = -1; - } - } else { - if (unlikely(status & RxRES)) { - if (status & (RxRWT | RxRUNT)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC) - RTLDEV->stats.rx_crc_errors++; - - ret = -1; - } - } - - return ret; -} - -static int -rtl8125_rx_interrupt(struct net_device *dev, - struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - napi_budget budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count = 0; - unsigned int entry; - struct RxDesc *desc; - u32 status; - u32 rx_quota; - u64 rx_buf_phy_addr; - u32 ring_index = ring->index; - - assert(dev != NULL); - assert(tp != NULL); - - if ((ring->RxDescArray == NULL)) - goto rx_out; - - rx_quota = RTL_RX_QUOTA(budget); - cur_rx = ring->cur_rx; - entry = cur_rx % NUM_RX_DESC; - desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); - rx_left = NUM_RX_DESC + ring->dirty_rx - cur_rx; - rx_left = rtl8125_rx_quota(rx_left, (u32)rx_quota); - - for (; rx_left > 0; rx_left--) { - rmb(); - status = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); - if (status & DescOwn) - break; - - if (unlikely(rtl8125_check_rx_desc_error(dev, tp, status) < 0)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - - RTLDEV->stats.rx_errors++; - - if (dev->features & NETIF_F_RXALL) - goto process_pkt; - - rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb; - int pkt_size; - -process_pkt: - if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8125_fragmented_frame(tp, status))) { - RTLDEV->stats.rx_dropped++; - RTLDEV->stats.rx_length_errors++; - rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); - continue; - } - - skb = ring->Rx_skbuff[entry]; - - if (!skb) - break; - -#ifdef ENABLE_PTP_SUPPORT - if (tp->EnablePtp) { - struct RxDescV3 *desc_next; - u8 desc_type; - u32 status_next; - - desc_type = rtl8125_rx_desc_type(status); - if (desc_type == RXDESC_TYPE_NEXT && rx_left > 0) { - unsigned int entry_next; - struct sk_buff *skb_next; - - cur_rx++; - rx_left--; - entry_next = cur_rx % NUM_RX_DESC; - desc_next = (struct RxDescV3 *)rtl8125_get_rxdesc(tp, ring->RxDescArray, entry_next); - status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); - if (status_next & DescOwn) - break; - - desc_type = rtl8125_rx_desc_type(status_next); - if (desc_type == RXDESC_TYPE_PTP) { - rtl8125_rx_ptp_pktstamp(tp, skb, desc_next); - skb_next = ring->Rx_skbuff[entry_next]; - dev_kfree_skb_any(skb_next); - ring->Rx_skbuff[entry_next] = NULL; - } else - WARN_ON(1); - } else - WARN_ON(desc_type != RXDESC_TYPE_NORMAL); - } -#endif - rx_buf_phy_addr = le64_to_cpu(ring->RxDescPhyAddr[entry]); - dma_sync_single_for_cpu(&tp->pci_dev->dev, - rx_buf_phy_addr, tp->rx_buf_sz, - DMA_FROM_DEVICE); - - if (rtl8125_try_rx_copy(tp, ring, &skb, pkt_size, - desc, tp->rx_buf_sz)) { - ring->Rx_skbuff[entry] = NULL; - dma_unmap_single(&tp->pci_dev->dev, rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - } else { - dma_sync_single_for_device(&tp->pci_dev->dev, rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - } - -#ifdef ENABLE_RSS_SUPPORT - rtl8125_rx_hash(tp, (struct RxDescV3 *)desc, skb); -#endif - - if (tp->cp_cmd & RxChkSum) - rtl8125_rx_csum(tp, skb, desc); - - skb->dev = dev; - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (skb->pkt_type == PACKET_MULTICAST) - RTLDEV->stats.multicast++; - - if (rtl8125_rx_vlan_skb(tp, desc, skb) < 0) - rtl8125_rx_skb(tp, skb, ring_index); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - dev->last_rx = jiffies; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - RTLDEV->stats.rx_bytes += pkt_size; - RTLDEV->stats.rx_packets++; - } - - cur_rx++; - entry = cur_rx % NUM_RX_DESC; - desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(desc); -#endif - } - - count = cur_rx - ring->cur_rx; - ring->cur_rx = cur_rx; - - delta = rtl8125_rx_fill(tp, ring, dev, ring->dirty_rx, ring->cur_rx, 1); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - ring->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((ring->dirty_rx + NUM_RX_DESC == ring->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - -rx_out: - return count; -} - -static bool -rtl8125_linkchg_interrupt(struct rtl8125_private *tp, u32 status) -{ - if (tp->HwCurrIsrVer == 2) - return status & ISRIMR_V2_LINKCHG; - - return status & LinkChg; -} - -/* - *The interrupt handler does all of the Rx thread work and cleans up after - *the Tx thread. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance) -#endif -{ - struct r8125_napi *r8125napi = dev_instance; - struct rtl8125_private *tp = r8125napi->priv; - struct net_device *dev = tp->dev; - u32 status; - int handled = 0; - - do { - status = RTL_R32(tp, tp->isr_reg[0]); - - if (!(tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) { - /* hotplug/major error/no more work/shared irq */ - if (!status) - break; - - if ((status == 0xFFFFFFFF)) - break; - - if (!(status & (tp->intr_mask | tp->timer_intr_mask))) - break; - } - - handled = 1; - - rtl8125_disable_hw_interrupt(tp); - - RTL_W32(tp, tp->isr_reg[0], status&~RxFIFOOver); - - if (rtl8125_linkchg_interrupt(tp, status)) - rtl8125_check_link_status(dev, 0); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u8 DashIntType2Status; - - if (status & ISRIMR_DASH_INTR_CMAC_RESET) - tp->CmacResetIntr = TRUE; - - DashIntType2Status = RTL_CMAC_R8(tp, CMAC_IBISR0); - if (DashIntType2Status & ISRIMR_DASH_TYPE2_ROK) { - tp->RcvFwDashOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_TOK) { - tp->SendFwHostOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE) { - tp->DashFwDisableRx = TRUE; - } - - RTL_CMAC_W8(tp, CMAC_IBISR0, DashIntType2Status); - } - } -#endif - -#ifdef CONFIG_R8125_NAPI - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &tp->r8125napi[0].napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &tp->r8125napi[0].napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8125_switch_to_hw_interrupt(tp); - } -#else - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - u32 budget = ~(u32)0; - int i; - - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - - for (i = 0; i < tp->num_tx_rings; i++) - rtl8125_tx_interrupt(&tp->tx_ring[i], ~(u32)0); -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - struct net_device *dev = tp->dev; - - HandleDashInterrupt(dev); - } -#endif - - rtl8125_switch_to_timer_interrupt(tp); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8125_switch_to_hw_interrupt(tp); - } -#endif - } while (false); - - return IRQ_RETVAL(handled); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance) -#endif -{ - struct r8125_napi *r8125napi = dev_instance; - struct rtl8125_private *tp = r8125napi->priv; - struct net_device *dev = tp->dev; - int message_id = r8125napi->index; -#ifndef CONFIG_R8125_NAPI - u32 budget = ~(u32)0; -#endif - - do { - rtl8125_disable_hw_interrupt_v2(tp, message_id); - - rtl8125_clear_hw_isr_v2(tp, message_id); - - //link change - if (message_id == 21) { - rtl8125_check_link_status(dev, 0); - return IRQ_HANDLED; - } - -#ifdef CONFIG_R8125_NAPI - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &r8125napi->napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &r8125napi->napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt message id %d in poll_msix\n", - dev->name, message_id); -#else - if (message_id < tp->num_rx_rings) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - } - - //spin_lock_irqsave(&tp->lock, flags); - rtl8125_tx_interrupt_with_vector(tp, message_id, ~(u32)0); - //spin_unlock_irqrestore(&tp->lock, flags); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); -#endif - - } while (false); - - return IRQ_HANDLED; -} - -static void rtl8125_down(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - rtl8125_delete_esd_timer(dev, &tp->esd_timer); - - //rtl8125_delete_link_timer(dev, &tp->link_timer); - - rtl8125_stop_all_tx_queue(dev); - - _rtl8125_wait_for_quiescence(dev); - - spin_lock_irqsave(&tp->lock, flags); - - netif_carrier_off(dev); - - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - rtl8125_rx_clear(tp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8125_resource_freed(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) - if (tp->tx_ring[i].TxDescArray) return 0; - - for (i = 0; i < tp->num_rx_rings; i++) - if (tp->rx_ring[i].RxDescArray) return 0; - - return 1; -} - -static int rtl8125_close(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; - - if (!rtl8125_resource_freed(tp)) { - rtl8125_cancel_schedule_work(dev); - - rtl8125_down(dev); - - spin_lock_irqsave(&tp->lock, flags); -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_stop(tp); -#endif - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 0); - - spin_unlock_irqrestore(&tp->lock, flags); - - rtl8125_free_irq(tp); - - rtl8125_free_alloc_resources(tp); - } else { - spin_lock_irqsave(&tp->lock, flags); - - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 0); - - spin_unlock_irqrestore(&tp->lock, flags); - } - - return 0; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) -static void rtl8125_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->DASH) - rtl8125_driver_stop(tp); - - rtl8125_set_bios_setting(dev); - if (s5_keep_curr_mac == 0 && tp->random_mac == 0) - rtl8125_rar_set(tp, tp->org_mac_addr); - - if (s5wol == 0) - tp->wol_enabled = WOL_DISABLED; - - rtl8125_close(dev); - rtl8125_disable_msi(pdev, tp); -} -#endif - -/** - * rtl8125_get_stats - Get rtl8125 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8125 - */ -static struct -net_device_stats *rtl8125_get_stats(struct net_device *dev) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - struct rtl8125_private *tp = netdev_priv(dev); -#endif - if (netif_running(dev)) { -// spin_lock_irqsave(&tp->lock, flags); -// spin_unlock_irqrestore(&tp->lock, flags); - } - - return &RTLDEV->stats; -} - -#ifdef CONFIG_PM - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -static int -rtl8125_suspend(struct pci_dev *pdev, u32 state) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static int -rtl8125_suspend(struct device *device) -#else -static int -rtl8125_suspend(struct pci_dev *pdev, pm_message_t state) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); -#else - struct net_device *dev = pci_get_drvdata(pdev); -#endif - struct rtl8125_private *tp = netdev_priv(dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = pci_choose_state(pdev, state); -#endif - unsigned long flags; - - if (!netif_running(dev)) - goto out; - - rtl8125_cancel_schedule_work(dev); - - rtl8125_delete_esd_timer(dev, &tp->esd_timer); - - //rtl8125_delete_link_timer(dev, &tp->link_timer); - - rtl8125_stop_all_tx_queue(dev); - - netif_carrier_off(dev); - - netif_device_detach(dev); - - spin_lock_irqsave(&tp->lock, flags); - -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_suspend(tp); -#endif - rtl8125_hw_reset(dev); - - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 1); - - spin_unlock_irqrestore(&tp->lock, flags); - - if (tp->DASH) - rtl8125_driver_stop(tp); -out: - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_save_state(pdev, &pci_pm_state); -#else - pci_save_state(pdev); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); -#endif - //pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int -rtl8125_hw_d3_not_power_off(struct net_device *dev) -{ - return rtl8125_check_hw_phy_mcu_code_ver(dev); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -static int -rtl8125_resume(struct pci_dev *pdev) -#else -static int -rtl8125_resume(struct device *device) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); -#else - struct net_device *dev = pci_get_drvdata(pdev); -#endif - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long flags; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = PCI_D0; -#endif - - pci_set_power_state(pdev, PCI_D0); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_restore_state(pdev, &pci_pm_state); -#else - pci_restore_state(pdev); -#endif - pci_enable_wake(pdev, PCI_D0, 0); - - spin_lock_irqsave(&tp->lock, flags); - - /* restore last modified mac address */ - rtl8125_rar_set(tp, dev->dev_addr); - - if (tp->check_keep_link_speed && - //tp->link_ok(dev) && - rtl8125_hw_d3_not_power_off(dev)) - tp->resume_not_chg_speed = 1; - else - tp->resume_not_chg_speed = 0; - - spin_unlock_irqrestore(&tp->lock, flags); - - if (!netif_running(dev)) - goto out; - - spin_lock_irqsave(&tp->lock, flags); - - rtl8125_exit_oob(dev); - - rtl8125_hw_init(dev); - - rtl8125_powerup_pll(dev); - - rtl8125_hw_ephy_config(dev); - - rtl8125_hw_phy_config(dev); - - rtl8125_hw_config(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - - if (tp->resume_not_chg_speed) - rtl8125_check_link_status(dev, 1); - else - rtl8125_schedule_work(dev, rtl8125_reset_task); - - netif_device_attach(dev); - - mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); - //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); -out: - return 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - -static struct dev_pm_ops rtl8125_pm_ops = { - .suspend = rtl8125_suspend, - .resume = rtl8125_resume, - .freeze = rtl8125_suspend, - .thaw = rtl8125_resume, - .poweroff = rtl8125_suspend, - .restore = rtl8125_resume, -}; - -#define RTL8125_PM_OPS (&rtl8125_pm_ops) - -#endif - -#else /* !CONFIG_PM */ - -#define RTL8125_PM_OPS NULL - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8125_pci_driver = { - .name = MODULENAME, - .id_table = rtl8125_pci_tbl, - .probe = rtl8125_init_one, - .remove = __devexit_p(rtl8125_remove_one), -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) - .shutdown = rtl8125_shutdown, -#endif -#ifdef CONFIG_PM -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - .suspend = rtl8125_suspend, - .resume = rtl8125_resume, -#else - .driver.pm = RTL8125_PM_OPS, -#endif -#endif -}; - -static int __init -rtl8125_init_module(void) -{ - int ret = 0; -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_module_init(); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - ret = pci_register_driver(&rtl8125_pci_driver); -#else - ret = pci_module_init(&rtl8125_pci_driver); -#endif - - return ret; -} - -static void __exit -rtl8125_cleanup_module(void) -{ - pci_unregister_driver(&rtl8125_pci_driver); - -#ifdef ENABLE_R8125_PROCFS - if (rtl8125_proc) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(MODULENAME, init_net.proc_net); -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - remove_proc_entry(MODULENAME, init_net.proc_net); -#else - remove_proc_entry(MODULENAME, proc_net); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - rtl8125_proc = NULL; - } -#endif -} - -module_init(rtl8125_init_module); -module_exit(rtl8125_cleanup_module); diff --git a/r8125/src/r8125_ptp.c b/r8125/src/r8125_ptp.c deleted file mode 100644 index e1102b76d..000000000 --- a/r8125/src/r8125_ptp.c +++ /dev/null @@ -1,594 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "r8125.h" -#include "r8125_ptp.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) -{ - return *(const struct timespec *)&ts64; -} - -static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) -{ - return *(const struct timespec64 *)&ts; -} -#endif - -static int _rtl8125_phc_gettime(struct rtl8125_private *tp, struct timespec64 *ts64) -{ - //get local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_LATCHED_LOCAL_TIME | PTP_EXEC_CMD)); - - /* nanoseconds */ - //0x6808[29:0] - ts64->tv_nsec = (RTL_R32(tp, PTP_SOFT_CONFIG_Time_NS_8125) & 0x3fffffff) + - tp->ptp_adjust; - - /* seconds */ - //0x680C[47:0] - ts64->tv_sec = RTL_R16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4); - ts64->tv_sec <<= 32; - ts64->tv_sec |= RTL_R32(tp, PTP_SOFT_CONFIG_Time_S_8125); - - return 0; -} - -static int _rtl8125_phc_settime(struct rtl8125_private *tp, const struct timespec64 *ts64) -{ - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, (ts64->tv_nsec & 0x3fffffff)); - - /* seconds */ - //0x680C[47:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, ts64->tv_sec); - RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (ts64->tv_sec >> 32)); - - //set local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} - -#if 0 -static int _rtl8125_phc_adjtime(struct rtl8125_private *tp, s64 delta) -{ - struct timespec64 now, then = ns_to_timespec64(delta); - u32 nsec; - u64 sec; - - _rtl8125_phc_gettime(tp, &now); - now = timespec64_add(now, then); - - nsec = now.tv_nsec & 0x3fffffff; - sec = now.tv_sec & 0x0000ffffffffffff; - - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, nsec); - - /* seconds */ - //0x680C[47:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, sec); - RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (sec >> 32)); - - //adjust local time - //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} -#endif - -static int rtl8125_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - //int ret = 0; - - //netif_info(tp, drv, tp->dev, "phc adjust time\n"); - - spin_lock_irqsave(&tp->lock, flags); - //ret = _rtl8125_phc_adjtime(tp, delta); - tp->ptp_adjust += delta; - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -/* -1ppm means every 125MHz plus 125Hz. It also means every 8ns minus 8ns*10^(-6) - -1ns=2^30 sub_ns - -8ns*10^(-6) = 8 * 2^30 sub_ns * 10^(-6) = 2^33 sub_ns * 10^(-6) = 8590 = 0x218E sub_ns - -1ppb means every 125MHz plus 0.125Hz. It also means every 8ns minus 8ns*10^(-9) - -1ns=2^30 sub_ns - -8ns*10^(-9) = 8 * 2^30 sub_ns * 10^(-9) = 2^33 sub_ns * 10^(-9) = 8.59 sub_ns = 9 sub_ns -*/ -static int _rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - bool negative = false; - u32 sub_ns; - - if (ppb < 0) { - negative = true; - ppb = -ppb; - } - - sub_ns = ppb * 9; - if (negative) { - sub_ns = -sub_ns; - sub_ns &= 0x3fffffff; - sub_ns |= PTP_ADJUST_TIME_NS_NEGATIVE; - } else - sub_ns &= 0x3fffffff; - - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, sub_ns); - - //adjust local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); - //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} - -static int rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) -{ - //struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - - //netif_info(tp, drv, tp->dev, "phc adjust freq\n"); - - if (delta > ptp->max_adj || delta < -ptp->max_adj) - return -EINVAL; - - _rtl8125_phc_adjfreq(ptp, delta); - - return 0; -} - -static int rtl8125_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - int ret; - - //netif_info(tp, drv, tp->dev, "phc get ts\n"); - - spin_lock_irqsave(&tp->lock, flags); - ret = _rtl8125_phc_gettime(tp, ts64); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int rtl8125_phc_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts64) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - int ret; - - //netif_info(tp, drv, tp->dev, "phc set ts\n"); - - spin_lock_irqsave(&tp->lock, flags); - ret = _rtl8125_phc_settime(tp, ts64); - tp->ptp_adjust = 0; - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int rtl8125_phc_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, int on) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - u16 ptp_ctrl; - - //netif_info(tp, drv, tp->dev, "phc enable type %x on %d\n", rq->type, on); - - switch (rq->type) { - case PTP_CLK_REQ_PPS: - spin_lock_irqsave(&tp->lock, flags); - ptp_ctrl = RTL_R16(tp, PTP_CTRL_8125); - ptp_ctrl &= ~BIT_15; - if (on) - ptp_ctrl |= BIT_14; - else - ptp_ctrl &= ~BIT_14; - RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); - spin_unlock_irqrestore(&tp->lock, flags); - return 0; - default: - return -EOPNOTSUPP; - } -} - -int rtl8125_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - - /* we always support timestamping disabled */ - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); - - if (tp->HwSuppPtpVer == 0) - return ethtool_op_get_ts_info(netdev, info); - - info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE | - SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE; - - if (tp->ptp_clock) - info->phc_index = ptp_clock_index(tp->ptp_clock); - else - info->phc_index = -1; - - info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); - - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | - BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | - BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); - - return 0; -} - -static const struct ptp_clock_info rtl_ptp_clock_info = { - .owner = THIS_MODULE, - .n_alarm = 0, - .n_ext_ts = 0, - .n_per_out = 0, - .n_pins = 0, - .pps = 1, - .adjfreq = rtl8125_phc_adjfreq, - .adjtime = rtl8125_phc_adjtime, - .gettime64 = rtl8125_phc_gettime, - .settime64 = rtl8125_phc_settime, - .enable = rtl8125_phc_enable, -}; - -static int rtl8125_get_tx_ptp_pkt_tstamp(struct rtl8125_private *tp, struct timespec64 *ts64) -{ - return _rtl8125_phc_gettime(tp, ts64); -} - -static void rtl8125_ptp_tx_hwtstamp(struct rtl8125_private *tp) -{ - struct sk_buff *skb = tp->ptp_tx_skb; - struct skb_shared_hwtstamps shhwtstamps = {0}; - struct timespec64 ts64; - - RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); - - rtl8125_get_tx_ptp_pkt_tstamp(tp, &ts64); - - /* Upper 32 bits contain s, lower 32 bits contain ns. */ - shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec, - ts64.tv_nsec); - - /* Clear the lock early before calling skb_tstamp_tx so that - * applications are not woken up before the lock bit is clear. We use - * a copy of the skb pointer to ensure other threads can't change it - * while we're notifying the stack. - */ - tp->ptp_tx_skb = NULL; - - /* Notify the stack and free the skb after we've unlocked */ - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); -} - -#define RTL8125_PTP_TX_TIMEOUT (HZ * 15) -static void rtl8125_ptp_tx_work(struct work_struct *work) -{ - struct rtl8125_private *tp = container_of(work, struct rtl8125_private, - ptp_tx_work); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (!tp->ptp_tx_skb) - goto Exit; - - if (time_is_before_jiffies(tp->ptp_tx_start + - RTL8125_PTP_TX_TIMEOUT)) { - dev_kfree_skb_any(tp->ptp_tx_skb); - tp->ptp_tx_skb = NULL; - tp->tx_hwtstamp_timeouts++; - /* Clear the tx valid bit in TSYNCTXCTL register to enable - * interrupt - */ - RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); - goto Exit; - } - - if (RTL_R8(tp, PTP_ISR_8125) & (PTP_ISR_TOK)) - rtl8125_ptp_tx_hwtstamp(tp); - else - /* reschedule to check later */ - schedule_work(&tp->ptp_tx_work); - -Exit: - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8125_hwtstamp_enable(struct rtl8125_private *tp, bool enable) -{ - RTL_W16(tp, PTP_CTRL_8125, 0); - if (enable) { - u16 ptp_ctrl; - struct timespec64 ts64; - - //clear ptp isr - RTL_W8(tp, PTP_ISR_8125, 0xff); - //ptp source 0:gphy 1:mac - rtl8125_mac_ocp_write(tp, 0xDC00, rtl8125_mac_ocp_read(tp, 0xDC00) | BIT_6); - //enable ptp - ptp_ctrl = (BIT_0 | BIT_3 | BIT_4 | BIT_6 | BIT_10 | BIT_12 | BIT_13); - if (tp->ptp_master_mode) { - ptp_ctrl &= ~BIT_13; - ptp_ctrl |= BIT_1; - } - RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); - - //set system time - /* - if (ktime_to_timespec64_cond(ktime_get_real(), &ts64)) - _rtl8125_phc_settime(tp, timespec64_to_timespec(ts64)); - */ - ktime_get_real_ts64(&ts64); - ts64.tv_nsec += tp->ptp_adjust; - _rtl8125_phc_settime(tp, &ts64); - tp->ptp_adjust = 0; - } - - return 0; -} - -static long rtl8125_ptp_create_clock(struct rtl8125_private *tp) -{ - struct net_device *netdev = tp->dev; - long err; - - if (!IS_ERR_OR_NULL(tp->ptp_clock)) - return 0; - - if (tp->HwSuppPtpVer == 0) { - tp->ptp_clock = NULL; - return -EOPNOTSUPP; - } - - tp->ptp_clock_info = rtl_ptp_clock_info; - snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name), - "%pm", tp->dev->dev_addr); - tp->ptp_clock_info.max_adj = 119304647; - tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev); - if (IS_ERR(tp->ptp_clock)) { - err = PTR_ERR(tp->ptp_clock); - tp->ptp_clock = NULL; - netif_err(tp, drv, tp->dev, "ptp_clock_register failed\n"); - return err; - } else - netif_info(tp, drv, tp->dev, "registered PHC device on %s\n", netdev->name); - - return 0; -} - -void rtl8125_ptp_reset(struct rtl8125_private *tp) -{ - if (!tp->ptp_clock) - return; - - netif_info(tp, drv, tp->dev, "reset PHC clock\n"); - - rtl8125_hwtstamp_enable(tp, false); -} - -void rtl8125_ptp_init(struct rtl8125_private *tp) -{ - /* obtain a PTP device, or re-use an existing device */ - if (rtl8125_ptp_create_clock(tp)) - return; - - /* we have a clock so we can initialize work now */ - INIT_WORK(&tp->ptp_tx_work, rtl8125_ptp_tx_work); - - tp->ptp_adjust = 0; - - /* reset the PTP related hardware bits */ - rtl8125_ptp_reset(tp); - - return; -} - -void rtl8125_ptp_suspend(struct rtl8125_private *tp) -{ - if (!tp->ptp_clock) - return; - - netif_info(tp, drv, tp->dev, "suspend PHC clock\n"); - - rtl8125_hwtstamp_enable(tp, false); - - /* ensure that we cancel any pending PTP Tx work item in progress */ - cancel_work_sync(&tp->ptp_tx_work); -} - -void rtl8125_ptp_stop(struct rtl8125_private *tp) -{ - struct net_device *netdev = tp->dev; - - netif_info(tp, drv, tp->dev, "stop PHC clock\n"); - - /* first, suspend PTP activity */ - rtl8125_ptp_suspend(tp); - - /* disable the PTP clock device */ - if (tp->ptp_clock) { - ptp_clock_unregister(tp->ptp_clock); - tp->ptp_clock = NULL; - netif_info(tp, drv, tp->dev, "removed PHC on %s\n", - netdev->name); - } -} - -static int rtl8125_set_tstamp(struct net_device *netdev, struct ifreq *ifr) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - struct hwtstamp_config config; - bool hwtstamp = 0; - - //netif_info(tp, drv, tp->dev, "ptp set ts\n"); - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - if (config.flags) - return -EINVAL; - - switch (config.tx_type) { - case HWTSTAMP_TX_ON: - hwtstamp = 1; - case HWTSTAMP_TX_OFF: - break; - case HWTSTAMP_TX_ONESTEP_SYNC: - default: - return -ERANGE; - } - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - hwtstamp = 1; - case HWTSTAMP_FILTER_NONE: - break; - default: - return -ERANGE; - } - - if (tp->hwtstamp_config.tx_type != config.tx_type || - tp->hwtstamp_config.rx_filter != config.rx_filter) { - tp->hwtstamp_config = config; - rtl8125_hwtstamp_enable(tp, hwtstamp); - } - - return copy_to_user(ifr->ifr_data, &config, - sizeof(config)) ? -EFAULT : 0; -} - -static int rtl8125_get_tstamp(struct net_device *netdev, struct ifreq *ifr) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - - //netif_info(tp, drv, tp->dev, "ptp get ts\n"); - - return copy_to_user(ifr->ifr_data, &tp->hwtstamp_config, - sizeof(tp->hwtstamp_config)) ? -EFAULT : 0; -} - -int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - int ret; - unsigned long flags; - - //netif_info(tp, drv, tp->dev, "ptp ioctl\n"); - - ret = 0; - switch (cmd) { -#ifdef ENABLE_PTP_SUPPORT - case SIOCSHWTSTAMP: - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8125_set_tstamp(netdev, ifr); - spin_unlock_irqrestore(&tp->lock, flags); - break; - case SIOCGHWTSTAMP: - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8125_get_tstamp(netdev, ifr); - spin_unlock_irqrestore(&tp->lock, flags); - break; -#endif - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, - struct RxDescV3 *descv3) -{ - time64_t tv_sec; - long tv_nsec; - - tv_sec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampHigh) + - ((u64)le32_to_cpu(descv3->RxDescPTPDDWord4.TimeStampHHigh) << 32); - tv_nsec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampLow) + tp->ptp_adjust; - - skb_hwtstamps(skb)->hwtstamp = ktime_set(tv_sec, tv_nsec); -} diff --git a/r8125/src/r8125_ptp.h b/r8125/src/r8125_ptp.h deleted file mode 100644 index a324ff382..000000000 --- a/r8125/src/r8125_ptp.h +++ /dev/null @@ -1,81 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_PTP_H -#define _LINUX_rtl8125_PTP_H - -#include -#include -#include -#include -#include - -struct rtl8125_ptp_info { - s64 time_sec; - u32 time_ns; - u16 ts_info; -}; - -#ifndef _STRUCT_TIMESPEC -#define _STRUCT_TIMESPEC -struct timespec { - __kernel_old_time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; -#endif - -enum PTP_CMD_TYPE { - PTP_CMD_SET_LOCAL_TIME = 0, - PTP_CMD_DRIFT_LOCAL_TIME, - PTP_CMD_LATCHED_LOCAL_TIME, -}; - - -struct rtl8125_private; -struct RxDescV3; - -int rtl8125_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info); - -void rtl8125_ptp_reset(struct rtl8125_private *tp); -void rtl8125_ptp_init(struct rtl8125_private *tp); -void rtl8125_ptp_suspend(struct rtl8125_private *tp); -void rtl8125_ptp_stop(struct rtl8125_private *tp); - -int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); - -void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, - struct RxDescV3 *descv3); - -#endif /* _LINUX_rtl8125_PTP_H */ diff --git a/r8125/src/r8125_realwow.h b/r8125/src/r8125_realwow.h deleted file mode 100644 index 352e3270f..000000000 --- a/r8125/src/r8125_realwow.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8125_REALWOW_H -#define _LINUX_R8125_REALWOW_H - -#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3 - -#define MAX_RealWoW_KCP_SIZE (100) -#define MAX_RealWoW_Payload (64) - -#define KA_TX_PACKET_SIZE (100) -#define KA_WAKEUP_PATTERN_SIZE (120) - -//HwSuppKeepAliveOffloadVer -#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0) - -enum rtl_realwow_cmd { - - RTL_REALWOW_SET_KCP_DISABLE=0, - RTL_REALWOW_SET_KCP_INFO, - RTL_REALWOW_SET_KCP_CONTENT, - - RTL_REALWOW_SET_KCP_ACKPKTINFO, - RTL_REALWOW_SET_KCP_WPINFO, - RTL_REALWOW_SET_KCPDHCP_TIMEOUT, - - RTLT_REALWOW_COMMAND_INVALID -}; - -struct rtl_realwow_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -typedef struct _MP_KCPInfo { - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort[2]; - u8 PKTLEN[2]; - - u16 ackLostCnt; - u8 KCP_WakePattern[MAX_RealWoW_Payload]; - u8 KCP_AckPacket[MAX_RealWoW_Payload]; - u32 KCP_interval; - u8 KCP_WakePattern_Len; - u8 KCP_AckPacket_Len; - u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; -} MP_KCP_INFO, *PMP_KCP_INFO; - -typedef struct _KCPInfo { - u32 nId; // = id - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort; - u16 PKTLEN; -} KCPInfo, *PKCPInfo; - -typedef struct _KCPContent { - u32 id; // = id - u32 mSec; // = msec - u32 size; // =size - u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here -} KCPContent, *PKCPContent; - -typedef struct _RealWoWAckPktInfo { - u16 ackLostCnt; - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWAckPktInfo,*PRealWoWAckPktInfo; - -typedef struct _RealWoWWPInfo { - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWWPInfo,*PRealWoWWPInfo; - -int rtl8125_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); -void rtl8125_realwow_hw_init(struct net_device *dev); -void rtl8125_get_realwow_hw_version(struct net_device *dev); -void rtl8125_set_realwow_d3_para(struct net_device *dev); - -#endif /* _LINUX_R8125_REALWOW_H */ diff --git a/r8125/src/r8125_rss.c b/r8125/src/r8125_rss.c deleted file mode 100644 index a77917a93..000000000 --- a/r8125/src/r8125_rss.c +++ /dev/null @@ -1,484 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include "r8125.h" - -enum rtl8125_rss_register_content { - /* RSS */ - RSS_CTRL_TCP_IPV4_SUPP = (1 << 0), - RSS_CTRL_IPV4_SUPP = (1 << 1), - RSS_CTRL_TCP_IPV6_SUPP = (1 << 2), - RSS_CTRL_IPV6_SUPP = (1 << 3), - RSS_HALF_SUPP = (1 << 7), - RSS_CTRL_UDP_IPV4_SUPP = (1 << 11), - RSS_CTRL_UDP_IPV6_SUPP = (1 << 12), - RSS_QUAD_CPU_EN = (1 << 16), - RSS_HQ_Q_SUP_R = (1 << 31), -}; - -static int rtl8125_get_rss_hash_opts(struct rtl8125_private *tp, - struct ethtool_rxnfc *cmd) -{ - cmd->data = 0; - - /* Report default options for RSS */ - switch (cmd->flow_type) { - case TCP_V4_FLOW: - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case UDP_V4_FLOW: - if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case IPV4_FLOW: - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - break; - case TCP_V6_FLOW: - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case UDP_V6_FLOW: - if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case IPV6_FLOW: - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - break; - default: - return -EINVAL; - } - - return 0; -} - -int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - netif_info(tp, drv, tp->dev, "rss get rxnfc\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return ret; - - switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = rtl8125_tot_rx_rings(tp); - ret = 0; - break; - case ETHTOOL_GRXFH: - ret = rtl8125_get_rss_hash_opts(tp, cmd); - break; - default: - break; - } - - return ret; -} - -u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp) -{ - return tp->HwSuppIndirTblEntries; -} - -#define RSS_MASK_BITS_OFFSET (8) -#define RSS_CPU_NUM_OFFSET (16) -#define RTL8125_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \ - RTL_8125_RSS_FLAG_HASH_UDP_IPV6) -static int _rtl8125_set_rss_hash_opt(struct rtl8125_private *tp) -{ - u32 rss_flags = tp->rss_flags; - u32 hash_mask_len; - u32 rss_ctrl; - - rss_ctrl = ilog2(rtl8125_tot_rx_rings(tp)); - rss_ctrl &= (BIT_0 | BIT_1 | BIT_2); - rss_ctrl <<= RSS_CPU_NUM_OFFSET; - - /* Perform hash on these packet types */ - rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP - | RSS_CTRL_IPV4_SUPP - | RSS_CTRL_IPV6_SUPP - | RSS_CTRL_TCP_IPV6_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; - - hash_mask_len = ilog2(rtl8125_rss_indir_tbl_entries(tp)); - hash_mask_len &= (BIT_0 | BIT_1 | BIT_2); - rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET; - - RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); - - return 0; -} - -static int rtl8125_set_rss_hash_opt(struct rtl8125_private *tp, - struct ethtool_rxnfc *nfc) -{ - u32 rss_flags = tp->rss_flags; - - netif_info(tp, drv, tp->dev, "rss set hash\n"); - - /* - * RSS does not support anything other than hashing - * to queues on src and dst IPs and ports - */ - if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | - RXH_L4_B_0_1 | RXH_L4_B_2_3)) - return -EINVAL; - - switch (nfc->flow_type) { - case TCP_V4_FLOW: - case TCP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST) || - !(nfc->data & RXH_L4_B_0_1) || - !(nfc->data & RXH_L4_B_2_3)) - return -EINVAL; - break; - case UDP_V4_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV4; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV4; - break; - default: - return -EINVAL; - } - break; - case UDP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV6; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV6; - break; - default: - return -EINVAL; - } - break; - case SCTP_V4_FLOW: - case AH_ESP_V4_FLOW: - case AH_V4_FLOW: - case ESP_V4_FLOW: - case SCTP_V6_FLOW: - case AH_ESP_V6_FLOW: - case AH_V6_FLOW: - case ESP_V6_FLOW: - case IP_USER_FLOW: - case ETHER_FLOW: - /* RSS is not supported for these protocols */ - if (nfc->data) { - netif_err(tp, drv, tp->dev, "Command parameters not supported\n"); - return -EINVAL; - } - return 0; - break; - default: - return -EINVAL; - } - - /* if we changed something we need to update flags */ - if (rss_flags != tp->rss_flags) { - u32 rss_ctrl = RTL_R32(tp, RSS_CTRL_8125); - - if ((rss_flags & RTL8125_UDP_RSS_FLAGS) && - !(tp->rss_flags & RTL8125_UDP_RSS_FLAGS)) - netdev_warn(tp->dev, - "enabling UDP RSS: fragmented packets may " - "arrive out of order to the stack above\n"); - - tp->rss_flags = rss_flags; - - /* Perform hash on these packet types */ - rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP - | RSS_CTRL_IPV4_SUPP - | RSS_CTRL_IPV6_SUPP - | RSS_CTRL_TCP_IPV6_SUPP; - - rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP | - RSS_CTRL_UDP_IPV6_SUPP); - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; - - RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); - } - - return 0; -} - -int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - netif_info(tp, drv, tp->dev, "rss set rxnfc\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return ret; - - switch (cmd->cmd) { - case ETHTOOL_SRXFH: - ret = rtl8125_set_rss_hash_opt(tp, cmd); - break; - default: - break; - } - - return ret; -} - -static u32 _rtl8125_get_rxfh_key_size(struct rtl8125_private *tp) -{ - return sizeof(tp->rss_key); -} - -u32 rtl8125_get_rxfh_key_size(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get key size\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return 0; - - return _rtl8125_get_rxfh_key_size(tp); -} - -u32 rtl8125_rss_indir_size(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get indir tbl size\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return 0; - - return rtl8125_rss_indir_tbl_entries(tp); -} - -static void rtl8125_get_reta(struct rtl8125_private *tp, u32 *indir) -{ - int i, reta_size = rtl8125_rss_indir_tbl_entries(tp); - - for (i = 0; i < reta_size; i++) - indir[i] = tp->rss_indir_tbl[i]; -} - -int rtl8125_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, - u8 *hfunc) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get rxfh\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return -EOPNOTSUPP; - - if (hfunc) - *hfunc = ETH_RSS_HASH_TOP; - - if (indir) - rtl8125_get_reta(tp, indir); - - if (key) - memcpy(key, tp->rss_key, rtl8125_get_rxfh_key_size(dev)); - - return 0; -} - -#define RSS_KEY_8125 0x4600 -#define RSS_INDIRECTION_TBL_8125_V2 0x4700 - -static u32 rtl8125_rss_key_reg(struct rtl8125_private *tp) -{ - return RSS_KEY_8125; -} - -static u32 rtl8125_rss_indir_tbl_reg(struct rtl8125_private *tp) -{ - return RSS_INDIRECTION_TBL_8125_V2; -} - -static void rtl8125_store_reta(struct rtl8125_private *tp) -{ - u16 indir_tbl_reg = rtl8125_rss_indir_tbl_reg(tp); - u32 i, reta_entries = rtl8125_rss_indir_tbl_entries(tp); - u32 reta = 0; - u8 *indir_tbl = tp->rss_indir_tbl; - - /* Write redirection table to HW */ - for (i = 0; i < reta_entries; i++) { - reta |= indir_tbl[i] << (i & 0x3) * 8; - if ((i & 3) == 3) { - RTL_W32(tp, indir_tbl_reg, reta); - - indir_tbl_reg += 4; - reta = 0; - } - } -} - -static void rtl8125_store_rss_key(struct rtl8125_private *tp) -{ - const u16 rss_key_reg = rtl8125_rss_key_reg(tp); - u32 i, rss_key_size = _rtl8125_get_rxfh_key_size(tp); - u32 *rss_key = (u32*)tp->rss_key; - - /* Write redirection table to HW */ - for (i = 0; i < rss_key_size; i+=4) - RTL_W32(tp, rss_key_reg + i, *rss_key++); -} - -int rtl8125_set_rxfh(struct net_device *dev, const u32 *indir, - const u8 *key, const u8 hfunc) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - u32 reta_entries = rtl8125_rss_indir_tbl_entries(tp); - - netif_info(tp, drv, tp->dev, "rss set rxfh\n"); - - /* We require at least one supported parameter to be changed and no - * change in any of the unsupported parameters - */ - if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) - return -EOPNOTSUPP; - - /* Fill out the redirection table */ - if (indir) { - int max_queues = tp->num_rx_rings; - - /* Verify user input. */ - for (i = 0; i < reta_entries; i++) - if (indir[i] >= max_queues) - return -EINVAL; - - for (i = 0; i < reta_entries; i++) - tp->rss_indir_tbl[i] = indir[i]; - } - - /* Fill out the rss hash key */ - if (key) - memcpy(tp->rss_key, key, rtl8125_get_rxfh_key_size(dev)); - - rtl8125_store_reta(tp); - - rtl8125_store_rss_key(tp); - - return 0; -} - -static u32 rtl8125_get_rx_desc_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3) -{ - return le32_to_cpu(descv3->RxDescNormalDDWord2.RSSResult); -} - -#define RXS_8125B_RSS_UDP BIT(9) -#define RXS_8125_RSS_IPV4 BIT(10) -#define RXS_8125_RSS_IPV6 BIT(12) -#define RXS_8125_RSS_TCP BIT(13) -#define RTL8125_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6) -#define RTL8125_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP) -void rtl8125_rx_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3, - struct sk_buff *skb) -{ - u16 rss_header_info; - - if (!(tp->dev->features & NETIF_F_RXHASH)) - return; - - rss_header_info = le16_to_cpu(descv3->RxDescNormalDDWord2.HeaderInfo); - - if (!(rss_header_info & RTL8125_RXS_RSS_L3_TYPE_MASK)) - return; - - skb_set_hash(skb, rtl8125_get_rx_desc_hash(tp, descv3), - (RTL8125_RXS_RSS_L4_TYPE_MASK & rss_header_info) ? - PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); -} - -void rtl8125_disable_rss(struct rtl8125_private *tp) -{ - RTL_W32(tp, RSS_CTRL_8125, 0x00); -} - -void _rtl8125_config_rss(struct rtl8125_private *tp) -{ - _rtl8125_set_rss_hash_opt(tp); - - rtl8125_store_reta(tp); - - rtl8125_store_rss_key(tp); -} - -void rtl8125_config_rss(struct rtl8125_private *tp) -{ - if (!tp->EnableRss) { - rtl8125_disable_rss(tp); - return; - } - - _rtl8125_config_rss(tp); -} - -void rtl8125_init_rss(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < rtl8125_rss_indir_tbl_entries(tp); i++) - tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings); - - netdev_rss_key_fill(tp->rss_key, RTL8125_RSS_KEY_SIZE); -} diff --git a/r8125/src/r8125_rss.h b/r8125/src/r8125_rss.h deleted file mode 100644 index d77752816..000000000 --- a/r8125/src/r8125_rss.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_RSS_H -#define _LINUX_rtl8125_RSS_H - -#include -#include - -enum rtl8125_rss_flag { - RTL_8125_RSS_FLAG_HASH_UDP_IPV4 = (1 << 0), - RTL_8125_RSS_FLAG_HASH_UDP_IPV6 = (1 << 1), -}; - -struct rtl8125_private; - -int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs); -int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); -u32 rtl8125_get_rxfh_key_size(struct net_device *netdev); -u32 rtl8125_rss_indir_size(struct net_device *netdev); -int rtl8125_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, - u8 *hfunc); -int rtl8125_set_rxfh(struct net_device *netdev, const u32 *indir, - const u8 *key, const u8 hfunc); -void rtl8125_rx_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3, - struct sk_buff *skb); -void _rtl8125_config_rss(struct rtl8125_private *tp); -void rtl8125_config_rss(struct rtl8125_private *tp); -void rtl8125_init_rss(struct rtl8125_private *tp); -u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp); -void rtl8125_disable_rss(struct rtl8125_private *tp); - -#endif /* _LINUX_rtl8125_RSS_H */ diff --git a/r8125/src/rtl_eeprom.c b/r8125/src/rtl_eeprom.c deleted file mode 100644 index 866ae5f33..000000000 --- a/r8125/src/rtl_eeprom.c +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -#include "r8125.h" -#include "rtl_eeprom.h" - -//------------------------------------------------------------------- -//rtl8125_eeprom_type(): -// tell the eeprom type -//return value: -// 0: the eeprom type is 93C46 -// 1: the eeprom type is 93C56 or 93C66 -//------------------------------------------------------------------- -void rtl8125_eeprom_type(struct rtl8125_private *tp) -{ - u16 magic = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - goto out_no_eeprom; - - if(RTL_R8(tp, 0xD2)&0x04) { - //not support - //tp->eeprom_type = EEPROM_TWSI; - //tp->eeprom_len = 256; - goto out_no_eeprom; - } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { - tp->eeprom_type = EEPROM_TYPE_93C56; - tp->eeprom_len = 256; - } else { - tp->eeprom_type = EEPROM_TYPE_93C46; - tp->eeprom_len = 128; - } - - magic = rtl8125_eeprom_read_sc(tp, 0); - -out_no_eeprom: - if ((magic != 0x8129) && (magic != 0x8128)) { - tp->eeprom_type = EEPROM_TYPE_NONE; - tp->eeprom_len = 0; - } -} - -void rtl8125_eeprom_cleanup(struct rtl8125_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EECS); - - RTL_W8(tp, Cfg9346, x); - - rtl8125_raise_clock(tp, &x); - rtl8125_lower_clock(tp, &x); -} - -int rtl8125_eeprom_cmd_done(struct rtl8125_private *tp) -{ - u8 x; - int i; - - rtl8125_stand_by(tp); - - for (i = 0; i < 50000; i++) { - x = RTL_R8(tp, Cfg9346); - - if (x & Cfg9346_EEDO) { - udelay(RTL_CLOCK_RATE * 2 * 3); - return 0; - } - udelay(1); - } - - return -1; -} - -//------------------------------------------------------------------- -//rtl8125_eeprom_read_sc(): -// read one word from eeprom -//------------------------------------------------------------------- -u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg) -{ - int addr_sz = 6; - u8 x; - u16 data; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return -1; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) - addr_sz = 6; - else if (tp->eeprom_type==EEPROM_TYPE_93C56) - addr_sz = 8; - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - - data = rtl8125_shift_in_bits(tp); - - rtl8125_eeprom_cleanup(tp); - - RTL_W8(tp, Cfg9346, 0); - - return data; -} - -//------------------------------------------------------------------- -//rtl8125_eeprom_write_sc(): -// write one word to a specific address in the eeprom -//------------------------------------------------------------------- -void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data) -{ - u8 x; - int addr_sz = 6; - int w_dummy_addr = 4; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return ; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) { - addr_sz = 6; - w_dummy_addr = 4; - } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { - addr_sz = 8; - w_dummy_addr = 6; - } - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); - rtl8125_shift_out_bits(tp, reg, w_dummy_addr); - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - if (rtl8125_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - rtl8125_shift_out_bits(tp, data, 16); - if (rtl8125_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); - rtl8125_shift_out_bits(tp, reg, w_dummy_addr); - - rtl8125_eeprom_cleanup(tp); - RTL_W8(tp, Cfg9346, 0); -} - -void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x) -{ - *x = *x | Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x) -{ - - *x = *x & ~Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count) -{ - u8 x; - int mask; - - mask = 0x01 << (count - 1); - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - do { - if (data & mask) - x |= Cfg9346_EEDI; - else - x &= ~Cfg9346_EEDI; - - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - rtl8125_raise_clock(tp, &x); - rtl8125_lower_clock(tp, &x); - mask = mask >> 1; - } while(mask); - - x &= ~Cfg9346_EEDI; - RTL_W8(tp, Cfg9346, x); -} - -u16 rtl8125_shift_in_bits(struct rtl8125_private *tp) -{ - u8 x; - u16 d, i; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - d = 0; - - for (i = 0; i < 16; i++) { - d = d << 1; - rtl8125_raise_clock(tp, &x); - - x = RTL_R8(tp, Cfg9346); - x &= ~Cfg9346_EEDI; - - if (x & Cfg9346_EEDO) - d |= 1; - - rtl8125_lower_clock(tp, &x); - } - - return d; -} - -void rtl8125_stand_by(struct rtl8125_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EECS | Cfg9346_EESK); - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - - x |= Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); -} - -void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); - RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); - - udelay(20); - - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); -} diff --git a/r8125/src/rtl_eeprom.h b/r8125/src/rtl_eeprom.h deleted file mode 100644 index b0c4a050b..000000000 --- a/r8125/src/rtl_eeprom.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -//EEPROM opcodes -#define RTL_EEPROM_READ_OPCODE 06 -#define RTL_EEPROM_WRITE_OPCODE 05 -#define RTL_EEPROM_ERASE_OPCODE 07 -#define RTL_EEPROM_EWEN_OPCODE 19 -#define RTL_EEPROM_EWDS_OPCODE 16 - -#define RTL_CLOCK_RATE 3 - -void rtl8125_eeprom_type(struct rtl8125_private *tp); -void rtl8125_eeprom_cleanup(struct rtl8125_private *tp); -u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg); -void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data); -void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count); -u16 rtl8125_shift_in_bits(struct rtl8125_private *tp); -void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x); -void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x); -void rtl8125_stand_by(struct rtl8125_private *tp); -void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp); diff --git a/r8125/src/rtltool.c b/r8125/src/rtltool.c deleted file mode 100644 index a9c46ea74..000000000 --- a/r8125/src/rtltool.c +++ /dev/null @@ -1,359 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "r8125.h" -#include "rtl_eeprom.h" -#include "rtltool.h" - -int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr) -{ - struct rtltool_cmd my_cmd; - unsigned long flags; - int ret; - - if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) - return -EFAULT; - - ret = 0; - switch (my_cmd.cmd) { - case RTLTOOL_READ_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8125_mdio_prot_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTLTOOL_READ_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8125_ephy_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_ephy_write(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTLTOOL_READ_ERI: - my_cmd.data = 0; - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8125_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_ERI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - spin_lock_irqsave(&tp->lock, flags); - rtl8125_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - ret = -EOPNOTSUPP; - break; - } - break; - - case RTLTOOL_READ_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = 0; - if (my_cmd.len==1) - pci_read_config_byte(tp->pci_dev, my_cmd.offset, - (u8 *)&my_cmd.data); - else if (my_cmd.len==2) - pci_read_config_word(tp->pci_dev, my_cmd.offset, - (u16 *)&my_cmd.data); - else if (my_cmd.len==4) - pci_read_config_dword(tp->pci_dev, my_cmd.offset, - &my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - pci_write_config_byte(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==2) - pci_write_config_word(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==4) - pci_write_config_dword(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8125_eeprom_read_sc(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_READ_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_oob_mutex_lock(tp); - my_cmd.data = rtl8125_ocp_read(tp, my_cmd.offset, 4); - rtl8125_oob_mutex_unlock(tp); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len == 0 || my_cmd.len > 4) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_oob_mutex_lock(tp); - rtl8125_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); - rtl8125_oob_mutex_unlock(tp); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_ENABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - tp->rtk_enable_diag = 1; - spin_unlock_irqrestore(&tp->lock, flags); - - dprintk("enable rtk diag\n"); - break; - - case RTL_DISABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - tp->rtk_enable_diag = 0; - spin_unlock_irqrestore(&tp->lock, flags); - - dprintk("disable rtk diag\n"); - break; - - case RTL_READ_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.offset % 2) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8125_mac_ocp_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if ((my_cmd.offset % 2) || (my_cmd.len != 2)) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_DIRECT_READ_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTL_DIRECT_WRITE_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} diff --git a/r8125/src/rtltool.h b/r8125/src/rtltool.h deleted file mode 100644 index fc8a10ca8..000000000 --- a/r8125/src/rtltool.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_RTLTOOL_H -#define _LINUX_RTLTOOL_H - -#define SIOCRTLTOOL SIOCDEVPRIVATE+1 - -enum rtl_cmd { - RTLTOOL_READ_MAC=0, - RTLTOOL_WRITE_MAC, - RTLTOOL_READ_PHY, - RTLTOOL_WRITE_PHY, - RTLTOOL_READ_EPHY, - RTLTOOL_WRITE_EPHY, - RTLTOOL_READ_ERI, - RTLTOOL_WRITE_ERI, - RTLTOOL_READ_PCI, - RTLTOOL_WRITE_PCI, - RTLTOOL_READ_EEPROM, - RTLTOOL_WRITE_EEPROM, - - RTL_READ_OOB_MAC, - RTL_WRITE_OOB_MAC, - - RTL_ENABLE_PCI_DIAG, - RTL_DISABLE_PCI_DIAG, - - RTL_READ_MAC_OCP, - RTL_WRITE_MAC_OCP, - - RTL_DIRECT_READ_PHY_OCP, - RTL_DIRECT_WRITE_PHY_OCP, - - RTLTOOL_INVALID -}; - -struct rtltool_cmd { - __u32 cmd; - __u32 offset; - __u32 len; - __u32 data; -}; - -enum mode_access { - MODE_NONE=0, - MODE_READ, - MODE_WRITE -}; - -#ifdef __KERNEL__ -int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr); -#endif - -#endif /* _LINUX_RTLTOOL_H */ diff --git a/r8152/Makefile b/r8152/Makefile new file mode 100644 index 000000000..da66898e8 --- /dev/null +++ b/r8152/Makefile @@ -0,0 +1,55 @@ +# +# Download realtek r8152 linux driver from official site: +# [https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-usb-3-0-software] +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=r8152 +PKG_VERSION:=2.15 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/1715173329/realtek-r8152-linux/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=dc8a06ed6ff397029c396a7e83476f1bf9541c4f927a4dbac8810c6ce014f8ca + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/realtek-$(PKG_NAME)-linux-$(PKG_VERSION) + +PKG_BUILD_PARALLEL:=1 + +PKG_MAINTAINER:=Tianling Shen + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/usb-net-rtl8152-vendor + TITLE:=Kernel module for USB-to-Ethernet Realtek convertors + SUBMENU:=USB Support + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + DEPENDS:=@TARGET_x86 +kmod-usb-net + CONFLICTS:=kmod-usb-net-rtl8152 + FILES:= $(PKG_BUILD_DIR)/r8152.ko + AUTOLOAD:=$(call AutoProbe,r8152) +endef + +define KernelPackage/usb-net-rtl8152-vendor/description + Kernel module for Realtek RTL8152/RTL8153 Based USB Ethernet Adapters +endef + +R8152_MAKEOPTS= -C $(PKG_BUILD_DIR) \ + PATH="$(TARGET_PATH)" \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + TARGET="$(HAL_TARGET)" \ + TOOLPREFIX="$(KERNEL_CROSS)" \ + TOOLPATH="$(KERNEL_CROSS)" \ + KERNELPATH="$(LINUX_DIR)" \ + KERNELDIR="$(LINUX_DIR)" \ + LDOPTS=" " \ + DOMULTI=1 + +define Build/Compile + +$(MAKE) $(PKG_JOBS) $(R8152_MAKEOPTS) modules +endef + +$(eval $(call KernelPackage,usb-net-rtl8152-vendor)) diff --git a/r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch b/r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch new file mode 100644 index 000000000..fdbf84253 --- /dev/null +++ b/r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch @@ -0,0 +1,26 @@ +From b61b90b9aea30b944fc51b891dab3ab5eb30980c Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Sat, 29 May 2021 00:46:25 +0800 +Subject: [PATCH] compat: skb_mark_not_on_list was backported since kernel + 4.14.217 and 4.19.10 + +Signed-off-by: Tianling Shen +--- + compatibility.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/compatibility.h ++++ b/compatibility.h +@@ -548,10 +548,12 @@ + linkmode_clear_bit(nr, addr); + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,217) || LINUX_VERSION_CODE < KERNEL_VERSION(4,19,10) + static inline void skb_mark_not_on_list(struct sk_buff *skb) + { + skb->next = NULL; + } ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,14,217) || LINUX_VERSION_CODE < KERNEL_VERSION(4,19,10) */ + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) */ + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0) */ + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) */ diff --git a/r8152/patches/100-add-LED-configuration-from-OF.patch b/r8152/patches/100-add-LED-configuration-from-OF.patch new file mode 100644 index 000000000..38d885d72 --- /dev/null +++ b/r8152/patches/100-add-LED-configuration-from-OF.patch @@ -0,0 +1,74 @@ +From 82985725e071f2a5735052f18e109a32aeac3a0b Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 26 Jul 2020 02:38:31 +0200 +Subject: [PATCH] add LED configuration from OF + +This adds the ability to configure the LED configuration register using +OF. This way, the correct value for board specific LED configuration can +be determined. + +Signed-off-by: David Bauer +--- + r8152.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/r8152.c ++++ b/r8152.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -9804,6 +9805,22 @@ static void rtl_tally_reset(struct r8152 + ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); + } + ++static int r8152_led_configuration(struct r8152 *tp) ++{ ++ u32 led_data; ++ int ret; ++ ++ ret = of_property_read_u32(tp->udev->dev.of_node, "realtek,led-data", ++ &led_data); ++ ++ if (ret) ++ return ret; ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_LEDSEL, led_data); ++ ++ return 0; ++} ++ + static void r8152b_init(struct r8152 *tp) + { + u32 ocp_data; +@@ -9865,6 +9882,8 @@ static void r8152b_init(struct r8152 *tp + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); + ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); + ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ r8152_led_configuration(tp); + } + + static void r8153_init(struct r8152 *tp) +@@ -10008,6 +10027,8 @@ static void r8153_init(struct r8152 *tp) + tp->coalesce = COALESCE_SLOW; + break; + } ++ ++ r8152_led_configuration(tp); + } + + static void r8153b_init(struct r8152 *tp) +@@ -10098,6 +10119,8 @@ static void r8153b_init(struct r8152 *tp + rtl_tally_reset(tp); + + tp->coalesce = 15000; /* 15 us */ ++ ++ r8152_led_configuration(tp); + } + + static void r8153c_init(struct r8152 *tp) diff --git a/r8168/Makefile b/r8168/Makefile new file mode 100644 index 000000000..fd5977a5b --- /dev/null +++ b/r8168/Makefile @@ -0,0 +1,54 @@ +# +# Download realtek r8168 linux driver from official site: +# [https://www.realtek.com/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software] +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=r8168 +PKG_VERSION:=8.049.02 +PKG_RELEASE:=$(AUTORELEAE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/BROBIRD/openwrt-r8168.git +PKG_SOURCE_DATE:=2021-10-08 +PKG_SOURCE_VERSION:=2b969c15afe403a685fc7ee069620782241e3ad6 +PKG_MIRROR_HASH:=e4632c10d460f005eff76da8a183d7ff0c8819b0d099872589b7b06a9b8d9952 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +MAKE_PATH:=src + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/r8168 + TITLE:=Driver for Realtek r8168 chipsets + SUBMENU:=Network Devices + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + FILES:= $(PKG_BUILD_DIR)/src/r8168.ko + AUTOLOAD:=$(call AutoProbe,r8168) + CONFLICTS:=kmod-r8169 +endef + +define Package/r8168/description + This package contains a driver for Realtek r8168 chipsets. +endef + +R8168_MAKEOPTS= -C $(PKG_BUILD_DIR)/src \ + PATH="$(TARGET_PATH)" \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + TARGET="$(HAL_TARGET)" \ + TOOLPREFIX="$(KERNEL_CROSS)" \ + TOOLPATH="$(KERNEL_CROSS)" \ + KERNELPATH="$(LINUX_DIR)" \ + KERNELDIR="$(LINUX_DIR)" \ + LDOPTS=" " \ + DOMULTI=1 + +define Build/Compile + $(MAKE) $(R8168_MAKEOPTS) modules +endef + +$(eval $(call KernelPackage,r8168)) diff --git a/r8168/patches/001-r8168-add-LED-configuration-from-OF.patch b/r8168/patches/001-r8168-add-LED-configuration-from-OF.patch new file mode 100644 index 000000000..62a352dd8 --- /dev/null +++ b/r8168/patches/001-r8168-add-LED-configuration-from-OF.patch @@ -0,0 +1,42 @@ +--- a/src/r8168_n.c ++++ b/src/r8168_n.c +@@ -47,6 +47,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -23482,6 +23483,22 @@ rtl8168_set_bios_setting(struct net_devi + } + } + ++static int rtl8168_led_configuration(struct rtl8168_private *tp) ++{ ++ u32 led_data; ++ int ret; ++ ++ ret = of_property_read_u32(tp->pci_dev->dev.of_node, ++ "realtek,led-data", &led_data); ++ ++ if (ret) ++ return ret; ++ ++ RTL_W16(tp, CustomLED, led_data); ++ ++ return 0; ++} ++ + static void + rtl8168_init_software_variable(struct net_device *dev) + { +@@ -24000,6 +24017,8 @@ rtl8168_init_software_variable(struct ne + tp->NotWrMcuPatchCode = TRUE; + } + ++ rtl8168_led_configuration(tp); ++ + tp->NicCustLedValue = RTL_R16(tp, CustomLED); + + rtl8168_get_hw_wol(dev); From 308bbb5b347bd31cc723d7b047ce1a47b18e2f3a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 26 Nov 2021 19:36:58 +0100 Subject: [PATCH 0626/2059] Update v2ray URL --- v2ray-core/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 48f2f8197..f17adbf69 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -12,8 +12,9 @@ PKG_NAME:=v2ray-core PKG_VERSION:=4.43.0 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/v$(PKG_VERSION) +#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE:=v$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/refs/tags/ PKG_HASH:=f27b8fe8e1e102b0297339ee368c8b650fde0f949e0d90e1229ff6744f99ba0f PKG_LICENSE:=MIT From caab49cc2670083689d1380a92053e5b31fdd5af Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 26 Nov 2021 19:37:56 +0100 Subject: [PATCH 0627/2059] Remove r8152 driver --- r8152/Makefile | 55 -------------- ...not_on_list-was-backported-since-ker.patch | 26 ------- .../100-add-LED-configuration-from-OF.patch | 74 ------------------- 3 files changed, 155 deletions(-) delete mode 100644 r8152/Makefile delete mode 100644 r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch delete mode 100644 r8152/patches/100-add-LED-configuration-from-OF.patch diff --git a/r8152/Makefile b/r8152/Makefile deleted file mode 100644 index da66898e8..000000000 --- a/r8152/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# Download realtek r8152 linux driver from official site: -# [https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-usb-3-0-software] -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=r8152 -PKG_VERSION:=2.15 -PKG_RELEASE:=2 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/1715173329/realtek-r8152-linux/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=dc8a06ed6ff397029c396a7e83476f1bf9541c4f927a4dbac8810c6ce014f8ca - -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/realtek-$(PKG_NAME)-linux-$(PKG_VERSION) - -PKG_BUILD_PARALLEL:=1 - -PKG_MAINTAINER:=Tianling Shen - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/usb-net-rtl8152-vendor - TITLE:=Kernel module for USB-to-Ethernet Realtek convertors - SUBMENU:=USB Support - VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) - DEPENDS:=@TARGET_x86 +kmod-usb-net - CONFLICTS:=kmod-usb-net-rtl8152 - FILES:= $(PKG_BUILD_DIR)/r8152.ko - AUTOLOAD:=$(call AutoProbe,r8152) -endef - -define KernelPackage/usb-net-rtl8152-vendor/description - Kernel module for Realtek RTL8152/RTL8153 Based USB Ethernet Adapters -endef - -R8152_MAKEOPTS= -C $(PKG_BUILD_DIR) \ - PATH="$(TARGET_PATH)" \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - TARGET="$(HAL_TARGET)" \ - TOOLPREFIX="$(KERNEL_CROSS)" \ - TOOLPATH="$(KERNEL_CROSS)" \ - KERNELPATH="$(LINUX_DIR)" \ - KERNELDIR="$(LINUX_DIR)" \ - LDOPTS=" " \ - DOMULTI=1 - -define Build/Compile - +$(MAKE) $(PKG_JOBS) $(R8152_MAKEOPTS) modules -endef - -$(eval $(call KernelPackage,usb-net-rtl8152-vendor)) diff --git a/r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch b/r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch deleted file mode 100644 index fdbf84253..000000000 --- a/r8152/patches/010-compat-skb_mark_not_on_list-was-backported-since-ker.patch +++ /dev/null @@ -1,26 +0,0 @@ -From b61b90b9aea30b944fc51b891dab3ab5eb30980c Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Sat, 29 May 2021 00:46:25 +0800 -Subject: [PATCH] compat: skb_mark_not_on_list was backported since kernel - 4.14.217 and 4.19.10 - -Signed-off-by: Tianling Shen ---- - compatibility.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/compatibility.h -+++ b/compatibility.h -@@ -548,10 +548,12 @@ - linkmode_clear_bit(nr, addr); - } - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,217) || LINUX_VERSION_CODE < KERNEL_VERSION(4,19,10) - static inline void skb_mark_not_on_list(struct sk_buff *skb) - { - skb->next = NULL; - } -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,14,217) || LINUX_VERSION_CODE < KERNEL_VERSION(4,19,10) */ - #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) */ - #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0) */ - #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) */ diff --git a/r8152/patches/100-add-LED-configuration-from-OF.patch b/r8152/patches/100-add-LED-configuration-from-OF.patch deleted file mode 100644 index 38d885d72..000000000 --- a/r8152/patches/100-add-LED-configuration-from-OF.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 82985725e071f2a5735052f18e109a32aeac3a0b Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Sun, 26 Jul 2020 02:38:31 +0200 -Subject: [PATCH] add LED configuration from OF - -This adds the ability to configure the LED configuration register using -OF. This way, the correct value for board specific LED configuration can -be determined. - -Signed-off-by: David Bauer ---- - r8152.c | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - ---- a/r8152.c -+++ b/r8152.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -9804,6 +9805,22 @@ static void rtl_tally_reset(struct r8152 - ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); - } - -+static int r8152_led_configuration(struct r8152 *tp) -+{ -+ u32 led_data; -+ int ret; -+ -+ ret = of_property_read_u32(tp->udev->dev.of_node, "realtek,led-data", -+ &led_data); -+ -+ if (ret) -+ return ret; -+ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_LEDSEL, led_data); -+ -+ return 0; -+} -+ - static void r8152b_init(struct r8152 *tp) - { - u32 ocp_data; -@@ -9865,6 +9882,8 @@ static void r8152b_init(struct r8152 *tp - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); - ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); - ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); -+ -+ r8152_led_configuration(tp); - } - - static void r8153_init(struct r8152 *tp) -@@ -10008,6 +10027,8 @@ static void r8153_init(struct r8152 *tp) - tp->coalesce = COALESCE_SLOW; - break; - } -+ -+ r8152_led_configuration(tp); - } - - static void r8153b_init(struct r8152 *tp) -@@ -10098,6 +10119,8 @@ static void r8153b_init(struct r8152 *tp - rtl_tally_reset(tp); - - tp->coalesce = 15000; /* 15 us */ -+ -+ r8152_led_configuration(tp); - } - - static void r8153c_init(struct r8152 *tp) From 20e8dce69f83b50bf994e75147b03ead6f18d4b2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 30 Nov 2021 17:43:47 +0100 Subject: [PATCH 0628/2059] Enable SQM by default on interfaces --- .../luasrc/controller/openmptcprouter.lua | 2 +- openmptcprouter/files/etc/uci-defaults/2040-omr-sqm | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 27bae5b7f..58d354013 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -201,7 +201,7 @@ function wizard_add() ucic:set("sqm","wan" .. i,"script","simple.qos") ucic:set("sqm","wan" .. i,"qdisc_advanced","0") ucic:set("sqm","wan" .. i,"linklayer","none") - ucic:set("sqm","wan" .. i,"enabled","0") + ucic:set("sqm","wan" .. i,"enabled","1") ucic:set("sqm","wan" .. i,"debug_logging","0") ucic:set("sqm","wan" .. i,"verbosity","5") ucic:set("sqm","wan" .. i,"download","0") diff --git a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm index 030400bb9..1054b39b9 100755 --- a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm +++ b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm @@ -10,7 +10,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan1.script="simple.qos" set sqm.wan1.qdisc_advanced='0' set sqm.wan1.linklayer='none' - set sqm.wan1.enabled='0' + set sqm.wan1.enabled='1' set sqm.wan1.interface="${wan1}" set sqm.wan1.download='0' set sqm.wan1.upload='0' @@ -23,7 +23,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan2.script="simple.qos" set sqm.wan2.qdisc_advanced='0' set sqm.wan2.linklayer='none' - set sqm.wan2.enabled='0' + set sqm.wan2.enabled='1' set sqm.wan2.interface="${wan2}" set sqm.wan2.download='0' set sqm.wan2.upload='0' @@ -41,7 +41,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan3.script="simple.qos" set sqm.wan3.qdisc_advanced='0' set sqm.wan3.linklayer='none' - set sqm.wan3.enabled='0' + set sqm.wan3.enabled='1' set sqm.wan3.interface="${wan3}" set sqm.wan3.download='0' set sqm.wan3.upload='0' @@ -60,7 +60,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan4.script="simple.qos" set sqm.wan4.qdisc_advanced='0' set sqm.wan4.linklayer='none' - set sqm.wan4.enabled='0' + set sqm.wan4.enabled='1' set sqm.wan4.interface="${wan4}" set sqm.wan4.download='0' set sqm.wan4.upload='0' From e9a628fae5fa5b5f3ad37fae60b1f11f089d1cfc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 30 Nov 2021 17:44:33 +0100 Subject: [PATCH 0629/2059] Remove iptables-mod-fullconenat that doesn't compile with 5.15 for now --- iptables-mod-fullconenat/Makefile | 65 ------------------- iptables-mod-fullconenat/README.md | 27 -------- iptables-mod-fullconenat/files/Makefile | 7 -- .../patches/000-printk.patch | 17 ----- 4 files changed, 116 deletions(-) delete mode 100644 iptables-mod-fullconenat/Makefile delete mode 100644 iptables-mod-fullconenat/README.md delete mode 100644 iptables-mod-fullconenat/files/Makefile delete mode 100644 iptables-mod-fullconenat/patches/000-printk.patch diff --git a/iptables-mod-fullconenat/Makefile b/iptables-mod-fullconenat/Makefile deleted file mode 100644 index 279c1eb9a..000000000 --- a/iptables-mod-fullconenat/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (C) 2018 Chion Tang -# -# 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:=fullconenat -PKG_RELEASE:=1 - -PKG_SOURCE_DATE:=2019-10-21 -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/Chion82/netfilter-full-cone-nat.git -PKG_SOURCE_VERSION:=0cf3b48fd7d2fa81d0297d1fff12bbd0580fc435 - -PKG_LICENSE:=GPL-2.0 -PKG_LICENSE_FILES:=LICENSE - -include $(INCLUDE_DIR)/package.mk - -define Package/iptables-mod-fullconenat - SUBMENU:=Firewall - SECTION:=net - CATEGORY:=Network - TITLE:=FULLCONENAT iptables extension - DEPENDS:=+iptables +kmod-ipt-fullconenat - MAINTAINER:=Chion Tang -endef - -define Package/iptables-mod-fullconenat/install - $(INSTALL_DIR) $(1)/usr/lib/iptables - $(INSTALL_BIN) $(PKG_BUILD_DIR)/libipt_FULLCONENAT.so $(1)/usr/lib/iptables -endef - -define KernelPackage/ipt-fullconenat - SUBMENU:=Netfilter Extensions - TITLE:=FULLCONENAT netfilter module - DEPENDS:=+kmod-nf-ipt +kmod-nf-nat - MAINTAINER:=Chion Tang - KCONFIG:=CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y - FILES:=$(PKG_BUILD_DIR)/xt_FULLCONENAT.ko -endef - -include $(INCLUDE_DIR)/kernel-defaults.mk - -define Build/Prepare - $(call Build/Prepare/Default) - $(CP) ./files/Makefile $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(BUILDFLAGS)" \ - modules - $(call Build/Compile/Default) -endef - -$(eval $(call BuildPackage,iptables-mod-fullconenat)) -$(eval $(call KernelPackage,ipt-fullconenat)) diff --git a/iptables-mod-fullconenat/README.md b/iptables-mod-fullconenat/README.md deleted file mode 100644 index 4d4909802..000000000 --- a/iptables-mod-fullconenat/README.md +++ /dev/null @@ -1,27 +0,0 @@ -## Netfilter and iptables extension for [FULLCONENAT](https://github.com/Chion82/netfilter-full-cone-nat) target ported to OpenWrt. - -Compile ---- -``` -# cd to OpenWrt source path -# Clone this repo -git clone -b master --single-branch https://github.com/LGA1150/openwrt-fullconenat package/fullconenat -# Select Network -> Firewall -> iptables-mod-fullconenat -make menuconfig -# Compile -make V=s -``` - -Usage ---- -You can apply [this patch](https://github.com/LGA1150/fullconenat-fw3-patch) to OpenWrt's Firewall3 (Recommended). - -Or manually add the following rules to `/etc/firewall.user` -``` -iptables -t nat -A zone_wan_prerouting -j FULLCONENAT -iptables -t nat -A zone_wan_postrouting -j FULLCONENAT -``` - -Workaround for conflicting with module `nf_conntrack_netlink` ---- -This module uses conntrack events to register a callback function. In the same netns, only one callback method can be registered, that causes conflicts with `nf_conntrack_netlink`, which also uses conntrack events. Qualcomm Shortcut FE has introduced a patch to allow multiple callbacks to be registered. To apply, put [this patch](https://github.com/coolsnowwolf/lede/blob/master/target/linux/generic/hack-4.14/952-net-conntrack-events-support-multiple-registrant.patch) into `target/linux/generic/hack-4.14`. diff --git a/iptables-mod-fullconenat/files/Makefile b/iptables-mod-fullconenat/files/Makefile deleted file mode 100644 index da52a2a4e..000000000 --- a/iptables-mod-fullconenat/files/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -libipt_FULLCONENAT.so: libipt_FULLCONENAT.o - $(CC) -shared -lxtables -o $@ $^; -libipt_FULLCONENAT.o: libipt_FULLCONENAT.c - $(CC) ${CFLAGS} -fPIC -D_INIT=$*_init -c -o $@ $<; - -obj-m += xt_FULLCONENAT.o - diff --git a/iptables-mod-fullconenat/patches/000-printk.patch b/iptables-mod-fullconenat/patches/000-printk.patch deleted file mode 100644 index 4e764c5d6..000000000 --- a/iptables-mod-fullconenat/patches/000-printk.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/xt_FULLCONENAT.c b/xt_FULLCONENAT.c -index 9e52eba..8658c5f 100644 ---- a/xt_FULLCONENAT.c -+++ b/xt_FULLCONENAT.c -@@ -702,9 +702,11 @@ static struct xt_target tg_reg[] __read_mostly = { - - static int __init fullconenat_tg_init(void) - { -+ printk(KERN_INFO "xt_FULLCONENAT: RFC3489 Full Cone NAT module\n" -+ "xt_FULLCONENAT: Copyright (C) 2018 Chion Tang \n"); - wq = create_singlethread_workqueue("xt_FULLCONENAT"); - if (wq == NULL) { -- printk("xt_FULLCONENAT: warning: failed to create workqueue\n"); -+ printk(KERN_WARNING "xt_FULLCONENAT: warning: failed to create workqueue\n"); - } - - return xt_register_targets(tg_reg, ARRAY_SIZE(tg_reg)); From 7b1f07935b4ef1eb9f19a4f6026aaf6ebc37348b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 30 Nov 2021 17:45:08 +0100 Subject: [PATCH 0630/2059] Make sure ip doesn't have subnet --- mptcp/files/etc/init.d/mptcp | 1 + 1 file changed, 1 insertion(+) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 7dd629733..383650953 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -213,6 +213,7 @@ interface_multipath_settings() { [ -n "$netmask" ] && [ "$(echo $netmask | grep '/')" != "" ] && netmask="" [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep peer | awk '{print $4}' | cut -d/ -f2 | tr -d "\n") [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + [ -n "$ipaddr" ] && ipaddr=$(echo $ipaddr | cut -d/ -f1 | tr -d "\n") [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr $netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi From a64df3c0745bcd7980e36a2f1b37b49198865641 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 30 Nov 2021 17:45:26 +0100 Subject: [PATCH 0631/2059] Increase log in post-tracking --- .../files/usr/share/omr/post-tracking.d/post-tracking | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 4e2e52212..964d78ea5 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -597,7 +597,7 @@ del_server_route() { remove_route() { local serverip="$1" [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" - [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + [ -n "$serverip" ] && _log "Delete default route to $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" local metric metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) [ -n "$metric" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 @@ -617,11 +617,11 @@ del_server_route6() { remove_route() { local serverip="$1" [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" - [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" + [ -n "$serverip" ] && _log "Delete default route to $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" local metric metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 - [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip"] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 } config_list_foreach $server ip remove_route if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then @@ -836,11 +836,13 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om fi if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Current route: $(ip r)" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null if [ "$(pgrep openmptcprouter-vps)" = "" ]; then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 fi [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New route: $(ip r)" fi # Set VPN MTU From 2e6ddfb810273f8ca8c020e8dbd130a530dc4507 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 30 Nov 2021 17:45:43 +0100 Subject: [PATCH 0632/2059] Compile for 5.15 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8345ecf8b..ab824216b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800] - OMR_KERNEL: [5.4, 5.14] + OMR_KERNEL: [5.4, 5.15] runs-on: ubuntu-latest continue-on-error: true From 0121c6c4ce37424647c4934bd4731d009c3198ce Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 6 Dec 2021 19:36:33 +0100 Subject: [PATCH 0633/2059] Add more log and small changes --- .../usr/share/omr/post-tracking.d/post-tracking | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 964d78ea5..76770b61c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -53,7 +53,8 @@ set_route() { interface_gw=$(ubus call network.interface.${INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") fi if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" = "yes" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" != "yes" ] && _log "$PREVINTERFACE down. Replace default in table 991337 route by $interface_gw dev $interface_if" [ "$SETDEFAULT" = "yes" ] && ip route replace default scope global nexthop via $interface_gw dev $interface_if 2>&1 >/dev/null ip route replace default via $interface_gw dev $interface_if table 991337 2>&1 >/dev/null && SETROUTE=true fi @@ -727,15 +728,19 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then config_foreach del_server_route6 server #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set balancing route (current: $(ip r) )" config_foreach set_server_all_routes server config_foreach set_server_all_routes6 server + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set balancing route done (new: $(ip r) )" fi fi if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw: $default_gw - Set routes (current: $(ip r) )" config_load network config_foreach set_route interface $OMR_TRACKER_INTERFACE config_foreach set_route6 interface $OMR_TRACKER_INTERFACE + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New routes $(ip r)" elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then config_load network config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" @@ -940,7 +945,7 @@ if [ "$multipath_config" = "master" ]; then if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") - if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null fi @@ -970,7 +975,7 @@ if [ "$multipath_config" = "master" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") - if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then + if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then routesbalancing="" routesbalancingbackup="" nbintf=0 @@ -982,7 +987,7 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { - _log "Set ip route replace default scope global $routesbalancing" + _log "Change in routes, set ip route replace default scope global $routesbalancing (omrvpn_intf: $omrvpn_intf)" ip route replace default scope global metric 1 $routesbalancing 2>&1 >/dev/null } } @@ -994,7 +999,7 @@ if [ "$multipath_config" = "master" ]; then } [ -n "$routesbalancingbackup" ] && { ([ "$nbintfb" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { - _log "Set backup ip route replace default scope global $routesbalancingbackup" + _log "Set backup ip route replace default scope global metric 999 $routesbalancingbackup" ip route replace default scope global metric 999 $routesbalancingbackup 2>&1 >/dev/null } } @@ -1027,6 +1032,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then config_foreach set_server_route server fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + _log "Interface route not yet set, set route ip r replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" ip r replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi fi From 0ab2a14842579d142ff2e6255b6c1c51a66bdf26 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 10 Dec 2021 21:16:48 +0100 Subject: [PATCH 0634/2059] Fix set route too often --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 76770b61c..436dbfc3c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -454,7 +454,7 @@ set_server_all_routes() { config_foreach set_routes_intf interface uintf="$(echo $routesintf | awk '{print $5}')" uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 1 | grep $uintf)" = "" ]); then + if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 1 | tr -d '\t' | sort | tr -d '\n' | sed 's/ *$//')" != "$(echo $serverip $routesintf | sort | sed 's/ *$//')" ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 1 | grep $uintf)" = "" ]); then while [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip r del $serverip done @@ -500,7 +500,7 @@ set_server_all_routes6() { config_foreach set_routes_intf6 interface uintf="$(echo $routesintf6 | awk '{print $5}')" uintfb="$(echo $routesintfbackup6 | awk '{print $5}')" - if [ -n "$routesintf6" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf6 " ]) || ([ "$nbintf6" = "1" ] && [ -n "$uintf" ] && [ "$(ip -6 r show $serverip metric 1 | grep $uintf)" = "" ]); then + if [ -n "$routesintf6" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 1 | tr -d '\t' | sort | tr -d '\n' | sed 's/ *$//')" != "$(echo $serverip $routesintf6 | sort | sed 's/ *$//')" ]) || ([ "$nbintf6" = "1" ] && [ -n "$uintf" ] && [ "$(ip -6 r show $serverip metric 1 | grep $uintf)" = "" ]); then while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip -6 r del $serverip done @@ -988,7 +988,9 @@ if [ "$multipath_config" = "master" ]; then [ -n "$routesbalancing" ] && { ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Change in routes, set ip route replace default scope global $routesbalancing (omrvpn_intf: $omrvpn_intf)" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Current route: $(ip r)" ip route replace default scope global metric 1 $routesbalancing 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New route: $(ip r)" } } [ -n "$routesbalancing6" ] && { From aa159e62e4f6988b07e3023ccfeba0d5f677363a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 10 Dec 2021 21:17:13 +0100 Subject: [PATCH 0635/2059] Fix when host have more than 10 cores --- openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks index f47a4200c..7ddcc4e57 100755 --- a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks +++ b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks @@ -53,6 +53,7 @@ fi if [ "$(uci -q get shadowsocks-libev.hi3)" != "" ]; then port=1100 + [ "$NBCPU" -gt "10" ] && NBCPU=10 for c in $(seq 1 2 $NBCPU); do uci -q batch <<-EOF >/dev/null set shadowsocks-libev.hi$c.local_port=$port From 38927997e21ac0e8eb22429a150b015541305b42 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 11 Dec 2021 08:42:35 +0100 Subject: [PATCH 0636/2059] Update go --- golang/golang/Makefile | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 1c311d571..30979fe7c 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk GO_VERSION_MAJOR_MINOR:=1.17 -GO_VERSION_PATCH:=2 +GO_VERSION_PATCH:=3 PKG_NAME:=golang PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=2255eb3e4e824dd7d5fcdc2e7f84534371c186312e546fb1086a34c17752f431 +PKG_HASH:=705c64251e5b25d5d55ede1039c6aa22bea40a7a931d14c370339853643c3df0 PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause @@ -48,12 +48,13 @@ HOST_GO_VALID_OS_ARCH:= \ freebsd_386 freebsd_amd64 freebsd_arm freebsd_arm64 \ linux_386 linux_amd64 linux_arm linux_arm64 \ openbsd_386 openbsd_amd64 openbsd_arm openbsd_arm64 \ + netbsd_386 netbsd_amd64 netbsd_arm netbsd_arm64 \ + windows_386 windows_amd64 windows_arm windows_arm64 \ \ - netbsd_386 netbsd_amd64 netbsd_arm \ plan9_386 plan9_amd64 plan9_arm \ - windows_386 windows_amd64 windows_arm \ \ darwin_amd64 darwin_arm64 \ + ios_amd64 ios_arm64 \ \ dragonfly_amd64 \ illumos_amd64 \ @@ -64,7 +65,9 @@ HOST_GO_VALID_OS_ARCH:= \ \ linux_ppc64 linux_ppc64le \ linux_mips linux_mipsle linux_mips64 linux_mips64le \ - linux_riscv64 linux_s390x + linux_riscv64 linux_s390x \ + \ + openbsd_mips64 BOOTSTRAP_SOURCE:=go1.4-bootstrap-20171003.tar.gz BOOTSTRAP_SOURCE_URL:=$(GO_SOURCE_URLS) @@ -258,12 +261,14 @@ endif $(eval $(call GoCompiler/AddProfile,Package,$(PKG_BUILD_DIR),$(PKG_GO_PREFIX),$(PKG_GO_VERSION_ID),$(GO_OS_ARCH),$(PKG_GO_INSTALL_SUFFIX))) PKG_GO_ZBOOTSTRAP_MODS:= \ - s/defaultGO386 = `[^`]*`/defaultGO386 = `$(or $(GO_386),387)`/; \ + s/defaultGO386 = `[^`]*`/defaultGO386 = `$(or $(GO_386),sse2)`/; \ s/defaultGOARM = `[^`]*`/defaultGOARM = `$(or $(GO_ARM),5)`/; \ s/defaultGOMIPS = `[^`]*`/defaultGOMIPS = `$(or $(GO_MIPS),hardfloat)`/; \ s/defaultGOMIPS64 = `[^`]*`/defaultGOMIPS64 = `$(or $(GO_MIPS64),hardfloat)`/; \ s/defaultGOPPC64 = `[^`]*`/defaultGOPPC64 = `power8`/; +PKG_GO_ZBOOTSTRAP_PATH:=$(PKG_BUILD_DIR)/src/internal/buildcfg/zbootstrap.go + PKG_GO_VARS= \ GOCACHE="$(GO_BUILD_CACHE_DIR)" \ GOENV=off \ @@ -306,8 +311,17 @@ define Build/Compile $(PKG_GO_VARS) \ ) - $(SED) '$(PKG_GO_ZBOOTSTRAP_MODS)' \ - "$(PKG_BUILD_DIR)/src/cmd/internal/objabi/zbootstrap.go" + $(SED) '$(PKG_GO_ZBOOTSTRAP_MODS)' "$(PKG_GO_ZBOOTSTRAP_PATH)" + + ( \ + if echo 'int main() { return 0; }' | $(TARGET_CC) -o $(PKG_BUILD_DIR)/test-ldso -x c - > /dev/null 2>&1; then \ + LDSO=$$$$( \ + readelf -l $(PKG_BUILD_DIR)/test-ldso | \ + sed -n -e 's/^.*interpreter: \(.*\)[]]/\1/p' \ + ) ; \ + fi ; \ + $(SED) "s,defaultGO_LDSO = \`[^\`]*\`,defaultGO_LDSO = \`$$$$LDSO\`," "$(PKG_GO_ZBOOTSTRAP_PATH)" ; \ + ) @echo "Building target Go second stage" From 54d696e593c941da20560f40af937fbbba08934b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 16 Dec 2021 21:27:49 +0100 Subject: [PATCH 0637/2059] Fix compilation using GO --- golang/golang-values.mk | 42 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/golang/golang-values.mk b/golang/golang-values.mk index 69126a1ed..34c9c1c65 100644 --- a/golang/golang-values.mk +++ b/golang/golang-values.mk @@ -13,10 +13,11 @@ endif # Unset environment variables # There are more magic variables to track down, but ain't nobody got time for that -# From https://golang.org/cmd/go/#hdr-Environment_variables +# From https://pkg.go.dev/cmd/go#hdr-Environment_variables # General-purpose environment variables: unexport \ + GO111MODULE \ GCCGO \ GOARCH \ GOBIN \ @@ -36,6 +37,7 @@ unexport \ # GONOPROXY # GOSUMDB # GONOSUMDB +# GOVCS # Environment variables for use with cgo: unexport \ @@ -63,23 +65,20 @@ unexport \ # Special-purpose environment variables: unexport \ GCCGOTOOLDIR \ + GOEXPERIMENT \ GOROOT_FINAL \ GO_EXTLINK_ENABLED # Unmodified: # GIT_ALLOW_PROTOCOL -# From https://golang.org/cmd/go/#hdr-Module_support -unexport \ - GO111MODULE - -# From https://golang.org/pkg/runtime/#hdr-Environment_Variables +# From https://pkg.go.dev/runtime#hdr-Environment_Variables unexport \ GOGC \ GOMAXPROCS \ GORACE \ GOTRACEBACK -# From https://golang.org/cmd/cgo/#hdr-Using_cgo_with_the_go_command +# From https://pkg.go.dev/cmd/cgo#hdr-Using_cgo_with_the_go_command unexport \ CC_FOR_TARGET \ CXX_FOR_TARGET @@ -111,10 +110,6 @@ unexport \ BOOT_GO_GCFLAGS \ BOOT_GO_LDFLAGS -# From https://golang.org/src/cmd/dist/buildruntime.go -unexport \ - GOEXPERIMENT - # From https://golang.org/src/cmd/dist/buildtool.go unexport \ GOBOOTSTRAP_TOOLEXEC @@ -148,8 +143,11 @@ else endif ifeq ($(GO_ARCH),386) - # ensure binaries can run on older CPUs - GO_386:=387 + ifeq ($(CONFIG_TARGET_x86_geode)$(CONFIG_TARGET_x86_legacy),y) + GO_386:=softfloat + else + GO_386:=sse2 + endif # -fno-plt: causes "unexpected GOT reloc for non-dynamic symbol" errors GO_CFLAGS_TO_REMOVE:=-fno-plt @@ -195,19 +193,23 @@ GO_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mips64||mips64el||mipsel||pow # ASLR/PIE +# From https://golang.org/src/cmd/internal/sys/supported.go GO_PIE_SUPPORTED_OS_ARCH:= \ - android_386 android_amd64 android_arm android_arm64 \ - linux_386 linux_amd64 linux_arm linux_arm64 \ + android_386 android_amd64 android_arm android_arm64 \ + linux_386 linux_amd64 linux_arm linux_arm64 \ \ - windows_386 windows_amd64 windows_arm \ + windows_386 windows_amd64 windows_arm \ + \ + darwin_amd64 darwin_arm64 \ + ios_amd64 ios_arm64 \ \ - darwin_amd64 \ freebsd_amd64 \ \ aix_ppc64 \ \ - linux_ppc64le linux_s390x + linux_ppc64le linux_riscv64 linux_s390x +# From https://golang.org/src/cmd/go/internal/work/init.go go_pie_install_suffix=$(if $(filter $(1),aix_ppc64 windows_386 windows_amd64 windows_arm),,shared) ifneq ($(filter $(GO_HOST_OS_ARCH),$(GO_PIE_SUPPORTED_OS_ARCH)),) @@ -236,7 +238,7 @@ endif # General build info -GO_BUILD_CACHE_DIR:=$(or $(call qstrip,$(CONFIG_GOLANG_BUILD_CACHE_DIR)),$(TOPDIR)/.go-build) +GO_BUILD_CACHE_DIR:=$(or $(call qstrip,$(CONFIG_GOLANG_BUILD_CACHE_DIR)),$(TMP_DIR)/go-build) GO_MOD_CACHE_DIR:=$(DL_DIR)/go-mod-cache GO_MOD_ARGS= \ @@ -249,6 +251,6 @@ GO_GENERAL_BUILD_CONFIG_VARS= \ GO_MOD_ARGS="$(GO_MOD_ARGS)" define Go/CacheCleanup - $(GENERAL_BUILD_CONFIG_VARS) \ + $(GO_GENERAL_BUILD_CONFIG_VARS) \ $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh cache_cleanup endef From 278baea272b79a013649510de01522bbac9d5ec8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 20 Dec 2021 19:41:28 +0100 Subject: [PATCH 0638/2059] Little changes on mptcp v6 routes --- mptcp/files/etc/init.d/mptcp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 383650953..dbaf7f01b 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -316,7 +316,7 @@ interface_multipath_settings() { [ -n "$(ip -6 rule list | grep 6$id)" ] && ip -6 rule del table 6$id > /dev/null 2>&1 ip -6 route flush 6$id > /dev/null 2>&1 fi - if [ -n "$ip6addr" ] && [ -n "$gateway6" ] && [ -n "$network6" ]; then + if [ -n "$gateway6" ] && [ -n "$network6" ]; then if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null delete network.${config}_rule6 @@ -341,12 +341,12 @@ interface_multipath_settings() { commit network EOF else - ip -6 rule add from $ip6addr table 6$id pref 0 2>&1 >/dev/null + [ -n "$ip6addr" ] && ip -6 rule add from $ip6addr table 6$id pref 0 2>&1 >/dev/null ip -6 route replace $network6/$netmask6 dev $iface scope link metric 6$id 2>&1 >/dev/null ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface table 6$id 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface metric 6$id 2>&1 >/dev/null - ip -6 route flush 6$id 2>&1 >/dev/null + #ip -6 route flush 6$id 2>&1 >/dev/null fi #config_get mode "$config" multipath "off" From 63457ef662c625b78bfac3fa39ee70efb02d78f8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 20 Dec 2021 20:34:02 +0100 Subject: [PATCH 0639/2059] Get IPv6 when not static --- mptcp/files/etc/init.d/mptcp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index dbaf7f01b..140db96f9 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -290,20 +290,20 @@ interface_multipath_settings() { ip6addr=`echo $ip6addr | cut -d/ -f1` netmask6=`ipcalc $ipaddr6 | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` - if [ -z "$ip6addr" ] || [ -z "$network6" ]; then - ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") - gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") - [ -z "$gateway6" ] && gateway6=$(uci -q get "network.$config.ip6gw") - [ -z "$gateway6" ] && gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") - if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then - gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") - fi - if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then - gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") - fi - netmask6=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") - network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + fi + if [ -z "$ip6addr" ] || [ -z "$network6" ]; then + ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") + gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") + [ -z "$gateway6" ] && gateway6=$(uci -q get "network.$config.ip6gw") + [ -z "$gateway6" ] && gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then + gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") fi + if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then + gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + netmask6=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null From 6725ab4c45237367442bd0ef9d027ce9066f518a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 26 Dec 2021 18:41:14 +0100 Subject: [PATCH 0640/2059] Remove some false errors --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 2 +- luci-app-omr-dscp/root/etc/init.d/omr-dscp | 4 ++-- openmptcprouter/files/etc/uci-defaults/2090-omr-wwan | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index ed267449d..57d81c923 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -539,7 +539,7 @@ _intf_rule() { EOF else ip rule add prio 1 fwmark 0x539$count lookup $count pref 1 > /dev/null 2>&1 - ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count > /dev/null 2>&1 + ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count pref 1 > /dev/null 2>&1 fi } if [ "$(iptables-save | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then diff --git a/luci-app-omr-dscp/root/etc/init.d/omr-dscp b/luci-app-omr-dscp/root/etc/init.d/omr-dscp index 9ea0d661f..4997e1cbc 100755 --- a/luci-app-omr-dscp/root/etc/init.d/omr-dscp +++ b/luci-app-omr-dscp/root/etc/init.d/omr-dscp @@ -19,10 +19,10 @@ config_get lan_device lan ifname config_load dscp _ipt4() { - iptables -w -t mangle "$@" + iptables -w -t mangle "$@" 2>&1 >/dev/null } _ipt6() { - ip6tables -w -t mangle "$@" + ip6tables -w -t mangle "$@" >/dev/null } _add_dscp_rule() { diff --git a/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan b/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan index 42d8f2555..cab4295ea 100755 --- a/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan +++ b/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan @@ -4,9 +4,9 @@ if [ "$(grep usbmode /etc/rc.local)" = "" ]; then sed -i 's:exit 0::g' /etc/rc.local cat <<-EOF >> /etc/rc.local /bin/sleep 5 - /sbin/usbmode -l + /sbin/usbmode -l 2>&1 /dev/null /bin/sleep 3 - /sbin/usbmode -s + /sbin/usbmode -s 2>&1 /dev/null exit 0 EOF fi From 46efae0eabaf38f5dc0de40a94d762be2994769f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 26 Dec 2021 18:41:29 +0100 Subject: [PATCH 0641/2059] Fix for wrt update --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 902dae6dc..dd68fb82c 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -24,5 +24,11 @@ fi uci -q set openmptcprouter.settings.scaling_governor='performance' uci -q commit openmptcprouter } +[ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep wrt)" ] && [ "$(uci -q get system.@system[0].compat_version)" == "" ] && { + uci -q batch <<-EOF >/dev/null + set system.@system[-1].compat_version='1.1' + commit system + EOF +} exit 0 \ No newline at end of file From d9b5b9991cd4f10656c05c1e57a0a2b95a28ad81 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 3 Jan 2022 20:25:25 +0100 Subject: [PATCH 0642/2059] Line break --- glorytun/init | 1 + 1 file changed, 1 insertion(+) diff --git a/glorytun/init b/glorytun/init index 3d549f0aa..1384a0315 100755 --- a/glorytun/init +++ b/glorytun/init @@ -62,6 +62,7 @@ start_instance() { uci -q set network.omrvpn.device=${dev} uci -q commit network fi + _log "starting ${PROG_NAME} ${1} instance $*" procd_open_instance From 4a33826a28c62c9dc8cd372c368888f8df0f2868 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 4 Jan 2022 09:05:50 +0100 Subject: [PATCH 0643/2059] Add r8125 driver --- r8125/Makefile | 45 + r8125/src/Makefile | 197 + r8125/src/Makefile_linux24x | 75 + r8125/src/r8125.h | 2508 ++++++ r8125/src/r8125_dash.h | 261 + r8125/src/r8125_firmware.c | 264 + r8125/src/r8125_firmware.h | 68 + r8125/src/r8125_n.c | 15150 ++++++++++++++++++++++++++++++++++ r8125/src/r8125_ptp.c | 594 ++ r8125/src/r8125_ptp.h | 81 + r8125/src/r8125_realwow.h | 118 + r8125/src/r8125_rss.c | 481 ++ r8125/src/r8125_rss.h | 69 + r8125/src/rtl_eeprom.c | 289 + r8125/src/rtl_eeprom.h | 53 + r8125/src/rtltool.c | 320 + r8125/src/rtltool.h | 86 + 17 files changed, 20659 insertions(+) create mode 100644 r8125/Makefile create mode 100755 r8125/src/Makefile create mode 100755 r8125/src/Makefile_linux24x create mode 100755 r8125/src/r8125.h create mode 100755 r8125/src/r8125_dash.h create mode 100755 r8125/src/r8125_firmware.c create mode 100755 r8125/src/r8125_firmware.h create mode 100755 r8125/src/r8125_n.c create mode 100755 r8125/src/r8125_ptp.c create mode 100755 r8125/src/r8125_ptp.h create mode 100755 r8125/src/r8125_realwow.h create mode 100755 r8125/src/r8125_rss.c create mode 100755 r8125/src/r8125_rss.h create mode 100755 r8125/src/rtl_eeprom.c create mode 100755 r8125/src/rtl_eeprom.h create mode 100755 r8125/src/rtltool.c create mode 100755 r8125/src/rtltool.h diff --git a/r8125/Makefile b/r8125/Makefile new file mode 100644 index 000000000..e9b213c6e --- /dev/null +++ b/r8125/Makefile @@ -0,0 +1,45 @@ +# Attribution: https://gist.github.com/lenew/9b41ba901c3393047ede0766760f9d55 + +#Put this source to 'package/lean/r8125' folder of OpenWRT/LEDE SDK +#Build(make menuconfig, make defconfig, make) + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=r8125 +PKG_VERSION:=9.006.04 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/r8125 + TITLE:=Driver for Realtek r8125 chipsets + SUBMENU:=Network Devices + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + FILES:= $(PKG_BUILD_DIR)/r8125.ko + AUTOLOAD:=$(call AutoProbe,r8125) +endef + +define Package/r8125/description + This package contains a driver for Realtek r8125 chipsets. +endef + +R8125_MAKEOPTS= -C $(PKG_BUILD_DIR) \ + PATH="$(TARGET_PATH)" \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + TARGET="$(HAL_TARGET)" \ + TOOLPREFIX="$(KERNEL_CROSS)" \ + TOOLPATH="$(KERNEL_CROSS)" \ + KERNELPATH="$(LINUX_DIR)" \ + KERNELDIR="$(LINUX_DIR)" \ + LDOPTS=" " \ + DOMULTI=1 + +define Build/Compile + $(MAKE) $(R8125_MAKEOPTS) modules +endef + +$(eval $(call KernelPackage,r8125)) diff --git a/r8125/src/Makefile b/r8125/src/Makefile new file mode 100755 index 000000000..514c0acdd --- /dev/null +++ b/r8125/src/Makefile @@ -0,0 +1,197 @@ +# SPDX-License-Identifier: GPL-2.0-only +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ + +################################################################################ +# This product is covered by one or more of the following patents: +# US6,570,884, US6,115,776, and US6,327,625. +################################################################################ + +CONFIG_SOC_LAN = n +ENABLE_REALWOW_SUPPORT = n +ENABLE_DASH_SUPPORT = n +ENABLE_DASH_PRINTER_SUPPORT = n +CONFIG_DOWN_SPEED_100 = n +CONFIG_ASPM = y +ENABLE_S5WOL = y +ENABLE_S5_KEEP_CURR_MAC = n +ENABLE_EEE = y +ENABLE_S0_MAGIC_PACKET = n +ENABLE_TX_NO_CLOSE = y +ENABLE_MULTIPLE_TX_QUEUE = n +ENABLE_PTP_SUPPORT = n +ENABLE_PTP_MASTER_MODE = n +ENABLE_RSS_SUPPORT = y +ENABLE_LIB_SUPPORT = n +ENABLE_USE_FIRMWARE_FILE = n +DISABLE_PM_SUPPORT = n +DISABLE_MULTI_MSIX_VECTOR = n + +ifneq ($(KERNELRELEASE),) + obj-m := r8125.o + r8125-objs := r8125_n.o rtl_eeprom.o rtltool.o + ifeq ($(CONFIG_SOC_LAN), y) + EXTRA_CFLAGS += -DCONFIG_SOC_LAN + endif + ifeq ($(ENABLE_REALWOW_SUPPORT), y) + r8125-objs += r8125_realwow.o + EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT + endif + ifeq ($(ENABLE_DASH_SUPPORT), y) + r8125-objs += r8125_dash.o + EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT + endif + ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) + r8125-objs += r8125_dash.o + EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT + endif + EXTRA_CFLAGS += -DCONFIG_R8125_NAPI + EXTRA_CFLAGS += -DCONFIG_R8125_VLAN + ifeq ($(CONFIG_DOWN_SPEED_100), y) + EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 + endif + ifeq ($(CONFIG_ASPM), y) + EXTRA_CFLAGS += -DCONFIG_ASPM + endif + ifeq ($(ENABLE_S5WOL), y) + EXTRA_CFLAGS += -DENABLE_S5WOL + endif + ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) + EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC + endif + ifeq ($(ENABLE_EEE), y) + EXTRA_CFLAGS += -DENABLE_EEE + endif + ifeq ($(ENABLE_S0_MAGIC_PACKET), y) + EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET + endif + ifeq ($(ENABLE_TX_NO_CLOSE), y) + EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE + endif + ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y) + EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE + endif + ifeq ($(ENABLE_PTP_SUPPORT), y) + r8125-objs += r8125_ptp.o + EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT + endif + ifeq ($(ENABLE_PTP_MASTER_MODE), y) + EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE + endif + ifeq ($(ENABLE_RSS_SUPPORT), y) + r8125-objs += r8125_rss.o + EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT + endif + ifeq ($(ENABLE_LIB_SUPPORT), y) + r8125-objs += r8125_lib.o + EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT + endif + ifeq ($(ENABLE_USE_FIRMWARE_FILE), y) + r8125-objs += r8125_firmware.o + EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE + endif + ifeq ($(DISABLE_PM_SUPPORT), y) + EXTRA_CFLAGS += -DDISABLE_PM_SUPPORT + endif + ifeq ($(DISABLE_MULTI_MSIX_VECTOR), y) + EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR + endif +else + BASEDIR := /lib/modules/$(shell uname -r) + KERNELDIR ?= $(BASEDIR)/build + PWD :=$(shell pwd) + DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net/ethernet -name realtek -type d) + ifeq ($(DRIVERDIR),) + DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net -name realtek -type d) + endif + ifeq ($(DRIVERDIR),) + DRIVERDIR := $(BASEDIR)/kernel/drivers/net + endif + RTKDIR := $(subst $(BASEDIR)/,,$(DRIVERDIR)) + + KERNEL_GCC_VERSION := $(shell cat /proc/version | sed -n 's/.*gcc version \([[:digit:]]\.[[:digit:]]\.[[:digit:]]\).*/\1/p') + CCVERSION = $(shell $(CC) -dumpversion) + + KVER = $(shell uname -r) + KMAJ = $(shell echo $(KVER) | \ + sed -e 's/^\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*.*/\1/') + KMIN = $(shell echo $(KVER) | \ + sed -e 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*.*/\1/') + KREV = $(shell echo $(KVER) | \ + sed -e 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/') + + kver_ge = $(shell \ + echo test | awk '{if($(KMAJ) < $(1)) {print 0} else { \ + if($(KMAJ) > $(1)) {print 1} else { \ + if($(KMIN) < $(2)) {print 0} else { \ + if($(KMIN) > $(2)) {print 1} else { \ + if($(KREV) < $(3)) {print 0} else { print 1 } \ + }}}}}' \ + ) + +.PHONY: all +all: print_vars clean modules install + +print_vars: + @echo + @echo "CC: " $(CC) + @echo "CCVERSION: " $(CCVERSION) + @echo "KERNEL_GCC_VERSION: " $(KERNEL_GCC_VERSION) + @echo "KVER: " $(KVER) + @echo "KMAJ: " $(KMAJ) + @echo "KMIN: " $(KMIN) + @echo "KREV: " $(KREV) + @echo "BASEDIR: " $(BASEDIR) + @echo "DRIVERDIR: " $(DRIVERDIR) + @echo "PWD: " $(PWD) + @echo "RTKDIR: " $(RTKDIR) + @echo + +.PHONY:modules +modules: +#ifeq ($(call kver_ge,5,0,0),1) + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +#else +# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules +#endif + +.PHONY:clean +clean: +#ifeq ($(call kver_ge,5,0,0),1) + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean +#else +# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean +#endif + +.PHONY:install +install: +#ifeq ($(call kver_ge,5,0,0),1) + $(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install +#else +# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install +#endif + +endif diff --git a/r8125/src/Makefile_linux24x b/r8125/src/Makefile_linux24x new file mode 100755 index 000000000..d043fb00c --- /dev/null +++ b/r8125/src/Makefile_linux24x @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0-only +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ + +################################################################################ +# This product is covered by one or more of the following patents: +# US6,570,884, US6,115,776, and US6,327,625. +################################################################################ + +CC := gcc +LD := ld +ARCH := $(shell uname -m | sed 's/i.86/i386/') +KSRC := /lib/modules/$(shell uname -r)/build +CONFIG_FILE := $(KSRC)/include/linux/autoconf.h +KMISC := /lib/modules/$(shell uname -r)/kernel/drivers/net/ + + +ifeq ($(ARCH),x86_64) + MODCFLAGS += -mcmodel=kernel -mno-red-zone +endif + +#standard flags for module builds +MODCFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +MODCFLAGS += -I$(KSRC)/include -I. +MODCFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h +SOURCE := r8125_n.c rtl_eeprom.c rtltool.c +OBJS := $(SOURCE:.c=.o) + + +SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \ + grep CONFIG_SMP | awk '{print $$3}') + +ifneq ($(SMP),1) + SMP := 0 +endif + +ifeq ($(SMP),1) + MODCFLAGS += -D__SMP__ +endif + +modules: $(OBJS) + $(LD) -r $^ -o r8125.o + strip --strip-debug r8125.o + +%.o: %.c + $(CC) $(MODCFLAGS) -c $< -o $@ + +clean: + rm *.o -f + +install: + install -m 744 -c r8125.o $(KMISC) diff --git a/r8125/src/r8125.h b/r8125/src/r8125.h new file mode 100755 index 000000000..4875ccca4 --- /dev/null +++ b/r8125/src/r8125.h @@ -0,0 +1,2508 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef __R8125_H +#define __R8125_H + +//#include +#include +#include +#include +#include "r8125_dash.h" +#include "r8125_realwow.h" +#include "r8125_ptp.h" +#include "r8125_rss.h" +#ifdef ENABLE_LIB_SUPPORT +#include "r8125_lib.h" +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) +typedef int netdev_tx_t; +#endif + +/* +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)&& !defined(ENABLE_LIB_SUPPORT) +#define RTL_USE_NEW_INTR_API +#endif +*/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +#define skb_transport_offset(skb) (skb->h.raw - skb->data) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +#define device_set_wakeup_enable(dev, val) do {} while (0) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) +static inline void ether_addr_copy(u8 *dst, const u8 *src) +{ + u16 *a = (u16 *)dst; + const u16 *b = (const u16 *)src; + + a[0] = b[0]; + a[1] = b[1]; + a[2] = b[2]; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) +#define IS_ERR_OR_NULL(ptr) (!ptr) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) +#define reinit_completion(x) ((x)->done = 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#define pm_runtime_mark_last_busy(x) +#define pm_runtime_put_autosuspend(x) pm_runtime_put(x) +#define pm_runtime_put_sync_autosuspend(x) pm_runtime_put_sync(x) + +static inline bool pm_runtime_suspended(struct device *dev) +{ + return dev->power.runtime_status == RPM_SUSPENDED + && !dev->power.disable_depth; +} + +static inline bool pm_runtime_active(struct device *dev) +{ + return dev->power.runtime_status == RPM_ACTIVE + || dev->power.disable_depth; +} +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +#define queue_delayed_work(long_wq, work, delay) schedule_delayed_work(work, delay) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) +#define netif_printk(priv, type, level, netdev, fmt, args...) \ + do { \ + if (netif_msg_##type(priv)) \ + printk(level "%s: " fmt,(netdev)->name , ##args); \ + } while (0) + +#define netif_emerg(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_EMERG, netdev, fmt, ##args) +#define netif_alert(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_ALERT, netdev, fmt, ##args) +#define netif_crit(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_CRIT, netdev, fmt, ##args) +#define netif_err(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_ERR, netdev, fmt, ##args) +#define netif_warn(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_WARNING, netdev, fmt, ##args) +#define netif_notice(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_NOTICE, netdev, fmt, ##args) +#define netif_info(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_INFO, (netdev), fmt, ##args) +#endif +#endif +#endif +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +#define setup_timer(_timer, _function, _data) \ +do { \ + (_timer)->function = _function; \ + (_timer)->data = _data; \ + init_timer(_timer); \ +} while (0) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) +#if defined(skb_vlan_tag_present) && !defined(vlan_tx_tag_present) +#define vlan_tx_tag_present skb_vlan_tag_present +#endif +#if defined(skb_vlan_tag_get) && !defined(vlan_tx_tag_get) +#define vlan_tx_tag_get skb_vlan_tag_get +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) + +#define RTL_ALLOC_SKB_INTR(napi, length) dev_alloc_skb(length) +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) +#undef RTL_ALLOC_SKB_INTR +#define RTL_ALLOC_SKB_INTR(napi, length) napi_alloc_skb(napi, length) +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) +#define netdev_features_t u32 +#endif +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) +#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK +#else +#ifndef NETIF_F_ALL_CSUM +#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK +#endif +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) +#define ENABLE_R8125_PROCFS +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX +#define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +#define __devinit +#define __devexit +#define __devexit_p(func) func +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +#define CHECKSUM_PARTIAL CHECKSUM_HW +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#define irqreturn_t void +#define IRQ_HANDLED 1 +#define IRQ_NONE 0 +#define IRQ_RETVAL(x) +#endif + +#ifndef NETIF_F_RXALL +#define NETIF_F_RXALL 0 +#endif + +#ifndef NETIF_F_RXFCS +#define NETIF_F_RXFCS 0 +#endif + +#ifndef HAVE_FREE_NETDEV +#define free_netdev(x) kfree(x) +#endif + +#ifndef SET_NETDEV_DEV +#define SET_NETDEV_DEV(net, pdev) +#endif + +#ifndef SET_MODULE_OWNER +#define SET_MODULE_OWNER(dev) +#endif + +#ifndef SA_SHIRQ +#define SA_SHIRQ IRQF_SHARED +#endif + +#ifndef NETIF_F_GSO +#define gso_size tso_size +#define gso_segs tso_segs +#endif + +#ifndef PCI_VENDOR_ID_DLINK +#define PCI_VENDOR_ID_DLINK 0x1186 +#endif + +#ifndef dma_mapping_error +#define dma_mapping_error(a,b) 0 +#endif + +#ifndef netif_err +#define netif_err(a,b,c,d) +#endif + +#ifndef AUTONEG_DISABLE +#define AUTONEG_DISABLE 0x00 +#endif + +#ifndef AUTONEG_ENABLE +#define AUTONEG_ENABLE 0x01 +#endif + +#ifndef BMCR_SPEED1000 +#define BMCR_SPEED1000 0x0040 +#endif + +#ifndef BMCR_SPEED100 +#define BMCR_SPEED100 0x2000 +#endif + +#ifndef BMCR_SPEED10 +#define BMCR_SPEED10 0x0000 +#endif + +#ifndef SPEED_UNKNOWN +#define SPEED_UNKNOWN -1 +#endif + +#ifndef DUPLEX_UNKNOWN +#define DUPLEX_UNKNOWN 0xff +#endif + +#ifndef SUPPORTED_Pause +#define SUPPORTED_Pause (1 << 13) +#endif + +#ifndef SUPPORTED_Asym_Pause +#define SUPPORTED_Asym_Pause (1 << 14) +#endif + +#ifndef MDIO_EEE_100TX +#define MDIO_EEE_100TX 0x0002 +#endif + +#ifndef MDIO_EEE_1000T +#define MDIO_EEE_1000T 0x0004 +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#ifdef CONFIG_NET_POLL_CONTROLLER +#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8125_netpoll +#else +#define RTL_NET_POLL_CONTROLLER +#endif + +#ifdef CONFIG_R8125_VLAN +#define RTL_SET_VLAN dev->vlan_rx_register=rtl8125_vlan_rx_register +#else +#define RTL_SET_VLAN +#endif + +#define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8125_open; \ + dev->hard_start_xmit=rtl8125_start_xmit; \ + dev->get_stats=rtl8125_get_stats; \ + dev->stop=rtl8125_close; \ + dev->tx_timeout=rtl8125_tx_timeout; \ + dev->set_multicast_list=rtl8125_set_rx_mode; \ + dev->change_mtu=rtl8125_change_mtu; \ + dev->set_mac_address=rtl8125_set_mac_address; \ + dev->do_ioctl=rtl8125_do_ioctl; \ + RTL_NET_POLL_CONTROLLER; \ + RTL_SET_VLAN; +#else +#define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef true +#define true 1 +#endif + +//Hardware will continue interrupt 10 times after interrupt finished. +#define RTK_KEEP_INTERRUPT_COUNT (10) + +//the low 32 bit address of receive buffer must be 8-byte alignment. +#ifndef NET_IP_ALIGN +#define NET_IP_ALIGN 2 +#endif +#define RTK_RX_ALIGN 8 + +#ifdef CONFIG_R8125_NAPI +#define NAPI_SUFFIX "-NAPI" +#else +#define NAPI_SUFFIX "" +#endif +#if defined(ENABLE_DASH_PRINTER_SUPPORT) +#define DASH_SUFFIX "-PRINTER" +#elif defined(ENABLE_DASH_SUPPORT) +#define DASH_SUFFIX "-DASH" +#else +#define DASH_SUFFIX "" +#endif + +#if defined(ENABLE_REALWOW_SUPPORT) +#define REALWOW_SUFFIX "-REALWOW" +#else +#define REALWOW_SUFFIX "" +#endif + +#if defined(ENABLE_PTP_SUPPORT) +#define PTP_SUFFIX "-PTP" +#else +#define PTP_SUFFIX "" +#endif + +#if defined(ENABLE_RSS_SUPPORT) +#define RSS_SUFFIX "-RSS" +#else +#define RSS_SUFFIX "" +#endif + +#define RTL8125_VERSION "9.006.04" NAPI_SUFFIX DASH_SUFFIX REALWOW_SUFFIX PTP_SUFFIX RSS_SUFFIX +#define MODULENAME "r8125" +#define PFX MODULENAME ": " + +#define GPL_CLAIM "\ +r8125 Copyright (C) 2021 Realtek NIC software team \n \ +This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ +This is free software, and you are welcome to redistribute it under certain conditions; see . \n" + +#ifdef RTL8125_DEBUG +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) +#else +#define assert(expr) do {} while (0) +#define dprintk(fmt, args...) do {} while (0) +#endif /* RTL8125_DEBUG */ + +#define R8125_MSG_DEFAULT \ + (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) + +#ifdef CONFIG_R8125_NAPI +#define rtl8125_rx_hwaccel_skb vlan_hwaccel_receive_skb +#define rtl8125_rx_quota(count, quota) min(count, quota) +#else +#define rtl8125_rx_hwaccel_skb vlan_hwaccel_rx +#define rtl8125_rx_quota(count, quota) count +#endif + +/* MAC address length */ +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif + +#ifndef MAC_PROTOCOL_LEN +#define MAC_PROTOCOL_LEN 2 +#endif + +#ifndef ETH_FCS_LEN +#define ETH_FCS_LEN 4 +#endif + +#ifndef NETIF_F_TSO6 +#define NETIF_F_TSO6 0 +#endif + +#define Reserved2_data 7 +#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST_unlimited 7 +#define TX_DMA_BURST_1024 6 +#define TX_DMA_BURST_512 5 +#define TX_DMA_BURST_256 4 +#define TX_DMA_BURST_128 3 +#define TX_DMA_BURST_64 2 +#define TX_DMA_BURST_32 1 +#define TX_DMA_BURST_16 0 +#define Reserved1_data 0x3F +#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ +#define Jumbo_Frame_1k ETH_DATA_LEN +#define Jumbo_Frame_2k (2*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_3k (3*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_4k (4*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_5k (5*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_6k (6*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_7k (7*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_8k (8*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_9k (9*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ +#define RxEarly_off_V1 (0x07 << 11) +#define RxEarly_off_V2 (1 << 11) +#define Rx_Single_fetch_V2 (1 << 14) + +#define R8125_REGS_SIZE (256) +#define R8125_MAC_REGS_SIZE (256) +#define R8125_PHY_REGS_SIZE (16*2) +#define R8125_EPHY_REGS_SIZE (31*2) +#define R8125_ERI_REGS_SIZE (0x100) +#define R8125_REGS_DUMP_SIZE (0x400) +#define R8125_PCI_REGS_SIZE (0x100) +#define R8125_NAPI_WEIGHT 64 + +#define R8125_MAX_MSIX_VEC_8125B 32 +#define R8125_MIN_MSIX_VEC_8125B 17 +#define R8125_MAX_MSIX_VEC 32 +#define R8125_MAX_RX_QUEUES_VEC_V3 (16) + +#define RTL8125_TX_TIMEOUT (6 * HZ) +#define RTL8125_LINK_TIMEOUT (1 * HZ) +#define RTL8125_ESD_TIMEOUT (2 * HZ) + +#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ +#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ + +#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ +#define R8125_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) +#define R8125_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) +#define R8125_MAX_TX_QUEUES (2) +#define R8125_MAX_RX_QUEUES (4) +#define R8125_MAX_QUEUES R8125_MAX_RX_QUEUES + +#define OCP_STD_PHY_BASE 0xa400 + +#ifdef ENABLE_LIB_SUPPORT +#define R8125_MULTI_RX_Q(tp) 0 +#else +#define R8125_MULTI_RX_Q(tp) (tp->num_rx_rings > 1) +#endif + +#define NODE_ADDRESS_SIZE 6 + +#define SHORT_PACKET_PADDING_BUF_SIZE 256 + +#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef + +/* write/read MMIO register */ +#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) +#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) +#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg)) +#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg)) +#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg)) +#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg))) + +#ifndef DMA_64BIT_MASK +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#endif + +#ifndef DMA_32BIT_MASK +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#endif + +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 /* driver took care of packet */ +#endif + +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ +#endif + +#ifndef NETDEV_TX_LOCKED +#define NETDEV_TX_LOCKED -1t /* driver tx lock was already taken */ +#endif + +#ifndef ADVERTISED_Pause +#define ADVERTISED_Pause (1 << 13) +#endif + +#ifndef ADVERTISED_Asym_Pause +#define ADVERTISED_Asym_Pause (1 << 14) +#endif + +#ifndef ADVERTISE_PAUSE_CAP +#define ADVERTISE_PAUSE_CAP 0x400 +#endif + +#ifndef ADVERTISE_PAUSE_ASYM +#define ADVERTISE_PAUSE_ASYM 0x800 +#endif + +#ifndef MII_CTRL1000 +#define MII_CTRL1000 0x09 +#endif + +#ifndef ADVERTISE_1000FULL +#define ADVERTISE_1000FULL 0x200 +#endif + +#ifndef ADVERTISE_1000HALF +#define ADVERTISE_1000HALF 0x100 +#endif + +#ifndef ADVERTISED_2500baseX_Full +#define ADVERTISED_2500baseX_Full 0x8000 +#endif + +#define RTK_ADVERTISE_2500FULL 0x80 +#define RTK_LPA_ADVERTISE_2500FULL 0x20 +#define RTK_LPA_ADVERTISE_5000FULL 0x40 +#define RTK_LPA_ADVERTISE_10000FULL 0x800 + +/* Tx NO CLOSE */ +#define MAX_TX_NO_CLOSE_DESC_PTR_V2 0x10000 +#define TX_NO_CLOSE_SW_PTR_MASK_V2 0x1FFFF + +#ifndef ETH_MIN_MTU +#define ETH_MIN_MTU 68 +#endif + +#define D0_SPEED_UP_SPEED_DISABLE 0 +#define D0_SPEED_UP_SPEED_1000 1 +#define D0_SPEED_UP_SPEED_2500 2 + +#ifndef WRITE_ONCE +#define WRITE_ONCE(var, val) (*((volatile typeof(val) *)(&(var))) = (val)) +#endif +#ifndef READ_ONCE +#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) +#endif + +/*****************************************************************************/ + +//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) +#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ + (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ + ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) +/* copied from linux kernel 2.6.20 include/linux/netdev.h */ +#define NETDEV_ALIGN 32 +#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) + +static inline void *netdev_priv(struct net_device *dev) +{ + return (char *)dev + ((sizeof(struct net_device) + + NETDEV_ALIGN_CONST) + & ~NETDEV_ALIGN_CONST); +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) + +/*****************************************************************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +#define RTLDEV tp +#else +#define RTLDEV dev +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +/*****************************************************************************/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +typedef struct net_device *napi_ptr; +typedef int *napi_budget; + +#define napi dev +#define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ + ndev->weight=weig; +#define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) +#define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) +#define RTL_GET_NETDEV(priv_ptr) +#define RTL_RX_QUOTA(budget) *budget +#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ + ndev->quota -= work_done; +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev) +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) +#define RTL_NAPI_RETURN_VALUE work_done >= work_to_do +#define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) +#define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +#else +typedef struct napi_struct *napi_ptr; +typedef int napi_budget; + +#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) +#define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) +#define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) +#define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; +#define RTL_RX_QUOTA(budget) budget +#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev, napi) +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) +#endif +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(napi) +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete_done(napi, work_done) +#else +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete(napi) +#endif +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) +#endif +#define RTL_NAPI_RETURN_VALUE work_done +#define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) +#define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#define RTL_NAPI_DEL(priv) +#else +#define RTL_NAPI_DEL(priv) netif_napi_del(&priv->napi) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + +/*****************************************************************************/ +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) napi_consume_skb(skb, budget) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); +#else +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) +#else //CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); +#else +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); +#endif +#endif //CONFIG_R8125_NAPI + +/*****************************************************************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) +#ifdef __CHECKER__ +#define __iomem __attribute__((noderef, address_space(2))) +extern void __chk_io_ptr(void __iomem *); +#define __bitwise __attribute__((bitwise)) +#else +#define __iomem +#define __chk_io_ptr(x) (void)0 +#define __bitwise +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) + +/*****************************************************************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) +#ifdef __CHECKER__ +#define __force __attribute__((force)) +#else +#define __force +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) + +#ifndef module_param +#define module_param(v,t,p) MODULE_PARM(v, "i"); +#endif + +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif + +/*****************************************************************************/ +/* 2.5.28 => 2.4.23 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) + +static inline void _kc_synchronize_irq(void) +{ + synchronize_irq(); +} +#undef synchronize_irq +#define synchronize_irq(X) _kc_synchronize_irq() + +#include +#define work_struct tq_struct +#undef INIT_WORK +#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) +#undef container_of +#define container_of list_entry +#define schedule_work schedule_task +#define flush_scheduled_work flush_scheduled_tasks +#endif /* 2.5.28 => 2.4.17 */ + +/*****************************************************************************/ +/* 2.6.4 => 2.6.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) +#define MODULE_VERSION(_version) MODULE_INFO(version, _version) +#endif /* 2.6.4 => 2.6.0 */ +/*****************************************************************************/ +/* 2.6.0 => 2.5.28 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) +#define MODULE_INFO(version, _version) +#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT +#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 +#endif + +#define pci_set_consistent_dma_mask(dev,mask) 1 + +#undef dev_put +#define dev_put(dev) __dev_put(dev) + +#ifndef skb_fill_page_desc +#define skb_fill_page_desc _kc_skb_fill_page_desc +extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); +#endif + +#ifndef pci_dma_mapping_error +#define pci_dma_mapping_error _kc_pci_dma_mapping_error +static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) +{ + return dma_addr == 0; +} +#endif + +#undef ALIGN +#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + +#endif /* 2.6.0 => 2.5.28 */ + +/*****************************************************************************/ +/* 2.4.22 => 2.4.17 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) +#define pci_name(x) ((x)->slot_name) +#endif /* 2.4.22 => 2.4.17 */ + +/*****************************************************************************/ +/* 2.6.5 => 2.6.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) +#define pci_dma_sync_single_for_cpu pci_dma_sync_single +#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu +#endif /* 2.6.5 => 2.6.0 */ + +/*****************************************************************************/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +/* + * initialize a work-struct's func and data pointers: + */ +#define PREPARE_WORK(_work, _func, _data) \ + do { \ + (_work)->func = _func; \ + (_work)->data = _data; \ + } while (0) + +#endif +/*****************************************************************************/ +/* 2.6.4 => 2.6.0 */ +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) && \ + LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)) || \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))) +#define ETHTOOL_OPS_COMPAT +#endif /* 2.6.4 => 2.6.0 */ + +/*****************************************************************************/ +/* Installations with ethtool version without eeprom, adapter id, or statistics + * support */ + +#ifndef ETH_GSTRING_LEN +#define ETH_GSTRING_LEN 32 +#endif + +#ifndef ETHTOOL_GSTATS +#define ETHTOOL_GSTATS 0x1d +#undef ethtool_drvinfo +#define ethtool_drvinfo k_ethtool_drvinfo +struct k_ethtool_drvinfo { + u32 cmd; + char driver[32]; + char version[32]; + char fw_version[32]; + char bus_info[32]; + char reserved1[32]; + char reserved2[16]; + u32 n_stats; + u32 testinfo_len; + u32 eedump_len; + u32 regdump_len; +}; + +struct ethtool_stats { + u32 cmd; + u32 n_stats; + u64 data[0]; +}; +#endif /* ETHTOOL_GSTATS */ + +#ifndef ETHTOOL_PHYS_ID +#define ETHTOOL_PHYS_ID 0x1c +#endif /* ETHTOOL_PHYS_ID */ + +#ifndef ETHTOOL_GSTRINGS +#define ETHTOOL_GSTRINGS 0x1b +enum ethtool_stringset { + ETH_SS_TEST = 0, + ETH_SS_STATS, +}; +struct ethtool_gstrings { + u32 cmd; /* ETHTOOL_GSTRINGS */ + u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ + u32 len; /* number of strings in the string set */ + u8 data[0]; +}; +#endif /* ETHTOOL_GSTRINGS */ + +#ifndef ETHTOOL_TEST +#define ETHTOOL_TEST 0x1a +enum ethtool_test_flags { + ETH_TEST_FL_OFFLINE = (1 << 0), + ETH_TEST_FL_FAILED = (1 << 1), +}; +struct ethtool_test { + u32 cmd; + u32 flags; + u32 reserved; + u32 len; + u64 data[0]; +}; +#endif /* ETHTOOL_TEST */ + +#ifndef ETHTOOL_GEEPROM +#define ETHTOOL_GEEPROM 0xb +#undef ETHTOOL_GREGS +struct ethtool_eeprom { + u32 cmd; + u32 magic; + u32 offset; + u32 len; + u8 data[0]; +}; + +struct ethtool_value { + u32 cmd; + u32 data; +}; +#endif /* ETHTOOL_GEEPROM */ + +#ifndef ETHTOOL_GLINK +#define ETHTOOL_GLINK 0xa +#endif /* ETHTOOL_GLINK */ + +#ifndef ETHTOOL_GREGS +#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ +#define ethtool_regs _kc_ethtool_regs +/* for passing big chunks of data */ +struct _kc_ethtool_regs { + u32 cmd; + u32 version; /* driver-specific, indicates different chips/revs */ + u32 len; /* bytes */ + u8 data[0]; +}; +#endif /* ETHTOOL_GREGS */ + +#ifndef ETHTOOL_GMSGLVL +#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ +#endif +#ifndef ETHTOOL_SMSGLVL +#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ +#endif +#ifndef ETHTOOL_NWAY_RST +#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ +#endif +#ifndef ETHTOOL_GLINK +#define ETHTOOL_GLINK 0x0000000a /* Get link status */ +#endif +#ifndef ETHTOOL_GEEPROM +#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ +#endif +#ifndef ETHTOOL_SEEPROM +#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ +#endif +#ifndef ETHTOOL_GCOALESCE +#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ +/* for configuring coalescing parameters of chip */ +#define ethtool_coalesce _kc_ethtool_coalesce +struct _kc_ethtool_coalesce { + u32 cmd; /* ETHTOOL_{G,S}COALESCE */ + + /* How many usecs to delay an RX interrupt after + * a packet arrives. If 0, only rx_max_coalesced_frames + * is used. + */ + u32 rx_coalesce_usecs; + + /* How many packets to delay an RX interrupt after + * a packet arrives. If 0, only rx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause RX interrupts to never be + * generated. + */ + u32 rx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being serviced by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 rx_coalesce_usecs_irq; + u32 rx_max_coalesced_frames_irq; + + /* How many usecs to delay a TX interrupt after + * a packet is sent. If 0, only tx_max_coalesced_frames + * is used. + */ + u32 tx_coalesce_usecs; + + /* How many packets to delay a TX interrupt after + * a packet is sent. If 0, only tx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause TX interrupts to never be + * generated. + */ + u32 tx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being serviced by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 tx_coalesce_usecs_irq; + u32 tx_max_coalesced_frames_irq; + + /* How many usecs to delay in-memory statistics + * block updates. Some drivers do not have an in-memory + * statistic block, and in such cases this value is ignored. + * This value must not be zero. + */ + u32 stats_block_coalesce_usecs; + + /* Adaptive RX/TX coalescing is an algorithm implemented by + * some drivers to improve latency under low packet rates and + * improve throughput under high packet rates. Some drivers + * only implement one of RX or TX adaptive coalescing. Anything + * not implemented by the driver causes these values to be + * silently ignored. + */ + u32 use_adaptive_rx_coalesce; + u32 use_adaptive_tx_coalesce; + + /* When the packet rate (measured in packets per second) + * is below pkt_rate_low, the {rx,tx}_*_low parameters are + * used. + */ + u32 pkt_rate_low; + u32 rx_coalesce_usecs_low; + u32 rx_max_coalesced_frames_low; + u32 tx_coalesce_usecs_low; + u32 tx_max_coalesced_frames_low; + + /* When the packet rate is below pkt_rate_high but above + * pkt_rate_low (both measured in packets per second) the + * normal {rx,tx}_* coalescing parameters are used. + */ + + /* When the packet rate is (measured in packets per second) + * is above pkt_rate_high, the {rx,tx}_*_high parameters are + * used. + */ + u32 pkt_rate_high; + u32 rx_coalesce_usecs_high; + u32 rx_max_coalesced_frames_high; + u32 tx_coalesce_usecs_high; + u32 tx_max_coalesced_frames_high; + + /* How often to do adaptive coalescing packet rate sampling, + * measured in seconds. Must not be zero. + */ + u32 rate_sample_interval; +}; +#endif /* ETHTOOL_GCOALESCE */ + +#ifndef ETHTOOL_SCOALESCE +#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ +#endif +#ifndef ETHTOOL_GRINGPARAM +#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ +/* for configuring RX/TX ring parameters */ +#define ethtool_ringparam _kc_ethtool_ringparam +struct _kc_ethtool_ringparam { + u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ + + /* Read only attributes. These indicate the maximum number + * of pending RX/TX ring entries the driver will allow the + * user to set. + */ + u32 rx_max_pending; + u32 rx_mini_max_pending; + u32 rx_jumbo_max_pending; + u32 tx_max_pending; + + /* Values changeable by the user. The valid values are + * in the range 1 to the "*_max_pending" counterpart above. + */ + u32 rx_pending; + u32 rx_mini_pending; + u32 rx_jumbo_pending; + u32 tx_pending; +}; +#endif /* ETHTOOL_GRINGPARAM */ + +#ifndef ETHTOOL_SRINGPARAM +#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ +#endif +#ifndef ETHTOOL_GPAUSEPARAM +#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ +/* for configuring link flow control parameters */ +#define ethtool_pauseparam _kc_ethtool_pauseparam +struct _kc_ethtool_pauseparam { + u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ + + /* If the link is being auto-negotiated (via ethtool_cmd.autoneg + * being true) the user may set 'autonet' here non-zero to have the + * pause parameters be auto-negotiated too. In such a case, the + * {rx,tx}_pause values below determine what capabilities are + * advertised. + * + * If 'autoneg' is zero or the link is not being auto-negotiated, + * then {rx,tx}_pause force the driver to use/not-use pause + * flow control. + */ + u32 autoneg; + u32 rx_pause; + u32 tx_pause; +}; +#endif /* ETHTOOL_GPAUSEPARAM */ + +#ifndef ETHTOOL_SPAUSEPARAM +#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ +#endif +#ifndef ETHTOOL_GRXCSUM +#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_SRXCSUM +#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_GTXCSUM +#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_STXCSUM +#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_GSG +#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable +* (ethtool_value) */ +#endif +#ifndef ETHTOOL_SSG +#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable +* (ethtool_value). */ +#endif +#ifndef ETHTOOL_TEST +#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ +#endif +#ifndef ETHTOOL_GSTRINGS +#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ +#endif +#ifndef ETHTOOL_PHYS_ID +#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ +#endif +#ifndef ETHTOOL_GSTATS +#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ +#endif +#ifndef ETHTOOL_GTSO +#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_STSO +#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ +#endif + +#ifndef ETHTOOL_BUSINFO_LEN +#define ETHTOOL_BUSINFO_LEN 32 +#endif + +/*****************************************************************************/ + +enum RTL8125_registers { + MAC0 = 0x00, /* Ethernet hardware address. */ + MAC4 = 0x04, + MAR0 = 0x08, /* Multicast filter. */ + CounterAddrLow = 0x10, + CounterAddrHigh = 0x14, + CustomLED = 0x18, + TxDescStartAddrLow = 0x20, + TxDescStartAddrHigh = 0x24, + TxHDescStartAddrLow = 0x28, + TxHDescStartAddrHigh = 0x2c, + FLASH = 0x30, + INT_CFG0_8125 = 0x34, + ERSR = 0x36, + ChipCmd = 0x37, + TxPoll = 0x38, + IntrMask = 0x3C, + IntrStatus = 0x3E, + TxConfig = 0x40, + RxConfig = 0x44, + TCTR = 0x48, + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + Config2 = 0x53, + Config3 = 0x54, + Config4 = 0x55, + Config5 = 0x56, + TDFNR = 0x57, + TimeInt0 = 0x58, + TimeInt1 = 0x5C, + PHYAR = 0x60, + CSIDR = 0x64, + CSIAR = 0x68, + PHYstatus = 0x6C, + MACDBG = 0x6D, + GPIO = 0x6E, + PMCH = 0x6F, + ERIDR = 0x70, + ERIAR = 0x74, + INT_CFG1_8125 = 0x7A, + EPHY_RXER_NUM = 0x7C, + EPHYAR = 0x80, + TimeInt2 = 0x8C, + OCPDR = 0xB0, + MACOCP = 0xB0, + OCPAR = 0xB4, + SecMAC0 = 0xB4, + SecMAC4 = 0xB8, + PHYOCP = 0xB8, + DBG_reg = 0xD1, + TwiCmdReg = 0xD2, + MCUCmd_reg = 0xD3, + RxMaxSize = 0xDA, + EFUSEAR = 0xDC, + CPlusCmd = 0xE0, + IntrMitigate = 0xE2, + RxDescAddrLow = 0xE4, + RxDescAddrHigh = 0xE8, + MTPS = 0xEC, + FuncEvent = 0xF0, + PPSW = 0xF2, + FuncEventMask = 0xF4, + TimeInt3 = 0xF4, + FuncPresetState = 0xF8, + CMAC_IBCR0 = 0xF8, + CMAC_IBCR2 = 0xF9, + CMAC_IBIMR0 = 0xFA, + CMAC_IBISR0 = 0xFB, + FuncForceEvent = 0xFC, + //8125 + IMR0_8125 = 0x38, + ISR0_8125 = 0x3C, + TPPOLL_8125 = 0x90, + IMR1_8125 = 0x800, + ISR1_8125 = 0x802, + IMR2_8125 = 0x804, + ISR2_8125 = 0x806, + IMR3_8125 = 0x808, + ISR3_8125 = 0x80A, + BACKUP_ADDR0_8125 = 0x19E0, + BACKUP_ADDR1_8125 = 0X19E4, + TCTR0_8125 = 0x0048, + TCTR1_8125 = 0x004C, + TCTR2_8125 = 0x0088, + TCTR3_8125 = 0x001C, + TIMER_INT0_8125 = 0x0058, + TIMER_INT1_8125 = 0x005C, + TIMER_INT2_8125 = 0x008C, + TIMER_INT3_8125 = 0x00F4, + INT_MITI_V2_0_RX = 0x0A00, + INT_MITI_V2_0_TX = 0x0A02, + INT_MITI_V2_1_RX = 0x0A08, + INT_MITI_V2_1_TX = 0x0A0A, + IMR_V2_CLEAR_REG_8125 = 0x0D00, + ISR_V2_8125 = 0x0D04, + IMR_V2_SET_REG_8125 = 0x0D0C, + TDU_STA_8125 = 0x0D08, + RDU_STA_8125 = 0x0D0A, + TX_NEW_CTRL = 0x203E, + TNPDS_Q1_LOW_8125 = 0x2100, + PLA_TXQ0_IDLE_CREDIT = 0x2500, + PLA_TXQ1_IDLE_CREDIT = 0x2504, + SW_TAIL_PTR0_8125 = 0x2800, + HW_CLO_PTR0_8125 = 0x2802, + RDSAR_Q1_LOW_8125 = 0x4000, + RSS_CTRL_8125 = 0x4500, + Q_NUM_CTRL_8125 = 0x4800, + RSS_KEY_8125 = 0x4600, + RSS_INDIRECTION_TBL_8125_V2 = 0x4700, + EEE_TXIDLE_TIMER_8125 = 0x6048, + PTP_CTRL_8125 = 0x6800, + PTP_STATUS_8125 = 0x6802, + PTP_ISR_8125 = 0x6804, + PTP_IMR_8125 = 0x6805, + PTP_TIME_CORRECT_CMD_8125 = 0x6806, + PTP_SOFT_CONFIG_Time_NS_8125 = 0x6808, + PTP_SOFT_CONFIG_Time_S_8125 = 0x680C, + PTP_LOCAL_Time_SUB_NS_8125 = 0x6814, + PTP_LOCAL_Time_NS_8125 = 0x6818, + PTP_LOCAL_Time_S_8125 = 0x681C, + PTP_Time_SHIFTER_S_8125 = 0x6856, + PPS_RISE_TIME_NS_8125 = 0x68A0, + PPS_RISE_TIME_S_8125 = 0x68A4, +}; + +enum RTL8125_register_content { + /* InterruptStatusBits */ + SYSErr = 0x8000, + PCSTimeout = 0x4000, + SWInt = 0x0100, + TxDescUnavail = 0x0080, + RxFIFOOver = 0x0040, + LinkChg = 0x0020, + RxDescUnavail = 0x0010, + TxErr = 0x0008, + TxOK = 0x0004, + RxErr = 0x0002, + RxOK = 0x0001, + RxDU1 = 0x0002, + RxOK1 = 0x0001, + + /* RxStatusDesc */ + RxRWT = (1 << 22), + RxRES = (1 << 21), + RxRUNT = (1 << 20), + RxCRC = (1 << 19), + + RxRWT_V3 = (1 << 18), + RxRES_V3 = (1 << 20), + RxRUNT_V3 = (1 << 19), + RxCRC_V3 = (1 << 17), + + /* ChipCmdBits */ + StopReq = 0x80, + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, + RxBufEmpty = 0x01, + + /* Cfg9346Bits */ + Cfg9346_Lock = 0x00, + Cfg9346_Unlock = 0xC0, + Cfg9346_EEDO = (1 << 0), + Cfg9346_EEDI = (1 << 1), + Cfg9346_EESK = (1 << 2), + Cfg9346_EECS = (1 << 3), + Cfg9346_EEM0 = (1 << 6), + Cfg9346_EEM1 = (1 << 7), + + /* rx_mode_bits */ + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0x08, + AcceptMulticast = 0x04, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, + + /* Transmit Priority Polling*/ + HPQ = 0x80, + NPQ = 0x40, + FSWInt = 0x01, + + /* RxConfigBits */ + Reserved2_shift = 13, + RxCfgDMAShift = 8, + EnableRxDescV3 = (1 << 24), + EnableOuterVlan = (1 << 23), + EnableInnerVlan = (1 << 22), + RxCfg_128_int_en = (1 << 15), + RxCfg_fet_multi_en = (1 << 14), + RxCfg_half_refetch = (1 << 13), + RxCfg_pause_slot_en = (1 << 11), + RxCfg_9356SEL = (1 << 6), + + /* TxConfigBits */ + TxInterFrameGapShift = 24, + TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + TxMACLoopBack = (1 << 17), /* MAC loopback */ + + /* Config1 register */ + LEDS1 = (1 << 7), + LEDS0 = (1 << 6), + Speed_down = (1 << 4), + MEMMAP = (1 << 3), + IOMAP = (1 << 2), + VPD = (1 << 1), + PMEnable = (1 << 0), /* Power Management Enable */ + + /* Config2 register */ + PMSTS_En = (1 << 5), + + /* Config3 register */ + Isolate_en = (1 << 12), /* Isolate enable */ + MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ + LinkUp = (1 << 4), /* This bit is reserved in RTL8125B.*/ + /* Wake up when the cable connection is re-established */ + ECRCEN = (1 << 3), /* This bit is reserved in RTL8125B*/ + Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8125B*/ + RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8125B*/ + Beacon_en = (1 << 0), /* This bit is reserved in RTL8125B*/ + + /* Config4 register */ + Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8125B*/ + + /* Config5 register */ + BWF = (1 << 6), /* Accept Broadcast wakeup frame */ + MWF = (1 << 5), /* Accept Multicast wakeup frame */ + UWF = (1 << 4), /* Accept Unicast wakeup frame */ + LanWake = (1 << 1), /* LanWake enable/disable */ + PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ + + /* CPlusCmd */ + EnableBist = (1 << 15), + Macdbgo_oe = (1 << 14), + Normal_mode = (1 << 13), + Force_halfdup = (1 << 12), + Force_rxflow_en = (1 << 11), + Force_txflow_en = (1 << 10), + Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8125B + ASF = (1 << 8),//This bit is reserved in RTL8125C + PktCntrDisable = (1 << 7), + RxVlan = (1 << 6), + RxChkSum = (1 << 5), + Macdbgo_sel = 0x001C, + INTT_0 = 0x0000, + INTT_1 = 0x0001, + INTT_2 = 0x0002, + INTT_3 = 0x0003, + + /* rtl8125_PHYstatus */ + PowerSaveStatus = 0x80, + _2500bpsF = 0x400, + TxFlowCtrl = 0x40, + RxFlowCtrl = 0x20, + _1000bpsF = 0x10, + _100bps = 0x08, + _10bps = 0x04, + LinkStatus = 0x02, + FullDup = 0x01, + + /* DBG_reg */ + Fix_Nak_1 = (1 << 4), + Fix_Nak_2 = (1 << 3), + DBGPIN_E2 = (1 << 0), + + /* ResetCounterCommand */ + CounterReset = 0x1, + /* DumpCounterCommand */ + CounterDump = 0x8, + + /* PHY access */ + PHYAR_Flag = 0x80000000, + PHYAR_Write = 0x80000000, + PHYAR_Read = 0x00000000, + PHYAR_Reg_Mask = 0x1f, + PHYAR_Reg_shift = 16, + PHYAR_Data_Mask = 0xffff, + + /* EPHY access */ + EPHYAR_Flag = 0x80000000, + EPHYAR_Write = 0x80000000, + EPHYAR_Read = 0x00000000, + EPHYAR_Reg_Mask = 0x3f, + EPHYAR_Reg_Mask_v2 = 0x7f, + EPHYAR_Reg_shift = 16, + EPHYAR_Data_Mask = 0xffff, + + /* CSI access */ + CSIAR_Flag = 0x80000000, + CSIAR_Write = 0x80000000, + CSIAR_Read = 0x00000000, + CSIAR_ByteEn = 0x0f, + CSIAR_ByteEn_shift = 12, + CSIAR_Addr_Mask = 0x0fff, + + /* ERI access */ + ERIAR_Flag = 0x80000000, + ERIAR_Write = 0x80000000, + ERIAR_Read = 0x00000000, + ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ + ERIAR_ExGMAC = 0, + ERIAR_MSIX = 1, + ERIAR_ASF = 2, + ERIAR_OOB = 2, + ERIAR_Type_shift = 16, + ERIAR_ByteEn = 0x0f, + ERIAR_ByteEn_shift = 12, + + /* OCP GPHY access */ + OCPDR_Write = 0x80000000, + OCPDR_Read = 0x00000000, + OCPDR_Reg_Mask = 0xFF, + OCPDR_Data_Mask = 0xFFFF, + OCPDR_GPHY_Reg_shift = 16, + OCPAR_Flag = 0x80000000, + OCPAR_GPHY_Write = 0x8000F060, + OCPAR_GPHY_Read = 0x0000F060, + OCPR_Write = 0x80000000, + OCPR_Read = 0x00000000, + OCPR_Addr_Reg_shift = 16, + OCPR_Flag = 0x80000000, + OCP_STD_PHY_BASE_PAGE = 0x0A40, + + /* MCU Command */ + Now_is_oob = (1 << 7), + Txfifo_empty = (1 << 5), + Rxfifo_empty = (1 << 4), + + /* E-FUSE access */ + EFUSE_WRITE = 0x80000000, + EFUSE_WRITE_OK = 0x00000000, + EFUSE_READ = 0x00000000, + EFUSE_READ_OK = 0x80000000, + EFUSE_WRITE_V3 = 0x40000000, + EFUSE_WRITE_OK_V3 = 0x00000000, + EFUSE_READ_V3 = 0x80000000, + EFUSE_READ_OK_V3 = 0x00000000, + EFUSE_Reg_Mask = 0x03FF, + EFUSE_Reg_Shift = 8, + EFUSE_Check_Cnt = 300, + EFUSE_READ_FAIL = 0xFF, + EFUSE_Data_Mask = 0x000000FF, + + /* GPIO */ + GPIO_en = (1 << 0), + + /* PTP */ + PTP_ISR_TOK = (1 << 1), + PTP_ISR_TER = (1 << 2), + PTP_EXEC_CMD = (1 << 7), + PTP_ADJUST_TIME_NS_NEGATIVE = (1 << 30), + PTP_ADJUST_TIME_S_NEGATIVE = (1ULL << 48), + + /* New Interrupt Bits */ + INT_CFG0_ENABLE_8125 = (1 << 0), + INT_CFG0_TIMEOUT0_BYPASS_8125 = (1 << 1), + INT_CFG0_MITIGATION_BYPASS_8125 = (1 << 2), + ISRIMR_V2_ROK_Q0 = (1 << 0), + ISRIMR_TOK_Q0 = (1 << 16), + ISRIMR_TOK_Q1 = (1 << 18), + ISRIMR_V2_LINKCHG = (1 << 21), + + /* Magic Number */ + RTL8125_MAGIC_NUMBER = 0x0badbadbadbadbadull, +}; + +enum _DescStatusBit { + DescOwn = (1 << 31), /* Descriptor is owned by NIC */ + RingEnd = (1 << 30), /* End of descriptor ring */ + FirstFrag = (1 << 29), /* First segment of a packet */ + LastFrag = (1 << 28), /* Final segment of a packet */ + + DescOwn_V3 = (DescOwn), /* Descriptor is owned by NIC */ + RingEnd_V3 = (RingEnd), /* End of descriptor ring */ + FirstFrag_V3 = (1 << 25), /* First segment of a packet */ + LastFrag_V3 = (1 << 24), /* Final segment of a packet */ + + /* Tx private */ + /*------ offset 0 of tx descriptor ------*/ + LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ + GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ + GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ + LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ + MSSShift = 16, /* MSS value position */ + MSSMask = 0x7FFU, /* MSS value 11 bits */ + TxIPCS = (1 << 18), /* Calculate IP checksum */ + TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ + TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ + TxVlanTag = (1 << 17), /* Add VLAN tag */ + + /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only begin @@@@@@*/ + TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ + TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ + TxIPCS_C = (1 << 29), /* Calculate IP checksum */ + TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */ + /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only end @@@@@@*/ + + + /* Rx private */ + /*------ offset 0 of rx descriptor ------*/ + PID1 = (1 << 18), /* Protocol ID bit 1/2 */ + PID0 = (1 << 17), /* Protocol ID bit 2/2 */ + +#define RxProtoUDP (PID1) +#define RxProtoTCP (PID0) +#define RxProtoIP (PID1 | PID0) +#define RxProtoMask RxProtoIP + + RxIPF = (1 << 16), /* IP checksum failed */ + RxUDPF = (1 << 15), /* UDP/IP checksum failed */ + RxTCPF = (1 << 14), /* TCP/IP checksum failed */ + RxVlanTag = (1 << 16), /* VLAN tag available */ + + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxUDPT = (1 << 18), + RxTCPT = (1 << 17), + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ + + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxV6F = (1 << 31), + RxV4F = (1 << 30), + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ + + + PID1_v3 = (1 << 29), /* Protocol ID bit 1/2 */ + PID0_v3 = (1 << 28), /* Protocol ID bit 2/2 */ + +#define RxProtoUDP_v3 (PID1_v3) +#define RxProtoTCP_v3 (PID0_v3) +#define RxProtoIP_v3 (PID1_v3 | PID0_v3) +#define RxProtoMask_v3 RxProtoIP_v3 + + RxIPF_v3 = (1 << 26), /* IP checksum failed */ + RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */ + RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */ + RxSCTPF_v3 = (1 << 23), /* TCP/IP checksum failed */ + RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */ + + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxUDPT_v3 = (1 << 29), + RxTCPT_v3 = (1 << 28), + RxSCTP_v3 = (1 << 27), + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ + + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxV6F_v3 = (RxV6F), + RxV4F_v3 = (RxV4F), + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ +}; + +enum features { +// RTL_FEATURE_WOL = (1 << 0), + RTL_FEATURE_MSI = (1 << 1), + RTL_FEATURE_MSIX = (1 << 2), +}; + +enum wol_capability { + WOL_DISABLED = 0, + WOL_ENABLED = 1 +}; + +enum bits { + BIT_0 = (1 << 0), + BIT_1 = (1 << 1), + BIT_2 = (1 << 2), + BIT_3 = (1 << 3), + BIT_4 = (1 << 4), + BIT_5 = (1 << 5), + BIT_6 = (1 << 6), + BIT_7 = (1 << 7), + BIT_8 = (1 << 8), + BIT_9 = (1 << 9), + BIT_10 = (1 << 10), + BIT_11 = (1 << 11), + BIT_12 = (1 << 12), + BIT_13 = (1 << 13), + BIT_14 = (1 << 14), + BIT_15 = (1 << 15), + BIT_16 = (1 << 16), + BIT_17 = (1 << 17), + BIT_18 = (1 << 18), + BIT_19 = (1 << 19), + BIT_20 = (1 << 20), + BIT_21 = (1 << 21), + BIT_22 = (1 << 22), + BIT_23 = (1 << 23), + BIT_24 = (1 << 24), + BIT_25 = (1 << 25), + BIT_26 = (1 << 26), + BIT_27 = (1 << 27), + BIT_28 = (1 << 28), + BIT_29 = (1 << 29), + BIT_30 = (1 << 30), + BIT_31 = (1 << 31) +}; + +enum effuse { + EFUSE_NOT_SUPPORT = 0, + EFUSE_SUPPORT_V1, + EFUSE_SUPPORT_V2, + EFUSE_SUPPORT_V3, + EFUSE_SUPPORT_V4, +}; +#define RsvdMask 0x3fffc000 +#define RsvdMaskV3 0x3fff8000 + +struct TxDesc { + u32 opts1; + u32 opts2; + u64 addr; + u32 reserved0; + u32 reserved1; + u32 reserved2; + u32 reserved3; +}; + +struct RxDesc { + u32 opts1; + u32 opts2; + u64 addr; +}; + +struct RxDescV3 { + union { + struct { + u32 rsv1; + u32 rsv2; + } RxDescDDWord1; + }; + + union { + struct { + u32 RSSResult; + u16 HeaderBufferLen; + u16 HeaderInfo; + } RxDescNormalDDWord2; + + struct { + u32 rsv5; + u32 rsv6; + } RxDescDDWord2; + }; + + union { + u64 addr; + + struct { + u32 TimeStampLow; + u32 TimeStampHigh; + } RxDescTimeStamp; + + struct { + u32 rsv8; + u32 rsv9; + } RxDescDDWord3; + }; + + union { + struct { + u32 opts2; + u32 opts1; + } RxDescNormalDDWord4; + + struct { + u16 TimeStampHHigh; + u16 rsv11; + u32 opts1; + } RxDescPTPDDWord4; + }; +}; + +enum rxdesc_type { + RXDESC_TYPE_NORMAL=0, + RXDESC_TYPE_NEXT, + RXDESC_TYPE_PTP, + RXDESC_TYPE_MAX +}; + +//Rx Desc Type +enum rx_desc_ring_type { + RX_DESC_RING_TYPE_UNKNOWN=0, + RX_DESC_RING_TYPE_1, + RX_DESC_RING_TYPE_2, + RX_DESC_RING_TYPE_3, + RX_DESC_RING_TYPE_MAX +}; + +enum rx_desc_len { + RX_DESC_LEN_TYPE_1 = (sizeof(struct RxDesc)), + RX_DESC_LEN_TYPE_3 = (sizeof(struct RxDescV3)) +}; + +struct ring_info { + struct sk_buff *skb; + u32 len; + u8 __pad[sizeof(void *) - sizeof(u32)]; +}; + +struct pci_resource { + u8 cmd; + u8 cls; + u16 io_base_h; + u16 io_base_l; + u16 mem_base_h; + u16 mem_base_l; + u8 ilr; + u16 resv_0x1c_h; + u16 resv_0x1c_l; + u16 resv_0x20_h; + u16 resv_0x20_l; + u16 resv_0x24_h; + u16 resv_0x24_l; + u16 resv_0x2c_h; + u16 resv_0x2c_l; + u32 pci_sn_l; + u32 pci_sn_h; +}; + +enum r8125_flag { + R8125_FLAG_DOWN = 0, + R8125_FLAG_TASK_RESET_PENDING, + R8125_FLAG_TASK_ESD_CHECK_PENDING, + R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, + R8125_FLAG_MAX +}; + +struct rtl8125_tx_ring { + void* priv; + u32 index; + u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ + u32 dirty_tx; + struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + dma_addr_t TxPhyAddr; + struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + + u32 NextHwDesCloPtr; + u32 BeginHwDesCloPtr; + + u16 hw_clo_ptr_reg; + u16 sw_tail_ptr_reg; + + u16 tdsar_reg; /* Transmit Descriptor Start Address */ +}; + +struct rtl8125_rx_ring { + void* priv; + u32 index; + u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ + u32 dirty_rx; + struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ + u64 RxDescPhyAddr[NUM_RX_DESC]; /* Rx desc physical address*/ + dma_addr_t RxPhyAddr; + struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ + + u16 rdsar_reg; /* Receive Descriptor Start Address */ +}; + +struct r8125_napi { +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + struct napi_struct napi; +#endif +#endif + void* priv; + int index; +}; + +struct r8125_irq { + irq_handler_t handler; + unsigned int vector; + u8 requested; + char name[IFNAMSIZ + 10]; +}; + +#pragma pack(1) +struct rtl8125_regs { + //00 + u8 mac_id[6]; + u16 reg_06; + u8 mar[8]; + //10 + u64 dtccr; + u16 ledsel0; + u16 legreg; + u32 tctr3; + //20 + u32 txq0_dsc_st_addr_0; + u32 txq0_dsc_st_addr_2; + u64 reg_28; + //30 + u16 rit; + u16 ritc; + u16 reg_34; + u8 reg_36; + u8 command; + u32 imr0; + u32 isr0; + //40 + u32 tcr; + u32 rcr; + u32 tctr0; + u32 tctr1; + //50 + u8 cr93c46; + u8 config0; + u8 config1; + u8 config2; + u8 config3; + u8 config4; + u8 config5; + u8 tdfnr; + u32 timer_int0; + u32 timer_int1; + //60 + u32 gphy_mdcmdio; + u32 csidr; + u32 csiar; + u16 phy_status; + u8 config6; + u8 pmch; + //70 + u32 eridr; + u32 eriar; + u16 config7; + u16 reg_7a; + u32 ephy_rxerr_cnt; + //80 + u32 ephy_mdcmdio; + u16 ledsel2; + u16 ledsel1; + u32 tctr2; + u32 timer_int2; + //90 + u8 tppoll0; + u8 reg_91; + u16 reg_92; + u16 led_feature; + u16 ledsel3; + u16 eee_led_config; + u16 reg_9a; + u32 reg_9c; + //a0 + u32 reg_a0; + u32 reg_a4; + u32 reg_a8; + u32 reg_ac; + //b0 + u32 patch_dbg; + u32 reg_b4; + u32 gphy_ocp; + u32 reg_bc; + //c0 + u32 reg_c0; + u32 reg_c4; + u32 reg_c8; + u16 otp_cmd; + u16 otp_pg_config; + //d0 + u16 phy_pwr; + u8 twsi_ctrl; + u8 oob_ctrl; + u16 mac_dbgo; + u16 mac_dbg; + u16 reg_d8; + u16 rms; + u32 efuse_data; + //e0 + u16 cplus_cmd; + u16 reg_e2; + u32 rxq0_dsc_st_addr_0; + u32 rxq0_dsc_st_addr_2; + u16 reg_ec; + u16 tx10midle_cnt; + //f0 + u16 misc0; + u16 misc1; + u32 timer_int3; + u32 cmac_ib; + u16 reg_fc; + u16 sw_rst; +}; +#pragma pack() + +struct rtl8125_regs_save { + union { + u8 mac_io[R8125_MAC_REGS_SIZE]; + + struct rtl8125_regs mac_reg; + }; + u16 pcie_phy[R8125_EPHY_REGS_SIZE/2]; + u16 eth_phy[R8125_PHY_REGS_SIZE/2]; + u32 eri_reg[R8125_ERI_REGS_SIZE/4]; + u32 pci_reg[R8125_PCI_REGS_SIZE/4]; + u16 sw_tail_ptr_reg[R8125_MAX_TX_QUEUES]; + u16 hw_clo_ptr_reg[R8125_MAX_TX_QUEUES]; + + //ktime_t begin_ktime; + //ktime_t end_ktime; + //u64 duration_ns; + + u16 sw0_tail_ptr; + u16 next_hwq0_clo_ptr; + u16 sw1_tail_ptr; + u16 next_hwq1_clo_ptr; + + u16 int_miti_rxq0; + u16 int_miti_txq0; + u16 int_miti_rxq1; + u16 int_miti_txq1; + u8 int_config; + u32 imr_new; + u32 isr_new; + + u8 tdu_status; + u16 rdu_status; + + u16 tc_mode; + + u32 txq1_dsc_st_addr_0; + u32 txq1_dsc_st_addr_2; + + u32 pla_tx_q0_idle_credit; + u32 pla_tx_q1_idle_credit; + + u32 rxq1_dsc_st_addr_0; + u32 rxq1_dsc_st_addr_2; + + u32 rss_ctrl; + u8 rss_key[RTL8125_RSS_KEY_SIZE]; + u8 rss_i_table[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; + u16 rss_queue_num_sel_r; +}; + +struct rtl8125_counters { + /* legacy */ + u64 tx_packets; + u64 rx_packets; + u64 tx_errors; + u32 rx_errors; + u16 rx_missed; + u16 align_errors; + u32 tx_one_collision; + u32 tx_multi_collision; + u64 rx_unicast; + u64 rx_broadcast; + u32 rx_multicast; + u16 tx_aborted; + u16 tx_underrun; + + /* extended */ + u64 tx_octets; + u64 rx_octets; + u64 rx_multicast64; + u64 tx_unicast64; + u64 tx_broadcast64; + u64 tx_multicast64; + u32 tx_pause_on; + u32 tx_pause_off; + u32 tx_pause_all; + u32 tx_deferred; + u32 tx_late_collision; + u32 tx_all_collision; + u32 tx_aborted32; + u32 align_errors32; + u32 rx_frame_too_long; + u32 rx_runt; + u32 rx_pause_on; + u32 rx_pause_off; + u32 rx_pause_all; + u32 rx_unknown_opcode; + u32 rx_mac_error; + u32 tx_underrun32; + u32 rx_mac_missed; + u32 rx_tcam_dropped; + u32 tdu; + u32 rdu; +}; + +/* Flow Control Settings */ +enum rtl8125_fc_mode { + rtl8125_fc_none = 0, + rtl8125_fc_rx_pause, + rtl8125_fc_tx_pause, + rtl8125_fc_full, + rtl8125_fc_default +}; + +struct rtl8125_private { + void __iomem *mmio_addr; /* memory map physical address */ + struct pci_dev *pci_dev; /* Index of PCI device */ + struct net_device *dev; + struct r8125_napi r8125napi[R8125_MAX_MSIX_VEC]; + struct r8125_irq irq_tbl[R8125_MAX_MSIX_VEC]; + unsigned int irq_nvecs; + unsigned int max_irq_nvecs; + unsigned int min_irq_nvecs; + //struct msix_entry msix_entries[R8125_MAX_MSIX_VEC]; + struct net_device_stats stats; /* statistics of net device */ + spinlock_t lock; /* spin lock flag */ + u32 msg_enable; + u32 tx_tcp_csum_cmd; + u32 tx_udp_csum_cmd; + u32 tx_ip_csum_cmd; + u32 tx_ipv6_csum_cmd; + int max_jumbo_frame_size; + int chipset; + u32 mcfg; + //u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ + //u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ + //u32 dirty_rx; + //u32 dirty_tx; + //struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + //struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ + //dma_addr_t TxPhyAddr; + //dma_addr_t RxPhyAddr; + //struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ + //struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + unsigned rx_buf_sz; + u16 HwSuppNumTxQueues; + u16 HwSuppNumRxQueues; + unsigned int num_tx_rings; + unsigned int num_rx_rings; + struct rtl8125_tx_ring tx_ring[R8125_MAX_TX_QUEUES]; + struct rtl8125_rx_ring rx_ring[R8125_MAX_RX_QUEUES]; +#ifdef ENABLE_LIB_SUPPORT + struct atomic_notifier_head lib_nh; + struct rtl8125_ring lib_tx_ring[R8125_MAX_TX_QUEUES]; + struct rtl8125_ring lib_rx_ring[R8125_MAX_RX_QUEUES]; +#endif + //struct timer_list esd_timer; + //struct timer_list link_timer; + struct pci_resource pci_cfg_space; + unsigned int esd_flag; + unsigned int pci_cfg_is_read; + unsigned int rtl8125_rx_config; + u16 cp_cmd; + u32 intr_mask; + u32 timer_intr_mask; + u16 isr_reg[R8125_MAX_QUEUES]; + u16 imr_reg[R8125_MAX_QUEUES]; + int phy_auto_nego_reg; + int phy_1000_ctrl_reg; + int phy_2500_ctrl_reg; + u8 org_mac_addr[NODE_ADDRESS_SIZE]; + struct rtl8125_counters *tally_vaddr; + dma_addr_t tally_paddr; + +#ifdef CONFIG_R8125_VLAN + struct vlan_group *vlgrp; +#endif + u8 wol_enabled; + u32 wol_opts; + u8 efuse_ver; + u8 eeprom_type; + u8 autoneg; + u8 duplex; + u32 speed; + u32 advertising; + enum rtl8125_fc_mode fcpause; + u16 eeprom_len; + u16 cur_page; + u32 bios_setting; + + int (*set_speed)(struct net_device *, u8 autoneg, u32 speed, u8 duplex, u32 adv); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + void (*get_settings)(struct net_device *, struct ethtool_cmd *); +#else + void (*get_settings)(struct net_device *, struct ethtool_link_ksettings *); +#endif + void (*phy_reset_enable)(struct net_device *); + unsigned int (*phy_reset_pending)(struct net_device *); + unsigned int (*link_ok)(struct net_device *); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + struct work_struct reset_task; + struct work_struct esd_task; + struct work_struct linkchg_task; +#else + struct delayed_work reset_task; + struct delayed_work esd_task; + struct delayed_work linkchg_task; +#endif + DECLARE_BITMAP(task_flags, R8125_FLAG_MAX); + unsigned features; + + u8 org_pci_offset_99; + u8 org_pci_offset_180; + u8 issue_offset_99_event; + + u8 org_pci_offset_80; + u8 org_pci_offset_81; + u8 use_timer_interrrupt; + + u32 keep_intr_cnt; + + u8 HwIcVerUnknown; + u8 NotWrRamCodeToMicroP; + u8 NotWrMcuPatchCode; + u8 HwHasWrRamCodeToMicroP; + + u16 sw_ram_code_ver; + u16 hw_ram_code_ver; + + u8 rtk_enable_diag; + + u8 ShortPacketSwChecksum; + + u8 UseSwPaddingShortPkt; + + u8 RequireAdcBiasPatch; + u16 AdcBiasPatchIoffset; + + u8 RequireAdjustUpsTxLinkPulseTiming; + u16 SwrCnt1msIni; + + u8 HwSuppNowIsOobVer; + + u8 RequiredSecLanDonglePatch; + + u8 RequirePhyMdiSwapPatch; + + u8 RequireLSOPatch; + + u32 HwFiberModeVer; + u32 HwFiberStat; + u8 HwSwitchMdiToFiber; + + u16 NicCustLedValue; + + u8 HwSuppMagicPktVer; + + u8 HwSuppLinkChgWakeUpVer; + + u8 HwSuppCheckPhyDisableModeVer; + + u8 random_mac; + + u16 phy_reg_aner; + u16 phy_reg_anlpar; + u16 phy_reg_gbsr; + u16 phy_reg_status_2500; + + u32 HwPcieSNOffset; + + u8 HwSuppTxNoCloseVer; + u8 EnableTxNoClose; + + u8 HwSuppIsrVer; + u8 HwCurrIsrVer; + + u8 HwSuppIntMitiVer; + + u8 HwSuppExtendTallyCounterVer; + + u8 check_keep_link_speed; + u8 resume_not_chg_speed; + + u8 HwSuppD0SpeedUpVer; + u8 D0SpeedUpSpeed; + + u8 ring_lib_enabled; + + const char *fw_name; + struct rtl8125_fw *rtl_fw; + u32 ocp_base; + + //Dash+++++++++++++++++ + u8 HwSuppDashVer; + u8 DASH; + u8 dash_printer_enabled; + u8 HwPkgDet; + void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */ + void __iomem *cmac_ioaddr; /* cmac memory map physical address */ + +#ifdef ENABLE_DASH_SUPPORT + u16 AfterRecvFromFwBufLen; + u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE]; + u16 AfterSendToFwBufLen; + u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE]; + u16 SendToFwBufferLen; + u32 SizeOfSendToFwBuffer; + u32 SizeOfSendToFwBufferMemAlloc; + u32 NumOfSendToFwBuffer; + + u8 OobReq; + u8 OobAck; + u32 OobReqComplete; + u32 OobAckComplete; + + u8 RcvFwReqSysOkEvt; + u8 RcvFwDashOkEvt; + u8 SendFwHostOkEvt; + + u8 DashFwDisableRx; + + void *UnalignedSendToFwBufferVa; + void *SendToFwBuffer; + u64 SendToFwBufferPhy; + u8 SendingToFw; + dma_addr_t UnalignedSendToFwBufferPa; + PTX_DASH_SEND_FW_DESC TxDashSendFwDesc; + u64 TxDashSendFwDescPhy; + u8 *UnalignedTxDashSendFwDescVa; + u32 SizeOfTxDashSendFwDescMemAlloc; + u32 SizeOfTxDashSendFwDesc; + u32 NumTxDashSendFwDesc; + u32 CurrNumTxDashSendFwDesc; + u32 LastSendNumTxDashSendFwDesc; + dma_addr_t UnalignedTxDashSendFwDescPa; + + u32 NumRecvFromFwBuffer; + u32 SizeOfRecvFromFwBuffer; + u32 SizeOfRecvFromFwBufferMemAlloc; + void *RecvFromFwBuffer; + u64 RecvFromFwBufferPhy; + + void *UnalignedRecvFromFwBufferVa; + dma_addr_t UnalignedRecvFromFwBufferPa; + PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc; + u64 RxDashRecvFwDescPhy; + u8 *UnalignedRxDashRecvFwDescVa; + u32 SizeOfRxDashRecvFwDescMemAlloc; + u32 SizeOfRxDashRecvFwDesc; + u32 NumRxDashRecvFwDesc; + u32 CurrNumRxDashRecvFwDesc; + dma_addr_t UnalignedRxDashRecvFwDescPa; + u8 DashReqRegValue; + u16 HostReqValue; + + u32 CmacResetIsrCounter; + u8 CmacResetIntr; + u8 CmacResetting; + u8 CmacOobIssueCmacReset; + u32 CmacResetbyFwCnt; + +#if defined(ENABLE_DASH_PRINTER_SUPPORT) + struct completion fw_ack; + struct completion fw_req; + struct completion fw_host_ok; +#endif + //Dash----------------- +#endif //ENABLE_DASH_SUPPORT + + //Realwow++++++++++++++ + u8 HwSuppKCPOffloadVer; + + u8 EnableDhcpTimeoutWake; + u8 EnableTeredoOffload; + u8 EnableKCPOffload; +#ifdef ENABLE_REALWOW_SUPPORT + u32 DhcpTimeout; + MP_KCP_INFO MpKCPInfo; + //Realwow-------------- +#endif //ENABLE_REALWOW_SUPPORT + + struct ethtool_eee eee; + +#ifdef ENABLE_R8125_PROCFS + //Procfs support + struct proc_dir_entry *proc_dir; +#endif + u8 InitRxDescType; + u16 RxDescLength; //V1 16 Byte V2 32 Bytes + u32 RxDescRingLength; + + u8 HwSuppPtpVer; + u8 EnablePtp; + u8 ptp_master_mode; + s64 ptp_adjust; +#ifdef ENABLE_PTP_SUPPORT + u32 tx_hwtstamp_timeouts; + u32 tx_hwtstamp_skipped; + struct work_struct ptp_tx_work; + struct sk_buff *ptp_tx_skb; + struct hwtstamp_config hwtstamp_config; + unsigned long ptp_tx_start; + struct ptp_clock_info ptp_clock_info; + struct ptp_clock *ptp_clock; +#endif + + u8 HwSuppRssVer; + u8 EnableRss; + u16 HwSuppIndirTblEntries; +#ifdef ENABLE_RSS_SUPPORT + u32 rss_flags; + /* Receive Side Scaling settings */ + u8 rss_key[RTL8125_RSS_KEY_SIZE]; + u8 rss_indir_tbl[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; + u32 rss_options; +#endif +}; + +#ifdef ENABLE_LIB_SUPPORT +static inline unsigned int +rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) +{ + int count, i; + + for (count = 0, i = tp->num_tx_rings; i < tp->HwSuppNumTxQueues; i++) + if(tp->lib_tx_ring[i].enabled) + count++; + + return count; +} + +static inline unsigned int +rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) +{ + int count, i; + + for (count = 0, i = tp->num_rx_rings; i < tp->HwSuppNumRxQueues; i++) + if(tp->lib_rx_ring[i].enabled) + count++; + + return count; +} + +#else +static inline unsigned int +rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) +{ + return 0; +} + +static inline unsigned int +rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) +{ + return 0; +} +#endif + +static inline unsigned int +rtl8125_tot_tx_rings(struct rtl8125_private *tp) +{ + return tp->num_tx_rings + rtl8125_num_lib_tx_rings(tp); +} + +static inline unsigned int +rtl8125_tot_rx_rings(struct rtl8125_private *tp) +{ + return tp->num_rx_rings + rtl8125_num_lib_rx_rings(tp); +} + +enum eetype { + EEPROM_TYPE_NONE=0, + EEPROM_TYPE_93C46, + EEPROM_TYPE_93C56, + EEPROM_TWSI +}; + +enum mcfg { + CFG_METHOD_2=2, + CFG_METHOD_3, + CFG_METHOD_4, + CFG_METHOD_5, + CFG_METHOD_DEFAULT, + CFG_METHOD_MAX +}; + +#define LSO_32K 32000 +#define LSO_64K 64000 + +#define NIC_MIN_PHYS_BUF_COUNT (2) +#define NIC_MAX_PHYS_BUF_COUNT_LSO_64K (24) +#define NIC_MAX_PHYS_BUF_COUNT_LSO2 (16*4) + +#define GTTCPHO_SHIFT 18 +#define GTTCPHO_MAX 0x7fU +#define GTPKTSIZE_MAX 0x3ffffU +#define TCPHO_SHIFT 18 +#define TCPHO_MAX 0x3ffU +#define LSOPKTSIZE_MAX 0xffffU +#define MSS_MAX 0x07ffu /* MSS value */ + +#define OOB_CMD_RESET 0x00 +#define OOB_CMD_DRIVER_START 0x05 +#define OOB_CMD_DRIVER_STOP 0x06 +#define OOB_CMD_SET_IPMAC 0x41 + +#define WAKEUP_MAGIC_PACKET_NOT_SUPPORT (0) +#define WAKEUP_MAGIC_PACKET_V1 (1) +#define WAKEUP_MAGIC_PACKET_V2 (2) +#define WAKEUP_MAGIC_PACKET_V3 (3) + +//Ram Code Version +#define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0b11) +#define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0b33) +#define NIC_RAMCODE_VERSION_CFG_METHOD_4 (0x0b17) +#define NIC_RAMCODE_VERSION_CFG_METHOD_5 (0x0b55) + +//hwoptimize +#define HW_PATCH_SOC_LAN (BIT_0) +#define HW_PATCH_SAMSUNG_LAN_DONGLE (BIT_2) + +static const u16 other_q_intr_mask = (RxOK1 | RxDU1); + +void rtl8125_mdio_write(struct rtl8125_private *tp, u16 RegAddr, u16 value); +void rtl8125_mdio_prot_write(struct rtl8125_private *tp, u32 RegAddr, u32 value); +void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, u32 RegAddr, u32 value); +u32 rtl8125_mdio_read(struct rtl8125_private *tp, u16 RegAddr); +u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, u32 RegAddr); +u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, u32 RegAddr); +void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value); +void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value); +u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr); +void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); +void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); +void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 data); +void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd); +void rtl8125_init_ring_indexes(struct rtl8125_private *tp); +int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); +void rtl8125_oob_mutex_lock(struct rtl8125_private *tp); +u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len); +u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 base_address); +u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, u32 base_address); +u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type); +u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, u32 base_address); +int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); +int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, u32 base_address); +u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr); +void rtl8125_wait_txrx_fifo_empty(struct net_device *dev); +void rtl8125_enable_now_is_oob(struct rtl8125_private *tp); +void rtl8125_disable_now_is_oob(struct rtl8125_private *tp); +void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp); +void rtl8125_dash2_disable_tx(struct rtl8125_private *tp); +void rtl8125_dash2_enable_tx(struct rtl8125_private *tp); +void rtl8125_dash2_disable_rx(struct rtl8125_private *tp); +void rtl8125_dash2_enable_rx(struct rtl8125_private *tp); +void rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev); +void rtl8125_mark_to_asic(struct rtl8125_private *tp, struct RxDesc *desc, u32 rx_buf_sz); + +static inline void +rtl8125_make_unusable_by_asic(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { + ((struct RxDescV3 *)desc)->addr = RTL8125_MAGIC_NUMBER; + ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV3); + } else { + desc->addr = RTL8125_MAGIC_NUMBER; + desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); + } +} + +static inline struct RxDesc* +rtl8125_get_rxdesc(struct rtl8125_private *tp, struct RxDesc *RxDescBase, u32 const cur_rx) +{ + return (struct RxDesc*)((u8*)RxDescBase + (cur_rx * tp->RxDescLength)); +} + +static inline void +rtl8125_disable_hw_interrupt_v2(struct rtl8125_private *tp, + u32 message_id) +{ + RTL_W32(tp, IMR_V2_CLEAR_REG_8125, BIT(message_id)); +} + +static inline void +rtl8125_enable_hw_interrupt_v2(struct rtl8125_private *tp, u32 message_id) +{ + RTL_W32(tp, IMR_V2_SET_REG_8125, BIT(message_id)); +} + +int rtl8125_open(struct net_device *dev); +int rtl8125_close(struct net_device *dev); +void rtl8125_hw_config(struct net_device *dev); +void rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, u32 message_id, u8 timer_intmiti_val); +void rtl8125_set_rx_q_num(struct rtl8125_private *tp, unsigned int num_rx_queues); +void rtl8125_set_tx_q_num(struct rtl8125_private *tp, unsigned int num_tx_queues); +void rtl8125_hw_start(struct net_device *dev); +void rtl8125_hw_reset(struct net_device *dev); +void rtl8125_tx_clear(struct rtl8125_private *tp); +void rtl8125_rx_clear(struct rtl8125_private *tp); +int rtl8125_init_ring(struct net_device *dev); +void rtl8125_hw_set_rx_packet_filter(struct net_device *dev); +void rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp); +int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr); + +#ifndef ENABLE_LIB_SUPPORT +static inline void rtl8125_lib_reset_prepare(struct rtl8125_private *tp) { } +static inline void rtl8125_lib_reset_complete(struct rtl8125_private *tp) { } +#endif + +#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) +#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) +#define HW_SUPPORT_D0_SPEED_UP(_M) ((_M)->HwSuppD0SpeedUpVer > 0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) +#define netdev_mc_count(dev) ((dev)->mc_count) +#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) +#define netdev_for_each_mc_addr(mclist, dev) \ + for (mclist = dev->mc_list; mclist; mclist = mclist->next) +#endif + +#endif /* __R8125_H */ diff --git a/r8125/src/r8125_dash.h b/r8125/src/r8125_dash.h new file mode 100755 index 000000000..f86d4255a --- /dev/null +++ b/r8125/src/r8125_dash.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_R8125_DASH_H +#define _LINUX_R8125_DASH_H + +#include + +#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2 + +enum rtl_dash_cmd { + RTL_DASH_ARP_NS_OFFLOAD = 0, + RTL_DASH_SET_OOB_IPMAC, + RTL_DASH_NOTIFY_OOB, + + RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW, + RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE, + RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA, + RTL_DASH_OOB_REQ, + RTL_DASH_OOB_ACK, + RTL_DASH_DETACH_OOB_REQ, + RTL_DASH_DETACH_OOB_ACK, + + RTL_FW_SET_IPV4 = 0x10, + RTL_FW_GET_IPV4, + RTL_FW_SET_IPV6, + RTL_FW_GET_IPV6, + RTL_FW_SET_EXT_SNMP, + RTL_FW_GET_EXT_SNMP, + RTL_FW_SET_WAKEUP_PATTERN, + RTL_FW_GET_WAKEUP_PATTERN, + RTL_FW_DEL_WAKEUP_PATTERN, + + RTLT_DASH_COMMAND_INVALID, +}; + +struct rtl_dash_ip_mac { + struct sockaddr ifru_addr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; +}; + +struct rtl_dash_ioctl_struct { + __u32 cmd; + __u32 offset; + __u32 len; + union { + __u32 data; + void *data_buffer; + }; +}; + +struct settings_ipv4 { + __u32 IPv4addr; + __u32 IPv4mask; + __u32 IPv4Gateway; +}; + +struct settings_ipv6 { + __u32 reserved; + __u32 prefixLen; + __u16 IPv6addr[8]; + __u16 IPv6Gateway[8]; +}; + +struct settings_ext_snmp { + __u16 index; + __u16 oid_get_len; + __u8 oid_for_get[24]; + __u8 reserved0[26]; + __u16 value_len; + __u8 value[256]; + __u8 supported; + __u8 reserved1[27]; +}; + +struct wakeup_pattern { + __u8 index; + __u8 valid; + __u8 start; + __u8 length; + __u8 name[36]; + __u8 mask[16]; + __u8 pattern[128]; + __u32 reserved[2]; +}; + +typedef struct _RX_DASH_FROM_FW_DESC { + u16 length; + u8 statusLowByte; + u8 statusHighByte; + u32 resv; + u64 BufferAddress; +} +RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC; + +typedef struct _TX_DASH_SEND_FW_DESC { + u16 length; + u8 statusLowByte; + u8 statusHighByte; + u32 resv; + u64 BufferAddress; +} +TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC; + +typedef struct _OSOOBHdr { + u32 len; + u8 type; + u8 flag; + u8 hostReqV; + u8 res; +} +OSOOBHdr, *POSOOBHdr; + +typedef struct _RX_DASH_BUFFER_TYPE_2 { + OSOOBHdr oobhdr; + u8 RxDataBuffer[0]; +} +RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2; + +#define ALIGN_8 (0x7) +#define ALIGN_16 (0xf) +#define ALIGN_32 (0x1f) +#define ALIGN_64 (0x3f) +#define ALIGN_256 (0xff) +#define ALIGN_4096 (0xfff) + +#define OCP_REG_CONFIG0 (0x10) +#define OCP_REG_CONFIG0_REV_F (0xB8) +#define OCP_REG_DASH_POLL (0x30) +#define OCP_REG_HOST_REQ (0x34) +#define OCP_REG_DASH_REQ (0x35) +#define OCP_REG_CR (0x36) +#define OCP_REG_DMEMSTA (0x38) +#define OCP_REG_GPHYAR (0x60) + + +#define OCP_REG_CONFIG0_DASHEN BIT_15 +#define OCP_REG_CONFIG0_OOBRESET BIT_14 +#define OCP_REG_CONFIG0_APRDY BIT_13 +#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12 +#define OCP_REG_CONFIG0_DRIVERRDY BIT_11 +#define OCP_REG_CONFIG0_OOB_WDT BIT_9 +#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 +#define OCP_REG_CONFIG0_TLSEN BIT_7 + +#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0 ) +#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1 ) +#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2 ) +#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3 ) + +#define RECV_FROM_FW_BUF_SIZE (1520) +#define SEND_TO_FW_BUF_SIZE (1520) + +#define RX_DASH_FROM_FW_OWN BIT_15 +#define TX_DASH_SEND_FW_OWN BIT_15 +#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7 + +#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3) +#define TXS_EXC BIT_4 +#define TXS_LNKF BIT_5 +#define TXS_OWC BIT_6 +#define TXS_TES BIT_7 +#define TXS_UNF BIT_9 +#define TXS_LGSEN BIT_11 +#define TXS_LS BIT_12 +#define TXS_FS BIT_13 +#define TXS_EOR BIT_14 +#define TXS_OWN BIT_15 + +#define TPPool_HRDY 0x20 + +#define HostReqReg (0xC0) +#define SystemMasterDescStartAddrLow (0xF0) +#define SystemMasterDescStartAddrHigh (0xF4) +#define SystemSlaveDescStartAddrLow (0xF8) +#define SystemSlaveDescStartAddrHigh (0xFC) + +//DASH Request Type +#define WSMANREG 0x01 +#define OSPUSHDATA 0x02 + +#define RXS_OWN BIT_15 +#define RXS_EOR BIT_14 +#define RXS_FS BIT_13 +#define RXS_LS BIT_12 + +#define ISRIMR_DP_DASH_OK BIT_15 +#define ISRIMR_DP_HOST_OK BIT_13 +#define ISRIMR_DP_REQSYS_OK BIT_11 + +#define ISRIMR_DASH_INTR_EN BIT_12 +#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15 + +#define ISRIMR_DASH_TYPE2_ROK BIT_0 +#define ISRIMR_DASH_TYPE2_RDU BIT_1 +#define ISRIMR_DASH_TYPE2_TOK BIT_2 +#define ISRIMR_DASH_TYPE2_TDU BIT_3 +#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4 +#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5 +#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6 + +#define CMAC_OOB_STOP 0x25 +#define CMAC_OOB_INIT 0x26 +#define CMAC_OOB_RESET 0x2a + +#define NO_BASE_ADDRESS 0x00000000 +#define RTL8168FP_OOBMAC_BASE 0xBAF70000 +#define RTL8168FP_CMAC_IOBASE 0xBAF20000 +#define RTL8168FP_KVM_BASE 0xBAF80400 +#define CMAC_SYNC_REG 0x20 +#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98 +#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F + +/* cmac write/read MMIO register */ +#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg))) + +int rtl8125_dash_ioctl(struct net_device *dev, struct ifreq *ifr); +void HandleDashInterrupt(struct net_device *dev); +int AllocateDashShareMemory(struct net_device *dev); +void FreeAllocatedDashShareMemory(struct net_device *dev); +void DashHwInit(struct net_device *dev); + + +#endif /* _LINUX_R8125_DASH_H */ diff --git a/r8125/src/r8125_firmware.c b/r8125/src/r8125_firmware.c new file mode 100755 index 000000000..ac4ea626b --- /dev/null +++ b/r8125/src/r8125_firmware.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8168 is the Linux device driver released for Realtek Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include + +#include "r8125_firmware.h" + +enum rtl_fw_opcode { + PHY_READ = 0x0, + PHY_DATA_OR = 0x1, + PHY_DATA_AND = 0x2, + PHY_BJMPN = 0x3, + PHY_MDIO_CHG = 0x4, + PHY_CLEAR_READCOUNT = 0x7, + PHY_WRITE = 0x8, + PHY_READCOUNT_EQ_SKIP = 0x9, + PHY_COMP_EQ_SKIPN = 0xa, + PHY_COMP_NEQ_SKIPN = 0xb, + PHY_WRITE_PREVIOUS = 0xc, + PHY_SKIPN = 0xd, + PHY_DELAY_MS = 0xe, +}; + +struct fw_info { + u32 magic; + char version[RTL8125_VER_SIZE]; + __le32 fw_start; + __le32 fw_len; + u8 chksum; +} __packed; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) +#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) +#endif +#define FW_OPCODE_SIZE sizeof_field(struct rtl8125_fw_phy_action, code[0]) + +static bool rtl8125_fw_format_ok(struct rtl8125_fw *rtl_fw) +{ + const struct firmware *fw = rtl_fw->fw; + struct fw_info *fw_info = (struct fw_info *)fw->data; + struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; + + if (fw->size < FW_OPCODE_SIZE) + return false; + + if (!fw_info->magic) { + size_t i, size, start; + u8 checksum = 0; + + if (fw->size < sizeof(*fw_info)) + return false; + + for (i = 0; i < fw->size; i++) + checksum += fw->data[i]; + if (checksum != 0) + return false; + + start = le32_to_cpu(fw_info->fw_start); + if (start > fw->size) + return false; + + size = le32_to_cpu(fw_info->fw_len); + if (size > (fw->size - start) / FW_OPCODE_SIZE) + return false; + + strscpy(rtl_fw->version, fw_info->version, RTL8125_VER_SIZE); + + pa->code = (__le32 *)(fw->data + start); + pa->size = size; + } else { + if (fw->size % FW_OPCODE_SIZE) + return false; + + strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8125_VER_SIZE); + + pa->code = (__le32 *)fw->data; + pa->size = fw->size / FW_OPCODE_SIZE; + } + + return true; +} + +static bool rtl8125_fw_data_ok(struct rtl8125_fw *rtl_fw) +{ + struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; + size_t index; + + for (index = 0; index < pa->size; index++) { + u32 action = le32_to_cpu(pa->code[index]); + u32 val = action & 0x0000ffff; + u32 regno = (action & 0x0fff0000) >> 16; + + switch (action >> 28) { + case PHY_READ: + case PHY_DATA_OR: + case PHY_DATA_AND: + case PHY_CLEAR_READCOUNT: + case PHY_WRITE: + case PHY_WRITE_PREVIOUS: + case PHY_DELAY_MS: + break; + + case PHY_MDIO_CHG: + if (val > 1) + goto out; + break; + + case PHY_BJMPN: + if (regno > index) + goto out; + break; + case PHY_READCOUNT_EQ_SKIP: + if (index + 2 >= pa->size) + goto out; + break; + case PHY_COMP_EQ_SKIPN: + case PHY_COMP_NEQ_SKIPN: + case PHY_SKIPN: + if (index + 1 + regno >= pa->size) + goto out; + break; + + default: + dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); + return false; + } + } + + return true; +out: + dev_err(rtl_fw->dev, "Out of range of firmware\n"); + return false; +} + +void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw) +{ + struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; + rtl8125_fw_write_t fw_write = rtl_fw->phy_write; + rtl8125_fw_read_t fw_read = rtl_fw->phy_read; + int predata = 0, count = 0; + size_t index; + + for (index = 0; index < pa->size; index++) { + u32 action = le32_to_cpu(pa->code[index]); + u32 data = action & 0x0000ffff; + u32 regno = (action & 0x0fff0000) >> 16; + enum rtl_fw_opcode opcode = action >> 28; + + if (!action) + break; + + switch (opcode) { + case PHY_READ: + predata = fw_read(tp, regno); + count++; + break; + case PHY_DATA_OR: + predata |= data; + break; + case PHY_DATA_AND: + predata &= data; + break; + case PHY_BJMPN: + index -= (regno + 1); + break; + case PHY_MDIO_CHG: + if (data) { + fw_write = rtl_fw->mac_mcu_write; + fw_read = rtl_fw->mac_mcu_read; + } else { + fw_write = rtl_fw->phy_write; + fw_read = rtl_fw->phy_read; + } + + break; + case PHY_CLEAR_READCOUNT: + count = 0; + break; + case PHY_WRITE: + fw_write(tp, regno, data); + break; + case PHY_READCOUNT_EQ_SKIP: + if (count == data) + index++; + break; + case PHY_COMP_EQ_SKIPN: + if (predata == data) + index += regno; + break; + case PHY_COMP_NEQ_SKIPN: + if (predata != data) + index += regno; + break; + case PHY_WRITE_PREVIOUS: + fw_write(tp, regno, predata); + break; + case PHY_SKIPN: + index += regno; + break; + case PHY_DELAY_MS: + mdelay(data); + break; + } + } +} + +void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw) +{ + release_firmware(rtl_fw->fw); +} + +int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw) +{ + int rc; + + rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); + if (rc < 0) + goto out; + + if (!rtl8125_fw_format_ok(rtl_fw) || !rtl8125_fw_data_ok(rtl_fw)) { + release_firmware(rtl_fw->fw); + rc = -EINVAL; + goto out; + } + + return 0; +out: + dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", + rtl_fw->fw_name, rc); + return rc; +} diff --git a/r8125/src/r8125_firmware.h b/r8125/src/r8125_firmware.h new file mode 100755 index 000000000..1961be5d5 --- /dev/null +++ b/r8125/src/r8125_firmware.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_rtl8125_FIRMWARE_H +#define _LINUX_rtl8125_FIRMWARE_H + +#include +#include + +struct rtl8125_private; +typedef void (*rtl8125_fw_write_t)(struct rtl8125_private *tp, u16 reg, u16 val); +typedef u32 (*rtl8125_fw_read_t)(struct rtl8125_private *tp, u16 reg); + +#define RTL8125_VER_SIZE 32 + +struct rtl8125_fw { + rtl8125_fw_write_t phy_write; + rtl8125_fw_read_t phy_read; + rtl8125_fw_write_t mac_mcu_write; + rtl8125_fw_read_t mac_mcu_read; + const struct firmware *fw; + const char *fw_name; + struct device *dev; + + char version[RTL8125_VER_SIZE]; + + struct rtl8125_fw_phy_action { + __le32 *code; + size_t size; + } phy_action; +}; + +int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw); +void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw); +void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw); + +#endif /* _LINUX_rtl8125_FIRMWARE_H */ diff --git a/r8125/src/r8125_n.c b/r8125/src/r8125_n.c new file mode 100755 index 000000000..fd96e8f8e --- /dev/null +++ b/r8125/src/r8125_n.c @@ -0,0 +1,15150 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +/* + * This driver is modified from r8169.c in Linux kernel 2.6.18 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +#include +#include +#endif +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) +#include +#endif +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) +#else +#include +#include +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) +#include +#endif + +#include +#include + +#include "r8125.h" +#include "rtl_eeprom.h" +#include "rtltool.h" +#include "r8125_firmware.h" + +#ifdef ENABLE_R8125_PROCFS +#include +#include +#endif + +#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw" +#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw" + +/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + The RTL chips use a 64 element hash table based on the Ethernet CRC. */ +static const int multicast_filter_limit = 32; + +static const struct { + const char *name; + const char *fw_name; +} rtl_chip_fw_infos[] = { + /* PCI-E devices. */ + [CFG_METHOD_2] = {"RTL8125A" }, + [CFG_METHOD_3] = {"RTL8125A", FIRMWARE_8125A_3}, + [CFG_METHOD_4] = {"RTL8125B", }, + [CFG_METHOD_5] = {"RTL8125B", FIRMWARE_8125B_2}, + [CFG_METHOD_DEFAULT] = {"Unknown", }, +}; + +#define _R(NAME,MAC,RCR,MASK,JumFrameSz) \ + { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz } + +static const struct { + const char *name; + u8 mcfg; + u32 RCR_Cfg; + u32 RxConfigMask; /* Clears the bits supported by this chip */ + u32 jumbo_frame_sz; +} rtl_chip_info[] = { + _R("RTL8125A", + CFG_METHOD_2, + BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("RTL8125A", + CFG_METHOD_3, + BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("RTL8125B", + CFG_METHOD_4, + BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("RTL8125B", + CFG_METHOD_5, + BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("Unknown", + CFG_METHOD_DEFAULT, + (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_1k) +}; +#undef _R + + +#ifndef PCI_VENDOR_ID_DLINK +#define PCI_VENDOR_ID_DLINK 0x1186 +#endif + +static struct pci_device_id rtl8125_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125), }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x3000), }, + {0,}, +}; + +MODULE_DEVICE_TABLE(pci, rtl8125_pci_tbl); + +static int rx_copybreak = 0; +static int use_dac = 1; +static int timer_count = 0x2600; +static int timer_count_v2 = (0x2600 / 0x100); + +static struct { + u32 msg_enable; +} debug = { -1 }; + +static unsigned int speed_mode = SPEED_2500; +static unsigned int duplex_mode = DUPLEX_FULL; +static unsigned int autoneg_mode = AUTONEG_ENABLE; +static unsigned int advertising_mode = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_2500baseX_Full; +#ifdef CONFIG_ASPM +static int aspm = 1; +#else +static int aspm = 0; +#endif +#ifdef ENABLE_S5WOL +static int s5wol = 1; +#else +static int s5wol = 0; +#endif +#ifdef ENABLE_S5_KEEP_CURR_MAC +static int s5_keep_curr_mac = 1; +#else +static int s5_keep_curr_mac = 0; +#endif +#ifdef ENABLE_EEE +static int eee_enable = 1; +#else +static int eee_enable = 0; +#endif +#ifdef CONFIG_SOC_LAN +static ulong hwoptimize = HW_PATCH_SOC_LAN; +#else +static ulong hwoptimize = 0; +#endif +#ifdef ENABLE_S0_MAGIC_PACKET +static int s0_magic_packet = 1; +#else +static int s0_magic_packet = 0; +#endif +#ifdef ENABLE_TX_NO_CLOSE +static int tx_no_close_enable = 1; +#else +static int tx_no_close_enable = 0; +#endif +#ifdef ENABLE_PTP_MASTER_MODE +static int enable_ptp_master_mode = 1; +#else +static int enable_ptp_master_mode = 0; +#endif +#ifdef DISABLE_PM_SUPPORT +static int disable_pm_support = 1; +#else +static int disable_pm_support = 0; +#endif + +MODULE_AUTHOR("Realtek and the Linux r8125 crew "); +MODULE_DESCRIPTION("Realtek RTL8125 2.5Gigabit Ethernet driver"); + +module_param(speed_mode, uint, 0); +MODULE_PARM_DESC(speed_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(duplex_mode, uint, 0); +MODULE_PARM_DESC(duplex_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(autoneg_mode, uint, 0); +MODULE_PARM_DESC(autoneg_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(advertising_mode, uint, 0); +MODULE_PARM_DESC(advertising_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(aspm, int, 0); +MODULE_PARM_DESC(aspm, "Enable ASPM."); + +module_param(s5wol, int, 0); +MODULE_PARM_DESC(s5wol, "Enable Shutdown Wake On Lan."); + +module_param(s5_keep_curr_mac, int, 0); +MODULE_PARM_DESC(s5_keep_curr_mac, "Enable Shutdown Keep Current MAC Address."); + +module_param(rx_copybreak, int, 0); +MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); + +module_param(use_dac, int, 0); +MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); + +module_param(timer_count, int, 0); +MODULE_PARM_DESC(timer_count, "Timer Interrupt Interval."); + +module_param(eee_enable, int, 0); +MODULE_PARM_DESC(eee_enable, "Enable Energy Efficient Ethernet."); + +module_param(hwoptimize, ulong, 0); +MODULE_PARM_DESC(hwoptimize, "Enable HW optimization function."); + +module_param(s0_magic_packet, int, 0); +MODULE_PARM_DESC(s0_magic_packet, "Enable S0 Magic Packet."); + +module_param(tx_no_close_enable, int, 0); +MODULE_PARM_DESC(tx_no_close_enable, "Enable TX No Close."); + +module_param(enable_ptp_master_mode, int, 0); +MODULE_PARM_DESC(enable_ptp_master_mode, "Enable PTP Master Mode."); + +module_param(disable_pm_support, int, 0); +MODULE_PARM_DESC(disable_pm_support, "Disable PM support."); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +module_param_named(debug, debug.msg_enable, int, 0); +MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); +#endif//LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + +MODULE_LICENSE("GPL"); +#ifdef ENABLE_USE_FIRMWARE_FILE +MODULE_FIRMWARE(FIRMWARE_8125A_3); +MODULE_FIRMWARE(FIRMWARE_8125B_2); +#endif + +MODULE_VERSION(RTL8125_VERSION); + +/* +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +static void rtl8125_esd_timer(unsigned long __opaque); +#else +static void rtl8125_esd_timer(struct timer_list *t); +#endif +*/ +/* +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +static void rtl8125_link_timer(unsigned long __opaque); +#else +static void rtl8125_link_timer(struct timer_list *t); +#endif +*/ + +static netdev_tx_t rtl8125_start_xmit(struct sk_buff *skb, struct net_device *dev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +#else +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs); +#else +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance); +#endif +static void rtl8125_set_rx_mode(struct net_device *dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static void rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue); +#else +static void rtl8125_tx_timeout(struct net_device *dev); +#endif +static struct net_device_stats *rtl8125_get_stats(struct net_device *dev); +static int rtl8125_rx_interrupt(struct net_device *, struct rtl8125_private *, struct rtl8125_rx_ring *, napi_budget); +static int rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget); +static int rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, const int message_id, int budget); +static int rtl8125_change_mtu(struct net_device *dev, int new_mtu); +static void rtl8125_down(struct net_device *dev); + +static int rtl8125_set_mac_address(struct net_device *dev, void *p); +static void rtl8125_rar_set(struct rtl8125_private *tp, uint8_t *addr); +static void rtl8125_desc_addr_fill(struct rtl8125_private *); +static void rtl8125_tx_desc_init(struct rtl8125_private *tp); +static void rtl8125_rx_desc_init(struct rtl8125_private *tp); + +static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, u16 RegAddr); +static u16 rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp); +static void rtl8125_phy_power_up(struct net_device *dev); +static void rtl8125_phy_power_down(struct net_device *dev); +static int rtl8125_set_speed(struct net_device *dev, u8 autoneg, u32 speed, u8 duplex, u32 adv); +static bool rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp); +static bool rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp); + +#ifdef CONFIG_R8125_NAPI +static int rtl8125_poll(napi_ptr napi, napi_budget budget); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_reset_task(void *_data); +static void rtl8125_esd_task(void *_data); +static void rtl8125_linkchg_task(void *_data); +#else +static void rtl8125_reset_task(struct work_struct *work); +static void rtl8125_esd_task(struct work_struct *work); +static void rtl8125_linkchg_task(struct work_struct *work); +#endif +static void rtl8125_schedule_reset_work(struct rtl8125_private *tp); +static void rtl8125_schedule_esd_work(struct rtl8125_private *tp); +static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp); +static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp); +static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp); + +static inline struct device *tp_to_dev(struct rtl8125_private *tp) +{ + return &tp->pci_dev->dev; +} + +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) && \ + LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,00))) +void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, + u32 legacy_u32) +{ + bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); + dst[0] = legacy_u32; +} + +bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, + const unsigned long *src) +{ + bool retval = true; + + /* TODO: following test will soon always be true */ + if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { + __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); + + bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_fill(ext, 32); + bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); + if (bitmap_intersects(ext, src, + __ETHTOOL_LINK_MODE_MASK_NBITS)) { + /* src mask goes beyond bit 31 */ + retval = false; + } + } + *legacy_u32 = src[0]; + return retval; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) + +#ifndef LPA_1000FULL +#define LPA_1000FULL 0x0800 +#endif + +#ifndef LPA_1000HALF +#define LPA_1000HALF 0x0400 +#endif + +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) +static inline void eth_hw_addr_random(struct net_device *dev) +{ + random_ether_addr(dev->dev_addr); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#undef ethtool_ops +#define ethtool_ops _kc_ethtool_ops + +struct _kc_ethtool_ops { + int (*get_settings)(struct net_device *, struct ethtool_cmd *); + int (*set_settings)(struct net_device *, struct ethtool_cmd *); + void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); + int (*get_regs_len)(struct net_device *); + void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); + void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); + int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); + u32 (*get_msglevel)(struct net_device *); + void (*set_msglevel)(struct net_device *, u32); + int (*nway_reset)(struct net_device *); + u32 (*get_link)(struct net_device *); + int (*get_eeprom_len)(struct net_device *); + int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); + int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); + int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); + int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); + void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); + int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); + void (*get_pauseparam)(struct net_device *, + struct ethtool_pauseparam*); + int (*set_pauseparam)(struct net_device *, + struct ethtool_pauseparam*); + u32 (*get_rx_csum)(struct net_device *); + int (*set_rx_csum)(struct net_device *, u32); + u32 (*get_tx_csum)(struct net_device *); + int (*set_tx_csum)(struct net_device *, u32); + u32 (*get_sg)(struct net_device *); + int (*set_sg)(struct net_device *, u32); + u32 (*get_tso)(struct net_device *); + int (*set_tso)(struct net_device *, u32); + int (*self_test_count)(struct net_device *); + void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); + void (*get_strings)(struct net_device *, u32 stringset, u8 *); + int (*phys_id)(struct net_device *, u32); + int (*get_stats_count)(struct net_device *); + void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, + u64 *); +} *ethtool_ops = NULL; + +#undef SET_ETHTOOL_OPS +#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) + +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) +#ifndef SET_ETHTOOL_OPS +#define SET_ETHTOOL_OPS(netdev,ops) \ + ( (netdev)->ethtool_ops = (ops) ) +#endif //SET_ETHTOOL_OPS +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) + +//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) +#ifndef netif_msg_init +#define netif_msg_init _kc_netif_msg_init +/* copied from linux kernel 2.6.20 include/linux/netdevice.h */ +static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) +{ + /* use default */ + if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) + return default_msg_enable_bits; + if (debug_value == 0) /* no output */ + return 0; + /* set low N bits */ + return (1 << debug_value) - 1; +} + +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) +static inline void eth_copy_and_sum (struct sk_buff *dest, + const unsigned char *src, + int len, int base) +{ + memcpy (dest->data, src, len); +} +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) +/* copied from linux kernel 2.6.20 /include/linux/time.h */ +/* Parameters used to convert the timespec values: */ +#define MSEC_PER_SEC 1000L + +/* copied from linux kernel 2.6.20 /include/linux/jiffies.h */ +/* + * Change timeval to jiffies, trying to avoid the + * most obvious overflows.. + * + * And some not so obvious. + * + * Note that we don't want to return MAX_LONG, because + * for various timeout reasons we often end up having + * to wait "jiffies+1" in order to guarantee that we wait + * at _least_ "jiffies" - so "jiffies+1" had better still + * be positive. + */ +#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) + +/* + * Convert jiffies to milliseconds and back. + * + * Avoid unnecessary multiplications/divisions in the + * two most common HZ cases: + */ +static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) +{ +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + return (MSEC_PER_SEC / HZ) * j; +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); +#else + return (j * MSEC_PER_SEC) / HZ; +#endif +} + +static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) +{ + if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + return m * (HZ / MSEC_PER_SEC); +#else + return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; +#endif +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) + +/* copied from linux kernel 2.6.12.6 /include/linux/pm.h */ +typedef int __bitwise pci_power_t; + +/* copied from linux kernel 2.6.12.6 /include/linux/pci.h */ +typedef u32 __bitwise pm_message_t; + +#define PCI_D0 ((pci_power_t __force) 0) +#define PCI_D1 ((pci_power_t __force) 1) +#define PCI_D2 ((pci_power_t __force) 2) +#define PCI_D3hot ((pci_power_t __force) 3) +#define PCI_D3cold ((pci_power_t __force) 4) +#define PCI_POWER_ERROR ((pci_power_t __force) -1) + +/* copied from linux kernel 2.6.12.6 /drivers/pci/pci.c */ +/** + * pci_choose_state - Choose the power state of a PCI device + * @dev: PCI device to be suspended + * @state: target sleep state for the whole system. This is the value + * that is passed to suspend() function. + * + * Returns PCI power state suitable for given device and given system + * message. + */ + +pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) +{ + if (!pci_find_capability(dev, PCI_CAP_ID_PM)) + return PCI_D0; + + switch (state) { + case 0: + return PCI_D0; + case 3: + return PCI_D3hot; + default: + printk("They asked me for state %d\n", state); +// BUG(); + } + return PCI_D0; +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) +/** + * msleep_interruptible - sleep waiting for waitqueue interruptions + * @msecs: Time in milliseconds to sleep for + */ +#define msleep_interruptible _kc_msleep_interruptible +unsigned long _kc_msleep_interruptible(unsigned int msecs) +{ + unsigned long timeout = _kc_msecs_to_jiffies(msecs); + + while (timeout && !signal_pending(current)) { + set_current_state(TASK_INTERRUPTIBLE); + timeout = schedule_timeout(timeout); + } + return _kc_jiffies_to_msecs(timeout); +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) +/* copied from linux kernel 2.6.20 include/linux/sched.h */ +#ifndef __sched +#define __sched __attribute__((__section__(".sched.text"))) +#endif + +/* copied from linux kernel 2.6.20 kernel/timer.c */ +signed long __sched schedule_timeout_uninterruptible(signed long timeout) +{ + __set_current_state(TASK_UNINTERRUPTIBLE); + return schedule_timeout(timeout); +} + +/* copied from linux kernel 2.6.20 include/linux/mii.h */ +#undef if_mii +#define if_mii _kc_if_mii +static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) +{ + return (struct mii_ioctl_data *) &rq->ifr_ifru; +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) + +static u32 rtl8125_read_thermal_sensor(struct rtl8125_private *tp) +{ + u16 ts_digout; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + ts_digout = mdio_direct_read_phy_ocp(tp, 0xBD84); + ts_digout &= 0x3ff; + break; + default: + ts_digout = 0xffff; + break; + } + + return ts_digout; +} + +int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr) +{ + u32 cmd; + u32 WaitCnt; + int retval = -1; + + RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); + cmd = (u64)paddr & DMA_BIT_MASK(32); + RTL_W32(tp, CounterAddrLow, cmd); + RTL_W32(tp, CounterAddrLow, cmd | CounterDump); + + WaitCnt = 0; + while (RTL_R32(tp, CounterAddrLow) & CounterDump) { + udelay(10); + + WaitCnt++; + if (WaitCnt > 20) + break; + } + + if (WaitCnt <= 20) + retval = 0; + + return retval; +} + +#ifdef ENABLE_R8125_PROCFS +/**************************************************************************** +* -----------------------------PROCFS STUFF------------------------- +***************************************************************************** +*/ + +static struct proc_dir_entry *rtl8125_proc; +static int proc_init_num = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +static int proc_get_driver_variable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump Driver Variable\n"); + + rtnl_lock(); + + seq_puts(m, "Variable\tValue\n----------\t-----\n"); + seq_printf(m, "MODULENAME\t%s\n", MODULENAME); + seq_printf(m, "driver version\t%s\n", RTL8125_VERSION); + seq_printf(m, "mcfg\t%d\n", tp->mcfg); + seq_printf(m, "chipset\t%d\n", tp->chipset); + seq_printf(m, "chipset_name\t%s\n", rtl_chip_info[tp->chipset].name); + seq_printf(m, "mtu\t%d\n", dev->mtu); + seq_printf(m, "NUM_RX_DESC\t0x%x\n", NUM_RX_DESC); + seq_printf(m, "cur_rx0\t0x%x\n", tp->rx_ring[0].cur_rx); + seq_printf(m, "dirty_rx0\t0x%x\n", tp->rx_ring[0].dirty_rx); + seq_printf(m, "cur_rx1\t0x%x\n", tp->rx_ring[1].cur_rx); + seq_printf(m, "dirty_rx1\t0x%x\n", tp->rx_ring[1].dirty_rx); + seq_printf(m, "cur_rx2\t0x%x\n", tp->rx_ring[2].cur_rx); + seq_printf(m, "dirty_rx2\t0x%x\n", tp->rx_ring[2].dirty_rx); + seq_printf(m, "cur_rx3\t0x%x\n", tp->rx_ring[3].cur_rx); + seq_printf(m, "dirty_rx3\t0x%x\n", tp->rx_ring[3].dirty_rx); + seq_printf(m, "NUM_TX_DESC\t0x%x\n", NUM_TX_DESC); + seq_printf(m, "cur_tx0\t0x%x\n", tp->tx_ring[0].cur_tx); + seq_printf(m, "dirty_tx0\t0x%x\n", tp->tx_ring[0].dirty_tx); + seq_printf(m, "cur_tx1\t0x%x\n", tp->tx_ring[1].cur_tx); + seq_printf(m, "dirty_tx1\t0x%x\n", tp->tx_ring[1].dirty_tx); + seq_printf(m, "rx_buf_sz\t0x%x\n", tp->rx_buf_sz); + seq_printf(m, "esd_flag\t0x%x\n", tp->esd_flag); + seq_printf(m, "pci_cfg_is_read\t0x%x\n", tp->pci_cfg_is_read); + seq_printf(m, "rtl8125_rx_config\t0x%x\n", tp->rtl8125_rx_config); + seq_printf(m, "cp_cmd\t0x%x\n", tp->cp_cmd); + seq_printf(m, "intr_mask\t0x%x\n", tp->intr_mask); + seq_printf(m, "timer_intr_mask\t0x%x\n", tp->timer_intr_mask); + seq_printf(m, "wol_enabled\t0x%x\n", tp->wol_enabled); + seq_printf(m, "wol_opts\t0x%x\n", tp->wol_opts); + seq_printf(m, "efuse_ver\t0x%x\n", tp->efuse_ver); + seq_printf(m, "eeprom_type\t0x%x\n", tp->eeprom_type); + seq_printf(m, "autoneg\t0x%x\n", tp->autoneg); + seq_printf(m, "duplex\t0x%x\n", tp->duplex); + seq_printf(m, "speed\t%d\n", tp->speed); + seq_printf(m, "advertising\t0x%x\n", tp->advertising); + seq_printf(m, "eeprom_len\t0x%x\n", tp->eeprom_len); + seq_printf(m, "cur_page\t0x%x\n", tp->cur_page); + seq_printf(m, "bios_setting\t0x%x\n", tp->bios_setting); + seq_printf(m, "features\t0x%x\n", tp->features); + seq_printf(m, "org_pci_offset_99\t0x%x\n", tp->org_pci_offset_99); + seq_printf(m, "org_pci_offset_180\t0x%x\n", tp->org_pci_offset_180); + seq_printf(m, "issue_offset_99_event\t0x%x\n", tp->issue_offset_99_event); + seq_printf(m, "org_pci_offset_80\t0x%x\n", tp->org_pci_offset_80); + seq_printf(m, "org_pci_offset_81\t0x%x\n", tp->org_pci_offset_81); + seq_printf(m, "use_timer_interrrupt\t0x%x\n", tp->use_timer_interrrupt); + seq_printf(m, "HwIcVerUnknown\t0x%x\n", tp->HwIcVerUnknown); + seq_printf(m, "NotWrRamCodeToMicroP\t0x%x\n", tp->NotWrRamCodeToMicroP); + seq_printf(m, "NotWrMcuPatchCode\t0x%x\n", tp->NotWrMcuPatchCode); + seq_printf(m, "HwHasWrRamCodeToMicroP\t0x%x\n", tp->HwHasWrRamCodeToMicroP); + seq_printf(m, "sw_ram_code_ver\t0x%x\n", tp->sw_ram_code_ver); + seq_printf(m, "hw_ram_code_ver\t0x%x\n", tp->hw_ram_code_ver); + seq_printf(m, "rtk_enable_diag\t0x%x\n", tp->rtk_enable_diag); + seq_printf(m, "ShortPacketSwChecksum\t0x%x\n", tp->ShortPacketSwChecksum); + seq_printf(m, "UseSwPaddingShortPkt\t0x%x\n", tp->UseSwPaddingShortPkt); + seq_printf(m, "RequireAdcBiasPatch\t0x%x\n", tp->RequireAdcBiasPatch); + seq_printf(m, "AdcBiasPatchIoffset\t0x%x\n", tp->AdcBiasPatchIoffset); + seq_printf(m, "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n", tp->RequireAdjustUpsTxLinkPulseTiming); + seq_printf(m, "SwrCnt1msIni\t0x%x\n", tp->SwrCnt1msIni); + seq_printf(m, "HwSuppNowIsOobVer\t0x%x\n", tp->HwSuppNowIsOobVer); + seq_printf(m, "HwFiberModeVer\t0x%x\n", tp->HwFiberModeVer); + seq_printf(m, "HwFiberStat\t0x%x\n", tp->HwFiberStat); + seq_printf(m, "HwSwitchMdiToFiber\t0x%x\n", tp->HwSwitchMdiToFiber); + seq_printf(m, "NicCustLedValue\t0x%x\n", tp->NicCustLedValue); + seq_printf(m, "RequiredSecLanDonglePatch\t0x%x\n", tp->RequiredSecLanDonglePatch); + seq_printf(m, "HwSuppDashVer\t0x%x\n", tp->HwSuppDashVer); + seq_printf(m, "DASH\t0x%x\n", tp->DASH); + seq_printf(m, "dash_printer_enabled\t0x%x\n", tp->dash_printer_enabled); + seq_printf(m, "HwSuppKCPOffloadVer\t0x%x\n", tp->HwSuppKCPOffloadVer); + seq_printf(m, "speed_mode\t0x%x\n", speed_mode); + seq_printf(m, "duplex_mode\t0x%x\n", duplex_mode); + seq_printf(m, "autoneg_mode\t0x%x\n", autoneg_mode); + seq_printf(m, "advertising_mode\t0x%x\n", advertising_mode); + seq_printf(m, "aspm\t0x%x\n", aspm); + seq_printf(m, "s5wol\t0x%x\n", s5wol); + seq_printf(m, "s5_keep_curr_mac\t0x%x\n", s5_keep_curr_mac); + seq_printf(m, "eee_enable\t0x%x\n", tp->eee.eee_enabled); + seq_printf(m, "hwoptimize\t0x%lx\n", hwoptimize); + seq_printf(m, "proc_init_num\t0x%x\n", proc_init_num); + seq_printf(m, "s0_magic_packet\t0x%x\n", s0_magic_packet); + seq_printf(m, "HwSuppMagicPktVer\t0x%x\n", tp->HwSuppMagicPktVer); + seq_printf(m, "HwSuppLinkChgWakeUpVer\t0x%x\n", tp->HwSuppLinkChgWakeUpVer); + seq_printf(m, "HwSuppD0SpeedUpVer\t0x%x\n", tp->HwSuppD0SpeedUpVer); + seq_printf(m, "D0SpeedUpSpeed\t0x%x\n", tp->D0SpeedUpSpeed); + seq_printf(m, "HwSuppCheckPhyDisableModeVer\t0x%x\n", tp->HwSuppCheckPhyDisableModeVer); + seq_printf(m, "HwPkgDet\t0x%x\n", tp->HwPkgDet); + seq_printf(m, "HwSuppTxNoCloseVer\t0x%x\n", tp->HwSuppTxNoCloseVer); + seq_printf(m, "EnableTxNoClose\t0x%x\n", tp->EnableTxNoClose); + seq_printf(m, "NextHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].NextHwDesCloPtr); + seq_printf(m, "BeginHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].BeginHwDesCloPtr); + seq_printf(m, "NextHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].NextHwDesCloPtr); + seq_printf(m, "BeginHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].BeginHwDesCloPtr); + seq_printf(m, "InitRxDescType\t0x%x\n", tp->InitRxDescType); + seq_printf(m, "RxDescLength\t0x%x\n", tp->RxDescLength); + seq_printf(m, "num_rx_rings\t0x%x\n", tp->num_rx_rings); + seq_printf(m, "num_tx_rings\t0x%x\n", tp->num_tx_rings); + seq_printf(m, "tot_rx_rings\t0x%x\n", rtl8125_tot_rx_rings(tp)); + seq_printf(m, "tot_tx_rings\t0x%x\n", rtl8125_tot_tx_rings(tp)); + seq_printf(m, "EnableRss\t0x%x\n", tp->EnableRss); + seq_printf(m, "EnablePtp\t0x%x\n", tp->EnablePtp); + seq_printf(m, "ptp_master_mode\t0x%x\n", tp->ptp_master_mode); + seq_printf(m, "min_irq_nvecs\t0x%x\n", tp->min_irq_nvecs); + seq_printf(m, "irq_nvecs\t0x%x\n", tp->irq_nvecs); + seq_printf(m, "ring_lib_enabled\t0x%x\n", tp->ring_lib_enabled); + seq_printf(m, "HwSuppIsrVer\t0x%x\n", tp->HwSuppIsrVer); + seq_printf(m, "HwCurrIsrVer\t0x%x\n", tp->HwCurrIsrVer); +#ifdef ENABLE_PTP_SUPPORT + seq_printf(m, "tx_hwtstamp_timeouts\t0x%x\n", tp->tx_hwtstamp_timeouts); + seq_printf(m, "tx_hwtstamp_skipped\t0x%x\n", tp->tx_hwtstamp_skipped); +#endif + seq_printf(m, "random_mac\t0x%x\n", tp->random_mac); + seq_printf(m, "org_mac_addr\t%pM\n", tp->org_mac_addr); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + seq_printf(m, "perm_addr\t%pM\n", dev->perm_addr); +#endif + seq_printf(m, "dev_addr\t%pM\n", dev->dev_addr); + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_tally_counter(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_counters *counters; + dma_addr_t paddr; + + seq_puts(m, "\nDump Tally Counter\n"); + + rtnl_lock(); + + counters = tp->tally_vaddr; + paddr = tp->tally_paddr; + if (!counters) { + seq_puts(m, "\nDump Tally Counter Fail\n"); + goto out_unlock; + } + + rtl8125_dump_tally_counter(tp, paddr); + + seq_puts(m, "Statistics\tValue\n----------\t-----\n"); + seq_printf(m, "tx_packets\t%lld\n", le64_to_cpu(counters->tx_packets)); + seq_printf(m, "rx_packets\t%lld\n", le64_to_cpu(counters->rx_packets)); + seq_printf(m, "tx_errors\t%lld\n", le64_to_cpu(counters->tx_errors)); + seq_printf(m, "rx_errors\t%d\n", le32_to_cpu(counters->rx_errors)); + seq_printf(m, "rx_missed\t%d\n", le16_to_cpu(counters->rx_missed)); + seq_printf(m, "align_errors\t%d\n", le16_to_cpu(counters->align_errors)); + seq_printf(m, "tx_one_collision\t%d\n", le32_to_cpu(counters->tx_one_collision)); + seq_printf(m, "tx_multi_collision\t%d\n", le32_to_cpu(counters->tx_multi_collision)); + seq_printf(m, "rx_unicast\t%lld\n", le64_to_cpu(counters->rx_unicast)); + seq_printf(m, "rx_broadcast\t%lld\n", le64_to_cpu(counters->rx_broadcast)); + seq_printf(m, "rx_multicast\t%d\n", le32_to_cpu(counters->rx_multicast)); + seq_printf(m, "tx_aborted\t%d\n", le16_to_cpu(counters->tx_aborted)); + seq_printf(m, "tx_underrun\t%d\n", le16_to_cpu(counters->tx_underrun)); + + seq_printf(m, "tx_octets\t%lld\n", le64_to_cpu(counters->tx_octets)); + seq_printf(m, "rx_octets\t%lld\n", le64_to_cpu(counters->rx_octets)); + seq_printf(m, "rx_multicast64\t%lld\n", le64_to_cpu(counters->rx_multicast64)); + seq_printf(m, "tx_unicast64\t%lld\n", le64_to_cpu(counters->tx_unicast64)); + seq_printf(m, "tx_broadcast64\t%lld\n", le64_to_cpu(counters->tx_broadcast64)); + seq_printf(m, "tx_multicast64\t%lld\n", le64_to_cpu(counters->tx_multicast64)); + seq_printf(m, "tx_pause_on\t%d\n", le32_to_cpu(counters->tx_pause_on)); + seq_printf(m, "tx_pause_off\t%d\n", le32_to_cpu(counters->tx_pause_off)); + seq_printf(m, "tx_pause_all\t%d\n", le32_to_cpu(counters->tx_pause_all)); + seq_printf(m, "tx_deferred\t%d\n", le32_to_cpu(counters->tx_deferred)); + seq_printf(m, "tx_late_collision\t%d\n", le32_to_cpu(counters->tx_late_collision)); + seq_printf(m, "tx_all_collision\t%d\n", le32_to_cpu(counters->tx_all_collision)); + seq_printf(m, "tx_aborted32\t%d\n", le32_to_cpu(counters->tx_aborted32)); + seq_printf(m, "align_errors32\t%d\n", le32_to_cpu(counters->align_errors32)); + seq_printf(m, "rx_frame_too_long\t%d\n", le32_to_cpu(counters->rx_frame_too_long)); + seq_printf(m, "rx_runt\t%d\n", le32_to_cpu(counters->rx_runt)); + seq_printf(m, "rx_pause_on\t%d\n", le32_to_cpu(counters->rx_pause_on)); + seq_printf(m, "rx_pause_off\t%d\n", le32_to_cpu(counters->rx_pause_off)); + seq_printf(m, "rx_pause_all\t%d\n", le32_to_cpu(counters->rx_pause_all)); + seq_printf(m, "rx_unknown_opcode\t%d\n", le32_to_cpu(counters->rx_unknown_opcode)); + seq_printf(m, "rx_mac_error\t%d\n", le32_to_cpu(counters->rx_mac_error)); + seq_printf(m, "tx_underrun32\t%d\n", le32_to_cpu(counters->tx_underrun32)); + seq_printf(m, "rx_mac_missed\t%d\n", le32_to_cpu(counters->rx_mac_missed)); + seq_printf(m, "rx_tcam_dropped\t%d\n", le32_to_cpu(counters->rx_tcam_dropped)); + seq_printf(m, "tdu\t%d\n", le32_to_cpu(counters->tdu)); + seq_printf(m, "rdu\t%d\n", le32_to_cpu(counters->rdu)); + + seq_putc(m, '\n'); + +out_unlock: + rtnl_unlock(); + + return 0; +} + +static int proc_get_registers(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_MAC_REGS_SIZE; + u8 byte_rd; + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + seq_puts(m, "\nDump MAC Registers\n"); + seq_puts(m, "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 16 && n < max; i++, n++) { + byte_rd = readb(ioaddr + n); + seq_printf(m, "%02x ", byte_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_pcie_phy(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_EPHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump PCIE PHY\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_ephy_read(tp, n); + seq_printf(m, "%04x ", word_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_eth_phy(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_PHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump Ethernet PHY\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + seq_puts(m, "\n####################page 0##################\n "); + rtl8125_mdio_write(tp, 0x1f, 0x0000); + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_mdio_read(tp, n); + seq_printf(m, "%04x ", word_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_extended_registers(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_ERI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump Extended Registers\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); + seq_printf(m, "%08x ", dword_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_pci_registers(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_PCI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump PCI Registers\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%03x:\t", n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + seq_printf(m, "%08x ", dword_rd); + } + } + + n = 0x110; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); + n = 0x70c; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_temperature(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct rtl8125_private *tp = netdev_priv(dev); + u16 ts_digout, tj, fah; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + seq_puts(m, "\nChip Temperature\n"); + break; + default: + seq_puts(m, "\nThis Chip Does Not Support Dump Temperature\n"); + break; + } + + rtnl_lock(); + ts_digout = rtl8125_read_thermal_sensor(tp); + rtnl_unlock(); + + tj = ts_digout / 2; + if (ts_digout <= 512) { + tj = ts_digout / 2; + seq_printf(m, "Cel:%d\n", tj); + fah = tj * (9/5) + 32; + seq_printf(m, "Fah:%d\n", fah); + } else { + tj = (512 - ((ts_digout / 2) - 512)) / 2; + seq_printf(m, "Cel:-%d\n", tj); + fah = tj * (9/5) + 32; + seq_printf(m, "Fah:-%d\n", fah); + } + + seq_putc(m, '\n'); + return 0; +} +#else + +static int proc_get_driver_variable(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Driver Driver\n"); + + rtnl_lock(); + + len += snprintf(page + len, count - len, + "Variable\tValue\n----------\t-----\n"); + + len += snprintf(page + len, count - len, + "MODULENAME\t%s\n" + "driver version\t%s\n" + "mcfg\t%d\n" + "chipset\t%d\n" + "chipset_name\t%s\n" + "mtu\t%d\n" + "NUM_RX_DESC\t0x%x\n" + "cur_rx0\t0x%x\n" + "dirty_rx0\t0x%x\n" + "cur_rx1\t0x%x\n" + "dirty_rx1\t0x%x\n" + "cur_rx2\t0x%x\n" + "dirty_rx2\t0x%x\n" + "cur_rx3\t0x%x\n" + "dirty_rx3\t0x%x\n" + "NUM_TX_DESC\t0x%x\n" + "cur_tx0\t0x%x\n" + "dirty_tx0\t0x%x\n" + "cur_tx1\t0x%x\n" + "dirty_tx1\t0x%x\n" + "rx_buf_sz\t0x%x\n" + "esd_flag\t0x%x\n" + "pci_cfg_is_read\t0x%x\n" + "rtl8125_rx_config\t0x%x\n" + "cp_cmd\t0x%x\n" + "intr_mask\t0x%x\n" + "timer_intr_mask\t0x%x\n" + "wol_enabled\t0x%x\n" + "wol_opts\t0x%x\n" + "efuse_ver\t0x%x\n" + "eeprom_type\t0x%x\n" + "autoneg\t0x%x\n" + "duplex\t0x%x\n" + "speed\t%d\n" + "advertising\t0x%x\n" + "eeprom_len\t0x%x\n" + "cur_page\t0x%x\n" + "bios_setting\t0x%x\n" + "features\t0x%x\n" + "org_pci_offset_99\t0x%x\n" + "org_pci_offset_180\t0x%x\n" + "issue_offset_99_event\t0x%x\n" + "org_pci_offset_80\t0x%x\n" + "org_pci_offset_81\t0x%x\n" + "use_timer_interrrupt\t0x%x\n" + "HwIcVerUnknown\t0x%x\n" + "NotWrRamCodeToMicroP\t0x%x\n" + "NotWrMcuPatchCode\t0x%x\n" + "HwHasWrRamCodeToMicroP\t0x%x\n" + "sw_ram_code_ver\t0x%x\n" + "hw_ram_code_ver\t0x%x\n" + "rtk_enable_diag\t0x%x\n" + "ShortPacketSwChecksum\t0x%x\n" + "UseSwPaddingShortPkt\t0x%x\n" + "RequireAdcBiasPatch\t0x%x\n" + "AdcBiasPatchIoffset\t0x%x\n" + "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n" + "SwrCnt1msIni\t0x%x\n" + "HwSuppNowIsOobVer\t0x%x\n" + "HwFiberModeVer\t0x%x\n" + "HwFiberStat\t0x%x\n" + "HwSwitchMdiToFiber\t0x%x\n" + "NicCustLedValue\t0x%x\n" + "RequiredSecLanDonglePatch\t0x%x\n" + "HwSuppDashVer\t0x%x\n" + "DASH\t0x%x\n" + "dash_printer_enabled\t0x%x\n" + "HwSuppKCPOffloadVer\t0x%x\n" + "speed_mode\t0x%x\n" + "duplex_mode\t0x%x\n" + "autoneg_mode\t0x%x\n" + "advertising_mode\t0x%x\n" + "aspm\t0x%x\n" + "s5wol\t0x%x\n" + "s5_keep_curr_mac\t0x%x\n" + "eee_enable\t0x%x\n" + "hwoptimize\t0x%lx\n" + "proc_init_num\t0x%x\n" + "s0_magic_packet\t0x%x\n" + "HwSuppMagicPktVer\t0x%x\n" + "HwSuppLinkChgWakeUpVer\t0x%x\n" + "HwSuppD0SpeedUpVer\t0x%x\n" + "D0SpeedUpSpeed\t0x%x\n" + "HwSuppCheckPhyDisableModeVer\t0x%x\n" + "HwPkgDet\t0x%x\n" + "HwSuppTxNoCloseVer\t0x%x\n" + "EnableTxNoClose\t0x%x\n" + "NextHwDesCloPtr0\t0x%x\n" + "BeginHwDesCloPtr0\t0x%x\n" + "NextHwDesCloPtr1\t0x%x\n" + "BeginHwDesCloPtr1\t0x%x\n" + "InitRxDescType\t0x%x\n" + "RxDescLength\t0x%x\n" + "num_rx_rings\t0x%x\n" + "num_tx_rings\t0x%x\n" + "tot_rx_rings\t0x%x\n" + "tot_tx_rings\t0x%x\n" + "EnableRss\t0x%x\n" + "EnablePtp\t0x%x\n" + "ptp_master_mode\t0x%x\n" + "min_irq_nvecs\t0x%x\n" + "irq_nvecs\t0x%x\n" + "ring_lib_enabled\t0x%x\n" + "HwSuppIsrVer\t0x%x\n" + "HwCurrIsrVer\t0x%x\n" +#ifdef ENABLE_PTP_SUPPORT + "tx_hwtstamp_timeouts\t0x%x\n" + "tx_hwtstamp_skipped\t0x%x\n" +#endif + "random_mac\t0x%x\n" + "org_mac_addr\t%pM\n" +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + "perm_addr\t%pM\n" +#endif + "dev_addr\t%pM\n", + MODULENAME, + RTL8125_VERSION, + tp->mcfg, + tp->chipset, + rtl_chip_info[tp->chipset].name, + dev->mtu, + NUM_RX_DESC, + tp->rx_ring[0].cur_rx, + tp->rx_ring[0].dirty_rx, + tp->rx_ring[1].cur_rx, + tp->rx_ring[1].dirty_rx, + tp->rx_ring[2].cur_rx, + tp->rx_ring[2].dirty_rx, + tp->rx_ring[3].cur_rx, + tp->rx_ring[3].dirty_rx, + NUM_TX_DESC, + tp->tx_ring[0].cur_tx, + tp->tx_ring[0].dirty_tx, + tp->tx_ring[1].cur_tx, + tp->tx_ring[1].dirty_tx, + tp->rx_buf_sz, + tp->esd_flag, + tp->pci_cfg_is_read, + tp->rtl8125_rx_config, + tp->cp_cmd, + tp->intr_mask, + tp->timer_intr_mask, + tp->wol_enabled, + tp->wol_opts, + tp->efuse_ver, + tp->eeprom_type, + tp->autoneg, + tp->duplex, + tp->speed, + tp->advertising, + tp->eeprom_len, + tp->cur_page, + tp->bios_setting, + tp->features, + tp->org_pci_offset_99, + tp->org_pci_offset_180, + tp->issue_offset_99_event, + tp->org_pci_offset_80, + tp->org_pci_offset_81, + tp->use_timer_interrrupt, + tp->HwIcVerUnknown, + tp->NotWrRamCodeToMicroP, + tp->NotWrMcuPatchCode, + tp->HwHasWrRamCodeToMicroP, + tp->sw_ram_code_ver, + tp->hw_ram_code_ver, + tp->rtk_enable_diag, + tp->ShortPacketSwChecksum, + tp->UseSwPaddingShortPkt, + tp->RequireAdcBiasPatch, + tp->AdcBiasPatchIoffset, + tp->RequireAdjustUpsTxLinkPulseTiming, + tp->SwrCnt1msIni, + tp->HwSuppNowIsOobVer, + tp->HwFiberModeVer, + tp->HwFiberStat, + tp->HwSwitchMdiToFiber, + tp->NicCustLedValue, + tp->RequiredSecLanDonglePatch, + tp->HwSuppDashVer, + tp->DASH, + tp->dash_printer_enabled, + tp->HwSuppKCPOffloadVer, + speed_mode, + duplex_mode, + autoneg_mode, + advertising_mode, + aspm, + s5wol, + s5_keep_curr_mac, + tp->eee.eee_enabled, + hwoptimize, + proc_init_num, + s0_magic_packet, + tp->HwSuppMagicPktVer, + tp->HwSuppLinkChgWakeUpVer, + tp->HwSuppD0SpeedUpVer, + tp->D0SpeedUpSpeed, + tp->HwSuppCheckPhyDisableModeVer, + tp->HwPkgDet, + tp->HwSuppTxNoCloseVer, + tp->EnableTxNoClose, + tp->tx_ring[0].NextHwDesCloPtr, + tp->tx_ring[0].BeginHwDesCloPtr, + tp->tx_ring[1].NextHwDesCloPtr, + tp->tx_ring[1].BeginHwDesCloPtr, + tp->InitRxDescType, + tp->RxDescLength, + tp->num_rx_rings, + tp->num_tx_rings, + tp->tot_rx_rings, + tp->tot_tx_rings, + tp->EnableRss, + tp->EnablePtp, + tp->ptp_master_mode, + tp->min_irq_nvecs, + tp->irq_nvecs, + tp->ring_lib_enabled, + tp->HwSuppIsrVer, + tp->HwCurrIsrVer, +#ifdef ENABLE_PTP_SUPPORT + tp->tx_hwtstamp_timeouts, + tp->tx_hwtstamp_skipped, +#endif + tp->random_mac, + tp->org_mac_addr, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + dev->perm_addr, +#endif + dev->dev_addr + ); + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_tally_counter(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_counters *counters; + dma_addr_t paddr; + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Tally Counter\n"); + + rtnl_lock(); + + counters = tp->tally_vaddr; + paddr = tp->tally_paddr; + if (!counters) { + len += snprintf(page + len, count - len, + "\nDump Tally Counter Fail\n"); + goto out_unlock; + } + + rtl8125_dump_tally_counter(tp, paddr); + + len += snprintf(page + len, count - len, + "Statistics\tValue\n----------\t-----\n"); + + len += snprintf(page + len, count - len, + "tx_packets\t%lld\n" + "rx_packets\t%lld\n" + "tx_errors\t%lld\n" + "rx_errors\t%d\n" + "rx_missed\t%d\n" + "align_errors\t%d\n" + "tx_one_collision\t%d\n" + "tx_multi_collision\t%d\n" + "rx_unicast\t%lld\n" + "rx_broadcast\t%lld\n" + "rx_multicast\t%d\n" + "tx_aborted\t%d\n" + "tx_underrun\t%d\n", + + "tx_octets\t%lld\n", + "rx_octets\t%lld\n", + "rx_multicast64\t%lld\n", + "tx_unicast64\t%lld\n", + "tx_broadcast64\t%lld\n", + "tx_multicast64\t%lld\n", + "tx_pause_on\t%d\n", + "tx_pause_off\t%d\n", + "tx_pause_all\t%d\n", + "tx_deferred\t%d\n", + "tx_late_collision\t%d\n", + "tx_all_collision\t%d\n", + "tx_aborted32\t%d\n", + "align_errors32\t%d\n", + "rx_frame_too_long\t%d\n", + "rx_runt\t%d\n", + "rx_pause_on\t%d\n", + "rx_pause_off\t%d\n", + "rx_pause_all\t%d\n", + "rx_unknown_opcode\t%d\n", + "rx_mac_error\t%d\n", + "tx_underrun32\t%d\n", + "rx_mac_missed\t%d\n", + "rx_tcam_dropped\t%d\n", + "tdu\t%d\n", + "rdu\t%d\n", + le64_to_cpu(counters->tx_packets), + le64_to_cpu(counters->rx_packets), + le64_to_cpu(counters->tx_errors), + le32_to_cpu(counters->rx_errors), + le16_to_cpu(counters->rx_missed), + le16_to_cpu(counters->align_errors), + le32_to_cpu(counters->tx_one_collision), + le32_to_cpu(counters->tx_multi_collision), + le64_to_cpu(counters->rx_unicast), + le64_to_cpu(counters->rx_broadcast), + le32_to_cpu(counters->rx_multicast), + le16_to_cpu(counters->tx_aborted), + le16_to_cpu(counters->tx_underrun), + + le64_to_cpu(counters->tx_octets), + le64_to_cpu(counters->rx_octets), + le64_to_cpu(counters->rx_multicast64), + le64_to_cpu(counters->tx_unicast64), + le64_to_cpu(counters->tx_broadcast64), + le64_to_cpu(counters->tx_multicast64), + le32_to_cpu(counters->tx_pause_on), + le32_to_cpu(counters->tx_pause_off), + le32_to_cpu(counters->tx_pause_all), + le32_to_cpu(counters->tx_deferred), + le32_to_cpu(counters->tx_late_collision), + le32_to_cpu(counters->tx_all_collision), + le32_to_cpu(counters->tx_aborted32), + le32_to_cpu(counters->align_errors32), + le32_to_cpu(counters->rx_frame_too_long), + le32_to_cpu(counters->rx_runt), + le32_to_cpu(counters->rx_pause_on), + le32_to_cpu(counters->rx_pause_off), + le32_to_cpu(counters->rx_pause_all), + le32_to_cpu(counters->rx_unknown_opcode), + le32_to_cpu(counters->rx_mac_error), + le32_to_cpu(counters->tx_underrun32), + le32_to_cpu(counters->rx_mac_missed), + le32_to_cpu(counters->rx_tcam_dropped), + le32_to_cpu(counters->tdu), + le32_to_cpu(counters->rdu), + ); + + len += snprintf(page + len, count - len, "\n"); +out_unlock: + rtnl_unlock(); + + *eof = 1; + return len; +} + +static int proc_get_registers(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_MAC_REGS_SIZE; + u8 byte_rd; + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump MAC Registers\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 16 && n < max; i++, n++) { + byte_rd = readb(ioaddr + n); + len += snprintf(page + len, count - len, + "%02x ", + byte_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_pcie_phy(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_EPHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump PCIE PHY\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_ephy_read(tp, n); + len += snprintf(page + len, count - len, + "%04x ", + word_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_eth_phy(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_PHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Ethernet PHY\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + len += snprintf(page + len, count - len, + "\n####################page 0##################\n"); + rtl8125_mdio_write(tp, 0x1f, 0x0000); + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_mdio_read(tp, n); + len += snprintf(page + len, count - len, + "%04x ", + word_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_extended_registers(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_ERI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Extended Registers\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); + len += snprintf(page + len, count - len, + "%08x ", + dword_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_pci_registers(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_PCI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump PCI Registers\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%03x:\t", + n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + len += snprintf(page + len, count - len, + "%08x ", + dword_rd); + } + } + + n = 0x110; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + len += snprintf(page + len, count - len, + "\n0x%03x:\t%08x ", + n, + dword_rd); + n = 0x70c; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + len += snprintf(page + len, count - len, + "\n0x%03x:\t%08x ", + n, + dword_rd); + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_temperature(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct rtl8125_private *tp = netdev_priv(dev); + u16 ts_digout, tj, fah; + int len = 0; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + len += snprintf(page + len, count - len, + "\nChip Temperature\n"); + break; + default: + len += snprintf(page + len, count - len, + "\nThis Chip Does Not Support Dump Temperature\n"); + break; + } + + rtnl_lock(); + ts_digout = rtl8125_read_thermal_sensor(tp); + rtnl_unlock(); + + tj = ts_digout / 2; + if (ts_digout <= 512) { + tj = ts_digout / 2; + len += snprintf(page + len, count - len, + "Cel:%d\n", + tj); + fah = tj * (9/5) + 32; + len += snprintf(page + len, count - len, + "Fah:%d\n", + fah); + + } else { + tj = (512 - ((ts_digout / 2) - 512)) / 2; + len += snprintf(page + len, count - len, + "Cel:-%d\n", + tj); + fah = tj * (9/5) + 32; + len += snprintf(page + len, count - len, + "Fah:-%d\n", + fah); + } + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} +#endif +static void rtl8125_proc_module_init(void) +{ + //create /proc/net/r8125 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + rtl8125_proc = proc_mkdir(MODULENAME, init_net.proc_net); +#else + rtl8125_proc = proc_mkdir(MODULENAME, proc_net); +#endif + if (!rtl8125_proc) + dprintk("cannot create %s proc entry \n", MODULENAME); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +/* + * seq_file wrappers for procfile show routines. + */ +static int rtl8125_proc_open(struct inode *inode, struct file *file) +{ + struct net_device *dev = proc_get_parent_data(inode); + int (*show)(struct seq_file *, void *) = PDE_DATA(inode); + + return single_open(file, show, dev); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static const struct proc_ops rtl8125_proc_fops = { + .proc_open = rtl8125_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#else +static const struct file_operations rtl8125_proc_fops = { + .open = rtl8125_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +#endif + +/* + * Table of proc files we need to create. + */ +struct rtl8125_proc_file { + char name[12]; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + int (*show)(struct seq_file *, void *); +#else + int (*show)(char *, char **, off_t, int, int *, void *); +#endif +}; + +static const struct rtl8125_proc_file rtl8125_proc_files[] = { + { "driver_var", &proc_get_driver_variable }, + { "tally", &proc_get_tally_counter }, + { "registers", &proc_get_registers }, + { "pcie_phy", &proc_get_pcie_phy }, + { "eth_phy", &proc_get_eth_phy }, + { "ext_regs", &proc_get_extended_registers }, + { "pci_regs", &proc_get_pci_registers }, + { "temp", &proc_get_temperature }, + { "", NULL } +}; + +static void rtl8125_proc_init(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + const struct rtl8125_proc_file *f; + struct proc_dir_entry *dir; + + if (rtl8125_proc && !tp->proc_dir) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + dir = proc_mkdir_data(dev->name, 0, rtl8125_proc, dev); + if (!dir) { + printk("Unable to initialize /proc/net/%s/%s\n", + MODULENAME, dev->name); + return; + } + + tp->proc_dir = dir; + proc_init_num++; + + for (f = rtl8125_proc_files; f->name[0]; f++) { + if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, + &rtl8125_proc_fops, f->show)) { + printk("Unable to initialize " + "/proc/net/%s/%s/%s\n", + MODULENAME, dev->name, f->name); + return; + } + } +#else + dir = proc_mkdir(dev->name, rtl8125_proc); + if (!dir) { + printk("Unable to initialize /proc/net/%s/%s\n", + MODULENAME, dev->name); + return; + } + + tp->proc_dir = dir; + proc_init_num++; + + for (f = rtl8125_proc_files; f->name[0]; f++) { + if (!create_proc_read_entry(f->name, S_IFREG | S_IRUGO, + dir, f->show, dev)) { + printk("Unable to initialize " + "/proc/net/%s/%s/%s\n", + MODULENAME, dev->name, f->name); + return; + } + } +#endif + } +} + +static void rtl8125_proc_remove(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->proc_dir) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + remove_proc_subtree(dev->name, rtl8125_proc); + proc_init_num--; + +#else + const struct rtl8125_proc_file *f; + struct rtl8125_private *tp = netdev_priv(dev); + + for (f = rtl8125_proc_files; f->name[0]; f++) + remove_proc_entry(f->name, tp->proc_dir); + + remove_proc_entry(dev->name, rtl8125_proc); + proc_init_num--; +#endif + tp->proc_dir = NULL; + } +} + +#endif //ENABLE_R8125_PROCFS + +static inline u16 map_phy_ocp_addr(u16 PageNum, u8 RegNum) +{ + u16 OcpPageNum = 0; + u8 OcpRegNum = 0; + u16 OcpPhyAddress = 0; + + if ( PageNum == 0 ) { + OcpPageNum = OCP_STD_PHY_BASE_PAGE + ( RegNum / 8 ); + OcpRegNum = 0x10 + ( RegNum % 8 ); + } else { + OcpPageNum = PageNum; + OcpRegNum = RegNum; + } + + OcpPageNum <<= 4; + + if ( OcpRegNum < 16 ) { + OcpPhyAddress = 0; + } else { + OcpRegNum -= 16; + OcpRegNum <<= 1; + + OcpPhyAddress = OcpPageNum + OcpRegNum; + } + + + return OcpPhyAddress; +} + +static void mdio_real_direct_write_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + u32 data32; + int i; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(RegAddr % 2); +#endif + data32 = RegAddr/2; + data32 <<= OCPR_Addr_Reg_shift; + data32 |= OCPR_Write | value; + + RTL_W32(tp, PHYOCP, data32); + for (i = 0; i < 100; i++) { + udelay(1); + + if (!(RTL_R32(tp, PHYOCP) & OCPR_Flag)) + break; + } +} + +static void mdio_direct_write_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + if (tp->rtk_enable_diag) return; + + mdio_real_direct_write_phy_ocp(tp, RegAddr, value); +} + +/* +static void rtl8125_mdio_write_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr, + u32 value) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + mdio_direct_write_phy_ocp(tp, ocp_addr, value); +} +*/ + +static void rtl8125_mdio_real_write_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr, + u32 value) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + mdio_real_direct_write_phy_ocp(tp, ocp_addr, value); +} + +static void mdio_real_write(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + if (RegAddr == 0x1F) { + tp->cur_page = value; + return; + } + rtl8125_mdio_real_write_phy_ocp(tp, tp->cur_page, RegAddr, value); +} + +void rtl8125_mdio_write(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + if (tp->rtk_enable_diag) return; + + mdio_real_write(tp, RegAddr, value); +} + +void rtl8125_mdio_prot_write(struct rtl8125_private *tp, + u32 RegAddr, + u32 value) +{ + mdio_real_write(tp, RegAddr, value); +} + +void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, + u32 RegAddr, + u32 value) +{ + mdio_real_direct_write_phy_ocp(tp, RegAddr, value); +} + +static u32 mdio_real_direct_read_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr) +{ + u32 data32; + int i, value = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(RegAddr % 2); +#endif + data32 = RegAddr/2; + data32 <<= OCPR_Addr_Reg_shift; + + RTL_W32(tp, PHYOCP, data32); + for (i = 0; i < 100; i++) { + udelay(1); + + if (RTL_R32(tp, PHYOCP) & OCPR_Flag) + break; + } + value = RTL_R32(tp, PHYOCP) & OCPDR_Data_Mask; + + return value; +} + +static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr) +{ + if (tp->rtk_enable_diag) return 0xffffffff; + + return mdio_real_direct_read_phy_ocp(tp, RegAddr); +} + +/* +static u32 rtl8125_mdio_read_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + return mdio_direct_read_phy_ocp(tp, ocp_addr); +} +*/ + +static u32 rtl8125_mdio_real_read_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + return mdio_real_direct_read_phy_ocp(tp, ocp_addr); +} + +static u32 mdio_real_read(struct rtl8125_private *tp, + u16 RegAddr) +{ + return rtl8125_mdio_real_read_phy_ocp(tp, tp->cur_page, RegAddr); +} + +u32 rtl8125_mdio_read(struct rtl8125_private *tp, + u16 RegAddr) +{ + if (tp->rtk_enable_diag) return 0xffffffff; + + return mdio_real_read(tp, RegAddr); +} + +u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, + u32 RegAddr) +{ + return mdio_real_read(tp, RegAddr); +} + +u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, + u32 RegAddr) +{ + return mdio_real_direct_read_phy_ocp(tp, RegAddr); +} + +static void ClearAndSetEthPhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) +{ + u16 PhyRegValue; + + PhyRegValue = rtl8125_mdio_read(tp, addr); + PhyRegValue &= ~clearmask; + PhyRegValue |= setmask; + rtl8125_mdio_write(tp, addr, PhyRegValue); +} + +void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetEthPhyBit(tp, + addr, + mask, + 0 + ); +} + +void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetEthPhyBit(tp, + addr, + 0, + mask + ); +} + +static void ClearAndSetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 clearmask, u16 setmask) +{ + u16 PhyRegValue; + + PhyRegValue = mdio_direct_read_phy_ocp(tp, addr); + PhyRegValue &= ~clearmask; + PhyRegValue |= setmask; + mdio_direct_write_phy_ocp(tp, addr, PhyRegValue); +} + +void ClearEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) +{ + ClearAndSetEthPhyOcpBit(tp, + addr, + mask, + 0 + ); +} + +void SetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) +{ + ClearAndSetEthPhyOcpBit(tp, + addr, + 0, + mask + ); +} + +void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value) +{ + u32 data32; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(reg_addr % 2); +#endif + + data32 = reg_addr/2; + data32 <<= OCPR_Addr_Reg_shift; + data32 += value; + data32 |= OCPR_Write; + + RTL_W32(tp, MACOCP, data32); +} + +u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr) +{ + u32 data32; + u16 data16 = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(reg_addr % 2); +#endif + + data32 = reg_addr/2; + data32 <<= OCPR_Addr_Reg_shift; + + RTL_W32(tp, MACOCP, data32); + data16 = (u16)RTL_R32(tp, MACOCP); + + return data16; +} + +#ifdef ENABLE_USE_FIRMWARE_FILE +static void mac_mcu_write(struct rtl8125_private *tp, u16 reg, u16 value) +{ + if (reg == 0x1f) { + tp->ocp_base = value << 4; + return; + } + + rtl8125_mac_ocp_write(tp, tp->ocp_base + reg, value); +} + +static u32 mac_mcu_read(struct rtl8125_private *tp, u16 reg) +{ + return rtl8125_mac_ocp_read(tp, tp->ocp_base + reg); +} +#endif + +static void +ClearAndSetMcuAccessRegBit( + struct rtl8125_private *tp, + u16 addr, + u16 clearmask, + u16 setmask +) +{ + u16 PhyRegValue; + + PhyRegValue = rtl8125_mac_ocp_read(tp, addr); + PhyRegValue &= ~clearmask; + PhyRegValue |= setmask; + rtl8125_mac_ocp_write(tp, addr, PhyRegValue); +} + +static void +ClearMcuAccessRegBit( + struct rtl8125_private *tp, + u16 addr, + u16 mask +) +{ + ClearAndSetMcuAccessRegBit(tp, + addr, + mask, + 0 + ); +} + +static void +SetMcuAccessRegBit( + struct rtl8125_private *tp, + u16 addr, + u16 mask +) +{ + ClearAndSetMcuAccessRegBit(tp, + addr, + 0, + mask + ); +} + +u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, const u32 base_address) +{ + return rtl8125_eri_read_with_oob_base_address(tp, addr, len, ERIAR_OOB, base_address); +} + +u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len) +{ + u32 value = 0; + + if (HW_DASH_SUPPORT_TYPE_2(tp)) + value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, NO_BASE_ADDRESS); + else if (HW_DASH_SUPPORT_TYPE_3(tp)) + value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, RTL8168FP_OOBMAC_BASE); + + return value; +} + +u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, const u32 base_address) +{ + return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, ERIAR_OOB, base_address); +} + +void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 value) +{ + if (HW_DASH_SUPPORT_TYPE_2(tp)) + rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, NO_BASE_ADDRESS); + else if (HW_DASH_SUPPORT_TYPE_3(tp)) + rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, RTL8168FP_OOBMAC_BASE); +} + +void rtl8125_oob_mutex_lock(struct rtl8125_private *tp) +{ + u8 reg_16, reg_a0; + u32 wait_cnt_0, wait_Cnt_1; + u16 ocp_reg_mutex_ib; + u16 ocp_reg_mutex_oob; + u16 ocp_reg_mutex_prio; + + if (!tp->DASH) return; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + ocp_reg_mutex_oob = 0x110; + ocp_reg_mutex_ib = 0x114; + ocp_reg_mutex_prio = 0x11C; + break; + } + + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); + reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); + wait_cnt_0 = 0; + while(reg_16) { + reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); + if (reg_a0) { + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); + reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); + wait_Cnt_1 = 0; + while(reg_a0) { + reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); + + wait_Cnt_1++; + + if (wait_Cnt_1 > 2000) + break; + }; + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); + + } + reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); + + wait_cnt_0++; + + if (wait_cnt_0 > 2000) + break; + }; +} + +void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp) +{ + u16 ocp_reg_mutex_ib; + u16 ocp_reg_mutex_oob; + u16 ocp_reg_mutex_prio; + + if (!tp->DASH) return; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + ocp_reg_mutex_oob = 0x110; + ocp_reg_mutex_ib = 0x114; + ocp_reg_mutex_prio = 0x11C; + break; + } + + rtl8125_ocp_write(tp, ocp_reg_mutex_prio, 1, BIT_0); + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); +} + +void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd) +{ + rtl8125_eri_write(tp, 0xE8, 1, cmd, ERIAR_ExGMAC); + + rtl8125_ocp_write(tp, 0x30, 1, 0x01); +} + +static int rtl8125_check_dash(struct rtl8125_private *tp) +{ + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + if (rtl8125_ocp_read(tp, 0x128, 1) & BIT_0) + return 1; + } + + return 0; +} + +void rtl8125_dash2_disable_tx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + u16 WaitCnt; + u8 TmpUchar; + + //Disable oob Tx + RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) & ~( BIT_0 )); + WaitCnt = 0; + + //wait oob tx disable + do { + TmpUchar = RTL_CMAC_R8(tp, CMAC_IBISR0); + + if ( TmpUchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE ) { + break; + } + + udelay( 50 ); + WaitCnt++; + } while(WaitCnt < 2000); + + //Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE + RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0) | ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE); + } +} + +void rtl8125_dash2_enable_tx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) | BIT_0); + } +} + +void rtl8125_dash2_disable_rx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) & ~( BIT_0 )); + } +} + +void rtl8125_dash2_enable_rx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) | BIT_0); + } +} + +static void rtl8125_dash2_disable_txrx(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + rtl8125_dash2_disable_tx( tp ); + rtl8125_dash2_disable_rx( tp ); + } +} + +static void rtl8125_driver_start(struct rtl8125_private *tp) +{ + if (!tp->DASH) + return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + int timeout; + u32 tmp_value; + + rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_START); + tmp_value = rtl8125_ocp_read(tp, 0x30, 1); + tmp_value |= BIT_0; + rtl8125_ocp_write(tp, 0x30, 1, tmp_value); + + for (timeout = 0; timeout < 10; timeout++) { + mdelay(10); + if (rtl8125_ocp_read(tp, 0x124, 1) & BIT_0) + break; + } + } +} + +static void rtl8125_driver_stop(struct rtl8125_private *tp) +{ + if (!tp->DASH) + return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + struct net_device *dev = tp->dev; + int timeout; + u32 tmp_value; + + rtl8125_dash2_disable_txrx(dev); + + rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_STOP); + tmp_value = rtl8125_ocp_read(tp, 0x30, 1); + tmp_value |= BIT_0; + rtl8125_ocp_write(tp, 0x30, 1, tmp_value); + + for (timeout = 0; timeout < 10; timeout++) { + mdelay(10); + if (!(rtl8125_ocp_read(tp, 0x124, 1) & BIT_0)) + break; + } + } +} + +void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value) +{ + int i; + + RTL_W32(tp, EPHYAR, + EPHYAR_Write | + (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift | + (value & EPHYAR_Data_Mask)); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed EPHY write */ + if (!(RTL_R32(tp, EPHYAR) & EPHYAR_Flag)) + break; + } + + udelay(20); +} + +u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr) +{ + int i; + u16 value = 0xffff; + + RTL_W32(tp, EPHYAR, + EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed EPHY read */ + if (RTL_R32(tp, EPHYAR) & EPHYAR_Flag) { + value = (u16) (RTL_R32(tp, EPHYAR) & EPHYAR_Data_Mask); + break; + } + } + + udelay(20); + + return value; +} + +static void ClearAndSetPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) +{ + u16 EphyValue; + + EphyValue = rtl8125_ephy_read(tp, addr); + EphyValue &= ~clearmask; + EphyValue |= setmask; + rtl8125_ephy_write(tp, addr, EphyValue); +} + +static void ClearPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetPCIePhyBit( tp, + addr, + mask, + 0 + ); +} + +static void SetPCIePhyBit( struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetPCIePhyBit( tp, + addr, + 0, + mask + ); +} + +static u32 +rtl8125_csi_other_fun_read(struct rtl8125_private *tp, + u8 multi_fun_sel_bit, + u32 addr) +{ + u32 cmd; + int i; + u32 value = 0; + + cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + multi_fun_sel_bit = 0; + + if (multi_fun_sel_bit > 7) + return 0xffffffff; + + cmd |= multi_fun_sel_bit << 16; + + RTL_W32(tp, CSIAR, cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed CSI read */ + if (RTL_R32(tp, CSIAR) & CSIAR_Flag) { + value = (u32)RTL_R32(tp, CSIDR); + break; + } + } + + udelay(20); + + return value; +} + +static void +rtl8125_csi_other_fun_write(struct rtl8125_private *tp, + u8 multi_fun_sel_bit, + u32 addr, + u32 value) +{ + u32 cmd; + int i; + + RTL_W32(tp, CSIDR, value); + cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); + if (tp->mcfg == CFG_METHOD_DEFAULT) + multi_fun_sel_bit = 0; + + if ( multi_fun_sel_bit > 7 ) + return; + + cmd |= multi_fun_sel_bit << 16; + + RTL_W32(tp, CSIAR, cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed CSI write */ + if (!(RTL_R32(tp, CSIAR) & CSIAR_Flag)) + break; + } + + udelay(20); +} + +static u32 +rtl8125_csi_read(struct rtl8125_private *tp, + u32 addr) +{ + u8 multi_fun_sel_bit; + + multi_fun_sel_bit = 0; + + return rtl8125_csi_other_fun_read(tp, multi_fun_sel_bit, addr); +} + +static void +rtl8125_csi_write(struct rtl8125_private *tp, + u32 addr, + u32 value) +{ + u8 multi_fun_sel_bit; + + multi_fun_sel_bit = 0; + + rtl8125_csi_other_fun_write(tp, multi_fun_sel_bit, addr, value); +} + +static u8 +rtl8125_csi_fun0_read_byte(struct rtl8125_private *tp, + u32 addr) +{ + u8 RetVal = 0; + + if (tp->mcfg == CFG_METHOD_DEFAULT) { + struct pci_dev *pdev = tp->pci_dev; + + pci_read_config_byte(pdev, addr, &RetVal); + } else { + u32 TmpUlong; + u16 RegAlignAddr; + u8 ShiftByte; + + RegAlignAddr = addr & ~(0x3); + ShiftByte = addr & (0x3); + TmpUlong = rtl8125_csi_other_fun_read(tp, 0, addr); + TmpUlong >>= (8*ShiftByte); + RetVal = (u8)TmpUlong; + } + + udelay(20); + + return RetVal; +} + +static void +rtl8125_csi_fun0_write_byte(struct rtl8125_private *tp, + u32 addr, + u8 value) +{ + if (tp->mcfg == CFG_METHOD_DEFAULT) { + struct pci_dev *pdev = tp->pci_dev; + + pci_write_config_byte(pdev, addr, value); + } else { + u32 TmpUlong; + u16 RegAlignAddr; + u8 ShiftByte; + + RegAlignAddr = addr & ~(0x3); + ShiftByte = addr & (0x3); + TmpUlong = rtl8125_csi_other_fun_read(tp, 0, RegAlignAddr); + TmpUlong &= ~(0xFF << (8*ShiftByte)); + TmpUlong |= (value << (8*ShiftByte)); + rtl8125_csi_other_fun_write( tp, 0, RegAlignAddr, TmpUlong ); + } + + udelay(20); +} + +u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, const u32 base_address) +{ + int i, val_shift, shift = 0; + u32 value1 = 0, value2 = 0, mask; + u32 eri_cmd; + const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); + + if (len > 4 || len <= 0) + return -1; + + while (len > 0) { + val_shift = addr % ERIAR_Addr_Align; + addr = addr & ~0x3; + + eri_cmd = ERIAR_Read | + transformed_base_address | + type << ERIAR_Type_shift | + ERIAR_ByteEn << ERIAR_ByteEn_shift | + (addr & 0x0FFF); + if (addr & 0xF000) { + u32 tmp; + + tmp = addr & 0xF000; + tmp >>= 12; + eri_cmd |= (tmp << 20) & 0x00F00000; + } + + RTL_W32(tp, ERIAR, eri_cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed ERI read */ + if (RTL_R32(tp, ERIAR) & ERIAR_Flag) + break; + } + + if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + + value1 = RTL_R32(tp, ERIDR) & mask; + value2 |= (value1 >> val_shift * 8) << shift * 8; + + if (len <= 4 - val_shift) { + len = 0; + } else { + len -= (4 - val_shift); + shift = 4 - val_shift; + addr += 4; + } + } + + udelay(20); + + return value2; +} + +u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type) +{ + return rtl8125_eri_read_with_oob_base_address(tp, addr, len, type, 0); +} + +int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, const u32 base_address) +{ + int i, val_shift, shift = 0; + u32 value1 = 0, mask; + u32 eri_cmd; + const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); + + if (len > 4 || len <= 0) + return -1; + + while (len > 0) { + val_shift = addr % ERIAR_Addr_Align; + addr = addr & ~0x3; + + if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + + value1 = rtl8125_eri_read_with_oob_base_address(tp, addr, 4, type, base_address) & ~mask; + value1 |= ((value << val_shift * 8) >> shift * 8); + + RTL_W32(tp, ERIDR, value1); + + eri_cmd = ERIAR_Write | + transformed_base_address | + type << ERIAR_Type_shift | + ERIAR_ByteEn << ERIAR_ByteEn_shift | + (addr & 0x0FFF); + if (addr & 0xF000) { + u32 tmp; + + tmp = addr & 0xF000; + tmp >>= 12; + eri_cmd |= (tmp << 20) & 0x00F00000; + } + + RTL_W32(tp, ERIAR, eri_cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed ERI write */ + if (!(RTL_R32(tp, ERIAR) & ERIAR_Flag)) + break; + } + + if (len <= 4 - val_shift) { + len = 0; + } else { + len -= (4 - val_shift); + shift = 4 - val_shift; + addr += 4; + } + } + + udelay(20); + + return 0; +} + +int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type) +{ + return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, type, NO_BASE_ADDRESS); +} + +static void +rtl8125_enable_rxdvgate(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_3); + mdelay(2); + break; + } +} + +static void +rtl8125_disable_rxdvgate(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_3); + mdelay(2); + break; + } +} + +static u8 +rtl8125_is_gpio_low(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 gpio_low = FALSE; + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + if (!(rtl8125_mac_ocp_read(tp, 0xDC04) & BIT_13)) + gpio_low = TRUE; + break; + } + + if (gpio_low) + dprintk("gpio is low.\n"); + + return gpio_low; +} + +static u8 +rtl8125_is_phy_disable_mode_enabled(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 phy_disable_mode_enabled = FALSE; + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + if (RTL_R8(tp, 0xF2) & BIT_5) + phy_disable_mode_enabled = TRUE; + break; + } + + if (phy_disable_mode_enabled) + dprintk("phy disable mode enabled.\n"); + + return phy_disable_mode_enabled; +} + +static u8 +rtl8125_is_in_phy_disable_mode(struct net_device *dev) +{ + u8 in_phy_disable_mode = FALSE; + + if (rtl8125_is_phy_disable_mode_enabled(dev) && rtl8125_is_gpio_low(dev)) + in_phy_disable_mode = TRUE; + + if (in_phy_disable_mode) + dprintk("Hardware is in phy disable mode.\n"); + + return in_phy_disable_mode; +} + +static bool +rtl8125_stop_all_request(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + for (i = 0; i < 20; i++) { + udelay(10); + if (!(RTL_R8(tp, ChipCmd) & StopReq)) break; + } + + if (i == 20) + return 0; + break; + } + + return 1; +} + +void +rtl8125_wait_txrx_fifo_empty(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_stop_all_request(dev); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + for (i = 0; i < 3000; i++) { + udelay(50); + if ((RTL_R8(tp, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) == (Txfifo_empty | Rxfifo_empty)) + break; + } + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + for (i = 0; i < 3000; i++) { + udelay(50); + if ((RTL_R16(tp, IntrMitigate) & (BIT_0 | BIT_1 | BIT_8)) == (BIT_0 | BIT_1 | BIT_8)) + break; + } + break; + } +} + +#ifdef ENABLE_DASH_SUPPORT + +static inline void +rtl8125_enable_dash2_interrupt(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBIMR0, ( ISRIMR_DASH_TYPE2_ROK | ISRIMR_DASH_TYPE2_TOK | ISRIMR_DASH_TYPE2_TDU | ISRIMR_DASH_TYPE2_RDU | ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE )); + } +} + +static inline void +rtl8125_disable_dash2_interrupt(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBIMR0, 0); + } +} +#endif + +void +rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp) +{ + switch (tp->HwCurrIsrVer) { + case 2: + RTL_W32(tp, IMR_V2_SET_REG_8125, ISRIMR_V2_LINKCHG); + break; + case 1: + RTL_W32(tp, tp->imr_reg[0], LinkChg | RTL_R32(tp, tp->imr_reg[0])); + break; + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_enable_dash2_interrupt(tp); +#endif +} + +static inline void +rtl8125_enable_hw_interrupt(struct rtl8125_private *tp) +{ + switch (tp->HwCurrIsrVer) { + case 2: + RTL_W32(tp, IMR_V2_SET_REG_8125, tp->intr_mask); + break; + case 1: + RTL_W32(tp, tp->imr_reg[0], tp->intr_mask); + + if (R8125_MULTI_RX_Q(tp)) { + int i; + for (i=1; inum_rx_rings; i++) + RTL_W16(tp, tp->imr_reg[i], other_q_intr_mask); + } + break; + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_enable_dash2_interrupt(tp); +#endif +} + +static inline void rtl8125_clear_hw_isr_v2(struct rtl8125_private *tp, + u32 message_id) +{ + RTL_W32(tp, ISR_V2_8125, BIT(message_id)); +} + +static inline void +rtl8125_disable_hw_interrupt(struct rtl8125_private *tp) +{ + if (tp->HwCurrIsrVer == 2) { + RTL_W32(tp, IMR_V2_CLEAR_REG_8125, 0xFFFFFFFF); + } else { + RTL_W32(tp, tp->imr_reg[0], 0x0000); + + if (R8125_MULTI_RX_Q(tp)) { + int i; + for (i=1; inum_rx_rings; i++) + RTL_W16(tp, tp->imr_reg[i], 0); + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_disable_dash2_interrupt(tp); +#endif + } +} + +static inline void +rtl8125_switch_to_hw_interrupt(struct rtl8125_private *tp) +{ + RTL_W32(tp, TIMER_INT0_8125, 0x0000); + + rtl8125_enable_hw_interrupt(tp); +} + +static inline void +rtl8125_switch_to_timer_interrupt(struct rtl8125_private *tp) +{ + if (tp->use_timer_interrrupt) { + RTL_W32(tp, TIMER_INT0_8125, timer_count); + RTL_W32(tp, TCTR0_8125, timer_count); + RTL_W32(tp, tp->imr_reg[0], tp->timer_intr_mask); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_enable_dash2_interrupt(tp); +#endif + } else { + rtl8125_switch_to_hw_interrupt(tp); + } +} + +static void +rtl8125_irq_mask_and_ack(struct rtl8125_private *tp) +{ + rtl8125_disable_hw_interrupt(tp); + + if (tp->HwCurrIsrVer == 2) { + RTL_W32(tp, ISR_V2_8125, 0xFFFFFFFF); + } else { +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + if (tp->dash_printer_enabled) { + RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0]) & + ~(ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); + } else { + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0)); + } + } + } else { + RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); + } +#else + RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); +#endif + if (R8125_MULTI_RX_Q(tp)) { + int i; + for (i=1; inum_rx_rings; i++) + RTL_W16(tp, tp->isr_reg[i], RTL_R16(tp, tp->isr_reg[i])); + } + } +} + +static void +rtl8125_nic_reset(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); + + rtl8125_enable_rxdvgate(dev); + + rtl8125_stop_all_request(dev); + + rtl8125_wait_txrx_fifo_empty(dev); + + mdelay(2); + + /* Soft reset the chip. */ + RTL_W8(tp, ChipCmd, CmdReset); + + /* Check that the chip has finished the reset. */ + for (i = 100; i > 0; i--) { + udelay(100); + if ((RTL_R8(tp, ChipCmd) & CmdReset) == 0) + break; + } +} + +static void +rtl8125_hw_set_interrupt_type(struct rtl8125_private *tp, u8 isr_ver) +{ + u8 tmp; + + switch (tp->HwSuppIsrVer) { + case 2: + tmp = RTL_R8(tp, INT_CFG0_8125); + tmp &= ~(INT_CFG0_ENABLE_8125); + if (isr_ver == 2) + tmp |= INT_CFG0_ENABLE_8125; + RTL_W8(tp, INT_CFG0_8125, tmp); + break; + } +} + +static void +rtl8125_hw_clear_timer_int(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W32(tp, TIMER_INT0_8125, 0x0000); + RTL_W32(tp, TIMER_INT1_8125, 0x0000); + RTL_W32(tp, TIMER_INT2_8125, 0x0000); + RTL_W32(tp, TIMER_INT3_8125, 0x0000); + break; + } +} + +static void +rtl8125_hw_clear_int_miti(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + switch (tp->HwSuppIntMitiVer) { + case 3: + //IntMITI_0-IntMITI_31 + for (i=0xA00; i<0xB00; i+=4) + RTL_W32(tp, i, 0x0000); + break; + case 4: + //IntMITI_0-IntMITI_15 + for (i = 0xA00; i < 0xA80; i += 4) + RTL_W32(tp, i, 0x0000); + + RTL_W8(tp, INT_CFG0_8125, RTL_R8(tp, INT_CFG0_8125) & + ~(INT_CFG0_TIMEOUT0_BYPASS_8125 | INT_CFG0_MITIGATION_BYPASS_8125)); + + RTL_W16(tp, INT_CFG1_8125, 0x0000); + break; + } +} + +void +rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, + u32 message_id, + u8 timer_intmiti_val) +{ + switch (tp->HwSuppIntMitiVer) { + case 4: + if (message_id < R8125_MAX_RX_QUEUES_VEC_V3) //ROK + RTL_W8(tp,INT_MITI_V2_0_RX + 8 * message_id, timer_intmiti_val); + else if (message_id == 16) //TOK + RTL_W8(tp,INT_MITI_V2_0_TX, timer_intmiti_val); + else if (message_id == 18) //TOK + RTL_W8(tp,INT_MITI_V2_1_TX, timer_intmiti_val); + break; + } +} + +void +rtl8125_hw_reset(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_lib_reset_prepare(tp); + + /* Disable interrupts */ + rtl8125_irq_mask_and_ack(tp); + + rtl8125_hw_clear_timer_int(dev); + + rtl8125_nic_reset(dev); +} + +static unsigned int +rtl8125_xmii_reset_pending(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned int retval; + + rtl8125_mdio_write(tp, 0x1f, 0x0000); + retval = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; + + return retval; +} + +static unsigned int +rtl8125_xmii_link_ok(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned int retval; + + retval = (RTL_R16(tp, PHYstatus) & LinkStatus) ? 1 : 0; + + return retval; +} + +static int +rtl8125_wait_phy_reset_complete(struct rtl8125_private *tp) +{ + int i, val; + + for (i = 0; i < 2500; i++) { + val = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; + if (!val) + return 0; + + mdelay(1); + } + + return -1; +} + +static void +rtl8125_xmii_reset_enable(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (rtl8125_is_in_phy_disable_mode(dev)) { + return; + } + + rtl8125_mdio_write(tp, 0x1f, 0x0000); + rtl8125_mdio_write(tp, MII_ADVERTISE, rtl8125_mdio_read(tp, MII_ADVERTISE) & + ~(ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL)); + rtl8125_mdio_write(tp, MII_CTRL1000, rtl8125_mdio_read(tp, MII_CTRL1000) & + ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL)); + mdio_direct_write_phy_ocp(tp, 0xA5D4, mdio_direct_read_phy_ocp(tp, 0xA5D4) & ~(RTK_ADVERTISE_2500FULL)); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); + + if (rtl8125_wait_phy_reset_complete(tp) == 0) return; + + if (netif_msg_link(tp)) + printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); +} + +void +rtl8125_init_ring_indexes(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->HwSuppNumTxQueues; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + ring->dirty_tx = ring->cur_tx = 0; + ring->NextHwDesCloPtr = 0; + ring->BeginHwDesCloPtr = 0; + ring->index = i; + ring->priv = tp; + } + + for (i = 0; i < tp->HwSuppNumRxQueues; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + ring->dirty_rx = ring->cur_rx = 0; + ring->index = i; + ring->priv = tp; + } + +#ifdef ENABLE_LIB_SUPPORT + for (i = 0; i < tp->HwSuppNumTxQueues; i++) { + struct rtl8125_ring *ring = &tp->lib_tx_ring[i]; + ring->direction = RTL8125_CH_DIR_TX; + ring->queue_num = i; + ring->private = tp; + } + + for (i = 0; i < tp->HwSuppNumRxQueues; i++) { + struct rtl8125_ring *ring = &tp->lib_rx_ring[i]; + ring->direction = RTL8125_CH_DIR_RX; + ring->queue_num = i; + ring->private = tp; + } +#endif +} + +static void +rtl8125_issue_offset_99_event(struct rtl8125_private *tp) +{ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE09A, rtl8125_mac_ocp_read(tp, 0xE09A) | BIT_0); + break; + } +} + +#ifdef ENABLE_DASH_SUPPORT +static void +NICChkTypeEnableDashInterrupt(struct rtl8125_private *tp) +{ + if (tp->DASH) { + // + // even disconnected, enable 3 dash interrupt mask bits for in-band/out-band communication + // + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + rtl8125_enable_dash2_interrupt(tp); + RTL_W16(tp, IntrMask, (ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); + } + } +} +#endif + +static int rtl8125_enable_eee_plus(struct rtl8125_private *tp) +{ + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)|BIT_1); + break; + + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int rtl8125_disable_eee_plus(struct rtl8125_private *tp) +{ + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)&~BIT_1); + break; + + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static void +rtl8125_link_on_patch(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_hw_config(dev); + + if ((tp->mcfg == CFG_METHOD_2) && + netif_running(dev)) { + if (RTL_R16(tp, PHYstatus)&FullDup) + RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | (BIT_24 | BIT_25)) & ~BIT_19); + else + RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_25) & ~(BIT_19 | BIT_24)); + } + + if ((tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) && + (RTL_R8(tp, PHYstatus) & _10bps)) + rtl8125_enable_eee_plus(tp); + + rtl8125_hw_start(dev); + + netif_carrier_on(dev); + + netif_tx_wake_all_queues(dev); + + tp->phy_reg_aner = rtl8125_mdio_read(tp, MII_EXPANSION); + tp->phy_reg_anlpar = rtl8125_mdio_read(tp, MII_LPA); + tp->phy_reg_gbsr = rtl8125_mdio_read(tp, MII_STAT1000); + tp->phy_reg_status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); +} + +static void +rtl8125_link_down_patch(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->phy_reg_aner = 0; + tp->phy_reg_anlpar = 0; + tp->phy_reg_gbsr = 0; + tp->phy_reg_status_2500 = 0; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_disable_eee_plus(tp); + + netif_tx_stop_all_queues(dev); + + netif_carrier_off(dev); + + rtl8125_hw_reset(dev); + + rtl8125_tx_clear(tp); + + rtl8125_rx_clear(tp); + + rtl8125_init_ring(dev); + + rtl8125_enable_hw_linkchg_interrupt(tp); + + //rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + NICChkTypeEnableDashInterrupt(tp); + } +#endif +} + +static void +_rtl8125_check_link_status(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->link_ok(dev)) { + rtl8125_link_on_patch(dev); + + if (netif_msg_ifup(tp)) + printk(KERN_INFO PFX "%s: link up\n", dev->name); + } else { + if (netif_msg_ifdown(tp)) + printk(KERN_INFO PFX "%s: link down\n", dev->name); + + rtl8125_link_down_patch(dev); + } +} + +static void +rtl8125_check_link_status(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + _rtl8125_check_link_status(dev); + + tp->resume_not_chg_speed = 0; +} + +static void +rtl8125_link_option(u8 *aut, + u32 *spd, + u8 *dup, + u32 *adv) +{ + if ((*spd != SPEED_2500) && (*spd != SPEED_1000) && + (*spd != SPEED_100) && (*spd != SPEED_10)) + *spd = SPEED_2500; + + if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) + *dup = DUPLEX_FULL; + + if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) + *aut = AUTONEG_ENABLE; + + *adv &= (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_2500baseX_Full); + if (*adv == 0) + *adv = (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_2500baseX_Full); +} + +/* +static void +rtl8125_enable_ocp_phy_power_saving(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 val; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + val = mdio_direct_read_phy_ocp(tp, 0xC416); + if (val != 0x0050) { + rtl8125_set_phy_mcu_patch_request(tp); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0050); + rtl8125_clear_phy_mcu_patch_request(tp); + } + } +} +*/ + +static void +rtl8125_disable_ocp_phy_power_saving(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 val; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + val = mdio_direct_read_phy_ocp(tp, 0xC416); + if (val != 0x0500) { + rtl8125_set_phy_mcu_patch_request(tp); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0500); + rtl8125_clear_phy_mcu_patch_request(tp); + } + } +} + +static void +rtl8125_wait_ll_share_fifo_ready(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + for (i = 0; i < 10; i++) { + udelay(100); + if (RTL_R16(tp, 0xD2) & BIT_9) + break; + } +} + +static void +rtl8125_disable_pci_offset_99(struct rtl8125_private *tp) +{ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE032, rtl8125_mac_ocp_read(tp, 0xE032) & ~(BIT_0 | BIT_1)); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_csi_fun0_write_byte(tp, 0x99, 0x00); + break; + } +} + +static void +rtl8125_enable_pci_offset_99(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_csi_fun0_write_byte(tp, 0x99, tp->org_pci_offset_99); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); + csi_tmp &= ~(BIT_0 | BIT_1); + if (tp->org_pci_offset_99 & (BIT_5 | BIT_6)) + csi_tmp |= BIT_1; + if (tp->org_pci_offset_99 & BIT_2) + csi_tmp |= BIT_0; + rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); + break; + } +} + +static void +rtl8125_init_pci_offset_99(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xCDD0, 0x9003); + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE034); + csi_tmp |= (BIT_15 | BIT_14); + rtl8125_mac_ocp_write(tp, 0xE034, csi_tmp); + rtl8125_mac_ocp_write(tp, 0xCDD2, 0x889C); + rtl8125_mac_ocp_write(tp, 0xCDD8, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDD4, 0x8C30); + rtl8125_mac_ocp_write(tp, 0xCDDA, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDD6, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDDC, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDE8, 0x883E); + rtl8125_mac_ocp_write(tp, 0xCDEA, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDEC, 0x889C); + rtl8125_mac_ocp_write(tp, 0xCDEE, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDF0, 0x8C09); + rtl8125_mac_ocp_write(tp, 0xCDF2, 0x9003); + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); + csi_tmp |= (BIT_14); + rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE0A2); + csi_tmp |= (BIT_0); + rtl8125_mac_ocp_write(tp, 0xE0A2, csi_tmp); + break; + } + + rtl8125_enable_pci_offset_99(tp); +} + +static void +rtl8125_disable_pci_offset_180(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); + csi_tmp &= 0xFF00; + rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); + break; + } +} + +static void +rtl8125_enable_pci_offset_180(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE094); + csi_tmp &= 0x00FF; + rtl8125_mac_ocp_write(tp, 0xE094, csi_tmp); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); + csi_tmp &= 0xFF00; + csi_tmp |= BIT_2; + rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); + break; + } +} + +static void +rtl8125_init_pci_offset_180(struct rtl8125_private *tp) +{ + if (tp->org_pci_offset_180 & (BIT_0|BIT_1)) + rtl8125_enable_pci_offset_180(tp); + else + rtl8125_disable_pci_offset_180(tp); +} + +static void +rtl8125_set_pci_99_180_exit_driver_para(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_issue_offset_99_event(tp); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_disable_pci_offset_99(tp); + break; + } + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_disable_pci_offset_180(tp); + break; + } +} + +static void +rtl8125_enable_cfg9346_write(struct rtl8125_private *tp) +{ + RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) | Cfg9346_Unlock); +} + +static void +rtl8125_disable_cfg9346_write(struct rtl8125_private *tp) +{ + RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) & ~Cfg9346_Unlock); +} + +static void +rtl8125_enable_exit_l1_mask(struct rtl8125_private *tp) +{ + //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b111111, L1 Mask + SetMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); +} + +static void +rtl8125_disable_exit_l1_mask(struct rtl8125_private *tp) +{ + //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b000000, L1 Mask + ClearMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); +} + +static void +rtl8125_enable_extend_tally_couter(struct rtl8125_private *tp) +{ + switch (tp->HwSuppExtendTallyCounterVer) { + case 1: + SetMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); + break; + } +} + +static void +rtl8125_disable_extend_tally_couter(struct rtl8125_private *tp) +{ + switch (tp->HwSuppExtendTallyCounterVer) { + case 1: + ClearMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); + break; + } +} + +static void +rtl8125_hw_d3_para(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + RTL_W16(tp, RxMaxSize, RX_BUF_SIZE); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + rtl8125_disable_cfg9346_write(tp); + break; + } + + rtl8125_disable_exit_l1_mask(tp); + +#ifdef ENABLE_REALWOW_SUPPORT + rtl8125_set_realwow_d3_para(dev); +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xEA18, 0x0064); + break; + } + + rtl8125_set_pci_99_180_exit_driver_para(dev); + + /*disable ocp phy power saving*/ + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_disable_ocp_phy_power_saving(dev); + + rtl8125_disable_rxdvgate(dev); + + rtl8125_disable_extend_tally_couter(tp); +} + +static void +rtl8125_enable_magic_packet(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) | BIT_0); + break; + } +} +static void +rtl8125_disable_magic_packet(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) & ~BIT_0); + break; + } +} + +static void +rtl8125_enable_linkchg_wakeup(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppLinkChgWakeUpVer) { + case 3: + RTL_W8(tp, Config3, RTL_R8(tp, Config3) | LinkUp); + ClearAndSetMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_3 | BIT_2), (BIT_4 | BIT_1 | BIT_0)); + break; + } +} + +static void +rtl8125_disable_linkchg_wakeup(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppLinkChgWakeUpVer) { + case 3: + RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~LinkUp); + ClearMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0)); + break; + } +} + +#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) + +static u32 +rtl8125_get_hw_wol(struct rtl8125_private *tp) +{ + u8 options; + u32 csi_tmp; + u32 wol_opts = 0; + + if (disable_pm_support) + goto out; + + options = RTL_R8(tp, Config1); + if (!(options & PMEnable)) + goto out; + + options = RTL_R8(tp, Config3); + if (options & LinkUp) + wol_opts |= WAKE_PHY; + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xC0B6); + if (csi_tmp & BIT_0) + wol_opts |= WAKE_MAGIC; + break; + } + + options = RTL_R8(tp, Config5); + if (options & UWF) + wol_opts |= WAKE_UCAST; + if (options & BWF) + wol_opts |= WAKE_BCAST; + if (options & MWF) + wol_opts |= WAKE_MCAST; + +out: + return wol_opts; +} + +static void +rtl8125_enable_d0_speedup(struct rtl8125_private *tp) +{ + if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; + if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_DISABLE) return; + + if (tp->HwSuppD0SpeedUpVer == 1) { + u16 mac_ocp_data; + + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_3); + + //speed up speed + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE10A); + mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8 | BIT_7); + if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_2500) { + mac_ocp_data |= BIT_7; + } + rtl8125_mac_ocp_write(tp, 0xE10A, mac_ocp_data); + + //speed up flowcontrol + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE860); + mac_ocp_data |= (BIT_15 | BIT_14); + rtl8125_mac_ocp_write(tp, 0xE860, mac_ocp_data); + } +} + +static void +rtl8125_disable_d0_speedup(struct rtl8125_private *tp) +{ + if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; + + if (tp->HwSuppD0SpeedUpVer == 1) + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_7); +} + +static void +rtl8125_set_hw_wol(struct net_device *dev, u32 wolopts) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i,tmp; + static struct { + u32 opt; + u16 reg; + u8 mask; + } cfg[] = { + { WAKE_PHY, Config3, LinkUp }, + { WAKE_UCAST, Config5, UWF }, + { WAKE_BCAST, Config5, BWF }, + { WAKE_MCAST, Config5, MWF }, + { WAKE_ANY, Config5, LanWake }, + { WAKE_MAGIC, Config3, MagicPacket }, + }; + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + default: + tmp = ARRAY_SIZE(cfg) - 1; + + if (wolopts & WAKE_MAGIC) + rtl8125_enable_magic_packet(dev); + else + rtl8125_disable_magic_packet(dev); + break; + } + + rtl8125_enable_cfg9346_write(tp); + + for (i = 0; i < tmp; i++) { + u8 options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; + if (wolopts & cfg[i].opt) + options |= cfg[i].mask; + RTL_W8(tp, cfg[i].reg, options); + } + + switch (tp->HwSuppLinkChgWakeUpVer) { + case 3: + if (wolopts & WAKE_PHY) + rtl8125_enable_linkchg_wakeup(dev); + else + rtl8125_disable_linkchg_wakeup(dev); + break; + } + + rtl8125_disable_cfg9346_write(tp); +} + +static void +rtl8125_phy_restart_nway(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (rtl8125_is_in_phy_disable_mode(dev)) return; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); +} + +static void +rtl8125_phy_setup_force_mode(struct net_device *dev, u32 speed, u8 duplex) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 bmcr_true_force = 0; + + if (rtl8125_is_in_phy_disable_mode(dev)) return; + + if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) { + bmcr_true_force = BMCR_SPEED10; + } else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) { + bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX; + } else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) { + bmcr_true_force = BMCR_SPEED100; + } else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) { + bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX; + } else { + netif_err(tp, drv, dev, "Failed to set phy force mode!\n"); + return; + } + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, bmcr_true_force); +} + +static void +rtl8125_set_pci_pme(struct rtl8125_private *tp, int set) +{ + struct pci_dev *pdev = tp->pci_dev; + u16 pmc; + + if (!pdev->pm_cap) + return; + + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); + pmc |= PCI_PM_CTRL_PME_STATUS; + if (set) + pmc |= PCI_PM_CTRL_PME_ENABLE; + else + pmc &= ~PCI_PM_CTRL_PME_ENABLE; + pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); +} + +static void +rtl8125_set_wol_link_speed(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int auto_nego; + int giga_ctrl; + int ctrl_2500; + u32 adv; + u16 anlpar; + u16 gbsr; + u16 status_2500; + u16 aner; + + if (tp->autoneg != AUTONEG_ENABLE) + goto exit; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + + auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); + auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL + | ADVERTISE_100HALF | ADVERTISE_100FULL); + + giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); + giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); + + ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); + ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); + + aner = anlpar = gbsr = status_2500 = 0; + if (tp->link_ok(dev)) { + aner = rtl8125_mdio_read(tp, MII_EXPANSION); + anlpar = rtl8125_mdio_read(tp, MII_LPA); + gbsr = rtl8125_mdio_read(tp, MII_STAT1000); + status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); + } else { + if (netif_running(dev)) { + aner = tp->phy_reg_aner; + anlpar = tp->phy_reg_anlpar; + gbsr = tp->phy_reg_gbsr; + status_2500 = tp->phy_reg_status_2500; + } + } + + if ((aner | anlpar | gbsr | status_2500) == 0) { + int auto_nego_tmp = 0; + adv = tp->advertising; + if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) + auto_nego_tmp |= ADVERTISE_10HALF; + if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) + auto_nego_tmp |= ADVERTISE_10FULL; + if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) + auto_nego_tmp |= ADVERTISE_100HALF; + if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) + auto_nego_tmp |= ADVERTISE_100FULL; + + if (auto_nego_tmp == 0) goto exit; + + auto_nego |= auto_nego_tmp; + goto skip_check_lpa; + } + if (!(aner & EXPANSION_NWAY)) goto exit; + + adv = tp->advertising; + if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) + auto_nego |= ADVERTISE_10HALF; + else if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) + auto_nego |= ADVERTISE_10FULL; + else if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) + auto_nego |= ADVERTISE_100HALF; + else if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) + auto_nego |= ADVERTISE_100FULL; + else if (adv & ADVERTISED_1000baseT_Half && (gbsr & LPA_1000HALF)) + giga_ctrl |= ADVERTISE_1000HALF; + else if (adv & ADVERTISED_1000baseT_Full && (gbsr & LPA_1000FULL)) + giga_ctrl |= ADVERTISE_1000FULL; + else if (adv & ADVERTISED_2500baseX_Full && (status_2500 & RTK_LPA_ADVERTISE_2500FULL)) + ctrl_2500 |= RTK_ADVERTISE_2500FULL; + else + goto exit; + +skip_check_lpa: + if (tp->DASH) + auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); + +#ifdef CONFIG_DOWN_SPEED_100 + auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); +#endif + + rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); + rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); + mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); + + rtl8125_phy_restart_nway(dev); + +exit: + return; +} + +static bool +rtl8125_keep_wol_link_speed(struct net_device *dev, u8 from_suspend) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if ((from_suspend && !tp->link_ok(dev)) || + (!from_suspend && tp->resume_not_chg_speed)) + return 1; + + return 0; +} +static void +rtl8125_powerdown_pll(struct net_device *dev, u8 from_suspend) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->check_keep_link_speed = 0; + if (tp->wol_enabled == WOL_ENABLED || tp->DASH || tp->EnableKCPOffload) { + rtl8125_set_hw_wol(dev, tp->wol_opts); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) | PMSTS_En); + rtl8125_disable_cfg9346_write(tp); + } + + /* Enable the PME and clear the status */ + rtl8125_set_pci_pme(tp, 1); + + if (rtl8125_keep_wol_link_speed(dev, from_suspend)) { + if (tp->wol_opts & WAKE_PHY) + tp->check_keep_link_speed = 1; + } else { + if (HW_SUPPORT_D0_SPEED_UP(tp)) { + rtl8125_enable_d0_speedup(tp); + tp->check_keep_link_speed = 1; + } + + rtl8125_set_wol_link_speed(dev); + } + + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); + + return; + } + + if (tp->DASH) + return; + + rtl8125_phy_power_down(dev); + + if (!tp->HwIcVerUnknown) { + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~BIT_7); + break; + } + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); + break; + } +} + +static void rtl8125_powerup_pll(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | BIT_7 | BIT_6); + break; + } + + if (tp->resume_not_chg_speed) return; + + rtl8125_phy_power_up(dev); +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static void +rtl8125_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 options; + + wol->wolopts = 0; + + if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) { + wol->supported = 0; + return; + } else { + wol->supported = WAKE_ANY; + } + + options = RTL_R8(tp, Config1); + if (!(options & PMEnable)) + return; + + wol->wolopts = tp->wol_opts; +} + +static int +rtl8125_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) + return -EOPNOTSUPP; + + tp->wol_opts = wol->wolopts; + + tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; + + device_set_wakeup_enable(tp_to_dev(tp), wol->wolopts); + + return 0; +} + +static void +rtl8125_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_fw *rtl_fw = tp->rtl_fw; + + strcpy(info->driver, MODULENAME); + strcpy(info->version, RTL8125_VERSION); + strcpy(info->bus_info, pci_name(tp->pci_dev)); + info->regdump_len = R8125_REGS_DUMP_SIZE; + info->eedump_len = tp->eeprom_len; + BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); + if (rtl_fw) + strlcpy(info->fw_version, rtl_fw->version, + sizeof(info->fw_version)); +} + +static int +rtl8125_get_regs_len(struct net_device *dev) +{ + return R8125_REGS_DUMP_SIZE; +} +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +static void +rtl8125_set_d0_speedup_speed(struct rtl8125_private *tp) +{ + if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; + + tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_DISABLE; + if (tp->autoneg == AUTONEG_ENABLE) { + if (tp->speed == SPEED_2500) + tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_2500; + else if(tp->speed == SPEED_1000) + tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_1000; + } +} + +static int +rtl8125_set_speed_xmii(struct net_device *dev, + u8 autoneg, + u32 speed, + u8 duplex, + u32 adv) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int auto_nego = 0; + int giga_ctrl = 0; + int ctrl_2500 = 0; + int rc = -EINVAL; + + //Disable Giga Lite + ClearEthPhyOcpBit(tp, 0xA428, BIT_9); + ClearEthPhyOcpBit(tp, 0xA5EA, BIT_0); + + if (speed != SPEED_2500 && + (speed != SPEED_1000) && + (speed != SPEED_100) && + (speed != SPEED_10)) { + speed = SPEED_2500; + duplex = DUPLEX_FULL; + } + + giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); + giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); + ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); + ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); + + if (autoneg == AUTONEG_ENABLE) { + /*n-way force*/ + auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); + auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL | + ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + + if (adv & ADVERTISED_10baseT_Half) + auto_nego |= ADVERTISE_10HALF; + if (adv & ADVERTISED_10baseT_Full) + auto_nego |= ADVERTISE_10FULL; + if (adv & ADVERTISED_100baseT_Half) + auto_nego |= ADVERTISE_100HALF; + if (adv & ADVERTISED_100baseT_Full) + auto_nego |= ADVERTISE_100FULL; + if (adv & ADVERTISED_1000baseT_Half) + giga_ctrl |= ADVERTISE_1000HALF; + if (adv & ADVERTISED_1000baseT_Full) + giga_ctrl |= ADVERTISE_1000FULL; + if (adv & ADVERTISED_2500baseX_Full) + ctrl_2500 |= RTK_ADVERTISE_2500FULL; + + //flow control + if (dev->mtu <= ETH_DATA_LEN && tp->fcpause == rtl8125_fc_full) + auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + + tp->phy_auto_nego_reg = auto_nego; + tp->phy_1000_ctrl_reg = giga_ctrl; + + tp->phy_2500_ctrl_reg = ctrl_2500; + + rtl8125_mdio_write(tp, 0x1f, 0x0000); + rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); + rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); + mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); + rtl8125_phy_restart_nway(dev); + mdelay(20); + } else { + /*true force*/ + if (speed == SPEED_10 || speed == SPEED_100) + rtl8125_phy_setup_force_mode(dev, speed, duplex); + else + goto out; + } + + tp->autoneg = autoneg; + tp->speed = speed; + tp->duplex = duplex; + tp->advertising = adv; + + rtl8125_set_d0_speedup_speed(tp); + + rc = 0; +out: + return rc; +} + +static int +rtl8125_set_speed(struct net_device *dev, + u8 autoneg, + u32 speed, + u8 duplex, + u32 adv) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret; + + if (tp->resume_not_chg_speed) return 0; + + ret = tp->set_speed(dev, autoneg, speed, duplex, adv); + + return ret; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static int +rtl8125_set_settings(struct net_device *dev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + struct ethtool_cmd *cmd +#else + const struct ethtool_link_ksettings *cmd +#endif + ) +{ + int ret; + u8 autoneg; + u32 speed; + u8 duplex; + u32 supported, advertising; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + autoneg = cmd->autoneg; + speed = cmd->speed; + duplex = cmd->duplex; + supported = cmd->supported; + advertising = cmd->advertising; +#else + const struct ethtool_link_settings *base = &cmd->base; + autoneg = base->autoneg; + speed = base->speed; + duplex = base->duplex; + ethtool_convert_link_mode_to_legacy_u32(&supported, + cmd->link_modes.supported); + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.supported)) + supported |= ADVERTISED_2500baseX_Full; + if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.advertising)) + advertising |= ADVERTISED_2500baseX_Full; +#endif + if (advertising & ~supported) + return -EINVAL; + + ret = rtl8125_set_speed(dev, autoneg, speed, duplex, advertising); + + return ret; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +static u32 +rtl8125_get_tx_csum(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 ret; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + ret = ((dev->features & NETIF_F_IP_CSUM) != 0); +#else + ret = ((dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != 0); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + + return ret; +} + +static u32 +rtl8125_get_rx_csum(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 ret; + + ret = tp->cp_cmd & RxChkSum; + + return ret; +} + +static int +rtl8125_set_tx_csum(struct net_device *dev, + u32 data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + return -EOPNOTSUPP; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + if (data) + dev->features |= NETIF_F_IP_CSUM; + else + dev->features &= ~NETIF_F_IP_CSUM; +#else + if (data) + dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + else + dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + + return 0; +} + +static int +rtl8125_set_rx_csum(struct net_device *dev, + u32 data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + return -EOPNOTSUPP; + + if (data) + tp->cp_cmd |= RxChkSum; + else + tp->cp_cmd &= ~RxChkSum; + + RTL_W16(tp, CPlusCmd, tp->cp_cmd); + + return 0; +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +static u32 +rtl8125_rx_desc_opts1(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1; + else + return desc->opts1; +} + +static u32 +rtl8125_rx_desc_opts2(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2; + else + return desc->opts2; +} + +static void +rtl8125_clear_rx_desc_opts2(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2 = 0; + else + desc->opts2 = 0; +} + +#ifdef CONFIG_R8125_VLAN + +static inline u32 +rtl8125_tx_vlan_tag(struct rtl8125_private *tp, + struct sk_buff *skb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + return (tp->vlgrp && vlan_tx_tag_present(skb)) ? + TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) + return (vlan_tx_tag_present(skb)) ? + TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; +#else + return (skb_vlan_tag_present(skb)) ? + TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; +#endif + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + +static void +rtl8125_vlan_rx_register(struct net_device *dev, + struct vlan_group *grp) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->vlgrp = grp; + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + if (tp->vlgrp) { + tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | (EnableInnerVlan | EnableOuterVlan)) + } else { + tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(EnableInnerVlan | EnableOuterVlan)) + } + } +} + +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +static void +rtl8125_vlan_rx_kill_vid(struct net_device *dev, + unsigned short vid) +{ + struct rtl8125_private *tp = netdev_priv(dev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) + if (tp->vlgrp) + tp->vlgrp->vlan_devices[vid] = NULL; +#else + vlan_group_set_device(tp->vlgrp, vid, NULL); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + +static int +rtl8125_rx_vlan_skb(struct rtl8125_private *tp, + struct RxDesc *desc, + struct sk_buff *skb) +{ + u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); + int ret = -1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + if (tp->vlgrp && (opts2 & RxVlanTag)) { + rtl8125_rx_hwaccel_skb(skb, tp->vlgrp, + swab16(opts2 & 0xffff)); + ret = 0; + } +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + if (opts2 & RxVlanTag) + __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); +#else + if (opts2 & RxVlanTag) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); +#endif + + rtl8125_clear_rx_desc_opts2(tp, desc); + return ret; +} + +#else /* !CONFIG_R8125_VLAN */ + +static inline u32 +rtl8125_tx_vlan_tag(struct rtl8125_private *tp, + struct sk_buff *skb) +{ + return 0; +} + +static int +rtl8125_rx_vlan_skb(struct rtl8125_private *tp, + struct RxDesc *desc, + struct sk_buff *skb) +{ + return -1; +} + +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) + +static netdev_features_t rtl8125_fix_features(struct net_device *dev, + netdev_features_t features) +{ + if (dev->mtu > MSS_MAX) + features &= ~NETIF_F_ALL_TSO; + if (dev->mtu > ETH_DATA_LEN) { + features &= ~NETIF_F_ALL_TSO; + features &= ~NETIF_F_ALL_CSUM; + } +#ifndef CONFIG_R8125_VLAN + features &= ~NETIF_F_ALL_CSUM; +#endif + + return features; +} + +static int rtl8125_hw_set_features(struct net_device *dev, + netdev_features_t features) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 rx_config; + + rx_config = RTL_R32(tp, RxConfig); + if (features & NETIF_F_RXALL) { + tp->rtl8125_rx_config |= (AcceptErr | AcceptRunt); + rx_config |= (AcceptErr | AcceptRunt); + } else { + tp->rtl8125_rx_config &= ~(AcceptErr | AcceptRunt); + rx_config &= ~(AcceptErr | AcceptRunt); + } + + if (features & NETIF_F_HW_VLAN_RX) { + tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); + rx_config |= (EnableInnerVlan | EnableOuterVlan); + } else { + tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); + rx_config &= ~(EnableInnerVlan | EnableOuterVlan); + } + + RTL_W32(tp, RxConfig, rx_config); + + if (features & NETIF_F_RXCSUM) + tp->cp_cmd |= RxChkSum; + else + tp->cp_cmd &= ~RxChkSum; + + RTL_W16(tp, CPlusCmd, tp->cp_cmd); + RTL_R16(tp, CPlusCmd); + + return 0; +} + +static int rtl8125_set_features(struct net_device *dev, + netdev_features_t features) +{ + features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX; + + rtl8125_hw_set_features(dev, features); + + return 0; +} + +#endif + +static void rtl8125_gset_xmii(struct net_device *dev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + struct ethtool_cmd *cmd +#else + struct ethtool_link_ksettings *cmd +#endif + ) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 aner = tp->phy_reg_aner; + u16 anlpar = tp->phy_reg_anlpar; + u16 gbsr = tp->phy_reg_gbsr; + u16 status_2500 = tp->phy_reg_status_2500; + u32 lpa_adv = 0; + u16 status; + u8 autoneg, duplex; + u32 speed = 0; + u16 bmcr; + u32 supported, advertising; + u8 report_lpa = 0; + + supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_2500baseX_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause; + + advertising = ADVERTISED_TP; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + bmcr = rtl8125_mdio_read(tp, MII_BMCR); + + if (bmcr & BMCR_ANENABLE) { + advertising |= ADVERTISED_Autoneg; + autoneg = AUTONEG_ENABLE; + + if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) + advertising |= ADVERTISED_10baseT_Half; + if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) + advertising |= ADVERTISED_10baseT_Full; + if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) + advertising |= ADVERTISED_100baseT_Half; + if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) + advertising |= ADVERTISED_100baseT_Full; + if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) + advertising |= ADVERTISED_1000baseT_Full; + if (tp->phy_2500_ctrl_reg & RTK_ADVERTISE_2500FULL) + advertising |= ADVERTISED_2500baseX_Full; + } else { + autoneg = AUTONEG_DISABLE; + } + + status = RTL_R16(tp, PHYstatus); + if (netif_running(dev) && (status & LinkStatus)) + report_lpa = 1; + + if (report_lpa) { + /*link on*/ + if (status & _2500bpsF) + speed = SPEED_2500; + else if (status & _1000bpsF) + speed = SPEED_1000; + else if (status & _100bps) + speed = SPEED_100; + else if (status & _10bps) + speed = SPEED_10; + + if (status & TxFlowCtrl) + advertising |= ADVERTISED_Asym_Pause; + + if (status & RxFlowCtrl) + advertising |= ADVERTISED_Pause; + + duplex = ((status & (_1000bpsF | _2500bpsF)) || (status & FullDup)) ? + DUPLEX_FULL : DUPLEX_HALF; + + /*link partner*/ + if (aner & EXPANSION_NWAY) + lpa_adv |= ADVERTISED_Autoneg; + if (anlpar & LPA_10HALF) + lpa_adv |= ADVERTISED_10baseT_Half; + if (anlpar & LPA_10FULL) + lpa_adv |= ADVERTISED_10baseT_Full; + if (anlpar & LPA_100HALF) + lpa_adv |= ADVERTISED_100baseT_Half; + if (anlpar & LPA_100FULL) + lpa_adv |= ADVERTISED_100baseT_Full; + if (anlpar & LPA_PAUSE_CAP) + lpa_adv |= ADVERTISED_Pause; + if (anlpar & LPA_PAUSE_ASYM) + lpa_adv |= ADVERTISED_Asym_Pause; + if (gbsr & LPA_1000HALF) + lpa_adv |= ADVERTISED_1000baseT_Half; + if (gbsr & LPA_1000FULL) + lpa_adv |= ADVERTISED_1000baseT_Full; + if (status_2500 & RTK_LPA_ADVERTISE_2500FULL) + lpa_adv |= ADVERTISED_2500baseX_Full; + } else { + /*link down*/ + speed = SPEED_UNKNOWN; + duplex = DUPLEX_UNKNOWN; + lpa_adv = 0; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + cmd->supported = supported; + cmd->advertising = advertising; + cmd->autoneg = autoneg; + cmd->speed = speed; + cmd->duplex = duplex; + cmd->port = PORT_TP; + cmd->lp_advertising = lpa_adv; +#else + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + advertising); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, + lpa_adv); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) + if (supported & SUPPORTED_2500baseX_Full) { + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, + cmd->link_modes.supported, 0); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.supported, 1); + } + if (advertising & ADVERTISED_2500baseX_Full) { + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, + cmd->link_modes.advertising, 0); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.advertising, 1); + } + if (report_lpa) { + if (lpa_adv & ADVERTISED_2500baseX_Full) { + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, + cmd->link_modes.lp_advertising, 0); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.lp_advertising, 1); + } + if (status_2500 & RTK_LPA_ADVERTISE_5000FULL) + linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + cmd->link_modes.lp_advertising, 1); + if (status_2500 & RTK_LPA_ADVERTISE_10000FULL) + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + cmd->link_modes.lp_advertising, 1); + } +#endif + cmd->base.autoneg = autoneg; + cmd->base.speed = speed; + cmd->base.duplex = duplex; + cmd->base.port = PORT_TP; +#endif +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static int +rtl8125_get_settings(struct net_device *dev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + struct ethtool_cmd *cmd +#else + struct ethtool_link_ksettings *cmd +#endif + ) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->get_settings(dev, cmd); + + return 0; +} + +static void rtl8125_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + unsigned int i; + u8 *data = p; + + if (regs->len < R8125_REGS_DUMP_SIZE) + return /* -EINVAL */; + + memset(p, 0, regs->len); + + for (i = 0; i < R8125_MAC_REGS_SIZE; i++) + *data++ = readb(ioaddr + i); + data = (u8*)p + 256; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + for (i = 0; i < R8125_PHY_REGS_SIZE/2; i++) { + *(u16*)data = rtl8125_mdio_read(tp, i); + data += 2; + } + data = (u8*)p + 256 * 2; + + for (i = 0; i < R8125_EPHY_REGS_SIZE/2; i++) { + *(u16*)data = rtl8125_ephy_read(tp, i); + data += 2; + } + data = (u8*)p + 256 * 3; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + for (i = 0; i < R8125_ERI_REGS_SIZE; i+=4) { + *(u32*)data = rtl8125_eri_read(tp, i , 4, ERIAR_ExGMAC); + data += 4; + } + break; + } +} + +static void rtl8125_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + pause->autoneg = (tp->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + if (tp->fcpause == rtl8125_fc_rx_pause) + pause->rx_pause = 1; + else if (tp->fcpause == rtl8125_fc_tx_pause) + pause->tx_pause = 1; + else if (tp->fcpause == rtl8125_fc_full) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } +} + +static int rtl8125_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct rtl8125_private *tp = netdev_priv(dev); + enum rtl8125_fc_mode newfc; + + if (pause->tx_pause || pause->rx_pause) + newfc = rtl8125_fc_full; + else + newfc = rtl8125_fc_none; + + if (tp->fcpause != newfc) { + tp->fcpause = newfc; + + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + } + + return 0; + +} + +static u32 +rtl8125_get_msglevel(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + return tp->msg_enable; +} + +static void +rtl8125_set_msglevel(struct net_device *dev, + u32 value) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->msg_enable = value; +} + +static const char rtl8125_gstrings[][ETH_GSTRING_LEN] = { + /* legacy */ + "tx_packets", + "rx_packets", + "tx_errors", + "rx_errors", + "rx_missed", + "align_errors", + "tx_single_collisions", + "tx_multi_collisions", + "unicast", + "broadcast", + "multicast", + "tx_aborted", + "tx_underrun", + + /* extended */ + "tx_octets", + "rx_octets", + "rx_multicast64", + "tx_unicast64", + "tx_broadcast64", + "tx_multicast64", + "tx_pause_on", + "tx_pause_off", + "tx_pause_all", + "tx_deferred", + "tx_late_collision", + "tx_all_collision", + "tx_aborted32", + "align_errors32", + "rx_frame_too_long", + "rx_runt", + "rx_pause_on", + "rx_pause_off", + "rx_pause_all", + "rx_unknown_opcode", + "rx_mac_error", + "tx_underrun32", + "rx_mac_missed", + "rx_tcam_dropped", + "tdu", + "rdu", +}; +#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static int rtl8125_get_stats_count(struct net_device *dev) +{ + return ARRAY_SIZE(rtl8125_gstrings); +} +#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +#else +static int rtl8125_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(rtl8125_gstrings); + default: + return -EOPNOTSUPP; + } +} +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static void +rtl8125_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_counters *counters; + dma_addr_t paddr; + + ASSERT_RTNL(); + + counters = tp->tally_vaddr; + paddr = tp->tally_paddr; + if (!counters) + return; + + rtl8125_dump_tally_counter(tp, paddr); + + data[0] = le64_to_cpu(counters->tx_packets); + data[1] = le64_to_cpu(counters->rx_packets); + data[2] = le64_to_cpu(counters->tx_errors); + data[3] = le32_to_cpu(counters->rx_errors); + data[4] = le16_to_cpu(counters->rx_missed); + data[5] = le16_to_cpu(counters->align_errors); + data[6] = le32_to_cpu(counters->tx_one_collision); + data[7] = le32_to_cpu(counters->tx_multi_collision); + data[8] = le64_to_cpu(counters->rx_unicast); + data[9] = le64_to_cpu(counters->rx_broadcast); + data[10] = le32_to_cpu(counters->rx_multicast); + data[11] = le16_to_cpu(counters->tx_aborted); + data[12] = le16_to_cpu(counters->tx_underrun); + + data[13] = le64_to_cpu(counters->tx_octets); + data[14] = le64_to_cpu(counters->rx_octets); + data[15] = le64_to_cpu(counters->rx_multicast64); + data[16] = le64_to_cpu(counters->tx_unicast64); + data[17] = le64_to_cpu(counters->tx_broadcast64); + data[18] = le64_to_cpu(counters->tx_multicast64); + data[19] = le32_to_cpu(counters->tx_pause_on); + data[20] = le32_to_cpu(counters->tx_pause_off); + data[21] = le32_to_cpu(counters->tx_pause_all); + data[22] = le32_to_cpu(counters->tx_deferred); + data[23] = le32_to_cpu(counters->tx_late_collision); + data[24] = le32_to_cpu(counters->tx_all_collision); + data[25] = le32_to_cpu(counters->tx_aborted32); + data[26] = le32_to_cpu(counters->align_errors32); + data[27] = le32_to_cpu(counters->rx_frame_too_long); + data[28] = le32_to_cpu(counters->rx_runt); + data[29] = le32_to_cpu(counters->rx_pause_on); + data[30] = le32_to_cpu(counters->rx_pause_off); + data[31] = le32_to_cpu(counters->rx_pause_all); + data[32] = le32_to_cpu(counters->rx_unknown_opcode); + data[33] = le32_to_cpu(counters->rx_mac_error); + data[34] = le32_to_cpu(counters->tx_underrun32); + data[35] = le32_to_cpu(counters->rx_mac_missed); + data[36] = le32_to_cpu(counters->rx_tcam_dropped); + data[37] = le32_to_cpu(counters->tdu); + data[38] = le32_to_cpu(counters->rdu); +} + +static void +rtl8125_get_strings(struct net_device *dev, + u32 stringset, + u8 *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *rtl8125_gstrings, sizeof(rtl8125_gstrings)); + break; + } +} +#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +static int rtl_get_eeprom_len(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + return tp->eeprom_len; +} + +static int rtl_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i,j,ret; + int start_w, end_w; + int VPD_addr, VPD_data; + u32 *eeprom_buff; + u16 tmp; + + if (tp->eeprom_type == EEPROM_TYPE_NONE) { + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Detect none EEPROM\n"); + return -EOPNOTSUPP; + } else if (eeprom->len == 0 || (eeprom->offset+eeprom->len) > tp->eeprom_len) { + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Invalid parameter\n"); + return -EINVAL; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + VPD_addr = 0xD2; + VPD_data = 0xD4; + break; + } + + start_w = eeprom->offset >> 2; + end_w = (eeprom->offset + eeprom->len - 1) >> 2; + + eeprom_buff = kmalloc(sizeof(u32)*(end_w - start_w + 1), GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + rtl8125_enable_cfg9346_write(tp); + ret = -EFAULT; + for (i=start_w; i<=end_w; i++) { + pci_write_config_word(tp->pci_dev, VPD_addr, (u16)i*4); + ret = -EFAULT; + for (j = 0; j < 10; j++) { + udelay(400); + pci_read_config_word(tp->pci_dev, VPD_addr, &tmp); + if (tmp&0x8000) { + ret = 0; + break; + } + } + + if (ret) + break; + + pci_read_config_dword(tp->pci_dev, VPD_data, &eeprom_buff[i-start_w]); + } + rtl8125_disable_cfg9346_write(tp); + + if (!ret) + memcpy(buf, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); + + kfree(eeprom_buff); + + return ret; +} + +#undef ethtool_op_get_link +#define ethtool_op_get_link _kc_ethtool_op_get_link +static u32 _kc_ethtool_op_get_link(struct net_device *dev) +{ + return netif_carrier_ok(dev) ? 1 : 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +#undef ethtool_op_get_sg +#define ethtool_op_get_sg _kc_ethtool_op_get_sg +static u32 _kc_ethtool_op_get_sg(struct net_device *dev) +{ +#ifdef NETIF_F_SG + return (dev->features & NETIF_F_SG) != 0; +#else + return 0; +#endif +} + +#undef ethtool_op_set_sg +#define ethtool_op_set_sg _kc_ethtool_op_set_sg +static int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + return -EOPNOTSUPP; + +#ifdef NETIF_F_SG + if (data) + dev->features |= NETIF_F_SG; + else + dev->features &= ~NETIF_F_SG; +#endif + + return 0; +} +#endif + +static int rtl8125_enable_eee(struct rtl8125_private *tp) +{ + struct ethtool_eee *eee = &tp->eee; + u16 eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); + + SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + SetMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); + + SetEthPhyOcpBit(tp, 0xA432, BIT_4); + SetEthPhyOcpBit(tp, 0xA5D0, eee_adv_t); + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); + + SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + + SetEthPhyOcpBit(tp, 0xA5D0, eee_adv_t); + if (eee->advertised & SUPPORTED_2500baseX_Full) + SetEthPhyOcpBit(tp, 0xA6D4, BIT_0); + else + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); + ret = -EOPNOTSUPP; + break; + } + + /*Advanced EEE*/ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_set_phy_mcu_patch_request(tp); + ClearMcuAccessRegBit(tp, 0xE052, BIT_0); + ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); + ClearEthPhyOcpBit(tp, 0xA430, BIT_15); + rtl8125_clear_phy_mcu_patch_request(tp); + break; + } + + return ret; +} + +static int rtl8125_disable_eee(struct rtl8125_private *tp) +{ + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + ClearMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); + + ClearEthPhyOcpBit(tp, 0xA432, BIT_4); + ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + + ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); + ret = -EOPNOTSUPP; + break; + } + + /*Advanced EEE*/ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_set_phy_mcu_patch_request(tp); + ClearMcuAccessRegBit(tp, 0xE052, BIT_0); + ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); + ClearEthPhyOcpBit(tp, 0xA430, BIT_15); + rtl8125_clear_phy_mcu_patch_request(tp); + break; + } + + return ret; +} + +static int rtl_nway_reset(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret, bmcr; + + if (unlikely(tp->rtk_enable_diag)) + return -EBUSY; + + /* if autoneg is off, it's an error */ + rtl8125_mdio_write(tp, 0x1F, 0x0000); + bmcr = rtl8125_mdio_read(tp, MII_BMCR); + + if (bmcr & BMCR_ANENABLE) { + bmcr |= BMCR_ANRESTART; + rtl8125_mdio_write(tp, MII_BMCR, bmcr); + ret = 0; + } else { + ret = -EINVAL; + } + + return ret; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +static u32 +rtl8125_tx_lpi_timer_to_us(struct rtl8125_private *tp , u32 tx_lpi_timer) +{ + u32 to_us; + u16 status; + + //2.5G : tx_lpi_timer * 3.2ns + //Giga: tx_lpi_timer * 8ns + //100M : tx_lpi_timer * 80ns + to_us = tx_lpi_timer * 80; + status = RTL_R16(tp, PHYstatus); + if (status & LinkStatus) { + /*link on*/ + if (status & _2500bpsF) + to_us = (tx_lpi_timer * 32) / 10; + else if (status & _1000bpsF) + to_us = tx_lpi_timer * 8; + } + + //ns to us + to_us /= 1000; + + return to_us; +} + +static int +rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) +{ + struct rtl8125_private *tp = netdev_priv(net); + struct ethtool_eee *eee = &tp->eee; + u32 lp, adv, tx_lpi_timer, supported = 0; + u16 val; + + if (unlikely(tp->rtk_enable_diag)) + return -EBUSY; + + /* Get Supported EEE */ + //val = mdio_direct_read_phy_ocp(tp, 0xA5C4); + //supported = mmd_eee_cap_to_ethtool_sup_t(val); + supported = eee->supported; + + /* Get advertisement EEE */ + val = mdio_direct_read_phy_ocp(tp, 0xA5D0); + adv = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Get LP advertisement EEE */ + val = mdio_direct_read_phy_ocp(tp, 0xA5D2); + lp = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Get EEE Tx LPI timer*/ + tx_lpi_timer = RTL_R16(tp, EEE_TXIDLE_TIMER_8125); + + val = rtl8125_mac_ocp_read(tp, 0xE040); + val &= BIT_1 | BIT_0; + + edata->eee_enabled = !!val; + edata->eee_active = !!(supported & adv & lp); + edata->supported = supported; + edata->advertised = adv; + edata->lp_advertised = lp; + edata->tx_lpi_enabled = edata->eee_enabled; + edata->tx_lpi_timer = rtl8125_tx_lpi_timer_to_us(tp, tx_lpi_timer); + + return 0; +} + +static int +rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) +{ + struct rtl8125_private *tp = netdev_priv(net); + struct ethtool_eee *eee = &tp->eee; + u32 advertising; + int rc = 0; + + if (!HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp) || + tp->DASH) + return -EOPNOTSUPP; + + if (unlikely(tp->rtk_enable_diag)) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "Diag Enabled\n"); + rc = -EBUSY; + goto out; + } + + if (tp->autoneg != AUTONEG_ENABLE) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE requires autoneg\n"); + rc = -EINVAL; + goto out; + } + + if (edata->tx_lpi_enabled) { + if (edata->tx_lpi_timer > tp->max_jumbo_frame_size || + edata->tx_lpi_timer < ETH_MIN_MTU) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "Valid LPI timer range is %d to %d. \n", + ETH_MIN_MTU, tp->max_jumbo_frame_size); + rc = -EINVAL; + goto out; + } + } + + advertising = tp->advertising; + if (!edata->advertised) { + edata->advertised = advertising & eee->supported; + } else if (edata->advertised & ~advertising) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of autoneg advertised speeds %x\n", + edata->advertised, advertising); + rc = -EINVAL; + goto out; + } + + if (edata->advertised & ~eee->supported) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of support %x\n", + edata->advertised, eee->supported); + rc = -EINVAL; + goto out; + } + + //tp->eee.eee_enabled = edata->eee_enabled; + //tp->eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); + + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE tx_lpi_timer %x must be a subset of support %x\n", + edata->tx_lpi_timer, eee->tx_lpi_timer); + + eee->advertised = edata->advertised; + eee->tx_lpi_enabled = edata->tx_lpi_enabled; + eee->tx_lpi_timer = edata->tx_lpi_timer; + eee->eee_enabled = edata->eee_enabled; + + if (eee->eee_enabled) + rtl8125_enable_eee(tp); + else + rtl8125_disable_eee(tp); + + rtl_nway_reset(net); + + return rc; + +out: + + return rc; +} +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static const struct ethtool_ops rtl8125_ethtool_ops = { + .get_drvinfo = rtl8125_get_drvinfo, + .get_regs_len = rtl8125_get_regs_len, + .get_link = ethtool_op_get_link, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + .get_settings = rtl8125_get_settings, + .set_settings = rtl8125_set_settings, +#else + .get_link_ksettings = rtl8125_get_settings, + .set_link_ksettings = rtl8125_set_settings, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .get_pauseparam = rtl8125_get_pauseparam, + .set_pauseparam = rtl8125_set_pauseparam, +#endif + .get_msglevel = rtl8125_get_msglevel, + .set_msglevel = rtl8125_set_msglevel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) + .get_rx_csum = rtl8125_get_rx_csum, + .set_rx_csum = rtl8125_set_rx_csum, + .get_tx_csum = rtl8125_get_tx_csum, + .set_tx_csum = rtl8125_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, +#endif +#endif + .get_regs = rtl8125_get_regs, + .get_wol = rtl8125_get_wol, + .set_wol = rtl8125_set_wol, + .get_strings = rtl8125_get_strings, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + .get_stats_count = rtl8125_get_stats_count, +#else + .get_sset_count = rtl8125_get_sset_count, +#endif + .get_ethtool_stats = rtl8125_get_ethtool_stats, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) +#ifdef ETHTOOL_GPERMADDR + .get_perm_addr = ethtool_op_get_perm_addr, +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + .get_eeprom = rtl_get_eeprom, + .get_eeprom_len = rtl_get_eeprom_len, +#ifdef ENABLE_RSS_SUPPORT + .get_rxnfc = rtl8125_get_rxnfc, + .set_rxnfc = rtl8125_set_rxnfc, + .get_rxfh_indir_size = rtl8125_rss_indir_size, + .get_rxfh_key_size = rtl8125_get_rxfh_key_size, + .get_rxfh = rtl8125_get_rxfh, + .set_rxfh = rtl8125_set_rxfh, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) +#ifdef ENABLE_PTP_SUPPORT + .get_ts_info = rtl8125_get_ts_info, +#else + .get_ts_info = ethtool_op_get_ts_info, +#endif //ENABLE_PTP_SUPPORT +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + .get_eee = rtl_ethtool_get_eee, + .set_eee = rtl_ethtool_set_eee, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ + .nway_reset = rtl_nway_reset, + +}; +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +#if 0 + +static int rtl8125_enable_green_feature(struct rtl8125_private *tp) +{ + u16 gphy_val; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); + SetEthPhyOcpBit(tp, 0xA438, BIT_15); + rtl8125_mdio_write(tp, 0x00, 0x9200); + break; + default: + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); + break; + } + + return 0; +} + +static int rtl8125_disable_green_feature(struct rtl8125_private *tp) +{ + u16 gphy_val; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); + ClearEthPhyOcpBit(tp, 0xA438, BIT_15); + rtl8125_mdio_write(tp, 0x00, 0x9200); + break; + default: + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); + break; + } + + return 0; +} + +#endif + +static void rtl8125_get_mac_version(struct rtl8125_private *tp) +{ + u32 reg,val32; + u32 ICVerID; + + val32 = RTL_R32(tp, TxConfig); + reg = val32 & 0x7c800000; + ICVerID = val32 & 0x00700000; + + switch (reg) { + case 0x60800000: + if (ICVerID == 0x00000000) { + tp->mcfg = CFG_METHOD_2; + } else if (ICVerID == 0x100000) { + tp->mcfg = CFG_METHOD_3; + } else { + tp->mcfg = CFG_METHOD_3; + tp->HwIcVerUnknown = TRUE; + } + + tp->efuse_ver = EFUSE_SUPPORT_V4; + break; + case 0x64000000: + if (ICVerID == 0x00000000) { + tp->mcfg = CFG_METHOD_4; + } else if (ICVerID == 0x100000) { + tp->mcfg = CFG_METHOD_5; + } else { + tp->mcfg = CFG_METHOD_5; + tp->HwIcVerUnknown = TRUE; + } + + tp->efuse_ver = EFUSE_SUPPORT_V4; + break; + default: + printk("unknown chip version (%x)\n",reg); + tp->mcfg = CFG_METHOD_DEFAULT; + tp->HwIcVerUnknown = TRUE; + tp->efuse_ver = EFUSE_NOT_SUPPORT; + break; + } +} + +static void +rtl8125_print_mac_version(struct rtl8125_private *tp) +{ + int i; + for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { + if (tp->mcfg == rtl_chip_info[i].mcfg) { + dprintk("Realtek PCIe 2.5GbE Family Controller mcfg = %04d\n", + rtl_chip_info[i].mcfg); + return; + } + } + + dprintk("mac_version == Unknown\n"); +} + +static void +rtl8125_tally_counter_addr_fill(struct rtl8125_private *tp) +{ + if (!tp->tally_paddr) + return; + + RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); + RTL_W32(tp, CounterAddrLow, (u64)tp->tally_paddr & (DMA_BIT_MASK(32))); +} + +static void +rtl8125_tally_counter_clear(struct rtl8125_private *tp) +{ + if (!tp->tally_paddr) + return; + + RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); + RTL_W32(tp, CounterAddrLow, ((u64)tp->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); +} + +static void +rtl8125_clear_phy_ups_reg(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + ClearEthPhyOcpBit(tp, 0xA466, BIT_0); + break; + }; + ClearEthPhyOcpBit(tp, 0xA468, BIT_3 | BIT_1); +} + +static int +rtl8125_is_ups_resume(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + return (rtl8125_mac_ocp_read(tp, 0xD42C) & BIT_8); + + return 0; +} + +static void +rtl8125_clear_ups_resume_bit(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_mac_ocp_write(tp, 0xD408, rtl8125_mac_ocp_read(tp, 0xD408) & ~(BIT_8)); +} + +static void +rtl8125_wait_phy_ups_resume(struct net_device *dev, u16 PhyState) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 TmpPhyState; + int i=0; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + do { + TmpPhyState = mdio_direct_read_phy_ocp(tp, 0xA420); + TmpPhyState &= 0x7; + mdelay(1); + i++; + } while ((i < 100) && (TmpPhyState != PhyState)); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(i == 100); +#endif +} + +void +rtl8125_enable_now_is_oob(struct rtl8125_private *tp) +{ + if ( tp->HwSuppNowIsOobVer == 1 ) { + RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | Now_is_oob); + } +} + +void +rtl8125_disable_now_is_oob(struct rtl8125_private *tp) +{ + if ( tp->HwSuppNowIsOobVer == 1 ) { + RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) & ~Now_is_oob); + } +} + +static void +rtl8125_exit_oob(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 data16; + + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_dash2_disable_txrx(dev); + break; + } + + if (tp->DASH) { + rtl8125_driver_stop(tp); + rtl8125_driver_start(tp); +#ifdef ENABLE_DASH_SUPPORT + DashHwInit(dev); +#endif + } + +#ifdef ENABLE_REALWOW_SUPPORT + rtl8125_realwow_hw_init(dev); +#else + //Disable realwow function + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xC0BC, 0x00FF); + break; + } +#endif //ENABLE_REALWOW_SUPPORT + + rtl8125_nic_reset(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_disable_now_is_oob(tp); + + data16 = rtl8125_mac_ocp_read(tp, 0xE8DE) & ~BIT_14; + rtl8125_mac_ocp_write(tp, 0xE8DE, data16); + rtl8125_wait_ll_share_fifo_ready(dev); + + rtl8125_mac_ocp_write(tp, 0xC0AA, 0x07D0); + rtl8125_mac_ocp_write(tp, 0xC0A6, 0x01B5); + rtl8125_mac_ocp_write(tp, 0xC01E, 0x5555); + + rtl8125_wait_ll_share_fifo_ready(dev); + break; + } + + //wait ups resume (phy state 2) + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (rtl8125_is_ups_resume(dev)) { + rtl8125_wait_phy_ups_resume(dev, 2); + rtl8125_clear_ups_resume_bit(dev); + rtl8125_clear_phy_ups_reg(dev); + } + break; + }; +} + +void +rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + rtl8125_disable_cfg9346_write(tp); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xFC38, 0x0000); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xFC28, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC2C, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC30, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC32, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC34, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC36, 0x0000); + mdelay(3); + rtl8125_mac_ocp_write(tp, 0xFC26, 0x0000); + break; + } +} + +#ifndef ENABLE_USE_FIRMWARE_FILE +static void +rtl8125_set_mac_mcu_8125a_1(struct net_device *dev) +{ + rtl8125_hw_disable_mac_mcu_bps(dev); +} + +static void +rtl8125_set_mac_mcu_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 i; + static const u16 mcu_patch_code_8125a_2[] = { + 0xE008, 0xE01E, 0xE02E, 0xE054, 0xE057, 0xE059, 0xE0C2, 0xE0CB, 0x9996, + 0x49D1, 0xF005, 0x49D4, 0xF10A, 0x49D8, 0xF108, 0xC00F, 0x7100, 0x209C, + 0x249C, 0xC009, 0x9900, 0xE004, 0xC006, 0x1900, 0x9900, 0xC602, 0xBE00, + 0x5A48, 0xE0C2, 0x0004, 0xE10A, 0xC60F, 0x73C4, 0x49B3, 0xF106, 0x73C2, + 0xC608, 0xB406, 0xC609, 0xFF80, 0xC605, 0xB406, 0xC605, 0xFF80, 0x0544, + 0x0568, 0xE906, 0xCDE8, 0xC724, 0xC624, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, + 0x49E0, 0xF1FE, 0x76E6, 0x486D, 0x4868, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, + 0x49E0, 0xF1FE, 0xC615, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, + 0x76E6, 0x486F, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, 0x7196, + 0xC702, 0xBF00, 0x5A44, 0xEB0E, 0x0070, 0x00C3, 0x1BC0, 0xC602, 0xBE00, + 0x0E26, 0xC602, 0xBE00, 0x0EBA, 0x1501, 0xF02A, 0x1500, 0xF15D, 0xC661, + 0x75C8, 0x49D5, 0xF00A, 0x49D6, 0xF008, 0x49D7, 0xF006, 0x49D8, 0xF004, + 0x75D2, 0x49D9, 0xF150, 0xC553, 0x77A0, 0x75C8, 0x4855, 0x4856, 0x4857, + 0x4858, 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, + 0x9DC8, 0x75D2, 0x4859, 0x9DD2, 0xC643, 0x75C0, 0x49D4, 0xF033, 0x49D0, + 0xF137, 0xE030, 0xC63A, 0x75C8, 0x49D5, 0xF00E, 0x49D6, 0xF00C, 0x49D7, + 0xF00A, 0x49D8, 0xF008, 0x75D2, 0x49D9, 0xF005, 0xC62E, 0x75C0, 0x49D7, + 0xF125, 0xC528, 0x77A0, 0xC627, 0x75C8, 0x4855, 0x4856, 0x4857, 0x4858, + 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, 0x9DC8, + 0x75D2, 0x4859, 0x9DD2, 0xC616, 0x75C0, 0x4857, 0x9DC0, 0xC613, 0x75C0, + 0x49DA, 0xF003, 0x49D0, 0xF107, 0xC60B, 0xC50E, 0x48D9, 0x9DC0, 0x4859, + 0x9DC0, 0xC608, 0xC702, 0xBF00, 0x3AE0, 0xE860, 0xB400, 0xB5D4, 0xE908, + 0xE86C, 0x1200, 0xC409, 0x6780, 0x48F1, 0x8F80, 0xC404, 0xC602, 0xBE00, + 0x10AA, 0xC010, 0xEA7C, 0xC602, 0xBE00, 0x0000 + }; + + rtl8125_hw_disable_mac_mcu_bps(dev); + + for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125a_2); i++) { + rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125a_2[i]); + } + + rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); + + rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0540); + rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0E24); + rtl8125_mac_ocp_write(tp, 0xFC30, 0x0EB8); + rtl8125_mac_ocp_write(tp, 0xFC32, 0x3A5C); + rtl8125_mac_ocp_write(tp, 0xFC34, 0x10A8); + + rtl8125_mac_ocp_write(tp, 0xFC48, 0x007A); +} + +static void +rtl8125_set_mac_mcu_8125b_1(struct net_device *dev) +{ + rtl8125_hw_disable_mac_mcu_bps(dev); +} + +static void +rtl8125_set_mac_mcu_8125b_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 i; + static const u16 mcu_patch_code_8125b_2[] = { + 0xE010, 0xE01B, 0xE026, 0xE037, 0xE03D, 0xE057, 0xE05B, 0xE05F, 0xE061, + 0xE063, 0xE065, 0xE067, 0xE069, 0xE06B, 0xE06D, 0xE06F, 0x740A, 0x4846, + 0x4847, 0x9C0A, 0xC607, 0x74C0, 0x48C6, 0x9CC0, 0xC602, 0xBE00, 0x13F0, + 0xE054, 0x72CA, 0x4826, 0x4827, 0x9ACA, 0xC607, 0x72C0, 0x48A6, 0x9AC0, + 0xC602, 0xBE00, 0x081C, 0xE054, 0xC60F, 0x74C4, 0x49CC, 0xF109, 0xC60C, + 0x74CA, 0x48C7, 0x9CCA, 0xC609, 0x74C0, 0x4846, 0x9CC0, 0xC602, 0xBE00, + 0x2494, 0xE092, 0xE0C0, 0xE054, 0x7420, 0x48C0, 0x9C20, 0x7444, 0xC602, + 0xBE00, 0x12DC, 0x733A, 0x21B5, 0x25BC, 0x1304, 0xF111, 0x1B12, 0x1D2A, + 0x3168, 0x3ADA, 0x31AB, 0x1A00, 0x9AC0, 0x1300, 0xF1FB, 0x7620, 0x236E, + 0x276F, 0x1A3C, 0x22A1, 0x41B5, 0x9EE2, 0x76E4, 0x486F, 0x9EE4, 0xC602, + 0xBE00, 0x4A26, 0x733A, 0x49BB, 0xC602, 0xBE00, 0x47A2, 0x48C1, 0x48C2, + 0xC5C3, 0xBD00, 0x0A52, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, + 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, + 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, + 0xC602, 0xBE00, 0x0000 + }; + + rtl8125_hw_disable_mac_mcu_bps(dev); + + for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125b_2); i++) { + rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125b_2[i]); + } + + rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); + + rtl8125_mac_ocp_write(tp, 0xFC28, 0x13E6); + rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0812); + rtl8125_mac_ocp_write(tp, 0xFC2C, 0x248C); + rtl8125_mac_ocp_write(tp, 0xFC2E, 0x12DA); + rtl8125_mac_ocp_write(tp, 0xFC30, 0x4A20); + rtl8125_mac_ocp_write(tp, 0xFC32, 0x47A0); + rtl8125_mac_ocp_write(tp, 0xFC34, 0x0A46); + + rtl8125_mac_ocp_write(tp, 0xFC48, 0x007F); +} + +static void +rtl8125_hw_mac_mcu_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->NotWrMcuPatchCode == TRUE) return; + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_set_mac_mcu_8125a_1(dev); + break; + case CFG_METHOD_3: + rtl8125_set_mac_mcu_8125a_2(dev); + break; + case CFG_METHOD_4: + rtl8125_set_mac_mcu_8125b_1(dev); + break; + case CFG_METHOD_5: + rtl8125_set_mac_mcu_8125b_2(dev); + break; + } +} +#endif + +#ifdef ENABLE_USE_FIRMWARE_FILE +static void rtl8125_release_firmware(struct rtl8125_private *tp) +{ + if (tp->rtl_fw) { + rtl8125_fw_release_firmware(tp->rtl_fw); + kfree(tp->rtl_fw); + tp->rtl_fw = NULL; + } +} + +void rtl8125_apply_firmware(struct rtl8125_private *tp) +{ + /* TODO: release firmware if rtl_fw_write_firmware signals failure. */ + if (tp->rtl_fw) { + rtl8125_fw_write_firmware(tp, tp->rtl_fw); + /* At least one firmware doesn't reset tp->ocp_base. */ + tp->ocp_base = OCP_STD_PHY_BASE; + + /* PHY soft reset may still be in progress */ + //phy_read_poll_timeout(tp->phydev, MII_BMCR, val, + // !(val & BMCR_RESET), + // 50000, 600000, true); + rtl8125_wait_phy_reset_complete(tp); + + tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); + tp->sw_ram_code_ver = tp->hw_ram_code_ver; + tp->HwHasWrRamCodeToMicroP = TRUE; + } +} +#endif + +static void +rtl8125_hw_init(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + rtl8125_disable_cfg9346_write(tp); + RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); + break; + } + + //Disable UPS + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xD40A, rtl8125_mac_ocp_read( tp, 0xD40A) & ~(BIT_4)); + break; + } + +#ifndef ENABLE_USE_FIRMWARE_FILE + if (!tp->rtl_fw) + rtl8125_hw_mac_mcu_config(dev); +#endif + + /*disable ocp phy power saving*/ + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_disable_ocp_phy_power_saving(dev); + + //Set PCIE uncorrectable error status mask pcie 0x108 + csi_tmp = rtl8125_csi_read(tp, 0x108); + csi_tmp |= BIT_20; + rtl8125_csi_write(tp, 0x108, csi_tmp); + + rtl8125_enable_cfg9346_write(tp); + rtl8125_disable_linkchg_wakeup(dev); + rtl8125_disable_cfg9346_write(tp); + rtl8125_disable_magic_packet(dev); + rtl8125_disable_d0_speedup(tp); + rtl8125_set_pci_pme(tp, 0); + if (s0_magic_packet == 1) + rtl8125_enable_magic_packet(dev); + +#ifdef ENABLE_USE_FIRMWARE_FILE + if (tp->rtl_fw && + !tp->resume_not_chg_speed && + !(HW_DASH_SUPPORT_TYPE_3(tp) && + tp->HwPkgDet == 0x06)) + rtl8125_apply_firmware(tp); +#endif +} + +static void +rtl8125_hw_ephy_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_ephy_write(tp, 0x01, 0xA812); + rtl8125_ephy_write(tp, 0x09, 0x520C); + rtl8125_ephy_write(tp, 0x04, 0xD000); + rtl8125_ephy_write(tp, 0x0D, 0xF702); + rtl8125_ephy_write(tp, 0x0A, 0x8653); + rtl8125_ephy_write(tp, 0x06, 0x001E); + rtl8125_ephy_write(tp, 0x08, 0x3595); + rtl8125_ephy_write(tp, 0x20, 0x9455); + rtl8125_ephy_write(tp, 0x21, 0x99FF); + rtl8125_ephy_write(tp, 0x02, 0x6046); + rtl8125_ephy_write(tp, 0x29, 0xFE00); + rtl8125_ephy_write(tp, 0x23, 0xAB62); + + rtl8125_ephy_write(tp, 0x41, 0xA80C); + rtl8125_ephy_write(tp, 0x49, 0x520C); + rtl8125_ephy_write(tp, 0x44, 0xD000); + rtl8125_ephy_write(tp, 0x4D, 0xF702); + rtl8125_ephy_write(tp, 0x4A, 0x8653); + rtl8125_ephy_write(tp, 0x46, 0x001E); + rtl8125_ephy_write(tp, 0x48, 0x3595); + rtl8125_ephy_write(tp, 0x60, 0x9455); + rtl8125_ephy_write(tp, 0x61, 0x99FF); + rtl8125_ephy_write(tp, 0x42, 0x6046); + rtl8125_ephy_write(tp, 0x69, 0xFE00); + rtl8125_ephy_write(tp, 0x63, 0xAB62); + break; + case CFG_METHOD_3: + rtl8125_ephy_write(tp, 0x04, 0xD000); + rtl8125_ephy_write(tp, 0x0A, 0x8653); + rtl8125_ephy_write(tp, 0x23, 0xAB66); + rtl8125_ephy_write(tp, 0x20, 0x9455); + rtl8125_ephy_write(tp, 0x21, 0x99FF); + rtl8125_ephy_write(tp, 0x29, 0xFE04); + + rtl8125_ephy_write(tp, 0x44, 0xD000); + rtl8125_ephy_write(tp, 0x4A, 0x8653); + rtl8125_ephy_write(tp, 0x63, 0xAB66); + rtl8125_ephy_write(tp, 0x60, 0x9455); + rtl8125_ephy_write(tp, 0x61, 0x99FF); + rtl8125_ephy_write(tp, 0x69, 0xFE04); + + ClearAndSetPCIePhyBit(tp, + 0x2A, + (BIT_14 | BIT_13 | BIT_12), + (BIT_13 | BIT_12) + ); + ClearPCIePhyBit(tp, 0x19, BIT_6); + SetPCIePhyBit(tp, 0x1B, (BIT_11 | BIT_10 | BIT_9)); + ClearPCIePhyBit(tp, 0x1B, (BIT_14 | BIT_13 | BIT_12)); + rtl8125_ephy_write(tp, 0x02, 0x6042); + rtl8125_ephy_write(tp, 0x06, 0x0014); + + ClearAndSetPCIePhyBit(tp, + 0x6A, + (BIT_14 | BIT_13 | BIT_12), + (BIT_13 | BIT_12) + ); + ClearPCIePhyBit(tp, 0x59, BIT_6); + SetPCIePhyBit(tp, 0x5B, (BIT_11 | BIT_10 | BIT_9)); + ClearPCIePhyBit(tp, 0x5B, (BIT_14 | BIT_13 | BIT_12)); + rtl8125_ephy_write(tp, 0x42, 0x6042); + rtl8125_ephy_write(tp, 0x46, 0x0014); + break; + case CFG_METHOD_4: + rtl8125_ephy_write(tp, 0x06, 0x001F); + rtl8125_ephy_write(tp, 0x0A, 0xB66B); + rtl8125_ephy_write(tp, 0x01, 0xA852); + rtl8125_ephy_write(tp, 0x24, 0x0008); + rtl8125_ephy_write(tp, 0x2F, 0x6052); + rtl8125_ephy_write(tp, 0x0D, 0xF716); + rtl8125_ephy_write(tp, 0x20, 0xD477); + rtl8125_ephy_write(tp, 0x21, 0x4477); + rtl8125_ephy_write(tp, 0x22, 0x0013); + rtl8125_ephy_write(tp, 0x23, 0xBB66); + rtl8125_ephy_write(tp, 0x0B, 0xA909); + rtl8125_ephy_write(tp, 0x29, 0xFF04); + rtl8125_ephy_write(tp, 0x1B, 0x1EA0); + + rtl8125_ephy_write(tp, 0x46, 0x001F); + rtl8125_ephy_write(tp, 0x4A, 0xB66B); + rtl8125_ephy_write(tp, 0x41, 0xA84A); + rtl8125_ephy_write(tp, 0x64, 0x000C); + rtl8125_ephy_write(tp, 0x6F, 0x604A); + rtl8125_ephy_write(tp, 0x4D, 0xF716); + rtl8125_ephy_write(tp, 0x60, 0xD477); + rtl8125_ephy_write(tp, 0x61, 0x4477); + rtl8125_ephy_write(tp, 0x62, 0x0013); + rtl8125_ephy_write(tp, 0x63, 0xBB66); + rtl8125_ephy_write(tp, 0x4B, 0xA909); + rtl8125_ephy_write(tp, 0x69, 0xFF04); + rtl8125_ephy_write(tp, 0x5B, 0x1EA0); + break; + case CFG_METHOD_5: + rtl8125_ephy_write(tp, 0x0B, 0xA908); + rtl8125_ephy_write(tp, 0x22, 0x0023); + rtl8125_ephy_write(tp, 0x1E, 0x28EB); + + rtl8125_ephy_write(tp, 0x4B, 0xA908); + rtl8125_ephy_write(tp, 0x62, 0x0023); + rtl8125_ephy_write(tp, 0x5E, 0x28EB); + break; + } +} + +static u16 +rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp) +{ + u16 hw_ram_code_ver = ~0; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); + hw_ram_code_ver = mdio_direct_read_phy_ocp(tp, 0xA438); + break; + } + + return hw_ram_code_ver; +} + +static int +rtl8125_check_hw_phy_mcu_code_ver(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ram_code_ver_match = 0; + + tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); + + if (tp->hw_ram_code_ver == tp->sw_ram_code_ver) { + ram_code_ver_match = 1; + tp->HwHasWrRamCodeToMicroP = TRUE; + } + + return ram_code_ver_match; +} + +bool +rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp) +{ + u16 gphy_val; + u16 WaitCount; + bool bSuccess = TRUE; + + SetEthPhyOcpBit(tp, 0xB820, BIT_4); + + WaitCount = 0; + do { + gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); + udelay(100); + WaitCount++; + } while (!(gphy_val & BIT_6) && (WaitCount < 1000)); + + if (!(gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; + + if (!bSuccess) + dprintk("rtl8125_set_phy_mcu_patch_request fail.\n"); + + return bSuccess; +} + +bool +rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp) +{ + u16 gphy_val; + u16 WaitCount; + bool bSuccess = TRUE; + + ClearEthPhyOcpBit(tp, 0xB820, BIT_4); + + WaitCount = 0; + do { + gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); + udelay(100); + WaitCount++; + } while ((gphy_val & BIT_6) && (WaitCount < 1000)); + + if ((gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; + + if (!bSuccess) + dprintk("rtl8125_clear_phy_mcu_patch_request fail.\n"); + + return bSuccess; +} + +#ifndef ENABLE_USE_FIRMWARE_FILE +static void +rtl8125_write_hw_phy_mcu_code_ver(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); + mdio_direct_write_phy_ocp(tp, 0xA438, tp->sw_ram_code_ver); + tp->hw_ram_code_ver = tp->sw_ram_code_ver; + break; + } +} + +static void +rtl8125_acquire_phy_mcu_patch_key_lock(struct rtl8125_private *tp) +{ + u16 PatchKey; + + switch (tp->mcfg) { + case CFG_METHOD_2: + PatchKey = 0x8600; + break; + case CFG_METHOD_3: + PatchKey = 0x8601; + break; + case CFG_METHOD_4: + PatchKey = 0x3700; + break; + case CFG_METHOD_5: + PatchKey = 0x3701; + break; + default: + return; + } + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); + mdio_direct_write_phy_ocp(tp, 0xA438, PatchKey); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xB82E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); +} + +static void +rtl8125_release_phy_mcu_patch_key_lock(struct rtl8125_private *tp) +{ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + ClearEthPhyOcpBit(tp, 0xB82E, BIT_0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + break; + default: + break; + } +} + +static void +rtl8125_set_phy_mcu_ram_code(struct net_device *dev, const u16 *ramcode, u16 codesize) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 i; + u16 addr; + u16 val; + + if (ramcode == NULL || codesize % 2) { + goto out; + } + + for (i = 0; i < codesize; i += 2) { + addr = ramcode[i]; + val = ramcode[i + 1]; + if (addr == 0xFFFF && val == 0xFFFF) { + break; + } + mdio_direct_write_phy_ocp(tp, addr, val); + } + +out: + return; +} + +static void +rtl8125_enable_phy_disable_mode(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_5); + break; + } + + dprintk("enable phy disable mode.\n"); +} + +static void +rtl8125_disable_phy_disable_mode(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_5); + break; + } + + mdelay(1); + + dprintk("disable phy disable mode.\n"); +} + +static void +rtl8125_set_hw_phy_before_init_phy_mcu(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 PhyRegValue; + + switch (tp->mcfg) { + case CFG_METHOD_4: + mdio_direct_write_phy_ocp(tp, 0xBF86, 0x9000); + + SetEthPhyOcpBit(tp, 0xC402, BIT_10); + ClearEthPhyOcpBit(tp, 0xC402, BIT_10); + + PhyRegValue = mdio_direct_read_phy_ocp(tp, 0xBF86); + PhyRegValue &= (BIT_1 | BIT_0); + if (PhyRegValue != 0) + dprintk("PHY watch dog not clear, value = 0x%x \n", PhyRegValue); + + mdio_direct_write_phy_ocp(tp, 0xBD86, 0x1010); + mdio_direct_write_phy_ocp(tp, 0xBD88, 0x1010); + + ClearAndSetEthPhyOcpBit(tp, + 0xBD4E, + BIT_11 | BIT_10, + BIT_11); + ClearAndSetEthPhyOcpBit(tp, + 0xBF46, + BIT_11 | BIT_10 | BIT_9 | BIT_8, + BIT_10 | BIT_9 | BIT_8); + break; + } +} + +static void +rtl8125_real_set_phy_mcu_8125a_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_acquire_phy_mcu_patch_key_lock(tp); + + + SetEthPhyOcpBit(tp, 0xB820, BIT_7); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8013); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8021); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x802f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x803d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8042); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa088); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a50); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a6c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd019); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a84); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8970); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c07); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0901); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcf09); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd705); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xceff); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf0a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1213); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8401); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8580); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1253); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd181); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4018); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd706); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2c59); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x804d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc60f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc605); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10fd); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10f4); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1252); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1206); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a78); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a60); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a4f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3f00); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8066); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x807c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8089); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x808e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80b2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80c2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62db); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x655c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x653c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0346); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8208); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x609d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x607d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0221); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ce); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0169); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00a6); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x000d); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x029f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x007f); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8017); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8029); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8054); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x805a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8064); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9430); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9480); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb408); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd120); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd057); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb80); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9906); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0567); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb94); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8406); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8dff); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0773); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4045); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07ec); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fa7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0481); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8220); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x078e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd150); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6121); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61a2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6223); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0537); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0642); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0686); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0788); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x047b); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x065c); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0769); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0565); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x06f9); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ff); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8593); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9caf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x85a5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfb0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86d7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xda02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xdd02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfd0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86dd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fe); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf2f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2cac); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0286); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x65af); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x212b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x022c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86b6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf21); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cd1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8710); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x870d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8716); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x871f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x871c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8728); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8725); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8707); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbad); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x281c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3102); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3d02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3a02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4302); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4c02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4902); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2e02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4602); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4f02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf35); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7ff8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfaef); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x69bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fe); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ec); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ef); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cef); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x96fe); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf8fa); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef69); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf202); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf502); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf802); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef96); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfefc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0420); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x53b5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4086); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb9b5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb03a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbac8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb13a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xba77); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2677); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2640); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x28bb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa430); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2f71); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x20d9); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2109); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x34e7); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x000f); + + + ClearEthPhyOcpBit(tp, 0xB820, BIT_7); + + + rtl8125_release_phy_mcu_patch_key_lock(tp); +} + +static void +rtl8125_set_phy_mcu_8125a_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125a_1(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static void +rtl8125_real_set_phy_mcu_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_acquire_phy_mcu_patch_key_lock(tp); + + + SetEthPhyOcpBit(tp, 0xB820, BIT_7); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x808b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x808f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8093); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8097); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x809d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80aa); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x607b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x42da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x615b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac11); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa410); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4779); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac22); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa420); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4559); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf023); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac44); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa440); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4339); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac88); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa480); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4119); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf001); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fac); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc48f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x141b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x121a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0898); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd18a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x401c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa804); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8804); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x053b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0648); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc520); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa201); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x252d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd708); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4006); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0307); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1645); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0647); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x053a); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7c); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0c); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0896); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xff00); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8015); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xad02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x02d7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ed); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x008f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x008d); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00eb); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8018); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8055); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8072); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80dc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa380); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4085); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8280); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd158); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd04d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8380); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd10d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa220); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd130); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbb80); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd074); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x604b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa90c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd116); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd119); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6241); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x63e2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6583); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf054); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d50); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf021); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d60); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf013); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d70); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d80); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ff4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07fb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f6f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f4e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f2d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1f5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd049); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ec); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ea); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x06a9); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x078a); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d2); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x067f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0665); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00fc); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x45af); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xee82); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf900); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf03); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7f8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0a6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00e1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa601); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x58f0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x37a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae16); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa185); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa188); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8902); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03b3); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); + + + ClearEthPhyOcpBit(tp, 0xB820, BIT_7); + + + rtl8125_release_phy_mcu_patch_key_lock(tp); +} + +static void +rtl8125_set_phy_mcu_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125a_2(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static const u16 phy_mcu_ram_code_8125b_1[] = { + 0xa436, 0x8024, 0xa438, 0x3700, 0xa436, 0xB82E, 0xa438, 0x0001, + 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x8025, 0xa438, 0x1800, 0xa438, 0x803a, + 0xa438, 0x1800, 0xa438, 0x8044, 0xa438, 0x1800, 0xa438, 0x8083, + 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0x1800, 0xa438, 0x808d, + 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0xd712, 0xa438, 0x4077, + 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, 0xa438, 0x6099, + 0xa438, 0x7f44, 0xa438, 0x1800, 0xa438, 0x1a14, 0xa438, 0x9040, + 0xa438, 0x9201, 0xa438, 0x1800, 0xa438, 0x1b1a, 0xa438, 0xd71e, + 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, 0xa438, 0x3ce5, + 0xa438, 0x1afb, 0xa438, 0x1800, 0xa438, 0x1b00, 0xa438, 0xd712, + 0xa438, 0x4077, 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, + 0xa438, 0x60b9, 0xa438, 0x2421, 0xa438, 0x1c17, 0xa438, 0x1800, + 0xa438, 0x1a14, 0xa438, 0x9040, 0xa438, 0x1800, 0xa438, 0x1c2c, + 0xa438, 0xd71e, 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, + 0xa438, 0x3ce5, 0xa438, 0x1c0f, 0xa438, 0x1800, 0xa438, 0x1c13, + 0xa438, 0xd702, 0xa438, 0xd501, 0xa438, 0x6072, 0xa438, 0x8401, + 0xa438, 0xf002, 0xa438, 0xa401, 0xa438, 0x1000, 0xa438, 0x146e, + 0xa438, 0x1800, 0xa438, 0x0b77, 0xa438, 0xd703, 0xa438, 0x665d, + 0xa438, 0x653e, 0xa438, 0x641f, 0xa438, 0xd700, 0xa438, 0x62c4, + 0xa438, 0x6185, 0xa438, 0x6066, 0xa438, 0x1800, 0xa438, 0x165a, + 0xa438, 0xc101, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, + 0xa438, 0xd700, 0xa438, 0x7fa6, 0xa438, 0x1800, 0xa438, 0x807d, + 0xa438, 0xc102, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, + 0xa438, 0xd700, 0xa438, 0x2569, 0xa438, 0x8058, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc104, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd700, 0xa438, 0x7fa4, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc120, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbf, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc140, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbe, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc180, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbd, 0xa438, 0xc100, + 0xa438, 0xcb00, 0xa438, 0xd708, 0xa438, 0x6018, 0xa438, 0x1800, + 0xa438, 0x165a, 0xa438, 0x1000, 0xa438, 0x14f6, 0xa438, 0xd014, + 0xa438, 0xd1e3, 0xa438, 0x1000, 0xa438, 0x1356, 0xa438, 0xd705, + 0xa438, 0x5fbe, 0xa438, 0x1800, 0xa438, 0x1559, 0xa436, 0xA026, + 0xa438, 0xffff, 0xa436, 0xA024, 0xa438, 0xffff, 0xa436, 0xA022, + 0xa438, 0xffff, 0xa436, 0xA020, 0xa438, 0x1557, 0xa436, 0xA006, + 0xa438, 0x1677, 0xa436, 0xA004, 0xa438, 0x0b75, 0xa436, 0xA002, + 0xa438, 0x1c17, 0xa436, 0xA000, 0xa438, 0x1b04, 0xa436, 0xA008, + 0xa438, 0x1f00, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x817f, 0xa438, 0x1800, 0xa438, 0x82ab, + 0xa438, 0x1800, 0xa438, 0x83f8, 0xa438, 0x1800, 0xa438, 0x8444, + 0xa438, 0x1800, 0xa438, 0x8454, 0xa438, 0x1800, 0xa438, 0x8459, + 0xa438, 0x1800, 0xa438, 0x8465, 0xa438, 0xcb11, 0xa438, 0xa50c, + 0xa438, 0x8310, 0xa438, 0xd701, 0xa438, 0x4076, 0xa438, 0x0c03, + 0xa438, 0x0903, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x1000, 0xa438, 0x0a4d, + 0xa438, 0xcb12, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5f84, 0xa438, 0xd102, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd701, + 0xa438, 0x60f3, 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, + 0xa438, 0xd410, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb13, + 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, + 0xa438, 0xa00a, 0xa438, 0xa910, 0xa438, 0xa780, 0xa438, 0xd14a, + 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, + 0xa438, 0x6255, 0xa438, 0xd700, 0xa438, 0x5f74, 0xa438, 0x6326, + 0xa438, 0xd702, 0xa438, 0x5f07, 0xa438, 0x800a, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, + 0xa438, 0x0902, 0xa438, 0xffe2, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5fab, 0xa438, 0xba08, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8b, 0xa438, 0x9a08, + 0xa438, 0x800a, 0xa438, 0xd702, 0xa438, 0x6535, 0xa438, 0xd40d, + 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb14, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa00a, + 0xa438, 0xa780, 0xa438, 0xd14a, 0xa438, 0xd048, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x6206, + 0xa438, 0xd702, 0xa438, 0x5f47, 0xa438, 0x800a, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, + 0xa438, 0x0902, 0xa438, 0x1800, 0xa438, 0x8064, 0xa438, 0x800a, + 0xa438, 0xd40e, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0xd701, 0xa438, 0x6073, 0xa438, 0xd701, + 0xa438, 0x4216, 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8004, 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8001, 0xa438, 0xd120, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x8504, + 0xa438, 0xcb21, 0xa438, 0xa301, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, 0xa438, 0xd704, + 0xa438, 0x40e0, 0xa438, 0xd196, 0xa438, 0xd04d, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb22, + 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, + 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8910, 0xa438, 0x8720, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb23, + 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, + 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, + 0xa438, 0x5dee, 0xa438, 0xcb24, 0xa438, 0x8f1f, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f6e, 0xa438, 0xa111, + 0xa438, 0xa215, 0xa438, 0xa401, 0xa438, 0x8404, 0xa438, 0xa720, + 0xa438, 0xcb25, 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, + 0xa438, 0x9503, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, + 0xa438, 0x0b86, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0xcb26, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x8205, + 0xa438, 0x8404, 0xa438, 0xcb27, 0xa438, 0xd404, 0xa438, 0x1000, + 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0xa104, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8104, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa120, + 0xa438, 0xaa0f, 0xa438, 0x8110, 0xa438, 0xa284, 0xa438, 0xa404, + 0xa438, 0xa00a, 0xa438, 0xd193, 0xa438, 0xd046, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb28, + 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fa8, 0xa438, 0x8110, 0xa438, 0x8284, 0xa438, 0xa404, + 0xa438, 0x800a, 0xa438, 0x8710, 0xa438, 0xb804, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, + 0xa438, 0xcb29, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, + 0xa438, 0xcb2a, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa404, + 0xa438, 0xa00a, 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8149, + 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8151, + 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, + 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, + 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8404, + 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, + 0xa438, 0x0433, 0xa438, 0xcb15, 0xa438, 0xa508, 0xa438, 0xd700, + 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, + 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, + 0xa438, 0x1000, 0xa438, 0x0a4d, 0xa438, 0xa301, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, + 0xa438, 0xd704, 0xa438, 0x40e0, 0xa438, 0xd115, 0xa438, 0xd04f, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, + 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb16, + 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, + 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8720, 0xa438, 0xd17a, + 0xa438, 0xd04c, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb17, + 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, + 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, + 0xa438, 0x61ce, 0xa438, 0xd700, 0xa438, 0x5db4, 0xa438, 0xcb18, + 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, + 0xa438, 0xa720, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xffd6, 0xa438, 0x8f1f, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f8e, 0xa438, 0xa131, + 0xa438, 0xaa0f, 0xa438, 0xa2d5, 0xa438, 0xa407, 0xa438, 0xa720, + 0xa438, 0x8310, 0xa438, 0xa308, 0xa438, 0x8308, 0xa438, 0xcb19, + 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, + 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, 0xa438, 0x0b86, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, + 0xa438, 0xcb1a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x82c5, 0xa438, 0xa404, + 0xa438, 0x8402, 0xa438, 0xb804, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, 0xa438, 0xcb1b, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f85, + 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, 0xa438, 0xcb1c, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0xa110, 0xa438, 0xa284, 0xa438, 0xa404, + 0xa438, 0x8402, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fa8, 0xa438, 0xcb1d, 0xa438, 0xa180, 0xa438, 0xa402, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, + 0xa438, 0xa220, 0xa438, 0xd1f5, 0xa438, 0xd049, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8221, + 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xb920, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fa3, + 0xa438, 0xa504, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa00a, 0xa438, 0x8190, + 0xa438, 0x82a4, 0xa438, 0x8402, 0xa438, 0xa404, 0xa438, 0xb808, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7fa3, + 0xa438, 0x9808, 0xa438, 0xcb2b, 0xa438, 0xcb2c, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f84, 0xa438, 0xd14a, + 0xa438, 0xd048, 0xa438, 0xa780, 0xa438, 0xcb2d, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f94, 0xa438, 0x6208, + 0xa438, 0xd702, 0xa438, 0x5f27, 0xa438, 0x800a, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, + 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xffe9, 0xa438, 0xcb2e, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa406, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, + 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x827d, + 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, + 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, + 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8406, + 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, + 0xa438, 0x0433, 0xa438, 0xcb30, 0xa438, 0x8380, 0xa438, 0xcb31, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f86, + 0xa438, 0x9308, 0xa438, 0xb204, 0xa438, 0xb301, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x5fa2, 0xa438, 0xb302, + 0xa438, 0x9204, 0xa438, 0xcb32, 0xa438, 0xd408, 0xa438, 0x1000, + 0xa438, 0x0a37, 0xa438, 0xd141, 0xa438, 0xd043, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd704, + 0xa438, 0x4ccc, 0xa438, 0xd700, 0xa438, 0x4c81, 0xa438, 0xd702, + 0xa438, 0x609e, 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0xf003, + 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, + 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, 0xa438, 0x0c1f, + 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x8710, + 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, + 0xa438, 0xa203, 0xa438, 0x8120, 0xa438, 0x8a0f, 0xa438, 0xa111, + 0xa438, 0x8204, 0xa438, 0xa140, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8140, 0xa438, 0xd17a, 0xa438, 0xd04b, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xa204, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, + 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0xd404, 0xa438, 0x1000, + 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0x8101, + 0xa438, 0x8201, 0xa438, 0xa104, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8104, 0xa438, 0xa120, 0xa438, 0xaa0f, 0xa438, 0x8110, + 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0xa00a, 0xa438, 0xd193, + 0xa438, 0xd047, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fa8, 0xa438, 0xa180, 0xa438, 0xd13d, + 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0xf024, 0xa438, 0xa710, 0xa438, 0xa00a, + 0xa438, 0x8190, 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, + 0xa438, 0x8710, 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0x800a, + 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0x8406, 0xa438, 0xd700, + 0xa438, 0x4121, 0xa438, 0xd701, 0xa438, 0x60f3, 0xa438, 0xd1e5, + 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x8710, 0xa438, 0xa00a, 0xa438, 0x8190, + 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0xcb33, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, + 0xa438, 0x9820, 0xa438, 0xcb34, 0xa438, 0xa00a, 0xa438, 0xa190, + 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fa9, 0xa438, 0xd701, 0xa438, 0x6853, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d00, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0xcb35, + 0xa438, 0xd407, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8110, + 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa00a, 0xa438, 0xd704, + 0xa438, 0x4215, 0xa438, 0xa304, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fb8, 0xa438, 0xd1c3, 0xa438, 0xd043, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, + 0xa438, 0x8304, 0xa438, 0xd700, 0xa438, 0x4109, 0xa438, 0xf01e, + 0xa438, 0xcb36, 0xa438, 0xd412, 0xa438, 0x1000, 0xa438, 0x0a37, + 0xa438, 0xd700, 0xa438, 0x6309, 0xa438, 0xd702, 0xa438, 0x42c7, + 0xa438, 0x800a, 0xa438, 0x8180, 0xa438, 0x8280, 0xa438, 0x8404, + 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, + 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, + 0xa438, 0x0c03, 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xd14a, + 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xcc55, 0xa438, 0xcb37, + 0xa438, 0xa00a, 0xa438, 0xa190, 0xa438, 0xa2a4, 0xa438, 0xa404, + 0xa438, 0xd700, 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd13d, + 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fa9, 0xa438, 0xd702, 0xa438, 0x5f71, 0xa438, 0xcb38, + 0xa438, 0x8224, 0xa438, 0xa288, 0xa438, 0x8180, 0xa438, 0xa110, + 0xa438, 0xa404, 0xa438, 0x800a, 0xa438, 0xd700, 0xa438, 0x6041, + 0xa438, 0x8402, 0xa438, 0xd415, 0xa438, 0x1000, 0xa438, 0x0a37, + 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb39, 0xa438, 0xa00a, + 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xd700, + 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd17a, 0xa438, 0xd047, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, + 0xa438, 0x1800, 0xa438, 0x0560, 0xa438, 0xa111, 0xa438, 0x0000, + 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0xd3f5, + 0xa438, 0xd219, 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, + 0xa438, 0x5fa5, 0xa438, 0xa215, 0xa438, 0xd30e, 0xa438, 0xd21a, + 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x63e9, + 0xa438, 0xd708, 0xa438, 0x5f65, 0xa438, 0xd708, 0xa438, 0x7f36, + 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8004, + 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8001, + 0xa438, 0xd708, 0xa438, 0x4098, 0xa438, 0xd102, 0xa438, 0x9401, + 0xa438, 0xf003, 0xa438, 0xd103, 0xa438, 0xb401, 0xa438, 0x1000, + 0xa438, 0x0c27, 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0c35, + 0xa438, 0x8108, 0xa438, 0x8110, 0xa438, 0x8294, 0xa438, 0xa202, + 0xa438, 0x1800, 0xa438, 0x0bdb, 0xa438, 0xd39c, 0xa438, 0xd210, + 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x5fa5, + 0xa438, 0xd39c, 0xa438, 0xd210, 0xa438, 0x1000, 0xa438, 0x0c31, + 0xa438, 0xd708, 0xa438, 0x5fa5, 0xa438, 0x1000, 0xa438, 0x0c31, + 0xa438, 0xd708, 0xa438, 0x29b5, 0xa438, 0x840e, 0xa438, 0xd708, + 0xa438, 0x5f4a, 0xa438, 0x0c1f, 0xa438, 0x1014, 0xa438, 0x1000, + 0xa438, 0x0c31, 0xa438, 0xd709, 0xa438, 0x7fa4, 0xa438, 0x901f, + 0xa438, 0x1800, 0xa438, 0x0c23, 0xa438, 0xcb43, 0xa438, 0xa508, + 0xa438, 0xd701, 0xa438, 0x3699, 0xa438, 0x844a, 0xa438, 0xa504, + 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xa00a, + 0xa438, 0xd700, 0xa438, 0x2109, 0xa438, 0x05ea, 0xa438, 0xa402, + 0xa438, 0x1800, 0xa438, 0x05ea, 0xa438, 0xcb90, 0xa438, 0x0cf0, + 0xa438, 0x0ca0, 0xa438, 0x1800, 0xa438, 0x06db, 0xa438, 0xd1ff, + 0xa438, 0xd052, 0xa438, 0xa508, 0xa438, 0x8718, 0xa438, 0xa00a, + 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0x0cf0, + 0xa438, 0x0c50, 0xa438, 0x1800, 0xa438, 0x09ef, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd704, 0xa438, 0x2e70, 0xa438, 0x06da, + 0xa438, 0xd700, 0xa438, 0x5f55, 0xa438, 0xa90c, 0xa438, 0x1800, + 0xa438, 0x0645, 0xa436, 0xA10E, 0xa438, 0x0644, 0xa436, 0xA10C, + 0xa438, 0x09e9, 0xa436, 0xA10A, 0xa438, 0x06da, 0xa436, 0xA108, + 0xa438, 0x05e1, 0xa436, 0xA106, 0xa438, 0x0be4, 0xa436, 0xA104, + 0xa438, 0x0435, 0xa436, 0xA102, 0xa438, 0x0141, 0xa436, 0xA100, + 0xa438, 0x026d, 0xa436, 0xA110, 0xa438, 0x00ff, 0xa436, 0xb87c, + 0xa438, 0x85fe, 0xa436, 0xb87e, 0xa438, 0xaf86, 0xa438, 0x16af, + 0xa438, 0x8699, 0xa438, 0xaf86, 0xa438, 0xe5af, 0xa438, 0x86f9, + 0xa438, 0xaf87, 0xa438, 0x7aaf, 0xa438, 0x883a, 0xa438, 0xaf88, + 0xa438, 0x58af, 0xa438, 0x8b6c, 0xa438, 0xd48b, 0xa438, 0x7c02, + 0xa438, 0x8644, 0xa438, 0x2c00, 0xa438, 0x503c, 0xa438, 0xffd6, + 0xa438, 0xac27, 0xa438, 0x18e1, 0xa438, 0x82fe, 0xa438, 0xad28, + 0xa438, 0x0cd4, 0xa438, 0x8b84, 0xa438, 0x0286, 0xa438, 0x442c, + 0xa438, 0x003c, 0xa438, 0xac27, 0xa438, 0x06ee, 0xa438, 0x8299, + 0xa438, 0x01ae, 0xa438, 0x04ee, 0xa438, 0x8299, 0xa438, 0x00af, + 0xa438, 0x23dc, 0xa438, 0xf9fa, 0xa438, 0xcefa, 0xa438, 0xfbef, + 0xa438, 0x79fb, 0xa438, 0xc4bf, 0xa438, 0x8b76, 0xa438, 0x026c, + 0xa438, 0x6dac, 0xa438, 0x2804, 0xa438, 0xd203, 0xa438, 0xae02, + 0xa438, 0xd201, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, + 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x648a, + 0xa438, 0x0002, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, + 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x7402, + 0xa438, 0x72cd, 0xa438, 0xac50, 0xa438, 0x02ef, 0xa438, 0x643a, + 0xa438, 0x019f, 0xa438, 0xe4ef, 0xa438, 0x4678, 0xa438, 0x03ac, + 0xa438, 0x2002, 0xa438, 0xae02, 0xa438, 0xd0ff, 0xa438, 0xffef, + 0xa438, 0x97ff, 0xa438, 0xfec6, 0xa438, 0xfefd, 0xa438, 0x041f, + 0xa438, 0x771f, 0xa438, 0x221c, 0xa438, 0x450d, 0xa438, 0x481f, + 0xa438, 0x00ac, 0xa438, 0x7f04, 0xa438, 0x1a94, 0xa438, 0xae08, + 0xa438, 0x1a94, 0xa438, 0xac7f, 0xa438, 0x03d7, 0xa438, 0x0100, + 0xa438, 0xef46, 0xa438, 0x0d48, 0xa438, 0x1f00, 0xa438, 0x1c45, + 0xa438, 0xef69, 0xa438, 0xef57, 0xa438, 0xef74, 0xa438, 0x0272, + 0xa438, 0xe8a7, 0xa438, 0xffff, 0xa438, 0x0d1a, 0xa438, 0x941b, + 0xa438, 0x979e, 0xa438, 0x072d, 0xa438, 0x0100, 0xa438, 0x1a64, + 0xa438, 0xef76, 0xa438, 0xef97, 0xa438, 0x0d98, 0xa438, 0xd400, + 0xa438, 0xff1d, 0xa438, 0x941a, 0xa438, 0x89cf, 0xa438, 0x1a75, + 0xa438, 0xaf74, 0xa438, 0xf9bf, 0xa438, 0x8b79, 0xa438, 0x026c, + 0xa438, 0x6da1, 0xa438, 0x0005, 0xa438, 0xe180, 0xa438, 0xa0ae, + 0xa438, 0x03e1, 0xa438, 0x80a1, 0xa438, 0xaf26, 0xa438, 0x9aac, + 0xa438, 0x284d, 0xa438, 0xe08f, 0xa438, 0xffef, 0xa438, 0x10c0, + 0xa438, 0xe08f, 0xa438, 0xfe10, 0xa438, 0x1b08, 0xa438, 0xa000, + 0xa438, 0x04c8, 0xa438, 0xaf40, 0xa438, 0x67c8, 0xa438, 0xbf8b, + 0xa438, 0x8c02, 0xa438, 0x6c4e, 0xa438, 0xc4bf, 0xa438, 0x8b8f, + 0xa438, 0x026c, 0xa438, 0x6def, 0xa438, 0x74e0, 0xa438, 0x830c, + 0xa438, 0xad20, 0xa438, 0x0302, 0xa438, 0x74ac, 0xa438, 0xccef, + 0xa438, 0x971b, 0xa438, 0x76ad, 0xa438, 0x5f02, 0xa438, 0xae13, + 0xa438, 0xef69, 0xa438, 0xef30, 0xa438, 0x1b32, 0xa438, 0xc4ef, + 0xa438, 0x46e4, 0xa438, 0x8ffb, 0xa438, 0xe58f, 0xa438, 0xfce7, + 0xa438, 0x8ffd, 0xa438, 0xcc10, 0xa438, 0x11ae, 0xa438, 0xb8d1, + 0xa438, 0x00a1, 0xa438, 0x1f03, 0xa438, 0xaf40, 0xa438, 0x4fbf, + 0xa438, 0x8b8c, 0xa438, 0x026c, 0xa438, 0x4ec4, 0xa438, 0xbf8b, + 0xa438, 0x8f02, 0xa438, 0x6c6d, 0xa438, 0xef74, 0xa438, 0xe083, + 0xa438, 0x0cad, 0xa438, 0x2003, 0xa438, 0x0274, 0xa438, 0xaccc, + 0xa438, 0xef97, 0xa438, 0x1b76, 0xa438, 0xad5f, 0xa438, 0x02ae, + 0xa438, 0x04ef, 0xa438, 0x69ef, 0xa438, 0x3111, 0xa438, 0xaed1, + 0xa438, 0x0287, 0xa438, 0x80af, 0xa438, 0x2293, 0xa438, 0xf8f9, + 0xa438, 0xfafb, 0xa438, 0xef59, 0xa438, 0xe080, 0xa438, 0x13ad, + 0xa438, 0x252f, 0xa438, 0xbf88, 0xa438, 0x2802, 0xa438, 0x6c6d, + 0xa438, 0xef64, 0xa438, 0x1f44, 0xa438, 0xe18f, 0xa438, 0xb91b, + 0xa438, 0x64ad, 0xa438, 0x4f1d, 0xa438, 0xd688, 0xa438, 0x2bd7, + 0xa438, 0x882e, 0xa438, 0x0274, 0xa438, 0x73ad, 0xa438, 0x5008, + 0xa438, 0xbf88, 0xa438, 0x3102, 0xa438, 0x737c, 0xa438, 0xae03, + 0xa438, 0x0287, 0xa438, 0xd0bf, 0xa438, 0x882b, 0xa438, 0x0273, + 0xa438, 0x73e0, 0xa438, 0x824c, 0xa438, 0xf621, 0xa438, 0xe482, + 0xa438, 0x4cbf, 0xa438, 0x8834, 0xa438, 0x0273, 0xa438, 0x7cef, + 0xa438, 0x95ff, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, + 0xa438, 0xfafb, 0xa438, 0xef79, 0xa438, 0xbf88, 0xa438, 0x1f02, + 0xa438, 0x737c, 0xa438, 0x1f22, 0xa438, 0xac32, 0xa438, 0x31ef, + 0xa438, 0x12bf, 0xa438, 0x8822, 0xa438, 0x026c, 0xa438, 0x4ed6, + 0xa438, 0x8fba, 0xa438, 0x1f33, 0xa438, 0xac3c, 0xa438, 0x1eef, + 0xa438, 0x13bf, 0xa438, 0x8837, 0xa438, 0x026c, 0xa438, 0x4eef, + 0xa438, 0x96d8, 0xa438, 0x19d9, 0xa438, 0xbf88, 0xa438, 0x2502, + 0xa438, 0x6c4e, 0xa438, 0xbf88, 0xa438, 0x2502, 0xa438, 0x6c4e, + 0xa438, 0x1616, 0xa438, 0x13ae, 0xa438, 0xdf12, 0xa438, 0xaecc, + 0xa438, 0xbf88, 0xa438, 0x1f02, 0xa438, 0x7373, 0xa438, 0xef97, + 0xa438, 0xfffe, 0xa438, 0xfdfc, 0xa438, 0x0466, 0xa438, 0xac88, + 0xa438, 0x54ac, 0xa438, 0x88f0, 0xa438, 0xac8a, 0xa438, 0x92ac, + 0xa438, 0xbadd, 0xa438, 0xac6c, 0xa438, 0xeeac, 0xa438, 0x6cff, + 0xa438, 0xad02, 0xa438, 0x99ac, 0xa438, 0x0030, 0xa438, 0xac88, + 0xa438, 0xd4c3, 0xa438, 0x5000, 0xa438, 0x0000, 0xa438, 0x0000, + 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, + 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x00b4, 0xa438, 0xecee, + 0xa438, 0x8298, 0xa438, 0x00af, 0xa438, 0x1412, 0xa438, 0xf8bf, + 0xa438, 0x8b5d, 0xa438, 0x026c, 0xa438, 0x6d58, 0xa438, 0x03e1, + 0xa438, 0x8fb8, 0xa438, 0x2901, 0xa438, 0xe58f, 0xa438, 0xb8a0, + 0xa438, 0x0049, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x02e5, + 0xa438, 0x8303, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, + 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, + 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, + 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, + 0xa438, 0xf728, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0xf628, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6002, + 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, + 0xa438, 0xaf89, 0xa438, 0x96a0, 0xa438, 0x0149, 0xa438, 0xef47, + 0xa438, 0xe483, 0xa438, 0x04e5, 0xa438, 0x8305, 0xa438, 0xbfc2, + 0xa438, 0x5f1a, 0xa438, 0x95f7, 0xa438, 0x05ee, 0xa438, 0xffd2, + 0xa438, 0x00d8, 0xa438, 0xf605, 0xa438, 0x1f11, 0xa438, 0xef60, + 0xa438, 0xbf8b, 0xa438, 0x3002, 0xa438, 0x6c4e, 0xa438, 0xbf8b, + 0xa438, 0x3302, 0xa438, 0x6c6d, 0xa438, 0xf729, 0xa438, 0xbf8b, + 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0xf629, 0xa438, 0xbf8b, + 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0x0c64, 0xa438, 0xef46, + 0xa438, 0xbf8b, 0xa438, 0x6302, 0xa438, 0x6c4e, 0xa438, 0x0289, + 0xa438, 0x9902, 0xa438, 0x3920, 0xa438, 0xaf89, 0xa438, 0x96a0, + 0xa438, 0x0249, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x06e5, + 0xa438, 0x8307, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, + 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, + 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, + 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, + 0xa438, 0xf72a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0xf62a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6602, + 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, + 0xa438, 0xaf89, 0xa438, 0x96ef, 0xa438, 0x47e4, 0xa438, 0x8308, + 0xa438, 0xe583, 0xa438, 0x09bf, 0xa438, 0xc25f, 0xa438, 0x1a95, + 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xd8f6, + 0xa438, 0x051f, 0xa438, 0x11ef, 0xa438, 0x60bf, 0xa438, 0x8b30, + 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b33, 0xa438, 0x026c, + 0xa438, 0x6df7, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, + 0xa438, 0x4ef6, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, + 0xa438, 0x4e0c, 0xa438, 0x64ef, 0xa438, 0x46bf, 0xa438, 0x8b69, + 0xa438, 0x026c, 0xa438, 0x4e02, 0xa438, 0x8999, 0xa438, 0x0239, + 0xa438, 0x20af, 0xa438, 0x8996, 0xa438, 0xaf39, 0xa438, 0x1ef8, + 0xa438, 0xf9fa, 0xa438, 0xe08f, 0xa438, 0xb838, 0xa438, 0x02ad, + 0xa438, 0x2702, 0xa438, 0xae03, 0xa438, 0xaf8b, 0xa438, 0x201f, + 0xa438, 0x66ef, 0xa438, 0x65bf, 0xa438, 0xc21f, 0xa438, 0x1a96, + 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdaf6, + 0xa438, 0x05bf, 0xa438, 0xc22f, 0xa438, 0x1a96, 0xa438, 0xf705, + 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdbf6, 0xa438, 0x05ef, + 0xa438, 0x021f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b3c, + 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021b, 0xa438, 0x031f, + 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b36, 0xa438, 0x026c, + 0xa438, 0x4eef, 0xa438, 0x021a, 0xa438, 0x031f, 0xa438, 0x110d, + 0xa438, 0x42bf, 0xa438, 0x8b39, 0xa438, 0x026c, 0xa438, 0x4ebf, + 0xa438, 0xc23f, 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, + 0xa438, 0xd200, 0xa438, 0xdaf6, 0xa438, 0x05bf, 0xa438, 0xc24f, + 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, + 0xa438, 0xdbf6, 0xa438, 0x05ef, 0xa438, 0x021f, 0xa438, 0x110d, + 0xa438, 0x42bf, 0xa438, 0x8b45, 0xa438, 0x026c, 0xa438, 0x4eef, + 0xa438, 0x021b, 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, + 0xa438, 0x8b3f, 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021a, + 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b42, + 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x56d0, 0xa438, 0x201f, + 0xa438, 0x11bf, 0xa438, 0x8b4e, 0xa438, 0x026c, 0xa438, 0x4ebf, + 0xa438, 0x8b48, 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b4b, + 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8578, 0xa438, 0xef03, + 0xa438, 0x480a, 0xa438, 0x2805, 0xa438, 0xef20, 0xa438, 0x1b01, + 0xa438, 0xad27, 0xa438, 0x3f1f, 0xa438, 0x44e0, 0xa438, 0x8560, + 0xa438, 0xe185, 0xa438, 0x61bf, 0xa438, 0x8b51, 0xa438, 0x026c, + 0xa438, 0x4ee0, 0xa438, 0x8566, 0xa438, 0xe185, 0xa438, 0x67bf, + 0xa438, 0x8b54, 0xa438, 0x026c, 0xa438, 0x4ee0, 0xa438, 0x856c, + 0xa438, 0xe185, 0xa438, 0x6dbf, 0xa438, 0x8b57, 0xa438, 0x026c, + 0xa438, 0x4ee0, 0xa438, 0x8572, 0xa438, 0xe185, 0xa438, 0x73bf, + 0xa438, 0x8b5a, 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8fb8, + 0xa438, 0x5900, 0xa438, 0xf728, 0xa438, 0xe58f, 0xa438, 0xb8af, + 0xa438, 0x8b2c, 0xa438, 0xe185, 0xa438, 0x791b, 0xa438, 0x21ad, + 0xa438, 0x373e, 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x62e1, + 0xa438, 0x8563, 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, + 0xa438, 0xe085, 0xa438, 0x68e1, 0xa438, 0x8569, 0xa438, 0xbf8b, + 0xa438, 0x5402, 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x6ee1, + 0xa438, 0x856f, 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, + 0xa438, 0xe085, 0xa438, 0x74e1, 0xa438, 0x8575, 0xa438, 0xbf8b, + 0xa438, 0x5a02, 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, + 0xa438, 0x00f7, 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae4a, + 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x64e1, 0xa438, 0x8565, + 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, 0xa438, 0xe085, + 0xa438, 0x6ae1, 0xa438, 0x856b, 0xa438, 0xbf8b, 0xa438, 0x5402, + 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x70e1, 0xa438, 0x8571, + 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, 0xa438, 0xe085, + 0xa438, 0x76e1, 0xa438, 0x8577, 0xa438, 0xbf8b, 0xa438, 0x5a02, + 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, 0xa438, 0x00f7, + 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae0c, 0xa438, 0xe18f, + 0xa438, 0xb839, 0xa438, 0x04ac, 0xa438, 0x2f04, 0xa438, 0xee8f, + 0xa438, 0xb800, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf0ac, + 0xa438, 0x8efc, 0xa438, 0xac8c, 0xa438, 0xf0ac, 0xa438, 0xfaf0, + 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xf6f0, 0xa438, 0xad00, + 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacfc, 0xa438, 0xf0ac, + 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, 0xa438, 0xf0f0, + 0xa438, 0xacb0, 0xa438, 0xf0ac, 0xa438, 0xaef0, 0xa438, 0xacac, + 0xa438, 0xf0ac, 0xa438, 0xaaf0, 0xa438, 0xacee, 0xa438, 0xf0b0, + 0xa438, 0x24f0, 0xa438, 0xb0a4, 0xa438, 0xf0b1, 0xa438, 0x24f0, + 0xa438, 0xb1a4, 0xa438, 0xee8f, 0xa438, 0xb800, 0xa438, 0xd400, + 0xa438, 0x00af, 0xa438, 0x3976, 0xa438, 0x66ac, 0xa438, 0xeabb, + 0xa438, 0xa430, 0xa438, 0x6e50, 0xa438, 0x6e53, 0xa438, 0x6e56, + 0xa438, 0x6e59, 0xa438, 0x6e5c, 0xa438, 0x6e5f, 0xa438, 0x6e62, + 0xa438, 0x6e65, 0xa438, 0xd9ac, 0xa438, 0x70f0, 0xa438, 0xac6a, + 0xa436, 0xb85e, 0xa438, 0x23b7, 0xa436, 0xb860, 0xa438, 0x74db, + 0xa436, 0xb862, 0xa438, 0x268c, 0xa436, 0xb864, 0xa438, 0x3FE5, + 0xa436, 0xb886, 0xa438, 0x2250, 0xa436, 0xb888, 0xa438, 0x140e, + 0xa436, 0xb88a, 0xa438, 0x3696, 0xa436, 0xb88c, 0xa438, 0x3973, + 0xa436, 0xb838, 0xa438, 0x00ff, 0xb820, 0x0010, 0xa436, 0x8464, + 0xa438, 0xaf84, 0xa438, 0x7caf, 0xa438, 0x8485, 0xa438, 0xaf85, + 0xa438, 0x13af, 0xa438, 0x851e, 0xa438, 0xaf85, 0xa438, 0xb9af, + 0xa438, 0x8684, 0xa438, 0xaf87, 0xa438, 0x01af, 0xa438, 0x8701, + 0xa438, 0xac38, 0xa438, 0x03af, 0xa438, 0x38bb, 0xa438, 0xaf38, + 0xa438, 0xc302, 0xa438, 0x4618, 0xa438, 0xbf85, 0xa438, 0x0a02, + 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x1002, 0xa438, 0x54c0, + 0xa438, 0xd400, 0xa438, 0x0fbf, 0xa438, 0x8507, 0xa438, 0x024f, + 0xa438, 0x48bf, 0xa438, 0x8504, 0xa438, 0x024f, 0xa438, 0x6759, + 0xa438, 0xf0a1, 0xa438, 0x3008, 0xa438, 0xbf85, 0xa438, 0x0d02, + 0xa438, 0x54c0, 0xa438, 0xae06, 0xa438, 0xbf85, 0xa438, 0x0d02, + 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x0402, 0xa438, 0x4f67, + 0xa438, 0xa183, 0xa438, 0x02ae, 0xa438, 0x15a1, 0xa438, 0x8502, + 0xa438, 0xae10, 0xa438, 0x59f0, 0xa438, 0xa180, 0xa438, 0x16bf, + 0xa438, 0x8501, 0xa438, 0x024f, 0xa438, 0x67a1, 0xa438, 0x381b, + 0xa438, 0xae0b, 0xa438, 0xe18f, 0xa438, 0xffbf, 0xa438, 0x84fe, + 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x17bf, 0xa438, 0x84fe, + 0xa438, 0x0254, 0xa438, 0xb7bf, 0xa438, 0x84fb, 0xa438, 0x0254, + 0xa438, 0xb7ae, 0xa438, 0x09a1, 0xa438, 0x5006, 0xa438, 0xbf84, + 0xa438, 0xfb02, 0xa438, 0x54c0, 0xa438, 0xaf04, 0xa438, 0x4700, + 0xa438, 0xad34, 0xa438, 0xfdad, 0xa438, 0x0670, 0xa438, 0xae14, + 0xa438, 0xf0a6, 0xa438, 0x00b8, 0xa438, 0xbd32, 0xa438, 0x30bd, + 0xa438, 0x30aa, 0xa438, 0xbd2c, 0xa438, 0xccbd, 0xa438, 0x2ca1, + 0xa438, 0x0705, 0xa438, 0xec80, 0xa438, 0xaf40, 0xa438, 0xf7af, + 0xa438, 0x40f5, 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, + 0xa438, 0x4f48, 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, + 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, + 0xa438, 0x024d, 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, + 0xa438, 0x67bf, 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, + 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, + 0xa438, 0x85b3, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, + 0xa438, 0xddbf, 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, + 0xa438, 0x8ffa, 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, + 0xa438, 0x024f, 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, + 0xa438, 0xad02, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, + 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, + 0xa438, 0xfcdd, 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, + 0xa438, 0xbf8f, 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, + 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, + 0xa438, 0xa702, 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0xa102, + 0xa438, 0x54b7, 0xa438, 0xaf3c, 0xa438, 0x2066, 0xa438, 0xb800, + 0xa438, 0xb8bd, 0xa438, 0x30ee, 0xa438, 0xbd2c, 0xa438, 0xb8bd, + 0xa438, 0x7040, 0xa438, 0xbd86, 0xa438, 0xc8bd, 0xa438, 0x8640, + 0xa438, 0xbd88, 0xa438, 0xc8bd, 0xa438, 0x8802, 0xa438, 0x1929, + 0xa438, 0xa202, 0xa438, 0x02ae, 0xa438, 0x03a2, 0xa438, 0x032e, + 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, + 0xa438, 0xe18f, 0xa438, 0xf7bf, 0xa438, 0x85ad, 0xa438, 0x024f, + 0xa438, 0x48e1, 0xa438, 0x8ff8, 0xa438, 0xbf85, 0xa438, 0xb002, + 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x85b3, + 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ffa, 0xa438, 0xbf85, + 0xa438, 0xb602, 0xa438, 0x4f48, 0xa438, 0xae2c, 0xa438, 0xd100, + 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0xe18f, + 0xa438, 0xfbbf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x48e1, + 0xa438, 0x8ffc, 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f48, + 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x85b3, 0xa438, 0x024f, + 0xa438, 0x48e1, 0xa438, 0x8ffe, 0xa438, 0xbf85, 0xa438, 0xb602, + 0xa438, 0x4f48, 0xa438, 0xbf86, 0xa438, 0x7e02, 0xa438, 0x4f67, + 0xa438, 0xa100, 0xa438, 0x02ae, 0xa438, 0x25a1, 0xa438, 0x041d, + 0xa438, 0xe18f, 0xa438, 0xf1bf, 0xa438, 0x8675, 0xa438, 0x024f, + 0xa438, 0x48e1, 0xa438, 0x8ff2, 0xa438, 0xbf86, 0xa438, 0x7802, + 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf3bf, 0xa438, 0x867b, + 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x29a1, 0xa438, 0x070b, + 0xa438, 0xae24, 0xa438, 0xbf86, 0xa438, 0x8102, 0xa438, 0x4f67, + 0xa438, 0xad28, 0xa438, 0x1be1, 0xa438, 0x8ff4, 0xa438, 0xbf86, + 0xa438, 0x7502, 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf5bf, + 0xa438, 0x8678, 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ff6, + 0xa438, 0xbf86, 0xa438, 0x7b02, 0xa438, 0x4f48, 0xa438, 0xaf09, + 0xa438, 0x8420, 0xa438, 0xbc32, 0xa438, 0x20bc, 0xa438, 0x3e76, + 0xa438, 0xbc08, 0xa438, 0xfda6, 0xa438, 0x1a00, 0xa438, 0xb64e, + 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, 0xa438, 0x4f48, + 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, 0xa438, 0xd10f, + 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0x024d, + 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x67bf, + 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, 0xa438, 0x024f, + 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, 0xa438, 0x85b3, + 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, 0xa438, 0xddbf, + 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ffa, + 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, 0xa438, 0x024f, + 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, 0xa438, 0xad02, + 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, 0xa438, 0xbf85, + 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfcdd, + 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, 0xa438, 0xbf8f, + 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, 0xa438, 0x4f67, + 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, 0xa438, 0xa702, + 0xa438, 0x54b7, 0xa438, 0xaf00, 0xa438, 0x8800, 0xa436, 0xb818, + 0xa438, 0x38b8, 0xa436, 0xb81a, 0xa438, 0x0444, 0xa436, 0xb81c, + 0xa438, 0x40ee, 0xa436, 0xb81e, 0xa438, 0x3C1A, 0xa436, 0xb850, + 0xa438, 0x0981, 0xa436, 0xb852, 0xa438, 0x0085, 0xa436, 0xb878, + 0xa438, 0xffff, 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, + 0xa438, 0x003f, 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, + 0xa438, 0x0000, 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, + 0xa436, 0x801E, 0xa438, 0x0021, 0xFFFF, 0xFFFF +}; + +static const u16 phy_mcu_ram_code_8125b_2[] = { + 0xa436, 0x8024, 0xa438, 0x3701, 0xa436, 0xB82E, 0xa438, 0x0001, + 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x801a, 0xa438, 0x1800, 0xa438, 0x803f, + 0xa438, 0x1800, 0xa438, 0x8045, 0xa438, 0x1800, 0xa438, 0x8067, + 0xa438, 0x1800, 0xa438, 0x806d, 0xa438, 0x1800, 0xa438, 0x8079, + 0xa438, 0x1800, 0xa438, 0x807e, 0xa438, 0xd093, 0xa438, 0xd1c4, + 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd704, 0xa438, 0x5fbc, + 0xa438, 0xd504, 0xa438, 0xc9f1, 0xa438, 0x1800, 0xa438, 0x0fc9, + 0xa438, 0xbb50, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd504, + 0xa438, 0x8c0f, 0xa438, 0xd500, 0xa438, 0x1000, 0xa438, 0x1519, + 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, 0xa438, 0x5fae, + 0xa438, 0x9b50, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, + 0xa438, 0x7fae, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd707, + 0xa438, 0x40a7, 0xa438, 0xd719, 0xa438, 0x4071, 0xa438, 0x1800, + 0xa438, 0x1557, 0xa438, 0xd719, 0xa438, 0x2f70, 0xa438, 0x803b, + 0xa438, 0x2f73, 0xa438, 0x156a, 0xa438, 0x5e70, 0xa438, 0x1800, + 0xa438, 0x155d, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd500, + 0xa438, 0xffed, 0xa438, 0xd709, 0xa438, 0x4054, 0xa438, 0xa788, + 0xa438, 0xd70b, 0xa438, 0x1800, 0xa438, 0x172a, 0xa438, 0xc0c1, + 0xa438, 0xc0c0, 0xa438, 0xd05a, 0xa438, 0xd1ba, 0xa438, 0xd701, + 0xa438, 0x2529, 0xa438, 0x022a, 0xa438, 0xd0a7, 0xa438, 0xd1b9, + 0xa438, 0xa208, 0xa438, 0x1000, 0xa438, 0x080e, 0xa438, 0xd701, + 0xa438, 0x408b, 0xa438, 0x1000, 0xa438, 0x0a65, 0xa438, 0xf003, + 0xa438, 0x1000, 0xa438, 0x0a6b, 0xa438, 0xd701, 0xa438, 0x1000, + 0xa438, 0x0920, 0xa438, 0x1000, 0xa438, 0x0915, 0xa438, 0x1000, + 0xa438, 0x0909, 0xa438, 0x228f, 0xa438, 0x804e, 0xa438, 0x9801, + 0xa438, 0xd71e, 0xa438, 0x5d61, 0xa438, 0xd701, 0xa438, 0x1800, + 0xa438, 0x022a, 0xa438, 0x2005, 0xa438, 0x091a, 0xa438, 0x3bd9, + 0xa438, 0x0919, 0xa438, 0x1800, 0xa438, 0x0916, 0xa438, 0x1000, + 0xa438, 0x14c5, 0xa438, 0xd703, 0xa438, 0x3181, 0xa438, 0x8077, + 0xa438, 0x60ad, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd703, + 0xa438, 0x5fba, 0xa438, 0x1800, 0xa438, 0x0cc7, 0xa438, 0xd096, + 0xa438, 0xd1a9, 0xa438, 0xd503, 0xa438, 0x1800, 0xa438, 0x0c94, + 0xa438, 0xa802, 0xa438, 0xa301, 0xa438, 0xa801, 0xa438, 0xc004, + 0xa438, 0xd710, 0xa438, 0x4000, 0xa438, 0x1800, 0xa438, 0x1e79, + 0xa436, 0xA026, 0xa438, 0x1e78, 0xa436, 0xA024, 0xa438, 0x0c93, + 0xa436, 0xA022, 0xa438, 0x0cc5, 0xa436, 0xA020, 0xa438, 0x0915, + 0xa436, 0xA006, 0xa438, 0x020a, 0xa436, 0xA004, 0xa438, 0x1726, + 0xa436, 0xA002, 0xa438, 0x1542, 0xa436, 0xA000, 0xa438, 0x0fc7, + 0xa436, 0xA008, 0xa438, 0xff00, 0xa436, 0xA016, 0xa438, 0x0010, + 0xa436, 0xA012, 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, + 0xa438, 0x8010, 0xa438, 0x1800, 0xa438, 0x801d, 0xa438, 0x1800, + 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, + 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, + 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0xd700, + 0xa438, 0x6090, 0xa438, 0x60d1, 0xa438, 0xc95c, 0xa438, 0xf007, + 0xa438, 0x60b1, 0xa438, 0xc95a, 0xa438, 0xf004, 0xa438, 0xc956, + 0xa438, 0xf002, 0xa438, 0xc94e, 0xa438, 0x1800, 0xa438, 0x00cd, + 0xa438, 0xd700, 0xa438, 0x6090, 0xa438, 0x60d1, 0xa438, 0xc95c, + 0xa438, 0xf007, 0xa438, 0x60b1, 0xa438, 0xc95a, 0xa438, 0xf004, + 0xa438, 0xc956, 0xa438, 0xf002, 0xa438, 0xc94e, 0xa438, 0x1000, + 0xa438, 0x022a, 0xa438, 0x1800, 0xa438, 0x0132, 0xa436, 0xA08E, + 0xa438, 0xffff, 0xa436, 0xA08C, 0xa438, 0xffff, 0xa436, 0xA08A, + 0xa438, 0xffff, 0xa436, 0xA088, 0xa438, 0xffff, 0xa436, 0xA086, + 0xa438, 0xffff, 0xa436, 0xA084, 0xa438, 0xffff, 0xa436, 0xA082, + 0xa438, 0x012f, 0xa436, 0xA080, 0xa438, 0x00cc, 0xa436, 0xA090, + 0xa438, 0x0103, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x8020, 0xa438, 0x1800, 0xa438, 0x802a, + 0xa438, 0x1800, 0xa438, 0x8035, 0xa438, 0x1800, 0xa438, 0x803c, + 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0x1800, 0xa438, 0x803c, + 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0xd107, 0xa438, 0xd042, + 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x8280, 0xa438, 0xd700, 0xa438, 0x6065, + 0xa438, 0xd125, 0xa438, 0xf002, 0xa438, 0xd12b, 0xa438, 0xd040, + 0xa438, 0x1800, 0xa438, 0x077f, 0xa438, 0x0cf0, 0xa438, 0x0c50, + 0xa438, 0xd104, 0xa438, 0xd040, 0xa438, 0x1000, 0xa438, 0x0aa8, + 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x1800, 0xa438, 0x0a2e, + 0xa438, 0xcb9b, 0xa438, 0xd110, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0b7b, 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x1800, 0xa438, 0x081b, 0xa438, 0x1000, + 0xa438, 0x09df, 0xa438, 0xd704, 0xa438, 0x7fb8, 0xa438, 0xa718, + 0xa438, 0x1800, 0xa438, 0x074e, 0xa436, 0xA10E, 0xa438, 0xffff, + 0xa436, 0xA10C, 0xa438, 0xffff, 0xa436, 0xA10A, 0xa438, 0xffff, + 0xa436, 0xA108, 0xa438, 0xffff, 0xa436, 0xA106, 0xa438, 0x074d, + 0xa436, 0xA104, 0xa438, 0x0818, 0xa436, 0xA102, 0xa438, 0x0a2c, + 0xa436, 0xA100, 0xa438, 0x077e, 0xa436, 0xA110, 0xa438, 0x000f, + 0xa436, 0xb87c, 0xa438, 0x8625, 0xa436, 0xb87e, 0xa438, 0xaf86, + 0xa438, 0x3daf, 0xa438, 0x8689, 0xa438, 0xaf88, 0xa438, 0x69af, + 0xa438, 0x8887, 0xa438, 0xaf88, 0xa438, 0x9caf, 0xa438, 0x889c, + 0xa438, 0xaf88, 0xa438, 0x9caf, 0xa438, 0x889c, 0xa438, 0xbf86, + 0xa438, 0x49d7, 0xa438, 0x0040, 0xa438, 0x0277, 0xa438, 0x7daf, + 0xa438, 0x2727, 0xa438, 0x0000, 0xa438, 0x7205, 0xa438, 0x0000, + 0xa438, 0x7208, 0xa438, 0x0000, 0xa438, 0x71f3, 0xa438, 0x0000, + 0xa438, 0x71f6, 0xa438, 0x0000, 0xa438, 0x7229, 0xa438, 0x0000, + 0xa438, 0x722c, 0xa438, 0x0000, 0xa438, 0x7217, 0xa438, 0x0000, + 0xa438, 0x721a, 0xa438, 0x0000, 0xa438, 0x721d, 0xa438, 0x0000, + 0xa438, 0x7211, 0xa438, 0x0000, 0xa438, 0x7220, 0xa438, 0x0000, + 0xa438, 0x7214, 0xa438, 0x0000, 0xa438, 0x722f, 0xa438, 0x0000, + 0xa438, 0x7223, 0xa438, 0x0000, 0xa438, 0x7232, 0xa438, 0x0000, + 0xa438, 0x7226, 0xa438, 0xf8f9, 0xa438, 0xfae0, 0xa438, 0x85b3, + 0xa438, 0x3802, 0xa438, 0xad27, 0xa438, 0x02ae, 0xa438, 0x03af, + 0xa438, 0x8830, 0xa438, 0x1f66, 0xa438, 0xef65, 0xa438, 0xbfc2, + 0xa438, 0x1f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, + 0xa438, 0x00da, 0xa438, 0xf605, 0xa438, 0xbfc2, 0xa438, 0x2f1a, + 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00db, + 0xa438, 0xf605, 0xa438, 0xef02, 0xa438, 0x1f11, 0xa438, 0x0d42, + 0xa438, 0xbf88, 0xa438, 0x4202, 0xa438, 0x6e7d, 0xa438, 0xef02, + 0xa438, 0x1b03, 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, + 0xa438, 0x4502, 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1a03, + 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4802, + 0xa438, 0x6e7d, 0xa438, 0xbfc2, 0xa438, 0x3f1a, 0xa438, 0x96f7, + 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00da, 0xa438, 0xf605, + 0xa438, 0xbfc2, 0xa438, 0x4f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, + 0xa438, 0xffd2, 0xa438, 0x00db, 0xa438, 0xf605, 0xa438, 0xef02, + 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4b02, + 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1b03, 0xa438, 0x1f11, + 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4e02, 0xa438, 0x6e7d, + 0xa438, 0xef02, 0xa438, 0x1a03, 0xa438, 0x1f11, 0xa438, 0x0d42, + 0xa438, 0xbf88, 0xa438, 0x5102, 0xa438, 0x6e7d, 0xa438, 0xef56, + 0xa438, 0xd020, 0xa438, 0x1f11, 0xa438, 0xbf88, 0xa438, 0x5402, + 0xa438, 0x6e7d, 0xa438, 0xbf88, 0xa438, 0x5702, 0xa438, 0x6e7d, + 0xa438, 0xbf88, 0xa438, 0x5a02, 0xa438, 0x6e7d, 0xa438, 0xe185, + 0xa438, 0xa0ef, 0xa438, 0x0348, 0xa438, 0x0a28, 0xa438, 0x05ef, + 0xa438, 0x201b, 0xa438, 0x01ad, 0xa438, 0x2735, 0xa438, 0x1f44, + 0xa438, 0xe085, 0xa438, 0x88e1, 0xa438, 0x8589, 0xa438, 0xbf88, + 0xa438, 0x5d02, 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x8ee1, + 0xa438, 0x858f, 0xa438, 0xbf88, 0xa438, 0x6002, 0xa438, 0x6e7d, + 0xa438, 0xe085, 0xa438, 0x94e1, 0xa438, 0x8595, 0xa438, 0xbf88, + 0xa438, 0x6302, 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x9ae1, + 0xa438, 0x859b, 0xa438, 0xbf88, 0xa438, 0x6602, 0xa438, 0x6e7d, + 0xa438, 0xaf88, 0xa438, 0x3cbf, 0xa438, 0x883f, 0xa438, 0x026e, + 0xa438, 0x9cad, 0xa438, 0x2835, 0xa438, 0x1f44, 0xa438, 0xe08f, + 0xa438, 0xf8e1, 0xa438, 0x8ff9, 0xa438, 0xbf88, 0xa438, 0x5d02, + 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfae1, 0xa438, 0x8ffb, + 0xa438, 0xbf88, 0xa438, 0x6002, 0xa438, 0x6e7d, 0xa438, 0xe08f, + 0xa438, 0xfce1, 0xa438, 0x8ffd, 0xa438, 0xbf88, 0xa438, 0x6302, + 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfee1, 0xa438, 0x8fff, + 0xa438, 0xbf88, 0xa438, 0x6602, 0xa438, 0x6e7d, 0xa438, 0xaf88, + 0xa438, 0x3ce1, 0xa438, 0x85a1, 0xa438, 0x1b21, 0xa438, 0xad37, + 0xa438, 0x341f, 0xa438, 0x44e0, 0xa438, 0x858a, 0xa438, 0xe185, + 0xa438, 0x8bbf, 0xa438, 0x885d, 0xa438, 0x026e, 0xa438, 0x7de0, + 0xa438, 0x8590, 0xa438, 0xe185, 0xa438, 0x91bf, 0xa438, 0x8860, + 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8596, 0xa438, 0xe185, + 0xa438, 0x97bf, 0xa438, 0x8863, 0xa438, 0x026e, 0xa438, 0x7de0, + 0xa438, 0x859c, 0xa438, 0xe185, 0xa438, 0x9dbf, 0xa438, 0x8866, + 0xa438, 0x026e, 0xa438, 0x7dae, 0xa438, 0x401f, 0xa438, 0x44e0, + 0xa438, 0x858c, 0xa438, 0xe185, 0xa438, 0x8dbf, 0xa438, 0x885d, + 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8592, 0xa438, 0xe185, + 0xa438, 0x93bf, 0xa438, 0x8860, 0xa438, 0x026e, 0xa438, 0x7de0, + 0xa438, 0x8598, 0xa438, 0xe185, 0xa438, 0x99bf, 0xa438, 0x8863, + 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x859e, 0xa438, 0xe185, + 0xa438, 0x9fbf, 0xa438, 0x8866, 0xa438, 0x026e, 0xa438, 0x7dae, + 0xa438, 0x0ce1, 0xa438, 0x85b3, 0xa438, 0x3904, 0xa438, 0xac2f, + 0xa438, 0x04ee, 0xa438, 0x85b3, 0xa438, 0x00af, 0xa438, 0x39d9, + 0xa438, 0x22ac, 0xa438, 0xeaf0, 0xa438, 0xacf6, 0xa438, 0xf0ac, + 0xa438, 0xfaf0, 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xfcf0, + 0xa438, 0xad00, 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacf0, + 0xa438, 0xf0ac, 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, + 0xa438, 0xb0f0, 0xa438, 0xacae, 0xa438, 0xf0ac, 0xa438, 0xacf0, + 0xa438, 0xacaa, 0xa438, 0xa100, 0xa438, 0x0ce1, 0xa438, 0x8ff7, + 0xa438, 0xbf88, 0xa438, 0x8402, 0xa438, 0x6e7d, 0xa438, 0xaf26, + 0xa438, 0xe9e1, 0xa438, 0x8ff6, 0xa438, 0xbf88, 0xa438, 0x8402, + 0xa438, 0x6e7d, 0xa438, 0xaf26, 0xa438, 0xf520, 0xa438, 0xac86, + 0xa438, 0xbf88, 0xa438, 0x3f02, 0xa438, 0x6e9c, 0xa438, 0xad28, + 0xa438, 0x03af, 0xa438, 0x3324, 0xa438, 0xad38, 0xa438, 0x03af, + 0xa438, 0x32e6, 0xa438, 0xaf32, 0xa438, 0xfb00, 0xa436, 0xb87c, + 0xa438, 0x8ff6, 0xa436, 0xb87e, 0xa438, 0x0705, 0xa436, 0xb87c, + 0xa438, 0x8ff8, 0xa436, 0xb87e, 0xa438, 0x19cc, 0xa436, 0xb87c, + 0xa438, 0x8ffa, 0xa436, 0xb87e, 0xa438, 0x28e3, 0xa436, 0xb87c, + 0xa438, 0x8ffc, 0xa436, 0xb87e, 0xa438, 0x1047, 0xa436, 0xb87c, + 0xa438, 0x8ffe, 0xa436, 0xb87e, 0xa438, 0x0a45, 0xa436, 0xb85e, + 0xa438, 0x271E, 0xa436, 0xb860, 0xa438, 0x3846, 0xa436, 0xb862, + 0xa438, 0x26E6, 0xa436, 0xb864, 0xa438, 0x32E3, 0xa436, 0xb886, + 0xa438, 0xffff, 0xa436, 0xb888, 0xa438, 0xffff, 0xa436, 0xb88a, + 0xa438, 0xffff, 0xa436, 0xb88c, 0xa438, 0xffff, 0xa436, 0xb838, + 0xa438, 0x000f, 0xb820, 0x0010, 0xa436, 0x846e, 0xa438, 0xaf84, + 0xa438, 0x86af, 0xa438, 0x8690, 0xa438, 0xaf86, 0xa438, 0xa4af, + 0xa438, 0x86a4, 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, + 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, 0xa438, 0xee82, + 0xa438, 0x5f00, 0xa438, 0x0284, 0xa438, 0x90af, 0xa438, 0x0441, + 0xa438, 0xf8e0, 0xa438, 0x8ff3, 0xa438, 0xa000, 0xa438, 0x0502, + 0xa438, 0x84a4, 0xa438, 0xae06, 0xa438, 0xa001, 0xa438, 0x0302, + 0xa438, 0x84c8, 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, + 0xa438, 0xe080, 0xa438, 0x15ad, 0xa438, 0x2702, 0xa438, 0xae03, + 0xa438, 0xaf84, 0xa438, 0xc3bf, 0xa438, 0x53ca, 0xa438, 0x0252, + 0xa438, 0xc8ad, 0xa438, 0x2807, 0xa438, 0x0285, 0xa438, 0x2cee, + 0xa438, 0x8ff3, 0xa438, 0x01ef, 0xa438, 0x95fd, 0xa438, 0xfc04, + 0xa438, 0xf8f9, 0xa438, 0xfaef, 0xa438, 0x69bf, 0xa438, 0x53ca, + 0xa438, 0x0252, 0xa438, 0xc8ac, 0xa438, 0x2822, 0xa438, 0xd480, + 0xa438, 0x00bf, 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9bf, + 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868a, + 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868d, 0xa438, 0x0252, + 0xa438, 0xa9ee, 0xa438, 0x8ff3, 0xa438, 0x00af, 0xa438, 0x8526, + 0xa438, 0xe08f, 0xa438, 0xf4e1, 0xa438, 0x8ff5, 0xa438, 0xe28f, + 0xa438, 0xf6e3, 0xa438, 0x8ff7, 0xa438, 0x1b45, 0xa438, 0xac27, + 0xa438, 0x0eee, 0xa438, 0x8ff4, 0xa438, 0x00ee, 0xa438, 0x8ff5, + 0xa438, 0x0002, 0xa438, 0x852c, 0xa438, 0xaf85, 0xa438, 0x26e0, + 0xa438, 0x8ff4, 0xa438, 0xe18f, 0xa438, 0xf52c, 0xa438, 0x0001, + 0xa438, 0xe48f, 0xa438, 0xf4e5, 0xa438, 0x8ff5, 0xa438, 0xef96, + 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, + 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa18b, + 0xa438, 0x02ae, 0xa438, 0x03af, 0xa438, 0x85da, 0xa438, 0xbf57, + 0xa438, 0x7202, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xf8e5, + 0xa438, 0x8ff9, 0xa438, 0xbf57, 0xa438, 0x7502, 0xa438, 0x52c8, + 0xa438, 0xe48f, 0xa438, 0xfae5, 0xa438, 0x8ffb, 0xa438, 0xbf57, + 0xa438, 0x7802, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfce5, + 0xa438, 0x8ffd, 0xa438, 0xbf57, 0xa438, 0x7b02, 0xa438, 0x52c8, + 0xa438, 0xe48f, 0xa438, 0xfee5, 0xa438, 0x8fff, 0xa438, 0xbf57, + 0xa438, 0x6c02, 0xa438, 0x52c8, 0xa438, 0xa102, 0xa438, 0x13ee, + 0xa438, 0x8ffc, 0xa438, 0x80ee, 0xa438, 0x8ffd, 0xa438, 0x00ee, + 0xa438, 0x8ffe, 0xa438, 0x80ee, 0xa438, 0x8fff, 0xa438, 0x00af, + 0xa438, 0x8599, 0xa438, 0xa101, 0xa438, 0x0cbf, 0xa438, 0x534c, + 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x0303, 0xa438, 0xaf85, + 0xa438, 0x77bf, 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, + 0xa438, 0x8b02, 0xa438, 0xae03, 0xa438, 0xaf86, 0xa438, 0x64e0, + 0xa438, 0x8ff8, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x8684, + 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffa, 0xa438, 0xe18f, + 0xa438, 0xfbbf, 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9e0, + 0xa438, 0x8ffc, 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x868a, + 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffe, 0xa438, 0xe18f, + 0xa438, 0xffbf, 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9af, + 0xa438, 0x867f, 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, + 0xa438, 0xa144, 0xa438, 0x3cbf, 0xa438, 0x547b, 0xa438, 0x0252, + 0xa438, 0xc8e4, 0xa438, 0x8ff8, 0xa438, 0xe58f, 0xa438, 0xf9bf, + 0xa438, 0x547e, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffa, + 0xa438, 0xe58f, 0xa438, 0xfbbf, 0xa438, 0x5481, 0xa438, 0x0252, + 0xa438, 0xc8e4, 0xa438, 0x8ffc, 0xa438, 0xe58f, 0xa438, 0xfdbf, + 0xa438, 0x5484, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffe, + 0xa438, 0xe58f, 0xa438, 0xffbf, 0xa438, 0x5322, 0xa438, 0x0252, + 0xa438, 0xc8a1, 0xa438, 0x4448, 0xa438, 0xaf85, 0xa438, 0xa7bf, + 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x313c, + 0xa438, 0xbf54, 0xa438, 0x7b02, 0xa438, 0x52c8, 0xa438, 0xe48f, + 0xa438, 0xf8e5, 0xa438, 0x8ff9, 0xa438, 0xbf54, 0xa438, 0x7e02, + 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfae5, 0xa438, 0x8ffb, + 0xa438, 0xbf54, 0xa438, 0x8102, 0xa438, 0x52c8, 0xa438, 0xe48f, + 0xa438, 0xfce5, 0xa438, 0x8ffd, 0xa438, 0xbf54, 0xa438, 0x8402, + 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfee5, 0xa438, 0x8fff, + 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa131, + 0xa438, 0x03af, 0xa438, 0x85a7, 0xa438, 0xd480, 0xa438, 0x00bf, + 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x8687, + 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868a, 0xa438, 0x0252, + 0xa438, 0xa9bf, 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9ef, + 0xa438, 0x95fd, 0xa438, 0xfc04, 0xa438, 0xf0d1, 0xa438, 0x2af0, + 0xa438, 0xd12c, 0xa438, 0xf0d1, 0xa438, 0x44f0, 0xa438, 0xd146, + 0xa438, 0xbf86, 0xa438, 0xa102, 0xa438, 0x52c8, 0xa438, 0xbf86, + 0xa438, 0xa102, 0xa438, 0x52c8, 0xa438, 0xd101, 0xa438, 0xaf06, + 0xa438, 0xa570, 0xa438, 0xce42, 0xa436, 0xb818, 0xa438, 0x043d, + 0xa436, 0xb81a, 0xa438, 0x06a3, 0xa436, 0xb81c, 0xa438, 0xffff, + 0xa436, 0xb81e, 0xa438, 0xffff, 0xa436, 0xb850, 0xa438, 0xffff, + 0xa436, 0xb852, 0xa438, 0xffff, 0xa436, 0xb878, 0xa438, 0xffff, + 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, 0xa438, 0x0003, + 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, 0xa438, 0x0000, + 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, 0xa436, 0x801E, + 0xa438, 0x0020, 0xFFFF, 0xFFFF +}; + +static void +rtl8125_real_set_phy_mcu_8125b_1(struct net_device *dev) +{ + rtl8125_set_phy_mcu_ram_code(dev, + phy_mcu_ram_code_8125b_1, + ARRAY_SIZE(phy_mcu_ram_code_8125b_1) + ); +} + +static void +rtl8125_set_phy_mcu_8125b_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125b_1(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static void +rtl8125_real_set_phy_mcu_8125b_2(struct net_device *dev) +{ + rtl8125_set_phy_mcu_ram_code(dev, + phy_mcu_ram_code_8125b_2, + ARRAY_SIZE(phy_mcu_ram_code_8125b_2) + ); +} + +static void +rtl8125_set_phy_mcu_8125b_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125b_2(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static void +rtl8125_init_hw_phy_mcu(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 require_disable_phy_disable_mode = FALSE; + + if (tp->NotWrRamCodeToMicroP == TRUE) return; + if (rtl8125_check_hw_phy_mcu_code_ver(dev)) return; + + if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(tp) && rtl8125_is_in_phy_disable_mode(dev)) + require_disable_phy_disable_mode = TRUE; + + if (require_disable_phy_disable_mode) + rtl8125_disable_phy_disable_mode(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_set_phy_mcu_8125a_1(dev); + break; + case CFG_METHOD_3: + rtl8125_set_phy_mcu_8125a_2(dev); + break; + case CFG_METHOD_4: + rtl8125_set_phy_mcu_8125b_1(dev); + break; + case CFG_METHOD_5: + rtl8125_set_phy_mcu_8125b_2(dev); + break; + } + + if (require_disable_phy_disable_mode) + rtl8125_enable_phy_disable_mode(dev); + + rtl8125_write_hw_phy_mcu_code_ver(dev); + + rtl8125_mdio_write(tp,0x1F, 0x0000); + + tp->HwHasWrRamCodeToMicroP = TRUE; +} +#endif + +static void +rtl8125_enable_phy_aldps(struct rtl8125_private *tp) +{ + //enable aldps + //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) + SetEthPhyOcpBit(tp, 0xA430, BIT_2); +} + +static void +rtl8125_hw_phy_config_8125a_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + ClearAndSetEthPhyOcpBit(tp, + 0xAD40, + 0x03FF, + 0x84 + ); + + SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); + ClearAndSetEthPhyOcpBit(tp, + 0xAD16, + 0x03FF, + 0x0006 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD32, + 0x003F, + 0x0006 + ); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xAC8A, + BIT_15|BIT_14|BIT_13|BIT_12, + BIT_14|BIT_13|BIT_12 + ); + SetEthPhyOcpBit(tp, 0xAD18, BIT_10); + SetEthPhyOcpBit(tp, 0xAD1A, 0x3FF); + SetEthPhyOcpBit(tp, 0xAD1C, 0x3FF); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xC400 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EB); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0x0700, + 0x0300 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F8); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x1C00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F1); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x3000 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80FE); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xA500 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8102); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x5000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8105); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x3300 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8100); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x7000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8104); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xF000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8106); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x6500 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xED00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); + SetEthPhyOcpBit(tp, 0xA438, BIT_8); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80E1); + ClearEthPhyOcpBit(tp, 0xA438, BIT_8); + + ClearAndSetEthPhyOcpBit(tp, + 0xBF06, + 0x003F, + 0x38 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x819F); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xD0B6); + + mdio_direct_write_phy_ocp(tp, 0xBC34, 0x5555); + ClearAndSetEthPhyOcpBit(tp, + 0xBF0A, + BIT_11|BIT_10|BIT_9, + BIT_11|BIT_9 + ); + + ClearEthPhyOcpBit(tp, 0xA5C0, BIT_10); + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + //enable aldps + //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); + ClearAndSetEthPhyOcpBit(tp, + 0xAD16, + 0x03FF, + 0x03FF + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD32, + 0x003F, + 0x0006 + ); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xACC0, + BIT_1|BIT_0, + BIT_1 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD40, + BIT_7|BIT_6|BIT_5, + BIT_6 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD40, + BIT_2|BIT_1|BIT_0, + BIT_2 + ); + ClearEthPhyOcpBit(tp, 0xAC14, BIT_7); + ClearEthPhyOcpBit(tp, 0xAC80, BIT_9|BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xAC5E, + BIT_2|BIT_1|BIT_0, + BIT_1 + ); + mdio_direct_write_phy_ocp(tp, 0xAD4C, 0x00A8); + mdio_direct_write_phy_ocp(tp, 0xAC5C, 0x01FF); + ClearAndSetEthPhyOcpBit(tp, + 0xAC8A, + BIT_7|BIT_6|BIT_5|BIT_4, + BIT_5|BIT_4 + ); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); + ClearAndSetEthPhyOcpBit(tp, + 0xB87E, + 0xFF00, + 0x0500 + ); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8159); + ClearAndSetEthPhyOcpBit(tp, + 0xB87E, + 0xFF00, + 0x0700 + ); + + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80A2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x809C); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x81B3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0043); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00A7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00D6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00EC); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00F6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FB); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FD); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FF); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00BB); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0058); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0029); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0013); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0009); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0004); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8257); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x020F); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7843); + + + rtl8125_set_phy_mcu_patch_request(tp); + + ClearEthPhyOcpBit(tp, 0xB896, BIT_0); + ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); + + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC091); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC092); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1214); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC094); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1516); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC096); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x171B); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC098); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1B1C); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1F1F); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09C); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2021); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2224); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A0); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A2); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A4); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC018); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0AF2); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0D4A); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01C); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0F26); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x118D); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC020); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x14F3); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC022); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x175A); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC024); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x19C0); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC026); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1C26); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC089); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6050); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x5F6E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08C); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC090); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); + + SetEthPhyOcpBit(tp, 0xB896, BIT_0); + + rtl8125_clear_phy_mcu_patch_request(tp); + + + SetEthPhyOcpBit(tp, 0xD068, BIT_13); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x81A2); + SetEthPhyOcpBit(tp, 0xA438, BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xB54C, + 0xFF00, + 0xDB00); + + + ClearEthPhyOcpBit(tp, 0xA454, BIT_0); + + + SetEthPhyOcpBit(tp, 0xA5D4, BIT_5); + ClearEthPhyOcpBit(tp, 0xAD4E, BIT_4); + ClearEthPhyOcpBit(tp, 0xA86A, BIT_0); + + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + + if (tp->RequirePhyMdiSwapPatch) { + u16 adccal_offset_p0; + u16 adccal_offset_p1; + u16 adccal_offset_p2; + u16 adccal_offset_p3; + u16 rg_lpf_cap_xg_p0; + u16 rg_lpf_cap_xg_p1; + u16 rg_lpf_cap_xg_p2; + u16 rg_lpf_cap_xg_p3; + u16 rg_lpf_cap_p0; + u16 rg_lpf_cap_p1; + u16 rg_lpf_cap_p2; + u16 rg_lpf_cap_p3; + + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0007, + 0x0001 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0000 + ); + adccal_offset_p0 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p0 &= 0x07FF; + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0008 + ); + adccal_offset_p1 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p1 &= 0x07FF; + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0010 + ); + adccal_offset_p2 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p2 &= 0x07FF; + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0018 + ); + adccal_offset_p3 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p3 &= 0x07FF; + + + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0000 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p3 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0008 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p2 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0010 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p1 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0018 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p0 + ); + + + rg_lpf_cap_xg_p0 = mdio_direct_read_phy_ocp(tp, 0xBD5A); + rg_lpf_cap_xg_p0 &= 0x001F; + rg_lpf_cap_xg_p1 = mdio_direct_read_phy_ocp(tp, 0xBD5A); + rg_lpf_cap_xg_p1 &= 0x1F00; + rg_lpf_cap_xg_p2 = mdio_direct_read_phy_ocp(tp, 0xBD5C); + rg_lpf_cap_xg_p2 &= 0x001F; + rg_lpf_cap_xg_p3 = mdio_direct_read_phy_ocp(tp, 0xBD5C); + rg_lpf_cap_xg_p3 &= 0x1F00; + rg_lpf_cap_p0 = mdio_direct_read_phy_ocp(tp, 0xBC18); + rg_lpf_cap_p0 &= 0x001F; + rg_lpf_cap_p1 = mdio_direct_read_phy_ocp(tp, 0xBC18); + rg_lpf_cap_p1 &= 0x1F00; + rg_lpf_cap_p2 = mdio_direct_read_phy_ocp(tp, 0xBC1A); + rg_lpf_cap_p2 &= 0x001F; + rg_lpf_cap_p3 = mdio_direct_read_phy_ocp(tp, 0xBC1A); + rg_lpf_cap_p3 &= 0x1F00; + + + ClearAndSetEthPhyOcpBit(tp, + 0xBD5A, + 0x001F, + rg_lpf_cap_xg_p3 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBD5A, + 0x1F00, + rg_lpf_cap_xg_p2 << 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBD5C, + 0x001F, + rg_lpf_cap_xg_p1 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBD5C, + 0x1F00, + rg_lpf_cap_xg_p0 << 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC18, + 0x001F, + rg_lpf_cap_p3 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC18, + 0x1F00, + rg_lpf_cap_p2 << 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC1A, + 0x001F, + rg_lpf_cap_p1 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC1A, + 0x1F00, + rg_lpf_cap_p0 << 8 + ); + } + + + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config_8125b_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + + SetEthPhyOcpBit(tp, 0xBC08, (BIT_3 | BIT_2)); + + + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FFF); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x0400 + ); + } + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8560); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8562); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8564); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8566); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8568); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x856A); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FFE); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0907); + } + ClearAndSetEthPhyOcpBit(tp, + 0xACDA, + 0xFF00, + 0xFF00 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xACDE, + 0xF000, + 0xF000 + ); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80D6); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F4); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x6077); + mdio_direct_write_phy_ocp(tp, 0xB506, 0x01E7); + mdio_direct_write_phy_ocp(tp, 0xAC8C, 0x0FFC); + mdio_direct_write_phy_ocp(tp, 0xAC46, 0xB7B4); + mdio_direct_write_phy_ocp(tp, 0xAC50, 0x0FBC); + mdio_direct_write_phy_ocp(tp, 0xAC3C, 0x9240); + mdio_direct_write_phy_ocp(tp, 0xAC4E, 0x0DB4); + mdio_direct_write_phy_ocp(tp, 0xACC6, 0x0707); + mdio_direct_write_phy_ocp(tp, 0xACC8, 0xA0D3); + mdio_direct_write_phy_ocp(tp, 0xAD08, 0x0007); + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8013); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0700); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FB9); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBA); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBC); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1900); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBE); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC0); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0800); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE500); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC4); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC6); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC8); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0400); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCa); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF300); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCc); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFD00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCe); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD0); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFB00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD4); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF400); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD6); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD8); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF600); + + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x813D); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x390E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x814F); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x790E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80B0); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F31); + SetEthPhyOcpBit(tp, 0xBF4C, BIT_1); + SetEthPhyOcpBit(tp, 0xBCCA, (BIT_9 | BIT_8)); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8141); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x320E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8153); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x720E); + ClearEthPhyOcpBit(tp, 0xA432, BIT_6); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8529); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x050E); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x816C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8174); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8178); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x817C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0719); + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0400); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0404); + } + mdio_direct_write_phy_ocp(tp, 0xBF4A, 0x001B); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8033); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8037); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803B); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFC32); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803F); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8043); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8047); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8145); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x370E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x770E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8169); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0D0A); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x817B); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1D0A); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8217); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x5000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x821A); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x5000 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DA); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0403); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x1000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0384); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BA); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x6C00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xF009); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BD); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x9F00 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf083); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DD); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03f0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x1000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CB); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CE); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x6C00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8009); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80D1); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x8000 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x200A); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xF0AD); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x809F); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6073); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x000B); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A9); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xC000 + ); + + rtl8125_set_phy_mcu_patch_request(tp); + + ClearEthPhyOcpBit(tp, 0xB896, BIT_0); + ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); + + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC23E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC240); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0103); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC242); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0507); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC244); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x090B); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC246); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0C0E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC248); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1012); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC24A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1416); + + SetEthPhyOcpBit(tp, 0xB896, BIT_0); + + rtl8125_clear_phy_mcu_patch_request(tp); + + + SetEthPhyOcpBit(tp, 0xA86A, BIT_0); + SetEthPhyOcpBit(tp, 0xA6F0, BIT_0); + + + mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); + mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); + mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); + mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); + mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); + ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); + SetEthPhyOcpBit(tp, 0xA438, BIT_12); + + + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config_8125b_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + + ClearAndSetEthPhyOcpBit(tp, + 0xAC46, + 0x00F0, + 0x0090 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD30, + 0x0003, + 0x0001 + ); + + + RTL_W16(tp, EEE_TXIDLE_TIMER_8125, tp->eee.tx_lpi_timer); + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F5); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x760E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8107); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x360E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8551); + ClearAndSetEthPhyOcpBit(tp, + 0xB87E, + BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8, + BIT_11 + ); + + ClearAndSetEthPhyOcpBit(tp, + 0xbf00, + 0xE000, + 0xA000 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xbf46, + 0x0F00, + 0x0300 + ); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8044); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x804A); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8050); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8056); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x805C); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8062); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8068); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x806E); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8074); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x807A); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + + + SetEthPhyOcpBit(tp, 0xA4CA, BIT_6); + + + ClearAndSetEthPhyOcpBit(tp, + 0xBF84, + BIT_15 | BIT_14 | BIT_13, + BIT_15 | BIT_13 + ); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + BIT_13 | BIT_10 | BIT_9 | BIT_8, + BIT_15 | BIT_14 | BIT_12 | BIT_11 + ); + + /* + mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); + mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); + mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); + mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); + mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); + ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); + SetEthPhyOcpBit(tp, 0xA438, BIT_12); + */ + + + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->resume_not_chg_speed) return; + + tp->phy_reset_enable(dev); + + if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) return; + +#ifndef ENABLE_USE_FIRMWARE_FILE + if (!tp->rtl_fw) { + rtl8125_set_hw_phy_before_init_phy_mcu(dev); + + rtl8125_init_hw_phy_mcu(dev); + } +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_hw_phy_config_8125a_1(dev); + break; + case CFG_METHOD_3: + rtl8125_hw_phy_config_8125a_2(dev); + break; + case CFG_METHOD_4: + rtl8125_hw_phy_config_8125b_1(dev); + break; + case CFG_METHOD_5: + rtl8125_hw_phy_config_8125b_2(dev); + break; + } + + //legacy force mode(Chap 22) + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + rtl8125_mdio_write(tp, 0x1F, 0x0A5B); + rtl8125_clear_eth_phy_bit(tp, 0x12, BIT_15); + rtl8125_mdio_write(tp, 0x1F, 0x0000); + break; + } + + /*ocp phy power saving*/ + /* + if (aspm) { + if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) + rtl8125_enable_ocp_phy_power_saving(dev); + } + */ + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + if (tp->eee.eee_enabled) + rtl8125_enable_eee(tp); + else + rtl8125_disable_eee(tp); + } +} + +static void +rtl8125_up(struct net_device *dev) +{ + rtl8125_hw_init(dev); + rtl8125_hw_reset(dev); + rtl8125_powerup_pll(dev); + rtl8125_hw_ephy_config(dev); + rtl8125_hw_phy_config(dev); + rtl8125_hw_config(dev); +} + +/* +static inline void rtl8125_delete_esd_timer(struct net_device *dev, struct timer_list *timer) +{ + del_timer_sync(timer); +} + +static inline void rtl8125_request_esd_timer(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->esd_timer; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + setup_timer(timer, rtl8125_esd_timer, (unsigned long)dev); +#else + timer_setup(timer, rtl8125_esd_timer, 0); +#endif + mod_timer(timer, jiffies + RTL8125_ESD_TIMEOUT); +} +*/ + +/* +static inline void rtl8125_delete_link_timer(struct net_device *dev, struct timer_list *timer) +{ + del_timer_sync(timer); +} + +static inline void rtl8125_request_link_timer(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->link_timer; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + setup_timer(timer, rtl8125_link_timer, (unsigned long)dev); +#else + timer_setup(timer, rtl8125_link_timer, 0); +#endif + mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); +} +*/ + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +static void +rtl8125_netpoll(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + for (i = 0; i < tp->irq_nvecs; i++) { + struct r8125_irq *irq = &tp->irq_tbl[i]; + struct r8125_napi *r8125napi = &tp->r8125napi[i]; + + disable_irq(irq->vector); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) + irq->handler(irq->vector, r8125napi); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + irq->handler(irq->vector, r8125napi, NULL); +#else + irq->handler(irq->vector, r8125napi); +#endif + + enable_irq(irq->vector); + } +} +#endif //CONFIG_NET_POLL_CONTROLLER + +static void +rtl8125_get_bios_setting(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->bios_setting = RTL_R32(tp, TimeInt2); + break; + } +} + +static void +rtl8125_set_bios_setting(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W32(tp, TimeInt2, tp->bios_setting); + break; + } +} + +static void +rtl8125_setup_mqs_reg(struct rtl8125_private *tp) +{ + int i; + + //tx + tp->tx_ring[0].tdsar_reg = TxDescStartAddrLow; + for (i = 1; i < R8125_MAX_TX_QUEUES; i++) { + tp->tx_ring[i].tdsar_reg = (u16)(TNPDS_Q1_LOW_8125 + (i - 1) * 8); + } + + for (i = 0; i < R8125_MAX_TX_QUEUES; i++) { + tp->tx_ring[i].hw_clo_ptr_reg = (u16)(HW_CLO_PTR0_8125 + i * 4); + tp->tx_ring[i].sw_tail_ptr_reg = (u16)(SW_TAIL_PTR0_8125 + i * 4); + } + + //rx + tp->rx_ring[0].rdsar_reg = RxDescAddrLow; + for (i = 1; i < R8125_MAX_RX_QUEUES; i++) { + tp->rx_ring[i].rdsar_reg = (u16)(RDSAR_Q1_LOW_8125 + (i - 1) * 8); + } + + tp->isr_reg[0] = ISR0_8125; + for (i = 1; i < R8125_MAX_QUEUES; i++) { + tp->isr_reg[i] = (u16)(ISR1_8125 + (i - 1) * 4); + } + + tp->imr_reg[0] = IMR0_8125; + for (i = 1; i < R8125_MAX_QUEUES; i++) { + tp->imr_reg[i] = (u16)(IMR1_8125 + (i - 1) * 4); + } +} + +static void +rtl8125_init_software_variable(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct pci_dev *pdev = tp->pci_dev; + + rtl8125_get_bios_setting(dev); + +#ifdef ENABLE_LIB_SUPPORT + tp->ring_lib_enabled = 1; +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + //tp->HwSuppDashVer = 3; + break; + default: + tp->HwSuppDashVer = 0; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwPkgDet = rtl8125_mac_ocp_read(tp, 0xDC00); + tp->HwPkgDet = (tp->HwPkgDet >> 3) & 0x07; + break; + } + + if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) + eee_enable = 0; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppNowIsOobVer = 1; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwPcieSNOffset = 0x16C; + break; + } + +#ifdef ENABLE_REALWOW_SUPPORT + rtl8125_get_realwow_hw_version(dev); +#endif //ENABLE_REALWOW_SUPPORT + + if (HW_DASH_SUPPORT_DASH(tp) && rtl8125_check_dash(tp)) + tp->DASH = 1; + else + tp->DASH = 0; + + if (tp->DASH) { + if (HW_DASH_SUPPORT_TYPE_3(tp)) { + u64 CmacMemPhysAddress; + void __iomem *cmac_ioaddr = NULL; + + //map CMAC IO space + CmacMemPhysAddress = rtl8125_csi_other_fun_read(tp, 0, 0x18); + if (!(CmacMemPhysAddress & BIT_0)) { + if (CmacMemPhysAddress & BIT_2) + CmacMemPhysAddress |= (u64)rtl8125_csi_other_fun_read(tp, 0, 0x1C) << 32; + + CmacMemPhysAddress &= 0xFFFFFFF0; + /* ioremap MMIO region */ + cmac_ioaddr = ioremap(CmacMemPhysAddress, R8125_REGS_SIZE); + } + + if (cmac_ioaddr == NULL) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "cannot remap CMAC MMIO, aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + } + + if (cmac_ioaddr == NULL) { + tp->DASH = 0; + } else { + tp->mapped_cmac_ioaddr = cmac_ioaddr; + } + } + + eee_enable = 0; + } + + if (HW_DASH_SUPPORT_TYPE_3(tp)) + tp->cmac_ioaddr = tp->mapped_cmac_ioaddr; + + if (aspm) { + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->org_pci_offset_99 = rtl8125_csi_fun0_read_byte(tp, 0x99); + tp->org_pci_offset_99 &= ~(BIT_5|BIT_6); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x264); + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x214); + break; + } + } + + pci_read_config_byte(pdev, 0x80, &tp->org_pci_offset_80); + pci_read_config_byte(pdev, 0x81, &tp->org_pci_offset_81); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + tp->use_timer_interrrupt = TRUE; + break; + } + + if (timer_count == 0 || tp->mcfg == CFG_METHOD_DEFAULT) + tp->use_timer_interrrupt = FALSE; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V3; + break; + default: + tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_NOT_SUPPORT; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppLinkChgWakeUpVer = 3; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppD0SpeedUpVer = 1; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppCheckPhyDisableModeVer = 3; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppTxNoCloseVer = 3; + break; + } + + if (tp->HwSuppTxNoCloseVer > 0 && tx_no_close_enable == 1) + tp->EnableTxNoClose = TRUE; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + tp->RequireLSOPatch = TRUE; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_2; + break; + case CFG_METHOD_3: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_3; + break; + case CFG_METHOD_4: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_4; + break; + case CFG_METHOD_5: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_5; + break; + } + + if (tp->HwIcVerUnknown) { + tp->NotWrRamCodeToMicroP = TRUE; + tp->NotWrMcuPatchCode = TRUE; + } + + switch (tp->mcfg) { + case CFG_METHOD_3: + if ((rtl8125_mac_ocp_read(tp, 0xD442) & BIT_5) && + (mdio_direct_read_phy_ocp(tp, 0xD068) & BIT_1) + ) { + tp->RequirePhyMdiSwapPatch = TRUE; + } + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppNumTxQueues = 2; + tp->HwSuppNumRxQueues = 4; + break; + default: + tp->HwSuppNumTxQueues = 1; + tp->HwSuppNumRxQueues = 1; + break; + } + + tp->num_tx_rings = 1; +#ifdef ENABLE_MULTIPLE_TX_QUEUE +#ifndef ENABLE_LIB_SUPPORT + tp->num_tx_rings = tp->HwSuppNumTxQueues; +#endif +#endif + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppRssVer = 5; + tp->HwSuppIndirTblEntries = 128; + break; + } + + tp->num_rx_rings = 1; +#ifdef ENABLE_RSS_SUPPORT +#ifdef ENABLE_LIB_SUPPORT + if (tp->HwSuppRssVer > 0) + tp->EnableRss = 1; +#else + if (tp->HwSuppRssVer > 0) { + u8 rss_queue_num = netif_get_num_default_rss_queues(); + tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)? + rss_queue_num : tp->HwSuppNumRxQueues; + + if (!(tp->num_rx_rings >= 2 && tp->irq_nvecs >= tp->num_rx_rings)) + tp->num_rx_rings = 1; + + if (tp->num_rx_rings >= 2) + tp->EnableRss = 1; + } +#endif + if (tp->EnableRss) + rtl8125_init_rss(tp); +#endif + + rtl8125_setup_mqs_reg(tp); + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppPtpVer = 1; + break; + } +#ifdef ENABLE_PTP_SUPPORT + if (tp->HwSuppPtpVer > 0) + tp->EnablePtp = 1; +#endif + + tp->InitRxDescType = RX_DESC_RING_TYPE_1; + if (tp->EnableRss || tp->EnablePtp) + tp->InitRxDescType = RX_DESC_RING_TYPE_3; + + tp->RxDescLength = RX_DESC_LEN_TYPE_1; + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + tp->RxDescLength = RX_DESC_LEN_TYPE_3; + tp->RxDescRingLength = NUM_RX_DESC * tp->RxDescLength; + + tp->rtl8125_rx_config = rtl_chip_info[tp->chipset].RCR_Cfg; + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + tp->rtl8125_rx_config |= EnableRxDescV3; + + //init interrupt + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppIsrVer = 2; + break; + default: + tp->HwSuppIsrVer = 1; + break; + } + + tp->HwCurrIsrVer = tp->HwSuppIsrVer; + if (tp->HwSuppIsrVer == 2) { + if (!(tp->features & RTL_FEATURE_MSIX) || + tp->irq_nvecs < R8125_MIN_MSIX_VEC_8125B) + tp->HwCurrIsrVer = 1; + } + + if (tp->HwCurrIsrVer < 2 || tp->irq_nvecs < 19) + tp->num_tx_rings = 1; + + if (tp->HwCurrIsrVer == 2) { + int i; + + tp->intr_mask = ISRIMR_V2_LINKCHG | ISRIMR_TOK_Q0; + if (tp->num_tx_rings > 1) + tp->intr_mask |= ISRIMR_TOK_Q1; + + for (i = 0; i < tp->num_rx_rings; i++) + tp->intr_mask |= ISRIMR_V2_ROK_Q0 << i; + } else { + tp->intr_mask = LinkChg | RxDescUnavail | TxOK | RxOK | SWInt; + tp->timer_intr_mask = LinkChg | PCSTimeout; + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + if (HW_DASH_SUPPORT_TYPE_3(tp)) { + tp->timer_intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); + tp->intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); + } + } +#endif + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + tp->HwSuppIntMitiVer = 3; + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppIntMitiVer = 4; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppExtendTallyCounterVer = 1; + break; + } + + timer_count_v2 = (timer_count / 0x100); + + tp->NicCustLedValue = RTL_R16(tp, CustomLED); + + tp->wol_opts = rtl8125_get_hw_wol(tp); + tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; + + rtl8125_link_option((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); + + tp->autoneg = autoneg_mode; + tp->speed = speed_mode; + tp->duplex = duplex_mode; + tp->advertising = advertising_mode; + tp->fcpause = rtl8125_fc_full; + + tp->max_jumbo_frame_size = rtl_chip_info[tp->chipset].jumbo_frame_sz; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + /* MTU range: 60 - hw-specific max */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = tp->max_jumbo_frame_size; +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + + if (tp->mcfg != CFG_METHOD_DEFAULT) { + struct ethtool_eee *eee = &tp->eee; + + eee->eee_enabled = eee_enable; + eee->supported = SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full; + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + eee->supported |= SUPPORTED_2500baseX_Full; + break; + } + eee->advertised = mmd_eee_adv_to_ethtool_adv_t(MDIO_EEE_1000T | MDIO_EEE_100TX); + eee->tx_lpi_timer = dev->mtu + ETH_HLEN + 0x20; + } + + tp->ptp_master_mode = enable_ptp_master_mode; +} + +static void +rtl8125_release_board(struct pci_dev *pdev, + struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + rtl8125_set_bios_setting(dev); + rtl8125_rar_set(tp, tp->org_mac_addr); + tp->wol_enabled = WOL_DISABLED; + + if (!tp->DASH) + rtl8125_phy_power_down(dev); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + FreeAllocatedDashShareMemory(dev); +#endif + + if (tp->mapped_cmac_ioaddr != NULL) + iounmap(tp->mapped_cmac_ioaddr); + + iounmap(ioaddr); + pci_release_regions(pdev); + pci_clear_mwi(pdev); + pci_disable_device(pdev); + free_netdev(dev); +} + +static int +rtl8125_get_mac_address(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + u8 mac_addr[MAC_ADDR_LEN]; + + for (i = 0; i < MAC_ADDR_LEN; i++) + mac_addr[i] = RTL_R8(tp, MAC0 + i); + + if(tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + *(u32*)&mac_addr[0] = RTL_R32(tp, BACKUP_ADDR0_8125); + *(u16*)&mac_addr[4] = RTL_R16(tp, BACKUP_ADDR1_8125); + } + + if (!is_valid_ether_addr(mac_addr)) { + netif_err(tp, probe, dev, "Invalid ether addr %pM\n", + mac_addr); + eth_hw_addr_random(dev); + ether_addr_copy(mac_addr, dev->dev_addr); + netif_info(tp, probe, dev, "Random ether addr %pM\n", + mac_addr); + tp->random_mac = 1; + } + + rtl8125_rar_set(tp, mac_addr); + + for (i = 0; i < MAC_ADDR_LEN; i++) { + dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); + tp->org_mac_addr[i] = dev->dev_addr[i]; /* keep the original MAC address */ + } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); +#endif +// memcpy(dev->dev_addr, dev->dev_addr, dev->addr_len); + + return 0; +} + +/** + * rtl8125_set_mac_address - Change the Ethernet Address of the NIC + * @dev: network interface device structure + * @p: pointer to an address structure + * + * Return 0 on success, negative on failure + **/ +static int +rtl8125_set_mac_address(struct net_device *dev, + void *p) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + rtl8125_rar_set(tp, dev->dev_addr); + + return 0; +} + +/****************************************************************************** + * rtl8125_rar_set - Puts an ethernet address into a receive address register. + * + * tp - The private data structure for driver + * addr - Address to put into receive address register + *****************************************************************************/ +void +rtl8125_rar_set(struct rtl8125_private *tp, + uint8_t *addr) +{ + uint32_t rar_low = 0; + uint32_t rar_high = 0; + + rar_low = ((uint32_t) addr[0] | + ((uint32_t) addr[1] << 8) | + ((uint32_t) addr[2] << 16) | + ((uint32_t) addr[3] << 24)); + + rar_high = ((uint32_t) addr[4] | + ((uint32_t) addr[5] << 8)); + + rtl8125_enable_cfg9346_write(tp); + RTL_W32(tp, MAC0, rar_low); + RTL_W32(tp, MAC4, rar_high); + + rtl8125_disable_cfg9346_write(tp); +} + +#ifdef ETHTOOL_OPS_COMPAT +static int ethtool_get_settings(struct net_device *dev, void *useraddr) +{ + struct ethtool_cmd cmd = { ETHTOOL_GSET }; + int err; + + if (!ethtool_ops->get_settings) + return -EOPNOTSUPP; + + err = ethtool_ops->get_settings(dev, &cmd); + if (err < 0) + return err; + + if (copy_to_user(useraddr, &cmd, sizeof(cmd))) + return -EFAULT; + return 0; +} + +static int ethtool_set_settings(struct net_device *dev, void *useraddr) +{ + struct ethtool_cmd cmd; + + if (!ethtool_ops->set_settings) + return -EOPNOTSUPP; + + if (copy_from_user(&cmd, useraddr, sizeof(cmd))) + return -EFAULT; + + return ethtool_ops->set_settings(dev, &cmd); +} + +static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) +{ + struct ethtool_drvinfo info; + struct ethtool_ops *ops = ethtool_ops; + + if (!ops->get_drvinfo) + return -EOPNOTSUPP; + + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GDRVINFO; + ops->get_drvinfo(dev, &info); + + if (ops->self_test_count) + info.testinfo_len = ops->self_test_count(dev); + if (ops->get_stats_count) + info.n_stats = ops->get_stats_count(dev); + if (ops->get_regs_len) + info.regdump_len = ops->get_regs_len(dev); + if (ops->get_eeprom_len) + info.eedump_len = ops->get_eeprom_len(dev); + + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +static int ethtool_get_regs(struct net_device *dev, char *useraddr) +{ + struct ethtool_regs regs; + struct ethtool_ops *ops = ethtool_ops; + void *regbuf; + int reglen, ret; + + if (!ops->get_regs || !ops->get_regs_len) + return -EOPNOTSUPP; + + if (copy_from_user(®s, useraddr, sizeof(regs))) + return -EFAULT; + + reglen = ops->get_regs_len(dev); + if (regs.len > reglen) + regs.len = reglen; + + regbuf = kmalloc(reglen, GFP_USER); + if (!regbuf) + return -ENOMEM; + + ops->get_regs(dev, ®s, regbuf); + + ret = -EFAULT; + if (copy_to_user(useraddr, ®s, sizeof(regs))) + goto out; + useraddr += offsetof(struct ethtool_regs, data); + if (copy_to_user(useraddr, regbuf, reglen)) + goto out; + ret = 0; + +out: + kfree(regbuf); + return ret; +} + +static int ethtool_get_wol(struct net_device *dev, char *useraddr) +{ + struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; + + if (!ethtool_ops->get_wol) + return -EOPNOTSUPP; + + ethtool_ops->get_wol(dev, &wol); + + if (copy_to_user(useraddr, &wol, sizeof(wol))) + return -EFAULT; + return 0; +} + +static int ethtool_set_wol(struct net_device *dev, char *useraddr) +{ + struct ethtool_wolinfo wol; + + if (!ethtool_ops->set_wol) + return -EOPNOTSUPP; + + if (copy_from_user(&wol, useraddr, sizeof(wol))) + return -EFAULT; + + return ethtool_ops->set_wol(dev, &wol); +} + +static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GMSGLVL }; + + if (!ethtool_ops->get_msglevel) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_msglevel(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_msglevel) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + ethtool_ops->set_msglevel(dev, edata.data); + return 0; +} + +static int ethtool_nway_reset(struct net_device *dev) +{ + if (!ethtool_ops->nway_reset) + return -EOPNOTSUPP; + + return ethtool_ops->nway_reset(dev); +} + +static int ethtool_get_link(struct net_device *dev, void *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GLINK }; + + if (!ethtool_ops->get_link) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_link(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) +{ + struct ethtool_eeprom eeprom; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->get_eeprom || !ops->get_eeprom_len) + return -EOPNOTSUPP; + + if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) + return -EFAULT; + + /* Check for wrap and zero */ + if (eeprom.offset + eeprom.len <= eeprom.offset) + return -EINVAL; + + /* Check for exceeding total eeprom len */ + if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) + return -EINVAL; + + data = kmalloc(eeprom.len, GFP_USER); + if (!data) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) + goto out; + + ret = ops->get_eeprom(dev, &eeprom, data); + if (ret) + goto out; + + ret = -EFAULT; + if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) + goto out; + if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) +{ + struct ethtool_eeprom eeprom; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->set_eeprom || !ops->get_eeprom_len) + return -EOPNOTSUPP; + + if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) + return -EFAULT; + + /* Check for wrap and zero */ + if (eeprom.offset + eeprom.len <= eeprom.offset) + return -EINVAL; + + /* Check for exceeding total eeprom len */ + if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) + return -EINVAL; + + data = kmalloc(eeprom.len, GFP_USER); + if (!data) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) + goto out; + + ret = ops->set_eeprom(dev, &eeprom, data); + if (ret) + goto out; + + if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) + ret = -EFAULT; + +out: + kfree(data); + return ret; +} + +static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) +{ + struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; + + if (!ethtool_ops->get_coalesce) + return -EOPNOTSUPP; + + ethtool_ops->get_coalesce(dev, &coalesce); + + if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) + return -EFAULT; + return 0; +} + +static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) +{ + struct ethtool_coalesce coalesce; + + if (!ethtool_ops->get_coalesce) + return -EOPNOTSUPP; + + if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) + return -EFAULT; + + return ethtool_ops->set_coalesce(dev, &coalesce); +} + +static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; + + if (!ethtool_ops->get_ringparam) + return -EOPNOTSUPP; + + ethtool_ops->get_ringparam(dev, &ringparam); + + if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) + return -EFAULT; + return 0; +} + +static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_ringparam ringparam; + + if (!ethtool_ops->get_ringparam) + return -EOPNOTSUPP; + + if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) + return -EFAULT; + + return ethtool_ops->set_ringparam(dev, &ringparam); +} + +static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; + + if (!ethtool_ops->get_pauseparam) + return -EOPNOTSUPP; + + ethtool_ops->get_pauseparam(dev, &pauseparam); + + if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) + return -EFAULT; + return 0; +} + +static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_pauseparam pauseparam; + + if (!ethtool_ops->get_pauseparam) + return -EOPNOTSUPP; + + if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) + return -EFAULT; + + return ethtool_ops->set_pauseparam(dev, &pauseparam); +} + +static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GRXCSUM }; + + if (!ethtool_ops->get_rx_csum) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_rx_csum(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_rx_csum) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + ethtool_ops->set_rx_csum(dev, edata.data); + return 0; +} + +static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + + if (!ethtool_ops->get_tx_csum) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_tx_csum(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_tx_csum) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_tx_csum(dev, edata.data); +} + +static int ethtool_get_sg(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GSG }; + + if (!ethtool_ops->get_sg) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_sg(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_sg(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_sg) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_sg(dev, edata.data); +} + +static int ethtool_get_tso(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GTSO }; + + if (!ethtool_ops->get_tso) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_tso(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_tso(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_tso) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_tso(dev, edata.data); +} + +static int ethtool_self_test(struct net_device *dev, char *useraddr) +{ + struct ethtool_test test; + struct ethtool_ops *ops = ethtool_ops; + u64 *data; + int ret; + + if (!ops->self_test || !ops->self_test_count) + return -EOPNOTSUPP; + + if (copy_from_user(&test, useraddr, sizeof(test))) + return -EFAULT; + + test.len = ops->self_test_count(dev); + data = kmalloc(test.len * sizeof(u64), GFP_USER); + if (!data) + return -ENOMEM; + + ops->self_test(dev, &test, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &test, sizeof(test))) + goto out; + useraddr += sizeof(test); + if (copy_to_user(useraddr, data, test.len * sizeof(u64))) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_get_strings(struct net_device *dev, void *useraddr) +{ + struct ethtool_gstrings gstrings; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->get_strings) + return -EOPNOTSUPP; + + if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) + return -EFAULT; + + switch (gstrings.string_set) { + case ETH_SS_TEST: + if (!ops->self_test_count) + return -EOPNOTSUPP; + gstrings.len = ops->self_test_count(dev); + break; + case ETH_SS_STATS: + if (!ops->get_stats_count) + return -EOPNOTSUPP; + gstrings.len = ops->get_stats_count(dev); + break; + default: + return -EINVAL; + } + + data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); + if (!data) + return -ENOMEM; + + ops->get_strings(dev, gstrings.string_set, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) + goto out; + useraddr += sizeof(gstrings); + if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_phys_id(struct net_device *dev, void *useraddr) +{ + struct ethtool_value id; + + if (!ethtool_ops->phys_id) + return -EOPNOTSUPP; + + if (copy_from_user(&id, useraddr, sizeof(id))) + return -EFAULT; + + return ethtool_ops->phys_id(dev, id.data); +} + +static int ethtool_get_stats(struct net_device *dev, void *useraddr) +{ + struct ethtool_stats stats; + struct ethtool_ops *ops = ethtool_ops; + u64 *data; + int ret; + + if (!ops->get_ethtool_stats || !ops->get_stats_count) + return -EOPNOTSUPP; + + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + + stats.n_stats = ops->get_stats_count(dev); + data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); + if (!data) + return -ENOMEM; + + ops->get_ethtool_stats(dev, &stats, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); + if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_ioctl(struct ifreq *ifr) +{ + struct net_device *dev = __dev_get_by_name(ifr->ifr_name); + void *useraddr = (void *) ifr->ifr_data; + u32 ethcmd; + + /* + * XXX: This can be pushed down into the ethtool_* handlers that + * need it. Keep existing behaviour for the moment. + */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!dev || !netif_device_present(dev)) + return -ENODEV; + + if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GSET: + return ethtool_get_settings(dev, useraddr); + case ETHTOOL_SSET: + return ethtool_set_settings(dev, useraddr); + case ETHTOOL_GDRVINFO: + return ethtool_get_drvinfo(dev, useraddr); + case ETHTOOL_GREGS: + return ethtool_get_regs(dev, useraddr); + case ETHTOOL_GWOL: + return ethtool_get_wol(dev, useraddr); + case ETHTOOL_SWOL: + return ethtool_set_wol(dev, useraddr); + case ETHTOOL_GMSGLVL: + return ethtool_get_msglevel(dev, useraddr); + case ETHTOOL_SMSGLVL: + return ethtool_set_msglevel(dev, useraddr); + case ETHTOOL_NWAY_RST: + return ethtool_nway_reset(dev); + case ETHTOOL_GLINK: + return ethtool_get_link(dev, useraddr); + case ETHTOOL_GEEPROM: + return ethtool_get_eeprom(dev, useraddr); + case ETHTOOL_SEEPROM: + return ethtool_set_eeprom(dev, useraddr); + case ETHTOOL_GCOALESCE: + return ethtool_get_coalesce(dev, useraddr); + case ETHTOOL_SCOALESCE: + return ethtool_set_coalesce(dev, useraddr); + case ETHTOOL_GRINGPARAM: + return ethtool_get_ringparam(dev, useraddr); + case ETHTOOL_SRINGPARAM: + return ethtool_set_ringparam(dev, useraddr); + case ETHTOOL_GPAUSEPARAM: + return ethtool_get_pauseparam(dev, useraddr); + case ETHTOOL_SPAUSEPARAM: + return ethtool_set_pauseparam(dev, useraddr); + case ETHTOOL_GRXCSUM: + return ethtool_get_rx_csum(dev, useraddr); + case ETHTOOL_SRXCSUM: + return ethtool_set_rx_csum(dev, useraddr); + case ETHTOOL_GTXCSUM: + return ethtool_get_tx_csum(dev, useraddr); + case ETHTOOL_STXCSUM: + return ethtool_set_tx_csum(dev, useraddr); + case ETHTOOL_GSG: + return ethtool_get_sg(dev, useraddr); + case ETHTOOL_SSG: + return ethtool_set_sg(dev, useraddr); + case ETHTOOL_GTSO: + return ethtool_get_tso(dev, useraddr); + case ETHTOOL_STSO: + return ethtool_set_tso(dev, useraddr); + case ETHTOOL_TEST: + return ethtool_self_test(dev, useraddr); + case ETHTOOL_GSTRINGS: + return ethtool_get_strings(dev, useraddr); + case ETHTOOL_PHYS_ID: + return ethtool_phys_id(dev, useraddr); + case ETHTOOL_GSTATS: + return ethtool_get_stats(dev, useraddr); + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; +} +#endif //ETHTOOL_OPS_COMPAT + +static int +rtl8125_do_ioctl(struct net_device *dev, + struct ifreq *ifr, + int cmd) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct mii_ioctl_data *data = if_mii(ifr); + int ret; + + ret = 0; + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = 32; /* Internal PHY */ + break; + + case SIOCGMIIREG: + rtl8125_mdio_write(tp, 0x1F, 0x0000); + data->val_out = rtl8125_mdio_read(tp, data->reg_num); + break; + + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, data->reg_num, data->val_in); + break; + +#ifdef ETHTOOL_OPS_COMPAT + case SIOCETHTOOL: + ret = ethtool_ioctl(ifr); + break; +#endif + +#ifdef ENABLE_DASH_SUPPORT + case SIOCDEVPRIVATE_RTLDASH: + if (!netif_running(dev)) { + ret = -ENODEV; + break; + } + if (!capable(CAP_NET_ADMIN)) { + ret = -EPERM; + break; + } + + ret = rtl8125_dash_ioctl(dev, ifr); + break; +#endif + +#ifdef ENABLE_REALWOW_SUPPORT + case SIOCDEVPRIVATE_RTLREALWOW: + if (!netif_running(dev)) { + ret = -ENODEV; + break; + } + + ret = rtl8125_realwow_ioctl(dev, ifr); + break; +#endif + +#ifdef ENABLE_PTP_SUPPORT + case SIOCSHWTSTAMP: + case SIOCGHWTSTAMP: + if (tp->EnablePtp) + ret = rtl8125_ptp_ioctl(dev, ifr, cmd); + else + ret = -EOPNOTSUPP; + break; +#endif + case SIOCRTLTOOL: + ret = rtl8125_tool_ioctl(tp, ifr); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static void +rtl8125_phy_power_up(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (rtl8125_is_in_phy_disable_mode(dev)) { + return; + } + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE); + + //wait ups resume (phy state 3) + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_wait_phy_ups_resume(dev, 3); + break; + }; +} + +static void +rtl8125_phy_power_down(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); +} + +static int __devinit +rtl8125_init_board(struct pci_dev *pdev, + struct net_device **dev_out, + void __iomem **ioaddr_out) +{ + void __iomem *ioaddr; + struct net_device *dev; + struct rtl8125_private *tp; + int rc = -ENOMEM, i, pm_cap; + + assert(ioaddr_out != NULL); + + /* dev zeroed in alloc_etherdev */ + dev = alloc_etherdev_mq(sizeof (*tp), R8125_MAX_QUEUES); + if (dev == NULL) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_drv(&debug)) + dev_err(&pdev->dev, "unable to alloc new ethernet\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out; + } + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + tp = netdev_priv(dev); + tp->dev = dev; + tp->pci_dev = pdev; + tp->msg_enable = netif_msg_init(debug.msg_enable, R8125_MSG_DEFAULT); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + if (!aspm) + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | + PCIE_LINK_STATE_CLKPM); +#endif + + /* enable device (incl. PCI PM wakeup and hotplug setup) */ + rc = pci_enable_device(pdev); + if (rc < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "enable failure\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out_free_dev; + } + + if (pci_set_mwi(pdev) < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_drv(&debug)) + dev_info(&pdev->dev, "Mem-Wr-Inval unavailable.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + } + + /* save power state before pci_enable_device overwrites it */ + pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (pm_cap) { + u16 pwr_command; + + pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); + } else { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) { + dev_err(&pdev->dev, "PowerManagement capability not found.\n"); + } +#else + printk("PowerManagement capability not found.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + + } + + /* make sure PCI base addr 1 is MMIO */ + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + rc = -ENODEV; + goto err_out_mwi; + } + /* check for weird/broken PCI region reporting */ + if (pci_resource_len(pdev, 2) < R8125_REGS_SIZE) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + rc = -ENODEV; + goto err_out_mwi; + } + + rc = pci_request_regions(pdev, MODULENAME); + if (rc < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "could not request regions.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out_mwi; + } + + if ((sizeof(dma_addr_t) > 4) && + use_dac && + !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && + !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + dev->features |= NETIF_F_HIGHDMA; + } else { + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "DMA configuration failed.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out_free_res; + } + } + + /* ioremap MMIO region */ + ioaddr = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); + if (ioaddr == NULL) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + rc = -EIO; + goto err_out_free_res; + } + + tp->mmio_addr = ioaddr; + + /* Identify chip attached to board */ + rtl8125_get_mac_version(tp); + + rtl8125_print_mac_version(tp); + + for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { + if (tp->mcfg == rtl_chip_info[i].mcfg) + break; + } + + if (i < 0) { + /* Unknown chip: assume array element #0, original RTL-8125 */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_printk(KERN_DEBUG, &pdev->dev, "unknown chip version, assuming %s\n", rtl_chip_info[0].name); +#else + printk("Realtek unknown chip version, assuming %s\n", rtl_chip_info[0].name); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + i++; + } + + tp->chipset = i; + + *ioaddr_out = ioaddr; + *dev_out = dev; +out: + return rc; + +err_out_free_res: + pci_release_regions(pdev); +err_out_mwi: + pci_clear_mwi(pdev); + pci_disable_device(pdev); +err_out_free_dev: + free_netdev(dev); +err_out: + *ioaddr_out = NULL; + *dev_out = NULL; + goto out; +} + +static void +rtl8125_esd_checker(struct rtl8125_private *tp) +{ + struct net_device *dev = tp->dev; + struct pci_dev *pdev = tp->pci_dev; + u8 cmd; + u16 io_base_l; + u16 mem_base_l; + u16 mem_base_h; + u8 ilr; + u16 resv_0x1c_h; + u16 resv_0x1c_l; + u16 resv_0x20_l; + u16 resv_0x20_h; + u16 resv_0x24_l; + u16 resv_0x24_h; + u16 resv_0x2c_h; + u16 resv_0x2c_l; + u32 pci_sn_l; + u32 pci_sn_h; + + tp->esd_flag = 0; + + pci_read_config_byte(pdev, PCI_COMMAND, &cmd); + if (cmd != tp->pci_cfg_space.cmd) { + printk(KERN_ERR "%s: cmd = 0x%02x, should be 0x%02x \n.", dev->name, cmd, tp->pci_cfg_space.cmd); + pci_write_config_byte(pdev, PCI_COMMAND, tp->pci_cfg_space.cmd); + tp->esd_flag |= BIT_0; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); + if (io_base_l != tp->pci_cfg_space.io_base_l) { + printk(KERN_ERR "%s: io_base_l = 0x%04x, should be 0x%04x \n.", dev->name, io_base_l, tp->pci_cfg_space.io_base_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); + tp->esd_flag |= BIT_1; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); + if (mem_base_l != tp->pci_cfg_space.mem_base_l) { + printk(KERN_ERR "%s: mem_base_l = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_l, tp->pci_cfg_space.mem_base_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); + tp->esd_flag |= BIT_2; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); + if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { + printk(KERN_ERR "%s: mem_base_h = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_h, tp->pci_cfg_space.mem_base_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); + tp->esd_flag |= BIT_3; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); + if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { + printk(KERN_ERR "%s: resv_0x1c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_l, tp->pci_cfg_space.resv_0x1c_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); + tp->esd_flag |= BIT_4; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); + if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { + printk(KERN_ERR "%s: resv_0x1c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_h, tp->pci_cfg_space.resv_0x1c_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); + tp->esd_flag |= BIT_5; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &resv_0x20_l); + if (resv_0x20_l != tp->pci_cfg_space.resv_0x20_l) { + printk(KERN_ERR "%s: resv_0x20_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_l, tp->pci_cfg_space.resv_0x20_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_4, tp->pci_cfg_space.resv_0x20_l); + tp->esd_flag |= BIT_6; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &resv_0x20_h); + if (resv_0x20_h != tp->pci_cfg_space.resv_0x20_h) { + printk(KERN_ERR "%s: resv_0x20_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_h, tp->pci_cfg_space.resv_0x20_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, tp->pci_cfg_space.resv_0x20_h); + tp->esd_flag |= BIT_7; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &resv_0x24_l); + if (resv_0x24_l != tp->pci_cfg_space.resv_0x24_l) { + printk(KERN_ERR "%s: resv_0x24_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_l, tp->pci_cfg_space.resv_0x24_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_5, tp->pci_cfg_space.resv_0x24_l); + tp->esd_flag |= BIT_8; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &resv_0x24_h); + if (resv_0x24_h != tp->pci_cfg_space.resv_0x24_h) { + printk(KERN_ERR "%s: resv_0x24_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_h, tp->pci_cfg_space.resv_0x24_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, tp->pci_cfg_space.resv_0x24_h); + tp->esd_flag |= BIT_9; + } + + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); + if (ilr != tp->pci_cfg_space.ilr) { + printk(KERN_ERR "%s: ilr = 0x%02x, should be 0x%02x \n.", dev->name, ilr, tp->pci_cfg_space.ilr); + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); + tp->esd_flag |= BIT_10; + } + + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); + if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { + printk(KERN_ERR "%s: resv_0x2c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_l, tp->pci_cfg_space.resv_0x2c_l); + pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); + tp->esd_flag |= BIT_11; + } + + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); + if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { + printk(KERN_ERR "%s: resv_0x2c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_h, tp->pci_cfg_space.resv_0x2c_h); + pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); + tp->esd_flag |= BIT_12; + } + + if (tp->HwPcieSNOffset > 0) { + pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); + if (pci_sn_l != tp->pci_cfg_space.pci_sn_l) { + printk(KERN_ERR "%s: pci_sn_l = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_l, tp->pci_cfg_space.pci_sn_l); + rtl8125_csi_write(tp, tp->HwPcieSNOffset, tp->pci_cfg_space.pci_sn_l); + tp->esd_flag |= BIT_13; + } + + pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); + if (pci_sn_h != tp->pci_cfg_space.pci_sn_h) { + printk(KERN_ERR "%s: pci_sn_h = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_h, tp->pci_cfg_space.pci_sn_h); + rtl8125_csi_write(tp, tp->HwPcieSNOffset + 4, tp->pci_cfg_space.pci_sn_h); + tp->esd_flag |= BIT_14; + } + } + + if (tp->esd_flag != 0) { + printk(KERN_ERR "%s: esd_flag = 0x%04x\n.\n", dev->name, tp->esd_flag); + netif_tx_stop_all_queues(dev); + netif_carrier_off(dev); + rtl8125_hw_reset(dev); + rtl8125_tx_clear(tp); + rtl8125_rx_clear(tp); + rtl8125_init_ring(dev); + rtl8125_up(dev); + rtl8125_enable_hw_linkchg_interrupt(tp); + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + tp->esd_flag = 0; + } +} +/* +static void +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +rtl8125_esd_timer(unsigned long __opaque) +#else +rtl8125_esd_timer(struct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + struct net_device *dev = (struct net_device *)__opaque; + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->esd_timer; +#else + struct rtl8125_private *tp = from_timer(tp, t, esd_timer); + //struct net_device *dev = tp->dev; + struct timer_list *timer = t; +#endif + rtl8125_esd_checker(tp); + + mod_timer(timer, jiffies + timeout); +} +*/ + +/* +static void +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +rtl8125_link_timer(unsigned long __opaque) +#else +rtl8125_link_timer(struct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + struct net_device *dev = (struct net_device *)__opaque; + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->link_timer; +#else + struct rtl8125_private *tp = from_timer(tp, t, link_timer); + struct net_device *dev = tp->dev; + struct timer_list *timer = t; +#endif + rtl8125_check_link_status(dev); + + mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); +} +*/ + +int +rtl8125_enable_msix(struct rtl8125_private *tp) +{ + int i, nvecs = 0; + struct msix_entry msix_ent[R8125_MAX_MSIX_VEC]; + //struct net_device *dev = tp->dev; + //const int len = sizeof(tp->irq_tbl[0].name); + + for (i = 0; i < R8125_MAX_MSIX_VEC; i++) { + msix_ent[i].entry = i; + msix_ent[i].vector = 0; + } + + nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent, + tp->min_irq_nvecs, tp->max_irq_nvecs); + if (nvecs < 0) + goto out; + + for (i = 0; i < nvecs; i++) { + struct r8125_irq *irq = &tp->irq_tbl[i]; + irq->vector = msix_ent[i].vector; + //snprintf(irq->name, len, "%s-%d", dev->name, i); + //irq->handler = rtl8125_interrupt_msix; + } + +out: + return nvecs; +} + +void rtl8125_dump_msix_tbl(struct rtl8125_private *tp) +{ + void __iomem *ioaddr; + + /* ioremap MMIO region */ + ioaddr = ioremap(pci_resource_start(tp->pci_dev, 4), pci_resource_len(tp->pci_dev, 4)); + if (ioaddr) { + int i = 0; + for (i=0; iirq_nvecs; i++) { + printk("entry 0x%d %08X %08X %08X %08X \n", + i, + readl(ioaddr + 16 * i), + readl(ioaddr + 16 * i + 4), + readl(ioaddr + 16 * i + 8), + readl(ioaddr + 16 * i + 12)); + } + iounmap(ioaddr); + } +} + +/* Cfg9346_Unlock assumed. */ +static int rtl8125_try_msi(struct rtl8125_private *tp) +{ + struct pci_dev *pdev = tp->pci_dev; + unsigned msi = 0; + int nvecs = 1; + + tp->max_irq_nvecs = 1; + tp->min_irq_nvecs = 1; +#ifndef DISABLE_MULTI_MSIX_VECTOR + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->max_irq_nvecs = R8125_MAX_MSIX_VEC_8125B; + tp->min_irq_nvecs = R8125_MIN_MSIX_VEC_8125B; + break; + } +#endif + +#if defined(RTL_USE_NEW_INTR_API) + if ((nvecs = pci_alloc_irq_vectors(pdev, tp->min_irq_nvecs, tp->max_irq_nvecs, PCI_IRQ_MSIX)) > 0) + msi |= RTL_FEATURE_MSIX; + else if ((nvecs = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES)) > 0 && + pci_dev_msi_enabled(pdev)) + msi |= RTL_FEATURE_MSI; +#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + if ((nvecs = rtl8125_enable_msix(tp)) > 0) + msi |= RTL_FEATURE_MSIX; + else if (!pci_enable_msi(pdev)) + msi |= RTL_FEATURE_MSI; +#endif + if (!(msi & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) + dev_info(&pdev->dev, "no MSI/MSI-X. Back to INTx.\n"); + + if (!(msi & RTL_FEATURE_MSIX) || nvecs < 1) + nvecs = 1; + + tp->irq_nvecs = nvecs; + + tp->features |= msi; + + return nvecs; +} + +static void rtl8125_disable_msi(struct pci_dev *pdev, struct rtl8125_private *tp) +{ +#if defined(RTL_USE_NEW_INTR_API) + if (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) + pci_free_irq_vectors(pdev); +#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + if (tp->features & (RTL_FEATURE_MSIX)) + pci_disable_msix(pdev); + else if (tp->features & (RTL_FEATURE_MSI)) + pci_disable_msi(pdev); +#endif + tp->features &= ~(RTL_FEATURE_MSI | RTL_FEATURE_MSIX); +} + +static int rtl8125_get_irq(struct pci_dev *pdev) +{ +#if defined(RTL_USE_NEW_INTR_API) + return pci_irq_vector(pdev, 0); +#else + return pdev->irq; +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +static const struct net_device_ops rtl8125_netdev_ops = { + .ndo_open = rtl8125_open, + .ndo_stop = rtl8125_close, + .ndo_get_stats = rtl8125_get_stats, + .ndo_start_xmit = rtl8125_start_xmit, + .ndo_tx_timeout = rtl8125_tx_timeout, + .ndo_change_mtu = rtl8125_change_mtu, + .ndo_set_mac_address = rtl8125_set_mac_address, + .ndo_do_ioctl = rtl8125_do_ioctl, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) + .ndo_set_multicast_list = rtl8125_set_rx_mode, +#else + .ndo_set_rx_mode = rtl8125_set_rx_mode, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) +#ifdef CONFIG_R8125_VLAN + .ndo_vlan_rx_register = rtl8125_vlan_rx_register, +#endif +#else + .ndo_fix_features = rtl8125_fix_features, + .ndo_set_features = rtl8125_set_features, +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = rtl8125_netpoll, +#endif +}; +#endif + + +#ifdef CONFIG_R8125_NAPI + +static int rtl8125_poll(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + int i; + + for (i = 0; i < tp->num_rx_rings; i++) + work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); + + for (i = 0; i < tp->num_tx_rings; i++) + rtl8125_tx_interrupt(&tp->tx_ring[i], budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + HandleDashInterrupt(tp->dev); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_switch_to_timer_interrupt(tp); + } + + return RTL_NAPI_RETURN_VALUE; +} + +#if 0 +static int rtl8125_poll_msix_ring(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + const int message_id = r8125napi->index; + + work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); + + rtl8125_tx_interrupt_with_vector(tp, message_id, budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH && message_id == 0) + HandleDashInterrupt(tp->dev); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + } + + return RTL_NAPI_RETURN_VALUE; +} +#endif + +static int rtl8125_poll_msix_tx(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + const int message_id = r8125napi->index; + + //suppress unused variable + (void)(dev); + + rtl8125_tx_interrupt_with_vector(tp, message_id, budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + } + + return RTL_NAPI_RETURN_VALUE; +} + +static int rtl8125_poll_msix_other(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + const int message_id = r8125napi->index; + + //suppress unused variable + (void)(dev); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); +#endif + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + + return 1; +} + +static int rtl8125_poll_msix_rx(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + const int message_id = r8125napi->index; + + work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + } + + return RTL_NAPI_RETURN_VALUE; +} + +static void rtl8125_enable_napi(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + int i; + + for (i = 0; i < tp->irq_nvecs; i++) + RTL_NAPI_ENABLE(tp->dev, &tp->r8125napi[i].napi); +#endif +} + +static void rtl8125_disable_napi(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + int i; + + for (i = 0; i < tp->irq_nvecs; i++) + RTL_NAPI_DISABLE(tp->dev, &tp->r8125napi[i].napi); +#endif +} + +static void rtl8125_del_napi(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + int i; + + for (i = 0; i < tp->irq_nvecs; i++) + RTL_NAPI_DEL((&tp->r8125napi[i])); +#endif +} +#endif //CONFIG_R8125_NAPI + +static void rtl8125_init_napi(struct rtl8125_private *tp) +{ + int i; + + for (i=0; iirq_nvecs; i++) { + struct r8125_napi *r8125napi = &tp->r8125napi[i]; +#ifdef CONFIG_R8125_NAPI + int (*poll)(struct napi_struct *, int); + + if (tp->features & RTL_FEATURE_MSIX && + tp->HwCurrIsrVer == 2) { + if (i < R8125_MAX_RX_QUEUES_VEC_V3) + poll = rtl8125_poll_msix_rx; + else if (i == 16 || i == 18) + poll = rtl8125_poll_msix_tx; + else + poll = rtl8125_poll_msix_other; + } else { + poll = rtl8125_poll; + } + + RTL_NAPI_CONFIG(tp->dev, r8125napi, poll, R8125_NAPI_WEIGHT); +#endif + + r8125napi->priv = tp; + r8125napi->index = i; + } +} + +static int +rtl8125_set_real_num_queue(struct rtl8125_private *tp) +{ + int retval = 0; + + retval = netif_set_real_num_tx_queues(tp->dev, tp->num_tx_rings); + if (retval < 0) + goto exit; + + retval = netif_set_real_num_rx_queues(tp->dev, tp->num_rx_rings); + if (retval < 0) + goto exit; + +exit: + return retval; +} + +static int __devinit +rtl8125_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *dev = NULL; + struct rtl8125_private *tp; + void __iomem *ioaddr = NULL; + static int board_idx = -1; + + int rc; + + assert(pdev != NULL); + assert(ent != NULL); + + board_idx++; + + if (netif_msg_drv(&debug)) + printk(KERN_INFO "%s 2.5Gigabit Ethernet driver %s loaded\n", + MODULENAME, RTL8125_VERSION); + + rc = rtl8125_init_board(pdev, &dev, &ioaddr); + if (rc) + goto out; + + tp = netdev_priv(dev); + assert(ioaddr != NULL); + + tp->set_speed = rtl8125_set_speed_xmii; + tp->get_settings = rtl8125_gset_xmii; + tp->phy_reset_enable = rtl8125_xmii_reset_enable; + tp->phy_reset_pending = rtl8125_xmii_reset_pending; + tp->link_ok = rtl8125_xmii_link_ok; + + rc = rtl8125_try_msi(tp); + if (rc < 0) { + dev_err(&pdev->dev, "Can't allocate interrupt\n"); + goto err_out_1; + } + + rtl8125_init_software_variable(dev); + + RTL_NET_DEVICE_OPS(rtl8125_netdev_ops); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + SET_ETHTOOL_OPS(dev, &rtl8125_ethtool_ops); +#endif + + dev->watchdog_timeo = RTL8125_TX_TIMEOUT; + dev->irq = rtl8125_get_irq(pdev); + dev->base_addr = (unsigned long) ioaddr; + + rtl8125_init_napi(tp); + +#ifdef CONFIG_R8125_VLAN + if (tp->mcfg != CFG_METHOD_DEFAULT) { + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + dev->vlan_rx_kill_vid = rtl8125_vlan_rx_kill_vid; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + } +#endif + + /* There has been a number of reports that using SG/TSO results in + * tx timeouts. However for a lot of people SG/TSO works fine. + * Therefore disable both features by default, but allow users to + * enable them. Use at own risk! + */ + tp->cp_cmd |= RTL_R16(tp, CPlusCmd); + if (tp->mcfg != CFG_METHOD_DEFAULT) { + dev->features |= NETIF_F_IP_CSUM; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + tp->cp_cmd |= RxChkSum; +#else + dev->features |= NETIF_F_RXCSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HIGHDMA; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) + dev->hw_features |= NETIF_F_RXALL; + dev->hw_features |= NETIF_F_RXFCS; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->features |= NETIF_F_IPV6_CSUM; + netif_set_gso_max_size(dev, LSO_64K); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) + dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO2; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) + +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + +#ifdef ENABLE_RSS_SUPPORT + if (tp->EnableRss) { + dev->hw_features |= NETIF_F_RXHASH; + dev->features |= NETIF_F_RXHASH; + } +#endif + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + AllocateDashShareMemory(dev); +#endif + +#ifdef ENABLE_LIB_SUPPORT + ATOMIC_INIT_NOTIFIER_HEAD(&tp->lib_nh); +#endif + rtl8125_init_all_schedule_work(tp); + + rc = rtl8125_set_real_num_queue(tp); + if (rc < 0) + goto err_out; + + rtl8125_exit_oob(dev); + + rtl8125_powerup_pll(dev); + + rtl8125_hw_init(dev); + + rtl8125_hw_reset(dev); + + /* Get production from EEPROM */ + rtl8125_eeprom_type(tp); + + if (tp->eeprom_type == EEPROM_TYPE_93C46 || tp->eeprom_type == EEPROM_TYPE_93C56) + rtl8125_set_eeprom_sel_low(tp); + + rtl8125_get_mac_address(dev); + + tp->fw_name = rtl_chip_fw_infos[tp->mcfg].fw_name; + + tp->tally_vaddr = dma_alloc_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), + &tp->tally_paddr, GFP_KERNEL); + if (!tp->tally_vaddr) { + rc = -ENOMEM; + goto err_out; + } + + rtl8125_tally_counter_clear(tp); + + pci_set_drvdata(pdev, dev); + + rc = register_netdev(dev); + if (rc) + goto err_out; + + printk(KERN_INFO "%s: This product is covered by one or more of the following patents: US6,570,884, US6,115,776, and US6,327,625.\n", MODULENAME); + + rtl8125_disable_rxdvgate(dev); + + device_set_wakeup_enable(&pdev->dev, tp->wol_enabled); + + netif_carrier_off(dev); + + printk("%s", GPL_CLAIM); + +out: + return rc; + +err_out: + if (tp->tally_vaddr != NULL) { + dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, + tp->tally_paddr); + + tp->tally_vaddr = NULL; + } +#ifdef CONFIG_R8125_NAPI + rtl8125_del_napi(tp); +#endif + rtl8125_disable_msi(pdev, tp); + +err_out_1: + rtl8125_release_board(pdev, dev); + + goto out; +} + +static void __devexit +rtl8125_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8125_private *tp = netdev_priv(dev); + + assert(dev != NULL); + assert(tp != NULL); + + set_bit(R8125_FLAG_DOWN, tp->task_flags); + + rtl8125_cancel_all_schedule_work(tp); + +#ifdef CONFIG_R8125_NAPI + rtl8125_del_napi(tp); +#endif + if (tp->DASH) + rtl8125_driver_stop(tp); + + unregister_netdev(dev); + rtl8125_disable_msi(pdev, tp); +#ifdef ENABLE_R8125_PROCFS + rtl8125_proc_remove(dev); +#endif + if (tp->tally_vaddr != NULL) { + dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, tp->tally_paddr); + tp->tally_vaddr = NULL; + } + + rtl8125_release_board(pdev, dev); + +#ifdef ENABLE_USE_FIRMWARE_FILE + rtl8125_release_firmware(tp); +#endif + + pci_set_drvdata(pdev, NULL); +} + +static void +rtl8125_set_rxbufsize(struct rtl8125_private *tp, + struct net_device *dev) +{ + unsigned int mtu = dev->mtu; + + tp->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 + 1 : RX_BUF_SIZE; +} + +static void rtl8125_free_irq(struct rtl8125_private *tp) +{ + int i; + + for (i=0; iirq_nvecs; i++) { + struct r8125_irq *irq = &tp->irq_tbl[i]; + struct r8125_napi *r8125napi = &tp->r8125napi[i]; + + if (irq->requested) { + irq->requested = 0; +#if defined(RTL_USE_NEW_INTR_API) + pci_free_irq(tp->pci_dev, i, r8125napi); +#else + free_irq(irq->vector, r8125napi); +#endif + } + } +} + +static int rtl8125_alloc_irq(struct rtl8125_private *tp) +{ + struct net_device *dev = tp->dev; + int rc = 0; + struct r8125_irq *irq; + struct r8125_napi *r8125napi; + int i = 0; + const int len = sizeof(tp->irq_tbl[0].name); + +#if defined(RTL_USE_NEW_INTR_API) + for (i=0; iirq_nvecs; i++) { + irq = &tp->irq_tbl[i]; + if (tp->features & RTL_FEATURE_MSIX && + tp->HwCurrIsrVer == 2) + irq->handler = rtl8125_interrupt_msix; + else + irq->handler = rtl8125_interrupt; + + r8125napi = &tp->r8125napi[i]; + snprintf(irq->name, len, "%s-%d", dev->name, i); + rc = pci_request_irq(tp->pci_dev, i, irq->handler, NULL, r8125napi, + irq->name); + if (rc) + break; + + irq->vector = pci_irq_vector(tp->pci_dev, i); + irq->requested = 1; + } +#else + unsigned long irq_flags = 0; +#ifdef ENABLE_LIB_SUPPORT + irq_flags |= IRQF_NO_SUSPEND; +#endif + if (tp->features & RTL_FEATURE_MSIX && + tp->HwCurrIsrVer == 2) { + for (i=0; iirq_nvecs; i++) { + irq = &tp->irq_tbl[i]; + irq->handler = rtl8125_interrupt_msix; + r8125napi = &tp->r8125napi[i]; + snprintf(irq->name, len, "%s-%d", dev->name, i); + rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); + + if (rc) + break; + + irq->requested = 1; + } + } else { + irq = &tp->irq_tbl[0]; + irq->handler = rtl8125_interrupt; + r8125napi = &tp->r8125napi[0]; + snprintf(irq->name, len, "%s-0", dev->name); + if (!(tp->features & RTL_FEATURE_MSIX)) + irq->vector = dev->irq; + irq_flags |= (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) ? 0 : SA_SHIRQ; + rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); + + if (rc == 0) + irq->requested = 1; + } +#endif + if (rc) + rtl8125_free_irq(tp); + + return rc; +} + +static int rtl8125_alloc_tx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_tx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + ring = &tp->tx_ring[i]; + ring->TxDescArray = dma_alloc_coherent(&pdev->dev, R8125_TX_RING_BYTES, + &ring->TxPhyAddr, GFP_KERNEL); + + if (!ring->TxDescArray) + return -1; + } + + return 0; +} + +static int rtl8125_alloc_rx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_rx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_rx_rings; i++) { + ring = &tp->rx_ring[i]; + ring->RxDescArray = dma_alloc_coherent(&pdev->dev, tp->RxDescRingLength, + &ring->RxPhyAddr, GFP_KERNEL); + + if (!ring->RxDescArray) + return -1; + } + + return 0; +} + +static void rtl8125_free_tx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_tx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + ring = &tp->tx_ring[i]; + if (ring->TxDescArray) { + dma_free_coherent(&pdev->dev, R8125_TX_RING_BYTES, ring->TxDescArray, + ring->TxPhyAddr); + ring->TxDescArray = NULL; + } + } +} + +static void rtl8125_free_rx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_rx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_rx_rings; i++) { + ring = &tp->rx_ring[i]; + if (ring->RxDescArray) { + dma_free_coherent(&pdev->dev, tp->RxDescRingLength, ring->RxDescArray, + ring->RxPhyAddr); + ring->RxDescArray = NULL; + } + } +} + +static void rtl8125_free_alloc_resources(struct rtl8125_private *tp) +{ + rtl8125_free_rx_desc(tp); + + rtl8125_free_tx_desc(tp); +} + +#ifdef ENABLE_USE_FIRMWARE_FILE +static void rtl8125_request_firmware(struct rtl8125_private *tp) +{ + struct rtl8125_fw *rtl_fw; + + /* firmware loaded already or no firmware available */ + if (tp->rtl_fw || !tp->fw_name) + return; + + rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); + if (!rtl_fw) + return; + + rtl_fw->phy_write = rtl8125_mdio_write; + rtl_fw->phy_read = rtl8125_mdio_read; + rtl_fw->mac_mcu_write = mac_mcu_write; + rtl_fw->mac_mcu_read = mac_mcu_read; + rtl_fw->fw_name = tp->fw_name; + rtl_fw->dev = tp_to_dev(tp); + + if (rtl8125_fw_request_firmware(rtl_fw)) + kfree(rtl_fw); + else + tp->rtl_fw = rtl_fw; +} +#endif + +int rtl8125_open(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int retval; + + retval = -ENOMEM; + +#ifdef ENABLE_R8125_PROCFS + rtl8125_proc_init(dev); +#endif + rtl8125_set_rxbufsize(tp, dev); + /* + * Rx and Tx descriptors needs 256 bytes alignment. + * pci_alloc_consistent provides more. + */ + if (rtl8125_alloc_tx_desc(tp) < 0 || rtl8125_alloc_rx_desc(tp) < 0) + goto err_free_all_allocated_mem; + + retval = rtl8125_init_ring(dev); + if (retval < 0) + goto err_free_all_allocated_mem; + + retval = rtl8125_alloc_irq(tp); + if (retval < 0) + goto err_free_all_allocated_mem; + + if (netif_msg_probe(tp)) { + printk(KERN_INFO "%s: 0x%lx, " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " + "IRQ %d\n", + dev->name, + dev->base_addr, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5], dev->irq); + } + +#ifdef ENABLE_USE_FIRMWARE_FILE + rtl8125_request_firmware(tp); +#endif + pci_set_master(tp->pci_dev); + +#ifdef CONFIG_R8125_NAPI + rtl8125_enable_napi(tp); +#endif + + rtl8125_exit_oob(dev); + + rtl8125_up(dev); + +#ifdef ENABLE_PTP_SUPPORT + if (tp->EnablePtp) + rtl8125_ptp_init(tp); +#endif + clear_bit(R8125_FLAG_DOWN, tp->task_flags); + + if (tp->resume_not_chg_speed) + rtl8125_check_link_status(dev); + else + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + + if (tp->esd_flag == 0) { + //rtl8125_request_esd_timer(dev); + + rtl8125_schedule_esd_work(tp); + } + + //rtl8125_request_link_timer(dev); + + rtl8125_enable_hw_linkchg_interrupt(tp); + +out: + + return retval; + +err_free_all_allocated_mem: + rtl8125_free_alloc_resources(tp); + + goto out; +} + +static void +set_offset70F(struct rtl8125_private *tp, u8 setting) +{ + u32 csi_tmp; + u32 temp = (u32)setting; + temp = temp << 24; + /*set PCI configuration space offset 0x70F to setting*/ + /*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/ + + csi_tmp = rtl8125_csi_read(tp, 0x70c) & 0x00ffffff; + rtl8125_csi_write(tp, 0x70c, csi_tmp | temp); +} + +static void +set_offset79(struct rtl8125_private *tp, u8 setting) +{ + //Set PCI configuration space offset 0x79 to setting + + struct pci_dev *pdev = tp->pci_dev; + u8 device_control; + + if (hwoptimize & HW_PATCH_SOC_LAN) return; + + pci_read_config_byte(pdev, 0x79, &device_control); + device_control &= ~0x70; + device_control |= setting; + pci_write_config_byte(pdev, 0x79, device_control); +} + +void +rtl8125_hw_set_rx_packet_filter(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 mc_filter[2]; /* Multicast hash filter */ + int rx_mode; + u32 tmp = 0; + + if (dev->flags & IFF_PROMISC) { + /* Unconditionally log net taps. */ + if (netif_msg_link(tp)) + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", + dev->name); + + rx_mode = + AcceptBroadcast | AcceptMulticast | AcceptMyPhys | + AcceptAllPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + } else if ((netdev_mc_count(dev) > multicast_filter_limit) + || (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter perfectly -- accept all multicasts. */ + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + } else { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) + struct dev_mc_list *mclist; + unsigned int i; + + rx_mode = AcceptBroadcast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0; + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) { + int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + rx_mode |= AcceptMulticast; + } +#else + struct netdev_hw_addr *ha; + + rx_mode = AcceptBroadcast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0; + netdev_for_each_mc_addr(ha, dev) { + int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + rx_mode |= AcceptMulticast; + } +#endif + } + + if (dev->features & NETIF_F_RXALL) + rx_mode |= (AcceptErr | AcceptRunt); + + tmp = mc_filter[0]; + mc_filter[0] = swab32(mc_filter[1]); + mc_filter[1] = swab32(tmp); + + tmp = tp->rtl8125_rx_config | rx_mode | (RTL_R32(tp, RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); + + RTL_W32(tp, RxConfig, tmp); + RTL_W32(tp, MAR0 + 0, mc_filter[0]); + RTL_W32(tp, MAR0 + 4, mc_filter[1]); +} + +static void +rtl8125_set_rx_mode(struct net_device *dev) +{ + rtl8125_hw_set_rx_packet_filter(dev); +} + +void +rtl8125_set_rx_q_num(struct rtl8125_private *tp, + unsigned int num_rx_queues) +{ + u16 q_ctrl; + u16 rx_q_num; + + rx_q_num = (u16)ilog2(num_rx_queues); + rx_q_num &= (BIT_0 | BIT_1 | BIT_2); + rx_q_num <<= 2; + q_ctrl = RTL_R16(tp, Q_NUM_CTRL_8125); + q_ctrl &= ~(BIT_2 | BIT_3 | BIT_4); + q_ctrl |= rx_q_num; + RTL_W16(tp, Q_NUM_CTRL_8125, q_ctrl); +} + +void +rtl8125_set_tx_q_num(struct rtl8125_private *tp, + unsigned int num_tx_queues) +{ + u16 mac_ocp_data; + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); + mac_ocp_data &= ~(BIT_11 | BIT_10); + mac_ocp_data |= ((ilog2(num_tx_queues) & 0x03) << 10); + rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); +} + +void +rtl8125_hw_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct pci_dev *pdev = tp->pci_dev; + u16 mac_ocp_data; + int i; + + RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); + + rtl8125_hw_reset(dev); + + rtl8125_enable_cfg9346_write(tp); + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + break; + } + + //clear io_rdy_l23 + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_1); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + //IntMITI_0-IntMITI_31 + for (i=0xA00; i<0xB00; i+=4) + RTL_W32(tp, i, 0x00000000); + break; + } + + //keep magic packet only + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B6); + mac_ocp_data &= BIT_0; + rtl8125_mac_ocp_write(tp, 0xC0B6, mac_ocp_data); + break; + } + + rtl8125_tally_counter_addr_fill(tp); + + rtl8125_enable_extend_tally_couter(tp); + + rtl8125_desc_addr_fill(tp); + + /* Set DMA burst size and Interframe Gap Time */ + RTL_W32(tp, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) | + (InterFrameGap << TxInterFrameGapShift)); + + if (tp->EnableTxNoClose) + RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_6)); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + set_offset70F(tp, 0x27); + set_offset79(tp, 0x50); + + RTL_W16(tp, 0x382, 0x221B); + +#ifdef ENABLE_RSS_SUPPORT + rtl8125_config_rss(tp); +#else + RTL_W32(tp, RSS_CTRL_8125, 0x00); +#endif + rtl8125_set_rx_q_num(tp, rtl8125_tot_rx_rings(tp)); + + RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); + + rtl8125_mac_ocp_write(tp, 0xC140, 0xFFFF); + rtl8125_mac_ocp_write(tp, 0xC142, 0xFFFF); + + //new tx desc format + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB58); + mac_ocp_data |= (BIT_0); + rtl8125_mac_ocp_write(tp, 0xEB58, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE614); + mac_ocp_data &= ~( BIT_10 | BIT_9 | BIT_8); + if (tp->mcfg == CFG_METHOD_4 || tp->mcfg == CFG_METHOD_5) { + mac_ocp_data |= ((2 & 0x07) << 8); + } else { + if (tp->DASH && !(rtl8125_csi_fun0_read_byte(tp, 0x79) & BIT_0)) + mac_ocp_data |= ((3 & 0x07) << 8); + else + mac_ocp_data |= ((4 & 0x07) << 8); + } + rtl8125_mac_ocp_write(tp, 0xE614, mac_ocp_data); + + rtl8125_set_tx_q_num(tp, rtl8125_tot_tx_rings(tp)); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); + mac_ocp_data &= ~(BIT_5 | BIT_4); + if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) + mac_ocp_data |= ((0x02 & 0x03) << 4); + rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); + mac_ocp_data &= ~BIT_0; + rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); + mac_ocp_data |= BIT_0; + rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); + mac_ocp_data |= (BIT_3|BIT_2); + rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB6A); + mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); + mac_ocp_data |= (BIT_5 | BIT_4 | BIT_1 | BIT_0); + rtl8125_mac_ocp_write(tp, 0xEB6A, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB50); + mac_ocp_data &= ~(BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5); + mac_ocp_data |= (BIT_6); + rtl8125_mac_ocp_write(tp, 0xEB50, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE056); + mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); + //mac_ocp_data |= (BIT_4 | BIT_5); + rtl8125_mac_ocp_write(tp, 0xE056, mac_ocp_data); + + RTL_W8(tp, TDFNR, 0x10); + + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE040); + mac_ocp_data &= ~(BIT_12); + rtl8125_mac_ocp_write(tp, 0xE040, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); + mac_ocp_data &= ~(BIT_1 | BIT_0); + mac_ocp_data |= (BIT_0); + rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); + + rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4000); + + SetMcuAccessRegBit(tp, 0xE052, (BIT_6 | BIT_5)); + ClearMcuAccessRegBit(tp, 0xE052, BIT_3 | BIT_7); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xD430); + mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); + mac_ocp_data |= 0x45F; + rtl8125_mac_ocp_write(tp, 0xD430, mac_ocp_data); + + //rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4F87); + if (!tp->DASH) + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6 | BIT_7); + else + RTL_W8(tp, 0xD0, (RTL_R8(tp, 0xD0) & ~BIT_6) | BIT_7); + + if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) + RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | BIT_0); + + rtl8125_disable_eee_plus(tp); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); + mac_ocp_data &= ~(BIT_2); + rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); + + SetMcuAccessRegBit(tp, 0xEB54, BIT_0); + udelay(1); + ClearMcuAccessRegBit(tp, 0xEB54, BIT_0); + RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~(BIT_4 | BIT_5)); + } + + /* csum offload command for RTL8125 */ + tp->tx_tcp_csum_cmd = TxTCPCS_C; + tp->tx_udp_csum_cmd = TxUDPCS_C; + tp->tx_ip_csum_cmd = TxIPCS_C; + tp->tx_ipv6_csum_cmd = TxIPV6F_C; + + /* config interrupt type for RTL8125B */ + if (tp->HwSuppIsrVer == 2) + rtl8125_hw_set_interrupt_type(tp, tp->HwCurrIsrVer); + + //other hw parameters + rtl8125_hw_clear_timer_int(dev); + + rtl8125_hw_clear_int_miti(dev); + + if (tp->use_timer_interrrupt && + (tp->HwCurrIsrVer == 2) && + (tp->HwSuppIntMitiVer == 4) && + (tp->features & RTL_FEATURE_MSIX)) { + int i; + for (i = 0; i < tp->irq_nvecs; i++) + rtl8125_hw_set_timer_int_8125(tp, i, timer_count_v2); + } + + rtl8125_enable_exit_l1_mask(tp); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE098, 0xC302); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (aspm) { + rtl8125_init_pci_offset_99(tp); + } + break; + } + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (aspm) { + rtl8125_init_pci_offset_180(tp); + } + break; + } + + tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | + Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | + ASF | Macdbgo_sel); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + RTL_W16(tp, CPlusCmd, tp->cp_cmd); +#else + rtl8125_hw_set_features(dev, dev->features); +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: { + int timeout; + for (timeout = 0; timeout < 10; timeout++) { + if ((rtl8125_mac_ocp_read(tp, 0xE00E) & BIT_13)==0) + break; + mdelay(1); + } + } + break; + } + + RTL_W16(tp, RxMaxSize, tp->rx_buf_sz); + + rtl8125_disable_rxdvgate(dev); + + if (!tp->pci_cfg_is_read) { + pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); + if (tp->HwPcieSNOffset > 0) { + tp->pci_cfg_space.pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); + tp->pci_cfg_space.pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); + } + + tp->pci_cfg_is_read = 1; + } + + /* Set Rx packet filter */ + rtl8125_hw_set_rx_packet_filter(dev); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH && !tp->dash_printer_enabled) + NICChkTypeEnableDashInterrupt(tp); +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (aspm) { + RTL_W8(tp, Config5, RTL_R8(tp, Config5) | BIT_0); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) | BIT_7); + } else { + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + } + break; + } + + rtl8125_disable_cfg9346_write(tp); + + udelay(10); +} + +void +rtl8125_hw_start(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); + + rtl8125_enable_hw_interrupt(tp); + + rtl8125_lib_reset_complete(tp); +} + +static int +rtl8125_change_mtu(struct net_device *dev, + int new_mtu) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret = 0; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) + if (new_mtu < ETH_MIN_MTU) + return -EINVAL; + else if (new_mtu > tp->max_jumbo_frame_size) + new_mtu = tp->max_jumbo_frame_size; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) + + dev->mtu = new_mtu; + + if (!netif_running(dev)) + goto out; + + rtl8125_down(dev); + + rtl8125_set_rxbufsize(tp, dev); + + ret = rtl8125_init_ring(dev); + + if (ret < 0) + goto err_out; + +#ifdef CONFIG_R8125_NAPI + rtl8125_enable_napi(tp); +#endif//CONFIG_R8125_NAPI + + //netif_tx_stop_all_queues(dev); + //netif_carrier_off(dev); + rtl8125_hw_config(dev); + rtl8125_enable_hw_linkchg_interrupt(tp); + + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + + //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); + //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); +out: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) + netdev_update_features(dev); +#endif + +err_out: + return ret; +} + +static void +rtl8125_free_rx_skb(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct sk_buff **sk_buff, + struct RxDesc *desc, + const u32 cur_rx) +{ + struct pci_dev *pdev = tp->pci_dev; + + dma_unmap_single(&pdev->dev, ring->RxDescPhyAddr[cur_rx], tp->rx_buf_sz, + DMA_FROM_DEVICE); + dev_kfree_skb(*sk_buff); + *sk_buff = NULL; + rtl8125_make_unusable_by_asic(tp, desc); +} + +static inline void +rtl8125_mark_to_asic_v3(struct RxDescV3 *descv3, + u32 rx_buf_sz) +{ + u32 eor = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1) & RingEnd; + + WRITE_ONCE(descv3->RxDescNormalDDWord4.opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); +} + +void +rtl8125_mark_to_asic(struct rtl8125_private *tp, + struct RxDesc *desc, + u32 rx_buf_sz) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + rtl8125_mark_to_asic_v3((struct RxDescV3 *)desc, rx_buf_sz); + else { + u32 eor = le32_to_cpu(desc->opts1) & RingEnd; + + WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); + } +} + +static inline void +rtl8125_map_to_asic(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct RxDesc *desc, + dma_addr_t mapping, + u32 rx_buf_sz, + const u32 cur_rx) +{ + ring->RxDescPhyAddr[cur_rx] = mapping; + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + ((struct RxDescV3 *)desc)->addr = cpu_to_le64(mapping); + else + desc->addr = cpu_to_le64(mapping); + wmb(); + rtl8125_mark_to_asic(tp, desc, rx_buf_sz); +} + +static int +rtl8125_alloc_rx_skb(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct sk_buff **sk_buff, + struct RxDesc *desc, + int rx_buf_sz, + const u32 cur_rx, + u8 in_intr) +{ + struct sk_buff *skb; + dma_addr_t mapping; + int ret = 0; + + if (in_intr) + skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, rx_buf_sz + RTK_RX_ALIGN); + else + skb = dev_alloc_skb(rx_buf_sz + RTK_RX_ALIGN); + + if (unlikely(!skb)) + goto err_out; + + skb_reserve(skb, RTK_RX_ALIGN); + + mapping = dma_map_single(tp_to_dev(tp), skb->data, rx_buf_sz, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); + goto err_out; + } + + *sk_buff = skb; + rtl8125_map_to_asic(tp, ring, desc, mapping, rx_buf_sz, cur_rx); +out: + return ret; + +err_out: + if (skb) + dev_kfree_skb(skb); + ret = -ENOMEM; + rtl8125_make_unusable_by_asic(tp, desc); + goto out; +} + +static void +_rtl8125_rx_clear(struct rtl8125_private *tp, struct rtl8125_rx_ring *ring) +{ + int i; + + for (i = 0; i < NUM_RX_DESC; i++) { + if (ring->Rx_skbuff[i]) { + rtl8125_free_rx_skb(tp, + ring, + ring->Rx_skbuff + i, + rtl8125_get_rxdesc(tp, ring->RxDescArray, i), + i); + ring->Rx_skbuff[i] = NULL; + } + } +} + +void +rtl8125_rx_clear(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_rx_rings; i++) + _rtl8125_rx_clear(tp, &tp->rx_ring[i]); +} + +static u32 +rtl8125_rx_fill(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct net_device *dev, + u32 start, + u32 end, + u8 in_intr) +{ + u32 cur; + + for (cur = start; end - cur > 0; cur++) { + int ret, i = cur % NUM_RX_DESC; + + if (ring->Rx_skbuff[i]) + continue; + + ret = rtl8125_alloc_rx_skb(tp, + ring, + ring->Rx_skbuff + i, + rtl8125_get_rxdesc(tp, ring->RxDescArray, i), + tp->rx_buf_sz, + i, + in_intr + ); + if (ret < 0) + break; + } + return cur - start; +} + +static inline void +rtl8125_mark_as_last_descriptor_8125(struct RxDescV3 *descv3) +{ + descv3->RxDescNormalDDWord4.opts1 |= cpu_to_le32(RingEnd); +} + +static inline void +rtl8125_mark_as_last_descriptor(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + rtl8125_mark_as_last_descriptor_8125((struct RxDescV3 *)desc); + else + desc->opts1 |= cpu_to_le32(RingEnd); +} + +static void +rtl8125_desc_addr_fill(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + RTL_W32(tp, ring->tdsar_reg, ((u64)ring->TxPhyAddr & DMA_BIT_MASK(32))); + RTL_W32(tp, ring->tdsar_reg + 4, ((u64)ring->TxPhyAddr >> 32)); + } + + for (i = 0; i < tp->num_rx_rings; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + RTL_W32(tp, ring->rdsar_reg, ((u64)ring->RxPhyAddr & DMA_BIT_MASK(32))); + RTL_W32(tp, ring->rdsar_reg + 4, ((u64)ring->RxPhyAddr >> 32)); + } +} + +static void +rtl8125_tx_desc_init(struct rtl8125_private *tp) +{ + int i = 0; + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + memset(ring->TxDescArray, 0x0, R8125_TX_RING_BYTES); + + ring->TxDescArray[NUM_TX_DESC - 1].opts1 = cpu_to_le32(RingEnd); + } +} + +static void +rtl8125_rx_desc_init(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_rx_rings; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + memset(ring->RxDescArray, 0x0, tp->RxDescRingLength); + } +} + +int +rtl8125_init_ring(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + rtl8125_init_ring_indexes(tp); + + rtl8125_tx_desc_init(tp); + rtl8125_rx_desc_init(tp); + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + memset(ring->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); + } + + for (i = 0; i < tp->num_rx_rings; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + + memset(ring->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); + if (rtl8125_rx_fill(tp, ring, dev, 0, NUM_RX_DESC, 0) != NUM_RX_DESC) + goto err_out; + + rtl8125_mark_as_last_descriptor(tp, rtl8125_get_rxdesc(tp, ring->RxDescArray, NUM_RX_DESC - 1)); + } + + return 0; + +err_out: + rtl8125_rx_clear(tp); + return -ENOMEM; +} + +static void +rtl8125_unmap_tx_skb(struct pci_dev *pdev, + struct ring_info *tx_skb, + struct TxDesc *desc) +{ + unsigned int len = tx_skb->len; + + dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); + + desc->opts1 = cpu_to_le32(RTK_MAGIC_DEBUG_VALUE); + desc->opts2 = 0x00; + desc->addr = RTL8125_MAGIC_NUMBER; + tx_skb->len = 0; +} + +static void +rtl8125_tx_clear_range(struct rtl8125_private *tp, + struct rtl8125_tx_ring *ring, + u32 start, + unsigned int n) +{ + unsigned int i; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + struct net_device *dev = tp->dev; +#endif + + for (i = 0; i < n; i++) { + unsigned int entry = (start + i) % NUM_TX_DESC; + struct ring_info *tx_skb = ring->tx_skb + entry; + unsigned int len = tx_skb->len; + + if (len) { + struct sk_buff *skb = tx_skb->skb; + + rtl8125_unmap_tx_skb(tp->pci_dev, tx_skb, + ring->TxDescArray + entry); + if (skb) { + RTLDEV->stats.tx_dropped++; + dev_kfree_skb_any(skb); + tx_skb->skb = NULL; + } + } + } +} + +void +rtl8125_tx_clear(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + rtl8125_tx_clear_range(tp, ring, ring->dirty_tx, NUM_TX_DESC); + ring->cur_tx = ring->dirty_tx = 0; + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); + schedule_delayed_work(&tp->reset_task, 4); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +} + +static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +} + +static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->linkchg_task, 4); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +} + +#define rtl8125_cancel_schedule_reset_work(a) +#define rtl8125_cancel_schedule_esd_work(a) +#define rtl8125_cancel_schedule_linkchg_work(a) + +#else +static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) +{ + set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); + schedule_delayed_work(&tp->reset_task, 4); +} + +static void rtl8125_cancel_schedule_reset_work(struct rtl8125_private *tp) +{ + struct work_struct *work = &tp->reset_task.work; + + if (!work->func) return; + + cancel_delayed_work_sync(&tp->reset_task); +} + +static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) +{ + set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); +} + +static void rtl8125_cancel_schedule_esd_work(struct rtl8125_private *tp) +{ + struct work_struct *work = &tp->esd_task.work; + + if (!work->func) return; + + cancel_delayed_work_sync(&tp->esd_task); +} + +static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) +{ + set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->linkchg_task, RTL8125_ESD_TIMEOUT); +} + +static void rtl8125_cancel_schedule_linkchg_work(struct rtl8125_private *tp) +{ + struct work_struct *work = &tp->linkchg_task.work; + + if (!work->func) return; + + cancel_delayed_work_sync(&tp->linkchg_task); +} +#endif + +static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&tp->reset_task, rtl8125_reset_task, dev); + INIT_WORK(&tp->esd_task, rtl8125_esd_task, dev); + INIT_WORK(&tp->linkchg_task, rtl8125_linkchg_task, dev); +#else + INIT_DELAYED_WORK(&tp->reset_task, rtl8125_reset_task); + INIT_DELAYED_WORK(&tp->esd_task, rtl8125_esd_task); + INIT_DELAYED_WORK(&tp->linkchg_task, rtl8125_linkchg_task); +#endif +} + +static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp) +{ + rtl8125_cancel_schedule_reset_work(tp); + rtl8125_cancel_schedule_esd_work(tp); + rtl8125_cancel_schedule_linkchg_work(tp); +} + +static void +rtl8125_wait_for_irq_complete(struct rtl8125_private *tp) +{ + if (tp->features & RTL_FEATURE_MSIX) { + int i; + for (i = 0; i < tp->irq_nvecs; i++) + synchronize_irq(tp->irq_tbl[i].vector); + } else { + synchronize_irq(tp->dev->irq); + } +} + +static void +_rtl8125_wait_for_quiescence(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + /* Wait for any pending NAPI task to complete */ +#ifdef CONFIG_R8125_NAPI + rtl8125_disable_napi(tp); +#endif//CONFIG_R8125_NAPI + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) + /* Give a racing hard_start_xmit a few cycles to complete. */ + synchronize_net(); +#endif + + rtl8125_irq_mask_and_ack(tp); + + rtl8125_wait_for_irq_complete(tp); +} + +static void +rtl8125_wait_for_quiescence(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + //suppress unused variable + (void)(tp); + + _rtl8125_wait_for_quiescence(dev); + +#ifdef CONFIG_R8125_NAPI + rtl8125_enable_napi(tp); +#endif//CONFIG_R8125_NAPI +} + +static int rtl8125_rx_nostuck(struct rtl8125_private *tp) +{ + int i, ret = 1; + for (i = 0; i < tp->num_rx_rings; i++) + ret &= (tp->rx_ring[i].dirty_rx == tp->rx_ring[i].cur_rx); + return ret; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_reset_task(void *_data) +{ + struct net_device *dev = _data; + struct rtl8125_private *tp = netdev_priv(dev); +#else +static void rtl8125_reset_task(struct work_struct *work) +{ + struct rtl8125_private *tp = + container_of(work, struct rtl8125_private, reset_task.work); + struct net_device *dev = tp->dev; +#endif + u32 budget = ~(u32)0; + int i; + + rtnl_lock(); + + if (!netif_running(dev) || + test_bit(R8125_FLAG_DOWN, tp->task_flags) || + !test_and_clear_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags)) + goto out_unlock; + + rtl8125_wait_for_quiescence(dev); + + for (i = 0; i < tp->num_rx_rings; i++) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], &budget); +#else + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + } + + netif_tx_stop_all_queues(dev); + netif_carrier_off(dev); + rtl8125_hw_reset(dev); + + rtl8125_tx_clear(tp); + + if (rtl8125_rx_nostuck(tp)) { + rtl8125_rx_clear(tp); + rtl8125_init_ring(dev); +#ifdef ENABLE_PTP_SUPPORT + rtl8125_ptp_reset(tp); +#endif + if (tp->resume_not_chg_speed) { + _rtl8125_check_link_status(dev); + + tp->resume_not_chg_speed = 0; + } else { + rtl8125_enable_hw_linkchg_interrupt(tp); + + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + } + } else { + if (unlikely(net_ratelimit())) { + struct rtl8125_private *tp = netdev_priv(dev); + + if (netif_msg_intr(tp)) { + printk(PFX KERN_EMERG + "%s: Rx buffers shortage\n", dev->name); + } + } + rtl8125_schedule_reset_work(tp); + } + +out_unlock: + rtnl_unlock(); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_esd_task(void *_data) +{ + struct net_device *dev = _data; + struct rtl8125_private *tp = netdev_priv(dev); +#else +static void rtl8125_esd_task(struct work_struct *work) +{ + struct rtl8125_private *tp = + container_of(work, struct rtl8125_private, esd_task.work); + struct net_device *dev = tp->dev; +#endif + rtnl_lock(); + + if (!netif_running(dev) || + test_bit(R8125_FLAG_DOWN, tp->task_flags) || + !test_and_clear_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags)) + goto out_unlock; + + rtl8125_esd_checker(tp); + + rtl8125_schedule_esd_work(tp); + +out_unlock: + rtnl_unlock(); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_linkchg_task(void *_data) +{ + struct net_device *dev = _data; + //struct rtl8125_private *tp = netdev_priv(dev); +#else +static void rtl8125_linkchg_task(struct work_struct *work) +{ + struct rtl8125_private *tp = + container_of(work, struct rtl8125_private, linkchg_task.work); + struct net_device *dev = tp->dev; +#endif + rtnl_lock(); + + if (!netif_running(dev) || + test_bit(R8125_FLAG_DOWN, tp->task_flags) || + !test_and_clear_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags)) + goto out_unlock; + + rtl8125_check_link_status(dev); + +out_unlock: + rtnl_unlock(); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static void +rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue) +#else +static void +rtl8125_tx_timeout(struct net_device *dev) +#endif +{ + struct rtl8125_private *tp = netdev_priv(dev); + + /* Let's wait a bit while any (async) irq lands on */ + rtl8125_schedule_reset_work(tp); +} + +static u32 +rtl8125_get_txd_opts1(u32 opts1, u32 len, unsigned int entry) +{ + u32 status = opts1 | len; + + if (entry == NUM_TX_DESC - 1) + status |= RingEnd; + + return status; +} + +static int +rtl8125_xmit_frags(struct rtl8125_private *tp, + struct rtl8125_tx_ring *ring, + struct sk_buff *skb, + const u32 *opts) +{ + struct skb_shared_info *info = skb_shinfo(skb); + unsigned int cur_frag, entry; + struct TxDesc *txd = NULL; + const unsigned char nr_frags = info->nr_frags; + unsigned long PktLenCnt = 0; + bool LsoPatchEnabled = FALSE; + + entry = ring->cur_tx; + for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { + skb_frag_t *frag = info->frags + cur_frag; + dma_addr_t mapping; + u32 status, len; + void *addr; + + entry = (entry + 1) % NUM_TX_DESC; + + txd = ring->TxDescArray + entry; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) + len = frag->size; + addr = ((void *) page_address(frag->page)) + frag->page_offset; +#else + len = skb_frag_size(frag); + addr = skb_frag_address(frag); +#endif + if (tp->RequireLSOPatch && + (cur_frag == nr_frags - 1) && + (opts[0] & (GiantSendv4|GiantSendv6)) && + PktLenCnt < ETH_FRAME_LEN && + len > 1) { + len -= 1; + mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, tp->dev, + "Failed to map TX fragments DMA!\n"); + goto err_out; + } + + /* anti gcc 2.95.3 bugware (sic) */ + status = rtl8125_get_txd_opts1(opts[0], len, entry); + + txd->addr = cpu_to_le64(mapping); + + ring->tx_skb[entry].len = len; + + txd->opts2 = cpu_to_le32(opts[1]); + wmb(); + txd->opts1 = cpu_to_le32(status); + + //second txd + addr += len; + len = 1; + entry = (entry + 1) % NUM_TX_DESC; + txd = ring->TxDescArray + entry; + cur_frag += 1; + + LsoPatchEnabled = TRUE; + } + + mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, tp->dev, + "Failed to map TX fragments DMA!\n"); + goto err_out; + } + + /* anti gcc 2.95.3 bugware (sic) */ + status = rtl8125_get_txd_opts1(opts[0], len, entry); + if (cur_frag == (nr_frags - 1) || LsoPatchEnabled == TRUE) { + //ring->tx_skb[entry].skb = skb; + status |= LastFrag; + } + + txd->addr = cpu_to_le64(mapping); + + ring->tx_skb[entry].len = len; + + txd->opts2 = cpu_to_le32(opts[1]); + wmb(); + txd->opts1 = cpu_to_le32(status); + + PktLenCnt += len; + } + + return cur_frag; + +err_out: + rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, cur_frag); + return -EIO; +} + +static inline +__be16 get_protocol(struct sk_buff *skb) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) + return vlan_get_protocol(skb); +#else + __be16 protocol; + + if (skb->protocol == htons(ETH_P_8021Q)) + protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; + else + protocol = skb->protocol; + + return protocol; +#endif +} + +static inline +u8 rtl8125_get_l4_protocol(struct sk_buff *skb) +{ + int no = skb_network_offset(skb); + struct ipv6hdr *i6h, _i6h; + struct iphdr *ih, _ih; + u8 ip_protocol = IPPROTO_RAW; + + switch (get_protocol(skb)) { + case __constant_htons(ETH_P_IP): + ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih); + if (ih) + ip_protocol = ih->protocol; + break; + case __constant_htons(ETH_P_IPV6): + i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h); + if (i6h) + ip_protocol = i6h->nexthdr; + break; + } + + return ip_protocol; +} + +static bool rtl8125_skb_pad_with_len(struct sk_buff *skb, unsigned int len) +{ + if (skb_padto(skb, len)) + return false; + skb_put(skb, len - skb->len); + return true; +} + +static bool rtl8125_skb_pad(struct sk_buff *skb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) + return rtl8125_skb_pad_with_len(skb, ETH_ZLEN); +#else + return !eth_skb_pad(skb); +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) +/* msdn_giant_send_check() + * According to the document of microsoft, the TCP Pseudo Header excludes the + * packet length for IPv6 TCP large packets. + */ +static int msdn_giant_send_check(struct sk_buff *skb) +{ + const struct ipv6hdr *ipv6h; + struct tcphdr *th; + int ret; + + ret = skb_cow_head(skb, 0); + if (ret) + return ret; + + ipv6h = ipv6_hdr(skb); + th = tcp_hdr(skb); + + th->check = 0; + th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); + + return ret; +} +#endif + +#define MIN_PATCH_LEN (47) +static u32 +rtl8125_get_patch_pad_len(struct sk_buff *skb) +{ + u32 pad_len = 0; + int trans_data_len; + u32 hdr_len; + u32 pkt_len = skb->len; + u8 ip_protocol; + bool has_trans = skb_transport_header_was_set(skb); + + if (!(has_trans && (pkt_len < 175))) //128 + MIN_PATCH_LEN + goto no_padding; + + ip_protocol = rtl8125_get_l4_protocol(skb); + if (!(ip_protocol == IPPROTO_TCP || ip_protocol == IPPROTO_UDP)) + goto no_padding; + + trans_data_len = pkt_len - + (skb->transport_header - + skb_headroom(skb)); + if (ip_protocol == IPPROTO_UDP) { + if (trans_data_len > 3 && trans_data_len < MIN_PATCH_LEN) { + u16 dest_port = 0; + + skb_copy_bits(skb, skb->transport_header - skb_headroom(skb) + 2, &dest_port, 2); + dest_port = ntohs(dest_port); + + if (dest_port == 0x13f || + dest_port == 0x140) { + pad_len = MIN_PATCH_LEN - trans_data_len; + goto out; + } + } + } + + hdr_len = 0; + if (ip_protocol == IPPROTO_TCP) + hdr_len = 20; + else if (ip_protocol == IPPROTO_UDP) + hdr_len = 8; + if (trans_data_len < hdr_len) + pad_len = hdr_len - trans_data_len; + +out: + if ((pkt_len + pad_len) < ETH_ZLEN) + pad_len = ETH_ZLEN - pkt_len; + + return pad_len; + +no_padding: + + return 0; +} + +static bool +rtl8125_tso_csum(struct sk_buff *skb, + struct net_device *dev, + u32 *opts) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned long large_send = 0; + u32 csum_cmd = 0; + u8 sw_calc_csum = false; + u8 check_patch_required = true; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) + u32 mss = skb_shinfo(skb)->tso_size; +#else + u32 mss = skb_shinfo(skb)->gso_size; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) + + /* TCP Segmentation Offload (or TCP Large Send) */ + if (mss) { + u32 transport_offset = (u32)skb_transport_offset(skb); + assert((transport_offset%2) == 0); + switch (get_protocol(skb)) { + case __constant_htons(ETH_P_IP): + if (transport_offset <= GTTCPHO_MAX) { + opts[0] |= GiantSendv4; + opts[0] |= transport_offset << GTTCPHO_SHIFT; + opts[1] |= min(mss, MSS_MAX) << 18; + large_send = 1; + } + break; + case __constant_htons(ETH_P_IPV6): +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) + if (msdn_giant_send_check(skb)) + return false; +#endif + if (transport_offset <= GTTCPHO_MAX) { + opts[0] |= GiantSendv6; + opts[0] |= transport_offset << GTTCPHO_SHIFT; + opts[1] |= min(mss, MSS_MAX) << 18; + large_send = 1; + } + break; + default: + if (unlikely(net_ratelimit())) + dprintk("tso proto=%x!\n", skb->protocol); + break; + } + + if (large_send == 0) + return false; + + return true; + } + } +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + const struct iphdr *ip = skb->nh.iph; + + if (dev->features & NETIF_F_IP_CSUM) { + if (ip->protocol == IPPROTO_TCP) + csum_cmd = tp->tx_ip_csum_cmd | tp->tx_tcp_csum_cmd; + else if (ip->protocol == IPPROTO_UDP) + csum_cmd = tp->tx_ip_csum_cmd | tp->tx_udp_csum_cmd; + else if (ip->protocol == IPPROTO_IP) + csum_cmd = tp->tx_ip_csum_cmd; + } +#else + u8 ip_protocol = IPPROTO_RAW; + + switch (get_protocol(skb)) { + case __constant_htons(ETH_P_IP): + if (dev->features & NETIF_F_IP_CSUM) { + ip_protocol = ip_hdr(skb)->protocol; + csum_cmd = tp->tx_ip_csum_cmd; + } + break; + case __constant_htons(ETH_P_IPV6): + if (dev->features & NETIF_F_IPV6_CSUM) { + u32 transport_offset = (u32)skb_transport_offset(skb); + if (transport_offset > 0 && transport_offset <= TCPHO_MAX) { + ip_protocol = ipv6_hdr(skb)->nexthdr; + csum_cmd = tp->tx_ipv6_csum_cmd; + csum_cmd |= transport_offset << TCPHO_SHIFT; + } + } + break; + default: + if (unlikely(net_ratelimit())) + dprintk("checksum_partial proto=%x!\n", skb->protocol); + break; + } + + if (ip_protocol == IPPROTO_TCP) + csum_cmd |= tp->tx_tcp_csum_cmd; + else if (ip_protocol == IPPROTO_UDP) + csum_cmd |= tp->tx_udp_csum_cmd; +#endif + if (csum_cmd == 0) { + sw_calc_csum = true; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + WARN_ON(1); /* we need a WARN() */ +#endif + } + + if (ip_protocol == IPPROTO_TCP) + check_patch_required = false; + } + + if (check_patch_required) { + u32 pad_len = rtl8125_get_patch_pad_len(skb); + + if (pad_len > 0) { + if (!rtl8125_skb_pad_with_len(skb, skb->len + pad_len)) + return false; + + if (csum_cmd != 0) + sw_calc_csum = true; + } + } + + if (skb->len < ETH_ZLEN) { + if (tp->UseSwPaddingShortPkt || + (tp->ShortPacketSwChecksum && csum_cmd != 0)) { + if (!rtl8125_skb_pad(skb)) + return false; + + if (csum_cmd != 0) + sw_calc_csum = true; + } + } + + if (sw_calc_csum) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) + skb_checksum_help(&skb, 0); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) + skb_checksum_help(skb, 0); +#else + skb_checksum_help(skb); +#endif + } else + opts[1] |= csum_cmd; + + return true; +} + +static bool rtl8125_tx_slots_avail(struct rtl8125_private *tp, + struct rtl8125_tx_ring *ring) +{ + unsigned int slots_avail = READ_ONCE(ring->dirty_tx) + NUM_TX_DESC + - READ_ONCE(ring->cur_tx); + + /* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ + return slots_avail > MAX_SKB_FRAGS; +} + +static netdev_tx_t +rtl8125_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned int entry; + struct TxDesc *txd; + dma_addr_t mapping; + u32 len; + u32 opts[2]; + netdev_tx_t ret = NETDEV_TX_OK; + int frags; + u8 EnableTxNoClose = tp->EnableTxNoClose; + const u16 queue_mapping = skb_get_queue_mapping(skb); + struct rtl8125_tx_ring *ring; + bool stop_queue; + + assert(queue_mapping < tp->num_tx_queues); + + ring = &tp->tx_ring[queue_mapping]; + + if (unlikely(!rtl8125_tx_slots_avail(tp, ring))) { + if (netif_msg_drv(tp)) { + printk(KERN_ERR + "%s: BUG! Tx Ring[%d] full when queue awake!\n", + dev->name, + queue_mapping); + } + goto err_stop; + } + + entry = ring->cur_tx % NUM_TX_DESC; + txd = ring->TxDescArray + entry; + + if (!EnableTxNoClose) { + if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) { + if (netif_msg_drv(tp)) { + printk(KERN_ERR + "%s: BUG! Tx Desc is own by hardware!\n", + dev->name); + } + goto err_stop; + } + } + + opts[0] = DescOwn; + opts[1] = rtl8125_tx_vlan_tag(tp, skb); + + if (unlikely(!rtl8125_tso_csum(skb, dev, opts))) + goto err_dma_0; + + frags = rtl8125_xmit_frags(tp, ring, skb, opts); + if (unlikely(frags < 0)) + goto err_dma_0; + if (frags) { + len = skb_headlen(skb); + opts[0] |= FirstFrag; + } else { + len = skb->len; + + //ring->tx_skb[entry].skb = skb; + + opts[0] |= FirstFrag | LastFrag; + } + + opts[0] = rtl8125_get_txd_opts1(opts[0], len, entry); + mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); + goto err_dma_1; + } + ring->tx_skb[entry].len = len; +#ifdef ENABLE_PTP_SUPPORT + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + if (tp->hwtstamp_config.tx_type == HWTSTAMP_TX_ON && + !tp->ptp_tx_skb) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + tp->ptp_tx_skb = skb_get(skb); + tp->ptp_tx_start = jiffies; + schedule_work(&tp->ptp_tx_work); + } else { + tp->tx_hwtstamp_skipped++; + } + } +#endif + ring->tx_skb[entry].skb = skb; + txd->addr = cpu_to_le64(mapping); + txd->opts2 = cpu_to_le32(opts[1]); + wmb(); + txd->opts1 = cpu_to_le32(opts[0]); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) + dev->trans_start = jiffies; +#else + skb_tx_timestamp(skb); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) + + /* rtl_tx needs to see descriptor changes before updated tp->cur_tx */ + smp_wmb(); + + WRITE_ONCE(ring->cur_tx, ring->cur_tx + frags + 1); + + stop_queue = !rtl8125_tx_slots_avail(tp, ring); + if (unlikely(stop_queue)) { + /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must + * not miss a ring update when it notices a stopped queue. + */ + smp_wmb(); + netif_stop_subqueue(dev, queue_mapping); + } + + if (EnableTxNoClose) + RTL_W16(tp, ring->sw_tail_ptr_reg, ring->cur_tx % MAX_TX_NO_CLOSE_DESC_PTR_V2); + else + RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); /* set polling bit */ + + if (unlikely(stop_queue)) { + /* Sync with rtl_tx: + * - publish queue status and cur_tx ring index (write barrier) + * - refresh dirty_tx ring index (read barrier). + * May the current thread have a pessimistic view of the ring + * status and forget to wake up queue, a racing rtl_tx thread + * can't. + */ + smp_mb(); + if (rtl8125_tx_slots_avail(tp, ring)) + netif_start_subqueue(dev, queue_mapping); + } +out: + return ret; +err_dma_1: + ring->tx_skb[entry].skb = NULL; + rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, frags); +err_dma_0: + RTLDEV->stats.tx_dropped++; + dev_kfree_skb_any(skb); + ret = NETDEV_TX_OK; + goto out; +err_stop: + netif_stop_subqueue(dev, queue_mapping); + ret = NETDEV_TX_BUSY; + RTLDEV->stats.tx_dropped++; + goto out; +} + +static inline u32 +rtl8125_fast_mod(const u32 input, const u32 ceil) +{ + return input >= ceil ? input % ceil : input; +} + +static int +rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget) +{ + struct rtl8125_private *tp = ring->priv; + struct net_device *dev = tp->dev; + unsigned int dirty_tx, tx_left; + unsigned int count = 0; + u8 EnableTxNoClose = tp->EnableTxNoClose; + + dirty_tx = ring->dirty_tx; + smp_rmb(); + tx_left = READ_ONCE(ring->cur_tx) - dirty_tx; + if (EnableTxNoClose) { + unsigned int tx_desc_closed; + u32 NextHwDesCloPtr = RTL_R16(tp, ring->hw_clo_ptr_reg); + ring->NextHwDesCloPtr = NextHwDesCloPtr; + smp_rmb(); + tx_desc_closed = rtl8125_fast_mod(NextHwDesCloPtr - ring->BeginHwDesCloPtr, MAX_TX_NO_CLOSE_DESC_PTR_V2); + if(tx_left > tx_desc_closed) tx_left = tx_desc_closed; + ring->BeginHwDesCloPtr = NextHwDesCloPtr; + } + + while (tx_left > 0) { + unsigned int entry = dirty_tx % NUM_TX_DESC; + struct ring_info *tx_skb = ring->tx_skb + entry; + + if (!EnableTxNoClose && + (le32_to_cpu(ring->TxDescArray[entry].opts1) & DescOwn)) + break; + + RTLDEV->stats.tx_bytes += tx_skb->len; + RTLDEV->stats.tx_packets++; + + rtl8125_unmap_tx_skb(tp->pci_dev, + tx_skb, + ring->TxDescArray + entry); + + if (tx_skb->skb != NULL) { + RTL_NAPI_CONSUME_SKB_ANY(tx_skb->skb, budget); + tx_skb->skb = NULL; + } + dirty_tx++; + tx_left--; + } + + if (ring->dirty_tx != dirty_tx) { + count = dirty_tx - ring->dirty_tx; + WRITE_ONCE(ring->dirty_tx, dirty_tx); + smp_wmb(); + if (__netif_subqueue_stopped(dev, ring->index) && + (rtl8125_tx_slots_avail(tp, ring))) { + netif_start_subqueue(dev, ring->index); + } + smp_rmb(); + if (!EnableTxNoClose && (ring->cur_tx != dirty_tx)) { + RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); + } + } + + return count; +} + +static int +rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, + const int message_id, + int budget) +{ + int count = 0; + + if (message_id == 16) + count += rtl8125_tx_interrupt(&tp->tx_ring[0], budget); +#ifdef ENABLE_MULTIPLE_TX_QUEUE + else if (message_id == 18) + count += rtl8125_tx_interrupt(&tp->tx_ring[1], budget); +#endif + + return count; +} + +static inline int +rtl8125_fragmented_frame(struct rtl8125_private *tp, u32 status) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + return (status & (FirstFrag_V3 | LastFrag_V3)) != (FirstFrag_V3 | LastFrag_V3); + else + return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); +} + +static inline int +rtl8125_rx_desc_type(u32 status) +{ + return ((status >> 26) & 0x0F); +} + +static inline void +rtl8125_rx_v3_csum(struct rtl8125_private *tp, + struct sk_buff *skb, + struct RxDescV3 *descv3) +{ + //u32 opts1 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1); + u32 opts2 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts2); + + /* rx csum offload for RTL8125 */ + if (((opts2 & RxV4F_v3) && !(opts2 & RxIPF_v3)) || (opts2 & RxV6F_v3)) { + if (((opts2 & RxTCPT_v3) && !(opts2 & RxTCPF_v3)) || + ((opts2 & RxUDPT_v3) && !(opts2 & RxUDPF_v3))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + } else + skb->ip_summed = CHECKSUM_NONE; +} + +static inline void +rtl8125_rx_csum(struct rtl8125_private *tp, + struct sk_buff *skb, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + rtl8125_rx_v3_csum(tp, skb, (struct RxDescV3 *)desc); + else { + u32 opts1 = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); + u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); + + /* rx csum offload for RTL8125 */ + if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) { + if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) || + ((opts1 & RxUDPT) && !(opts1 & RxUDPF))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + } else + skb->ip_summed = CHECKSUM_NONE; + } +} + +static inline int +rtl8125_try_rx_copy(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct sk_buff **sk_buff, + int pkt_size, + struct RxDesc *desc, + int rx_buf_sz) +{ + int ret = -1; + + if (pkt_size < rx_copybreak) { + struct sk_buff *skb; + + skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, pkt_size + RTK_RX_ALIGN); + if (skb) { + u8 *data; + + data = sk_buff[0]->data; + skb_reserve(skb, RTK_RX_ALIGN); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) + prefetch(data - RTK_RX_ALIGN); +#endif + eth_copy_and_sum(skb, data, pkt_size, 0); + *sk_buff = skb; + rtl8125_mark_to_asic(tp, desc, rx_buf_sz); + ret = 0; + } + } + return ret; +} + +static inline void +rtl8125_rx_skb(struct rtl8125_private *tp, + struct sk_buff *skb, + u32 ring_index) +{ +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + netif_receive_skb(skb); +#else + napi_gro_receive(&tp->r8125napi[ring_index].napi, skb); +#endif +#else + netif_rx(skb); +#endif +} + +static int +rtl8125_check_rx_desc_error(struct net_device *dev, + struct rtl8125_private *tp, + u32 status) +{ + int ret = 0; + + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { + if (unlikely(status & RxRES_V3)) { + if (status & (RxRWT_V3 | RxRUNT_V3)) + RTLDEV->stats.rx_length_errors++; + if (status & RxCRC_V3) + RTLDEV->stats.rx_crc_errors++; + + ret = -1; + } + } else { + if (unlikely(status & RxRES)) { + if (status & (RxRWT | RxRUNT)) + RTLDEV->stats.rx_length_errors++; + if (status & RxCRC) + RTLDEV->stats.rx_crc_errors++; + + ret = -1; + } + } + + return ret; +} + +static int +rtl8125_rx_interrupt(struct net_device *dev, + struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + napi_budget budget) +{ + unsigned int cur_rx, rx_left; + unsigned int delta, count = 0; + unsigned int entry; + struct RxDesc *desc; + u32 status; + u32 rx_quota; + u64 rx_buf_phy_addr; + u32 ring_index = ring->index; + + assert(dev != NULL); + assert(tp != NULL); + + if ((ring->RxDescArray == NULL)) + goto rx_out; + + rx_quota = RTL_RX_QUOTA(budget); + cur_rx = ring->cur_rx; + entry = cur_rx % NUM_RX_DESC; + desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); + rx_left = NUM_RX_DESC + ring->dirty_rx - cur_rx; + rx_left = rtl8125_rx_quota(rx_left, (u32)rx_quota); + + for (; rx_left > 0; rx_left--) { + rmb(); + status = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); + if (status & DescOwn) + break; + + if (unlikely(rtl8125_check_rx_desc_error(dev, tp, status) < 0)) { + if (netif_msg_rx_err(tp)) { + printk(KERN_INFO + "%s: Rx ERROR. status = %08x\n", + dev->name, status); + } + + RTLDEV->stats.rx_errors++; + + if (dev->features & NETIF_F_RXALL) + goto process_pkt; + + rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); + } else { + struct sk_buff *skb; + int pkt_size; + +process_pkt: + if (likely(!(dev->features & NETIF_F_RXFCS))) + pkt_size = (status & 0x00003fff) - 4; + else + pkt_size = status & 0x00003fff; + + /* + * The driver does not support incoming fragmented + * frames. They are seen as a symptom of over-mtu + * sized frames. + */ + if (unlikely(rtl8125_fragmented_frame(tp, status))) { + RTLDEV->stats.rx_dropped++; + RTLDEV->stats.rx_length_errors++; + rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); + continue; + } + + skb = ring->Rx_skbuff[entry]; + + if (!skb) + break; + +#ifdef ENABLE_PTP_SUPPORT + if (tp->EnablePtp) { + u8 desc_type; + + desc_type = rtl8125_rx_desc_type(status); + if (desc_type == RXDESC_TYPE_NEXT && rx_left > 0) { + u32 status_next; + struct RxDescV3 *desc_next; + unsigned int entry_next; + struct sk_buff *skb_next; + + entry_next = (cur_rx + 1) % NUM_RX_DESC; + desc_next = (struct RxDescV3 *)rtl8125_get_rxdesc(tp, ring->RxDescArray, entry_next); + rmb(); + status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); + if (unlikely(status_next & DescOwn)) { + udelay(1); + rmb(); + status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); + if (unlikely(status_next & DescOwn)) { + if (netif_msg_rx_err(tp)) { + printk(KERN_ERR + "%s: Rx Next Desc ERROR. status = %08x\n", + dev->name, status_next); + } + break; + } + } + + cur_rx++; + rx_left--; + desc_type = rtl8125_rx_desc_type(status_next); + if (desc_type == RXDESC_TYPE_PTP) + rtl8125_rx_ptp_pktstamp(tp, skb, desc_next); + else + WARN_ON(1); + + rx_buf_phy_addr = ring->RxDescPhyAddr[entry_next]; + dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, + tp->rx_buf_sz, DMA_FROM_DEVICE); + skb_next = ring->Rx_skbuff[entry_next]; + dev_kfree_skb_any(skb_next); + ring->Rx_skbuff[entry_next] = NULL; + } else + WARN_ON(desc_type != RXDESC_TYPE_NORMAL); + } +#endif + rx_buf_phy_addr = ring->RxDescPhyAddr[entry]; + dma_sync_single_for_cpu(tp_to_dev(tp), + rx_buf_phy_addr, tp->rx_buf_sz, + DMA_FROM_DEVICE); + + if (rtl8125_try_rx_copy(tp, ring, &skb, pkt_size, + desc, tp->rx_buf_sz)) { + ring->Rx_skbuff[entry] = NULL; + dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, + tp->rx_buf_sz, DMA_FROM_DEVICE); + } else { + dma_sync_single_for_device(tp_to_dev(tp), rx_buf_phy_addr, + tp->rx_buf_sz, DMA_FROM_DEVICE); + } + +#ifdef ENABLE_RSS_SUPPORT + rtl8125_rx_hash(tp, (struct RxDescV3 *)desc, skb); +#endif + + if (tp->cp_cmd & RxChkSum) + rtl8125_rx_csum(tp, skb, desc); + + skb->dev = dev; + skb_put(skb, pkt_size); + skb->protocol = eth_type_trans(skb, dev); + + if (skb->pkt_type == PACKET_MULTICAST) + RTLDEV->stats.multicast++; + + if (rtl8125_rx_vlan_skb(tp, desc, skb) < 0) + rtl8125_rx_skb(tp, skb, ring_index); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) + dev->last_rx = jiffies; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) + RTLDEV->stats.rx_bytes += pkt_size; + RTLDEV->stats.rx_packets++; + } + + cur_rx++; + entry = cur_rx % NUM_RX_DESC; + desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) + prefetch(desc); +#endif + } + + count = cur_rx - ring->cur_rx; + ring->cur_rx = cur_rx; + + delta = rtl8125_rx_fill(tp, ring, dev, ring->dirty_rx, ring->cur_rx, 1); + if (!delta && count && netif_msg_intr(tp)) + printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); + ring->dirty_rx += delta; + + /* + * FIXME: until there is periodic timer to try and refill the ring, + * a temporary shortage may definitely kill the Rx process. + * - disable the asic to try and avoid an overflow and kick it again + * after refill ? + * - how do others driver handle this condition (Uh oh...). + */ + if ((ring->dirty_rx + NUM_RX_DESC == ring->cur_rx) && netif_msg_intr(tp)) + printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + +rx_out: + return count; +} + +static bool +rtl8125_linkchg_interrupt(struct rtl8125_private *tp, u32 status) +{ + if (tp->HwCurrIsrVer == 2) + return status & ISRIMR_V2_LINKCHG; + + return status & LinkChg; +} + +/* + *The interrupt handler does all of the Rx thread work and cleans up after + *the Tx thread. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +#else +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance) +#endif +{ + struct r8125_napi *r8125napi = dev_instance; + struct rtl8125_private *tp = r8125napi->priv; + struct net_device *dev = tp->dev; + u32 status; + int handled = 0; + + do { + status = RTL_R32(tp, tp->isr_reg[0]); + + if (!(tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) { + /* hotplug/major error/no more work/shared irq */ + if (!status) + break; + + if ((status == 0xFFFFFFFF)) + break; + + if (!(status & (tp->intr_mask | tp->timer_intr_mask))) + break; + } + + handled = 1; + +#if defined(RTL_USE_NEW_INTR_API) + if (!tp->irq_tbl[0].requested) + break; +#endif + rtl8125_disable_hw_interrupt(tp); + + RTL_W32(tp, tp->isr_reg[0], status&~RxFIFOOver); + + if (rtl8125_linkchg_interrupt(tp, status)) + rtl8125_schedule_linkchg_work(tp); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + if (HW_DASH_SUPPORT_TYPE_3(tp)) { + u8 DashIntType2Status; + + if (status & ISRIMR_DASH_INTR_CMAC_RESET) + tp->CmacResetIntr = TRUE; + + DashIntType2Status = RTL_CMAC_R8(tp, CMAC_IBISR0); + if (DashIntType2Status & ISRIMR_DASH_TYPE2_ROK) { + tp->RcvFwDashOkEvt = TRUE; + } + if (DashIntType2Status & ISRIMR_DASH_TYPE2_TOK) { + tp->SendFwHostOkEvt = TRUE; + } + if (DashIntType2Status & ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE) { + tp->DashFwDisableRx = TRUE; + } + + RTL_CMAC_W8(tp, CMAC_IBISR0, DashIntType2Status); + } + } +#endif + +#ifdef CONFIG_R8125_NAPI + if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { + if (status & tp->intr_mask) + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + + if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &tp->r8125napi[0].napi))) + __RTL_NETIF_RX_SCHEDULE(dev, &tp->r8125napi[0].napi); + else if (netif_msg_intr(tp)) + printk(KERN_INFO "%s: interrupt %04x in poll\n", + dev->name, status); + } else { + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + rtl8125_switch_to_hw_interrupt(tp); + } +#else + if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { + u32 budget = ~(u32)0; + int i; + + if (status & tp->intr_mask) + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], &budget); +#else + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], budget); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + + for (i = 0; i < tp->num_tx_rings; i++) + rtl8125_tx_interrupt(&tp->tx_ring[i], ~(u32)0); +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + struct net_device *dev = tp->dev; + + HandleDashInterrupt(dev); + } +#endif + + rtl8125_switch_to_timer_interrupt(tp); + } else { + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + rtl8125_switch_to_hw_interrupt(tp); + } +#endif + } while (false); + + return IRQ_RETVAL(handled); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs) +#else +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance) +#endif +{ + struct r8125_napi *r8125napi = dev_instance; + struct rtl8125_private *tp = r8125napi->priv; + struct net_device *dev = tp->dev; + int message_id = r8125napi->index; +#ifndef CONFIG_R8125_NAPI + u32 budget = ~(u32)0; +#endif + + do { +#if defined(RTL_USE_NEW_INTR_API) + if (!tp->irq_tbl[message_id].requested) + break; +#endif + rtl8125_disable_hw_interrupt_v2(tp, message_id); + + rtl8125_clear_hw_isr_v2(tp, message_id); + + //link change + if (message_id == 21) { + rtl8125_schedule_linkchg_work(tp); + break; + } + +#ifdef CONFIG_R8125_NAPI + if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &r8125napi->napi))) + __RTL_NETIF_RX_SCHEDULE(dev, &r8125napi->napi); + else if (netif_msg_intr(tp)) + printk(KERN_INFO "%s: interrupt message id %d in poll_msix\n", + dev->name, message_id); +#else + if (message_id < tp->num_rx_rings) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], &budget); +#else + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + } + + rtl8125_tx_interrupt_with_vector(tp, message_id, ~(u32)0); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); +#endif + + } while (false); + + return IRQ_HANDLED; +} + +static void rtl8125_down(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + //rtl8125_delete_esd_timer(dev, &tp->esd_timer); + + //rtl8125_delete_link_timer(dev, &tp->link_timer); + + netif_tx_disable(dev); + + _rtl8125_wait_for_quiescence(dev); + + netif_carrier_off(dev); + + rtl8125_hw_reset(dev); + + rtl8125_tx_clear(tp); + + rtl8125_rx_clear(tp); +} + +static int rtl8125_resource_freed(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_tx_rings; i++) + if (tp->tx_ring[i].TxDescArray) return 0; + + for (i = 0; i < tp->num_rx_rings; i++) + if (tp->rx_ring[i].RxDescArray) return 0; + + return 1; +} + +int rtl8125_close(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (!rtl8125_resource_freed(tp)) { + set_bit(R8125_FLAG_DOWN, tp->task_flags); + + rtl8125_down(dev); + + pci_clear_master(tp->pci_dev); + +#ifdef ENABLE_PTP_SUPPORT + rtl8125_ptp_stop(tp); +#endif + rtl8125_hw_d3_para(dev); + + rtl8125_powerdown_pll(dev, 0); + + rtl8125_free_irq(tp); + + rtl8125_free_alloc_resources(tp); + } else { + rtl8125_hw_d3_para(dev); + + rtl8125_powerdown_pll(dev, 0); + } + + return 0; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) +static void rtl8125_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8125_private *tp = netdev_priv(dev); + + rtnl_lock(); + + if (tp->DASH) + rtl8125_driver_stop(tp); + + rtl8125_set_bios_setting(dev); + if (s5_keep_curr_mac == 0 && tp->random_mac == 0) + rtl8125_rar_set(tp, tp->org_mac_addr); + + if (s5wol == 0) + tp->wol_enabled = WOL_DISABLED; + + rtl8125_close(dev); + rtl8125_disable_msi(pdev, tp); + + rtnl_unlock(); + + if (system_state == SYSTEM_POWER_OFF) { + pci_clear_master(tp->pci_dev); + pci_wake_from_d3(pdev, tp->wol_enabled); + pci_set_power_state(pdev, PCI_D3hot); + } +} +#endif + +/** + * rtl8125_get_stats - Get rtl8125 read/write statistics + * @dev: The Ethernet Device to get statistics for + * + * Get TX/RX statistics for rtl8125 + */ +static struct +net_device_stats *rtl8125_get_stats(struct net_device *dev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + struct rtl8125_private *tp = netdev_priv(dev); +#endif + return &RTLDEV->stats; +} + +#ifdef CONFIG_PM + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) +static int +rtl8125_suspend(struct pci_dev *pdev, u32 state) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +static int +rtl8125_suspend(struct device *device) +#else +static int +rtl8125_suspend(struct pci_dev *pdev, pm_message_t state) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + struct pci_dev *pdev = to_pci_dev(device); + struct net_device *dev = pci_get_drvdata(pdev); +#else + struct net_device *dev = pci_get_drvdata(pdev); +#endif + struct rtl8125_private *tp = netdev_priv(dev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + u32 pci_pm_state = pci_choose_state(pdev, state); +#endif + if (!netif_running(dev)) + goto out; + + //rtl8125_cancel_all_schedule_work(tp); + + //rtl8125_delete_esd_timer(dev, &tp->esd_timer); + + //rtl8125_delete_link_timer(dev, &tp->link_timer); + + rtnl_lock(); + + set_bit(R8125_FLAG_DOWN, tp->task_flags); + + netif_tx_disable(dev); + + netif_carrier_off(dev); + + netif_device_detach(dev); + +#ifdef ENABLE_PTP_SUPPORT + rtl8125_ptp_suspend(tp); +#endif + rtl8125_hw_reset(dev); + + pci_clear_master(pdev); + + rtl8125_hw_d3_para(dev); + + rtl8125_powerdown_pll(dev, 1); + + if (tp->DASH) + rtl8125_driver_stop(tp); + + rtnl_unlock(); +out: + + pci_disable_device(pdev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + pci_save_state(pdev, &pci_pm_state); +#else + pci_save_state(pdev); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); +#endif + + pci_prepare_to_sleep(pdev); + + return 0; +} + +static int +rtl8125_hw_d3_not_power_off(struct net_device *dev) +{ + return rtl8125_check_hw_phy_mcu_code_ver(dev); +} + +static int rtl8125_wait_phy_nway_complete_sleep(struct rtl8125_private *tp) +{ + int i, val; + + for (i = 0; i < 30; i++) { + val = rtl8125_mdio_read(tp, MII_BMSR) & BMSR_ANEGCOMPLETE; + if (val) + return 0; + + msleep(100); + } + + return -1; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +static int +rtl8125_resume(struct pci_dev *pdev) +#else +static int +rtl8125_resume(struct device *device) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + struct pci_dev *pdev = to_pci_dev(device); + struct net_device *dev = pci_get_drvdata(pdev); +#else + struct net_device *dev = pci_get_drvdata(pdev); +#endif + struct rtl8125_private *tp = netdev_priv(dev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + u32 pci_pm_state = PCI_D0; +#endif + u32 err; + + rtnl_lock(); + + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n"); + goto out_unlock; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + pci_restore_state(pdev, &pci_pm_state); +#else + pci_restore_state(pdev); +#endif + pci_enable_wake(pdev, PCI_D0, 0); + + /* restore last modified mac address */ + rtl8125_rar_set(tp, dev->dev_addr); + + tp->resume_not_chg_speed = 0; + if (tp->check_keep_link_speed && + //tp->link_ok(dev) && + rtl8125_hw_d3_not_power_off(dev) && + rtl8125_wait_phy_nway_complete_sleep(tp) == 0) + tp->resume_not_chg_speed = 1; + + if (!netif_running(dev)) + goto out_unlock; + + pci_set_master(pdev); + + rtl8125_exit_oob(dev); + + rtl8125_up(dev); + + clear_bit(R8125_FLAG_DOWN, tp->task_flags); + + rtl8125_schedule_reset_work(tp); + + rtl8125_schedule_esd_work(tp); + + //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); + //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); +out_unlock: + netif_device_attach(dev); + + rtnl_unlock(); + + return err; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + +static struct dev_pm_ops rtl8125_pm_ops = { + .suspend = rtl8125_suspend, + .resume = rtl8125_resume, + .freeze = rtl8125_suspend, + .thaw = rtl8125_resume, + .poweroff = rtl8125_suspend, + .restore = rtl8125_resume, +}; + +#define RTL8125_PM_OPS (&rtl8125_pm_ops) + +#endif + +#else /* !CONFIG_PM */ + +#define RTL8125_PM_OPS NULL + +#endif /* CONFIG_PM */ + +static struct pci_driver rtl8125_pci_driver = { + .name = MODULENAME, + .id_table = rtl8125_pci_tbl, + .probe = rtl8125_init_one, + .remove = __devexit_p(rtl8125_remove_one), +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) + .shutdown = rtl8125_shutdown, +#endif +#ifdef CONFIG_PM +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + .suspend = rtl8125_suspend, + .resume = rtl8125_resume, +#else + .driver.pm = RTL8125_PM_OPS, +#endif +#endif +}; + +static int __init +rtl8125_init_module(void) +{ + int ret = 0; +#ifdef ENABLE_R8125_PROCFS + rtl8125_proc_module_init(); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + + ret = pci_register_driver(&rtl8125_pci_driver); +#else + ret = pci_module_init(&rtl8125_pci_driver); +#endif + + return ret; +} + +static void __exit +rtl8125_cleanup_module(void) +{ + pci_unregister_driver(&rtl8125_pci_driver); + +#ifdef ENABLE_R8125_PROCFS + if (rtl8125_proc) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + remove_proc_subtree(MODULENAME, init_net.proc_net); +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + remove_proc_entry(MODULENAME, init_net.proc_net); +#else + remove_proc_entry(MODULENAME, proc_net); +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + rtl8125_proc = NULL; + } +#endif +} + +module_init(rtl8125_init_module); +module_exit(rtl8125_cleanup_module); diff --git a/r8125/src/r8125_ptp.c b/r8125/src/r8125_ptp.c new file mode 100755 index 000000000..e1102b76d --- /dev/null +++ b/r8125/src/r8125_ptp.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "r8125.h" +#include "r8125_ptp.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) +{ + return *(const struct timespec *)&ts64; +} + +static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) +{ + return *(const struct timespec64 *)&ts; +} +#endif + +static int _rtl8125_phc_gettime(struct rtl8125_private *tp, struct timespec64 *ts64) +{ + //get local time + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_LATCHED_LOCAL_TIME | PTP_EXEC_CMD)); + + /* nanoseconds */ + //0x6808[29:0] + ts64->tv_nsec = (RTL_R32(tp, PTP_SOFT_CONFIG_Time_NS_8125) & 0x3fffffff) + + tp->ptp_adjust; + + /* seconds */ + //0x680C[47:0] + ts64->tv_sec = RTL_R16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4); + ts64->tv_sec <<= 32; + ts64->tv_sec |= RTL_R32(tp, PTP_SOFT_CONFIG_Time_S_8125); + + return 0; +} + +static int _rtl8125_phc_settime(struct rtl8125_private *tp, const struct timespec64 *ts64) +{ + /* nanoseconds */ + //0x6808[29:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, (ts64->tv_nsec & 0x3fffffff)); + + /* seconds */ + //0x680C[47:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, ts64->tv_sec); + RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (ts64->tv_sec >> 32)); + + //set local time + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); + + return 0; +} + +#if 0 +static int _rtl8125_phc_adjtime(struct rtl8125_private *tp, s64 delta) +{ + struct timespec64 now, then = ns_to_timespec64(delta); + u32 nsec; + u64 sec; + + _rtl8125_phc_gettime(tp, &now); + now = timespec64_add(now, then); + + nsec = now.tv_nsec & 0x3fffffff; + sec = now.tv_sec & 0x0000ffffffffffff; + + /* nanoseconds */ + //0x6808[29:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, nsec); + + /* seconds */ + //0x680C[47:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, sec); + RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (sec >> 32)); + + //adjust local time + //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); + + return 0; +} +#endif + +static int rtl8125_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + //int ret = 0; + + //netif_info(tp, drv, tp->dev, "phc adjust time\n"); + + spin_lock_irqsave(&tp->lock, flags); + //ret = _rtl8125_phc_adjtime(tp, delta); + tp->ptp_adjust += delta; + spin_unlock_irqrestore(&tp->lock, flags); + + return 0; +} + +/* +1ppm means every 125MHz plus 125Hz. It also means every 8ns minus 8ns*10^(-6) + +1ns=2^30 sub_ns + +8ns*10^(-6) = 8 * 2^30 sub_ns * 10^(-6) = 2^33 sub_ns * 10^(-6) = 8590 = 0x218E sub_ns + +1ppb means every 125MHz plus 0.125Hz. It also means every 8ns minus 8ns*10^(-9) + +1ns=2^30 sub_ns + +8ns*10^(-9) = 8 * 2^30 sub_ns * 10^(-9) = 2^33 sub_ns * 10^(-9) = 8.59 sub_ns = 9 sub_ns +*/ +static int _rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + bool negative = false; + u32 sub_ns; + + if (ppb < 0) { + negative = true; + ppb = -ppb; + } + + sub_ns = ppb * 9; + if (negative) { + sub_ns = -sub_ns; + sub_ns &= 0x3fffffff; + sub_ns |= PTP_ADJUST_TIME_NS_NEGATIVE; + } else + sub_ns &= 0x3fffffff; + + /* nanoseconds */ + //0x6808[29:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, sub_ns); + + //adjust local time + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); + //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); + + return 0; +} + +static int rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) +{ + //struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + + //netif_info(tp, drv, tp->dev, "phc adjust freq\n"); + + if (delta > ptp->max_adj || delta < -ptp->max_adj) + return -EINVAL; + + _rtl8125_phc_adjfreq(ptp, delta); + + return 0; +} + +static int rtl8125_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + int ret; + + //netif_info(tp, drv, tp->dev, "phc get ts\n"); + + spin_lock_irqsave(&tp->lock, flags); + ret = _rtl8125_phc_gettime(tp, ts64); + spin_unlock_irqrestore(&tp->lock, flags); + + return ret; +} + +static int rtl8125_phc_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts64) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + int ret; + + //netif_info(tp, drv, tp->dev, "phc set ts\n"); + + spin_lock_irqsave(&tp->lock, flags); + ret = _rtl8125_phc_settime(tp, ts64); + tp->ptp_adjust = 0; + spin_unlock_irqrestore(&tp->lock, flags); + + return ret; +} + +static int rtl8125_phc_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + u16 ptp_ctrl; + + //netif_info(tp, drv, tp->dev, "phc enable type %x on %d\n", rq->type, on); + + switch (rq->type) { + case PTP_CLK_REQ_PPS: + spin_lock_irqsave(&tp->lock, flags); + ptp_ctrl = RTL_R16(tp, PTP_CTRL_8125); + ptp_ctrl &= ~BIT_15; + if (on) + ptp_ctrl |= BIT_14; + else + ptp_ctrl &= ~BIT_14; + RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); + spin_unlock_irqrestore(&tp->lock, flags); + return 0; + default: + return -EOPNOTSUPP; + } +} + +int rtl8125_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + + /* we always support timestamping disabled */ + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); + + if (tp->HwSuppPtpVer == 0) + return ethtool_op_get_ts_info(netdev, info); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + if (tp->ptp_clock) + info->phc_index = ptp_clock_index(tp->ptp_clock); + else + info->phc_index = -1; + + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); + + return 0; +} + +static const struct ptp_clock_info rtl_ptp_clock_info = { + .owner = THIS_MODULE, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .n_pins = 0, + .pps = 1, + .adjfreq = rtl8125_phc_adjfreq, + .adjtime = rtl8125_phc_adjtime, + .gettime64 = rtl8125_phc_gettime, + .settime64 = rtl8125_phc_settime, + .enable = rtl8125_phc_enable, +}; + +static int rtl8125_get_tx_ptp_pkt_tstamp(struct rtl8125_private *tp, struct timespec64 *ts64) +{ + return _rtl8125_phc_gettime(tp, ts64); +} + +static void rtl8125_ptp_tx_hwtstamp(struct rtl8125_private *tp) +{ + struct sk_buff *skb = tp->ptp_tx_skb; + struct skb_shared_hwtstamps shhwtstamps = {0}; + struct timespec64 ts64; + + RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); + + rtl8125_get_tx_ptp_pkt_tstamp(tp, &ts64); + + /* Upper 32 bits contain s, lower 32 bits contain ns. */ + shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec, + ts64.tv_nsec); + + /* Clear the lock early before calling skb_tstamp_tx so that + * applications are not woken up before the lock bit is clear. We use + * a copy of the skb pointer to ensure other threads can't change it + * while we're notifying the stack. + */ + tp->ptp_tx_skb = NULL; + + /* Notify the stack and free the skb after we've unlocked */ + skb_tstamp_tx(skb, &shhwtstamps); + dev_kfree_skb_any(skb); +} + +#define RTL8125_PTP_TX_TIMEOUT (HZ * 15) +static void rtl8125_ptp_tx_work(struct work_struct *work) +{ + struct rtl8125_private *tp = container_of(work, struct rtl8125_private, + ptp_tx_work); + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + if (!tp->ptp_tx_skb) + goto Exit; + + if (time_is_before_jiffies(tp->ptp_tx_start + + RTL8125_PTP_TX_TIMEOUT)) { + dev_kfree_skb_any(tp->ptp_tx_skb); + tp->ptp_tx_skb = NULL; + tp->tx_hwtstamp_timeouts++; + /* Clear the tx valid bit in TSYNCTXCTL register to enable + * interrupt + */ + RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); + goto Exit; + } + + if (RTL_R8(tp, PTP_ISR_8125) & (PTP_ISR_TOK)) + rtl8125_ptp_tx_hwtstamp(tp); + else + /* reschedule to check later */ + schedule_work(&tp->ptp_tx_work); + +Exit: + spin_unlock_irqrestore(&tp->lock, flags); +} + +static int rtl8125_hwtstamp_enable(struct rtl8125_private *tp, bool enable) +{ + RTL_W16(tp, PTP_CTRL_8125, 0); + if (enable) { + u16 ptp_ctrl; + struct timespec64 ts64; + + //clear ptp isr + RTL_W8(tp, PTP_ISR_8125, 0xff); + //ptp source 0:gphy 1:mac + rtl8125_mac_ocp_write(tp, 0xDC00, rtl8125_mac_ocp_read(tp, 0xDC00) | BIT_6); + //enable ptp + ptp_ctrl = (BIT_0 | BIT_3 | BIT_4 | BIT_6 | BIT_10 | BIT_12 | BIT_13); + if (tp->ptp_master_mode) { + ptp_ctrl &= ~BIT_13; + ptp_ctrl |= BIT_1; + } + RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); + + //set system time + /* + if (ktime_to_timespec64_cond(ktime_get_real(), &ts64)) + _rtl8125_phc_settime(tp, timespec64_to_timespec(ts64)); + */ + ktime_get_real_ts64(&ts64); + ts64.tv_nsec += tp->ptp_adjust; + _rtl8125_phc_settime(tp, &ts64); + tp->ptp_adjust = 0; + } + + return 0; +} + +static long rtl8125_ptp_create_clock(struct rtl8125_private *tp) +{ + struct net_device *netdev = tp->dev; + long err; + + if (!IS_ERR_OR_NULL(tp->ptp_clock)) + return 0; + + if (tp->HwSuppPtpVer == 0) { + tp->ptp_clock = NULL; + return -EOPNOTSUPP; + } + + tp->ptp_clock_info = rtl_ptp_clock_info; + snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name), + "%pm", tp->dev->dev_addr); + tp->ptp_clock_info.max_adj = 119304647; + tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev); + if (IS_ERR(tp->ptp_clock)) { + err = PTR_ERR(tp->ptp_clock); + tp->ptp_clock = NULL; + netif_err(tp, drv, tp->dev, "ptp_clock_register failed\n"); + return err; + } else + netif_info(tp, drv, tp->dev, "registered PHC device on %s\n", netdev->name); + + return 0; +} + +void rtl8125_ptp_reset(struct rtl8125_private *tp) +{ + if (!tp->ptp_clock) + return; + + netif_info(tp, drv, tp->dev, "reset PHC clock\n"); + + rtl8125_hwtstamp_enable(tp, false); +} + +void rtl8125_ptp_init(struct rtl8125_private *tp) +{ + /* obtain a PTP device, or re-use an existing device */ + if (rtl8125_ptp_create_clock(tp)) + return; + + /* we have a clock so we can initialize work now */ + INIT_WORK(&tp->ptp_tx_work, rtl8125_ptp_tx_work); + + tp->ptp_adjust = 0; + + /* reset the PTP related hardware bits */ + rtl8125_ptp_reset(tp); + + return; +} + +void rtl8125_ptp_suspend(struct rtl8125_private *tp) +{ + if (!tp->ptp_clock) + return; + + netif_info(tp, drv, tp->dev, "suspend PHC clock\n"); + + rtl8125_hwtstamp_enable(tp, false); + + /* ensure that we cancel any pending PTP Tx work item in progress */ + cancel_work_sync(&tp->ptp_tx_work); +} + +void rtl8125_ptp_stop(struct rtl8125_private *tp) +{ + struct net_device *netdev = tp->dev; + + netif_info(tp, drv, tp->dev, "stop PHC clock\n"); + + /* first, suspend PTP activity */ + rtl8125_ptp_suspend(tp); + + /* disable the PTP clock device */ + if (tp->ptp_clock) { + ptp_clock_unregister(tp->ptp_clock); + tp->ptp_clock = NULL; + netif_info(tp, drv, tp->dev, "removed PHC on %s\n", + netdev->name); + } +} + +static int rtl8125_set_tstamp(struct net_device *netdev, struct ifreq *ifr) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + struct hwtstamp_config config; + bool hwtstamp = 0; + + //netif_info(tp, drv, tp->dev, "ptp set ts\n"); + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + + if (config.flags) + return -EINVAL; + + switch (config.tx_type) { + case HWTSTAMP_TX_ON: + hwtstamp = 1; + case HWTSTAMP_TX_OFF: + break; + case HWTSTAMP_TX_ONESTEP_SYNC: + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + hwtstamp = 1; + case HWTSTAMP_FILTER_NONE: + break; + default: + return -ERANGE; + } + + if (tp->hwtstamp_config.tx_type != config.tx_type || + tp->hwtstamp_config.rx_filter != config.rx_filter) { + tp->hwtstamp_config = config; + rtl8125_hwtstamp_enable(tp, hwtstamp); + } + + return copy_to_user(ifr->ifr_data, &config, + sizeof(config)) ? -EFAULT : 0; +} + +static int rtl8125_get_tstamp(struct net_device *netdev, struct ifreq *ifr) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + + //netif_info(tp, drv, tp->dev, "ptp get ts\n"); + + return copy_to_user(ifr->ifr_data, &tp->hwtstamp_config, + sizeof(tp->hwtstamp_config)) ? -EFAULT : 0; +} + +int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + int ret; + unsigned long flags; + + //netif_info(tp, drv, tp->dev, "ptp ioctl\n"); + + ret = 0; + switch (cmd) { +#ifdef ENABLE_PTP_SUPPORT + case SIOCSHWTSTAMP: + spin_lock_irqsave(&tp->lock, flags); + ret = rtl8125_set_tstamp(netdev, ifr); + spin_unlock_irqrestore(&tp->lock, flags); + break; + case SIOCGHWTSTAMP: + spin_lock_irqsave(&tp->lock, flags); + ret = rtl8125_get_tstamp(netdev, ifr); + spin_unlock_irqrestore(&tp->lock, flags); + break; +#endif + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, + struct RxDescV3 *descv3) +{ + time64_t tv_sec; + long tv_nsec; + + tv_sec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampHigh) + + ((u64)le32_to_cpu(descv3->RxDescPTPDDWord4.TimeStampHHigh) << 32); + tv_nsec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampLow) + tp->ptp_adjust; + + skb_hwtstamps(skb)->hwtstamp = ktime_set(tv_sec, tv_nsec); +} diff --git a/r8125/src/r8125_ptp.h b/r8125/src/r8125_ptp.h new file mode 100755 index 000000000..a324ff382 --- /dev/null +++ b/r8125/src/r8125_ptp.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_rtl8125_PTP_H +#define _LINUX_rtl8125_PTP_H + +#include +#include +#include +#include +#include + +struct rtl8125_ptp_info { + s64 time_sec; + u32 time_ns; + u16 ts_info; +}; + +#ifndef _STRUCT_TIMESPEC +#define _STRUCT_TIMESPEC +struct timespec { + __kernel_old_time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif + +enum PTP_CMD_TYPE { + PTP_CMD_SET_LOCAL_TIME = 0, + PTP_CMD_DRIFT_LOCAL_TIME, + PTP_CMD_LATCHED_LOCAL_TIME, +}; + + +struct rtl8125_private; +struct RxDescV3; + +int rtl8125_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info); + +void rtl8125_ptp_reset(struct rtl8125_private *tp); +void rtl8125_ptp_init(struct rtl8125_private *tp); +void rtl8125_ptp_suspend(struct rtl8125_private *tp); +void rtl8125_ptp_stop(struct rtl8125_private *tp); + +int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); + +void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, + struct RxDescV3 *descv3); + +#endif /* _LINUX_rtl8125_PTP_H */ diff --git a/r8125/src/r8125_realwow.h b/r8125/src/r8125_realwow.h new file mode 100755 index 000000000..352e3270f --- /dev/null +++ b/r8125/src/r8125_realwow.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_R8125_REALWOW_H +#define _LINUX_R8125_REALWOW_H + +#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3 + +#define MAX_RealWoW_KCP_SIZE (100) +#define MAX_RealWoW_Payload (64) + +#define KA_TX_PACKET_SIZE (100) +#define KA_WAKEUP_PATTERN_SIZE (120) + +//HwSuppKeepAliveOffloadVer +#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0) + +enum rtl_realwow_cmd { + + RTL_REALWOW_SET_KCP_DISABLE=0, + RTL_REALWOW_SET_KCP_INFO, + RTL_REALWOW_SET_KCP_CONTENT, + + RTL_REALWOW_SET_KCP_ACKPKTINFO, + RTL_REALWOW_SET_KCP_WPINFO, + RTL_REALWOW_SET_KCPDHCP_TIMEOUT, + + RTLT_REALWOW_COMMAND_INVALID +}; + +struct rtl_realwow_ioctl_struct { + __u32 cmd; + __u32 offset; + __u32 len; + union { + __u32 data; + void *data_buffer; + }; +}; + +typedef struct _MP_KCPInfo { + u8 DIPv4[4]; + u8 MacID[6]; + u16 UdpPort[2]; + u8 PKTLEN[2]; + + u16 ackLostCnt; + u8 KCP_WakePattern[MAX_RealWoW_Payload]; + u8 KCP_AckPacket[MAX_RealWoW_Payload]; + u32 KCP_interval; + u8 KCP_WakePattern_Len; + u8 KCP_AckPacket_Len; + u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; +} MP_KCP_INFO, *PMP_KCP_INFO; + +typedef struct _KCPInfo { + u32 nId; // = id + u8 DIPv4[4]; + u8 MacID[6]; + u16 UdpPort; + u16 PKTLEN; +} KCPInfo, *PKCPInfo; + +typedef struct _KCPContent { + u32 id; // = id + u32 mSec; // = msec + u32 size; // =size + u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here +} KCPContent, *PKCPContent; + +typedef struct _RealWoWAckPktInfo { + u16 ackLostCnt; + u16 patterntSize; + u8 pattern[MAX_RealWoW_Payload]; +} RealWoWAckPktInfo,*PRealWoWAckPktInfo; + +typedef struct _RealWoWWPInfo { + u16 patterntSize; + u8 pattern[MAX_RealWoW_Payload]; +} RealWoWWPInfo,*PRealWoWWPInfo; + +int rtl8125_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); +void rtl8125_realwow_hw_init(struct net_device *dev); +void rtl8125_get_realwow_hw_version(struct net_device *dev); +void rtl8125_set_realwow_d3_para(struct net_device *dev); + +#endif /* _LINUX_R8125_REALWOW_H */ diff --git a/r8125/src/r8125_rss.c b/r8125/src/r8125_rss.c new file mode 100755 index 000000000..78e53f514 --- /dev/null +++ b/r8125/src/r8125_rss.c @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8168 is the Linux device driver released for Realtek Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include "r8125.h" + +enum rtl8125_rss_register_content { + /* RSS */ + RSS_CTRL_TCP_IPV4_SUPP = (1 << 0), + RSS_CTRL_IPV4_SUPP = (1 << 1), + RSS_CTRL_TCP_IPV6_SUPP = (1 << 2), + RSS_CTRL_IPV6_SUPP = (1 << 3), + RSS_HALF_SUPP = (1 << 7), + RSS_CTRL_UDP_IPV4_SUPP = (1 << 11), + RSS_CTRL_UDP_IPV6_SUPP = (1 << 12), + RSS_QUAD_CPU_EN = (1 << 16), + RSS_HQ_Q_SUP_R = (1 << 31), +}; + +static int rtl8125_get_rss_hash_opts(struct rtl8125_private *tp, + struct ethtool_rxnfc *cmd) +{ + cmd->data = 0; + + /* Report default options for RSS */ + switch (cmd->flow_type) { + case TCP_V4_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case UDP_V4_FLOW: + if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case IPV4_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + case TCP_V6_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case UDP_V6_FLOW: + if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case IPV6_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + default: + return -EINVAL; + } + + return 0; +} + +int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + netif_info(tp, drv, tp->dev, "rss get rxnfc\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return ret; + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = rtl8125_tot_rx_rings(tp); + ret = 0; + break; + case ETHTOOL_GRXFH: + ret = rtl8125_get_rss_hash_opts(tp, cmd); + break; + default: + break; + } + + return ret; +} + +u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp) +{ + return tp->HwSuppIndirTblEntries; +} + +#define RSS_MASK_BITS_OFFSET (8) +#define RSS_CPU_NUM_OFFSET (16) +#define RTL8125_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \ + RTL_8125_RSS_FLAG_HASH_UDP_IPV6) +static int _rtl8125_set_rss_hash_opt(struct rtl8125_private *tp) +{ + u32 rss_flags = tp->rss_flags; + u32 hash_mask_len; + u32 rss_ctrl; + + rss_ctrl = ilog2(rtl8125_tot_rx_rings(tp)); + rss_ctrl &= (BIT_0 | BIT_1 | BIT_2); + rss_ctrl <<= RSS_CPU_NUM_OFFSET; + + /* Perform hash on these packet types */ + rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP + | RSS_CTRL_IPV4_SUPP + | RSS_CTRL_IPV6_SUPP + | RSS_CTRL_TCP_IPV6_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) + rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) + rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; + + hash_mask_len = ilog2(rtl8125_rss_indir_tbl_entries(tp)); + hash_mask_len &= (BIT_0 | BIT_1 | BIT_2); + rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET; + + RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); + + return 0; +} + +static int rtl8125_set_rss_hash_opt(struct rtl8125_private *tp, + struct ethtool_rxnfc *nfc) +{ + u32 rss_flags = tp->rss_flags; + + netif_info(tp, drv, tp->dev, "rss set hash\n"); + + /* + * RSS does not support anything other than hashing + * to queues on src and dst IPs and ports + */ + if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + switch (nfc->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST) || + !(nfc->data & RXH_L4_B_0_1) || + !(nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + break; + case UDP_V4_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV4; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV4; + break; + default: + return -EINVAL; + } + break; + case UDP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV6; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV6; + break; + default: + return -EINVAL; + } + break; + case SCTP_V4_FLOW: + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case SCTP_V6_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case IP_USER_FLOW: + case ETHER_FLOW: + /* RSS is not supported for these protocols */ + if (nfc->data) { + netif_err(tp, drv, tp->dev, "Command parameters not supported\n"); + return -EINVAL; + } + return 0; + break; + default: + return -EINVAL; + } + + /* if we changed something we need to update flags */ + if (rss_flags != tp->rss_flags) { + u32 rss_ctrl = RTL_R32(tp, RSS_CTRL_8125); + + if ((rss_flags & RTL8125_UDP_RSS_FLAGS) && + !(tp->rss_flags & RTL8125_UDP_RSS_FLAGS)) + netdev_warn(tp->dev, + "enabling UDP RSS: fragmented packets may " + "arrive out of order to the stack above\n"); + + tp->rss_flags = rss_flags; + + /* Perform hash on these packet types */ + rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP + | RSS_CTRL_IPV4_SUPP + | RSS_CTRL_IPV6_SUPP + | RSS_CTRL_TCP_IPV6_SUPP; + + rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP | + RSS_CTRL_UDP_IPV6_SUPP); + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) + rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) + rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; + + RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); + } + + return 0; +} + +int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + netif_info(tp, drv, tp->dev, "rss set rxnfc\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return ret; + + switch (cmd->cmd) { + case ETHTOOL_SRXFH: + ret = rtl8125_set_rss_hash_opt(tp, cmd); + break; + default: + break; + } + + return ret; +} + +static u32 _rtl8125_get_rxfh_key_size(struct rtl8125_private *tp) +{ + return sizeof(tp->rss_key); +} + +u32 rtl8125_get_rxfh_key_size(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + netif_info(tp, drv, tp->dev, "rss get key size\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return 0; + + return _rtl8125_get_rxfh_key_size(tp); +} + +u32 rtl8125_rss_indir_size(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + netif_info(tp, drv, tp->dev, "rss get indir tbl size\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return 0; + + return rtl8125_rss_indir_tbl_entries(tp); +} + +static void rtl8125_get_reta(struct rtl8125_private *tp, u32 *indir) +{ + int i, reta_size = rtl8125_rss_indir_tbl_entries(tp); + + for (i = 0; i < reta_size; i++) + indir[i] = tp->rss_indir_tbl[i]; +} + +int rtl8125_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + netif_info(tp, drv, tp->dev, "rss get rxfh\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return -EOPNOTSUPP; + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + if (indir) + rtl8125_get_reta(tp, indir); + + if (key) + memcpy(key, tp->rss_key, rtl8125_get_rxfh_key_size(dev)); + + return 0; +} + +static u32 rtl8125_rss_key_reg(struct rtl8125_private *tp) +{ + return RSS_KEY_8125; +} + +static u32 rtl8125_rss_indir_tbl_reg(struct rtl8125_private *tp) +{ + return RSS_INDIRECTION_TBL_8125_V2; +} + +static void rtl8125_store_reta(struct rtl8125_private *tp) +{ + u16 indir_tbl_reg = rtl8125_rss_indir_tbl_reg(tp); + u32 i, reta_entries = rtl8125_rss_indir_tbl_entries(tp); + u32 reta = 0; + u8 *indir_tbl = tp->rss_indir_tbl; + + /* Write redirection table to HW */ + for (i = 0; i < reta_entries; i++) { + reta |= indir_tbl[i] << (i & 0x3) * 8; + if ((i & 3) == 3) { + RTL_W32(tp, indir_tbl_reg, reta); + + indir_tbl_reg += 4; + reta = 0; + } + } +} + +static void rtl8125_store_rss_key(struct rtl8125_private *tp) +{ + const u16 rss_key_reg = rtl8125_rss_key_reg(tp); + u32 i, rss_key_size = _rtl8125_get_rxfh_key_size(tp); + u32 *rss_key = (u32*)tp->rss_key; + + /* Write redirection table to HW */ + for (i = 0; i < rss_key_size; i+=4) + RTL_W32(tp, rss_key_reg + i, *rss_key++); +} + +int rtl8125_set_rxfh(struct net_device *dev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + u32 reta_entries = rtl8125_rss_indir_tbl_entries(tp); + + netif_info(tp, drv, tp->dev, "rss set rxfh\n"); + + /* We require at least one supported parameter to be changed and no + * change in any of the unsupported parameters + */ + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + /* Fill out the redirection table */ + if (indir) { + int max_queues = tp->num_rx_rings; + + /* Verify user input. */ + for (i = 0; i < reta_entries; i++) + if (indir[i] >= max_queues) + return -EINVAL; + + for (i = 0; i < reta_entries; i++) + tp->rss_indir_tbl[i] = indir[i]; + } + + /* Fill out the rss hash key */ + if (key) + memcpy(tp->rss_key, key, rtl8125_get_rxfh_key_size(dev)); + + rtl8125_store_reta(tp); + + rtl8125_store_rss_key(tp); + + return 0; +} + +static u32 rtl8125_get_rx_desc_hash(struct rtl8125_private *tp, + struct RxDescV3 *descv3) +{ + return le32_to_cpu(descv3->RxDescNormalDDWord2.RSSResult); +} + +#define RXS_8125B_RSS_UDP BIT(9) +#define RXS_8125_RSS_IPV4 BIT(10) +#define RXS_8125_RSS_IPV6 BIT(12) +#define RXS_8125_RSS_TCP BIT(13) +#define RTL8125_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6) +#define RTL8125_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP) +void rtl8125_rx_hash(struct rtl8125_private *tp, + struct RxDescV3 *descv3, + struct sk_buff *skb) +{ + u16 rss_header_info; + + if (!(tp->dev->features & NETIF_F_RXHASH)) + return; + + rss_header_info = le16_to_cpu(descv3->RxDescNormalDDWord2.HeaderInfo); + + if (!(rss_header_info & RTL8125_RXS_RSS_L3_TYPE_MASK)) + return; + + skb_set_hash(skb, rtl8125_get_rx_desc_hash(tp, descv3), + (RTL8125_RXS_RSS_L4_TYPE_MASK & rss_header_info) ? + PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); +} + +void rtl8125_disable_rss(struct rtl8125_private *tp) +{ + RTL_W32(tp, RSS_CTRL_8125, 0x00); +} + +void _rtl8125_config_rss(struct rtl8125_private *tp) +{ + _rtl8125_set_rss_hash_opt(tp); + + rtl8125_store_reta(tp); + + rtl8125_store_rss_key(tp); +} + +void rtl8125_config_rss(struct rtl8125_private *tp) +{ + if (!tp->EnableRss) { + rtl8125_disable_rss(tp); + return; + } + + _rtl8125_config_rss(tp); +} + +void rtl8125_init_rss(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < rtl8125_rss_indir_tbl_entries(tp); i++) + tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings); + + netdev_rss_key_fill(tp->rss_key, RTL8125_RSS_KEY_SIZE); +} diff --git a/r8125/src/r8125_rss.h b/r8125/src/r8125_rss.h new file mode 100755 index 000000000..90e280902 --- /dev/null +++ b/r8125/src/r8125_rss.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_rtl8125_RSS_H +#define _LINUX_rtl8125_RSS_H + +#include +#include + +#define RTL8125_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ +#define RTL8125_MAX_INDIRECTION_TABLE_ENTRIES 128 + +enum rtl8125_rss_flag { + RTL_8125_RSS_FLAG_HASH_UDP_IPV4 = (1 << 0), + RTL_8125_RSS_FLAG_HASH_UDP_IPV6 = (1 << 1), +}; + +struct rtl8125_private; + +int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs); +int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); +u32 rtl8125_get_rxfh_key_size(struct net_device *netdev); +u32 rtl8125_rss_indir_size(struct net_device *netdev); +int rtl8125_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, + u8 *hfunc); +int rtl8125_set_rxfh(struct net_device *netdev, const u32 *indir, + const u8 *key, const u8 hfunc); +void rtl8125_rx_hash(struct rtl8125_private *tp, + struct RxDescV3 *descv3, + struct sk_buff *skb); +void _rtl8125_config_rss(struct rtl8125_private *tp); +void rtl8125_config_rss(struct rtl8125_private *tp); +void rtl8125_init_rss(struct rtl8125_private *tp); +u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp); +void rtl8125_disable_rss(struct rtl8125_private *tp); + +#endif /* _LINUX_rtl8125_RSS_H */ diff --git a/r8125/src/rtl_eeprom.c b/r8125/src/rtl_eeprom.c new file mode 100755 index 000000000..866ae5f33 --- /dev/null +++ b/r8125/src/rtl_eeprom.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "r8125.h" +#include "rtl_eeprom.h" + +//------------------------------------------------------------------- +//rtl8125_eeprom_type(): +// tell the eeprom type +//return value: +// 0: the eeprom type is 93C46 +// 1: the eeprom type is 93C56 or 93C66 +//------------------------------------------------------------------- +void rtl8125_eeprom_type(struct rtl8125_private *tp) +{ + u16 magic = 0; + + if (tp->mcfg == CFG_METHOD_DEFAULT) + goto out_no_eeprom; + + if(RTL_R8(tp, 0xD2)&0x04) { + //not support + //tp->eeprom_type = EEPROM_TWSI; + //tp->eeprom_len = 256; + goto out_no_eeprom; + } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { + tp->eeprom_type = EEPROM_TYPE_93C56; + tp->eeprom_len = 256; + } else { + tp->eeprom_type = EEPROM_TYPE_93C46; + tp->eeprom_len = 128; + } + + magic = rtl8125_eeprom_read_sc(tp, 0); + +out_no_eeprom: + if ((magic != 0x8129) && (magic != 0x8128)) { + tp->eeprom_type = EEPROM_TYPE_NONE; + tp->eeprom_len = 0; + } +} + +void rtl8125_eeprom_cleanup(struct rtl8125_private *tp) +{ + u8 x; + + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EEDI | Cfg9346_EECS); + + RTL_W8(tp, Cfg9346, x); + + rtl8125_raise_clock(tp, &x); + rtl8125_lower_clock(tp, &x); +} + +int rtl8125_eeprom_cmd_done(struct rtl8125_private *tp) +{ + u8 x; + int i; + + rtl8125_stand_by(tp); + + for (i = 0; i < 50000; i++) { + x = RTL_R8(tp, Cfg9346); + + if (x & Cfg9346_EEDO) { + udelay(RTL_CLOCK_RATE * 2 * 3); + return 0; + } + udelay(1); + } + + return -1; +} + +//------------------------------------------------------------------- +//rtl8125_eeprom_read_sc(): +// read one word from eeprom +//------------------------------------------------------------------- +u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg) +{ + int addr_sz = 6; + u8 x; + u16 data; + + if(tp->eeprom_type == EEPROM_TYPE_NONE) { + return -1; + } + + if (tp->eeprom_type==EEPROM_TYPE_93C46) + addr_sz = 6; + else if (tp->eeprom_type==EEPROM_TYPE_93C56) + addr_sz = 8; + + x = Cfg9346_EEM1 | Cfg9346_EECS; + RTL_W8(tp, Cfg9346, x); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); + rtl8125_shift_out_bits(tp, reg, addr_sz); + + data = rtl8125_shift_in_bits(tp); + + rtl8125_eeprom_cleanup(tp); + + RTL_W8(tp, Cfg9346, 0); + + return data; +} + +//------------------------------------------------------------------- +//rtl8125_eeprom_write_sc(): +// write one word to a specific address in the eeprom +//------------------------------------------------------------------- +void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data) +{ + u8 x; + int addr_sz = 6; + int w_dummy_addr = 4; + + if(tp->eeprom_type == EEPROM_TYPE_NONE) { + return ; + } + + if (tp->eeprom_type==EEPROM_TYPE_93C46) { + addr_sz = 6; + w_dummy_addr = 4; + } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { + addr_sz = 8; + w_dummy_addr = 6; + } + + x = Cfg9346_EEM1 | Cfg9346_EECS; + RTL_W8(tp, Cfg9346, x); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); + rtl8125_shift_out_bits(tp, reg, w_dummy_addr); + rtl8125_stand_by(tp); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); + rtl8125_shift_out_bits(tp, reg, addr_sz); + if (rtl8125_eeprom_cmd_done(tp) < 0) { + return; + } + rtl8125_stand_by(tp); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); + rtl8125_shift_out_bits(tp, reg, addr_sz); + rtl8125_shift_out_bits(tp, data, 16); + if (rtl8125_eeprom_cmd_done(tp) < 0) { + return; + } + rtl8125_stand_by(tp); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); + rtl8125_shift_out_bits(tp, reg, w_dummy_addr); + + rtl8125_eeprom_cleanup(tp); + RTL_W8(tp, Cfg9346, 0); +} + +void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x) +{ + *x = *x | Cfg9346_EESK; + RTL_W8(tp, Cfg9346, *x); + udelay(RTL_CLOCK_RATE); +} + +void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x) +{ + + *x = *x & ~Cfg9346_EESK; + RTL_W8(tp, Cfg9346, *x); + udelay(RTL_CLOCK_RATE); +} + +void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count) +{ + u8 x; + int mask; + + mask = 0x01 << (count - 1); + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); + + do { + if (data & mask) + x |= Cfg9346_EEDI; + else + x &= ~Cfg9346_EEDI; + + RTL_W8(tp, Cfg9346, x); + udelay(RTL_CLOCK_RATE); + rtl8125_raise_clock(tp, &x); + rtl8125_lower_clock(tp, &x); + mask = mask >> 1; + } while(mask); + + x &= ~Cfg9346_EEDI; + RTL_W8(tp, Cfg9346, x); +} + +u16 rtl8125_shift_in_bits(struct rtl8125_private *tp) +{ + u8 x; + u16 d, i; + + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); + + d = 0; + + for (i = 0; i < 16; i++) { + d = d << 1; + rtl8125_raise_clock(tp, &x); + + x = RTL_R8(tp, Cfg9346); + x &= ~Cfg9346_EEDI; + + if (x & Cfg9346_EEDO) + d |= 1; + + rtl8125_lower_clock(tp, &x); + } + + return d; +} + +void rtl8125_stand_by(struct rtl8125_private *tp) +{ + u8 x; + + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EECS | Cfg9346_EESK); + RTL_W8(tp, Cfg9346, x); + udelay(RTL_CLOCK_RATE); + + x |= Cfg9346_EECS; + RTL_W8(tp, Cfg9346, x); +} + +void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp) +{ + RTL_W8(tp, Cfg9346, Cfg9346_EEM1); + RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); + + udelay(20); + + RTL_W8(tp, Cfg9346, Cfg9346_EEM1); +} diff --git a/r8125/src/rtl_eeprom.h b/r8125/src/rtl_eeprom.h new file mode 100755 index 000000000..b0c4a050b --- /dev/null +++ b/r8125/src/rtl_eeprom.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +//EEPROM opcodes +#define RTL_EEPROM_READ_OPCODE 06 +#define RTL_EEPROM_WRITE_OPCODE 05 +#define RTL_EEPROM_ERASE_OPCODE 07 +#define RTL_EEPROM_EWEN_OPCODE 19 +#define RTL_EEPROM_EWDS_OPCODE 16 + +#define RTL_CLOCK_RATE 3 + +void rtl8125_eeprom_type(struct rtl8125_private *tp); +void rtl8125_eeprom_cleanup(struct rtl8125_private *tp); +u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg); +void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data); +void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count); +u16 rtl8125_shift_in_bits(struct rtl8125_private *tp); +void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x); +void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x); +void rtl8125_stand_by(struct rtl8125_private *tp); +void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp); diff --git a/r8125/src/rtltool.c b/r8125/src/rtltool.c new file mode 100755 index 000000000..ace717bde --- /dev/null +++ b/r8125/src/rtltool.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "r8125.h" +#include "rtl_eeprom.h" +#include "rtltool.h" + +int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr) +{ + struct rtltool_cmd my_cmd; + int ret; + + if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) + return -EFAULT; + + ret = 0; + switch (my_cmd.cmd) { + case RTLTOOL_READ_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1) + my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); + else if (my_cmd.len==2) + my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); + else if (my_cmd.len==4) + my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); + else { + ret = -EOPNOTSUPP; + break; + } + + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTLTOOL_WRITE_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1) + writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); + else if (my_cmd.len==2) + writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); + else if (my_cmd.len==4) + writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); + else { + ret = -EOPNOTSUPP; + break; + } + + break; + + case RTLTOOL_READ_PHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_mdio_prot_read(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_PHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); + break; + + case RTLTOOL_READ_EPHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_ephy_read(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_EPHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_ephy_write(tp, my_cmd.offset, my_cmd.data); + break; + + case RTLTOOL_READ_ERI: + my_cmd.data = 0; + if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { + my_cmd.data = rtl8125_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); + } else { + ret = -EOPNOTSUPP; + break; + } + + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_ERI: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { + rtl8125_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); + } else { + ret = -EOPNOTSUPP; + break; + } + break; + + case RTLTOOL_READ_PCI: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = 0; + if (my_cmd.len==1) + pci_read_config_byte(tp->pci_dev, my_cmd.offset, + (u8 *)&my_cmd.data); + else if (my_cmd.len==2) + pci_read_config_word(tp->pci_dev, my_cmd.offset, + (u16 *)&my_cmd.data); + else if (my_cmd.len==4) + pci_read_config_dword(tp->pci_dev, my_cmd.offset, + &my_cmd.data); + else { + ret = -EOPNOTSUPP; + break; + } + + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTLTOOL_WRITE_PCI: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1) + pci_write_config_byte(tp->pci_dev, my_cmd.offset, + my_cmd.data); + else if (my_cmd.len==2) + pci_write_config_word(tp->pci_dev, my_cmd.offset, + my_cmd.data); + else if (my_cmd.len==4) + pci_write_config_dword(tp->pci_dev, my_cmd.offset, + my_cmd.data); + else { + ret = -EOPNOTSUPP; + break; + } + + break; + + case RTLTOOL_READ_EEPROM: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_eeprom_read_sc(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_EEPROM: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); + break; + + case RTL_READ_OOB_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_oob_mutex_lock(tp); + my_cmd.data = rtl8125_ocp_read(tp, my_cmd.offset, 4); + rtl8125_oob_mutex_unlock(tp); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTL_WRITE_OOB_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len == 0 || my_cmd.len > 4) + return -EOPNOTSUPP; + + rtl8125_oob_mutex_lock(tp); + rtl8125_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); + rtl8125_oob_mutex_unlock(tp); + break; + + case RTL_ENABLE_PCI_DIAG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + tp->rtk_enable_diag = 1; + + dprintk("enable rtk diag\n"); + break; + + case RTL_DISABLE_PCI_DIAG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + tp->rtk_enable_diag = 0; + + dprintk("disable rtk diag\n"); + break; + + case RTL_READ_MAC_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.offset % 2) + return -EOPNOTSUPP; + + my_cmd.data = rtl8125_mac_ocp_read(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTL_WRITE_MAC_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if ((my_cmd.offset % 2) || (my_cmd.len != 2)) + return -EOPNOTSUPP; + + rtl8125_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); + break; + + case RTL_DIRECT_READ_PHY_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTL_DIRECT_WRITE_PHY_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} diff --git a/r8125/src/rtltool.h b/r8125/src/rtltool.h new file mode 100755 index 000000000..fc8a10ca8 --- /dev/null +++ b/r8125/src/rtltool.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_RTLTOOL_H +#define _LINUX_RTLTOOL_H + +#define SIOCRTLTOOL SIOCDEVPRIVATE+1 + +enum rtl_cmd { + RTLTOOL_READ_MAC=0, + RTLTOOL_WRITE_MAC, + RTLTOOL_READ_PHY, + RTLTOOL_WRITE_PHY, + RTLTOOL_READ_EPHY, + RTLTOOL_WRITE_EPHY, + RTLTOOL_READ_ERI, + RTLTOOL_WRITE_ERI, + RTLTOOL_READ_PCI, + RTLTOOL_WRITE_PCI, + RTLTOOL_READ_EEPROM, + RTLTOOL_WRITE_EEPROM, + + RTL_READ_OOB_MAC, + RTL_WRITE_OOB_MAC, + + RTL_ENABLE_PCI_DIAG, + RTL_DISABLE_PCI_DIAG, + + RTL_READ_MAC_OCP, + RTL_WRITE_MAC_OCP, + + RTL_DIRECT_READ_PHY_OCP, + RTL_DIRECT_WRITE_PHY_OCP, + + RTLTOOL_INVALID +}; + +struct rtltool_cmd { + __u32 cmd; + __u32 offset; + __u32 len; + __u32 data; +}; + +enum mode_access { + MODE_NONE=0, + MODE_READ, + MODE_WRITE +}; + +#ifdef __KERNEL__ +int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr); +#endif + +#endif /* _LINUX_RTLTOOL_H */ From 791a0643aaba0cf1dc6c4c959fc06fb0fff133fa Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 4 Jan 2022 09:06:13 +0100 Subject: [PATCH 0644/2059] Add luci-proto-modemmanager --- luci-proto-modemmanager/Makefile | 14 ++ .../resources/protocol/modemmanager.js | 136 ++++++++++++++++++ .../rpcd/acl.d/luci-proto-modemmanager.json | 12 ++ 3 files changed, 162 insertions(+) create mode 100644 luci-proto-modemmanager/Makefile create mode 100644 luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js create mode 100644 luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json diff --git a/luci-proto-modemmanager/Makefile b/luci-proto-modemmanager/Makefile new file mode 100644 index 000000000..37d96f118 --- /dev/null +++ b/luci-proto-modemmanager/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2008-2014 The LuCI Team +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Support for ModemManager +LUCI_DEPENDS:=+modemmanager + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js b/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js new file mode 100644 index 000000000..88e516a8e --- /dev/null +++ b/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js @@ -0,0 +1,136 @@ +'use strict'; +'require fs'; +'require form'; +'require network'; + +function getModemList() { + return fs.exec_direct('/usr/bin/mmcli', [ '-L' ]).then(function(res) { + var lines = (res || '').split(/\n/), + tasks = []; + + for (var i = 0; i < lines.length; i++) { + var m = lines[i].match(/\/Modem\/(\d+)/); + if (m) + tasks.push(fs.exec_direct('/usr/bin/mmcli', [ '-m', m[1] ])); + } + + return Promise.all(tasks).then(function(res) { + var modems = []; + + for (var i = 0; i < res.length; i++) { + var man = res[i].match(/manufacturer: ([^\n]+)/), + mod = res[i].match(/model: ([^\n]+)/), + dev = res[i].match(/device: ([^\n]+)/); + + if (dev) { + modems.push({ + device: dev[1].trim(), + manufacturer: (man ? man[1].trim() : '') || '?', + model: (mod ? mod[1].trim() : '') || dev[1].trim() + }); + } + } + + return modems; + }); + }); +} + +network.registerPatternVirtual(/^mobiledata-.+$/); +network.registerErrorCode('MM_CONNECT_FAILED', _('Connection attempt failed.')); +network.registerErrorCode('MM_DISCONNECT_IN_PROGRESS', _('Modem disconnection in progress. Please wait.')); +network.registerErrorCode('MM_CONNECT_IN_PROGRESS', _('Modem connection in progress. Please wait. This process will timeout after 2 minutes.')); +network.registerErrorCode('MM_TEARDOWN_IN_PROGRESS', _('Modem bearer teardown in progress.')); +network.registerErrorCode('MM_MODEM_DISABLED', _('Modem is disabled.')); +network.registerErrorCode('DEVICE_NOT_MANAGED', _('Device not managed by ModemManager.')); +network.registerErrorCode('INVALID_BEARER_LIST', _('Invalid bearer list. Possibly too many bearers created. This protocol supports one and only one bearer.')); +network.registerErrorCode('UNKNOWN_METHOD', _('Unknown and unsupported connection method.')); +network.registerErrorCode('DISCONNECT_FAILED', _('Disconnection attempt failed.')); + +return network.registerProtocol('modemmanager', { + getI18n: function() { + return _('ModemManager'); + }, + + getIfname: function() { + return this._ubus('l3_device') || 'modemmanager-%s'.format(this.sid); + }, + + getOpkgPackage: function() { + return 'modemmanager'; + }, + + isFloating: function() { + return true; + }, + + isVirtual: function() { + return true; + }, + + getDevices: function() { + return null; + }, + + containsDevice: function(ifname) { + return (network.getIfnameOf(ifname) == this.getIfname()); + }, + + renderFormOptions: function(s) { + var dev = this.getL3Device() || this.getDevice(), o; + + o = s.taboption('general', form.ListValue, '_modem_device', _('Modem device')); + o.ucioption = 'device'; + o.rmempty = false; + o.load = function(section_id) { + return getModemList().then(L.bind(function(devices) { + for (var i = 0; i < devices.length; i++) + this.value(devices[i].device, + '%s - %s'.format(devices[i].manufacturer, devices[i].model)); + return form.Value.prototype.load.apply(this, [section_id]); + }, this)); + }; + + o = s.taboption('general', form.Value, 'apn', _('APN')); + o.validate = function(section_id, value) { + if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value)) + return _('Invalid APN provided'); + + return true; + }; + + o = s.taboption('general', form.Value, 'pincode', _('PIN')); + o.datatype = 'and(uinteger,minlength(4),maxlength(8))'; + + o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type')); + o.value('both', _('PAP/CHAP (both)')); + o.value('pap', 'PAP'); + o.value('chap', 'CHAP'); + o.value('none', _('None')); + o.default = 'none'; + + o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username')); + o.depends('auth', 'pap'); + o.depends('auth', 'chap'); + o.depends('auth', 'both'); + + o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password')); + o.depends('auth', 'pap'); + o.depends('auth', 'chap'); + o.depends('auth', 'both'); + o.password = true; + + o = s.taboption('general', form.ListValue, 'iptype', _('IP Type')); + o.value('ipv4v6', _('IPv4/IPv6 (both - defaults to IPv4)')) + o.value('ipv4', _('IPv4 only')); + o.value('ipv6', _('IPv6 only')); + o.default = 'ipv4v6'; + + o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU')); + o.placeholder = dev ? (dev.getMTU() || '1500') : '1500'; + o.datatype = 'max(9200)'; + + o = s.taboption('general', form.Value, 'signalrate', _('Signal Refresh Rate'), _("In seconds")); + o.datatype = 'uinteger'; + } +}); diff --git a/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json b/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json new file mode 100644 index 000000000..716f4c465 --- /dev/null +++ b/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json @@ -0,0 +1,12 @@ +{ + "luci-proto-modemmanager": { + "description": "Grant access to mmcli", + "read": { + "cgi-io": [ "exec" ], + "file": { + "/usr/bin/mmcli -L": [ "exec" ], + "/usr/bin/mmcli -m [0-9]": [ "exec" ] + } + } + } +} From 6e94306e936fbad13d47f6cb4e3df937ce8ff487 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 5 Jan 2022 08:50:44 +0100 Subject: [PATCH 0645/2059] Fix on setting some routes --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 436dbfc3c..fd04c31bc 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -454,7 +454,7 @@ set_server_all_routes() { config_foreach set_routes_intf interface uintf="$(echo $routesintf | awk '{print $5}')" uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 1 | tr -d '\t' | sort | tr -d '\n' | sed 's/ *$//')" != "$(echo $serverip $routesintf | sort | sed 's/ *$//')" ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 1 | grep $uintf)" = "" ]); then + if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 1 | tr -d '\t' | tr -d '\n' | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" != "$(echo $serverip $routesintf | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 1 | grep $uintf)" = "" ]); then while [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip r del $serverip done @@ -462,7 +462,7 @@ set_server_all_routes() { ip route replace $serverip scope global metric 1 $routesintf 2>&1 >/dev/null [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" fi - if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ -n "$uintfb" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then + if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n' | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" != "$(echo $serverip $routesintfbackup | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" ]) || ([ "$nbintfb" = "1" ] && [ -n "$uintfb" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" ip route replace $serverip scope global metric 999 $routesintfbackup 2>&1 >/dev/null fi @@ -1034,8 +1034,8 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then config_foreach set_server_route server fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then - _log "Interface route not yet set, set route ip r replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" - ip r replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 + _log "Interface route not yet set, set route ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" + ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi fi if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then From 6f43402777a922feab807dce0509318ee2fd3404 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Jan 2022 15:35:21 +0100 Subject: [PATCH 0646/2059] Remove luci-proto-manager, not needed --- luci-proto-modemmanager/Makefile | 14 -- .../resources/protocol/modemmanager.js | 136 ------------------ .../rpcd/acl.d/luci-proto-modemmanager.json | 12 -- 3 files changed, 162 deletions(-) delete mode 100644 luci-proto-modemmanager/Makefile delete mode 100644 luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js delete mode 100644 luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json diff --git a/luci-proto-modemmanager/Makefile b/luci-proto-modemmanager/Makefile deleted file mode 100644 index 37d96f118..000000000 --- a/luci-proto-modemmanager/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (C) 2008-2014 The LuCI Team -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Support for ModemManager -LUCI_DEPENDS:=+modemmanager - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js b/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js deleted file mode 100644 index 88e516a8e..000000000 --- a/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js +++ /dev/null @@ -1,136 +0,0 @@ -'use strict'; -'require fs'; -'require form'; -'require network'; - -function getModemList() { - return fs.exec_direct('/usr/bin/mmcli', [ '-L' ]).then(function(res) { - var lines = (res || '').split(/\n/), - tasks = []; - - for (var i = 0; i < lines.length; i++) { - var m = lines[i].match(/\/Modem\/(\d+)/); - if (m) - tasks.push(fs.exec_direct('/usr/bin/mmcli', [ '-m', m[1] ])); - } - - return Promise.all(tasks).then(function(res) { - var modems = []; - - for (var i = 0; i < res.length; i++) { - var man = res[i].match(/manufacturer: ([^\n]+)/), - mod = res[i].match(/model: ([^\n]+)/), - dev = res[i].match(/device: ([^\n]+)/); - - if (dev) { - modems.push({ - device: dev[1].trim(), - manufacturer: (man ? man[1].trim() : '') || '?', - model: (mod ? mod[1].trim() : '') || dev[1].trim() - }); - } - } - - return modems; - }); - }); -} - -network.registerPatternVirtual(/^mobiledata-.+$/); -network.registerErrorCode('MM_CONNECT_FAILED', _('Connection attempt failed.')); -network.registerErrorCode('MM_DISCONNECT_IN_PROGRESS', _('Modem disconnection in progress. Please wait.')); -network.registerErrorCode('MM_CONNECT_IN_PROGRESS', _('Modem connection in progress. Please wait. This process will timeout after 2 minutes.')); -network.registerErrorCode('MM_TEARDOWN_IN_PROGRESS', _('Modem bearer teardown in progress.')); -network.registerErrorCode('MM_MODEM_DISABLED', _('Modem is disabled.')); -network.registerErrorCode('DEVICE_NOT_MANAGED', _('Device not managed by ModemManager.')); -network.registerErrorCode('INVALID_BEARER_LIST', _('Invalid bearer list. Possibly too many bearers created. This protocol supports one and only one bearer.')); -network.registerErrorCode('UNKNOWN_METHOD', _('Unknown and unsupported connection method.')); -network.registerErrorCode('DISCONNECT_FAILED', _('Disconnection attempt failed.')); - -return network.registerProtocol('modemmanager', { - getI18n: function() { - return _('ModemManager'); - }, - - getIfname: function() { - return this._ubus('l3_device') || 'modemmanager-%s'.format(this.sid); - }, - - getOpkgPackage: function() { - return 'modemmanager'; - }, - - isFloating: function() { - return true; - }, - - isVirtual: function() { - return true; - }, - - getDevices: function() { - return null; - }, - - containsDevice: function(ifname) { - return (network.getIfnameOf(ifname) == this.getIfname()); - }, - - renderFormOptions: function(s) { - var dev = this.getL3Device() || this.getDevice(), o; - - o = s.taboption('general', form.ListValue, '_modem_device', _('Modem device')); - o.ucioption = 'device'; - o.rmempty = false; - o.load = function(section_id) { - return getModemList().then(L.bind(function(devices) { - for (var i = 0; i < devices.length; i++) - this.value(devices[i].device, - '%s - %s'.format(devices[i].manufacturer, devices[i].model)); - return form.Value.prototype.load.apply(this, [section_id]); - }, this)); - }; - - o = s.taboption('general', form.Value, 'apn', _('APN')); - o.validate = function(section_id, value) { - if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value)) - return _('Invalid APN provided'); - - return true; - }; - - o = s.taboption('general', form.Value, 'pincode', _('PIN')); - o.datatype = 'and(uinteger,minlength(4),maxlength(8))'; - - o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type')); - o.value('both', _('PAP/CHAP (both)')); - o.value('pap', 'PAP'); - o.value('chap', 'CHAP'); - o.value('none', _('None')); - o.default = 'none'; - - o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username')); - o.depends('auth', 'pap'); - o.depends('auth', 'chap'); - o.depends('auth', 'both'); - - o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password')); - o.depends('auth', 'pap'); - o.depends('auth', 'chap'); - o.depends('auth', 'both'); - o.password = true; - - o = s.taboption('general', form.ListValue, 'iptype', _('IP Type')); - o.value('ipv4v6', _('IPv4/IPv6 (both - defaults to IPv4)')) - o.value('ipv4', _('IPv4 only')); - o.value('ipv6', _('IPv6 only')); - o.default = 'ipv4v6'; - - o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU')); - o.placeholder = dev ? (dev.getMTU() || '1500') : '1500'; - o.datatype = 'max(9200)'; - - o = s.taboption('general', form.Value, 'signalrate', _('Signal Refresh Rate'), _("In seconds")); - o.datatype = 'uinteger'; - } -}); diff --git a/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json b/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json deleted file mode 100644 index 716f4c465..000000000 --- a/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "luci-proto-modemmanager": { - "description": "Grant access to mmcli", - "read": { - "cgi-io": [ "exec" ], - "file": { - "/usr/bin/mmcli -L": [ "exec" ], - "/usr/bin/mmcli -m [0-9]": [ "exec" ] - } - } - } -} From eca6a66cf6ec81805742f7454ee5a0c0c6be9ca9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 11 Jan 2022 11:11:49 +0100 Subject: [PATCH 0647/2059] Disable sysctl error --- mptcp/files/etc/init.d/mptcp | 30 +++++++++---------- .../share/omr/post-tracking.d/post-tracking | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 140db96f9..ac2b7496d 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -33,24 +33,24 @@ global_multipath_settings() { # Global MPTCP configuration if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then - sysctl -qw net.mptcp.mptcp_enabled="$multipath_status" - [ -z "$mptcp_path_manager" ] || sysctl -qw net.mptcp.mptcp_path_manager="$mptcp_path_manager" - [ -z "$mptcp_scheduler" ] || sysctl -qw net.mptcp.mptcp_scheduler="$mptcp_scheduler" - [ -z "$mptcp_checksum" ] || sysctl -qw net.mptcp.mptcp_checksum="$mptcp_checksum" - [ -z "$mptcp_debug" ] || sysctl -qw net.mptcp.mptcp_debug="$mptcp_debug" - [ -z "$mptcp_syn_retries" ] || sysctl -qw net.mptcp.mptcp_syn_retries="$mptcp_syn_retries" - [ -z "$mptcp_fullmesh_num_subflows" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/num_subflows="$mptcp_fullmesh_num_subflows" - [ -z "$mptcp_fullmesh_create_on_err" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/create_on_err="$mptcp_fullmesh_create_on_err" - [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qw /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" - [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qw /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" - [ -z "$mptcp_rr_num_segments" ] || sysctl -qw /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" + sysctl -qew net.mptcp.mptcp_enabled="$multipath_status" + [ -z "$mptcp_path_manager" ] || sysctl -qew net.mptcp.mptcp_path_manager="$mptcp_path_manager" + [ -z "$mptcp_scheduler" ] || sysctl -qew net.mptcp.mptcp_scheduler="$mptcp_scheduler" + [ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.mptcp_checksum="$mptcp_checksum" + [ -z "$mptcp_debug" ] || sysctl -qew net.mptcp.mptcp_debug="$mptcp_debug" + [ -z "$mptcp_syn_retries" ] || sysctl -qew net.mptcp.mptcp_syn_retries="$mptcp_syn_retries" + [ -z "$mptcp_fullmesh_num_subflows" ] || sysctl -qew /sys/module/mptcp_fullmesh/parameters/num_subflows="$mptcp_fullmesh_num_subflows" + [ -z "$mptcp_fullmesh_create_on_err" ] || sysctl -qew /sys/module/mptcp_fullmesh/parameters/create_on_err="$mptcp_fullmesh_create_on_err" + [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qew /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" + [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qew /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" + [ -z "$mptcp_rr_num_segments" ] || sysctl -qew /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" else - sysctl -qw net.mptcp.enabled="$multipath_status" + sysctl -qew net.mptcp.enabled="$multipath_status" ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null - [ -z "$mptcp_add_addr_timeout" ] || sysctl -qw net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" - [ -z "$mptcp_checksum" ] || sysctl -qw net.mptcp.checksum_enabled="$mptcp_checksum" + [ -z "$mptcp_add_addr_timeout" ] || sysctl -qew net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" + [ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.checksum_enabled="$mptcp_checksum" fi - [ -z "$congestion" ] || sysctl -qw net.ipv4.tcp_congestion_control="$congestion" + [ -z "$congestion" ] || sysctl -qew net.ipv4.tcp_congestion_control="$congestion" } interface_macaddr_count() { diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index fd04c31bc..8df993d79 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1111,7 +1111,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { - if [ "$(sysctl -qn net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ] || [ "$(sysctl -qn net.mptcp.enabled | tr -d '\n')" = "1" ]; then + if [ "$(sysctl -qen net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ] || [ "$(sysctl -qen net.mptcp.enabled | tr -d '\n')" = "1" ]; then _log "Multipath $OMR_TRACKER_DEVICE switched to $multipath_config" multipath "$OMR_TRACKER_DEVICE" "$multipath_config" fi From e7d53854bb9804e19e0d351b5d05c32f0c1d8666 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 12 Jan 2022 09:22:33 +0100 Subject: [PATCH 0648/2059] Fix glorytun-udp issue when path is back --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 8df993d79..d3bd7e17f 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1066,7 +1066,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then serverip=$1 #gtudpst="up" #[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" - if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ] && [ -n "$(resolveip -4 $serverip)" ]; then + if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP | grep running)" = "" ] && [ -n "$(resolveip -4 $serverip)" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 @@ -1081,7 +1081,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi fi fi - if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6)" = "" ] && [ -n "$(resolveip -6 $serverip)" ]; then + if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6 | grep running)" = "" ] && [ -n "$(resolveip -6 $serverip)" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 From d8850437c31b470641ff96e19f745c2ac7823b9f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 12 Jan 2022 18:23:15 +0100 Subject: [PATCH 0649/2059] Set Force TTL as optional --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index d3610bd36..0e4e087ef 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -896,7 +896,7 @@

    - +
    <%:You can force a TTL. Some LTE provider detect tethering by inpecting packet TTL value, setting it to 65 often solve the issue.%> From 5140d59e8c57d8d3d62f0fe841d05cda79411a01 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 12 Jan 2022 18:23:34 +0100 Subject: [PATCH 0650/2059] Fixes on post-tracking --- .../share/omr/post-tracking.d/post-tracking | 68 +++++++++++++------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index d3bd7e17f..b54139b8c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -15,9 +15,10 @@ find_network_device() { [ "${name}" = "${device}" ] && device_section="${cfg}" } - - config_load network - config_foreach check_device device "$(uci -q netwok.${device}.device)" + if [ ! -z "$device" ]; then + config_load network + config_foreach check_device device "$(uci -q network.${device}.device)" + fi echo "${device_section}" } @@ -27,6 +28,7 @@ set_route() { PREVINTERFACE=$2 SETDEFAULT=$3 [ -z "$SETDEFAULT" ] && SETDEFAULT="yes" + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -67,6 +69,7 @@ set_route6() { PREVINTERFACE=$2 SETDEFAULT=$3 [ -z "$SETDEFAULT" ] && SETDEFAULT="yes" + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -108,6 +111,7 @@ set_server_default_route() { [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return + [ -z "$OMR_TRACKER_INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { @@ -133,6 +137,7 @@ set_server_default_route6() { [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return + [ -z "$OMR_TRACKER_INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { @@ -183,6 +188,7 @@ delete_server_default_route6() { set_routes_intf() { local multipath_config_route local INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -239,6 +245,7 @@ set_routes_intf() { set_routes_intf6() { local multipath_config_route local INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -311,6 +318,7 @@ set_routes_intf6() { set_route_balancing() { local multipath_config_route interface_gw interface_if INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -361,6 +369,7 @@ set_route_balancing() { set_route_balancing6() { local multipath_config_route interface_gw interface_if INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -426,6 +435,7 @@ set_route_balancing6() { set_server_all_routes() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -473,6 +483,7 @@ set_server_all_routes() { set_server_all_routes6() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -521,6 +532,7 @@ set_server_all_routes6() { set_server_route() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -558,6 +570,7 @@ set_server_route() { set_server_route6() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -600,7 +613,11 @@ del_server_route() { [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" [ -n "$serverip" ] && _log "Delete default route to $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" local metric - metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + if [ -z "$OMR_TRACKER_INTERFACE" ]; then + metric=0 + else + metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + fi [ -n "$metric" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip | grep $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 @@ -620,7 +637,11 @@ del_server_route6() { [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" [ -n "$serverip" ] && _log "Delete default route to $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" local metric - metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + if [ -z "$OMR_TRACKER_INTERFACE" ]; then + metric=0 + else + metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + fi [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip"] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 } @@ -650,7 +671,7 @@ disable_pihole() { enable_pihole() { local server=$1 nbserver=$((nbserver+1)) - if [ "$(uci -q get openmptcprouter.${server}.pihole)" = "1" ] && [ "$(uci -q get dhcp.@dnsmasq[0].server | grep '127.0.0.1#5353')" != "" ]; then + if [ -n "$server" ] && [ "$(uci -q get openmptcprouter.${server}.pihole)" = "1" ] && [ "$(uci -q get dhcp.@dnsmasq[0].server | grep '127.0.0.1#5353')" != "" ]; then piholeenabled=$((piholeenabled+1)) fi } @@ -685,7 +706,7 @@ interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e # An interface in error will never be used in MPTCP if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then - if [ "$interface_up" = "true" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then + if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart interface" _log "Set $OMR_TRACKER_INTERFACE down" ifdown $OMR_TRACKER_INTERFACE @@ -698,7 +719,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ "$OMR_TRACKER_PREV_STATUS" = "$OMR_TRACKER_STATUS" ]; then exit 0 fi - if [ "$multipath_status" != "off" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ]; then + if [ "$multipath_status" != "off" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ]); then if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then _log "$OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) switched off" else @@ -714,7 +735,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ -n "$OMR_TRACKER_DEVICE_IP6" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set down > /dev/null 2>&1 fi - if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ] && [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ]; then + if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ] && [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ]; then VPN_BASE_INTF="$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.baseintf)" VPN_BASE_INTF_IP=$(ubus call network.interface.$VPN_BASE_INTF status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") uci -q batch <<-EOF >/dev/null @@ -735,16 +756,18 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi fi - if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw: $default_gw - Set routes (current: $(ip r) )" - config_load network - config_foreach set_route interface $OMR_TRACKER_INTERFACE - config_foreach set_route6 interface $OMR_TRACKER_INTERFACE - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New routes $(ip r)" - elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then - config_load network - config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" - config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw: $default_gw - Set routes (current: $(ip r) )" + config_load network + config_foreach set_route interface $OMR_TRACKER_INTERFACE + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New routes $(ip r)" + elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then + config_load network + config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" + fi fi mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)" [ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" @@ -851,7 +874,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om fi # Set VPN MTU - if [ -n "$OMR_TRACKER_LATENCY" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ]); then + if [ -n "$OMR_TRACKER_LATENCY" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ]); then local serverip=$(uci -q get shadowsocks-libev.sss0.server) [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" if [ "$serverip" = "192.168.1.3" ] || [ "$serverip" = "127.0.0.1" ]; then @@ -860,8 +883,9 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE="interface" uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then - if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) + OMR_NETWORK_DEVICE=$(find_network_device ${OMR_TRACKER_INTERFACE}) + if [ -n "$OMR_NETWORK_DEVICE" ] && [ -n "$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + mtu=$(uci -q get network.$OMR_NETWORK_DEVICE.mtu) uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu [ -n "$mtu" ] && ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") From e7f09b2b4cfe44e6edc3f0a807ec2cc8cf3fd7cd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 13 Jan 2022 14:33:46 +0100 Subject: [PATCH 0651/2059] Make IPv6 address and gateway optional in wizard --- .../luasrc/view/openmptcprouter/wizard.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 0e4e087ef..f2c85d3e9 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -682,7 +682,7 @@
    - +
    <%:Set an IP in the same network as the modem%> @@ -696,7 +696,7 @@
    - " data-type="ip6addr"> + " data-type="ip6addr" data-optional="true">
    <%:Set here IP of the modem%> From 41087ba6f98e0c68d4e4eed8278d7a5e8868c92a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 13 Jan 2022 14:34:14 +0100 Subject: [PATCH 0652/2059] Disable httping test by default --- omr-tracker/files/etc/config/omr-tracker | 2 +- omr-tracker/files/etc/uci-defaults/omr-tracker | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index 93aaf1674..f0c485a70 100644 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -23,7 +23,7 @@ config defaults 'defaults' option interval_tries '1' option type 'ping' option wait_test '0' - option server_http_test '1' + option server_http_test '0' option restart_down '0' option mail_alert '0' diff --git a/omr-tracker/files/etc/uci-defaults/omr-tracker b/omr-tracker/files/etc/uci-defaults/omr-tracker index 13e4fe990..7ae77dddf 100755 --- a/omr-tracker/files/etc/uci-defaults/omr-tracker +++ b/omr-tracker/files/etc/uci-defaults/omr-tracker @@ -95,7 +95,7 @@ fi if [ "$(uci -q get omr-tracker.defaults.server_http_test)" = "" ]; then uci -q batch <<-EOF >/dev/null - set omr-tracker.defaults.server_http_test=1 + set omr-tracker.defaults.server_http_test=0 commit omr-tracker EOF fi From 90e0c41dc6b6059bb65f73a6948ac5ff76b39438 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 13 Jan 2022 19:46:01 +0100 Subject: [PATCH 0653/2059] Fix default for http server test --- omr-tracker/files/etc/init.d/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 479ce2d5e..419e2bd05 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -28,7 +28,7 @@ _validate_section() { 'wait_test:uinteger' \ 'type:string:undef' \ 'enabled:bool:1' \ - 'server_http_test:bool:1' \ + 'server_http_test:bool:0' \ 'options:string' [ -z "$hosts" ] && hosts=$tmp_hosts From 571d37e14741d40cf4a8e5ea9095ba6c3eb9efbf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 14 Jan 2022 09:01:39 +0100 Subject: [PATCH 0654/2059] Changes on netifd and modemmanager to use the defaultroute setting --- modemmanager/Config.in | 21 + modemmanager/Makefile | 138 +++++ modemmanager/README.md | 40 ++ modemmanager/files/25-modemmanager-net | 31 + modemmanager/files/25-modemmanager-tty | 16 + modemmanager/files/25-modemmanager-usb | 13 + modemmanager/files/modemmanager.common | 332 +++++++++++ modemmanager/files/modemmanager.init | 36 ++ modemmanager/files/modemmanager.proto | 554 ++++++++++++++++++ netifd/Makefile | 52 ++ netifd/files/etc/hotplug.d/iface/00-netstate | 6 + .../etc/hotplug.d/net/20-smp-packet-steering | 67 +++ netifd/files/etc/init.d/network | 144 +++++ .../etc/uci-defaults/14_migrate-dhcp-release | 23 + netifd/files/etc/udhcpc.user | 1 + netifd/files/lib/netifd/dhcp.script | 119 ++++ netifd/files/lib/netifd/proto/dhcp.sh | 89 +++ netifd/files/lib/network/config.sh | 76 +++ netifd/files/sbin/devstatus | 12 + netifd/files/sbin/ifdown | 1 + netifd/files/sbin/ifstatus | 13 + netifd/files/sbin/ifup | 77 +++ netifd/files/usr/share/udhcpc/default.script | 57 ++ 23 files changed, 1918 insertions(+) create mode 100644 modemmanager/Config.in create mode 100644 modemmanager/Makefile create mode 100644 modemmanager/README.md create mode 100644 modemmanager/files/25-modemmanager-net create mode 100644 modemmanager/files/25-modemmanager-tty create mode 100644 modemmanager/files/25-modemmanager-usb create mode 100644 modemmanager/files/modemmanager.common create mode 100755 modemmanager/files/modemmanager.init create mode 100755 modemmanager/files/modemmanager.proto create mode 100644 netifd/Makefile create mode 100644 netifd/files/etc/hotplug.d/iface/00-netstate create mode 100644 netifd/files/etc/hotplug.d/net/20-smp-packet-steering create mode 100755 netifd/files/etc/init.d/network create mode 100644 netifd/files/etc/uci-defaults/14_migrate-dhcp-release create mode 100644 netifd/files/etc/udhcpc.user create mode 100755 netifd/files/lib/netifd/dhcp.script create mode 100755 netifd/files/lib/netifd/proto/dhcp.sh create mode 100755 netifd/files/lib/network/config.sh create mode 100755 netifd/files/sbin/devstatus create mode 120000 netifd/files/sbin/ifdown create mode 100755 netifd/files/sbin/ifstatus create mode 100755 netifd/files/sbin/ifup create mode 100755 netifd/files/usr/share/udhcpc/default.script diff --git a/modemmanager/Config.in b/modemmanager/Config.in new file mode 100644 index 000000000..283a9e10a --- /dev/null +++ b/modemmanager/Config.in @@ -0,0 +1,21 @@ +menu "Configuration" +depends on PACKAGE_modemmanager + + config MODEMMANAGER_WITH_MBIM + bool "Include MBIM support" + default y + help + Compile ModemManager with MBIM support + + config MODEMMANAGER_WITH_QMI + bool "Include QMI support" + default y + help + Compile ModemManager with QMI support + + config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS + bool "Allow AT commands via DBus" + default n + help + Compile ModemManager allowing AT commands without debug flag +endmenu diff --git a/modemmanager/Makefile b/modemmanager/Makefile new file mode 100644 index 000000000..19f94b01f --- /dev/null +++ b/modemmanager/Makefile @@ -0,0 +1,138 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=modemmanager +PKG_VERSION:=1.16.6 +PKG_RELEASE:=1 + +PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager +PKG_HASH:=2a90b6260f66d3135609d62667ada73416694d717e7fd9b73223e3703a499617 +PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION) + +PKG_MAINTAINER:=Nicholas Smith +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/modemmanager/config + source "$(SOURCE)/Config.in" +endef + +define Package/modemmanager + SECTION:=net + CATEGORY:=Network + TITLE:=Control utility for any kind of mobile broadband modem + URL:=https://www.freedesktop.org/wiki/Software/ModemManager + DEPENDS:= \ + $(INTL_DEPENDS) \ + +glib2 \ + +dbus \ + +ppp \ + +MODEMMANAGER_WITH_MBIM:libmbim \ + +MODEMMANAGER_WITH_QMI:libqmi +endef + +define Package/modemmanager/description + ModemManager is a D-Bus-activated service which allows controlling mobile + broadband modems. Add kernel modules for your modems as needed. + Select Utilities/usb-modeswitch if needed. +endef + +CONFIGURE_ARGS += \ + --without-polkit \ + --without-udev \ + --without-systemdsystemunitdir \ + --disable-rpath \ + --disable-gtk-doc + +ifeq ($(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),y) + CONFIGURE_ARGS += --with-at-command-via-dbus +endif + +ifdef CONFIG_MODEMMANAGER_WITH_MBIM + CONFIGURE_ARGS += --with-mbim +else + CONFIGURE_ARGS += --without-mbim +endif + +ifdef CONFIG_MODEMMANAGER_WITH_QMI + CONFIGURE_ARGS += --with-qmi +else + CONFIGURE_ARGS += --without-qmi +endif + +define Build/Prepare + $(call Build/Prepare/Default) + ( cd "$(PKG_BUILD_DIR)"; \ + printf "all:\ninstall:\n" >po/Makefile.in.in; \ + ) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/include/ModemManager/*.h $(1)/usr/include/ModemManager + $(INSTALL_DIR) $(1)/usr/include/libmm-glib + $(CP) $(PKG_INSTALL_DIR)/usr/include/libmm-glib/*.h $(1)/usr/include/libmm-glib + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so* $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ModemManager.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mm-glib.pc $(1)/usr/lib/pkgconfig +endef + +define Package/modemmanager/install + $(INSTALL_DIR) $(1)/lib/udev/rules.d + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/lib/udev/rules.d/*.rules $(1)/lib/udev/rules.d + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin + + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so.* $(1)/usr/lib + + $(INSTALL_DIR) $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager + + $(INSTALL_DIR) $(1)/etc/dbus-1/system.d + $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d + + $(INSTALL_DIR) $(1)/usr/share/dbus-1/system-services + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service $(1)/usr/share/dbus-1/system-services + + $(INSTALL_DIR) $(1)/usr/share/ModemManager + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager + $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager + + $(INSTALL_DIR) $(1)/etc/hotplug.d/usb + $(INSTALL_DATA) ./files/25-modemmanager-usb $(1)/etc/hotplug.d/usb + + $(INSTALL_DIR) $(1)/etc/hotplug.d/net + $(INSTALL_DATA) ./files/25-modemmanager-net $(1)/etc/hotplug.d/net + + $(INSTALL_DIR) $(1)/etc/hotplug.d/tty + $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty + + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh +endef + +$(eval $(call BuildPackage,modemmanager)) diff --git a/modemmanager/README.md b/modemmanager/README.md new file mode 100644 index 000000000..c9d880ea4 --- /dev/null +++ b/modemmanager/README.md @@ -0,0 +1,40 @@ +# OpenWrt ModemManager + +## Description + +Cellular modem control and connectivity + +Optional libraries libmbim and libqmi are available. +Your modem may require additional kernel modules and/or the usb-modeswitch +package. + +## Usage + +Once installed, you can configure the 2G/3G/4G modem connections directly in +/etc/config/network as in the following example: + + config interface 'broadband' + option device '/sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2.1' + option proto 'modemmanager' + option apn 'ac.vodafone.es' + option allowedauth 'pap chap' + option username 'vodafone' + option password 'vodafone' + option pincode '7423' + option iptype 'ipv4' + option lowpower '1' + option signalrate '30' + +Only 'device' and 'proto' are mandatory options, the remaining ones are all +optional. + +The 'allowedauth' option allows limiting the list of authentication protocols. +It is given as a space-separated list of values, including any of the +following: 'pap', 'chap', 'mschap', 'mschapv2' or 'eap'. It will default to +allowing all protocols. + +The 'iptype' option supports any of these values: 'ipv4', 'ipv6' or 'ipv4v6'. +It will default to 'ipv4' if not given. + +The 'signalrate' option set's the signal refresh rate (in seconds) for the device. +You can call signal info with command: mmcli -m 0 --signal-get diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/25-modemmanager-net new file mode 100644 index 000000000..e87231e31 --- /dev/null +++ b/modemmanager/files/25-modemmanager-net @@ -0,0 +1,31 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a interface name +[ -n "${INTERFACE}" ] || exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report network interface +mm_log "${ACTION} network interface ${INTERFACE}: event processed" +mm_report_event "${ACTION}" "${INTERFACE}" "net" "/sys${DEVPATH}" + +# Look for an associated cdc-wdm interface + +cdcwdm="" + +case "${ACTION}" in + "add") cdcwdm=$(mm_track_cdcwdm "${INTERFACE}") ;; + "remove") cdcwdm=$(mm_untrack_cdcwdm "${INTERFACE}") ;; +esac + +# Report cdc-wdm device, if any +[ -n "${cdcwdm}" ] && { + mm_log "${ACTION} cdc interface ${cdcwdm}: custom event processed" + mm_report_event "${ACTION}" "${cdcwdm}" "usbmisc" "/sys${DEVPATH}" +} diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/25-modemmanager-tty new file mode 100644 index 000000000..c13148a33 --- /dev/null +++ b/modemmanager/files/25-modemmanager-tty @@ -0,0 +1,16 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load hotplug common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a device name +[ -n "$DEVNAME" ] || exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report TTY +mm_log "${ACTION} serial interface ${DEVNAME}: event processed" +mm_report_event "${ACTION}" "${DEVNAME}" "tty" "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-usb b/modemmanager/files/25-modemmanager-usb new file mode 100644 index 000000000..93d0bf70a --- /dev/null +++ b/modemmanager/files/25-modemmanager-usb @@ -0,0 +1,13 @@ +#!/bin/sh +# Copyright (C) 2019 Aleksander Morgado + +# We need to process only full USB device removal events, we don't +# want to process specific interface removal events. +[ "$ACTION" = remove ] || exit +[ -z "${INTERFACE}" ] || exit + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +mm_clear_modem_wait_status "/sys${DEVPATH}" +mm_cleanup_interface_by_sysfspath "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common new file mode 100644 index 000000000..a25d32b68 --- /dev/null +++ b/modemmanager/files/modemmanager.common @@ -0,0 +1,332 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +################################################################################ + +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh + +################################################################################ +# Runtime state + +MODEMMANAGER_RUNDIR="/var/run/modemmanager" +MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid" +MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache" +MODEMMANAGER_SYSFS_CACHE="${MODEMMANAGER_RUNDIR}/sysfs.cache" +MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" + +################################################################################ +# Common logging + +mm_log() { + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && logger -t "ModemManager" "hotplug: $*" +} + +################################################################################ +# Receives as input argument the full sysfs path of the device +# Returns the physical device sysfs path +# +# NOTE: this method only works when the device exists, i.e. it cannot be used +# on removal hotplug events + +mm_find_physdev_sysfs_path() { + local tmp_path="$1" + + while true; do + tmp_path=$(dirname "${tmp_path}") + + # avoid infinite loops iterating + [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return + + # the physical device will be that with a idVendor and idProduct pair of files + [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { + tmp_path=$(readlink -f "$tmp_path") + echo "${tmp_path}" + return + } + done +} + +################################################################################ + +# Returns the cdc-wdm name retrieved from sysfs +mm_track_cdcwdm() { + local wwan="$1" + local cdcwdm + + cdcwdm=$(ls "/sys/class/net/${wwan}/device/usbmisc/") + [ -n "${cdcwdm}" ] || return + + # We have to cache it for later, as we won't be able to get the + # associated cdc-wdm device on a remove event + echo "${wwan} ${cdcwdm}" >> "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +# Returns the cdc-wdm name retrieved from the cache +mm_untrack_cdcwdm() { + local wwan="$1" + local cdcwdm + + # Look for the cached associated cdc-wdm device + [ -f "${MODEMMANAGER_CDCWDM_CACHE}" ] || return + + cdcwdm=$(awk -v wwan="${wwan}" '!/^#/ && $0 ~ wwan { print $2 }' "${MODEMMANAGER_CDCWDM_CACHE}") + [ -n "${cdcwdm}" ] || return + + # Remove from cache + sed -i "/${wwan} ${cdcwdm}/d" "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +################################################################################ +# ModemManager needs some time from the ports being added until a modem object +# is exposed in DBus. With the logic here we do an explicit wait of N seconds +# for ModemManager to expose the new modem object, making sure that the wait is +# unique per device (i.e. per physical device sysfs path). + +# Gets the modem wait status as retrieved from the cache +mm_get_modem_wait_status() { + local sysfspath="$1" + + # If no sysfs cache file, we're done + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return + + # Get status of the sysfs path + awk -v sysfspath="${sysfspath}" '!/^#/ && $0 ~ sysfspath { print $2 }' "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Clear the modem wait status from the cache, if any +mm_clear_modem_wait_status() { + local sysfspath="$1" + + local escaped_sysfspath + + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] && { + # escape '/', '\' and '&' for sed... + escaped_sysfspath=$(echo "$sysfspath" | sed -e 's/[\/&]/\\&/g') + sed -i "/${escaped_sysfspath}/d" "${MODEMMANAGER_SYSFS_CACHE}" + } +} + +# Sets the modem wait status in the cache +mm_set_modem_wait_status() { + local sysfspath="$1" + local status="$2" + + # Remove sysfs line before adding the new one with the new state + mm_clear_modem_wait_status "${sysfspath}" + + # Add the new status + echo "${sysfspath} ${status}" >> "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Callback for config_foreach() +mm_get_modem_config_foreach_cb() { + local cfg="$1" + local sysfspath="$2" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + local dev + dev=$(uci_get network "${cfg}" device) + [ "${dev}" = "${sysfspath}" ] || return 0 + + echo "${cfg}" +} + +# Returns the name of the interface configured for this device +mm_get_modem_config() { + local sysfspath="$1" + + # Look for configuration for the given sysfs path + config_load network + config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}" +} + +# Wait for a modem in the specified sysfspath +mm_wait_for_modem() { + local cfg="$1" + local sysfspath="$2" + + # TODO: config max wait + local n=45 + local step=5 + + while [ $n -ge 0 ]; do + [ -d "${sysfspath}" ] || { + mm_log "error: ignoring modem detection request: no device at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 1 + } + + # Check if the modem exists at the given sysfs path + if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 + then + mm_log "error: modem not detected at sysfs path" + else + mm_log "modem exported successfully at ${sysfspath}" + mm_log "setting interface '${cfg}' as available" + proto_set_available "${cfg}" 1 + return 0 + fi + + sleep $step + n=$((n-step)) + done + + mm_log "error: timed out waiting for the modem to get exported at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 2 +} + +mm_report_modem_wait() { + local sysfspath=$1 + + local parent_sysfspath status + + parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") + [ -n "${parent_sysfspath}" ] || { + mm_log "error: parent device sysfspath not found" + return + } + + status=$(mm_get_modem_wait_status "${parent_sysfspath}") + case "${status}" in + "") + local cfg + + cfg=$(mm_get_modem_config "${parent_sysfspath}") + if [ -n "${cfg}" ]; then + mm_log "interface '${cfg}' is set to configure device '${parent_sysfspath}'" + mm_log "now waiting for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "processed" + # Launch subshell for the explicit wait + ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & + else + mm_log "no need to wait for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "ignored" + fi + ;; + "processed") + mm_log "already waiting for modem at sysfs path ${parent_sysfspath}" + ;; + "ignored") + ;; + *) + mm_log "error: unknown status read for device at sysfs path ${parent_sysfspath}" + ;; + esac +} + +################################################################################ +# Cleanup interfaces + +mm_cleanup_interface_cb() { + local cfg="$1" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + proto_set_available "${cfg}" 0 +} + +mm_cleanup_interfaces() { + config_load network + config_foreach mm_cleanup_interface_cb interface +} + +mm_cleanup_interface_by_sysfspath() { + local dev="$1" + + local cfg + cfg=$(mm_get_modem_config "$dev") + [ -n "${cfg}" ] || return + + mm_log "setting interface '$cfg' as unavailable" + proto_set_available "${cfg}" 0 +} + +################################################################################ +# Event reporting + +# Receives as input the action, the device name and the subsystem +mm_report_event() { + local action="$1" + local name="$2" + local subsystem="$3" + local sysfspath="$4" + + # Track/untrack events in cache + case "${action}" in + "add") + # On add events, store event details in cache (if not exists yet) + grep -qs "${name},${subsystem}" "${MODEMMANAGER_EVENTS_CACHE}" || \ + echo "${action},${name},${subsystem},${sysfspath}" >> "${MODEMMANAGER_EVENTS_CACHE}" + ;; + "remove") + # On remove events, remove old events from cache (match by subsystem+name) + sed -i "/${name},${subsystem}/d" "${MODEMMANAGER_EVENTS_CACHE}" + ;; + esac + + # Report the event + mm_log "event reported: action=${action}, name=${name}, subsystem=${subsystem}" + mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 1>/dev/null 2>&1 & + + # Wait for added modem if a sysfspath is given + [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" +} + +mm_report_event_from_cache_line() { + local event_line="$1" + + local action name subsystem sysfspath + action=$(echo "${event_line}" | awk -F ',' '{ print $1 }') + name=$(echo "${event_line}" | awk -F ',' '{ print $2 }') + subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }') + sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }') + + mm_log "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" + mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}" +} + +mm_report_events_from_cache() { + # Remove the sysfs cache + rm -f "${MODEMMANAGER_SYSFS_CACHE}" + + local n=60 + local step=1 + local mmrunning=0 + + # Wait for ModemManager to be available in the bus + while [ $n -ge 0 ]; do + sleep $step + mm_log "checking if ModemManager is available..." + + if ! mmcli -L >/dev/null 2>&1 + then + mm_log "ModemManager not yet available" + else + mmrunning=1 + break + fi + n=$((n-step)) + done + + [ ${mmrunning} -eq 1 ] || { + mm_log "error: couldn't report initial kernel events: ModemManager not running" + return + } + + # Report cached kernel events + while IFS= read -r event_line; do + mm_report_event_from_cache_line "${event_line}" + done < ${MODEMMANAGER_EVENTS_CACHE} +} diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init new file mode 100755 index 000000000..b3f9f9290 --- /dev/null +++ b/modemmanager/files/modemmanager.init @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2016 Aleksander Morgado + +USE_PROCD=1 +START=70 + +stop_service() { + # Load common utils + . /usr/share/ModemManager/modemmanager.common + # Set all configured interfaces as unavailable + mm_cleanup_interfaces +} + +start_service() { + # Setup ModemManager service + # + # We will make sure that the rundir always exists, and we initially cleanup + # all interfaces flagging them as unavailable. + # + # The cached events processing will wait for MM to be available in DBus + # and will make sure all ports are re-notified to ModemManager every time + # it starts. + # + # All these commands need to be executed on every MM start, even after + # procd-triggered respawns, which is why they're all included as instance command + # + procd_open_instance + procd_set_param command sh -c ". /usr/share/ModemManager/modemmanager.common; \ + mkdir -m 0755 -p ${MODEMMANAGER_RUNDIR}; \ + mm_cleanup_interfaces; \ + ( mm_report_events_from_cache ) >/dev/null 2>&1 & \ + /usr/sbin/ModemManager" + procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" + procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" + procd_close_instance +} diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto new file mode 100755 index 000000000..2cce0b7c2 --- /dev/null +++ b/modemmanager/files/modemmanager.proto @@ -0,0 +1,554 @@ +#!/bin/sh +# Copyright (C) 2016-2019 Aleksander Morgado + +[ -x /usr/bin/mmcli ] || exit 0 +[ -x /usr/sbin/pppd ] || exit 0 + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + . ./ppp.sh + init_proto "$@" +} + +cdr2mask () +{ + # Number of args to shift, 255..255, first non-255 byte, zeroes + set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0 + if [ "$1" -gt 1 ] + then + shift "$1" + else + shift + fi + echo "${1-0}"."${2-0}"."${3-0}"."${4-0}" +} + +# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue +# The second argument must be exactly the name of the field to read +# +# Sample output: +# $ mmcli -m 0 -K +# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 +# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 +# modem.generic.manufacturer : Dell Inc. +# modem.generic.model : DW5821e Snapdragon X20 LTE +# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 +# modem.generic.carrier-configuration : GCF +# modem.generic.carrier-configuration-revision : 08E00009 +# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE +# .... +modemmanager_get_field() { + local list=$1 + local field=$2 + local value="" + + [ -z "${list}" ] || [ -z "${field}" ] && return + + # there is always at least a whitespace after each key, and we use that as part of the + # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result + # when grepping for 'modem.generic.state'. + line=$(echo "${list}" | grep "${field} ") + value=$(echo ${line#*:}) + + # not found? + [ -n "${value}" ] || return 2 + + # only print value if set + [ "${value}" != "--" ] && echo "${value}" + return 0 +} + +# build a comma-separated list of values from the list +modemmanager_get_multivalue_field() { + local list=$1 + local field=$2 + local value="" + local length idx item + + [ -z "${list}" ] || [ -z "${field}" ] && return + + length=$(modemmanager_get_field "${list}" "${field}.length") + [ -n "${length}" ] || return 0 + [ "$length" -ge 1 ] || return 0 + + idx=1 + while [ $idx -le "$length" ]; do + item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") + [ -n "${item}" ] && [ "${item}" != "--" ] && { + [ -n "${value}" ] && value="${value}, " + value="${value}${item}" + } + idx=$((idx + 1)) + done + + # nothing built? + [ -n "${value}" ] || return 2 + + # only print value if set + echo "${value}" + return 0 +} + +modemmanager_cleanup_connection() { + local modemstatus="$1" + + local bearercount idx bearerpath + + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + + # do nothing if no bearers reported + [ -n "${bearercount}" ] && [ "$bearercount" -ge 1 ] && { + # explicitly disconnect just in case + mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1 + # and remove all bearer objects, if any found + idx=1 + while [ $idx -le "$bearercount" ]; do + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[$idx\]") + mmcli --modem "${device}" --delete-bearer="${bearerpath}" >/dev/null 2>&1 + idx=$((idx + 1)) + done + } +} + +modemmanager_connected_method_ppp_ipv4() { + local interface="$1" + local ttyname="$2" + local username="$3" + local password="$4" + local allowedauth="$5" + + # all auth types are allowed unless a user given list is given + local authopts + local pap=1 + local chap=1 + local mschap=1 + local mschapv2=1 + local eap=1 + + [ -n "$allowedauth" ] && { + pap=0 chap=0 mschap=0 mschapv2=0 eap=0 + for auth in $allowedauth; do + case $auth in + "pap") pap=1 ;; + "chap") chap=1 ;; + "mschap") mschap=1 ;; + "mschapv2") mschapv2=1 ;; + "eap") eap=1 ;; + *) ;; + esac + done + } + + [ $pap -eq 1 ] || append authopts "refuse-pap" + [ $chap -eq 1 ] || append authopts "refuse-chap" + [ $mschap -eq 1 ] || append authopts "refuse-mschap" + [ $mschapv2 -eq 1 ] || append authopts "refuse-mschap-v2" + [ $eap -eq 1 ] || append authopts "refuse-eap" + + proto_run_command "${interface}" /usr/sbin/pppd \ + "${ttyname}" \ + 115200 \ + nodetach \ + noaccomp \ + nobsdcomp \ + nopcomp \ + novj \ + noauth \ + $authopts \ + ${username:+ user $username} \ + ${password:+ password $password} \ + lcp-echo-failure 5 \ + lcp-echo-interval 15 \ + lock \ + crtscts \ + nodefaultroute \ + usepeerdns \ + ipparam "${interface}" \ + ip-up-script /lib/netifd/ppp-up \ + ip-down-script /lib/netifd/ppp-down +} + +modemmanager_disconnected_method_ppp_ipv4() { + local interface="$1" + + echo "running disconnection (ppp method)" + + [ -n "${ERROR}" ] && { + local errorstring + errorstring=$(ppp_exitcode_tostring "${ERROR}") + case "$ERROR" in + 0) + ;; + 2) + proto_notify_error "$interface" "$errorstring" + proto_block_restart "$interface" + ;; + *) + proto_notify_error "$interface" "$errorstring" + ;; + esac + } || echo "pppd result code not given" + + proto_kill_command "$interface" +} + +modemmanager_connected_method_dhcp_ipv4() { + local interface="$1" + local wwan="$2" + local metric="$3" + local defaultroute="$4" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@${interface}" + json_add_string proto "dhcp" + proto_add_dynamic_defaults + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv4() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + local defaultroute="$10" + + local mask="" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + mask=$(cdr2mask "${prefix}") + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv4 address ${address}, netmask ${mask}" + proto_add_ipv4_address "${address}" "${mask}" + [ -n "${gateway}" ] && [ "${defaultroute}" != 0 ] && { + echo "adding default IPv4 route via ${gateway}" + proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_connected_method_dhcp_ipv6() { + local interface="$1" + local wwan="$2" + local metric="$3" + local defaultroute="$4" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@${interface}" + json_add_string proto "dhcpv6" + proto_add_dynamic_defaults + json_add_string extendprefix 1 # RFC 7278: Extend an IPv6 /64 Prefix to LAN + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv6() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + local defaultroute="$10" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv6 address ${address}, prefix ${prefix}" + proto_add_ipv6_address "${address}" "128" + proto_add_ipv6_prefix "${address}/${prefix}" + [ -n "${gateway}" ] && [ "$defaultroute" != 0 ] && { + echo "adding default IPv6 route via ${gateway}" + proto_add_ipv6_route "${gateway}" "128" + proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_disconnected_method_common() { + local interface="$1" + + echo "running disconnection (common)" + proto_notify_error "${interface}" MM_DISCONNECT_IN_PROGRESS + + proto_init_update "*" 0 + proto_send_update "${interface}" +} + +proto_modemmanager_init_config() { + available=1 + no_device=1 + proto_config_add_string device + proto_config_add_string apn + proto_config_add_string 'allowedauth:list(string)' + proto_config_add_string username + proto_config_add_string password + proto_config_add_string pincode + proto_config_add_string iptype + proto_config_add_int signalrate + proto_config_add_boolean lowpower + proto_config_add_defaults +} + +proto_modemmanager_setup() { + local interface="$1" + + local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface + local bearermethod_ipv4 bearermethod_ipv6 auth cliauth + local operatorname operatorid registration accesstech signalquality + + local device apn allowedauth username password pincode iptype metric signalrate + + local address prefix gateway mtu dns1 dns2 defaultroute + + json_get_vars device apn allowedauth username password pincode iptype metric signalrate defaultroute + + # validate sysfs path given in config + [ -n "${device}" ] || { + echo "No device specified" + proto_notify_error "${interface}" NO_DEVICE + proto_set_available "${interface}" 0 + return 1 + } + [ -e "${device}" ] || { + echo "Device not found in sysfs" + proto_set_available "${interface}" 0 + return 1 + } + + # validate that ModemManager is handling the modem at the sysfs path + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + modempath=$(modemmanager_get_field "${modemstatus}" "modem.dbus-path") + [ -n "${modempath}" ] || { + echo "Device not managed by ModemManager" + proto_notify_error "${interface}" DEVICE_NOT_MANAGED + proto_set_available "${interface}" 0 + return 1 + } + echo "modem available at ${modempath}" + + # always cleanup before attempting a new connection, just in case + modemmanager_cleanup_connection "${modemstatus}" + + # if allowedauth list given, build option string + for auth in $allowedauth; do + cliauth="${cliauth}${cliauth:+|}$auth" + done + + # setup connect args; APN mandatory (even if it may be empty) + echo "starting connection with apn '${apn}'..." + proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS + + connectargs="apn=${apn}${iptype:+,ip-type=${iptype}}${cliauth:+,allowed-auth=${cliauth}}${username:+,user=${username}}${password:+,password=${password}}${pincode:+,pin=${pincode}}" + mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { + proto_notify_error "${interface}" MM_CONNECT_FAILED + proto_block_restart "${interface}" + return 1 + } + + # check if Signal refresh rate is set + if [ -n "${signalrate}" ] && [ "${signalrate}" -eq "${signalrate}" ] 2>/dev/null; then + echo "setting signal refresh rate to ${signalrate} seconds" + mmcli --modem="${device}" --signal-setup="${signalrate}" + else + echo "signal refresh rate is not set" + fi + + # log additional useful information + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + operatorname=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-name") + [ -n "${operatorname}" ] && echo "network operator name: ${operatorname}" + operatorid=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-code") + [ -n "${operatorid}" ] && echo "network operator MCCMNC: ${operatorid}" + registration=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.registration-state") + [ -n "${registration}" ] && echo "registration type: ${registration}" + accesstech=$(modemmanager_get_multivalue_field "${modemstatus}" "modem.generic.access-technologies") + [ -n "${accesstech}" ] && echo "access technology: ${accesstech}" + signalquality=$(modemmanager_get_field "${modemstatus}" "modem.generic.signal-quality.value") + [ -n "${signalquality}" ] && echo "signal quality: ${signalquality}%" + + # we won't like it if there are more than one bearers, as that would mean the + # user manually created them, and that's unsupported by this proto + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + [ -n "${bearercount}" ] && [ "$bearercount" -eq 1 ] || { + proto_notify_error "${interface}" INVALID_BEARER_LIST + return 1 + } + + # load connected bearer information + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + + # load network interface and method information + beareriface=$(modemmanager_get_field "${bearerstatus}" "bearer.status.interface") + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + + # setup IPv4 + [ -n "${bearermethod_ipv4}" ] && { + echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}" + case "${bearermethod_ipv4}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" "${defaultroute}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" "${defaultroute}" + ;; + "ppp") + modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}" + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + # setup IPv6 + # note: if using ipv4v6, both IPv4 and IPv6 settings will have the same MTU and metric values reported + [ -n "${bearermethod_ipv6}" ] && { + echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}" + case "${bearermethod_ipv6}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" "${defaultroute}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" "${defaultroute}" + ;; + "ppp") + proto_notify_error "${interface}" "unsupported method" + return 1 + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + return 0 +} + +proto_modemmanager_teardown() { + local interface="$1" + + local modemstatus bearerpath errorstring + local bearermethod_ipv4 bearermethod_ipv6 + + local device lowpower iptype + json_get_vars device lowpower iptype + + echo "stopping network" + proto_notify_error "${interface}" MM_TEARDOWN_IN_PROGRESS + + # load connected bearer information, just the first one should be ok + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + [ -n "${bearerpath}" ] || { + echo "couldn't load bearer path" + return + } + + # load bearer connection methods + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + [ -n "${bearermethod_ipv4}" ] && + echo "IPv4 connection teardown required in interface ${interface}: ${bearermethod_ipv4}" + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + [ -n "${bearermethod_ipv6}" ] && + echo "IPv6 connection teardown required in interface ${interface}: ${bearermethod_ipv6}" + + # disconnection handling only requires special treatment in IPv4/PPP + [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}" + modemmanager_disconnected_method_common "${interface}" + + # disconnect + mmcli --modem="${device}" --simple-disconnect || + proto_notify_error "${interface}" DISCONNECT_FAILED + + # disable + mmcli --modem="${device}" --disable + proto_notify_error "${interface}" MM_MODEM_DISABLED + + # low power, only if requested + [ "${lowpower:-0}" -lt 1 ] || + mmcli --modem="${device}" --set-power-state-low +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol modemmanager +} diff --git a/netifd/Makefile b/netifd/Makefile new file mode 100644 index 000000000..4b5f110da --- /dev/null +++ b/netifd/Makefile @@ -0,0 +1,52 @@ +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-07-26 +PKG_SOURCE_VERSION:=440eb0647708274cc8d7d9e7c2bb0cfdfba90023 +PKG_MIRROR_HASH:=eed957036ab608fdc49bdf801fc5b4405fcd2a3a5e5d3343ec39898e156c10e9 +PKG_MAINTAINER:=Felix Fietkau + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_BUILD_PARALLEL:=1 + +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)) diff --git a/netifd/files/etc/hotplug.d/iface/00-netstate b/netifd/files/etc/hotplug.d/iface/00-netstate new file mode 100644 index 000000000..71ccb0191 --- /dev/null +++ b/netifd/files/etc/hotplug.d/iface/00-netstate @@ -0,0 +1,6 @@ +[ ifup = "$ACTION" ] && { + uci_toggle_state network "$INTERFACE" up 1 + [ -n "$DEVICE" ] && { + uci_toggle_state network "$INTERFACE" ifname "$DEVICE" + } +} diff --git a/netifd/files/etc/hotplug.d/net/20-smp-packet-steering b/netifd/files/etc/hotplug.d/net/20-smp-packet-steering new file mode 100644 index 000000000..8a86bf75f --- /dev/null +++ b/netifd/files/etc/hotplug.d/net/20-smp-packet-steering @@ -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 diff --git a/netifd/files/etc/init.d/network b/netifd/files/etc/init.d/network new file mode 100755 index 000000000..dc208c4ce --- /dev/null +++ b/netifd/files/etc/init.d/network @@ -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 +} diff --git a/netifd/files/etc/uci-defaults/14_migrate-dhcp-release b/netifd/files/etc/uci-defaults/14_migrate-dhcp-release new file mode 100644 index 000000000..f1b384eec --- /dev/null +++ b/netifd/files/etc/uci-defaults/14_migrate-dhcp-release @@ -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 diff --git a/netifd/files/etc/udhcpc.user b/netifd/files/etc/udhcpc.user new file mode 100644 index 000000000..78e2ba5f1 --- /dev/null +++ b/netifd/files/etc/udhcpc.user @@ -0,0 +1 @@ +# This script is sourced by udhcpc's dhcp.script at every DHCP event. diff --git a/netifd/files/lib/netifd/dhcp.script b/netifd/files/lib/netifd/dhcp.script new file mode 100755 index 000000000..278ffb04e --- /dev/null +++ b/netifd/files/lib/netifd/dhcp.script @@ -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" + [ "$DEFAULTROUTE" = 0 ] || 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 diff --git a/netifd/files/lib/netifd/proto/dhcp.sh b/netifd/files/lib/netifd/proto/dhcp.sh new file mode 100755 index 000000000..8db848260 --- /dev/null +++ b/netifd/files/lib/netifd/proto/dhcp.sh @@ -0,0 +1,89 @@ +#!/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 defaultroute + json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute defaultroute + + 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" + [ -n "$defaultroute" ] && proto_export "DEFAULTROUTE=$defaultroute" + [ "$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 diff --git a/netifd/files/lib/network/config.sh b/netifd/files/lib/network/config.sh new file mode 100755 index 000000000..4cd28e4ce --- /dev/null +++ b/netifd/files/lib/network/config.sh @@ -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" +} diff --git a/netifd/files/sbin/devstatus b/netifd/files/sbin/devstatus new file mode 100755 index 000000000..3c35b26a4 --- /dev/null +++ b/netifd/files/sbin/devstatus @@ -0,0 +1,12 @@ +#!/bin/sh +. /usr/share/libubox/jshn.sh +DEVICE="$1" + +[ -n "$DEVICE" ] || { + echo "Usage: $0 " + exit 1 +} + +json_init +json_add_string name "$DEVICE" +ubus call network.device status "$(json_dump)" diff --git a/netifd/files/sbin/ifdown b/netifd/files/sbin/ifdown new file mode 120000 index 000000000..a0e5c176a --- /dev/null +++ b/netifd/files/sbin/ifdown @@ -0,0 +1 @@ +ifup \ No newline at end of file diff --git a/netifd/files/sbin/ifstatus b/netifd/files/sbin/ifstatus new file mode 100755 index 000000000..8a951e6e1 --- /dev/null +++ b/netifd/files/sbin/ifstatus @@ -0,0 +1,13 @@ +#!/bin/sh +INTERFACE="$1" + +[ -n "$INTERFACE" ] || { + echo "Usage: $0 " + exit 1 +} + +ubus -S list "network.interface.$INTERFACE" >/dev/null || { + echo "Interface $INTERFACE not found" + exit 1 +} +ubus call network.interface status "{ \"interface\" : \"$INTERFACE\" }" diff --git a/netifd/files/sbin/ifup b/netifd/files/sbin/ifup new file mode 100755 index 000000000..15be535bb --- /dev/null +++ b/netifd/files/sbin/ifup @@ -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 diff --git a/netifd/files/usr/share/udhcpc/default.script b/netifd/files/usr/share/udhcpc/default.script new file mode 100755 index 000000000..0a9eb0180 --- /dev/null +++ b/netifd/files/usr/share/udhcpc/default.script @@ -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 From 232890376e942d1497e5ee7ceeb5e0572679f260 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 14 Jan 2022 09:02:46 +0100 Subject: [PATCH 0655/2059] Disable some SQM logs --- openmptcprouter/files/etc/uci-defaults/2040-omr-sqm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm index 1054b39b9..ace19d8a4 100755 --- a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm +++ b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm @@ -93,6 +93,8 @@ if [ "$(uci -q get sqm.omrvpn)" = "" ]; then EOF fi +sed -i 's/SQM_SYSLOG=1/SQM_SYSLOG=0/g' /etc/sqm/sqm.conf + rm -f /tmp/luci-indexcache exit 0 From 3ca89cfd4895656562d0e02c2e1fed9334d22665 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 14 Jan 2022 17:31:58 +0100 Subject: [PATCH 0656/2059] Update modemmanager --- modemmanager/Makefile | 8 +++-- modemmanager/files/25-modemmanager-wwan | 15 +++++++++ modemmanager/files/modemmanager.common | 11 ++++++- modemmanager/files/modemmanager.init | 10 +++--- .../files/usr/bin/ModemManager-wrapper | 33 +++++++++++++++++++ 5 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 modemmanager/files/25-modemmanager-wwan mode change 100755 => 100644 modemmanager/files/modemmanager.init create mode 100755 modemmanager/files/usr/bin/ModemManager-wrapper diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 19f94b01f..570bc9293 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_VERSION:=1.16.6 +PKG_VERSION:=1.18.2 PKG_RELEASE:=1 PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager -PKG_HASH:=2a90b6260f66d3135609d62667ada73416694d717e7fd9b73223e3703a499617 +PKG_HASH:=374be158ae1c1fb38a29eef1cc3cdf89ff3536b48ff1320d208ab204ea6c5f8a PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION) PKG_MAINTAINER:=Nicholas Smith @@ -98,6 +98,7 @@ define Package/modemmanager/install $(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/ModemManager-wrapper $(1)/usr/sbin $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin @@ -131,6 +132,9 @@ define Package/modemmanager/install $(INSTALL_DIR) $(1)/etc/hotplug.d/tty $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty + $(INSTALL_DIR) $(1)/etc/hotplug.d/wwan + $(INSTALL_DATA) ./files/25-modemmanager-wwan $(1)/etc/hotplug.d/wwan + $(INSTALL_DIR) $(1)/lib/netifd/proto $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh endef diff --git a/modemmanager/files/25-modemmanager-wwan b/modemmanager/files/25-modemmanager-wwan new file mode 100644 index 000000000..c4dc6b897 --- /dev/null +++ b/modemmanager/files/25-modemmanager-wwan @@ -0,0 +1,15 @@ +#!/bin/sh +# Copyright (C) 2021 Aleksander Morgado + +# Load hotplug common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a device name +[ -n "$DEVNAME" ] || exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report wwan +mm_log "${ACTION} wwan control port ${DEVNAME}: event processed" +mm_report_event "${ACTION}" "${DEVNAME}" "wwan" "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common index a25d32b68..a439179de 100644 --- a/modemmanager/files/modemmanager.common +++ b/modemmanager/files/modemmanager.common @@ -39,12 +39,21 @@ mm_find_physdev_sysfs_path() { # avoid infinite loops iterating [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return - # the physical device will be that with a idVendor and idProduct pair of files + # for USB devices, the physical device will be that with a idVendor + # and idProduct pair of files [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { tmp_path=$(readlink -f "$tmp_path") echo "${tmp_path}" return } + + # For PCI devices, the physical device will be that with a vendor + # and device pair of files + [ -f "${tmp_path}"/vendor ] && [ -f "${tmp_path}"/device ] && { + tmp_path=$(readlink -f "$tmp_path") + echo "${tmp_path}" + return + } done } diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init old mode 100755 new mode 100644 index b3f9f9290..a3f6c1b12 --- a/modemmanager/files/modemmanager.init +++ b/modemmanager/files/modemmanager.init @@ -22,14 +22,12 @@ start_service() { # it starts. # # All these commands need to be executed on every MM start, even after - # procd-triggered respawns, which is why they're all included as instance command + # procd-triggered respawns, which is why this is wrapped in a startup + # wrapper script called '/usr/sbin/ModemManager-wrapper'. # + . /usr/share/ModemManager/modemmanager.common procd_open_instance - procd_set_param command sh -c ". /usr/share/ModemManager/modemmanager.common; \ - mkdir -m 0755 -p ${MODEMMANAGER_RUNDIR}; \ - mm_cleanup_interfaces; \ - ( mm_report_events_from_cache ) >/dev/null 2>&1 & \ - /usr/sbin/ModemManager" + procd_set_param command /usr/sbin/ModemManager-wrapper procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" procd_close_instance diff --git a/modemmanager/files/usr/bin/ModemManager-wrapper b/modemmanager/files/usr/bin/ModemManager-wrapper new file mode 100755 index 000000000..4fd64227f --- /dev/null +++ b/modemmanager/files/usr/bin/ModemManager-wrapper @@ -0,0 +1,33 @@ +#!/bin/sh + +trap_with_arg() { + func="$1" ; shift + for sig ; do + # shellcheck disable=SC2064 + trap "$func $sig" "$sig" + done +} + +func_trap() { + logger "ModemManager-wrapper[$$]" "Sending signal ${1}..." + kill "-${1}" "$CHILD" 2>/dev/null +} + +main() { + . /usr/share/ModemManager/modemmanager.common + + trap_with_arg func_trap INT TERM KILL + + mkdir -p "${MODEMMANAGER_RUNDIR}" + chmod 0755 "${MODEMMANAGER_RUNDIR}" + mm_cleanup_interfaces + + /usr/sbin/ModemManager "$@" 1>/dev/null 2>/dev/null & + CHILD="$!" + + mm_report_events_from_cache + + wait "$CHILD" +} + +main "$@" From 9a01c5a68f1399b9ff606cb485bf30713d219b62 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 15 Jan 2022 09:00:04 +0100 Subject: [PATCH 0657/2059] Fix modemmanager package --- modemmanager/files/usr/{bin => sbin}/ModemManager-wrapper | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modemmanager/files/usr/{bin => sbin}/ModemManager-wrapper (100%) diff --git a/modemmanager/files/usr/bin/ModemManager-wrapper b/modemmanager/files/usr/sbin/ModemManager-wrapper similarity index 100% rename from modemmanager/files/usr/bin/ModemManager-wrapper rename to modemmanager/files/usr/sbin/ModemManager-wrapper From 03c20f58c6f73e6630c6509fbfa5385972802cce Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 15 Jan 2022 09:00:24 +0100 Subject: [PATCH 0658/2059] Check if a server exist --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index b54139b8c..145349b29 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1541,7 +1541,7 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter fi -if [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then _log "Set firewall on server" /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 From 5816d407a581da70d7e6e464af5e602153462df5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 16 Jan 2022 17:21:50 +0100 Subject: [PATCH 0659/2059] Add modemmanager dependencies --- libmbim/Makefile | 95 +++++++++++++++++++++++++++++++++++++ libqmi/Config.in | 16 +++++++ libqmi/Makefile | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 libmbim/Makefile create mode 100644 libqmi/Config.in create mode 100644 libqmi/Makefile diff --git a/libmbim/Makefile b/libmbim/Makefile new file mode 100644 index 000000000..32c8ef493 --- /dev/null +++ b/libmbim/Makefile @@ -0,0 +1,95 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libmbim +PKG_VERSION:=1.26.0 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://www.freedesktop.org/software/libmbim +PKG_HASH:=1e1f0926b22c77210442129eca689722ecf324ab9c9abf421a5c989f46e813cf + +PKG_MAINTAINER:=Nicholas Smith + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +CONFIGURE_ARGS += \ + --disable-static \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf \ + --disable-silent-rules \ + --enable-more-warnings=yes + +define Package/libmbim + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:=+glib2 + TITLE:=Helper library and utils to talk to MBIM enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libmbim + LICENSE:=LGPL-2.0-or-later + LICENSE_FILES:=COPYING.LIB +endef + +define Package/libmbim/description + Helper library to talk to MBIM enabled modems. + Add mbim-utils for extra utilities. +endef + +define Package/mbim-utils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libmbim + TITLE:=Utilities to talk to MBIM enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libmbim + LICENSE:=GPL-2.0-or-later + LICENSE_FILES:=COPYING +endef + +CONFIGURE_ARGS += \ + --without-udev \ + --without-udev-base-dir + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) \ + $(PKG_INSTALL_DIR)/usr/include/libmbim-glib \ + $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so* \ + $(1)/usr/lib/ + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mbim-glib.pc \ + $(1)/usr/lib/pkgconfig +endef + +define Package/libmbim/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so.* \ + $(1)/usr/lib/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/mbim-proxy $(1)/usr/lib/ +endef + +define Package/mbim-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbimcli $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbim-network $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,libmbim)) +$(eval $(call BuildPackage,mbim-utils)) diff --git a/libqmi/Config.in b/libqmi/Config.in new file mode 100644 index 000000000..6f35b7453 --- /dev/null +++ b/libqmi/Config.in @@ -0,0 +1,16 @@ +menu "Configuration" + depends on PACKAGE_libqmi + +config LIBQMI_WITH_MBIM_QMUX + bool "Include MBIM QMUX service support" + default y + help + Compile libqmi with QMI-over-MBIM support + +config LIBQMI_WITH_QRTR_GLIB + bool "Include QRTR support" + default y + help + Compile libqmi with QRTR support + +endmenu diff --git a/libqmi/Makefile b/libqmi/Makefile new file mode 100644 index 000000000..ee5b69749 --- /dev/null +++ b/libqmi/Makefile @@ -0,0 +1,119 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libqmi +PKG_VERSION:=1.30.2 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://www.freedesktop.org/software/libqmi +PKG_HASH:=be01ece0ea2c2194cbea5744bf5aaf06c04ba5fb7ec7887a13116c76d114fedd + +PKG_MAINTAINER:=Nicholas Smith + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/libqmi/config + source "$(SOURCE)/Config.in" +endef + +define Package/libqmi + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:= \ + +glib2 \ + +LIBQMI_WITH_MBIM_QMUX:libmbim \ + +LIBQMI_WITH_QRTR_GLIB:libqrtr-glib + TITLE:=Helper library to talk to QMI enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libqmi + LICENSE:=LGPL-2.0-or-later + LICENSE_FILES:=COPYING.LIB +endef + +define Package/libqmi/description + Helper library talk to QMI enabled modems. + Add qmi-utils for extra utilities. +endef + +define Package/qmi-utils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libqmi + TITLE:=Utilities to talk to QMI enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libqmi + LICENSE:=GPL-2.0-or-later + LICENSE_FILES:=COPYING +endef + +define Package/libqmi-utils/description + Utils to talk to QMI enabled modems +endef + +CONFIGURE_ARGS += \ + --disable-static \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf \ + --disable-silent-rules \ + --enable-firmware-update \ + --enable-more-warnings=yes \ + --without-udev \ + --without-udev-base-dir + +ifeq ($(CONFIG_LIBQMI_WITH_MBIM_QMUX),y) + CONFIGURE_ARGS += --enable-mbim-qmux +else + CONFIGURE_ARGS += --disable-mbim-qmux +endif + +ifeq ($(CONFIG_LIBQMI_WITH_QRTR_GLIB),y) + CONFIGURE_ARGS += --enable-qrtr +else + CONFIGURE_ARGS += --disable-qrtr +endif + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) \ + $(PKG_INSTALL_DIR)/usr/include/libqmi-glib \ + $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so* \ + $(1)/usr/lib/ + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/qmi-glib.pc \ + $(1)/usr/lib/pkgconfig +endef + +define Package/libqmi/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so.* \ + $(1)/usr/lib/ + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/qmi-proxy $(1)/usr/lib/ +endef + +define Package/qmi-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmicli $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-network $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-firmware-update $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,libqmi)) +$(eval $(call BuildPackage,qmi-utils)) From 68ed55b7ed76a57e55b5490183302a47925bed36 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 18 Jan 2022 12:15:27 +0100 Subject: [PATCH 0660/2059] Fix DHCP --- netifd/files/lib/netifd/dhcp.script | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/netifd/files/lib/netifd/dhcp.script b/netifd/files/lib/netifd/dhcp.script index 278ffb04e..c857c9fc0 100755 --- a/netifd/files/lib/netifd/dhcp.script +++ b/netifd/files/lib/netifd/dhcp.script @@ -27,7 +27,8 @@ setup_interface() { eval "$(ipcalc.sh "$i/$mask")";gw_net="$NETWORK" [ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip" - [ "$DEFAULTROUTE" = 0 ] || proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" + #[ "$DEFAULTROUTE" = 0 ] || proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" + proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" local r for r in $CUSTOMROUTES; do From be962ec5e7ee453c03d65fb747f02457c605674e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 Jan 2022 20:11:09 +0100 Subject: [PATCH 0661/2059] Don't set master as default gateway here --- mptcp/files/etc/init.d/mptcp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index ac2b7496d..e9c128343 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -267,10 +267,10 @@ interface_multipath_settings() { #config_get mode "$config" multipath "" #[ "$mode" = "" ] && mode="$(uci -q get openmptcprouter.${config}.multipath)" - [ "$mode" = "master" ] && { - #echo "ip route replace default via $gateway dev $iface" - ip route replace default via $gateway dev $iface 2>&1 >/dev/null - } + #[ "$mode" = "master" ] && { + # #echo "ip route replace default via $gateway dev $iface" + # ip route replace default via $gateway dev $iface 2>&1 >/dev/null + #} if [ "$txqueuelen" != "" ]; then ifconfig $iface txqueuelen $txqueuelen > /dev/null 2>&1 else @@ -350,9 +350,9 @@ interface_multipath_settings() { fi #config_get mode "$config" multipath "off" - [ "$mode" = "master" ] && { - ip -6 route replace default via $gateway6 dev $iface 2>&1 >/dev/null - } + #[ "$mode" = "master" ] && { + # ip -6 route replace default via $gateway6 dev $iface 2>&1 >/dev/null + #} #[ "$mode" = "off" ] && { # ifconfig $iface txqueuelen 50 > /dev/null 2>&1 #} || { @@ -490,6 +490,10 @@ start_service() { [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep raspberry)" ] && [ -z "$(ubus call system board | jsonfilter -e '@.board_name' | grep '4-model-b')" ] && { ethtool --offload eth0 rx off tx off > /dev/null 2>&1 } + [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep -i r2s)" ] && { + ethtool -K eth0 rx off tx off > /dev/null 2>&1 + ethtool -K eth1 rx off tx off > /dev/null 2>&1 + } } reload_service() { From d2e7ac01764c024753490af68e7206336ba1a936 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 Jan 2022 20:21:43 +0100 Subject: [PATCH 0662/2059] Add some log to modemmanager --- modemmanager/files/modemmanager.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto index 2cce0b7c2..0e050e7b9 100755 --- a/modemmanager/files/modemmanager.proto +++ b/modemmanager/files/modemmanager.proto @@ -246,6 +246,7 @@ modemmanager_connected_method_static_ipv4() { proto_add_ipv4_address "${address}" "${mask}" [ -n "${gateway}" ] && [ "${defaultroute}" != 0 ] && { echo "adding default IPv4 route via ${gateway}" + logger -t "modemmanager.proto" "adding default IPv4 route via ${gateway} ${address}" proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" } [ -n "${dns1}" ] && { From cc4512766e21f2e40168dabc15116f3c50feabc6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 Jan 2022 20:22:16 +0100 Subject: [PATCH 0663/2059] Fix workaround for some 2.5G card --- openmptcprouter/files/etc/hotplug.d/iface/00-nego | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/hotplug.d/iface/00-nego b/openmptcprouter/files/etc/hotplug.d/iface/00-nego index 67e62dcec..9ad0cb927 100644 --- a/openmptcprouter/files/etc/hotplug.d/iface/00-nego +++ b/openmptcprouter/files/etc/hotplug.d/iface/00-nego @@ -1,3 +1,3 @@ #!/bin/sh # Needed for some device, like rtl8156 2.5G USB adapter -[ "$ACTION" = "ifup" ] && [ -n "$DEVICE" ] && [ -n "$(lsusb | grep 8156)" ] [ -n "$(ethtool $DEVICE | grep 2500)" ] && ethtool -s $DEVICE autoneg on \ No newline at end of file +[ "$ACTION" = "ifup" ] && [ -n "$DEVICE" ] && ([ -n "$(lsusb | grep 8156)" ] || [ -n "$(ethtool $DEVICE | grep 2500)" ]) && ethtool -s $DEVICE autoneg on \ No newline at end of file From 098a498124346ec734cdb2109d6b4d0db07a5382 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 27 Jan 2022 21:02:09 +0100 Subject: [PATCH 0664/2059] Fix and MPTCP config reload when public ip change --- .../share/omr/post-tracking.d/post-tracking | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 145349b29..c96828632 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1182,7 +1182,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( if [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ]; then #local asn="$(wget -4 -qO- -T 4 http://api.iptoasn.com/v1/as/ip/$ipaddr | jsonfilter -q -e '@.as_description')" #[ -z "$asn" ] && { - local asn="$(whois $ipaddr 2>/dev/null | grep -m 1 -i 'netname' | awk '{print $2}')" + local asn="$(timeout 2 whois $ipaddr 2>/dev/null | grep -m 1 -i 'netname' | awk '{print $2}')" #} fi [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE)" ] && { @@ -1197,9 +1197,16 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( uci -q set openmptcprouter.latest_versions.lc=$(date +"%s") } fi - [ -n "$ipaddr" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ipaddr" + [ -n "$ipaddr" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.publicip)" != "$ipaddr" ] && { + _log "New public ip detected for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE): $ipaddr" + /etc/init.d/mptcp enabled && { + _log "Reload MPTCP for $OMR_TRACKER_DEVICE" + /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" >/dev/null + } + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ipaddr" + } [ -n "$OMR_TRACKER_LATENCY" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" - [ -n "$asn" ] && { + [ -n "$asn" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.asn)" != "$asn" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.asn="$asn" } @@ -1291,7 +1298,14 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( uci -q set openmptcprouter.latest_versions.lc=$(date +"%s") } fi - [ -n "$ipaddr" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip6="$ip6addr" + [ -n "$ip6addr" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.publicip)" != "$ip6addr" ] && { + _log "New public ip detected for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE): $ip6addr" + /etc/init.d/mptcp enabled && { + _log "Reload MPTCP for $OMR_TRACKER_DEVICE" + /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" >/dev/null + } + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ip6addr" + } [ -n "$OMR_TRACKER_LATENCY" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" [ -n "$asn" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.asn="$asn" From a241e1e9c91645795628595d829c479309250335 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 Jan 2022 10:43:33 +0100 Subject: [PATCH 0665/2059] Set script executable --- luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename diff --git a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename old mode 100644 new mode 100755 From 536eadc629a3c3aea684cda8af2a61e5e670847f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 Jan 2022 10:44:19 +0100 Subject: [PATCH 0666/2059] add command to remove some log for modemmanager when using upstream version --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index dd68fb82c..92e9a5fd3 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -31,4 +31,6 @@ fi EOF } +#sed -i 's/^\tlogger -t/\t[ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] \&\& logger -t/g' /usr/share/ModemManager/modemmanager.common + exit 0 \ No newline at end of file From e74f092816c85d95f41dc5e5afb92357b3e61569 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 29 Jan 2022 16:58:52 +0100 Subject: [PATCH 0667/2059] Add mptcpd as default package --- openmptcprouter-full/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index f6e533057..f8b0b483d 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -81,7 +81,8 @@ MY_DEPENDS := \ luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ - luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic + luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ + mptcpd # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status # luci-proto-bonding luci-app-statistics luci-proto-gre # softethervpn5-client softethervpn5-server luci-app-nginx-ha From fb32c87a746e12de6ec9a1126722479ba81f3267 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Feb 2022 19:57:59 +0100 Subject: [PATCH 0668/2059] Fix ipv6 error --- mptcp/files/etc/init.d/mptcp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 312a1839f..1ccb1f314 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -291,8 +291,10 @@ interface_multipath_settings() { network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ -z "$ip6addr" ] || [ -z "$network6" ]; then - ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") - gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") + [ -z "$ip6addr" ] && network_get_ipaddr6 ip6addr $config + [ -z "$ip6addr" ] && ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") + [ -z "$gateway6" ] && network_get_gateway6 gateway6 $config true + [ -z "$gateway6" ] && gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") [ -z "$gateway6" ] && gateway6=$(uci -q get "network.$config.ip6gw") [ -z "$gateway6" ] && gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then @@ -302,7 +304,7 @@ interface_multipath_settings() { gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi netmask6=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") - network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ip6addr" ] && network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null From a12f74df7f13717f22bdbe9239dc81ad2b243a54 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Feb 2022 20:24:00 +0100 Subject: [PATCH 0669/2059] Fix MPTCP for 5.15 --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 1ccb1f314..0516f773e 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -44,7 +44,7 @@ global_multipath_settings() { [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qew /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qew /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" [ -z "$mptcp_rr_num_segments" ] || sysctl -qew /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" - else + elif [ -f /proc/sys/net/mptcp/enabled ]; then sysctl -qew net.mptcp.enabled="$multipath_status" ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null [ -z "$mptcp_add_addr_timeout" ] || sysctl -qew net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" From 5a64d743d1c4c15e30e2bf46f03def4dcf70e604 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Feb 2022 20:31:31 +0100 Subject: [PATCH 0670/2059] Fix DNS config --- openmptcprouter/files/etc/uci-defaults/1940-omr-dns | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index 2d4e3cbd9..ecb75b2f5 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -42,7 +42,7 @@ if [ "$(uci -q get dhcp.lan.dhcp_options)" = "" ]; then EOF fi -if [ -n "$(uci -q dhcp.@dnsmasq[0].server | grep 127.0.0.1)" ] && [ -z "$(uci -q dhcp.@dnsmasq[0].server | grep 127.0.0.1#5353)" ]; then +if [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep 127.0.0.1)" ] && [ -z "$(uci -q get dhcp.@dnsmasq[0].server | grep 127.0.0.1#5353)" ]; then /etc/init.d/https-dns-proxy start /etc/init.d/https-dns-proxy enable else @@ -59,7 +59,7 @@ fi # commit unbound #EOF -if [ -z "$(uci -q unbound.auth_icann)" ]; then +if [ -z "$(uci -q show unbound.auth_icann)" ]; then uci -q batch <<-EOF >/dev/null set unbound.auth_icann=zone set unbound.auth_icann.fallback='1' From 4c0649109d7515755837897ad9d97fa4643c9277 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Feb 2022 21:27:45 +0100 Subject: [PATCH 0671/2059] Fix MPTCP display --- luci-app-mptcp/luasrc/controller/mptcp.lua | 12 +----------- mptcp/files/usr/bin/multipath | 10 ++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index c81458f80..842adc6ef 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -209,7 +209,7 @@ end function mptcp_monitor_data() luci.http.prepare_content("text/plain") local fullmesh - fullmesh = io.popen("cat /proc/net/mptcp_net/snmp") + fullmesh = io.popen("multipath -m") if fullmesh:read() ~= nil then while true do local ln = fullmesh:read("*l") @@ -217,16 +217,6 @@ function mptcp_monitor_data() luci.http.write(ln) luci.http.write("\n") end - else - fullmesh = io.popen("nstat -z") - if fullmesh then - while true do - local ln = fullmesh:read("*l") - if not ln then break end - luci.http.write(ln) - luci.http.write("\n") - end - end end return end diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 62e029da5..42bb1ddff 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -29,6 +29,7 @@ case $1 in echo "show established conections: -c" echo "show fullmesh info: -f" echo "show kernel config: -k" + echo "show MPTCP info: -m" echo echo "Flag on the device, to enable/disable MPTCP for this interface. The backup-flag" echo "will allow a subflow to be established across this interface, but only be used" @@ -75,6 +76,13 @@ case $1 in fi echo exit 0 ;; + "-m") + if [ -f /proc/net/mptcp_net/snmp ]; then + cat /proc/net/mptcp_net/snmp + else + nstat -z | grep -i mptcp + fi + exit 0 ;; "") for ifpath in /sys/class/net/*; do $0 ${ifpath##*/} @@ -126,6 +134,8 @@ else ID=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $3}') IFF=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $4}') IP=$(ifconfig $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') + RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') + [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null case $TYPE in "off") [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null From 779ad66f3c958d46b32588310fda23bbb04538fb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 3 Feb 2022 19:54:39 +0100 Subject: [PATCH 0672/2059] Add missing var --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 0516f773e..d7646364d 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -10,7 +10,7 @@ USE_PROCD=1 . /lib/functions/network.sh global_multipath_settings() { - local multipath mptcp_path_manager mptcp_schdeduler mptcp_debug congestion mptcp_checksum mptcp_syn_retries mptcp_fullmesh_num_subflows mptcp_fullmesh_create_on_err mptcp_ndiffports_num_subflows mptcp_rr_cwnd_limited mptcp_rr_num_segments + local multipath mptcp_path_manager mptcp_scheduler mptcp_subflows mptcp_debug mptcp_add_addr_accepted congestion mptcp_checksum mptcp_syn_retries mptcp_fullmesh_num_subflows mptcp_fullmesh_create_on_err mptcp_ndiffports_num_subflows mptcp_rr_cwnd_limited mptcp_rr_num_segments local multipath_status=0 config_load network config_get multipath globals multipath From 2597f7783b5464a6724d6ecde1c6930c5eff1c5c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 3 Feb 2022 19:55:31 +0100 Subject: [PATCH 0673/2059] Remove new line for ping --- openmptcprouter/files/bin/omr-test-speed | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 15666e1e9..618da96fe 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -20,9 +20,9 @@ if [ "$HETZNER" = false ]; then for pinghost in $HOSTLST; do domain=$(echo $pinghost | awk -F/ '{print $3}') if [ -z "$INTERFACE" ]; then - ping=$(ping -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1) + ping=$(ping -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') else - ping=$(ping -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1) + ping=$(ping -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') fi echo "host: $domain - ping: $ping" if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then From 58fcea225faec0849f486e9912df2a23090346b3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Feb 2022 20:44:41 +0100 Subject: [PATCH 0674/2059] More anonymous config --- luci-app-openmptcprouter/root/bin/anonymous_config.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-openmptcprouter/root/bin/anonymous_config.sh b/luci-app-openmptcprouter/root/bin/anonymous_config.sh index 674d01726..65c0813a2 100755 --- a/luci-app-openmptcprouter/root/bin/anonymous_config.sh +++ b/luci-app-openmptcprouter/root/bin/anonymous_config.sh @@ -21,5 +21,6 @@ uci show | \ -e "/vpn\.key=/s/......$/xxxxxx'/" \ -e "/vps\.key=/s/......$/xxxxxx'/" \ -e "/wgkey=/s/......$/xxxxxx'/" \ + -e "/key=/s/......$/xxxxxx'/" \ -e "/ula_prefix=2/s/=.........../='xxxxxxxxxxx/" \ -e "/token=/s/............$/xxxxxx'/" \ No newline at end of file From e0ec6cbd3d8cd6df29d8fd10ce14fd7378f22e89 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Feb 2022 20:45:15 +0100 Subject: [PATCH 0675/2059] More server for speed test --- openmptcprouter/files/bin/omr-test-speed | 40 ++++++++++------------ openmptcprouter/files/bin/omr-test-speedv6 | 39 ++++++++++----------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 618da96fe..71bc4d75c 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -1,9 +1,9 @@ #!/bin/sh # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : -HETZNER=false -if [ "$1" = "hetzner" ]; then - HETZNER=true +FORCEVPS=false +if [ "$1" = "forcevps" ]; then INTERFACE="$2" + FORCEVPS=true else INTERFACE="$1" fi @@ -13,24 +13,22 @@ fi exit 0 } -if [ "$HETZNER" = false ]; then - echo "Select best test server..." - HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" - bestping="9999" - for pinghost in $HOSTLST; do - domain=$(echo $pinghost | awk -F/ '{print $3}') - if [ -z "$INTERFACE" ]; then - ping=$(ping -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') - else - ping=$(ping -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') - fi - echo "host: $domain - ping: $ping" - if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then - bestping=$ping - HOST=$pinghost - fi - done -fi +echo "Select best test server..." +HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" +bestping="9999" +for pinghost in $HOSTLST; do + domain=$(echo $pinghost | awk -F/ '{print $3}') + if [ -z "$INTERFACE" ] || [ "$FORCEVPS" = true ]; then + ping=$(ping -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + else + ping=$(ping -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + fi + echo "host: $domain - ping: $ping" + if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then + bestping=$ping + HOST=$pinghost + fi +done [ -z "$HOST" ] && HOST="https://speed.hetzner.de/10GB.bin" diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index 3db10fee9..32269f215 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -1,8 +1,8 @@ #!/bin/sh # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : -HETZNER=false -if [ "$1" = "hetzner" ]; then - HETZNER=true +FORCEVPS=false +if [ "$1" = "forcevps" ]; then + FORCEVPS=true INTERFACE="$2" else INTERFACE="$1" @@ -14,23 +14,22 @@ fi } -if [ "$HETZNER" = false ]; then - echo "Select best test server..." - HOSTLST="http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://speedtest.tele2.net/1000GB.zip https://speed.hetzner.de/10GB.bin http://ipv6.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" - bestping="9999" - for pinghost in $HOSTLST; do - domain=$(echo $pinghost | awk -F/ '{print $3}') - if [ -z "$INTERFACE" ]; then - ping=$(ping -6 -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1) - else - ping=$(ping -6 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1) - fi - echo "host: $domain - ping: $ping" - if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then - bestping=$ping - HOST=$pinghost - fi - done +echo "Select best test server..." +HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv6.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" +bestping="9999" +for pinghost in $HOSTLST; do + domain=$(echo $pinghost | awk -F/ '{print $3}') + if [ -z "$INTERFACE" ] || [ "$FORCEVPS" = true ]; then + ping=$(ping -6 -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1) + else + ping=$(ping -6 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1) + fi + echo "host: $domain - ping: $ping" + if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then + bestping=$ping + HOST=$pinghost + fi +done fi [ -z "$HOST" ] && HOST="https://speed.hetzner.de/10GB.bin" From 0b7ee45a1a944040f361b933f2abfa70a350582f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Feb 2022 22:25:38 +0100 Subject: [PATCH 0676/2059] Force token reset if not working on status --- .../root/usr/libexec/rpcd/openmptcprouter | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index e42883f1a..9c9ab517b 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -931,6 +931,11 @@ function interfaces_status() else mArray.openmptcprouter["vps_admin"] = false mArray.openmptcprouter["vps_admin_error_msg"] = "No result" + uci:set("openmptcprouter",s[".name"],"admin_error","1") + mArray.openmptcprouter["vps_admin_error"] = true + uci:delete("openmptcprouter",s[".name"],"token") + uci:save("openmptcprouter",s[".name"]) + uci:commit("openmptcprouter",s[".name"]) end else mArray.openmptcprouter["vps_admin"] = false From fa07ce7e73d938b1dba1e14d002c8fda502fac9d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Feb 2022 22:26:10 +0100 Subject: [PATCH 0677/2059] Use speedtestc++ instead of speedtestc --- openmptcprouter-full/Makefile | 2 +- speedtestcpp/Makefile | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 speedtestcpp/Makefile diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index f8b0b483d..e759dc5ee 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -46,7 +46,7 @@ MY_DEPENDS := \ luci-app-openvpn \ shadowsocks-libev-ss-server shadowsocks-libev-ss-tunnel \ omr-6in4 ip6tables-mod-nat luci-proto-ipv6 6to4 6in4 6rd ip6tables \ - speedtestc \ + speedtestcpp \ iftop \ htop \ nano \ diff --git a/speedtestcpp/Makefile b/speedtestcpp/Makefile new file mode 100644 index 000000000..db25f5bb8 --- /dev/null +++ b/speedtestcpp/Makefile @@ -0,0 +1,42 @@ +# +# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter project +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=speedtestcpp +PKG_VERSION:=1.12 +PKG_RELEASE:=2 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=a01ae6eb04c5d3f4847aef73bf77849275ccc6eb +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/fmantz/SpeedTest.git + +PKG_MAINTAINER:=Ycarus +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE + +CMAKE_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/speedtestcpp + SECTION:=net + CATEGORY:=Network + TITLE:=Yet another unofficial speedtest.net client cli interface + URL:=https://github.com/fmantz/SpeedTest + DEPENDS:=+curl +libstdcpp +libopenssl +libxml2 +endef + +define Package/speedtestcpp/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/SpeedTest $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/speedtestJson $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,speedtestcpp)) \ No newline at end of file From 6a0fa5b88c666a230cc043a7e405df40a7767d21 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 7 Feb 2022 22:11:52 +0100 Subject: [PATCH 0678/2059] Use latest iproute2 package for MPTCP upstream --- iproute2/Makefile | 246 ++++++++++++++++++ iproute2/patches/100-configure.patch | 12 + iproute2/patches/110-darwin_fixes.patch | 59 +++++ .../patches/115-add-config-xtlibdir.patch | 12 + .../120-no_arpd_ifstat_rtacct_lnstat.patch | 20 ++ .../130-no_netem_tipc_dcb_man_vdpa.patch | 11 + iproute2/patches/140-allow_pfifo_fast.patch | 9 + .../patches/140-keep_libmnl_optional.patch | 11 + .../patches/145-keep_libelf_optional.patch | 11 + .../patches/150-keep_libcap_optional.patch | 11 + iproute2/patches/160-libnetlink-pic.patch | 11 + .../patches/175-reduce-dynamic-syms.patch | 45 ++++ iproute2/patches/180-drop_FAILED_POLICY.patch | 41 +++ iproute2/patches/190-fix-nls-rpath-link.patch | 20 ++ .../patches/200-drop_libbsd_dependency.patch | 19 ++ .../patches/300-selinux-configurable.patch | 11 + 16 files changed, 549 insertions(+) create mode 100644 iproute2/Makefile create mode 100644 iproute2/patches/100-configure.patch create mode 100644 iproute2/patches/110-darwin_fixes.patch create mode 100644 iproute2/patches/115-add-config-xtlibdir.patch create mode 100644 iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch create mode 100644 iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch create mode 100644 iproute2/patches/140-allow_pfifo_fast.patch create mode 100644 iproute2/patches/140-keep_libmnl_optional.patch create mode 100644 iproute2/patches/145-keep_libelf_optional.patch create mode 100644 iproute2/patches/150-keep_libcap_optional.patch create mode 100644 iproute2/patches/160-libnetlink-pic.patch create mode 100644 iproute2/patches/175-reduce-dynamic-syms.patch create mode 100644 iproute2/patches/180-drop_FAILED_POLICY.patch create mode 100644 iproute2/patches/190-fix-nls-rpath-link.patch create mode 100644 iproute2/patches/200-drop_libbsd_dependency.patch create mode 100644 iproute2/patches/300-selinux-configurable.patch diff --git a/iproute2/Makefile b/iproute2/Makefile new file mode 100644 index 000000000..1405f0752 --- /dev/null +++ b/iproute2/Makefile @@ -0,0 +1,246 @@ +# +# Copyright (C) 2006-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=iproute2 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://git.kernel.org/pub/scm/network/iproute2/iproute2.git +PKG_SOURCE_VERSION:=29da83f89f6e1fe528c59131a01f5d43bcd0a000 +PKG_VERSION:=5.16.0-$(PKG_SOURCE_VERSION) + +PKG_BUILD_PARALLEL:=1 +PKG_BUILD_DEPENDS:=iptables +PKG_LICENSE:=GPL-2.0 +PKG_CPE_ID:=cpe:/a:iproute2_project:iproute2 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/iproute2/Default + SECTION:=net + CATEGORY:=Network + URL:=http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 + SUBMENU:=Routing and Redirection + MAINTAINER:=Russell Senior +endef + +define Package/ip-tiny +$(call Package/iproute2/Default) + TITLE:=Routing control utility (minimal) + VARIANT:=iptiny + DEFAULT_VARIANT:=1 + PROVIDES:=ip + ALTERNATIVES:=200:/sbin/ip:/usr/libexec/ip-tiny + DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/ip-full +$(call Package/iproute2/Default) + TITLE:=Routing control utility (full) + VARIANT:=ipfull + PROVIDES:=ip + ALTERNATIVES:=300:/sbin/ip:/usr/libexec/ip-full + DEPENDS:=+libnl-tiny +libbpf +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/tc-tiny +$(call Package/iproute2/Default) + TITLE:=Traffic control utility (minimal) + VARIANT:=tctiny + DEFAULT_VARIANT:=1 + PROVIDES:=tc + ALTERNATIVES:=200:/sbin/tc:/usr/libexec/tc-tiny + DEPENDS:=+kmod-sched-core +libxtables +tc-mod-iptables +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/tc-full +$(call Package/iproute2/Default) + TITLE:=Traffic control utility (full) + VARIANT:=tcfull + PROVIDES:=tc + ALTERNATIVES:=300:/sbin/tc:/usr/libexec/tc-full + DEPENDS:=+kmod-sched-core +libxtables +tc-mod-iptables +libbpf +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/tc-mod-iptables +$(call Package/iproute2/Default) + TITLE:=Traffic control module - iptables action + DEPENDS:=+libxtables +endef + +define Package/genl +$(call Package/iproute2/Default) + TITLE:=General netlink utility frontend + DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/ip-bridge +$(call Package/iproute2/Default) + TITLE:=Bridge configuration utility from iproute2 + DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/ss +$(call Package/iproute2/Default) + TITLE:=Socket statistics utility + DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +kmod-netlink-diag +endef + +define Package/nstat +$(call Package/iproute2/Default) + TITLE:=Network statistics utility + DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/devlink +$(call Package/iproute2/Default) + TITLE:=Network devlink utility + DEPENDS:=+libmnl +endef + +define Package/rdma +$(call Package/iproute2/Default) + TITLE:=Network rdma utility + DEPENDS:=+libmnl +endef + +ifeq ($(BUILD_VARIANT),iptiny) + IP_CONFIG_TINY:=y + LIBBPF_FORCE:=off +endif + +ifeq ($(BUILD_VARIANT),ipfull) + HAVE_ELF:=y + LIBBPF_FORCE:=on +endif + +ifeq ($(BUILD_VARIANT),tctiny) + LIBBPF_FORCE:=off + SHARED_LIBS:=y +endif + +ifeq ($(BUILD_VARIANT),tcfull) + HAVE_ELF:=y + LIBBPF_FORCE:=on + SHARED_LIBS:=y +endif + +ifdef CONFIG_PACKAGE_devlink + HAVE_MNL:=y +endif + +ifdef CONFIG_PACKAGE_rdma + HAVE_MNL:=y +endif + +define Build/Configure + echo "static const char SNAPSHOT[] = \"$(PKG_VERSION)-$(PKG_RELEASE)-openwrt\";" \ + > $(PKG_BUILD_DIR)/include/SNAPSHOT.h +endef + +TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto +TARGET_LDFLAGS += -Wl,--gc-sections -Wl,--as-needed +TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny + +MAKE_FLAGS += \ + KERNEL_INCLUDE="$(LINUX_DIR)/user_headers/include" \ + SHARED_LIBS=$(SHARED_LIBS) \ + IP_CONFIG_TINY=$(IP_CONFIG_TINY) \ + BUILD_VARIANT=$(BUILD_VARIANT) \ + LIBBPF_FORCE=$(LIBBPF_FORCE) \ + HAVE_ELF=$(HAVE_ELF) \ + HAVE_MNL=$(HAVE_MNL) \ + HAVE_CAP=$(HAVE_CAP) \ + IPT_LIB_DIR=/usr/lib/iptables \ + XT_LIB_DIR=/usr/lib/iptables \ + FPIC="$(FPIC)" \ + $(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') + +define Build/Compile + +$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/iproute2 + $(CP) $(PKG_BUILD_DIR)/include/bpf_elf.h $(1)/usr/include/iproute2 + $(CP) $(PKG_BUILD_DIR)/include/{libgenl,libnetlink}.h $(1)/usr/include/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/lib/libnetlink.a $(1)/usr/lib/ +endef + +define Package/ip-tiny/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/libexec/ip-tiny +endef + +define Package/ip-full/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/libexec/ip-full +endef + +define Package/tc-tiny/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-tiny +endef + +define Package/tc-full/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-full +endef + +define Package/tc-mod-iptables/install + $(INSTALL_DIR) $(1)/usr/lib/tc + $(CP) $(PKG_BUILD_DIR)/tc/m_xt.so $(1)/usr/lib/tc +endef + +define Package/genl/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/genl/genl $(1)/usr/sbin/ +endef + +define Package/ip-bridge/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/bridge/bridge $(1)/usr/sbin/ +endef + +define Package/ss/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc/ss $(1)/usr/sbin/ +endef + +define Package/nstat/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc/nstat $(1)/usr/sbin/ +endef + +define Package/devlink/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/devlink/devlink $(1)/usr/sbin/ +endef + +define Package/rdma/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rdma/rdma $(1)/usr/sbin/ +endef + +#$(eval $(call BuildPackage,ip-tiny)) +$(eval $(call BuildPackage,ip-full)) +# build tc-mod-iptables before its dependents, to avoid +# spurious rebuilds when building multiple variants. +$(eval $(call BuildPackage,tc-mod-iptables)) +#$(eval $(call BuildPackage,tc-tiny)) +$(eval $(call BuildPackage,tc-full)) +$(eval $(call BuildPackage,genl)) +$(eval $(call BuildPackage,ip-bridge)) +$(eval $(call BuildPackage,ss)) +$(eval $(call BuildPackage,nstat)) +$(eval $(call BuildPackage,devlink)) +$(eval $(call BuildPackage,rdma)) diff --git a/iproute2/patches/100-configure.patch b/iproute2/patches/100-configure.patch new file mode 100644 index 000000000..0c19b2086 --- /dev/null +++ b/iproute2/patches/100-configure.patch @@ -0,0 +1,12 @@ +--- a/configure ++++ b/configure +@@ -34,7 +34,8 @@ int main(int argc, char **argv) { + } + EOF + +- if $CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1; then ++# OpenWrt: disable ATM support even if present on host system ++ if [ 1 -eq 0 ]; then + echo "TC_CONFIG_ATM:=y" >>$CONFIG + echo yes + else diff --git a/iproute2/patches/110-darwin_fixes.patch b/iproute2/patches/110-darwin_fixes.patch new file mode 100644 index 000000000..1f3eb101e --- /dev/null +++ b/iproute2/patches/110-darwin_fixes.patch @@ -0,0 +1,59 @@ +--- a/netem/maketable.c ++++ b/netem/maketable.c +@@ -10,7 +10,9 @@ + #include + #include + #include ++#if !defined(__APPLE__) && !defined(__FreeBSD__) + #include ++#endif + #include + #include + #include +--- a/netem/normal.c ++++ b/netem/normal.c +@@ -8,8 +8,12 @@ + #include + #include + ++#if !defined(__APPLE__) && !defined(__FreeBSD__) + #include + #include ++#else ++#define NETEM_DIST_SCALE 8192 ++#endif + + #define TABLESIZE 16384 + #define TABLEFACTOR NETEM_DIST_SCALE +--- a/netem/pareto.c ++++ b/netem/pareto.c +@@ -7,8 +7,12 @@ + #include + #include + ++#if !defined(__APPLE__) && !defined(__FreeBSD__) + #include + #include ++#else ++#define NETEM_DIST_SCALE 8192 ++#endif + + static const double a=3.0; + #define TABLESIZE 16384 +--- a/netem/paretonormal.c ++++ b/netem/paretonormal.c +@@ -14,10 +14,13 @@ + #include + #include + #include ++#if !defined(__APPLE__) && !defined(__FreeBSD__) + #include +- + #include + #include ++#else ++#define NETEM_DIST_SCALE 8192 ++#endif + + #define TABLESIZE 16384 + #define TABLEFACTOR NETEM_DIST_SCALE diff --git a/iproute2/patches/115-add-config-xtlibdir.patch b/iproute2/patches/115-add-config-xtlibdir.patch new file mode 100644 index 000000000..8702d5fd2 --- /dev/null +++ b/iproute2/patches/115-add-config-xtlibdir.patch @@ -0,0 +1,12 @@ +--- a/tc/Makefile ++++ b/tc/Makefile +@@ -128,6 +128,9 @@ CFLAGS += -DCONFIG_GACT -DCONFIG_GACT_PR + ifneq ($(IPT_LIB_DIR),) + CFLAGS += -DIPT_LIB_DIR=\"$(IPT_LIB_DIR)\" + endif ++ifneq ($(XT_LIB_DIR),) ++ CFLAGS += -DXT_LIB_DIR=\"$(XT_LIB_DIR)\" ++endif + + LEX := flex + CFLAGS += -DYY_NO_INPUT diff --git a/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch b/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch new file mode 100644 index 000000000..bb6a8d018 --- /dev/null +++ b/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch @@ -0,0 +1,20 @@ +--- a/misc/Makefile ++++ b/misc/Makefile +@@ -2,13 +2,13 @@ + SSOBJ=ss.o ssfilter_check.o ssfilter.tab.o + LNSTATOBJ=lnstat.o lnstat_util.o + +-TARGETS=ss nstat ifstat rtacct lnstat ++TARGETS=ss nstat + + include ../config.mk + +-ifeq ($(HAVE_BERKELEY_DB),y) +- TARGETS += arpd +-endif ++#ifeq ($(HAVE_BERKELEY_DB),y) ++# TARGETS += arpd ++#endif + + all: $(TARGETS) + diff --git a/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch b/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch new file mode 100644 index 000000000..8ddb31674 --- /dev/null +++ b/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -55,7 +55,7 @@ WFLAGS += -Wmissing-declarations -Wold-s + CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS) + YACCFLAGS = -d -t -v + +-SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma dcb man vdpa ++SUBDIRS=lib ip tc bridge misc genl devlink rdma + + LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a + LDLIBS += $(LIBNETLINK) diff --git a/iproute2/patches/140-allow_pfifo_fast.patch b/iproute2/patches/140-allow_pfifo_fast.patch new file mode 100644 index 000000000..13de48f41 --- /dev/null +++ b/iproute2/patches/140-allow_pfifo_fast.patch @@ -0,0 +1,9 @@ +--- a/tc/q_fifo.c ++++ b/tc/q_fifo.c +@@ -95,5 +95,6 @@ struct qdisc_util pfifo_head_drop_qdisc_ + + struct qdisc_util pfifo_fast_qdisc_util = { + .id = "pfifo_fast", ++ .parse_qopt = fifo_parse_opt, + .print_qopt = prio_print_opt, + }; diff --git a/iproute2/patches/140-keep_libmnl_optional.patch b/iproute2/patches/140-keep_libmnl_optional.patch new file mode 100644 index 000000000..ff7e9ca4e --- /dev/null +++ b/iproute2/patches/140-keep_libmnl_optional.patch @@ -0,0 +1,11 @@ +--- a/configure ++++ b/configure +@@ -387,7 +387,7 @@ check_selinux() + + check_mnl() + { +- if ${PKG_CONFIG} libmnl --exists; then ++ if [ "${HAVE_MNL}" = "y" ] && ${PKG_CONFIG} libmnl --exists; then + echo "HAVE_MNL:=y" >>$CONFIG + echo "yes" + diff --git a/iproute2/patches/145-keep_libelf_optional.patch b/iproute2/patches/145-keep_libelf_optional.patch new file mode 100644 index 000000000..079ca0512 --- /dev/null +++ b/iproute2/patches/145-keep_libelf_optional.patch @@ -0,0 +1,11 @@ +--- a/configure ++++ b/configure +@@ -255,7 +255,7 @@ EOF + + check_elf() + { +- if ${PKG_CONFIG} libelf --exists; then ++ if [ "${HAVE_ELF}" = "y" ] && ${PKG_CONFIG} libelf --exists; then + echo "HAVE_ELF:=y" >>$CONFIG + echo "yes" + diff --git a/iproute2/patches/150-keep_libcap_optional.patch b/iproute2/patches/150-keep_libcap_optional.patch new file mode 100644 index 000000000..68e162416 --- /dev/null +++ b/iproute2/patches/150-keep_libcap_optional.patch @@ -0,0 +1,11 @@ +--- a/configure ++++ b/configure +@@ -445,7 +445,7 @@ EOF + + check_cap() + { +- if ${PKG_CONFIG} libcap --exists; then ++ if [ "${HAVE_CAP}" = "y" ] && ${PKG_CONFIG} libcap --exists; then + echo "HAVE_CAP:=y" >>$CONFIG + echo "yes" + diff --git a/iproute2/patches/160-libnetlink-pic.patch b/iproute2/patches/160-libnetlink-pic.patch new file mode 100644 index 000000000..145ec7a9e --- /dev/null +++ b/iproute2/patches/160-libnetlink-pic.patch @@ -0,0 +1,11 @@ +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + include ../config.mk + +-CFLAGS += -fPIC ++CFLAGS += $(FPIC) + + UTILOBJ = utils.o utils_math.o rt_names.o ll_map.o ll_types.o ll_proto.o ll_addr.o \ + inet_proto.o namespace.o json_writer.o json_print.o json_print_math.o \ diff --git a/iproute2/patches/175-reduce-dynamic-syms.patch b/iproute2/patches/175-reduce-dynamic-syms.patch new file mode 100644 index 000000000..c3892e5a0 --- /dev/null +++ b/iproute2/patches/175-reduce-dynamic-syms.patch @@ -0,0 +1,45 @@ +--- a/tc/Makefile ++++ b/tc/Makefile +@@ -114,7 +114,7 @@ LDLIBS += -L. -lm + + ifeq ($(SHARED_LIBS),y) + LDLIBS += -ldl +-LDFLAGS += -Wl,-export-dynamic ++LDFLAGS += -Wl,--dynamic-list=dynsyms.list + endif + + TCLIB := tc_core.o +@@ -144,7 +144,7 @@ MODDESTDIR := $(DESTDIR)$(LIBDIR)/tc + all: tc $(TCSO) + + tc: $(TCOBJ) $(LIBNETLINK) libtc.a +- $(QUIET_LINK)$(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@ ++ $(QUIET_LINK)$(CC) $(filter-out dynsyms.list, $^) $(LDFLAGS) $(LDLIBS) -o $@ + + libtc.a: $(TCLIB) + $(QUIET_AR)$(AR) rcs $@ $^ +@@ -166,6 +166,7 @@ install: all + clean: + rm -f $(TCOBJ) $(TCLIB) libtc.a tc *.so emp_ematch.tab.h; \ + rm -f emp_ematch.tab.* ++ rm -f dynsyms.list + + q_atm.so: q_atm.c + $(QUIET_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -shared -fpic -o q_atm.so q_atm.c -latm +@@ -205,4 +206,16 @@ static-syms.h: $(wildcard *.c) + sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:extern char \1[] __attribute__((weak)); if (!strcmp(sym, "\1")) return \1;:;p}' $$files ; \ + done > $@ + ++else ++ ++tc: dynsyms.list ++m_xt.so: dynsyms.list ++dynsyms.list: $(wildcard *.c) ++ files="$(filter-out $(patsubst %.so,%.c,$(TCSO)), $^)" ; \ ++ echo "{" > $@ ; \ ++ for s in `grep -B 3 '\> $@ ; \ ++ echo "show_stats; print_nl; print_tm; parse_rtattr; parse_rtattr_flags; get_u32; matches; addattr_l; addattr_nest; addattr_nest_end; };" >> $@ ++ + endif diff --git a/iproute2/patches/180-drop_FAILED_POLICY.patch b/iproute2/patches/180-drop_FAILED_POLICY.patch new file mode 100644 index 000000000..07d5230a6 --- /dev/null +++ b/iproute2/patches/180-drop_FAILED_POLICY.patch @@ -0,0 +1,41 @@ +From 4e7dbf76227e8c7be7897dc81def3011f637864d Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Thu, 30 May 2013 11:54:04 +0200 +Subject: [PATCH] add support for dropping with FAILED_POLICY + +--- + include/linux/fib_rules.h | 4 ++++ + include/linux/rtnetlink.h | 1 + + ip/rtm_map.c | 4 ++++ + 3 files changed, 9 insertions(+) + +--- a/ip/rtm_map.c ++++ b/ip/rtm_map.c +@@ -54,6 +54,8 @@ char *rtnl_rtntype_n2a(int id, char *buf + return "nat"; + case RTN_XRESOLVE: + return "xresolve"; ++ case RTN_FAILED_POLICY: ++ return "failed_policy"; + default: + snprintf(buf, len, "%d", id); + return buf; +@@ -89,6 +91,8 @@ int rtnl_rtntype_a2n(int *id, char *arg) + res = RTN_UNICAST; + else if (strcmp(arg, "throw") == 0) + res = RTN_THROW; ++ else if (strcmp(arg, "failed_policy") == 0) ++ res = RTN_FAILED_POLICY; + else { + res = strtoul(arg, &end, 0); + if (!end || end == arg || *end || res > 255) +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -256,6 +256,7 @@ enum { + RTN_THROW, /* Not in this table */ + RTN_NAT, /* Translate this address */ + RTN_XRESOLVE, /* Use external resolver */ ++ RTN_FAILED_POLICY, /* Source address failed policy */ + __RTN_MAX + }; + diff --git a/iproute2/patches/190-fix-nls-rpath-link.patch b/iproute2/patches/190-fix-nls-rpath-link.patch new file mode 100644 index 000000000..92d02b9a4 --- /dev/null +++ b/iproute2/patches/190-fix-nls-rpath-link.patch @@ -0,0 +1,20 @@ +--- a/configure ++++ b/configure +@@ -279,7 +279,7 @@ int main(int argc, char **argv) { + } + EOF + +- $CC -o $TMPDIR/libbpf_test $TMPDIR/libbpf_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS >/dev/null 2>&1 ++ $CC -o $TMPDIR/libbpf_test $TMPDIR/libbpf_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS $LDFLAGS >/dev/null 2>&1 + local ret=$? + + rm -f $TMPDIR/libbpf_test.c $TMPDIR/libbpf_test +@@ -297,7 +297,7 @@ int main(int argc, char **argv) { + } + EOF + +- $CC -o $TMPDIR/libbpf_sec_test $TMPDIR/libbpf_sec_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS >/dev/null 2>&1 ++ $CC -o $TMPDIR/libbpf_sec_test $TMPDIR/libbpf_sec_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS $LDFLAGS >/dev/null 2>&1 + local ret=$? + + rm -f $TMPDIR/libbpf_sec_test.c $TMPDIR/libbpf_sec_test diff --git a/iproute2/patches/200-drop_libbsd_dependency.patch b/iproute2/patches/200-drop_libbsd_dependency.patch new file mode 100644 index 000000000..12a1ccfa3 --- /dev/null +++ b/iproute2/patches/200-drop_libbsd_dependency.patch @@ -0,0 +1,19 @@ +--- a/configure ++++ b/configure +@@ -431,14 +431,8 @@ EOF + if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then + echo "no" + else +- if ${PKG_CONFIG} libbsd --exists; then +- echo 'CFLAGS += -DHAVE_LIBBSD' `${PKG_CONFIG} libbsd --cflags` >>$CONFIG +- echo 'LDLIBS +=' `${PKG_CONFIG} libbsd --libs` >> $CONFIG +- echo "no" +- else +- echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG +- echo "yes" +- fi ++ echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG ++ echo "yes" + fi + rm -f $TMPDIR/strtest.c $TMPDIR/strtest + } diff --git a/iproute2/patches/300-selinux-configurable.patch b/iproute2/patches/300-selinux-configurable.patch new file mode 100644 index 000000000..b7e61fd3b --- /dev/null +++ b/iproute2/patches/300-selinux-configurable.patch @@ -0,0 +1,11 @@ +--- a/configure ++++ b/configure +@@ -374,7 +374,7 @@ check_libbpf() + check_selinux() + # SELinux is a compile time option in the ss utility + { +- if ${PKG_CONFIG} libselinux --exists; then ++ if [ "${HAVE_SELINUX}" = "y" ] && ${PKG_CONFIG} libselinux --exists; then + echo "HAVE_SELINUX:=y" >>$CONFIG + echo "yes" + From 26585702bad44aa5c00ff764a39c5a270bb7cafc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 9 Feb 2022 20:29:04 +0100 Subject: [PATCH 0679/2059] Update ModemManager --- modemmanager/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 570bc9293..1dbccf127 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_VERSION:=1.18.2 +PKG_VERSION:=1.18.4 PKG_RELEASE:=1 PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager -PKG_HASH:=374be158ae1c1fb38a29eef1cc3cdf89ff3536b48ff1320d208ab204ea6c5f8a +PKG_HASH:=11fb970f63e2da88df4b6d8759e4ee649944c515244b979bf50a7a6df1d7f199 PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION) PKG_MAINTAINER:=Nicholas Smith From 1699147b924dcd518e1ae80c64b39a9e39a42e70 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 9 Feb 2022 20:29:21 +0100 Subject: [PATCH 0680/2059] More check on post tracking --- .../share/omr/post-tracking.d/post-tracking | 88 ++++++++++++------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index c96828632..50fa888b7 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -725,7 +725,9 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then else _log "$OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) switched off because $OMR_TRACKER_STATUS_MSG" fi - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='down' + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='down' + fi #if [ "$(sysctl -n net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ]; then # multipath "$OMR_TRACKER_DEVICE" off > /dev/null 2>&1 #fi @@ -738,10 +740,12 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ] && [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ]; then VPN_BASE_INTF="$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.baseintf)" VPN_BASE_INTF_IP=$(ubus call network.interface.$VPN_BASE_INTF status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") - uci -q batch <<-EOF >/dev/null - set openvpn.$VPN_BASE_INTF.local=$VPN_BASE_INTF_IP - commit openvpn - EOF + if [ -n "$VPN_BASE_INTF" ]; then + uci -q batch <<-EOF >/dev/null + set openvpn.$VPN_BASE_INTF.local=$VPN_BASE_INTF_IP + commit openvpn + EOF + fi /etc/init.d/openvpn restart $VPN_BASE_INTF fi config_load openmptcprouter @@ -769,7 +773,11 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" fi fi - mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)" + + mail_alert="" + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)" + fi [ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" [ "$mail_alert" = "1" ] && [ -n "$(uci -q get mail.default.to)" ] && { OMR_SYSNAME="$(uci -q get system.@system[0].hostname)" @@ -783,10 +791,16 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then echo -e "Subject: $OMR_SYSNAME: $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) is down\n\nConnection failure of $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) detected. The reason is \"$OMR_TRACKER_STATUS_MSG\"." | sendmail $(uci -q get mail.default.to) fi } - script_alert_down="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.script_alert_down)" + script_alert_down="" + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + script_alert_down="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.script_alert_down)" + fi [ -n "$script_alert_down" ] && eval $script_alert_down - restart_down="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.restart_down)" + restart_down="" + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + restart_down="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.restart_down)" + fi [ -z "$restart_down" ] && restart_down="$(uci -q get omr-tracker.defaults.restart_down)" [ "$restart_down" = "1" ] && { _log "Restart $OMR_TRACKER_INTERFACE" @@ -839,7 +853,9 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi fi dns_flush - uci -q delete openmptcprouter.$OMR_TRACKER_INTERFACE.lc + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + uci -q delete openmptcprouter.$OMR_TRACKER_INTERFACE.lc + fi uci -q commit openmptcprouter #ubus call network reload @@ -924,7 +940,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om exit 0 fi -if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then +if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" != "up" ]; then uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' uci -q commit openmptcprouter @@ -932,7 +948,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then exit 0 fi -if [ "$OMR_TRACKER_PREV_STATUS" != "" ] && [ "$OMR_TRACKER_PREV_STATUS" != "$OMR_TRACKER_STATUS" ]; then +if [ "$OMR_TRACKER_PREV_STATUS" != "" ] && [ "$OMR_TRACKER_PREV_STATUS" != "$OMR_TRACKER_STATUS" ] && [ -n "$OMR_TRACKER_INTERFACE" ]; then _log "$OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) switched up" mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)" [ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" @@ -951,18 +967,20 @@ if [ "$OMR_TRACKER_PREV_STATUS" != "" ] && [ "$OMR_TRACKER_PREV_STATUS" != "$OMR script_alert_up="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.script_alert_up)" [ -n "$script_alert_up" ] && eval $script_alert_up fi -if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" != "up" ]; then +if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" != "up" ]; then uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' uci -q commit openmptcprouter dns_flush fi -multipath_config=$(uci -q get "openmtpcprouter.$OMR_TRACKER_INTERFACE.multipath") -[ -z "$multipath_config" ] && multipath_config=$(uci -q get "network.$OMR_TRACKER_INTERFACE.multipath" || echo "off") -[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { - [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" -} +if [ -n "$OMR_TRACKER_INTERFACE" ]; then + multipath_config=$(uci -q get "openmtpcprouter.$OMR_TRACKER_INTERFACE.multipath") + [ -z "$multipath_config" ] && multipath_config=$(uci -q get "network.$OMR_TRACKER_INTERFACE.multipath" || echo "off") + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + } +fi if [ "$multipath_config" = "master" ]; then #if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && ([ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ] || [ "$(uci -q get openmptcprouter.settings.vpn)" = "mlvpn" ]); then @@ -1010,7 +1028,7 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_route_balancing interface config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { + ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Change in routes, set ip route replace default scope global $routesbalancing (omrvpn_intf: $omrvpn_intf)" [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Current route: $(ip r)" ip route replace default scope global metric 1 $routesbalancing 2>&1 >/dev/null @@ -1024,7 +1042,7 @@ if [ "$multipath_config" = "master" ]; then } } [ -n "$routesbalancingbackup" ] && { - ([ "$nbintfb" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { + ([ "$nbintfb" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Set backup ip route replace default scope global metric 999 $routesbalancingbackup" ip route replace default scope global metric 999 $routesbalancingbackup 2>&1 >/dev/null } @@ -1043,7 +1061,7 @@ if [ "$multipath_config" = "master" ]; then if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE " ]; then ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 991337 2>&1 >/dev/null fi - if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") + $((10 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]; then + if ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ]) || [ $(($(date +"%s") + $((10 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]; then [ "$(pgrep openmptcprouter-vps)" = "" ] && /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 fi multipath_config="on" @@ -1057,7 +1075,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route server fi - if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then _log "Interface route not yet set, set route ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi @@ -1070,12 +1088,12 @@ if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; th elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route6 server fi - if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi fi -if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then +if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]); then download="$(uci -q get network.$OMR_TRACKER_INTERFACE.downloadspeed)" [ -z "$download" ] && download="$(uci -q get sqm.$OMR_TRACKER_INTERFACE.download)" upload="$(uci -q get network.$OMR_TRACKER_INTERFACE.uploadspeed)" @@ -1144,7 +1162,7 @@ fi #ubus call network reload # Save wan settings for status page -if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") + $((30 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" = "down" ]; then +if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") + $((30 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" = "down" ]); then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Get status and settings for $OMR_TRACKER_INTERFACE..." local ipaddr="" local ip6addr="" @@ -1214,7 +1232,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( local lanip="$(uci -q get network.lan.ipaddr)" local masterip get_master_ip() { - if [ "$(uci -q get openmptcprouter.$1.multipath)" = "master" ]; then + if [ -n "$1" ] && [ "$(uci -q get openmptcprouter.$1.multipath)" = "master" ]; then masterip="$(uci -q get openmptcprouter.$1.publicip)" fi } @@ -1223,7 +1241,8 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( if [ -n "$lanip" ] && [ -n "$masterip" ] && [ -n "$ipaddr" ] && [ "$ipaddr" = "$masterip" ] && [ "$(uci -q get openmptcprouter.settings.disableloopdetection)" != "1" ]; then loop=0 routingloop() { - vpsip="$(uci -q get openmptcprouter.$1.ip)" + vpsip="" + [ -n "$1"] && vpsip="$(uci -q get openmptcprouter.$1.ip)" if [ -n "$vpsip" ] && [ "$(omr-routing-loop $vpsip $lanip $OMR_TRACKER_DEVICE)" = "detected" ]; then loop=1 fi @@ -1249,7 +1268,9 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( } if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ]; then - mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) + network_device=$(find_network_device ${OMR_TRACKER_INTERFACE}) + mtu="" + [ -n "$network_device" ] && mtu=$(uci -q get network.${network_device}.mtu) [ -n "$mtu" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 @@ -1275,7 +1296,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( } config_load openmptcprouter config_foreach traceboxmtutest server - [ "$(uci -q get openmptcprouter.settings.tracebox)" = "0" ] && { + [ "$(uci -q get openmptcprouter.settings.tracebox)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE" ] && { mptcpsupport="$(omr-mptcp-intf $OMR_TRACKER_DEVICE)" [ -n "$mptcpsupport" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$mptcpsupport" } @@ -1319,7 +1340,8 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ]; then + network_device=$(find_network_device ${OMR_TRACKER_INTERFACE}) + if [ -n "$network_device" ] && [ -n "$(uci -q get network.${network_device}.mtu)" ]; then mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) [ -n "$mtu" ] && { uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu @@ -1390,7 +1412,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( dns_flush fi -[ -n "$OMR_TRACKER_LATENCY" ] && { +[ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_LATENCY" ] && { [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.latency)" != "" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency_previous="$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.latency)" uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" #[ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.latency_max)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency_max="$OMR_TRACKER_LATENCY" @@ -1399,7 +1421,7 @@ fi masterintf="$(uci -q show openmptcprouter | grep -m 1 multipath=\'master\' | cut -d'.' -f2)" [ -z "$masterintf" ] && masterintf="$(uci -q show network | grep -m 1 multipath=\'master\' | cut -d'.' -f2)" masterlatency="$(uci -q get openmptcprouter.$masterintf.latency | tr -d '\n')" - if [ -z "$masterlatency" ] || [ "$(uci -q get openmptcprouter.$masterintf.state)" = "down" ]; then + if [ -z "$masterlatency" ] || ([ -n "$masterintf" ] &&[ "$(uci -q get openmptcprouter.$masterintf.state)" = "down" ]); then masterlatency=1000 fi if [ -n "$masterintf" ] && ([ "$masterlatency" != "" ] || [ "$(uci -q get openmptcprouter.$masterintf.state)" = "down" ]); then @@ -1560,7 +1582,7 @@ if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(pgrep openmp /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 run_fw_include() { - [ "$(uci -q get firewall.$1.reload)" = "0" ] && sh $(uci -q get firewall.$1.path) >/dev/null 2>&1 + [ -n "$1" ] && [ "$(uci -q get firewall.$1.reload)" = "0" ] && sh $(uci -q get firewall.$1.path) >/dev/null 2>&1 } config_load firewall config_foreach run_fw_include include From 95ea617630f750c0364479db6d43dc7d5d521d6d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 9 Feb 2022 20:29:41 +0100 Subject: [PATCH 0681/2059] Fix configuration for 5.15 --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index b9e7d0630..08d1307ee 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -30,7 +30,7 @@ if uname.release:sub(1,4) ~= "5.14" then end o = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler")) o:value("default", translate("default")) -if uname.release:sub(1,4) ~= "5.14" then +if uname.release:sub(1,4) ~= "5.15" then o:value("roundrobin", "round-robin") o:value("redundant", "redundant") if uname.release:sub(1,4) ~= "4.14" then @@ -38,7 +38,7 @@ if uname.release:sub(1,4) ~= "5.14" then o:value("ecf", "ECF") end end -if uname.release:sub(1,4) ~= "5.14" then +if uname.release:sub(1,4) ~= "5.15" then o = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) o.datatype = "uinteger" o.rmempty = false @@ -49,7 +49,7 @@ for cong in string.gmatch(availablecong, "[^%s]+") do o:value(cong, translate(cong)) end -if uname.release:sub(1,4) == "5.14" then +if uname.release:sub(1,4) == "5.15" then o = s:option(Value, "mptcp_subflows", translate("specifies the maximum number of additional subflows allowed for each MPTCP connection")) o.datatype = "uinteger" o.rmempty = false From 43865452a526a8b7dffe7aefe3d3e8314d063d39 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 9 Feb 2022 20:38:43 +0100 Subject: [PATCH 0682/2059] Check var exist on omr-tracker --- omr-tracker/files/bin/omr-tracker | 7 +++++-- omr-tracker/files/etc/init.d/omr-tracker | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index f78571aab..27824791c 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -92,6 +92,7 @@ _post_tracking() { _ping_server() { local servername=$1 + [ -z "$servername" ] && return local disabled=$(uci -q get openmptcprouter.$1.disabled) local device=$2 if [ -n "$device" ] && [ "$disabled" != "1" ]; then @@ -113,6 +114,7 @@ _ping_server() { _httping_server() { local servername=$1 + [ -z "$servername" ] && return local disabled=$(uci -q get openmptcprouter.$1.disabled) local port=$(uci -q get openmptcprouter.$1.port) local device=$2 @@ -135,9 +137,10 @@ _httping_server() { _ping() { local host=$1 + [ -z "$host" ] && return local device=$2 local localip=$3 - if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "3g" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "qmi" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "ncm" ]; then + if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "3g" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "qmi" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "ncm" ]); then ret=$(ping -I "${device}" \ -w "$OMR_TRACKER_TIMEOUT" \ -c 2 \ @@ -222,7 +225,7 @@ _none() { _restart -OMR_TRACKER_INTERFACE_PROTO="$(uci -q get network.${OMR_TRACKER_INTERFACE_PROTO}.proto)" +OMR_TRACKER_INTERFACE_PROTO="$(uci -q get network.${OMR_TRACKER_INTERFACE}.proto)" OMR_TRACKER_PREV_STATUS="" # main loop while true; do diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 419e2bd05..0f80614ed 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -48,7 +48,7 @@ _launch_tracker() { case "$1" in loopback|lan*|if0*) return;; esac - + [ -z "$1" ] && return local hosts hosts6 timeout tries interval interval_tries options type enabled wait_test ipv6 proto server_http_test _validate_section "defaults" "defaults" _validate_section "interface" "$1" @@ -152,6 +152,7 @@ _initialize_shadowsocks_tracker() { server=$1 [ -n "$(echo $server | grep sss)" ] || return + [ -z "$server" ] && return #redir_tcp=$(uci -q get shadowsocks-libev.ss_rules.redir_tcp) #config_get tracker_server ss_rules server @@ -199,7 +200,8 @@ _launch_shadowsocks_tracker() { config_get server "$1" server [ "$enabled" = "0" ] || [ "$disabled" = "1" ] || [ -z "$hosts" ] && return - [ -z "$server" ] || [ "$(uci -q get shadowsocks-libev.$server.server)" = "192.168.1.3" ] || [ "$(uci -q get shadowsocks-libev.$server.server)" = "" ] && return + [ -z "$server" ] && return + [ "$(uci -q get shadowsocks-libev.$server.server)" = "192.168.1.3" ] || [ "$(uci -q get shadowsocks-libev.$server.server)" = "" ] && return procd_open_instance # shellcheck disable=SC2086 From 095a7b0b511f565ad7e15e2710a23a1dc8c99ca4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 10 Feb 2022 20:37:29 +0100 Subject: [PATCH 0683/2059] Update iperf3 to 3.11 --- iperf3/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iperf3/Makefile b/iperf3/Makefile index 6cdb6b8a9..cf0d6599c 100644 --- a/iperf3/Makefile +++ b/iperf3/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iperf -PKG_VERSION:=3.10.1 +PKG_VERSION:=3.11 PKG_RELEASE:=10 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://downloads.es.net/pub/iperf -PKG_HASH:=03bc9760cc54a245191d46bfc8edaf8a4750f0e87abca6764486972044d6715a +PKG_SOURCE:=$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/esnet/iperf/archive/refs/tags/ +PKG_HASH:=96e909c0d3ab6034c52328c2954fb3934aaff349395c4bc2611dcd50e6b89875 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=BSD-3-Clause From 1bcfffa39295d15d01db6cca64b6bf48b36bfa7b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 11 Feb 2022 12:06:41 +0100 Subject: [PATCH 0684/2059] Add and remove logs on omr-tracker --- .../share/omr/post-tracking.d/post-tracking | 56 +++++++++---------- omr-tracker/files/bin/omr-tracker | 6 +- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 50fa888b7..0e8ca6953 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -664,7 +664,7 @@ disable_pihole() { commit dhcp EOF fi - /etc/init.d/dnsmasq restart + /etc/init.d/dnsmasq restart 2>&1 >/dev/null fi } @@ -746,7 +746,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then commit openvpn EOF fi - /etc/init.d/openvpn restart $VPN_BASE_INTF + /etc/init.d/openvpn restart $VPN_BASE_INTF 2>&1 >/dev/null fi config_load openmptcprouter config_foreach del_server_route server @@ -824,25 +824,25 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then _log "Tunnel down use ShadowSocks for UDP" uci -q set shadowsocks-libev.ss_rules.redir_udp='hi1' if /etc/init.d/shadowsocks-libev rules_exist ; then - /etc/init.d/shadowsocks-libev rules_down - /etc/init.d/shadowsocks-libev rules_up + /etc/init.d/shadowsocks-libev rules_down 2>&1 >/dev/null + /etc/init.d/shadowsocks-libev rules_up 2>&1 >/dev/null fi fi if [ "$(uci -q get dsvpn.vpn.enable)" = "1" ]; then _log "DSVPN down, restart it" - /etc/init.d/dsvpn restart + /etc/init.d/dsvpn restart 2>&1 >/dev/null fi if [ "$(uci -q get mlvpn.general.enable)" = "1" ]; then _log "MLVPN down, restart it" - /etc/init.d/mlvpn restart + /etc/init.d/mlvpn restart 2>&1 >/dev/null fi if [ "$(uci -q get glorytun.vpn.enable)" = "1" ]; then _log "Glorytun VPN down, restart it" - /etc/init.d/glorytun restart + /etc/init.d/glorytun restart 2>&1 >/dev/null fi if [ "$(uci -q get glorytun-udp.vpn.enable)" = "1" ]; then _log "Glorytun UDP VPN down, restart it" - /etc/init.d/glorytun-udp restart + /etc/init.d/glorytun-udp restart 2>&1 >/dev/null fi config_load openmptcprouter config_foreach disable_pihole server @@ -935,7 +935,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om config_load openmptcprouter config_foreach enable_pihole server #config_foreach delete_server_default_route server - [ "$nbserver" = "$piholeenabled" ] && /etc/init.d/openmptcprouter-vps set_pihole + [ "$nbserver" = "$piholeenabled" ] && /etc/init.d/openmptcprouter-vps set_pihole 2>&1 >/dev/null #ubus call network reload exit 0 fi @@ -1219,7 +1219,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC _log "New public ip detected for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE): $ipaddr" /etc/init.d/mptcp enabled && { _log "Reload MPTCP for $OMR_TRACKER_DEVICE" - /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" >/dev/null + /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" 2>&1 >/dev/null } uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ipaddr" } @@ -1323,7 +1323,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC _log "New public ip detected for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE): $ip6addr" /etc/init.d/mptcp enabled && { _log "Reload MPTCP for $OMR_TRACKER_DEVICE" - /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" >/dev/null + /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" 2>&1 >/dev/null } uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ip6addr" } @@ -1421,7 +1421,7 @@ fi masterintf="$(uci -q show openmptcprouter | grep -m 1 multipath=\'master\' | cut -d'.' -f2)" [ -z "$masterintf" ] && masterintf="$(uci -q show network | grep -m 1 multipath=\'master\' | cut -d'.' -f2)" masterlatency="$(uci -q get openmptcprouter.$masterintf.latency | tr -d '\n')" - if [ -z "$masterlatency" ] || ([ -n "$masterintf" ] &&[ "$(uci -q get openmptcprouter.$masterintf.state)" = "down" ]); then + if [ -z "$masterlatency" ] || ([ -n "$masterintf" ] && [ "$(uci -q get openmptcprouter.$masterintf.state)" = "down" ]); then masterlatency=1000 fi if [ -n "$masterintf" ] && ([ "$masterlatency" != "" ] || [ "$(uci -q get openmptcprouter.$masterintf.state)" = "down" ]); then @@ -1449,22 +1449,22 @@ fi # If a service is down, force restart it if [ "$(pgrep ss-redir)" = "" ] && [ "$(pgrep ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then _log "Can't find Shadowsocks, restart it..." - /etc/init.d/shadowsocks-libev restart + /etc/init.d/shadowsocks-libev restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep glorytun)" = "" ] && [ "$(uci -q get glorytun.vpn.enable)" = "1" ] && [ -f /etc/init.d/glorytun ] && [ "$(uci -q get glorytun.vpn.key)" != "" ]; then _log "Can't find Glorytun, restart it..." - /etc/init.d/glorytun restart + /etc/init.d/glorytun restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep glorytun-udp)" = "" ] && [ "$(uci -q get glorytun-usp.vpn.enable)" = "1" ] && [ -f /etc/init.d/glorytun-udp ] && [ "$(uci -q get glorytun-udp.vpn.key)" != "" ]; then _log "Can't find Glorytun UDP, restart it..." - /etc/init.d/glorytun-udp restart + /etc/init.d/glorytun-udp restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep unbound)" = "" ] && [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then - /etc/init.d/unbound restart + /etc/init.d/unbound restart 2>&1 >/dev/null sleep 5 fi @@ -1477,53 +1477,53 @@ if [ "$(pgrep openvpn)" = "" ] && [ -f /etc/init.d/openvpn ]; then config_foreach openvpn_enabled openvpn if [ "$openvpn_enable" = "1" ]; then _log "Can't find OpenVPN, restart it" - /etc/init.d/openvpn restart + /etc/init.d/openvpn restart 2>&1 >/dev/null sleep 5 fi fi if [ "$(pgrep mlvpn)" = "" ] && [ "$(uci -q get mlvpn.general.enable)" = "1" ] && [ -f /etc/init.d/mlvpn ] && [ "$(uci -q get mlvpn.general.password)" != "" ]; then _log "Can't find MLVPN, restart it..." - /etc/init.d/mlvpn restart + /etc/init.d/mlvpn restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep dsvpn)" = "" ] && [ "$(uci -q get dsvpn.vpn.enable)" = "1" ] && [ -f /etc/init.d/dsvpn ] && [ "$(uci -q get dsvpn.vpn.key)" != "" ]; then _log "Can't find DSVPN, restart it..." - /etc/init.d/dsvpn restart + /etc/init.d/dsvpn restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep v2ray)" = "" ] && [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ]; then _log "Can't find V2Ray, restart it..." - /etc/init.d/v2ray restart + /etc/init.d/v2ray restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep miniupnpd)" = "" ] && [ "$(uci -q get upnpd.config.enabled)" = "1" ] && [ -f /etc/init.d/miniupnpd ]; then _log "Can't find miniupnpd, restart it..." - /etc/init.d/miniupnpd restart + /etc/init.d/miniupnpd restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep rpcd)" = "" ] && [ -f /etc/init.d/rpcd ]; then _log "Can't find rpcd, restart it..." - /etc/init.d/rpcd restart + /etc/init.d/rpcd restart 2>&1 >/dev/null sleep 5 fi if [ "$(pgrep uhttpd)" = "" ] && [ -f /etc/init.d/uhttpd ]; then _log "Can't find uhttpd, restart it..." - /etc/init.d/uhttpd restart + /etc/init.d/uhttpd restart 2>&1 >/dev/null sleep 5 fi #if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ] && [ "$(uci -q get openmptcprouter.settings.modemmanager)" != "0" ]; then # _log "Can't find ModemManager, restart it..." -# /etc/init.d/modemmanager restart +# /etc/init.d/modemmanager restart 2>&1 >/dev/null # sleep 5 #fi if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ "$(pgrep -f omr-tracker-v2ray)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-v2ray, restart omr-tracker..." - /etc/init.d/omr-tracker restart + /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi set_get_config() { @@ -1539,7 +1539,7 @@ fi if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-ss, restart omr-tracker..." - /etc/init.d/omr-tracker restart + /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi if [ "$(uci -q get glorytun.vpn.enable)" = "1" ] && [ "$(uci -q get glorytun.vpn.key)" = "" ]; then @@ -1563,12 +1563,12 @@ fi if [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep omr-bypass)" = "" ]; then _log "Can't find omr-bypass rules, restart omr-bypass..." - /etc/init.d/omr-bypass + /etc/init.d/omr-bypass 2>&1 >/dev/null fi if [ -f /etc/backup/installed_packages.txt ]; then _log "Reinstall packages..." - /etc/init.d/sysupgrade restart + /etc/init.d/sysupgrade restart 2>&1 >/dev/null fi if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 27824791c..0799c90ce 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -85,7 +85,11 @@ _post_tracking() { _log() { logger -t "post-tracking-${tracker_bin##*/}" "$*" } - . "$tracker_bin" + tmp=$(mktemp) + . "$tracker_bin" 2>&1 > "$tmp" + trackresult=$(< "$tmp") + [ -n "$trackresult" ] && _log $trackresult + rm -f "$tmp" ) done } From a3131ab8b04bcf74103aa33f08cf1a25cfce9497 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 11 Feb 2022 12:07:14 +0100 Subject: [PATCH 0685/2059] Update ndpi-netfilter2 and add host to bypass only if not already here --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 9 +++++++-- ndpi-netfilter2/Makefile | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 57d81c923..5220f47e2 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -14,13 +14,18 @@ _add_proto() { if [ "$(dd if=/proc/net/xt_ndpi/proto bs=4096 2> /dev/null | grep $protoname)" = "" ]; then echo "add_custom $protoname" >/proc/net/xt_ndpi/proto fi + allurls="$(dd if=/proc/net/xt_ndpi/host_proto bs=4096 2> /dev/null)" hosts="$( uci -q get omr-bypass.$protoname.url )" for url in $hosts; do - echo "$protoname:$url" >/proc/net/xt_ndpi/host_proto + if [ "$(echo "$allurls" | grep -i ^${protoname}: | grep $url)" = "" ]; then + echo "$protoname:$url" >/proc/net/xt_ndpi/host_proto + fi done ip="$( uci -q get omr-bypass.$protoname.ip )" for ip in $ips; do - echo "$protoname:$ip" >/proc/net/xt_ndpi/ip_proto + if [ "$(echo "$allurls" | grep -i ^${protoname}: | grep $ip)" = "" ]; then + echo "$protoname:$ip" >/proc/net/xt_ndpi/ip_proto + fi done } diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index b74ed75c1..2c0377aa8 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,8 +11,8 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=3 -PKG_REV:=25a5c2e1d619aa2d819b18bed8276b3bd7eb4c5b -PKG_VERSION:=3.2-$(PKG_REV) +PKG_REV:=59f295ba86110f2642f76eb967b041c4108fedd5 +PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 From 57e413c334f2a555a603d31bcd41cdd39ec6ed39 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 13 Feb 2022 10:55:18 +0100 Subject: [PATCH 0686/2059] Fix script, keep device --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 452749803..928feb60f 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -39,7 +39,7 @@ omr_intf_set() { uci -q set network.$1.modalias="$(cat /sys/class/net/${ifname}/device/uevent | grep MODALIAS | cut -d '=' -f2 | tr -d '\n')-$mac" uci -q set network.$1.product="$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT | cut -d '=' -f2 | tr -d '\n')" elif [ -n "$devicepath" ] && ([ "$(echo ${devicepath} | grep virtual)" != "" ] || [ "$(echo ${devicepath} | grep virtual)" = "" ] && [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PRODUCT)" = "" ] || [ "$(cat /sys/class/net/${ifname}/device/uevent | grep PCI_SLOT_NAME)" != "" ] || [ "$(cat /sys/class/net/${ifname}tmp/device/uevent)" != "" ]); then - uci -q delete network.$1.device + #uci -q delete network.$1.device uci -q delete network.$1.modalias uci -q delete network.$1.product fi From cd38c1a7e8a9b46e1669cef00eaef6d18e275555 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 15 Feb 2022 20:46:46 +0100 Subject: [PATCH 0687/2059] Fix ifname to device in wizard --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index f2c85d3e9..dafe89a3d 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -11,7 +11,7 @@ function device_notvirtual(dev) for _, iface in ipairs(net:get_networks()) do local ifacen = iface:name() - local ifacename = uci:get("network",ifacen,"ifname") + local ifacename = uci:get("network",ifacen,"device") local ifacetype = uci:get("network",ifacen,"type") or "" local ifaceproto = uci:get("network",ifacen,"proto") or "" --if ifacename == dev and (ifacetype == "macvlan" or ifacetype == "bridge" or ifaceproto == "6in4") then From 0395613d5fb18b4d166473cc2aac10f3aadd2a24 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 15 Feb 2022 20:47:08 +0100 Subject: [PATCH 0688/2059] Fix macvlan --- macvlan/files/etc/init.d/macvlan | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/macvlan/files/etc/init.d/macvlan b/macvlan/files/etc/init.d/macvlan index a09988504..6669a9ff2 100755 --- a/macvlan/files/etc/init.d/macvlan +++ b/macvlan/files/etc/init.d/macvlan @@ -13,6 +13,7 @@ _save_macaddr() { local _macaddr uci -q get "network.$1_dev.ifname" >/dev/null && { _ifname=$(uci -q get "network.$1.ifname") + [ -z "$_ifname" ] && _ifname=$(uci -q get "network.$1.device") if [ -n "$(uci -q get network.$1.macaddr)" ] && [ "$(uci -q get network.$1.macaddr)" != "$(uci -q get network.$1_dev.macaddr)" ]; then uci -q set network.$1_dev.macaddr="$(uci -q get network.$1.macaddr)" else @@ -25,6 +26,7 @@ _save_macaddr() { } [ -z "$(uci -q get network.$1.macaddr)" ] && { _ifname=$(uci -q get "network.$1.ifname") + [ -z "$_ifname" ] && _ifname=$(uci -q get "network.$1.device") [ -n "$_ifname" ] && [ -z "$(echo $_ifname | grep '\.')" ] && { _macaddr=$(ip link show dev $_ifname 2>/dev/null | grep link | awk '{print $2}') [ -n "$_macaddr" ] && { @@ -42,8 +44,6 @@ _delete_device() { uci -q batch <<-EOF delete network.$1 commit network - delete macvlan.$1 - commit macvlan EOF } return @@ -67,7 +67,7 @@ _setup_interface() { [ -z "$(uci -q get network.$1.masterintf)" ] && uci -q set network.$1.masterintf=$(uci -q get network.$1_dev.ifname) [ -n "$(uci -q get network.$1.masterintf)" ] && uci -q set network.$1_dev.ifname=$(uci -q get network.$1.masterintf) [ -n "$(uci -q get network.$1.macaddr)" ] && uci -q set network.$1_dev.macaddr=$(uci -q get network.$1.macaddr) - uci set network.$1.ifname=$1 + uci set network.$1.device=$1 uci -q commit network return 0 } @@ -75,9 +75,11 @@ _setup_interface() { uci -q batch <<-EOF set network.$1_dev=device set network.$1_dev.name=$1 - set network.$1_dev.type=macvlan + set network.$1_dev.type='macvlan' set network.$1_dev.ifname=$_ifname - set network.$1.ifname=$1 + set network.$1_dev.mode='private' + set network.$1_dev.multicast=0 + set network.$1.device=$1 set network.$1.masterintf=$_ifname set network.$1.type=macvlan set network.$1.defaultroute=0 @@ -86,7 +88,7 @@ _setup_interface() { #_macaddr=$(uci -q get "network.$1.macaddr") #_setup_macaddr "$1" "${_macaddr:-auto$(date +%s)}" - _setup_macaddr "$1" "auto$(date +%s)" + _setup_macaddr "$1" "$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')" uci -q set network.$1_dev.mtu=$(uci -q get network.$1.mtu) uci -q commit network } From 57108e16608c9624892d499132ccb6061c33103b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 15 Feb 2022 20:47:28 +0100 Subject: [PATCH 0689/2059] Fix set mac address --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index ef722926a..c8be3490a 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -27,7 +27,7 @@ _setup_macvlan() { set network.$1.masterintf=$_ifname EOF _macaddr=$(uci -q get "network.$1.macaddr") - _setup_macaddr "$1_dev" "${_macaddr:-auto$(date +%s)}" + _setup_macaddr "$1_dev" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" } #_setup_macvlan_update() { From 03802f5b4711038c86b1da3b71ea4aceb653fa2a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 17 Feb 2022 13:21:36 +0100 Subject: [PATCH 0690/2059] Use listvalue for protocol/services in omr-bypass --- .../htdocs/luci-static/resources/view/services/omr-bypass.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js index 109279953..361d203db 100644 --- a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js +++ b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js @@ -190,7 +190,7 @@ return L.view.extend({ o = s.option(form.Flag, 'enabled', _('Enabled')); o.default = o.enabled; - o = s.option(form.Value, 'proto', _('Protocol/Service')); + o = s.option(form.ListValue, 'proto', _('Protocol/Service')); o.rmempty = false; o.load = function(section_id) { return Promise.all([ From 5d38d60559728fd7a1af7ca1035a5b46ef8376ef Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Feb 2022 08:28:39 +0100 Subject: [PATCH 0691/2059] Add Multipath version support --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 6 ++++++ mptcp/files/etc/init.d/mptcp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index 08d1307ee..d853e8e49 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -43,6 +43,12 @@ if uname.release:sub(1,4) ~= "5.15" then o.datatype = "uinteger" o.rmempty = false end +if uname.release:sub(1,4) ~= "5.15" then + o = s:option(Value, "mptcp_version", translate("Multipath TCP version")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 0 +end o = s:option(ListValue, "congestion", translate("Congestion Control"),translate("Default is cubic")) local availablecong = sys.exec("sysctl -n net.ipv4.tcp_available_congestion_control | xargs -n1 | sort | xargs") for cong in string.gmatch(availablecong, "[^%s]+") do diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index d7646364d..9eb53107a 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -28,6 +28,7 @@ global_multipath_settings() { config_get mptcp_ndiffports_num_subflows globals mptcp_ndiffports_num_subflows config_get mptcp_rr_cwnd_limited globals mptcp_rr_cwnd_limited config_get mptcp_rr_num_segments globals mptcp_rr_num_segments + config_get mptcp_version globals mptcp_version "0" [ "$multipath" = "enable" ] && multipath_status=1 @@ -44,6 +45,7 @@ global_multipath_settings() { [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qew /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qew /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" [ -z "$mptcp_rr_num_segments" ] || sysctl -qew /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" + [ -z "$mptcp_version" ] || sysctl -qew net.mptcp.mptcp_version="$mptcp_version" elif [ -f /proc/sys/net/mptcp/enabled ]; then sysctl -qew net.mptcp.enabled="$multipath_status" ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null @@ -257,6 +259,7 @@ interface_multipath_settings() { else #echo "Add routes for $ipaddr table $id" [ -n "$ipaddr" ] && ip rule add from $ipaddr table $id pref 0 + ip rule add oif $iface table $id pref 0 ip route replace $network/$netmask dev $iface scope link metric $id 2>&1 >/dev/null ip route replace $network/$netmask dev $iface scope link table $id 2>&1 >/dev/null ip route replace default via $gateway dev $iface table $id 2>&1 >/dev/null @@ -343,6 +346,7 @@ interface_multipath_settings() { EOF else [ -n "$ip6addr" ] && ip -6 rule add from $ip6addr table 6$id pref 0 2>&1 >/dev/null + ip rule add oif $iface table 6$id pref 0 ip -6 route replace $network6/$netmask6 dev $iface scope link metric 6$id 2>&1 >/dev/null ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface table 6$id 2>&1 >/dev/null From cb7c547b00fdf6cf6bacc149683df705c0995c32 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Feb 2022 08:29:08 +0100 Subject: [PATCH 0692/2059] Redirect error for sysupgrade --- luci-app-sysupgrade/root/etc/init.d/sysupgrade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-sysupgrade/root/etc/init.d/sysupgrade b/luci-app-sysupgrade/root/etc/init.d/sysupgrade index 377c67944..9ffc3c537 100755 --- a/luci-app-sysupgrade/root/etc/init.d/sysupgrade +++ b/luci-app-sysupgrade/root/etc/init.d/sysupgrade @@ -11,7 +11,7 @@ start_service() { if [ -f /etc/backup/installed_packages.txt ]; then - if [ "$(opkg -V0 update)" = "" ]; then + if [ "$(opkg -V0 update 2>&1)" = "" ]; then grep "\toverlay" /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg -V0 install rm /etc/backup/installed_packages.txt fi From 275c61de5021f978814fe34a0fb1689da023b62e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Feb 2022 14:10:45 +0100 Subject: [PATCH 0693/2059] Fix stupid error for ipv6 --- omr-6in4/files/etc/init.d/omr-6in4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-6in4/files/etc/init.d/omr-6in4 b/omr-6in4/files/etc/init.d/omr-6in4 index 5bec94c02..8a3e38a38 100755 --- a/omr-6in4/files/etc/init.d/omr-6in4 +++ b/omr-6in4/files/etc/init.d/omr-6in4 @@ -73,7 +73,7 @@ set_ipv6_state() { unbound.ub_main.protocol='mixed' commit unbound EOF - if [ "$(network.lan.ip6assign)" = "" ]; then + if [ "$(uci -q get network.lan.ip6assign)" = "" ]; then uci -q set network.lan.ip6assign='60' fi if [ "$(uci -q get network.globals.ula_prefix)" = "" ]; then From 1b3fc8b4a2b9d55e36034e1ea44bb0dbdcddd4a2 Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 9 Jul 2021 11:17:58 +0000 Subject: [PATCH 0694/2059] Translated using Weblate (French) Currently translated at 100.0% (287 of 287 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/fr/ --- luci-app-openmptcprouter/po/fr/openmptcprouter.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/po/fr/openmptcprouter.po b/luci-app-openmptcprouter/po/fr/openmptcprouter.po index 001127345..5e5a8d056 100644 --- a/luci-app-openmptcprouter/po/fr/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/fr/openmptcprouter.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-06-01 06:35+0000\n" +"PO-Revision-Date: 2021-07-10 11:51+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -87,7 +87,7 @@ msgstr "Type d'authentification" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 msgid "Backup" -msgstr "Sauvegarder" +msgstr "Remplaçant" #: luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua:21 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:10 From 68b7d0f6d555394b2dc2376a605cad3715cd4cf5 Mon Sep 17 00:00:00 2001 From: antrouter Date: Mon, 10 Jan 2022 10:09:49 +0000 Subject: [PATCH 0695/2059] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (287 of 287 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/zh_Hans/ --- luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po index e8827e0ff..7bcec9785 100644 --- a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-06-02 09:51+0000\n" +"PO-Revision-Date: 2022-01-11 10:52+0000\n" "Last-Translator: antrouter \n" "Language-Team: Chinese (Simplified) \n" @@ -113,7 +113,7 @@ msgstr "默认情况下,VPN用于非TCP的任何流量." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." -msgstr "默认情况下,代理用于任何TCP(对于V2Ray是UDP)流量。" +msgstr "默认情况下,仅代理TCP(如果选用V2Ray则代理TCP跟UDP还有ICMP任何)流量。" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "CHAP" @@ -946,9 +946,7 @@ msgstr "将服务器设置为主服务器" msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." -msgstr "" -"设置启用ShadowSocks时用于TCP的默认代理,启用V2Ray时设置用于TCP和UDP的默认代" -"理." +msgstr "启用ShadowSocks时用于默认代理TC流量,启用V2Ray时用于默认代理TCP和UDP还有ICMP任何流量." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 msgid "" @@ -1098,7 +1096,7 @@ msgstr "V2Ray没有运行" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 msgid "V2Ray is used for TCP and UDP." -msgstr "V2Ray用于TCP和UDP传输." +msgstr "V2Ray用于TCP和UDP代理." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 msgid "V2Ray user" From 7c1298438973f649890337a4918f767841fc330d Mon Sep 17 00:00:00 2001 From: Riccardo Tornesello Date: Thu, 10 Feb 2022 13:22:11 +0000 Subject: [PATCH 0696/2059] Translated using Weblate (Italian) Currently translated at 16.1% (5 of 31 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-tracker Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-tracker/it/ --- luci-app-omr-tracker/po/it/omr-tracker.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-omr-tracker/po/it/omr-tracker.po b/luci-app-omr-tracker/po/it/omr-tracker.po index 4257d56b1..eed54997d 100644 --- a/luci-app-omr-tracker/po/it/omr-tracker.po +++ b/luci-app-omr-tracker/po/it/omr-tracker.po @@ -1,18 +1,18 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-09-21 12:51+0000\n" -"Last-Translator: Weblate Admin \n" +"PO-Revision-Date: 2022-02-11 13:53+0000\n" +"Last-Translator: Riccardo Tornesello \n" "Language-Team: Italian \n" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 msgid "Add" -msgstr "" +msgstr "Aggiungi" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 From 694505d82f63be0964407c2922829d3a0fa3df8b Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:24:09 +0000 Subject: [PATCH 0697/2059] Translated using Weblate (French) Currently translated at 100.0% (287 of 287 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/fr/ --- luci-app-openmptcprouter/po/fr/openmptcprouter.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/po/fr/openmptcprouter.po b/luci-app-openmptcprouter/po/fr/openmptcprouter.po index 5e5a8d056..5f1b0670d 100644 --- a/luci-app-openmptcprouter/po/fr/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/fr/openmptcprouter.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-07-10 11:51+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -112,7 +112,7 @@ msgstr "Passerelle" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 msgid "Bridge can't have multipath enabled" -msgstr "Un pont ne peut avoir multipath d'activer" +msgstr "Les passerelles ne peuvent pas utiliser le protocole multipath" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 msgid "By default VPN is used for any traffic that is not TCP." From caac50e2e5644c0b778f3024da825b39b7380375 Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:25:11 +0000 Subject: [PATCH 0698/2059] Translated using Weblate (French) Currently translated at 100.0% (20 of 20 strings) Translation: OpenMPTCProuter/LuCI/applications/iperf Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsiperf/fr/ --- luci-app-iperf/po/fr/iperf.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-iperf/po/fr/iperf.po b/luci-app-iperf/po/fr/iperf.po index 6057249da..711692095 100644 --- a/luci-app-iperf/po/fr/iperf.po +++ b/luci-app-iperf/po/fr/iperf.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-05-21 19:20+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -74,7 +74,7 @@ msgstr "Vitesse souhaitée (Mbits/s)" #: luci-app-iperf/luasrc/view/iperf/test.htm:169 msgid "Test" -msgstr "Teste" +msgstr "Essai" #: luci-app-iperf/luasrc/view/iperf/test.htm:100 msgid "This iPerf interface is in bêta. No support for this." From b1648820cd0a6269db15a7292481fd0d6152fd54 Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:25:11 +0000 Subject: [PATCH 0699/2059] Translated using Weblate (French) Currently translated at 100.0% (54 of 54 strings) Translation: OpenMPTCProuter/LuCI/applications/mptcp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsmptcp/fr/ --- luci-app-mptcp/po/fr/mptcp.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/luci-app-mptcp/po/fr/mptcp.po b/luci-app-mptcp/po/fr/mptcp.po index 146ec4466..0901267ce 100644 --- a/luci-app-mptcp/po/fr/mptcp.po +++ b/luci-app-mptcp/po/fr/mptcp.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.5.2\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" @@ -44,7 +44,7 @@ msgstr "Contrôle de la congestion" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 msgid "Consecutive segments that should be sent for round robin" -msgstr "" +msgstr "Segments consécutifs à envoyer pour round robin" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 @@ -77,7 +77,7 @@ msgstr "Connexions établies" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 msgid "Fill the congestion window on all subflows for round robin" -msgstr "" +msgstr "Remplir la fenêtre de congestion de tous les sous-flux pour round robin" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 msgid "Fullmesh subflows for each pair of IP addresses" @@ -215,7 +215,7 @@ msgstr "Paramètres" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 msgid "Test" -msgstr "" +msgstr "Essai" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" From 70cbf743f038ef74c668b5ac86ebbd0e9f8df7df Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:23:28 +0000 Subject: [PATCH 0700/2059] Translated using Weblate (French) Currently translated at 100.0% (23 of 23 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-bypass Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-bypass/fr/ --- luci-app-omr-bypass/po/fr/omr-bypass.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-omr-bypass/po/fr/omr-bypass.po b/luci-app-omr-bypass/po/fr/omr-bypass.po index 272fe4b31..0e9543bdf 100644 --- a/luci-app-omr-bypass/po/fr/omr-bypass.po +++ b/luci-app-omr-bypass/po/fr/omr-bypass.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.5.2\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 @@ -94,7 +94,7 @@ msgstr "Ports de destination" #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 msgid "Ports source" -msgstr "" +msgstr "Ports source" #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 msgid "Protocol/Service" From d82263d5ca01d8939d3724e4797e365725741472 Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:24:17 +0000 Subject: [PATCH 0701/2059] Translated using Weblate (French) Currently translated at 100.0% (34 of 34 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-dscp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-dscp/fr/ --- luci-app-omr-dscp/po/fr/omr-dscp.po | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/luci-app-omr-dscp/po/fr/omr-dscp.po b/luci-app-omr-dscp/po/fr/omr-dscp.po index 8ab04ac95..a7389d8f3 100644 --- a/luci-app-omr-dscp/po/fr/omr-dscp.po +++ b/luci-app-omr-dscp/po/fr/omr-dscp.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.5.2\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 @@ -36,15 +36,15 @@ msgstr "CS3 - SIP" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 msgid "CS4 - Real-Time Interactive" -msgstr "" +msgstr "CS4 - Temps réel interactif" #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 msgid "CS5 - Broadcast Video" -msgstr "" +msgstr "CS5 - Diffusion vidéo" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 msgid "CS5 - Broadcast video" -msgstr "" +msgstr "CS5 - Diffusion vidéo" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 @@ -54,7 +54,7 @@ msgstr "CS6 - Routage réseau" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 msgid "CS7 - Latency sensitive" -msgstr "" +msgstr "CS7 - Sensible à la latence" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 @@ -116,7 +116,7 @@ msgstr "EF - Voix" #: luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json:3 msgid "Grant UCI access for luci-app-dscp" -msgstr "" +msgstr "Permettre l'accès pour luci-app-dscp" #: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 #: luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json:3 From 1daa1f897c2555b2424c937918e41f1e4cce5fa9 Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:21:45 +0000 Subject: [PATCH 0702/2059] Translated using Weblate (French) Currently translated at 100.0% (12 of 12 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-quota Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-quota/fr/ --- luci-app-omr-quota/po/fr/omr-quota.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-omr-quota/po/fr/omr-quota.po b/luci-app-omr-quota/po/fr/omr-quota.po index a7af2a13a..e67782587 100644 --- a/luci-app-omr-quota/po/fr/omr-quota.po +++ b/luci-app-omr-quota/po/fr/omr-quota.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.5.2\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 msgid "Add" @@ -23,7 +23,7 @@ msgstr "Activer" #: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 msgid "Grant UCI access for luci-app-omr-quota" -msgstr "" +msgstr "Permettre l'accès à luci-app-omr-quota" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" From b43aa89c61b528279bb077cca42bb9e55414aab4 Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:23:57 +0000 Subject: [PATCH 0703/2059] Translated using Weblate (French) Currently translated at 100.0% (21 of 21 strings) Translation: OpenMPTCProuter/LuCI/applications/glorytun-tcp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/glorytun-tcp/fr/ --- luci-app-glorytun-tcp/po/fr/glorytun-tcp.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po index 8fac07bca..977d4d7e7 100644 --- a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po +++ b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.5.2\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:32 msgid "Advanced Settings" @@ -89,7 +89,7 @@ msgstr "Serveur" #: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:73 msgid "Timeout" -msgstr "Temporisation" +msgstr "Hors Délais" #: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 msgid "chacha" From 5219d7ab2c8699543a290f0a8bf346109088ea7b Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:21:56 +0000 Subject: [PATCH 0704/2059] Translated using Weblate (French) Currently translated at 100.0% (18 of 18 strings) Translation: OpenMPTCProuter/LuCI/applications/mlvpn Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsmlvpn/fr/ --- luci-app-mlvpn/po/fr/mlvpn.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-mlvpn/po/fr/mlvpn.po b/luci-app-mlvpn/po/fr/mlvpn.po index f7ef82ca8..97c7d305e 100644 --- a/luci-app-mlvpn/po/fr/mlvpn.po +++ b/luci-app-mlvpn/po/fr/mlvpn.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.5.2\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:32 msgid "Advanced Settings" @@ -20,7 +20,7 @@ msgstr "Client" #: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:75 msgid "Disable encryption" -msgstr "" +msgstr "Désactiver le chiffrement" #: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:34 msgid "Enabled" From 8a4ac3e1e62689d972981ffdffe581d46c649e7f Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:25:08 +0000 Subject: [PATCH 0705/2059] Translated using Weblate (French) Currently translated at 94.8% (37 of 39 strings) Translation: OpenMPTCProuter/LuCI/applications/snmpd Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationssnmpd/fr/ --- luci-app-snmpd/po/fr/snmpd.po | 38 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/luci-app-snmpd/po/fr/snmpd.po b/luci-app-snmpd/po/fr/snmpd.po index 976057fbf..7efb48a42 100644 --- a/luci-app-snmpd/po/fr/snmpd.po +++ b/luci-app-snmpd/po/fr/snmpd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-05-21 19:20+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -57,7 +57,7 @@ msgstr "" #: luci-app-snmpd/luasrc/view/snmpd.htm:21 #: luci-app-snmpd/luasrc/view/snmpd.htm:48 msgid "General" -msgstr "" +msgstr "Général" #: luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json:3 msgid "Grant UCI access for luci-app-snmpd" @@ -80,11 +80,11 @@ msgstr "Interface" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:101 msgid "Level" -msgstr "" +msgstr "Niveau" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:22 msgid "Location" -msgstr "" +msgstr "Localisation" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:24 #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:137 @@ -97,11 +97,11 @@ msgstr "Réseaux" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:116 msgid "Notify" -msgstr "" +msgstr "Notifier" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:136 msgid "ObjectID" -msgstr "" +msgstr "ObjectID" #: luci-app-snmpd/luasrc/view/snmpd.htm:55 #: luci-app-snmpd/luasrc/view/snmpd.htm:90 @@ -110,7 +110,7 @@ msgstr "Interface de sortie" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:138 msgid "Program" -msgstr "" +msgstr "Programme" #: luci-app-snmpd/luasrc/view/snmpd.htm:85 #: luci-app-snmpd/luasrc/view/snmpd.htm:89 @@ -119,28 +119,28 @@ msgstr "Protocoles" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:106 msgid "Read" -msgstr "" +msgstr "Lecture" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:34 #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:69 msgid "Read-only" -msgstr "" +msgstr "Lecture Seule" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:35 #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:70 msgid "Read-write" -msgstr "" +msgstr "Lecture-écriture" #: luci-app-snmpd/luasrc/controller/snmpd.lua:6 #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:4 #: luci-app-snmpd/luasrc/view/snmpd.htm:19 #: luci-app-snmpd/root/usr/share/luci/menu.d/luci-app-snmpd.json:3 msgid "SNMPd" -msgstr "" +msgstr "SNMPd" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:4 msgid "SNMPd settings interface (Beta)" -msgstr "" +msgstr "Paramètres du protocole SNMPd (Beta)" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:32 msgid "Server" @@ -148,7 +148,7 @@ msgstr "Serveur" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:37 msgid "Source" -msgstr "" +msgstr "Source" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:19 msgid "System" @@ -156,23 +156,23 @@ msgstr "Système" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:111 msgid "Write" -msgstr "" +msgstr "Ecriture" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:92 msgid "any" -msgstr "" +msgstr "Tout" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:104 msgid "auth" -msgstr "" +msgstr "Authentification" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:29 msgid "com2sec security" -msgstr "" +msgstr "com2sec security" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:103 msgid "noauth" -msgstr "" +msgstr "pas d'authentification" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:67 msgid "secname" @@ -181,4 +181,4 @@ msgstr "" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:76 #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:90 msgid "version" -msgstr "" +msgstr "version" From 6af138896469d2d691843b61bd22bf39513e8fd8 Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Fri, 18 Feb 2022 07:25:39 +0000 Subject: [PATCH 0706/2059] Translated using Weblate (French) Currently translated at 100.0% (50 of 50 strings) Translation: OpenMPTCProuter/LuCI/mod/dashboard Translate-URL: http://weblate.openmptcprouter.com/projects/omr/lucimoddashboard/fr/ --- luci-mod-dashboard/po/fr/dashboard.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/luci-mod-dashboard/po/fr/dashboard.po b/luci-mod-dashboard/po/fr/dashboard.po index cdf32c682..ee91c668b 100644 --- a/luci-mod-dashboard/po/fr/dashboard.po +++ b/luci-mod-dashboard/po/fr/dashboard.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-05-31 18:51+0000\n" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -47,11 +47,11 @@ msgstr "Tableau de bord" #: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 msgid "Devices" -msgstr "Appareils" +msgstr "Périphériques" #: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 msgid "Devices Connected" -msgstr "Appareils connectés" +msgstr "Périphériques connectés" #: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 msgid "Down." @@ -71,7 +71,7 @@ msgstr "Version du micrologiciel" #: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 msgid "GHz" -msgstr "Ghz" +msgstr "GHz" #: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 msgid "Grant access to DHCP status display" @@ -83,7 +83,7 @@ msgstr "Permettre l'accès à l'affichage de l'état principal" #: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 msgid "Grant access to the system route status" -msgstr "Permettre l'acces au Status du Routage" +msgstr "Permettre l’accès au status de routage" #: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 msgid "Grant access to wireless status display" @@ -220,4 +220,4 @@ msgstr "non" #: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 #: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 msgid "yes" -msgstr "Oui" +msgstr "oui" From 343eb53b1f7baced0b46c8d9adfaeeb841378f5c Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Sat, 19 Feb 2022 10:19:00 +0000 Subject: [PATCH 0707/2059] Translated using Weblate (German) Currently translated at 53.6% (154 of 287 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/de/ --- .../po/de/openmptcprouter.po | 133 ++++++++---------- 1 file changed, 59 insertions(+), 74 deletions(-) diff --git a/luci-app-openmptcprouter/po/de/openmptcprouter.po b/luci-app-openmptcprouter/po/de/openmptcprouter.po index 58d482708..7efcbe36f 100644 --- a/luci-app-openmptcprouter/po/de/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/de/openmptcprouter.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-10-21 12:55+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2022-02-19 10:30+0000\n" +"Last-Translator: Weblate Admin \n" "Language-Team: German \n" "Language: de\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" @@ -23,10 +23,12 @@ msgstr "Schlüssel 'Dead Simple VPN'" msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" +"Die zweite IP eines Servers kann für Dual-IPv4/IPv6-Server festgelegt " +"werden, wenn WAN-IPv6 eingerichtet ist" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 msgid "API username to retrieve personnalized settings from the server." -msgstr "API Benutzername zum Download der Settings vom Server." +msgstr "API Benutzername zum Download der Einstellungen vom Server." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 msgid "APN" @@ -88,7 +90,7 @@ msgstr "Backup der Router-Einstellungen auf den Server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 msgid "Balancing" -msgstr "" +msgstr "Ausgleich" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:22 msgid "Beta" @@ -96,11 +98,11 @@ msgstr "Beta" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 msgid "Big time difference between the server and the router" -msgstr "" +msgstr "Großer Zeitunterschied zwischen dem Server und dem Router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 msgid "Bridge" -msgstr "" +msgstr "Netzwerkbrücke" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 msgid "Bridge can't have multipath enabled" @@ -113,28 +115,27 @@ msgstr "" "übertragen." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 -#, fuzzy msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" -"IP-Pakete, die nicht TCP sind, werden standardmäßig mit einem VPN-Protokoll " -"übertragen." +"Standard wird TCP Netzwerk Verkehr über Proxy übertragen (Auch UDP für " +"V2Ray)." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "CHAP" -msgstr "" +msgstr "CHAP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 msgid "Can\\'t access and use server part" -msgstr "" +msgstr "Kann Server Teil nicht öffnen und verwenden" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:297 msgid "Can\\'t contact Server Admin Script" -msgstr "" +msgstr "Kann nicht verbinden zum Server Admin Skript" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:287 msgid "Can\\'t get public IP address from ShadowSocks" -msgstr "" +msgstr "Kann keine Public IP Adresse vom ShadowSocks beziehen" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:290 msgid "Can\\'t get public IP address from V2Ray" @@ -142,7 +143,7 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:284 msgid "Can\\'t ping server" -msgstr "" +msgstr "Kann Server nicht pingen" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 msgid "China" @@ -153,20 +154,22 @@ msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." msgstr "" +"Wähle MacVLAN um ein virtuelles Interface basierend auf ein Physikalisches " +"Interface an zu legen." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 msgid "Choose physical interface." -msgstr "" +msgstr "Wähle physikalische Schnittstelle." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:135 msgid "Core temp:" -msgstr "" +msgstr "Kerntemperatur:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 msgid "Country" -msgstr "" +msgstr "Land" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 #, fuzzy @@ -179,22 +182,20 @@ msgid "DHCP" msgstr "DHCP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 -#, fuzzy msgid "DHCPv6" -msgstr "DHCP" +msgstr "DHCPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:188 msgid "DNS issue: can\\'t resolve hostname" -msgstr "" +msgstr "DNS Problem: Hostnamen nicht beziehbar" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 msgid "Debug" -msgstr "" +msgstr "Debug" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 -#, fuzzy msgid "Default Proxy" -msgstr "Standard VPN" +msgstr "Standard Proxy" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 msgid "Default VPN" @@ -209,7 +210,7 @@ msgstr "Löschen" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 msgid "Device" -msgstr "" +msgstr "Gerät" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 #, fuzzy @@ -232,13 +233,12 @@ msgstr "" "Abschalten von TCP-Fast-Open für Linux und die ShadowsSocks-Einstellungen" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 -#, fuzzy msgid "Disable default gateway" -msgstr "Gateway-Ping aus" +msgstr "Default Gateway aus" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 msgid "Disable default gateway, no internet if VPS are down" -msgstr "" +msgstr "Default Gateway aus, kein Internet wenn VPS down ist" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:193 msgid "Disable external check" @@ -254,13 +254,12 @@ msgid "Disable gateway ping check in status page" msgstr "Gateway-Ping Statusüberprüfung aus" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 -#, fuzzy msgid "Disable interfaces auto rename" -msgstr "Externe Prüfung aus" +msgstr "Automatische Umbenennung von Interfaces deaktivieren" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 msgid "Disable multipath test using tracebox" -msgstr "" +msgstr "Deaktiviere multipath Test mittels Tracebox" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 #, fuzzy @@ -277,9 +276,8 @@ msgid "" msgstr "Portweiterleitungen in der Server-Firewall zu diesem Router abschalten" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 -#, fuzzy msgid "Disable renaming interfaces" -msgstr "Bezeichnung der Schnittstelle" +msgstr "Umbenennung der Schnittstelle deaktivieren" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 @@ -288,14 +286,12 @@ msgid "Disable route loop detection" msgstr "Server-Ping aus" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 -#, fuzzy msgid "Disable server" -msgstr "Server-Ping aus" +msgstr "Server deaktivieren" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 -#, fuzzy msgid "Disable server http test" -msgstr "Server-Ping aus" +msgstr "Server-http-Test aus" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 msgid "Disable server ping" @@ -306,15 +302,14 @@ msgid "Disable server ping status check" msgstr "Server-Ping Status-Prüfung aus" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 -#, fuzzy msgid "Disable tracebox test" -msgstr "Externe Prüfung aus" +msgstr "Deaktiviere tracebox Test" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 msgid "Disabled" -msgstr "" +msgstr "inaktiv" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 msgid "Download speed (Kb/s)" @@ -351,13 +346,12 @@ msgid "Enable ShadowSocks Obfuscating" msgstr "Shadowsocks-Verschleierung aktiv" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:213 -#, fuzzy msgid "Enable TCP Low Latency" -msgstr "TCP-Fast-Open aus" +msgstr "Aktiviere TCP Low Latency" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 msgid "Enable debug logs" -msgstr "" +msgstr "Aktiviere debug Logs" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 @@ -370,31 +364,30 @@ msgid "Encryption" msgstr "Verschlüsselung" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 -#, fuzzy msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." -msgstr "Verschlüsselungverfahren wird ebenfalls für Glorytun genutzt." +msgstr "" +"Verschlüsselungverfahren wird verwendet für Shadowsocks, V2Ray, Glorytun " +"and OpenVPN." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:176 msgid "Filesystem is readonly" -msgstr "" +msgstr "Filesystem ist nur lesen" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 -#, fuzzy msgid "Force retrieve all keys from server." -msgstr "API Benutzername zum Download der Settings vom Server." +msgstr "Erzwingen alle Schlüssel vom Server runter zu laden." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 -#, fuzzy msgid "Force retrieve settings" -msgstr "Server-Einstellungen" +msgstr "Erzwingen Einstellungen runter zu laden." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "GPRS only" -msgstr "" +msgstr "Nur GPRS" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 @@ -472,15 +465,13 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 -#, fuzzy msgid "IPv6 address" -msgstr "IPv4-Adresse" +msgstr "IPv6-Adresse" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 -#, fuzzy msgid "IPv6 gateway" -msgstr "IPv4-Standardgateway" +msgstr "IPv6-Standardgateway" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 @@ -488,9 +479,8 @@ msgid "IPv6 route received" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 -#, fuzzy msgid "IPv6 settings" -msgstr "VPN-Einstellungen" +msgstr "IPv6-Einstellungen" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:209 msgid "IPv6 tunnel DOWN" @@ -637,7 +627,7 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 msgid "Multipath TCP" -msgstr "" +msgstr "Multipath-TCP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 @@ -790,7 +780,7 @@ msgstr "Nur eine Verbindung kann als 'primär' definiert werden." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 msgid "Only work with Shadowsocks as proxy." -msgstr "" +msgstr "Funktioniert nur mit Shadowsocks als Proxy." #: luci-app-openmptcprouter/root/usr/share/luci/menu.d/luci-app-openmptcprouter.json:3 msgid "OpenMPTCProuter" @@ -802,7 +792,7 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:218 msgid "Optimize for latency instead of bandwidth" -msgstr "" +msgstr "Für niedrige Latenz anstatt für Bandbreite optimieren" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 @@ -849,11 +839,11 @@ msgstr "Interface hinzufügen" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 msgid "Prefer LTE" -msgstr "" +msgstr "Bevorzuge LTE" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Prefer UMTS" -msgstr "" +msgstr "Bevorzuge UMTS" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 #, fuzzy @@ -921,9 +911,8 @@ msgid "Scaling governor" msgstr "Methode der CPU-Taktung" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 -#, fuzzy msgid "Secondary server IP" -msgstr "Server IPv4" +msgstr "zweite Server IP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 msgid "Select the device you want to base the interface on." @@ -963,9 +952,8 @@ msgid "Server username" msgstr "Server-Benutzername" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 -#, fuzzy msgid "Service Type" -msgstr "Server-Schlüssel" +msgstr "Dienst Typ" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 msgid "Set VPN to use for MPTCP over VPN." @@ -1106,7 +1094,7 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 msgid "Type" -msgstr "" +msgstr "Typ" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 msgid "UBOND can replace Glorytun with connections with same latency" @@ -1176,9 +1164,8 @@ msgid "VLAN" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:184 -#, fuzzy msgid "VPN is not running" -msgstr "VPN-Einstellungen" +msgstr "VPN läuft nicht" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "VPN settings" @@ -1313,7 +1300,7 @@ msgstr "Statische Adresse" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 msgid "latency:" -msgstr "" +msgstr "Latenz:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 @@ -1352,14 +1339,12 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 -#, fuzzy msgid "wan address:" -msgstr "Statische Adresse" +msgstr "öffentliche IP Adresse:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 -#, fuzzy msgid "wan ipv6 address:" -msgstr "Statische Adresse" +msgstr "öffentliche ipv6 Adresse:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 From 644705d89b0ded03ec7bab0947c6594a16c8347a Mon Sep 17 00:00:00 2001 From: Weblate Admin Date: Sat, 19 Feb 2022 10:25:05 +0000 Subject: [PATCH 0708/2059] Translated using Weblate (Italian) Currently translated at 92.6% (266 of 287 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/it/ --- .../po/it/openmptcprouter.po | 107 ++++++++---------- 1 file changed, 45 insertions(+), 62 deletions(-) diff --git a/luci-app-openmptcprouter/po/it/openmptcprouter.po b/luci-app-openmptcprouter/po/it/openmptcprouter.po index 1d7926872..6d4ddf076 100644 --- a/luci-app-openmptcprouter/po/it/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/it/openmptcprouter.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-01 17:19+0000\n" -"Last-Translator: Giuseppe Dipierro \n" +"PO-Revision-Date: 2022-02-19 10:30+0000\n" +"Last-Translator: Weblate Admin \n" "Language-Team: Italian \n" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" @@ -23,6 +23,8 @@ msgstr "Chiave Dead Simple VPN" msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" +"Può essere impostato un secondo IP per il doppio server IPv4/IPv6 se è stato " +"impostato il server WAN IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 msgid "API username to retrieve personnalized settings from the server." @@ -106,7 +108,7 @@ msgstr "Ponte" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 msgid "Bridge can't have multipath enabled" -msgstr "" +msgstr "Il Bridge non può avere il multipath abilitato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 msgid "By default VPN is used for any traffic that is not TCP." @@ -138,9 +140,8 @@ msgid "Can\\'t get public IP address from ShadowSocks" msgstr "Impossibile ottenere un indirizzo IP pubblico da ShadowSocks" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:290 -#, fuzzy msgid "Can\\'t get public IP address from V2Ray" -msgstr "Impossibile ottenere un indirizzo IP pubblico da ShadowSocks" +msgstr "Impossibile ottenere un indirizzo IP pubblico da V2Ray" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:284 msgid "Can\\'t ping server" @@ -148,7 +149,7 @@ msgstr "Impossibile eseguire il ping del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 msgid "China" -msgstr "" +msgstr "Cina" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 msgid "" @@ -170,12 +171,11 @@ msgstr "Temp. Nucleo:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 msgid "Country" -msgstr "" +msgstr "Nazione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 -#, fuzzy msgid "Country settings" -msgstr "Impostazioni del router" +msgstr "Impostazioni nazionali del router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 @@ -183,9 +183,8 @@ msgid "DHCP" msgstr "DHCP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 -#, fuzzy msgid "DHCPv6" -msgstr "DHCP" +msgstr "DHCPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:188 msgid "DNS issue: can\\'t resolve hostname" @@ -215,15 +214,13 @@ msgid "Device" msgstr "Dispositivo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 -#, fuzzy msgid "Disable HTTP test on Server API in status page" -msgstr "Disabilitare il controllo dello stato del ping del server" +msgstr "Disabilitare il test HTTP sulle API Server nella pagina di stato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 -#, fuzzy msgid "Disable ModemManager" -msgstr "ModemManager" +msgstr "Disabilita ModemManager" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:203 msgid "Disable TCP Fast Open" @@ -251,24 +248,20 @@ msgid "Disable gateway ping" msgstr "Disabilita il ping del gateway" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 -#, fuzzy msgid "Disable gateway ping check in status page" -msgstr "Disabilitare il controllo dello stato del ping del gateway" +msgstr "Disabilita il controllo del ping del gateway nella pagina di stato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 -#, fuzzy msgid "Disable interfaces auto rename" -msgstr "Disabilita il test Tracebox" +msgstr "Disabilita auto rinomina interfacce" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 msgid "Disable multipath test using tracebox" msgstr "Disabilita il test multipath usando tracebox" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 -#, fuzzy -#| msgid "Disabled" msgid "Disable nDPI" -msgstr "Disabilitato" +msgstr "Disabilita nDPI" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 msgid "Disable nDPI, used for protocols in OMR-ByPass" @@ -282,9 +275,8 @@ msgstr "" "a questo router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 -#, fuzzy msgid "Disable renaming interfaces" -msgstr "Etichetta per l'interfaccia" +msgstr "Disabilita rinomina interfaccia" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 @@ -297,9 +289,8 @@ msgid "Disable server" msgstr "Disabilita il server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 -#, fuzzy msgid "Disable server http test" -msgstr "Disabilita il ping del server" +msgstr "Disabilita http test server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 msgid "Disable server ping" @@ -329,12 +320,11 @@ msgstr "Cambiamento dinamico" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 msgid "Enable Bridge Acceleration" -msgstr "" +msgstr "Abilita Accelerazione modalità Bridge" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 -#, fuzzy msgid "Enable DNS64" -msgstr "Abilita MQ" +msgstr "Abilita DNS64" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 msgid "Enable Fast Patch offloading for connections" @@ -383,7 +373,7 @@ msgstr "Il filesystem è di sola lettura" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 msgid "For China, set an accessible DNS and disable DNSSEC." -msgstr "" +msgstr "Per la Cina, imposta un DNS accessibile e disabilita DNSSEC." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 msgid "Force retrieve all keys from server." @@ -403,9 +393,8 @@ msgid "Gateway DOWN" msgstr "Tipi di pagamento" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 -#, fuzzy msgid "Gateway IPv6 DOWN" -msgstr "Tipi di pagamento" +msgstr "Gateway IPv6 SPENTO" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "Glorytun TCP is used by default for UDP and ICMP" @@ -475,15 +464,13 @@ msgstr "Prefisso IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 -#, fuzzy msgid "IPv6 address" -msgstr "Indirizzi IPv4" +msgstr "Indirizzi IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 -#, fuzzy msgid "IPv6 gateway" -msgstr "Gateway IPv4" +msgstr "Gateway IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 @@ -504,7 +491,7 @@ msgstr "IPv6:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 msgid "If host support NAT64, you can enable DNS64 support." -msgstr "" +msgstr "Se l'host supporta NAT64, puoi abilitare il supporto DNS64." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 msgid "Interfaces settings" @@ -588,15 +575,16 @@ msgid "MPTCP over VPN" msgstr "MPTCP su VPN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 -#, fuzzy msgid "MPTCP over VPN settings" -msgstr "MPTCP su VPN" +msgstr "Impostazioni MPTCP su VPN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." msgstr "" +"MPTCP su VPN deve essere usato solo quando il Multipath TCP è bloccatp su " +"una connessione." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 msgid "MacVLAN" @@ -650,7 +638,7 @@ msgstr "Lo stato corrente di Multipath è" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 msgid "Multipath master already defined" -msgstr "Multipath master già definito" +msgstr "Multipath principale già definito" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 @@ -666,9 +654,8 @@ msgid "NONE" msgstr "NESSUNO" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 -#, fuzzy msgid "Network interface MAC address duplicated" -msgstr "Interfaccia di rete duplicata" +msgstr "Interfaccia di rete con MAC address duplicata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 @@ -676,9 +663,8 @@ msgid "Network interface duplicated" msgstr "Interfaccia di rete duplicata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 -#, fuzzy msgid "Network interface not in WAN firewall zone" -msgstr "Interfaccia di rete duplicata" +msgstr "Interfaccia di rete non in WAN firewall zone" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 @@ -699,18 +685,17 @@ msgid "No IPv6 access" msgstr "Nessun accesso IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 -#, fuzzy msgid "No Server http response after 1 second" -msgstr "Nessuna risposta al ping del server dopo 1 secondo" +msgstr "Nessuna risposta dal server HTTP dopo 1 secondo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 msgid "No Server ping response after 1 second" -msgstr "Nessuna risposta al ping del server dopo 1 secondo" +msgstr "Nessuna risposta al ping dal server dopo 1 secondo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 msgid "No WAN with multipath enabled:" -msgstr "" +msgstr "Nessuna WAN con multipath abilitata:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:26 msgid "No available backup on server." @@ -735,14 +720,12 @@ msgid "No output" msgstr "Nessun output" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:293 -#, fuzzy msgid "No public IP address detected in less than 1 second" -msgstr "Nessun indirizzo IP WAN rilevato in meno di 1 secondo" +msgstr "Nessun indirizzo IP pubblico rilevato in meno di 1 secondo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:267 -#, fuzzy msgid "No server IP address, No public IP address" -msgstr "Nessun indirizzo IP del server, nessun indirizzo IP WAN" +msgstr "Nessun indirizzo IP del server, nessun indirizzo IP pubblico" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:280 msgid "No server defined" @@ -783,13 +766,15 @@ msgstr "Al cambio della procedura guidata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 msgid "Only ShadowSocks is supported with server multiple IPs for now." -msgstr "" +msgstr "Solo ShadowSocks è supportato con server multi IP per adesso." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." msgstr "" +"Solo un' interfaccia può essere impostata come \"Master\", deve essere " +"impostata l'interfaccia più stabile." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 msgid "Only one server can be master, else all servers are set as backup." @@ -799,7 +784,7 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 msgid "Only work with Shadowsocks as proxy." -msgstr "" +msgstr "Funziona solo con Shadowsocks come proxy." #: luci-app-openmptcprouter/root/usr/share/luci/menu.d/luci-app-openmptcprouter.json:3 msgid "OpenMPTCProuter" @@ -861,9 +846,8 @@ msgid "Prefer UMTS" msgstr "Preferisci UMTS" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 -#, fuzzy msgid "Primary server IP" -msgstr "Indirizzo IP del server" +msgstr "IP principale del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 @@ -896,7 +880,7 @@ msgstr "Reindirizza tutte le porte dal server a questo router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 msgid "Reset" -msgstr "" +msgstr "Resetta" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm:32 msgid "Restore backup" @@ -924,9 +908,8 @@ msgid "Scaling governor" msgstr "Governatore in scala" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 -#, fuzzy msgid "Secondary server IP" -msgstr "Indirizzo IP del server" +msgstr "IP secondario del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 msgid "Select the device you want to base the interface on." @@ -968,7 +951,7 @@ msgstr "Tipo di servizio" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 msgid "Set VPN to use for MPTCP over VPN." -msgstr "" +msgstr "Seleziona la VPN da utilizzare per MPTCP su VPN." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 @@ -1225,7 +1208,7 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 msgid "Wizard" -msgstr "Wizard" +msgstr "Procedura guidata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 msgid "World" From 2ea13ecfaa1a2d787d14c32fb29c5740aba3f9e9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 20 Feb 2022 09:04:39 +0100 Subject: [PATCH 0709/2059] Fix status page error abproxy disabled when MPTCP over VPN is used on all interfaces --- .../root/usr/libexec/rpcd/openmptcprouter | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 9c9ab517b..a06035f7f 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1027,7 +1027,7 @@ function interfaces_status() mArray.openmptcprouter["multi_vpn"] = true end end - + -- check Shadowsocks is running mArray.openmptcprouter["shadowsocks_service"] = false if string.find(sys.exec("/usr/bin/pgrep ss-redir"), "%d+") then @@ -1035,10 +1035,16 @@ function interfaces_status() end mArray.openmptcprouter["shadowsocks_enabled"] = true - local ss_server = uci:get("shadowsocks-libev","sss0","disabled") or "0" + local ss_server = "1" + ucic:foreach("shadowsocks-libev", "server", function(s) + if uci:get("shadowsocks-libev",s[".name"],"disabled") == "0" then + ss_server = "0" + end + end) if ss_server == "1" then mArray.openmptcprouter["shadowsocks_enabled"] = false end + -- check V2Ray is running mArray.openmptcprouter["v2ray_service"] = false if string.find(sys.exec("/usr/bin/pgrep v2ray"), "%d+") then From 57c6fbc13f091c7957271776102cb5417aef3f10 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 23 Feb 2022 20:59:59 +0100 Subject: [PATCH 0710/2059] Add milkywan tv in DSCP --- luci-app-omr-dscp/root/etc/config/dscp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/luci-app-omr-dscp/root/etc/config/dscp b/luci-app-omr-dscp/root/etc/config/dscp index ef2ef31f2..310ae3e31 100644 --- a/luci-app-omr-dscp/root/etc/config/dscp +++ b/luci-app-omr-dscp/root/etc/config/dscp @@ -256,3 +256,8 @@ config domains option class 'cs1' option comment 'WindowsUpdate' +config domains + option name 'tv.milkywan.fr' + option class 'cs5' + option comment 'MilkyWan TV' + From 00a1919ad10310b9ac039072f38b61232a9f15d8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 23 Feb 2022 21:00:52 +0100 Subject: [PATCH 0711/2059] Add rutx in github actions build --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ab824216b..a5d283713 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx] OMR_KERNEL: [5.4, 5.15] runs-on: ubuntu-latest continue-on-error: true From 6c08bdbe9f60749a87e596156bd3431d261f607a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 8 Mar 2022 15:47:26 +0100 Subject: [PATCH 0712/2059] Fix omr-tracker --- omr-tracker/files/bin/omr-tracker | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 0799c90ce..910654913 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -85,11 +85,12 @@ _post_tracking() { _log() { logger -t "post-tracking-${tracker_bin##*/}" "$*" } - tmp=$(mktemp) - . "$tracker_bin" 2>&1 > "$tmp" - trackresult=$(< "$tmp") - [ -n "$trackresult" ] && _log $trackresult - rm -f "$tmp" + . "$tracker_bin" 2>&1 + #tmp=$(mktemp) + #. "$tracker_bin" 2>&1 > "$tmp" + #trackresult=$(< "$tmp") + #[ -n "$trackresult" ] && _log $trackresult + #rm -f "$tmp" ) done } From cf15b5161c6d8f76c56e696942694c46e14f110c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 11 Mar 2022 20:05:50 +0100 Subject: [PATCH 0713/2059] Update ModemManger, libmbim and libqmi --- libmbim/Makefile | 4 ++-- libqmi/Makefile | 4 ++-- modemmanager/Makefile | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index 32c8ef493..505ae7bc6 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_VERSION:=1.26.0 +PKG_VERSION:=1.26.2 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/libmbim -PKG_HASH:=1e1f0926b22c77210442129eca689722ecf324ab9c9abf421a5c989f46e813cf +PKG_HASH:=10c77bf5b5eb8c92ba80e9b519923ad9b898362bc8e1928e2bc9a17eeba649af PKG_MAINTAINER:=Nicholas Smith diff --git a/libqmi/Makefile b/libqmi/Makefile index ee5b69749..d3ebdeecd 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqmi -PKG_VERSION:=1.30.2 +PKG_VERSION:=1.30.4 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/libqmi -PKG_HASH:=be01ece0ea2c2194cbea5744bf5aaf06c04ba5fb7ec7887a13116c76d114fedd +PKG_HASH:=00d7da30a4f8d1185f37cba289cfaf1dfcd04a58f2f76d6acfdf5b85312d6ed6 PKG_MAINTAINER:=Nicholas Smith diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 1dbccf127..3eb780398 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_VERSION:=1.18.4 +PKG_VERSION:=1.18.6 PKG_RELEASE:=1 PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager -PKG_HASH:=11fb970f63e2da88df4b6d8759e4ee649944c515244b979bf50a7a6df1d7f199 +PKG_HASH:=d4f804b31cf504239c5f1d4973c62095c00cba1ee9abb503718dac6d146a470a PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION) PKG_MAINTAINER:=Nicholas Smith From eb87da4feb233cc90a6261223d064db408e87f77 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 14 Mar 2022 20:57:38 +0100 Subject: [PATCH 0714/2059] Add network modems configuration for RUTX12 --- .../files/etc/uci-defaults/1920-omr-network | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index c8be3490a..18726e3f0 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -306,6 +306,54 @@ sed -i 's/omrip/oip/g' /etc/config/* uci -q delete network.loopback.ifname uci -q set network.loopback.device='lo' +local board=$(board_name) +if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ] && [ "$(mnf_info -n)" = "RUTX1200XXXX" ]; then + uci -q batch <<-EOF + set network.modem1=interface + set network.modem1.proto='modemmanager' + set network.modem1.apn='' + set network.modem1.auth='none' + set network.modem1.iptype='ipv4v6' + set network.modem1.addlatency='0' + set network.modem1.force_link='1' + set network.modem1.device='/sys/devices/platform/soc/60f8800.usb2/6000000.dwc3/xhci-hcd.1.auto/usb3/3-1' + set network.wan_modem1=interface + set network.wan_modem1.proto='dhcp' + set network.wan_modem1.device='wwan0' + set network.wan_modem1.force_link='1' + set network.wan_modem1.multipath='on' + set network.wan_modem1.addlatency='0' + set network.wan_modem1.hostname='*' + set network.wan_modem1.defaultroute='0' + set network.wan_modem1.peerdns='0' + set network.wan_modem1.ip4table=wan + commit network + add_list firewall.@zone[1].network='wan_modem1' + commit firewall + set network.modem2=interface + set network.modem2.proto='modemmanager' + set network.modem2.apn='' + set network.modem2.auth='none' + set network.modem2.iptype='ipv4v6' + set network.modem2.addlatency='0' + set network.modem2.force_link='1' + set network.modem2.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' + set network.wan_modem2=interface + set network.wan_modem2.proto='dhcp' + set network.wan_modem2.device='wwan1' + set network.wan_modem2.force_link='1' + set network.wan_modem2.multipath='on' + set network.wan_modem2.addlatency='0' + set network.wan_modem2.hostname='*' + set network.wan_modem2.defaultroute='0' + set network.wan_modem2.peerdns='0' + set network.wan_modem2.ip4table=wan + commit network + add_list firewall.@zone[1].network='wan_modem2' + commit firewall + EOF +fi + uci -q commit macvlan uci -q commit network rm -f /tmp/luci-indexcache From a4d9f6dd39fa9bfa7e761085405bc64cafe1eedf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 16 Mar 2022 20:54:34 +0100 Subject: [PATCH 0715/2059] Fix status page when proto is modemmanager --- luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index a06035f7f..f8ac6eca0 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1160,7 +1160,7 @@ function interfaces_status() --end duplicateif = false - if ifname ~= "" and ifname ~= nil and not (section["device"] ~= nil and section["device"]:match("^@.*")) then + if ifname ~= "" and ifname ~= nil and not (section["device"] ~= nil and section["device"]:match("^@.*")) and (proto == "static" or proto == "dhcp") then if allintf[ifname] then connectivity = "ERROR" duplicateif = true From a949d1f55791ccc66ab8f1a443995adb55277561 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 28 Mar 2022 18:29:13 +0200 Subject: [PATCH 0716/2059] Run script for fw only if server defined --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 0e8ca6953..9b5e53d11 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1577,7 +1577,7 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter fi -if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then _log "Set firewall on server" /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 From e3eae6d44ebb78c57aef4c28bd952f51878e5a56 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 29 Mar 2022 19:54:58 +0200 Subject: [PATCH 0717/2059] Check that API give an output before setting fw --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 9c581ea92..6ac763eac 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1140,9 +1140,11 @@ _set_vps_firewall() { username="$(uci -q get openmptcprouter.${fwservername}.username)" settings='{"name" : "redirect router"}' fw_list=$(_set_json "shorewalllist" "$settings") + [ -z "$fw_list" ] && return vpsfwlist=$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d') settings='{"name" : "open router"}' fw_list=$(_set_json "shorewalllist" "$settings") + [ -z "$fw_list" ] && return if [ -n "$vpsfwlist" ]; then vpsfwlist="$vpsfwlist\n$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" else @@ -1150,9 +1152,11 @@ _set_vps_firewall() { fi settings='{"name" : "redirect router","ipproto" : "ipv6"}' fw6_list=$(_set_json "shorewalllist" "$settings") + [ -z "$fw6_list" ] && return vpsfw6list=$(echo $fw6_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d') settings='{"name" : "open router","ipproto" : "ipv6"}' fw6_list=$(_set_json "shorewalllist" "$settings") + [ -z "$fw6_list" ] && return if [ -n "$vpsfw6list" ]; then vpsfw6list="$vpsfw6list\n$(echo $fw6_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" else From af89e81dff7d857fd4b6569dd3d5507e2a9c01bf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 31 Mar 2022 20:16:12 +0200 Subject: [PATCH 0718/2059] Fix wizard page --- .../luasrc/view/openmptcprouter/wizard.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index dafe89a3d..d1a819796 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -428,7 +428,7 @@ <% for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() - local firewall_lan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_lan.network | grep " .. ifname)) + local firewall_lan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_lan.network | grep \'" .. ifname .. "\'")) if firewall_lan ~= "" then %>

    <%=ifname%>

    @@ -531,7 +531,7 @@ <% for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() - local firewall_wan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_wan.network | grep " .. ifname)) + local firewall_wan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_wan.network | grep \'" .. ifname .. "\'")) if firewall_wan ~= "" then -- local multipath = uci:get("network",ifname,"multipath") From 2248e12100c42a0007dca54c732bae43596518cf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Apr 2022 13:24:07 +0200 Subject: [PATCH 0719/2059] Make wizard page faster to display --- .../luasrc/view/openmptcprouter/wizard.htm | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index d1a819796..e447518f4 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -7,9 +7,15 @@ local sys = require "luci.sys" local ut = require "luci.util" local ifaces = sys.net:devices() + local ifttyu = nixio.fs.glob("/dev/ttyUSB*") + local ifttyc = nixio.fs.glob("/dev/cdc-wdm*") menuentry = uci:get("openmptcprouter","settings","menu") or "openmptcprouter" function device_notvirtual(dev) - for _, iface in ipairs(net:get_networks()) do + if dev:match("^eth.*") or dev:match("^wwan.*") or dev:match("^tun.*") or dev:match("/") then + return true + end + networks = net:get_networks() + for _, iface in ipairs(networks) do local ifacen = iface:name() local ifacename = uci:get("network",ifacen,"device") local ifacetype = uci:get("network",ifacen,"type") or "" @@ -428,7 +434,7 @@ <% for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() - local firewall_lan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_lan.network | grep \'" .. ifname .. "\'")) + local firewall_lan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_lan.network | tr ' ' '\n' | grep \'^" .. ifname .. "$\'")) if firewall_lan ~= "" then %>

    <%=ifname%>

    @@ -531,7 +537,7 @@ <% for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() - local firewall_wan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_wan.network | grep \'" .. ifname .. "\'")) + local firewall_wan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_wan.network | tr ' ' '\n' | grep \'^" .. ifname .. "$\'")) if firewall_wan ~= "" then -- local multipath = uci:get("network",ifname,"multipath") @@ -743,14 +749,12 @@ <% iffind=0 - iftty = nixio.fs.glob("/dev/cdc-wdm*") - for tty in iftty do + for tty in ifttyc do %> <% From e959dc316f4bfcb3443ee3e5b0231775318cbd78 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Apr 2022 13:24:30 +0200 Subject: [PATCH 0720/2059] Fix bypass error when device is a path --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 5220f47e2..87878277b 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -511,6 +511,7 @@ _intf_rule() { intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') [ -z "$intf" ] && config_get intf $1 device + [ -n "$(echo $intf | grep '/') " ] && return #count=$((count+1)) config_get count $1 metric local mode From 65a593e90478563e129b4a29c41dad62411a1f1b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Apr 2022 17:34:22 +0200 Subject: [PATCH 0721/2059] No set VPS fw when omr-bypass not defined because it's not related --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 9b5e53d11..45650cf4c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1577,7 +1577,8 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter fi -if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then _log "Set firewall on server" /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 From d525478bc0c2cd27da95348eb37111f46577ec84 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Apr 2022 18:28:16 +0200 Subject: [PATCH 0722/2059] Add RUTX11 modem configuration --- .../files/etc/uci-defaults/1920-omr-network | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 18726e3f0..5c0dfd8a7 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -307,7 +307,8 @@ uci -q delete network.loopback.ifname uci -q set network.loopback.device='lo' local board=$(board_name) -if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ] && [ "$(mnf_info -n)" = "RUTX1200XXXX" ]; then +if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then + # Same part for RUTX12 and RUTX11, maybe other RUTX ? uci -q batch <<-EOF set network.modem1=interface set network.modem1.proto='modemmanager' @@ -332,28 +333,33 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ] && [ "$(mnf_info -n) commit firewall set network.modem2=interface set network.modem2.proto='modemmanager' - set network.modem2.apn='' - set network.modem2.auth='none' - set network.modem2.iptype='ipv4v6' - set network.modem2.addlatency='0' - set network.modem2.force_link='1' - set network.modem2.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' - set network.wan_modem2=interface - set network.wan_modem2.proto='dhcp' - set network.wan_modem2.device='wwan1' - set network.wan_modem2.force_link='1' - set network.wan_modem2.multipath='on' - set network.wan_modem2.addlatency='0' - set network.wan_modem2.hostname='*' - set network.wan_modem2.defaultroute='0' - set network.wan_modem2.peerdns='0' - set network.wan_modem2.ip4table=wan - commit network - add_list firewall.@zone[1].network='wan_modem2' - commit firewall EOF + if [ "$(mnf_info -n)" = "RUTX1200XXXX" ] || ; then + uci -q batch <<-EOF + set network.modem2.apn='' + set network.modem2.auth='none' + set network.modem2.iptype='ipv4v6' + set network.modem2.addlatency='0' + set network.modem2.force_link='1' + set network.modem2.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' + set network.wan_modem2=interface + set network.wan_modem2.proto='dhcp' + set network.wan_modem2.device='wwan1' + set network.wan_modem2.force_link='1' + set network.wan_modem2.multipath='on' + set network.wan_modem2.addlatency='0' + set network.wan_modem2.hostname='*' + set network.wan_modem2.defaultroute='0' + set network.wan_modem2.peerdns='0' + set network.wan_modem2.ip4table=wan + commit network + add_list firewall.@zone[1].network='wan_modem2' + commit firewall + EOF + fi fi + uci -q commit macvlan uci -q commit network rm -f /tmp/luci-indexcache From b8985b8ea814a0dbba31c6457deb5e92d0354cb0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 7 Apr 2022 08:28:41 +0200 Subject: [PATCH 0723/2059] Fix config for RUTX --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 5c0dfd8a7..5ed5603d9 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -331,11 +331,11 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then commit network add_list firewall.@zone[1].network='wan_modem1' commit firewall - set network.modem2=interface - set network.modem2.proto='modemmanager' EOF - if [ "$(mnf_info -n)" = "RUTX1200XXXX" ] || ; then + if [ "$(mnf_info -n)" = "RUTX1200XXXX" ]; then uci -q batch <<-EOF + set network.modem2=interface + set network.modem2.proto='modemmanager' set network.modem2.apn='' set network.modem2.auth='none' set network.modem2.iptype='ipv4v6' From 8b127c63677db7f349fccff57a0c7a9deba4b39d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 11 Apr 2022 20:44:13 +0200 Subject: [PATCH 0724/2059] Force ntp client --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 92e9a5fd3..aef5d9446 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -1,8 +1,15 @@ #!/bin/sh uci -q batch <<-EOF >/dev/null set system.@system[-1].ttylogin=1 + set system.ntp=timeserver set system.ntp.use_dhcp='0' set system.ntp.enable_server='1' + set system.ntp.enabled='1' + del system.ntp.server + add_list system.ntp.server='0.pool.ntp.org' + add_list system.ntp.server='1.pool.ntp.org' + add_list system.ntp.server='2.pool.ntp.org' + add_list system.ntp.server='3.pool.ntp.org' commit system set rpcd.@rpcd[0].timeout=120 commit rpcd From 2d9f9e7fa26ff33fa73fa2941bea0a6879bc1bfe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Apr 2022 19:57:01 +0200 Subject: [PATCH 0725/2059] Change RUTX network configuration (vlan1 & 2 are reserved) --- .../files/etc/uci-defaults/1920-omr-network | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 5ed5603d9..a480d0d12 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -88,6 +88,34 @@ elif [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/c lanif="wan" elif [ -d /sys/class/net/lan ] || [ -n "$(ip link | grep ' lan')" ]; then lanif="lan" +elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ "$(cat /etc/board.json | jsonfilter -q -e '@.model.platform' | tr -d '\n')" = "RUTX" ]; then + lanif="eth1" + uci -q batch <<-EOF + set network.@switch_vlan[0]=switch_vlan + set network.@switch_vlan[0].device='switch0' + set network.@switch_vlan[0].vlan=1 + set network.@switch_vlan[0].ports='1t 2t 3t 4t 0t' + set network.@switch_vlan[1]=switch_vlan + set network.@switch_vlan[1].device='switch0' + set network.@switch_vlan[1].vlan=1 + set network.@switch_vlan[1].ports='5 0' + add network switch_vlan + set network.@switch_vlan[2].device='switch0' + set network.@switch_vlan[2].vlan=3 + set network.@switch_vlan[2].ports='0t 1' + add network switch_vlan + set network.@switch_vlan[3].device='switch0' + set network.@switch_vlan[3].vlan=4 + set network.@switch_vlan[3].ports='0t 2' + add network switch_vlan + set network.@switch_vlan[4].device='switch0' + set network.@switch_vlan[4].vlan=5 + set network.@switch_vlan[4].ports='0t 3' + add network switch_vlan + set network.@switch_vlan[5].device='switch0' + set network.@switch_vlan[5].vlan=6 + set network.@switch_vlan[5].ports='0t 4' + EOF elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ -d '/sys/class/net/eth1.5' ]; then lanif="eth1.5" uci -q batch <<-EOF @@ -131,6 +159,7 @@ set network.lan.proto=static set network.lan.ipaddr=192.168.100.1 set network.lan.netmask=255.255.255.0 set network.lan.device=${lanif} +set network.lan.ifname=${lanif} set network.lan.metric=2048 set network.lan.ipv6=0 set network.lan.delegate=0 @@ -181,6 +210,11 @@ if [ "$(uci -q show network.wan1 | grep multipath)" = "" ] && [ -z "$(uci -q get _setup_wan_interface wan2 eth0 on macvlan _setup_macvlan wan1 _setup_macvlan wan2 + elif [ "$(cat /etc/board.json | jsonfilter -q -e '@.model.platform' | tr -d '\n')" = "RUTX" ]; then + _setup_wan_interface wan1 eth0.3 master + _setup_wan_interface wan2 eth0.4 on + _setup_wan_interface wan3 eth0.5 on + _setup_wan_interface wan4 eth0.6 on elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ]; then _setup_wan_interface wan1 eth0.1 master _setup_wan_interface wan2 eth0.2 on From 3e8c9b87f8800e3e42e16f371c22f28a49a70db4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Apr 2022 19:57:40 +0200 Subject: [PATCH 0726/2059] Add grpcurl package --- grpcurl/Makefile | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 grpcurl/Makefile diff --git a/grpcurl/Makefile b/grpcurl/Makefile new file mode 100644 index 000000000..8bec5ccf4 --- /dev/null +++ b/grpcurl/Makefile @@ -0,0 +1,60 @@ +# +# Copyright (C) 2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=grpcurl +PKG_VERSION:=1.8.6 +PKG_RELEASE:=1 + +PKG_SOURCE:=v$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/fullstorydev/grpcurl/archive/refs/tags/ +PKG_HASH:=18b457f644baabeef0de350596dd8d23563586ee94a3ed3cb290063e097ab934 + +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Yannick Chabanois + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/fullstorydev/grpcurl +GO_PKG_BUILD_PKG:=github.com/fullstorydev/grpcurl/cmd/grpcurl +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG)/constant.Version=$(PKG_VERSION) \ + $(GO_PKG)/constant.Commit=v$(PKG_VERSION) +GO_PKG_LDFLAGS:=-s -w +GO_PKG_TAGS:=master + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/grpcurl + TITLE:=grpcurl is a command-line tool that lets you interact with gRPC servers + URL:=https://github.com/fullstorydev/grpcurl + SECTION:=net + CATEGORY:=Network + DEPENDS:=$(GO_ARCH_DEPENDS) +protobuf +endef + +define Package/grpcurl/description + grpcurl is a command-line tool that lets you interact with gRPC servers. It's basically curl for gRPC servers. + + The main purpose for this tool is to invoke RPC methods on a gRPC server from the command-line. gRPC servers use a binary encoding on the wire (protocol buffers, or "protobufs" for short). So they are basically impossible to interact with using regular curl (and older versions of curl that do not support HTTP/2 are of course non-starters). This program accepts messages using JSON encoding, which is much more friendly for both humans and scripts. +endef + +define Package/v2ray-core/install + $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + + $(INSTALL_DIR) $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/grpcurl $(1)/usr/bin +endef + +$(eval $(call GoBinPackage,grpcurl)) +$(eval $(call BuildPackage,grpcurl)) From 3694172044437fe5c5deaad1e6b4662d1cadbb23 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Apr 2022 08:59:51 +0200 Subject: [PATCH 0727/2059] Fix omr-modemamanger connection type --- luci-app-openmptcprouter/root/bin/omr-modemmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/bin/omr-modemmanager b/luci-app-openmptcprouter/root/bin/omr-modemmanager index b7dc840ba..57115c2e0 100755 --- a/luci-app-openmptcprouter/root/bin/omr-modemmanager +++ b/luci-app-openmptcprouter/root/bin/omr-modemmanager @@ -10,7 +10,7 @@ timeout 1 mmcli -L | while read MODEM; do OPERATOR=$(echo "$MODEM_INFO" | grep 'modem.3gpp.operator-name ' | awk -F": " '{print $2}') NUMBER=$(echo "$MODEM_INFO" | grep 'modem.generic.own-numbders.value[1]' | awk -F": " '{print $2}') STATE=$(echo "$MODEM_INFO" | grep 'modem.generic.state ' | awk -F": " '{print $2}') - TYPE=$(echo "$MODEM_INFO" | grep 'modem.generic.access-technologies.values[1]' | awk -F": " '{print $2}') + TYPE=$(echo "$MODEM_INFO" | grep 'modem.generic.access-technologies.value\[1\]' | awk -F": " '{print $2}') [ -z "$INFO" ] && echo $PERCENT [ "$INFO" = "all" ] && echo "$PERCENT;$OPERATOR;$NUMBER;$STATE;$TYPE" exit From 98b9bcd2314ec52db67144def71a4ca4cbb9604a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Apr 2022 09:00:22 +0200 Subject: [PATCH 0728/2059] Add RUTX12 leds support --- .../share/omr/post-tracking.d/post-tracking | 90 ++++++++++++++++++- .../files/etc/uci-defaults/2060-omr-system | 29 ++++++ 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 45650cf4c..69c64d7b0 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -704,6 +704,95 @@ default_gw6=$(ip -6 route show default | grep -v "metric" | awk '/default/ {prin interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') + +if [ -n "$(grep RUTX /etc/board.json)" ] && [ -n "$OMR_TRACKER_INTERFACE" ]; then + if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.device)" = "wwan0" ]; then + modemdata=$(omr-modemmanager '/sys/devices/platform/soc/60f8800.usb2/6000000.dwc3/xhci-hcd.1.auto/usb3/3-1' all) + gen=$(echo $modemdata | cut -d ';' -f 5 | tr -d '\n') + if [ "$gen" = "gsm" ]; then + echo "default-on" > /sys/class/leds/mob_gen_2/trigger + echo "none" > /sys/class/leds/mob_gen_3/trigger + echo "none" > /sys/class/leds/mob_gen_4/trigger + elif [ "$gen" = "umts" ]; then + echo "none" > /sys/class/leds/mob_gen_2/trigger + echo "default-on" > /sys/class/leds/mob_gen_3/trigger + echo "none" > /sys/class/leds/mob_gen_4/trigger + elif [ "$gen" = "lte" ]; then + echo "none" > /sys/class/leds/mob_gen_2/trigger + echo "none" > /sys/class/leds/mob_gen_3/trigger + echo "default-on" > /sys/class/leds/mob_gen_4/trigger + fi + bar=$(echo $modemdata | cut -d ';' -f 1 | tr -d '\n') + if [ "$bar" -gt "0" ]; then + echo "default-on" > /sys/class/leds/mob_ssid_1/trigger + else + echo "none" > /sys/class/leds/mob_ssid_1/trigger + fi + if [ "$bar" -gt "30" ]; then + echo "default-on" > /sys/class/leds/mob_ssid_2/trigger + else + echo "none" > /sys/class/leds/mob_ssid_2/trigger + fi + if [ "$bar" -gt "50" ]; then + echo "default-on" > /sys/class/leds/mob_ssid_3/trigger + else + echo "none" > /sys/class/leds/mob_ssid_3/trigger + fi + if [ "$bar" -gt "70" ]; then + echo "default-on" > /sys/class/leds/mob_ssid_4/trigger + else + echo "none" > /sys/class/leds/mob_ssid_4/trigger + fi + if [ "$bar" -gt "90" ]; then + echo "default-on" > /sys/class/leds/mob_ssid_5/trigger + else + echo "none" > /sys/class/leds/mob_ssid_5/trigger + fi + elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.device)" = "wwan1" ]; then + modemdata=$(omr-modemmanager '/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' all) + gen=$(echo $modemdata | cut -d ';' -f 5 | tr -d '\n') + if [ "$gen" = "gsm" ]; then + echo "default-on" > /sys/class/leds/mob2_gen_2/trigger + echo "none" > /sys/class/leds/mob2_gen_3/trigger + echo "none" > /sys/class/leds/mob2_gen_4/trigger + elif [ "$gen" = "umts" ]; then + echo "none" > /sys/class/leds/mob2_gen_2/trigger + echo "default-on" > /sys/class/leds/mob2_gen_3/trigger + echo "none" > /sys/class/leds/mob2_gen_4/trigger + elif [ "$gen" = "lte" ]; then + echo "none" > /sys/class/leds/mob2_gen_2/trigger + echo "none" > /sys/class/leds/mob2_gen_3/trigger + echo "default-on" > /sys/class/leds/mob2_gen_4/trigger + fi + bar=$(echo $modemdata | cut -d ';' -f 1 | tr -d '\n') + if [ "$bar" -gt "0" ]; then + echo "default-on" > /sys/class/leds/mob2_ssid_1/trigger + else + echo "none" > /sys/class/leds/mob2_ssid_1/trigger + fi + if [ "$bar" -gt "30" ]; then + echo "default-on" > /sys/class/leds/mob2_ssid_2/trigger + else + echo "none" > /sys/class/leds/mob2_ssid_2/trigger + fi + if [ "$bar" -gt "50" ]; then + echo "default-on" > /sys/class/leds/mob2_ssid_3/trigger + else + echo "none" > /sys/class/leds/mob2_ssid_3/trigger + fi + if [ "$bar" -gt "70" ]; then + echo "default-on" > /sys/class/leds/mob2_ssid_4/trigger + else + echo "none" > /sys/class/leds/mob2_ssid_4/trigger + fi + if [ "$bar" -gt "90" ]; then + echo "default-on" > /sys/class/leds/mob2_ssid_5/trigger + else + echo "none" > /sys/class/leds/mob2_ssid_5/trigger + fi + fi +fi + # An interface in error will never be used in MPTCP if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then @@ -1576,7 +1665,6 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter sleep 5 fi - #if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then _log "Set firewall on server" diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index aef5d9446..579452b5d 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -38,6 +38,35 @@ fi EOF } +if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" ]; then + uci -q batch <<-EOF >/dev/null + add system led + set system.@led[-1].sysfs='wan_wifi_4' + set system.@led[-1].name='WAN_ETH' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='eth0' + set system.@led[-1].mode='tx' 'rx' + add system led + set system.@led[-1].sysfs='wan_eth_3' + set system.@led[-1].name='WAN_WIFI' + set system.@led[-1].trigger='netdev' + set system.@led[-1].mode='tx' 'rx' + add system led + set system.@led[-1].sysfs='wan_sim_1' + set system.@led[-1].name='WAN_MODEM1' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='wwan0' + set system.@led[-1].mode='rx' + add system led + set system.@led[-1].name='WAN_MODEM2' + set system.@led[-1].sysfs='wan_sim_2' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='wwan1' + set system.@led[-1].mode='rx' + commit system + EOF +fi + #sed -i 's/^\tlogger -t/\t[ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] \&\& logger -t/g' /usr/share/ModemManager/modemmanager.common exit 0 \ No newline at end of file From 31140cceec35c6467a95ce4cf00d091f86b0479d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Apr 2022 10:48:19 +0200 Subject: [PATCH 0729/2059] Fix typo --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index a480d0d12..c3ec17ce6 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -97,8 +97,8 @@ elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ "$(cat /etc/board.jso set network.@switch_vlan[0].ports='1t 2t 3t 4t 0t' set network.@switch_vlan[1]=switch_vlan set network.@switch_vlan[1].device='switch0' - set network.@switch_vlan[1].vlan=1 - set network.@switch_vlan[1].ports='5 0' + set network.@switch_vlan[1].vlan=2 + set network.@switch_vlan[1].ports='0 5' add network switch_vlan set network.@switch_vlan[2].device='switch0' set network.@switch_vlan[2].vlan=3 From c4c90ed46c33a4479479509b0c2c6729c3cd08f5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Apr 2022 15:24:25 +0200 Subject: [PATCH 0730/2059] Add wifi interfaces and wifi leds for RUTX12 --- .../files/etc/uci-defaults/1920-omr-network | 13 ++++++++++++ .../files/etc/uci-defaults/2060-omr-system | 20 +++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index c3ec17ce6..0925c70cc 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -391,6 +391,19 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then commit firewall EOF fi + uci -q batch <<-EOF + set network.wifi24=interface + set network.wifi24.proto='none' + set network.wifi5=interface + set network.wifi5.proto='none' + commit network + set wireless.radio0.cell_density='0' + set wireless.default_radio0.network='wifi24' + set wireless.radio1.cell_density='0' + set wireless.default_radio1.network='wifi5' + commit wireless + EOF + fi diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 579452b5d..4a4a37962 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -45,12 +45,14 @@ if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" ] set system.@led[-1].name='WAN_ETH' set system.@led[-1].trigger='netdev' set system.@led[-1].dev='eth0' - set system.@led[-1].mode='tx' 'rx' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' add system led set system.@led[-1].sysfs='wan_eth_3' set system.@led[-1].name='WAN_WIFI' set system.@led[-1].trigger='netdev' - set system.@led[-1].mode='tx' 'rx' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' add system led set system.@led[-1].sysfs='wan_sim_1' set system.@led[-1].name='WAN_MODEM1' @@ -63,6 +65,20 @@ if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" ] set system.@led[-1].trigger='netdev' set system.@led[-1].dev='wwan1' set system.@led[-1].mode='rx' + add system led + set system.@led[-1].name='WIFI24' + set system.@led[-1].sysfs='wifi_gen_2' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='radio0.network1' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' + add system led + set system.@led[-1].name='WIFI5' + set system.@led[-1].sysfs='wifi_gen_5' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='radio1.network1' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' commit system EOF fi From 1a8dfa260d4a2c34a767c4ce9403b0fd8549ec20 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 16 Apr 2022 17:41:13 +0200 Subject: [PATCH 0731/2059] Remove use of DNS for modem on RUTX --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 0925c70cc..a0e15b2f5 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -352,6 +352,7 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then set network.modem1.addlatency='0' set network.modem1.force_link='1' set network.modem1.device='/sys/devices/platform/soc/60f8800.usb2/6000000.dwc3/xhci-hcd.1.auto/usb3/3-1' + set network.modem1.peerdns='0' set network.wan_modem1=interface set network.wan_modem1.proto='dhcp' set network.wan_modem1.device='wwan0' @@ -376,6 +377,7 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then set network.modem2.addlatency='0' set network.modem2.force_link='1' set network.modem2.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' + set network.modem2.peerdns='0' set network.wan_modem2=interface set network.wan_modem2.proto='dhcp' set network.wan_modem2.device='wwan1' From 8ef28ba4bc6eea454cbb97b1f16795d297d27ee9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 18 Apr 2022 07:43:15 +0200 Subject: [PATCH 0732/2059] Update shadowsocks v2ray-plugin --- shadowsocks-v2ray-plugin/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-v2ray-plugin/Makefile b/shadowsocks-v2ray-plugin/Makefile index f9e700fe1..5cc81054e 100644 --- a/shadowsocks-v2ray-plugin/Makefile +++ b/shadowsocks-v2ray-plugin/Makefile @@ -15,7 +15,7 @@ PKG_SOURCE_PROTO:=git #PKG_SOURCE_URL:=https://github.com/shadowsocks/v2ray-plugin.git PKG_SOURCE_URL:=https://github.com/teddysun/v2ray-plugin.git #PKG_SOURCE_VERSION:=63a74bef9e9f639bc199255db9d452d96f01d11a -PKG_SOURCE_VERSION:=6c0c5fb15851e13b36fe2eeaaba97fd27c9d291b +PKG_SOURCE_VERSION:=5cafcf9a0ae316cb268120eb1994adf5255eb7f0 PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 From cc5c57af33ca4d09c82bfd2801856494b70c63fe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Apr 2022 21:55:00 +0200 Subject: [PATCH 0733/2059] Fix omr-bypass --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 87878277b..b95a0a806 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -511,7 +511,7 @@ _intf_rule() { intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') [ -z "$intf" ] && config_get intf $1 device - [ -n "$(echo $intf | grep '/') " ] && return + [ -n "$(echo $intf | grep '/')" ] && return #count=$((count+1)) config_get count $1 metric local mode From dd0cd92a354625daa1c79f703fd7318e915ea62d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Apr 2022 17:13:53 +0200 Subject: [PATCH 0734/2059] test install workaround --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 69c64d7b0..5a30323f7 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1655,7 +1655,7 @@ if [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep omr-bypass)" = "" /etc/init.d/omr-bypass 2>&1 >/dev/null fi -if [ -f /etc/backup/installed_packages.txt ]; then +if [ -f /etc/backup/installed_packages.txt ] && [ -n "$(grep overlay /etc/backup/installed_packages.txt)" ]; then _log "Reinstall packages..." /etc/init.d/sysupgrade restart 2>&1 >/dev/null fi From 36b50e7a5ccd78c149ff45d487d3d1201214072e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 26 Apr 2022 07:46:40 +0200 Subject: [PATCH 0735/2059] Only launch init script restart if the script exist --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 5a30323f7..5879a6ccb 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1536,17 +1536,17 @@ fi } # If a service is down, force restart it -if [ "$(pgrep ss-redir)" = "" ] && [ "$(pgrep ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then +if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(pgrep ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then _log "Can't find Shadowsocks, restart it..." /etc/init.d/shadowsocks-libev restart 2>&1 >/dev/null sleep 5 fi -if [ "$(pgrep glorytun)" = "" ] && [ "$(uci -q get glorytun.vpn.enable)" = "1" ] && [ -f /etc/init.d/glorytun ] && [ "$(uci -q get glorytun.vpn.key)" != "" ]; then +if [ -f /etc/init.d/glorytun ] && [ "$(pgrep glorytun)" = "" ] && [ "$(uci -q get glorytun.vpn.enable)" = "1" ] && [ -f /etc/init.d/glorytun ] && [ "$(uci -q get glorytun.vpn.key)" != "" ]; then _log "Can't find Glorytun, restart it..." /etc/init.d/glorytun restart 2>&1 >/dev/null sleep 5 fi -if [ "$(pgrep glorytun-udp)" = "" ] && [ "$(uci -q get glorytun-usp.vpn.enable)" = "1" ] && [ -f /etc/init.d/glorytun-udp ] && [ "$(uci -q get glorytun-udp.vpn.key)" != "" ]; then +if [ -f /etc/init.d/glorytun-udp ] && [ "$(pgrep glorytun-udp)" = "" ] && [ "$(uci -q get glorytun-usp.vpn.enable)" = "1" ] && [ -f /etc/init.d/glorytun-udp ] && [ "$(uci -q get glorytun-udp.vpn.key)" != "" ]; then _log "Can't find Glorytun UDP, restart it..." /etc/init.d/glorytun-udp restart 2>&1 >/dev/null sleep 5 @@ -1650,7 +1650,7 @@ if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then echo 1 > /sys/bus/pci/rescan fi -if [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep omr-bypass)" = "" ]; then +if [ -f /etc/init.d/omr-bypass ] && [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep omr-bypass)" = "" ]; then _log "Can't find omr-bypass rules, restart omr-bypass..." /etc/init.d/omr-bypass 2>&1 >/dev/null fi From 94a4b68fd97d6e7bd48ddd6ffc13d390aa7fba2b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 26 Apr 2022 20:39:36 +0200 Subject: [PATCH 0736/2059] Add date/time of VPS and router when there is a time diff) --- .../luasrc/view/openmptcprouter/wanstatus.htm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 5f248ab31..be05b035e 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -19,7 +19,7 @@ -- along with OverTheBox. If not, see (http://www.gnu.org/licenses/) -%> <% --- Copyright 2018-2020 Ycarus (Yannick Chabanois) ycarus@zugaina.org for OpenMPTCProuter +-- Copyright 2018-2022 Ycarus (Yannick Chabanois) ycarus@zugaina.org for OpenMPTCProuter -- -- Small changes to make this work with OpenMPTCProuter -- New features: @@ -307,7 +307,9 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm } if (mArray.openmptcprouter.vps_time_accurate == false) { - statusMessage += '<%:Big time difference between the server and the router%>' + '
    '; + var vps_time = new Date(mArray.openmptcprouter.vps_time*1000).toISOString(); + var omr_time = new Date(mArray.openmptcprouter.omr_time*1000).toISOString(); + statusMessage += '<%:Big time difference between the server and the router%> (' + vps_time + '/' + omr_time + ')
    '; } } if (statusMessage !== "" && statusMessageClass !== "error") From 883ecab5102177cf729054b3be17bb85a8bdff3a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 26 Apr 2022 20:43:16 +0200 Subject: [PATCH 0737/2059] Force ntpd restart after wizard changes --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 58d354013..20e9db6cd 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -987,6 +987,7 @@ function wizard_add() luci.sys.call("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/vnstat restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/v2ray restart >/dev/null 2>/dev/null") + luci.sys.call("/etc/init.d/sysntpd restart >/dev/null 2>/dev/null") luci.http.redirect(luci.dispatcher.build_url("admin/system/" .. menuentry:lower() .. "/status")) else luci.http.redirect(luci.dispatcher.build_url("admin/system/" .. menuentry:lower() .. "/wizard")) From 4f1c731a2580a2d63a4d9b43a3b7fca2839cce38 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Apr 2022 13:24:14 +0200 Subject: [PATCH 0738/2059] Add milkywan iperf and file to omr-test-speed --- luci-app-iperf/root/etc/config/iperf | 10 ++++++++++ openmptcprouter/files/bin/omr-test-speed | 2 +- openmptcprouter/files/bin/omr-test-speedv6 | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/luci-app-iperf/root/etc/config/iperf b/luci-app-iperf/root/etc/config/iperf index 911c3a1e6..d40063bcc 100644 --- a/luci-app-iperf/root/etc/config/iperf +++ b/luci-app-iperf/root/etc/config/iperf @@ -94,3 +94,13 @@ config server 'he' option tcp '1' option udp '1' option location 'America' + +config server 'milkywan' + option host 'speedtest.milkywan.fr' + option ipv4 '1' + option ipv6 '1' + option speed '10000' + option ports '9200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,9215' + option tcp '1' + option udp '1' + option location 'France' diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 71bc4d75c..431049e2c 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -14,7 +14,7 @@ fi } echo "Select best test server..." -HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" +HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://speedtest.milkywan.fr/files/10G.iso" bestping="9999" for pinghost in $HOSTLST; do domain=$(echo $pinghost | awk -F/ '{print $3}') diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index 32269f215..6e4b1215e 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -15,7 +15,7 @@ fi echo "Select best test server..." -HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv6.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin" +HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv6.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://speedtest.milkywan.fr/files/10G.iso" bestping="9999" for pinghost in $HOSTLST; do domain=$(echo $pinghost | awk -F/ '{print $3}') From 19f8760c22deedac68b6385f7b6e0df83c1af3f5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Apr 2022 13:39:25 +0200 Subject: [PATCH 0739/2059] Add an iperf server in asia --- luci-app-iperf/root/etc/config/iperf | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/luci-app-iperf/root/etc/config/iperf b/luci-app-iperf/root/etc/config/iperf index d40063bcc..2067c865e 100644 --- a/luci-app-iperf/root/etc/config/iperf +++ b/luci-app-iperf/root/etc/config/iperf @@ -95,6 +95,15 @@ config server 'he' option udp '1' option location 'America' +config server 'biznetnetworks.com' + option host 'iperf.biznetnetworks.com' + option ipv4 '1' + option ipv6 '1' + option ports '5201,5202,5203' + option tcp '1' + option udp '1' + option location 'Asia' + config server 'milkywan' option host 'speedtest.milkywan.fr' option ipv4 '1' @@ -103,4 +112,4 @@ config server 'milkywan' option ports '9200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,9215' option tcp '1' option udp '1' - option location 'France' + option location 'Europe' From b174b3ba3e2560de5c2c679d05b372262e0a72b1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 1 May 2022 12:34:43 +0200 Subject: [PATCH 0740/2059] Fix wizard when modifying a macvlan interface --- .../luasrc/controller/openmptcprouter.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 20e9db6cd..f5193e100 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -333,6 +333,12 @@ function wizard_add() ucic:set("network",intf .. "_dev","name",ifname) end end + if typeintf ~= "macvlan" and ucic:get("network",intf .. "_dev","type") == "macvlan" then + ucic:delete("network",intf .. "_dev","type") + ucic:delete("network",intf .. "_dev","mode") + ucic:delete("network",intf .. "_dev","ifname") + ucic:delete("network",intf .. "_dev","macaddr") + end if proto == "pppoe" then ucic:set("network",intf,"pppd_options","persist maxfail 0") end From eedbfc56b7bf777e616452c7d3d59a70ce654f48 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 18 May 2022 21:06:09 +0200 Subject: [PATCH 0741/2059] Add option to enable/disable SIP ALG --- .../luasrc/controller/openmptcprouter.lua | 13 +++++++++++++ .../luasrc/view/openmptcprouter/settings.htm | 6 ++++++ .../files/etc/init.d/openmptcprouter-vps | 14 ++++++++++++++ .../files/etc/uci-defaults/1980-omr-firewall | 9 +++++++++ 4 files changed, 42 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index f5193e100..9e94a08a1 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1190,6 +1190,19 @@ function settings_add() local sfe_bridge = luci.http.formvalue("sfe_bridge") or "0" ucic:set("openmptcprouter","settings","sfe_bridge",sfe_bridge) + -- Enable/disable SIP ALG + local sipalg = luci.http.formvalue("sipalg") or "0" + ucic:set("openmptcprouter","settings","sipalg",sipalg) + ucic:foreach("firewall", "zone", function (section) + ucic:set("firewall",section[".name"],"auto_helper",sipalg) + end) + if sipalg == "1" then + luci.sys.call("modprobe nf_conntrack_ip >/dev/null 2>/dev/null") + luci.sys.call("modprobe nf_nat_sip >/dev/null 2>/dev/null") + else + luci.sys.call("rmmod nf_nat_sip >/dev/null 2>/dev/null") + luci.sys.call("rmmod nf_conntrack_ip >/dev/null 2>/dev/null") + end ucic:save("openmptcprouter") ucic:commit("openmptcprouter") diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index c866f921e..2db886333 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -219,6 +219,12 @@
    +
    + +
    + checked<% end %>> +
    +

    diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 6ac763eac..0f3b63c10 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -843,6 +843,19 @@ _set_vpn_ip() { fi } +_set_sipalg() { + local settings + sipalg="$(uci -q get openmptcprouter.settings.sipalg)" + if [ "$sipalg" = "1" ]; then + sipalg="true" + else + sipalg="false" + fi + settings='{"enable" : "'$sipalg'"}' + result=$(_set_json "sipalg" "$settings") +} + + _delete_client2client() { if [ -n "$(echo $1 | grep omr_client2client)" ]; then uci -q delete network.$1 @@ -1882,6 +1895,7 @@ _config_service() { lanips="" config_foreach _get_lan_ip interface _set_lan_ip + _set_sipalg config_foreach _delete_client2client route if [ "$(uci -q get openmptcprouter.settings.vpn)" != "openvpn" ] && [ "$(echo "$vps_config" | jsonfilter -q -e '@.client2client.enabled')" == "true" ]; then _set_client2client diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index fe0cbdf61..709eaaf05 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -240,6 +240,15 @@ uci -q batch <<-EOF >/dev/null set firewall.@include[0].reload='1' commit firewall EOF +if [ "$(uci -q get openmptcprouter.settings.sipalg)" != "1" ]; then + uci -q batch <<-EOF >/dev/null + set firewall.zone_lan.auto_helper='0' + set firewall.zone_wan.auto_helper='0' + commit firewall + EOF + rmmod nf_nat_sip 2>&1 >/dev/null + rmmod nf_conntrack_sip 2>&1 >/dev/null +fi rm -f /tmp/luci-indexcache From 7a2e7ae1e93a55e1203cc4fb5ad7a993f2e60092 Mon Sep 17 00:00:00 2001 From: Florian Karuhtz Date: Fri, 20 May 2022 16:49:04 +0200 Subject: [PATCH 0742/2059] Update mptcpd to v0.9 and simplify patch --- mptcpd/Makefile | 17 ++- mptcpd/patches/remove_log.patch | 167 ------------------------------ mptcpd/patches/stub_error_h.patch | 16 +++ 3 files changed, 28 insertions(+), 172 deletions(-) delete mode 100644 mptcpd/patches/remove_log.patch create mode 100644 mptcpd/patches/stub_error_h.patch diff --git a/mptcpd/Makefile b/mptcpd/Makefile index 47f0de339..6bb9f7f71 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -10,13 +10,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mptcpd PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/intel/mptcpd.git -PKG_SOURCE_VERSION:=0e7175adf721c95a3bd742be77cb85e0b47138cd -PKG_VERSION:=0.7-$(PKG_SOURCE_VERSION) +PKG_SOURCE_VERSION:=df4ea048cd3821f749bf06e0d01bb7d79faac812 +PKG_VERSION:=0.9-$(PKG_SOURCE_VERSION) PKG_RELEASE:=1 PKG_MAINTAINER:=Ycarus (Yannick Chabanois) -PKG_FIXUP:=autoreconf - PKG_FORTIFY_SOURCE:=2 PKG_INSTALL:=1 PKG_BUILD_PARALLEL:=1 @@ -36,7 +34,16 @@ define Package/$(PKG_NAME)/conffiles /etc/mptcpd/mptcpd.conf endef -TARGET_CFLAGS += -D_GNU_SOURCE -Wno-unused-result -Wno-format-nonliteral +CONFIGURE_ARGS += \ + --disable-doxygen-doc \ + --disable-logging + +TARGET_CFLAGS += -Wno-unused-result -Wno-format-nonliteral + +define Build/Prepare + $(Build/Prepare/Default) + ( cd $(PKG_BUILD_DIR); $(AM_TOOL_PATHS) ./bootstrap ) +endef define Build/Compile +$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) diff --git a/mptcpd/patches/remove_log.patch b/mptcpd/patches/remove_log.patch deleted file mode 100644 index ed077f859..000000000 --- a/mptcpd/patches/remove_log.patch +++ /dev/null @@ -1,167 +0,0 @@ ---- a/src/configuration.c 2021-06-29 17:44:20.481179981 +0200 -+++ b/src/configuration.c 2021-06-29 17:44:52.580655950 +0200 -@@ -37,21 +37,12 @@ - * Preprocessor concatenation that expands preprocessor tokens as - * needed by leveraging the usual indirection technique. - */ --///@{ --/// Underlying string concatenation macro. --#define MPTCPD_CONCAT_IMPL(x, ...) x ## __VA_ARGS__ -- --/// Concatenate strings using the preprocessor. --#define MPTCPD_CONCAT(x, ...) MPTCPD_CONCAT_IMPL(x, __VA_ARGS__) --///@} - - // Compile-time default logging choice - #ifndef MPTCPD_LOGGER - // This should never occur! - # error Problem configuring default log message destination. - #endif --/// Name of the default logging function determined at compile-time. --#define MPTCPD_SET_LOG_FUNCTION MPTCPD_CONCAT(l_log_set_, MPTCPD_LOGGER) - - /** - * @brief Get the function that sets the log message destination. -@@ -474,7 +465,6 @@ - - struct mptcpd_config *mptcpd_config_create(int argc, char *argv[]) - { -- MPTCPD_SET_LOG_FUNCTION(); // For early logging. - - struct mptcpd_config *const config = - l_new(struct mptcpd_config, 1); ---- a/src/mptcpize.c 2021-06-29 19:29:57.810281053 +0200 -+++ b/src/mptcpize.c 2021-06-29 19:29:29.942701557 +0200 -@@ -17,7 +17,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -79,7 +78,7 @@ - nr++; - envp = calloc(nr + 3, sizeof(char *)); - if (!envp) -- error(1, errno, "can't allocate env list"); -+ fprintf(stderr, "can't allocate env list"); - - // ... filtering out any 'LD_PRELOAD' ... - nr = 0; -@@ -103,7 +102,7 @@ - // build the NULL terminated arg list - argv = calloc(argc + 1, sizeof(char *)); - if (!argv) -- error(1, errno, "can't allocate argument list"); -+ fprintf(stderr, "can't allocate argument list"); - - memcpy(argv, av, argc * sizeof(char*)); - return execvpe(argv[0], argv, envp); -@@ -124,33 +123,33 @@ - len = strlen(name) + 1 + strlen(SYSTEMCTL_SHOW); - cmd = malloc(len); - if (!cmd) -- error(1, 0, "can't allocate systemctl command string"); -+ fprintf(stderr, "can't allocate systemctl command string"); - - sprintf(cmd, SYSTEMCTL_SHOW"%s", name); - systemctl = popen(cmd, "r"); - if (!systemctl) -- error(1, errno, "can't execute %s", cmd); -+ fprintf(stderr, "can't execute %s", cmd); - - free(cmd); - while ((read = getline(&line, &len, systemctl)) != -1) { - if (strncmp(line, SYSTEMD_UNIT_VAR, strlen(SYSTEMD_UNIT_VAR)) == 0) { - char *ret = strdup(&line[strlen(SYSTEMD_UNIT_VAR)]); - if (!ret) -- error(1, errno, "failed to duplicate string"); -+ fprintf(stderr, "failed to duplicate string"); - - // trim trailing newline, if any - len = strlen(ret); - if (len > 0 && ret[len - 1] == '\n') - ret[--len] = 0; - if (len == 0) -- error(1, 0, "can't find unit file for service %s", name); -+ fprintf(stderr, "can't find unit file for service %s", name); - free(line); - pclose(systemctl); - return ret; - } - } - -- error(1, 0, "can't find FragmentPath attribute for unit %s", name); -+ fprintf(stderr, "can't find FragmentPath attribute for unit %s", name); - - // never reached: just silence gcc - return NULL; -@@ -175,12 +174,12 @@ - unit = locate_unit(argv[0]); - src = fopen(unit, "r"); - if (!src) -- error(1, errno, "can't open file %s", unit); -+ fprintf(stderr, "can't open file %s", unit); - - strcpy(dst_path, "/tmp/unit_XXXXXX"); - dst = mkstemp(dst_path); - if (dst < 0) -- error(1, errno, "can't create tmp file"); -+ fprintf(stderr, "can't create tmp file"); - - // reset any prior error, to allow later check on errno - errno = 0; -@@ -194,27 +193,27 @@ - - if (!is_env) { - if (write(dst, line, read) < 0) -- error(1, errno, "can't write '%s' into %s", line, dst_path); -+ fprintf(stderr, "can't write '%s' into %s", line, dst_path); - } - - if (append_env && - (is_env || strncmp(line, SYSTEMD_SERVICE_TAG, strlen(SYSTEMD_SERVICE_TAG)) == 0)) { - if (dprintf(dst, "%s%s\n", SYSTEMD_ENV_VAR, MPTCPWRAP_ENV) < 0) -- error(1, errno, "can't write to env string into %s", dst_path); -+ fprintf(stderr, "can't write to env string into %s", dst_path); - append_env = 0; - } - } - if (errno != 0) -- error(1, errno, "can't read from %s", unit); -+ fprintf(stderr, "can't read from %s", unit); - free(line); - fclose(src); - close(dst); - - if (rename(dst_path, unit) < 0) -- error(1, errno, "can't rename %s to %s", dst_path, unit); -+ fprintf(stderr, "can't rename %s to %s", dst_path, unit); - - if (system("systemctl daemon-reload") != 0) -- error(1, errno, "can't reload unit, manual 'systemctl daemon-reload' is required"); -+ fprintf(stderr, "can't reload unit, manual 'systemctl daemon-reload' is required"); - - printf("mptcp successfully %s on unit %s\n", - enable ? "enabled" : "disabled", unit); -@@ -239,7 +238,7 @@ - argp_program_version = "mptcpize "VERSION; - argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; - if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, &idx, 0) < 0) -- error(1, errno, "can't parse arguments"); -+ fprintf(stderr, "can't parse arguments"); - - argc -= idx; - argv += idx; ---- a/src/mptcpize.c 2021-07-05 20:06:07.035838944 +0200 -+++ b/src/mptcpize.c 2021-07-05 20:06:26.875505617 +0200 -@@ -7,8 +7,6 @@ - * Copyright (c) 2021, Red Hat, Inc. - */ - --#define _GNU_SOURCE -- - #include - - #include diff --git a/mptcpd/patches/stub_error_h.patch b/mptcpd/patches/stub_error_h.patch new file mode 100644 index 000000000..8a8f5be19 --- /dev/null +++ b/mptcpd/patches/stub_error_h.patch @@ -0,0 +1,16 @@ +--- a/src/error.h ++++ b/src/error.h +@@ -0,0 +1,13 @@ ++#ifndef _ERROR_H ++#define _ERROR_H 1 ++ ++#include ++#include ++ ++// mimic the behaviour of https://man7.org/linux/man-pages/man3/error.3.html ++void error(int status, int errnum, const char *format, ...) ++{ ++ fprintf(stderr, "Error %d: %s", errnum, format); ++ if (status != 0) exit(status); ++} ++#endif From 3d68e2acdc5d2b49dd085ebd660a663c832f97a2 Mon Sep 17 00:00:00 2001 From: Florian Karuhtz Date: Fri, 20 May 2022 16:56:56 +0200 Subject: [PATCH 0743/2059] Add CLA --- contributors/flesser.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 contributors/flesser.md diff --git a/contributors/flesser.md b/contributors/flesser.md new file mode 100644 index 000000000..126dab7b5 --- /dev/null +++ b/contributors/flesser.md @@ -0,0 +1,9 @@ +2022-05-20 + +I hereby agree to the terms of the "OpenMPTCProuter Individual Contributor License Agreement", with MD5 checksum bc827a07eb93611d793ddb7c75083c00. + +I furthermore declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +Florian Karuhtz https://github.com/flesser From dc01b097d2c61d58fde99cc4e2ff8254ff8b0994 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 23 May 2022 20:40:51 +0200 Subject: [PATCH 0744/2059] Display as direct output when public IP is the same as one wan public ip --- .../root/usr/libexec/rpcd/openmptcprouter | 6 + luci-theme-argon/Makefile | 16 - luci-theme-argon/README.md | 119 - luci-theme-argon/README_ZH.md | 101 - .../Screenshots/screenshot_pc.jpg | Bin 673706 -> 0 bytes .../Screenshots/screenshot_phone.jpg | Bin 467306 -> 0 bytes .../luci-static/argon/background/README.md | 2 - .../htdocs/luci-static/argon/css/cascade.css | 3285 -------------- .../htdocs/luci-static/argon/css/dark.css | 646 --- .../htdocs/luci-static/argon/css/fonts.css | 186 - .../htdocs/luci-static/argon/css/pure-min.css | 11 - .../htdocs/luci-static/argon/favicon.ico | Bin 15406 -> 0 bytes .../luci-static/argon/fonts/TypoGraphica.eot | Bin 33846 -> 0 bytes .../luci-static/argon/fonts/TypoGraphica.svg | 1191 ----- .../luci-static/argon/fonts/TypoGraphica.ttf | Bin 33632 -> 0 bytes .../luci-static/argon/fonts/TypoGraphica.woff | Bin 17816 -> 0 bytes .../htdocs/luci-static/argon/fonts/argon.eot | Bin 8888 -> 0 bytes .../htdocs/luci-static/argon/fonts/argon.svg | 38 - .../htdocs/luci-static/argon/fonts/argon.ttf | Bin 8732 -> 0 bytes .../htdocs/luci-static/argon/fonts/argon.woff | Bin 8808 -> 0 bytes .../argon/icon/android-icon-192x192.png | Bin 6411 -> 0 bytes .../argon/icon/apple-icon-144x144.png | Bin 5222 -> 0 bytes .../argon/icon/apple-icon-60x60.png | Bin 2561 -> 0 bytes .../argon/icon/apple-icon-72x72.png | Bin 2877 -> 0 bytes .../htdocs/luci-static/argon/icon/arrow.svg | 1 - .../luci-static/argon/icon/browserconfig.xml | 2 - .../luci-static/argon/icon/favicon-16x16.png | Bin 1019 -> 0 bytes .../luci-static/argon/icon/favicon-32x32.png | Bin 1720 -> 0 bytes .../luci-static/argon/icon/favicon-96x96.png | Bin 3650 -> 0 bytes .../luci-static/argon/icon/manifest.json | 41 - .../argon/icon/ms-icon-144x144.png | Bin 5222 -> 0 bytes .../htdocs/luci-static/argon/icon/spinner.svg | 1 - .../htdocs/luci-static/argon/img/argon.svg | 61 - .../htdocs/luci-static/argon/img/bg1.jpg | Bin 159265 -> 0 bytes .../htdocs/luci-static/argon/img/blank.png | Bin 938 -> 0 bytes .../luci-static/argon/img/volume_high.svg | 1 - .../luci-static/argon/img/volume_off.svg | 1 - .../htdocs/luci-static/argon/js/jquery.min.js | 2 - .../luci-static/argon/js/polyfill.min.js | 3 - .../htdocs/luci-static/argon/js/script.js | 219 - .../luci-static/argon/less/cascade.less | 3982 ----------------- .../htdocs/luci-static/argon/less/dark.less | 828 ---- .../luasrc/view/themes/argon/footer.htm | 46 - .../luasrc/view/themes/argon/footer_login.htm | 46 - .../luasrc/view/themes/argon/header.htm | 282 -- .../luasrc/view/themes/argon/header_login.htm | 123 - .../view/themes/argon/out_footer_login.htm | 27 - .../view/themes/argon/out_header_login.htm | 38 - .../luasrc/view/themes/argon/sysauth.htm | 157 - .../root/etc/uci-defaults/30_luci-theme-argon | 12 - 50 files changed, 6 insertions(+), 11468 deletions(-) delete mode 100644 luci-theme-argon/Makefile delete mode 100644 luci-theme-argon/README.md delete mode 100644 luci-theme-argon/README_ZH.md delete mode 100644 luci-theme-argon/Screenshots/screenshot_pc.jpg delete mode 100644 luci-theme-argon/Screenshots/screenshot_phone.jpg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/background/README.md delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/css/cascade.css delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/css/dark.css delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/css/fonts.css delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/favicon.ico delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.eot delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.svg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.ttf delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.woff delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/argon.eot delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/argon.svg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/argon.ttf delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/fonts/argon.woff delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/android-icon-192x192.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/browserconfig.xml delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon-32x32.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon-96x96.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/manifest.json delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/ms-icon-144x144.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/img/argon.svg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/img/bg1.jpg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/img/blank.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/js/jquery.min.js delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/js/polyfill.min.js delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/js/script.js delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/less/cascade.less delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/less/dark.less delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/footer.htm delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/footer_login.htm delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/header.htm delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/header_login.htm delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/sysauth.htm delete mode 100644 luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index f8ac6eca0..c609b4737 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1489,6 +1489,9 @@ function interfaces_status() whois = ut.trim(sys.exec("whois " .. publicIP .. " | grep -i 'netname' | awk '{print $2}'")) --whois = ut.trim(sys.exec("wget -4 -qO- -T 1 'http://api.iptoasn.com/v1/as/ip/" .. publicIP .. "' | jsonfilter -q -e '@.as_description'")) end + if publicIP == mArray.openmptcprouter["wan_addr"] then + mArray.openmptcprouter["direct_output"] = true + end end if publicIP6 ~= "" then whois6 = uci:get("openmptcprouter",interface,"asn") or "" @@ -1496,6 +1499,9 @@ function interfaces_status() whois6 = ut.trim(sys.exec("whois " .. publicIP6 .. " | grep -i 'netname' | awk '{print $2}'")) --whois6 = ut.trim(sys.exec("wget -6 -qO- -T 1 'http://api.iptoasn.com/v1/as/ip/" .. publicIP6 .. "' | jsonfilter -q -e '@.as_description'")) end + if publicIP6 == mArray.openmptcprouter["wan_addr6"] then + mArray.openmptcprouter["direct_output"] = true + end end if ifname ~= "" and ifname ~= nil then if fs.access("/sys/class/net/" .. ifname) then diff --git a/luci-theme-argon/Makefile b/luci-theme-argon/Makefile deleted file mode 100644 index 1f786223e..000000000 --- a/luci-theme-argon/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (C) 2008-2019 Jerrykuku -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Argon Theme -LUCI_DEPENDS:= -PKG_VERSION:=2.2.6 -PKG_RELEASE:=20210215 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-theme-argon/README.md b/luci-theme-argon/README.md deleted file mode 100644 index 11b84a6f8..000000000 --- a/luci-theme-argon/README.md +++ /dev/null @@ -1,119 +0,0 @@ -
    - -

    - A new LuCI theme for OpenWrt -

    -

    - Argon is a clean HTML5 theme for LuCI. Users may
    setup their own favorite logins, including beautiful
    pics and customized mp4 videos.

    -

    - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    -
    - -
    - -
    English | [简体中文](README_ZH.md) - -## Notice -It is strongly recommended to use the Chrome browser. Some new css3 features are used in the theme, and currently only Chrome has the best compatibility. -The mainline version of IE series currently has bugs to be resolved. -FireFox does not enable the backdrop-filter by default, see here for the opening method: https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter - -v2.x.x Adapt to official mainline snapshot. -You can checkout branch 18.06 for OpenWRT 18.06 or lean 19.07. - -## Update Log 2020.09.13 v2.2.5 - -- 【v2.2.5】New config app for argon theme. You can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.[Chrome is recommended] [Download](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) -- 【v2.2.5】Automatically set as the default theme when compiling. -- 【v2.2.5】Modify the file structure to adapt to luci-app-argon-config. The old method of turning on dark mode is no longer applicable, please use it with luci-app-argon-config. -- 【v2.2.5】Adapt to Koolshare lede 2.3.6。 -- 【v2.2.5】Fix some Bug。 -- 【v2.2.4】Fix the problem that the login background cannot be displayed on some phones. -- 【v2.2.4】Remove the dependency of luasocket. -- 【v2.2.3】Fix Firmware flash page display error in dark mode. -- 【v2.2.3】Update font icon, add a default icon of undefined menu. -- 【v2.2.2】Add custom login background,put your image (allow png jpg gif) or MP4 video into /www/luci-static/argon/background, random change. -- 【v2.2.2】Add force dark mode, login ssh and type "touch /etc/dark" to open dark mode. -- 【v2.2.2】Add a volume mute button for video background, default is muted. -- 【v2.2.2】fix login page when keyboard show the bottom text overlay the button on mobile. -- 【v2.2.2】fix select color in dark mode,and add a style for scrollbar. -- 【v2.2.2】jquery update to v3.5.1. -- 【v2.2.2】change request bing api method form wget to luasocket (DEPENDS). -- 【v2.2.1】Add blur effect for login form. -- 【v2.2.1】New login theme, Request background imge from bing.com, Auto change everyday. -- 【v2.2.1】New theme icon. -- 【v2.2.1】Add more menu category icon. -- 【v2.2.1】Fix font-size and padding margin. -- 【v2.2.1】Restructure css file. -- 【v2.2.1】Auto adapt to dark mode. - -## How to build - -Enter in your openwrt/package/lean or other - -### Lean lede - -``` -cd lede/package/lean -rm -rf luci-theme-argon -git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s -``` - -### Openwrt official SnapShots - -``` -cd openwrt/package -git clone https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s -``` - -## How to Install - -### For Lean openwrt 18.06 LuCI - -``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.0/luci-theme-argon_1.7.0-20200909_all.ipk -opkg install luci-theme-argon*.ipk -``` - -### For openwrt official 19.07 Snapshots LuCI master - -``` -opkg install luci-compat -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.5/luci-theme-argon_2.2.5-20200914_all.ipk -opkg install luci-theme-argon*.ipk -``` -![](/Screenshots/screenshot_pc.jpg) -![](/Screenshots/screenshot_phone.jpg) - -## Thanks to - -luci-theme-material: https://github.com/LuttyYang/luci-theme-material/ diff --git a/luci-theme-argon/README_ZH.md b/luci-theme-argon/README_ZH.md deleted file mode 100644 index b229fa4fe..000000000 --- a/luci-theme-argon/README_ZH.md +++ /dev/null @@ -1,101 +0,0 @@ -# luci-theme-argon ([English](/README.md)) -[1]: https://img.shields.io/badge/license-MIT-brightgreen.svg -[2]: /LICENSE -[3]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg -[4]: https://github.com/jerrykuku/luci-theme-argon/pulls -[5]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg -[6]: https://github.com/jerrykuku/luci-theme-argon/issues/new -[7]: https://img.shields.io/badge/release-v2.2.5-blue.svg? -[8]: https://github.com/jerrykuku/luci-theme-argon/releases -[9]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total -[10]: https://img.shields.io/badge/Contact-telegram-blue -[11]: https://t.me/jerryk6 -[![license][1]][2] -[![PRs Welcome][3]][4] -[![Issue Welcome][5]][6] -[![Release Version][7]][8] -[![Release Count][9]][8] -[![Contact Me][10]][11] - -![](/Screenshots/screenshot_pc.jpg) -![](/Screenshots/screenshot_phone.jpg) - -全新的 Openwrt 主题,基于luci-theme-material 和 开源免费的 Argon 模板进行移植。 - -## 注意 -强烈建议使用Chrome 浏览器。主题中使用了一些新的css3特性,目前只有Chrome有最佳的兼容性。 -主线版本 IE 系列目前还有Bug有待解决。 -FireFox 默认不开启backdrop-filter,开启方法见这里:https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter -当前master版本基于官方 OpenWrt 19.07.1 稳定版固件进行移植适配。 -v2.x.x 适配主线快照版本。 -v1.x.x 适配18.06 和 Lean Openwrt [如果你是lean代码 请选择这个版本] - - -## 更新日志 2020.09.13 v2.2.5 - -- 【v2.2.5】全新的设置app.你可以设置argon 主题的登录页面的模糊和透明度,并管理背景图片与视频。[建议使用 Chrome][点击下载](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) -- 【v2.2.5】当编译固件时,将自动设置为默认主题。 -- 【v2.2.5】修改文件结构,以适应luci-app-argon-config,旧的开启暗色模式方法将不再适用,请搭配luci-app-argon-config使用。 -- 【v2.2.5】适配Koolshare lede 2.3.6。 -- 【v2.2.5】修复了一些Bug。 -- 【v2.2.4】修复了在某些手机下图片背景第一次加载不能显示的问题。 -- 【v2.2.4】取消 luasocket 的依赖,无需再担心依赖问题。 -- 【v2.2.3】修正了在暗色模式下,固件刷写弹窗内的显示错误。 -- 【v2.2.3】更新了图标库,为未定义的菜单增加了一个默认的图标。 -- 【v2.2.2】背景文件策略调整为,同时接受 jpg png gif mp4, 自行上传文件至 /www/luci-static/argon/background 图片和视频同时随机。 -- 【v2.2.2】增加强制暗色模式,进入ssh 输入 "touch /etc/dark" 进行开启。 -- 【v2.2.2】视频背景加了一个音量开关,喜欢带声音的可以自行点击开启,默认为静音模式。 -- 【v2.2.2】修复了手机模式下,登录页面出现键盘时,文字覆盖按钮的问题。 -- 【v2.2.2】修正了暗黑模式下下拉选项的背景颜色,同时修改了滚动条的样式。 -- 【v2.2.2】jquery 更新到 v3.5.1。 -- 【v2.2.2】获取Bing Api 的方法从wget 更新到luasocket 并添加依赖。 -- 【v2.2.1】登录背景添加毛玻璃效果。 -- 【v2.2.1】全新的登录界面,图片背景跟随Bing.com,每天自动切换。 -- 【v2.2.1】全新的主题icon。 -- 【v2.2.1】增加多个导航icon。 -- 【v2.2.1】细致的微调了 字号大小边距等等。 -- 【v2.2.1】重构了css文件。 -- 【v2.2.1】自动适应的暗黑模式。 - -## 如何编译 - -进入 openwrt/package/lean 或者其他目录 - -### Lean源码 - -``` -cd lede/package/lean -rm -rf luci-theme-argon -git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s -``` - -### Openwrt 官方源码 - -``` -cd openwrt/package -git clone https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s -``` - -## 如何安装 - -### Lean源码 - -``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.0/luci-theme-argon_1.7.0-20200909_all.ipk -opkg install luci-theme-argon*.ipk -``` - -### For openwrt official 19.07 Snapshots LuCI master - -``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.5/luci-theme-argon_2.2.5-20200914_all.ipk -opkg install luci-theme-argon*.ipk -``` - -## 感谢 - -luci-theme-material: https://github.com/LuttyYang/luci-theme-material/ diff --git a/luci-theme-argon/Screenshots/screenshot_pc.jpg b/luci-theme-argon/Screenshots/screenshot_pc.jpg deleted file mode 100644 index 4c355449a3aa732fd06f2b69fd6f6bd1f0342647..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673706 zcmeFYWmFu&`!0wECk*cH?hb+A2@Zopa2s5LLvSBlLXhAv_~06x0fNKe1b25y$mZ_e zy?giD{c!i}|HJP+r%!cv)mvRvPgQsI^Hlv^`n!q{fq?kGZb<)+A^#8i@9s#5i2q{$ z9seWZfA!?=Isyv9`rmT|Tv=;ZOB)31UIYXL#J{}=0CZ%?n*(G700JTa5eb0!cMy>u z0TBTa1^M4I|E2lA3=IYK4LULgCK4jnzq^R2|8pDy3L+9R>Kin447`7Ch{%Y@$Qamo zIJl^YY{-a6{~Qs}0Ql$xbc95F7{v6lTDrj5ITCUP9Sir+l+?8Jc}zxreTR(9tipK_O8&Z9`8l@8aewW=jvBC}_(fi?E3N=dg&T0R<)N z=(09eD;rz8@W`T){$Vy1`_jP?Mdg?w*v|F8Iw2#WApI*kIyxpA>c0viAR(gwQ1R*b zWVPN9&|A2p5%Pzo6cRDK*S2h!*&-IO@+j)tzCa7BR=<(A)nf z`2VX3;{Q(n2Z;X)oiP6I%zuFRuK~pDe}MR}0mR&YfcUQg#QcAN_^$!P!v78+;v1!5 z%YW2qpd?yl`ZXE3dE+oU?IB;lrFK6zTO_|w`a`kVA{T%6Ae#RouRMEu7e{W@qL(K! z(J5)fvMCCGGP(Ns*j#HhH$!Rma$!n3-@a3=`Db&ULT=(8mHcYGOo?d`f5vQi-Z-`M z*MP19ErAnd_ha_a2dh5zazT=J?|6!NDFZ>#{-(uFvaM~YeX;q~ zb>@7t)8>wT?02TVBWG%#60>RE>)g`^=^jezePuTOBz7#i0ZWAhyxcgrP+ZNC1}*{E z%lGDuy)FHuo7+8J3n`9V{&C#rZv$ku#zC|y&slyz^B7{5J>S0wUp0u(XZ$WNe@}_e z@~#=D9ul2R#vh(Dl+T|>zf8dO{AI0D;Ep}o!wGVHf!WmD3a_c}-c~*3sV2A^JrF?i z57jVPa}E>}@-beoxkK*QhAS-4g1mL{t;wq+o+yb~G(5=&R-f^@>;5bnT9y+}qf$HO z{~;lTioP|Is2J;sP(bhD;g~GBGqNwjXrw?*d7p*(-d8EE>#=-VzAM0N)thS5c)qM( zt=sX~-fc|e6_~ia@vh|UnfpuyeyGJ}i`&}_?^=m81v0C=iCCH;${(|6=R7p<03*2C zbLI-d=Z=#L;V8T@aX((2p^y!Oe9F34c97D$lGfYdW1+Zd!Lfhrm>0HhD|!r;7@1)u9o7t$1lJeXPrhVJ@s z6i1$l(2qr#eAs5lU{Kr&3@M49dytNtw-c0HOVovnO*m)bfN&}NI~YdfpTkI~-@Vk< zlgfQ2(Pl_b3;u{KT3kpOONyRb_uc9R>nYEI7tH?Aww0o;B}yUQ=4F0k2{bd%=Hls|GxCu;NKu|Da2p{;1P}n$d z>UErNyECBRUgI*BHPP?-PUda#5$7w8jSX4Pm}JH#7E+IPz511MzgbWTLC}x-%1WG~ zo*f0iQe;%ANwId~S}>4g9*F)&dOLu~RMm$0I}V}Uws22Xi3Tvs_Bv?fm)Yc{BfqjQ zkPs(heAmQSU3{>XZL}R%gV8OT^n}}L`}V3=8MmnL+I1S2$J1uyS^`vPB+#>D|A~FO0TwPeQne-A_VWap@=n!uOem zw_6A;=wb}%aa7szc8D$X>j;(>0#wEm= z1X_{tbXp}SPXv$HEZxsM$2~e*4{v;q*x>jxSW8wUmCcMNv|8=rY{IK_zO|ca6$M+pgRK&M69~Pn_GhM{Eh8J~lr!Q6l3uJN>kXN=S=#3?_Up?7qLo*(#Yw ztWprSpDB1`!-iO(#|I**6XN#?R4xbnc(mWy7z;X%nAG!l8DDeruEN63n;ieSe zeiI&XC^R$B(%?4$YA=^i=3tHk+4gqQm?XUoaR{O!<=U1{FiedK@!fF!$^T`Wa6(WEh{$DxF-%3 z+usGo7?aYKW**HBunY%HQU+WoGv{|+%cUpHdtCDDtQ<||CTbWZUB_lWnpY*vLcMOq zRLE?FfJOIeKs+t-1$m%C4KW~6YjXK}go^rvYUaJevB8y-4$a_-)u7{!t+W4k&Yf-V z<{trEZOi!+67Ee`2mEz3&7*baN$l`_Sv$Xd6Xp;88TDv<>qv31!&=3p%A^qEthI%^ zrSuEW0###dza}&dLrf}M98_r~*oc~bmbNG^^2555;`aVh@S=0q?=*oA$K*!Y5&m*+ z1?IF+Ud@!SOSvNzPxO0w){L?9QpIM{0k+O~j2_IgFt&6m*&c!X8@0&lkk|F7 zfWuZL^9RGp?##qk)MP{f z4W)wHcq*m}<)KzMU@(PQPK$c8Axii9{HvculsKB)?rX+HZAF_9v}N*(KjZLJI{KMu zZujLO+zhJ zq^+3V(_QvDXG2Qk3K{+r5rOWiT;hi=# ziGszmGTn4W5?x>+h0{)6L5e$!`&*a!)_5W?+52$){i|YgUU21om=t)u${angxe?Zm z>cZNLVI!RE*-fvWO;ugt?B=oN9s|lX{+Jx9B(du+Omu+J`Fu`C_kPIrH}cA2DHT-CXWI?z9_w>In1&jlKdD?pa9@pCWUcEJl6J?bSXgsER~uIH9y4b^l32xD z;~qh3pVX*KruC=3)nSiuwdCA)W-3?N@bG>7F7W~!*T7n!_Q(xOm5~}3 zR_@)tt>!MQdealde#c-s*@`!sNeumn;S75FE44-Q=R?v}pxEjwD6@rYQi(e*vn_c? zbo0ko+C5#joemNnPv(c?;RjrBj7&2*++$bCU*BMDjwrnCn*#)TJi~%9T4?y>tx)wg z1vpZbYFWM55oa9A{fX+flpbehVJvR?QA{^2kB?u=Blb!SkSB%_EnVsQ&(AMVNrH77*6Wf)aX!|&cjXxQW>aCuL(XsO&+YWCGe zp`(hVWp|}pVgUD5Qm2?2PDVrTH^_b_0H_&Mn7iy??6&I%RGYu zb6j_(Ai5~!HAkw)s?`Tf!2&y^kBtdmdb6;#++*5Y`AaJ)k33jDNW$ej7beLH5x5;B zN_=OkwvJ2{J^2-3rjNa40JwK*U5ojeU55Dw3?-)F6e2vdFAp#H-SHa&-FxB&>kgJojj(enL+VCod*=zX zI`LhtC=UmYAmeqoJUMA8!zX^MZ27Rzy$v%$0I51rx3ZvTU=W+91P|zK3F;qNg+Nyl zcXAv(hxpYVHYIkc>>*5b6)j?0fnTEph!zg+96y&uan*0Xb9tvv52a9bMWigvdsL-# zja#i8q)J;wx7tM3;R=(GyU&>W)m!($c#?1EQr8#TCAhZXV*yrG+M4m?$_&M8hcisX z7J#^mBiM!(!AJs{Qs_AAJzK*oSI>_c^Lo2{mA89|fj5L4*c`uLiMtWXuC%3J&lvDR zDf^pYLPwyKn1y@xjuZhEmv6|BuF4S9NE z!bN5LN0e9U=1v-(1;LGMx4*uhT}$mb(>re+e{ll4l<9Owi*WuxUL8+0GBe(NT2n>* zW}Q|Wk2nbqoNt$ZqIRwRKD0IJw{52J)f}Fx@sXK#(sP%v21KNzlVHia#YbkpmH8Ymx$sM#UP~F&MBO%KG%9aU>}OI7R!#u3Ql5!ur!xsC;A3YSoDaOB$T@6c zOWZ0p6y*mVJ!yn_oa9~S|Fomas+S!(+1rpCEC$O%{5F(DPc*MM(*xwS$7qtq_2UPO z*z=Y8aIEO3zw{BZD9-;nFfBPNu5P*Te1^9~PCC_qRs}wWzV(@mEZzlN%y_r1piz!D z1P%6ga+&h)|G-J}iJkk|ndZ`5KH36BL{*606|SvxPgG@1PI%I1actX$g0;Vvrg}*I z(%$skOgfBIQgbW*@OOgDx;K8EzhRJKi$=Jp2XXb1kmjyYGX~|q{EZrZcx0?C# zdY&nITfXz8!9-FegDhZ?7DKc@AeF$HE%P8E8}#zZfcR|m#3$6-=>XjeaYAuUy7_Ax zwb9r#EV4KipT)(I(Q9mK!V~PcNmRml&QN?8oxEh!HnBa)0VlU!3P6}g?Hp!U4z{*9 zxJa~m5yk*|qc`Rig!cLmHI0)zquvr&cEyE+C>H6^J-OH%0P7Ar(mnt@_*d;=b z@3E6sloRo6RO|iPA#(fKPq6#CZm8a1j{j%e@eZxtPz8+D+4ZTM@sjcT zM^O!O)|oAGzs2--tlmNBeVYUS{w*CqJ#WFxI>SbP5rjPR&4!NxnvS>6@4`fnzH&Q! z^&#m{ofK(9TK#=;D$4yNBH$xD?&5l!c%skty|3j2S9oJ_mrPpco8{6QHqAA^jGwDP z`Kt+f1kkm=2;Te=Z73WP%yC6sTzr(N3!`*DpFHB?35G1K>?%+AFpnb2csCa6e7et< z8w!%8SODMawICey#c6c`Hp%?>+YhVI4K<2yK_7LmKALpWubfqM#Ksuev=BbtR?B}z zYaW5Plal7DuvBz5G+;+d}Y%hQZN?a0{tqYH%p$eTkWn#x68mn6{npdZX~Yi`nDuN zTvjJZe)>gn-;3*Oi&GNUX``CZyt{V!;BL8qSi3YBbR3f+& z`@O|}3{%FT=9<%A&v`N1lA23U#FF!kIs=bqw}*;#dbM2CC&9BrP)cW@g?Ui{5>i=G*4IUF0w$FjU_%FymMoZ%_$iFxPU0|S|E~K*kz-R5#q4{izBpWr>-hr} zJkRUs|KVY~KfcPFzZZe%cMkBrx0Ps6-wz-_v6a`|=$RY?+xaf~xT=dDyJGc2Jo_Qs zt%QFOSZMO4i^`^7MPFS{u%3mVI(}^M{zX7V8$FR}X~Eb({)^x{@SBi^rO1HgTh*VP zx0jlM`LX8tE_DwH@A_n~{h7l2{)fw9=KuE&SWjCqMH${%Qu0iH5eB;Me#|caak2BC zzwaLWlNh{fK9suU1+Et<4v*e7=y8RRu`?ncbiUHpn)XVk@^m*o3N;zcg_y;*Y2+ztr_fwm5 zRZ06v<{$r)#edqOcI@7ebsln>ZN5`F#<*f`B= zMCIaE)iB?~pN!9!{T9_sm9Wq9J^W|zE?evZF1#6cpKOSwOvwTD!z&%m0eeHOZ4PDL zIDfW`@znJdqfK~uK4xqyc;>`)LD)TK=KV?qI=U1R18NFsFJBhPJ_0{UanMAzy{CQ= zr53+9HChi6Hp!l@T@%3+U}{r~Nhy|tBr)%T6G*RmYrPvlWhy|eCnc)w$JVH;8sjDF zP^g>>RLKCB_@%{^(ZesEdfAKy%lPY>_l1tUs@cj}Gp>{$s8F}BF3au{G3|FGhu>*m z45SH6=_)afsmr^kJl6;v+q)zpjt`G0#}rAxGoA)YwX3zrl(m6(ws0rJuV1K1p0j*= zO1^)G>$>h4?BqzL?VU+~Wa*OQ<%dAo11oPEw|V<${Mno$^nGgX-^$B7(lfWaqyeGD zgh7JAiSMj>o(a5{Zq<_}E1PD66x7pdcP1Tz0s^A1aBiJYKh$x zUejgT$57?@QZOQ&;doU|&jJYM;7grozTK_kbF>vmvb<1giti5!c}w*H%p$t3lo^19 z>W^yO%0tC{`Pvz2MzVhETia6KZ`v`Zp$AV?hcw@51LAK*JkQvR%HQd%UCj>=>urpi zt$g_eI;@FDKMi4BI7r_~fByYP-V{{wmfWplO=dsECRx8nIXAcH(O-(Sr(g+Af4wfs zMuzm$a*dEn9XP%je{}GAE~MU6C082{8_xVE^@~9zv$gJyXDyh7{=h)vnt40z|qBH>v^Y;y4{Nz*cA*fl+ zZgQYw(2zk`UwD*YZtmqTg1#Pc^F~~^TZ-bjzm}Mp-~Df?Up_1dbIa0i3hoWHTo}K<(%O=y^VunRTUi!UMls;}F0&-fNTfw@ zpd>4R1VC9MFR!84K}kWJ6NX_K+6NB&677EL%WXx|$1qeL=RmqlL1}FedK3FAn58Z6 zr4}Ag+O&$C2)1=j-+9z!jwQqIkzE>1&F_;;z-E;@*5tzrpMR{H*tpYlZ6zOa%L{K#QvFDf-{ms^c2Gt& z7^2mXpvxdk@0awznRL>^dDVeM(_p`Evr)vPhg-*?nRhv|E z17W{5oPf_G$n`LH$YS!|n(8C%;Qh+CfmCBT=MsA&UfR%NGb^vOG4X(YdPqa%+EyO= zAZVi8M;~{q^Nst`<=#JuOj)wjJo_Vd1EP@T%yNJ_i$zG9=SWsuddr-{O~N;^DDwHd zc2h_4VdAu|flK{1S>J%W+@&Kc_O=)%yWlOMYl4xbL@l8+QfE{WrHUmo9nNN4=lB}i zlhMG7#GS_}_2cJOZAI1{cZQ||>4R9}=4fhUQ0-CuME5^NB1e+ag_^ewjOxw1W8*MCWAj2&B+%Llb-wL3Oc z7pXT~`x+bYb#%ylDFI4D3@3_gs?=H+DgI&q_1(~Ez;GN~>Nu{8-J>G5g6BvG1#P0T zFlD-PH#8t+_;=I^NMk0!((Y;9dL|mom@hdWF^)~(l5lDL(ih)rE!%!wMgI}`y!;{V zN)+Eh&L=~%j3Eb1N1j`(RjWtuS?fbKxU8gn{CsGLLqhU%b6TQzeWZ=M0Hy!f@no1H zTKoefY@Gu6W2~gCgvemVyb=UsMTByU%%+)e{2)6JsElJXT41625|f!+qm64rl;HGc zK@_m0BCUKw(WMm`2?|&UnOtW(n$Y-Y#;ZyMwo}|{JHc5xj=mWmO8mU|N%z)jbdN@s z_7POVl;*YaxoHTUZboPLvvq_kopY>6n>cqzD}(T`kAGa*17-afh`FUO8QcOFD*hIB zkZzZWs0GBuLnW6M;4LILX2kgUOhyE$VfiG^DI8@Y&46--@I}@Y3Ab!bVe&VLO{}Hr z5XFIJ_vF`>AIxG!aQj_R_x<{Zk%rN$Rf$!r?<}*%!|~}rCAY8i9nbb7(wsA0E@o{a zMG65p^D$8J`}T22W(%5dUe5a)r!ItD;tqo$XS_PbuSQOP5pv(6QJksQMiJBJZOI?ErhF+{e5-;-c#5!>p9W+vSXj;n}8 z6)fLgo7*X8GPIyH$1Z+q65^e_k;X=@SCVACexLkPxB^%xP%1TXZZveXwH`dArK4F| zS(?(HV=2GWXdbMO%2nT~veS_8Ir1JlL|6Dldl`kw!>D__SX7+=-qAJm?&C}?!-sj# z6)-5{{8--6tw%f$nOso`l;ui9uH>D>Z-4|mM$9JT`^nd}(87n9CF?$1jAt2Yi0K(l zXY#-XEU~P5bY!RJpb>FWKpDDx!P4| z0GE-EWf4mbh(QUpWMWC(SNdrO)j#z&>qMAQK>)VnPvIxP01pZFKf)r+dhgPDRAXhl z6KlH2%Bxdv#EO$$WJKSmjmoF=r3iS--X8_0F*&3{IWp}Jx z8)e&hRj1M;;E**Lb&7x7($=%EL;;DBebx)h9%ks@@55d>PK9AgM8vb+pzA7?$Kjkz zN!9^&Gp3T$oG}nT#KOyB5=*?3*23yql0E5EsWFrJ>ZUkP0F&-8JfMwJa9&`MFt*fdEk5am4DgTKsCd%5U)%Lz_OH$ zmMyEVo{T4}OJNjqlUV(`R}(ay8$hH%!Lc8xiTQc8s`~|Qi+z{%v_eGi)4J13CU zOdD$YJ|^KhC34e!&;i@QfPXxMlT4?JHU-iX=_*bOk0wb{J}*@r9Z@UP} zNS+(gVYP}f1{H1RdDGAbT4u9i34vkD@>)vh5#xP>2@N%ReRXUFpVBH`4jy0|v3d6J zB8YqBdeHb1g+=XU)UOkW6gaRDx!%5n+pRm~< zs-0Q^a_}3pF~ITgi~kOvn8R*W7mh=DVr1k<;N;>%M;H2bf^Jl_vRdLDWyV;GnpbQ& zSTrh0bsUc^PaY3R7NYe>TA57o6H^Mk?CLsTGQcEUiAP7jka$KgWh7-WqgWHS_tGck zV#e0SA#w{$vwd-ziA!6FImZU|A|JKrCW9V-lzxQ{bHN}CiX-dz{VDV6pO`MT!tBA} zp3i$K4y4*bCUe&lsv0-3CVg1YA4&+bviGbRkL9M?G7;H3_Eril$f;AG&zC;80xU~Q z6MU*|n)8?!W?0XS#9>e;CjDOQoxyAAqpOvLckFhFwLTx(C)6DIezMe-h1Kxa*D7bd*iRU_#c&|1$-13XF^IeUBF=~tMstagQHs4sPe+?8^ICq2n zq2p+X@?(w`<8Ho=)GXFs0t@Dh`;^*lco_>0r1H>N9-tDvo#zw{lEaJH4fxjPPWweE zv6{H3ET!zT9!Y0K3<5PGS918!PK=~)B;t-?SC@AG{rJ0KC#a}j#)b+L8oIIsMeOIx zt-eGszd|5Clt_V!QRIWcX%eX%JKv5a0H$!}-jfhlsHPGAk&>XFVqtXLWRj(O?L$7R z9qvt6E!R)ejBh=^+mpR7fqfkX&WYQ2g!nuxgQ^w7H?j#rvE(aDwRH*i3>fr)%|(Fv zO*>u`-vq`~Wx_mwhDcvzc=Y;Af$37z` z=RH08u!%N)uPG&Bs`)vskKn>&sG8y)Z#dutBZAKzm-+DoV}FP$BdDrHOiz@>|<;iHP<$me4{;%CcJ$uHquBLxE4e&V*ksn9aH?n;(jU# z`f^PkC<^>}y9RagUWfE_J<{1(kAa!^&Q7Ac^{eo<>!iz07&S?YFV5pNg%PE=z%u>* zcF%TT%-iNL){3hooIh*fL|O#tmHm8`;-B=vmc+pnD$y{y@`Uhw6)OPNnFI1i@Jr~g zfP*M>Hu{o*UyFL9npB*1#AHg`A@YLp?me03BaPC_8)p~R=m8!^+;N9wfNd z9N*iBrZljLDeesZ_($Div=FjZbIB{Sz6WNaROzn><&UDgp%1j#WA3`m8e`0uo}JfO zoSmB+SQxjXyyT7ks72wjXkw6z6GQ)8LF6_eN8rH1&8#n(yj3M2zS-o9l|=oKy1eA6 z&14^*wREl(-9OGQKs4!|EaROms}`o8Z8Le}lpEJf(r&xI*dOOGTfU+|q-#vtARhx1 z5W;tGynOaGTHemM+y&X#!+y_(m+NiJ(U<=)H#qm@;<9ymZ^y6H)eD0KM^Juqohm@3 zGuvIfZuvnx`f{9WhPyR6*65I-V>N5sD@iWgh`)+Ws715iUa19?r+puZnNPvCHJTi5 z_Ir{|-%v>%zBBugQrdIheS{$Y@j6WTgpu}Cy|sP)V`RbFAGaBDD5v>f*gub5B=z(tI4Qf=`;Qp?sNAf6MU3wIoR^VFCzpZEW4p`#sf- zU($zlY0~>}zKuw}5tzLKV|TYV{@NbTFY{}7avEoCo0Gw1xmgoOL28vpZ@DbYCv4y_ zt+(y%w?0R7$5zGRMaEXx7t*J)3-}I+_Y<{Nvf}j|c*o6lXVI$MYnh)xGr_aBRz4;U z^LfxuYr>tf;~A}}o8xeYSFhjX*@OWlN0F4lR*pfQEa%BcBxMa;=UFSLr-1U9KC8lN z!LtTC5e1ApOFQ-pkY=2IbH&eG(nBcEvQR&bYR}iC7zJ3TistEWK&04mS-~9WU3bH} z9=;N02ZU*Goj%?KsMw}cVI7KCVJ~s>&Tc0gN>Up1%knnAx7yhcQ^gfl{>`0w#yEQ> zN>=AXzuiPeoW>IHJ8!0g^uZHJx7b9_Z>PYiTeqB*{!z;DkA>t8qbz=L+zp-8>M*Zu z*W|(cr#Z@9#zL}gcb#@eKZ!mv#ku0I^IbgppJUJb#ZrI8y4r!NaqR;F0=+dS+AOL& zOR;t(H)WqJloipn$v7jF9pg8zE3+5$`LqauW7P@KOB|o3Nn7!=)eepD!l^(2xdES9W2W&GP0P$HmNdm+uDal zJam=XC$aR(XcKm-Rftddh`I!N0@!o+`NnG9{mEnJFXXa@r0b;Ob)|#rq?#sLgR(x& zR8sDL=tupQ@Gg)eRt?w=Mtm6VEdo3R&J%Fmb>hMI=0nRe9Yw}8e?TP-)DHY{K*^L z%HNxZTawJu`z`IR0glxt3{wlXu0{&i zYi4U_-JJ^uS{X-096_bcHk258t-^Thj+?O>;$xH6zIb$qJ-CwXsW8^7{srB=DNm!^ zXYW*WcJ^``Ax_uKqW8!~y(R|)^&lC>{7s^|0MglqWO5P4rMHd)WiFHO-r0rPx=_k5#kct704TGiEc_tq+>e}}H9&*>l0K75Aliol+UK%C)#(V;d;Z`Qk zyE~YLue@S^T?E6*Cj;!Fo&`{kaF{J9DCn9xQjgN7O#fWuw-s%kaHE@Wn{MtsMin z2=9k(A|3uBkcIp=0SxNwI{!bB#s6>W_PS>k$~e`U z`03}k{ataqrv-Zpgp%|&qosv_`J*HTuE#B}ta)1HT6av3-Ja6eh+YVq%Tw+JW-DAY$GZtSo#N)X- zpNhzp*wjA6m!ai}w33kwenA$EHRkaYd7S*VBN?19 zj_SiW(q!d6^>keqZiwjgm||0%8M%lUU@Wc@LbLUCcN!rWbL7i%?fOog5^^iSg9Ea!n#h zNcS%Sb{+E<(^QbRVqXjYTEE%E6dW?$seaCbFY3%|9I^=?<FM`7F!0dR1)HVK|3&CDu8VWo;4}S{P|)61RAa^Ie0E~lccaLIUdDL5q(z@K zfy_3u!?3oPGZt8K2(-^gP+Jel-u~VrvZ3ikOiN8p6*r?jVjLxh%@gD8r_8*Wtil)+ zP{quZuo#Zj1RISQssfWW=#8+9jjbAgb4V$=>tl30Vy~|}eN&Xv1x2}ezSf2}E3V~8nDa^;$4AD>y;L0Q z{e!DriSN%^=f96xY^a^7=IgL~uVE$TCb=_)$@GO%8f>VM7mz`$+LM>O+!@5k7kS?M zbgRlM@kkpd0!M)Qi%L~4z6N=%`+@qk=3bL!1FHnJ{9ib|o9oJHCBn}BFcrC<{wP@3 z6N9%=_Mez5B*t~hU9P_xxC#k7^S!(7*Z}b4Eta9?pbxYKQ|@JO zE9i$hgz+7RjfG8mb1aO(L`cC*l4MOii29vzqG=j$+gfq3D^Wue{#rFT`y)I3ONiBj z5Uwp^u!UNf5{?)JCp0J|Yd8Sdb-l19dK*Bkvj&eU_MV=jfQ|%k`Hc&&j>joIuy>n0 zQ*50*UY*w#5r^rXH^Ap?C<9?>RRt`%>V8-1IuD{d`Y{0+WjfBcCZkOg8V_Jm4I0Z_ zcF((JW>%T`3QyS1caDdB%kV4ZSGIrh=Lp7&_*(Dqo1=~y-43~p3hT4uW=PE2rCXM! zAFiu#AE6S~hW0b>HctB&|MSvKjxm1%u-}7LaBFjo*Cm#TBk@LlId`OXE%p`5m$sdO zA+hJzcb|+FdtHOEoT+4JDXOfiD?&|8R!l zhp%e4IBVtQOLeXH%^4jo4M?Jpio4kqoyyvs6Q1UyPc(|qdXu9*t5g|;8PiB3@2ev- zs;$FYmX-UvhQwA{@IT(?|kDQj2$37pOaK74%l`P_Y7-}=Zk$Vtf`P?Q~5B@Z{B(!S(JL8>U@D)O9JWE;1CN2K{2onZ6q@jJwzsq|07Vb$&y}3475Pe z&*Pw?q60W#EsSChezTa?n^xL(1li;>TsAu|Ca%q~UDazNDIl;Xtv8V$9KS(OqzC>IzT8MpT-^O;0KB3 zjb10~Q9^J%u2u&8eTF1y4d$Cx;`iUj#jOqw^rYY{CZsV3_)0U_UJNV3=#c>iU0{|3 zb6@Kq7an~|eEtzuvAv*s2lMV|j-}cQ^uzOaNvdPPiCR78C*d4D+{6Z;93_LcVEehR zrh+a7kmYu=Zl`CQ_QV@5nA3Ip{1-?QQK>qj!c`cD;hbl@gsz&TJV$^JhUoA#t#`vdx4n4*}PR1)mm`o<64_+ zGv(NF`-UlW`f6`fs%#+vC+=h{5J@_q9y=!Csku0zb>-haffkG$x1iJV!N^J? zs&o)>^0!76FbI6SX1VC*Qm7}_Fy!QRD&8Y6@dgUa`=gMNQd7mPClR-a^EgjBg_N#F zhBaU60dXHR7MqF@n8l~kcuSNLnu4)jRry>aYRgdI-}<5Yjg&X%rRG_j@7-eZ2raS< zdc;n9Rb9&La0dEfm;J6;eu-tBbfTda=k5Fs-IQohOiS;>mBGr<0qHF_=XXSxM94D^m+Q?Y!M-v z5v(anE@r82F=nvEILOc@wW#E4(KV{11tKGQL-_iaVz>S~0)Ntx$OdqnqF9%AGv&e- zkvBaC13;{NR&&>?7tLiF$cLM;P~Vj)PAyQ9t6GQExtvO`EaEF$Sn5;mP@?3|K@?M= zc=MEbGc3AdOws6JSnB3ZybE2DoucAYrrpjP>Y8W0$(n zHD3S#APb&pgxnxzP`(p4(kO??qZ#Z07F=4_To~?!p04+qHeT~^z$C&dGfZ+uq*E%$ zq+SUT8)@7v|De61YPx4g3zmC^+Hn+nt4!Rsvkt2fO-Xs*`-dv)%df#Cc(G(+U9d`2 z5)H&_97IB8sTjqQ(HBilSv+iZ1b~HKAKAY)`*2JT0uTDUJ(C~D$*Lxzxm+ilEgV4M zuv5ekA0|5Q<#{a`4v?u4y8*$b?vPigsM|3|5$*gH=5Wf-0t?FWOC zs`GIPaY`|e=u5}-TbZ`xN){ui8M8>|**-<@CWNX}pYCL%7OR|`lxqp!(-q8@@Tb#Rbr|HSIktPJFD&i$%RJkT zP$k~@BexM$690M9nPhSsH79-FJ@_4)y>~^rrw~M}vzM`qGw?}TbFN)Zo=6^rDcX}= zVx=Zs4u_H?t(5Z4vP9StswAwEm?Jtoi*VHw^=IsvB-_fxLA;a1mbjhvl>2*UoXS#0 z__YBt(~xtuvC(*3Q^G=B8knZEG<~)Nd|#$UmD*HK?xl?()5Y=RQEoxm?M`@uPdP1d z;qG2>@NboVpf_H3t5p-@r6gPmuP~F>a0Gla|G|7Il41=$8n7{wBatu6Q1!bN41ndC zD;x~;kqG*Dt;?Avx7Rw%W&fJ@20~)bVpCI=rYe#4;k!Z{o=$Gh676Jf^qrHzlCUO& znxBET`H96w5wQ2{M!CdA!}4$$2r7orfwYpW3a`VsbWD<>pVpv%_7Jw4XnU$u=`Ycy ze~XdL?j_h4WqzlhGjLE%Y1nIV%k;rfwvgnkkKE*wf3oDLnqzeWVl7!JDfy(Trh;SU z6$PR_YJu{pZ zMDoCV#V6c!VX6r<_5(5bF0Xc>*&&K?S?8KHT@@4gXq}FNOV-;g--s^AlO9pCQ)Tng z@BVr?Paep?ol^AFz=^O@4~RoL82wF1UNm(QX!UPiBS`e72>bm9&CSPgxfuFhk=Q?X z?9Uiw<@_H7dz))Jjl8g7R#N%JP46n#6fU0%l7tw?DOS?pJ|JBk#|XHN7Y5 zt^ROO{Q4%d<^cH>s8=-NrcUit%b=gdZqOElmKDzt?oL5eW00M9E~LZH`bKy`CUEq# zr#M5K2QeQYZ;o{6=>Sk!-Fr-7N*cxD{W)M|+oV?+#w|S6+~!DpfIYy@TR{;$4})(- z?R}S&THNHnIT(+d3+#ati*=Bs3*DP{6sBaT_47)wsN2htQ2&rDGDGsqF3&xw$gH@c z)<%{?e^}B1~+Aq)} zH!E6v9Cd&GHX9ohVaczD$eYuilYudtrIGM=EEMUezcLRs+{>lu?Os1G6aH--VRhcM zvW+LS$;B7>-h$1UbUgVPxId^0jBjjSh4I?F3`zNL;nw}ca^teZR83q{Hgse8zTIoYrzhaG8OL(1PEE}n{MHk$yh`ai9NUe6@Aj_DztV4RACW7D9Mi%CXEkcV`E|?cwY)_ zXba)m&uIcUGMBr78mL6@PC{e9hPA61PW3aa1B1M7N6Kj}?%Zu%Q#RSkiV3fe$Zy3t z;^BSxexA-a%wL>H!Z$C=laV3L{d%GEHx&s}1ANT!##b@~H731$?w#BkTtebqz_3AUZU}bhP!GQ=h0Izjlu*pm8F}TXggJ$>Jdy4^F-KCS&`CRy zG7=4vtwVrR;Z$Y=QOb_AILJ+yY>ST>yL4Eu-r`IZskh5v<6RWRU>f$+iA4a>5{C&b zBX|Wgp+k+^Fs)yjM()`id%E~3d?&+ zEJ`U@9+wS&598~y0)?EkCg~=jZ14+cY%O()DKc)s8D^1?X`Yo1tts7`k9!5q7_wMLDaaBtEEill*6XY1HHn4^pR&` z-^WDx?_E*Yh>_DJkX0nKJxtnN%-=Bhdri8-(ZTBV5s9(CHD*G4T78hbx6vdp5cVM$!(tl(;+Z4ycQLA>*qp4jU-la@ zMm5Db3scAUsu-PfnyGEl-KSHqFp+#&NIkR{W(_xJlJ9?7hCti-8sclc!8W)I-=1DW zr{Nv2`i*jBQd@BT7=}iZ#pJ<;!z?{&Z|BYDemA~HoFV!1wIrvZGSXwakGCowZ*hQosZM7TjYrZB1gL`)qmM=9C)|MwX z>ViIjqe?iMh%<9r@iXV$sW=jhC!ee6`FzCW{=PW8%-jaP64qsFo4l8k>r#7`qu+Dbo_S`mYty6+ zFZ-+vHuyS1(h=DsI8>-_-8de6c&aIu#3H!saaX&=Bxj6>*oq4AFxn7fiprn1AD9Jm z?VZgFT{4*e+EPq;S`)=ug&IxjlHsXrx~I#?I97qCU?M^RhRZxO=zB zf%jv|Tm}J&dgFE1Y)gH4nkzPq$6)f)z;c0ESoEs9EIvb(q<1eT_4JK9%h(u4ZIjDM#-AUgxCKd=1CGUBG4 z=V0IF_muFkCeIRO?ZMIBtp~oTF`}(Zj>{igJsmr=y#Bmi2m%2Sje@W-JrDaC19t2S zu3hJH;6r)rpqJ58Q43>@_Hu@;IK81mMBf6KZX12gI?1wr0$9FuI``XZ2rI#n`GnQM zE_ZL)Azn27yLiku!}Q-jVhE?8VSDawvF97xGxA9rjZ_l**WO|eH_kPaBHHS_$JBa6 z^MjO`p^O~mfn(q-+}7{rHX*~}YqH?{WFKTPIc=GoYo)v4gKcBuXbnHJ!IR6h1wx>8 zJuJiNz|xmOzEgTJSf(yb<@&XPKO{@qpDi6cd$r3W5Gd_evk#6r^5jzF1VPF&d{#~S z*oo`(_UrGw?K@nT^d+B_elKlP%>V~WcI}|%WqCzdLP9zS$l65s{k%^NO!$h7HF)1} zq}l8<)t=;h7BEC_#v8WvN|ROaYD}xK$n;o6>-n>(BJXbn#dNdyF@{+%!iY#@U?&l| zp^G!Fb@Gk#r1De)GQ_gByx6IFNs0^`cAsF~7wgE&Y#)2Z!nI=b@;HZR#FoipKTJ{Y zOKNg|O1SDExo2}xQ4AR5e+3c(S_B}(l-UI+>!)Q<=bPe4GxJEUk}YESh`{DKct;{9 zjKQ7rH0>ZZ4X6{uHQz2#rBMHk{`EQJPp1ZAt;HvpK^iJ8c8Yhk7U#OC)lXsIqY<)f3fiC!Z^3TH$Yc|(MAwQVZip; z&d}vRPrk0AWRKMRMP7%nqD>)lZaHf?&CTr@ZDAQHGS=+HRkvgLbS|jfCAnQ&s(yj` z4!0!<18ra^89Gr|gc&X{8w+k}+-`^_y6lX;{o1ni7PXCQib4p-uhOJ9uY%J+V(;qx zs%9L&ZVxkCMMz&vlol#Rp=^Stt!1&a_K}NdYO|uDeFstR7%uC`)pd{IaL+?7$o$A- z(I&1zov^1tI;+-}j_#)!M$00~l}XAU#!REeTkM%0Stj?_d^lcX0-|_%+Y)8Ou`6UExIzcqDsNf%_t{Nl(v&_v({vj`XQabyvb zBdD>TxnTrIA{=UNd~-3tp-7iLI8vXL*GO=b@`IRBWhnVNnS1;jkFd5E4&n#ah2^qu z{nL|@;fC>SoFWOaobsH(@K-bJONG)8ghCoiWRdac!CYG=qHbv-WLP9O& zR{~7NhXF0|=(VBA+6(e!GLf@YxnMGWR`STdGg4I_IyLm^U(WylJDCt$hs4FPQ-~XY^rPPg(E7qy-PJjEBu&e8kz5xe;wab!=vsmKS4h=?!`K$-+!sQWD^ONJZzA?f5 zc;Dw!PJPfn0P^|OS(xu?=|8~bH{Hs(s6MrSfF-ei0K}xIw>iPHtW)BDfUNR&O&?bi zyIrL4MMRLvN2V<8vf^d?wg^X4jr@PvzW!Ug$N4`)EDp8kw3K57lJ7G)ZavO_Y6>I(@<}?kTqp*~S(Dm)W6m+>x z3hhlI1fPDDH*V@+U->G%>n?WVD_C4gx>XkE<)A*C?}5;Jm)@c4exYB|dSoKXHm?}2jk_jUXBFWJWMngmJiWRMnCXwMG>}|RJ zV#;f^m$+HZa$Ei&%gH>IGkYyW?5Ci*SmexoTlcCd&Xv``he*g3x+sz7#J8ecK=57( z6_k+W!0y8903P{4X!?Z{HLpkJidAZzZW=Y_BYiTDI*d7A7z>k7%vfVvqYoubsKVZY zm&|V6c-P-n;J*E*Up#3R*k`uH#kWTh8yZ87F(wat2jr3yDdrKUt53rt#vet_za-SD zKO`WqaFgA9BTeg|ErcalDVn>~i+q%PLs+<@WEyUTTlnErUG3S=J2phw*>*7}d7$0f zbV_eGY>z{hQ+nVlMPqoJ>#TfOYD~ph#GTEvI?#PAcK1%BaH=-NeJHctSy$6s?kUOA zH3!0aa_H1|(S~Savn6ByFyZY3z6TT_Cj=*6!TNAM29*jnN8|Sc2O&0Ln9{TqAM5x1 z824mTm{aE{Ylw805eyCrIQ5i$2ah#<)5+^z(={pV2Y;k^32muP`Q1!r60Osn%Y_py z{(;s7y=%m6eW-i*8gwQ#^WaElEl}-pBjn)n#*^#va#phdpe?Mj zEDCLX+ixky5^dnzXhujetPlOu-A;N{5^*;_F!O@geT-zzK0JI%hfU``DZYDQ-mrP< zlXo%O*j4vHeMM+9r0DiTRh7%AGB*>W=lGbkb8ioOqcQ6%Vv}BC&a1p&kmfS8ZGb7h zw7oL{NHlcN?r!n)Su)+JtUG79Ogu>!D}EM&(}!M?xsH(9QHHuw>KPt7!czZjskN@1 zSdkCow4i8@?W{ykgH1#17YRg_M>I=$X8Y__WiCSoi|4+~KISj~3W#9fjh3>UsrICV zmZ(Ep`QzGeE2o29KEVLBWWa*1u19(x@<%YV&U(fFnri zv{88)3{4$aBv>>@b!yN-?h?;Bw-J5*{G4iLu!X_Irz&iiWAxJyBdRFf9Sov{6$?T9 z7_*0v+}YoeVz>A@CTU{~YvZHBsnmF(GXw*P%S7k8oAPzwerj%2t-bs*!S05hlSfw% z$EEI073Kdn{A!~~-u3i>uELtZa$(g)Wck|L)eGzvWH#fl7fLZ#zob8u?FH6muuID| z>-|_K<Mv7=$V@S9g+a=~GyZRF>#)h=(78((N%Ung&Ya zzDRat=Q&A1l0k}u&5QsH%yg4BdA71IiUiF_7;OMAjeio3O#ER~R@v7E8E|5gCuzLZ zd6u7ILEMovrX4}%X0CIWrfo)|^_ZzoG)n$A?&KnpIjM_wu|)AoTp9AdO7^V|{&k7A zmc&5o_RjPBVm8O*B{+VzSiVCq!p682l(0m`5-OxFEP0#|&4mf!5A0&Pl7>iFW3fLE zeg)YZjlGUwEDXiJ(rR8-}xXiMzBSQ)G8a}6{8Z9pLlc?Ej~Dc=-gm*Co>OY^*p zt$dwH4sWe|N^EhBycKTv*m!8a;5t{=Bt@wwIx(<|k@4GRmQUCOVdmFkOg@qarPNQ& zaV{C^iXaq#>JLT|bmcw0BoB$wKB6aCit@kRtWn`nHFP@`tXxlkh*Kk+*;k}1aL~=q zR6dD3M{k;_uX{rnen-U_U1cE!(}G~WI|+(%F6g?MQ2&7&r)!{%GAtc?L@SL)SlONi zel=fkXbQRm-q)`S98Ud)dGPT}o#vS0#?J+%Gd&hO@+%_PrTIN1E@FI0A0>Mhy@pO< z$tsio9O=58Rdj-ug^=}V_c{mC;M;qsZJ}VBB)MPs^g8RI1M|jmNh(8FXEOE!fdZb; z_BGs!@$fGT*q_P!${}oiAwOs(zHqCmM(wJyFHen{f>Rlw+<9oo*E&|qSG*QY!*?#q zwF5o2689U0Uo~THJm}|&2}%4a&5j_dIRRyT@sfy9uY1(=g|>0=!}x+2Xfnu zPx!V!ENm1EQ7?0Ft5K_|di%GDDi&*Zp;=Bx%<52jSm~TB*PV^>R_2U^NH4ju!L#*? zh)AtuM9ia0=?sI@f4bBLYn;Z@a=G+JMmYz^ZsXP!x<85TxQy9I_eIeFGrUV^n^tlP zC5Idb$&o+S1!jYL&%B_a;ycdKUmbA*HVf9ijD?wf7(BU3ZRoWpk*-J~%At`(shZ}H zb$1{eGFDE$5JmSvu(}lrTCgvLra~g=d^I@Xk7D45NfvOgOOtu2iM4GGJl zDKFn@OZz`OlH&M@i{tZf2W+10_qiWzvd(b1R3vor$~Dq?z<=+mQZ$pJWVay_Vd<0$ zAsJLuA5s-m-jEZE*XXgEQmtP4MAkCSlQj|gdK$T>;t(ITHD(C7b!PdXSgFWUJ2 zQhrLss{#*%-loVYuQJvAjHQ!3vgkwrK3|C=#GhcBVMo%;I-`2)&a;Ib42fGcXkC?r)#6VmCbn@>7pg|seS+e zgs4lE_8Uxf{^V&@y}#x$|D5kIYoNQ?u+`%`B1M6$ql=;>3Im?BhrL`OeL?JgGoi!Z zUBkAt)nLtK?Iy>k+!FR+gTs(2m6#O$%g#~er9)N0TF_^XCLZM_DLRLkye8u#ZSYEk zMU7E0{Kj8|!^!wHwR^O3&6qjTtX4$5o9KtveQAi|EAW|o7YhSDFuSfZEeQ5pz76X1 zohSrH>zPgw&w&95<78=LOvFU5(=Lw)LgR8NBY=-QPl3nX%gvnItZ;uXc$jRzl!kqJa-@p<*DJjatU9Fu<@A{4=+Q1iK!l07v)Ox_Kq7KL&>*Bp)<;Z3_o(r zy(z`-3_)=q(He;yFQL4i=+fxXk#-VaAOu>}o`-oa=4v7?t37{O=c;3kfGof@0b22z z;$R)4)OTi+dxo`Sj`m|5(e=)A5Ez>YW#Kl4V)#AJGNmSlpI*7eCAnQMs6{q2bTQDe zi68o+r_5F@aPk|a_ghBDx^DNPQV+ql(~e6@;@y_yP8EK%a^x6a4&PyX1t?$3UnSRB zw)&e%zO^Q$VlD+s-4W;C9}{eMarw%z%pvpbo+*FfD$LZv>RP^zi(V2O+G+J*^p1XI z^3*|j`?5iOO)-d-m%5d@!$PMf6mBUO2rsh@GM3>&llnmZ<-SiZhKhnLDYsMBsv@V} z+~kD6qQDKAjcn&ZSDV}k&$#iSC9PEcQhBED9QSj>)X^t7&DjyFhZs{0m?{J*3>j_t z5NrhRqH|+1Ze5aWz5HXxHf5Kof;m<3Mal?BBRF2?7tHzmk9<`YYVA~HW5K5Ta!}tD z?37HB#J4jWPl*IX~ozO><+A!XT#ee-&1a=}NL`1&b|eO7+hS~`=chAIQn)pAkS)xeLn zI0+fT9BZx&9T~BxS=QZAuQ+x-R5`d?kSQ%V6E}pnOOU{aJ2Ed3cbd}b=hk&4B3jgz zzfR;unJ36ZR8jg3<^M*#99h?W^)8J#ci5dWDD!0ex3Ztm2O;`ZNP1tm*G&uPh zy>4L%6PJdQwiBi)> z!o>3ujuA(e%>ZJ`_o8&A+$kHm>}{0kc9hNf962$H2=`F)*k_g&sSh?fwg-@4VYjGb zwa;Puuk<~+1NNa-9<=1^wH_{0{ zLIM7e11G2*r#+OYAk-{+9y=%;vM^wOIs}2}r6>kWZN^XXkeU>uwyd2x#yR>F%D7!A zCY3$4veFGU5L1Q7IeKXRU~aBb84mNXlS@*lstLqTf-n1mj3|g)#94^uS$10+cAMi;j%+#50;PoB;nSO zLIBEyIljZaF8ULiw49$bHE*;K7@@+&;mY-}w$)M>Ro?0I}NGx-XUg(a4a z?MtdDq3Mg))9m}aC)Gk|#!qAbdO3jX)RHj%YZKE}1gT1tLn!wnPLV4OBDd%VPHfv)@N78g^3h_WkG|cW3Epcvg@MOc<9Z4SXf!MK*{B3-reH1EmTlmHjzsxcT2k2@?|8aNYn>$qTP6~8>UWyCEAEl$LtNjr|%pq?0`dq*cqVEMH$0W@E4 z-bmkG>?eqppF0RY$;;&ZM?&%xtf6X$SV?fO3nx3C>P_FKDj672k#OZVH%1?ZJEEhf zA4{-^%~^#gs!b%W5W-#6G|dfxG`L(HW~_)k*sG`}h@8S@Y~!w)@IyzX0tM>jc_Ze> zik5+x8VOQ=m$YjvtDd?f+X`KUrHc(+5@shrjb*f{ipkS#p3Ro4lTV+`-x&&2s?1}I zFV@vK1m4DHS~4!**et;xRDxu!3a?oX&77>ilh+HJergkc%{|ODPpKO>6-qN&)(mU@ zDS*5_;y9$z5-9d-W)sKJ!fwFd2sY{iqFg|)|DkORMI8Ck;8*by02%}QZv_twjmW+f1$}e zN787Ot+HWQ`R|ZiutS5%blz4_kS=rCH`MoRdQAm6`m{bn?>IR8E&lNNeCTg}cGqq} zK`562eMsft@tSq^@I3F2jd=_0{9v6{zm%M>W=KveBJ!#F!rpF#BS(F2LV6w|!BxTi zB)pN3d!-(dHh$z!`tG|hscq9C8j(&3z*cq)y?o3Yf4?`HPR>9fbk-ASb$ll#G?VF0cwa$rkm=Sua+P7RYs1CoASf_1AkT$prM7#iO8r(D> z&|YaiJYx)CRS^;MRa%58SBNXuZZZ`;+@ezKCWk5?9Ygz%Dvv@xd@PQjqUh+oad7i+ zzEGLEkhMw(HZvKDX>0!=`Igr55Gmfd)W`iHV#IifdpT7FI6Xyo*;$t1d9J$EusE&sCH2$h|a7dKObpI}Ab~*TSs_HG2;H^L^;5Ja(AeEKSpa!L-bH zb5XQ0Cy;avp>)4DjBY0s8=^^Vj`MkAR-e$>omiGfaVnh`vzrNjh~{F{DqdNwf3lnQ z8_GDDgOkqQuT$IZc_J%9IXFU-stILW@7ePSJkAzEu#VOW_X_RFx*12MV?lnRZ^J`@ zuHmr^ZKpoVRSw-Ed^f9~7>aI)G>v#gQsfS@|0l^mdR1J0csxJC!Lb~u(?8>!e=_94 zl^5mzRuxeq07e>%i3u2g+<;w7B;7|?quUGO(i{J_&W=SPHKs^FbP||k-$d`0H#16r z%<)4W>I!=jQ^PgBxA~sXS61Iz9{9oM=15(BdSzYEK+&HI?`-wre0c>fHR~@di865& zL;C?H{ComT=Zu`mYuEBFc5XrMfq47kX6h(>NtvD=>=!}IN$9Ka{?!F^^IGX|+Fc9_ zhTe0|E8cj)XaCXil*C;yw?MUIu($uv=^8Srv$X7^_`x$~t?;Tl3efW9GvMRB3|Zbg z2Kw7|PFqo5PIatKQ-4+eqzzcPITN= z3((jT)Mc$@nFEm6NNj{QqyqF1V*YTjef$au7q!ZvY>k3Dl#t@#pVsg+444~2l`<&4 z{-a{?_^~(Egx|nRZ%b-a2YHD6NbSj!RytKggw4itw|H%SO&=4t z*hATMTwX7&N1)ws<@$0>->0F&lZ{R~uSj9^unC8gUH zo+SkZ&DB;<11TV?glYZ(H~upQr-(9k2deJ?rEO!<2#7c!q8tFzi43@fbA@7gzRQ@5 z`--Y>%cdRAS+<|v>gStZyAJjrbCTW;KfNL1jNNAKGQQmV_P)Cw<5m72TFL(e=KUXb zJ*q>OSEq)rUVi=qko2EmGDaQ)jo$Y0tG$hyBFU9B6y+15!zeG;OAFmFgS_p1CF8)aB+w?{e_a7eYoRj9s*W(pIo$^_>{Xg)-Ly==L`y1 zEN4BQoZTPSG_LpiSp5Thd?I-Z>J}`TeiwYJA5UG%=O^r*-@R>?|MN~rV@JP@@`X$e z@qsn*Qv~C^)P6$8$i&;_yX2&h%CP_D#oO|9V#|1$ruu?;5cNd-=`C00b-FTh9`)(* zA7D-JS?XH+9ko1R?$)6j(f7t`mF2ICMqscYcuT8)7B}%OVkKq0Zokbw=Gyx1*R`w> zMZJa*gl*n-T%@he`Tq9+yWXjX4*73~d{6E7$NL?xxo>kJ(FNSn9#nA*vi^ypDRCy5 zCX0^p_n21&a`7V4DGWk-6(rL4(UGd^+^QbXGp_9re`+nLF!WDdIZQcNiw^qVS8=~= z0DPB(Q~H+9mP|+!`AV!C`86MO)Yau5z-TY)dRXxFF0Io4AK=gZqnlXA+1x+CLo}oO zmBT~H`m`*5N+H4x^~ z(F8*WY5;K!m=Kec=GI10lxRj@9U?3wcKR8x0+}|Q2Q(3`Q;2)quLPovZgJ0;My37% zcA%}yU#$Vt`++y>UW_IOcb{dZj&Ob`FPFJldC=Q9w|FePS3~N8O%z!|E(_+(QjAfZ zl`{8KB@~Wru_$^d)E+efwA|G;?NJ&qep9O-kiC)8KYR^2^O`h0-p!D% zkjLrM?yps?;*YZeXlrRD4R@P1?H=oPcjL+5<&c(mc|ZH!A0z)-)VsF(T0o~v%sfoR z9a=mQ6qMV?$3G#S-(&WqgI({HgjUR}Hr-5Yp5_L^61?bv6;-`)Un1luI&0g0;Fii7 zUIo3so}B8wn|0t)+)ep?UIPhe1MlpCPr=+%8ez6um^t%83ei2$y6fo*c9-V$p58{? zSVi}{_J>b%Vmz(H9+%r~cXK~XCGA3}YV(GUuH;T=A zmwpBtCy%MI4SN(M=47gIPmI+#lXK_vP+7q5o-fM;kJOJ7gm3E=shO*W^hcn;jhokb zh}Cj=d+=Ge&;`i}Qf@}5S}2%Oj8?HKM=G$N>EkdoPmtjj(1iKI!>eq=O{4-@G5tAt zl`ONZM+3UbPDMvn{`A6k((6nA4JC?~UigmemFv(jZV$Is?ZS7~f?3c{fSV_O9vK(I zr~F&N?7Tkpfdl{VER+54dJzq}5}K`R^IYcKYPlURrLC{o(v*#E|M}_oL73A-v&I|h z7uj-X_COUv<7?TF9J?#>;uVVP zim$~Lf%lJrruq@quyD(>6c!{Zq`vQhNwq7eT9>>T?b%sSwKbh@%pe$MUP$lJ@k1(j?DFOwk#CukmE2Kc^R-FwSoO$nRZXG|HC{eO?%4Ls3R z0{$;tWt6%zp}U8kw2X82KIM`RT1zXM;%pqeSo_O!0n4)I&Mm^O*6_rUv6tUYY>h^^ ziJZ&JBXm$xJ>+*2WoXcU`8(;P)3y~=I8xDcUqWxdL|w(j`&n2ec?HN`)@CU&Y1jd- zwdv!88(L39Z_0TO-ZSEZG`X2l&i2+0P50kgHKOS_+oC@3p5|&xG9E$gfxt9 z_r$Q!kKUWJp+oS*OZ0E2f|`ALX$|`TFGy3kc1QA+L=`wSl~1z%>xK8UU^tQJ)N z?RxBS#kjAs39=lKNU0g4^1d9rB~Ff@5)!GN%g0*CYr2KP($g|+et4S0XNkVX#;CcK@qytcqL#=vte(R-s-v&& z%-IGyQ0C=~LU88cMjha0n?&0YVcw+SYl_@)QvQ2pY=8N(L)kU)wrAQ zCrmJ1;ZLirWb3HF84veNW}uQOS@-Qcz1RyiE$JblDzAk}Uz*yyl$7{eMapTot0qXQ zC5*t_oD;7Mx#`L4#eakCfzEKD#{TKZv0p_2Q6EGk*^-U3x^r>{ysytWr<@mBrW3TM zb0C_g82uy@5=Lf=S5H8kw9RT!YDz>GoSf+px1!0zhV)2-5?9cPwj&t(TiIXiH-N8fx{-T8p4D7Zr&uk0xu!`=T$8O5)??!AN--XNKwl(*6w~bu zC9iF%+H^g6r-({$Yf0}s%IRm6ouUs56{-xmMOLWoR9^w+dV45n=!7WEFH{QmKQWPWe%=>(< z_rPE$fVhXS;s`W~18LwSAB2SG=?x-QZ}if4$cbqZcrhG~7*4 zRi-DBt*8g-9qxvR@COTNbSGlx0=cdA9)XwF-KB}x-wu{}4Pz?7J2=O1SIg}yYM!)l zK>3K~KUqd`rJOD);uru-)sN|aHG5rTjXoqVj7{ceI>~UKiEvLF-k*oVK#Jx+wYXK? zRPac?p(dP{TA;^V+F`@IoKHaO6S$ebSd3CJ8O}FeX`J@GNgDS+{PfvJtK;yYOeR&8 zbjuvc8yUz6c|r>0o9TAIK(J3(YM&duT9fIR%3|@#LHcsQmE`3{j+pqJJPh1pP-tOJ zogaqN<%8m;UL<>2iIt3d)Ccv%+9az>4e8{*V?~rUBq=`5#9aKfEM$XY6KhiOm1r2k zyH^>$(TKW;a5i`}{O=!nGx$p!`FB#7bH<}B*7Pwbs|HN!N|+J!%;JxBxI}-0e>i?Z z|81v43Xv?gQ)(Jc8!Rx%Ijz@5B&_sNs9Nz%OyB#(rGivBZi@=*1#=7_)@ratl2W4B zgz+9U3E}|`$j9MLxJP_yW%oOw1FEr4C7Q&r2}_W2kK)&%4wV!5k0;V7HNa`3VSgMEHQV^fMhGDhoDH)-;LhrPb^%)uShh~}Q>w?$r2D}Oh1 z9tZ@rd6{NN4#1S}FOaF~4g_JLf>X7&P|OZ}?D`B-as0gNIoHJ!B?6TUHCEh6y>=a_ zn!(Z*oe8La+bu7_=sFMiPEWccih+7qIDyjLj-60h7e16`T?3?;LRRsT#U0fu8C+2$ z^T!_x`KIBO6tEN-zfG8e<$T>YKSv!ZdI_9{zvEZc!%C8AEVF*BEgIX|TJ4RI?V@wn zyLE_-SwvSwf7b!)Q3~#09zLN$}~Ta zx&M%Z=YVVZN1|de%x;;W6T7@H zqEDq!OmlHO_05HBCE~k80`YH_N)&aFw>M6PJ3N%2JnuX13i(aTY^4cU>Q<`(iNmZe=An9GDGHZD6(@X1GpP4RZ8nymhXeqtdHu7p41%#8tAl*if_ zDbIhn$t;D%a+820T5IY{cmLo(g0Y7k18v(@6k(hBho&M9COS7keiJqgYep9HlA_EV zE_kHyPs|2e&`ZjBr84s3j7V}JL;^>SrWrk|*}sHC$S(Z(jW#6u7}U8Y*~GX~u>4|V ztAG!GzJBF48-t{4oEe(b?yG(+tX6fJ3ppgj%dD?NFcm55M^DK+*yng#CX%KklhoSA zeeXO7v-E~xcmb>vW}oQ`aJ0?`Q?mIJsXJt1sVDY zFd;<;^5_=epK&d|1xo6d#|rLKlpc`gDe-qaZVBG@g(~GDp~hO~aA(_}5dL~1>&ZOU zVlcp7gx`ob17wi5s~C|*Z?pCL^YWx-D4gfLq6Y33g>`fO-t`jX_RlCR9Z91v{`bN@SdVMb0bUHi-*JRv9&WbII9&d!Y!PB_L z&ek^X+Qfh(8Il8Gj@D0cIfBAGAFC%F*nE}il&6C?)Q|r709UqgBiEbWdGE?9OO)A1NnLx49etsL0u#bca@PLAHiVC0Yv&1bn+3UlGxn z(jhCdxp-z{`)WO4_RvH2XPYrw>~`jRJ!EpO7mwUWB-fY-xHc6tO|VM`?OEYX5CC{d zir2*%!}sfF9c=f7AgIyBAepsb#>z=y=STMEc}_LWU4;;$|IG}=ZW;v>oz_!m)9VOZ zbL8@K#qV)cA!8$BZ(-SYsVxapMobNhoj7yyMm|$J@kTH~(ta#GTy3Z=Xh26o+^lO8 z8t-@+8ik@Y8>Wfg!)Td*aP|1!@BQ?30|xxLdEY=IM~`T*&Ph}_mjH9hxN8qcVR+-i zo`bYjlh$>@Sx8Dis$78fRXTvb)JwYkY;AYiFvFjgmwmv4Cot{M#&t_Kh#(s>Jy!n zViGyX#hajI83A20sY`}fWX`?}F_DzwC^e^P#X-%S7|9LzaK1t#Y}}lHbXBXPrykf1wzk#9yaP6Y#+u(#B22M( zCA3~>Wlyfe5J`3j?18UaKV7nTs#R`%>TbQ=Cn@C5vV~MF@+9TjKkwYtBME2zk=F8{ z3Qh@1=Ncq{)v@70NNr0c4qZ$=*#0J(rsSF`Rg@^ zM)p5P*yMvCZe}Snw$-$M*QA=UF^`AavU|jfx%oWHUz@f73;+`%%Ja-9I5FF z*{jv(>Zf%m^{H4znF0y@)E(>ziw>}0dj9-qCjV4|E;V59-k?bd|SuQ0%$)vFT& z`-F1pOFyQw$%azOL0#;B>A880=ViVjiVg?O4VyUe)UPZcx3mo}A}AV$*Y&WPcAGS~ z#lcSQ#eYzX&H*RSl8{wJ-sAK|T+EF*Nw&y!x1ExQQ6E#s$50N1&N**MdgVzNDt?3o zOxQ^_KS@mX?Z*lZZ*$I@9g8As~nd5P!SP%PasK;~@U3jLDTArff!n7Y~S<>+()f zE289nWl5(FMnD%2%?pJy77x8*@8^9=SmBI#uk<`>VF3_rxo!Q03h)G1enzptzo&++ z?KJ2~3GMXj3`A}azM^0@#TSIhwiux_^fo2ZScp=mf>_x@AK2M*`jhXZSGvbI8=8;Z zrrJwOq9v?X(-yS%wT{)<^K}0=Cm*A-ehlVYvFq8p#3H}<4-i=~{si6X*x9}wm{nOK z9v~hQ)X<+=)`F}5e-*s+$8$qmU=1y+b(ZR}j01Ewaf#TZ|wQD3kb(~bp)^&j7# z9O6lE3u=LLwLJZ_c(?9;-}33_jtTa2P_j{iOJajt-7M}H10fT;!L{`l0{r|KOB)(w zQrTiuP_rI0a+$@P{$ec)%&R>3>pd5bWN>_p)F`Vyi!+D-hJ6T!TA9hw&_FDJ-yRIg+ zY>n<7xsghP&-c>0qP%r>{3tC!NKuL~XQkg*G5%b!_71Ppml4Z)w&hT*M*I8YS6+^u zUcgFBPj;+n{mJMO&v=orxyFerh~Lg=+I4smNUbHK*)$+ZK@xr^Xjt}Du}xCvt@DX) zk@x!re*ftAu8{igR75)SC|z{;&A|L!p&LC0tQc`T~%_me^g_(S5$x4^b z@5{JSL@aW|9~=**z7=L+`#CR?LWg$v@-DNom)1RdkKyZf$LYPSF zMTx8meLQs;dTfF8++I}*wD5KO$<~!k#hgzLabt|z%Fp#dG3 zB=w+@K3O?EtA5x9ik^-BqAUX!Gl|}8BE~~}=islp?Tr?os$mk_M@c854>|`)LC<$f zh&x-baGE$=V*19+7Ay(oJg;rh@r7JPm(~}@%`(jg#O-ic(4w_e1=PzE=hhrJ5UCVT zG`P3tkWR}A!0bjO;@Q8rFk>SOV1vN@BU1M?M3VuNqjr71CAZuzKq4C5qMBBY>+ldS z4nByYj?qk!!~|_#%vQy%KMG3+WgU=8_bn!}+L`id1*$o%dULkO^RiytBP6S@NuOCM zpKj*^#JX7yD@UOv`_@@}#89~{t_vW|Hy&U+OSbsCG_#X%G(CDI;j_adsFhPBd2#;M zkx9p|$7$j6X4;Ih7u)!OUJy{%1MKHz6ocL&FA$J*3TgRimtb2Xek=oaRCuf9eyE(7 zo5f3dx6^cQkF>^S@5rYvb?@}l)?R(~{xlD_X(BMv$7$w$LxcWtLghPhi+0~4s>IN` z9JizzpVU`$?LI?HpMi7BG2RqnzAd6G$HNU{*p0#r?EFl3RhNPkJx4M#y;+6V40GXx zd$C}BeYn|{&K^9!%Uqe;s^=E76uP{HIfM@hZgf6I*ByeaybL6YC#bjFxJaBY&dWva zwV2_`h&Wt!Px;dr0O<>gatWf)4%`Ui8#P>N2k_J>WrOo$ekchQ+SV#km4}S6jSlHp zqU^Xnzi%MkKL#`ZocQ)cL}lHc_QW$TGStyD#$p;~U0m{9Z!ij&T8?UPms|eKPC{CYi6Z&)ztBFg?wTA^?3H6fr08Jeh-f8p%t{DV#~T%^-1^KUqUf zrglCay}{{PidoQeF4UO5qP#G~r8+YcI`a+a>;((OA6}xtYB2C&VP@tvS_~BoQqWRf zrq88OveGYQ1TK6%btGPC)U#OL#v-l;S%|b5az7IYtu69m4DpJ%uef|Yydjs)_48Lt zpZPtao*cK0H+x)?$%Z3MwDnfaBn*w5I?w54p_^=e5bS&8p7b(G#Om=Dp|%5)?D7?) zBxs3xFL0sBSDWVS1@7@bWIYjp#z*kHYQQzvh)P0ttxc=DEhttz!!r2OD=cTn=2AhF zhC#R`VlyFk*fk3~!dwGmg>=3#kAbH!6!r^cEC-FBYnJVHZ5~_!=`B7S@<}WDNyQ=2 zvT05Y?{{anw*yfV;gL+iW-md}`Ajd6nNkf}gx>N;AwB9fLksiJ~c)x-zO%+0Y;%$gFU z_Nmfmr7+8+o93~9i6N-`c}#+iDVwsVx|6JEN8JIPd8R-X8}3%eGg;<3il*^)*M;jA z9{9~m45DKkkKS?s!K(*N#oeu&RGdTdo>A&1G^bApBtCSM^tv5%gk(g{M+ZZe;DX{R zoZ4GaI3N}P)Ro20bVME%wGOm9c}bS};M52m?_7~p*_I1B;+dN5Y8EP~W!pwnvf7WQ zthKO~`c3JWb${5)PFzU@`03c0Neg}y@6%=Ijoo@cwoaPS#6p&ANpWi?>Z~*yrgsMD zdhgC^$|q1|{RH19SBp_11%VR#1|b*oocxF<6~iW@^RWe!5!#iQJ&pjD1r&PgdhCgf$G?J7jC=*y)M-@k(dmw^%Dxy;@ZOz{M zF22OC!ZqJ(PQAGU7NgeM;)Z!J7naQ>4etj0Vs|sZHbd9dCpwv^Bm_hpE)|}_eiLIX zbzTSEcyG|-m&kQs_&>PwIX{sF>%G!Wfx17(>fk}eiZaNKaE~gJ zooeCh#h->M@br>&uC~ehe5o1S{k0zLPdsGrB!s}!GU`OM($s3PI``XHs-!h9F;T24 zLf96Q_BVBp44jW?ZMIH&m~ompXN7S|hKzUqZoeiP3Bu>uT3(R?dlE%GYtxFEi6||Z z-3T*U+Qu-hk5qoAvdk#m%b!4zJLdKa&Dfo*z_u0m^ks3{7W+xln##hmwqdHRq_Ey* z2fE5ps(DTI8TFOls{L+1snHk$rLZ^^4fI=5B1-XN2?`5iC)PsxNmb9~qmfR>Fw8r% z^*rnxPZ{M%<&~!+WobQ2js!-7rd;l=TbjXLP52gG+V;%U(2C2R^?7@FANkO>0^4SB z=uqx^;rC{7dGl=&9ibyk)Dd9@Meoba%HlwzIJhPGMx|g}CIyU8%3a}keq*}E&whHT z0c%ozYSezKz=LfTD)D8Zr*72%kTqsAKP;1-Yy=}q(2K6Kf4k{?d!`<=hSn*K;_-z! znwM3b2ZwBq!6S0s&1p$ZQxH2`qhEZ31s)djYPI0_S2&7VO>q&X)XgE*l*L0vI$~Wb zzrI4Ts!(1XucMT-opv7*W2e7XY4~NUBwfK$ElM>yEJNn2j-G(-*Q)6Zb*7#|`O}l~ zxdGRa!t+VhxlJzThb|md@$GQjqV%Awzf$=S1Y^7EK3gkBS~vN+3Dx;7nV))$L>A(XqCsO5+diOh_cIL%cap$G(y zJX8L|+g3pS{xM%4P^xZDRb}Jbk6O7rtQp4YjDK*O&)U2^G^+I}^&s!;I~XP9iCI`>GIDKa z44Z*ODxp5Z3z+WluA8>fA1$S=C=xt#HW4S7L58W~6heeQ6jOQr)=R6%VY&0gZQ)IL z&3$7tS_svb+)>*xE*@UjU5(Sc{7Aw-Z4x}aHKaR1!%wP)jbJtWtqH(<_6TS(DQRa= zTd14;;OfQ_xWLq9 zy+h@p4UIi1W@cGBNM9mxuctPZ0CTkRTiBT?e-(W}#Hok-`bVL7Rq0m|5_ezfrqQLg zb~!NJ4NGMFv>N}S>ol7*dy6N5NfLxSvp>3R)q}T->19 z$aA4yOZNv-jnka`EXjbcVjEUhkRB-l5(5lDc6X1jUDC{2H9HG8JWhv9B-1n?@!}r zv&}-rYPCIzOF(sZ$4qR#qX#6dNG$y zXZbU$+#jhc$ZrPPr_p8-L)}T#U{TxDlN~4#J9Gt~*CB(gm*;U#1%x$-X2vbm)ThH~ zB8{0>Og>nC5t9C@sRE(1S7nl_Wbe5=aG*}ZvWuv^BvkAUL;PlnsY5yru$4fv;j&9s z!vXv7OH&ZS4jr1R_gTy^G5L4i&7Z5J9iNQZGi-2(Q|j~Fq6^(N;T0xosjPJlzEh;9 zB%X*hA{>Yw59=J6o0Mi1W|q{KsxEhvC$nGw9k(>#+u`R?U)xw;+(dpGummj8mt^+U zljWce=5;isTpT1P)cS%+i$Sf3GmS?5kzbX~#5=LwdUX$zxI83rf?6RVxfQ6r1v*%q z%q-_y3)s9}>+&J+2*@Evke3U5=|3fQHy-e~BPl8}r`_O+sE6LsgVX5o8v13rU~ z&lC-aF4HU)ThU@QaiUU70Lr2e-DpEgrqL^wl zeUx_e=kC!1=EGm+ydSJTGnndHN<{~JR`Xt+-KscXXcOn6L{DjuMn3?ZO5>4CHBIp^ zfn%{&5^Bu}v%iX{z+Et(!5h2TpfcD=boP`zJRNh!^+TvZ!5CO-+3PG`)%dm z{FTNvVV~vqh>A$wjfAW!r1c=KcAbZn#KXUD4K1~}j1UVmvuxH(7&H2y&8JDrC7DKH znbI96M)~U+Upc^W=&z5brClwi9xmiF8*G=`I28d_{m~#@2?r5zUvjIxpbtLql*!X5 z2u1+BpVk0OmQTD=L;CYY()&dFbkfjSJS&IuR7FS?3W%eSdGKgRn{@aLarmul}bQ4{3g z+=Xv-O*`7fy(q!Zr%wZ24Q54Uk9kb`+5q~JtR_8H7T;L^kIr3E9 zaQVz%&-0H0IZa!F>x2mHm;~3lB(@~d?0uqkh+}peNaryQZ+Jt(aSkBQd|pNNIYq=o zNzzQ^JHjH6yoZ=U5st2Asoe6lRv~Wi;RgTyQEi(vA5<9;%u8;2dQ@puL7QMu3xM$m z=?d|^7Pk=^Y>SR=hxQPqPzFSi-L~xII1Eo?tAej2BR>-5)p3&jE%Y+Q;Nkbx>+g8` z*QP50EwA)1pw})x_!8u8;5p5U?|Owac5=uZ55B+yOSJ{4un= zm{0Q*e(%x<=nX?N*5~U$L&&G*Jzhc=eNvUXMOarAoXpHL@W`*k(^7%I?(;FW4HnSG zw8e{ESO)f2ZUgq#nG3E~-Q%xMSTJYNy=Nbmq=va^B~>D~>$ZSu_KgE`#*st3Na3wQ z7hKo~mbwUH6r=DGW*!vZe-XhnYgDhfxw@1oDj+@P6(wGFc8tUa&H;{uO2cP}Rs_b| zGbEp`ctU-!T9upFY9;tWSeW z?0lpPAjpF;Zp2Tq$pVO|BtzO+W>!BSf!G4@IUkd0bD?S zT#f7nb3?Jzj(*d zea7*5YQDI2*4@j{h;*dZ`JVX>*JmG_{z`Pf7P{qul-wf`FMrzxEWa|RlnNby+XDQV zTvzF6Z|c2(mrhU0BX-Zs%tj^g`q1jEAyz*uvCt4}bS(DpRRBWbQEPEwVDG-Pb)(l* z%g^%H0ZFaCZcFniQy<;;$U;>D(huUfbF{v)8cEg|mm>UITKcg_9Gk`wnc$k==riNJ z0@(-Py_FMcnQ#%U}&4KdX{9c#9+0CY@lBYB8`{Is9A zi9(|cY58(ce$JTkx#4~mks&dS$@YYEvo!_I_lr^T_H0_DLn$7DSp^HymOb5i$qmwn|#*V;H_yeAa|6QZgG( z7+;ekbiIYJlExp?1`|>!E`kBjr>37S&2=D4D=}52RfYaR!72`DLiviDQus!zjeeE!1>!+;K@U-5-+g|NI1{U-}{5{QeBeW0}RF&PP)fGUuNV+bojdYQ%E zw1N19c)_=%j5|-D%leOde}6Nh6clUGVKzI|x~yN)59X#$ZkMDRggU z)(g?wHyA5a2d6}|K7gEEBamvY5LXxM;<0~M+q+C!Q= zyc>#G1Li)Bp~&qlw8wUW=2@f2a^$vTbX3MH88UvEoQ{7Jw?u}(VHusqFHI7l}m)^6+2_TyVUkYeLsZ<`5?|U-;xKx*9;&B9HdhEmNxJ$f9M201M;9DHoR-Z?p0tv{pX(K zK8y&ao#8LhpXFdQaT+_gmF0t3juGWda4m*Lc@srSFZX4Qcb1HWJt5k-eP>v=0kAKo zO;!6QL)vApm~@MbQ((=v&@aaugZhSRioiVOc9;nzayJr&RH$6`wW@fM zCo6_Y0^3$Ag@CHS*i<3rN130UirD-vx|OpP;Q4}rdd)BcqxE3hqk1^NXy_HR*WWU9-_RNm}A;0u>TUg!*93|8?8?C*vV|W{#L1)8?)gYz?zo89Ke#2O{Ra1U&#&T-KUdE-?Q{Rnm!aL8PfhH7&ie;nPY$NDt6NUR_&2#?Ps@0+-n}M;C*K4g~8?CYmmoH zhRDmeA4IM$4+HxmPxLSN_P-2s2mO@++0P0y_cdNF|KP;hAICnw=8Iso@jq`}e||}N zjp8+8o!AyB!yJF5J$TmYcr)(it-V;p{)1D_4b>-kb$a~pI_xi*Sxc~Y`FR$3&mY(I zm2n;T4{p-_wc#y}U#8T{0`}*7LHP$~E>bYIh<^3(;Sj;4JEF}W?~KKNpVwdKZ8gsR zH+`(?l12OJ71Ct~GUzampkoE+aMh1FdJg0s%ow*~yvi*sBNL#i{p|y>3|&s zX>#8dduMLXE0&ChuLr4#9p8jlOI&f4=f((h$b2DY(XH05&g|nc4?uJv@use;Bl5!P z#(l}>NSHc;Zn4OK7v=YkbzP+<8KZtB06=_ztkvat90{B1@Fum5=l>od(!_Pc*@Z2nip-ds91i`Uat<{&EJUfnOxhUc(4d&qzAE zsAtQFJPf_Fbet@WXE9DP+?+)Js*EfaKDa;L7kq64Zi5)KS!aqNi7)S=MqtGR+fe~; z(F}d7A_ApxO;&qty0oC_4MNDR7k~7FhMIn^jX4zESrJdV=(%Q?Ozu*#&-wsPyaa|pf}D9s*>n>%Tc9)JY99z;e#a1t zU|A@2vc4cg7M1Ana_R-&`pf`*#|N8B!zr}w?{uKH-$%}&@>}hdz!MLl*r;2p8{R|C z72grEAg>iFcUvdn?tzU#RE{tsA15RC(_1&@(=(>63|Kt5X`N6A$*=JKooWiTXi~Q1 z`(_0&jzTplBK3DqnG->R(y zLn`dH5SQ{E#Rhh;c@eF6_A0JHhZOE=R<5e0wSPK89+2++%M5H!eti?SZLJIk+p!DJ?wO zh7L8$Y3pgZH@!jzBnr2F1Xzt}>hsV->s)!BN88;>-FPQ+$@xHik84a+Uuk!^Q}{l< zs*;ACjF&&wG_f3P(=?p1-$plGWty)~S#qExU1aOoLb}TS(q-%I3nWs zG_Jm5Q&;WNzzNhhWk9GoE(fV7>+cw_`nIXfnIPci=C2X@fh;miJv7{$6$BBTWtnuMNS;%1qEO#p zpz+n?n_Hm*3?(olb8}G(|Y_bY0U%taj7`DDf>2djqfxfo4Q4*a(Z z$l7ZDbn=^qEV!uQ$}w^~pTJkiVY)gA35i0Xc9of?c=1Vacz8jaEa8x{IN7A`5Wv~F zvzi(OQX`7|i@#7%E!IAtAm>fKG{MD3qMD(?MI*jHiI_ATd=OmI1d~4$ubZVnj z1GKBL9}57<8qSr;uPg>y$r^WBh9dArfJ@QG#ziZ^F!+K$$mpwwO;3^VECtr}kEd%2%KH&rRQr)<`9rz}MF7A*@Oc69ft z_bNv5PN%q?^jr~9QLp7?+GtOvZ2KV4)xiEZ#}sVZ-XkLY3a71A2Wt=ZQX8-2NDM88#+ZrIBC zJn?m*^w=k((tE%LD+;qcuc=$mh(s<7DR zf=%uXKCXr|$7$Ie)>Y|}g0)g$h?hh*r<~FCf0G-X4{UNV{J+_Z*K%fLV;UsS3q&$3 zTS-bZ%%T$EaKlf4vNr-YKETNZIf+ow!A;wm?-uv_;l2{pR{yurIJyj#N1#{}YxImsOS2A2*7%}P zG;CAeX&u%&)$dQpL;EZ_OAPKpe*Yz7B;NV2y)N3UzD_olFsx&OVhtqAi9q(+mdRAy zU)s3<$oH`{li6@x4I8wO>vtkvbUb;_N7}hSg`ENk4t^R413ELUWDn zk|AC>0EnH)?D4e?fc~^f6&71+%dL|TbDe2rjExOlGF4Q%J#R$Wsr!}Zs(D2Go#o5h zK(n_xSeS1NE{~x`&^{l>zwxpj?~jj!NH>Iaak6E2f5#2rPnciO3_Qr$17L4?AY6Om z6l60&Qlw_NKv*#d-Kq0Un{&ZKboThVBj})%1<8)uC=dwyon2>4yo4Z0DKimuJ&C){ zSX}u2Pj-FUZxwX4#4hV9Z8<3^IiZZ~Rgq&xD57gT1j3nm8WzrbW}Ts z7k_k@K3x;pv2Pc6R&I|mX|1W(tKD0Asm$@QRU^7rJ}Udoz?J2E+13YBD6r7{lv6n1 zFic(*QCXsOb-g*CdpEiGliHE?@gp?XwqW+x3CdB$_|O;jWxh)qT*tjdSShVit5)*5 zZ4G6?%YVt!W#bW02AS<@SelUv@*~WR_59;?nk1EC zCV@P@j*${Pce`mfu0x?mzU4~ft7|T^i_8Q)(i7SbIv7lL{8+=J#y%ZU1_M&@wFqu7 z0jUASJ=i80&|dL&XT!X7>7Y(mXnnZ`iKMmGR7;~xGPyN^<>G;GG>m-FmAyaC7;!ix zlFs9ucd1;9q~wk7yFwf;yYfn=$hx9MPUp4Itm=V?g-(OPOe)*kAR-b^h~Vn2hWYxe zB`t(Wve5CsKDb_Ioq*_#aG!LE?-{T2-d9)7i^6(J1$Pk#2dA=p=G*eHPWctw-A|7? zYQU51?oX5&;3`CYR^4a3!A#FT^$zf?;Nf~ervM`%xNT>X21 z7bZmr+mzEoNVp^j$iX)1++JSo-qfftDUt-C zLQ)VPlgB@#v499PbGjlwPaG;!nbPmNCdzE!>MW6972Mv?_d1b+v2vj6HNyRA$0sam>c^5^jEZG#L$a)Yb-`+Aqq1G8}!vh1i>3t{gECE4B8IO#vGI9vdQK zd0Z!f1#E{U=wZIO_;(db*{$*fP<=VSJLPy|@seI?9_=dQ?ZxWG-~Bd7B$^AuaVQh$ zl+q~`@mWUs?{6_;Tnu|VBP$amsixjeqbog>{Ns#YtSUwlsT)AgQ^drkylH z$}WFXLT4(3J7W?9Z&&cAq9daW!JR|+>(gfCm;wX0I1+>o-h~g&MVx@G6X}cKmNyg0 z!$5DYck0|OsZc@c0`PmcskV+*HW2d7WfIi1jjh^5V3mh~D*YCz!9rjw_4f z1Nm7IzoblVh6<@HVsCORF5VqV*amctS|t_(W-HRqE5bCAVSMfvr;LajBQui_yC;Lz?SfJJU@U? z{&U2V1ZI4}2^QvC7Cv5ADVYRShwE%;T3%n{Iow4a;UBt+QV+^mN1%9PhI>UrAOa2b1nwtQ!nD67TFA8=TO~@g_*_r)Oc-Pv%74HY~--h8VoaJj4QojaF3l# zywBVh-Zh*I*ka)oU$i^Zv={Nk*k?tyF=wQb!D5M3GWn+}7D%4UNdoQ3+j+ff; zD~cquuCDUzKu>Kptl3)6{NoQj51{5qqW5>Xz7z^rM&*}gjhCHt*wlBbpR#q7(HOWY zGP65Y`(|a_o?W;^c+5VOyyV>T*8#iyCvHs*6}rRUZ?_$JG2KI-7@lf$=EyNuy&9PF z8;Az#TIZD+E03h*K9Kv3KIxi>23l3BB&`PG$kJ~z1&vxQ=6z12C#~WXH;j~=WzSE> z^zsqorPRzsxjYa*iNi_S7 zWG<$oF}S>x^S?ajY3i>GCWJ<9AO5CD3on*X(%aXNV%7D(#nb!%(gI96go;+;O$VkG*U~8VXsi zt~RB4dYJK;MyNmiGhvW-%fhAn!`WXle?-*RL-1!ctX8;k2;j6^a!Efarfj77WIcK| zaOpn$TxomxqZ?7Ev&^Cc#lLBUUUb@9rWG9unbT=+b559Pjs!5sZEMvNRw6}!zsW^j zu;u%R_wsvJ&a^^Ge*R5XcgFAdN|10VE^1eks(;qB@BtZ@1y2Rjm)T`IQi{JCK?^;` z4tAlxw)aV}t_jzqZ`e53#VMwzC@3D6N%yG*el*%}Xgxc2@ne_LFYbV-Fz;=~=I z@sUBmwnZW>hqnKh98479?UZlCb!!Ec5|HP>s<&*0uEhI^3C5}h)q!W+5;^n;q%!pg zwfC}_N9*k<45Se^Wa+CqHj;V{v@|5Dv@jJZqQ5233Hbr*Di_)dXa$^T#A(gN2T{aL z`1D#`N=XVM)$r)7^NW_B^qu7!VIKBp0A^Y-{hz0e;_|gC$KyQ_^$eAl{5LysfF&*u z92uLTO)qi!9=@cxGlwKr@x{vOu-|x#LiShT`m`TX9#BuPne!gW&yIm+Z@KZt&R^0@ zMsZSLM1y&u1;gy@+iuFX6C@AGAo%-}KEEMbTKlYy6btLDS+jjvyay@$y?HRy)XY4c zclX?0g(f4PM* z;St)6MS~@tXwtZXB>sV-SWi&lc5EMw7_=uNTOOOjU;2spvc9>0X-BtanDzU`*QlA< z+IEazyBSfVYYE|l;>1E5r!D>(X`w4$ScnbH-+%YU_!`%Z1)}dbE#Mhp{GE_LmDv)A zHaxk9P$>1wiFPG7=QQTWy$OCZU&tKTfW*|{mKaa6Dm%KVu_7HnpH68n%ZvO;{1;?U zGGI#i69Gi^}95qw$mNk zQWt;bw z_lXUwK_5pcKHw~;aeF>jA>hDF)imamM#@Y$hR2~^cB_)vb^^D?S;(D%M&He}N?VLx zaDNF1Zcod8;he6A&=FaBGN(^-!){awY~bMB?5v>rsm$Vnh5Ze~y_{KpNv0~%?ece) z1Y&K#cXWso&N;JcDQ?)(QO2oLpo^n7D97V(3q;h)jUA*u>maTYwqnZ^JC!fm=Xc*s z5qCh|YW`C{;$77WUljrHX&hZuL}pV!{JtTr5`t+aSYja@{%fTK?u?Ch~4VX19vOIU64%k|VdgA7NTOG08V+urehiCMzy zr>pmx6?;UqV|#^@b?uVgg=a`dW4cDPrhskiM>3W77WwhPW?q!hRk%|)WR)-MzQj4b z<;(jP<)H~eCBFyECsby->c8oG;IticV39Q5Yxq&S^m}V)ur(uwgMAC+1kkj9amA{m zJ_yFc|LtJl_hVV0_-XyKN^M6nfBo9HC zl(};(YkyAZSN~khE&b75)q2kQ;rSSuDSp58PYmxILAmkN&|WEMfeReiUSbOKamt|Fx@wkc09hp?#mw zAx>=NF09$R-&VJ9(}KPd0sZaH+VZ2AXY@pKSIh3zYq`PcAP;C1Hd=8;W%r3G(5%&o z17B64T-$TauVu485;u5QjmzFAGQ7{3d;d?)xzdL0^m@DzYkw^`YU6SU&nV=WyCx=2 zKYcql*+rm7KXeYk_kH2U?6;Es8-8NgwXrLYzQf5w@Yie%+G z+8jI6Wme~6r$)$0ux>aD0@DQ1OqO*~Ea^OJdGrJM&l(&H85>DJ9L$7uPWx3@VG0s6 zd!305)|#GHb(`j(P3?MsA7(-un&;!5j??Wokbd_|W|Q8UR8M=EPfmQ>3naVZ_ra^S zOMhrekw4YUujjYp+zAQ>OwOPszANN z0x|Alt5Q@;OYdp+4j$YcAGm%euUgx$DG={6EBZt9wCQ=bgc+XV>+!45nL4l$D~L8h zvsc;FDPp4)9ja!;DTZB^d{GBZ9<8gZ1zlPk6Y!nW?YN2Pq64r0oQP6RdI=4eDoS3!o@57TQc<9Ikg#j+9XWQ3<;-8$ZQJ6fm* z^Aul6Lnckw!Y$(qbbME(?g37uGVd&9cE=daqBeCH-x5*>fHXXNs=%Qzi6L`enh8@y z&9GI$9bU~Hq`W}!a31m%jcVZ0%zQ>~oT957mKgsO6F=gfMC~?i_Q(GWDexnCx$`D* z*3{q+6Hb}1-=P-$;CK9u?m#mr6VHnn>Pn4$uH%CDj?v9oE3WHzv6iO|u9FZuj5}Gq z@3fLD56zT?+m0yvJF=aP?)psLvyp=pbc7<%h?DS7V&z9e`esdqpfd;2_WBQRZnW-0 zj8Y;x8#hI@iU!NJ7LASJ8GE|#ts)#1v(5#q#W-#kTIWl=y=|O!ZNo>Nx~UG;-mHlQ z@^iswDXgz&ZX9+C<+6+5Tc#tTH2XcK74*^2Vbd8ej((&oCi^NnImbZ!hXmN~(_@-ii3!qCNDuLJ zfu5itZ;zR-L@%j<30VOhCKrh z8P3sO?EaBZNSY}OcjULr;s*6EfDkM5W9~rL1V6U^vKs*K@U!f-yn8bjkBNg@>kLF zJx{}C$-A*@?y(0Nd|S*>@#5Zu&U$b|cr?os*^-K2i2BqD$29rEn6NzrOg4Fs$zulkg1ZCaL z92yYA39Iag|IIF&)jWzL6;Fu04*Ed;G=f!6k4~ ziz45)+o~6|7~7y^Rh`+q_A-AW*qJuJXAgPqModlEBqU?TCtEwoyj`!~`p{o-zIu6B z(d_DSA^%%wc0|@=pGUSmhNFjC;JQ}Gb-^V0I+?vsP7=o!hk)dCYJ#=SZE*pgJ^$AZ zW-BH+fnZ2HY#6oRJJ0?#B41INGH|h^AI_VQ|ontIc?Q6~_5V%Pe)rJB-8gpQiOaGM+ z1j{YwFDnR$MF8zQs>zx6OMoiX2ak1z)ZY*>%kUzT$r&foN~f-xSGbraFyzlZ;6hNP zwer%9eq6PwTYF~?JCAEcUPkSxm2|0F7N(Y{_44PL#ROG`@;OJy>C+kmq#QTrcg8Ah zJpq_GIDyJW)p5$)V;|%6JqT>3j6uiTU+11r+ST8hKKvW~UwK@tkN<{C;(zNp4FApkmlVTWYSaj9*)brHJLd5dYAqAOS0&GMYf^mQ z{ey6^ynZHD#-l#O^J!ABEcq0LOq>oo;v$1odFE_nPTgdck#RO@j(|IX35R-C=q={4 zbom}+q|e)bYR^=ksWhWRsxPEhV)|0@DyQCHa9gx)K|%B4l-C+FeYJYBNZPLOazuCE zP0uILK1YeH5)wp=zTT9U!W%jL+wLoW3^Fj`j;Yv&Jo!)-In7Lsr6)4QmuPy^+1E`T zGQNwv+61%bJ378)mM;*}uiJ?Ga3LclHF%YT9}^OqotbH*th9``ur4TL=$j(X(a~&BnVzq?;l;KyEw~vVm%R?@0NKhCh&z zLL^;|d!0JGJ8mTUr0&89{)m1J8^@o-W*%JfmbejM6X}eAbrhYB>;qWW^LtcHID)>(j#49?uvY84WYgN=VZ*AP%&xM>InOil8YIj8FD;k;)SJZqqy=#g%eXEX|Ve)h% z*?HY-9IEg2_Rb8uCOA0&xw(YsmSCN~O;EAX{Ro>oM_?*izEcTv}WZf6gt=!(vdhOJn)t6aQ zNv1CJJ7Bsb{>ELoP0R%yfuvQ~-G1q0z|919SCzoy5O&3Wz*6yiSp%((t|U}a0Ai}j z4b31L63$N@R|Byv8K}ShX#C8)XAMq(T;JEsUA$uIr?L!3#hhvRIaEHs5ZgpuL=3+; zd~T?y!t&}i+pi=JpS=^}*H_N8(FhqAgz(}9pWi+U`H7gWT-!`;p4{pbG<7AEsQRfZ z3Qv4!t_l)^R-ErIoV(V2jnYPUf4L{fk#bYe}>b(}1+}7D;hFhKjw-m|* z6sSO;N_p}mNb+AdUU9s&6;Gg2i4T0a^>O3=B$LZI?>1`K!1QW46A3r(B zyZ{kMs#;kXy5w7Jody+= zBQq8qDMD1_N2R2@z87$IWd0F^p3nc5C@ZU}qT+8)gIfs`!3)Pvf{`B9MJ1TdReRQT7KAYea6d)*V$8eC+wgM`?}uKiGS#;JAWtTThk+mIbyX3rEb%%*@Qv2rPyf zF_UF6Gcz+YGmO|`X0(_Y9OdNXp4?QWDi60(c{tCryL$Ftz4!F=`q#G@bp0YDjbkT| zjsllSiH{?+5-7`mu4yeH0(~)Clus|$;ygs1NsX5pMuOV1arv%|4TqU~jg#)Nc0X{v zo`VJ0r;OE%#<@!tw41b+;Ps}?NsuY>#sgM2 zc@&jDe(B8USEuJ2jU`fZ=rTX@xLtb|>4q`9=9cF*Oq2AM#(R69F)v-L%02y0o|SF? zc6$$ZkLKL`{InuTwP4Ok#x^!S=&9;*&Nv_tU~`77Rn?9*Cw0d3`jCpsp(;&PLI2^xf*eu zsS=0o1+PHawE=uGk?F0;(Q#GHjz%Ua@?fvXCKZs)@nwgV@}VjV{`XwkL&b(}UVtU(XrHP` z2%9bA{_{4o7wl5BG*LxK>OUwr@gJ%APv`NTvAGripJ;~jZTSph@J?Vz-9O_D$P{nvUdoq25-=pwlB~^m)P~j= zsgcI&vkTrk9q48V(O6D^i%J9RFOI~by;v3yzpqQT=)2KPa zW6q~m7%1r)g3h^Q?;dksEpv=oys_nh zN%W@OR=HNC1FhRpqN>EA=F_XS@%eaFqi@s8dGVC|mtbDtN|(Xs2{0`Gp1p7z_VECB z&Rx4Jw@FFGDqIecsrcZl%moz~$W?S9e5yR!i(eAf`3;nWj;+)GIn#qRr8!7nz8Q`C z3P`oXE*B@YoO#8`Y)Lx3<8C=(Qdi)7fYqS-C9PzpCD#! zrGPlsd!7+tF>rv4fr@c5s;+Ew>sFmL!{zM2ocnB{#ZNEb+@!oNuB-)_YE5!;F}udA z9uZ5W?+D}3X8x?j6Ju;2Oz?cI{+puBWTY2BCYGCtYa5rO(#J9wmM@W-L;IwN;bCjR z^hD{nL52h7gnPNsfdtof%0-Ueb49uG&2M5hAy{-YC1cd6jE8D$^#nb|(&|o?hXLR> zIzox>*T+z0C}8uHqk}u$w^v)3(zMQ>bmbsP;hz{ek>S?n?t+&18;~0lp)2A~P11T)XN2q~-Qd%-LVoibGCM7g633pm$gHhTxg0l5!bty6v-|F$9RZRL4KM(K{ z1mh01iE!(_KVJHq&i&3lz#8IhpW?v#%{aY^(|?|Iek;9o>q8R`!CihO#v1kGBrtcb z_NEJx<+1$KHPP602d8~FXli`y0P+_PMiCDw-DSZ>0P2s#X_Je5BG%QS=kD7`P}Ape zv&wU0sI4?+O$z7U!+-KFcOJs4Gf)$bZG9}?r>(rEg!HAsqHyfT&PJxFV_VYR(`Yy(S0#GNVAW!mpK8uluy6|ezJlL$ znt2;_sOsuHr(NYCe+`xeyF`uSp!cIr7xf{^5idvrzMvI06nZr7Nm43`;?5m=G^bVd zT2ZD5kl^u*L*yHmweHQE+F;{GA)zdFQI7j8lU^^fRJV@@tc0Uy281nm?SOCu<&c|Y z0_Kb=sFeA?i27xfR&Lv#RwtBkahQz_r`CI(kk;bB77TNhn|wNb7yRSxrbv2>7u$S| zpznn00zaru133=(!5p1$cWHQCO46ECWFo#tBO69EoQ0V@k)bsquT!R;I-*sxmF+L> ziQ{2;ymt{qgdS>_vKR^X9~MDhiqr8F5Do0yJA4+jv^1<)-!r`~vUs%DN*(CDPfDik>&ECmR@rqixO_I#!g`3(AX(IysEChE||Bbbo zg$%cRb(n$)^O;eYSeZ4Qka?M41+5Ahu_uP*tZ z)5+OkY|$ZU!el0<`@i`2ofq3azM2HwWKe`Na_A@=KZ=|0+BPHD>1oeE=4v|9T{(%G$k!}){uI^Z zkz5(bl>v|IHx*`WqM3UG5xu@wxEUmjG+D->Mo#t9@`woEP;O=Gbs$FkkZ$q6OQ!T} zGh%;Htjt+iGeP@!!SrqpdQIRMCOScoxjZ$+zWYxQ0!x)zdq)5}bT9>LhUamMy;<%z zR8u*-bUN!j)|Fo74;7v7XIt(?R>x`~F0$jB# z&wU13TvkwEUSS0Ipq~kP1L|a=^J$^I!?V(h-mlt1|9f!9N05L&-IgZdIfc8SA>k=ByP53 zrVJm!(V20o!+6`|SqjV2Q?9^h_7*^<{w`f(ryiK7~G(u7E z54z&i-Uv6wsf(ojrX4OnEP*AH7?5ik#3|D_&RR{zi$D2kK8apiH2sjQ&fgQ0iRF|R ze(X?rC-rPz*DQ|;OcqZVa_f*n#^=)Ll*!aXdj-aoBgw)(EMwKdAT|$_bh_bpHI>9)zoW@}7NiRT-EH1h-f=5d4^wV!kpAI>4Xc705HG-1O zo4zULkuv7{NACC1E`81Eq*`0JR=cIKVUS9T(x=AU9Df*f2bc4qs-MZEM2Tby*opcN z4!#5zc`XuviiU_n46`J+8}1^deyaMS_Q-%rqNL5~uC(JumTf<-*9B%l9rAC6C^f?z zhC5!G2QLTXu;d&*@w<=d5AftTzV#nTI^hJ6rg}@`xv^xLMF&Ton1)uE9XSBD1w#{9 z!zuPJidG54h6llK0924y6lbO+L;wPf+jxr`r$L!0rJI5R>sqdGZE6=()g*3o58(B; z#Ju5d><`>F)8_EA`s+$5drQkIk58%djJW}hr#nS)`uzEz~!$? zaw+6#Kc&TdWW^#CO$Y7acW1^|zPj(Zf0|OkN^VhDI^Ae{kL>41&lj$n-%f~s8Z!d< zlXyxo@Ei?6+Wq1VZTDS1r!4Mqp?rj!rW-LA?s7?3)TD!=b})>pQ-zui4AZ1qIh@_d z5wIZ*JCVkKQG${xV+|iszBJ>OGgz?=<&{yJ$hp47w#=YEakg=*=SwSWwKcA=wOpqu zd{0#2=H-@jp?faIgw*Ho4!@*v!|7Gi(fXWTgL%dd6-OL+!_oEhR!o$2msu!V;lDG+ zp&|PP_blz-`@A^z&n8&Wcz^acY~V7(fJ5~cMdrXz=oxCP#3J&hU!Op%WwGX6X0~*n10S!_``N&n7-T-0Vw~2Xd_tUgIjDQXUhRR@&#TW= zAK)XJaY&lTJrXsNc;@Ykbo#h%*aJw@Y&h$#u|5S7Cg}~z^ew8(@mDCdUY%O^u8W1! z7{i1xGwCT%>y~T;b$57*4II5LG)_x{3nGQ}VD2dy|2#0Xc&dq*I2fYAIkS>I?;3lI z1~|r$4y_eSJkr8Q4r{QhqiVJrI0n>p2@~5SZQfC{$&IAj0KQ?AJTI1x{D+zIKdelh z^1sAXp9@#p-v)Wp-+9`3Pk>?nJ8SX}p|Yxl51tR(o1slHXr@80zFl$D5!YVij5d9e z&Dj+>h32$?WlzX+HW5G(#_M-T8Lo4ub_=@yJOcb+SCaAL8Ow)1^M3xcXMkWKKu^Xy zKV1ENX!y~k;v5!O#r=Crim!^R@~MYk{ZtXeiMGhMItiIeiI5$qK_Rt{oIQ_)=0(70 zo@K~cA5A-D%k$hp>FL3a`LZX{y1tW_uiD3)y;UD_8w?u`KlH54E*CS8lS-FhvX2s3 z+Zt(`p${RIb^-D9n8K^i&fYG3)rsfl|89)Pk`yWs>wFOhaXedh*7iNrNcU{zx<61A zFORj3IuxETl4vfe=!zim*pppG4n;ZUYa3ek;~l1A4Z~{tQD~CH{$;5AR|e#g#wOOu zCO@COIjFqz|D2nbD-RhlnuI zF#(@dXS*O0p=}A_t;7oLz0DhLa=tfbRd8pVA~7zUv82xnb2>Ippy6QJsORC{yUvFjII`zCm8^C~FZ5D|eAZbUQ|iS~o8?iZ?LQ_p(KO}F4WlM? z@+}zMqN^A*Dha*p$5f{JG!W-xI6lP2N%g6qZE$6!F8y60|BfRYQbhZ^;-98$adO2fl zg*@;!QnIqbs30TYelJC*m{ zR#yUr%Eg5!BJqDv>xrvFQ;Znj)Njd76qjp~LaY6fi|7OMJF0xY$C?q2WX;A@+G~m9 zXzAmHL6EDq$Muz!-5!25aW=%;Rart=RU;-$dr^IJyn%a*&UGwj;f-r&)%;VHMi?mk zK>0+kH!tNzV`lYwH!ply@@q$N__$N9Bc4@tQ60W7_a#)2v{;pqY<%v2e0(%FHp0rz z@2uoSL)a33&Ew2+EjOX4r$+cS_?+xDD)YYw|98QL|9g@AFMKdeyrL?Z`E1ac45SmL zUNmwH-sV1x_%a2&X1Os}y-y)8?4Zlm3wVAk*l&6+|_X?6tW>K1+FbPE= znm+1(=FwRwYhKYL<=$O6)b zs@;DxFdUWJ%PgEojGR}Vv>^(ZGbfX6mdeujvLxBF$G)Fc+p}$k+e4;KK%U8tZ|U9= zQLCvLb^E;Q$wrx(WmR}3&qrv0EE`i(b5->k3;VX~D$a=1D{eyFWeBN$*?BZbKUh{- zUQCbOSruPRysiOSY6bF}*nKWmT|*L2%L^sA)SlmD(SnnA-)8ss(oHkLbra#-)hT4T zBBH&&M$_aa;GTH_Sl`MLnQjA{k;ELL&CuMc+Egkf;ml+g^eH?Gy|<*zmx7Z{_-YoZ z;hYb7l9PCXt{;kq_ejyPYFSN6TXsa;0Sy-ifo1Ui~ ze5xm)q;lshhGwUqCbXXBKuKu9WX=FZMe3u&)j5WS(p12RgllSq+uvKs=3cBQJ&2#h zQDxi6T!T%{c(TI~L4)P$sN-LQkKOg?i%y?8E$>f07bX7p1FkAcc!y^%)C~fG&0>hw z_z98UDpk=e2l4#aMyt<*$vc6j+DYh?MGy&B#n)d#yAEY{&!zK!U-W6Wi**z-)Wv?< zmJJpFNy=UrCFkFN(N>uDJGKqOHUMa~!5-aJZ`p*^L$zHR&4aqwihhOK3_kpP_Gi_X zo;soALi18lcpHem7Y2%c)dHLOXWo$#-s1PmawgW8h~cGUe`vAJ^N&z zTFB%J1JcVwdOAF_2wTs+t##z*$4=U9o67J1K~0z2)SxYT?VjpZ*y4GHzR;ESN4B(x8L2_bsd^8 z)?jX|l*^4+45%I7z8S2~h3wdK^1@m=Mx9`@&3_n06{7_;fnT=B%)W+2k7jn!?Ytw%JpzaP$0@5t*os$>25Av=^}E_+4pC45tQ0%w8uW z<-p=oAOD2Um%&J#mFDS`lBGkmZ3jGnwIs;c69rGbj^~t{qoteoxUFOrB+Cackh4aW zkoYhTp_FN>9|G^Wr?rj#SV^5vVyh!i@a@VI2j3YgM>-O0=!9iT4=yEsw&yXQ5&&{Y zGO=vL%hK&AB3c%E1kF;}ZyK7)RCZQC9OP&mNyUa3s>}0&(!{fqmz9JJUvIEc%awkU z3^fuWnIz|@JijN3i;4Yej)pucE!1Znrow`@p8fUt4q3si!16o_3=KEH4 zfQG*89SWk@-=&t6Ce$=Eh6=+CHr#(Z9`&HI5G9Z5A%sM0I=AbL^3fs`aQ}qcLSv1Q zAL;B}(~Wbc5mcLf+|D`73$63StENszGZRhYrHg0Tp6Lj&D+q&eKY%)sCxK=X3Z#(Z z`h8ALmDr`gVSjF47g!@AO9Ta2^Q}5KT&ZW8Wimk;KR=17!*>4ZorBH%d>M^29Q4DX z!iO<#C=dBBRUivT7isL@2NK$~1xjGr{#82fG6rvcNMjYx=VJ3tAQ5BaS+ONJNB8@; zS}A$Fwv4bEf4r~9>F8-g>;M$j*z0TzNffQalKc^i6?m#vkJ=3MsA$u^;}WY(WeII% zYCCYyJuY55ezQ7i8%I>THhty$V9NaV4GUfp%-6OYylPSr%X&YZ(J{bXDfyh2UgyzX z4HkkP-Y6$&e8+j)bor^W;m%{YWv*u(D(s5%)@lrcB4U)43y#QNVb7t()9g*Z5<1$T zYLBUbL=+R6c-SA2VcaYk8fa2t=#dbZvKe-X!_G7N6p7e=1>A56Nv(rd2_-ze+>OQ4 zqtR9Rl6EKPjdI$L^@@;ipOi{wI27?7%hkjUgA3ipmB)W6uJgn58fPyNWB=2a%BUeH z&cd)mN_1Pi3*^|kukDC%Q4>QCl;Xxa>C~(#ubTq~tv{!%wIhLI_0?5c(_3Oymcb~U z_~caQI1Df)8X8H_+_`Oh+TLr56d=_?&1L7-<5UAl40+lktMI`!JdX9Y%X_U0XN8hE z%>Hk=8M=|;O|{SS`qV&CMZ=i0voj~z>DeZ{UU_iXlqkP}QX$+>>#W~S3hPgtvIvI~ z40SK{k=?3P-y2Eg;4#vl4DBl%_Djv}-L_5Q?Bx7xe{xbz0Arzm*tN>-&zGlu^qK0) zCPtU=b~S3s=cc=|s?J{;IkdWzribilO2HQz%I|X0MYuCOqzy<)PMmrL)w)U9Rbgc~k4JVw@@9D42-OlX-nh8(j91 zl07|{B#EKkmm#3PA?-K95 zr72#9lV@~bA&>+C^#>9_wUGPX>$o7Ra0aUf`{0suajnUIRtOvE!V||c>BtiW`uHMx zK}7|T><3t6hu^U*zl{$_9*Do-;1~Cq*;EfxLiq<19>!%x$_4K=E)IOc3S-aUNt1$rJNp zBv(N1<#|p!a5zV$Rn#>Nka^gj=vhKtD>Ct04gvzx>X)pOmXr-vjq7US$5o&mKN~IQ zyAyL8)(TDMuVIztEAyy_lnjzwhV3mJbLr!|^0LyeKPTXrMN@;|G}nciJ(WWh>+ag4 zl1ZvZ=zDgIrWhtL>De@Ye>sYxe;akKTQ{SnLWxlwS-P!*elnqW~GlFSreUhkQJ z>18FRDicdE)ZSGkNgv@*JFS5i#N5ZGDVjAGOT6ca;s0~`_#f1S-NJQgL^!}+8&fmV zudyAa>aWXfJ} zBLOKx7t?`6Me6sQs2&uh5sI|+93j*TW>eoOlqii>oqV(((Z>?p=!xnfM>cZ8{lp6^ zpxp^MFc=EpQc=JYgPb2q@T@!RXOi1`X}wN;iH~F!)+EB8z%s~Xz}s%IvcN4D5;~J9 z6;^XhtxY=OPG^tF0e!yz>s&({XeVv`r&BJaP(jTriNoHgzP@iUE`J>3wkZZ|MGGo5 zf2cj-n}GzWTBV|D!BaYqb`ogTUZ@|cstP01BmO-C#K`pFZGHR>0?xk$CX^wuaGS9T zitKuxddr&BMP3YCc|2iGitcI5lCtPlC|?=5&rY7Y(J@@hm6O{M<>X4lE2NAl6%rQWf{n#8stN<0gf#B@%9D6%hG@zC&A{?CrSTUu^PS1J`amJ4?ze zyT&F)c9`i4MkB|!7D^EzAWGA=5n(1MIczPT+OiWs!j>ln88FqD1u%CY*mtf;6zkn9 z5sVxkg~%ayxyVYoT_914wezt2sZ`);%q8+#Jju`Nu%-&?WR~I;6Gs< zgWehpc7-z0ZEME~UrXv^n>>J`A(PD4RZvo%U>!e}*6TOu8&0`3qGa@uF^~nYj-ZRD zk~N=?+qxP&d{x(tV)7Cr5@7a3y_VR0nE% zJSRyfOrkTOyMi7n(up=8D@n#G*?AFcZApgD$A{_I3M2pD zcZ|~>pOQV1Nkyt4cWLi`Q)9&n&Xe>c9KE}Yr2_r6ho3-($0j#XSt(_NW zC~2yQA~nX|flI=9*=oi<{%Y>Y;@UyCkYH&6>ZH#f`!o6l=C(+(HK== z{3si_q(v$UV(I{cH{y{yWvX4rxSBJKrrRvio-L`zmatEPYtL}82snviTs}MB2Ep@v z?>s2dCqX_mG(LfEEL;kvx5)xTkM^JdC z6S4M8SAbc_4x4qrOwfAHvm9V!HGbEjExnR$+*?{3uU_GcB$R1F6hN9s3Hq;MtS!CN z6x{d~x8vwStB%bT_xY2g_ow-$w#>$=nuG?<`4$4iG2$c-90P#pbMtpyA)eK=<#A4@ zU>>z<-DJ&Afl-p=>?puU%}|mFZ*{&D_G@~g-&2|38tg*8JUM1~>gkkxE7X3Q24^lC z64K)mAtxJ7`W6^_Zt11#t}xwBvYgUtq$)Ickuerwqn;gl*T~`R%F&$l@^Ft~wxe^PL1m6qce%#tYc^Ge+ta z;eaQPK_C2sOV=%3s=m^r3KuW zd?*@9Rn8LZ2 zL#3I-#{<_I&3ERU0R@2dp6&@l_0@%O*yWPr(XGSt6c{srav-GHHtW>FtHYShPr=EB z&%xcHbz)!O_lM`2I&y3N$KwyBI_wPy^M&OYQUrfjO}O4Uu9n@!y!&mVQ97FORkHNF zY3(qW0L5RlvS(uyxUL5ox=zULyNoP>a4cHe!9C>z298ip5S}n@{h`H&L=*J!L@@Tt z!3lfjE+58;Lt3cn?EwSFYscwPg-B7=Fj>CDr8BVa_2>Z`a}G4_aNr2^K*VZdTs3;} z!12I$$h=BV-$JB>omr0p`=c}`e>q0ZeM~WR`mOx(7)H~O^<#XTtYR5+5gYo*^8t83){8HBs z&NwlKr7qRY#W7(=i3OkprHpnxnO8KxUfs^ewS!X-VeCF7Z_krGwmADt`%2PLam)J2 zKVOT1s6RjzniyOo%$sk>-PRK^eUyKVO&&?#l~CMkjS2&UMd~3brZs{EGTeJpVyG zM8Bv$BY6k;)OwG-xz=Z27iAAY#td$b4UW~a*D1FIC4J(2ULbF!Z*T(rf=gZd@9oQf zo>UcgjrXgc?ilZA6wl-T$KA~R-|o8js`h&E^*Q-Dk@7+M@!Ry~UiSOdKPW37;pmz_ z_l&JRRrikXA4eMhRhoiV_`es|ivOV8{y{Yg=0KLrU$EA?7d<}!eKeM@V6TrLX@SD` zLg}}eU!QMXpD6!9b@;4gPZ^)GzJ;F~oOEXVgGyw3=Md2O2bHbz4@#xr{YdcBGw*Bs z2ZU1aOz}VK#`;mW?*GTSRYFb|msyQHDU6d-Hb#xiaxqoS0A58q3kR!YBP`t0(0>~z z8#~$(87%YFMLmM(Txg--T1OX1HzWnecs%zxi?UQfIRiY#nulnrV#a}y#w1}B@u|zC zk(ECk*H=6%Qx~Ap*>h}}#tFam?l`d_jV|)+#Yt0kq{rLf{;jDjaDAS7_d=yyzRbFK z-ldJMYugo~G-Z~9b9)pgY2@Q?6jKy&2>pY1!ejxkDJj8|Dt)ti{0B8^UVQSBW@5z{ zbu^4VD6tQ#O#oJQ$Q zcogx{^lHtLWs!O7Q^b0{det!M{@<7XcV+&6un4+;Om{Zd`aHP2TB|bhE8}W)6xR{1 zb3ST5uno_(l>l}f!si4_N)BGS@Z8?-Q-wZ4>GkyB4lYANA@lF}ItQ=o^O|Y`WzaXE zn)i!T&d=}jIq%3~@iP}6Zu8;wh@^2(x8B26_%nRPllDT3h0j7Evut@X!AGP~ zH}ssLJu8ZT6Sj+^^^D)02cI94fwjPCM`lQ7sAil5`W$PPHF}}_&Vw__&9fw|tgH*+ z?{gRKau;6Ygy&i%`i>_~DnwrwqYCm2>`+FcX>%a05wk9+bmOglKL4 zLNsWGeM1fFLa}0g)AjKFV|+&Ac8vF1=3G-d2Tt0Ct(9W*WT|eCNz?0NuQYERa5LAH zm4cPw^mw%uUge1PSlrCf+AE_vA7~;wQJk#V=3obge4Vlph`KLt{ z>f%+YU*L6{dU<*CG*@=Rx(DE&R>EefA0|6=?NrmgN9r!~%cAEsV}N7%hqL%zy0TQK z-y=;=z!*WSz1pE{Q3kM=_bmpSw~r@CaZ8}O;U$H`xIK7ftSoo&2X8#amaLV$W0*$x zeFyDT%=~^+kMEkrH#DV3SNhy91PhJlWpis46A>tTq^gBpsQi4z^V?oN#+r?boN7c3 z4>TA)(FhR2KbcasJ9WAYhGjHwKHti+Rqvgngo_=@ssY?SG9IYEHa|LtxnheEX~8T9 zyvrY1CzZQXS$J=X2Wf#yZnO+Sny?D0k)o99;?L9UZqNUq%pYReMfTL`&~>^N^H=oU zpPzH=>}E|xgs^yN5^RI#cAwr9*nJ1$tD!$|OVeH@k5`Jf|DcN1rj1*-y3{dHy|{K) zZhhcN@Mi1E>n&657z;JEQ(%2}N+hj%?Yajwv$zygKZGZb{Oa1RN(cQ&akX2@=DSY9 z_KFCYbQ(Gq_j%pD!}VKlMc0!POGLIgi$HA*b?+``9*%uXp{^Jk1IGtv$IJvhQxM8I zE%h*RotHVgdlX7Y& z_$xB3?+ErmV>%wSzZMBTIh)Az6L5h5ENo$+*Fdi7tbGg%qXCts_C?FpO)Y2^ScG=FR2cbA;7DwFJjF0k z>N1;@lP^p_rdF;;T$g-BeGbY)a|apo18AmGRE#YiArDS9Zg7RbwM9_O2AO6R_R1_iu`+JT3zzHht;m@x|j!K`S%tA;cTk1F3OHSW|zTb@puIFdk+lC9+2 zV}u%RXpn||LX)O>$RLA*37Hj_aG>3xU{*zhK*zQDw>Fy=Q(tZ@K^MQXdz71kq0Dh} z3)AMpdC66BcZ5r-)<;yTW8&`aGW*}qpE1L0ks$XN=e91cF?5sZEdD)Un2h$ zD=A3uUO;O+#Wl13fmk&8-@Q<35?Y?D!Sl5{PmB)@Y|-!gCs8%0_)isk#05NL?Jl z&gXoqXp&#|D5{S#5ZQ3PRTa}k3HQNq23*(0oSUd?7Z#j=7oOYcTN|bN`%4TLyD-*p0rDqxoUDk?)h6Ra?2K$y!nImeX$E;!lA8_?@{ zlNVMviF|Igd8jLJV!MX8I2Xi&@B>>aUN8rG;zIz`eU(GYWWT!;DXLTyJ@j#MboRor zONnxdqts}=kSPSR%dat#px%UH9hH3era; zC%|E#HS1~UwapHiY-s}vb3h1dn>?FdnCy(XUqeawdO4L*rkTZt_=h(%-KA-NhNvUQcx_4AX!K3I>on z5pe|-a|Bw6Ne+Z$E*9vJz+rW$HOx{SH-0|%_uw{hX#S|_Ohi0Sv1QH z{ck$3ffKRr2=N!}-79v^rx+w`c0?; zf0d1^2S`o8e998@7lYi;PI_+K^G3%G)p?qJ0wGUQ&`=er;fX#of}^R^1S6P1AeeY` zvsG1~Ukkb(#^hytk(DX71&bZ3sf$FYCE9QQ#RDl1_NAPn#;XAuCRQ}-0gd-dDE`P? zg~Mf|^W6Cnpk@IiV+qp=$@yXrO7*U{CwbUuALWL@<`s&-lab_tYj+t0H9P<|c0n{d zU%d}AX-qo~I`ZvBks@)-<=actv{57R0w|S(Q5>-Y|LzlTI-D1Zt7k0EDq$wGHKj@X zRYZI%Lk;sNL2=;Q4*un`!^fd&Hms|8pcLpE(&d`*7?<&-I7l0f8Brx+%b(&)$keCI zr3e$^v`FfYH)3%icbB_fmsD8FQx&Y((@CN9^n%L!u+;=M+wP?M&J3?g0!2DWy@tmZXE#V$223D=Nfw#;Lh&p9*%KWPf}OBPt+cG3L9LF z;(>hRvRK2yI?_?pXvY*uta(c)UYxBE_E4yKXbg3Ug-&%0-Lka)@b*+P49Qn}v<=lfYemVD0{3v6*`y>^?;-p4Z zP2O~+7s*nKg_m_HP{$e?SXyA7DO z?vPj$4`i+z5IC50jM++LtC3*mq4^@jj6Kb*K3ZNF46rN4z)*zgytjbYD8 z{}7WbK2k?1TCes3Md(KFZ50sg&D+_8;fic>?S7eQ0mO?5Uv@eHXYi|BJ#K2^IdYSTipK|}jO z=H_u;j-17U?$Y#dXH$#QBL1oacvAUG(Nu>_*0U>KUv~2>Ty64uG3BAEGTi(mNj_ah zn%P7y?t4Up=#P>uShT}rto2F;(^JWj&zViiMnOb`^BHmRF7X4`1l1~izljv9!X#wA z(@Cn@<0i%N;&A+F@i%#jgj5tuhNAHnt|?|66%hXjj)bj3Bx{veu;QEl-cKA_%-<4O zrB;$osDi^q7XvNdNn%^n`BL5)5^8Emze_o7qP#3q6>Uy*y=><8E=Dn)xggxU7y>S! z7MXoy&jmfZ?T?TbnW;onaxf4K{!G#?a$LIzA9me1=8b0AY%LAP)J=O3jyc#~j1$=* zHD8cJ-wz|BbaIU^LW*Kb?j8scQ_w#@Q_)mM&vW_|;mqeZ*>#w<}%5MT5|*1H~71 z^D8St?x5F!w(+e^3-2fPIt=j;aaA%0mEk8bzZvwQ)#%N*bHRonX2sSQ;l>5lzZClF zYWLuk8tC5o-8waq8Ku6I6Iefs+V;nF2Le)Y4dmCzYKJ_c=U3HS3=B63di_2fLJDfu zbx_pU=1+QvlFZ#kV!wEZq1q6W9t;=wQ?R{Dy}@SK5u-;F$_?nWoB$_=zT^UA;Hl0N z^RD!T^!x58zwvklF3M;b+f|xSH|u(Qg8J3&->*DPn(vgXQal@Lf<8ukPW{A%G8g9r+Ali`_Fi_*R(Q6Zg9K$BPlg5Svx!_5~bKfq@nWwKgTep44dBz zGGdJUUrVyk_k(j;HD;t|bdhw5!Z>-fbOiDGkN9rrac`Pds&%imXTQ>MqI2nU$(CA$ zYa>OG?qu6aK!os{Ba>UG+P~00t~Tbc8^)PDrJN0IuJ-Z$gCeHm77G&HWmTFl{+1A0 zFEsN&?3%#Zq2`#_k>_O?JU@b%t%1w-(gdrw)V zIfSycxdWgRP`Ag*2WrEGImmqj49G6RQM2@SHKaXz2I3-!Nuvwq5YwbO6wNEeUOWyUwA-O?E$t;L?jZmF(D zJ%`AO0sC5!k)?Yx2-zy@`PpaK7*dIYSGLQJYN**CEDXfTkiy}ni>=z)QuzJ3)UK&> z3@;H)R%ob8pboA9FciWuuzHqL{;$88Ns3RW%N2q^?6O~-{d|vOP5*IhSAKzeYF%VTV?6MG51F-0eRuf1Xb-b&+a^eW^FzRpD`sA5wRX#na@u~sY+Zlq<+>rZc9`}49GoUA z7uOH6(zJ(lj-L@)e#?_qzOL8_pRkEVHZ{R%aMi4ffRE)EG!hVtpG!IK?WAvs~U&f0RV+}&b_uO|2Xs2 zV9SgP1v^@zJ*`_HBA5|p7;muFh7#IICWRp#jZp3@Rn5*=G=6M8e;{cqKr^@G&AZuu z%NV||rYmBbJfa|}GN|;-`KE30SBEs`y8BJU;vFu^M0~NNu;>E^|*3YKnC%5LeJw9HTp3L4Qxo zft^uJnZcapnh&Ube<&-0`Q1=G$BcGGbBrhvn@ockhSTW|ClgC=P?_+YJ@`<9jT50mppX<_^`ti%ktJh>4V~2p(Gy0kW!f>2y z(1ykm*%ertgEV zqPOqtK&r;{S|zMprKZV`%B{W|5M}i<^MFgwVdBl_T2mP3CwC`F+w!#ef3;Bmzo0cf z^MZt$M)K(K@1&Y;oH&8CHg{+5le&8;?^`BH%uH&!hOuW9`S%`-l z+vCMiq=a#*tkkc0wd4GN|KtigI2?_ z^k&UY_MDPeRWsJLZPu?{Y+v%K zkYsO8Z0e0w4FVtC*Bh3X+9TPhEAWycW}h_E7EZ99CLzZcnADXiSj0}?5qVCJn`>i% zp8wAf!2j@#HH=xV5AwbdU}AQck%P~vF{wd%M88qLO2Zj%NU)#G zP&zS(&V|n`6t{lFl^AAD{z=|j*6*R;s51@xpig35KtHDS{`z_b?f!$&eee~}09`g= z`j`6;jBT$d#;+M4!NXpPw)ajG8%daLZ`auRH{p+5T@=aGKeI#;H|%}jzYWaWsPys$ zVRh`hqY#D`j%rcH^gU!4^!8t|waUW$=ZIhb(}Cu?Z-6TLO*w;|Cn0v zW9k}3;=l{8ZvWsNONS(cJ*Lh>tV_FBd4~U<;=c>^|K*Ch{XdpDP5Hxc?#m1(p8Xq< zezfBaK_r7Z-47slK5W6`jun$|OeFw)YN$2BN5*F-KdXbXA=_Bhn5+SP#MtGebW`nR zXx4CXJ%8=nQe*DhxK<~sd`IEWyC@&B z!#u<(OtPubw|nHhJ%?-CG64^@Y)%5G=tG+}&M5;}8h$?oQ)PMI$cV-@@=HcF#c{*>qPVIeapS{<&zV+LFeT(;ZBYWfYv#Lm> zRc#$}7$mi?_w8ps({TV96_3ZJif0U^n)y*1xgdm%Q%D_X+-THy*2hgnS;X1P2niZW z{o!F}eP1~IQu)lrt&iEal(ELr1-n6BGSlY{_uE;%2dpBNsT_2zcH6SC8ZtO!;#{73 z0xjJcFl&mmCmKNrNxkyP;YMgzNQRQ0{0UQylf7ErvDrzQ;J@e0rJuItIhm46OP&4i zuF>j2>yHnfCT=EKDPwF42AefcWM_?)>nqf!<`yA1HFj*D;$vLF6ECE#KFO#59b~0{ zWAbp&EJjHE$j3Fm_A})67cZ>29igKKctM2`-@NG8AFAuZ%GZ-JqjvBB<_eTI^VqfU za=o*2URkh+F>Yv~YV)-1Uw6=!m1c8lwr@al2a7zv*!=!t(Q)#dD(?@mx;fj_q-yv$ z-KK{x9tN_PWzsVZJd%u0TOCo@`eLLRNkw+?x3RJ6f@PZO_60*%_oCn?z+-ryLvZ%* z+ghSJ#4nmfHy^pII2*1lrOI|cJL;yG7=^|6@~s`8-M~MXjTj$DlFBrE(G>Hi{eI&N`nLPX5u+Xj5^Dn!D60UIiSF5hb@>x$KYG^gSAcj7`qB!NZ^9o;O`s zIz4qUpr!We@|sfLX~nd>|B6r3uI$u%%$}`W-Pf@F;{2;=bm?8~dA2-V|Ld#@U*Fd2 zaDOCoKl%95MUKMT+VGW%_*HXmi1=Q7dzRpMIM^y(>~!7dW9bMDu*S3mCJPMvDDxaQc&(pLQs=vp_CUGK|QgG zpKU@tPCntW>HT-=tUT*0u`(j_-Ck$sF9zi}R=Z`REvrH*1|(Txq6rSemotM{@+)r} z6m`hvN=-$}5YDLMJWZgbH^G;ui~t~Ly5RhxW^XXx4wPs5+v2ALPD=PNf_$alKmRMf z`~t_G(3Vybr-``%5Ycdz7pd4+mA4KjLNoo5fm{WR45{Lwc1f$k1QIyq<}Gc;ZVg-n zZjMXCU*9sHE8WRx>-+o4Nw?sA110W6Pwex4H*9Y2|26p_aKF{@9(6Lo1}FOtKy zP8^Y33f{1>MgNflq2ScKWv2`rrOVI-+Gc!a*KSfhl!cJC(Z*-h(k>9ku<mhu6TyV4A`(wNs?oEw^kr_p~@D&=ELhl#e0JW9uc>*L}xyf2>XmB zMY~n}yqe6JLKM$jdrb5eQrGO2L&?nt(Gy_OD3+KuXcW-{wAPsB0#_fd{h^MX4n#(eyK@Ml&fd zJO&{cApWLCitJkts~Wj=v~bGnuCBv@@D<9ygMbiF{;4(W9M{DQ7FWw%hL_}7{_ZAC zFuI;HIqFr_b>YD^SNWHHMqvSiF@uLsl3bL%o1!BYQtI02Y46LEsob|o15e4vTL8~y ztA!ac!b0ZM|4htN&gU7LNzG5QG_!eY`fEhPOpNdaV+GFb(}vaKSY9iBoH`tkR|FXN zw7LO)09~l9aNYf~e=F&HMtmZZBjE@eJ6fY&_|)E>@D|n*-@Z&x^U=TiS3@Dde4;{9 zJD19MEsgBUSqX&vXv#V7ID3sNYM6~;2+Tys6BjFLPUD9hNjVa&LcHSOWQq*Zq?Xjr zZO^xz9iPGKSS0@geaTYH$pBS~S;HESjgfAze%!UmPb7Bun-b-szs6`|%x|7B6|-ug}o|xK>F{Q5~mj ze^XjKqqC0}KR8IO-8VgAVEM7;$-JuYZy>+!yAf*&xRpELNPlEM_#im}2>TDEV+1~8 z?++Jjt=n7|GtqlWu!r(=F}X^$+9dx`{|$a=A-?lx0w~^*>}>Jw+wjL z710qwva(a9sN7+!MWYq=Du3Ey)6A09;+VRbR(g!bJ=R7t12iyc7FAs}BX!mIe(hR& zI)h3!u5MQv6SPS*UefuG6IB>WU?`W%M-Pjs#AUPOZ-K3P4pU z3hztk@f$`VU3aDdSmXM%qyqy64P89)z3#jX#JNL_p>OW}oi~+jqS>(dGUN)vUx|;U zSzU~64HRWd)g0A$#Fe_%g~0^Bq&yV9CR-Yaskg5s&>NjZk@{LQ$3OpmYT6k*c2KG$ zJv`^S@JdpP$$KVc%z}G+H0@8W9d4qvX{-s~!|Qr74pOKKXIu}OWRl2?Qpia3lef;P z9ih7Ag2S4_M)V}9;GSYEmN2HSuU-GOJodyDcGO2>u|GtU;e(Iy+mxdUHxH_LSEv5~ zQH$>O_~l=g+Zr&ZR5mG(_S@U;=%<-)m&YPFi-=Y|I_5NF$0Nu&u}B;#UM{nBV5-nc z&}O|AjY4I-#1!@064x@rQ1O&mw;v=mRAa4VzSkABKC<}Q-4`?Li*LA_-!SY;e$x_A zq%DfmrDcX>_b33(=YoxNwv`h;%GF64`lYRyyR})-pzF+LfA)NLS82dur$8c)WVmo+ z$SjeHs8f$lN`ghVbn~kZz4JwJQf6ozU9Kcxf{k3?BcOfYLf zDNh!S=*jgR6epT}0_E8w&kW~9hbaho?ZyLN;y{ADN*Mg0lhYAR8^>3^?N79{<#N$WN7|QJ ztV*N+wH3yCSfdXI&xpNp5 zJ%*@2`0<{jm0XyKIov#nU=!SlcFw6)h>CcKsYAVBOXIld=H1)B7gNI(j!o* zGfPypn6^WTI8kuSjP&qGtXV@ z9YGg*lB6VY_RtYRO8-Lww|C&frN^hD^7lK>5fK)##_NagA0D}@|1?T($36(w?r6qa zJ}u_WqqiA@o67>eBNdgzD2Jbg0VGg)<X?}hb#n0)RwcKr?s>;EGpvW@|mvf-}$&cd{H4}IneH^2U1z1Xr^M&0t9q= z>)7LkISl3Ob}jQp6ME5gmda< z`$qy{7JtM_<9x3ef~lWxfD4JT_1;fx7GC5VidVKs z+ySET=Q^|2hFO#x7AfNZW|Q1$r@f4uZC1IlTKhQUUE-0*l!Fw)5!dY%GEMIFs3j$I zMQ_1XleDw%_`Mg}*FD9`tKEC2C#%SLG;&4?I^@A}aJ~y*f4f@(7UtV-mYjyr2otU` z4@~DMAH21)mKo_PGddK&dX<|u?jPyH;%RF(&Sg7H(Q z)zU27T9i-5U(swa`}d|Uw(|Nco!b(8@_C*F@p5@C=n?!nb$i*{mG1%R_2$Y}yq&AA zsrDH#lgoZp@~t79O}(X#nNad8Zd#*mm&5{BCQW07IF*@-g%XA@Kgdji@}adeZR7fz z*=OCG3&`855zg|m+JI~>*yfeYYH{mTJrzVL(bQVtoL7mBzPBpQo^(&&YqB&$yvIZ# zrIv&#s=OEwdsM1?ms$9o!G%Ah2wHx5x7{_C?UNhF(14Nz5$SY#aTR&Aml$tpys2 z4$LUW%7XyDezTMVgzZT8zObtR6iS?*e@1-n{1g{+vN2A%1bMOI?l%((nnS z4mTsYxmDJ77$kMiv^Yr4Ke!iSh-@86A`}Ternw2+t*4;;59Lb`Qyg;dS8J>OPM)f0 z@NR<$9p1A!Q1yht;X~JcQ|1L4>tzF{yS|m<~=0Y!W zrkR_EO9n(=yZ4n!zdYkMO_hmxnk`^bhuZL&Oj_Lwg2^W3W+1PxMUttxH@Bft_}Obn zf4m>9KSH^Vw&@C>OL>$hCn6h{Cp#>P}&&spEVvnXShwkuToNfHMtVZH_M zw8Kral(RsX$K-_#`@%r3WAkUpUwj<3tK*8Bsi9cCzlt~;GSg-rMdZp?%-6e!{s%_l z|3jn2Kj`{59+*?Yn@vvF_5V=Fa!oqAT6y}W)EH424u#1xT(^ZpcX9~lp?`ub+UQxt zgIOhcf+lREtdOyX?y8s9;=Qyn1ooN|icf!p07Ku}y*16%l%3Dzn3=fh_5=%%?b)3} zdNlGWS$fKhd3$p_^I+eLO*f(M3MhZ3p3Odk8#w-63Rykf_RaeJhZ6ZuZ2;lY_z(Hw z_g8M)c1-*aMauCx>~HJu%!l@W8|He?>rMmrht9vW4to9?zUWSu&L4ip9RabBX;}P!8?Wg9f5U~Cz2xtJ<2{mXyFM&0DO}{Nv{{Z?|f$+h?n)kfqtx6R}W#YF|EDE_gC^V_Tzu z#3^jEo_9U!KNOS6ll?j20jtdB%xB7cIy#KV`pOZbJUgp@lG*==bdLYnm{7nDW|I}j z@TU$AF=OZ`l9R0H7*lQBxI<9bBMi8+jtYYVGk3~j+3}d-1a46#W)zrWM_s!3MN=f` z$-IuA`ntK+d9N`aE%BeZO~NC59*!lZf%Dr**%AE~MIFk^U50;b+&f48_CJZd72POI zq3J&(@)N9cqHCJzlmA z;=EzxG&_C22zjy**m8XIlp2|JCYTj2OPNM@+DUN!xyeDzD%(%&;?m!&Q`GQ0>Df`m z?1Q)PcfPs1O*F}YuRp51Tr2Tr{Doled;Yi`Gu34{#WV|rS6L!kkEx6uuLI7#fJ9A7 z%slfR@a8&*sjri_F`8Ti7=rp~uB`Ud^k}KA(E~Dewd3}tzv7>yFclt(nP$ z7pjNpE&2a+Uev|qG?(quGR5@*KxfR2k)fADJYAB|b>7e9BfVD+s+@l|Q5|u=u8=)k zXl}~<(EIoIspfg1?|DehYz-nQz2N80vP_i`I8l=~y7e_=zZPXuqQNBIi8yq=e6#5nlA=OTK_!?Df9^5N%V zOexVsm4g;Rlo<3C97dKb*=VYE`^myek^ty)E6uIb80;-D$M=>;Ix;j33(}!mb8-s0 z6ZBUe&nN8!d^zodJ)YN0LKL1_DldteGkcu!KcxV34b>t)CUgn^8XMx6yBvzV?!CRq zj4va$=m!+|N>&{iQ7^bLF=X8j;6+nAeby{74xW~*XTx^}RP z+=cJ;&nc;{5esE3Q|Zji^`)f&2;=I3mtfve%yaDJDI?@z7R;IwtSA0E8=e-3&KM??DD0&mE~k z#e=vgUvbv<>I6PYan($+(`40#c3l|_ee@C;tNLCIUw-r@Svmt(8Ew@sc=@Y-$Cqw= z0+64#N15*XJQaQ4K%x=s)WIq}NhAXwjYih@&jZd09A70|dlf+UH-0ky`UkIk@QtaV zy4HvFk3zoR>*#z~x^D|ZqThCx47?ctjyxI}<|?5yceOJPd2{}(Tz-^7Ac?BGOk|px z%<;Wy_@tw*uOEFOZ<^2+^qcyA)i4f}OGy_WKX>Pom5>Yp^$wl_tm@^*V0;aTlW1i%XhBwfdxP14=H=iR}%_wEHe0yJdd_jug6I(_T$gm(W_Fv3Pi;* zJbrB;#!)ICG~wj&C~Xob!3ibAGm~F)^|7g@K4tP>*xZgJoITq~N#_?2VqGCK?ln}} zPW-lq;2vLoGaoxC55%zxRI;XFoNDJ+I`BlC*eWUYzNoVfn*9b-iSPH#O{D}Ln6AcS z3gt32Gy*S~evZClG}bCm(GIT%UZJ1T=oCDvJW&U&jzEmMapbQWqQwmAcc;}a@c2BZ zzJVJ7-atNPfAFk5jB`hSG=_$;U#6CZ9C2zHp{)*kza7f89Y$Qu9vCaHEBSK#)>~yF z0YtS4h;@aDg^V>-l-niJLpOXoqzxqvMV#qV(Ilp}ZP=tu82gFJFy=hQk&2DJ)lpOU z78$J|bO2*d_Zj4uy#6fF20yQ32}yFV`^2BY=PXP1hFI}k5>Tvj67(TZSy^==Wph~E zS^k)4pg>H}U<|Y>PuUB0kAW#bpE`5)7V+(0dR&q%++eSlJ=D@{S1-O!+u0Xmz+HNs z57pmDOeCeDiZrOj?@K0o7GJ1aR@^Q3Itk!v>d1XC$QMi87=JJ^qxPH{U$SEGr?uBY zX8K^^?C7;$sds&w=TV|G_jn9U#4#)|&`x6NqcmJsfW`q9@&qy8bt^VNvY}YG^)=AI z_p7S3-+Z?kXc~a56_H$odrvL<(31(hO_jn~Zj7>2`0 zox{(cvzNN+U9ORUMxt!!k1=s<6Bl-zbIL)FM+xWwT4n8heVM+tilm^}xMD0sgGsHh zFMci2b?jEN(8kL8HM`iIoH(E$Y%(jJw5B&DoN+4cX*vz{W)u^{+{A)wdHkNYd0#ZU z_^{elUat_=`3ir~kPIKG3KVoDEWyVt^q@8^@()VX7sWLxRsszD z5e0Xm-@G$uVMq+t2ZGJBfy5TL@(^G>Y z5Umasu5;d$S8h^iN&;X>Bh7~l4iVNUAr2r%8*_X`XEd#@-EFI0<0k5~5z%c*cjN)Y zvObWY{y~z{xmzXnb)GFVma>{Lel~LD+VGoR?=-cb#Z6m%D)KjS;EDvuq37XF2Xc3D z&O)1Dcc~t+7lJVx+N{>R!u3=VdrcgLAC2Xe_&SgLf|5Nw%B!}G$WSHh+xBmn#4O9- zcBzA2%fip~$%X=0WK%SVt~C`j?H6=+p5!uA(if-ybbRuC=#W6m)XMV=IB2 z#%-{}|ApNe4)4C1`Fjh+KM24GPLEg5jdOVC*e&Pq>WP@K+oVh(oyK<5oy48{BfLI> zLUl|Ge~0)kNStJg*M(J;+Z5VDT3*BV)_WD~o`H7--ULI|K30`gC(lvJ+*zM@SXhnl zUzuBWnjF$7>~pZ&fcFZW5VrP z>DL74ia9p_zTAomjr4W@34Pe$(0^``7hfKS1uOvbU}wFz1+jMmq>_e{v9E72g}L%A z-|#w<1Gqj2!Fw{a@En+N&PMCKbB0}yl9Ii0jp{r}&o*lw!~98>Y6Z?u#v(FO_nV3Vu&7-(V7= zwM>${-BZ%w=`f`p7RXsDsrpA*&!*dKjJ@B;wwfBY6L&fkCu~}%eIVj9-pXgl$h81K z4sof|iyWRwiXi0ckVXRCZ4r7y_F0d9m~CUICNwQFtMMQXdFB}DYS;B6MA;j@(|nAi zaAMi7;wdM{l3E>t=`5>JTGOg`|Dj|6o{!vr_@=sJxNHEyECojLT^+dM>}AxG!VEqg zf|Bt=;>zUZ{>CW6?~*}-u~o5GIsu5e8)}RntEj$BDdgLfFSR+tTvBl-enDl{IAVVA zI~eyNF=Hw_f3E#Dp@J69cm5$yeO_;(a`cAX%`VXh>YLf%7@2B_OGD~`YMkVQU%EXt z5+jCF1xRm8{w3H(Hc4EPoIZgTJuIAyR)~mV%cDU-N$l)m)=!sO(OQ(2OB9&vc#8ld z>FAS3>mpyL?xn8&z64#-cP0R7IJa*KPRCvopGZ0~Gx|YA1riPI9hCkqjreoUPW6-|(O#o*I%bUOY?`R6 zrw4*?SQx8{216a5eoSV4Y=fQ{_1y0nrBdA-DVAV$=zAtLa;u8L7#f~4lcr7GhQb9w zLK=E^C(-rwi*3ggeW5j>k#?yJC1IY#Kw-jhZz{gH9F{Sua%KJ6pU#B%_S_mwW%o=l-H;WQKXs)c|FEjsI% zLK#MIC*m*!K-y0v<0Ne%&4fQ$Q=UqHd9|>As_8jqfad&E3S^1xX_eX@ti)CvGvq8d zeuw;%3OQ}Mzbc2XDUQ1KmSuYiY}6#g#bM9EV6JB`s64La(@%m^6ME&EZ&N441tp<) z$GQNhY^|}93%$36?(aeTxLFjM*y*p*TV3@TSHU{jDz;m~;AAH&=);;rk6KPz>D%_! zzUs+amtX1HoqhFT%=q$WZ}`njKyOX~hPs-K9r6%XHM=TIB5Gn;P6jfdiHK1=TzxI? zYH+`0Hgqj_~Yifhat2EYB5)$gT2I98XOw4XE zZ+l>)cX{l}%7mvbTYY>3vFsY-JNs;-UWei{BuNM%6BF`O2c|;8AF!Ic&*%Ce1t+LFC*R8jxA><7(41Xx~Iv zD~@A7-#{3fzk=O>`i786(h~6?EfJ|=6g73`7rJwMX;I!rAJhoDcT17#+|=#{-PgBl zZSE+*lW};vC7d7Z?)Tjj9G`;-*T@93@u5Ok1+2LYcDZjzRqSX^j>aMgk`+4(wG50H zxl$#i#2m$SY4Ls)nsSN4QFf1ossQPT|cz z{mHgIg&o9{i#jkZ7!D<<{fE-ZjtVR|cL+8U_%MNMC+l~#8aChh8zH)zc^qPC2Bo9d^kdXZK%I$;9Np=Q>IGOJF z-ommPvAp?MRXq0)j7;c9*0Yf3g6wTVM7u00*PEo&$uGiWpULlv&~kSG7LMTAB0XW6 zdXuW}vhJ})`!`-Ed)cIO@o5_@&23+*;FeBq!OkKgq==YA(XgQ0G@V(0)ixdJ^3lCg zZ=0f|OQEIkqX>_4)SPUgGZd^45S)WceW@$WK5=}9n#y)jrTtIVi#}TEENLY$^56~R zZdyqD!qGXWHI=or;NYp z2Q2m{*h1^8#;)N2gd5O>oEER-4AXF8nkpNVBNYCYhD=Rb;5cA15qojSWi-i=6#4-Br zGEI=Jpl`6>1Osi^q3B%vPhFQ@-I7w0Lq7B3>xJLxGY`ewg zN2Z9urBV~DE5A4EH9j}vO0)S%?c>dpli&%5tDEU-in37Zwu~9-IFdF3?kfj)S5vXm zKEX#_OorgXx-%nr3HbtFDZP_m?0o!+u`~9nh%q6*{?KgEP+5lv{@>%n)6?dg86Nuj zuLLNl<*;zjdXmw=F)Tx%^MC-0g50)r*1QJ@gYMFp$GEmW_So=k`r~NOD0)|uzUMfc zYa7|vZ0L0v z)dEwJ{8r!4uN_-S0ZKk|1BD=&o6#fG52q$1|p^q;J!WCZ%;ED4S-f+TCkRwRYF5uU|g-7}L>bA-z)* z@;b(DT~p)Plu7TNQ40Aw^6|b6HRO`m$Azj?stfH9$-C-zfAr)((}Q=K^Sj257d^ZF z{;H)l$+SwQld=>uF+O`DKPE};bLukTT7|} zb#w67F?81FSKRP4S*0*XWiR+bLGqH45Vw^z~VS*%sXxRWeR|i3U z-AhxfSCeP9Go$=w(*=8W5c)J_x{so`&_U%~~L60!QbCu3wA-+AQ}x!q^O6~YB? zhit0OuqNg+&4U}mls8@9d95A-1N>cUF8uCLJJY4X?F6x=8f|d5>t~fLQ3Us?UjS5% zT@R*iI4obqBDCpEpGQjR!^l;t#-(!zEQqaka~3?9x#+-ri4Fd(^1}_7aoyE^s89IX zLp&V31+m;73h~4Kt)QTiu(-S*fRHkjO4eSHt1SIm+8Cp!rlDs+?a6g^=5jtli|6Y@ zUg8vvk`(@KJqe^kK)}VErpAzEM5em$rNW%Ptyyl0Y)hINL<_`w)qRHW`ae2f{;v!0 zze<;n0SEJerRxU%p_BZb)kye8H$W1%opu(15dRMaEX?#TVt(M#lt(e$X3yYq?XzG5 z;=@((CEZJnyng3D6mk>N?)cB6@9(gdTfIX7-wQ(8UY&D}{y*RQzlHxPB7ATU2l!`Q z2mWN4DjfNPvbi|LW`&c?Kb_7Bahjr&+Y8ttZwx z_SZrMXi4oxQCfuJxhKLLKvFt-TFfH@p?ot5y4gJaVWy?iPHq8E+yp-uNFQUn)=x-t zBoi!#I!$4aJV)p*vNuW1F;&@Cb77)a_}q*C3I&Mou|(N_OJ+bBlsrL%8M1g{dD`rdYSr-gGS@}N3#s9}x!xC*k344TCIqdjwAE;#rj968lOOuy$)9PJ z(t1ppi;}4jk+0@^1vrU*&%0HewlInnTa2+grw&*JP5L3u&4Z=p>#tb5=0#mY+PmMHQ?&$H^(4loeVdkU;*%``=o^QX(Nb5wB}#JC7v+qGdJ zuVKyIPVxLBfUSX-l13skl&A?|N_*9IbEEYZHehxELSH0kyDDp?LJ=`~t?u<KV)_PDEGPrjkz zaJicCi}nGMWK}x3Ovz7N`G zO|f-77h4&tYwQ7xx2%2E^y21z5Qtg%|9&oT;a&)pK-9i(aJfcUeZ21d)VPW)0aGhs z$ne1?sD=Sjv_E1HKSA#hmXw-Le8ZeRck?mgUG=P0>Rk~TfZNG|Ae@eUyQ4O}oE9v=r@FK! zp&;gjhGvG3kw%lLgd}0ytXfRSDf8I$x`PSL%WQ5%r7YIpuC-Xbb&hnhHt)dlmXxjW zN}?&6p?D;)aq@3wpAfrf?^3K+7L>8PNmb`CmDgJd_S59b+EwHO`K&RSisVKY22RG= z3zSL#CgVY$;VDqAt-x#(rerDd&K zr$87PFBn&5T{OS#HDy3bSu9*L$Vej1R~qP{bZf`&5;BXSfpS5Eawv)oNE{WemXfjtL-_YqVK~ zn~3Yt5t`ZG+*2)hxi+*F2hC%6t$Yd2X>&QYI5nABD#UILz)TAg7FBtuTmK6lu)XGH ze-5EJGZ&2~Kg%e&wVr>6Q1c+ zx`5w!XaWPB$-ek(Pv2j)_hT6pzR}#ptM+A7`tm5EZ9AkrFjF_PK2TJk$@pn1mYb3+}HTn9UaKtky5tDv)zktYVY= zJ2LC;>Gc+CGMr329d*h{78B1)a`70jws9qAkr?d}OmErB@%+)r?EkLcer&%QF7T4v z>ovxs=WP}1%%*ux5OQCWPu50i6rkjUx8K)W5u>6cSQj0=){vC4VWLk6$hh#zsF`O< z!Un4kVa~bW_Dw7(kLr4i{cf2`R%3~&kfJ-eCl;KKL%w-WDs->zj6ZcO0Se!e{cdm~ zMLY7;9bd}ss6CGAbt%J(ilmuc>G37qTQRsNd0*>7mk6)yYzY&da`nhrJj{}c9G(fz zMTT=|ysBsWEh+ov(zROSHb!7_G3kP{WR&xK2MnP;b>8E#?!xP9W$D$z$z;WLaWM@n zM2b{+EXCS$pm_+37>qx>gikMRGJav(k%X;oPCnU`Y$yB z(6^>lvzTvyRDouTuz9L%qEjp)FWKL<^UauoCfnX*qbmiKu_&j{H)es&8;u$nI)@S_ zc_t}jf~TcxJArszx{_*dI`=mm&q1u>KBIyPd2k_?l=zj%c#(JDAkX7ZY=az4c@I9d zSc%w1s^k5nPE3413#bO^JP|%Z#v?8sk2ZkjVo}^)FSJuUSdrgW$f2gPp|6|21=v8_ zR(%5Z79TLvC19OqX7e#tI!ll(L+T@vvr^Zqw^7v_X}y|Gp+K~M*%>aFG>8@V7gUhC z1%!H9VTt+#~Q$8pVT7P^57pA6DxxgT@_B|a|UzVI1<+2vCuAk#k1 z*y`HSEJ@Y2<*U@D?!PGt_lF^zdS!8|5T@jVp13a9QyWW^XN-sH`Xn-^z$56KI4q;> zA?Gn;l%47gL1X#~#RUVft7god{ZLa!G&goBFDTyS#B@o6W{Ayv@W=V#q{~)e%W-0U ztHm~!J4U*lmz52nM(EmW0@&-+#x&!ikrgI#;XDp{VohDjAcAB|Z zq41o!;<}l^m!521O=BnF>eu%j3?C6t?HLZnya@-$m(fPAI3-4LS+?M^&q@JTK~LF{ z8s3f-?|l_!p~Iu5D`o^}II<#L*o@HgsWs1CD;+gu27ZZOd&G9!#+BYWfoELnC{k0% zzQ)6%`SL9;xL6S-PW{O%@HWZUVZpM(W~;_J(LPV6#)K3AEV zXK`8T8IJoLQo3RiXN$xHNRR<#k`a@^6q2>~2XR_=C1%wqmvf{#)X3MQjSr|i_3VFM z^4+Ep_!6%&w&mHLN0R~l+ckE|Fda-TEC(yEjRLXuFgKL}%rjNo;?mZt3j#Yrhl>TUZivz5(Qw5preg0hgC(2U^5)`PlB74L!M_7q>6E= znDP?1MFqA(If#s#Gc9&{p;G=afs|NxCI!u`nt+i}){3+@EOvn|bZaQr%%DAR&H64+ zmgDaM8Pi0}HgaWHU6DB4OsyC8 zBa-lAieIc(Dek;cNB60P5G%I0=o*n71P#``5##O^;xa9Hr1~gWX32&-JH^ej^+_|q z?&|!j*hK2dG5*wIGz%#!pNv4Qr&>;C>drJu(j?(& z#;#fG(V5t{byJp>@y-c44G?H1FIgbY%ypwm`K31n8;r2x_h?&HWd(O8S?Co}K#k^le&%kH9G%1#qSq3y z?^MNfO#ef%t6h$MFm)Ov-f>8cbU=lNTpQ7!+CshpjDkn=)BMSru$IedhNhW+Bt1x| zsygg#eYpXdZa{=#*TS8O&oL20RE!Dn4q&;kG~sgu||Mo*82N{0M1g;<{;@4hP9x2FJuXMrs^0ly|M8ONMn zJ=p42g{gB!|HNao^FgxZteqW#td;4#5`)t6BtD%!^T>2=beBl^U6BppzA|Om>ay94dtlo0VlYWP$XQ z{ewyQZC^p<#u56OzGZM*U@mU!;2VZ`0hW989wW06EsWMds}-?@Wx|u=yc-&*w#JY9 zN4~xdM&Pf+-?oOLoun%GCb8chtDZmFe>4r$yqa35lfPZUFdwhAeD$-7XlOk@YEu%uUtj z%?s{83}p0{-J(bDtm}H5^~5+dt(J{sFCk?qO^uZlI*InvbJ#QNFF$8A+Der(q8=(1 zskcuY9c{bI{B;)8c=A2;fOG(VjI$|QygTcP8zc+<>Fr(*CvxLjqujjw_a`U^a+Bkl z3sYr+UmQle0fhBjegl5{0dickoGspaReMgio1ib0FYW)Pi83K4Q}D^THCb4Wf*9>^ zV_}bWiyUf(B>zlJT^1H=7|K@?fOGS8kUG%!>l}ZmVx;zJqqoHI|?jtxc6YGe;xv;9~{| zcSNLn3PXI)IY^E)$CjF(v6}Yasi!oDlH+NF|g|J~bORy^?AkyS( z$xNXYQ!GX!(+i>@&#THjeD?`E_Ik zhAIea@C(FG%XPc9Vroc(IDHe7n35o@y)`yO=adn|K8yPAnFg zH0^*1|MEOcy<(Hq>Z7n}HYIBA_z zQ`oUb;V&gJouzDxXToE=EG|=u_f>UofwV-GNP8ao3-a#_@UwJk-En|C=eU2Bp**$_ zpBRabWuNj&K+Pj&kl(%cQm?oO?7+?aDbpA|;}-CpRfgxGYHzVjP)0%mRnqG?OF4Qn z3r+Kv=fY*;wA&ShUkxO6s1Wez#A+YdAsA-tfl$m#qiw7cYYC{;-*B9$brn!i zPO04#%zTyX@6S`Nyhy?fVU6WfqF;X~O}#oE8Jo(#CGA(vS)I-go|0&0urBIV^vOUe zOVf{vul@;aip2F3Q{8F0AYVyqCaF30{8kVELWhY#QQOy)DC-*VT+f;MVR zEx0=jgA-f^2<{Nv2X}X8a2YJYT?2!=yMzEi@*K{tUGKYV)j4~w535$4GvB7GrswYN ze@#!{*LDA{&a+rOn9RSq9wz1AshM82E;jz|=1u(rM`@h*yKd;)*vL^rWmU`P_|Msa z4c|-JS}+{4sdq%ZZ!<%Z;YP{C!X$H5c;1J)ihh;Dg?u%nh^p*%jV)&3yiw8P#?x!8 zey60!_ft#Z{PQrb7#l#V0&ffCWs{+zkfD432?ukWts9$SdYRn;u-zDbqK%v}w7gDfl!4Jp3!ZQcsaK>dHKwC45gz~9cpiSvJddH;VrrT?F+ znZWQ1eaP+)nzLgHNV-STfv-R(-t{iw49!y79Tecf{dwpqoxxYR+EnN4wPpF+6OQ;> zs0d>#>EEcE&s8RiFXLT0|G;&AYx(v!us!s}%+lc0?jN}KGm{^*=B6H(0$rXKFluY? z{)2!L`_KG;i3Z^?5ow^}LAwgqHq(>+hgP|u@AN+$s=kex=bWWQoOn24M+9eu= z@z<*rz;S4+)*%~7bbg7?a`bx}tqpoBH_HTmcYkr*Q1aNhpCxn84#xYK1a+E|Z*q-x z$8z$mbHYsmah;xIsGgw`XyWk`K-OM+j9fpN0Fb(X*VjuYZe_=%A@lg*-kGBIMd!Ul z)ygDfTHimCByquRU@~prt#j`a7GHq&3P-t_wzh`$KxpT=zX}{>U&rJd6o{O`3y5#k z;X}Xf#Y~*ebX_E*DDGf;K&rt7Q)vVr@Q5^5MueSQF4O8h`cVZ?Z59Gx6KwKB*2w~< z5{ifj^;}=d+xRouh!2|M^U^lHRW{?^*mtSd2cCRnmu#6Jxs;+7bSN7)sI^Z?bH(x( zT3l##a5GvqAdw_)|L}*cPLvItmzPlGl}@{Zzov725P`Th_w`+Xsh#$k z8XtSMmtd?LP*4xlC(pBpyQLrSp|S2xcEw9iO*j9YCR~7hR8;s5)K-V|3(9wRiF&tPnBf+=c6-1Us?P*MH!!WRfcd!2NBK zE`IieqweO#FZZP(ONkizv_)JQQZGmf$%a%`JWm zyjplBi`E1&Am#k9X|#7ckuhz35uTmCoNMRvw{V5LIOp#^7ie!RI4kG_m=wP!3Q=kVAbr+jC32fBb+2k__<&aW|fG+?uk?Irf_%Zc)fMjvvEM+B?hUxUl-2> zCkqUhD6WY}(_Q*ngf+)9cfOy$o!K`Qr1W7(U=)7Pr5PRT$;{eCNE;6{JI?%kmFK*8#q>UO(f_5)TI*oY1h8z^RJ_1$i;Q0Z@w253GGDZ*_ zn6SrRsESek13!C^Hn<+>W#7ZfK;a>R=`y6eDnQzD&wA4?VqD&)`w|e}5u!JNdEoG@ z_iGLF$jzKApOFO8{aq5%e>9F44#r~eBee>)0OUZUgCJUeEp9y|PN^jQ7Kmhfyb|vfPvG&S0LO*lMnz9T+H`E5*_@0lXM31ay-+X z!k|>^XD6d5Wwk)e3;2?HgSroZkY^6aoH-mZ4gMVDvho^AAgE2*WSI=LL+xQZ&;)cl z2J%s;26(7^BQgbnAAUBkclt8>{S>JAKn$rExzNvNXun0Ud}etXZRawVNVC>e{zO&D zD^d-gt`vXzX@5gt?8gIhtpP(=3hU{TXayd}t5>X_>%Qg9ly$<3HckdLq`8#

    Dtl=~q8lY*16U)w0tS1tMxyBu<;t7@4D0S3Y>N(f3dU~b8r=KN261FUh;yMvC z&hhdL3MBOIx0i2PZKu>Yw6ifHLs<8{qFrnFaK`GOQ)ia*v88jq`mOb)Pd*Wa$L1Pq zDv;!mk0^N7Momx4{!{N||E6{UkeNG-8Upv+dnf~Zi;F)aSC}oFjp_IHVBnK+39%jk zQQGC3+{1Cym?+YoISSqw#^}*h`>RHALK_p=H~EQ(e?RLE&N^aZrUtr=_R(N9Lq^P0 zkF|!fsOMSxr|ZM@;d6QDo^~jX)iRf7QfQgJ5*J>Om$X7mRPLH9t24ED$JA8o%*jS@ z6j#8tXb+I_Q0zi>uAXUl{uk@Wc{0nJz3n=mHlS+TqE9{pJ0MM^i`@2}cfO{y|M!?( zm_$H=tNaQ9HUtt$sIaZ{`QaozUD?;bl|Y;d)-8tlwy<-Ohvzg&cu36U4X&5oDd z%L~AWpWGufI;RC#SxPuVAG|pVIEB5YfHF+KL&Tf3)beut?q?ZUm(t%i{;{Kan&otG zG^3mZ-n{Q~*HU7IN`&p(g&$Zm=uMq(!4^-xhS2w<>RfnNaSk0}MhS4e88qw<^ZKB| zU_N0cSKY}S8nYA@VU@2j!isudsc4#L4nlwPbkY&9RrZU@cR0gTw~=HGg^M)WWT34_O%Ic=;QO z-s>rQt<0r6PSa(rJZ-LrIsZqQK>Md zn`r$+Ox(q^)o)^<8D@z&jB<3-TLj1)0H}3kX@?fSKDH+!n~=vdx4;~xT!_C2&}1(Q zsv7!E#2)J|DnKXKh=*#J(J>|FcF)#RKE3+@lOuAEY=Db@XwJ;%kd*~|EfzZW!TwA# zy3E}i?9sXeRY*He;AsONwQln_?R4iDGfB+OSmgqSnZquhKco|m&?OC7?38An5uvZi zUTUbN4hzy+WX1vSs%u&4eeB7o*b;@07Ssx=6q3Cy!HsQ4wE7-IOTTMF$-{i((s7cN zqP^bB7XZCUKk<;!)HxRtlwVTSm;U!1ucvx00z}LU|Bss@akUS!KN-z`->6o zEqT@2f>3q9@RiHzqygfDL8+s0z(OR~Y%~E^X8Bo!9MnjWh)XoAdgqz;K42+Q%B3oK zV&$VzM_$lUMsrLw+sQ8Y_8d*bS;TGzP*>XA)L4!=9uwK78m6==n6imd8u}ylohtpR zpz&;cT!MKqRC7|E%iEROIo|@jAmL(bHvxI<^UNJ+<6l!la->O=mb0cGxzOe<=pn`*Asr({J@~it3{!R!?-?NIlL&Jv^jQMr(-1@Zp zl$RfX2LZt{wL~Kma)~Ad@KQ0d08`NMRp4s{_UWTmL(ZC9~%R~ zrCJD|5el_fR34kFp@OBA$j;!8bRh~?Q{5nUeNbtBa@|i+9A2UY@~)LJ)yy7COh}o- z_C~1>KUeV-G+=hVjaUC}fTi~3*<*|Mp6`ruTtZImrc91AW@fVZ2B2euSw-OJSZp!+ zu6%cTb+czlUtXQigTSpNc68H|G*VnXxoeou2w86UbW)i~U}4@))_Ub*U0pDGXRiX} zV2TG(u`K>JXnS83@3HzfM-1)g7q>i^;Cs@#_zZ2b!})h=KVA213^QuZ^xJ0E#VJCh z2Ci#JZ*H=M_>(W0$i^GPWHCaPb=#Are8+E$(ujlxSfdu=2|&3^EM&(d1)6}HCQ;6U zxwedUs(>>$X&@oNw&pP9M?37^3TP>+Hc(>i( zjAJ&sJ{r|uTEv#zuNl&?;&Os;6Ig+^!3_%AXpZlZM}Bk*C1H3lKS2bo`<<+k>C{oON~6vSUHot#EPTO9^^ASrp*vyG_|`m zymDroMP|IB=H87gkcQgH9<)YR*Fh}s3bFu%D6+Cb%6(#>h40Gmx1^e0dUZiI?YJl0 ze!^W(;}LZ#xxNrMuDrpj6c9zY3#BpLPeU3?lqPv1;ZEMNL)4rx%>*ut)uC6>FZ zO_!A<1FHyjgZc4^6lv5YM`df;S_AIOV-&OhLj6@Y8en^BKk=P_Ei zVMSzb-Ko!LxAESxQ*lSpC2$S`-gu^N=%~#Y))m>>3dtIE-8$ zSUd5RmBNd*i?q$nuZlKlen>LP93(e4cn|clM6@Qq%_T4=H zA|eHBIUi-A^%vW^{!bRrO$~+!^&e99bC#NF%RjObJMg(G$(|#@n^?om*bZ@5ec1As%-*5pM^=!JPiXFQ)2v_%;f2i}A&HfXOX7sq)-aCHx#R0^&Br zANrizqk&(I4pzN?ywY>nqG{wwcY6pIR~B z-=bR~Z&pu{F4(H${b!cR=jb*Ph;rLJt;v{^Ams){@enes83*iBHX~e}$N+KahO1kF zPriJ;lxtAvF#@?nC~L~=9_Ox+?9E<(q;%YCnwugARURbEi`0q4CVRpaENz#UA5lX_ ziZq%^n1T~5%1ei=zEj8C?62gdcEBFmo};-EBW^5~W#&b3@Tp2a;%dm;8Lkjt z9Arx_O?V-LrTN+n&m{~_qbM<_e<9}=mBo47u{%3Xri-FJ)P(oo*IMhX8jj%a^BZ|L zn6(aat?FVmp^<2kM9KOX=t2h$pMtO8!vD$kRPRVN^IZ~T=~5p; zo}}(=q-bHO5nDEt83$5AjElPS_qGR^(PJV7ViyE4q~ZL*;}Rc{kK#2KX1X;q3HI%LvLu-!GD7q zOZ!l%l4iiz#Ev%D?vpavHxFS+DeIte2WhOi@xL#!AcZ!R|C6w=Xl8oB@%KUHA2_ti zUw?TPh~&=eiIa)w*t*N72`x%=)f3lf{xF9?r3p$EhZX0kB{c?hAL6fKxZK-Udg>0e zksz|c^e+NH_UcbpZGV+2E*M)4v$MqIA1HkFTpqC`v>Sr*hK75!+f zMe5{Dc1;19Jg=@})%h8_Wwi8e>+I@pl-8{!+4-b7>Z%s(1eJ_%I&7!jd3)~f>(MLb zZa3H;nx`gnt&+V5DrMM!Y<+FZMXZT?$X_xu{im7eFhOkZlfYfgJc=BNpXG@T>FVan z)>{`yH9t;d4b*aV2f=wva2vH4S@W|CIkCH68lo*9xje9NdD_W$356IQq_&8-I8bnE zdoHp5j@EQD^fKNsbP8NipcMa>V!Ce8w6DTaa~ernhc8Jv=@+LW7^gGE=E37=(;)FeKt9{!p;ALUqA85SyDLROqPn-6bO`c5bAU6s z-TpSSmn%gTeNqGQ*b$pcl+2#92TBv!wm2Xf>U2=JX2{CZDFKU$!r`!80^wIOgbxkf zqiC1G%DxzP{Bng!B_%oPDtZBoTiG`zleZV{z2myDi=g(*KSWYYdTGGNx0S+~_b_S-DnD z+hO`VxY3R5?Y`my=fuJJt(wQZ$+&rgd^{k(eVCg9ia)ZPt6&MJ?z@uUvhdrMHVF(#L~GJetcOu2DmlkhvOwMB zERCZK%(gM82u8@Z=by5-Fr;L|D#vNbl?Tqv=s$?Hrrw4Y2lxPEtTD^$x z`4WecmvL+pJuU0GJ!_}vYmT6Wh5zkU{a-L_y#Kn?|8b+nLHo1cn`-eEPPI+F zF#5({JN;}hc%>*!4qf?a|8U*04xR{3oM!(-G)_l0XL(O@CWDb8mn25lgwCw$H-VLh z{Vf)k5P!aN&;S(`{jX|X&&|`Mdb_$Kt3g^MAwS>hM2q!jEg>yMZjCdh_DC*B&=~i` zoxZ%K-sJ!NM0hFd`UvUN;|&fy#;LNidI5bGd9ppZ_JQiG^oux09d^ zzfP0a5)7Bzkc_0PbvnsZX-QEaRgO_+iD$XEBx(BOZ!0dqN){7eK3zAG{N{Q^s*194 zyKU)x4K2naeV*%D@-jbTF|6OV%qq#UQ}B60>G2nJK9>7{pBtaj*IG zY$btgtzmu^Xq`_3Lw7vo4_{bQb-K`jgLF3Z z(L(M0K~%5&Oj;%NGH%l9E}WS!6L2tZi)`2SxRFRx85nP!pRX|XCH(4ZDL;MxK91ak zXeu(AA%&$V=eqYTGZr$FVzy>p0LVgP#e-O;H_b$;AkKtXIp;d{lKw`@G43)bxQ8!}^4gb%U=ZiQK&MUj3IWBgJHx6> z4ovus;fJfa&M6kh`Audr7%fr;_|yR>C`<$lx$_NN zf>wSJ8ir}D&JxCN8n77e?Hym=dH9)HBUITiA;pO`^%2C2Bm>qdICPI6wPg_mhAPda?)ig69@FRpM9MGGvas6xpt9LJc z&SBQqb1!sShV%8M&#=_#DO1nN9NvNvJp_|1>vnc(ztQQ`u zO3m|zVm*EcY;Ub%rOjbciNDl6PS`)WeDe1fquPSO$b!vwo4AIipoh)JN_ngg!ahr% zH4uygS$KVUtNV!u^8LlOwqY#zO`~ku(&g-_>px%ztM}42gt~RHepUgZ-$vCVq=|R;)ff z<%S1J&`u`UNSD ze04jnbPtG)zpVk1JKJW(HJE5BYX)HyF8xnp!E~eCO+4s6xE8uUVoAiV{P+E$#3LA@ ziR0A$%Az4OhS%4IaC5k9PSdu)Ne=R8cG@uxc}%{B;bhZIMV|uuB#M>BeEx82+$IXb z_qg@sNvDga=FU;cMU4{g?xJ4p8#IN1rhh958vu8lHI3umxBE?EU?Xbf03+{_)M}=Z zm&%32K~@D6Nc?VP|A-)jqsdECjEp&EjJ7gu8mrM()SEqHYTJ?DnaAo6joZ%eDh6CE zQ6)oCbS(qEU_eAEKJEWouo8TR~11cj}e>jVms!*i-Gfu4tG(gt~714 z(Ge@Pn;%z`1nC^);DG$FZn}7-Pj8mGXU{nkKZMAw^>d;#cl4HqyY0^$jAUndoxq+2 zrmlg?IjZF&Gu%;+PbKq}OjuF6bJc!snY&{Ut^9fud(y46S@eww%Yvqm+rWb33R`5dF zbw~KNiQWvg>q9NtRT#|0$pQs8L=&l0Y;7B>c?&xzs5QuJ;Rj)L{L%m$9Qg1=Y#l-s z8tU~NkXB3va^KmctjJCrVjKz zA=A^J4i91?hFp|RZ->20K6a(Y`)8q!#vv?w;mOljcMo8AI57aQ8AM`jX;T=-uaEZ~ zN7>y1J+91&OLXVum6m!6g|0wuT)jzN(>J|;F>0P;CI>!GB9PrqHUA12m^h^ytQ8@- z(Ev<4XmPrZ3xprmR3~Tvkw#p@F|A!IqoS_94(t!uR^sIJ>qicb$Sn!D8nDlQ6HGf= z%rsiW<~^AH)jmGaveq=YnzXf79Oq}Ysa!gA+MwT-(41y@dX~F`G^nRhi^I7f*h>3p zi2TET0B)W+fWv^&*RM?G$fRh01S4HV!dx91-V-&p9`ug(A;jC+C?mD=kL`84*o`ikT?X}pfIM{;V^GPOV^{GYb*)0UKQ}y~Br7Z0CopJKlF4A0Bzhc; zqUQ+h_%1(bQE8q!4)Zr57zJ9lEArxQ;xeaX?V(=dLrvyO9pKb^N}eVIuQ`+;xDz5T zQ_+wqJt-&uo_Y{*(7^?+a*H{ES}zV*4^M+%B;CUqg3JUy}kJ~ zt@l)n(#LL>(f|rf)bd*Icu*vDBh2_JSxh*k2d_P!ET*%qXVYFzt_5$_u?}hqt6^E= z;l`1B`0hK-C2}TOjHTLh=fewlVdJ%7ExIktH3=!OB}BpD{~2^Ox+;j3p2SF|+WuL6J@IS$ z(|BBcq#K+49<0wj2n$v4wg8VOU83VO_2#x}hRq}*=~`9mL1?EfLBi*k9;Joy`1JP# zmrEeqW?U9uZkOUfO)8^1?^KGu+K=&DDW&)OLSIr7KKh>$BrfmRe?JcYdI$jE^8Nl@ z&Wxgp3$FrMIAg0i8r>dH@|MJl8TsOsirOU_VdOC_Of>H4T1GK zE+#Xbt>o*vS@S7I-Cu99H8T6WO7W8*ax7{7TL_hckDhY=)~@U8#$QuKqIdDkRhsyUg+-JnzGk zw*|U^&9j%R%z;!6LxUX!PD z!!Yp~i2W`JK6!GsZUJ1II%pJVx5YWPV<5q-f{4r*VG^Pr!Azq`QXM^`9&0$Gicz09Mqx=z%(sq};kiQn%c+yTZK}0n z^95!s=M!x?;Dz``(Y{5+Jv5Q6tacmhm1eqK$5&BkoFXs#HN9LaIvf_YRr0y6`<{CA z-T0OAkFCET^WoMs__9Ll^OFH(wvaWl6(M$;MCk;P5Ao+ADqkcR)kWzF4$W$)+p0Y} zj69`V&)WL4c=p|sgxUlDczXw&HO|k` zlP17^DzjD5?JcjyehN*L2MeXWwQ-`wKg}Q(n=S8DKd|AOETKmAu-zO1C;e5V1A=)@=Hn%fstCuW)Mjwvl!~@kW9sm zUTX0rmi3TTYBo~Nw$*Hp6Av{1czuQiFE|aJmS$^Us&?$+bjjB0Pm5AWxgXcyLxXKN ziH^}vtfQ0+5qc#o6l1iaN>Yeq+U}ZgN$L)!b?&is+XI3DG1;Cf+ZaJKCjKu#zUcWE ze7#d&m$VrRc97yHt@EJj@Zk0L`n1%P zuC6Sf^!=j&MrB3Q0#l150fFXwTg+rxdiumVQ~1~GV18Pt<_DlPV?2aTr=4{1_PIT2 z%BER04MA_!Yso*pV_0(CFnWKtRWLW+9bDo@u{1_*Oy!6)x+`1ngz&qLX-jo_y}PM^ zW_?^#D8G~czAo)KJY+DcD6f4nP>V!$kr4Jh~Io8 z)Lx3!j?Nh<+|1pUK5Ucs>qODu1T~UfQZ2|;XhAwjK8B4CtIS#>1h`)todx?_?YBZb zQ4)NYmWA}iY~Rf?5QRXhBbuZvn6G_Ku&W5ze_2< z9I;Qbb(&*OPNFpsF~x=qTN}!^_{DrAUoVA4p-)yqpbGhl;D>!ft%;FznR`8t`Bg2! ze7}1#RjFPhn4bB6E zR9uUfS*0ix25#(FTYNq*T_xqqa4B9}O_yLUxl_W7=y!l}bm3;@Cte z_XB46k7{P~p|SwLyU|r^I5O(SNe`#8rOk&8>6!tS8#29>;NM(bwH!Y1m(E`;jdGR^ zgBo<>djC?=^}z2-V#Y!8{R*9^6v37LqiD|NZ5b3JHDEQphNh^;doivlfTl1lbZ+^G z@-J~cdopxZ4E1GhCUgl zm*Ao9qMcbp`6@j>M*>%VfLOG)3w7i<}*EIEQMu3^-8S zqBYc%fIRqXQI(!oQ6+4^M45Js1_KY_AlHIiY7sE{@o%CUx12w5J*M%oeo)m*GgF9?RZlVN!ET%byQVr)g6| zal5apx-8?}ZkG)K<>@F5HsX;zX8Ks+LEGaM=A+Vzh-hUo_h}W9VJ~PFN%8jY{a;C9 zfXuvakr6=prej@f{@uoX!lZe$HLOVU-;*qJA3o-5?DeXQ{kR?Z7)`|U)>ra6)DDw5 z7^{8t`_UQ_%Zt0uLA!azSvg^6E{@31PuD!dccDL*KVM=kE-jkNL=mcE0S|N+sx_~s z$?JdePC=Y*oONoQANojB-ADvGvu5NXj_?SSci;*sZoMt@$&}G1o9+w!JWIp4rvOLQ zFO;WZ()RID#tVp=v7SbqO)p4FM{7wu=h1kY9pOqpGTE50k5?Pn@r$UjE{YQdzUs>s z1Y^2(Prg}j2en$`-7@A*WQu#H!~Qa+OrKTP5mpud3;xoh8YrXvRJPXjIwX?wSGY^$ z%rNF3xRivM51QJx-zdKEzM6fLceEv1;gyX(B4MY23Qk3k=V|nhHTnT%Jksc52xo14 zFh}ok4Qb6krj`(lmVA?{S5E5|A{3IP2CuEuSQ#F%=W_Wvmg%Ub4vpT9U~*TwqCr(9 z?U&CMm3YIynfow~ny8I*K;%nu1~g*Ad(xgi^XGfud(IcJR1n1-M+@K3FBXu+3#OtB zU-+LK8EGuyB8MQH;ouJ7L8E%uU6}}qA}%iR+mmW{zAR7aGMRogKl5pIcXxhyZ4d7RPECvO_tmq%a{7*TF=ia5NTX z6(N&}AabeRC^f{ypBPr{l5Gal= zLu3zLZl`@7hz&bGZiTKp@OVW2C8}emeQAE@=lMPmc%S3 z2H%%n8o%Z9Z0|!xS;{gU8i01X>u&X<%goZOS@R?VBzWcn|HJp128#pbMFAdYR!ZQe5 zgHSoLz7**u6`qi9mb%_-3&x`mu_VX0u~9O5BmhhrBWI4T1J-qQtS> zc2Z&87k2KObmO0mV!Jomn&FXXynMl~nz*8fITzi`jqYDP2pFJC!s0iIDiZKDhi*{h z)tWOX{aV&08bi??U859bsIicM)9*Ag4Bjpy`Q6p}`Up9ok@s69PQbzbcKKA$Souq+ zv9=BlBTs2`Z{%_{-UNT({2#cj=j;&2PhDPGq@+Y{?WW1ryeh5&VJ4ztTaC4Ik^xFR zhf^#lUC?k-WRJSi<;6vhBz5uOVV5j20#wbcO@$2BtDRz0xfqD+tK|Uz*DH15vIEX| zByzb>=oy;@f3PXeP^^YXGQyJ3N0ziSpT^N1TWVO*1yDuLWS|KzL5osXefZwdB!jww zv9dFZ=L3$lTzc;sl@d$#w!_7EIs8IIFtGVi{lZbD!@OB1 z_au1db_wF51ut?;>75G;8|CL~r#*-U4Bn?`os3Pg*ZR#A^EV|p z^iJi#wIN-zyKqp@hQY_iOdYSKXDBHuR4d-wA*S39|247ip?c7sfu!2TZfbVBQ zqhrJ4U(qb2p}OixF2u}tD~jAv1F3)TWOYJ!xrZYpb@2LC-X`RCqVV5agGgXSy5>p3 z*|}%NB{Rm^H&{-7si(H~`)Yq0GzWzu7osl2WQIe$#GAH9oi=2HXp|q=^M#qjv6Bt_;K`xH z?UBBt*VXtc6E~+y-8`-kuGc=1#+oM#^zkov0dY1k*xH^4?pf#|qYo<`i#jTvu>bl2 znD&CYWVBmOAVEvpY>`K2Ol~#CX_gK)dmpq{7g7+h-4UmDRu()RK1KBQpE;QwO%#1u zSuAvut$f_^#$18OMcu{W+=e?GXv@N!eQs`8J7DaAL7Rm5!&>9%SUv2IhsC#)5#rhD zeUbiLvs>_-zkPNF@gT)GdSx&d@d>P_4NCK+f0rFAnC!gG`3oR(>hsY2I6clpAoA*| z7lInP@cClXycYtUp7%oV#y&ywIfjeTsLOtc``3?E{+T+1>5Zfbb954LXH2&P2UkM* z1m)`SmZ0LXZ=j$5A$K6@0s7W3s$(_Qwe}|p_ zaEE)m7WJ;HTo(%^q}p>rCjCmAg@2Eob}gN;Ww50+kAPZP^^Q|*=Ka@EjsDow{<=oN z6Kl*1F0-To&YxXUJTo-6;Xq0(WR?gbZVJtV5Rzp|21AE=ode<)0aEpG1`PpYKA<%1 z05hExFRQ;Mudwy;J3H$8Ckdl?VJ46VS6=lh`wY=?ssCYWyUvuGl4x?b!OuOAaC zL%}R2u`k}gxyCzE!llX!{_3ZVyPHB&65q>E^h$g3LHWtx9Ee|>jA?x6ovpxM>0sF~ zx%R}>Jjb@2jDs|LSA*QwAWB~{X^&Lmz=4O8Qpjf2#&BdBA8X{cp5U@?t(r{XN|6o9 zM4EP_{T?zsv5~OXnsP7>@rSav)h7YqE``oClz1;kQ3_u&ZLd_1FX+*LYAgFF(v~7+&(%4| zEog=bYrBmt9)2=eiGKoQxI6Ew@dn-^tdb^|puMy>0&E(aG2J=QQE9wGmb^XFz21FA zs*iCsW@pei&fjDBl7|LTD^a6JkMm3)Q%|zGs%=OSw|XsC*BPC0&%dW-CaL!+hBa|F z(AA3h(6*SzT;9}@6Hd9M0nRRsQNm~EwbL=Qhx;i(zA{eoA_2-rTa2wqQ$UR+;a{UW zsi4Arjxm4*5sLNF6;nxvjSjS{Eav0;#^R9#i+!F_0|k2_Qnm&Zf;bK>7L=`rT;^i> zwvK$o#%xB2aJ!Q6H{JZ7#jr1q*;Mhne5@#paq>c`VA`YNo61Xj}A1^@X6iw zS>Depn+W2N*qs;k!3&|Flg=3dvnUsCxr~Nn&F$BL1QzCrjx^Te5=8BFQhnD&Y(_c| zsF-s6lRdAgkOx^yXb|y(7M{oiwQxzNj75j$C`qW~L%C3K8mi@~$ytHL$wIdxcrY2ZQmWMZuGK43= zT&T2gCk6B2vnZ(W%c^BCfE5Gbs)6)}%Br5rT?3k57pgFf?9sj!ech4`H&4j5ec%LJ zu(w6P-2ViL>Z7Z(WIr_dzuh+vWN_&^dB`BHP{RShv|2u2|Ki*(8{N`l;ZJAY>lH`o zLXXS`{dQ!S2sk9kWR$D1#`ZnDN-tYj$r^vBgCc?$W^i$gPonLS1g{xt^n$KO68Jzn z0$QEP#DXP8z9;Z2WWwkw&;+BTx-109b>3$2-YxRo6QoT5JCfZA2HQ`6U-OByD+QU( zAB~4WF~d^Dk1DJ|--=pVB&n3X!Ij2qW>-YegmS{?pwU6iAj?!~baR;;U-p-sm+i%8 zx9YVWcQ?(QK)*c5l!j{vpEp*oDZ&rPd^?Y0*;U}MWmhSgEqa=_hHDm=*$bm`4loV!`tP>|9x zLX)lP#VYN&5nItVukoi@;6#J>ww_EgB=HRUZ`0_WhU_m%y+;}_GCH(WXp3!UryA^F zgXP;HFOuM&)d>yRoLZXENxnzRn5R*1)P-#EHq^{eZOm>9f15qVKss;ffOh0EN+iYH z2`l9@n*0ODlt!(Hhzjp#H2gix-i^E0Q)rNDCJt283azVUb2FlFdPioMP^Hi&XeB0U zwukBOALCrfhGn^2JtynvXSg|}H{Tt{9V^_%!Hr7IQr37Hb0m;zE?p5I3bg{q+kPXz z?rFtv)FRo2@!FGDwt~AJYo!Us)7c2ym>5%v^O;U*u&xBR{A}VW59RjyPp)EwgH01{ z2txSiZg;tki*@N+mnZSG7d=`AM6ro3smdDqL2GPi{kihFAsDjlOVQW*cOt8g^%itK z+2--I)+-Zj@xP?v8JKk9-iL8j_)E!ac=Y5cYyu`Gau1HI%aU6T<6f-yO<+xDC-#(> zrEnBvD7X{mZPIqPePp*Dah)R#_nKpfP87Og_6c{$BXN*Sep%ZYqXqlxOT)`nh^k9R z4?_MqM1W189mj?bX2!?P5g;vr*DC@i>V0h-Y-&ZM)ppZn#l13>4wU=sLobBG_B#!1 zv1KJ>#RXT0p?M0S=BxkOaC#IrJ3k21{nH#k1H!3a?(Ej`jjoc6ZfCQFt_|t#uGPp& zk`@0r(-)?c#o}RdF&kiW+p=ZcwcA&TFOZ1?WNZEY+~X=%v+x%fF93K{`MECN=mHfb zcd^*J)MUId@TR8M^m^wEw_fLY!IW%{rqZ537FbXp1cmd# zfib9LPQ6VkoFs(}^IBP=`nkRfN0easjEgI5dk{ZxG<+gtc!6GACd zu;3?MPoWbV3xi<7vvsXZyzJ3w*SlQWCt}8!?B&srx$CUPGeb%zj^t|* z^1Kx2m0$3GN*0t`)4KEsMW0?L2lss>Z;jd!V-~QLsaW9}X_Rt| z7JUbBDeicwu4S&}+*&KSf0~D+o24fk3U&p#dBSgkAM3>6tW=5f+S{XAh@g>%?Xlp8 zhJ!j-)m7l&&x<*ixEcH&kNd?-;U;S#Gj!gpuR|A@0^-*Ai8a}C(w*_8z@^Mkxyh(~ zS3asYPN_Rz6F}h}AV8-fV%OTPWw5+I1BQ41@z~<&Nm(H0!Wuh_nn-YDr3SsMcw2gmNyf=O+&{O^-xoiN(FYY$) za%xOyh7ON45+z!IHd2j5jKA^kW3yOEttytqFjrwZ+kdbQQE2;1!D~3vvKG6N?lfTI zqkE^?6-$+$mE-&x#5Sy$jPF|e0aa$ODW_SUK#wm+F*5gSGD+(dy)^aS?chil!hyei zd&%;-F+*@Bs5o99#po#qZaMqt|03?KquT!7eNQOXV#OVb1ZW{Zai>t+9fG?C4=ye4 z?heH*IDue=;_ktMThSJW()K&tIrn$YnLBsnt~qPX|9d_8?EUQZ$>*`x+Y}Th)M@FO z9f~GJZekPIVG|@==L0(V4q}KmM&kCQ?!od-yfwYY_O&4ityNJzwuY05C8Tu$F?uKE zY3YOR^QyE-%sXjn*wO%qn9KGQF-_I-7t#$mK}A}At0Ekp!7IL=Gs$J}3a!E&N4q?& z_$M+GZFk^nnD#Id4y{?MF<6Ci+QrArF&RkJMtHETGll{ua--i~P2q`-x}l~q$+^XI zmo8SE>NU~yitIjX2uMEE{9)-*c0v7t)A@~!=FZFZJx)ZO^A9@gW|}T#O~XN8_0LP7 zzfF+wf_?xgE?W^ZNk`k6W0?mifu*+7@NcshBbUBDySxCKCA&!Duc-L`Qu9-XFGkrO zhmdzS5OH89=u>0eQyg3;Ly(e0IOX*8@+|!4F&jWnGm{6QuO;2^ic(6O0xDe3GGLCd zGrX_4?+$&tr0E6wX3u6@8S9{0V}agfWW>#~ahg2LQW{z{_U?rsY|ULvzV7m{0VMZi zbx$UQNp)Dy-_n7X@w=K&&zlLVTvuU@^KS3CL`Kp7S?6h8sL2Ye6FqbZ!9PG$t*g6^ z8os0{#Q~;UZE`qIF2u!>gZ+(paevtAc|BtIo#wE8(xHIGO*J9TX@0LO;-;x5wD9}Y z!&8bQ4mK#+X~c#|EN97aLgWPZ6YpL_mOQMfTT3+}a+e^aZ}6gY!k^zX{8MMu0VCPM zZ8E_i_pUBkfj!ftm@?9*bY@@UKZ(bc)m{ zrxiu>H*a5OaOf!AKe`?o-Ze;5)l@;9kkdAO2)z(DQG~%uJh0jK?sf1(RTfvM?Q|S< zjZOY59wQNYWvs3im}ic%i6&7EZ%PX@5mg>EEZfw|sN` z6olSI9Osp_iw#Sn@&P0mu<nr(`scNMSXe9%1gL8JbBDE3)d zl=0sk;Ty~Pu+-gDp`k*_t~&8JO)+&Iey9T+EA<&6tvp7rNXE|AEDGwE3B&!6dB&i8 zG#X=oj_+3ip;z@UULsIct89>Guj#DM*#mm;b(~?5T2vI2z2^)5BbtQl?7Y>CpdqJL zd3lnkP=*w8g(Nn=p0wEJa8zcyg>amC5EM@R(F)XKZEQRcjaVWpWB*TW zz5ff6%UH;|6>8Uz0|R6gpgAs9d#p19o#g_Lk&o}Af_ZFkYL(7wtu_(b#eKO4$T*>6 zB=dR_)#%UNBVxB&>`pD~6}oq(-}O_PwG~>Y0ier+(u#Vv<^Iz88gBJx!s7yE4aJpG z0t1EYSi;@rFwdl-hf=;{b+dB5)k?VIDc<7x=Gi=gw|8hl@e7MSbniRUP9UOt)9uOI^>iVRXQQ zzyRAgATs}xGR=i$bSN8cg3cV-(l$KY>6$7cU8=6RCd~3tLWcUI4w+2!+&+;gOMH4} z76C1lR*W&fbZzHnK14%gbn_p=e|1X#Px(pxTK!RsFGwzDBMf+`8h(^D>DKApR4T*^ zJkv&|^`8}q?W#?uGS;WOdT-RfvHaz&W4nDi%>4%i{pthh%_mUa-ns85gUib~@}u0^ zp6^BBs=w`I)cK#86sfFqiGd}qG*3lm1%zTtCO>3;GrI1HF#6TEZ^k^xYz=$LT${M| z5dVz%`drvJ?A-Ea-68%=IY<2OKUKn-dm8lbCJ|3_A717?Oh*@jq4y=92n8>n%`O}L z|87=y^WP5Uf9+{&y8cgxaNIju=ve>Xw+7Vw&wKm#)qfQJW66Kzp=Q4Qzc|&J|0iet zr|sANhqLqp{_majFSB0C;p+VV&9kqbJzMi1w_tvVc;?5%v z@o`F(@$n(_SJS92X$#NQgA>*><<`5teEthndd52Q@^TN~^#qH)AcsuIi_w(5EMTTC7~S?!*-r$9i>f`arNE#r0WF`78WBQP;Z8EYC-i$V=+ z^$>kLfTAWm{0=z3YBDl#{@3xAJWe zAKRer^0tW*>y--zRkr>fgsQw5VP*WslrNqTN@JF)l<18hFEay`@2H;|tm-9cExhZD}a_bTXZLQw*A}WTbQ9+0fj$acCJak z+FVUfBb41H=SJq-$SW^lkVRUr9n@mL=;^kY_CwF#Fupmp%BrBov-)Sfu^By zps4)`=?K=Q-Fmwv58pcv$aicv&|MRA z3G}_x-OKp11+C+u8_%G|f!cUnTM7&79O#M>5+}7l!3Su%+>J!tKmFT$|AedVpPgqe z3~<-Ei)T&R^%x_dfw5n6g}Zk&S*!Xfacn4OtPH#1!j8|8OSCShvy3fTS7KDk*Ap!R zRRDJqx)0GHL9+%gBkWXOd9hQAw2EXWZ0`gsrytt?64Sd zmmetu0mh56vL@i#Qj0?3PcX7%so52$A1^wweXCDI;0`e-qwo(3j)tOL_XeD_x;6!_ zL28@Z=@KRZ7RssnKJqajhl~ZgUEY2|*fTZrBN*=uLn0zZP69^ULma)C$_}iBwl9FWU554Uhb)2$-S>bPM$S^PnY{>;dcG0Z;i5hmQ zwRc(v`|weVVpn=zjVrAcam)-v?-OIXzHK0Je>-f_L83);mzP5fCizC=dm!J{`8ZKg zsLfXB`2IT@wFKib46A30Y=A;UK zi)>^&I$=fMNteUMQ{i*~SF0Z#PV_3ZJ6k(DdO~*aBVHM{ab|92Dk62C8(m~{NnfbE zf>Q3f*|^mYT13*IsFr@nzIv6;AH;FYrBG}`z&-cvFLa?;4&5S1qw23x=h}VQ6Zk(rmy8ffDi0pv|IbIG4kT zZ>zK$UG2q0YCT2Gnz&UuL>CI2EA+bnUq^Wq1Um*ted+i2L@i{^5;|kWYQeR?6OXAx zN%VxK!6j%cYNIXiqHey;bn?XAJh21`PgNA+vK!Y#^5 zR7!HbQEoORV=%M4T&$n<5VSly0{61*g5F|K*FksM$8YW?;7b@*(aRvzRM0yEO^TG| z7d-dGZ>)oHJdk`_Mk}?K-oM#Zjd&}8waHEWA%ksakCsOohMr7Wkh1iSN}oA}0`=cDmr^EH<(uFV0n3fYR+gzfI!7C&!#p-J&rTfx?x!EOMkIRN(=D44UnHfn8 zjYIjgoT_ob;>!!NjeWcMH%c|OPKoIcvWD;AbXn!XYa@esXe_a$X&tWnB6 zz7o-E#M}xXz=BKa7Z*ABh@1hm9=U0Bl1afShgu0XibPDw6$x)vZdxMTG`njqhda9^ z7)XUskepb=wa&Vb2~P%aq|2emVDraV9!fKsM1SFV7D`=>D9B1Q0=^-xeD0CY0&~i4 z`vRll0DQZCgMr(zv9X`T#K6=7Eu-oVdi|qlVUw{5$;G8>D!ijfF0WvE7%EhCjl<_# zEl-_nSd#nk&3A708FO!JrT7BPO(}fQ#O3#w00mjMwHq@`(GeuVaWv%Q$bloJ+pp>} zgni=;!>`Qcor4fYSjWIS##ozo6)3;_HqpTcto@JO?eBwjWFA{Y;&Ci~pd|rC;jks!DRd zD&}ArFv;}AD?qrfT6ytb<>B=w4rwpTG~tppG((Q`(Zd71C{}cVaE=p&jdyb!wZAq7 zv>|T@VHm~L!S!0%uRxS_Kz`pdvz1W=QRRNI`ofc-qr-|^c z1HBMwhAA(h2LoE%!pFL*_9Dt3-5xCJ?O(_#pfYI~3bHP?-)PQM%h3)7mQWyY+SKxQS}rofhe#*kS#IBLkLL-yo!@ zbZs!yUCkpt)}u1EG&cdPpRwGvlO6Asekpn&9JXBYvs)i4H?rrlo9ua|Xh;xNXj1W* zr=doqvAt>z+3PG_#SFmg_J|->frAc~+{c21eoxfiy^d2Ix3ug0BVd4wjPx<3W53s|to&SP#Ia}ja< zmA(TTfKHyMep-z5H;BwJkYcmTKQh(MM!e)ckFFU9LaX zq}KAfiZ5J9W#yXK`NETq?6yIz4^M(Y&QUVHZ3c)BhcoWyL1?0wIS~fA*?%?#@k?ZU zdFV6!itH>HuJ)&aZi)PcY(j20Y|0s$n;KBCuzXgLT*l3Lk+^aB(R-L)u=6JN@v(Jk z7P~{d2b~~uC&VQE8~~pDLD*b7%JD_^rPXi>b|y-6hSKfF0AXI|ec*Zy6PQ5BQ!g${ zxN4ajx)88U~Oa2h}V%M-ZvkKo*kMrH<5`EPB6Vd7FpQbe43$}{ zQP`wHi-uVQWeFxBVhv;7wsJRK?zwv{jRbg{Wq#Xx6R5!0lKQ~!ra2XTN{zw(l;ib- zew?jRUXPKm=9&1=!+C7#wbj4WujX)Y&i`#S@&1G1weapK8?C1LrH4=gmFLzP?4HHB zS2m%GzA2Amx6#S|UbYJ$nA_bt%Ycg)FH3ZtI74$Hq+luUAs0;a-t99f`1Q+TpgG^^$?~kWCf%^aNV7nS1O$>B25hph^ptg zxN}H72#JCgPQOS@LkY_i@ljtu!6LfeOSsl^nM%m%fZ(3n#S4xhh)(K^vZ!5!cm>#n zZ0|x_PxJ#$HAfr|h%d9CKverV1<2=4XA?-tEACZ!u~-2$&w6|6A@Y)fk~hDK}^Hzujm8mb-gr>8|j#|zGT zUvWElKFM|wxQQjPw2snCg%utc@X1Y&6z>c-LJX2gNM`g$o#e%n`vw^_f=;QSrQB`Ey#u zTY5|PCY;j!RZ4b?WhyyNu`XiU^}QYB)X3b0sXPGY{wv^#&p3^5^;t!S%8W^Uj`M}MmKRdIO!zZYXhZXLH$OJDF z!A_7+PxQpm3vJll-eUq{Y0sp*VRsgXcG3sCw-^0;nx)j}&$*cqkiUxF5pIMT0clycPjdn6a^Lm43^j zmxq&1If~%X;=V|k&Qy;Fw}94N=t;Zs2y0WTrv@xI14_p^6{bc6lRR=^3(e`VRoULU zoyms>Fyb|PMhP}b)(mSn39 zEBE|1KHU(fM65^+#c6H!u2DcpRmYC=&HY6OPdv3t&5?_acKYw-mrh6OMc+1lz+l+a@XW|$g3bI1# zvm{EAPpLk*4P0VMYlzP`guzH|!*@UV0aQ-`0m0{QB<<(1TI(RQ+R9O#LTE;~R^StL zTAhj3hx;P7BRd06(57ujY8OR3=Vht`sz@|`7N=hvLwyz-Y9V2AgPQ>$GBx_LhQDDk z$DQ?dLmF@2;+)QBeWg^}La>~_jpHFJj?bf=!1r{@W;fIESP!9H*+=+$g3&1qzvDD@ z3|@GU@S>A6o;12ord8H=jjRvl~vi9tct}G$}I(;(jHoncEi0wmG!j;9|Jh(J6hdE+Jlyo)oF<7 z`huXx4!3N=ls&&=Dz77InT-@QrXA3n48ON#Oj%@$d52eTP{Hb(d*q0UBkQRNDfngf zv>o2s?y5ge{Qm z_V$udS~SvveBOy^&iVz3XcMCMZ5c@S%b-IB0N9ZxH!4s<6soRFkeDdnmSmMdH_zeq z+Df%M31w3{*@i@zr0V8CLN#V&uqo{|{RkJw6)qT1UlSHDQq!y_EV45YK_ad2BAyWM zmz4&E5FZ@om!zeCNSd>RAq$ANmo6P+T3B7&T)|e2N z&ylBnXwpjnQ!*;CkR_q52;;vr1>%$hO8-=R{=)$N2gQD3@%zIAMmRKKjA@s>iY7P}xG;SQT)nhfk{;-@ck+)#?RJ!W}YtAp)|N0W;j($Cgu~M{n7V z2xiv5@#|P9^11lf?b6v^w=wmjyY5`nDBfkU_Nxb;cGmk(7O|;13=zmD>iKaqb2V>DVCzY%+z(SNFty}2pbJ9Dr`7=8o({0~Iq*7Q z*e}?xU1xr-qJGo~GgD;kcSo(ky}n@M@VVnu?^BGvU$;;=%`*Pj$toKHPgjDx7s8E< zJaQ=+sTqpUVpsi&?jG7UlBgV!JkmyZ0m-~5@9|C+tWDV68AQ8`cL$qP?`7WgO6`=# zr)p5=48qUpjjWPKvcp^za0kP{d8h#!Zabo3Uq!21y(eJs;qSO)+ zv!w9@c}uI4vZc(pd3z{KazICl7b(# zX|Z_riUZ|WhrH#Eh*5|V(V=wInMEg@e)v2!QK&>ib{nBKD>!p45l&)`Vo+T3ggIkQFp|ld}MaU zh^I)98--bI zfOd+(R9APIWR6Ez)M6;&1X7gsM+Z}1cBO$0o@v6<;I&h`vtW!-xQAEV>MLU7q zXHl*#U=p}=cz}ndg{w1TO|KUFlR<1V-IjXuw~46Xu1Qmzz$AhR`54RW>HSx6EnC1FHxf6BdYKZJMpHDS<$b^6JOWIK0~Rk$vB`4GG5Ih=s$@wI@o_S)Px^hveBym?CeR z*m=J{tkl`3!u(`VR>QTDt?xw2(jTlWoh1W9%9GraTHMVQ66$*ssrZoKAWnWk0mH@} z+>r9sHRRgw5>!7lH$lejJGEt;*wR+c8!dx1Yte|vX@L(!E{X>ktsvXoW{KB{M!K^b z&Wp<9**av`Eh;6`({86xV1s#q;C-j6Z%lMMnm6gwt!^E5+*rn$`SVeV-gwRJZ(Yn? zTx4T*t(P$RM%U3Kv{2S~C{zj#>L-oBs3W?`(p#Jh!(v93PLXd<6kopEgc;HfCFPcx zZ|zXzRK@ybOcf^u*nQyQPkwn(by@3}xWIpMR4Ah4Bpxqp%VJ!NwBh(VY}2@xRckL2 zmla1i99mMo(OduR$-R9j%YUPw|EnNNJ31;#muJAo(9VUoD$8!`QAwy3Y0^cCN&$gB z0OXE^j^8VRc``~IT$>FRS@-TcyDDV^0nS=xPY0o2@=k}iwE!svIs|u}=Z5(i*aJD~ zVtIyeBiuMB#v<~cT$Ms2X;z{*A{S2>g@{U0NxCzRXjXyce#KYnQ>0D>21un+78HD-9Bza2M5)khqO}19&S|q zq`~zuDgtM%j3b?kx=k7?;-s!6C#u>J&ZdGav6aB)k@vBn4BN4Dy9s`dXWfW~3S0;J zJpR*-R*#A}{KCqbax`{Z=P_ZllIgR3lM%gVfMw_R4eZ3_#SwA??%B3AoV0A%SBn@$w!&NXlXgBA=2CH4X3j&IR;%|ov20=hvgy7lk3LW|G8QHM5{qqiJ|*Y6*{*$cTZ{zAfKn7Slt~YuIR? zlfxmgDy@0`^py*Z+<7A>oZfh=QF0~CslT1?Nf|C)!r?JhTQSXSO;qoMku*HfSKrQvIFy>vAp)>d40-$hM7C z1Zw%3l-p}^mgTbp`n6TZYi`)&IaftQS%<`*^Tx()l*cu<^T?lfQR6=FmGdEkBH7mr zZP4lWBbHLo`o6bVYyt1ivv`w1BWWC$1DhBxRvYpUnG~vcL;6Ml6ySF>hpB)G?`~ob z-#c&ft&jM{Cr&QBx}BA8o!4mX@KxszpQufD5ogJM>kQNPX8u2oKX^09d??}#ab?c< zM3`=J-gXwKkG1N@9#6^>M}-u~W6sNz87^BC-{;bkw*(L0EM7!`^erBslVRfk0o?BK$E!jiTW zDU9sG9d>ztS~Z_$SH)?yX6a`P z=fB*ZtTjJ7Ad-yW)c8`0*inzVRSVM29rK3~QMp>0S)xo!huBPA&;VaKCk%xe44x%q zc}aMndflRC0ghK02ArkfP4nY=>jmGDaVr5eIQN!63t$h2xY%7dbvWK=>7WCm%Lkro zQL$2*C|x?*^Ow%$k3e3l2&Qsn^zw^vRJ_9^U1hcT&6<5h-iWYlImuH#v}$l2SA8b^ zmK(1$FvL|jXJBaKplhN^Le(yghLL13<#q0TW_^es_PG72cS!^iZH&Nx~ zLs&*%C4TEHDdG~sn`5=ma2IxaZ93{2%4n=!uo$ipLioTGTX3VLbk93o&(jL;?;}Es zlWp$k5G_n_02oJjR#=ERnfvGjF>;Kie9o037gOz9p_cl%`K;^Y;MxG)Ke~Hrop?1X zNbS9UG|PXIQUgm*OWwn&&n1XiK0R}!A?={el3v*jETT=!0i%#^YXY%z7 zWwyc@PZYkFWW;rcpix&#e;=lx1}}dZd@z{?@%$ns^(%xBra&>L(D7UYh(AvOFcSqu zj=Q(g?L>#(w7Se$l4iS@7`5`&TAmC)8 zQQqqGFY&(;Ngnye9v-#25a(^Z!Ec}B?KHozJ>pw5%0fp79mDR)*Cru6RUrw}L+-I% zLU#g>Uiss{a%A2Of8_089Cag1oWjag>Kjjl2J?Dv30ToPw*jaH_7eo=3 zeV||T&$`~VtsI|DxmHZd0u-Lr|1fYbW=KuVCoK;i-=V+q>)`3|{o}kTYoZ^uyi657 zTh}g7l9*0TCY`P{{%Dc^{v%UP8hH8~w@GRdg+mOwde2)`%d}ZQP`W7j+cNmtdZ~b_8?0iRQ zRAk$Rkq65TJ@8)i_976teG-j_HG&cy*xG4k+)st?<5)+dMNj4Hh!hk1c=)0lrHH@S z>hZ{DqOG}`14e)TWfIVfL|tp_DoDRTwh4Q`@$@t9FX4VK<|}3d%(<% zsi&fL=IYk07^RKvtuV$j!-O{AvQE>FKsk|9DJI&pGd5f!wgNNriil+;B#o=yqG0Ba zj0glfax^edxA+EFAfH|ph6^H{9kls_HE*XevTZ0S71;l$#gFFqF1wNBN;GAiBoGfkGX%1$$w&;K zI=oGAF&#Uz9yfLV>X4i0`jz?92m6afc%*1S67_16RVGD&?D?d!qk^9ll$Ypn?=>Am zAks*QAm8OOzLK zxuo<{ypwf!czB!)YlWk;%^pFBfJJ**ef9J2;s95?XJ>mb4w-_ zzd8_1#rCKzOO>mV`+_26=0K@`pH)twRyXp%1bh_xwk##(LtRXXSUnk)kiX&S8Z6(-qD`FR(V zDM;ZIo-gNAp5A+c60hqRG^eBYUjqnKuU5zjvs%^x)P|cWI}qfgTx3nv1)bWu3kTh{=dU|Tr0ZS?cS7{7G z|Fo-Jl;Pe|2UZjxpRo1k!Wd^t2Zt2sva{hb(T`H|r*-2&JRw8#3yJHsJKM&t*0HN! zH1nlGwKeTXh=nkF$pJ|<8SZ33E9tGMHnrfo2nbOwPRXGjjf8Tf+toCC@?S+BWMT{G zHOe6+&L*5(Gl!nD zFrw?8b&O(W8Dl+RtD_aYeUSA-x!414;Q1z!f4$Sgl6>VLf8`M6*u5P#4vcC$vX>E7 zi4DSIaAVZ;I5K0;%Ys}=b8}98Pu^Qy1a%lp*E-rVURbr*P;cG=O!mLy$a5+6eP1a4 zQ?w@CMxxLv06ja9#w3%^(c3MBjym)DuhaN7HRXy{r*f6`e`ztjcXxKt!{>{S?CW>S z;7}TSsjye3!-wyea7}1_^hV}5?=8xA&RJejZSOdN{m{hf>XTo?ZDsZn8jGzRT}H{T zS|pL=#@~U>(4I}&#mW1qH>IQ1MsbNOs$DA^hwSR)OlgTq{m0zDx}1F8r`e?GYEOJJ zO0;nxs&I<_LPF{_QOb`u&(ls^eQcocNO5+-&E1!WaC3%Z;i=wi(1J<+4Y_T8{dL`7>$>vu308IdZ?h+M;vQxb>e;Ub zMPF+PKQox=xc>TL(*2=}w+-vzVw!(m`XTd^{jbbSv*E7mBt+|s0U6)_fbJ&$2k~Fh z>uL@|JhVPI1R_8`Ikj2ym|fKRYL>pyI&-On2vr?6e*R}Qta5s#k(i-XFXiD+L~1!RszCR%&+DeCNv%#eV-Q)rpDPe=`S!I*rLlm0FtzZd)$Vt4ZLAde15i(R`<>*>lPdEQlE6$c)M&4 zlF0V1fY@7zOcmmKxUE@yKa)rqfBOX1^kNvb$z zQSY7_5Xfkrl9g2R^})C>!I>eJ6CYrdwb>{pXA)3kIbtojUaos2GWJzNGehVP=*e)E zyN;R;dtH9=iAc9C-g;i}6R%O4X569=8a5hsciP~)^%S$5{s ztQZg2i)uUL54ZpVlxUQF?oV;ofnVO$>_w^}ZCCfJgc_UA;r4r6>HR;PSEOYwy5omL zvhAmf@CAS7N@RF`CLHk>*m;nW`gjzVyaR9tXX^d*BPSPGTYEQu<5*kb+XEEJQy2iV zfQ_kwURiymS7(i#D6?X1E)` zeOm`Sv_6;&ZR7x>FY`DXFGAK9QQ(iVf3=$=a&905-!|}cRqF8qHHIfAE0PJusI}BI zR*W}5m)TJVXK|?#VRcu2vU3B9u{$#{bth#JSG|(+-xHg}!;O!)I9}5jcw z3DZ?u6Q4TUh}(9*OY=zbvyynw#Q9|0MKR@Kr8Hji?wCHbSEE@!SxR`1Qi?(E<>1A6 ziT{T&x6LHP-a{srdhFw*Z@2p(eI?}9DFKVYyEih&v#sB>Ckz2g!zmdw&n>K=DE#zZ zkmEWecg;B1ML`gL?wy%bJJ?U;DbtTx9(Pd4`|#G4m^) zu9v<+nhxN6-zYS9q!4G+7kNxUd=suppIwu zv_jA6V${KR)>>cnV(#B`G_nPHfCUaN5KdlcSQ4JVzVo+<#*21FO>4>w zrrQ6Ey&1o=QbB~+eJ}INcgq_l7xiAe6RVLnp%p_?oC!K`X`wC4o~LEx!0bS8&GKk6 ziB_%or|x&~c6)Pa<5f(XAmVB-wZ>{)I}k_UvHz|Gn#54-NOW)|xxYQZXTQsjEa7Z# z+VT7bT;h1aIy@_7&rsgpIMH_Z)6i~jr7n@qUZH5Zz)mc`n0o7%;rb>tE50(YJ+pUQ zcAY(NpJ^OjVsd2HHu?pk8P61JjWpAC=D3H_F|nJyvhd?MXnQWqG>^IeTpx&{ zCLy@kqnZy5d3+f~JJb3l;*|`@1t8fgvr8f^!-}?JD38|w4l1IG{}_|Xw#eSZaglhAjiZ-1c}Q6bR&MgL^MbQSyPn_DZ zz;f&OG_JhFW}=SZ$cbTVNglF>^XN&bI*kJZkjlhi8N*xX&LAvZ(k<8%fJbFR5R zx{bM{1}bwuu-4T?6TH#;2jx4C!9d4P&>}F7g_9RE72n8m%^<~*WmTV2^pJ?3eY&+N ze6HB+B@t_O40?3*fi&sF(qiYy^qWYS6qA8NBw}ad)L3$eTaj`6{9M{)4V&-)Qd&-DMtGZ8Av&;?zMv2nsfGU5=xVa}N!7L3| zQFM(qcu8K3enkbWz?(e1@`O;hPTsbsvb9weidDw4ihP+p5UqP{mA^-SMqapg*9)@qZ5?#likar-eW8PbCyDBO^J0i9YfNDg8X$Tl6sn0WdIZ<{ z)*9-Td!&F~?$4dz^O70-M~vk;=1$3u>0q2t)LK>9Ij1djEW9EtNwIx9TWS;7d;4cs z$c1;|JEuoYdmS`%W{QhLN7vNvW+$TF`cI?Gr@f%`D8f=B*eOAhCxvf(s%*jy6P?P- zc%O8tL9hT@SqxM1A~B;}JrR8LuB`?E4d5`PLn0Mp?u9Tcf`AxI6b&L_{xSO??hh4f8-~wE?VaIySbcJv1F6qS&(QE z)I)9D*(_ha8+a)m3Hysr6DW7T-Sz%Fq@%QPI^eyXCqazqu($2{iDML7Okn1Z=Rw$N z-Z!^xag6Uva#t|yGlboJ9mvadsS54pjESgR;t|^8KMlw4#p|&o=h1@2&f8;8xZ@RX zGgh3vgwF*+>6I0`;%L|47af=E4griVp3y>)p2CR@Rf)=d8=8iysXLSH-4}tW8UT6x=pThD5nUaAlYh^L8B%`t_-mRh-k4FI zu*AL^8B#QV_4uK8LVNxA14h6y#sYlE49O7{A(k+*;>UIk-K|vxiT^SL()e7Q=`3 zl*9|pBNnWz!f>nZh$)TB-$TI1A>jNrypz);%0s6JcI=Pb#YBX&yH#K|6GZ3aSJF(w zcjbh!zEhhUFBhE0o)t3zU9`|>c8gvR^NKEyJ=27PQhcIqRp+^N&X0?D19>L3Z$0Hd z45Moo#u;6!H%NSJ)==Am@9ODcZ0Il+Uytm@2`sq86;FnxG@=<$h#chrNj&) zW)~4{-|A3#@sK;u(CeAdQ;RC@#oof$>0s{i4G=?aTmklk;asX$q>f~B2WBo`1_5@t zOkg-Q|$R`DZlW^FCAR8Xi;cm`m;bX01TQchNmJ@>#W7$HtoppbiqA1fpf zDO6AvTp+P@AkO0;6o=f9&1-m}+v0GE`)Qm^R;1GzU`JNpThXjqnYOCC3{uG*i)3z7 zjAf+ilrbj~MrZvZBPf^w(bP5?Up^(K@}e&St*^BDS_>C2aG*zld_0<0fknjCV*&A&# zJ;)iHEA7)T>#~!5)W)s@w~p-^zHO@FMR7TEgqUQgN@tiJWHz9%n?ww#qrAt zoh3jxO5PY%!<%Ny60j#AGc)Bj1CEAq{)iL&v z(T;ma%z-yPJLLc;fv|{CDI5fu3~z-(rmgaI)0imEf@XcIfUymjFaN6 z`QO-k%b>V}aNToA2*HCxu;4DiJ;7aqI|P@(-9rd6$lweP!C~;hHNo8-2DjkugzVg{ zJ?Groy}MuT*4BQwQ#D_Dr0U<@)m`1s^FF__FiVK1KWFZNDe!7a7q=%peEw4g>oegO zq!ZHJEoB%xNE5_OuKn<_I)w!$ZG&4!vV^iDeYVA?zU7~F<4y`%tMWag2Fff^ zkva}?eulbdbBz?mEp!1f%;~LWro2x+1p_e77{GG6UBpc3jO>gp6_KGIq8zp^3ZKP z8?6zy+Gyz8^6n|I-Yp)s8_oRm0&>L}eic9*w(>N2qhpw$fr1&w>n*AJ*M=eav$I?H z>M<^!IMWd=3E{ikR>U=d%_|y#_D+SpJPxms2RNO$$_OQE!t~CJ9RC4~3Nohs`e3vy zSyyQ$2IAj!gwjWCFV+24*Xjxk{Xw$aaDf<4dt;``GqW+kfi zaY$sbhgRa9NUEzXqj^wKx~UUZ!>B*zWB)o`q_7M`C2rAURARU|HB-BC^+js8E0ihW zmA?X>y?qvc4VU62FPpZvhWY&`VyhCnceuQt{s9znZ@!&4$u4u`7^KQ5+cRa|cVU~2 z9_7pz-E9N)+&Ul_vH?|@1idVOV$&*(8;lz_$37WsMf|a7p!|$}cwxzPjuzh{Ha!QT~u&;5zctAnq7f1 z*}Ve1Pj5rFu5b9#;^eUn9+aKKr{8j&xSTA3SIQ^di0PfUsuDKl^gJmEgL^ks@GbF$ zHr|p))a-$u{Qu-XrOzDMpQ+H{ZNe;Dv%DA>lHh%YXg8C`6@~JxOjGRTM>;?R%?8vh zWKt<@-k@25Jw{81&4Af7V^LXsVq_U2e^m>1&EA`D{ORmc@T3=pEUzir0`;#+B+jNA z=P56v9p&a?cv}ir&8Dw?O533!6c?bWE!&8k)Et5=DIC6N%;?OJutKV1p1n}*-hcz%-o>`BW?Pq_sJSSe2DGCW-%s6F_g7A# zi7%pvrXgC&jY$8dFwVZI?E5w}upd`iR{uHnb4F0juY$&U z42KMw0a$xAdDq2}ay5H%gjDSGcbLOT1!_Swj@rk9NRvw7+9jz(8dq(l`=DGyrHorX zGXcHk^2FC_R%09eY~EvQ8MPQ;G$wAnCIzc_s~MLlN#9s)LC5x0oA`xf$t3t4%Y1%$ zQdw!CwkJgie*rBtu!@V5X-M7e<2EjDVd>IUTPDCtnD~bC#V}QBfyRn6hrqwI!*BPCsjl=oCrG&ql zE8(`rHSZ>mJiWi@mngeFSS#CjQIpSc8Qzg8gO)TKbj09?uQYcl9oJ-)neMpxN3fP0 zQ$m#*5ws*01QYvz&RpsH67N_k?TRvYS;pFv(_c+qHxQ;}Lae@j{a5kU@kqB&FhTvx zmJH%0g+)jxs;=(WPDre$eUvccH&b*Oep_8sEx0y!u^$G^s?^$F*4jqwBAq&4=A!6% zJ@KwD>0Lyszk=pzFs@MNX%X4{n}TYtyrlL5GM7>S=sr$@NuergmEO^sKuJkquClYD zYxiZAoqH4VxskbEFwXCHw6TC%6q1W+UKeEB_MhE=YgAJ z;7$0*S?9Z%A9qvFj_TSX8-E2q2Y%?E!vBvp-2Y!R1#&BqbSNkCvy_n6AKPCXY$yA1 zk{5$I6V3T>@eI|;1{CQa`2ykBC1?xXF6-|q^Eq>wKCpWSQ5HAlRiC|C;{{Ga`IB-k z^0moyi--{iii=@Jt#QQ=zu~*t&fs~JQui(q^Ch5)YiS*HS(IFxa`w!@V z?VFgJ?5Q?+hnz)=n?Mnvuis_q|K4Q_iogW*X}uj?PZnV*Lc+l;PZri^<8If9mVBCF zV8*<#JbeCQdQOCptlI??xzJ6+0Q#k2K*NU^fcFof3RtSSZ=7pygDCrkbM-wWibwW` z^{2s?3D*s)j?O{j$==U&&ZemC)g`J#8<}T)K^2YAa)>73aHX~>lQT=jg*o)*654m| zpF#7epH;4HO;fH5fezW1>&6N>Pl<{WgK=H+`ayenyQ@NJ> zpoZJTDcsV;G*I6zD3KI2r=_LsTz4y)U%fKj6T}qBj_a4GiR;5rL3J3l2(-W6^(A)Y$5FSEK%%m9H9e+rtFmZ}w$<ZtbiLcf+_C=^PUeb0C_dk+nRM71M& z^r@U0+8M!EQk^Tca8lit?|orf&WC`q(p*Q7K zLIlTJCZU^IC8ikDIdSf)r>LC}0~TmSF-u!XnU0ihc|l)?$;3cWAo(Nj6!F$DFhzSh zZC8htP)ABzJNm#J`YXl!>d&=pvJ?0D=`&@$^#1CUfN3;+6lgAy z&t4#pw8RE=R!hsC(G+!7rzE1F2eIZMKFwyOvtNTW6{+^ALVRl5JrVQF6#2IPY%5pe z?`82#o@iP279;9E0F$!;BYKvn=hXmuE6ra8Tg31zgXVPk@TAm9_uYp}>dv(fO@cZ> zzeLMQp=I=lc?9iv5;fR8bk|+FZx}bx7HgOZYo>Y74AV{dNVtmi!605NaE7?-`}TEmfDa{a&kF9BX}r50U4kAzgYy~xuT5+$_W8@II#3}Z&1M}a z3un!TJk4Zd6`QSpfF-@`)@tw{(~61pd0x{&-8r(CQeEeFr=uqlFCukdkN6k*+>B2} zMX486&)YYZJo7T(|A_edKQ?Zee+&O_D6dhrE4D@Kz@2x^vIDS;Dznh(M!8*s0lxD2 zISVq1F-iYG=K~oT>DfoqzT6MB_FPC8Jy+lKHIO$9g(`3X{b}Zy;=ejCF69zF;Jjw6 zqebQRLwz9}uF_=@2%9bD;eoBn;qTfKExPOIyZmCU4DIH1?dBiM=G(zTLjqX&4-Y!H zPf%~#zJ$!*(6%P16KeCl-#ev+L|Ijko@H@VJfw(beVsPnDI_(K7F9RW!koK9{z0Q9 z-&lXWZScTNncpE)wz)?BESkUtvGK(jd9N(i3SK^2R#k8fK=tEwIzm z8S#>Jaz!Ru|;ineoI1?M~S^2UfYse=qLoZ6PFBt?n@O$bHt zmoHv`l}7PP%VC^Kcjboz{!822r}sWSLF1JUU&)pTi#a4+rdZO6HDH$uaWPUe%papfnBEu}oN zC{a?zxt{$}9hy1c{Fg5tL0R@_0I~}i>*O14x2xy->yi(Kx_kpxW>#bKLacFC{{S&_ z+lQ`Y30@95j4@TP0ZSIQ&i#U0(Qj6sbup_=r&@aLcRnJ=m$|0ds$}opXh$g1Kt&E2 zPhB@}8nVMr^tZ1A?MK#FgaXIEJuSiC&NpkuAV+jfPuwM<^kI1&4^Qa^!8Td z^Gj7NSBuB0(M*bY#49NDkx=OAv!+JIGqlP@gw-!{xO1IyJ>t~gfbYbqOW)J*Jv3Kc z=x^^eP-w|WK%Y*{Vrn9y<+i~cmF!$I-^rQ{!pS_)@aN^59Uq%0#XOKLpSF2B&JlkA zjwr&kb)1*w-=Vz8n8lLc6POt;`JnzeH@1E*h5F~ZRa?OizWS}=3cvJz*%rgoKsB|+ zg||^#;MffcT{9`UG~3pL8#&h7ZHyrov91Y*6eHt;!P^%sWV_lewd57$DW|vbS_53j zE6lTQp})jAcWwCoAS6(wZByO{ojzfiNDGpn*TK!aWB57yI7$+DR_{TJxFu)RjlKfK zKMP|6WE+>vl8xJqxQ!NFMN_jm)_yNYTDh=26`zxMtw#{!dv3Z=9NrY zC1%$(UTp<5TX@v{!Yc1EIPX{NY24cgZ_12zcI|Q=w_DN_S$Em^TgOATgeY$J^;hj1 zch5v$VKB7xAaI4P3&&>AW43e=614wvISLqXh>K6`n$*n(b^ycZb#VZ?H9A33DSmeCp1vrx63j{e8mP41)F%SIr^wNmhj)>&W+1_b zG-s|qx-R#9oEtwfKYS-Enxo!CR5VcHk!bNMN{~{?h>R(A$;kOKm^9n@=B&0eQNt{` z0oQD@Be~fBaBnGZp&5W*Y`%|yaa-XvQ^^fC*dco0UCMp3+4PX?fcO8L2Q904!D+DpfC@W010ap=ix=yUY zWM!S`^!Z>UOVjIWM9-=zXf+26;xJNr(Lo+Uqt`^d)ZRVPa@+C z`k5pNV^rBvnVng2Zz_Autlxk>CF;EW^ku;`T-VX*qVH?Xg~%x6r4Mm$fV)JTS)g3o zbYRIMIN5jowGRiUNYMWv?$6gyJ8WHA5e8Y5#Qh;!v`-EAZXEP1%kw5BBJW|d5t zd0umPj#W;Gv*jE0hP~15J1Hl5F7%~v0QDn7lxuQ*t%S)6KN;?Ll>e51HYlzBeG`a? z$*Kx{8yl`3!uTUmL&q+E6^TGsAOA^HcP2FK*6+>qxo z4r=5`I9jh*&^5CuOdEh#-P8R6z~Pz zNL?AJ@30V*daZFzrY0cO;_FM5`=jFMGPt#9ndeFN?8%JEKLIvkrT+ld*HT=a zUk0EFxT{L=8!ka-4VEM8{(VM6c8m4IWn&p%%W%Ztq zc&3|$BY*c$#Bg24>nMpBsgG9-1w9*i{z3SL1wxyEK|f)`?(kEZY6_Ltq|lk%hcmdT zih9LXhjA!j$uWQF*bBZ9OZgY4i~QgseS5%-8J#%neE5cyT$Yf~puMeYc+Q&%lvK01 znuGhYEVP_Fc7Hkx zVUy(PZ>=DPg;d#$$~UN^CsKbzn6W^8A1&nL8|kB5zpEoBO5y$xFHgWVp3N#j&${G& z1FnF&_)~ECjJcan@?ten+N)q#1R7P0zL5eUm7M5;n+nq~fBF&!EzQh=dZshccqOo#&f+V7tNA7Kzd#!F>sWc$tzIZ}5L& z?ta{Pzb_S5m54xq)CO}D#}}#!8)U0Gr*F@ud@-jm7C|FI8b2kgHu>Z5h=dVV2+VRW z)^vRPE$TSVhRiIRC`iQDSh$$P@YOuq?|JlYXn2lM9IueWZYMRxKJ$V*fv0-R+AFDM z_D5R%(yKX5^#)j@>ZA)1S?oW6PWeYcd_8|4h3Gy$hU~O&IXUv z<5)Ophpd^W{cV&={8(!_;h}`a;b64!6u?qH@Yt;K2u2C(h8cDlI#=7Yykfp2i zJRxd}kTSD}*0D{8)cTy!4Bl)j%on3&K7jf2dxsLwd(%K#k?`C?A0}zNxiOCvM+FWt z7FUb@C^VXA%EJd(Q6lUQ5lSXuA~1pgn`y5Uz{`bRyF6#^a^R72p)E-_ipI|HQYqFB z@vGog)a_q@FG3*T%Qi`g)7?J(JDabjAPc-bxsc@rW!eg+t)A-gXo_0`?ls@)9Hso$ z`C$l&-@Jeaf0zyrj{QF0L1iOa)WcDzI~mI9$*r*6se!2bn~xgrnKQ@~H-9z(dvlb^ z(cCiC6FO{A>lWR)zojIF*T8mC27D={@_o6I!S+J2z!V{^?a7R@y<$f#q}0`4znb9f zX(&y)WbzA+jv(Q{az7C+C(GwHNA9Th;Oe2O+Q6x1b`CLh-S>?ii#bkImXLYZ5Ze(` zV#4SY-GoqPqhe5mI=ExGz;m-h_;(+r*c%y2J(|R18xGG5qaL#j`So;@yPbWKB>Wzh z(nC%$X-#4Qrjy;oRkQPE05*XAXHSJ|?xz7?*2D4%Y*8Aez>onbuUy4|dTnJuuOCI8_bK6|cx`tk8$)DaTDQ@-1b06guo)_~}p^$pxNd!2#8&suLJmiFz@ z5=@Ku*vJiv=2*ULF9oK+{nMrpjt8+pIxgykqO@1^E^7qe#Qt>0xRtME+x4<2JA^G+ zja*h*1ep{K%}%PzeEA39v$HlUZfa=M^6fLqno1_{Tv9Ki-TIMVTpneEBK=)QD)}CL zg)#F;(0V&F(_9jxT-DF)V_7!0@4j>-U1V7bFIcH8kMvPS`pJQ2> zqtw@KxVsXo5{L|g?67c(uO2pQUj5aPKo!dZ&kC5w=Sw|9^maUW#{hssefp zzR?s`?mv=kL_48s?wHz$b$$cayyVQE3&(3@| zUS8Wa)ad4Fh<0J;RQ|)wA&73Rg~pUxiJLILEZhy(kb1ZZKR~{0X80)PfK%=hNtCQC z6=7&9-)=CZqoBqUeqdEs6c7_L^4>E?++_?X01j&~Zrv(hdO}@`G;|LCdXETP&|Wbr zK}&7&w5)3U)nz%7j>qTa8)J^RxGB<1e^9B+O%Og9PqM6`7W$!6+oR+2P2S}+LqP#s z0HlSkw~h?Xs$;dJ!cAGVs>47zAgMDBtcD&Im319_>vQ>oe1$VbMiEfOu+ZEQ9Z6@J z*nuDhD^SF?@iYPJemL$qrr(A&4pufk+0`UL50qdWo6xSSX&lu0{{ZPfU#B@8gZLiyo&NDHuU(tKu7T^l{f@<-(Lh z?J>mIj+}e5;NW03j6=&NGnZxi{kkb}i6JP*hFwylXV3X$fV!BuQD zV|LzCcXugF8w)o{WOfM5b^8~%_ z!s?QSwvIW@F1Hx_r_XW0h2@6FCh79}m3A4~BZ?BfLhu{bb|2~9QB_Rgq67_3>zK9E z8oC?-kslKXXSGnPER+nu}8 z8ax@U0?5aE8n2V{H`HC7m$K8_PBCv7rqgxFsl>+a zS5i@kh>#1L!4SLrpllcs-SNmNQr)kDn!MGRMB-9sNL0D5gxggRD9EN0#MP|1H@`es z&1*M%O+i*AS$-bhs}Fnod+azt&}KPF;||mjHLop1C5e=>4dQ zdd+l!aLkk;#R)IpO@gtWW<_i?%_L_7%gLymgv2iu{GT`NcRzTNcl5lUnqn7pH!7dq zQ7zgm+n(0Y;;R8nc|vP)5@pN&4MGOkDlQK?E_S27#jPE|L@<6E z*VxKSc33X#18Ic+52YC8e*m75v9Q)(>;+vF5|E_@J>=pH))jas)+)_hT&uekCAE=M zLEog7EvRwZ;es`bl^{;WKOTcRV<>4qk48Hr2l~^?%~)vh29vt|QZ80gLFlzfVjP1Z z4OPD;;pmYD^Xva2Cfmu*eyc~g{R`Q@oxJzU{_p`%lTx<`4nWgp(f^n)&k0eq@$uZGU4wCrAK3fh=VHm_UgZ3Q2~6qBr5^@iR6U~$3<1$wL?<-QjlDP2JC&r>c(tC1 zjqeGZ6aO1qfrWTV*ZA}wpr#-owFzoWeD8G}P_=)?JhZq6y}Op& z9WMg4+brNdMf!U}|0;aDX8t!eeQ$XEt9=|KTJjk=HT>fAu3BEBq~Gkt@U@s%k@(4)pP1?Dm3Lw{9Q{|0joDw`nS6Qt z5d66i;nFD03u`HI6paf=;E7&akp6A33b$~-jBZ}~nNXO2z(8jFg}H#!A(sDrFw#Ig zRkj+&@{=?0;I^I5dFDS>T|=q3Tdot<kMQC>to_3f0*++HX-npMw(qI3mQ{uTq}hl}sJPe2hzz%xj(x<4a&qsH z&WI(@O#8n!=KnO@5Of5?KecAa%XZy#T16U2U3;)X*rg1*JZr}^N)*cz2#Jd{r?$#E zySKsDryPK+{X>k@0s4d#c1(T>y+?RqhKR`1!**pPDWi+i^K^v_rB=Zmt~t|i&HGtc z997pLSyoP{TYL2gto>k?$HpywOjM#~ZLqEL7kl_!Ci!!mxZQq!#B-O0Nj~nnrk^ zAiTHOAL%r|^c~3Oo8R@*vKjw=EG(F-79y{5H62OOT&YOrOcWu8^cwbrR8lf^QMZ2` zM5`55Jnfm)4OWmi(Q`||cDGznzGB54BU!6&(ab{PI+z8M!OLc$&@;7&0t58st(fp0 zHzca0fi7pJ-5lj#KjRGrqlERt9Lf(Ryt^^O*-G}vmSIjXL*x7 zzRdR{V#fzhm1_@~m^Si|XH>Ifg|v74Umlg{RzE0F% zvuM;CR|?q^+_66*Gg4wDf2DlI-WDa?c32)|r)lSONIw`W-m<}|hu!y{G`hP&7{tbd zL6lh$*7_EMD1~{TR{GB8_BlZC?+NgOTHcwChy=Xab^mGr`AjRjNXVL|V zdH;2FSj|X6cRBu@=FCehpZ|L|thon&p_Fh1ZS}yp+n4;uZ|<5~PBvIN%y0T0Sdrk+ z&d;U~e>)t=N@~CA9XFP@CdEA^<*v<+MR=y@@Uh^pZh>Ed4xbE~Dr~o4y`Oa7*n9d< ztuaqfu3yRQdYUwpXlK2W=^t+8ArSS`jN9*aFFh5C6fria%6??^F};2{tr(7q0Rua$ z+XhHWiDVSTo0ip{{sH{6wP^mLBFrYC7p97g1uuU&04=)x@Ns=QahiPh?LXT+w?U1i zj9ZOtok#SMACm1E;|gX@I8P6i7=#=YN9Xq%=5_J#+6sCeXHDhu#D3M5GvtglTx;fi zmrr}94EhV0|x12 ztHh1PMPKK7?8px*^$G~Xq|M={oeGNrd43lyTms7-^zS;<`0blnebGY#|Ug+oQtkNGk7JAyD!zp%Vkl9 zKrC(Wtm>{}kzLP19vi;ja_TRZ*^u05UT(gV7VGHbkzBhxg&r(l6g4k2+;_w*j4QiL zifN#q1I!1~xbGm1`&)bkqAa*){6-R9>scuFR@^G+KdM=n=|Q2ORf0>8RhkDWD>c=daboMuPV-mwIi;b1jO#EdqF$2qdHj^XE{nf?8gsBn;+)Wg1CLQt#YqdUYD7t(!n}fU?-*Y5nXUmqIPX7 zH|S5*f?t>CEB%A|=*pWT!9!kp#5w3c)cCYH{=GKf%X7G*BOBsLTB!gTwX7 ztJnD1ON*kJPrg;wKM2Z;ISNYsTd#P;u~)}P@r1rlgrr=t^#@$(gs6N+M_0^5(&_Ad zt&vz!De3zw{+wE#Y-;$Lra)%6Hme{-NA_(*-)wUtW-L|fK-97aw4s4p>V56ts?b4~ zp8ci1`^2{desUXlPqbR#E8d0n@tEbW^uAhNQdFXAp`bqZ^w~?-neFYWVhGX9?&0ro zw5E^7m+h~vO6mufdVk~0N8nyH2Y>1dXzsa0e>U0nU_?hA($|;M#nVke7T9bWN#FMp zF3xFrP1IOSCrfT6%xX~&`bd)}v?o$4?DT6i?_FCY{rvG#cIqo1Qy1u?h2kJ9i_C6z zx&cZfHZgV+hM_j;>XPL?G*bpe2JAqRs=n#l+Pca(Ueiz+l~_^rj{GONk864U1W@|2 zRsy+*Ray>L+moB=fV#p_%Pge4{22dFqVw6Q!Eobz6eoA7M_i#p*R4~bsNb9IA2QdE ziaZJ$6p8x!s}f-xIy~B}R6cA5N#$Q9Jf*wdI2dsAYLE-jNuohPP^UOxvT;FyN6ZNQ zioa1@Af)Uj&`Qt3fP%_y{rhW4|1;RI0QYDkndpd=LUK9<5oZ|xL2Z=f8C%6mlu&r` zhv9@AKNw@cKpy#iTbs0vVtMV99Gx}?FxJ*Rf+vy+D=;I2c$FL(&Vu8&N_Rpv zv&j6DW;iy{M(wWg)-;0mCH2d+e^EDl2^CmF$I(7cdvT67ujon@7Uhm&}KZ*GTpTJ&3yK!|UQ z8km7V^lNwQ&2Tu(vC^PpG>tuhQc8+x=vtj$L>srCEF22fI=?k)w6Nr$;!Qj{U$v-x z%?EC&h*yh6b^Y1vprKjli);Gon~}>a< zTZhzC2jK^lSM*Zj)!s$UnL$R$R+dW`pGv4Qd8>I_a2+pO@}x1|@D^+3?u=vT?^Gs` zfZwOhm(MCqV|pZEjh$J;CV+!VZS1uM|#$}d6pJ9hIV3m!UYcnpii%epz#d9$NvDl!sn zVsh@5YN!i|2JkzA?}%np{sD$Rw)Y4YtwB-K-|#y^^i;;1Sh98^_vCNW8-_xGHqOm2_Dr zz~5nV%556u)KwVnu5PlUh{Uo}@8#L@%2M#JBR@0C@C7QSRUU{(3Nye?@@M`JUo+HE zeM{F|D)hVRPeYnNi;k9WVY>+p3-lTL0*m)e;rjanXm7&Fl(6MOFi9c`3tItKg24B~W3bPGb&z7;}*Gpw~V ztv~KKwabJxoV7j#wF+>T9j76&iX*>6KF-c~{b6;46hk@72mHyM@V-$B!dju#K$U_! zz2(cBkpu{FIWYr)7H%+m-FU%nKAdl7+C{hYfIFDnW2&b$7%M8^2@ZO%4nS`wW}iO5 zKR>D{oUx@d$=x2q|CD{*b5(X>Yq3#R1iy*gA(JnfhJY!!Es5d-`sn=@=p#eb7J+A2D8yY-R5vH9Zr5HJPR3EY*% zEee7(WNm%H{HIbEt+gtNqw0wC2V^jvxi(gQ@|20~m3x0)vRnyBZ>m;&?>rRfNg19G zg+!PA_+;??>)XM%A-@QNbrqL0|Df{E59Efls#U_$o8M!-?1vMSHBe|$~8GJcyGQWk!F^=T{<(_sIJ#4f_ zfd^}u!1%>Pz5L%1tXy>sb(pxYH!`BQDsjqRMyc}0E90jGWwrmvvCfquI1Aa~>`@xO z$;gotWtCjt?H?N$37|pC5~gIl`65JePN|$N`bwOx^7G-(lMk|{uQoL1+PpakY)SY< z-*c%D)@DeEH(b(HlA$XusM*n=OEyH0Gy`+8E`r`dLf;p?&jk`^|L*wxE6T#0WrMbm z-2scD_@vt9@3r1>>2&E4^Ot-&!=+)bP&Cw7QM4GdCCczB5_m!`1Ih5b*x@xsmW;MG z0&4+9aW_} zJrhKhPx+ae> zKYiGMlvjMWnU-PWs; zE%zO@DbNcNLyf?H$J>i3jI>Cc#^P}$7t3? z({F0y^YU3bWqjx)LecNlL`I^Oz8oPf1r64@SyO&CXrZF@yjjK4SI$igG>{J@mJNlO zanB=GwPdkXtG+6Q2hpd&#VSYyK_~aHsHFIz@B3u3!|AEobJI4n^wthKltV@3aP`pu zP-p-bA?g+p%bg<&^|S}}%_SLa-(Ls&rcgC<&)MqYl!=(E6QoubWY-(Q10Us$e%j=l zc)s7^6z*iV9(R@31GIzf98!sL35IIID!c(noE?{D!lHuLjyM*(C=HMqwXm>RJ-KK= ztWG0|a%t#+E=yZf2Gcuj6(N9Bod)RL*53gJC)4V{fW1?FyXhXfQDS&QC)(# zFWU@T^-AIo@z8(IsxZ-g#G``Y=y|xTUhBFZw+(QL2>T@@Yx2cnT4fntDK+0`Px#Hu zPAkymcwBZ5wATYXks?xE&^d;gR(x$8AYFFbzgrW`{fVf7wuQjAS&vz2i`A70|h92#q(UtrxcCrQEH))Tf~b9-^^$ zrnsQn)zPsP%GZ?$E1|wgG>hpKGU=81V?r9Yi`z+wzmX(5#&NB%khpIZO~*00S`dUG z>u-$CH1xetA0=UUm*Q&YV+@Z9d}~-DwS7MoJY04h7)S0p5Zic+NjwNRH;@w>zm8;8 zzVU1LFK0h-S@mGlH?21BZ_Op{-v)GT0)eikm#z=nhb)fow&V74D>(n0RK8ka0F@rI z0T0b``lmgFm+vd(hO*7*K5h%d|TwWZLhb5RDwJT34Jot!6e zR6M?gj~mom#6xRXqw3Hn$!?igV{@?IN=>rhQf<#nq$U%uzH`&lG~jr2dW5QvyCMwx zVl8(G3JI` z=@)y|@7fbs+lhdbu$P9fe@grrxFd&~6o_-usT`c}$`Ou?*bN*SNk0E=TcXH+I1pQRd~=@v-Z9UIT@?UuUHvb4rrZV zEco@ylE}aU-wn9*+pIuN2k=fJx>N!4Od4WZLN)vb`HLc&*;>lbtT1& z@@w~6XNV&jo@NkLr=*M3pG0%;N7;JY%FIWSWbSan1weB8Y3QHrzzK}Th5NXq$eY@{ zO;qV3?pzYD>3m$f-D`UHg`ocblvjxVAL0VyUS8&vS9IAJ3=^F}tjWF3F94A~%~Vue zK6sw#b6pOC^$Zs*?g@#O(IgJ(^|Kpnt9a0%>GZpp_h|u@_ZwxX!y1sTR-leU$oLt{ zyED;o){h1|=X&;V45C7y=)}0v1`ya(AA*Uf;gzIMIZ>X*a8th<`}SCibaUcjWWvnB!5w?a7t#q7Zv!YY$M!`41d+8 z<2Ny$frGTnPxz-hr2ZuX2Q+qd^5xV|@{2~iKm(Nq*O`jWu1dtdOu>dkJi^0ra@|z3 z>e%<&@$MH{F_!H7YuqlIHp&zM#zwK*4~aG!Os@WqLkv9|(tTljJmpbK?@|~he@L`* z#T+p|PsK)|f5-3Sg|E(IAxF22QN=4Xf8YamToFP{+9N*EY)qlmOz#eaH6f#%6<3|= z?e=pn?*&bGWfy}XyL0-LjcS^44xO6D!pLnGhWK>hA}6DHRY`Hu*z}D@l*58jap?|l zrsSDIn8JHe+gXh-T-Ouq?*M!8WWnM!gASe??Cy0K`qj3R^#uVto=YIAhOXiTI378G zDrC}tJ!ocGjdCuSpQ6Fpn?c7^O*h_xPv7#%Mt8$7Z1(sq`p>?`ecImb!X~pwhG*~e zoGoqPYpk>J*)U-YZ9ScGyaQR1Wm*i+^d_Oq1H6~Yt{;5gabw0h!q&4M`L#l4GlKX3 z{C@2ah-a`L^9Zy<(KYmHV!zQW?y?p+0|FB#_ml5}!$2pE>)jRDz#mK7ZkLWjH|55x zT-o?;TWa%gje&u;CEBZuC@2Y6=o3KSSf`&fkJKBxoaE%bWen`n^`Q z9b;j3t75(GCf)q-cu&uUy6Wn{-=0s&&d&bJ^Ipacy2N^8Rbt*2O-ooo5;z%hf@+{FW?WW>MfUsxS>&ZityftaZ0?%$q{7{_zpWZeGZ8 zD&F*-QS@sdMkZQ0XWYjoyM@=Wt-zW(Po#NZ1M%3`O2TxM2abLV!IL?}6;5C7J9hl0 z*TVfQ9L1-xN{!%Xe!8}2*=qL6z%|YUmGKcAtD;lOMcD$(^e>Mg=PV``1$@?0bEqTO zI@a%{#x7rNc-m5w2wqTEH#XLMf(i%x6dE5Z6KHWtKV~mzp#Ev=wp!fFl779KXTGh+ z{&KQwcw?oWF^~;x7Car4C<3QD?kT(@FR1Qj+QuM=I=ZtU0>@eK9{^XW<>KQp{hyZ$ zWtZmF(+eGW%-bB3xcKQFy~py1uX&J`W)C@>>$@ubqerk~KQJK$6rx1K4>H!vRi64x zE-eJFhDSCNW<6DDxszky>D79;k25q5d>+#6a_+mfoOus&rfLzSvz@CJm5`;l0)OZ3 zXM(*)+Q8eT;G31@FUW_~%WtUv@pe!Fl_JzDwvqxvt`#y`Mc(-+wy+g6nq%iO)fkHu!7= zAZfQSs?q!rZj6OU&-|XIIfUhNPWbR;w&R1;<<<77Xwcke?&Hlcac!$Nc?PZBCq>$j7hmLlU|C(*- zL%i=|w}HpmuRm_r|H0`j+4;74@ce_z%Zm92cdkJBT&~!EVSJUT`qGwtk+kc;_D1k5 zWB3QR60r9=nNT@2>h^r6`w!0Zt*AI73vWuDLyHfAhv<}ZB^Lkj99k?gKOGPhno0Zkn(~a&B7kb1fk^Z@Qo?yd~Bk+{#K;AZmFEc5hyJ z>KD1^dCVpffw8IW%upT_;P~9oe-%|~l2A>@5?q-d&8S!;C+#jbha=bzUz*8b_Ta#j z#lESbA0=|xfJ^-KW6TU;HcmXDl3>@A^ToPz&G54R*CbqK222HBS(0$2X?`ZK+D)6P ziQ&ksmcY66<59(^Ydp{9#B4^uWQ(91$iZDq9ip+K6oD3;Ty4TUr&M5yWAvu=76HS1 ze82($axy->Z!3xbl}|YIP!f-KIanDw_&DUos0q7_9xfR&*f}^Ap|d<%mEx}Tk7yzg z77nyoBu#kV3Fw@+wrJ9>%@Q$1%z!e=V5diz%9<`0H@*qK8q$2MWf4b@6O{7Tms)#o z&~tlyWNnz@f@IP-B&Cri;+ zxYUge;C`CVb>||c;&GSSEE!4ZUAk?$b0uPOs!zOpvaR?@Z>FZkFQqCQ;oKn@JLurc z^0{DcyZrsIBtfMrvZktp?`sVqPDdn>&hjswmZQ9e2CD?q&_!#VozX|WK#s;X^T!RS zF7`=TZm&OXA2%H|7GB<8*N(N-8b|tC8nm>nimnIWB%FB2`=&MB^XSOjFc5zOhq0@?`8QgWjCcwYECDw1gjNa=w=A8Yd`vkjyycI>>WxcZFV6KdN74` zB%QzdQtbZG=T4x+uI@=GIqcN(g+9762aL5Oo_sVdR)$T?t1c)jS`UlsXq5+Q8Oxq} zip)GdzDdga?|p_;Y)8+Wx=Y{rr5(QbDDHOw<=&33NA-vQ1LPcYgRL znq-6{ES7zGgl7Q?zGrKsHdD`aV>$bPas?}~75GK1rAM(N>zI9aXl9B<_;XXsH!7nw zc+)RCW)Y^dj@_P~3-6Ocn^d;1S`7`IpCe@r{6L_ALGG{@bbSSTdUtBWb~emjGlAzy zKEe@&WJ7b&L+f{T{f40cbu69SS-eOP2LE6}Kpv{48D1UpVnBW39Y>qr`1b8H(E!9Y z8Ah^7MXeENj+PI_8A%L4%`!{TO&)oWcdPau+mKx6H4ASQwxr@CW@X^&(*B(_KZGsN zg3T-$lTuP^Fd~DdsP(3O9n&ePu3)>#rr~;exuzxb#(*1b;dSGfyk%T2rmleYYbK z%&n0)Ib1 zQ3PrRyJQ3uS~=jhBqbAYnwr(o$ElGN5{eG(M#0nD>!wFwd`k@^{>~m|WJOROZv`Yo zmDdm4QVkyU>uwHrL{-GQ;l6VqH}pENP2JJrr4H@?c-ZfiI`^gS2f7GGulIO^n%x(@ zX$SIos=#BJzQ+zeh?-oEA;UNTK%@O;Up8ZYOryA*e%UdYP==-0F0W-Dk zY%=w2iWa4`xIyB0$8KR~Wn9gyxaM=r_d+d1W&07}a}}QU@Wl)klam2Gp?cC7^(j-3 z%n+$K^T_W$et$?tM?tK)ei9)$u$=C9E#soJ-lGn#*Of<2F1B7Tww+rdH-ybY6@a-d zD<=?k8baem*Nur}X*B(7tTU88pcXexKyUzK!bSYI%H+bU zHOKO|F@uTi+4Ht8`JiB|2J!d22ip1MdK`_Sg(GVoVO$iR>`0TQCt>Z}cZFv3%}(+9 z23g`Y<$GhG6};ya*l2sm$~gEI7#~Gz~n; z-ZtAmHq#RX&YXmC^v4^7CrurqGm9lv^sN)gq2-5-cnt!MyhHl}XGkl~YG6!lA^9c? zBrC4Hb{{QOd5xA2S`}g8UxJK}B;v@S8cpX~=X1lQ#nK`2)JPV=D;^)_yRG+23`OZN zI4B7p7T#@|o;>4kwhGuPMGBAFQK`h^D6V|#DGk>a|Dw)B{VDy7PKm_jcl}u)eAr*| zZz?~QBG%mileQFs81IvbnmU{)tP-v=m!^{{D}~q_)I7opN72Dv<0=a$0jT z?^+xD+hEZl$9|2q%~-=t#6LtSjza1Ffai#s>R}usRI0w*TYj=v=YXXm8e#a$&*HCu zI%O$tp1#fDvNx%#eYsvzgSlPsZPf~eRTIIPuYAkbO~YL<{e;O!y%TxF@5>y$j_+K% zey2#(FGnyf^#6*%RV(`YcW!l7JGsF%y?CF5#^b)k$_N}`oo710iE&@O0s+Kze4<@D zw6RH+r=<&D{j>aYSR}zO9!}^!I=RDslxW)$V&Rfg zK}d5*G+3XPLb25%jafh{Ni{njhueT(_;D(4FAd8Rc7ITOgCv*x{vd-`vGM*C) z|7&dG`_n$i8dM5vk$#uGWrD@V-jQBM-Uf2}!T+|n(R!?%bP0byGa;u$gg8QMN&ceb z*7p@)`laZP=yIIObL1Cym3dO&V(LX6->cNWi6sGAiHl-o1j-~-b1Qkabg8`=-MPE9+&1vIsDnVIOTm;_2 zL`Hj)3oO=-15-*HbR(dSv^8kE_vBPdgkZVbI8z!aeyEYkw1j}}kK4tC$MvC6nd+K+ z`dGUlh7xSc6oZRo8iG-?LDBs@>AherRl6_A#C!2N1-#K0%^iGGBN{4q{X#Zo*P9^Y zW5LRA%hpiXr__cHzm+jE1@{&AELk%cbW)+z~hzUFXN{VoR@l9+%nMg1Hb9 zHkLHv*@ny90U-rdDL`x15n~@GGi>{`Asll=h}c&-&eCcyZa5BP-318Wms5&o&BoDw zNAf~i@snptSTsIDyRL=VmRB&HbmyE^XW#7zd$nzAovF6_aD--^F58-je<;{2X|#ib zL9T%sI{faE3f$t_H-0yMX9}+tm*gKs7#nzS4cJU_`Emip>1d!0;}E*{n$OIzNx=KP z5D9Z}YC=WWv$P({`RF$49+#U?aaGb>*JZE>Ei8*MVV|Al`BGIhmfy>qgP3}6D3_nv z5J^Ebn@<ncHEsv>?QEfb+<@ z32}fJyCT{-`jqNYl~h$EV?;Vjs&Cb7DH#iul^&n%i1O<_1OAi?d%l@2}CPD0Z{;<&KI*XEk6cL{-&%r~Q-P&xLibM@KEqK+;&4K zQ#%&%^$E3hCS1e z6U_vLbTnpDw|)>1ti1KahONs2@VkHOi1St%keh$9w;B-V;6vAhXQUe#6Hdqzs?<_wg67p9&@t|4V$;4sQjNmE?blSal{?##V45n4y5V8wafN22{&F7X;TrL?LxIeBfi~g-WgolJ zzK?v69N4?Q7YoufvMO|^hVJVOz_G&IIXn82vBjGkp7fy7RlP?TNHu?m`t;50J~*{3 zj2*3J<~B9vrq}&-*11w_dq`(KfXV6&H>8j7xuIiIaRgk>Jkw?oS>M7$=P2 z6E2N9(3*3xLV$XR$4gSIe9xt2rEIT#JUpbKC29grMzGd2kQj9ejmlh?|a z?!qhw>`;i)EEV(BIa2EQV|q& z{bvWkW3ym%{Ofn3#B%NmcLCxk^zMc|od)a{=R^A61(S(H@=qy&LbEAf+gY+21Vcjx z=UVaueSFL!v>!LToDk11{w5q^$-i_A_TWyUKgdzx^c^K2?l+|{6KySzUQ|;H| zpU?4UU-|3|$6@x0QRP>|jl2p&>`oL?UPO=KK12 z)A}zD>>c)K;hgoik?Z_vSyQ(}^|*kZruF4AH}!coxsuPcJQ{+yW=Gq{DVTN+ScoS5 zihsIE9)C{r3lgJ;!=1uEs4&(kh6Y5|L=_R~0h8K7)&dtMp!+r_nm5UHu1O(YjBrX~fP( zoT)npRtw*_;Cw8tHShPS6H?qd#`>9}L6lVKT^2{~wn3;klnQjN|ZMOMbpl{G3#F|G|MF}vEFC~i=Cen-rFY(KwSgY3r#R}HKyq=^GA*cwb{SB})K zsc{g-@!2F+Q$F)O#+!=#Z)~*@EOBd_@R3k#g(Q)<$w;P z+NoT0HP*(fSDD|M+FYN{NCD-F zUjEW z-uDM(HomRMyK&dfw`&|?!*5hgP{qB(hfSwf4JlQDxo2wB{}wKnG2_S=JMiAXFLClM z(tnQr5xyt59z^v@M7i@t>MGNr2ip%l<}!`OW4!S{Zwg0vPyalKvIq8D81_Feawp+% zwGS^g(c2mI+aHyD*Kjhc@ffb`eR1^P+{#YwzD)ZAlo>L=O0xQoJ479}X&`k}bb3qA z37SE5aq97w)vSik^tjfWlT$Am<$qLDy_;86K->E*{VFfNmjq4B9}7sUz8(XW>*r$V zF*hB*Pi>mN@>R7I1ibub*tf(j$dWY1wIcr`$bXv>?jYk1Q2BqBQxWO^QqR)d|G#VW zKd<`#dq<97TkA2@iFGhRc`#I>TA8mt`4$-rTq>PsoHJG_l)dj%dz@qRRDkg1_|}T~ zY16z)bQG`ONVK~9{j{?AaIu;J%n!X_d!D>uXX}i1+oP*v$I zss9yN7QquC)V3BQoxHCkmZNd_lMUBW;m{{1@;SgyoFl57@d{@oRu)Ci?4Ik!B$z%M zC3-28%hLci^i$THWh7e#q0|kmN+g$rQMGQFo9Pg|xfncXr5q45Yn)Ahj{ueL}QWByJ`hW)a!6z(l2TSA_*iLL=?v3(!F&~pJD22j$G$$ zI+bbvrk;w|p68VYT1kI!u8Yqqe~xO{(+w(8sAlL9X&Z#zA6XcS(M{NCJ(W zC#P*NFgG=yUs7#@seQ4 zm}&P%z3OW1eKerE&0+Y75ciBRIiKIgi+aSLuOa{46Rij(2SE z)3TQXBw#N9Dm%p{*iukeMRZfy4q3*8XN;k$7c*jOjGSTU@;gCY6nmaL>3prOTY7Q7 z1pb4Q6`}kGw~;9Jppz20)ww5_{p2AAW6g~ctI4`?P`;IS2sgtF1q)HP{iyMdS681J zc0WYZ>r z$_Z|Klag^La*=B>3>w^+cP%GdnRJ*0#WY)!zaX!%JDJ3oCu!`TvE;Mqla%ongbIF~ ztnd?u{Vu2V9Jp;SgDNg;znMT5mtCFGhnN!ccsCibVkF*2aSXrl34lv()u@KzNaSHu zkpb@xXp#kBxIG*D860Rc1iE3S0$3jLGp57^ewog!2S(BwhC7bm9}KdNgHPKa!%F;A zkHi`6(yXML2YX=i@9qrDQ%ZUmACMy<{Vc}Gyq0F41^br2fPpB#4)@?HinCaB4Alfi z(4~i}c_|QfJduw94FUsGw$KWZ?);n1SkII8+RG0DntHElsU&j)VoB<%HNn@ivVPTP zg3~ehDjL~S|KO-HaSu=>9+5bW5;Ptf821w76NH_Ak|!{a;jN9?x{NvXA@BImlovw! zJRbp8k+jmsGP%!a$UmS!ilOB<5dMu$lWn=6g1FaadNx;?&i3MJqSc|XyTVFVlK!Bu zOzZ!hVz&og_FDXNSzbw7y&7Q8f$ddBxWJ`$Set$dD`vC9DM-_!6Tq0EUdyYXL+fTK zzi?qyJ$CZNXr2fOZ)!v5lt4CET3LfbH$4r;ItIDJDYhoX>31!ORnyy=pLZWSHl}Wa zvL6>izTaIGc#u~}^#T_9FHFpibi@3o2g7-%>%uCXL7p+O~sFCN#41wo=?fH>B z&a&zhqAzo_kn|ShC)CMAwQlbQx594pc-m&O;~*T6-EC z#i>`g93?4_cQmV0KGI0zZq4V4BT8-`mj)%N;YHh?pX-y>A_y6m*Z|YIcEe6=i_F$4 zoO7~RqE8$LwW!CTxwLY8H*R+CqmQn6Hnn_&bKQ&TD+tU!*eH^}n-4kiQRW2dW;8O0 z`;mG9d_{BEk~{M1gUsE-P%QOTxeD?4t+&$xnJ@xqvoh}_@_**?j7-g3z*1N$g>QdW z)`E|61B@C(kkiEcoUh5`$*ImYrDSqxe88fmHcDy@8!Vy{%NDEO=bVk&eMb)e!HMz+ zRP*GnXll@3GaM1YGp}=z#lp6O&5ZX!?yMmdt?nS%22O@#gstfvN_#^{cEgR+14HZ{Rrh|In zXWo<;qBEj-3A@fMqbZwi3_pcemJ2$`!1fWsDy+Yi0J=4>npio*66nVLFt7vzlMFLp zD2w7IjLeH4ta;`J&8Bc?nD-PgmgNLYmt4fz3zntr5{6>C8X($_xt|+eKAp}z87=v$ z&7OW|70KK78P378@{m$LOIhTY_oXcc0})+Tzq$G;uGFynJwYgSN${M1Ylm!o6OG>J zQ6a$7^Mnrkm8>n!Qr3w7usOI+SnB`?UGjoL0 zZ!9I!;y~6!J>zi5l$&8kUc?6HX-nKcE`J!G>NA;nkjGAV#{U2UC)f`(lkF=2e1mg) zgPGQ=E_@}H6+m5h#kCukJGtn6ST==gQDw<@I?jW&7C~b0S0iL7dt$N;J+a_qn-`^O zGZg)aWRINFt0D*8oo0m6vwuOoHx4So6bZYjm$y#4_%msO1u}G<JK3=0L zC=$B!u_2dkHzE|>DTyjtKU4AOa&fycyS%s;qTi83yCc7C*E~4f5Eumal<$Wip8ZA3 zY&>! z_5N5BO=e2a$I4k&ZurVRwx~-Yx5uV75Q06YaFt{j*Ry?Tr8OLawv~!-KLKvt>GoM9oDvFB(SQ<6?QKj4(a-Z3IM$(cCdwdu(<1M5lRO_k+sJc^~Yx=Kp zdR>NokX$;-Y6hX4ZmS%c8Msv$xN_vo%&AIT5SrS5syf#=(3dvoWsv!WSua}uODfdr z8!2Zpy%t$IyksGGY5z>u*(P6=GQ-wpkl~ZFtc+<)1^LYD)k0Ckkw@qVvi{dtpxuiB zfH_i~g!5pF5Q`TmQ?%HTw@{Nc-L3aHRt^1=%ugU8q~m)2RENaFohM8Fw7+KOVU&d zAQUn7`tFEB3s>=5UXnrSV~jP~Ut#zLD^KzI)lZ~?c>QBibEczx484UR0%)KeAWGn0 zj@pXD>3*f|{2U9z&xJ9c^`Om57eM>oBHxbp0x=v)faFWfE!j*#wq7z6)~AMv2DX3> zYXZ3ntDgkgO{x;5rI#H+%0Dr}z6!>&>5+(hMd!fMRowCZwOHwuX)l%F`c*?dNk_IH zynl#79xa0ul+5>AOOZaB=1V0hL4}GtP~bw-SS3H48Uusv{z#wisHVC`KGk5g47-{c zZLTL-GHM_Hqx5Q25Xfj3=fyi(twOFW zy(D6a2j$hPUiQ=bGm3o8^Vv!&zWTyoO$3V$-jx@TlgSt6-ZF z6))pT0gxmAE<~uiZCzN2QCOXz$fA~IO~r~(HDgXgNJ?n+Zy zP$MwPHM*_@o~mFac|bQb7`EFeMmpN#ySo;%)>IZ_0 znR~R{(ZyOvK>TWA8C;#Cj7{fgoTCqv;eo9Tb2U|bwCMWP zYUS2wr1B==<40d=pB=oMIqks;yM&w}F0+=Ju95c=dSD^BooH-(SrNmnEn1C4V@zie zuAZE}bAbcB(M#fy;Ks3>>Gj+LLGtiU#6z8meUyOm9)|JbI^Ng zLw&vOBCw)Yn!;dJATFU3ix*cjGu_26xkcd+>C2x8NY-4G1O;cUjR_UL+W6J)1i=+! z*0Bg=4$e~@ef){;fo;3!WYvZ_tCey#wr-8jNws!0a2EIa=EO4CV(QrBZF0skqY;lePwpIhJ}h81h!784@gUs zBy6L>c2efz?GwMcqfw&R3gdJSeMs^xao9e1NoPzcf}6z|madFcr&`Lbh~j1vA(SXw zIn8Lbk#~Hwt?jOzP4~x56^*hz81IoFKtqDF%fIZf1)R2e)I_SGlpO`FL+n)Pk21G8 z1mROz^?~!UbX4_=jq~#sTTO2g5gMoh1rU?vxb1ppGVMtN8CnA_u=S#zybNO6hg^a{ zbq`76ov=UquwUaxX=Jezv z05qkJgxB@$6yR*r{aTjafg!UYDeF^&J3w^Msz;@~_v-y*821>PAg<5R$Dr6~T;wm- z)raCpmU0flu&Y@}|}OA5R$JA=*MIzelB1NZOA4h;jIv1M7~A?u6`G_AG(& zKvMgXfG*4w^JM{J+)xKg3$HBCuzRqGMxuqzOI?^MdoWm==`Tziox;_WkZYV8g9Eo2 zLA-rp7&?YN*JRp&4+fQC4&zu`g))gvROei%Kt*@c3dwpuw;3)s}3^w zGxGIGqQhITa3I~uik|6v6qax@U#ai|jyVDJd%i2kXD{-ZhF()HjgS%c@;!16 zx2nCZJSc&(%fl{VAm<=T7nXO7)7-H2@SaS`fVASfKLWeBBFg181Ny9rk^!WPjw$SX zfNvJjQI}4oMXD})LLrRmn>o2hXlW(|x1AIe{n@x_I^r{~4uptpPP>FPvqSrX=2`>7 z?*bE$FSp~n^F%CEcN*I`*$vcxQNx8&mJC8!IF-#brUzP6Q@O+09C9~+EZkxxu{>jB z{9v1g$K6v6F#lB~cb0H1=9Scd^l$FBMwEDSP9@+FE^clOw>zy=2TN&N;S{^U@@cc@ zo`pLIrEd{9=c*_~5viNli)WBvfe;o7d@mObu1(g2WyuqFIE6Tpqy8-}Eru8sxm;De zFuUaZjlQnl=8rM1ch<@CUU*-;aJ;j02J#iHG)?(gI&9C#GLIL_w3ic(>@?fPF9i|j=U|}`S(mhN-lO4Y#Q_>Jd2x`Tu}_-{R3wuN7oN9ojtY`DP#fb0 zV0@e^RTN}m`eYKXtXWc{5;4RWbq-%if@V&Xm=ZTgNq#llXX99!))q1=JFoJ2#y{sN zF?DIsg7XW?^xD$_Xtcs%>~;szj>w`ah~IQkfd*RWbCS4b+GYJs#DCoe%8e z0Q^=B*{z>6+LmB79C6pYNKqv%46JcZ_tH-DtmI4XifZ7atkBDu(!SJ^j{bO_FYHe} z+D)P_{!#I-3vl2(N(H2*wC(A9DzKNNB$M{ueq7(F6MV#m_t1s=<;btZswvWXENray zw}to7`~5P(p0qCoyHkI5ugp`Mp1-y^E62}7fs>)_M(-4OU9V{g3`e)rX5>2xt z7NJH4N@UQe)5eM@E$o4~RRS|%X$OGBrvzA?vt$g3!a(4c>NQ?4Ceeh+!0XO_le7}| z=2mV}pCnpc{sqUiy-My1KS4q-Thj^TGczoeX(y9LX=vGNI zno#$}(m6}BA79_6FN1ivWkmLHKsvF#QmvUFOI|;_ zNVD9|r{mYu)VrDOnKgHZbnM}p5av&J8-OHZAOpR0&QUv%8C3tEii@Pp_mP;*Vn)S9 zR%W>T2RAU-HHn_C<+9BxYfB&~{;gx3V%AVsHE45ku4mBfelBX9Dm#(j(oBm-DXs9U z>F)|Q%!aKwB)lOYg+5{7?rD4-*eM$UlKXnwBW4)8kKz&=SWsClrb!l+Jlh{&LO@X= z?ZkheO~Y8S32{hAKSDc(!)!IGaABRO_MlHLh{~wHY+wkG{ak|D=Eig>xhC{gxfJ8{vQd3$4teTbYO^U)kIRo}8`D*U7;*x0sA*|wrN={K>GeHBBYyv? zSvOt7*lqgy4Tp1cwB@%+v&us~r;-SS|2hWy{{{>HpWKQ6!8FoStEW8q{15H`-S|ny zs7Myt#YS%{jZGWhOr|rb^yV-TpJ^F|C>Escm}ySBI+ZmA>ah`ivx2%|U2Lo{Qm1?K zEA&U!(!#-^>eJHF+Qh+Y-q8Z+I9PaY>-{Z?nC+L+lG*{9(Kzo&**O1^y3mrETG#pq zXH?q2dI5wL6}I4d5x7O6h4+#kcwSPXFt&7%*`!o8zdW_MFUJ>=`tFb$p*YR!;$&35 zn>GAcTz0d9qzstDi`@eB^oC`jqagU5VW?78TvHHyArzwTdA^kMz3{)sP>q|!8=`(1 zK;7UHm6cMZ3q2#I{MGkBjw2jT+4kKR5pUZ?>VKo5L`Nol&UyOA$m7P6`Uo_o=Nb1j zs7dF_ID}*}rMX=J5s^K)U11RsS&5q8E+ZmyX(Yo+!(ypQOLJ-H&>~99Hp0SJ?n@zI zo!S`YD%vf$j9A7b_az(iE&_h}o+M|;cSNe|%Z+t5Lb1T7OBwMf=>rQF##XSqoj2eU z#n~^S-lSPuw~g>^HE*%Gd!vyoF(&B?Sht#JAgredT!G}~c2X2WSH11Kj(oKp`wSSQ za?Hve<`Nb=^l8`Jw>|lARvF;F4>*hKy9=U}6+1@j01NCrs^-Ozt8X|stlwSK6ca5w zcdFxSspuQO8*IyUGA8iQF49QoqDXXzcnU8)@Unh-y*rFSFNnx%}dao!L505SbvC%bF{DdJ^*yC`j3hm%NMm&}Hfk4$G4Nu*N9{AATuFj^pEjVeVWz z_O~T{Yxkk!lZF~zl9mcAQA(8@rMMH9O!m_|g!h$Au{59RhcB)vDeyF#>hI~nD}cRt zDJf|kY&D`Rg6~qB?$_t-6X*kFPEW6|mH6vw`&XNrTOG;xntLw}!5f*14-%gO0brs> z)f|uM=%)MV2lqRwP8=ZmV{_#MP2}*Klxs^8j+$`5Czi;qi13xm4w8bq)0dZ$w|=_L zZeI^NG54-#1jhO|?w7}Hy;{Xd)%tvm&g(z8PAuV+Ly54ChK`*dSG+ju1Xu0K>gu5fyJmQqv+J#86Sw=vLEcKG!tF z`Ol0{7zg*mw_{&mi08!Fw7HD`PcuaG-;@8}VrV2r>RinfP-g%$I({37GEg0@65`Gi zB?Z(tq+uwmz3@9OSGi8=`R`D+&ZHl;v8Kagj$xZv>*spZ`_plrDard}-ye_3$;Jb% zS21&S6S{<7{%;g>qJPu>E1+!r<|@i3BVN^ia6;)0|KKW;cv~G9Iv^*y|iv1m>tO$pmNH(o~< zMCoh9D|+2MT}%JqPRM;Sg6mT}eAI?BSUH>ee%_&B8L;_!r?ryBFKyJ%PL+TEeX$#o ziy^1}fddv7)pa&cNy4i}oO zCr93<_M=AQrzE$xNt6&9;H55E?_qrn<%)St_y;GVRDEsre24nvckf{2dh_7kZs8fU z@Zsgp6XV&IWRt3*bqM7KJ+*E zF{C%@`-LKM)D6h*wuT2+*>UhGbJI|bC>x_Zq(>ibWva*xb`Xv64XR1W7IkrQDOEQk4r3ol>m zSH!pMr7N3OvUZYgZBL+4XUS4zcvMjGpj{B{AiEH%#h!wa|9RH~cb-(NT-A10mARU5 z1w4sNo0%Ijz_EYjf%z3XRW?yrx&5s@LxnO%B)?B^yoR|ZV2=mFZkBrf*MN9K9Fx~W zkc}8BQ`k#$m6|=L5eP|U@0gzn_*8JcZqJH(Bl|NX?aI!~{+dZVCc#AG@W^g2jLq8i zBC@2n49Pm*K{4uZx%rQan^0M+b;OLS)i9{DCp`zBI7VuD`UfqL%T`owk+y42!NZ6a z(+L(2sH#fe!E&caj`yTBrgIJP?@KjD@*nClg7qQ#!4J8j*LyryRIIQ898CbS4M~x@ z9)ko^QF0eMakLp|+^I?)C=+>C!!(s49klxn@&)^D^81gLM$I<#gp z!4K9|9Cqq)OnVWyRGeO_WG2TYrzB=&y)KODOc;_&!u_07vvRThf(se{AD0%C1I*;yeL7nzo3!gSgyuns?<&B$ahq&ph;t!l)Qt1rp@hliRa6+Oa!~V+Z zJQ&Q2@%}b+vc3CCM?rJ`Z{A-1C>`h7x=}=O!{N36}XJL?rhO7$a+v;|h zU_yA^i3BRu{*T_GS`6Q|_&n+?ZEjXN1=D(sl2bl6c)fBf^x<33w(&U+q>;C-n>&GX0f7S+oTh-c+< z=J50PUUa=MJ~{1kFr~LY+=}*j`zO!F*c+jxTNPu6Zr2u8nQ~_g+;_fVdw(8hS878` z)cBq22O))ISSXl>VNM6p|5T^EfmRE!YW!jSNui}{ciAT~xrrR1CLzf9ZTIl4 zsM>}YV7WgFW@J1WCB2O4ZTPAj_By*5sIYnivOj!yW2w%}@$rr!otD`V)P<^OdAK#g zpgDLe7uS%yK^gV@0W`Y_f+ymkHBT)yy(}_M(cBj!o}!W^m@=VNBwHftX2m9;yRC8o zcFQw9zB1mlRefI>j^}>9Go0b-DQ331$rB`5Iu6w_j>yMYGlmU&`7)n?@-}IMmkPq) z2`&x)gCo%Z^d?>0X-saOfc9rpiZNYf+Z(D@jgTxqp-;@6Ul+~HcIkhuX34tu_VhFH zoo_CSQzMiFOrG4oRJtA7gjEy@xoc?|*B|UH-w6v$5(Ma{wLJooj0x^UAU^FzyqY?7 z)kW&f0(;rk!tTcP6M}K11JQFEY}I&aD+KLhHtrYuj~OgJE~+36cq9X6+m1#V0fM1} zy(7@(c-1JJWip_=BXdmJLG;j5WBSA=6GWUskjALHl$3!ys$DOjT5$>*b~-)EKxMtr z*D->_Vp1xx=Zxmw`@&-w@J%k!P;Ued$Zg zo57_LQUwLNF{^X7-qq}3&koMU8Ko6N%eWFcvA$yRSWs9`J`q%OD_<9u@>>o^VFffBS87vQrF6{!*?*rtv_O_=#F3vfdxBrh-|V@1s35-RI}X8i(*A? zT^4}QJCsD~*YpEVYGP(j+iW+ZixtK&@re#QmtG%$Hf_!Q&<(vJTFB%ulNhUM>iK<( zo2cnVn=9&LRXL?VcTN>0a|ByNOj5bUI}$m$LYlHU4B z9yC4VHsqra6TXGlt1|yhqyQpVE~5mKmrnQ`(({WSDT5Pr7!|P@AP~Q@k!L8F>T@(> zCN0}E?#U?HKQzq+4h~35Vg4kbH}7N+G`+g!B$R2=OeVU+tGQAm!q#Rvb$>e0=d{h= zp14aR+Oj@m-rns9YrddTUk)lh7zK5Nar1aM@k{LVUVlR1 zak0onFT5`U2dBQXU3~A#EpB>=E*pq4|hh( z0Y`>hx^8-7(0xh|Z>M`-8I|`*NzYN^E4v)k7UVi^7A;-E(TKP$mp>xt-A`{LXK5Jg z@RsK74*gh}OtkY;^Q0)5n$i4g%JJ!UOf-Zlqs38p;%Avf2ozITg#d}@QO~*2v;V5~ zeaYSZ^%AjkajCzI;CnecM-%LzKHx%cX`$lzVQ2^G}UI6q@FSB`G_?QPO z=bMV7w?d&nsbn4!oJ)&8-}l_?rh5xuevS-D+MVL(Al~AF9u-x}A*9n-u2oEDp3=E? zqOxv}xx@IAP)2O+toE_^Z@V$^wLVR4GN^8#8b)#J^XGW_Z(+Ns!M{N)BG@~Z(Qg!7DBQKn7Vo1_=^!SAcb=EDa3X+lZi(aA}Tz{jKnvdYvu*~!-;ay7C;Ny|rUR4& z58#DV?Xk;Ehxnl!KTzq^vG?e-sP#!(L7r$}2aW%OySEH$D~#4Qp*R#;+$q-L?gVIY zcY?b^aMu=!TW~E>+$DIh;_fcN-5m$)XWdVeTPL6f%<`*Q?%PkiHpu$J#15KWh7sF!<(ow2pdSyI4m%oTvS^JmZ6YGPAcSVE~< zf;-iIoN%!?yP(_>A!VQOMlG7?gnt`xn6uo|wjrD}ndhx59N~_68fMCvW5V{`j|;Qk zuD|-kS=FoB4L6WOoA&zn%8eZ&S`3D)>$o(uFv%$xu>aLvlS``H=q^?7@8wK-b9;Y- zf}7l7&j*(ftHwuwOBA-2vjw5eR3Bwx8q~-K+RA^B*2R&DszqL$d2|!_+@Pb_51DS% z8!p7ErxoK|0R&PpWzg zJrc;Eb${dyROco^A?F1MUolynqQ-8r-EWSXOYeviBheV@tp`$hR zdZ$)Smap^5#kt)Jkv%{wI^cIPK`>;30u#nFO@-ysd_b3rUXRC-+UHAG6&#zC$*fT) zm2g{BX0%Hm>G#LbJ>M_0A zZUdd~0YO>tEil;1H-}z@Mh=AarYNX9W*w~TBXR z1Cx1<3kB^c>6$65Re6-vp7XtWx@0VwI7A%USc|A;_7!J#t4w&T^xXje@?jde5GIOw z^QNw`qL>fiHJMW$Q^*KHu(*lvG3`G>^HaFPOP=9-H_&PS6hQkAISlT8rq<54o^@ah zF2_M8EVWOK?_9QJGG_SFde9YS#Uv#Lb2W#nkNp67Qb#Rvt7f)gE6XHK>qymuTgUFL zhM$CHnCwXoc~O5PVNCn`r>pokMU2Im+0VNMS@A@7Z6T5w&&ins1(#7M{NB{OlS4fb{O9Dj3&i~e{dq5KIT zQQucg;*Y29YvYe+E*<)SaY#5oXCc-=(_V(Zg;&u)UEprj`aVb;Q0zCnbANpkp;Gtg z;Xi75$dr}U6qm;Rw?;ZwMCMObSM7}z5C^c=jV3q{Iip}o(|K_2Ez%6TXxoD6xz@Pt zb?E*4mGkab(n8(k$0e0CLRMMyFD$$7?`H<+I?xnXH@a|j!Ye>aegOQ}cen$^qCE(= z#-RA|V=go?jko7Q%I&Sc87Gx3!w0~H>6 zk?a!RO_1=zCKz|mIAmZNkwtd|Rm$$>{Jg(4%K4}muqv4AHp|ypc`foeaEb3N8CjK2 zrWrxgWKE=mP}8*qg$4`#Al+xSaCtyuD*otu<;X~BzxEF1h+<;dd13i+4m)%$ka@>o$-eC+~4SeNNou>Pgd{H6V=IOGTK!=LX9T z4eEzpNKo>^)zEI6N85j?BTABkZBFY?Bw&=vqezR8vy|Djx4s#>`<(KV6t`Hs+E^}O z7b11>=O-y(i1w=qNr0};PxM5RdFgKy%s!=LDMP3of@efzA(=rfd%+ib5QB&j(O3(m z2Tmp>7pXATfG~*lyQq&S-ZKF;;`z7~8lPwPua5nF7JHc{qT-dcD=f%|x%rkxWt*hc zxoOWwetsF2vY4P>%dBdXmVEqOM`BkRLWxT_TZ1?(!7iK{xnPWYX3@laP|CR6sQdeo z4a@A7eFlOCa?vwhJH+`l$#fN)z~xM9qTpF<;TS$eOCVQuGi1IP2G%`9UK>FKjdqi0 zkkp*wl3f7V%cBxyjIf{A>;l^t?d2z=@{?X!+^3+*zMURNRjH{4p<>=p(Funn(RJ?p zDpQH~h1{eRrZVw(+@W0P_cY+1TFtKTTCe;h89Ho)&HL)@@5JrALH9YZR{wNE@ z5y)=n%p(z^!|tFfB~2flK20i_mP)FB?!AnV2-ya%DA`fjH^LJ`Cl&&=1!DfkQ7x9# zg-Xo&Q#k#rn%pmI<4GUISv})Z!}85o7d5(| zeVRG&EP%=qGqWo_(8TMI_!B#qepBG!$_SM*enMJNl%j=qE-l@v>0%wqI)t~;?&~!C zb4^XP!NALaJHes>Tciws^`(E}1|?$fBSr2WQ{2c;H!dNm%HZVtFrW zk#-5CG*D~^ItYi46k)MJS;t==EQebm8Aw-{)qNVP|X3n8{8$5 zlBZ)v2{)?|A3FlkHdDt+iVjJWQ_Rb}=tt*9X=$g+DgvmZ_TI=LtU0~pxt%jTTd789 zLbt(b-aIl*MJ)m%ed;h#d-d8)$D8%%NnaHe%>3rOE!8C+;&*N{X;_I21nZFI?ayJqM=k}?>p404|vUPT4^j#Imm2@X( z$RJC^BE0vkKlrEI{seT%I%A62%4^UXT6nB+Gs8kYln-P*Naq+Os+IuLfhhxmd!h?B zh`84ZQntFW&uo>A-%uOHjSS2&aN9oQ-ZI{qB-lWxJo?E)*KfgEp2+D3dK*;q_0lH@Fae(BjjS;y zPG|OEsc6;fz+jVPtkN5fI6j=g!mSbU77XwN%boc6P@Sh zkOy|RE?KQULT7DK0%!`QbfHiP;7N;qile_#rw|F1iQ>NJXsEW8N)P_Be8jGN+7 z=_+i1n+6sddJd<8l2!QUNA@)}12|HTu{H#9{fYGKE_%JmDYU03;EiJv=_YcQ+()>h525~!2aa#I%pbT#}m}RSlsjymv7;~^L`BTA`ZTdqR7bSAS#KvmzqX!tqI!`#EoNp`M+)wRwh>8$Gr;^HaeE3&*&@qt--e3UX}2 zDrq&juo6vTjXACZ&VMzr&BnoV=XQDj5ajg#A*^!W3yX;%nz2~8{zG_xd_L6pb+0t< z`wxNiM5n=7AL8Ul5|5y%D){36BOINDl)hOu%g}t<70Hm%nW9&fHG(hS)^N5p zdfvP+mCr#>Dui=(x6ifhSA^g3)VtNd`C2bEg(`q|-AMY{x6GP%-@J{|E%S$d@_;xh zsvtcY@*#49UP8)J=#|8iVFdZcE27^KO-PHpHGzC$ipBy&9S4+Y>m}NPx~Kk>?CeV3 z3>=hF4hf@MJiGvQNhcvg>>->H*CmOo4PuS*2lqhN6+oi#r3vwsHM!9jE5Tc0Yyru*kM^K8(3Sl25A`0_~;MV;O1Cr?`~q&hFjs zPr}%EpyxHR#vPl7#<7q8W<_*uTKBhen!=gxjGC~hZ$2Ny@3L77oGz*Ed-Q7g*cQcf zPYO)5I^R&ViGh8x^JV$uxcyOkdEb|xie>rtjYXO@dZ|$`8_A-Mi2Vt$4SePs;Dp^d z#z%&_Y~?wS>$J56U_&V~L~tzisF}&%hDwL@AfGxKVqf$eWAh|&FB`^foTY*A{+qs${u8nYCtqwe$=ALCGW-XkvU zIDfZKrbp$(@LV0-Hx+pLz*u)Nt!n+`iGWWVRX>Cy&qFob5HYlLPbI=8M5?@zl&=!UMZlOXSr?2UV{{bdo2+Yd{SSCGj`51P&nva>l2?a zJZ5U?b8baoz7$^E!eLJG-g;CxzX->D06A{_1}O;JKUjbr!D!s7N}m1=h5nqmbWK6S zq^=~YDY~mE?Ku)(7S-wcPlQ9PH>d9fh=i;;$eU|`s_{}&?3Je=`ff)r{ggF-^{@>X z7Slu}BsMiH`E+u1>U~~|uGAX2UwNvftS+nEzMCg==#m0wn&`pXy@LjJ=bskCo>hGA zp{9*6tRKg2@WN4iTFW$=x4$ly_nm`D*JKsgaoG@0LWlN3R}Sh%!;M~^GzR^h0~zR~&+Lk%hu(pEuvgMpbHxxI z#mn0k-l$b)wub0{2iLl{)??P+p~}s~c+$-i8x~LW*{n1_bUB4W3AR?as?y%b#HzGj zDTfd6x(gL@{LtMe7Ii9k2<-M|p=hUMcl6(_NDyQB;oH3_zVIMVOtuem^?ErXBESSs zt0o4Fq;{51MJ)H<@N<~BQPiZF7 z*3E=AM&6=fCAQ~eZI`lDA${+k(Ur+xLd;*HYg)AnY(+rn z<6dsN_%*_8-+$_T)8*B_Vf~F45Vb7B@?&T1m!h&GSmEbb>AL0)57*m#5E?TqNgUe%sF{a0j-+s1vDPP}Q7KxaT5>aO zg3X>}G#k0uu6zX#R<<*d9jcpCUP}BdHu#rnhsmM{&6^$Esdz&(kz9tCsUC4U1lZ#3 z@*jOBWsG!Dl~G=#j$~qx2dgLDX+IEnb`7y>8xKS4xEXa9QtSvpw4gWy3H0oT%J)i* zBXVxSU&|NX6ocJ^<`|J&$Pf|0(@0Hq(~^!s5oF-Cwvkz`E!Ev=(vg07(`Ub6c>}Wlk**V&W5LCfMr0SJv_KI z5-EhaAA8WkV%eMf(A14iaZ6Xl-C=|M25=(Apy^t8X;wd|r#oo82Zcngfyfh_EJwX3 zS=T5HK)*Mg7#=PY?6mJ`SlF5BDYghn4y%=@P_bRe$LVDUS?U=lM;I&xNH)-%DW>Ax ziF~5$?A1_om-o0)r^i3my!DSz+hRY>?nc9c7OcQaSX|x5fnHq(ivTmbAY|TWf#Flg zkQ~b%#JjP1!)6q}*1BOXIM$faU6d2S1x;wS2gs}z5$?*6szOj;3Y-nq{dS)hD1}_?tO`dGiPliAu z4Q2x+q+tKPFHbe>oi&PH&Xjz0hXvL7!K*T*ETdonC(*c-W1eTBCn^Ksv_8igH>@$g zqjr=GGZL5TP4agk;WOy7?lj*ioEca~88C;zhpD_A(bqr(w{2d%@eKEpcb~XOK^I7l*EZJ{ z>Q!-KiFIB^Jcf8&sK9%a?|+>w42~DyDR;Y=ky)(?fSAZAE^5Rslve&u1hbHy3#d9L z?dddU6f0E@Kj?wiwI!_rt;_}JpGp=s51qRjWcIWP?pru%spFWNF@hK;G`G^r@FW&V zFhBs6rjV$4-nYfgHu*W{0t|p)A|!fii6_7AtD(oPnv#{sm7|KkV5$NY+(=2-G#SiOE zcN4u1`PUx|*CeVN20&-xHlHSWQQOKm07Oz4<}yu*<(5UK6sO$Wa@0c5WmNxGUi&~S zME@UX2$C^!ZC>+MAjHXOJ_xpJgTt(H<2mdYR-+px`^Xcv$Kn>eyntyfGZTZnd2dml7riOxAUxBx-2KSf!o6mM@NG4MDxyyVBrce zZo~SG?6vEbrwes)8gno)gRfGtA z&CA>EP4b^9X=pBE{r>Fwv)&jW&L3(&c?s16fN@zRZ^=5~oy!*NV=R#MXhv>IX6kjZ zlI(Pi@u17f9o~7%MzCY?$+-I5^7rZ4N8Cbq#$eFVn_MtF;hp{Y7!N~xTXwI`ICsMC zG6IN(La|Cwuf^87&aP|1f!-mPYSNUe0YP7?olvXM0nnGF3?oBZ*T=^W_V8ssE@}=5 z@9NMXlBmkP2TL-iQndvGlWSefkb}niv5cNj-N$qcj|-+yovIAqueCD*!ViSRcbi%? zE()tg{wHqae-jA&7lR}QE$4N0@*hGD;2(mTsFDqwBDSKNbIg3S5%xU(_pffu6XtW_ zw*}1e?Y}EIWuJ$ zXOgv!0-%5Pti`esERx;6&KY!KyN}0{RVIK9mX&p;8c-)*-R(1}7o4x@ZR6A7)h)Z+bG#4oTyS`|a)b3eSvgwri#)xhI`_=Rin+FNa-NK30i5V*rf<3L zCr>o{eHA%P6hG9>TZ2$D57~|OS)K26L%gD-=%y(|4Bz}|&+HPkm0E+A8~#d7g{3@8 z#P^$b8%Fl7N{|qy0-<1oYZxiows%s(_hs5#VY$ z?9<7vUmV0$wQ4^Q;if_#EdL?g$~ON)cpjVs-S3Xn{-wD4_7CB^+CPMSb7PKZIAHGN z+xZ?`MP19Q*O)v$esi1@xhtQVyg8C!bG@jUyQrri>)Px29t^E{0`nRzfoQb!VIk7%h?i2^PI|Vxvpt`n%ZP$5` z=RSF=tM;w)gu!18{O53s>jJf2Ke|MU$nDK}QLvP;W_i3lGe=|jT>*Mbh%=}ocU&1J*<{yzlwme*W(R9-GsYiBvOpzu!izJCaj zT7l}d9LLU2oBt3}HW%B*&X?fE6LbF%rsJ>OBSCw4+l2oRlziZQ@ACf;5=)HoWWJ3j ze1nTkBJazdulYLvTTUu>7jGVT5kK31k}8;U+JDGLXt4w-dwjL&(M&6iz}l%CY`#O< zd3X5rC-jf?xsSj1*z@Q}VYjeQC?4*ftRUF98A@0K5-pOwe^(tf*IU4)Gc;FI!fb0n zD+6AK*2pN77o&jbXfAY~xQd6vCFJR)W$yCH-p8s~B&t^d1<(&k|BA9psR&+6Jz6pj zIo*fnio^J2(Y$s=_d%4TWg+g#@ozF;k$jdn2w}9$ex8M%(uze~yx(W#R-DaB!yrvt zUN<3am&Ef5Dbq_2r8X=Z4fLzlIeuBy5>Lr2K-=H;%v_=yK+1F18mIDl%=p;VRraJG zEh=OJMlX^OSqQFSZm0>>=egagy4E*fJuL{ABBU8AS`O8IuW-M({_|vHu<*lp zq+%RO53J$6$}6a&;EXU_xKg(L*| zPI3f2WQ+Fzp)?-wb)Nt`tmcZ=fN6gx{JFG(-AtLmlY_VNFbebD@F2FB;ng1TPTNUb}w4L zx$t_v)*caAd9L3fS?};AOr7M=z`pR1pBewmW)&;15`zrUkn9!QCQl8CpsBEqPb+|4 zdVhEAwKt^hzv!O7(mpw~cg}c*vMNmCmdp9$%0(+21tV9=jm=hnPT{Gt;2g}p;{(>X zxo-7KNr7_8lX~d8N#aW48{d5-()O(iO9m-zn+v_}Tah%bqJ(`Q$X&sXN+PIZx(v4p z;Gb7cAL3QMF#fw8Fi<#bz#u=>&0mkpZMz4Ldm32WqrChp%*uA!WWKu1~07B4q-+ClIO zR;X>J*up`I?gcVc8Xid6fazCiLgfZ@_@Fid^9M7j$OaFew=Hx<&ymf^OP9+_7N}v? zt6T_@%o*H@lZ||2@zf?-Rr_uX;L<8P)}Ap)dvjpHLTI`W|T&M^ZMg9k#qW?ihB4plk#BUejDloYTZRgX5;g=gti8FWjQDzn#k0!tCQ`H=-U#eMnqr34RuJTkSKX?EXq^* z?@}l2xyUxrl$(qsVMf=S?<6^)-rT+h_hqhR!u;sVr(-v@7wUt%>#VmKaV%Tn8m;G+ zOz-4*%mu4-gY)Ra^h9`7wsoWX-AZFL!F)|6!F7Y&CpYY>+)Y6DHa(mctGgM=9=g4} zBF5FD$g-W3qhg+*iYosEtZ&!6|MSXHHM8b zZ*Xzd{R~Fw{38THje)DaI7o>4V6^|IHy8_?>*Fk}2&ogv+I za>KJBm--}0dCW?RG^d@9w&BsUh6}^?jL+kc!MTJ;I+j%2oJ|uA4$M~{6XdI5-4Voh zt4r#V;I9ofdWu{$zKk*G+!h&-;v^{|I3P);0KG)v^|tE3eWUP8E!#1OV)0qfkk?Hl zlkS(*_ua=Gu&Xar&jDYS)t5E*Mk12PyWYRiA2%7-zrK*3>q3ZdG*&z!zjMdaeTss8 zm@xPpNv*~KlF_;_OOMx^VaIzF&&`xV8>f628W>eHq+Us(*;z$~+c_FFT5I2FSgnu( zx1z5pLtcGec|(9FOc~e@Z;E#H50RB%v=K4drC7r`3q-$@^@QJ84t4Iq*g}r=y;qW+ zMC!%K)6Jo2oXtF0{6e~MF4>{95x-0`is^DmIldVfs#;c5Wc%?=wd!5aMHz(q(e*e? ziYAH|^%Zh8P@?K7nwSoWCcl;2#Us4Y8VLTxn;I~9_h_*X1Z!O#O9S(XksS*<41ZuR zIR{4Y0E~v$D$w~nOWAThfj$q@NCdcK%vsBa9*NgTGZO5@8{o-{ru)r!cka-Ng1>gT z+?0^x@EehbIwrkW9_Zn3&Sg1*>lpAfbWD}=>4TAL&o%~@mfV}5>;pWkc-?#?(s6um zh+gkB&qTf}iwx^V)rNe8Ez9PPgylG-63toVe4r_mc3GL*Kr91aWmaT={Jmrq&Xw{Z zm+e0FY@RonghL56prrc`*qdRt>{A zN21Pp2NTN&Ip3c+f-?`Y#^If0^U`-UAzK{%+m;D$^bcclFHO3}BxeJxMTBbncR>+4 zscT3-e(31&``>oyb$)@2t)0R(o(8O06>aq>Y6;iZFKDA-E-BcoKk-Cf_vL<Z#9SFO8N}@RDy;fcJL2uv{vl}0xqw_m=V2F9FG1u=F8+@(ZwitItb585 z(Oh?NBq5PEXM6Q>>jp^!*?td<1R(+7ZNtj>3z7CQF)ThWB*ocmy4}jF)u2O!&wnUa zMG~P%stBE$!)XBJ2n)VWs(uPm`N%IyIIeYsY|fTG0Henl^Os}g&*&R}(g`QAxalqW z9pt>5HCT3fnt3(&syuLkiRWb%A8VDE;&@2nunfU&bXnD~JMJ!49pva5E^BCuzk@%r z%Xrf|6R55$K~Y)2{`_3<$O+JDq?^thV--J|_eM)dDwS785rG7>Z)K@5*ytehn^qR1 zkT1k#hU5W4k(;aIs@p@cUzqTCQed`V;#!qjHzPnMx zufKCyhW$p*P(EHb=bpQxJRS>%zLg+U8=+4?U%#-btLU1=t4<$YhyKV{y(=>}l06B} zISEjo6k(3aA4{|1xJNm*2!kH3baS^x6WIxvr=@O)gvrg{<5#thxUxu4%QAfoj(7QP z4K1(>$SbZmWYIso%D%XYwC12RBX#m>uFUDDI?6J2&NpRy`D@SWl3hn!O6g8JGL7flYq@h8hv*&*^7g{?~CgC=$TOmf!nl`0{y z0%urp648&eIKayiaw2aMq7|zga;)}ugdfy4!hwhsrEa2fk^~yKgqJ7A>K%NzgzEgf zFxfXvsY(u+?(Y`P)txNhNNFj0-(eZC(k?!&tJ;9&20Ew;PaUI7lb%!5I&Q^+%st)T z8c%+K&hVKF?X(KUjV0c*X~#3&jiH5T1r^ae_cyoH2`@e+faMn@3%UY-hCa7$XNX)H z=Ynpyy->(Ev9#;K-g*X+@LmAXQhzl&*(1diLrYd)UyoC`EXEU#*s`WX3Cr%7h%Z;9 zS#K8;UFGcSoAxriBrR{qXtl~Y=^4-uDmB-Z3IVW$WdoL^32r(X$tgW&>=uDdkg8x| zzyc{-A}POg*40IZ`o@B%&vYCp)I!eNtKcv#eZXKgE0fS-yUsBNp8oD9GLL(!$+tWEBFgvkDCd(*|dP1@J z$#O2BzDx{-PWGUtrRCEhEAY@t0C-Zf2v5|9d5UWuu4EREwRQ7P8#TtQc7ff<`n572 z3Uq4U(caURKu<oV|UEJU?QX@8pgQXlr=B8O| zvUX@fP>$-DF`&w=`((LcdD~55;FO}IlrawIOt#q7mI2t2cV}zccuVDzg(Cj(P`xA# zpeMV$L7Xzd$0nVkmjq(Bs6Lf&%Z<|T!gji*HYaeHGGAKdiqY;4ejMa*95MyRD zLcCWJ$922fzE+EDnh>sy#@#?1U(YD0Xa&84EAqnl3$)stYhn>{@x58Bklev7Jc&fP zksQf=?CZX-W!=Q0S&7_Obh@@Dj+{)ZpY^_XzX=&Y=N%}JG z{gRyZ5_ZY4bbQtB396uXv(X1FIUZ^r>4o!?1b4}rShi#+jg)^PP|Ev-IcDjQtZKuH zYZLP)*oA6;fPy@JQ87E7s|H)NrY%1BxBT2V?^s9L3xh>i>WZz0ce^|oP{$iJ6Wv^6 z?J6VCjSU|neZ-yoJpwD#9duc0`g7a{m_>)2$w2S!>gVQ$7Q#EXa9XW1Y>2j3rrkt{ zh6uV%g0~wTlgg9F81%CEH+Rr+lllUkS0VJ+2BZB)uWbuI|6AJR|FV?l|19IFz+d>c z8cF1T2b8WySq4bHgiKqI;XA>=KgpE~r zFEjL@(tYBq?+)5`-+mE++`K}-@=e*H$4fR8S7+Ub6?ODSjEi(j(Ek1+4e&(PtpsRX zw2cdg$|vH_Rb2n_K5YZ_Z$5sue=^Wt00Q$U;j{vv{3x99RZ%&_Tv1uTkOK<*OAd$Y z&-{OM^D^&fhWKPnhef^1C4P1RXzv}<%kqo2e0zI}%pm^q^qwi21|eKR@aER;VnnlXLvP1tNbP@VhjJMf5K@JQlOvF}n8u6{NwVD3E@1bn-4O zoTip9sHJts%t3{jMf=yl{=fg2YNIP^DJm+C;E`_nk4VEqfdBvUEg}ZS5WbZ9sB`L( zkCSF39Zly)=57lQb1CzSUpfA!My*xGI!pYu{`v|j_PL8nvOA> zVho!x!}8=ySv{F7U$M$rmw6qlX^Eu4)xJ)#_U_qd3vPYIq9wl5Fq%z z_C4|(@QpWE^|val17ZNwRo7pcHRxx>viHYG)pk*x4UaH0p@)3x7f^t9p83+aQ}$N4 zt$zh*&j8Ju8q5~PxfXj^b`vAKI>BuI$~EjuZ?K^pj&WzHaY;O0f^Xh&dZIX*m}P5x zRbSOa;#Et%f_Su!vh874R7c^UC=Fku1Gm*lX%8IK{7vRO&wll6qLvT*sob9JowYma zZ^BEw(O=G9Ox|VLb$(Hloz+{zdB^B_E;d2Am!R5;e`3`9aQY9ytp-k_IFkK6*w6P+ zdIc|NGvqyW{j^oQSVg5rPJl#^#?u-WRhRSC%Ky-XOO51lU-pe(3 zYw1${?2U6-)oHbmf1_oRUzi#glkF8>x%y}JrlWRc5qi%haxd|8ITpP#pv*!>Klib= z?ZSUvPjEiFfEiO$Oyzt)=NTbLP9H(TaPHwyrq6Y|50N#kkbBAs)AV$!9(}tW9n9by?$+_p>6ytB+y0NlsXIV9$1uJz1 zE)GvbiGPcBs!15K6B=|*4yRRgQ94~26R*IHmljIM$;qprh5Hvk+B%@I`e+vw)mYz& zf0u9{J>7hjtDR_KL5+Nk8|}^h^Q7v#JA0lT#|2i*V&0~0U$@)yn|}z%56KUFHd-8Q zdKQNn6|aPoCVw|)bC-liyJ3q+(pfC_KDDhkzJ6{sQit&qUoYFT5(r9SQ2a@8eXfBo zBG00=l~wovMHHY{^ef@7tlgB?ud5(g9alG?!7)mL6bHwjSq{vY-kUtobk^J`hSQJg zPy{@Jg>VJiVJe+`b%P84ub1;iZmrou_vCsWDf$KjPGCg)feYPzDLBiAgK2mB$i)5e zz8|O_^f%oAu_@(}R*@3d2Yw@E+CFD!zc@LOdu~DOamsIX1fS})U}z=_b+~jIax6V8 zoq^hVYrasP@R^ayVU12z%93f-Ob6y9{Yq3&4uc`HCPqdiK#-syCYneG()W(ZG?6tN z5t1YqKwNd=Uj@W*6I(h=YD1YJ%NS#Bj$JX;qxCqJp>ZUGfkH~fA|a90EXV4xmSy#p z)N1y7=H8CSAa&gfvTT=12tlsB;+omV;KPCrZElwXd3W-4SF4G|{2-6jl52ngopM%Wgt4{PK>@>cd#}%-aKKr(y>A$`ku9Dv8x~OK@f* zN7U6ZJ`b_=4oa`6DTaWKOLH~Fh!slL^l6<-LFmp*W23+?!Iyl z?Z@UCQo_*0m=#9Ns0Ot^tAEH`{M{)$AuRFM8$dm*f#9J17m`a8sY%_JRzxj7yX24O z0X588;C5G4+l5m`vcO*<-Q{xwsyb53ClSA4RLQ?mJ_8Fo$vEjJl6=$zqn9nrG~|m3N6mW)JnV4kCxuJ>fV+L* zqGP89-Qa>Hg{{Lk>s64~!XdV}(8wA4Fe-{9$qJ;PJ_TOtj2gXJ!#$VfH+-GW$MDpb zfPoBeD=PL`p>mZJn_2qX~$z8A|Qm)k#cxqC* zR)cgmoikcP1Z;+`H`fXpEvq>Zk|xi^9XTV^oX(|?Gi8JSQQv@#M7uBc$T)|!PENp8 zwpqL;$I9;duLWi6y;og~d5$VBPRF21%VtdV+5TPQ1KKVF85w3OtsQ@cVY)=a`HR(T zE?mvxsL>PNP|?S&;`+f)n_rm+F=iR4j1pm+R6$Jz+GTwdVo0{Dk8}%T3!_)rp3El; zZp|?A@(ME!ulXYyDp_dRVZ$;c?n8`Rhfi%jj03t`NlB-_)#smTK+N0drj>d#nZ|`V zRA&iN@NgmiS+>ZBTkxfn;%zMOf$1z&Xwf=><13AnEytbKuAV7LTHX5rYV#2m`Zv>6 z=CbjuISLD|vWqhPp#BgYE}d4b2j%?$8rf^SgJg3-``VLSUv>h4K>MaoNxMp#^j)YL z-tufyEbF{Z#<_nHz|tV7j=!jiqY+>tV@s8~V$_$)t$FEMFUCfkf;@tX$B}+4oLc-r z`mNlYzDh!xls43WSxD-zaJg0rKa~nj)smiELc@wnd(Xk3Ez0*4H)4@Gy`{_Ke=_3v z5F>~kO%U(}q5fkuW9pEI6d-T*&Q0iewq~EQ*W`f(BpstK=$0}*X+?dnH<=sXVi(uY{W0{CZ|=ttT{7<5 zYr%E5PRlt59h^!AeOeVZN6o}rlTJ|w`v*)ou*KZCvc2=>m**%WfdsOCKU{k!HR{tu+_>vZh$sE!7+=5zgM(R^xxhIZV<-pjyt9)JMswBv-36W z5FCGxla^$lA3xs>FP^2q@QkQnZVEN?Q3dr3GAN3XhpO>Pdg0U6uAK2gFVPMLXEMM5 zS7W_dvTU(5((3?4-U~W9LkjLKy&A16@v>o@K^^nq|~uwj$mc?(l@CZI__&7@$>I<`l65y)$HWE;I*>ky@H;??7$=QC%7qXA8jkle2cZ8dYe`cUi-Jm5 zF&DkX_8QILxNFR)#4%OAy~S9c9LoV?j?^Rx9daC@oO*}u>C3ob$K$Y~`Tlj_UJW^# zi4|z~K2A%yQ&~x)Rcetu#C&?zpTWfgf@~{3cWT(7>x;vO|3KQ)AH=?1ZQ&o%)YNvS zV0ba zI(CF`(vMK*kZbyD&d@&MUuu$lr9es!wg9fQ!Qn!?k16xxrflqAgKt2kR9~ZXK2rBt zq`x&yJP-bfF;o4T;XOa%88<{?u<5bvrpiUuI|a4wSKkXXPQ@m0Ww%V2BtP zwiq7n@*FP7lEu8`iri#VeshMUS5f<-=2kB5nl0k#q=K&N=W=jB;r9m zDi5LKtAp*i7*^j2l=}{m;H1vJK|fxGxvG~?#9w1Cig{afqsMm%{U zI`x|GyF;E{Z;$O!Dp*&|v1(x`Q?*dJr|M4QT|_~&jjKyrK5pOI_;IB)huhiSX zEgJy3uV&xV3e0R*myHh(aS~!bhR17FUs-kQ5xwOyM*1`5B7$&z z^(T_2^13^2(FstMP--8SiO}-rsxmlCHV+$j@KYohngu3*ZDQD25nTky8aG}St!s)$ zG0{$FsYzAH@^o4Ctd}qloFz-7|B_v#BV%h87ovw5S>nxDIfPYd>(Vm9pnvVy87$ZD3Z-%W(Y#3n z>s+FU$E`UvZpNa@Fj|K>#&^Z~B2FBcS$9X1m1}ErIzyIcoGd%|f|4mGXvK3EGl3hU z0E)XiW>%HNz6I{2uH1{019$9JzOCTX1DsJ=8J;e`ap8)IBz-eF>AwuJtDf-@Emi`~ zE!Jc4MkLywbEuZy*EJ4US$nih)Fp)87HvT0hojie@mY`0b{9h>bV_|5QAo0d$S1qP zJI|xWBOB{PTD~HEGrDNdG5cTGd&{V{!ggIZEd@%k;_gSb3= ze93HRPL%u2Ee^;%dY8;_70}FkL!jf(F;ON)eU+V?TqFJd;3`2`>LXi7v3uEIDRg3U&G~CE^SKE0*!Ta{D3(3oi8Jurm2w3x_=xq`+GG>i+3ZXcJ z8WE_&n!mWWG5f|-v^5=*Vf@z9i8u1Y$UR59V~Q3qIfc^ZG)5L(3i*DztoX&OJtbXB z61DD*aAf<#EkXXK<2zA5>A`yRQJe;m!9=!7S}djGL&bfdmcjy*OML6Q+P>$Bd{%M z{e{@=!35vtgdy4vt|vILBdqUq=0eHfU65+8oLNIhVf1#C;6r1g(RwLRKX|I;r5q7C zkFhVf!^HJJt@&P9+LIB78h7-pYqs_5RyKCST5BH#eqY@Z@I_t?|5Sw&-FU!*9a5wX zHdc4JCod_deLtt3)m!rm*95=d^15}|m2aqTOmccD%(6wlOsFQo(o64^35scZ(@}jv zrfxFF(UZ0M!3)0T^G>3jNbAnaL!u>(x9-|!-JsiEM=|3hlC$KqOWG{xq2fAI@3$c6 zMJ`Z=jkwx2NM2T7nRX1?A$u1*;zFK4G~Bojrr%H`zo%P!8p%vYCxsiExcLz=Ood9s zPNgNWldofC&L5k{u+-z~4q-4KYbSo$m#eJd-wmX1At;W^--IuNNC*!ig+^IDdQj`g z!&WDNIL-Bg5DbSbikR(H$`g9Q0=|5klh5)PR>wG&aZxgzqS+1Ay_3y>BxCmixP|*I zqueuB77Nm)_I7P^6f9xt!I)DRi6zWIHR8Xv(|)@y*j3>F{MQQmrXoA>RqMZiIl`X1 z*e;cXgdjbI)hgCMC4T{%M+MsmJ!!}%WMm^<5BhnS_2^QyvWice9&_o(RozXyeV6Tl+IHPLNpiXCdunULE56~2)^p!` z(aDeZ8}hS@!@6SR$3Y?X{9Rpso!TGxmReyMy{9M297=#?Nwyy#5-TbEFSte$1SYeD zN**}MyZg4^SXQ&Z=|)mC&j^N}jH1Fs^~h;y^p6#p(G zLGsCe+EWo)$ijJU>#QDdT>ih_(!Z$T|7r98<;7@n#KLta2l2y#->(d^sCNDUPyXR! z$o${*F~I-#RDipCU%UFVquw)*pUhd1m+9-b$@F7il2F)-sI)<(Q$heZFT9>~DW6sS z&qvov0(AnSaMfAIoEu?`qYEJ8k0CDls~MFa<9XR#+FQ8##{f}6GV3fgS?M}wt;o~{~^HT;wd}_z; zXH$I?5HCakXUlH5@2GyUZ%ogh@;`)^T`68ee&3V*1^6o>lrGhOjVo{T?Rar|zIw*z zov&`uk-_nuXn5aXX{fn%Fu}m~h4bo=5{3xht3qV;ld<>xo{LK~h<5kZ(u_&;%?I2g zLMq)DvF7-+Ij#mp6+NSk&`?{w9TD>R&C=~I<^fjL!jiPasLe~v(Awh;#96tu8R;(o zJT&?ja0qeu3%G44T^f5<4m=_&Lcm=e5pY*t+>WA`60v1a!PXO1CN zd~a=Sf<;baMan3m@)i~CqFw2*Z8dSKPCeOccZM)X~c1ms0gm1c8~QXT_K&a;s@r&onFiI8)pO^#bM-uxlqstGgzy8L+n-K z&WHndats)aG-!ppHY_UG=+L>>8)$xB%i^KVI#cYPj>tF#roW7UHzDWSv4{RBB0wwO-b)Afqtuk_ zY&oc0eKKGBdLzK$LeH^@Me;vR;L%cpi#5>mj$#@r(1()o$8?za65T@XgBvdn(Z-T~ z&|g5Z@bk{wVN+ zk7l2v`)^YqIRF;J z8v5ncR$at-(fqtDG@lYpJfY>$bl4O@#l{0B0E@Q*Z%`4Izc$r=#>*0fH|fJ2(KmjX z0Tq#@3EY;{}AwN?E!y<+6J?(X>)fY$nyZ;+o* zaYKb^Bp$3C`Fw+Y{EuC(d~ikyNm2b}x@^SSs$vod50geX;=Bs|54E2e5Pmnjgk!{4 zR4a(2dj5ZQ0^u+5d9q8n?AazP4-D3&>I?pZc*`-t_ejiLxxmfmzTdY`oty;kV$L58 z0xsQEceDcG!GEL>K%BR3`#qDGJ!k)@gx8IU-$Fq+0!*JL{#h46oTqyJikODqT=b_0 z^8BN!bx@L4h3RL!pS#-w11gA=ifT~G1D^F?z%^p>TR;?6&&QSXS^nP&t6h4)Ld%q; z+uvWnao2r?s29=-OqAu{>Sf?#kBzYHQQh~{byKye1Tr6(;2lq?1oQ;)COpIo{{jEo zC@r^@B0J6J`#XZR$F)spg-#qI;AFSk>*>1$T>Up{FXCg%1J%Tz!qd8hZB`T4p6Bm~ zmLZ4e^BPNDg|+)Vs#Jd>wV&z55uN&fuWQ3IRZBR@Ux4qgH#?$J&QIP&K)S$(U-5y* zym5a4y`G4XX&?Xns4Lh8Q2e+>SPuWBnM|(fASUh5^#?@JFC2kQsS*|%DZ32Uga$ZkzFWzzFNtw&b!~Q(*0m9bj7ad12|Mtba z5l^BZ1&c%--y}H49?g*0ugV>9oUiQnQsSXM)r|YrXBMBr zPSe>oI+M9hy|B-Q>GBlZL)LU&HKg>h(Pg2ds;s za+Te_Sn}OkIOvwH-`*H1gw)s;pKGpu$vww8y~6pY9@%`rDf@=IIo8s2qz1`jkjgJxofpIAgARU7nI~LBvApeR)C~%7sn?R+ zP3$tV!X+fb^hR9D^m!R;67Gyp5^k)vYEsKq($MJ(ZCxVFL6Bm9#g-C7Rh8upA)jVV z^ra*-eqR=0rU{qjSS(SO^m7TZ>@xv@L7uPyiyV~KFV2=+L~OAPT9pqVB|f}!J-FK4 zArghf^T%MJUu_9FEE>zb+%abR{C=xh#>jaf+3Sn%p1wStkGE5UZ}wFB^#Bme%kZIq z`Q+o6`+THlNI$Q%v((aD&M28f&6kJrfX#FH%6{B21LZVJ5kgLVRS5-O>ETDqurkl+ zsH-kw0W&R$&=MS+^Zn5oDfAa7$QLah1>Kc#*ff38R_LC zuG3SCnp*g=z?cj|S?apPEQ|Chc}5M0EB~8IIJEFYTy08rlg3$mPIu#gL45@RdQNLRT?0wjjT$Gi+8SVkIKn4vq7NfdiAjHO>2N%*lMq5 zg1&|Yom#E)KCeDQ2#_vKUAxAvjcmM=KyZTm&LU+$EBE#JLA#%OA(J$ziYAhqu*o>N zjiO2P93X{lY){X*Fky687dEiJ=Pl@MHLA%wdIRKr^Ap-Yc{YR0AWq>x}7krv47Sf#X!07o=|`~*Wo za4!_BZz9<)su1pHsd`kk?R)=(VnR?2CK{}jF?WMLK)t~D_a_Ek;cDeCD@na%Z`EOY zHp_0ZZM`XdZMB|QI`@81n4h!JnVZu3c7bh2uhp6DL4Ax1T$6tDng$97LZwrKj3~r_BMB*6mg}y`#iE8?Bg42x(OUkBmuAlp&C0&S8V1)2r9P_kEp$PDWa;V|YiwQGyT5XyNEy-R@h~cG+ir9k_=|Sk;CCYUHT-2(Og_=?Z7| z@+AfR+ss2si7}>D_1uGp8<^2hN4o2t^isOFruT0O_h+Thm4@@*ISM3m%X*yf^!EN> zzPa5tPhhCA$-;(7_B~zQ5cFr2P9xg**%jE=Q2q|!H{j<1LPP0mS1zh#K<&)Dr-(-8 zR47Y`oNU5zcYMqBrI{ZUlV3P?V`Kb8fK2QeT34x$R@gD2%-0P%1#Qa|>+OE*) zS}4?dkkzFuC1pSwAjJl-AxAOpNT0^;x3PQ25FhhlTJO+!z({a2eVwz#HL_8;q4e~Z zi|J3vEWDg$d~d>y;ZPwfc6W!jv)1~$;6gwo%>Dmr;I}u{^vaR9g`a!_Q-;0>u zmP<*q$)XPKuX4zk@t9WD#NF1YI$$0fcKDVR zIl4p5Zz5G~U2=RT-2P>wqg#)X0g9?E5BM*eFG_b5y_53Eg!#P6_8!@t?v#3RoZkBQ z*KuYE^KXRxMip%V(yn99S^FAvu5cy;TE`0Jtq7ke9{;$XdCF1EYTl?|CxgA?683Zq zNj{6r)w4%2z5}nCc|ONVtTADVgU3y`4umV|T&Rsehd<@elc05f18!=D28`DM%6&mT z5TuOXp(`d;3dyokee=p#iZwBi;-T!r#FZ&%86Zy(_Lm9&1E)SLK!nx!S=^1%lL`E-Mp1 z)qS|qpS)tDPtO{nuRm5El)4N;zPpRI_OtheLK&KwQ$R!5*m_5FvA{d}?>ZydYlOOe5T@m!c-`f9 zdc+)V+-z6j#r74{8K*^GDIJeCM@jmV7>7ktr1ee!Jgpm_s`_?6@W~CH@@*A%7Ao&Y z0hY!Rh||({(incw$GyeDl96)^u>xXnGJbyb8xeeMxj%ZECZG}@A?JkWKK+TqE5{!k zF|d;}71z-GUS;=F{o3bawB#I(uq-|Un6cFWaWF|Op5i`-ljoeb61w)r@?teunbRlDxHuZEx)nzGd6=mkhX7u%wNH}p?V3hk>Zs9>0T|xC+ zAG~}&>)R>z=5!j#A`lgtZ;MUqZ9oZy1>asz@=Ez8nV8m!quFY$&!bWJCklpmEopU0 zFj>EUbZuMTaZ;n;ceO$-g-6nvb8ClmW7wnUCbGW~siq*TIlX@FsZPp!*Fc4A75{C} z(t9T#{)l&iHv62CzWCs@ITlV?Ha4OI)Xv!)GA=e_nxTNf0uXy=>ta~FLY#*8mo{+fNL zQ^4Z_W?s7<*&XmnSIpxMVAUC8Ig;B}j;~?ejzd`v@$P-VmOH%;H?K#DUi2x_pBcPT z#g7W2%GACw~ zrpx>_GY%XTr>*Tndl|jSJ7+fc_II<*)-JVj2ylnur%3l264GAC)f^|nP%d>#=%Wmf`mEg^vHQBAp_gH>Q)$ori(gF*ZPHIx9 z7V9rbk@NgvdX@JkXF1Rla;#+aqIriq!8aCb%_sK%i99(Jqg#c>v3Q;nhS%UIIK)ouBY2P6#iij|McXB($v0<)+4 zQqW*+t|FR}Zm2P@j34#l$9nEIwLv_;Oevj~uicwFkwweyNYeOmZuX1^Q;WkXwYSxT zTyZ<@vGy>_Qor5y0T;~eTXyWTU5L;nnJ6DfAG0Pjy;z7(z(_+z@4*l*^oq{OHF>YI zf#CIFnh6lnuikm{;LnD?@{}HQXmI!$b{1%Bl+S6Xt+kw`b}w2rnMz4C?(4PeOJw4+ zTuu8QO}77kfve8)aikWI{w#9b9R)PdSPZ=q!ss|LND|~sP)ib`-ez!sz|PoRRt!Z| z-{Iry?7U;QwX^?5`|*IBkYMH@?79zS2&3qYoI)Q$Rij?Lm4V3Sz3cR{iHSz+x=ucQ z_Nh<&tLz6rWiTy)((AHteFDoWyXEj#F5Nt@$3^}u>s6BpA6|ZjpUahNBKP4oShAQc zLp7J%x8VfL30e#mhZZsy4X8@NdjX0JOQm-Zf>X~l;ekBGLbgoFx3AszDmEQYEXZ<{Nt!OLS1HaB-!Ieq_BMBBx<;&v zMJ-d%C0GBqk(Nd)PsVZ19ElHZHOC%zy=$s*pR_XBZ~q*)P;wj^supOiQ47fxtzli6 z#L;ROW#*v`n9~ckH=vQEk_U-o2@Mkltxv+D)?>Fr`w zRMJ@EGLv!FiCABZjDjl|OzJ4&H?w|$T8Xu~>ZkM!oe>Cy5^E9)Mt-*m*Q2bo@OJHu zT^fo?PbsRpkv~qlQr+1G6(La~K~Sh=?5Vqk2KUD+RuhSOc3b|&kFR)#rtH%vP5=jB zGB@g~I=E^Q;fshZ@ZEa+Fdi;h$_d+jQ!1bG}mO1*(YW1B(Z#`Io%loC&580j% zMJFtEmdv%&x}^#f>&d{#>2r$FA1Rf=oyoll+-;%!K8s5`+L#p;Ck7HOZ5}!i-1m)cXIkJ1Sf1BLgO7cfp(zCWtmIlS{yUhI=_I357>km-C-|)}cbQr64%d9Yy2sCV3 zK_O$zI0&~_LJ}Ua<#ZcSMN!*Y+yvhzy|8|pUc9wLvc+jv^;hNk39h7_bm16Kx>^ z?mQIt<#pGQb7ZnH4C>eM-*nYqA%qoDOU~E>OxOr0EMo8F3x-lS5p{cS4n~sfL3;ZD zk2PV}DVmwXecSACz=)vZ$F_B2@Ivu_2{Zj?%=EuJr~egM{a=Tu?YI2$Mf8hB5NaXq z!pL6$(XqI}z=gcl5Q1)GeQ`WsI-|!OtJlQSP7E{4_#sbHA=AoMyGC$rz1;s8wn6! zWxlS#s8^q$B_R!{np!P99I(NWt|&S+iFGVi^Pa_})ykg;X?LH_F)*6+mTH$^Kj9A- zq7R-b{$yG4n*`A@PW&S%-c)dWa;E)wgyNpBUBMm+ek*dCpR2BF$qv z)|sQd&~uto;=nX_`Q?*#`Jht@%3|=54liDOfuu`K17*R@bv_keDB0kO>Q6&`HL^cA z)Rg;}%N~@6)^2YzAZ!lLB|;t?C8HlU=a*&bvBegefc0b7!rs@|JUhXLI$nh$qZ*W& zNpsetaRkwaEVl&RbDWehd$^&5M@(t!Vr}Qip7SIuOljww&LBF-3rMa!!?c@AOv(`! zlCrg2aYP1k@_QtyAn?a|4W}=cubwh&H+s$s7w`>TQ;K`gM-1Eky6jV2qQAULaAhV7fLun$q+c{Gw z28$Jw_O9sa^DOB`o&_Pf``V@^{UV*-y5BBW{g|)@eLBU`QKaxhR^wJcpTEXBT5GmV zjlqLG1zK14Qe52{ZhTSmb(Puplg>Gqgm3BB^C%o1*{w3({Vb8sd6#!uk&MYA@1r+$ zdHs4PGY<)jGSwie8&SwBcqy&yE%I|*Q~20gurz6ZitpvQOB)~I%e_+ox+^?_hqpV5 z@J$a@7i_S$g4>SSM9Mqf5WYFDa!#jkEo|^PxUME`Zyt%3K7lENBH_ooP5!I?>;q`w zNIw_p1Ql-CVBO)ZS2){gHq%PYIK2ussG(J`X6zu;nx|=X0LR%OolzC z7@X1$SIte(>P3@SVC>rVipRG18hKazNHc7+>C%f*3x!<6K%BK|=&K4UDw6TY*szz& z^qcbTqw-BYMn7!Qfu~cBk}M1B9E}ej95EY#NG801jT&UTqf2tebgKmkLj7z< zEbAPfm?(p_T4qCcLsO8MCLepA)=^rzn$qaoD%O2c{AE{^&e$um)DYdb7X8MR4ek;)O&Tvy)jL{srsuy*o$&lRKaL@rxIqlX%cw<^#bBEeOKR$6s zt;iR2^(y~-;fM_-Em>H_=JGly|d?D6CP#Oq)uiNqA3(+~G_YM^RYoYFfjXBj^gI7$9y_42fOxCB)>13|Q4ZS1k z>eKdS`YGuH-(}ET{CK;}2kAF}7t(sGFh#*Z#A&kZQ9V@yEMC3@*MKX^Jvh21KdY#J|a#H%ujy58#Pg3FpZLO^`@d#ODUWaQo2&jc}_o$-J8ioAfbpwH1 zyg8k8wGNCl|FtUN4MGd?7dJKh#$%n(2FX*(jfCkSO9DmprU<-DZnuumytQ51aJ042 zhbhIEd<3+NO_pF=>6PTe?^njwcz?W4nzl=tA~AvoDuPLdUptb=-zi+EF75Wumb=ql z3b<%8%h^wOuXr*abE17#Tn(%k(&%7Z-RBk%otgh*G5V|f%zo!4x? zo??cw{OcY9+^;$Q`JAZh^Olz*^o0;6{Q3-7vAas-?JU~8Zln;fG*Gxf?0T^6>~vij zrH>gyU9~7+0hb;;1cq31w{EPqE5wF_KgM6=!@>Pe+P`W13f#mg280Bohd+--Z6~9s zn1@HOyROW3&GWQ+tcqgv?eDiq7&8#bxQIxmv$RrRYYRKBWgykh1g*ujoj1iFlTUc~ z?`sce$}|q0R#%);!-&0cs>%=Kf-N!g#y16#@mp&_KID6}g>KO6?7Md6t$~U!RfWFB z@|t)IaZf>@w6CWwD1*hYzO6Op^$SN2Ss`W${A|&9c25_wpKD8n>-N)iI={Bo6q7Er z(`x3|wlizUjPuuIhCV0?$5wDvO2Q+!cGWo8ai-I`4Pv@*-tbUi%XqSH`-Q%`zM5eR zEOGmTQJjDmNm^0m&x&y+Jt94O*y`8iTebE+23C4beb)U{R3wnbi&wdB?uYTo8`Fhj z%;DM@dOsm7u^V;`U^n!2>jJ|)AR$o4+n7-!@RV(sf<`wu)XYmf2{gU2mig8XNs5a zt#WwZ_GiN{i+zoMuKm`>#l^XZd=Ps6vwv>U^t-aVm(*ksE2iAb-8S#9wtKfX-f&rciHy7Yav~Ky3Phb|~u!iJENqM3oUKAv1Y6+86V1F&58%F!)hb`#X z%E@3DX))0ORNnD<&kJ+G-&aUuZKR}IXbz7m(rWp$=ryBUTslm6)S^b3ySO|Bf0~{y z>BsWrqxP{*qcJ-3$5Je(QY$-{fcCYLFu3ODyxE7h&*CjsZ=sirIrnqcl|Cm`sp{_w99ZUU9m}OE(eJ z7HyJr$hd_!pG*w0cbq_4AB1>r1?`-iH&vZQ$S7&)hD9K%>)qg;h+E-}%X~Ax70SL# z8UbhCW28Bm50Yijs-8@J4j<&#K|e_E-K;r`z1xYy8_etW{ zzw2r$#yFYcarRxK#~L!Y`w!^IS{$dfmkH8{68*SB1jj3|*iCR`+w5hgFOy(@zpw7* z)kN0fIS=3Nm7O|AxH#eUQ*E|@E_?g#?#8LKS6GocpnE5D+Vn*)-ejOok&!?ZnEYnj zsFS7UsHpO{HI>0Z33#%hN}SdSvm)+vn77yBx+U^`UA9RAlVtt+3o2%VLl}-Ao|me^ z&#ID1F1%~G`%7&z@JHL5J0X`Vy-2y8F>eOZ&*Z1H!3u}B6_V#iuV-&MI*vJ6_Aj*q z+p{BU2?Esfii1D7>-fIjRDMZ+Wa;{7KdNp|)^GG+BUL^Wf_qbuS-%LK(#Fvp6u4Tj zE%GhM>W)iYQbe;Q_p&MMsOK)URdZDNl7w#;2NaUqe3k~fJ@h2`_~?e2_zN`?!D{GF zB|ke5jB&|>@UOkizl4?CVV!LM@n0havRn`9UPtBnny_RS*I+rbuZ|EPmbg^uB9l9k zhH80Ijuy;~4F@VBuAL~ob!kiMp;d*M&Xy#z2T%+s9s0Bxm6JhHQw!7kOpwn8_9#MUzKlvh|S^$$)2C7Uw;5dg6ES zvbAjc6vGMVG-e?3C8Med6SuJ(j&6b65t<0ktPQpo`nWG+CzIa)OjXVzciMY*AS%b8 zb*W{dsrY$8Mp=_=&qIeWuPyF|V(gK@Lh8e0WcXr(m3S)18rgr6tv&74R|OHxo17m76z9Qhr+MwV|Ag_!h6SLQJcP56!+{p;=_?lMg6HkuL;@KLUKvv$FI|e z9SH3(yQjI>21n?6%QNrSz2#rm=jpO>)5<&jS{1AT7A;a%oMu;ym60C!7>5Z{_LlW! z*KoW8a!x4{YmALZ^pj#@EjU-5^>(vAQb*lP9jKeubUk#rgp~7{ePVWK@4U^21qxi6 zq-W>k*=~!8Fcj=(ty1~@ajUrqCDFL6vTF04K;zXqU;DUtHbwy%_K#uZ;7I6OO^;v zRj$&#U8QAziiQ*+{2?|3pUvwk+G5!aOq}w%%nJA6JKfXa$U)3<17Sx&63xqsR$CNug*ucJMie zGGPwKR2B6BA6yWrv0RfoQ{O|=SlWCq64pa9G8XDBZB5+Kakt`ZNS2WI;%{$5u2! zQqNw0f;rr0%yN)zkyCj#H&D#e;84e9nk(zC>{YppG6TFhaGKvc|IbxhC1B#3HLb*VV)^A(j6KAj2Yc?f#t>%g^hPo~~AiV*A1jK---C zBGpAry*Lc_K{!^TS!?y6i5{e0>_s|Tltd0as)Eot>ONU(IW0V}C3UqXQpYp-CFMQaS#K$41}+W`H#-Owd2K5VWtyW1k_^a!sb|FX)wehQpH z;Xx&3G;>6YQe7_?qHfh$zcc0d>4P25cbQ~d=HqM@S({ymVovM%Jm^$6lTj~Sr$rJ! zrbVeuc7e~>?+EwWqn*TJ&2Sxb`^{<fB@?=lvdI<=b0Q*$ScDiXwm1tnJx(=_MW% z9P`rwO8wTOp%dQ-_%~&KeFcD5YFjldnDl@ts7?r}2U*A=PsF~RSNhEhnet9U^a^j5 zm6f1|lOKjaO1L2{nj&cw{#)xo|1fVhZ^khhxj0(_&C1N=b{~aC3aM_okG&{+mm)z2 z9Y%bp=J;_A>^XEbCgYc+KfLdK(w$qa#Prh3$M3x5ET!#%T45IaTPFpGfS|T~Z`RTZhrJO} z13tbBQZ^w!y`)#+p~Sq2xgQAyDCaKKiZrXG#jRADAVM2`u+n2wNiUA4tUp$<41>cF z-J6P$1Jn_zJ@tzjP61-*{57)nQE19}Jte@}gLUK2o3p>(b zB!8SpH~5&Exw4m#jCBR(T<N zY!F_c6SCq@L`*9C5WRbQQD{S*L`W}*H1Q#sN}QnZf<4p32}rq*MLrdnq&^}ey{|d5 zpsc0Tzw+u@6G_QAQVwNklSO}({9vjSZdoM%y*FE8Xk<$PJlCv^PrP4wtoqI*6H*4f zF2-AhE~uob5*XTnMu{1hdXT!mO?E0AQuo`pQhgKtLW#ei^EhIPZ=iyldorIdWHe$DxTQX<0TfhxaC*Wp!%Z0 zq?dgo8mQ40Gt0cVLJbh|lh-qfh*&IB7Ly9BAF@#Fcy6H52o0h0bW3Hy`j_UCp9`x4 zz|;rR{^&{Oebs$Sjg6%Z4&z>r;!o}y= zLoHptu&}n|Bog|!j-IzwlflD$;1?O29_rSh(X40YmIW8~O4Go|!zKLyB(a!rWI`o| z5E53x<1elqQB8Byo5wIvk zP$IXbaK-vnwnkEsnef346edEaIgQ1TBl>d?y#5w*u;~}Sq1`tI3`t!8Lxv)z8!E&x zV3B-sl&ygTR^6EGS(g-p-lq0a3iR3UYp+~_wp~cGU}oqES<>-0F8|~wkN5LY`Q&VR zo~+swepZqe^nf`&;XEB8hSDZdX%h27KIRynKl8*x?L=X^5;hO45jU=Hb1T~sO?dO@ z+?tY>tKJ0JZJAv6;F9dv&Vbu;(JBTNe-8M!0xpJbjNFS>-8LO5bCUN5!H4Ei{*-FV ze;lq57Tt5Owd!@3X|+u~pj{34Nf$A%uT3ulW@ZRgYgGrf}h&#o*8U9_FTl}2gaVyYDaHAuTv9X z){;1-Wk;gy?xLssrf9F7?0$Q)y*|D0rn{E6vk&2`+JCIQ=GH$s@eD+MB5d10{Y@Y9 zTl53EKyYtoU!$11)L{V%nk&-fGASuXZ6)SkKrMGD>E@rl$!|etcj^VWbnNE4_!<{6 z1j*^F3_?q)%YeNrTl7p857}rM;aLkNFA7zn)G&(!?fiG6 z%t~5KeMa3ZbKdFvAl5fH2kyezTfL4uZu9PvABi;h7CmPA_%+=VV9qX&+ODyN3KIe6 zvX(6$kW#+y;9qgH5Mrtbx;eDbes&wLBzk9-Zn;~mdN;e!zMk!o!q z6KMrFXu=<_;fphUOO&pIy0)$CLSWN00xriMct+xrM@0pwOKVu}TD0^xO_@la$r&rb z`zmYgi<*+osrl;Qp)8@SU;Xg6b%llFIPLAM)McpHPo_QhaHIV8cL8s$H!Xh0NB!TY z|F;hR#~lPkwuksR-q(N|YGtM>CuxXJ_E%iU+zmKokU&ITl=L4?T^V!F;>sc)qLUBz zx8|ICtj7quh!$&0bB4G*`bHANOVhVl`9D#l<&tUZnWq%S2+(My8Rr|j$s`oxt?uT@!= zR8jxOR_`au(6`;cpRsr-6`@ZI98?OQDvo4~R4m=JF|G9uT;c`RRqWJVRvr2`s(Vyw^hz%g~@EKth|wc!@9s5WUS z`qgyXFCX}cixI`Gs)DKd@b6p=(pb*`RIQ;|LbiW}c3e}OS$ec$(`W?3-%`!MGWRghG z(A5bFtsZd6T4mr!R?ddUp$1X@>9F<4j_e_^bfBcv7ynSjd)*0#MAe%nt&eVL zT#UY*BhN!ya^~xNxsHh)jM!4~-0DK}0KPR`8at!l(=;a~ zx*nO7Sf(;-h7GOWr8>YD|Fd_d||t3u_+z(sX6f|C<^wlcasaX2x|~ zvB;vEP`^#o9y&X%!NS7YCG_JmT1QpsP#_VKR2F2EFRJyxN(>JI>R=xUTBwcG?{U2Z zWL?;`)i_DEO#*Mapx;q$T)T_{jjJ!zzM0jG=l+b$NhTGAUJf`DObDc;^i=F>(7rW( zSGh3Mwr68FmrF~RF}z&XR`LGh%p8aRI339$(uepWWg_yaHw-?^a(o?SU(e2CviV_%n^W2N?w#=KwqzHu6hukQMC{z5rncxbHE^ezUJ)|k0TIPwKZ_zvvy!#^rgz@ zy}ec-`ZU^fWPGdAN0CW$J-0_{Y$x8;?Z_SM3eWe}Zf)zetkaPT2xB+Q@smf9JB)}) zISmJq!4NZCbPo$Rs$*MOpC!PX-G@DkYa?iyz=du1n}SQ#o(FJg_g?^#dEkS34Y-u( z0qy+J*iGstI*Rwn-qXauQ(0a8pDPjO?|*e-i;+QV=6?x372_MCHVK1a*LR0*je@>D z6KQ@=zgu2ffLiEi4kU}dQsmK`+PV0>xp_8~#S<7LLL)g2k=A+yjd5PO4YqsFV*pFu znhS`M6P(A-X4@6s-G1Vole_C+Jt+S)s&c55#X|>&$zqO9p(n+Gbe^sW z*ns(z$!+yE4)4t$de?pl0-me6&nrrF5E?Uw_cU4P=5edhzCK(XMg@ebI71?#%n<23}FNtY%j1o!LFTHP!cj{rQgfT3P1lYNyLC4{jM*Tvt`LQaRuM6aDw|RJ$Kt z$gp-f>(mmoR+});#$@VhM393gFK2Q$@Amu?TaMD7Zx>ZLSiNU@izBK`U^!jE+8;i! z%F~SeDeG<)Gd2rrR8ak|$9Ft9pDo<1%?a~@=f1_ZH(hw=(_6QSz4&BFFDY3C zO~#GqImnhM%f!TC&%PrHRv+xGKiBssj;!)@EzRT20vA`wml8q zYQe{r1Weo4g4Y8Liv9<4ZynXf+pl|5pcIM}cZUMSiaWHl5FCmJ2<`+Au5ED(?$Y8A zBv^o8#a#-;-QBf?!tdnS?>gt%`>eCpyZ_vOPS)hk%w%TW_gvTa`?(rhqTev**eG+c z0)UC~%$#qI8QzEipC8)GDG`xX`ZY)PQnP4^-(Gh9+`ZBN3BFHph>m*WfII(l(_{8& z=Znb-_b1F(c#30@S_854m_GZSFJqyy{38PP31OcqbWK-@0%H=ZbY|@~z$GJr&r@Eu zAVI6huJ5gCVn*_~YK<0y>C2IMAUDBb%v~v7ZN-E+r6d~!;D(=4CLu05j>a%=$~{}Y zSnr|dJH?!AYY2&=?&_rz9zEphdNGeG`)FaRUhF9#9*HDZqoHx;ne=jU{TCi(7!!7exDq^Zd$_uGb% zr9zBX(y{3`y~SOz#-F?EsUkn-{*rG^R*1qGhWO{XS}fSBu9PF0mfrg0Lp`_>D`3TC z<@vp;({TY`CS$^r2;zUBd87AUF824T_Suzl)m+dSEzo?7%Q^YN!?Sv_c!$2FS=Apg zWV7MXy~eX2yP$?%a_hpa^6Vq`Kp*YAQG9Y(>}QLV(o9NK3&!O=&hu4W{i)XF$sr?6 zRs})T@##}f=Dm4@<^ZWsO3||VJdj&sa`~?ED``1VR#&)V=~H+e4O#SV@Q%dOwuVpJ|(uOro&K`Mui{+L>pg7f~|BPbD@6M zlN6-eKg9<>f_IzC5F$k{sxyv5w|jX>l87xf?q1>7EkM^JRb40wB~lwPI@mhAD06SF z6S!U6P_x9?!4s+FlpKyuw#p;%zfDwa|Ma@14LWL}3oi0>4H1awd*1B>=Q>bluFF5O zMq$)m2TV4;QMELy;rcA|F@jTxbc}B@QMOy?aI(~E+CTe|r8Rih_ZsH5p4DFq^AV)m z?vR7y>B|CG{PSzTT|T3up|SH+}`2%PK`f)n1z^Vk)^>GJhUpG zZ_8HfPYv+7Oy27vSQnx&xmubs6TO(%gih=nI<^sC-x6|JI>~i7 zI%2yr^`Z-{yNsFVc#aKw7%cmvZ#zcCt0&qsvy@gkJVd;M)xlIKyYkdLyvSw+%!mpA ziE-XuIYHKj)9zPr=(iVEGow+J#a82JHNfUpEe+SEc8d`;)s0X6X|+|;qC51qr@A%+ zB|W&c$Dg&j6o4-xiRVVS~ z0>MqsdojdAKQV}5Akv^4T89nwV39-o>8wprraB1I!*HBo0Q;Q%iEaaUb+{j?x z;>LYdQ<%AcNZs(KH==dGTk_oKr9%i;%(5_QO*54Bz}A6X79dwHTHd&btDs$72`SZ4m;bB6Etgo=I?KNc)p6}ZFFc!Bd;B(uRh&V$P+?YUnQHXEz-Pi!lPm0oaHPKtHIe_tgRoe;tr)J6ALpZ>~%9@d64AwYZS;ma!VYi zV$;e;#DE$^%YfZmC4iTOWndfkkzQKRdq=JT9%$Ie$7%{73I!f#uu&~?OZ+%DqDV0R znf}Sv4vZORX-E*-AojNcgju1s~9 z*9h4+<8;$^m`!+iBlukWtqwLV%=0_C4+uBK% z+ydO$wSGyo3Noj>5bgvn?KUq>Nv{@fwbSok6Itr&Tx%^FdL!fQraQLYqb-vhywTdj zFH44g+M6u=5N2@`BFW!Z+oViKz_Ij9F%HWM6^EH@_EY)qV4gR*f?p+=Om2HWUOuuz zdEw2@;3A-9)UCrpAO!xrsn1V@V=IO@C0>I6g$m8{&!Q`Z?%0iOI$ne9gJZz^A#$(c zwu**yHnq4i^o$dADHmp_zt5{nVA4Z(pJo{{V1MwoopQsyW#6hYTx2ci|CYLBeZ5`Ht0Ssoq0S5TyNnx-P&4wzI~urDDjk?@2X=X3N%b7(@Y zGnhzo%6MjkidsA(emRFRH;Rj?aDo$P7ls5~ze) z%-OFgJ{3Xvaf?jtZ7IZgu7Qx}dT7)8*Vj{)KJ#9?J}YU1ATYVm^5w%Ug_~tyilHx@ z{42XrhY{@Tj7^%#ux@rJ*R8B@Ub;iu2B8o?jEp5@&4{G|?Y>n%frr%!l=vD_zjt#w z3pycBD&ah!J(Tdt!T#A6_e0M*I)bR*a&??nHZa-x3d`M7FZ2bi&DS?32bzOAmZop4 zQ=DY+LGLRV4 z7?-rAv6$Y2Uer6WJfVaEp1~}}H zKdkLK`hGkY6W022r?$_)_=~Iz0 zBCq;lAe>SmtkSk_dP*5>F%_*`%NDRoJQHM^&q+w`Ze&u3gaOab5Q}&6qVMU7U4OA`2~MoHG~_KqQt?P z!v1S0im?Z+_*Hl=3VEFhz^S}dsZ1OkqRGsQoAwqSdkw$-0?b>rc}T|=N60A2QcENG z!Bj%-HY&o#E8_F$UmF+jXSWflCiU6J%c7YQQUQLTgsZfXQVQ_0SXD^DRpcmRwiwuH zz%TEX#9QQ+e#}B_>HO&Hnb++5x`8NkwS6l~3bB*Evs{H{9cOp$n1HxOc|q)4`~WSw zUO)F)PT4AGbp;XRs*amGL8U{t6M;1Ba;nKXRDFjN6&pDc2N*KA4&uLi^>=JE@vyxNug4#GY;-|wv{k1Df^^?ev&+cOJFSIrH&iuqL#V^ zWFm1$Wna*BV63Tr@XF|QC;kh~;Ay=*+^T|LlfO=9Rs~Em!lmABSP%DU$eza1!L6}C zJSF~$T&B%TP;2(@6QoGUBBjhepk^W}eDUm>)3JVrF%U+{< zplj%hw0cSw2!HYH60u$ye7^1;(xcAxNm6sfAg^|GuU!#3BquBF_fQ%s)o6+evug49u}QD!9m;wpu;UEjfxeqZ6bCQME!dx9Z0c z%v+C}C#C6doTxh!C;JX)%-njO_R~u{HM7V~v557~imM+XXAGKq(!r+XM9aTy{y{sJ z^fZ75E6?7${2t#5#%d|@2u7pV%nb`5ck3KZG~T7R+?DkF6GY5^7W2Y)_T%)uL=}8x zrA=o4Bu}@o7XB@!f7D?m-Vh`oY5>`^yc*V;u z!W_umb)&mx6VBz4S1`?8G1Zf%S-z_fz58Yj^k^Dga|9jE0p(M&5D4;9r@2e#5G3a-WY6->4cyQeUci`l7SRY72 zvwz+DC4V}ub60^-MCX-xd*n~hQH>5>KZ)*`79z{e#~MoOLD_ z;;j6znto99&=gEirK^7ZLydi<^|y!InacH4;L?u>x&IL#=|G(FXX8rh8pD7T$Wba( z6p(&ssNJ9~o^^(6+_s(EUWKNvW}NOdGfYQ#T*QvGWHC3@Nc|20r-fd-SSku&?`smp zJBY_q0q*dRA-bsSJxx!IDy^*`+`IO-@sl~xc~jXDk}LZTNZO~A3lkzA4YFThzd27@ zy!-C$Wlq+5U?7u4V^I+rc!L2aDvbKPd_vlJgSuTAYRX{I2axOwkdA(c>GLuDimw*F zU-7zqQ@mgO2zr$+Eg|tkaAx?or@zT*x$E=s!5_igH(cTZ;%%P7plhAOtzwE)b+X~@ z4QYhVou|&0GuH*(Yuz%aK*gVZb<>e%UHJ`}f`Z2?QMIN`)K||drcJ14++orq$C}iz z>y5xVvs>C=uoM4(*J*{4CHWD^G7i{Z7D(&~P_t zPAD#txtFLjOhLH%c{N(YIj3dC3B!++^-Ca4UvniiSDHC74Wwb0Sl-P?Z_26s+3wqH zt>IdE^=bStJOze*pXKOHN_6Qd7vJPMz6V4Vl*5CF!UiESd0clwuVBOPhOR1?M8vjt z4T3b%6kozVFTB1fUU)Vg8U5KarJR%ex_}*jLrh(odeaOlqB|rPP#) z3*M<`yWXTqcve=1VV(#;Cg%P9XJBTMwK6Zx99(SM?}7@8DZ0v{%TIlLz|davhR)B__>bV4p1fZ;coHaE zQ|nYh@i85xSgh?CHu3$fBA-bD9#@4OYLISq>BnJ?dH|~x48h9vA7VH1 zQ@$tA->h)^Z?%K+A%FcFSU_datx#h>c%n>>d5~IL(UeC$E!5sM{Fjcl+6?Xx4JVLh zj=zb{JhFj=uFGGg?(q5b?-SDIYRY>tMdDp>*w`0tQM7FPVDv&4L($dv*YOj`ovz1t zdWs%X&tU3T%>I8_Knnk$y()j8K=y2(&MZMYa*Ch#mJRadAEaOo-}*xa zzukXmMdjWd2K9ZMbaZr~H9Z3&wO5>?Hz=@ zg2Bt2JU3jZ+^~x&Ugr46E1Bt={NNM$xZke95xVcXBL-6uy<8_N5z~QDzhB1(zh-#Y z4Xik6wgFu4)NH|@?w*T3=6P!VW&ay>%#V`4Oc*q8xisYYJDp|}o^E0i`5be#yYXCp zp|PJH{^<7~gx`Po@vk$K>C@r@ zhnuhzcmb(A3hx*jymIaEqu=}A1NHu;=x-iic$j6cq^(%xf2Ue#|JODk`X97+@PE*b z@4waRpPN!YseL=6x`n5kWqu6gD|o2ri}l>ndDrbfSoROvMOg4ZXtvXV(ciw#FD#0o zz~VKW-sVUWDRNdT)W$lzbn=0^|7=5k`#t?EQ>0(beSEEn1Uob_2=?x7^g*AbR%JHG zfkURZE2x{jRF7dpbDPg4(t-um6m#?X9p=T_b|DIQ*>`bdakiTOm(Q<1ILsv>?dTlJ zjJhib%JoGH#I72n-`!O{=ucTRK~0D`bc6Ro)PTWZ@d=vwy|t)6=X^0$!9#(;d)S z2(n_7vm|L+QEO&1R1uA%IgH-I$;VDN(8n~#{5jAR-S_5eDG>Rr0*VYOyXV~0y_XEhIjDBHqoQtLSqr)k!J;6T3b#O@*U+M zQKgl~@5!{GRy&K};om11OmD0rm!b`b&C83CpuW_V8d*S7vGR@nTYQ~4Z3Dh=6!YX~ zu7C4=S^)7g$zqJD*7x_brqn$&2E+g`&U!asqa~%N`%!G@}DPK_#*bp zSG~DEFtcRA)rB!I;BKXs3;QkiS0{ln#Rmjb+$p)Bcd>&a5>+}QOlf!s@OC7WTanFr z1`=MJ2;`WsiuzPoAXdWkIuZCQ5wMAXwabKQDEHVV_B1XXEVn@@!hx)ZD_O^Axn9jc zbqxqF4HdQEus>BoMNx;)T;*ql5T0mkFOlaIJ7&mT;))qUW%5G9_RZFm<<8l!jxP%D z=iX`U$`^BVRX2j4vIxc?B^eFaxC@iV<>mz@oS|y7RhpY@=UyN7# z(;9ol32D|73$s>Y)<`yuk;O)FTN;q22~uiFUnzIqgyWgZ+dhl^s(Y($lJ3J^m^z(& zs#)k5m$=Z5%iz$z*8)0-C!<<0pxf^r>B!;l_4bezQov*$q4fgL+TatJOmD{w7hJ42 zyd3&Lb@*~TNzTMvKl%`&NbWir&TSWHr=!?qPFw94HNl{Dp7Y}y={1;JPUJnvkz0>$ zj!>DR_PuR~?sOFG_@()sZt7$XI-jL4R_<|K`=(tln?E^A;J2poDhP=8musfcpg$Sj z2p0hT-A^V!j$VJ1@w3VV(GSt_6wlx3YlGasB{gtXLsoa;yELWI(X+^8DtaEeyHlVL z67o$ziVtWs`w?+g!AoW2B-1*gSwCP+D`13up$BG#r1{&%DEfaT zjiBQ=M|2-9ej(E>U!`H8yHspu1=mg;rBME5`&ecTe7_4wx<4R}8Aw)g|B|#Lo}>x& z-4;JuDV!l`52ocTo(aGyQyEvfqmYCGd&k!mb*FMF3 z-loRiY-cEUjX%D#>?e&~|BT>TZCd?%{p8$ic^^#&hXSW*Fq;vmR+erwb>|gHa_dLt zT1u<}AJ2lTQ#RQ1vF1v30&4t|f6!jbS{n#ovEV;G1H}0$O~YxGioCrNX@+Z6W#fp3 z^WJ4%KN$9Ds?7?$@RA=+Cf#LRHG2@!EK#Kb)FgEe*<14zmM$p!-H;ZY`b{aPQqLr_ zky@*FkogZtmqq4E%qpqx=K&`d)*CH+ip8&yyOl2#roc;mvOgZmV5+|sO06hK$dUrnH(i&&9jExk@IhMSZ$M@{wW z>@Aey_O#Q#)9#U5ar*=MO3$AoY%VvE|Mp`-D43#r3}VpJT8h*!m!{=BD6c^xx?A`< zPk&N5`n-|ilA)Kz+7$a@sp#G;V6Lc;bE5$DLQGn583IP&AH>D(smp#9!zvD@56rBP zpvxDwOIxeo2f4R~KvBHN@i-Tw6_UZ-uLcS3MPjwhj9TV^`Q5`vM$ukSMF3UzWm#0E z*3X6yMmB>J8E0~9!A*TEjc%Uo%7ZS}&6S&1A0MFv};T?`|TliQFJfPYbW zfTv<)gJJAz)6fOYqA(-oYZhhEIn{U<9i>R# zzZQSstsMQTdCD6yQa*Hm$CP>as=$lGXLle&3gWyQ+9gU_ie3b?1_A(azGIX3Q=^_A zWOJAKCs>o!tAxt9?X*;0{>%(?HLWio{2$0D*iL?a^?^RTN!sEY`P4ndGlO<{ zVt9lfUunMv%M=;#t%j7()PPlY*BIC+sXNmar?PtW-A9OFr6uAYfS4hAZg>-n8Da-S z`_quTRg2jvtzQG&^$ilD&n)DlYFgtOf5C3P>m3 zKe`x_H>TIb7{ni)be+wP0C&>0kF1t`@7^e~?`8Mr${QIpu)u|mims)GZ)uLod-?Rw zZ0i9xuFMFM1%~d3yJgn@OYh)06`U!_HHPj z(V2Tp60i(_;q^7{p1B-(;|t_?&HNtwTxy1>uiEObE*m+lkt{07&NREV6^u_>ze($k zlB$mG#eT-&tV^AZw23YyFSpi}7M2Q!Szrvsk~sG7l(u;<_Q)Sn+E9dU2_;QWYo+lg zrb&pBH>!`vF^!AhvqsFDJUnYQjA$jBZFTa{iykhKpK0(MR5vV@ueUH<{so^s-yKKNqR+@pg<|oUzmx|uvt9?O z5O@062fKGkwUXDCXOP9lM$cg~*5Vdnezrtk2p7lJ;_vxJ-c_<=a7`>O9{e&gs@clj zbBjY-liD4mVIXIBiG;d2f7!kB_UV9K7$r;%m1WARh);2EC%GwEW4jgNwy{3zfnFJm zoSJ`qZa2DP#qJrdG`^ciRMtC<+;ls_i)-@*JQ&MfvZiLse4_1*AlcXvxRR%?vTmB>h%bH1&5pn2?qhuNqC%S8 zmM0{f@ed3X8+3eZS*+}?kv7Zf8h6TMvZ~zl0v2GwEm|uDhkOf8pn;fo_c~e6X?jE} zQXe=d`r~HM(0FspBzjNLy1+)mn!G7|38a&(jnXw6Ga9uLF0Mdpz1GiPS6itVTwl5> zWAid`b0t-qX>lJEzenZfMP8IqhI(-eQXLf}zjBfaN5CN=PLP?u=U&6UCR<5~Q5)K` zKPKq7g{G5sELAEAz)ntQo6S`sS(swg@QOihCr9gv0P)PQPOk5pU*R!3Z}s{~-BlVJ z;v`6!2cH3VE7K5degXcboXbgN-)Zkah9eTwlQVEMo+`7qPQKSWv`YwtzG+RZs+!NJ1c z{%fw?pAD9Jn#$-b4}fuL7wb~|%&J;(!l{ekqZ-_>7S^#cw#19H`anO|5~6qD!ibI` zTullYVj)wZmvV25BTOU=^G`j#(9un1Q!+FhbAp$-pvnjrEQ9oxO&?cKGJggwY)@ZM@#`~N3^_0>cah%Wwl*PTwcF5#humWhYG;)*#=^^^CP*@ z`1^#Im_w(|DszIj30f-LM;RnnSq?Q7<&`8%>3YXOs^KiQDS%IkIqbe1lYXE*yvVf= z?payCNT9M7$}_ES`}RS!Q*tpT-6dtr9J5~>?A^9Wb2(?ptNf3a0TCY>T$1O7A}DrO z3)LI$gx%txHXokZG7ISq%-IOYyFOXUBYuy+S8P7ZfV|9pIojQ96STVHbS8io^qy_d zaVX*R8^NF-T>!#a99QDohOAE@GUlH&q9w86kM&QG+s+k9s$AEFWVjyZo?RhfyYJ+IDuVr#7;N-`i4Jyp*U`xuk}G)rLtFk`M4H zk{w^(3#dRbti2EjlDgR4>CZV zqs=FIUMxt7yEFHK~Yz`#!lq8vXwb^edL^S_IG<%?-FpMJf2N-BG;bPJ2%@#5ga z%(AN|!D+b7Dq_T+Sni&ynTSPCEmb0KoD`_9ktAV|^ty-d8Trn6uYGJ;f)iImoLA5 z_7B~jTF66gW5^2yI;uT6+RE!4)@y+k{ItIQg;DPCk7RBdw)3FT1a)95qd9qcBc#&O_jZ77Iog0s zn|TT_G*zujV48k^7nd|Mk#0@Iq(9zko>s!F#Du#8rJ>@P&t=)f^L5c-W<;B!RYF`l zgFNtYBtClE zOZayX0bSpaqv`I$CrcyibnH2Zh5VoZ%ftYal{Y`v=DYx{5f0XNER>CZH;8>xv$f*r zTOM0_TMfbM3xfAG$XMSRNLZ7o2o;rvhy{>aL1&GShRHL2_}REUvUb_kh-twVT&Gr- z-lF;TqFE*_Q9Pw6Di4fybLI+H&AFPU3u|4E~z8hK}WO zIdht&#;1j9d3fXfSDCt+>HdT79y}{O8uYk^9hSx=u0*RtOL&W~q!@?^}=0#%lmt)SQi>D>&DUf#70T5Mh(NCqr zBa+^hkNyImcseU62o_t9Iw$rD+>*a#eKt}TSaqiF)HA>Gd!&x1Zk$Un7Qkj+_ZweV zj}5G;l!g@9*uEildt4eWU6Z%cw)knQ-E8rKu#$n_aF2xr{<5h@Ux_eHV8BybEX2}+ zWwO%Xu&tWE1x?`4ETBC*_Kv|q{aA{y_UNKG@)H?=~&V%wJ3;tCn+@2 zI;zze-sD*42GrU7RXcamr>>HH8l>0k;n2zr5eYMf2#yL+(Gumd7AtWvR$BRd(PU4d_lSv})*|D%z!@Vpyk2^U?<4_TEy!_H{th}fplKOL!Q+-i zYFt#?t*%T=go%RQm2c|TOA#+S)iuND7?8=5P?u;p=Pwx@O3}pfwlz84a!<0@XKGBL zS1Dfz@TGM={puf(?pEE~UgiUaOGrCqBxmk+Cd@XVUT1iLc?Y>H3f7f1qKy_BPVnaI z_vF^_ikz*>_k-JxY#Xf(x6XOcExP;_{EFdv)nwYnY)I0IC6Jc3F~*&Xv$kcH?1ash z1Un*CPw%7WXL_04S3&%>lwCYD`WWm9$fDlg0wk9?M|>246w+h7zdmU+mb{?M{tnLO z@Hdnuk6Ghs7@hqp4}EZNFlMiZUM@KriS$1)y5rP>j~p(TjZY61o4PFp`gc?bMT@P+d^DSNHyTg z1p6nzr`hm&o+@zRS3rCB#uyL!daffk%_!C(o%?ZL@A9*1iYB^rQ6q|>+o|y({{H>} z=L;j)-_M!Fp`)dCHGf^026^4_%PPL8X{f|m<1HWljjK7n7Mvs_w=IFF~Dh>ZTk6@qYHB-{p0 zxYSDz4evSW5m_o(HZ$e%)Y|OjwZ2@<;o}oT)7v)sY(2m_UbW(I{EY>_JL{8mSG?&< zX)6;3T6cX6hkQpOxjAG!QQoZ4jkCCiQ{=G_h=v?F?&ZIa-hQEIlcXTz=}k^cPp!l> z_me{G>m*o6h;M%{H7>iJ_l(+U>C|mmfs0O8W?Ele$^Q$l5W&<;v+Bzz-vFMek26_Q zb-PdZTn2gzBi0549W@^$#AgNltXhdnWFlR`-<7d$-;nSn{Bs4~=PFtt`@2U3x4@4EGM)WJ#qQ z5Q>K7FwxHJ1SSO=4=5vqB$@k;)zxph6$hdEty1MhqTPxv}sv+m8^5id{~p^sptt8KTS81?o{#{d~4%IyGKvF@bhNf@>0j) z>TaOAW*{5_T%M95JG#g})F7bv#=u~Yigh#UUMAA}`Zhks7}aIHdA0SFCxrO@xhiNC z;pS+Lkj9QVxeuBvH9%l!@mPahx?D3p%AFrP6mNZl-w2214y{-@TjsAAf_is!i8@lx z4~@+w4!sRJnZCP$LS9Ofbai~Q*I&H=-&2p7ha8M*sKDLhR^JUx-jSte*;f`U!f2H$lb{_aSh!2%q)Ch`MfHP zzqfdy^Ye3bXqN`V=;PEwR{ti?YBkz%Wht)jE%Mw{`O#&0`pt{RVU=eXx-J}vffMDM z9dk`(uO5{vzE~E(W$5P`Tjn~Riu3p|TzcV+&vXNbWZ-o=*Z1#ifwUusWE0L{t_<|J ztuC=^Ki$Bh$I}2$XrCFr+dTJI&O%LTS|2}YsladEz%>FV4KkOnE&1AAM8*?^U1I7o z6Zyg+Wj~7EX(bcZ!!5`^YHkAjsG~bVudg=NJ5FnK22zW1kDF2?2w%>}^5?PaNKi+{ z3^bN+Y@lKTE2`PaYF}iX@~ymQao6jgO*NuI`95S)(l`V3XNZkz@ssBdyp7BlZ!arr zmh-fPVbkvCIq<9dJc$Fo$TPS=zE1NOv$ltO7!}Ee%bcwbQQ{W=?bKAi)oyLBSt$OL zqn%l_etTpRzKz_W3&-kNs;-=gHmtn(=ncfqpO<_K&U@W;Xfm`+>7FhI9z179T54V% z`Um)gHox-}E2qoPp%7TC{`gY^JJ$)w){RX}TI8Pv9Mus(iYr`uzGVsTc}@GMBpO#W zb&s!nO~o!Kw|Tp=;0ThbAF|Io=z)c+s1O=fous735wmiJmn{&oYbxd8@U`Uxz7nKc zh4BZ4kEe@2I#g+Bb~~sP;iX_T)U98ww?!25HPY7=Lyu@TXMwJ}8VE4mHPtO3?=5>O zdfohi%;^(q0wLw#-jBz6>$-<;-b*Z87MAx$uPUnLyBuCnzWfY<&mhKo>n3)nPQ9Q;>S5w1^YEP_@ec-N93+#v?3?Z?Ylm9FPecvdDl(jET zGOhJjj-|QR1@yOmx0~^fsJlm6Is=xBe^+X$&9uyRMEA}nvJP59id0*KwrR5=QtEd8 zlU%G7n7a-3Or0(tH6y>q3~<8Eyxu16QbG-GEsiSsh!`P^({|7b*jFV$h@kndf!bpV8<~(}f?g zy`*8$*gRn4<18qIHmdtA;>#7~wiP3Y2z;qM;heZWPcB9SWvuvZ5$)F^<#V~40H-PJ zQ&RK5-qZDF6Y>_X6qlcE$KF;4p_sdzr2-3VDhHnEhiQ{FjMo`FZc!_LD63u9U> ziDw8jJ5V>fv#8W0a~jshV@Gy#q|$Az&vb!QH7WX*%Ko(4dCM@q(V+t&@Jln&6atVZ zZW$**NBcTdfmrfyPB^MQ5!C2LO3dj60ZS3pm{CN#N>y1V5w#X%nlN_PPs!zB4xC`E zA;E0dx|JC%4F#s?(zgbI0@*Q;mQEWvM;7EoR>`wJl=sP{#k~%1U$!y7)zI>}=&yec z%f9F+cCnlwj0C{oo_`RBCSf~%CcW%4*Pfz%;^&i=`W$-(Zw+2h^H=H#V_mkkiE@;U zZ^csxm#^o*5fjJ)e6^JHc%5NdjGg3p_L&Z|L-P+xPE@<23@QY&!cc87B5f!FtSgZm zw$WCN(AB*ycf!DE`CB|LGKut@>(eSYZx#*Ytp|j!K4-80AdocGgA51A`QR1H!W2XB z`pp(QR8K#R5npZQ(Z1z+i`Qpf?SC+DG&|7D{^_QcR zKT+s`zXXk;;RWJs*Z&Pl%DN2j@pa_DCyRwt0aP3;XLWUI#{Cb?(?IN8M+fYr1kZ|o zbgBbdQ!RYXjoFIe-x=^X;sR;_F2a&8>`(rTVz^Isfoqj>)T7yEH)4-sT`l33fW3@4X!>C=md8Q4yHRa1(j7-4q0WEo*kOQ>wxv9-0K>o zVMMbSuPMUo6@0ulAlu~_Pna9sbateY`)gtuA1fDo#2|sbCrl`DRrgSxX1zl?jSRXj zwk5cpN;nf^TF;^ufng3i;;a0KGr+?}_h~4r3z860`dRcxq%sXGYuKTCTlmV^Sz?J7 zhx_xn&I}Ncz@`wx%FEo*|2o!!ESX;P*@{fqPT6)#9aNKL`KYny^O8DlRdMgZ=9g=c zV1o?c{K2wIPrK8sG-67mncuyCd$qBTd~dKWO=o^prHpROd~;qlx>L8aCYc%_OFD)r z5w4udZ#=^&f2a%ivtz>cC&!+Z&QgUN_cJC*KBKG1-CM=3bKmtMC;Pr-c6}|b=+wHwU6;bwFUTC+*Ys2*;VvKSSeL@r2l>v zkIiPUjFoN0?&19LB39_T@2*!Za(t|P=p1zllP(+mj4nzF-At=ygQ{W2lYdUk&}OO{ zyVutO$=2$2Vo&B)GrW=EFEX}T?IR}ZXq5~Y+;UB{b~i$OK2@FwaAI}Azo9EyJ->{@ z)Tq^>EJ~&W#?cpCM@MryL&xNX%Yuk<$3_wi^4t7bZFpaNk(yn~7e-K?seI3>i!N^_ zbwgGO65rjdz3y8SYKS`-b3wMM-ujP=q9;5015QYDuIj55d@*R+yO;rinKhsvv;&p- zf2Uo4&k)39^2lXeXaycHCyAFzn*@au)3CITTkH!53cu*4)K%H+r}0jA99Y}KA3Vja z9cT#-`)G2nJWnG+Z3VVM;ha@o;Sw#l5IliZ&L10FquLFub;HMyI>RjZ;ileUTbkR&R?t!W1|wzrCH1@ED_`UN>|-gh zYQR`)MFP?68kt=jn`AawYU*aAz2P>;wxO~X%iprn4+Jb3x!ji8cnjsd_mi5FWl&r& zAa(V$6a>-!F)b&so9t>e?gciPdkV!1MkMR$sPd$699Pkb-^rVeaN_Vr6V(}8lMpH~ z<6OYd@34F&K7=JzfdK_a9)^Yv;Sv4RTb~F90@`q-{)!q6FMr7L*KMyF-bKt&qyKH> zY3w8b&CRI#q~+sICH+H%I(hOH#0F887KvtGPjx_67O)JJK)JgDX6PJIEQ-hl`$$SoK z_AeMlsrTgw!TCS~HFlr<3k5cs!f3IqyWvCdePUVLhl<|;TcmCqkHD_^HK?0so}`iW zR!N^JPIp1)1xd7A5Ji^ApJwOpqLY|;SbxbomS_7E)Aihbc4!cA1NB5SbFSvss3k&s zs!9~f>0V+I=k^dYGd~cEk6(ielT1bJo3FQ<&-WgVk$T$F)5om0hMm&pay18|4hFtf zN2JwmXC+&;9Fe+#DN$}m3a-zqpOGH1l?W-oQ`8PmKk|H1=|0bzAUa~@KQY7q?O3R! zIyK&wi_=tTSO3_Y%S-lkEk~n1m#7Nwc}f{#vKrfkJx(}+oiWqem~<>n2qMRbjPs6H zc9^Rdj==w`<1>&wG$-~#$WF|;p61&d#8qsO05Pzlh$zX#B-GMyS3&49(gmFNhmBLL z4j4Ies}9yr=Nz)qB){dwTE5YIP?(y2Du!p`dt~yZ$e(u6c17QH@Xhy+a1q9RlqQN? zeHm&(zb()C_RRz$H8EUL__rG_=^RnEbM0WtKPq~Qk^fK85DXT4;4Q~snm5`~c= zZkF3w;dQtUvh5?$mjUJQa#xjJzl!d7fl0VJ9cO1ps2-NUQI*$S9P?0Q;f*0tjv3FA zQ`W9HZRzuO(Wjf8|Ltx)uW!mPmab&_9#-x|R`Op%B!h6e6tQBQ?XQNRF!x3Yva;0% z^^=pG9ML>S2<0P4L?3Z#Ti~s!;&nUE-BSBaC^iI`u!7BB7sY4wJUIh~?Yfm3?ud+| zA&du8bs}$-+X@_pAa!FS3nFs~d#j|8nDLf*cM=bmEUA?Ryg!>)KgLLsRQyPGwiTRk z3FnHzPKKi8Q2uQau0m&xEbGvk)}x}n)_by+Zfgd&3@$%C_>*Pys5(QL_aw&HPS2X= z5%or|i~lX1$RC0)nZM2OuB@HDSzf!CSy(e%*8iImsONIwC8Z#!`t~F=?u{SGOt`dQUN{~P?Er7 zH_*V0Q7uR-stUnL5m%ZJnzT(Ym(`mPAR5#B3=ptzQevnyRe2{g}&JB@u# ze%KRCEyx&UevC-8@)ji(lUWD7pumz2+aafL!oJ98E-{sD5_Y|)Org{@z_rBUZc_1x ziS5T+TwsCnNmDT^7TUcC8;FRAKh(iYs;BSuzguLN9KU#3H8y-I7}(a)B}o03`TW`^ zOy_vfd38I{?$UU2#4$U}jOZJ;HLc=kbuUhWuGkzw!XG?b^jQN*X0+|ePAGfiJml;( zwFcReNg>xSloa+Kq8v~R@`Bf26o;FQ%s`3$@^zT+ir~-(_$jOW;ODQlnO6UcytfXD zeJ_a&g%8@%pASEEyRtcl zzI3dU{)1Ga_fgFVaJ0vBANl=AeWiCv>LbJ4+$!zYdYtV)yIh{s&35^iO(B zp6-Re>EASs-`s=}CF_?h&m7s;CX4}UU0ZIC0O8#x`Rk0J-i;fW+lWK#{|8UZtLY!^ zn)4WnsObJ+arnQ`h5i5LH@2EtTd?PQX13Q)GyjCQ#ToKR0+W%+TsTBQ-ds>HKmH#i z+ZXa%4dMUGfX(cGi>Uo!AkIU^Ej95Xa3U8GJ7#pp?6fCSIZyHuMeL?U{Coc7FX{iN zYTJ2~m3$)5?nO(cI<)mfllG_Hs?3CF<`;6V{hTH|jyo5X-xFEq@iC;7h(a^#<;rMP z9)xvPb7FTELO&mQ5yo#F`O$%mtqBRdmj4iEidE7!EOciWR3xwS)Uq4>6pJ(+h8(>D zcYGhG86A?)Q1lp*1bSAUy)BryZgXg8=v7$tD_`Fi%5Rz_zf2xUaxoG8<~5A)Qu`7_ z!dU2Yb@#mH1^De1fB&~+THD#stN4a>;rYx-bIj(aI;Yh#?wsSH z^sAjyYas6K4^Ku%xdfEN>}eoX+;rxA~~{e z%JC1$2d|i^*x2<6jY@oe<6KjS@?uccTfV$om_7^iVaDftQ{!MZ6s;8>e?R4pRA|JZxAQ&^Bh1SWahzZ!M_S(E<{($6x5WIdvMy732pufr#E%KD+W zR&+OEDEnz>01>phyg}l$vA#vvpaE~vuomklHS5yNbFPvHgEGoyn!F6`5|()L^bzq* z+_Wl~Y_vXP?m2&Rjukb1)xei9!yG45)-ReyDzD^m18n5CWWK!x_L>Kx4QSD!Z-oXK zf8r8ctTMB7`J-CtnEZV~knGswNea=Bsj^#R=c#Ea8K3+4#9{(g=>HJpcqSC(UAGmEnEjWd4 z`mkdb^M_OCSb#<|ii^TYwS09{qz{!a%L#`7NaK+xPQj`2>zE1O^-CB)enAUB9>NEz zp-b9h^4PAo^z!i`%LE833y`@#dC|FT9pU%+zv#E0XB^(+GA|>8Y!hN{j3B%(S z0Y&=9Suwt|Q6x#Bo_Es|1NijLS<^aPAy76y0$N%EZyg+tU^SHHh@s_Ks88#fV!-}N zRAI<0JD0M25S37`%U&=i8InB*rMR70(lq_x`=ZR8MCI#_z7ooHvf|>Q_Qgy@Q%7SE zKFUjqYHGWcMsoc)_&YhTXOC+@isp`+?!0q?zR~J$nS39iySeEv=;E@AH`1H<$<&R^ z-fVI86zhzFlzhozDx3WP^A4OUNOcjDOUcFf$0uI?7k&j!Jnp2Aj7z+W-QK?V#Sbu` zEyhz_VuYVj;2g|c$88mq*T6*kDFum>c42^$v7B-cuN$*VZS+p!RhYS-HqzH+bO%bg zYrEg9{zy^s?)dJRX(eBvZhL_*3FR+|9HU?IXV(Sp@NQtWg)f~`W<6nbwQbGs7o$*n z(-jnzw8O)(WwB`YiRFH!Fump@AF7-mUI_X?aXf#;zZF$i_X)xZ9 zB2n3PkDxGt4Rn~yvI8)`JrCrJDep3;2203F|D6(bj?3v%fb92!IaI4SXXGfWG6>#= zsx8aG&6AX-x>oYyw|-JT{HoxHtbV(T0*E;>##Sz>KXdlpXOE-rnzjE>Vy=T{R9-)= z6QIi**D?DOQVu`=1L`zj$*s(!r+gRpb|}rjPQml9QLrLS1db;3goq$gIAE)9HqZ1Y zXJON6b+)7B^!Q{1;@$K((xRq=_BW3AGBV^=IK$;Jp=|7w2;PREoX$d4j$|%8>F+4b z1o`oq?#B^H47j#2)oje=>oEyN(GXU?ouJHWZ1~vv2>o>VxnW5cTTJC-X;j;KjLB6) zGxfC!y)(7{se`-?ghh-i84KeaTaVXY(97ZoY!X*_q%S|0x1pE5R%v=>1o_y)*KO93 zfqJq>aY)WvhyBG2S3Igbl8Vq|GlG|6;j8(5M}=YJr3LYh&hnB{QKmmvZpJmo!k&-- zBUDFwfu!;sk?ao!lRA6mBq{Z4Nz57#Oc?=JaDXQxhd*O!`TlpqB(FWjKR#P0OTZ;H zB#?3)lP21Id8$;xh^WVvrBaAX(wRLFWED1|5s%Wlc#$eZEE13C>9g!P!X_gzSA4jR z+ubo)1Wqs6R!NTe8JdhH6eQ;spn{g#W;Orf5Ra5!@O{1W|7)o6zWsszll5>3MPW>n z@4EqeolsoeMRwk*5wH!0zHnEyVeHY_|ixm8V$TL}ZmoGeVmfFA!z%t&>Jw#q4sLe4mwPYqgA;SM-Zw z#2Hlu;F@|G6GR`y$k$0w`Z(2MwP{Mw$js;*|P`_I+ zlDNnUXCA@ATpQ7)R<8EX9-$^Nyeu#Fnyp=INz{X#U=8>DrfFUNbNj6N`Bk7v_Qx$3 zsShFxM#HBKm7+@`&fA492r6|W=!cqbS$d@VK&QoBZZD?@pNq6psy$J1L9b*T(;jPQ z7h3v_2nHANPvPb1O4KEvAJNwDfVn`TnK`VwyJoQrx&&5f(3b1deY4H$=@rX?nMG zYX-6F<+ME2>&+Tuq24WZ8zn2&yjmaj12;97MV2R0d9yAEc;^ne!y<ZZo84za@nx-sy&*jg3($g9Xcf(i2QIbPQ#8TcO3dDJF#vH)=Zy zm-3MK6II2C3EACTB8qE2!I5C>aed_lJ@-pjOe&y+WST7%!`6#FEC z$ge&MJD?@`Ant+Pg43=EH{mG?@v{R0*8=d80>Q0*BkD7xrUMLpV!wsO@W4 zKUUhBaR+{XJE(LrXKa$}pJwQ1j+SZl>x|gjl+RO11^(j%W&Y=cqtC%x2?2s4B+QG^ zN~|fAqwKGZ2G`2y#UzVe$CmrDes2_a%U?-wpeA}#5mpopvMnP+R9+ig&VHK+p7hwn zhs+$4tZI%fMxy(w7U*>pYV+V)0hL6LCLTW z87&oSp-RD}*0K)ooOOwqY>^|Z&++`I3dhjgagwvdJRi&7sts|R1ZLak#4C%GgU7`#UQ;miv2=VXv zVdB$W)U^_izy~g`g&+F+5!+l_u05#G#E05OHZee~mA}MXqPJ)N5#>H=Wwr;%^-NNY zZ)IRunDcF2YT}&i*iOl3qp!Y_I_?hqBcwB2h`in~zf>!Ly55`m+{J6{J5%8&l1p6C8=9{6^X`$5^u6Z8*n&W_Vj^BE@>pj@Ht{;f z#2DkY@L~nuMBUJNk^F%BooxEzJ9IQ`I_@D}2DLki}HISTwINqX{(E3>E?!i&xvDDjp z#bv(#ZI?egW;9RK*hbCNCQ0q9H&tZXFwV8ui7*yRI$dd}me6aRkw`h1W*kxzJqCJHN#F=J9m44jx5N`t+=MRP3BFY!sLptU0ZPgScMA}dxtVvj{M z-`<^_4>dmtt~@u7Z(Wd@8XM=^`emp2K}ScUdJXdFs#X$uOAGi4WPM2t4iDK664ChA z-$m8q{Vvm2neaVfySN1U_$bM`{3M_l^Q0&PtPvQEV`u?kP`FJiOgHyi_vO zAe+;AQ>TEF$#;{xf1Oe6hZp@w+g0++-dE615mkRR!W2s(7yj{6hneW9KQB$ep{8i8 zl@~}}NJti|jlxKa+nbgO!ii2~Mk`N99xcu!S@Z_hsbMb%Kr*&EK{nx&3=YhkQxYEP zi(JsA!<}wc=64d}jO6if@Gfh1`)G(UI9e)SH0;oSk6T4STfe@IX`{_fIADNRuITgp zk~Y)SuDRm|=wGz}+>B(3$h?GWWuAh~Dqd#tutOlX&j{Yu zh)H;o2;n(b^K|Om#+ct_3~NoVJM8u4b`a`1>+|74*l;*i%5rC(n~HPRcfwh|Wm*l` zCZx-&Dif{>RXN*b0i%`QFjmm|!OEl;`_(1ocCxEeKUN8?znZyXjZ4$gKaOKSv*~C8 zy8P1Y`Rl0vmDGH=eg%0l25ZY}H=Pdnl^I3gh*rWrjwyKk7anztpl3_l8_oywY8wX> z>8qm2&xxZ$oSy@g6xk zk)EkPMCF&duL)?Xn@x_wosF4VZO^5jLq?n7oF$YY>H)_;MHD~1sfs`q36Oa!_QDgy zt1#ut??Pl9qDkz zrR5;Ua)%!G3d%c-hEiU-3$gCDDO-7A*6ynDuU-y83Kiib)ykJxVo6J}g1RDa6vyc* zbUl!Bgeryg2*iZ@7wJ!dw;(ano$3+^ndeA<%+SqmNzAoXqIgHa-n<#|7et`|e*RKo-+|!&1Q} z6{EV^_e5>bXkOhhs*T)gwBnCa*r#g5((?DM7V zGXTa7nDVC>;xoF=z2GJ<7UQTejCfMU1CgfI6rX1`10Qy<-oHz!8iavae`3mR)mr?X z;{1gF`1txET1Z}ERCIY#g{4z}MgBTI_Wp&qIkkx>99;1CQ6-M{MR zs^#GeR-zcH_H>N>z*t{gR8y7h!^bp~kiumnhZM`Owra;wSgZOy;|g)WaawtmV?i8+ z?W_tbEX+##%HW(LdY0J2%842~%Cl3jWmSjdB|;|K&M+N#ysA}{X@-u^6f=gHS3@I| ze~f((Z`<>tocU#kvmtxZG2<0mId-`Uk}6D1*e9NLD=#Hw-!)XfNaB@XN6o;N1EPHH zOU5=bvP`Z4_ZtYF>3iwu0kIrA{LCb4+av!$nu}hluWr5$DH`P5HIEpjfv2f1&8|+= zv{uGz*=wtfc3}G973E?Oi4Sv&TUDg(pFeFAKsu^Yvr4szqan`wOV*;n;}?{DC+rOY z{%Z!bOLc49$zVPcZbdCmQCHJ+4WN?s zLYVnKJo&A!NZ)C^$me0YEca?`JD7`(92kC9#^_+}sB@)L)49r-4YVym)6{Qb97b*f zUdM5jszOE2rJ>IZ;1{>%*xcd61N!G`Snu~`i|6yNe~JE$$W_jjxMZVuAYb|E{b;}v zC0?*Gk=+QZ*noN@xAvY=rW>hRirH_IiKVCCG364&KsrgBok} zxHwU@RsJ2e@V(wWc-c3(LUL#|=Pfos;nVvi=WDU{CK%Kv*#PwvF(_{#Tm{c$25C&) zdQj$gb~^6gVk{YLtJF=MOs@BxYBo#pkiwsVe@I3(56=FGmewX`g3hwZZwR5}z6_$D zgUg9*c0fT$#XCR4YQ(o|3(8r&VGmwz03q#DNOSw*@)=U{$4wcIE*sl{42m$c2db47 z>$bXy;hq)(1KS@B%UmT*4WPbOTgfonESP@lr+flZzQqf+&nnspGqIS6`%mVj*Lh-6 zq9CN<8Pr-(&q@g3#{_c|jnav6bJf34YyXKu*x-rN3FdH`;bCh5AWkWiq0VMcE*N57 zx_euQYn&h|9w94AIS0^Js5CjCdiUmBM!T(=B1hUSa0h*lD_`ulV3!T_ z-Egql$tF77AyQXmm{vJF%0b!s3i~uYZQ|QC-OI~ z6u%!-6YM=^d5*%8ahRhjT??+b3jyQ7MuG)#Cn%jHXDP?#y}&5?vMg3m z(A3e<`=O(!zW{0n5_&W=al#;FjGFbbzDnQGU;RCguhb?em= zj_DdSO?O~Rh^|D)+FvYpjc_vTO~!;BiU>tw7LYPy;)MUGaG4&aFdR?|T7I!sz~bUZ zouW1u548!lJj#Jt9HsyMbpDUQng4iX|DSh8bAMl1(fWPx4-ztIsnWxDoks*~plYe` zw~vhvaH=yyO@?U>iV<@m4vhyVS< zc>kIEZxPG63RU8%mEW|XG?bKifA-Src0XB;GGOEo?@-XHzfCpc!Q#&*jI4Tl@%H{4 zC*=qi&qvPAtIvg;wE3~)OjnP-nZ$kl1X(5hV;Ou~UItHLW>(22zmV{yxH7LlS5j@T zgmkA6zGb zik|)#c0o%bLK5Ufk9-K>leA&1KUDw(epNQ1Y@4`cgjR zz_Z(>7;A0_SoW_Z_sBhgf`uhp${|s(d zD!hhuV;yQ$SIZUSfT^5a0mzacKt}PgXns#$N>3}ywqbess*EA>7VC)j(qtTWO|460 z-z3N&IwF@^n|q@35pt`I7*U60bW#WGccJI=II-&AJj)DeUjwwNE1gx1cMVQ zxAX-q;vH6$hV`Ch7Q0l}J$p8QRlush#&yYtE7=&?QFlJ{7bl8b~X>Sf~p zz5Z`5i1Cs02a|2jWf}Fat+O&(=+c~_05H;e%hE8PL|)$FwVMtzsjx9JNb_^{Jx4ko zAqhZ7s+O+4N~Rz?5n=cSBfB<(gYgL%OodP zG~oZj*YOoGMVd7|gp<_3e=m8{9OtH`hkSdI1SuvVl$w`33f>M;mLmLUtM~V_3js@$tH0<)jam1=nTSo4 zwG9}E>9C;|QpxwyA31vWm?xl2ux+F4@D;19yB)+ZS42L2W7r^)@CL3b^~{(I931iF zoF)WN)%QiwrgY@h#Mo2sr?L56rE(7>yg@dU&vpE!161Q-b% z-0X>bt6>#XCcq;qLo!I&a@`Mo8>%B+ZScghhp~61Y)Q#$ zxr42qPQScOEjXaa;pqz}38aR-Frx5D1d~ZvvIMWqs7upmq8*+_*LP}+&28>5aD_Ml z)t;iAe8&eKrx|OqobunuOJoQ>$~ORXFow#~CNL`P16ovbYr#3~G9 zS+YT#xT7Y&zodW$<)z7)DQt>{cQd3YqB$hO+T}WiV2RxYHdp+H2_lDzp{W&h-+}v}OOulMIL6s!jfYfioOmOS!_+eq0IM@`Xti)$( z*S}Qa^+O5QAMy;L*12k1JC&H@y;?=K{&t}Wt)m(X-03gIdoyb`bC0%kZx0$4G`Zha zh0L0NU&U2<@KMdoS+g>^LCXfIG^#X5)dNNt5+_2Q;H?}qKaVa?5=^-}Qd7_IY90~B z`af!6G|D_eznE6a;k)6s#=;D;`Ak*g<LOXKsk~)ew#Hh9V3n z9N)1qydCOl%AVnTy|j3{W`nsz?*PVS3`3-XzTToGz8e!#KiY}e&urM?BJGPgV4VWK zpb{=@tKW)8O&iRNa81S9;G+rMu?)#HZ@RheQ5Hh7Dw^}~;eYUk>-2BF5{n?-etlP6 zo67(5y}2)z&HHYFHcbE_@#y|<9sTlYCLLh^9q`vqMV{;8CfG(8Y%*=-F{Y(E#KNR* zjMa$#LLb-itc4%aC@b&dqqPn|-xD8>>yi$NtH;SAA6A2tCX2w5n5T#TK;9Ru-99XZ12gw#Xz7E|Yn zRY#sz-gxf>ny3y-9E^|`;U-EMK#iBU;OG0klp~f#C!(>PMUk$D1Ge@AL{Sc+3piMK zSvksE;uRay7Bbw>q(nA>?rer(_S$_1+s0iUFWx`#9j{noSc3x%b#erg@-A%abrp}i zf%}CcfHL)4ifEQ`5P{GW0#=iyymvwcCUYzuLurc-fJ{I`u}A$2btY+=lI2j*M5VvX zU?>On?q{K8FjkU)ICxcWc_Uyvg&kNCCV?4(pQ_TiikJV$%yDKdd*KwOzx$0>wbOTI z%+2G|$~aWX&T%ci0Q%${cSMYwgsL-A(U!bX!kd)c$?vqQ#*sX=UUV49j#mA#wH*?( zd0TC3>Ij0gN=OXPR_3koX7m`LmuD0{QDB}1#^8qI z6wX_!pMdZ(C!7xFB*oBa&`=yB-?=+bpXgCBg?x|^)BH|pq|dS;73>OD$QSI*c6!?{O4xge^QS!Pf+4m zwlnG7DXhD$B#6tAgRu&8UKG{3%o~2JXE3Hyq!-Z!+u-gCWD|Quby&W^ZBDn)uKerp zj_iEqOg(*5b5+Vg=yY}@fofw3PUaEGs4ikfj_ z9mxfZo^upv5}mNS(53dXnC~R<8R3)8pWsZl-q-UZrkbnPn_>gY>B;31jUP)+$ffv{ zqJL0lI&|`^4{p-o`I%xR&hHqDI^Dmbnb@`ZX=`p^ifbZnLygF2`$Qu=am_}o{;jyz zr3QdtzyywHm--N!t&IM)^tmN2nbM#$p(S5kXbyWcc$B*R9*q={^5X2!^WjeD8f3D! zsM?SluU0xEgKTML#O=PRFtU9MJUj?lI6QdB2=u|zxrOk;=5L3BlHZuL$VT@ zB;HT&4*mk=+eQY#cX!JUcLG5GA@R@Z$10nYbK-*46jK<;)<_geI7DsrRIrap_)#ia zkp_Zr=NhPZMU<(E`+mwn`(7=tZwQX2Zy48tWX*Vxt}jwXLs`F{y6f2PUC`<mvW;vr-xYtE`O@zn3p z40Ct#PB6=nh$18E%F_9Bu7-q@$AVat9F=#^10NWODhS2=> z{qRS82vdsa+)pBSN=Fj0(DH0vMkqV$8t|$qxE9bPh`_9rlCE0uT)YwDMTM+^yC-fE zbH(yUu@mNd$X7J_~!iWD}bib4U6i`gmi2KFk_mU)(40LXg zHkeGD8;yG8)RiH&Yt1i>cDU69O~rsZ%%8H$YZz||i{0K^o^bgDHJUF&PX5e`&Zmsc z3283qPp#0-1^@*%*z0FjxF&1%C9|FR!p-}OOv)EtL~^?~-3p%_-l*Z!wBm!K0^`a* z`RNu4M{xo-Y%Xv~dfqF?L#@tnzw-`}&e*;Q57L7a zOKUQ%pHPY8rz>j$6B2}yCcUz0v373x3Y99%rZ(tE0R0T2W(-2Zf7&5T&?@&^E~u3E zgY_#zq|JaU2Yi`Vl#ZBoy%ySG<*{3uE->oldNCO ze95VNAZj$PJ!x+>&&$iHB(z1u7$r53Wm>JePGH#&iWwzXWd~ax~W&m z=Ggzxj}|`BOkN`8mL}}xe61SnDrnA`Za-UntwN;R-X8zDLLi=Fx2_iYUhWjZ<)b}B zg?p1QZ@?>s_32G*2z{IkMe@ujf+)x+PpY77D-*<-^FYVt(Lip-!25yO3H77LxlxzG z?ME%3vG-{TLapGqG{G`0N?`J;Yubz^4$)cjigC~EhUYu+oPp^Ml&m9-N+EcBd!GV@SFq%h4S|Tznjb%{()K?n^aVA0{^A2 z{8w5id;mKy&>Zb7U+Ch(%hj!o51KhO=h;XXr~VdO{%w)Oj8=agDpZx0dqeCNvTXr6 zx}5U>s9Ve*P}I7aT)a;C2Z@ad@4;d->*u@Uz||#%$Evo*-R|JFAj7f4yXJZI6qdm# z^i&~ve@k$`Fs(`yQd2ZPQ#gbj_@gMnQ!qg@z-u)o2Uf@xAvg>8fhYSX_)yM+@^`Y) zW}bka;5FJjaYYmjpig)$@e#24$Bz3eyRJsntPoS_A&qyP|x-hug{rm_AU(1TFp|;HO@FKzW^VP&DpJR*QrDw}IhKvP1 zhpn*xtiqdhbbZ@*WAsM^adVh4zld-FO^I#3y7%3tONp$U*=f~`XB|L|RpeG`f1C-4 zk_0NzYOA??b19 z`=Ph*WU-K`FD4<1wa`K<*%ykBpC>yvuoM=(Vnbf~6(JL2+l==eaxqpO+%x-qUSJC4 z{f+5`%KCE$fA{WPvk4}_pC7ZFGwir4CYpQuJa%l;jwq2W;-*1DHr*sk*ObS^BdmGj zxECdh2D(Z->WkVkB9mD~F$bO2ps4xy7y~7P{jT;8G0g}tl~?ciD9{D|uvkGn)lLOp z@w)QLbq%y@sc>nAkE;HQIQ4(kD;NIGWE&^BkuEK6ww~~js9oC4}4o{3`UT@uQz@staFdw5=;&b=5Mae^0!hhBI|M z^Qw{2JcOUdQ@6L0kLxal8jJV5{FM-W?AxA(;->R>a-Lq!0*9QID(6PEOr#)&&k@0N zR(9D0+@+=4QEBJLCTeORTS!(0vfX_;Y6ThDwu`%Sw)m2;yUm{vr8V(Y-Ldx!SDz}(lga97Vmj6|=uFf7W^eflCfFy+v0K4D1;Pr=}UfMDTNj$gRMb@onW-gI$tLbICNr!OC)OFH02~5ApNe z89EjoJ5D4BW_ycZ(*7&pj~_q6l2-URb4*UxioTIbCXvkOk*P4RoIz(K7xDA!u8J%AR)4qV)JEP{IV_q>g2F+LZ>b{7S$moF8#d%wosPS$^ zAGOY$1;zzvX+! zS8{a}k(i`j9)2*=^vTtj>DIo;pLlUK6%YO_DBGZ! z(Vy^U+~@#CmW1D=^+mB5ht}X7(npg+_7zgQ5eAz=jh@l{N0!n_npArM(mS(I)kh0K z{=J~YK9haYY!8fu?*T|n*~hCz>Mi`FBWJY7F6#m5tF{4a1`1KD+nGKZF2qW^*oVfX z;u^+=R`!MfAvv~ptG=@G94Ms(y9KM7zrJghy*7d!A000O2a|*=*+t>9hK%07kzD?hiP3*)r(F8R*;(12U;iM5 z#p^Nsu_%8A6LqoZQB8d}&i`IX7|LLw@Aml3tn)($Km66h`J~{C+(Y_DhnIFIi@}ax zP(;&DV^V?X|M?q`{WJgHF;j?B>PP;q&@g582nn9PcjaITUA%={5U8B47aa^Od-Bd* zojghnQ5v>Yx1HcOpF3@fY3UIABtT3F=TU19#7~U_PR(faKe?yb5_KFNI^m5Csh~`K z_;R#INFBdfad>s(wuQ%!%+hdWf+RENK*rBC|7umBP~U&OjI7?xw@SgYVD-SeRdvq1 z^w*f)vYA1h9939MysbEi_Kar42}(CL;S`JiEWLp}r7i4n*V* zUNu0criBWmm5+?*xsn`Jq{FkBp=#U?7rSl|T#GL6?8ApP{j$Lt{|Bj8veF>=8JLl! zo?op4jDaC|qdR_zZB@Q3zgNDj_nZdQe19F!^x|`9IWe0dSG8A3Fx9e=ugJPQ?e8)N>{)B+>IRJE_r4JcV{8im%%i0}_Nt`Z*6iR2Q&L>-4~<(eBJX;A^rQ{qgJ-FO=rWzvGiT>U0jhZC>I;6I z01LW<^S5=K@f(rpKI$cVAs_6aG*-M0YPAE5ye&T$|3T`|Sv@&Ubo52YdwPt9N(shJ z;IG*veiz{pWL=au5BcyD;$zTczGbIhA}sOn5R|taV&UkI0B9_bkBp@b^-Z6Le6RmT z=~M~kg5XS>BwD!jO>bw#bGpGw2T!S(c{#Q1-55VANbCHmq>EWXmR&bdui9ARHyh>v&tjhI~+aWn?(do~*l9D6Ml2TBuGTuRL6 zBel9T3-5~{PUKHwNl3M;iKCp^FCi>-!QyFAuZTLT9OnPxy46!@cNSiDM!EQu6%%el?#9BXE*5CZ#RaLdgw&bJCYe!)<>W^vQ6u7XFZY?tIIhpH)l zpuzLhC>sPt|74aMA#{~Cl$aKUdA;o=Xm)HU1)KgP`fwI?PVRy=b*Ze^pX<2$IKp{1zuVUM3S>ev`ZFNsvj_FCjPA4kH zAd`IT)S&ocSw{t!vMiCHURLR6w2_jkVi81-8WIFJ{>4aL92CY-7s7VlO}?i|2nbfL ziHOI7*?ROx5@PJq;RVT}K%+!U6`2-FY7`4rPV@E)E7O7r;=}4qwN3u@G$m;yLVzJk{Qp_onSRCvX1KL3sH4FyW>TJ^y zIe-`@YFFufWFI4MLZM{3FR~a4Fd`h%LOJh&X**{bPAoJp51vjaSG8at~D7XB)1 z_q1qM5cMH=d6^!8+a2F_BzdlKj%ep~=dWJv6hD1#KgLEZf=4i?RTwCP>x_aH!(USL zkP6q)xvHOC9vuodx$m8i28 z(q(2)yO@GBvMnZm@q9I;CYh4lC2>=h7#Ccdo=IDC#xwQ61#-LWppwsJ#2y2)aJ*wX zAXJ5Zp3f3YuhvfCT9AkvBBX`sZyn}+ne)>?qe$qJaGh#_UW6E6i#fq6#w>YA8HPF& z{fzL=NLY;1_v0vMjV6=sfU|O1Y~@YoFAg&v2tRprHHfm8E3>>d&X6gGC-M#lSK9ia zcR&5?o9^S(w&|CKf@A4L2q$4SZ4v!-T0FgW5@tCotLZ@#tdj|kW>*#iH;=N2QIL9W zj|_@t+9b}Y79wB1k3jz7oM4s6ED$qDlJH0|Eo#8@!oPp&)ZZiV_w*?2V|KyoP;xpR zSB|EVz7iN$gsta%#oC`FMPiN&BDp2)J=iDaWDcX)5*0Dg`v)VT~zvavvaqe3O@LcFxQ}T6A`0b)uSc!8}>V$%IO*dfpqnZ0C$H0 zWGl7IgUDly%$Nf%1Nuioh?ZR?Y(Png35WbQ7y7`t&uyiJ`-`7_TfAdV&&)8zWKpfD zCZ4t{#fI3WCWAvga{x)aI0Ijex<&_EOb`IoCz^*r6aZS}y{{CmT*gga6Et(ZVD*I@ zD9+A|L+)0MQ5eb$rO?E~`<%mAKB{Wj^x}rNe|gi-NO9d?114XO<}^KRZ_~8VAhxt0 zUF`!y;kKo)JbNFv*Lb6Tq_YFcLB{QdByEG@7Oi^RS_GEpOcutpe0@3!cvnewlEjw9 zCt~ffAQhI+to8dx{+UI3oT-UNq=bT+bi6;1lNTC(e)!US)smXqb1D)!ZRMXBLL%>6 zkap_Ti9fLz+dy~)&VP`D!sq4(nG;F>elxVdTULP`h5dNs@J|b?rde%K;L-X~QD)NQqv`zEFt=*O-^6x^c z+cxykB;${UUEZ>SA)5O;2IL5!`5EFW!sOQfPnzPxc_^&~DSFI~8H240b)Flt6(6B} z6zL(QVj}N?`ruQo8f@TFD#3EyiE=b+`xkNaPGBEZLtBqX*m+f3LH3<1M#N|aoEOxY zkG~j_apo7k^VTeCJ@B1kwYPJ-`KIEEOTW(_*iEckAkw#;&46O0UO}x4cBqcvZaB-S zC!fXijan(m7xL9yx+Apu_GZ>3W_rcPTp_;H#b7_A@FVl>I~~4pCiEjs)XP$2)NI3f z_>3&j+~|csH{ACNU+*LR@?Gn9i+9>r&KjibRjXTz?fhI^#RKebaZ&Wsu!Q3_o zY;^=+{Z4oRp1fGK?r{cPi2;prkv-zjjfl&yj^l#we{fQw*_aQ3vtL()tQr1xVT%(| zKTISY;eE?ITm@mssZvch!2EO_)5okw*X1c`GL#7G*Y`Xg(#IH^U)eJ@6=eEE#jMzm zPff-n=zhPiuZur5Y;xpRBTXr?j&*&l&O4sM__;pGK9>fhL^$Ubh*j!H_AMB <9F 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

    3fNN(I!%o6!(io%Ea>{!`= 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 z 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%0A9b24siOI!3$VDy&gqgCsc!e{XLM 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

    CT{pxmNUcw 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

    BW9zrHP>w3I!v}o((L?t| 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�XmH0BX8{7Fo+5_+B0y51fCh=1gyC_ zeXDGwYgHUUY2B>`nY(|p5Lr|Z&k_gB0`RKZrt{$GR&#&7HlmXJ?(=0}j3Id2pjK2ft}>dMx~ z>W}yai=Pg_+G}HdKJktlogUT;b`9NQHB(S=c{-V^8R5$P9T&rtl`H&B``6^XQ~+9o z*$Aq6f3+s)1p}wf)Z5fwY}Oae&vPGjtWy_F^v=FNf9a^;9`)KG63`7#io^EVU%0AU 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π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¨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

    Tr`~umt5;lf?z^s5VIro`H-P%l~ge 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 ZAOB9FaQ^)_;C1{vo%?^F!*c$G{}-XHNrC_X diff --git a/luci-theme-argon/Screenshots/screenshot_phone.jpg b/luci-theme-argon/Screenshots/screenshot_phone.jpg deleted file mode 100644 index 8237a0368813d8d7b9c9db585e088db8c999ed06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 467306 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�+7nJaJ7mB9sLzVyJJZ=+*$74h7n0@`hdg#0= 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

    lOFHKxW{3#(Fx9m%qBfZq)kvVO1c3-Pc^W;%aRL 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ą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

    52_`cE(zZMEpNgo`EY*4G)I09>a1 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 ?@Ps4J#L1b@yTXJK07_F;-CIu>*o89f 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 - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-material: - * Copyright 2015 Lutty Yang - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * Font generate by Icomoon - * - * Licensed to the public under the Apache License 2.0 - */ -/* - * Include base and custom css - */ -@import url("fonts.css?v=3"); -@import url("pure-min.css?v=1"); -:root { - --primary: #5e72e4; - --dark-primary: #483d8b; - --main-color: #09c; - --header-bg: #09c; - --header-color: #fff; - --bar-bg: #5e72e4; - --menu-bg-color: #fff; - --menu-color: #5f6368; - --menu-color-hover: #202124; - --main-menu-color: #202124; - --submenu-bg-hover: #d4d4d4; - --submenu-bg-hover-active: #09c; - --blue: #5e72e4; - --indigo: #5603ad; - --purple: #8965e0; - --pink: #f3a4b5; - --red: #f5365c; - --orange: #fb6340; - --yellow: #ffd600; - --green: #2dce89; - --teal: #11cdef; - --cyan: #2bffc6; - --gray: #8898aa; - --gray-dark: #32325d; - --light: #ced4da; - --lighter: #e9ecef; - --secondary: #f7fafc; - --success: #2dce89; - --info: #11cdef; - --warning: #fb6340; - --danger: #f5365c; - --light: #adb5bd; - --dark: #212529; - --default: #172b4d; - --white: #fff; - --neutral: #fff; - --darker: black; - --background-color: #f4f5f7; - --login-form-bg-color: rgba(244, 245, 247, 0.8); - --breakpoint-xs: 0; - --breakpoint-sm: 576px; - --breakpoint-md: 768px; - --breakpoint-lg: 992px; - --breakpoint-xl: 1200px; - --blur-radius: 10px; - --blur-opacity: 0.5; - --blur-radius-dark: 10px; - --blur-opacity-dark: 0.5; - --font-family-sans-serif: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; - --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; - --font-family-normal: Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif; -} -html, -body { - margin: 0px; - padding: 0px; - height: 100%; - font-size: 16px; - font-family: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; - font-family: var(--font-family-sans-serif); -} -html { - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -body { - font-size: 0.875rem; - background-color: #f4f5f7; - background-color: var(--background-color); - color: #32325d; - color: var(--gray-dark); -} -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} -::selection { - background-color: #5e72e4; - background-color: var(--primary); - color: #ffffff; - color: var(--white); -} -a:link, -a:visited, -a:active { - color: #5e72e4; - color: var(--primary); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -li { - list-style-type: none; -} -.table { - position: relative; - display: table; -} -.tr { - display: table-row; -} -.thead { - display: table-header-group; -} -.tbody { - display: table-row-group; -} -.tfoot { - display: table-footer-group; -} -.td, -.th { - line-height: normal; - display: table-cell; - padding: 0.5em; - text-align: center; - vertical-align: middle; -} -.th { - font-weight: bold; - white-space: nowrap; -} -.tr.placeholder { - height: 4em; -} -.tr.placeholder > .td { - line-height: 3; - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 0.4rem 0 !important; - text-align: center !important; - background: inherit; -} -.td[width="33%"] { - padding: 1.1em 1.5rem; -} -.table[width="33%"], -.th[width="33%"], -.td[width="33%"] { - width: 33%; -} -.table[width="100%"], -.th[width="100%"], -.td[width="100%"] { - width: 100%; -} -.col-1 { - flex: 1 1 30px !important; -} -.col-2 { - flex: 2 2 60px !important; -} -.col-3 { - flex: 3 3 90px !important; -} -.col-4 { - flex: 4 4 120px !important; -} -.col-5 { - flex: 5 5 150px !important; -} -.col-6 { - flex: 6 6 180px !important; -} -.col-7 { - flex: 7 7 210px !important; -} -.col-8 { - flex: 8 8 240px !important; -} -.col-9 { - flex: 9 9 270px !important; -} -.col-10 { - flex: 10 10 300px !important; -} -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} -.h1, -.h2, -.h3, -.h4, -.h5, -.h6, -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: inherit; - font-weight: normal; - line-height: 1.1 !important; - color: inherit; -} -select { - padding: 0.36rem 0.8rem; - color: #555; - border: thin solid #ccc; - background-color: #fff; - background-image: none; -} -.btn, -button, -select, -input, -.cbi-dropdown { - line-height: 1.5rem; - padding: 0.5rem 0.75rem; - margin: 0.25rem 0.1rem; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - transition: box-shadow 0.15s ease; -} -select, -.cbi-dropdown { - width: inherit; - cursor: default; -} -select:not([multiple="multiple"]):focus, -input:not(.cbi-button):focus, -.cbi-dropdown:focus { - border-color: #5e72e4; - border-color: var(--primary); - box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, 0.1); -} -.cbi-dropdown, -select[multiple="multiple"] { - height: auto; -} -pre { - overflow: auto; -} -code { - font-size: 1rem; - font-size-adjust: 0.35; - padding: 1px 3px; - color: #101010; - border-radius: 2px; - background: #ddd; -} -abbr { - cursor: help; - text-decoration: underline; - color: #5e72e4; - color: var(--primary); -} -hr { - margin: 1rem 0; - opacity: 0.1; - border-color: #eee; -} -/*********************** -* -* Login Page -* -***************************/ -.login-page { - height: 100%; -} -.login-page .video { - position: absolute; - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - background-color: #000; - background-color: var(--darker); - overflow: hidden; -} -.login-page .video video { - width: 100%; - height: auto; -} -.login-page .volume-control { - position: fixed; - right: 1rem; - top: 1rem; - width: 1.5rem; - height: 1.5rem; - z-index: 5000; - cursor: pointer; - background-size: contain; - background-image: url(../img/volume_high.svg); -} -.login-page .volume-control.mute { - background-image: url(../img/volume_off.svg); -} -.login-page .main-bg { - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - background-image: url(../img/blank.png); - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all 0.5s; -} -.login-page .login-container { - height: 100%; - margin-left: 4.5rem; - position: absolute; - top: 0px; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 100%; - z-index: 2; - width: 420px; - box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 35px -5px; - margin-left: 5%; - background: transparent; -} -.login-page .login-container .login-form { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: absolute; - top: 0px; - width: 100%; - min-height: 100%; - max-width: 420px; - background-color: #fff; - background-color: var(--white); -} -.login-page .login-container .login-form .brand { - display: flex; - -webkit-box-align: center; - align-items: center; - margin: 50px auto 100px 50px; - color: #525461; - color: var(--default); -} -.login-page .login-container .login-form .brand .icon { - width: 50px; - height: auto; - margin-right: 25px; -} -.login-page .login-container .login-form .brand .brand-text { - font-size: 1.25rem; - font-weight: 700; - font-family: "TypoGraphica"; -} -.login-page .login-container .login-form .brand:hover { - text-decoration: none; -} -.login-page .login-container .login-form .form-login { - width: 100%; - padding: 20px 50px; - box-sizing: border-box; -} -.login-page .login-container .login-form .form-login .errorbox { - text-align: center; - color: #fb6340; - color: var(--warning); - padding-bottom: 2rem; -} -.login-page .login-container .login-form .form-login .input-group { - margin-bottom: 1.25rem; - position: relative; -} -.login-page .login-container .login-form .form-login .input-group::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - color: #525461; - color: var(--default); - font-size: 1.5rem; - position: absolute; - z-index: 100; - left: 10px; - top: 10px; -} -.login-page .login-container .login-form .form-login .input-group .border { - position: absolute; - width: 100%; - height: 1px; - bottom: 0; - border-bottom: 1px #5e72e4 solid; - border-bottom: 1px var(--primary) solid; - transform: scaleX(0); - transition: transform 0.3s; -} -.login-page .login-container .login-form .form-login .input-group input { - font-size: 1rem; - line-height: 1.5em; - display: block; - width: 100%; - padding: 0.5rem 0.75rem 0.5rem 3rem; - margin: 0.825rem 0; - box-sizing: border-box; - transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); - color: #525461; - color: var(--default); - border: 0; - border-radius: 0; - border-bottom: 1px solid #fff; - border-bottom: 1px solid var(--white); - background-color: transparent; - background-clip: padding-box; - box-shadow: 0 3px 2px rgba(233, 236, 239, 0.05); - outline: none; -} -.login-page .login-container .login-form .form-login .input-group input:focus + .border { - transform: scaleX(1); -} -.login-page .login-container .login-form .form-login .input-group .cbi-input-password { - margin-bottom: 2rem; - position: relative; -} -.login-page .login-container .login-form .form-login .user-icon::before { - content: "\e971"; -} -.login-page .login-container .login-form .form-login .pass-icon::before { - content: "\e910"; -} -.login-page .login-container .login-form .cbi-button-apply { - width: 100% !important; - box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 50px 0px; - font-weight: 600; - font-size: 15px; - color: #fff; - color: var(--white); - text-align: center; - width: 100%; - cursor: pointer; - min-height: 50px; - background-color: #5e72e4 !important; - background-color: var(--primary) !important; - border-radius: 6px; - outline: none; - border-width: initial; - border-style: none; - border-color: initial; - border-image: initial; - padding: 10px 0px; - margin: 30px 0px 100px; - transition: all 0.3s !important; - letter-spacing: 0.8rem; -} -.login-page .login-container .login-form .cbi-button-apply:hover, -.login-page .login-container .login-form .cbi-button-apply :focus { - opacity: 0.9; -} -.login-page .login-container footer { - box-sizing: border-box; - width: 100%; - text-align: center; - line-height: 1.6rem; - display: flex; - justify-content: space-evenly; - margin-top: auto; - padding: 0px 0px 30px; - z-index: 10; - color: #525461; - color: var(--default); - position: absolute; - bottom: 0; -} -.login-page .login-container footer .ftc { - position: absolute; - bottom: 30px; - width: 100%; -} -.login-page .login-container footer .luci-link { - display: block; -} -@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) { - .login-page .login-container .login-form { - -webkit-backdrop-filter: blur(var(--blur-radius)); - backdrop-filter: blur(var(--blur-radius)); - background-color: rgba(244, 245, 247, var(--blur-opacity)); - } -} -header, -.main { - width: 100%; -} -footer { - font-size: 0.8rem; - overflow: hidden; - padding: 1rem; - text-align: right; - white-space: nowrap; - color: #aaa; -} -footer > a { - text-decoration: none; - color: #aaa; -} -small { - font-size: 90%; - line-height: 1.42857143; - white-space: normal; -} -.main { - position: relative; - top: 0; - bottom: 0; - overflow-y: auto; - height: 100%; -} -.main-left { - top: 0; - float: left; - width: 15%; - width: calc(0% + 15rem); - height: 100%; - background-color: #fff; - background-color: var(--menu-bg-color); - box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 15px -5px; - overflow-x: auto; - position: fixed; - z-index: 100; -} -.main-left .sidenav-header { - padding: 1.5rem; - text-align: center; -} -.main-left .sidenav-header .brand { - font-size: 1.8rem; - color: #5e72e4; - color: var(--primary); - font-family: "TypoGraphica"; - text-decoration: none; - text-align: center; - cursor: default; - vertical-align: text-bottom; - white-space: nowrap; -} -.main-left::-webkit-scrollbar { - width: 5px; - height: 1px; -} -.main-left::-webkit-scrollbar-thumb { - background-color: #f6f9fc; -} -.main-left::-webkit-scrollbar-track { - background-color: #fff; -} -.main-right { - float: right; - width: 85%; - width: calc(100% - 15rem); - height: 100%; - transition: all 0.2s; -} -.main-right > #maincontent { - position: relative; - z-index: 50; -} -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.nowrap:not(.td) { - white-space: nowrap; -} -[disabled="disabled"] { - pointer-events: none; -} -header { - color: #fff; - color: var(--header-color); - padding: 0; - position: relative; -} -header.bg-primary { - background-color: #5e72e4 !important; - background-color: var(--primary) !important; -} -header::after { - content: ""; - position: absolute; - height: 2rem; - width: 100%; - background-color: #5e72e4 !important; - background-color: var(--primary) !important; -} -header .fill { - padding: 0.8rem 0; - border-bottom: 0px solid rgba(255, 255, 255, 0.08) !important; -} -header .fill .container { - height: 2rem; - padding: 0 1.25rem; -} -header .fill .container .showSide { - display: none; - color: #fff; - font-size: 1.4rem; -} -header .fill .container .showSide:hover { - text-decoration: none; -} -header .fill .container .brand { - font-size: 1.5rem; - color: #fff; - font-family: "TypoGraphica"; - text-decoration: none; - padding-left: 1rem; - cursor: default; - vertical-align: text-bottom; - display: none; -} -header .fill .container .pull-right { - float: right; - margin-top: 0rem; - display: flex; -} -header .fill .status { - position: absolute; - top: 25%; - right: 1.25rem; - float: right; -} -header .fill .status span[data-indicator] { - display: inline-block; - font-size: 0.8rem; - font-weight: bold; - padding: 0.3rem 0.8rem; - margin: 0 0.5rem; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - text-shadow: none; - border-radius: 3px; - cursor: pointer; - transition: all 0.3s; -} -header .fill .status span[data-style="active"] { - color: #32325d !important; - background-color: #fff; -} -header .fill .status span[data-style="inactive"] { - color: #ffffff !important; - background-color: #32325d; -} -#xhr_poll_status { - display: flex; - margin-left: 0.5rem; -} -#xhr_poll_status * { - color: #fff; -} -div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - border: 0 !important; -} -.danger { - background-color: #ff7d60 !important; -} -.warning { - background-color: #f0e68c !important; -} -.success { - background-color: #5cb85c !important; -} -.notice { - background-color: #11cdef !important; - color: #fff; -} -.error { - color: #f00; -} -.alert, -.alert-message { - font-weight: bold; - margin-bottom: 1em; - padding: 1rem; - border: 0; - border-radius: 0.375rem !important; - background-color: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - text-shadow: 1px 1px rgba(0, 0, 0, 0.1); -} -.alert.error, -.alert-message.error { - background-color: #ffd600; -} -.alert h4, -.alert-message h4 { - padding: 0rem 1.5rem 0.75rem 0rem; -} -.alert .btn, -.alert-message .btn { - height: auto; -} -.alert-message > h4 { - font-size: 110%; - font-weight: bold; -} -.alert-message > * { - margin: 0.5rem 0; -} -.alert-message .btn { - padding: 0.3rem 0.6rem; -} -.container .alert, -.container .alert-message { - margin-top: 1rem; -} -/* - * Main Menu - */ -.main .main-left { - transition: all 0.2s; -} -.main .main-left .nav { - margin-top: 0.5rem; -} -.main .main-left .nav > li > a:first-child { - display: block; - margin: 0.1rem 0.5rem 0.1rem 0.5rem; - padding: 0.675rem 0 0.675rem 2.5rem; - border-radius: 0.375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; -} -.main .main-left .nav > li > a:first-child.active { - color: #fff; - background: #5e72e4; - background: var(--primary); -} -.main .main-left .nav > li > a:first-child.active::before { - color: #fff !important; -} -.main .main-left .nav > li > a:first-child.active::after { - transform: rotate(90deg); - color: #fff !important; -} -.main .main-left .nav > li > a:first-child:hover { - cursor: pointer; - color: #fff; - background: #5e72e4; - background: var(--primary); -} -.main .main-left .nav > li > a:first-child:hover::before { - color: #fff !important; -} -.main .main-left .nav > li > a:first-child::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e915"; - color: #5e72e4; - color: var(--primary); -} -.main .main-left .nav li { - padding: 0.5rem 1rem; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - padding: 0; -} -.main .main-left .nav li a { - display: block; - color: #5f6368; - color: var(--menu-color); -} -.main .main-left .nav li.slide { - padding: 0; -} -.main .main-left .nav li.slide ul { - display: none; -} -.main .main-left .nav li.slide:hover { - background: none; -} -.main .main-left .nav li.slide .slide-menu { - margin: 0 0.5rem 0 2.5rem; - padding: 0rem 0.5rem; -} -.main .main-left .nav li.slide .slide-menu li { - position: relative; - border-radius: 0.375rem; - margin: 0; - padding: 0.5rem 0rem; - background: none; - list-style: none; -} -.main .main-left .nav li.slide .slide-menu li a { - white-space: nowrap; - text-decoration: none; -} -.main .main-left .nav li.slide .slide-menu li::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 0; - height: 2px; - background-color: #5e72e4; - background-color: var(--primary); - transition: all 0.2s; -} -.main .main-left .nav li.slide .slide-menu li:hover { - background: none; -} -.main .main-left .nav li.slide .slide-menu li:hover::after { - width: 100%; -} -.main .main-left .nav li.slide .slide-menu .active { - background: none; - color: var(--menu-color); -} -.main .main-left .nav li.slide .slide-menu .active a { - color: var(--menu-color); -} -.main .main-left .nav li.slide .slide-menu .active::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 100%; - height: 2px; - background-color: #5e72e4; - background-color: var(--primary); - transition: all 0.2s; -} -.main .main-left .nav li.slide .slide-menu .active:hover { - background: none; -} -.main .main-left .nav li.slide .slide-menu .active:hover::after { - width: 100%; -} -.main .main-left .nav li .menu { - display: block; - margin: 0.1rem 0.5rem 0.1rem 0.5rem; - padding: 0.675rem 0 0.675rem 2.5rem; - border-radius: 0.375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; -} -.main .main-left .nav li .menu.active { - color: #fff; - background: #5e72e4; - background: var(--primary); -} -.main .main-left .nav li .menu.active::before { - color: #fff !important; -} -.main .main-left .nav li .menu.active::after { - transform: rotate(90deg); - color: #fff !important; -} -.main .main-left .nav li .menu:hover { - cursor: pointer; - color: #fff; - background: #5e72e4; - background: var(--primary); -} -.main .main-left .nav li .menu:hover::before { - color: #fff !important; -} -.main .main-left .nav li .menu::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e915"; - color: #5e72e4; - color: var(--primary); -} -.main .main-left .nav li .menu::after { - position: absolute; - right: 0.5rem; - top: 0.8rem; - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -moz-osx-font-smoothing: grayscale; - content: '\e90f'; - transition: all 0.15s ease; - color: #ced4da; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - transition: all 0.3s; -} -.main .main-left .nav li .menu[data-title=Status]:before { - content: "\e906"; - color: #5e72e4; - color: var(--primary); -} -.main .main-left .nav li .menu[data-title=System]:before { - content: "\e90a"; - color: #fb6340; -} -.main .main-left .nav li .menu[data-title=Services]:before { - content: "\e909"; - color: #11cdef; -} -.main .main-left .nav li .menu[data-title=NAS]:before { - content: "\e90c"; - color: #f3a4b5; -} -.main .main-left .nav li .menu[data-title=VPN]:before { - content: "\e90b"; - color: #8965e0; -} -.main .main-left .nav li .menu[data-title=Network]:before { - content: "\e908"; - color: #8965e0; -} -.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before { - content: "\e90d"; - color: #2dce89; -} -.main .main-left .nav li .menu[data-title=Docker]:before { - content: "\e911"; - color: #6699ff; -} -.main .main-left .nav li .menu[data-title=Statistics]:before { - content: "\e913"; - color: #8965e0; -} -.main .main-left .nav li .menu[data-title=Control]:before { - content: "\e912"; - color: #5e72e4; - color: var(--primary); -} -.main .main-left .nav li .menu[data-title=Asterisk]:before { - content: "\e914"; - color: #fb6340; -} -.main .main-left .nav li a[data-title=Logout]:before { - content: "\e907"; - color: #adb5bd; -} -.lg { - margin: 0; - padding: 0 !important; -} -.logout { - display: block; - margin: 0.8rem 0.5rem 0.1rem 0.5rem; - padding: 0.675rem 0 0.675rem 2.5rem; - border-radius: 0.375rem; - text-decoration: none; - font-size: 1rem; - transition: all 0.2s; - position: relative; -} -.logout:before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e907"; - color: #32325d !important; -} -body[class*="node-"] > .main > .main-left > .nav > .slide > .menu::before { - transition: transform 0.1s ease-in-out; -} -body[class*="node-"] > .main > .main-left > .nav > .slide > .menu.active::before { - transition: transform 0.2s ease-in-out; -} -.main > .main-left[style*="overflow: hidden"] > .nav > .slide > .menu::before { - display: none; -} -#maincontent > .container { - margin: 0 1.25rem 1rem 1.25rem; -} -ul { - line-height: normal; -} -li { - list-style-type: none; -} -h1 { - font-size: 2rem; - padding-bottom: 10px; - border-bottom: thin solid #eee; -} -h2 { - margin: 0 0 1rem 0; - font-size: 1.25rem; - letter-spacing: 0.1rem; - padding: 1rem 1.5rem; - color: #32325d; - border-radius: 0.375rem; - background: #fff; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); -} -h3 { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - margin: 0; - margin-bottom: 0; - padding: 0.8755rem 1.5rem; - color: #32325d; - color: var(--gray-dark); - border-radius: 0.375rem; - background: #fff; -} -h4 { - margin: 0; - padding: 0.75rem 1.5rem; - font-size: 0.7rem; - font-weight: 600; - color: #525f7f; - background-color: #e9ecef; - background-color: var(--lighter); -} -h4 em { - padding: 0 0.5rem; -} -h5 { - font-size: 1rem; - margin: 2rem 0 0 0; - padding-bottom: 10px; -} -.cbi-section, -.cbi-section-error, -#iptables, -.Firewall form, -#cbi-network > .cbi-section-node, -#cbi-wireless > .cbi-section-node, -#cbi-wireless > #wifi_assoclist_table, -[data-tab-title], -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent > .container { - font-family: inherit; - font-weight: normal; - font-style: normal; - line-height: normal; - min-width: inherit; - margin: 1.5rem 0; - padding: 0rem; - border: 0; - border-radius: 0.375rem; - background-color: #fff; - box-shadow: 0 0 1rem 0 rgba(136, 152, 170, 0.15); -} -.cbi-modal .cbi-section, -.cbi-section .cbi-section { - padding: 0; - box-shadow: none; -} -.cbi-modal .cbi-tabmenu { - margin-left: 0; -} -.cbi-map-descr, -.cbi-section-descr { - font-size: small; - line-height: 1.42857143; - padding: 0.5rem 1.5rem; -} -.cbi-map-descr + fieldset { - margin-top: 1rem; -} -.cbi-map-descr > abbr { - cursor: help; - text-decoration: underline; -} -.cbi-section > legend { - display: none !important; -} -fieldset > fieldset, -.cbi-section > .cbi-section { - margin: 0; - padding: 0; - border: 0; - box-shadow: none; -} -.cbi-section > h3:first-child, -.panel-title { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - margin: 0; - margin-bottom: 0; - padding: 0.8755rem 1.5rem; - color: #32325d; - color: var(--gray-dark); -} -.cbi-section > h3:first-child, -.cbi-section > h4:first-child, -.cbi-section > p:first-child, -[data-tab-title] > h3:first-child, -[data-tab-title] > h4:first-child, -[data-tab-title] > p:first-child { - padding: 1rem; -} -.cbi-section p { - padding: 1rem; -} -table { - border-spacing: 0; - border-collapse: collapse; -} -table, -.table { - overflow-y: hidden; - width: 100%; - font-size: 90%; -} -.table .table-titles th { - background-color: #e9ecef; - background-color: var(--lighter); -} -table > tbody > tr > td, -table > tbody > tr > th, -table > tfoot > tr > td, -table > tfoot > tr > th, -table > thead > tr > td, -table > thead > tr > th, -.table > .tbody > .tr > .td, -.table > .tbody > .tr > .th, -.table > .tfoot > .tr > .td, -.table > .tfoot > .tr > .th, -.table > .thead > .tr > .td, -.table > .thead > .tr > .th, -.table > .tr > .td.cbi-value-field, -.table > .tr > .th.cbi-section-table-cell { - padding: 0.5rem; -} -.container > .cbi-section:first-of-type > .table[width="100%"] > .tr > .td { - padding: 0.6rem; -} -.cbi-section-table-cell { - line-height: 1.1; - align-self: flex-end; - flex: 1 1 auto; -} -tr > td, -tr > th, -.tr > .td, -.tr > .th, -.cbi-section-table-row::before, -#cbi-wireless > #wifi_assoclist_table > .tr:nth-child(2) { - border-top: thin solid #ddd; - padding: 1.1em 1.5rem; -} -#cbi-wireless .td, -#cbi-network .tr:first-child > .td, -.table[width="100%"] > .tr:first-child > .td, -[data-page="admin-network-diagnostics"] .tr > .td, -.tr.table-titles > .th, -.tr.cbi-section-table-titles > .th { - border-top: 0 !important; - background-color: #f6f9fc; - padding: 1.1em 1.5rem; - line-height: 1.3rem; -} -.table[width="100%"] > .tr:first-child > .td { - margin: auto 0; -} -.cbi-section-table-row { - margin-bottom: 1rem; - text-align: center !important; - background: #f4f4f4; -} -.cbi-section-table-row:last-child { - margin-bottom: 0; -} -.cbi-section-table-row > .cbi-value-field .cbi-dropdown, -.cbi-section-table-row > .cbi-value-field .cbi-input-select, -.cbi-section-table-row > .cbi-value-field .cbi-input-text, -.cbi-section-table-row > .cbi-value-field .cbi-input-password { - width: 100%; -} -.cbi-section-table-row > .cbi-value-field [data-dynlist] > input, -.cbi-section-table-row > .cbi-value-field input.cbi-input-password { - width: calc(100% - 1.5rem); -} -.cbi-section-table-row .td { - text-align: center !important; -} -div > table > tbody > tr:nth-of-type(2n), -div > .table > .tr:nth-of-type(2n) { - background-color: #f9f9f9; -} -/* fix multiple table */ -table table, -.table .table, -.cbi-value-field table, -.cbi-value-field .table, -td > table > tbody > tr > td, -.td > .table > .tbody > .tr > .td, -.cbi-value-field > table > tbody > tr > td, -.cbi-value-field > .table > .tbody > .tr > .td { - border: 0; -} -/* button style */ -.btn, -.cbi-button, -.item::after { - font-size: 0.8rem; - display: inline-block; - width: auto !important; - padding: 0.45rem 0.8rem; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all 0.2s ease-in-out; - text-align: center; - vertical-align: middle; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: rgba(0, 0, 0, 0.87); - border: 0; - border-radius: 0.2rem; - background-color: #f0f0f0; - background-image: none; - -webkit-appearance: none; - -ms-touch-action: manipulation; - touch-action: manipulation; -} -.cbi-button-up, -.cbi-button-down { - font-size: 1.2rem; - display: inline-block; - min-width: 0; - padding: 0.2rem 0.3rem; - color: transparent !important; - background: url(../icon/arrow.svg) no-repeat center; - background-size: 12px 20px; -} -.cbi-button-up { - transform: scaleY(-1); -} -.cbi-button:not(select) { - -webkit-appearance: none !important; -} -.btn:hover, -.btn:focus, -.btn:active, -.cbi-button:hover, -.cbi-button:focus, -.cbi-button:active, -.item:hover::after, -.item:focus::after, -.item:active::after, -.cbi-page-actions .cbi-button-apply + .cbi-button-save:hover, -.cbi-page-actions .cbi-button-apply + .cbi-button-save:focus, -.cbi-page-actions .cbi-button-apply + .cbi-button-save:active { - text-decoration: none; - outline: 0; -} -.btn:hover, -.btn:focus, -.cbi-button:hover, -.cbi-button:focus, -.item:hover::after, -.item:focus::after { - box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 2px rgba(0, 0, 0, 0.2); -} -.btn:active, -.cbi-button:active, -.item:active::after { - box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); -} -.cbi-button-up:hover, -.cbi-button-up:focus { - box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 -2px 2px rgba(0, 0, 0, 0.2); -} -.cbi-button-up:active { - box-shadow: 0 -10px 20px rgba(0, 0, 0, 0.19), 0 -6px 6px rgba(0, 0, 0, 0.23); -} -.btn:disabled, -.cbi-button:disabled { - cursor: not-allowed; - pointer-events: none; - opacity: 0.5; - box-shadow: none; -} -/* gray */ -.alert-message [class="btn"], -.modal div[class="btn"], -.cbi-button-find, -.cbi-button-link, -.cbi-button-up, -.cbi-button-down, -.cbi-button-neutral, -.cbi-button[name="zero"], -.cbi-button[name="restart"], -.cbi-button[onclick="hide_empty(this)"] { - font-weight: bold; - color: #fff; - border: thin solid #8898aa; - background-color: #8898aa; -} -/* dark blue */ -.btn.primary, -.cbi-page-actions .cbi-button-save, -.cbi-page-actions .cbi-button-apply + .cbi-button-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-positive, -.cbi-button-link, -.cbi-button[value="Enable"], -.cbi-button[value="Scan"], -.cbi-button[value^="Back"], -.cbi-button-neutral[onclick="handleConfig(event)"] { - font-weight: normal; - color: #fff !important; - border: thin solid #5e72e4; - border: thin solid var(--primary); - background-color: #5e72e4; - background-color: var(--primary); -} -/* light blue */ -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-action, -.cbi-button[value="Submit"], -.cbi-button[value="Upload"], -.cbi-button[value$="Apply"], -.cbi-button[onclick="addKey(event)"] { - font-weight: normal; - color: #fff !important; - border: thin solid #5e72e4; - border: thin solid var(--primary); - background-color: #5e72e4; - background-color: var(--primary); -} -/* red */ -.btn.danger, -.cbi-section-remove > .cbi-button, -.cbi-button-remove, -.cbi-button-reset, -.cbi-button-negative, -.cbi-button[value="Stop"], -.cbi-button[value="Kill"], -.cbi-button[onclick="reboot(this)"], -.cbi-button-neutral[value="Restart"] { - font-weight: normal; - color: #fff; - border: thin solid #f5365c; - border: thin solid var(--red); - background-color: #f5365c; - background-color: var(--red); -} -/* yellow */ -.btn[value="Dismiss"], -.cbi-button[value="Terminate"], -.cbi-button[value="Reset"], -.cbi-button[value="Disabled"], -.cbi-button[onclick^="iface_reconnect"], -.cbi-button[onclick="handleReset(event)"], -.cbi-button-neutral[value="Disable"] { - font-weight: normal; - color: #fff; - border: thin solid #eea236; - background-color: #f0ad4e; -} -/* green */ -.cbi-button-success, -.cbi-button-download, -.cbi-button[name="backup"], -.cbi-button[value="Download"], -.cbi-button[value="Save mtdblock"] { - font-weight: normal; - color: #fff; - border: thin solid #4cae4c; - background-color: #5cb85c; -} -.cbi-page-actions .cbi-button-link:first-child { - float: left; -} -.a-to-btn { - text-decoration: none; -} -.cbi-value-field .cbi-button-add { - font-weight: bold; - margin: 4px 0 4px 3px; - padding: 1px 6px; - display: flex; - align-items: center; -} -.tabs { - margin: 0 0 1rem 0; - padding: 0 1rem; - background-color: #FFFFFF; - border-radius: 0.375rem; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); - white-space: nowrap; - overflow-x: auto; -} -.tabs::-webkit-scrollbar { - width: 1px; - height: 5px; -} -.tabs::-webkit-scrollbar-thumb { - background-color: #f6f9fc; -} -.tabs::-webkit-scrollbar-track { - background-color: #fff; -} -.tabs li[class~="active"], -.tabs li:hover { - cursor: pointer; - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - border-radius: 0; -} -.tabs li[class~="active"] a, -.tabs li:hover a { - color: #5e72e4; - color: var(--primary); -} -.tabs li { - font-size: 0.875rem; - display: inline-block; - padding: 0.875rem 0rem; - border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); - margin: 0 0.2rem; -} -.tabs li a { - text-decoration: none; - color: #404040; - padding: 0.5rem 0.8rem; -} -.tabs li:hover { - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); -} -.cbi-tabmenu { - color: white; - padding: 0.5rem 1rem 0 1rem; - white-space: nowrap; - overflow-x: auto; -} -.cbi-tabmenu::-webkit-scrollbar { - width: 1px; - height: 5px; -} -.cbi-tabmenu::-webkit-scrollbar-thumb { - background-color: #f6f9fc; -} -.cbi-tabmenu::-webkit-scrollbar-track { - background-color: #fff; -} -.cbi-tabmenu li { - background: #dce3e9; - display: inline-block; - font-size: 0.875rem; - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; - padding: 0.5rem 0rem; - border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); - margin: 0 0.2rem; -} -.cbi-tabmenu li a { - text-decoration: none; - color: #404040; - padding: 0.5rem 0.8rem; -} -.cbi-tabmenu li:hover { - cursor: pointer; - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; -} -.cbi-tabmenu li:hover a { - color: #525f7f; -} -.cbi-tabmenu li[class~="cbi-tab"] { - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; -} -.cbi-tabmenu li[class~="cbi-tab"] a { - color: #5e72e4; - color: var(--primary); -} -.cbi-tab-descr { - padding: 0.5rem 1.5rem; -} -.cbi-section .cbi-section-remove:nth-of-type(2n), -.container > .cbi-section .cbi-section-node:nth-of-type(2n) { - background-color: #f9f9f9; -} -[data-tab-title] { - overflow: hidden; - height: 0; - opacity: 0; - margin: 0; - padding: 0rem 0rem !important; -} -[data-tab-title] p { - margin-left: 1rem; - margin-bottom: 1rem; -} -[data-tab-active="true"] { - overflow: visible; - height: auto; - opacity: 1; - transition: opacity 0.25s ease-in; - margin: inherit !important; -} -.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3), -.cbi-section[id] .cbi-section-node:nth-of-type(4n+4) { - background-color: #f9f9f9; -} -.cbi-section-node-tabbed { - margin-top: 0; - padding: 0; - border: 0 solid #d4d4d4; - border-radius: 0.375rem; -} -.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { - background-color: #f9f9f9; -} -.cbi-value-field, -.cbi-value-description { - line-height: 1.25; - display: table-cell; -} -.cbi-value-field abbr, -.cbi-value-description abbr { - color: #32325d; - color: var(--gray-dark); -} -.cbi-value-description { - font-size: small; - padding: 0.5rem; - opacity: 0.5; -} -.cbi-value-title { - display: table-cell; - float: left; - width: 23rem; - padding-top: 0.25rem; - padding-right: 2rem; - text-align: right; - word-wrap: break-word; -} -.cbi-value { - display: inline-block; - width: 100%; - padding: 0.35rem 1rem 0.2rem 1rem; - line-height: 2.4rem; -} -.cbi-value ul { - line-height: 1.25; -} -.cbi-value-field .cbi-dropdown, -.cbi-value-field .cbi-input-select, -.cbi-value input[type="text"], -.cbi-value input[type="password"] { - min-width: 18rem; -} -.cbi-value input[type="password"] { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - margin-right: 0; -} -.cbi-value input[type="password"] + .cbi-button-neutral { - height: 42px; - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin-left: 0; - border: 0; -} -#cbi-firewall-zone .cbi-input-select, -#cbi-network-switch_vlan .cbi-input-select { - min-width: 11rem; -} -#cbi-network-switch_vlan .cbi-input-text { - max-width: 3rem; -} -.cbi-input-invalid { - color: #f5365c; - border-bottom-color: #f5365c; -} -.cbi-section-error { - font-weight: bold; - line-height: 1.42857143; - margin: 18px; - padding: 6px; - border: thin solid #f5365c; - border-radius: 3px; - background-color: #fce6e6; -} -.cbi-section-error ul { - margin: 0 0 0 20px; -} -.cbi-section-error ul li { - font-weight: bold; - color: #f5365c; -} -.td[data-title]::before { - font-weight: bold; - display: none; - padding: 0.25rem 0; - content: attr(data-title) ":\20"; - text-align: left; - white-space: nowrap; -} -.tr.placeholder .td[data-title]::before { - display: none; -} -.tr[data-title]::before, -.tr.cbi-section-table-titles.named::before { - font-weight: bold; - display: table-cell; - align-self: center; - flex: 1 1 5%; - padding: 0.25rem; - content: attr(data-title) "\20"; - text-align: center; - vertical-align: middle; - white-space: normal; - word-wrap: break-word; -} -.cbi-rowstyle-1 { - background-color: #f9f9f9; -} -.cbi-rowstyle-2 { - background-color: #eee; -} -.cbi-rowstyle-2 .cbi-button-up, -.cbi-rowstyle-2 .cbi-button-down, -body:not(.Interfaces) .cbi-rowstyle-2:first-child { - background-color: #fff !important; -} -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - width: auto !important; -} -.td.cbi-section-actions { - text-align: right !important; - vertical-align: middle; -} -.td.cbi-section-actions > * { - display: inline-flex; -} -.td.cbi-section-actions > * > *, -.td.cbi-section-actions > * > form > * { - margin: 0 5px; - display: flex; - align-items: center; -} -.td.cbi-section-actions > * > form { - display: inline-flex; - margin: 0; -} -.cbi-checkbox { - margin: 0 0.25rem; -} -/* lists */ -.cbi-dynlist { - line-height: 1.3; - flex-direction: column; - min-height: 30px; - cursor: text; -} -.cbi-dynlist > .item { - position: relative; - max-width: 25rem; - pointer-events: none; - color: #8898aa; - outline: 0; -} -.cbi-dynlist[name="sshkeys"] > .item { - max-width: none; -} -.cbi-dynlist > .item::after { - position: absolute; - width: 2.2rem !important; - height: calc(100% - 0.5rem - 2px); - right: 0; - bottom: 0; - content: "\00D7"; - pointer-events: auto; - background-color: var(--red); - font-weight: normal; - font-size: 1.2rem; - display: flex; - align-items: center; - justify-content: center; - line-height: 1.5rem; - padding: 0; - margin: 0.25rem 0.1rem 0.25rem 0; - color: #fff; - border: 1px solid #f5365c; - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.cbi-dynlist > .item > span { - white-space: normal; - word-break: break-word; - line-height: 1.5rem; - padding: 0.5rem 0.5rem; - margin: 0.25rem 0.1rem; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - display: block; - transition: box-shadow 0.15s ease; - box-sizing: border-box; - min-width: 15rem; -} -.cbi-dynlist > .add-item { - display: inline-flex; - align-items: center; - width: 100%; - min-width: 16rem; -} -.cbi-dynlist > .add-item input { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - margin-right: 0; - border-right: none; -} -.cbi-dynlist > .add-item .cbi-button-add { - font-weight: normal; - font-size: 1.2rem; - display: flex; - align-items: center; - line-height: 1.5rem; - padding: 0.5rem 0.75rem; - margin: 0.25rem 0.1rem 0.25rem 0; - color: #fff; - border: 1px solid #5e72e4; - border: 1px solid var(--primary); - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.cbi-dynlist > .add-item:not([ondrop]) > input { - overflow: hidden; - width: 100%; - min-width: 15rem; - white-space: nowrap; - text-overflow: ellipsis; -} -.cbi-dynlist > .add-item[ondrop] > input { - min-width: 13rem; -} -.cbi-dynlist, -.cbi-dropdown { - position: relative; - display: inline-flex; - padding: 0.2rem 0.2rem; -} -.cbi-dropdown[placeholder*="select"] { - max-width: 25rem; - height: auto; - margin-top: -3px; -} -.cbi-dropdown > ul { - display: flex; - overflow-x: hidden; - overflow-y: auto; - width: 100%; - margin: 0 !important; - padding: 0; - list-style: none; - outline: 0; -} -.cbi-dropdown > ul.preview { - display: none; -} -.cbi-button-apply > ul.preview { - display: none; -} -.cbi-button-apply > ul.preview li { - color: #fff; -} -.cbi-button-apply > ul:first-child li { - color: #fff; -} -.cbi-dropdown > .open { - flex-basis: 15px; -} -.cbi-dropdown > .open, -.cbi-dropdown > .more { - font-size: 1rem; - font-weight: 900; - line-height: 2; - display: flex; - flex-direction: column; - flex-grow: 0; - flex-shrink: 0; - justify-content: center; - padding: 0 0.25em; - cursor: default; - text-align: center; - outline: 0; -} -.cbi-dropdown > .more, -.cbi-dropdown > ul > li[placeholder] { - font-weight: bold; - display: none; - color: #777; - text-shadow: 1px 1px 0 #fff; -} -.cbi-dropdown > ul > li { - display: none; - overflow: hidden; - align-items: center; - align-self: center; - flex-grow: 1; - flex-shrink: 1; - min-height: 20px; - padding: 0.25em; - white-space: nowrap; - text-overflow: ellipsis; -} -.cbi-dropdown > ul > li .hide-open { - display: initial; -} -.cbi-dropdown > ul > li .hide-close { - display: none; -} -.cbi-dropdown > ul > li[display]:not([display="0"]) { - border-left: thin solid #ccc; -} -.cbi-dropdown[empty] > ul { - max-width: 1px; -} -.cbi-dropdown > ul > li > form { - display: none; - margin: 0; - padding: 0; - pointer-events: none; -} -.cbi-dropdown > ul > li img { - margin-right: 0.25em; - vertical-align: middle; -} -.cbi-dropdown > ul > li > form > input[type="checkbox"] { - height: auto; - margin: 0; -} -.cbi-dropdown > ul > li input[type="text"] { - height: 20px; -} -.cbi-dropdown[open] > ul.dropdown { - position: absolute; - z-index: 1100; - display: block; - width: auto; - min-width: 100%; - max-width: none; - max-height: 200px !important; - border: 0 solid #918e8c; - background: #ffffff; - box-shadow: 0 0 4px #918e8c; - border-bottom-left-radius: 0.35rem; - border-bottom-right-radius: 0.35rem; - color: var(--main-menu-color); - margin-left: -0.2rem !important; -} -.cbi-dropdown[open] > ul.dropdown li { - color: #000; -} -.cbi-dropdown > ul > li[display], -.cbi-dropdown[open] > ul.preview, -.cbi-dropdown[open] > ul.dropdown > li, -.cbi-dropdown[multiple] > ul > li > label, -.cbi-dropdown[multiple][open] > ul.dropdown > li, -.cbi-dropdown[multiple][more] > .more, -.cbi-dropdown[multiple][empty] > .more { - display: flex; - align-items: center; - flex-grow: 1; -} -.cbi-dropdown[empty] > ul > li, -.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], -.cbi-dropdown[multiple][open] > ul.dropdown > li > form { - display: block; -} -.cbi-dropdown[open] > ul.dropdown > li .hide-open { - display: none; -} -.cbi-dropdown[open] > ul.dropdown > li .hide-close { - display: initial; -} -.cbi-dropdown[open] > ul.dropdown > li { - border-bottom: thin solid #ccc; - padding: 0.5rem 0.8rem; -} -.cbi-dropdown[open] > ul.dropdown > li label { - margin-left: 0.5rem; -} -.cbi-dropdown[open] > ul.dropdown > li[selected] { - background: #dce1fe; -} -.cbi-dropdown[open] > ul.dropdown > li.focus { - background: #dce1fe; - outline: none; -} -.cbi-dropdown[open] > ul.dropdown > li:last-child { - margin-bottom: 0; - border-bottom: 0; -} -.cbi-dropdown[open] > ul.dropdown > li[unselectable] { - opacity: 0.7; -} -.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child { - width: 100%; -} -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: 0.6; -} -.cbi-dropdown .zonebadge { - width: 100%; -} -.cbi-dropdown[open] .zonebadge { - width: auto; -} -/* progressbar */ -.cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - margin: 6px 0; - border: thin solid #999; - background: #eee; - border-radius: 0.2rem; - overflow: hidden; -} -.cbi-progressbar > div { - width: 0; - height: 100%; - transition: width 0.25s ease-in; - background: #5e72e4; - background: var(--primary); -} -.cbi-progressbar::after { - font-family: monospace; - font-size: 1em; - font-weight: bold; - font-size-adjust: 0.38; - line-height: normal; - position: absolute; - top: 2px; - right: 0; - bottom: 2px; - left: 0; - overflow: hidden; - content: attr(title); - text-align: center; - white-space: pre; - text-overflow: ellipsis; -} -#modal_overlay { - position: fixed; - z-index: 900; - top: 0; - right: 10000px; - bottom: 0; - left: -10000px; - overflow-y: scroll; - transition: opacity 0.125s ease-in; - opacity: 0; - background: rgba(0, 0, 0, 0.7); - -webkit-overflow-scrolling: touch; -} -.modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 90%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - margin: 5em auto; - padding: 1em; - border-radius: 3px !important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); -} -.modal > * { - line-height: normal; - flex-basis: 100%; - margin-bottom: 0.5em; - max-width: 100%; -} -.modal > pre, -.modal > textarea { - font-size: 1rem; - font-size-adjust: 0.35; - overflow: auto; - margin-bottom: 0.5em; - padding: 8.5px; - cursor: auto; - white-space: pre-wrap; - color: #eee; - outline: 0; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); -} -.modal > h4 { - margin: 0.5em 0; -} -.modal ul { - margin-left: 2.2em; -} -.modal li { - list-style-type: square; - color: #808080; -} -.modal p { - word-break: break-word; -} -.modal .label { - font-size: 0.6rem; - font-weight: normal; - padding: 0.1rem 0.3rem; - padding-bottom: 0; - cursor: default; - border-radius: 0; -} -.modal .label.warning { - background-color: #f0ad4e !important; -} -.modal .btn { - padding: 0.45rem 0.8rem; -} -.modal.cbi-modal { - max-width: 90%; - max-height: none; -} -body.modal-overlay-active { - overflow: hidden; - height: 100vh; -} -body.modal-overlay-active #modal_overlay { - right: 0; - left: 0; - opacity: 1; -} -.spinning { - position: relative; - padding-left: 32px !important; -} -.spinning::before { - position: absolute; - top: 0; - bottom: 0; - left: 0.2em; - width: 32px; - content: ""; - background: url(/luci-static/resources/icons/loading.gif) no-repeat center; - background-size: 16px; -} -/* luci */ -.hidden { - display: none; -} -.left, -.left::before { - text-align: left !important; -} -.right, -.right::before { - text-align: right !important; -} -.center, -.center::before { - text-align: center !important; -} -.top { - align-self: flex-start !important; - vertical-align: top !important; -} -.bottom { - align-self: flex-end !important; - vertical-align: bottom !important; -} -.inline { - display: inline; -} -.cbi-page-actions { - padding-top: 1rem; - text-align: right; -} -.cbi-page-actions > form[method="post"] { - display: inline-block; -} -.th[data-type="button"], -.td[data-type="button"], -.th[data-type="fvalue"], -.td[data-type="fvalue"] { - flex: 1 1 2em; - text-align: center; -} -.ifacebadge { - display: inline-flex; - padding: 0.5rem 0.8rem; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} -td > .ifacebadge, -.td > .ifacebadge { - font-size: 0.8rem; - background-color: #f0f0f0; -} -.ifacebadge > em, -.ifacebadge > img { - display: inline-block; - align-self: flex-start; - margin: 0 0.2rem; -} -.ifacebadge > img + img { - margin: 0 0.2rem 0 0; -} -.network-status-table { - display: flex; - flex-wrap: wrap; -} -.network-status-table .ifacebox { - flex-grow: 1; - margin: 0.5em; -} -.network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; -} -.network-status-table .ifacebox-body > span { - flex: 10 10 auto; - height: 100%; -} -.network-status-table .ifacebox-body > div { - display: flex; - flex-wrap: wrap; -} -.network-status-table .ifacebox-body .ifacebadge { - align-items: center; - flex: 1 1 auto; - min-width: 220px; - margin: 0.5em 0em 0 0em; - padding: 0.5em; - background-color: #fff; -} -/* textarea */ -.cbi-input-textarea { - font-family: monospace; - width: 100%; - font-size: 0.875rem; - min-height: 14rem; - padding: 0.8rem; - color: #000; -} -#syslog { - font-size: small; - line-height: 1.25; - overflow-y: hidden; - width: 100%; - min-height: 15rem; - padding: 1rem; - resize: none; - color: #242424; - border: 0; - border-radius: 0.375rem; - background-color: #ffffff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); -} -#syslog:focus { - outline: 0; -} -/* config changes */ -.uci-change-list { - font-family: monospace; -} -.uci-change-list ins, -.uci-change-legend-label ins { - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #0f0; - background-color: #cfc; -} -.uci-change-list del, -.uci-change-legend-label del { - font-style: normal; - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #f00; - background-color: #fcc; -} -.uci-change-list var, -.uci-change-legend-label var { - font-style: normal; - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #ccc; - background-color: #eee; -} -.uci-change-list var ins, -.uci-change-list var del { - font-style: normal; - padding: 0; - white-space: pre; - border: 0; -} -.uci-change-legend { - padding: 5px; -} -.uci-change-legend-label { - float: left; - width: 150px; -} -.uci-change-legend-label > ins, -.uci-change-legend-label > del, -.uci-change-legend-label > var { - display: block; - float: left; - width: 10px; - height: 10px; - margin-right: 4px; -} -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - line-height: 0.4; - border: 0; -} -.uci-change-list var, -.uci-change-list del, -.uci-change-list ins { - padding: 0.5rem; -} -/* other fix */ -#iwsvg, -#iwsvg2, -#bwsvg { - border: thin solid #d4d4d4 !important; -} -#iwsvg, -[data-page="admin-status-realtime-bandwidth"] #bwsvg { - border-top: 0 !important; -} -.ifacebox { - line-height: 1.25; - display: inline-flex; - flex-direction: column; - min-width: 100px; - border-bottom: thin solid #ccc; - background-color: #f9f9f9; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.2); -} -.ifacebox-head { - padding: 0.25em; - background: #eee; -} -.ifacebox-head.active { - background: #5e72e4; - background: var(--primary); -} -.ifacebox-head.active * { - color: #fff; - color: var(--white); -} -.ifacebox-body { - padding: 0.5em 1rem; - line-height: 1.6em; -} -.cbi-image-button { - margin-left: 0.5rem; -} -.zonebadge { - display: inline-block; - padding: 0.2rem 0.5rem; -} -.zonebadge .ifacebadge { - margin: 0.1rem 0.2rem; - padding: 0.2rem 0.3rem; - border: thin solid #6c6c6c; -} -.zonebadge > input[type="text"] { - min-width: 10rem; - margin-top: 0.3rem; - padding: 0.16rem 1rem; -} -.zonebadge > em, -.zonebadge > strong { - display: inline-block; - margin: 0 0.2rem; -} -.cbi-value-field .cbi-input-checkbox, -.cbi-value-field .cbi-input-radio { - margin-top: 0.1rem; -} -.cbi-value-field > ul > li { - display: flex; -} -.cbi-value-field > ul > li > label { - margin-top: 0.5rem; -} -.cbi-value-field > ul > li .ifacebadge { - margin-top: -0.5rem; - margin-left: 0.4rem; - background-color: #eee; -} -.cbi-section-table-row > .cbi-value-field .cbi-dropdown { - min-width: 7rem; -} -.cbi-section-create { - display: inline-flex; - align-items: center; - margin: 0.25rem 0 0.25rem 1rem; -} -.cbi-section-create > * { - margin: 0.5rem; -} -.cbi-section-remove { - padding: 0.5rem; -} -div.cbi-value var, -td.cbi-value-field var, -.td.cbi-value-field var { - font-style: italic; - color: #0069d6; -} -.cbi-optionals { - padding: 1rem 1rem 0 1rem; - border-top: thin solid #ccc; -} -.cbi-dropdown-container { - position: relative; -} -.cbi-tooltip-container, -span[data-tooltip], -span[data-tooltip] .label { - cursor: help !important; -} -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - padding: 2px 5px; - transition: opacity 0.25s ease-out; - white-space: pre; - pointer-events: none; - opacity: 0; - border-radius: 3px; - background: #fff; - box-shadow: 0 0 2px #444; -} -.cbi-tooltip-container:hover .cbi-tooltip { - left: auto; - transition: opacity 0.25s ease-in; - opacity: 1; -} -.zonebadge .cbi-tooltip { - margin: -1.5rem 0 0 -0.5rem; - padding: 0.25rem; - background: inherit; -} -.zonebadge-empty { - color: #404040; - background: repeating-linear-gradient(45deg, rgba(204, 204, 204, 0.5), rgba(204, 204, 204, 0.5) 5px, rgba(255, 255, 255, 0.5) 5px, rgba(255, 255, 255, 0.5) 10px); -} -.zone-forwards { - display: flex; - min-width: 10rem; -} -.zone-forwards > * { - flex: 1 1 45%; -} -.zone-forwards > span { - flex-basis: 10%; - padding: 0 0.25rem; - text-align: center; -} -.zone-forwards .zone-src, -.zone-forwards .zone-dest { - display: flex; - flex-direction: column; -} -.label { - font-size: 0.8rem; - font-weight: bold; - padding: 0.3rem 0.8rem; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: #fff !important; - border-radius: 3px; - background-color: #bfbfbf; - text-shadow: none; -} -label > input[type="checkbox"], -label > input[type="radio"] { - position: relative; - top: 0.4rem; - right: 0.2rem; - margin: 0; - vertical-align: bottom; -} -label[data-index][data-depends] { - padding-right: 2em; -} -.showSide { - display: none; -} -.darkMask { - position: fixed; - z-index: 99; - display: none; - width: 100%; - height: 100%; - content: ""; - top: 0; - background-color: rgba(0, 0, 0, 0.56); -} -/* diagnostics */ -#diag-rc-output > pre, -#command-rc-output > pre, -[data-page="admin-services-wol"] .notice code { - font-size: 1.2rem; - font-size-adjust: 0.35; - line-height: normal; - display: block; - overflow-y: hidden; - width: 100%; - padding: 8.5px; - white-space: pre; - color: #eee; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); -} -[data-page="admin-network-diagnostics"] .table { - box-shadow: none; -} -input[name="ping"], -input[name="traceroute"], -input[name="nslookup"] { - width: 80%; -} -/* fix status */ -.node-status-overview > .main fieldset:nth-child(4) .td:nth-child(2), -.node-status-processes > .main .table .tr .td:nth-child(3) { - white-space: normal; -} -/* fix system reboot */ -[data-page="admin-system-reboot"] p { - padding-left: 1.5rem; -} -[data-page="admin-system-reboot"] .cbi-button { - background: #fb6340 !important; -} -[data-page="admin-system-reboot"] p > span { - position: relative; - top: 0.1rem; - left: 1rem; -} -[data-page="admin-vpn-passwall"] h4 { - background: transparent; -} -/* samba */ -#cbi-samba [data-tab="template"] .cbi-value-field { - display: block; -} -#cbi-samba [data-tab="template"] .cbi-value-title { - width: auto; - padding-bottom: 0.6rem; -} -/* admin-system-admin-password */ -[data-page="admin-system-admin"] .cbi-map h2, -[data-page="admin-system-admin-password"] .cbi-map h2, -[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, -[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - margin-left: 0; - color: #32325d; - color: var(--gray-dark); -} -/* software */ -[data-page="admin-system-opkg"] h2 { - margin-left: 0; - color: #32325d; - color: var(--gray-dark); -} -.controls { - margin: 0.5em 1rem 1em 1rem !important; -} -.controls > * > .btn:not([aria-label$="page"]) { - flex-grow: initial !important; - margin-top: 0.25rem; -} -.controls > #pager > .btn[aria-label$="page"] { - font-size: 1.4rem; - font-weight: bold; -} -.controls > * > label { - margin-bottom: 0.2rem; -} -[data-page="admin-system-opkg"] div.btn { - line-height: 3; - display: inline; - padding: 0.3rem 0.6rem; -} -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent > .container { - margin-top: 2rem; - padding-top: 0.1rem; -} -[data-page="admin-system-opkg"] #maincontent > .container { - margin: 0 1.25rem 1rem 1.25rem; - margin-bottom: 1rem; -} -.td.version, -.td.size { - white-space: normal !important; - word-break: break-word; -} -.cbi-tabmenu + .cbi-section { - margin-top: 0; -} -/* admin-system-crontab*/ -[data-page="admin-system-crontab"] #view p { - margin-bottom: 1rem; -} -/*admin-system-flash*/ -[data-page="admin-system-flash"] .cbi-value { - padding: 0; -} -[data-page="admin-system-flash"] .cbi-section .cbi-section { - margin-top: 0; -} -[data-page="admin-system-flash"] .cbi-map-tabbed { - border-radius: 0.375rem; -} -[data-page="admin-system-flash"] legend { - display: block !important; - font-size: 1.2rem; - width: 100%; - display: block; - margin-bottom: 0; - padding: 1rem 0 1rem 1.5rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: 0.1rem; - color: #32325d; - font-weight: bold; -} -[data-page="admin-system-flash"] .cbi-section-descr { - font-weight: 600; - padding: 1rem 0 1rem 1.5rem; - color: #525f7f; -} -[data-page="admin-system-flash"] .modal label > input[type="checkbox"] { - top: -0.35rem; -} -[data-page="admin-system-flash"] .modal .btn { - white-space: normal !important; -} -/* wireless overview */ -#cbi-wireless > #wifi_assoclist_table > .tr { - box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; -} -#cbi-wireless > #wifi_assoclist_table > .tr.placeholder > .td { - right: 33px; - bottom: 33px; - left: 33px; - border-top: thin solid #ddd !important; -} -#cbi-wireless > #wifi_assoclist_table > .tr.table-titles { - box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; -} -#cbi-wireless > #wifi_assoclist_table > .tr.table-titles > .th { - border-bottom: thin solid #ddd; - box-shadow: 0 -1px 0 0 #ddd; -} -#wifi_assoclist_table > .tr > .td[data-title="RX Rate / TX Rate"] { - width: 23rem; -} -[data-page="admin-network-dhcp"] .cbi-value { - padding: 0; -} -[data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem 0 !important; -} -/* firewall */ -#iptables { - margin: 0; -} -.Firewall form { - margin: 2rem 2rem 0 0; - padding: 0; - box-shadow: none; -} -#cbi-firewall-redirect table *, -#cbi-network-switch_vlan table *, -#cbi-firewall-zone table * { - font-size: small; -} -#cbi-firewall-redirect table input[type="text"], -#cbi-network-switch_vlan table input[type="text"], -#cbi-firewall-zone table input[type="text"] { - width: 5rem; -} -#cbi-firewall-redirect table select, -#cbi-network-switch_vlan table select, -#cbi-firewall-zone table select { - min-width: 3.5rem; -} -#cbi-network-switch_vlan .th, -#cbi-network-switch_vlan .td { - flex-basis: 12%; -} -#cbi-firewall-zone .table, -#cbi-network-switch_vlan .table { - display: block; -} -#cbi-firewall-zone .td, -#cbi-network-switch_vlan .td { - width: 100%; -} -[data-page="admin-network-firewall-custom"] #view p, -[data-page="admin-status-routes"] #view p { - padding: 0 1.5rem; - margin-bottom: 1rem; -} -[data-page="admin-network-firewall-custom"] #view p textarea, -[data-page="admin-status-routes"] #view p textarea { - padding: 1rem; - border-radius: 0.375rem; -} -/* applyreboot fix */ -#applyreboot-container { - margin: 2rem; -} -#applyreboot-section { - line-height: 300%; - margin: 2rem; -} -/* openvpn bug fix */ -.OpenVPN a { - line-height: initial !important; -} -/* custom commands */ -.commandbox { - width: 24% !important; - margin: 10px 0 0 10px !important; - padding: 0.5rem 1rem; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.commandbox h3 { - line-height: normal !important; - overflow: hidden; - margin: 6px 0 !important; - white-space: nowrap; - text-overflow: ellipsis; -} -.commandbox div { - left: auto !important; -} -.commandbox code { - position: absolute; - overflow: hidden; - max-width: 60%; - margin-left: 4px; - padding: 2px 3px; - white-space: nowrap; - text-overflow: ellipsis; -} -.commandbox code:hover { - overflow-y: auto; - max-height: 50px; - white-space: normal; -} -.commandbox p:first-of-type { - margin-top: -6px; -} -.commandbox p:nth-of-type(2) { - margin-top: 2px; -} -[data-page^="admin-system-commands"] .panel-title, -[data-page^="command-cfg"] .mobile-hide, -[data-page^="command-cfg"] .showSide { - display: none; -} -#command-rc-output .alert-message { - line-height: 1.42857143; - position: absolute; - top: 40px; - right: 32px; - max-width: 40%; - margin: 0; - animation: anim-fade-in 1.5s forwards; - word-break: break-word; - opacity: 0; -} -@keyframes anim-fade-in { - 100% { - opacity: 1; - } -} -/* other fix */ -input[type="checkbox"] { - appearance: none !important; - -webkit-appearance: none !important; - border: 1px solid #dee2e6; - width: 16px !important; - height: 16px !important; - padding: 0; - cursor: pointer; - transition: all 0.2s; - margin: 1rem 0 0 0; -} -input[type="checkbox"]:checked { - border: 1px solid #5e72e4; - border: 1px solid var(--primary); - background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; - background-color: #5e72e4; - background-color: var(--primary); - background-size: 70%; - background-repeat: no-repeat; - background-position: center; -} -.fb-container .cbi-button { - height: auto !important; -} -#cbi-usb_printer-printer em { - display: block; - padding: 1rem; - text-align: center; -} -pre.command-output { - padding: 1.5rem; -} -[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { - padding: 1.5rem !important; -} -[data-page="admin-nlbw-backup"] form { - padding-left: 1.5rem; -} -[data-page="admin-status-iptables"] .right { - margin-bottom: 0 !important; -} -/* IE hacks */ -@media all and (-ms-high-contrast: none) { - .main > .main-left > .nav > .slide > .menu::before { - top: 30.25%; - } - .main > .main-left > .nav > li:last-child::before { - top: 20%; - } - .showSide::before { - top: -12px; - } -} -@media screen and (max-width: 1600px) { - header > .fill > .container > #logo { - margin: 0 2.5rem 0 0.5rem; - } - .main-left { - width: calc(0% + 13rem); - } - .main-right { - width: calc(100% - 13rem); - } - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - } - .label { - padding: 0.2rem 0.6rem; - } - .cbi-value-title { - width: 15rem; - padding-right: 0.6rem; - } - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 18rem; - } - #cbi-firewall-zone .cbi-input-select { - min-width: 9rem; - } - .cbi-input-textarea { - font-size: small; - } - .node-admin-status > .main fieldset li > a { - padding: 0.3rem 0.6rem; - } -} -@media screen and (max-width: 1366px) { - header > .fill > .container { - cursor: default; - } - .main-left { - width: calc(0% + 13rem); - } - .main-right { - width: calc(100% - 13rem); - } - .tabs > li > a, - .cbi-tabmenu > li > a { - padding: 0.2rem 0.8rem; - } - .panel-title { - font-size: 1.1rem; - padding-bottom: 1rem; - } - table { - font-size: 0.7rem !important; - width: 100% !important; - } - .table .cbi-input-text { - width: 100%; - } - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 16rem; - } - #cbi-firewall-zone .cbi-input-select { - min-width: 4rem; - } - .main > .main-left > .nav > li, - .main > .main-left > .nav > li > a, - .main .main-left .nav > li > a:first-child, - .main > .main-left > .nav > .slide > .menu, - .main > .main-left > .nav > li > [data-title="Logout"] { - font-size: 0.9rem; - } - .main > .main-left > .nav > .slide > .slide-menu > li > a { - font-size: 0.7rem; - } - #modal_overlay { - top: 0rem; - } - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { - display: block; - } - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), - [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), - [data-page="admin-network-hosts"] .table, - [data-page="admin-network-routes"] .table { - overflow-y: visible; - } - .commandbox { - width: 32% !important; - } - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - } -} -@media screen and (max-width: 1152px) { - header > .fill > .container > #logo { - display: none; - } - header > .fill > .container > .brand { - position: relative; - } - html, - .main { - overflow-y: visible; - } - .main > .loading > span { - top: 25%; - } - .main-left { - width: calc(0% + 13rem); - } - .main-right { - width: calc(100% - 13rem); - } - body:not(.logged-in) .showSide { - visibility: hidden; - width: 0; - margin: 0; - } - .node-main-login > .main .cbi-value-title { - text-align: left; - } - .cbi-value-title { - width: 12rem; - padding-right: 1rem; - } - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"] { - width: 16rem; - min-width: 16rem; - } - /*.cbi-value input[type="password"],*/ - .cbi-value input[name^="pw"], - .cbi-value input[data-update="change"]:nth-child(2) { - width: 13rem !important; - min-width: 13rem; - } - #diag-rc-output > pre, - #command-rc-output > pre, - [data-page="admin-services-wol"] .notice code { - font-size: 1rem; - } - .table { - display: block; - } - .Interfaces .table { - overflow-x: hidden; - } - #packages.table { - display: grid; - } - .tr { - display: flex; - flex-direction: row; - flex-wrap: wrap; - } - .Overview .table[width="100%"] > .tr { - flex-wrap: nowrap; - } - .tr.placeholder { - border-bottom: thin solid #ddd; - } - .tr.placeholder > .td, - #cbi-firewall .tr > .td, - #cbi-network .tr:nth-child(2) > .td, - .cbi-section #wifi_assoclist_table .tr > .td { - border-top: 0; - } - .th, - .td { - display: inline-block; - align-self: flex-start; - flex: 2 2 10%; - text-overflow: ellipsis; - word-wrap: break-word; - } - .td select, - .td input[type="text"] { - width: 100%; - word-wrap: normal; - } - .td [data-dynlist] > input, - .td input.cbi-input-password { - width: calc(100% - 1.5rem); - } - .td[data-type="button"], - .td[data-type="fvalue"] { - flex: 1 1 12.5%; - text-align: left; - } - .th.cbi-value-field, - .td.cbi-value-field, - .th.cbi-section-table-cell, - .td.cbi-section-table-cell { - flex-basis: auto; - padding-top: 1rem; - } - .cbi-section-table-row { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-between; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - } - .td.cbi-value-field, - .cbi-section-table-cell { - display: inline-block; - flex: 10 10 auto; - flex-basis: 50%; - text-align: center; - } - .td.cbi-section-actions { - vertical-align: bottom; - } - .tr.table-titles, - .tr.cbi-section-table-titles, - .tr.cbi-section-table-descr { - display: none; - } - .tr[data-title]::before, - .tr.cbi-section-table-titles.named::before { - font-size: 0.9rem; - display: block; - flex: 1 1 100%; - border-bottom: thin solid rgba(0, 0, 0, 0.26); - background: #e9ecef; - } - .td[data-title], - [data-page^="admin-status-realtime"] .td[id] { - text-align: left; - } - .td[data-title]::before { - display: block; - } - .cbi-button + .cbi-button { - margin-left: 0; - } - .td.cbi-section-actions > * > *, - .td.cbi-section-actions > * > form > * { - margin: 2.1px 3px; - } - .Firewall form { - position: static !important; - margin: 0 0 2rem 0; - padding: 2rem; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - } - .Firewall form input { - width: 100% !important; - margin: 0; - margin-top: 1rem; - } - .Firewall .center, - .Firewall .center::before { - text-align: left !important; - } - .commandbox { - width: 100% !important; - margin-left: 0 !important; - } - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - } -} -@media screen and (max-width: 768px) { - body { - font-size: 0.8rem; - } - .cbi-progressbar::after { - font-size: 0.5rem; - line-height: 1.5; - } - .main-left { - position: fixed; - z-index: 100; - width: 0; - } - .main-right { - width: 100%; - } - .showSide { - padding: 0.1rem; - position: relative; - z-index: 99; - display: inline-block !important; - } - .showSide::before { - font-family: 'argon' !important; - font-style: normal !important; - font-weight: normal !important; - font-variant: normal !important; - text-transform: none !important; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: "\e20e"; - font-size: 1.7rem; - } - header > .fill > .container > .brand { - display: inline-block; - } - .main > .main-left > .nav > .slide > .slide-menu > li > a { - font-size: 0.8rem; - } -} -@media screen and (max-width: 600px) { - .mobile-hide { - display: none; - } - #maincontent > .container { - margin: 0 1rem 1rem 1rem; - } - .cbi-value-title { - text-align: left; - } - [data-page="admin-system-flash"] legend { - padding: 1rem 0 1rem 1rem; - } - [data-page="admin-system-flash"] .cbi-section-descr { - padding: 1rem 0 1rem 1rem; - } - [data-page="admin-system-flash"] .cbi-value { - padding: 0 1rem; - } - [data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem 1rem !important; - } - .cbi-dynlist p { - padding: 0.5rem 1rem; - } - body { - overflow-x: hidden; - } - .node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field { - width: 16rem; - } - .node-main-login footer { - display: none; - } - .tabs::-webkit-scrollbar, - .cbi-tabmenu::-webkit-scrollbar { - width: 0px; - height: 0px; - } - .cbi-value-field, - .cbi-value-description { - display: block !important; - padding-left: 0 !important; - padding-right: 0 !important; - } - [data-page="admin-system-admin-password"] .cbi-value-field { - display: table-cell !important; - } - .modal.cbi-modal { - max-width: 100%; - max-height: none; - } - .modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 100%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - margin: 5em auto; - padding: 1em; - border-radius: 3px !important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - } - .cbi-dropdown[open] > ul.dropdown { - left: 0.2rem !important; - right: 0 !important; - margin-bottom: 1rem; - } -} -@media screen and (min-width: 600px) { - ::-webkit-scrollbar { - width: 10px; - height: 10px; - } - ::-webkit-scrollbar, - ::-webkit-scrollbar-corner { - background: transparent; - } - ::-webkit-scrollbar-thumb { - background: #9e9e9e; - } - ::-webkit-scrollbar-thumb:hover { - background: #757575; - } - ::-webkit-scrollbar-thumb:active { - background: #424242; - } -} -@media screen and (max-width: 480px) { - .mobile-hide { - display: none; - } - .login-page .login-container { - margin-left: 0rem !important; - width: 100%; - } - .login-page .login-container .login-form .form-login .input-group::before { - color: #525461; - } - .login-page .login-container .login-form .form-login .input-group input { - color: #525461; - border-bottom: white 1px solid; - border-bottom: var(--white) 1px solid; - border-radius: 0; - } -} diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/dark.css b/luci-theme-argon/htdocs/luci-static/argon/css/dark.css deleted file mode 100644 index 2b52701c3..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/css/dark.css +++ /dev/null @@ -1,646 +0,0 @@ -/** - * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template - * - * luci-theme-argon - * Copyright 2020 Jerryk - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-bootstrap: - * Copyright 2008 Steven Barth - * Copyright 2008 Jo-Philipp Wich - * Copyright 2012 David Menting - * - * MUI: - * https://github.com/muicss/mui - * - * luci-theme-material: - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * - * Licensed to the public under the Apache License 2.0 - */ -body { - background: #1e1e1e; - color: #cccccc; -} -.login-page .login-container .login-form { - background-color: #1e1e1e; -} -.login-page .login-container .login-form .brand { - color: #adb5bd; -} -.login-page .login-container .login-form .form-login .input-group::before { - color: #adb5bd; -} -.login-page .login-container .login-form .form-login .input-group input { - background-color: transparent !important; - color: #adb5bd; - border-bottom: #adb5bd 1px solid !important; - border-radius: 0 !important; - border-top: none !important; - border-left: none !important; - border-right: none !important; - box-shadow: none; -} -.login-page .login-container .login-form .form-login .cbi-button-apply { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; -} -.login-page .login-container .login-form .form-login .cbi-button-apply:hover, -.login-page .login-container .login-form .form-login .cbi-button-apply:focus { - opacity: 0.9; -} -header::after { - background-color: #1e1e1e !important; -} -.main .main-left { - background-color: #333333 !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.15); -} -.main .main-left .sidenav-header .brand { - color: #ccc; -} -.main .main-left .nav .slide .slide-menu .active a { - color: #cccccc; -} -.main .main-left .nav .slide .slide-menu .active a::after { - background-color: #cccccc !important; -} -.main .main-left .nav .slide .slide-menu li a { - color: #cccccc; -} -.main .main-left .nav .slide .slide-menu li a:hover { - background: none !important; -} -.main .main-left .nav .slide .menu.active { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - color: #cccccc !important; -} -.main .main-left .nav .slide .menu.active a::after { - background-color: #cccccc !important; -} -.main .main-left .nav li a { - color: #cccccc !important; -} -.main .main-left .nav li a:hover { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - color: #cccccc !important; -} -.main .main-left::-webkit-scrollbar-thumb { - background-color: #252526 !important; -} -.main .main-left::-webkit-scrollbar-track { - background-color: #333; -} -.main .main-right { - background-color: #1e1e1e; -} -h2 { - color: #ccc; - background: #333333; -} -h3 { - color: #ccc; - border-bottom: 0; - background: #333333; -} -a:-webkit-any-link { - color: -webkit-link; - cursor: pointer; - color: #483d8b; - color: var(--dark-primary); -} -input:-webkit-autofill { - background-color: #3c3c3c !important; -} -.cbi-value-field .cbi-input-apply, -.cbi-button-apply, -.cbi-button-edit { - color: #fff !important; - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; -} -.cbi-section em { - color: #ccc; -} -header.bg-primary { - background-color: #1e1e1e !important; -} -.cbi-map-descr { - color: #ccc; -} -.cbi-section { - background: none; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); -} -.panel-title { - color: #ccc; - background-color: #333333; - border-bottom: 0px; -} -div > table > tbody > tr:nth-of-type(2n), -div > .table > .tr:nth-of-type(2n) { - background-color: #252526; -} -table > tbody > tr > td, -table > tfoot > tr > td, -table > thead > tr > td { - color: #ccc; -} -fieldset > table > tbody > tr:nth-of-type(2n) { - background-color: #252526; -} -table > tbody > tr > td, -table > tfoot > tr > td, -table > thead > tr > td { - border-top: 1px solid #252526; -} -#swaptotal > div > div, -#swapfree > div > div, -#memfree > div > div, -#membuff > div > div, -#conns > div > div, -#memtotal > div > div { - background-color: #32325d !important; -} -#swaptotal > div > div > div > small, -#swapfree > div > div > div > small, -#memfree > div > div > div > small, -#membuff > div > div > div > small, -#conns > div > div > div > small, -#memtotal > div > div > div > small { - color: #ccc !important; -} -.node-system-packages > .main .cbi-section-node:first-child .cbi-value-last { - line-height: 1.8em; -} -.node-system-packages > .main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] { - border: 1px solid #999999 !important; - background-color: transparent !important; -} -.node-system-packages > .main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div { - background-color: #32325d !important; -} -table > tbody > tr > th, -table > tfoot > tr > th, -table > thead > tr > th { - background-color: #252526; - border-bottom: black 1px solid !important; -} -tr > td, -tr > th, -.tr > .td, -.tr > .th, -.cbi-section-table-row::before, -#cbi-wireless > #wifi_assoclist_table > .tr:nth-child(2) { - border-top: 0; -} -.cbi-rowstyle-2 { - background-color: #1e1e1e; -} -.cbi-rowstyle-1 { - background-color: #252526; -} -.cbi-section > h3:first-child, -.panel-title, -h3 { - color: #ccc; - border-bottom: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} -h4 { - background-color: #1e1e1f; -} -.cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - margin: 6px 0; - border: thin solid #999; - background: transparent; - border-radius: 0.2rem; - overflow: hidden; -} -.cbi-progressbar div { - background-color: #32325d !important; -} -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - background-color: #1e1e1f; -} -.cbi-button { - color: #ccc !important; - background-color: #483d8b; - background-color: var(--dark-primary); -} -.cbi-section-node { - background: none; - border-radius: 0 0 0.375rem 0.375rem; - padding: 0rem; -} -abbr { - color: #5e72e4; -} -div > table > tbody > tr:nth-of-type(2n), -div > .table > .tbody > .tr:nth-of-type(2n) { - background-color: #252526; -} -#content_syslog { - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); -} -#syslog { - color: #ccc; - background-color: #1e1e1e; -} -#iwsvg, -#iwsvg2, -#bwsvg { - overflow: hidden; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - background-color: #1e1e1e !important; -} -.tabs { - background-color: #252526; -} -.tabs > li[class~="active"] > a { - color: #ccc; -} -.tabs > li[class~="active"], -.tabs > li:hover { - border-bottom: 0.18751rem solid #483d8b; - border-bottom: 0.18751rem solid var(--dark-primary); - color: #ccc; - background-color: #181819; -} -.cbi-tabmenu > li > a, -.tabs > li > a { - color: #ccc; -} -.cbi-tabmenu > li > a:hover, -.tabs > li > a:hover { - color: #ccc; -} -.cbi-tabmenu > li { - background: #2d2d2d; -} -.cbi-tabmenu li[class~="cbi-tab"] a { - color: #ccc; -} -.cbi-tabmenu > li:hover { - color: #ccc; - background: #2d2d2d; -} -.cbi-tabmenu > li[class~="cbi-tab"] { - background-color: #181819; -} -.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { - background-color: #252526; -} -.cbi-value-title { - color: #ccc; -} -select, -input { - color: #ccc; - background-color: transparent !important; - border: 1px solid #252526; - box-shadow: none; -} -select:not([multiple="multiple"]):focus, -input:focus { - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; - outline: 0; -} -select { - background-color: #1e1e1e !important; -} -#cbi-dropbear h2, -#cbi-dropbear .cbi-map-descr, -#cbi-dropbear .cbi-map-descr abbr, -#cbi-rc h2, -#cbi-rc .cbi-map-descr, -#cbi-distfeedconf h2, -#cbi-distfeedconf .cbi-map-descr, -#cbi-customfeedconf h2, -#cbi-customfeedconf .cbi-map-descr, -#cbi-download h2, -#cbi-filelist h2 { - color: #ccc !important; -} -.cbi-value-field > ul > li .ifacebadge { - background-color: #3c3c3c; -} -.cbi-section-descr { - color: #ccc; -} -.cbi-input-textarea { - background-color: #1e1e1e; - color: #ccc; -} -.cbi-section-remove:nth-of-type(2n), -.cbi-section-node:nth-of-type(2n) { - background-color: #1e1e1e; -} -.node-system-packages > .main table tr td:nth-last-child(1) { - color: #ccc; -} -.cbi-section-node .cbi-value { - padding: 1rem 1rem 0.3rem 1rem; -} -.ifacebox { - background-color: none; - border: 1px solid #1e1e1e; -} -.ifacebox-head { - color: #666; -} -.ifacebox-body { - background-color: #333; -} -.zonebadge strong { - color: #333; -} -.zonebadge > .ifacebadge { - background-color: #3c3c3c; -} -div.cbi-value var, -td.cbi-value-field var { - color: #5e72e4; -} -#diag-rc-output > pre { - color: #ccc; - background-color: #1e1e1e; -} -.node-services-vssr .block { - background-color: #3c3c3c !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); -} -.node-services-vssr .block h4 { - color: #ccc !important; -} -.node-services-vssr .status-bar { - color: #ccc; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - background-color: #1e1e1e; -} -.node-services-vssr .cbi-section-table-row { - color: #ccc; - background-color: #3c3c3c !important; - box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.35); -} -.node-services-vssr .cbi-section-table-row.fast { - background: #483d8b !important; - background: var(--dark-primary) !important; - color: #fff; -} -.node-services-vssr .ssr-button { - color: #ccc; -} -.node-services-vssr .incon:nth-child(2) { - border-right: #1e1e1e 1px solid; -} -#xhr_poll_status > .label.success { - color: #ccc !important; - background-color: darkolivegreen !important; -} -.notice { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; -} -.cbi-input-find, -.cbi-input-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-find, -.cbi-input-reload, -.cbi-button-reload { - color: #fff !important; - background: darkolivegreen !important; - border-color: darkolivegreen !important; -} -.cbi-button-reset, -.cbi-input-remove { - color: #fff !important; - background-color: darkorange !important; - border-color: darkorange !important; -} -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit.important, -.cbi-button-apply.important, -.cbi-button-reload.important, -.cbi-button-action.important { - border: 1px #483d8b solid !important; - border: 1px var(--dark-primary) solid !important; -} -.btn[value="Dismiss"], -.cbi-button[value="Terminate"], -.cbi-button[value="Reset"], -.cbi-button[value="Disabled"], -.cbi-button[onclick^="iface_reconnect"], -.cbi-button[onclick="handleReset(event)"], -.cbi-button-neutral[value="Disable"] { - font-weight: normal; - color: #fff; - border: thin solid darkorange !important; - background-color: darkorange !important; -} -fieldset[id^="cbi-apply-"] { - background-color: #333333; -} -#detail-bubble > div { - border: 1px solid #ccc; - border-radius: 2px; - padding: 5px; - background: #252525; -} -.ifacebox-head.active { - background-color: #32325d !important; -} -header .fill .status span[data-style="active"] { - color: #ccc !important; - background-color: darkolivegreen !important; -} -#cbi-wireless .td, -#cbi-network .tr:first-child > .td, -.table[width="100%"] > .tr:first-child > .td, -[data-page="admin-network-diagnostics"] .tr > .td, -.tr.table-titles > .th, -.tr.cbi-section-table-titles > .th { - background-color: #252526; - border-bottom: black 1px solid !important; -} -.network-status-table .ifacebox-body .ifacebadge { - background-color: #252526; - border-bottom: 0; - box-shadow: none; -} -td > .ifacebadge, -.td > .ifacebadge { - background-color: #483d8b; - background-color: var(--dark-primary); - border: 0; -} -.btn.danger, -.cbi-section-remove > .cbi-button, -.cbi-button-remove, -.cbi-button-reset, -.cbi-button-negative, -.cbi-button[value="Stop"], -.cbi-button[value="Kill"], -.cbi-button[onclick="reboot(this)"], -.cbi-button-neutral[value="Restart"] { - border: thin solid darkorange !important; - background-color: darkorange !important; -} -.cbi-section, -.cbi-section-error, -#iptables, -.Firewall form, -#cbi-network > .cbi-section-node, -#cbi-wireless > .cbi-section-node, -#cbi-wireless > #wifi_assoclist_table, -[data-tab-title], -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent > .container { - background: #1e1e1e !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); -} -div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - background: transparent !important; -} -[data-page="admin-system-admin"] .cbi-map h2, -[data-page="admin-system-admin-password"] .cbi-map h2, -[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, -[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - color: #ccc; -} -[data-page="admin-system-flash"] .modal label > input[type="checkbox"] { - top: -0.35rem; -} -[data-page="admin-system-flash"] .modal .btn { - white-space: normal !important; - background-color: darkseagreen; -} -[data-page="admin-system-flash"] .modal .alert-message { - background-color: transparent !important; -} -[data-page="admin-system-flash"] .modal .danger { - border: thin solid darkorange !important; - background-color: darkorange !important; -} -.cbi-value input[type="password"] + .cbi-button-neutral { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; -} -.btn, -button, -select, -input, -.cbi-dropdown { - border: 1px solid #3c3c3c !important; -} -.cbi-dropdown .preview { - color: #ccc; -} -.cbi-section-table-row { - background-color: #1e1e1e !important; -} -.modal { - background-color: #1e1e1e; -} -.cbi-button-positive { - color: #fff !important; - background-color: darkolivegreen !important; -} -[data-page="admin-system-flash"] legend { - color: #ccc; -} -.logout:before { - color: #adb5bd !important; -} -.cbi-dropdown[open] { - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; -} -.cbi-dropdown[open] > ul.dropdown { - background: #252526 !important; - color: #ccc !important; - box-shadow: none; - border: 1px solid #3c3c3c !important; -} -.cbi-dropdown[open] > ul.dropdown li { - color: #ccc; - border-bottom: 1px solid #3c3c3c !important; -} -.cbi-dropdown[open] > ul.dropdown > li[selected] { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - border-bottom: 1px solid #3c3c3c !important; -} -.cbi-dropdown[open] > ul.dropdown > li.focus { - background: #483d8b; - background: var(--dark-primary); - outline: none; -} -.ifacebadge { - background-color: #333333; -} -.cbi-dynlist > .item > span { - border: 1px solid #3c3c3c !important; -} -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-action, -.cbi-button[value="Submit"], -.cbi-button[value="Upload"], -.cbi-button[value$="Apply"], -.cbi-button[onclick="addKey(event)"] { - background: #483d8b !important; - background: var(--dark-primary) !important; -} -.btn.primary, -.cbi-page-actions .cbi-button-save, -.cbi-page-actions .cbi-button-apply + .cbi-button-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-positive, -.cbi-button-link, -.cbi-button[value="Enable"], -.cbi-button[value="Scan"], -.cbi-button[value^="Back"], -.cbi-button-neutral[onclick="handleConfig(event)"] { - background: #483d8b; - background: var(--dark-primary); -} -[data-page="admin-system-opkg"] h2 { - color: #ccc !important; -} -@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) { - .login-page .login-container .login-form { - -webkit-backdrop-filter: blur(var(--blur-radius-dark)); - backdrop-filter: blur(var(--blur-radius-dark)); - background-color: rgba(0, 0, 0, var(--blur-opacity-dark)); - } -} -@media screen and (max-width: 480px) { - .node-status-iptables > .main div > .cbi-map > form { - background-color: #1e1e1e; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); - } -} diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/fonts.css b/luci-theme-argon/htdocs/luci-static/argon/css/fonts.css deleted file mode 100644 index 87667288b..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/css/fonts.css +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template - * - * luci-theme-argon - * Copyright 2020 Jerryk - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-bootstrap: - * Copyright 2008 Steven Barth - * Copyright 2008 Jo-Philipp Wich - * Copyright 2012 David Menting - * - * MUI: - * https://github.com/muicss/mui - * - * luci-theme-material: - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * - * Licensed to the public under the Apache License 2.0 - */ - - -@font-face { - font-family: 'Google Sans'; - src: url('data:application/font-woff2;charset=utf-8;base64,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') format('woff2'), - url('data:application/font-woff;charset=utf-8;base64,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') format('woff'); - font-weight: normal; - font-style: normal; -} - -/* Logo Font */ -@font-face { - font-family: 'TypoGraphica'; - src: url('../fonts/TypoGraphica.eot?#iefix') format('embedded-opentype'), url('../fonts/TypoGraphica.woff') format('woff'), url('../fonts/TypoGraphica.ttf') format('truetype'), url('../fonts/TypoGraphica.svg#TypoGraphica') format('svg'); - font-weight: normal; - font-style: normal; -} - -/* ICON Font */ - -@font-face { - font-family: 'argon'; - src: url('../fonts/argon.eot?u6kthm'); - src: url('../fonts/argon.eot?u6kthm#iefix') format('embedded-opentype'), - url('../fonts/argon.ttf?u6kthm') format('truetype'), - url('../fonts/argon.woff?u6kthm') format('woff'), - url('../fonts/argon.svg?u6kthm#argon') format('svg'); - font-weight: normal; - font-style: normal; - font-display: block; -} - -[class^="icon-"], -[class*=" icon-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.icon-expand_more:before { - content: "\e20b"; -} - -.icon-menu:before { - content: "\e20e"; -} - -.icon-favorite:before { - content: "\e291"; -} - -.icon-spinner:before { - content: "\e603"; -} - -.icon-delete:before { - content: "\e900"; -} - -.icon-edit:before { - content: "\e901"; -} - -.icon-use:before { - content: "\e902"; -} - -.icon-loading:before { - content: "\e903"; -} - -.icon-switch:before { - content: "\e904"; -} - -.icon-error:before { - content: "\e905"; -} - -.icon-dashboard:before { - content: "\e906"; -} - -.icon-logout:before { - content: "\e907"; -} - -.icon-Network:before { - content: "\e908"; -} - -.icon-services:before { - content: "\e909"; -} - -.icon-system:before { - content: "\e90a"; -} - -.icon-vpn:before { - content: "\e90b"; -} - -.icon-storage:before { - content: "\e90c"; -} - -.icon-statistics:before { - content: "\e90d"; -} - -.icon-hello-world:before { - content: "\e90e"; -} - -.icon-angle-right:before { - content: "\e90f"; -} - -.icon-password:before { - content: "\e910"; -} - -.icon-user:before { - content: "\e971"; -} - -.icon-question:before { - content: "\f059"; -} - -.icon-docker:before { - content: "\e911"; -} - -.icon-control:before { - content: "\e912"; -} - -.icon-statistics1:before { - content: "\e913"; -} - -.icon-asterisk:before { - content: "\e914"; -} - -.icon-app:before { - content: "\e915"; -} diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css b/luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css deleted file mode 100644 index 31d891db3..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/css/pure-min.css +++ /dev/null @@ -1,11 +0,0 @@ -/*! -Pure v2.0.3 -Copyright 2013 Yahoo! -Licensed under the BSD License. -https://github.com/pure-css/pure/blob/master/LICENSE.md -*/ -/*! -normalize.css v | MIT License | git.io/normalize -Copyright (c) Nicolas Gallagher and Jonathan Neal -*/ -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear,left top,left bottom,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0} diff --git a/luci-theme-argon/htdocs/luci-static/argon/favicon.ico b/luci-theme-argon/htdocs/luci-static/argon/favicon.ico deleted file mode 100644 index 4611336803d49af0896adf2698cfaec54e96b800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15406 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 BLQ((# diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.eot b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.eot deleted file mode 100644 index efce636a84d6da92d5e40498fc945e93a90e4307..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33846 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 M>%j(UEQQ4X1Pp)(oB#j- diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.svg b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.svg deleted file mode 100644 index c555b7594..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.svg +++ /dev/null @@ -1,1191 +0,0 @@ - - - - -Created by FontForge 20090622 at Tue Jul 23 03:29:07 2019 - By deploy user -TypoGraphica ©Sharkshock Productions 2015. All Rights Reserved - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.ttf b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.ttf deleted file mode 100644 index e11f89a0f749b95a9001e33de3100be7a0bb858e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33632 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 diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.woff b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.woff deleted file mode 100644 index fef38ca003e3d02372d80287057424843e6bd4f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17816 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 P{|_V(EFb^?vO@>^k62-U diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.eot b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.eot deleted file mode 100644 index e28f6db55e898dd8a1d9ead5318f7528ec9286c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8888 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 JAO6eX{{!P-6bb+U diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.svg b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.svg deleted file mode 100644 index 1e12b5f6a..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.ttf b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.ttf deleted file mode 100644 index 3d062dcf264462eae98dbe9565560187362e7f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8732 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 DNS*~X diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.woff b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.woff deleted file mode 100644 index ef1e9c2c434f786a409d2e3ac47a5035872e98e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8808 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 b$ejqMF;>UORRG?q5=PhE&nt)jo%sI(Ce#aG diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/android-icon-192x192.png b/luci-theme-argon/htdocs/luci-static/argon/icon/android-icon-192x192.png deleted file mode 100644 index 7c17009d3d83e8d0aedf334165c8fcdf95df501b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6411 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 diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png deleted file mode 100644 index 5308d66b779b26d1828690516a4ab5dc01b7cec9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5222 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 aWS&p(fIu!(CjkFLSj>$d8r2y%$NwKzaNBSI diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png deleted file mode 100644 index f18dfa49cd35fa6d5cb882ea8ae703c852e313df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2561 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 diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png deleted file mode 100644 index bb3e2423331068c72c5ad0e1bc49a51e1fdd71af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2877 zcmYjSc{tSD8=r0}vX+WuN!ij(L|36)A(HGRB#dS3W{feIF_y*{)QDuu_ERKVCP@?$ zB}*himadx^%Ph>8efxcTe*gT=bIyCt`8?12p3nO^?|Dv^i<6z~UX{Hd5J>ily^R|% z+y5StI{^zewnhMx1jOo^6$nJkl@bi=&4v0EVJB1CblC z89e_uQdAlfl0*$oB*$e6pm#V3ya*h><_BMnNoU1pi^DPWkR(b(3Ox|H9-h4Q+hXWI zhh=bqemnM8Sn?)-0}Euf_;&0v;P}6Fe3l46klDX&L<%D^l>r2aOkn_92#O{aivh=| z)a`K0Rw$YV;6P;P9X2?A6@sG1W^jR+(P_*G3?1--VmSc_QXp~-pyVI70>g3uN&sOP zmIucP5O^WLJUX2fo52r5Zw4i-$J}8DC2T;FC}C(Ca5O+EJb4q~6Ou>{PS^-V(Lzzw z$W$gkDKLHwNES#WDvcF{Tn8goMIvzkVik_#0h$2%1jLcTF${rF3emkLMBVhV2YMVLV-Z+2VVilugBp9TMRLqBOadySaBw2g(1J?rIKmCr3g>n z{{BN4il+1UVxdrcx0DWumQl!wPG@%y@E4bbs~f_I6eev;H1bt|y2piKw`0;73qJ)> zY3#;!AYV@Zh+uGB2x$1clMP00)V^Scq5-Y8!jkFj?>H}egs6LhgsknAHPP5NVPp#P zO+T-whSl(jgSpQyuNS1{^QxPfkty_bvWUYK|J?v-&rjq%|b4B{I> zX`QgJhTqg7#6AQ9ZX&Zb8{3)T=#Bg;I<9cDs*w?#u--c;>K)=`77KDK1sDQ=P@bU) zQ@|VeGtSM)9rXVHTi;Ie_qtP|9Q9D$soJzOb55=LbZr_(eY!8Lc8WiDdRYnt+Vl8| zjg`mEzNVSPn~D$>(59=8&nbtkS8P_x0ON#&2j1JK&3m8z2JvU}Ou_6EZ>(11n-Im8 zyrWVlur2s`Nj>&)S-hm=AF)ZUP2{9hyWXAsHz-|E$nP;{j7yMmll8R9!C!30?zf(} zqo1Ja#?(aJGwQH@#WQQ=^Vs4t$}IvBprNC!?Q36uZTZ&?n+#PmEs63r%a?r(ODKd{?T@Z5)Y8AG z(sQdLYPJ?T___REWoXoPui=cTfqFLX#Af0isGj6DQE|~F$`S|TJI|iD|Llc8j#qXC zLY0(B>+akyVs%{QCO6JW7{ANus_eL^{D;%fb*Rj%%J&?hVUv^lO0vpX8CFZp-NqouQt3Kng0xwwO%WQ7@@ z-AVs~*1{Z@&ebeK^?b#;&=9aB)v_~g=4dcQe08T&&Tf`Za@)Rh%1L)y?bfmb>>hp~ zc^%fJdY^>EnL<_f|0D-?(!4ub4W}Kvltxmr4EAp`6*aarXg6V=

    l43o znrK}nG+gtc>gLx>3i3^0x2Jw8raK+QC7@P3yP)0$WkXdfo&(SJ7avZx7?9gye*=Fh z7^#U3mveCVTs5L%k>I3&;}DR@Gbl&OjgX3u6tH~ViyWGN=xhHJmXqb75p?YjBWI!7 zXQOk-o;;ew1%hU;dPQNyb1>nPku#Dsp8165-LI*cm;3`hb@pts4Q9lGd3wP*%H&|w z#Y>P2Qdtzn;Zr^Nrr-KTgP$9mN;J=My)3^EvJclURe zzxaz!|C)L*;B4u@+V+tfo@4yjLty;pzP;DbiSEZ!{C2@hNG7H+L8>yc0aV=!#xqsf_rp|b*a?=O zdkVxzBZ`Xxvy1NF!Of&k>bbv|?No7}*&6tlNnM-BoI~GLkBVxAjG^a7Bjs-?yuPT{ zaCZ9d049+>}fFM zCuM`!K6?G2=tfO`8%FKLCo0w-FIs3?#=UL&dYAFn92b2cl7NrqHomX5^lw6=lPxZ;uW0c%Ty}83g+jQYV9D~#HHw~lDUs=oH8a=Hj`uh= z!BzHhEOD6gYOc$2dw7sCJ#_5-L+xxIh_vkW9Hl+35F2w2p`x1c-S~PyU#40vro1qf z*QDd|-L1B<&Pe-a=&Hu+2vT?+eYlk`b3I7pU$^P^vQ=OUo=@of5wksfpx*xpfoHPg z!}gpIjQ$ldh4xh7F>6ZzF;idtxrrv>4EFQ(l?hCGu#Ysm{Jp zXJe*zQIKhfkM@M2hi6x1BfELj=@yOO&>qu%Go-mBjM(Vo_eJ%p|Htkl^Wku3@3Zi>ZKo#XAY5CTVcnVy;=;QYF>U;ju%hgvOoXWk7$Wk8E$eH zKVY6^yFDE_AM>65v32|SDW&Lg9*xEG9bJW#WJW69eso4uvF_WS$dy0c_5LCYUSYC@ zDDu<@1|K+ld`9`>$0d)uPr%!slyse{)ip#KSRIf?hg$kD@Xdp+*gDxXU-D1?FEo)L Ao&W#< diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg b/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg deleted file mode 100644 index be864c5ac..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/browserconfig.xml b/luci-theme-argon/htdocs/luci-static/argon/icon/browserconfig.xml deleted file mode 100644 index c55414822..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/icon/browserconfig.xml +++ /dev/null @@ -1,2 +0,0 @@ - -#ffffff \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png deleted file mode 100644 index 308843a09261dc8c5d95f01a3b4e6592e1a83ff0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1019 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 aWS&p(fIu!(CjkFLSj>$d8r2y%$NwKzaNBSI diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg b/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg deleted file mode 100644 index 6ddd3b3ed..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg b/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg deleted file mode 100644 index 654e2fe24..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/bg1.jpg b/luci-theme-argon/htdocs/luci-static/argon/img/bg1.jpg deleted file mode 100644 index 26a52a5351f3c68d326dcacbf98fe3cf9ac485a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159265 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 z 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

    Y2#d_pOEdAHz8x0cU)30N4^@W{p|L> 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

    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-material: - * Copyright 2015 Lutty Yang - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * Font generate by Icomoon - * - * Licensed to the public under the Apache License 2.0 - */ - -document.addEventListener('luci-loaded', function(ev) { -(function ($) { - - /** - * trim text, Remove spaces, wrap - * @param text - * @returns {string} - */ - function trimText(text) { - return text.replace(/[ \t\n\r]+/g, " "); - } - - var lastNode = undefined; - var mainNodeName = undefined; - - var nodeUrl = ""; - (function(node){ - var luciLocation; - if (node[0] == "admin"){ - luciLocation = [node[1], node[2]]; - }else{ - luciLocation = node; - } - - for(var i in luciLocation){ - nodeUrl += luciLocation[i]; - if (i != luciLocation.length - 1){ - nodeUrl += "/"; - } - } - })(luciLocation); - - /** - * get the current node by Burl (primary) - * @returns {boolean} success? - */ - function getCurrentNodeByUrl() { - var ret = false; - if (!$('body').hasClass('logged-in')) { - luciLocation = ["Main", "Login"]; - return true; - } - - $(".main > .main-left > .nav > .slide > .menu").each(function () { - var ulNode = $(this); - ulNode.next().find("a").each(function () { - var that = $(this); - var href = that.attr("href"); - - if (href.indexOf(nodeUrl) != -1) { - ulNode.click(); - ulNode.next(".slide-menu").stop(true, true); - lastNode = that.parent(); - lastNode.addClass("active"); - ret = true; - return true; - } - }); - }); - return ret; - } - - /** - * menu click - */ - $(".main > .main-left > .nav > .slide > .menu").click(function () { - var ul = $(this).next(".slide-menu"); - var menu = $(this); - $(".main > .main-left > .nav > .slide > .menu").each(function () { - var ulNode = $(this); - ulNode.removeClass("active"); - ulNode.next(".slide-menu").stop(true).slideUp("fast") - }); - if (!ul.is(":visible")) { - menu.addClass("active"); - ul.addClass("active"); - ul.stop(true).slideDown("fast"); - } else { - ul.stop(true).slideUp("fast", function () { - menu.removeClass("active"); - ul.removeClass("active"); - }); - } - return false; - }); - - /** - * hook menu click and add the hash - */ - $(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () { - if (lastNode != undefined) lastNode.removeClass("active"); - $(this).parent().addClass("active"); - return true; - }); - - /** - * fix menu click - */ - $(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () { - if (lastNode != undefined) lastNode.removeClass("active"); - $(this).addClass("active"); - window.location = $($(this).find("a")[0]).attr("href"); - return false; - }); - - /** - * get current node and open it - */ - if (getCurrentNodeByUrl()) { - mainNodeName = "node-" + luciLocation[0] + "-" + luciLocation[1]; - mainNodeName = mainNodeName.replace(/[ \t\n\r\/]+/g, "_").toLowerCase(); - $("body").addClass(mainNodeName); - } - - /** - * Sidebar expand - */ - var showSide = false; - $(".showSide").click(function () { - if (showSide) { - $(".darkMask").stop(true).fadeOut("fast"); - $(".main-left").width(0); - $(".main-right").css("overflow-y", "visible"); - showSide = false; - } else { - $(".darkMask").stop(true).fadeIn("fast"); - $(".main-left").width("13rem") - $(".main-right").css("overflow-y", "hidden"); - showSide = true; - } - }); - - $(".darkMask").click(function () { - if (showSide) { - showSide = false; - $(".darkMask").stop(true).fadeOut("fast"); - $(".main-left").width(0); - $(".main-right").css("overflow-y", "visible"); - } - }); - - $(window).resize(function () { - if ($(window).width() > 921) { - $(".main-left").css("width", ""); - $(".darkMask").stop(true); - $(".darkMask").css("display", "none"); - showSide = false; - } - }); - - /** - * fix legend position - */ - $("legend").each(function () { - var that = $(this); - that.after("" + that.text() + ""); - }); - - $(".cbi-section-table-titles, .cbi-section-table-descr, .cbi-section-descr").each(function () { - var that = $(this); - if (that.text().trim() == ""){ - that.css("display", "none"); - } - }); - - $(".main-right").focus(); - $(".main-right").blur(); - $("input").attr("size", "0"); - $(".cbi-button-up").val("__"); - $(".cbi-button-down").val("__"); - $(".slide > a").removeAttr("href"); - - if (mainNodeName != undefined) { - console.log(mainNodeName); - switch (mainNodeName) { - case "node-status-system_log": - case "node-status-kernel_log": - $("#syslog").focus(function () { - $("#syslog").blur(); - $(".main-right").focus(); - $(".main-right").blur(); - }); - break; - case "node-status-firewall": - var button = $(".node-status-firewall > .main fieldset li > a"); - button.addClass("cbi-button cbi-button-reset a-to-btn"); - break; - case "node-system-reboot": - var button = $(".node-system-reboot > .main > .main-right p > a"); - button.addClass("cbi-button cbi-input-reset a-to-btn"); - break; - } - } - -})(jQuery); -}); diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less b/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less deleted file mode 100644 index 54969b3b7..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less +++ /dev/null @@ -1,3982 +0,0 @@ -// out: ../css/cascade.css, compress: false , sourceMap: false -/** - * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template - * - * luci-theme-argon - * Copyright 2020 Jerrykuku - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-material: - * Copyright 2015 Lutty Yang - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * Font generate by Icomoon - * - * Licensed to the public under the Apache License 2.0 - */ - -/* - * Include base and custom css - */ - -@import url("fonts.css?v=3"); -@import url("pure-min.css?v=1"); - -:root { - --primary: #5e72e4; - --dark-primary: #483d8b; - --main-color: #09c; - --header-bg: #09c; - --header-color: #fff; - --bar-bg: #5e72e4; - --menu-bg-color: #fff; - --menu-color: #5f6368; - --menu-color-hover: #202124; - --main-menu-color: #202124; - --submenu-bg-hover: #d4d4d4; - --submenu-bg-hover-active: #09c; - --blue: #5e72e4; - --indigo: #5603ad; - --purple: #8965e0; - --pink: #f3a4b5; - --red: #f5365c; - --orange: #fb6340; - --yellow: #ffd600; - --green: #2dce89; - --teal: #11cdef; - --cyan: #2bffc6; - --white: #fff; - --gray: #8898aa; - --gray-dark: #32325d; - --light: #ced4da; - --lighter: #e9ecef; - --secondary: #f7fafc; - --success: #2dce89; - --info: #11cdef; - --warning: #fb6340; - --danger: #f5365c; - --light: #adb5bd; - --dark: #212529; - --default: #172b4d; - --white: #fff; - --neutral: #fff; - --darker: black; - --background-color: #f4f5f7; - --login-form-bg-color: rgba(244, 245, 247, 0.8); - --breakpoint-xs: 0; - --breakpoint-sm: 576px; - --breakpoint-md: 768px; - --breakpoint-lg: 992px; - --breakpoint-xl: 1200px; - --blur-radius: 10px; - --blur-opacity: 0.5; - --blur-radius-dark: 10px; - --blur-opacity-dark: 0.5; - --font-family-sans-serif: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; - --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; - --font-family-normal: Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif; -} - -html, -body { - margin: 0px; - padding: 0px; - height: 100%; - font-size: 16px; - font-family: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; - font-family: var(--font-family-sans-serif); -} - -html { - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -body { - font-size: 0.875rem; - background-color: #f4f5f7; - background-color: var(--background-color); - color: #32325d; - color: var(--gray-dark); -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -::selection { - background-color: #5e72e4; - background-color: var(--primary); - color: #ffffff; - color: var(--white); -} - -a:link, -a:visited, -a:active { - color: #5e72e4; - color: var(--primary); - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -li { - list-style-type: none; -} - - - -.table { - position: relative; - display: table; -} - -.tr { - display: table-row; -} - -.thead { - display: table-header-group; -} - -.tbody { - display: table-row-group; -} - -.tfoot { - display: table-footer-group; -} - -.td, -.th { - line-height: normal; - display: table-cell; - padding: .5em; - text-align: center; - vertical-align: middle; -} - -.th { - font-weight: bold; - white-space: nowrap; -} - -.tr.placeholder { - height: 4em; -} - -.tr.placeholder>.td { - line-height: 3; - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 0.4rem 0 !important; - text-align: center !important; - background: inherit; -} - -.td[width="33%"] { - padding: 1.1em 1.5rem; -} - -.table[width="33%"], -.th[width="33%"], -.td[width="33%"] { - width: 33%; -} - -.table[width="100%"], -.th[width="100%"], -.td[width="100%"] { - width: 100%; -} - -.col-1 { - flex: 1 1 30px !important; -} - -.col-2 { - flex: 2 2 60px !important; -} - -.col-3 { - flex: 3 3 90px !important; -} - -.col-4 { - flex: 4 4 120px !important; -} - -.col-5 { - flex: 5 5 150px !important; -} - -.col-6 { - flex: 6 6 180px !important; -} - -.col-7 { - flex: 7 7 210px !important; -} - -.col-8 { - flex: 8 8 240px !important; -} - -.col-9 { - flex: 9 9 270px !important; -} - -.col-10 { - flex: 10 10 300px !important; -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; - -} - -.h1, -.h2, -.h3, -.h4, -.h5, -.h6, -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: inherit; - font-weight: normal; - line-height: 1.1 !important; - color: inherit; -} - - - -select { - padding: .36rem .8rem; - color: #555; - border: thin solid #ccc; - background-color: #fff; - background-image: none; -} - -.btn, -button, -select, -input, -.cbi-dropdown { - line-height: 1.5rem; - padding: .5rem .75rem; - margin: 0.25rem 0.1rem; - color: #8898aa; - border: 1px solid #dee2e6; - - border-radius: .25rem; - outline: 0; - background-image: none; - box-shadow: none; - transition: box-shadow .15s ease; -} - -select, -.cbi-dropdown { - width: inherit; - cursor: default; -} - -select:not([multiple="multiple"]):focus, -input:not(.cbi-button):focus, -.cbi-dropdown:focus { - border-color: #5e72e4; - border-color: var(--primary); - box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, .1); -} - -.cbi-dropdown, -select[multiple="multiple"] { - height: auto; -} - -pre { - overflow: auto; -} - -code { - font-size: 1rem; - font-size-adjust: .35; - padding: 1px 3px; - color: #101010; - border-radius: 2px; - background: #ddd; -} - -abbr { - cursor: help; - text-decoration: underline; - color: #5e72e4; - color: var(--primary); -} - -hr { - margin: 1rem 0; - opacity: .1; - border-color: #eee; -} - - - - -/*********************** -* -* Login Page -* -***************************/ - -.login-page { - height: 100%; - - .video { - position: absolute; - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - background-color: #000; - background-color: var(--darker); - overflow: hidden; - video { - width: 100%; - height: auto; - } - } - - .volume-control{ - position: fixed; - right: 1rem; - top: 1rem; - width: 1.5rem; - height: 1.5rem; - z-index: 5000; - cursor: pointer; - background-size: contain; - background-image: url(../img/volume_high.svg); - &.mute{ - background-image: url(../img/volume_off.svg); - } - } - - .main-bg{ - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - background-image: url(../img/blank.png); - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all 0.5s; - } - - .login-container { - height: 100%; - margin-left: 4.5rem; - position: absolute; - top: 0px; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 100%; - z-index: 2; - width: 420px; - box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 35px -5px; - margin-left: 5%; - background: transparent; - - .login-form { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: absolute; - top: 0px; - width: 100%; - min-height: 100%; - max-width: 420px; - background-color: #fff; - background-color: var(--white); - - .brand { - display: flex; - -webkit-box-align: center; - align-items: center; - margin: 50px auto 100px 50px; - color: #525461; - color: var(--default); - - .icon { - width: 50px; - height: auto; - margin-right: 25px; - } - - .brand-text { - font-size: 1.25rem; - font-weight: 700; - font-family: "TypoGraphica"; - - } - - &:hover { - text-decoration: none; - } - } - - .form-login { - width: 100%; - padding: 20px 50px; - box-sizing: border-box; - - .errorbox { - text-align: center; - color: #fb6340; - color: var(--warning); - padding-bottom: 2rem; - } - - .input-group { - margin-bottom: 1.25rem; - position: relative; - - &::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - color: #525461; - color: var(--default); - font-size: 1.5rem; - position: absolute; - z-index: 100; - left: 10px; - top: 10px; - } - - .border { - position: absolute; - width: 100%; - height: 1px; - bottom: 0; - border-bottom: 1px #5e72e4 solid; - border-bottom: 1px var(--primary) solid; - transform: scaleX(0); - transition: transform 0.3s; - } - - input { - font-size: 1rem; - line-height: 1.5em; - display: block; - width: 100%; - padding: .5rem .75rem 0.5rem 3rem; - margin: 0.825rem 0; - box-sizing: border-box; - transition: all .3s cubic-bezier(.68, -.55, .265, 1.55); - color: #525461; - color:var(--default); - border: 0; - border-radius: 0; - border-bottom: 1px solid #fff; - border-bottom: 1px solid var(--white); - background-color: transparent; - background-clip: padding-box; - box-shadow: 0 3px 2px rgba(233, 236, 239, .05); - outline: none; - - &:focus+.border { - transform: scaleX(1); - } - } - - .cbi-input-password { - margin-bottom: 2rem; - position: relative; - } - } - - .user-icon::before { - content: "\e971"; - } - - .pass-icon::before { - content: "\e910"; - - } - } - - .cbi-button-apply { - width: 100% !important; - box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 50px 0px; - font-weight: 600; - font-size: 15px; - color: #fff; - color: var(--white); - text-align: center; - width: 100%; - cursor: pointer; - min-height: 50px; - background-color: #5e72e4 !important; - background-color: var(--primary) !important; - border-radius: 6px; - outline: none; - border-width: initial; - border-style: none; - border-color: initial; - border-image: initial; - padding: 10px 0px; - margin: 30px 0px 100px; - transition: all 0.3s !important; - letter-spacing: 0.8rem; - - &:hover, - :focus { - opacity: 0.9; - } - } - } - - footer { - box-sizing: border-box; - width: 100%; - text-align: center; - line-height: 1.6rem; - display: flex; - justify-content: space-evenly; - margin-top: auto; - padding: 0px 0px 30px; - z-index: 10; - color: #525461; - color: var(--default); - position: absolute; - bottom: 0; - .ftc{ - position: absolute; - bottom: 30px; - width: 100%; - } - - .luci-link { - display: block; - } - } - } -} - -@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) { - .login-page .login-container .login-form { - -webkit-backdrop-filter: blur(var(--blur-radius)); - backdrop-filter: blur(var(--blur-radius)); - background-color: rgba(244, 245, 247, var(--blur-opacity)); - - } -} - - -header, -.main { - width: 100%; -} - - -footer { - font-size: .8rem; - overflow: hidden; - padding: 1rem; - text-align: right; - white-space: nowrap; - color: #aaa; -} - -footer>a { - text-decoration: none; - color: #aaa; -} - -small { - font-size: 90%; - line-height: 1.42857143; - white-space: normal; -} - -.main { - position: relative; - top: 0; - bottom: 0; - overflow-y: auto; - height: 100%; -} - -.main-left { - position: fixed; - top: 0; - float: left; - overflow-x: auto; - width: 15%; - width: calc(0% + 15rem); - height: 100%; - background-color: #fff; - background-color: var(--menu-bg-color); - box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 15px -5px; - overflow-x: auto; - position: fixed; - z-index: 100; - - - .sidenav-header { - padding: 1.5rem; - text-align: center; - - .brand { - font-size: 1.8rem; - color: #5e72e4; - color: var(--primary); - font-family: "TypoGraphica"; - text-decoration: none; - text-align: center; - cursor: default; - vertical-align: text-bottom; - white-space: nowrap; - } - } - - &::-webkit-scrollbar { - width: 5px; - height: 1px; - } - - &::-webkit-scrollbar-thumb { - background-color: #f6f9fc - } - - &::-webkit-scrollbar-track { - background-color: #fff; - } -} - -.main-right { - float: right; - width: 85%; - width: calc(100% - 15rem); - height: 100%; - transition: all 0.2s; -} - -.main-right>#maincontent { - position: relative; - z-index: 50; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.nowrap:not(.td) { - white-space: nowrap; -} - -[disabled="disabled"] { - pointer-events: none; -} - -header { - color: #fff; - color: var(--header-color); - padding: 0; - position: relative; - - &.bg-primary { - background-color: #5e72e4 !important; - background-color: var(--primary) !important; - } - - &::after { - content: ""; - position: absolute; - height: 2rem; - width: 100%; - background-color: #5e72e4 !important; - background-color: var(--primary) !important; - } - - .fill { - padding: 0.8rem 0; - border-bottom: 0px solid rgba(255, 255, 255, .08) !important; - - .container { - height: 2rem; - padding: 0 1.25rem; - - .showSide { - display: none; - color: #fff; - font-size: 1.4rem; - - &:hover { - text-decoration: none; - } - } - - .brand { - font-size: 1.5rem; - color: #fff; - font-family: "TypoGraphica"; - text-decoration: none; - padding-left: 1rem; - cursor: default; - vertical-align: text-bottom; - display: none; - } - - .pull-right { - float: right; - margin-top: 0rem; - display: flex; - } - } - - .status { - position: absolute; - top: 25%; - right: 1.25rem; - float: right; - - span[data-indicator] { - display: inline-block; - font-size: 0.8rem; - font-weight: bold; - padding: 0.3rem 0.8rem; - margin: 0 0.5rem; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - text-shadow: none; - border-radius: 3px; - cursor: pointer; - transition: all 0.3s; - } - - span[data-style="active"] { - color: #32325d !important; - background-color: #fff; - - } - - span[data-style="inactive"] { - color: #ffffff !important; - background-color: #32325d; - - } - } - } -} - - - -#xhr_poll_status { - display: flex; - margin-left: 0.5rem; - - * { - color: #fff; - } -} - -div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - border: 0 !important; -} - -.danger { - background-color: #ff7d60 !important; -} - -.warning { - background-color: #f0e68c !important; -} - -.success { - background-color: #5cb85c !important; -} - -.notice { - background-color: #11cdef !important; - color: #fff; -} - -.error { - color: #f00; -} - -.alert, -.alert-message { - font-weight: bold; - margin-bottom: 1em; - padding: 1rem; - border: 0; - border-radius: 0.375rem !important; - background-color: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); - text-shadow: 1px 1px rgba(0, 0, 0, .1); - - &.error { - background-color: #ffd600; - } - - h4 { - padding: 0rem 1.5rem 0.75rem 0rem; - } - - .btn { - height: auto; - } -} - -.alert-message>h4 { - font-size: 110%; - font-weight: bold; -} - -.alert-message>* { - margin: .5rem 0; -} - -.alert-message .btn { - padding: .3rem .6rem; -} - -.container .alert, -.container .alert-message { - margin-top: 1rem; -} - - -/* - * Main Menu - */ - -.main { - .main-left { - transition: all 0.2s; - - .nav { - margin-top: 0.5rem; - - >li>a:first-child { - display: block; - margin: 0.1rem .5rem 0.1rem .5rem; - padding: .675rem 0 .675rem 2.5rem; - border-radius: .375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; - - &.active { - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - - &::after { - transform: rotate(90deg); - color: #fff !important; - } - } - - &:hover { - cursor: pointer; - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - } - - &::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e915"; - color: #5e72e4; - color: var(--primary); - } - } - - li { - padding: 0.5rem 1rem; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - padding: 0; - - a { - display: block; - color: #5f6368; - color: var(--menu-color); - } - - &.slide { - padding: 0; - - ul { - display: none; - } - - - - &:hover { - background: none; - } - - .slide-menu { - margin: 0 0.5rem 0 2.5rem; - padding: 0rem 0.5rem; - - li { - position: relative; - border-radius: 0.375rem; - margin: 0; - padding: 0.5rem 0rem; - background: none; - list-style: none; - - a { - white-space: nowrap; - text-decoration: none; - } - - &::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 0; - height: 2px; - background-color: #5e72e4; - background-color: var(--primary); - transition: all 0.2s; - } - - &:hover { - background: none; - - &::after { - width: 100%; - } - } - - } - - .active { - background: none; - - color: var(--menu-color); - - a { - color: var(--menu-color); - } - - &::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 100%; - height: 2px; - background-color: #5e72e4; - background-color: var(--primary); - transition: all 0.2s; - } - - &:hover { - - background: none; - - &::after { - width: 100%; - } - } - } - } - - } - - - - .menu { - display: block; - margin: 0.1rem .5rem 0.1rem .5rem; - padding: .675rem 0 .675rem 2.5rem; - border-radius: .375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; - - &.active { - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - - &::after { - transform: rotate(90deg); - color: #fff !important; - } - } - - &:hover { - cursor: pointer; - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - } - - &::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e915"; - color: #5e72e4; - color: var(--primary); - } - - &::after { - position: absolute; - right: 0.5rem; - top: 0.8rem; - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: '\e90f'; - transition: all .15s ease; - color: #ced4da; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - transition: all 0.3s; - } - } - - - .menu[data-title=Status]:before { - content: "\e906"; - color: #5e72e4; - color: var(--primary); - } - - .menu[data-title=System]:before { - content: "\e90a"; - color: #fb6340; - } - - .menu[data-title=Services]:before { - content: "\e909"; - color: #11cdef; - } - - .menu[data-title=NAS]:before { - content: "\e90c"; - color: #f3a4b5; - } - - .menu[data-title=VPN]:before { - content: "\e90b"; - color: #8965e0; - } - - .menu[data-title=Network]:before { - content: "\e908"; - color: #8965e0; - } - - .menu[data-title=Bandwidth_Monitor]:before { - content: "\e90d"; - color: #2dce89; - } - - .menu[data-title=Docker]:before { - content: "\e911"; - color: #6699ff; - } - - .menu[data-title=Statistics]:before { - content: "\e913"; - color: #8965e0; - } - - .menu[data-title=Control]:before { - content: "\e912"; - color: #5e72e4; - color: var(--primary); - } - - .menu[data-title=Asterisk]:before { - content: "\e914"; - color: #fb6340; - } - - a[data-title=Logout]:before { - content: "\e907"; - color: #adb5bd; - } - } - } - } -} - -.lg { - margin: 0; - padding: 0 !important; -} - -.logout { - display: block; - margin: 0.8rem .5rem 0.1rem 0.5rem; - padding: .675rem 0 .675rem 2.5rem; - border-radius: .375rem; - text-decoration: none; - font-size: 1rem; - transition: all 0.2s; - position: relative; -} - -.logout:before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e907"; - color: #32325d !important; -} - - -body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { - transition: transform .1s ease-in-out; -} - -body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { - transition: transform .2s ease-in-out; -} - -.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before { - display: none; -} - - - - -#maincontent>.container { - margin: 0 1.25rem 1rem 1.25rem; -} - -ul { - line-height: normal; -} - -li { - list-style-type: none; -} - -h1 { - font-size: 2rem; - padding-bottom: 10px; - border-bottom: thin solid #eee; -} - -h2 { - margin: 0 0 1rem 0; - font-size: 1.25rem; - letter-spacing: 0.1rem; - padding: 1rem 1.5rem; - color: #32325d; - border-radius: .375rem; - background: #fff; - box-shadow: 0 4px 8px rgba(0, 0, 0, .03); - -} - -h3 { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - margin: 0; - margin-bottom: 0; - padding: 0.8755rem 1.5rem; - color: #32325d; - color: var(--gray-dark); - border-radius: .375rem; - background: #fff; -} - -h4 { - margin: 0; - padding: 0.75rem 1.5rem; - font-size: 0.7rem; - font-weight: 600; - color: #525f7f; - background-color: #e9ecef; - background-color: var(--lighter); - - em { - padding: 0 0.5rem; - } - -} - -h5 { - font-size: 1rem; - margin: 2rem 0 0 0; - padding-bottom: 10px; -} - -.cbi-section, -.cbi-section-error, -#iptables, -.Firewall form, -#cbi-network>.cbi-section-node, -#cbi-wireless>.cbi-section-node, -#cbi-wireless>#wifi_assoclist_table, -[data-tab-title], -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent>.container { - font-family: inherit; - font-weight: normal; - font-style: normal; - line-height: normal; - min-width: inherit; - margin: 1.5rem 0; - padding: 0rem; - border: 0; - - border-radius: 0.375rem; - background-color: #fff; - box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .15) -} - -.cbi-modal .cbi-section, -.cbi-section .cbi-section { - padding: 0; - box-shadow: none; -} - -.cbi-modal .cbi-tabmenu { - margin-left: 0; -} - -.cbi-map-descr, -.cbi-section-descr { - font-size: small; - line-height: 1.42857143; - padding: .5rem 1.5rem; -} - -.cbi-map-descr+fieldset { - margin-top: 1rem; -} - -.cbi-map-descr>abbr { - cursor: help; - text-decoration: underline; -} - -.cbi-section>legend { - display: none !important; -} - -fieldset>fieldset, -.cbi-section>.cbi-section { - margin: 0; - padding: 0; - border: 0; - box-shadow: none; -} - -.cbi-section>h3:first-child, -.panel-title { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - margin: 0; - margin-bottom: 0; - padding: 0.8755rem 1.5rem; - color: #32325d; - color: var(--gray-dark); - -} - -.cbi-section>h3:first-child, -.cbi-section>h4:first-child, -.cbi-section>p:first-child, -[data-tab-title]>h3:first-child, -[data-tab-title]>h4:first-child, -[data-tab-title]>p:first-child { - padding: 1rem; -} - -.cbi-section p { - padding: 1rem; -} - -table { - border-spacing: 0; - border-collapse: collapse; -} - -table, -.table { - overflow-y: hidden; - width: 100%; - font-size: 90%; -} - -.table .table-titles th { - background-color: #e9ecef; - background-color: var(--lighter); -} - -table>tbody>tr>td, -table>tbody>tr>th, -table>tfoot>tr>td, -table>tfoot>tr>th, -table>thead>tr>td, -table>thead>tr>th, -.table>.tbody>.tr>.td, -.table>.tbody>.tr>.th, -.table>.tfoot>.tr>.td, -.table>.tfoot>.tr>.th, -.table>.thead>.tr>.td, -.table>.thead>.tr>.th, -.table>.tr>.td.cbi-value-field, -.table>.tr>.th.cbi-section-table-cell { - padding: .5rem; -} - -.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { - padding: .6rem; -} - -.cbi-section-table-cell { - line-height: 1.1; - align-self: flex-end; - flex: 1 1 auto; -} - -tr>td, -tr>th, -.tr>.td, -.tr>.th, -.cbi-section-table-row::before, -#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { - border-top: thin solid #ddd; - padding: 1.1em 1.5rem; -} - -#cbi-wireless .td, -#cbi-network .tr:first-child>.td, -.table[width="100%"]>.tr:first-child>.td, -[data-page="admin-network-diagnostics"] .tr>.td, -.tr.table-titles>.th, -.tr.cbi-section-table-titles>.th { - border-top: 0 !important; - background-color: #f6f9fc; - padding: 1.1em 1.5rem; - line-height: 1.3rem; -} - -.table[width="100%"]>.tr:first-child>.td { - margin: auto 0; -} - -.cbi-section-table-row { - margin-bottom: 1rem; - text-align: center !important; - background: #f4f4f4; -} - -.cbi-section-table-row:last-child { - margin-bottom: 0; -} - -.cbi-section-table-row>.cbi-value-field .cbi-dropdown, -.cbi-section-table-row>.cbi-value-field .cbi-input-select, -.cbi-section-table-row>.cbi-value-field .cbi-input-text, -.cbi-section-table-row>.cbi-value-field .cbi-input-password { - width: 100%; -} - -.cbi-section-table-row>.cbi-value-field [data-dynlist]>input, -.cbi-section-table-row>.cbi-value-field input.cbi-input-password { - width: calc(100% - 1.5rem); -} - -.cbi-section-table-row .td { - text-align: center !important; -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tr:nth-of-type(2n) { - background-color: #f9f9f9; -} - -/* fix multiple table */ -table table, -.table .table, -.cbi-value-field table, -.cbi-value-field .table, -td>table>tbody>tr>td, -.td>.table>.tbody>.tr>.td, -.cbi-value-field>table>tbody>tr>td, -.cbi-value-field>.table>.tbody>.tr>.td { - border: 0; -} - -/* button style */ -.btn, -.cbi-button, -.item::after { - font-size: .8rem; - display: inline-block; - width: auto !important; - padding: 0.45rem .8rem; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all .2s ease-in-out; - text-align: center; - vertical-align: middle; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: rgba(0, 0, 0, .87); - border: 0; - border-radius: .2rem; - background-color: #f0f0f0; - background-image: none; - -webkit-appearance: none; - -ms-touch-action: manipulation; - touch-action: manipulation; -} - -.cbi-button-up, -.cbi-button-down { - font-size: 1.2rem; - display: inline-block; - min-width: 0; - padding: .2rem .3rem; - color: transparent !important; - background: url(../icon/arrow.svg) no-repeat center; - background-size: 12px 20px; -} - -.cbi-button-up { - transform: scaleY(-1); -} - -.cbi-button:not(select) { - -webkit-appearance: none !important; -} - - -.btn:hover, -.btn:focus, -.btn:active, -.cbi-button:hover, -.cbi-button:focus, -.cbi-button:active, -.item:hover::after, -.item:focus::after, -.item:active::after, -.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover, -.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus, -.cbi-page-actions .cbi-button-apply+.cbi-button-save:active { - text-decoration: none; - outline: 0; -} - -.btn:hover, -.btn:focus, -.cbi-button:hover, -.cbi-button:focus, -.item:hover::after, -.item:focus::after { - box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 2px 2px rgba(0, 0, 0, .2); -} - -.btn:active, -.cbi-button:active, -.item:active::after { - box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23); -} - -.cbi-button-up:hover, -.cbi-button-up:focus { - box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 -2px 2px rgba(0, 0, 0, .2); -} - -.cbi-button-up:active { - box-shadow: 0 -10px 20px rgba(0, 0, 0, .19), 0 -6px 6px rgba(0, 0, 0, .23); -} - -.btn:disabled, -.cbi-button:disabled { - cursor: not-allowed; - pointer-events: none; - opacity: .5; - box-shadow: none; -} - -/* gray */ -.alert-message [class="btn"], -.modal div[class="btn"], -.cbi-button-find, -.cbi-button-link, -.cbi-button-up, -.cbi-button-down, -.cbi-button-neutral, -.cbi-button[name="zero"], -.cbi-button[name="restart"], -.cbi-button[onclick="hide_empty(this)"] { - font-weight: bold; - color: #fff; - border: thin solid #8898aa; - background-color: #8898aa; -} - -/* dark blue */ -.btn.primary, -.cbi-page-actions .cbi-button-save, -.cbi-page-actions .cbi-button-apply+.cbi-button-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-positive, -.cbi-button-link, -.cbi-button[value="Enable"], -.cbi-button[value="Scan"], -.cbi-button[value^="Back"], -.cbi-button-neutral[onclick="handleConfig(event)"] { - font-weight: normal; - color: #fff !important; - border: thin solid #5e72e4; - border: thin solid var(--primary); - background-color: #5e72e4; - background-color: var(--primary); - ; -} - -/* light blue */ -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-action, -.cbi-button[value="Submit"], -.cbi-button[value="Upload"], -.cbi-button[value$="Apply"], -.cbi-button[onclick="addKey(event)"] { - font-weight: normal; - color: #fff !important; - border: thin solid #5e72e4; - border: thin solid var(--primary); - - background-color: #5e72e4; - background-color: var(--primary); -} - -/* red */ -.btn.danger, -.cbi-section-remove>.cbi-button, -.cbi-button-remove, -.cbi-button-reset, -.cbi-button-negative, -.cbi-button[value="Stop"], -.cbi-button[value="Kill"], -.cbi-button[onclick="reboot(this)"], -.cbi-button-neutral[value="Restart"] { - font-weight: normal; - color: #fff; - border: thin solid #f5365c; - border: thin solid var(--red); - background-color: #f5365c; - background-color: var(--red); -} - -/* yellow */ -.btn[value="Dismiss"], -.cbi-button[value="Terminate"], -.cbi-button[value="Reset"], -.cbi-button[value="Disabled"], -.cbi-button[onclick^="iface_reconnect"], -.cbi-button[onclick="handleReset(event)"], -.cbi-button-neutral[value="Disable"] { - font-weight: normal; - color: #fff; - border: thin solid #eea236; - background-color: #f0ad4e; -} - -/* green */ -.cbi-button-success, -.cbi-button-download, -.cbi-button[name="backup"], -.cbi-button[value="Download"], -.cbi-button[value="Save mtdblock"] { - font-weight: normal; - color: #fff; - border: thin solid #4cae4c; - background-color: #5cb85c; -} - -.cbi-page-actions .cbi-button-link:first-child { - float: left; -} - -.a-to-btn { - text-decoration: none; -} - -.cbi-value-field .cbi-button-add { - font-weight: bold; - margin: 4px 0 4px 3px; - padding: 1px 6px; - display: flex; - align-items: center; -} - -.tabs { - margin: 0 0 1rem 0; - padding: 0 1rem; - background-color: #FFFFFF; - border-radius: 0.375rem; - box-shadow: 0 4px 8px rgba(0, 0, 0, .03); - white-space: nowrap; - overflow-x: auto; - - &::-webkit-scrollbar { - width: 1px; - height: 5px; - } - - &::-webkit-scrollbar-thumb { - background-color: #f6f9fc - } - - &::-webkit-scrollbar-track { - background-color: #fff; - } - - li[class~="active"], - li:hover { - cursor: pointer; - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - border-radius: 0; - - a { - color: #5e72e4; - color: var(--primary); - } - } - - li { - font-size: 0.875rem; - display: inline-block; - padding: 0.875rem 0rem; - border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); - margin: 0 0.2rem; - - a { - text-decoration: none; - color: #404040; - padding: 0.5rem 0.8rem; - } - - &:hover { - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - } - } -} - - - - -.cbi-tabmenu { - color: white; - padding: 0.5rem 1rem 0 1rem; - white-space: nowrap; - overflow-x: auto; - - &::-webkit-scrollbar { - width: 1px; - height: 5px; - } - - &::-webkit-scrollbar-thumb { - background-color: #f6f9fc - } - - &::-webkit-scrollbar-track { - background-color: #fff; - } - - li { - background: #dce3e9; - display: inline-block; - font-size: 0.875rem; - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; - padding: 0.5rem 0rem; - border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); - margin: 0 0.2rem; - - a { - text-decoration: none; - color: #404040; - padding: 0.5rem 0.8rem; - } - - &:hover { - cursor: pointer; - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - - a { - color: #525f7f; - } - } - } - - li[class~="cbi-tab"] { - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - - a { - color: #5e72e4; - color: var(--primary); - } - } -} - -.cbi-tab-descr { - padding: 0.5rem 1.5rem; -} - - -.cbi-section .cbi-section-remove:nth-of-type(2n), -.container>.cbi-section .cbi-section-node:nth-of-type(2n) { - background-color: #f9f9f9; -} - -[data-tab-title] { - overflow: hidden; - height: 0; - opacity: 0; - margin: 0; - padding: 0rem 0rem !important; - - p { - margin-left: 1rem; - margin-bottom: 1rem; - } -} - - - -[data-tab-active="true"] { - overflow: visible; - height: auto; - opacity: 1; - transition: opacity .25s ease-in; - margin: inherit !important; -} - - -.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3), -.cbi-section[id] .cbi-section-node:nth-of-type(4n+4) { - background-color: #f9f9f9; -} - -.cbi-section-node-tabbed { - margin-top: 0; - padding: 0; - border: 0 solid #d4d4d4; - border-radius: 0.375rem; -} - -.cbi-tabcontainer>.cbi-value:nth-of-type(2n) { - background-color: #f9f9f9; -} - -.cbi-value-field, -.cbi-value-description { - line-height: 1.25; - display: table-cell; - - abbr { - color: #32325d; - color: var(--gray-dark); - } -} - -.cbi-value-description { - font-size: small; - padding: .5rem; - opacity: .5; -} - -.cbi-value-title { - display: table-cell; - float: left; - width: 23rem; - padding-top: .25rem; - padding-right: 2rem; - text-align: right; - word-wrap: break-word; -} - -.cbi-value { - display: inline-block; - width: 100%; - padding: .35rem 1rem .2rem 1rem; - line-height: 2.4rem; -} - -.cbi-value ul { - line-height: 1.25; -} - -.cbi-value-field .cbi-dropdown, -.cbi-value-field .cbi-input-select, -.cbi-value input[type="text"], -.cbi-value input[type="password"] { - min-width: 18rem; -} - -.cbi-value input[type="password"] { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - margin-right: 0; -} - -.cbi-value input[type="password"]+.cbi-button-neutral { - height: 42px; - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin-left: 0; - border: 0; -} - -#cbi-firewall-zone .cbi-input-select, -#cbi-network-switch_vlan .cbi-input-select { - min-width: 11rem; -} - -#cbi-network-switch_vlan .cbi-input-text { - max-width: 3rem; -} - -.cbi-input-invalid { - color: #f5365c; - border-bottom-color: #f5365c; -} - -.cbi-section-error { - font-weight: bold; - line-height: 1.42857143; - margin: 18px; - padding: 6px; - border: thin solid #f5365c; - border-radius: 3px; - background-color: #fce6e6; -} - -.cbi-section-error ul { - margin: 0 0 0 20px; -} - -.cbi-section-error ul li { - font-weight: bold; - color: #f5365c; -} - -.td[data-title]::before { - font-weight: bold; - display: none; - padding: .25rem 0; - content: attr(data-title) ":\20"; - text-align: left; - white-space: nowrap; -} - -.tr.placeholder .td[data-title]::before { - display: none; -} - -.tr[data-title]::before, -.tr.cbi-section-table-titles.named::before { - font-weight: bold; - display: table-cell; - align-self: center; - flex: 1 1 5%; - padding: .25rem; - content: attr(data-title) "\20"; - text-align: center; - vertical-align: middle; - white-space: normal; - word-wrap: break-word; -} - -.cbi-rowstyle-1 { - background-color: #f9f9f9; -} - -.cbi-rowstyle-2 { - background-color: #eee; -} - -.cbi-rowstyle-2 .cbi-button-up, -.cbi-rowstyle-2 .cbi-button-down, -body:not(.Interfaces) .cbi-rowstyle-2:first-child { - background-color: #fff !important; -} - -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - width: auto !important; -} - -.td.cbi-section-actions { - text-align: right !important; - vertical-align: middle; -} - -.td.cbi-section-actions>* { - display: inline-flex; -} - -.td.cbi-section-actions>*>*, -.td.cbi-section-actions>*>form>* { - margin: 0 5px; - display: flex; - align-items: center; -} - -.td.cbi-section-actions>*>form { - display: inline-flex; - margin: 0; -} - -.cbi-checkbox { - margin: 0 0.25rem; -} - -/* lists */ -.cbi-dynlist { - line-height: 1.3; - flex-direction: column; - min-height: 30px; - cursor: text; -} - -.cbi-dynlist>.item { - position: relative; - max-width: 25rem; - pointer-events: none; - color: #8898aa; - outline: 0; -} - -.cbi-dynlist[name="sshkeys"]>.item { - max-width: none; -} - -.cbi-dynlist>.item::after { - position: absolute; - width: 2.2rem !important; - height: calc(100% - 0.5rem - 2px); - right: 0; - bottom: 0; - content: "\00D7"; - pointer-events: auto; - background-color: var(--red); - font-weight: normal; - font-size: 1.2rem; - display: flex; - align-items: center; - justify-content: center; - line-height: 1.5rem; - padding: 0; - margin: 0.25rem 0.1rem 0.25rem 0; - color: #fff; - border: 1px solid #f5365c; - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.cbi-dynlist>.item>span { - white-space: normal; - word-break: break-word; - line-height: 1.5rem; - padding: 0.5rem 0.5rem; - margin: 0.25rem 0.1rem; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - display: block; - transition: box-shadow 0.15s ease; - box-sizing: border-box; - min-width: 15rem; -} - -.cbi-dynlist>.add-item { - display: inline-flex; - align-items: center; - width: 100%; - min-width: 16rem; -} - -.cbi-dynlist>.add-item input { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - margin-right: 0; - border-right: none; -} - -.cbi-dynlist>.add-item .cbi-button-add { - font-weight: normal; - font-size: 1.2rem; - display: flex; - align-items: center; - line-height: 1.5rem; - padding: 0.5rem 0.75rem; - margin: 0.25rem 0.1rem 0.25rem 0; - color: #fff; - border: 1px solid #5e72e4; - border: 1px solid var(--primary); - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.cbi-dynlist>.add-item:not([ondrop])>input { - overflow: hidden; - width: 100%; - min-width: 15rem; - white-space: nowrap; - text-overflow: ellipsis; -} - -.cbi-dynlist>.add-item[ondrop]>input { - min-width: 13rem; -} - -.cbi-dynlist, -.cbi-dropdown { - position: relative; - display: inline-flex; - padding: 0.2rem 0.2rem; -} - -.cbi-dropdown[placeholder*="select"] { - max-width: 25rem; - height: auto; - margin-top: -3px; -} - -.cbi-dropdown>ul { - display: flex; - overflow-x: hidden; - overflow-y: auto; - width: 100%; - margin: 0 !important; - padding: 0; - list-style: none; - outline: 0; -} - - -.cbi-dropdown>ul.preview { - display: none; - -} - -.cbi-button-apply>ul.preview { - display: none; - - li { - color: #fff; - } - -} - -.cbi-button-apply>ul:first-child { - li { - color: #fff; - } - -} - -.cbi-dropdown>.open { - flex-basis: 15px; -} - -.cbi-dropdown>.open, -.cbi-dropdown>.more { - font-size: 1rem; - font-weight: 900; - line-height: 2; - display: flex; - flex-direction: column; - flex-grow: 0; - flex-shrink: 0; - justify-content: center; - padding: 0 .25em; - cursor: default; - text-align: center; - outline: 0; -} - -.cbi-dropdown>.more, -.cbi-dropdown>ul>li[placeholder] { - font-weight: bold; - display: none; - color: #777; - text-shadow: 1px 1px 0 #fff; -} - -.cbi-dropdown>ul>li { - display: none; - overflow: hidden; - align-items: center; - align-self: center; - flex-grow: 1; - flex-shrink: 1; - min-height: 20px; - padding: .25em; - white-space: nowrap; - text-overflow: ellipsis; - -} - -.cbi-dropdown>ul>li .hide-open { - display: initial; -} - -.cbi-dropdown>ul>li .hide-close { - display: none; -} - -.cbi-dropdown>ul>li[display]:not([display="0"]) { - border-left: thin solid #ccc; -} - -.cbi-dropdown[empty]>ul { - max-width: 1px; -} - -.cbi-dropdown>ul>li>form { - display: none; - margin: 0; - padding: 0; - pointer-events: none; -} - -.cbi-dropdown>ul>li img { - margin-right: .25em; - vertical-align: middle; -} - -.cbi-dropdown>ul>li>form>input[type="checkbox"] { - height: auto; - margin: 0; -} - -.cbi-dropdown>ul>li input[type="text"] { - height: 20px; -} - -.cbi-dropdown[open]>ul.dropdown { - position: absolute; - z-index: 1100; - display: block; - width: auto; - min-width: 100%; - max-width: none; - max-height: 200px !important; - border: 0 solid #918e8c; - background: #ffffff; - box-shadow: 0 0 4px #918e8c; - border-bottom-left-radius: 0.35rem; - border-bottom-right-radius: 0.35rem; - color: var(--main-menu-color); - margin-left: -0.2rem !important; - - li { - color: #000; - } -} - - -.cbi-dropdown>ul>li[display], -.cbi-dropdown[open]>ul.preview, -.cbi-dropdown[open]>ul.dropdown>li, -.cbi-dropdown[multiple]>ul>li>label, -.cbi-dropdown[multiple][open]>ul.dropdown>li, -.cbi-dropdown[multiple][more]>.more, -.cbi-dropdown[multiple][empty]>.more { - display: flex; - align-items: center; - flex-grow: 1; - -} - -.cbi-dropdown[empty]>ul>li, -.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], -.cbi-dropdown[multiple][open]>ul.dropdown>li>form { - display: block; -} - -.cbi-dropdown[open]>ul.dropdown>li .hide-open { - display: none; -} - -.cbi-dropdown[open]>ul.dropdown>li .hide-close { - display: initial; -} - -.cbi-dropdown[open]>ul.dropdown>li { - border-bottom: thin solid #ccc; - padding: 0.5rem 0.8rem; -} - -.cbi-dropdown[open]>ul.dropdown>li label { - margin-left: 0.5rem; -} - -.cbi-dropdown[open]>ul.dropdown>li[selected] { - background: #dce1fe; -} - -.cbi-dropdown[open]>ul.dropdown>li.focus { - background: #dce1fe; - outline: none; -} - -.cbi-dropdown[open]>ul.dropdown>li:last-child { - margin-bottom: 0; - border-bottom: 0; -} - -.cbi-dropdown[open]>ul.dropdown>li[unselectable] { - opacity: .7; -} - -.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child { - width: 100%; -} - -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: .6; -} - -.cbi-dropdown .zonebadge { - width: 100%; -} - -.cbi-dropdown[open] .zonebadge { - width: auto; -} - -/* progressbar */ -.cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - margin: 6px 0; - border: thin solid #999; - background: #eee; - border-radius: 0.2rem; - overflow: hidden; -} - -.cbi-progressbar>div { - width: 0; - height: 100%; - transition: width .25s ease-in; - background: #5e72e4; - background: var(--primary); -} - -.cbi-progressbar::after { - font-family: monospace; - font-size: 1em; - font-weight: bold; - font-size-adjust: .38; - line-height: normal; - position: absolute; - top: 2px; - right: 0; - bottom: 2px; - left: 0; - overflow: hidden; - content: attr(title); - text-align: center; - white-space: pre; - text-overflow: ellipsis; -} - -#modal_overlay { - position: fixed; - z-index: 900; - top: 0; - right: 10000px; - bottom: 0; - left: -10000px; - overflow-y: scroll; - transition: opacity .125s ease-in; - opacity: 0; - background: rgba(0, 0, 0, .7); - -webkit-overflow-scrolling: touch; -} - -.modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 90%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - margin: 5em auto; - padding: 1em; - border-radius: 3px !important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -.modal>* { - line-height: normal; - flex-basis: 100%; - margin-bottom: .5em; - max-width: 100%; -} - -.modal>pre, -.modal>textarea { - font-size: 1rem; - font-size-adjust: .35; - overflow: auto; - margin-bottom: .5em; - padding: 8.5px; - cursor: auto; - white-space: pre-wrap; - color: #eee; - outline: 0; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -.modal>h4 { - margin: .5em 0; -} - -.modal ul { - margin-left: 2.2em; -} - -.modal li { - list-style-type: square; - color: #808080; -} - -.modal p { - - word-break: break-word; -} - -.modal .label { - font-size: .6rem; - font-weight: normal; - padding: .1rem .3rem; - padding-bottom: 0; - cursor: default; - border-radius: 0; -} - -.modal .label.warning { - background-color: #f0ad4e !important; -} - -.modal .btn { - padding: 0.45rem 0.8rem; -} - -.modal.cbi-modal { - max-width: 90%; - max-height: none; -} - -body.modal-overlay-active { - overflow: hidden; - height: 100vh; -} - -body.modal-overlay-active #modal_overlay { - right: 0; - left: 0; - opacity: 1; -} - - - -.spinning { - position: relative; - padding-left: 32px !important; -} - -.spinning::before { - position: absolute; - top: 0; - bottom: 0; - left: .2em; - width: 32px; - content: ""; - background: url(/luci-static/resources/icons/loading.gif) no-repeat center; - background-size: 16px; -} - -/* luci */ -.hidden { - display: none; -} - -.left, -.left::before { - text-align: left !important; -} - -.right, -.right::before { - text-align: right !important; -} - -.center, -.center::before { - text-align: center !important; -} - -.top { - align-self: flex-start !important; - vertical-align: top !important; -} - -.bottom { - align-self: flex-end !important; - vertical-align: bottom !important; -} - -.inline { - display: inline; -} - -.cbi-page-actions { - padding-top: 1rem; - text-align: right; -} - -.cbi-page-actions>form[method="post"] { - display: inline-block; -} - -.th[data-type="button"], -.td[data-type="button"], -.th[data-type="fvalue"], -.td[data-type="fvalue"] { - flex: 1 1 2em; - text-align: center; -} - -.ifacebadge { - display: inline-flex; - padding: .5rem .8rem; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); -} - -td>.ifacebadge, -.td>.ifacebadge { - font-size: .8rem; - background-color: #f0f0f0; -} - -.ifacebadge>em, -.ifacebadge>img { - display: inline-block; - align-self: flex-start; - margin: 0 .2rem; -} - -.ifacebadge>img+img { - margin: 0 .2rem 0 0; -} - -.network-status-table { - display: flex; - flex-wrap: wrap; -} - -.network-status-table .ifacebox { - flex-grow: 1; - margin: .5em; -} - -.network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; -} - -.network-status-table .ifacebox-body>span { - flex: 10 10 auto; - height: 100%; -} - -.network-status-table .ifacebox-body>div { - display: flex; - flex-wrap: wrap; -} - -.network-status-table .ifacebox-body .ifacebadge { - align-items: center; - flex: 1 1 auto; - min-width: 220px; - margin: .5em 0em 0 0em; - padding: .5em; - background-color: #fff; -} - -/* textarea */ -.cbi-input-textarea { - font-family: monospace; - width: 100%; - font-size: 0.875rem; - min-height: 14rem; - padding: .8rem; - color: #000; -} - -#syslog { - font-size: small; - line-height: 1.25; - overflow-y: hidden; - width: 100%; - min-height: 15rem; - padding: 1rem; - resize: none; - color: #242424; - border: 0; - border-radius: 0.375rem; - background-color: #ffffff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -#syslog:focus { - outline: 0; -} - -/* config changes */ -.uci-change-list { - font-family: monospace; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #0f0; - background-color: #cfc; -} - -.uci-change-list del, -.uci-change-legend-label del { - font-style: normal; - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #f00; - background-color: #fcc; -} - -.uci-change-list var, -.uci-change-legend-label var { - font-style: normal; - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #ccc; - background-color: #eee; -} - -.uci-change-list var ins, -.uci-change-list var del { - font-style: normal; - padding: 0; - white-space: pre; - border: 0; -} - -.uci-change-legend { - padding: 5px; -} - -.uci-change-legend-label { - float: left; - width: 150px; -} - -.uci-change-legend-label>ins, -.uci-change-legend-label>del, -.uci-change-legend-label>var { - display: block; - float: left; - width: 10px; - height: 10px; - margin-right: 4px; -} - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - line-height: .4; - border: 0; -} - -.uci-change-list var, -.uci-change-list del, -.uci-change-list ins { - padding: .5rem; -} - -/* other fix */ -#iwsvg, -#iwsvg2, -#bwsvg { - border: thin solid #d4d4d4 !important; -} - -#iwsvg, -[data-page="admin-status-realtime-bandwidth"] #bwsvg { - border-top: 0 !important; -} - -.ifacebox { - line-height: 1.25; - display: inline-flex; - flex-direction: column; - min-width: 100px; - border-bottom: thin solid #ccc; - background-color: #f9f9f9; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 1px 2px rgba(0, 0, 0, .2); -} - -.ifacebox-head { - padding: .25em; - background: #eee; -} - -.ifacebox-head.active { - background: #5e72e4; - background: var(--primary); - - * { - color: #fff; - color: var(--white); - } - -} - -.ifacebox-body { - padding: .5em 1rem; - line-height: 1.6em; -} - -.cbi-image-button { - margin-left: .5rem; -} - -.zonebadge { - display: inline-block; - padding: .2rem .5rem; -} - -.zonebadge .ifacebadge { - margin: .1rem .2rem; - padding: .2rem .3rem; - border: thin solid #6c6c6c; -} - -.zonebadge>input[type="text"] { - min-width: 10rem; - margin-top: .3rem; - padding: .16rem 1rem; -} - -.zonebadge>em, -.zonebadge>strong { - display: inline-block; - margin: 0 .2rem; -} - -.cbi-value-field .cbi-input-checkbox, -.cbi-value-field .cbi-input-radio { - margin-top: .1rem; -} - -.cbi-value-field>ul>li { - display: flex; -} - -.cbi-value-field>ul>li>label { - margin-top: .5rem; -} - -.cbi-value-field>ul>li .ifacebadge { - margin-top: -.5rem; - margin-left: .4rem; - background-color: #eee; -} - -.cbi-section-table-row>.cbi-value-field .cbi-dropdown { - min-width: 7rem; -} - -.cbi-section-create { - display: inline-flex; - align-items: center; - margin: 0.25rem 0 0.25rem 1rem; -} - -.cbi-section-create>* { - margin: .5rem; -} - -.cbi-section-remove { - padding: .5rem; -} - -div.cbi-value var, -td.cbi-value-field var, -.td.cbi-value-field var { - font-style: italic; - color: #0069d6; -} - -.cbi-optionals { - padding: 1rem 1rem 0 1rem; - border-top: thin solid #ccc; -} - -.cbi-dropdown-container { - position: relative; -} - -.cbi-tooltip-container, -span[data-tooltip], -span[data-tooltip] .label { - cursor: help !important; -} - -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - padding: 2px 5px; - transition: opacity .25s ease-out; - white-space: pre; - pointer-events: none; - opacity: 0; - border-radius: 3px; - background: #fff; - box-shadow: 0 0 2px #444; -} - -.cbi-tooltip-container:hover .cbi-tooltip { - left: auto; - transition: opacity .25s ease-in; - opacity: 1; -} - -.zonebadge .cbi-tooltip { - margin: -1.5rem 0 0 -.5rem; - padding: .25rem; - background: inherit; -} - -.zonebadge-empty { - color: #404040; - background: repeating-linear-gradient(45deg, rgba(204, 204, 204, .5), rgba(204, 204, 204, .5) 5px, rgba(255, 255, 255, .5) 5px, rgba(255, 255, 255, .5) 10px); -} - -.zone-forwards { - display: flex; - min-width: 10rem; -} - -.zone-forwards>* { - flex: 1 1 45%; -} - -.zone-forwards>span { - flex-basis: 10%; - padding: 0 .25rem; - text-align: center; -} - -.zone-forwards .zone-src, -.zone-forwards .zone-dest { - display: flex; - flex-direction: column; -} - -.label { - font-size: .8rem; - font-weight: bold; - padding: .3rem .8rem; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: #fff !important; - border-radius: 3px; - background-color: #bfbfbf; - text-shadow: none; -} - -label>input[type="checkbox"], -label>input[type="radio"] { - position: relative; - top: .4rem; - right: .2rem; - margin: 0; - vertical-align: bottom; -} - -label[data-index][data-depends] { - padding-right: 2em; -} - -.showSide { - display: none; -} - -.darkMask { - position: fixed; - z-index: 99; - display: none; - width: 100%; - height: 100%; - content: ""; - top: 0; - background-color: rgba(0, 0, 0, .56); -} - -/* diagnostics */ -#diag-rc-output>pre, -#command-rc-output>pre, -[data-page="admin-services-wol"] .notice code { - font-size: 1.2rem; - font-size-adjust: .35; - line-height: normal; - display: block; - overflow-y: hidden; - width: 100%; - padding: 8.5px; - white-space: pre; - color: #eee; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -[data-page="admin-network-diagnostics"] .table { - box-shadow: none; -} - -input[name="ping"], -input[name="traceroute"], -input[name="nslookup"] { - width: 80%; -} - - - -/* fix status */ -.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2), -.node-status-processes>.main .table .tr .td:nth-child(3) { - white-space: normal; -} - -/* fix system reboot */ -[data-page="admin-system-reboot"] p { - padding-left: 1.5rem; -} - -[data-page="admin-system-reboot"] .cbi-button { - background: #fb6340 !important; -} - -[data-page="admin-system-reboot"] p>span { - position: relative; - top: .1rem; - left: 1rem; -} - -[data-page="admin-vpn-passwall"] h4 { - background: transparent; -} - -/* samba */ -#cbi-samba [data-tab="template"] .cbi-value-field { - display: block; -} - -#cbi-samba [data-tab="template"] .cbi-value-title { - width: auto; - padding-bottom: .6rem; -} - -/* admin-system-admin-password */ -[data-page="admin-system-admin"] .cbi-map h2, -[data-page="admin-system-admin-password"] .cbi-map h2, -[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, -[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - margin-left: 0; - color: #32325d; - color: var(--gray-dark); -} - - -/* software */ -[data-page="admin-system-opkg"] h2 { - margin-left: 0; - color: #32325d; - color: var(--gray-dark); -} - -.controls { - margin: .5em 1rem 1em 1rem !important; -} - -.controls>*>.btn:not([aria-label$="page"]) { - flex-grow: initial !important; - margin-top: .25rem; -} - -.controls>#pager>.btn[aria-label$="page"] { - font-size: 1.4rem; - font-weight: bold; -} - -.controls>*>label { - margin-bottom: .2rem; -} - -[data-page="admin-system-opkg"] div.btn { - line-height: 3; - display: inline; - padding: .3rem .6rem; -} - -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent>.container { - margin-top: 2rem; - padding-top: .1rem; -} - -[data-page="admin-system-opkg"] #maincontent>.container { - margin: 0 1.25rem 1rem 1.25rem; - margin-bottom: 1rem; -} - -.td.version, -.td.size { - white-space: normal !important; - word-break: break-word; -} - -.cbi-tabmenu+.cbi-section { - margin-top: 0; -} - -/* admin-system-crontab*/ -[data-page="admin-system-crontab"] #view p { - margin-bottom: 1rem; -} - -/*admin-system-flash*/ - -[data-page="admin-system-flash"] { - .cbi-value { - padding: 0; - } - - .cbi-section { - .cbi-section { - margin-top: 0; - } - } - - .cbi-map-tabbed { - border-radius: 0.375rem; - } - - legend { - display: block !important; - font-size: 1.2rem; - width: 100%; - display: block; - margin-bottom: 0; - padding: 1rem 0 1rem 1.5rem; - border-bottom: 1px solid rgba(0, 0, 0, .05); - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: 0.1rem; - color: #32325d; - font-weight: bold; - } - - .cbi-section-descr { - font-weight: 600; - padding: 1rem 0 1rem 1.5rem; - color: #525f7f; - } - - .modal { - - - label>input[type="checkbox"] { - top: -0.35rem; - } - - .btn { - white-space: normal !important; - } - } -} - -/* wireless overview */ -#cbi-wireless>#wifi_assoclist_table>.tr { - box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { - right: 33px; - bottom: 33px; - left: 33px; - border-top: thin solid #ddd !important; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.table-titles { - box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { - border-bottom: thin solid #ddd; - box-shadow: 0 -1px 0 0 #ddd; -} - -#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { - width: 23rem; -} - -[data-page="admin-network-dhcp"] .cbi-value { - padding: 0; - -} - -[data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem 0 !important; -} - -/* firewall */ -#iptables { - margin: 0; -} - -.Firewall form { - margin: 2rem 2rem 0 0; - padding: 0; - box-shadow: none; -} - -#cbi-firewall-redirect table *, -#cbi-network-switch_vlan table *, -#cbi-firewall-zone table * { - font-size: small; -} - -#cbi-firewall-redirect table input[type="text"], -#cbi-network-switch_vlan table input[type="text"], -#cbi-firewall-zone table input[type="text"] { - width: 5rem; -} - -#cbi-firewall-redirect table select, -#cbi-network-switch_vlan table select, -#cbi-firewall-zone table select { - min-width: 3.5rem; -} - -#cbi-network-switch_vlan .th, -#cbi-network-switch_vlan .td { - flex-basis: 12%; -} - -#cbi-firewall-zone .table, -#cbi-network-switch_vlan .table { - display: block; -} - -#cbi-firewall-zone .td, -#cbi-network-switch_vlan .td { - width: 100%; -} - -[data-page="admin-network-firewall-custom"] #view p, -[data-page="admin-status-routes"] #view p { - padding: 0 1.5rem; - margin-bottom: 1rem; - - textarea { - padding: 1rem; - border-radius: 0.375rem; - } -} - -/* applyreboot fix */ -#applyreboot-container { - margin: 2rem; -} - -#applyreboot-section { - line-height: 300%; - margin: 2rem; -} - -/* openvpn bug fix */ -.OpenVPN a { - line-height: initial !important; -} - -/* custom commands */ -.commandbox { - width: 24% !important; - margin: 10px 0 0 10px !important; - padding: .5rem 1rem; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); -} - -.commandbox h3 { - line-height: normal !important; - overflow: hidden; - margin: 6px 0 !important; - white-space: nowrap; - text-overflow: ellipsis; -} - -.commandbox div { - left: auto !important; -} - -.commandbox code { - position: absolute; - overflow: hidden; - max-width: 60%; - margin-left: 4px; - padding: 2px 3px; - white-space: nowrap; - text-overflow: ellipsis; -} - -.commandbox code:hover { - overflow-y: auto; - max-height: 50px; - white-space: normal; -} - -.commandbox p:first-of-type { - margin-top: -6px; -} - -.commandbox p:nth-of-type(2) { - margin-top: 2px; -} - -[data-page^="admin-system-commands"] .panel-title, -[data-page^="command-cfg"] .mobile-hide, -[data-page^="command-cfg"] .showSide { - display: none; -} - -#command-rc-output .alert-message { - line-height: 1.42857143; - position: absolute; - top: 40px; - right: 32px; - max-width: 40%; - margin: 0; - animation: anim-fade-in 1.5s forwards; - word-break: break-word; - opacity: 0; -} - -@keyframes anim-fade-in { - 100% { - opacity: 1; - } -} - -/* other fix */ -input[type="checkbox"] { - appearance: none !important; - -webkit-appearance: none !important; - border: 1px solid #dee2e6; - - width: 16px !important; - height: 16px !important; - padding: 0; - cursor: pointer; - transition: all 0.2s; - margin: 1rem 0 0 0; -} - -input[type="checkbox"]:checked { - border: 1px solid #5e72e4; - border: 1px solid var(--primary); - background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; - background-color: #5e72e4; - background-color: var(--primary); - background-size: 70%; - background-repeat: no-repeat; - background-position: center; -} - -.fb-container .cbi-button { - height: auto !important; -} - -#cbi-usb_printer-printer em { - display: block; - padding: 1rem; - text-align: center; -} - -pre.command-output { - padding: 1.5rem; -} - -[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { - padding: 1.5rem !important; -} - -[data-page="admin-nlbw-backup"] form { - padding-left: 1.5rem; -} - -[data-page="admin-status-iptables"] .right { - margin-bottom: 0 !important; -} - -/* IE hacks */ -@media all and (-ms-high-contrast: none) { - .main>.main-left>.nav>.slide>.menu::before { - top: 30.25%; - } - - .main>.main-left>.nav>li:last-child::before { - top: 20%; - } - - .showSide::before { - top: -12px; - } -} - -@media screen and (max-width: 1600px) { - header>.fill>.container>#logo { - margin: 0 2.5rem 0 .5rem; - } - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - .btn:not(button), - .cbi-button { - font-size: .8rem; - } - - .label { - padding: .2rem .6rem; - } - - - .cbi-value-title { - width: 15rem; - padding-right: .6rem; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 18rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 9rem; - } - - .cbi-input-textarea { - font-size: small; - } - - .node-admin-status>.main fieldset li>a { - padding: .3rem .6rem; - } -} - -@media screen and (max-width: 1366px) { - - - header>.fill>.container { - - cursor: default; - } - - - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - - .tabs>li>a, - .cbi-tabmenu>li>a { - padding: .2rem .8rem; - } - - .panel-title { - font-size: 1.1rem; - padding-bottom: 1rem; - } - - table { - font-size: .7rem !important; - width: 100% !important; - } - - .table .cbi-input-text { - width: 100%; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 16rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 4rem; - } - - .main>.main-left>.nav>li, - .main>.main-left>.nav>li>a, - .main .main-left .nav>li>a:first-child, - .main>.main-left>.nav>.slide>.menu, - .main>.main-left>.nav>li>[data-title="Logout"] { - font-size: .9rem; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: .7rem; - } - - #modal_overlay { - top: 0rem; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { - display: block; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), - [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), - [data-page="admin-network-hosts"] .table, - [data-page="admin-network-routes"] .table { - overflow-y: visible; - } - - .commandbox { - width: 32% !important; - } - - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - - } -} - -@media screen and (max-width: 1152px) { - header>.fill>.container>#logo { - display: none; - } - - header>.fill>.container>.brand { - position: relative; - } - - html, - .main { - overflow-y: visible; - } - - .main>.loading>span { - top: 25%; - } - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - - - body:not(.logged-in) .showSide { - visibility: hidden; - width: 0; - margin: 0; - } - - .node-main-login>.main .cbi-value-title { - text-align: left; - } - - .cbi-value-title { - width: 12rem; - padding-right: 1rem; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"] { - width: 16rem; - min-width: 16rem; - } - - /*.cbi-value input[type="password"],*/ - .cbi-value input[name^="pw"], - .cbi-value input[data-update="change"]:nth-child(2) { - width: 13rem !important; - min-width: 13rem; - } - - #diag-rc-output>pre, - #command-rc-output>pre, - [data-page="admin-services-wol"] .notice code { - font-size: 1rem; - } - - .table { - display: block; - } - - .Interfaces .table { - overflow-x: hidden; - } - - #packages.table { - display: grid; - } - - .tr { - display: flex; - flex-direction: row; - flex-wrap: wrap; - } - - .Overview .table[width="100%"]>.tr { - flex-wrap: nowrap; - } - - .tr.placeholder { - border-bottom: thin solid #ddd; - } - - .tr.placeholder>.td, - #cbi-firewall .tr>.td, - #cbi-network .tr:nth-child(2)>.td, - .cbi-section #wifi_assoclist_table .tr>.td { - border-top: 0; - } - - .th, - .td { - display: inline-block; - align-self: flex-start; - flex: 2 2 10%; - text-overflow: ellipsis; - word-wrap: break-word; - } - - .td select, - .td input[type="text"] { - width: 100%; - word-wrap: normal; - } - - .td [data-dynlist]>input, - .td input.cbi-input-password { - width: calc(100% - 1.5rem); - } - - .td[data-type="button"], - .td[data-type="fvalue"] { - flex: 1 1 12.5%; - text-align: left; - } - - .th.cbi-value-field, - .td.cbi-value-field, - .th.cbi-section-table-cell, - .td.cbi-section-table-cell { - flex-basis: auto; - padding-top: 1rem; - } - - .cbi-section-table-row { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-between; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); - } - - .td.cbi-value-field, - .cbi-section-table-cell { - display: inline-block; - flex: 10 10 auto; - flex-basis: 50%; - text-align: center; - } - - .td.cbi-section-actions { - vertical-align: bottom; - } - - .tr.table-titles, - .tr.cbi-section-table-titles, - .tr.cbi-section-table-descr { - display: none; - } - - .tr[data-title]::before, - .tr.cbi-section-table-titles.named::before { - font-size: .9rem; - display: block; - flex: 1 1 100%; - border-bottom: thin solid rgba(0, 0, 0, .26); - background: #e9ecef; - } - - .td[data-title], - [data-page^="admin-status-realtime"] .td[id] { - text-align: left; - } - - .td[data-title]::before { - display: block; - } - - .cbi-button+.cbi-button { - margin-left: 0; - } - - .td.cbi-section-actions>*>*, - .td.cbi-section-actions>*>form>* { - margin: 2.1px 3px; - } - - .Firewall form { - position: static !important; - margin: 0 0 2rem 0; - padding: 2rem; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); - } - - .Firewall form input { - width: 100% !important; - margin: 0; - margin-top: 1rem; - } - - .Firewall .center, - .Firewall .center::before { - text-align: left !important; - } - - .commandbox { - width: 100% !important; - margin-left: 0 !important; - } - - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - } -} - - - - -@media screen and (max-width: 768px) { - body { - font-size: .8rem; - } - - .cbi-progressbar::after { - font-size: .5rem; - line-height: 1.5; - } - - - - .main-left { - position: fixed; - z-index: 100; - width: 0; - } - - .main-right { - width: 100%; - } - - .showSide { - padding: 0.1rem; - position: relative; - z-index: 99; - display: inline-block !important; - - &::before { - font-family: 'argon' !important; - font-style: normal !important; - font-weight: normal !important; - font-variant: normal !important; - text-transform: none !important; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: "\e20e"; - font-size: 1.7rem; - } - } - - - header>.fill>.container>.brand { - display: inline-block; - } - - - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: 0.8rem; - } - - - -} - -@media screen and (max-width: 600px) { - .mobile-hide { - display: none; - } - - #maincontent>.container { - margin: 0 1rem 1rem 1rem; - } - - .cbi-value-title { - text-align: left; - } - - [data-page="admin-system-flash"] legend { - padding: 1rem 0 1rem 1rem; - - } - - [data-page="admin-system-flash"] .cbi-section-descr { - padding: 1rem 0 1rem 1rem; - - } - - [data-page="admin-system-flash"] .cbi-value { - padding: 0 1rem; - } - - [data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem 1rem !important; - } - - .cbi-dynlist p { - padding: 0.5rem 1rem; - } - - body { - overflow-x: hidden; - } - - .node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field { - width: 16rem; - } - - .node-main-login footer { - display: none; - } - - .tabs, - .cbi-tabmenu { - &::-webkit-scrollbar { - width: 0px; - height: 0px; - } - } - - .cbi-value-field, - .cbi-value-description { - display: block !important; - padding-left: 0 !important; - padding-right: 0 !important; - } - - [data-page="admin-system-admin-password"] .cbi-value-field { - display: table-cell !important; - } - - .modal.cbi-modal { - max-width: 100%; - max-height: none; - } - - .modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 100%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - margin: 5em auto; - padding: 1em; - border-radius: 3px !important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - } - - .cbi-dropdown[open]>ul.dropdown { - left: 0.2rem !important; - right: 0 !important; - margin-bottom: 1rem; - } -} - - - -@media screen and (min-width: 600px) { - ::-webkit-scrollbar { - width: 10px; - height: 10px; - } - - ::-webkit-scrollbar, - ::-webkit-scrollbar-corner { - background: transparent; - } - - ::-webkit-scrollbar-thumb { - background: #9e9e9e; - } - - ::-webkit-scrollbar-thumb:hover { - background: #757575; - } - - ::-webkit-scrollbar-thumb:active { - background: #424242; - } - - - - -} - - - -@media screen and (max-width: 480px) { - .mobile-hide { - display: none; - } - - .login-page .login-container { - margin-left: 0rem !important; - width: 100%; - - .login-form { - .form-login { - .input-group { - &::before { - color: #525461; - } - - input { - color: #525461; - border-bottom: white 1px solid; - border-bottom: var(--white) 1px solid; - border-radius: 0; - } - - } - } - } - - } - - -} diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/dark.less b/luci-theme-argon/htdocs/luci-static/argon/less/dark.less deleted file mode 100644 index 8143723e5..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/less/dark.less +++ /dev/null @@ -1,828 +0,0 @@ -// compress: false , sourceMap: false -/** - * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template - * - * luci-theme-argon - * Copyright 2020 Jerryk - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-bootstrap: - * Copyright 2008 Steven Barth - * Copyright 2008 Jo-Philipp Wich - * Copyright 2012 David Menting - * - * MUI: - * https://github.com/muicss/mui - * - * luci-theme-material: - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * - * Licensed to the public under the Apache License 2.0 - */ - -body { - background: #1e1e1e; - color: #cccccc; -} - -.login-page .login-container { - - .login-form { - background-color: #1e1e1e; - - .brand { - color: #adb5bd; - } - - .form-login { - .input-group { - &::before { - color: #adb5bd; - } - - input { - background-color: transparent !important; - color: #adb5bd; - border-bottom: #adb5bd 1px solid !important; - border-radius: 0 !important; - border-top: none !important; - border-left: none !important; - border-right: none !important; - box-shadow: none; - } - - } - - .cbi-button-apply { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - - &:hover, - &:focus { - opacity: 0.9; - } - } - } - } - -} - -header::after { - background-color: #1e1e1e !important; -} - - -.main { - .main-left { - - background-color: #333333 !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .15); - - .sidenav-header .brand { - color: #ccc; - } - - .nav { - .slide { - .slide-menu { - .active { - a { - color: #cccccc; - - &::after { - background-color: #cccccc !important; - } - } - } - - li { - a { - color: #cccccc; - } - - a:hover { - background: none !important; - } - } - } - - .menu.active { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - color: #cccccc !important; - - a::after { - background-color: #cccccc !important; - } - } - } - - li { - a { - color: #cccccc !important; - } - - a:hover { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - color: #cccccc !important; - } - } - } - - - &::-webkit-scrollbar-thumb { - background-color: #252526 !important; - } - - &::-webkit-scrollbar-track { - background-color: #333; - } - } - - .main-right { - background-color: #1e1e1e; - } -} - -h2 { - color: #ccc; - background: #333333; -} - -h3 { - color: #ccc; - border-bottom: 0; - background: #333333; -} - -a:-webkit-any-link { - color: -webkit-link; - cursor: pointer; - color: #483d8b; - color: var(--dark-primary); -} - - -input:-webkit-autofill { - background-color: #3c3c3c !important; -} - -.cbi-value-field .cbi-input-apply, -.cbi-button-apply, -.cbi-button-edit { - color: #fff !important; - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; -} - - -.cbi-section em { - color: #ccc; -} - -header.bg-primary { - background-color: #1e1e1e !important; -} - -.cbi-map-descr { - color: #ccc; -} - -.cbi-section { - background: none; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) -} - -.panel-title { - color: #ccc; - background-color: #333333; - border-bottom: 0px; -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tr:nth-of-type(2n) { - background-color: #252526; -} - -table>tbody>tr>td, -table>tfoot>tr>td, -table>thead>tr>td { - color: #ccc; -} - -fieldset>table>tbody>tr:nth-of-type(2n) { - background-color: #252526; -} - -table>tbody>tr>td, -table>tfoot>tr>td, -table>thead>tr>td { - border-top: 1px solid #252526; -} - -#swaptotal>div>div, -#swapfree>div>div, -#memfree>div>div, -#membuff>div>div, -#conns>div>div, -#memtotal>div>div { - background-color: #32325d !important; -} - -#swaptotal>div>div>div>small, -#swapfree>div>div>div>small, -#memfree>div>div>div>small, -#membuff>div>div>div>small, -#conns>div>div>div>small, -#memtotal>div>div>div>small { - - color: #ccc !important; -} - -.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last { - line-height: 1.8em; - - div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] { - border: 1px solid #999999 !important; - background-color: transparent !important; - - div { - background-color: #32325d !important; - } - } - -} - -table>tbody>tr>th, -table>tfoot>tr>th, -table>thead>tr>th { - - background-color: #252526; - border-bottom: black 1px solid !important; -} - -tr>td, -tr>th, -.tr>.td, -.tr>.th, -.cbi-section-table-row::before, -#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { - border-top: 0; -} - -.cbi-rowstyle-2 { - background-color: #1e1e1e; -} - -.cbi-rowstyle-1 { - background-color: #252526; -} - -.cbi-section>h3:first-child, -.panel-title, -h3 { - color: #ccc; - border-bottom: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} - -h4 { - background-color: #1e1e1f; -} - -.cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - margin: 6px 0; - border: thin solid #999; - background: transparent; - border-radius: 0.2rem; - overflow: hidden; - - div { - background-color: #32325d !important; - } -} - -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - background-color: #1e1e1f; -} - -.cbi-button { - color: #ccc !important; - background-color: #483d8b; - background-color: var(--dark-primary); -} - -.cbi-section-node { - background: none; - border-radius: 0 0 .375rem .375rem; - padding: 0rem; -} - -abbr { - color: #5e72e4; -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tbody>.tr:nth-of-type(2n) { - background-color: #252526; -} - -#content_syslog { - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) -} - -#syslog { - color: #ccc; - background-color: #1e1e1e; -} - -#iwsvg, -#iwsvg2, -#bwsvg { - overflow: hidden; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - background-color: #1e1e1e !important; -} - -.tabs { - background-color: #252526; -} - -.tabs>li[class~="active"]>a { - color: #ccc; -} - -.tabs>li[class~="active"], -.tabs>li:hover { - border-bottom: 0.18751rem solid #483d8b; - border-bottom: 0.18751rem solid var(--dark-primary); - color: #ccc; - background-color: #181819; -} - -.cbi-tabmenu>li>a, -.tabs>li>a { - color: #ccc; - - &:hover { - color: #ccc; - } -} - -.cbi-tabmenu>li { - background: #2d2d2d; -} - -.cbi-tabmenu li[class~="cbi-tab"] a { - color: #ccc; -} - -.cbi-tabmenu>li:hover { - color: #ccc; - background: #2d2d2d; -} - -.cbi-tabmenu>li[class~="cbi-tab"] { - background-color: #181819; -} - -.cbi-tabcontainer>.cbi-value:nth-of-type(2n) { - background-color: #252526; -} - -.cbi-value-title { - color: #ccc; -} - -select, -input { - color: #ccc; - background-color: transparent !important; - border: 1px solid #252526; - box-shadow: none; -} - -select:not([multiple="multiple"]):focus, -input:focus { - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; - outline: 0; - -} - -select { - background-color: #1e1e1e !important; -} - -#cbi-dropbear h2, -#cbi-dropbear .cbi-map-descr, -#cbi-dropbear .cbi-map-descr abbr, -#cbi-rc h2, -#cbi-rc .cbi-map-descr, -#cbi-distfeedconf h2, -#cbi-distfeedconf .cbi-map-descr, -#cbi-customfeedconf h2, -#cbi-customfeedconf .cbi-map-descr, -#cbi-download h2, -#cbi-filelist h2 { - color: #ccc !important; -} - -.cbi-value-field>ul>li .ifacebadge { - background-color: #3c3c3c; -} - -.cbi-section-descr { - color: #ccc; -} - -.cbi-input-textarea { - background-color: #1e1e1e; - color: #ccc; -} - - - -.cbi-section-remove:nth-of-type(2n), -.cbi-section-node:nth-of-type(2n) { - background-color: #1e1e1e; -} - -.node-system-packages>.main table tr td:nth-last-child(1) { - color: #ccc; - -} - -.cbi-section-node .cbi-value { - padding: 1rem 1rem 0.3rem 1rem; -} - -.ifacebox { - background-color: none; - border: 1px solid #1e1e1e; -} - -.ifacebox-head { - color: #666; -} - -.ifacebox-body { - background-color: #333; -} - -.zonebadge strong { - color: #333; -} - -.zonebadge>.ifacebadge { - background-color: #3c3c3c; -} - -div.cbi-value var, -td.cbi-value-field var { - color: #5e72e4; -} - -#diag-rc-output>pre { - color: #ccc; - background-color: #1e1e1e; -} - -.node-services-vssr .block { - background-color: #3c3c3c !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); -} - -.node-services-vssr .block h4 { - color: #ccc !important; -} - -.node-services-vssr .status-bar { - color: #ccc; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - background-color: #1e1e1e; -} - -.node-services-vssr .cbi-section-table-row { - color: #ccc; - background-color: #3c3c3c !important; - box-shadow: 0 0 5px 0 rgba(0, 0, 0, .35) -} - -.node-services-vssr .cbi-section-table-row.fast { - background: #483d8b !important; - background: var(--dark-primary) !important; - color: #fff; -} - -.node-services-vssr .ssr-button { - color: #ccc; - -} - -.node-services-vssr .incon:nth-child(2) { - border-right: #1e1e1e 1px solid; -} - -#xhr_poll_status>.label.success { - color: #ccc !important; - - background-color: darkolivegreen !important; -} - -.notice { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; -} - -.cbi-input-find, -.cbi-input-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-find, -.cbi-input-reload, -.cbi-button-reload { - color: #fff !important; - background: darkolivegreen !important; - border-color: darkolivegreen !important; -} - -.cbi-button-reset, -.cbi-input-remove { - color: #fff !important; - background-color: darkorange !important; - border-color: darkorange !important; -} - -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit.important, -.cbi-button-apply.important, -.cbi-button-reload.important, -.cbi-button-action.important { - border: 1px #483d8b solid !important; - border: 1px var(--dark-primary) solid !important; -} - -.btn[value="Dismiss"], -.cbi-button[value="Terminate"], -.cbi-button[value="Reset"], -.cbi-button[value="Disabled"], -.cbi-button[onclick^="iface_reconnect"], -.cbi-button[onclick="handleReset(event)"], -.cbi-button-neutral[value="Disable"] { - font-weight: normal; - color: #fff; - border: thin solid darkorange !important; - background-color: darkorange !important; -} - -fieldset[id^="cbi-apply-"] { - background-color: #333333; -} - -#detail-bubble>div { - border: 1px solid #ccc; - border-radius: 2px; - padding: 5px; - background: #252525; -} - -.ifacebox-head.active { - background-color: #32325d !important; -} - -header .fill .status span[data-style="active"] { - color: #ccc !important; - background-color: darkolivegreen !important; -} - -#cbi-wireless .td, -#cbi-network .tr:first-child>.td, -.table[width="100%"]>.tr:first-child>.td, -[data-page="admin-network-diagnostics"] .tr>.td, -.tr.table-titles>.th, -.tr.cbi-section-table-titles>.th { - background-color: #252526; - border-bottom: black 1px solid !important; - -} - -.network-status-table .ifacebox-body .ifacebadge { - background-color: #252526; - border-bottom: 0; - box-shadow: none; -} - -td>.ifacebadge, -.td>.ifacebadge { - - background-color: #483d8b; - background-color: var(--dark-primary); - border: 0; -} - -.btn.danger, -.cbi-section-remove>.cbi-button, -.cbi-button-remove, -.cbi-button-reset, -.cbi-button-negative, -.cbi-button[value="Stop"], -.cbi-button[value="Kill"], -.cbi-button[onclick="reboot(this)"], -.cbi-button-neutral[value="Restart"] { - border: thin solid darkorange !important; - background-color: darkorange !important; -} - -.cbi-section, -.cbi-section-error, -#iptables, -.Firewall form, -#cbi-network>.cbi-section-node, -#cbi-wireless>.cbi-section-node, -#cbi-wireless>#wifi_assoclist_table, -[data-tab-title], -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent>.container { - background: #1e1e1e !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); -} - -div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - background: transparent !important; -} - -[data-page="admin-system-admin"] .cbi-map h2, -[data-page="admin-system-admin-password"] .cbi-map h2, -[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, -[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - color: #ccc; -} - -[data-page="admin-system-flash"] { - .modal { - label>input[type="checkbox"] { - top: -0.35rem; - } - - .btn { - white-space: normal !important; - background-color: darkseagreen; - } - - .alert-message { - background-color: transparent !important; - } - - .danger { - border: thin solid darkorange !important; - background-color: darkorange !important; - } - } -} - -.cbi-value input[type="password"]+.cbi-button-neutral { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; -} - -.btn, -button, -select, -input, -.cbi-dropdown { - border: 1px solid #3c3c3c !important; -} - - -.cbi-dropdown .preview { - color: #ccc; -} - -.cbi-section-table-row { - background-color: #1e1e1e !important; -} - -.modal { - background-color: #1e1e1e; -} - -.cbi-button-positive { - color: #fff !important; - background-color: darkolivegreen !important; -} - -[data-page="admin-system-flash"] legend { - color: #ccc; -} - -.logout:before { - color: #adb5bd !important; -} - -.cbi-dropdown[open] { - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; -} - -.cbi-dropdown[open]>ul.dropdown { - background: #252526 !important; - color: #ccc !important; - box-shadow: none; - border: 1px solid #3c3c3c !important; - - -} - -.cbi-dropdown[open]>ul.dropdown li { - color: #ccc; - border-bottom: 1px solid #3c3c3c !important; -} - -.cbi-dropdown[open]>ul.dropdown>li[selected] { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - border-bottom: 1px solid #3c3c3c !important; -} - -.cbi-dropdown[open]>ul.dropdown>li.focus { - background: #483d8b; - background: var(--dark-primary); - outline: none; -} - -.ifacebadge { - background-color: #333333; -} - -.cbi-dynlist>.item>span { - border: 1px solid #3c3c3c !important; -} - -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-action, -.cbi-button[value="Submit"], -.cbi-button[value="Upload"], -.cbi-button[value$="Apply"], -.cbi-button[onclick="addKey(event)"] { - background: #483d8b !important; - background: var(--dark-primary) !important; -} - -.btn.primary, -.cbi-page-actions .cbi-button-save, -.cbi-page-actions .cbi-button-apply+.cbi-button-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-positive, -.cbi-button-link, -.cbi-button[value="Enable"], -.cbi-button[value="Scan"], -.cbi-button[value^="Back"], -.cbi-button-neutral[onclick="handleConfig(event)"] { - background: #483d8b; - background: var(--dark-primary); -} - -[data-page="admin-system-opkg"] h2 { - color: #ccc !important; -} - -@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) { - .login-page .login-container .login-form { - -webkit-backdrop-filter: blur(var(--blur-radius-dark)); - backdrop-filter: blur(var(--blur-radius-dark)); - background-color: rgba(0, 0, 0, var(--blur-opacity-dark)); - - } -} - - -@media screen and (max-width: 480px) { - .node-status-iptables>.main div>.cbi-map>form { - background-color: #1e1e1e; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - } - - -} diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer.htm b/luci-theme-argon/luasrc/view/themes/argon/footer.htm deleted file mode 100644 index a4e1df4b2..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/footer.htm +++ /dev/null @@ -1,46 +0,0 @@ -<%# - Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template - - luci-theme-argon - Copyright 2020 Jerrykuku - - Have a bug? Please create an issue here on GitHub! - https://github.com/jerrykuku/luci-theme-argon/issues - - luci-theme-material: - Copyright 2015 Lutty Yang - - Agron Theme - https://demos.creative-tim.com/argon-dashboard/index.html - - Licensed to the public under the Apache License 2.0 --%> - -<% local ver = require "luci.version" %> -

    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�$dl3gH)Q&OCfV6T};Oqr8= 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 J%do#+{vV8|Vut_# diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/blank.png b/luci-theme-argon/htdocs/luci-static/argon/img/blank.png deleted file mode 100644 index 9f4100e6e2ea2fa08912439eb7425af3f048eedd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 938 zcmaJ=L66cv6t0pOLtGQRxu;1t8cn3rmX@UxDuEV+#1g`iEC&ykc7V#ZQ`^B74o1E0 z!9@RtCjJ4Vo;`W;;-Byjn5vqfmTeG-$ z^$PpHk-vXt%Pra((IYaUi5+3C;gT^1UEiMK0k+-cvv0V@afLhHa70JeBjgZYurrL1 z`XOU;T&;m#;qnwG=S{ zA5$Bo{z(v{ROi>ah{f44|Y zg;KdBRgfYgSq7VrXW1fmf(B-LlZ)+ienx4CAWV`(NXi0_9I4~G;sIW3tW=K z_tqTCLfs&ycHrQysq;)l@H`ilE0WPRn-#+l6-jC}G^uPDimIwwvsqP|M$R>fv+!|1 zbFO>AJ>1F7#=#F+W)nx=bL_Sw;)8YB$lL8j*{QeTy1TuoJGqdVf!XE$b=mn5o1iS* zjxO75haU%Q;v+WNFFxG9&Ys17*K7>apX1+WXZ3>g^7K_leE${|FI~RI{kU1U@$}2P Q$Jy)YwtD8r=9AZd04Jv&d;kCd diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg b/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg deleted file mode 100644 index f01ad5c79..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg b/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg deleted file mode 100644 index 0598d584e..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/js/jquery.min.js b/luci-theme-argon/htdocs/luci-static/argon/js/jquery.min.js deleted file mode 100644 index b0614034a..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/js/jquery.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="

    - -
    -
    - - - - diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm deleted file mode 100644 index a4e1df4b2..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm +++ /dev/null @@ -1,46 +0,0 @@ -<%# - Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template - - luci-theme-argon - Copyright 2020 Jerrykuku - - Have a bug? Please create an issue here on GitHub! - https://github.com/jerrykuku/luci-theme-argon/issues - - luci-theme-material: - Copyright 2015 Lutty Yang - - Agron Theme - https://demos.creative-tim.com/argon-dashboard/index.html - - Licensed to the public under the Apache License 2.0 --%> - -<% local ver = require "luci.version" %> -
    - -
    -
    - - - - diff --git a/luci-theme-argon/luasrc/view/themes/argon/header.htm b/luci-theme-argon/luasrc/view/themes/argon/header.htm deleted file mode 100644 index 1da2486b6..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/header.htm +++ /dev/null @@ -1,282 +0,0 @@ -<%# - Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template - - luci-theme-argon - Copyright 2020 Jerrykuku - - Have a bug? Please create an issue here on GitHub! - https://github.com/jerrykuku/luci-theme-argon/issues - - luci-theme-material: - Copyright 2015 Lutty Yang - - Argon Theme - https://demos.creative-tim.com/argon-dashboard/index.html - - Licensed to the public under the Apache License 2.0 --%> - -<% - local sys = require "luci.sys" - local util = require "luci.util" - local http = require "luci.http" - local disp = require "luci.dispatcher" - - local boardinfo = util.ubus("system", "board") - - local node = disp.context.dispatched - - local fs = require "nixio.fs" - local nutil = require "nixio.util" - local uci = require 'luci.model.uci'.cursor() - - -- send as HTML5 - http.prepare_content("text/html") - - math.randomseed(os.time()) - - -- Custom settings - local mode = 'normal' - local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') - local bar_color = '#5e72e4' - local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity - if fs.access('/etc/config/argon') then - primary = uci:get_first('argon', 'global', 'primary') - dark_primary = uci:get_first('argon', 'global', 'dark_primary') - blur_radius = uci:get_first('argon', 'global', 'blur') - blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') - blur_opacity = uci:get_first('argon', 'global', 'transparency') - blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') - mode = uci:get_first('argon', 'global', 'mode') - bar_color = mode == 'dark' and dark_primary or primary - end - - -- Brand name - local brand_name = boardinfo.hostname or "?" --%> - - - - - - - <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - - LuCI - - - - - - - - - - - - LuCI"> - - LuCI"> - - - - - - - - - - - - - - - <% if node and node.css then %> - - <% end -%> - <% if css then %> - - <% end -%> - - - - - - - - -"> - -
    - -
    -
    -
    -
    - - <%=brand_name%> -
    - -
    -
    -
    -
    -
    -
    -
    - <%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%> -
    -

    <%:No password set!%>

    -

    <%:There is no password set on this router. Please configure a root password to protect the web interface.%> -

    - <% if disp.lookup("admin/system/admin") then %> - - <% end %> -
    - <%- end -%> - - - - diff --git a/luci-theme-argon/luasrc/view/themes/argon/header_login.htm b/luci-theme-argon/luasrc/view/themes/argon/header_login.htm deleted file mode 100644 index 36de24c47..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/header_login.htm +++ /dev/null @@ -1,123 +0,0 @@ -<%# - Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template - - luci-theme-argon - Copyright 2020 Jerrykuku - - Have a bug? Please create an issue here on GitHub! - https://github.com/jerrykuku/luci-theme-argon/issues - - luci-theme-material: - Copyright 2015 Lutty Yang - - Argon Theme - https://demos.creative-tim.com/argon-dashboard/index.html - - Licensed to the public under the Apache License 2.0 --%> - -<% - local sys = require "luci.sys" - local util = require "luci.util" - local http = require "luci.http" - local disp = require "luci.dispatcher" - - local boardinfo = util.ubus("system", "board") - - local node = disp.context.dispatched - - local fs = require "nixio.fs" - local nutil = require "nixio.util" - local uci = require 'luci.model.uci'.cursor() - - -- send as HTML5 - http.prepare_content("text/html") - - math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 9))) - - -- Custom settings - local mode = 'normal' - local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') - local bar_color = '#5e72e4' - local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity - if fs.access('/etc/config/argon') then - primary = uci:get_first('argon', 'global', 'primary') - dark_primary = uci:get_first('argon', 'global', 'dark_primary') - blur_radius = uci:get_first('argon', 'global', 'blur') - blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') - blur_opacity = uci:get_first('argon', 'global', 'transparency') - blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') - mode = uci:get_first('argon', 'global', 'mode') - bar_color = mode == 'dark' and dark_primary or primary - end --%> - - - - - - - <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - - LuCI - - - - - - - - - - - - LuCI"> - - LuCI"> - - - - - - - - - - - - - - - <% if node and node.css then %> - - <% end -%> - <% if css then %> - - <% end -%> - - - - - - - -"> diff --git a/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm deleted file mode 100644 index 398314779..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm +++ /dev/null @@ -1,27 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008-2019 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<% - local is_rollback_pending, rollback_time_remaining, rollback_session, rollback_token = luci.model.uci:rollback_pending() - - if is_rollback_pending or trigger_apply or trigger_revert then -%> - -<% - end - - include("themes/" .. theme .. "/footer_login") -%> diff --git a/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm b/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm deleted file mode 100644 index 075c1e873..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm +++ /dev/null @@ -1,38 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008-2019 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<% - if not luci.dispatcher.context.template_header_sent then - include("themes/" .. theme .. "/header_login") - luci.dispatcher.context.template_header_sent = true - end - - local applyconf = luci.config and luci.config.apply -%> - - - - diff --git a/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm b/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm deleted file mode 100644 index 0820aa577..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm +++ /dev/null @@ -1,157 +0,0 @@ -<%# - Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI and Argon Template - - luci-theme-argon - Copyright 2020 Jerryk - - Have a bug? Please create an issue here on GitHub! - https://github.com/jerrykuku/luci-theme-argon/issues - - luci-theme-bootstrap: - Copyright 2008 Steven Barth - Copyright 2008-2016 Jo-Philipp Wich - Copyright 2012 David Menting - - MUI: - https://github.com/muicss/mui - - Argon Theme - https://demos.creative-tim.com/argon-dashboard/index.html - - Licensed to the public under the Apache License 2.0 --%> - -<%+themes/argon/out_header_login%> -<% - local util = require "luci.util" - local boardinfo = util.ubus("system", "board") - local fs = require "nixio.fs" - local nutil = require "nixio.util" - - function glob(...) - local iter, code, msg = fs.glob(...) - if iter then - return nutil.consume(iter) - else - return nil, code, msg - end - end - - function getExtension(str) - return str:match(".+%.(%w+)$") - end - - local bgcount = 0 - local currentBg = {} - local bgs,attr = {} - local theme_dir = media .. "/background/" - for i, f in ipairs(glob("/www" .. theme_dir .. "*")) do - attr = fs.stat(f) - if attr then - local ext = getExtension(fs.basename(f)) - if ext == "jpg" or ext == "png" or ext == "gif" or ext == "mp4" then - local bg = {} - bg.type = ext - bg.url = theme_dir .. fs.basename(f) - table.insert(bgs,bg) - bgcount = bgcount + 1 - end - end - end - - if bgcount > 0 then - currentBg = bgs[math.random(1,bgcount)] - end -%> - + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm new file mode 100644 index 000000000..8098df211 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm @@ -0,0 +1,44 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Agron Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% local ver = require "luci.version" %> +
    + +
    +
    + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/header.htm b/luci-theme-argon/luasrc/view/themes/argon/header.htm new file mode 100644 index 000000000..17717ff65 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/header.htm @@ -0,0 +1,180 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% + local sys = require "luci.sys" + local util = require "luci.util" + local http = require "luci.http" + local disp = require "luci.dispatcher" + local ver = require "luci.version" + + local boardinfo = util.ubus("system", "board") + + local node = disp.context.dispatched + + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local uci = require 'luci.model.uci'.cursor() + + -- send as HTML5 + http.prepare_content("text/html") + + math.randomseed(os.time()) + + -- Custom settings + local mode = 'normal' + local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') + local bar_color = '#5e72e4' + local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity + if fs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bar_color = mode == 'dark' and dark_primary or primary + end + + -- Brand name + local brand_name = boardinfo.hostname or "?" +-%> + + + + + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + + <% if node and node.css then %> + + <% end -%> + <% if css then %> + + <% end -%> + + + + + + + +"> + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + <%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%> +
    +

    <%:No password set!%>

    +

    <%:There is no password set on this router. Please configure a root password to protect the web interface.%> +

    + <% if disp.lookup("admin/system/admin") then %> + + <% end %> +
    + <%- end -%> + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/header_login.htm b/luci-theme-argon/luasrc/view/themes/argon/header_login.htm new file mode 100644 index 000000000..568e0cecb --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/header_login.htm @@ -0,0 +1,119 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% + local sys = require "luci.sys" + local util = require "luci.util" + local http = require "luci.http" + local disp = require "luci.dispatcher" + local ver = require "luci.version" + + local boardinfo = util.ubus("system", "board") + + local node = disp.context.dispatched + + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local uci = require 'luci.model.uci'.cursor() + + -- send as HTML5 + http.prepare_content("text/html") + + math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 9))) + + -- Custom settings + local mode = 'normal' + local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') + local bar_color = '#5e72e4' + local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity + if fs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bar_color = mode == 'dark' and dark_primary or primary + end +-%> + + + + + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + + <% if node and node.css then %> + + <% end -%> + <% if css then %> + + <% end -%> + + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm new file mode 100644 index 000000000..398314779 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm @@ -0,0 +1,27 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008-2019 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<% + local is_rollback_pending, rollback_time_remaining, rollback_session, rollback_token = luci.model.uci:rollback_pending() + + if is_rollback_pending or trigger_apply or trigger_revert then +%> + +<% + end + + include("themes/" .. theme .. "/footer_login") +%> diff --git a/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm b/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm new file mode 100644 index 000000000..35e73ec46 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm @@ -0,0 +1,14 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008-2019 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<% + local ver = require "luci.version" + + if not luci.dispatcher.context.template_header_sent then + include("themes/" .. theme .. "/header_login") + luci.dispatcher.context.template_header_sent = true + end +%> diff --git a/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm b/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm new file mode 100644 index 000000000..5b46f2fa3 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm @@ -0,0 +1,186 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI and Argon Template + + luci-theme-argon + Copyright 2020 Jerryk + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-bootstrap: + Copyright 2008 Steven Barth + Copyright 2008-2016 Jo-Philipp Wich + Copyright 2012 David Menting + + MUI: + https://github.com/muicss/mui + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<%+themes/argon/out_header_login%> +<% + local util = require "luci.util" + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local json = require "luci.jsonc" + local sys = require "luci.sys" + local uci = require 'luci.model.uci'.cursor() + + -- Fetch Local Background Media + + local function glob(...) + local iter, code, msg = fs.glob(...) + if iter then + return nutil.consume(iter) + else + return nil, code, msg + end + end + + + local imageTypes = " jpg png gif " + local videoTypes = " mp4 webm " + local allTypes = imageTypes .. videoTypes + local function fetchMedia(path,themeDir) + local backgroundTable = {} + local backgroundCount = 0 + for i, f in ipairs(glob(path)) do + attr = fs.stat(f) + if attr then + local ext = fs.basename(f):match(".+%.(%w+)$") + if ext ~= nil then + ext = ext:lower() + end + if ext ~= nil and string.match(allTypes, " "..ext.." ") ~= nil then + local bg = {} + bg.type = ext + bg.url = themeDir .. fs.basename(f) + table.insert(backgroundTable,bg) + backgroundCount = backgroundCount + 1 + end + end + end + return backgroundTable,backgroundCount + end + local function selectBackground(themeDir) + local bgUrl = media .. "/img/bg1.jpg" + local backgroundType = "Image" + local mimeType = "" + + if fs.access("/etc/config/argon") then + if uci:get_first('argon', 'global', 'bing_background') == "1" then + local bing = sys.exec("/usr/libexec/argon/bing_wallpaper") + if (bing and bing ~= '') then + return bing, "Image", "" + end + end + end + + local backgroundTable, backgroundCount = fetchMedia("/www" .. themeDir .. "*",themeDir) + if ( backgroundCount > 0 ) then + local currentBg = backgroundTable[math.random(1,backgroundCount)] + bgUrl = currentBg.url + if (string.match(videoTypes, " "..currentBg.type.." ") ~= nil) then + backgroundType = "Video" + mimeType = "video/" .. currentBg.type + end + end + + return bgUrl,backgroundType,mimeType + end + + local boardinfo = util.ubus("system", "board") + local themeDir = media .. "/background/" + local bgUrl,backgroundType,mimeType = selectBackground(themeDir) +%> + + + <% + if sqm == "1" then + %>
    checked<% end %> />
    + <%:SQM control bufferloat: the undesirable latency that arises when the router buffers too much data.%> <%:You should disable SQM for LTE or any interfaces with variable speed.%>
    + <% + end + %> + <% + if qos == "1" then + %> +
    + +
    + checked<% end %> /> +
    +
    + <%:QoS permit to prioritize any upload traffic.%> +
    +
    +
    + <% + end + %>
    diff --git a/openmptcprouter/files/etc/uci-defaults/1960-omr-qos b/openmptcprouter/files/etc/uci-defaults/1960-omr-qos index eaf728dc3..1eba41af4 100755 --- a/openmptcprouter/files/etc/uci-defaults/1960-omr-qos +++ b/openmptcprouter/files/etc/uci-defaults/1960-omr-qos @@ -1,58 +1,56 @@ #!/bin/sh -if [ "$(uci -q get openmptcprouter.latest_versions)" ]; then - if [ "$(uci -q get qos.wan1)" = "" ]; then +if [ -z "$(uci -q get qos.omrvpn)" ]; then + uci -q batch <<-EOF >/dev/null + delete qos.wan + set qos.wan1=interface + set qos.wan1.classgroup="Default" + set qos.wan1.enabled="0" + set qos.wan1.upload="4000" + set qos.wan1.download="100000" + set qos.wan2=interface + set qos.wan2.classgroup="Default" + set qos.wan2.enabled="0" + set qos.wan2.upload="4000" + set qos.wan2.download="100000" + set qos.omrvpn=interface + set qos.omrvpn.classgroup="Default" + set qos.omrvpn.enabled="0" + set qos.omrvpn.interface="tun0" + set qos.omrvpn.upload="0" + set qos.omrvpn.download="0" + set qos.omrvpn.qdisc="cake" + set qos.omrvpn.script="layer_cake.qos" + delete qos.@classify[-1] + add qos classify + set qos.@classify[-1].target='Express' + set qos.@classify[-1].ports='5600' + set qos.@classify[-1].comments='SIP' + add qos classify + set qos.@classify[-1].target='Express' + set qos.@classify[-1].portrange='27000-27050' + set qos.@classify[-1].proto='udp' + set qos.@classify[-1].comments='Steam' + commit qos + EOF + if [ "$(uci -q get network.wan3)" != "" ]; then uci -q batch <<-EOF >/dev/null - delete qos.wan - set qos.wan1=interface - set qos.wan1.classgroup="Default" - set qos.wan1.enabled="0" - set qos.wan1.upload="4000" - set qos.wan1.download="100000" - set qos.wan2=interface - set qos.wan2.classgroup="Default" - set qos.wan2.enabled="0" - set qos.wan2.upload="4000" - set qos.wan2.download="100000" - set qos.omrvpn=interface - set qos.omrvpn.classgroup="Default" - set qos.omrvpn.enabled="1" - set qos.omrvpn.interface="tun0" - set qos.omrvpn.upload="0" - set qos.omrvpn.download="0" - set qos.omrvpn.qdisc="cake" - set qos.omrvpn.script="layer_cake.qos" - delete qos.@classify[-1] - add qos classify - set qos.@classify[-1].target='Express' - set qos.@classify[-1].ports='5600' - set qos.@classify[-1].comments='SIP' - add qos classify - set qos.@classify[-1].target='Express' - set qos.@classify[-1].portrange='27000-27050' - set qos.@classify[-1].proto='udp' - set qos.@classify[-1].comments='Steam' + set qos.wan3=interface + set qos.wan3.classgroup="Default" + set qos.wan3.enabled="0" + set qos.wan3.upload="4000" + set qos.wan3.download="100000" + commit qos + EOF + fi + if [ "$(uci -q get network.wan4)" != "" ]; then + uci -q batch <<-EOF >/dev/null + set qos.wan4=interface + set qos.wan4.classgroup="Default" + set qos.wan4.enabled="0" + set qos.wan4.upload="4000" + set qos.wan4.download="100000" commit qos EOF - if [ "$(uci -q get network.wan3)" != "" ]; then - uci -q batch <<-EOF >/dev/null - set qos.wan3=interface - set qos.wan3.classgroup="Default" - set qos.wan3.enabled="0" - set qos.wan3.upload="4000" - set qos.wan3.download="100000" - commit qos - EOF - fi - if [ "$(uci -q get network.wan4)" != "" ]; then - uci -q batch <<-EOF >/dev/null - set qos.wan4=interface - set qos.wan4.classgroup="Default" - set qos.wan4.enabled="0" - set qos.wan4.upload="4000" - set qos.wan4.download="100000" - commit qos - EOF - fi fi fi rm -f /tmp/luci-indexcache From ac15a5b374da17a8fcab011c8e3506d724ab7113 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 28 May 2022 08:37:39 +0200 Subject: [PATCH 0749/2059] Fixes when default gateway is disabled --- mptcp/files/etc/init.d/mptcp | 6 ++++-- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 9eb53107a..29f4a354e 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -133,6 +133,7 @@ interface_multipath_settings() { [ -z "$mptcpmintf" ] && mptcpmintf="$config" uci -q set network.${config}.defaultroute=0 uci -q set network.${config}.peerdns=0 + echo '' > /etc/resolv.conf 2>&1 >/dev/null } [ "$mode" = "master" ] && { # Force that only one interface is master @@ -166,6 +167,7 @@ interface_multipath_settings() { [ "$config" = "omrvpn" ] && mode="off" [ -n "$(ifconfig | grep $iface)" ] || return 0 [ "$(echo $iface | grep _dev)" != "" ] && return 0 + [ "$(echo $iface | grep '^if')" != "" ] && return 0 if [ "$mode" = "master" ]; then multipath "$iface" "on" @@ -263,7 +265,7 @@ interface_multipath_settings() { ip route replace $network/$netmask dev $iface scope link metric $id 2>&1 >/dev/null ip route replace $network/$netmask dev $iface scope link table $id 2>&1 >/dev/null ip route replace default via $gateway dev $iface table $id 2>&1 >/dev/null - ip route replace default via $gateway dev $iface metric $id 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default via $gateway dev $iface metric $id 2>&1 >/dev/null #ip route flush $id fi @@ -350,7 +352,7 @@ interface_multipath_settings() { ip -6 route replace $network6/$netmask6 dev $iface scope link metric 6$id 2>&1 >/dev/null ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface table 6$id 2>&1 >/dev/null - ip -6 route replace default via $gateway6 dev $iface metric 6$id 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip -6 route replace default via $gateway6 dev $iface metric 6$id 2>&1 >/dev/null #ip -6 route flush 6$id 2>&1 >/dev/null fi diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 5879a6ccb..932c51155 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -563,7 +563,7 @@ set_server_route() { fi } config_list_foreach $server ip server_route - if [ -n "$metric" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ -n "$metric" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null fi } @@ -601,7 +601,7 @@ set_server_route6() { fi } config_list_foreach $server ip server_route - if [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null fi } @@ -1164,7 +1164,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route server fi - if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then _log "Interface route not yet set, set route ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi @@ -1177,7 +1177,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; th elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route6 server fi - if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi fi From 005844c6740c2b2c78cb5f9de89ae9aa68eeb46a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 29 May 2022 20:37:39 +0200 Subject: [PATCH 0750/2059] Fix for 5.15 multipath --- mptcp/files/usr/bin/multipath | 1 + 1 file changed, 1 insertion(+) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 42bb1ddff..c616044e4 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -134,6 +134,7 @@ else ID=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $3}') IFF=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $4}') IP=$(ifconfig $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') + [ -z "$ID" ] && ID=$(ip mptcp endpoint show | grep "$IP" | awk '{print $3}') RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null case $TYPE in From cd3b59436f134ee9ad15fda44e8fa6e198d238be Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 29 May 2022 20:47:47 +0200 Subject: [PATCH 0751/2059] Set txqueuelen to 20 by default for WANs --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 1 + openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 ++ 2 files changed, 3 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index fabf6d97a..ec8eeb466 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -167,6 +167,7 @@ function wizard_add() ucic:set("network","wan" .. i .. "_dev","mode","vepa") ucic:set("network","wan" .. i .. "_dev","ifname",defif) ucic:set("network","wan" .. i .. "_dev","name","wan" .. i) + ucic:set("network","wan" .. i .. "_dev","txqueuelen","20") end ucic:set("network","wan" .. i,"ip4table","wan") if multipath_master then diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index a0e15b2f5..8c2e18080 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -22,6 +22,7 @@ _setup_macvlan() { set network.$1_dev.type=macvlan set network.$1_dev.ifname=$_ifname set network.$1_dev.mode='vepa' + set network.$1_dev.txqueuelen=20 set network.$1.device=$1 set network.$1.type=macvlan set network.$1.masterintf=$_ifname @@ -64,6 +65,7 @@ _setup_wan_interface() { set network.$1.defaultroute=0 set network.${1}_dev=device set network.${1}_dev.name=$2 + set network.${1}_dev.txqueuelen=20 commit network add_list firewall.@zone[1].network=$1 commit firewall From 864f453fe6b54cf8956f45e03d07e629fa5d2410 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 29 May 2022 20:48:59 +0200 Subject: [PATCH 0752/2059] Add quiet to modprobe commands --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 928feb60f..2463d20fa 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -165,7 +165,7 @@ start_service() { fi if [ "$(uci -q get openmptcprouter.settings.sfe_enabled)" = "1" ]; then - [ -z "$(lsmod | grep fast_classifier)" ] && modprobe fast_classifier 2>&1 >/dev/null + [ -z "$(lsmod | grep fast_classifier)" ] && modprobe -q fast_classifier 2>&1 >/dev/null if [ "$(uci -q get openmptcprouter.settings.sfe_bridge)" = "1" ]; then echo 1 >/sys/fast_classifier/skip_to_bridge_ingress else From fdd81a95325fc0b35393be70f77239dabe770b0c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 29 May 2022 20:49:43 +0200 Subject: [PATCH 0753/2059] Change setting text --- .../luasrc/view/openmptcprouter/settings.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index 2db886333..ebd013851 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -256,7 +256,7 @@ checked<% end %>>
    - <%:Disable HTTP test on Server API in status page%> + <%:Disable HTTP test on Server API%>
    From 8927d6d2fe87ebfc98d1fed60002a0dea2f88293 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 29 May 2022 20:50:36 +0200 Subject: [PATCH 0754/2059] API not responding is not a fatal error for connection --- omr-tracker/files/bin/omr-tracker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 910654913..00a6274f4 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -392,7 +392,7 @@ while true; do config_load openmptcprouter config_foreach _httping_server server $OMR_TRACKER_DEVICE_IP if [ "$serverip_ping" = false ]; then - OMR_TRACKER_STATUS="ERROR" + #OMR_TRACKER_STATUS="ERROR" OMR_TRACKER_STATUS_MSG="No access to server API" else OMR_TRACKER_STATUS_MSG="" @@ -493,7 +493,7 @@ while true; do config_foreach _httping_server server $OMR_TRACKER_DEVICE_IP if [ "$serverip_ping" = false ]; then OMR_TRACKER_STATUS_MSG="No access to server API" - OMR_TRACKER_STATUS="ERROR" + #OMR_TRACKER_STATUS="ERROR" else OMR_TRACKER_STATUS_MSG="" OMR_TRACKER_STATUS="OK" From 3506d1fcef49f411c113d835ca9493c128e6470c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 May 2022 18:32:58 +0200 Subject: [PATCH 0755/2059] No mptcpd build on kernel 5.4 --- openmptcprouter-full/Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index e759dc5ee..b5eb342c8 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -28,7 +28,7 @@ MY_DEPENDS := \ iperf3-ssl luci-app-iperf \ arptables \ bind-dig \ - libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ + libnetfilter-conntrack ip-full nstat \ iptables-mod-iface iptables-mod-ipmark iptables-mod-hashlimit iptables-mod-condition iptables-mod-trace iptables-mod-conntrack-extra iptables-mod-account \ kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra conntrack \ iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 kmod-ipt-ipsec \ @@ -78,11 +78,14 @@ MY_DEPENDS := \ !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su kmod-rtl8812au-ct \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 TARGET_r4s:kmod-r8168 (TARGET_x86||TARGET_x86_64):kmod-usb-net-rtl8152 \ - luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ + luci-app-mlvpn mlvpn 464xlat kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ - luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ - mptcpd + luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ + !LINUX_5.4:mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec +# !TARGET_mvebu:kmod-usb-net-smsc75xx +# libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ + # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status # luci-proto-bonding luci-app-statistics luci-proto-gre # softethervpn5-client softethervpn5-server luci-app-nginx-ha From 824fce0c830e7d5870906ed220e3b20aeda84927 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 30 May 2022 21:54:45 +0200 Subject: [PATCH 0756/2059] Use correct golang --- v2ray-core/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index f17adbf69..beb3bd2f4 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -60,7 +60,8 @@ GO_PKG:=github.com/v2fly/v2ray-core/v4 GO_PKG_LDFLAGS:=-s -w include $(INCLUDE_DIR)/package.mk -include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk +#include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk +include $(TOPDIR)/feeds/openmptcprouter/golang/golang-package.mk define Package/v2ray-core TITLE:=A platform for building proxies From 072c061af6119018904e85a11b374690caafd85a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 31 May 2022 11:49:16 +0200 Subject: [PATCH 0757/2059] Install mptcpd only on 5.15 kernel --- mptcpd/Makefile | 2 +- openmptcprouter-full/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcpd/Makefile b/mptcpd/Makefile index 6bb9f7f71..f234e8362 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -25,7 +25,7 @@ include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) SECTION:=net CATEGORY:=Network -DEPENDS:=+libell +DEPENDS:=+libell @LINUX_5_15 TITLE:=mptcpd URL:=https://github.com/intel/mptcpd endef diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index b5eb342c8..a041d9bae 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -82,7 +82,7 @@ MY_DEPENDS := \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ - !LINUX_5.4:mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec + LINUX_5_15:mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From 0e2d6b6b22d70699957de167e0b2f5e13705ab71 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 1 Jun 2022 08:11:57 +0200 Subject: [PATCH 0758/2059] Changes in Guthub Actions due to kernel name in path --- .github/workflows/main.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a5d283713..c43ccaa45 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -66,20 +66,22 @@ jobs: OMR_PORT: ${{ secrets.OMR_PORT }} run: | OMR_KERNEL="${OMR_KERNEL}" OMR_FEED_SRC="${SOURCE_NAME}" sh build.sh prepare {tools,toolchain}/install -j$(nproc) || OMR_KERNEL="${OMR_KERNEL}" OMR_FEED_SRC="${SOURCE_NAME}" sh build.sh prepare {tools,toolchain}/install -j1 V=s - #echo -e "${{ secrets.OMR_PRIVKEY }}" > $OMR_TARGET/source/key-build - #echo -e "${{ secrets.OMR_PUBKEY }}" > $OMR_TARGET/source/key-build.pub + #echo -e "${{ secrets.OMR_PRIVKEY }}" > $OMR_TARGET/$OMR_KERNEL/source/key-build + #echo -e "${{ secrets.OMR_PUBKEY }}" > $OMR_TARGET/$OMR_KERNEL/source/key-build.pub - name: Build packages working-directory: ../../omr env: OMR_TARGET: ${{ matrix.OMR_TARGET }} + OMR_KERNEL: ${{ matrix.OMR_KERNEL }} run: | - make IGNORE_ERRORS=m -C $OMR_TARGET/source package/{compile,install,index} -j$(nproc) || make IGNORE_ERRORS=m -C $OMR_TARGET/source package/{compile,install,index} -j1 V=s + make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source package/{compile,install,index} -j$(nproc) || make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source package/{compile,install,index} -j1 V=s - name: Build image working-directory: ../../omr env: OMR_TARGET: ${{ matrix.OMR_TARGET }} + OMR_KERNEL: ${{ matrix.OMR_KERNEL }} run: | - make IGNORE_ERRORS=m -C $OMR_TARGET/source target/install -j$(nproc) || make IGNORE_ERRORS=m -C $OMR_TARGET/source target/install -j1 V=s + make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source target/install -j$(nproc) || make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source target/install -j1 V=s - name: Upload artifacts uses: actions/upload-artifact@v2 with: @@ -119,9 +121,10 @@ jobs: working-directory: ../../omr env: OMR_TARGET: ${{ matrix.OMR_TARGET }} + OMR_KERNEL: ${{ matrix.OMR_KERNEL }} GITHUB_WORKSPACE: ${{ steps.branch_name.outputs.WORKSPACE }} run: | - mv ${OMR_TARGET}/source/bin ${GITHUB_WORKSPACE}/ + mv ${OMR_TARGET}/${OMR_KERNEL}/source/bin ${GITHUB_WORKSPACE}/ - if: steps.branch_name.outputs.SOURCE_BRANCH == '' name: Deploy - Upload via rsync uses: ysurac/action-rsync@master From bf1c4154d040ef3b4f481295c8dcdbb0a911bde1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 1 Jun 2022 20:44:52 +0200 Subject: [PATCH 0759/2059] Fix Github actions --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c43ccaa45..8ec59e8da 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,7 +131,7 @@ jobs: env: ARGS: -av --delete-after TARGET: deploy/release/${{steps.branch_name.outputs.SOURCE_TAG}}/${{matrix.OMR_TARGET}} - SOURCE: ./bin/ + SOURCE: ./${{matrix.OMR_KERNEL}}/bin/ KEY: ${{ secrets.PRIVATE_KEY }} USER: deploy HOST: ${{ secrets.OMR_DEPLOY_HOST }} @@ -146,7 +146,7 @@ jobs: env: ARGS: -av --delete-after TARGET: deploy/${{ steps.branch_name.outputs.SOURCE_BRANCH }}/${{matrix.OMR_KERNEL}}/${{matrix.OMR_TARGET}} - SOURCE: ./bin/ + SOURCE: ./${{matrix.OMR_KERNEL}}/bin/ KEY: ${{ secrets.PRIVATE_KEY }} USER: deploy HOST: ${{ secrets.OMR_DEPLOY_HOST }} From 3419876fd597270542473dd9acba658e80cd066f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Jun 2022 15:52:43 +0200 Subject: [PATCH 0760/2059] Fix server failover --- omr-tracker/files/bin/omr-tracker-server | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 428a2d1a8..e3a376c28 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -98,16 +98,20 @@ _check_master() { /etc/init.d/openvpn restart >/dev/null 2>/dev/null /etc/init.d/dsvpn restart >/dev/null 2>/dev/null fi + else + logger -t "OMR-Tracker-Server" "Master server already up" fi config_load shadowsocks-libev config_foreach _enable_redir ss_redir count=$((count+1)) else + logger -t "OMR-Tracker-Server" "Master server down" config_load shadowsocks-libev config_foreach _disable_redir ss_redir fi countips=$((countips+1)) } + config_load openmptcprouter config_list_foreach $1 ip set_ip #if [ "$server_ping" = true ] && [ "$countips" = "1" ]; then # uci -q batch <<-EOF >/dev/null @@ -176,6 +180,7 @@ _check_backup() { fi countips=$((countips+1)) } + config_load openmptcprouter config_list_foreach $1 ip set_ip #if [ "$server_ping" = true ] && [ "$countips" = "1" ]; then # uci -q batch <<-EOF >/dev/null @@ -202,6 +207,7 @@ while true; do config_load openmptcprouter config_foreach _check_master server [ "$server_ping" = false ] && { + config_load openmptcprouter config_foreach _check_backup server } sleep "${interval}" From bc14122b3ec98e13ff096df235abf13613db4bf2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Jun 2022 15:53:04 +0200 Subject: [PATCH 0761/2059] Fix QoS in wizard --- .../luasrc/controller/openmptcprouter.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index ec8eeb466..de061fae5 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -283,6 +283,7 @@ function wizard_add() local auth = luci.http.formvalue("cbid.network.%s.auth" % intf) or "" local mode = luci.http.formvalue("cbid.network.%s.mode" % intf) or "" local sqmenabled = luci.http.formvalue("cbid.sqm.%s.enabled" % intf) or "0" + local qosenabled = luci.http.formvalue("cbid.qos.%s.enabled" % intf) or "0" local multipath = luci.http.formvalue("cbid.network.%s.multipath" % intf) or "on" local lan = luci.http.formvalue("cbid.network.%s.lan" % intf) or "0" local ttl = luci.http.formvalue("cbid.network.%s.ttl" % intf) or "" @@ -463,9 +464,12 @@ function wizard_add() --ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress dual-dsthost") --ucic:set("sqm",intf,"eqdisc_opts","dual-srchost") ucic:set("sqm",intf,"enabled","1") - ucic:set("qos",intf,"enabled","1") else ucic:set("sqm",intf,"enabled","0") + end + if qosenabled == "1" then + ucic:set("qos",intf,"enabled","1") + else ucic:set("qos",intf,"enabled","0") end end From 3836f9a22591523a5b17e07b2b75838ea10d76aa Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Jun 2022 15:53:28 +0200 Subject: [PATCH 0762/2059] Fix server routes when multiples servers are defined --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 932c51155..1cfecffc7 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -478,6 +478,7 @@ set_server_all_routes() { fi fi } + config_load openmptcprouter config_list_foreach $server ip server_route } @@ -525,6 +526,7 @@ set_server_all_routes6() { fi fi } + config_load openmptcprouter config_list_foreach $server ip server_route } From c9ad59784e9401efa60be3a393bd2b3830b90622 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Jun 2022 15:54:17 +0200 Subject: [PATCH 0763/2059] Return latencies without endline --- omr-tracker/files/bin/omr-tracker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 00a6274f4..fe21c7473 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -153,7 +153,7 @@ _ping() { "${host}" 2>&1 ) && echo "$ret" | grep -sq "bytes from" && { if [ "$localip" = "yes" ]; then - OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1) + OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') _update_rto "$OMR_TRACKER_LATENCY" fi return @@ -166,7 +166,7 @@ _ping() { "${host}" 2>&1 ) && echo "$ret" | grep -sq "bytes from" && { if [ "$localip" = "yes" ]; then - OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1) + OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') _update_rto "$OMR_TRACKER_LATENCY" fi return From ab417428f92f7265638593becf59d7a4b1d9e2dc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Jun 2022 16:35:59 +0200 Subject: [PATCH 0764/2059] Update github actions --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8ec59e8da..2ca1b3894 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,7 +86,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: ${{ matrix.OMR_TARGET }} - path: /home/runner/work/omr/${{ matrix.OMR_TARGET }}/source/bin + path: /home/runner/work/omr/${{ matrix.OMR_TARGET }}/${{ matrix.OMR_KERNEL }}/source/bin - if: steps.branch_name.outputs.SOURCE_BRANCH == '' name: Deploy - Create directory uses: ysurac/ssh-action@master From 990790e6c8faaf96dc2a3a089e9810727810869d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Jun 2022 19:10:56 +0200 Subject: [PATCH 0765/2059] Fix server failover for glorytun udp --- omr-tracker/files/bin/omr-tracker-server | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index e3a376c28..d9ffbd1e9 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -82,6 +82,8 @@ _check_master() { commit v2ray set glorytun.vpn.host=$ip commit glorytun + glorytun-udp.vpn.host=$ip + commit glorytun set dsvpn.vpn.host=$ip commit dsvpn set mlvpn.general.host=$ip @@ -153,6 +155,8 @@ _check_backup() { commit v2ray set glorytun.vpn.host=$ip commit glorytun + glorytun-udp.vpn.host=$ip + commit glorytun set dsvpn.vpn.host=$ip commit dsvpn set mlvpn.general.host=$ip From 9dc249d7c5c0d206c3bcce0802e3b15d9915f70e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Jun 2022 19:11:11 +0200 Subject: [PATCH 0766/2059] Fix Github actions --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ca1b3894..4ab1b4b77 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,7 +131,7 @@ jobs: env: ARGS: -av --delete-after TARGET: deploy/release/${{steps.branch_name.outputs.SOURCE_TAG}}/${{matrix.OMR_TARGET}} - SOURCE: ./${{matrix.OMR_KERNEL}}/bin/ + SOURCE: ./bin/ KEY: ${{ secrets.PRIVATE_KEY }} USER: deploy HOST: ${{ secrets.OMR_DEPLOY_HOST }} @@ -146,7 +146,7 @@ jobs: env: ARGS: -av --delete-after TARGET: deploy/${{ steps.branch_name.outputs.SOURCE_BRANCH }}/${{matrix.OMR_KERNEL}}/${{matrix.OMR_TARGET}} - SOURCE: ./${{matrix.OMR_KERNEL}}/bin/ + SOURCE: ./bin/ KEY: ${{ secrets.PRIVATE_KEY }} USER: deploy HOST: ${{ secrets.OMR_DEPLOY_HOST }} From 0ddda315d09c3886078eba739dec2110bcb8113e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 3 Jun 2022 20:44:35 +0200 Subject: [PATCH 0767/2059] Fix omr tracker server log --- omr-tracker/files/bin/omr-tracker-server | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index d9ffbd1e9..662eabcc5 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -100,14 +100,12 @@ _check_master() { /etc/init.d/openvpn restart >/dev/null 2>/dev/null /etc/init.d/dsvpn restart >/dev/null 2>/dev/null fi - else - logger -t "OMR-Tracker-Server" "Master server already up" fi config_load shadowsocks-libev config_foreach _enable_redir ss_redir count=$((count+1)) else - logger -t "OMR-Tracker-Server" "Master server down" + logger -t "OMR-Tracker-Server" "Master server ${name} down ($ip)" config_load shadowsocks-libev config_foreach _disable_redir ss_redir fi From c4157bfc0ff1adad419a91e659cc0e3bd5ece561 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 3 Jun 2022 20:45:19 +0200 Subject: [PATCH 0768/2059] Modify openmptcprouter mini --- openmptcprouter-mini/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter-mini/Makefile b/openmptcprouter-mini/Makefile index 96a01ac3a..c1a1b91ab 100644 --- a/openmptcprouter-mini/Makefile +++ b/openmptcprouter-mini/Makefile @@ -28,7 +28,7 @@ MY_DEPENDS := \ iperf3-ssl luci-app-iperf \ arptables \ bind-dig \ - libnetfilter-conntrack ebtables ebtables-utils ip-full \ + libnetfilter-conntrack ip-full \ iptables-mod-iface iptables-mod-ipmark iptables-mod-hashlimit iptables-mod-condition iptables-mod-trace iptables-mod-conntrack-extra iptables-mod-account \ kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra \ iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 kmod-ipt-ipsec \ @@ -74,7 +74,7 @@ MY_DEPENDS := \ !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 \ - luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang iptables-mod-ipopt ss \ + luci-app-mlvpn mlvpn 464xlat kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang iptables-mod-ipopt ss \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre OMR_SUPPORTED_LANGS := en From b8c865872058358ffdef28cc51b6251167cec6cb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 16 Jun 2022 19:28:25 +0200 Subject: [PATCH 0769/2059] Add Cake Autorate --- .../luasrc/controller/openmptcprouter.lua | 23 +- .../luasrc/view/openmptcprouter/wizard.htm | 27 +- luci-app-sqm-autorate/Makefile | 16 + .../luci-static/resources/view/network/sqm.js | 294 +++++++++ luci-app-sqm-autorate/po/ar/sqm.po | 211 ++++++ luci-app-sqm-autorate/po/bg/sqm.po | 219 +++++++ luci-app-sqm-autorate/po/bn_BD/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/ca/sqm.po | 202 ++++++ luci-app-sqm-autorate/po/cs/sqm.po | 210 ++++++ luci-app-sqm-autorate/po/da/sqm.po | 248 +++++++ luci-app-sqm-autorate/po/de/sqm.po | 255 ++++++++ luci-app-sqm-autorate/po/el/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/en/sqm.po | 202 ++++++ luci-app-sqm-autorate/po/es/sqm.po | 250 +++++++ luci-app-sqm-autorate/po/fi/sqm.po | 216 +++++++ luci-app-sqm-autorate/po/fr/sqm.po | 247 +++++++ luci-app-sqm-autorate/po/he/sqm.po | 202 ++++++ luci-app-sqm-autorate/po/hi/sqm.po | 202 ++++++ luci-app-sqm-autorate/po/hu/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/it/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/ja/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/ko/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/mr/sqm.po | 202 ++++++ luci-app-sqm-autorate/po/ms/sqm.po | 202 ++++++ luci-app-sqm-autorate/po/nb_NO/sqm.po | 202 ++++++ luci-app-sqm-autorate/po/pl/sqm.po | 253 ++++++++ luci-app-sqm-autorate/po/pt/sqm.po | 256 ++++++++ luci-app-sqm-autorate/po/pt_BR/sqm.po | 258 ++++++++ luci-app-sqm-autorate/po/ro/sqm.po | 257 ++++++++ luci-app-sqm-autorate/po/ru/sqm.po | 222 +++++++ luci-app-sqm-autorate/po/sk/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/sv/sqm.po | 216 +++++++ luci-app-sqm-autorate/po/templates/sqm.pot | 199 ++++++ luci-app-sqm-autorate/po/tr/sqm.po | 244 +++++++ luci-app-sqm-autorate/po/uk/sqm.po | 209 ++++++ luci-app-sqm-autorate/po/vi/sqm.po | 208 ++++++ luci-app-sqm-autorate/po/zh_Hans/sqm.po | 217 +++++++ luci-app-sqm-autorate/po/zh_Hant/sqm.po | 218 +++++++ .../root/etc/init.d/sqm-autorate | 39 ++ .../root/etc/uci-defaults/50-luci-sqm | 12 + .../usr/share/luci/menu.d/luci-app-sqm.json | 13 + .../usr/share/rpcd/acl.d/luci-app-sqm.json | 23 + .../usr/share/sqm-autorate/CAKE-autorate.sh | 608 ++++++++++++++++++ .../root/usr/share/sqm-autorate/config.sh | 158 +++++ 44 files changed, 8689 insertions(+), 7 deletions(-) create mode 100644 luci-app-sqm-autorate/Makefile create mode 100644 luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js create mode 100644 luci-app-sqm-autorate/po/ar/sqm.po create mode 100644 luci-app-sqm-autorate/po/bg/sqm.po create mode 100644 luci-app-sqm-autorate/po/bn_BD/sqm.po create mode 100644 luci-app-sqm-autorate/po/ca/sqm.po create mode 100644 luci-app-sqm-autorate/po/cs/sqm.po create mode 100644 luci-app-sqm-autorate/po/da/sqm.po create mode 100644 luci-app-sqm-autorate/po/de/sqm.po create mode 100644 luci-app-sqm-autorate/po/el/sqm.po create mode 100644 luci-app-sqm-autorate/po/en/sqm.po create mode 100644 luci-app-sqm-autorate/po/es/sqm.po create mode 100644 luci-app-sqm-autorate/po/fi/sqm.po create mode 100644 luci-app-sqm-autorate/po/fr/sqm.po create mode 100644 luci-app-sqm-autorate/po/he/sqm.po create mode 100644 luci-app-sqm-autorate/po/hi/sqm.po create mode 100644 luci-app-sqm-autorate/po/hu/sqm.po create mode 100644 luci-app-sqm-autorate/po/it/sqm.po create mode 100644 luci-app-sqm-autorate/po/ja/sqm.po create mode 100644 luci-app-sqm-autorate/po/ko/sqm.po create mode 100644 luci-app-sqm-autorate/po/mr/sqm.po create mode 100644 luci-app-sqm-autorate/po/ms/sqm.po create mode 100644 luci-app-sqm-autorate/po/nb_NO/sqm.po create mode 100644 luci-app-sqm-autorate/po/pl/sqm.po create mode 100644 luci-app-sqm-autorate/po/pt/sqm.po create mode 100644 luci-app-sqm-autorate/po/pt_BR/sqm.po create mode 100644 luci-app-sqm-autorate/po/ro/sqm.po create mode 100644 luci-app-sqm-autorate/po/ru/sqm.po create mode 100644 luci-app-sqm-autorate/po/sk/sqm.po create mode 100644 luci-app-sqm-autorate/po/sv/sqm.po create mode 100644 luci-app-sqm-autorate/po/templates/sqm.pot create mode 100644 luci-app-sqm-autorate/po/tr/sqm.po create mode 100644 luci-app-sqm-autorate/po/uk/sqm.po create mode 100644 luci-app-sqm-autorate/po/vi/sqm.po create mode 100644 luci-app-sqm-autorate/po/zh_Hans/sqm.po create mode 100644 luci-app-sqm-autorate/po/zh_Hant/sqm.po create mode 100755 luci-app-sqm-autorate/root/etc/init.d/sqm-autorate create mode 100755 luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm create mode 100644 luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json create mode 100644 luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json create mode 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh create mode 100644 luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index de061fae5..74a638186 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -283,6 +283,7 @@ function wizard_add() local auth = luci.http.formvalue("cbid.network.%s.auth" % intf) or "" local mode = luci.http.formvalue("cbid.network.%s.mode" % intf) or "" local sqmenabled = luci.http.formvalue("cbid.sqm.%s.enabled" % intf) or "0" + local sqmautorate = luci.http.formvalue("cbid.sqm.%s.autorate" % intf) or "0" local qosenabled = luci.http.formvalue("cbid.qos.%s.enabled" % intf) or "0" local multipath = luci.http.formvalue("cbid.network.%s.multipath" % intf) or "on" local lan = luci.http.formvalue("cbid.network.%s.lan" % intf) or "0" @@ -439,10 +440,21 @@ function wizard_add() --ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress dual-dsthost") --ucic:set("sqm",intf,"eqdisc_opts","dual-srchost") end + ucic:set("sqm",intf,"autorate",sqmautorate) + if sqmautorate == "1" then + ucic:set("sqm",intf,"qdisc","cake") + ucic:set("sqm",intf,"script","piece_of_cake.qos") + end if downloadspeed ~= "0" and downloadspeed ~= "" then + if sqmautorate == "1" and (ucic:get("network",intf,"downloadspeed") ~= downloadspeed or ucic:get("sqm",intf,"max_download") == "" or ucic:get("sqm",intf,"download") == "0") then + ucic:set("sqm",intf,"download",math.ceil(downloadspeed*65/100)) + ucic:set("sqm",intf,"min_download",math.ceil(downloadspeed*10/100)) + ucic:set("sqm",intf,"max_download",downloadspeed) + elseif sqmautorate ~= "1" then + ucic:set("sqm",intf,"download",math.ceil(downloadspeed*95/100)) + end ucic:set("network",intf,"downloadspeed",downloadspeed) - ucic:set("sqm",intf,"download",math.ceil(downloadspeed*95/100)) ucic:set("qos",intf,"download",math.ceil(downloadspeed*95/100)) else ucic:delete("network",intf,"downloadspeed") @@ -450,8 +462,14 @@ function wizard_add() ucic:set("qos",intf,"download","0") end if uploadspeed ~= "0" and uploadspeed ~= "" then + if sqmautorate == "1" and (ucic:get("network",intf,"uploadspeed") ~= uploadspeed or ucic:get("sqm",intf,"max_upload") == "" or ucic:get("sqm",intf,"upload") == "0") then + ucic:set("sqm",intf,"upload",math.ceil(uploadspeed*65/100)) + ucic:set("sqm",intf,"min_upload",math.ceil(uploadspeed*10/100)) + ucic:set("sqm",intf,"max_upload",uploadspeed) + elseif sqmautorate ~= "1" then + ucic:set("sqm",intf,"upload",math.ceil(uploadspeed*95/100)) + end ucic:set("network",intf,"uploadspeed",uploadspeed) - ucic:set("sqm",intf,"upload",math.ceil(uploadspeed*95/100)) ucic:set("qos",intf,"upload",math.ceil(uploadspeed*95/100)) else ucic:delete("network",intf,"uploadspeed") @@ -998,6 +1016,7 @@ function wizard_add() luci.sys.call("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/vnstat restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/v2ray restart >/dev/null 2>/dev/null") + luci.sys.call("/etc/init.d/sqm-autorate restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/sysntpd restart >/dev/null 2>/dev/null") luci.http.redirect(luci.dispatcher.build_url("admin/system/" .. menuentry:lower() .. "/status")) else diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index f86b61ce7..58a08e11b 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -914,6 +914,7 @@ local upload = "0" download = uci:get("network",ifname,"downloadspeed") or "0" upload = uci:get("network",ifname,"uploadspeed") or "0" + cake = uci:get("sqm",ifname,"qdisc") or "cake" --if download == "0" or upload == "0" then -- if nixio.fs.access("/etc/init.d/sqm") then -- download = uci:get("sqm",ifname,"download") @@ -940,11 +941,27 @@
    - checked<% end %> /> + checked<% end %> />
    <%:SQM control bufferloat: the undesirable latency that arises when the router buffers too much data.%> - <%:You should disable SQM for LTE or any interfaces with variable speed.%> +
    +
    +
    +
    + +
    + checked<% end %> /> +
    +
    + <%:SQM autorate is for LTE and connection without a stable speed.%> + <% + if cake ~= "cake" then + %> + <%:Cake queue discipline is not set, autorate will only work after a reboot if enabled here.%> + <% + end + %>
    @@ -954,7 +971,7 @@ <% if qos == "1" then %> -
    +
    checked<% end %> /> @@ -967,7 +984,7 @@ <% end %> -
    +
    @@ -983,7 +1000,7 @@ -->
    -
    +
    diff --git a/luci-app-sqm-autorate/Makefile b/luci-app-sqm-autorate/Makefile new file mode 100644 index 000000000..df160a3e5 --- /dev/null +++ b/luci-app-sqm-autorate/Makefile @@ -0,0 +1,16 @@ +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI Support for SQM Scripts with autorate +LUCI_DESCRIPTION:=Luci interface for the SQM scripts queue management package with SQM autorate + +PKG_MAINTAINER:=Toke Høiland-Jørgensen + +LUCI_DEPENDS:=+sqm-scripts +bash +LUCI_PKGARCH:=all + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js new file mode 100644 index 000000000..c7f33a8b8 --- /dev/null +++ b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js @@ -0,0 +1,294 @@ +'use strict'; +'require fs'; +'require ui'; +'require rpc'; +'require uci'; +'require view'; +'require form'; +'require tools.widgets as widgets'; + +return view.extend({ + handleGetHelpText: function(script_name, tbl) { + return fs.read("/usr/lib/sqm/" + script_name + ".help").then(function (text) { + if (text) + return [script_name, text]; + }); + }, + + handleEnableSQM: rpc.declare({ + object: 'luci', + method: 'setInitAction', + params: [ 'sqm', 'enable' ], + expect: { result: false } + }), + + load: function() { + return Promise.all([ + L.resolveDefault(fs.list('/var/run/sqm/available_qdiscs'), []), + L.resolveDefault(fs.list('/usr/lib/sqm'), []).then(L.bind(function(scripts) { + var tasks = [], scriptHelpTbl = {}; + + for (var i = 0; i < scripts.length; i++) + if (scripts[i].name.search(/\.qos$/) != -1) + tasks.push(L.resolveDefault(this.handleGetHelpText(scripts[i].name, scriptHelpTbl), [scripts[i].name, null])); + + return Promise.all(tasks); + }, this)), + uci.load('sqm') + ]); + }, + + render: function(data) { + var qdiscs = data[0], + scripts = data[1]; + + if (qdiscs.length === 0) { + ui.addNotification(null, + E('div', { 'class': 'left' }, [ + E('p', _("The SQM service seems to be disabled. Please use the button below to activate this service.")), + E('button', { + 'class': 'btn cbi-button-active', + 'click': ui.createHandlerFn(this, function() { + return fs.exec('/etc/init.d/sqm', ['enable']).then(function() { + return fs.exec('/etc/init.d/sqm', ['start']); + }).then(function() { + location.reload(); + }); + }) + }, _('Enable SQM')) + ])); + } + + var m, s, o; + + m = new form.Map('sqm', _('Smart Queue Management')); + m.description = _("With SQM you " + + "can enable traffic shaping, better mixing (Fair Queueing)," + + " active queue length management (AQM) " + + " and prioritisation on one " + + "network interface."); + + s = m.section(form.TypedSection, 'queue', _('Queues')); + s.tab("tab_basic", _("Basic Settings")); + s.tab("tab_qdisc", _("Queue Discipline")); + s.tab("tab_linklayer", _("Link Layer Adaptation")); + s.tab("tab_autorate", _("Autorate settings")); + s.anonymous = true; + s.addremove = true; + + o = s.taboption("tab_basic", form.Flag, "enabled", _("Enable this SQM instance.")); + o.rmempty = false; + o.write = L.bind(function(section, value) { + if (value == "1") { + this.handleEnableSQM(); + ui.addNotification(null, E('p', _("The SQM GUI has just enabled the sqm initscript on your behalf. Remember to disable the sqm initscript manually under System Startup menu in case this change was not wished for."))); + } + + return uci.set("sqm", section, "enabled", value); + }, this); + + o = s.taboption("tab_basic", form.Flag, "autorate", _("Enable SQM autorate")); + o.rmempty = false; + + o = s.taboption("tab_basic", widgets.DeviceSelect, "interface", _("Interface name")); + o.rmempty = false; + + o = s.taboption("tab_basic", form.Value, "download", _("Base download speed (kbit/s) (ingress):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + + o = s.taboption("tab_basic", form.Value, "min_download", _("Minimum download speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Value, "max_download", _("Maximum download speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Value, "upload", _("Base upload speed (kbit/s) (egress):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + + o = s.taboption("tab_basic", form.Value, "min_upload", _("Minimum upload speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Value, "max_upload", _("Maximum upload speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Flag, "debug_logging", _("Create log file for this SQM instance under /var/run/sqm/${Interface_name}.[start|stop]-sqm.log.")); + o.rmempty = false; + + o = s.taboption("tab_basic", form.ListValue, "verbosity", _("Verbosity of SQM's output into the system log.")); + o.value("0", "silent"); + o.value("1", "error"); + o.value("2", "warning"); + o.value("5", "info ("+_("default")+")"); + o.value("8", "debug"); + o.value("10", "trace"); + o.default = "5"; + + o = s.taboption("tab_qdisc", form.ListValue, "qdisc", _("Queuing disciplines useable on this system. After installing a new qdisc, you need to restart the router to see updates!"),_("Must be set to cake if autorate is used.")); + for (var i=0; i < qdiscs.length; i++) { + o.value(qdiscs[i].name); + } + o.default = "cake"; + o.rmempty = false; + + var qos_desc = ""; + o = s.taboption("tab_qdisc", form.ListValue, "script", _("Queue setup script")); + for (i = 0; i < scripts.length; i++) { + o.value(scripts[i][0]); + qos_desc += "

    " + scripts[i][0] + ":
    "; + if (scripts[i][1]) + qos_desc += scripts[i][1] + "

    "; + else + qos_desc += "No help text

    "; + } + o.default = "piece_of_cake.qos"; + o.rmempty = false; + o.description = qos_desc; + + o = s.taboption("tab_qdisc", form.Flag, "qdisc_advanced", _("Show and Use Advanced Configuration. Advanced options will only be used as long as this box is checked.")); + o.default = false; + + o = s.taboption("tab_qdisc", form.ListValue, "squash_dscp", _("Squash DSCP on inbound packets (ingress):")); + o.value("1", "SQUASH"); + o.value("0", "DO NOT SQUASH"); + o.default = "1"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.ListValue, "squash_ingress", _("Ignore DSCP on ingress:")); + o.value("1", "Ignore"); + o.value("0", "Allow"); + o.default = "1"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.ListValue, "ingress_ecn", _("Explicit congestion notification (ECN) status on inbound packets (ingress):")); + o.value("ECN", "ECN (" + _("default") + ")"); + o.value("NOECN"); + o.default = "ECN"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.ListValue, "egress_ecn", _("Explicit congestion notification (ECN) status on outbound packets (egress).")); + o.value("NOECN", "NOECN (" + _("default") + ")"); + o.value("ECN"); + o.default = "NOECN"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Flag, "qdisc_really_really_advanced", _("Show and Use Dangerous Configuration. Dangerous options will only be used as long as this box is checked.")); + o.default = false + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "ilimit", _("Hard limit on ingress queues; leave empty for default.")); + o.datatype = "and(uinteger,min(0))"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "elimit", _("Hard limit on egress queues; leave empty for default.")); + o.datatype = "and(uinteger,min(0))"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "itarget", _("Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for automatic selection, put in the word default for the qdisc's default.")); + o.datatype = "string"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "etarget", _("Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for automatic selection, put in the word default for the qdisc's default.")); + o.datatype = "string"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "iqdisc_opts", _("Advanced option string to pass to the ingress queueing disciplines; no error checking, use very carefully.")); + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "eqdisc_opts", _("Advanced option string to pass to the egress queueing disciplines; no error checking, use very carefully.")); + o.depends("qdisc_really_really_advanced", "1"); + + // LINKLAYER + o = s.taboption("tab_linklayer", form.ListValue, "linklayer", _("Which link layer to account for:")); + o.value("none", "none (" + _("default") + ")"); + o.value("ethernet", "Ethernet with overhead: select for e.g. VDSL2."); + o.value("atm", "ATM: select for e.g. ADSL1, ADSL2, ADSL2+."); + o.default = "none"; + + o = s.taboption("tab_linklayer", form.Value, "overhead", _("Per Packet Overhead (byte):")); + o.datatype = "and(integer,min(-1500))"; + o.default = 0 + o.depends("linklayer", "ethernet"); + o.depends("linklayer", "atm"); + + o = s.taboption("tab_linklayer", form.Flag, "linklayer_advanced", _("Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced options will only be used as long as this box is checked.")); + o.depends("linklayer", "ethernet"); + o.depends("linklayer", "atm"); + + o = s.taboption("tab_linklayer", form.Value, "tcMTU", _("Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= interface MTU + overhead:")); + o.datatype = "and(uinteger,min(0))"; + o.default = 2047 + o.depends("linklayer_advanced", "1"); + + o = s.taboption("tab_linklayer", form.Value, "tcTSIZE", _("Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU + 1) / 16:")); + o.datatype = "and(uinteger,min(0))"; + o.default = 128 + o.depends("linklayer_advanced", "1"); + + o = s.taboption("tab_linklayer", form.Value, "tcMPU", _("Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:")); + o.datatype = "and(uinteger,min(0))"; + o.default = 0 + o.depends("linklayer_advanced", "1"); + + o = s.taboption("tab_linklayer", form.ListValue, "linklayer_adaptation_mechanism", _("Which linklayer adaptation mechanism to use; for testing only")); + o.value("default", "default (" + _("default") + ")"); + o.value("cake"); + o.value("htb_private"); + o.value("tc_stab"); + o.default = "default"; + o.depends("linklayer_advanced", "1"); + + // Autorate + o = s.taboption("tab_autorate", form.Flag, "output_processing_stats", _("Output monitoring lines showing processing stats")); + o.default = false; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Flag, "output_cake_changes", _("Output monitoring lines showing cake bandwidth changes")); + o.default = false; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Flag, "debug", _("Debug")); + o.default = false; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "reflector_ping_interval_s", _("Reflector ping interval in seconds:")); + o.default = "0.2"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "no_pingers", _("Pingers numbers:")); + o.default = "4"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "delay_thr_ms",_("delay threshold in ms:")); + o.default = "25"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Flag, "enable_sleep_function", _("Sleep functionnality")); + o.default = true; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "connection_active_thr_kbps",_("Threshold in Kbit/s below which dl/ul is considered idle")); + o.default = "500"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "substained_idle_sleep_thr_s",_("Time threshold to put pingers to sleep on substained dl/ul achieved rate < idle_threshold")); + o.default = "60"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "startup_wait_s",_("Number of seconds to wait on startup:")); + o.default = "60"; + o.depends("autorate","1"); + + + return m.render(); + } +}) diff --git a/luci-app-sqm-autorate/po/ar/sqm.po b/luci-app-sqm-autorate/po/ar/sqm.po new file mode 100644 index 000000000..48447fae9 --- /dev/null +++ b/luci-app-sqm-autorate/po/ar/sqm.po @@ -0,0 +1,211 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-03-07 14:36+0000\n" +"Last-Translator: Said Zakaria \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" +"X-Generator: Weblate 4.5.1\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"سلسلة خيارات متقدمة لتمريرها إلى تخصصات الخروج قائمة انتظار; لا يوجد خطأ " +"التحقق، واستخدام بعناية فائقة." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "الإعدادات الأساسية" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "اسم الواجهة" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/bg/sqm.po b/luci-app-sqm-autorate/po/bg/sqm.po new file mode 100644 index 000000000..4763b4aa3 --- /dev/null +++ b/luci-app-sqm-autorate/po/bg/sqm.po @@ -0,0 +1,219 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-09-27 22:36+0000\n" +"Last-Translator: Iskren Mihaylov \n" +"Language-Team: Bulgarian \n" +"Language: bg\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.9-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Основни настройки" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Създаване на журнален файл за тази инстанция на SQM под /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +#, fuzzy +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Скорост на изтегляне (kbit/s) (входящ) зададена на 0, деактивира оформянето " +"на входящия трафик:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Активиране на SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Активиране на тази SQM инстанция." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Предоставяне на достъп на UCI за luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Твърд лимит на изходните опашки; оставете празно по подразбиране." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Твърд лимит на входящите опашки; оставете празно по подразбиране." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Игнориране на DSCP за входящ:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Име на интерфейса" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Целева латентност за изходящ трафик, напр. 5ms [единици: s, ms или us]; " +"оставете празно за автоматичен избор, поставете думата default за използване " +"стойности по подразбиране на qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Целева латентност за входящ трафик, например 5ms [единици: s, ms или us]; " +"оставете празно за автоматичен избор, поставете думата default за стойности " +"по подразбиране на qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/bn_BD/sqm.po b/luci-app-sqm-autorate/po/bn_BD/sqm.po new file mode 100644 index 000000000..81e5f56c2 --- /dev/null +++ b/luci-app-sqm-autorate/po/bn_BD/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-10 19:29+0000\n" +"Last-Translator: Debashish Das \n" +"Language-Team: Bengali (Bangladesh) \n" +"Language: bn_BD\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.4-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "সাধারন সেটিংস" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/ca/sqm.po b/luci-app-sqm-autorate/po/ca/sqm.po new file mode 100644 index 000000000..bab2a9f42 --- /dev/null +++ b/luci-app-sqm-autorate/po/ca/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: ca\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/cs/sqm.po b/luci-app-sqm-autorate/po/cs/sqm.po new file mode 100644 index 000000000..53293384b --- /dev/null +++ b/luci-app-sqm-autorate/po/cs/sqm.po @@ -0,0 +1,210 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-05-07 11:32+0000\n" +"Last-Translator: Adam Salač \n" +"Language-Team: Czech \n" +"Language: cs\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Weblate 4.7-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Řetězec rozšířených možností pro předání do frontových disciplín; bez " +"kontroly chyb, používejte s opatrností." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Základní nastavení" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/da/sqm.po b/luci-app-sqm-autorate/po/da/sqm.po new file mode 100644 index 000000000..66b4f784a --- /dev/null +++ b/luci-app-sqm-autorate/po/da/sqm.po @@ -0,0 +1,248 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-11-11 19:12+0000\n" +"Last-Translator: drax red \n" +"Language-Team: Danish \n" +"Language: da\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.9.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avanceret indstillingsstreng, der skal sendes til egress-kø-disciplinerne; " +"ingen fejlkontrol, brug den med stor forsigtighed." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avanceret indstillingsstreng, der skal overføres til de indgående " +"kø-discipliner; ingen fejlkontrol, brug den med stor forsigtighed." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Grundlæggende indstillinger" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Opret logfil for denne SQM-instans under /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Downloadhastighed (kbit/s) (ingress) indstilles til 0 for selektivt at " +"deaktivere indgangsformning:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Aktiver SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Aktiver denne SQM-instans." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"ECN-status (Explicit congestion notification) for indgående pakker (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"ECN-status (Explicit congestion notification) på udgående pakker (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Giv UCI-adgang til luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Hård grænse for egress køer; lad den være tom som standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Hård grænse for ingress køer; lad den være tom som standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignorer DSCP ved ingress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Interface navn" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latency-mål for egress, f.eks. 5ms [enheder: s, ms eller os]; lad det være " +"tomt for automatisk valg, indsæt ordet standard for qdisc'ens standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latency-mål for ingress, f.eks. 5ms [enheder: s, ms eller os]; lad det være " +"tomt for automatisk valg, indsæt ordet standard for qdisc'ens standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Tilpasning af linklag" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Maksimal størrelse til beregning af størrelse og hastighed, tcMTU (byte); " +"skal være >= MTU for grænsefladen + overhead:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimal pakkestørrelse, MPU (byte); skal være > 0 for ethernet-" +"størrelsestabeller:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Antal poster i størrelses-/taksttabeller, TSIZE; for ATM skal du vælge TSIZE " +"= (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Overhead pr. pakke (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Kø Disciplin" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Køopsætningsscript" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Køer" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Kø-discipliner, der kan bruges på dette system. Når du har installeret en ny " +"qdisc, skal du genstarte routeren for at se opdateringer!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Vis avancerede linklagsindstillinger (kun nødvendige, hvis MTU > 1500). " +"Avancerede indstillinger bruges kun, så længe dette afkrydsningsfelt er " +"markeret." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Vis og brug avanceret konfiguration. Avancerede indstillinger vil kun blive " +"brugt, så længe dette felt er markeret." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Vis og brug farlig konfiguration. Farlige indstillinger anvendes kun, så " +"længe dette felt er markeret." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Smart køstyring" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Squash DSCP på indgående pakker (indgang):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"SQM GUI har netop aktiveret sqm initscript på dine vegne. Husk at deaktivere " +"sqm initscript manuelt under System Startup menuen, hvis denne ændring ikke " +"var ønsket." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"SQM-tjenesten ser ud til at være deaktiveret. Brug venligst knappen nedenfor " +"for at aktivere denne tjeneste." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Uploadhastighed (kbit/s) (egress) sat til 0 for selektivt at deaktivere " +"udgående formning:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosity af SQM's output i systemloggen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Hvilket forbindelseslag der skal tages hensyn til:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Hvilken forbindelseslag tilpasningsmekanisme der skal bruges; kun til test" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Med SQM kan du aktivere " +"trafikformning, bedre blanding (Fair Queueing), aktiv kølængdestyring (AQM) " +"og prioritering på én netværksgrænseflade." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Standard" diff --git a/luci-app-sqm-autorate/po/de/sqm.po b/luci-app-sqm-autorate/po/de/sqm.po new file mode 100644 index 000000000..e3cadb151 --- /dev/null +++ b/luci-app-sqm-autorate/po/de/sqm.po @@ -0,0 +1,255 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-04-26 22:07+0000\n" +"Last-Translator: ssantos \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Erweiterte Optionszeichenkette zur Übergabe an die ausgangsseitigen " +"Warteschlangendisziplinen; keine Fehlerprüfung, sehr vorsichtig verwenden." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Erweiterte Optionszeichenkette zur Übergabe an die in die Warteschlange " +"einsteigenden Disziplinen; keine Fehlerprüfung, sehr vorsichtig verwenden." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Grundlegende Einstellungen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Logdatei für diese SQM-Instanz unter /var/run/sqm/${Interface_name}.[start|" +"stop]-sqm.log erstellen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Download-Geschwindigkeit (kbit/s) (Ingress) auf 0 setzen, um Ingress-Shaping " +"selektiv zu deaktivieren:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "SQM aktivieren" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Diese SQM-Instanz aktivieren" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Explicit congestion notification (ECN) Status für eingehende Pakete " +"(ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Explicit congestion notification (ECN) Status für ausgehende Pakete (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "UCI-Zugriff für luci-app-sqm erlauben" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Harte Begrenzung der Ausgangswarteschlangen; Standardmäßig leer lassen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Harte Begrenzung der Eingangswarteschlangen; Standardmäßig leer lassen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "DSCP bei Paketeingang ignorieren:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Schnittstellenname" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latenzziel für Ausgangswarteschlange, z.B. 5ms [Einheit: s, ms oder us]; " +"Leer lassen für automatische Auswahl, das Wort 'default' eintragen für qdisc " +"Standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latenzziel für Eingangswarteschlange, z.B. 5ms [Einheit: s, ms oder us]; " +"Leer lassen für automatische Auswahl, das Wort 'default' eintragen für qdisc " +"Standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Anpassung der Verbindungsschicht" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Maximale Größe für Größen- und Ratenberechnungen, tcMTU (Byte); muss >= " +"Schnittstellen-MTU + Overhead sein:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimale Paketgröße, MPU (Byte); muss > 0 für Ethernet-Größentabellen sein:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Anzahl der Einträge in Größen/Raten-Tabellen, TSIZE; für ATM wählen Sie " +"TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Overhead pro Paket (Byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +#, fuzzy +msgid "Queue Discipline" +msgstr "Queue Discipline" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Skript zum Aufsetzen der Warteschlange" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Warteschlangen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Warteschlangenstrukturen die auf diesem System benutzbar sind. Der Router " +"muss nach der Installation einer neuen qdisc neu gestartet werden, um die " +"Änderungen sehen zu können." + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Erweiterte Verbindungsschicht-Optionen anzeigen, (nur erforderlich, wenn MTU " +"> 1500). Die erweiterten Optionen werden nur verwendet, solange dieses " +"Kästchen markiert ist." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Erweiterte Konfiguration anzeigen und verwenden. Die erweiterten Optionen " +"werden nur verwendet, wenn diese Option ausgewählt ist." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Gefährliche Einstellungen anzeigen und nutzen. Gefährliche Optionen werden " +"nur benutzt, solange diese Box ausgewählt ist." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Smart Queue Management" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +#, fuzzy +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Squash DSCP bei eingehenden Paketen (Ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"Die SQM-GUI hat soeben das sqm-Initskript in Ihrem Namen aktiviert. Denken " +"Sie daran, das sqm-Initscript manuell im Systemstartmenü zu deaktivieren, " +"falls diese Änderung nicht gewünscht wurde." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Der SQM-Dienst scheint deaktiviert zu sein. Bitte verwenden Sie die " +"Schaltfläche unten, um diesen Dienst zu aktivieren." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Upload-Geschwindigkeit (kbit/s) (egress) auf 0 setzen, um die egress " +"Paketflusskontrolle abzuschalten:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Festlegen, wie ausführlich SQM ins Systemlog schreiben soll" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Welche Verbindungsschicht zu berücksichtigen ist:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Welcher Verbindungsschicht-Anpassungsmechanismus verwendet werden soll; nur " +"zum Testen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Mit SQM können Sie Traffic " +"Shaping, besseres Mischen (Fair Queueing), aktives Queue Length Management " +"(AQM) und Priorisierung auf einer Netzwerkschnittstelle aktivieren." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Standardeinstellung" diff --git a/luci-app-sqm-autorate/po/el/sqm.po b/luci-app-sqm-autorate/po/el/sqm.po new file mode 100644 index 000000000..d165ea0d0 --- /dev/null +++ b/luci-app-sqm-autorate/po/el/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-06 14:38+0000\n" +"Last-Translator: Stefanos Batsios \n" +"Language-Team: Greek \n" +"Language: el\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.7-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Βασικές Ρυθμίσεις" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Χορήγηση δικαιώματος χρήσης του UCI από το luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Όνομα διεπαφής (Interface)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/en/sqm.po b/luci-app-sqm-autorate/po/en/sqm.po new file mode 100644 index 000000000..548b41e7d --- /dev/null +++ b/luci-app-sqm-autorate/po/en/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: en\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/es/sqm.po b/luci-app-sqm-autorate/po/es/sqm.po new file mode 100644 index 000000000..8ca3d0c57 --- /dev/null +++ b/luci-app-sqm-autorate/po/es/sqm.po @@ -0,0 +1,250 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-04-28 18:11+0000\n" +"Last-Translator: Franco Castillo \n" +"Language-Team: Spanish \n" +"Language: es\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadena de opciones avanzadas para pasar a las disciplinas de cola de salida; " +"sin verificación de errores, use con mucho cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadena de opciones avanzadas para pasar a las disciplinas de colas de " +"ingreso; sin verificación de errores, use con mucho cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Configuración básica" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Cree un archivo de registro para esta instancia de SQM en /var/run/sqm/" +"${Interface_name}.[start|stopfont>-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"La velocidad de descarga (kbit/s) (ingreso) se establece en 0 para " +"desactivar selectivamente la configuración de ingreso:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Activar SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Activar esta instancia de SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Estado de notificación explícita de congestión (ECN) en paquetes entrantes " +"(ingreso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Estado explícito de notificación de congestión (ECN) en paquetes salientes " +"(salida)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Conceder acceso UCI para luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Límite estricto en las colas de salida; dejar en blanco por defecto." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Límite estricto en las colas de ingreso; dejar en blanco por defecto." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignorar DSCP en ingreso:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nombre de interfaz" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Objetivo de latencia para la salida, p.e. 5ms [unidades: s, ms o us]; déjelo " +"en blanco para la selección automática, ingrese la palabra default para el " +"qdisc predeterminado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Objetivo de latencia para la entrada, p.e. 5 ms [unidades: s, ms o us]; " +"déjelo en blanco para la selección automática, ingrese la palabra default " +"para el qdisc predeterminado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptación de capa de enlace" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Tamaño máximo para cálculos de tamaño y velocidad, tcMTU (byte); necesita " +"ser >= interfaz MTU + gastos generales:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Tamaño de paquete mínimo, MPU (byte); debe ser > 0 para tablas de tamaño de " +"ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Número de entradas en tablas de tamaño/tasa, TSIZE; para ATM, elija TSIZE = " +"(tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Por paquete de arriba (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina de cola" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configuración de cola" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Colas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Disciplinas de colas utilizables en este sistema. Después de instalar un " +"nuevo qdisc, ¡debe reiniciar el enrutador para ver las actualizaciones!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "Gestión inteligente de colas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Mostrar opciones avanzadas de Linklayer (solo es necesario si MTU > 1500). " +"Las opciones avanzadas solo se utilizarán mientras esta casilla esté marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar y usar la Configuración avanzada. Las opciones avanzadas solo se " +"utilizarán mientras esta casilla esté marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar y usar la Configuración Peligrosa. Las opciones peligrosas sólo se " +"utilizarán mientras esté marcada esta casilla." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestión inteligente de colas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Aplastar DSCP en paquetes entrantes (ingreso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"La GUI de SQM acaba de activar el initscript de sqm en su nombre. Recuerde " +"desactivar el initscript de sqm manualmente en el menú Inicio del sistema en " +"caso de que no se desee este cambio." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"El servicio SQM parece estar desactivado. Utilice el botón de abajo para " +"activar este servicio." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Velocidad de carga (kbit/s) (salida) establecida en 0 para desactivar " +"selectivamente la configuración de salida:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosidad de la salida de SQM en el registro del sistema." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Qué capa de enlace debe tener en cuenta:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Qué mecanismo de adaptación de capa de enlace usar; solo para pruebas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Con SQM puede activar la " +"conformación del tráfico, una mejor mezcla (Fair Queuing), gestión activa de " +"la longitud de la cola (AQM) y priorización en una interfaz de red." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "predeterminado" diff --git a/luci-app-sqm-autorate/po/fi/sqm.po b/luci-app-sqm-autorate/po/fi/sqm.po new file mode 100644 index 000000000..d37903f76 --- /dev/null +++ b/luci-app-sqm-autorate/po/fi/sqm.po @@ -0,0 +1,216 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-06-30 13:42+0000\n" +"Last-Translator: Petri Asikainen \n" +"Language-Team: Finnish \n" +"Language: fi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.2-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Perusasetukset" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Luo lokitiedosto tälle SQM-esiintymälle: /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Latausnopeus (kbit/s) (ingress). Aseta arvoksi 0 ottaaksesi latausnopeuden " +"säädön pois päältä:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Ota tämä SQM-esiintymä käyttöön." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Salli pääsy SQM-asetuksiin" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Sivuuta DSCP saapuvalta liikenteeltä:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Sovittimen nimi" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Linkkikerroksen sopeuttaminen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Lisäkuorma pakettia kohti (tavu):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Jonomenetelmä (qdisc)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Jonomenetelmän asetustiedosto" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Jonot" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Käytettävissä olevat jonomenetelmät (qdisc). Uuden qdiscin asentamisen " +"jälkeen tiedot päivittyvät laitteen uudelleenkäynnistyksen yhteydessä." + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Älykäs jononhallinta" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Lähetysnopeus kilobitteinä sekunnissa (kbit/s). Aseta arvoksi 0 ottaaksesi " +"lähetysnopeuden säädön pois päältä:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "SQM tapahtumien lokiinkirjaamisen tarkkuus." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Mitä linkkerroksen sopeutumistapaa käytetään (vain testaamiseen)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "vakio" diff --git a/luci-app-sqm-autorate/po/fr/sqm.po b/luci-app-sqm-autorate/po/fr/sqm.po new file mode 100644 index 000000000..b4ae43d92 --- /dev/null +++ b/luci-app-sqm-autorate/po/fr/sqm.po @@ -0,0 +1,247 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-08 14:26+0000\n" +"Last-Translator: ButterflyOfFire \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.2-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Chaîne d'options avancées pour passer aux disciplines de file d'attente de " +"sortie ; pas de vérification d'erreur, à utiliser avec précaution." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Chaîne d'options avancées à passer aux disciplines de file d'attente " +"d'entrée ; pas de vérification d'erreur, à utiliser avec beaucoup de " +"précaution." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Paramètres de base" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Créer un fichier journal pour cette instance SQM sous /var/run/sqm/" +"${nom_interface}. [start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Vitesse de téléchargement (kbit/s) (ingress) réglée sur 0 pour désactiver " +"sélectivement la mise en forme de l'ingress :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Activez cette instance SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Statut de notification de congestion (ECN) sur les paquets entrants " +"(ingress) :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Statut de notification de congestion (ECN) sur les paquets sortant (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Autoriser l'accès UCI pour luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Limite des files d'attente pour la sortie ; laisser vide par défaut." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Limite des files d'attente entrée ; laisser vide par défaut." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignoré DSCP à l'entrée :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nom de l’interface" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cible de latence pour la sortie, par exemple 5ms [unités : s, ms ou us] ; " +"laisser vide pour la sélection automatique, mettre Default pour la valeur " +"par défaut du qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cible de latence d'entrée, par exemple 5ms [unités : s, ms ou us] ; laisser " +"vide pour la sélection automatique, mettre default pour la valeur par défaut " +"du qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptation de liaison" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Taille maximale pour les calculs de taille et de taux, tcMTU (byte) ; doit " +"être >= interface MTU + overhead :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Taille minimale des paquets, MPU (byte) ; doit être > 0 pour les tailes de " +"tables ethernet :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Nombre d'entrées de taille/debit tables, TSIZE ; for ATM choose TSIZE = " +"(tcMTU + 1) / 16 :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Overhead par Packet(byte) :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Queue Discipline" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de file d'attente" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Queues" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Les disciplines de file d'attente sur ce système. Après avoir installé un " +"nouveau qdisc, vous devez redémarrer le routeur pour voir les mises à jour !" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Afficher les options avancées du Linklayer, (uniquement nécessaire si MTU > " +"1500). Les options avancées ne seront utilisées que si cette case est cochée." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Afficher et utiliser la configuration avancée. Les options avancées ne " +"seront utilisées que tant que cette case sera cochée." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Afficher et utiliser une configuration dangereuse. Les options dangereuses " +"ne seront utilisées que si cette case est cochée." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Management File d'attente" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Écraser le DSCP sur les paquets entrants (ingress) :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"L'interface graphique SQM vient d'activer l'initscript sqm en votre nom. " +"N'oubliez pas de désactiver manuellement le sqm initscript dans le menu de " +"démarrage du système au cas où ce changement ne serait pas souhaité." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "Vitesse de chargement (kbit/s) (sortie) Mettre sur 0 pour désactiver :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosité de la sortie de SQM dans le journal du système." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Quelle couche liaison à prendre en compte :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Mécanisme d'adaptation de la couche de liaison ; pour essai uniquement" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Avec SQM vous pouvez permettre " +"la régulation du trafic, un meilleur mélange (Fair Queueing), la gestion " +"active de la longueur des files d'attente (AQM) et la priorisation sur une " +"seule interface réseau." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Par défaut" diff --git a/luci-app-sqm-autorate/po/he/sqm.po b/luci-app-sqm-autorate/po/he/sqm.po new file mode 100644 index 000000000..587c49fcd --- /dev/null +++ b/luci-app-sqm-autorate/po/he/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: he\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/hi/sqm.po b/luci-app-sqm-autorate/po/hi/sqm.po new file mode 100644 index 000000000..111424659 --- /dev/null +++ b/luci-app-sqm-autorate/po/hi/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: hi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/hu/sqm.po b/luci-app-sqm-autorate/po/hu/sqm.po new file mode 100644 index 000000000..e4b96b811 --- /dev/null +++ b/luci-app-sqm-autorate/po/hu/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-08-16 16:38+0000\n" +"Last-Translator: Bence Csókás \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Alapszintű beállítások" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "SQM engedélyezése" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Csatoló neve" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "alapértelmezett" diff --git a/luci-app-sqm-autorate/po/it/sqm.po b/luci-app-sqm-autorate/po/it/sqm.po new file mode 100644 index 000000000..3a867c3ad --- /dev/null +++ b/luci-app-sqm-autorate/po/it/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-09-09 08:44+0000\n" +"Last-Translator: pisquan8 \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nome interfaccia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "predefinito" diff --git a/luci-app-sqm-autorate/po/ja/sqm.po b/luci-app-sqm-autorate/po/ja/sqm.po new file mode 100644 index 000000000..f7179b9dc --- /dev/null +++ b/luci-app-sqm-autorate/po/ja/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-10 19:29+0000\n" +"Last-Translator: Ryota <21ryotagamer@gmail.com>\n" +"Language-Team: Japanese \n" +"Language: ja\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.4-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "基本設定" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "この SQM インスタンスを有効にします。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "luci-app-sqmにUCIアクセスを許可" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "インターフェース名" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "キュー" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "スマート・キュー管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "デフォルト" diff --git a/luci-app-sqm-autorate/po/ko/sqm.po b/luci-app-sqm-autorate/po/ko/sqm.po new file mode 100644 index 000000000..8dbf6b6dd --- /dev/null +++ b/luci-app-sqm-autorate/po/ko/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-07 10:49+0000\n" +"Last-Translator: Sunggu Choi \n" +"Language-Team: Korean \n" +"Language: ko\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.7-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "기본 설정" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/mr/sqm.po b/luci-app-sqm-autorate/po/mr/sqm.po new file mode 100644 index 000000000..4c14d4090 --- /dev/null +++ b/luci-app-sqm-autorate/po/mr/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: mr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/ms/sqm.po b/luci-app-sqm-autorate/po/ms/sqm.po new file mode 100644 index 000000000..b1857d906 --- /dev/null +++ b/luci-app-sqm-autorate/po/ms/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: ms\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/nb_NO/sqm.po b/luci-app-sqm-autorate/po/nb_NO/sqm.po new file mode 100644 index 000000000..2c2441298 --- /dev/null +++ b/luci-app-sqm-autorate/po/nb_NO/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: nb_NO\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/pl/sqm.po b/luci-app-sqm-autorate/po/pl/sqm.po new file mode 100644 index 000000000..63d080dce --- /dev/null +++ b/luci-app-sqm-autorate/po/pl/sqm.po @@ -0,0 +1,253 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-22 17:33+0000\n" +"Last-Translator: Matthaiks \n" +"Language-Team: Polish \n" +"Language: pl\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.7.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Zaawansowany łańcuch opcji, aby przejść do dyscyplin kolejkowania egress; " +"bez sprawdzania błędów, używaj bardzo ostrożnie." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Zaawansowany łańcuch opcji, aby przejść do dyscyplin kolejkowania ingress; " +"bez sprawdzania błędów, używaj bardzo ostrożnie." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Podstawowe ustawienia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Utwórz plik dziennika dla tej instancji SQM w /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Prędkość pobierania (kbit/s) (ingress) ustawiona na 0, aby selektywnie " +"wyłączyć kształtowanie ingress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Włącz SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Włącz tę instancję SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Status jawnego powiadomienia o przeciążeniu (ECN) na pakietach " +"przychodzących (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Status jawnego powiadomienia o przeciążeniu (ECN) na pakietach wychodzących " +"(egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Udziel dostępu UCI do luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Twardy limit kolejek egress; pozostawić puste dla ustawień domyślnych." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Twardy limit kolejek ingress; pozostawić puste dla ustawień domyślnych." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignoruj DSCP przy ingress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nazwa interfejsu" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cel opóźnienia dla egress, np. 5ms [jednostki: s, ms lub us]; pozostaw puste " +"dla automatycznego wyboru, wpisz słowo default dla domyślnego qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cel opóźnienia dla ingress, np. 5ms [jednostki: s, ms lub us]; pozostaw " +"puste dla automatycznego wyboru, wpisz słowo default dla domyślnego qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptacja warstwy połączenia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Maksymalny rozmiar do obliczeń wielkości i szybkości, tcMTU (bajt); musi " +"być> = interfejs MTU + narzut:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimalny rozmiar pakietu, MPU (bajt); musi wynosić> 0 dla tabel rozmiarów " +"Ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Liczba wpisów w tabelach wielkości/szybkości, TSIZE; dla ATM wybrać TSIZE = " +"(tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Narzut na pakiet (bajt):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Dyscyplina kolejki" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Skrypt konfiguracji kolejki" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Kolejki" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Dyscypliny kolejkowania przydatne w tym systemie. Po zainstalowaniu nowej " +"qdisc musisz ponownie uruchomić router, aby zobaczyć aktualizacje!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Pokaż zaawansowane opcje Linklayera (wymagane tylko, jeśli MTU>1500). Opcje " +"zaawansowane będą używane tylko tak długo, jak to pole jest zaznaczone." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Pokaż i użyj konfiguracji zaawansowanej. Opcje zaawansowane będą używane " +"tylko tak długo, jak to pole jest zaznaczone." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Pokaż i używaj niebezpiecznej konfiguracji. Niebezpieczne opcje będą używane " +"tylko tak długo, jak to pole jest zaznaczone." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Inteligentne zarządzanie kolejkami" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Squash DSCP na pakietach przychodzących (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"SQM GUI właśnie włączył w Twoim imieniu initscript sqm. Pamiętaj, aby " +"ręcznie wyłączyć skrypt initscript sqm w menu autostart, jeśli ta zmiana nie " +"była pożądana." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Usługa SQM wydaje się wyłączona. Proszę użyć przycisku poniżej, aby " +"aktywować tę usługę." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Prędkość wysyłania (kbit/s) (egress) ustawiona na 0, aby selektywnie " +"wyłączyć kształtowanie egress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Szczegółowość danych wyjściowych SQM w dzienniku systemowym." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Którą warstwę łącza należy uwzględnić:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Którego mechanizmu dostosowania odtwarzacza linków należy użyć; tylko do " +"testowania" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Z SQM można włączyć " +"kształtowanie ruchu, lepsze mieszanie (Fair Queueing), aktywne zarządzanie " +"długością kolejki (AQM) i ustalanie priorytetów na jednym interfejsie " +"sieciowym." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "domyślna" diff --git a/luci-app-sqm-autorate/po/pt/sqm.po b/luci-app-sqm-autorate/po/pt/sqm.po new file mode 100644 index 000000000..ff2747104 --- /dev/null +++ b/luci-app-sqm-autorate/po/pt/sqm.po @@ -0,0 +1,256 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-08-04 20:24+0000\n" +"Last-Translator: ssantos \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançada para passar para as disciplinas de enfileiramento " +"de saída; sem verificação de erros, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançada para passar para as disciplinas de enfileiramento " +"de entrada; sem verificação de erros, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Configurações Básicas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Criar ficheiro de log para esta instância de SQM em /var/run/sqm/" +"${Nome_da_Interface}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Velocidade de descarrega (kbit/s) (ingresso) configurada a 0 para desativar " +"seletivamente a forma de ingresso:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Ativar o SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Ativar esta instância do SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Estado de notificação de congestionamento explícito (ECN) nos pacotes de " +"entrada (ingresso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Estado de notificação de congestionamento explícito (ECN) nos pacotes de " +"saída (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Conceder acesso UCI ao luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Limite rígido nas filas de espera de saída; deixe em branco para utilizar " +"valores predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Limite rígido nas filas de espera de entrada; deixe em branco para utilizar " +"valores predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignore o DSCP na entrada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nome da interface" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para saída, p.ex. 5ms [unidades: s, ms, ou us]; deixe vazio " +"para seleção automática, entre a palavra default para a predefinição do " +"qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para entrada, p.ex. 5ms [unidades: s, ms, ou us]; deixe " +"vazio para seleção automática, entre a palavra default para a predefinição " +"do qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptação da Camada de Ligação" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Tamanho máximo para cálculos de tamanho e taxa, tcMTU (byte); deve ser >= " +"MTU da interface + sobrecarga:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Tamanho mínimo do pacote, MPU (byte); deve ser > 0 para tabelas de tamanho " +"Ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Quantidade de entradas nas tabelas de tamanho/taxa, TSIZE; para ATM escolha " +"TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Sobrecarga por Pacote (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina de Fila de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configuração da fila de espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Filas de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Disciplinas de enfileiramento utilizáveis neste sistema. Depois de instalar " +"um novo qdisc, precisa reiniciar o roteador para ver as atualizações!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Mostrar Opções Avançadas da Camada de Ligações, (apenas necessário se MTU > " +"1500). As opções avançadas só serão usadas enquanto esta caixa estiver " +"marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar e Usar Configuração Avançada. As opções avançadas só serão usadas " +"enquanto esta caixa estiver marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar e Utilizar Configuração Perigosa. As opções perigosas só serão " +"usadas enquanto esta caixa estiver marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestão Inteligente de Filas de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Esmagar DSCP em pacotes de entrada (ingresso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"O GUI SQM acabou de ativar o initscript sqm em seu nome. Lembre-se de " +"desativar o initscript sqm manualmente no menu Início do Sistema no caso " +"desta alteração não ter sido desejada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"O serviço SQM parece estar desativado. Use o botão abaixo para ativar este " +"serviço." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Velocidade de envio (kbit/s) (saída) definida como 0 para desativar " +"seletivamente a forma de saída:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosidade da saída do SQM no log do sistema." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Que camada de ligação para a conta:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Utilizar qual mecanismo de adaptação da camada de ligação; apenas para testes" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Pode ativar a formação de tráfego com SQM, para melhor mistura (Fair Queueing), gestão ativa do " +"comprimento da fila de espera (AQM) e priorização numa interface de rede." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "padrão" diff --git a/luci-app-sqm-autorate/po/pt_BR/sqm.po b/luci-app-sqm-autorate/po/pt_BR/sqm.po new file mode 100644 index 000000000..ddcc9111b --- /dev/null +++ b/luci-app-sqm-autorate/po/pt_BR/sqm.po @@ -0,0 +1,258 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-22 17:33+0000\n" +"Last-Translator: Wellington Terumi Uemura \n" +"Language-Team: Portuguese (Brazil) \n" +"Language: pt_BR\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.7.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançadas passada para as disciplinas de enfileiramento de " +"saída; sem verificação de erros, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançadas passada para as disciplinas de enfileiramento de " +"entrada; sem verificação de erro, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Configurações Básicas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Criar um arquivo de registro log para esta instância SQM em /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Velocidade de Download (kbits/s) (entrada), defina como 0 para desativar " +"seletivamente a modelagem do tráfico de entrada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Ative o SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Ative esta instância do SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Status de notificação explicita de congestionamento (ECN) durante a entrada " +"de pacotes (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Status de notificação explicita de congestionamento (ECN) durante a saída de " +"pacotes (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Conceda acesso UCI ao luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Limite máximo nas filas de saída; deixe em branco para utilizar valores " +"predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Limite máximo nas filas de entrada; deixe em branco para utilizar valores " +"predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignore o DSCP na entrada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nome da Interface" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para saída, por exemplo, 5ms [unidades: s, ms ou nós]; " +"deixe vazio para usar a seleção automática, coloque a palavra default para " +"utilizar os valores predefinidos do qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para entrada, por exemplo, 5ms [unidades: s, ms ou nós]; " +"deixe vazio para usar a seleção automática, coloque a palavra default para " +"utilizar os valores predefinidos do qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptação da Camada do Link de Ligação" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Tamanho máximo para realizar os cálculos de tamanho e taxa, tcMTU (byte); " +"precisa ser >= interface MTU + sobrecarga:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Tamanho mínimo do pacote, MPU (byte); precisa ser > 0 para as tabelas de " +"tamanho ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Quantidade de entradas de tamanho/taxa nas tabelas, TSIZE; para o ATM, " +"escolha TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Por Sobrecarga de Pacote (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina da Fila" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configuração da fila" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Filas de espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"As disciplinas de enfileiramento utilizáveis neste sistema. Depois de " +"instalar um novo qdisc, você precisa reiniciar o roteador para ver as " +"atualizações!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Mostrar as Opções Avançadas da Camada do Link ( só é necessário caso MTU > " +"1500). As opções avançadas só serão usadas quando esta caixa for selecionada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Exibir e Usar a Configuração Avançada. As opções avançadas só serão usadas " +"quando esta caixa for selecionada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar e Usar as Configurações Perigosas. As opções perigosas só serão " +"usadas quando esta caixa for selecionada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestão Inteligente das Filas de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Liquidar o DSCP durante a entrada dos pacotes (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"O GUI SQM acabou de ativar o initscript sqm em seu nome. Lembre-se de " +"desativar o initscript sqm manualmente no menu Inicio do Sistema caso esta " +"alteração não tenha sido requerida." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"O serviço SQM parece estar desativado. Use o botão abaixo para ativar este " +"serviço." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Velocidade de upload (kbit/s) (saída), defina como 0 para desativar " +"seletivamente a modelagem do tráfico de saída:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Prolixidade da saída do SQM's nos arquivos de registro log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Qual camada de link deve ser considerada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Qual o mecanismo de adaptação de camadas do link para usar; para testes " +"apenas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Com a SQM você " +"pode habilitar a modelagem de tráfego, ter uma melhor mistura (Fila Justa), " +"gerenciamento ativo de comprimento de fila (AQM) e priorização em uma " +"interface de rede." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Padrão" diff --git a/luci-app-sqm-autorate/po/ro/sqm.po b/luci-app-sqm-autorate/po/ro/sqm.po new file mode 100644 index 000000000..6b5dd6579 --- /dev/null +++ b/luci-app-sqm-autorate/po/ro/sqm.po @@ -0,0 +1,257 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-11-29 10:52+0000\n" +"Last-Translator: Simona Iacob \n" +"Language-Team: Romanian \n" +"Language: ro\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2;\n" +"X-Generator: Weblate 4.10-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Șir de opțiuni avansate care trebuie transmise disciplinelor de coadă de " +"ieșire; nu se verifică erorile, se utilizează cu mare atenție." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Șir de opțiuni avansate care trebuie transmise disciplinelor de intrare în " +"coada de așteptare; fără verificare a erorilor, utilizați cu mare atenție." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Setări de bază" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Creați un fișier jurnal pentru această instanță SQM în /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Viteza de descărcare (kbit/s) (intrare) se setează la 0 pentru a dezactiva " +"selectiv modelarea intrării:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Activați SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Activează această instanță SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Starea ECN (Explicit congestion notification (notificare explicită de " +"congestie) pe pachetele de intrare (intrare):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Starea ECN (Explicit congestion notification (notificare explicită de " +"congestie) pe pachetele de ieșire (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Acordă acces UCI pentru luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Limita dură a cozilor de ieșire; lăsați gol pentru valoarea implicită." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Limita dură a cozilor de intrare; lăsați gol pentru valoarea implicită." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignoră DSCP la intrare:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Numele interfeței" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Obiectivul de latență pentru ieșire, de exemplu, 5ms [unități: s, ms sau " +"us]; lăsați gol pentru selecția automată, introduceți cuvântul default " +"pentru valoarea implicită a qdiscului." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Obiectivul de latență pentru intrare, de exemplu, 5ms [unități: s, ms sau " +"us]; lăsați gol pentru selecția automată, introduceți cuvântul default " +"pentru valoarea implicită a qdiscului." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptarea nivelului de legătură" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Dimensiunea maximă pentru calcularea mărimii și a ratei, tcMTU (byte); " +"trebuie să fie >= MTU al interfeței + overhead:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Dimensiunea minimă a pachetului, MPU (byte); trebuie să fie > 0 pentru " +"tabelele de dimensiuni ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Numărul de intrări în tabelele de mărime/taxe, TSIZE; pentru ATM, alegeți " +"TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Per Pachet Overhead (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina cozii" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configurare a cozilor de așteptare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Cozi de așteptare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Discipline de coadă de așteptare utilizabile pe acest sistem. După " +"instalarea unui nou qdisc, trebuie să reporniți routerul pentru a vedea " +"actualizările!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Afișează opțiunile avansate pentru Linklayer (necesar numai dacă MTU > 1500)" +". Opțiunile avansate vor fi utilizate numai atâta timp cât această casetă " +"este bifată." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Afișați și utilizați Configurație avansată. Opțiunile avansate vor fi " +"utilizate numai atât timp cât această casetă este bifată." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Afișare și utilizare Configurație periculoasă. Opțiunile periculoase vor fi " +"utilizate numai atât timp cât această casetă este bifată." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestionarea inteligentă a cozilor de așteptare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Zdrobiți DSCP pe pachetele de intrare (intrare):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"Interfața grafică SQM tocmai a activat initscriptul sqm în numele " +"dumneavoastră. Nu uitați să dezactivați manual sqm initscript în meniul " +"Pornire sistem în cazul în care această modificare nu a fost dorită." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Serviciul SQM pare să fie dezactivat. Vă rugăm să utilizați butonul de mai " +"jos pentru a activa acest serviciu." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Viteza de încărcare (kbit/s) (ieșire) se setează la 0 pentru a dezactiva " +"selectiv modelarea la ieșire:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbalitatea ieșirii SQM în jurnalul sistemului." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Ce strat de legătură trebuie luat în considerare:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Ce mecanism de adaptare a linklayer-ului trebuie utilizat; numai pentru " +"testare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Cu SQM puteți activa modelarea " +"traficului, o mai bună amestecare (Fair Queueing), gestionarea activă a " +"lungimii cozilor de așteptare (AQM) și prioritizarea pe o singură interfață " +"de rețea." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "implicit" diff --git a/luci-app-sqm-autorate/po/ru/sqm.po b/luci-app-sqm-autorate/po/ru/sqm.po new file mode 100644 index 000000000..3aa81dd5a --- /dev/null +++ b/luci-app-sqm-autorate/po/ru/sqm.po @@ -0,0 +1,222 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-10-30 16:38+0000\n" +"Last-Translator: masta0f1eave \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.9-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Строка расширенных параметров для перехода к дисциплинам исходящей очереди; " +"нет проверки ошибок, используйте очень осторожно." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Строка расширенных параметров для перехода к входящим дисциплинам очередей; " +"нет проверки ошибок, используйте очень осторожно." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Основные настройки" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Создать файл журнала для этого экземпляра SQM в папке /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Включить SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Включите этот экземпляр SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Прямое уведомление о перегрузке сети (ECN) для входящих пакетов (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Предоставить UCI доступ для luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Жесткое ограничение на исходящие очереди; оставьте пустым для значения по " +"умолчанию." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Жесткое ограничение на входящие очереди; оставьте пустым для значения по " +"умолчанию." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Имя интерфейса" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Адаптация канального уровня" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Минимальный размер пакета, MPU (байт); должен быть > 0 для таблиц размеров " +"Ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Скрипт настройки очереди" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Очереди" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Умное управление очередью" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Детальность вывода SQM в системный журнал." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "по умолчанию" diff --git a/luci-app-sqm-autorate/po/sk/sqm.po b/luci-app-sqm-autorate/po/sk/sqm.po new file mode 100644 index 000000000..972333d16 --- /dev/null +++ b/luci-app-sqm-autorate/po/sk/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-12-06 14:03+0000\n" +"Last-Translator: Dušan Kazik \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Weblate 4.10-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Základné nastavenia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/sv/sqm.po b/luci-app-sqm-autorate/po/sv/sqm.po new file mode 100644 index 000000000..fad4f0c12 --- /dev/null +++ b/luci-app-sqm-autorate/po/sv/sqm.po @@ -0,0 +1,216 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-01-31 14:55+0000\n" +"Last-Translator: Anders Jonsson \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.11-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avancerad alternativsträng för att överföra till utgångskö-disciplinerna; " +"inga felkontroller, använd mycket försiktigt." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avancerad alternativsträng för att överföra till inträde till " +"utgångskö-disciplinerna; inga felkontroller, använd mycket försiktigt." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Grundinställningar" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Skapa loggfil för denna SQM-instans under /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Nerladdnings hastighet (kbit/s) (inträde) ställs in på 0 för att selektivt " +"inaktivera ingångs formning:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Aktivera SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Aktivera denna SQM-instans." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Gränssnittets namn" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/templates/sqm.pot b/luci-app-sqm-autorate/po/templates/sqm.pot new file mode 100644 index 000000000..9503c8586 --- /dev/null +++ b/luci-app-sqm-autorate/po/templates/sqm.pot @@ -0,0 +1,199 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/tr/sqm.po b/luci-app-sqm-autorate/po/tr/sqm.po new file mode 100644 index 000000000..c90ec8848 --- /dev/null +++ b/luci-app-sqm-autorate/po/tr/sqm.po @@ -0,0 +1,244 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-07-05 20:29+0000\n" +"Last-Translator: ToldYouThat \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Çıkış kuyruğu denetimleri için gelişmiş seçenek satırı; hata kontrolü " +"yoktur, dikkatli kullanın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Giriş kuyruğu denetimleri için gelişmiş seçenek satırı; hata kontrolü " +"yoktur, dikkatli kullanın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Temel Ayarlar" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Bu SQM örneği için /var/run/sqm/${Interface_name}.[start|stop]-sqm.log " +"konumda günlük dosyası oluşturun." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"İndirme hızı (kbit/s) (giriş) Şekillendirmeyi devre dışı bırakmak için 0 " +"olarak ayarlayın:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "SQM'i etkinleştir" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Bu SQM örneğini etkinleştirin." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "Gelen paketlerde (giriş) açık tıkanıklık bildirimi (ECN) durumu:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "Giden paketlerde (çıkış) açık tıkanıklık bildirimi (ECN) durumu." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "luci-app-sqm için UCI erişimi verin" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Çıkış kuyrukları için kesin sınır; varsayılan ayar için boş bırakın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Giriş kuyrukları için kesin sınır; varsayılan ayar için boş bırakın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Giriş kuyruğunda DSCP'yi yoksay:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Arayüz ismi" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Çıkış için gecikme hedefi, örn. 5ms [birimler: s, ms, ya da us]; otomatik " +"seçim için boş bırakın, qdisc'in varsayılan ayarı için \"default\" yazın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Giriş için gecikme hedefi, örn. 5ms [birimler: s, ms, ya da us]; otomatik " +"seçim için boş bırakın, qdisc'in varsayılan ayarı için \"default\" yazın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Bağlantı Katmanı Uyarlaması" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Boyut ve hız hesaplamaları için Maksimum Boyut, tcMTU (bayt); arayüzün MTU " +"değeri ve overhead toplamından büyük olması gerekir:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimum paket boyutu, MPU (bayt); ethernet boyut tablosu için sıfırdan (0) " +"büyük olmalıdır:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Boyut/hız tabloları için girdi sayıları, TSIZE; ATM için TSIZE = (tcMTU + " +"1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Paket Başına Ek Yük (bayt):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Kuyruk Denetimi" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Kuyruk kurulum betiği" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Kuyruklar" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Bu sistemde kuyruk denetimleri kullanılabilir. Yeni bir qdisc yükledikten " +"sonra, devreye girmesi için yönlendiriciyi yeniden başlatmanız gerekir." + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Gelişmiş bağlantı katmanı ayarlarını göster, (sadece MTU 1500'den büyükse " +"gereklidir). Gelişmiş seçenekler yalnızca bu kutu işaretliyken kullanılır." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Gelişmiş Ayarları Göster ve kullan. Gelişmiş seçenekler yalnızca bu kutu " +"işaretliyken kullanılır." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Tehlikeli Ayarları Göster ve Kullan. Tehlikeli olabilecek seçenekler " +"yalnızca bu kutu işaretliyken kullanılacaktır." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Akıllı Kuyruk Yönetimi (SQM)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Gelen paketlerde (giriş) DSCP'yi sıkıştır:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"SQM GUI, sizin adınıza sqm initscript'i etkinleştirdi. Bu değişikliğin " +"istenmemesi durumunda sqm initscript'i System Startup menüsünden manuel " +"olarak devre dışı bırakmayı unutmayın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Bu SQM servisi devre dışı görünüyor. Servisi aktif etmek için lütfen alttaki " +"butonu kullanın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Yükleme hızı (kbit/s) (çıkış) Şekillendirmeyi devre dışı bırakmak için 0 " +"olarak ayarlayın:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "SQM çıktısının sistem günlüğü ayrıntısı." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Bağlantı katmanı seçimi:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Bağlantı katmanı uyarlama tekniği; yalnızca test için" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"SQM ile; trafik şekillendirme, " +"daha iyi sıkıştırma (Adil Kuyruklama), etkin kuyruk uzunluğu yönetimi (AQM) " +"ve bir ağ arayüzünü önceliklendirme gibi işlemler yapabilirsiniz." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "varsayılan" diff --git a/luci-app-sqm-autorate/po/uk/sqm.po b/luci-app-sqm-autorate/po/uk/sqm.po new file mode 100644 index 000000000..086b3c30c --- /dev/null +++ b/luci-app-sqm-autorate/po/uk/sqm.po @@ -0,0 +1,209 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-04-07 18:07+0000\n" +"Last-Translator: Yurii Petrashko \n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=" +"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.0-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Назва інтерфейсу" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/vi/sqm.po b/luci-app-sqm-autorate/po/vi/sqm.po new file mode 100644 index 000000000..da12d68ad --- /dev/null +++ b/luci-app-sqm-autorate/po/vi/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-11-21 12:21+0000\n" +"Last-Translator: Darias \n" +"Language-Team: Vietnamese \n" +"Language: vi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.4-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Mặc định" diff --git a/luci-app-sqm-autorate/po/zh_Hans/sqm.po b/luci-app-sqm-autorate/po/zh_Hans/sqm.po new file mode 100644 index 000000000..45eda0b1b --- /dev/null +++ b/luci-app-sqm-autorate/po/zh_Hans/sqm.po @@ -0,0 +1,217 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-04-22 07:14+0000\n" +"Last-Translator: 王攀 <41330784@qq.com>\n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "传递到出站队列规则的高级选项字符串;不会进行错误检查,请谨慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "传递到入站队列规则的高级选项字符串;不会进行错误检查,请谨慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "基本设置" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"在此 /var/run/sqm/${Interface_name} 下为此 SQM 实例创建日志文件。[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "下载速度(kbit/s)(入口) 设为 0 时,有选择地禁用入口整形:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "启用 SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "启用此 SQM 实例." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "入站数据包的显式拥塞通知(ECN)状态:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "出站数据包的显式拥塞通知(ECN)状态." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "授予 UCI 访问 luci-app-sqm 的权限" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "出口队列的硬限制; 默认留空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "入口队列的硬限制; 默认留空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "在入口忽略 DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "接口名称" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "出口的延迟目标,例如 5ms [单位:s、ms或us]; " +"为自动选择留空,为qdisc的默认值输入单词default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "入口的延迟目标,例如 5ms [单位:s、ms 或 us]; " +"为自动选择留空,为qdisc的默认值输入单词default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "链路层适应" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "大小和速率计算的最大大小,tcMTU(字节); 需要 >= 接口 MTU + 开销:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "最小数据包大小,MPU(byte); 在以太网中需要 >0 :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "大小/费率表中的条目数,TSIZE; 对于 ATM,选择 TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "每个数据包开销(字节):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "列队规则" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "队列设置脚本" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "队列" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "队列规则(需要重启路由器)!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "服务质量管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"显示高级链路选项,(仅在MTU> 1500时才需要)。 只有选中此框时,才会使用高级选" +"项。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "显示和使用高级配置。 只有在选中此框时,只会使用高级选项。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "显示和使用危险配置。 只要选中此框,就会使用危险选项。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "智能队列管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "在入站数据包(入口)上压缩 DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"你刚刚开启了SQM随机启动功能,如果你不希望SQM随机启动,可以在系统启动菜单下手" +"动禁用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "SQM服务似乎已被禁用。请使用下面的按钮来激活这项服务。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "上传速度 (kbit/s)(出口)设置为 0 以选择性地禁用出口整形:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "SQM 输出到系统日志的详细程度。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "要考虑哪个链路层:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "使用哪个链路适应机制; 仅用于测试" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"使用 SQM 你可以启用流量整形,更好的混合" +"(公平列队)主动列队管理(AQM) 并设置网络接口优先级。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "默认" diff --git a/luci-app-sqm-autorate/po/zh_Hant/sqm.po b/luci-app-sqm-autorate/po/zh_Hant/sqm.po new file mode 100644 index 000000000..33dc43351 --- /dev/null +++ b/luci-app-sqm-autorate/po/zh_Hant/sqm.po @@ -0,0 +1,218 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-08-14 14:43+0000\n" +"Last-Translator: Hulen \n" +"Language-Team: Chinese (Traditional) \n" +"Language: zh_Hant\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "傳遞到出站佇列規則的進階選項字串,沒有錯誤檢查,請謹慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "傳遞到入站佇列規則的進階選項字串,沒有錯誤檢查,請謹慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "基本設定" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "建立日誌檔案 (/var/run/sqm/${Interface_name}.[start|stop]-sqm.log)。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "下載速度 (kbit/s) (0-無限制):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "啟用 SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "啟用 SQM。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "傳入封包(入口)上的顯式擁塞通知 (ECN)狀態:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "傳出封包(出口)上的顯式擁塞通知(ECN)狀態。" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "授予 luci-app-sqm 擁有 UCI 存取的權限" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "嚴格限制出口隊列;預設保留為空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "對入口隊列的硬限制;預設保留為空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "在進入時忽略DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "介面名稱" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"出口的延遲目標,例如5ms [單位: s、ms、或us];留空以進行自動選擇,在qdisc的預" +"設值中輸入default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"進入的延遲目標,例如5ms [單位: s、ms、或us];留空以進行自動選擇,在qdisc的預" +"設值中輸入default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "連結層適應" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "用於大小和速率計算的最大大小,tcMTU (位元組);需要≧介面MTU +開銷:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "最小封包大小,MPU(位元組);對於乙太網大小表,必須>0:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "大小/費率表中的條目數,TSIZE;對於ATM,選擇TSIZE = (tcMTU + 1)/ 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "每個封包開銷(位元組):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "佇列規則" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "佇列設定指令碼" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "佇列" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "安裝新的佇列規則後,需要重新啟動路由器!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS頻寬管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"顯示 高級連接層選項 , (僅當MTU> 1500時才需要)。僅在選中此框時,才使用高級選" +"項。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "顯示使用進階選項,只有選取此選取框時,才會使用進階選項。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "顯示和使用危險組態。僅在選中此復選框後,才會使用危險選項。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "智慧隊列管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "在傳入封包(入口)上壓縮DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"此 SQM GUI 剛剛代表您啟用了sqm初始化指令碼。切記在「系統啟動」選單下,手動停" +"用sqm初始化指令碼,以防意外變更。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "SQM 服務似乎已被停用。請使用下面的按鈕來啟動這項服務。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "上傳速度 (kbit/s) (0-無限制):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "日誌等級。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "連結層:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "使用哪種連接層適配機制;僅用於測試" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"使用 SQM 您可以啟用流量整形,更" +"好的混合 (公平佇列),主動佇列管理 (AQM) 並設定網路介面優先順序。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "預設" diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate new file mode 100755 index 000000000..2d70776e7 --- /dev/null +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -0,0 +1,39 @@ +#!/bin/sh /etc/rc.common +# shellcheck disable=SC2039 +# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : +# Copyright (C) 2018-2022 Ycarus (Yannick Chabanois) +# Released under GPL 3. See LICENSE for the full terms. + +# shellcheck disable=SC2034 +{ + START=90 + STOP=10 + USE_PROCD=1 +} + +. /usr/lib/unbound/iptools.sh +. /lib/functions/network.sh + +_launch_autorate() { + logger -t "SQM-autorate" "Launch on $1" + config_get enabled "$1" enabled + [ "${enabled}" != "1" ] && return + config_get autorate "$1" autorate + [ "${autorate}" != "1" ] && return + + procd_open_instance + # shellcheck disable=SC2086 + procd_set_param command /usr/share/sqm-autorate/CAKE-autorate.sh "$1" +# procd_append_param env "OMR_TRACKER_SERVER_HTTP_TEST=$server_http_test" + procd_set_param limits nofile="51200 51200" + procd_set_param respawn 0 10 0 + procd_set_param stderr 1 + procd_close_instance + sleep 2 +} + +start_service() { + config_load sqm + config_foreach _launch_autorate queue +} + diff --git a/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm b/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm new file mode 100755 index 000000000..b3aa47c6d --- /dev/null +++ b/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm @@ -0,0 +1,12 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@sqm[-1] + add ucitrack sqm + set ucitrack.@sqm[-1].init=sqm + del_list ucitrack.@firewall[0].affects=sqm + add_list ucitrack.@firewall[0].affects=sqm + commit ucitrack +EOF + +exit 0 diff --git a/luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json b/luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json new file mode 100644 index 000000000..6c5ff4fa6 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json @@ -0,0 +1,13 @@ +{ + "admin/network/sqm": { + "title": "SQM QoS", + "order": 59, + "action": { + "type": "view", + "path": "network/sqm" + }, + "depends": { + "acl": [ "luci-app-sqm" ] + } + } +} diff --git a/luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json b/luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json new file mode 100644 index 000000000..810d91b83 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json @@ -0,0 +1,23 @@ +{ + "luci-app-sqm": { + "description": "Grant UCI access for luci-app-sqm", + "read": { + "file": { + "/var/run/sqm/available_qdiscs": [ "list" ], + "/usr/lib/sqm/*.qos.help": [ "read" ], + "/etc/init.d/sqm enable" : [ "exec" ], + "/etc/init.d/sqm start" : [ "exec" ], + "/etc/init.d/sqm-autorate enable" : [ "exec" ], + "/etc/init.d/sqm-autorate start" : [ "exec" ] + }, + "uci": [ "sqm" ], + "ubus": { + "file": [ "read", "list" ], + "luci": [ "setInitAction" ] + } + }, + "write": { + "uci": [ "sqm" ] + } + } +} diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh new file mode 100755 index 000000000..4f0504c94 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh @@ -0,0 +1,608 @@ +#!/bin/bash + +# CAKE-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and OWD/RTT +# requires packages: bash; and iputils-ping + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) +# Modified by Ycarus (Yannick Chabanois) for OpenMPTCProuter: +# * Add multiples interfaces support + +# Possible performance improvement +export LC_ALL=C +export TZ=UTC + +trap cleanup_and_killall INT TERM EXIT + +cleanup_and_killall() +{ + echo "Killing all background processes and cleaning up /tmp files." + trap - INT TERM EXIT + kill $monitor_achieved_rates_pid 2> /dev/null + kill $maintain_pingers_pid 2> /dev/null + [[ -d /tmp/CAKE-autorate-${dl_if} ]] && rm -r /tmp/CAKE-autorate-${dl_if} + exit +} + +install_dir="/usr/share/sqm-autorate/" + +. $install_dir"config.sh" "$1" + +# test if stdout is a tty (terminal) +[[ ! -t 1 ]] && exec &> /tmp/cake-autorate-${dl_if}.log + +get_next_shaper_rate() +{ + local min_shaper_rate_kbps=$1 + local base_shaper_rate_kbps=$2 + local max_shaper_rate_kbps=$3 + local achieved_rate_kbps=$4 + local load_condition=$5 + local t_next_rate_us=$6 + local -n t_last_bufferbloat_us=$7 + local -n t_last_decay_us=$8 + local -n shaper_rate_kbps=$9 + + case $load_condition in + + # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period + *delayed) + if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then + adjusted_achieved_rate_kbps=$(( ($achieved_rate_kbps*$achieved_rate_adjust_bufferbloat)/1000 )) + adjusted_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_bufferbloat)/1000 )) + shaper_rate_kbps=$(( $adjusted_achieved_rate_kbps < $adjusted_shaper_rate_kbps ? $adjusted_achieved_rate_kbps : $adjusted_shaper_rate_kbps )) + t_last_bufferbloat_us=${EPOCHREALTIME/./} + fi + ;; + + # high load, so increase rate providing not inside bufferbloat refractory period + high) + if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then + shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_load_high)/1000 )) + fi + ;; + # medium load, so just maintain rate as is, i.e. do nothing + medium) + : + ;; + # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate + low|idle) + if (($t_next_rate_us > ($t_last_decay_us+$decay_refractory_period_us) )); then + + if (($shaper_rate_kbps > $base_shaper_rate_kbps)); then + decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_load_low)/1000 )) + shaper_rate_kbps=$(( $decayed_shaper_rate_kbps > $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps)) + elif (($shaper_rate_kbps < $base_shaper_rate_kbps)); then + decayed_shaper_rate_kbps=$(( ((2000-$shaper_rate_adjust_load_low)*$shaper_rate_kbps)/1000 )) + shaper_rate_kbps=$(( $decayed_shaper_rate_kbps < $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps)) + fi + + t_last_decay_us=${EPOCHREALTIME/./} + fi + ;; + esac + # make sure to only return rates between cur_min_rate and cur_max_rate + (($shaper_rate_kbps < $min_shaper_rate_kbps)) && shaper_rate_kbps=$min_shaper_rate_kbps; + (($shaper_rate_kbps > $max_shaper_rate_kbps)) && shaper_rate_kbps=$max_shaper_rate_kbps; +} + +monitor_achieved_rates() +{ + # track rx and tx bytes transfered and divide by time since last update + # to determine achieved dl and ul transfer rates + + local rx_bytes_path=$1 + local tx_bytes_path=$2 + local monitor_achieved_rates_interval_us=$3 # (microseconds) + + compensated_monitor_achieved_rates_interval_us=$monitor_achieved_rates_interval_us + + [[ -f $rx_bytes_path ]] && { read -r prev_rx_bytes < $rx_bytes_path; } 2> /dev/null || prev_rx_bytes=0 + [[ -f $tx_bytes_path ]] && { read -r prev_tx_bytes < $tx_bytes_path; } 2> /dev/null || prev_tx_bytes=0 + + while true + do + t_start_us=${EPOCHREALTIME/./} + + # If rx/tx bytes file exists, read it in, otherwise set to prev_bytes + # This addresses interfaces going down and back up + [[ -f $rx_bytes_path ]] && { read -r rx_bytes < $rx_bytes_path; } 2> /dev/null || rx_bytes=$prev_rx_bytes + [[ -f $tx_bytes_path ]] && { read -r tx_bytes < $tx_bytes_path; } 2> /dev/null || tx_bytes=$prev_tx_bytes + + dl_achieved_rate_kbps=$(( ((8000*($rx_bytes - $prev_rx_bytes)) / $compensated_monitor_achieved_rates_interval_us ) )) + ul_achieved_rate_kbps=$(( ((8000*($tx_bytes - $prev_tx_bytes)) / $compensated_monitor_achieved_rates_interval_us ) )) + + (($dl_achieved_rate_kbps<0)) && dl_achieved_rate_kbps=0 + (($ul_achieved_rate_kbps<0)) && ul_achieved_rate_kbps=0 + + printf '%s' "$dl_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps + printf '%s' "$ul_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps + + prev_rx_bytes=$rx_bytes + prev_tx_bytes=$tx_bytes + + # read in the max_wire_packet_rtt_us + concurrent_read max_wire_packet_rtt_us /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us + + compensated_monitor_achieved_rates_interval_us=$(( (($monitor_achieved_rates_interval_us>(10*$max_wire_packet_rtt_us) )) ? $monitor_achieved_rates_interval_us : $((10*$max_wire_packet_rtt_us)) )) + + sleep_remaining_tick_time $t_start_us $compensated_monitor_achieved_rates_interval_us + done +} + +get_loads() +{ + # read in the dl/ul achived rates and determine the loads + + concurrent_read dl_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps + concurrent_read ul_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps + + dl_load_percent=$(((100*10#${dl_achieved_rate_kbps})/$dl_shaper_rate_kbps)) + ul_load_percent=$(((100*10#${ul_achieved_rate_kbps})/$ul_shaper_rate_kbps)) +} + +classify_load() +{ + # classify the load according to high/low/medium/idle and add _delayed if delayed + # thus ending up with high_delayed, low_delayed, etc. + local load_percent=$1 + local achieved_rate_kbps=$2 + local -n load_condition=$3 + + if (( $load_percent > $high_load_thr_percent )); then + load_condition="high" + elif (( $load_percent > $medium_load_thr_percent )); then + load_condition="medium" + elif (( $achieved_rate_kbps > $connection_active_thr_kbps )); then + load_condition="low" + else + load_condition="idle" + fi + + (($bufferbloat_detected)) && load_condition=$load_condition"_delayed" +} + +monitor_reflector_responses() +{ + # ping reflector, maintain baseline and output deltas to a common fifo + + local pinger=$1 + local rtt_baseline_us=$2 + + while read -r timestamp _ _ _ reflector seq_rtt + do + # If no match then skip onto the next one + [[ $seq_rtt =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + + seq=${BASH_REMATCH[1]} + + rtt_us=${BASH_REMATCH[3]}000 + rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + + reflector=${reflector//:/} + + rtt_delta_us=$(( $rtt_us-$rtt_baseline_us )) + + alpha=$(( (( $rtt_delta_us >=0 )) ? $alpha_baseline_increase : $alpha_baseline_decrease )) + + rtt_baseline_us=$(( ( (1000-$alpha)*$rtt_baseline_us+$alpha*$rtt_us )/1000 )) + + printf '%s %s %s %s %s %s\n' "$timestamp" "$reflector" "$seq" "$rtt_baseline_us" "$rtt_us" "$rtt_delta_us" > /tmp/CAKE-autorate-${dl_if}/ping_fifo + + printf '%s' "${timestamp//[[\[\].]}" > /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us + + done /dev/null + [[ -p /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo ]] && rm /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo + done + exit +} + +maintain_pingers() +{ + # this initiates the pingers and monitors reflector health, rotating reflectors as necessary + + trap kill_pingers TERM + + declare -A pinger_pids + declare -A rtt_baselines_us + + reflector_offences_idx=0 + + # For each pinger: create fifos, get baselines and initialize record of offences + for ((pinger=0; pinger<$no_pingers; pinger++)) + do + mkfifo /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo + [[ $(ping -B -I ${dl_if} -q -c 5 -i 0.1 ${reflectors[$pinger]} | tail -1) =~ ([0-9.]+)/ ]] && printf -v rtt_baselines_us[$pinger] %.0f\\n "${BASH_REMATCH[1]}e3" || rtt_baselines_us[$pinger]=0 + + declare -n reflector_offences="reflector_${pinger}_offences" + for ((i=0; i<$reflector_misbehaving_detection_window; i++)) do reflector_offences[i]=0; done + + sum_reflector_offences[$pinger]=0 + done + + pingers_t_start_us=${EPOCHREALTIME/./} + + # Initiate pingers + for ((pinger=0; pinger<$no_pingers; pinger++)) + do + printf '%s' "$pingers_t_start_us" > /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us + start_pinger_next_pinger_time_slot $pinger pid + pinger_pids[$pinger]=$pid + done + + # Reflector health check loop - verifies reflectors have not gone stale and rotates reflectors as necessary + while true + do + sleep_s $reflector_health_check_interval_s + + for ((pinger=0; pinger<$no_pingers; pinger++)) + do + reflector_check_time_us=${EPOCHREALTIME/./} + concurrent_read reflector_last_timestamp_us /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us + declare -n reflector_offences="reflector_${pinger}_offences" + + (( ${reflector_offences[$reflector_offences_idx]} )) && ((sum_reflector_offences[$pinger]--)) + reflector_offences[$reflector_offences_idx]=$(( (((${EPOCHREALTIME/./}-$reflector_last_timestamp_us) > $reflector_response_deadline_us)) ? 1 : 0 )) + ((reflector_offences[$reflector_offences_idx])) && ((sum_reflector_offences[$pinger]++)) + + if ((sum_reflector_offences[$pinger]>=$reflector_misbehaving_detection_thr)); then + + (($debug)) && echo "DEBUG: Warning: reflector: "${reflectors[$pinger]}" seems to be misbehaving." + + if(($no_reflectors>$no_pingers)); then + + # pingers always use reflectors[0]..[$no_pingers-1] as the initial set + # and the additional reflectors are spare reflectors should any from initial set go stale + # a bad reflector in the initial set is replaced with $reflectors[$no_pingers] + # $reflectors[$no_pingers] is then unset + # and the the bad reflector moved to the back of the queue (last element in $reflectors[]) + # and finally the indices for $reflectors are updated to reflect the new order + + (($debug)) && echo "DEBUG: Replacing reflector: "${reflectors[$pinger]}" with "${reflectors[$no_pingers]}"." + kill ${pinger_pids[$pinger]} 2> /dev/null + bad_reflector=${reflectors[$pinger]} + # overwrite the bad reflector with the reflector that is next in the queue (the one after 0..$no_pingers-1) + reflectors[$pinger]=${reflectors[$no_pingers]} + # remove the new reflector from the list of additional reflectors beginning from $reflectors[$no_pingers] + unset reflectors[$no_pingers] + # bad reflector goes to the back of the queue + reflectors+=($bad_reflector) + # reset array indices + reflectors=(${reflectors[*]}) + # set up the new pinger with the new reflector and retain pid + start_pinger_next_pinger_time_slot $pinger pid + pinger_pids[$pinger]=$pid + + else + (($debug)) && echo "DEBUG: No additional reflectors specified so just retaining: "${reflectors[$pinger]}"." + reflector_offences[$pinger]=0 + fi + + for ((i=0; i<$reflector_misbehaving_detection_window; i++)) do reflector_offences[i]=0; done + sum_reflector_offences[$pinger]=0 + fi + done + ((reflector_offences_idx=(reflector_offences_idx+1)%$reflector_misbehaving_detection_window)) + done +} + +start_pinger_next_pinger_time_slot() +{ + # wait until next pinger time slot and start pinger in its slot + # this allows pingers to be stopped and started (e.g. during sleep or reflector rotation) + # whilst ensuring pings will remain spaced out appropriately to maintain granularity + + local pinger=$1 + local -n pinger_pid=$2 + t_start_us=${EPOCHREALTIME/./} + time_to_next_time_slot_us=$(( ($reflector_ping_interval_us-($t_start_us-$pingers_t_start_us)%$reflector_ping_interval_us) + $pinger*$ping_response_interval_us )) + sleep_remaining_tick_time $t_start_us $time_to_next_time_slot_us + if (($debug)); then + ping -B -I ${dl_if} -D -i $reflector_ping_interval_s ${reflectors[$pinger]} > /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo & + pinger_pid=$! + else + ping -B -I ${dl_if} -D -i $reflector_ping_interval_s ${reflectors[$pinger]} > /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo 2> /dev/null & + pinger_pid=$! + fi + monitor_reflector_responses $pinger ${rtt_baselines_us[$pinger]} & +} + +set_cake_rate() +{ + local interface=$1 + local shaper_rate_kbps=$2 + local -n time_rate_set_us=$3 + + (($output_cake_changes)) && echo "tc qdisc change root dev ${interface} cake bandwidth ${shaper_rate_kbps}Kbit" + + if (($debug)); then + tc qdisc change root dev $interface cake bandwidth ${shaper_rate_kbps}Kbit + else + tc qdisc change root dev $interface cake bandwidth ${shaper_rate_kbps}Kbit 2> /dev/null + fi + + time_rate_set_us=${EPOCHREALTIME/./} +} + +set_shaper_rates() +{ + if (( $dl_shaper_rate_kbps != $last_dl_shaper_rate_kbps || $ul_shaper_rate_kbps != $last_ul_shaper_rate_kbps )); then + + # fire up tc in each direction if there are rates to change, and if rates change in either direction then update max wire calcs + (( $dl_shaper_rate_kbps != $last_dl_shaper_rate_kbps )) && { set_cake_rate $dl_if $dl_shaper_rate_kbps t_prev_dl_rate_set_us; last_dl_shaper_rate_kbps=$dl_shaper_rate_kbps; } + (( $ul_shaper_rate_kbps != $last_ul_shaper_rate_kbps )) && { set_cake_rate $ul_if $ul_shaper_rate_kbps t_prev_ul_rate_set_us; last_ul_shaper_rate_kbps=$ul_shaper_rate_kbps; } + + update_max_wire_packet_compensation + fi +} + +get_max_wire_packet_size_bits() +{ + local interface=$1 + local -n max_wire_packet_size_bits=$2 + + read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" + [[ $(tc qdisc show dev $interface) =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] + [[ ! -z "${BASH_REMATCH[2]}" ]] && max_wire_packet_size_bits=$((8*($max_wire_packet_size_bits+${BASH_REMATCH[2]}))) + # atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits + [[ "${BASH_REMATCH[1]}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*(($max_wire_packet_size_bits+376)/384) )) +} + +update_max_wire_packet_compensation() +{ + # Compensate for delays imposed by active traffic shaper + # This will serve to increase the delay thr at rates below around 12Mbit/s + + max_wire_packet_rtt_us=$(( (1000*$dl_max_wire_packet_size_bits)/$dl_shaper_rate_kbps + (1000*$ul_max_wire_packet_size_bits)/$ul_shaper_rate_kbps )) + compensated_delay_thr_us=$(( $delay_thr_us + $max_wire_packet_rtt_us )) + + # write out max_wire_packet_rtt_us + printf '%s' "$max_wire_packet_rtt_us" > /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us +} + +concurrent_read() +{ + # in the context of separate processes writing using > and reading form file + # it seems costly calls to the external flock binary can be avoided + # read either succeeds as expected or occassionally reads in bank value + # so just test for blank value and re-read until not blank + + local -n value=$1 + local path=$2 + read -r value < $path + while [[ -z $value ]]; do + sleep_us $concurrent_read_interval_us + read -r value < $path; + done +} + +verify_ifs_up() +{ + # Check the rx/tx paths exist and give extra time for ifb's to come up if needed + # This will block if ifs never come up + + while [[ ! -f $rx_bytes_path || ! -f $tx_bytes_path ]] + do + (($debug)) && [[ ! -f $rx_bytes_path ]] && echo "DEBUG Warning: $rx_bytes_path does not exist. Waiting "$if_up_check_interval_s" seconds for interface to come up." + (($debug)) && [[ ! -f $tx_bytes_path ]] && echo "DEBUG Warning: $tx_bytes_path does not exist. Waiting "$if_up_check_interval_s" seconds for interface to come up." + sleep_s $if_up_check_interval_s + done +} + +sleep_s() +{ + # calling external sleep binary is slow + # bash does have a loadable sleep + # but read's timeout can more portably be exploited and this is apparently even faster anyway + + local sleep_duration_s=$1 # (seconds, e.g. 0.5, 1 or 1.5) + + read -t $sleep_duration_s < /tmp/CAKE-autorate-${dl_if}/sleep_fifo +} + +sleep_us() +{ + # calling external sleep binary is slow + # bash does have a loadable sleep + # but read's timeout can more portably be exploited and this is apparently even fastera anyway + + local sleep_duration_us=$1 # (microseconds) + + sleep_duration_s=000000$sleep_duration_us + sleep_duration_s=${sleep_duration_s::-6}.${sleep_duration_s: -6} + read -t $sleep_duration_s < /tmp/CAKE-autorate-${dl_if}/sleep_fifo +} + +sleep_remaining_tick_time() +{ + # sleeps until the end of the tick duration + + local t_start_us=$1 # (microseconds) + local tick_duration_us=$2 # (microseconds) + + sleep_duration_us=$(( $t_start_us + $tick_duration_us - ${EPOCHREALTIME/./} )) + + if (( $sleep_duration_us > 0 )); then + sleep_us $sleep_duration_us + fi +} + +# Set up tmp directory, sleep fifo and perform various sanity checks + +# /tmp/CAKE-autorate-${dl_if}/ is used to store temporary files +# it should not exist on startup so if it does exit, else create the directory +if [[ -d /tmp/CAKE-autorate-${dl_if} ]]; then + echo "Error: /tmp/CAKE-autorate-${dl_if} already exists. Is another instance running? Exiting script." + trap - INT TERM EXIT + exit +else + mkdir /tmp/CAKE-autorate-${dl_if} +fi + +mkfifo /tmp/CAKE-autorate-${dl_if}/sleep_fifo +exec 3<> /tmp/CAKE-autorate-${dl_if}/sleep_fifo + +no_reflectors=${#reflectors[@]} + +# Check no_pingers <= no_reflectors +(( $no_pingers > $no_reflectors)) && { echo "Error: number of pingers cannot be greater than number of reflectors. Exiting script."; exit; } + +# Check dl/if interface not the same +[[ $dl_if == $ul_if ]] && { echo "Error: download interface and upload interface are both set to: '"$dl_if"', but cannot be the same. Exiting script."; exit; } + +# Check bufferbloat detection threshold not greater than window length +(( $bufferbloat_detection_thr > $bufferbloat_detection_window )) && { echo "Error: bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } + +# Wait if $startup_wait_s > 0 +if (($startup_wait_s>0)); then + (($debug)) && echo "DEBUG Waiting "$startup_wait_s" seconds before startup." + sleep_s $startup_wait_s +fi + +# Check interfaces are up and wait if necessary for them to come up +verify_ifs_up + +# Initialize variables + +# Convert human readable parameters to values that work with integer arithmetic +printf -v alpha_baseline_increase %.0f\\n "${alpha_baseline_increase}e3" +printf -v alpha_baseline_decrease %.0f\\n "${alpha_baseline_decrease}e3" +printf -v achieved_rate_adjust_bufferbloat %.0f\\n "${achieved_rate_adjust_bufferbloat}e3" +printf -v shaper_rate_adjust_bufferbloat %.0f\\n "${shaper_rate_adjust_bufferbloat}e3" +printf -v shaper_rate_adjust_load_high %.0f\\n "${shaper_rate_adjust_load_high}e3" +printf -v shaper_rate_adjust_load_low %.0f\\n "${shaper_rate_adjust_load_low}e3" +printf -v high_load_thr_percent %.0f\\n "${high_load_thr}e2" +printf -v medium_load_thr_percent %.0f\\n "${medium_load_thr}e2" +printf -v reflector_ping_interval_us %.0f\\n "${reflector_ping_interval_s}e6" +printf -v monitor_achieved_rates_interval_us %.0f\\n "${monitor_achieved_rates_interval_ms}e3" +printf -v sustained_idle_sleep_thr_us %.0f\\n "${sustained_idle_sleep_thr_s}e6" +printf -v reflector_response_deadline_us %.0f\\n "${reflector_response_deadline_s}e6" +bufferbloat_refractory_period_us=$(( 1000*$bufferbloat_refractory_period_ms )) +decay_refractory_period_us=$(( 1000*$decay_refractory_period_ms )) +delay_thr_us=$(( 1000*$delay_thr_ms )) + +ping_response_interval_us=$(($reflector_ping_interval_us/$no_pingers)) + +concurrent_read_interval_us=$(($ping_response_interval_us/4)) + +dl_shaper_rate_kbps=$base_dl_shaper_rate_kbps +ul_shaper_rate_kbps=$base_ul_shaper_rate_kbps + +last_dl_shaper_rate_kbps=$dl_shaper_rate_kbps +last_ul_shaper_rate_kbps=$ul_shaper_rate_kbps + +get_max_wire_packet_size_bits $dl_if dl_max_wire_packet_size_bits +get_max_wire_packet_size_bits $ul_if ul_max_wire_packet_size_bits + +set_cake_rate $dl_if $dl_shaper_rate_kbps t_prev_dl_rate_set_us +set_cake_rate $ul_if $ul_shaper_rate_kbps t_prev_ul_rate_set_us + +update_max_wire_packet_compensation + +t_start_us=${EPOCHREALTIME/./} +t_end_us=${EPOCHREALTIME/./} +t_prev_ul_rate_set_us=$t_start_us +t_prev_dl_rate_set_us=$t_start_us +t_ul_last_bufferbloat_us=$t_start_us +t_ul_last_decay_us=$t_start_us +t_dl_last_bufferbloat_us=$t_start_us +t_dl_last_decay_us=$t_start_us + +t_sustained_connection_idle_us=0 + +declare -a delays=( $(for i in {1..$bufferbloat_detection_window}; do echo 0; done) ) +delays_idx=0 +sum_delays=0 + +mkfifo /tmp/CAKE-autorate-${dl_if}/ping_fifo +exec 4<> /tmp/CAKE-autorate-${dl_if}/ping_fifo + +maintain_pingers & +maintain_pingers_pid=$! + +# Initiate achived rate monitor +monitor_achieved_rates $rx_bytes_path $tx_bytes_path $monitor_achieved_rates_interval_us& +monitor_achieved_rates_pid=$! + +prev_timestamp=0 + +while true +do + while read -t $global_ping_response_timeout_s -r timestamp reflector seq rtt_baseline_us rtt_us rtt_delta_us + do + t_start_us=${EPOCHREALTIME/./} + if ((($t_start_us - "${timestamp//[[\[\].]}")>500000)); then + (($debug)) && echo "DEBUG processed response from [" $reflector "] that is > 500ms old. Skipping." + continue + fi + + # Keep track of number of delays across detection window + (( ${delays[$delays_idx]} )) && ((sum_delays--)) + delays[$delays_idx]=$(( $rtt_delta_us > $compensated_delay_thr_us ? 1 : 0 )) + ((delays[$delays_idx])) && ((sum_delays++)) + (( delays_idx=(delays_idx+1)%$bufferbloat_detection_window )) + + bufferbloat_detected=$(( (($sum_delays>=$bufferbloat_detection_thr)) ? 1 : 0 )) + + get_loads + + classify_load $dl_load_percent $dl_achieved_rate_kbps dl_load_condition + classify_load $ul_load_percent $ul_achieved_rate_kbps ul_load_condition + + get_next_shaper_rate $min_dl_shaper_rate_kbps $base_dl_shaper_rate_kbps $max_dl_shaper_rate_kbps $dl_achieved_rate_kbps $dl_load_condition $t_start_us t_dl_last_bufferbloat_us t_dl_last_decay_us dl_shaper_rate_kbps + get_next_shaper_rate $min_ul_shaper_rate_kbps $base_ul_shaper_rate_kbps $max_ul_shaper_rate_kbps $ul_achieved_rate_kbps $ul_load_condition $t_start_us t_ul_last_bufferbloat_us t_ul_last_decay_us ul_shaper_rate_kbps + + (($output_processing_stats)) && printf '%s %-6s %-6s %-3s %-3s %s %-15s %-6s %-6s %-6s %-6s %-6s %s %-14s %-14s %-6s %-6s\n' $EPOCHREALTIME $dl_achieved_rate_kbps $ul_achieved_rate_kbps $dl_load_percent $ul_load_percent $timestamp $reflector $seq $rtt_baseline_us $rtt_us $rtt_delta_us $compensated_delay_thr_us $sum_delays $dl_load_condition $ul_load_condition $dl_shaper_rate_kbps $ul_shaper_rate_kbps + + set_shaper_rates + + # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) + if (($enable_sleep_function)); then + if [[ $dl_load_condition == idle* && $ul_load_condition == idle* ]]; then + ((t_sustained_connection_idle_us+=$((${EPOCHREALTIME/./}-$t_end_us)))) + (($t_sustained_connection_idle_us>$sustained_idle_sleep_thr_us)) && break + else + # reset timer + t_sustained_connection_idle_us=0 + fi + fi + t_end_us=${EPOCHREALTIME/./} + + done /dev/null + + # reset idle timer + t_sustained_connection_idle_us=0 + + # verify interfaces are up (e.g. following ping response timeout from interfaces going down) + verify_ifs_up + + # wait until load increases again + while true + do + t_start_us=${EPOCHREALTIME/./} + get_loads + (($dl_load_percent>$medium_load_thr_percent || $ul_load_percent>$medium_load_thr_percent)) && break + sleep_remaining_tick_time $t_start_us $reflector_ping_interval_us + done + + # Start up ping processes + maintain_pingers & + maintain_pingers_pid=$! +done diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh new file mode 100644 index 000000000..9e8fdb0ed --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh @@ -0,0 +1,158 @@ +#!/bin/bash + +# config.sh sets up defaults for CAKE-autorate + +# config.sh is a part of CAKE-autorate +# CAKE-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) +# Modified by Ycarus (Yannick Chabanois) for OpenMPTCProuter: +# * Get configuration via uci + +INTERFACE=$1 + +# *** OUTPUT OPTIONS *** + +#output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats +output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo "0") +#output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo "0") +#debug=0 # enable (1) or disable (0) out of debug lines +debug=$(uci -q get sqm.common.debug || echo "0") + +# *** STANDARD CONFIGURATION OPTIONS *** + +#dl_if=ifb4eth1 # download interface +#dl_if=$(uci -q get sqm.${INTERFACE}.download_interface) +dl_if=ifb4$(uci -q get sqm.${INTERFACE}.interface) +#ul_if=eth1 # upload interface +#ul_if=$(uci -q get sqm.${INTERFACE}.upload_interface) +ul_if=$(uci -q get sqm.${INTERFACE}.interface) + +#reflector_ping_interval_s=0.2 # (seconds, e.g. 0.2s or 2s) +reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.2") + +# list of reflectors to use and number of pingers to initiate +# pingers will be initiated with reflectors in the order specified in the list +# additional reflectors will be used to replace any reflectors that go stale +# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially +# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad +# a bad reflector will go to the back of the queue on reflector rotation +reflectors=("1.1.1.1" "1.0.0.1" "8.8.8.8" "8.8.4.4" "9.9.9.9" "9.9.9.10") +no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "4") + +# delay threshold in ms is the extent of RTT increase to classify as a delay +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +#delay_thr_ms=25 # (milliseconds) +delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "25") + +#min_dl_shaper_rate_kbps=10000 # minimum bandwidth for download (Kbit/s) +min_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_download) +#base_dl_shaper_rate_kbps=100000 # steady state bandwidth for download (Kbit/s) +base_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.download) +#max_dl_shaper_rate_kbps=200000 # maximum bandwidth for download (Kbit/s) +max_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_download) + +#min_ul_shaper_rate_kbps=10000 # minimum bandwidth for upload (Kbit/s) +min_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_upload) +#base_ul_shaper_rate_kbps=100000 # steady state bandwidth for upload (KBit/s) +base_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.upload) +#max_ul_shaper_rate_kbps=200000 # maximum bandwidth for upload (Kbit/s) +max_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_upload) + +# sleep functionality saves unecessary pings and CPU cycles by +# pausing all active pingers when connection is not in active use +#enable_sleep_function=1 # enable (1) or disable (0) sleep functonality +enable_sleep_function=$(uci -q get sqm.${INTERFACE}.enable_sleep_functions || echo "1") +#connection_active_thr_kbps=500 # threshold in Kbit/s below which dl/ul is considered idle +connection_active_thr_kbps=$(uci -q get sqm.${INTERFACE}.connection_active_thr_kbps || echo "500") +#sustained_idle_sleep_thr_s=60 # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) +sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.substained_idle_sleep_thr_s || echo "60") + +#startup_wait_s=0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) +startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "60") + +# *** ADVANCED CONFIGURATION OPTIONS *** + +# interval in ms for monitoring achieved rx/tx rates +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +monitor_achieved_rates_interval_ms=100 # (milliseconds) + +# bufferbloat is detected when (bufferbloat_detection_thr) samples +# out of the last (bufferbloat detection window) samples are delayed +bufferbloat_detection_window=4 # number of samples to retain in detection window +bufferbloat_detection_thr=2 # number of delayed samples for bufferbloat detection + +# RTT baseline against which to measure delays +# the idea is that the baseline is allowed to increase slowly to allow for path changes +# and slowly enough such that bufferbloat will be corrected well before the baseline increases, +# but it will decrease very rapidly to ensure delays are measured against the shortest path +alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase +alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease + +# rate adjustment parameters +# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate +# to exploit that transfer rates during bufferbloat provide an indication of line capacity +# otherwise shaper rate is adjusted up on load high, and down on load idle or low +# and held the same on load medium +achieved_rate_adjust_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat +shaper_rate_adjust_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat +shaper_rate_adjust_load_high=1.01 # how rapidly to increase shaper rate upon high load detected +shaper_rate_adjust_load_low=0.98 # how rapidly to return to base shaper rate upon idle or low load detected + +# the load is categoried as low if < medium_load_thr, medium if > medium_load_thr and high if > high_load_thr relative to the current shaper rate +medium_load_thr=0.25 # % of currently set bandwidth for detecting medium load +high_load_thr=0.75 # % of currently set bandwidth for detecting high load + +# refractory periods between successive bufferbloat/decay rate changes +bufferbloat_refractory_period_ms=300 # (milliseconds) +decay_refractory_period_ms=1000 # (milliseconds) + +# interval for checking reflector health +reflector_health_check_interval_s=1 # (seconds) +# deadline for reflector response not to be classified as an offence against reflector +reflector_response_deadline_s=1 # (seconds) + +# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples +# out of the last (reflector misbehaving detection window) samples are offences +# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to +# 3 offences within the last 60s +reflector_misbehaving_detection_window=60 +reflector_misbehaving_detection_thr=3 + +global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no ping response whatsoever (seconds) + +if_up_check_interval_s=10 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state) + +# verify these are correct using 'cat /sys/class/...' +case "${dl_if}" in + \veth*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + \ifb*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + *) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/rx_bytes" + ;; +esac + +case "${ul_if}" in + \veth*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + \ifb*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + *) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/tx_bytes" + ;; +esac + +if (( $debug )) ; then + echo "DEBUG: rx_bytes_path: $rx_bytes_path" + echo "DEBUG: tx_bytes_path: $tx_bytes_path" +fi From c5f6e2fc957deb7c2773568e25270688175a1260 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 16 Jun 2022 19:29:03 +0200 Subject: [PATCH 0770/2059] Fix software offloading --- openmptcprouter-full/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index a041d9bae..5f301a04b 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -30,14 +30,14 @@ MY_DEPENDS := \ bind-dig \ libnetfilter-conntrack ip-full nstat \ iptables-mod-iface iptables-mod-ipmark iptables-mod-hashlimit iptables-mod-condition iptables-mod-trace iptables-mod-conntrack-extra iptables-mod-account \ - kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra conntrack \ + kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra conntrack kmod-ipt-offload \ iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 kmod-ipt-ipsec \ wireless-tools \ libiwinfo-lua \ ca-bundle ca-certificates \ luci-mod-admin-full luci-app-firewall luci-app-glorytun-tcp luci-app-glorytun-udp luci-app-shadowsocks-libev luci-app-unbound luci-theme-openmptcprouter luci-theme-argon luci-base \ luci-app-omr-tracker luci-app-omr-dscp \ - luci-app-sqm sqm-scripts-extra \ + luci-app-sqm-autorate sqm-scripts-extra \ luci-app-vnstat2 omr-quota luci-app-omr-quota \ luci-app-mptcp luci-app-openmptcprouter luci-app-omr-bypass luci-app-mail luci-app-upnp \ luci-app-wol luci-app-opkg \ From 3c76172c2f09327e4e48d2fde4a48219ace0e466 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 16 Jun 2022 19:29:55 +0200 Subject: [PATCH 0771/2059] VPS FW cosmetic changes --- .../files/etc/init.d/openmptcprouter-vps | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 0f3b63c10..60a2764cd 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -937,9 +937,9 @@ _vps_firewall_redirect_port() { } [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then - checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port $protoi${comment}") + checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment}") else - checkfw=$(echo "$vpsfwlist" | grep "# OMR $username redirect router $src_dport port $protoi${comment}") + checkfw=$(echo "$vpsfwlist" | grep "# OMR $username redirect router $src_dport port ${protoi}${comment}") fi fi else @@ -954,9 +954,9 @@ _vps_firewall_redirect_port() { [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then - checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port $protoi${comment}") + checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment}") else - checkfw=$(echo "$vpsfw6list" | grep "# OMR $username redirect router $src_dport port $protoi${comment}") + checkfw=$(echo "$vpsfw6list" | grep "# OMR $username redirect router $src_dport port ${protoi}${comment}") fi fi fi @@ -978,11 +978,11 @@ _vps_firewall_redirect_port() { [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port $protoi${comment}") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") else - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username redirect router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR redirect router $src_dport port $protoi${comment}") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username redirect router $src_dport port ${protoi}${comment}") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR redirect router $src_dport port ${protoi}${comment}") fi fi else @@ -998,11 +998,11 @@ _vps_firewall_redirect_port() { [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port $protoi${comment}") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") else - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username redirect router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR redirect router $src_dport port $protoi${comment}") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username redirect router $src_dport port ${protoi}${comment}") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR redirect router $src_dport port ${protoi}${comment}") fi fi fi @@ -1018,44 +1018,44 @@ _vps_firewall_redirect_port() { iptables-save --counters | sed "s:-d $src_dip/32::g" | iptables-restore -w } [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port $protoi${comment}") + checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment}") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port $protoi") + checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi}") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port $protoi${comment}") + checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment}") fi fi if [ "$checkfw" = "" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'$protoi'","fwtype" : "ACCEPT","ipproto" : "'$family'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'"}' _set_json "shorewallopen" "$settings" - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","destip" : "'$dest_ip'","destport" : "'$dest_port'","proto" : "'$protoi'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","destip" : "'$dest_ip'","destport" : "'$dest_port'","proto" : "'${protoi}'"}' _set_json "v2rayredirect" "$settings" fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port $protoi") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port $protoi${comment}") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port $protoi") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}") else [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port $protoi${comment}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port $protoi${comment}") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") fi fi fi From 90edfd880f82992302d5c74cc78b849f73af9a0c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 16 Jun 2022 19:30:22 +0200 Subject: [PATCH 0772/2059] Add addlatency as a *default setting --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 8c2e18080..c1848fbdd 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -63,6 +63,7 @@ _setup_wan_interface() { set network.$1.ip4table=wan set network.$1.multipath=$3 set network.$1.defaultroute=0 + set network.$1.addlatency=0 set network.${1}_dev=device set network.${1}_dev.name=$2 set network.${1}_dev.txqueuelen=20 @@ -165,6 +166,7 @@ set network.lan.ifname=${lanif} set network.lan.metric=2048 set network.lan.ipv6=0 set network.lan.delegate=0 +set network.lan.addlatency=0 EOF uci -q batch <<-EOF From a3c247ed6fb833efb1f668d0a988a2734f840255 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 17 Jun 2022 20:12:31 +0200 Subject: [PATCH 0773/2059] Fix remove rule with source IP on VPS FW --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 60a2764cd..dcde475fc 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1072,6 +1072,7 @@ _vps_firewall_close_port() { src_dport=$(echo $line | awk '{print $5}' | tr -d "\n") source_port=$(echo $line | awk '{print $6}' | tr -d "\n") source_dip=$(echo $line | awk '{print $7}' | tr -d "\n") + [ "$source_dip" = "#" ] && source_sip="" source_ip=$(echo $line | awk '{print $2}' | awk -F ":" '{print $2}' | tr -d "\n") if [ "$source_port" = "-" ]; then settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","source_dip": "'$source_dip'","source_ip": "'$source_ip'"}' @@ -1096,6 +1097,7 @@ _vps_firewall_close_port() { src_dport=$(echo $line | awk '{print $5}' | tr -d "\n") source_port=$(echo $line | awk '{print $6}' | tr -d "\n") source_dip=$(echo $line | awk '{print $7}' | tr -d "\n") + [ "$source_dip" = "#" ] && source_sip="" source_ip=$(echo $line | awk '{print $2}' | awk -F ":" '{print $2}' | tr -d "\n") if [ "$source_port" = "-" ]; then settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","source_dip": "'$source_dip'","source_ip": "'$source_ip'"}' From 0d7c0427a14a10e1c0f5a091c038788f6554c166 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 17 Jun 2022 20:13:05 +0200 Subject: [PATCH 0774/2059] Use omr-tracker for sqm-autorate --- luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh index 9e8fdb0ed..7d0948f2a 100644 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh @@ -39,7 +39,8 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially # and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad # a bad reflector will go to the back of the queue on reflector rotation -reflectors=("1.1.1.1" "1.0.0.1" "8.8.8.8" "8.8.4.4" "9.9.9.9" "9.9.9.10") +#reflectors=("1.1.1.1" "1.0.0.1" "8.8.8.8" "8.8.4.4" "9.9.9.9" "9.9.9.10") +reflectors=($(uci get omr-tracker.defaults.hosts)) no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "4") # delay threshold in ms is the extent of RTT increase to classify as a delay From f110c5309e8abd6b4019db3e45b7df1326fc112e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 17 Jun 2022 20:13:55 +0200 Subject: [PATCH 0775/2059] Fixes for shadowsocks dead loop and multiple fw run --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 1cfecffc7..57b1412c5 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1463,7 +1463,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") } if [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get openmptcprouter.settings.external_check)" = "0" ]; then - if ping -c 1 $(uci -q get shadowsocks-libev.sss0.server) 2>&1 >/dev/null; then + if ping -B -I $OMR_TRACKER_DEVICE -c 1 $(uci -q get shadowsocks-libev.sss0.server) 2>&1 >/dev/null; then uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") fi fi @@ -1538,7 +1538,7 @@ fi } # If a service is down, force restart it -if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(pgrep ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then +if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(pgrep ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then _log "Can't find Shadowsocks, restart it..." /etc/init.d/shadowsocks-libev restart 2>&1 >/dev/null sleep 5 @@ -1668,7 +1668,7 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter fi #if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then -if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then +if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then _log "Set firewall on server" /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 From 02cade76439c600c119a2f306b00c3032772bdf0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Jun 2022 09:39:41 +0200 Subject: [PATCH 0776/2059] Fix typo --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index dcde475fc..1be9331a4 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1072,7 +1072,7 @@ _vps_firewall_close_port() { src_dport=$(echo $line | awk '{print $5}' | tr -d "\n") source_port=$(echo $line | awk '{print $6}' | tr -d "\n") source_dip=$(echo $line | awk '{print $7}' | tr -d "\n") - [ "$source_dip" = "#" ] && source_sip="" + [ "$source_dip" = "#" ] && source_dip="" source_ip=$(echo $line | awk '{print $2}' | awk -F ":" '{print $2}' | tr -d "\n") if [ "$source_port" = "-" ]; then settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","source_dip": "'$source_dip'","source_ip": "'$source_ip'"}' @@ -1097,7 +1097,7 @@ _vps_firewall_close_port() { src_dport=$(echo $line | awk '{print $5}' | tr -d "\n") source_port=$(echo $line | awk '{print $6}' | tr -d "\n") source_dip=$(echo $line | awk '{print $7}' | tr -d "\n") - [ "$source_dip" = "#" ] && source_sip="" + [ "$source_dip" = "#" ] && source_dip="" source_ip=$(echo $line | awk '{print $2}' | awk -F ":" '{print $2}' | tr -d "\n") if [ "$source_port" = "-" ]; then settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","source_dip": "'$source_dip'","source_ip": "'$source_ip'"}' From 15032839eac5fa0c0f6580d744960f70d1be1227 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Jun 2022 13:07:57 +0200 Subject: [PATCH 0777/2059] Fix another typo and populate fstab only if needed --- openmptcprouter/files/etc/uci-defaults/2030-omr-fstab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2030-omr-fstab b/openmptcprouter/files/etc/uci-defaults/2030-omr-fstab index 575d0e238..15f2dd49f 100755 --- a/openmptcprouter/files/etc/uci-defaults/2030-omr-fstab +++ b/openmptcprouter/files/etc/uci-defaults/2030-omr-fstab @@ -4,11 +4,11 @@ _set_fsck() { uci -q batch <<-EOF >/dev/null set "fstab.$1.enabled=1" - set "fstab.$1.enable_fsck=1" + set "fstab.$1.enabled_fsck=1" EOF } -/sbin/block detect > /etc/config/fstab +[ -z "$(uci show fstab | grep mount)" ] && /sbin/block detect > /etc/config/fstab uci -q set fstab.@global[0].check_fs='1' config_load fstab config_foreach _set_fsck mount From edf63868b1a19411e4114a94ae606662e988077e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Jun 2022 15:54:34 +0200 Subject: [PATCH 0778/2059] Use debian mirror for ndisc6 --- ndisc6/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ndisc6/Makefile b/ndisc6/Makefile index 76ebf9e08..990ec9a75 100644 --- a/ndisc6/Makefile +++ b/ndisc6/Makefile @@ -12,8 +12,8 @@ PKG_NAME:=ndisc6 PKG_VERSION:=1.0.3 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 -PKG_SOURCE_URL:=http://www.remlab.net/files/ndisc6 +PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.bz2 +PKG_SOURCE_URL:=http://deb.debian.org/debian/pool/main/n/ndisc6 PKG_HASH:=0f41d6caf5f2edc1a12924956ae8b1d372e3b426bd7b11eed7d38bc974eec821 PKG_INSTALL:=1 From 58679b713bf0da7fd9a04b03ac81f17c40519bb2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 19 Jun 2022 11:10:04 +0200 Subject: [PATCH 0779/2059] Reload sqm-autorate when sqm reload --- luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm b/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm index b3aa47c6d..7f472f725 100755 --- a/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm +++ b/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm @@ -6,6 +6,11 @@ uci -q batch <<-EOF >/dev/null set ucitrack.@sqm[-1].init=sqm del_list ucitrack.@firewall[0].affects=sqm add_list ucitrack.@firewall[0].affects=sqm + delete ucitrack.@sqm-autorate[-1] + add ucitrack sqm-autorate + set ucitrack.@sqm-autorate[-1].init=sqm-autorate + del_list ucitrack.@firewall[0].affects=sqm-autorate + add_list ucitrack.@firewall[0].affects=sqm-autorate commit ucitrack EOF From 129dc624b34d352631e8ab91df431d3a32aab08b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 19 Jun 2022 11:10:41 +0200 Subject: [PATCH 0780/2059] Reload FW only on needed server --- .../files/usr/share/omr/post-tracking.d/post-tracking | 11 +++++++++-- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 9 +++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 57b1412c5..edd7a35f6 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1669,8 +1669,15 @@ fi #if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then - _log "Set firewall on server" - /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 + check_server_fw() { + [ "$(uci -q get openmptcprouter.$1.set_firewall)" = "1" ] && { + _log "Set firewall on server $1" + /etc/init.d/openmptcprouter-vps set_vps_firewall $1 >/dev/null 2>&1 + } + } + config_load openmptcprouter + config_foreach check_server_fw server + run_fw_include() { [ -n "$1" ] && [ "$(uci -q get firewall.$1.reload)" = "0" ] && sh $(uci -q get firewall.$1.path) >/dev/null 2>&1 diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 1be9331a4..cc6425cdd 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1191,8 +1191,13 @@ _set_vps_firewall() { } set_vps_firewall() { - config_load openmptcprouter - config_foreach _set_vps_firewall server + local server_opt=$2 + if [ -n "$server_opt" ]; then + _set_vps_firewall $server_opt + else + config_load openmptcprouter + config_foreach _set_vps_firewall server + fi } _set_ss_redir() { From e982d7da9b0d84516ec570bbef5f27e34d7a9a75 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 20 Jun 2022 08:39:17 +0200 Subject: [PATCH 0781/2059] Fix fw adding rules when not needed --- .../files/etc/init.d/openmptcprouter-vps | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index cc6425cdd..867104fd7 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -967,42 +967,42 @@ _vps_firewall_redirect_port() { if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then if [ "$target" = "ACCEPT" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port $protoi") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi$") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port $protoi$") else - vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi$") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi$") fi else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}$") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment}$") else vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username redirect router $src_dport port ${protoi}${comment}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR redirect router $src_dport port ${protoi}${comment}") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR redirect router $src_dport port ${protoi}${comment}$") fi fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then if [ "$target" = "ACCEPT" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port $protoi") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port $protoi$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port $protoi$") else - vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username redirect router $src_dport port $protoi$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR redirect router $src_dport port $protoi$") fi else [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment}$") else - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username redirect router $src_dport port ${protoi}${comment}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR redirect router $src_dport port ${protoi}${comment}") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username redirect router $src_dport port ${protoi}${comment}$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR redirect router $src_dport port ${protoi}${comment}$") fi fi fi @@ -1038,24 +1038,24 @@ _vps_firewall_redirect_port() { fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}$") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}$") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}$") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment}$") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}$") else [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment}") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment}$") fi fi fi From 6b294cc9df23f8aec006d6189334aa7d61e1f8eb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 20 Jun 2022 08:39:42 +0200 Subject: [PATCH 0782/2059] Enable led when interface up --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index c1848fbdd..bdb6a12c7 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -408,6 +408,11 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then set wireless.radio1.cell_density='0' set wireless.default_radio1.network='wifi5' commit wireless + add ucitrack led + set ucitrack.@led[-1].init=led + del_list ucitrack.@firewall[0].affects=led + add_list ucitrack.@firewall[0].affects=led + commit ucitrack EOF fi From 90408a197a9dd64c33bcbb55fbde3366fb205854 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 20 Jun 2022 20:25:37 +0200 Subject: [PATCH 0783/2059] Fix carrier return on FW types concatenation --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 867104fd7..f64b78c56 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1161,7 +1161,7 @@ _set_vps_firewall() { fw_list=$(_set_json "shorewalllist" "$settings") [ -z "$fw_list" ] && return if [ -n "$vpsfwlist" ]; then - vpsfwlist="$vpsfwlist\n$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" + vpsfwlist="${vpsfwlist}"$'\n'"$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" else vpsfwlist="$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" fi From ff82abbb27b5d8c99ccf5bc2f45e3ce8b0ec79ae Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 21 Jun 2022 22:09:28 +0200 Subject: [PATCH 0784/2059] Fix modems connection for RUTX (and maybe some other cases) --- .../usr/share/omr/post-tracking.d/post-tracking | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index edd7a35f6..d5413e72c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -807,9 +807,24 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then sleep 20 fi + if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "dhcp" ]; then + for modem in $(mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do + if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then + modem_device=$(mmcli -m $modem -K | grep 'modem.generic.device ' | awk '{print $3}') + [ -n "$modem_device" ] && modem_interface=$(uci show network | grep $modem_device | awk -F. '{print $2}') + [ -n "$modem_interface" ] && { + _log "No anwser from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart associed interface $modem_interface" + ifup $modem_interface + } + fi + done + fi + + # This part must be done after modems restart because we have no idea when modems will be ready again... (another solution would be to check ModemManager status) if [ "$OMR_TRACKER_PREV_STATUS" = "$OMR_TRACKER_STATUS" ]; then exit 0 fi + if [ "$multipath_status" != "off" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ]); then if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then _log "$OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) switched off" @@ -910,6 +925,8 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then config_load network config_foreach set_route interface $OMR_TRACKER_INTERFACE config_foreach set_route6 interface $OMR_TRACKER_INTERFACE + else + _log "Default gateway disabled, no default gateway set" fi if [ "$(uci -q get openmptcprouter.settings.shadowsocksudp)" = "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.shadowsocks)" = "up" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "" ] && [ "$(uci -q get shadowsocks-libev.hi1.mode)" = "tcp_and_udp" ] && [ "$(uci -q get shadowsocks-libev.sss0.obfs)" != "1" ]; then _log "Tunnel down use ShadowSocks for UDP" From a26cb1d90bfdb951a985930612e32790ccfd42af Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 24 Jun 2022 18:12:43 +0200 Subject: [PATCH 0785/2059] Fixes on default gw --- .../usr/share/omr/post-tracking.d/post-tracking | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index d5413e72c..a4f2c2f6f 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -57,7 +57,7 @@ set_route() { if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" = "yes" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" != "yes" ] && _log "$PREVINTERFACE down. Replace default in table 991337 route by $interface_gw dev $interface_if" - [ "$SETDEFAULT" = "yes" ] && ip route replace default scope global nexthop via $interface_gw dev $interface_if 2>&1 >/dev/null + [ "$SETDEFAULT" = "yes" ] && [ "$(uci -q openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default scope global metric 1 nexthop via $interface_gw dev $interface_if 2>&1 >/dev/null ip route replace default via $interface_gw dev $interface_if table 991337 2>&1 >/dev/null && SETROUTE=true fi fi @@ -97,7 +97,7 @@ set_route6() { fi if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep ':')" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" - [ "$SETDEFAULT" = "yes" ] && ip -6 route replace default scope global nexthop via $interface_gw dev $interface_if 2>&1 >/dev/null + [ "$SETDEFAULT" = "yes" ] && [ "$(uci -q openmptcprouter.settings.defaultgw)" != "0" ] && ip -6 route replace default scope metric 1 global nexthop via $interface_gw dev $interface_if 2>&1 >/dev/null ip -6 route replace default via $interface_gw dev $interface_if table 991337 2>&1 >/dev/null && SETROUTE=true fi fi @@ -700,8 +700,10 @@ if [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then esac fi -default_gw=$(ip route show default | grep -v "metric" | awk '/default/ {print $3}') -default_gw6=$(ip -6 route show default | grep -v "metric" | awk '/default/ {print $3}') +#default_gw=$(ip route show default | awk '/default/ {print $3}') +#default_gw6=$(ip -6 route show default | awk '/default/ {print $3}') +default_gw=$(ip route get 1.1.1.1 | grep via | awk '{print $3}') +default_gw6=$(ip -6 route get 2606:4700:4700::1111 | grep via | awk '{print $3}') #current_interface_gw=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway") interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') @@ -988,7 +990,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om fi if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Current route: $(ip r)" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw : $default_gw - Current route: $(ip r)" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null if [ "$(pgrep openmptcprouter-vps)" = "" ]; then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 @@ -1097,7 +1099,7 @@ if [ "$multipath_config" = "master" ]; then [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" - ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null + ip route replace default scope global metric 1 nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null fi config_load openmptcprouter #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then From 5e73f8976495d52f7acb45d7170593772c1fbe8a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Jun 2022 14:07:45 +0200 Subject: [PATCH 0786/2059] Fix on status view --- .../luci-static/resources/openmptcprouter/css/wanstatus.css | 2 ++ .../luasrc/view/openmptcprouter/wanstatus.htm | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css index 35ad4be96..9dd88fd72 100644 --- a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css +++ b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css @@ -332,4 +332,6 @@ Thanks :)*/ } .spaceline { height: 55px; + z-index: -10; + position: relative; } diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index be05b035e..fe573ae19 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -101,7 +101,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm temp += '
  • '; if (mArray.wans) { - temp += ''; + temp += ''; for( var j = 1; j < mArray.wans.length; j++ ) { temp += ''; From bde0b7bcfe1f751b6e98eb6ff95ff5af10bb125c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Jun 2022 14:08:15 +0200 Subject: [PATCH 0787/2059] Simplify config for RUTX --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index a4f2c2f6f..c2f77fe34 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -709,8 +709,8 @@ default_gw6=$(ip -6 route get 2606:4700:4700::1111 | grep via | awk '{print $3}' interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') -if [ -n "$(grep RUTX /etc/board.json)" ] && [ -n "$OMR_TRACKER_INTERFACE" ]; then - if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.device)" = "wwan0" ]; then +if [ -n "$(grep RUTX /etc/board.json)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + if [ "$OMR_TRACKER_DEVICE" = "wwan0" ]; then modemdata=$(omr-modemmanager '/sys/devices/platform/soc/60f8800.usb2/6000000.dwc3/xhci-hcd.1.auto/usb3/3-1' all) gen=$(echo $modemdata | cut -d ';' -f 5 | tr -d '\n') if [ "$gen" = "gsm" ]; then @@ -752,7 +752,7 @@ if [ -n "$(grep RUTX /etc/board.json)" ] && [ -n "$OMR_TRACKER_INTERFACE" ]; the else echo "none" > /sys/class/leds/mob_ssid_5/trigger fi - elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.device)" = "wwan1" ]; then + elif [ "$OMR_TRACKER_DEVICE" = "wwan1" ]; then modemdata=$(omr-modemmanager '/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' all) gen=$(echo $modemdata | cut -d ';' -f 5 | tr -d '\n') if [ "$gen" = "gsm" ]; then From d16ab0859c20b097472a6c0f019a11aec11745bb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Jun 2022 14:08:37 +0200 Subject: [PATCH 0788/2059] Log when firewall reload --- openmptcprouter/files/etc/firewall.omr-server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/firewall.omr-server b/openmptcprouter/files/etc/firewall.omr-server index a3aaccd16..cbd8d719d 100644 --- a/openmptcprouter/files/etc/firewall.omr-server +++ b/openmptcprouter/files/etc/firewall.omr-server @@ -8,7 +8,7 @@ _enable_firewall_check() { set openmptcprouter.${server}.set_firewall=1 EOF } - +logger -t "firewall.omr-server" "Firewall reload, set server part firewall reloading" config_load openmptcprouter config_foreach _enable_firewall_check server uci -q commit firewall From 680ee18f6699d76b610b03a3cd84d92528dd37e2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Jun 2022 14:08:55 +0200 Subject: [PATCH 0789/2059] Simplify RUTX modem config --- .../files/etc/uci-defaults/1920-omr-network | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index bdb6a12c7..ee5922803 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -357,18 +357,10 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then set network.modem1.force_link='1' set network.modem1.device='/sys/devices/platform/soc/60f8800.usb2/6000000.dwc3/xhci-hcd.1.auto/usb3/3-1' set network.modem1.peerdns='0' - set network.wan_modem1=interface - set network.wan_modem1.proto='dhcp' - set network.wan_modem1.device='wwan0' - set network.wan_modem1.force_link='1' - set network.wan_modem1.multipath='on' - set network.wan_modem1.addlatency='0' - set network.wan_modem1.hostname='*' - set network.wan_modem1.defaultroute='0' - set network.wan_modem1.peerdns='0' - set network.wan_modem1.ip4table=wan + set network.modem1.multipath='on' + set network.modem1.defaultroute='0' commit network - add_list firewall.@zone[1].network='wan_modem1' + add_list firewall.@zone[1].network='modem1' commit firewall EOF if [ "$(mnf_info -n)" = "RUTX1200XXXX" ]; then @@ -382,18 +374,11 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then set network.modem2.force_link='1' set network.modem2.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' set network.modem2.peerdns='0' - set network.wan_modem2=interface - set network.wan_modem2.proto='dhcp' - set network.wan_modem2.device='wwan1' - set network.wan_modem2.force_link='1' - set network.wan_modem2.multipath='on' - set network.wan_modem2.addlatency='0' - set network.wan_modem2.hostname='*' - set network.wan_modem2.defaultroute='0' - set network.wan_modem2.peerdns='0' - set network.wan_modem2.ip4table=wan + set network.modem2.multipath='on' + set network.modem2.defaultroute='0' + set network.modem2.ip4table=wan commit network - add_list firewall.@zone[1].network='wan_modem2' + add_list firewall.@zone[1].network='modem2' commit firewall EOF fi From 3cb3b8057242f2ccb2b35acc1b8f927f5d98a4da Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Jun 2022 14:09:16 +0200 Subject: [PATCH 0790/2059] Cleaner firewall config --- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 709eaaf05..3719a41b0 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -226,12 +226,12 @@ fi allintf=$(uci -q get firewall.zone_wan.network) uci -q del firewall.zone_wan.network for intf in $allintf; do - uci -q add_list firewall.zone_wan.network=$intf + uci -q add_list firewall.zone_wan.network="${intf}" done allintf=$(uci -q get firewall.zone_vpn.network) uci -q del firewall.zone_vpn.network for intf in $allintf; do - uci -q add_list firewall.zone_vpn.network=$intf + uci -q add_list firewall.zone_vpn.network="${intf}" done uci -q batch <<-EOF >/dev/null From b869935ff747ce3eab7fc6f1efeff280d4dfeb46 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Jul 2022 21:44:51 +0200 Subject: [PATCH 0791/2059] Remove display of gre and loopback in MPTCP app --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index d853e8e49..e401c59f0 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -97,6 +97,9 @@ else end s = m:section(TypedSection, "interface", translate("Interfaces Settings")) +function s.filter(self, section) + return not section:match("^oip.*") and not section:match("^lo.*") and section ~= "omrvpn" and section ~= "omr6in4" +end o = s:option(ListValue, "multipath", translate("Multipath TCP"), translate("One interface must be set as master")) o:value("on", translate("enabled")) o:value("off", translate("disabled")) From ea4289223cb8432dd7f800a136c9f20c2500f067 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Jul 2022 21:46:22 +0200 Subject: [PATCH 0792/2059] Add speed and duplex setting in network page --- .../luci-static/resources/tools/network.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/luci-mod-network/htdocs/luci-static/resources/tools/network.js index b08f84058..311242905 100644 --- a/luci-mod-network/htdocs/luci-static/resources/tools/network.js +++ b/luci-mod-network/htdocs/luci-static/resources/tools/network.js @@ -622,6 +622,23 @@ return baseclass.extend({ o = this.replaceOption(s, 'devadvanced', form.Flag, 'promisc', _('Enable promiscuous mode')); o.default = o.disabled; + o = this.replaceOption(s, 'devadvanced', form.Flag, 'autoneg', _('Autonegociation')); + o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', form.Value, 'speed', _('Speed')); + o.placeholder = dev ? dev.getSpeed() : ''; + o.default = ''; + o.rmempty = true; + o.datatype = 'uinteger'; + o.depends('autoneg', '0'); + + o = this.replaceOption(s, 'devadvanced', form.ListValue, 'duplex', _('Duplex')); + o.default = ''; + o.value('', _('unknown')); + o.value('half', _('half')); + o.value('full', _('full')); + o.depends('autoneg', '0'); + o = this.replaceOption(s, 'devadvanced', form.ListValue, 'rpfilter', _('Reverse path filter')); o.default = ''; o.value('', _('disabled')); From ca8d80bc06588b403c4a87f3ec1856b9d408cb0c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Jul 2022 13:54:34 +0200 Subject: [PATCH 0793/2059] Fix wizard --- .../luasrc/controller/openmptcprouter.lua | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 74a638186..5662c273f 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -301,9 +301,10 @@ function wizard_add() ucic:set("network",intf,"type","macvlan") ucic:set("network",intf .. "_dev","device") ucic:set("network",intf .. "_dev","type","macvlan") - ucic:set("network",intf .. "_dev","ifname",masterinf) + ucic:set("network",intf .. "_dev","ifname",masterintf) ucic:set("network",intf .. "_dev","mode","vepa") ucic:set("network",intf .. "_dev","name",intf) + ucic:set("network",intf,"device",intf) ucic:set("network",intf,"masterintf",masterintf) elseif typeintf == "" and ifname ~= "" and (proto == "static" or proto == "dhcp" or proto == "dhcpv6") then ucic:set("network",intf,"device",ifname) @@ -336,11 +337,14 @@ function wizard_add() ucic:set("network",intf .. "_dev","name",ifname) end end - if typeintf ~= "macvlan" and ucic:get("network",intf .. "_dev","type") == "macvlan" then - ucic:delete("network",intf .. "_dev","type") - ucic:delete("network",intf .. "_dev","mode") - ucic:delete("network",intf .. "_dev","ifname") - ucic:delete("network",intf .. "_dev","macaddr") + if typeintf ~= "macvlan" then + if ucic:get("network",intf .. "_dev","type") == "macvlan" then + ucic:delete("network",intf .. "_dev","type") + ucic:delete("network",intf .. "_dev","mode") + ucic:delete("network",intf .. "_dev","ifname") + ucic:delete("network",intf .. "_dev","macaddr") + end + ucic:delete("network",intf,"masterintf") end if proto == "pppoe" then ucic:set("network",intf,"pppd_options","persist maxfail 0") @@ -373,17 +377,17 @@ function wizard_add() ucic:set("network",intf,"defaultroute",0) ucic:set("network",intf,"peerdns",0) if ipaddr ~= "" then - ucic:set("network",intf,"ipaddr",ipaddr) - ucic:set("network",intf,"netmask",netmask) - ucic:set("network",intf,"gateway",gateway) + ucic:set("network",intf,"ipaddr",ipaddr:gsub("%s+", "")) + ucic:set("network",intf,"netmask",netmask:gsub("%s+", "")) + ucic:set("network",intf,"gateway",gateway:gsub("%s+", "")) else ucic:set("network",intf,"ipaddr","") ucic:set("network",intf,"netmask","") ucic:set("network",intf,"gateway","") end if ip6addr ~= "" then - ucic:set("network",intf,"ip6addr",ip6addr) - ucic:set("network",intf,"ip6gw",ip6gw) + ucic:set("network",intf,"ip6addr",ip6addr:gsub("%s+", "")) + ucic:set("network",intf,"ip6gw",ip6gw:gsub("%s+", "")) else ucic:set("network",intf,"ip6addr","") ucic:set("network",intf,"ip6gw","") @@ -593,8 +597,8 @@ function wizard_add() serversnb = serversnb + 1 end ucic:set("openmptcprouter",server,"server") - ucic:set("openmptcprouter",server,"username",openmptcprouter_vps_username) - ucic:set("openmptcprouter",server,"password",openmptcprouter_vps_key) + ucic:set("openmptcprouter",server,"username",openmptcprouter_vps_username:gsub("%s+", "")) + ucic:set("openmptcprouter",server,"password",openmptcprouter_vps_key:gsub("%s+", "")) ucic:set("openmptcprouter",server,"disabled",openmptcprouter_vps_disabled) ucic:set_list("openmptcprouter",server,"ip",aserverips) ucic:set("openmptcprouter",server,"port","65500") From b1f3f3aa881fd2869e46e4977f792375ebd5129a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 8 Jul 2022 20:41:52 +0200 Subject: [PATCH 0794/2059] Use ip instead of ifconfig in multipath --- mptcp/files/usr/bin/multipath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index c616044e4..6125f1759 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -133,7 +133,7 @@ if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then else ID=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $3}') IFF=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $4}') - IP=$(ifconfig $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') + IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') [ -z "$ID" ] && ID=$(ip mptcp endpoint show | grep "$IP" | awk '{print $3}') RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null From ae667515aba88bd53831e4add56afeffbbcbff55 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 11 Jul 2022 20:21:59 +0200 Subject: [PATCH 0795/2059] Add changes for v2ray fw rules modifications support --- .../files/etc/init.d/openmptcprouter-vps | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index f64b78c56..503cf491c 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1010,7 +1010,7 @@ _vps_firewall_redirect_port() { checkfw="" if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi") + checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- V2Ray to ${dest_ip}:${dest_port}") else comment="" [ -n "$src_dip" ] && { @@ -1018,44 +1018,45 @@ _vps_firewall_redirect_port() { iptables-save --counters | sed "s:-d $src_dip/32::g" | iptables-restore -w } [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment}") + checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi}") + checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment}") + checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") fi fi if [ "$checkfw" = "" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "V2Ray to '${dest_ip}':'${dest_port}'"}' _set_json "shorewallopen" "$settings" + [ -z "$dest_port" ] && dest_port="$src_dport" settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","destip" : "'$dest_ip'","destport" : "'$dest_port'","proto" : "'${protoi}'"}' _set_json "v2rayredirect" "$settings" fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}$") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}$") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}$") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment}$") + vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi}$") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi}$") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") else [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment}$") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment}$") + vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") fi fi fi @@ -1072,18 +1073,21 @@ _vps_firewall_close_port() { src_dport=$(echo $line | awk '{print $5}' | tr -d "\n") source_port=$(echo $line | awk '{print $6}' | tr -d "\n") source_dip=$(echo $line | awk '{print $7}' | tr -d "\n") + comment=$(echo $line | awk -F' --- ' '{print $2}' | tr -d "\n") [ "$source_dip" = "#" ] && source_dip="" source_ip=$(echo $line | awk '{print $2}' | awk -F ":" '{print $2}' | tr -d "\n") if [ "$source_port" = "-" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","source_dip": "'$source_dip'","source_ip": "'$source_ip'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","source_dip": "'$source_dip'","source_ip": "'$source_ip'","comment" : "'$comment'"}' elif [ "$source_ip" != "" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","source_ip": "'$source_ip'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","source_ip": "'$source_ip'","comment" : "'$comment'"}' else - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","comment" : "'$comment'"}' fi _set_json "shorewallclose" "$settings" [ "$type" = "ACCEPT" ] && { - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'"}' + destip=$(echo $comment | awk '{print $3}' | awk -F: '{print $1}') + destport=$(echo $comment | awk '{print $3}' | awk -F: '{print $2}') + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","destip" : "'$destip'","destport": "'$destport'"}' _set_json "v2rayunredirect" "$settings" } } @@ -1097,18 +1101,19 @@ _vps_firewall_close_port() { src_dport=$(echo $line | awk '{print $5}' | tr -d "\n") source_port=$(echo $line | awk '{print $6}' | tr -d "\n") source_dip=$(echo $line | awk '{print $7}' | tr -d "\n") + comment=$(echo $line | awk -F' --- ' '{print $2}' | tr -d "\n") [ "$source_dip" = "#" ] && source_dip="" source_ip=$(echo $line | awk '{print $2}' | awk -F ":" '{print $2}' | tr -d "\n") if [ "$source_port" = "-" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","source_dip": "'$source_dip'","source_ip": "'$source_ip'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","source_dip": "'$source_dip'","source_ip": "'$source_ip'","comment" : "'$comment'"}' elif [ "$source_ip" != "" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","source_dip": "'$source_dip'","source_ip": "'$source_ip'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","source_dip": "'$source_dip'","source_ip": "'$source_ip'","comment" : "'$comment'"}' else - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","comment" : "'$comment'"}' fi _set_json "shorewallclose" "$settings" [ "$type" = "ACCEPT" ] && { - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'"}' + settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","comment" : "'$comment'"}' _set_json "v2rayunredirect" "$settings" } } From 171cc553b2855f4bb6f8af94c98dd951fa6f6eec Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Jul 2022 08:20:19 +0200 Subject: [PATCH 0796/2059] Force set firewall when wizard is saved --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 5662c273f..9786f8914 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -602,6 +602,7 @@ function wizard_add() ucic:set("openmptcprouter",server,"disabled",openmptcprouter_vps_disabled) ucic:set_list("openmptcprouter",server,"ip",aserverips) ucic:set("openmptcprouter",server,"port","65500") + ucic:set("openmptcprouter",server,"set_firewall","1") ucic:save("openmptcprouter") end From d84c079b96f013d3a37bda78cdd97f6e6120784f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Jul 2022 17:11:51 +0200 Subject: [PATCH 0797/2059] Force config retrieve if server IP change --- .../luasrc/controller/openmptcprouter.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 9786f8914..071aa1805 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -600,7 +600,12 @@ function wizard_add() ucic:set("openmptcprouter",server,"username",openmptcprouter_vps_username:gsub("%s+", "")) ucic:set("openmptcprouter",server,"password",openmptcprouter_vps_key:gsub("%s+", "")) ucic:set("openmptcprouter",server,"disabled",openmptcprouter_vps_disabled) - ucic:set_list("openmptcprouter",server,"ip",aserverips) + if ucic:get("openmptcprouter",server,"ip") ~= aserverips then + ucic:set_list("openmptcprouter",server,"ip",aserverips) + if ucic:get("openmptcprouter",server,"master") == "1" then + ucic:set("openmptcprouter",server,"get_config","1") + end + end ucic:set("openmptcprouter",server,"port","65500") ucic:set("openmptcprouter",server,"set_firewall","1") ucic:save("openmptcprouter") From 3865cfa800613bf9fdf43239d894829f329d8a22 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Jul 2022 17:12:22 +0200 Subject: [PATCH 0798/2059] Gateway is fixed for OpenVPN bonding --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 503cf491c..94608a5f5 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -835,6 +835,7 @@ _set_vpn_ip() { [ -z "$vpnip_remote" ] && [ -n "$vpnifname" ] && vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep kernel | awk '{print $1}' | tr -d "\n") [ -z "$vpnip_remote" ] && [ -n "$vpnifname" ] && vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep "proto static src" | awk '{print $3}' | tr -d "\n") [ -z "$vpnip_remote" ] && vpnip_remote=$(ifstatus omrvpn | jsonfilter -e '@.route[0].nexthop') + [ -z "$vpnip_remote" ] && [ "$vpnifname" = "bonding-omrvpn" ] && vpnip_remote="10.255.248.1" ula="$(uci -q get network.globals.ula_prefix)" ula_current="$(echo "$vps_config" | jsonfilter -q -e '@.ip6in4.ula')" if [ "$vpnip_remote" != "" ] && [ "$vpnip_local" != "" ] && ([ "$vpnip_remote" != "$vpnip_remote_current" ] || [ "$vpnip_local" != "$vpnip_local_current" ] || [ "$ula" != "$ula_current" ]); then From 1243f58e21833f699b1a9d08cb9af42b679c7851 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Jul 2022 17:12:41 +0200 Subject: [PATCH 0799/2059] Remove settings when OpenVPN is not used --- openmptcprouter/files/etc/init.d/openvpnbonding | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/openvpnbonding b/openmptcprouter/files/etc/init.d/openvpnbonding index f3c085802..2df9d5897 100755 --- a/openmptcprouter/files/etc/init.d/openvpnbonding +++ b/openmptcprouter/files/etc/init.d/openvpnbonding @@ -56,6 +56,23 @@ _disable_openvpnbonding() name=$1 if [ "$(echo $name | grep omr_bonding)" != "" ]; then uci -q set openvpn.${name}.enabled='0' + uci -q batch <<-EOF >/dev/null + del network.omrvpn.bonding_policy + del network.omrvpn.packets_per_slave + del network.omrvpn.xmit_hash_policy + del network.omrvpn.all_slaves_active + del network.omrvpn.netmask + del network.omrvpn.ipaddr + del network.omrvpn.link_monitoring + del network.omrvpn.miimon + del network.omrvpn.downdelay + del network.omrvpn.updelay + del network.omrvpn.use_carrier + del network.omrvpn.force_link + del network.omrvpn.slaves + commit network + EOF + fi } From 4a3bde8e098416fe12b46860e85be1b80cf0f115 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Jul 2022 21:34:36 +0200 Subject: [PATCH 0800/2059] Add MPTCP version support to use VPS with 5.4 kernel when router use 5.15 --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 94608a5f5..723c52b55 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -728,6 +728,7 @@ _set_mptcp_vps() { scheduler_current="$(echo "$vps_config" | jsonfilter -q -e '@.mptcp.scheduler')" syn_retries_current="$(echo "$vps_config" | jsonfilter -q -e '@.mptcp.syn_retries')" congestion_control_current="$(echo "$vps_config" | jsonfilter -q -e '@.network.congestion_control')" + mptcp_version_current="$(echo "$vps_config" | jsonfilter -q -e '@.mptcp.version')" mptcp_enabled="$(uci -q get network.globals.multipath)" if [ "$mptcp_enabled" = "disable" ]; then mptcp_enabled="0" @@ -739,9 +740,11 @@ _set_mptcp_vps() { scheduler="$(uci -q get network.globals.mptcp_scheduler)" syn_retries="$(uci -q get network.globals.mptcp_syn_retries)" congestion="$(uci -q get network.globals.congestion)" + mptcp_version="0" + [ ! -f /proc/sys/net/mptcp/mptcp_enabled ] && mptcp_version="1" [ -z "$congestion" ] && congestion="bbr" - if [ "$mptcp_enabled_current" != "$mptcp_enabled" ] || [ "$checksum_current" != "$checksum" ] || ([ "$path_manager_current" != "" ] && [ "$path_manager_current" != "$path_manager" ]) || ([ "$scheduler_current" != "" ] && [ "$scheduler_current" != "$scheduler" ]) || ([ "$syn_retries_current" != "" ] && [ "$syn_retries_current" != "$syn_retries" ]) || [ "$congestion_control_current" != "$congestion" ]; then - settings='{"enabled" : "'$mptcp_enabled'", "checksum": "'$checksum'","path_manager": "'$path_manager'","scheduler": "'$scheduler'","syn_retries": "'$syn_retries'","congestion_control": "'$congestion'"}' + if [ "$mptcp_enabled_current" != "$mptcp_enabled" ] || [ "$checksum_current" != "$checksum" ] || ([ "$path_manager_current" != "" ] && [ "$path_manager_current" != "$path_manager" ]) || ([ "$scheduler_current" != "" ] && [ "$scheduler_current" != "$scheduler" ]) || ([ "$syn_retries_current" != "" ] && [ "$syn_retries_current" != "$syn_retries" ]) || [ "$congestion_control_current" != "$congestion" ] || [ "$mptcp_version_current" != "$mptcp_version" ]; then + settings='{"enabled" : "'$mptcp_enabled'", "checksum": "'$checksum'","path_manager": "'$path_manager'","scheduler": "'$scheduler'","syn_retries": "'$syn_retries'","congestion_control": "'$congestion'","version": "'$mptcp_version'"}' echo $(_set_json "mptcp" "$settings") else echo 1 From debdc682e15227e4c7ce8ff40c6e35df7feb3d9c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Jul 2022 15:27:03 +0200 Subject: [PATCH 0801/2059] Fix adding latency to interface --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 2463d20fa..9954d850a 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -104,7 +104,7 @@ omr_set_settings() { tc qdisc del dev ${ifname} root netem 2>&1 >/dev/null fi if [ "$addlatency" != "0" ]; then - if [ "$(tc qdisc show dev $ifname | grep delay)" != "" ]; then + if [ "$(tc qdisc show dev $ifname | grep delay)" = "" ]; then tc qdisc add dev ${ifname} root netem delay ${addlatency}ms 2>&1 >/dev/null elif [ "$(tc qdisc show dev $ifname | awk '/delay/ { print $10 }' | sed 's/ms//')" != "$addlatency" ]; then tc qdisc replace dev ${ifname} root netem delay ${addlatency}ms 2>&1 >/dev/null From 966d58c0cf201571023c41db707a82f6489d0f12 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Jul 2022 15:28:56 +0200 Subject: [PATCH 0802/2059] Add mptcp_stale_loss_cnt sysctl setting for 5.15 kernel --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 5 +++++ mptcp/files/etc/init.d/mptcp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index e401c59f0..b95eca4ff 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -65,6 +65,11 @@ if uname.release:sub(1,4) == "5.15" then o.datatype = "uinteger" o.rmempty = false o.default = 1 + + o = s:option(Value, "mptcp_stale_loss_cnt", translate("The number of MPTCP-level retransmission intervals with no traffic and pending outstanding data on a given subflow required to declare it stale")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 4 else o = s:option(Value, "mptcp_fullmesh_num_subflows", translate("Fullmesh subflows for each pair of IP addresses")) o.datatype = "uinteger" diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 29f4a354e..4f26ff74e 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -29,6 +29,7 @@ global_multipath_settings() { config_get mptcp_rr_cwnd_limited globals mptcp_rr_cwnd_limited config_get mptcp_rr_num_segments globals mptcp_rr_num_segments config_get mptcp_version globals mptcp_version "0" + config_get mptcp_stale_loss_cnt globals mptcp_stale_loss_cnt "4" [ "$multipath" = "enable" ] && multipath_status=1 @@ -51,6 +52,7 @@ global_multipath_settings() { ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null [ -z "$mptcp_add_addr_timeout" ] || sysctl -qew net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" [ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.checksum_enabled="$mptcp_checksum" + [ -z "$mptcp_stale_loss_cnt" ] || sysctl -qew net.mptcp.stale_loss_cnt="$mptcp_stale_loss_cnt" fi [ -z "$congestion" ] || sysctl -qew net.ipv4.tcp_congestion_control="$congestion" } From a614a47da2720564d6f2d249b247cf3fd3264240 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 23 Jul 2022 09:23:27 +0200 Subject: [PATCH 0803/2059] Add latency in post-tracking --- .../usr/share/omr/post-tracking.d/post-tracking | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index c2f77fe34..615c0fad2 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1556,6 +1556,21 @@ fi fi } +if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + addlatency=$(uci -q get network.${OMR_TRACKER_INTERFACE}.addlatency) + [ -z "$addlatency" ] && addlatency="0" + if [ "$addlatency" = "0" ] && [ "$(tc qdisc show dev $OMR_TRACKER_DEVICE | grep delay)" != "" ]; then + tc qdisc del dev ${OMR_TRACKER_DEVICE} root netem 2>&1 >/dev/null + fi + if [ "$addlatency" != "0" ]; then + if [ "$(tc qdisc show dev $OMR_TRACKER_DEVICE | grep delay)" = "" ]; then + tc qdisc add dev ${OMR_TRACKER_DEVICE} root netem delay ${addlatency}ms 2>&1 >/dev/null + elif [ "$(tc qdisc show dev $OMR_TRACKER_DEVICE | awk '/delay/ { print $10 }' | sed 's/ms//')" != "$addlatency" ]; then + tc qdisc replace dev ${OMR_TRACKER_DEVICE} root netem delay ${addlatency}ms 2>&1 >/dev/null + fi + fi +fi + # If a service is down, force restart it if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(pgrep ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then _log "Can't find Shadowsocks, restart it..." From 2c57ab4d43fae55451f5efa3a6a0d60216d2d4d4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 24 Jul 2022 18:32:24 +0200 Subject: [PATCH 0804/2059] Update mptcpd --- mptcpd/Makefile | 7 ++++--- mptcpd/patches/endian.patch | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 mptcpd/patches/endian.patch diff --git a/mptcpd/Makefile b/mptcpd/Makefile index f234e8362..cb6f95f6d 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter project +# Copyright (C) 2020-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter project # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mptcpd PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/intel/mptcpd.git -PKG_SOURCE_VERSION:=df4ea048cd3821f749bf06e0d01bb7d79faac812 +PKG_SOURCE_VERSION:=88bea6802379ee1cdbcba4817351b63fd1489537 PKG_VERSION:=0.9-$(PKG_SOURCE_VERSION) PKG_RELEASE:=1 PKG_MAINTAINER:=Ycarus (Yannick Chabanois) @@ -36,7 +36,8 @@ endef CONFIGURE_ARGS += \ --disable-doxygen-doc \ - --disable-logging + --disable-logging \ + --with-kernel=upstream TARGET_CFLAGS += -Wno-unused-result -Wno-format-nonliteral diff --git a/mptcpd/patches/endian.patch b/mptcpd/patches/endian.patch new file mode 100644 index 000000000..72686126d --- /dev/null +++ b/mptcpd/patches/endian.patch @@ -0,0 +1,19 @@ +--- a/include/mptcpd/private/sockaddr.h 2022-07-24 18:29:37.995613204 +0200 ++++ b/include/mptcpd/private/sockaddr.h 2022-07-24 18:30:53.802312010 +0200 +@@ -24,6 +24,16 @@ + * These macros may be used in place of @c htons() or @c htonl() when + * initializing an IPv4 address or IP port constant at compile-time. + */ ++#ifndef __bswap_constant_16 ++#define __bswap_constant_16(x) \ ++ ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) ++#endif ++#ifndef __bswap_constant_32 ++#define __bswap_constant_32(x) \ ++ ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \ ++ | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) ++#endif ++ + ///@{ + #if __BYTE_ORDER == __LITTLE_ENDIAN + # define MPTCPD_CONSTANT_HTONS(hs) __bswap_constant_16(hs) From 8cde301b92c8bfbcc80b3827a8e9e6a0eb30389a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 27 Jul 2022 13:29:30 +0200 Subject: [PATCH 0805/2059] Fix static route and errors in log --- mptcp/files/etc/init.d/mptcp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 4f26ff74e..99cd7d0db 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -170,6 +170,7 @@ interface_multipath_settings() { [ -n "$(ifconfig | grep $iface)" ] || return 0 [ "$(echo $iface | grep _dev)" != "" ] && return 0 [ "$(echo $iface | grep '^if')" != "" ] && return 0 + [ "$iface" = "lo" ] && return 0 if [ "$mode" = "master" ]; then multipath "$iface" "on" @@ -262,8 +263,8 @@ interface_multipath_settings() { EOF else #echo "Add routes for $ipaddr table $id" - [ -n "$ipaddr" ] && ip rule add from $ipaddr table $id pref 0 - ip rule add oif $iface table $id pref 0 + [ -n "$ipaddr" ] && [ -z "$(ip rule show from $ipaddr table $id)" ] && ip rule add from $ipaddr table $id pref 0 + [ -z "$(ip rule show oif $iface table $id)" ] && ip rule add oif $iface table $id pref 0 ip route replace $network/$netmask dev $iface scope link metric $id 2>&1 >/dev/null ip route replace $network/$netmask dev $iface scope link table $id 2>&1 >/dev/null ip route replace default via $gateway dev $iface table $id 2>&1 >/dev/null @@ -389,11 +390,15 @@ set_multipath() { exist=1 fi done - [ "$exist" = "0" ] && multipath $iface off + [ "$exist" = "0" ] && { + multipath $iface off + } done } add_route() { + config_get disabled "$1" disabled + [ "$disabled" = "1" ] && return 0 config_get target "$1" target routeset="$target" config_get netmask "$1" netmask @@ -417,10 +422,14 @@ add_route() { [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$interface" | jsonfilter -q -e '@["device"]') [ -n "$iface" ] && routeset="$routeset dev $iface" logger -t "MPTCP" "Add route $routeset" - [ -n "$routeset" ] && ip route replace $routeset 2>&1 >/dev/null + [ -n "$routeset" ] && { + ip route replace ${routeset} 2>&1 >/dev/null + } } add_route6() { + config_get disabled "$1" disabled + [ "$disabled" = "1" ] && return 0 config_get target "$1" target routeset="$target" config_get gateway "$1" gateway @@ -438,7 +447,9 @@ add_route6() { [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$interface" | jsonfilter -q -e '@["device"]') [ -n "$iface" ] && routeset="$routeset dev $iface" logger -t "MPTCP" "Add IPv6 route $routeset" - [ -n "$routeset" ] && ip -6 route replace $routeset 2>&1 >/dev/null + [ -n "$routeset" ] && { + ip -6 route replace ${routeset} 2>&1 >/dev/null + } } remove() { @@ -484,7 +495,7 @@ start_service() { config_foreach interface_multipath_settings interface $intf set_multipath config_foreach add_route route - config_foreach add_route route6 + config_foreach add_route6 route6 # If no master is defined, one interface is defined as master if [ "$master" = "" ] && [ "$intf" = "" ]; then intfmaster="$mptcpmintf" From 81f221ec07c569b4cf3db2c7ed8ebcd6ccd680f0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 27 Jul 2022 13:29:54 +0200 Subject: [PATCH 0806/2059] Fix when device have no IP and multipath command launched --- mptcp/files/usr/bin/multipath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 6125f1759..294c3aaab 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -134,7 +134,7 @@ else ID=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $3}') IFF=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $4}') IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') - [ -z "$ID" ] && ID=$(ip mptcp endpoint show | grep "$IP" | awk '{print $3}') + [ -z "$ID" ] && [ -n "$IP" ] && ID=$(ip mptcp endpoint show | grep "$IP" | awk '{print $3}') RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null case $TYPE in From 04c4161845ea9d580ff11fb94fb94bd9d9ed3194 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 27 Jul 2022 13:30:24 +0200 Subject: [PATCH 0807/2059] Fix MTU detection --- .../share/omr/post-tracking.d/post-tracking | 10 +++++---- openmptcprouter/files/bin/omr-mtu6 | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100755 openmptcprouter/files/bin/omr-mtu6 diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 615c0fad2..9fcfb89ca 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1376,7 +1376,8 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } - if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + #if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ]; then network_device=$(find_network_device ${OMR_TRACKER_INTERFACE}) mtu="" @@ -1449,7 +1450,8 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } - if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + #if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then network_device=$(find_network_device ${OMR_TRACKER_INTERFACE}) if [ -n "$network_device" ] && [ -n "$(uci -q get network.${network_device}.mtu)" ]; then mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) @@ -1459,13 +1461,13 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC } elif [ -n "$OMR_TRACKER_DEVICE_IP" ]; then [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && { - local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) + local mtu=$(omr-mtu6 $OMR_TRACKER_DEVICE_IP6 $serverip) [ -n "$mtu" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 } } || { - local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 1.1.1.1) + local mtu=$(omr-mtu6 $OMR_TRACKER_DEVICE_IP 2606:4700:4700::1111) [ -n "$mtu" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 diff --git a/openmptcprouter/files/bin/omr-mtu6 b/openmptcprouter/files/bin/omr-mtu6 new file mode 100755 index 000000000..df63bdd54 --- /dev/null +++ b/openmptcprouter/files/bin/omr-mtu6 @@ -0,0 +1,21 @@ +#!/bin/sh + +PKT_SIZE=1472 +INTERFACE="$1" +HOSTNAME="$2" + +#count=$(ping -q -w 1 -M do -c 1 -s $PKT_SIZE -I $INTERFACE $HOSTNAME | grep -cE 'Message too long|100% packet loss') +#count=$(ping -B -w 1 -M do -c 1 -s $PKT_SIZE -I $INTERFACE $HOSTNAME 2>&1 | grep -c 'Message too long') +count=$(ping -6 -B -w 2 -M do -c 3 -s $PKT_SIZE -I $INTERFACE $HOSTNAME 2>&1 | grep -cE 'Message too long|100% packet loss') + +while [ $count -ge 1 ]; do + PKT_SIZE=$((PKT_SIZE - 1)) + if [ "$PKT_SIZE" -lt "1252" ]; then + exit 0 + fi + #count=$(ping -q -w 1 -M do -c 1 -s $PKT_SIZE -I $INTERFACE $HOSTNAME | grep -cE 'Message too long|100% packet loss') + #count=$(ping -B -w 1 -M do -c 1 -s $PKT_SIZE -I $INTERFACE $HOSTNAME 2>&1 | grep -c 'Message too long') + count=$(ping -6 -B -w 2 -M do -c 3 -s $PKT_SIZE -I $INTERFACE $HOSTNAME 2>&1 | grep -cE 'Message too long|100% packet loss') +done + +printf "$((PKT_SIZE + 28))" \ No newline at end of file From bc139fb048539ef2b5fe68117b3ac754c62945e8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jul 2022 19:14:48 +0200 Subject: [PATCH 0808/2059] Fix status displayed gateway when a static route is set --- .../root/usr/libexec/rpcd/openmptcprouter | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index c609b4737..6c9792f45 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1244,18 +1244,10 @@ function interfaces_status() -- Detect WAN gateway status local gw_ping = "UP" local gw_ping6 = "UP" - if ifname ~= nil and not (ifname:match("^tun.*") or interface:match("^ovpn.*") or interface:match("^wg.*")) then - if proto ~= "dhcpv6" then - gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) - end - if ipv6 == "1" or ipv6 == "auto" then - gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) - end - end - if gateway == "" and proto ~= "dhcpv6" then gateway = get_gateway(interface) end + if gateway == "" and ifname ~= nil and ifname ~= "" and ipv6 ~= "1" and ipv6 ~= "auto" then if fs.access("/sys/class/net/" .. ifname) then gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep kernel | awk '/proto kernel/ {print $1}' | grep -v / | tr -d '\n'")) @@ -1264,6 +1256,11 @@ function interfaces_status() end end end + if ifname ~= nil and not (ifname:match("^tun.*") or interface:match("^ovpn.*") or interface:match("^wg.*")) then + if proto ~= "dhcpv6" and gateway == "" then + gateway = ut.trim(sys.exec("ip -4 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) + end + end if gateway6 == "" and (ipv6 == "1" or ipv6 == "auto") then gateway6 = get_gateway6(interface) end @@ -1275,6 +1272,11 @@ function interfaces_status() end end end + if ifname ~= nil and not (ifname:match("^tun.*") or interface:match("^ovpn.*") or interface:match("^wg.*")) then + if ipv6 == "1" or ipv6 == "auto" and gateway6 == ""then + gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) + end + end local signal = "" local operator = "" local phonenumber = "" From 2fa26a32382c8fedabad6dbe6b13444f9f707f6b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jul 2022 19:15:23 +0200 Subject: [PATCH 0809/2059] Fix MTU test and check if autorate is really running --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 9fcfb89ca..89b8dfbbe 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1372,6 +1372,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC traceboxmtutest() { omr_tracebox_mtu() { local serverip=$1 + [ "$serverip" != "${1#*[0-9].[0-9]}" ] && serverip="" [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" @@ -1446,6 +1447,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC traceboxmtutest() { omr_tracebox_mtu() { local serverip=$1 + [ "$serverip" != "${1#*:[0-9a-fA-F]}" ] && serverip="" [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" @@ -1467,7 +1469,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 } } || { - local mtu=$(omr-mtu6 $OMR_TRACKER_DEVICE_IP 2606:4700:4700::1111) + local mtu=$(omr-mtu6 $OMR_TRACKER_DEVICE_IP6 2606:4700:4700::1111) [ -n "$mtu" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 @@ -1703,6 +1705,11 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter sleep 5 fi +if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -z $(pgrep -f "autorate.sh ${OMR_TRACKER_INTERFACE}") ]; then + /etc/init.d/sqm-autorate restart >/dev/null 2>&1 + sleep 5 +fi + #if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then check_server_fw() { From 0fdca79728b4c3f8c5efff5af1a526c01ef860fc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jul 2022 19:16:01 +0200 Subject: [PATCH 0810/2059] Remove some not needed log --- .../files/etc/init.d/openmptcprouter-vps | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 723c52b55..9ac1e17b2 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -271,7 +271,7 @@ _set_ss_server_vps() { if [ "$current_mptcp" != "$mptcp" ] || [ "$current_obfs_plugin" != "$obfs_plugin" ] || [ "$current_obfs_type" != "$obfs_type" ] || [ "$current_port" != "$port" ] || [ "$current_method" != "$method" ] || [ "$current_key" != "$key" ] || [ "$current_ebpf" != "$ebpf" ] || [ "$current_obfs" != "$obfs" ] || [ "$current_fast_open" != "$fast_open" ] || [ "$current_no_delay" != "$no_delay" ]; then local settings settings='{"port": '$port',"method":"'$method'","fast_open":'$fast_open',"reuse_port":true,"no_delay":'$no_delay',"mptcp":'$mptcp',"key":"'$key'","ebpf":'$ebpf',"obfs":'$obfs',"obfs_plugin":"'$obfs_plugin'","obfs_type":"'$obfs_type'"}' - _set_json "shadowsocks" "$settings" + result=$(_set_json "shadowsocks" "$settings") fi } @@ -966,7 +966,7 @@ _vps_firewall_redirect_port() { fi if [ "$checkfw" = "" ]; then settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'$protoi'","fwtype" : "'$target'","ipproto" : "'$family'"}' - _set_json "shorewallopen" "$settings" + result=$(_set_json "shorewallopen" "$settings") fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then @@ -1036,10 +1036,10 @@ _vps_firewall_redirect_port() { fi if [ "$checkfw" = "" ]; then settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "V2Ray to '${dest_ip}':'${dest_port}'"}' - _set_json "shorewallopen" "$settings" + result=$(_set_json "shorewallopen" "$settings") [ -z "$dest_port" ] && dest_port="$src_dport" settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","destip" : "'$dest_ip'","destport" : "'$dest_port'","proto" : "'${protoi}'"}' - _set_json "v2rayredirect" "$settings" + result=$(_set_json "v2rayredirect" "$settings") fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then @@ -1087,12 +1087,12 @@ _vps_firewall_close_port() { else settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","comment" : "'$comment'"}' fi - _set_json "shorewallclose" "$settings" + result=$(_set_json "shorewallclose" "$settings") [ "$type" = "ACCEPT" ] && { destip=$(echo $comment | awk '{print $3}' | awk -F: '{print $1}') destport=$(echo $comment | awk '{print $3}' | awk -F: '{print $2}') settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","destip" : "'$destip'","destport": "'$destport'"}' - _set_json "v2rayunredirect" "$settings" + result=$(_set_json "v2rayunredirect" "$settings") } } done @@ -1115,10 +1115,10 @@ _vps_firewall_close_port() { else settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","fwtype" : "DNAT","ipproto" : "ipv6","comment" : "'$comment'"}' fi - _set_json "shorewallclose" "$settings" + result=$(_set_json "shorewallclose" "$settings") [ "$type" = "ACCEPT" ] && { settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","comment" : "'$comment'"}' - _set_json "v2rayunredirect" "$settings" + result=$(_set_json "v2rayunredirect" "$settings") } } done @@ -1694,7 +1694,7 @@ _backup_send() { logger -t "OMR-VPS" "Send backup file to server $servername" local backupjson backupjson='{"data": "'$backup_data'","sha256sum": "'$backup_sha256sum'"}' - _set_json "backuppost" "$backupjson" + result=$(_set_json "backuppost" "$backupjson") uci -q set openmptcprouter.$servername.lastbackup=$(date +%s) } } From 77ea978dd1364f1f52242f1b5700c822dcfa931d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Jul 2022 19:16:21 +0200 Subject: [PATCH 0811/2059] Remove not needed vnstat log --- openmptcprouter/files/etc/init.d/vnstat_backup | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/vnstat_backup b/openmptcprouter/files/etc/init.d/vnstat_backup index ea00cb864..3a1cf5112 100755 --- a/openmptcprouter/files/etc/init.d/vnstat_backup +++ b/openmptcprouter/files/etc/init.d/vnstat_backup @@ -38,9 +38,7 @@ backup_database() { } restore_database() { - if [ ! -f $BACKUP_FILE ]; then - logger -t $LOGGER_TAG -p err "cannot restore, backup file does not exist (yet)" - else + if [ -f $BACKUP_FILE ]; then logger -t $LOGGER_TAG -p info 'restoring database' [ ! -d $VNSTAT_DIR ] && mkdir $VNSTAT_DIR /bin/tar -xzf $BACKUP_FILE -C $VNSTAT_DIR From 5932ad876d52491487abdecab6c35ec66a1b5899 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jul 2022 12:47:20 +0200 Subject: [PATCH 0812/2059] Update ndpi-netfilter2 --- ndpi-netfilter2/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 2c0377aa8..d218d7daa 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=3 -PKG_REV:=59f295ba86110f2642f76eb967b041c4108fedd5 +PKG_REV:=b19e6392cf0c7d51c44e076a91fc4db0cbbd6403 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git @@ -65,7 +65,7 @@ endef define Build/Compile (cd $(PKG_BUILD_DIR)/src/lib &&\ gcc -g -O2 -fPIC -DPIC -DNDPI_LIB_COMPILATION -I../../src/include/ -I../../src/lib/third_party/include/ ndpi_network_list_compile.c -o ndpi_network_list_compile &&\ - ./ndpi_network_list_compile -o ndpi_network_list.c.inc ndpi_network_list_std.yaml ndpi_network_list_tor.yaml) + ./ndpi_network_list_compile -o ndpi_network_list.c.inc ndpi_network_list_*.yaml) $(MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter endef From 0e1c92846d9f7d20ed710d6e1891069c58b2793b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Jul 2022 12:47:37 +0200 Subject: [PATCH 0813/2059] Remove crontab log --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 4a4a37962..fbb1a6912 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -6,6 +6,7 @@ uci -q batch <<-EOF >/dev/null set system.ntp.enable_server='1' set system.ntp.enabled='1' del system.ntp.server + set system.@system[-1].cronloglevel=9 add_list system.ntp.server='0.pool.ntp.org' add_list system.ntp.server='1.pool.ntp.org' add_list system.ntp.server='2.pool.ntp.org' @@ -38,7 +39,7 @@ fi EOF } -if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" ]; then +if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" ] && [ -z "$(uci show system | grep WAN_ETH)" ]; then uci -q batch <<-EOF >/dev/null add system led set system.@led[-1].sysfs='wan_wifi_4' From 018e8b47f4fb541eae3cbccfa08225b3a38ef6fc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 31 Jul 2022 16:28:59 +0200 Subject: [PATCH 0814/2059] Fix v2ray restart --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 89b8dfbbe..2a511e6cd 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1621,7 +1621,7 @@ if [ "$(pgrep dsvpn)" = "" ] && [ "$(uci -q get dsvpn.vpn.enable)" = "1" ] && [ /etc/init.d/dsvpn restart 2>&1 >/dev/null sleep 5 fi -if [ "$(pgrep v2ray)" = "" ] && [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ]; then +if [ "$(pgrep -f v2ray)" = "" ] && [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ]; then _log "Can't find V2Ray, restart it..." /etc/init.d/v2ray restart 2>&1 >/dev/null sleep 5 @@ -1690,9 +1690,10 @@ if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then echo 1 > /sys/bus/pci/rescan fi -if [ -f /etc/init.d/omr-bypass ] && [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep omr-bypass)" = "" ]; then +if [ -f /etc/init.d/omr-bypass ] && [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep -f omr-bypass)" = "" ]; then _log "Can't find omr-bypass rules, restart omr-bypass..." /etc/init.d/omr-bypass 2>&1 >/dev/null + sleep 5 fi if [ -f /etc/backup/installed_packages.txt ] && [ -n "$(grep overlay /etc/backup/installed_packages.txt)" ]; then From 4f53ff1fbaf063673e93d9704bbb2d4d0459dd46 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 31 Jul 2022 16:29:44 +0200 Subject: [PATCH 0815/2059] omr-bypass v2ray fixes --- .../root/etc/init.d/omr-bypass | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index b95a0a806..6b278ab43 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -471,18 +471,32 @@ _intf_rule_v2ray_rules() { #rule_name=$1 #[ "$rule_name" = "ss_rules" ] && rule_name="def" rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep v2r | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_dst)" != "" ] && [ "$(iptables-save | grep v2r_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I v2r_${rule_name}_dst 2 -m mark --mark 0x539$count -j RETURN + COMMIT + EOF + fi + if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_local_out)" != "" ] && [ "$(iptables-save | grep v2r_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then + iptables-restore -w --wait=60 --noflush <<-EOF + *nat -I v2r_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I v2r_${rule_name}_local_out 2 -m mark --mark 0x539$count -j RETURN + COMMIT + EOF + fi + if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep v2r_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then + iptables-restore -w --wait=60 --noflush <<-EOF + *nat -I v2r_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I v2r_${rule_name}_pre_src 2 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi + + if [ "$disableipv6" = "0" ]; then if [ "$(ip6tables-save | grep omr-bypass6 | grep omr6_dst_bypass_$intf)" = "" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF @@ -552,7 +566,9 @@ _intf_rule() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I omr-bypass 2 -m mark --mark 0x539$count -j RETURN -I omr-bypass-local 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I omr-bypass-local 2 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi @@ -610,7 +626,7 @@ _ss_rules_config() { iptables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I ssr_${rule_name}_dst 1 -m mark --mark 0x539 -j RETURN + -I ssr_${rule_name}_dst 2 -m mark --mark 0x539 -j RETURN -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539 -j RETURN -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 @@ -649,7 +665,7 @@ _v2ray_rules_config() { iptables-restore -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I v2r_${rule_name}_dst 1 -m mark --mark 0x539 -j RETURN + -I v2r_${rule_name}_dst 2 -m mark --mark 0x539 -j RETURN -I v2r_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 -I v2r_${rule_name}_local_out 2 -m mark --mark 0x539 -j RETURN -I v2r_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 From 643dd1e00ddb93a5fd4cf18350c9b8ebee024ea9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 31 Jul 2022 17:30:15 +0200 Subject: [PATCH 0816/2059] Add option to disable UDP transport via V2Ray --- .../luasrc/controller/openmptcprouter.lua | 4 ++++ .../luasrc/view/openmptcprouter/settings.htm | 6 ++++++ v2ray-core/files/etc/init.d/v2ray | 9 +++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 071aa1805..b73b045a1 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1153,6 +1153,10 @@ function settings_add() local shadowsocksudp = luci.http.formvalue("shadowsocksudp") or "0" ucic:set("openmptcprouter","settings","shadowsocksudp",shadowsocksudp) + -- Enable/disable v2ray udp + local shadowsocksudp = luci.http.formvalue("v2rayudp") or "1" + ucic:set("v2ray","main_transparent_proxy","redirect_udp",v2rayudp) + -- Enable/disable nDPI local ndpi = luci.http.formvalue("ndpi") or "1" ucic:set("openmptcprouter","settings","ndpi",ndpi) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index ebd013851..678d1d8e9 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -297,6 +297,12 @@ checked<% end %>> +
    + +
    + checked<% end %>> +
    +
    diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index f8772a0e1..284a8a761 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -414,10 +414,15 @@ add_v2ray_redirect_rules() { # This part need a rewrite v2ray-rules -f - v2ray-rules -l ${port} -L ${port} -s $OUTBOUND_SERVERS_V4 --rule-name def --src-default forward --dst-default forward --local-default forward + logger -t "v2ray" "v2ray-rules -l ${port} -L ${port} -s $OUTBOUND_SERVERS_V4 --rule-name def --src-default forward --dst-default forward --local-default forward" + commandline="-l ${port} -s $OUTBOUND_SERVERS_V4 --rule-name def --src-default forward --dst-default forward --local-default forward" + [ "$(uci -q get v2ray.main_transparent_proxy.redirect_udp)" = "1" ] && commandline="$commandline -L ${port}" + v2ray-rules $commandline [ "$(uci -q get v2ray.main.inbounds | grep omr6)" != "" ] && { v2ray-rules6 -f - v2ray-rules6 -l $((port+1)) -L $((port+1)) -s $OUTBOUND_SERVERS_V6 --rule-name def --src-default forward --dst-default forward --local-default forward + commandline="-l $((port+1)) -L $((port+1)) -s $OUTBOUND_SERVERS_V6 --rule-name def --src-default forward --dst-default forward --local-default forward" + [ "$(uci -q get v2ray.main_transparent_proxy.redirect_udp)" = "1" ] && commandline="$commandline -L ${port+1}" + v2ray-rules6 $commandline } [ -f /etc/init.d/omr-bypass ] && { logger -t "v2ray" "Reload omr-bypass rules" From 41314d1a5b0b3fdf76e6edb4a8e69b72da45e01e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 3 Aug 2022 21:36:39 +0200 Subject: [PATCH 0817/2059] Fix ndpi-netfilter2 compilation on ARM --- ndpi-netfilter2/Makefile | 20 +++++-------------- ndpi-netfilter2/patches/outline-atomics.patch | 10 ++++++++++ .../patches/skbuff-check_fix.patch | 11 ++++++++++ 3 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 ndpi-netfilter2/patches/outline-atomics.patch create mode 100644 ndpi-netfilter2/patches/skbuff-check_fix.patch diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index d218d7daa..0f737dbab 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -39,29 +39,19 @@ define Package/iptables-mod-ndpi/description nDPI is a ntop-maintained superset of the popular OpenDPI library endef -#CONFIGURE_CMD = ./autogen.sh -#CONFIGURE_ARGS += --with-pic -MAKE_PATH := ndpi-netfilter +CONFIGURE_CMD=./autogen.sh +CONFIGURE_ARGS += --with-pic + +MAKE_PATH:=ndpi-netfilter MAKE_FLAGS += \ KERNEL_DIR="$(LINUX_DIR)" \ MODULES_DIR="$(TARGET_MODULES_DIR)" \ ARCH="$(LINUX_KARCH)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ + CC="$(TARGET_CC)" \ NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter -define Build/Configure - cd $(PKG_BUILD_DIR) && \ - CC="" ./autogen.sh \ - --host="$(GNU_TARGET_NAME)" -# --with-pic \ -# CFLAGS="$(TARGET_CFLAGS)" \ -# HOST_CFLAGS="$(BUILD_CFLAGS)" \ -# BUILD_CPPFLAGS="$(TARGET_CPPLAGS)" \ -# BUILD_CFLAGS="$(TARGET_CFLAGS)" \ -# BUILD_LDFLAGS="$(TARGET_LDFLAGS)" -endef - define Build/Compile (cd $(PKG_BUILD_DIR)/src/lib &&\ gcc -g -O2 -fPIC -DPIC -DNDPI_LIB_COMPILATION -I../../src/include/ -I../../src/lib/third_party/include/ ndpi_network_list_compile.c -o ndpi_network_list_compile &&\ diff --git a/ndpi-netfilter2/patches/outline-atomics.patch b/ndpi-netfilter2/patches/outline-atomics.patch new file mode 100644 index 000000000..9fda12412 --- /dev/null +++ b/ndpi-netfilter2/patches/outline-atomics.patch @@ -0,0 +1,10 @@ +--- a/ndpi-netfilter/src/Makefile 2022-08-03 21:27:52.321058402 +0200 ++++ b/ndpi-netfilter/src/Makefile 2022-08-03 21:28:27.572452447 +0200 +@@ -5,6 +5,7 @@ + ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -I${src}/../libre -I${src}/${NDPI_SRC}/lib/third_party/include + ccflags-y += -DHAVE_CONFIG_H -DNDPI_LIB_COMPILATION -DOPENDPI_NETFILTER_MODULE -DNDPI_DETECTION_SUPPORT_IPV6 -g + ccflags-y += -Wno-declaration-after-statement ++ccflags-y += -mno-outline-atomics + #ccflags-y += -Wshadow-local + # Needed for pahole + #ccflags-y += -femit-struct-debug-detailed=any diff --git a/ndpi-netfilter2/patches/skbuff-check_fix.patch b/ndpi-netfilter2/patches/skbuff-check_fix.patch new file mode 100644 index 000000000..ccc90c3ab --- /dev/null +++ b/ndpi-netfilter2/patches/skbuff-check_fix.patch @@ -0,0 +1,11 @@ +--- a/ndpi-netfilter/src/Makefile 2022-08-03 19:15:39.849630013 +0200 ++++ b/ndpi-netfilter/src/Makefile 2022-08-03 19:15:57.481336123 +0200 +@@ -13,7 +13,7 @@ + KERNEL_DIR := /lib/modules/$(shell uname -r)/build + endif + +-ifeq ($(shell grep -qc userid $(KERNEL_DIR)/source/include/linux/skbuff.h),1) ++ifeq ($(shell grep -qc userid $(KERNEL_DIR)/include/linux/skbuff.h),1) + ccflags-y += -DUSE_HACK_USERID=1 + endif + From d5c8604783ae7d6146b66c8daa8bf6b89741373d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Aug 2022 08:34:13 +0200 Subject: [PATCH 0818/2059] Disable outline atomics only for ARM64 --- ndpi-netfilter2/patches/outline-atomics.patch | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ndpi-netfilter2/patches/outline-atomics.patch b/ndpi-netfilter2/patches/outline-atomics.patch index 9fda12412..bcb33a7fc 100644 --- a/ndpi-netfilter2/patches/outline-atomics.patch +++ b/ndpi-netfilter2/patches/outline-atomics.patch @@ -1,10 +1,12 @@ --- a/ndpi-netfilter/src/Makefile 2022-08-03 21:27:52.321058402 +0200 +++ b/ndpi-netfilter/src/Makefile 2022-08-03 21:28:27.572452447 +0200 -@@ -5,6 +5,7 @@ +@@ -5,6 +5,9 @@ ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -I${src}/../libre -I${src}/${NDPI_SRC}/lib/third_party/include ccflags-y += -DHAVE_CONFIG_H -DNDPI_LIB_COMPILATION -DOPENDPI_NETFILTER_MODULE -DNDPI_DETECTION_SUPPORT_IPV6 -g ccflags-y += -Wno-declaration-after-statement -+ccflags-y += -mno-outline-atomics ++ifeq ($(ARCH),arm64) ++ ccflags-y += -mno-outline-atomics ++endif #ccflags-y += -Wshadow-local # Needed for pahole #ccflags-y += -femit-struct-debug-detailed=any From b58311efbf0a24cc3f54f1afdf112e5786915fd1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Aug 2022 14:08:29 +0200 Subject: [PATCH 0819/2059] Fix ndpi-netfilter compilation on 5.4 --- ndpi-netfilter2/Makefile | 1 + ndpi-netfilter2/patches/outline-atomics.patch | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 0f737dbab..13ebc5f14 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -48,6 +48,7 @@ MAKE_FLAGS += \ KERNEL_DIR="$(LINUX_DIR)" \ MODULES_DIR="$(TARGET_MODULES_DIR)" \ ARCH="$(LINUX_KARCH)" \ + KERNEL_RELEASE="$(KERNEL_PATCHVER)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ CC="$(TARGET_CC)" \ NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter diff --git a/ndpi-netfilter2/patches/outline-atomics.patch b/ndpi-netfilter2/patches/outline-atomics.patch index bcb33a7fc..ef7f6fd5f 100644 --- a/ndpi-netfilter2/patches/outline-atomics.patch +++ b/ndpi-netfilter2/patches/outline-atomics.patch @@ -1,11 +1,13 @@ --- a/ndpi-netfilter/src/Makefile 2022-08-03 21:27:52.321058402 +0200 +++ b/ndpi-netfilter/src/Makefile 2022-08-03 21:28:27.572452447 +0200 -@@ -5,6 +5,9 @@ +@@ -5,6 +5,11 @@ ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -I${src}/../libre -I${src}/${NDPI_SRC}/lib/third_party/include ccflags-y += -DHAVE_CONFIG_H -DNDPI_LIB_COMPILATION -DOPENDPI_NETFILTER_MODULE -DNDPI_DETECTION_SUPPORT_IPV6 -g ccflags-y += -Wno-declaration-after-statement ++ifeq ($(KERNEL_RELEASE),5.15) +ifeq ($(ARCH),arm64) + ccflags-y += -mno-outline-atomics ++endif +endif #ccflags-y += -Wshadow-local # Needed for pahole From e61239f2039fc678761ed75a6711923ef1a55661 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 7 Aug 2022 20:08:50 +0200 Subject: [PATCH 0820/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/2454 --- openmptcprouter/files/etc/uci-defaults/1940-omr-dns | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index ecb75b2f5..d9986be6d 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -8,6 +8,11 @@ if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then set unbound.@unbound[-1].recursion="aggressive" set unbound.@unbound[-1].validator='1' set unbound.@unbound[-1].validator_ntp='1' + del unbound.ub_main.dns64_prefix + del unbound.ub_main.iface_wan + del unbound.ub_main.dhcp4_slaac6 + del unbound.ub_main.query_minimize + del unbound.ub_main.query_min_strict commit unbound EOF fi From d700848f06a924d2bd71b6cc1ff57102be88bafb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 7 Aug 2022 20:09:41 +0200 Subject: [PATCH 0821/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/2456 --- openmptcprouter/files/etc/init.d/openvpnbonding | 2 +- openmptcprouter/files/etc/uci-defaults/2020-omr-vpn | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openvpnbonding b/openmptcprouter/files/etc/init.d/openvpnbonding index 2df9d5897..77d0b8c75 100755 --- a/openmptcprouter/files/etc/init.d/openvpnbonding +++ b/openmptcprouter/files/etc/init.d/openvpnbonding @@ -55,7 +55,7 @@ _disable_openvpnbonding() { name=$1 if [ "$(echo $name | grep omr_bonding)" != "" ]; then - uci -q set openvpn.${name}.enabled='0' + uci -q del openvpn.${name}.enabled uci -q batch <<-EOF >/dev/null del network.omrvpn.bonding_policy del network.omrvpn.packets_per_slave diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index 4cb5a524c..75a947d27 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -38,7 +38,6 @@ if [ "$(uci -q get openvpn.omr.proto)" != "tcp-client" ]; then set openvpn.omr.port=65301 set openvpn.omr.cipher=AES-256-CBC set openvpn.omr.proto=tcp-client - set openvpn.omr.enabled=0 set openvpn.omr.ncp_disable=1 set openvpn.omr.auth_nocache=1 set openvpn.omr.client=1 From b9d5d51d428525d9334bac317268a938c12d1a47 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 7 Aug 2022 20:10:15 +0200 Subject: [PATCH 0822/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/2453 and add a limit on ICMP --- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 3719a41b0..b4493bb18 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -77,6 +77,7 @@ if [ "$(uci -q show firewall | grep Allow-All-Ping)" = "" ]; then set firewall.@rule[-1].dest='*' set firewall.@rule[-1].src='*' set firewall.@rule[-1].icmp_type='echo-request' + set firewall.@rule[-1].limit='1000/sec' commit firewall EOF fi @@ -195,6 +196,7 @@ if [ "$(uci -q get firewall.allowicmpipv6)" = "" ]; then set firewall.allowicmpipv6.src='wan' set firewall.allowicmpipv6.name='Allow IPv6 ICMP' set firewall.allowicmpipv6.family='ipv6' + set firewall.@rule[-1].limit='1000/sec' set firewall.allowicmpipv6.icmp_type='neighbour-advertisement neighbour-solicitation router-advertisement router-solicitation' commit firewall EOF @@ -244,6 +246,7 @@ if [ "$(uci -q get openmptcprouter.settings.sipalg)" != "1" ]; then uci -q batch <<-EOF >/dev/null set firewall.zone_lan.auto_helper='0' set firewall.zone_wan.auto_helper='0' + set firewall.zone_vpn.auto_helper='0' commit firewall EOF rmmod nf_nat_sip 2>&1 >/dev/null From 4435e86d5d8af976b0d6c592188beae5969f19bd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 8 Aug 2022 20:50:47 +0200 Subject: [PATCH 0823/2059] Update omr-6in4 --- omr-6in4/files/etc/init.d/omr-6in4 | 85 ++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/omr-6in4/files/etc/init.d/omr-6in4 b/omr-6in4/files/etc/init.d/omr-6in4 index 8a3e38a38..e29103a3d 100755 --- a/omr-6in4/files/etc/init.d/omr-6in4 +++ b/omr-6in4/files/etc/init.d/omr-6in4 @@ -1,5 +1,5 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2018 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2022 Ycarus (Yannick Chabanois) # shellcheck disable=SC2039 # vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : @@ -29,18 +29,10 @@ set_ipv6_state() { commit firewall EOF - if [ "$disable_ipv6" == "1" ]; then + if [ "$disable_ipv6" = "1" ]; then logger -t "omr-6in4" "Disable IPv6" uci -q batch <<-EOF >/dev/null - set dhcp.lan.ra_default="0" - set network.lan.ipv6="0" - delete network.lan.ipv6 - delete dhcp.lan.dhcpv6 - delete dhcp.lan.ra - delete dhcp.lan.ra_default - delete dhcp.lan.ra_management - delete dhcp.lan.ra_preference - unbound.ub_main.protocol='ip4_only' + set unbound.ub_main.protocol='ip4_only' commit unbound del_list v2ray.main.inbounds="omr6" commit v2ray @@ -48,34 +40,19 @@ set_ipv6_state() { config_load shadowsocks-libev config_foreach set_shadowsocks_address ss_redir "0.0.0.0" uci -q batch <<-EOF >/dev/null - commit network - commit dhcp commit shadowsocks-libev EOF [ ! -f /etc/wgetrc ] && cp /etc/wgetrc4 /etc/wgetrc else logger -t "omr-6in4" "Enable IPv6" uci -q batch <<-EOF >/dev/null - set dhcp.lan.dhcpv6="server" - set dhcp.lan.ra="server" - set dhcp.lan.ra_default="1" - set dhcp.lan.ra_preference="high" - set dhcp.lan.ra_management="1" - delete dhcp.lan.ra_flags - add_list dhcp.lan.ra_flags='managed-config' - set dhcp.lan.ra_slaac='1' - add_list dhcp.lan.ra_flags='other-config' - set network.lan.ipv6="1" set network.lan.delegate="0" set network.omr6in4.force_link=1 set network.omr6in4.metric=1 delete network.omr6in4.auto - unbound.ub_main.protocol='mixed' + set unbound.ub_main.protocol='mixed' commit unbound EOF - if [ "$(uci -q get network.lan.ip6assign)" = "" ]; then - uci -q set network.lan.ip6assign='60' - fi if [ "$(uci -q get network.globals.ula_prefix)" = "" ]; then r1=$(dd if=/dev/urandom bs=1 count=1 |hexdump -e '1/1 "%02x"') r2=$(dd if=/dev/urandom bs=2 count=1 |hexdump -e '2/1 "%02x"') @@ -106,12 +83,62 @@ set_ipv6_state() { fi } +set_ipv6_state_intf() { + local disable_ipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" + local intf="$1" + config_get ip4table $intf ip4table + config_get ipv6 $intf ipv6 "0" + if [ "$ip4table" = "lan" ]; then + if [ "$disable_ipv6" = "1" ] && [ "$ipv6" != "0" ]; then + logger -t "omr-6in4" "Disable IPv6 on ${intf}" + uci -q batch <<-EOF >/dev/null + set dhcp.${intf}.ra_default="0" + delete network.${intf}.ipv6 + delete dhcp.${intf}.dhcpv6 + delete dhcp.${intf}.ra + delete dhcp.${intf}.ra_default + delete dhcp.${intf}.ra_management + delete dhcp.${intf}.ra_preference + commit network + commit dhcp + EOF + elif [ "$disable_ipv6" != "1" ] && [ "$ipv6" != "1" ]; then + logger -t "omr-6in4" "Enable IPv6 on ${intf}" + uci -q batch <<-EOF >/dev/null + set dhcp.${intf}.dhcpv6="server" + set dhcp.${intf}.ra="server" + set dhcp.${intf}.ra_default="1" + set dhcp.${intf}.ra_preference="high" + set dhcp.${intf}.ra_management="1" + delete dhcp.${intf}.ra_flags + add_list dhcp.${intf}.ra_flags='managed-config' + set dhcp.${intf}.ra_slaac='1' + add_list dhcp.${intf}.ra_flags='other-config' + set network.${intf}.ipv6="1" + set network.${intf}.delegate="0" + EOF + if [ "$(uci -q get network.${intf}.ip6assign)" = "" ]; then + uci -q set network.${intf}.ip6assign='60' + fi + uci -q batch <<-EOF >/dev/null + commit network + commit dhcp + EOF + fi + fi +} start_service() { - [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && [ "$(uci -q get network.lan.ipv6)" != "1" ] && set_ipv6_state + [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && { + config_load network + config_foreach set_ipv6_state_intf interface + set_ipv6_state + } [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "0" ] && { + config_load network + config_foreach set_ipv6_state_intf interface ifdown omr6in4 - /etc/init.d/odhcpd stop + [ -z "$(/etc/init.d/odhcpd status | grep inactive)" ] && /etc/init.d/odhcpd stop return } [ "$(ifstatus omr6in4 | jsonfilter -e '@.up' | tr -d '\n')" != "true" ] && ifup omr6in4 From f116fa43c1e4ce18eca24fce7858f1390d63e2d8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Aug 2022 20:45:57 +0200 Subject: [PATCH 0824/2059] Update translations templates --- luci-app-mptcp/po/templates/mptcp.pot | 66 +- .../po/templates/openmptcprouter.pot | 630 ++++++++++-------- luci-app-sqm-autorate/po/templates/sqm.pot | 164 +++-- 3 files changed, 495 insertions(+), 365 deletions(-) diff --git a/luci-app-mptcp/po/templates/mptcp.pot b/luci-app-mptcp/po/templates/mptcp.pot index 770f34333..dfecf162a 100644 --- a/luci-app-mptcp/po/templates/mptcp.pot +++ b/luci-app-mptcp/po/templates/mptcp.pot @@ -26,11 +26,11 @@ msgstr "" msgid "Check if MPTCP between interface and server is working." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Congestion Control" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 msgid "Consecutive segments that should be sent for round robin" msgstr "" @@ -40,7 +40,7 @@ msgstr "" msgid "Current:" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Default is cubic" msgstr "" @@ -63,11 +63,11 @@ msgstr "" msgid "Established connections" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 msgid "Fill the congestion window on all subflows for round robin" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "" @@ -90,7 +90,7 @@ msgstr "" msgid "Interface" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 msgid "Interfaces Settings" msgstr "" @@ -135,11 +135,11 @@ msgid "Multipath Debug" msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "Multipath TCP" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 msgid "Multipath TCP SYN retries" msgstr "" @@ -151,11 +151,15 @@ msgstr "" msgid "Multipath TCP path-manager" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 msgid "Multipath TCP scheduler" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +msgid "Multipath TCP version" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 msgid "Netlink" msgstr "" @@ -166,7 +170,7 @@ msgid "" "ConfigureMPTCP for help." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "One interface must be set as master" msgstr "" @@ -182,7 +186,7 @@ msgstr "" msgid "Peak:" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "Re-create fullmesh subflows after a timeout" msgstr "" @@ -199,6 +203,12 @@ msgstr "" msgid "Test" msgstr "" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale" +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "" @@ -210,36 +220,36 @@ msgstr "" msgid "Waiting for command to complete..." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 msgid "backup" msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 msgid "default" msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 msgid "disable" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 msgid "disabled" msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 msgid "enable" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 msgid "enabled" msgstr "" @@ -277,10 +287,22 @@ msgstr "" msgid "kbit/s" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 msgid "master" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 msgid "ndiffports subflows number" msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "" +"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " +"connection" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" diff --git a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot index 2b76bb623..6aed2a49c 100644 --- a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot +++ b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot @@ -1,37 +1,37 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:302 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:312 msgid "A Dead Simple VPN key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:119 msgid "API username to retrieve personnalized settings from the server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:814 msgid "APN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:742 msgid "Accept IPv6 RA" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:156 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:164 msgid "Add a new server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:989 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1044 msgid "Add an interface" msgstr "" @@ -40,11 +40,11 @@ msgstr "" msgid "Advanced Settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 msgid "Advanced settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -54,18 +54,18 @@ msgstr "" msgid "All router settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:284 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "Authentication Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:878 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:894 msgid "Backup" msgstr "" @@ -74,7 +74,7 @@ msgstr "" msgid "Backup on server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:383 msgid "Balancing" msgstr "" @@ -82,31 +82,37 @@ msgstr "" msgid "Beta" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:312 msgid "Big time difference between the server and the router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 msgid "Bridge" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:620 msgid "Bridge can't have multipath enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "By default VPN is used for any traffic that is not TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:845 msgid "CHAP" msgstr "" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:961 +msgid "" +"Cake queue discipline is not set, autorate will only work after a reboot if " +"enabled here." +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 msgid "Can\\'t access and use server part" msgstr "" @@ -127,19 +133,19 @@ msgstr "" msgid "Can\\'t ping server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:423 msgid "China" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:596 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:655 msgid "Choose physical interface." msgstr "" @@ -147,20 +153,20 @@ msgstr "" msgid "Core temp:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:418 msgid "Country" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 msgid "Country settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 msgid "DHCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 msgid "DHCPv6" msgstr "" @@ -168,35 +174,35 @@ msgstr "" msgid "DNS issue: can\\'t resolve hostname" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:367 msgid "Debug" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:231 msgid "Default Proxy" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:345 msgid "Default VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:543 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:551 msgid "Delete" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:741 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:774 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 msgid "Device" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 -msgid "Disable HTTP test on Server API in status page" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 +msgid "Disable HTTP test on Server API" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:357 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 msgid "Disable ModemManager" msgstr "" @@ -208,11 +214,11 @@ msgstr "" msgid "Disable TCP Fast Open on Linux and Shadowsocks configuration" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 msgid "Disable default gateway" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:312 msgid "Disable default gateway, no internet if VPS are down" msgstr "" @@ -220,27 +226,27 @@ msgstr "" msgid "Disable external check" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:244 msgid "Disable gateway ping" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:249 msgid "Disable gateway ping check in status page" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:285 msgid "Disable interfaces auto rename" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:342 msgid "Disable multipath test using tracebox" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 msgid "Disable nDPI" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 msgid "Disable nDPI, used for protocols in OMR-ByPass" msgstr "" @@ -249,70 +255,82 @@ msgid "" "Disable ports redirection defined in firewall from server to this router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 msgid "Disable renaming interfaces" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 msgid "Disable route loop detection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 msgid "Disable server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:254 msgid "Disable server http test" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 msgid "Disable server ping" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:322 msgid "Disable server ping status check" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:337 msgid "Disable tracebox test" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:876 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:892 msgid "Disabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:988 msgid "Download speed (Kb/s)" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 msgid "Dynamic change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:402 msgid "Enable Bridge Acceleration" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 msgid "Enable DNS64" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:396 msgid "Enable Fast Patch offloading for connections" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 msgid "Enable IPv6" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:923 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:975 +msgid "Enable QoS" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:223 +msgid "Enable SIP ALG" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:942 msgid "Enable SQM" msgstr "" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 +msgid "Enable SQM autorate" +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:79 msgid "Enable ShadowSocks Obfuscating" msgstr "" @@ -321,21 +339,21 @@ msgstr "" msgid "Enable TCP Low Latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:372 msgid "Enable debug logs" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:886 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:875 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:891 msgid "Enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 msgid "Encryption" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:288 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "" @@ -343,37 +361,41 @@ msgstr "" msgid "Filesystem is readonly" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:902 +msgid "Force TTL" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 msgid "Force retrieve all keys from server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 msgid "Force retrieve settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:834 msgid "GPRS only" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:766 msgid "Gateway DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 msgid "Gateway IPv6 DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:290 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:300 msgid "Glorytun key" msgstr "" @@ -413,40 +435,40 @@ msgstr "" msgid "IPv4 TCP SYN retries2" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:653 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:661 msgid "IPv4 address" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:677 msgid "IPv4 gateway" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:663 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 msgid "IPv4 netmask" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 msgid "IPv6 Prefix" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 msgid "IPv6 address" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:705 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 msgid "IPv6 gateway" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 msgid "IPv6 route received" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 msgid "IPv6 settings" msgstr "" @@ -454,48 +476,48 @@ msgstr "" msgid "IPv6 tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 msgid "IPv6:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:222 msgid "If host support NAT64, you can enable DNS64 support." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 msgid "Interfaces settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "Key is retrieved from server API by default." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:129 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:435 msgid "LAN interfaces settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:832 msgid "LTE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:438 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:549 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:446 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:557 msgid "Label" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:452 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 msgid "Label for the interface" msgstr "" @@ -504,25 +526,25 @@ msgid "Last available backup on server:" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:329 msgid "Latest available version" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:335 msgid "Load:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:628 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 msgid "Looping route detected" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:314 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:316 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:324 msgid "MLVPN password" msgstr "" @@ -530,55 +552,55 @@ msgstr "" msgid "MPTCP is not enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:344 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 msgid "MPTCP may not be enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:393 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:913 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:929 msgid "MPTCP over VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:398 msgid "MPTCP over VPN settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 msgid "MacVLAN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:893 msgid "Master" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:377 msgid "Master interface selection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:409 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:421 msgid "Maximum scaling CPU frequency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:403 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 msgid "Minimum scaling CPU frequency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:824 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "Modem default" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:858 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:863 msgid "Modem init timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:601 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 msgid "ModemManager" msgstr "" @@ -586,51 +608,51 @@ msgstr "" msgid "More than one default VPN is enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 msgid "Multipath TCP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:787 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:793 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:795 msgid "Multipath current state is" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:784 msgid "Multipath master already defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:569 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 msgid "Multipath seems to be blocked on the connection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:610 msgid "NCM" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:838 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:843 msgid "NONE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:625 msgid "Network interface MAC address duplicated" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:615 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:801 msgid "Network interface duplicated" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:581 msgid "Network interface not in WAN firewall zone" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:903 msgid "Network overview" msgstr "" @@ -638,8 +660,8 @@ msgstr "" msgid "Networks settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:757 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:556 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:759 msgid "No IP defined" msgstr "" @@ -647,16 +669,16 @@ msgstr "" msgid "No IPv6 access" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:577 msgid "No Server http response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:573 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:773 msgid "No Server ping response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 msgid "No WAN with multipath enabled:" msgstr "" @@ -664,16 +686,16 @@ msgstr "" msgid "No available backup on server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:370 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:382 msgid "No change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:819 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:821 msgid "No data" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:761 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:560 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:763 msgid "No gateway defined" msgstr "" @@ -694,12 +716,12 @@ msgstr "" msgid "No server defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:413 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:421 msgid "None" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 msgid "Normal" msgstr "" @@ -721,25 +743,25 @@ msgstr "" msgid "Obfuscating will be enabled on both side" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:380 msgid "On wizard change" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:143 msgid "Only one server can be master, else all servers are set as backup." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "Only work with Shadowsocks as proxy." msgstr "" @@ -747,7 +769,7 @@ msgstr "" msgid "OpenMPTCProuter" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "" @@ -755,59 +777,59 @@ msgstr "" msgid "Optimize for latency instead of bandwidth" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 msgid "Other" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 msgid "Other settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:839 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:844 msgid "PAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "PAP/CHAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:852 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:857 msgid "PAP/CHAP password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 msgid "PAP/CHAP username" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:815 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:820 msgid "PIN code" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:611 msgid "PPPoE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:573 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:614 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:581 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 msgid "Physical interface" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "Prefer LTE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:831 msgid "Prefer UMTS" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:102 msgid "Primary server IP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 msgid "Protocol" msgstr "" @@ -815,19 +837,23 @@ msgstr "" msgid "Proxy is DISABLED" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:220 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 msgid "Proxy settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 msgid "Proxy traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:604 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:612 msgid "QMI" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:980 +msgid "QoS permit to prioritize any upload traffic." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:393 msgid "Qualcomm Shortcut FE driver" msgstr "" @@ -835,7 +861,7 @@ msgstr "" msgid "Redirects all ports from server to this router" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1054 msgid "Reset" msgstr "" @@ -843,32 +869,42 @@ msgstr "" msgid "Restore backup" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:179 msgid "Retrieve settings from server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:435 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:957 +msgid "SQM autorate is for LTE and connection without a stable speed." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:947 +msgid "" +"SQM control bufferloat: the undesirable latency that arises when the router " +"buffers too much data." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:447 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1053 msgid "Save & Apply" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:239 msgid "Save vnstats statistics on disk" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:234 msgid "Save vnstats stats" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:427 msgid "Scaling governor" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:103 msgid "Secondary server IP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1047 msgid "Select the device you want to base the interface on." msgstr "" @@ -876,78 +912,78 @@ msgstr "" msgid "Send backup" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 msgid "Server IP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:87 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 msgid "Server IP will be set for proxy and VPN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:126 msgid "Server key" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:75 msgid "Server settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:114 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 msgid "Server username" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Service Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:409 msgid "Set VPN to use for MPTCP over VPN." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:696 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 msgid "Set an IP in the same network as the modem" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:408 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 msgid "Set configuration for countries with some specificities." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:702 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 msgid "Set here IP of the modem" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 msgid "Set server as master" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " "for all traffic if proxy is disabled." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:943 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:959 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1014 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" @@ -960,16 +996,16 @@ msgstr "" msgid "ShadowSocks is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 msgid "ShadowSocks is used for TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 msgid "ShadowSocks key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 msgid "Show advanced settings" msgstr "" @@ -977,8 +1013,8 @@ msgstr "" msgid "Show all settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:606 msgid "Static address" msgstr "" @@ -986,7 +1022,7 @@ msgstr "" msgid "Status" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:400 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:412 msgid "Systems settings" msgstr "" @@ -997,7 +1033,7 @@ msgid "" "local end." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:278 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -1016,32 +1052,32 @@ msgid "" "retransmissions remain unacknowledged." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:263 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 msgid "Timeout for VPS checks on status pages" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Timeout for retrieving WANs IP on status pages" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:367 msgid "Total traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:567 msgid "Type" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:326 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:328 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:334 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:336 msgid "UBOND password" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:833 msgid "UMTS/GPRS" msgstr "" @@ -1058,17 +1094,17 @@ msgstr "" msgid "Update server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:949 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1004 msgid "Upload speed (Kb/s)" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "Uptime:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:938 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:954 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1009 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "" @@ -1076,20 +1112,20 @@ msgstr "" msgid "V2Ray is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 msgid "V2Ray is used for TCP and UDP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "V2Ray user" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 msgid "V2Ray user id" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:643 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:644 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:651 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:652 msgid "VLAN" msgstr "" @@ -1097,11 +1133,11 @@ msgstr "" msgid "VPN is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:294 msgid "VPN settings" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 msgid "VPN traffic:" msgstr "" @@ -1109,21 +1145,21 @@ msgstr "" msgid "VPN tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 msgid "VPS checks timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 msgid "Version" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 msgid "WAN IPs retrieve timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:584 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:775 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:586 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:591 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:777 msgid "Wan IP and gateway are identical" msgstr "" @@ -1133,15 +1169,19 @@ msgid "" "used to go outside." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 +msgid "When proxy V2Ray is used, use it for UDP" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 msgid "Wizard" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:422 msgid "World" msgstr "" @@ -1150,36 +1190,38 @@ msgstr "" msgid "You" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:918 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:934 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:907 +msgid "" +"You can force a TTL. Some LTE provider detect tethering by inpecting packet " +"TTL value, setting it to 65 often solve the issue." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:617 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:204 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:212 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:538 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:928 -msgid "You should disable SQM for LTE or any interfaces with variable speed." -msgstr "" - #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:58 msgid "You shouldn't do that and you should redirect only needed ports" msgstr "" @@ -1192,7 +1234,7 @@ msgstr "" msgid "address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 msgid "auto" msgstr "" @@ -1200,43 +1242,43 @@ msgstr "" msgid "empty key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:506 msgid "interface:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:488 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:737 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:490 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:739 msgid "ip address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:492 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:494 msgid "ipv6 address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:751 msgid "latency:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:755 msgid "mtu:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:644 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:808 msgid "multipath:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:526 msgid "operator:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 msgid "other" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:528 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:530 msgid "phone number:" msgstr "" @@ -1244,26 +1286,26 @@ msgstr "" msgid "range:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:532 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:534 msgid "state:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:647 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:649 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:811 msgid "traffic control:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:498 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:743 msgid "wan address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:502 msgid "wan ipv6 address:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:747 msgid "whois:" msgstr "" diff --git a/luci-app-sqm-autorate/po/templates/sqm.pot b/luci-app-sqm-autorate/po/templates/sqm.pot index 9503c8586..1ae5b9220 100644 --- a/luci-app-sqm-autorate/po/templates/sqm.pot +++ b/luci-app-sqm-autorate/po/templates/sqm.pot @@ -1,199 +1,265 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:207 msgid "" "Advanced option string to pass to the egress queueing disciplines; no error " "checking, use very carefully." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:204 msgid "" "Advanced option string to pass to the ingress queueing disciplines; no error " "checking, use very carefully." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:75 +msgid "Autorate settings" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "Base download speed (kbit/s) (ingress):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:110 +msgid "Base upload speed (kbit/s) (egress):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:72 msgid "Basic Settings" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:124 msgid "" "Create log file for this SQM instance under /var/run/sqm/${Interface_name}." "[start|stop]-sqm.log." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 -msgid "" -"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " -"shaping:" +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:259 +msgid "Debug" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:58 msgid "Enable SQM" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:90 +msgid "Enable SQM autorate" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:79 msgid "Enable this SQM instance." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:172 msgid "" "Explicit congestion notification (ECN) status on inbound packets (ingress):" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:178 msgid "" "Explicit congestion notification (ECN) status on outbound packets (egress)." msgstr "" -#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +#: luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 msgid "Grant UCI access for luci-app-sqm" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:192 msgid "Hard limit on egress queues; leave empty for default." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:188 msgid "Hard limit on ingress queues; leave empty for default." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:166 msgid "Ignore DSCP on ingress:" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:93 msgid "Interface name" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:200 msgid "" "Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " "automatic selection, put in the word default for the qdisc's default." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:196 msgid "" "Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " "automatic selection, put in the word default for the qdisc's default." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:74 msgid "Link Layer Adaptation" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:227 msgid "" "Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " "interface MTU + overhead:" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:105 +msgid "Maximum download speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:119 +msgid "Maximum upload speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:237 msgid "" "Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "Minimum download speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:114 +msgid "Minimum upload speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Must be set to cake if autorate is used." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:232 msgid "" "Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " "+ 1) / 16:" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:287 +msgid "Number of seconds to wait on startup:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:255 +msgid "Output monitoring lines showing cake bandwidth changes" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:251 +msgid "Output monitoring lines showing processing stats" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:217 msgid "Per Packet Overhead (byte):" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:267 +msgid "Pingers numbers:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:73 msgid "Queue Discipline" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:144 msgid "Queue setup script" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:71 msgid "Queues" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:136 msgid "" "Queuing disciplines useable on this system. After installing a new qdisc, " "you need to restart the router to see updates!" msgstr "" -#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:263 +msgid "Reflector ping interval in seconds:" +msgstr "" + +#: luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json:3 msgid "SQM QoS" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:223 msgid "" "Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " "options will only be used as long as this box is checked." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:157 msgid "" "Show and Use Advanced Configuration. Advanced options will only be used as " "long as this box is checked." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:184 msgid "" "Show and Use Dangerous Configuration. Dangerous options will only be used as " "long as this box is checked." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:275 +msgid "Sleep functionnality" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:64 msgid "Smart Queue Management" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:160 msgid "Squash DSCP on inbound packets (ingress):" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:84 msgid "" "The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " "disable the sqm initscript manually under System Startup menu in case this " "change was not wished for." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:48 msgid "" "The SQM service seems to be disabled. Please use the button below to " "activate this service." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 -msgid "" -"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " -"shaping:" +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:279 +msgid "Threshold in Kbit/s below which dl/ul is considered idle" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:283 +msgid "" +"Time threshold to put pingers to sleep on substained dl/ul achieved rate < " +"idle_threshold" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:127 msgid "Verbosity of SQM's output into the system log." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:211 msgid "Which link layer to account for:" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:242 msgid "Which linklayer adaptation mechanism to use; for testing only" msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:65 msgid "" "With SQM you can enable " "traffic shaping, better mixing (Fair Queueing), active queue length " "management (AQM) and prioritisation on one network interface." msgstr "" -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 -#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:131 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:173 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:179 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:212 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:243 msgid "default" msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:271 +msgid "delay threshold in ms:" +msgstr "" From bcafb1ee4d11d42c2bf78aeee3ec94cc0f534639 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Aug 2022 19:43:55 +0200 Subject: [PATCH 0825/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/2460 --- .../luasrc/controller/openmptcprouter.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index b73b045a1..f2142f37f 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -640,7 +640,7 @@ function wizard_add() ucic:set("v2ray","main","enabled","0") ucic:foreach("shadowsocks-libev", "server", function(s) local sectionname = s[".name"] - if sectionname:match("^sss.*") then + if sectionname:match("^sss.*") and ucic:get("shadowsocks-libev",sectionname,"server") ~= "" then ucic:set("shadowsocks-libev",sectionname,"disabled","0") end end) @@ -709,7 +709,7 @@ function wizard_add() local nbip = 0 for _, ssip in pairs(server_ips) do ucic:set("shadowsocks-libev","sss" .. nbip,"server",ssip) - if default_proxy == "shadowsocks" and serversnb > disablednb then + if default_proxy == "shadowsocks" and serversnb > disablednb and ssip ~= "" then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end nbip = nbip + 1 @@ -747,7 +747,7 @@ function wizard_add() local nbip = 0 for _, ssip in pairs(server_ips) do ucic:set("shadowsocks-libev","sss" .. nbip,"server",ssip) - if default_proxy == "shadowsocks" and serversnb > disablednb then + if default_proxy == "shadowsocks" and serversnb > disablednb and ssip ~= "" then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end nbip = nbip + 1 @@ -843,8 +843,8 @@ function wizard_add() end else if serversnb == 0 then - ucic:set("shadowsocks-libev","sss0","disabled",shadowsocks_disable) - ucic:set("shadowsocks-libev","sss1","disabled",shadowsocks_disable) + ucic:set("shadowsocks-libev","sss0","disabled","1") + ucic:set("shadowsocks-libev","sss1","disabled","1") end ucic:set("shadowsocks-libev","sss0","key","") ucic:set("shadowsocks-libev","sss1","key","") From 462dbc2dea99c048dc4992191f6e3510e0b0df53 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Aug 2022 08:53:11 +0200 Subject: [PATCH 0826/2059] Try to fix DNS issue --- omr-6in4/files/etc/init.d/omr-6in4 | 4 +-- .../files/etc/uci-defaults/1940-omr-dns | 25 +++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/omr-6in4/files/etc/init.d/omr-6in4 b/omr-6in4/files/etc/init.d/omr-6in4 index e29103a3d..533c06f17 100755 --- a/omr-6in4/files/etc/init.d/omr-6in4 +++ b/omr-6in4/files/etc/init.d/omr-6in4 @@ -32,7 +32,7 @@ set_ipv6_state() { if [ "$disable_ipv6" = "1" ]; then logger -t "omr-6in4" "Disable IPv6" uci -q batch <<-EOF >/dev/null - set unbound.ub_main.protocol='ip4_only' + set unbound.@unbound[-1].protocol='ip4_only' commit unbound del_list v2ray.main.inbounds="omr6" commit v2ray @@ -50,7 +50,7 @@ set_ipv6_state() { set network.omr6in4.force_link=1 set network.omr6in4.metric=1 delete network.omr6in4.auto - set unbound.ub_main.protocol='mixed' + set unbound.@unbound[-1].protocol='mixed' commit unbound EOF if [ "$(uci -q get network.globals.ula_prefix)" = "" ]; then diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index d9986be6d..6bf0e79e7 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -1,6 +1,6 @@ #!/bin/sh -if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then - if [ "$(uci -q get unbound.@unbound[0].listen_port | grep 5353)" = "" ]; then +if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then + if [ "$(uci -q get unbound.@unbound[-1].listen_port | grep 5353)" = "" ]; then uci -q batch <<-EOF >/dev/null set unbound.@unbound[-1].listen_port=5353 set unbound.@unbound[-1].protocol="ip4_only" @@ -8,11 +8,11 @@ if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then set unbound.@unbound[-1].recursion="aggressive" set unbound.@unbound[-1].validator='1' set unbound.@unbound[-1].validator_ntp='1' - del unbound.ub_main.dns64_prefix - del unbound.ub_main.iface_wan - del unbound.ub_main.dhcp4_slaac6 - del unbound.ub_main.query_minimize - del unbound.ub_main.query_min_strict + del unbound.@unbound[-1].dns64_prefix + del unbound.@unbound[-1].iface_wan + del unbound.@unbound[-1].dhcp4_slaac6 + del unbound.@unbound[-1].query_minimize + del unbound.@unbound[-1].query_min_strict commit unbound EOF fi @@ -24,6 +24,13 @@ if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then EOF fi fi +if [ -z "$(uci -q get unbound.ub_main)" ]; then + uci -q batch <<-EOF >/dev/null + rename unbound.@unbound[-1]=ub_main + commit unbound + EOF + +fi if [ "$(uci -q show dhcp | grep 'use-application-dns.net')" = "" ]; then uci -q batch <<-EOF >/dev/null add_list dhcp.@dnsmasq[-1].server="/use-application-dns.net/" @@ -66,6 +73,7 @@ fi if [ -z "$(uci -q show unbound.auth_icann)" ]; then uci -q batch <<-EOF >/dev/null + del unbound.auth_icann set unbound.auth_icann=zone set unbound.auth_icann.fallback='1' set unbound.auth_icann.url_dir='https://www.internic.net/domain/' @@ -77,6 +85,7 @@ if [ -z "$(uci -q show unbound.auth_icann)" ]; then add_list unbound.auth_icann.zone_name='in-addr.arpa.' add_list unbound.auth_icann.zone_name='ip6.arpa.' set unbound.auth_icann.enabled='1' + del unbound.fwd_isp set unbound.fwd_isp=zone set unbound.fwd_isp.enabled='0' set unbound.fwd_isp.fallback='1' @@ -84,6 +93,7 @@ if [ -z "$(uci -q show unbound.auth_icann)" ]; then set unbound.fwd_isp.zone_type='forward_zone' add_list unbound.fwd_isp.zone_name='isp-bill.example.com.' add_list unbound.fwd_isp.zone_name='isp-mail.example.net.' + del unbound.fwd_google set unbound.fwd_google=zone set unbound.fwd_google.enabled='0' set unbound.fwd_google.fallback='1' @@ -95,6 +105,7 @@ if [ -z "$(uci -q show unbound.auth_icann)" ]; then add_list unbound.fwd_google.server='2001:4860:4860::8844' add_list unbound.fwd_google.server='2001:4860:4860::8888' set unbound.fwd_google.zone_name='.' + del unbound.fwd_cloudflare set unbound.fwd_cloudflare=zone set unbound.fwd_cloudflare.enabled='0' set unbound.fwd_cloudflare.fallback='1' From 86cbd438493d72dec5973550f2d7a110ab6db7d8 Mon Sep 17 00:00:00 2001 From: openmptcprouter-translation <66313742+openmptcprouter-translation@users.noreply.github.com> Date: Fri, 12 Aug 2022 14:12:13 +0200 Subject: [PATCH 0827/2059] Translations update from Weblate (#103) * Translated using Weblate (Italian) Currently translated at 58.3% (7 of 12 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-quota Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-quota/it/ * Translated using Weblate (Italian) Currently translated at 19.3% (6 of 31 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-tracker Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-tracker/it/ * Translated using Weblate (Italian) Currently translated at 93.7% (269 of 287 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/it/ * Translated using Weblate (Italian) Currently translated at 95.6% (22 of 23 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-bypass Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-bypass/it/ * Translated using Weblate (Italian) Currently translated at 79.4% (27 of 34 strings) Translation: OpenMPTCProuter/LuCI/applications/omr-dscp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsomr-dscp/it/ * Translated using Weblate (Italian) Currently translated at 79.4% (31 of 39 strings) Translation: OpenMPTCProuter/LuCI/applications/snmpd Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationssnmpd/it/ * Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/ * Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: OpenMPTCProuter/LuCI/applications/mptcp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsmptcp/ * Translated using Weblate (French) Currently translated at 100.0% (296 of 296 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/fr/ * Translated using Weblate (French) Currently translated at 100.0% (58 of 58 strings) Translation: OpenMPTCProuter/LuCI/applications/mptcp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsmptcp/fr/ * Translated using Weblate (French) Currently translated at 97.4% (38 of 39 strings) Translation: OpenMPTCProuter/LuCI/applications/sqm-autorate Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationssqm-autorate/fr/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 96.9% (287 of 296 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/zh_Hans/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 91.3% (53 of 58 strings) Translation: OpenMPTCProuter/LuCI/applications/mptcp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsmptcp/zh_Hans/ * Translated using Weblate (Occitan) Currently translated at 54.3% (161 of 296 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/oc/ * Translated using Weblate (German) Currently translated at 52.3% (155 of 296 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/de/ * Translated using Weblate (Italian) Currently translated at 90.8% (269 of 296 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/it/ Co-authored-by: tiziano Co-authored-by: Deleted User Co-authored-by: Weblate --- luci-app-mptcp/po/de/mptcp.po | 68 +- luci-app-mptcp/po/fr/mptcp.po | 79 ++- luci-app-mptcp/po/it/mptcp.po | 68 +- luci-app-mptcp/po/oc/mptcp.po | 68 +- luci-app-mptcp/po/ru/mptcp.po | 68 +- luci-app-mptcp/po/zh_Hans/mptcp.po | 79 ++- luci-app-omr-bypass/po/it/omr-bypass.po | 8 +- luci-app-omr-dscp/po/it/omr-dscp.po | 8 +- luci-app-omr-quota/po/it/omr-quota.po | 8 +- luci-app-omr-tracker/po/it/omr-tracker.po | 8 +- .../po/de/openmptcprouter.po | 643 +++++++++-------- .../po/fr/openmptcprouter.po | 653 +++++++++-------- .../po/it/openmptcprouter.po | 661 ++++++++++-------- .../po/oc/openmptcprouter.po | 647 +++++++++-------- .../po/zh_Hans/openmptcprouter.po | 650 +++++++++-------- luci-app-snmpd/po/it/snmpd.po | 10 +- luci-app-sqm-autorate/po/fr/sqm.po | 12 +- 17 files changed, 2072 insertions(+), 1666 deletions(-) diff --git a/luci-app-mptcp/po/de/mptcp.po b/luci-app-mptcp/po/de/mptcp.po index 9b8c194ab..a67d0bbce 100644 --- a/luci-app-mptcp/po/de/mptcp.po +++ b/luci-app-mptcp/po/de/mptcp.po @@ -37,11 +37,11 @@ msgstr "" "Prüfung auf transparenten Transport von MPTCP-Paketen zwischen Anschluss und " "Server." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Congestion Control" msgstr "Überlauf-Steuerung" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 msgid "Consecutive segments that should be sent for round robin" msgstr "" @@ -51,7 +51,7 @@ msgstr "" msgid "Current:" msgstr "derzeit:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 #, fuzzy msgid "Default is cubic" msgstr "Voreinstellung ist 'bbr'" @@ -76,11 +76,11 @@ msgstr "Fehler" msgid "Established connections" msgstr "aufgebaute Verbindungen" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 msgid "Fill the congestion window on all subflows for round robin" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "" "Datenströme im vollvermaschter Betrieb für die jeweiligen Gegegenstellen-" @@ -105,7 +105,7 @@ msgstr "Ankommend:" msgid "Interface" msgstr "Schnittstelle" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 msgid "Interfaces Settings" msgstr "Anschluss-Einstellungen" @@ -150,11 +150,11 @@ msgid "Multipath Debug" msgstr "Mehrfachausbreitungspfad-Analyse" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "Multipath TCP" msgstr "Multipath-TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 msgid "Multipath TCP SYN retries" msgstr "Multipath TCP SYN Wiederholungen" @@ -166,11 +166,17 @@ msgstr "Multipath TCP Prüfummen" msgid "Multipath TCP path-manager" msgstr "Multipath TCP Pfadkontrolle" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 msgid "Multipath TCP scheduler" msgstr "Multpath TCP Priorisierungskontrolle" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#, fuzzy +#| msgid "Multipath TCP" +msgid "Multipath TCP version" +msgstr "Multipath-TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 msgid "Netlink" msgstr "Netlink-Layer" @@ -184,7 +190,7 @@ msgstr "" "tcp.org/pmwiki.php/Users/ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/" "Users/ConfigureMPTCP (english)." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "One interface must be set as master" msgstr "Ein Anschluss muss als 'primär' defininiert werden." @@ -200,7 +206,7 @@ msgstr "Abgehend:" msgid "Peak:" msgstr "Spitze:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "Re-create fullmesh subflows after a timeout" msgstr "Wiederverbindungs-Wartezeit der Vollvermaschungs-Verbindungen" @@ -217,6 +223,12 @@ msgstr "Einstellungen" msgid "Test" msgstr "Test" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale" +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Upstream:" @@ -228,36 +240,36 @@ msgstr "Upstream:" msgid "Waiting for command to complete..." msgstr "Warte auf Abschluss der Aufgaben" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 msgid "backup" msgstr "Sicherung" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 msgid "default" msgstr "Voreinstellung" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 msgid "disable" msgstr "ausschalten" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 msgid "disabled" msgstr "aus" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 msgid "enable" msgstr "anschalten" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 msgid "enabled" msgstr "an" @@ -295,14 +307,26 @@ msgstr "kBytes/s" msgid "kbit/s" msgstr "kBit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 msgid "master" msgstr "primär" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 msgid "ndiffports subflows number" msgstr "ndiff-Ports Verbindungs-Nummer" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "" +"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " +"connection" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" + #~ msgid "BLEST" #~ msgstr "Blockierungsvorhersage-Betrieb" diff --git a/luci-app-mptcp/po/fr/mptcp.po b/luci-app-mptcp/po/fr/mptcp.po index 0901267ce..b47876f87 100644 --- a/luci-app-mptcp/po/fr/mptcp.po +++ b/luci-app-mptcp/po/fr/mptcp.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-02-19 07:53+0000\n" +"PO-Revision-Date: 2022-08-10 18:51+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.6.1\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" @@ -38,11 +38,11 @@ msgstr "Bande passante" msgid "Check if MPTCP between interface and server is working." msgstr "Vérifiez si MPTCP entre l'interface et le serveur fonctionne." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Congestion Control" msgstr "Contrôle de la congestion" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 msgid "Consecutive segments that should be sent for round robin" msgstr "Segments consécutifs à envoyer pour round robin" @@ -52,7 +52,7 @@ msgstr "Segments consécutifs à envoyer pour round robin" msgid "Current:" msgstr "Actuellement :" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Default is cubic" msgstr "La valeur par défaut est cubic" @@ -75,11 +75,12 @@ msgstr "Erreur" msgid "Established connections" msgstr "Connexions établies" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 msgid "Fill the congestion window on all subflows for round robin" -msgstr "Remplir la fenêtre de congestion de tous les sous-flux pour round robin" +msgstr "" +"Remplir la fenêtre de congestion de tous les sous-flux pour round robin" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Sous-flux Fullmesh pour chaque paire d'adresses IP" @@ -105,7 +106,7 @@ msgstr "Entrant :" msgid "Interface" msgstr "Interface" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 msgid "Interfaces Settings" msgstr "Paramètres des interfaces" @@ -150,11 +151,11 @@ msgid "Multipath Debug" msgstr "Débogage multipath" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 msgid "Multipath TCP SYN retries" msgstr "Tentatives Multipath TCP SYN" @@ -166,11 +167,15 @@ msgstr "Somme de contrôle Multipath TCP" msgid "Multipath TCP path-manager" msgstr "Gestionnaire de chemins Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 msgid "Multipath TCP scheduler" msgstr "Planificateur Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +msgid "Multipath TCP version" +msgstr "Version de Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 msgid "Netlink" msgstr "Netlink" @@ -184,7 +189,7 @@ msgstr "" "php/Users/ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/Users/" "ConfigureMPTCP pour de l'aide." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "One interface must be set as master" msgstr "Une interface doit être configuré en temps que maître" @@ -200,7 +205,7 @@ msgstr "Sortant :" msgid "Peak:" msgstr "Pointe :" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "Re-create fullmesh subflows after a timeout" msgstr "Recréer les sous-flux fullmesh après le délai d'expiration" @@ -217,6 +222,14 @@ msgstr "Paramètres" msgid "Test" msgstr "Essai" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale" +msgstr "" +"Le nombre d'intervalles de retransmission au niveau de MPTCP sans trafic et " +"en attente de données sur un sous-flux requis pour le déclarer obsolète" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Envoie :" @@ -228,36 +241,36 @@ msgstr "Envoie :" msgid "Waiting for command to complete..." msgstr "En attente de la réponse de la commande..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 msgid "backup" msgstr "remplaçant" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 msgid "default" msgstr "Défaut" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 msgid "disable" msgstr "Désactive" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 msgid "disabled" msgstr "Désactivé" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 msgid "enable" msgstr "Active" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 msgid "enabled" msgstr "Activé" @@ -295,14 +308,30 @@ msgstr "Ko/s" msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 msgid "master" msgstr "maître" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 msgid "ndiffports subflows number" msgstr "Nombre de sous-flux ndiffports" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "" +"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " +"connection" +msgstr "" +"spécifie le nombre maximum de sous-options ADD_ADDR acceptées pour chaque " +"connexion MPTCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" +"spécifie le nombre maximum de sous-flux ADD_ADDR acceptées pour chaque " +"connexion MPTCP" + #~ msgid "binder" #~ msgstr "lier" diff --git a/luci-app-mptcp/po/it/mptcp.po b/luci-app-mptcp/po/it/mptcp.po index 048ef35ef..78e5a223e 100644 --- a/luci-app-mptcp/po/it/mptcp.po +++ b/luci-app-mptcp/po/it/mptcp.po @@ -35,11 +35,11 @@ msgstr "Larghezza banda" msgid "Check if MPTCP between interface and server is working." msgstr "Controlla se MPTCP tra l'interfaccia e il server funziona." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Congestion Control" msgstr "Controllo della congestione" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 msgid "Consecutive segments that should be sent for round robin" msgstr "" @@ -49,7 +49,7 @@ msgstr "" msgid "Current:" msgstr "Corrente:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 #, fuzzy msgid "Default is cubic" msgstr "L'impostazione predefinita è bbr" @@ -74,11 +74,11 @@ msgstr "Errore" msgid "Established connections" msgstr "Connessioni stabilite" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 msgid "Fill the congestion window on all subflows for round robin" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Flussi secondari fullmesh per ogni coppia di indirizzi IP" @@ -101,7 +101,7 @@ msgstr "In entrata:" msgid "Interface" msgstr "Interfaccia" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 msgid "Interfaces Settings" msgstr "Impostazioni delle interfacce" @@ -146,11 +146,11 @@ msgid "Multipath Debug" msgstr "Debug multipath" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 msgid "Multipath TCP SYN retries" msgstr "Multipath TCP SYN riprova" @@ -162,11 +162,17 @@ msgstr "Multipath TCP checksum" msgid "Multipath TCP path-manager" msgstr "Multipath TCP path-manager" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 msgid "Multipath TCP scheduler" msgstr "Multipath TCP scheduler" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#, fuzzy +#| msgid "Multipath TCP" +msgid "Multipath TCP version" +msgstr "Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 msgid "Netlink" msgstr "Netlink" @@ -177,7 +183,7 @@ msgid "" "ConfigureMPTCP for help." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "One interface must be set as master" msgstr "Un'interfaccia deve essere impostata come master" @@ -193,7 +199,7 @@ msgstr "Upload:" msgid "Peak:" msgstr "Picco:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "Re-create fullmesh subflows after a timeout" msgstr "Ricrea i flussi secondari fullmesh dopo un timeout" @@ -210,6 +216,12 @@ msgstr "Impostazioni" msgid "Test" msgstr "Test" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale" +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Upload:" @@ -221,36 +233,36 @@ msgstr "Upload:" msgid "Waiting for command to complete..." msgstr "In attesa del completamento del comando ..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 msgid "backup" msgstr "backup" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 msgid "default" msgstr "predefinito" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 msgid "disable" msgstr "disabilita" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 msgid "disabled" msgstr "disabilitato" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 msgid "enable" msgstr "Attivare" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 msgid "enabled" msgstr "Abilitato" @@ -288,14 +300,26 @@ msgstr "kB/s" msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 msgid "master" msgstr "Principale" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 msgid "ndiffports subflows number" msgstr "ndiffports subflows number" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "" +"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " +"connection" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" + #~ msgid "BLEST" #~ msgstr "BLEST" diff --git a/luci-app-mptcp/po/oc/mptcp.po b/luci-app-mptcp/po/oc/mptcp.po index 3a8ffd4f4..f9bd5bda5 100644 --- a/luci-app-mptcp/po/oc/mptcp.po +++ b/luci-app-mptcp/po/oc/mptcp.po @@ -35,11 +35,11 @@ msgstr "Benda passanta" msgid "Check if MPTCP between interface and server is working." msgstr "Verificar se MPTCP entre l‘interfàcia e lo servidor fonciona." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Congestion Control" msgstr "Contraròtle de congestion" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 msgid "Consecutive segments that should be sent for round robin" msgstr "" @@ -49,7 +49,7 @@ msgstr "" msgid "Current:" msgstr "Actualament :" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 #, fuzzy msgid "Default is cubic" msgstr "Per defaut bbr" @@ -74,11 +74,11 @@ msgstr "Error" msgid "Established connections" msgstr "Connexions establidas" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 msgid "Fill the congestion window on all subflows for round robin" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Jos flux Fullmesh per cada parelh d’adreças IP" @@ -101,7 +101,7 @@ msgstr "Dintrant :" msgid "Interface" msgstr "Interfàcia" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 msgid "Interfaces Settings" msgstr "Paramètres de las interfàcias" @@ -146,11 +146,11 @@ msgid "Multipath Debug" msgstr "Desbugatge multipath" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 msgid "Multipath TCP SYN retries" msgstr "Ensages Multipath TCP SYN" @@ -162,11 +162,17 @@ msgstr "Sòma de contraròtle Multipath TCP" msgid "Multipath TCP path-manager" msgstr "Gestionari dels camins Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 msgid "Multipath TCP scheduler" msgstr "Planificator Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#, fuzzy +#| msgid "Multipath TCP" +msgid "Multipath TCP version" +msgstr "Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 msgid "Netlink" msgstr "Ligam ret" @@ -180,7 +186,7 @@ msgstr "" "Users/ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/Users/" "ConfigureMPTCP per d’ajuda." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "One interface must be set as master" msgstr "Una interfàcia deu èsser configurada coma principala" @@ -196,7 +202,7 @@ msgstr "Sortent :" msgid "Peak:" msgstr "Punta :" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "Re-create fullmesh subflows after a timeout" msgstr "Tornar crear los jos-flus fullmesh aprèp lo relambi d’expiracion" @@ -213,6 +219,12 @@ msgstr "Paramètres" msgid "Test" msgstr "Pròva" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale" +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Mandadís :" @@ -224,36 +236,36 @@ msgstr "Mandadís :" msgid "Waiting for command to complete..." msgstr "En espèra d’una responsa de la comanda..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 msgid "backup" msgstr "subordinat" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 msgid "default" msgstr "Defaut" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 msgid "disable" msgstr "desactivar" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 msgid "disabled" msgstr "desactivat" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 msgid "enable" msgstr "Activar" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 msgid "enabled" msgstr "Activat" @@ -291,14 +303,26 @@ msgstr "kB/s" msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 msgid "master" msgstr "màger" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 msgid "ndiffports subflows number" msgstr "Nombre de jos-flux ndiffports" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "" +"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " +"connection" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" + #, fuzzy #~ msgid "BLEST" #~ msgstr "BLEST" diff --git a/luci-app-mptcp/po/ru/mptcp.po b/luci-app-mptcp/po/ru/mptcp.po index 721602f75..bdd6ac158 100644 --- a/luci-app-mptcp/po/ru/mptcp.po +++ b/luci-app-mptcp/po/ru/mptcp.po @@ -36,11 +36,11 @@ msgstr "Пропускная способность" msgid "Check if MPTCP between interface and server is working." msgstr "Проверьте, работает ли MPTCP между интерфейсом и сервером." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Congestion Control" msgstr "Контроль перегрузки" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 msgid "Consecutive segments that should be sent for round robin" msgstr "Последовательные сегменты, которые следует отправлять для round-robin" @@ -50,7 +50,7 @@ msgstr "Последовательные сегменты, которые сле msgid "Current:" msgstr "Текущая:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Default is cubic" msgstr "По умолчанию кубический" @@ -73,11 +73,11 @@ msgstr "Ошибка" msgid "Established connections" msgstr "Установленные соединения" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 msgid "Fill the congestion window on all subflows for round robin" msgstr "Заполнение окна перегрузки для всех подпотоков для round-robin" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Подпотоки Fullmesh для каждой пары IP-адресов" @@ -102,7 +102,7 @@ msgstr "Входящий:" msgid "Interface" msgstr "Интерфейс" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 msgid "Interfaces Settings" msgstr "Настройки интерфейсов" @@ -147,11 +147,11 @@ msgid "Multipath Debug" msgstr "Многоуровневая отладка" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "Multipath TCP" msgstr "Многопоточный TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 msgid "Multipath TCP SYN retries" msgstr "Попытки многопоточной TCP SYN" @@ -163,11 +163,17 @@ msgstr "Контрольная сумма многопоточного TCP" msgid "Multipath TCP path-manager" msgstr "Многопоточный TCP менеджер" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 msgid "Multipath TCP scheduler" msgstr "Планировщик многопоточного TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#, fuzzy +#| msgid "Multipath TCP" +msgid "Multipath TCP version" +msgstr "Многопоточный TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 msgid "Netlink" msgstr "Netlink" @@ -181,7 +187,7 @@ msgstr "" "Users/ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/Users/" "ConfigureMPTCP для справки." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "One interface must be set as master" msgstr "Один интерфейс должен быть установлен как главный" @@ -197,7 +203,7 @@ msgstr "Отправка:" msgid "Peak:" msgstr "Пиковое значение:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "Re-create fullmesh subflows after a timeout" msgstr "Повторно создать подпотоки fullmesh после тайм-аута" @@ -214,6 +220,12 @@ msgstr "Настройки" msgid "Test" msgstr "Тест" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale" +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Отправка:" @@ -225,36 +237,36 @@ msgstr "Отправка:" msgid "Waiting for command to complete..." msgstr "Ожидание завершения команды..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 msgid "backup" msgstr "Резервирование" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 msgid "default" msgstr "По умолчанию" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 msgid "disable" msgstr "отключить" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 msgid "disabled" msgstr "отключить" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 msgid "enable" msgstr "включить" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 msgid "enabled" msgstr "Установлено" @@ -292,10 +304,22 @@ msgstr "kB/s" msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 msgid "master" msgstr "мастер" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 msgid "ndiffports subflows number" msgstr "количество подпотоков ndiffports" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "" +"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " +"connection" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" diff --git a/luci-app-mptcp/po/zh_Hans/mptcp.po b/luci-app-mptcp/po/zh_Hans/mptcp.po index 6b16ddad4..cfa888b3b 100644 --- a/luci-app-mptcp/po/zh_Hans/mptcp.po +++ b/luci-app-mptcp/po/zh_Hans/mptcp.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-06-02 09:51+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2022-08-12 12:08+0000\n" +"Last-Translator: Weblate Admin \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.6.1\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" @@ -35,11 +35,11 @@ msgstr "带宽" msgid "Check if MPTCP between interface and server is working." msgstr "检查接口和服务器之间的MPTCP是否正常工作." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Congestion Control" msgstr "阻塞控制" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 msgid "Consecutive segments that should be sent for round robin" msgstr "连续轮播应发送的连续段" @@ -49,7 +49,7 @@ msgstr "连续轮播应发送的连续段" msgid "Current:" msgstr "实时:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Default is cubic" msgstr "默认设置 cubic" @@ -72,11 +72,11 @@ msgstr "错误" msgid "Established connections" msgstr "建立的连接" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 msgid "Fill the congestion window on all subflows for round robin" msgstr "在循环的所有子流上填充拥塞窗口" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "每对IP地址的全网格子流" @@ -85,13 +85,12 @@ msgid "Grant UCI access for luci-app-mptcp" msgstr "授予UCI访问luci-app-mptcp的权限" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +#, fuzzy msgid "" "If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " "MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " "blocked." -msgstr "" -"如果最后得到“ TCPOptionMPTCPCapable发件人的密钥”,则支持MPTCP。unesdoc.unesco.org " -"unesdoc.unesco.org 如果存在“ -TCPOptionMPTCPCapable”,则将其阻止。" +msgstr "如果您在末尾获得“TCPOptionMPTCPCapable [...] Sender 's Key” ,则支持MPTCP" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 msgid "Inbound:" @@ -101,7 +100,7 @@ msgstr "入站:" msgid "Interface" msgstr "接口" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 msgid "Interfaces Settings" msgstr "网卡设置" @@ -146,11 +145,11 @@ msgid "Multipath Debug" msgstr "Multipath 调试" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "Multipath TCP" msgstr "多路径TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 msgid "Multipath TCP SYN retries" msgstr "多路径 TCP SYN 重试" @@ -162,11 +161,17 @@ msgstr "多路径TCP校验和" msgid "Multipath TCP path-manager" msgstr "多路径TCP路径管理器" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 msgid "Multipath TCP scheduler" msgstr "多路径TCP调度程序" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#, fuzzy +#| msgid "Multipath TCP" +msgid "Multipath TCP version" +msgstr "多路径TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 msgid "Netlink" msgstr "网络链接" @@ -180,7 +185,7 @@ msgstr "" "ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/Users/ConfigureMPTCP4 获取更多的支持." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 msgid "One interface must be set as master" msgstr "必须设置一个网卡为主接口" @@ -196,7 +201,7 @@ msgstr "出站:" msgid "Peak:" msgstr "峰值:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "Re-create fullmesh subflows after a timeout" msgstr "超时后重新创建全网格子流" @@ -213,6 +218,12 @@ msgstr "设置" msgid "Test" msgstr "测试" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale" +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "上传:" @@ -224,36 +235,36 @@ msgstr "上传:" msgid "Waiting for command to complete..." msgstr "等待命令完成..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 msgid "backup" msgstr "备份" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 msgid "default" msgstr "默认" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 msgid "disable" msgstr "禁用" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 msgid "disabled" msgstr "禁用" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 msgid "enable" msgstr "启用" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 msgid "enabled" msgstr "启用" @@ -291,14 +302,26 @@ msgstr "kB/秒" msgid "kbit/s" msgstr "kbit/秒" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 msgid "master" msgstr "主" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 msgid "ndiffports subflows number" msgstr "ndiffports子流数" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "" +"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " +"connection" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" + #~ msgid "BLEST" #~ msgstr "最好的" diff --git a/luci-app-omr-bypass/po/it/omr-bypass.po b/luci-app-omr-bypass/po/it/omr-bypass.po index df50f91d0..203394eec 100644 --- a/luci-app-omr-bypass/po/it/omr-bypass.po +++ b/luci-app-omr-bypass/po/it/omr-bypass.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-10-02 08:44+0000\n" -"Last-Translator: Weblate Admin \n" +"PO-Revision-Date: 2022-02-21 21:14+0000\n" +"Last-Translator: Deleted User \n" "Language-Team: Italian \n" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 @@ -32,7 +32,7 @@ msgstr "Domini" #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 #: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 msgid "Enabled" -msgstr "" +msgstr "Abilitato" #: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 msgid "Grant access to ndpi resources" diff --git a/luci-app-omr-dscp/po/it/omr-dscp.po b/luci-app-omr-dscp/po/it/omr-dscp.po index 6194b0c41..2ea86eaf8 100644 --- a/luci-app-omr-dscp/po/it/omr-dscp.po +++ b/luci-app-omr-dscp/po/it/omr-dscp.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-09-21 12:51+0000\n" -"Last-Translator: Weblate Admin \n" +"PO-Revision-Date: 2022-02-21 21:14+0000\n" +"Last-Translator: Deleted User \n" "Language-Team: Italian \n" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 @@ -93,7 +93,7 @@ msgstr "Servizi differenziati" #: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:29 msgid "Direction" -msgstr "" +msgstr "Direzione" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:15 msgid "Domain" diff --git a/luci-app-omr-quota/po/it/omr-quota.po b/luci-app-omr-quota/po/it/omr-quota.po index 37e2dfec4..be100e360 100644 --- a/luci-app-omr-quota/po/it/omr-quota.po +++ b/luci-app-omr-quota/po/it/omr-quota.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-09-21 12:51+0000\n" -"Last-Translator: Weblate Admin \n" +"PO-Revision-Date: 2022-02-20 20:24+0000\n" +"Last-Translator: tiziano \n" "Language-Team: Italian \n" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 msgid "Add" @@ -24,7 +24,7 @@ msgstr "" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" -msgstr "Interfaccia" +msgstr "Interfacce" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 msgid "Interval between check (s)" diff --git a/luci-app-omr-tracker/po/it/omr-tracker.po b/luci-app-omr-tracker/po/it/omr-tracker.po index eed54997d..337631a7f 100644 --- a/luci-app-omr-tracker/po/it/omr-tracker.po +++ b/luci-app-omr-tracker/po/it/omr-tracker.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2022-02-11 13:53+0000\n" -"Last-Translator: Riccardo Tornesello \n" +"PO-Revision-Date: 2022-02-20 20:24+0000\n" +"Last-Translator: tiziano \n" "Language-Team: Italian \n" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.6.1\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 msgid "Add" @@ -69,7 +69,7 @@ msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:154 msgid "Interfaces" -msgstr "" +msgstr "Interfacce" #: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 msgid "Invalid" diff --git a/luci-app-openmptcprouter/po/de/openmptcprouter.po b/luci-app-openmptcprouter/po/de/openmptcprouter.po index 7efcbe36f..fddbdb4c0 100644 --- a/luci-app-openmptcprouter/po/de/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/de/openmptcprouter.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2022-02-19 10:30+0000\n" +"PO-Revision-Date: 2022-08-12 12:08+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: German \n" @@ -10,39 +10,39 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.10.1\n" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "'Dead Simple VPN' ist ein TCP VPN das 'Glorytun TCP' ersetzen kann" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:302 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:312 msgid "A Dead Simple VPN key" msgstr "Schlüssel 'Dead Simple VPN'" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" "Die zweite IP eines Servers kann für Dual-IPv4/IPv6-Server festgelegt " "werden, wenn WAN-IPv6 eingerichtet ist" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:119 msgid "API username to retrieve personnalized settings from the server." msgstr "API Benutzername zum Download der Einstellungen vom Server." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:814 msgid "APN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:742 msgid "Accept IPv6 RA" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:156 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:164 msgid "Add a new server" msgstr "Neuen Server hinzufügen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:989 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1044 msgid "Add an interface" msgstr "Interface hinzufügen" @@ -51,11 +51,11 @@ msgstr "Interface hinzufügen" msgid "Advanced Settings" msgstr "Erweiterte Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 msgid "Advanced settings" msgstr "Erweiterte Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -67,19 +67,19 @@ msgstr "" msgid "All router settings" msgstr "Alle Router-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:284 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." msgstr "" "Die CPU beherrscht AES-NI-Befehle zur Beschleunigung der Verschlüsselung." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "Authentication Type" msgstr "Authentifizierungs Methode" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:878 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:894 msgid "Backup" msgstr "Backup" @@ -88,7 +88,7 @@ msgstr "Backup" msgid "Backup on server" msgstr "Backup der Router-Einstellungen auf den Server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:383 msgid "Balancing" msgstr "Ausgleich" @@ -96,35 +96,41 @@ msgstr "Ausgleich" msgid "Beta" msgstr "Beta" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:312 msgid "Big time difference between the server and the router" msgstr "Großer Zeitunterschied zwischen dem Server und dem Router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 msgid "Bridge" msgstr "Netzwerkbrücke" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:620 msgid "Bridge can't have multipath enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "By default VPN is used for any traffic that is not TCP." msgstr "" "IP-Pakete, die nicht TCP sind, werden standardmäßig mit einem VPN-Protokoll " "übertragen." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" "Standard wird TCP Netzwerk Verkehr über Proxy übertragen (Auch UDP für " "V2Ray)." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:845 msgid "CHAP" msgstr "CHAP" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:961 +msgid "" +"Cake queue discipline is not set, autorate will only work after a reboot if " +"enabled here." +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 msgid "Can\\'t access and use server part" msgstr "Kann Server Teil nicht öffnen und verwenden" @@ -145,11 +151,11 @@ msgstr "" msgid "Can\\'t ping server" msgstr "Kann Server nicht pingen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:423 msgid "China" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." @@ -157,9 +163,9 @@ msgstr "" "Wähle MacVLAN um ein virtuelles Interface basierend auf ein Physikalisches " "Interface an zu legen." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:596 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:655 msgid "Choose physical interface." msgstr "Wähle physikalische Schnittstelle." @@ -167,21 +173,21 @@ msgstr "Wähle physikalische Schnittstelle." msgid "Core temp:" msgstr "Kerntemperatur:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:418 msgid "Country" msgstr "Land" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 #, fuzzy msgid "Country settings" msgstr "Alle Router-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 msgid "DHCP" msgstr "DHCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 msgid "DHCPv6" msgstr "DHCPv6" @@ -189,36 +195,36 @@ msgstr "DHCPv6" msgid "DNS issue: can\\'t resolve hostname" msgstr "DNS Problem: Hostnamen nicht beziehbar" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:367 msgid "Debug" msgstr "Debug" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:231 msgid "Default Proxy" msgstr "Standard Proxy" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:345 msgid "Default VPN" msgstr "Standard VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:543 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:551 msgid "Delete" msgstr "Löschen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:741 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:774 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 msgid "Device" msgstr "Gerät" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 #, fuzzy -msgid "Disable HTTP test on Server API in status page" +msgid "Disable HTTP test on Server API" msgstr "Server-Ping Status-Prüfung aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:357 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 #, fuzzy msgid "Disable ModemManager" msgstr "Server-Ping aus" @@ -232,11 +238,11 @@ msgid "Disable TCP Fast Open on Linux and Shadowsocks configuration" msgstr "" "Abschalten von TCP-Fast-Open für Linux und die ShadowsSocks-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 msgid "Disable default gateway" msgstr "Default Gateway aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:312 msgid "Disable default gateway, no internet if VPS are down" msgstr "Default Gateway aus, kein Internet wenn VPS down ist" @@ -244,29 +250,29 @@ msgstr "Default Gateway aus, kein Internet wenn VPS down ist" msgid "Disable external check" msgstr "Externe Prüfung aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:244 msgid "Disable gateway ping" msgstr "Gateway-Ping aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:249 #, fuzzy msgid "Disable gateway ping check in status page" msgstr "Gateway-Ping Statusüberprüfung aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:285 msgid "Disable interfaces auto rename" msgstr "Automatische Umbenennung von Interfaces deaktivieren" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:342 msgid "Disable multipath test using tracebox" msgstr "Deaktiviere multipath Test mittels Tracebox" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 #, fuzzy msgid "Disable nDPI" msgstr "Server-Ping aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 msgid "Disable nDPI, used for protocols in OMR-ByPass" msgstr "" @@ -275,72 +281,86 @@ msgid "" "Disable ports redirection defined in firewall from server to this router" msgstr "Portweiterleitungen in der Server-Firewall zu diesem Router abschalten" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 msgid "Disable renaming interfaces" msgstr "Umbenennung der Schnittstelle deaktivieren" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 #, fuzzy msgid "Disable route loop detection" msgstr "Server-Ping aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 msgid "Disable server" msgstr "Server deaktivieren" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:254 msgid "Disable server http test" msgstr "Server-http-Test aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 msgid "Disable server ping" msgstr "Server-Ping aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:322 msgid "Disable server ping status check" msgstr "Server-Ping Status-Prüfung aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:337 msgid "Disable tracebox test" msgstr "Deaktiviere tracebox Test" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:876 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:892 msgid "Disabled" msgstr "inaktiv" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:988 msgid "Download speed (Kb/s)" msgstr "Download-Geschwindigkeit (kBits/s)" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 msgid "Dynamic change" msgstr "Dynamische Anpassung" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:402 msgid "Enable Bridge Acceleration" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 #, fuzzy msgid "Enable DNS64" msgstr "SQM aktiv" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:396 msgid "Enable Fast Patch offloading for connections" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 msgid "Enable IPv6" msgstr "IPv6 aktiv" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:923 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:975 +msgid "Enable QoS" +msgstr "QoS aktiv" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:223 +msgid "Enable SIP ALG" +msgstr "SIP ALG aktiv" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:942 msgid "Enable SQM" msgstr "SQM aktiv" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 +#, fuzzy +#| msgid "Enable SQM" +msgid "Enable SQM autorate" +msgstr "SQM aktiv" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:79 msgid "Enable ShadowSocks Obfuscating" msgstr "Shadowsocks-Verschleierung aktiv" @@ -349,21 +369,21 @@ msgstr "Shadowsocks-Verschleierung aktiv" msgid "Enable TCP Low Latency" msgstr "Aktiviere TCP Low Latency" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:372 msgid "Enable debug logs" msgstr "Aktiviere debug Logs" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:886 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:875 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:891 msgid "Enabled" msgstr "Aktiv" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 msgid "Encryption" msgstr "Verschlüsselung" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:288 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "" "Verschlüsselungverfahren wird verwendet für Shadowsocks, V2Ray, Glorytun " @@ -373,37 +393,41 @@ msgstr "" msgid "Filesystem is readonly" msgstr "Filesystem ist nur lesen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:902 +msgid "Force TTL" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 msgid "Force retrieve all keys from server." msgstr "Erzwingen alle Schlüssel vom Server runter zu laden." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 msgid "Force retrieve settings" msgstr "Erzwingen Einstellungen runter zu laden." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:834 msgid "GPRS only" msgstr "Nur GPRS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:766 msgid "Gateway DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 msgid "Gateway IPv6 DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "Glorytun-TCP wird standardmäßig für UDP und ICMP genutzt." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:290 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:300 msgid "Glorytun key" msgstr "Glorytun Schlüssel" @@ -445,40 +469,40 @@ msgstr "IPv4 TCP SYN Wiederholversuche" msgid "IPv4 TCP SYN retries2" msgstr "IPv4 TCP SYN Wiederholversuche" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:653 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:661 msgid "IPv4 address" msgstr "IPv4-Adresse" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:677 msgid "IPv4 gateway" msgstr "IPv4-Standardgateway" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:663 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 msgid "IPv4 netmask" msgstr "IPv4-Netzmaske" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 msgid "IPv6 Prefix" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 msgid "IPv6 address" msgstr "IPv6-Adresse" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:705 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 msgid "IPv6 gateway" msgstr "IPv6-Standardgateway" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 msgid "IPv6 route received" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 msgid "IPv6 settings" msgstr "IPv6-Einstellungen" @@ -486,50 +510,50 @@ msgstr "IPv6-Einstellungen" msgid "IPv6 tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 msgid "IPv6:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:222 msgid "If host support NAT64, you can enable DNS64 support." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 msgid "Interfaces settings" msgstr "Schnittstellen-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "Key is retrieved from server API by default." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:129 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." msgstr "" "API-Schlüssel für die automatische Provisionierung der Schlüssel vom Server." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:435 #, fuzzy msgid "LAN interfaces settings" msgstr "Schnittstellen-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:832 msgid "LTE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:438 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:549 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:446 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:557 msgid "Label" msgstr "Bezeichnung" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:452 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 msgid "Label for the interface" msgstr "Bezeichnung der Schnittstelle" @@ -538,28 +562,28 @@ msgid "Last available backup on server:" msgstr "Aktuellstes auf dem Server verfügbares Backup:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:329 #, fuzzy msgid "Latest available version" msgstr "Aktuellstes auf dem Server verfügbares Backup:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:335 msgid "Load:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:628 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 msgid "Looping route detected" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "" "MLVPN kann Glorytun auf Verbindungen mit identischer Latenz ('ping') " "ersetzen." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:314 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:316 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:324 msgid "MLVPN password" msgstr "MLVPN Schlüssel" @@ -567,56 +591,56 @@ msgstr "MLVPN Schlüssel" msgid "MPTCP is not enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:344 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 msgid "MPTCP may not be enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:393 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:913 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:929 msgid "MPTCP over VPN" msgstr "MPTCP über VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:398 #, fuzzy msgid "MPTCP over VPN settings" msgstr "MPTCP über VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 msgid "MacVLAN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:893 msgid "Master" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:377 msgid "Master interface selection" msgstr "Primäre Schnittstelle:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:409 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:421 msgid "Maximum scaling CPU frequency" msgstr "Maximaler CPU-Takt" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:403 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 msgid "Minimum scaling CPU frequency" msgstr "Minimaler CPU-Takt" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:824 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "Modem default" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:858 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:863 msgid "Modem init timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:601 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 msgid "ModemManager" msgstr "" @@ -624,51 +648,51 @@ msgstr "" msgid "More than one default VPN is enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 msgid "Multipath TCP" msgstr "Multipath-TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:787 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:793 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:795 msgid "Multipath current state is" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:784 msgid "Multipath master already defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:569 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 msgid "Multipath seems to be blocked on the connection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:610 msgid "NCM" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:838 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:843 msgid "NONE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:625 msgid "Network interface MAC address duplicated" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:615 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:801 msgid "Network interface duplicated" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:581 msgid "Network interface not in WAN firewall zone" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:903 msgid "Network overview" msgstr "Netzwerk-Übersicht" @@ -676,8 +700,8 @@ msgstr "Netzwerk-Übersicht" msgid "Networks settings" msgstr "Netzwerk-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:757 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:556 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:759 msgid "No IP defined" msgstr "" @@ -685,16 +709,16 @@ msgstr "" msgid "No IPv6 access" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:577 msgid "No Server http response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:573 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:773 msgid "No Server ping response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 msgid "No WAN with multipath enabled:" msgstr "" @@ -702,16 +726,16 @@ msgstr "" msgid "No available backup on server." msgstr "Keine Konfigurations-Sicherung des Routers auf dem Server verfügbar." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:370 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:382 msgid "No change" msgstr "Keine Änderungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:819 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:821 msgid "No data" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:761 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:560 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:763 msgid "No gateway defined" msgstr "" @@ -733,12 +757,12 @@ msgstr "" msgid "No server defined" msgstr "Allgemeine Servereinstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:413 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:421 msgid "None" msgstr "Keine" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 msgid "Normal" msgstr "" @@ -760,25 +784,25 @@ msgstr "Verschleierungs-Typ" msgid "Obfuscating will be enabled on both side" msgstr "Die Verschleierung wird auf beiden Seiten aktiviert." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:380 msgid "On wizard change" msgstr "Bei Änderungen mittels des Assistenten" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:143 msgid "Only one server can be master, else all servers are set as backup." msgstr "Nur eine Verbindung kann als 'primär' definiert werden." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "Only work with Shadowsocks as proxy." msgstr "Funktioniert nur mit Shadowsocks als Proxy." @@ -786,7 +810,7 @@ msgstr "Funktioniert nur mit Shadowsocks als Proxy." msgid "OpenMPTCProuter" msgstr "OpenMPTCProuter" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "" @@ -794,64 +818,64 @@ msgstr "" msgid "Optimize for latency instead of bandwidth" msgstr "Für niedrige Latenz anstatt für Bandbreite optimieren" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 #, fuzzy msgid "Other" msgstr "Andere" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 #, fuzzy msgid "Other settings" msgstr "Server-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:839 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:844 msgid "PAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "PAP/CHAP" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:852 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:857 #, fuzzy msgid "PAP/CHAP password" msgstr "MLVPN Schlüssel" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 msgid "PAP/CHAP username" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:815 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:820 msgid "PIN code" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:611 msgid "PPPoE" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:573 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:614 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:581 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 #, fuzzy msgid "Physical interface" msgstr "Interface hinzufügen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "Prefer LTE" msgstr "Bevorzuge LTE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:831 msgid "Prefer UMTS" msgstr "Bevorzuge UMTS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:102 #, fuzzy msgid "Primary server IP" msgstr "Server IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 msgid "Protocol" msgstr "Protokoll" @@ -859,20 +883,24 @@ msgstr "Protokoll" msgid "Proxy is DISABLED" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:220 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 #, fuzzy msgid "Proxy settings" msgstr "VPN-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 msgid "Proxy traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:604 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:612 msgid "QMI" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:980 +msgid "QoS permit to prioritize any upload traffic." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:393 msgid "Qualcomm Shortcut FE driver" msgstr "" @@ -880,7 +908,7 @@ msgstr "" msgid "Redirects all ports from server to this router" msgstr "Weiterleitung aller Ports vom Server auf den Router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1054 msgid "Reset" msgstr "" @@ -888,33 +916,43 @@ msgstr "" msgid "Restore backup" msgstr "Parameter-Sicherung auf den Router wiederherstellen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:179 #, fuzzy msgid "Retrieve settings from server" msgstr "API Benutzername zum Download der Settings vom Server." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:435 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:957 +msgid "SQM autorate is for LTE and connection without a stable speed." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:947 +msgid "" +"SQM control bufferloat: the undesirable latency that arises when the router " +"buffers too much data." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:447 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1053 msgid "Save & Apply" msgstr "Speichern und Anwenden" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:239 msgid "Save vnstats statistics on disk" msgstr "vnstat-Daten fortlaufend auf Datenträger schreiben" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:234 msgid "Save vnstats stats" msgstr "Speichern der vnstat-Daten" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:427 msgid "Scaling governor" msgstr "Methode der CPU-Taktung" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:103 msgid "Secondary server IP" msgstr "zweite Server IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1047 msgid "Select the device you want to base the interface on." msgstr "Schnittstelle auswählen für diese Verbindung" @@ -922,64 +960,64 @@ msgstr "Schnittstelle auswählen für diese Verbindung" msgid "Send backup" msgstr "Parameter-Sicherung vom Router auf den Server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 msgid "Server IP" msgstr "Server IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:87 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 #, fuzzy msgid "Server IP will be set for proxy and VPN" msgstr "" "Die Server-IP wird für die Protokolle ShadowSockes, Glorytun, OpenVPN und " "MLVPN verwendet." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:126 msgid "Server key" msgstr "Server-Schlüssel" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:75 msgid "Server settings" msgstr "Server-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:114 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 msgid "Server username" msgstr "Server-Benutzername" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Service Type" msgstr "Dienst Typ" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:409 msgid "Set VPN to use for MPTCP over VPN." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:696 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 msgid "Set an IP in the same network as the modem" msgstr "IP-Adresse im gleichen Subnetz wie das Modem angeben" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:408 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 msgid "Set configuration for countries with some specificities." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:702 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 msgid "Set here IP of the modem" msgstr "IPv4 des Modems" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 msgid "Set server as master" msgstr "Server als 'primär' definieren" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 #, fuzzy msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " @@ -988,7 +1026,7 @@ msgstr "" "Auswahl des VPNs für UDP und ICMP (Sofern ShadowSocks für TCP aktiv ist. " "Andernfalls auch für TCP)" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 #, fuzzy msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " @@ -997,14 +1035,14 @@ msgstr "" "Auswahl des VPNs für UDP und ICMP (Sofern ShadowSocks für TCP aktiv ist. " "Andernfalls auch für TCP)" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:943 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" "Wert von etwa 80-95% der Downstream-Bandbreite; '0' zum Abschalten von SQM/" "QoS." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:959 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1014 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" @@ -1020,16 +1058,16 @@ msgstr "Parametrierungs-Assistent" msgid "ShadowSocks is not running" msgstr "Einstellungen ShadowSocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 msgid "ShadowSocks is used for TCP." msgstr "SchadowSocks wird für TCP genutzt." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 msgid "ShadowSocks key" msgstr "ShadowSocks Schlüssel" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 #, fuzzy msgid "Show advanced settings" msgstr "Erweiterte Einstellungen" @@ -1038,8 +1076,8 @@ msgstr "Erweiterte Einstellungen" msgid "Show all settings" msgstr "Alle Einstellungen anzeigen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:606 msgid "Static address" msgstr "Statische Adresse" @@ -1047,7 +1085,7 @@ msgstr "Statische Adresse" msgid "Status" msgstr "Status" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:400 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:412 msgid "Systems settings" msgstr "System-Einstellungen" @@ -1058,7 +1096,7 @@ msgid "" "local end." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:278 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -1079,35 +1117,35 @@ msgid "" "retransmissions remain unacknowledged." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:263 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 #, fuzzy msgid "Timeout for VPS checks on status pages" msgstr "Gateway-Ping Statusüberprüfung aus" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Timeout for retrieving WANs IP on status pages" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:367 msgid "Total traffic:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:567 msgid "Type" msgstr "Typ" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "" "UBOND kann ersatzweise für Glorytun genutzt werden, sofern die Verbindungen " "über identische Latenz verfügen." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:326 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:328 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:334 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:336 msgid "UBOND password" msgstr "UBOND Schlüssel" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:833 msgid "UMTS/GPRS" msgstr "" @@ -1125,17 +1163,17 @@ msgstr "automatische Aktualiserung des Servers" msgid "Update server" msgstr "Aktualisierung des Servers" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:949 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1004 msgid "Upload speed (Kb/s)" msgstr "Upstream-Bandbreite (kBit/s)" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "Uptime:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:938 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:954 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1009 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "" "Nutzung durch Glorytun für UDP und SQM/QoS, sofern aktiv. '0' für den " @@ -1145,21 +1183,21 @@ msgstr "" msgid "V2Ray is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 #, fuzzy msgid "V2Ray is used for TCP and UDP." msgstr "SchadowSocks wird für TCP genutzt." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "V2Ray user" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 msgid "V2Ray user id" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:643 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:644 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:651 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:652 msgid "VLAN" msgstr "" @@ -1167,11 +1205,11 @@ msgstr "" msgid "VPN is not running" msgstr "VPN läuft nicht" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:294 msgid "VPN settings" msgstr "VPN-Einstellungen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 msgid "VPN traffic:" msgstr "" @@ -1179,21 +1217,21 @@ msgstr "" msgid "VPN tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 msgid "VPS checks timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 msgid "Version" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 msgid "WAN IPs retrieve timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:584 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:775 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:586 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:591 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:777 msgid "Wan IP and gateway are identical" msgstr "" @@ -1203,15 +1241,20 @@ msgid "" "used to go outside." msgstr "Externe Prüfung der IP-Adressen der WAN-Adapter und der Server-IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 +#, fuzzy +msgid "When proxy V2Ray is used, use it for UDP" +msgstr "SchadowSocks wird für TCP genutzt." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 msgid "Wizard" msgstr "Assistent" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:422 msgid "World" msgstr "" @@ -1220,17 +1263,23 @@ msgstr "" msgid "You" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:918 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:934 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "" "'MPTCP over VPN' kann genutzt werden für Anschlüsse auf denen der Anbieter " "Multipath-TCP filtert." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:907 +msgid "" +"You can force a TTL. Some LTE provider detect tethering by inpecting packet " +"TTL value, setting it to 65 often solve the issue." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:617 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." @@ -1238,28 +1287,22 @@ msgstr "" "'DHCPclient' kann auf auf unabhängigen Schnittstellen genutzt werden. Andere " "Protokolle sind unter 'Netzwerk'/'Schnittstellen' einstellbar." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:204 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:212 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:538 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" "'DHCP' muss für diese Modems abgeschaltet und die IP-Adresse in ein andere " "Subnetz geändert werden." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "" "Server benötigt nutzbares IPv6. Andernfalls mit diesem Schalter die Nutzung " "sperren." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:928 -msgid "You should disable SQM for LTE or any interfaces with variable speed." -msgstr "" -"SQM sollte abgeschaltet werden für LTE und andere Verbindungen mit " -"variierender Geschwindigkeit." - #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:58 msgid "You shouldn't do that and you should redirect only needed ports" msgstr "" @@ -1273,7 +1316,7 @@ msgstr "" msgid "address:" msgstr "IPv4-Adresse" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 msgid "auto" msgstr "" @@ -1281,46 +1324,46 @@ msgstr "" msgid "empty key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:506 #, fuzzy msgid "interface:" msgstr "Interface hinzufügen" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:488 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:737 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:490 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:739 #, fuzzy msgid "ip address:" msgstr "Statische Adresse" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:492 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:494 #, fuzzy msgid "ipv6 address:" msgstr "Statische Adresse" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:751 msgid "latency:" msgstr "Latenz:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:755 msgid "mtu:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:644 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:808 msgid "multipath:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:526 msgid "operator:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 msgid "other" msgstr "andere" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:528 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:530 msgid "phone number:" msgstr "" @@ -1328,30 +1371,36 @@ msgstr "" msgid "range:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:532 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:534 msgid "state:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:647 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:649 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:811 msgid "traffic control:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:498 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:743 msgid "wan address:" msgstr "öffentliche IP Adresse:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:502 msgid "wan ipv6 address:" msgstr "öffentliche ipv6 Adresse:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:747 msgid "whois:" msgstr "" +#~ msgid "" +#~ "You should disable SQM for LTE or any interfaces with variable speed." +#~ msgstr "" +#~ "SQM sollte abgeschaltet werden für LTE und andere Verbindungen mit " +#~ "variierender Geschwindigkeit." + #~ msgid "Common server settings" #~ msgstr "Allgemeine Servereinstellungen" diff --git a/luci-app-openmptcprouter/po/fr/openmptcprouter.po b/luci-app-openmptcprouter/po/fr/openmptcprouter.po index 5f1b0670d..b48aaa23c 100644 --- a/luci-app-openmptcprouter/po/fr/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/fr/openmptcprouter.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-02-19 07:53+0000\n" +"PO-Revision-Date: 2022-08-10 18:51+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,45 +11,45 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.6.1\n" +"X-Generator: Weblate 4.10.1\n" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "" "Dead Simple VPN est un VPN exploitant le protocole TCP qui peut remplacer " "Glorytun TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:302 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:312 msgid "A Dead Simple VPN key" msgstr "Clef Dead Simple VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" "Si une connexion WAN a une connectivité IPv6, une seconde adresse IP peut " "être définie pour les VPS fonctionnant à la fois avec IPv4 et IPv6." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:119 msgid "API username to retrieve personnalized settings from the server." msgstr "" "Nom d'utilisateur pour récupérer la configuration personnalisée depuis le " "serveur." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:814 msgid "APN" msgstr "APN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:742 msgid "Accept IPv6 RA" msgstr "Accepter IPv6 RA" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:156 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:164 msgid "Add a new server" msgstr "Ajouter un serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:989 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1044 msgid "Add an interface" msgstr "Ajouter une interface" @@ -58,11 +58,11 @@ msgstr "Ajouter une interface" msgid "Advanced Settings" msgstr "Configuration avancée" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 msgid "Advanced settings" msgstr "Configuration avancée" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -74,18 +74,18 @@ msgstr "" msgid "All router settings" msgstr "Tous les paramètres du routeur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:284 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." msgstr "Les instruction AES sont intégrées dans le processeur." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "Authentication Type" msgstr "Type d'authentification" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:878 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:894 msgid "Backup" msgstr "Remplaçant" @@ -94,7 +94,7 @@ msgstr "Remplaçant" msgid "Backup on server" msgstr "Sauvegarde sur le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:383 msgid "Balancing" msgstr "Équilibrage" @@ -102,34 +102,42 @@ msgstr "Équilibrage" msgid "Beta" msgstr "Bêta" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:312 msgid "Big time difference between the server and the router" msgstr "Grande différence de temps entre le serveur et le routeur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 msgid "Bridge" msgstr "Passerelle" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:620 msgid "Bridge can't have multipath enabled" msgstr "Les passerelles ne peuvent pas utiliser le protocole multipath" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "By default VPN is used for any traffic that is not TCP." msgstr "" "Par défaut le VPN est utilisé pour tout le trafic n'étant pas une connexion " "TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" "Par défaut, le proxy est utilisé pour tout le trafic TCP (et UDP pour V2Ray)." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:845 msgid "CHAP" msgstr "CHAP" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:961 +msgid "" +"Cake queue discipline is not set, autorate will only work after a reboot if " +"enabled here." +msgstr "" +"La discipline de file d'attente Cake n'est pas définie, l'écriture ne " +"fonctionnera qu'après un redémarrage si elle est activée ici." + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 msgid "Can\\'t access and use server part" msgstr "Impossible d\\'accéder et d\\'utiliser la partie serveur" @@ -150,11 +158,11 @@ msgstr "Pas d'adresse IP publique récupérée via V2Ray" msgid "Can\\'t ping server" msgstr "Pas de réponse du serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:423 msgid "China" msgstr "Chine" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." @@ -162,9 +170,9 @@ msgstr "" "Choisissez MacVLAN si vous souhaitez créer une interface virtuelle basée sur " "une interface physique." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:596 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:655 msgid "Choose physical interface." msgstr "Choisissez l'interface physique." @@ -172,20 +180,20 @@ msgstr "Choisissez l'interface physique." msgid "Core temp:" msgstr "Température du cœur :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:418 msgid "Country" msgstr "Pays" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 msgid "Country settings" msgstr "Paramètres de Pays" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 msgid "DHCP" msgstr "DHCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 msgid "DHCPv6" msgstr "DHCPv6" @@ -193,35 +201,35 @@ msgstr "DHCPv6" msgid "DNS issue: can\\'t resolve hostname" msgstr "Erreur DNS : impossible de résoudre des noms d\\'hôtes" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:367 msgid "Debug" msgstr "Déboguer" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:231 msgid "Default Proxy" msgstr "Proxy par défaut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:345 msgid "Default VPN" msgstr "VPN par défaut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:543 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:551 msgid "Delete" msgstr "Supprimer" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:741 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:774 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 msgid "Device" msgstr "Périphérique" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 -msgid "Disable HTTP test on Server API in status page" -msgstr "Désactiver le test HTTP sur l'API du serveur dans la page d'état" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 +msgid "Disable HTTP test on Server API" +msgstr "Désactiver le test HTTP sur l'API" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:357 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 msgid "Disable ModemManager" msgstr "Désactiver ModemManager" @@ -234,11 +242,11 @@ msgid "Disable TCP Fast Open on Linux and Shadowsocks configuration" msgstr "" "Désactiver TCP Fast Open sur Linux et dans la configuration de Shadowsocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 msgid "Disable default gateway" msgstr "Désactiver la passerelle par défaut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:312 msgid "Disable default gateway, no internet if VPS are down" msgstr "" "Désactivez la passerelle par défaut, pas d'Internet si les VPS sont en panne" @@ -247,27 +255,27 @@ msgstr "" msgid "Disable external check" msgstr "Désactiver les tests externes" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:244 msgid "Disable gateway ping" msgstr "Désactiver le ping vers la passerelle" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:249 msgid "Disable gateway ping check in status page" msgstr "Désactiver le test ping de la passerelle dans la page d'état" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:285 msgid "Disable interfaces auto rename" msgstr "Désactiver le renommage automatique des interfaces" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:342 msgid "Disable multipath test using tracebox" msgstr "Désactiver le test multipath à l'aide de tracebox" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 msgid "Disable nDPI" msgstr "Désactiver nDPI" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 msgid "Disable nDPI, used for protocols in OMR-ByPass" msgstr "Désactiver nDPI, utilisé pour les protocoles dans OMR-ByPass" @@ -278,70 +286,82 @@ msgstr "" "Désactiver les redirections de ports définies dans la partie pare-feu du " "serveur vers ce routeur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 msgid "Disable renaming interfaces" msgstr "Désactiver les interfaces de renommage" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 msgid "Disable route loop detection" msgstr "Désactiver la détection de boucle de routage" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 msgid "Disable server" msgstr "Désactiver le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:254 msgid "Disable server http test" msgstr "Désactiver le test HTTP vers le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 msgid "Disable server ping" msgstr "Désactiver le ping vers le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:322 msgid "Disable server ping status check" msgstr "Désactiver le test ping vers le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:337 msgid "Disable tracebox test" msgstr "Désactiver le test de tracebox" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:876 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:892 msgid "Disabled" msgstr "Désactiver" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:988 msgid "Download speed (Kb/s)" msgstr "Vitesse de téléchargement (Kb/s)" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 msgid "Dynamic change" msgstr "Changement dynamique" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:402 msgid "Enable Bridge Acceleration" msgstr "Activer l'accélération du pont" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 msgid "Enable DNS64" msgstr "Active DNS64" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:396 msgid "Enable Fast Patch offloading for connections" msgstr "Activer le déchargement Fast Patch pour les connexions" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 msgid "Enable IPv6" msgstr "Activer IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:923 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:975 +msgid "Enable QoS" +msgstr "Active QoS" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:223 +msgid "Enable SIP ALG" +msgstr "Activer SIP ALG" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:942 msgid "Enable SQM" msgstr "Active SQM" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 +msgid "Enable SQM autorate" +msgstr "Active SQM autoadaptatif" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:79 msgid "Enable ShadowSocks Obfuscating" msgstr "Activer le brouillage pour ShadowSocks" @@ -350,21 +370,21 @@ msgstr "Activer le brouillage pour ShadowSocks" msgid "Enable TCP Low Latency" msgstr "Activer la faible latence TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:372 msgid "Enable debug logs" msgstr "Activer les journaux de débogage" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:886 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:875 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:891 msgid "Enabled" msgstr "Activer" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 msgid "Encryption" msgstr "Chiffrement" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:288 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "" "La méthode de chiffrement est utilisée pour Shadowsocks, V2Ray, Glorytun et " @@ -374,37 +394,41 @@ msgstr "" msgid "Filesystem is readonly" msgstr "Système de fichiers en lecture seule" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "Pour la Chine, définir un DNS accessible et désactiver DNSSEC." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:902 +msgid "Force TTL" +msgstr "Force le TTL" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 msgid "Force retrieve all keys from server." msgstr "Forcer la récupération de toutes les clés du serveur." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 msgid "Force retrieve settings" msgstr "Forcer la récupération des paramètres" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:834 msgid "GPRS only" msgstr "seulement GPRS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:766 msgid "Gateway DOWN" msgstr "La passerelle ne répond pas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 msgid "Gateway IPv6 DOWN" msgstr "La passerelle IPv6 ne répond pas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "Glorytun est utilisé par défaut pour UDP et ICMP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:290 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:300 msgid "Glorytun key" msgstr "Clef Glorytun" @@ -446,40 +470,40 @@ msgstr "IPv4 TCP SYN retries1" msgid "IPv4 TCP SYN retries2" msgstr "IPv4 TCP SYN retries2" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:653 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:661 msgid "IPv4 address" msgstr "Adresse IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:677 msgid "IPv4 gateway" msgstr "Passerelle IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:663 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 msgid "IPv4 netmask" msgstr "Masque de sous-réseau IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 msgid "IPv6 Prefix" msgstr "Préfixe IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 msgid "IPv6 address" msgstr "Adresse IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:705 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 msgid "IPv6 gateway" msgstr "Passerelle IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 msgid "IPv6 route received" msgstr "Route IPv6 reçue" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 msgid "IPv6 settings" msgstr "Paramètres IPv6" @@ -487,30 +511,30 @@ msgstr "Paramètres IPv6" msgid "IPv6 tunnel DOWN" msgstr "Le tunnel IPv6 ne répond pas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 msgid "IPv6:" msgstr "IPv6 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:222 msgid "If host support NAT64, you can enable DNS64 support." msgstr "" "Si l'hôte prend en charge NAT64, vous pouvez activer la prise en charge " "DNS64." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 msgid "Interfaces settings" msgstr "Paramètres des interfaces" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "Key is retrieved from server API by default." msgstr "La clé est récupérée de l'API du serveur par défaut." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:129 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." @@ -518,21 +542,21 @@ msgstr "" "Clef pour configurer et récupérer les autres clefs ainsi que les paramètres " "depuis le serveur." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:435 msgid "LAN interfaces settings" msgstr "Paramètres des interfaces LAN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:832 msgid "LTE" msgstr "LTE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:438 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:549 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:446 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:557 msgid "Label" msgstr "Étiquette" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:452 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 msgid "Label for the interface" msgstr "Étiquette pour l'interface" @@ -541,25 +565,25 @@ msgid "Last available backup on server:" msgstr "Dernière sauvegarde disponible sur le serveur :" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:329 msgid "Latest available version" msgstr "Dernière version disponible" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:335 msgid "Load:" msgstr "Charge :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:628 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 msgid "Looping route detected" msgstr "Boucle de routage détectée" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "MLVPN peut remplacer Glorytun pour les connexions avec la même latence" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:314 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:316 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:324 msgid "MLVPN password" msgstr "Mot de passe MLVPN" @@ -567,20 +591,20 @@ msgstr "Mot de passe MLVPN" msgid "MPTCP is not enabled on the server" msgstr "MPTCP n'est pas activé sur le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:344 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 msgid "MPTCP may not be enabled on the server" msgstr "MPTCP semble ne pas être activé sur le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:393 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:913 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:929 msgid "MPTCP over VPN" msgstr "MPTCP sur VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:398 msgid "MPTCP over VPN settings" msgstr "Paramètres MPTCP sur VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." @@ -588,36 +612,36 @@ msgstr "" "MPTCP sur VPN ne doit être utilisé que lorsque Multipath TCP est bloqué sur " "une connexion." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 msgid "MacVLAN" msgstr "MacVLAN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:893 msgid "Master" msgstr "Master" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:377 msgid "Master interface selection" msgstr "Sélection de l'interface maître" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:409 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:421 msgid "Maximum scaling CPU frequency" msgstr "Fréquence maximale du processeur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:403 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 msgid "Minimum scaling CPU frequency" msgstr "Fréquence minimale du processeur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:824 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "Modem default" msgstr "Modem par défaut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:858 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:863 msgid "Modem init timeout" msgstr "Délai max. d'initialisation du modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:601 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 msgid "ModemManager" msgstr "ModemManager" @@ -625,51 +649,51 @@ msgstr "ModemManager" msgid "More than one default VPN is enabled" msgstr "Plus d\\'un VPN par défaut est activé" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:787 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:793 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:795 msgid "Multipath current state is" msgstr "Multipath est actuellement" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:784 msgid "Multipath master already defined" msgstr "Maître multipath déjà défini" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:569 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 msgid "Multipath seems to be blocked on the connection" msgstr "Multipath semble bloquer sur la connexion" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:610 msgid "NCM" msgstr "NCM" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:838 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:843 msgid "NONE" msgstr "AUCUN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:625 msgid "Network interface MAC address duplicated" msgstr "Adresse MAC dupliquée" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:615 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:801 msgid "Network interface duplicated" msgstr "Interface réseau dupliquée" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:581 msgid "Network interface not in WAN firewall zone" msgstr "L'interface réseau n'est pas dans la zone WAN du pare-feu" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:903 msgid "Network overview" msgstr "Aperçu réseau" @@ -677,8 +701,8 @@ msgstr "Aperçu réseau" msgid "Networks settings" msgstr "Paramètres réseaux" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:757 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:556 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:759 msgid "No IP defined" msgstr "Aucune IP définie" @@ -686,16 +710,16 @@ msgstr "Aucune IP définie" msgid "No IPv6 access" msgstr "Pas d'accès IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:577 msgid "No Server http response after 1 second" msgstr "Pas de réponse http du serveur après 1 seconde" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:573 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:773 msgid "No Server ping response after 1 second" msgstr "Pas de réponse au ping du serveur après 1 seconde" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 msgid "No WAN with multipath enabled:" msgstr "Pas de WAN avec le multipath activé :" @@ -703,16 +727,16 @@ msgstr "Pas de WAN avec le multipath activé :" msgid "No available backup on server." msgstr "Aucune sauvegarde disponible sur le serveur." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:370 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:382 msgid "No change" msgstr "Pas de changement" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:819 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:821 msgid "No data" msgstr "Pas de données" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:761 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:560 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:763 msgid "No gateway defined" msgstr "Aucune passerelle définie" @@ -733,12 +757,12 @@ msgstr "Pas d'adresse IP du serveur, pas d'adresse IP publique" msgid "No server defined" msgstr "Aucun serveur défini" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:413 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:421 msgid "None" msgstr "Aucun" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 msgid "Normal" msgstr "Normal" @@ -762,17 +786,17 @@ msgstr "Type de brouillage" msgid "Obfuscating will be enabled on both side" msgstr "Le brouillage sera activé des deux côtés" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:380 msgid "On wizard change" msgstr "En cas de changements dans l'assistant" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "" "Seul ShadowSocks est pris en charge pour la gestion d'un serveur ayant " "plusieurs adresses IP pour le moment." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." @@ -780,12 +804,12 @@ msgstr "" "Une seule interface peut être défini comme maître. Cette interface est " "supposée être l'interface la plus stable." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:143 msgid "Only one server can be master, else all servers are set as backup." msgstr "" "Uniquement un serveur peut être maître, les autres sont définis en secours." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "Only work with Shadowsocks as proxy." msgstr "Ne fonctionne qu’avec Shadowsocks utilisé en proxy." @@ -793,7 +817,7 @@ msgstr "Ne fonctionne qu’avec Shadowsocks utilisé en proxy." msgid "OpenMPTCProuter" msgstr "OpenMPTCProuter" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "OpenVPN ne peut pas être utilisé dans une configuration multi VPS." @@ -801,59 +825,59 @@ msgstr "OpenVPN ne peut pas être utilisé dans une configuration multi VPS." msgid "Optimize for latency instead of bandwidth" msgstr "Optimiser la latence au lieu de la bande passante" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 msgid "Other" msgstr "Autre" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 msgid "Other settings" msgstr "Autres paramètres" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:839 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:844 msgid "PAP" msgstr "PAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "PAP/CHAP" msgstr "PAP / CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:852 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:857 msgid "PAP/CHAP password" msgstr "Mot de passe PAP/CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 msgid "PAP/CHAP username" msgstr "Identifiant PAP/CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:815 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:820 msgid "PIN code" msgstr "Code PIN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:611 msgid "PPPoE" msgstr "PPPoE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:573 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:614 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:581 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 msgid "Physical interface" msgstr "Interface physique" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "Prefer LTE" msgstr "Préférer LTE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:831 msgid "Prefer UMTS" msgstr "Préférer l'UMTS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:102 msgid "Primary server IP" msgstr "IP principale du serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 msgid "Protocol" msgstr "Protocole" @@ -861,19 +885,23 @@ msgstr "Protocole" msgid "Proxy is DISABLED" msgstr "Le proxy est DÉSACTIVÉ" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:220 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 msgid "Proxy settings" msgstr "Paramètres du Proxy" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 msgid "Proxy traffic:" msgstr "Trafic proxy :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:604 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:612 msgid "QMI" msgstr "QMI" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:980 +msgid "QoS permit to prioritize any upload traffic." +msgstr "Le QoS permet de prioriser du trafic de téléchargement." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:393 msgid "Qualcomm Shortcut FE driver" msgstr "Pilote Qualcomm Shortcut FE" @@ -881,7 +909,7 @@ msgstr "Pilote Qualcomm Shortcut FE" msgid "Redirects all ports from server to this router" msgstr "Rediriger tous les ports du serveur vers ce routeur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1054 msgid "Reset" msgstr "Réinitialiser" @@ -889,32 +917,46 @@ msgstr "Réinitialiser" msgid "Restore backup" msgstr "Restauration de la sauvegarde" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:179 msgid "Retrieve settings from server" msgstr "Récupérer les paramètres du serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:435 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:957 +msgid "SQM autorate is for LTE and connection without a stable speed." +msgstr "" +"SQM autoadaptatif est prévu pour les connexions LTE ainsi que toutes les " +"connexions n'ayant pas une vitesse stable." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:947 +msgid "" +"SQM control bufferloat: the undesirable latency that arises when the router " +"buffers too much data." +msgstr "" +"SQM contrôle le bufferloat : la latence indésirable qui survient lorsque le " +"routeur met trop de données en mémoire tampon." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:447 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1053 msgid "Save & Apply" msgstr "Sauvegarder et Appliquer" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:239 msgid "Save vnstats statistics on disk" msgstr "Sauvegarder les statistiques de vnstats sur le disque" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:234 msgid "Save vnstats stats" msgstr "Sauvegarder les statistiques de vnstats" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:427 msgid "Scaling governor" msgstr "Régulateur de mise à l'échelle" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:103 msgid "Secondary server IP" msgstr "IP secondaire du serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1047 msgid "Select the device you want to base the interface on." msgstr "Sélectionnez le périphérique pour l'interface." @@ -922,61 +964,61 @@ msgstr "Sélectionnez le périphérique pour l'interface." msgid "Send backup" msgstr "Envoyer la sauvegarde" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 msgid "Server IP" msgstr "IP du serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:87 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 msgid "Server IP will be set for proxy and VPN" msgstr "L'adresse IP du serveur sera définie pour le proxy et le VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:126 msgid "Server key" msgstr "Clef du serveur" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:75 msgid "Server settings" msgstr "Paramètres du serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:114 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 msgid "Server username" msgstr "Nom d'utilisateur sur le serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Service Type" msgstr "Type du service" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:409 msgid "Set VPN to use for MPTCP over VPN." msgstr "Configurez VPN à utiliser pour MPTCP sur VPN." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:696 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 msgid "Set an IP in the same network as the modem" msgstr "Mettez une IP dans le même réseau que le modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:408 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 msgid "Set configuration for countries with some specificities." msgstr "Définir une configuration spécifique pour certains pays." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:702 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 msgid "Set here IP of the modem" msgstr "Mettez ici l'IP du modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 msgid "Set server as master" msgstr "Configurer le serveur en tant que maître" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." @@ -984,7 +1026,7 @@ msgstr "" "Définissez le proxy par défaut utilisé pour TCP lorsque ShadowSocks est " "activé, pour TCP et UDP lorsque V2Ray est activé." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " "for all traffic if proxy is disabled." @@ -992,14 +1034,14 @@ msgstr "" "Configure le VPN utilisé par défaut pour ICMP (et UDP si le proxy est " "ShadowSocks), pour tout le trafic quand le proxy est désactivé." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:943 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" "Réglez une valeur entre 80-95% de la vitesse de téléchargement maximale. 0 " "pour désactiver SQM/QoS." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:959 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1014 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" @@ -1014,16 +1056,16 @@ msgstr "Assistant de configuration" msgid "ShadowSocks is not running" msgstr "ShadowSocks n'est pas lancé" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 msgid "ShadowSocks is used for TCP." msgstr "ShadowSocks est utilisé pour le TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 msgid "ShadowSocks key" msgstr "Clef de ShadowSocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 msgid "Show advanced settings" msgstr "Afficher les paramètres avancés" @@ -1031,8 +1073,8 @@ msgstr "Afficher les paramètres avancés" msgid "Show all settings" msgstr "Voir tous les paramètres" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:606 msgid "Static address" msgstr "Adresse statique" @@ -1040,7 +1082,7 @@ msgstr "Adresse statique" msgid "Status" msgstr "État" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:400 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:412 msgid "Systems settings" msgstr "Paramètres systèmes" @@ -1054,7 +1096,7 @@ msgstr "" "référencée par aucune application) restera dans l'état FIN_WAIT_2 avant " "d'être abandonnée à l'extrémité locale." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:278 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -1080,34 +1122,34 @@ msgstr "" "Cette valeur influence le délai d'expiration d'une connexion TCP active, " "lorsque les retransmissions RTO ne sont pas acquittées." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:263 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 msgid "Timeout for VPS checks on status pages" msgstr "Délai d’expiration pour les vérifications VPS sur la page d’état" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Timeout for retrieving WANs IP on status pages" msgstr "" "Délai d’expiration pour la récupération de l’adresse IP des WANs sur la " "pages d’état" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:367 msgid "Total traffic:" msgstr "Trafic total :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:567 msgid "Type" msgstr "Type" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "UBOND peut remplacer Glorytun par des connexions avec la même latence" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:326 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:328 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:334 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:336 msgid "UBOND password" msgstr "Mot de passe UBOND" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:833 msgid "UMTS/GPRS" msgstr "UMTS / GPRS" @@ -1124,17 +1166,17 @@ msgstr "Met à jour le serveur à la dernière version quand c'est nécessaire." msgid "Update server" msgstr "Mise à jour du serveur" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:949 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1004 msgid "Upload speed (Kb/s)" msgstr "Vitesse d'envoi (Kb/s)" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "Uptime:" msgstr "Durée de fonctionnement :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:938 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:954 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1009 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "" "Utilisé par Glorytun UDP et SQM/QoS si activé. 0 pour utiliser la valeur par " @@ -1144,20 +1186,20 @@ msgstr "" msgid "V2Ray is not running" msgstr "V2Ray n'est pas lancé" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 msgid "V2Ray is used for TCP and UDP." msgstr "V2Ray est utilisé pour TCP et UDP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "V2Ray user" msgstr "Utilisateur V2Ray" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 msgid "V2Ray user id" msgstr "ID utilisateur V2Ray" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:643 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:644 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:651 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:652 msgid "VLAN" msgstr "VLAN" @@ -1165,11 +1207,11 @@ msgstr "VLAN" msgid "VPN is not running" msgstr "Le VPN n'est pas lancé" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:294 msgid "VPN settings" msgstr "Paramètres du VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 msgid "VPN traffic:" msgstr "Trafic VPN :" @@ -1177,21 +1219,21 @@ msgstr "Trafic VPN :" msgid "VPN tunnel DOWN" msgstr "Le VPN ne répond pas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 msgid "VPS checks timeout" msgstr "Délai d’expiration des contrôles VPS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 msgid "Version" msgstr "Version" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 msgid "WAN IPs retrieve timeout" msgstr "Délai d'expiration pour la récupération des IPs WANs" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:584 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:775 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:586 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:591 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:777 msgid "Wan IP and gateway are identical" msgstr "La passerelle et l'adresse IP du WAN sont identiques" @@ -1201,17 +1243,21 @@ msgid "" "used to go outside." msgstr "Utilise des sites externes pour obtenir les IPs externes quand activé." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 +msgid "When proxy V2Ray is used, use it for UDP" +msgstr "Lorsque le proxy V2Ray est utilisé, l'utiliser pour UDP" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "" "Lorsque le proxy shadowsocks est utilisé, utilisez-le pour UDP si VPN en " "panne" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 msgid "Wizard" msgstr "Assistant" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:422 msgid "World" msgstr "Monde" @@ -1220,18 +1266,27 @@ msgstr "Monde" msgid "You" msgstr "Vous" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:918 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:934 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "" "Vous pouvez utiliser MTPCP over VPN si votre fournisseur filtre Multipath " "TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:907 +msgid "" +"You can force a TTL. Some LTE provider detect tethering by inpecting packet " +"TTL value, setting it to 65 often solve the issue." +msgstr "" +"Vous pouvez forcer un TTL. Certains fournisseur détecte le partage de " +"connexion en inspectant la valeur TTL des paquets, une valeur de 65 règle " +"souvent le souci." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "" "Vous pouvez utiliser DHCP si vous avez plusieurs ports Ethernet physique." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:617 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." @@ -1240,28 +1295,22 @@ msgstr "" "Choisissez autre si vous utilisez un autre protocole dans la page Réseau " "Interfaces." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:204 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:212 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" "Vous ne pouvez utiliser un préfixe IPv6 public que si vous ne définissez " "qu'un seul serveur." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:538 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" "Vous devez désactiver DHCP sur vos modems et configurer leurs IP dans des " "réseaux différents." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "Vous devriez désactiver IPv6 ici si le serveur ne supporte pas IPv6." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:928 -msgid "You should disable SQM for LTE or any interfaces with variable speed." -msgstr "" -"Vous devriez désactiver SQM pour la 4G ou toute interface avec une vitesse " -"très instable." - #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:58 msgid "You shouldn't do that and you should redirect only needed ports" msgstr "" @@ -1276,7 +1325,7 @@ msgstr "Votre IP n'a pas été attribuée par ce routeur" msgid "address:" msgstr "adresse :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 msgid "auto" msgstr "auto" @@ -1284,43 +1333,43 @@ msgstr "auto" msgid "empty key" msgstr "clef vide" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:506 msgid "interface:" msgstr "interface :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:488 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:737 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:490 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:739 msgid "ip address:" msgstr "adresse ip :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:492 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:494 msgid "ipv6 address:" msgstr "adresse ipv6 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:751 msgid "latency:" msgstr "latence :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:755 msgid "mtu:" msgstr "mtu :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:644 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:808 msgid "multipath:" msgstr "multipath :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:526 msgid "operator:" msgstr "opérateur :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 msgid "other" msgstr "autre" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:528 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:530 msgid "phone number:" msgstr "Numéro de téléphone :" @@ -1328,30 +1377,36 @@ msgstr "Numéro de téléphone :" msgid "range:" msgstr "plage :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:532 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:534 msgid "state:" msgstr "État :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:647 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:649 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:811 msgid "traffic control:" msgstr "Contrôle du trafic :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:498 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:743 msgid "wan address:" msgstr "adresse WAN :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:502 msgid "wan ipv6 address:" msgstr "adresse WAN IPv6 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:747 msgid "whois:" msgstr "whois :" +#~ msgid "" +#~ "You should disable SQM for LTE or any interfaces with variable speed." +#~ msgstr "" +#~ "Vous devriez désactiver SQM pour la 4G ou toute interface avec une " +#~ "vitesse très instable." + #~ msgid "Common server settings" #~ msgstr "Paramètres des serveurs" diff --git a/luci-app-openmptcprouter/po/it/openmptcprouter.po b/luci-app-openmptcprouter/po/it/openmptcprouter.po index 6d4ddf076..eeffeb590 100644 --- a/luci-app-openmptcprouter/po/it/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/it/openmptcprouter.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2022-02-19 10:30+0000\n" +"PO-Revision-Date: 2022-08-12 12:08+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: Italian \n" @@ -10,40 +10,40 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.10.1\n" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "Una Dead Simple VPN è una VPN TCP che può sostituire Glorytun TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:302 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:312 msgid "A Dead Simple VPN key" msgstr "Chiave Dead Simple VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" "Può essere impostato un secondo IP per il doppio server IPv4/IPv6 se è stato " "impostato il server WAN IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:119 msgid "API username to retrieve personnalized settings from the server." msgstr "" "Nome utente API per recuperare le impostazioni personalizzate dal server." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:814 msgid "APN" msgstr "APN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:742 msgid "Accept IPv6 RA" -msgstr "" +msgstr "Accetta IPv6 RA" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:156 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:164 msgid "Add a new server" msgstr "Aggiungi un nuovo server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:989 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1044 msgid "Add an interface" msgstr "Aggiungi un'interfaccia" @@ -52,11 +52,11 @@ msgstr "Aggiungi un'interfaccia" msgid "Advanced Settings" msgstr "Impostazioni avanzate" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 msgid "Advanced settings" msgstr "Impostazioni avanzate" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -68,7 +68,7 @@ msgstr "" msgid "All router settings" msgstr "Impostazioni del router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:284 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." @@ -76,12 +76,12 @@ msgstr "" "Un set di istruzioni Advanced Encryption Standard (AES) è integrato nel " "processore." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "Authentication Type" msgstr "Tipo di autenticazione" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:878 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:894 msgid "Backup" msgstr "Backup" @@ -90,7 +90,7 @@ msgstr "Backup" msgid "Backup on server" msgstr "Backup su server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:383 msgid "Balancing" msgstr "Bilanciamento" @@ -98,35 +98,41 @@ msgstr "Bilanciamento" msgid "Beta" msgstr "Beta" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:312 msgid "Big time difference between the server and the router" msgstr "Grande differenza di fuso orario tra il server e il router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 msgid "Bridge" msgstr "Ponte" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:620 msgid "Bridge can't have multipath enabled" msgstr "Il Bridge non può avere il multipath abilitato" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "By default VPN is used for any traffic that is not TCP." msgstr "" "Per impostazione predefinita, la VPN viene utilizzata per qualsiasi traffico " "che non sia TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" "Per impostazione predefinita, il proxy viene utilizzato per qualsiasi " "traffico che sia TCP (e UDP per V2Ray)." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:845 msgid "CHAP" msgstr "CHAP" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:961 +msgid "" +"Cake queue discipline is not set, autorate will only work after a reboot if " +"enabled here." +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 msgid "Can\\'t access and use server part" msgstr "Impossibile accedere e utilizzare la parte server" @@ -147,11 +153,11 @@ msgstr "Impossibile ottenere un indirizzo IP pubblico da V2Ray" msgid "Can\\'t ping server" msgstr "Impossibile eseguire il ping del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:423 msgid "China" msgstr "Cina" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." @@ -159,9 +165,9 @@ msgstr "" "Scegli MacVLAN se desideri creare un'interfaccia virtuale basata su " "un'interfaccia fisica." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:596 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:655 msgid "Choose physical interface." msgstr "Scegli l'interfaccia fisica." @@ -169,20 +175,20 @@ msgstr "Scegli l'interfaccia fisica." msgid "Core temp:" msgstr "Temp. Nucleo:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:418 msgid "Country" msgstr "Nazione" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 msgid "Country settings" msgstr "Impostazioni nazionali del router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 msgid "DHCP" msgstr "DHCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 msgid "DHCPv6" msgstr "DHCPv6" @@ -190,35 +196,37 @@ msgstr "DHCPv6" msgid "DNS issue: can\\'t resolve hostname" msgstr "Problema DNS: impossibile risolvere il nome host" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:367 msgid "Debug" msgstr "Debug" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:231 msgid "Default Proxy" msgstr "Proxy predefinito" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:345 msgid "Default VPN" msgstr "VPN predefinita" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:543 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:551 msgid "Delete" msgstr "Elimina" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:741 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:774 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 msgid "Device" msgstr "Dispositivo" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 -msgid "Disable HTTP test on Server API in status page" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 +#, fuzzy +#| msgid "Disable HTTP test on Server API in status page" +msgid "Disable HTTP test on Server API" msgstr "Disabilitare il test HTTP sulle API Server nella pagina di stato" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:357 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 msgid "Disable ModemManager" msgstr "Disabilita ModemManager" @@ -230,11 +238,11 @@ msgstr "Disabilita TCP Fast Open" msgid "Disable TCP Fast Open on Linux and Shadowsocks configuration" msgstr "Disabilita TCP Fast Open su Linux e configurazione Shadowsocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 msgid "Disable default gateway" msgstr "Disabilita il gateway predefinito" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:312 msgid "Disable default gateway, no internet if VPS are down" msgstr "" "Disabilita il gateway predefinito, niente Internet se i VPS sono inattivi" @@ -243,27 +251,27 @@ msgstr "" msgid "Disable external check" msgstr "Disabilita controllo esterno" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:244 msgid "Disable gateway ping" msgstr "Disabilita il ping del gateway" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:249 msgid "Disable gateway ping check in status page" msgstr "Disabilita il controllo del ping del gateway nella pagina di stato" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:285 msgid "Disable interfaces auto rename" msgstr "Disabilita auto rinomina interfacce" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:342 msgid "Disable multipath test using tracebox" msgstr "Disabilita il test multipath usando tracebox" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 msgid "Disable nDPI" msgstr "Disabilita nDPI" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 msgid "Disable nDPI, used for protocols in OMR-ByPass" msgstr "" @@ -274,71 +282,85 @@ msgstr "" "Disabilita il reindirizzamento delle porte definito nel firewall dal server " "a questo router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 msgid "Disable renaming interfaces" msgstr "Disabilita rinomina interfaccia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 #, fuzzy msgid "Disable route loop detection" msgstr "Disabilita il ping del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 msgid "Disable server" msgstr "Disabilita il server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:254 msgid "Disable server http test" msgstr "Disabilita http test server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 msgid "Disable server ping" msgstr "Disabilita il ping del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:322 msgid "Disable server ping status check" msgstr "Disabilitare il controllo dello stato del ping del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:337 msgid "Disable tracebox test" msgstr "Disabilita il test Tracebox" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:876 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:892 msgid "Disabled" msgstr "Disabilitato" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:988 msgid "Download speed (Kb/s)" msgstr "Velocità di download (Kb / s)" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 msgid "Dynamic change" msgstr "Cambiamento dinamico" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:402 msgid "Enable Bridge Acceleration" msgstr "Abilita Accelerazione modalità Bridge" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 msgid "Enable DNS64" msgstr "Abilita DNS64" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:396 msgid "Enable Fast Patch offloading for connections" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 msgid "Enable IPv6" msgstr "Abilita IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:923 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:975 +msgid "Enable QoS" +msgstr "Abilita QoS" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:223 +msgid "Enable SIP ALG" +msgstr "Abilita SIP ALG" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:942 msgid "Enable SQM" msgstr "Abilita MQ" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 +#, fuzzy +#| msgid "Enable SQM" +msgid "Enable SQM autorate" +msgstr "Abilita MQ" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:79 msgid "Enable ShadowSocks Obfuscating" msgstr "Abilita l'offuscamento di ShadowSocks" @@ -347,21 +369,21 @@ msgstr "Abilita l'offuscamento di ShadowSocks" msgid "Enable TCP Low Latency" msgstr "Abilita TCP bassa latenza" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:372 msgid "Enable debug logs" msgstr "Abilita registro di debug" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:886 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:875 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:891 msgid "Enabled" msgstr "Abilitato" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 msgid "Encryption" msgstr "Crittografia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:288 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "" "Il metodo di crittografia viene utilizzato per Shadowsocks, V2Ray, Glorytun " @@ -371,38 +393,42 @@ msgstr "" msgid "Filesystem is readonly" msgstr "Il filesystem è di sola lettura" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "Per la Cina, imposta un DNS accessibile e disabilita DNSSEC." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:902 +msgid "Force TTL" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 msgid "Force retrieve all keys from server." msgstr "Forza il recupero di tutte le chiavi dal server." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 msgid "Force retrieve settings" msgstr "Forza il recupero delle impostazioni" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:834 msgid "GPRS only" msgstr "Solo GPRS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:766 msgid "Gateway DOWN" msgstr "Tipi di pagamento" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 msgid "Gateway IPv6 DOWN" -msgstr "Gateway IPv6 SPENTO" +msgstr "Gateway IPV6 non raggiungibile" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "" "Glorytun TCP viene utilizzato per impostazione predefinita per UDP e ICMP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:290 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:300 msgid "Glorytun key" msgstr "Chiave Glorytun" @@ -444,40 +470,40 @@ msgstr "IPv4 TCP SYN retries1" msgid "IPv4 TCP SYN retries2" msgstr "IPv4 TCP SYN retries2" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:653 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:661 msgid "IPv4 address" msgstr "Indirizzi IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:677 msgid "IPv4 gateway" msgstr "Gateway IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:663 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 msgid "IPv4 netmask" msgstr "Netmask IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 msgid "IPv6 Prefix" msgstr "Prefisso IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 msgid "IPv6 address" msgstr "Indirizzi IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:705 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 msgid "IPv6 gateway" msgstr "Gateway IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 msgid "IPv6 route received" msgstr "Instradamento IPv6 ricevuto" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 msgid "IPv6 settings" msgstr "Impostazioni IPv6" @@ -485,30 +511,30 @@ msgstr "Impostazioni IPv6" msgid "IPv6 tunnel DOWN" msgstr "Tunnel IPv6 GIÙ" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 msgid "IPv6:" msgstr "IPv6:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:222 msgid "If host support NAT64, you can enable DNS64 support." msgstr "Se l'host supporta NAT64, puoi abilitare il supporto DNS64." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 msgid "Interfaces settings" msgstr "Impostazioni delle interfacce" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "Key is retrieved from server API by default." msgstr "" "La chiave viene recuperata dall'API del server per impostazione " "predefinita." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:129 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." @@ -516,21 +542,21 @@ msgstr "" "Tasto per configurare e recuperare altre chiavi dal server e per impostare " "le impostazioni del server da OpenMPTCProuter." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:435 msgid "LAN interfaces settings" msgstr "Impostazioni delle interfacce LAN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:832 msgid "LTE" msgstr "LTE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:438 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:549 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:446 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:557 msgid "Label" msgstr "Etichetta" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:452 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 msgid "Label for the interface" msgstr "Etichetta per l'interfaccia" @@ -539,25 +565,25 @@ msgid "Last available backup on server:" msgstr "Ultimo backup disponibile sul server:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:329 msgid "Latest available version" msgstr "Ultima versione disponibile" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:335 msgid "Load:" msgstr "Carico:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:628 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 msgid "Looping route detected" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "MLVPN può sostituire Glorytun con connessioni con la stessa latenza" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:314 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:316 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:324 msgid "MLVPN password" msgstr "Password MLVPN" @@ -565,20 +591,20 @@ msgstr "Password MLVPN" msgid "MPTCP is not enabled on the server" msgstr "MPTCP non è abilitato sul server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:344 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 msgid "MPTCP may not be enabled on the server" msgstr "MPTCP non è abilitato sul server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:393 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:913 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:929 msgid "MPTCP over VPN" msgstr "MPTCP su VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:398 msgid "MPTCP over VPN settings" msgstr "Impostazioni MPTCP su VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." @@ -586,36 +612,36 @@ msgstr "" "MPTCP su VPN deve essere usato solo quando il Multipath TCP è bloccatp su " "una connessione." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 msgid "MacVLAN" msgstr "MacVLAN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:893 msgid "Master" msgstr "Principale" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:377 msgid "Master interface selection" msgstr "Selezione dell'interfaccia principale" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:409 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:421 msgid "Maximum scaling CPU frequency" msgstr "Frequenza CPU di ridimensionamento massima" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:403 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 msgid "Minimum scaling CPU frequency" msgstr "Frequenza CPU con ridimensionamento minimo" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:824 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "Modem default" msgstr "Impostazione predefinita del modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:858 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:863 msgid "Modem init timeout" msgstr "Timeout inizializzazione modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:601 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 msgid "ModemManager" msgstr "ModemManager" @@ -623,51 +649,51 @@ msgstr "ModemManager" msgid "More than one default VPN is enabled" msgstr "È abilitata più di una VPN predefinita" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:787 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:793 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:795 msgid "Multipath current state is" msgstr "Lo stato corrente di Multipath è" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:784 msgid "Multipath master already defined" msgstr "Multipath principale già definito" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:569 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 msgid "Multipath seems to be blocked on the connection" msgstr "Multipath sembra essere bloccato sulla connessione" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:610 msgid "NCM" msgstr "NCM" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:838 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:843 msgid "NONE" msgstr "NESSUNO" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:625 msgid "Network interface MAC address duplicated" msgstr "Interfaccia di rete con MAC address duplicata" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:615 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:801 msgid "Network interface duplicated" msgstr "Interfaccia di rete duplicata" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:581 msgid "Network interface not in WAN firewall zone" msgstr "Interfaccia di rete non in WAN firewall zone" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:903 msgid "Network overview" msgstr "Panoramica della rete" @@ -675,8 +701,8 @@ msgstr "Panoramica della rete" msgid "Networks settings" msgstr "Impostazioni reti" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:757 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:556 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:759 msgid "No IP defined" msgstr "Nessun IP definito" @@ -684,16 +710,16 @@ msgstr "Nessun IP definito" msgid "No IPv6 access" msgstr "Nessun accesso IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:577 msgid "No Server http response after 1 second" msgstr "Nessuna risposta dal server HTTP dopo 1 secondo" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:573 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:773 msgid "No Server ping response after 1 second" msgstr "Nessuna risposta al ping dal server dopo 1 secondo" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 msgid "No WAN with multipath enabled:" msgstr "Nessuna WAN con multipath abilitata:" @@ -701,16 +727,16 @@ msgstr "Nessuna WAN con multipath abilitata:" msgid "No available backup on server." msgstr "Nessun backup disponibile sul server." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:370 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:382 msgid "No change" msgstr "Nessun cambiamento" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:819 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:821 msgid "No data" msgstr "Nessun dato" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:761 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:560 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:763 msgid "No gateway defined" msgstr "Nessun gateway definito" @@ -731,12 +757,12 @@ msgstr "Nessun indirizzo IP del server, nessun indirizzo IP pubblico" msgid "No server defined" msgstr "Nessun server definito" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:413 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:421 msgid "None" msgstr "Nessuno" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 msgid "Normal" msgstr "Normale" @@ -760,15 +786,15 @@ msgstr "Tipo di offuscamento" msgid "Obfuscating will be enabled on both side" msgstr "L'offuscamento sarà abilitato su entrambi i lati" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:380 msgid "On wizard change" msgstr "Al cambio della procedura guidata" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "Solo ShadowSocks è supportato con server multi IP per adesso." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." @@ -776,13 +802,13 @@ msgstr "" "Solo un' interfaccia può essere impostata come \"Master\", deve essere " "impostata l'interfaccia più stabile." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:143 msgid "Only one server can be master, else all servers are set as backup." msgstr "" "Solo un server può essere master, altrimenti tutti i server sono impostati " "come backup." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "Only work with Shadowsocks as proxy." msgstr "Funziona solo con Shadowsocks come proxy." @@ -790,7 +816,7 @@ msgstr "Funziona solo con Shadowsocks come proxy." msgid "OpenMPTCProuter" msgstr "OpenMPTCProuter" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "OpenVPN non può essere utilizzato nella configurazione multi VPS." @@ -798,59 +824,59 @@ msgstr "OpenVPN non può essere utilizzato nella configurazione multi VPS." msgid "Optimize for latency instead of bandwidth" msgstr "Ottimizza per la latenza invece che per la larghezza di banda" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 msgid "Other" msgstr "Altro" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 msgid "Other settings" msgstr "Altre impostazioni" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:839 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:844 msgid "PAP" msgstr "PAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "PAP/CHAP" msgstr "PAP/CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:852 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:857 msgid "PAP/CHAP password" msgstr "PAP/CHAP password" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 msgid "PAP/CHAP username" msgstr "Nome utente PAP/CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:815 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:820 msgid "PIN code" msgstr "Codice PIN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:611 msgid "PPPoE" msgstr "PPPoE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:573 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:614 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:581 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 msgid "Physical interface" msgstr "Interfaccia fisica" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "Prefer LTE" msgstr "Preferisci LTE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:831 msgid "Prefer UMTS" msgstr "Preferisci UMTS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:102 msgid "Primary server IP" msgstr "IP principale del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 msgid "Protocol" msgstr "Protocollo" @@ -858,19 +884,23 @@ msgstr "Protocollo" msgid "Proxy is DISABLED" msgstr "Il proxy è DISABILITATO" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:220 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 msgid "Proxy settings" msgstr "Impostazioni Proxy" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 msgid "Proxy traffic:" msgstr "Traffico proxy:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:604 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:612 msgid "QMI" msgstr "QMI" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:980 +msgid "QoS permit to prioritize any upload traffic." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:393 msgid "Qualcomm Shortcut FE driver" msgstr "" @@ -878,7 +908,7 @@ msgstr "" msgid "Redirects all ports from server to this router" msgstr "Reindirizza tutte le porte dal server a questo router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1054 msgid "Reset" msgstr "Resetta" @@ -886,32 +916,42 @@ msgstr "Resetta" msgid "Restore backup" msgstr "Ripristina backup" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:179 msgid "Retrieve settings from server" msgstr "Recupera le impostazioni dal server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:435 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:957 +msgid "SQM autorate is for LTE and connection without a stable speed." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:947 +msgid "" +"SQM control bufferloat: the undesirable latency that arises when the router " +"buffers too much data." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:447 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1053 msgid "Save & Apply" msgstr "Salva e applica" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:239 msgid "Save vnstats statistics on disk" msgstr "Salva le statistiche di vnstats su disco" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:234 msgid "Save vnstats stats" msgstr "Salva le statistiche di vnstats" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:427 msgid "Scaling governor" msgstr "Governatore in scala" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:103 msgid "Secondary server IP" msgstr "IP secondario del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1047 msgid "Select the device you want to base the interface on." msgstr "Seleziona il dispositivo su cui vuoi basare l'interfaccia." @@ -919,61 +959,61 @@ msgstr "Seleziona il dispositivo su cui vuoi basare l'interfaccia." msgid "Send backup" msgstr "Invia backup" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 msgid "Server IP" msgstr "Indirizzo IP del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:87 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 msgid "Server IP will be set for proxy and VPN" msgstr "L'IP del server verrà impostato per proxy e VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:126 msgid "Server key" msgstr "Chiave server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:75 msgid "Server settings" msgstr "Impostazioni server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:114 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 msgid "Server username" msgstr "Nome utente del server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Service Type" msgstr "Tipo di servizio" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:409 msgid "Set VPN to use for MPTCP over VPN." msgstr "Seleziona la VPN da utilizzare per MPTCP su VPN." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:696 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 msgid "Set an IP in the same network as the modem" msgstr "Imposta un IP nella stessa rete del modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:408 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 msgid "Set configuration for countries with some specificities." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:702 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 msgid "Set here IP of the modem" msgstr "Imposta qui l'IP del modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 msgid "Set server as master" msgstr "Imposta server come master" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." @@ -981,7 +1021,7 @@ msgstr "" "Imposta il proxy predefinito utilizzato per TCP quando ShadowSocks è " "abilitato, per TCP e UDP quando V2Ray è abilitato." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 #, fuzzy msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " @@ -990,14 +1030,14 @@ msgstr "" "Imposta la VPN predefinita utilizzata per UDP e ICMP quando ShadowSocks è " "abilitato, per tutto il traffico se ShadowSocks è disabilitato." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:943 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" "Impostare il valore tra l'80 e il 95% della velocità massima di download " "del collegamento" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:959 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1014 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" @@ -1012,16 +1052,16 @@ msgstr "Configurazione guidata" msgid "ShadowSocks is not running" msgstr "ShadowSocks non è in esecuzione" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 msgid "ShadowSocks is used for TCP." msgstr "ShadowSocks viene utilizzato per TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 msgid "ShadowSocks key" msgstr "Chiave ShadowSocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 #, fuzzy msgid "Show advanced settings" msgstr "Impostazioni avanzate" @@ -1030,8 +1070,8 @@ msgstr "Impostazioni avanzate" msgid "Show all settings" msgstr "Mostra tutte le impostazioni" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:606 msgid "Static address" msgstr "Indirizzo statico" @@ -1039,7 +1079,7 @@ msgstr "Indirizzo statico" msgid "Status" msgstr "Stato proprietà" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:400 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:412 msgid "Systems settings" msgstr "Impostazioni di sistema" @@ -1053,7 +1093,7 @@ msgstr "" "alcuna applicazione) rimarrà nello stato FIN_WAIT_2 prima che venga " "interrotta all'estremità locale." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:278 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -1079,33 +1119,33 @@ msgstr "" "Questo valore influenza il timeout di una connessione TCP attiva, quando le " "ritrasmissioni RTO rimangono non riconosciute." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:263 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 #, fuzzy msgid "Timeout for VPS checks on status pages" msgstr "Disabilitare il controllo dello stato del ping del gateway" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Timeout for retrieving WANs IP on status pages" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:367 msgid "Total traffic:" msgstr "Traffico globale:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:567 msgid "Type" msgstr "Tipo" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "UBOND può sostituire Glorytun con connessioni con la stessa latenza" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:326 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:328 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:334 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:336 msgid "UBOND password" msgstr "Password UBOND" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:833 msgid "UMTS/GPRS" msgstr "UMTS/GPRS" @@ -1114,61 +1154,60 @@ msgid "Update" msgstr "Aggiorna" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:22 -#, fuzzy msgid "Update remotly servers to latest version and reboot them." -msgstr "" -"Aggiorna in remoto il server alla versione più recente quando necessario." +msgstr "Aggiorna i server remoti all'ultima versione e riavviali." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:20 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:24 msgid "Update server" msgstr "Aggiorna server" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:949 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1004 msgid "Upload speed (Kb/s)" msgstr "Velocità di caricamento (Kb / s)" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "Uptime:" msgstr "Tempo di funzionamento:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:938 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:954 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1009 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." -msgstr "Utilizzato da Glorytun UDP e SQM / QoS se abilitato." +msgstr "" +"Utilizzato da Glorytun UDP e SQM / QoS se abilitato. 0 per usare i valori " +"predefiniti." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:170 msgid "V2Ray is not running" msgstr "V2Ray non è in esecuzione" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 msgid "V2Ray is used for TCP and UDP." msgstr "V2Ray è utilizzato per TCP e UDP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "V2Ray user" msgstr "Utente V2Ray" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 msgid "V2Ray user id" msgstr "ID utente V2Ray" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:643 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:644 -#, fuzzy +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:651 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:652 msgid "VLAN" -msgstr "MacVLAN" +msgstr "VLAN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:184 msgid "VPN is not running" msgstr "VPN non è in esecuzione" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:294 msgid "VPN settings" msgstr "Impostazioni VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 msgid "VPN traffic:" msgstr "Traffico VPN:" @@ -1176,21 +1215,21 @@ msgstr "Traffico VPN:" msgid "VPN tunnel DOWN" msgstr "Tunnel VPN non stabilito" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 msgid "VPS checks timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 msgid "Version" msgstr "Versione" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 msgid "WAN IPs retrieve timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:584 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:775 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:586 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:591 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:777 msgid "Wan IP and gateway are identical" msgstr "IP Wan e gateway sono identici" @@ -1202,15 +1241,21 @@ msgstr "" "Quando si abilita il controllo viene eseguito su siti esterni per ottenere " "ogni IP WAN e l'IP utilizzato per uscire." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 +#, fuzzy +#| msgid "V2Ray is used for TCP and UDP." +msgid "When proxy V2Ray is used, use it for UDP" +msgstr "V2Ray è utilizzato per TCP e UDP." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 msgid "Wizard" msgstr "Procedura guidata" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:422 msgid "World" msgstr "" @@ -1219,42 +1264,42 @@ msgstr "" msgid "You" msgstr "Ti" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:918 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:934 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "Puoi abilitare MPTCP su VPN se il tuo provider filtra Multipath TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:907 +msgid "" +"You can force a TTL. Some LTE provider detect tethering by inpecting packet " +"TTL value, setting it to 65 often solve the issue." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "Puoi usare DHCP se hai più porte ethernet reali." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:617 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." msgstr "Puoi usare DHCP se hai una WAN per ogni interfaccia." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:204 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:212 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" "È possibile utilizzare un prefisso IPv6 pubblico solo se si imposta un solo " "server." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:538 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" "È necessario disabilitare il DHCP sui modem e impostare l'IP in reti " "diverse." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "Dovresti disabilitare IPv6 qui se il server non fornisce IPv6." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:928 -msgid "You should disable SQM for LTE or any interfaces with variable speed." -msgstr "" -"È necessario disabilitare SQM per LTE o qualsiasi interfaccia con velocità " -"variabile." - #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:58 msgid "You shouldn't do that and you should redirect only needed ports" msgstr "" @@ -1267,7 +1312,7 @@ msgstr "Il tuo IP non è stato affittato da questo router" msgid "address:" msgstr "Indirizzo:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 msgid "auto" msgstr "Auto" @@ -1275,45 +1320,45 @@ msgstr "Auto" msgid "empty key" msgstr "chiave vuota" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:506 #, fuzzy msgid "interface:" msgstr "Aggiungi un'interfaccia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:488 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:737 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:490 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:739 msgid "ip address:" msgstr "Indirizzo IP:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:492 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:494 #, fuzzy msgid "ipv6 address:" msgstr "Indirizzo IP:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:751 msgid "latency:" msgstr "latenza:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:755 msgid "mtu:" msgstr "mtu:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:644 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:808 msgid "multipath:" msgstr "multipath:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:526 msgid "operator:" msgstr "operatore:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 msgid "other" msgstr "Altro" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:528 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:530 msgid "phone number:" msgstr "numero di telefono:" @@ -1321,31 +1366,37 @@ msgstr "numero di telefono:" msgid "range:" msgstr "intervallo:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:532 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:534 msgid "state:" msgstr "stato:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:647 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:649 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:811 msgid "traffic control:" msgstr "controllo del traffico:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:498 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:743 msgid "wan address:" msgstr "indirizzo wan:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:502 #, fuzzy msgid "wan ipv6 address:" msgstr "indirizzo wan:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:747 msgid "whois:" msgstr "whois:" +#~ msgid "" +#~ "You should disable SQM for LTE or any interfaces with variable speed." +#~ msgstr "" +#~ "È necessario disabilitare SQM per LTE o qualsiasi interfaccia con " +#~ "velocità variabile." + #~ msgid "Common server settings" #~ msgstr "Impostazioni comuni del server" diff --git a/luci-app-openmptcprouter/po/oc/openmptcprouter.po b/luci-app-openmptcprouter/po/oc/openmptcprouter.po index 1d932aebe..7e0121569 100644 --- a/luci-app-openmptcprouter/po/oc/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/oc/openmptcprouter.po @@ -1,49 +1,49 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-10-19 09:37+0000\n" -"Last-Translator: Quentin PAGÈS \n" +"PO-Revision-Date: 2022-08-12 12:08+0000\n" +"Last-Translator: Weblate Admin \n" "Language-Team: Occitan \n" "Language: oc\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.10.1\n" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "A Dead Simple VPN es un VPN TCP que pòt remplaçat Glorytun TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:302 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:312 msgid "A Dead Simple VPN key" msgstr "Clau Dead Simple VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:119 msgid "API username to retrieve personnalized settings from the server." msgstr "" "Nom d’utilizaire per recuperar la configuracion personalizada del servidor " "estant." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:814 msgid "APN" msgstr "APN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:742 msgid "Accept IPv6 RA" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:156 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:164 #, fuzzy msgid "Add a new server" msgstr "Ajustar un servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:989 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1044 msgid "Add an interface" msgstr "Ajustar una interfàcia" @@ -52,11 +52,11 @@ msgstr "Ajustar una interfàcia" msgid "Advanced Settings" msgstr "Paramètres avançats" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 msgid "Advanced settings" msgstr "Paramètres avançats" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -68,18 +68,18 @@ msgstr "" msgid "All router settings" msgstr "Totes los paramètres del router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:284 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." msgstr "Las instruccions AES son integradas al processor." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "Authentication Type" msgstr "Tipe d’autentificacion" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:878 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:894 msgid "Backup" msgstr "Salvagarda" @@ -88,7 +88,7 @@ msgstr "Salvagarda" msgid "Backup on server" msgstr "Salvagarda sul servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:383 msgid "Balancing" msgstr "Equilibratge" @@ -96,32 +96,38 @@ msgstr "Equilibratge" msgid "Beta" msgstr "Beta" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:312 msgid "Big time difference between the server and the router" msgstr "Granda diferéncia de temps entre lo servidor e lo router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 msgid "Bridge" msgstr "Pont" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:620 msgid "Bridge can't have multipath enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "By default VPN is used for any traffic that is not TCP." msgstr "Per defaut lo VPN es utilizat pel trafic qu’es pas TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 #, fuzzy msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "Per defaut lo VPN es utilizat pel trafic qu’es pas TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:845 msgid "CHAP" msgstr "CHAP" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:961 +msgid "" +"Cake queue discipline is not set, autorate will only work after a reboot if " +"enabled here." +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 msgid "Can\\'t access and use server part" msgstr "Accès e utilizacion impossible la part servidor" @@ -142,19 +148,19 @@ msgstr "" msgid "Can\\'t ping server" msgstr "Cap de responsa del servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:423 msgid "China" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:596 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:655 msgid "Choose physical interface." msgstr "Causissètz l’interfàcia fisica." @@ -162,21 +168,21 @@ msgstr "Causissètz l’interfàcia fisica." msgid "Core temp:" msgstr "Temperatura del còr :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:418 msgid "Country" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 #, fuzzy msgid "Country settings" msgstr "Totes los paramètres del router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 msgid "DHCP" msgstr "DHCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 #, fuzzy msgid "DHCPv6" msgstr "DHCP" @@ -185,37 +191,37 @@ msgstr "DHCP" msgid "DNS issue: can\\'t resolve hostname" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:367 msgid "Debug" msgstr "Desbugatge" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:231 #, fuzzy msgid "Default Proxy" msgstr "VPN per defaut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:345 msgid "Default VPN" msgstr "VPN per defaut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:543 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:551 msgid "Delete" msgstr "Suprimir" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:741 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:774 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 msgid "Device" msgstr "Periferic" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 #, fuzzy -msgid "Disable HTTP test on Server API in status page" +msgid "Disable HTTP test on Server API" msgstr "Desactivar la pròva ping cap al servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:357 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 #, fuzzy msgid "Disable ModemManager" msgstr "ModemManager" @@ -230,12 +236,12 @@ msgstr "" "Desactivacion de TCP Fast Open per Lunix e dins la configuracion de " "Shadowsocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 #, fuzzy msgid "Disable default gateway" msgstr "Desactivar lo ping cap a la palanca" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:312 msgid "Disable default gateway, no internet if VPS are down" msgstr "" @@ -243,31 +249,31 @@ msgstr "" msgid "Disable external check" msgstr "Desactivar las pròvas extèrnas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:244 msgid "Disable gateway ping" msgstr "Desactivar lo ping cap a la palanca" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:249 #, fuzzy msgid "Disable gateway ping check in status page" msgstr "Desactiva la pròva ping de la palanca" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:285 #, fuzzy msgid "Disable interfaces auto rename" msgstr "Desactivar las pròvas extèrnas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:342 msgid "Disable multipath test using tracebox" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 #, fuzzy #| msgid "Disabled" msgid "Disable nDPI" msgstr "Desactivat" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 msgid "Disable nDPI, used for protocols in OMR-ByPass" msgstr "" @@ -278,76 +284,90 @@ msgstr "" "Desactivar las redireccions de pòrts definits dins la part para-fuòc del " "servidor cap a aqueste router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 #, fuzzy msgid "Disable renaming interfaces" msgstr "Etiqueta per l’interfàcia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 #, fuzzy msgid "Disable route loop detection" msgstr "Desactivar lo ping cap al servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 #, fuzzy msgid "Disable server" msgstr "Desactivar lo ping cap al servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:254 #, fuzzy msgid "Disable server http test" msgstr "Desactivar lo ping cap al servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 msgid "Disable server ping" msgstr "Desactivar lo ping cap al servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:322 msgid "Disable server ping status check" msgstr "Desactivar la pròva ping cap al servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:337 #, fuzzy msgid "Disable tracebox test" msgstr "Desactivar las pròvas extèrnas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:876 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:892 msgid "Disabled" msgstr "Desactivat" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:988 msgid "Download speed (Kb/s)" msgstr "Velocitat de telecargament (Kb/s)" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 msgid "Dynamic change" msgstr "Cambiament dinamic" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:402 msgid "Enable Bridge Acceleration" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 #, fuzzy msgid "Enable DNS64" msgstr "Active SQM" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:396 msgid "Enable Fast Patch offloading for connections" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 msgid "Enable IPv6" msgstr "Activar l’IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:923 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:975 +msgid "Enable QoS" +msgstr "Active QoS" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:223 +msgid "Enable SIP ALG" +msgstr "Activar SIP ALG" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:942 msgid "Enable SQM" msgstr "Active SQM" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 +#, fuzzy +#| msgid "Enable SQM" +msgid "Enable SQM autorate" +msgstr "Active SQM" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:79 msgid "Enable ShadowSocks Obfuscating" msgstr "Activar las interferéncias per ShadowSocks" @@ -357,21 +377,21 @@ msgstr "Activar las interferéncias per ShadowSocks" msgid "Enable TCP Low Latency" msgstr "Desactivar TCP Fast Open" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:372 msgid "Enable debug logs" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:886 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:875 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:891 msgid "Enabled" msgstr "Activat" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 msgid "Encryption" msgstr "Chiframent" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:288 #, fuzzy msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "Metòde de chiframent utilizat per Glorytun." @@ -380,42 +400,46 @@ msgstr "Metòde de chiframent utilizat per Glorytun." msgid "Filesystem is readonly" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:902 +msgid "Force TTL" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 #, fuzzy msgid "Force retrieve all keys from server." msgstr "" "Nom d’utilizaire per recuperar la configuracion personalizada del servidor " "estant." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 #, fuzzy msgid "Force retrieve settings" msgstr "Paramètres servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:834 msgid "GPRS only" msgstr "solament GPRS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:766 msgid "Gateway DOWN" msgstr "La palanca respond pas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 #, fuzzy msgid "Gateway IPv6 DOWN" msgstr "La palanca respond pas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "Glorytun TCP es utilizat per defaut per UDP e ICMP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:290 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:300 msgid "Glorytun key" msgstr "Clau Glorytun" @@ -457,42 +481,42 @@ msgstr "Ensages IPv4 TCP SYN" msgid "IPv4 TCP SYN retries2" msgstr "Ensages IPv4 TCP SYN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:653 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:661 msgid "IPv4 address" msgstr "Adreça IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:677 msgid "IPv4 gateway" msgstr "Palanca IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:663 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 msgid "IPv4 netmask" msgstr "Masqueta ret IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 msgid "IPv6 Prefix" msgstr "Prefix IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 #, fuzzy msgid "IPv6 address" msgstr "Adreça IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:705 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 #, fuzzy msgid "IPv6 gateway" msgstr "Palanca IPv4" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 msgid "IPv6 route received" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 #, fuzzy msgid "IPv6 settings" msgstr "Paramètres del VPN" @@ -501,28 +525,28 @@ msgstr "Paramètres del VPN" msgid "IPv6 tunnel DOWN" msgstr "Lo tunèl IPv6 respond pas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 msgid "IPv6:" msgstr "IPv6 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:222 msgid "If host support NAT64, you can enable DNS64 support." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 msgid "Interfaces settings" msgstr "Paramètres interfàcias" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "Key is retrieved from server API by default." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:129 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." @@ -530,22 +554,22 @@ msgstr "" "Clau per configurar e recuperar las autras claus e tanban los paramètres del " "servidor estant." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:435 #, fuzzy msgid "LAN interfaces settings" msgstr "Paramètres interfàcias" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:832 msgid "LTE" msgstr "LTE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:438 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:549 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:446 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:557 msgid "Label" msgstr "Etiqueta" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:452 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 msgid "Label for the interface" msgstr "Etiqueta per l’interfàcia" @@ -554,26 +578,26 @@ msgid "Last available backup on server:" msgstr "Darrièra salvagarda disponibla sul servidor :" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:329 msgid "Latest available version" msgstr "Darrièra salvagarda disponibla sul servidor" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:335 msgid "Load:" msgstr "Carga :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:628 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 msgid "Looping route detected" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "" "MLVPN pòt remplaçar Glorytun per las connexions amb la meteissa laténcia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:314 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:316 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:324 msgid "MLVPN password" msgstr "Senhal MLVPN" @@ -581,56 +605,56 @@ msgstr "Senhal MLVPN" msgid "MPTCP is not enabled on the server" msgstr "MPTCP es pas activat sul servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:344 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 msgid "MPTCP may not be enabled on the server" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:393 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:913 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:929 msgid "MPTCP over VPN" msgstr "MPTCP over VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:398 #, fuzzy msgid "MPTCP over VPN settings" msgstr "MPTCP over VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 msgid "MacVLAN" msgstr "MacVLAN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:893 msgid "Master" msgstr "Principal" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:377 msgid "Master interface selection" msgstr "Seleccion de l’interfàcia màger" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:409 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:421 msgid "Maximum scaling CPU frequency" msgstr "Frequéncia maximala del processor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:403 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 msgid "Minimum scaling CPU frequency" msgstr "Frequéncia minimala del processor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:824 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "Modem default" msgstr "Modem per defaut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:858 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:863 msgid "Modem init timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:601 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 msgid "ModemManager" msgstr "ModemManager" @@ -638,53 +662,53 @@ msgstr "ModemManager" msgid "More than one default VPN is enabled" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:787 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:793 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:795 msgid "Multipath current state is" msgstr "Multipath es actualament" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:784 msgid "Multipath master already defined" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:569 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 msgid "Multipath seems to be blocked on the connection" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:610 msgid "NCM" msgstr "NCM" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:838 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:843 msgid "NONE" msgstr "CAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:625 #, fuzzy msgid "Network interface MAC address duplicated" msgstr "Interfàcia ret doblada" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:615 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:801 msgid "Network interface duplicated" msgstr "Interfàcia ret doblada" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:581 #, fuzzy msgid "Network interface not in WAN firewall zone" msgstr "Interfàcia ret doblada" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:903 msgid "Network overview" msgstr "Vista ret" @@ -692,8 +716,8 @@ msgstr "Vista ret" msgid "Networks settings" msgstr "Paramètres ret" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:757 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:556 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:759 msgid "No IP defined" msgstr "Cap d’IP pas definida" @@ -701,16 +725,16 @@ msgstr "Cap d’IP pas definida" msgid "No IPv6 access" msgstr "Cap d’accès IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:577 msgid "No Server http response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:573 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:773 msgid "No Server ping response after 1 second" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 msgid "No WAN with multipath enabled:" msgstr "" @@ -718,16 +742,16 @@ msgstr "" msgid "No available backup on server." msgstr "Cap de salvagarda pas disponibla sul servidor." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:370 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:382 msgid "No change" msgstr "Cap de modificacion" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:819 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:821 msgid "No data" msgstr "Cap de donadas" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:761 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:560 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:763 msgid "No gateway defined" msgstr "Cap de palanca pas definida" @@ -749,12 +773,12 @@ msgstr "" msgid "No server defined" msgstr "Paramètres dels servidors" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:413 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:421 msgid "None" msgstr "Cap" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 msgid "Normal" msgstr "Normala" @@ -776,27 +800,27 @@ msgstr "Tipe d’interferéncia" msgid "Obfuscating will be enabled on both side" msgstr "Las interferéncias seràn activadas dels dos costats" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:380 msgid "On wizard change" msgstr "En modificant dins l’assistent" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:143 msgid "Only one server can be master, else all servers are set as backup." msgstr "" "Pas qu’un servidor pòt pas qu’èsser lo servidor màger, los autres son pel " "replegament." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "Only work with Shadowsocks as proxy." msgstr "" @@ -804,7 +828,7 @@ msgstr "" msgid "OpenMPTCProuter" msgstr "OpenMPTCProuter" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "" @@ -812,63 +836,63 @@ msgstr "" msgid "Optimize for latency instead of bandwidth" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 msgid "Other" msgstr "Autre" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 #, fuzzy msgid "Other settings" msgstr "Paramètres servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:839 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:844 msgid "PAP" msgstr "PAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "PAP/CHAP" msgstr "PAP / CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:852 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:857 #, fuzzy msgid "PAP/CHAP password" msgstr "Senhal MLVPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 msgid "PAP/CHAP username" msgstr "Identificant PAP / CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:815 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:820 msgid "PIN code" msgstr "Còdi PIN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:611 msgid "PPPoE" msgstr "PPPoE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:573 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:614 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:581 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 #, fuzzy msgid "Physical interface" msgstr "Ajustar una interfàcia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "Prefer LTE" msgstr "Preferir LTE" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:831 msgid "Prefer UMTS" msgstr "Preferir UMTS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:102 #, fuzzy msgid "Primary server IP" msgstr "IP servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 msgid "Protocol" msgstr "Protocòl" @@ -876,20 +900,24 @@ msgstr "Protocòl" msgid "Proxy is DISABLED" msgstr "Lo servidor mandatari es DESACTIVAT" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:220 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 #, fuzzy msgid "Proxy settings" msgstr "Paramètres del VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 msgid "Proxy traffic:" msgstr "Trafic mandatari :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:604 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:612 msgid "QMI" msgstr "QMI" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:980 +msgid "QoS permit to prioritize any upload traffic." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:393 msgid "Qualcomm Shortcut FE driver" msgstr "" @@ -897,7 +925,7 @@ msgstr "" msgid "Redirects all ports from server to this router" msgstr "Redigir totes los pòrts del servidor cap a aqueste router" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1054 msgid "Reset" msgstr "" @@ -905,33 +933,43 @@ msgstr "" msgid "Restore backup" msgstr "Restaurar salvagarda" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:179 msgid "Retrieve settings from server" msgstr "Recuperar la configuracion personalizada del servidor estant" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:435 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:957 +msgid "SQM autorate is for LTE and connection without a stable speed." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:947 +msgid "" +"SQM control bufferloat: the undesirable latency that arises when the router " +"buffers too much data." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:447 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1053 msgid "Save & Apply" msgstr "Salvagardar e aplicar" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:239 msgid "Save vnstats statistics on disk" msgstr "Salvagardar las estatisticas de vnstats sul disc" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:234 msgid "Save vnstats stats" msgstr "Salvagardar las estatisticas de vnstats" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:427 msgid "Scaling governor" msgstr "Regulator a l’escala" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:103 #, fuzzy msgid "Secondary server IP" msgstr "IP servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1047 msgid "Select the device you want to base the interface on." msgstr "Seleccionatz lo periferic per l’interfàcia." @@ -939,63 +977,63 @@ msgstr "Seleccionatz lo periferic per l’interfàcia." msgid "Send backup" msgstr "Enviar la salvagarda" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 msgid "Server IP" msgstr "IP servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:87 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 #, fuzzy msgid "Server IP will be set for proxy and VPN" msgstr "" "L’IP del servidor serà configurada per ShadowSocks, Glorytun, OpenVPN e MLVPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:126 msgid "Server key" msgstr "Clau servidor" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:75 msgid "Server settings" msgstr "Paramètres servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:114 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 msgid "Server username" msgstr "Lo nom d'utilizaire servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Service Type" msgstr "Tipe de servici" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:409 msgid "Set VPN to use for MPTCP over VPN." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:696 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 msgid "Set an IP in the same network as the modem" msgstr "Botatz una IP dins lo meteis ret que lo modem" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:408 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 msgid "Set configuration for countries with some specificities." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:702 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 msgid "Set here IP of the modem" msgstr "Botatz l’IP del modem aquí" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 msgid "Set server as master" msgstr "Configurar lo servidor coma servidor màger" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 #, fuzzy msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " @@ -1004,7 +1042,7 @@ msgstr "" "Configura lo VPN utilizat per defaut per l’UDP e l’ICMP quand ShadowSocks es " "activat, per tot lo trafic quand ShadowSocks es desactivat." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 #, fuzzy msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " @@ -1013,14 +1051,14 @@ msgstr "" "Configura lo VPN utilizat per defaut per l’UDP e l’ICMP quand ShadowSocks es " "activat, per tot lo trafic quand ShadowSocks es desactivat." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:943 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" "Reglatz una valor entre 80-95% de la velocitat de telecargament maximala. 0 " "per desactivar SQM/QoS." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:959 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1014 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" @@ -1036,16 +1074,16 @@ msgstr "Assistent de configuracion" msgid "ShadowSocks is not running" msgstr "Paramètres ShadowSocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 msgid "ShadowSocks is used for TCP." msgstr "ShadowSocks es utilizat per TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 msgid "ShadowSocks key" msgstr "Clau de ShadowSocks" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 #, fuzzy msgid "Show advanced settings" msgstr "Paramètres avançats" @@ -1054,8 +1092,8 @@ msgstr "Paramètres avançats" msgid "Show all settings" msgstr "Veire totes los paramètres" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:606 msgid "Static address" msgstr "Adreça estatica" @@ -1063,7 +1101,7 @@ msgstr "Adreça estatica" msgid "Status" msgstr "Estatut" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:400 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:412 msgid "Systems settings" msgstr "Paramètres sistèma" @@ -1074,7 +1112,7 @@ msgid "" "local end." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:278 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -1095,34 +1133,34 @@ msgid "" "retransmissions remain unacknowledged." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:263 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 #, fuzzy msgid "Timeout for VPS checks on status pages" msgstr "Desactiva la pròva ping de la palanca" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Timeout for retrieving WANs IP on status pages" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:367 msgid "Total traffic:" msgstr "Tradif total :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:567 msgid "Type" msgstr "Tipe" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "" "UBOND pòt remplaçar Glorytun per de connexions amb la meteissa laténcia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:326 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:328 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:334 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:336 msgid "UBOND password" msgstr "Senhal UBOND" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:833 msgid "UMTS/GPRS" msgstr "UMTS / GPRS" @@ -1140,17 +1178,17 @@ msgstr "Met a jorn lo servidor amb la darrièra version quand cal." msgid "Update server" msgstr "Mesa a jorn del servidor" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:949 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1004 msgid "Upload speed (Kb/s)" msgstr "Velocitat de mandadís (Kb/s)" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "Uptime:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:938 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:954 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1009 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "" "Utilizat per Glorytun UDP e SQM/QoS se activat. 0 per utilizar la valor per " @@ -1160,21 +1198,21 @@ msgstr "" msgid "V2Ray is not running" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 #, fuzzy msgid "V2Ray is used for TCP and UDP." msgstr "ShadowSocks es utilizat per TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "V2Ray user" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 msgid "V2Ray user id" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:643 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:644 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:651 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:652 #, fuzzy msgid "VLAN" msgstr "MacVLAN" @@ -1184,11 +1222,11 @@ msgstr "MacVLAN" msgid "VPN is not running" msgstr "Paramètres del VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:294 msgid "VPN settings" msgstr "Paramètres del VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 msgid "VPN traffic:" msgstr "" @@ -1196,21 +1234,21 @@ msgstr "" msgid "VPN tunnel DOWN" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 msgid "VPS checks timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 msgid "Version" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 msgid "WAN IPs retrieve timeout" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:584 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:775 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:586 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:591 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:777 msgid "Wan IP and gateway are identical" msgstr "" @@ -1221,15 +1259,20 @@ msgid "" msgstr "" "Utiliza de sites extèrns per obténer d’adreças IP extèrnas quand activat." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 +#, fuzzy +msgid "When proxy V2Ray is used, use it for UDP" +msgstr "ShadowSocks es utilizat per TCP." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 msgid "Wizard" msgstr "Assistent" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:422 msgid "World" msgstr "" @@ -1238,16 +1281,22 @@ msgstr "" msgid "You" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:918 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:934 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "" "Podètz utilizar MTPCP over VPN se vòstre provesidor filtra Multipath TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:907 +msgid "" +"You can force a TTL. Some LTE provider detect tethering by inpecting packet " +"TTL value, setting it to 65 often solve the issue." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:617 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." @@ -1255,26 +1304,20 @@ msgstr "" "Podètz utilizar DHCP s’avètz mantuns pòrts ret fisics. Causissètz autre " "s’utilizatz un autre protocòl dins la pagina Interfàcias Ret." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:204 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:212 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:538 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" "Vos cal desactivar lo DHCP sus vòstres modems e configurar lor IP dins de " "rets diferents." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "Deuriatz desactivar IPv6 aquí se lo servidor es pas compatible IPv6." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:928 -msgid "You should disable SQM for LTE or any interfaces with variable speed." -msgstr "" -"Vos cal desactivar SQM per la 4G o tota interfàcia amb una velocitat fòrça " -"instabla." - #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:58 msgid "You shouldn't do that and you should redirect only needed ports" msgstr "" @@ -1287,7 +1330,7 @@ msgstr "" msgid "address:" msgstr "Adreça IPv4 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 msgid "auto" msgstr "auto" @@ -1295,45 +1338,45 @@ msgstr "auto" msgid "empty key" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:506 #, fuzzy msgid "interface:" msgstr "Ajustar una interfàcia" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:488 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:737 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:490 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:739 msgid "ip address:" msgstr "Adreça IP :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:492 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:494 #, fuzzy msgid "ipv6 address:" msgstr "Adreça IP :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:751 msgid "latency:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:755 msgid "mtu:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:644 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:808 msgid "multipath:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:526 msgid "operator:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 msgid "other" msgstr "autre" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:528 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:530 msgid "phone number:" msgstr "" @@ -1341,31 +1384,37 @@ msgstr "" msgid "range:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:532 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:534 msgid "state:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:647 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:649 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:811 msgid "traffic control:" msgstr "" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:498 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:743 msgid "wan address:" msgstr "Adreça wan :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:502 #, fuzzy msgid "wan ipv6 address:" msgstr "Adreça wan :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:747 msgid "whois:" msgstr "" +#~ msgid "" +#~ "You should disable SQM for LTE or any interfaces with variable speed." +#~ msgstr "" +#~ "Vos cal desactivar SQM per la 4G o tota interfàcia amb una velocitat " +#~ "fòrça instabla." + #~ msgid "Common server settings" #~ msgstr "Paramètres dels servidors" diff --git a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po index 7bcec9785..743382b02 100644 --- a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-01-11 10:52+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2022-08-12 12:08+0000\n" +"Last-Translator: Weblate Admin \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" @@ -11,39 +11,39 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.6.1\n" +"X-Generator: Weblate 4.10.1\n" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "A Dead Simple VPN 是可以替代Glorytun TCP的TCP VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:302 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:312 msgid "A Dead Simple VPN key" msgstr "简单VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "如果设置了WAN IPv6,则可以为设置第二台服务器的IP双IPv4 / IPv6服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:119 msgid "API username to retrieve personnalized settings from the server." msgstr "API用户名,从聚合服务器检索个性化设置." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:814 msgid "APN" msgstr "APN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:742 msgid "Accept IPv6 RA" msgstr "接受IPv6 RA" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:156 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:164 msgid "Add a new server" msgstr "添加一个新聚合服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:989 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1044 msgid "Add an interface" msgstr "添加网卡" @@ -52,11 +52,11 @@ msgstr "添加网卡" msgid "Advanced Settings" msgstr "高级设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 msgid "Advanced settings" msgstr "高级设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -66,18 +66,18 @@ msgstr "这里可用的所有VPN都可以通过MPTCP或使用自己的内部进 msgid "All router settings" msgstr "所有路由器设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:284 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." msgstr "处理器中集成了高级加密标准(AES)指令集." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "Authentication Type" msgstr "认证类型" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:878 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:894 msgid "Backup" msgstr "备份" @@ -86,7 +86,7 @@ msgstr "备份" msgid "Backup on server" msgstr "备份到服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:383 msgid "Balancing" msgstr "均衡" @@ -94,31 +94,37 @@ msgstr "均衡" msgid "Beta" msgstr "测试版" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:312 msgid "Big time difference between the server and the router" msgstr "服务器和路由器之间的时间差距很大" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 msgid "Bridge" msgstr "桥接" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:620 msgid "Bridge can't have multipath enabled" msgstr "网桥无法启用多路径聚合" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "By default VPN is used for any traffic that is not TCP." msgstr "默认情况下,VPN用于非TCP的任何流量." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "默认情况下,仅代理TCP(如果选用V2Ray则代理TCP跟UDP还有ICMP任何)流量。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:845 msgid "CHAP" msgstr "CHAP" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:961 +msgid "" +"Cake queue discipline is not set, autorate will only work after a reboot if " +"enabled here." +msgstr "" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:271 msgid "Can\\'t access and use server part" msgstr "无法访问和使用聚合服务器部分服务" @@ -139,19 +145,19 @@ msgstr "无法通过聚合服务器ShadowSocks获取公网IP地址" msgid "Can\\'t ping server" msgstr "无法ping聚合服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:423 msgid "China" msgstr "中国专属" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." msgstr "如果要基于物理接口创建虚拟接口,请选择MacVLAN。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:596 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:655 msgid "Choose physical interface." msgstr "选择物理接口。" @@ -159,20 +165,20 @@ msgstr "选择物理接口。" msgid "Core temp:" msgstr "核心温度:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:418 msgid "Country" msgstr "国家" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 msgid "Country settings" msgstr "国家设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 msgid "DHCP" msgstr "DHCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 msgid "DHCPv6" msgstr "DHCPV6" @@ -180,35 +186,37 @@ msgstr "DHCPV6" msgid "DNS issue: can\\'t resolve hostname" msgstr "DNS问题:无法解析主机名" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:367 msgid "Debug" msgstr "调试模式" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:231 msgid "Default Proxy" msgstr "默认代理" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:345 msgid "Default VPN" msgstr "默认VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:543 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:551 msgid "Delete" msgstr "删除" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:741 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:774 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 msgid "Device" msgstr "设备" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 -msgid "Disable HTTP test on Server API in status page" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 +#, fuzzy +#| msgid "Disable HTTP test on Server API in status page" +msgid "Disable HTTP test on Server API" msgstr "在状态页面中禁用服务器API上的HTTP测试" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:357 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 msgid "Disable ModemManager" msgstr "禁用调制解调器管理器" @@ -220,11 +228,11 @@ msgstr "禁用TCP Fast Open" msgid "Disable TCP Fast Open on Linux and Shadowsocks configuration" msgstr "在Linux和Shadowsocks配置上禁用TCP快速打开" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 msgid "Disable default gateway" msgstr "关闭默认网关" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:312 msgid "Disable default gateway, no internet if VPS are down" msgstr "禁用默认网关,如果VPS关闭,则没办法链接互联网" @@ -232,27 +240,27 @@ msgstr "禁用默认网关,如果VPS关闭,则没办法链接互联网" msgid "Disable external check" msgstr "禁用外部检查" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:244 msgid "Disable gateway ping" msgstr "禁用网关ping" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:249 msgid "Disable gateway ping check in status page" msgstr "禁用状态页面网关ping检查" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:285 msgid "Disable interfaces auto rename" msgstr "禁用接口自动重命名" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:342 msgid "Disable multipath test using tracebox" msgstr "禁止使用tracebox多路径测试" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 msgid "Disable nDPI" msgstr "禁用 nDPI" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 msgid "Disable nDPI, used for protocols in OMR-ByPass" msgstr "禁用 nDPI,用于 OMR-ByPass 中的协议" @@ -261,70 +269,84 @@ msgid "" "Disable ports redirection defined in firewall from server to this router" msgstr "禁用防火墙中定义的从服务器到此路由器的端口重定向" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 msgid "Disable renaming interfaces" msgstr "禁用网卡重命名" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 msgid "Disable route loop detection" msgstr "禁用路由环路检测" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 msgid "Disable server" msgstr "关闭禁用聚合服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:254 msgid "Disable server http test" msgstr "禁用服务器http 测试" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 msgid "Disable server ping" msgstr "禁用服务器ping" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:322 msgid "Disable server ping status check" msgstr "禁用服务器ping状态检查" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:337 msgid "Disable tracebox test" msgstr "禁用聚合检测" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:876 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:892 msgid "Disabled" msgstr "关闭" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:988 msgid "Download speed (Kb/s)" msgstr "下载速度 (Kb/s)" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:369 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 msgid "Dynamic change" msgstr "动态变化" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:402 msgid "Enable Bridge Acceleration" msgstr "启用网桥加速" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 msgid "Enable DNS64" msgstr "启用DNS64" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:396 msgid "Enable Fast Patch offloading for connections" msgstr "为连接启用快速流量卸载补丁" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 msgid "Enable IPv6" msgstr "开启 IPv6" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:923 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:975 +msgid "Enable QoS" +msgstr "开启 QoS" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:223 +msgid "Enable SIP ALG" +msgstr "开启 SIP ALG" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:942 msgid "Enable SQM" msgstr "开启 SQM" +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 +#, fuzzy +#| msgid "Enable SQM" +msgid "Enable SQM autorate" +msgstr "开启 SQM" + #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:79 msgid "Enable ShadowSocks Obfuscating" msgstr "启用ShadowSocks混淆" @@ -333,21 +355,21 @@ msgstr "启用ShadowSocks混淆" msgid "Enable TCP Low Latency" msgstr "启用TCP低延迟" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:372 msgid "Enable debug logs" msgstr "启用调试日志" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:886 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:875 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:891 msgid "Enabled" msgstr "启用" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 msgid "Encryption" msgstr "加密" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:288 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "加密方法用于Shadowsocks,V2Ray,Glorytun和OpenVPN。" @@ -355,37 +377,41 @@ msgstr "加密方法用于Shadowsocks,V2Ray,Glorytun和OpenVPN。" msgid "Filesystem is readonly" msgstr "文件系统处于只读状态/重新刷机吧" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "对于中国,设置专属的DNS并禁用DNSSEC." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:902 +msgid "Force TTL" +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 msgid "Force retrieve all keys from server." msgstr "强制从服务器检索并应用所有密钥。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 msgid "Force retrieve settings" msgstr "强制检索设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:834 msgid "GPRS only" msgstr "仅GPRS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:766 msgid "Gateway DOWN" msgstr "网关不通" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 msgid "Gateway IPv6 DOWN" msgstr "IPV6网关不通" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "Glorytun TCP默认用于UDP和ICMP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:290 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:292 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:300 msgid "Glorytun key" msgstr "Glorytun密钥" @@ -425,40 +451,40 @@ msgstr "IPv4 TCP SYN重试1" msgid "IPv4 TCP SYN retries2" msgstr "IPv4 TCP SYN重试2" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:653 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:661 msgid "IPv4 address" msgstr "IPv4地址" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:677 msgid "IPv4 gateway" msgstr "IPv4网关" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:663 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 msgid "IPv4 netmask" msgstr "IPv4网络掩码" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 msgid "IPv6 Prefix" msgstr "IPv6前缀" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 msgid "IPv6 address" msgstr "IPv6地址" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:705 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 msgid "IPv6 gateway" msgstr "IPv6网关" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 msgid "IPv6 route received" msgstr "经过的IPv6路由" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 msgid "IPv6 settings" msgstr "IPv6设置" @@ -466,48 +492,48 @@ msgstr "IPv6设置" msgid "IPv6 tunnel DOWN" msgstr "IPv6隧道DOWN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:350 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 msgid "IPv6:" msgstr "IPv6 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:222 msgid "If host support NAT64, you can enable DNS64 support." msgstr "如果主机支持NAT64,则可以启用DNS64支持。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 msgid "Interfaces settings" msgstr "接口设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "Key is retrieved from server API by default." msgstr "默认情况下,密钥是从服务器API检索的." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:129 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." msgstr "用于服务器配置密钥以及设置的密钥." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:435 msgid "LAN interfaces settings" msgstr "局域网接口设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:832 msgid "LTE" msgstr "4G LTE制式" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:438 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:549 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:446 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:557 msgid "Label" msgstr "标签" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:452 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 msgid "Label for the interface" msgstr "接口标签" @@ -516,25 +542,25 @@ msgid "Last available backup on server:" msgstr "服务器上的上次可用备份:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:329 msgid "Latest available version" msgstr "最新可用的版本" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:335 msgid "Load:" msgstr "负载:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:628 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 msgid "Looping route detected" msgstr "检测到循环路线" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "MLVPN可以用具有相同延迟的连接替换Glorytun" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:314 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:316 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:324 msgid "MLVPN password" msgstr "MLVPN密码" @@ -542,55 +568,55 @@ msgstr "MLVPN密码" msgid "MPTCP is not enabled on the server" msgstr "服务器上未启用MPTCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:344 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 msgid "MPTCP may not be enabled on the server" msgstr "服务器上可能未启用MPTCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:393 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:913 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:929 msgid "MPTCP over VPN" msgstr "通过MPTCP的VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:398 msgid "MPTCP over VPN settings" msgstr "通过MPTCP的VPN设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." msgstr "仅当在链路上阻止多路径TCP时,才应该使用基于VPN的MPTCP。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 msgid "MacVLAN" msgstr "Macvlan" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:893 msgid "Master" msgstr "主" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:377 msgid "Master interface selection" msgstr "主网卡选择" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:409 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:421 msgid "Maximum scaling CPU frequency" msgstr "最大扩展CPU频率" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:403 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 msgid "Minimum scaling CPU frequency" msgstr "最小扩展CPU频率" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:824 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "Modem default" msgstr "调制解调器默认" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:858 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:863 msgid "Modem init timeout" msgstr "调制解调器初始化超时" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:601 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 msgid "ModemManager" msgstr "调制解调器管理器" @@ -598,51 +624,51 @@ msgstr "调制解调器管理器" msgid "More than one default VPN is enabled" msgstr "启用了多个默认VPN" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 msgid "Multipath TCP" msgstr "多路径TCP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:787 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:793 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:789 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:795 msgid "Multipath current state is" msgstr "多路径当前状态为" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:784 msgid "Multipath master already defined" msgstr "已定义多路径主机" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:569 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 msgid "Multipath seems to be blocked on the connection" msgstr "多路径似乎在连接上被阻止" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:610 msgid "NCM" msgstr "NCM" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:838 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:843 msgid "NONE" msgstr "无" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:625 msgid "Network interface MAC address duplicated" msgstr "网络接口MAC地址重复" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:615 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:801 msgid "Network interface duplicated" msgstr "网络接口重复" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:581 msgid "Network interface not in WAN firewall zone" msgstr "网络接口不在WAN防火墙区域中" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:903 msgid "Network overview" msgstr "网络概览" @@ -650,8 +676,8 @@ msgstr "网络概览" msgid "Networks settings" msgstr "网络设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:757 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:556 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:759 msgid "No IP defined" msgstr "没有定义IP" @@ -659,16 +685,16 @@ msgstr "没有定义IP" msgid "No IPv6 access" msgstr "没有IPv6地址" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:577 msgid "No Server http response after 1 second" msgstr "1秒后无服务器HTTP响应" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:573 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:773 msgid "No Server ping response after 1 second" msgstr "1秒后无服务器ping响应" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 msgid "No WAN with multipath enabled:" msgstr "没有启用多路径的WAN:" @@ -676,16 +702,16 @@ msgstr "没有启用多路径的WAN:" msgid "No available backup on server." msgstr "服务器上没有可用的备份." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:370 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:382 msgid "No change" msgstr "没有改变" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:819 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:821 msgid "No data" msgstr "没有数据" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:761 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:560 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:763 msgid "No gateway defined" msgstr "未定义网关" @@ -706,12 +732,12 @@ msgstr "没有服务器IP地址,没有公共IP地址" msgid "No server defined" msgstr "未定义聚合服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:413 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:421 msgid "None" msgstr "没有" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 msgid "Normal" msgstr "正常" @@ -733,25 +759,25 @@ msgstr "混淆类型" msgid "Obfuscating will be enabled on both side" msgstr "双方都将启用混淆" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:380 msgid "On wizard change" msgstr "通过向导更改" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "目前服务器如果有多个公网IP仅支持ShadowSocks." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." msgstr "必须仅将一个接口设置为“主”,这应该是最稳定的接口。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:143 msgid "Only one server can be master, else all servers are set as backup." msgstr "只能将一台服务器作为主服务器,否则将所有服务器都设置为备用服务器." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 msgid "Only work with Shadowsocks as proxy." msgstr "只有Shadowsocks作为代理工作。" @@ -759,7 +785,7 @@ msgstr "只有Shadowsocks作为代理工作。" msgid "OpenMPTCProuter" msgstr "聚合路由器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "OpenVPN不能用于多VPS配置." @@ -767,59 +793,59 @@ msgstr "OpenVPN不能用于多VPS配置." msgid "Optimize for latency instead of bandwidth" msgstr "优化延迟而不是带宽" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 msgid "Other" msgstr "其他" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 msgid "Other settings" msgstr "聚合其他设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:839 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:844 msgid "PAP" msgstr "PAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "PAP/CHAP" msgstr "PAP/CHAP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:852 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:857 msgid "PAP/CHAP password" msgstr "PAP/CHAP 密码" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 msgid "PAP/CHAP username" msgstr "PAP/CHAP 账号" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:815 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:820 msgid "PIN code" msgstr "PIN码" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:611 msgid "PPPoE" msgstr "PPPoE拨号" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:573 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:614 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:581 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 msgid "Physical interface" msgstr "物理接口" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "Prefer LTE" msgstr "首选4G LTE制式" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:831 msgid "Prefer UMTS" msgstr "首选3G UMTS" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:102 msgid "Primary server IP" msgstr "主服务器IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 msgid "Protocol" msgstr "协议" @@ -827,19 +853,23 @@ msgstr "协议" msgid "Proxy is DISABLED" msgstr "代理已禁用" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:220 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 msgid "Proxy settings" msgstr "代理设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:355 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 msgid "Proxy traffic:" msgstr "代理流量:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:604 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:612 msgid "QMI" msgstr "QMI" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:980 +msgid "QoS permit to prioritize any upload traffic." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:393 msgid "Qualcomm Shortcut FE driver" msgstr "Qualcomm Shortcut FE驱动程序" @@ -847,7 +877,7 @@ msgstr "Qualcomm Shortcut FE驱动程序" msgid "Redirects all ports from server to this router" msgstr "将所有端口从服务器重定向到此路由器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1054 msgid "Reset" msgstr "复位" @@ -855,32 +885,42 @@ msgstr "复位" msgid "Restore backup" msgstr "恢复备份" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:179 msgid "Retrieve settings from server" msgstr "从服务器检索设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:435 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:957 +msgid "SQM autorate is for LTE and connection without a stable speed." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:947 +msgid "" +"SQM control bufferloat: the undesirable latency that arises when the router " +"buffers too much data." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:447 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1053 msgid "Save & Apply" msgstr "保存并且应用设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:239 msgid "Save vnstats statistics on disk" msgstr "将vnstats统计信息保存在磁盘上" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:234 msgid "Save vnstats stats" msgstr "保存vnstats统计信息" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:427 msgid "Scaling governor" msgstr "超频" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:103 msgid "Secondary server IP" msgstr "辅助服务器IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1047 msgid "Select the device you want to base the interface on." msgstr "选择要作为基础的接口." @@ -888,67 +928,69 @@ msgstr "选择要作为基础的接口." msgid "Send backup" msgstr "发送备份" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 msgid "Server IP" msgstr "服务器IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:87 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 msgid "Server IP will be set for proxy and VPN" msgstr "将为代理和VPN设置服务器IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:126 msgid "Server key" msgstr "服务器密钥" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:75 msgid "Server settings" msgstr "聚合服务器设定" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:114 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 msgid "Server username" msgstr "服务器用户名" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Service Type" msgstr "服务类型" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:409 msgid "Set VPN to use for MPTCP over VPN." msgstr "设置VPN以用于通过VPN的MPTCP。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:696 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 msgid "Set an IP in the same network as the modem" msgstr "在与调制解调器相同的网络中设置IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:408 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 msgid "Set configuration for countries with some specificities." msgstr "设置具有某些特殊性的国家/地区的配置。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:702 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 msgid "Set here IP of the modem" msgstr "在此处设置调制解调器的IP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:130 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 msgid "Set server as master" msgstr "将服务器设置为主服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." -msgstr "启用ShadowSocks时用于默认代理TC流量,启用V2Ray时用于默认代理TCP和UDP还有ICMP任何流量." +msgstr "" +"启用ShadowSocks时用于默认代理TC流量,启用V2Ray时用于默认代理TCP和UDP还有ICMP" +"任何流量." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " "for all traffic if proxy is disabled." @@ -956,12 +998,12 @@ msgstr "" "启用ShadowSocks时,为所有流量设置默认的VPN,用于UDP和ICMP,如果禁用" "ShadowSocks." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:943 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "设置最大下载速度链接的80-95%之间的值。 0禁用SQM / QoS." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:959 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1014 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "设置为最大上传速度链接的80-95%之间的值。 0禁用SQM / QoS." @@ -974,16 +1016,16 @@ msgstr "聚合设置向导" msgid "ShadowSocks is not running" msgstr "ShadowSocks n'est pas lancé" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 msgid "ShadowSocks is used for TCP." msgstr "ShadowSocks用于TCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 msgid "ShadowSocks key" msgstr "ShadowSocks密钥" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 msgid "Show advanced settings" msgstr "显示高级设置" @@ -991,8 +1033,8 @@ msgstr "显示高级设置" msgid "Show all settings" msgstr "显示所有设定" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:598 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:606 msgid "Static address" msgstr "静态地址" @@ -1000,7 +1042,7 @@ msgstr "静态地址" msgid "Status" msgstr "状态" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:400 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:412 msgid "Systems settings" msgstr "系统设定" @@ -1013,7 +1055,7 @@ msgstr "" "孤立的(不再被任何应用程序引用)连接在本地端中止之前将保持FIN_WAIT_2状态的时" "间。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:278 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -1034,32 +1076,32 @@ msgid "" "retransmissions remain unacknowledged." msgstr "当未确认RTO重传时,此值会影响有效TCP连接的超时。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:263 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 msgid "Timeout for VPS checks on status pages" msgstr "状态页面上 VPS 检查的超时时间" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:273 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Timeout for retrieving WANs IP on status pages" msgstr "在状态页面上检索 WAN IP 的超时时间" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:365 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:367 msgid "Total traffic:" msgstr "总流量:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:567 msgid "Type" msgstr "类型" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "UBOND可以用具有相同延迟的连接替换Glorytun" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:326 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:328 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:334 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:336 msgid "UBOND password" msgstr "UBOND密码" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:833 msgid "UMTS/GPRS" msgstr "UMTS/GPRS" @@ -1076,17 +1118,17 @@ msgstr "远程将服务器更新到最新版本并重置它们。" msgid "Update server" msgstr "更新服务器" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:949 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1004 msgid "Upload speed (Kb/s)" msgstr "上传速度 (Kb/s)" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 msgid "Uptime:" msgstr "运行时间:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:938 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:954 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1009 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "如果启用,则由Glorytun UDP和使用SQM / QoS, 默认值0." @@ -1094,20 +1136,20 @@ msgstr "如果启用,则由Glorytun UDP和使用SQM / QoS, 默认值0." msgid "V2Ray is not running" msgstr "V2Ray没有运行" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 msgid "V2Ray is used for TCP and UDP." msgstr "V2Ray用于TCP和UDP代理." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "V2Ray user" msgstr "V2Ray账号" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 msgid "V2Ray user id" msgstr "V2Ray账号ID" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:643 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:644 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:651 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:652 msgid "VLAN" msgstr "VLAN" @@ -1115,11 +1157,11 @@ msgstr "VLAN" msgid "VPN is not running" msgstr "VPN没有运行" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:294 msgid "VPN settings" msgstr "VPN设置" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:360 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 msgid "VPN traffic:" msgstr "VPN流量:" @@ -1127,21 +1169,21 @@ msgstr "VPN流量:" msgid "VPN tunnel DOWN" msgstr "VPN隧道关闭" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 msgid "VPS checks timeout" msgstr "VPS 检查超时" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:320 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 msgid "Version" msgstr "版本" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:268 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 msgid "WAN IPs retrieve timeout" msgstr "WAN IP 检索超时" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:584 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:775 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:586 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:591 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:777 msgid "Wan IP and gateway are identical" msgstr "WAN IP和网关相同" @@ -1151,15 +1193,21 @@ msgid "" "used to go outside." msgstr "启用后,将在外部站点上进行检查,以获取每个WAN IP和用于外出的IP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 +#, fuzzy +#| msgid "When proxy shadowsocks is used, use it for UDP if VPN down" +msgid "When proxy V2Ray is used, use it for UDP" +msgstr "当使用代理shadowsocks时,如果VPN关闭,将其用于UDP" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "当使用代理shadowsocks时,如果VPN关闭,将其用于UDP" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 msgid "Wizard" msgstr "聚合向导" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:422 msgid "World" msgstr "世界" @@ -1168,15 +1216,21 @@ msgstr "世界" msgid "You" msgstr "你" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:918 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:934 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "如果提供商过滤多路径TCP,则可以启用VPN上的MPTCP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:907 +msgid "" +"You can force a TTL. Some LTE provider detect tethering by inpecting packet " +"TTL value, setting it to 65 often solve the issue." +msgstr "" + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "如果您有多个真实的以太网端口,则可以使用DHCP。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:617 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." @@ -1184,22 +1238,18 @@ msgstr "" "如果您有多个真实的以太网端口,则可以使用DHCP。 如果要使用“网络接口”页面中可用" "的其他协议,请选择“其他”." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:204 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:212 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "仅当您仅设置一台服务器时,才能使用公共IPv6前缀。" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:538 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "您必须在调制解调器上禁用DHCP并在其他网络中设置IP." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "如果服务器不提供IPv6,则应在此处禁用IPv6." -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:928 -msgid "You should disable SQM for LTE or any interfaces with variable speed." -msgstr "您应该为LTE或任何网速不稳的接口禁用SQM." - #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:58 msgid "You shouldn't do that and you should redirect only needed ports" msgstr "错了亲,试试重定向端口" @@ -1212,7 +1262,7 @@ msgstr "您访问的IP来源未通过此路由器" msgid "address:" msgstr "地址:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 msgid "auto" msgstr "自动" @@ -1220,43 +1270,43 @@ msgstr "自动" msgid "empty key" msgstr "空键" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:506 msgid "interface:" msgstr "接口:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:488 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:737 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:490 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:739 msgid "ip address:" msgstr "IP地址:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:492 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:494 msgid "ipv6 address:" msgstr "IPV6地址:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:518 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:751 msgid "latency:" msgstr "时延:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:755 msgid "mtu:" msgstr "mtu :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:644 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:808 msgid "multipath:" msgstr "多路聚合:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:524 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:526 msgid "operator:" msgstr "运营商:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 msgid "other" msgstr "其他" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:528 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:530 msgid "phone number:" msgstr "电话号码:" @@ -1264,30 +1314,34 @@ msgstr "电话号码:" msgid "range:" msgstr "漫游:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:532 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:534 msgid "state:" msgstr "状态:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:647 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:809 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:649 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:811 msgid "traffic control:" msgstr "流量控制:" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:498 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:743 msgid "wan address:" msgstr "互联网地址 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:502 msgid "wan ipv6 address:" msgstr "IPV6互联网地址 :" -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 -#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:747 msgid "whois:" msgstr "whois查询 :" +#~ msgid "" +#~ "You should disable SQM for LTE or any interfaces with variable speed." +#~ msgstr "您应该为LTE或任何网速不稳的接口禁用SQM." + #~ msgid "Common server settings" #~ msgstr "通用服务器设置聚合" diff --git a/luci-app-snmpd/po/it/snmpd.po b/luci-app-snmpd/po/it/snmpd.po index 488c54486..5517296de 100644 --- a/luci-app-snmpd/po/it/snmpd.po +++ b/luci-app-snmpd/po/it/snmpd.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-09-21 12:51+0000\n" -"Last-Translator: Weblate Admin \n" +"PO-Revision-Date: 2022-02-21 21:14+0000\n" +"Last-Translator: Deleted User \n" "Language-Team: Italian \n" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.10.1\n" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:82 msgid "Access" @@ -51,13 +51,13 @@ msgstr "Abilitato" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:132 msgid "Exec" -msgstr "" +msgstr "Esegui" #: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:6 #: luci-app-snmpd/luasrc/view/snmpd.htm:21 #: luci-app-snmpd/luasrc/view/snmpd.htm:48 msgid "General" -msgstr "" +msgstr "Generale" #: luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json:3 msgid "Grant UCI access for luci-app-snmpd" diff --git a/luci-app-sqm-autorate/po/fr/sqm.po b/luci-app-sqm-autorate/po/fr/sqm.po index b4ae43d92..91b243562 100644 --- a/luci-app-sqm-autorate/po/fr/sqm.po +++ b/luci-app-sqm-autorate/po/fr/sqm.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-08-08 14:26+0000\n" -"Last-Translator: ButterflyOfFire \n" -"Language-Team: French \n" +"PO-Revision-Date: 2022-08-10 18:51+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" "Language: fr\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.2-dev\n" +"X-Generator: Weblate 4.10.1\n" #: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 msgid "" @@ -49,7 +49,7 @@ msgstr "" #: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 msgid "Enable SQM" -msgstr "" +msgstr "Active SQM" #: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 msgid "Enable this SQM instance." From 54bd5c2571c2ac4481001a6409084bc8d00299d1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Aug 2022 13:59:24 +0200 Subject: [PATCH 0828/2059] Back to ifconfig.co --- luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 6c9792f45..8fd59ecb4 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -824,7 +824,7 @@ function interfaces_status() if mArray.openmptcprouter["external_check"] ~= false then mArray.openmptcprouter["proxy_addr"] = ut.trim(sys.exec("curl -s -4 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m " .. timeout .. " " .. check_ipv4_website)) if mArray.openmptcprouter["proxy_addr"] == "" then - mArray.openmptcprouter["proxy_addr"] = ut.trim(sys.exec("curl -s -4 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m " .. timeout .. " ifconfig.me")) + mArray.openmptcprouter["proxy_addr"] = ut.trim(sys.exec("curl -s -4 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m " .. timeout .. " ifconfig.co")) end --mArray.openmptcprouter["ss_addr6"] = sys.exec("curl -s -6 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m 3 http://ipv6.openmptcprouter.com") end From 7d528284e0edffc5a465a99c405480935ea507a0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 14 Aug 2022 08:53:24 +0200 Subject: [PATCH 0829/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/2465 --- .../luasrc/controller/openmptcprouter.lua | 2 ++ omr-tracker/files/bin/omr-tracker-server | 14 ++++++++++++++ openmptcprouter/files/etc/init.d/mptcpovervpn | 13 +++++++------ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index f2142f37f..ce5edb130 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -584,10 +584,12 @@ function wizard_add() ucic:set("openmptcprouter",server,"get_config","1") end ucic:set("openmptcprouter",server,"master","1") + ucic:set("openmptcprouter",server,"current","1") ucic:set("openmptcprouter",server,"backup","0") else ucic:set("openmptcprouter",server,"get_config","0") ucic:set("openmptcprouter",server,"master","0") + ucic:set("openmptcprouter",server,"current","0") ucic:set("openmptcprouter",server,"backup","1") end if openmptcprouter_vps_disabled == "1" then diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 662eabcc5..a25bf9055 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -91,6 +91,8 @@ _check_master() { del openvpn.omr.remote add_list openvpn.omr.remote=$ip commit openvpn + set openmptcprouter.vps.current='1' + commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null @@ -99,6 +101,7 @@ _check_master() { /etc/init.d/mlvpn restart >/dev/null 2>/dev/null /etc/init.d/openvpn restart >/dev/null 2>/dev/null /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + /etc/init.d/mptcpovervpn restart >/dev/null 2>/dev/null fi fi config_load shadowsocks-libev @@ -106,6 +109,10 @@ _check_master() { count=$((count+1)) else logger -t "OMR-Tracker-Server" "Master server ${name} down ($ip)" + uci -q batch <<-EOF >/dev/null + set openmptcprouter.vps.current='0' + commit openmptcprouter + EOF config_load shadowsocks-libev config_foreach _disable_redir ss_redir fi @@ -162,6 +169,8 @@ _check_backup() { del openvpn.omr.remote add_list openvpn.omr.remote=$ip commit openvpn + set openmptcprouter.vps.current='1' + commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null @@ -170,6 +179,7 @@ _check_backup() { /etc/init.d/mlvpn restart >/dev/null 2>/dev/null /etc/init.d/openvpn restart >/dev/null 2>/dev/null /etc/init.d/dsvpn restart >/dev/null 2>/dev/null + /etc/init.d/mptcpovervpn restart >/dev/null 2>/dev/null fi sleep $waittest fi @@ -177,6 +187,10 @@ _check_backup() { config_foreach _enable_redir ss_redir count=$((count+1)) else + uci -q batch <<-EOF >/dev/null + set openmptcprouter.vps.current='0' + commit openmptcprouter + EOF config_load shadowsocks-libev config_foreach _disable_redir ss_redir fi diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index 0bb30c0dd..da3550df0 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -17,7 +17,7 @@ wireguard_restart() { } _getremoteip() { - [ "$(uci -q get openmptcprouter.$1.master)" = "1" ] && { + [ "$(uci -q get openmptcprouter.$1.current)" = "1" ] && { remoteip=$(uci -q get openmptcprouter.$1.ip | awk '{print $1}') wg_server_key=$(uci -q get openmptcprouter.$1.wgkey) } @@ -27,6 +27,10 @@ mptcp_over_vpn() { local interface=$1 [ -n "$(uci show firewall.zone_wan.network | grep $interface)" ] && nbintf=$(($nbintf+1)) if [ "$(uci -q get openmptcprouter.${interface}.multipathvpn)" = "1" ]; then + remoteip="" + config_load openmptcprouter + config_foreach _getremoteip server + if [ "$(uci -q get network.${interface})" = "" ]; then uci -q batch <<-EOF >/dev/null delete openmptcprouter.${interface} @@ -47,12 +51,9 @@ mptcp_over_vpn() { return fi nbintfvpn=$(($nbintfvpn+1)) - if [ "$(uci -q get network.ovpn${interface})" = "" ] && [ "$vpn" = "openvpn" ]; then + if ([ "$(uci -q get network.ovpn${interface})" = "" ] || [ "$(uci -q get openvpn.${interface}.remote)" != "${remoteip}" ]) && [ "$vpn" = "openvpn" ]; then logger -t "MPTCPoverVPN" "Enable MPTCP over VPN for ${interface}" id=$(uci -q get network.${interface}.metric) - remoteip="" - config_load openmptcprouter - config_foreach _getremoteip server localip=$(ubus call network.interface.$interface status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") [ -z "$(uci -q get openmptcprouter.ovpn${interface}.multipath)" ] && multipath=$(uci -q get network.${interface}.multipath) [ -n "$(uci -q get openmptcprouter.ovpn${interface}.multipath)" ] && multipath=$(uci -q get openmptcprouter.ovpn${interface}.multipath) @@ -103,7 +104,7 @@ mptcp_over_vpn() { add_list firewall.zone_vpn.network="ovpn${interface}" commit firewall EOF - elif [ "$(uci -q get network.wg${interface})" = "" ] && [ "$vpn" = "wireguard" ]; then + elif ([ "$(uci -q get network.wg${interface})" = "" ] || [ "$(uci -q get network.@wireguard_wg${interface}[0].endpoint_host)" != "$remoteip" ]) && [ "$vpn" = "wireguard" ]; then logger -t "MPTCPoverVPN" "Enable MPTCP over VPN for ${interface}" id=$(uci -q get network.${interface}.metric) remoteip="" From 04f77f602fbf54ae1b05393c2326fe46ebf292d8 Mon Sep 17 00:00:00 2001 From: openmptcprouter-translation <66313742+openmptcprouter-translation@users.noreply.github.com> Date: Mon, 15 Aug 2022 19:10:53 +0200 Subject: [PATCH 0830/2059] Translations update from Weblate (#105) * Translated using Weblate (Italian) Currently translated at 93.7% (269 of 287 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/it/ * Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/ * Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: OpenMPTCProuter/LuCI/applications/mptcp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsmptcp/ * Translated using Weblate (Italian) Currently translated at 90.8% (269 of 296 strings) Translation: OpenMPTCProuter/LuCI/applications/openmptcprouter Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsopenmptcprouter/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 93.1% (54 of 58 strings) Translation: OpenMPTCProuter/LuCI/applications/mptcp Translate-URL: http://weblate.openmptcprouter.com/projects/omr/luciapplicationsmptcp/zh_Hans/ Co-authored-by: tiziano Co-authored-by: Weblate --- luci-app-mptcp/po/zh_Hans/mptcp.po | 4 +- .../po/de/openmptcprouter.po | 5 +- .../po/fr/openmptcprouter.po | 3 + .../po/it/openmptcprouter.po | 305 +++++++++++++++++- .../po/oc/openmptcprouter.po | 6 +- .../po/zh_Hans/openmptcprouter.po | 6 +- 6 files changed, 312 insertions(+), 17 deletions(-) diff --git a/luci-app-mptcp/po/zh_Hans/mptcp.po b/luci-app-mptcp/po/zh_Hans/mptcp.po index cfa888b3b..36a27a977 100644 --- a/luci-app-mptcp/po/zh_Hans/mptcp.po +++ b/luci-app-mptcp/po/zh_Hans/mptcp.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2022-08-12 12:08+0000\n" +"PO-Revision-Date: 2022-08-12 19:29+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: Chinese (Simplified) \n" @@ -85,7 +85,6 @@ msgid "Grant UCI access for luci-app-mptcp" msgstr "授予UCI访问luci-app-mptcp的权限" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 -#, fuzzy msgid "" "If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " "MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " @@ -167,7 +166,6 @@ msgstr "多路径TCP调度程序" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 #, fuzzy -#| msgid "Multipath TCP" msgid "Multipath TCP version" msgstr "多路径TCP" diff --git a/luci-app-openmptcprouter/po/de/openmptcprouter.po b/luci-app-openmptcprouter/po/de/openmptcprouter.po index fddbdb4c0..73e6b7cf6 100644 --- a/luci-app-openmptcprouter/po/de/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/de/openmptcprouter.po @@ -357,7 +357,6 @@ msgstr "SQM aktiv" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 #, fuzzy -#| msgid "Enable SQM" msgid "Enable SQM autorate" msgstr "SQM aktiv" @@ -1418,3 +1417,7 @@ msgstr "" #~ msgid "Redundant" #~ msgstr "redundant" + +#, fuzzy +#~ msgid "Disable HTTP test on Server API in status page" +#~ msgstr "Server-Ping Status-Prüfung aus" diff --git a/luci-app-openmptcprouter/po/fr/openmptcprouter.po b/luci-app-openmptcprouter/po/fr/openmptcprouter.po index b48aaa23c..c55a741bb 100644 --- a/luci-app-openmptcprouter/po/fr/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/fr/openmptcprouter.po @@ -1560,3 +1560,6 @@ msgstr "whois :" #~ msgid "MLVPN can replace Glorytun with connection with same latency" #~ msgstr "" #~ "MLVPN peut remplacer Glorytun pour les connexions avec la même latence" + +#~ msgid "Disable HTTP test on Server API in status page" +#~ msgstr "Désactiver le test HTTP sur l'API du serveur dans la page d'état" diff --git a/luci-app-openmptcprouter/po/it/openmptcprouter.po b/luci-app-openmptcprouter/po/it/openmptcprouter.po index eeffeb590..19c08ec9d 100644 --- a/luci-app-openmptcprouter/po/it/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/it/openmptcprouter.po @@ -11,15 +11,19 @@ msgstr "" "X-Generator: Weblate 4.10.1\n" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 msgid "A Dead Simple VPN is a TCP VPN that can replace Glorytun TCP" msgstr "Una Dead Simple VPN è una VPN TCP che può sostituire Glorytun TCP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:310 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:312 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:302 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:304 msgid "A Dead Simple VPN key" msgstr "Chiave Dead Simple VPN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 msgid "" "A second server's IP can be set for dual IPv4/IPv6 server if WAN IPv6 are set" msgstr "" @@ -27,23 +31,28 @@ msgstr "" "impostato il server WAN IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:119 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:111 msgid "API username to retrieve personnalized settings from the server." msgstr "" "Nome utente API per recuperare le impostazioni personalizzate dal server." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:814 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:809 msgid "APN" msgstr "APN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:742 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:734 msgid "Accept IPv6 RA" msgstr "Accetta IPv6 RA" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:164 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:156 msgid "Add a new server" msgstr "Aggiungi un nuovo server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1044 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:989 msgid "Add an interface" msgstr "Aggiungi un'interfaccia" @@ -53,10 +62,12 @@ msgid "Advanced Settings" msgstr "Impostazioni avanzate" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:169 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:161 msgid "Advanced settings" msgstr "Impostazioni avanzate" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 msgid "" "All VPN available here can do aggregation over MPTCP or using own internal " "method." @@ -69,6 +80,7 @@ msgid "All router settings" msgstr "Impostazioni del router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:284 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:276 msgid "" "An Advanced Encryption Standard (AES) instruction set is integrated in the " "processor." @@ -77,11 +89,14 @@ msgstr "" "processore." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 msgid "Authentication Type" msgstr "Tipo di autenticazione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:878 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:894 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:873 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:889 msgid "Backup" msgstr "Backup" @@ -91,6 +106,7 @@ msgid "Backup on server" msgstr "Backup su server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:383 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:371 msgid "Balancing" msgstr "Bilanciamento" @@ -99,24 +115,29 @@ msgid "Beta" msgstr "Beta" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:312 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:310 msgid "Big time difference between the server and the router" msgstr "Grande differenza di fuso orario tra il server e il router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:572 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:564 msgid "Bridge" msgstr "Ponte" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:620 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:618 msgid "Bridge can't have multipath enabled" msgstr "Il Bridge non può avere il multipath abilitato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:287 msgid "By default VPN is used for any traffic that is not TCP." msgstr "" "Per impostazione predefinita, la VPN viene utilizzata per qualsiasi traffico " "che non sia TCP." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:229 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:221 msgid "" "By default proxy is used for any traffic that is TCP (and UDP for V2Ray)." msgstr "" @@ -124,6 +145,7 @@ msgstr "" "traffico che sia TCP (e UDP per V2Ray)." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:845 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:840 msgid "CHAP" msgstr "CHAP" @@ -154,10 +176,12 @@ msgid "Can\\'t ping server" msgstr "Impossibile eseguire il ping del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:423 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 msgid "China" msgstr "Cina" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:576 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:568 msgid "" "Choose MacVLAN if you want to create a virtual interface based on a physical " "interface." @@ -168,6 +192,9 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:596 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:655 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:502 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:588 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:647 msgid "Choose physical interface." msgstr "Scegli l'interfaccia fisica." @@ -176,19 +203,24 @@ msgid "Core temp:" msgstr "Temp. Nucleo:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:418 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:410 msgid "Country" msgstr "Nazione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:407 msgid "Country settings" msgstr "Impostazioni nazionali del router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:462 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:607 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:454 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:599 msgid "DHCP" msgstr "DHCP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:608 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:600 msgid "DHCPv6" msgstr "DHCPv6" @@ -197,36 +229,45 @@ msgid "DNS issue: can\\'t resolve hostname" msgstr "Problema DNS: impossibile risolvere il nome host" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:367 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:355 msgid "Debug" msgstr "Debug" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:231 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:223 msgid "Default Proxy" msgstr "Proxy predefinito" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:345 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:337 msgid "Default VPN" msgstr "VPN predefinita" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:551 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:77 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:543 msgid "Delete" msgstr "Elimina" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:749 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:774 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:794 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:741 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:768 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:789 msgid "Device" msgstr "Dispositivo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 #, fuzzy -#| msgid "Disable HTTP test on Server API in status page" msgid "Disable HTTP test on Server API" msgstr "Disabilitare il test HTTP sulle API Server nella pagina di stato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:357 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:362 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:345 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:350 msgid "Disable ModemManager" msgstr "Disabilita ModemManager" @@ -239,10 +280,12 @@ msgid "Disable TCP Fast Open on Linux and Shadowsocks configuration" msgstr "Disabilita TCP Fast Open su Linux e configurazione Shadowsocks" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 msgid "Disable default gateway" msgstr "Disabilita il gateway predefinito" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:312 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:300 msgid "Disable default gateway, no internet if VPS are down" msgstr "" "Disabilita il gateway predefinito, niente Internet se i VPS sono inattivi" @@ -252,26 +295,32 @@ msgid "Disable external check" msgstr "Disabilita controllo esterno" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:238 msgid "Disable gateway ping" msgstr "Disabilita il ping del gateway" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:243 msgid "Disable gateway ping check in status page" msgstr "Disabilita il controllo del ping del gateway nella pagina di stato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:285 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 msgid "Disable interfaces auto rename" msgstr "Disabilita auto rinomina interfacce" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:342 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:330 msgid "Disable multipath test using tracebox" msgstr "Disabilita il test multipath usando tracebox" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:335 msgid "Disable nDPI" msgstr "Disabilita nDPI" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:352 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:340 msgid "Disable nDPI, used for protocols in OMR-ByPass" msgstr "" @@ -283,63 +332,80 @@ msgstr "" "a questo router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:290 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:284 msgid "Disable renaming interfaces" msgstr "Disabilita rinomina interfaccia" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:327 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:332 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:315 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:320 #, fuzzy msgid "Disable route loop detection" msgstr "Disabilita il ping del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:152 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:144 msgid "Disable server" msgstr "Disabilita il server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:248 msgid "Disable server http test" msgstr "Disabilita http test server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:317 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:305 msgid "Disable server ping" msgstr "Disabilita il ping del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:310 msgid "Disable server ping status check" msgstr "Disabilitare il controllo dello stato del ping del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:337 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:325 msgid "Disable tracebox test" msgstr "Disabilita il test Tracebox" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:197 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:876 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:892 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:189 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:871 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:887 msgid "Disabled" msgstr "Disabilitato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:988 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:933 msgid "Download speed (Kb/s)" msgstr "Velocità di download (Kb / s)" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:369 msgid "Dynamic change" msgstr "Cambiamento dinamico" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:402 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:390 msgid "Enable Bridge Acceleration" msgstr "Abilita Accelerazione modalità Bridge" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:217 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:209 msgid "Enable DNS64" msgstr "Abilita DNS64" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:396 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:384 msgid "Enable Fast Patch offloading for connections" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:187 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 msgid "Enable IPv6" msgstr "Abilita IPv6" @@ -352,12 +418,12 @@ msgid "Enable SIP ALG" msgstr "Abilita SIP ALG" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:942 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:923 msgid "Enable SQM" msgstr "Abilita MQ" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 #, fuzzy -#| msgid "Enable SQM" msgid "Enable SQM autorate" msgstr "Abilita MQ" @@ -370,20 +436,26 @@ msgid "Enable TCP Low Latency" msgstr "Abilita TCP bassa latenza" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:372 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:360 msgid "Enable debug logs" msgstr "Abilita registro di debug" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:198 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:875 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:891 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:190 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:870 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:886 msgid "Enabled" msgstr "Abilitato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:267 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 msgid "Encryption" msgstr "Crittografia" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:288 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:280 msgid "Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN." msgstr "" "Il metodo di crittografia viene utilizzato per Shadowsocks, V2Ray, Glorytun " @@ -394,6 +466,7 @@ msgid "Filesystem is readonly" msgstr "Il filesystem è di sola lettura" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:419 msgid "For China, set an accessible DNS and disable DNSSEC." msgstr "Per la Cina, imposta un DNS accessibile e disabilita DNSSEC." @@ -402,33 +475,42 @@ msgid "Force TTL" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:186 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:178 msgid "Force retrieve all keys from server." msgstr "Forza il recupero di tutte le chiavi dal server." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:181 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:173 msgid "Force retrieve settings" msgstr "Forza il recupero delle impostazioni" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:834 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 msgid "GPRS only" msgstr "Solo GPRS" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:563 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:766 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:561 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:764 msgid "Gateway DOWN" msgstr "Tipi di pagamento" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:566 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:564 msgid "Gateway IPv6 DOWN" msgstr "Gateway IPV6 non raggiungibile" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:303 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 msgid "Glorytun TCP is used by default for UDP and ICMP" msgstr "" "Glorytun TCP viene utilizzato per impostazione predefinita per UDP e ICMP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:298 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:300 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:290 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:292 msgid "Glorytun key" msgstr "Chiave Glorytun" @@ -472,38 +554,51 @@ msgstr "IPv4 TCP SYN retries2" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:518 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:661 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:510 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:653 msgid "IPv4 address" msgstr "Indirizzi IPv4" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:677 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:669 msgid "IPv4 gateway" msgstr "Gateway IPv4" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:524 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:671 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:516 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:663 msgid "IPv4 netmask" msgstr "Netmask IPv4" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:207 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:199 msgid "IPv6 Prefix" msgstr "Prefisso IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:691 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:718 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:683 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 msgid "IPv6 address" msgstr "Indirizzi IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:705 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:728 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:697 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:720 msgid "IPv6 gateway" msgstr "Gateway IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:634 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:632 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:804 msgid "IPv6 route received" msgstr "Instradamento IPv6 ricevuto" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:192 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:184 msgid "IPv6 settings" msgstr "Impostazioni IPv6" @@ -512,14 +607,17 @@ msgid "IPv6 tunnel DOWN" msgstr "Tunnel IPv6 GIÙ" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:352 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:350 msgid "IPv6:" msgstr "IPv6:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:222 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:214 msgid "If host support NAT64, you can enable DNS64 support." msgstr "Se l'host supporta NAT64, puoi abilitare il supporto DNS64." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:537 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:529 msgid "Interfaces settings" msgstr "Impostazioni delle interfacce" @@ -529,12 +627,19 @@ msgstr "Impostazioni delle interfacce" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:315 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:307 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 msgid "Key is retrieved from server API by default." msgstr "" "La chiave viene recuperata dall'API del server per impostazione " "predefinita." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:129 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:121 msgid "" "Key to configure and retrieve others keys from Server and to set server " "settings from OpenMPTCProuter." @@ -543,20 +648,26 @@ msgstr "" "le impostazioni del server da OpenMPTCProuter." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:435 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:427 msgid "LAN interfaces settings" msgstr "Impostazioni delle interfacce LAN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:832 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:827 msgid "LTE" msgstr "LTE" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:446 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:557 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:438 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:549 msgid "Label" msgstr "Etichetta" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:452 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:444 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:554 msgid "Label for the interface" msgstr "Etichetta per l'interfaccia" @@ -566,24 +677,30 @@ msgstr "Ultimo backup disponibile sul server:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:124 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:329 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:327 msgid "Latest available version" msgstr "Ultima versione disponibile" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:130 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:335 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:333 msgid "Load:" msgstr "Carico:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:630 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:628 msgid "Looping route detected" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:327 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:319 msgid "MLVPN can replace Glorytun with connections with same latency" msgstr "MLVPN può sostituire Glorytun con connessioni con la stessa latenza" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:322 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:324 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:314 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:316 msgid "MLVPN password" msgstr "Password MLVPN" @@ -592,19 +709,24 @@ msgid "MPTCP is not enabled on the server" msgstr "MPTCP non è abilitato sul server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:346 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:344 msgid "MPTCP may not be enabled on the server" msgstr "MPTCP non è abilitato sul server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:929 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:393 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:913 msgid "MPTCP over VPN" msgstr "MPTCP su VPN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:398 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:390 msgid "MPTCP over VPN settings" msgstr "Impostazioni MPTCP su VPN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 msgid "" "MPTCP over VPN should be used only when Multipath TCP is blocked on a " "connection." @@ -613,35 +735,44 @@ msgstr "" "una connessione." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:571 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:563 msgid "MacVLAN" msgstr "MacVLAN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:893 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 msgid "Master" msgstr "Principale" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:377 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:365 msgid "Master interface selection" msgstr "Selezione dell'interfaccia principale" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:421 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:409 msgid "Maximum scaling CPU frequency" msgstr "Frequenza CPU di ridimensionamento massima" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:403 msgid "Minimum scaling CPU frequency" msgstr "Frequenza CPU con ridimensionamento minimo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:829 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:824 msgid "Modem default" msgstr "Impostazione predefinita del modem" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:863 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:858 msgid "Modem init timeout" msgstr "Timeout inizializzazione modem" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:601 msgid "ModemManager" msgstr "ModemManager" @@ -651,6 +782,8 @@ msgstr "È abilitata più di una VPN predefinita" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:872 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:888 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:867 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:883 msgid "Multipath TCP" msgstr "Multipath TCP" @@ -658,42 +791,57 @@ msgstr "Multipath TCP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:609 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:789 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:795 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:601 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:607 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:787 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:793 msgid "Multipath current state is" msgstr "Lo stato corrente di Multipath è" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:598 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:784 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:596 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:782 msgid "Multipath master already defined" msgstr "Multipath principale già definito" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:569 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:769 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:567 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:767 msgid "Multipath seems to be blocked on the connection" msgstr "Multipath sembra essere bloccato sulla connessione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:610 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 msgid "NCM" msgstr "NCM" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:843 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:838 msgid "NONE" msgstr "NESSUNO" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:625 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:623 msgid "Network interface MAC address duplicated" msgstr "Interfaccia di rete con MAC address duplicata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:615 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:801 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:613 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:799 msgid "Network interface duplicated" msgstr "Interfaccia di rete duplicata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:581 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:579 msgid "Network interface not in WAN firewall zone" msgstr "Interfaccia di rete non in WAN firewall zone" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:901 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:903 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:899 msgid "Network overview" msgstr "Panoramica della rete" @@ -703,6 +851,8 @@ msgstr "Impostazioni reti" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:556 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:759 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:554 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:757 msgid "No IP defined" msgstr "Nessun IP definito" @@ -711,15 +861,19 @@ msgid "No IPv6 access" msgstr "Nessun accesso IPv6" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:577 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:575 msgid "No Server http response after 1 second" msgstr "Nessuna risposta dal server HTTP dopo 1 secondo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:573 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:773 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:571 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:771 msgid "No Server ping response after 1 second" msgstr "Nessuna risposta al ping dal server dopo 1 secondo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:658 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:656 msgid "No WAN with multipath enabled:" msgstr "Nessuna WAN con multipath abilitata:" @@ -728,15 +882,19 @@ msgid "No available backup on server." msgstr "Nessun backup disponibile sul server." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:382 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:370 msgid "No change" msgstr "Nessun cambiamento" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:821 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:819 msgid "No data" msgstr "Nessun dato" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:560 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:763 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:558 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:761 msgid "No gateway defined" msgstr "Nessun gateway definito" @@ -759,10 +917,13 @@ msgstr "Nessun server definito" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:273 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:421 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:265 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:413 msgid "None" msgstr "Nessuno" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:570 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:562 msgid "Normal" msgstr "Normale" @@ -787,14 +948,17 @@ msgid "Obfuscating will be enabled on both side" msgstr "L'offuscamento sarà abilitato su entrambi i lati" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:380 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:368 msgid "On wizard change" msgstr "Al cambio della procedura guidata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:233 msgid "Only ShadowSocks is supported with server multiple IPs for now." msgstr "Solo ShadowSocks è supportato con server multi IP per adesso." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:882 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:877 msgid "" "Only one interface must be set as \"Master\", this should be the most stable " "interface." @@ -803,12 +967,14 @@ msgstr "" "impostata l'interfaccia più stabile." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:143 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:135 msgid "Only one server can be master, else all servers are set as backup." msgstr "" "Solo un server può essere master, altrimenti tutti i server sono impostati " "come backup." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:399 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:391 msgid "Only work with Shadowsocks as proxy." msgstr "Funziona solo con Shadowsocks come proxy." @@ -817,6 +983,7 @@ msgid "OpenMPTCProuter" msgstr "OpenMPTCProuter" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 msgid "OpenVPN can't be used in multi VPS configuration." msgstr "OpenVPN non può essere utilizzato nella configurazione multi VPS." @@ -826,57 +993,74 @@ msgstr "Ottimizza per la latenza invece che per la larghezza di banda" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:463 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:613 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:455 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:605 msgid "Other" msgstr "Altro" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:231 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:225 msgid "Other settings" msgstr "Altre impostazioni" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:844 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:839 msgid "PAP" msgstr "PAP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:841 msgid "PAP/CHAP" msgstr "PAP/CHAP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:857 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:852 msgid "PAP/CHAP password" msgstr "PAP/CHAP password" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:851 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:846 msgid "PAP/CHAP username" msgstr "Nome utente PAP/CHAP" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:820 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:815 msgid "PIN code" msgstr "Codice PIN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:611 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:603 msgid "PPPoE" msgstr "PPPoE" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:475 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:581 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:622 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:573 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:614 msgid "Physical interface" msgstr "Interfaccia fisica" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:825 msgid "Prefer LTE" msgstr "Preferisci LTE" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:831 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 msgid "Prefer UMTS" msgstr "Preferisci UMTS" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:102 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:94 msgid "Primary server IP" msgstr "IP principale del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:457 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:602 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:449 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:594 msgid "Protocol" msgstr "Protocollo" @@ -885,14 +1069,17 @@ msgid "Proxy is DISABLED" msgstr "Il proxy è DISABILITATO" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:228 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:220 msgid "Proxy settings" msgstr "Impostazioni Proxy" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:357 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:355 msgid "Proxy traffic:" msgstr "Traffico proxy:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:612 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:604 msgid "QMI" msgstr "QMI" @@ -901,6 +1088,7 @@ msgid "QoS permit to prioritize any upload traffic." msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:393 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:381 msgid "Qualcomm Shortcut FE driver" msgstr "" @@ -909,6 +1097,7 @@ msgid "Redirects all ports from server to this router" msgstr "Reindirizza tutte le porte dal server a questo router" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1054 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:999 msgid "Reset" msgstr "Resetta" @@ -917,6 +1106,7 @@ msgid "Restore backup" msgstr "Ripristina backup" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:179 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 msgid "Retrieve settings from server" msgstr "Recupera le impostazioni dal server" @@ -932,26 +1122,33 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:447 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1053 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:435 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 msgid "Save & Apply" msgstr "Salva e applica" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:239 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:233 msgid "Save vnstats statistics on disk" msgstr "Salva le statistiche di vnstats su disco" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:234 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:228 msgid "Save vnstats stats" msgstr "Salva le statistiche di vnstats" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:427 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:415 msgid "Scaling governor" msgstr "Governatore in scala" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:103 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 msgid "Secondary server IP" msgstr "IP secondario del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1047 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:992 msgid "Select the device you want to base the interface on." msgstr "Seleziona il dispositivo su cui vuoi basare l'interfaccia." @@ -962,58 +1159,79 @@ msgstr "Invia backup" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:91 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:93 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:100 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:83 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:85 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:92 msgid "Server IP" msgstr "Indirizzo IP del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:95 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:105 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:87 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:97 msgid "Server IP will be set for proxy and VPN" msgstr "L'IP del server verrà impostato per proxy e VPN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:124 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:126 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:118 msgid "Server key" msgstr "Chiave server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:43 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:75 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:67 msgid "Server settings" msgstr "Impostazioni server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:114 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:116 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:106 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:108 msgid "Server username" msgstr "Nome utente del server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:826 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:821 msgid "Service Type" msgstr "Tipo di servizio" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:409 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:401 msgid "Set VPN to use for MPTCP over VPN." msgstr "Seleziona la VPN da utilizzare per MPTCP su VPN." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:666 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:696 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:723 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:658 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:688 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:715 msgid "Set an IP in the same network as the modem" msgstr "Imposta un IP nella stessa rete del modem" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:416 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:408 msgid "Set configuration for countries with some specificities." msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:682 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:710 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:733 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:674 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:702 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:725 msgid "Set here IP of the modem" msgstr "Imposta qui l'IP del modem" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:138 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:130 msgid "Set server as master" msgstr "Imposta server come master" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:240 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:232 msgid "" "Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and " "UDP when V2Ray is enabled." @@ -1022,6 +1240,7 @@ msgstr "" "abilitato, per TCP e UDP quando V2Ray è abilitato." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:392 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:384 #, fuzzy msgid "" "Set the default VPN used for ICMP (and UDP if proxy used is shadowsocks), " @@ -1031,6 +1250,7 @@ msgstr "" "abilitato, per tutto il traffico se ShadowSocks è disabilitato." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:998 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:943 msgid "" "Set value between 80-95% of max download speed link. 0 to disable SQM/QoS." msgstr "" @@ -1038,6 +1258,7 @@ msgstr "" "del collegamento" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1014 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:959 msgid "" "Set value between 80-95% of max upload speed link. 0 to disable SQM/QoS." msgstr "" @@ -1053,15 +1274,19 @@ msgid "ShadowSocks is not running" msgstr "ShadowSocks non è in esecuzione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:252 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:244 msgid "ShadowSocks is used for TCP." msgstr "ShadowSocks viene utilizzato per TCP." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:247 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:239 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:241 msgid "ShadowSocks key" msgstr "Chiave ShadowSocks" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:171 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:163 #, fuzzy msgid "Show advanced settings" msgstr "Impostazioni avanzate" @@ -1072,6 +1297,8 @@ msgstr "Mostra tutte le impostazioni" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:461 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:606 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:453 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:598 msgid "Static address" msgstr "Indirizzo statico" @@ -1080,6 +1307,7 @@ msgid "Status" msgstr "Stato proprietà" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:412 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:400 msgid "Systems settings" msgstr "Impostazioni di sistema" @@ -1094,6 +1322,7 @@ msgstr "" "interrotta all'estremità locale." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:278 msgid "" "There is no Advanced Encryption Standard (AES) instruction set integrated in " "the processor, you should use chacha20." @@ -1120,32 +1349,40 @@ msgstr "" "ritrasmissioni RTO rimangono non riconosciute." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:269 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:263 #, fuzzy msgid "Timeout for VPS checks on status pages" msgstr "Disabilitare il controllo dello stato del ping del gateway" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:279 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:273 msgid "Timeout for retrieving WANs IP on status pages" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:367 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:365 msgid "Total traffic:" msgstr "Traffico globale:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:567 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:559 msgid "Type" msgstr "Tipo" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:339 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:331 msgid "UBOND can replace Glorytun with connections with same latency" msgstr "UBOND può sostituire Glorytun con connessioni con la stessa latenza" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:334 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:336 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:326 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:328 msgid "UBOND password" msgstr "Password UBOND" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:833 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:828 msgid "UMTS/GPRS" msgstr "UMTS/GPRS" @@ -1163,16 +1400,20 @@ msgid "Update server" msgstr "Aggiorna server" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1004 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:949 msgid "Upload speed (Kb/s)" msgstr "Velocità di caricamento (Kb / s)" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:141 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:341 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:339 msgid "Uptime:" msgstr "Tempo di funzionamento:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:993 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:1009 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:938 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:954 msgid "Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value." msgstr "" "Utilizzato da Glorytun UDP e SQM / QoS se abilitato. 0 per usare i valori " @@ -1183,19 +1424,24 @@ msgid "V2Ray is not running" msgstr "V2Ray non è in esecuzione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:262 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:254 msgid "V2Ray is used for TCP and UDP." msgstr "V2Ray è utilizzato per TCP e UDP." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:259 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:251 msgid "V2Ray user" msgstr "Utente V2Ray" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:257 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:249 msgid "V2Ray user id" msgstr "ID utente V2Ray" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:651 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:652 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:643 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:644 msgid "VLAN" msgstr "VLAN" @@ -1204,10 +1450,12 @@ msgid "VPN is not running" msgstr "VPN non è in esecuzione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:294 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:286 msgid "VPN settings" msgstr "Impostazioni VPN" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:362 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:360 msgid "VPN traffic:" msgstr "Traffico VPN:" @@ -1216,20 +1464,26 @@ msgid "VPN tunnel DOWN" msgstr "Tunnel VPN non stabilito" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:264 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:258 msgid "VPS checks timeout" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:322 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:320 msgid "Version" msgstr "Versione" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:274 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:268 msgid "WAN IPs retrieve timeout" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:586 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:591 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:777 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:584 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:589 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:775 msgid "Wan IP and gateway are identical" msgstr "IP Wan e gateway sono identici" @@ -1243,19 +1497,21 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 #, fuzzy -#| msgid "V2Ray is used for TCP and UDP." msgid "When proxy V2Ray is used, use it for UDP" msgstr "V2Ray è utilizzato per TCP e UDP." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:295 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:289 msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:73 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:65 msgid "Wizard" msgstr "Procedura guidata" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:422 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:414 msgid "World" msgstr "" @@ -1265,6 +1521,7 @@ msgid "You" msgstr "Ti" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:934 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:918 msgid "You can enable MPTCP over VPN if your provider filter Multipath TCP." msgstr "Puoi abilitare MPTCP su VPN se il tuo provider filtra Multipath TCP." @@ -1275,28 +1532,33 @@ msgid "" msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:467 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:459 msgid "You can use DHCP if you have multiple real ethernet ports." msgstr "Puoi usare DHCP se hai più porte ethernet reali." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:617 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:609 msgid "" "You can use DHCP if you have multiple real ethernet ports. Select other if " "you want to use another protocol available in Network Interfaces page." msgstr "Puoi usare DHCP se hai una WAN per ogni interfaccia." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:212 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:204 msgid "You can use a public IPv6 prefix only if you set only one server." msgstr "" "È possibile utilizzare un prefisso IPv6 pubblico solo se si imposta un solo " "server." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:538 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:530 msgid "You must disable DHCP on your modems and set IP in different networks." msgstr "" "È necessario disabilitare il DHCP sui modem e impostare l'IP in reti " "diverse." #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:202 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:194 msgid "You should disable IPv6 here if server doesn't provide IPv6." msgstr "Dovresti disabilitare IPv6 qui se il server non fornisce IPv6." @@ -1313,6 +1575,7 @@ msgid "address:" msgstr "Indirizzo:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:835 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:830 msgid "auto" msgstr "Auto" @@ -1321,44 +1584,57 @@ msgid "empty key" msgstr "chiave vuota" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:506 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:504 #, fuzzy msgid "interface:" msgstr "Aggiungi un'interfaccia" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:490 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:739 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:488 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:737 msgid "ip address:" msgstr "Indirizzo IP:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:494 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:492 #, fuzzy msgid "ipv6 address:" msgstr "Indirizzo IP:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:518 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:751 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:516 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:749 msgid "latency:" msgstr "latenza:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:522 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:755 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:520 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:753 msgid "mtu:" msgstr "mtu:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:646 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:808 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:644 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:806 msgid "multipath:" msgstr "multipath:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:526 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:524 msgid "operator:" msgstr "operatore:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:277 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:269 msgid "other" msgstr "Altro" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:530 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:528 msgid "phone number:" msgstr "numero di telefono:" @@ -1367,20 +1643,26 @@ msgid "range:" msgstr "intervallo:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:534 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:532 msgid "state:" msgstr "stato:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:649 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:811 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:647 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:809 msgid "traffic control:" msgstr "controllo del traffico:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:498 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:743 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:496 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:741 msgid "wan address:" msgstr "indirizzo wan:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:502 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:500 #, fuzzy msgid "wan ipv6 address:" msgstr "indirizzo wan:" @@ -1388,14 +1670,21 @@ msgstr "indirizzo wan:" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:510 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:514 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:747 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:508 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:512 +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm:745 msgid "whois:" msgstr "whois:" -#~ msgid "" -#~ "You should disable SQM for LTE or any interfaces with variable speed." -#~ msgstr "" -#~ "È necessario disabilitare SQM per LTE o qualsiasi interfaccia con " -#~ "velocità variabile." +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:928 +msgid "You should disable SQM for LTE or any interfaces with variable speed." +msgstr "" +"È necessario disabilitare SQM per LTE o qualsiasi interfaccia con velocità " +"variabile." + +#: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:253 +msgid "Disable HTTP test on Server API in status page" +msgstr "Disabilitare il test HTTP sulle API Server nella pagina di stato" #~ msgid "Common server settings" #~ msgstr "Impostazioni comuni del server" diff --git a/luci-app-openmptcprouter/po/oc/openmptcprouter.po b/luci-app-openmptcprouter/po/oc/openmptcprouter.po index 7e0121569..f2f82cd0d 100644 --- a/luci-app-openmptcprouter/po/oc/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/oc/openmptcprouter.po @@ -269,7 +269,6 @@ msgstr "" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:347 #, fuzzy -#| msgid "Disabled" msgid "Disable nDPI" msgstr "Desactivat" @@ -364,7 +363,6 @@ msgstr "Active SQM" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 #, fuzzy -#| msgid "Enable SQM" msgid "Enable SQM autorate" msgstr "Active SQM" @@ -1432,3 +1430,7 @@ msgstr "" #~ msgid "Redundant" #~ msgstr "Redondant" + +#, fuzzy +#~ msgid "Disable HTTP test on Server API in status page" +#~ msgstr "Desactivar la pròva ping cap al servidor" diff --git a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po index 743382b02..f06ba0249 100644 --- a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po +++ b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po @@ -211,7 +211,6 @@ msgstr "设备" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:259 #, fuzzy -#| msgid "Disable HTTP test on Server API in status page" msgid "Disable HTTP test on Server API" msgstr "在状态页面中禁用服务器API上的HTTP测试" @@ -343,7 +342,6 @@ msgstr "开启 SQM" #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm:952 #, fuzzy -#| msgid "Enable SQM" msgid "Enable SQM autorate" msgstr "开启 SQM" @@ -1195,7 +1193,6 @@ msgstr "启用后,将在外部站点上进行检查,以获取每个WAN IP和 #: luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm:301 #, fuzzy -#| msgid "When proxy shadowsocks is used, use it for UDP if VPN down" msgid "When proxy V2Ray is used, use it for UDP" msgstr "当使用代理shadowsocks时,如果VPN关闭,将其用于UDP" @@ -1490,3 +1487,6 @@ msgstr "whois查询 :" #~ msgid "MLVPN can replace Glorytun with connection with same latency" #~ msgstr "" #~ "MLVPN peut remplacer Glorytun pour les connexions avec la même latence" + +#~ msgid "Disable HTTP test on Server API in status page" +#~ msgstr "在状态页面中禁用服务器API上的HTTP测试" From 7289c40028671455d8d939fd3a9e1e69e57caff3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Aug 2022 20:03:39 +0200 Subject: [PATCH 0831/2059] Update RPI EEPROM --- bcm27xx-eeprom/Makefile | 9 ++--- ...date-chmod-silent-f-is-not-supported.patch | 33 +++++++++++++++++++ .../0004-rpi-eeprom-update-remove-chmod.patch | 24 -------------- ...om-config-change-default-text-editor.patch | 22 +++++++++++++ 4 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch delete mode 100644 bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch create mode 100644 bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch diff --git a/bcm27xx-eeprom/Makefile b/bcm27xx-eeprom/Makefile index 1dcf6883b..b114ee11a 100644 --- a/bcm27xx-eeprom/Makefile +++ b/bcm27xx-eeprom/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-eeprom -PKG_VERSION:=47976e4409c6999a8e211976c75c60a97c90275c -PKG_RELEASE:=4 +PKG_VERSION:=v2022.04.26-138a1 +PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/rpi-eeprom/tar.gz/$(PKG_VERSION)? -PKG_HASH:=skip +PKG_HASH:=7c54839e68f226c5853fb63c8a1539b729d84b2e6bac311a51766c601d10a413 PKG_LICENSE:=BSD-3-Clause Custom PKG_LICENSE_FILES:=LICENSE @@ -21,7 +21,7 @@ TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS) define Package/bcm27xx-eeprom SECTION:=utils CATEGORY:=Utilities - DEPENDS:=bcm27xx-userland +blkid +pciutils +python3-light +coreutils +coreutils-od + DEPENDS:=bcm27xx-userland +blkid +coreutils +coreutils-od +pciutils +python3-light TITLE:=BCM27xx EEPROM tools endef @@ -43,6 +43,7 @@ define Package/bcm27xx-eeprom/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-config $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-digest $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-update $(1)/usr/bin $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader diff --git a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch b/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch new file mode 100644 index 000000000..5872f12da --- /dev/null +++ b/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch @@ -0,0 +1,33 @@ +From 8376ac74390af0ad736c88615e128b82a75eebc0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Fri, 19 Feb 2021 10:54:23 +0100 +Subject: [PATCH] rpi-eeprom-update: chmod silent (-f) is not supported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + rpi-eeprom-update | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/rpi-eeprom-update ++++ b/rpi-eeprom-update +@@ -200,7 +200,7 @@ applyRecoveryUpdate() + || die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}" + + # For NFS mounts ensure that the files are readable to the TFTP user +- chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \ ++ chmod go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \ + || die "Failed to set permissions on eeprom update files" + fi + +@@ -211,7 +211,7 @@ applyRecoveryUpdate() + || die "Failed to copy ${VL805_UPDATE_IMAGE} to ${BOOTFS}/vl805.bin" + + # For NFS mounts ensure that the files are readable to the TFTP user +- chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \ ++ chmod go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \ + || die "Failed to set permissions on eeprom update files" + fi + diff --git a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch b/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch deleted file mode 100644 index a79fa89b1..000000000 --- a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-remove-chmod.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/rpi-eeprom-update 2020-11-05 21:58:02.247836497 +0100 -+++ b/rpi-eeprom-update 2020-11-05 21:58:36.911266307 +0100 -@@ -212,8 +212,8 @@ - || die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}" - - # For NFS mounts ensure that the files are readable to the TFTP user -- chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \ -- || die "Failed to set permissions on eeprom update files" -+ #chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \ -+ # || die "Failed to set permissions on eeprom update files" - fi - - if [ -n "${VL805_UPDATE_IMAGE}" ]; then -@@ -224,8 +224,8 @@ - || die "Failed to copy ${VL805_UPDATE_IMAGE} to ${BOOTFS}/vl805.bin" - - # For NFS mounts ensure that the files are readable to the TFTP user -- chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \ -- || die "Failed to set permissions on eeprom update files" -+ #chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \ -+ # || die "Failed to set permissions on eeprom update files" - fi - - cp -f "${RECOVERY_BIN}" "${BOOTFS}/recovery.bin" \ diff --git a/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch b/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch new file mode 100644 index 000000000..6feb7602c --- /dev/null +++ b/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch @@ -0,0 +1,22 @@ +--- a/rpi-eeprom-config ++++ b/rpi-eeprom-config +@@ -166,8 +166,8 @@ def edit_config(eeprom=None): + """ + Implements something like 'git commit' for editing EEPROM configs. + """ +- # Default to nano if $EDITOR is not defined. +- editor = 'nano' ++ # Default to vi if $EDITOR is not defined. ++ editor = 'vi' + if 'EDITOR' in os.environ: + editor = os.environ['EDITOR'] + +@@ -428,7 +428,7 @@ Operating modes: + + To cancel the pending update run 'sudo rpi-eeprom-update -r' + +- The default text editor is nano and may be overridden by setting the 'EDITOR' ++ The default text editor is vi and may be overridden by setting the 'EDITOR' + environment variable and passing '-E' to 'sudo' to preserve the environment. + + 6. Signing the bootloader config file. From 2ba607e34044b019933e16341adc080faf15ce0b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Aug 2022 20:51:53 +0200 Subject: [PATCH 0832/2059] Fix status page proxy check --- luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 8fd59ecb4..32af00eb8 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1037,7 +1037,8 @@ function interfaces_status() mArray.openmptcprouter["shadowsocks_enabled"] = true local ss_server = "1" ucic:foreach("shadowsocks-libev", "server", function(s) - if uci:get("shadowsocks-libev",s[".name"],"disabled") == "0" then + local ss_server_disabled = uci:get("shadowsocks-libev",s[".name"],"disabled") or "0" + if ss_server_disabled == "0" then ss_server = "0" end end) From 3a5fb9a6a50fc0b743cb0ebb492e7fc0b98ad800 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Aug 2022 20:52:21 +0200 Subject: [PATCH 0833/2059] Update CAKE autorate --- .../usr/share/sqm-autorate/CAKE-autorate.sh | 108 +++++++++++++----- 1 file changed, 79 insertions(+), 29 deletions(-) diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh index 4f0504c94..560039b22 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh @@ -19,7 +19,9 @@ cleanup_and_killall() echo "Killing all background processes and cleaning up /tmp files." trap - INT TERM EXIT kill $monitor_achieved_rates_pid 2> /dev/null + # Initiate termination of ping processes and wait until complete kill $maintain_pingers_pid 2> /dev/null + wait $maintain_pingers_pid [[ -d /tmp/CAKE-autorate-${dl_if} ]] && rm -r /tmp/CAKE-autorate-${dl_if} exit } @@ -45,35 +47,42 @@ get_next_shaper_rate() case $load_condition in + # upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period + ul*sss) + shaper_rate_kbps=$min_shaper_rate_kbps + ;; + # download Starlink satelite switching compensation, so drop down to base rate for download through switching period + dl*sss) + shaper_rate_kbps=$base_shaper_rate_kbps + ;; # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period - *delayed) + *bb*) if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then - adjusted_achieved_rate_kbps=$(( ($achieved_rate_kbps*$achieved_rate_adjust_bufferbloat)/1000 )) - adjusted_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_bufferbloat)/1000 )) + adjusted_achieved_rate_kbps=$(( ($achieved_rate_kbps*$achieved_rate_adjust_down_bufferbloat)/1000 )) + adjusted_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_down_bufferbloat)/1000 )) shaper_rate_kbps=$(( $adjusted_achieved_rate_kbps < $adjusted_shaper_rate_kbps ? $adjusted_achieved_rate_kbps : $adjusted_shaper_rate_kbps )) t_last_bufferbloat_us=${EPOCHREALTIME/./} fi ;; - # high load, so increase rate providing not inside bufferbloat refractory period - high) + *high*) if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then - shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_load_high)/1000 )) + shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_up_load_high)/1000 )) fi ;; # medium load, so just maintain rate as is, i.e. do nothing - medium) + *med*) : ;; # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate - low|idle) + *low*|*idle*) if (($t_next_rate_us > ($t_last_decay_us+$decay_refractory_period_us) )); then if (($shaper_rate_kbps > $base_shaper_rate_kbps)); then - decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_load_low)/1000 )) + decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_down_load_low)/1000 )) shaper_rate_kbps=$(( $decayed_shaper_rate_kbps > $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps)) elif (($shaper_rate_kbps < $base_shaper_rate_kbps)); then - decayed_shaper_rate_kbps=$(( ((2000-$shaper_rate_adjust_load_low)*$shaper_rate_kbps)/1000 )) + decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_up_load_low)/1000 )) shaper_rate_kbps=$(( $decayed_shaper_rate_kbps < $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps)) fi @@ -118,11 +127,11 @@ monitor_achieved_rates() printf '%s' "$dl_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps printf '%s' "$ul_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps - prev_rx_bytes=$rx_bytes - prev_tx_bytes=$tx_bytes + prev_rx_bytes=$rx_bytes + prev_tx_bytes=$tx_bytes # read in the max_wire_packet_rtt_us - concurrent_read max_wire_packet_rtt_us /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us + concurrent_read_positive_integer max_wire_packet_rtt_us /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us compensated_monitor_achieved_rates_interval_us=$(( (($monitor_achieved_rates_interval_us>(10*$max_wire_packet_rtt_us) )) ? $monitor_achieved_rates_interval_us : $((10*$max_wire_packet_rtt_us)) )) @@ -134,8 +143,8 @@ get_loads() { # read in the dl/ul achived rates and determine the loads - concurrent_read dl_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps - concurrent_read ul_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps + concurrent_read_positive_integer dl_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps + concurrent_read_positive_integer ul_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps dl_load_percent=$(((100*10#${dl_achieved_rate_kbps})/$dl_shaper_rate_kbps)) ul_load_percent=$(((100*10#${ul_achieved_rate_kbps})/$ul_shaper_rate_kbps)) @@ -152,14 +161,25 @@ classify_load() if (( $load_percent > $high_load_thr_percent )); then load_condition="high" elif (( $load_percent > $medium_load_thr_percent )); then - load_condition="medium" + load_condition="med" elif (( $achieved_rate_kbps > $connection_active_thr_kbps )); then load_condition="low" else load_condition="idle" fi - (($bufferbloat_detected)) && load_condition=$load_condition"_delayed" + (($bufferbloat_detected)) && load_condition=$load_condition"_bb" + + if ((sss_compensation)); then + for sss_time_us in "${sss_times_us[@]}" + do + ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) + if (( ($timestamp_usecs_past_minute > ($sss_time_us-$sss_compensation_pre_duration_us)) && ($timestamp_usecs_past_minute < ($sss_time_us+$sss_compensation_post_duration_us)) )); then + load_condition=$load_condition"_sss" + break + fi + done + fi } monitor_reflector_responses() @@ -245,7 +265,7 @@ maintain_pingers() for ((pinger=0; pinger<$no_pingers; pinger++)) do reflector_check_time_us=${EPOCHREALTIME/./} - concurrent_read reflector_last_timestamp_us /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us + concurrent_read_positive_integer reflector_last_timestamp_us /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us declare -n reflector_offences="reflector_${pinger}_offences" (( ${reflector_offences[$reflector_offences_idx]} )) && ((sum_reflector_offences[$pinger]--)) @@ -367,7 +387,7 @@ update_max_wire_packet_compensation() printf '%s' "$max_wire_packet_rtt_us" > /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us } -concurrent_read() +concurrent_read_positive_integer() { # in the context of separate processes writing using > and reading form file # it seems costly calls to the external flock binary can be avoided @@ -376,10 +396,20 @@ concurrent_read() local -n value=$1 local path=$2 - read -r value < $path - while [[ -z $value ]]; do - sleep_us $concurrent_read_interval_us + while true + do read -r value < $path; + if [[ -z "${value##*[!0-9]*}" ]]; then + if (($debug)); then + read -r caller_output< <(caller) + echo "DEBUG concurrent_read_positive_integer() misfire with the following particulars:" + echo "DEBUG caller="$caller_output"; value="$value"; and path="$path + fi + sleep_us $concurrent_read_positive_integer_interval_us + continue + else + break + fi done } @@ -474,10 +504,11 @@ verify_ifs_up # Convert human readable parameters to values that work with integer arithmetic printf -v alpha_baseline_increase %.0f\\n "${alpha_baseline_increase}e3" printf -v alpha_baseline_decrease %.0f\\n "${alpha_baseline_decrease}e3" -printf -v achieved_rate_adjust_bufferbloat %.0f\\n "${achieved_rate_adjust_bufferbloat}e3" -printf -v shaper_rate_adjust_bufferbloat %.0f\\n "${shaper_rate_adjust_bufferbloat}e3" -printf -v shaper_rate_adjust_load_high %.0f\\n "${shaper_rate_adjust_load_high}e3" -printf -v shaper_rate_adjust_load_low %.0f\\n "${shaper_rate_adjust_load_low}e3" +printf -v achieved_rate_adjust_down_bufferbloat %.0f\\n "${achieved_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_down_bufferbloat %.0f\\n "${shaper_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_up_load_high %.0f\\n "${shaper_rate_adjust_up_load_high}e3" +printf -v shaper_rate_adjust_down_load_low %.0f\\n "${shaper_rate_adjust_down_load_low}e3" +printf -v shaper_rate_adjust_up_load_low %.0f\\n "${shaper_rate_adjust_up_load_low}e3" printf -v high_load_thr_percent %.0f\\n "${high_load_thr}e2" printf -v medium_load_thr_percent %.0f\\n "${medium_load_thr}e2" printf -v reflector_ping_interval_us %.0f\\n "${reflector_ping_interval_s}e6" @@ -488,9 +519,16 @@ bufferbloat_refractory_period_us=$(( 1000*$bufferbloat_refractory_period_ms )) decay_refractory_period_us=$(( 1000*$decay_refractory_period_ms )) delay_thr_us=$(( 1000*$delay_thr_ms )) +for (( i=0; i<${#sss_times_s[@]}; i++ )); +do + printf -v sss_times_us[i] %.0f\\n "${sss_times_s[i]}e6" +done +printf -v sss_compensation_pre_duration_us %.0f\\n "${sss_compensation_pre_duration_ms}e3" +printf -v sss_compensation_post_duration_us %.0f\\n "${sss_compensation_post_duration_ms}e3" + ping_response_interval_us=$(($reflector_ping_interval_us/$no_pingers)) -concurrent_read_interval_us=$(($ping_response_interval_us/4)) +concurrent_read_positive_integer_interval_us=$(($ping_response_interval_us/4)) dl_shaper_rate_kbps=$base_dl_shaper_rate_kbps ul_shaper_rate_kbps=$base_ul_shaper_rate_kbps @@ -533,12 +571,20 @@ monitor_achieved_rates_pid=$! prev_timestamp=0 +if (($debug)); then + if (( $bufferbloat_refractory_period_us <= ($bufferbloat_detection_window*$ping_response_interval_us) )); then + echo "DEBUG Warning: bufferbloat refractory period: " $bufferbloat_refractory_period_us " us." + echo "DEBUG Warning: but expected time to overwrite samples in bufferbloat detection window is: " $(($bufferbloat_detection_window*$ping_response_interval_us)) " us." + echo "DEBUG Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." + fi +fi + while true do while read -t $global_ping_response_timeout_s -r timestamp reflector seq rtt_baseline_us rtt_us rtt_delta_us do t_start_us=${EPOCHREALTIME/./} - if ((($t_start_us - "${timestamp//[[\[\].]}")>500000)); then + if ((($t_start_us - 10#"${timestamp//[[\[\].]}")>500000)); then (($debug)) && echo "DEBUG processed response from [" $reflector "] that is > 500ms old. Skipping." continue fi @@ -556,6 +602,9 @@ do classify_load $dl_load_percent $dl_achieved_rate_kbps dl_load_condition classify_load $ul_load_percent $ul_achieved_rate_kbps ul_load_condition + dl_load_condition="dl_"$dl_load_condition + ul_load_condition="ul_"$ul_load_condition + get_next_shaper_rate $min_dl_shaper_rate_kbps $base_dl_shaper_rate_kbps $max_dl_shaper_rate_kbps $dl_achieved_rate_kbps $dl_load_condition $t_start_us t_dl_last_bufferbloat_us t_dl_last_decay_us dl_shaper_rate_kbps get_next_shaper_rate $min_ul_shaper_rate_kbps $base_ul_shaper_rate_kbps $max_ul_shaper_rate_kbps $ul_achieved_rate_kbps $ul_load_condition $t_start_us t_ul_last_bufferbloat_us t_ul_last_decay_us ul_shaper_rate_kbps @@ -584,8 +633,9 @@ do ul_shaper_rate_kbps=$min_ul_shaper_rate_kbps set_shaper_rates - # Kill off ping processes + # Initiate termination of ping processes and wait until complete kill $maintain_pingers_pid 2> /dev/null + wait $maintain_pingers_pid # reset idle timer t_sustained_connection_idle_us=0 From d5bdf2f3c5add4767af364845120cc59f926208a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Aug 2022 18:44:45 +0200 Subject: [PATCH 0834/2059] Fix ndpi support --- .../resources/view/services/omr-bypass.js | 3 +++ luci-app-omr-bypass/root/etc/init.d/omr-bypass | 13 ++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js index 361d203db..3119d93f0 100644 --- a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js +++ b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js @@ -223,6 +223,9 @@ return L.view.extend({ o.noinactive = true; o.nocreate = true; + o = s.option(form.Flag, 'ndpi', _('Enable ndpi')); + o.default = o.enabled; + o = s.option(form.Value, 'note', _('Note')); o.rmempty = true; diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 6b278ab43..69207c71b 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -341,6 +341,7 @@ _bypass_proto() { config_get proto $1 proto config_get intf $1 interface config_get enabled $1 enabled + config_get ndpi $1 ndpi [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return @@ -348,7 +349,7 @@ _bypass_proto() { [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return - if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ]; then + if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ] && [ "$ndpi" != "0" ]; then if [ "$intf" = "all" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *mangle @@ -802,9 +803,8 @@ start_service() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass-dpi - - -A PREROUTING -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi - -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi - -A POSTROUTING -m addrtype --dst-type LOCAL -j omr-bypass-dpi + -A INPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi + -A FORWARD -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi COMMIT EOF if [ "$disableipv6" = "0" ]; then @@ -812,9 +812,8 @@ start_service() { ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass6-dpi - - -A PREROUTING -m addrtype ! --dst-type LOCAL -j omr-bypass6-dpi - -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass6-dpi - -A POSTROUTING -m addrtype --dst-type LOCAL -j omr-bypass6-dpi + -A INPUT -m addrtype ! --dst-type LOCAL -j omr-bypass6-dpi + -A FORWARD -m addrtype ! --dst-type LOCAL -j omr-bypass6-dpi COMMIT EOF fi From e162e006385e12e7c807f85a570acb02fb9f64b7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Aug 2022 21:55:15 +0200 Subject: [PATCH 0835/2059] Launch omr-bypass only if not launching --- luci-app-omr-bypass/root/etc/firewall.omr-bypass | 2 +- shadowsocks-libev/files/shadowsocks-libev.init | 2 +- v2ray-core/files/etc/init.d/v2ray | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/firewall.omr-bypass b/luci-app-omr-bypass/root/etc/firewall.omr-bypass index fe65adb2f..7efffb894 100644 --- a/luci-app-omr-bypass/root/etc/firewall.omr-bypass +++ b/luci-app-omr-bypass/root/etc/firewall.omr-bypass @@ -1,2 +1,2 @@ #!/bin/sh -/etc/init.d/omr-bypass reload_rules +[ -z "$(pgrep -f omr-bypass)" ] && /etc/init.d/omr-bypass reload_rules diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 9868e9044..427a56682 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -356,7 +356,7 @@ rules_up() { done config_foreach ss_rules ss_rules [ -z "$(iptables-save | grep :ssr)" ] && logger -t "Shadowsocks" "Rules not applied" - [ -f /etc/init.d/omr-bypass ] && { + [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { logger -t "Shadowsocks" "Reload omr-bypass rules" /etc/init.d/omr-bypass reload_rules } diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index 284a8a761..ffe8d1db4 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -424,7 +424,7 @@ add_v2ray_redirect_rules() { [ "$(uci -q get v2ray.main_transparent_proxy.redirect_udp)" = "1" ] && commandline="$commandline -L ${port+1}" v2ray-rules6 $commandline } - [ -f /etc/init.d/omr-bypass ] && { + [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { logger -t "v2ray" "Reload omr-bypass rules" /etc/init.d/omr-bypass reload_rules } @@ -2106,7 +2106,7 @@ rules_up() { logger -t "v2ray" "Rules UP" add_v2ray_redirect_rules } - [ -f /etc/init.d/omr-bypass ] && { + [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { logger -t "v2ray" "Reload omr-bypass rules" /etc/init.d/omr-bypass reload_rules } From 9952f3d416ee75c632f3ca7778d7c319c175590d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 22 Aug 2022 12:54:25 +0200 Subject: [PATCH 0836/2059] Fix for MPTCP over VPN --- openmptcprouter/files/etc/init.d/mptcpovervpn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index da3550df0..24540feb0 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -298,7 +298,7 @@ start_service() uci -q batch <<-EOF >/dev/null commit shadowsocks-libev EOF - /etc/init.d/shadowsocks restart + /etc/init.d/shadowsocks-libev restart /etc/init.d/openvpn restart elif [ "$(uci -q get shadowsocks-libev.hivpn1)" != "" ]; then for c in $(seq 1 $NBCPU); do From 4804253d45e556ff563bbbb4a7a3c66119aee12f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 22 Aug 2022 13:37:05 +0200 Subject: [PATCH 0837/2059] Fix MPTCP over VPN --- openmptcprouter/files/etc/init.d/mptcpovervpn | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index 24540feb0..8595b5f4f 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -250,7 +250,7 @@ start_service() fi elif ([ "$(uci -q get glorytun.vpn.host)" = "10.255.250.1" ] || [ "$(uci -q get glorytun.vpn.host)" = "10.255.247.1" ]) && [ "$nbintf" != "$nbintfvpn" ]; then uci -q batch <<-EOF >/dev/null - delete shadowsocks-libev.sss0.disabled + set shadowsocks-libev.sss0.disabled='0' set glorytun.vpn.host="$(uci -q get openmptcprouter.vps.ip | awk '{print $1}')" set glorytun-udp.vpn.host="$(uci -q get openmptcprouter.vps.ip | awk '{print $1}')" commit glorytun @@ -266,7 +266,7 @@ start_service() set shadowsocks-libev.mptcpovervpn.key="$(uci -q get shadowsocks-libev.sss0.key)" set shadowsocks-libev.mptcpovervpn.method="$(uci -q get shadowsocks-libev.sss0.method)" set shadowsocks-libev.mptcpovervpn.server="10.255.250.1" - delete shadowsocks-libev.mptcpovervpn.disabled + set shadowsocks-libev.mptcpovervpn.disabled='0' EOF else uci -q batch <<-EOF >/dev/null @@ -275,7 +275,7 @@ start_service() set shadowsocks-libev.mptcpovervpn.key="$(uci -q get shadowsocks-libev.sss0.key)" set shadowsocks-libev.mptcpovervpn.method="$(uci -q get shadowsocks-libev.sss0.method)" set shadowsocks-libev.mptcpovervpn.server="10.255.247.1" - delete shadowsocks-libev.mptcpovervpn.disabled + set shadowsocks-libev.mptcpovervpn.disabled='0' EOF fi for c in $(seq 1 $NBCPU); do @@ -307,7 +307,7 @@ start_service() EOF done uci -q batch <<-EOF >/dev/null - delete shadowsocks-libev.sss0.disabled + set shadowsocks-libev.sss0.disabled='0' EOF uci -q batch <<-EOF >/dev/null delete shadowsocks-libev.mptcpovervpn From 4e3e03fa43bd2c7416cf93b5b32b9c73207cf763 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 22 Aug 2022 18:42:33 +0200 Subject: [PATCH 0838/2059] Fix MPTCP over VPN --- openmptcprouter/files/etc/init.d/mptcpovervpn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index 8595b5f4f..500acdc12 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -248,9 +248,11 @@ start_service() commit glorytun-udp EOF fi + uci -q set shadowsocks-libev.ss_rules.server='mptcpovervpn' elif ([ "$(uci -q get glorytun.vpn.host)" = "10.255.250.1" ] || [ "$(uci -q get glorytun.vpn.host)" = "10.255.247.1" ]) && [ "$nbintf" != "$nbintfvpn" ]; then uci -q batch <<-EOF >/dev/null set shadowsocks-libev.sss0.disabled='0' + set shadowsocks-libev.ss_rules.server='sss0' set glorytun.vpn.host="$(uci -q get openmptcprouter.vps.ip | awk '{print $1}')" set glorytun-udp.vpn.host="$(uci -q get openmptcprouter.vps.ip | awk '{print $1}')" commit glorytun @@ -310,6 +312,7 @@ start_service() set shadowsocks-libev.sss0.disabled='0' EOF uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.ss_rules.server='sss0' delete shadowsocks-libev.mptcpovervpn commit shadowsocks-libev EOF From 91811b555a9872c17dedf831bb1573bf531626c2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 22 Aug 2022 20:50:19 +0200 Subject: [PATCH 0839/2059] More MPTCP over VPN fixes --- openmptcprouter/files/etc/init.d/mptcpovervpn | 7 +++++-- shadowsocks-libev/files/shadowsocks-libev.init | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index 500acdc12..f192c51fa 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -248,8 +248,11 @@ start_service() commit glorytun-udp EOF fi - uci -q set shadowsocks-libev.ss_rules.server='mptcpovervpn' - elif ([ "$(uci -q get glorytun.vpn.host)" = "10.255.250.1" ] || [ "$(uci -q get glorytun.vpn.host)" = "10.255.247.1" ]) && [ "$nbintf" != "$nbintfvpn" ]; then + uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.ss_rules.server='mptcpovervpn' + set shadowsocks-libev.ss_rules.redir_tcp='all' + EOF + elif ([ "$(uci -q get glorytun.vpn.host)" = "10.255.250.1" ] || [ "$(uci -q get glorytun.vpn.host)" = "10.255.247.1" ] || [ "$(uci -q get shadowsocks-libev.ss_rules.server)" != "sss0" ]) && [ "$nbintf" != "$nbintfvpn" ]; then uci -q batch <<-EOF >/dev/null set shadowsocks-libev.sss0.disabled='0' set shadowsocks-libev.ss_rules.server='sss0' diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 427a56682..c93f03a3e 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -186,7 +186,8 @@ ss_rules() { eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)" validate_ss_rules_section "$cfg" || return 1 - [ "$disabled" = 0 ] || return 0 + [ "$disabled" != "1" ] || return 0 + [ "$(uci -q get shadowsocks-libev.${cfgrulesserver}.disabled)" != "1" ] || return 0 if [ "$ss_rules_redir_tcp_$redir_tcp" = "all" ]; then min_ss_redir_ports="65535" max_ss_redir_ports="0" From addb792bedbbee087a3ba546a5e053356e41b55b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Aug 2022 20:50:28 +0200 Subject: [PATCH 0840/2059] Workaround for Glorytun UDP when hostname used for server --- glorytun-udp/init | 2 ++ .../usr/share/omr/post-tracking.d/post-tracking | 14 ++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/glorytun-udp/init b/glorytun-udp/init index f5086024f..6b5522129 100755 --- a/glorytun-udp/init +++ b/glorytun-udp/init @@ -56,6 +56,8 @@ start_instance() { _log "starting ${PROG_NAME} ${1} instance $*" + host=$(resolveip $host) + if [ "$mode" = "to" ]; then bind="bind from addr :: port 5000 to addr $host port $port" else diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 2a511e6cd..5b723e4fd 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -644,7 +644,7 @@ del_server_route6() { else metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) fi - [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip"] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 } config_list_foreach $server ip remove_route @@ -1218,8 +1218,9 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$mul serverip=$1 #gtudpst="up" #[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" - if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP | grep running)" = "" ] && [ -n "$(resolveip -4 $serverip)" ]; then - if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then + if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP | grep running)" = "" ] && [ -n "$(resolveip -4 -t 5 $serverip)" ]; then + serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" + if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 else @@ -1233,7 +1234,8 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$mul fi fi fi - if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6 | grep running)" = "" ] && [ -n "$(resolveip -6 $serverip)" ]; then + if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6 | grep running)" = "" ] && [ -n "$(resolveip -6 -t 5 $serverip)" ]; then + serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 @@ -1252,8 +1254,8 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$mul # glorytun-udp set dev tun0 kxtimeout 7d > /dev/null 2>&1 # fi [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && { - [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$(resolveip -4 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 - [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$(resolveip -6 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$(resolveip -4 -t 5 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$(resolveip -6 -t 5 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 } } config_list_foreach $1 ip addpath From a054179ac770bfcbecbf9e1532a1685ec0617bc5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Aug 2022 20:51:32 +0200 Subject: [PATCH 0841/2059] Fix wizard when LAN interface set outside wizard --- .../luasrc/view/openmptcprouter/wizard.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 58a08e11b..8961bfa4e 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -514,13 +514,13 @@ <% end %> -
    +
    " data-type="ip4addr">
    -
    +
    " data-type="ip4addr"> From fad135665cd0766ff6c50fbd1fa245d5db584c64 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 25 Aug 2022 13:59:44 +0200 Subject: [PATCH 0842/2059] Fix omr-bypass --- .../root/etc/init.d/omr-bypass | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 69207c71b..6c349317d 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -354,12 +354,14 @@ _bypass_proto() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 + -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN COMMIT EOF if [ "$disableipv6" = "0" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN COMMIT EOF fi @@ -367,12 +369,14 @@ _bypass_proto() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid + -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN COMMIT EOF if [ "$disableipv6" = "0" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN COMMIT EOF fi @@ -725,13 +729,13 @@ start_service() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass - - -I PREROUTING -m addrtype ! --dst-type LOCAL -j omr-bypass + -A PREROUTING -j omr-bypass COMMIT EOF iptables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass-local - - -I OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-local + -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-local COMMIT EOF if [ "$disableipv6" = "0" ]; then @@ -739,7 +743,7 @@ start_service() { ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass6 - - -I PREROUTING -m addrtype ! --dst-type LOCAL -j omr-bypass6 + -A PREROUTING -j omr-bypass6 COMMIT EOF fi @@ -786,11 +790,13 @@ start_service() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass -m mark --mark 0x539 -j RETURN COMMIT EOF iptables-restore -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass-local -m mark --mark 0x539 -j RETURN COMMIT EOF fi @@ -803,8 +809,8 @@ start_service() { iptables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass-dpi - - -A INPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi - -A FORWARD -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi + -A INPUT -j omr-bypass-dpi + -A FORWARD -j omr-bypass-dpi COMMIT EOF if [ "$disableipv6" = "0" ]; then @@ -812,8 +818,8 @@ start_service() { ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass6-dpi - - -A INPUT -m addrtype ! --dst-type LOCAL -j omr-bypass6-dpi - -A FORWARD -m addrtype ! --dst-type LOCAL -j omr-bypass6-dpi + -A INPUT -j omr-bypass6-dpi + -A FORWARD -j omr-bypass6-dpi COMMIT EOF fi From ed7d5abfdf23dfdd5203dc16384fb505ffb3c5bc Mon Sep 17 00:00:00 2001 From: ta264 Date: Fri, 26 Aug 2022 07:19:09 +0100 Subject: [PATCH 0843/2059] Fix omr rename (#115) * Fix omr-rename * Sign CLA --- contributors/ta264.md | 9 +++++++++ .../root/etc/hotplug.d/net/99-omr-rename | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 contributors/ta264.md diff --git a/contributors/ta264.md b/contributors/ta264.md new file mode 100644 index 000000000..06ed382e6 --- /dev/null +++ b/contributors/ta264.md @@ -0,0 +1,9 @@ +2022-08-26 + +I hereby agree to the terms of the "OpenMPTCProuter Individual Contributor License Agreement", with MD5 checksum bc827a07eb93611d793ddb7c75083c00. + +I furthermore declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +ta264 https://github.com/ta264 diff --git a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename index 4ff952d0e..eb4521f11 100755 --- a/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename +++ b/luci-app-openmptcprouter/root/etc/hotplug.d/net/99-omr-rename @@ -39,7 +39,7 @@ _set_intf_name() { } ip link set ${INTERFACE} name ${ifname} 2>&1 >/dev/null ip link set ${ifname} up 2>&1 >/dev/null - [ "$existif" = "1" ] && ip link set ${ifname}tmp ${INTERFACE} 2>&1 >/dev/null + [ "$existif" = "1" ] && ip link set ${ifname}tmp name ${INTERFACE} 2>&1 >/dev/null fi fi elif [ -f /dev/${DEVICE_NAME} ] && [ -n "$MODALIAS" ] && [ "$modalias" = "$MODALIAS" ]; then @@ -68,4 +68,4 @@ if [ "$(uci -q get openmptcprouter.settings.disableintfrename)" != "1" ]; then config_load network config_foreach _set_intf_name interface # config_foreach _set_intf_name interface -fi \ No newline at end of file +fi From 002387972493424341efdff24cf7eb5d77b20433 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 27 Aug 2022 07:50:12 +0200 Subject: [PATCH 0844/2059] Fix SIP ALG --- .../root/etc/init.d/openmptcprouter | 20 +++++++++++++++++++ .../files/etc/uci-defaults/1980-omr-firewall | 7 ++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 9954d850a..8c75d0366 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -181,6 +181,26 @@ start_service() { rmmod fast_classifier 2>&1 >/dev/null fi + if [ "$(uci -q get openmptcprouter.settings.sipalg)" = "0" ]; then + uci -q batch <<-EOF >/dev/null + set firewall.zone_lan.auto_helper='0' + set firewall.zone_wan.auto_helper='0' + set firewall.zone_vpn.auto_helper='0' + commit firewall + EOF + rmmod nf_nat_sip 2>&1 >/dev/null + rmmod nf_conntrack_sip 2>&1 >/dev/null + else + uci -q batch <<-EOF >/dev/null + set firewall.zone_lan.auto_helper='1' + set firewall.zone_wan.auto_helper='1' + set firewall.zone_vpn.auto_helper='1' + commit firewall + EOF + modprobe nf_conntrack_sip 2>&1 >/dev/null + modprobe nf_nat_sip 2>&1 >/dev/null + fi + if [ "$(uci -q get rpcd.@rpcd[0].socket)" != "/var/run/ubus/ubus.sock" ]; then uci -q batch <<-EOF >/dev/null set rpcd.@rpcd[0].socket='/var/run/ubus/ubus.sock' diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index b4493bb18..c736e2b87 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -242,7 +242,12 @@ uci -q batch <<-EOF >/dev/null set firewall.@include[0].reload='1' commit firewall EOF -if [ "$(uci -q get openmptcprouter.settings.sipalg)" != "1" ]; then +if [ "$(uci -q get openmptcprouter.settings.sipalg)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set openmptcprouter.settings.sipalg='1' + EOF +fi +if [ "$(uci -q get openmptcprouter.settings.sipalg)" = "0" ]; then uci -q batch <<-EOF >/dev/null set firewall.zone_lan.auto_helper='0' set firewall.zone_wan.auto_helper='0' From 58c4f6cb28fa96232af8026b028c853645eef284 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 29 Aug 2022 20:08:59 +0200 Subject: [PATCH 0845/2059] Small SIP ALG fixes --- .../luasrc/controller/openmptcprouter.lua | 10 ---------- .../root/etc/init.d/openmptcprouter | 4 ++-- .../files/etc/uci-defaults/1980-omr-firewall | 1 + 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index ce5edb130..00c421517 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1233,16 +1233,6 @@ function settings_add() -- Enable/disable SIP ALG local sipalg = luci.http.formvalue("sipalg") or "0" ucic:set("openmptcprouter","settings","sipalg",sipalg) - ucic:foreach("firewall", "zone", function (section) - ucic:set("firewall",section[".name"],"auto_helper",sipalg) - end) - if sipalg == "1" then - luci.sys.call("modprobe -q nf_conntrack_sip >/dev/null 2>/dev/null") - luci.sys.call("modprobe -q nf_nat_sip >/dev/null 2>/dev/null") - else - luci.sys.call("rmmod nf_nat_sip >/dev/null 2>/dev/null") - luci.sys.call("rmmod nf_conntrack_sip >/dev/null 2>/dev/null") - end ucic:save("openmptcprouter") ucic:commit("openmptcprouter") diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 8c75d0366..6a667e263 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -197,8 +197,8 @@ start_service() { set firewall.zone_vpn.auto_helper='1' commit firewall EOF - modprobe nf_conntrack_sip 2>&1 >/dev/null - modprobe nf_nat_sip 2>&1 >/dev/null + modprobe -q nf_conntrack_sip 2>&1 >/dev/null + modprobe -q nf_nat_sip 2>&1 >/dev/null fi if [ "$(uci -q get rpcd.@rpcd[0].socket)" != "/var/run/ubus/ubus.sock" ]; then diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index c736e2b87..afde68d82 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -245,6 +245,7 @@ EOF if [ "$(uci -q get openmptcprouter.settings.sipalg)" = "" ]; then uci -q batch <<-EOF >/dev/null set openmptcprouter.settings.sipalg='1' + commit openmptcprouter EOF fi if [ "$(uci -q get openmptcprouter.settings.sipalg)" = "0" ]; then From d7c59fffae17441f32cb6e9724972b1df9ef6cbb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 30 Aug 2022 21:01:54 +0200 Subject: [PATCH 0846/2059] Fix release on upgrade, header and status page --- .../root/www/luci-static/resources/sysupgrade.js | 2 +- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js index 5750ad0b5..64c751dda 100644 --- a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js +++ b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js @@ -159,7 +159,7 @@ function set_status(type, message, loading, show_log) { function upgrade_check() { var current_version = data.release.version.toLowerCase(); - var current_branch = current_version.split('.').slice(0, 2).join('.') + var current_branch = current_version.split('-')[0].split('.').slice(0, 2).join('.') var candidates = [] hide("#status_box"); hide("#server_div"); diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 5b723e4fd..7500e76c1 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1322,7 +1322,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC local latestversions="$(curl -4 -s -m 3 https://www.openmptcprouter.com/version/version.json)" [ -n "$latestversions" ] && { uci -q set openmptcprouter.latest_versions=latest_versions - uci -q set openmptcprouter.latest_versions.omr=$(echo $latestversions | jsonfilter -q -e '@.omr') + uci -q set openmptcprouter.latest_versions.omr=$(echo $latestversions | jsonfilter -q -e '@.omr')-$(ubus call system board | jsonfilter -e '@.kernel' | cut -d'.' -f1,2) uci -q set openmptcprouter.latest_versions.vps=$(echo $latestversions | jsonfilter -q -e '@.vps') uci -q set openmptcprouter.latest_versions.lc=$(date +"%s") } From 70571e546bfd47f04e0b75b7d603a67cdf1a9244 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 30 Aug 2022 21:02:19 +0200 Subject: [PATCH 0847/2059] add a sleep between rmmod for sip alg --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 6a667e263..189f2669b 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -189,6 +189,7 @@ start_service() { commit firewall EOF rmmod nf_nat_sip 2>&1 >/dev/null + sleep 2 rmmod nf_conntrack_sip 2>&1 >/dev/null else uci -q batch <<-EOF >/dev/null @@ -198,6 +199,7 @@ start_service() { commit firewall EOF modprobe -q nf_conntrack_sip 2>&1 >/dev/null + sleep 2 modprobe -q nf_nat_sip 2>&1 >/dev/null fi From 218fb8a6e5165f8016b24a8e9fbf2300579e74d2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 12 Sep 2022 19:55:17 +0200 Subject: [PATCH 0848/2059] Various small fixes --- luci-app-mptcp/luasrc/view/mptcp/multipath.htm | 1 + .../luasrc/controller/openmptcprouter.lua | 6 ++++-- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/luci-app-mptcp/luasrc/view/mptcp/multipath.htm b/luci-app-mptcp/luasrc/view/mptcp/multipath.htm index 97ea6e956..01abf6a7f 100644 --- a/luci-app-mptcp/luasrc/view/mptcp/multipath.htm +++ b/luci-app-mptcp/luasrc/view/mptcp/multipath.htm @@ -85,6 +85,7 @@ function bandwidth_label(bytes, br) { + if (bytes < 0) bytes = 0; var uby = '<%:kB/s%>'; var kby = (bytes / 1024); diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 00c421517..ec1dbcd6b 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -634,6 +634,8 @@ function wizard_add() ucic:set("unbound","ub_main","dns64","0") end + ucic:save("unbound") + ucic:commit("unbound") -- Get Proxy set by default local default_proxy = luci.http.formvalue("default_proxy") or "shadowsocks" @@ -981,7 +983,7 @@ function wizard_add() ucic:set("openvpn","omr","enabled",1) ucic:set("network","omrvpn","proto","none") else - ucic:set("openvpn","omr","enabled",0) + ucic:delete("openvpn","omr","enabled") end ucic:save("openvpn") ucic:commit("openvpn") @@ -1156,7 +1158,7 @@ function settings_add() ucic:set("openmptcprouter","settings","shadowsocksudp",shadowsocksudp) -- Enable/disable v2ray udp - local shadowsocksudp = luci.http.formvalue("v2rayudp") or "1" + local v2rayudp = luci.http.formvalue("v2rayudp") or "1" ucic:set("v2ray","main_transparent_proxy","redirect_udp",v2rayudp) -- Enable/disable nDPI diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 9ac1e17b2..d49d3aed9 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1461,8 +1461,12 @@ _set_config_from_vps() { uci -q batch <<-EOF >/dev/null set openvpn.omr.port=$openvpn_port set openvpn.omr.secret="/etc/luci-uploads/openvpn.key" - set openvpn.omr.enabled=$openvpn_state EOF + if [ "$openvpn_state" = "1" ]; then + uci -q set openvpn.omr.enabled=$openvpn_state + else + uci -q del openvpn.omr.enabled + fi if [ "$(uci -q get openvpn.omr.remote)" != "127.0.0.1" ]; then uci -q set openvpn.omr.remote="$vpsip" fi From d08810bd895a334c37f41679db273d89140841ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 15 Sep 2022 09:07:47 +0200 Subject: [PATCH 0849/2059] Fix V2Ray UDP disable --- .../luasrc/controller/openmptcprouter.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index ec1dbcd6b..67e907243 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1158,8 +1158,10 @@ function settings_add() ucic:set("openmptcprouter","settings","shadowsocksudp",shadowsocksudp) -- Enable/disable v2ray udp - local v2rayudp = luci.http.formvalue("v2rayudp") or "1" + local v2rayudp = luci.http.formvalue("v2rayudp") or "0" ucic:set("v2ray","main_transparent_proxy","redirect_udp",v2rayudp) + ucic:save("v2ray") + ucic:commit("v2ray") -- Enable/disable nDPI local ndpi = luci.http.formvalue("ndpi") or "1" From 3d8e9968097f20c660748198f0c9bb39cecb71ec Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 15 Sep 2022 12:58:22 +0200 Subject: [PATCH 0850/2059] Add some USB dependencies --- openmptcprouter-full/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 5f301a04b..9a41f555a 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -62,7 +62,7 @@ MY_DEPENDS := \ rng-tools \ openvpn-openssl \ mmc-utils \ - libimobiledevice \ + libimobiledevice libimobiledevice-utils \ comgt \ kmod-random-core \ kmod-netem \ @@ -75,14 +75,14 @@ MY_DEPENDS := \ TARGET_mvebu:kmod-mwlwifi TARGET_mvebu:mwlwifi-firmware-88w8864 TARGET_mvebu:mwlwifi-firmware-88w8897 TARGET_mvebu:mwlwifi-firmware-88w8964 TARGET_mvebu:mwlwifi-firmware-88w8997 \ !TARGET_mvebu:kmod-usb-serial !TARGET_mvebu:kmod-usb-serial-option !TARGET_mvebu:kmod-usb-serial-wwan !TARGET_mvebu:usb-modeswitch !TARGET_mvebu:uqmi \ !TARGET_mvebu:umbim !TARGET_mvebu:kmod-mii !TARGET_mvebu:kmod-usb-net !TARGET_mvebu:kmod-usb-wdm !TARGET_mvebu:kmod-usb-net-qmi-wwan !TARGET_mvebu:kmod-usb-net-cdc-mbim !TARGET_mvebu:umbim \ - !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd \ + !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd !TARGET_mvebu:libusbmuxd \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su kmod-rtl8812au-ct \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 TARGET_r4s:kmod-r8168 (TARGET_x86||TARGET_x86_64):kmod-usb-net-rtl8152 \ luci-app-mlvpn mlvpn 464xlat kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ - LINUX_5_15:mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec + LINUX_5_15:mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec usbutils # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From a196e8b86a25471f39d731be0ff8b41b676571f2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 15 Sep 2022 20:55:53 +0200 Subject: [PATCH 0851/2059] Launch sqm-autorate only if max/min upload/download speed are set --- luci-app-sqm-autorate/root/etc/init.d/sqm-autorate | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 2d70776e7..1646d2e2a 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -21,6 +21,15 @@ _launch_autorate() { config_get autorate "$1" autorate [ "${autorate}" != "1" ] && return + config_get min_download "$1" min_download + config_get download "$1" download + config_get max_download "$1" max_download + [ "${min_download}" == "0" ] || [ "${max_download}" == "0" ] || [ "${download}" == "0" ] && return + config_get min_upload "$1" min_upload + config_get upload "$1" upload + config_get max_upload "$1" max_upload + [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return + procd_open_instance # shellcheck disable=SC2086 procd_set_param command /usr/share/sqm-autorate/CAKE-autorate.sh "$1" From a1404fd3eb0e73905db32f7d55a06c03e39cdb89 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 16 Sep 2022 08:32:15 +0200 Subject: [PATCH 0852/2059] ndpi-netfilter patch --- ndpi-netfilter2/patches/fcommon.patch | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 ndpi-netfilter2/patches/fcommon.patch diff --git a/ndpi-netfilter2/patches/fcommon.patch b/ndpi-netfilter2/patches/fcommon.patch new file mode 100644 index 000000000..faa8c57cf --- /dev/null +++ b/ndpi-netfilter2/patches/fcommon.patch @@ -0,0 +1,19 @@ +--- a/ndpi-netfilter/ipt/Makefile.anc 2022-09-05 09:34:30.579787766 +0200 ++++ b/ndpi-netfilter/ipt/Makefile 2022-09-05 09:34:42.555588398 +0200 +@@ -2,14 +2,14 @@ + NDPI_PRO := ${NDPI_SRC}/lib/protocols + XTBL := $(shell pkg-config --variable=xtlibdir xtables) + +-CFLAGS = -fPIC -I../.. -I${NDPI_SRC}/include -I${NDPI_SRC}/lib -I../src -I../libre -DOPENDPI_NETFILTER_MODULE -O2 -Wall ++CFLAGS = -fPIC -I../.. -I${NDPI_SRC}/include -I${NDPI_SRC}/lib -I../src -I../libre -DOPENDPI_NETFILTER_MODULE -O2 -Wall -fcommon + + all: libxt_ndpi.so + install: libxt_ndpi.so + if [ -n "$(DESTDIR)$(XTBL)" -a -d "$(DESTDIR)$(XTBL)" ]; then install -v libxt_ndpi.so $(DESTDIR)$(XTBL); ln -fs libxt_ndpi.so $(DESTDIR)$(XTBL)/libxt_NDPI.so ; else echo "No pkg-config --variable=xtlibdir xtables"; fi + + lib%.so: lib%.o +- $(CC) -shared -o $@ $^; ++ $(CC) -shared -nostartfiles -o $@ $^; + lib%.o: lib%.c ../src/xt_ndpi.h ${NDPI_SRC}/include/ndpi_config.h ../libre/regexp.h ../libre/regexp.c + $(CC) ${CFLAGS} -D_INIT=lib$*_init -c -o $@ $<; + clean: From 44ff4334bdc9595de134b44c60e4c8d94aa5b29b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Sep 2022 19:33:48 +0200 Subject: [PATCH 0853/2059] Fix typo and add help --- .../luasrc/view/openmptcprouter/wizard.htm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 8961bfa4e..d3cb34a89 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -944,7 +944,7 @@ checked<% end %> />
    - <%:SQM control bufferloat: the undesirable latency that arises when the router buffers too much data.%> + <%:SQM control bufferbloat: the undesirable latency that arises when the router buffers too much data.%>
    @@ -955,6 +955,7 @@
    <%:SQM autorate is for LTE and connection without a stable speed.%> + <%:Download and upload speed MUST be set to make this work.%> <% if cake ~= "cake" then %> From 25cdf439ca373d14b09163ce78a40ba01abd195b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Sep 2022 19:34:15 +0200 Subject: [PATCH 0854/2059] Interface with multiples IPs are working now --- mptcp/files/usr/bin/multipath | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 294c3aaab..a7953878c 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -143,16 +143,22 @@ else exit 0;; "on") [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null - ip mptcp endpoint add $IP dev $DEVICE subflow fullmesh + for i in $IP; do + ip mptcp endpoint add $i dev $DEVICE subflow fullmesh + done exit 0;; "signal") [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null - #ip mptcp endpoint add $IP dev $DEVICE signal subflow fullmesh - ip mptcp endpoint add $IP dev $DEVICE signal + for i in $IP; do + #ip mptcp endpoint add $i dev $DEVICE signal subflow fullmesh + ip mptcp endpoint add $i dev $DEVICE signal + done exit 0;; "backup") [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null - ip mptcp endpoint add $IP dev $DEVICE backup fullmesh + for i in $IP; do + ip mptcp endpoint add $i dev $DEVICE backup fullmesh + done exit 0;; "") case "$IFF" in From ca45d952c23b0120409d9020713496967e62ca30 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Sep 2022 10:17:37 +0200 Subject: [PATCH 0855/2059] Remove not needed iptables-save output --- https-dns-proxy/files/https-dns-proxy.init | 2 +- .../root/etc/firewall.omr-bypass | 2 +- .../root/etc/init.d/omr-bypass | 35 ++++++++++--------- omr-tracker/files/bin/omr-tracker-ss | 2 +- openmptcprouter/files/bin/blocklanfw | 18 +++++----- openmptcprouter/files/etc/firewall.ttl | 2 +- .../files/shadowsocks-libev.init | 4 +-- shadowsocks-libev/files/ss-rules | 4 +-- shadowsocks-libev/files/ss-rules6 | 2 +- v2ray-core/files/usr/bin/v2ray-rules | 6 ++-- v2ray-core/files/usr/bin/v2ray-rules6 | 2 +- 11 files changed, 40 insertions(+), 39 deletions(-) diff --git a/https-dns-proxy/files/https-dns-proxy.init b/https-dns-proxy/files/https-dns-proxy.init index 8b8680763..709999b13 100755 --- a/https-dns-proxy/files/https-dns-proxy.init +++ b/https-dns-proxy/files/https-dns-proxy.init @@ -91,7 +91,7 @@ start_instance() { p="$((p+1))" } -is_force_dns_active() { iptables-save | grep -q -w -- '--dport 53'; } +is_force_dns_active() { iptables-save 2>/dev/null | grep -q -w -- '--dport 53'; } start_service() { local p=5053 c diff --git a/luci-app-omr-bypass/root/etc/firewall.omr-bypass b/luci-app-omr-bypass/root/etc/firewall.omr-bypass index 7efffb894..5c482a198 100644 --- a/luci-app-omr-bypass/root/etc/firewall.omr-bypass +++ b/luci-app-omr-bypass/root/etc/firewall.omr-bypass @@ -1,2 +1,2 @@ #!/bin/sh -[ -z "$(pgrep -f omr-bypass)" ] && /etc/init.d/omr-bypass reload_rules +[ -z "$(pgrep -f omr-bypass)" ] && logger -t "firewall.omr-bypass" "reloal omr-bypass rules" && /etc/init.d/omr-bypass reload_rules diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 6c349317d..a8540b4fb 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -425,7 +425,7 @@ _bypass_proto() { _intf_rule_ss_rules() { rule_name=$1 [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$(iptables-save | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$(iptables-save 2>/dev/null | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -433,7 +433,7 @@ _intf_rule_ss_rules() { COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$(iptables-save | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$(iptables-save 2>/dev/null | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -441,7 +441,7 @@ _intf_rule_ss_rules() { COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save 2>/dev/null | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -457,7 +457,7 @@ _intf_rule_ss_rules() { COMMIT EOF fi - if [ "$(ip6tables --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables-save | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then + if [ "$(ip6tables --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables-save 2>/dev/null | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF *nat -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count @@ -476,7 +476,7 @@ _intf_rule_v2ray_rules() { #rule_name=$1 #[ "$rule_name" = "ss_rules" ] && rule_name="def" rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_dst)" != "" ] && [ "$(iptables-save | grep v2r_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_dst)" != "" ] && [ "$(iptables-save 2>/dev/null | grep v2r_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -484,7 +484,7 @@ _intf_rule_v2ray_rules() { COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_local_out)" != "" ] && [ "$(iptables-save | grep v2r_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_local_out)" != "" ] && [ "$(iptables-save 2>/dev/null | grep v2r_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -492,7 +492,7 @@ _intf_rule_v2ray_rules() { COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save | grep v2r_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save 2/dev/null | grep v2r6 | grep omr6_dst_bypass_$intf)" = "" ]; then ip6tables-restore -w --wait=60 --noflush <<-EOF *nat -I v2r6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count @@ -567,7 +567,7 @@ _intf_rule() { ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count pref 1 > /dev/null 2>&1 fi } - if [ "$(iptables-save | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then + if [ "$(iptables-save 2>/dev/null | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then iptables-restore -w --wait=60 --noflush <<-EOF *mangle -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count @@ -725,7 +725,7 @@ start_service() { create omr6_dst_bypass_all hash:net family inet6 hashsize 64 EOF } - iptables-save --counters | grep -v omr-bypass | iptables-restore -w --counters + iptables-save --counters 2>/dev/null | grep -v omr-bypass | iptables-restore -w --counters 2>/dev/null iptables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass - @@ -739,7 +739,7 @@ start_service() { COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-save --counters | grep -v omr-bypass6 | ip6tables-restore -w --counters + ip6tables-save --counters 2>/dev/null | grep -v omr-bypass6 | ip6tables-restore -w --counters 2>/dev/null ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass6 - @@ -805,7 +805,7 @@ start_service() { config_foreach _ss_rules_config _v2ray_rules_config - iptables-save --counters | grep -v omr-bypass-dpi | iptables-restore -w --counters + iptables-save --counters 2>/dev/null | grep -v omr-bypass-dpi | iptables-restore -w --counters 2>/dev/null iptables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass-dpi - @@ -814,7 +814,7 @@ start_service() { COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-save --counters | grep -v omr-bypass6-dpi | ip6tables-restore -w --counters + ip6tables-save --counters | grep -v omr-bypass6-dpi | ip6tables-restore -w --counters 2>/dev/null ip6tables-restore -w --wait=60 --noflush <<-EOF *mangle :omr-bypass6-dpi - @@ -839,10 +839,10 @@ start_service() { } stop_service() { - iptables-save --counters | grep -v omr-bypass | iptables-restore -w --counters - iptables-save --counters | grep -v omr_dst | iptables-restore -w --counters - ip6tables-save --counters | grep -v omr-bypass6 | ip6tables-restore -w --counters - ip6tables-save --counters | grep -v omr6_dst | ip6tables-restore -w --counters + iptables-save --counters 2>/dev/null | grep -v omr-bypass | iptables-restore -w --counters 2>/dev/null + iptables-save --counters 2>/dev/null | grep -v omr_dst | iptables-restore -w --counters 2>/dev/null + ip6tables-save --counters 2>/dev/null | grep -v omr-bypass6 | ip6tables-restore -w --counters 2>/dev/null + ip6tables-save --counters 2>/dev/null | grep -v omr6_dst | ip6tables-restore -w --counters 2>/dev/null for setname in $(ipset -n list | grep "omr_"); do ipset -q destroy "$setname" 2>/dev/null || true done @@ -853,6 +853,7 @@ service_triggers() { } reload_service() { + RELOAD=1 start } diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index 28f54b41a..ec1918024 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -76,7 +76,7 @@ while true; do uci -q set openmptcprouter.omr.ss_${server}="up" uci -q commit openmptcprouter.omr } - if [ -z "$(iptables-save | grep :ssr)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then + if [ -z "$(iptables-save 2>/dev/null | grep :ssr)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then _log "Reload Shadowsocks rules" /etc/init.d/shadowsocks-libev rules_up 2> /dev/null _get_ip diff --git a/openmptcprouter/files/bin/blocklanfw b/openmptcprouter/files/bin/blocklanfw index a35694dac..a839e3e2f 100755 --- a/openmptcprouter/files/bin/blocklanfw +++ b/openmptcprouter/files/bin/blocklanfw @@ -3,7 +3,7 @@ ss_rules_fw_drop() { timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi @@ -11,7 +11,7 @@ ss_rules_fw_drop() { timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi @@ -22,7 +22,7 @@ ss_rules6_fw_drop() { timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi @@ -30,7 +30,7 @@ ss_rules6_fw_drop() { timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi @@ -41,7 +41,7 @@ v2r_rules_fw_drop() { timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "iptables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi @@ -49,7 +49,7 @@ v2r_rules_fw_drop() { timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "iptables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi @@ -60,21 +60,21 @@ v2ray_rules6_fw_drop() { timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "ip6tables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fi done timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "ip6tables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fi done } [ -n "$(pgrep blocklanfw)" ] && exit 0 -[ -z "$(iptables-save | grep zone_lan)" ] && exit 0 +[ -z "$(iptables-save 2>/dev/null | grep zone_lan)" ] && exit 0 fw=0 if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then ss_rules6_fw_drop diff --git a/openmptcprouter/files/etc/firewall.ttl b/openmptcprouter/files/etc/firewall.ttl index e241dbfca..0c48ee873 100644 --- a/openmptcprouter/files/etc/firewall.ttl +++ b/openmptcprouter/files/etc/firewall.ttl @@ -5,7 +5,7 @@ _set_ttl() { device=$(uci -q get network.$1.name) ttl=$(uci -q get network.$1.ttl) - if [ -n "$ttl" ] && [ -z "$(iptables-save | grep TTL | grep $device)" ]; then + if [ -n "$ttl" ] && [ -z "$(iptables-save 2>/dev/null | grep TTL | grep $device)" ]; then iptables -w -t mangle -I POSTROUTING -o $device -j TTL --ttl-set $ttl 2>&1 >/dev/null fi } diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index c93f03a3e..094e1fdbd 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -326,7 +326,7 @@ reload_service() { } rules_exist() { - [ -n "$(iptables-save | grep 'A ssr')" ] && return 0 + [ -n "$(iptables-save 2>/dev/null | grep 'A ssr')" ] && return 0 return 1 } @@ -356,7 +356,7 @@ rules_up() { config_foreach ss_rules_restart "$cfgtype" "$cfgtype" done config_foreach ss_rules ss_rules - [ -z "$(iptables-save | grep :ssr)" ] && logger -t "Shadowsocks" "Rules not applied" + [ -z "$(iptables-save 2>/dev/null | grep :ssr)" ] && logger -t "Shadowsocks" "Rules not applied" [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { logger -t "Shadowsocks" "Reload omr-bypass rules" /etc/init.d/omr-bypass reload_rules diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 9364afb31..27e7f1de1 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -122,7 +122,7 @@ ss_rules_parse_args() { ss_rules_flush() { local setname - iptables-save --counters | grep -v ssr_ | iptables-restore -w --counters + iptables-save --counters 2>/dev/null | grep -v ssr_ | iptables-restore -w --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true for setname in $(ipset -n list | grep "ssr_${rule}"); do @@ -187,7 +187,7 @@ ss_rules_iptchains_init_tcp() { forward) local_target=ssr_${rule}_forward ;; bypass|*) return 0;; esac - if [ "$(iptables-save | grep ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then + if [ "$(iptables-save 2>/dev/null | grep ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then iptables-restore -w --noflush <<-EOF *nat :ssr_${rule}_local_out - diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index 0b1973523..cd178c88c 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -105,7 +105,7 @@ ss_rules6_parse_args() { ss_rules6_flush() { local setname - ip6tables-save --counters | grep -v ssr6_ | ip6tables-restore -w --counters + ip6tables-save --counters 2>/dev/null | grep -v ssr6_ | ip6tables-restore -w --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true for setname in $(ipset -n list | grep "ssr6_${rule}"); do diff --git a/v2ray-core/files/usr/bin/v2ray-rules b/v2ray-core/files/usr/bin/v2ray-rules index 45150d743..6d711a37d 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules +++ b/v2ray-core/files/usr/bin/v2ray-rules @@ -122,7 +122,7 @@ v2r_rules_parse_args() { v2r_rules_flush() { local setname - iptables-save --counters | grep -v v2r_ | iptables-restore -w --counters + iptables-save --counters 2>/dev/null | grep -v v2r_ | iptables-restore -w --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true for setname in $(ipset -n list | grep "ssr_${rule}"); do @@ -287,14 +287,14 @@ v2r_rules_fw_drop() { fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fi done fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then eval "iptables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fi done diff --git a/v2ray-core/files/usr/bin/v2ray-rules6 b/v2ray-core/files/usr/bin/v2ray-rules6 index 3d0e6d79f..33b44868c 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules6 +++ b/v2ray-core/files/usr/bin/v2ray-rules6 @@ -105,7 +105,7 @@ v2ray_rules6_parse_args() { v2ray_rules6_flush() { local setname - ip6tables-save --counters | grep -v v2r6_ | ip6tables-restore -w --counters + ip6tables-save --counters 2>/dev/null | grep -v v2r6_ | ip6tables-restore -w --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true for setname in $(ipset -n list | grep "ssr6_${rule}"); do From 827a93c478f1a0dea33efc472da2be74c38ab826 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 25 Sep 2022 19:02:32 +0200 Subject: [PATCH 0856/2059] Use iptables-legacy instead of iptables --- .../root/etc/init.d/omr-bypass | 168 ++++++++++-------- omr-tracker/files/bin/omr-tracker-ss | 14 +- omr-tracker/files/bin/omr-tracker-v2ray | 11 +- openmptcprouter/files/bin/blocklanfw | 47 +++-- openmptcprouter/files/etc/firewall.gre-tunnel | 16 +- shadowsocks-libev/files/ss-rules | 25 ++- shadowsocks-libev/files/ss-rules6 | 24 ++- v2ray-core/files/etc/init.d/v2ray | 2 +- v2ray-core/files/usr/bin/v2ray-rules | 32 ++-- v2ray-core/files/usr/bin/v2ray-rules6 | 26 ++- 10 files changed, 233 insertions(+), 132 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index a8540b4fb..0c3ba4932 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -8,6 +8,22 @@ EXTRA_COMMANDS="reload_rules bypass_asn" . /usr/lib/unbound/iptools.sh +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" + IP6TABLES="/usr/sbin/ip6tables-legacy" + IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESSAVE="/usr/sbin/iptables-save" + IP6TABLES="/usr/sbin/ip6tables" + IP6TABLESRESTORE="/usr/sbin/ip6tables-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + _add_proto() { protoname=$1 [ -z "$protoname" ] && return @@ -135,26 +151,26 @@ _bypass_mac() { [ -z "$intf" ] && intf="all" [ -z "$mac" ] && return if [ "$intf" = "all" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539 COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539 COMMIT EOF fi else - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539$intfid COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539$intfid COMMIT @@ -181,18 +197,18 @@ _bypass_lan_ip() { valid_ip6=$(valid_subnet6 $ip) if [ "$intf" = "all" ]; then if [ "$valid_ip4" = "ok" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass -s $ip -j MARK --set-mark 0x539 COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local -s $ip -j MARK --set-mark 0x539 COMMIT EOF elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539 COMMIT @@ -200,18 +216,18 @@ _bypass_lan_ip() { fi else if [ "$valid_ip4" = "ok" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass -s $ip -j MARK --set-mark 0x539$intfid COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local -s $ip -j MARK --set-mark 0x539$intfid COMMIT EOF elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539$intfid COMMIT @@ -239,36 +255,36 @@ _bypass_dest_port() { dport="$(echo $dport | sed 's/-/:/')" [ -z "$proto" ] && return if [ "$intf" = "all" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539 COMMIT EOF fi else - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539$intfid COMMIT @@ -296,36 +312,36 @@ _bypass_src_port() { sport="$(echo $sport | sed 's/-/:/')" [ -z "$proto" ] && return if [ "$intf" = "all" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539 COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539 COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539 COMMIT EOF fi else - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539$intfid COMMIT @@ -351,14 +367,14 @@ _bypass_proto() { [ -z "$proto" ] && return if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ] && [ "$ndpi" != "0" ]; then if [ "$intf" = "all" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN @@ -366,14 +382,14 @@ _bypass_proto() { EOF fi else - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN @@ -425,24 +441,24 @@ _bypass_proto() { _intf_rule_ss_rules() { rule_name=$1 [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$(iptables-save 2>/dev/null | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I ssr_${rule_name}_dst 2 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$(iptables-save 2>/dev/null | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save 2>/dev/null | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539$count -j RETURN @@ -450,15 +466,15 @@ _intf_rule_ss_rules() { EOF fi if [ "$disableipv6" = "0" ]; then - if [ "$(ip6tables --wait=40 -t mangle -L -n | grep omr6_dst_bypass_$intf)" = "" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep omr6_dst_bypass_$intf)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -I omr-bypass6 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count COMMIT EOF fi - if [ "$(ip6tables --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables-save 2>/dev/null | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLESSAVE 2>/dev/null | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count -I ssr6_${rule_name}_dst 2 -m mark --mark 0x6539$count -j RETURN @@ -476,24 +492,24 @@ _intf_rule_v2ray_rules() { #rule_name=$1 #[ "$rule_name" = "ss_rules" ] && rule_name="def" rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_dst)" != "" ] && [ "$(iptables-save 2>/dev/null | grep v2r_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep v2r_${rule_name}_dst)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep v2r_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I v2r_${rule_name}_dst 2 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_local_out)" != "" ] && [ "$(iptables-save 2>/dev/null | grep v2r_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep v2r_${rule_name}_local_out)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep v2r_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I v2r_${rule_name}_local_out 2 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables-save 2/dev/null | grep v2r6 | grep omr6_dst_bypass_$intf)" = "" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep v2r6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLESSAVE 2>/dev/null | grep v2r6 | grep omr6_dst_bypass_$intf)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I v2r6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count -I v2r6_${rule_name}_dst 2 -m mark --mark 0x6539$count -j RETURN @@ -567,8 +583,8 @@ _intf_rule() { ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count pref 1 > /dev/null 2>&1 fi } - if [ "$(iptables-save 2>/dev/null | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLESSAVE 2>/dev/null | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count -I omr-bypass 2 -m mark --mark 0x539$count -j RETURN @@ -627,8 +643,8 @@ _bypass_omr_server() { _ss_rules_config() { rule_name=$1 [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$(iptables --wait=40 -t nat -L -n | grep omr_dst_bypass_all)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLES --wait=40 -t nat -L -n | grep omr_dst_bypass_all)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 -I ssr_${rule_name}_dst 2 -m mark --mark 0x539 -j RETURN @@ -640,15 +656,15 @@ _ss_rules_config() { EOF fi if [ "$disableipv6" = "0" ]; then - if [ "$(ip6tables --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 COMMIT EOF fi - if [ "$(ip6tables --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables --wait=40 -t nat -L -n | grep omr6_dst_bypass_all)" = "" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLES --wait=40 -t nat -L -n | grep omr6_dst_bypass_all)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 -I ssr6_${rule_name}_dst 1 -m mark --mark 0x6539 -j RETURN @@ -666,8 +682,8 @@ _v2ray_rules_config() { #rule_name=$1 #[ "$rule_name" = "ss_rules" ] && rule_name="def" rule_name="def" - if [ "$(iptables --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$(iptables --wait=40 -t nat -L -n | grep omr_dst_bypass_all)" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep v2r_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLES --wait=40 -t nat -L -n | grep omr_dst_bypass_all)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I v2r_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 -I v2r_${rule_name}_dst 2 -m mark --mark 0x539 -j RETURN @@ -679,15 +695,15 @@ _v2ray_rules_config() { EOF fi if [ "$disableipv6" = "0" ]; then - if [ "$(ip6tables --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 COMMIT EOF fi - if [ "$(ip6tables --wait=40 -t nat -L -n | grep v2r6_${rule_name}_pre_src)" != "" ] && [ "$(ip6tables --wait=40 -t nat -L -n | grep omr6_dst_bypass_all)" = "" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep v2r6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLES --wait=40 -t nat -L -n | grep omr6_dst_bypass_all)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *nat -I v2r6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 -I v2r6_${rule_name}_dst 1 -m mark --mark 0x6539 -j RETURN @@ -725,22 +741,22 @@ start_service() { create omr6_dst_bypass_all hash:net family inet6 hashsize 64 EOF } - iptables-save --counters 2>/dev/null | grep -v omr-bypass | iptables-restore -w --counters 2>/dev/null - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle :omr-bypass - -A PREROUTING -j omr-bypass COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle :omr-bypass-local - -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-local COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-save --counters 2>/dev/null | grep -v omr-bypass6 | ip6tables-restore -w --counters 2>/dev/null - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle :omr-bypass6 - -A PREROUTING -j omr-bypass6 @@ -786,14 +802,14 @@ start_service() { ip rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 - if [ "$(iptables --wait=40 -t mangle -L -n | grep 'match-set omr_dst_bypass_all dst MARK set')" = "" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF + if [ "$($IPTABLES --wait=40 -t mangle -L -n | grep 'match-set omr_dst_bypass_all dst MARK set')" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 -A omr-bypass -m mark --mark 0x539 -j RETURN COMMIT EOF - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass-local -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 -A omr-bypass-local -m mark --mark 0x539 -j RETURN @@ -805,8 +821,8 @@ start_service() { config_foreach _ss_rules_config _v2ray_rules_config - iptables-save --counters 2>/dev/null | grep -v omr-bypass-dpi | iptables-restore -w --counters 2>/dev/null - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass-dpi | $IPTABLESRESTORE -w --counters 2>/dev/null + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle :omr-bypass-dpi - -A INPUT -j omr-bypass-dpi @@ -814,8 +830,8 @@ start_service() { COMMIT EOF if [ "$disableipv6" = "0" ]; then - ip6tables-save --counters | grep -v omr-bypass6-dpi | ip6tables-restore -w --counters 2>/dev/null - ip6tables-restore -w --wait=60 --noflush <<-EOF + $IP6TABLESSAVE --counters | grep -v omr-bypass6-dpi | $IP6TABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle :omr-bypass6-dpi - -A INPUT -j omr-bypass6-dpi @@ -839,10 +855,10 @@ start_service() { } stop_service() { - iptables-save --counters 2>/dev/null | grep -v omr-bypass | iptables-restore -w --counters 2>/dev/null - iptables-save --counters 2>/dev/null | grep -v omr_dst | iptables-restore -w --counters 2>/dev/null - ip6tables-save --counters 2>/dev/null | grep -v omr-bypass6 | ip6tables-restore -w --counters 2>/dev/null - ip6tables-save --counters 2>/dev/null | grep -v omr6_dst | ip6tables-restore -w --counters 2>/dev/null + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr_dst | $IPTABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr6_dst | $IP6TABLESRESTORE -w --counters 2>/dev/null for setname in $(ipset -n list | grep "omr_"); do ipset -q destroy "$setname" 2>/dev/null || true done diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index ec1918024..50337a094 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -4,6 +4,16 @@ name=$0 basename="$(basename $0)" +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IPTABLESAVE="/usr/sbin/iptables-legacy-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESAVE="/usr/sbin/iptables-save" +fi + + + _log() { logger -p daemon.info -t "${basename}" "$@" } @@ -76,7 +86,7 @@ while true; do uci -q set openmptcprouter.omr.ss_${server}="up" uci -q commit openmptcprouter.omr } - if [ -z "$(iptables-save 2>/dev/null | grep :ssr)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then + if [ -z "$($IPTABLESSAVE 2>/dev/null | grep :ssr)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then _log "Reload Shadowsocks rules" /etc/init.d/shadowsocks-libev rules_up 2> /dev/null _get_ip @@ -87,7 +97,7 @@ while true; do last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" [ "${last}" -ge "${retry}" ] && { - if [ -n "$(iptables -w -t nat -L -n | grep ssr)" ]; then + if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ssr)" ]; then _log "Shadowsocks ${server} is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.ss_${server}="down" uci -q commit openmptcprouter.omr diff --git a/omr-tracker/files/bin/omr-tracker-v2ray b/omr-tracker/files/bin/omr-tracker-v2ray index 2530ca63f..9201d54b0 100755 --- a/omr-tracker/files/bin/omr-tracker-v2ray +++ b/omr-tracker/files/bin/omr-tracker-v2ray @@ -4,6 +4,13 @@ name=$0 basename="$(basename $0)" +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" +else + IPTABLES="/usr/sbin/iptables" +fi + + _log() { logger -p daemon.info -t "${basename}" "$@" } @@ -75,7 +82,7 @@ while true; do uci -q set openmptcprouter.omr.v2ray="up" uci -q commit openmptcprouter.omr } - if [ -z "$(iptables -w -t nat -L -n | grep v2r)" ]; then + if [ -z "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep v2r)" ]; then _log "Reload V2Ray rules" /etc/init.d/v2ray rules_up 2> /dev/null _get_ip @@ -86,7 +93,7 @@ while true; do last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" [ "${last}" -ge "${retry}" ] && { - if [ -n "$(iptables -w -t nat -L -n | grep v2r)" ]; then + if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep v2r)" ]; then _log "V2Ray is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.v2ray="down" uci -q commit openmptcprouter.omr diff --git a/openmptcprouter/files/bin/blocklanfw b/openmptcprouter/files/bin/blocklanfw index a839e3e2f..56f176c81 100755 --- a/openmptcprouter/files/bin/blocklanfw +++ b/openmptcprouter/files/bin/blocklanfw @@ -1,18 +1,31 @@ #!/bin/sh + +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IP6TABLES="/usr/sbin/ip6tables-legacy" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" + IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +else + IPTABLES="/usr/sbin/iptables" + IP6TABLES="/usr/sbin/ip6tables" + IPTABLESSAVE="/usr/sbin/iptables-save" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + ss_rules_fw_drop() { timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IPTABLES-w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IPTABLES-w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done @@ -22,16 +35,16 @@ ss_rules6_fw_drop() { timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IP6TABLES-w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IP6TABLES-w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done @@ -41,16 +54,16 @@ v2r_rules_fw_drop() { timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IPTABLES-w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done timeout 1 fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IPTABLES-w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fw=$((fw+1)) fi done @@ -60,21 +73,21 @@ v2ray_rules6_fw_drop() { timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IP6TABLES-w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fi done timeout 1 fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j DROP/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/DROP/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IP6TABLES-w -t nat -I zone_lan_prerouting 1 ${fwrule} 2>&1 >/dev/null" fi done } [ -n "$(pgrep blocklanfw)" ] && exit 0 -[ -z "$(iptables-save 2>/dev/null | grep zone_lan)" ] && exit 0 +[ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan)" ] && exit 0 fw=0 if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then ss_rules6_fw_drop diff --git a/openmptcprouter/files/etc/firewall.gre-tunnel b/openmptcprouter/files/etc/firewall.gre-tunnel index 4d8d450e1..f287a096b 100644 --- a/openmptcprouter/files/etc/firewall.gre-tunnel +++ b/openmptcprouter/files/etc/firewall.gre-tunnel @@ -1,6 +1,14 @@ #!/bin/sh . /lib/functions.sh +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" + IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" +else + IPTABLESSAVE="/usr/sbin/iptables-save" + IPTABLESRESTORE="/usr/sbin/iptables-restore" +fi + _setup_rules() { config_get lookup $1 lookup [ -n "$lookup" ] && [ -z "$(ip rule list fwmark 0x${lookup})" ] && { @@ -30,8 +38,8 @@ _setup_fw() { [ -n "$src_ips_forward" ] && rule="$rule -s $(echo "${src_ips_forward}" | sed 's/ /,/g')" [ -n "$ifnames" ] && rule="$rule -i $(echo "${ifnames}" | sed 's/ /-i /g')" if [ -n "$rule" ] && [ -n "$lookup" ]; then - iptables-save --counters | grep -v "0x${lookup}" | iptables-restore -w --counters - iptables-restore -w --wait=60 --noflush <<-EOF + $IPTABLESAVE --counters | grep -v "0x${lookup}" | $IPTABLERESTORE -w --counters + $IPTABLERESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-gre-tunnel ${rule} -j MARK --set-mark 0x${lookup} COMMIT @@ -39,8 +47,8 @@ _setup_fw() { fi } -if [ -z "$(iptables-save | grep omr-gre-tunnel)" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF +if [ -z "$($IPTABLESAVE | grep omr-gre-tunnel)" ]; then + $IPTABLERESTORE -w --wait=60 --noflush <<-EOF *mangle :omr-gre-tunnel - -I PREROUTING 1 -m addrtype ! --dst-type LOCAL -j omr-gre-tunnel diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 27e7f1de1..9e6907fab 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -9,6 +9,17 @@ # See /LICENSE for more information. # +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESSAVE="/usr/sbin/iptables-save" +fi + + ss_rules_usage() { cat >&2 </dev/null; then + if [ -n "$o_dst_forward_recentrst" ] && ! $IPTABLES -w -m recent -h >/dev/null; then __errmsg "Please install iptables-mod-conntrack-extra with opkg" return 1 fi @@ -122,7 +133,7 @@ ss_rules_parse_args() { ss_rules_flush() { local setname - iptables-save --counters 2>/dev/null | grep -v ssr_ | iptables-restore -w --counters + $IPTABLESSAVE --counters 2>/dev/null | grep -v ssr_ | $IPTABLESRESTORE -w --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true for setname in $(ipset -n list | grep "ssr_${rule}"); do @@ -166,8 +177,8 @@ ss_rules_iptchains_init() { } ss_rules_iptchains_init_mark() { - if [ "$(iptables -w -t mangle -L PREROUTING | grep ss_rules_dst_bypass_all)" = "" ]; then - iptables-restore -w --noflush <<-EOF + if [ "$($IPTABLES -w -t mangle -L PREROUTING | grep ss_rules_dst_bypass_all)" = "" ]; then + $IPTABLESRESTORE -w --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 COMMIT @@ -187,8 +198,8 @@ ss_rules_iptchains_init_tcp() { forward) local_target=ssr_${rule}_forward ;; bypass|*) return 0;; esac - if [ "$(iptables-save 2>/dev/null | grep ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then - iptables-restore -w --noflush <<-EOF + if [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then + $IPTABLESRESTORE -w --noflush <<-EOF *nat :ssr_${rule}_local_out - -I OUTPUT 1 -p tcp -j ssr_${rule}_local_out @@ -244,7 +255,7 @@ ss_rules_iptchains_init_() { forward) dst_default_target=ssr_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IPTABLESRESTORE -w --noflush *$table :ssr_${rule}_pre_src - :ssr_${rule}_src - diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index cd178c88c..b0e2704d8 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -9,6 +9,18 @@ # See /LICENSE for more information. # +if [ -f /usr/sbin/iptables-legacy ]; then + IP6TABLES="/usr/sbin/ip6tables-legacy" + IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +else + IP6TABLES="/usr/sbin/ip6tables" + IP6TABLESRESTORE="/usr/sbin/ip6tables-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + + + ss_rules6_usage() { cat >&2 </dev/null; then + if [ -n "$o_dst_forward_recentrst" ] && ! $IP6TABLES -w -m recent -h >/dev/null; then __errmsg "Please install ip6tables-mod-conntrack-extra with opkg" return 1 fi @@ -105,7 +117,7 @@ ss_rules6_parse_args() { ss_rules6_flush() { local setname - ip6tables-save --counters 2>/dev/null | grep -v ssr6_ | ip6tables-restore -w --counters + $IP6TABLESSAVE --counters 2>/dev/null | grep -v ssr6_ | $IP6TABLESRESTORE -w --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true for setname in $(ipset -n list | grep "ssr6_${rule}"); do @@ -149,8 +161,8 @@ ss_rules6_iptchains_init() { } ss_rules6_iptchains_init_mark() { - if [ "$(ip6tables -w -t mangle -L PREROUTING | grep ss_rules6_dst_bypass_all)" = "" ]; then - ip6tables-restore -w --noflush <<-EOF + if [ "$($IP6TABLES -w -t mangle -L PREROUTING | grep ss_rules6_dst_bypass_all)" = "" ]; then + $IP6TABLESRESTORE -w --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 COMMIT @@ -172,7 +184,7 @@ ss_rules6_iptchains_init_tcp() { bypass|*) return 0;; esac - ip6tables-restore -w --noflush <<-EOF + $IP6TABLESRESTORE -w --noflush <<-EOF *nat :ssr6_${rule}_local_out - -I OUTPUT 1 -p tcp -j ssr6_${rule}_local_out @@ -227,7 +239,7 @@ ss_rules6_iptchains_init_() { forward) dst_default_target=ssr6_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | ip6tables-restore -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IP6TABLESRESTORE -w --noflush *$table :ssr6_${rule}_pre_src - :ssr6_${rule}_src - diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index ffe8d1db4..3cd9e8740 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -2086,7 +2086,7 @@ start_instance() { } rules_exist() { - [ -n "$(iptables -w -t nat -L -n | grep v2r_)" ] && return 0 + [ -n "$(iptables -w -t nat -L -n 2>/dev/null | grep v2r_)" ] && return 0 return 1 } diff --git a/v2ray-core/files/usr/bin/v2ray-rules b/v2ray-core/files/usr/bin/v2ray-rules index 6d711a37d..1424e52e1 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules +++ b/v2ray-core/files/usr/bin/v2ray-rules @@ -9,6 +9,18 @@ # See /LICENSE for more information. # +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESSAVE="/usr/sbin/iptables-save" +fi + + + v2r_rules_usage() { cat >&2 </dev/null; then + if [ -n "$o_dst_forward_recentrst" ] && ! $IPTABLES -w -m recent -h >/dev/null; then __errmsg "Please install iptables-mod-conntrack-extra with opkg" return 1 fi @@ -122,7 +134,7 @@ v2r_rules_parse_args() { v2r_rules_flush() { local setname - iptables-save --counters 2>/dev/null | grep -v v2r_ | iptables-restore -w --counters + $IPTABLESSAVE --counters 2>/dev/null | grep -v v2r_ | $IPTABLESRESTORE -w --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true for setname in $(ipset -n list | grep "ssr_${rule}"); do @@ -166,8 +178,8 @@ v2r_rules_iptchains_init() { } v2r_rules_iptchains_init_mark() { - if [ "$(iptables -w -t mangle -L PREROUTING | grep ss_rules_dst_bypass_all)" = "" ]; then - iptables-restore -w --noflush <<-EOF + if [ "$($IPTABLES -w -t mangle -L PREROUTING | grep ss_rules_dst_bypass_all)" = "" ]; then + $IPTABLESRESTORE -w --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 COMMIT @@ -188,7 +200,7 @@ v2r_rules_iptchains_init_tcp() { bypass|*) return 0;; esac - iptables-restore -w --noflush <<-EOF + $IPTABLESRESTORE -w --noflush <<-EOF *nat :v2r_${rule}_local_out - -I OUTPUT 1 -p tcp -j v2r_${rule}_local_out @@ -243,7 +255,7 @@ v2r_rules_iptchains_init_() { forward) dst_default_target=v2r_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | iptables-restore -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IPTABLESRESTORE -w --noflush *$table :v2r_${rule}_pre_src - :v2r_${rule}_src - @@ -287,15 +299,15 @@ v2r_rules_fw_drop() { fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IPTABLES -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fi done fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') - if [ -n "$fwrule" ] && [ -z "$(iptables-save 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "iptables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + if [ -n "$fwrule" ] && [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "$IPTABLES -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fi done } diff --git a/v2ray-core/files/usr/bin/v2ray-rules6 b/v2ray-core/files/usr/bin/v2ray-rules6 index 33b44868c..ed9ad2e1a 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules6 +++ b/v2ray-core/files/usr/bin/v2ray-rules6 @@ -9,6 +9,18 @@ # See /LICENSE for more information. # +if [ -f /usr/sbin/iptables-legacy ]; then + IP6TABLES="/usr/sbin/ip6tables-legacy" + IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +else + IP6TABLES="/usr/sbin/ip6tables" + IP6TABLESRESTORE="/usr/sbin/ip6tables-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + + + v2ray_rules6_usage() { cat >&2 </dev/null; then + if [ -n "$o_dst_forward_recentrst" ] && ! $IP6TABLES -w -m recent -h >/dev/null; then __errmsg "Please install ip6tables-mod-conntrack-extra with opkg" return 1 fi @@ -105,7 +117,7 @@ v2ray_rules6_parse_args() { v2ray_rules6_flush() { local setname - ip6tables-save --counters 2>/dev/null | grep -v v2r6_ | ip6tables-restore -w --counters + $IP6TABLESSAVE --counters 2>/dev/null | grep -v v2r6_ | $IP6TABLESRESTORE -w --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true for setname in $(ipset -n list | grep "ssr6_${rule}"); do @@ -149,7 +161,7 @@ v2ray_rules6_iptchains_init() { } v2ray_rules6_iptchains_init_mark() { - ip6tables-restore -w --noflush <<-EOF + $IP6TABLESRESTORE -w --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 COMMIT @@ -172,7 +184,7 @@ v2ray_rules6_iptchains_init_tcp() { esac # echo "tcp mangle" -# ip6tables-restore -w --noflush <<-EOF +# $IP6TABLESRESTORE -w --noflush <<-EOF # *mangle # :v2r6_${rule}_local_out - # -I OUTPUT 1 -p tcp -j v2r6_${rule}_local_out @@ -232,7 +244,7 @@ v2ray_rules6_iptchains_init_() { forward) dst_default_target=v2r6_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | ip6tables-restore -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IP6TABLESRESTORE -w --noflush *$table :v2r6_${rule}_pre_src - :v2r6_${rule}_src - @@ -279,14 +291,14 @@ v2ray_rules6_fw_drop() { while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + eval "$IP6TABLES -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fi done fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | while IFS=$"\n" read -r c; do fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then - eval "ip6tables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + eval "$IP6TABLES -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" fi done } From c8dbb17bd05bce5ebe462f231c1d1180ac0c76f7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 25 Sep 2022 19:03:25 +0200 Subject: [PATCH 0857/2059] Add a token function to openmptcprouter-vps script --- .../root/usr/libexec/rpcd/openmptcprouter | 4 +- .../share/omr/post-tracking.d/post-tracking | 8 +++- .../files/etc/init.d/openmptcprouter-vps | 40 ++++++++++++++++--- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 32af00eb8..f01761f1b 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -895,7 +895,7 @@ function interfaces_status() mArray.openmptcprouter["vps_status"] = "UP" mArray.openmptcprouter["vps_admin_error_msg"] = "" else - uci:set("openmptcprouter",s[".name"],"admin_error","1") + uci:set("openmptcprouter",s[".name"],"token_error","1") mArray.openmptcprouter["vps_admin_error"] = true uci:delete("openmptcprouter",s[".name"],"token") uci:save("openmptcprouter",s[".name"]) @@ -931,7 +931,7 @@ function interfaces_status() else mArray.openmptcprouter["vps_admin"] = false mArray.openmptcprouter["vps_admin_error_msg"] = "No result" - uci:set("openmptcprouter",s[".name"],"admin_error","1") + uci:set("openmptcprouter",s[".name"],"token_error","1") mArray.openmptcprouter["vps_admin_error"] = true uci:delete("openmptcprouter",s[".name"],"token") uci:save("openmptcprouter",s[".name"]) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 7500e76c1..156f928dd 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1692,7 +1692,7 @@ if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then echo 1 > /sys/bus/pci/rescan fi -if [ -f /etc/init.d/omr-bypass ] && [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep -f omr-bypass)" = "" ]; then +if [ -f /etc/init.d/omr-bypass ] && (([ -f /usr/sbin/iptables-legacy-save ] && [ "$(iptables-legacy-save 2>/dev/null | grep omr-bypass)" = "" ]) || [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ]) && [ "$(pgrep -f omr-bypass)" = "" ]; then _log "Can't find omr-bypass rules, restart omr-bypass..." /etc/init.d/omr-bypass 2>&1 >/dev/null sleep 5 @@ -1703,6 +1703,10 @@ if [ -f /etc/backup/installed_packages.txt ] && [ -n "$(grep overlay /etc/backup /etc/init.d/sysupgrade restart 2>&1 >/dev/null fi +if [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep token_error=\'1\')" != "" ]; then + /etc/init.d/openmptcprouter-vps token >/dev/null 2>&1 + sleep 5 +fi if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 sleep 5 @@ -1713,7 +1717,7 @@ if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q sleep 5 fi -#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || (([ -f /usr/sbin/iptables-legacy-save ] && [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]) || [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ])); then if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then check_server_fw() { [ "$(uci -q get openmptcprouter.$1.set_firewall)" = "1" ] && { diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index d49d3aed9..6fcf197d5 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -6,10 +6,27 @@ START=99 USE_PROCD=1 -EXTRA_COMMANDS="set_pihole backup_send backup_get backup_list set_vps_firewall get_openvpn_key set_gre_tunnel" +EXTRA_COMMANDS="set_pihole backup_send backup_get backup_list set_vps_firewall get_openvpn_key set_gre_tunnel token" . /usr/lib/unbound/iptools.sh +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" + IP6TABLES="/usr/sbin/ip6tables-legacy" + IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESSAVE="/usr/sbin/iptables-save" + IP6TABLES="/usr/sbin/ip6tables" + IP6TABLESRESTORE="/usr/sbin/ip6tables-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + + _parse_result() { result=$("echo $1 | jsonfilter -q -e '@.result'") echo $result @@ -937,7 +954,7 @@ _vps_firewall_redirect_port() { comment="" [ -n "$src_dip" ] && { comment=" to $src_dip" - iptables-save --counters | sed "s:-d $src_dip/32::g" | iptables-restore -w + $IPTABLESSAVE --counters | sed "s:-d $src_dip/32::g" | $IPTABLESRESTORE -w } [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then @@ -1019,7 +1036,7 @@ _vps_firewall_redirect_port() { comment="" [ -n "$src_dip" ] && { comment=" to $src_dip" - iptables-save --counters | sed "s:-d $src_dip/32::g" | iptables-restore -w + $IPTABLESSAVE --counters | sed "s:-d $src_dip/32::g" | $IPTABLESRESTORE -w } [ -n "$src_ip" ] && comment=" from $src_ip" checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") @@ -1791,7 +1808,7 @@ _count_server() { serversnb=$((serversnb+1)) } -_config_service() { +_get_token() { servername=$1 [ -z "$(uci -q get openmptcprouter.${servername}.username)" ] && return [ -z "$(uci -q get openmptcprouter.${servername}.password)" ] && return @@ -1799,7 +1816,6 @@ _config_service() { [ -z "$(uci -q get openmptcprouter.${servername}.ip)" ] && return [ "$(uci -q get openmptcprouter.${servername}.disabled)" = "1" ] && return token="" - vps_config="" _login [ -z "$token" ] && { reason="" @@ -1840,8 +1856,15 @@ _config_service() { uci -q batch <<-EOF >/dev/null set openmptcprouter.${servername}.admin_error=1 EOF - return } + echo $token +} + +_config_service() { + servername=$1 + vps_config="" + token=$(_get_token $servername) + [ -z "$token" ] && return error=0 if [ -n "$serial" ]; then [ -z "$vps_config" ] && vps_config=$(_get_json "config?serial=${serial}") @@ -1958,6 +1981,11 @@ set_pihole() { config_foreach _set_pihole_server server } +token() { + config_load openmptcprouter + config_foreach _get_token server +} + start_service() { serversnb=0 wanips="" From 2b61393baced5b6ce84680071b599a235a5237e0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 26 Sep 2022 21:06:30 +0200 Subject: [PATCH 0858/2059] reload openmptcprouter-vps less often --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 6fcf197d5..ad325a68e 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2006,7 +2006,8 @@ start_service() { } service_triggers() { - procd_add_reload_trigger openmptcprouter network shadowsocks-libev v2ray glorytun glorytun-udp mlspn openvpn dsvpn + #procd_add_reload_trigger openmptcprouter network shadowsocks-libev v2ray glorytun glorytun-udp mlvpn openvpn dsvpn + procd_add_reload_trigger shadowsocks-libev v2ray glorytun glorytun-udp mlvpn dsvpn procd_add_config_trigger "config.change" "firewall" /etc/init.d/openmptcprouter-vps set_vps_firewall #procd_add_config_trigger "config.change" "network" /etc/init.d/openmptcprouter-vps set_gre_tunnel #procd_add_reload_trigger openmptcprouter shadowsocks-libev network upnpd From dc6ae5907f399aa9119021afd551b066335616e0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 27 Sep 2022 21:09:17 +0200 Subject: [PATCH 0859/2059] Fix OpenMPTCProuter VPS script --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index ad325a68e..df34db4d3 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1857,13 +1857,16 @@ _get_token() { set openmptcprouter.${servername}.admin_error=1 EOF } - echo $token + echo "$server:$serverport:$token" } _config_service() { servername=$1 vps_config="" - token=$(_get_token $servername) + servertoken=$(_get_token $servername) + server="$(echo $tokenserver | cut -f1 -d:)" + serverport="$(echo $tokenserver | cut -f2 -d:)" + token="$(echo $tokenserver | cut -f3 -d:)" [ -z "$token" ] && return error=0 if [ -n "$serial" ]; then From 1c41df07c4c9e96ce3628a0e5ca5d8d0ddd57647 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Sep 2022 20:42:01 +0200 Subject: [PATCH 0860/2059] Fix mptcp version and openmptcprouter-vps script --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index df34db4d3..db37d8045 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -757,7 +757,8 @@ _set_mptcp_vps() { scheduler="$(uci -q get network.globals.mptcp_scheduler)" syn_retries="$(uci -q get network.globals.mptcp_syn_retries)" congestion="$(uci -q get network.globals.congestion)" - mptcp_version="0" + mptcp_version="$(uci -q get network.globals.mptcp_version)" + [ -z "$mptcp_version" ] && mptcp_version="0" [ ! -f /proc/sys/net/mptcp/mptcp_enabled ] && mptcp_version="1" [ -z "$congestion" ] && congestion="bbr" if [ "$mptcp_enabled_current" != "$mptcp_enabled" ] || [ "$checksum_current" != "$checksum" ] || ([ "$path_manager_current" != "" ] && [ "$path_manager_current" != "$path_manager" ]) || ([ "$scheduler_current" != "" ] && [ "$scheduler_current" != "$scheduler" ]) || ([ "$syn_retries_current" != "" ] && [ "$syn_retries_current" != "$syn_retries" ]) || [ "$congestion_control_current" != "$congestion" ] || [ "$mptcp_version_current" != "$mptcp_version" ]; then @@ -1863,7 +1864,7 @@ _get_token() { _config_service() { servername=$1 vps_config="" - servertoken=$(_get_token $servername) + tokenserver=$(_get_token $servername) server="$(echo $tokenserver | cut -f1 -d:)" serverport="$(echo $tokenserver | cut -f2 -d:)" token="$(echo $tokenserver | cut -f3 -d:)" From bd97c3d15ed39f72932516b2e1fe53fbfccaa4f3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Sep 2022 20:42:22 +0200 Subject: [PATCH 0861/2059] Disable openvpn bonding --- .../luasrc/view/openmptcprouter/wizard.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index d3cb34a89..cd1b585b9 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -381,7 +381,7 @@ <% if nixio.fs.access("/usr/sbin/mlvpn") then %><% end %> <% if nixio.fs.access("/usr/sbin/ubond") then %><% end %> <% if nixio.fs.access("/etc/init.d/openvpn") then %><% end %> - <% if nixio.fs.access("/etc/init.d/openvpnbonding") then %><% end %> + <% end @@ -535,7 +535,7 @@
    <%:Interfaces settings%> -
    <%:You must disable DHCP on your modems and set IP in different networks.%>
    + <% for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() From a427152a96e98e2216120eb68aa4b84b3c1c4e28 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Sep 2022 08:57:51 +0200 Subject: [PATCH 0862/2059] Fix Shadowsocks tracker --- omr-tracker/files/bin/omr-tracker-ss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index 50337a094..ad12bdf13 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -6,10 +6,10 @@ basename="$(basename $0)" if [ -f /usr/sbin/iptables-legacy ]; then IPTABLES="/usr/sbin/iptables-legacy" - IPTABLESAVE="/usr/sbin/iptables-legacy-save" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" else IPTABLES="/usr/sbin/iptables" - IPTABLESAVE="/usr/sbin/iptables-save" + IPTABLESSAVE="/usr/sbin/iptables-save" fi From 8404d5e0e4511c457a306dd675863140e375fce3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Sep 2022 19:40:21 +0200 Subject: [PATCH 0863/2059] Change luci-app-firewall dependencies --- luci-app-firewall/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-firewall/Makefile b/luci-app-firewall/Makefile index 372169986..e6e891e2d 100644 --- a/luci-app-firewall/Makefile +++ b/luci-app-firewall/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Firewall and Portforwarding application -LUCI_DEPENDS:=+firewall +LUCI_DEPENDS:=+@LINUX_5_4:firewall +@LINUX_5_15:uci-firewall PKG_LICENSE:=Apache-2.0 PKG_VERSION:=omr-202103 From 66310e38665f4d25f8dd27cc88113534fa924522 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 3 Oct 2022 14:03:40 +0200 Subject: [PATCH 0864/2059] MPTCP Luci interface, set MPTCP version with select option --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index b95eca4ff..6c9091033 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -44,9 +44,9 @@ if uname.release:sub(1,4) ~= "5.15" then o.rmempty = false end if uname.release:sub(1,4) ~= "5.15" then - o = s:option(Value, "mptcp_version", translate("Multipath TCP version")) - o.datatype = "uinteger" - o.rmempty = false + o = s:option(ListValue, "mptcp_version", translate("Multipath TCP version")) + o:value(0, translate("0")) + o:value(1, translate("1")) o.default = 0 end o = s:option(ListValue, "congestion", translate("Congestion Control"),translate("Default is cubic")) From 6008b81460afbc7539ca7a8d4de742f21338bea7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Oct 2022 08:39:48 +0200 Subject: [PATCH 0865/2059] Restart dnsmasq if needed --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 156f928dd..cc5431c33 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1594,7 +1594,13 @@ if [ -f /etc/init.d/glorytun-udp ] && [ "$(pgrep glorytun-udp)" = "" ] && [ "$(u sleep 5 fi +if [ "$(pgrep dnsmasq)" = "" ] && [ -f /etc/init.d/dnsmasq ]; then + _log "Can't find dnsmasq, restart it..." + /etc/init.d/dnsmasq restart 2>&1 >/dev/null + sleep 5 +fi if [ "$(pgrep unbound)" = "" ] && [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then + _log "Can't find unbound, restart it..." /etc/init.d/unbound restart 2>&1 >/dev/null sleep 5 fi From 410791e5302a06fbfd8c62147b3624cc8d264dc5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 17 Oct 2022 08:13:31 +0200 Subject: [PATCH 0866/2059] Fix error in Github Actions --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4ab1b4b77..911a89452 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -83,7 +83,7 @@ jobs: run: | make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source target/install -j$(nproc) || make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source target/install -j1 V=s - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ${{ matrix.OMR_TARGET }} path: /home/runner/work/omr/${{ matrix.OMR_TARGET }}/${{ matrix.OMR_KERNEL }}/source/bin From 5195a71f6a95843e7abcbc58093052014cc41664 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 17 Oct 2022 08:14:06 +0200 Subject: [PATCH 0867/2059] Should fix #2615 --- https-dns-proxy/files/https-dns-proxy.init | 1 + 1 file changed, 1 insertion(+) diff --git a/https-dns-proxy/files/https-dns-proxy.init b/https-dns-proxy/files/https-dns-proxy.init index 709999b13..ef0ffc7d2 100755 --- a/https-dns-proxy/files/https-dns-proxy.init +++ b/https-dns-proxy/files/https-dns-proxy.init @@ -191,6 +191,7 @@ dnsmasq_create_server_backup() { uci -q del_list "dhcp.${cfg}.server=$i" fi done + uci -q del_list "dhcp.${cfg}.server=127.0.0.1#5353" fi return 0 } From 70c25569e7187c07daeac54fb8fe1ba6d1793683 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 17 Oct 2022 08:14:40 +0200 Subject: [PATCH 0868/2059] Commit only when needed --- .../share/omr/post-tracking.d/post-tracking | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index cc5431c33..9aa5a2c43 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -966,7 +966,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ -n "$OMR_TRACKER_INTERFACE" ]; then uci -q delete openmptcprouter.$OMR_TRACKER_INTERFACE.lc fi - uci -q commit openmptcprouter + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter #ubus call network reload # Set a little sleep after an interface error @@ -1038,7 +1038,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om else uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") fi - uci -q commit openmptcprouter + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi nbserver=0 piholeenabled=0 @@ -1053,7 +1053,7 @@ fi if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" != "up" ]; then uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' - uci -q commit openmptcprouter + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi exit 0 fi @@ -1517,7 +1517,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC uci -q commit openmptcprouter else [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Get status and settings for $OMR_TRACKER_INTERFACE... Done" - uci -q commit openmptcprouter + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter if [ "$(pgrep openmptcprouter-vps)" = "" ] && ( [ "$(uci -q get openmptcprouter.settings.apilc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.settings.apilc))) -gt 3600 ] ); then _log "Check API configuration..." /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 @@ -1553,8 +1553,8 @@ fi uci -q set openmptcprouter.settings.master="change" fi if [ "$(uci -q get openmptcprouter.settings.master)" != "dynamic" ]; then - uci -q commit network - uci -q commit openmptcprouter + [ -n "$(uci -q changes network)" ] && uci -q commit network + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi _log "Change master interface from $masterintf ($masterlatency ms) to $OMR_TRACKER_INTERFACE ($OMR_TRACKER_LATENCY ms)" fi @@ -1671,7 +1671,7 @@ set_get_config() { if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ]; then config_load openmptcprouter config_foreach set_get_config server - uci -q commit openmptcprouter + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then @@ -1682,13 +1682,13 @@ fi if [ "$(uci -q get glorytun.vpn.enable)" = "1" ] && [ "$(uci -q get glorytun.vpn.key)" = "" ]; then config_load openmptcprouter config_foreach set_get_config server - uci -q commit openmptcprouter + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ "$(uci -q get v2ray.omrout.s_vless_user_id)" = "" ]; then config_load openmptcprouter config_foreach set_get_config server - uci -q commit openmptcprouter + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then From 7046310f7cb419c0ab8d1ae6443fd8bf77146220 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 19 Oct 2022 19:28:04 +0200 Subject: [PATCH 0869/2059] Update iperf3 --- iperf3/Makefile | 4 +-- iperf3/patches/remove-in6_flowlabel_req.patch | 25 ------------------- 2 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 iperf3/patches/remove-in6_flowlabel_req.patch diff --git a/iperf3/Makefile b/iperf3/Makefile index cf0d6599c..4501eede8 100644 --- a/iperf3/Makefile +++ b/iperf3/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iperf -PKG_VERSION:=3.11 +PKG_VERSION:=3.12 PKG_RELEASE:=10 PKG_SOURCE:=$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/esnet/iperf/archive/refs/tags/ -PKG_HASH:=96e909c0d3ab6034c52328c2954fb3934aaff349395c4bc2611dcd50e6b89875 +PKG_HASH:=e38e0a97b30a97b4355da93467160a20dea10932f6c17473774802e03d61d4a7 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=BSD-3-Clause diff --git a/iperf3/patches/remove-in6_flowlabel_req.patch b/iperf3/patches/remove-in6_flowlabel_req.patch deleted file mode 100644 index 539f9c3c8..000000000 --- a/iperf3/patches/remove-in6_flowlabel_req.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/src/flowlabel.h 2021-06-24 13:26:33.142463630 +0200 -+++ b/src/flowlabel.h 2021-06-24 13:27:45.669235179 +0200 -@@ -37,21 +37,21 @@ - conflicts with "netinet/in.h" . - */ - --#ifndef __ANDROID__ -+#ifndef _LINUX_IN6_H - struct in6_flowlabel_req - { - struct in6_addr flr_dst; - __u32 flr_label; - __u8 flr_action; - __u8 flr_share; - __u16 flr_flags; - __u16 flr_expires; - __u16 flr_linger; - __u32 __flr_pad; - /* Options in format of IPV6_PKTOPTIONS */ - }; - #endif - - #define IPV6_FL_A_GET 0 - #define IPV6_FL_A_PUT 1 - #define IPV6_FL_A_RENEW 2 From f8ee275ab38adadcaf2194cc766001c6c8ce43c9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 20 Oct 2022 10:22:01 +0200 Subject: [PATCH 0870/2059] Update libmbim --- libmbim/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index 505ae7bc6..6c9766480 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_VERSION:=1.26.2 +PKG_VERSION:=1.26.4 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/libmbim -PKG_HASH:=10c77bf5b5eb8c92ba80e9b519923ad9b898362bc8e1928e2bc9a17eeba649af +PKG_HASH:=f688cec4c4586a17575f5e327448ce62f2000ef6a07c9e4589873d4a68568ad9 PKG_MAINTAINER:=Nicholas Smith From 0f092db924969b1fbb1d476d293e2b05d829bc02 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 20 Oct 2022 10:22:09 +0200 Subject: [PATCH 0871/2059] Update libqmi --- libqmi/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libqmi/Makefile b/libqmi/Makefile index d3ebdeecd..7cb640ea8 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqmi -PKG_VERSION:=1.30.4 +PKG_VERSION:=1.30.8 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/libqmi -PKG_HASH:=00d7da30a4f8d1185f37cba289cfaf1dfcd04a58f2f76d6acfdf5b85312d6ed6 +PKG_HASH:=862482ce9e3ad0bd65d264334ee311cdb94b9df2863b5b7136309b41b8ac1990 PKG_MAINTAINER:=Nicholas Smith From 570af8dff550b3eb056d476853ce886600de82ee Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 20 Oct 2022 10:22:29 +0200 Subject: [PATCH 0872/2059] Update ModemManager --- modemmanager/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 3eb780398..9d6e1174a 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_VERSION:=1.18.6 +PKG_VERSION:=1.18.12 PKG_RELEASE:=1 PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager -PKG_HASH:=d4f804b31cf504239c5f1d4973c62095c00cba1ee9abb503718dac6d146a470a +PKG_HASH:=b464e4925d955a6ca86dd08616e763b26ae46d7fd37dbe281678e34065b1e430 PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION) PKG_MAINTAINER:=Nicholas Smith From a74e9a455c8a3f9166e4cd918c4ca9e94a56bbcc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 20 Oct 2022 10:22:59 +0200 Subject: [PATCH 0873/2059] Update ndpi-netfilter2 --- ndpi-netfilter2/Makefile | 5 +- .../patches/add_streaming_service.patch | 114 ++++++++++++++++++ 2 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 ndpi-netfilter2/patches/add_streaming_service.patch diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 13ebc5f14..de684c287 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -1,6 +1,6 @@ # # Based on package from https://github.com/openwrt-develop/ndpi-netfilter/ -# Copyright (C) 2018-2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Copyright (C) 2018-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -11,7 +11,8 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=3 -PKG_REV:=b19e6392cf0c7d51c44e076a91fc4db0cbbd6403 +#PKG_REV:=b19e6392cf0c7d51c44e076a91fc4db0cbbd6403 +PKG_REV:=ad41165daf477f9f575819782d8e19adb772fbbd PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git diff --git a/ndpi-netfilter2/patches/add_streaming_service.patch b/ndpi-netfilter2/patches/add_streaming_service.patch new file mode 100644 index 000000000..21133573e --- /dev/null +++ b/ndpi-netfilter2/patches/add_streaming_service.patch @@ -0,0 +1,114 @@ +From 9aeb879f3ffb9f854c574936740fa61620886063 Mon Sep 17 00:00:00 2001 +From: root +Date: Fri, 16 Sep 2022 13:29:46 -0500 +Subject: [PATCH] Added streaming services as protos to nDPI + +* Apple TV+ +* DirecTV +* HBO +* Vudu +* Showtime +* Dailymotion +* Livestream +* Tencent Video +* IHeart Radio +* Tidal +* TuneIn +* SiriusXM Radio + +Domains based on https://www.netify.ai/resources/applications +--- + src/include/ndpi_protocol_ids.h | 12 +++++++ + src/lib/ndpi_content_match.c.inc | 56 ++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+) + +diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h +index 256fd8f24f..94d621d0c9 100644 +--- a/src/include/ndpi_protocol_ids.h ++++ b/src/include/ndpi_protocol_ids.h +@@ -340,6 +340,18 @@ + NDPI_PROTOCOL_KISMET = 309, + NDPI_PROTOCOL_FASTCGI = 310, + NDPI_PROTOCOL_FTPS = 311, ++ NDPI_PROTOCOL_APPLETVPLUS = 306, ++ NDPI_PROTOCOL_DIRECTV = 307, ++ NDPI_PROTOCOL_HBO = 308, ++ NDPI_PROTOCOL_VUDU = 309, ++ NDPI_PROTOCOL_SHOWTIME = 310, ++ NDPI_PROTOCOL_DAILYMOTION = 311, ++ NDPI_PROTOCOL_LIVESTREAM = 312, ++ NDPI_PROTOCOL_TENCENTVIDEO = 313, ++ NDPI_PROTOCOL_IHEARTRADIO = 314, ++ NDPI_PROTOCOL_TIDAL = 315, ++ NDPI_PROTOCOL_TUNEIN = 316, ++ NDPI_PROTOCOL_SIRIUSXMRADIO = 317, + + #ifdef CUSTOM_NDPI_PROTOCOLS + #include "../../../nDPI-custom/custom_ndpi_protocol_ids.h" +diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc +index eb320df253..161fd77f4f 100644 +--- a/src/lib/ndpi_content_match.c.inc ++++ b/src/lib/ndpi_content_match.c.inc +@@ -1703,6 +1703,62 @@ ndpi_protocol_match host_match[] = + + { "cachefly.com", "CacheFly", NDPI_PROTOCOL_CACHEFLY, NDPI_PROTOCOL_CATEGORY_CLOUD, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DEFAULT_LEVEL }, + ++ { "tv.apple.com", "AppleTVPlus", NDPI_PROTOCOL_APPLETVPLUS, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "tv.g.apple.com", "AppleTVPlus", NDPI_PROTOCOL_APPLETVPLUS, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "tv.v.aaplimg.com", "AppleTVPlus", NDPI_PROTOCOL_APPLETVPLUS, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "directv.com", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "directvnow.com", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "dtvbb.tv", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "dtvce.com", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "hbo.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbogo.co.th", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbogo.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbogo.eu", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbogoasia.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbogoasia.id", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbogoasia.ph", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbomax.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbomaxcdn.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "hbonow.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "maxgo.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "vudu.com", "Vudu", NDPI_PROTOCOL_VUDU, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { ".showtime.com", "Showtime", NDPI_PROTOCOL_SHOWTIME, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "dai.ly", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "dailymotion.com", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "dailymotionadvertising.com", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "dmcdn.net", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "dmxleo.com", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { ".livestream.com", "Livestream", NDPI_PROTOCOL_LIVESTREAM, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "v.qq.com", "Tencentvideo", NDPI_PROTOCOL_TENCENTVIDEO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "937theriver.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "iheart.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "iheart.mx", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "iheartmedia.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "iheartradio.ca", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "iheartradio.co.nz", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "iheartradio.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "ihrdev.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "ihrhls.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "ihrint.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "ihrstage.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { ".tidal.com", "Tidal", NDPI_PROTOCOL_TIDAL, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "radiotime.com", "TuneIn", NDPI_PROTOCOL_TUNEIN, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "tunein.com", "TuneIn", NDPI_PROTOCOL_TUNEIN, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "tunenet.io", "TuneIn", NDPI_PROTOCOL_TUNEIN, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ ++ { "siriusxm.ca", "SiriusXMRadio", NDPI_PROTOCOL_SIRIUSXMRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ { "siriusxm.com", "SiriusXMRadio", NDPI_PROTOCOL_SIRIUSXMRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, ++ + #ifdef CUSTOM_NDPI_PROTOCOLS + #include "../../../nDPI-custom/custom_ndpi_content_match_host_match.c.inc" + #endif From 43c844fe7ef23099fe82256ce4b981db024c036d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 20 Oct 2022 10:23:27 +0200 Subject: [PATCH 0874/2059] Update v2fly --- v2ray-core/Config.in | 2 +- v2ray-core/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/v2ray-core/Config.in b/v2ray-core/Config.in index 20a764336..53c714859 100644 --- a/v2ray-core/Config.in +++ b/v2ray-core/Config.in @@ -23,7 +23,7 @@ config V2RAY_EXCLUDE_V2CTL config V2RAY_EXCLUDE_ASSETS bool "Exclude geoip.dat & geosite.dat" - default n + default y config V2RAY_COMPRESS_UPX bool "Compress executable files with UPX" diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index beb3bd2f4..08a9d018d 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -9,13 +9,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=v2ray-core -PKG_VERSION:=4.43.0 +PKG_VERSION:=4.45.2 PKG_RELEASE:=1 #PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=v$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/refs/tags/ -PKG_HASH:=f27b8fe8e1e102b0297339ee368c8b650fde0f949e0d90e1229ff6744f99ba0f +PKG_HASH:=7a126bac7df32f627f34331778cb39ac99db18d7edcd45628db06e123fa0694b PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE From 8834808de2ca14ba1e8f41433048d82bbac59409 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 26 Oct 2022 20:09:23 +0200 Subject: [PATCH 0875/2059] Change MPTCP default setting --- mptcp/files/etc/uci-defaults/mptcp-defaults | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/uci-defaults/mptcp-defaults b/mptcp/files/etc/uci-defaults/mptcp-defaults index 97235fb8d..594086874 100755 --- a/mptcp/files/etc/uci-defaults/mptcp-defaults +++ b/mptcp/files/etc/uci-defaults/mptcp-defaults @@ -7,7 +7,7 @@ if [ "$(uci -q get network.globals.mptcp_path_manager)" = "" ]; then set network.globals.congestion='cubic' set network.globals.mptcp_checksum=0 set network.globals.mptcp_debug=0 - set network.globals.mptcp_syn_retries=2 + set network.globals.mptcp_syn_retries=4 set network.globals.mptcp_subflows=3 set network.globals.mptcp_add_addr_accepted=1 set network.globals.mptcp_add_addr_timeout=120 From bb6cb0e8ae85e9a80aaedf35f7acdee1ceb4f7c1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 26 Oct 2022 20:09:53 +0200 Subject: [PATCH 0876/2059] Update for Github Actions --- .github/workflows/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 911a89452..20fbf85f6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,10 +17,10 @@ jobs: - name: Branch name id: branch_name run: | - echo ::set-output name=SOURCE_NAME::${GITHUB_REF#refs/*/} - echo ::set-output name=SOURCE_BRANCH::${GITHUB_REF#refs/heads/} - echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/} - echo ::set-output name=WORKSPACE::${GITHUB_WORKSPACE} + echo "SOURCE_NAME=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT + echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT + echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + echo "WORKSPACE=${GITHUB_WORKSPACE}" >> $GITHUB_OUTPUT - name: Prepare run: | sudo apt-get update From 82f8b3c838551a695c4b1b4bcecc094000fbcb2d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Nov 2022 18:10:09 +0100 Subject: [PATCH 0877/2059] Small IPv6 fixes --- luci-app-omr-dscp/root/etc/init.d/omr-dscp | 2 +- v2ray-core/files/etc/init.d/v2ray | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-omr-dscp/root/etc/init.d/omr-dscp b/luci-app-omr-dscp/root/etc/init.d/omr-dscp index 4997e1cbc..63dd5e19b 100755 --- a/luci-app-omr-dscp/root/etc/init.d/omr-dscp +++ b/luci-app-omr-dscp/root/etc/init.d/omr-dscp @@ -22,7 +22,7 @@ _ipt4() { iptables -w -t mangle "$@" 2>&1 >/dev/null } _ipt6() { - ip6tables -w -t mangle "$@" >/dev/null + ip6tables -w -t mangle "$@" 2>&1 >/dev/null } _add_dscp_rule() { diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index 3cd9e8740..e0af11346 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -1,7 +1,7 @@ #!/bin/sh /etc/rc.common # # Copyright 2019-2020 Xingwang Liao -# Copyright 2020-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Copyright 2020-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter # Licensed to the public under the MIT License. # @@ -2102,7 +2102,7 @@ rules_up() { OUTBOUND_SERVERS_V4="$(uci -q get v2ray.omrout.s_vless_address)" OUTBOUND_SERVERS_V6="$(uci -q get v2ray.omrout.s_vless_address)" TRANSPARENT_PROXY_PORT="$(uci -q get v2ray.omr.port)" - [ -n "$OUTBOUND_SERVERS_V4" ] && { + [ -n "$OUTBOUND_SERVERS_V4" ] || [ -n "$OUTBOUND_SERVERS_V6" ] && { logger -t "v2ray" "Rules UP" add_v2ray_redirect_rules } From 5f0b7918103e0bbde8d95914285e0b1b63bfc883 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 16 Nov 2022 20:08:36 +0100 Subject: [PATCH 0878/2059] Update r8125 and r8168 drivers --- r8125/Makefile | 24 +- r8125/src/Makefile | 197 - r8125/src/Makefile_linux24x | 75 - r8125/src/r8125.h | 2508 ------ r8125/src/r8125_dash.h | 261 - r8125/src/r8125_firmware.c | 264 - r8125/src/r8125_firmware.h | 68 - r8125/src/r8125_n.c | 15150 ---------------------------------- r8125/src/r8125_ptp.c | 594 -- r8125/src/r8125_ptp.h | 81 - r8125/src/r8125_realwow.h | 118 - r8125/src/r8125_rss.c | 481 -- r8125/src/r8125_rss.h | 69 - r8125/src/rtl_eeprom.c | 289 - r8125/src/rtl_eeprom.h | 53 - r8125/src/rtltool.c | 320 - r8125/src/rtltool.h | 86 - r8168/Makefile | 8 +- 18 files changed, 12 insertions(+), 20634 deletions(-) delete mode 100755 r8125/src/Makefile delete mode 100755 r8125/src/Makefile_linux24x delete mode 100755 r8125/src/r8125.h delete mode 100755 r8125/src/r8125_dash.h delete mode 100755 r8125/src/r8125_firmware.c delete mode 100755 r8125/src/r8125_firmware.h delete mode 100755 r8125/src/r8125_n.c delete mode 100755 r8125/src/r8125_ptp.c delete mode 100755 r8125/src/r8125_ptp.h delete mode 100755 r8125/src/r8125_realwow.h delete mode 100755 r8125/src/r8125_rss.c delete mode 100755 r8125/src/r8125_rss.h delete mode 100755 r8125/src/rtl_eeprom.c delete mode 100755 r8125/src/rtl_eeprom.h delete mode 100755 r8125/src/rtltool.c delete mode 100755 r8125/src/rtltool.h diff --git a/r8125/Makefile b/r8125/Makefile index e9b213c6e..befd2aabb 100644 --- a/r8125/Makefile +++ b/r8125/Makefile @@ -7,10 +7,14 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=r8125 -PKG_VERSION:=9.006.04 +PKG_VERSION:=9.010.01-1 PKG_RELEASE:=$(AUTORELEASE) -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/awesometic/realtek-r8125-dkms/tar.gz/$(PKG_VERSION)? +PKG_HASH:=81fb9a100e6cefb421557639b476fd03af61a99c55bc8fb03c6e396532bd0944 +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/realtek-$(PKG_NAME)-dkms-$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk @@ -18,7 +22,7 @@ define KernelPackage/r8125 TITLE:=Driver for Realtek r8125 chipsets SUBMENU:=Network Devices VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) - FILES:= $(PKG_BUILD_DIR)/r8125.ko + FILES:= $(PKG_BUILD_DIR)/src/r8125.ko AUTOLOAD:=$(call AutoProbe,r8125) endef @@ -26,20 +30,8 @@ define Package/r8125/description This package contains a driver for Realtek r8125 chipsets. endef -R8125_MAKEOPTS= -C $(PKG_BUILD_DIR) \ - PATH="$(TARGET_PATH)" \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - TARGET="$(HAL_TARGET)" \ - TOOLPREFIX="$(KERNEL_CROSS)" \ - TOOLPATH="$(KERNEL_CROSS)" \ - KERNELPATH="$(LINUX_DIR)" \ - KERNELDIR="$(LINUX_DIR)" \ - LDOPTS=" " \ - DOMULTI=1 - define Build/Compile - $(MAKE) $(R8125_MAKEOPTS) modules + +$(KERNEL_MAKE) M=$(PKG_BUILD_DIR)/src modules endef $(eval $(call KernelPackage,r8125)) diff --git a/r8125/src/Makefile b/r8125/src/Makefile deleted file mode 100755 index 514c0acdd..000000000 --- a/r8125/src/Makefile +++ /dev/null @@ -1,197 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ - -################################################################################ -# This product is covered by one or more of the following patents: -# US6,570,884, US6,115,776, and US6,327,625. -################################################################################ - -CONFIG_SOC_LAN = n -ENABLE_REALWOW_SUPPORT = n -ENABLE_DASH_SUPPORT = n -ENABLE_DASH_PRINTER_SUPPORT = n -CONFIG_DOWN_SPEED_100 = n -CONFIG_ASPM = y -ENABLE_S5WOL = y -ENABLE_S5_KEEP_CURR_MAC = n -ENABLE_EEE = y -ENABLE_S0_MAGIC_PACKET = n -ENABLE_TX_NO_CLOSE = y -ENABLE_MULTIPLE_TX_QUEUE = n -ENABLE_PTP_SUPPORT = n -ENABLE_PTP_MASTER_MODE = n -ENABLE_RSS_SUPPORT = y -ENABLE_LIB_SUPPORT = n -ENABLE_USE_FIRMWARE_FILE = n -DISABLE_PM_SUPPORT = n -DISABLE_MULTI_MSIX_VECTOR = n - -ifneq ($(KERNELRELEASE),) - obj-m := r8125.o - r8125-objs := r8125_n.o rtl_eeprom.o rtltool.o - ifeq ($(CONFIG_SOC_LAN), y) - EXTRA_CFLAGS += -DCONFIG_SOC_LAN - endif - ifeq ($(ENABLE_REALWOW_SUPPORT), y) - r8125-objs += r8125_realwow.o - EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT - endif - ifeq ($(ENABLE_DASH_SUPPORT), y) - r8125-objs += r8125_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT - endif - ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) - r8125-objs += r8125_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT - endif - EXTRA_CFLAGS += -DCONFIG_R8125_NAPI - EXTRA_CFLAGS += -DCONFIG_R8125_VLAN - ifeq ($(CONFIG_DOWN_SPEED_100), y) - EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 - endif - ifeq ($(CONFIG_ASPM), y) - EXTRA_CFLAGS += -DCONFIG_ASPM - endif - ifeq ($(ENABLE_S5WOL), y) - EXTRA_CFLAGS += -DENABLE_S5WOL - endif - ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) - EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC - endif - ifeq ($(ENABLE_EEE), y) - EXTRA_CFLAGS += -DENABLE_EEE - endif - ifeq ($(ENABLE_S0_MAGIC_PACKET), y) - EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET - endif - ifeq ($(ENABLE_TX_NO_CLOSE), y) - EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE - endif - ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y) - EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE - endif - ifeq ($(ENABLE_PTP_SUPPORT), y) - r8125-objs += r8125_ptp.o - EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT - endif - ifeq ($(ENABLE_PTP_MASTER_MODE), y) - EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE - endif - ifeq ($(ENABLE_RSS_SUPPORT), y) - r8125-objs += r8125_rss.o - EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT - endif - ifeq ($(ENABLE_LIB_SUPPORT), y) - r8125-objs += r8125_lib.o - EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT - endif - ifeq ($(ENABLE_USE_FIRMWARE_FILE), y) - r8125-objs += r8125_firmware.o - EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE - endif - ifeq ($(DISABLE_PM_SUPPORT), y) - EXTRA_CFLAGS += -DDISABLE_PM_SUPPORT - endif - ifeq ($(DISABLE_MULTI_MSIX_VECTOR), y) - EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR - endif -else - BASEDIR := /lib/modules/$(shell uname -r) - KERNELDIR ?= $(BASEDIR)/build - PWD :=$(shell pwd) - DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net/ethernet -name realtek -type d) - ifeq ($(DRIVERDIR),) - DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net -name realtek -type d) - endif - ifeq ($(DRIVERDIR),) - DRIVERDIR := $(BASEDIR)/kernel/drivers/net - endif - RTKDIR := $(subst $(BASEDIR)/,,$(DRIVERDIR)) - - KERNEL_GCC_VERSION := $(shell cat /proc/version | sed -n 's/.*gcc version \([[:digit:]]\.[[:digit:]]\.[[:digit:]]\).*/\1/p') - CCVERSION = $(shell $(CC) -dumpversion) - - KVER = $(shell uname -r) - KMAJ = $(shell echo $(KVER) | \ - sed -e 's/^\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*.*/\1/') - KMIN = $(shell echo $(KVER) | \ - sed -e 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*.*/\1/') - KREV = $(shell echo $(KVER) | \ - sed -e 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/') - - kver_ge = $(shell \ - echo test | awk '{if($(KMAJ) < $(1)) {print 0} else { \ - if($(KMAJ) > $(1)) {print 1} else { \ - if($(KMIN) < $(2)) {print 0} else { \ - if($(KMIN) > $(2)) {print 1} else { \ - if($(KREV) < $(3)) {print 0} else { print 1 } \ - }}}}}' \ - ) - -.PHONY: all -all: print_vars clean modules install - -print_vars: - @echo - @echo "CC: " $(CC) - @echo "CCVERSION: " $(CCVERSION) - @echo "KERNEL_GCC_VERSION: " $(KERNEL_GCC_VERSION) - @echo "KVER: " $(KVER) - @echo "KMAJ: " $(KMAJ) - @echo "KMIN: " $(KMIN) - @echo "KREV: " $(KREV) - @echo "BASEDIR: " $(BASEDIR) - @echo "DRIVERDIR: " $(DRIVERDIR) - @echo "PWD: " $(PWD) - @echo "RTKDIR: " $(RTKDIR) - @echo - -.PHONY:modules -modules: -#ifeq ($(call kver_ge,5,0,0),1) - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules -#else -# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules -#endif - -.PHONY:clean -clean: -#ifeq ($(call kver_ge,5,0,0),1) - $(MAKE) -C $(KERNELDIR) M=$(PWD) clean -#else -# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean -#endif - -.PHONY:install -install: -#ifeq ($(call kver_ge,5,0,0),1) - $(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install -#else -# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install -#endif - -endif diff --git a/r8125/src/Makefile_linux24x b/r8125/src/Makefile_linux24x deleted file mode 100755 index d043fb00c..000000000 --- a/r8125/src/Makefile_linux24x +++ /dev/null @@ -1,75 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ - -################################################################################ -# This product is covered by one or more of the following patents: -# US6,570,884, US6,115,776, and US6,327,625. -################################################################################ - -CC := gcc -LD := ld -ARCH := $(shell uname -m | sed 's/i.86/i386/') -KSRC := /lib/modules/$(shell uname -r)/build -CONFIG_FILE := $(KSRC)/include/linux/autoconf.h -KMISC := /lib/modules/$(shell uname -r)/kernel/drivers/net/ - - -ifeq ($(ARCH),x86_64) - MODCFLAGS += -mcmodel=kernel -mno-red-zone -endif - -#standard flags for module builds -MODCFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall -MODCFLAGS += -I$(KSRC)/include -I. -MODCFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h -SOURCE := r8125_n.c rtl_eeprom.c rtltool.c -OBJS := $(SOURCE:.c=.o) - - -SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \ - grep CONFIG_SMP | awk '{print $$3}') - -ifneq ($(SMP),1) - SMP := 0 -endif - -ifeq ($(SMP),1) - MODCFLAGS += -D__SMP__ -endif - -modules: $(OBJS) - $(LD) -r $^ -o r8125.o - strip --strip-debug r8125.o - -%.o: %.c - $(CC) $(MODCFLAGS) -c $< -o $@ - -clean: - rm *.o -f - -install: - install -m 744 -c r8125.o $(KMISC) diff --git a/r8125/src/r8125.h b/r8125/src/r8125.h deleted file mode 100755 index 4875ccca4..000000000 --- a/r8125/src/r8125.h +++ /dev/null @@ -1,2508 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef __R8125_H -#define __R8125_H - -//#include -#include -#include -#include -#include "r8125_dash.h" -#include "r8125_realwow.h" -#include "r8125_ptp.h" -#include "r8125_rss.h" -#ifdef ENABLE_LIB_SUPPORT -#include "r8125_lib.h" -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) -typedef int netdev_tx_t; -#endif - -/* -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)&& !defined(ENABLE_LIB_SUPPORT) -#define RTL_USE_NEW_INTR_API -#endif -*/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define skb_transport_offset(skb) (skb->h.raw - skb->data) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -#define device_set_wakeup_enable(dev, val) do {} while (0) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) -static inline void ether_addr_copy(u8 *dst, const u8 *src) -{ - u16 *a = (u16 *)dst; - const u16 *b = (const u16 *)src; - - a[0] = b[0]; - a[1] = b[1]; - a[2] = b[2]; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) -#define IS_ERR_OR_NULL(ptr) (!ptr) -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) -#define reinit_completion(x) ((x)->done = 0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#define pm_runtime_mark_last_busy(x) -#define pm_runtime_put_autosuspend(x) pm_runtime_put(x) -#define pm_runtime_put_sync_autosuspend(x) pm_runtime_put_sync(x) - -static inline bool pm_runtime_suspended(struct device *dev) -{ - return dev->power.runtime_status == RPM_SUSPENDED - && !dev->power.disable_depth; -} - -static inline bool pm_runtime_active(struct device *dev) -{ - return dev->power.runtime_status == RPM_ACTIVE - || dev->power.disable_depth; -} -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -#define queue_delayed_work(long_wq, work, delay) schedule_delayed_work(work, delay) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netif_printk(priv, type, level, netdev, fmt, args...) \ - do { \ - if (netif_msg_##type(priv)) \ - printk(level "%s: " fmt,(netdev)->name , ##args); \ - } while (0) - -#define netif_emerg(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_EMERG, netdev, fmt, ##args) -#define netif_alert(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ALERT, netdev, fmt, ##args) -#define netif_crit(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_CRIT, netdev, fmt, ##args) -#define netif_err(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ERR, netdev, fmt, ##args) -#define netif_warn(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_WARNING, netdev, fmt, ##args) -#define netif_notice(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_NOTICE, netdev, fmt, ##args) -#define netif_info(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_INFO, (netdev), fmt, ##args) -#endif -#endif -#endif -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -#define setup_timer(_timer, _function, _data) \ -do { \ - (_timer)->function = _function; \ - (_timer)->data = _data; \ - init_timer(_timer); \ -} while (0) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) -#if defined(skb_vlan_tag_present) && !defined(vlan_tx_tag_present) -#define vlan_tx_tag_present skb_vlan_tag_present -#endif -#if defined(skb_vlan_tag_get) && !defined(vlan_tx_tag_get) -#define vlan_tx_tag_get skb_vlan_tag_get -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - -#define RTL_ALLOC_SKB_INTR(napi, length) dev_alloc_skb(length) -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#undef RTL_ALLOC_SKB_INTR -#define RTL_ALLOC_SKB_INTR(napi, length) napi_alloc_skb(napi, length) -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) -#define netdev_features_t u32 -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#else -#ifndef NETIF_F_ALL_CSUM -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#define ENABLE_R8125_PROCFS -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -#define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX -#define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -#define __devinit -#define __devexit -#define __devexit_p(func) func -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define CHECKSUM_PARTIAL CHECKSUM_HW -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define irqreturn_t void -#define IRQ_HANDLED 1 -#define IRQ_NONE 0 -#define IRQ_RETVAL(x) -#endif - -#ifndef NETIF_F_RXALL -#define NETIF_F_RXALL 0 -#endif - -#ifndef NETIF_F_RXFCS -#define NETIF_F_RXFCS 0 -#endif - -#ifndef HAVE_FREE_NETDEV -#define free_netdev(x) kfree(x) -#endif - -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) -#endif - -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) -#endif - -#ifndef SA_SHIRQ -#define SA_SHIRQ IRQF_SHARED -#endif - -#ifndef NETIF_F_GSO -#define gso_size tso_size -#define gso_segs tso_segs -#endif - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -#ifndef dma_mapping_error -#define dma_mapping_error(a,b) 0 -#endif - -#ifndef netif_err -#define netif_err(a,b,c,d) -#endif - -#ifndef AUTONEG_DISABLE -#define AUTONEG_DISABLE 0x00 -#endif - -#ifndef AUTONEG_ENABLE -#define AUTONEG_ENABLE 0x01 -#endif - -#ifndef BMCR_SPEED1000 -#define BMCR_SPEED1000 0x0040 -#endif - -#ifndef BMCR_SPEED100 -#define BMCR_SPEED100 0x2000 -#endif - -#ifndef BMCR_SPEED10 -#define BMCR_SPEED10 0x0000 -#endif - -#ifndef SPEED_UNKNOWN -#define SPEED_UNKNOWN -1 -#endif - -#ifndef DUPLEX_UNKNOWN -#define DUPLEX_UNKNOWN 0xff -#endif - -#ifndef SUPPORTED_Pause -#define SUPPORTED_Pause (1 << 13) -#endif - -#ifndef SUPPORTED_Asym_Pause -#define SUPPORTED_Asym_Pause (1 << 14) -#endif - -#ifndef MDIO_EEE_100TX -#define MDIO_EEE_100TX 0x0002 -#endif - -#ifndef MDIO_EEE_1000T -#define MDIO_EEE_1000T 0x0004 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#ifdef CONFIG_NET_POLL_CONTROLLER -#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8125_netpoll -#else -#define RTL_NET_POLL_CONTROLLER -#endif - -#ifdef CONFIG_R8125_VLAN -#define RTL_SET_VLAN dev->vlan_rx_register=rtl8125_vlan_rx_register -#else -#define RTL_SET_VLAN -#endif - -#define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8125_open; \ - dev->hard_start_xmit=rtl8125_start_xmit; \ - dev->get_stats=rtl8125_get_stats; \ - dev->stop=rtl8125_close; \ - dev->tx_timeout=rtl8125_tx_timeout; \ - dev->set_multicast_list=rtl8125_set_rx_mode; \ - dev->change_mtu=rtl8125_change_mtu; \ - dev->set_mac_address=rtl8125_set_mac_address; \ - dev->do_ioctl=rtl8125_do_ioctl; \ - RTL_NET_POLL_CONTROLLER; \ - RTL_SET_VLAN; -#else -#define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef false -#define false 0 -#endif - -#ifndef true -#define true 1 -#endif - -//Hardware will continue interrupt 10 times after interrupt finished. -#define RTK_KEEP_INTERRUPT_COUNT (10) - -//the low 32 bit address of receive buffer must be 8-byte alignment. -#ifndef NET_IP_ALIGN -#define NET_IP_ALIGN 2 -#endif -#define RTK_RX_ALIGN 8 - -#ifdef CONFIG_R8125_NAPI -#define NAPI_SUFFIX "-NAPI" -#else -#define NAPI_SUFFIX "" -#endif -#if defined(ENABLE_DASH_PRINTER_SUPPORT) -#define DASH_SUFFIX "-PRINTER" -#elif defined(ENABLE_DASH_SUPPORT) -#define DASH_SUFFIX "-DASH" -#else -#define DASH_SUFFIX "" -#endif - -#if defined(ENABLE_REALWOW_SUPPORT) -#define REALWOW_SUFFIX "-REALWOW" -#else -#define REALWOW_SUFFIX "" -#endif - -#if defined(ENABLE_PTP_SUPPORT) -#define PTP_SUFFIX "-PTP" -#else -#define PTP_SUFFIX "" -#endif - -#if defined(ENABLE_RSS_SUPPORT) -#define RSS_SUFFIX "-RSS" -#else -#define RSS_SUFFIX "" -#endif - -#define RTL8125_VERSION "9.006.04" NAPI_SUFFIX DASH_SUFFIX REALWOW_SUFFIX PTP_SUFFIX RSS_SUFFIX -#define MODULENAME "r8125" -#define PFX MODULENAME ": " - -#define GPL_CLAIM "\ -r8125 Copyright (C) 2021 Realtek NIC software team \n \ -This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ -This is free software, and you are welcome to redistribute it under certain conditions; see . \n" - -#ifdef RTL8125_DEBUG -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8125_DEBUG */ - -#define R8125_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#ifdef CONFIG_R8125_NAPI -#define rtl8125_rx_hwaccel_skb vlan_hwaccel_receive_skb -#define rtl8125_rx_quota(count, quota) min(count, quota) -#else -#define rtl8125_rx_hwaccel_skb vlan_hwaccel_rx -#define rtl8125_rx_quota(count, quota) count -#endif - -/* MAC address length */ -#ifndef MAC_ADDR_LEN -#define MAC_ADDR_LEN 6 -#endif - -#ifndef MAC_PROTOCOL_LEN -#define MAC_PROTOCOL_LEN 2 -#endif - -#ifndef ETH_FCS_LEN -#define ETH_FCS_LEN 4 -#endif - -#ifndef NETIF_F_TSO6 -#define NETIF_F_TSO6 0 -#endif - -#define Reserved2_data 7 -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST_unlimited 7 -#define TX_DMA_BURST_1024 6 -#define TX_DMA_BURST_512 5 -#define TX_DMA_BURST_256 4 -#define TX_DMA_BURST_128 3 -#define TX_DMA_BURST_64 2 -#define TX_DMA_BURST_32 1 -#define TX_DMA_BURST_16 0 -#define Reserved1_data 0x3F -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define Jumbo_Frame_1k ETH_DATA_LEN -#define Jumbo_Frame_2k (2*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_3k (3*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_4k (4*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_5k (5*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_6k (6*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_7k (7*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_8k (8*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_9k (9*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -#define RxEarly_off_V1 (0x07 << 11) -#define RxEarly_off_V2 (1 << 11) -#define Rx_Single_fetch_V2 (1 << 14) - -#define R8125_REGS_SIZE (256) -#define R8125_MAC_REGS_SIZE (256) -#define R8125_PHY_REGS_SIZE (16*2) -#define R8125_EPHY_REGS_SIZE (31*2) -#define R8125_ERI_REGS_SIZE (0x100) -#define R8125_REGS_DUMP_SIZE (0x400) -#define R8125_PCI_REGS_SIZE (0x100) -#define R8125_NAPI_WEIGHT 64 - -#define R8125_MAX_MSIX_VEC_8125B 32 -#define R8125_MIN_MSIX_VEC_8125B 17 -#define R8125_MAX_MSIX_VEC 32 -#define R8125_MAX_RX_QUEUES_VEC_V3 (16) - -#define RTL8125_TX_TIMEOUT (6 * HZ) -#define RTL8125_LINK_TIMEOUT (1 * HZ) -#define RTL8125_ESD_TIMEOUT (2 * HZ) - -#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ - -#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ -#define R8125_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8125_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) -#define R8125_MAX_TX_QUEUES (2) -#define R8125_MAX_RX_QUEUES (4) -#define R8125_MAX_QUEUES R8125_MAX_RX_QUEUES - -#define OCP_STD_PHY_BASE 0xa400 - -#ifdef ENABLE_LIB_SUPPORT -#define R8125_MULTI_RX_Q(tp) 0 -#else -#define R8125_MULTI_RX_Q(tp) (tp->num_rx_rings > 1) -#endif - -#define NODE_ADDRESS_SIZE 6 - -#define SHORT_PACKET_PADDING_BUF_SIZE 256 - -#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef - -/* write/read MMIO register */ -#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) -#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) -#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg)) -#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg)) -#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg)) -#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg))) - -#ifndef DMA_64BIT_MASK -#define DMA_64BIT_MASK 0xffffffffffffffffULL -#endif - -#ifndef DMA_32BIT_MASK -#define DMA_32BIT_MASK 0x00000000ffffffffULL -#endif - -#ifndef NETDEV_TX_OK -#define NETDEV_TX_OK 0 /* driver took care of packet */ -#endif - -#ifndef NETDEV_TX_BUSY -#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ -#endif - -#ifndef NETDEV_TX_LOCKED -#define NETDEV_TX_LOCKED -1t /* driver tx lock was already taken */ -#endif - -#ifndef ADVERTISED_Pause -#define ADVERTISED_Pause (1 << 13) -#endif - -#ifndef ADVERTISED_Asym_Pause -#define ADVERTISED_Asym_Pause (1 << 14) -#endif - -#ifndef ADVERTISE_PAUSE_CAP -#define ADVERTISE_PAUSE_CAP 0x400 -#endif - -#ifndef ADVERTISE_PAUSE_ASYM -#define ADVERTISE_PAUSE_ASYM 0x800 -#endif - -#ifndef MII_CTRL1000 -#define MII_CTRL1000 0x09 -#endif - -#ifndef ADVERTISE_1000FULL -#define ADVERTISE_1000FULL 0x200 -#endif - -#ifndef ADVERTISE_1000HALF -#define ADVERTISE_1000HALF 0x100 -#endif - -#ifndef ADVERTISED_2500baseX_Full -#define ADVERTISED_2500baseX_Full 0x8000 -#endif - -#define RTK_ADVERTISE_2500FULL 0x80 -#define RTK_LPA_ADVERTISE_2500FULL 0x20 -#define RTK_LPA_ADVERTISE_5000FULL 0x40 -#define RTK_LPA_ADVERTISE_10000FULL 0x800 - -/* Tx NO CLOSE */ -#define MAX_TX_NO_CLOSE_DESC_PTR_V2 0x10000 -#define TX_NO_CLOSE_SW_PTR_MASK_V2 0x1FFFF - -#ifndef ETH_MIN_MTU -#define ETH_MIN_MTU 68 -#endif - -#define D0_SPEED_UP_SPEED_DISABLE 0 -#define D0_SPEED_UP_SPEED_1000 1 -#define D0_SPEED_UP_SPEED_2500 2 - -#ifndef WRITE_ONCE -#define WRITE_ONCE(var, val) (*((volatile typeof(val) *)(&(var))) = (val)) -#endif -#ifndef READ_ONCE -#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) -#endif - -/*****************************************************************************/ - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ - (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ - ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) -/* copied from linux kernel 2.6.20 include/linux/netdev.h */ -#define NETDEV_ALIGN 32 -#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) - -static inline void *netdev_priv(struct net_device *dev) -{ - return (char *)dev + ((sizeof(struct net_device) - + NETDEV_ALIGN_CONST) - & ~NETDEV_ALIGN_CONST); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define RTLDEV tp -#else -#define RTLDEV dev -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -typedef struct net_device *napi_ptr; -typedef int *napi_budget; - -#define napi dev -#define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ - ndev->weight=weig; -#define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) -#define RTL_RX_QUOTA(budget) *budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ - ndev->quota -= work_done; -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) -#define RTL_NAPI_RETURN_VALUE work_done >= work_to_do -#define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) -#define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) -#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) -#else -typedef struct napi_struct *napi_ptr; -typedef int napi_budget; - -#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -#define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; -#define RTL_RX_QUOTA(budget) budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev, napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) -#endif -#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete_done(napi, work_done) -#else -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete(napi) -#endif -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) -#endif -#define RTL_NAPI_RETURN_VALUE work_done -#define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) -#define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -#define RTL_NAPI_DEL(priv) -#else -#define RTL_NAPI_DEL(priv) netif_napi_del(&priv->napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - -/*****************************************************************************/ -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) napi_consume_skb(skb, budget) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); -#else -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) -#else //CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); -#else -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); -#endif -#endif //CONFIG_R8125_NAPI - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -#ifdef __CHECKER__ -#define __iomem __attribute__((noderef, address_space(2))) -extern void __chk_io_ptr(void __iomem *); -#define __bitwise __attribute__((bitwise)) -#else -#define __iomem -#define __chk_io_ptr(x) (void)0 -#define __bitwise -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#else -#define __force -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) - -#ifndef module_param -#define module_param(v,t,p) MODULE_PARM(v, "i"); -#endif - -#ifndef PCI_DEVICE -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif - -/*****************************************************************************/ -/* 2.5.28 => 2.4.23 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) - -static inline void _kc_synchronize_irq(void) -{ - synchronize_irq(); -} -#undef synchronize_irq -#define synchronize_irq(X) _kc_synchronize_irq() - -#include -#define work_struct tq_struct -#undef INIT_WORK -#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) -#undef container_of -#define container_of list_entry -#define schedule_work schedule_task -#define flush_scheduled_work flush_scheduled_tasks -#endif /* 2.5.28 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) -#define MODULE_VERSION(_version) MODULE_INFO(version, _version) -#endif /* 2.6.4 => 2.6.0 */ -/*****************************************************************************/ -/* 2.6.0 => 2.5.28 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -#define MODULE_INFO(version, _version) -#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT -#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 -#endif - -#define pci_set_consistent_dma_mask(dev,mask) 1 - -#undef dev_put -#define dev_put(dev) __dev_put(dev) - -#ifndef skb_fill_page_desc -#define skb_fill_page_desc _kc_skb_fill_page_desc -extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); -#endif - -#ifndef pci_dma_mapping_error -#define pci_dma_mapping_error _kc_pci_dma_mapping_error -static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) -{ - return dma_addr == 0; -} -#endif - -#undef ALIGN -#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) - -#endif /* 2.6.0 => 2.5.28 */ - -/*****************************************************************************/ -/* 2.4.22 => 2.4.17 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -#define pci_name(x) ((x)->slot_name) -#endif /* 2.4.22 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.5 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) -#define pci_dma_sync_single_for_cpu pci_dma_sync_single -#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu -#endif /* 2.6.5 => 2.6.0 */ - -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -/* - * initialize a work-struct's func and data pointers: - */ -#define PREPARE_WORK(_work, _func, _data) \ - do { \ - (_work)->func = _func; \ - (_work)->data = _data; \ - } while (0) - -#endif -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) && \ - LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))) -#define ETHTOOL_OPS_COMPAT -#endif /* 2.6.4 => 2.6.0 */ - -/*****************************************************************************/ -/* Installations with ethtool version without eeprom, adapter id, or statistics - * support */ - -#ifndef ETH_GSTRING_LEN -#define ETH_GSTRING_LEN 32 -#endif - -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x1d -#undef ethtool_drvinfo -#define ethtool_drvinfo k_ethtool_drvinfo -struct k_ethtool_drvinfo { - u32 cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char bus_info[32]; - char reserved1[32]; - char reserved2[16]; - u32 n_stats; - u32 testinfo_len; - u32 eedump_len; - u32 regdump_len; -}; - -struct ethtool_stats { - u32 cmd; - u32 n_stats; - u64 data[0]; -}; -#endif /* ETHTOOL_GSTATS */ - -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x1c -#endif /* ETHTOOL_PHYS_ID */ - -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x1b -enum ethtool_stringset { - ETH_SS_TEST = 0, - ETH_SS_STATS, -}; -struct ethtool_gstrings { - u32 cmd; /* ETHTOOL_GSTRINGS */ - u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ - u32 len; /* number of strings in the string set */ - u8 data[0]; -}; -#endif /* ETHTOOL_GSTRINGS */ - -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x1a -enum ethtool_test_flags { - ETH_TEST_FL_OFFLINE = (1 << 0), - ETH_TEST_FL_FAILED = (1 << 1), -}; -struct ethtool_test { - u32 cmd; - u32 flags; - u32 reserved; - u32 len; - u64 data[0]; -}; -#endif /* ETHTOOL_TEST */ - -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0xb -#undef ETHTOOL_GREGS -struct ethtool_eeprom { - u32 cmd; - u32 magic; - u32 offset; - u32 len; - u8 data[0]; -}; - -struct ethtool_value { - u32 cmd; - u32 data; -}; -#endif /* ETHTOOL_GEEPROM */ - -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0xa -#endif /* ETHTOOL_GLINK */ - -#ifndef ETHTOOL_GREGS -#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ -#define ethtool_regs _kc_ethtool_regs -/* for passing big chunks of data */ -struct _kc_ethtool_regs { - u32 cmd; - u32 version; /* driver-specific, indicates different chips/revs */ - u32 len; /* bytes */ - u8 data[0]; -}; -#endif /* ETHTOOL_GREGS */ - -#ifndef ETHTOOL_GMSGLVL -#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -#endif -#ifndef ETHTOOL_SMSGLVL -#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ -#endif -#ifndef ETHTOOL_NWAY_RST -#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ -#endif -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0x0000000a /* Get link status */ -#endif -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -#endif -#ifndef ETHTOOL_SEEPROM -#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ -#endif -#ifndef ETHTOOL_GCOALESCE -#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -/* for configuring coalescing parameters of chip */ -#define ethtool_coalesce _kc_ethtool_coalesce -struct _kc_ethtool_coalesce { - u32 cmd; /* ETHTOOL_{G,S}COALESCE */ - - /* How many usecs to delay an RX interrupt after - * a packet arrives. If 0, only rx_max_coalesced_frames - * is used. - */ - u32 rx_coalesce_usecs; - - /* How many packets to delay an RX interrupt after - * a packet arrives. If 0, only rx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause RX interrupts to never be - * generated. - */ - u32 rx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 rx_coalesce_usecs_irq; - u32 rx_max_coalesced_frames_irq; - - /* How many usecs to delay a TX interrupt after - * a packet is sent. If 0, only tx_max_coalesced_frames - * is used. - */ - u32 tx_coalesce_usecs; - - /* How many packets to delay a TX interrupt after - * a packet is sent. If 0, only tx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause TX interrupts to never be - * generated. - */ - u32 tx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 tx_coalesce_usecs_irq; - u32 tx_max_coalesced_frames_irq; - - /* How many usecs to delay in-memory statistics - * block updates. Some drivers do not have an in-memory - * statistic block, and in such cases this value is ignored. - * This value must not be zero. - */ - u32 stats_block_coalesce_usecs; - - /* Adaptive RX/TX coalescing is an algorithm implemented by - * some drivers to improve latency under low packet rates and - * improve throughput under high packet rates. Some drivers - * only implement one of RX or TX adaptive coalescing. Anything - * not implemented by the driver causes these values to be - * silently ignored. - */ - u32 use_adaptive_rx_coalesce; - u32 use_adaptive_tx_coalesce; - - /* When the packet rate (measured in packets per second) - * is below pkt_rate_low, the {rx,tx}_*_low parameters are - * used. - */ - u32 pkt_rate_low; - u32 rx_coalesce_usecs_low; - u32 rx_max_coalesced_frames_low; - u32 tx_coalesce_usecs_low; - u32 tx_max_coalesced_frames_low; - - /* When the packet rate is below pkt_rate_high but above - * pkt_rate_low (both measured in packets per second) the - * normal {rx,tx}_* coalescing parameters are used. - */ - - /* When the packet rate is (measured in packets per second) - * is above pkt_rate_high, the {rx,tx}_*_high parameters are - * used. - */ - u32 pkt_rate_high; - u32 rx_coalesce_usecs_high; - u32 rx_max_coalesced_frames_high; - u32 tx_coalesce_usecs_high; - u32 tx_max_coalesced_frames_high; - - /* How often to do adaptive coalescing packet rate sampling, - * measured in seconds. Must not be zero. - */ - u32 rate_sample_interval; -}; -#endif /* ETHTOOL_GCOALESCE */ - -#ifndef ETHTOOL_SCOALESCE -#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -#endif -#ifndef ETHTOOL_GRINGPARAM -#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -/* for configuring RX/TX ring parameters */ -#define ethtool_ringparam _kc_ethtool_ringparam -struct _kc_ethtool_ringparam { - u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ - - /* Read only attributes. These indicate the maximum number - * of pending RX/TX ring entries the driver will allow the - * user to set. - */ - u32 rx_max_pending; - u32 rx_mini_max_pending; - u32 rx_jumbo_max_pending; - u32 tx_max_pending; - - /* Values changeable by the user. The valid values are - * in the range 1 to the "*_max_pending" counterpart above. - */ - u32 rx_pending; - u32 rx_mini_pending; - u32 rx_jumbo_pending; - u32 tx_pending; -}; -#endif /* ETHTOOL_GRINGPARAM */ - -#ifndef ETHTOOL_SRINGPARAM -#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ -#endif -#ifndef ETHTOOL_GPAUSEPARAM -#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -/* for configuring link flow control parameters */ -#define ethtool_pauseparam _kc_ethtool_pauseparam -struct _kc_ethtool_pauseparam { - u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ - - /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the - * pause parameters be auto-negotiated too. In such a case, the - * {rx,tx}_pause values below determine what capabilities are - * advertised. - * - * If 'autoneg' is zero or the link is not being auto-negotiated, - * then {rx,tx}_pause force the driver to use/not-use pause - * flow control. - */ - u32 autoneg; - u32 rx_pause; - u32 tx_pause; -}; -#endif /* ETHTOOL_GPAUSEPARAM */ - -#ifndef ETHTOOL_SPAUSEPARAM -#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -#endif -#ifndef ETHTOOL_GRXCSUM -#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_SRXCSUM -#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GTXCSUM -#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STXCSUM -#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GSG -#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable -* (ethtool_value) */ -#endif -#ifndef ETHTOOL_SSG -#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable -* (ethtool_value). */ -#endif -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ -#endif -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -#endif -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -#endif -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -#endif -#ifndef ETHTOOL_GTSO -#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STSO -#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -#endif - -#ifndef ETHTOOL_BUSINFO_LEN -#define ETHTOOL_BUSINFO_LEN 32 -#endif - -/*****************************************************************************/ - -enum RTL8125_registers { - MAC0 = 0x00, /* Ethernet hardware address. */ - MAC4 = 0x04, - MAR0 = 0x08, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - CustomLED = 0x18, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - INT_CFG0_8125 = 0x34, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - TCTR = 0x48, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - TDFNR = 0x57, - TimeInt0 = 0x58, - TimeInt1 = 0x5C, - PHYAR = 0x60, - CSIDR = 0x64, - CSIAR = 0x68, - PHYstatus = 0x6C, - MACDBG = 0x6D, - GPIO = 0x6E, - PMCH = 0x6F, - ERIDR = 0x70, - ERIAR = 0x74, - INT_CFG1_8125 = 0x7A, - EPHY_RXER_NUM = 0x7C, - EPHYAR = 0x80, - TimeInt2 = 0x8C, - OCPDR = 0xB0, - MACOCP = 0xB0, - OCPAR = 0xB4, - SecMAC0 = 0xB4, - SecMAC4 = 0xB8, - PHYOCP = 0xB8, - DBG_reg = 0xD1, - TwiCmdReg = 0xD2, - MCUCmd_reg = 0xD3, - RxMaxSize = 0xDA, - EFUSEAR = 0xDC, - CPlusCmd = 0xE0, - IntrMitigate = 0xE2, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - MTPS = 0xEC, - FuncEvent = 0xF0, - PPSW = 0xF2, - FuncEventMask = 0xF4, - TimeInt3 = 0xF4, - FuncPresetState = 0xF8, - CMAC_IBCR0 = 0xF8, - CMAC_IBCR2 = 0xF9, - CMAC_IBIMR0 = 0xFA, - CMAC_IBISR0 = 0xFB, - FuncForceEvent = 0xFC, - //8125 - IMR0_8125 = 0x38, - ISR0_8125 = 0x3C, - TPPOLL_8125 = 0x90, - IMR1_8125 = 0x800, - ISR1_8125 = 0x802, - IMR2_8125 = 0x804, - ISR2_8125 = 0x806, - IMR3_8125 = 0x808, - ISR3_8125 = 0x80A, - BACKUP_ADDR0_8125 = 0x19E0, - BACKUP_ADDR1_8125 = 0X19E4, - TCTR0_8125 = 0x0048, - TCTR1_8125 = 0x004C, - TCTR2_8125 = 0x0088, - TCTR3_8125 = 0x001C, - TIMER_INT0_8125 = 0x0058, - TIMER_INT1_8125 = 0x005C, - TIMER_INT2_8125 = 0x008C, - TIMER_INT3_8125 = 0x00F4, - INT_MITI_V2_0_RX = 0x0A00, - INT_MITI_V2_0_TX = 0x0A02, - INT_MITI_V2_1_RX = 0x0A08, - INT_MITI_V2_1_TX = 0x0A0A, - IMR_V2_CLEAR_REG_8125 = 0x0D00, - ISR_V2_8125 = 0x0D04, - IMR_V2_SET_REG_8125 = 0x0D0C, - TDU_STA_8125 = 0x0D08, - RDU_STA_8125 = 0x0D0A, - TX_NEW_CTRL = 0x203E, - TNPDS_Q1_LOW_8125 = 0x2100, - PLA_TXQ0_IDLE_CREDIT = 0x2500, - PLA_TXQ1_IDLE_CREDIT = 0x2504, - SW_TAIL_PTR0_8125 = 0x2800, - HW_CLO_PTR0_8125 = 0x2802, - RDSAR_Q1_LOW_8125 = 0x4000, - RSS_CTRL_8125 = 0x4500, - Q_NUM_CTRL_8125 = 0x4800, - RSS_KEY_8125 = 0x4600, - RSS_INDIRECTION_TBL_8125_V2 = 0x4700, - EEE_TXIDLE_TIMER_8125 = 0x6048, - PTP_CTRL_8125 = 0x6800, - PTP_STATUS_8125 = 0x6802, - PTP_ISR_8125 = 0x6804, - PTP_IMR_8125 = 0x6805, - PTP_TIME_CORRECT_CMD_8125 = 0x6806, - PTP_SOFT_CONFIG_Time_NS_8125 = 0x6808, - PTP_SOFT_CONFIG_Time_S_8125 = 0x680C, - PTP_LOCAL_Time_SUB_NS_8125 = 0x6814, - PTP_LOCAL_Time_NS_8125 = 0x6818, - PTP_LOCAL_Time_S_8125 = 0x681C, - PTP_Time_SHIFTER_S_8125 = 0x6856, - PPS_RISE_TIME_NS_8125 = 0x68A0, - PPS_RISE_TIME_S_8125 = 0x68A4, -}; - -enum RTL8125_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxDescUnavail = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - RxDU1 = 0x0002, - RxOK1 = 0x0001, - - /* RxStatusDesc */ - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - RxRWT_V3 = (1 << 18), - RxRES_V3 = (1 << 20), - RxRUNT_V3 = (1 << 19), - RxCRC_V3 = (1 << 17), - - /* ChipCmdBits */ - StopReq = 0x80, - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, - Cfg9346_EEDO = (1 << 0), - Cfg9346_EEDI = (1 << 1), - Cfg9346_EESK = (1 << 2), - Cfg9346_EECS = (1 << 3), - Cfg9346_EEM0 = (1 << 6), - Cfg9346_EEM1 = (1 << 7), - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* Transmit Priority Polling*/ - HPQ = 0x80, - NPQ = 0x40, - FSWInt = 0x01, - - /* RxConfigBits */ - Reserved2_shift = 13, - RxCfgDMAShift = 8, - EnableRxDescV3 = (1 << 24), - EnableOuterVlan = (1 << 23), - EnableInnerVlan = (1 << 22), - RxCfg_128_int_en = (1 << 15), - RxCfg_fet_multi_en = (1 << 14), - RxCfg_half_refetch = (1 << 13), - RxCfg_pause_slot_en = (1 << 11), - RxCfg_9356SEL = (1 << 6), - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - TxMACLoopBack = (1 << 17), /* MAC loopback */ - - /* Config1 register */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register */ - PMSTS_En = (1 << 5), - - /* Config3 register */ - Isolate_en = (1 << 12), /* Isolate enable */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* This bit is reserved in RTL8125B.*/ - /* Wake up when the cable connection is re-established */ - ECRCEN = (1 << 3), /* This bit is reserved in RTL8125B*/ - Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8125B*/ - RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8125B*/ - Beacon_en = (1 << 0), /* This bit is reserved in RTL8125B*/ - - /* Config4 register */ - Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8125B*/ - - /* Config5 register */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* CPlusCmd */ - EnableBist = (1 << 15), - Macdbgo_oe = (1 << 14), - Normal_mode = (1 << 13), - Force_halfdup = (1 << 12), - Force_rxflow_en = (1 << 11), - Force_txflow_en = (1 << 10), - Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8125B - ASF = (1 << 8),//This bit is reserved in RTL8125C - PktCntrDisable = (1 << 7), - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - Macdbgo_sel = 0x001C, - INTT_0 = 0x0000, - INTT_1 = 0x0001, - INTT_2 = 0x0002, - INTT_3 = 0x0003, - - /* rtl8125_PHYstatus */ - PowerSaveStatus = 0x80, - _2500bpsF = 0x400, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* DBG_reg */ - Fix_Nak_1 = (1 << 4), - Fix_Nak_2 = (1 << 3), - DBGPIN_E2 = (1 << 0), - - /* ResetCounterCommand */ - CounterReset = 0x1, - /* DumpCounterCommand */ - CounterDump = 0x8, - - /* PHY access */ - PHYAR_Flag = 0x80000000, - PHYAR_Write = 0x80000000, - PHYAR_Read = 0x00000000, - PHYAR_Reg_Mask = 0x1f, - PHYAR_Reg_shift = 16, - PHYAR_Data_Mask = 0xffff, - - /* EPHY access */ - EPHYAR_Flag = 0x80000000, - EPHYAR_Write = 0x80000000, - EPHYAR_Read = 0x00000000, - EPHYAR_Reg_Mask = 0x3f, - EPHYAR_Reg_Mask_v2 = 0x7f, - EPHYAR_Reg_shift = 16, - EPHYAR_Data_Mask = 0xffff, - - /* CSI access */ - CSIAR_Flag = 0x80000000, - CSIAR_Write = 0x80000000, - CSIAR_Read = 0x00000000, - CSIAR_ByteEn = 0x0f, - CSIAR_ByteEn_shift = 12, - CSIAR_Addr_Mask = 0x0fff, - - /* ERI access */ - ERIAR_Flag = 0x80000000, - ERIAR_Write = 0x80000000, - ERIAR_Read = 0x00000000, - ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ - ERIAR_ExGMAC = 0, - ERIAR_MSIX = 1, - ERIAR_ASF = 2, - ERIAR_OOB = 2, - ERIAR_Type_shift = 16, - ERIAR_ByteEn = 0x0f, - ERIAR_ByteEn_shift = 12, - - /* OCP GPHY access */ - OCPDR_Write = 0x80000000, - OCPDR_Read = 0x00000000, - OCPDR_Reg_Mask = 0xFF, - OCPDR_Data_Mask = 0xFFFF, - OCPDR_GPHY_Reg_shift = 16, - OCPAR_Flag = 0x80000000, - OCPAR_GPHY_Write = 0x8000F060, - OCPAR_GPHY_Read = 0x0000F060, - OCPR_Write = 0x80000000, - OCPR_Read = 0x00000000, - OCPR_Addr_Reg_shift = 16, - OCPR_Flag = 0x80000000, - OCP_STD_PHY_BASE_PAGE = 0x0A40, - - /* MCU Command */ - Now_is_oob = (1 << 7), - Txfifo_empty = (1 << 5), - Rxfifo_empty = (1 << 4), - - /* E-FUSE access */ - EFUSE_WRITE = 0x80000000, - EFUSE_WRITE_OK = 0x00000000, - EFUSE_READ = 0x00000000, - EFUSE_READ_OK = 0x80000000, - EFUSE_WRITE_V3 = 0x40000000, - EFUSE_WRITE_OK_V3 = 0x00000000, - EFUSE_READ_V3 = 0x80000000, - EFUSE_READ_OK_V3 = 0x00000000, - EFUSE_Reg_Mask = 0x03FF, - EFUSE_Reg_Shift = 8, - EFUSE_Check_Cnt = 300, - EFUSE_READ_FAIL = 0xFF, - EFUSE_Data_Mask = 0x000000FF, - - /* GPIO */ - GPIO_en = (1 << 0), - - /* PTP */ - PTP_ISR_TOK = (1 << 1), - PTP_ISR_TER = (1 << 2), - PTP_EXEC_CMD = (1 << 7), - PTP_ADJUST_TIME_NS_NEGATIVE = (1 << 30), - PTP_ADJUST_TIME_S_NEGATIVE = (1ULL << 48), - - /* New Interrupt Bits */ - INT_CFG0_ENABLE_8125 = (1 << 0), - INT_CFG0_TIMEOUT0_BYPASS_8125 = (1 << 1), - INT_CFG0_MITIGATION_BYPASS_8125 = (1 << 2), - ISRIMR_V2_ROK_Q0 = (1 << 0), - ISRIMR_TOK_Q0 = (1 << 16), - ISRIMR_TOK_Q1 = (1 << 18), - ISRIMR_V2_LINKCHG = (1 << 21), - - /* Magic Number */ - RTL8125_MAGIC_NUMBER = 0x0badbadbadbadbadull, -}; - -enum _DescStatusBit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - DescOwn_V3 = (DescOwn), /* Descriptor is owned by NIC */ - RingEnd_V3 = (RingEnd), /* End of descriptor ring */ - FirstFrag_V3 = (1 << 25), /* First segment of a packet */ - LastFrag_V3 = (1 << 24), /* Final segment of a packet */ - - /* Tx private */ - /*------ offset 0 of tx descriptor ------*/ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ - GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ - LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0x7FFU, /* MSS value 11 bits */ - TxIPCS = (1 << 18), /* Calculate IP checksum */ - TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only begin @@@@@@*/ - TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ - TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ - TxIPCS_C = (1 << 29), /* Calculate IP checksum */ - TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */ - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only end @@@@@@*/ - - - /* Rx private */ - /*------ offset 0 of rx descriptor ------*/ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - RxIPF = (1 << 16), /* IP checksum failed */ - RxUDPF = (1 << 15), /* UDP/IP checksum failed */ - RxTCPF = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxUDPT = (1 << 18), - RxTCPT = (1 << 17), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxV6F = (1 << 31), - RxV4F = (1 << 30), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - - PID1_v3 = (1 << 29), /* Protocol ID bit 1/2 */ - PID0_v3 = (1 << 28), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP_v3 (PID1_v3) -#define RxProtoTCP_v3 (PID0_v3) -#define RxProtoIP_v3 (PID1_v3 | PID0_v3) -#define RxProtoMask_v3 RxProtoIP_v3 - - RxIPF_v3 = (1 << 26), /* IP checksum failed */ - RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */ - RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */ - RxSCTPF_v3 = (1 << 23), /* TCP/IP checksum failed */ - RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxUDPT_v3 = (1 << 29), - RxTCPT_v3 = (1 << 28), - RxSCTP_v3 = (1 << 27), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxV6F_v3 = (RxV6F), - RxV4F_v3 = (RxV4F), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ -}; - -enum features { -// RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_MSIX = (1 << 2), -}; - -enum wol_capability { - WOL_DISABLED = 0, - WOL_ENABLED = 1 -}; - -enum bits { - BIT_0 = (1 << 0), - BIT_1 = (1 << 1), - BIT_2 = (1 << 2), - BIT_3 = (1 << 3), - BIT_4 = (1 << 4), - BIT_5 = (1 << 5), - BIT_6 = (1 << 6), - BIT_7 = (1 << 7), - BIT_8 = (1 << 8), - BIT_9 = (1 << 9), - BIT_10 = (1 << 10), - BIT_11 = (1 << 11), - BIT_12 = (1 << 12), - BIT_13 = (1 << 13), - BIT_14 = (1 << 14), - BIT_15 = (1 << 15), - BIT_16 = (1 << 16), - BIT_17 = (1 << 17), - BIT_18 = (1 << 18), - BIT_19 = (1 << 19), - BIT_20 = (1 << 20), - BIT_21 = (1 << 21), - BIT_22 = (1 << 22), - BIT_23 = (1 << 23), - BIT_24 = (1 << 24), - BIT_25 = (1 << 25), - BIT_26 = (1 << 26), - BIT_27 = (1 << 27), - BIT_28 = (1 << 28), - BIT_29 = (1 << 29), - BIT_30 = (1 << 30), - BIT_31 = (1 << 31) -}; - -enum effuse { - EFUSE_NOT_SUPPORT = 0, - EFUSE_SUPPORT_V1, - EFUSE_SUPPORT_V2, - EFUSE_SUPPORT_V3, - EFUSE_SUPPORT_V4, -}; -#define RsvdMask 0x3fffc000 -#define RsvdMaskV3 0x3fff8000 - -struct TxDesc { - u32 opts1; - u32 opts2; - u64 addr; - u32 reserved0; - u32 reserved1; - u32 reserved2; - u32 reserved3; -}; - -struct RxDesc { - u32 opts1; - u32 opts2; - u64 addr; -}; - -struct RxDescV3 { - union { - struct { - u32 rsv1; - u32 rsv2; - } RxDescDDWord1; - }; - - union { - struct { - u32 RSSResult; - u16 HeaderBufferLen; - u16 HeaderInfo; - } RxDescNormalDDWord2; - - struct { - u32 rsv5; - u32 rsv6; - } RxDescDDWord2; - }; - - union { - u64 addr; - - struct { - u32 TimeStampLow; - u32 TimeStampHigh; - } RxDescTimeStamp; - - struct { - u32 rsv8; - u32 rsv9; - } RxDescDDWord3; - }; - - union { - struct { - u32 opts2; - u32 opts1; - } RxDescNormalDDWord4; - - struct { - u16 TimeStampHHigh; - u16 rsv11; - u32 opts1; - } RxDescPTPDDWord4; - }; -}; - -enum rxdesc_type { - RXDESC_TYPE_NORMAL=0, - RXDESC_TYPE_NEXT, - RXDESC_TYPE_PTP, - RXDESC_TYPE_MAX -}; - -//Rx Desc Type -enum rx_desc_ring_type { - RX_DESC_RING_TYPE_UNKNOWN=0, - RX_DESC_RING_TYPE_1, - RX_DESC_RING_TYPE_2, - RX_DESC_RING_TYPE_3, - RX_DESC_RING_TYPE_MAX -}; - -enum rx_desc_len { - RX_DESC_LEN_TYPE_1 = (sizeof(struct RxDesc)), - RX_DESC_LEN_TYPE_3 = (sizeof(struct RxDescV3)) -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -struct pci_resource { - u8 cmd; - u8 cls; - u16 io_base_h; - u16 io_base_l; - u16 mem_base_h; - u16 mem_base_l; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_h; - u16 resv_0x20_l; - u16 resv_0x24_h; - u16 resv_0x24_l; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; -}; - -enum r8125_flag { - R8125_FLAG_DOWN = 0, - R8125_FLAG_TASK_RESET_PENDING, - R8125_FLAG_TASK_ESD_CHECK_PENDING, - R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, - R8125_FLAG_MAX -}; - -struct rtl8125_tx_ring { - void* priv; - u32 index; - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - dma_addr_t TxPhyAddr; - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - - u32 NextHwDesCloPtr; - u32 BeginHwDesCloPtr; - - u16 hw_clo_ptr_reg; - u16 sw_tail_ptr_reg; - - u16 tdsar_reg; /* Transmit Descriptor Start Address */ -}; - -struct rtl8125_rx_ring { - void* priv; - u32 index; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - u64 RxDescPhyAddr[NUM_RX_DESC]; /* Rx desc physical address*/ - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - - u16 rdsar_reg; /* Receive Descriptor Start Address */ -}; - -struct r8125_napi { -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - struct napi_struct napi; -#endif -#endif - void* priv; - int index; -}; - -struct r8125_irq { - irq_handler_t handler; - unsigned int vector; - u8 requested; - char name[IFNAMSIZ + 10]; -}; - -#pragma pack(1) -struct rtl8125_regs { - //00 - u8 mac_id[6]; - u16 reg_06; - u8 mar[8]; - //10 - u64 dtccr; - u16 ledsel0; - u16 legreg; - u32 tctr3; - //20 - u32 txq0_dsc_st_addr_0; - u32 txq0_dsc_st_addr_2; - u64 reg_28; - //30 - u16 rit; - u16 ritc; - u16 reg_34; - u8 reg_36; - u8 command; - u32 imr0; - u32 isr0; - //40 - u32 tcr; - u32 rcr; - u32 tctr0; - u32 tctr1; - //50 - u8 cr93c46; - u8 config0; - u8 config1; - u8 config2; - u8 config3; - u8 config4; - u8 config5; - u8 tdfnr; - u32 timer_int0; - u32 timer_int1; - //60 - u32 gphy_mdcmdio; - u32 csidr; - u32 csiar; - u16 phy_status; - u8 config6; - u8 pmch; - //70 - u32 eridr; - u32 eriar; - u16 config7; - u16 reg_7a; - u32 ephy_rxerr_cnt; - //80 - u32 ephy_mdcmdio; - u16 ledsel2; - u16 ledsel1; - u32 tctr2; - u32 timer_int2; - //90 - u8 tppoll0; - u8 reg_91; - u16 reg_92; - u16 led_feature; - u16 ledsel3; - u16 eee_led_config; - u16 reg_9a; - u32 reg_9c; - //a0 - u32 reg_a0; - u32 reg_a4; - u32 reg_a8; - u32 reg_ac; - //b0 - u32 patch_dbg; - u32 reg_b4; - u32 gphy_ocp; - u32 reg_bc; - //c0 - u32 reg_c0; - u32 reg_c4; - u32 reg_c8; - u16 otp_cmd; - u16 otp_pg_config; - //d0 - u16 phy_pwr; - u8 twsi_ctrl; - u8 oob_ctrl; - u16 mac_dbgo; - u16 mac_dbg; - u16 reg_d8; - u16 rms; - u32 efuse_data; - //e0 - u16 cplus_cmd; - u16 reg_e2; - u32 rxq0_dsc_st_addr_0; - u32 rxq0_dsc_st_addr_2; - u16 reg_ec; - u16 tx10midle_cnt; - //f0 - u16 misc0; - u16 misc1; - u32 timer_int3; - u32 cmac_ib; - u16 reg_fc; - u16 sw_rst; -}; -#pragma pack() - -struct rtl8125_regs_save { - union { - u8 mac_io[R8125_MAC_REGS_SIZE]; - - struct rtl8125_regs mac_reg; - }; - u16 pcie_phy[R8125_EPHY_REGS_SIZE/2]; - u16 eth_phy[R8125_PHY_REGS_SIZE/2]; - u32 eri_reg[R8125_ERI_REGS_SIZE/4]; - u32 pci_reg[R8125_PCI_REGS_SIZE/4]; - u16 sw_tail_ptr_reg[R8125_MAX_TX_QUEUES]; - u16 hw_clo_ptr_reg[R8125_MAX_TX_QUEUES]; - - //ktime_t begin_ktime; - //ktime_t end_ktime; - //u64 duration_ns; - - u16 sw0_tail_ptr; - u16 next_hwq0_clo_ptr; - u16 sw1_tail_ptr; - u16 next_hwq1_clo_ptr; - - u16 int_miti_rxq0; - u16 int_miti_txq0; - u16 int_miti_rxq1; - u16 int_miti_txq1; - u8 int_config; - u32 imr_new; - u32 isr_new; - - u8 tdu_status; - u16 rdu_status; - - u16 tc_mode; - - u32 txq1_dsc_st_addr_0; - u32 txq1_dsc_st_addr_2; - - u32 pla_tx_q0_idle_credit; - u32 pla_tx_q1_idle_credit; - - u32 rxq1_dsc_st_addr_0; - u32 rxq1_dsc_st_addr_2; - - u32 rss_ctrl; - u8 rss_key[RTL8125_RSS_KEY_SIZE]; - u8 rss_i_table[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; - u16 rss_queue_num_sel_r; -}; - -struct rtl8125_counters { - /* legacy */ - u64 tx_packets; - u64 rx_packets; - u64 tx_errors; - u32 rx_errors; - u16 rx_missed; - u16 align_errors; - u32 tx_one_collision; - u32 tx_multi_collision; - u64 rx_unicast; - u64 rx_broadcast; - u32 rx_multicast; - u16 tx_aborted; - u16 tx_underrun; - - /* extended */ - u64 tx_octets; - u64 rx_octets; - u64 rx_multicast64; - u64 tx_unicast64; - u64 tx_broadcast64; - u64 tx_multicast64; - u32 tx_pause_on; - u32 tx_pause_off; - u32 tx_pause_all; - u32 tx_deferred; - u32 tx_late_collision; - u32 tx_all_collision; - u32 tx_aborted32; - u32 align_errors32; - u32 rx_frame_too_long; - u32 rx_runt; - u32 rx_pause_on; - u32 rx_pause_off; - u32 rx_pause_all; - u32 rx_unknown_opcode; - u32 rx_mac_error; - u32 tx_underrun32; - u32 rx_mac_missed; - u32 rx_tcam_dropped; - u32 tdu; - u32 rdu; -}; - -/* Flow Control Settings */ -enum rtl8125_fc_mode { - rtl8125_fc_none = 0, - rtl8125_fc_rx_pause, - rtl8125_fc_tx_pause, - rtl8125_fc_full, - rtl8125_fc_default -}; - -struct rtl8125_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct r8125_napi r8125napi[R8125_MAX_MSIX_VEC]; - struct r8125_irq irq_tbl[R8125_MAX_MSIX_VEC]; - unsigned int irq_nvecs; - unsigned int max_irq_nvecs; - unsigned int min_irq_nvecs; - //struct msix_entry msix_entries[R8125_MAX_MSIX_VEC]; - struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - u32 tx_tcp_csum_cmd; - u32 tx_udp_csum_cmd; - u32 tx_ip_csum_cmd; - u32 tx_ipv6_csum_cmd; - int max_jumbo_frame_size; - int chipset; - u32 mcfg; - //u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - //u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - //u32 dirty_rx; - //u32 dirty_tx; - //struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - //struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - //dma_addr_t TxPhyAddr; - //dma_addr_t RxPhyAddr; - //struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - //struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned rx_buf_sz; - u16 HwSuppNumTxQueues; - u16 HwSuppNumRxQueues; - unsigned int num_tx_rings; - unsigned int num_rx_rings; - struct rtl8125_tx_ring tx_ring[R8125_MAX_TX_QUEUES]; - struct rtl8125_rx_ring rx_ring[R8125_MAX_RX_QUEUES]; -#ifdef ENABLE_LIB_SUPPORT - struct atomic_notifier_head lib_nh; - struct rtl8125_ring lib_tx_ring[R8125_MAX_TX_QUEUES]; - struct rtl8125_ring lib_rx_ring[R8125_MAX_RX_QUEUES]; -#endif - //struct timer_list esd_timer; - //struct timer_list link_timer; - struct pci_resource pci_cfg_space; - unsigned int esd_flag; - unsigned int pci_cfg_is_read; - unsigned int rtl8125_rx_config; - u16 cp_cmd; - u32 intr_mask; - u32 timer_intr_mask; - u16 isr_reg[R8125_MAX_QUEUES]; - u16 imr_reg[R8125_MAX_QUEUES]; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; - int phy_2500_ctrl_reg; - u8 org_mac_addr[NODE_ADDRESS_SIZE]; - struct rtl8125_counters *tally_vaddr; - dma_addr_t tally_paddr; - -#ifdef CONFIG_R8125_VLAN - struct vlan_group *vlgrp; -#endif - u8 wol_enabled; - u32 wol_opts; - u8 efuse_ver; - u8 eeprom_type; - u8 autoneg; - u8 duplex; - u32 speed; - u32 advertising; - enum rtl8125_fc_mode fcpause; - u16 eeprom_len; - u16 cur_page; - u32 bios_setting; - - int (*set_speed)(struct net_device *, u8 autoneg, u32 speed, u8 duplex, u32 adv); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - void (*get_settings)(struct net_device *, struct ethtool_cmd *); -#else - void (*get_settings)(struct net_device *, struct ethtool_link_ksettings *); -#endif - void (*phy_reset_enable)(struct net_device *); - unsigned int (*phy_reset_pending)(struct net_device *); - unsigned int (*link_ok)(struct net_device *); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct reset_task; - struct work_struct esd_task; - struct work_struct linkchg_task; -#else - struct delayed_work reset_task; - struct delayed_work esd_task; - struct delayed_work linkchg_task; -#endif - DECLARE_BITMAP(task_flags, R8125_FLAG_MAX); - unsigned features; - - u8 org_pci_offset_99; - u8 org_pci_offset_180; - u8 issue_offset_99_event; - - u8 org_pci_offset_80; - u8 org_pci_offset_81; - u8 use_timer_interrrupt; - - u32 keep_intr_cnt; - - u8 HwIcVerUnknown; - u8 NotWrRamCodeToMicroP; - u8 NotWrMcuPatchCode; - u8 HwHasWrRamCodeToMicroP; - - u16 sw_ram_code_ver; - u16 hw_ram_code_ver; - - u8 rtk_enable_diag; - - u8 ShortPacketSwChecksum; - - u8 UseSwPaddingShortPkt; - - u8 RequireAdcBiasPatch; - u16 AdcBiasPatchIoffset; - - u8 RequireAdjustUpsTxLinkPulseTiming; - u16 SwrCnt1msIni; - - u8 HwSuppNowIsOobVer; - - u8 RequiredSecLanDonglePatch; - - u8 RequirePhyMdiSwapPatch; - - u8 RequireLSOPatch; - - u32 HwFiberModeVer; - u32 HwFiberStat; - u8 HwSwitchMdiToFiber; - - u16 NicCustLedValue; - - u8 HwSuppMagicPktVer; - - u8 HwSuppLinkChgWakeUpVer; - - u8 HwSuppCheckPhyDisableModeVer; - - u8 random_mac; - - u16 phy_reg_aner; - u16 phy_reg_anlpar; - u16 phy_reg_gbsr; - u16 phy_reg_status_2500; - - u32 HwPcieSNOffset; - - u8 HwSuppTxNoCloseVer; - u8 EnableTxNoClose; - - u8 HwSuppIsrVer; - u8 HwCurrIsrVer; - - u8 HwSuppIntMitiVer; - - u8 HwSuppExtendTallyCounterVer; - - u8 check_keep_link_speed; - u8 resume_not_chg_speed; - - u8 HwSuppD0SpeedUpVer; - u8 D0SpeedUpSpeed; - - u8 ring_lib_enabled; - - const char *fw_name; - struct rtl8125_fw *rtl_fw; - u32 ocp_base; - - //Dash+++++++++++++++++ - u8 HwSuppDashVer; - u8 DASH; - u8 dash_printer_enabled; - u8 HwPkgDet; - void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */ - void __iomem *cmac_ioaddr; /* cmac memory map physical address */ - -#ifdef ENABLE_DASH_SUPPORT - u16 AfterRecvFromFwBufLen; - u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE]; - u16 AfterSendToFwBufLen; - u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE]; - u16 SendToFwBufferLen; - u32 SizeOfSendToFwBuffer; - u32 SizeOfSendToFwBufferMemAlloc; - u32 NumOfSendToFwBuffer; - - u8 OobReq; - u8 OobAck; - u32 OobReqComplete; - u32 OobAckComplete; - - u8 RcvFwReqSysOkEvt; - u8 RcvFwDashOkEvt; - u8 SendFwHostOkEvt; - - u8 DashFwDisableRx; - - void *UnalignedSendToFwBufferVa; - void *SendToFwBuffer; - u64 SendToFwBufferPhy; - u8 SendingToFw; - dma_addr_t UnalignedSendToFwBufferPa; - PTX_DASH_SEND_FW_DESC TxDashSendFwDesc; - u64 TxDashSendFwDescPhy; - u8 *UnalignedTxDashSendFwDescVa; - u32 SizeOfTxDashSendFwDescMemAlloc; - u32 SizeOfTxDashSendFwDesc; - u32 NumTxDashSendFwDesc; - u32 CurrNumTxDashSendFwDesc; - u32 LastSendNumTxDashSendFwDesc; - dma_addr_t UnalignedTxDashSendFwDescPa; - - u32 NumRecvFromFwBuffer; - u32 SizeOfRecvFromFwBuffer; - u32 SizeOfRecvFromFwBufferMemAlloc; - void *RecvFromFwBuffer; - u64 RecvFromFwBufferPhy; - - void *UnalignedRecvFromFwBufferVa; - dma_addr_t UnalignedRecvFromFwBufferPa; - PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc; - u64 RxDashRecvFwDescPhy; - u8 *UnalignedRxDashRecvFwDescVa; - u32 SizeOfRxDashRecvFwDescMemAlloc; - u32 SizeOfRxDashRecvFwDesc; - u32 NumRxDashRecvFwDesc; - u32 CurrNumRxDashRecvFwDesc; - dma_addr_t UnalignedRxDashRecvFwDescPa; - u8 DashReqRegValue; - u16 HostReqValue; - - u32 CmacResetIsrCounter; - u8 CmacResetIntr; - u8 CmacResetting; - u8 CmacOobIssueCmacReset; - u32 CmacResetbyFwCnt; - -#if defined(ENABLE_DASH_PRINTER_SUPPORT) - struct completion fw_ack; - struct completion fw_req; - struct completion fw_host_ok; -#endif - //Dash----------------- -#endif //ENABLE_DASH_SUPPORT - - //Realwow++++++++++++++ - u8 HwSuppKCPOffloadVer; - - u8 EnableDhcpTimeoutWake; - u8 EnableTeredoOffload; - u8 EnableKCPOffload; -#ifdef ENABLE_REALWOW_SUPPORT - u32 DhcpTimeout; - MP_KCP_INFO MpKCPInfo; - //Realwow-------------- -#endif //ENABLE_REALWOW_SUPPORT - - struct ethtool_eee eee; - -#ifdef ENABLE_R8125_PROCFS - //Procfs support - struct proc_dir_entry *proc_dir; -#endif - u8 InitRxDescType; - u16 RxDescLength; //V1 16 Byte V2 32 Bytes - u32 RxDescRingLength; - - u8 HwSuppPtpVer; - u8 EnablePtp; - u8 ptp_master_mode; - s64 ptp_adjust; -#ifdef ENABLE_PTP_SUPPORT - u32 tx_hwtstamp_timeouts; - u32 tx_hwtstamp_skipped; - struct work_struct ptp_tx_work; - struct sk_buff *ptp_tx_skb; - struct hwtstamp_config hwtstamp_config; - unsigned long ptp_tx_start; - struct ptp_clock_info ptp_clock_info; - struct ptp_clock *ptp_clock; -#endif - - u8 HwSuppRssVer; - u8 EnableRss; - u16 HwSuppIndirTblEntries; -#ifdef ENABLE_RSS_SUPPORT - u32 rss_flags; - /* Receive Side Scaling settings */ - u8 rss_key[RTL8125_RSS_KEY_SIZE]; - u8 rss_indir_tbl[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; - u32 rss_options; -#endif -}; - -#ifdef ENABLE_LIB_SUPPORT -static inline unsigned int -rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) -{ - int count, i; - - for (count = 0, i = tp->num_tx_rings; i < tp->HwSuppNumTxQueues; i++) - if(tp->lib_tx_ring[i].enabled) - count++; - - return count; -} - -static inline unsigned int -rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) -{ - int count, i; - - for (count = 0, i = tp->num_rx_rings; i < tp->HwSuppNumRxQueues; i++) - if(tp->lib_rx_ring[i].enabled) - count++; - - return count; -} - -#else -static inline unsigned int -rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) -{ - return 0; -} - -static inline unsigned int -rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) -{ - return 0; -} -#endif - -static inline unsigned int -rtl8125_tot_tx_rings(struct rtl8125_private *tp) -{ - return tp->num_tx_rings + rtl8125_num_lib_tx_rings(tp); -} - -static inline unsigned int -rtl8125_tot_rx_rings(struct rtl8125_private *tp) -{ - return tp->num_rx_rings + rtl8125_num_lib_rx_rings(tp); -} - -enum eetype { - EEPROM_TYPE_NONE=0, - EEPROM_TYPE_93C46, - EEPROM_TYPE_93C56, - EEPROM_TWSI -}; - -enum mcfg { - CFG_METHOD_2=2, - CFG_METHOD_3, - CFG_METHOD_4, - CFG_METHOD_5, - CFG_METHOD_DEFAULT, - CFG_METHOD_MAX -}; - -#define LSO_32K 32000 -#define LSO_64K 64000 - -#define NIC_MIN_PHYS_BUF_COUNT (2) -#define NIC_MAX_PHYS_BUF_COUNT_LSO_64K (24) -#define NIC_MAX_PHYS_BUF_COUNT_LSO2 (16*4) - -#define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x7fU -#define GTPKTSIZE_MAX 0x3ffffU -#define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU -#define LSOPKTSIZE_MAX 0xffffU -#define MSS_MAX 0x07ffu /* MSS value */ - -#define OOB_CMD_RESET 0x00 -#define OOB_CMD_DRIVER_START 0x05 -#define OOB_CMD_DRIVER_STOP 0x06 -#define OOB_CMD_SET_IPMAC 0x41 - -#define WAKEUP_MAGIC_PACKET_NOT_SUPPORT (0) -#define WAKEUP_MAGIC_PACKET_V1 (1) -#define WAKEUP_MAGIC_PACKET_V2 (2) -#define WAKEUP_MAGIC_PACKET_V3 (3) - -//Ram Code Version -#define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0b11) -#define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0b33) -#define NIC_RAMCODE_VERSION_CFG_METHOD_4 (0x0b17) -#define NIC_RAMCODE_VERSION_CFG_METHOD_5 (0x0b55) - -//hwoptimize -#define HW_PATCH_SOC_LAN (BIT_0) -#define HW_PATCH_SAMSUNG_LAN_DONGLE (BIT_2) - -static const u16 other_q_intr_mask = (RxOK1 | RxDU1); - -void rtl8125_mdio_write(struct rtl8125_private *tp, u16 RegAddr, u16 value); -void rtl8125_mdio_prot_write(struct rtl8125_private *tp, u32 RegAddr, u32 value); -void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, u32 RegAddr, u32 value); -u32 rtl8125_mdio_read(struct rtl8125_private *tp, u16 RegAddr); -u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, u32 RegAddr); -u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, u32 RegAddr); -void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value); -void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value); -u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr); -void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); -void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); -void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 data); -void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd); -void rtl8125_init_ring_indexes(struct rtl8125_private *tp); -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); -void rtl8125_oob_mutex_lock(struct rtl8125_private *tp); -u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len); -u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 base_address); -u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, u32 base_address); -u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type); -u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, u32 base_address); -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); -int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, u32 base_address); -u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr); -void rtl8125_wait_txrx_fifo_empty(struct net_device *dev); -void rtl8125_enable_now_is_oob(struct rtl8125_private *tp); -void rtl8125_disable_now_is_oob(struct rtl8125_private *tp); -void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp); -void rtl8125_dash2_disable_tx(struct rtl8125_private *tp); -void rtl8125_dash2_enable_tx(struct rtl8125_private *tp); -void rtl8125_dash2_disable_rx(struct rtl8125_private *tp); -void rtl8125_dash2_enable_rx(struct rtl8125_private *tp); -void rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev); -void rtl8125_mark_to_asic(struct rtl8125_private *tp, struct RxDesc *desc, u32 rx_buf_sz); - -static inline void -rtl8125_make_unusable_by_asic(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { - ((struct RxDescV3 *)desc)->addr = RTL8125_MAGIC_NUMBER; - ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV3); - } else { - desc->addr = RTL8125_MAGIC_NUMBER; - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); - } -} - -static inline struct RxDesc* -rtl8125_get_rxdesc(struct rtl8125_private *tp, struct RxDesc *RxDescBase, u32 const cur_rx) -{ - return (struct RxDesc*)((u8*)RxDescBase + (cur_rx * tp->RxDescLength)); -} - -static inline void -rtl8125_disable_hw_interrupt_v2(struct rtl8125_private *tp, - u32 message_id) -{ - RTL_W32(tp, IMR_V2_CLEAR_REG_8125, BIT(message_id)); -} - -static inline void -rtl8125_enable_hw_interrupt_v2(struct rtl8125_private *tp, u32 message_id) -{ - RTL_W32(tp, IMR_V2_SET_REG_8125, BIT(message_id)); -} - -int rtl8125_open(struct net_device *dev); -int rtl8125_close(struct net_device *dev); -void rtl8125_hw_config(struct net_device *dev); -void rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, u32 message_id, u8 timer_intmiti_val); -void rtl8125_set_rx_q_num(struct rtl8125_private *tp, unsigned int num_rx_queues); -void rtl8125_set_tx_q_num(struct rtl8125_private *tp, unsigned int num_tx_queues); -void rtl8125_hw_start(struct net_device *dev); -void rtl8125_hw_reset(struct net_device *dev); -void rtl8125_tx_clear(struct rtl8125_private *tp); -void rtl8125_rx_clear(struct rtl8125_private *tp); -int rtl8125_init_ring(struct net_device *dev); -void rtl8125_hw_set_rx_packet_filter(struct net_device *dev); -void rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp); -int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr); - -#ifndef ENABLE_LIB_SUPPORT -static inline void rtl8125_lib_reset_prepare(struct rtl8125_private *tp) { } -static inline void rtl8125_lib_reset_complete(struct rtl8125_private *tp) { } -#endif - -#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) -#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) -#define HW_SUPPORT_D0_SPEED_UP(_M) ((_M)->HwSuppD0SpeedUpVer > 0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netdev_mc_count(dev) ((dev)->mc_count) -#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) -#define netdev_for_each_mc_addr(mclist, dev) \ - for (mclist = dev->mc_list; mclist; mclist = mclist->next) -#endif - -#endif /* __R8125_H */ diff --git a/r8125/src/r8125_dash.h b/r8125/src/r8125_dash.h deleted file mode 100755 index f86d4255a..000000000 --- a/r8125/src/r8125_dash.h +++ /dev/null @@ -1,261 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8125_DASH_H -#define _LINUX_R8125_DASH_H - -#include - -#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2 - -enum rtl_dash_cmd { - RTL_DASH_ARP_NS_OFFLOAD = 0, - RTL_DASH_SET_OOB_IPMAC, - RTL_DASH_NOTIFY_OOB, - - RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW, - RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE, - RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA, - RTL_DASH_OOB_REQ, - RTL_DASH_OOB_ACK, - RTL_DASH_DETACH_OOB_REQ, - RTL_DASH_DETACH_OOB_ACK, - - RTL_FW_SET_IPV4 = 0x10, - RTL_FW_GET_IPV4, - RTL_FW_SET_IPV6, - RTL_FW_GET_IPV6, - RTL_FW_SET_EXT_SNMP, - RTL_FW_GET_EXT_SNMP, - RTL_FW_SET_WAKEUP_PATTERN, - RTL_FW_GET_WAKEUP_PATTERN, - RTL_FW_DEL_WAKEUP_PATTERN, - - RTLT_DASH_COMMAND_INVALID, -}; - -struct rtl_dash_ip_mac { - struct sockaddr ifru_addr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; -}; - -struct rtl_dash_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -struct settings_ipv4 { - __u32 IPv4addr; - __u32 IPv4mask; - __u32 IPv4Gateway; -}; - -struct settings_ipv6 { - __u32 reserved; - __u32 prefixLen; - __u16 IPv6addr[8]; - __u16 IPv6Gateway[8]; -}; - -struct settings_ext_snmp { - __u16 index; - __u16 oid_get_len; - __u8 oid_for_get[24]; - __u8 reserved0[26]; - __u16 value_len; - __u8 value[256]; - __u8 supported; - __u8 reserved1[27]; -}; - -struct wakeup_pattern { - __u8 index; - __u8 valid; - __u8 start; - __u8 length; - __u8 name[36]; - __u8 mask[16]; - __u8 pattern[128]; - __u32 reserved[2]; -}; - -typedef struct _RX_DASH_FROM_FW_DESC { - u16 length; - u8 statusLowByte; - u8 statusHighByte; - u32 resv; - u64 BufferAddress; -} -RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC; - -typedef struct _TX_DASH_SEND_FW_DESC { - u16 length; - u8 statusLowByte; - u8 statusHighByte; - u32 resv; - u64 BufferAddress; -} -TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC; - -typedef struct _OSOOBHdr { - u32 len; - u8 type; - u8 flag; - u8 hostReqV; - u8 res; -} -OSOOBHdr, *POSOOBHdr; - -typedef struct _RX_DASH_BUFFER_TYPE_2 { - OSOOBHdr oobhdr; - u8 RxDataBuffer[0]; -} -RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2; - -#define ALIGN_8 (0x7) -#define ALIGN_16 (0xf) -#define ALIGN_32 (0x1f) -#define ALIGN_64 (0x3f) -#define ALIGN_256 (0xff) -#define ALIGN_4096 (0xfff) - -#define OCP_REG_CONFIG0 (0x10) -#define OCP_REG_CONFIG0_REV_F (0xB8) -#define OCP_REG_DASH_POLL (0x30) -#define OCP_REG_HOST_REQ (0x34) -#define OCP_REG_DASH_REQ (0x35) -#define OCP_REG_CR (0x36) -#define OCP_REG_DMEMSTA (0x38) -#define OCP_REG_GPHYAR (0x60) - - -#define OCP_REG_CONFIG0_DASHEN BIT_15 -#define OCP_REG_CONFIG0_OOBRESET BIT_14 -#define OCP_REG_CONFIG0_APRDY BIT_13 -#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12 -#define OCP_REG_CONFIG0_DRIVERRDY BIT_11 -#define OCP_REG_CONFIG0_OOB_WDT BIT_9 -#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 -#define OCP_REG_CONFIG0_TLSEN BIT_7 - -#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0 ) -#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1 ) -#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2 ) -#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3 ) - -#define RECV_FROM_FW_BUF_SIZE (1520) -#define SEND_TO_FW_BUF_SIZE (1520) - -#define RX_DASH_FROM_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7 - -#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3) -#define TXS_EXC BIT_4 -#define TXS_LNKF BIT_5 -#define TXS_OWC BIT_6 -#define TXS_TES BIT_7 -#define TXS_UNF BIT_9 -#define TXS_LGSEN BIT_11 -#define TXS_LS BIT_12 -#define TXS_FS BIT_13 -#define TXS_EOR BIT_14 -#define TXS_OWN BIT_15 - -#define TPPool_HRDY 0x20 - -#define HostReqReg (0xC0) -#define SystemMasterDescStartAddrLow (0xF0) -#define SystemMasterDescStartAddrHigh (0xF4) -#define SystemSlaveDescStartAddrLow (0xF8) -#define SystemSlaveDescStartAddrHigh (0xFC) - -//DASH Request Type -#define WSMANREG 0x01 -#define OSPUSHDATA 0x02 - -#define RXS_OWN BIT_15 -#define RXS_EOR BIT_14 -#define RXS_FS BIT_13 -#define RXS_LS BIT_12 - -#define ISRIMR_DP_DASH_OK BIT_15 -#define ISRIMR_DP_HOST_OK BIT_13 -#define ISRIMR_DP_REQSYS_OK BIT_11 - -#define ISRIMR_DASH_INTR_EN BIT_12 -#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15 - -#define ISRIMR_DASH_TYPE2_ROK BIT_0 -#define ISRIMR_DASH_TYPE2_RDU BIT_1 -#define ISRIMR_DASH_TYPE2_TOK BIT_2 -#define ISRIMR_DASH_TYPE2_TDU BIT_3 -#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4 -#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5 -#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6 - -#define CMAC_OOB_STOP 0x25 -#define CMAC_OOB_INIT 0x26 -#define CMAC_OOB_RESET 0x2a - -#define NO_BASE_ADDRESS 0x00000000 -#define RTL8168FP_OOBMAC_BASE 0xBAF70000 -#define RTL8168FP_CMAC_IOBASE 0xBAF20000 -#define RTL8168FP_KVM_BASE 0xBAF80400 -#define CMAC_SYNC_REG 0x20 -#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98 -#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F - -/* cmac write/read MMIO register */ -#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg))) - -int rtl8125_dash_ioctl(struct net_device *dev, struct ifreq *ifr); -void HandleDashInterrupt(struct net_device *dev); -int AllocateDashShareMemory(struct net_device *dev); -void FreeAllocatedDashShareMemory(struct net_device *dev); -void DashHwInit(struct net_device *dev); - - -#endif /* _LINUX_R8125_DASH_H */ diff --git a/r8125/src/r8125_firmware.c b/r8125/src/r8125_firmware.c deleted file mode 100755 index ac4ea626b..000000000 --- a/r8125/src/r8125_firmware.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include - -#include "r8125_firmware.h" - -enum rtl_fw_opcode { - PHY_READ = 0x0, - PHY_DATA_OR = 0x1, - PHY_DATA_AND = 0x2, - PHY_BJMPN = 0x3, - PHY_MDIO_CHG = 0x4, - PHY_CLEAR_READCOUNT = 0x7, - PHY_WRITE = 0x8, - PHY_READCOUNT_EQ_SKIP = 0x9, - PHY_COMP_EQ_SKIPN = 0xa, - PHY_COMP_NEQ_SKIPN = 0xb, - PHY_WRITE_PREVIOUS = 0xc, - PHY_SKIPN = 0xd, - PHY_DELAY_MS = 0xe, -}; - -struct fw_info { - u32 magic; - char version[RTL8125_VER_SIZE]; - __le32 fw_start; - __le32 fw_len; - u8 chksum; -} __packed; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) -#endif -#define FW_OPCODE_SIZE sizeof_field(struct rtl8125_fw_phy_action, code[0]) - -static bool rtl8125_fw_format_ok(struct rtl8125_fw *rtl_fw) -{ - const struct firmware *fw = rtl_fw->fw; - struct fw_info *fw_info = (struct fw_info *)fw->data; - struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; - - if (fw->size < FW_OPCODE_SIZE) - return false; - - if (!fw_info->magic) { - size_t i, size, start; - u8 checksum = 0; - - if (fw->size < sizeof(*fw_info)) - return false; - - for (i = 0; i < fw->size; i++) - checksum += fw->data[i]; - if (checksum != 0) - return false; - - start = le32_to_cpu(fw_info->fw_start); - if (start > fw->size) - return false; - - size = le32_to_cpu(fw_info->fw_len); - if (size > (fw->size - start) / FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, fw_info->version, RTL8125_VER_SIZE); - - pa->code = (__le32 *)(fw->data + start); - pa->size = size; - } else { - if (fw->size % FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8125_VER_SIZE); - - pa->code = (__le32 *)fw->data; - pa->size = fw->size / FW_OPCODE_SIZE; - } - - return true; -} - -static bool rtl8125_fw_data_ok(struct rtl8125_fw *rtl_fw) -{ - struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 val = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - - switch (action >> 28) { - case PHY_READ: - case PHY_DATA_OR: - case PHY_DATA_AND: - case PHY_CLEAR_READCOUNT: - case PHY_WRITE: - case PHY_WRITE_PREVIOUS: - case PHY_DELAY_MS: - break; - - case PHY_MDIO_CHG: - if (val > 1) - goto out; - break; - - case PHY_BJMPN: - if (regno > index) - goto out; - break; - case PHY_READCOUNT_EQ_SKIP: - if (index + 2 >= pa->size) - goto out; - break; - case PHY_COMP_EQ_SKIPN: - case PHY_COMP_NEQ_SKIPN: - case PHY_SKIPN: - if (index + 1 + regno >= pa->size) - goto out; - break; - - default: - dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); - return false; - } - } - - return true; -out: - dev_err(rtl_fw->dev, "Out of range of firmware\n"); - return false; -} - -void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw) -{ - struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; - rtl8125_fw_write_t fw_write = rtl_fw->phy_write; - rtl8125_fw_read_t fw_read = rtl_fw->phy_read; - int predata = 0, count = 0; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 data = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - enum rtl_fw_opcode opcode = action >> 28; - - if (!action) - break; - - switch (opcode) { - case PHY_READ: - predata = fw_read(tp, regno); - count++; - break; - case PHY_DATA_OR: - predata |= data; - break; - case PHY_DATA_AND: - predata &= data; - break; - case PHY_BJMPN: - index -= (regno + 1); - break; - case PHY_MDIO_CHG: - if (data) { - fw_write = rtl_fw->mac_mcu_write; - fw_read = rtl_fw->mac_mcu_read; - } else { - fw_write = rtl_fw->phy_write; - fw_read = rtl_fw->phy_read; - } - - break; - case PHY_CLEAR_READCOUNT: - count = 0; - break; - case PHY_WRITE: - fw_write(tp, regno, data); - break; - case PHY_READCOUNT_EQ_SKIP: - if (count == data) - index++; - break; - case PHY_COMP_EQ_SKIPN: - if (predata == data) - index += regno; - break; - case PHY_COMP_NEQ_SKIPN: - if (predata != data) - index += regno; - break; - case PHY_WRITE_PREVIOUS: - fw_write(tp, regno, predata); - break; - case PHY_SKIPN: - index += regno; - break; - case PHY_DELAY_MS: - mdelay(data); - break; - } - } -} - -void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw) -{ - release_firmware(rtl_fw->fw); -} - -int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw) -{ - int rc; - - rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); - if (rc < 0) - goto out; - - if (!rtl8125_fw_format_ok(rtl_fw) || !rtl8125_fw_data_ok(rtl_fw)) { - release_firmware(rtl_fw->fw); - rc = -EINVAL; - goto out; - } - - return 0; -out: - dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", - rtl_fw->fw_name, rc); - return rc; -} diff --git a/r8125/src/r8125_firmware.h b/r8125/src/r8125_firmware.h deleted file mode 100755 index 1961be5d5..000000000 --- a/r8125/src/r8125_firmware.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_FIRMWARE_H -#define _LINUX_rtl8125_FIRMWARE_H - -#include -#include - -struct rtl8125_private; -typedef void (*rtl8125_fw_write_t)(struct rtl8125_private *tp, u16 reg, u16 val); -typedef u32 (*rtl8125_fw_read_t)(struct rtl8125_private *tp, u16 reg); - -#define RTL8125_VER_SIZE 32 - -struct rtl8125_fw { - rtl8125_fw_write_t phy_write; - rtl8125_fw_read_t phy_read; - rtl8125_fw_write_t mac_mcu_write; - rtl8125_fw_read_t mac_mcu_read; - const struct firmware *fw; - const char *fw_name; - struct device *dev; - - char version[RTL8125_VER_SIZE]; - - struct rtl8125_fw_phy_action { - __le32 *code; - size_t size; - } phy_action; -}; - -int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw); -void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw); -void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw); - -#endif /* _LINUX_rtl8125_FIRMWARE_H */ diff --git a/r8125/src/r8125_n.c b/r8125/src/r8125_n.c deleted file mode 100755 index fd96e8f8e..000000000 --- a/r8125/src/r8125_n.c +++ /dev/null @@ -1,15150 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -/* - * This driver is modified from r8169.c in Linux kernel 2.6.18 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#include -#include -#endif -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) -#include -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) -#else -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) -#include -#endif - -#include -#include - -#include "r8125.h" -#include "rtl_eeprom.h" -#include "rtltool.h" -#include "r8125_firmware.h" - -#ifdef ENABLE_R8125_PROCFS -#include -#include -#endif - -#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw" -#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw" - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -static const struct { - const char *name; - const char *fw_name; -} rtl_chip_fw_infos[] = { - /* PCI-E devices. */ - [CFG_METHOD_2] = {"RTL8125A" }, - [CFG_METHOD_3] = {"RTL8125A", FIRMWARE_8125A_3}, - [CFG_METHOD_4] = {"RTL8125B", }, - [CFG_METHOD_5] = {"RTL8125B", FIRMWARE_8125B_2}, - [CFG_METHOD_DEFAULT] = {"Unknown", }, -}; - -#define _R(NAME,MAC,RCR,MASK,JumFrameSz) \ - { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz } - -static const struct { - const char *name; - u8 mcfg; - u32 RCR_Cfg; - u32 RxConfigMask; /* Clears the bits supported by this chip */ - u32 jumbo_frame_sz; -} rtl_chip_info[] = { - _R("RTL8125A", - CFG_METHOD_2, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125A", - CFG_METHOD_3, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125B", - CFG_METHOD_4, - BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125B", - CFG_METHOD_5, - BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("Unknown", - CFG_METHOD_DEFAULT, - (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_1k) -}; -#undef _R - - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -static struct pci_device_id rtl8125_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x3000), }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8125_pci_tbl); - -static int rx_copybreak = 0; -static int use_dac = 1; -static int timer_count = 0x2600; -static int timer_count_v2 = (0x2600 / 0x100); - -static struct { - u32 msg_enable; -} debug = { -1 }; - -static unsigned int speed_mode = SPEED_2500; -static unsigned int duplex_mode = DUPLEX_FULL; -static unsigned int autoneg_mode = AUTONEG_ENABLE; -static unsigned int advertising_mode = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full; -#ifdef CONFIG_ASPM -static int aspm = 1; -#else -static int aspm = 0; -#endif -#ifdef ENABLE_S5WOL -static int s5wol = 1; -#else -static int s5wol = 0; -#endif -#ifdef ENABLE_S5_KEEP_CURR_MAC -static int s5_keep_curr_mac = 1; -#else -static int s5_keep_curr_mac = 0; -#endif -#ifdef ENABLE_EEE -static int eee_enable = 1; -#else -static int eee_enable = 0; -#endif -#ifdef CONFIG_SOC_LAN -static ulong hwoptimize = HW_PATCH_SOC_LAN; -#else -static ulong hwoptimize = 0; -#endif -#ifdef ENABLE_S0_MAGIC_PACKET -static int s0_magic_packet = 1; -#else -static int s0_magic_packet = 0; -#endif -#ifdef ENABLE_TX_NO_CLOSE -static int tx_no_close_enable = 1; -#else -static int tx_no_close_enable = 0; -#endif -#ifdef ENABLE_PTP_MASTER_MODE -static int enable_ptp_master_mode = 1; -#else -static int enable_ptp_master_mode = 0; -#endif -#ifdef DISABLE_PM_SUPPORT -static int disable_pm_support = 1; -#else -static int disable_pm_support = 0; -#endif - -MODULE_AUTHOR("Realtek and the Linux r8125 crew "); -MODULE_DESCRIPTION("Realtek RTL8125 2.5Gigabit Ethernet driver"); - -module_param(speed_mode, uint, 0); -MODULE_PARM_DESC(speed_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(duplex_mode, uint, 0); -MODULE_PARM_DESC(duplex_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(autoneg_mode, uint, 0); -MODULE_PARM_DESC(autoneg_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(advertising_mode, uint, 0); -MODULE_PARM_DESC(advertising_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(aspm, int, 0); -MODULE_PARM_DESC(aspm, "Enable ASPM."); - -module_param(s5wol, int, 0); -MODULE_PARM_DESC(s5wol, "Enable Shutdown Wake On Lan."); - -module_param(s5_keep_curr_mac, int, 0); -MODULE_PARM_DESC(s5_keep_curr_mac, "Enable Shutdown Keep Current MAC Address."); - -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); - -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); - -module_param(timer_count, int, 0); -MODULE_PARM_DESC(timer_count, "Timer Interrupt Interval."); - -module_param(eee_enable, int, 0); -MODULE_PARM_DESC(eee_enable, "Enable Energy Efficient Ethernet."); - -module_param(hwoptimize, ulong, 0); -MODULE_PARM_DESC(hwoptimize, "Enable HW optimization function."); - -module_param(s0_magic_packet, int, 0); -MODULE_PARM_DESC(s0_magic_packet, "Enable S0 Magic Packet."); - -module_param(tx_no_close_enable, int, 0); -MODULE_PARM_DESC(tx_no_close_enable, "Enable TX No Close."); - -module_param(enable_ptp_master_mode, int, 0); -MODULE_PARM_DESC(enable_ptp_master_mode, "Enable PTP Master Mode."); - -module_param(disable_pm_support, int, 0); -MODULE_PARM_DESC(disable_pm_support, "Disable PM support."); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -#endif//LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - -MODULE_LICENSE("GPL"); -#ifdef ENABLE_USE_FIRMWARE_FILE -MODULE_FIRMWARE(FIRMWARE_8125A_3); -MODULE_FIRMWARE(FIRMWARE_8125B_2); -#endif - -MODULE_VERSION(RTL8125_VERSION); - -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8125_esd_timer(unsigned long __opaque); -#else -static void rtl8125_esd_timer(struct timer_list *t); -#endif -*/ -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8125_link_timer(unsigned long __opaque); -#else -static void rtl8125_link_timer(struct timer_list *t); -#endif -*/ - -static netdev_tx_t rtl8125_start_xmit(struct sk_buff *skb, struct net_device *dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance); -#endif -static void rtl8125_set_rx_mode(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue); -#else -static void rtl8125_tx_timeout(struct net_device *dev); -#endif -static struct net_device_stats *rtl8125_get_stats(struct net_device *dev); -static int rtl8125_rx_interrupt(struct net_device *, struct rtl8125_private *, struct rtl8125_rx_ring *, napi_budget); -static int rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget); -static int rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, const int message_id, int budget); -static int rtl8125_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8125_down(struct net_device *dev); - -static int rtl8125_set_mac_address(struct net_device *dev, void *p); -static void rtl8125_rar_set(struct rtl8125_private *tp, uint8_t *addr); -static void rtl8125_desc_addr_fill(struct rtl8125_private *); -static void rtl8125_tx_desc_init(struct rtl8125_private *tp); -static void rtl8125_rx_desc_init(struct rtl8125_private *tp); - -static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, u16 RegAddr); -static u16 rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp); -static void rtl8125_phy_power_up(struct net_device *dev); -static void rtl8125_phy_power_down(struct net_device *dev); -static int rtl8125_set_speed(struct net_device *dev, u8 autoneg, u32 speed, u8 duplex, u32 adv); -static bool rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp); -static bool rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp); - -#ifdef CONFIG_R8125_NAPI -static int rtl8125_poll(napi_ptr napi, napi_budget budget); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_reset_task(void *_data); -static void rtl8125_esd_task(void *_data); -static void rtl8125_linkchg_task(void *_data); -#else -static void rtl8125_reset_task(struct work_struct *work); -static void rtl8125_esd_task(struct work_struct *work); -static void rtl8125_linkchg_task(struct work_struct *work); -#endif -static void rtl8125_schedule_reset_work(struct rtl8125_private *tp); -static void rtl8125_schedule_esd_work(struct rtl8125_private *tp); -static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp); -static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp); -static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp); - -static inline struct device *tp_to_dev(struct rtl8125_private *tp) -{ - return &tp->pci_dev->dev; -} - -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) && \ - LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,00))) -void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, - u32 legacy_u32) -{ - bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); - dst[0] = legacy_u32; -} - -bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, - const unsigned long *src) -{ - bool retval = true; - - /* TODO: following test will soon always be true */ - if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); - - bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_fill(ext, 32); - bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - if (bitmap_intersects(ext, src, - __ETHTOOL_LINK_MODE_MASK_NBITS)) { - /* src mask goes beyond bit 31 */ - retval = false; - } - } - *legacy_u32 = src[0]; - return retval; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#ifndef LPA_1000FULL -#define LPA_1000FULL 0x0800 -#endif - -#ifndef LPA_1000HALF -#define LPA_1000HALF 0x0400 -#endif - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - random_ether_addr(dev->dev_addr); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#undef ethtool_ops -#define ethtool_ops _kc_ethtool_ops - -struct _kc_ethtool_ops { - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - int (*set_settings)(struct net_device *, struct ethtool_cmd *); - void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); - int (*get_regs_len)(struct net_device *); - void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); - void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); - int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); - u32 (*get_msglevel)(struct net_device *); - void (*set_msglevel)(struct net_device *, u32); - int (*nway_reset)(struct net_device *); - u32 (*get_link)(struct net_device *); - int (*get_eeprom_len)(struct net_device *); - int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); - int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); - void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); - int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); - void (*get_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - int (*set_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - u32 (*get_rx_csum)(struct net_device *); - int (*set_rx_csum)(struct net_device *, u32); - u32 (*get_tx_csum)(struct net_device *); - int (*set_tx_csum)(struct net_device *, u32); - u32 (*get_sg)(struct net_device *); - int (*set_sg)(struct net_device *, u32); - u32 (*get_tso)(struct net_device *); - int (*set_tso)(struct net_device *, u32); - int (*self_test_count)(struct net_device *); - void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); - void (*get_strings)(struct net_device *, u32 stringset, u8 *); - int (*phys_id)(struct net_device *, u32); - int (*get_stats_count)(struct net_device *); - void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, - u64 *); -} *ethtool_ops = NULL; - -#undef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) -#ifndef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev,ops) \ - ( (netdev)->ethtool_ops = (ops) ) -#endif //SET_ETHTOOL_OPS -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) -#ifndef netif_msg_init -#define netif_msg_init _kc_netif_msg_init -/* copied from linux kernel 2.6.20 include/linux/netdevice.h */ -static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) -{ - /* use default */ - if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) - return default_msg_enable_bits; - if (debug_value == 0) /* no output */ - return 0; - /* set low N bits */ - return (1 << debug_value) - 1; -} - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) -static inline void eth_copy_and_sum (struct sk_buff *dest, - const unsigned char *src, - int len, int base) -{ - memcpy (dest->data, src, len); -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 /include/linux/time.h */ -/* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L - -/* copied from linux kernel 2.6.20 /include/linux/jiffies.h */ -/* - * Change timeval to jiffies, trying to avoid the - * most obvious overflows.. - * - * And some not so obvious. - * - * Note that we don't want to return MAX_LONG, because - * for various timeout reasons we often end up having - * to wait "jiffies+1" in order to guarantee that we wait - * at _least_ "jiffies" - so "jiffies+1" had better still - * be positive. - */ -#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) - -/* - * Convert jiffies to milliseconds and back. - * - * Avoid unnecessary multiplications/divisions in the - * two most common HZ cases: - */ -static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) -{ -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (MSEC_PER_SEC / HZ) * j; -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); -#else - return (j * MSEC_PER_SEC) / HZ; -#endif -} - -static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) -{ - if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return m * (HZ / MSEC_PER_SEC); -#else - return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; -#endif -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -/* copied from linux kernel 2.6.12.6 /include/linux/pm.h */ -typedef int __bitwise pci_power_t; - -/* copied from linux kernel 2.6.12.6 /include/linux/pci.h */ -typedef u32 __bitwise pm_message_t; - -#define PCI_D0 ((pci_power_t __force) 0) -#define PCI_D1 ((pci_power_t __force) 1) -#define PCI_D2 ((pci_power_t __force) 2) -#define PCI_D3hot ((pci_power_t __force) 3) -#define PCI_D3cold ((pci_power_t __force) 4) -#define PCI_POWER_ERROR ((pci_power_t __force) -1) - -/* copied from linux kernel 2.6.12.6 /drivers/pci/pci.c */ -/** - * pci_choose_state - Choose the power state of a PCI device - * @dev: PCI device to be suspended - * @state: target sleep state for the whole system. This is the value - * that is passed to suspend() function. - * - * Returns PCI power state suitable for given device and given system - * message. - */ - -pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) -{ - if (!pci_find_capability(dev, PCI_CAP_ID_PM)) - return PCI_D0; - - switch (state) { - case 0: - return PCI_D0; - case 3: - return PCI_D3hot; - default: - printk("They asked me for state %d\n", state); -// BUG(); - } - return PCI_D0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -/** - * msleep_interruptible - sleep waiting for waitqueue interruptions - * @msecs: Time in milliseconds to sleep for - */ -#define msleep_interruptible _kc_msleep_interruptible -unsigned long _kc_msleep_interruptible(unsigned int msecs) -{ - unsigned long timeout = _kc_msecs_to_jiffies(msecs); - - while (timeout && !signal_pending(current)) { - set_current_state(TASK_INTERRUPTIBLE); - timeout = schedule_timeout(timeout); - } - return _kc_jiffies_to_msecs(timeout); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 include/linux/sched.h */ -#ifndef __sched -#define __sched __attribute__((__section__(".sched.text"))) -#endif - -/* copied from linux kernel 2.6.20 kernel/timer.c */ -signed long __sched schedule_timeout_uninterruptible(signed long timeout) -{ - __set_current_state(TASK_UNINTERRUPTIBLE); - return schedule_timeout(timeout); -} - -/* copied from linux kernel 2.6.20 include/linux/mii.h */ -#undef if_mii -#define if_mii _kc_if_mii -static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) -{ - return (struct mii_ioctl_data *) &rq->ifr_ifru; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - -static u32 rtl8125_read_thermal_sensor(struct rtl8125_private *tp) -{ - u16 ts_digout; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - ts_digout = mdio_direct_read_phy_ocp(tp, 0xBD84); - ts_digout &= 0x3ff; - break; - default: - ts_digout = 0xffff; - break; - } - - return ts_digout; -} - -int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr) -{ - u32 cmd; - u32 WaitCnt; - int retval = -1; - - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - - if (WaitCnt <= 20) - retval = 0; - - return retval; -} - -#ifdef ENABLE_R8125_PROCFS -/**************************************************************************** -* -----------------------------PROCFS STUFF------------------------- -***************************************************************************** -*/ - -static struct proc_dir_entry *rtl8125_proc; -static int proc_init_num = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -static int proc_get_driver_variable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump Driver Variable\n"); - - rtnl_lock(); - - seq_puts(m, "Variable\tValue\n----------\t-----\n"); - seq_printf(m, "MODULENAME\t%s\n", MODULENAME); - seq_printf(m, "driver version\t%s\n", RTL8125_VERSION); - seq_printf(m, "mcfg\t%d\n", tp->mcfg); - seq_printf(m, "chipset\t%d\n", tp->chipset); - seq_printf(m, "chipset_name\t%s\n", rtl_chip_info[tp->chipset].name); - seq_printf(m, "mtu\t%d\n", dev->mtu); - seq_printf(m, "NUM_RX_DESC\t0x%x\n", NUM_RX_DESC); - seq_printf(m, "cur_rx0\t0x%x\n", tp->rx_ring[0].cur_rx); - seq_printf(m, "dirty_rx0\t0x%x\n", tp->rx_ring[0].dirty_rx); - seq_printf(m, "cur_rx1\t0x%x\n", tp->rx_ring[1].cur_rx); - seq_printf(m, "dirty_rx1\t0x%x\n", tp->rx_ring[1].dirty_rx); - seq_printf(m, "cur_rx2\t0x%x\n", tp->rx_ring[2].cur_rx); - seq_printf(m, "dirty_rx2\t0x%x\n", tp->rx_ring[2].dirty_rx); - seq_printf(m, "cur_rx3\t0x%x\n", tp->rx_ring[3].cur_rx); - seq_printf(m, "dirty_rx3\t0x%x\n", tp->rx_ring[3].dirty_rx); - seq_printf(m, "NUM_TX_DESC\t0x%x\n", NUM_TX_DESC); - seq_printf(m, "cur_tx0\t0x%x\n", tp->tx_ring[0].cur_tx); - seq_printf(m, "dirty_tx0\t0x%x\n", tp->tx_ring[0].dirty_tx); - seq_printf(m, "cur_tx1\t0x%x\n", tp->tx_ring[1].cur_tx); - seq_printf(m, "dirty_tx1\t0x%x\n", tp->tx_ring[1].dirty_tx); - seq_printf(m, "rx_buf_sz\t0x%x\n", tp->rx_buf_sz); - seq_printf(m, "esd_flag\t0x%x\n", tp->esd_flag); - seq_printf(m, "pci_cfg_is_read\t0x%x\n", tp->pci_cfg_is_read); - seq_printf(m, "rtl8125_rx_config\t0x%x\n", tp->rtl8125_rx_config); - seq_printf(m, "cp_cmd\t0x%x\n", tp->cp_cmd); - seq_printf(m, "intr_mask\t0x%x\n", tp->intr_mask); - seq_printf(m, "timer_intr_mask\t0x%x\n", tp->timer_intr_mask); - seq_printf(m, "wol_enabled\t0x%x\n", tp->wol_enabled); - seq_printf(m, "wol_opts\t0x%x\n", tp->wol_opts); - seq_printf(m, "efuse_ver\t0x%x\n", tp->efuse_ver); - seq_printf(m, "eeprom_type\t0x%x\n", tp->eeprom_type); - seq_printf(m, "autoneg\t0x%x\n", tp->autoneg); - seq_printf(m, "duplex\t0x%x\n", tp->duplex); - seq_printf(m, "speed\t%d\n", tp->speed); - seq_printf(m, "advertising\t0x%x\n", tp->advertising); - seq_printf(m, "eeprom_len\t0x%x\n", tp->eeprom_len); - seq_printf(m, "cur_page\t0x%x\n", tp->cur_page); - seq_printf(m, "bios_setting\t0x%x\n", tp->bios_setting); - seq_printf(m, "features\t0x%x\n", tp->features); - seq_printf(m, "org_pci_offset_99\t0x%x\n", tp->org_pci_offset_99); - seq_printf(m, "org_pci_offset_180\t0x%x\n", tp->org_pci_offset_180); - seq_printf(m, "issue_offset_99_event\t0x%x\n", tp->issue_offset_99_event); - seq_printf(m, "org_pci_offset_80\t0x%x\n", tp->org_pci_offset_80); - seq_printf(m, "org_pci_offset_81\t0x%x\n", tp->org_pci_offset_81); - seq_printf(m, "use_timer_interrrupt\t0x%x\n", tp->use_timer_interrrupt); - seq_printf(m, "HwIcVerUnknown\t0x%x\n", tp->HwIcVerUnknown); - seq_printf(m, "NotWrRamCodeToMicroP\t0x%x\n", tp->NotWrRamCodeToMicroP); - seq_printf(m, "NotWrMcuPatchCode\t0x%x\n", tp->NotWrMcuPatchCode); - seq_printf(m, "HwHasWrRamCodeToMicroP\t0x%x\n", tp->HwHasWrRamCodeToMicroP); - seq_printf(m, "sw_ram_code_ver\t0x%x\n", tp->sw_ram_code_ver); - seq_printf(m, "hw_ram_code_ver\t0x%x\n", tp->hw_ram_code_ver); - seq_printf(m, "rtk_enable_diag\t0x%x\n", tp->rtk_enable_diag); - seq_printf(m, "ShortPacketSwChecksum\t0x%x\n", tp->ShortPacketSwChecksum); - seq_printf(m, "UseSwPaddingShortPkt\t0x%x\n", tp->UseSwPaddingShortPkt); - seq_printf(m, "RequireAdcBiasPatch\t0x%x\n", tp->RequireAdcBiasPatch); - seq_printf(m, "AdcBiasPatchIoffset\t0x%x\n", tp->AdcBiasPatchIoffset); - seq_printf(m, "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n", tp->RequireAdjustUpsTxLinkPulseTiming); - seq_printf(m, "SwrCnt1msIni\t0x%x\n", tp->SwrCnt1msIni); - seq_printf(m, "HwSuppNowIsOobVer\t0x%x\n", tp->HwSuppNowIsOobVer); - seq_printf(m, "HwFiberModeVer\t0x%x\n", tp->HwFiberModeVer); - seq_printf(m, "HwFiberStat\t0x%x\n", tp->HwFiberStat); - seq_printf(m, "HwSwitchMdiToFiber\t0x%x\n", tp->HwSwitchMdiToFiber); - seq_printf(m, "NicCustLedValue\t0x%x\n", tp->NicCustLedValue); - seq_printf(m, "RequiredSecLanDonglePatch\t0x%x\n", tp->RequiredSecLanDonglePatch); - seq_printf(m, "HwSuppDashVer\t0x%x\n", tp->HwSuppDashVer); - seq_printf(m, "DASH\t0x%x\n", tp->DASH); - seq_printf(m, "dash_printer_enabled\t0x%x\n", tp->dash_printer_enabled); - seq_printf(m, "HwSuppKCPOffloadVer\t0x%x\n", tp->HwSuppKCPOffloadVer); - seq_printf(m, "speed_mode\t0x%x\n", speed_mode); - seq_printf(m, "duplex_mode\t0x%x\n", duplex_mode); - seq_printf(m, "autoneg_mode\t0x%x\n", autoneg_mode); - seq_printf(m, "advertising_mode\t0x%x\n", advertising_mode); - seq_printf(m, "aspm\t0x%x\n", aspm); - seq_printf(m, "s5wol\t0x%x\n", s5wol); - seq_printf(m, "s5_keep_curr_mac\t0x%x\n", s5_keep_curr_mac); - seq_printf(m, "eee_enable\t0x%x\n", tp->eee.eee_enabled); - seq_printf(m, "hwoptimize\t0x%lx\n", hwoptimize); - seq_printf(m, "proc_init_num\t0x%x\n", proc_init_num); - seq_printf(m, "s0_magic_packet\t0x%x\n", s0_magic_packet); - seq_printf(m, "HwSuppMagicPktVer\t0x%x\n", tp->HwSuppMagicPktVer); - seq_printf(m, "HwSuppLinkChgWakeUpVer\t0x%x\n", tp->HwSuppLinkChgWakeUpVer); - seq_printf(m, "HwSuppD0SpeedUpVer\t0x%x\n", tp->HwSuppD0SpeedUpVer); - seq_printf(m, "D0SpeedUpSpeed\t0x%x\n", tp->D0SpeedUpSpeed); - seq_printf(m, "HwSuppCheckPhyDisableModeVer\t0x%x\n", tp->HwSuppCheckPhyDisableModeVer); - seq_printf(m, "HwPkgDet\t0x%x\n", tp->HwPkgDet); - seq_printf(m, "HwSuppTxNoCloseVer\t0x%x\n", tp->HwSuppTxNoCloseVer); - seq_printf(m, "EnableTxNoClose\t0x%x\n", tp->EnableTxNoClose); - seq_printf(m, "NextHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].NextHwDesCloPtr); - seq_printf(m, "BeginHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].BeginHwDesCloPtr); - seq_printf(m, "NextHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].NextHwDesCloPtr); - seq_printf(m, "BeginHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].BeginHwDesCloPtr); - seq_printf(m, "InitRxDescType\t0x%x\n", tp->InitRxDescType); - seq_printf(m, "RxDescLength\t0x%x\n", tp->RxDescLength); - seq_printf(m, "num_rx_rings\t0x%x\n", tp->num_rx_rings); - seq_printf(m, "num_tx_rings\t0x%x\n", tp->num_tx_rings); - seq_printf(m, "tot_rx_rings\t0x%x\n", rtl8125_tot_rx_rings(tp)); - seq_printf(m, "tot_tx_rings\t0x%x\n", rtl8125_tot_tx_rings(tp)); - seq_printf(m, "EnableRss\t0x%x\n", tp->EnableRss); - seq_printf(m, "EnablePtp\t0x%x\n", tp->EnablePtp); - seq_printf(m, "ptp_master_mode\t0x%x\n", tp->ptp_master_mode); - seq_printf(m, "min_irq_nvecs\t0x%x\n", tp->min_irq_nvecs); - seq_printf(m, "irq_nvecs\t0x%x\n", tp->irq_nvecs); - seq_printf(m, "ring_lib_enabled\t0x%x\n", tp->ring_lib_enabled); - seq_printf(m, "HwSuppIsrVer\t0x%x\n", tp->HwSuppIsrVer); - seq_printf(m, "HwCurrIsrVer\t0x%x\n", tp->HwCurrIsrVer); -#ifdef ENABLE_PTP_SUPPORT - seq_printf(m, "tx_hwtstamp_timeouts\t0x%x\n", tp->tx_hwtstamp_timeouts); - seq_printf(m, "tx_hwtstamp_skipped\t0x%x\n", tp->tx_hwtstamp_skipped); -#endif - seq_printf(m, "random_mac\t0x%x\n", tp->random_mac); - seq_printf(m, "org_mac_addr\t%pM\n", tp->org_mac_addr); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - seq_printf(m, "perm_addr\t%pM\n", dev->perm_addr); -#endif - seq_printf(m, "dev_addr\t%pM\n", dev->dev_addr); - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_tally_counter(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - - seq_puts(m, "\nDump Tally Counter\n"); - - rtnl_lock(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - seq_puts(m, "\nDump Tally Counter Fail\n"); - goto out_unlock; - } - - rtl8125_dump_tally_counter(tp, paddr); - - seq_puts(m, "Statistics\tValue\n----------\t-----\n"); - seq_printf(m, "tx_packets\t%lld\n", le64_to_cpu(counters->tx_packets)); - seq_printf(m, "rx_packets\t%lld\n", le64_to_cpu(counters->rx_packets)); - seq_printf(m, "tx_errors\t%lld\n", le64_to_cpu(counters->tx_errors)); - seq_printf(m, "rx_errors\t%d\n", le32_to_cpu(counters->rx_errors)); - seq_printf(m, "rx_missed\t%d\n", le16_to_cpu(counters->rx_missed)); - seq_printf(m, "align_errors\t%d\n", le16_to_cpu(counters->align_errors)); - seq_printf(m, "tx_one_collision\t%d\n", le32_to_cpu(counters->tx_one_collision)); - seq_printf(m, "tx_multi_collision\t%d\n", le32_to_cpu(counters->tx_multi_collision)); - seq_printf(m, "rx_unicast\t%lld\n", le64_to_cpu(counters->rx_unicast)); - seq_printf(m, "rx_broadcast\t%lld\n", le64_to_cpu(counters->rx_broadcast)); - seq_printf(m, "rx_multicast\t%d\n", le32_to_cpu(counters->rx_multicast)); - seq_printf(m, "tx_aborted\t%d\n", le16_to_cpu(counters->tx_aborted)); - seq_printf(m, "tx_underrun\t%d\n", le16_to_cpu(counters->tx_underrun)); - - seq_printf(m, "tx_octets\t%lld\n", le64_to_cpu(counters->tx_octets)); - seq_printf(m, "rx_octets\t%lld\n", le64_to_cpu(counters->rx_octets)); - seq_printf(m, "rx_multicast64\t%lld\n", le64_to_cpu(counters->rx_multicast64)); - seq_printf(m, "tx_unicast64\t%lld\n", le64_to_cpu(counters->tx_unicast64)); - seq_printf(m, "tx_broadcast64\t%lld\n", le64_to_cpu(counters->tx_broadcast64)); - seq_printf(m, "tx_multicast64\t%lld\n", le64_to_cpu(counters->tx_multicast64)); - seq_printf(m, "tx_pause_on\t%d\n", le32_to_cpu(counters->tx_pause_on)); - seq_printf(m, "tx_pause_off\t%d\n", le32_to_cpu(counters->tx_pause_off)); - seq_printf(m, "tx_pause_all\t%d\n", le32_to_cpu(counters->tx_pause_all)); - seq_printf(m, "tx_deferred\t%d\n", le32_to_cpu(counters->tx_deferred)); - seq_printf(m, "tx_late_collision\t%d\n", le32_to_cpu(counters->tx_late_collision)); - seq_printf(m, "tx_all_collision\t%d\n", le32_to_cpu(counters->tx_all_collision)); - seq_printf(m, "tx_aborted32\t%d\n", le32_to_cpu(counters->tx_aborted32)); - seq_printf(m, "align_errors32\t%d\n", le32_to_cpu(counters->align_errors32)); - seq_printf(m, "rx_frame_too_long\t%d\n", le32_to_cpu(counters->rx_frame_too_long)); - seq_printf(m, "rx_runt\t%d\n", le32_to_cpu(counters->rx_runt)); - seq_printf(m, "rx_pause_on\t%d\n", le32_to_cpu(counters->rx_pause_on)); - seq_printf(m, "rx_pause_off\t%d\n", le32_to_cpu(counters->rx_pause_off)); - seq_printf(m, "rx_pause_all\t%d\n", le32_to_cpu(counters->rx_pause_all)); - seq_printf(m, "rx_unknown_opcode\t%d\n", le32_to_cpu(counters->rx_unknown_opcode)); - seq_printf(m, "rx_mac_error\t%d\n", le32_to_cpu(counters->rx_mac_error)); - seq_printf(m, "tx_underrun32\t%d\n", le32_to_cpu(counters->tx_underrun32)); - seq_printf(m, "rx_mac_missed\t%d\n", le32_to_cpu(counters->rx_mac_missed)); - seq_printf(m, "rx_tcam_dropped\t%d\n", le32_to_cpu(counters->rx_tcam_dropped)); - seq_printf(m, "tdu\t%d\n", le32_to_cpu(counters->tdu)); - seq_printf(m, "rdu\t%d\n", le32_to_cpu(counters->rdu)); - - seq_putc(m, '\n'); - -out_unlock: - rtnl_unlock(); - - return 0; -} - -static int proc_get_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - seq_puts(m, "\nDump MAC Registers\n"); - seq_puts(m, "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - seq_printf(m, "%02x ", byte_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pcie_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump PCIE PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_ephy_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_eth_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump Ethernet PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - seq_puts(m, "\n####################page 0##################\n "); - rtl8125_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_mdio_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_extended_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump Extended Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); - seq_printf(m, "%08x ", dword_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pci_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump PCI Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%03x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "%08x ", dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_temperature(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - u16 ts_digout, tj, fah; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - seq_puts(m, "\nChip Temperature\n"); - break; - default: - seq_puts(m, "\nThis Chip Does Not Support Dump Temperature\n"); - break; - } - - rtnl_lock(); - ts_digout = rtl8125_read_thermal_sensor(tp); - rtnl_unlock(); - - tj = ts_digout / 2; - if (ts_digout <= 512) { - tj = ts_digout / 2; - seq_printf(m, "Cel:%d\n", tj); - fah = tj * (9/5) + 32; - seq_printf(m, "Fah:%d\n", fah); - } else { - tj = (512 - ((ts_digout / 2) - 512)) / 2; - seq_printf(m, "Cel:-%d\n", tj); - fah = tj * (9/5) + 32; - seq_printf(m, "Fah:-%d\n", fah); - } - - seq_putc(m, '\n'); - return 0; -} -#else - -static int proc_get_driver_variable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Driver Driver\n"); - - rtnl_lock(); - - len += snprintf(page + len, count - len, - "Variable\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "MODULENAME\t%s\n" - "driver version\t%s\n" - "mcfg\t%d\n" - "chipset\t%d\n" - "chipset_name\t%s\n" - "mtu\t%d\n" - "NUM_RX_DESC\t0x%x\n" - "cur_rx0\t0x%x\n" - "dirty_rx0\t0x%x\n" - "cur_rx1\t0x%x\n" - "dirty_rx1\t0x%x\n" - "cur_rx2\t0x%x\n" - "dirty_rx2\t0x%x\n" - "cur_rx3\t0x%x\n" - "dirty_rx3\t0x%x\n" - "NUM_TX_DESC\t0x%x\n" - "cur_tx0\t0x%x\n" - "dirty_tx0\t0x%x\n" - "cur_tx1\t0x%x\n" - "dirty_tx1\t0x%x\n" - "rx_buf_sz\t0x%x\n" - "esd_flag\t0x%x\n" - "pci_cfg_is_read\t0x%x\n" - "rtl8125_rx_config\t0x%x\n" - "cp_cmd\t0x%x\n" - "intr_mask\t0x%x\n" - "timer_intr_mask\t0x%x\n" - "wol_enabled\t0x%x\n" - "wol_opts\t0x%x\n" - "efuse_ver\t0x%x\n" - "eeprom_type\t0x%x\n" - "autoneg\t0x%x\n" - "duplex\t0x%x\n" - "speed\t%d\n" - "advertising\t0x%x\n" - "eeprom_len\t0x%x\n" - "cur_page\t0x%x\n" - "bios_setting\t0x%x\n" - "features\t0x%x\n" - "org_pci_offset_99\t0x%x\n" - "org_pci_offset_180\t0x%x\n" - "issue_offset_99_event\t0x%x\n" - "org_pci_offset_80\t0x%x\n" - "org_pci_offset_81\t0x%x\n" - "use_timer_interrrupt\t0x%x\n" - "HwIcVerUnknown\t0x%x\n" - "NotWrRamCodeToMicroP\t0x%x\n" - "NotWrMcuPatchCode\t0x%x\n" - "HwHasWrRamCodeToMicroP\t0x%x\n" - "sw_ram_code_ver\t0x%x\n" - "hw_ram_code_ver\t0x%x\n" - "rtk_enable_diag\t0x%x\n" - "ShortPacketSwChecksum\t0x%x\n" - "UseSwPaddingShortPkt\t0x%x\n" - "RequireAdcBiasPatch\t0x%x\n" - "AdcBiasPatchIoffset\t0x%x\n" - "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n" - "SwrCnt1msIni\t0x%x\n" - "HwSuppNowIsOobVer\t0x%x\n" - "HwFiberModeVer\t0x%x\n" - "HwFiberStat\t0x%x\n" - "HwSwitchMdiToFiber\t0x%x\n" - "NicCustLedValue\t0x%x\n" - "RequiredSecLanDonglePatch\t0x%x\n" - "HwSuppDashVer\t0x%x\n" - "DASH\t0x%x\n" - "dash_printer_enabled\t0x%x\n" - "HwSuppKCPOffloadVer\t0x%x\n" - "speed_mode\t0x%x\n" - "duplex_mode\t0x%x\n" - "autoneg_mode\t0x%x\n" - "advertising_mode\t0x%x\n" - "aspm\t0x%x\n" - "s5wol\t0x%x\n" - "s5_keep_curr_mac\t0x%x\n" - "eee_enable\t0x%x\n" - "hwoptimize\t0x%lx\n" - "proc_init_num\t0x%x\n" - "s0_magic_packet\t0x%x\n" - "HwSuppMagicPktVer\t0x%x\n" - "HwSuppLinkChgWakeUpVer\t0x%x\n" - "HwSuppD0SpeedUpVer\t0x%x\n" - "D0SpeedUpSpeed\t0x%x\n" - "HwSuppCheckPhyDisableModeVer\t0x%x\n" - "HwPkgDet\t0x%x\n" - "HwSuppTxNoCloseVer\t0x%x\n" - "EnableTxNoClose\t0x%x\n" - "NextHwDesCloPtr0\t0x%x\n" - "BeginHwDesCloPtr0\t0x%x\n" - "NextHwDesCloPtr1\t0x%x\n" - "BeginHwDesCloPtr1\t0x%x\n" - "InitRxDescType\t0x%x\n" - "RxDescLength\t0x%x\n" - "num_rx_rings\t0x%x\n" - "num_tx_rings\t0x%x\n" - "tot_rx_rings\t0x%x\n" - "tot_tx_rings\t0x%x\n" - "EnableRss\t0x%x\n" - "EnablePtp\t0x%x\n" - "ptp_master_mode\t0x%x\n" - "min_irq_nvecs\t0x%x\n" - "irq_nvecs\t0x%x\n" - "ring_lib_enabled\t0x%x\n" - "HwSuppIsrVer\t0x%x\n" - "HwCurrIsrVer\t0x%x\n" -#ifdef ENABLE_PTP_SUPPORT - "tx_hwtstamp_timeouts\t0x%x\n" - "tx_hwtstamp_skipped\t0x%x\n" -#endif - "random_mac\t0x%x\n" - "org_mac_addr\t%pM\n" -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - "perm_addr\t%pM\n" -#endif - "dev_addr\t%pM\n", - MODULENAME, - RTL8125_VERSION, - tp->mcfg, - tp->chipset, - rtl_chip_info[tp->chipset].name, - dev->mtu, - NUM_RX_DESC, - tp->rx_ring[0].cur_rx, - tp->rx_ring[0].dirty_rx, - tp->rx_ring[1].cur_rx, - tp->rx_ring[1].dirty_rx, - tp->rx_ring[2].cur_rx, - tp->rx_ring[2].dirty_rx, - tp->rx_ring[3].cur_rx, - tp->rx_ring[3].dirty_rx, - NUM_TX_DESC, - tp->tx_ring[0].cur_tx, - tp->tx_ring[0].dirty_tx, - tp->tx_ring[1].cur_tx, - tp->tx_ring[1].dirty_tx, - tp->rx_buf_sz, - tp->esd_flag, - tp->pci_cfg_is_read, - tp->rtl8125_rx_config, - tp->cp_cmd, - tp->intr_mask, - tp->timer_intr_mask, - tp->wol_enabled, - tp->wol_opts, - tp->efuse_ver, - tp->eeprom_type, - tp->autoneg, - tp->duplex, - tp->speed, - tp->advertising, - tp->eeprom_len, - tp->cur_page, - tp->bios_setting, - tp->features, - tp->org_pci_offset_99, - tp->org_pci_offset_180, - tp->issue_offset_99_event, - tp->org_pci_offset_80, - tp->org_pci_offset_81, - tp->use_timer_interrrupt, - tp->HwIcVerUnknown, - tp->NotWrRamCodeToMicroP, - tp->NotWrMcuPatchCode, - tp->HwHasWrRamCodeToMicroP, - tp->sw_ram_code_ver, - tp->hw_ram_code_ver, - tp->rtk_enable_diag, - tp->ShortPacketSwChecksum, - tp->UseSwPaddingShortPkt, - tp->RequireAdcBiasPatch, - tp->AdcBiasPatchIoffset, - tp->RequireAdjustUpsTxLinkPulseTiming, - tp->SwrCnt1msIni, - tp->HwSuppNowIsOobVer, - tp->HwFiberModeVer, - tp->HwFiberStat, - tp->HwSwitchMdiToFiber, - tp->NicCustLedValue, - tp->RequiredSecLanDonglePatch, - tp->HwSuppDashVer, - tp->DASH, - tp->dash_printer_enabled, - tp->HwSuppKCPOffloadVer, - speed_mode, - duplex_mode, - autoneg_mode, - advertising_mode, - aspm, - s5wol, - s5_keep_curr_mac, - tp->eee.eee_enabled, - hwoptimize, - proc_init_num, - s0_magic_packet, - tp->HwSuppMagicPktVer, - tp->HwSuppLinkChgWakeUpVer, - tp->HwSuppD0SpeedUpVer, - tp->D0SpeedUpSpeed, - tp->HwSuppCheckPhyDisableModeVer, - tp->HwPkgDet, - tp->HwSuppTxNoCloseVer, - tp->EnableTxNoClose, - tp->tx_ring[0].NextHwDesCloPtr, - tp->tx_ring[0].BeginHwDesCloPtr, - tp->tx_ring[1].NextHwDesCloPtr, - tp->tx_ring[1].BeginHwDesCloPtr, - tp->InitRxDescType, - tp->RxDescLength, - tp->num_rx_rings, - tp->num_tx_rings, - tp->tot_rx_rings, - tp->tot_tx_rings, - tp->EnableRss, - tp->EnablePtp, - tp->ptp_master_mode, - tp->min_irq_nvecs, - tp->irq_nvecs, - tp->ring_lib_enabled, - tp->HwSuppIsrVer, - tp->HwCurrIsrVer, -#ifdef ENABLE_PTP_SUPPORT - tp->tx_hwtstamp_timeouts, - tp->tx_hwtstamp_skipped, -#endif - tp->random_mac, - tp->org_mac_addr, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - dev->perm_addr, -#endif - dev->dev_addr - ); - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_tally_counter(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Tally Counter\n"); - - rtnl_lock(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - len += snprintf(page + len, count - len, - "\nDump Tally Counter Fail\n"); - goto out_unlock; - } - - rtl8125_dump_tally_counter(tp, paddr); - - len += snprintf(page + len, count - len, - "Statistics\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "tx_packets\t%lld\n" - "rx_packets\t%lld\n" - "tx_errors\t%lld\n" - "rx_errors\t%d\n" - "rx_missed\t%d\n" - "align_errors\t%d\n" - "tx_one_collision\t%d\n" - "tx_multi_collision\t%d\n" - "rx_unicast\t%lld\n" - "rx_broadcast\t%lld\n" - "rx_multicast\t%d\n" - "tx_aborted\t%d\n" - "tx_underrun\t%d\n", - - "tx_octets\t%lld\n", - "rx_octets\t%lld\n", - "rx_multicast64\t%lld\n", - "tx_unicast64\t%lld\n", - "tx_broadcast64\t%lld\n", - "tx_multicast64\t%lld\n", - "tx_pause_on\t%d\n", - "tx_pause_off\t%d\n", - "tx_pause_all\t%d\n", - "tx_deferred\t%d\n", - "tx_late_collision\t%d\n", - "tx_all_collision\t%d\n", - "tx_aborted32\t%d\n", - "align_errors32\t%d\n", - "rx_frame_too_long\t%d\n", - "rx_runt\t%d\n", - "rx_pause_on\t%d\n", - "rx_pause_off\t%d\n", - "rx_pause_all\t%d\n", - "rx_unknown_opcode\t%d\n", - "rx_mac_error\t%d\n", - "tx_underrun32\t%d\n", - "rx_mac_missed\t%d\n", - "rx_tcam_dropped\t%d\n", - "tdu\t%d\n", - "rdu\t%d\n", - le64_to_cpu(counters->tx_packets), - le64_to_cpu(counters->rx_packets), - le64_to_cpu(counters->tx_errors), - le32_to_cpu(counters->rx_errors), - le16_to_cpu(counters->rx_missed), - le16_to_cpu(counters->align_errors), - le32_to_cpu(counters->tx_one_collision), - le32_to_cpu(counters->tx_multi_collision), - le64_to_cpu(counters->rx_unicast), - le64_to_cpu(counters->rx_broadcast), - le32_to_cpu(counters->rx_multicast), - le16_to_cpu(counters->tx_aborted), - le16_to_cpu(counters->tx_underrun), - - le64_to_cpu(counters->tx_octets), - le64_to_cpu(counters->rx_octets), - le64_to_cpu(counters->rx_multicast64), - le64_to_cpu(counters->tx_unicast64), - le64_to_cpu(counters->tx_broadcast64), - le64_to_cpu(counters->tx_multicast64), - le32_to_cpu(counters->tx_pause_on), - le32_to_cpu(counters->tx_pause_off), - le32_to_cpu(counters->tx_pause_all), - le32_to_cpu(counters->tx_deferred), - le32_to_cpu(counters->tx_late_collision), - le32_to_cpu(counters->tx_all_collision), - le32_to_cpu(counters->tx_aborted32), - le32_to_cpu(counters->align_errors32), - le32_to_cpu(counters->rx_frame_too_long), - le32_to_cpu(counters->rx_runt), - le32_to_cpu(counters->rx_pause_on), - le32_to_cpu(counters->rx_pause_off), - le32_to_cpu(counters->rx_pause_all), - le32_to_cpu(counters->rx_unknown_opcode), - le32_to_cpu(counters->rx_mac_error), - le32_to_cpu(counters->tx_underrun32), - le32_to_cpu(counters->rx_mac_missed), - le32_to_cpu(counters->rx_tcam_dropped), - le32_to_cpu(counters->tdu), - le32_to_cpu(counters->rdu), - ); - - len += snprintf(page + len, count - len, "\n"); -out_unlock: - rtnl_unlock(); - - *eof = 1; - return len; -} - -static int proc_get_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump MAC Registers\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - len += snprintf(page + len, count - len, - "%02x ", - byte_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_pcie_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCIE PHY\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_ephy_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_eth_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Ethernet PHY\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - len += snprintf(page + len, count - len, - "\n####################page 0##################\n"); - rtl8125_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_mdio_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_extended_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Extended Registers\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_pci_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCI Registers\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%03x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_temperature(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - u16 ts_digout, tj, fah; - int len = 0; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - len += snprintf(page + len, count - len, - "\nChip Temperature\n"); - break; - default: - len += snprintf(page + len, count - len, - "\nThis Chip Does Not Support Dump Temperature\n"); - break; - } - - rtnl_lock(); - ts_digout = rtl8125_read_thermal_sensor(tp); - rtnl_unlock(); - - tj = ts_digout / 2; - if (ts_digout <= 512) { - tj = ts_digout / 2; - len += snprintf(page + len, count - len, - "Cel:%d\n", - tj); - fah = tj * (9/5) + 32; - len += snprintf(page + len, count - len, - "Fah:%d\n", - fah); - - } else { - tj = (512 - ((ts_digout / 2) - 512)) / 2; - len += snprintf(page + len, count - len, - "Cel:-%d\n", - tj); - fah = tj * (9/5) + 32; - len += snprintf(page + len, count - len, - "Fah:-%d\n", - fah); - } - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} -#endif -static void rtl8125_proc_module_init(void) -{ - //create /proc/net/r8125 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - rtl8125_proc = proc_mkdir(MODULENAME, init_net.proc_net); -#else - rtl8125_proc = proc_mkdir(MODULENAME, proc_net); -#endif - if (!rtl8125_proc) - dprintk("cannot create %s proc entry \n", MODULENAME); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -/* - * seq_file wrappers for procfile show routines. - */ -static int rtl8125_proc_open(struct inode *inode, struct file *file) -{ - struct net_device *dev = proc_get_parent_data(inode); - int (*show)(struct seq_file *, void *) = PDE_DATA(inode); - - return single_open(file, show, dev); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static const struct proc_ops rtl8125_proc_fops = { - .proc_open = rtl8125_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, -}; -#else -static const struct file_operations rtl8125_proc_fops = { - .open = rtl8125_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -#endif - -/* - * Table of proc files we need to create. - */ -struct rtl8125_proc_file { - char name[12]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - int (*show)(struct seq_file *, void *); -#else - int (*show)(char *, char **, off_t, int, int *, void *); -#endif -}; - -static const struct rtl8125_proc_file rtl8125_proc_files[] = { - { "driver_var", &proc_get_driver_variable }, - { "tally", &proc_get_tally_counter }, - { "registers", &proc_get_registers }, - { "pcie_phy", &proc_get_pcie_phy }, - { "eth_phy", &proc_get_eth_phy }, - { "ext_regs", &proc_get_extended_registers }, - { "pci_regs", &proc_get_pci_registers }, - { "temp", &proc_get_temperature }, - { "", NULL } -}; - -static void rtl8125_proc_init(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - const struct rtl8125_proc_file *f; - struct proc_dir_entry *dir; - - if (rtl8125_proc && !tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - dir = proc_mkdir_data(dev->name, 0, rtl8125_proc, dev); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8125_proc_files; f->name[0]; f++) { - if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, - &rtl8125_proc_fops, f->show)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#else - dir = proc_mkdir(dev->name, rtl8125_proc); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8125_proc_files; f->name[0]; f++) { - if (!create_proc_read_entry(f->name, S_IFREG | S_IRUGO, - dir, f->show, dev)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#endif - } -} - -static void rtl8125_proc_remove(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(dev->name, rtl8125_proc); - proc_init_num--; - -#else - const struct rtl8125_proc_file *f; - struct rtl8125_private *tp = netdev_priv(dev); - - for (f = rtl8125_proc_files; f->name[0]; f++) - remove_proc_entry(f->name, tp->proc_dir); - - remove_proc_entry(dev->name, rtl8125_proc); - proc_init_num--; -#endif - tp->proc_dir = NULL; - } -} - -#endif //ENABLE_R8125_PROCFS - -static inline u16 map_phy_ocp_addr(u16 PageNum, u8 RegNum) -{ - u16 OcpPageNum = 0; - u8 OcpRegNum = 0; - u16 OcpPhyAddress = 0; - - if ( PageNum == 0 ) { - OcpPageNum = OCP_STD_PHY_BASE_PAGE + ( RegNum / 8 ); - OcpRegNum = 0x10 + ( RegNum % 8 ); - } else { - OcpPageNum = PageNum; - OcpRegNum = RegNum; - } - - OcpPageNum <<= 4; - - if ( OcpRegNum < 16 ) { - OcpPhyAddress = 0; - } else { - OcpRegNum -= 16; - OcpRegNum <<= 1; - - OcpPhyAddress = OcpPageNum + OcpRegNum; - } - - - return OcpPhyAddress; -} - -static void mdio_real_direct_write_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - u32 data32; - int i; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 |= OCPR_Write | value; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (!(RTL_R32(tp, PHYOCP) & OCPR_Flag)) - break; - } -} - -static void mdio_direct_write_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -/* -static void rtl8125_mdio_write_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_direct_write_phy_ocp(tp, ocp_addr, value); -} -*/ - -static void rtl8125_mdio_real_write_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_real_direct_write_phy_ocp(tp, ocp_addr, value); -} - -static void mdio_real_write(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - if (RegAddr == 0x1F) { - tp->cur_page = value; - return; - } - rtl8125_mdio_real_write_phy_ocp(tp, tp->cur_page, RegAddr, value); -} - -void rtl8125_mdio_write(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_write(tp, RegAddr, value); -} - -void rtl8125_mdio_prot_write(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_write(tp, RegAddr, value); -} - -void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -static u32 mdio_real_direct_read_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr) -{ - u32 data32; - int i, value = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (RTL_R32(tp, PHYOCP) & OCPR_Flag) - break; - } - value = RTL_R32(tp, PHYOCP) & OCPDR_Data_Mask; - - return value; -} - -static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -/* -static u32 rtl8125_mdio_read_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_direct_read_phy_ocp(tp, ocp_addr); -} -*/ - -static u32 rtl8125_mdio_real_read_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_real_direct_read_phy_ocp(tp, ocp_addr); -} - -static u32 mdio_real_read(struct rtl8125_private *tp, - u16 RegAddr) -{ - return rtl8125_mdio_real_read_phy_ocp(tp, tp->cur_page, RegAddr); -} - -u32 rtl8125_mdio_read(struct rtl8125_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, - u32 RegAddr) -{ - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, - u32 RegAddr) -{ - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -static void ClearAndSetEthPhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - PhyRegValue = rtl8125_mdio_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8125_mdio_write(tp, addr, PhyRegValue); -} - -void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - mask, - 0 - ); -} - -void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - 0, - mask - ); -} - -static void ClearAndSetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - PhyRegValue = mdio_direct_read_phy_ocp(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - mdio_direct_write_phy_ocp(tp, addr, PhyRegValue); -} - -void ClearEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) -{ - ClearAndSetEthPhyOcpBit(tp, - addr, - mask, - 0 - ); -} - -void SetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) -{ - ClearAndSetEthPhyOcpBit(tp, - addr, - 0, - mask - ); -} - -void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value) -{ - u32 data32; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 += value; - data32 |= OCPR_Write; - - RTL_W32(tp, MACOCP, data32); -} - -u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr) -{ - u32 data32; - u16 data16 = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, MACOCP, data32); - data16 = (u16)RTL_R32(tp, MACOCP); - - return data16; -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void mac_mcu_write(struct rtl8125_private *tp, u16 reg, u16 value) -{ - if (reg == 0x1f) { - tp->ocp_base = value << 4; - return; - } - - rtl8125_mac_ocp_write(tp, tp->ocp_base + reg, value); -} - -static u32 mac_mcu_read(struct rtl8125_private *tp, u16 reg) -{ - return rtl8125_mac_ocp_read(tp, tp->ocp_base + reg); -} -#endif - -static void -ClearAndSetMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 clearmask, - u16 setmask -) -{ - u16 PhyRegValue; - - PhyRegValue = rtl8125_mac_ocp_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8125_mac_ocp_write(tp, addr, PhyRegValue); -} - -static void -ClearMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 mask -) -{ - ClearAndSetMcuAccessRegBit(tp, - addr, - mask, - 0 - ); -} - -static void -SetMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 mask -) -{ - ClearAndSetMcuAccessRegBit(tp, - addr, - 0, - mask - ); -} - -u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, const u32 base_address) -{ - return rtl8125_eri_read_with_oob_base_address(tp, addr, len, ERIAR_OOB, base_address); -} - -u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len) -{ - u32 value = 0; - - if (HW_DASH_SUPPORT_TYPE_2(tp)) - value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, RTL8168FP_OOBMAC_BASE); - - return value; -} - -u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, const u32 base_address) -{ - return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, ERIAR_OOB, base_address); -} - -void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 value) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp)) - rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, RTL8168FP_OOBMAC_BASE); -} - -void rtl8125_oob_mutex_lock(struct rtl8125_private *tp) -{ - u8 reg_16, reg_a0; - u32 wait_cnt_0, wait_Cnt_1; - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); - wait_cnt_0 = 0; - while(reg_16) { - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - if (reg_a0) { - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - wait_Cnt_1 = 0; - while(reg_a0) { - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - - wait_Cnt_1++; - - if (wait_Cnt_1 > 2000) - break; - }; - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - - } - reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); - - wait_cnt_0++; - - if (wait_cnt_0 > 2000) - break; - }; -} - -void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp) -{ - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8125_ocp_write(tp, ocp_reg_mutex_prio, 1, BIT_0); - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); -} - -void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd) -{ - rtl8125_eri_write(tp, 0xE8, 1, cmd, ERIAR_ExGMAC); - - rtl8125_ocp_write(tp, 0x30, 1, 0x01); -} - -static int rtl8125_check_dash(struct rtl8125_private *tp) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - if (rtl8125_ocp_read(tp, 0x128, 1) & BIT_0) - return 1; - } - - return 0; -} - -void rtl8125_dash2_disable_tx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - u16 WaitCnt; - u8 TmpUchar; - - //Disable oob Tx - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) & ~( BIT_0 )); - WaitCnt = 0; - - //wait oob tx disable - do { - TmpUchar = RTL_CMAC_R8(tp, CMAC_IBISR0); - - if ( TmpUchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE ) { - break; - } - - udelay( 50 ); - WaitCnt++; - } while(WaitCnt < 2000); - - //Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0) | ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE); - } -} - -void rtl8125_dash2_enable_tx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) | BIT_0); - } -} - -void rtl8125_dash2_disable_rx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) & ~( BIT_0 )); - } -} - -void rtl8125_dash2_enable_rx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) | BIT_0); - } -} - -static void rtl8125_dash2_disable_txrx(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8125_dash2_disable_tx( tp ); - rtl8125_dash2_disable_rx( tp ); - } -} - -static void rtl8125_driver_start(struct rtl8125_private *tp) -{ - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - int timeout; - u32 tmp_value; - - rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_START); - tmp_value = rtl8125_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8125_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (rtl8125_ocp_read(tp, 0x124, 1) & BIT_0) - break; - } - } -} - -static void rtl8125_driver_stop(struct rtl8125_private *tp) -{ - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - struct net_device *dev = tp->dev; - int timeout; - u32 tmp_value; - - rtl8125_dash2_disable_txrx(dev); - - rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_STOP); - tmp_value = rtl8125_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8125_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (!(rtl8125_ocp_read(tp, 0x124, 1) & BIT_0)) - break; - } - } -} - -void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value) -{ - int i; - - RTL_W32(tp, EPHYAR, - EPHYAR_Write | - (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift | - (value & EPHYAR_Data_Mask)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed EPHY write */ - if (!(RTL_R32(tp, EPHYAR) & EPHYAR_Flag)) - break; - } - - udelay(20); -} - -u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr) -{ - int i; - u16 value = 0xffff; - - RTL_W32(tp, EPHYAR, - EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed EPHY read */ - if (RTL_R32(tp, EPHYAR) & EPHYAR_Flag) { - value = (u16) (RTL_R32(tp, EPHYAR) & EPHYAR_Data_Mask); - break; - } - } - - udelay(20); - - return value; -} - -static void ClearAndSetPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 EphyValue; - - EphyValue = rtl8125_ephy_read(tp, addr); - EphyValue &= ~clearmask; - EphyValue |= setmask; - rtl8125_ephy_write(tp, addr, EphyValue); -} - -static void ClearPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - mask, - 0 - ); -} - -static void SetPCIePhyBit( struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - 0, - mask - ); -} - -static u32 -rtl8125_csi_other_fun_read(struct rtl8125_private *tp, - u8 multi_fun_sel_bit, - u32 addr) -{ - u32 cmd; - int i; - u32 value = 0; - - cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - multi_fun_sel_bit = 0; - - if (multi_fun_sel_bit > 7) - return 0xffffffff; - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed CSI read */ - if (RTL_R32(tp, CSIAR) & CSIAR_Flag) { - value = (u32)RTL_R32(tp, CSIDR); - break; - } - } - - udelay(20); - - return value; -} - -static void -rtl8125_csi_other_fun_write(struct rtl8125_private *tp, - u8 multi_fun_sel_bit, - u32 addr, - u32 value) -{ - u32 cmd; - int i; - - RTL_W32(tp, CSIDR, value); - cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - if (tp->mcfg == CFG_METHOD_DEFAULT) - multi_fun_sel_bit = 0; - - if ( multi_fun_sel_bit > 7 ) - return; - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed CSI write */ - if (!(RTL_R32(tp, CSIAR) & CSIAR_Flag)) - break; - } - - udelay(20); -} - -static u32 -rtl8125_csi_read(struct rtl8125_private *tp, - u32 addr) -{ - u8 multi_fun_sel_bit; - - multi_fun_sel_bit = 0; - - return rtl8125_csi_other_fun_read(tp, multi_fun_sel_bit, addr); -} - -static void -rtl8125_csi_write(struct rtl8125_private *tp, - u32 addr, - u32 value) -{ - u8 multi_fun_sel_bit; - - multi_fun_sel_bit = 0; - - rtl8125_csi_other_fun_write(tp, multi_fun_sel_bit, addr, value); -} - -static u8 -rtl8125_csi_fun0_read_byte(struct rtl8125_private *tp, - u32 addr) -{ - u8 RetVal = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) { - struct pci_dev *pdev = tp->pci_dev; - - pci_read_config_byte(pdev, addr, &RetVal); - } else { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8125_csi_other_fun_read(tp, 0, addr); - TmpUlong >>= (8*ShiftByte); - RetVal = (u8)TmpUlong; - } - - udelay(20); - - return RetVal; -} - -static void -rtl8125_csi_fun0_write_byte(struct rtl8125_private *tp, - u32 addr, - u8 value) -{ - if (tp->mcfg == CFG_METHOD_DEFAULT) { - struct pci_dev *pdev = tp->pci_dev; - - pci_write_config_byte(pdev, addr, value); - } else { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8125_csi_other_fun_read(tp, 0, RegAlignAddr); - TmpUlong &= ~(0xFF << (8*ShiftByte)); - TmpUlong |= (value << (8*ShiftByte)); - rtl8125_csi_other_fun_write( tp, 0, RegAlignAddr, TmpUlong ); - } - - udelay(20); -} - -u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, value2 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - eri_cmd = ERIAR_Read | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed ERI read */ - if (RTL_R32(tp, ERIAR) & ERIAR_Flag) - break; - } - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = RTL_R32(tp, ERIDR) & mask; - value2 |= (value1 >> val_shift * 8) << shift * 8; - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return value2; -} - -u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type) -{ - return rtl8125_eri_read_with_oob_base_address(tp, addr, len, type, 0); -} - -int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = rtl8125_eri_read_with_oob_base_address(tp, addr, 4, type, base_address) & ~mask; - value1 |= ((value << val_shift * 8) >> shift * 8); - - RTL_W32(tp, ERIDR, value1); - - eri_cmd = ERIAR_Write | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed ERI write */ - if (!(RTL_R32(tp, ERIAR) & ERIAR_Flag)) - break; - } - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return 0; -} - -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type) -{ - return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, type, NO_BASE_ADDRESS); -} - -static void -rtl8125_enable_rxdvgate(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_3); - mdelay(2); - break; - } -} - -static void -rtl8125_disable_rxdvgate(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_3); - mdelay(2); - break; - } -} - -static u8 -rtl8125_is_gpio_low(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 gpio_low = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - if (!(rtl8125_mac_ocp_read(tp, 0xDC04) & BIT_13)) - gpio_low = TRUE; - break; - } - - if (gpio_low) - dprintk("gpio is low.\n"); - - return gpio_low; -} - -static u8 -rtl8125_is_phy_disable_mode_enabled(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 phy_disable_mode_enabled = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - if (RTL_R8(tp, 0xF2) & BIT_5) - phy_disable_mode_enabled = TRUE; - break; - } - - if (phy_disable_mode_enabled) - dprintk("phy disable mode enabled.\n"); - - return phy_disable_mode_enabled; -} - -static u8 -rtl8125_is_in_phy_disable_mode(struct net_device *dev) -{ - u8 in_phy_disable_mode = FALSE; - - if (rtl8125_is_phy_disable_mode_enabled(dev) && rtl8125_is_gpio_low(dev)) - in_phy_disable_mode = TRUE; - - if (in_phy_disable_mode) - dprintk("Hardware is in phy disable mode.\n"); - - return in_phy_disable_mode; -} - -static bool -rtl8125_stop_all_request(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - for (i = 0; i < 20; i++) { - udelay(10); - if (!(RTL_R8(tp, ChipCmd) & StopReq)) break; - } - - if (i == 20) - return 0; - break; - } - - return 1; -} - -void -rtl8125_wait_txrx_fifo_empty(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_stop_all_request(dev); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - for (i = 0; i < 3000; i++) { - udelay(50); - if ((RTL_R8(tp, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) == (Txfifo_empty | Rxfifo_empty)) - break; - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - for (i = 0; i < 3000; i++) { - udelay(50); - if ((RTL_R16(tp, IntrMitigate) & (BIT_0 | BIT_1 | BIT_8)) == (BIT_0 | BIT_1 | BIT_8)) - break; - } - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT - -static inline void -rtl8125_enable_dash2_interrupt(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, ( ISRIMR_DASH_TYPE2_ROK | ISRIMR_DASH_TYPE2_TOK | ISRIMR_DASH_TYPE2_TDU | ISRIMR_DASH_TYPE2_RDU | ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE )); - } -} - -static inline void -rtl8125_disable_dash2_interrupt(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, 0); - } -} -#endif - -void -rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp) -{ - switch (tp->HwCurrIsrVer) { - case 2: - RTL_W32(tp, IMR_V2_SET_REG_8125, ISRIMR_V2_LINKCHG); - break; - case 1: - RTL_W32(tp, tp->imr_reg[0], LinkChg | RTL_R32(tp, tp->imr_reg[0])); - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif -} - -static inline void -rtl8125_enable_hw_interrupt(struct rtl8125_private *tp) -{ - switch (tp->HwCurrIsrVer) { - case 2: - RTL_W32(tp, IMR_V2_SET_REG_8125, tp->intr_mask); - break; - case 1: - RTL_W32(tp, tp->imr_reg[0], tp->intr_mask); - - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->imr_reg[i], other_q_intr_mask); - } - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif -} - -static inline void rtl8125_clear_hw_isr_v2(struct rtl8125_private *tp, - u32 message_id) -{ - RTL_W32(tp, ISR_V2_8125, BIT(message_id)); -} - -static inline void -rtl8125_disable_hw_interrupt(struct rtl8125_private *tp) -{ - if (tp->HwCurrIsrVer == 2) { - RTL_W32(tp, IMR_V2_CLEAR_REG_8125, 0xFFFFFFFF); - } else { - RTL_W32(tp, tp->imr_reg[0], 0x0000); - - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->imr_reg[i], 0); - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_disable_dash2_interrupt(tp); -#endif - } -} - -static inline void -rtl8125_switch_to_hw_interrupt(struct rtl8125_private *tp) -{ - RTL_W32(tp, TIMER_INT0_8125, 0x0000); - - rtl8125_enable_hw_interrupt(tp); -} - -static inline void -rtl8125_switch_to_timer_interrupt(struct rtl8125_private *tp) -{ - if (tp->use_timer_interrrupt) { - RTL_W32(tp, TIMER_INT0_8125, timer_count); - RTL_W32(tp, TCTR0_8125, timer_count); - RTL_W32(tp, tp->imr_reg[0], tp->timer_intr_mask); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif - } else { - rtl8125_switch_to_hw_interrupt(tp); - } -} - -static void -rtl8125_irq_mask_and_ack(struct rtl8125_private *tp) -{ - rtl8125_disable_hw_interrupt(tp); - - if (tp->HwCurrIsrVer == 2) { - RTL_W32(tp, ISR_V2_8125, 0xFFFFFFFF); - } else { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (tp->dash_printer_enabled) { - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0]) & - ~(ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } else { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0)); - } - } - } else { - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); - } -#else - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); -#endif - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->isr_reg[i], RTL_R16(tp, tp->isr_reg[i])); - } - } -} - -static void -rtl8125_nic_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8125_enable_rxdvgate(dev); - - rtl8125_stop_all_request(dev); - - rtl8125_wait_txrx_fifo_empty(dev); - - mdelay(2); - - /* Soft reset the chip. */ - RTL_W8(tp, ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { - udelay(100); - if ((RTL_R8(tp, ChipCmd) & CmdReset) == 0) - break; - } -} - -static void -rtl8125_hw_set_interrupt_type(struct rtl8125_private *tp, u8 isr_ver) -{ - u8 tmp; - - switch (tp->HwSuppIsrVer) { - case 2: - tmp = RTL_R8(tp, INT_CFG0_8125); - tmp &= ~(INT_CFG0_ENABLE_8125); - if (isr_ver == 2) - tmp |= INT_CFG0_ENABLE_8125; - RTL_W8(tp, INT_CFG0_8125, tmp); - break; - } -} - -static void -rtl8125_hw_clear_timer_int(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W32(tp, TIMER_INT0_8125, 0x0000); - RTL_W32(tp, TIMER_INT1_8125, 0x0000); - RTL_W32(tp, TIMER_INT2_8125, 0x0000); - RTL_W32(tp, TIMER_INT3_8125, 0x0000); - break; - } -} - -static void -rtl8125_hw_clear_int_miti(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - switch (tp->HwSuppIntMitiVer) { - case 3: - //IntMITI_0-IntMITI_31 - for (i=0xA00; i<0xB00; i+=4) - RTL_W32(tp, i, 0x0000); - break; - case 4: - //IntMITI_0-IntMITI_15 - for (i = 0xA00; i < 0xA80; i += 4) - RTL_W32(tp, i, 0x0000); - - RTL_W8(tp, INT_CFG0_8125, RTL_R8(tp, INT_CFG0_8125) & - ~(INT_CFG0_TIMEOUT0_BYPASS_8125 | INT_CFG0_MITIGATION_BYPASS_8125)); - - RTL_W16(tp, INT_CFG1_8125, 0x0000); - break; - } -} - -void -rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, - u32 message_id, - u8 timer_intmiti_val) -{ - switch (tp->HwSuppIntMitiVer) { - case 4: - if (message_id < R8125_MAX_RX_QUEUES_VEC_V3) //ROK - RTL_W8(tp,INT_MITI_V2_0_RX + 8 * message_id, timer_intmiti_val); - else if (message_id == 16) //TOK - RTL_W8(tp,INT_MITI_V2_0_TX, timer_intmiti_val); - else if (message_id == 18) //TOK - RTL_W8(tp,INT_MITI_V2_1_TX, timer_intmiti_val); - break; - } -} - -void -rtl8125_hw_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_lib_reset_prepare(tp); - - /* Disable interrupts */ - rtl8125_irq_mask_and_ack(tp); - - rtl8125_hw_clear_timer_int(dev); - - rtl8125_nic_reset(dev); -} - -static unsigned int -rtl8125_xmii_reset_pending(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int retval; - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - retval = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; - - return retval; -} - -static unsigned int -rtl8125_xmii_link_ok(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int retval; - - retval = (RTL_R16(tp, PHYstatus) & LinkStatus) ? 1 : 0; - - return retval; -} - -static int -rtl8125_wait_phy_reset_complete(struct rtl8125_private *tp) -{ - int i, val; - - for (i = 0; i < 2500; i++) { - val = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; - if (!val) - return 0; - - mdelay(1); - } - - return -1; -} - -static void -rtl8125_xmii_reset_enable(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) { - return; - } - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - rtl8125_mdio_write(tp, MII_ADVERTISE, rtl8125_mdio_read(tp, MII_ADVERTISE) & - ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL)); - rtl8125_mdio_write(tp, MII_CTRL1000, rtl8125_mdio_read(tp, MII_CTRL1000) & - ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL)); - mdio_direct_write_phy_ocp(tp, 0xA5D4, mdio_direct_read_phy_ocp(tp, 0xA5D4) & ~(RTK_ADVERTISE_2500FULL)); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - - if (rtl8125_wait_phy_reset_complete(tp) == 0) return; - - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -void -rtl8125_init_ring_indexes(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->HwSuppNumTxQueues; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - ring->dirty_tx = ring->cur_tx = 0; - ring->NextHwDesCloPtr = 0; - ring->BeginHwDesCloPtr = 0; - ring->index = i; - ring->priv = tp; - } - - for (i = 0; i < tp->HwSuppNumRxQueues; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - ring->dirty_rx = ring->cur_rx = 0; - ring->index = i; - ring->priv = tp; - } - -#ifdef ENABLE_LIB_SUPPORT - for (i = 0; i < tp->HwSuppNumTxQueues; i++) { - struct rtl8125_ring *ring = &tp->lib_tx_ring[i]; - ring->direction = RTL8125_CH_DIR_TX; - ring->queue_num = i; - ring->private = tp; - } - - for (i = 0; i < tp->HwSuppNumRxQueues; i++) { - struct rtl8125_ring *ring = &tp->lib_rx_ring[i]; - ring->direction = RTL8125_CH_DIR_RX; - ring->queue_num = i; - ring->private = tp; - } -#endif -} - -static void -rtl8125_issue_offset_99_event(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE09A, rtl8125_mac_ocp_read(tp, 0xE09A) | BIT_0); - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT -static void -NICChkTypeEnableDashInterrupt(struct rtl8125_private *tp) -{ - if (tp->DASH) { - // - // even disconnected, enable 3 dash interrupt mask bits for in-band/out-band communication - // - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8125_enable_dash2_interrupt(tp); - RTL_W16(tp, IntrMask, (ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } - } -} -#endif - -static int rtl8125_enable_eee_plus(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)|BIT_1); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static int rtl8125_disable_eee_plus(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)&~BIT_1); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8125_link_on_patch(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_hw_config(dev); - - if ((tp->mcfg == CFG_METHOD_2) && - netif_running(dev)) { - if (RTL_R16(tp, PHYstatus)&FullDup) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | (BIT_24 | BIT_25)) & ~BIT_19); - else - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_25) & ~(BIT_19 | BIT_24)); - } - - if ((tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) && - (RTL_R8(tp, PHYstatus) & _10bps)) - rtl8125_enable_eee_plus(tp); - - rtl8125_hw_start(dev); - - netif_carrier_on(dev); - - netif_tx_wake_all_queues(dev); - - tp->phy_reg_aner = rtl8125_mdio_read(tp, MII_EXPANSION); - tp->phy_reg_anlpar = rtl8125_mdio_read(tp, MII_LPA); - tp->phy_reg_gbsr = rtl8125_mdio_read(tp, MII_STAT1000); - tp->phy_reg_status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); -} - -static void -rtl8125_link_down_patch(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->phy_reg_aner = 0; - tp->phy_reg_anlpar = 0; - tp->phy_reg_gbsr = 0; - tp->phy_reg_status_2500 = 0; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_disable_eee_plus(tp); - - netif_tx_stop_all_queues(dev); - - netif_carrier_off(dev); - - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - rtl8125_rx_clear(tp); - - rtl8125_init_ring(dev); - - rtl8125_enable_hw_linkchg_interrupt(tp); - - //rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - NICChkTypeEnableDashInterrupt(tp); - } -#endif -} - -static void -_rtl8125_check_link_status(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->link_ok(dev)) { - rtl8125_link_on_patch(dev); - - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - - rtl8125_link_down_patch(dev); - } -} - -static void -rtl8125_check_link_status(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - _rtl8125_check_link_status(dev); - - tp->resume_not_chg_speed = 0; -} - -static void -rtl8125_link_option(u8 *aut, - u32 *spd, - u8 *dup, - u32 *adv) -{ - if ((*spd != SPEED_2500) && (*spd != SPEED_1000) && - (*spd != SPEED_100) && (*spd != SPEED_10)) - *spd = SPEED_2500; - - if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) - *dup = DUPLEX_FULL; - - if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) - *aut = AUTONEG_ENABLE; - - *adv &= (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full); - if (*adv == 0) - *adv = (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full); -} - -/* -static void -rtl8125_enable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - val = mdio_direct_read_phy_ocp(tp, 0xC416); - if (val != 0x0050) { - rtl8125_set_phy_mcu_patch_request(tp); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0050); - rtl8125_clear_phy_mcu_patch_request(tp); - } - } -} -*/ - -static void -rtl8125_disable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - val = mdio_direct_read_phy_ocp(tp, 0xC416); - if (val != 0x0500) { - rtl8125_set_phy_mcu_patch_request(tp); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0500); - rtl8125_clear_phy_mcu_patch_request(tp); - } - } -} - -static void -rtl8125_wait_ll_share_fifo_ready(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - for (i = 0; i < 10; i++) { - udelay(100); - if (RTL_R16(tp, 0xD2) & BIT_9) - break; - } -} - -static void -rtl8125_disable_pci_offset_99(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE032, rtl8125_mac_ocp_read(tp, 0xE032) & ~(BIT_0 | BIT_1)); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_csi_fun0_write_byte(tp, 0x99, 0x00); - break; - } -} - -static void -rtl8125_enable_pci_offset_99(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_csi_fun0_write_byte(tp, 0x99, tp->org_pci_offset_99); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); - csi_tmp &= ~(BIT_0 | BIT_1); - if (tp->org_pci_offset_99 & (BIT_5 | BIT_6)) - csi_tmp |= BIT_1; - if (tp->org_pci_offset_99 & BIT_2) - csi_tmp |= BIT_0; - rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); - break; - } -} - -static void -rtl8125_init_pci_offset_99(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xCDD0, 0x9003); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE034); - csi_tmp |= (BIT_15 | BIT_14); - rtl8125_mac_ocp_write(tp, 0xE034, csi_tmp); - rtl8125_mac_ocp_write(tp, 0xCDD2, 0x889C); - rtl8125_mac_ocp_write(tp, 0xCDD8, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDD4, 0x8C30); - rtl8125_mac_ocp_write(tp, 0xCDDA, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDD6, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDDC, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDE8, 0x883E); - rtl8125_mac_ocp_write(tp, 0xCDEA, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDEC, 0x889C); - rtl8125_mac_ocp_write(tp, 0xCDEE, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDF0, 0x8C09); - rtl8125_mac_ocp_write(tp, 0xCDF2, 0x9003); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); - csi_tmp |= (BIT_14); - rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE0A2); - csi_tmp |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xE0A2, csi_tmp); - break; - } - - rtl8125_enable_pci_offset_99(tp); -} - -static void -rtl8125_disable_pci_offset_180(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); - csi_tmp &= 0xFF00; - rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); - break; - } -} - -static void -rtl8125_enable_pci_offset_180(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE094); - csi_tmp &= 0x00FF; - rtl8125_mac_ocp_write(tp, 0xE094, csi_tmp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); - csi_tmp &= 0xFF00; - csi_tmp |= BIT_2; - rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); - break; - } -} - -static void -rtl8125_init_pci_offset_180(struct rtl8125_private *tp) -{ - if (tp->org_pci_offset_180 & (BIT_0|BIT_1)) - rtl8125_enable_pci_offset_180(tp); - else - rtl8125_disable_pci_offset_180(tp); -} - -static void -rtl8125_set_pci_99_180_exit_driver_para(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_issue_offset_99_event(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_disable_pci_offset_99(tp); - break; - } - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_disable_pci_offset_180(tp); - break; - } -} - -static void -rtl8125_enable_cfg9346_write(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) | Cfg9346_Unlock); -} - -static void -rtl8125_disable_cfg9346_write(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) & ~Cfg9346_Unlock); -} - -static void -rtl8125_enable_exit_l1_mask(struct rtl8125_private *tp) -{ - //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b111111, L1 Mask - SetMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); -} - -static void -rtl8125_disable_exit_l1_mask(struct rtl8125_private *tp) -{ - //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b000000, L1 Mask - ClearMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); -} - -static void -rtl8125_enable_extend_tally_couter(struct rtl8125_private *tp) -{ - switch (tp->HwSuppExtendTallyCounterVer) { - case 1: - SetMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); - break; - } -} - -static void -rtl8125_disable_extend_tally_couter(struct rtl8125_private *tp) -{ - switch (tp->HwSuppExtendTallyCounterVer) { - case 1: - ClearMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); - break; - } -} - -static void -rtl8125_hw_d3_para(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - RTL_W16(tp, RxMaxSize, RX_BUF_SIZE); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - rtl8125_disable_cfg9346_write(tp); - break; - } - - rtl8125_disable_exit_l1_mask(tp); - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_set_realwow_d3_para(dev); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xEA18, 0x0064); - break; - } - - rtl8125_set_pci_99_180_exit_driver_para(dev); - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_disable_ocp_phy_power_saving(dev); - - rtl8125_disable_rxdvgate(dev); - - rtl8125_disable_extend_tally_couter(tp); -} - -static void -rtl8125_enable_magic_packet(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) | BIT_0); - break; - } -} -static void -rtl8125_disable_magic_packet(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) & ~BIT_0); - break; - } -} - -static void -rtl8125_enable_linkchg_wakeup(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | LinkUp); - ClearAndSetMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_3 | BIT_2), (BIT_4 | BIT_1 | BIT_0)); - break; - } -} - -static void -rtl8125_disable_linkchg_wakeup(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~LinkUp); - ClearMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0)); - break; - } -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 -rtl8125_get_hw_wol(struct rtl8125_private *tp) -{ - u8 options; - u32 csi_tmp; - u32 wol_opts = 0; - - if (disable_pm_support) - goto out; - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out; - - options = RTL_R8(tp, Config3); - if (options & LinkUp) - wol_opts |= WAKE_PHY; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xC0B6); - if (csi_tmp & BIT_0) - wol_opts |= WAKE_MAGIC; - break; - } - - options = RTL_R8(tp, Config5); - if (options & UWF) - wol_opts |= WAKE_UCAST; - if (options & BWF) - wol_opts |= WAKE_BCAST; - if (options & MWF) - wol_opts |= WAKE_MCAST; - -out: - return wol_opts; -} - -static void -rtl8125_enable_d0_speedup(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_DISABLE) return; - - if (tp->HwSuppD0SpeedUpVer == 1) { - u16 mac_ocp_data; - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_3); - - //speed up speed - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE10A); - mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8 | BIT_7); - if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_2500) { - mac_ocp_data |= BIT_7; - } - rtl8125_mac_ocp_write(tp, 0xE10A, mac_ocp_data); - - //speed up flowcontrol - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE860); - mac_ocp_data |= (BIT_15 | BIT_14); - rtl8125_mac_ocp_write(tp, 0xE860, mac_ocp_data); - } -} - -static void -rtl8125_disable_d0_speedup(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - - if (tp->HwSuppD0SpeedUpVer == 1) - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_7); -} - -static void -rtl8125_set_hw_wol(struct net_device *dev, u32 wolopts) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i,tmp; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake }, - { WAKE_MAGIC, Config3, MagicPacket }, - }; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - default: - tmp = ARRAY_SIZE(cfg) - 1; - - if (wolopts & WAKE_MAGIC) - rtl8125_enable_magic_packet(dev); - else - rtl8125_disable_magic_packet(dev); - break; - } - - rtl8125_enable_cfg9346_write(tp); - - for (i = 0; i < tmp; i++) { - u8 options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(tp, cfg[i].reg, options); - } - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - if (wolopts & WAKE_PHY) - rtl8125_enable_linkchg_wakeup(dev); - else - rtl8125_disable_linkchg_wakeup(dev); - break; - } - - rtl8125_disable_cfg9346_write(tp); -} - -static void -rtl8125_phy_restart_nway(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) return; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); -} - -static void -rtl8125_phy_setup_force_mode(struct net_device *dev, u32 speed, u8 duplex) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 bmcr_true_force = 0; - - if (rtl8125_is_in_phy_disable_mode(dev)) return; - - if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED10; - } else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED100; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX; - } else { - netif_err(tp, drv, dev, "Failed to set phy force mode!\n"); - return; - } - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, bmcr_true_force); -} - -static void -rtl8125_set_pci_pme(struct rtl8125_private *tp, int set) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 pmc; - - if (!pdev->pm_cap) - return; - - pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); - pmc |= PCI_PM_CTRL_PME_STATUS; - if (set) - pmc |= PCI_PM_CTRL_PME_ENABLE; - else - pmc &= ~PCI_PM_CTRL_PME_ENABLE; - pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); -} - -static void -rtl8125_set_wol_link_speed(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int auto_nego; - int giga_ctrl; - int ctrl_2500; - u32 adv; - u16 anlpar; - u16 gbsr; - u16 status_2500; - u16 aner; - - if (tp->autoneg != AUTONEG_ENABLE) - goto exit; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - - auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL - | ADVERTISE_100HALF | ADVERTISE_100FULL); - - giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); - ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); - - aner = anlpar = gbsr = status_2500 = 0; - if (tp->link_ok(dev)) { - aner = rtl8125_mdio_read(tp, MII_EXPANSION); - anlpar = rtl8125_mdio_read(tp, MII_LPA); - gbsr = rtl8125_mdio_read(tp, MII_STAT1000); - status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); - } else { - if (netif_running(dev)) { - aner = tp->phy_reg_aner; - anlpar = tp->phy_reg_anlpar; - gbsr = tp->phy_reg_gbsr; - status_2500 = tp->phy_reg_status_2500; - } - } - - if ((aner | anlpar | gbsr | status_2500) == 0) { - int auto_nego_tmp = 0; - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego_tmp |= ADVERTISE_10HALF; - if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego_tmp |= ADVERTISE_10FULL; - if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego_tmp |= ADVERTISE_100HALF; - if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego_tmp |= ADVERTISE_100FULL; - - if (auto_nego_tmp == 0) goto exit; - - auto_nego |= auto_nego_tmp; - goto skip_check_lpa; - } - if (!(aner & EXPANSION_NWAY)) goto exit; - - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego |= ADVERTISE_10HALF; - else if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego |= ADVERTISE_10FULL; - else if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego |= ADVERTISE_100HALF; - else if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego |= ADVERTISE_100FULL; - else if (adv & ADVERTISED_1000baseT_Half && (gbsr & LPA_1000HALF)) - giga_ctrl |= ADVERTISE_1000HALF; - else if (adv & ADVERTISED_1000baseT_Full && (gbsr & LPA_1000FULL)) - giga_ctrl |= ADVERTISE_1000FULL; - else if (adv & ADVERTISED_2500baseX_Full && (status_2500 & RTK_LPA_ADVERTISE_2500FULL)) - ctrl_2500 |= RTK_ADVERTISE_2500FULL; - else - goto exit; - -skip_check_lpa: - if (tp->DASH) - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); - -#ifdef CONFIG_DOWN_SPEED_100 - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); -#endif - - rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); - mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); - - rtl8125_phy_restart_nway(dev); - -exit: - return; -} - -static bool -rtl8125_keep_wol_link_speed(struct net_device *dev, u8 from_suspend) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if ((from_suspend && !tp->link_ok(dev)) || - (!from_suspend && tp->resume_not_chg_speed)) - return 1; - - return 0; -} -static void -rtl8125_powerdown_pll(struct net_device *dev, u8 from_suspend) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->check_keep_link_speed = 0; - if (tp->wol_enabled == WOL_ENABLED || tp->DASH || tp->EnableKCPOffload) { - rtl8125_set_hw_wol(dev, tp->wol_opts); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | PMSTS_En); - rtl8125_disable_cfg9346_write(tp); - } - - /* Enable the PME and clear the status */ - rtl8125_set_pci_pme(tp, 1); - - if (rtl8125_keep_wol_link_speed(dev, from_suspend)) { - if (tp->wol_opts & WAKE_PHY) - tp->check_keep_link_speed = 1; - } else { - if (HW_SUPPORT_D0_SPEED_UP(tp)) { - rtl8125_enable_d0_speedup(tp); - tp->check_keep_link_speed = 1; - } - - rtl8125_set_wol_link_speed(dev); - } - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - - return; - } - - if (tp->DASH) - return; - - rtl8125_phy_power_down(dev); - - if (!tp->HwIcVerUnknown) { - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~BIT_7); - break; - } - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); - break; - } -} - -static void rtl8125_powerup_pll(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | BIT_7 | BIT_6); - break; - } - - if (tp->resume_not_chg_speed) return; - - rtl8125_phy_power_up(dev); -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8125_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 options; - - wol->wolopts = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) { - wol->supported = 0; - return; - } else { - wol->supported = WAKE_ANY; - } - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - return; - - wol->wolopts = tp->wol_opts; -} - -static int -rtl8125_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) - return -EOPNOTSUPP; - - tp->wol_opts = wol->wolopts; - - tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; - - device_set_wakeup_enable(tp_to_dev(tp), wol->wolopts); - - return 0; -} - -static void -rtl8125_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_fw *rtl_fw = tp->rtl_fw; - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8125_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = R8125_REGS_DUMP_SIZE; - info->eedump_len = tp->eeprom_len; - BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); - if (rtl_fw) - strlcpy(info->fw_version, rtl_fw->version, - sizeof(info->fw_version)); -} - -static int -rtl8125_get_regs_len(struct net_device *dev) -{ - return R8125_REGS_DUMP_SIZE; -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static void -rtl8125_set_d0_speedup_speed(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_DISABLE; - if (tp->autoneg == AUTONEG_ENABLE) { - if (tp->speed == SPEED_2500) - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_2500; - else if(tp->speed == SPEED_1000) - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_1000; - } -} - -static int -rtl8125_set_speed_xmii(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int auto_nego = 0; - int giga_ctrl = 0; - int ctrl_2500 = 0; - int rc = -EINVAL; - - //Disable Giga Lite - ClearEthPhyOcpBit(tp, 0xA428, BIT_9); - ClearEthPhyOcpBit(tp, 0xA5EA, BIT_0); - - if (speed != SPEED_2500 && - (speed != SPEED_1000) && - (speed != SPEED_100) && - (speed != SPEED_10)) { - speed = SPEED_2500; - duplex = DUPLEX_FULL; - } - - giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); - ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); - - if (autoneg == AUTONEG_ENABLE) { - /*n-way force*/ - auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - if (adv & ADVERTISED_10baseT_Half) - auto_nego |= ADVERTISE_10HALF; - if (adv & ADVERTISED_10baseT_Full) - auto_nego |= ADVERTISE_10FULL; - if (adv & ADVERTISED_100baseT_Half) - auto_nego |= ADVERTISE_100HALF; - if (adv & ADVERTISED_100baseT_Full) - auto_nego |= ADVERTISE_100FULL; - if (adv & ADVERTISED_1000baseT_Half) - giga_ctrl |= ADVERTISE_1000HALF; - if (adv & ADVERTISED_1000baseT_Full) - giga_ctrl |= ADVERTISE_1000FULL; - if (adv & ADVERTISED_2500baseX_Full) - ctrl_2500 |= RTK_ADVERTISE_2500FULL; - - //flow control - if (dev->mtu <= ETH_DATA_LEN && tp->fcpause == rtl8125_fc_full) - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - tp->phy_2500_ctrl_reg = ctrl_2500; - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); - mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); - rtl8125_phy_restart_nway(dev); - mdelay(20); - } else { - /*true force*/ - if (speed == SPEED_10 || speed == SPEED_100) - rtl8125_phy_setup_force_mode(dev, speed, duplex); - else - goto out; - } - - tp->autoneg = autoneg; - tp->speed = speed; - tp->duplex = duplex; - tp->advertising = adv; - - rtl8125_set_d0_speedup_speed(tp); - - rc = 0; -out: - return rc; -} - -static int -rtl8125_set_speed(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret; - - if (tp->resume_not_chg_speed) return 0; - - ret = tp->set_speed(dev, autoneg, speed, duplex, adv); - - return ret; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8125_set_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - const struct ethtool_link_ksettings *cmd -#endif - ) -{ - int ret; - u8 autoneg; - u32 speed; - u8 duplex; - u32 supported, advertising; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - autoneg = cmd->autoneg; - speed = cmd->speed; - duplex = cmd->duplex; - supported = cmd->supported; - advertising = cmd->advertising; -#else - const struct ethtool_link_settings *base = &cmd->base; - autoneg = base->autoneg; - speed = base->speed; - duplex = base->duplex; - ethtool_convert_link_mode_to_legacy_u32(&supported, - cmd->link_modes.supported); - ethtool_convert_link_mode_to_legacy_u32(&advertising, - cmd->link_modes.advertising); - if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.supported)) - supported |= ADVERTISED_2500baseX_Full; - if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.advertising)) - advertising |= ADVERTISED_2500baseX_Full; -#endif - if (advertising & ~supported) - return -EINVAL; - - ret = rtl8125_set_speed(dev, autoneg, speed, duplex, advertising); - - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -static u32 -rtl8125_get_tx_csum(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 ret; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - ret = ((dev->features & NETIF_F_IP_CSUM) != 0); -#else - ret = ((dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != 0); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - - return ret; -} - -static u32 -rtl8125_get_rx_csum(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 ret; - - ret = tp->cp_cmd & RxChkSum; - - return ret; -} - -static int -rtl8125_set_tx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; -#else - if (data) - dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - - return 0; -} - -static int -rtl8125_set_rx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - - return 0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static u32 -rtl8125_rx_desc_opts1(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1; - else - return desc->opts1; -} - -static u32 -rtl8125_rx_desc_opts2(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2; - else - return desc->opts2; -} - -static void -rtl8125_clear_rx_desc_opts2(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2 = 0; - else - desc->opts2 = 0; -} - -#ifdef CONFIG_R8125_VLAN - -static inline u32 -rtl8125_tx_vlan_tag(struct rtl8125_private *tp, - struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - return (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#else - return (skb_vlan_tag_present(skb)) ? - TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; -#endif - - return 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -static void -rtl8125_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->vlgrp = grp; - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - if (tp->vlgrp) { - tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | (EnableInnerVlan | EnableOuterVlan)) - } else { - tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(EnableInnerVlan | EnableOuterVlan)) - } - } -} - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -static void -rtl8125_vlan_rx_kill_vid(struct net_device *dev, - unsigned short vid) -{ - struct rtl8125_private *tp = netdev_priv(dev); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; -#else - vlan_group_set_device(tp->vlgrp, vid, NULL); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - -static int -rtl8125_rx_vlan_skb(struct rtl8125_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); - int ret = -1; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8125_rx_hwaccel_skb(skb, tp->vlgrp, - swab16(opts2 & 0xffff)); - ret = 0; - } -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); -#else - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); -#endif - - rtl8125_clear_rx_desc_opts2(tp, desc); - return ret; -} - -#else /* !CONFIG_R8125_VLAN */ - -static inline u32 -rtl8125_tx_vlan_tag(struct rtl8125_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int -rtl8125_rx_vlan_skb(struct rtl8125_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - -static netdev_features_t rtl8125_fix_features(struct net_device *dev, - netdev_features_t features) -{ - if (dev->mtu > MSS_MAX) - features &= ~NETIF_F_ALL_TSO; - if (dev->mtu > ETH_DATA_LEN) { - features &= ~NETIF_F_ALL_TSO; - features &= ~NETIF_F_ALL_CSUM; - } -#ifndef CONFIG_R8125_VLAN - features &= ~NETIF_F_ALL_CSUM; -#endif - - return features; -} - -static int rtl8125_hw_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 rx_config; - - rx_config = RTL_R32(tp, RxConfig); - if (features & NETIF_F_RXALL) { - tp->rtl8125_rx_config |= (AcceptErr | AcceptRunt); - rx_config |= (AcceptErr | AcceptRunt); - } else { - tp->rtl8125_rx_config &= ~(AcceptErr | AcceptRunt); - rx_config &= ~(AcceptErr | AcceptRunt); - } - - if (features & NETIF_F_HW_VLAN_RX) { - tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); - rx_config |= (EnableInnerVlan | EnableOuterVlan); - } else { - tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - } - - RTL_W32(tp, RxConfig, rx_config); - - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - RTL_R16(tp, CPlusCmd); - - return 0; -} - -static int rtl8125_set_features(struct net_device *dev, - netdev_features_t features) -{ - features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX; - - rtl8125_hw_set_features(dev, features); - - return 0; -} - -#endif - -static void rtl8125_gset_xmii(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 aner = tp->phy_reg_aner; - u16 anlpar = tp->phy_reg_anlpar; - u16 gbsr = tp->phy_reg_gbsr; - u16 status_2500 = tp->phy_reg_status_2500; - u32 lpa_adv = 0; - u16 status; - u8 autoneg, duplex; - u32 speed = 0; - u16 bmcr; - u32 supported, advertising; - u8 report_lpa = 0; - - supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_2500baseX_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | - SUPPORTED_Pause | - SUPPORTED_Asym_Pause; - - advertising = ADVERTISED_TP; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8125_mdio_read(tp, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - advertising |= ADVERTISED_Autoneg; - autoneg = AUTONEG_ENABLE; - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - advertising |= ADVERTISED_1000baseT_Full; - if (tp->phy_2500_ctrl_reg & RTK_ADVERTISE_2500FULL) - advertising |= ADVERTISED_2500baseX_Full; - } else { - autoneg = AUTONEG_DISABLE; - } - - status = RTL_R16(tp, PHYstatus); - if (netif_running(dev) && (status & LinkStatus)) - report_lpa = 1; - - if (report_lpa) { - /*link on*/ - if (status & _2500bpsF) - speed = SPEED_2500; - else if (status & _1000bpsF) - speed = SPEED_1000; - else if (status & _100bps) - speed = SPEED_100; - else if (status & _10bps) - speed = SPEED_10; - - if (status & TxFlowCtrl) - advertising |= ADVERTISED_Asym_Pause; - - if (status & RxFlowCtrl) - advertising |= ADVERTISED_Pause; - - duplex = ((status & (_1000bpsF | _2500bpsF)) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; - - /*link partner*/ - if (aner & EXPANSION_NWAY) - lpa_adv |= ADVERTISED_Autoneg; - if (anlpar & LPA_10HALF) - lpa_adv |= ADVERTISED_10baseT_Half; - if (anlpar & LPA_10FULL) - lpa_adv |= ADVERTISED_10baseT_Full; - if (anlpar & LPA_100HALF) - lpa_adv |= ADVERTISED_100baseT_Half; - if (anlpar & LPA_100FULL) - lpa_adv |= ADVERTISED_100baseT_Full; - if (anlpar & LPA_PAUSE_CAP) - lpa_adv |= ADVERTISED_Pause; - if (anlpar & LPA_PAUSE_ASYM) - lpa_adv |= ADVERTISED_Asym_Pause; - if (gbsr & LPA_1000HALF) - lpa_adv |= ADVERTISED_1000baseT_Half; - if (gbsr & LPA_1000FULL) - lpa_adv |= ADVERTISED_1000baseT_Full; - if (status_2500 & RTK_LPA_ADVERTISE_2500FULL) - lpa_adv |= ADVERTISED_2500baseX_Full; - } else { - /*link down*/ - speed = SPEED_UNKNOWN; - duplex = DUPLEX_UNKNOWN; - lpa_adv = 0; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - cmd->supported = supported; - cmd->advertising = advertising; - cmd->autoneg = autoneg; - cmd->speed = speed; - cmd->duplex = duplex; - cmd->port = PORT_TP; - cmd->lp_advertising = lpa_adv; -#else - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, - advertising); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, - lpa_adv); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) - if (supported & SUPPORTED_2500baseX_Full) { - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, - cmd->link_modes.supported, 0); - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.supported, 1); - } - if (advertising & ADVERTISED_2500baseX_Full) { - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, - cmd->link_modes.advertising, 0); - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.advertising, 1); - } - if (report_lpa) { - if (lpa_adv & ADVERTISED_2500baseX_Full) { - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, - cmd->link_modes.lp_advertising, 0); - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.lp_advertising, 1); - } - if (status_2500 & RTK_LPA_ADVERTISE_5000FULL) - linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, - cmd->link_modes.lp_advertising, 1); - if (status_2500 & RTK_LPA_ADVERTISE_10000FULL) - linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, - cmd->link_modes.lp_advertising, 1); - } -#endif - cmd->base.autoneg = autoneg; - cmd->base.speed = speed; - cmd->base.duplex = duplex; - cmd->base.port = PORT_TP; -#endif -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8125_get_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->get_settings(dev, cmd); - - return 0; -} - -static void rtl8125_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - u8 *data = p; - - if (regs->len < R8125_REGS_DUMP_SIZE) - return /* -EINVAL */; - - memset(p, 0, regs->len); - - for (i = 0; i < R8125_MAC_REGS_SIZE; i++) - *data++ = readb(ioaddr + i); - data = (u8*)p + 256; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - for (i = 0; i < R8125_PHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8125_mdio_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 2; - - for (i = 0; i < R8125_EPHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8125_ephy_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 3; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - for (i = 0; i < R8125_ERI_REGS_SIZE; i+=4) { - *(u32*)data = rtl8125_eri_read(tp, i , 4, ERIAR_ExGMAC); - data += 4; - } - break; - } -} - -static void rtl8125_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - pause->autoneg = (tp->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - if (tp->fcpause == rtl8125_fc_rx_pause) - pause->rx_pause = 1; - else if (tp->fcpause == rtl8125_fc_tx_pause) - pause->tx_pause = 1; - else if (tp->fcpause == rtl8125_fc_full) { - pause->rx_pause = 1; - pause->tx_pause = 1; - } -} - -static int rtl8125_set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct rtl8125_private *tp = netdev_priv(dev); - enum rtl8125_fc_mode newfc; - - if (pause->tx_pause || pause->rx_pause) - newfc = rtl8125_fc_full; - else - newfc = rtl8125_fc_none; - - if (tp->fcpause != newfc) { - tp->fcpause = newfc; - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - } - - return 0; - -} - -static u32 -rtl8125_get_msglevel(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void -rtl8125_set_msglevel(struct net_device *dev, - u32 value) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8125_gstrings[][ETH_GSTRING_LEN] = { - /* legacy */ - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", - - /* extended */ - "tx_octets", - "rx_octets", - "rx_multicast64", - "tx_unicast64", - "tx_broadcast64", - "tx_multicast64", - "tx_pause_on", - "tx_pause_off", - "tx_pause_all", - "tx_deferred", - "tx_late_collision", - "tx_all_collision", - "tx_aborted32", - "align_errors32", - "rx_frame_too_long", - "rx_runt", - "rx_pause_on", - "rx_pause_off", - "rx_pause_all", - "rx_unknown_opcode", - "rx_mac_error", - "tx_underrun32", - "rx_mac_missed", - "rx_tcam_dropped", - "tdu", - "rdu", -}; -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int rtl8125_get_stats_count(struct net_device *dev) -{ - return ARRAY_SIZE(rtl8125_gstrings); -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -#else -static int rtl8125_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8125_gstrings); - default: - return -EOPNOTSUPP; - } -} -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8125_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, - u64 *data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - - ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) - return; - - rtl8125_dump_tally_counter(tp, paddr); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underrun); - - data[13] = le64_to_cpu(counters->tx_octets); - data[14] = le64_to_cpu(counters->rx_octets); - data[15] = le64_to_cpu(counters->rx_multicast64); - data[16] = le64_to_cpu(counters->tx_unicast64); - data[17] = le64_to_cpu(counters->tx_broadcast64); - data[18] = le64_to_cpu(counters->tx_multicast64); - data[19] = le32_to_cpu(counters->tx_pause_on); - data[20] = le32_to_cpu(counters->tx_pause_off); - data[21] = le32_to_cpu(counters->tx_pause_all); - data[22] = le32_to_cpu(counters->tx_deferred); - data[23] = le32_to_cpu(counters->tx_late_collision); - data[24] = le32_to_cpu(counters->tx_all_collision); - data[25] = le32_to_cpu(counters->tx_aborted32); - data[26] = le32_to_cpu(counters->align_errors32); - data[27] = le32_to_cpu(counters->rx_frame_too_long); - data[28] = le32_to_cpu(counters->rx_runt); - data[29] = le32_to_cpu(counters->rx_pause_on); - data[30] = le32_to_cpu(counters->rx_pause_off); - data[31] = le32_to_cpu(counters->rx_pause_all); - data[32] = le32_to_cpu(counters->rx_unknown_opcode); - data[33] = le32_to_cpu(counters->rx_mac_error); - data[34] = le32_to_cpu(counters->tx_underrun32); - data[35] = le32_to_cpu(counters->rx_mac_missed); - data[36] = le32_to_cpu(counters->rx_tcam_dropped); - data[37] = le32_to_cpu(counters->tdu); - data[38] = le32_to_cpu(counters->rdu); -} - -static void -rtl8125_get_strings(struct net_device *dev, - u32 stringset, - u8 *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8125_gstrings, sizeof(rtl8125_gstrings)); - break; - } -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static int rtl_get_eeprom_len(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - return tp->eeprom_len; -} - -static int rtl_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i,j,ret; - int start_w, end_w; - int VPD_addr, VPD_data; - u32 *eeprom_buff; - u16 tmp; - - if (tp->eeprom_type == EEPROM_TYPE_NONE) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Detect none EEPROM\n"); - return -EOPNOTSUPP; - } else if (eeprom->len == 0 || (eeprom->offset+eeprom->len) > tp->eeprom_len) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Invalid parameter\n"); - return -EINVAL; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - VPD_addr = 0xD2; - VPD_data = 0xD4; - break; - } - - start_w = eeprom->offset >> 2; - end_w = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32)*(end_w - start_w + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - rtl8125_enable_cfg9346_write(tp); - ret = -EFAULT; - for (i=start_w; i<=end_w; i++) { - pci_write_config_word(tp->pci_dev, VPD_addr, (u16)i*4); - ret = -EFAULT; - for (j = 0; j < 10; j++) { - udelay(400); - pci_read_config_word(tp->pci_dev, VPD_addr, &tmp); - if (tmp&0x8000) { - ret = 0; - break; - } - } - - if (ret) - break; - - pci_read_config_dword(tp->pci_dev, VPD_data, &eeprom_buff[i-start_w]); - } - rtl8125_disable_cfg9346_write(tp); - - if (!ret) - memcpy(buf, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); - - kfree(eeprom_buff); - - return ret; -} - -#undef ethtool_op_get_link -#define ethtool_op_get_link _kc_ethtool_op_get_link -static u32 _kc_ethtool_op_get_link(struct net_device *dev) -{ - return netif_carrier_ok(dev) ? 1 : 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#undef ethtool_op_get_sg -#define ethtool_op_get_sg _kc_ethtool_op_get_sg -static u32 _kc_ethtool_op_get_sg(struct net_device *dev) -{ -#ifdef NETIF_F_SG - return (dev->features & NETIF_F_SG) != 0; -#else - return 0; -#endif -} - -#undef ethtool_op_set_sg -#define ethtool_op_set_sg _kc_ethtool_op_set_sg -static int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - -#ifdef NETIF_F_SG - if (data) - dev->features |= NETIF_F_SG; - else - dev->features &= ~NETIF_F_SG; -#endif - - return 0; -} -#endif - -static int rtl8125_enable_eee(struct rtl8125_private *tp) -{ - struct ethtool_eee *eee = &tp->eee; - u16 eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); - - SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - SetMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); - - SetEthPhyOcpBit(tp, 0xA432, BIT_4); - SetEthPhyOcpBit(tp, 0xA5D0, eee_adv_t); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); - - SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - - SetEthPhyOcpBit(tp, 0xA5D0, eee_adv_t); - if (eee->advertised & SUPPORTED_2500baseX_Full) - SetEthPhyOcpBit(tp, 0xA6D4, BIT_0); - else - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_set_phy_mcu_patch_request(tp); - ClearMcuAccessRegBit(tp, 0xE052, BIT_0); - ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); - ClearEthPhyOcpBit(tp, 0xA430, BIT_15); - rtl8125_clear_phy_mcu_patch_request(tp); - break; - } - - return ret; -} - -static int rtl8125_disable_eee(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - ClearMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); - - ClearEthPhyOcpBit(tp, 0xA432, BIT_4); - ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - - ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_set_phy_mcu_patch_request(tp); - ClearMcuAccessRegBit(tp, 0xE052, BIT_0); - ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); - ClearEthPhyOcpBit(tp, 0xA430, BIT_15); - rtl8125_clear_phy_mcu_patch_request(tp); - break; - } - - return ret; -} - -static int rtl_nway_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret, bmcr; - - if (unlikely(tp->rtk_enable_diag)) - return -EBUSY; - - /* if autoneg is off, it's an error */ - rtl8125_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8125_mdio_read(tp, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - rtl8125_mdio_write(tp, MII_BMCR, bmcr); - ret = 0; - } else { - ret = -EINVAL; - } - - return ret; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) -static u32 -rtl8125_tx_lpi_timer_to_us(struct rtl8125_private *tp , u32 tx_lpi_timer) -{ - u32 to_us; - u16 status; - - //2.5G : tx_lpi_timer * 3.2ns - //Giga: tx_lpi_timer * 8ns - //100M : tx_lpi_timer * 80ns - to_us = tx_lpi_timer * 80; - status = RTL_R16(tp, PHYstatus); - if (status & LinkStatus) { - /*link on*/ - if (status & _2500bpsF) - to_us = (tx_lpi_timer * 32) / 10; - else if (status & _1000bpsF) - to_us = tx_lpi_timer * 8; - } - - //ns to us - to_us /= 1000; - - return to_us; -} - -static int -rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) -{ - struct rtl8125_private *tp = netdev_priv(net); - struct ethtool_eee *eee = &tp->eee; - u32 lp, adv, tx_lpi_timer, supported = 0; - u16 val; - - if (unlikely(tp->rtk_enable_diag)) - return -EBUSY; - - /* Get Supported EEE */ - //val = mdio_direct_read_phy_ocp(tp, 0xA5C4); - //supported = mmd_eee_cap_to_ethtool_sup_t(val); - supported = eee->supported; - - /* Get advertisement EEE */ - val = mdio_direct_read_phy_ocp(tp, 0xA5D0); - adv = mmd_eee_adv_to_ethtool_adv_t(val); - - /* Get LP advertisement EEE */ - val = mdio_direct_read_phy_ocp(tp, 0xA5D2); - lp = mmd_eee_adv_to_ethtool_adv_t(val); - - /* Get EEE Tx LPI timer*/ - tx_lpi_timer = RTL_R16(tp, EEE_TXIDLE_TIMER_8125); - - val = rtl8125_mac_ocp_read(tp, 0xE040); - val &= BIT_1 | BIT_0; - - edata->eee_enabled = !!val; - edata->eee_active = !!(supported & adv & lp); - edata->supported = supported; - edata->advertised = adv; - edata->lp_advertised = lp; - edata->tx_lpi_enabled = edata->eee_enabled; - edata->tx_lpi_timer = rtl8125_tx_lpi_timer_to_us(tp, tx_lpi_timer); - - return 0; -} - -static int -rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) -{ - struct rtl8125_private *tp = netdev_priv(net); - struct ethtool_eee *eee = &tp->eee; - u32 advertising; - int rc = 0; - - if (!HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp) || - tp->DASH) - return -EOPNOTSUPP; - - if (unlikely(tp->rtk_enable_diag)) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "Diag Enabled\n"); - rc = -EBUSY; - goto out; - } - - if (tp->autoneg != AUTONEG_ENABLE) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE requires autoneg\n"); - rc = -EINVAL; - goto out; - } - - if (edata->tx_lpi_enabled) { - if (edata->tx_lpi_timer > tp->max_jumbo_frame_size || - edata->tx_lpi_timer < ETH_MIN_MTU) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "Valid LPI timer range is %d to %d. \n", - ETH_MIN_MTU, tp->max_jumbo_frame_size); - rc = -EINVAL; - goto out; - } - } - - advertising = tp->advertising; - if (!edata->advertised) { - edata->advertised = advertising & eee->supported; - } else if (edata->advertised & ~advertising) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of autoneg advertised speeds %x\n", - edata->advertised, advertising); - rc = -EINVAL; - goto out; - } - - if (edata->advertised & ~eee->supported) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of support %x\n", - edata->advertised, eee->supported); - rc = -EINVAL; - goto out; - } - - //tp->eee.eee_enabled = edata->eee_enabled; - //tp->eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); - - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE tx_lpi_timer %x must be a subset of support %x\n", - edata->tx_lpi_timer, eee->tx_lpi_timer); - - eee->advertised = edata->advertised; - eee->tx_lpi_enabled = edata->tx_lpi_enabled; - eee->tx_lpi_timer = edata->tx_lpi_timer; - eee->eee_enabled = edata->eee_enabled; - - if (eee->eee_enabled) - rtl8125_enable_eee(tp); - else - rtl8125_disable_eee(tp); - - rtl_nway_reset(net); - - return rc; - -out: - - return rc; -} -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static const struct ethtool_ops rtl8125_ethtool_ops = { - .get_drvinfo = rtl8125_get_drvinfo, - .get_regs_len = rtl8125_get_regs_len, - .get_link = ethtool_op_get_link, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - .get_settings = rtl8125_get_settings, - .set_settings = rtl8125_set_settings, -#else - .get_link_ksettings = rtl8125_get_settings, - .set_link_ksettings = rtl8125_set_settings, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .get_pauseparam = rtl8125_get_pauseparam, - .set_pauseparam = rtl8125_set_pauseparam, -#endif - .get_msglevel = rtl8125_get_msglevel, - .set_msglevel = rtl8125_set_msglevel, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - .get_rx_csum = rtl8125_get_rx_csum, - .set_rx_csum = rtl8125_set_rx_csum, - .get_tx_csum = rtl8125_get_tx_csum, - .set_tx_csum = rtl8125_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, -#ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, -#endif -#endif - .get_regs = rtl8125_get_regs, - .get_wol = rtl8125_get_wol, - .set_wol = rtl8125_set_wol, - .get_strings = rtl8125_get_strings, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - .get_stats_count = rtl8125_get_stats_count, -#else - .get_sset_count = rtl8125_get_sset_count, -#endif - .get_ethtool_stats = rtl8125_get_ethtool_stats, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -#ifdef ETHTOOL_GPERMADDR - .get_perm_addr = ethtool_op_get_perm_addr, -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) - .get_eeprom = rtl_get_eeprom, - .get_eeprom_len = rtl_get_eeprom_len, -#ifdef ENABLE_RSS_SUPPORT - .get_rxnfc = rtl8125_get_rxnfc, - .set_rxnfc = rtl8125_set_rxnfc, - .get_rxfh_indir_size = rtl8125_rss_indir_size, - .get_rxfh_key_size = rtl8125_get_rxfh_key_size, - .get_rxfh = rtl8125_get_rxfh, - .set_rxfh = rtl8125_set_rxfh, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#ifdef ENABLE_PTP_SUPPORT - .get_ts_info = rtl8125_get_ts_info, -#else - .get_ts_info = ethtool_op_get_ts_info, -#endif //ENABLE_PTP_SUPPORT -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) - .get_eee = rtl_ethtool_get_eee, - .set_eee = rtl_ethtool_set_eee, -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - .nway_reset = rtl_nway_reset, - -}; -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if 0 - -static int rtl8125_enable_green_feature(struct rtl8125_private *tp) -{ - u16 gphy_val; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); - SetEthPhyOcpBit(tp, 0xA438, BIT_15); - rtl8125_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -static int rtl8125_disable_green_feature(struct rtl8125_private *tp) -{ - u16 gphy_val; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); - ClearEthPhyOcpBit(tp, 0xA438, BIT_15); - rtl8125_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -#endif - -static void rtl8125_get_mac_version(struct rtl8125_private *tp) -{ - u32 reg,val32; - u32 ICVerID; - - val32 = RTL_R32(tp, TxConfig); - reg = val32 & 0x7c800000; - ICVerID = val32 & 0x00700000; - - switch (reg) { - case 0x60800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_2; - } else if (ICVerID == 0x100000) { - tp->mcfg = CFG_METHOD_3; - } else { - tp->mcfg = CFG_METHOD_3; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V4; - break; - case 0x64000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_4; - } else if (ICVerID == 0x100000) { - tp->mcfg = CFG_METHOD_5; - } else { - tp->mcfg = CFG_METHOD_5; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V4; - break; - default: - printk("unknown chip version (%x)\n",reg); - tp->mcfg = CFG_METHOD_DEFAULT; - tp->HwIcVerUnknown = TRUE; - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - } -} - -static void -rtl8125_print_mac_version(struct rtl8125_private *tp) -{ - int i; - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) { - dprintk("Realtek PCIe 2.5GbE Family Controller mcfg = %04d\n", - rtl_chip_info[i].mcfg); - return; - } - } - - dprintk("mac_version == Unknown\n"); -} - -static void -rtl8125_tally_counter_addr_fill(struct rtl8125_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, (u64)tp->tally_paddr & (DMA_BIT_MASK(32))); -} - -static void -rtl8125_tally_counter_clear(struct rtl8125_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, ((u64)tp->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); -} - -static void -rtl8125_clear_phy_ups_reg(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - ClearEthPhyOcpBit(tp, 0xA466, BIT_0); - break; - }; - ClearEthPhyOcpBit(tp, 0xA468, BIT_3 | BIT_1); -} - -static int -rtl8125_is_ups_resume(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - return (rtl8125_mac_ocp_read(tp, 0xD42C) & BIT_8); - - return 0; -} - -static void -rtl8125_clear_ups_resume_bit(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_mac_ocp_write(tp, 0xD408, rtl8125_mac_ocp_read(tp, 0xD408) & ~(BIT_8)); -} - -static void -rtl8125_wait_phy_ups_resume(struct net_device *dev, u16 PhyState) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 TmpPhyState; - int i=0; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - do { - TmpPhyState = mdio_direct_read_phy_ocp(tp, 0xA420); - TmpPhyState &= 0x7; - mdelay(1); - i++; - } while ((i < 100) && (TmpPhyState != PhyState)); - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(i == 100); -#endif -} - -void -rtl8125_enable_now_is_oob(struct rtl8125_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | Now_is_oob); - } -} - -void -rtl8125_disable_now_is_oob(struct rtl8125_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) & ~Now_is_oob); - } -} - -static void -rtl8125_exit_oob(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 data16; - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_dash2_disable_txrx(dev); - break; - } - - if (tp->DASH) { - rtl8125_driver_stop(tp); - rtl8125_driver_start(tp); -#ifdef ENABLE_DASH_SUPPORT - DashHwInit(dev); -#endif - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_realwow_hw_init(dev); -#else - //Disable realwow function - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xC0BC, 0x00FF); - break; - } -#endif //ENABLE_REALWOW_SUPPORT - - rtl8125_nic_reset(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_disable_now_is_oob(tp); - - data16 = rtl8125_mac_ocp_read(tp, 0xE8DE) & ~BIT_14; - rtl8125_mac_ocp_write(tp, 0xE8DE, data16); - rtl8125_wait_ll_share_fifo_ready(dev); - - rtl8125_mac_ocp_write(tp, 0xC0AA, 0x07D0); - rtl8125_mac_ocp_write(tp, 0xC0A6, 0x01B5); - rtl8125_mac_ocp_write(tp, 0xC01E, 0x5555); - - rtl8125_wait_ll_share_fifo_ready(dev); - break; - } - - //wait ups resume (phy state 2) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (rtl8125_is_ups_resume(dev)) { - rtl8125_wait_phy_ups_resume(dev, 2); - rtl8125_clear_ups_resume_bit(dev); - rtl8125_clear_phy_ups_reg(dev); - } - break; - }; -} - -void -rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - rtl8125_disable_cfg9346_write(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xFC38, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xFC28, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC2C, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC34, 0x0000); - rtl8125_mac_ocp_write(tp, 0xFC36, 0x0000); - mdelay(3); - rtl8125_mac_ocp_write(tp, 0xFC26, 0x0000); - break; - } -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8125_set_mac_mcu_8125a_1(struct net_device *dev) -{ - rtl8125_hw_disable_mac_mcu_bps(dev); -} - -static void -rtl8125_set_mac_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8125a_2[] = { - 0xE008, 0xE01E, 0xE02E, 0xE054, 0xE057, 0xE059, 0xE0C2, 0xE0CB, 0x9996, - 0x49D1, 0xF005, 0x49D4, 0xF10A, 0x49D8, 0xF108, 0xC00F, 0x7100, 0x209C, - 0x249C, 0xC009, 0x9900, 0xE004, 0xC006, 0x1900, 0x9900, 0xC602, 0xBE00, - 0x5A48, 0xE0C2, 0x0004, 0xE10A, 0xC60F, 0x73C4, 0x49B3, 0xF106, 0x73C2, - 0xC608, 0xB406, 0xC609, 0xFF80, 0xC605, 0xB406, 0xC605, 0xFF80, 0x0544, - 0x0568, 0xE906, 0xCDE8, 0xC724, 0xC624, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, - 0x49E0, 0xF1FE, 0x76E6, 0x486D, 0x4868, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, - 0x49E0, 0xF1FE, 0xC615, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, - 0x76E6, 0x486F, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, 0x7196, - 0xC702, 0xBF00, 0x5A44, 0xEB0E, 0x0070, 0x00C3, 0x1BC0, 0xC602, 0xBE00, - 0x0E26, 0xC602, 0xBE00, 0x0EBA, 0x1501, 0xF02A, 0x1500, 0xF15D, 0xC661, - 0x75C8, 0x49D5, 0xF00A, 0x49D6, 0xF008, 0x49D7, 0xF006, 0x49D8, 0xF004, - 0x75D2, 0x49D9, 0xF150, 0xC553, 0x77A0, 0x75C8, 0x4855, 0x4856, 0x4857, - 0x4858, 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, - 0x9DC8, 0x75D2, 0x4859, 0x9DD2, 0xC643, 0x75C0, 0x49D4, 0xF033, 0x49D0, - 0xF137, 0xE030, 0xC63A, 0x75C8, 0x49D5, 0xF00E, 0x49D6, 0xF00C, 0x49D7, - 0xF00A, 0x49D8, 0xF008, 0x75D2, 0x49D9, 0xF005, 0xC62E, 0x75C0, 0x49D7, - 0xF125, 0xC528, 0x77A0, 0xC627, 0x75C8, 0x4855, 0x4856, 0x4857, 0x4858, - 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, 0x9DC8, - 0x75D2, 0x4859, 0x9DD2, 0xC616, 0x75C0, 0x4857, 0x9DC0, 0xC613, 0x75C0, - 0x49DA, 0xF003, 0x49D0, 0xF107, 0xC60B, 0xC50E, 0x48D9, 0x9DC0, 0x4859, - 0x9DC0, 0xC608, 0xC702, 0xBF00, 0x3AE0, 0xE860, 0xB400, 0xB5D4, 0xE908, - 0xE86C, 0x1200, 0xC409, 0x6780, 0x48F1, 0x8F80, 0xC404, 0xC602, 0xBE00, - 0x10AA, 0xC010, 0xEA7C, 0xC602, 0xBE00, 0x0000 - }; - - rtl8125_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125a_2); i++) { - rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125a_2[i]); - } - - rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0540); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0E24); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x0EB8); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x3A5C); - rtl8125_mac_ocp_write(tp, 0xFC34, 0x10A8); - - rtl8125_mac_ocp_write(tp, 0xFC48, 0x007A); -} - -static void -rtl8125_set_mac_mcu_8125b_1(struct net_device *dev) -{ - rtl8125_hw_disable_mac_mcu_bps(dev); -} - -static void -rtl8125_set_mac_mcu_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8125b_2[] = { - 0xE010, 0xE01B, 0xE026, 0xE037, 0xE03D, 0xE057, 0xE05B, 0xE05F, 0xE061, - 0xE063, 0xE065, 0xE067, 0xE069, 0xE06B, 0xE06D, 0xE06F, 0x740A, 0x4846, - 0x4847, 0x9C0A, 0xC607, 0x74C0, 0x48C6, 0x9CC0, 0xC602, 0xBE00, 0x13F0, - 0xE054, 0x72CA, 0x4826, 0x4827, 0x9ACA, 0xC607, 0x72C0, 0x48A6, 0x9AC0, - 0xC602, 0xBE00, 0x081C, 0xE054, 0xC60F, 0x74C4, 0x49CC, 0xF109, 0xC60C, - 0x74CA, 0x48C7, 0x9CCA, 0xC609, 0x74C0, 0x4846, 0x9CC0, 0xC602, 0xBE00, - 0x2494, 0xE092, 0xE0C0, 0xE054, 0x7420, 0x48C0, 0x9C20, 0x7444, 0xC602, - 0xBE00, 0x12DC, 0x733A, 0x21B5, 0x25BC, 0x1304, 0xF111, 0x1B12, 0x1D2A, - 0x3168, 0x3ADA, 0x31AB, 0x1A00, 0x9AC0, 0x1300, 0xF1FB, 0x7620, 0x236E, - 0x276F, 0x1A3C, 0x22A1, 0x41B5, 0x9EE2, 0x76E4, 0x486F, 0x9EE4, 0xC602, - 0xBE00, 0x4A26, 0x733A, 0x49BB, 0xC602, 0xBE00, 0x47A2, 0x48C1, 0x48C2, - 0xC5C3, 0xBD00, 0x0A52, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, - 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, - 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, - 0xC602, 0xBE00, 0x0000 - }; - - rtl8125_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125b_2); i++) { - rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125b_2[i]); - } - - rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8125_mac_ocp_write(tp, 0xFC28, 0x13E6); - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0812); - rtl8125_mac_ocp_write(tp, 0xFC2C, 0x248C); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x12DA); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x4A20); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x47A0); - rtl8125_mac_ocp_write(tp, 0xFC34, 0x0A46); - - rtl8125_mac_ocp_write(tp, 0xFC48, 0x007F); -} - -static void -rtl8125_hw_mac_mcu_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->NotWrMcuPatchCode == TRUE) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_set_mac_mcu_8125a_1(dev); - break; - case CFG_METHOD_3: - rtl8125_set_mac_mcu_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_set_mac_mcu_8125b_1(dev); - break; - case CFG_METHOD_5: - rtl8125_set_mac_mcu_8125b_2(dev); - break; - } -} -#endif - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8125_release_firmware(struct rtl8125_private *tp) -{ - if (tp->rtl_fw) { - rtl8125_fw_release_firmware(tp->rtl_fw); - kfree(tp->rtl_fw); - tp->rtl_fw = NULL; - } -} - -void rtl8125_apply_firmware(struct rtl8125_private *tp) -{ - /* TODO: release firmware if rtl_fw_write_firmware signals failure. */ - if (tp->rtl_fw) { - rtl8125_fw_write_firmware(tp, tp->rtl_fw); - /* At least one firmware doesn't reset tp->ocp_base. */ - tp->ocp_base = OCP_STD_PHY_BASE; - - /* PHY soft reset may still be in progress */ - //phy_read_poll_timeout(tp->phydev, MII_BMCR, val, - // !(val & BMCR_RESET), - // 50000, 600000, true); - rtl8125_wait_phy_reset_complete(tp); - - tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); - tp->sw_ram_code_ver = tp->hw_ram_code_ver; - tp->HwHasWrRamCodeToMicroP = TRUE; - } -} -#endif - -static void -rtl8125_hw_init(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - rtl8125_disable_cfg9346_write(tp); - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - break; - } - - //Disable UPS - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xD40A, rtl8125_mac_ocp_read( tp, 0xD40A) & ~(BIT_4)); - break; - } - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) - rtl8125_hw_mac_mcu_config(dev); -#endif - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) - rtl8125_disable_ocp_phy_power_saving(dev); - - //Set PCIE uncorrectable error status mask pcie 0x108 - csi_tmp = rtl8125_csi_read(tp, 0x108); - csi_tmp |= BIT_20; - rtl8125_csi_write(tp, 0x108, csi_tmp); - - rtl8125_enable_cfg9346_write(tp); - rtl8125_disable_linkchg_wakeup(dev); - rtl8125_disable_cfg9346_write(tp); - rtl8125_disable_magic_packet(dev); - rtl8125_disable_d0_speedup(tp); - rtl8125_set_pci_pme(tp, 0); - if (s0_magic_packet == 1) - rtl8125_enable_magic_packet(dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - if (tp->rtl_fw && - !tp->resume_not_chg_speed && - !(HW_DASH_SUPPORT_TYPE_3(tp) && - tp->HwPkgDet == 0x06)) - rtl8125_apply_firmware(tp); -#endif -} - -static void -rtl8125_hw_ephy_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_ephy_write(tp, 0x01, 0xA812); - rtl8125_ephy_write(tp, 0x09, 0x520C); - rtl8125_ephy_write(tp, 0x04, 0xD000); - rtl8125_ephy_write(tp, 0x0D, 0xF702); - rtl8125_ephy_write(tp, 0x0A, 0x8653); - rtl8125_ephy_write(tp, 0x06, 0x001E); - rtl8125_ephy_write(tp, 0x08, 0x3595); - rtl8125_ephy_write(tp, 0x20, 0x9455); - rtl8125_ephy_write(tp, 0x21, 0x99FF); - rtl8125_ephy_write(tp, 0x02, 0x6046); - rtl8125_ephy_write(tp, 0x29, 0xFE00); - rtl8125_ephy_write(tp, 0x23, 0xAB62); - - rtl8125_ephy_write(tp, 0x41, 0xA80C); - rtl8125_ephy_write(tp, 0x49, 0x520C); - rtl8125_ephy_write(tp, 0x44, 0xD000); - rtl8125_ephy_write(tp, 0x4D, 0xF702); - rtl8125_ephy_write(tp, 0x4A, 0x8653); - rtl8125_ephy_write(tp, 0x46, 0x001E); - rtl8125_ephy_write(tp, 0x48, 0x3595); - rtl8125_ephy_write(tp, 0x60, 0x9455); - rtl8125_ephy_write(tp, 0x61, 0x99FF); - rtl8125_ephy_write(tp, 0x42, 0x6046); - rtl8125_ephy_write(tp, 0x69, 0xFE00); - rtl8125_ephy_write(tp, 0x63, 0xAB62); - break; - case CFG_METHOD_3: - rtl8125_ephy_write(tp, 0x04, 0xD000); - rtl8125_ephy_write(tp, 0x0A, 0x8653); - rtl8125_ephy_write(tp, 0x23, 0xAB66); - rtl8125_ephy_write(tp, 0x20, 0x9455); - rtl8125_ephy_write(tp, 0x21, 0x99FF); - rtl8125_ephy_write(tp, 0x29, 0xFE04); - - rtl8125_ephy_write(tp, 0x44, 0xD000); - rtl8125_ephy_write(tp, 0x4A, 0x8653); - rtl8125_ephy_write(tp, 0x63, 0xAB66); - rtl8125_ephy_write(tp, 0x60, 0x9455); - rtl8125_ephy_write(tp, 0x61, 0x99FF); - rtl8125_ephy_write(tp, 0x69, 0xFE04); - - ClearAndSetPCIePhyBit(tp, - 0x2A, - (BIT_14 | BIT_13 | BIT_12), - (BIT_13 | BIT_12) - ); - ClearPCIePhyBit(tp, 0x19, BIT_6); - SetPCIePhyBit(tp, 0x1B, (BIT_11 | BIT_10 | BIT_9)); - ClearPCIePhyBit(tp, 0x1B, (BIT_14 | BIT_13 | BIT_12)); - rtl8125_ephy_write(tp, 0x02, 0x6042); - rtl8125_ephy_write(tp, 0x06, 0x0014); - - ClearAndSetPCIePhyBit(tp, - 0x6A, - (BIT_14 | BIT_13 | BIT_12), - (BIT_13 | BIT_12) - ); - ClearPCIePhyBit(tp, 0x59, BIT_6); - SetPCIePhyBit(tp, 0x5B, (BIT_11 | BIT_10 | BIT_9)); - ClearPCIePhyBit(tp, 0x5B, (BIT_14 | BIT_13 | BIT_12)); - rtl8125_ephy_write(tp, 0x42, 0x6042); - rtl8125_ephy_write(tp, 0x46, 0x0014); - break; - case CFG_METHOD_4: - rtl8125_ephy_write(tp, 0x06, 0x001F); - rtl8125_ephy_write(tp, 0x0A, 0xB66B); - rtl8125_ephy_write(tp, 0x01, 0xA852); - rtl8125_ephy_write(tp, 0x24, 0x0008); - rtl8125_ephy_write(tp, 0x2F, 0x6052); - rtl8125_ephy_write(tp, 0x0D, 0xF716); - rtl8125_ephy_write(tp, 0x20, 0xD477); - rtl8125_ephy_write(tp, 0x21, 0x4477); - rtl8125_ephy_write(tp, 0x22, 0x0013); - rtl8125_ephy_write(tp, 0x23, 0xBB66); - rtl8125_ephy_write(tp, 0x0B, 0xA909); - rtl8125_ephy_write(tp, 0x29, 0xFF04); - rtl8125_ephy_write(tp, 0x1B, 0x1EA0); - - rtl8125_ephy_write(tp, 0x46, 0x001F); - rtl8125_ephy_write(tp, 0x4A, 0xB66B); - rtl8125_ephy_write(tp, 0x41, 0xA84A); - rtl8125_ephy_write(tp, 0x64, 0x000C); - rtl8125_ephy_write(tp, 0x6F, 0x604A); - rtl8125_ephy_write(tp, 0x4D, 0xF716); - rtl8125_ephy_write(tp, 0x60, 0xD477); - rtl8125_ephy_write(tp, 0x61, 0x4477); - rtl8125_ephy_write(tp, 0x62, 0x0013); - rtl8125_ephy_write(tp, 0x63, 0xBB66); - rtl8125_ephy_write(tp, 0x4B, 0xA909); - rtl8125_ephy_write(tp, 0x69, 0xFF04); - rtl8125_ephy_write(tp, 0x5B, 0x1EA0); - break; - case CFG_METHOD_5: - rtl8125_ephy_write(tp, 0x0B, 0xA908); - rtl8125_ephy_write(tp, 0x22, 0x0023); - rtl8125_ephy_write(tp, 0x1E, 0x28EB); - - rtl8125_ephy_write(tp, 0x4B, 0xA908); - rtl8125_ephy_write(tp, 0x62, 0x0023); - rtl8125_ephy_write(tp, 0x5E, 0x28EB); - break; - } -} - -static u16 -rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp) -{ - u16 hw_ram_code_ver = ~0; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); - hw_ram_code_ver = mdio_direct_read_phy_ocp(tp, 0xA438); - break; - } - - return hw_ram_code_ver; -} - -static int -rtl8125_check_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ram_code_ver_match = 0; - - tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); - - if (tp->hw_ram_code_ver == tp->sw_ram_code_ver) { - ram_code_ver_match = 1; - tp->HwHasWrRamCodeToMicroP = TRUE; - } - - return ram_code_ver_match; -} - -bool -rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp) -{ - u16 gphy_val; - u16 WaitCount; - bool bSuccess = TRUE; - - SetEthPhyOcpBit(tp, 0xB820, BIT_4); - - WaitCount = 0; - do { - gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); - udelay(100); - WaitCount++; - } while (!(gphy_val & BIT_6) && (WaitCount < 1000)); - - if (!(gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; - - if (!bSuccess) - dprintk("rtl8125_set_phy_mcu_patch_request fail.\n"); - - return bSuccess; -} - -bool -rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp) -{ - u16 gphy_val; - u16 WaitCount; - bool bSuccess = TRUE; - - ClearEthPhyOcpBit(tp, 0xB820, BIT_4); - - WaitCount = 0; - do { - gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); - udelay(100); - WaitCount++; - } while ((gphy_val & BIT_6) && (WaitCount < 1000)); - - if ((gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; - - if (!bSuccess) - dprintk("rtl8125_clear_phy_mcu_patch_request fail.\n"); - - return bSuccess; -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8125_write_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); - mdio_direct_write_phy_ocp(tp, 0xA438, tp->sw_ram_code_ver); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - } -} - -static void -rtl8125_acquire_phy_mcu_patch_key_lock(struct rtl8125_private *tp) -{ - u16 PatchKey; - - switch (tp->mcfg) { - case CFG_METHOD_2: - PatchKey = 0x8600; - break; - case CFG_METHOD_3: - PatchKey = 0x8601; - break; - case CFG_METHOD_4: - PatchKey = 0x3700; - break; - case CFG_METHOD_5: - PatchKey = 0x3701; - break; - default: - return; - } - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, PatchKey); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xB82E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); -} - -static void -rtl8125_release_phy_mcu_patch_key_lock(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - ClearEthPhyOcpBit(tp, 0xB82E, BIT_0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - break; - default: - break; - } -} - -static void -rtl8125_set_phy_mcu_ram_code(struct net_device *dev, const u16 *ramcode, u16 codesize) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 i; - u16 addr; - u16 val; - - if (ramcode == NULL || codesize % 2) { - goto out; - } - - for (i = 0; i < codesize; i += 2) { - addr = ramcode[i]; - val = ramcode[i + 1]; - if (addr == 0xFFFF && val == 0xFFFF) { - break; - } - mdio_direct_write_phy_ocp(tp, addr, val); - } - -out: - return; -} - -static void -rtl8125_enable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_5); - break; - } - - dprintk("enable phy disable mode.\n"); -} - -static void -rtl8125_disable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_5); - break; - } - - mdelay(1); - - dprintk("disable phy disable mode.\n"); -} - -static void -rtl8125_set_hw_phy_before_init_phy_mcu(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 PhyRegValue; - - switch (tp->mcfg) { - case CFG_METHOD_4: - mdio_direct_write_phy_ocp(tp, 0xBF86, 0x9000); - - SetEthPhyOcpBit(tp, 0xC402, BIT_10); - ClearEthPhyOcpBit(tp, 0xC402, BIT_10); - - PhyRegValue = mdio_direct_read_phy_ocp(tp, 0xBF86); - PhyRegValue &= (BIT_1 | BIT_0); - if (PhyRegValue != 0) - dprintk("PHY watch dog not clear, value = 0x%x \n", PhyRegValue); - - mdio_direct_write_phy_ocp(tp, 0xBD86, 0x1010); - mdio_direct_write_phy_ocp(tp, 0xBD88, 0x1010); - - ClearAndSetEthPhyOcpBit(tp, - 0xBD4E, - BIT_11 | BIT_10, - BIT_11); - ClearAndSetEthPhyOcpBit(tp, - 0xBF46, - BIT_11 | BIT_10 | BIT_9 | BIT_8, - BIT_10 | BIT_9 | BIT_8); - break; - } -} - -static void -rtl8125_real_set_phy_mcu_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_acquire_phy_mcu_patch_key_lock(tp); - - - SetEthPhyOcpBit(tp, 0xB820, BIT_7); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8021); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x802f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x803d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8042); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a50); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a6c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd019); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a84); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8970); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c07); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcf09); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd705); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xceff); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf0a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1213); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8401); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8580); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1253); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd181); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4018); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd706); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2c59); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x804d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc60f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc605); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10fd); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10f4); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1252); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1206); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a78); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a60); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a4f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3f00); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8066); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x807c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8089); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80b2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80c2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62db); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x655c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x653c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0346); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8208); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x609d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x607d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0221); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ce); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0169); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00a6); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000d); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x029f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x007f); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8017); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8029); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8054); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x805a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9430); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9480); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb408); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd120); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd057); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9906); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0567); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb94); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8406); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8dff); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0773); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4045); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07ec); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fa7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0481); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8220); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x078e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd150); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6121); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61a2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6223); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0537); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0642); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0686); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0788); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x047b); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x065c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0769); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0565); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x06f9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ff); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8593); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x85a5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfb0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86d7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xda02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdd02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfd0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86dd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf2f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2cac); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0286); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x65af); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x212b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x022c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86b6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf21); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cd1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8710); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8716); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x871f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x871c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8728); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8725); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbad); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x281c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4902); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2e02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4602); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4f02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf35); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7ff8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfaef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x69bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ec); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x96fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf8fa); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef69); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf802); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef96); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfefc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0420); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x53b5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb9b5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb03a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbac8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb13a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xba77); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2677); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2640); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x28bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa430); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2f71); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x20d9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2109); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x34e7); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000f); - - - ClearEthPhyOcpBit(tp, 0xB820, BIT_7); - - - rtl8125_release_phy_mcu_patch_key_lock(tp); -} - -static void -rtl8125_set_phy_mcu_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125a_1(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_real_set_phy_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_acquire_phy_mcu_patch_key_lock(tp); - - - SetEthPhyOcpBit(tp, 0xB820, BIT_7); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8093); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8097); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x809d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80aa); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x607b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x42da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x615b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa410); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4779); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa420); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4559); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf023); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac44); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa440); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4339); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac88); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa480); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4119); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf001); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fac); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc48f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x141b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x121a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0898); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd18a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa804); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8804); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x053b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0648); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc520); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa201); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x252d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd708); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0307); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1645); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0647); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x053a); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0896); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xff00); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8015); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xad02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02d7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ed); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x008f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x008d); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00eb); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8018); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8055); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8072); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa380); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4085); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd158); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd04d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8380); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd10d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa220); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd130); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbb80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd074); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x604b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa90c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd116); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd119); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6241); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x63e2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6583); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf054); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d50); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf021); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d60); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d70); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ff4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07fb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f6f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f4e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f2d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1f5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd049); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ec); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ea); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x06a9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x078a); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d2); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x067f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0665); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00fc); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x45af); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xee82); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf900); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf03); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7f8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa601); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x58f0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x37a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae16); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa185); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa188); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8902); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03b3); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); - - - ClearEthPhyOcpBit(tp, 0xB820, BIT_7); - - - rtl8125_release_phy_mcu_patch_key_lock(tp); -} - -static void -rtl8125_set_phy_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125a_2(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static const u16 phy_mcu_ram_code_8125b_1[] = { - 0xa436, 0x8024, 0xa438, 0x3700, 0xa436, 0xB82E, 0xa438, 0x0001, - 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x8025, 0xa438, 0x1800, 0xa438, 0x803a, - 0xa438, 0x1800, 0xa438, 0x8044, 0xa438, 0x1800, 0xa438, 0x8083, - 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0x1800, 0xa438, 0x808d, - 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0xd712, 0xa438, 0x4077, - 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, 0xa438, 0x6099, - 0xa438, 0x7f44, 0xa438, 0x1800, 0xa438, 0x1a14, 0xa438, 0x9040, - 0xa438, 0x9201, 0xa438, 0x1800, 0xa438, 0x1b1a, 0xa438, 0xd71e, - 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, 0xa438, 0x3ce5, - 0xa438, 0x1afb, 0xa438, 0x1800, 0xa438, 0x1b00, 0xa438, 0xd712, - 0xa438, 0x4077, 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, - 0xa438, 0x60b9, 0xa438, 0x2421, 0xa438, 0x1c17, 0xa438, 0x1800, - 0xa438, 0x1a14, 0xa438, 0x9040, 0xa438, 0x1800, 0xa438, 0x1c2c, - 0xa438, 0xd71e, 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, - 0xa438, 0x3ce5, 0xa438, 0x1c0f, 0xa438, 0x1800, 0xa438, 0x1c13, - 0xa438, 0xd702, 0xa438, 0xd501, 0xa438, 0x6072, 0xa438, 0x8401, - 0xa438, 0xf002, 0xa438, 0xa401, 0xa438, 0x1000, 0xa438, 0x146e, - 0xa438, 0x1800, 0xa438, 0x0b77, 0xa438, 0xd703, 0xa438, 0x665d, - 0xa438, 0x653e, 0xa438, 0x641f, 0xa438, 0xd700, 0xa438, 0x62c4, - 0xa438, 0x6185, 0xa438, 0x6066, 0xa438, 0x1800, 0xa438, 0x165a, - 0xa438, 0xc101, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, - 0xa438, 0xd700, 0xa438, 0x7fa6, 0xa438, 0x1800, 0xa438, 0x807d, - 0xa438, 0xc102, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, - 0xa438, 0xd700, 0xa438, 0x2569, 0xa438, 0x8058, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc104, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd700, 0xa438, 0x7fa4, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc120, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbf, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc140, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbe, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc180, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbd, 0xa438, 0xc100, - 0xa438, 0xcb00, 0xa438, 0xd708, 0xa438, 0x6018, 0xa438, 0x1800, - 0xa438, 0x165a, 0xa438, 0x1000, 0xa438, 0x14f6, 0xa438, 0xd014, - 0xa438, 0xd1e3, 0xa438, 0x1000, 0xa438, 0x1356, 0xa438, 0xd705, - 0xa438, 0x5fbe, 0xa438, 0x1800, 0xa438, 0x1559, 0xa436, 0xA026, - 0xa438, 0xffff, 0xa436, 0xA024, 0xa438, 0xffff, 0xa436, 0xA022, - 0xa438, 0xffff, 0xa436, 0xA020, 0xa438, 0x1557, 0xa436, 0xA006, - 0xa438, 0x1677, 0xa436, 0xA004, 0xa438, 0x0b75, 0xa436, 0xA002, - 0xa438, 0x1c17, 0xa436, 0xA000, 0xa438, 0x1b04, 0xa436, 0xA008, - 0xa438, 0x1f00, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x817f, 0xa438, 0x1800, 0xa438, 0x82ab, - 0xa438, 0x1800, 0xa438, 0x83f8, 0xa438, 0x1800, 0xa438, 0x8444, - 0xa438, 0x1800, 0xa438, 0x8454, 0xa438, 0x1800, 0xa438, 0x8459, - 0xa438, 0x1800, 0xa438, 0x8465, 0xa438, 0xcb11, 0xa438, 0xa50c, - 0xa438, 0x8310, 0xa438, 0xd701, 0xa438, 0x4076, 0xa438, 0x0c03, - 0xa438, 0x0903, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x1000, 0xa438, 0x0a4d, - 0xa438, 0xcb12, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f84, 0xa438, 0xd102, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd701, - 0xa438, 0x60f3, 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd410, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb13, - 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, - 0xa438, 0xa00a, 0xa438, 0xa910, 0xa438, 0xa780, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x6255, 0xa438, 0xd700, 0xa438, 0x5f74, 0xa438, 0x6326, - 0xa438, 0xd702, 0xa438, 0x5f07, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0xffe2, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5fab, 0xa438, 0xba08, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8b, 0xa438, 0x9a08, - 0xa438, 0x800a, 0xa438, 0xd702, 0xa438, 0x6535, 0xa438, 0xd40d, - 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb14, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa00a, - 0xa438, 0xa780, 0xa438, 0xd14a, 0xa438, 0xd048, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x6206, - 0xa438, 0xd702, 0xa438, 0x5f47, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0x1800, 0xa438, 0x8064, 0xa438, 0x800a, - 0xa438, 0xd40e, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xd701, 0xa438, 0x6073, 0xa438, 0xd701, - 0xa438, 0x4216, 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8004, 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8001, 0xa438, 0xd120, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x8504, - 0xa438, 0xcb21, 0xa438, 0xa301, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, 0xa438, 0xd704, - 0xa438, 0x40e0, 0xa438, 0xd196, 0xa438, 0xd04d, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb22, - 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, - 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8910, 0xa438, 0x8720, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb23, - 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, - 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x5dee, 0xa438, 0xcb24, 0xa438, 0x8f1f, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f6e, 0xa438, 0xa111, - 0xa438, 0xa215, 0xa438, 0xa401, 0xa438, 0x8404, 0xa438, 0xa720, - 0xa438, 0xcb25, 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, - 0xa438, 0x9503, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, - 0xa438, 0x0b86, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xcb26, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x8205, - 0xa438, 0x8404, 0xa438, 0xcb27, 0xa438, 0xd404, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0xa104, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8104, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa120, - 0xa438, 0xaa0f, 0xa438, 0x8110, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0xa00a, 0xa438, 0xd193, 0xa438, 0xd046, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb28, - 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa8, 0xa438, 0x8110, 0xa438, 0x8284, 0xa438, 0xa404, - 0xa438, 0x800a, 0xa438, 0x8710, 0xa438, 0xb804, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, - 0xa438, 0xcb29, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, - 0xa438, 0xcb2a, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0xa00a, 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8149, - 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8151, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, - 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, - 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8404, - 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, - 0xa438, 0x0433, 0xa438, 0xcb15, 0xa438, 0xa508, 0xa438, 0xd700, - 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, - 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, - 0xa438, 0x1000, 0xa438, 0x0a4d, 0xa438, 0xa301, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, - 0xa438, 0xd704, 0xa438, 0x40e0, 0xa438, 0xd115, 0xa438, 0xd04f, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb16, - 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, - 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8720, 0xa438, 0xd17a, - 0xa438, 0xd04c, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb17, - 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, - 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x61ce, 0xa438, 0xd700, 0xa438, 0x5db4, 0xa438, 0xcb18, - 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, - 0xa438, 0xa720, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xffd6, 0xa438, 0x8f1f, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f8e, 0xa438, 0xa131, - 0xa438, 0xaa0f, 0xa438, 0xa2d5, 0xa438, 0xa407, 0xa438, 0xa720, - 0xa438, 0x8310, 0xa438, 0xa308, 0xa438, 0x8308, 0xa438, 0xcb19, - 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, - 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, 0xa438, 0x0b86, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, - 0xa438, 0xcb1a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x82c5, 0xa438, 0xa404, - 0xa438, 0x8402, 0xa438, 0xb804, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, 0xa438, 0xcb1b, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f85, - 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, 0xa438, 0xcb1c, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0xa110, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0x8402, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa8, 0xa438, 0xcb1d, 0xa438, 0xa180, 0xa438, 0xa402, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, - 0xa438, 0xa220, 0xa438, 0xd1f5, 0xa438, 0xd049, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8221, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xb920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fa3, - 0xa438, 0xa504, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa00a, 0xa438, 0x8190, - 0xa438, 0x82a4, 0xa438, 0x8402, 0xa438, 0xa404, 0xa438, 0xb808, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7fa3, - 0xa438, 0x9808, 0xa438, 0xcb2b, 0xa438, 0xcb2c, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f84, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0xa780, 0xa438, 0xcb2d, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f94, 0xa438, 0x6208, - 0xa438, 0xd702, 0xa438, 0x5f27, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xffe9, 0xa438, 0xcb2e, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa406, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, - 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x827d, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, - 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, - 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8406, - 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, - 0xa438, 0x0433, 0xa438, 0xcb30, 0xa438, 0x8380, 0xa438, 0xcb31, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f86, - 0xa438, 0x9308, 0xa438, 0xb204, 0xa438, 0xb301, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x5fa2, 0xa438, 0xb302, - 0xa438, 0x9204, 0xa438, 0xcb32, 0xa438, 0xd408, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd141, 0xa438, 0xd043, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd704, - 0xa438, 0x4ccc, 0xa438, 0xd700, 0xa438, 0x4c81, 0xa438, 0xd702, - 0xa438, 0x609e, 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0xf003, - 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, - 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, 0xa438, 0x0c1f, - 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x8710, - 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, - 0xa438, 0xa203, 0xa438, 0x8120, 0xa438, 0x8a0f, 0xa438, 0xa111, - 0xa438, 0x8204, 0xa438, 0xa140, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8140, 0xa438, 0xd17a, 0xa438, 0xd04b, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xa204, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, - 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0xd404, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0x8101, - 0xa438, 0x8201, 0xa438, 0xa104, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8104, 0xa438, 0xa120, 0xa438, 0xaa0f, 0xa438, 0x8110, - 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0xa00a, 0xa438, 0xd193, - 0xa438, 0xd047, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fa8, 0xa438, 0xa180, 0xa438, 0xd13d, - 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xf024, 0xa438, 0xa710, 0xa438, 0xa00a, - 0xa438, 0x8190, 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, - 0xa438, 0x8710, 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0x800a, - 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0x8406, 0xa438, 0xd700, - 0xa438, 0x4121, 0xa438, 0xd701, 0xa438, 0x60f3, 0xa438, 0xd1e5, - 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x8710, 0xa438, 0xa00a, 0xa438, 0x8190, - 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xcb33, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, - 0xa438, 0x9820, 0xa438, 0xcb34, 0xa438, 0xa00a, 0xa438, 0xa190, - 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fa9, 0xa438, 0xd701, 0xa438, 0x6853, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0xcb35, - 0xa438, 0xd407, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8110, - 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa00a, 0xa438, 0xd704, - 0xa438, 0x4215, 0xa438, 0xa304, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb8, 0xa438, 0xd1c3, 0xa438, 0xd043, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x8304, 0xa438, 0xd700, 0xa438, 0x4109, 0xa438, 0xf01e, - 0xa438, 0xcb36, 0xa438, 0xd412, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd700, 0xa438, 0x6309, 0xa438, 0xd702, 0xa438, 0x42c7, - 0xa438, 0x800a, 0xa438, 0x8180, 0xa438, 0x8280, 0xa438, 0x8404, - 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, - 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, - 0xa438, 0x0c03, 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xcc55, 0xa438, 0xcb37, - 0xa438, 0xa00a, 0xa438, 0xa190, 0xa438, 0xa2a4, 0xa438, 0xa404, - 0xa438, 0xd700, 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd13d, - 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa9, 0xa438, 0xd702, 0xa438, 0x5f71, 0xa438, 0xcb38, - 0xa438, 0x8224, 0xa438, 0xa288, 0xa438, 0x8180, 0xa438, 0xa110, - 0xa438, 0xa404, 0xa438, 0x800a, 0xa438, 0xd700, 0xa438, 0x6041, - 0xa438, 0x8402, 0xa438, 0xd415, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb39, 0xa438, 0xa00a, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xd700, - 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd17a, 0xa438, 0xd047, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x1800, 0xa438, 0x0560, 0xa438, 0xa111, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0xd3f5, - 0xa438, 0xd219, 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, - 0xa438, 0x5fa5, 0xa438, 0xa215, 0xa438, 0xd30e, 0xa438, 0xd21a, - 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x63e9, - 0xa438, 0xd708, 0xa438, 0x5f65, 0xa438, 0xd708, 0xa438, 0x7f36, - 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8004, - 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8001, - 0xa438, 0xd708, 0xa438, 0x4098, 0xa438, 0xd102, 0xa438, 0x9401, - 0xa438, 0xf003, 0xa438, 0xd103, 0xa438, 0xb401, 0xa438, 0x1000, - 0xa438, 0x0c27, 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0c35, - 0xa438, 0x8108, 0xa438, 0x8110, 0xa438, 0x8294, 0xa438, 0xa202, - 0xa438, 0x1800, 0xa438, 0x0bdb, 0xa438, 0xd39c, 0xa438, 0xd210, - 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x5fa5, - 0xa438, 0xd39c, 0xa438, 0xd210, 0xa438, 0x1000, 0xa438, 0x0c31, - 0xa438, 0xd708, 0xa438, 0x5fa5, 0xa438, 0x1000, 0xa438, 0x0c31, - 0xa438, 0xd708, 0xa438, 0x29b5, 0xa438, 0x840e, 0xa438, 0xd708, - 0xa438, 0x5f4a, 0xa438, 0x0c1f, 0xa438, 0x1014, 0xa438, 0x1000, - 0xa438, 0x0c31, 0xa438, 0xd709, 0xa438, 0x7fa4, 0xa438, 0x901f, - 0xa438, 0x1800, 0xa438, 0x0c23, 0xa438, 0xcb43, 0xa438, 0xa508, - 0xa438, 0xd701, 0xa438, 0x3699, 0xa438, 0x844a, 0xa438, 0xa504, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xa00a, - 0xa438, 0xd700, 0xa438, 0x2109, 0xa438, 0x05ea, 0xa438, 0xa402, - 0xa438, 0x1800, 0xa438, 0x05ea, 0xa438, 0xcb90, 0xa438, 0x0cf0, - 0xa438, 0x0ca0, 0xa438, 0x1800, 0xa438, 0x06db, 0xa438, 0xd1ff, - 0xa438, 0xd052, 0xa438, 0xa508, 0xa438, 0x8718, 0xa438, 0xa00a, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0x0cf0, - 0xa438, 0x0c50, 0xa438, 0x1800, 0xa438, 0x09ef, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd704, 0xa438, 0x2e70, 0xa438, 0x06da, - 0xa438, 0xd700, 0xa438, 0x5f55, 0xa438, 0xa90c, 0xa438, 0x1800, - 0xa438, 0x0645, 0xa436, 0xA10E, 0xa438, 0x0644, 0xa436, 0xA10C, - 0xa438, 0x09e9, 0xa436, 0xA10A, 0xa438, 0x06da, 0xa436, 0xA108, - 0xa438, 0x05e1, 0xa436, 0xA106, 0xa438, 0x0be4, 0xa436, 0xA104, - 0xa438, 0x0435, 0xa436, 0xA102, 0xa438, 0x0141, 0xa436, 0xA100, - 0xa438, 0x026d, 0xa436, 0xA110, 0xa438, 0x00ff, 0xa436, 0xb87c, - 0xa438, 0x85fe, 0xa436, 0xb87e, 0xa438, 0xaf86, 0xa438, 0x16af, - 0xa438, 0x8699, 0xa438, 0xaf86, 0xa438, 0xe5af, 0xa438, 0x86f9, - 0xa438, 0xaf87, 0xa438, 0x7aaf, 0xa438, 0x883a, 0xa438, 0xaf88, - 0xa438, 0x58af, 0xa438, 0x8b6c, 0xa438, 0xd48b, 0xa438, 0x7c02, - 0xa438, 0x8644, 0xa438, 0x2c00, 0xa438, 0x503c, 0xa438, 0xffd6, - 0xa438, 0xac27, 0xa438, 0x18e1, 0xa438, 0x82fe, 0xa438, 0xad28, - 0xa438, 0x0cd4, 0xa438, 0x8b84, 0xa438, 0x0286, 0xa438, 0x442c, - 0xa438, 0x003c, 0xa438, 0xac27, 0xa438, 0x06ee, 0xa438, 0x8299, - 0xa438, 0x01ae, 0xa438, 0x04ee, 0xa438, 0x8299, 0xa438, 0x00af, - 0xa438, 0x23dc, 0xa438, 0xf9fa, 0xa438, 0xcefa, 0xa438, 0xfbef, - 0xa438, 0x79fb, 0xa438, 0xc4bf, 0xa438, 0x8b76, 0xa438, 0x026c, - 0xa438, 0x6dac, 0xa438, 0x2804, 0xa438, 0xd203, 0xa438, 0xae02, - 0xa438, 0xd201, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, - 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x648a, - 0xa438, 0x0002, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, - 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x7402, - 0xa438, 0x72cd, 0xa438, 0xac50, 0xa438, 0x02ef, 0xa438, 0x643a, - 0xa438, 0x019f, 0xa438, 0xe4ef, 0xa438, 0x4678, 0xa438, 0x03ac, - 0xa438, 0x2002, 0xa438, 0xae02, 0xa438, 0xd0ff, 0xa438, 0xffef, - 0xa438, 0x97ff, 0xa438, 0xfec6, 0xa438, 0xfefd, 0xa438, 0x041f, - 0xa438, 0x771f, 0xa438, 0x221c, 0xa438, 0x450d, 0xa438, 0x481f, - 0xa438, 0x00ac, 0xa438, 0x7f04, 0xa438, 0x1a94, 0xa438, 0xae08, - 0xa438, 0x1a94, 0xa438, 0xac7f, 0xa438, 0x03d7, 0xa438, 0x0100, - 0xa438, 0xef46, 0xa438, 0x0d48, 0xa438, 0x1f00, 0xa438, 0x1c45, - 0xa438, 0xef69, 0xa438, 0xef57, 0xa438, 0xef74, 0xa438, 0x0272, - 0xa438, 0xe8a7, 0xa438, 0xffff, 0xa438, 0x0d1a, 0xa438, 0x941b, - 0xa438, 0x979e, 0xa438, 0x072d, 0xa438, 0x0100, 0xa438, 0x1a64, - 0xa438, 0xef76, 0xa438, 0xef97, 0xa438, 0x0d98, 0xa438, 0xd400, - 0xa438, 0xff1d, 0xa438, 0x941a, 0xa438, 0x89cf, 0xa438, 0x1a75, - 0xa438, 0xaf74, 0xa438, 0xf9bf, 0xa438, 0x8b79, 0xa438, 0x026c, - 0xa438, 0x6da1, 0xa438, 0x0005, 0xa438, 0xe180, 0xa438, 0xa0ae, - 0xa438, 0x03e1, 0xa438, 0x80a1, 0xa438, 0xaf26, 0xa438, 0x9aac, - 0xa438, 0x284d, 0xa438, 0xe08f, 0xa438, 0xffef, 0xa438, 0x10c0, - 0xa438, 0xe08f, 0xa438, 0xfe10, 0xa438, 0x1b08, 0xa438, 0xa000, - 0xa438, 0x04c8, 0xa438, 0xaf40, 0xa438, 0x67c8, 0xa438, 0xbf8b, - 0xa438, 0x8c02, 0xa438, 0x6c4e, 0xa438, 0xc4bf, 0xa438, 0x8b8f, - 0xa438, 0x026c, 0xa438, 0x6def, 0xa438, 0x74e0, 0xa438, 0x830c, - 0xa438, 0xad20, 0xa438, 0x0302, 0xa438, 0x74ac, 0xa438, 0xccef, - 0xa438, 0x971b, 0xa438, 0x76ad, 0xa438, 0x5f02, 0xa438, 0xae13, - 0xa438, 0xef69, 0xa438, 0xef30, 0xa438, 0x1b32, 0xa438, 0xc4ef, - 0xa438, 0x46e4, 0xa438, 0x8ffb, 0xa438, 0xe58f, 0xa438, 0xfce7, - 0xa438, 0x8ffd, 0xa438, 0xcc10, 0xa438, 0x11ae, 0xa438, 0xb8d1, - 0xa438, 0x00a1, 0xa438, 0x1f03, 0xa438, 0xaf40, 0xa438, 0x4fbf, - 0xa438, 0x8b8c, 0xa438, 0x026c, 0xa438, 0x4ec4, 0xa438, 0xbf8b, - 0xa438, 0x8f02, 0xa438, 0x6c6d, 0xa438, 0xef74, 0xa438, 0xe083, - 0xa438, 0x0cad, 0xa438, 0x2003, 0xa438, 0x0274, 0xa438, 0xaccc, - 0xa438, 0xef97, 0xa438, 0x1b76, 0xa438, 0xad5f, 0xa438, 0x02ae, - 0xa438, 0x04ef, 0xa438, 0x69ef, 0xa438, 0x3111, 0xa438, 0xaed1, - 0xa438, 0x0287, 0xa438, 0x80af, 0xa438, 0x2293, 0xa438, 0xf8f9, - 0xa438, 0xfafb, 0xa438, 0xef59, 0xa438, 0xe080, 0xa438, 0x13ad, - 0xa438, 0x252f, 0xa438, 0xbf88, 0xa438, 0x2802, 0xa438, 0x6c6d, - 0xa438, 0xef64, 0xa438, 0x1f44, 0xa438, 0xe18f, 0xa438, 0xb91b, - 0xa438, 0x64ad, 0xa438, 0x4f1d, 0xa438, 0xd688, 0xa438, 0x2bd7, - 0xa438, 0x882e, 0xa438, 0x0274, 0xa438, 0x73ad, 0xa438, 0x5008, - 0xa438, 0xbf88, 0xa438, 0x3102, 0xa438, 0x737c, 0xa438, 0xae03, - 0xa438, 0x0287, 0xa438, 0xd0bf, 0xa438, 0x882b, 0xa438, 0x0273, - 0xa438, 0x73e0, 0xa438, 0x824c, 0xa438, 0xf621, 0xa438, 0xe482, - 0xa438, 0x4cbf, 0xa438, 0x8834, 0xa438, 0x0273, 0xa438, 0x7cef, - 0xa438, 0x95ff, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, - 0xa438, 0xfafb, 0xa438, 0xef79, 0xa438, 0xbf88, 0xa438, 0x1f02, - 0xa438, 0x737c, 0xa438, 0x1f22, 0xa438, 0xac32, 0xa438, 0x31ef, - 0xa438, 0x12bf, 0xa438, 0x8822, 0xa438, 0x026c, 0xa438, 0x4ed6, - 0xa438, 0x8fba, 0xa438, 0x1f33, 0xa438, 0xac3c, 0xa438, 0x1eef, - 0xa438, 0x13bf, 0xa438, 0x8837, 0xa438, 0x026c, 0xa438, 0x4eef, - 0xa438, 0x96d8, 0xa438, 0x19d9, 0xa438, 0xbf88, 0xa438, 0x2502, - 0xa438, 0x6c4e, 0xa438, 0xbf88, 0xa438, 0x2502, 0xa438, 0x6c4e, - 0xa438, 0x1616, 0xa438, 0x13ae, 0xa438, 0xdf12, 0xa438, 0xaecc, - 0xa438, 0xbf88, 0xa438, 0x1f02, 0xa438, 0x7373, 0xa438, 0xef97, - 0xa438, 0xfffe, 0xa438, 0xfdfc, 0xa438, 0x0466, 0xa438, 0xac88, - 0xa438, 0x54ac, 0xa438, 0x88f0, 0xa438, 0xac8a, 0xa438, 0x92ac, - 0xa438, 0xbadd, 0xa438, 0xac6c, 0xa438, 0xeeac, 0xa438, 0x6cff, - 0xa438, 0xad02, 0xa438, 0x99ac, 0xa438, 0x0030, 0xa438, 0xac88, - 0xa438, 0xd4c3, 0xa438, 0x5000, 0xa438, 0x0000, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x00b4, 0xa438, 0xecee, - 0xa438, 0x8298, 0xa438, 0x00af, 0xa438, 0x1412, 0xa438, 0xf8bf, - 0xa438, 0x8b5d, 0xa438, 0x026c, 0xa438, 0x6d58, 0xa438, 0x03e1, - 0xa438, 0x8fb8, 0xa438, 0x2901, 0xa438, 0xe58f, 0xa438, 0xb8a0, - 0xa438, 0x0049, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x02e5, - 0xa438, 0x8303, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, - 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, - 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, - 0xa438, 0xf728, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0xf628, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6002, - 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, - 0xa438, 0xaf89, 0xa438, 0x96a0, 0xa438, 0x0149, 0xa438, 0xef47, - 0xa438, 0xe483, 0xa438, 0x04e5, 0xa438, 0x8305, 0xa438, 0xbfc2, - 0xa438, 0x5f1a, 0xa438, 0x95f7, 0xa438, 0x05ee, 0xa438, 0xffd2, - 0xa438, 0x00d8, 0xa438, 0xf605, 0xa438, 0x1f11, 0xa438, 0xef60, - 0xa438, 0xbf8b, 0xa438, 0x3002, 0xa438, 0x6c4e, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c6d, 0xa438, 0xf729, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0xf629, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0x0c64, 0xa438, 0xef46, - 0xa438, 0xbf8b, 0xa438, 0x6302, 0xa438, 0x6c4e, 0xa438, 0x0289, - 0xa438, 0x9902, 0xa438, 0x3920, 0xa438, 0xaf89, 0xa438, 0x96a0, - 0xa438, 0x0249, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x06e5, - 0xa438, 0x8307, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, - 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, - 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, - 0xa438, 0xf72a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0xf62a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6602, - 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, - 0xa438, 0xaf89, 0xa438, 0x96ef, 0xa438, 0x47e4, 0xa438, 0x8308, - 0xa438, 0xe583, 0xa438, 0x09bf, 0xa438, 0xc25f, 0xa438, 0x1a95, - 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xd8f6, - 0xa438, 0x051f, 0xa438, 0x11ef, 0xa438, 0x60bf, 0xa438, 0x8b30, - 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x6df7, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x4ef6, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x4e0c, 0xa438, 0x64ef, 0xa438, 0x46bf, 0xa438, 0x8b69, - 0xa438, 0x026c, 0xa438, 0x4e02, 0xa438, 0x8999, 0xa438, 0x0239, - 0xa438, 0x20af, 0xa438, 0x8996, 0xa438, 0xaf39, 0xa438, 0x1ef8, - 0xa438, 0xf9fa, 0xa438, 0xe08f, 0xa438, 0xb838, 0xa438, 0x02ad, - 0xa438, 0x2702, 0xa438, 0xae03, 0xa438, 0xaf8b, 0xa438, 0x201f, - 0xa438, 0x66ef, 0xa438, 0x65bf, 0xa438, 0xc21f, 0xa438, 0x1a96, - 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdaf6, - 0xa438, 0x05bf, 0xa438, 0xc22f, 0xa438, 0x1a96, 0xa438, 0xf705, - 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdbf6, 0xa438, 0x05ef, - 0xa438, 0x021f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b3c, - 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021b, 0xa438, 0x031f, - 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b36, 0xa438, 0x026c, - 0xa438, 0x4eef, 0xa438, 0x021a, 0xa438, 0x031f, 0xa438, 0x110d, - 0xa438, 0x42bf, 0xa438, 0x8b39, 0xa438, 0x026c, 0xa438, 0x4ebf, - 0xa438, 0xc23f, 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, - 0xa438, 0xd200, 0xa438, 0xdaf6, 0xa438, 0x05bf, 0xa438, 0xc24f, - 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, - 0xa438, 0xdbf6, 0xa438, 0x05ef, 0xa438, 0x021f, 0xa438, 0x110d, - 0xa438, 0x42bf, 0xa438, 0x8b45, 0xa438, 0x026c, 0xa438, 0x4eef, - 0xa438, 0x021b, 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, - 0xa438, 0x8b3f, 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021a, - 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b42, - 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x56d0, 0xa438, 0x201f, - 0xa438, 0x11bf, 0xa438, 0x8b4e, 0xa438, 0x026c, 0xa438, 0x4ebf, - 0xa438, 0x8b48, 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b4b, - 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8578, 0xa438, 0xef03, - 0xa438, 0x480a, 0xa438, 0x2805, 0xa438, 0xef20, 0xa438, 0x1b01, - 0xa438, 0xad27, 0xa438, 0x3f1f, 0xa438, 0x44e0, 0xa438, 0x8560, - 0xa438, 0xe185, 0xa438, 0x61bf, 0xa438, 0x8b51, 0xa438, 0x026c, - 0xa438, 0x4ee0, 0xa438, 0x8566, 0xa438, 0xe185, 0xa438, 0x67bf, - 0xa438, 0x8b54, 0xa438, 0x026c, 0xa438, 0x4ee0, 0xa438, 0x856c, - 0xa438, 0xe185, 0xa438, 0x6dbf, 0xa438, 0x8b57, 0xa438, 0x026c, - 0xa438, 0x4ee0, 0xa438, 0x8572, 0xa438, 0xe185, 0xa438, 0x73bf, - 0xa438, 0x8b5a, 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8fb8, - 0xa438, 0x5900, 0xa438, 0xf728, 0xa438, 0xe58f, 0xa438, 0xb8af, - 0xa438, 0x8b2c, 0xa438, 0xe185, 0xa438, 0x791b, 0xa438, 0x21ad, - 0xa438, 0x373e, 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x62e1, - 0xa438, 0x8563, 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, - 0xa438, 0xe085, 0xa438, 0x68e1, 0xa438, 0x8569, 0xa438, 0xbf8b, - 0xa438, 0x5402, 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x6ee1, - 0xa438, 0x856f, 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, - 0xa438, 0xe085, 0xa438, 0x74e1, 0xa438, 0x8575, 0xa438, 0xbf8b, - 0xa438, 0x5a02, 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, - 0xa438, 0x00f7, 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae4a, - 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x64e1, 0xa438, 0x8565, - 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, 0xa438, 0xe085, - 0xa438, 0x6ae1, 0xa438, 0x856b, 0xa438, 0xbf8b, 0xa438, 0x5402, - 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x70e1, 0xa438, 0x8571, - 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, 0xa438, 0xe085, - 0xa438, 0x76e1, 0xa438, 0x8577, 0xa438, 0xbf8b, 0xa438, 0x5a02, - 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, 0xa438, 0x00f7, - 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae0c, 0xa438, 0xe18f, - 0xa438, 0xb839, 0xa438, 0x04ac, 0xa438, 0x2f04, 0xa438, 0xee8f, - 0xa438, 0xb800, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf0ac, - 0xa438, 0x8efc, 0xa438, 0xac8c, 0xa438, 0xf0ac, 0xa438, 0xfaf0, - 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xf6f0, 0xa438, 0xad00, - 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacfc, 0xa438, 0xf0ac, - 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, 0xa438, 0xf0f0, - 0xa438, 0xacb0, 0xa438, 0xf0ac, 0xa438, 0xaef0, 0xa438, 0xacac, - 0xa438, 0xf0ac, 0xa438, 0xaaf0, 0xa438, 0xacee, 0xa438, 0xf0b0, - 0xa438, 0x24f0, 0xa438, 0xb0a4, 0xa438, 0xf0b1, 0xa438, 0x24f0, - 0xa438, 0xb1a4, 0xa438, 0xee8f, 0xa438, 0xb800, 0xa438, 0xd400, - 0xa438, 0x00af, 0xa438, 0x3976, 0xa438, 0x66ac, 0xa438, 0xeabb, - 0xa438, 0xa430, 0xa438, 0x6e50, 0xa438, 0x6e53, 0xa438, 0x6e56, - 0xa438, 0x6e59, 0xa438, 0x6e5c, 0xa438, 0x6e5f, 0xa438, 0x6e62, - 0xa438, 0x6e65, 0xa438, 0xd9ac, 0xa438, 0x70f0, 0xa438, 0xac6a, - 0xa436, 0xb85e, 0xa438, 0x23b7, 0xa436, 0xb860, 0xa438, 0x74db, - 0xa436, 0xb862, 0xa438, 0x268c, 0xa436, 0xb864, 0xa438, 0x3FE5, - 0xa436, 0xb886, 0xa438, 0x2250, 0xa436, 0xb888, 0xa438, 0x140e, - 0xa436, 0xb88a, 0xa438, 0x3696, 0xa436, 0xb88c, 0xa438, 0x3973, - 0xa436, 0xb838, 0xa438, 0x00ff, 0xb820, 0x0010, 0xa436, 0x8464, - 0xa438, 0xaf84, 0xa438, 0x7caf, 0xa438, 0x8485, 0xa438, 0xaf85, - 0xa438, 0x13af, 0xa438, 0x851e, 0xa438, 0xaf85, 0xa438, 0xb9af, - 0xa438, 0x8684, 0xa438, 0xaf87, 0xa438, 0x01af, 0xa438, 0x8701, - 0xa438, 0xac38, 0xa438, 0x03af, 0xa438, 0x38bb, 0xa438, 0xaf38, - 0xa438, 0xc302, 0xa438, 0x4618, 0xa438, 0xbf85, 0xa438, 0x0a02, - 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x1002, 0xa438, 0x54c0, - 0xa438, 0xd400, 0xa438, 0x0fbf, 0xa438, 0x8507, 0xa438, 0x024f, - 0xa438, 0x48bf, 0xa438, 0x8504, 0xa438, 0x024f, 0xa438, 0x6759, - 0xa438, 0xf0a1, 0xa438, 0x3008, 0xa438, 0xbf85, 0xa438, 0x0d02, - 0xa438, 0x54c0, 0xa438, 0xae06, 0xa438, 0xbf85, 0xa438, 0x0d02, - 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x0402, 0xa438, 0x4f67, - 0xa438, 0xa183, 0xa438, 0x02ae, 0xa438, 0x15a1, 0xa438, 0x8502, - 0xa438, 0xae10, 0xa438, 0x59f0, 0xa438, 0xa180, 0xa438, 0x16bf, - 0xa438, 0x8501, 0xa438, 0x024f, 0xa438, 0x67a1, 0xa438, 0x381b, - 0xa438, 0xae0b, 0xa438, 0xe18f, 0xa438, 0xffbf, 0xa438, 0x84fe, - 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x17bf, 0xa438, 0x84fe, - 0xa438, 0x0254, 0xa438, 0xb7bf, 0xa438, 0x84fb, 0xa438, 0x0254, - 0xa438, 0xb7ae, 0xa438, 0x09a1, 0xa438, 0x5006, 0xa438, 0xbf84, - 0xa438, 0xfb02, 0xa438, 0x54c0, 0xa438, 0xaf04, 0xa438, 0x4700, - 0xa438, 0xad34, 0xa438, 0xfdad, 0xa438, 0x0670, 0xa438, 0xae14, - 0xa438, 0xf0a6, 0xa438, 0x00b8, 0xa438, 0xbd32, 0xa438, 0x30bd, - 0xa438, 0x30aa, 0xa438, 0xbd2c, 0xa438, 0xccbd, 0xa438, 0x2ca1, - 0xa438, 0x0705, 0xa438, 0xec80, 0xa438, 0xaf40, 0xa438, 0xf7af, - 0xa438, 0x40f5, 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, - 0xa438, 0x4f48, 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, - 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, - 0xa438, 0x024d, 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, - 0xa438, 0x67bf, 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, - 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, - 0xa438, 0x85b3, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, - 0xa438, 0xddbf, 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, - 0xa438, 0x8ffa, 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, - 0xa438, 0x024f, 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, - 0xa438, 0xad02, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, - 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, - 0xa438, 0xfcdd, 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, - 0xa438, 0xbf8f, 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, - 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, - 0xa438, 0xa702, 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0xa102, - 0xa438, 0x54b7, 0xa438, 0xaf3c, 0xa438, 0x2066, 0xa438, 0xb800, - 0xa438, 0xb8bd, 0xa438, 0x30ee, 0xa438, 0xbd2c, 0xa438, 0xb8bd, - 0xa438, 0x7040, 0xa438, 0xbd86, 0xa438, 0xc8bd, 0xa438, 0x8640, - 0xa438, 0xbd88, 0xa438, 0xc8bd, 0xa438, 0x8802, 0xa438, 0x1929, - 0xa438, 0xa202, 0xa438, 0x02ae, 0xa438, 0x03a2, 0xa438, 0x032e, - 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, - 0xa438, 0xe18f, 0xa438, 0xf7bf, 0xa438, 0x85ad, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ff8, 0xa438, 0xbf85, 0xa438, 0xb002, - 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x85b3, - 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ffa, 0xa438, 0xbf85, - 0xa438, 0xb602, 0xa438, 0x4f48, 0xa438, 0xae2c, 0xa438, 0xd100, - 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0xe18f, - 0xa438, 0xfbbf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x48e1, - 0xa438, 0x8ffc, 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f48, - 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x85b3, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ffe, 0xa438, 0xbf85, 0xa438, 0xb602, - 0xa438, 0x4f48, 0xa438, 0xbf86, 0xa438, 0x7e02, 0xa438, 0x4f67, - 0xa438, 0xa100, 0xa438, 0x02ae, 0xa438, 0x25a1, 0xa438, 0x041d, - 0xa438, 0xe18f, 0xa438, 0xf1bf, 0xa438, 0x8675, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ff2, 0xa438, 0xbf86, 0xa438, 0x7802, - 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf3bf, 0xa438, 0x867b, - 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x29a1, 0xa438, 0x070b, - 0xa438, 0xae24, 0xa438, 0xbf86, 0xa438, 0x8102, 0xa438, 0x4f67, - 0xa438, 0xad28, 0xa438, 0x1be1, 0xa438, 0x8ff4, 0xa438, 0xbf86, - 0xa438, 0x7502, 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf5bf, - 0xa438, 0x8678, 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ff6, - 0xa438, 0xbf86, 0xa438, 0x7b02, 0xa438, 0x4f48, 0xa438, 0xaf09, - 0xa438, 0x8420, 0xa438, 0xbc32, 0xa438, 0x20bc, 0xa438, 0x3e76, - 0xa438, 0xbc08, 0xa438, 0xfda6, 0xa438, 0x1a00, 0xa438, 0xb64e, - 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, 0xa438, 0x4f48, - 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, 0xa438, 0xd10f, - 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0x024d, - 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x67bf, - 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, 0xa438, 0x024f, - 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, 0xa438, 0x85b3, - 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, 0xa438, 0xddbf, - 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ffa, - 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, 0xa438, 0x024f, - 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, 0xa438, 0xad02, - 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, 0xa438, 0xbf85, - 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfcdd, - 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, 0xa438, 0xbf8f, - 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, 0xa438, 0x4f67, - 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, 0xa438, 0xa702, - 0xa438, 0x54b7, 0xa438, 0xaf00, 0xa438, 0x8800, 0xa436, 0xb818, - 0xa438, 0x38b8, 0xa436, 0xb81a, 0xa438, 0x0444, 0xa436, 0xb81c, - 0xa438, 0x40ee, 0xa436, 0xb81e, 0xa438, 0x3C1A, 0xa436, 0xb850, - 0xa438, 0x0981, 0xa436, 0xb852, 0xa438, 0x0085, 0xa436, 0xb878, - 0xa438, 0xffff, 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, - 0xa438, 0x003f, 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, - 0xa438, 0x0000, 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, - 0xa436, 0x801E, 0xa438, 0x0021, 0xFFFF, 0xFFFF -}; - -static const u16 phy_mcu_ram_code_8125b_2[] = { - 0xa436, 0x8024, 0xa438, 0x3701, 0xa436, 0xB82E, 0xa438, 0x0001, - 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x801a, 0xa438, 0x1800, 0xa438, 0x803f, - 0xa438, 0x1800, 0xa438, 0x8045, 0xa438, 0x1800, 0xa438, 0x8067, - 0xa438, 0x1800, 0xa438, 0x806d, 0xa438, 0x1800, 0xa438, 0x8079, - 0xa438, 0x1800, 0xa438, 0x807e, 0xa438, 0xd093, 0xa438, 0xd1c4, - 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd704, 0xa438, 0x5fbc, - 0xa438, 0xd504, 0xa438, 0xc9f1, 0xa438, 0x1800, 0xa438, 0x0fc9, - 0xa438, 0xbb50, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd504, - 0xa438, 0x8c0f, 0xa438, 0xd500, 0xa438, 0x1000, 0xa438, 0x1519, - 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, 0xa438, 0x5fae, - 0xa438, 0x9b50, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, - 0xa438, 0x7fae, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd707, - 0xa438, 0x40a7, 0xa438, 0xd719, 0xa438, 0x4071, 0xa438, 0x1800, - 0xa438, 0x1557, 0xa438, 0xd719, 0xa438, 0x2f70, 0xa438, 0x803b, - 0xa438, 0x2f73, 0xa438, 0x156a, 0xa438, 0x5e70, 0xa438, 0x1800, - 0xa438, 0x155d, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd500, - 0xa438, 0xffed, 0xa438, 0xd709, 0xa438, 0x4054, 0xa438, 0xa788, - 0xa438, 0xd70b, 0xa438, 0x1800, 0xa438, 0x172a, 0xa438, 0xc0c1, - 0xa438, 0xc0c0, 0xa438, 0xd05a, 0xa438, 0xd1ba, 0xa438, 0xd701, - 0xa438, 0x2529, 0xa438, 0x022a, 0xa438, 0xd0a7, 0xa438, 0xd1b9, - 0xa438, 0xa208, 0xa438, 0x1000, 0xa438, 0x080e, 0xa438, 0xd701, - 0xa438, 0x408b, 0xa438, 0x1000, 0xa438, 0x0a65, 0xa438, 0xf003, - 0xa438, 0x1000, 0xa438, 0x0a6b, 0xa438, 0xd701, 0xa438, 0x1000, - 0xa438, 0x0920, 0xa438, 0x1000, 0xa438, 0x0915, 0xa438, 0x1000, - 0xa438, 0x0909, 0xa438, 0x228f, 0xa438, 0x804e, 0xa438, 0x9801, - 0xa438, 0xd71e, 0xa438, 0x5d61, 0xa438, 0xd701, 0xa438, 0x1800, - 0xa438, 0x022a, 0xa438, 0x2005, 0xa438, 0x091a, 0xa438, 0x3bd9, - 0xa438, 0x0919, 0xa438, 0x1800, 0xa438, 0x0916, 0xa438, 0x1000, - 0xa438, 0x14c5, 0xa438, 0xd703, 0xa438, 0x3181, 0xa438, 0x8077, - 0xa438, 0x60ad, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd703, - 0xa438, 0x5fba, 0xa438, 0x1800, 0xa438, 0x0cc7, 0xa438, 0xd096, - 0xa438, 0xd1a9, 0xa438, 0xd503, 0xa438, 0x1800, 0xa438, 0x0c94, - 0xa438, 0xa802, 0xa438, 0xa301, 0xa438, 0xa801, 0xa438, 0xc004, - 0xa438, 0xd710, 0xa438, 0x4000, 0xa438, 0x1800, 0xa438, 0x1e79, - 0xa436, 0xA026, 0xa438, 0x1e78, 0xa436, 0xA024, 0xa438, 0x0c93, - 0xa436, 0xA022, 0xa438, 0x0cc5, 0xa436, 0xA020, 0xa438, 0x0915, - 0xa436, 0xA006, 0xa438, 0x020a, 0xa436, 0xA004, 0xa438, 0x1726, - 0xa436, 0xA002, 0xa438, 0x1542, 0xa436, 0xA000, 0xa438, 0x0fc7, - 0xa436, 0xA008, 0xa438, 0xff00, 0xa436, 0xA016, 0xa438, 0x0010, - 0xa436, 0xA012, 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, - 0xa438, 0x8010, 0xa438, 0x1800, 0xa438, 0x801d, 0xa438, 0x1800, - 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, - 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, - 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0xd700, - 0xa438, 0x6090, 0xa438, 0x60d1, 0xa438, 0xc95c, 0xa438, 0xf007, - 0xa438, 0x60b1, 0xa438, 0xc95a, 0xa438, 0xf004, 0xa438, 0xc956, - 0xa438, 0xf002, 0xa438, 0xc94e, 0xa438, 0x1800, 0xa438, 0x00cd, - 0xa438, 0xd700, 0xa438, 0x6090, 0xa438, 0x60d1, 0xa438, 0xc95c, - 0xa438, 0xf007, 0xa438, 0x60b1, 0xa438, 0xc95a, 0xa438, 0xf004, - 0xa438, 0xc956, 0xa438, 0xf002, 0xa438, 0xc94e, 0xa438, 0x1000, - 0xa438, 0x022a, 0xa438, 0x1800, 0xa438, 0x0132, 0xa436, 0xA08E, - 0xa438, 0xffff, 0xa436, 0xA08C, 0xa438, 0xffff, 0xa436, 0xA08A, - 0xa438, 0xffff, 0xa436, 0xA088, 0xa438, 0xffff, 0xa436, 0xA086, - 0xa438, 0xffff, 0xa436, 0xA084, 0xa438, 0xffff, 0xa436, 0xA082, - 0xa438, 0x012f, 0xa436, 0xA080, 0xa438, 0x00cc, 0xa436, 0xA090, - 0xa438, 0x0103, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x8020, 0xa438, 0x1800, 0xa438, 0x802a, - 0xa438, 0x1800, 0xa438, 0x8035, 0xa438, 0x1800, 0xa438, 0x803c, - 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0x1800, 0xa438, 0x803c, - 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0xd107, 0xa438, 0xd042, - 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x8280, 0xa438, 0xd700, 0xa438, 0x6065, - 0xa438, 0xd125, 0xa438, 0xf002, 0xa438, 0xd12b, 0xa438, 0xd040, - 0xa438, 0x1800, 0xa438, 0x077f, 0xa438, 0x0cf0, 0xa438, 0x0c50, - 0xa438, 0xd104, 0xa438, 0xd040, 0xa438, 0x1000, 0xa438, 0x0aa8, - 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x1800, 0xa438, 0x0a2e, - 0xa438, 0xcb9b, 0xa438, 0xd110, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0b7b, 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x1800, 0xa438, 0x081b, 0xa438, 0x1000, - 0xa438, 0x09df, 0xa438, 0xd704, 0xa438, 0x7fb8, 0xa438, 0xa718, - 0xa438, 0x1800, 0xa438, 0x074e, 0xa436, 0xA10E, 0xa438, 0xffff, - 0xa436, 0xA10C, 0xa438, 0xffff, 0xa436, 0xA10A, 0xa438, 0xffff, - 0xa436, 0xA108, 0xa438, 0xffff, 0xa436, 0xA106, 0xa438, 0x074d, - 0xa436, 0xA104, 0xa438, 0x0818, 0xa436, 0xA102, 0xa438, 0x0a2c, - 0xa436, 0xA100, 0xa438, 0x077e, 0xa436, 0xA110, 0xa438, 0x000f, - 0xa436, 0xb87c, 0xa438, 0x8625, 0xa436, 0xb87e, 0xa438, 0xaf86, - 0xa438, 0x3daf, 0xa438, 0x8689, 0xa438, 0xaf88, 0xa438, 0x69af, - 0xa438, 0x8887, 0xa438, 0xaf88, 0xa438, 0x9caf, 0xa438, 0x889c, - 0xa438, 0xaf88, 0xa438, 0x9caf, 0xa438, 0x889c, 0xa438, 0xbf86, - 0xa438, 0x49d7, 0xa438, 0x0040, 0xa438, 0x0277, 0xa438, 0x7daf, - 0xa438, 0x2727, 0xa438, 0x0000, 0xa438, 0x7205, 0xa438, 0x0000, - 0xa438, 0x7208, 0xa438, 0x0000, 0xa438, 0x71f3, 0xa438, 0x0000, - 0xa438, 0x71f6, 0xa438, 0x0000, 0xa438, 0x7229, 0xa438, 0x0000, - 0xa438, 0x722c, 0xa438, 0x0000, 0xa438, 0x7217, 0xa438, 0x0000, - 0xa438, 0x721a, 0xa438, 0x0000, 0xa438, 0x721d, 0xa438, 0x0000, - 0xa438, 0x7211, 0xa438, 0x0000, 0xa438, 0x7220, 0xa438, 0x0000, - 0xa438, 0x7214, 0xa438, 0x0000, 0xa438, 0x722f, 0xa438, 0x0000, - 0xa438, 0x7223, 0xa438, 0x0000, 0xa438, 0x7232, 0xa438, 0x0000, - 0xa438, 0x7226, 0xa438, 0xf8f9, 0xa438, 0xfae0, 0xa438, 0x85b3, - 0xa438, 0x3802, 0xa438, 0xad27, 0xa438, 0x02ae, 0xa438, 0x03af, - 0xa438, 0x8830, 0xa438, 0x1f66, 0xa438, 0xef65, 0xa438, 0xbfc2, - 0xa438, 0x1f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, - 0xa438, 0x00da, 0xa438, 0xf605, 0xa438, 0xbfc2, 0xa438, 0x2f1a, - 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00db, - 0xa438, 0xf605, 0xa438, 0xef02, 0xa438, 0x1f11, 0xa438, 0x0d42, - 0xa438, 0xbf88, 0xa438, 0x4202, 0xa438, 0x6e7d, 0xa438, 0xef02, - 0xa438, 0x1b03, 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, - 0xa438, 0x4502, 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1a03, - 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4802, - 0xa438, 0x6e7d, 0xa438, 0xbfc2, 0xa438, 0x3f1a, 0xa438, 0x96f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00da, 0xa438, 0xf605, - 0xa438, 0xbfc2, 0xa438, 0x4f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, - 0xa438, 0xffd2, 0xa438, 0x00db, 0xa438, 0xf605, 0xa438, 0xef02, - 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4b02, - 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1b03, 0xa438, 0x1f11, - 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4e02, 0xa438, 0x6e7d, - 0xa438, 0xef02, 0xa438, 0x1a03, 0xa438, 0x1f11, 0xa438, 0x0d42, - 0xa438, 0xbf88, 0xa438, 0x5102, 0xa438, 0x6e7d, 0xa438, 0xef56, - 0xa438, 0xd020, 0xa438, 0x1f11, 0xa438, 0xbf88, 0xa438, 0x5402, - 0xa438, 0x6e7d, 0xa438, 0xbf88, 0xa438, 0x5702, 0xa438, 0x6e7d, - 0xa438, 0xbf88, 0xa438, 0x5a02, 0xa438, 0x6e7d, 0xa438, 0xe185, - 0xa438, 0xa0ef, 0xa438, 0x0348, 0xa438, 0x0a28, 0xa438, 0x05ef, - 0xa438, 0x201b, 0xa438, 0x01ad, 0xa438, 0x2735, 0xa438, 0x1f44, - 0xa438, 0xe085, 0xa438, 0x88e1, 0xa438, 0x8589, 0xa438, 0xbf88, - 0xa438, 0x5d02, 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x8ee1, - 0xa438, 0x858f, 0xa438, 0xbf88, 0xa438, 0x6002, 0xa438, 0x6e7d, - 0xa438, 0xe085, 0xa438, 0x94e1, 0xa438, 0x8595, 0xa438, 0xbf88, - 0xa438, 0x6302, 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x9ae1, - 0xa438, 0x859b, 0xa438, 0xbf88, 0xa438, 0x6602, 0xa438, 0x6e7d, - 0xa438, 0xaf88, 0xa438, 0x3cbf, 0xa438, 0x883f, 0xa438, 0x026e, - 0xa438, 0x9cad, 0xa438, 0x2835, 0xa438, 0x1f44, 0xa438, 0xe08f, - 0xa438, 0xf8e1, 0xa438, 0x8ff9, 0xa438, 0xbf88, 0xa438, 0x5d02, - 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfae1, 0xa438, 0x8ffb, - 0xa438, 0xbf88, 0xa438, 0x6002, 0xa438, 0x6e7d, 0xa438, 0xe08f, - 0xa438, 0xfce1, 0xa438, 0x8ffd, 0xa438, 0xbf88, 0xa438, 0x6302, - 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfee1, 0xa438, 0x8fff, - 0xa438, 0xbf88, 0xa438, 0x6602, 0xa438, 0x6e7d, 0xa438, 0xaf88, - 0xa438, 0x3ce1, 0xa438, 0x85a1, 0xa438, 0x1b21, 0xa438, 0xad37, - 0xa438, 0x341f, 0xa438, 0x44e0, 0xa438, 0x858a, 0xa438, 0xe185, - 0xa438, 0x8bbf, 0xa438, 0x885d, 0xa438, 0x026e, 0xa438, 0x7de0, - 0xa438, 0x8590, 0xa438, 0xe185, 0xa438, 0x91bf, 0xa438, 0x8860, - 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8596, 0xa438, 0xe185, - 0xa438, 0x97bf, 0xa438, 0x8863, 0xa438, 0x026e, 0xa438, 0x7de0, - 0xa438, 0x859c, 0xa438, 0xe185, 0xa438, 0x9dbf, 0xa438, 0x8866, - 0xa438, 0x026e, 0xa438, 0x7dae, 0xa438, 0x401f, 0xa438, 0x44e0, - 0xa438, 0x858c, 0xa438, 0xe185, 0xa438, 0x8dbf, 0xa438, 0x885d, - 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8592, 0xa438, 0xe185, - 0xa438, 0x93bf, 0xa438, 0x8860, 0xa438, 0x026e, 0xa438, 0x7de0, - 0xa438, 0x8598, 0xa438, 0xe185, 0xa438, 0x99bf, 0xa438, 0x8863, - 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x859e, 0xa438, 0xe185, - 0xa438, 0x9fbf, 0xa438, 0x8866, 0xa438, 0x026e, 0xa438, 0x7dae, - 0xa438, 0x0ce1, 0xa438, 0x85b3, 0xa438, 0x3904, 0xa438, 0xac2f, - 0xa438, 0x04ee, 0xa438, 0x85b3, 0xa438, 0x00af, 0xa438, 0x39d9, - 0xa438, 0x22ac, 0xa438, 0xeaf0, 0xa438, 0xacf6, 0xa438, 0xf0ac, - 0xa438, 0xfaf0, 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xfcf0, - 0xa438, 0xad00, 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacf0, - 0xa438, 0xf0ac, 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, - 0xa438, 0xb0f0, 0xa438, 0xacae, 0xa438, 0xf0ac, 0xa438, 0xacf0, - 0xa438, 0xacaa, 0xa438, 0xa100, 0xa438, 0x0ce1, 0xa438, 0x8ff7, - 0xa438, 0xbf88, 0xa438, 0x8402, 0xa438, 0x6e7d, 0xa438, 0xaf26, - 0xa438, 0xe9e1, 0xa438, 0x8ff6, 0xa438, 0xbf88, 0xa438, 0x8402, - 0xa438, 0x6e7d, 0xa438, 0xaf26, 0xa438, 0xf520, 0xa438, 0xac86, - 0xa438, 0xbf88, 0xa438, 0x3f02, 0xa438, 0x6e9c, 0xa438, 0xad28, - 0xa438, 0x03af, 0xa438, 0x3324, 0xa438, 0xad38, 0xa438, 0x03af, - 0xa438, 0x32e6, 0xa438, 0xaf32, 0xa438, 0xfb00, 0xa436, 0xb87c, - 0xa438, 0x8ff6, 0xa436, 0xb87e, 0xa438, 0x0705, 0xa436, 0xb87c, - 0xa438, 0x8ff8, 0xa436, 0xb87e, 0xa438, 0x19cc, 0xa436, 0xb87c, - 0xa438, 0x8ffa, 0xa436, 0xb87e, 0xa438, 0x28e3, 0xa436, 0xb87c, - 0xa438, 0x8ffc, 0xa436, 0xb87e, 0xa438, 0x1047, 0xa436, 0xb87c, - 0xa438, 0x8ffe, 0xa436, 0xb87e, 0xa438, 0x0a45, 0xa436, 0xb85e, - 0xa438, 0x271E, 0xa436, 0xb860, 0xa438, 0x3846, 0xa436, 0xb862, - 0xa438, 0x26E6, 0xa436, 0xb864, 0xa438, 0x32E3, 0xa436, 0xb886, - 0xa438, 0xffff, 0xa436, 0xb888, 0xa438, 0xffff, 0xa436, 0xb88a, - 0xa438, 0xffff, 0xa436, 0xb88c, 0xa438, 0xffff, 0xa436, 0xb838, - 0xa438, 0x000f, 0xb820, 0x0010, 0xa436, 0x846e, 0xa438, 0xaf84, - 0xa438, 0x86af, 0xa438, 0x8690, 0xa438, 0xaf86, 0xa438, 0xa4af, - 0xa438, 0x86a4, 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, - 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, 0xa438, 0xee82, - 0xa438, 0x5f00, 0xa438, 0x0284, 0xa438, 0x90af, 0xa438, 0x0441, - 0xa438, 0xf8e0, 0xa438, 0x8ff3, 0xa438, 0xa000, 0xa438, 0x0502, - 0xa438, 0x84a4, 0xa438, 0xae06, 0xa438, 0xa001, 0xa438, 0x0302, - 0xa438, 0x84c8, 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, - 0xa438, 0xe080, 0xa438, 0x15ad, 0xa438, 0x2702, 0xa438, 0xae03, - 0xa438, 0xaf84, 0xa438, 0xc3bf, 0xa438, 0x53ca, 0xa438, 0x0252, - 0xa438, 0xc8ad, 0xa438, 0x2807, 0xa438, 0x0285, 0xa438, 0x2cee, - 0xa438, 0x8ff3, 0xa438, 0x01ef, 0xa438, 0x95fd, 0xa438, 0xfc04, - 0xa438, 0xf8f9, 0xa438, 0xfaef, 0xa438, 0x69bf, 0xa438, 0x53ca, - 0xa438, 0x0252, 0xa438, 0xc8ac, 0xa438, 0x2822, 0xa438, 0xd480, - 0xa438, 0x00bf, 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9bf, - 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868a, - 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868d, 0xa438, 0x0252, - 0xa438, 0xa9ee, 0xa438, 0x8ff3, 0xa438, 0x00af, 0xa438, 0x8526, - 0xa438, 0xe08f, 0xa438, 0xf4e1, 0xa438, 0x8ff5, 0xa438, 0xe28f, - 0xa438, 0xf6e3, 0xa438, 0x8ff7, 0xa438, 0x1b45, 0xa438, 0xac27, - 0xa438, 0x0eee, 0xa438, 0x8ff4, 0xa438, 0x00ee, 0xa438, 0x8ff5, - 0xa438, 0x0002, 0xa438, 0x852c, 0xa438, 0xaf85, 0xa438, 0x26e0, - 0xa438, 0x8ff4, 0xa438, 0xe18f, 0xa438, 0xf52c, 0xa438, 0x0001, - 0xa438, 0xe48f, 0xa438, 0xf4e5, 0xa438, 0x8ff5, 0xa438, 0xef96, - 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, - 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa18b, - 0xa438, 0x02ae, 0xa438, 0x03af, 0xa438, 0x85da, 0xa438, 0xbf57, - 0xa438, 0x7202, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xf8e5, - 0xa438, 0x8ff9, 0xa438, 0xbf57, 0xa438, 0x7502, 0xa438, 0x52c8, - 0xa438, 0xe48f, 0xa438, 0xfae5, 0xa438, 0x8ffb, 0xa438, 0xbf57, - 0xa438, 0x7802, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfce5, - 0xa438, 0x8ffd, 0xa438, 0xbf57, 0xa438, 0x7b02, 0xa438, 0x52c8, - 0xa438, 0xe48f, 0xa438, 0xfee5, 0xa438, 0x8fff, 0xa438, 0xbf57, - 0xa438, 0x6c02, 0xa438, 0x52c8, 0xa438, 0xa102, 0xa438, 0x13ee, - 0xa438, 0x8ffc, 0xa438, 0x80ee, 0xa438, 0x8ffd, 0xa438, 0x00ee, - 0xa438, 0x8ffe, 0xa438, 0x80ee, 0xa438, 0x8fff, 0xa438, 0x00af, - 0xa438, 0x8599, 0xa438, 0xa101, 0xa438, 0x0cbf, 0xa438, 0x534c, - 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x0303, 0xa438, 0xaf85, - 0xa438, 0x77bf, 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, - 0xa438, 0x8b02, 0xa438, 0xae03, 0xa438, 0xaf86, 0xa438, 0x64e0, - 0xa438, 0x8ff8, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x8684, - 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffa, 0xa438, 0xe18f, - 0xa438, 0xfbbf, 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9e0, - 0xa438, 0x8ffc, 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x868a, - 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffe, 0xa438, 0xe18f, - 0xa438, 0xffbf, 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9af, - 0xa438, 0x867f, 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, - 0xa438, 0xa144, 0xa438, 0x3cbf, 0xa438, 0x547b, 0xa438, 0x0252, - 0xa438, 0xc8e4, 0xa438, 0x8ff8, 0xa438, 0xe58f, 0xa438, 0xf9bf, - 0xa438, 0x547e, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffa, - 0xa438, 0xe58f, 0xa438, 0xfbbf, 0xa438, 0x5481, 0xa438, 0x0252, - 0xa438, 0xc8e4, 0xa438, 0x8ffc, 0xa438, 0xe58f, 0xa438, 0xfdbf, - 0xa438, 0x5484, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffe, - 0xa438, 0xe58f, 0xa438, 0xffbf, 0xa438, 0x5322, 0xa438, 0x0252, - 0xa438, 0xc8a1, 0xa438, 0x4448, 0xa438, 0xaf85, 0xa438, 0xa7bf, - 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x313c, - 0xa438, 0xbf54, 0xa438, 0x7b02, 0xa438, 0x52c8, 0xa438, 0xe48f, - 0xa438, 0xf8e5, 0xa438, 0x8ff9, 0xa438, 0xbf54, 0xa438, 0x7e02, - 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfae5, 0xa438, 0x8ffb, - 0xa438, 0xbf54, 0xa438, 0x8102, 0xa438, 0x52c8, 0xa438, 0xe48f, - 0xa438, 0xfce5, 0xa438, 0x8ffd, 0xa438, 0xbf54, 0xa438, 0x8402, - 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfee5, 0xa438, 0x8fff, - 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa131, - 0xa438, 0x03af, 0xa438, 0x85a7, 0xa438, 0xd480, 0xa438, 0x00bf, - 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x8687, - 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868a, 0xa438, 0x0252, - 0xa438, 0xa9bf, 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9ef, - 0xa438, 0x95fd, 0xa438, 0xfc04, 0xa438, 0xf0d1, 0xa438, 0x2af0, - 0xa438, 0xd12c, 0xa438, 0xf0d1, 0xa438, 0x44f0, 0xa438, 0xd146, - 0xa438, 0xbf86, 0xa438, 0xa102, 0xa438, 0x52c8, 0xa438, 0xbf86, - 0xa438, 0xa102, 0xa438, 0x52c8, 0xa438, 0xd101, 0xa438, 0xaf06, - 0xa438, 0xa570, 0xa438, 0xce42, 0xa436, 0xb818, 0xa438, 0x043d, - 0xa436, 0xb81a, 0xa438, 0x06a3, 0xa436, 0xb81c, 0xa438, 0xffff, - 0xa436, 0xb81e, 0xa438, 0xffff, 0xa436, 0xb850, 0xa438, 0xffff, - 0xa436, 0xb852, 0xa438, 0xffff, 0xa436, 0xb878, 0xa438, 0xffff, - 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, 0xa438, 0x0003, - 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, 0xa438, 0x0000, - 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, 0xa436, 0x801E, - 0xa438, 0x0020, 0xFFFF, 0xFFFF -}; - -static void -rtl8125_real_set_phy_mcu_8125b_1(struct net_device *dev) -{ - rtl8125_set_phy_mcu_ram_code(dev, - phy_mcu_ram_code_8125b_1, - ARRAY_SIZE(phy_mcu_ram_code_8125b_1) - ); -} - -static void -rtl8125_set_phy_mcu_8125b_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125b_1(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_real_set_phy_mcu_8125b_2(struct net_device *dev) -{ - rtl8125_set_phy_mcu_ram_code(dev, - phy_mcu_ram_code_8125b_2, - ARRAY_SIZE(phy_mcu_ram_code_8125b_2) - ); -} - -static void -rtl8125_set_phy_mcu_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125b_2(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_init_hw_phy_mcu(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 require_disable_phy_disable_mode = FALSE; - - if (tp->NotWrRamCodeToMicroP == TRUE) return; - if (rtl8125_check_hw_phy_mcu_code_ver(dev)) return; - - if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(tp) && rtl8125_is_in_phy_disable_mode(dev)) - require_disable_phy_disable_mode = TRUE; - - if (require_disable_phy_disable_mode) - rtl8125_disable_phy_disable_mode(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_set_phy_mcu_8125a_1(dev); - break; - case CFG_METHOD_3: - rtl8125_set_phy_mcu_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_set_phy_mcu_8125b_1(dev); - break; - case CFG_METHOD_5: - rtl8125_set_phy_mcu_8125b_2(dev); - break; - } - - if (require_disable_phy_disable_mode) - rtl8125_enable_phy_disable_mode(dev); - - rtl8125_write_hw_phy_mcu_code_ver(dev); - - rtl8125_mdio_write(tp,0x1F, 0x0000); - - tp->HwHasWrRamCodeToMicroP = TRUE; -} -#endif - -static void -rtl8125_enable_phy_aldps(struct rtl8125_private *tp) -{ - //enable aldps - //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) - SetEthPhyOcpBit(tp, 0xA430, BIT_2); -} - -static void -rtl8125_hw_phy_config_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - 0x03FF, - 0x84 - ); - - SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearAndSetEthPhyOcpBit(tp, - 0xAD16, - 0x03FF, - 0x0006 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD32, - 0x003F, - 0x0006 - ); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xAC8A, - BIT_15|BIT_14|BIT_13|BIT_12, - BIT_14|BIT_13|BIT_12 - ); - SetEthPhyOcpBit(tp, 0xAD18, BIT_10); - SetEthPhyOcpBit(tp, 0xAD1A, 0x3FF); - SetEthPhyOcpBit(tp, 0xAD1C, 0x3FF); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xC400 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EB); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0x0700, - 0x0300 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F8); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F1); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x3000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80FE); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xA500 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8102); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8105); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x3300 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8100); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x7000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8104); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xF000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8106); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6500 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xED00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); - SetEthPhyOcpBit(tp, 0xA438, BIT_8); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80E1); - ClearEthPhyOcpBit(tp, 0xA438, BIT_8); - - ClearAndSetEthPhyOcpBit(tp, - 0xBF06, - 0x003F, - 0x38 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x819F); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xD0B6); - - mdio_direct_write_phy_ocp(tp, 0xBC34, 0x5555); - ClearAndSetEthPhyOcpBit(tp, - 0xBF0A, - BIT_11|BIT_10|BIT_9, - BIT_11|BIT_9 - ); - - ClearEthPhyOcpBit(tp, 0xA5C0, BIT_10); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - //enable aldps - //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearAndSetEthPhyOcpBit(tp, - 0xAD16, - 0x03FF, - 0x03FF - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD32, - 0x003F, - 0x0006 - ); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xACC0, - BIT_1|BIT_0, - BIT_1 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - BIT_7|BIT_6|BIT_5, - BIT_6 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - BIT_2|BIT_1|BIT_0, - BIT_2 - ); - ClearEthPhyOcpBit(tp, 0xAC14, BIT_7); - ClearEthPhyOcpBit(tp, 0xAC80, BIT_9|BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xAC5E, - BIT_2|BIT_1|BIT_0, - BIT_1 - ); - mdio_direct_write_phy_ocp(tp, 0xAD4C, 0x00A8); - mdio_direct_write_phy_ocp(tp, 0xAC5C, 0x01FF); - ClearAndSetEthPhyOcpBit(tp, - 0xAC8A, - BIT_7|BIT_6|BIT_5|BIT_4, - BIT_5|BIT_4 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - 0xFF00, - 0x0500 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8159); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - 0xFF00, - 0x0700 - ); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80A2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x809C); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x81B3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0043); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00A7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00D6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00EC); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00F6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FD); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FF); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00BB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0058); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0029); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0009); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8257); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020F); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7843); - - - rtl8125_set_phy_mcu_patch_request(tp); - - ClearEthPhyOcpBit(tp, 0xB896, BIT_0); - ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); - - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC091); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC092); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1214); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC094); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1516); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC096); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x171B); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC098); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1B1C); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1F1F); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2021); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2224); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A0); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A2); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A4); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC018); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0AF2); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0D4A); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0F26); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x118D); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC020); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x14F3); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC022); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x175A); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC024); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x19C0); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC026); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1C26); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC089); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6050); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x5F6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC090); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); - - SetEthPhyOcpBit(tp, 0xB896, BIT_0); - - rtl8125_clear_phy_mcu_patch_request(tp); - - - SetEthPhyOcpBit(tp, 0xD068, BIT_13); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x81A2); - SetEthPhyOcpBit(tp, 0xA438, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xB54C, - 0xFF00, - 0xDB00); - - - ClearEthPhyOcpBit(tp, 0xA454, BIT_0); - - - SetEthPhyOcpBit(tp, 0xA5D4, BIT_5); - ClearEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearEthPhyOcpBit(tp, 0xA86A, BIT_0); - - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - if (tp->RequirePhyMdiSwapPatch) { - u16 adccal_offset_p0; - u16 adccal_offset_p1; - u16 adccal_offset_p2; - u16 adccal_offset_p3; - u16 rg_lpf_cap_xg_p0; - u16 rg_lpf_cap_xg_p1; - u16 rg_lpf_cap_xg_p2; - u16 rg_lpf_cap_xg_p3; - u16 rg_lpf_cap_p0; - u16 rg_lpf_cap_p1; - u16 rg_lpf_cap_p2; - u16 rg_lpf_cap_p3; - - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0007, - 0x0001 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0000 - ); - adccal_offset_p0 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p0 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0008 - ); - adccal_offset_p1 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p1 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0010 - ); - adccal_offset_p2 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p2 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0018 - ); - adccal_offset_p3 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p3 &= 0x07FF; - - - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0000 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p3 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0008 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p2 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0010 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p1 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0018 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p0 - ); - - - rg_lpf_cap_xg_p0 = mdio_direct_read_phy_ocp(tp, 0xBD5A); - rg_lpf_cap_xg_p0 &= 0x001F; - rg_lpf_cap_xg_p1 = mdio_direct_read_phy_ocp(tp, 0xBD5A); - rg_lpf_cap_xg_p1 &= 0x1F00; - rg_lpf_cap_xg_p2 = mdio_direct_read_phy_ocp(tp, 0xBD5C); - rg_lpf_cap_xg_p2 &= 0x001F; - rg_lpf_cap_xg_p3 = mdio_direct_read_phy_ocp(tp, 0xBD5C); - rg_lpf_cap_xg_p3 &= 0x1F00; - rg_lpf_cap_p0 = mdio_direct_read_phy_ocp(tp, 0xBC18); - rg_lpf_cap_p0 &= 0x001F; - rg_lpf_cap_p1 = mdio_direct_read_phy_ocp(tp, 0xBC18); - rg_lpf_cap_p1 &= 0x1F00; - rg_lpf_cap_p2 = mdio_direct_read_phy_ocp(tp, 0xBC1A); - rg_lpf_cap_p2 &= 0x001F; - rg_lpf_cap_p3 = mdio_direct_read_phy_ocp(tp, 0xBC1A); - rg_lpf_cap_p3 &= 0x1F00; - - - ClearAndSetEthPhyOcpBit(tp, - 0xBD5A, - 0x001F, - rg_lpf_cap_xg_p3 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5A, - 0x1F00, - rg_lpf_cap_xg_p2 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5C, - 0x001F, - rg_lpf_cap_xg_p1 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5C, - 0x1F00, - rg_lpf_cap_xg_p0 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC18, - 0x001F, - rg_lpf_cap_p3 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC18, - 0x1F00, - rg_lpf_cap_p2 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC1A, - 0x001F, - rg_lpf_cap_p1 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC1A, - 0x1F00, - rg_lpf_cap_p0 << 8 - ); - } - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125b_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - SetEthPhyOcpBit(tp, 0xBC08, (BIT_3 | BIT_2)); - - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FFF); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x0400 - ); - } - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8560); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8562); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8564); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8566); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8568); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x856A); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FFE); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0907); - } - ClearAndSetEthPhyOcpBit(tp, - 0xACDA, - 0xFF00, - 0xFF00 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xACDE, - 0xF000, - 0xF000 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80D6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x6077); - mdio_direct_write_phy_ocp(tp, 0xB506, 0x01E7); - mdio_direct_write_phy_ocp(tp, 0xAC8C, 0x0FFC); - mdio_direct_write_phy_ocp(tp, 0xAC46, 0xB7B4); - mdio_direct_write_phy_ocp(tp, 0xAC50, 0x0FBC); - mdio_direct_write_phy_ocp(tp, 0xAC3C, 0x9240); - mdio_direct_write_phy_ocp(tp, 0xAC4E, 0x0DB4); - mdio_direct_write_phy_ocp(tp, 0xACC6, 0x0707); - mdio_direct_write_phy_ocp(tp, 0xACC8, 0xA0D3); - mdio_direct_write_phy_ocp(tp, 0xAD08, 0x0007); - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8013); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0700); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FB9); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBA); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBC); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1900); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBE); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0800); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE500); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC8); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0400); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCa); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF300); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCc); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFD00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCe); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFB00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF400); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD8); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF600); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x813D); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x390E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x814F); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x790E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80B0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F31); - SetEthPhyOcpBit(tp, 0xBF4C, BIT_1); - SetEthPhyOcpBit(tp, 0xBCCA, (BIT_9 | BIT_8)); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8141); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x320E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8153); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x720E); - ClearEthPhyOcpBit(tp, 0xA432, BIT_6); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8529); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x050E); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x816C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8174); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8178); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0719); - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0400); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0404); - } - mdio_direct_write_phy_ocp(tp, 0xBF4A, 0x001B); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8033); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8037); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803B); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFC32); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803F); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8043); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8047); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8145); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x370E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x770E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8169); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0D0A); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x817B); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1D0A); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8217); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x821A); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DA); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0403); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0384); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BA); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xF009); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BD); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x9F00 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf083); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DD); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03f0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CE); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8009); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80D1); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x8000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x200A); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xF0AD); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x809F); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6073); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000B); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A9); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xC000 - ); - - rtl8125_set_phy_mcu_patch_request(tp); - - ClearEthPhyOcpBit(tp, 0xB896, BIT_0); - ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); - - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC23E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC240); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0103); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC242); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0507); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC244); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x090B); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC246); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0C0E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC248); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1012); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC24A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1416); - - SetEthPhyOcpBit(tp, 0xB896, BIT_0); - - rtl8125_clear_phy_mcu_patch_request(tp); - - - SetEthPhyOcpBit(tp, 0xA86A, BIT_0); - SetEthPhyOcpBit(tp, 0xA6F0, BIT_0); - - - mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); - mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); - mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); - mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); - mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); - ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); - SetEthPhyOcpBit(tp, 0xA438, BIT_12); - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - ClearAndSetEthPhyOcpBit(tp, - 0xAC46, - 0x00F0, - 0x0090 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD30, - 0x0003, - 0x0001 - ); - - - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, tp->eee.tx_lpi_timer); - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F5); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x760E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8107); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x360E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8551); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8, - BIT_11 - ); - - ClearAndSetEthPhyOcpBit(tp, - 0xbf00, - 0xE000, - 0xA000 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xbf46, - 0x0F00, - 0x0300 - ); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8044); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x804A); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8050); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8056); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x805C); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8062); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8068); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x806E); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8074); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x807A); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - - - SetEthPhyOcpBit(tp, 0xA4CA, BIT_6); - - - ClearAndSetEthPhyOcpBit(tp, - 0xBF84, - BIT_15 | BIT_14 | BIT_13, - BIT_15 | BIT_13 - ); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - BIT_13 | BIT_10 | BIT_9 | BIT_8, - BIT_15 | BIT_14 | BIT_12 | BIT_11 - ); - - /* - mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); - mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); - mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); - mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); - mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); - ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); - SetEthPhyOcpBit(tp, 0xA438, BIT_12); - */ - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->resume_not_chg_speed) return; - - tp->phy_reset_enable(dev); - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) return; - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) { - rtl8125_set_hw_phy_before_init_phy_mcu(dev); - - rtl8125_init_hw_phy_mcu(dev); - } -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_hw_phy_config_8125a_1(dev); - break; - case CFG_METHOD_3: - rtl8125_hw_phy_config_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_hw_phy_config_8125b_1(dev); - break; - case CFG_METHOD_5: - rtl8125_hw_phy_config_8125b_2(dev); - break; - } - - //legacy force mode(Chap 22) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - rtl8125_mdio_write(tp, 0x1F, 0x0A5B); - rtl8125_clear_eth_phy_bit(tp, 0x12, BIT_15); - rtl8125_mdio_write(tp, 0x1F, 0x0000); - break; - } - - /*ocp phy power saving*/ - /* - if (aspm) { - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) - rtl8125_enable_ocp_phy_power_saving(dev); - } - */ - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - if (tp->eee.eee_enabled) - rtl8125_enable_eee(tp); - else - rtl8125_disable_eee(tp); - } -} - -static void -rtl8125_up(struct net_device *dev) -{ - rtl8125_hw_init(dev); - rtl8125_hw_reset(dev); - rtl8125_powerup_pll(dev); - rtl8125_hw_ephy_config(dev); - rtl8125_hw_phy_config(dev); - rtl8125_hw_config(dev); -} - -/* -static inline void rtl8125_delete_esd_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8125_request_esd_timer(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8125_esd_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8125_esd_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8125_ESD_TIMEOUT); -} -*/ - -/* -static inline void rtl8125_delete_link_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8125_request_link_timer(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8125_link_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8125_link_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); -} -*/ - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void -rtl8125_netpoll(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - for (i = 0; i < tp->irq_nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - struct r8125_napi *r8125napi = &tp->r8125napi[i]; - - disable_irq(irq->vector); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) - irq->handler(irq->vector, r8125napi); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - irq->handler(irq->vector, r8125napi, NULL); -#else - irq->handler(irq->vector, r8125napi); -#endif - - enable_irq(irq->vector); - } -} -#endif //CONFIG_NET_POLL_CONTROLLER - -static void -rtl8125_get_bios_setting(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->bios_setting = RTL_R32(tp, TimeInt2); - break; - } -} - -static void -rtl8125_set_bios_setting(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W32(tp, TimeInt2, tp->bios_setting); - break; - } -} - -static void -rtl8125_setup_mqs_reg(struct rtl8125_private *tp) -{ - int i; - - //tx - tp->tx_ring[0].tdsar_reg = TxDescStartAddrLow; - for (i = 1; i < R8125_MAX_TX_QUEUES; i++) { - tp->tx_ring[i].tdsar_reg = (u16)(TNPDS_Q1_LOW_8125 + (i - 1) * 8); - } - - for (i = 0; i < R8125_MAX_TX_QUEUES; i++) { - tp->tx_ring[i].hw_clo_ptr_reg = (u16)(HW_CLO_PTR0_8125 + i * 4); - tp->tx_ring[i].sw_tail_ptr_reg = (u16)(SW_TAIL_PTR0_8125 + i * 4); - } - - //rx - tp->rx_ring[0].rdsar_reg = RxDescAddrLow; - for (i = 1; i < R8125_MAX_RX_QUEUES; i++) { - tp->rx_ring[i].rdsar_reg = (u16)(RDSAR_Q1_LOW_8125 + (i - 1) * 8); - } - - tp->isr_reg[0] = ISR0_8125; - for (i = 1; i < R8125_MAX_QUEUES; i++) { - tp->isr_reg[i] = (u16)(ISR1_8125 + (i - 1) * 4); - } - - tp->imr_reg[0] = IMR0_8125; - for (i = 1; i < R8125_MAX_QUEUES; i++) { - tp->imr_reg[i] = (u16)(IMR1_8125 + (i - 1) * 4); - } -} - -static void -rtl8125_init_software_variable(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8125_get_bios_setting(dev); - -#ifdef ENABLE_LIB_SUPPORT - tp->ring_lib_enabled = 1; -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - //tp->HwSuppDashVer = 3; - break; - default: - tp->HwSuppDashVer = 0; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwPkgDet = rtl8125_mac_ocp_read(tp, 0xDC00); - tp->HwPkgDet = (tp->HwPkgDet >> 3) & 0x07; - break; - } - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) - eee_enable = 0; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppNowIsOobVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwPcieSNOffset = 0x16C; - break; - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_get_realwow_hw_version(dev); -#endif //ENABLE_REALWOW_SUPPORT - - if (HW_DASH_SUPPORT_DASH(tp) && rtl8125_check_dash(tp)) - tp->DASH = 1; - else - tp->DASH = 0; - - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u64 CmacMemPhysAddress; - void __iomem *cmac_ioaddr = NULL; - - //map CMAC IO space - CmacMemPhysAddress = rtl8125_csi_other_fun_read(tp, 0, 0x18); - if (!(CmacMemPhysAddress & BIT_0)) { - if (CmacMemPhysAddress & BIT_2) - CmacMemPhysAddress |= (u64)rtl8125_csi_other_fun_read(tp, 0, 0x1C) << 32; - - CmacMemPhysAddress &= 0xFFFFFFF0; - /* ioremap MMIO region */ - cmac_ioaddr = ioremap(CmacMemPhysAddress, R8125_REGS_SIZE); - } - - if (cmac_ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap CMAC MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - } - - if (cmac_ioaddr == NULL) { - tp->DASH = 0; - } else { - tp->mapped_cmac_ioaddr = cmac_ioaddr; - } - } - - eee_enable = 0; - } - - if (HW_DASH_SUPPORT_TYPE_3(tp)) - tp->cmac_ioaddr = tp->mapped_cmac_ioaddr; - - if (aspm) { - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->org_pci_offset_99 = rtl8125_csi_fun0_read_byte(tp, 0x99); - tp->org_pci_offset_99 &= ~(BIT_5|BIT_6); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x264); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x214); - break; - } - } - - pci_read_config_byte(pdev, 0x80, &tp->org_pci_offset_80); - pci_read_config_byte(pdev, 0x81, &tp->org_pci_offset_81); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - default: - tp->use_timer_interrrupt = TRUE; - break; - } - - if (timer_count == 0 || tp->mcfg == CFG_METHOD_DEFAULT) - tp->use_timer_interrrupt = FALSE; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V3; - break; - default: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_NOT_SUPPORT; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppLinkChgWakeUpVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppD0SpeedUpVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppCheckPhyDisableModeVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppTxNoCloseVer = 3; - break; - } - - if (tp->HwSuppTxNoCloseVer > 0 && tx_no_close_enable == 1) - tp->EnableTxNoClose = TRUE; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->RequireLSOPatch = TRUE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_2; - break; - case CFG_METHOD_3: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_3; - break; - case CFG_METHOD_4: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_4; - break; - case CFG_METHOD_5: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_5; - break; - } - - if (tp->HwIcVerUnknown) { - tp->NotWrRamCodeToMicroP = TRUE; - tp->NotWrMcuPatchCode = TRUE; - } - - switch (tp->mcfg) { - case CFG_METHOD_3: - if ((rtl8125_mac_ocp_read(tp, 0xD442) & BIT_5) && - (mdio_direct_read_phy_ocp(tp, 0xD068) & BIT_1) - ) { - tp->RequirePhyMdiSwapPatch = TRUE; - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppNumTxQueues = 2; - tp->HwSuppNumRxQueues = 4; - break; - default: - tp->HwSuppNumTxQueues = 1; - tp->HwSuppNumRxQueues = 1; - break; - } - - tp->num_tx_rings = 1; -#ifdef ENABLE_MULTIPLE_TX_QUEUE -#ifndef ENABLE_LIB_SUPPORT - tp->num_tx_rings = tp->HwSuppNumTxQueues; -#endif -#endif - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppRssVer = 5; - tp->HwSuppIndirTblEntries = 128; - break; - } - - tp->num_rx_rings = 1; -#ifdef ENABLE_RSS_SUPPORT -#ifdef ENABLE_LIB_SUPPORT - if (tp->HwSuppRssVer > 0) - tp->EnableRss = 1; -#else - if (tp->HwSuppRssVer > 0) { - u8 rss_queue_num = netif_get_num_default_rss_queues(); - tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)? - rss_queue_num : tp->HwSuppNumRxQueues; - - if (!(tp->num_rx_rings >= 2 && tp->irq_nvecs >= tp->num_rx_rings)) - tp->num_rx_rings = 1; - - if (tp->num_rx_rings >= 2) - tp->EnableRss = 1; - } -#endif - if (tp->EnableRss) - rtl8125_init_rss(tp); -#endif - - rtl8125_setup_mqs_reg(tp); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppPtpVer = 1; - break; - } -#ifdef ENABLE_PTP_SUPPORT - if (tp->HwSuppPtpVer > 0) - tp->EnablePtp = 1; -#endif - - tp->InitRxDescType = RX_DESC_RING_TYPE_1; - if (tp->EnableRss || tp->EnablePtp) - tp->InitRxDescType = RX_DESC_RING_TYPE_3; - - tp->RxDescLength = RX_DESC_LEN_TYPE_1; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - tp->RxDescLength = RX_DESC_LEN_TYPE_3; - tp->RxDescRingLength = NUM_RX_DESC * tp->RxDescLength; - - tp->rtl8125_rx_config = rtl_chip_info[tp->chipset].RCR_Cfg; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - tp->rtl8125_rx_config |= EnableRxDescV3; - - //init interrupt - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppIsrVer = 2; - break; - default: - tp->HwSuppIsrVer = 1; - break; - } - - tp->HwCurrIsrVer = tp->HwSuppIsrVer; - if (tp->HwSuppIsrVer == 2) { - if (!(tp->features & RTL_FEATURE_MSIX) || - tp->irq_nvecs < R8125_MIN_MSIX_VEC_8125B) - tp->HwCurrIsrVer = 1; - } - - if (tp->HwCurrIsrVer < 2 || tp->irq_nvecs < 19) - tp->num_tx_rings = 1; - - if (tp->HwCurrIsrVer == 2) { - int i; - - tp->intr_mask = ISRIMR_V2_LINKCHG | ISRIMR_TOK_Q0; - if (tp->num_tx_rings > 1) - tp->intr_mask |= ISRIMR_TOK_Q1; - - for (i = 0; i < tp->num_rx_rings; i++) - tp->intr_mask |= ISRIMR_V2_ROK_Q0 << i; - } else { - tp->intr_mask = LinkChg | RxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = LinkChg | PCSTimeout; - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - tp->timer_intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - tp->intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - } - } -#endif - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->HwSuppIntMitiVer = 3; - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppIntMitiVer = 4; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->HwSuppExtendTallyCounterVer = 1; - break; - } - - timer_count_v2 = (timer_count / 0x100); - - tp->NicCustLedValue = RTL_R16(tp, CustomLED); - - tp->wol_opts = rtl8125_get_hw_wol(tp); - tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; - - rtl8125_link_option((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); - - tp->autoneg = autoneg_mode; - tp->speed = speed_mode; - tp->duplex = duplex_mode; - tp->advertising = advertising_mode; - tp->fcpause = rtl8125_fc_full; - - tp->max_jumbo_frame_size = rtl_chip_info[tp->chipset].jumbo_frame_sz; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - /* MTU range: 60 - hw-specific max */ - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - - if (tp->mcfg != CFG_METHOD_DEFAULT) { - struct ethtool_eee *eee = &tp->eee; - - eee->eee_enabled = eee_enable; - eee->supported = SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full; - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - eee->supported |= SUPPORTED_2500baseX_Full; - break; - } - eee->advertised = mmd_eee_adv_to_ethtool_adv_t(MDIO_EEE_1000T | MDIO_EEE_100TX); - eee->tx_lpi_timer = dev->mtu + ETH_HLEN + 0x20; - } - - tp->ptp_master_mode = enable_ptp_master_mode; -} - -static void -rtl8125_release_board(struct pci_dev *pdev, - struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8125_set_bios_setting(dev); - rtl8125_rar_set(tp, tp->org_mac_addr); - tp->wol_enabled = WOL_DISABLED; - - if (!tp->DASH) - rtl8125_phy_power_down(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - FreeAllocatedDashShareMemory(dev); -#endif - - if (tp->mapped_cmac_ioaddr != NULL) - iounmap(tp->mapped_cmac_ioaddr); - - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static int -rtl8125_get_mac_address(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - u8 mac_addr[MAC_ADDR_LEN]; - - for (i = 0; i < MAC_ADDR_LEN; i++) - mac_addr[i] = RTL_R8(tp, MAC0 + i); - - if(tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - *(u32*)&mac_addr[0] = RTL_R32(tp, BACKUP_ADDR0_8125); - *(u16*)&mac_addr[4] = RTL_R16(tp, BACKUP_ADDR1_8125); - } - - if (!is_valid_ether_addr(mac_addr)) { - netif_err(tp, probe, dev, "Invalid ether addr %pM\n", - mac_addr); - eth_hw_addr_random(dev); - ether_addr_copy(mac_addr, dev->dev_addr); - netif_info(tp, probe, dev, "Random ether addr %pM\n", - mac_addr); - tp->random_mac = 1; - } - - rtl8125_rar_set(tp, mac_addr); - - for (i = 0; i < MAC_ADDR_LEN; i++) { - dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); - tp->org_mac_addr[i] = dev->dev_addr[i]; /* keep the original MAC address */ - } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); -#endif -// memcpy(dev->dev_addr, dev->dev_addr, dev->addr_len); - - return 0; -} - -/** - * rtl8125_set_mac_address - Change the Ethernet Address of the NIC - * @dev: network interface device structure - * @p: pointer to an address structure - * - * Return 0 on success, negative on failure - **/ -static int -rtl8125_set_mac_address(struct net_device *dev, - void *p) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl8125_rar_set(tp, dev->dev_addr); - - return 0; -} - -/****************************************************************************** - * rtl8125_rar_set - Puts an ethernet address into a receive address register. - * - * tp - The private data structure for driver - * addr - Address to put into receive address register - *****************************************************************************/ -void -rtl8125_rar_set(struct rtl8125_private *tp, - uint8_t *addr) -{ - uint32_t rar_low = 0; - uint32_t rar_high = 0; - - rar_low = ((uint32_t) addr[0] | - ((uint32_t) addr[1] << 8) | - ((uint32_t) addr[2] << 16) | - ((uint32_t) addr[3] << 24)); - - rar_high = ((uint32_t) addr[4] | - ((uint32_t) addr[5] << 8)); - - rtl8125_enable_cfg9346_write(tp); - RTL_W32(tp, MAC0, rar_low); - RTL_W32(tp, MAC4, rar_high); - - rtl8125_disable_cfg9346_write(tp); -} - -#ifdef ETHTOOL_OPS_COMPAT -static int ethtool_get_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - int err; - - if (!ethtool_ops->get_settings) - return -EOPNOTSUPP; - - err = ethtool_ops->get_settings(dev, &cmd); - if (err < 0) - return err; - - if (copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; -} - -static int ethtool_set_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd; - - if (!ethtool_ops->set_settings) - return -EOPNOTSUPP; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - return ethtool_ops->set_settings(dev, &cmd); -} - -static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) -{ - struct ethtool_drvinfo info; - struct ethtool_ops *ops = ethtool_ops; - - if (!ops->get_drvinfo) - return -EOPNOTSUPP; - - memset(&info, 0, sizeof(info)); - info.cmd = ETHTOOL_GDRVINFO; - ops->get_drvinfo(dev, &info); - - if (ops->self_test_count) - info.testinfo_len = ops->self_test_count(dev); - if (ops->get_stats_count) - info.n_stats = ops->get_stats_count(dev); - if (ops->get_regs_len) - info.regdump_len = ops->get_regs_len(dev); - if (ops->get_eeprom_len) - info.eedump_len = ops->get_eeprom_len(dev); - - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int ethtool_get_regs(struct net_device *dev, char *useraddr) -{ - struct ethtool_regs regs; - struct ethtool_ops *ops = ethtool_ops; - void *regbuf; - int reglen, ret; - - if (!ops->get_regs || !ops->get_regs_len) - return -EOPNOTSUPP; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - - reglen = ops->get_regs_len(dev); - if (regs.len > reglen) - regs.len = reglen; - - regbuf = kmalloc(reglen, GFP_USER); - if (!regbuf) - return -ENOMEM; - - ops->get_regs(dev, ®s, regbuf); - - ret = -EFAULT; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - goto out; - useraddr += offsetof(struct ethtool_regs, data); - if (copy_to_user(useraddr, regbuf, reglen)) - goto out; - ret = 0; - -out: - kfree(regbuf); - return ret; -} - -static int ethtool_get_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - if (!ethtool_ops->get_wol) - return -EOPNOTSUPP; - - ethtool_ops->get_wol(dev, &wol); - - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; -} - -static int ethtool_set_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol; - - if (!ethtool_ops->set_wol) - return -EOPNOTSUPP; - - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - - return ethtool_ops->set_wol(dev, &wol); -} - -static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - - if (!ethtool_ops->get_msglevel) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_msglevel(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_msglevel) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_msglevel(dev, edata.data); - return 0; -} - -static int ethtool_nway_reset(struct net_device *dev) -{ - if (!ethtool_ops->nway_reset) - return -EOPNOTSUPP; - - return ethtool_ops->nway_reset(dev); -} - -static int ethtool_get_link(struct net_device *dev, void *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - if (!ethtool_ops->get_link) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_link(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->get_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - ret = -EFAULT; - if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) - goto out; - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->set_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->set_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - ret = -EFAULT; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - ethtool_ops->get_coalesce(dev, &coalesce); - - if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) - return -EFAULT; - return 0; -} - -static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) - return -EFAULT; - - return ethtool_ops->set_coalesce(dev, &coalesce); -} - -static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - ethtool_ops->get_ringparam(dev, &ringparam); - - if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) - return -EFAULT; - - return ethtool_ops->set_ringparam(dev, &ringparam); -} - -static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - ethtool_ops->get_pauseparam(dev, &pauseparam); - - if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) - return -EFAULT; - - return ethtool_ops->set_pauseparam(dev, &pauseparam); -} - -static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - if (!ethtool_ops->get_rx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_rx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_rx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_rx_csum(dev, edata.data); - return 0; -} - -static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - if (!ethtool_ops->get_tx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tx_csum(dev, edata.data); -} - -static int ethtool_get_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GSG }; - - if (!ethtool_ops->get_sg) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_sg(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_sg) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_sg(dev, edata.data); -} - -static int ethtool_get_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTSO }; - - if (!ethtool_ops->get_tso) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tso(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tso) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tso(dev, edata.data); -} - -static int ethtool_self_test(struct net_device *dev, char *useraddr) -{ - struct ethtool_test test; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->self_test || !ops->self_test_count) - return -EOPNOTSUPP; - - if (copy_from_user(&test, useraddr, sizeof(test))) - return -EFAULT; - - test.len = ops->self_test_count(dev); - data = kmalloc(test.len * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->self_test(dev, &test, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &test, sizeof(test))) - goto out; - useraddr += sizeof(test); - if (copy_to_user(useraddr, data, test.len * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_strings(struct net_device *dev, void *useraddr) -{ - struct ethtool_gstrings gstrings; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_strings) - return -EOPNOTSUPP; - - if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) - return -EFAULT; - - switch (gstrings.string_set) { - case ETH_SS_TEST: - if (!ops->self_test_count) - return -EOPNOTSUPP; - gstrings.len = ops->self_test_count(dev); - break; - case ETH_SS_STATS: - if (!ops->get_stats_count) - return -EOPNOTSUPP; - gstrings.len = ops->get_stats_count(dev); - break; - default: - return -EINVAL; - } - - data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_strings(dev, gstrings.string_set, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) - goto out; - useraddr += sizeof(gstrings); - if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_phys_id(struct net_device *dev, void *useraddr) -{ - struct ethtool_value id; - - if (!ethtool_ops->phys_id) - return -EOPNOTSUPP; - - if (copy_from_user(&id, useraddr, sizeof(id))) - return -EFAULT; - - return ethtool_ops->phys_id(dev, id.data); -} - -static int ethtool_get_stats(struct net_device *dev, void *useraddr) -{ - struct ethtool_stats stats; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->get_ethtool_stats || !ops->get_stats_count) - return -EOPNOTSUPP; - - if (copy_from_user(&stats, useraddr, sizeof(stats))) - return -EFAULT; - - stats.n_stats = ops->get_stats_count(dev); - data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_ethtool_stats(dev, &stats, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &stats, sizeof(stats))) - goto out; - useraddr += sizeof(stats); - if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_ioctl(struct ifreq *ifr) -{ - struct net_device *dev = __dev_get_by_name(ifr->ifr_name); - void *useraddr = (void *) ifr->ifr_data; - u32 ethcmd; - - /* - * XXX: This can be pushed down into the ethtool_* handlers that - * need it. Keep existing behaviour for the moment. - */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!dev || !netif_device_present(dev)) - return -ENODEV; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GSET: - return ethtool_get_settings(dev, useraddr); - case ETHTOOL_SSET: - return ethtool_set_settings(dev, useraddr); - case ETHTOOL_GDRVINFO: - return ethtool_get_drvinfo(dev, useraddr); - case ETHTOOL_GREGS: - return ethtool_get_regs(dev, useraddr); - case ETHTOOL_GWOL: - return ethtool_get_wol(dev, useraddr); - case ETHTOOL_SWOL: - return ethtool_set_wol(dev, useraddr); - case ETHTOOL_GMSGLVL: - return ethtool_get_msglevel(dev, useraddr); - case ETHTOOL_SMSGLVL: - return ethtool_set_msglevel(dev, useraddr); - case ETHTOOL_NWAY_RST: - return ethtool_nway_reset(dev); - case ETHTOOL_GLINK: - return ethtool_get_link(dev, useraddr); - case ETHTOOL_GEEPROM: - return ethtool_get_eeprom(dev, useraddr); - case ETHTOOL_SEEPROM: - return ethtool_set_eeprom(dev, useraddr); - case ETHTOOL_GCOALESCE: - return ethtool_get_coalesce(dev, useraddr); - case ETHTOOL_SCOALESCE: - return ethtool_set_coalesce(dev, useraddr); - case ETHTOOL_GRINGPARAM: - return ethtool_get_ringparam(dev, useraddr); - case ETHTOOL_SRINGPARAM: - return ethtool_set_ringparam(dev, useraddr); - case ETHTOOL_GPAUSEPARAM: - return ethtool_get_pauseparam(dev, useraddr); - case ETHTOOL_SPAUSEPARAM: - return ethtool_set_pauseparam(dev, useraddr); - case ETHTOOL_GRXCSUM: - return ethtool_get_rx_csum(dev, useraddr); - case ETHTOOL_SRXCSUM: - return ethtool_set_rx_csum(dev, useraddr); - case ETHTOOL_GTXCSUM: - return ethtool_get_tx_csum(dev, useraddr); - case ETHTOOL_STXCSUM: - return ethtool_set_tx_csum(dev, useraddr); - case ETHTOOL_GSG: - return ethtool_get_sg(dev, useraddr); - case ETHTOOL_SSG: - return ethtool_set_sg(dev, useraddr); - case ETHTOOL_GTSO: - return ethtool_get_tso(dev, useraddr); - case ETHTOOL_STSO: - return ethtool_set_tso(dev, useraddr); - case ETHTOOL_TEST: - return ethtool_self_test(dev, useraddr); - case ETHTOOL_GSTRINGS: - return ethtool_get_strings(dev, useraddr); - case ETHTOOL_PHYS_ID: - return ethtool_phys_id(dev, useraddr); - case ETHTOOL_GSTATS: - return ethtool_get_stats(dev, useraddr); - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} -#endif //ETHTOOL_OPS_COMPAT - -static int -rtl8125_do_ioctl(struct net_device *dev, - struct ifreq *ifr, - int cmd) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - int ret; - - ret = 0; - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - break; - - case SIOCGMIIREG: - rtl8125_mdio_write(tp, 0x1F, 0x0000); - data->val_out = rtl8125_mdio_read(tp, data->reg_num); - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, data->reg_num, data->val_in); - break; - -#ifdef ETHTOOL_OPS_COMPAT - case SIOCETHTOOL: - ret = ethtool_ioctl(ifr); - break; -#endif - -#ifdef ENABLE_DASH_SUPPORT - case SIOCDEVPRIVATE_RTLDASH: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8125_dash_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_REALWOW_SUPPORT - case SIOCDEVPRIVATE_RTLREALWOW: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - ret = rtl8125_realwow_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_PTP_SUPPORT - case SIOCSHWTSTAMP: - case SIOCGHWTSTAMP: - if (tp->EnablePtp) - ret = rtl8125_ptp_ioctl(dev, ifr, cmd); - else - ret = -EOPNOTSUPP; - break; -#endif - case SIOCRTLTOOL: - ret = rtl8125_tool_ioctl(tp, ifr); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8125_phy_power_up(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) { - return; - } - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE); - - //wait ups resume (phy state 3) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_wait_phy_ups_resume(dev, 3); - break; - }; -} - -static void -rtl8125_phy_power_down(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); -} - -static int __devinit -rtl8125_init_board(struct pci_dev *pdev, - struct net_device **dev_out, - void __iomem **ioaddr_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8125_private *tp; - int rc = -ENOMEM, i, pm_cap; - - assert(ioaddr_out != NULL); - - /* dev zeroed in alloc_etherdev */ - dev = alloc_etherdev_mq(sizeof (*tp), R8125_MAX_QUEUES); - if (dev == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out; - } - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8125_MSG_DEFAULT); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - if (!aspm) - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); -#endif - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_dev; - } - - if (pci_set_mwi(pdev) < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_info(&pdev->dev, "Mem-Wr-Inval unavailable.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - } - - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command; - - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - } else { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, "PowerManagement capability not found.\n"); - } -#else - printk("PowerManagement capability not found.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - } - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, 2) < R8125_REGS_SIZE) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_mwi; - } - - if ((sizeof(dma_addr_t) > 4) && - use_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "DMA configuration failed.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_res; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); - if (ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -EIO; - goto err_out_free_res; - } - - tp->mmio_addr = ioaddr; - - /* Identify chip attached to board */ - rtl8125_get_mac_version(tp); - - rtl8125_print_mac_version(tp); - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) - break; - } - - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8125 */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_printk(KERN_DEBUG, &pdev->dev, "unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#else - printk("Realtek unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - i++; - } - - tp->chipset = i; - - *ioaddr_out = ioaddr; - *dev_out = dev; -out: - return rc; - -err_out_free_res: - pci_release_regions(pdev); -err_out_mwi: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev: - free_netdev(dev); -err_out: - *ioaddr_out = NULL; - *dev_out = NULL; - goto out; -} - -static void -rtl8125_esd_checker(struct rtl8125_private *tp) -{ - struct net_device *dev = tp->dev; - struct pci_dev *pdev = tp->pci_dev; - u8 cmd; - u16 io_base_l; - u16 mem_base_l; - u16 mem_base_h; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_l; - u16 resv_0x20_h; - u16 resv_0x24_l; - u16 resv_0x24_h; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; - - tp->esd_flag = 0; - - pci_read_config_byte(pdev, PCI_COMMAND, &cmd); - if (cmd != tp->pci_cfg_space.cmd) { - printk(KERN_ERR "%s: cmd = 0x%02x, should be 0x%02x \n.", dev->name, cmd, tp->pci_cfg_space.cmd); - pci_write_config_byte(pdev, PCI_COMMAND, tp->pci_cfg_space.cmd); - tp->esd_flag |= BIT_0; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); - if (io_base_l != tp->pci_cfg_space.io_base_l) { - printk(KERN_ERR "%s: io_base_l = 0x%04x, should be 0x%04x \n.", dev->name, io_base_l, tp->pci_cfg_space.io_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); - tp->esd_flag |= BIT_1; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); - if (mem_base_l != tp->pci_cfg_space.mem_base_l) { - printk(KERN_ERR "%s: mem_base_l = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_l, tp->pci_cfg_space.mem_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); - tp->esd_flag |= BIT_2; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); - if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { - printk(KERN_ERR "%s: mem_base_h = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_h, tp->pci_cfg_space.mem_base_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); - tp->esd_flag |= BIT_3; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); - if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { - printk(KERN_ERR "%s: resv_0x1c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_l, tp->pci_cfg_space.resv_0x1c_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); - tp->esd_flag |= BIT_4; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); - if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { - printk(KERN_ERR "%s: resv_0x1c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_h, tp->pci_cfg_space.resv_0x1c_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); - tp->esd_flag |= BIT_5; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &resv_0x20_l); - if (resv_0x20_l != tp->pci_cfg_space.resv_0x20_l) { - printk(KERN_ERR "%s: resv_0x20_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_l, tp->pci_cfg_space.resv_0x20_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4, tp->pci_cfg_space.resv_0x20_l); - tp->esd_flag |= BIT_6; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &resv_0x20_h); - if (resv_0x20_h != tp->pci_cfg_space.resv_0x20_h) { - printk(KERN_ERR "%s: resv_0x20_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_h, tp->pci_cfg_space.resv_0x20_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, tp->pci_cfg_space.resv_0x20_h); - tp->esd_flag |= BIT_7; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &resv_0x24_l); - if (resv_0x24_l != tp->pci_cfg_space.resv_0x24_l) { - printk(KERN_ERR "%s: resv_0x24_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_l, tp->pci_cfg_space.resv_0x24_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5, tp->pci_cfg_space.resv_0x24_l); - tp->esd_flag |= BIT_8; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &resv_0x24_h); - if (resv_0x24_h != tp->pci_cfg_space.resv_0x24_h) { - printk(KERN_ERR "%s: resv_0x24_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_h, tp->pci_cfg_space.resv_0x24_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, tp->pci_cfg_space.resv_0x24_h); - tp->esd_flag |= BIT_9; - } - - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); - if (ilr != tp->pci_cfg_space.ilr) { - printk(KERN_ERR "%s: ilr = 0x%02x, should be 0x%02x \n.", dev->name, ilr, tp->pci_cfg_space.ilr); - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); - tp->esd_flag |= BIT_10; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); - if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { - printk(KERN_ERR "%s: resv_0x2c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_l, tp->pci_cfg_space.resv_0x2c_l); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); - tp->esd_flag |= BIT_11; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); - if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { - printk(KERN_ERR "%s: resv_0x2c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_h, tp->pci_cfg_space.resv_0x2c_h); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); - tp->esd_flag |= BIT_12; - } - - if (tp->HwPcieSNOffset > 0) { - pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); - if (pci_sn_l != tp->pci_cfg_space.pci_sn_l) { - printk(KERN_ERR "%s: pci_sn_l = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_l, tp->pci_cfg_space.pci_sn_l); - rtl8125_csi_write(tp, tp->HwPcieSNOffset, tp->pci_cfg_space.pci_sn_l); - tp->esd_flag |= BIT_13; - } - - pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); - if (pci_sn_h != tp->pci_cfg_space.pci_sn_h) { - printk(KERN_ERR "%s: pci_sn_h = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_h, tp->pci_cfg_space.pci_sn_h); - rtl8125_csi_write(tp, tp->HwPcieSNOffset + 4, tp->pci_cfg_space.pci_sn_h); - tp->esd_flag |= BIT_14; - } - } - - if (tp->esd_flag != 0) { - printk(KERN_ERR "%s: esd_flag = 0x%04x\n.\n", dev->name, tp->esd_flag); - netif_tx_stop_all_queues(dev); - netif_carrier_off(dev); - rtl8125_hw_reset(dev); - rtl8125_tx_clear(tp); - rtl8125_rx_clear(tp); - rtl8125_init_ring(dev); - rtl8125_up(dev); - rtl8125_enable_hw_linkchg_interrupt(tp); - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - tp->esd_flag = 0; - } -} -/* -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8125_esd_timer(unsigned long __opaque) -#else -rtl8125_esd_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#else - struct rtl8125_private *tp = from_timer(tp, t, esd_timer); - //struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - rtl8125_esd_checker(tp); - - mod_timer(timer, jiffies + timeout); -} -*/ - -/* -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8125_link_timer(unsigned long __opaque) -#else -rtl8125_link_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; -#else - struct rtl8125_private *tp = from_timer(tp, t, link_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - rtl8125_check_link_status(dev); - - mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); -} -*/ - -int -rtl8125_enable_msix(struct rtl8125_private *tp) -{ - int i, nvecs = 0; - struct msix_entry msix_ent[R8125_MAX_MSIX_VEC]; - //struct net_device *dev = tp->dev; - //const int len = sizeof(tp->irq_tbl[0].name); - - for (i = 0; i < R8125_MAX_MSIX_VEC; i++) { - msix_ent[i].entry = i; - msix_ent[i].vector = 0; - } - - nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent, - tp->min_irq_nvecs, tp->max_irq_nvecs); - if (nvecs < 0) - goto out; - - for (i = 0; i < nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - irq->vector = msix_ent[i].vector; - //snprintf(irq->name, len, "%s-%d", dev->name, i); - //irq->handler = rtl8125_interrupt_msix; - } - -out: - return nvecs; -} - -void rtl8125_dump_msix_tbl(struct rtl8125_private *tp) -{ - void __iomem *ioaddr; - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(tp->pci_dev, 4), pci_resource_len(tp->pci_dev, 4)); - if (ioaddr) { - int i = 0; - for (i=0; iirq_nvecs; i++) { - printk("entry 0x%d %08X %08X %08X %08X \n", - i, - readl(ioaddr + 16 * i), - readl(ioaddr + 16 * i + 4), - readl(ioaddr + 16 * i + 8), - readl(ioaddr + 16 * i + 12)); - } - iounmap(ioaddr); - } -} - -/* Cfg9346_Unlock assumed. */ -static int rtl8125_try_msi(struct rtl8125_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - unsigned msi = 0; - int nvecs = 1; - - tp->max_irq_nvecs = 1; - tp->min_irq_nvecs = 1; -#ifndef DISABLE_MULTI_MSIX_VECTOR - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - tp->max_irq_nvecs = R8125_MAX_MSIX_VEC_8125B; - tp->min_irq_nvecs = R8125_MIN_MSIX_VEC_8125B; - break; - } -#endif - -#if defined(RTL_USE_NEW_INTR_API) - if ((nvecs = pci_alloc_irq_vectors(pdev, tp->min_irq_nvecs, tp->max_irq_nvecs, PCI_IRQ_MSIX)) > 0) - msi |= RTL_FEATURE_MSIX; - else if ((nvecs = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES)) > 0 && - pci_dev_msi_enabled(pdev)) - msi |= RTL_FEATURE_MSI; -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - if ((nvecs = rtl8125_enable_msix(tp)) > 0) - msi |= RTL_FEATURE_MSIX; - else if (!pci_enable_msi(pdev)) - msi |= RTL_FEATURE_MSI; -#endif - if (!(msi & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) - dev_info(&pdev->dev, "no MSI/MSI-X. Back to INTx.\n"); - - if (!(msi & RTL_FEATURE_MSIX) || nvecs < 1) - nvecs = 1; - - tp->irq_nvecs = nvecs; - - tp->features |= msi; - - return nvecs; -} - -static void rtl8125_disable_msi(struct pci_dev *pdev, struct rtl8125_private *tp) -{ -#if defined(RTL_USE_NEW_INTR_API) - if (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) - pci_free_irq_vectors(pdev); -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - if (tp->features & (RTL_FEATURE_MSIX)) - pci_disable_msix(pdev); - else if (tp->features & (RTL_FEATURE_MSI)) - pci_disable_msi(pdev); -#endif - tp->features &= ~(RTL_FEATURE_MSI | RTL_FEATURE_MSIX); -} - -static int rtl8125_get_irq(struct pci_dev *pdev) -{ -#if defined(RTL_USE_NEW_INTR_API) - return pci_irq_vector(pdev, 0); -#else - return pdev->irq; -#endif -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static const struct net_device_ops rtl8125_netdev_ops = { - .ndo_open = rtl8125_open, - .ndo_stop = rtl8125_close, - .ndo_get_stats = rtl8125_get_stats, - .ndo_start_xmit = rtl8125_start_xmit, - .ndo_tx_timeout = rtl8125_tx_timeout, - .ndo_change_mtu = rtl8125_change_mtu, - .ndo_set_mac_address = rtl8125_set_mac_address, - .ndo_do_ioctl = rtl8125_do_ioctl, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) - .ndo_set_multicast_list = rtl8125_set_rx_mode, -#else - .ndo_set_rx_mode = rtl8125_set_rx_mode, -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) -#ifdef CONFIG_R8125_VLAN - .ndo_vlan_rx_register = rtl8125_vlan_rx_register, -#endif -#else - .ndo_fix_features = rtl8125_fix_features, - .ndo_set_features = rtl8125_set_features, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8125_netpoll, -#endif -}; -#endif - - -#ifdef CONFIG_R8125_NAPI - -static int rtl8125_poll(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); - - for (i = 0; i < tp->num_tx_rings; i++) - rtl8125_tx_interrupt(&tp->tx_ring[i], budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - HandleDashInterrupt(tp->dev); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_switch_to_timer_interrupt(tp); - } - - return RTL_NAPI_RETURN_VALUE; -} - -#if 0 -static int rtl8125_poll_msix_ring(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - const int message_id = r8125napi->index; - - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); - - rtl8125_tx_interrupt_with_vector(tp, message_id, budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && message_id == 0) - HandleDashInterrupt(tp->dev); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} -#endif - -static int rtl8125_poll_msix_tx(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - const int message_id = r8125napi->index; - - //suppress unused variable - (void)(dev); - - rtl8125_tx_interrupt_with_vector(tp, message_id, budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} - -static int rtl8125_poll_msix_other(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - const int message_id = r8125napi->index; - - //suppress unused variable - (void)(dev); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); -#endif - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - - return 1; -} - -static int rtl8125_poll_msix_rx(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - const int message_id = r8125napi->index; - - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} - -static void rtl8125_enable_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_ENABLE(tp->dev, &tp->r8125napi[i].napi); -#endif -} - -static void rtl8125_disable_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_DISABLE(tp->dev, &tp->r8125napi[i].napi); -#endif -} - -static void rtl8125_del_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_DEL((&tp->r8125napi[i])); -#endif -} -#endif //CONFIG_R8125_NAPI - -static void rtl8125_init_napi(struct rtl8125_private *tp) -{ - int i; - - for (i=0; iirq_nvecs; i++) { - struct r8125_napi *r8125napi = &tp->r8125napi[i]; -#ifdef CONFIG_R8125_NAPI - int (*poll)(struct napi_struct *, int); - - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) { - if (i < R8125_MAX_RX_QUEUES_VEC_V3) - poll = rtl8125_poll_msix_rx; - else if (i == 16 || i == 18) - poll = rtl8125_poll_msix_tx; - else - poll = rtl8125_poll_msix_other; - } else { - poll = rtl8125_poll; - } - - RTL_NAPI_CONFIG(tp->dev, r8125napi, poll, R8125_NAPI_WEIGHT); -#endif - - r8125napi->priv = tp; - r8125napi->index = i; - } -} - -static int -rtl8125_set_real_num_queue(struct rtl8125_private *tp) -{ - int retval = 0; - - retval = netif_set_real_num_tx_queues(tp->dev, tp->num_tx_rings); - if (retval < 0) - goto exit; - - retval = netif_set_real_num_rx_queues(tp->dev, tp->num_rx_rings); - if (retval < 0) - goto exit; - -exit: - return retval; -} - -static int __devinit -rtl8125_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8125_private *tp; - void __iomem *ioaddr = NULL; - static int board_idx = -1; - - int rc; - - assert(pdev != NULL); - assert(ent != NULL); - - board_idx++; - - if (netif_msg_drv(&debug)) - printk(KERN_INFO "%s 2.5Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8125_VERSION); - - rc = rtl8125_init_board(pdev, &dev, &ioaddr); - if (rc) - goto out; - - tp = netdev_priv(dev); - assert(ioaddr != NULL); - - tp->set_speed = rtl8125_set_speed_xmii; - tp->get_settings = rtl8125_gset_xmii; - tp->phy_reset_enable = rtl8125_xmii_reset_enable; - tp->phy_reset_pending = rtl8125_xmii_reset_pending; - tp->link_ok = rtl8125_xmii_link_ok; - - rc = rtl8125_try_msi(tp); - if (rc < 0) { - dev_err(&pdev->dev, "Can't allocate interrupt\n"); - goto err_out_1; - } - - rtl8125_init_software_variable(dev); - - RTL_NET_DEVICE_OPS(rtl8125_netdev_ops); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - SET_ETHTOOL_OPS(dev, &rtl8125_ethtool_ops); -#endif - - dev->watchdog_timeo = RTL8125_TX_TIMEOUT; - dev->irq = rtl8125_get_irq(pdev); - dev->base_addr = (unsigned long) ioaddr; - - rtl8125_init_napi(tp); - -#ifdef CONFIG_R8125_VLAN - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - dev->vlan_rx_kill_vid = rtl8125_vlan_rx_kill_vid; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - } -#endif - - /* There has been a number of reports that using SG/TSO results in - * tx timeouts. However for a lot of people SG/TSO works fine. - * Therefore disable both features by default, but allow users to - * enable them. Use at own risk! - */ - tp->cp_cmd |= RTL_R16(tp, CPlusCmd); - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_IP_CSUM; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; - dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_HIGHDMA; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; - dev->features |= NETIF_F_IPV6_CSUM; - netif_set_gso_max_size(dev, LSO_64K); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO2; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) - dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -#ifdef ENABLE_RSS_SUPPORT - if (tp->EnableRss) { - dev->hw_features |= NETIF_F_RXHASH; - dev->features |= NETIF_F_RXHASH; - } -#endif - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - AllocateDashShareMemory(dev); -#endif - -#ifdef ENABLE_LIB_SUPPORT - ATOMIC_INIT_NOTIFIER_HEAD(&tp->lib_nh); -#endif - rtl8125_init_all_schedule_work(tp); - - rc = rtl8125_set_real_num_queue(tp); - if (rc < 0) - goto err_out; - - rtl8125_exit_oob(dev); - - rtl8125_powerup_pll(dev); - - rtl8125_hw_init(dev); - - rtl8125_hw_reset(dev); - - /* Get production from EEPROM */ - rtl8125_eeprom_type(tp); - - if (tp->eeprom_type == EEPROM_TYPE_93C46 || tp->eeprom_type == EEPROM_TYPE_93C56) - rtl8125_set_eeprom_sel_low(tp); - - rtl8125_get_mac_address(dev); - - tp->fw_name = rtl_chip_fw_infos[tp->mcfg].fw_name; - - tp->tally_vaddr = dma_alloc_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), - &tp->tally_paddr, GFP_KERNEL); - if (!tp->tally_vaddr) { - rc = -ENOMEM; - goto err_out; - } - - rtl8125_tally_counter_clear(tp); - - pci_set_drvdata(pdev, dev); - - rc = register_netdev(dev); - if (rc) - goto err_out; - - printk(KERN_INFO "%s: This product is covered by one or more of the following patents: US6,570,884, US6,115,776, and US6,327,625.\n", MODULENAME); - - rtl8125_disable_rxdvgate(dev); - - device_set_wakeup_enable(&pdev->dev, tp->wol_enabled); - - netif_carrier_off(dev); - - printk("%s", GPL_CLAIM); - -out: - return rc; - -err_out: - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, - tp->tally_paddr); - - tp->tally_vaddr = NULL; - } -#ifdef CONFIG_R8125_NAPI - rtl8125_del_napi(tp); -#endif - rtl8125_disable_msi(pdev, tp); - -err_out_1: - rtl8125_release_board(pdev, dev); - - goto out; -} - -static void __devexit -rtl8125_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8125_private *tp = netdev_priv(dev); - - assert(dev != NULL); - assert(tp != NULL); - - set_bit(R8125_FLAG_DOWN, tp->task_flags); - - rtl8125_cancel_all_schedule_work(tp); - -#ifdef CONFIG_R8125_NAPI - rtl8125_del_napi(tp); -#endif - if (tp->DASH) - rtl8125_driver_stop(tp); - - unregister_netdev(dev); - rtl8125_disable_msi(pdev, tp); -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_remove(dev); -#endif - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, tp->tally_paddr); - tp->tally_vaddr = NULL; - } - - rtl8125_release_board(pdev, dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8125_release_firmware(tp); -#endif - - pci_set_drvdata(pdev, NULL); -} - -static void -rtl8125_set_rxbufsize(struct rtl8125_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 + 1 : RX_BUF_SIZE; -} - -static void rtl8125_free_irq(struct rtl8125_private *tp) -{ - int i; - - for (i=0; iirq_nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - struct r8125_napi *r8125napi = &tp->r8125napi[i]; - - if (irq->requested) { - irq->requested = 0; -#if defined(RTL_USE_NEW_INTR_API) - pci_free_irq(tp->pci_dev, i, r8125napi); -#else - free_irq(irq->vector, r8125napi); -#endif - } - } -} - -static int rtl8125_alloc_irq(struct rtl8125_private *tp) -{ - struct net_device *dev = tp->dev; - int rc = 0; - struct r8125_irq *irq; - struct r8125_napi *r8125napi; - int i = 0; - const int len = sizeof(tp->irq_tbl[0].name); - -#if defined(RTL_USE_NEW_INTR_API) - for (i=0; iirq_nvecs; i++) { - irq = &tp->irq_tbl[i]; - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) - irq->handler = rtl8125_interrupt_msix; - else - irq->handler = rtl8125_interrupt; - - r8125napi = &tp->r8125napi[i]; - snprintf(irq->name, len, "%s-%d", dev->name, i); - rc = pci_request_irq(tp->pci_dev, i, irq->handler, NULL, r8125napi, - irq->name); - if (rc) - break; - - irq->vector = pci_irq_vector(tp->pci_dev, i); - irq->requested = 1; - } -#else - unsigned long irq_flags = 0; -#ifdef ENABLE_LIB_SUPPORT - irq_flags |= IRQF_NO_SUSPEND; -#endif - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) { - for (i=0; iirq_nvecs; i++) { - irq = &tp->irq_tbl[i]; - irq->handler = rtl8125_interrupt_msix; - r8125napi = &tp->r8125napi[i]; - snprintf(irq->name, len, "%s-%d", dev->name, i); - rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); - - if (rc) - break; - - irq->requested = 1; - } - } else { - irq = &tp->irq_tbl[0]; - irq->handler = rtl8125_interrupt; - r8125napi = &tp->r8125napi[0]; - snprintf(irq->name, len, "%s-0", dev->name); - if (!(tp->features & RTL_FEATURE_MSIX)) - irq->vector = dev->irq; - irq_flags |= (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) ? 0 : SA_SHIRQ; - rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); - - if (rc == 0) - irq->requested = 1; - } -#endif - if (rc) - rtl8125_free_irq(tp); - - return rc; -} - -static int rtl8125_alloc_tx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_tx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - ring = &tp->tx_ring[i]; - ring->TxDescArray = dma_alloc_coherent(&pdev->dev, R8125_TX_RING_BYTES, - &ring->TxPhyAddr, GFP_KERNEL); - - if (!ring->TxDescArray) - return -1; - } - - return 0; -} - -static int rtl8125_alloc_rx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_rx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - ring = &tp->rx_ring[i]; - ring->RxDescArray = dma_alloc_coherent(&pdev->dev, tp->RxDescRingLength, - &ring->RxPhyAddr, GFP_KERNEL); - - if (!ring->RxDescArray) - return -1; - } - - return 0; -} - -static void rtl8125_free_tx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_tx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - ring = &tp->tx_ring[i]; - if (ring->TxDescArray) { - dma_free_coherent(&pdev->dev, R8125_TX_RING_BYTES, ring->TxDescArray, - ring->TxPhyAddr); - ring->TxDescArray = NULL; - } - } -} - -static void rtl8125_free_rx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_rx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - ring = &tp->rx_ring[i]; - if (ring->RxDescArray) { - dma_free_coherent(&pdev->dev, tp->RxDescRingLength, ring->RxDescArray, - ring->RxPhyAddr); - ring->RxDescArray = NULL; - } - } -} - -static void rtl8125_free_alloc_resources(struct rtl8125_private *tp) -{ - rtl8125_free_rx_desc(tp); - - rtl8125_free_tx_desc(tp); -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8125_request_firmware(struct rtl8125_private *tp) -{ - struct rtl8125_fw *rtl_fw; - - /* firmware loaded already or no firmware available */ - if (tp->rtl_fw || !tp->fw_name) - return; - - rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); - if (!rtl_fw) - return; - - rtl_fw->phy_write = rtl8125_mdio_write; - rtl_fw->phy_read = rtl8125_mdio_read; - rtl_fw->mac_mcu_write = mac_mcu_write; - rtl_fw->mac_mcu_read = mac_mcu_read; - rtl_fw->fw_name = tp->fw_name; - rtl_fw->dev = tp_to_dev(tp); - - if (rtl8125_fw_request_firmware(rtl_fw)) - kfree(rtl_fw); - else - tp->rtl_fw = rtl_fw; -} -#endif - -int rtl8125_open(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int retval; - - retval = -ENOMEM; - -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_init(dev); -#endif - rtl8125_set_rxbufsize(tp, dev); - /* - * Rx and Tx descriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - if (rtl8125_alloc_tx_desc(tp) < 0 || rtl8125_alloc_rx_desc(tp) < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_init_ring(dev); - if (retval < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_alloc_irq(tp); - if (retval < 0) - goto err_free_all_allocated_mem; - - if (netif_msg_probe(tp)) { - printk(KERN_INFO "%s: 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); - } - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8125_request_firmware(tp); -#endif - pci_set_master(tp->pci_dev); - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif - - rtl8125_exit_oob(dev); - - rtl8125_up(dev); - -#ifdef ENABLE_PTP_SUPPORT - if (tp->EnablePtp) - rtl8125_ptp_init(tp); -#endif - clear_bit(R8125_FLAG_DOWN, tp->task_flags); - - if (tp->resume_not_chg_speed) - rtl8125_check_link_status(dev); - else - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - if (tp->esd_flag == 0) { - //rtl8125_request_esd_timer(dev); - - rtl8125_schedule_esd_work(tp); - } - - //rtl8125_request_link_timer(dev); - - rtl8125_enable_hw_linkchg_interrupt(tp); - -out: - - return retval; - -err_free_all_allocated_mem: - rtl8125_free_alloc_resources(tp); - - goto out; -} - -static void -set_offset70F(struct rtl8125_private *tp, u8 setting) -{ - u32 csi_tmp; - u32 temp = (u32)setting; - temp = temp << 24; - /*set PCI configuration space offset 0x70F to setting*/ - /*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/ - - csi_tmp = rtl8125_csi_read(tp, 0x70c) & 0x00ffffff; - rtl8125_csi_write(tp, 0x70c, csi_tmp | temp); -} - -static void -set_offset79(struct rtl8125_private *tp, u8 setting) -{ - //Set PCI configuration space offset 0x79 to setting - - struct pci_dev *pdev = tp->pci_dev; - u8 device_control; - - if (hwoptimize & HW_PATCH_SOC_LAN) return; - - pci_read_config_byte(pdev, 0x79, &device_control); - device_control &= ~0x70; - device_control |= setting; - pci_write_config_byte(pdev, 0x79, device_control); -} - -void -rtl8125_hw_set_rx_packet_filter(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#else - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#endif - } - - if (dev->features & NETIF_F_RXALL) - rx_mode |= (AcceptErr | AcceptRunt); - - tmp = mc_filter[0]; - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(tmp); - - tmp = tp->rtl8125_rx_config | rx_mode | (RTL_R32(tp, RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - RTL_W32(tp, RxConfig, tmp); - RTL_W32(tp, MAR0 + 0, mc_filter[0]); - RTL_W32(tp, MAR0 + 4, mc_filter[1]); -} - -static void -rtl8125_set_rx_mode(struct net_device *dev) -{ - rtl8125_hw_set_rx_packet_filter(dev); -} - -void -rtl8125_set_rx_q_num(struct rtl8125_private *tp, - unsigned int num_rx_queues) -{ - u16 q_ctrl; - u16 rx_q_num; - - rx_q_num = (u16)ilog2(num_rx_queues); - rx_q_num &= (BIT_0 | BIT_1 | BIT_2); - rx_q_num <<= 2; - q_ctrl = RTL_R16(tp, Q_NUM_CTRL_8125); - q_ctrl &= ~(BIT_2 | BIT_3 | BIT_4); - q_ctrl |= rx_q_num; - RTL_W16(tp, Q_NUM_CTRL_8125, q_ctrl); -} - -void -rtl8125_set_tx_q_num(struct rtl8125_private *tp, - unsigned int num_tx_queues) -{ - u16 mac_ocp_data; - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); - mac_ocp_data &= ~(BIT_11 | BIT_10); - mac_ocp_data |= ((ilog2(num_tx_queues) & 0x03) << 10); - rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); -} - -void -rtl8125_hw_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u16 mac_ocp_data; - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8125_hw_reset(dev); - - rtl8125_enable_cfg9346_write(tp); - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - break; - } - - //clear io_rdy_l23 - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_1); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - //IntMITI_0-IntMITI_31 - for (i=0xA00; i<0xB00; i+=4) - RTL_W32(tp, i, 0x00000000); - break; - } - - //keep magic packet only - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B6); - mac_ocp_data &= BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B6, mac_ocp_data); - break; - } - - rtl8125_tally_counter_addr_fill(tp); - - rtl8125_enable_extend_tally_couter(tp); - - rtl8125_desc_addr_fill(tp); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(tp, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - if (tp->EnableTxNoClose) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_6)); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - RTL_W16(tp, 0x382, 0x221B); - -#ifdef ENABLE_RSS_SUPPORT - rtl8125_config_rss(tp); -#else - RTL_W32(tp, RSS_CTRL_8125, 0x00); -#endif - rtl8125_set_rx_q_num(tp, rtl8125_tot_rx_rings(tp)); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); - - rtl8125_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8125_mac_ocp_write(tp, 0xC142, 0xFFFF); - - //new tx desc format - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB58); - mac_ocp_data |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xEB58, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE614); - mac_ocp_data &= ~( BIT_10 | BIT_9 | BIT_8); - if (tp->mcfg == CFG_METHOD_4 || tp->mcfg == CFG_METHOD_5) { - mac_ocp_data |= ((2 & 0x07) << 8); - } else { - if (tp->DASH && !(rtl8125_csi_fun0_read_byte(tp, 0x79) & BIT_0)) - mac_ocp_data |= ((3 & 0x07) << 8); - else - mac_ocp_data |= ((4 & 0x07) << 8); - } - rtl8125_mac_ocp_write(tp, 0xE614, mac_ocp_data); - - rtl8125_set_tx_q_num(tp, rtl8125_tot_tx_rings(tp)); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); - mac_ocp_data &= ~(BIT_5 | BIT_4); - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) - mac_ocp_data |= ((0x02 & 0x03) << 4); - rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); - mac_ocp_data &= ~BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - mac_ocp_data |= BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); - mac_ocp_data |= (BIT_3|BIT_2); - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB6A); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= (BIT_5 | BIT_4 | BIT_1 | BIT_0); - rtl8125_mac_ocp_write(tp, 0xEB6A, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB50); - mac_ocp_data &= ~(BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5); - mac_ocp_data |= (BIT_6); - rtl8125_mac_ocp_write(tp, 0xEB50, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE056); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); - //mac_ocp_data |= (BIT_4 | BIT_5); - rtl8125_mac_ocp_write(tp, 0xE056, mac_ocp_data); - - RTL_W8(tp, TDFNR, 0x10); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE040); - mac_ocp_data &= ~(BIT_12); - rtl8125_mac_ocp_write(tp, 0xE040, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); - mac_ocp_data &= ~(BIT_1 | BIT_0); - mac_ocp_data |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); - - rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4000); - - SetMcuAccessRegBit(tp, 0xE052, (BIT_6 | BIT_5)); - ClearMcuAccessRegBit(tp, 0xE052, BIT_3 | BIT_7); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xD430); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x45F; - rtl8125_mac_ocp_write(tp, 0xD430, mac_ocp_data); - - //rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4F87); - if (!tp->DASH) - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6 | BIT_7); - else - RTL_W8(tp, 0xD0, (RTL_R8(tp, 0xD0) & ~BIT_6) | BIT_7); - - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | BIT_0); - - rtl8125_disable_eee_plus(tp); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); - mac_ocp_data &= ~(BIT_2); - rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); - - SetMcuAccessRegBit(tp, 0xEB54, BIT_0); - udelay(1); - ClearMcuAccessRegBit(tp, 0xEB54, BIT_0); - RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~(BIT_4 | BIT_5)); - } - - /* csum offload command for RTL8125 */ - tp->tx_tcp_csum_cmd = TxTCPCS_C; - tp->tx_udp_csum_cmd = TxUDPCS_C; - tp->tx_ip_csum_cmd = TxIPCS_C; - tp->tx_ipv6_csum_cmd = TxIPV6F_C; - - /* config interrupt type for RTL8125B */ - if (tp->HwSuppIsrVer == 2) - rtl8125_hw_set_interrupt_type(tp, tp->HwCurrIsrVer); - - //other hw parameters - rtl8125_hw_clear_timer_int(dev); - - rtl8125_hw_clear_int_miti(dev); - - if (tp->use_timer_interrrupt && - (tp->HwCurrIsrVer == 2) && - (tp->HwSuppIntMitiVer == 4) && - (tp->features & RTL_FEATURE_MSIX)) { - int i; - for (i = 0; i < tp->irq_nvecs; i++) - rtl8125_hw_set_timer_int_8125(tp, i, timer_count_v2); - } - - rtl8125_enable_exit_l1_mask(tp); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - rtl8125_mac_ocp_write(tp, 0xE098, 0xC302); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (aspm) { - rtl8125_init_pci_offset_99(tp); - } - break; - } - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (aspm) { - rtl8125_init_pci_offset_180(tp); - } - break; - } - - tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | - Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | - ASF | Macdbgo_sel); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - RTL_W16(tp, CPlusCmd, tp->cp_cmd); -#else - rtl8125_hw_set_features(dev, dev->features); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: { - int timeout; - for (timeout = 0; timeout < 10; timeout++) { - if ((rtl8125_mac_ocp_read(tp, 0xE00E) & BIT_13)==0) - break; - mdelay(1); - } - } - break; - } - - RTL_W16(tp, RxMaxSize, tp->rx_buf_sz); - - rtl8125_disable_rxdvgate(dev); - - if (!tp->pci_cfg_is_read) { - pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); - if (tp->HwPcieSNOffset > 0) { - tp->pci_cfg_space.pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); - tp->pci_cfg_space.pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); - } - - tp->pci_cfg_is_read = 1; - } - - /* Set Rx packet filter */ - rtl8125_hw_set_rx_packet_filter(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && !tp->dash_printer_enabled) - NICChkTypeEnableDashInterrupt(tp); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - if (aspm) { - RTL_W8(tp, Config5, RTL_R8(tp, Config5) | BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | BIT_7); - } else { - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - } - break; - } - - rtl8125_disable_cfg9346_write(tp); - - udelay(10); -} - -void -rtl8125_hw_start(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl8125_enable_hw_interrupt(tp); - - rtl8125_lib_reset_complete(tp); -} - -static int -rtl8125_change_mtu(struct net_device *dev, - int new_mtu) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = 0; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - if (new_mtu < ETH_MIN_MTU) - return -EINVAL; - else if (new_mtu > tp->max_jumbo_frame_size) - new_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8125_down(dev); - - rtl8125_set_rxbufsize(tp, dev); - - ret = rtl8125_init_ring(dev); - - if (ret < 0) - goto err_out; - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif//CONFIG_R8125_NAPI - - //netif_tx_stop_all_queues(dev); - //netif_carrier_off(dev); - rtl8125_hw_config(dev); - rtl8125_enable_hw_linkchg_interrupt(tp); - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); - //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); -out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - netdev_update_features(dev); -#endif - -err_out: - return ret; -} - -static void -rtl8125_free_rx_skb(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - struct RxDesc *desc, - const u32 cur_rx) -{ - struct pci_dev *pdev = tp->pci_dev; - - dma_unmap_single(&pdev->dev, ring->RxDescPhyAddr[cur_rx], tp->rx_buf_sz, - DMA_FROM_DEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8125_make_unusable_by_asic(tp, desc); -} - -static inline void -rtl8125_mark_to_asic_v3(struct RxDescV3 *descv3, - u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1) & RingEnd; - - WRITE_ONCE(descv3->RxDescNormalDDWord4.opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); -} - -void -rtl8125_mark_to_asic(struct rtl8125_private *tp, - struct RxDesc *desc, - u32 rx_buf_sz) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_mark_to_asic_v3((struct RxDescV3 *)desc, rx_buf_sz); - else { - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); - } -} - -static inline void -rtl8125_map_to_asic(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct RxDesc *desc, - dma_addr_t mapping, - u32 rx_buf_sz, - const u32 cur_rx) -{ - ring->RxDescPhyAddr[cur_rx] = mapping; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - ((struct RxDescV3 *)desc)->addr = cpu_to_le64(mapping); - else - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8125_mark_to_asic(tp, desc, rx_buf_sz); -} - -static int -rtl8125_alloc_rx_skb(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - struct RxDesc *desc, - int rx_buf_sz, - const u32 cur_rx, - u8 in_intr) -{ - struct sk_buff *skb; - dma_addr_t mapping; - int ret = 0; - - if (in_intr) - skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, rx_buf_sz + RTK_RX_ALIGN); - else - skb = dev_alloc_skb(rx_buf_sz + RTK_RX_ALIGN); - - if (unlikely(!skb)) - goto err_out; - - skb_reserve(skb, RTK_RX_ALIGN); - - mapping = dma_map_single(tp_to_dev(tp), skb->data, rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - *sk_buff = skb; - rtl8125_map_to_asic(tp, ring, desc, mapping, rx_buf_sz, cur_rx); -out: - return ret; - -err_out: - if (skb) - dev_kfree_skb(skb); - ret = -ENOMEM; - rtl8125_make_unusable_by_asic(tp, desc); - goto out; -} - -static void -_rtl8125_rx_clear(struct rtl8125_private *tp, struct rtl8125_rx_ring *ring) -{ - int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (ring->Rx_skbuff[i]) { - rtl8125_free_rx_skb(tp, - ring, - ring->Rx_skbuff + i, - rtl8125_get_rxdesc(tp, ring->RxDescArray, i), - i); - ring->Rx_skbuff[i] = NULL; - } - } -} - -void -rtl8125_rx_clear(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_rx_rings; i++) - _rtl8125_rx_clear(tp, &tp->rx_ring[i]); -} - -static u32 -rtl8125_rx_fill(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct net_device *dev, - u32 start, - u32 end, - u8 in_intr) -{ - u32 cur; - - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % NUM_RX_DESC; - - if (ring->Rx_skbuff[i]) - continue; - - ret = rtl8125_alloc_rx_skb(tp, - ring, - ring->Rx_skbuff + i, - rtl8125_get_rxdesc(tp, ring->RxDescArray, i), - tp->rx_buf_sz, - i, - in_intr - ); - if (ret < 0) - break; - } - return cur - start; -} - -static inline void -rtl8125_mark_as_last_descriptor_8125(struct RxDescV3 *descv3) -{ - descv3->RxDescNormalDDWord4.opts1 |= cpu_to_le32(RingEnd); -} - -static inline void -rtl8125_mark_as_last_descriptor(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_mark_as_last_descriptor_8125((struct RxDescV3 *)desc); - else - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void -rtl8125_desc_addr_fill(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - RTL_W32(tp, ring->tdsar_reg, ((u64)ring->TxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, ring->tdsar_reg + 4, ((u64)ring->TxPhyAddr >> 32)); - } - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - RTL_W32(tp, ring->rdsar_reg, ((u64)ring->RxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, ring->rdsar_reg + 4, ((u64)ring->RxPhyAddr >> 32)); - } -} - -static void -rtl8125_tx_desc_init(struct rtl8125_private *tp) -{ - int i = 0; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - memset(ring->TxDescArray, 0x0, R8125_TX_RING_BYTES); - - ring->TxDescArray[NUM_TX_DESC - 1].opts1 = cpu_to_le32(RingEnd); - } -} - -static void -rtl8125_rx_desc_init(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - memset(ring->RxDescArray, 0x0, tp->RxDescRingLength); - } -} - -int -rtl8125_init_ring(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - rtl8125_init_ring_indexes(tp); - - rtl8125_tx_desc_init(tp); - rtl8125_rx_desc_init(tp); - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - memset(ring->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - } - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - - memset(ring->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - if (rtl8125_rx_fill(tp, ring, dev, 0, NUM_RX_DESC, 0) != NUM_RX_DESC) - goto err_out; - - rtl8125_mark_as_last_descriptor(tp, rtl8125_get_rxdesc(tp, ring->RxDescArray, NUM_RX_DESC - 1)); - } - - return 0; - -err_out: - rtl8125_rx_clear(tp); - return -ENOMEM; -} - -static void -rtl8125_unmap_tx_skb(struct pci_dev *pdev, - struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = cpu_to_le32(RTK_MAGIC_DEBUG_VALUE); - desc->opts2 = 0x00; - desc->addr = RTL8125_MAGIC_NUMBER; - tx_skb->len = 0; -} - -static void -rtl8125_tx_clear_range(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring, - u32 start, - unsigned int n) -{ - unsigned int i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - struct net_device *dev = tp->dev; -#endif - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = ring->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8125_unmap_tx_skb(tp->pci_dev, tx_skb, - ring->TxDescArray + entry); - if (skb) { - RTLDEV->stats.tx_dropped++; - dev_kfree_skb_any(skb); - tx_skb->skb = NULL; - } - } - } -} - -void -rtl8125_tx_clear(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - rtl8125_tx_clear_range(tp, ring, ring->dirty_tx, NUM_TX_DESC); - ring->cur_tx = ring->dirty_tx = 0; - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); - schedule_delayed_work(&tp->reset_task, 4); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->linkchg_task, 4); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -#define rtl8125_cancel_schedule_reset_work(a) -#define rtl8125_cancel_schedule_esd_work(a) -#define rtl8125_cancel_schedule_linkchg_work(a) - -#else -static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) -{ - set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); - schedule_delayed_work(&tp->reset_task, 4); -} - -static void rtl8125_cancel_schedule_reset_work(struct rtl8125_private *tp) -{ - struct work_struct *work = &tp->reset_task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->reset_task); -} - -static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) -{ - set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); -} - -static void rtl8125_cancel_schedule_esd_work(struct rtl8125_private *tp) -{ - struct work_struct *work = &tp->esd_task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->esd_task); -} - -static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) -{ - set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->linkchg_task, RTL8125_ESD_TIMEOUT); -} - -static void rtl8125_cancel_schedule_linkchg_work(struct rtl8125_private *tp) -{ - struct work_struct *work = &tp->linkchg_task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->linkchg_task); -} -#endif - -static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&tp->reset_task, rtl8125_reset_task, dev); - INIT_WORK(&tp->esd_task, rtl8125_esd_task, dev); - INIT_WORK(&tp->linkchg_task, rtl8125_linkchg_task, dev); -#else - INIT_DELAYED_WORK(&tp->reset_task, rtl8125_reset_task); - INIT_DELAYED_WORK(&tp->esd_task, rtl8125_esd_task); - INIT_DELAYED_WORK(&tp->linkchg_task, rtl8125_linkchg_task); -#endif -} - -static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp) -{ - rtl8125_cancel_schedule_reset_work(tp); - rtl8125_cancel_schedule_esd_work(tp); - rtl8125_cancel_schedule_linkchg_work(tp); -} - -static void -rtl8125_wait_for_irq_complete(struct rtl8125_private *tp) -{ - if (tp->features & RTL_FEATURE_MSIX) { - int i; - for (i = 0; i < tp->irq_nvecs; i++) - synchronize_irq(tp->irq_tbl[i].vector); - } else { - synchronize_irq(tp->dev->irq); - } -} - -static void -_rtl8125_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8125_NAPI - rtl8125_disable_napi(tp); -#endif//CONFIG_R8125_NAPI - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_net(); -#endif - - rtl8125_irq_mask_and_ack(tp); - - rtl8125_wait_for_irq_complete(tp); -} - -static void -rtl8125_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - //suppress unused variable - (void)(tp); - - _rtl8125_wait_for_quiescence(dev); - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif//CONFIG_R8125_NAPI -} - -static int rtl8125_rx_nostuck(struct rtl8125_private *tp) -{ - int i, ret = 1; - for (i = 0; i < tp->num_rx_rings; i++) - ret &= (tp->rx_ring[i].dirty_rx == tp->rx_ring[i].cur_rx); - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_reset_task(void *_data) -{ - struct net_device *dev = _data; - struct rtl8125_private *tp = netdev_priv(dev); -#else -static void rtl8125_reset_task(struct work_struct *work) -{ - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, reset_task.work); - struct net_device *dev = tp->dev; -#endif - u32 budget = ~(u32)0; - int i; - - rtnl_lock(); - - if (!netif_running(dev) || - test_bit(R8125_FLAG_DOWN, tp->task_flags) || - !test_and_clear_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags)) - goto out_unlock; - - rtl8125_wait_for_quiescence(dev); - - for (i = 0; i < tp->num_rx_rings; i++) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - } - - netif_tx_stop_all_queues(dev); - netif_carrier_off(dev); - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - if (rtl8125_rx_nostuck(tp)) { - rtl8125_rx_clear(tp); - rtl8125_init_ring(dev); -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_reset(tp); -#endif - if (tp->resume_not_chg_speed) { - _rtl8125_check_link_status(dev); - - tp->resume_not_chg_speed = 0; - } else { - rtl8125_enable_hw_linkchg_interrupt(tp); - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - } - } else { - if (unlikely(net_ratelimit())) { - struct rtl8125_private *tp = netdev_priv(dev); - - if (netif_msg_intr(tp)) { - printk(PFX KERN_EMERG - "%s: Rx buffers shortage\n", dev->name); - } - } - rtl8125_schedule_reset_work(tp); - } - -out_unlock: - rtnl_unlock(); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_esd_task(void *_data) -{ - struct net_device *dev = _data; - struct rtl8125_private *tp = netdev_priv(dev); -#else -static void rtl8125_esd_task(struct work_struct *work) -{ - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, esd_task.work); - struct net_device *dev = tp->dev; -#endif - rtnl_lock(); - - if (!netif_running(dev) || - test_bit(R8125_FLAG_DOWN, tp->task_flags) || - !test_and_clear_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags)) - goto out_unlock; - - rtl8125_esd_checker(tp); - - rtl8125_schedule_esd_work(tp); - -out_unlock: - rtnl_unlock(); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_linkchg_task(void *_data) -{ - struct net_device *dev = _data; - //struct rtl8125_private *tp = netdev_priv(dev); -#else -static void rtl8125_linkchg_task(struct work_struct *work) -{ - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, linkchg_task.work); - struct net_device *dev = tp->dev; -#endif - rtnl_lock(); - - if (!netif_running(dev) || - test_bit(R8125_FLAG_DOWN, tp->task_flags) || - !test_and_clear_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags)) - goto out_unlock; - - rtl8125_check_link_status(dev); - -out_unlock: - rtnl_unlock(); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void -rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue) -#else -static void -rtl8125_tx_timeout(struct net_device *dev) -#endif -{ - struct rtl8125_private *tp = netdev_priv(dev); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8125_schedule_reset_work(tp); -} - -static u32 -rtl8125_get_txd_opts1(u32 opts1, u32 len, unsigned int entry) -{ - u32 status = opts1 | len; - - if (entry == NUM_TX_DESC - 1) - status |= RingEnd; - - return status; -} - -static int -rtl8125_xmit_frags(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring, - struct sk_buff *skb, - const u32 *opts) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc *txd = NULL; - const unsigned char nr_frags = info->nr_frags; - unsigned long PktLenCnt = 0; - bool LsoPatchEnabled = FALSE; - - entry = ring->cur_tx; - for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = ring->TxDescArray + entry; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; -#else - len = skb_frag_size(frag); - addr = skb_frag_address(frag); -#endif - if (tp->RequireLSOPatch && - (cur_frag == nr_frags - 1) && - (opts[0] & (GiantSendv4|GiantSendv6)) && - PktLenCnt < ETH_FRAME_LEN && - len > 1) { - len -= 1; - mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8125_get_txd_opts1(opts[0], len, entry); - - txd->addr = cpu_to_le64(mapping); - - ring->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - - //second txd - addr += len; - len = 1; - entry = (entry + 1) % NUM_TX_DESC; - txd = ring->TxDescArray + entry; - cur_frag += 1; - - LsoPatchEnabled = TRUE; - } - - mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8125_get_txd_opts1(opts[0], len, entry); - if (cur_frag == (nr_frags - 1) || LsoPatchEnabled == TRUE) { - //ring->tx_skb[entry].skb = skb; - status |= LastFrag; - } - - txd->addr = cpu_to_le64(mapping); - - ring->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - - PktLenCnt += len; - } - - return cur_frag; - -err_out: - rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, cur_frag); - return -EIO; -} - -static inline -__be16 get_protocol(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) - return vlan_get_protocol(skb); -#else - __be16 protocol; - - if (skb->protocol == htons(ETH_P_8021Q)) - protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; - else - protocol = skb->protocol; - - return protocol; -#endif -} - -static inline -u8 rtl8125_get_l4_protocol(struct sk_buff *skb) -{ - int no = skb_network_offset(skb); - struct ipv6hdr *i6h, _i6h; - struct iphdr *ih, _ih; - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih); - if (ih) - ip_protocol = ih->protocol; - break; - case __constant_htons(ETH_P_IPV6): - i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h); - if (i6h) - ip_protocol = i6h->nexthdr; - break; - } - - return ip_protocol; -} - -static bool rtl8125_skb_pad_with_len(struct sk_buff *skb, unsigned int len) -{ - if (skb_padto(skb, len)) - return false; - skb_put(skb, len - skb->len); - return true; -} - -static bool rtl8125_skb_pad(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) - return rtl8125_skb_pad_with_len(skb, ETH_ZLEN); -#else - return !eth_skb_pad(skb); -#endif -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -/* msdn_giant_send_check() - * According to the document of microsoft, the TCP Pseudo Header excludes the - * packet length for IPv6 TCP large packets. - */ -static int msdn_giant_send_check(struct sk_buff *skb) -{ - const struct ipv6hdr *ipv6h; - struct tcphdr *th; - int ret; - - ret = skb_cow_head(skb, 0); - if (ret) - return ret; - - ipv6h = ipv6_hdr(skb); - th = tcp_hdr(skb); - - th->check = 0; - th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); - - return ret; -} -#endif - -#define MIN_PATCH_LEN (47) -static u32 -rtl8125_get_patch_pad_len(struct sk_buff *skb) -{ - u32 pad_len = 0; - int trans_data_len; - u32 hdr_len; - u32 pkt_len = skb->len; - u8 ip_protocol; - bool has_trans = skb_transport_header_was_set(skb); - - if (!(has_trans && (pkt_len < 175))) //128 + MIN_PATCH_LEN - goto no_padding; - - ip_protocol = rtl8125_get_l4_protocol(skb); - if (!(ip_protocol == IPPROTO_TCP || ip_protocol == IPPROTO_UDP)) - goto no_padding; - - trans_data_len = pkt_len - - (skb->transport_header - - skb_headroom(skb)); - if (ip_protocol == IPPROTO_UDP) { - if (trans_data_len > 3 && trans_data_len < MIN_PATCH_LEN) { - u16 dest_port = 0; - - skb_copy_bits(skb, skb->transport_header - skb_headroom(skb) + 2, &dest_port, 2); - dest_port = ntohs(dest_port); - - if (dest_port == 0x13f || - dest_port == 0x140) { - pad_len = MIN_PATCH_LEN - trans_data_len; - goto out; - } - } - } - - hdr_len = 0; - if (ip_protocol == IPPROTO_TCP) - hdr_len = 20; - else if (ip_protocol == IPPROTO_UDP) - hdr_len = 8; - if (trans_data_len < hdr_len) - pad_len = hdr_len - trans_data_len; - -out: - if ((pkt_len + pad_len) < ETH_ZLEN) - pad_len = ETH_ZLEN - pkt_len; - - return pad_len; - -no_padding: - - return 0; -} - -static bool -rtl8125_tso_csum(struct sk_buff *skb, - struct net_device *dev, - u32 *opts) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long large_send = 0; - u32 csum_cmd = 0; - u8 sw_calc_csum = false; - u8 check_patch_required = true; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - u32 mss = skb_shinfo(skb)->tso_size; -#else - u32 mss = skb_shinfo(skb)->gso_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - - /* TCP Segmentation Offload (or TCP Large Send) */ - if (mss) { - u32 transport_offset = (u32)skb_transport_offset(skb); - assert((transport_offset%2) == 0); - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv4; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - case __constant_htons(ETH_P_IPV6): -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - if (msdn_giant_send_check(skb)) - return false; -#endif - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv6; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("tso proto=%x!\n", skb->protocol); - break; - } - - if (large_send == 0) - return false; - - return true; - } - } -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - const struct iphdr *ip = skb->nh.iph; - - if (dev->features & NETIF_F_IP_CSUM) { - if (ip->protocol == IPPROTO_TCP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_tcp_csum_cmd; - else if (ip->protocol == IPPROTO_UDP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_udp_csum_cmd; - else if (ip->protocol == IPPROTO_IP) - csum_cmd = tp->tx_ip_csum_cmd; - } -#else - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (dev->features & NETIF_F_IP_CSUM) { - ip_protocol = ip_hdr(skb)->protocol; - csum_cmd = tp->tx_ip_csum_cmd; - } - break; - case __constant_htons(ETH_P_IPV6): - if (dev->features & NETIF_F_IPV6_CSUM) { - u32 transport_offset = (u32)skb_transport_offset(skb); - if (transport_offset > 0 && transport_offset <= TCPHO_MAX) { - ip_protocol = ipv6_hdr(skb)->nexthdr; - csum_cmd = tp->tx_ipv6_csum_cmd; - csum_cmd |= transport_offset << TCPHO_SHIFT; - } - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("checksum_partial proto=%x!\n", skb->protocol); - break; - } - - if (ip_protocol == IPPROTO_TCP) - csum_cmd |= tp->tx_tcp_csum_cmd; - else if (ip_protocol == IPPROTO_UDP) - csum_cmd |= tp->tx_udp_csum_cmd; -#endif - if (csum_cmd == 0) { - sw_calc_csum = true; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - WARN_ON(1); /* we need a WARN() */ -#endif - } - - if (ip_protocol == IPPROTO_TCP) - check_patch_required = false; - } - - if (check_patch_required) { - u32 pad_len = rtl8125_get_patch_pad_len(skb); - - if (pad_len > 0) { - if (!rtl8125_skb_pad_with_len(skb, skb->len + pad_len)) - return false; - - if (csum_cmd != 0) - sw_calc_csum = true; - } - } - - if (skb->len < ETH_ZLEN) { - if (tp->UseSwPaddingShortPkt || - (tp->ShortPacketSwChecksum && csum_cmd != 0)) { - if (!rtl8125_skb_pad(skb)) - return false; - - if (csum_cmd != 0) - sw_calc_csum = true; - } - } - - if (sw_calc_csum) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) - skb_checksum_help(&skb, 0); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - skb_checksum_help(skb, 0); -#else - skb_checksum_help(skb); -#endif - } else - opts[1] |= csum_cmd; - - return true; -} - -static bool rtl8125_tx_slots_avail(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring) -{ - unsigned int slots_avail = READ_ONCE(ring->dirty_tx) + NUM_TX_DESC - - READ_ONCE(ring->cur_tx); - - /* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ - return slots_avail > MAX_SKB_FRAGS; -} - -static netdev_tx_t -rtl8125_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int entry; - struct TxDesc *txd; - dma_addr_t mapping; - u32 len; - u32 opts[2]; - netdev_tx_t ret = NETDEV_TX_OK; - int frags; - u8 EnableTxNoClose = tp->EnableTxNoClose; - const u16 queue_mapping = skb_get_queue_mapping(skb); - struct rtl8125_tx_ring *ring; - bool stop_queue; - - assert(queue_mapping < tp->num_tx_queues); - - ring = &tp->tx_ring[queue_mapping]; - - if (unlikely(!rtl8125_tx_slots_avail(tp, ring))) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring[%d] full when queue awake!\n", - dev->name, - queue_mapping); - } - goto err_stop; - } - - entry = ring->cur_tx % NUM_TX_DESC; - txd = ring->TxDescArray + entry; - - if (!EnableTxNoClose) { - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Desc is own by hardware!\n", - dev->name); - } - goto err_stop; - } - } - - opts[0] = DescOwn; - opts[1] = rtl8125_tx_vlan_tag(tp, skb); - - if (unlikely(!rtl8125_tso_csum(skb, dev, opts))) - goto err_dma_0; - - frags = rtl8125_xmit_frags(tp, ring, skb, opts); - if (unlikely(frags < 0)) - goto err_dma_0; - if (frags) { - len = skb_headlen(skb); - opts[0] |= FirstFrag; - } else { - len = skb->len; - - //ring->tx_skb[entry].skb = skb; - - opts[0] |= FirstFrag | LastFrag; - } - - opts[0] = rtl8125_get_txd_opts1(opts[0], len, entry); - mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_1; - } - ring->tx_skb[entry].len = len; -#ifdef ENABLE_PTP_SUPPORT - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { - if (tp->hwtstamp_config.tx_type == HWTSTAMP_TX_ON && - !tp->ptp_tx_skb) { - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - - tp->ptp_tx_skb = skb_get(skb); - tp->ptp_tx_start = jiffies; - schedule_work(&tp->ptp_tx_work); - } else { - tp->tx_hwtstamp_skipped++; - } - } -#endif - ring->tx_skb[entry].skb = skb; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(opts[0]); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - dev->trans_start = jiffies; -#else - skb_tx_timestamp(skb); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - - /* rtl_tx needs to see descriptor changes before updated tp->cur_tx */ - smp_wmb(); - - WRITE_ONCE(ring->cur_tx, ring->cur_tx + frags + 1); - - stop_queue = !rtl8125_tx_slots_avail(tp, ring); - if (unlikely(stop_queue)) { - /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must - * not miss a ring update when it notices a stopped queue. - */ - smp_wmb(); - netif_stop_subqueue(dev, queue_mapping); - } - - if (EnableTxNoClose) - RTL_W16(tp, ring->sw_tail_ptr_reg, ring->cur_tx % MAX_TX_NO_CLOSE_DESC_PTR_V2); - else - RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); /* set polling bit */ - - if (unlikely(stop_queue)) { - /* Sync with rtl_tx: - * - publish queue status and cur_tx ring index (write barrier) - * - refresh dirty_tx ring index (read barrier). - * May the current thread have a pessimistic view of the ring - * status and forget to wake up queue, a racing rtl_tx thread - * can't. - */ - smp_mb(); - if (rtl8125_tx_slots_avail(tp, ring)) - netif_start_subqueue(dev, queue_mapping); - } -out: - return ret; -err_dma_1: - ring->tx_skb[entry].skb = NULL; - rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, frags); -err_dma_0: - RTLDEV->stats.tx_dropped++; - dev_kfree_skb_any(skb); - ret = NETDEV_TX_OK; - goto out; -err_stop: - netif_stop_subqueue(dev, queue_mapping); - ret = NETDEV_TX_BUSY; - RTLDEV->stats.tx_dropped++; - goto out; -} - -static inline u32 -rtl8125_fast_mod(const u32 input, const u32 ceil) -{ - return input >= ceil ? input % ceil : input; -} - -static int -rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget) -{ - struct rtl8125_private *tp = ring->priv; - struct net_device *dev = tp->dev; - unsigned int dirty_tx, tx_left; - unsigned int count = 0; - u8 EnableTxNoClose = tp->EnableTxNoClose; - - dirty_tx = ring->dirty_tx; - smp_rmb(); - tx_left = READ_ONCE(ring->cur_tx) - dirty_tx; - if (EnableTxNoClose) { - unsigned int tx_desc_closed; - u32 NextHwDesCloPtr = RTL_R16(tp, ring->hw_clo_ptr_reg); - ring->NextHwDesCloPtr = NextHwDesCloPtr; - smp_rmb(); - tx_desc_closed = rtl8125_fast_mod(NextHwDesCloPtr - ring->BeginHwDesCloPtr, MAX_TX_NO_CLOSE_DESC_PTR_V2); - if(tx_left > tx_desc_closed) tx_left = tx_desc_closed; - ring->BeginHwDesCloPtr = NextHwDesCloPtr; - } - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = ring->tx_skb + entry; - - if (!EnableTxNoClose && - (le32_to_cpu(ring->TxDescArray[entry].opts1) & DescOwn)) - break; - - RTLDEV->stats.tx_bytes += tx_skb->len; - RTLDEV->stats.tx_packets++; - - rtl8125_unmap_tx_skb(tp->pci_dev, - tx_skb, - ring->TxDescArray + entry); - - if (tx_skb->skb != NULL) { - RTL_NAPI_CONSUME_SKB_ANY(tx_skb->skb, budget); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (ring->dirty_tx != dirty_tx) { - count = dirty_tx - ring->dirty_tx; - WRITE_ONCE(ring->dirty_tx, dirty_tx); - smp_wmb(); - if (__netif_subqueue_stopped(dev, ring->index) && - (rtl8125_tx_slots_avail(tp, ring))) { - netif_start_subqueue(dev, ring->index); - } - smp_rmb(); - if (!EnableTxNoClose && (ring->cur_tx != dirty_tx)) { - RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); - } - } - - return count; -} - -static int -rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, - const int message_id, - int budget) -{ - int count = 0; - - if (message_id == 16) - count += rtl8125_tx_interrupt(&tp->tx_ring[0], budget); -#ifdef ENABLE_MULTIPLE_TX_QUEUE - else if (message_id == 18) - count += rtl8125_tx_interrupt(&tp->tx_ring[1], budget); -#endif - - return count; -} - -static inline int -rtl8125_fragmented_frame(struct rtl8125_private *tp, u32 status) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return (status & (FirstFrag_V3 | LastFrag_V3)) != (FirstFrag_V3 | LastFrag_V3); - else - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline int -rtl8125_rx_desc_type(u32 status) -{ - return ((status >> 26) & 0x0F); -} - -static inline void -rtl8125_rx_v3_csum(struct rtl8125_private *tp, - struct sk_buff *skb, - struct RxDescV3 *descv3) -{ - //u32 opts1 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1); - u32 opts2 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts2); - - /* rx csum offload for RTL8125 */ - if (((opts2 & RxV4F_v3) && !(opts2 & RxIPF_v3)) || (opts2 & RxV6F_v3)) { - if (((opts2 & RxTCPT_v3) && !(opts2 & RxTCPF_v3)) || - ((opts2 & RxUDPT_v3) && !(opts2 & RxUDPF_v3))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline void -rtl8125_rx_csum(struct rtl8125_private *tp, - struct sk_buff *skb, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_rx_v3_csum(tp, skb, (struct RxDescV3 *)desc); - else { - u32 opts1 = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); - u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); - - /* rx csum offload for RTL8125 */ - if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) { - if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) || - ((opts1 & RxUDPT) && !(opts1 & RxUDPF))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; - } -} - -static inline int -rtl8125_try_rx_copy(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - int pkt_size, - struct RxDesc *desc, - int rx_buf_sz) -{ - int ret = -1; - - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; - - skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, pkt_size + RTK_RX_ALIGN); - if (skb) { - u8 *data; - - data = sk_buff[0]->data; - skb_reserve(skb, RTK_RX_ALIGN); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(data - RTK_RX_ALIGN); -#endif - eth_copy_and_sum(skb, data, pkt_size, 0); - *sk_buff = skb; - rtl8125_mark_to_asic(tp, desc, rx_buf_sz); - ret = 0; - } - } - return ret; -} - -static inline void -rtl8125_rx_skb(struct rtl8125_private *tp, - struct sk_buff *skb, - u32 ring_index) -{ -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - netif_receive_skb(skb); -#else - napi_gro_receive(&tp->r8125napi[ring_index].napi, skb); -#endif -#else - netif_rx(skb); -#endif -} - -static int -rtl8125_check_rx_desc_error(struct net_device *dev, - struct rtl8125_private *tp, - u32 status) -{ - int ret = 0; - - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { - if (unlikely(status & RxRES_V3)) { - if (status & (RxRWT_V3 | RxRUNT_V3)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC_V3) - RTLDEV->stats.rx_crc_errors++; - - ret = -1; - } - } else { - if (unlikely(status & RxRES)) { - if (status & (RxRWT | RxRUNT)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC) - RTLDEV->stats.rx_crc_errors++; - - ret = -1; - } - } - - return ret; -} - -static int -rtl8125_rx_interrupt(struct net_device *dev, - struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - napi_budget budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count = 0; - unsigned int entry; - struct RxDesc *desc; - u32 status; - u32 rx_quota; - u64 rx_buf_phy_addr; - u32 ring_index = ring->index; - - assert(dev != NULL); - assert(tp != NULL); - - if ((ring->RxDescArray == NULL)) - goto rx_out; - - rx_quota = RTL_RX_QUOTA(budget); - cur_rx = ring->cur_rx; - entry = cur_rx % NUM_RX_DESC; - desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); - rx_left = NUM_RX_DESC + ring->dirty_rx - cur_rx; - rx_left = rtl8125_rx_quota(rx_left, (u32)rx_quota); - - for (; rx_left > 0; rx_left--) { - rmb(); - status = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); - if (status & DescOwn) - break; - - if (unlikely(rtl8125_check_rx_desc_error(dev, tp, status) < 0)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - - RTLDEV->stats.rx_errors++; - - if (dev->features & NETIF_F_RXALL) - goto process_pkt; - - rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb; - int pkt_size; - -process_pkt: - if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8125_fragmented_frame(tp, status))) { - RTLDEV->stats.rx_dropped++; - RTLDEV->stats.rx_length_errors++; - rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); - continue; - } - - skb = ring->Rx_skbuff[entry]; - - if (!skb) - break; - -#ifdef ENABLE_PTP_SUPPORT - if (tp->EnablePtp) { - u8 desc_type; - - desc_type = rtl8125_rx_desc_type(status); - if (desc_type == RXDESC_TYPE_NEXT && rx_left > 0) { - u32 status_next; - struct RxDescV3 *desc_next; - unsigned int entry_next; - struct sk_buff *skb_next; - - entry_next = (cur_rx + 1) % NUM_RX_DESC; - desc_next = (struct RxDescV3 *)rtl8125_get_rxdesc(tp, ring->RxDescArray, entry_next); - rmb(); - status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); - if (unlikely(status_next & DescOwn)) { - udelay(1); - rmb(); - status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); - if (unlikely(status_next & DescOwn)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_ERR - "%s: Rx Next Desc ERROR. status = %08x\n", - dev->name, status_next); - } - break; - } - } - - cur_rx++; - rx_left--; - desc_type = rtl8125_rx_desc_type(status_next); - if (desc_type == RXDESC_TYPE_PTP) - rtl8125_rx_ptp_pktstamp(tp, skb, desc_next); - else - WARN_ON(1); - - rx_buf_phy_addr = ring->RxDescPhyAddr[entry_next]; - dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - skb_next = ring->Rx_skbuff[entry_next]; - dev_kfree_skb_any(skb_next); - ring->Rx_skbuff[entry_next] = NULL; - } else - WARN_ON(desc_type != RXDESC_TYPE_NORMAL); - } -#endif - rx_buf_phy_addr = ring->RxDescPhyAddr[entry]; - dma_sync_single_for_cpu(tp_to_dev(tp), - rx_buf_phy_addr, tp->rx_buf_sz, - DMA_FROM_DEVICE); - - if (rtl8125_try_rx_copy(tp, ring, &skb, pkt_size, - desc, tp->rx_buf_sz)) { - ring->Rx_skbuff[entry] = NULL; - dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - } else { - dma_sync_single_for_device(tp_to_dev(tp), rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - } - -#ifdef ENABLE_RSS_SUPPORT - rtl8125_rx_hash(tp, (struct RxDescV3 *)desc, skb); -#endif - - if (tp->cp_cmd & RxChkSum) - rtl8125_rx_csum(tp, skb, desc); - - skb->dev = dev; - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (skb->pkt_type == PACKET_MULTICAST) - RTLDEV->stats.multicast++; - - if (rtl8125_rx_vlan_skb(tp, desc, skb) < 0) - rtl8125_rx_skb(tp, skb, ring_index); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - dev->last_rx = jiffies; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - RTLDEV->stats.rx_bytes += pkt_size; - RTLDEV->stats.rx_packets++; - } - - cur_rx++; - entry = cur_rx % NUM_RX_DESC; - desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(desc); -#endif - } - - count = cur_rx - ring->cur_rx; - ring->cur_rx = cur_rx; - - delta = rtl8125_rx_fill(tp, ring, dev, ring->dirty_rx, ring->cur_rx, 1); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - ring->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((ring->dirty_rx + NUM_RX_DESC == ring->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - -rx_out: - return count; -} - -static bool -rtl8125_linkchg_interrupt(struct rtl8125_private *tp, u32 status) -{ - if (tp->HwCurrIsrVer == 2) - return status & ISRIMR_V2_LINKCHG; - - return status & LinkChg; -} - -/* - *The interrupt handler does all of the Rx thread work and cleans up after - *the Tx thread. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance) -#endif -{ - struct r8125_napi *r8125napi = dev_instance; - struct rtl8125_private *tp = r8125napi->priv; - struct net_device *dev = tp->dev; - u32 status; - int handled = 0; - - do { - status = RTL_R32(tp, tp->isr_reg[0]); - - if (!(tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) { - /* hotplug/major error/no more work/shared irq */ - if (!status) - break; - - if ((status == 0xFFFFFFFF)) - break; - - if (!(status & (tp->intr_mask | tp->timer_intr_mask))) - break; - } - - handled = 1; - -#if defined(RTL_USE_NEW_INTR_API) - if (!tp->irq_tbl[0].requested) - break; -#endif - rtl8125_disable_hw_interrupt(tp); - - RTL_W32(tp, tp->isr_reg[0], status&~RxFIFOOver); - - if (rtl8125_linkchg_interrupt(tp, status)) - rtl8125_schedule_linkchg_work(tp); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u8 DashIntType2Status; - - if (status & ISRIMR_DASH_INTR_CMAC_RESET) - tp->CmacResetIntr = TRUE; - - DashIntType2Status = RTL_CMAC_R8(tp, CMAC_IBISR0); - if (DashIntType2Status & ISRIMR_DASH_TYPE2_ROK) { - tp->RcvFwDashOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_TOK) { - tp->SendFwHostOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE) { - tp->DashFwDisableRx = TRUE; - } - - RTL_CMAC_W8(tp, CMAC_IBISR0, DashIntType2Status); - } - } -#endif - -#ifdef CONFIG_R8125_NAPI - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &tp->r8125napi[0].napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &tp->r8125napi[0].napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8125_switch_to_hw_interrupt(tp); - } -#else - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - u32 budget = ~(u32)0; - int i; - - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - - for (i = 0; i < tp->num_tx_rings; i++) - rtl8125_tx_interrupt(&tp->tx_ring[i], ~(u32)0); -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - struct net_device *dev = tp->dev; - - HandleDashInterrupt(dev); - } -#endif - - rtl8125_switch_to_timer_interrupt(tp); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8125_switch_to_hw_interrupt(tp); - } -#endif - } while (false); - - return IRQ_RETVAL(handled); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance) -#endif -{ - struct r8125_napi *r8125napi = dev_instance; - struct rtl8125_private *tp = r8125napi->priv; - struct net_device *dev = tp->dev; - int message_id = r8125napi->index; -#ifndef CONFIG_R8125_NAPI - u32 budget = ~(u32)0; -#endif - - do { -#if defined(RTL_USE_NEW_INTR_API) - if (!tp->irq_tbl[message_id].requested) - break; -#endif - rtl8125_disable_hw_interrupt_v2(tp, message_id); - - rtl8125_clear_hw_isr_v2(tp, message_id); - - //link change - if (message_id == 21) { - rtl8125_schedule_linkchg_work(tp); - break; - } - -#ifdef CONFIG_R8125_NAPI - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &r8125napi->napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &r8125napi->napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt message id %d in poll_msix\n", - dev->name, message_id); -#else - if (message_id < tp->num_rx_rings) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - } - - rtl8125_tx_interrupt_with_vector(tp, message_id, ~(u32)0); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); -#endif - - } while (false); - - return IRQ_HANDLED; -} - -static void rtl8125_down(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - //rtl8125_delete_esd_timer(dev, &tp->esd_timer); - - //rtl8125_delete_link_timer(dev, &tp->link_timer); - - netif_tx_disable(dev); - - _rtl8125_wait_for_quiescence(dev); - - netif_carrier_off(dev); - - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - rtl8125_rx_clear(tp); -} - -static int rtl8125_resource_freed(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) - if (tp->tx_ring[i].TxDescArray) return 0; - - for (i = 0; i < tp->num_rx_rings; i++) - if (tp->rx_ring[i].RxDescArray) return 0; - - return 1; -} - -int rtl8125_close(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (!rtl8125_resource_freed(tp)) { - set_bit(R8125_FLAG_DOWN, tp->task_flags); - - rtl8125_down(dev); - - pci_clear_master(tp->pci_dev); - -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_stop(tp); -#endif - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 0); - - rtl8125_free_irq(tp); - - rtl8125_free_alloc_resources(tp); - } else { - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 0); - } - - return 0; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) -static void rtl8125_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8125_private *tp = netdev_priv(dev); - - rtnl_lock(); - - if (tp->DASH) - rtl8125_driver_stop(tp); - - rtl8125_set_bios_setting(dev); - if (s5_keep_curr_mac == 0 && tp->random_mac == 0) - rtl8125_rar_set(tp, tp->org_mac_addr); - - if (s5wol == 0) - tp->wol_enabled = WOL_DISABLED; - - rtl8125_close(dev); - rtl8125_disable_msi(pdev, tp); - - rtnl_unlock(); - - if (system_state == SYSTEM_POWER_OFF) { - pci_clear_master(tp->pci_dev); - pci_wake_from_d3(pdev, tp->wol_enabled); - pci_set_power_state(pdev, PCI_D3hot); - } -} -#endif - -/** - * rtl8125_get_stats - Get rtl8125 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8125 - */ -static struct -net_device_stats *rtl8125_get_stats(struct net_device *dev) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - struct rtl8125_private *tp = netdev_priv(dev); -#endif - return &RTLDEV->stats; -} - -#ifdef CONFIG_PM - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -static int -rtl8125_suspend(struct pci_dev *pdev, u32 state) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static int -rtl8125_suspend(struct device *device) -#else -static int -rtl8125_suspend(struct pci_dev *pdev, pm_message_t state) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); -#else - struct net_device *dev = pci_get_drvdata(pdev); -#endif - struct rtl8125_private *tp = netdev_priv(dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = pci_choose_state(pdev, state); -#endif - if (!netif_running(dev)) - goto out; - - //rtl8125_cancel_all_schedule_work(tp); - - //rtl8125_delete_esd_timer(dev, &tp->esd_timer); - - //rtl8125_delete_link_timer(dev, &tp->link_timer); - - rtnl_lock(); - - set_bit(R8125_FLAG_DOWN, tp->task_flags); - - netif_tx_disable(dev); - - netif_carrier_off(dev); - - netif_device_detach(dev); - -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_suspend(tp); -#endif - rtl8125_hw_reset(dev); - - pci_clear_master(pdev); - - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 1); - - if (tp->DASH) - rtl8125_driver_stop(tp); - - rtnl_unlock(); -out: - - pci_disable_device(pdev); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_save_state(pdev, &pci_pm_state); -#else - pci_save_state(pdev); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); -#endif - - pci_prepare_to_sleep(pdev); - - return 0; -} - -static int -rtl8125_hw_d3_not_power_off(struct net_device *dev) -{ - return rtl8125_check_hw_phy_mcu_code_ver(dev); -} - -static int rtl8125_wait_phy_nway_complete_sleep(struct rtl8125_private *tp) -{ - int i, val; - - for (i = 0; i < 30; i++) { - val = rtl8125_mdio_read(tp, MII_BMSR) & BMSR_ANEGCOMPLETE; - if (val) - return 0; - - msleep(100); - } - - return -1; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -static int -rtl8125_resume(struct pci_dev *pdev) -#else -static int -rtl8125_resume(struct device *device) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); -#else - struct net_device *dev = pci_get_drvdata(pdev); -#endif - struct rtl8125_private *tp = netdev_priv(dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = PCI_D0; -#endif - u32 err; - - rtnl_lock(); - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n"); - goto out_unlock; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_restore_state(pdev, &pci_pm_state); -#else - pci_restore_state(pdev); -#endif - pci_enable_wake(pdev, PCI_D0, 0); - - /* restore last modified mac address */ - rtl8125_rar_set(tp, dev->dev_addr); - - tp->resume_not_chg_speed = 0; - if (tp->check_keep_link_speed && - //tp->link_ok(dev) && - rtl8125_hw_d3_not_power_off(dev) && - rtl8125_wait_phy_nway_complete_sleep(tp) == 0) - tp->resume_not_chg_speed = 1; - - if (!netif_running(dev)) - goto out_unlock; - - pci_set_master(pdev); - - rtl8125_exit_oob(dev); - - rtl8125_up(dev); - - clear_bit(R8125_FLAG_DOWN, tp->task_flags); - - rtl8125_schedule_reset_work(tp); - - rtl8125_schedule_esd_work(tp); - - //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); - //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); -out_unlock: - netif_device_attach(dev); - - rtnl_unlock(); - - return err; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - -static struct dev_pm_ops rtl8125_pm_ops = { - .suspend = rtl8125_suspend, - .resume = rtl8125_resume, - .freeze = rtl8125_suspend, - .thaw = rtl8125_resume, - .poweroff = rtl8125_suspend, - .restore = rtl8125_resume, -}; - -#define RTL8125_PM_OPS (&rtl8125_pm_ops) - -#endif - -#else /* !CONFIG_PM */ - -#define RTL8125_PM_OPS NULL - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8125_pci_driver = { - .name = MODULENAME, - .id_table = rtl8125_pci_tbl, - .probe = rtl8125_init_one, - .remove = __devexit_p(rtl8125_remove_one), -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) - .shutdown = rtl8125_shutdown, -#endif -#ifdef CONFIG_PM -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - .suspend = rtl8125_suspend, - .resume = rtl8125_resume, -#else - .driver.pm = RTL8125_PM_OPS, -#endif -#endif -}; - -static int __init -rtl8125_init_module(void) -{ - int ret = 0; -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_module_init(); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - ret = pci_register_driver(&rtl8125_pci_driver); -#else - ret = pci_module_init(&rtl8125_pci_driver); -#endif - - return ret; -} - -static void __exit -rtl8125_cleanup_module(void) -{ - pci_unregister_driver(&rtl8125_pci_driver); - -#ifdef ENABLE_R8125_PROCFS - if (rtl8125_proc) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(MODULENAME, init_net.proc_net); -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - remove_proc_entry(MODULENAME, init_net.proc_net); -#else - remove_proc_entry(MODULENAME, proc_net); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - rtl8125_proc = NULL; - } -#endif -} - -module_init(rtl8125_init_module); -module_exit(rtl8125_cleanup_module); diff --git a/r8125/src/r8125_ptp.c b/r8125/src/r8125_ptp.c deleted file mode 100755 index e1102b76d..000000000 --- a/r8125/src/r8125_ptp.c +++ /dev/null @@ -1,594 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "r8125.h" -#include "r8125_ptp.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) -{ - return *(const struct timespec *)&ts64; -} - -static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) -{ - return *(const struct timespec64 *)&ts; -} -#endif - -static int _rtl8125_phc_gettime(struct rtl8125_private *tp, struct timespec64 *ts64) -{ - //get local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_LATCHED_LOCAL_TIME | PTP_EXEC_CMD)); - - /* nanoseconds */ - //0x6808[29:0] - ts64->tv_nsec = (RTL_R32(tp, PTP_SOFT_CONFIG_Time_NS_8125) & 0x3fffffff) + - tp->ptp_adjust; - - /* seconds */ - //0x680C[47:0] - ts64->tv_sec = RTL_R16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4); - ts64->tv_sec <<= 32; - ts64->tv_sec |= RTL_R32(tp, PTP_SOFT_CONFIG_Time_S_8125); - - return 0; -} - -static int _rtl8125_phc_settime(struct rtl8125_private *tp, const struct timespec64 *ts64) -{ - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, (ts64->tv_nsec & 0x3fffffff)); - - /* seconds */ - //0x680C[47:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, ts64->tv_sec); - RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (ts64->tv_sec >> 32)); - - //set local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} - -#if 0 -static int _rtl8125_phc_adjtime(struct rtl8125_private *tp, s64 delta) -{ - struct timespec64 now, then = ns_to_timespec64(delta); - u32 nsec; - u64 sec; - - _rtl8125_phc_gettime(tp, &now); - now = timespec64_add(now, then); - - nsec = now.tv_nsec & 0x3fffffff; - sec = now.tv_sec & 0x0000ffffffffffff; - - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, nsec); - - /* seconds */ - //0x680C[47:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, sec); - RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (sec >> 32)); - - //adjust local time - //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} -#endif - -static int rtl8125_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - //int ret = 0; - - //netif_info(tp, drv, tp->dev, "phc adjust time\n"); - - spin_lock_irqsave(&tp->lock, flags); - //ret = _rtl8125_phc_adjtime(tp, delta); - tp->ptp_adjust += delta; - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -/* -1ppm means every 125MHz plus 125Hz. It also means every 8ns minus 8ns*10^(-6) - -1ns=2^30 sub_ns - -8ns*10^(-6) = 8 * 2^30 sub_ns * 10^(-6) = 2^33 sub_ns * 10^(-6) = 8590 = 0x218E sub_ns - -1ppb means every 125MHz plus 0.125Hz. It also means every 8ns minus 8ns*10^(-9) - -1ns=2^30 sub_ns - -8ns*10^(-9) = 8 * 2^30 sub_ns * 10^(-9) = 2^33 sub_ns * 10^(-9) = 8.59 sub_ns = 9 sub_ns -*/ -static int _rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - bool negative = false; - u32 sub_ns; - - if (ppb < 0) { - negative = true; - ppb = -ppb; - } - - sub_ns = ppb * 9; - if (negative) { - sub_ns = -sub_ns; - sub_ns &= 0x3fffffff; - sub_ns |= PTP_ADJUST_TIME_NS_NEGATIVE; - } else - sub_ns &= 0x3fffffff; - - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, sub_ns); - - //adjust local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); - //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} - -static int rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) -{ - //struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - - //netif_info(tp, drv, tp->dev, "phc adjust freq\n"); - - if (delta > ptp->max_adj || delta < -ptp->max_adj) - return -EINVAL; - - _rtl8125_phc_adjfreq(ptp, delta); - - return 0; -} - -static int rtl8125_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - int ret; - - //netif_info(tp, drv, tp->dev, "phc get ts\n"); - - spin_lock_irqsave(&tp->lock, flags); - ret = _rtl8125_phc_gettime(tp, ts64); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int rtl8125_phc_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts64) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - int ret; - - //netif_info(tp, drv, tp->dev, "phc set ts\n"); - - spin_lock_irqsave(&tp->lock, flags); - ret = _rtl8125_phc_settime(tp, ts64); - tp->ptp_adjust = 0; - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int rtl8125_phc_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, int on) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - u16 ptp_ctrl; - - //netif_info(tp, drv, tp->dev, "phc enable type %x on %d\n", rq->type, on); - - switch (rq->type) { - case PTP_CLK_REQ_PPS: - spin_lock_irqsave(&tp->lock, flags); - ptp_ctrl = RTL_R16(tp, PTP_CTRL_8125); - ptp_ctrl &= ~BIT_15; - if (on) - ptp_ctrl |= BIT_14; - else - ptp_ctrl &= ~BIT_14; - RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); - spin_unlock_irqrestore(&tp->lock, flags); - return 0; - default: - return -EOPNOTSUPP; - } -} - -int rtl8125_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - - /* we always support timestamping disabled */ - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); - - if (tp->HwSuppPtpVer == 0) - return ethtool_op_get_ts_info(netdev, info); - - info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE | - SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE; - - if (tp->ptp_clock) - info->phc_index = ptp_clock_index(tp->ptp_clock); - else - info->phc_index = -1; - - info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); - - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | - BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | - BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); - - return 0; -} - -static const struct ptp_clock_info rtl_ptp_clock_info = { - .owner = THIS_MODULE, - .n_alarm = 0, - .n_ext_ts = 0, - .n_per_out = 0, - .n_pins = 0, - .pps = 1, - .adjfreq = rtl8125_phc_adjfreq, - .adjtime = rtl8125_phc_adjtime, - .gettime64 = rtl8125_phc_gettime, - .settime64 = rtl8125_phc_settime, - .enable = rtl8125_phc_enable, -}; - -static int rtl8125_get_tx_ptp_pkt_tstamp(struct rtl8125_private *tp, struct timespec64 *ts64) -{ - return _rtl8125_phc_gettime(tp, ts64); -} - -static void rtl8125_ptp_tx_hwtstamp(struct rtl8125_private *tp) -{ - struct sk_buff *skb = tp->ptp_tx_skb; - struct skb_shared_hwtstamps shhwtstamps = {0}; - struct timespec64 ts64; - - RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); - - rtl8125_get_tx_ptp_pkt_tstamp(tp, &ts64); - - /* Upper 32 bits contain s, lower 32 bits contain ns. */ - shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec, - ts64.tv_nsec); - - /* Clear the lock early before calling skb_tstamp_tx so that - * applications are not woken up before the lock bit is clear. We use - * a copy of the skb pointer to ensure other threads can't change it - * while we're notifying the stack. - */ - tp->ptp_tx_skb = NULL; - - /* Notify the stack and free the skb after we've unlocked */ - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); -} - -#define RTL8125_PTP_TX_TIMEOUT (HZ * 15) -static void rtl8125_ptp_tx_work(struct work_struct *work) -{ - struct rtl8125_private *tp = container_of(work, struct rtl8125_private, - ptp_tx_work); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (!tp->ptp_tx_skb) - goto Exit; - - if (time_is_before_jiffies(tp->ptp_tx_start + - RTL8125_PTP_TX_TIMEOUT)) { - dev_kfree_skb_any(tp->ptp_tx_skb); - tp->ptp_tx_skb = NULL; - tp->tx_hwtstamp_timeouts++; - /* Clear the tx valid bit in TSYNCTXCTL register to enable - * interrupt - */ - RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); - goto Exit; - } - - if (RTL_R8(tp, PTP_ISR_8125) & (PTP_ISR_TOK)) - rtl8125_ptp_tx_hwtstamp(tp); - else - /* reschedule to check later */ - schedule_work(&tp->ptp_tx_work); - -Exit: - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8125_hwtstamp_enable(struct rtl8125_private *tp, bool enable) -{ - RTL_W16(tp, PTP_CTRL_8125, 0); - if (enable) { - u16 ptp_ctrl; - struct timespec64 ts64; - - //clear ptp isr - RTL_W8(tp, PTP_ISR_8125, 0xff); - //ptp source 0:gphy 1:mac - rtl8125_mac_ocp_write(tp, 0xDC00, rtl8125_mac_ocp_read(tp, 0xDC00) | BIT_6); - //enable ptp - ptp_ctrl = (BIT_0 | BIT_3 | BIT_4 | BIT_6 | BIT_10 | BIT_12 | BIT_13); - if (tp->ptp_master_mode) { - ptp_ctrl &= ~BIT_13; - ptp_ctrl |= BIT_1; - } - RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); - - //set system time - /* - if (ktime_to_timespec64_cond(ktime_get_real(), &ts64)) - _rtl8125_phc_settime(tp, timespec64_to_timespec(ts64)); - */ - ktime_get_real_ts64(&ts64); - ts64.tv_nsec += tp->ptp_adjust; - _rtl8125_phc_settime(tp, &ts64); - tp->ptp_adjust = 0; - } - - return 0; -} - -static long rtl8125_ptp_create_clock(struct rtl8125_private *tp) -{ - struct net_device *netdev = tp->dev; - long err; - - if (!IS_ERR_OR_NULL(tp->ptp_clock)) - return 0; - - if (tp->HwSuppPtpVer == 0) { - tp->ptp_clock = NULL; - return -EOPNOTSUPP; - } - - tp->ptp_clock_info = rtl_ptp_clock_info; - snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name), - "%pm", tp->dev->dev_addr); - tp->ptp_clock_info.max_adj = 119304647; - tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev); - if (IS_ERR(tp->ptp_clock)) { - err = PTR_ERR(tp->ptp_clock); - tp->ptp_clock = NULL; - netif_err(tp, drv, tp->dev, "ptp_clock_register failed\n"); - return err; - } else - netif_info(tp, drv, tp->dev, "registered PHC device on %s\n", netdev->name); - - return 0; -} - -void rtl8125_ptp_reset(struct rtl8125_private *tp) -{ - if (!tp->ptp_clock) - return; - - netif_info(tp, drv, tp->dev, "reset PHC clock\n"); - - rtl8125_hwtstamp_enable(tp, false); -} - -void rtl8125_ptp_init(struct rtl8125_private *tp) -{ - /* obtain a PTP device, or re-use an existing device */ - if (rtl8125_ptp_create_clock(tp)) - return; - - /* we have a clock so we can initialize work now */ - INIT_WORK(&tp->ptp_tx_work, rtl8125_ptp_tx_work); - - tp->ptp_adjust = 0; - - /* reset the PTP related hardware bits */ - rtl8125_ptp_reset(tp); - - return; -} - -void rtl8125_ptp_suspend(struct rtl8125_private *tp) -{ - if (!tp->ptp_clock) - return; - - netif_info(tp, drv, tp->dev, "suspend PHC clock\n"); - - rtl8125_hwtstamp_enable(tp, false); - - /* ensure that we cancel any pending PTP Tx work item in progress */ - cancel_work_sync(&tp->ptp_tx_work); -} - -void rtl8125_ptp_stop(struct rtl8125_private *tp) -{ - struct net_device *netdev = tp->dev; - - netif_info(tp, drv, tp->dev, "stop PHC clock\n"); - - /* first, suspend PTP activity */ - rtl8125_ptp_suspend(tp); - - /* disable the PTP clock device */ - if (tp->ptp_clock) { - ptp_clock_unregister(tp->ptp_clock); - tp->ptp_clock = NULL; - netif_info(tp, drv, tp->dev, "removed PHC on %s\n", - netdev->name); - } -} - -static int rtl8125_set_tstamp(struct net_device *netdev, struct ifreq *ifr) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - struct hwtstamp_config config; - bool hwtstamp = 0; - - //netif_info(tp, drv, tp->dev, "ptp set ts\n"); - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - if (config.flags) - return -EINVAL; - - switch (config.tx_type) { - case HWTSTAMP_TX_ON: - hwtstamp = 1; - case HWTSTAMP_TX_OFF: - break; - case HWTSTAMP_TX_ONESTEP_SYNC: - default: - return -ERANGE; - } - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - hwtstamp = 1; - case HWTSTAMP_FILTER_NONE: - break; - default: - return -ERANGE; - } - - if (tp->hwtstamp_config.tx_type != config.tx_type || - tp->hwtstamp_config.rx_filter != config.rx_filter) { - tp->hwtstamp_config = config; - rtl8125_hwtstamp_enable(tp, hwtstamp); - } - - return copy_to_user(ifr->ifr_data, &config, - sizeof(config)) ? -EFAULT : 0; -} - -static int rtl8125_get_tstamp(struct net_device *netdev, struct ifreq *ifr) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - - //netif_info(tp, drv, tp->dev, "ptp get ts\n"); - - return copy_to_user(ifr->ifr_data, &tp->hwtstamp_config, - sizeof(tp->hwtstamp_config)) ? -EFAULT : 0; -} - -int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - int ret; - unsigned long flags; - - //netif_info(tp, drv, tp->dev, "ptp ioctl\n"); - - ret = 0; - switch (cmd) { -#ifdef ENABLE_PTP_SUPPORT - case SIOCSHWTSTAMP: - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8125_set_tstamp(netdev, ifr); - spin_unlock_irqrestore(&tp->lock, flags); - break; - case SIOCGHWTSTAMP: - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8125_get_tstamp(netdev, ifr); - spin_unlock_irqrestore(&tp->lock, flags); - break; -#endif - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, - struct RxDescV3 *descv3) -{ - time64_t tv_sec; - long tv_nsec; - - tv_sec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampHigh) + - ((u64)le32_to_cpu(descv3->RxDescPTPDDWord4.TimeStampHHigh) << 32); - tv_nsec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampLow) + tp->ptp_adjust; - - skb_hwtstamps(skb)->hwtstamp = ktime_set(tv_sec, tv_nsec); -} diff --git a/r8125/src/r8125_ptp.h b/r8125/src/r8125_ptp.h deleted file mode 100755 index a324ff382..000000000 --- a/r8125/src/r8125_ptp.h +++ /dev/null @@ -1,81 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_PTP_H -#define _LINUX_rtl8125_PTP_H - -#include -#include -#include -#include -#include - -struct rtl8125_ptp_info { - s64 time_sec; - u32 time_ns; - u16 ts_info; -}; - -#ifndef _STRUCT_TIMESPEC -#define _STRUCT_TIMESPEC -struct timespec { - __kernel_old_time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; -#endif - -enum PTP_CMD_TYPE { - PTP_CMD_SET_LOCAL_TIME = 0, - PTP_CMD_DRIFT_LOCAL_TIME, - PTP_CMD_LATCHED_LOCAL_TIME, -}; - - -struct rtl8125_private; -struct RxDescV3; - -int rtl8125_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info); - -void rtl8125_ptp_reset(struct rtl8125_private *tp); -void rtl8125_ptp_init(struct rtl8125_private *tp); -void rtl8125_ptp_suspend(struct rtl8125_private *tp); -void rtl8125_ptp_stop(struct rtl8125_private *tp); - -int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); - -void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, - struct RxDescV3 *descv3); - -#endif /* _LINUX_rtl8125_PTP_H */ diff --git a/r8125/src/r8125_realwow.h b/r8125/src/r8125_realwow.h deleted file mode 100755 index 352e3270f..000000000 --- a/r8125/src/r8125_realwow.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8125_REALWOW_H -#define _LINUX_R8125_REALWOW_H - -#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3 - -#define MAX_RealWoW_KCP_SIZE (100) -#define MAX_RealWoW_Payload (64) - -#define KA_TX_PACKET_SIZE (100) -#define KA_WAKEUP_PATTERN_SIZE (120) - -//HwSuppKeepAliveOffloadVer -#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0) - -enum rtl_realwow_cmd { - - RTL_REALWOW_SET_KCP_DISABLE=0, - RTL_REALWOW_SET_KCP_INFO, - RTL_REALWOW_SET_KCP_CONTENT, - - RTL_REALWOW_SET_KCP_ACKPKTINFO, - RTL_REALWOW_SET_KCP_WPINFO, - RTL_REALWOW_SET_KCPDHCP_TIMEOUT, - - RTLT_REALWOW_COMMAND_INVALID -}; - -struct rtl_realwow_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -typedef struct _MP_KCPInfo { - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort[2]; - u8 PKTLEN[2]; - - u16 ackLostCnt; - u8 KCP_WakePattern[MAX_RealWoW_Payload]; - u8 KCP_AckPacket[MAX_RealWoW_Payload]; - u32 KCP_interval; - u8 KCP_WakePattern_Len; - u8 KCP_AckPacket_Len; - u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; -} MP_KCP_INFO, *PMP_KCP_INFO; - -typedef struct _KCPInfo { - u32 nId; // = id - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort; - u16 PKTLEN; -} KCPInfo, *PKCPInfo; - -typedef struct _KCPContent { - u32 id; // = id - u32 mSec; // = msec - u32 size; // =size - u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here -} KCPContent, *PKCPContent; - -typedef struct _RealWoWAckPktInfo { - u16 ackLostCnt; - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWAckPktInfo,*PRealWoWAckPktInfo; - -typedef struct _RealWoWWPInfo { - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWWPInfo,*PRealWoWWPInfo; - -int rtl8125_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); -void rtl8125_realwow_hw_init(struct net_device *dev); -void rtl8125_get_realwow_hw_version(struct net_device *dev); -void rtl8125_set_realwow_d3_para(struct net_device *dev); - -#endif /* _LINUX_R8125_REALWOW_H */ diff --git a/r8125/src/r8125_rss.c b/r8125/src/r8125_rss.c deleted file mode 100755 index 78e53f514..000000000 --- a/r8125/src/r8125_rss.c +++ /dev/null @@ -1,481 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include "r8125.h" - -enum rtl8125_rss_register_content { - /* RSS */ - RSS_CTRL_TCP_IPV4_SUPP = (1 << 0), - RSS_CTRL_IPV4_SUPP = (1 << 1), - RSS_CTRL_TCP_IPV6_SUPP = (1 << 2), - RSS_CTRL_IPV6_SUPP = (1 << 3), - RSS_HALF_SUPP = (1 << 7), - RSS_CTRL_UDP_IPV4_SUPP = (1 << 11), - RSS_CTRL_UDP_IPV6_SUPP = (1 << 12), - RSS_QUAD_CPU_EN = (1 << 16), - RSS_HQ_Q_SUP_R = (1 << 31), -}; - -static int rtl8125_get_rss_hash_opts(struct rtl8125_private *tp, - struct ethtool_rxnfc *cmd) -{ - cmd->data = 0; - - /* Report default options for RSS */ - switch (cmd->flow_type) { - case TCP_V4_FLOW: - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case UDP_V4_FLOW: - if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case IPV4_FLOW: - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - break; - case TCP_V6_FLOW: - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case UDP_V6_FLOW: - if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case IPV6_FLOW: - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - break; - default: - return -EINVAL; - } - - return 0; -} - -int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - netif_info(tp, drv, tp->dev, "rss get rxnfc\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return ret; - - switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = rtl8125_tot_rx_rings(tp); - ret = 0; - break; - case ETHTOOL_GRXFH: - ret = rtl8125_get_rss_hash_opts(tp, cmd); - break; - default: - break; - } - - return ret; -} - -u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp) -{ - return tp->HwSuppIndirTblEntries; -} - -#define RSS_MASK_BITS_OFFSET (8) -#define RSS_CPU_NUM_OFFSET (16) -#define RTL8125_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \ - RTL_8125_RSS_FLAG_HASH_UDP_IPV6) -static int _rtl8125_set_rss_hash_opt(struct rtl8125_private *tp) -{ - u32 rss_flags = tp->rss_flags; - u32 hash_mask_len; - u32 rss_ctrl; - - rss_ctrl = ilog2(rtl8125_tot_rx_rings(tp)); - rss_ctrl &= (BIT_0 | BIT_1 | BIT_2); - rss_ctrl <<= RSS_CPU_NUM_OFFSET; - - /* Perform hash on these packet types */ - rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP - | RSS_CTRL_IPV4_SUPP - | RSS_CTRL_IPV6_SUPP - | RSS_CTRL_TCP_IPV6_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; - - hash_mask_len = ilog2(rtl8125_rss_indir_tbl_entries(tp)); - hash_mask_len &= (BIT_0 | BIT_1 | BIT_2); - rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET; - - RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); - - return 0; -} - -static int rtl8125_set_rss_hash_opt(struct rtl8125_private *tp, - struct ethtool_rxnfc *nfc) -{ - u32 rss_flags = tp->rss_flags; - - netif_info(tp, drv, tp->dev, "rss set hash\n"); - - /* - * RSS does not support anything other than hashing - * to queues on src and dst IPs and ports - */ - if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | - RXH_L4_B_0_1 | RXH_L4_B_2_3)) - return -EINVAL; - - switch (nfc->flow_type) { - case TCP_V4_FLOW: - case TCP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST) || - !(nfc->data & RXH_L4_B_0_1) || - !(nfc->data & RXH_L4_B_2_3)) - return -EINVAL; - break; - case UDP_V4_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV4; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV4; - break; - default: - return -EINVAL; - } - break; - case UDP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV6; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV6; - break; - default: - return -EINVAL; - } - break; - case SCTP_V4_FLOW: - case AH_ESP_V4_FLOW: - case AH_V4_FLOW: - case ESP_V4_FLOW: - case SCTP_V6_FLOW: - case AH_ESP_V6_FLOW: - case AH_V6_FLOW: - case ESP_V6_FLOW: - case IP_USER_FLOW: - case ETHER_FLOW: - /* RSS is not supported for these protocols */ - if (nfc->data) { - netif_err(tp, drv, tp->dev, "Command parameters not supported\n"); - return -EINVAL; - } - return 0; - break; - default: - return -EINVAL; - } - - /* if we changed something we need to update flags */ - if (rss_flags != tp->rss_flags) { - u32 rss_ctrl = RTL_R32(tp, RSS_CTRL_8125); - - if ((rss_flags & RTL8125_UDP_RSS_FLAGS) && - !(tp->rss_flags & RTL8125_UDP_RSS_FLAGS)) - netdev_warn(tp->dev, - "enabling UDP RSS: fragmented packets may " - "arrive out of order to the stack above\n"); - - tp->rss_flags = rss_flags; - - /* Perform hash on these packet types */ - rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP - | RSS_CTRL_IPV4_SUPP - | RSS_CTRL_IPV6_SUPP - | RSS_CTRL_TCP_IPV6_SUPP; - - rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP | - RSS_CTRL_UDP_IPV6_SUPP); - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; - - RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); - } - - return 0; -} - -int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - netif_info(tp, drv, tp->dev, "rss set rxnfc\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return ret; - - switch (cmd->cmd) { - case ETHTOOL_SRXFH: - ret = rtl8125_set_rss_hash_opt(tp, cmd); - break; - default: - break; - } - - return ret; -} - -static u32 _rtl8125_get_rxfh_key_size(struct rtl8125_private *tp) -{ - return sizeof(tp->rss_key); -} - -u32 rtl8125_get_rxfh_key_size(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get key size\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return 0; - - return _rtl8125_get_rxfh_key_size(tp); -} - -u32 rtl8125_rss_indir_size(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get indir tbl size\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return 0; - - return rtl8125_rss_indir_tbl_entries(tp); -} - -static void rtl8125_get_reta(struct rtl8125_private *tp, u32 *indir) -{ - int i, reta_size = rtl8125_rss_indir_tbl_entries(tp); - - for (i = 0; i < reta_size; i++) - indir[i] = tp->rss_indir_tbl[i]; -} - -int rtl8125_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, - u8 *hfunc) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get rxfh\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return -EOPNOTSUPP; - - if (hfunc) - *hfunc = ETH_RSS_HASH_TOP; - - if (indir) - rtl8125_get_reta(tp, indir); - - if (key) - memcpy(key, tp->rss_key, rtl8125_get_rxfh_key_size(dev)); - - return 0; -} - -static u32 rtl8125_rss_key_reg(struct rtl8125_private *tp) -{ - return RSS_KEY_8125; -} - -static u32 rtl8125_rss_indir_tbl_reg(struct rtl8125_private *tp) -{ - return RSS_INDIRECTION_TBL_8125_V2; -} - -static void rtl8125_store_reta(struct rtl8125_private *tp) -{ - u16 indir_tbl_reg = rtl8125_rss_indir_tbl_reg(tp); - u32 i, reta_entries = rtl8125_rss_indir_tbl_entries(tp); - u32 reta = 0; - u8 *indir_tbl = tp->rss_indir_tbl; - - /* Write redirection table to HW */ - for (i = 0; i < reta_entries; i++) { - reta |= indir_tbl[i] << (i & 0x3) * 8; - if ((i & 3) == 3) { - RTL_W32(tp, indir_tbl_reg, reta); - - indir_tbl_reg += 4; - reta = 0; - } - } -} - -static void rtl8125_store_rss_key(struct rtl8125_private *tp) -{ - const u16 rss_key_reg = rtl8125_rss_key_reg(tp); - u32 i, rss_key_size = _rtl8125_get_rxfh_key_size(tp); - u32 *rss_key = (u32*)tp->rss_key; - - /* Write redirection table to HW */ - for (i = 0; i < rss_key_size; i+=4) - RTL_W32(tp, rss_key_reg + i, *rss_key++); -} - -int rtl8125_set_rxfh(struct net_device *dev, const u32 *indir, - const u8 *key, const u8 hfunc) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - u32 reta_entries = rtl8125_rss_indir_tbl_entries(tp); - - netif_info(tp, drv, tp->dev, "rss set rxfh\n"); - - /* We require at least one supported parameter to be changed and no - * change in any of the unsupported parameters - */ - if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) - return -EOPNOTSUPP; - - /* Fill out the redirection table */ - if (indir) { - int max_queues = tp->num_rx_rings; - - /* Verify user input. */ - for (i = 0; i < reta_entries; i++) - if (indir[i] >= max_queues) - return -EINVAL; - - for (i = 0; i < reta_entries; i++) - tp->rss_indir_tbl[i] = indir[i]; - } - - /* Fill out the rss hash key */ - if (key) - memcpy(tp->rss_key, key, rtl8125_get_rxfh_key_size(dev)); - - rtl8125_store_reta(tp); - - rtl8125_store_rss_key(tp); - - return 0; -} - -static u32 rtl8125_get_rx_desc_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3) -{ - return le32_to_cpu(descv3->RxDescNormalDDWord2.RSSResult); -} - -#define RXS_8125B_RSS_UDP BIT(9) -#define RXS_8125_RSS_IPV4 BIT(10) -#define RXS_8125_RSS_IPV6 BIT(12) -#define RXS_8125_RSS_TCP BIT(13) -#define RTL8125_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6) -#define RTL8125_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP) -void rtl8125_rx_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3, - struct sk_buff *skb) -{ - u16 rss_header_info; - - if (!(tp->dev->features & NETIF_F_RXHASH)) - return; - - rss_header_info = le16_to_cpu(descv3->RxDescNormalDDWord2.HeaderInfo); - - if (!(rss_header_info & RTL8125_RXS_RSS_L3_TYPE_MASK)) - return; - - skb_set_hash(skb, rtl8125_get_rx_desc_hash(tp, descv3), - (RTL8125_RXS_RSS_L4_TYPE_MASK & rss_header_info) ? - PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); -} - -void rtl8125_disable_rss(struct rtl8125_private *tp) -{ - RTL_W32(tp, RSS_CTRL_8125, 0x00); -} - -void _rtl8125_config_rss(struct rtl8125_private *tp) -{ - _rtl8125_set_rss_hash_opt(tp); - - rtl8125_store_reta(tp); - - rtl8125_store_rss_key(tp); -} - -void rtl8125_config_rss(struct rtl8125_private *tp) -{ - if (!tp->EnableRss) { - rtl8125_disable_rss(tp); - return; - } - - _rtl8125_config_rss(tp); -} - -void rtl8125_init_rss(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < rtl8125_rss_indir_tbl_entries(tp); i++) - tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings); - - netdev_rss_key_fill(tp->rss_key, RTL8125_RSS_KEY_SIZE); -} diff --git a/r8125/src/r8125_rss.h b/r8125/src/r8125_rss.h deleted file mode 100755 index 90e280902..000000000 --- a/r8125/src/r8125_rss.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_RSS_H -#define _LINUX_rtl8125_RSS_H - -#include -#include - -#define RTL8125_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ -#define RTL8125_MAX_INDIRECTION_TABLE_ENTRIES 128 - -enum rtl8125_rss_flag { - RTL_8125_RSS_FLAG_HASH_UDP_IPV4 = (1 << 0), - RTL_8125_RSS_FLAG_HASH_UDP_IPV6 = (1 << 1), -}; - -struct rtl8125_private; - -int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs); -int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); -u32 rtl8125_get_rxfh_key_size(struct net_device *netdev); -u32 rtl8125_rss_indir_size(struct net_device *netdev); -int rtl8125_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, - u8 *hfunc); -int rtl8125_set_rxfh(struct net_device *netdev, const u32 *indir, - const u8 *key, const u8 hfunc); -void rtl8125_rx_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3, - struct sk_buff *skb); -void _rtl8125_config_rss(struct rtl8125_private *tp); -void rtl8125_config_rss(struct rtl8125_private *tp); -void rtl8125_init_rss(struct rtl8125_private *tp); -u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp); -void rtl8125_disable_rss(struct rtl8125_private *tp); - -#endif /* _LINUX_rtl8125_RSS_H */ diff --git a/r8125/src/rtl_eeprom.c b/r8125/src/rtl_eeprom.c deleted file mode 100755 index 866ae5f33..000000000 --- a/r8125/src/rtl_eeprom.c +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -#include "r8125.h" -#include "rtl_eeprom.h" - -//------------------------------------------------------------------- -//rtl8125_eeprom_type(): -// tell the eeprom type -//return value: -// 0: the eeprom type is 93C46 -// 1: the eeprom type is 93C56 or 93C66 -//------------------------------------------------------------------- -void rtl8125_eeprom_type(struct rtl8125_private *tp) -{ - u16 magic = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - goto out_no_eeprom; - - if(RTL_R8(tp, 0xD2)&0x04) { - //not support - //tp->eeprom_type = EEPROM_TWSI; - //tp->eeprom_len = 256; - goto out_no_eeprom; - } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { - tp->eeprom_type = EEPROM_TYPE_93C56; - tp->eeprom_len = 256; - } else { - tp->eeprom_type = EEPROM_TYPE_93C46; - tp->eeprom_len = 128; - } - - magic = rtl8125_eeprom_read_sc(tp, 0); - -out_no_eeprom: - if ((magic != 0x8129) && (magic != 0x8128)) { - tp->eeprom_type = EEPROM_TYPE_NONE; - tp->eeprom_len = 0; - } -} - -void rtl8125_eeprom_cleanup(struct rtl8125_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EECS); - - RTL_W8(tp, Cfg9346, x); - - rtl8125_raise_clock(tp, &x); - rtl8125_lower_clock(tp, &x); -} - -int rtl8125_eeprom_cmd_done(struct rtl8125_private *tp) -{ - u8 x; - int i; - - rtl8125_stand_by(tp); - - for (i = 0; i < 50000; i++) { - x = RTL_R8(tp, Cfg9346); - - if (x & Cfg9346_EEDO) { - udelay(RTL_CLOCK_RATE * 2 * 3); - return 0; - } - udelay(1); - } - - return -1; -} - -//------------------------------------------------------------------- -//rtl8125_eeprom_read_sc(): -// read one word from eeprom -//------------------------------------------------------------------- -u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg) -{ - int addr_sz = 6; - u8 x; - u16 data; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return -1; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) - addr_sz = 6; - else if (tp->eeprom_type==EEPROM_TYPE_93C56) - addr_sz = 8; - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - - data = rtl8125_shift_in_bits(tp); - - rtl8125_eeprom_cleanup(tp); - - RTL_W8(tp, Cfg9346, 0); - - return data; -} - -//------------------------------------------------------------------- -//rtl8125_eeprom_write_sc(): -// write one word to a specific address in the eeprom -//------------------------------------------------------------------- -void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data) -{ - u8 x; - int addr_sz = 6; - int w_dummy_addr = 4; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return ; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) { - addr_sz = 6; - w_dummy_addr = 4; - } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { - addr_sz = 8; - w_dummy_addr = 6; - } - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); - rtl8125_shift_out_bits(tp, reg, w_dummy_addr); - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - if (rtl8125_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - rtl8125_shift_out_bits(tp, data, 16); - if (rtl8125_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); - rtl8125_shift_out_bits(tp, reg, w_dummy_addr); - - rtl8125_eeprom_cleanup(tp); - RTL_W8(tp, Cfg9346, 0); -} - -void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x) -{ - *x = *x | Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x) -{ - - *x = *x & ~Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count) -{ - u8 x; - int mask; - - mask = 0x01 << (count - 1); - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - do { - if (data & mask) - x |= Cfg9346_EEDI; - else - x &= ~Cfg9346_EEDI; - - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - rtl8125_raise_clock(tp, &x); - rtl8125_lower_clock(tp, &x); - mask = mask >> 1; - } while(mask); - - x &= ~Cfg9346_EEDI; - RTL_W8(tp, Cfg9346, x); -} - -u16 rtl8125_shift_in_bits(struct rtl8125_private *tp) -{ - u8 x; - u16 d, i; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - d = 0; - - for (i = 0; i < 16; i++) { - d = d << 1; - rtl8125_raise_clock(tp, &x); - - x = RTL_R8(tp, Cfg9346); - x &= ~Cfg9346_EEDI; - - if (x & Cfg9346_EEDO) - d |= 1; - - rtl8125_lower_clock(tp, &x); - } - - return d; -} - -void rtl8125_stand_by(struct rtl8125_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EECS | Cfg9346_EESK); - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - - x |= Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); -} - -void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); - RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); - - udelay(20); - - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); -} diff --git a/r8125/src/rtl_eeprom.h b/r8125/src/rtl_eeprom.h deleted file mode 100755 index b0c4a050b..000000000 --- a/r8125/src/rtl_eeprom.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -//EEPROM opcodes -#define RTL_EEPROM_READ_OPCODE 06 -#define RTL_EEPROM_WRITE_OPCODE 05 -#define RTL_EEPROM_ERASE_OPCODE 07 -#define RTL_EEPROM_EWEN_OPCODE 19 -#define RTL_EEPROM_EWDS_OPCODE 16 - -#define RTL_CLOCK_RATE 3 - -void rtl8125_eeprom_type(struct rtl8125_private *tp); -void rtl8125_eeprom_cleanup(struct rtl8125_private *tp); -u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg); -void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data); -void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count); -u16 rtl8125_shift_in_bits(struct rtl8125_private *tp); -void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x); -void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x); -void rtl8125_stand_by(struct rtl8125_private *tp); -void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp); diff --git a/r8125/src/rtltool.c b/r8125/src/rtltool.c deleted file mode 100755 index ace717bde..000000000 --- a/r8125/src/rtltool.c +++ /dev/null @@ -1,320 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "r8125.h" -#include "rtl_eeprom.h" -#include "rtltool.h" - -int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr) -{ - struct rtltool_cmd my_cmd; - int ret; - - if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) - return -EFAULT; - - ret = 0; - switch (my_cmd.cmd) { - case RTLTOOL_READ_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = rtl8125_mdio_prot_read(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - rtl8125_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); - break; - - case RTLTOOL_READ_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = rtl8125_ephy_read(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - rtl8125_ephy_write(tp, my_cmd.offset, my_cmd.data); - break; - - case RTLTOOL_READ_ERI: - my_cmd.data = 0; - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - my_cmd.data = rtl8125_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); - } else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_ERI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - rtl8125_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); - } else { - ret = -EOPNOTSUPP; - break; - } - break; - - case RTLTOOL_READ_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = 0; - if (my_cmd.len==1) - pci_read_config_byte(tp->pci_dev, my_cmd.offset, - (u8 *)&my_cmd.data); - else if (my_cmd.len==2) - pci_read_config_word(tp->pci_dev, my_cmd.offset, - (u16 *)&my_cmd.data); - else if (my_cmd.len==4) - pci_read_config_dword(tp->pci_dev, my_cmd.offset, - &my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - pci_write_config_byte(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==2) - pci_write_config_word(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==4) - pci_write_config_dword(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = rtl8125_eeprom_read_sc(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - rtl8125_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); - break; - - case RTL_READ_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - rtl8125_oob_mutex_lock(tp); - my_cmd.data = rtl8125_ocp_read(tp, my_cmd.offset, 4); - rtl8125_oob_mutex_unlock(tp); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len == 0 || my_cmd.len > 4) - return -EOPNOTSUPP; - - rtl8125_oob_mutex_lock(tp); - rtl8125_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); - rtl8125_oob_mutex_unlock(tp); - break; - - case RTL_ENABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - tp->rtk_enable_diag = 1; - - dprintk("enable rtk diag\n"); - break; - - case RTL_DISABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - tp->rtk_enable_diag = 0; - - dprintk("disable rtk diag\n"); - break; - - case RTL_READ_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.offset % 2) - return -EOPNOTSUPP; - - my_cmd.data = rtl8125_mac_ocp_read(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if ((my_cmd.offset % 2) || (my_cmd.len != 2)) - return -EOPNOTSUPP; - - rtl8125_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); - break; - - case RTL_DIRECT_READ_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTL_DIRECT_WRITE_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} diff --git a/r8125/src/rtltool.h b/r8125/src/rtltool.h deleted file mode 100755 index fc8a10ca8..000000000 --- a/r8125/src/rtltool.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_RTLTOOL_H -#define _LINUX_RTLTOOL_H - -#define SIOCRTLTOOL SIOCDEVPRIVATE+1 - -enum rtl_cmd { - RTLTOOL_READ_MAC=0, - RTLTOOL_WRITE_MAC, - RTLTOOL_READ_PHY, - RTLTOOL_WRITE_PHY, - RTLTOOL_READ_EPHY, - RTLTOOL_WRITE_EPHY, - RTLTOOL_READ_ERI, - RTLTOOL_WRITE_ERI, - RTLTOOL_READ_PCI, - RTLTOOL_WRITE_PCI, - RTLTOOL_READ_EEPROM, - RTLTOOL_WRITE_EEPROM, - - RTL_READ_OOB_MAC, - RTL_WRITE_OOB_MAC, - - RTL_ENABLE_PCI_DIAG, - RTL_DISABLE_PCI_DIAG, - - RTL_READ_MAC_OCP, - RTL_WRITE_MAC_OCP, - - RTL_DIRECT_READ_PHY_OCP, - RTL_DIRECT_WRITE_PHY_OCP, - - RTLTOOL_INVALID -}; - -struct rtltool_cmd { - __u32 cmd; - __u32 offset; - __u32 len; - __u32 data; -}; - -enum mode_access { - MODE_NONE=0, - MODE_READ, - MODE_WRITE -}; - -#ifdef __KERNEL__ -int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr); -#endif - -#endif /* _LINUX_RTLTOOL_H */ diff --git a/r8168/Makefile b/r8168/Makefile index fd5977a5b..6ec31651c 100644 --- a/r8168/Makefile +++ b/r8168/Makefile @@ -7,14 +7,14 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=r8168 -PKG_VERSION:=8.049.02 +PKG_VERSION:=8.050.03 PKG_RELEASE:=$(AUTORELEAE) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/BROBIRD/openwrt-r8168.git -PKG_SOURCE_DATE:=2021-10-08 -PKG_SOURCE_VERSION:=2b969c15afe403a685fc7ee069620782241e3ad6 -PKG_MIRROR_HASH:=e4632c10d460f005eff76da8a183d7ff0c8819b0d099872589b7b06a9b8d9952 +PKG_SOURCE_DATE:=2022-06-15 +PKG_SOURCE_VERSION:=ddfaceacd1b7ed2857fb995642a8ffb1fc37e989 +#PKG_MIRROR_HASH:=e4632c10d460f005eff76da8a183d7ff0c8819b0d099872589b7b06a9b8d9952 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) From 27be75b03cb58a011cc6eb3db5464088e399aabc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 18 Nov 2022 18:14:15 +0100 Subject: [PATCH 0879/2059] Add r5s image compilation --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 20fbf85f6..52c865a26 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx, r5s] OMR_KERNEL: [5.4, 5.15] runs-on: ubuntu-latest continue-on-error: true From b799eb7e9bd6df019a6930bc315e494830dd1ccd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 19 Nov 2022 07:30:22 +0100 Subject: [PATCH 0880/2059] Try to reinstall packages less often and only for 1 day --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 9aa5a2c43..a1f089df5 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1704,9 +1704,11 @@ if [ -f /etc/init.d/omr-bypass ] && (([ -f /usr/sbin/iptables-legacy-save ] && [ sleep 5 fi -if [ -f /etc/backup/installed_packages.txt ] && [ -n "$(grep overlay /etc/backup/installed_packages.txt)" ]; then +if [ -f /etc/backup/installed_packages.txt ] && [ -n "$(grep overlay /etc/backup/installed_packages.txt)" ] && ([ "$(uci -q get openmptcprouter.settings.sysupgrade_lc)" = "" ] || [ $(($(date +"%s") + $((30 + RANDOM % 31)) - $(uci -q get openmptcprouter.settings.sysupgrade_lc))) -gt 3600 ]) && [ $(($(date +"%s") - $(stat -c "%Y" /etc/backup/installed_packages.txt))) -gt 86400 ]; then _log "Reinstall packages..." + uci -q set openmptcprouter.settings.sysupgrade_lc=$(date +"%s") /etc/init.d/sysupgrade restart 2>&1 >/dev/null + sleep 10 fi if [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep token_error=\'1\')" != "" ]; then From 18542cb4d7bff7956f4322feb3128369704c5d2d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 22 Nov 2022 20:17:00 +0100 Subject: [PATCH 0881/2059] Update ndpi-netfilter2 --- ndpi-netfilter2/Makefile | 2 +- .../patches/add_streaming_service.patch | 114 ------------------ .../patches/fix-confidence-level.patch | 34 ++++++ 3 files changed, 35 insertions(+), 115 deletions(-) delete mode 100644 ndpi-netfilter2/patches/add_streaming_service.patch create mode 100644 ndpi-netfilter2/patches/fix-confidence-level.patch diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index de684c287..2c8976aa6 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -12,7 +12,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=3 #PKG_REV:=b19e6392cf0c7d51c44e076a91fc4db0cbbd6403 -PKG_REV:=ad41165daf477f9f575819782d8e19adb772fbbd +PKG_REV:=ce5cca1ec5972f8404ad66ec750a3c10968010fd PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git diff --git a/ndpi-netfilter2/patches/add_streaming_service.patch b/ndpi-netfilter2/patches/add_streaming_service.patch deleted file mode 100644 index 21133573e..000000000 --- a/ndpi-netfilter2/patches/add_streaming_service.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 9aeb879f3ffb9f854c574936740fa61620886063 Mon Sep 17 00:00:00 2001 -From: root -Date: Fri, 16 Sep 2022 13:29:46 -0500 -Subject: [PATCH] Added streaming services as protos to nDPI - -* Apple TV+ -* DirecTV -* HBO -* Vudu -* Showtime -* Dailymotion -* Livestream -* Tencent Video -* IHeart Radio -* Tidal -* TuneIn -* SiriusXM Radio - -Domains based on https://www.netify.ai/resources/applications ---- - src/include/ndpi_protocol_ids.h | 12 +++++++ - src/lib/ndpi_content_match.c.inc | 56 ++++++++++++++++++++++++++++++++ - 2 files changed, 68 insertions(+) - -diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h -index 256fd8f24f..94d621d0c9 100644 ---- a/src/include/ndpi_protocol_ids.h -+++ b/src/include/ndpi_protocol_ids.h -@@ -340,6 +340,18 @@ - NDPI_PROTOCOL_KISMET = 309, - NDPI_PROTOCOL_FASTCGI = 310, - NDPI_PROTOCOL_FTPS = 311, -+ NDPI_PROTOCOL_APPLETVPLUS = 306, -+ NDPI_PROTOCOL_DIRECTV = 307, -+ NDPI_PROTOCOL_HBO = 308, -+ NDPI_PROTOCOL_VUDU = 309, -+ NDPI_PROTOCOL_SHOWTIME = 310, -+ NDPI_PROTOCOL_DAILYMOTION = 311, -+ NDPI_PROTOCOL_LIVESTREAM = 312, -+ NDPI_PROTOCOL_TENCENTVIDEO = 313, -+ NDPI_PROTOCOL_IHEARTRADIO = 314, -+ NDPI_PROTOCOL_TIDAL = 315, -+ NDPI_PROTOCOL_TUNEIN = 316, -+ NDPI_PROTOCOL_SIRIUSXMRADIO = 317, - - #ifdef CUSTOM_NDPI_PROTOCOLS - #include "../../../nDPI-custom/custom_ndpi_protocol_ids.h" -diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc -index eb320df253..161fd77f4f 100644 ---- a/src/lib/ndpi_content_match.c.inc -+++ b/src/lib/ndpi_content_match.c.inc -@@ -1703,6 +1703,62 @@ ndpi_protocol_match host_match[] = - - { "cachefly.com", "CacheFly", NDPI_PROTOCOL_CACHEFLY, NDPI_PROTOCOL_CATEGORY_CLOUD, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DEFAULT_LEVEL }, - -+ { "tv.apple.com", "AppleTVPlus", NDPI_PROTOCOL_APPLETVPLUS, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "tv.g.apple.com", "AppleTVPlus", NDPI_PROTOCOL_APPLETVPLUS, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "tv.v.aaplimg.com", "AppleTVPlus", NDPI_PROTOCOL_APPLETVPLUS, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "directv.com", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "directvnow.com", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "dtvbb.tv", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "dtvce.com", "DirecTV", NDPI_PROTOCOL_DIRECTV, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "hbo.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbogo.co.th", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbogo.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbogo.eu", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbogoasia.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbogoasia.id", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbogoasia.ph", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbomax.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbomaxcdn.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "hbonow.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "maxgo.com", "HBO", NDPI_PROTOCOL_HBO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "vudu.com", "Vudu", NDPI_PROTOCOL_VUDU, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { ".showtime.com", "Showtime", NDPI_PROTOCOL_SHOWTIME, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "dai.ly", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "dailymotion.com", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "dailymotionadvertising.com", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "dmcdn.net", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "dmxleo.com", "Dailymotion", NDPI_PROTOCOL_DAILYMOTION, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { ".livestream.com", "Livestream", NDPI_PROTOCOL_LIVESTREAM, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "v.qq.com", "Tencentvideo", NDPI_PROTOCOL_TENCENTVIDEO, NDPI_PROTOCOL_CATEGORY_STREAMING, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "937theriver.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "iheart.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "iheart.mx", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "iheartmedia.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "iheartradio.ca", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "iheartradio.co.nz", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "iheartradio.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "ihrdev.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "ihrhls.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "ihrint.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "ihrstage.com", "IHeartRadio", NDPI_PROTOCOL_IHEARTRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { ".tidal.com", "Tidal", NDPI_PROTOCOL_TIDAL, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "radiotime.com", "TuneIn", NDPI_PROTOCOL_TUNEIN, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "tunein.com", "TuneIn", NDPI_PROTOCOL_TUNEIN, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "tunenet.io", "TuneIn", NDPI_PROTOCOL_TUNEIN, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ -+ { "siriusxm.ca", "SiriusXMRadio", NDPI_PROTOCOL_SIRIUSXMRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ { "siriusxm.com", "SiriusXMRadio", NDPI_PROTOCOL_SIRIUSXMRADIO, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DEFAULT_LEVEL }, -+ - #ifdef CUSTOM_NDPI_PROTOCOLS - #include "../../../nDPI-custom/custom_ndpi_content_match_host_match.c.inc" - #endif diff --git a/ndpi-netfilter2/patches/fix-confidence-level.patch b/ndpi-netfilter2/patches/fix-confidence-level.patch new file mode 100644 index 000000000..a28dbc90d --- /dev/null +++ b/ndpi-netfilter2/patches/fix-confidence-level.patch @@ -0,0 +1,34 @@ +From d238ff6ad1715a640df62c7b47373293c8c136bd Mon Sep 17 00:00:00 2001 +From: Vitaly Lavrov +Date: Tue, 22 Nov 2022 15:18:46 +0300 +Subject: [PATCH] Fix confidence level after ndpi_detection_giveup() + +--- + ndpi-netfilter/src/main.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/ndpi-netfilter/src/main.c b/ndpi-netfilter/src/main.c +index 5582eee938..3c39af8d5e 100644 +--- a/ndpi-netfilter/src/main.c ++++ b/ndpi-netfilter/src/main.c +@@ -1676,9 +1676,20 @@ ndpi_mt(const struct sk_buff *skb, struct xt_action_param *par) + detect_complete = 1; + if(proto.app_protocol == NDPI_PROTOCOL_UNKNOWN) { + u_int8_t proto_guessed; ++ ndpi_protocol p_old = proto; + proto = ndpi_detection_giveup(n->ndpi_struct, flow, 1, &proto_guessed); ++ if(_DBG_TRACE_DPI) { ++ if( p_old.app_protocol != proto.app_protocol || ++ p_old.master_protocol != proto.master_protocol || ++ confidence != flow->confidence) ++ pr_info(" ndpi_process_packet ndpi_detection_giveup app,master [%u,%u]->[%u,%u] c %u->%u\n", ++ p_old.app_protocol,p_old.master_protocol, ++ proto.app_protocol,proto.master_protocol, ++ confidence,flow->confidence); ++ } + ct_ndpi->proto.app_protocol = proto.app_protocol; + ct_ndpi->proto.master_protocol = proto.master_protocol; ++ ct_ndpi->confidence = confidence = flow->confidence; + c_proto->proto = pack_proto(proto); + } + if(_DBG_TRACE_DDONE) From b151a4ec90900906835353e5ae0d259950d29aba Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 24 Nov 2022 20:59:06 +0100 Subject: [PATCH 0882/2059] Update ndpi-netfilter2 --- ndpi-netfilter2/Makefile | 5 ++- .../patches/fix-confidence-level.patch | 34 ------------------- 2 files changed, 2 insertions(+), 37 deletions(-) delete mode 100644 ndpi-netfilter2/patches/fix-confidence-level.patch diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 2c8976aa6..13f73dc14 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -10,9 +10,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 -PKG_RELEASE:=3 -#PKG_REV:=b19e6392cf0c7d51c44e076a91fc4db0cbbd6403 -PKG_REV:=ce5cca1ec5972f8404ad66ec750a3c10968010fd +PKG_RELEASE:=4 +PKG_REV:=cf017cc2fecee644d0b2ff633a17377f776d1505 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git diff --git a/ndpi-netfilter2/patches/fix-confidence-level.patch b/ndpi-netfilter2/patches/fix-confidence-level.patch deleted file mode 100644 index a28dbc90d..000000000 --- a/ndpi-netfilter2/patches/fix-confidence-level.patch +++ /dev/null @@ -1,34 +0,0 @@ -From d238ff6ad1715a640df62c7b47373293c8c136bd Mon Sep 17 00:00:00 2001 -From: Vitaly Lavrov -Date: Tue, 22 Nov 2022 15:18:46 +0300 -Subject: [PATCH] Fix confidence level after ndpi_detection_giveup() - ---- - ndpi-netfilter/src/main.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/ndpi-netfilter/src/main.c b/ndpi-netfilter/src/main.c -index 5582eee938..3c39af8d5e 100644 ---- a/ndpi-netfilter/src/main.c -+++ b/ndpi-netfilter/src/main.c -@@ -1676,9 +1676,20 @@ ndpi_mt(const struct sk_buff *skb, struct xt_action_param *par) - detect_complete = 1; - if(proto.app_protocol == NDPI_PROTOCOL_UNKNOWN) { - u_int8_t proto_guessed; -+ ndpi_protocol p_old = proto; - proto = ndpi_detection_giveup(n->ndpi_struct, flow, 1, &proto_guessed); -+ if(_DBG_TRACE_DPI) { -+ if( p_old.app_protocol != proto.app_protocol || -+ p_old.master_protocol != proto.master_protocol || -+ confidence != flow->confidence) -+ pr_info(" ndpi_process_packet ndpi_detection_giveup app,master [%u,%u]->[%u,%u] c %u->%u\n", -+ p_old.app_protocol,p_old.master_protocol, -+ proto.app_protocol,proto.master_protocol, -+ confidence,flow->confidence); -+ } - ct_ndpi->proto.app_protocol = proto.app_protocol; - ct_ndpi->proto.master_protocol = proto.master_protocol; -+ ct_ndpi->confidence = confidence = flow->confidence; - c_proto->proto = pack_proto(proto); - } - if(_DBG_TRACE_DDONE) From 8dba67311ae476c08879fef965f5a5e64c209b5b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 25 Nov 2022 20:26:58 +0100 Subject: [PATCH 0883/2059] Fix #2679 - DHCP gateway setting --- .../htdocs/luci-static/resources/view/network/dhcp.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js index 4dd90cc32..bbafc8c7b 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js @@ -519,6 +519,14 @@ return view.extend({ so.value(ipv4, ipaddrs[ipv4] ? '%s (%s)'.format(ipv4, ipaddrs[ipv4]) : ipv4); }); + so = ss.options(form.value, 'gw', _('Gateway IPv4 Address')); + so.rmempty = true; + so.datatype = 'or(ip4addr,"ignore")'; + Object.keys(hosts).forEach(function(mac) { + if (hosts[mac].ipv4) + so.value(hosts[mac].ipv4); + }); + so = ss.option(form.Value, 'leasetime', _('Lease time')); so.rmempty = true; From 77afcb8d322d88b504e0c01562e863f1be668039 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 28 Nov 2022 20:15:28 +0100 Subject: [PATCH 0884/2059] Force dhcp on LAN interface --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index ee5922803..832fdc808 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -167,6 +167,7 @@ set network.lan.metric=2048 set network.lan.ipv6=0 set network.lan.delegate=0 set network.lan.addlatency=0 +set dhcp.lan.dhcpv4='server' EOF uci -q batch <<-EOF @@ -405,5 +406,6 @@ fi uci -q commit macvlan uci -q commit network +uci -q commit dhcp rm -f /tmp/luci-indexcache exit 0 From c0503fcc06b68564f764c0ffc984e2321f196421 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 28 Nov 2022 20:17:54 +0100 Subject: [PATCH 0885/2059] Fix interface display in status page --- .../root/usr/libexec/rpcd/openmptcprouter | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index f01761f1b..f6b275150 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1074,8 +1074,10 @@ function interfaces_status() mArray.openmptcprouter.dhcpd[itf].range_end = range_end mArray.openmptcprouter.dhcpd[itf].netmask = mask mArray.openmptcprouter.dhcpd[itf].leasetime = leasetime - mArray.openmptcprouter.dhcpd[itf].router = mArray.openmptcprouter["local_addr"] - mArray.openmptcprouter.dhcpd[itf].dns = mArray.openmptcprouter["local_addr"] + local net = ntm:get_network(itf) + local ipaddr = net:ipaddr() or "" + mArray.openmptcprouter.dhcpd[itf].router = ipaddr + mArray.openmptcprouter.dhcpd[itf].dns = ipaddr end for itf, option, value in dnsmasq:gmatch("option=(%w+),([%w:-]+),(%d+\.%d+\.%d+\.%d+)") do if mArray.openmptcprouter.dhcpd[itf] then From 7f7feb0c919329574f0aebabb0d000f387d6186a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 2 Dec 2022 16:59:09 +0100 Subject: [PATCH 0886/2059] Fix DHCP menu --- .../htdocs/luci-static/resources/view/network/dhcp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js index bbafc8c7b..6bd6c7d8e 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js @@ -519,7 +519,7 @@ return view.extend({ so.value(ipv4, ipaddrs[ipv4] ? '%s (%s)'.format(ipv4, ipaddrs[ipv4]) : ipv4); }); - so = ss.options(form.value, 'gw', _('Gateway IPv4 Address')); + so = ss.option(form.value, 'gw', _('Gateway IPv4 Address')); so.rmempty = true; so.datatype = 'or(ip4addr,"ignore")'; Object.keys(hosts).forEach(function(mac) { From 88dcdd748b1ab6673d7b211ae4496af5e23057b7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 2 Dec 2022 17:00:36 +0100 Subject: [PATCH 0887/2059] Various route fixes --- .../share/omr/post-tracking.d/post-tracking | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index a1f089df5..9546be6ec 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -860,6 +860,20 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then config_foreach del_server_route server config_foreach del_server_route6 server #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then + + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw: $default_gw - Set routes (current: $(ip r) )" + config_load network + config_foreach set_route interface $OMR_TRACKER_INTERFACE + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New routes $(ip r)" + elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then + config_load network + config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" + fi + fi if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set balancing route (current: $(ip r) )" config_foreach set_server_all_routes server @@ -867,20 +881,6 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set balancing route done (new: $(ip r) )" fi fi - - if [ -n "$OMR_TRACKER_INTERFACE" ]; then - if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw: $default_gw - Set routes (current: $(ip r) )" - config_load network - config_foreach set_route interface $OMR_TRACKER_INTERFACE - config_foreach set_route6 interface $OMR_TRACKER_INTERFACE - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New routes $(ip r)" - elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then - config_load network - config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" - config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" - fi - fi mail_alert="" if [ -n "$OMR_TRACKER_INTERFACE" ]; then @@ -992,8 +992,8 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw : $default_gw - Current route: $(ip r)" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null - if [ "$(pgrep openmptcprouter-vps)" = "" ]; then - /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 + if [ "$(pgrep -f openmptcprouter-vps)" = "" ]; then + /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & fi [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp 2>&1 >/dev/null [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New route: $(ip r)" @@ -1172,7 +1172,7 @@ if [ "$multipath_config" = "master" ]; then ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 991337 2>&1 >/dev/null fi if ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ]) || [ $(($(date +"%s") + $((10 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]; then - [ "$(pgrep openmptcprouter-vps)" = "" ] && /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 + [ "$(pgrep -f openmptcprouter-vps)" = "" ] && /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & fi multipath_config="on" fi @@ -1217,8 +1217,8 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$mul addpath() { serverip=$1 #gtudpst="up" - #[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" - if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP | grep running)" = "" ] && [ -n "$(resolveip -4 -t 5 $serverip)" ]; then + #[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep -f glorytun-udp)" != "" ] && gtudpst="backup" + if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep -f glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP | grep running)" = "" ] && [ -n "$(resolveip -4 -t 5 $serverip)" ]; then serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then @@ -1234,7 +1234,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$mul fi fi fi - if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6 | grep running)" = "" ] && [ -n "$(resolveip -6 -t 5 $serverip)" ]; then + if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep -f glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6 | grep running)" = "" ] && [ -n "$(resolveip -6 -t 5 $serverip)" ]; then serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then @@ -1250,10 +1250,10 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$mul fi fi fi -# if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp set | grep 'kxtimeout 7d')" = "" ]; then +# if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep -f glorytun-udp)" != "" ] && [ "$(glorytun-udp set | grep 'kxtimeout 7d')" = "" ]; then # glorytun-udp set dev tun0 kxtimeout 7d > /dev/null 2>&1 # fi - [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && { + [ "$multipath_config" = "backup" ] && [ "$(pgrep -f glorytun-udp)" != "" ] && { [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$(resolveip -4 -t 5 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$(resolveip -6 -t 5 $serverip)" ] && glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set pref 125 > /dev/null 2>&1 } @@ -1375,7 +1375,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC omr_tracebox_mtu() { local serverip=$1 [ "$serverip" != "${1#*[0-9].[0-9]}" ] && serverip="" - [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep -f tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } @@ -1450,7 +1450,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC omr_tracebox_mtu() { local serverip=$1 [ "$serverip" != "${1#*:[0-9a-fA-F]}" ] && serverip="" - [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { + [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ] && [ "$(pgrep -f tracebox)" = "" ] && [ "$(uci -q get openmptcprouter.settings.tracebox)" != "0" ] && { omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } @@ -1518,9 +1518,9 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC else [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Get status and settings for $OMR_TRACKER_INTERFACE... Done" [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter - if [ "$(pgrep openmptcprouter-vps)" = "" ] && ( [ "$(uci -q get openmptcprouter.settings.apilc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.settings.apilc))) -gt 3600 ] ); then + if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ( [ "$(uci -q get openmptcprouter.settings.apilc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.settings.apilc))) -gt 3600 ] ); then _log "Check API configuration..." - /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 + /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & uci -q set openmptcprouter.settings.apilc=$(date +"%s") _log "Check API configuration... Done" fi @@ -1578,7 +1578,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then fi # If a service is down, force restart it -if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(pgrep ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then +if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f ss-redir)" = "" ] && [ "$(pgrep -f ss-local)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ]; then _log "Can't find Shadowsocks, restart it..." /etc/init.d/shadowsocks-libev restart 2>&1 >/dev/null sleep 5 @@ -1594,12 +1594,12 @@ if [ -f /etc/init.d/glorytun-udp ] && [ "$(pgrep glorytun-udp)" = "" ] && [ "$(u sleep 5 fi -if [ "$(pgrep dnsmasq)" = "" ] && [ -f /etc/init.d/dnsmasq ]; then +if [ "$(pgrep -f dnsmasq)" = "" ] && [ -f /etc/init.d/dnsmasq ]; then _log "Can't find dnsmasq, restart it..." /etc/init.d/dnsmasq restart 2>&1 >/dev/null sleep 5 fi -if [ "$(pgrep unbound)" = "" ] && [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then +if [ "$(pgrep -f unbound)" = "" ] && [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then _log "Can't find unbound, restart it..." /etc/init.d/unbound restart 2>&1 >/dev/null sleep 5 @@ -1711,12 +1711,12 @@ if [ -f /etc/backup/installed_packages.txt ] && [ -n "$(grep overlay /etc/backup sleep 10 fi -if [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep token_error=\'1\')" != "" ]; then - /etc/init.d/openmptcprouter-vps token >/dev/null 2>&1 +if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep token_error=\'1\')" != "" ]; then + /etc/init.d/openmptcprouter-vps token >/dev/null 2>&1 & sleep 5 fi -if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then - /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 +if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then + /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & sleep 5 fi @@ -1725,8 +1725,8 @@ if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q sleep 5 fi -#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || (([ -f /usr/sbin/iptables-legacy-save ] && [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]) || [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ])); then -if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then +#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || (([ -f /usr/sbin/iptables-legacy-save ] && [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]) || [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ])); then +if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then check_server_fw() { [ "$(uci -q get openmptcprouter.$1.set_firewall)" = "1" ] && { _log "Set firewall on server $1" From dd48923a0b103550c5d2f4e0fd4337370e82be5a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 2 Dec 2022 20:31:04 +0100 Subject: [PATCH 0888/2059] Really fix dhcp menu --- .../htdocs/luci-static/resources/view/network/dhcp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js index 6bd6c7d8e..6c6163c7c 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js @@ -519,7 +519,7 @@ return view.extend({ so.value(ipv4, ipaddrs[ipv4] ? '%s (%s)'.format(ipv4, ipaddrs[ipv4]) : ipv4); }); - so = ss.option(form.value, 'gw', _('Gateway IPv4 Address')); + so = ss.option(form.Value, 'gw', _('Gateway IPv4 Address')); so.rmempty = true; so.datatype = 'or(ip4addr,"ignore")'; Object.keys(hosts).forEach(function(mac) { From 136eca2afad7c7e94db70a0a458b94878a8facb1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 4 Dec 2022 08:32:41 +0100 Subject: [PATCH 0889/2059] Fix IPv6 check in omr-tracker --- omr-tracker/files/bin/omr-tracker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index fe21c7473..61d328932 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -289,10 +289,10 @@ while true; do OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | awk '/proto kernel/ {print $1}' | tr -d "\n") fi fi - if [ "$OMR_TRACKER_INTERFACE_IPV6" = "1" ] || [ "$OMR_TRACKER_INTERFACE_IPV6" = "auto" ]; then + if [ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ]; then #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then - OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | grep -v 'inet6 f' | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) + OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | grep -v 'inet6 fe80' | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1) #fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then OMR_TRACKER_DEVICE_GATEWAY6=$(uci -q get "network.$OMR_TRACKER_INTERFACE.ip6gw") From dd381f45f965f9bc64ba9467c5bbfa9737c74721 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 5 Dec 2022 08:34:42 +0100 Subject: [PATCH 0890/2059] Fix dependencies --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 52c865a26..0a17c78df 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: - name: Prepare run: | sudo apt-get update - sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc1 libc6-dev-i386 subversion flex uglifyjs git-core gcc-multilib p7zip p7zip-full msmtp libssl-dev texinfo libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint device-tree-compiler + sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc-s1 libc6-dev-i386 subversion flex uglifyjs git-core gcc-multilib p7zip p7zip-full msmtp libssl-dev texinfo libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint device-tree-compiler - name: Free disk space run: | df -h From cf871353f87fa1d6bcfb3bab4164a033a1b3692f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 8 Dec 2022 09:43:47 +0100 Subject: [PATCH 0891/2059] Add atinout package --- atinout/Makefile | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 atinout/Makefile diff --git a/atinout/Makefile b/atinout/Makefile new file mode 100644 index 000000000..5457697e0 --- /dev/null +++ b/atinout/Makefile @@ -0,0 +1,57 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=atinout +PKG_VERSION=0.9.1 + +PKG_MAINTAINER:=Konstantine Shevlakov +PKG_LICENSE:=GPLv2 +PKG_LICENSE_FILES:=LICENSE + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/beralt/atinout.git +PKG_SOURCE_VERSION:=4013e8db4cd140c1df24bb90f929efeb9b61b238 + +PKG_SOURCE_SUBDIR:=$(PKG_NAME) +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=net + CATEGORY:=Network + SUBMENU:=Telephony + TITLE:=Send AT commands to a modem + URL:=http://atinout.sourceforge.net/ + MAINTAINER:=Adrian Guenter +endef + +define Package/$(PKG_NAME)/description + Atinout is a program that will execute AT commands in sequence and + capture the response from the modem. +endef + + +CONFIGURE_VARS += \ + CC="$(TARGET_CC)" \ + CXX="$(TARGET_CC) +.c++" \ + CFLAGS="$(TARGET_CFLAGS) -Wall -DVERSION=\"\\\"$(PKG_VERSION)\\\"\"" \ + LDFLAGS="$(TARGET_LDFLAGS)" + +define Build/Configure + $(call Build/Configure/Default,--with-linux-headers=$(LINUX_DIR)) +endef + +define Build/Compile + @echo -e "\n=== Build/Compile ===" + $(CONFIGURE_VARS) $(MAKE) -C $(PKG_BUILD_DIR) \ + all \ + +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin/$(PKG_NAME) +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) From 89c7a3c2067ffd2066ed8295c3f6e3607a5ad06c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:47:56 +0100 Subject: [PATCH 0892/2059] Update shortcut-fe --- fast-classifier/Makefile | 59 ++-- fast-classifier/src/fast-classifier.c | 38 ++- fast-classifier/src/sfe.h | 114 -------- fast-classifier/src/sfe_backport.h | 195 ------------- fast-classifier/src/sfe_cm.h | 259 ------------------ shortcut-fe/Makefile | 35 ++- shortcut-fe/files/etc/init.d/shortcut-fe | 51 ++++ shortcut-fe/files/usr/bin/sfe_dump | 0 shortcut-fe/src/Kconfig | 3 +- shortcut-fe/src/Makefile | 1 + shortcut-fe/src/sfe_backport.h | 2 +- shortcut-fe/src/sfe_cm.c | 160 +++++++---- shortcut-fe/src/sfe_cm.h | 3 +- shortcut-fe/src/sfe_ipv4.c | 39 ++- shortcut-fe/src/sfe_ipv6.c | 41 ++- simulated-driver/Makefile | 60 ++++ .../patches/200-nss-qdisc-support.patch | 11 + 17 files changed, 369 insertions(+), 702 deletions(-) delete mode 100644 fast-classifier/src/sfe.h delete mode 100644 fast-classifier/src/sfe_backport.h delete mode 100644 fast-classifier/src/sfe_cm.h create mode 100755 shortcut-fe/files/etc/init.d/shortcut-fe mode change 100644 => 100755 shortcut-fe/files/usr/bin/sfe_dump create mode 100644 simulated-driver/Makefile create mode 100644 simulated-driver/patches/200-nss-qdisc-support.patch diff --git a/fast-classifier/Makefile b/fast-classifier/Makefile index 29d024e7b..09c1174dd 100644 --- a/fast-classifier/Makefile +++ b/fast-classifier/Makefile @@ -1,43 +1,60 @@ +# +# Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=fast-classifier -PKG_RELEASE:=1 -PKG_CONFIG_DEPENDS := CONFIG_IPV6 +PKG_RELEASE:=6 include $(INCLUDE_DIR)/package.mk -define KernelPackage/$(PKG_NAME)/Default +define KernelPackage/fast-classifier/Default SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe TITLE:=Kernel driver for FAST Classifier FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko - KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y CONFIG_NF_CONNTRACK_MARK=y - PROVIDES:=$(PKG_NAME) + KCONFIG:= \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ + CONFIG_NF_CONNTRACK_MARK=y \ + CONFIG_XFRM=y + CONFLICTS:=kmod-shortcut-fe-drv kmod-shortcut-fe-cm endef -define KernelPackage/$(PKG_NAME) - $(call KernelPackage/$(PKG_NAME)/Default) +define KernelPackage/fast-classifier + $(call KernelPackage/fast-classifier/Default) endef -define KernelPackage/$(PKG_NAME)-noload - $(call KernelPackage/$(PKG_NAME)/Default) +define KernelPackage/fast-classifier-noload + $(call KernelPackage/fast-classifier/Default) endef -define KernelPackage/$(PKG_NAME)/Default/description +define KernelPackage/fast-classifier/Default/description FAST Classifier talks to SFE to make decisions about offloading connections endef -define KernelPackage/$(PKG_NAME)/description -$(call KernelPackage/$(PKG_NAME)/Default/description) +define KernelPackage/fast-classifier/description +$(call KernelPackage/fast-classifier/Default/description) endef -define KernelPackage/$(PKG_NAME)-noload/description -$(call KernelPackage/$(PKG_NAME)/Default/description) +define KernelPackage/fast-classifier-noload/description +$(call KernelPackage/fast-classifier/Default/description) -This package does not load $(PKG_NAME) at boot by default +This package does not load fast-classifier at boot by default endef define Package/fast-classifier-example @@ -50,15 +67,16 @@ Example user space program that communicates with fast classifier kernel module endef -SFE_MAKE_OPTS:=SFE_SUPPORT_IPV6=$(if $(CONFIG_IPV6),y,n) +HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard) define Build/Compile/kmod - +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(SFE_MAKE_OPTS) \ + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ $(KERNEL_MAKE_FLAGS) \ $(PKG_MAKE_FLAGS) \ M="$(PKG_BUILD_DIR)" \ CONFIG_FAST_CLASSIFIER=m \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" \ + $(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \ modules endef @@ -81,12 +99,11 @@ define Build/InstallDev $(CP) $(PKG_BUILD_DIR)/fast-classifier.h $(1)/usr/include/ endef - define Package/fast-classifier-example/install $(INSTALL_DIR) $(1)/sbin $(CP) $(PKG_BUILD_DIR)/userspace_fast_classifier $(1)/sbin/ endef -$(eval $(call KernelPackage,$(PKG_NAME))) -$(eval $(call KernelPackage,$(PKG_NAME)-noload)) +$(eval $(call KernelPackage,fast-classifier)) +#$(eval $(call KernelPackage,fast-classifier-noload)) #$(eval $(call BuildPackage,fast-classifier-example)) diff --git a/fast-classifier/src/fast-classifier.c b/fast-classifier/src/fast-classifier.c index 7ca5d973b..944dfae38 100644 --- a/fast-classifier/src/fast-classifier.c +++ b/fast-classifier/src/fast-classifier.c @@ -36,9 +36,9 @@ #include #include -#include "sfe_backport.h" -#include "sfe.h" -#include "sfe_cm.h" +#include +#include +#include #include "fast-classifier.h" typedef enum fast_classifier_exception { @@ -451,6 +451,10 @@ static u32 fc_conn_hash(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, */ static int fast_classifier_update_protocol(struct sfe_connection_create *p_sic, struct nf_conn *ct) { + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + struct net *net=NULL ; + struct nf_tcp_net *tn=NULL; + #endif switch (p_sic->protocol) { case IPPROTO_TCP: p_sic->src_td_window_scale = ct->proto.tcp.seen[0].td_scale; @@ -461,8 +465,14 @@ static int fast_classifier_update_protocol(struct sfe_connection_create *p_sic, p_sic->dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; p_sic->dest_td_end = ct->proto.tcp.seen[1].td_end; p_sic->dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; - - if (nf_ct_tcp_no_window_check +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + net = nf_ct_net(ct); + tn = nf_tcp_pernet(net); + if ((tn&&tn->tcp_no_window_check) +#else + if (nf_ct_tcp_no_window_check +#endif + || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { p_sic->flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; @@ -1744,8 +1754,11 @@ static int __init fast_classifier_init(void) { struct fast_classifier *sc = &__sc; int result = -1; +#ifdef CONFIG_SFE_ECM + int (*fast_recv)(struct sk_buff *skb); +#endif - printk(KERN_ALERT "fast-classifier (PBR safe v2.1.4a): starting up\n"); + printk(KERN_ALERT "fast-classifier: starting up\n"); DEBUG_INFO("SFE CM init\n"); hash_init(fc_conn_ht); @@ -1810,6 +1823,7 @@ static int __init fast_classifier_init(void) goto exit3; } +#ifdef CONFIG_NF_CONNTRACK_EVENTS /* * Register a notifier hook to get fast notifications of expired connections. */ @@ -1817,12 +1831,14 @@ static int __init fast_classifier_init(void) result = nf_conntrack_register_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); #else result = nf_conntrack_register_notifier(&init_net, &fast_classifier_conntrack_notifier); +#endif if (result < 0) { DEBUG_ERROR("can't register nf notifier hook: %d\n", result); goto exit4; } #endif + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) result = genl_register_family(&fast_classifier_gnl_family); if (result) { @@ -1865,7 +1881,16 @@ static int __init fast_classifier_init(void) /* * Hook the receive path in the network stack. */ +#ifdef CONFIG_SFE_ECM + rcu_read_lock(); + fast_recv = rcu_dereference(athrs_fast_nat_recv); + rcu_read_unlock(); + if (!fast_recv) { + BUG_ON(athrs_fast_nat_recv); + } +#else BUG_ON(athrs_fast_nat_recv); +#endif RCU_INIT_POINTER(athrs_fast_nat_recv, fast_classifier_recv); /* @@ -1974,3 +1999,4 @@ module_exit(fast_classifier_exit) MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager"); MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/fast-classifier/src/sfe.h b/fast-classifier/src/sfe.h deleted file mode 100644 index 279e7b3dc..000000000 --- a/fast-classifier/src/sfe.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * sfe.h - * Shortcut forwarding engine. - * - * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -/* - * The following are debug macros used throughout the SFE. - * - * The DEBUG_LEVEL enables the followings based on its value, - * when dynamic debug option is disabled. - * - * 0 = OFF - * 1 = ASSERTS / ERRORS - * 2 = 1 + WARN - * 3 = 2 + INFO - * 4 = 3 + TRACE - */ -#define DEBUG_LEVEL 2 - -#if (DEBUG_LEVEL < 1) -#define DEBUG_ASSERT(s, ...) -#define DEBUG_ERROR(s, ...) -#else -#define DEBUG_ASSERT(c, s, ...) if (!(c)) { pr_emerg("ASSERT: %s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); BUG(); } -#define DEBUG_ERROR(s, ...) pr_err("%s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if defined(CONFIG_DYNAMIC_DEBUG) -/* - * Compile messages for dynamic enable/disable - */ -#define DEBUG_WARN(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define DEBUG_INFO(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define DEBUG_TRACE(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#else - -/* - * Statically compile messages at different levels - */ -#if (DEBUG_LEVEL < 2) -#define DEBUG_WARN(s, ...) -#else -#define DEBUG_WARN(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if (DEBUG_LEVEL < 3) -#define DEBUG_INFO(s, ...) -#else -#define DEBUG_INFO(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if (DEBUG_LEVEL < 4) -#define DEBUG_TRACE(s, ...) -#else -#define DEBUG_TRACE(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif -#endif - -#ifdef CONFIG_NF_FLOW_COOKIE -typedef int (*flow_cookie_set_func_t)(u32 protocol, __be32 src_ip, __be16 src_port, - __be32 dst_ip, __be16 dst_port, u16 flow_cookie); -/* - * sfe_register_flow_cookie_cb - * register a function in SFE to let SFE use this function to configure flow cookie for a flow - * - * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE - * can use this function to configure flow cookie for a flow. - * return: 0, success; !=0, fail - */ -int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb); - -/* - * sfe_unregister_flow_cookie_cb - * unregister function which is used to configure flow cookie for a flow - * - * return: 0, success; !=0, fail - */ -int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb); - -typedef int (*sfe_ipv6_flow_cookie_set_func_t)(u32 protocol, __be32 src_ip[4], __be16 src_port, - __be32 dst_ip[4], __be16 dst_port, u16 flow_cookie); - -/* - * sfe_ipv6_register_flow_cookie_cb - * register a function in SFE to let SFE use this function to configure flow cookie for a flow - * - * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE - * can use this function to configure flow cookie for a flow. - * return: 0, success; !=0, fail - */ -int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); - -/* - * sfe_ipv6_unregister_flow_cookie_cb - * unregister function which is used to configure flow cookie for a flow - * - * return: 0, success; !=0, fail - */ -int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); - -#endif /*CONFIG_NF_FLOW_COOKIE*/ diff --git a/fast-classifier/src/sfe_backport.h b/fast-classifier/src/sfe_backport.h deleted file mode 100644 index 2f8c8ca3c..000000000 --- a/fast-classifier/src/sfe_backport.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * sfe_backport.h - * Shortcut forwarding engine compatible header file. - * - * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) -#include -#else -enum udp_conntrack { - UDP_CT_UNREPLIED, - UDP_CT_REPLIED, - UDP_CT_MAX -}; - -static inline unsigned int * -nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct, - struct nf_conntrack_l4proto *l4proto) -{ -#ifdef CONFIG_NF_CONNTRACK_TIMEOUT - struct nf_conn_timeout *timeout_ext; - unsigned int *timeouts; - - timeout_ext = nf_ct_timeout_find(ct); - if (timeout_ext) - timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); - else - timeouts = l4proto->get_timeouts(net); - - return timeouts; -#else - return l4proto->get_timeouts(net); -#endif /*CONFIG_NF_CONNTRACK_TIMEOUT*/ -} -#endif /*KERNEL_VERSION(3, 7, 0)*/ -#endif /*KERNEL_VERSION(3, 4, 0)*/ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) -#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ -static unsigned int FN_NAME(void *priv, \ - struct sk_buff *SKB, \ - const struct nf_hook_state *state) -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ -static unsigned int FN_NAME(const struct nf_hook_ops *OPS, \ - struct sk_buff *SKB, \ - const struct net_device *UNUSED, \ - const struct net_device *OUT, \ - int (*OKFN)(struct sk_buff *)) -#else -#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ -static unsigned int FN_NAME(unsigned int HOOKNUM, \ - struct sk_buff *SKB, \ - const struct net_device *UNUSED, \ - const struct net_device *OUT, \ - int (*OKFN)(struct sk_buff *)) -#endif - -#define sfe_cm_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__sfe_cm_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) -#define sfe_cm_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__sfe_cm_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) -#define fast_classifier_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__fast_classifier_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) -#define fast_classifier_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ - sfe_define_post_routing_hook(__fast_classifier_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) -#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .pf = NFPROTO_IPV4, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP_PRI_NAT_SRC + 1, \ - } -#else -#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .owner = THIS_MODULE, \ - .pf = NFPROTO_IPV4, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP_PRI_NAT_SRC + 1, \ - } -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) -#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .pf = NFPROTO_IPV6, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP_PRI_NAT_SRC + 1, \ - } -#else -#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ - { \ - .hook = fn, \ - .owner = THIS_MODULE, \ - .pf = NFPROTO_IPV6, \ - .hooknum = NF_INET_POST_ROUTING, \ - .priority = NF_IP6_PRI_NAT_SRC + 1, \ - } -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) -#define SFE_NF_CT_DEFAULT_ZONE (&nf_ct_zone_dflt) -#else -#define SFE_NF_CT_DEFAULT_ZONE NF_CT_DEFAULT_ZONE -#endif - -/* - * sfe_dev_get_master - * get master of bridge port, and hold it - */ -static inline struct net_device *sfe_dev_get_master(struct net_device *dev) -{ - struct net_device *master; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) - rcu_read_lock(); - master = netdev_master_upper_dev_get_rcu(dev); - if (master) - dev_hold(master); - - rcu_read_unlock(); -#else - master = dev->master; - if (master) - dev_hold(master); -#endif - return master; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) -#define SFE_DEV_EVENT_PTR(PTR) netdev_notifier_info_to_dev(PTR) -#else -#define SFE_DEV_EVENT_PTR(PTR) (struct net_device *)(PTR) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -#define SFE_NF_CONN_ACCT(NM) struct nf_conn_acct *NM -#else -#define SFE_NF_CONN_ACCT(NM) struct nf_conn_counter *NM -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) -#define SFE_ACCT_COUNTER(NM) ((NM)->counter) -#else -#define SFE_ACCT_COUNTER(NM) (NM) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) -#define sfe_hash_for_each_possible(name, obj, node, member, key) \ - hash_for_each_possible(name, obj, member, key) -#else -#define sfe_hash_for_each_possible(name, obj, node, member, key) \ - hash_for_each_possible(name, obj, node, member, key) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) -#define sfe_hash_for_each(name, bkt, node, obj, member) \ - hash_for_each(name, bkt, obj, member) -#else -#define sfe_hash_for_each(name, bkt, node, obj, member) \ - hash_for_each(name, bkt, node, obj, member) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) -#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, daddr) -#else -static inline struct neighbour * -sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr) -{ - struct neighbour *neigh = dst_get_neighbour_noref(dst); - - if (neigh) - neigh_hold(neigh); - - return neigh; -} -#endif diff --git a/fast-classifier/src/sfe_cm.h b/fast-classifier/src/sfe_cm.h deleted file mode 100644 index 23cbde859..000000000 --- a/fast-classifier/src/sfe_cm.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * sfe_cm.h - * Shortcut forwarding engine. - * - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * connection flags. - */ -#define SFE_CREATE_FLAG_NO_SEQ_CHECK BIT(0) - /* Indicates that we should not check sequence numbers */ -#define SFE_CREATE_FLAG_REMARK_PRIORITY BIT(1) - /* Indicates that we should remark priority of skb */ -#define SFE_CREATE_FLAG_REMARK_DSCP BIT(2) - /* Indicates that we should remark DSCP of packet */ - -/* - * IPv6 address structure - */ -struct sfe_ipv6_addr { - __be32 addr[4]; -}; - -typedef union { - __be32 ip; - struct sfe_ipv6_addr ip6[1]; -} sfe_ip_addr_t; - -/* - * connection creation structure. - */ -struct sfe_connection_create { - int protocol; - struct net_device *src_dev; - struct net_device *dest_dev; - u32 flags; - u32 src_mtu; - u32 dest_mtu; - sfe_ip_addr_t src_ip; - sfe_ip_addr_t src_ip_xlate; - sfe_ip_addr_t dest_ip; - sfe_ip_addr_t dest_ip_xlate; - __be16 src_port; - __be16 src_port_xlate; - __be16 dest_port; - __be16 dest_port_xlate; - u8 src_mac[ETH_ALEN]; - u8 src_mac_xlate[ETH_ALEN]; - u8 dest_mac[ETH_ALEN]; - u8 dest_mac_xlate[ETH_ALEN]; - u8 src_td_window_scale; - u32 src_td_max_window; - u32 src_td_end; - u32 src_td_max_end; - u8 dest_td_window_scale; - u32 dest_td_max_window; - u32 dest_td_end; - u32 dest_td_max_end; - u32 mark; -#ifdef CONFIG_XFRM - u32 original_accel; - u32 reply_accel; -#endif - u32 src_priority; - u32 dest_priority; - u32 src_dscp; - u32 dest_dscp; -}; - -/* - * connection destruction structure. - */ -struct sfe_connection_destroy { - int protocol; - sfe_ip_addr_t src_ip; - sfe_ip_addr_t dest_ip; - __be16 src_port; - __be16 dest_port; -}; - -typedef enum sfe_sync_reason { - SFE_SYNC_REASON_STATS, /* Sync is to synchronize stats */ - SFE_SYNC_REASON_FLUSH, /* Sync is to flush a entry */ - SFE_SYNC_REASON_DESTROY /* Sync is to destroy a entry(requested by connection manager) */ -} sfe_sync_reason_t; - -/* - * Structure used to sync connection stats/state back within the system. - * - * NOTE: The addresses here are NON-NAT addresses, i.e. the true endpoint addressing. - * 'src' is the creator of the connection. - */ -struct sfe_connection_sync { - struct net_device *src_dev; - struct net_device *dest_dev; - int is_v6; /* Is it for ipv6? */ - int protocol; /* IP protocol number (IPPROTO_...) */ - sfe_ip_addr_t src_ip; /* Non-NAT source address, i.e. the creator of the connection */ - sfe_ip_addr_t src_ip_xlate; /* NATed source address */ - __be16 src_port; /* Non-NAT source port */ - __be16 src_port_xlate; /* NATed source port */ - sfe_ip_addr_t dest_ip; /* Non-NAT destination address, i.e. to whom the connection was created */ - sfe_ip_addr_t dest_ip_xlate; /* NATed destination address */ - __be16 dest_port; /* Non-NAT destination port */ - __be16 dest_port_xlate; /* NATed destination port */ - u32 src_td_max_window; - u32 src_td_end; - u32 src_td_max_end; - u64 src_packet_count; - u64 src_byte_count; - u32 src_new_packet_count; - u32 src_new_byte_count; - u32 dest_td_max_window; - u32 dest_td_end; - u32 dest_td_max_end; - u64 dest_packet_count; - u64 dest_byte_count; - u32 dest_new_packet_count; - u32 dest_new_byte_count; - u32 reason; /* reason for stats sync message, i.e. destroy, flush, period sync */ - u64 delta_jiffies; /* Time to be added to the current timeout to keep the connection alive */ -}; - -/* - * connection mark structure - */ -struct sfe_connection_mark { - int protocol; - sfe_ip_addr_t src_ip; - sfe_ip_addr_t dest_ip; - __be16 src_port; - __be16 dest_port; - u32 mark; -}; - -/* - * Expose the hook for the receive processing. - */ -extern int (*athrs_fast_nat_recv)(struct sk_buff *skb); - -/* - * Expose what should be a static flag in the TCP connection tracker. - */ -extern int nf_ct_tcp_no_window_check; - -/* - * This callback will be called in a timer - * at 100 times per second to sync stats back to - * Linux connection track. - * - * A RCU lock is taken to prevent this callback - * from unregistering. - */ -typedef void (*sfe_sync_rule_callback_t)(struct sfe_connection_sync *); - -/* - * IPv4 APIs used by connection manager - */ -int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb); -int sfe_ipv4_create_rule(struct sfe_connection_create *sic); -void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid); -void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev); -void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callback); -void sfe_ipv4_update_rule(struct sfe_connection_create *sic); -void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark); - -#ifdef SFE_SUPPORT_IPV6 -/* - * IPv6 APIs used by connection manager - */ -int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb); -int sfe_ipv6_create_rule(struct sfe_connection_create *sic); -void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid); -void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev); -void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback); -void sfe_ipv6_update_rule(struct sfe_connection_create *sic); -void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark); -#else -static inline int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) -{ - return 0; -} - -static inline int sfe_ipv6_create_rule(struct sfe_connection_create *sic) -{ - return 0; -} - -static inline void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) -{ - return; -} - -static inline void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) -{ - return; -} - -static inline void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback) -{ - return; -} - -static inline void sfe_ipv6_update_rule(struct sfe_connection_create *sic) -{ - return; -} - -static inline void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) -{ - return; -} -#endif - -/* - * sfe_ipv6_addr_equal() - * compare ipv6 address - * - * return: 1, equal; 0, no equal - */ -static inline int sfe_ipv6_addr_equal(struct sfe_ipv6_addr *a, - struct sfe_ipv6_addr *b) -{ - return a->addr[0] == b->addr[0] && - a->addr[1] == b->addr[1] && - a->addr[2] == b->addr[2] && - a->addr[3] == b->addr[3]; -} - -/* - * sfe_ipv4_addr_equal() - * compare ipv4 address - * - * return: 1, equal; 0, no equal - */ -#define sfe_ipv4_addr_equal(a, b) ((u32)(a) == (u32)(b)) - -/* - * sfe_addr_equal() - * compare ipv4 or ipv6 address - * - * return: 1, equal; 0, no equal - */ -static inline int sfe_addr_equal(sfe_ip_addr_t *a, - sfe_ip_addr_t *b, int is_v4) -{ - return is_v4 ? sfe_ipv4_addr_equal(a->ip, b->ip) : sfe_ipv6_addr_equal(a->ip6, b->ip6); -} diff --git a/shortcut-fe/Makefile b/shortcut-fe/Makefile index 54711c46a..dd53042e5 100644 --- a/shortcut-fe/Makefile +++ b/shortcut-fe/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2014 The Linux Foundation. All rights reserved. +# Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the # above copyright notice and this permission notice appear in all copies. @@ -11,12 +11,12 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # + include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=shortcut-fe -PKG_RELEASE:=2 -PKG_CONFIG_DEPENDS := CONFIG_IPV6 +PKG_RELEASE:=8 include $(INCLUDE_DIR)/package.mk @@ -24,13 +24,17 @@ define KernelPackage/shortcut-fe SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support - DEPENDS:= + DEPENDS:=@IPV6 +kmod-nf-conntrack TITLE:=Kernel driver for SFE - FILES:=$(PKG_BUILD_DIR)/shortcut-fe.ko $(if $(CONFIG_IPV6),$(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko,) - KCONFIG:=CONFIG_NF_CONNTRACK_EVENTS=y \ + FILES:= \ + $(PKG_BUILD_DIR)/shortcut-fe.ko \ + $(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko + KCONFIG:= \ + CONFIG_NF_CONNTRACK_EVENTS=y \ CONFIG_NF_CONNTRACK_TIMEOUT=y \ CONFIG_SHORTCUT_FE=y \ CONFIG_XFRM=y + PROVIDES:=$(PKG_NAME) AUTOLOAD:=$(call AutoLoad,09,shortcut-fe shortcut-fe-ipv6) endef @@ -43,6 +47,8 @@ define KernelPackage/shortcut-fe/install $(INSTALL_BIN) ./files/usr/bin/sfe_dump $(1)/usr/bin endef +HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard) + define KernelPackage/shortcut-fe-cm SECTION:=kernel CATEGORY:=Kernel modules @@ -50,7 +56,11 @@ define KernelPackage/shortcut-fe-cm DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe TITLE:=Kernel driver for SFE FILES:=$(PKG_BUILD_DIR)/shortcut-fe-cm.ko - KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y + KCONFIG:= \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_XFRM=y + CONFLICTS:=kmod-shortcut-fe-drv endef define KernelPackage/shortcut-fe-cm/Description @@ -58,20 +68,21 @@ Simple connection manager for the Shortcut forwarding engine. endef define Build/Compile - +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ $(KERNEL_MAKE_FLAGS) \ $(PKG_MAKE_FLAGS) \ M="$(PKG_BUILD_DIR)" \ - modules \ - $(if $(CONFIG_IPV6),EXTRA_CFLAGS="-DSFE_SUPPORT_IPV6" SFE_SUPPORT_IPV6=y,) + EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" SFE_SUPPORT_IPV6=y \ + $(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \ + modules endef -#ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm),) +ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm),) define Build/InstallDev $(INSTALL_DIR) $(1)/usr/include/shortcut-fe $(CP) -rf $(PKG_BUILD_DIR)/sfe.h $(1)/usr/include/shortcut-fe endef -#endif +endif $(eval $(call KernelPackage,shortcut-fe)) $(eval $(call KernelPackage,shortcut-fe-cm)) diff --git a/shortcut-fe/files/etc/init.d/shortcut-fe b/shortcut-fe/files/etc/init.d/shortcut-fe new file mode 100755 index 000000000..838512a36 --- /dev/null +++ b/shortcut-fe/files/etc/init.d/shortcut-fe @@ -0,0 +1,51 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +#SFE connection manager has a lower priority, it should be started after other connection manager +#to detect the existence of connection manager with higher priority +START=70 + +have_cm() { + [ -d "/sys/kernel/debug/ecm" ] && echo 1 && return + + echo 0 +} + +#load shortcut-fe and connection manager +load_sfe() { + local kernel_version=$(uname -r) + + [ -d "/sys/module/shortcut_fe" ] || insmod /lib/modules/$kernel_version/shortcut-fe.ko + [ -d "/sys/module/shortcut_fe_ipv6" ] || insmod /lib/modules/$kernel_version/shortcut-fe-ipv6.ko + + [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { + [ -d /sys/module/shortcut_fe_cm ] || insmod /lib/modules/$kernel_version/shortcut-fe-cm.ko + } + [ -e "/lib/modules/$kernel_version/fast-classifier.ko" ] && { + [ -d /sys/module/fast_classifier ] || insmod /lib/modules/$kernel_version/fast-classifier.ko + } +} + +start() { + [ "$(have_cm)" = "0" ] && load_sfe +} + +stop() { + [ -d "/sys/module/shortcut_fe_cm" ] && rmmod shortcut_fe_cm + [ -d "/sys/module/shortcut_fe_ipv6" ] && rmmod shortcut_fe_ipv6 + [ -d "/sys/module/shortcut_fe" ] && rmmod shortcut_fe + [ -d "/sys/module/shortcut_fe_drv" ] && rmmod shortcut_fe_drv + [ -d "/sys/module/fast_classifier" ] && rmmod fast_classifier +} diff --git a/shortcut-fe/files/usr/bin/sfe_dump b/shortcut-fe/files/usr/bin/sfe_dump old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/Kconfig b/shortcut-fe/src/Kconfig index f45e56b47..487f1e065 100644 --- a/shortcut-fe/src/Kconfig +++ b/shortcut-fe/src/Kconfig @@ -5,8 +5,7 @@ config SHORTCUT_FE tristate "Shortcut Forwarding Engine" depends on NF_CONNTRACK - default n - help + ---help--- Shortcut is a fast in-kernel packet forwarding engine. To compile this code as a module, choose M here: the module will be diff --git a/shortcut-fe/src/Makefile b/shortcut-fe/src/Makefile index 3b1ceaa44..991a20ec6 100644 --- a/shortcut-fe/src/Makefile +++ b/shortcut-fe/src/Makefile @@ -21,3 +21,4 @@ endif shortcut-fe-cm-objs := \ sfe_cm.o +ccflags-y += -Werror -Wall diff --git a/shortcut-fe/src/sfe_backport.h b/shortcut-fe/src/sfe_backport.h index 2f8c8ca3c..d2d60c73c 100644 --- a/shortcut-fe/src/sfe_backport.h +++ b/shortcut-fe/src/sfe_backport.h @@ -180,7 +180,7 @@ static inline struct net_device *sfe_dev_get_master(struct net_device *dev) #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) -#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, daddr) +#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, addr) #else static inline struct neighbour * sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr) diff --git a/shortcut-fe/src/sfe_cm.c b/shortcut-fe/src/sfe_cm.c index 18f3475e5..2d3f79a04 100644 --- a/shortcut-fe/src/sfe_cm.c +++ b/shortcut-fe/src/sfe_cm.c @@ -2,7 +2,7 @@ * sfe-cm.c * Shortcut forwarding engine connection manager. * - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -199,7 +199,7 @@ int sfe_cm_recv(struct sk_buff *skb) * structure, obtain the hardware address. This means this function also * works if the neighbours are routers too. */ -static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, int is_v4) +static bool sfe_cm_find_dev_and_mac_addr(struct sk_buff *skb, sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, int is_v4) { struct neighbour *neigh; struct rtable *rt; @@ -207,6 +207,15 @@ static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device struct dst_entry *dst; struct net_device *mac_dev; + /* + * If we have skb provided, use it as the original code is unable + * to lookup routes that are policy routed. + */ + if (unlikely(skb)) { + dst = skb_dst(skb); + goto skip_dst_lookup; + } + /* * Look up the rtable entry for the IP address then get the hardware * address from its neighbour structure. This means this work when the @@ -220,11 +229,11 @@ static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device dst = (struct dst_entry *)rt; } else { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) - rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)) rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0); -#endif /*KERNEL_VERSION(4, 17, 0)*/ +#else + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); +#endif if (!rt6) { goto ret_fail; } @@ -232,18 +241,21 @@ static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device dst = (struct dst_entry *)rt6; } +skip_dst_lookup: rcu_read_lock(); neigh = sfe_dst_get_neighbour(dst, addr); if (unlikely(!neigh)) { rcu_read_unlock(); - dst_release(dst); + if (likely(!skb)) + dst_release(dst); goto ret_fail; } if (unlikely(!(neigh->nud_state & NUD_VALID))) { rcu_read_unlock(); neigh_release(neigh); - dst_release(dst); + if (likely(!skb)) + dst_release(dst); goto ret_fail; } @@ -251,7 +263,8 @@ static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device if (!mac_dev) { rcu_read_unlock(); neigh_release(neigh); - dst_release(dst); + if (likely(!skb)) + dst_release(dst); goto ret_fail; } @@ -261,7 +274,8 @@ static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device *dev = mac_dev; rcu_read_unlock(); neigh_release(neigh); - dst_release(dst); + if (likely(!skb)) + dst_release(dst); return true; @@ -295,7 +309,13 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) struct net_device *dest_br_dev = NULL; struct nf_conntrack_tuple orig_tuple; struct nf_conntrack_tuple reply_tuple; + struct sk_buff *tmp_skb = NULL; SFE_NF_CONN_ACCT(acct); + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + struct net *net=NULL; + struct nf_tcp_net *tn=NULL; + #endif /* * Don't process broadcast or multicast packets. @@ -352,16 +372,18 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) return NF_ACCEPT; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) /* * Don't process untracked connections. */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) if (unlikely(nf_ct_is_untracked(ct))) { +#else + if (unlikely(ctinfo == IP_CT_UNTRACKED)) { +#endif sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_NO_TRACK); DEBUG_TRACE("untracked connection\n"); return NF_ACCEPT; } -#endif /*KERNEL_VERSION(4, 12, 0)*/ /* * Unconfirmed connection may be dropped by Linux at the final step, @@ -479,8 +501,13 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) sic.dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; sic.dest_td_end = ct->proto.tcp.seen[1].td_end; sic.dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; - - if (nf_ct_tcp_no_window_check +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + net = nf_ct_net(ct); + tn = nf_tcp_pernet(net); + if ((tn&&tn->tcp_no_window_check) +#else + if (nf_ct_tcp_no_window_check +#endif || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { sic.flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; @@ -510,6 +537,21 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) return NF_ACCEPT; } spin_unlock_bh(&ct->lock); + + /* + * Somehow, SFE is not playing nice with IPSec traffic. + * Do not accelerate for now. + */ + if (ntohs(sic.dest_port) == 4500 || ntohs(sic.dest_port) == 500) { + if (likely(is_v4)) + DEBUG_TRACE("IPsec bypass: %pI4:%d(%pI4:%d) to %pI4:%d(%pI4:%d)\n", + &sic.src_ip.ip, ntohs(sic.src_port), &sic.src_ip_xlate.ip, ntohs(sic.src_port_xlate), + &sic.dest_ip.ip, ntohs(sic.dest_port), &sic.dest_ip_xlate.ip, ntohs(sic.dest_port_xlate)); + else + DEBUG_TRACE("IPsec bypass: %pI6:%d to %pI6:%d\n", + &sic.src_ip.ip6, ntohs(sic.src_port), &sic.dest_ip.ip6, ntohs(sic.dest_port)); + return NF_ACCEPT; + } break; case IPPROTO_UDP: @@ -533,10 +575,10 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) * For packets de-capsulated from xfrm, we still can accelerate it * on the direction we just received the packet. */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) - if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) if (unlikely(skb->sp)) { +#else + if (unlikely(secpath_exists(skb))) { #endif if (sic.protocol == IPPROTO_TCP && !(sic.flags & SFE_CREATE_FLAG_NO_SEQ_CHECK)) { @@ -564,25 +606,27 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) * Get the net device and MAC addresses that correspond to the various source and * destination host addresses. */ - if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { + if (!sfe_cm_find_dev_and_mac_addr(NULL, &sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_DEV); return NF_ACCEPT; } src_dev = src_dev_tmp; - if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { + if (!sfe_cm_find_dev_and_mac_addr(NULL, &sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV); goto done1; } dev_put(dev); - - if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip, &dev, sic.dest_mac, is_v4)) { + /* Somehow, for IPv6, we need this workaround as well */ + if (unlikely(!is_v4)) + tmp_skb = skb; + if (!sfe_cm_find_dev_and_mac_addr(tmp_skb, &sic.dest_ip, &dev, sic.dest_mac, is_v4)) { sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_DEV); goto done1; } dev_put(dev); - if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { + if (!sfe_cm_find_dev_and_mac_addr(skb, &sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV); goto done1; } @@ -688,14 +732,11 @@ static int sfe_cm_conntrack_event(unsigned int events, struct nf_ct_event *item) } #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) - /* - * If this is an untracked connection then we can't have any state either. - */ if (unlikely(nf_ct_is_untracked(ct))) { DEBUG_TRACE("ignoring untracked conn\n"); return NOTIFY_DONE; } -#endif /*KERNEL_VERSION(4, 12, 0)*/ +#endif /* * We're only interested in destroy events. @@ -825,18 +866,17 @@ static void sfe_cm_sync_rule(struct sfe_connection_sync *sis) ct = nf_ct_tuplehash_to_ctrack(h); #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); -#endif /*KERNEL_VERSION(4, 9, 0)*/ - +#endif /* * Only update if this is not a fixed timeout */ if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { spin_lock_bh(&ct->lock); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) - ct->timeout += sis->delta_jiffies; -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) ct->timeout.expires += sis->delta_jiffies; -#endif /*KERNEL_VERSION(4, 9, 0)*/ +#else + ct->timeout += sis->delta_jiffies; +#endif spin_unlock_bh(&ct->lock); } @@ -891,26 +931,26 @@ static void sfe_cm_sync_rule(struct sfe_connection_sync *sis) if (reply_pkts != 0) { unsigned int *timeouts; - + struct nf_conntrack_l4proto *l4proto __maybe_unused; set_bit(IPS_SEEN_REPLY_BIT, &ct->status); set_bit(IPS_ASSURED_BIT, &ct->status); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) - timeouts = nf_ct_timeout_lookup(ct); -#else - struct nf_conntrack_l4proto *l4proto; - +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) l4proto = __nf_ct_l4proto_find((sis->is_v6 ? AF_INET6 : AF_INET), IPPROTO_UDP); timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); -#endif /*KERNEL_VERSION(4, 19, 0)*/ + spin_lock_bh(&ct->lock); + ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; + spin_unlock_bh(&ct->lock); +#else + timeouts = nf_ct_timeout_lookup(ct); + if (!timeouts) { + timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts; + } spin_lock_bh(&ct->lock); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; -#else - ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; -#endif /*KERNEL_VERSION(4, 9, 0)*/ spin_unlock_bh(&ct->lock); +#endif } } break; @@ -1001,6 +1041,9 @@ static int __init sfe_cm_init(void) { struct sfe_cm *sc = &__sc; int result = -1; +#ifdef CONFIG_SFE_ECM + int (*fast_recv)(struct sk_buff *skb); +#endif DEBUG_INFO("SFE CM init\n"); @@ -1036,7 +1079,11 @@ static int __init sfe_cm_init(void) /* * Register our netfilter hooks. */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + result = nf_register_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#else result = nf_register_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#endif if (result < 0) { DEBUG_ERROR("can't register nf post routing hook: %d\n", result); goto exit3; @@ -1049,22 +1096,30 @@ static int __init sfe_cm_init(void) */ #ifdef CONFIG_NF_CONNTRACK_EVENTS #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS - (void)nf_conntrack_register_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); + result = nf_conntrack_register_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); #else result = nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier); +#endif if (result < 0) { DEBUG_ERROR("can't register nf notifier hook: %d\n", result); goto exit4; } #endif -#endif - spin_lock_init(&sc->lock); /* * Hook the receive path in the network stack. */ +#ifdef CONFIG_SFE_ECM + rcu_read_lock(); + fast_recv = rcu_dereference(athrs_fast_nat_recv); + rcu_read_unlock(); + if (!fast_recv) { + BUG_ON(athrs_fast_nat_recv); + } +#else BUG_ON(athrs_fast_nat_recv); +#endif RCU_INIT_POINTER(athrs_fast_nat_recv, sfe_cm_recv); /* @@ -1075,10 +1130,15 @@ static int __init sfe_cm_init(void) return 0; #ifdef CONFIG_NF_CONNTRACK_EVENTS -#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS exit4: +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#else nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); #endif + +#endif #endif exit3: unregister_inet6addr_notifier(&sc->inet6_notifier); @@ -1129,8 +1189,12 @@ static void __exit sfe_cm_exit(void) nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier); #endif #endif - nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#else + nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#endif unregister_inet6addr_notifier(&sc->inet6_notifier); unregister_inetaddr_notifier(&sc->inet_notifier); unregister_netdevice_notifier(&sc->dev_notifier); diff --git a/shortcut-fe/src/sfe_cm.h b/shortcut-fe/src/sfe_cm.h index 23cbde859..124c86f47 100644 --- a/shortcut-fe/src/sfe_cm.h +++ b/shortcut-fe/src/sfe_cm.h @@ -152,8 +152,9 @@ extern int (*athrs_fast_nat_recv)(struct sk_buff *skb); /* * Expose what should be a static flag in the TCP connection tracker. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) extern int nf_ct_tcp_no_window_check; - +#endif /* * This callback will be called in a timer * at 100 times per second to sync stats back to diff --git a/shortcut-fe/src/sfe_ipv4.c b/shortcut-fe/src/sfe_ipv4.c index 531456c05..cdcdd66dd 100644 --- a/shortcut-fe/src/sfe_ipv4.c +++ b/shortcut-fe/src/sfe_ipv4.c @@ -2,7 +2,7 @@ * sfe_ipv4.c * Shortcut forwarding engine - IPv4 edition. * - * Copyright (c) 2013-2016, 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, 2019-2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -1311,14 +1311,13 @@ static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne * change the cloned skb's data section. */ if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); skb = skb_unshare(skb, GFP_ATOMIC); if (!skb) { DEBUG_WARN("Failed to unshare the cloned skb\n"); si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; si->packets_not_forwarded++; spin_unlock_bh(&si->lock); - return 0; } @@ -1891,14 +1890,13 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne * change the cloned skb's data section. */ if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); skb = skb_unshare(skb, GFP_ATOMIC); if (!skb) { DEBUG_WARN("Failed to unshare the cloned skb\n"); si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; si->packets_not_forwarded++; spin_unlock_bh(&si->lock); - return 0; } @@ -2512,7 +2510,7 @@ int sfe_ipv4_create_rule(struct sfe_connection_create *sic) spin_unlock_bh(&si->lock); DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" - " s: %s:%pM:%pI4:%u, d: %s:%pM:%pI4:%u\n", + " s: %s:%pxM:%pI4:%u, d: %s:%pxM:%pI4:%u\n", sic->mark, sic->protocol, sic->src_dev->name, sic->src_mac, &sic->src_ip.ip, ntohs(sic->src_port), sic->dest_dev->name, sic->dest_mac, &sic->dest_ip.ip, ntohs(sic->dest_port)); @@ -2728,8 +2726,8 @@ int sfe_ipv4_create_rule(struct sfe_connection_create *sic) * We have everything we need! */ DEBUG_INFO("new connection - mark: %08x, p: %d\n" - " s: %s:%pM(%pM):%pI4(%pI4):%u(%u)\n" - " d: %s:%pM(%pM):%pI4(%pI4):%u(%u)\n", + " s: %s:%pxM(%pxM):%pI4(%pI4):%u(%u)\n" + " d: %s:%pxM(%pxM):%pI4(%pI4):%u(%u)\n", sic->mark, sic->protocol, sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, &sic->src_ip.ip, &sic->src_ip_xlate.ip, ntohs(sic->src_port), ntohs(sic->src_port_xlate), @@ -2858,17 +2856,17 @@ another_round: /* * sfe_ipv4_periodic_sync() */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) -static void sfe_ipv4_periodic_sync(struct timer_list *arg) -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) static void sfe_ipv4_periodic_sync(unsigned long arg) -#endif /*KERNEL_VERSION(4, 15, 0)*/ -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) - struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg->cust_data; #else +static void sfe_ipv4_periodic_sync(struct timer_list *tl) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg; -#endif /*KERNEL_VERSION(4, 15, 0)*/ +#else + struct sfe_ipv4 *si = from_timer(si, tl, timer); +#endif u64 now_jiffies; int quota; sfe_sync_rule_callback_t sync_rule_callback; @@ -3547,12 +3545,11 @@ static int __init sfe_ipv4_init(void) /* * Create a timer to handle periodic statistics. */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) - timer_setup(&si->timer, sfe_ipv4_periodic_sync, 0); - si->timer.cust_data = (unsigned long)si; -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) setup_timer(&si->timer, sfe_ipv4_periodic_sync, (unsigned long)si); -#endif /*KERNEL_VERSION(4, 15, 0)*/ +#else + timer_setup(&si->timer, sfe_ipv4_periodic_sync, 0); +#endif mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); spin_lock_init(&si->lock); diff --git a/shortcut-fe/src/sfe_ipv6.c b/shortcut-fe/src/sfe_ipv6.c index 3c5ef1263..ae3306693 100644 --- a/shortcut-fe/src/sfe_ipv6.c +++ b/shortcut-fe/src/sfe_ipv6.c @@ -2,7 +2,7 @@ * sfe_ipv6.c * Shortcut forwarding engine - IPv6 support. * - * Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2019-2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -1369,14 +1369,13 @@ static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne * change the cloned skb's data section. */ if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); skb = skb_unshare(skb, GFP_ATOMIC); if (!skb) { DEBUG_WARN("Failed to unshare the cloned skb\n"); si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; si->packets_not_forwarded++; spin_unlock_bh(&si->lock); - return 0; } @@ -1929,14 +1928,13 @@ static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne * change the cloned skb's data section. */ if (unlikely(skb_cloned(skb))) { - DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + DEBUG_TRACE("%px: skb is a cloned skb\n", skb); skb = skb_unshare(skb, GFP_ATOMIC); if (!skb) { DEBUG_WARN("Failed to unshare the cloned skb\n"); si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; si->packets_not_forwarded++; spin_unlock_bh(&si->lock); - return 0; } @@ -2328,7 +2326,7 @@ int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) si->packets_not_forwarded++; spin_unlock_bh(&si->lock); - DEBUG_TRACE("payload_len: %u, exceeds len: %u\n", payload_len, (len - sizeof(struct sfe_ipv6_ip_hdr))); + DEBUG_TRACE("payload_len: %u, exceeds len: %u\n", payload_len, (len - (unsigned int)sizeof(struct sfe_ipv6_ip_hdr))); return 0; } @@ -2526,7 +2524,7 @@ int sfe_ipv6_create_rule(struct sfe_connection_create *sic) spin_unlock_bh(&si->lock); DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" - " s: %s:%pM:%pI6:%u, d: %s:%pM:%pI6:%u\n", + " s: %s:%pxM:%pI6:%u, d: %s:%pxM:%pI6:%u\n", sic->mark, sic->protocol, sic->src_dev->name, sic->src_mac, sic->src_ip.ip6, ntohs(sic->src_port), sic->dest_dev->name, sic->dest_mac, sic->dest_ip.ip6, ntohs(sic->dest_port)); @@ -2742,8 +2740,8 @@ int sfe_ipv6_create_rule(struct sfe_connection_create *sic) * We have everything we need! */ DEBUG_INFO("new connection - mark: %08x, p: %d\n" - " s: %s:%pM(%pM):%pI6(%pI6):%u(%u)\n" - " d: %s:%pM(%pM):%pI6(%pI6):%u(%u)\n", + " s: %s:%pxM(%pxM):%pI6(%pI6):%u(%u)\n" + " d: %s:%pxM(%pxM):%pI6(%pI6):%u(%u)\n", sic->mark, sic->protocol, sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, sic->src_ip.ip6, sic->src_ip_xlate.ip6, ntohs(sic->src_port), ntohs(sic->src_port_xlate), @@ -2866,17 +2864,17 @@ another_round: /* * sfe_ipv6_periodic_sync() */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) -static void sfe_ipv6_periodic_sync(struct timer_list *arg) -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) static void sfe_ipv6_periodic_sync(unsigned long arg) -#endif /*KERNEL_VERSION(4, 15, 0)*/ -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) - struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg->cust_data; #else +static void sfe_ipv6_periodic_sync(struct timer_list *tl) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg; -#endif /*KERNEL_VERSION(4, 15, 0)*/ +#else + struct sfe_ipv6 *si = from_timer(si, tl, timer); +#endif u64 now_jiffies; int quota; sfe_sync_rule_callback_t sync_rule_callback; @@ -3555,12 +3553,11 @@ static int __init sfe_ipv6_init(void) /* * Create a timer to handle periodic statistics. */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) - timer_setup(&si->timer, sfe_ipv6_periodic_sync, 0); - si->timer.cust_data = (unsigned long)si; -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) setup_timer(&si->timer, sfe_ipv6_periodic_sync, (unsigned long)si); -#endif /*KERNEL_VERSION(4, 15, 0)*/ +#else + timer_setup(&si->timer, sfe_ipv6_periodic_sync, 0); +#endif mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); spin_lock_init(&si->lock); diff --git a/simulated-driver/Makefile b/simulated-driver/Makefile new file mode 100644 index 000000000..ecf9c41bd --- /dev/null +++ b/simulated-driver/Makefile @@ -0,0 +1,60 @@ +# +# Copyright (c) 2015,2016 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=shortcut-fe-simulated-driver +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/shortcut-fe +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-03-17 +PKG_SOURCE_VERSION:=697977d8d0ccf0ab596e5692d08608a75dd7f33d +PKG_MIRROR_HASH:=659fa82a431e15af797a6c7069faeee02810453ad8b576c51c29f95a1761a045 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/shortcut-fe-drv + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe + KCONFIG:= \ + CONFIG_NET_CLS_ACT=y \ + CONFIG_XFRM=y + TITLE:=Simulated sfe driver for ECM + FILES:=$(PKG_BUILD_DIR)/simulated-driver/shortcut-fe-drv.ko +endef + +define KernelPackage/shortcut-fe-drv/Description +Simulated sfe driver which act as an adapter to convert message +between a connection manager and the SFE core engine. +endef + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)/simulated-driver" \ + EXTRA_CFLAGS="-DSFE_SUPPORT_IPV6" \ + modules +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/shortcut-fe + $(CP) -rf $(PKG_BUILD_DIR)/simulated-driver/sfe_drv.h $(1)/usr/include/shortcut-fe +endef + +$(eval $(call KernelPackage,shortcut-fe-drv)) diff --git a/simulated-driver/patches/200-nss-qdisc-support.patch b/simulated-driver/patches/200-nss-qdisc-support.patch new file mode 100644 index 000000000..638ad8a84 --- /dev/null +++ b/simulated-driver/patches/200-nss-qdisc-support.patch @@ -0,0 +1,11 @@ +--- ./simulated-driver/sfe_drv.c.orig 2020-06-16 12:49:47.680153371 +0800 ++++ ./simulated-driver/sfe_drv.c 2020-06-16 12:50:18.540153371 +0800 +@@ -1167,7 +1167,7 @@ int sfe_drv_recv(struct sk_buff *skb) + * If ingress Qdisc configured, and packet not processed by ingress Qdisc yet + * We can not accelerate this packet. + */ +- if (dev->ingress_queue && !(skb->tc_verd & TC_NCLS)) { ++ if (dev->ingress_queue && !(skb->tc_verd_qca_nss & TC_NCLS)) { + return 0; + } + #endif From 915501a3efae5daa987f1dd65a59ca3d62123f9f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:48:33 +0100 Subject: [PATCH 0893/2059] Update r8168 --- r8168/Makefile | 25 +++++-------------------- r8168/patches/030-6.1-support.patch | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 20 deletions(-) create mode 100644 r8168/patches/030-6.1-support.patch diff --git a/r8168/Makefile b/r8168/Makefile index 6ec31651c..8f810c518 100644 --- a/r8168/Makefile +++ b/r8168/Makefile @@ -7,19 +7,16 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=r8168 -PKG_VERSION:=8.050.03 -PKG_RELEASE:=$(AUTORELEAE) +PKG_VERSION:=8.051.02 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/BROBIRD/openwrt-r8168.git -PKG_SOURCE_DATE:=2022-06-15 -PKG_SOURCE_VERSION:=ddfaceacd1b7ed2857fb995642a8ffb1fc37e989 -#PKG_MIRROR_HASH:=e4632c10d460f005eff76da8a183d7ff0c8819b0d099872589b7b06a9b8d9952 +PKG_SOURCE_VERSION:=4f6cfe1ca12fb772deed57f1d2d1062af041ad07 +PKG_MIRROR_HASH:=6b149f5eb3b9e1dc50867a694984d253aa58d97dd5fbab30eb405d2d7b2be587 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) -MAKE_PATH:=src - include $(INCLUDE_DIR)/package.mk define KernelPackage/r8168 @@ -35,20 +32,8 @@ define Package/r8168/description This package contains a driver for Realtek r8168 chipsets. endef -R8168_MAKEOPTS= -C $(PKG_BUILD_DIR)/src \ - PATH="$(TARGET_PATH)" \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - TARGET="$(HAL_TARGET)" \ - TOOLPREFIX="$(KERNEL_CROSS)" \ - TOOLPATH="$(KERNEL_CROSS)" \ - KERNELPATH="$(LINUX_DIR)" \ - KERNELDIR="$(LINUX_DIR)" \ - LDOPTS=" " \ - DOMULTI=1 - define Build/Compile - $(MAKE) $(R8168_MAKEOPTS) modules + +$(KERNEL_MAKE) M=$(PKG_BUILD_DIR)/src modules endef $(eval $(call KernelPackage,r8168)) diff --git a/r8168/patches/030-6.1-support.patch b/r8168/patches/030-6.1-support.patch new file mode 100644 index 000000000..44ab2be19 --- /dev/null +++ b/r8168/patches/030-6.1-support.patch @@ -0,0 +1,14 @@ +--- a/src/r8168.h +--- b/src/r8168.h +@@ -566,7 +566,11 @@ + typedef struct napi_struct *napi_ptr; + typedef int napi_budget; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add_weight(ndev, &priv->napi, function, weight) ++#else + #define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) ++#endif + #define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) + #define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) + #define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; From a90fd8429777d8d87a10dae43d03a319efd29533 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:48:51 +0100 Subject: [PATCH 0894/2059] Update xtables-addons --- xtables-addons/Makefile | 6 +- ...-packetscript-kernel-5.16-no-isystem.patch | 284 ++++++++++++++++++ 2 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch diff --git a/xtables-addons/Makefile b/xtables-addons/Makefile index fa7587589..cba09357d 100644 --- a/xtables-addons/Makefile +++ b/xtables-addons/Makefile @@ -9,9 +9,9 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=xtables-addons -PKG_VERSION:=3.18 -PKG_RELEASE:=4 -PKG_HASH:=a77914a483ff381663f52120577e5e9355ca07cca73958b038e09d91247458d5 +PKG_VERSION:=3.22 +PKG_RELEASE:=$(AUTORELEASE) +PKG_HASH:=faa16a27166275afbfe8df605f55c3a81ac693bf19da674d45ceded4137ae217 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://inai.de/files/xtables-addons/ diff --git a/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch b/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch new file mode 100644 index 000000000..5279619da --- /dev/null +++ b/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch @@ -0,0 +1,284 @@ +Linux 5.16 includes 04e85bbf71c9 ("isystem: delete global -isystem compile option") + +compile error on >=5.16 +xtables-addons-3.21/extensions/LUA/lua/lua.h:12:10: fatal error: stdarg.h: No such file or directory + 12 | #include + | ^~~~~~~~~~ + +Generated with coccinelle: + +cat <cocci-xtables-lua-linux-5.16.spatch +@include_arg@ +@@ + #include + +@include_def@ +@@ + #include + +@include_both depends on include_arg && include_def@ +@@ + #include + +@add_include_linux_stdheaders_both depends on include_both@ +@@ ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) +?#include +?#include ++#else ++#include ++#include ++#endif + +@add_include_linux_stdheaders depends on !include_both@ +@@ +( ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif +| ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif +) +EOF +spatch --in-place --include-headers --no-includes --sp-file cocci-xtables-lua-linux-5.16.spatch --dir extensions/LUA/lua/ + +--- + +--- a/extensions/LUA/lua/lauxlib.c ++++ b/extensions/LUA/lua/lauxlib.c +@@ -4,7 +4,12 @@ + ** See Copyright Notice in lua.h + */ + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #if !defined(__KERNEL__) + #include +--- a/extensions/LUA/lua/lauxlib.h ++++ b/extensions/LUA/lua/lauxlib.h +@@ -9,7 +9,12 @@ + #define lauxlib_h + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + #include /* for kmalloc and kfree when allocating luaL_Buffer */ + + #if !defined(__KERNEL__) +--- a/extensions/LUA/lua/ldebug.c ++++ b/extensions/LUA/lua/ldebug.c +@@ -5,8 +5,14 @@ + */ + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include + #include ++#else ++#include ++#include ++#endif + #include + + #define ldebug_c +--- a/extensions/LUA/lua/ldump.c ++++ b/extensions/LUA/lua/ldump.c +@@ -4,7 +4,12 @@ + ** See Copyright Notice in lua.h + */ + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #define ldump_c + #define LUA_CORE +--- a/extensions/LUA/lua/lfunc.c ++++ b/extensions/LUA/lua/lfunc.c +@@ -5,7 +5,12 @@ + */ + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #define lfunc_c + #define LUA_CORE +--- a/extensions/LUA/lua/llimits.h ++++ b/extensions/LUA/lua/llimits.h +@@ -7,7 +7,12 @@ + #ifndef llimits_h + #define llimits_h + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #include "lua.h" + +--- a/extensions/LUA/lua/lmem.c ++++ b/extensions/LUA/lua/lmem.c +@@ -5,7 +5,12 @@ + */ + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #define lmem_c + #define LUA_CORE +--- a/extensions/LUA/lua/lmem.h ++++ b/extensions/LUA/lua/lmem.h +@@ -8,7 +8,12 @@ + #define lmem_h + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #include "llimits.h" + #include "lua.h" +--- a/extensions/LUA/lua/lobject.c ++++ b/extensions/LUA/lua/lobject.c +@@ -4,7 +4,12 @@ + ** See Copyright Notice in lua.h + */ + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #include + #include +--- a/extensions/LUA/lua/lobject.h ++++ b/extensions/LUA/lua/lobject.h +@@ -9,7 +9,12 @@ + #define lobject_h + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + + #include "llimits.h" +--- a/extensions/LUA/lua/lstate.c ++++ b/extensions/LUA/lua/lstate.c +@@ -5,7 +5,12 @@ + */ + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #define lstate_c + #define LUA_CORE +--- a/extensions/LUA/lua/lstrlib.c ++++ b/extensions/LUA/lua/lstrlib.c +@@ -6,7 +6,12 @@ + + + #include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + #include + #include + #include +--- a/extensions/LUA/lua/ltablib.c ++++ b/extensions/LUA/lua/ltablib.c +@@ -5,7 +5,12 @@ + */ + + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #define ltablib_c + #define LUA_LIB +--- a/extensions/LUA/lua/lua.h ++++ b/extensions/LUA/lua/lua.h +@@ -9,8 +9,14 @@ + #ifndef lua_h + #define lua_h + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include + #include ++#else ++#include ++#include ++#endif + + #include "luaconf.h" + +--- a/extensions/LUA/lua/luaconf.h ++++ b/extensions/LUA/lua/luaconf.h +@@ -8,7 +8,12 @@ + #ifndef lconfig_h + #define lconfig_h + ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) + #include ++#else ++#include ++#endif + + #if !defined(__KERNEL__) + #include From 31ea55283ce63cda2833ac616f67acc612586080 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:49:41 +0100 Subject: [PATCH 0895/2059] Disable rtl8812ct-au driver for 6.1 --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 9a41f555a..6a2d6dbcc 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -76,7 +76,7 @@ MY_DEPENDS := \ !TARGET_mvebu:kmod-usb-serial !TARGET_mvebu:kmod-usb-serial-option !TARGET_mvebu:kmod-usb-serial-wwan !TARGET_mvebu:usb-modeswitch !TARGET_mvebu:uqmi \ !TARGET_mvebu:umbim !TARGET_mvebu:kmod-mii !TARGET_mvebu:kmod-usb-net !TARGET_mvebu:kmod-usb-wdm !TARGET_mvebu:kmod-usb-net-qmi-wwan !TARGET_mvebu:kmod-usb-net-cdc-mbim !TARGET_mvebu:umbim \ !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd !TARGET_mvebu:libusbmuxd \ - kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su kmod-rtl8812au-ct \ + kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su !LINUX_6_1:kmod-rtl8812au-ct \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 TARGET_r4s:kmod-r8168 (TARGET_x86||TARGET_x86_64):kmod-usb-net-rtl8152 \ luci-app-mlvpn mlvpn 464xlat kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ From d1760e0efbcd1eeedca11239fd37cb25049aed1b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:50:18 +0100 Subject: [PATCH 0896/2059] Update r8125 --- r8125/patches/021-6.1-suppot.patch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 r8125/patches/021-6.1-suppot.patch diff --git a/r8125/patches/021-6.1-suppot.patch b/r8125/patches/021-6.1-suppot.patch new file mode 100644 index 000000000..c460ce33b --- /dev/null +++ b/r8125/patches/021-6.1-suppot.patch @@ -0,0 +1,14 @@ +--- a/src/r8125.h ++++ b/src/r8125.h +@@ -633,7 +633,11 @@ + typedef struct napi_struct *napi_ptr; + typedef int napi_budget; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add_weight(ndev, &priv->napi, function, weight) ++#else + #define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) ++#endif + #define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) + #define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) + #define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; From cb31c04475e591a4720b1b036c4c999eaf38cf14 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:50:32 +0100 Subject: [PATCH 0897/2059] Update r8152 --- r8152/Makefile | 55 ++++++++++++++++++++++++++++ r8152/patches/010-5.19-support.patch | 19 ++++++++++ r8152/patches/020-6.1-support.patch | 38 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 r8152/Makefile create mode 100644 r8152/patches/010-5.19-support.patch create mode 100644 r8152/patches/020-6.1-support.patch diff --git a/r8152/Makefile b/r8152/Makefile new file mode 100644 index 000000000..5921bdcc7 --- /dev/null +++ b/r8152/Makefile @@ -0,0 +1,55 @@ +# +# Download realtek r8152 linux driver from official site: +# [https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-usb-3-0-software] +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=r8152 +PKG_VERSION:=2.16.3.20220914 +PKG_RELEASE:=3 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/wget/realtek-r8152-linux/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=61ed7af34c8882c6028ddd1a27bb78fb5bfba41211f84dd7a06e4dc84dbe9a9a + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/realtek-$(PKG_NAME)-linux-$(PKG_VERSION) + +PKG_BUILD_PARALLEL:=1 + +PKG_MAINTAINER:=Tianling Shen + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/usb-net-rtl8152-vendor + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + TITLE:=Kernel module for USB-to-Ethernet Realtek convertors + SUBMENU:=USB Support + DEPENDS:=+kmod-usb-net + FILES:=$(PKG_BUILD_DIR)/r8152.ko + AUTOLOAD:=$(call AutoProbe,r8152) + CONFLICTS:=kmod-usb-net-rtl8152 +endef + +define KernelPackage/usb-net-rtl8152-vendor/description + Kernel module for Realtek RTL8152/RTL8153 Based USB Ethernet Adapters +endef + +R8152_MAKEOPTS= -C $(PKG_BUILD_DIR) \ + PATH="$(TARGET_PATH)" \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + TARGET="$(HAL_TARGET)" \ + TOOLPREFIX="$(KERNEL_CROSS)" \ + TOOLPATH="$(KERNEL_CROSS)" \ + KERNELPATH="$(LINUX_DIR)" \ + KERNELDIR="$(LINUX_DIR)" \ + LDOPTS=" " \ + DOMULTI=1 + +define Build/Compile + +$(MAKE) $(PKG_JOBS) $(R8152_MAKEOPTS) modules +endef + +$(eval $(call KernelPackage,usb-net-rtl8152-vendor)) diff --git a/r8152/patches/010-5.19-support.patch b/r8152/patches/010-5.19-support.patch new file mode 100644 index 000000000..944e5bfcc --- /dev/null +++ b/r8152/patches/010-5.19-support.patch @@ -0,0 +1,19 @@ +--- a/r8152.c ++++ b/r8152.c +@@ -1026,6 +1026,16 @@ + #define RTL_ADVERTISED_1000_FULL BIT(5) + #define RTL_ADVERTISED_2500_FULL BIT(6) + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++static inline void netif_set_gso_max_size(struct net_device *dev, ++ unsigned int size) ++{ ++ /* dev->gso_max_size is read locklessly from sk_setup_caps() */ ++ WRITE_ONCE(dev->gso_max_size, size); ++} ++#endif ++ ++ + /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + * The RTL chips use a 64 element hash table based on the Ethernet CRC. + */ diff --git a/r8152/patches/020-6.1-support.patch b/r8152/patches/020-6.1-support.patch new file mode 100644 index 000000000..756aba51f --- /dev/null +++ b/r8152/patches/020-6.1-support.patch @@ -0,0 +1,38 @@ +--- a/compatibility.h ++++ b/compatibility.h +@@ -237,9 +237,15 @@ + #define napi_disable(napi_ptr) netif_poll_disable(container_of(napi_ptr, struct r8152, napi)->netdev) + #define napi_schedule(napi_ptr) netif_rx_schedule(container_of(napi_ptr, struct r8152, napi)->netdev) + #define napi_complete(napi_ptr) netif_rx_complete(container_of(napi_ptr, struct r8152, napi)->netdev) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ #define netif_napi_add_weight(ndev, napi_ptr, function, weight_t) \ ++ ndev->poll = function; \ ++ ndev->weight = weight_t; ++#else + #define netif_napi_add(ndev, napi_ptr, function, weight_t) \ + ndev->poll = function; \ + ndev->weight = weight_t; ++#endif + typedef unsigned long uintptr_t; + #define DMA_BIT_MASK(value) \ + (value < 64 ? ((1ULL << value) - 1) : 0xFFFFFFFFFFFFFFFFULL) +--- a/r8152.c ++++ b/r8152.c +@@ -20718,10 +20718,17 @@ + + usb_set_intfdata(intf, tp); + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ if (tp->support_2500full) ++ netif_napi_add_weight(netdev, &tp->napi, r8152_poll, 256); ++ else ++ netif_napi_add_weight(netdev, &tp->napi, r8152_poll, 64); ++#else + if (tp->support_2500full) + netif_napi_add(netdev, &tp->napi, r8152_poll, 256); + else + netif_napi_add(netdev, &tp->napi, r8152_poll, 64); ++#endif + + ret = register_netdev(netdev); + if (ret != 0) { From b069e5663393776e18b027ddfb2c60554da914d1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:50:49 +0100 Subject: [PATCH 0898/2059] Add fullconenat --- fullconenat/Makefile | 62 +++++++++++++++++++ .../001-fix-init-Repeat-definition.patch | 20 ++++++ .../patches/001-linux-6.1-support.patch | 26 ++++++++ fullconenat/src/Makefile | 6 ++ 4 files changed, 114 insertions(+) create mode 100644 fullconenat/Makefile create mode 100644 fullconenat/patches/001-fix-init-Repeat-definition.patch create mode 100644 fullconenat/patches/001-linux-6.1-support.patch create mode 100644 fullconenat/src/Makefile diff --git a/fullconenat/Makefile b/fullconenat/Makefile new file mode 100644 index 000000000..d49155c7e --- /dev/null +++ b/fullconenat/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (C) 2022 Chion Tang +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=fullconenat +PKG_RELEASE:=9 + +PKG_SOURCE_DATE:=2022-02-13 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/llccd/netfilter-full-cone-nat.git +PKG_SOURCE_VERSION:=108a36cbdca17e68c9e6e7fd5e26156a88f738e8 +PKG_MIRROR_HASH:=00d749235271dee194dcd23c22e6e85207ea90192a62a110b2af0b4e4de1971f + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Chion Tang + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define Package/iptables-mod-fullconenat + SUBMENU:=Firewall + SECTION:=net + CATEGORY:=Network + TITLE:=FULLCONENAT iptables extension + DEPENDS:=+iptables +kmod-ipt-fullconenat +endef + +define Package/iptables-mod-fullconenat/install + $(INSTALL_DIR) $(1)/usr/lib/iptables + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libipt_FULLCONENAT.so $(1)/usr/lib/iptables +endef + +define KernelPackage/ipt-fullconenat + SUBMENU:=Netfilter Extensions + TITLE:=FULLCONENAT netfilter module + DEPENDS:=+kmod-nf-ipt +kmod-nf-nat + KCONFIG:= \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y + FILES:=$(PKG_BUILD_DIR)/xt_FULLCONENAT.ko +endef + +include $(INCLUDE_DIR)/kernel-defaults.mk + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(BUILDFLAGS)" \ + modules + $(call Build/Compile/Default) +endef + +$(eval $(call KernelPackage,ipt-fullconenat)) +$(eval $(call BuildPackage,iptables-mod-fullconenat)) diff --git a/fullconenat/patches/001-fix-init-Repeat-definition.patch b/fullconenat/patches/001-fix-init-Repeat-definition.patch new file mode 100644 index 000000000..67c9332c8 --- /dev/null +++ b/fullconenat/patches/001-fix-init-Repeat-definition.patch @@ -0,0 +1,20 @@ +--- a/libip6t_FULLCONENAT.c ++++ b/libip6t_FULLCONENAT.c +@@ -214,6 +214,7 @@ static struct xtables_target fullconenat_tg_reg = { + .x6_options = FULLCONENAT_opts, + }; + ++#define _init __attribute__((constructor)) _INIT + void _init(void) + { + xtables_register_target(&fullconenat_tg_reg); +--- a/libipt_FULLCONENAT.c ++++ b/libipt_FULLCONENAT.c +@@ -235,6 +235,7 @@ static struct xtables_target fullconenat_tg_reg = { + .x6_options = FULLCONENAT_opts, + }; + ++#define _init __attribute__((constructor)) _INIT + void _init(void) + { + xtables_register_target(&fullconenat_tg_reg); diff --git a/fullconenat/patches/001-linux-6.1-support.patch b/fullconenat/patches/001-linux-6.1-support.patch new file mode 100644 index 000000000..41721fb5c --- /dev/null +++ b/fullconenat/patches/001-linux-6.1-support.patch @@ -0,0 +1,26 @@ +--- a/xt_FULLCONENAT.c ++++ b/xt_FULLCONENAT.c +@@ -325,7 +325,11 @@ + /* for now we do the same thing for both --random and --random-fully */ + + /* select a random starting point */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ start = (uint16_t)(get_random_u32() % (u32)range_size); ++#else + start = (uint16_t)(prandom_u32() % (u32)range_size); ++#endif + } else { + + if ((original_port >= min && original_port <= min + range_size - 1) +@@ -995,7 +999,11 @@ + /* for now we do the same thing for both --random and --random-fully */ + + /* select a random starting point */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ start = (uint16_t)(get_random_u32() % (u32)range_size); ++#else + start = (uint16_t)(prandom_u32() % (u32)range_size); ++#endif + } else { + + if ((original_port >= min && original_port <= min + range_size - 1) diff --git a/fullconenat/src/Makefile b/fullconenat/src/Makefile new file mode 100644 index 000000000..b2f88db33 --- /dev/null +++ b/fullconenat/src/Makefile @@ -0,0 +1,6 @@ +libipt_FULLCONENAT.so: libipt_FULLCONENAT.o + $(CC) -shared -lxtables -o $@ $^; +libipt_FULLCONENAT.o: libipt_FULLCONENAT.c + $(CC) ${CFLAGS} -fPIC -D_INIT=$*_init -c -o $@ $<; + +obj-m += xt_FULLCONENAT.o From 1d046f0ca33471383eea544c668afaf939275066 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Dec 2022 12:57:10 +0100 Subject: [PATCH 0899/2059] Add 6.1 Github Actions compilation --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0a17c78df..0c8fde96e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx, r5s] - OMR_KERNEL: [5.4, 5.15] + OMR_KERNEL: [5.4, 5.15, 6.1] runs-on: ubuntu-latest continue-on-error: true From 1ebc65b1c9e4032efb26aaae013c1eaa53591843 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Dec 2022 19:42:35 +0100 Subject: [PATCH 0900/2059] Remove the -w of iptables-restore --- openmptcprouter/files/etc/firewall.gre-tunnel | 4 ++-- shadowsocks-libev/files/ss-rules | 8 ++++---- shadowsocks-libev/files/ss-rules6 | 8 ++++---- v2ray-core/files/usr/bin/v2ray-rules | 8 ++++---- v2ray-core/files/usr/bin/v2ray-rules6 | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/openmptcprouter/files/etc/firewall.gre-tunnel b/openmptcprouter/files/etc/firewall.gre-tunnel index f287a096b..4cef768f1 100644 --- a/openmptcprouter/files/etc/firewall.gre-tunnel +++ b/openmptcprouter/files/etc/firewall.gre-tunnel @@ -39,7 +39,7 @@ _setup_fw() { [ -n "$ifnames" ] && rule="$rule -i $(echo "${ifnames}" | sed 's/ /-i /g')" if [ -n "$rule" ] && [ -n "$lookup" ]; then $IPTABLESAVE --counters | grep -v "0x${lookup}" | $IPTABLERESTORE -w --counters - $IPTABLERESTORE -w --wait=60 --noflush <<-EOF + $IPTABLERESTORE --wait=60 --noflush <<-EOF *mangle -A omr-gre-tunnel ${rule} -j MARK --set-mark 0x${lookup} COMMIT @@ -48,7 +48,7 @@ _setup_fw() { } if [ -z "$($IPTABLESAVE | grep omr-gre-tunnel)" ]; then - $IPTABLERESTORE -w --wait=60 --noflush <<-EOF + $IPTABLERESTORE --wait=60 --noflush <<-EOF *mangle :omr-gre-tunnel - -I PREROUTING 1 -m addrtype ! --dst-type LOCAL -j omr-gre-tunnel diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 9e6907fab..e945d9ef9 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -133,7 +133,7 @@ ss_rules_parse_args() { ss_rules_flush() { local setname - $IPTABLESSAVE --counters 2>/dev/null | grep -v ssr_ | $IPTABLESRESTORE -w --counters + $IPTABLESSAVE --counters 2>/dev/null | grep -v ssr_ | $IPTABLESRESTORE --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true for setname in $(ipset -n list | grep "ssr_${rule}"); do @@ -178,7 +178,7 @@ ss_rules_iptchains_init() { ss_rules_iptchains_init_mark() { if [ "$($IPTABLES -w -t mangle -L PREROUTING | grep ss_rules_dst_bypass_all)" = "" ]; then - $IPTABLESRESTORE -w --noflush <<-EOF + $IPTABLESRESTORE --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 COMMIT @@ -199,7 +199,7 @@ ss_rules_iptchains_init_tcp() { bypass|*) return 0;; esac if [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule}_local_out | grep ssr_${rule}_dst_bypass)" = "" ]; then - $IPTABLESRESTORE -w --noflush <<-EOF + $IPTABLESRESTORE --noflush <<-EOF *nat :ssr_${rule}_local_out - -I OUTPUT 1 -p tcp -j ssr_${rule}_local_out @@ -255,7 +255,7 @@ ss_rules_iptchains_init_() { forward) dst_default_target=ssr_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IPTABLESRESTORE -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IPTABLESRESTORE --noflush *$table :ssr_${rule}_pre_src - :ssr_${rule}_src - diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index b0e2704d8..2c2a3eddc 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -117,7 +117,7 @@ ss_rules6_parse_args() { ss_rules6_flush() { local setname - $IP6TABLESSAVE --counters 2>/dev/null | grep -v ssr6_ | $IP6TABLESRESTORE -w --counters + $IP6TABLESSAVE --counters 2>/dev/null | grep -v ssr6_ | $IP6TABLESRESTORE --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true for setname in $(ipset -n list | grep "ssr6_${rule}"); do @@ -162,7 +162,7 @@ ss_rules6_iptchains_init() { ss_rules6_iptchains_init_mark() { if [ "$($IP6TABLES -w -t mangle -L PREROUTING | grep ss_rules6_dst_bypass_all)" = "" ]; then - $IP6TABLESRESTORE -w --noflush <<-EOF + $IP6TABLESRESTORE --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 COMMIT @@ -184,7 +184,7 @@ ss_rules6_iptchains_init_tcp() { bypass|*) return 0;; esac - $IP6TABLESRESTORE -w --noflush <<-EOF + $IP6TABLESRESTORE --noflush <<-EOF *nat :ssr6_${rule}_local_out - -I OUTPUT 1 -p tcp -j ssr6_${rule}_local_out @@ -239,7 +239,7 @@ ss_rules6_iptchains_init_() { forward) dst_default_target=ssr6_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IP6TABLESRESTORE -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IP6TABLESRESTORE --noflush *$table :ssr6_${rule}_pre_src - :ssr6_${rule}_src - diff --git a/v2ray-core/files/usr/bin/v2ray-rules b/v2ray-core/files/usr/bin/v2ray-rules index 1424e52e1..c65682622 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules +++ b/v2ray-core/files/usr/bin/v2ray-rules @@ -134,7 +134,7 @@ v2r_rules_parse_args() { v2r_rules_flush() { local setname - $IPTABLESSAVE --counters 2>/dev/null | grep -v v2r_ | $IPTABLESRESTORE -w --counters + $IPTABLESSAVE --counters 2>/dev/null | grep -v v2r_ | $IPTABLESRESTORE --counters while ip rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip route flush table 100 || true for setname in $(ipset -n list | grep "ssr_${rule}"); do @@ -179,7 +179,7 @@ v2r_rules_iptchains_init() { v2r_rules_iptchains_init_mark() { if [ "$($IPTABLES -w -t mangle -L PREROUTING | grep ss_rules_dst_bypass_all)" = "" ]; then - $IPTABLESRESTORE -w --noflush <<-EOF + $IPTABLESRESTORE --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 COMMIT @@ -200,7 +200,7 @@ v2r_rules_iptchains_init_tcp() { bypass|*) return 0;; esac - $IPTABLESRESTORE -w --noflush <<-EOF + $IPTABLESRESTORE --noflush <<-EOF *nat :v2r_${rule}_local_out - -I OUTPUT 1 -p tcp -j v2r_${rule}_local_out @@ -255,7 +255,7 @@ v2r_rules_iptchains_init_() { forward) dst_default_target=v2r_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IPTABLESRESTORE -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IPTABLESRESTORE --noflush *$table :v2r_${rule}_pre_src - :v2r_${rule}_src - diff --git a/v2ray-core/files/usr/bin/v2ray-rules6 b/v2ray-core/files/usr/bin/v2ray-rules6 index ed9ad2e1a..0f9cfeb35 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules6 +++ b/v2ray-core/files/usr/bin/v2ray-rules6 @@ -117,7 +117,7 @@ v2ray_rules6_parse_args() { v2ray_rules6_flush() { local setname - $IP6TABLESSAVE --counters 2>/dev/null | grep -v v2r6_ | $IP6TABLESRESTORE -w --counters + $IP6TABLESSAVE --counters 2>/dev/null | grep -v v2r6_ | $IP6TABLESRESTORE --counters while ip -f inet6 rule del fwmark 1 lookup 100 2>/dev/null; do true; done ip -f inet6 route flush table 100 || true for setname in $(ipset -n list | grep "ssr6_${rule}"); do @@ -161,7 +161,7 @@ v2ray_rules6_iptchains_init() { } v2ray_rules6_iptchains_init_mark() { - $IP6TABLESRESTORE -w --noflush <<-EOF + $IP6TABLESRESTORE --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 COMMIT @@ -184,7 +184,7 @@ v2ray_rules6_iptchains_init_tcp() { esac # echo "tcp mangle" -# $IP6TABLESRESTORE -w --noflush <<-EOF +# $IP6TABLESRESTORE --noflush <<-EOF # *mangle # :v2r6_${rule}_local_out - # -I OUTPUT 1 -p tcp -j v2r6_${rule}_local_out @@ -244,7 +244,7 @@ v2ray_rules6_iptchains_init_() { forward) dst_default_target=v2r6_${rule}_forward ;; bypass|*) dst_default_target=RETURN ;; esac - sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IP6TABLESRESTORE -w --noflush + sed -e '/^\s*$/d' -e 's/^\s\+//' <<-EOF | $IP6TABLESRESTORE --noflush *$table :v2r6_${rule}_pre_src - :v2r6_${rule}_src - From 833e0814eb2d6f28d7702dbfe29765fee7e89ffe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Dec 2022 12:59:30 +0100 Subject: [PATCH 0901/2059] Force dnsmasq to have ipset support --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 6a2d6dbcc..d0566a2b2 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -21,7 +21,7 @@ MY_DEPENDS := \ mc \ f2fs-tools \ openmptcprouter \ - dnsmasq-full \ + dnsmasq-full dnsmasq_full_ipset \ uhttpd \ uhttpd-mod-ubus \ curl \ From af843b8156bef14f49365c24b2b422b941c1d2c0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Dec 2022 12:59:43 +0100 Subject: [PATCH 0902/2059] Fix multipath script --- mptcp/files/usr/bin/multipath | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index a7953878c..3609eaf51 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -131,31 +131,47 @@ if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then printf "0x%02x" $(($(($IFF^$(($IFF&$IFF_MASK))))|$FLAG)) > $FLAG_PATH else - ID=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $3}') - IFF=$(ip mptcp endpoint show | grep "dev $DEVICE" | awk '{print $4}') + ID=$(ip mptcp endpoint show | grep -m 1 "dev $DEVICE" | awk '{print $3}') + IFF=$(ip mptcp endpoint show | grep -m 1 "dev $DEVICE" | awk '{print $4}') IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') [ -z "$ID" ] && [ -n "$IP" ] && ID=$(ip mptcp endpoint show | grep "$IP" | awk '{print $3}') RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null case $TYPE in "off") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null + [ -n "$ID" ] && { + for i in $ID; do + ip mptcp endpoint delete id $i 2>&1 >/dev/null + done + } exit 0;; "on") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null + [ -n "$ID" ] && { + for i in $ID; do + ip mptcp endpoint delete id $i 2>&1 >/dev/null + done + } for i in $IP; do ip mptcp endpoint add $i dev $DEVICE subflow fullmesh done exit 0;; "signal") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null + [ -n "$ID" ] && { + for i in $ID; do + ip mptcp endpoint delete id $i 2>&1 >/dev/null + done + } for i in $IP; do #ip mptcp endpoint add $i dev $DEVICE signal subflow fullmesh ip mptcp endpoint add $i dev $DEVICE signal done exit 0;; "backup") - [ -n "$ID" ] && ip mptcp endpoint delete id $ID 2>&1 >/dev/null + [ -n "$ID" ] && { + for i in $ID; do + ip mptcp endpoint delete id $i 2>&1 >/dev/null + done + } for i in $IP; do ip mptcp endpoint add $i dev $DEVICE backup fullmesh done From f814139c3d7ed5861958904f8cf5965e06deaf82 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 30 Dec 2022 20:14:56 +0100 Subject: [PATCH 0903/2059] Changes for kernel 6.1 support --- luci-app-firewall/Makefile | 2 +- mptcpd/Makefile | 2 +- openmptcprouter-full/Makefile | 2 +- openmptcprouter/files/etc/firewall.gre-tunnel | 4 ++-- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 7 +++++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/luci-app-firewall/Makefile b/luci-app-firewall/Makefile index e6e891e2d..b255cd140 100644 --- a/luci-app-firewall/Makefile +++ b/luci-app-firewall/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Firewall and Portforwarding application -LUCI_DEPENDS:=+@LINUX_5_4:firewall +@LINUX_5_15:uci-firewall +LUCI_DEPENDS:=+@LINUX_5_4:firewall +@(LINUX_5_15||LINUX_6_1):uci-firewall PKG_LICENSE:=Apache-2.0 PKG_VERSION:=omr-202103 diff --git a/mptcpd/Makefile b/mptcpd/Makefile index cb6f95f6d..1b67f08fd 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -25,7 +25,7 @@ include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) SECTION:=net CATEGORY:=Network -DEPENDS:=+libell @LINUX_5_15 +DEPENDS:=+libell @(LINUX_5_15||LINUX_6_1) TITLE:=mptcpd URL:=https://github.com/intel/mptcpd endef diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index d0566a2b2..999651843 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -82,7 +82,7 @@ MY_DEPENDS := \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ - LINUX_5_15:mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec usbutils + (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec usbutils # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ diff --git a/openmptcprouter/files/etc/firewall.gre-tunnel b/openmptcprouter/files/etc/firewall.gre-tunnel index 4cef768f1..59d161781 100644 --- a/openmptcprouter/files/etc/firewall.gre-tunnel +++ b/openmptcprouter/files/etc/firewall.gre-tunnel @@ -39,7 +39,7 @@ _setup_fw() { [ -n "$ifnames" ] && rule="$rule -i $(echo "${ifnames}" | sed 's/ /-i /g')" if [ -n "$rule" ] && [ -n "$lookup" ]; then $IPTABLESAVE --counters | grep -v "0x${lookup}" | $IPTABLERESTORE -w --counters - $IPTABLERESTORE --wait=60 --noflush <<-EOF + $IPTABLERESTORE --noflush <<-EOF *mangle -A omr-gre-tunnel ${rule} -j MARK --set-mark 0x${lookup} COMMIT @@ -48,7 +48,7 @@ _setup_fw() { } if [ -z "$($IPTABLESAVE | grep omr-gre-tunnel)" ]; then - $IPTABLERESTORE --wait=60 --noflush <<-EOF + $IPTABLERESTORE --noflush <<-EOF *mangle :omr-gre-tunnel - -I PREROUTING 1 -m addrtype ! --dst-type LOCAL -j omr-gre-tunnel diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index afde68d82..c1a13dfeb 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -236,9 +236,12 @@ for intf in $allintf; do uci -q add_list firewall.zone_vpn.network="${intf}" done + +#uci -q batch <<-EOF >/dev/null +# set firewall.zone_lan.mtu_fix='1' +# set firewall.zone_vpn.mtu_fix='1' +#EOF uci -q batch <<-EOF >/dev/null - set firewall.zone_lan.mtu_fix='1' - set firewall.zone_vpn.mtu_fix='1' set firewall.@include[0].reload='1' commit firewall EOF From ed36b06234da7fa9032d6a0a1caeda4d63c02635 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 1 Jan 2023 09:16:35 +0100 Subject: [PATCH 0904/2059] IPv6 fixes --- mptcp/files/etc/init.d/mptcp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 99cd7d0db..375c60276 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -295,8 +295,8 @@ interface_multipath_settings() { config_get gateway6 $config ip6gw if [ -n "$ipaddr6" ]; then ip6addr=`echo $ip6addr | cut -d/ -f1` - netmask6=`ipcalc $ipaddr6 | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` - network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + netmask6=`ipcalc -p $ipaddr6 | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` + network6=`ipcalc -n $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ -z "$ip6addr" ] || [ -z "$network6" ]; then [ -z "$ip6addr" ] && network_get_ipaddr6 ip6addr $config @@ -312,7 +312,7 @@ interface_multipath_settings() { gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi netmask6=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") - [ -n "$ip6addr" ] && network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ip6addr" ] && network6=`ipcalc -n $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null From d773ee086d7fbdcf22ed9e343692e1beb6d9bf65 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 1 Jan 2023 10:09:50 +0100 Subject: [PATCH 0905/2059] Add 6.1 support to MPTCP interface --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index 6c9091033..710f034d0 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -21,7 +21,7 @@ o:value(0, translate("disable")) o = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager"), translate("Default is fullmesh")) o:value("default", translate("default")) o:value("fullmesh", "fullmesh") -if uname.release:sub(1,4) ~= "5.14" then +if tonumber(uname.release:sub(1,4)) <= 5.15 then o:value("ndiffports", "ndiffports") o:value("binder", "binder") if uname.release:sub(1,4) ~= "4.14" then @@ -30,7 +30,7 @@ if uname.release:sub(1,4) ~= "5.14" then end o = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler")) o:value("default", translate("default")) -if uname.release:sub(1,4) ~= "5.15" then +if tonumber(uname.release:sub(1,4)) <= 5.15 then o:value("roundrobin", "round-robin") o:value("redundant", "redundant") if uname.release:sub(1,4) ~= "4.14" then @@ -38,12 +38,12 @@ if uname.release:sub(1,4) ~= "5.15" then o:value("ecf", "ECF") end end -if uname.release:sub(1,4) ~= "5.15" then +if tonumber(uname.release:sub(1,4)) <= 5.15 then o = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) o.datatype = "uinteger" o.rmempty = false end -if uname.release:sub(1,4) ~= "5.15" then +if tonumber(uname.release:sub(1,4)) <= 5.15 then o = s:option(ListValue, "mptcp_version", translate("Multipath TCP version")) o:value(0, translate("0")) o:value(1, translate("1")) @@ -55,7 +55,7 @@ for cong in string.gmatch(availablecong, "[^%s]+") do o:value(cong, translate(cong)) end -if uname.release:sub(1,4) == "5.15" then +if tonumber(uname.release:sub(1,4)) >= 5.15 then o = s:option(Value, "mptcp_subflows", translate("specifies the maximum number of additional subflows allowed for each MPTCP connection")) o.datatype = "uinteger" o.rmempty = false From b3ebd3a83d16c48d1c59b888531ef588ffe2e98e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 2 Jan 2023 19:56:50 +0100 Subject: [PATCH 0906/2059] More IPv6 fixes --- mptcp/files/etc/init.d/mptcp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 375c60276..140c4460b 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -172,6 +172,8 @@ interface_multipath_settings() { [ "$(echo $iface | grep '^if')" != "" ] && return 0 [ "$iface" = "lo" ] && return 0 + #echo "îface: $iface" + if [ "$mode" = "master" ]; then multipath "$iface" "on" else @@ -214,6 +216,7 @@ interface_multipath_settings() { fi if [ -z "$gateway" ] || [ "$( valid_subnet4 $gateway )" != "ok" ]; then gateway=$(traceroute -m1 -i $iface 8.8.8.8 2>/dev/null | awk 'FNR==2{ print $2 }') + [ "$gateway" = "*" ] && gateway="" fi network_get_subnet netmask $config [ -n "$netmask" ] && [ "$(echo $netmask | grep '/')" != "" ] && netmask="" @@ -262,7 +265,6 @@ interface_multipath_settings() { commit network EOF else - #echo "Add routes for $ipaddr table $id" [ -n "$ipaddr" ] && [ -z "$(ip rule show from $ipaddr table $id)" ] && ip rule add from $ipaddr table $id pref 0 [ -z "$(ip rule show oif $iface table $id)" ] && ip rule add oif $iface table $id pref 0 ip route replace $network/$netmask dev $iface scope link metric $id 2>&1 >/dev/null @@ -294,24 +296,26 @@ interface_multipath_settings() { config_get ipaddr6 $config ip6addr config_get gateway6 $config ip6gw if [ -n "$ipaddr6" ]; then - ip6addr=`echo $ip6addr | cut -d/ -f1` + ip6addr=`echo "$ipaddr6" | cut -d/ -f1 | tr -d "\n"` netmask6=`ipcalc -p $ipaddr6 | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` network6=`ipcalc -n $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi - if [ -z "$ip6addr" ] || [ -z "$network6" ]; then + if [ -z "$ip6addr" ] || [ -z "$gateway6" ]; then [ -z "$ip6addr" ] && network_get_ipaddr6 ip6addr $config [ -z "$ip6addr" ] && ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") [ -z "$gateway6" ] && network_get_gateway6 gateway6 $config true [ -z "$gateway6" ] && gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") [ -z "$gateway6" ] && gateway6=$(uci -q get "network.$config.ip6gw") [ -z "$gateway6" ] && gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") - if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then - gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") - fi - if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then - gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") - fi - netmask6=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + #if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then + # gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") + #fi + #if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then + # echo "ipv6 not ok" + # gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + #fi + gateway6=$(echo $gateway6 | cut -d/ -f1 | tr -d "\n") + netmask6=$(ip -6 addr show dev $iface | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") [ -n "$ip6addr" ] && network6=`ipcalc -n $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then @@ -326,6 +330,7 @@ interface_multipath_settings() { ip -6 route flush 6$id > /dev/null 2>&1 fi if [ -n "$gateway6" ] && [ -n "$network6" ]; then + #echo "gateway6: $gateway6 - network6: $network6 -> ok" if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null delete network.${config}_rule6 @@ -351,7 +356,7 @@ interface_multipath_settings() { EOF else [ -n "$ip6addr" ] && ip -6 rule add from $ip6addr table 6$id pref 0 2>&1 >/dev/null - ip rule add oif $iface table 6$id pref 0 + [ -z "$(ip rule show pref 0 table 6$id oif $iface)" ] && ip rule add oif $iface table 6$id pref 0 ip -6 route replace $network6/$netmask6 dev $iface scope link metric 6$id 2>&1 >/dev/null ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface table 6$id 2>&1 >/dev/null From 9d544752a462ab986a092d059dab13cc525a51c9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 3 Jan 2023 20:54:40 +0100 Subject: [PATCH 0907/2059] Various IPv6 fixes --- .../luasrc/controller/openmptcprouter.lua | 2 + .../root/etc/uci-defaults/openmptcprouter | 10 ++--- .../share/omr/post-tracking.d/post-tracking | 42 ++++++++++++++----- omr-tracker/files/bin/omr-tracker | 2 +- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 67e907243..4f79fda7e 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -388,9 +388,11 @@ function wizard_add() if ip6addr ~= "" then ucic:set("network",intf,"ip6addr",ip6addr:gsub("%s+", "")) ucic:set("network",intf,"ip6gw",ip6gw:gsub("%s+", "")) + ucic:set("network",intf,"ipv6","1") else ucic:set("network",intf,"ip6addr","") ucic:set("network",intf,"ip6gw","") + ucic:set("network",intf,"ipv6","0") end if proto == "dhcpv6" then diff --git a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter index f8a0dc21c..647c23303 100755 --- a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter @@ -135,11 +135,11 @@ _set_omr_ip() { server=$1 serverip="$(uci -q get openmptcprouter.${server}.ip)" if [ -n "$serverip" ]; then - uci -q batch <<-EOF >/dev/null - delete openmptcprouter.${server}.ip - add_list openmptcprouter.${server}.ip="${serverip}" - commit openmptcprouter - EOF + uci -q delete openmptcprouter.${server}.ip + for ip in ${serverip}; do + uci -q add_list openmptcprouter.${server}.ip="${ip}" + done + uci -q commit openmptcprouter fi } diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 9546be6ec..573973648 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1106,6 +1106,7 @@ if [ "$multipath_config" = "master" ]; then # config_foreach set_server_all_routes server if [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_default_route server + #config_foreach set_server_default_route6 server fi fi if ([ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$default_gw6" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then @@ -1119,12 +1120,12 @@ if [ "$multipath_config" = "master" ]; then #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then # config_foreach set_server_all_routes server if [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then - config_foreach set_server_default_route server + #config_foreach set_server_default_route server config_foreach set_server_default_route6 server fi fi #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then - if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && ([ "$(ip route show default | grep weight)" = "" ] || [ "$(ip -6 route show default | grep weight)" = "" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then @@ -1132,11 +1133,11 @@ if [ "$multipath_config" = "master" ]; then routesbalancingbackup="" nbintf=0 nbintfb=0 - nbintf6=0 - nbintfb6=0 + #nbintf6=0 + #nbintfb6=0 config_load network config_foreach set_route_balancing interface - config_foreach set_route_balancing6 interface + #config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Change in routes, set ip route replace default scope global $routesbalancing (omrvpn_intf: $omrvpn_intf)" @@ -1145,18 +1146,37 @@ if [ "$multipath_config" = "master" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New route: $(ip r)" } } - [ -n "$routesbalancing6" ] && { - ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { - _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" - ip -6 route replace default scope global metric 1 $routesbalancing6 2>&1 >/dev/null - } - } + #[ -n "$routesbalancing6" ] && { + # ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { + # _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" + # ip -6 route replace default scope global metric 1 $routesbalancing6 2>&1 >/dev/null + # } + #} [ -n "$routesbalancingbackup" ] && { ([ "$nbintfb" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Set backup ip route replace default scope global metric 999 $routesbalancingbackup" ip route replace default scope global metric 999 $routesbalancingbackup 2>&1 >/dev/null } } + #[ -n "$routesbalancingbackup6" ] && { + # ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { + # _log "Set backup ip -6 route replace default scope global $routesbalancingbackup6" + # ip -6 route replace default scope global metric 999 $routesbalancingbackup6 2>&1 >/dev/null + # } + #} + elif [ -n "$omrvpn_intf" ] && [ "$(ip -6 route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then + routesbalancing6="" + routesbalancingbackup6="" + nbintf6=0 + nbintfb6=0 + config_load network + config_foreach set_route_balancing6 interface + [ -n "$routesbalancing6" ] && { + ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { + _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" + ip -6 route replace default scope global metric 1 $routesbalancing6 2>&1 >/dev/null + } + } [ -n "$routesbalancingbackup6" ] && { ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { _log "Set backup ip -6 route replace default scope global $routesbalancingbackup6" diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 61d328932..72decbe1a 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -292,7 +292,7 @@ while true; do if [ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ]; then #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then - OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | grep -v 'inet6 fe80' | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1) + OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1) #fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then OMR_TRACKER_DEVICE_GATEWAY6=$(uci -q get "network.$OMR_TRACKER_INTERFACE.ip6gw") From 3a99d973486936e00e17a865629c28698179a420 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 9 Jan 2023 12:38:59 +0100 Subject: [PATCH 0908/2059] Enable back mtu_fix --- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index c1a13dfeb..07ea31f1f 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -237,10 +237,10 @@ for intf in $allintf; do done -#uci -q batch <<-EOF >/dev/null -# set firewall.zone_lan.mtu_fix='1' -# set firewall.zone_vpn.mtu_fix='1' -#EOF +uci -q batch <<-EOF >/dev/null + set firewall.zone_lan.mtu_fix='1' + set firewall.zone_vpn.mtu_fix='1' +EOF uci -q batch <<-EOF >/dev/null set firewall.@include[0].reload='1' commit firewall From e412adf7ca7bb54368c1500656c1e95855003e9c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 9 Jan 2023 12:39:17 +0100 Subject: [PATCH 0909/2059] Try to reduce mvebu images size --- openmptcprouter-full/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 999651843..6f0ec53b9 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -46,7 +46,7 @@ MY_DEPENDS := \ luci-app-openvpn \ shadowsocks-libev-ss-server shadowsocks-libev-ss-tunnel \ omr-6in4 ip6tables-mod-nat luci-proto-ipv6 6to4 6in4 6rd ip6tables \ - speedtestcpp \ + !TARGET_mvebu:speedtestcpp \ iftop \ htop \ nano \ @@ -69,7 +69,7 @@ MY_DEPENDS := \ ca-bundle openssl-util \ dejavu-fonts-ttf-DejaVuSerif dejavu-fonts-ttf-DejaVuSerif-Bold dejavu-fonts-ttf-DejaVuSerif-Italic dejavu-fonts-ttf-DejaVuSerif-BoldItalic \ luci-app-snmpd \ - iputils-tracepath v2ray-plugin netcat simple-obfs \ + iputils-tracepath !TARGET_mvebu:v2ray-plugin netcat simple-obfs \ (TARGET_x86||TARGET_x86_64):kmod-iwlwifi (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl1000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl100 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl105 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl135 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl2000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl2030 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl3160 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl3168 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl5000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl5150 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2a (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2b (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6050 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7260 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7265 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7265d (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl8260c (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl8265 \ (TARGET_x86||TARGET_x86_64):kmod-e1000 (TARGET_x86||TARGET_x86_64):kmod-e1000e (TARGET_x86||TARGET_x86_64):kmod-igb (TARGET_x86||TARGET_x86_64):kmod-ne2k-pci (TARGET_x86||TARGET_x86_64):kmod-r8169 (TARGET_x86||TARGET_x86_64):kmod-8139too (TARGET_x86||TARGET_x86_64):kmod-bnx2 \ TARGET_mvebu:kmod-mwlwifi TARGET_mvebu:mwlwifi-firmware-88w8864 TARGET_mvebu:mwlwifi-firmware-88w8897 TARGET_mvebu:mwlwifi-firmware-88w8964 TARGET_mvebu:mwlwifi-firmware-88w8997 \ @@ -78,11 +78,11 @@ MY_DEPENDS := \ !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd !TARGET_mvebu:libusbmuxd \ kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su !LINUX_6_1:kmod-rtl8812au-ct \ !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 TARGET_r4s:kmod-r8168 (TARGET_x86||TARGET_x86_64):kmod-usb-net-rtl8152 \ - luci-app-mlvpn mlvpn 464xlat kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ + !TARGET_mvebu:luci-app-mlvpn !TARGET_mvebu:mlvpn 464xlat kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ - (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc kmod-mmc-spi kmod-macsec usbutils + (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From 8dcd96b4ffe7e9894090ed64f48c3b67cc6c9723 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 9 Jan 2023 20:06:30 +0100 Subject: [PATCH 0910/2059] Fix MPTCP luci app --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index 710f034d0..7d2e8ffaf 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -21,7 +21,8 @@ o:value(0, translate("disable")) o = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager"), translate("Default is fullmesh")) o:value("default", translate("default")) o:value("fullmesh", "fullmesh") -if tonumber(uname.release:sub(1,4)) <= 5.15 then +--if tonumber(uname.release:sub(1,4)) <= 5.15 then +if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then o:value("ndiffports", "ndiffports") o:value("binder", "binder") if uname.release:sub(1,4) ~= "4.14" then @@ -30,7 +31,8 @@ if tonumber(uname.release:sub(1,4)) <= 5.15 then end o = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler")) o:value("default", translate("default")) -if tonumber(uname.release:sub(1,4)) <= 5.15 then +-- if tonumber(uname.release:sub(1,4)) <= 5.15 then +if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then o:value("roundrobin", "round-robin") o:value("redundant", "redundant") if uname.release:sub(1,4) ~= "4.14" then @@ -38,12 +40,14 @@ if tonumber(uname.release:sub(1,4)) <= 5.15 then o:value("ecf", "ECF") end end -if tonumber(uname.release:sub(1,4)) <= 5.15 then +-- if tonumber(uname.release:sub(1,4)) <= 5.15 then +if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then o = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) o.datatype = "uinteger" o.rmempty = false end -if tonumber(uname.release:sub(1,4)) <= 5.15 then +-- if tonumber(uname.release:sub(1,4)) <= 5.15 then +if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then o = s:option(ListValue, "mptcp_version", translate("Multipath TCP version")) o:value(0, translate("0")) o:value(1, translate("1")) @@ -55,7 +59,8 @@ for cong in string.gmatch(availablecong, "[^%s]+") do o:value(cong, translate(cong)) end -if tonumber(uname.release:sub(1,4)) >= 5.15 then +-- if tonumber(uname.release:sub(1,4)) >= 5.15 then +if uname.release:sub(1,4) == "5.15" or uname.release:sub(1,1) == "6" then o = s:option(Value, "mptcp_subflows", translate("specifies the maximum number of additional subflows allowed for each MPTCP connection")) o.datatype = "uinteger" o.rmempty = false From 6992a21269d4c1fdd02dc97df856ec1064d44e16 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 11 Jan 2023 13:11:52 +0100 Subject: [PATCH 0911/2059] Force mptcp routes settings when force link set --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 573973648..cffa56207 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1286,6 +1286,10 @@ fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { if [ "$(sysctl -qen net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ] || [ "$(sysctl -qen net.mptcp.enabled | tr -d '\n')" = "1" ]; then + if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.force_link)" != "0" ]; then + _log "Reload MPTCP config for $OMR_TRACKER_DEVICE" + /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" + fi _log "Multipath $OMR_TRACKER_DEVICE switched to $multipath_config" multipath "$OMR_TRACKER_DEVICE" "$multipath_config" fi From a496b2affc9d999225856856e966a5b2a93f668e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 12 Jan 2023 19:41:46 +0100 Subject: [PATCH 0912/2059] Fix https://github.com/Ysurac/openmptcprouter-feeds/commit/49db48e3dc8e25ab7c0ab209e0d2d08e3c7f37e8#commitcomment-95940169 --- luci-app-iperf/luasrc/controller/iperf.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-iperf/luasrc/controller/iperf.lua b/luci-app-iperf/luasrc/controller/iperf.lua index cbc3f1e12..8af54323d 100644 --- a/luci-app-iperf/luasrc/controller/iperf.lua +++ b/luci-app-iperf/luasrc/controller/iperf.lua @@ -26,7 +26,7 @@ function run_test(server,proto,mode,updown,omit,parallel,transmit,bitrate) if mode == "udp" then options = options .. " -u -b " .. bitrate end - if mode ~= "upload" then + if updown ~= "upload" then options = options .. " -R" end local ipv = "4" From 6ca6ba2244c9507a4897fc51c2d834a8c9ab805a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 13 Jan 2023 17:53:14 +0100 Subject: [PATCH 0913/2059] Update modemmanager, libmbim and libqmi --- libmbim/Makefile | 41 +++++++------- libqmi/Config.in | 15 ++++++ libqmi/Makefile | 56 +++++++++---------- modemmanager/Config.in | 41 ++++++++------ modemmanager/Makefile | 72 ++++++++++++------------- modemmanager/files/10-report-down | 35 ++++++++++++ modemmanager/files/25-modemmanager-net | 4 +- modemmanager/files/25-modemmanager-tty | 2 +- modemmanager/files/25-modemmanager-wwan | 2 +- modemmanager/files/modemmanager.proto | 28 +++++----- 10 files changed, 169 insertions(+), 127 deletions(-) create mode 100644 modemmanager/files/10-report-down mode change 100755 => 100644 modemmanager/files/modemmanager.proto diff --git a/libmbim/Makefile b/libmbim/Makefile index 6c9766480..abd94d617 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -8,28 +8,27 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_VERSION:=1.26.4 -PKG_RELEASE:=$(AUTORELEASE) +PKG_SOURCE_VERSION:=1.28.2 +PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=https://www.freedesktop.org/software/libmbim -PKG_HASH:=f688cec4c4586a17575f5e327448ce62f2000ef6a07c9e4589873d4a68568ad9 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git +PKG_MIRROR_HASH:=0b0b46016738fc22355d5a58c8a2d1b2f04906c49c51a50b57a09640d13b00b7 PKG_MAINTAINER:=Nicholas Smith -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk +include $(INCLUDE_DIR)/meson.mk -CONFIGURE_ARGS += \ - --disable-static \ - --disable-gtk-doc \ - --disable-gtk-doc-html \ - --disable-gtk-doc-pdf \ - --disable-silent-rules \ - --enable-more-warnings=yes +TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants +TARGET_LDFLAGS += -Wl,--gc-sections + +MESON_ARGS += \ + -Dintrospection=false \ + -Dman=false \ + -Dbash_completion=false \ + -Db_lto=true define Package/libmbim SECTION:=libs @@ -56,10 +55,6 @@ define Package/mbim-utils LICENSE_FILES:=COPYING endef -CONFIGURE_ARGS += \ - --without-udev \ - --without-udev-base-dir - define Build/InstallDev $(INSTALL_DIR) $(1)/usr/include $(CP) \ @@ -78,11 +73,15 @@ define Build/InstallDev endef define Package/libmbim/install - $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_DIR) \ + $(1)/usr/lib \ + $(1)/usr/libexec + $(CP) \ $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so.* \ $(1)/usr/lib/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/mbim-proxy $(1)/usr/lib/ + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/libexec/mbim-proxy $(1)/usr/libexec/ endef define Package/mbim-utils/install diff --git a/libqmi/Config.in b/libqmi/Config.in index 6f35b7453..7dfa7ca52 100644 --- a/libqmi/Config.in +++ b/libqmi/Config.in @@ -13,4 +13,19 @@ config LIBQMI_WITH_QRTR_GLIB help Compile libqmi with QRTR support +choice + prompt "Select QMI message collection to build" + default LIBQMI_COLLECTION_BASIC + + config LIBQMI_COLLECTION_MINIMAL + depends on !MODEMMANAGER_WITH_QMI + bool "minimal" + + config LIBQMI_COLLECTION_BASIC + bool "basic (default)" + + config LIBQMI_COLLECTION_FULL + bool "full" +endchoice + endmenu diff --git a/libqmi/Makefile b/libqmi/Makefile index 7cb640ea8..bfa3bab7c 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -8,20 +8,21 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqmi -PKG_VERSION:=1.30.8 -PKG_RELEASE:=$(AUTORELEASE) +PKG_SOURCE_VERSION:=1.32.2 +PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=https://www.freedesktop.org/software/libqmi -PKG_HASH:=862482ce9e3ad0bd65d264334ee311cdb94b9df2863b5b7136309b41b8ac1990 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git +PKG_MIRROR_HASH:=711d16d75a6a9afaefcf2be1bc845a4a6181dff786dfbd079e41e91279a0be91 PKG_MAINTAINER:=Nicholas Smith -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk +include $(INCLUDE_DIR)/meson.mk + +TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants +TARGET_LDFLAGS += -Wl,--gc-sections define Package/libqmi/config source "$(SOURCE)/Config.in" @@ -59,28 +60,16 @@ define Package/libqmi-utils/description Utils to talk to QMI enabled modems endef -CONFIGURE_ARGS += \ - --disable-static \ - --disable-gtk-doc \ - --disable-gtk-doc-html \ - --disable-gtk-doc-pdf \ - --disable-silent-rules \ - --enable-firmware-update \ - --enable-more-warnings=yes \ - --without-udev \ - --without-udev-base-dir - -ifeq ($(CONFIG_LIBQMI_WITH_MBIM_QMUX),y) - CONFIGURE_ARGS += --enable-mbim-qmux -else - CONFIGURE_ARGS += --disable-mbim-qmux -endif - -ifeq ($(CONFIG_LIBQMI_WITH_QRTR_GLIB),y) - CONFIGURE_ARGS += --enable-qrtr -else - CONFIGURE_ARGS += --disable-qrtr -endif +MESON_ARGS += \ + -Dudev=false \ + -Dintrospection=false \ + -Dman=false \ + -Dbash_completion=false \ + -Db_lto=true \ + -Dmbim_qmux=$(if $(CONFIG_LIBQMI_WITH_MBIM_QMUX),true,false) \ + -Dqrtr=$(if $(CONFIG_LIBQMI_WITH_QRTR_GLIB),true,false) \ + -Dcollection=$(if $(CONFIG_LIBQMI_COLLECTION_MINIMAL),minimal\ + ,$(if $(CONFIG_LIBQMI_COLLECTION_BASIC),basic,full)) define Build/InstallDev $(INSTALL_DIR) $(1)/usr/include @@ -100,12 +89,15 @@ define Build/InstallDev endef define Package/libqmi/install - $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_DIR) \ + $(1)/usr/lib \ + $(1)/usr/libexec + $(CP) \ $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so.* \ $(1)/usr/lib/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/qmi-proxy $(1)/usr/lib/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/libexec/qmi-proxy $(1)/usr/libexec/ endef define Package/qmi-utils/install diff --git a/modemmanager/Config.in b/modemmanager/Config.in index 283a9e10a..ebcb60dbc 100644 --- a/modemmanager/Config.in +++ b/modemmanager/Config.in @@ -1,21 +1,30 @@ menu "Configuration" -depends on PACKAGE_modemmanager + depends on PACKAGE_modemmanager - config MODEMMANAGER_WITH_MBIM - bool "Include MBIM support" - default y - help - Compile ModemManager with MBIM support +config MODEMMANAGER_WITH_MBIM + bool "Include MBIM support" + default y + help + Compile ModemManager with MBIM support - config MODEMMANAGER_WITH_QMI - bool "Include QMI support" - default y - help - Compile ModemManager with QMI support +config MODEMMANAGER_WITH_QMI + bool "Include QMI support" + default y + help + Compile ModemManager with QMI support + +config MODEMMANAGER_WITH_QRTR + bool "Include QRTR support" + default y + depends on MODEMMANAGER_WITH_QMI + select LIBQMI_WITH_QRTR_GLIB + help + Compile ModemManager with QRTR support + +config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS + bool "Allow AT commands via DBus" + default n + help + Compile ModemManager allowing AT commands without debug flag - config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS - bool "Allow AT commands via DBus" - default n - help - Compile ModemManager allowing AT commands without debug flag endmenu diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 9d6e1174a..6cbd6f738 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,23 +8,25 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_VERSION:=1.18.12 +PKG_SOURCE_VERSION:=1.20.2 PKG_RELEASE:=1 -PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager -PKG_HASH:=b464e4925d955a6ca86dd08616e763b26ae46d7fd37dbe281678e34065b1e430 -PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION) +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git +PKG_MIRROR_HASH:=f138effc693456c5040ec22e17c0a8b41143c3b17b62437462995c297a9150dc -PKG_MAINTAINER:=Nicholas Smith +PKG_MAINTAINER:=Nicholas Smith PKG_LICENSE:=GPL-2.0-or-later PKG_LICENSE_FILES:=COPYING -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 +PKG_BUILD_DEPENDS:=glib2/host libxslt/host include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk +include $(INCLUDE_DIR)/meson.mk + +TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants +TARGET_LDFLAGS += -Wl,--gc-sections define Package/modemmanager/config source "$(SOURCE)/Config.in" @@ -41,7 +43,8 @@ define Package/modemmanager +dbus \ +ppp \ +MODEMMANAGER_WITH_MBIM:libmbim \ - +MODEMMANAGER_WITH_QMI:libqmi + +MODEMMANAGER_WITH_QMI:libqmi \ + +MODEMMANAGER_WITH_QRTR:libqrtr-glib endef define Package/modemmanager/description @@ -50,35 +53,22 @@ define Package/modemmanager/description Select Utilities/usb-modeswitch if needed. endef -CONFIGURE_ARGS += \ - --without-polkit \ - --without-udev \ - --without-systemdsystemunitdir \ - --disable-rpath \ - --disable-gtk-doc - -ifeq ($(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),y) - CONFIGURE_ARGS += --with-at-command-via-dbus -endif - -ifdef CONFIG_MODEMMANAGER_WITH_MBIM - CONFIGURE_ARGS += --with-mbim -else - CONFIGURE_ARGS += --without-mbim -endif - -ifdef CONFIG_MODEMMANAGER_WITH_QMI - CONFIGURE_ARGS += --with-qmi -else - CONFIGURE_ARGS += --without-qmi -endif - -define Build/Prepare - $(call Build/Prepare/Default) - ( cd "$(PKG_BUILD_DIR)"; \ - printf "all:\ninstall:\n" >po/Makefile.in.in; \ - ) -endef +MESON_ARGS += \ + -Dudev=false \ + -Dudevdir=/lib/udev \ + -Dtests=false \ + -Dsystemdsystemunitdir=no \ + -Dsystemd_suspend_resume=false \ + -Dsystemd_journal=false \ + -Dpolkit=no \ + -Dintrospection=false \ + -Dman=false \ + -Dbash_completion=false \ + -Db_lto=true \ + -Dmbim=$(if $(CONFIG_MODEMMANAGER_WITH_MBIM),true,false) \ + -Dqmi=$(if $(CONFIG_MODEMMANAGER_WITH_QMI),true,false) \ + -Dqrtr=$(if $(CONFIG_MODEMMANAGER_WITH_QRTR),true,false) \ + -Dat_command_via_dbus=$(if $(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),true,false) define Build/InstallDev $(INSTALL_DIR) $(1)/usr/include/ModemManager @@ -110,6 +100,9 @@ define Package/modemmanager/install $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager + $(INSTALL_DIR) $(1)/usr/lib/ModemManager/connection.d + $(INSTALL_BIN) ./files/10-report-down $(1)/usr/lib/ModemManager/connection.d + $(INSTALL_DIR) $(1)/etc/dbus-1/system.d $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d @@ -120,6 +113,9 @@ define Package/modemmanager/install $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager + $(INSTALL_DIR) $(1)/usr/share/ModemManager/fcc-unlock.available.d + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/fcc-unlock.available.d/* $(1)/usr/share/ModemManager/fcc-unlock.available.d + $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager diff --git a/modemmanager/files/10-report-down b/modemmanager/files/10-report-down new file mode 100644 index 000000000..a3e5fb4ba --- /dev/null +++ b/modemmanager/files/10-report-down @@ -0,0 +1,35 @@ +#!/bin/sh + +# SPDX-License-Identifier: CC0-1.0 +# 2022 Aleksander Morgado +# +# Automatically report to netifd that the underlying modem +# is really disconnected +# +# require program name and at least 4 arguments +[ $# -lt 4 ] && exit 1 + +MODEM_PATH="$1" +BEARER_PATH="$2" +INTERFACE="$3" +STATE="$4" + +[ "${STATE}" = "disconnected" ] || exit 0 + +. /usr/share/ModemManager/modemmanager.common +. /lib/netifd/netifd-proto.sh +INCLUDE_ONLY=1 . /lib/netifd/proto/modemmanager.sh + +MODEM_STATUS=$(mmcli --modem="${MODEM_PATH}" --output-keyvalue) +[ -n "${MODEM_STATUS}" ] || exit 1 + +MODEM_DEVICE=$(modemmanager_get_field "${MODEM_STATUS}" "modem.generic.device") +[ -n "${MODEM_DEVICE}" ] || exit 2 + +CFG=$(mm_get_modem_config "${MODEM_DEVICE}") +[ -n "${CFG}" ] || exit 3 + +logger -t "modemmanager" "interface ${CFG} (network device ${INTERFACE}) ${STATE}" +proto_init_update $INTERFACE 0 +proto_send_update $CFG +exit 0 diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/25-modemmanager-net index e87231e31..ff4642019 100644 --- a/modemmanager/files/25-modemmanager-net +++ b/modemmanager/files/25-modemmanager-net @@ -12,7 +12,7 @@ mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" # Report network interface -mm_log "${ACTION} network interface ${INTERFACE}: event processed" +mm_log "info" "${ACTION} network interface ${INTERFACE}: event processed" mm_report_event "${ACTION}" "${INTERFACE}" "net" "/sys${DEVPATH}" # Look for an associated cdc-wdm interface @@ -26,6 +26,6 @@ esac # Report cdc-wdm device, if any [ -n "${cdcwdm}" ] && { - mm_log "${ACTION} cdc interface ${cdcwdm}: custom event processed" + mm_log "info" "${ACTION} cdc interface ${cdcwdm}: custom event processed" mm_report_event "${ACTION}" "${cdcwdm}" "usbmisc" "/sys${DEVPATH}" } diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/25-modemmanager-tty index c13148a33..5d1042cdd 100644 --- a/modemmanager/files/25-modemmanager-tty +++ b/modemmanager/files/25-modemmanager-tty @@ -12,5 +12,5 @@ mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" # Report TTY -mm_log "${ACTION} serial interface ${DEVNAME}: event processed" +mm_log "info" "${ACTION} serial interface ${DEVNAME}: event processed" mm_report_event "${ACTION}" "${DEVNAME}" "tty" "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-wwan b/modemmanager/files/25-modemmanager-wwan index c4dc6b897..b36ade478 100644 --- a/modemmanager/files/25-modemmanager-wwan +++ b/modemmanager/files/25-modemmanager-wwan @@ -11,5 +11,5 @@ mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" # Report wwan -mm_log "${ACTION} wwan control port ${DEVNAME}: event processed" +mm_log "info" "${ACTION} wwan control port ${DEVNAME}: event processed" mm_report_event "${ACTION}" "${DEVNAME}" "wwan" "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto old mode 100755 new mode 100644 index 0e050e7b9..e6ec9e203 --- a/modemmanager/files/modemmanager.proto +++ b/modemmanager/files/modemmanager.proto @@ -156,8 +156,8 @@ modemmanager_connected_method_ppp_ipv4() { novj \ noauth \ $authopts \ - ${username:+ user $username} \ - ${password:+ password $password} \ + ${username:+ user "$username"} \ + ${password:+ password "$password"} \ lcp-echo-failure 5 \ lcp-echo-interval 15 \ lock \ @@ -197,7 +197,6 @@ modemmanager_connected_method_dhcp_ipv4() { local interface="$1" local wwan="$2" local metric="$3" - local defaultroute="$4" proto_init_update "${wwan}" 1 proto_set_keep 1 @@ -223,7 +222,6 @@ modemmanager_connected_method_static_ipv4() { local dns1="$7" local dns2="$8" local metric="$9" - local defaultroute="$10" local mask="" @@ -244,9 +242,8 @@ modemmanager_connected_method_static_ipv4() { proto_set_keep 1 echo "adding IPv4 address ${address}, netmask ${mask}" proto_add_ipv4_address "${address}" "${mask}" - [ -n "${gateway}" ] && [ "${defaultroute}" != 0 ] && { + [ -n "${gateway}" ] && { echo "adding default IPv4 route via ${gateway}" - logger -t "modemmanager.proto" "adding default IPv4 route via ${gateway} ${address}" proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" } [ -n "${dns1}" ] && { @@ -265,7 +262,6 @@ modemmanager_connected_method_dhcp_ipv6() { local interface="$1" local wwan="$2" local metric="$3" - local defaultroute="$4" proto_init_update "${wwan}" 1 proto_set_keep 1 @@ -292,7 +288,6 @@ modemmanager_connected_method_static_ipv6() { local dns1="$7" local dns2="$8" local metric="$9" - local defaultroute="$10" [ -n "${address}" ] || { proto_notify_error "${interface}" ADDRESS_MISSING @@ -311,7 +306,7 @@ modemmanager_connected_method_static_ipv6() { echo "adding IPv6 address ${address}, prefix ${prefix}" proto_add_ipv6_address "${address}" "128" proto_add_ipv6_prefix "${address}/${prefix}" - [ -n "${gateway}" ] && [ "$defaultroute" != 0 ] && { + [ -n "${gateway}" ] && { echo "adding default IPv6 route via ${gateway}" proto_add_ipv6_route "${gateway}" "128" proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}" @@ -362,9 +357,9 @@ proto_modemmanager_setup() { local device apn allowedauth username password pincode iptype metric signalrate - local address prefix gateway mtu dns1 dns2 defaultroute + local address prefix gateway mtu dns1 dns2 - json_get_vars device apn allowedauth username password pincode iptype metric signalrate defaultroute + json_get_vars device apn allowedauth username password pincode iptype metric signalrate # validate sysfs path given in config [ -n "${device}" ] || { @@ -452,7 +447,7 @@ proto_modemmanager_setup() { echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}" case "${bearermethod_ipv4}" in "dhcp") - modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" "${defaultroute}" + modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" ;; "static") address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address") @@ -461,7 +456,7 @@ proto_modemmanager_setup() { mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu") dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]") dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]") - modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" "${defaultroute}" + modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" ;; "ppp") modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}" @@ -479,7 +474,7 @@ proto_modemmanager_setup() { echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}" case "${bearermethod_ipv6}" in "dhcp") - modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" "${defaultroute}" + modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" ;; "static") address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address") @@ -488,7 +483,7 @@ proto_modemmanager_setup() { mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu") dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]") dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]") - modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" "${defaultroute}" + modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" ;; "ppp") proto_notify_error "${interface}" "unsupported method" @@ -520,7 +515,8 @@ proto_modemmanager_teardown() { modemstatus=$(mmcli --modem="${device}" --output-keyvalue) bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") [ -n "${bearerpath}" ] || { - echo "couldn't load bearer path" + echo "couldn't load bearer path: disconnecting anyway" + mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1 return } From 7375f8363d7ae94e93e27203da6641d41c34a590 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 13 Jan 2023 21:29:38 +0100 Subject: [PATCH 0914/2059] Add shadowsocks compile fix --- shadowsocks-libev/patches/020-FIX.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 shadowsocks-libev/patches/020-FIX.patch diff --git a/shadowsocks-libev/patches/020-FIX.patch b/shadowsocks-libev/patches/020-FIX.patch new file mode 100644 index 000000000..3edff9cae --- /dev/null +++ b/shadowsocks-libev/patches/020-FIX.patch @@ -0,0 +1,11 @@ +--- a/src/manager.c.old 2023-01-12 13:23:01.201603055 +0100 ++++ b/src/manager.c 2023-01-12 13:23:37.180961405 +0100 +@@ -684,7 +684,7 @@ + while ((entry = cork_hash_table_iterator_next(&iter)) != NULL) { + struct server *server = (struct server *)entry->value; + char *method = server->method ? server->method : manager->method; +- char *passkey = server->key ? server->key : server->password; ++ char *passkey = server->key[0] ? server->key : server->password; + size_t pos = strlen(buf); + size_t entry_len = strlen(server->port) + strlen(passkey) + strlen(method); + if (pos > BUF_SIZE - entry_len - 50) { From ad6475198878cc6d771a8499ee695d3c0e4a3a8b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 25 Jan 2023 20:31:39 +0100 Subject: [PATCH 0915/2059] Change optimisation values --- shadowsocks-libev/files/shadowsocks.conf | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks.conf b/shadowsocks-libev/files/shadowsocks.conf index a80d14c85..070a876be 100644 --- a/shadowsocks-libev/files/shadowsocks.conf +++ b/shadowsocks-libev/files/shadowsocks.conf @@ -2,18 +2,18 @@ # max open files fs.file-max = 512000 # max read buffer -net.core.rmem_max = 67108864 +net.core.rmem_max = 16777216 # max write buffer -net.core.wmem_max = 67108864 +net.core.wmem_max = 16777216 net.core.optmem_max = 33554432 # default read buffer -#net.core.rmem_default = 131072 +#net.core.rmem_default = 16777216 # default write buffer -#net.core.wmem_default = 131072 +#net.core.wmem_default = 16777216 # max processor input queue -net.core.netdev_max_backlog = 4096 +net.core.netdev_max_backlog = 8192 # max backlog -net.core.somaxconn = 4096 +net.core.somaxconn = 8192 # resist SYN flood attacks net.ipv4.tcp_syncookies = 1 @@ -36,13 +36,13 @@ net.ipv4.tcp_max_tw_buckets = 10000 # turn on TCP Fast Open on both client and server side #net.ipv4.tcp_fastopen = 3 # TCP receive buffer -net.ipv4.tcp_rmem = 4096 87380 33554432 +net.ipv4.tcp_rmem = 4096 87380 16777216 # TCP write buffer -net.ipv4.tcp_wmem = 4096 65536 33554432 +net.ipv4.tcp_wmem = 4096 87380 16777216 # TCP buffer -net.ipv4.tcp_mem = 8092 131072 67108864 +net.ipv4.tcp_mem = 8192000 8192000 8192000 # UDP buffer -net.ipv4.udp_mem = 8092 131072 67108864 +net.ipv4.udp_mem = 4096 131072 67108864 # turn off path MTU discovery net.ipv4.tcp_mtu_probing = 0 @@ -54,3 +54,6 @@ net.netfilter.nf_conntrack_max = 131072 net.ipv4.tcp_ecn = 2 #net.ipv4.tcp_sack = 0 +#net.ipv4.tcp_dsack = 0 +#net.ipv4.tcp_fack = 0 +net.ipv4.tcp_slow_start_after_idle = 0 \ No newline at end of file From f5195e4a2e4ca7342b3e7274b1b9a08407ad8cf5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Feb 2023 15:38:36 +0100 Subject: [PATCH 0916/2059] Update libmbim --- libmbim/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index abd94d617..cfcb5ba96 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_SOURCE_VERSION:=1.28.2 +PKG_SOURCE_VERSION:=1.29.2 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -PKG_MIRROR_HASH:=0b0b46016738fc22355d5a58c8a2d1b2f04906c49c51a50b57a09640d13b00b7 +#PKG_MIRROR_HASH:=0b0b46016738fc22355d5a58c8a2d1b2f04906c49c51a50b57a09640d13b00b7 PKG_MAINTAINER:=Nicholas Smith From a45690c33b6d2b820cd19b673ea67abe8a49d931 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Feb 2023 15:38:45 +0100 Subject: [PATCH 0917/2059] Update libqmi --- libqmi/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libqmi/Makefile b/libqmi/Makefile index bfa3bab7c..cecee6cb6 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqmi -PKG_SOURCE_VERSION:=1.32.2 +PKG_SOURCE_VERSION:=1.33.3 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_MIRROR_HASH:=711d16d75a6a9afaefcf2be1bc845a4a6181dff786dfbd079e41e91279a0be91 +#PKG_MIRROR_HASH:=711d16d75a6a9afaefcf2be1bc845a4a6181dff786dfbd079e41e91279a0be91 PKG_MAINTAINER:=Nicholas Smith From fdb1aa84bf89550b0da502e473f05ac96e665483 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Feb 2023 15:39:00 +0100 Subject: [PATCH 0918/2059] Update ModemManager --- modemmanager/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 6cbd6f738..30e17b657 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_SOURCE_VERSION:=1.20.2 +PKG_SOURCE_VERSION:=1.20.4 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_MIRROR_HASH:=f138effc693456c5040ec22e17c0a8b41143c3b17b62437462995c297a9150dc +#PKG_MIRROR_HASH:=f138effc693456c5040ec22e17c0a8b41143c3b17b62437462995c297a9150dc PKG_MAINTAINER:=Nicholas Smith PKG_LICENSE:=GPL-2.0-or-later From 6a148735e4dcb632a6f934340338864569dca96a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Feb 2023 15:40:28 +0100 Subject: [PATCH 0919/2059] Fix on rmmod --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 6 +++--- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index 189f2669b..e74aced38 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -177,7 +177,7 @@ start_service() { else rm -f /dev/sfe_ipv6 fi - else + elif [ -d "/sys/module/fast_classifier" ]; then rmmod fast_classifier 2>&1 >/dev/null fi @@ -188,9 +188,9 @@ start_service() { set firewall.zone_vpn.auto_helper='0' commit firewall EOF - rmmod nf_nat_sip 2>&1 >/dev/null + [ -n "$(lsmod | grep nf_nat_sip)" ] && rmmod nf_nat_sip 2>&1 >/dev/null sleep 2 - rmmod nf_conntrack_sip 2>&1 >/dev/null + [ -n "$(lsmod | grep nf_conntrack_sip)" ] && rmmod nf_conntrack_sip 2>&1 >/dev/null else uci -q batch <<-EOF >/dev/null set firewall.zone_lan.auto_helper='1' diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 07ea31f1f..5bab51455 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -258,8 +258,8 @@ if [ "$(uci -q get openmptcprouter.settings.sipalg)" = "0" ]; then set firewall.zone_vpn.auto_helper='0' commit firewall EOF - rmmod nf_nat_sip 2>&1 >/dev/null - rmmod nf_conntrack_sip 2>&1 >/dev/null + [ -n "$(lsmod | grep nf_nat_sip)" ] && rmmod nf_nat_sip 2>&1 >/dev/null + [ -n "$(lsmod | grep nf_conntrack_sip)" ] && rmmod nf_conntrack_sip 2>&1 >/dev/null fi rm -f /tmp/luci-indexcache From 8bd23a967ea9d12ddaefe0a9f436be0fa754b503 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Feb 2023 15:41:02 +0100 Subject: [PATCH 0920/2059] Use omr-test-speed only on IPv4 --- openmptcprouter/files/bin/omr-test-speed | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 431049e2c..ab8e1a929 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -19,9 +19,9 @@ bestping="9999" for pinghost in $HOSTLST; do domain=$(echo $pinghost | awk -F/ '{print $3}') if [ -z "$INTERFACE" ] || [ "$FORCEVPS" = true ]; then - ping=$(ping -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + ping=$(ping -4 -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') else - ping=$(ping -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + ping=$(ping -4 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') fi echo "host: $domain - ping: $ping" if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then From efe3594a229189d5e86ea5d5a68338490ff9ceca Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Feb 2023 17:36:40 +0100 Subject: [PATCH 0921/2059] Small fix on getting modemmanager info --- luci-app-openmptcprouter/root/bin/omr-modemmanager | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/root/bin/omr-modemmanager b/luci-app-openmptcprouter/root/bin/omr-modemmanager index 57115c2e0..3cdbbda6f 100755 --- a/luci-app-openmptcprouter/root/bin/omr-modemmanager +++ b/luci-app-openmptcprouter/root/bin/omr-modemmanager @@ -6,11 +6,11 @@ timeout 1 mmcli -L | while read MODEM; do MODEM_ID=$(echo $MODEM | awk -F' ' '{print $1}' | awk -F/ '{print $6}') MODEM_INFO="$(timeout 1 mmcli -m $MODEM_ID --output-keyvalue)" if [ -n "$MODEM_INFO" ] && [ "$(echo "$MODEM_INFO" | grep 'modem.generic.device ' | awk -F": " '{print $2}')" = "$MODEM_INTF" ]; then - PERCENT=$(echo "$MODEM_INFO" | grep 'modem.generic.signal-quality.value ' | awk -F": " '{print $2}') - OPERATOR=$(echo "$MODEM_INFO" | grep 'modem.3gpp.operator-name ' | awk -F": " '{print $2}') - NUMBER=$(echo "$MODEM_INFO" | grep 'modem.generic.own-numbders.value[1]' | awk -F": " '{print $2}') - STATE=$(echo "$MODEM_INFO" | grep 'modem.generic.state ' | awk -F": " '{print $2}') - TYPE=$(echo "$MODEM_INFO" | grep 'modem.generic.access-technologies.value\[1\]' | awk -F": " '{print $2}') + PERCENT=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.signal-quality.value ' | awk -F": " '{print $2}') + OPERATOR=$(echo "$MODEM_INFO" | grep -m 1 'modem.3gpp.operator-name ' | awk -F": " '{print $2}') + NUMBER=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.own-numbders.value[1]' | awk -F": " '{print $2}') + STATE=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.state ' | awk -F": " '{print $2}') + TYPE=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.access-technologies.value\[1\]' | awk -F": " '{print $2}') [ -z "$INFO" ] && echo $PERCENT [ "$INFO" = "all" ] && echo "$PERCENT;$OPERATOR;$NUMBER;$STATE;$TYPE" exit From 9337bd30daea345bbce39797764be574d015520f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 18 Feb 2023 17:37:34 +0100 Subject: [PATCH 0922/2059] Update ndpi-netfilter2 --- ndpi-netfilter2/Makefile | 2 +- ndpi-netfilter2/patches/fcommon.patch | 19 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 ndpi-netfilter2/patches/fcommon.patch diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 13f73dc14..8983cff1b 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 -PKG_REV:=cf017cc2fecee644d0b2ff633a17377f776d1505 +PKG_REV:=ac0ad66b3644a43cbaa821a6135d3e610f8b2c1a PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git diff --git a/ndpi-netfilter2/patches/fcommon.patch b/ndpi-netfilter2/patches/fcommon.patch deleted file mode 100644 index faa8c57cf..000000000 --- a/ndpi-netfilter2/patches/fcommon.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/ndpi-netfilter/ipt/Makefile.anc 2022-09-05 09:34:30.579787766 +0200 -+++ b/ndpi-netfilter/ipt/Makefile 2022-09-05 09:34:42.555588398 +0200 -@@ -2,14 +2,14 @@ - NDPI_PRO := ${NDPI_SRC}/lib/protocols - XTBL := $(shell pkg-config --variable=xtlibdir xtables) - --CFLAGS = -fPIC -I../.. -I${NDPI_SRC}/include -I${NDPI_SRC}/lib -I../src -I../libre -DOPENDPI_NETFILTER_MODULE -O2 -Wall -+CFLAGS = -fPIC -I../.. -I${NDPI_SRC}/include -I${NDPI_SRC}/lib -I../src -I../libre -DOPENDPI_NETFILTER_MODULE -O2 -Wall -fcommon - - all: libxt_ndpi.so - install: libxt_ndpi.so - if [ -n "$(DESTDIR)$(XTBL)" -a -d "$(DESTDIR)$(XTBL)" ]; then install -v libxt_ndpi.so $(DESTDIR)$(XTBL); ln -fs libxt_ndpi.so $(DESTDIR)$(XTBL)/libxt_NDPI.so ; else echo "No pkg-config --variable=xtlibdir xtables"; fi - - lib%.so: lib%.o -- $(CC) -shared -o $@ $^; -+ $(CC) -shared -nostartfiles -o $@ $^; - lib%.o: lib%.c ../src/xt_ndpi.h ${NDPI_SRC}/include/ndpi_config.h ../libre/regexp.h ../libre/regexp.c - $(CC) ${CFLAGS} -D_INIT=lib$*_init -c -o $@ $<; - clean: From 93fb75da176870fa2be7fd710ccf905e0598c816 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 25 Feb 2023 15:21:56 +0100 Subject: [PATCH 0923/2059] Optimize some network settings and set MPTCP when needed --- .../luasrc/controller/openmptcprouter.lua | 2 +- mptcp/files/etc/init.d/mptcp | 18 ++++++------- mptcp/files/etc/uci-defaults/mptcp-defaults | 2 +- .../share/omr/post-tracking.d/post-tracking | 25 ++++++++++++------- .../files/etc/uci-defaults/1920-omr-network | 5 ++-- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 4f79fda7e..be6f36f31 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -167,7 +167,7 @@ function wizard_add() ucic:set("network","wan" .. i .. "_dev","mode","vepa") ucic:set("network","wan" .. i .. "_dev","ifname",defif) ucic:set("network","wan" .. i .. "_dev","name","wan" .. i) - ucic:set("network","wan" .. i .. "_dev","txqueuelen","20") + ucic:set("network","wan" .. i .. "_dev","txqueuelen","1000") end ucic:set("network","wan" .. i,"ip4table","wan") if multipath_master then diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 140c4460b..0e3a0b391 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -267,10 +267,10 @@ interface_multipath_settings() { else [ -n "$ipaddr" ] && [ -z "$(ip rule show from $ipaddr table $id)" ] && ip rule add from $ipaddr table $id pref 0 [ -z "$(ip rule show oif $iface table $id)" ] && ip rule add oif $iface table $id pref 0 - ip route replace $network/$netmask dev $iface scope link metric $id 2>&1 >/dev/null - ip route replace $network/$netmask dev $iface scope link table $id 2>&1 >/dev/null - ip route replace default via $gateway dev $iface table $id 2>&1 >/dev/null - [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default via $gateway dev $iface metric $id 2>&1 >/dev/null + ip route replace $network/$netmask dev $iface scope link metric $id initcwnd 10 initrwnd 10 2>&1 >/dev/null + ip route replace $network/$netmask dev $iface scope link table $id initcwnd 10 initrwnd 10 2>&1 >/dev/null + ip route replace default via $gateway dev $iface table $id initcwnd 10 initrwnd 10 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default via $gateway dev $iface metric $id initcwnd 10 initrwnd 10 2>&1 >/dev/null #ip route flush $id fi @@ -283,7 +283,7 @@ interface_multipath_settings() { if [ "$txqueuelen" != "" ]; then ifconfig $iface txqueuelen $txqueuelen > /dev/null 2>&1 else - ifconfig $iface txqueuelen 100 > /dev/null 2>&1 + ifconfig $iface txqueuelen 1000 > /dev/null 2>&1 fi fi if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && [ "$config" != "omr6in4" ]; then @@ -357,10 +357,10 @@ interface_multipath_settings() { else [ -n "$ip6addr" ] && ip -6 rule add from $ip6addr table 6$id pref 0 2>&1 >/dev/null [ -z "$(ip rule show pref 0 table 6$id oif $iface)" ] && ip rule add oif $iface table 6$id pref 0 - ip -6 route replace $network6/$netmask6 dev $iface scope link metric 6$id 2>&1 >/dev/null - ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id 2>&1 >/dev/null - ip -6 route replace default via $gateway6 dev $iface table 6$id 2>&1 >/dev/null - [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip -6 route replace default via $gateway6 dev $iface metric 6$id 2>&1 >/dev/null + ip -6 route replace $network6/$netmask6 dev $iface scope link metric 6$id initcwnd 10 initrwnd 10 2>&1 >/dev/null + ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id initcwnd 10 initrwnd 10 2>&1 >/dev/null + ip -6 route replace default via $gateway6 dev $iface table 6$id initcwnd 10 initrwnd 10 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip -6 route replace default via $gateway6 dev $iface metric 6$id initcwnd 10 initrwnd 10 2>&1 >/dev/null #ip -6 route flush 6$id 2>&1 >/dev/null fi diff --git a/mptcp/files/etc/uci-defaults/mptcp-defaults b/mptcp/files/etc/uci-defaults/mptcp-defaults index 594086874..21d2678a5 100755 --- a/mptcp/files/etc/uci-defaults/mptcp-defaults +++ b/mptcp/files/etc/uci-defaults/mptcp-defaults @@ -22,7 +22,7 @@ fi #fi if [ "$(uci -q get network.globals.mptcp_syn_retries)" = "1" ]; then uci -q batch <<-EOF >/dev/null - set network.globals.mptcp_syn_retries=2 + set network.globals.mptcp_syn_retries=4 commit network EOF fi diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index cffa56207..958a29504 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -57,8 +57,8 @@ set_route() { if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" = "yes" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" != "yes" ] && _log "$PREVINTERFACE down. Replace default in table 991337 route by $interface_gw dev $interface_if" - [ "$SETDEFAULT" = "yes" ] && [ "$(uci -q openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default scope global metric 1 nexthop via $interface_gw dev $interface_if 2>&1 >/dev/null - ip route replace default via $interface_gw dev $interface_if table 991337 2>&1 >/dev/null && SETROUTE=true + [ "$SETDEFAULT" = "yes" ] && [ "$(uci -q openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default scope global metric 1 via $interface_gw dev $interface_if initcwnd 10 initrwnd 10 2>&1 >/dev/null + ip route replace default via $interface_gw dev $interface_if table 991337 initcwnd 10 initrwnd 10 2>&1 >/dev/null && SETROUTE=true fi fi } @@ -123,7 +123,7 @@ set_server_default_route() { if [ "$(ip r show $serverip | grep nexthop)" != "" ]; then ip r delete $serverip >/dev/null 2>&1 fi - ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric 1 2>&1 >/dev/null + ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric 1 initcwnd 10 initrwnd 10 2>&1 >/dev/null fi } config_list_foreach $server ip server_route @@ -561,12 +561,12 @@ set_server_route() { #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then if [ "$serverip" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" - ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null + ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric initcwnd 10 initrwnd 10 2>&1 >/dev/null fi } config_list_foreach $server ip server_route if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ -n "$metric" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then - ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null + ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric initcwnd 10 initrwnd 10 2>&1 >/dev/null fi } @@ -991,7 +991,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw : $default_gw - Current route: $(ip r)" - ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null + ip route replace default scope global via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE initcwnd 10 initrwnd 10 2>&1 >/dev/null if [ "$(pgrep -f openmptcprouter-vps)" = "" ]; then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & fi @@ -1092,6 +1092,13 @@ if [ -n "$OMR_TRACKER_INTERFACE" ]; then } fi +if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + metric="$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" + if [ -z "$metric" ] || [ -z "$(ip route show table $metric | grep $OMR_TRACKER_DEVICE)" ]; then + /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" + fi +fi + if [ "$multipath_config" = "master" ]; then #if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && ([ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ] || [ "$(uci -q get openmptcprouter.settings.vpn)" = "mlvpn" ]); then if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then @@ -1099,7 +1106,7 @@ if [ "$multipath_config" = "master" ]; then [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" - ip route replace default scope global metric 1 nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null + ip route replace default scope global metric 1 via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE initcwnd 10 initrwnd 10 2>&1 >/dev/null fi config_load openmptcprouter #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then @@ -1186,10 +1193,10 @@ if [ "$multipath_config" = "master" ]; then fi fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE " ]; then - ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE table 991337 2>&1 >/dev/null + ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE table 991337 initcwnd 10 initrwnd 10 2>&1 >/dev/null fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE " ]; then - ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 991337 2>&1 >/dev/null + ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 991337 initcwnd 10 initrwnd 10 2>&1 >/dev/null fi if ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ]) || [ $(($(date +"%s") + $((10 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]; then [ "$(pgrep -f openmptcprouter-vps)" = "" ] && /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 832fdc808..0f1b7bc14 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -22,7 +22,7 @@ _setup_macvlan() { set network.$1_dev.type=macvlan set network.$1_dev.ifname=$_ifname set network.$1_dev.mode='vepa' - set network.$1_dev.txqueuelen=20 + set network.$1_dev.txqueuelen=1000 set network.$1.device=$1 set network.$1.type=macvlan set network.$1.masterintf=$_ifname @@ -66,7 +66,7 @@ _setup_wan_interface() { set network.$1.addlatency=0 set network.${1}_dev=device set network.${1}_dev.name=$2 - set network.${1}_dev.txqueuelen=20 + set network.${1}_dev.txqueuelen=1000 commit network add_list firewall.@zone[1].network=$1 commit firewall @@ -167,6 +167,7 @@ set network.lan.metric=2048 set network.lan.ipv6=0 set network.lan.delegate=0 set network.lan.addlatency=0 +set network.lan.txqueuelen=2000 set dhcp.lan.dhcpv4='server' EOF From e88d3b7b07c13195a6550d928bfae975f038cc47 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Feb 2023 21:00:08 +0100 Subject: [PATCH 0924/2059] Update iproute2 --- iproute2/Makefile | 62 +++++++--- .../130-no_netem_tipc_dcb_man_vdpa.patch | 11 +- .../patches/155-keep_tirpc_optional.patch | 11 ++ iproute2/patches/170-ip_tiny.patch | 108 ++++++++++++++++++ .../patches/195-build_variant_ip_tc.patch | 22 ++++ 5 files changed, 197 insertions(+), 17 deletions(-) create mode 100644 iproute2/patches/155-keep_tirpc_optional.patch create mode 100644 iproute2/patches/170-ip_tiny.patch create mode 100644 iproute2/patches/195-build_variant_ip_tc.patch diff --git a/iproute2/Makefile b/iproute2/Makefile index 1405f0752..302d57bf8 100644 --- a/iproute2/Makefile +++ b/iproute2/Makefile @@ -8,13 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iproute2 -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=git://git.kernel.org/pub/scm/network/iproute2/iproute2.git -PKG_SOURCE_VERSION:=29da83f89f6e1fe528c59131a01f5d43bcd0a000 -PKG_VERSION:=5.16.0-$(PKG_SOURCE_VERSION) +PKG_VERSION:=6.2.0 +PKG_RELEASE:=1 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 +PKG_HASH:=4d72730200ec5b2aabaa1a2f20553c6748292f065d9a154c7d5e22559df9fd62 PKG_BUILD_PARALLEL:=1 PKG_BUILD_DEPENDS:=iptables PKG_LICENSE:=GPL-2.0 @@ -58,7 +57,16 @@ $(call Package/iproute2/Default) DEFAULT_VARIANT:=1 PROVIDES:=tc ALTERNATIVES:=200:/sbin/tc:/usr/libexec/tc-tiny - DEPENDS:=+kmod-sched-core +libxtables +tc-mod-iptables +(PACKAGE_devlink||PACKAGE_rdma):libmnl + DEPENDS:=+kmod-sched-core +(PACKAGE_devlink||PACKAGE_rdma):libmnl +endef + +define Package/tc-bpf +$(call Package/iproute2/Default) + TITLE:=Traffic control utility (bpf) + VARIANT:=tcbpf + PROVIDES:=tc + ALTERNATIVES:=300:/sbin/tc:/usr/libexec/tc-bpf + DEPENDS:=+kmod-sched-core +(PACKAGE_devlink||PACKAGE_rdma):libmnl +libbpf endef define Package/tc-full @@ -66,14 +74,15 @@ $(call Package/iproute2/Default) TITLE:=Traffic control utility (full) VARIANT:=tcfull PROVIDES:=tc - ALTERNATIVES:=300:/sbin/tc:/usr/libexec/tc-full - DEPENDS:=+kmod-sched-core +libxtables +tc-mod-iptables +libbpf +(PACKAGE_devlink||PACKAGE_rdma):libmnl + ALTERNATIVES:=400:/sbin/tc:/usr/libexec/tc-full + DEPENDS:=+kmod-sched-core +(PACKAGE_devlink||PACKAGE_rdma):libmnl +libbpf +libxtables +tc-mod-iptables endef define Package/tc-mod-iptables $(call Package/iproute2/Default) TITLE:=Traffic control module - iptables action - DEPENDS:=+libxtables + VARIANT:=tcfull + DEPENDS:=+libxtables +libbpf endef define Package/genl @@ -124,13 +133,29 @@ endif ifeq ($(BUILD_VARIANT),tctiny) LIBBPF_FORCE:=off +endif + +ifeq ($(BUILD_VARIANT),tcbpf) + HAVE_ELF:=y + LIBBPF_FORCE:=on SHARED_LIBS:=y endif ifeq ($(BUILD_VARIANT),tcfull) + #enable iptables/xtables requirement only if tciptables variant is selected + TC_CONFIG_XT:=y + TC_CONFIG_XT_OLD:=y + TC_CONFIG_XT_OLD_H:=y + TC_CONFIG_IPSET:=y HAVE_ELF:=y LIBBPF_FORCE:=on SHARED_LIBS:=y +else + #disable iptables requirement by default + TC_CONFIG_XT:=n + TC_CONFIG_XT_OLD:=n + TC_CONFIG_XT_OLD_H:=n + TC_CONFIG_IPSET:=n endif ifdef CONFIG_PACKAGE_devlink @@ -151,7 +176,7 @@ TARGET_LDFLAGS += -Wl,--gc-sections -Wl,--as-needed TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny MAKE_FLAGS += \ - KERNEL_INCLUDE="$(LINUX_DIR)/user_headers/include" \ + KERNEL_INCLUDE="$(LINUX_DIR)/include/uapi" \ SHARED_LIBS=$(SHARED_LIBS) \ IP_CONFIG_TINY=$(IP_CONFIG_TINY) \ BUILD_VARIANT=$(BUILD_VARIANT) \ @@ -159,8 +184,13 @@ MAKE_FLAGS += \ HAVE_ELF=$(HAVE_ELF) \ HAVE_MNL=$(HAVE_MNL) \ HAVE_CAP=$(HAVE_CAP) \ + HAVE_TIRPC=n \ IPT_LIB_DIR=/usr/lib/iptables \ XT_LIB_DIR=/usr/lib/iptables \ + TC_CONFIG_XT=$(TC_CONFIG_XT) \ + TC_CONFIG_XT_OLD=$(TC_CONFIG_XT_OLD) \ + TC_CONFIG_XT_OLD_H=$(TC_CONFIG_XT_OLD_H) \ + TC_CONFIG_IPSET=$(TC_CONFIG_IPSET) \ FPIC="$(FPIC)" \ $(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') @@ -191,6 +221,11 @@ define Package/tc-tiny/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-tiny endef +define Package/tc-bpf/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-bpf +endef + define Package/tc-full/install $(INSTALL_DIR) $(1)/usr/libexec $(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-full @@ -231,12 +266,13 @@ define Package/rdma/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/rdma/rdma $(1)/usr/sbin/ endef -#$(eval $(call BuildPackage,ip-tiny)) +$(eval $(call BuildPackage,ip-tiny)) $(eval $(call BuildPackage,ip-full)) # build tc-mod-iptables before its dependents, to avoid # spurious rebuilds when building multiple variants. $(eval $(call BuildPackage,tc-mod-iptables)) -#$(eval $(call BuildPackage,tc-tiny)) +$(eval $(call BuildPackage,tc-tiny)) +$(eval $(call BuildPackage,tc-bpf)) $(eval $(call BuildPackage,tc-full)) $(eval $(call BuildPackage,genl)) $(eval $(call BuildPackage,ip-bridge)) diff --git a/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch b/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch index 8ddb31674..2a3f9eb90 100644 --- a/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch +++ b/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch @@ -1,11 +1,14 @@ --- a/Makefile +++ b/Makefile -@@ -55,7 +55,7 @@ WFLAGS += -Wmissing-declarations -Wold-s +@@ -65,9 +65,9 @@ WFLAGS += -Wmissing-declarations -Wold-s CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS) YACCFLAGS = -d -t -v --SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma dcb man vdpa -+SUBDIRS=lib ip tc bridge misc genl devlink rdma +-SUBDIRS=lib ip tc bridge misc netem genl man ++SUBDIRS=lib ip tc bridge misc genl + ifeq ($(HAVE_MNL),y) +-SUBDIRS += tipc devlink rdma dcb vdpa ++SUBDIRS += devlink rdma + endif LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a - LDLIBS += $(LIBNETLINK) diff --git a/iproute2/patches/155-keep_tirpc_optional.patch b/iproute2/patches/155-keep_tirpc_optional.patch new file mode 100644 index 000000000..28ba7e521 --- /dev/null +++ b/iproute2/patches/155-keep_tirpc_optional.patch @@ -0,0 +1,11 @@ +--- a/configure ++++ b/configure +@@ -398,7 +398,7 @@ check_selinux() + + check_tirpc() + { +- if ${PKG_CONFIG} libtirpc --exists; then ++ if [ "${HAVE_TIRPC}" = "y" ] && ${PKG_CONFIG} libtirpc --exists; then + echo "HAVE_RPC:=y" >>$CONFIG + echo "yes" + diff --git a/iproute2/patches/170-ip_tiny.patch b/iproute2/patches/170-ip_tiny.patch new file mode 100644 index 000000000..71081c36b --- /dev/null +++ b/iproute2/patches/170-ip_tiny.patch @@ -0,0 +1,108 @@ +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -19,6 +19,13 @@ RTMONOBJ=rtmon.o + + include ../config.mk + ++STATIC_SYM_FILTER:= ++ifeq ($(IP_CONFIG_TINY),y) ++ STATIC_SYM_FILTER:=iplink_can.c iplink_ipoib.c iplink_vxlan.c ++ CFLAGS += -DIPROUTE2_TINY ++endif ++STATIC_SYM_SOURCES:=$(filter-out $(STATIC_SYM_FILTER),$(wildcard *.c)) ++ + ALLOBJ=$(IPOBJ) $(RTMONOBJ) + SCRIPTS=routel + TARGETS=ip rtmon +@@ -48,7 +55,7 @@ else + + ip: static-syms.o + static-syms.o: static-syms.h +-static-syms.h: $(wildcard *.c) ++static-syms.h: $(STATIC_SYM_SOURCES) + files="$^" ; \ + for s in `grep -B 3 '\ Date: Sat, 4 Mar 2023 08:24:31 +0100 Subject: [PATCH 0925/2059] Add MPTCP upstream support to dsvpn --- dsvpn/Makefile | 8 +++-- dsvpn/patches/nofirewall.patch | 65 ---------------------------------- 2 files changed, 5 insertions(+), 68 deletions(-) delete mode 100644 dsvpn/patches/nofirewall.patch diff --git a/dsvpn/Makefile b/dsvpn/Makefile index c3215e93a..0aed2bc5c 100644 --- a/dsvpn/Makefile +++ b/dsvpn/Makefile @@ -8,10 +8,12 @@ include $(TOPDIR)/rules.mk PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/jedisct1/dsvpn.git -PKG_SOURCE_VERSION:=3b99d2ef6c02b2ef68b5784bec8adfdd55b29b1a +#PKG_SOURCE_URL:=https://github.com/jedisct1/dsvpn.git +PKG_SOURCE_URL:=https://github.com/Ysurac/dsvpn.git +#PKG_SOURCE_VERSION:=3b99d2ef6c02b2ef68b5784bec8adfdd55b29b1a +PKG_SOURCE_VERSION:=4333aa705efd9c86c76809614d20dc5ebf43da7f PKG_NAME:=dsvpn -PKG_VERSION:=0.1.4-$(PKG_SOURCE_VERSION) +PKG_VERSION:=0.1.5-$(PKG_SOURCE_VERSION) PKG_RELEASE:=1 include $(INCLUDE_DIR)/package.mk diff --git a/dsvpn/patches/nofirewall.patch b/dsvpn/patches/nofirewall.patch deleted file mode 100644 index 89c866640..000000000 --- a/dsvpn/patches/nofirewall.patch +++ /dev/null @@ -1,65 +0,0 @@ ---- a/src/os.c 2019-12-06 19:49:50.323898270 +0100 -+++ b/src/os.c 2019-12-06 19:54:20.987206244 +0100 -@@ -445,24 +445,28 @@ - #ifdef __linux__ - static const char - *set_cmds[] = -- { "sysctl net.ipv4.ip_forward=1", -- "ip addr add $LOCAL_TUN_IP peer $REMOTE_TUN_IP dev $IF_NAME", -+ { "ip addr add $LOCAL_TUN_IP peer $REMOTE_TUN_IP dev $IF_NAME", - "ip -6 addr add $LOCAL_TUN_IP6 peer $REMOTE_TUN_IP6/96 dev $IF_NAME", - "ip link set dev $IF_NAME up", -+#ifndef NO_DEFAULT_FIREWALL -+ "sysctl net.ipv4.ip_forward=1", - "iptables -t raw -I PREROUTING ! -i $IF_NAME -d $LOCAL_TUN_IP -m addrtype ! " - "--src-type LOCAL -j DROP", - "iptables -t nat -A POSTROUTING -o $EXT_IF_NAME -s $REMOTE_TUN_IP -j MASQUERADE", - "iptables -t filter -A FORWARD -i $EXT_IF_NAME -o $IF_NAME -m state --state " - "RELATED,ESTABLISHED -j ACCEPT", - "iptables -t filter -A FORWARD -i $IF_NAME -o $EXT_IF_NAME -j ACCEPT", -+#endif - NULL }, - *unset_cmds[] = { -+#ifndef NO_DEFAULT_FIREWALL - "iptables -t nat -D POSTROUTING -o $EXT_IF_NAME -s $REMOTE_TUN_IP -j MASQUERADE", - "iptables -t filter -D FORWARD -i $EXT_IF_NAME -o $IF_NAME -m state --state " - "RELATED,ESTABLISHED -j ACCEPT", - "iptables -t filter -D FORWARD -i $IF_NAME -o $EXT_IF_NAME -j ACCEPT", - "iptables -t raw -D PREROUTING ! -i $IF_NAME -d $LOCAL_TUN_IP -m addrtype ! " - "--src-type LOCAL -j DROP", -+#endif - NULL - }; - #elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ -@@ -503,12 +507,17 @@ - #elif defined(__linux__) - static const char - *set_cmds[] = -- { "sysctl net.ipv4.tcp_congestion_control=bbr", -+ { -+#ifndef NO_DEFAULT_CONGESTION -+ "sysctl net.ipv4.tcp_congestion_control=bbr", -+#endif - "ip link set dev $IF_NAME up", -- "iptables -t raw -I PREROUTING ! -i $IF_NAME -d $LOCAL_TUN_IP -m addrtype ! " -- "--src-type LOCAL -j DROP", - "ip addr add $LOCAL_TUN_IP peer $REMOTE_TUN_IP dev $IF_NAME", - "ip -6 addr add $LOCAL_TUN_IP6 peer $REMOTE_TUN_IP6/96 dev $IF_NAME", -+#ifndef NO_DEFAULT_FIREWALL -+ "iptables -t raw -I PREROUTING ! -i $IF_NAME -d $LOCAL_TUN_IP -m addrtype ! " -+ "--src-type LOCAL -j DROP", -+#endif - #ifndef NO_DEFAULT_ROUTES - "ip route add default dev $IF_NAME table 42069", - "ip -6 route add default dev $IF_NAME table 42069", -@@ -525,8 +534,10 @@ - "ip rule delete table main suppress_prefixlength 0", - "ip -6 rule delete table main suppress_prefixlength 0", - #endif -+#ifndef NO_DEFAULT_FIREWALL - "iptables -t raw -D PREROUTING ! -i $IF_NAME -d $LOCAL_TUN_IP -m addrtype ! " - "--src-type LOCAL -j DROP", -+#endif - NULL - }; - #else From 6a15da5486566d7e77fb2fd76c7a2951ba92a4dd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 8 Mar 2023 20:40:19 +0100 Subject: [PATCH 0926/2059] Update ndpi-netfilter2 --- ndpi-netfilter2/Makefile | 2 +- ndpi-netfilter2/patches/skbuff-check_fix.patch | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 8983cff1b..23baad9a3 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 -PKG_REV:=ac0ad66b3644a43cbaa821a6135d3e610f8b2c1a +PKG_REV:=845399a0acb423e940c67a881a10f30f4c6a5fb7 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git diff --git a/ndpi-netfilter2/patches/skbuff-check_fix.patch b/ndpi-netfilter2/patches/skbuff-check_fix.patch index ccc90c3ab..f5fe4defc 100644 --- a/ndpi-netfilter2/patches/skbuff-check_fix.patch +++ b/ndpi-netfilter2/patches/skbuff-check_fix.patch @@ -4,8 +4,8 @@ KERNEL_DIR := /lib/modules/$(shell uname -r)/build endif --ifeq ($(shell grep -qc userid $(KERNEL_DIR)/source/include/linux/skbuff.h),1) -+ifeq ($(shell grep -qc userid $(KERNEL_DIR)/include/linux/skbuff.h),1) +-ifeq ($(shell test -f $(KERNEL_DIR)/source/include/linux/skbuff.h && grep -qc userid $(KERNEL_DIR)/source/include/linux/skbuff.h),1) ++ifeq ($(shell test -f $(KERNEL_DIR)/include/linux/skbuff.h && shell grep -qc userid $(KERNEL_DIR)/include/linux/skbuff.h),1) ccflags-y += -DUSE_HACK_USERID=1 endif From 5ca7fd25b0f73b8c7b89300333ee5bde0f36e502 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 10 Mar 2023 20:26:46 +0100 Subject: [PATCH 0927/2059] Optimize Glorytun TCP --- glorytun/init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glorytun/init b/glorytun/init index 1384a0315..2adf71989 100755 --- a/glorytun/init +++ b/glorytun/init @@ -79,10 +79,10 @@ start_instance() { [ "${multiqueue}" = "1" ] && procd_append_param command multiqueue procd_append_param command \ - retry count -1 const 500000 \ + retry count -1 const 5000000 \ timeout ${timeout} \ keepalive count 5 idle 20 interval 2 \ - buffer-size 32768 + buffer-size 1024 procd_set_param respawn 0 30 0 procd_set_param file /tmp/${PROG_NAME}-${1}.key From 42514609b53bf88f596904b2b4022130267734bf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 10 Mar 2023 20:27:35 +0100 Subject: [PATCH 0928/2059] Enable MTU calculation again on Glorytun --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 958a29504..79ea2fcb9 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1008,7 +1008,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om fi uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE="interface" uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" - if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then + #if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then OMR_NETWORK_DEVICE=$(find_network_device ${OMR_TRACKER_INTERFACE}) if [ -n "$OMR_NETWORK_DEVICE" ] && [ -n "$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then mtu=$(uci -q get network.$OMR_NETWORK_DEVICE.mtu) @@ -1035,9 +1035,9 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om else uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") fi - else - uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") - fi + #else + # uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") + #fi [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi nbserver=0 From a3fc59f80e1980cbceb76b7a2c8399a405f5263a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Mar 2023 20:24:13 +0200 Subject: [PATCH 0929/2059] Fix glorytun buffer --- glorytun/init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glorytun/init b/glorytun/init index 2adf71989..c0011edc1 100755 --- a/glorytun/init +++ b/glorytun/init @@ -82,7 +82,7 @@ start_instance() { retry count -1 const 5000000 \ timeout ${timeout} \ keepalive count 5 idle 20 interval 2 \ - buffer-size 1024 + buffer-size 32768 procd_set_param respawn 0 30 0 procd_set_param file /tmp/${PROG_NAME}-${1}.key From 063a468465a39b5f5d6692d9c76fe6a82b3ebc65 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 28 Mar 2023 20:26:02 +0200 Subject: [PATCH 0930/2059] Update SQM autorate --- .../luci-static/resources/view/network/sqm.js | 4 + .../root/etc/init.d/sqm-autorate | 28 +- luci-app-sqm-autorate/root/root/cake-autorate | 1 + .../usr/share/sqm-autorate/CAKE-autorate.sh | 658 ------ .../usr/share/sqm-autorate/cake-autorate.sh | 1790 +++++++++++++++++ .../sqm-autorate/cake-autorate_defaults.sh | 209 ++ .../sqm-autorate/cake-autorate_launcher.sh | 26 + .../share/sqm-autorate/cake-autorate_lib.sh | 257 +++ .../sqm-autorate/cake-autorate_template.sh | 213 ++ .../root/usr/share/sqm-autorate/config.sh | 32 +- .../share/omr/post-tracking.d/post-tracking | 3 +- 11 files changed, 2526 insertions(+), 695 deletions(-) create mode 120000 luci-app-sqm-autorate/root/root/cake-autorate delete mode 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh create mode 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh create mode 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh create mode 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh create mode 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh create mode 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh mode change 100644 => 100755 luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh diff --git a/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js index c7f33a8b8..c367e660c 100644 --- a/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js +++ b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js @@ -260,6 +260,10 @@ return view.extend({ o.default = false; o.depends("autorate","1"); + o = s.taboption("tab_autorate", form.Flag, "sss_compensation", _("Starlink support")); + o.default = false; + o.depends("autorate","1"); + o = s.taboption("tab_autorate", form.Value, "reflector_ping_interval_s", _("Reflector ping interval in seconds:")); o.default = "0.2"; o.depends("autorate","1"); diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 1646d2e2a..7ab556492 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -14,8 +14,8 @@ . /usr/lib/unbound/iptools.sh . /lib/functions/network.sh -_launch_autorate() { - logger -t "SQM-autorate" "Launch on $1" +_config_autorate() { + logger -t "SQM-autorate" "Set config for $1" config_get enabled "$1" enabled [ "${enabled}" != "1" ] && return config_get autorate "$1" autorate @@ -29,20 +29,36 @@ _launch_autorate() { config_get upload "$1" upload config_get max_upload "$1" max_upload [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return + config_get interface "$1" interface + cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh +} +_launch_autorate() { + logger -t "SQM-autorate" "Launch..." procd_open_instance # shellcheck disable=SC2086 - procd_set_param command /usr/share/sqm-autorate/CAKE-autorate.sh "$1" -# procd_append_param env "OMR_TRACKER_SERVER_HTTP_TEST=$server_http_test" + procd_set_param command /usr/share/sqm-autorate/cake-autorate_launcher.sh procd_set_param limits nofile="51200 51200" procd_set_param respawn 0 10 0 procd_set_param stderr 1 procd_close_instance - sleep 2 } start_service() { config_load sqm - config_foreach _launch_autorate queue + config_foreach _config_autorate queue + _launch_autorate } +stop_service() { + rm -f /usr/share/sqm-autorate/cake-autorate_config.*.sh +} + +reload_service() { + stop + start +} + +service_triggers() { + procd_add_reload_trigger sqm +} \ No newline at end of file diff --git a/luci-app-sqm-autorate/root/root/cake-autorate b/luci-app-sqm-autorate/root/root/cake-autorate new file mode 120000 index 000000000..66f5d6886 --- /dev/null +++ b/luci-app-sqm-autorate/root/root/cake-autorate @@ -0,0 +1 @@ +../usr/share/sqm-autorate \ No newline at end of file diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh deleted file mode 100755 index 560039b22..000000000 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/CAKE-autorate.sh +++ /dev/null @@ -1,658 +0,0 @@ -#!/bin/bash - -# CAKE-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and OWD/RTT -# requires packages: bash; and iputils-ping - -# Author: @Lynx (OpenWrt forum) -# Inspiration taken from: @moeller0 (OpenWrt forum) -# Modified by Ycarus (Yannick Chabanois) for OpenMPTCProuter: -# * Add multiples interfaces support - -# Possible performance improvement -export LC_ALL=C -export TZ=UTC - -trap cleanup_and_killall INT TERM EXIT - -cleanup_and_killall() -{ - echo "Killing all background processes and cleaning up /tmp files." - trap - INT TERM EXIT - kill $monitor_achieved_rates_pid 2> /dev/null - # Initiate termination of ping processes and wait until complete - kill $maintain_pingers_pid 2> /dev/null - wait $maintain_pingers_pid - [[ -d /tmp/CAKE-autorate-${dl_if} ]] && rm -r /tmp/CAKE-autorate-${dl_if} - exit -} - -install_dir="/usr/share/sqm-autorate/" - -. $install_dir"config.sh" "$1" - -# test if stdout is a tty (terminal) -[[ ! -t 1 ]] && exec &> /tmp/cake-autorate-${dl_if}.log - -get_next_shaper_rate() -{ - local min_shaper_rate_kbps=$1 - local base_shaper_rate_kbps=$2 - local max_shaper_rate_kbps=$3 - local achieved_rate_kbps=$4 - local load_condition=$5 - local t_next_rate_us=$6 - local -n t_last_bufferbloat_us=$7 - local -n t_last_decay_us=$8 - local -n shaper_rate_kbps=$9 - - case $load_condition in - - # upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period - ul*sss) - shaper_rate_kbps=$min_shaper_rate_kbps - ;; - # download Starlink satelite switching compensation, so drop down to base rate for download through switching period - dl*sss) - shaper_rate_kbps=$base_shaper_rate_kbps - ;; - # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period - *bb*) - if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then - adjusted_achieved_rate_kbps=$(( ($achieved_rate_kbps*$achieved_rate_adjust_down_bufferbloat)/1000 )) - adjusted_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_down_bufferbloat)/1000 )) - shaper_rate_kbps=$(( $adjusted_achieved_rate_kbps < $adjusted_shaper_rate_kbps ? $adjusted_achieved_rate_kbps : $adjusted_shaper_rate_kbps )) - t_last_bufferbloat_us=${EPOCHREALTIME/./} - fi - ;; - # high load, so increase rate providing not inside bufferbloat refractory period - *high*) - if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then - shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_up_load_high)/1000 )) - fi - ;; - # medium load, so just maintain rate as is, i.e. do nothing - *med*) - : - ;; - # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate - *low*|*idle*) - if (($t_next_rate_us > ($t_last_decay_us+$decay_refractory_period_us) )); then - - if (($shaper_rate_kbps > $base_shaper_rate_kbps)); then - decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_down_load_low)/1000 )) - shaper_rate_kbps=$(( $decayed_shaper_rate_kbps > $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps)) - elif (($shaper_rate_kbps < $base_shaper_rate_kbps)); then - decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_up_load_low)/1000 )) - shaper_rate_kbps=$(( $decayed_shaper_rate_kbps < $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps)) - fi - - t_last_decay_us=${EPOCHREALTIME/./} - fi - ;; - esac - # make sure to only return rates between cur_min_rate and cur_max_rate - (($shaper_rate_kbps < $min_shaper_rate_kbps)) && shaper_rate_kbps=$min_shaper_rate_kbps; - (($shaper_rate_kbps > $max_shaper_rate_kbps)) && shaper_rate_kbps=$max_shaper_rate_kbps; -} - -monitor_achieved_rates() -{ - # track rx and tx bytes transfered and divide by time since last update - # to determine achieved dl and ul transfer rates - - local rx_bytes_path=$1 - local tx_bytes_path=$2 - local monitor_achieved_rates_interval_us=$3 # (microseconds) - - compensated_monitor_achieved_rates_interval_us=$monitor_achieved_rates_interval_us - - [[ -f $rx_bytes_path ]] && { read -r prev_rx_bytes < $rx_bytes_path; } 2> /dev/null || prev_rx_bytes=0 - [[ -f $tx_bytes_path ]] && { read -r prev_tx_bytes < $tx_bytes_path; } 2> /dev/null || prev_tx_bytes=0 - - while true - do - t_start_us=${EPOCHREALTIME/./} - - # If rx/tx bytes file exists, read it in, otherwise set to prev_bytes - # This addresses interfaces going down and back up - [[ -f $rx_bytes_path ]] && { read -r rx_bytes < $rx_bytes_path; } 2> /dev/null || rx_bytes=$prev_rx_bytes - [[ -f $tx_bytes_path ]] && { read -r tx_bytes < $tx_bytes_path; } 2> /dev/null || tx_bytes=$prev_tx_bytes - - dl_achieved_rate_kbps=$(( ((8000*($rx_bytes - $prev_rx_bytes)) / $compensated_monitor_achieved_rates_interval_us ) )) - ul_achieved_rate_kbps=$(( ((8000*($tx_bytes - $prev_tx_bytes)) / $compensated_monitor_achieved_rates_interval_us ) )) - - (($dl_achieved_rate_kbps<0)) && dl_achieved_rate_kbps=0 - (($ul_achieved_rate_kbps<0)) && ul_achieved_rate_kbps=0 - - printf '%s' "$dl_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps - printf '%s' "$ul_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps - - prev_rx_bytes=$rx_bytes - prev_tx_bytes=$tx_bytes - - # read in the max_wire_packet_rtt_us - concurrent_read_positive_integer max_wire_packet_rtt_us /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us - - compensated_monitor_achieved_rates_interval_us=$(( (($monitor_achieved_rates_interval_us>(10*$max_wire_packet_rtt_us) )) ? $monitor_achieved_rates_interval_us : $((10*$max_wire_packet_rtt_us)) )) - - sleep_remaining_tick_time $t_start_us $compensated_monitor_achieved_rates_interval_us - done -} - -get_loads() -{ - # read in the dl/ul achived rates and determine the loads - - concurrent_read_positive_integer dl_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps - concurrent_read_positive_integer ul_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps - - dl_load_percent=$(((100*10#${dl_achieved_rate_kbps})/$dl_shaper_rate_kbps)) - ul_load_percent=$(((100*10#${ul_achieved_rate_kbps})/$ul_shaper_rate_kbps)) -} - -classify_load() -{ - # classify the load according to high/low/medium/idle and add _delayed if delayed - # thus ending up with high_delayed, low_delayed, etc. - local load_percent=$1 - local achieved_rate_kbps=$2 - local -n load_condition=$3 - - if (( $load_percent > $high_load_thr_percent )); then - load_condition="high" - elif (( $load_percent > $medium_load_thr_percent )); then - load_condition="med" - elif (( $achieved_rate_kbps > $connection_active_thr_kbps )); then - load_condition="low" - else - load_condition="idle" - fi - - (($bufferbloat_detected)) && load_condition=$load_condition"_bb" - - if ((sss_compensation)); then - for sss_time_us in "${sss_times_us[@]}" - do - ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) - if (( ($timestamp_usecs_past_minute > ($sss_time_us-$sss_compensation_pre_duration_us)) && ($timestamp_usecs_past_minute < ($sss_time_us+$sss_compensation_post_duration_us)) )); then - load_condition=$load_condition"_sss" - break - fi - done - fi -} - -monitor_reflector_responses() -{ - # ping reflector, maintain baseline and output deltas to a common fifo - - local pinger=$1 - local rtt_baseline_us=$2 - - while read -r timestamp _ _ _ reflector seq_rtt - do - # If no match then skip onto the next one - [[ $seq_rtt =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue - - seq=${BASH_REMATCH[1]} - - rtt_us=${BASH_REMATCH[3]}000 - rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) - - reflector=${reflector//:/} - - rtt_delta_us=$(( $rtt_us-$rtt_baseline_us )) - - alpha=$(( (( $rtt_delta_us >=0 )) ? $alpha_baseline_increase : $alpha_baseline_decrease )) - - rtt_baseline_us=$(( ( (1000-$alpha)*$rtt_baseline_us+$alpha*$rtt_us )/1000 )) - - printf '%s %s %s %s %s %s\n' "$timestamp" "$reflector" "$seq" "$rtt_baseline_us" "$rtt_us" "$rtt_delta_us" > /tmp/CAKE-autorate-${dl_if}/ping_fifo - - printf '%s' "${timestamp//[[\[\].]}" > /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us - - done /dev/null - [[ -p /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo ]] && rm /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo - done - exit -} - -maintain_pingers() -{ - # this initiates the pingers and monitors reflector health, rotating reflectors as necessary - - trap kill_pingers TERM - - declare -A pinger_pids - declare -A rtt_baselines_us - - reflector_offences_idx=0 - - # For each pinger: create fifos, get baselines and initialize record of offences - for ((pinger=0; pinger<$no_pingers; pinger++)) - do - mkfifo /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo - [[ $(ping -B -I ${dl_if} -q -c 5 -i 0.1 ${reflectors[$pinger]} | tail -1) =~ ([0-9.]+)/ ]] && printf -v rtt_baselines_us[$pinger] %.0f\\n "${BASH_REMATCH[1]}e3" || rtt_baselines_us[$pinger]=0 - - declare -n reflector_offences="reflector_${pinger}_offences" - for ((i=0; i<$reflector_misbehaving_detection_window; i++)) do reflector_offences[i]=0; done - - sum_reflector_offences[$pinger]=0 - done - - pingers_t_start_us=${EPOCHREALTIME/./} - - # Initiate pingers - for ((pinger=0; pinger<$no_pingers; pinger++)) - do - printf '%s' "$pingers_t_start_us" > /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us - start_pinger_next_pinger_time_slot $pinger pid - pinger_pids[$pinger]=$pid - done - - # Reflector health check loop - verifies reflectors have not gone stale and rotates reflectors as necessary - while true - do - sleep_s $reflector_health_check_interval_s - - for ((pinger=0; pinger<$no_pingers; pinger++)) - do - reflector_check_time_us=${EPOCHREALTIME/./} - concurrent_read_positive_integer reflector_last_timestamp_us /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us - declare -n reflector_offences="reflector_${pinger}_offences" - - (( ${reflector_offences[$reflector_offences_idx]} )) && ((sum_reflector_offences[$pinger]--)) - reflector_offences[$reflector_offences_idx]=$(( (((${EPOCHREALTIME/./}-$reflector_last_timestamp_us) > $reflector_response_deadline_us)) ? 1 : 0 )) - ((reflector_offences[$reflector_offences_idx])) && ((sum_reflector_offences[$pinger]++)) - - if ((sum_reflector_offences[$pinger]>=$reflector_misbehaving_detection_thr)); then - - (($debug)) && echo "DEBUG: Warning: reflector: "${reflectors[$pinger]}" seems to be misbehaving." - - if(($no_reflectors>$no_pingers)); then - - # pingers always use reflectors[0]..[$no_pingers-1] as the initial set - # and the additional reflectors are spare reflectors should any from initial set go stale - # a bad reflector in the initial set is replaced with $reflectors[$no_pingers] - # $reflectors[$no_pingers] is then unset - # and the the bad reflector moved to the back of the queue (last element in $reflectors[]) - # and finally the indices for $reflectors are updated to reflect the new order - - (($debug)) && echo "DEBUG: Replacing reflector: "${reflectors[$pinger]}" with "${reflectors[$no_pingers]}"." - kill ${pinger_pids[$pinger]} 2> /dev/null - bad_reflector=${reflectors[$pinger]} - # overwrite the bad reflector with the reflector that is next in the queue (the one after 0..$no_pingers-1) - reflectors[$pinger]=${reflectors[$no_pingers]} - # remove the new reflector from the list of additional reflectors beginning from $reflectors[$no_pingers] - unset reflectors[$no_pingers] - # bad reflector goes to the back of the queue - reflectors+=($bad_reflector) - # reset array indices - reflectors=(${reflectors[*]}) - # set up the new pinger with the new reflector and retain pid - start_pinger_next_pinger_time_slot $pinger pid - pinger_pids[$pinger]=$pid - - else - (($debug)) && echo "DEBUG: No additional reflectors specified so just retaining: "${reflectors[$pinger]}"." - reflector_offences[$pinger]=0 - fi - - for ((i=0; i<$reflector_misbehaving_detection_window; i++)) do reflector_offences[i]=0; done - sum_reflector_offences[$pinger]=0 - fi - done - ((reflector_offences_idx=(reflector_offences_idx+1)%$reflector_misbehaving_detection_window)) - done -} - -start_pinger_next_pinger_time_slot() -{ - # wait until next pinger time slot and start pinger in its slot - # this allows pingers to be stopped and started (e.g. during sleep or reflector rotation) - # whilst ensuring pings will remain spaced out appropriately to maintain granularity - - local pinger=$1 - local -n pinger_pid=$2 - t_start_us=${EPOCHREALTIME/./} - time_to_next_time_slot_us=$(( ($reflector_ping_interval_us-($t_start_us-$pingers_t_start_us)%$reflector_ping_interval_us) + $pinger*$ping_response_interval_us )) - sleep_remaining_tick_time $t_start_us $time_to_next_time_slot_us - if (($debug)); then - ping -B -I ${dl_if} -D -i $reflector_ping_interval_s ${reflectors[$pinger]} > /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo & - pinger_pid=$! - else - ping -B -I ${dl_if} -D -i $reflector_ping_interval_s ${reflectors[$pinger]} > /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo 2> /dev/null & - pinger_pid=$! - fi - monitor_reflector_responses $pinger ${rtt_baselines_us[$pinger]} & -} - -set_cake_rate() -{ - local interface=$1 - local shaper_rate_kbps=$2 - local -n time_rate_set_us=$3 - - (($output_cake_changes)) && echo "tc qdisc change root dev ${interface} cake bandwidth ${shaper_rate_kbps}Kbit" - - if (($debug)); then - tc qdisc change root dev $interface cake bandwidth ${shaper_rate_kbps}Kbit - else - tc qdisc change root dev $interface cake bandwidth ${shaper_rate_kbps}Kbit 2> /dev/null - fi - - time_rate_set_us=${EPOCHREALTIME/./} -} - -set_shaper_rates() -{ - if (( $dl_shaper_rate_kbps != $last_dl_shaper_rate_kbps || $ul_shaper_rate_kbps != $last_ul_shaper_rate_kbps )); then - - # fire up tc in each direction if there are rates to change, and if rates change in either direction then update max wire calcs - (( $dl_shaper_rate_kbps != $last_dl_shaper_rate_kbps )) && { set_cake_rate $dl_if $dl_shaper_rate_kbps t_prev_dl_rate_set_us; last_dl_shaper_rate_kbps=$dl_shaper_rate_kbps; } - (( $ul_shaper_rate_kbps != $last_ul_shaper_rate_kbps )) && { set_cake_rate $ul_if $ul_shaper_rate_kbps t_prev_ul_rate_set_us; last_ul_shaper_rate_kbps=$ul_shaper_rate_kbps; } - - update_max_wire_packet_compensation - fi -} - -get_max_wire_packet_size_bits() -{ - local interface=$1 - local -n max_wire_packet_size_bits=$2 - - read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" - [[ $(tc qdisc show dev $interface) =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] - [[ ! -z "${BASH_REMATCH[2]}" ]] && max_wire_packet_size_bits=$((8*($max_wire_packet_size_bits+${BASH_REMATCH[2]}))) - # atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits - [[ "${BASH_REMATCH[1]}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*(($max_wire_packet_size_bits+376)/384) )) -} - -update_max_wire_packet_compensation() -{ - # Compensate for delays imposed by active traffic shaper - # This will serve to increase the delay thr at rates below around 12Mbit/s - - max_wire_packet_rtt_us=$(( (1000*$dl_max_wire_packet_size_bits)/$dl_shaper_rate_kbps + (1000*$ul_max_wire_packet_size_bits)/$ul_shaper_rate_kbps )) - compensated_delay_thr_us=$(( $delay_thr_us + $max_wire_packet_rtt_us )) - - # write out max_wire_packet_rtt_us - printf '%s' "$max_wire_packet_rtt_us" > /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us -} - -concurrent_read_positive_integer() -{ - # in the context of separate processes writing using > and reading form file - # it seems costly calls to the external flock binary can be avoided - # read either succeeds as expected or occassionally reads in bank value - # so just test for blank value and re-read until not blank - - local -n value=$1 - local path=$2 - while true - do - read -r value < $path; - if [[ -z "${value##*[!0-9]*}" ]]; then - if (($debug)); then - read -r caller_output< <(caller) - echo "DEBUG concurrent_read_positive_integer() misfire with the following particulars:" - echo "DEBUG caller="$caller_output"; value="$value"; and path="$path - fi - sleep_us $concurrent_read_positive_integer_interval_us - continue - else - break - fi - done -} - -verify_ifs_up() -{ - # Check the rx/tx paths exist and give extra time for ifb's to come up if needed - # This will block if ifs never come up - - while [[ ! -f $rx_bytes_path || ! -f $tx_bytes_path ]] - do - (($debug)) && [[ ! -f $rx_bytes_path ]] && echo "DEBUG Warning: $rx_bytes_path does not exist. Waiting "$if_up_check_interval_s" seconds for interface to come up." - (($debug)) && [[ ! -f $tx_bytes_path ]] && echo "DEBUG Warning: $tx_bytes_path does not exist. Waiting "$if_up_check_interval_s" seconds for interface to come up." - sleep_s $if_up_check_interval_s - done -} - -sleep_s() -{ - # calling external sleep binary is slow - # bash does have a loadable sleep - # but read's timeout can more portably be exploited and this is apparently even faster anyway - - local sleep_duration_s=$1 # (seconds, e.g. 0.5, 1 or 1.5) - - read -t $sleep_duration_s < /tmp/CAKE-autorate-${dl_if}/sleep_fifo -} - -sleep_us() -{ - # calling external sleep binary is slow - # bash does have a loadable sleep - # but read's timeout can more portably be exploited and this is apparently even fastera anyway - - local sleep_duration_us=$1 # (microseconds) - - sleep_duration_s=000000$sleep_duration_us - sleep_duration_s=${sleep_duration_s::-6}.${sleep_duration_s: -6} - read -t $sleep_duration_s < /tmp/CAKE-autorate-${dl_if}/sleep_fifo -} - -sleep_remaining_tick_time() -{ - # sleeps until the end of the tick duration - - local t_start_us=$1 # (microseconds) - local tick_duration_us=$2 # (microseconds) - - sleep_duration_us=$(( $t_start_us + $tick_duration_us - ${EPOCHREALTIME/./} )) - - if (( $sleep_duration_us > 0 )); then - sleep_us $sleep_duration_us - fi -} - -# Set up tmp directory, sleep fifo and perform various sanity checks - -# /tmp/CAKE-autorate-${dl_if}/ is used to store temporary files -# it should not exist on startup so if it does exit, else create the directory -if [[ -d /tmp/CAKE-autorate-${dl_if} ]]; then - echo "Error: /tmp/CAKE-autorate-${dl_if} already exists. Is another instance running? Exiting script." - trap - INT TERM EXIT - exit -else - mkdir /tmp/CAKE-autorate-${dl_if} -fi - -mkfifo /tmp/CAKE-autorate-${dl_if}/sleep_fifo -exec 3<> /tmp/CAKE-autorate-${dl_if}/sleep_fifo - -no_reflectors=${#reflectors[@]} - -# Check no_pingers <= no_reflectors -(( $no_pingers > $no_reflectors)) && { echo "Error: number of pingers cannot be greater than number of reflectors. Exiting script."; exit; } - -# Check dl/if interface not the same -[[ $dl_if == $ul_if ]] && { echo "Error: download interface and upload interface are both set to: '"$dl_if"', but cannot be the same. Exiting script."; exit; } - -# Check bufferbloat detection threshold not greater than window length -(( $bufferbloat_detection_thr > $bufferbloat_detection_window )) && { echo "Error: bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } - -# Wait if $startup_wait_s > 0 -if (($startup_wait_s>0)); then - (($debug)) && echo "DEBUG Waiting "$startup_wait_s" seconds before startup." - sleep_s $startup_wait_s -fi - -# Check interfaces are up and wait if necessary for them to come up -verify_ifs_up - -# Initialize variables - -# Convert human readable parameters to values that work with integer arithmetic -printf -v alpha_baseline_increase %.0f\\n "${alpha_baseline_increase}e3" -printf -v alpha_baseline_decrease %.0f\\n "${alpha_baseline_decrease}e3" -printf -v achieved_rate_adjust_down_bufferbloat %.0f\\n "${achieved_rate_adjust_down_bufferbloat}e3" -printf -v shaper_rate_adjust_down_bufferbloat %.0f\\n "${shaper_rate_adjust_down_bufferbloat}e3" -printf -v shaper_rate_adjust_up_load_high %.0f\\n "${shaper_rate_adjust_up_load_high}e3" -printf -v shaper_rate_adjust_down_load_low %.0f\\n "${shaper_rate_adjust_down_load_low}e3" -printf -v shaper_rate_adjust_up_load_low %.0f\\n "${shaper_rate_adjust_up_load_low}e3" -printf -v high_load_thr_percent %.0f\\n "${high_load_thr}e2" -printf -v medium_load_thr_percent %.0f\\n "${medium_load_thr}e2" -printf -v reflector_ping_interval_us %.0f\\n "${reflector_ping_interval_s}e6" -printf -v monitor_achieved_rates_interval_us %.0f\\n "${monitor_achieved_rates_interval_ms}e3" -printf -v sustained_idle_sleep_thr_us %.0f\\n "${sustained_idle_sleep_thr_s}e6" -printf -v reflector_response_deadline_us %.0f\\n "${reflector_response_deadline_s}e6" -bufferbloat_refractory_period_us=$(( 1000*$bufferbloat_refractory_period_ms )) -decay_refractory_period_us=$(( 1000*$decay_refractory_period_ms )) -delay_thr_us=$(( 1000*$delay_thr_ms )) - -for (( i=0; i<${#sss_times_s[@]}; i++ )); -do - printf -v sss_times_us[i] %.0f\\n "${sss_times_s[i]}e6" -done -printf -v sss_compensation_pre_duration_us %.0f\\n "${sss_compensation_pre_duration_ms}e3" -printf -v sss_compensation_post_duration_us %.0f\\n "${sss_compensation_post_duration_ms}e3" - -ping_response_interval_us=$(($reflector_ping_interval_us/$no_pingers)) - -concurrent_read_positive_integer_interval_us=$(($ping_response_interval_us/4)) - -dl_shaper_rate_kbps=$base_dl_shaper_rate_kbps -ul_shaper_rate_kbps=$base_ul_shaper_rate_kbps - -last_dl_shaper_rate_kbps=$dl_shaper_rate_kbps -last_ul_shaper_rate_kbps=$ul_shaper_rate_kbps - -get_max_wire_packet_size_bits $dl_if dl_max_wire_packet_size_bits -get_max_wire_packet_size_bits $ul_if ul_max_wire_packet_size_bits - -set_cake_rate $dl_if $dl_shaper_rate_kbps t_prev_dl_rate_set_us -set_cake_rate $ul_if $ul_shaper_rate_kbps t_prev_ul_rate_set_us - -update_max_wire_packet_compensation - -t_start_us=${EPOCHREALTIME/./} -t_end_us=${EPOCHREALTIME/./} -t_prev_ul_rate_set_us=$t_start_us -t_prev_dl_rate_set_us=$t_start_us -t_ul_last_bufferbloat_us=$t_start_us -t_ul_last_decay_us=$t_start_us -t_dl_last_bufferbloat_us=$t_start_us -t_dl_last_decay_us=$t_start_us - -t_sustained_connection_idle_us=0 - -declare -a delays=( $(for i in {1..$bufferbloat_detection_window}; do echo 0; done) ) -delays_idx=0 -sum_delays=0 - -mkfifo /tmp/CAKE-autorate-${dl_if}/ping_fifo -exec 4<> /tmp/CAKE-autorate-${dl_if}/ping_fifo - -maintain_pingers & -maintain_pingers_pid=$! - -# Initiate achived rate monitor -monitor_achieved_rates $rx_bytes_path $tx_bytes_path $monitor_achieved_rates_interval_us& -monitor_achieved_rates_pid=$! - -prev_timestamp=0 - -if (($debug)); then - if (( $bufferbloat_refractory_period_us <= ($bufferbloat_detection_window*$ping_response_interval_us) )); then - echo "DEBUG Warning: bufferbloat refractory period: " $bufferbloat_refractory_period_us " us." - echo "DEBUG Warning: but expected time to overwrite samples in bufferbloat detection window is: " $(($bufferbloat_detection_window*$ping_response_interval_us)) " us." - echo "DEBUG Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." - fi -fi - -while true -do - while read -t $global_ping_response_timeout_s -r timestamp reflector seq rtt_baseline_us rtt_us rtt_delta_us - do - t_start_us=${EPOCHREALTIME/./} - if ((($t_start_us - 10#"${timestamp//[[\[\].]}")>500000)); then - (($debug)) && echo "DEBUG processed response from [" $reflector "] that is > 500ms old. Skipping." - continue - fi - - # Keep track of number of delays across detection window - (( ${delays[$delays_idx]} )) && ((sum_delays--)) - delays[$delays_idx]=$(( $rtt_delta_us > $compensated_delay_thr_us ? 1 : 0 )) - ((delays[$delays_idx])) && ((sum_delays++)) - (( delays_idx=(delays_idx+1)%$bufferbloat_detection_window )) - - bufferbloat_detected=$(( (($sum_delays>=$bufferbloat_detection_thr)) ? 1 : 0 )) - - get_loads - - classify_load $dl_load_percent $dl_achieved_rate_kbps dl_load_condition - classify_load $ul_load_percent $ul_achieved_rate_kbps ul_load_condition - - dl_load_condition="dl_"$dl_load_condition - ul_load_condition="ul_"$ul_load_condition - - get_next_shaper_rate $min_dl_shaper_rate_kbps $base_dl_shaper_rate_kbps $max_dl_shaper_rate_kbps $dl_achieved_rate_kbps $dl_load_condition $t_start_us t_dl_last_bufferbloat_us t_dl_last_decay_us dl_shaper_rate_kbps - get_next_shaper_rate $min_ul_shaper_rate_kbps $base_ul_shaper_rate_kbps $max_ul_shaper_rate_kbps $ul_achieved_rate_kbps $ul_load_condition $t_start_us t_ul_last_bufferbloat_us t_ul_last_decay_us ul_shaper_rate_kbps - - (($output_processing_stats)) && printf '%s %-6s %-6s %-3s %-3s %s %-15s %-6s %-6s %-6s %-6s %-6s %s %-14s %-14s %-6s %-6s\n' $EPOCHREALTIME $dl_achieved_rate_kbps $ul_achieved_rate_kbps $dl_load_percent $ul_load_percent $timestamp $reflector $seq $rtt_baseline_us $rtt_us $rtt_delta_us $compensated_delay_thr_us $sum_delays $dl_load_condition $ul_load_condition $dl_shaper_rate_kbps $ul_shaper_rate_kbps - - set_shaper_rates - - # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) - if (($enable_sleep_function)); then - if [[ $dl_load_condition == idle* && $ul_load_condition == idle* ]]; then - ((t_sustained_connection_idle_us+=$((${EPOCHREALTIME/./}-$t_end_us)))) - (($t_sustained_connection_idle_us>$sustained_idle_sleep_thr_us)) && break - else - # reset timer - t_sustained_connection_idle_us=0 - fi - fi - t_end_us=${EPOCHREALTIME/./} - - done /dev/null - wait $maintain_pingers_pid - - # reset idle timer - t_sustained_connection_idle_us=0 - - # verify interfaces are up (e.g. following ping response timeout from interfaces going down) - verify_ifs_up - - # wait until load increases again - while true - do - t_start_us=${EPOCHREALTIME/./} - get_loads - (($dl_load_percent>$medium_load_thr_percent || $ul_load_percent>$medium_load_thr_percent)) && break - sleep_remaining_tick_time $t_start_us $reflector_ping_interval_us - done - - # Start up ping processes - maintain_pingers & - maintain_pingers_pid=$! -done diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh new file mode 100755 index 000000000..426c08579 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh @@ -0,0 +1,1790 @@ +#!/bin/bash + +# CAKE-autorate automatically adjusts CAKE bandwidth(s) +# in dependence on: a) receive and transmit transfer rates; and b) latency +# (or can just be used to monitor and log transfer rates and latency) + +# requires packages: bash; and one of the supported ping binaries + +# each cake-autorate instance must be configured using a corresponding config file + +# Project homepage: https://github.com/lynxthecat/cake-autorate +# Licence details: https://github.com/lynxthecat/cake-autorate/blob/master/LICENCE.md + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) + +# Initialize file descriptors +## -1 signifies that the log file fd will not be used and +## that the log file will be written to directly +log_fd=-1 +## ping_fd should be open for the duration of the script +## as it's integral to the operation of the script +exec {ping_fd}<> <(:) || true + +# Bash correctness options +## Disable globbing (expansion of *). +set -f +## Forbid using unset variables. +set -u +## The exit status of a pipeline is the status of the last +## command to exit with a non-zero status, or zero if no +## command exited with a non-zero status. +set -o pipefail + +# Possible performance improvement +export LC_ALL=C + +# Set PREFIX +PREFIX=/root/cake-autorate + +# shellcheck source=cake-autorate_lib.sh +. "${PREFIX}/cake-autorate_lib.sh" +# shellcheck source=cake-autorate_defaults.sh +. "${PREFIX}/cake-autorate_defaults.sh" + +trap cleanup_and_killall INT TERM EXIT + +cleanup_and_killall() +{ + trap true INT TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + log_msg "INFO" "Stopping cake-autorate with PID: ${BASHPID} and config: ${config_path}" + + log_msg "INFO" "Killing all background processes and cleaning up temporary files." + + proc_man_stop maintain_pingers + proc_man_stop monitor_achieved_rates + proc_man_stop maintain_log_file + + [[ -d "${run_path}" ]] && rm -r "${run_path}" + rmdir /var/run/cake-autorate 2>/dev/null + + log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}" + + trap - INT TERM EXIT + exit +} + +log_msg() +{ + # send logging message to terminal, log file fifo, log file and/or system logger + + local type=${1} + local msg=${2} + local instance_id=${instance_id:-"unknown"} + + case ${type} in + + DEBUG) + [[ "${debug}" == "0" ]] && return # skip over DEBUG messages where debug disabled + log_timestamp=${EPOCHREALTIME} + ((log_DEBUG_messages_to_syslog)) && ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" + ;; + + ERROR) + log_timestamp=${EPOCHREALTIME} + ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" + ;; + + SYSLOG) + log_timestamp=${EPOCHREALTIME} + ((use_logger)) && logger -t "cake-autorate.${instance_id}" "INFO: ${log_timestamp} ${msg}" + ;; + + *) + log_timestamp=${EPOCHREALTIME} + ;; + esac + + # Output to the log file fifo if available (for rotation handling) + # else output directly to the log file + if (( log_fd >= 0 )); then + ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >&"${log_fd}" + else + ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >> "${log_file_path}" + fi + + ((terminal)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" +} + +print_headers() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + header="DATA_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; DL_LOAD_PERCENT; UL_LOAD_PERCENT; RTT_TIMESTAMP; REFLECTOR; SEQUENCE; DL_OWD_BASELINE; DL_OWD_US; DL_OWD_DELTA_EWMA_US; DL_OWD_DELTA_US; DL_ADJ_DELAY_THR; UL_OWD_BASELINE; UL_OWD_US; UL_OWD_DELTA_EWMA_US; UL_OWD_DELTA_US; UL_ADJ_DELAY_THR; SUM_DL_DELAYS; SUM_UL_DELAYS; DL_LOAD_CONDITION; UL_LOAD_CONDITION; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" + + header="LOAD_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" + + header="REFLECTOR_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; REFLECTOR; DL_MIN_BASELINE_US; DL_BASELINE_US; DL_BASELINE_DELTA_US; DL_BASELINE_DELTA_THR_US; DL_MIN_DELTA_EWMA_US; DL_DELTA_EWMA_US; DL_DELTA_EWMA_DELTA_US; DL_DELTA_EWMA_DELTA_THR; UL_MIN_BASELINE_US; UL_BASELINE_US; UL_BASELINE_DELTA_US; UL_BASELINE_DELTA_THR_US; UL_MIN_DELTA_EWMA_US; UL_DELTA_EWMA_US; UL_DELTA_EWMA_DELTA_US; UL_DELTA_EWMA_DELTA_THR" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" +} + +# MAINTAIN_LOG_FILE + HELPER FUNCTIONS + +rotate_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + if [[ -f ${log_file_path} ]] + then + cat "${log_file_path}" > "${log_file_path}.old" + true > "${log_file_path}" + fi + ((output_processing_stats)) && print_headers +} + +generate_log_file_exporter() +{ + cat > "${run_path}/export_log_file" <<- EOT + #!/bin/bash + + . "${PREFIX}/cake-autorate_lib.sh" + PROC_STATE_FILE="${run_path}/proc_state" + PROC_STATE_FILE_LOCK="${run_path}/proc_state.lock" + + timeout_s=\${1:-20} + + if ! proc_man_signal maintain_log_file "USR1" + then + printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 + exit 1 + fi + rm -f "${run_path}/last_log_file_export" + + read_try=0 + + while [[ ! -f "${run_path}/last_log_file_export" ]] + do + sleep 1 + if (( ++read_try >= \${timeout_s} )); then + printf "ERROR: Timeout (\${timeout_s}s) reached before new log file export identified.\n" >&2 + exit 1 + fi + done + + read -r log_file_export_path < "${run_path}/last_log_file_export" + + printf "Log file export complete.\n" + + printf "Log file available at location: " + printf "\${log_file_export_path}\n" + EOT + + chmod +x "${run_path}/export_log_file" +} + +export_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + printf -v log_file_export_datetime '%(%Y_%m_%d_%H_%M_%S)T' + log_file_export_path="${log_file_path/.log/_${log_file_export_datetime}.log}" + log_msg "DEBUG" "Exporting log file with path: ${log_file_path/.log/_${log_file_export_datetime}.log}" + + # Now export with or without compression to the appropriate export path + if ((log_file_export_compress)); then + log_file_export_path="${log_file_export_path}.gz" + if [[ -f "${log_file_path}.old" ]]; then + gzip -c "${log_file_path}.old" > "${log_file_export_path}" + gzip -c "${log_file_path}" >> "${log_file_export_path}" + else + gzip -c "${log_file_path}" > "${log_file_export_path}" + fi + else + if [[ -f "${log_file_path}.old" ]]; then + cp "${log_file_path}.old" "${log_file_export_path}" + cat "${log_file_path}" >> "${log_file_export_path}" + else + cp "${log_file_path}" "${log_file_export_path}" + fi + fi + + printf '%s' "${log_file_export_path}" > "${run_path}/last_log_file_export" +} + +flush_log_fd() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + while read -r -t 0.01 -u "${log_fd}" log_line + do + printf '%s\n' "${log_line}" >> "${log_file_path}" + done +} + +get_log_file_size_bytes() +{ + log_file_size_bytes=$(wc -c "${log_file_path}" 2>/dev/null | awk '{print $1}') + log_file_size_bytes=${log_file_size_bytes:-0} +} + +kill_maintain_log_file() +{ + trap - TERM EXIT + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + flush_log_fd + exit +} + +maintain_log_file() +{ + trap '' INT + trap 'kill_maintain_log_file' TERM EXIT + trap 'export_log_file' USR1 + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + t_log_file_start_us=${EPOCHREALTIME/./} + + get_log_file_size_bytes + + while true + do + while read -r -u "${log_fd}" log_line + do + + printf '%s\n' "${log_line}" >> "${log_file_path}" + + # Verify log file size < configured maximum + # The following two lines with costly call to 'du': + # read log_file_size_bytes< <(du -b ${log_file_path}/cake-autorate.log) + # log_file_size_bytes=${log_file_size_bytes//[!0-9]/} + # can be more efficiently handled with this line: + ((log_file_size_bytes=log_file_size_bytes+${#log_line}+1)) + + # Verify log file time < configured maximum + if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )); then + + log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so rotating log file" + break + fi + + if (( log_file_size_bytes > log_file_max_size_bytes )); then + + log_file_size_KB=$((log_file_size_bytes/1024)) + log_msg "DEBUG" "log file size: ${log_file_size_KB} KB has exceeded configured maximum: ${log_file_max_size_KB} KB so rotating log file" + break + fi + + done + + flush_log_fd + rotate_log_file + t_log_file_start_us=${EPOCHREALTIME/./} + get_log_file_size_bytes + + done +} + +get_next_shaper_rate() +{ + local min_shaper_rate_kbps=${1} + local base_shaper_rate_kbps=${2} + local max_shaper_rate_kbps=${3} + local achieved_rate_kbps=${4} + local load_condition=${5} + local t_next_rate_us=${6} + local -n t_last_bufferbloat_us=${7} + local -n t_last_decay_us=${8} + local -n shaper_rate_kbps=${9} + + case ${load_condition} in + + # upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period + ul*sss) + shaper_rate_kbps=${min_shaper_rate_kbps} + ;; + # download Starlink satelite switching compensation, so drop down to base rate for download through switching period + dl*sss) + shaper_rate_kbps=$(( shaper_rate_kbps > base_shaper_rate_kbps ? base_shaper_rate_kbps : shaper_rate_kbps )) + ;; + # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period + *bb*) + if (( t_next_rate_us > (t_last_bufferbloat_us+bufferbloat_refractory_period_us) )); then + adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps*achieved_rate_adjust_down_bufferbloat)/1000 )) + adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_down_bufferbloat)/1000 )) + shaper_rate_kbps=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) + t_last_bufferbloat_us=${EPOCHREALTIME/./} + fi + ;; + # high load, so increase rate providing not inside bufferbloat refractory period + *high*) + if (( t_next_rate_us > (t_last_bufferbloat_us+bufferbloat_refractory_period_us) )); then + shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_up_load_high)/1000 )) + fi + ;; + # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate + *low*|*idle*) + if (( t_next_rate_us > (t_last_decay_us+decay_refractory_period_us) )); then + + if ((shaper_rate_kbps > base_shaper_rate_kbps)); then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_down_load_low)/1000 )) + shaper_rate_kbps=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps ? decayed_shaper_rate_kbps : base_shaper_rate_kbps)) + elif ((shaper_rate_kbps < base_shaper_rate_kbps)); then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_up_load_low)/1000 )) + shaper_rate_kbps=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps ? decayed_shaper_rate_kbps : base_shaper_rate_kbps)) + fi + + t_last_decay_us=${EPOCHREALTIME/./} + fi + ;; + *) + log_msg "ERROR" "unknown load condition: ${load_condition} in get_next_shaper_rate" + exit 1 + ;; + esac + # make sure to only return rates between cur_min_rate and cur_max_rate + ((shaper_rate_kbps < min_shaper_rate_kbps)) && shaper_rate_kbps=${min_shaper_rate_kbps} + ((shaper_rate_kbps > max_shaper_rate_kbps)) && shaper_rate_kbps=${max_shaper_rate_kbps} +} + +monitor_achieved_rates() +{ + trap '' INT + + # track rx and tx bytes transfered and divide by time since last update + # to determine achieved dl and ul transfer rates + + local rx_bytes_path=${1} + local tx_bytes_path=${2} + local monitor_achieved_rates_interval_us=${3} # (microseconds) + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + compensated_monitor_achieved_rates_interval_us=${monitor_achieved_rates_interval_us} + + [[ -f "${rx_bytes_path}" ]] && { read -r prev_rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || prev_rx_bytes=0 + [[ -f "${tx_bytes_path}" ]] && { read -r prev_tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || prev_tx_bytes=0 + + while true + do + t_start_us=${EPOCHREALTIME/./} + + # If rx/tx bytes file exists, read it in, otherwise set to prev_bytes + # This addresses interfaces going down and back up + [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes=${prev_rx_bytes} + [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes=${prev_tx_bytes} + + dl_achieved_rate_kbps=$(( ((8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) + ul_achieved_rate_kbps=$(( ((8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) + + ((dl_achieved_rate_kbps<0)) && dl_achieved_rate_kbps=0 + ((ul_achieved_rate_kbps<0)) && ul_achieved_rate_kbps=0 + + printf '%s' "${dl_achieved_rate_kbps}" > "${run_path}/dl_achieved_rate_kbps" + printf '%s' "${ul_achieved_rate_kbps}" > "${run_path}/ul_achieved_rate_kbps" + + if ((output_load_stats)); then + + concurrent_read_integer dl_shaper_rate_kbps "${run_path}/dl_shaper_rate_kbps" + concurrent_read_integer ul_shaper_rate_kbps "${run_path}/ul_shaper_rate_kbps" + printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${dl_achieved_rate_kbps}" "${ul_achieved_rate_kbps}" "${dl_shaper_rate_kbps}" "${ul_shaper_rate_kbps}" + log_msg "LOAD" "${load_stats}" + fi + + prev_rx_bytes=${rx_bytes} + prev_tx_bytes=${tx_bytes} + + # read in the max_wire_packet_rtt_us + concurrent_read_integer max_wire_packet_rtt_us "${run_path}/max_wire_packet_rtt_us" + + compensated_monitor_achieved_rates_interval_us=$(( ((monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) )) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) + + sleep_remaining_tick_time "${t_start_us}" "${compensated_monitor_achieved_rates_interval_us}" + done +} + +get_loads() +{ + # read in the dl/ul achieved rates and determine the loads + + concurrent_read_integer dl_achieved_rate_kbps "${run_path}/dl_achieved_rate_kbps" + concurrent_read_integer ul_achieved_rate_kbps "${run_path}/ul_achieved_rate_kbps" + + dl_load_percent=$(( (100*dl_achieved_rate_kbps)/dl_shaper_rate_kbps )) + ul_load_percent=$(( (100*ul_achieved_rate_kbps)/ul_shaper_rate_kbps )) + + printf '%s' "${dl_load_percent}" > "${run_path}/dl_load_percent" + printf '%s' "${ul_load_percent}" > "${run_path}/ul_load_percent" +} + +classify_load() +{ + # classify the load according to high/low/idle and add _delayed if delayed + # thus ending up with high_delayed, low_delayed, etc. + local load_percent=${1} + local achieved_rate_kbps=${2} + local bufferbloat_detected=${3} + local -n load_condition=${4} + + if (( load_percent > high_load_thr_percent )); then + load_condition="high" + elif (( achieved_rate_kbps > connection_active_thr_kbps )); then + load_condition="low" + else + load_condition="idle" + fi + + ((bufferbloat_detected)) && load_condition=${load_condition}"_bb" + + if ((sss_compensation)); then + # shellcheck disable=SC2154 + for sss_time_us in "${sss_times_us[@]}" + do + ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) + if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )); then + load_condition=${load_condition}"_sss" + break + fi + done + fi +} + +# MAINTAIN PINGERS + ASSOCIATED HELPER FUNCTIONS + +# TSPING FUNCTIONS # + +kill_monitor_reflector_responses_tsping() +{ + trap - TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + # Store baselines and ewmas to files ready for next instance (e.g. after sleep) + for (( reflector=0; reflector "${run_path}/reflector_${reflectors[reflector]//./-}_dl_baseline_us" + [[ -n "${ul_owd_baselines_us[${reflectors[reflector]}]}" ]] && printf '%s' "${ul_owd_baselines_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_ul_baseline_us" + [[ -n "${dl_owd_delta_ewmas_us[${reflectors[reflector]}]}" ]] && printf '%s' "${dl_owd_delta_ewmas_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_dl_delta_ewma_us" + [[ -n "${ul_owd_delta_ewmas_us[${reflectors[reflector]}]}" ]] && printf '%s' "${ul_owd_delta_ewmas_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_ul_delta_ewma_us" + done + + exit +} + +monitor_reflector_responses_tsping() +{ + trap '' INT + trap kill_monitor_reflector_responses_tsping TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + t_start_us=${EPOCHREALTIME/./} + + # Read in baselines if they exist, else just set them to 1s (rapidly converges downwards on new OWDs) + for (( reflector=0; reflector < no_reflectors; reflector++ )) + do + if [[ -f "${run_path}/reflector_${reflectors[reflector]//./-}_dl_baseline_us" ]]; then + read -r "dl_owd_baselines_us[${reflectors[reflector]}]" < "${run_path}/reflector_${reflectors[reflector]//./-}_dl_baseline_us" + else + dl_owd_baselines_us[${reflectors[reflector]}]=100000 + fi + if [[ -f "${run_path}/reflector_${reflectors[reflector]//./-}_ul_baseline_us" ]]; then + read -r "ul_owd_baselines_us[${reflectors[reflector]}]" < "${run_path}/reflector_${reflectors[reflector]//./-}_ul_baseline_us" + else + ul_owd_baselines_us[${reflectors[reflector]}]=100000 + fi + if [[ -f "${run_path}/reflector_${reflectors[reflector]//./-}_dl_delta_ewma_us" ]]; then + read -r "dl_owd_delta_ewmas_us[${reflectors[reflector]}]" < "${run_path}/reflector_${reflectors[reflector]//./-}_dl_delta_ewma_us" + else + dl_owd_delta_ewmas_us[${reflectors[reflector]}]=0 + fi + if [[ -f "${run_path}/reflector_${reflectors[reflector]//./-}_ul_delta_ewma_us" ]]; then + read -r "ul_owd_delta_ewmas_us[${reflectors[reflector]}]" < "${run_path}/reflector_${reflectors[reflector]//./-}_ul_delta_ewma_us" + else + ul_owd_delta_ewmas_us[${reflectors[reflector]}]=0 + fi + done + + # shellcheck disable=SC2154 + while read -r -u "${pinger_fds[pinger]}" timestamp reflector seq _ _ _ _ _ dl_owd_ms ul_owd_ms + do + t_start_us=${EPOCHREALTIME/./} + + dl_owd_us=${dl_owd_ms}000 + ul_owd_us=${ul_owd_ms}000 + + dl_alpha=$(( (( dl_owd_us >= dl_owd_baselines_us[${reflector}] )) ? alpha_baseline_increase : alpha_baseline_decrease )) + ul_alpha=$(( (( ul_owd_us >= ul_owd_baselines_us[${reflector}] )) ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ewma_iteration "${ul_owd_us}" "${ul_alpha}" "ul_owd_baselines_us[${reflector}]" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us=$(( ul_owd_us - ul_owd_baselines_us[${reflector}] )) + + concurrent_read_integer dl_load_percent "${run_path}/dl_load_percent" + concurrent_read_integer ul_load_percent "${run_path}/ul_load_percent" + + if (( dl_load_percent < high_load_thr_percent && ul_load_percent < high_load_thr_percent)); then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ewma_iteration "${ul_owd_delta_us}" "${alpha_delta_ewma}" "ul_owd_delta_ewmas_us[${reflector}]" + fi + + timestamp=${timestamp//[\[\]]}0 + + printf '%s %s %s %s %s %s %s %s %s %s %s\n' "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${ping_fd}" + + timestamp_us=${timestamp//[.]} + + printf '%s' "${timestamp_us}" > "${run_path}/reflector_${reflector//./-}_last_timestamp_us" + + printf '%s' "${dl_owd_baselines_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_dl_owd_baseline_us" + printf '%s' "${ul_owd_baselines_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_ul_owd_baseline_us" + + printf '%s' "${dl_owd_delta_ewmas_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_dl_owd_delta_ewma_us" + printf '%s' "${ul_owd_delta_ewmas_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_ul_owd_delta_ewma_us" + + printf '%s' "${timestamp_us}" > "${run_path}/reflectors_last_timestamp_us" + + done +} + +# FPING FUNCTIONS # + +kill_monitor_reflector_responses_fping() +{ + trap - TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + # Store baselines and ewmas to files ready for next instance (e.g. after sleep) + for (( reflector=0; reflector "${run_path}/reflector_${reflectors[reflector]//./-}_baseline_us" + [[ -n "${rtt_delta_ewmas_us[${reflectors[reflector]}]}" ]] && printf '%s' "${rtt_delta_ewmas_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_delta_ewma_us" + done + + exit +} + +monitor_reflector_responses_fping() +{ + trap '' INT + trap kill_monitor_reflector_responses_fping TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A rtt_baselines_us + declare -A rtt_delta_ewmas_us + + t_start_us=${EPOCHREALTIME/./} + + # Read in baselines if they exist, else just set them to 1s (rapidly converges downwards on new RTTs) + for (( reflector=0; reflector < no_reflectors; reflector++ )) + do + if [[ -f "${run_path}/reflector_${reflectors[reflector]//./-}_baseline_us" ]]; then + read -r "rtt_baselines_us[${reflectors[reflector]}]" < "${run_path}/reflector_${reflectors[reflector]//./-}_baseline_us" + else + rtt_baselines_us[${reflectors[reflector]}]=100000 + fi + if [[ -f "${run_path}/reflector_${reflectors[reflector]//./-}_delta_ewma_us" ]]; then + read -r "rtt_delta_ewmas_us[${reflectors[reflector]}]" < "${run_path}/reflector_${reflectors[reflector]//./-}_delta_ewma_us" + else + rtt_delta_ewmas_us[${reflectors[reflector]}]=0 + fi + done + + # shellcheck disable=SC2154 + while read -r -u "${pinger_fds[pinger]}" timestamp reflector _ seq_rtt 2>/dev/null + do + t_start_us=${EPOCHREALTIME/./} + + [[ ${seq_rtt} =~ \[([0-9]+)\].*[[:space:]]([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + + seq=${BASH_REMATCH[1]} + + rtt_us=${BASH_REMATCH[3]}000 + rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + + alpha=$(( (( rtt_us >= rtt_baselines_us[${reflector}] )) ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${rtt_us}" "${alpha}" "rtt_baselines_us[${reflector}]" + + rtt_delta_us=$(( rtt_us-rtt_baselines_us[${reflector}] )) + + concurrent_read_integer dl_load_percent "${run_path}/dl_load_percent" + concurrent_read_integer ul_load_percent "${run_path}/ul_load_percent" + + if (( dl_load_percent < high_load_thr_percent && ul_load_percent < high_load_thr_percent)); then + ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" "rtt_delta_ewmas_us[${reflector}]" + fi + + dl_owd_baseline_us=$((rtt_baselines_us[${reflector}]/2)) + ul_owd_baseline_us=${dl_owd_baseline_us} + + dl_owd_delta_ewma_us=$((rtt_delta_ewmas_us[${reflector}]/2)) + ul_owd_delta_ewma_us=${dl_owd_delta_ewma_us} + + dl_owd_us=$((rtt_us/2)) + ul_owd_us=${dl_owd_us} + + dl_owd_delta_us=$((rtt_delta_us/2)) + ul_owd_delta_us=${dl_owd_delta_us} + + timestamp=${timestamp//[\[\]]}0 + + printf '%s %s %s %s %s %s %s %s %s %s %s\n' "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${ping_fd}" + + timestamp_us=${timestamp//[.]} + + printf '%s' "${timestamp_us}" > "${run_path}/reflector_${reflector//./-}_last_timestamp_us" + + printf '%s' "${dl_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_baseline_us" + printf '%s' "${ul_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_baseline_us" + + printf '%s' "${dl_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_delta_ewma_us" + printf '%s' "${ul_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_delta_ewma_us" + + printf '%s' "${timestamp_us}" > "${run_path}/reflectors_last_timestamp_us" + + done 2>/dev/null +} + +# IPUTILS-PING FUNCTIONS + +kill_monitor_reflector_responses_ping() +{ + trap - TERM EXIT + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + [[ -n "${rtt_baseline_us:-}" ]] && printf '%s' "${rtt_baseline_us}" > "${run_path}/reflector_${reflectors[pinger]//./-}_baseline_us" + [[ -n "${rtt_delta_ewma_us:-}" ]] && printf '%s' "${rtt_delta_ewma_us}" > "${run_path}/reflector_${reflectors[pinger]//./-}_delta_ewma_us" + exit +} + +monitor_reflector_responses_ping() +{ + trap '' INT + trap kill_monitor_reflector_responses_ping TERM EXIT + + # ping reflector, maintain baseline and output deltas to a common fifo + + local pinger=${1} + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + if [[ -f "${run_path}/reflector_${reflectors[pinger]//./-}_baseline_us" ]]; then + read -r rtt_baseline_us < "${run_path}/reflector_${reflectors[pinger]//./-}_baseline_us" + else + rtt_baseline_us=100000 + fi + + if [[ -f "${run_path}/reflector_${reflectors[pinger]//./-}_delta_ewma_us" ]]; then + read -r rtt_delta_ewma_us < "${run_path}/reflector_${reflectors[pinger]//./-}_delta_ewma_us" + else + rtt_delta_ewma_us=0 + fi + + while read -r -u "${pinger_fds[pinger]}" timestamp _ _ _ reflector seq_rtt 2>/dev/null + do + # If no match then skip onto the next one + [[ ${seq_rtt} =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + + seq=${BASH_REMATCH[1]} + + rtt_us=${BASH_REMATCH[3]}000 + rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + + reflector=${reflector//:/} + + alpha=$(( (( rtt_us >= rtt_baseline_us )) ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${rtt_us}" "${alpha}" rtt_baseline_us + + rtt_delta_us=$(( rtt_us-rtt_baseline_us )) + + concurrent_read_integer dl_load_percent "${run_path}/dl_load_percent" + concurrent_read_integer ul_load_percent "${run_path}/ul_load_percent" + + if (( dl_load_percent < high_load_thr_percent && ul_load_percent < high_load_thr_percent )); then + ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" rtt_delta_ewma_us + fi + + dl_owd_baseline_us=$((rtt_baseline_us/2)) + ul_owd_baseline_us=${dl_owd_baseline_us} + + dl_owd_delta_ewma_us=$((rtt_delta_ewma_us/2)) + ul_owd_delta_ewma_us=${dl_owd_delta_ewma_us} + + dl_owd_us=$((rtt_us/2)) + ul_owd_us=${dl_owd_us} + + dl_owd_delta_us=$((rtt_delta_us/2)) + ul_owd_delta_us=${dl_owd_delta_us} + + timestamp=${timestamp//[\[\]]} + + printf '%s %s %s %s %s %s %s %s %s %s %s\n' "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${ping_fd}" + + timestamp_us=${timestamp//[.]} + + printf '%s' "${timestamp_us}" > "${run_path}/reflector_${reflector//./-}_last_timestamp_us" + + printf '%s' "${dl_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_baseline_us" + printf '%s' "${ul_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_baseline_us" + + printf '%s' "${dl_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_delta_ewma_us" + printf '%s' "${ul_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_delta_ewma_us" + + printf '%s' "${timestamp_us}" > "${run_path}/reflectors_last_timestamp_us" + + done 2>/dev/null +} + +# END OF IPUTILS-PING FUNCTIONS + +# GENERIC PINGER START AND STOP FUNCTIONS + +start_pinger() +{ + local pinger=${1} + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + # shellcheck disable=SC1083,SC2086,SC2261 + case ${pinger_binary} in + + tsping) + pinger=0 + exec {pinger_fds[pinger]}<> <(:) || true + proc_man_start "pinger_${pinger}" ${ping_prefix_string} tsping ${ping_extra_args} --print-timestamps --machine-readable=' ' --sleep-time "0" --target-spacing "${ping_response_interval_ms}" "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${pinger_fds[pinger]}" + ;; + fping) + pinger=0 + exec {pinger_fds[pinger]}<> <(:) || true + proc_man_start "pinger_${pinger}" ${ping_prefix_string} fping ${ping_extra_args} --timestamp --loop --period "${reflector_ping_interval_ms}" --interval "${ping_response_interval_ms}" --timeout 10000 "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${pinger_fds[pinger]}" + ;; + ping) + exec {pinger_fds[pinger]}<> <(:) || true + sleep_until_next_pinger_time_slot "${pinger}" + proc_man_start "pinger_${pinger}" ${ping_prefix_string} ping ${ping_extra_args} -D -i "${reflector_ping_interval_s}" "${reflectors[pinger]}" 2> /dev/null >&"${pinger_fds[pinger]}" + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + exit 1 + ;; + esac + + proc_man_start "monitor_${pinger}" "monitor_reflector_responses_${pinger_binary}" "${pinger}" +} + +start_pingers() +{ + # Initiate pingers + log_msg "DEBUG" "Starting pingers." + case ${pinger_binary} in + + tsping|fping) + start_pinger 0 + ;; + ping) + for ((pinger=0; pinger < no_pingers; pinger++)) + do + start_pinger "${pinger}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + exit 1 + ;; + esac +} + +sleep_until_next_pinger_time_slot() +{ + # wait until next pinger time slot and start pinger in its slot + # this allows pingers to be stopped and started (e.g. during sleep or reflector rotation) + # whilst ensuring pings will remain spaced out appropriately to maintain granularity + + local pinger=${1} + + t_start_us=${EPOCHREALTIME/./} + time_to_next_time_slot_us=$(( (reflector_ping_interval_us-(t_start_us-pingers_t_start_us)%reflector_ping_interval_us) + pinger*ping_response_interval_us )) + sleep_remaining_tick_time "${t_start_us}" "${time_to_next_time_slot_us}" +} + +kill_pinger() +{ + local pinger=${1} + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case ${pinger_binary} in + tsping|fping) + pinger=0 + ;; + + *) + : + ;; + esac + + proc_man_stop "pinger_${pinger}" + proc_man_stop "monitor_${pinger}" + + # shellcheck disable=SC1083 + exec {pinger_fds[pinger]}<&- +} + +kill_pingers() +{ + case ${pinger_binary} in + + tsping|fping) + log_msg "DEBUG" "Killing ${pinger_binary} instance." + kill_pinger 0 + ;; + ping) + for (( pinger=0; pinger < no_pingers; pinger++)) + do + log_msg "DEBUG" "Killing pinger instance: ${pinger}" + kill_pinger "${pinger}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + exit 1 + ;; + esac +} + +replace_pinger_reflector() +{ + # pingers always use reflectors[0]..[no_pingers-1] as the initial set + # and the additional reflectors are spare reflectors should any from initial set go stale + # a bad reflector in the initial set is replaced with ${reflectors[no_pingers]} + # ${reflectors[no_pingers]} is then unset + # and the the bad reflector moved to the back of the queue (last element in ${reflectors[]}) + # and finally the indices for ${reflectors} are updated to reflect the new order + + local pinger=${1} + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + lock "${run_path}/replace_pinger_reflector_lock" + + if ((no_reflectors > no_pingers)); then + log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}." + kill_pinger "${pinger}" + bad_reflector=${reflectors[pinger]} + # overwrite the bad reflector with the reflector that is next in the queue (the one after 0..${no_pingers}-1) + reflectors[pinger]=${reflectors[no_pingers]} + # remove the new reflector from the list of additional reflectors beginning from ${reflectors[no_pingers]} + unset "reflectors[no_pingers]" + # bad reflector goes to the back of the queue + reflectors+=("${bad_reflector}") + # reset array indices + mapfile -t reflectors < <(for i in "${reflectors[@]}"; do printf '%s\n' "${i}"; done) + # set up the new pinger with the new reflector and retain pid + start_pinger "${pinger}" + else + log_msg "DEBUG" "No additional reflectors specified so just retaining: ${reflectors[pinger]}." + reflector_offences[pinger]=0 + fi + + unlock "${run_path}/replace_pinger_reflector_lock" +} + +# END OF GENERIC PINGER START AND STOP FUNCTIONS + +kill_maintain_pingers() +{ + trap - TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + lock "${run_path}/replace_pinger_reflector_lock" + + log_msg "DEBUG" "Terminating maintain_pingers." + + kill_pingers + + unlock "${run_path}/replace_pinger_reflector_lock" + + exit +} + +change_state_maintain_pingers() +{ + local maintain_pingers_next_state=${1:-unset} + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + if [[ "${maintain_pingers_next_state}" == "unset" ]]; then + if [[ -f "${run_path}/maintain_pingers_next_state" ]]; then + for ((read_try=1; read_try<11; read_try++)) + do + read -r maintain_pingers_next_state < "${run_path}/maintain_pingers_next_state" + maintain_pingers_next_state=${maintain_pingers_next_state:-unset} + [[ "${maintain_pingers_next_state}" != "unset" ]] && break + done + else + log_msg "ERROR" "Received change signal but ${run_path}/maintain_pingers_next_state does not exist. Exiting now." + kill -INT $$ + fi + fi + + case ${maintain_pingers_next_state} in + + START|STOP|PAUSED|RUNNING) + + if [[ "${maintain_pingers_state}" != "${maintain_pingers_next_state}" ]] + then + log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" + maintain_pingers_state=${maintain_pingers_next_state} + printf "%s" ${maintain_pingers_state} > ${run_path}/maintain_pingers_state + else + log_msg "ERROR" "Received request to change maintain_pingers state to existing state." + fi + ;; + + *) + + log_msg "ERROR" "Received unrecognized state change request: ${maintain_pingers_next_state}. Exiting now." + kill -INT $$ + ;; + esac +} + +maintain_pingers() +{ + # this initiates the pingers and monitors reflector health, rotating reflectors as necessary + + trap '' INT + trap 'kill_maintain_pingers' TERM EXIT + + trap 'change_state_maintain_pingers' USR1 + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + err_silence=0 + reflector_offences_idx=0 + pingers_active=0 + + pingers_t_start_us=${EPOCHREALTIME/./} + t_last_reflector_replacement_us=${EPOCHREALTIME/./} + t_last_reflector_comparison_us=${EPOCHREALTIME/./} + + for ((reflector=0; reflector < no_reflectors; reflector++)) + do + printf '%s' "${pingers_t_start_us}" > "${run_path}/reflector_${reflectors[reflector]//./-}_last_timestamp_us" + done + + printf '%s' "${pingers_t_start_us}" > "${run_path}/reflectors_last_timestamp_us" + + # For each pinger initialize record of offences + for ((pinger=0; pinger < no_pingers; pinger++)) + do + # shellcheck disable=SC2178 + declare -n reflector_offences="reflector_${pinger}_offences" + for ((i=0; i(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000))); then + + log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." + replace_pinger_reflector $((RANDOM%no_pingers)) + t_last_reflector_replacement_us=${EPOCHREALTIME/./} + continue + fi + + if (( ${EPOCHREALTIME/./}>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then + + t_last_reflector_comparison_us=${EPOCHREALTIME/./} + + concurrent_read_integer dl_min_owd_baseline_us "${run_path}/reflector_${reflectors[0]//./-}_dl_owd_baseline_us" 0 || continue + concurrent_read_integer dl_min_owd_delta_ewma_us "${run_path}/reflector_${reflectors[0]//./-}_dl_owd_delta_ewma_us" 0 || continue + concurrent_read_integer ul_min_owd_baseline_us "${run_path}/reflector_${reflectors[0]//./-}_ul_owd_baseline_us" 0 || continue + concurrent_read_integer ul_min_owd_delta_ewma_us "${run_path}/reflector_${reflectors[0]//./-}_ul_owd_delta_ewma_us" 0 || continue + + concurrent_read_integer compensated_dl_delay_thr_us "${run_path}/compensated_dl_delay_thr_us" + concurrent_read_integer compensated_ul_delay_thr_us "${run_path}/compensated_ul_delay_thr_us" + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + concurrent_read_integer "dl_owd_baselines_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_dl_owd_baseline_us" 0 || continue 2 + concurrent_read_integer "dl_owd_delta_ewmas_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_dl_owd_delta_ewma_us" 0 || continue 2 + concurrent_read_integer "ul_owd_baselines_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_ul_owd_baseline_us" 0 || continue 2 + concurrent_read_integer "ul_owd_delta_ewmas_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_ul_owd_delta_ewma_us" 0 || continue 2 + + (( dl_owd_baselines_us[${reflectors[pinger]}] < dl_min_owd_baseline_us )) && dl_min_owd_baseline_us="${dl_owd_baselines_us[${reflectors[pinger]}]}" + (( dl_owd_delta_ewmas_us[${reflectors[pinger]}] < dl_min_owd_delta_ewma_us )) && dl_min_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" + (( ul_owd_baselines_us[${reflectors[pinger]}] < ul_min_owd_baseline_us )) && ul_min_owd_baseline_us="${ul_owd_baselines_us[${reflectors[pinger]}]}" + (( ul_owd_delta_ewmas_us[${reflectors[pinger]}] < ul_min_owd_delta_ewma_us )) && ul_min_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" + done + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + + dl_owd_baseline_delta_us=$(( dl_owd_baselines_us[${reflectors[pinger]}] - dl_min_owd_baseline_us )) + dl_owd_delta_ewma_delta_us=$(( dl_owd_delta_ewmas_us[${reflectors[pinger]}] - dl_min_owd_delta_ewma_us )) + ul_owd_baseline_delta_us=$(( ul_owd_baselines_us[${reflectors[pinger]}] - ul_min_owd_baseline_us )) + ul_owd_delta_ewma_delta_us=$(( ul_owd_delta_ewmas_us[${reflectors[pinger]}] - ul_min_owd_delta_ewma_us )) + + if ((output_reflector_stats)); then + printf -v reflector_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${reflectors[pinger]}" "${dl_min_owd_baseline_us}" "${dl_owd_baselines_us[${reflectors[pinger]}]}" "${dl_owd_baseline_delta_us}" "${reflector_owd_baseline_delta_thr_us}" "${dl_min_owd_delta_ewma_us}" "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${dl_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" "${ul_min_owd_baseline_us}" "${ul_owd_baselines_us[${reflectors[pinger]}]}" "${ul_owd_baseline_delta_us}" "${reflector_owd_baseline_delta_thr_us}" "${ul_min_owd_delta_ewma_us}" "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${ul_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" + log_msg "REFLECTOR" "${reflector_stats}" + fi + + if (( dl_owd_baseline_delta_us > reflector_owd_baseline_delta_thr_us )); then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} dl_owd_baseline_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + + if (( dl_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )); then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} dl_owd_delta_ewma_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + + if (( ul_owd_baseline_delta_us > reflector_owd_baseline_delta_thr_us )); then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} ul_owd_baseline_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + + if (( ul_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )); then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} ul_owd_delta_ewma_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + done + + fi + + enable_replace_pinger_reflector=1 + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + reflector_check_time_us=${EPOCHREALTIME/./} + concurrent_read_integer reflector_last_timestamp_us "${run_path}/reflector_${reflectors[pinger]//./-}_last_timestamp_us" + # shellcheck disable=SC2178 + declare -n reflector_offences="reflector_${pinger}_offences" + + (( reflector_offences[reflector_offences_idx] )) && ((sum_reflector_offences[pinger]--)) + # shellcheck disable=SC2154 + reflector_offences[reflector_offences_idx]=$(( (((reflector_check_time_us-reflector_last_timestamp_us) > reflector_response_deadline_us)) ? 1 : 0 )) + + if (( reflector_offences[reflector_offences_idx] )); then + ((sum_reflector_offences[pinger]++)) + log_msg "DEBUG" "no ping response from reflector: ${reflectors[pinger]} within reflector_response_deadline: ${reflector_response_deadline_s}s" + log_msg "DEBUG" "reflector=${reflectors[pinger]}, sum_reflector_offences=${sum_reflector_offences[pinger]} and reflector_misbehaving_detection_thr=${reflector_misbehaving_detection_thr}" + fi + + if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )); then + + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving." + if ((enable_replace_pinger_reflector)); then + replace_pinger_reflector "${pinger}" + for ((i=0; i /dev/null + fi + + else + ((output_cake_changes)) && log_msg "DEBUG" "adjust_shaper_rate set to 0 in config, so skipping the tc qdisc change call" + fi +} + +set_shaper_rates() +{ + if (( dl_shaper_rate_kbps != last_dl_shaper_rate_kbps || ul_shaper_rate_kbps != last_ul_shaper_rate_kbps )); then + + # fire up tc in each direction if there are rates to change, and if rates change in either direction then update max wire calcs + if (( dl_shaper_rate_kbps != last_dl_shaper_rate_kbps )); then + set_cake_rate "${dl_if}" "${dl_shaper_rate_kbps}" adjust_dl_shaper_rate + printf '%s' "${dl_shaper_rate_kbps}" > "${run_path}/dl_shaper_rate_kbps" + last_dl_shaper_rate_kbps=${dl_shaper_rate_kbps} + fi + if (( ul_shaper_rate_kbps != last_ul_shaper_rate_kbps )); then + set_cake_rate "${ul_if}" "${ul_shaper_rate_kbps}" adjust_ul_shaper_rate + printf '%s' "${ul_shaper_rate_kbps}" > "${run_path}/ul_shaper_rate_kbps" + last_ul_shaper_rate_kbps=${ul_shaper_rate_kbps} + fi + + update_max_wire_packet_compensation + fi +} + +set_min_shaper_rates() +{ + log_msg "DEBUG" "Enforcing minimum shaper rates." + dl_shaper_rate_kbps=${min_dl_shaper_rate_kbps} + ul_shaper_rate_kbps=${min_ul_shaper_rate_kbps} + set_shaper_rates +} + +get_max_wire_packet_size_bits() +{ + local interface=${1} + local -n max_wire_packet_size_bits=${2} + + read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" + [[ $(tc qdisc show dev "${interface}" || true) =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] + [[ -n "${BASH_REMATCH[2]:-}" ]] && max_wire_packet_size_bits=$(( 8*(max_wire_packet_size_bits+BASH_REMATCH[2]) )) + # atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits + [[ "${BASH_REMATCH[1]:-}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*((max_wire_packet_size_bits+376)/384) )) +} + +update_max_wire_packet_compensation() +{ + # Compensate for delays imposed by active traffic shaper + # This will serve to increase the delay thr at rates below around 12Mbit/s + + # compensated OWD delay thresholds in microseconds + compensated_dl_delay_thr_us=$(( dl_delay_thr_us + (1000*dl_max_wire_packet_size_bits)/dl_shaper_rate_kbps )) + compensated_ul_delay_thr_us=$(( ul_delay_thr_us + (1000*ul_max_wire_packet_size_bits)/ul_shaper_rate_kbps )) + + printf '%s' "${compensated_dl_delay_thr_us}" > "${run_path}/compensated_dl_delay_thr_us" + printf '%s' "${compensated_ul_delay_thr_us}" > "${run_path}/compensated_ul_delay_thr_us" + + # determine and write out ${max_wire_packet_rtt_us} + max_wire_packet_rtt_us=$(( (1000*dl_max_wire_packet_size_bits)/dl_shaper_rate_kbps + (1000*ul_max_wire_packet_size_bits)/ul_shaper_rate_kbps )) + printf '%s' "${max_wire_packet_rtt_us}" > "${run_path}/max_wire_packet_rtt_us" +} + +concurrent_read_integer() +{ + # in the context of a single process that writes to a file and + # a separate process that reads from the file, costly calls to + # the external flock binary can be avoided for the reason that + # the read either reads in a blank value or the last true value + # and so it is possible to just read, test and reread if necessary + + local -n value=${1} + local path=${2} + local exit_on_no_file=${3:-1} + + if ! [[ -f ${path} ]] + then + if ((exit_on_no_file)) + then + log_msg "ERROR" "Non-existent file at: ${path} and exit_on_no_file enabled. Exiting now." + kill -$$ INT + else + log_msg "DEBUG" "Non-existent file at: ${path} but exit_on_no_file disabled. Returning 1." + value=0 + return 1 + fi + fi + + for ((read_try=1; read_try<11; read_try++)) + do + read -r value < "${path}" + value="${value:-unset}" + + # printf '%.0f' is used here to sanitize unsigned integers: + # - it removes any leading zeros whilst preserving the sign; and + # - it returns false if ${value} is not a number + if printf -v sanitized_value '%.0f' "${value}" 2>/dev/null; then + + value=${sanitized_value} + return 0 + + else + if ((debug)); then + read -r caller_output< <(caller) || true + log_msg "DEBUG" "concurrent_read_integer() misfire: ${read_try} of 10, with the following particulars:" + log_msg "DEBUG" "caller=${caller_output}, value=${value} and path=${path}" + fi + sleep_us "${concurrent_read_integer_interval_us}" + continue + fi + done + + if ((debug)); then + read -r caller_output< <(caller) || true + log_msg "ERROR" "If you see this, then please report these messages (ideally with log file)" + log_msg "ERROR" "at the cake-autorate forum of OpenWrt and/or at github.com/lynxthecat/cake-autorate" + log_msg "ERROR" "concurrent_read_integer() 10x misfires, with the following particulars:" + log_msg "ERROR" "caller=${caller_output}, value=${value} and path=${path}" + fi + value=0 + return 1 +} + +verify_ifs_up() +{ + # Check the rx/tx paths exist and give extra time for ifb's to come up if needed + # This will block if ifs never come up + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + while [[ ! -f ${rx_bytes_path} || ! -f ${tx_bytes_path} ]] + do + [[ ! -f ${rx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured download interface: '${dl_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." + [[ ! -f ${tx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured upload interface: '${ul_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." + sleep_s "${if_up_check_interval_s}" + done +} + +ewma_iteration() +{ + local value=${1} + local alpha=${2} # alpha must be scaled by factor of 1000000 + local -n ewma=${3} + + prev_ewma=${ewma} + ewma=$(( (alpha*value+(1000000-alpha)*prev_ewma)/1000000 )) +} + +# redirect stderr to log_msg and exit cake-autorate +intercept_stderr() +{ + exec 2> >( + while read -r error + do + log_msg "ERROR" "${error}" + kill -INT $$ + done + ) +} + +# Debug command wrapper +# Inspired by cmd_wrapper of sqm-script +debug_cmd() +{ + # Usage: debug_cmd debug_msg err_silence cmd arg1 arg2, etc. + + # Error messages are output as log_msg ERROR messages + # Or set error_silence=1 to output errors as log_msg DEBUG messages + + local debug_msg=${1} + local err_silence=${2} + local cmd=${3} + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + shift 3 + + local args=("${@}") + + local caller_id + local err_type + + local ret + local stderr + + err_type="ERROR" + + if ((err_silence)); then + err_type="DEBUG" + fi + + stderr=$(${cmd} "${args[@]}" 2>&1) + ret=${?} + + caller_id=$(caller) + + if ((ret==0)); then + log_msg "DEBUG" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=SUCCESS" + else + [[ "${err_type}" == "DEBUG" && "${debug}" == "0" ]] && return # if debug disabled, then skip on DEBUG but not on ERROR + + log_msg "${err_type}" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=FAILURE (${ret})" + log_msg "${err_type}" "debug_cmd: LAST ERROR (${stderr})" + + frame=1 + while caller_output=$(caller "${frame}") + do + log_msg "${err_type}" "debug_cmd: CALL CHAIN: ${caller_output}" + ((++frame)) + done + fi +} + +# ======= Start of the Main Routine ======== + +[[ -t 1 ]] && terminal=1 || terminal=0 + +type logger &> /dev/null && use_logger=1 || use_logger=0 # only perform the test once. + +log_file_path=/var/log/cake-autorate.log + +# *** WARNING: take great care if attempting to alter the run_path! *** +# *** cake-autorate issues mkdir -p ${run_path} and rm -r ${run_path} on exit. *** +run_path=/var/run/cake-autorate/ + +# cake-autorate first argument is config file path +if [[ -n ${1:-} ]]; then + config_path=${1} +else + config_path="$PREFIX/cake-autorate_config.primary.sh" +fi + +if [[ ! -f "${config_path}" ]]; then + log_msg "ERROR" "No config file found. Exiting now." + exit +fi + +# shellcheck source=cake-autorate_config.primary.sh +. "${config_path}" + +if [[ ${config_file_check} != "cake-autorate" ]]; then + log_msg "ERROR" "Config file error. Please check config file entries." + exit +fi + +if [[ ${config_path} =~ cake-autorate_config\.(.*)\.sh ]]; then + instance_id=${BASH_REMATCH[1]} + run_path=/var/run/cake-autorate/${instance_id} +else + log_msg "ERROR" "Instance identifier 'X' set by cake-autorate_config.X.sh cannot be empty. Exiting now." + exit +fi + +PROC_STATE_FILE="${run_path}/proc_state" +PROC_STATE_FILE_LOCK="${run_path}/proc_state.lock" + +if [[ -n "${log_file_path_override:-}" ]]; then + if [[ ! -d ${log_file_path_override} ]]; then + broken_log_file_path_override=${log_file_path_override} + log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log + log_msg "ERROR" "Log file path override: '${broken_log_file_path_override}' does not exist. Exiting now." + exit + fi + log_file_path=${log_file_path_override}/cake-autorate${instance_id:+.${instance_id}}.log +else + log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log +fi + +rotate_log_file # rotate here to force header prints at top of log file + +# Intercept stderr, redirect it to log_msg and exit cake-autorate +intercept_stderr + +log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${config_path}" + +# ${run_path}/ is used to store temporary files +# it should not exist on startup so if it does exit, else create the directory +if [[ -d "${run_path}" ]]; then + if [[ -f "${run_path}/pid" ]] && [[ -d "/proc/$(<"${run_path}/pid")" ]]; then + log_msg "ERROR" "${run_path} already exists and an instance may be running. Exiting script." + trap - INT TERM EXIT + exit + else + log_msg "DEBUG" "${run_path} already exists but no instance is running. Removing and recreating." + rm -r "${run_path}" + mkdir -p "${run_path}" + fi +else + mkdir -p "${run_path}" +fi + +# Initialize proc_man +proc_man_initialize + +printf "%s" "${BASHPID}" > "${run_path}/pid" + +no_reflectors=${#reflectors[@]} + +# Check ping binary exists +command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${pinger_binary} does not exist. Exiting script."; exit; } + +# Check no_pingers <= no_reflectors +(( no_pingers > no_reflectors )) && { log_msg "ERROR" "number of pingers cannot be greater than number of reflectors. Exiting script."; exit; } + +# Check dl/if interface not the same +[[ "${dl_if}" == "${ul_if}" ]] && { log_msg "ERROR" "download interface and upload interface are both set to: '${dl_if}', but cannot be the same. Exiting script."; exit; } + +# Check bufferbloat detection threshold not greater than window length +(( bufferbloat_detection_thr > bufferbloat_detection_window )) && { log_msg "ERROR" "bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } + +# Passed error checks + +if ((log_to_file)); then + log_file_max_time_us=$((log_file_max_time_mins*60000000)) + log_file_max_size_bytes=$((log_file_max_size_KB*1024)) + exec {log_fd}<> <(:) || true + proc_man_start "maintain_log_file" maintain_log_file +fi + +# test if stdout is a tty (terminal) +if ! ((terminal)); then + echo "stdout not a terminal so redirecting output to: ${log_file_path}" + ((log_to_file)) && exec 1>&"${log_fd}" +fi + +# Initialize rx_bytes_path and tx_bytes_path if not set +if [[ -z "${rx_bytes_path:-}" ]]; then + case "${dl_if}" in + veth*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + ifb*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + *) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + esac +fi +if [[ -z "${tx_bytes_path:-}" ]]; then + case "${ul_if}" in + veth*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + ifb*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + *) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/tx_bytes" + ;; + esac +fi + +if ((debug)) ; then + log_msg "DEBUG" "CAKE-autorate version: ${cake_autorate_version}" + log_msg "DEBUG" "config_path: ${config_path}" + log_msg "DEBUG" "run_path: ${run_path}" + log_msg "DEBUG" "log_file_path: ${log_file_path}" + log_msg "DEBUG" "pinger_binary:${pinger_binary}" + log_msg "DEBUG" "download interface: ${dl_if} (${min_dl_shaper_rate_kbps} / ${base_dl_shaper_rate_kbps} / ${max_dl_shaper_rate_kbps})" + log_msg "DEBUG" "upload interface: ${ul_if} (${min_ul_shaper_rate_kbps} / ${base_ul_shaper_rate_kbps} / ${max_ul_shaper_rate_kbps})" + log_msg "DEBUG" "rx_bytes_path: ${rx_bytes_path}" + log_msg "DEBUG" "tx_bytes_path: ${tx_bytes_path}" +fi + +# Check interfaces are up and wait if necessary for them to come up +verify_ifs_up + +# Initialize variables + +# Convert human readable parameters to values that work with integer arithmetic + +printf -v dl_delay_thr_us %.0f "${dl_delay_thr_ms}e3" +printf -v ul_delay_thr_us %.0f "${ul_delay_thr_ms}e3" +printf -v alpha_baseline_increase %.0f "${alpha_baseline_increase}e6" +printf -v alpha_baseline_decrease %.0f "${alpha_baseline_decrease}e6" +printf -v alpha_delta_ewma %.0f "${alpha_delta_ewma}e6" +printf -v achieved_rate_adjust_down_bufferbloat %.0f "${achieved_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_down_bufferbloat %.0f "${shaper_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_up_load_high %.0f "${shaper_rate_adjust_up_load_high}e3" +printf -v shaper_rate_adjust_down_load_low %.0f "${shaper_rate_adjust_down_load_low}e3" +printf -v shaper_rate_adjust_up_load_low %.0f "${shaper_rate_adjust_up_load_low}e3" +printf -v high_load_thr_percent %.0f "${high_load_thr}e2" +printf -v reflector_ping_interval_ms %.0f "${reflector_ping_interval_s}e3" +printf -v reflector_ping_interval_us %.0f "${reflector_ping_interval_s}e6" +printf -v monitor_achieved_rates_interval_us %.0f "${monitor_achieved_rates_interval_ms}e3" +printf -v sustained_idle_sleep_thr_us %.0f "${sustained_idle_sleep_thr_s}e6" +printf -v reflector_response_deadline_us %.0f "${reflector_response_deadline_s}e6" +printf -v reflector_owd_baseline_delta_thr_us %.0f "${reflector_owd_baseline_delta_thr_ms}e3" +printf -v reflector_owd_delta_ewma_delta_thr_us %.0f "${reflector_owd_delta_ewma_delta_thr_ms}e3" +printf -v startup_wait_us %.0f "${startup_wait_s}e6" +printf -v global_ping_response_timeout_us %.0f "${global_ping_response_timeout_s}e6" +printf -v bufferbloat_refractory_period_us %.0f "${bufferbloat_refractory_period_ms}e3" +printf -v decay_refractory_period_us %.0f "${decay_refractory_period_ms}e3" + +for (( i=0; i<${#sss_times_s[@]}; i++ )); +do + printf -v sss_times_us[i] %.0f\\n "${sss_times_s[i]}e6" +done +printf -v sss_compensation_pre_duration_us %.0f "${sss_compensation_pre_duration_ms}e3" +printf -v sss_compensation_post_duration_us %.0f "${sss_compensation_post_duration_ms}e3" + +ping_response_interval_us=$(( reflector_ping_interval_us/no_pingers )) +ping_response_interval_ms=$(( ping_response_interval_us/1000 )) + +stall_detection_timeout_us=$(( stall_detection_thr*ping_response_interval_us )) +stall_detection_timeout_s=000000${stall_detection_timeout_us} +stall_detection_timeout_s=$(( 10#${stall_detection_timeout_s::-6})).${stall_detection_timeout_s: -6} + +concurrent_read_integer_interval_us=$((ping_response_interval_us/4)) + +dl_shaper_rate_kbps=${base_dl_shaper_rate_kbps} +ul_shaper_rate_kbps=${base_ul_shaper_rate_kbps} + +last_dl_shaper_rate_kbps=0 +last_ul_shaper_rate_kbps=0 + +get_max_wire_packet_size_bits "${dl_if}" dl_max_wire_packet_size_bits +get_max_wire_packet_size_bits "${ul_if}" ul_max_wire_packet_size_bits + +set_shaper_rates + +update_max_wire_packet_compensation + +t_start_us=${EPOCHREALTIME/./} +t_end_us=${EPOCHREALTIME/./} + +t_prev_ul_rate_set_us=${t_start_us} +t_prev_dl_rate_set_us=${t_start_us} +t_ul_last_bufferbloat_us=${t_start_us} +t_ul_last_decay_us=${t_start_us} +t_dl_last_bufferbloat_us=${t_start_us} +t_dl_last_decay_us=${t_start_us} + +t_sustained_connection_idle_us=0 + +mapfile -t dl_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) +mapfile -t ul_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) + +delays_idx=0 +sum_dl_delays=0 +sum_ul_delays=0 + +if ((debug)); then + if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )); then + log_msg "DEBUG" "Warning: bufferbloat refractory period: ${bufferbloat_refractory_period_us} us." + log_msg "DEBUG" "Warning: but expected time to overwrite samples in bufferbloat detection window is: $((bufferbloat_detection_window*ping_response_interval_us)) us." + log_msg "DEBUG" "Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." + fi + if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )); then + log_msg "DEBUG" "Warning: reflector_response_deadline_s < 2*reflector_ping_interval_s" + log_msg "DEBUG" "Warning: consider setting an increased reflector_response_deadline." + fi +fi + +# Randomize reflectors array providing randomize_reflectors set to 1 +((randomize_reflectors)) && randomize_array reflectors + +# Wait if ${startup_wait_s} > 0 +if ((startup_wait_us>0)); then + log_msg "DEBUG" "Waiting ${startup_wait_s} seconds before startup." + sleep_us "${startup_wait_us}" +fi + +# Initiate achieved rate monitor +proc_man_start monitor_achieved_rates monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" + +printf '%s' "0" > "${run_path}/dl_load_percent" +printf '%s' "0" > "${run_path}/ul_load_percent" + +proc_man_start maintain_pingers maintain_pingers + +generate_log_file_exporter + +log_msg "INFO" "Started cake-autorate with PID: ${BASHPID} and config: ${config_path}" + +while true +do + while read -r -t "${stall_detection_timeout_s}" -u "${ping_fd}" timestamp reflector seq dl_owd_baseline_us dl_owd_us dl_owd_delta_ewma_us dl_owd_delta_us ul_owd_baseline_us ul_owd_us ul_owd_delta_ewma_us ul_owd_delta_us + do + t_start_us=${EPOCHREALTIME/./} + if (( (t_start_us - 10#"${timestamp//[.]}")>500000 )); then + log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." + continue + fi + + # Keep track of number of dl delays across detection window + # .. for download: + (( dl_delays[delays_idx] )) && ((sum_dl_delays--)) + dl_delays[delays_idx]=$(( dl_owd_delta_us > compensated_dl_delay_thr_us ? 1 : 0 )) + ((dl_delays[delays_idx])) && ((sum_dl_delays++)) + # .. for upload + (( ul_delays[delays_idx] )) && ((sum_ul_delays--)) + ul_delays[delays_idx]=$(( ul_owd_delta_us > compensated_ul_delay_thr_us ? 1 : 0 )) + ((ul_delays[delays_idx])) && ((sum_ul_delays++)) + # .. and move index on + (( delays_idx=(delays_idx+1)%bufferbloat_detection_window )) + + dl_bufferbloat_detected=$(( ((sum_dl_delays >= bufferbloat_detection_thr)) ? 1 : 0 )) + ul_bufferbloat_detected=$(( ((sum_ul_delays >= bufferbloat_detection_thr)) ? 1 : 0 )) + + get_loads + + classify_load "${dl_load_percent}" "${dl_achieved_rate_kbps}" "${dl_bufferbloat_detected}" dl_load_condition + classify_load "${ul_load_percent}" "${ul_achieved_rate_kbps}" "${ul_bufferbloat_detected}" ul_load_condition + + dl_load_condition="dl_"${dl_load_condition} + ul_load_condition="ul_"${ul_load_condition} + + get_next_shaper_rate "${min_dl_shaper_rate_kbps}" "${base_dl_shaper_rate_kbps}" "${max_dl_shaper_rate_kbps}" "${dl_achieved_rate_kbps}" "${dl_load_condition}" "${t_start_us}" t_dl_last_bufferbloat_us t_dl_last_decay_us dl_shaper_rate_kbps + get_next_shaper_rate "${min_ul_shaper_rate_kbps}" "${base_ul_shaper_rate_kbps}" "${max_ul_shaper_rate_kbps}" "${ul_achieved_rate_kbps}" "${ul_load_condition}" "${t_start_us}" t_ul_last_bufferbloat_us t_ul_last_decay_us ul_shaper_rate_kbps + + set_shaper_rates + + if (( output_processing_stats )); then + printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${dl_achieved_rate_kbps}" "${ul_achieved_rate_kbps}" "${dl_load_percent}" "${ul_load_percent}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${dl_load_condition}" "${ul_load_condition}" "${dl_shaper_rate_kbps}" "${ul_shaper_rate_kbps}" + log_msg "DATA" "${processing_stats}" + fi + + # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) + if (( enable_sleep_function )); then + if [[ ${dl_load_condition} == *idle* && ${ul_load_condition} == *idle* ]]; then + ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) + ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) && break + else + # reset timer + t_sustained_connection_idle_us=0 + fi + fi + + t_end_us=${EPOCHREALTIME/./} + + done + + # stall handling procedure + # PIPESTATUS[0] == 142 corresponds with while loop timeout + # i.e. no reflector responses within ${stall_detection_thr} * ${ping_response_interval_us} + if (( PIPESTATUS[0] == 142 )); then + + log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking for loads." + + get_loads + + log_msg "DEBUG" "load check is: ((${dl_achieved_rate_kbps} kbps > ${connection_stall_thr_kbps} kbps && ${ul_achieved_rate_kbps} kbps > ${connection_stall_thr_kbps} kbps))" + + # non-zero load so despite no reflector response within stall interval, the connection not considered to have stalled + # and therefore resume normal operation + if (( dl_achieved_rate_kbps > connection_stall_thr_kbps && ul_achieved_rate_kbps > connection_stall_thr_kbps )); then + + log_msg "DEBUG" "load above connection stall threshold so resuming normal operation." + continue + + fi + + log_msg "DEBUG" "Warning: connection stall detection. Waiting for new ping or increased load" + + # save intial global reflector timestamp to check against for any new reflector response + concurrent_read_integer initial_reflectors_last_timestamp_us "${run_path}/reflectors_last_timestamp_us" + + # update maintain_pingers state + printf "PAUSED" > ${run_path}/maintain_pingers_next_state + proc_man_signal maintain_pingers "USR1" + + t_connection_stall_time_us=${EPOCHREALTIME/./} + + global_ping_response_timeout=0 + + # wait until load resumes or ping response received (or global reflector response timeout) + while true + do + t_start_us=${EPOCHREALTIME/./} + + concurrent_read_integer new_reflectors_last_timestamp_us "${run_path}/reflectors_last_timestamp_us" + get_loads + + # shellcheck disable=SC2154 + if (( new_reflectors_last_timestamp_us != initial_reflectors_last_timestamp_us || ( dl_achieved_rate_kbps > connection_stall_thr_kbps && ul_achieved_rate_kbps > connection_stall_thr_kbps) )); then + + log_msg "DEBUG" "Connection stall ended. Resuming normal operation." + + # update maintain_pingers state + printf "RUNNING" > ${run_path}/maintain_pingers_next_state + proc_man_signal maintain_pingers "USR1" + + # continue main loop (i.e. skip idle/global timeout handling below) + continue 2 + fi + + sleep_remaining_tick_time "${t_start_us}" "${reflector_ping_interval_us}" + + if (( global_ping_response_timeout==0 && t_start_us > (t_connection_stall_time_us + global_ping_response_timeout_us - stall_detection_timeout_us) )); then + log_msg "SYSLOG" "Warning: Configured global ping response timeout: ${global_ping_response_timeout_s} seconds exceeded." + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + global_ping_response_timeout=1 + fi + done + + else + log_msg "DEBUG" "Connection idle. Waiting for minimum load." + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + fi + + # update maintain_pingers state + printf "STOP" > ${run_path}/maintain_pingers_next_state + proc_man_signal maintain_pingers "USR1" + + # reset idle timer + t_sustained_connection_idle_us=0 + + # wait until load increases again + while true + do + t_start_us=${EPOCHREALTIME/./} + get_loads + + if (( dl_achieved_rate_kbps > connection_active_thr_kbps || ul_achieved_rate_kbps > connection_active_thr_kbps )); then + log_msg "DEBUG" "dl achieved rate: ${dl_achieved_rate_kbps} kbps or ul achieved rate: ${ul_achieved_rate_kbps} kbps exceeded connection active threshold: ${connection_active_thr_kbps} kbps. Resuming normal operation." + break + fi + sleep_remaining_tick_time "${t_start_us}" "${reflector_ping_interval_us}" + done + + # update maintain_pingers state + printf "START" > ${run_path}/maintain_pingers_next_state + proc_man_signal maintain_pingers "USR1" + + t_end_us=${EPOCHREALTIME/./} +done diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh new file mode 100755 index 000000000..e6f290d82 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh @@ -0,0 +1,209 @@ +#!/bin/bash + +# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT + +# cake-autorate_config.sh is a script that sets up defaults for cake-autorate + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) + +cake_autorate_version="2.0.0" + +# *** OUTPUT AND LOGGING OPTIONS *** + +output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats +output_load_stats=1 # enable (1) or disable (0) output monitoring lines showing achieved loads +output_reflector_stats=1 # enable (1) or disable (0) output monitoring lines showing reflector stats +output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +debug=1 # enable (1) or disable (0) out of debug lines + +# This can generate a LOT of records so be careful: +log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. + +# ** Take care with these settings to ensure you won't run into OOM issues on your router *** +# every write the cumulative write time and bytes associated with each log line are checked +# and if either exceeds the configured values below, the log log file is rotated +log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log) +log_file_max_time_mins=10 # maximum time between log file rotations +log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations + +# log file path defaults to /var/log/ +# or, if set below, then ${log_file_path_override} +log_file_path_override="" + +# *** STANDARD CONFIGURATION OPTIONS *** + +### For multihomed setups, it is the responsibility of the user to ensure that the probes +### sent by this instance of cake-autorate actually travel through these interfaces. +### See ping_extra_args and ping_prefix_string + +dl_if=ifb-wan # download interface +ul_if=wan # upload interface + +# pinger selection can be any of: +# fping - round robin pinging (rtts) +# ping - (iputils-ping) individual pinging (rtts) +# hping3 - individidual pinging (owds) +pinger_binary=ping + +# list of reflectors to use and number of pingers to initiate +# pingers will be initiated with reflectors in the order specified in the list +# additional reflectors will be used to replace any reflectors that go stale +# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially +# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad +# a bad reflector will go to the back of the queue on reflector rotation +reflectors=( +"1.1.1.1" "1.0.0.1" # Cloudflare +"8.8.8.8" "8.8.4.4" # Google +"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 +"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard +"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar +"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS +"185.228.168.9" "185.228.168.10" # CleanBrowsing +) + +randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup + +# Think carefully about the following settings +# to avoid excessive CPU use (proportional with ping interval / number of pingers) +# and to avoid abusive network activity (excessive ICMP frequency to one reflector) +# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G +no_pingers=6 # number of pingers to maintain +reflector_ping_interval_s=0.3 # (seconds, e.g. 0.2s or 2s) + +# delay threshold in ms is the extent of OWD increase to classify as a delay +# these are automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +dl_delay_thr_ms=30 # (milliseconds) +ul_delay_thr_ms=30 # (milliseconds) + +# Set either of the below to 0 to adjust one direction only +# or alternatively set both to 0 to simply use cake-autorate to monitor a connection +adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate +adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate + +min_dl_shaper_rate_kbps=5000 # minimum bandwidth for download (Kbit/s) +base_dl_shaper_rate_kbps=20000 # steady state bandwidth for download (Kbit/s) +max_dl_shaper_rate_kbps=80000 # maximum bandwidth for download (Kbit/s) + +min_ul_shaper_rate_kbps=5000 # minimum bandwidth for upload (Kbit/s) +base_ul_shaper_rate_kbps=20000 # steady state bandwidth for upload (KBit/s) +max_ul_shaper_rate_kbps=35000 # maximum bandwidth for upload (Kbit/s) + +# sleep functionality saves unecessary pings and CPU cycles by +# pausing all active pingers when connection is not in active use +enable_sleep_function=1 # enable (1) or disable (0) sleep functonality +connection_active_thr_kbps=1000 # threshold in Kbit/s below which dl/ul is considered idle +sustained_idle_sleep_thr_s=60.0 # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) + +min_shaper_rates_enforcement=0 # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall + +startup_wait_s=0.0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) + +# *** ADVANCED CONFIGURATION OPTIONS *** + +log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename + +### In multi-homed setups, it is mandatory to use either ping_extra_args +### or ping_prefix_string to direct the pings through $dl_if and $ul_if. +### No universal recommendation exists, because there are multiple +### policy-routing packages available (e.g. vpn-policy-routing and mwan3). +### Typically they either react to a firewall mark set on the pings, or +### provide a convenient wrapper. +### +### In a traditional single-homed setup, there is usually no need for these parameters. +### +### These arguments can also be used for any other purpose - e.g. for setting a +### particular QoS mark. + +# extra arguments for ping or fping +# e.g., here is how you can set the correct outgoing interface and +# the firewall mark for ping: +# ping_extra_args="-I wwan0 -m $((0x300))" +# Unfortunately, fping does not offer a command line switch to set +# the firewall mark. +# WARNING: no error checking so use at own risk! +ping_extra_args="" + +# a wrapper for ping binary - used as a prefix for the real command +# e.g., when using mwan3, it is recommended to set it like this: +# ping_prefix_string="mwan3 use gpon exec" +# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess. +# Running ping or fping as a subprocess will lead to problems stopping it. +# WARNING: no error checking - so use at own risk! +ping_prefix_string="" + +# interval in ms for monitoring achieved rx/tx rates +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +monitor_achieved_rates_interval_ms=200 # (milliseconds) + +# bufferbloat is detected when (bufferbloat_detection_thr) samples +# out of the last (bufferbloat detection window) samples are delayed +bufferbloat_detection_window=6 # number of samples to retain in detection window +bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection + +# OWD baseline against which to measure delays +# the idea is that the baseline is allowed to increase slowly to allow for path changes +# and slowly enough such that bufferbloat will be corrected well before the baseline increases, +# but it will decrease very rapidly to ensure delays are measured against the shortest path +alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase +alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease + +# OWD delta from baseline is tracked using ewma with alpha set below +alpha_delta_ewma=0.095 + +# rate adjustment parameters +# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate +# to exploit that transfer rates during bufferbloat provide an indication of line capacity +# otherwise shaper rate is adjusted up on load high, and down on load idle or low +achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat +shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat +shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected +shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected +shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected + +# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate +high_load_thr=0.75 # % of currently set bandwidth for detecting high load + +# refractory periods between successive bufferbloat/decay rate changes +# the bufferbloat refractory period should be greater than the +# average time it would take to replace the bufferbloat +# detection window with new samples upon a bufferbloat event +bufferbloat_refractory_period_ms=300 # (milliseconds) +decay_refractory_period_ms=1000 # (milliseconds) + +# interval for checking reflector health +reflector_health_check_interval_s=1.0 # (seconds) +# deadline for reflector response not to be classified as an offence against reflector +reflector_response_deadline_s=1.0 # (seconds) + +# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples +# out of the last (reflector misbehaving detection window) samples are offences +# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to +# 3 offences within the last 60s +reflector_misbehaving_detection_window=60 +reflector_misbehaving_detection_thr=3 + +reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list + +reflector_comparison_interval_mins=1 # how often to compare reflectors +reflector_owd_baseline_delta_thr_ms=10 # max increase from min baseline before reflector rotated +reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated + +# stall is detected when the following two conditions are met: +# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and +# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr +stall_detection_thr=5 +connection_stall_thr_kbps=10 + +global_ping_response_timeout_s=10.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) + +if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) + +# Starlink satellite switch (sss) compensation options +sss_compensation=0 # enable (1) or disable (0) Starlink handling +# satellite switch compensation start times in seconds of each minute +sss_times_s=("12.0" "27.0" "42.0" "57.0") +sss_compensation_pre_duration_ms=300 +sss_compensation_post_duration_ms=200 diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh new file mode 100755 index 000000000..f708f328a --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +cake_instances=(/usr/share/sqm-autorate/cake-autorate_config*sh) +cake_instance_pids=() + +trap kill_cake_instances INT TERM EXIT + +kill_cake_instances() +{ + trap - INT TERM EXIT + + echo "Killing all instances of cake one-by-one now." + + for ((cake_instance=0; cake_instance<${#cake_instances[@]}; cake_instance++)) + do + kill "${cake_instance_pids[${cake_instance}]}" 2>/dev/null || true + done + wait +} + +for cake_instance in "${cake_instances[@]}" +do + /usr/share/sqm-autorate/cake-autorate.sh "${cake_instance}" & + cake_instance_pids+=(${!}) +done +wait diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh new file mode 100755 index 000000000..413d191c0 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh @@ -0,0 +1,257 @@ +#!/bin/bash +# cake-autorate_lib.sh -- common functions for use by cake-autorate.sh +# This file is part of cake-autorate. + +__set_e=0 +if [[ ! ${-} =~ e ]]; then + set -e + __set_e=1 +fi + +exec {__sleep_fd}<> <(:) || true + +sleep_s() +{ + # Calling the external sleep binary could be rather slow, + # especially as it is called very frequently and typically on mediocre hardware. + # + # bash's loadable sleep module is not typically available + # in OpenWRT and most embedded systems, and use of the bash + # read command with a timeout offers performance that is + # at least on a par with bash's sleep module. + # + # For benchmarks, check the following links: + # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460057382 + # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460074498 + + local sleep_duration_s=${1} # (seconds, e.g. 0.5, 1 or 1.5) + read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : & + wait "${!}" +} + +sleep_us() +{ + local sleep_duration_us=${1} # (microseconds) + + sleep_duration_s=000000${sleep_duration_us} + sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6} + sleep_s "${sleep_duration_s}" +} + +sleep_remaining_tick_time() +{ + # sleeps until the end of the tick duration + + local t_start_us=${1} # (microseconds) + local tick_duration_us=${2} # (microseconds) + + # shellcheck disable=SC2154 + sleep_duration_us=$(( t_start_us + tick_duration_us - ${EPOCHREALTIME/./} )) + + if (( sleep_duration_us > 0 )); then + sleep_us "${sleep_duration_us}" + fi +} + +randomize_array() +{ + local -n array=${1} + + subset=("${array[@]}") + array=() + for ((set=${#subset[@]}; set>0; set--)) + do + idx=$((RANDOM%set)) + array+=("${subset[idx]}") + unset "subset[idx]" + subset=("${subset[@]}") + done +} + +lock() +{ + local path=${1} + + while true; do + ( set -o noclobber; echo "$$" > "${path:?}" ) 2> /dev/null && return 0 + sleep_us 100000 + done +} + +unlock() +{ + local path=${1} + + rm -f "${path:?}" +} + +_proc_man_set_key() +{ + local key=${1} + local value=${2} + + lock "${PROC_STATE_FILE_LOCK:?}" + trap 'unlock "${PROC_STATE_FILE_LOCK:?}"' RETURN + + local entered=0 + while read -r line; do + if [[ ${line} =~ ^${key}= ]]; then + printf '%s\n' "${key}=${value}" + entered=1 + else + printf '%s\n' "${line}" + fi + done < "${PROC_STATE_FILE:?}" > "${PROC_STATE_FILE:?}.tmp" + if (( entered == 0 )); then + printf '%s\n' "${key}=${value}" >> "${PROC_STATE_FILE:?}.tmp" + fi + mv "${PROC_STATE_FILE:?}.tmp" "${PROC_STATE_FILE:?}" + return 0 +} + +_proc_man_get_key_value() +{ + local key=${1} + + lock "${PROC_STATE_FILE_LOCK:?}" + trap 'unlock "${PROC_STATE_FILE_LOCK:?}"' RETURN + + while read -r line; do + if [[ ${line} =~ ^${key}= ]]; then + printf '%s\n' "${line#*=}" + return 0 + fi + done < "${PROC_STATE_FILE:?}" + return 1 +} + +proc_man() +{ + local action=${1} + local name=${2} + shift 2 + + if [[ ! -f "${PROC_STATE_FILE:?}" ]]; then + return 1 + fi + + # shellcheck disable=SC2311 + case "${action}" in + "start") + pid=$(_proc_man_get_key_value "${name}") + if (( pid && pid > 0 )) && kill -0 "${pid}" 2> /dev/null; then + return 1; + fi + + "${@}" & + local pid=${!} + _proc_man_set_key "${name}" "${pid}" + ;; + "stop") + local pid + pid=$(_proc_man_get_key_value "${name}") + if ! (( pid && pid > 0 )); then + return 0; + fi + + kill "${pid}" 2> /dev/null || true + + # wait for process to die + killed=0 + for ((i=0; i<10; i++)); + do + if kill -0 "${pid}" 2> /dev/null; then + sleep_us 100000 + else + killed=1 + break + fi + done + + # if process still alive, kill it with fire + if (( killed == 0 )); then + kill -9 "${pid}" 2> /dev/null || true + fi + + _proc_man_set_key "${name}" "-1" "${PROC_STATE_FILE:?}" + ;; + "status") + local pid + pid=$(_proc_man_get_key_value "${name}") + if (( pid && pid > 0 )); then + if kill -0 "${pid}" 2> /dev/null; then + printf '%s\n' "running" + else + printf '%s\n' "dead" + fi + else + printf '%s\n' "stopped" + fi + ;; + "wait") + local pid + pid=$(_proc_man_get_key_value "${name}") + if (( pid && pid > 0 )); then + wait "${pid}" && return 0 + fi + + return 1 + ;; + "signal") + shift 3 + + local pid + pid=$(_proc_man_get_key_value "${name}") + if (( pid && pid > 0 )); then + kill -s "${1}" "${pid}" 2>/dev/null && return 0 + fi + + return 1 + ;; + "initialize") + proc_man_initialize + return $? + ;; + *) + printf '%s\n' "unknown action: ${action}" >&2 + return 1 + ;; + esac + + return 0 +} + +proc_man_initialize() +{ + true > "${PROC_STATE_FILE:?}" +} + +proc_man_start() +{ + proc_man start "${@}" +} + +proc_man_stop() +{ + proc_man stop "${@}" +} + +proc_man_status() +{ + proc_man status "${@}" +} + +proc_man_wait() +{ + proc_man wait "${@}" +} + +proc_man_signal() +{ + proc_man signal "${@}" +} + +if (( __set_e == 1 )); then + set +e +fi +unset __set_e diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh new file mode 100755 index 000000000..5d3195dff --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh @@ -0,0 +1,213 @@ +#!/bin/bash + +# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT + +# cake-autorate_config.sh is a script that sets up defaults for cake-autorate + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) + +INTERFACE=$(basename "$0" | cut -d. -f2) + +cake_autorate_version="2.0.0" + +# *** OUTPUT AND LOGGING OPTIONS *** + +output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing processing stats +output_load_stats=$(uci -q get sqm.${INTERFACE}.output_load_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing achieved loads +output_reflector_stats=$(uci -q get sqm.${INTERFACE}.output_reflector_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing reflector stats +output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo '0') # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +debug=$(uci -q get sqm.${INTERFACE}.debug || echo '0') # enable (1) or disable (0) out of debug lines + +# This can generate a LOT of records so be careful: +log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. + +# ** Take care with these settings to ensure you won't run into OOM issues on your router *** +# every write the cumulative write time and bytes associated with each log line are checked +# and if either exceeds the configured values below, the log log file is rotated +log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log) +log_file_max_time_mins=10 # maximum time between log file rotations +log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations + +# log file path defaults to /var/log/ +# or, if set below, then ${log_file_path_override} +log_file_path_override="" + +# *** STANDARD CONFIGURATION OPTIONS *** + +### For multihomed setups, it is the responsibility of the user to ensure that the probes +### sent by this instance of cake-autorate actually travel through these interfaces. +### See ping_extra_args and ping_prefix_string + +dl_if=ifb4$(uci -q get sqm.${INTERFACE}.interface) # download interface +ul_if=$(uci -q get sqm.${INTERFACE}.interface) # upload interface + +# pinger selection can be any of: +# fping - round robin pinging (rtts) +# ping - (iputils-ping) individual pinging (rtts) +# hping3 - individidual pinging (owds) +pinger_binary=ping + +# list of reflectors to use and number of pingers to initiate +# pingers will be initiated with reflectors in the order specified in the list +# additional reflectors will be used to replace any reflectors that go stale +# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially +# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad +# a bad reflector will go to the back of the queue on reflector rotation +reflectors=($(uci -q get omr-tracker.defaults.hosts)) +#reflectors=( +#"1.1.1.1" "1.0.0.1" # Cloudflare +#"8.8.8.8" "8.8.4.4" # Google +#"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 +#"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard +#"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar +#"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS +#"185.228.168.9" "185.228.168.10" # CleanBrowsing +#) + +randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup + +# Think carefully about the following settings +# to avoid excessive CPU use (proportional with ping interval / number of pingers) +# and to avoid abusive network activity (excessive ICMP frequency to one reflector) +# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G +no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "6") # number of pingers to maintain +reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.3") # (seconds, e.g. 0.2s or 2s) + +# delay threshold in ms is the extent of OWD increase to classify as a delay +# these are automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "30") # (milliseconds) +ul_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "30") # (milliseconds) + +# Set either of the below to 0 to adjust one direction only +# or alternatively set both to 0 to simply use cake-autorate to monitor a connection +adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate +adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate + +min_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_download || echo "5000") # minimum bandwidth for download (Kbit/s) +base_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.download || echo "40000") # steady state bandwidth for download (Kbit/s) +max_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_download || echo "80000") # maximum bandwidth for download (Kbit/s) + +min_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_upload || echo "5000") # minimum bandwidth for upload (Kbit/s) +base_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.upload || echo "20000") # steady state bandwidth for upload (KBit/s) +max_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_upload || echo "35000") # maximum bandwidth for upload (Kbit/s) + +# sleep functionality saves unecessary pings and CPU cycles by +# pausing all active pingers when connection is not in active use +enable_sleep_function=$(uci -q get sqm.${INTERFACE}.enable_sleep_functions || echo "1") # enable (1) or disable (0) sleep functonality +connection_active_thr_kbps=$(uci -q get sqm.${INTERFACE}.connection_active_thr_kpbs || echo "1000") # threshold in Kbit/s below which dl/ul is considered idle +sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.sustained_idle_sleep_thr || echo "60.0") # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) + +min_shaper_rates_enforcement=$(uci -q get sqm.${INTERFACE}.min_shaper_rates_enforcement || echo "0") # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall + +startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "60.0") # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) + +# *** ADVANCED CONFIGURATION OPTIONS *** + +log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename + +### In multi-homed setups, it is mandatory to use either ping_extra_args +### or ping_prefix_string to direct the pings through $dl_if and $ul_if. +### No universal recommendation exists, because there are multiple +### policy-routing packages available (e.g. vpn-policy-routing and mwan3). +### Typically they either react to a firewall mark set on the pings, or +### provide a convenient wrapper. +### +### In a traditional single-homed setup, there is usually no need for these parameters. +### +### These arguments can also be used for any other purpose - e.g. for setting a +### particular QoS mark. + +# extra arguments for ping or fping +# e.g., here is how you can set the correct outgoing interface and +# the firewall mark for ping: +# ping_extra_args="-I wwan0 -m $((0x300))" +# Unfortunately, fping does not offer a command line switch to set +# the firewall mark. +# WARNING: no error checking so use at own risk! +ping_extra_args="- B -I ${INTERFACE}" + +# a wrapper for ping binary - used as a prefix for the real command +# e.g., when using mwan3, it is recommended to set it like this: +# ping_prefix_string="mwan3 use gpon exec" +# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess. +# Running ping or fping as a subprocess will lead to problems stopping it. +# WARNING: no error checking - so use at own risk! +ping_prefix_string="" +# interval in ms for monitoring achieved rx/tx rates +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +monitor_achieved_rates_interval_ms=200 # (milliseconds) + +# bufferbloat is detected when (bufferbloat_detection_thr) samples +# out of the last (bufferbloat detection window) samples are delayed +bufferbloat_detection_window=6 # number of samples to retain in detection window +bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection + +# OWD baseline against which to measure delays +# the idea is that the baseline is allowed to increase slowly to allow for path changes +# and slowly enough such that bufferbloat will be corrected well before the baseline increases, +# but it will decrease very rapidly to ensure delays are measured against the shortest path +alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase +alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease + +# OWD delta from baseline is tracked using ewma with alpha set below +alpha_delta_ewma=0.095 + +# rate adjustment parameters +# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate +# to exploit that transfer rates during bufferbloat provide an indication of line capacity +# otherwise shaper rate is adjusted up on load high, and down on load idle or low +achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat +shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat +shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected +shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected +shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected + +# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate +high_load_thr=0.75 # % of currently set bandwidth for detecting high load + +# refractory periods between successive bufferbloat/decay rate changes +# the bufferbloat refractory period should be greater than the +# average time it would take to replace the bufferbloat +# detection window with new samples upon a bufferbloat event +bufferbloat_refractory_period_ms=300 # (milliseconds) +decay_refractory_period_ms=1000 # (milliseconds) + +# interval for checking reflector health +reflector_health_check_interval_s=1.0 # (seconds) +# deadline for reflector response not to be classified as an offence against reflector +reflector_response_deadline_s=1.0 # (seconds) + +# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples +# out of the last (reflector misbehaving detection window) samples are offences +# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to +# 3 offences within the last 60s +reflector_misbehaving_detection_window=60 +reflector_misbehaving_detection_thr=3 + +reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list + +reflector_comparison_interval_mins=1 # how often to compare reflectors +reflector_owd_baseline_delta_thr_ms=10 # max increase from min baseline before reflector rotated +reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated + +# stall is detected when the following two conditions are met: +# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and +# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr +stall_detection_thr=5 +connection_stall_thr_kbps=10 + +global_ping_response_timeout_s=10.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) + +if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) + +# Starlink satellite switch (sss) compensation options +sss_compensation=$(uci -q get sqm.${INTERFACE}.sss_compensation || echo "0") # enable (1) or disable (0) Starlink handling +# satellite switch compensation start times in seconds of each minute +sss_times_s=("12.0" "27.0" "42.0" "57.0") +sss_compensation_pre_duration_ms=300 +sss_compensation_post_duration_ms=200 + +config_file_check="cake-autorate" \ No newline at end of file diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh old mode 100644 new mode 100755 index 7d0948f2a..509dee635 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh @@ -19,7 +19,8 @@ output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || #output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo "0") #debug=0 # enable (1) or disable (0) out of debug lines -debug=$(uci -q get sqm.common.debug || echo "0") +#debug=$(uci -q get sqm.common.debug || echo "0") +debug=1 # *** STANDARD CONFIGURATION OPTIONS *** @@ -128,32 +129,3 @@ global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no pin if_up_check_interval_s=10 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state) -# verify these are correct using 'cat /sys/class/...' -case "${dl_if}" in - \veth*) - rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" - ;; - \ifb*) - rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" - ;; - *) - rx_bytes_path="/sys/class/net/${dl_if}/statistics/rx_bytes" - ;; -esac - -case "${ul_if}" in - \veth*) - tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" - ;; - \ifb*) - tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" - ;; - *) - tx_bytes_path="/sys/class/net/${ul_if}/statistics/tx_bytes" - ;; -esac - -if (( $debug )) ; then - echo "DEBUG: rx_bytes_path: $rx_bytes_path" - echo "DEBUG: tx_bytes_path: $tx_bytes_path" -fi diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 79ea2fcb9..506828a73 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1010,6 +1010,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" #if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then OMR_NETWORK_DEVICE=$(find_network_device ${OMR_TRACKER_INTERFACE}) + #_log "OMR_NETWORK_DEVICE: $OMR_NETWORK_DEVICE for $OMR_TRACKER_DEVICE - $OMR_TRACKER_INTERFACE" if [ -n "$OMR_NETWORK_DEVICE" ] && [ -n "$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then mtu=$(uci -q get network.$OMR_NETWORK_DEVICE.mtu) uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu @@ -1751,7 +1752,7 @@ if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprout sleep 5 fi -if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -z $(pgrep -f "autorate.sh ${OMR_TRACKER_INTERFACE}") ]; then +if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "autorate.*${OMR_TRACKER_DEVICE}") ]; then /etc/init.d/sqm-autorate restart >/dev/null 2>&1 sleep 5 fi From be8b7165fcc1cb2df1f53995c3633b059b3d81f6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 1 Apr 2023 08:31:11 +0200 Subject: [PATCH 0931/2059] Detect when VPS and router kernel doesn't match --- .../luasrc/view/openmptcprouter/wanstatus.htm | 6 ++++++ .../root/usr/libexec/rpcd/openmptcprouter | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index fe573ae19..085bbce00 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -347,6 +347,12 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm statusMessageClass = "warning"; statusIcon = "<%=resource%>/openmptcprouter/images/statusWarning.png"; } + if (mArray.openmptcprouter.kernel_match == false) + { + statusMessage += '<%:MPTCP kernel on router and VPS doesn't match%>' + '
    '; + statusMessageClass = "warning"; + statusIcon = "<%=resource%>/openmptcprouter/images/statusWarning.png"; + } if (mArray.openmptcprouter.wan_addr6) { content += '<%:IPv6:%>' + " " + mArray.openmptcprouter.wan_addr6; diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index f6b275150..cec97258f 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -761,6 +761,7 @@ function interfaces_status() mArray.openmptcprouter["local_addr"] = ipaddr --mArray.openmptcprouter["local_addr"] = uci:get("network", "lan", "ipaddr") mArray.openmptcprouter["hostname"] = "OpenMPTCProuter" + mArray.openmptcprouter["kernel"] = sys.exec("uname -r") ucic:foreach("system", "system", function(s) mArray.openmptcprouter["hostname"] = uci:get("system",s[".name"],"hostname") or "OpenMPTCProuter" end) @@ -955,6 +956,12 @@ function interfaces_status() end end) + mArray.openmptcprouter["kernel_match"] = true + if mArray.openmptcprouter["vps_kernel"] ~= "" then + if mArray.openmptcprouter["kernel"]:sub(1,3) == "5.4" and mArray.openmptcprouter["vps_kernel"]:sub(1,3) ~= "5.4" then + mArray.openmptcprouter["kernel_match"] = false + end + end if mArray.openmptcprouter["vps_hostname"] == "" then mArray.openmptcprouter["vps_hostname"] = "Server" From 3e47ecf0c3f8477244571bbd29195da18b03fe29 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 1 Apr 2023 08:32:30 +0200 Subject: [PATCH 0932/2059] Add GSO/GRO/TSO/LRO & UFO configuration for each network interface --- .../luci-static/resources/tools/network.js | 15 +++++++++++++++ mptcp/files/etc/init.d/mptcp | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/luci-mod-network/htdocs/luci-static/resources/tools/network.js index 311242905..6f16713fe 100644 --- a/luci-mod-network/htdocs/luci-static/resources/tools/network.js +++ b/luci-mod-network/htdocs/luci-static/resources/tools/network.js @@ -625,6 +625,21 @@ return baseclass.extend({ o = this.replaceOption(s, 'devadvanced', form.Flag, 'autoneg', _('Autonegociation')); o.default = o.enabled; + o = this.replaceOption(s, 'devadvanced', form.Flag, 'gro', _('Generic Receive Offload (GRO)')); + o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'gso', _('Generic Segmentation Offload (GSO)')); + o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'tso', _('TCP Segmentation Offload (TSO)')); + o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'lro', _('Large Receive Offload (LRO)')); + o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', form.Flag, 'ufo', _('UDP Fragmentation Offload (UFO)')); + o.default = o.enabled; + o = this.replaceOption(s, 'devadvanced', form.Value, 'speed', _('Speed')); o.placeholder = dev ? dev.getSpeed() : ''; o.default = ''; diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 0e3a0b391..b444420f4 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -116,6 +116,23 @@ interface_multipath_settings() { uci -q set openmptcprouter.${config}.metric=$metric config_get mode "$config" multipath id=$metric + [ -n "$iface" ] && { + gro=$(uci -q network.${config}.gro) + [ "$gro" = "1" ] && ethtool -K $iface gro on 2>&1 >/dev/null + [ "$gro" = "0" ] && ethtool -K $iface gro on 2>&1 >/dev/null + gso=$(uci -q network.${config}.gso) + [ "$gso" = "1" ] && ethtool -K $iface gso on 2>&1 >/dev/null + [ "$gso" = "0" ] && ethtool -K $iface gso on 2>&1 >/dev/null + lro=$(uci -q network.${config}.lro) + [ "$lro" = "1" ] && ethtool -K $iface lro on 2>&1 >/dev/null + [ "$lro" = "0" ] && ethtool -K $iface lro on 2>&1 >/dev/null + ufo=$(uci -q network.${config}.ufo) + [ "$ufo" = "1" ] && ethtool -K $iface ufo on 2>&1 >/dev/null + [ "$ufo" = "0" ] && ethtool -K $iface ufo on 2>&1 >/dev/null + tso=$(uci -q network.${config}.tso) + [ "$tso" = "1" ] && ethtool -K $iface tso on 2>&1 >/dev/null + [ "$tso" = "0" ] && ethtool -K $iface tso on 2>&1 >/dev/null + } [ "$mode" = "" ] && { mode="$(uci -q get openmptcprouter.${config}.multipath)" [ -n "$mode" ] && uci -q set network.${config}.multipath="$mode" From e99265278330f377f7f4c7c4d8841e6982f31ab4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 2 Apr 2023 19:26:04 +0200 Subject: [PATCH 0933/2059] tun0 sqm autorate wizard config --- .../luasrc/controller/openmptcprouter.lua | 12 ++++++++ .../files/etc/uci-defaults/2040-omr-sqm | 28 +++++++++++++------ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index be6f36f31..ba87c23ee 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -258,6 +258,8 @@ function wizard_add() end -- Set interfaces settings + local downloadmax = 0 + local uploadmax = 0 local interfaces = luci.http.formvaluetable("intf") for intf, _ in pairs(interfaces) do local label = luci.http.formvalue("cbid.network.%s.label" % intf) or "" @@ -462,6 +464,7 @@ function wizard_add() end ucic:set("network",intf,"downloadspeed",downloadspeed) ucic:set("qos",intf,"download",math.ceil(downloadspeed*95/100)) + downloadmax = downloadmax + tonumber(downloadspeed) else ucic:delete("network",intf,"downloadspeed") ucic:set("sqm",intf,"download","0") @@ -477,6 +480,7 @@ function wizard_add() end ucic:set("network",intf,"uploadspeed",uploadspeed) ucic:set("qos",intf,"upload",math.ceil(uploadspeed*95/100)) + uploadmax = uploadmax + tonumber(uploadspeed) else ucic:delete("network",intf,"uploadspeed") ucic:set("sqm",intf,"upload","0") @@ -547,6 +551,14 @@ function wizard_add() vpn_intf = "bonding-omrvpn" ucic:set("network","omrvpn","proto","bonding") end + if downloadmax ~= 0 and uploadmax ~= 0 then + ucic:set("sqm","omrvpn","max_download",downloadmax) + ucic:set("sqm","omrvpn","max_upload",uploadmax) + ucic:set("sqm","omrvpn","download",math.ceil(downloadmax*50/100)) + ucic:set("sqm","omrvpn","min_download",math.ceil(downloadmax*8/100)) + ucic:set("sqm","omrvpn","upload",math.ceil(uploadmax*50/100)) + ucic:set("sqm","omrvpn","min_upload",math.ceil(uploadmax*8/100)) + end if vpn_intf ~= "" then ucic:set("network","omrvpn","device",vpn_intf) ucic:set("sqm","omrvpn","interface",vpn_intf) diff --git a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm index ace19d8a4..6d3a09a12 100755 --- a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm +++ b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm @@ -6,8 +6,8 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then uci -q batch <<-EOF >/dev/null delete sqm.eth1 set sqm.wan1=queue - set sqm.wan1.qdisc="fq_codel" - set sqm.wan1.script="simple.qos" + set sqm.wan1.qdisc="cake" + set sqm.wan1.script="piece_of_cake.qos" set sqm.wan1.qdisc_advanced='0' set sqm.wan1.linklayer='none' set sqm.wan1.enabled='1' @@ -19,8 +19,8 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan1.iqdisc_opts='autorate-ingress dual-dsthost' set sqm.wan1.eqdisc_opts='dual-srchost' set sqm.wan2=queue - set sqm.wan2.qdisc="fq_codel" - set sqm.wan2.script="simple.qos" + set sqm.wan2.qdisc="cake" + set sqm.wan2.script="piece_of_cake.qos" set sqm.wan2.qdisc_advanced='0' set sqm.wan2.linklayer='none' set sqm.wan2.enabled='1' @@ -37,8 +37,8 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then wan3="$(uci -q get network.wan3.device)" uci -q batch <<-EOF >/dev/null set sqm.wan3=queue - set sqm.wan3.qdisc="fq_codel" - set sqm.wan3.script="simple.qos" + set sqm.wan3.qdisc="cake" + set sqm.wan3.script="piece_of_cake.qos" set sqm.wan3.qdisc_advanced='0' set sqm.wan3.linklayer='none' set sqm.wan3.enabled='1' @@ -56,8 +56,8 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then wan4="$(uci -q get network.wan4.device)" uci -q batch <<-EOF >/dev/null set sqm.wan4=queue - set sqm.wan4.qdisc="fq_codel" - set sqm.wan4.script="simple.qos" + set sqm.wan4.qdisc="cake" + set sqm.wan4.script="piece_of_cake.qos" set sqm.wan4.qdisc_advanced='0' set sqm.wan4.linklayer='none' set sqm.wan4.enabled='1' @@ -74,7 +74,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then fi fi -if [ "$(uci -q get sqm.omrvpn)" = "" ]; then +if [ "$(uci -q get sqm.omrvpn)" = "" ] || [ -z "$(uci -q get sqm.omrvpn.delay_thr_ms)" ]; then uci -q batch <<-EOF >/dev/null set sqm.omrvpn=queue set sqm.omrvpn.qdisc="cake" @@ -89,6 +89,16 @@ if [ "$(uci -q get sqm.omrvpn)" = "" ]; then set sqm.omrvpn.verbosity='5' set sqm.omrvpn.overhead='40' set sqm.omrvpn.iqdisc_opts='autorate-ingress' + set sqm.omrvpn.delay_thr_ms='300' + set sqm.omrvpn.reflector_ping_interval_s='0.5' + set sqm.omrvpn.download='20000' + set sqm.omrvpn.min_download='1000' + set sqm.omrvpn.max_download='60000' + set sqm.omrvpn.upload='20000' + set sqm.omrvpn.min_upload='1000' + set sqm.omrvpn.max_upload='60000' + set sqm.omrvpn.enable_sleep_function='0' + set sqm.omrvpn.autorate='1' commit sqm EOF fi From d322ac87b8ddee0ce32d91a1d6f3829da832085b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Apr 2023 21:01:09 +0200 Subject: [PATCH 0934/2059] Update golang --- golang/golang-compiler.mk | 13 ++-- golang/golang-values.mk | 38 ++++++++---- golang/golang/Makefile | 62 +++++++++++++++---- ...-ARM-ARM64-only-if-gold-is-available.patch | 48 ++++++++++++++ 4 files changed, 130 insertions(+), 31 deletions(-) create mode 100644 golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch diff --git a/golang/golang-compiler.mk b/golang/golang-compiler.mk index e8b4b9156..b8c278568 100644 --- a/golang/golang-compiler.mk +++ b/golang/golang-compiler.mk @@ -27,7 +27,10 @@ define GoCompiler/Default/Make cd "$(1)/src" ; \ $(if $(2),GOROOT_FINAL="$(2)/lib/go-$(3)") \ $(4) \ - $(BASH) make.bash --no-banner ; \ + $(BASH) make.bash \ + $(if $(findstring s,$(OPENWRT_VERBOSE)),-v) \ + --no-banner \ + ; \ ) endef @@ -73,8 +76,10 @@ define GoCompiler/Default/Install/Bin $(INSTALL_BIN) -p "$(1)/bin/$(4)"/* "$(2)/lib/go-$(3)/bin/" endif - $(INSTALL_DIR) "$(2)/lib/go-$(3)/pkg" - $(CP) "$(1)/pkg/$(4)$(if $(5),_$(5))" "$(2)/lib/go-$(3)/pkg/" + if [ -d "$(1)/pkg/$(4)$(if $(5),_$(5))" ]; then \ + $(INSTALL_DIR) "$(2)/lib/go-$(3)/pkg" ; \ + $(CP) "$(1)/pkg/$(4)$(if $(5),_$(5))" "$(2)/lib/go-$(3)/pkg/" ; \ + fi $(INSTALL_DIR) "$(2)/lib/go-$(3)/pkg/tool/$(4)" $(INSTALL_BIN) -p "$(1)/pkg/tool/$(4)"/* "$(2)/lib/go-$(3)/pkg/tool/$(4)/" @@ -95,8 +100,6 @@ define GoCompiler/Default/Install/Doc $(call GoCompiler/Default/Install/make-dirs,$(2),$(3)) $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),doc) - $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),favicon.ico) - $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),robots.txt) endef # $(1) source go root diff --git a/golang/golang-values.mk b/golang/golang-values.mk index 34c9c1c65..3c170f308 100644 --- a/golang/golang-values.mk +++ b/golang/golang-values.mk @@ -29,7 +29,8 @@ unexport \ GOOS \ GOPATH \ GOROOT \ - GOTMPDIR + GOTMPDIR \ + GOWORK # Unmodified: # GOINSECURE # GOPRIVATE @@ -58,10 +59,16 @@ unexport \ unexport \ GOARM \ GO386 \ + GOAMD64 \ GOMIPS \ GOMIPS64 \ + GOPPC64 \ GOWASM +# Environment variables for use with code coverage: +unexport \ + GOCOVERDIR + # Special-purpose environment variables: unexport \ GCCGOTOOLDIR \ @@ -74,6 +81,7 @@ unexport \ # From https://pkg.go.dev/runtime#hdr-Environment_Variables unexport \ GOGC \ + GOMEMLIMIT \ GOMAXPROCS \ GORACE \ GOTRACEBACK @@ -86,13 +94,12 @@ unexport \ # CC_FOR_${GOOS}_${GOARCH} # CXX_FOR_${GOOS}_${GOARCH} -# From https://golang.org/doc/install/source#environment +# From https://go.dev/doc/install/source#environment unexport \ GOHOSTOS \ - GOHOSTARCH \ - GOPPC64 + GOHOSTARCH -# From https://golang.org/src/make.bash +# From https://go.dev/src/make.bash unexport \ GO_GCFLAGS \ GO_LDFLAGS \ @@ -101,16 +108,16 @@ unexport \ GOBUILDTIMELOGFILE \ GOROOT_BOOTSTRAP -# From https://golang.org/doc/go1.9#parallel-compile +# From https://go.dev/doc/go1.9#parallel-compile unexport \ GO19CONCURRENTCOMPILATION -# From https://golang.org/src/cmd/dist/build.go +# From https://go.dev/src/cmd/dist/build.go unexport \ BOOT_GO_GCFLAGS \ BOOT_GO_LDFLAGS -# From https://golang.org/src/cmd/dist/buildtool.go +# From https://go.dev/src/cmd/dist/buildtool.go unexport \ GOBOOTSTRAP_TOOLEXEC @@ -152,6 +159,9 @@ ifeq ($(GO_ARCH),386) # -fno-plt: causes "unexpected GOT reloc for non-dynamic symbol" errors GO_CFLAGS_TO_REMOVE:=-fno-plt +else ifeq ($(GO_ARCH),amd64) + GO_AMD64:=v1 + else ifeq ($(GO_ARCH),arm) GO_TARGET_FPU:=$(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE)))) @@ -183,6 +193,9 @@ else ifneq ($(filter $(GO_ARCH),mips64 mips64le),) GO_MIPS64:=softfloat endif +else ifeq ($(GO_ARCH),ppc64) + GO_PPC64:=power8 + endif @@ -193,12 +206,11 @@ GO_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mips64||mips64el||mipsel||pow # ASLR/PIE -# From https://golang.org/src/cmd/internal/sys/supported.go +# From https://go.dev/src/internal/platform/supported.go GO_PIE_SUPPORTED_OS_ARCH:= \ android_386 android_amd64 android_arm android_arm64 \ linux_386 linux_amd64 linux_arm linux_arm64 \ - \ - windows_386 windows_amd64 windows_arm \ + windows_386 windows_amd64 windows_arm windows_arm64 \ \ darwin_amd64 darwin_arm64 \ ios_amd64 ios_arm64 \ @@ -209,8 +221,8 @@ GO_PIE_SUPPORTED_OS_ARCH:= \ \ linux_ppc64le linux_riscv64 linux_s390x -# From https://golang.org/src/cmd/go/internal/work/init.go -go_pie_install_suffix=$(if $(filter $(1),aix_ppc64 windows_386 windows_amd64 windows_arm),,shared) +# From https://go.dev/src/cmd/go/internal/work/init.go +go_pie_install_suffix=$(if $(filter $(1),aix_ppc64 windows_386 windows_amd64 windows_arm windows_arm64),,shared) ifneq ($(filter $(GO_HOST_OS_ARCH),$(GO_PIE_SUPPORTED_OS_ARCH)),) GO_HOST_PIE_SUPPORTED:=1 diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 30979fe7c..6f6f28b24 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk -GO_VERSION_MAJOR_MINOR:=1.17 +GO_VERSION_MAJOR_MINOR:=1.20 GO_VERSION_PATCH:=3 PKG_NAME:=golang @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=705c64251e5b25d5d55ede1039c6aa22bea40a7a931d14c370339853643c3df0 +PKG_HASH:=e447b498cde50215c4f7619e5124b0fc4e25fb5d16ea47271c47f278e7aa763a PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause @@ -63,9 +63,11 @@ HOST_GO_VALID_OS_ARCH:= \ aix_ppc64 \ js_wasm \ \ + freebsd_riscv64 \ + \ linux_ppc64 linux_ppc64le \ linux_mips linux_mipsle linux_mips64 linux_mips64le \ - linux_riscv64 linux_s390x \ + linux_loong64 linux_riscv64 linux_s390x \ \ openbsd_mips64 @@ -86,6 +88,12 @@ BOOTSTRAP_GO_VALID_OS_ARCH:= \ solaris_amd64 \ windows_386 windows_amd64 +BOOTSTRAP_1_17_SOURCE:=go1.17.13.src.tar.gz +BOOTSTRAP_1_17_SOURCE_URL:=$(GO_SOURCE_URLS) +BOOTSTRAP_1_17_HASH:=a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd + +BOOTSTRAP_1_17_BUILD_DIR:=$(HOST_BUILD_DIR)/.go_bootstrap_1.17 + include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk include ../golang-compiler.mk @@ -94,6 +102,7 @@ include ../golang-package.mk PKG_UNPACK:=$(HOST_TAR) -C "$(PKG_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" HOST_UNPACK:=$(HOST_TAR) -C "$(HOST_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" BOOTSTRAP_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_SOURCE)" +BOOTSTRAP_1_17_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_1_17_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_1_17_SOURCE)" # don't strip ELF executables in test data RSTRIP:=: @@ -106,7 +115,7 @@ endif define Package/golang/Default $(call GoPackage/GoSubMenu) TITLE:=Go programming language - URL:=https://golang.org/ + URL:=https://go.dev/ DEPENDS:=$(GO_ARCH_DEPENDS) endef @@ -181,8 +190,7 @@ ifeq ($(BOOTSTRAP_ROOT_DIR),) $(eval $(call Download,golang-bootstrap)) define Bootstrap/Prepare - mkdir -p "$(BOOTSTRAP_BUILD_DIR)" - $(BOOTSTRAP_UNPACK) + mkdir -p "$(BOOTSTRAP_BUILD_DIR)" && $(BOOTSTRAP_UNPACK) ; endef Hooks/HostPrepare/Post+=Bootstrap/Prepare @@ -190,6 +198,23 @@ ifeq ($(BOOTSTRAP_ROOT_DIR),) endif +# Bootstrap 1.17 + +define Download/golang-bootstrap-1.17 + FILE:=$(BOOTSTRAP_1_17_SOURCE) + URL:=$(BOOTSTRAP_1_17_SOURCE_URL) + HASH:=$(BOOTSTRAP_1_17_HASH) +endef +$(eval $(call Download,golang-bootstrap-1.17)) + +define Bootstrap-1.17/Prepare + mkdir -p "$(BOOTSTRAP_1_17_BUILD_DIR)" && $(BOOTSTRAP_1_17_UNPACK) ; +endef +Hooks/HostPrepare/Post+=Bootstrap-1.17/Prepare + +$(eval $(call GoCompiler/AddProfile,Bootstrap-1.17,$(BOOTSTRAP_1_17_BUILD_DIR),,bootstrap-1.17,$(GO_HOST_OS_ARCH))) + + # Host ifeq ($(GO_HOST_PIE_SUPPORTED),1) @@ -202,23 +227,31 @@ endif $(eval $(call GoCompiler/AddProfile,Host,$(HOST_BUILD_DIR),$(HOST_GO_PREFIX),$(HOST_GO_VERSION_ID),$(GO_HOST_OS_ARCH),$(HOST_GO_INSTALL_SUFFIX))) HOST_GO_VARS= \ + GOHOSTARCH="$(GO_HOST_ARCH)" \ GOCACHE="$(GO_BUILD_CACHE_DIR)" \ GOENV=off \ CC="$(HOSTCC_NOCACHE)" \ CXX="$(HOSTCXX_NOCACHE)" -define Host/Compile +define Host/Configure $(call GoCompiler/Bootstrap/CheckHost,$(BOOTSTRAP_GO_VALID_OS_ARCH)) $(call GoCompiler/Host/CheckHost,$(HOST_GO_VALID_OS_ARCH)) mkdir -p "$(GO_BUILD_CACHE_DIR)" +endef +define Host/Compile $(call GoCompiler/Bootstrap/Make, \ $(HOST_GO_VARS) \ ) - $(call GoCompiler/Host/Make, \ + $(call GoCompiler/Bootstrap-1.17/Make, \ GOROOT_BOOTSTRAP="$(BOOTSTRAP_ROOT_DIR)" \ + $(HOST_GO_VARS) \ + ) + + $(call GoCompiler/Host/Make, \ + GOROOT_BOOTSTRAP="$(BOOTSTRAP_1_17_BUILD_DIR)" \ $(if $(HOST_GO_ENABLE_PIE),GO_LDFLAGS="-buildmode pie") \ $(HOST_GO_VARS) \ ) @@ -262,14 +295,16 @@ $(eval $(call GoCompiler/AddProfile,Package,$(PKG_BUILD_DIR),$(PKG_GO_PREFIX),$( PKG_GO_ZBOOTSTRAP_MODS:= \ s/defaultGO386 = `[^`]*`/defaultGO386 = `$(or $(GO_386),sse2)`/; \ + s/defaultGOAMD64 = `[^`]*`/defaultGOAMD64 = `$(or $(GO_AMD64),v1)`/; \ s/defaultGOARM = `[^`]*`/defaultGOARM = `$(or $(GO_ARM),5)`/; \ s/defaultGOMIPS = `[^`]*`/defaultGOMIPS = `$(or $(GO_MIPS),hardfloat)`/; \ s/defaultGOMIPS64 = `[^`]*`/defaultGOMIPS64 = `$(or $(GO_MIPS64),hardfloat)`/; \ - s/defaultGOPPC64 = `[^`]*`/defaultGOPPC64 = `power8`/; + s/defaultGOPPC64 = `[^`]*`/defaultGOPPC64 = `$(or $(GO_PPC64),power8)`/; PKG_GO_ZBOOTSTRAP_PATH:=$(PKG_BUILD_DIR)/src/internal/buildcfg/zbootstrap.go PKG_GO_VARS= \ + GOHOSTARCH="$(GO_HOST_ARCH)" \ GOCACHE="$(GO_BUILD_CACHE_DIR)" \ GOENV=off \ GO_GCC_HELPER_PATH="$$$$PATH" \ @@ -290,18 +325,19 @@ PKG_GO_LDFLAGS= \ -extldflags '$(patsubst -z%,-Wl$(comma)-z$(comma)%,$(TARGET_LDFLAGS))' \ $(if $(CONFIG_NO_STRIP)$(CONFIG_DEBUG),,-s -w) -# setting -trimpath is not necessary here because the paths inside the -# compiler binary are relative to GOROOT_FINAL (PKG_GO_ROOT), which is -# static / not dependent on the build environment PKG_GO_INSTALL_ARGS= \ + -buildvcs=false \ + -trimpath \ -ldflags "all=$(PKG_GO_LDFLAGS)" \ $(if $(PKG_GO_GCFLAGS),-gcflags "all=$(PKG_GO_GCFLAGS)") \ $(if $(PKG_GO_ASMFLAGS),-asmflags "all=$(PKG_GO_ASMFLAGS)") \ $(if $(filter $(GO_PKG_ENABLE_PIE),1),-buildmode pie) -define Build/Compile +define Build/Configure mkdir -p "$(GO_BUILD_CACHE_DIR)" +endef +define Build/Compile @echo "Building target Go first stage" $(call GoCompiler/Package/Make, \ diff --git a/golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch b/golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch new file mode 100644 index 000000000..683480442 --- /dev/null +++ b/golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch @@ -0,0 +1,48 @@ +From 5ccf9f47bf4f5ba53e0ab7338a7fd4626714cfb2 Mon Sep 17 00:00:00 2001 +From: Jeffery To +Date: Tue, 23 Nov 2021 15:05:37 +0800 +Subject: [PATCH] cmd/link: use gold on ARM/ARM64 only if gold is available + +COPY relocation handling on ARM/ARM64 has been fixed in recent versions +of the GNU linker. This switches to gold only if gold is available. + +Fixes #22040. +--- + src/cmd/link/internal/ld/lib.go | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -1535,25 +1535,20 @@ func (ctxt *Link) hostlink() { + } + + if ctxt.Arch.InFamily(sys.ARM, sys.ARM64) && buildcfg.GOOS == "linux" { +- // On ARM, the GNU linker will generate COPY relocations +- // even with -znocopyreloc set. ++ // On ARM, older versions of the GNU linker will generate ++ // COPY relocations even with -znocopyreloc set. + // https://sourceware.org/bugzilla/show_bug.cgi?id=19962 + // +- // On ARM64, the GNU linker will fail instead of +- // generating COPY relocations. ++ // On ARM64, older versions of the GNU linker will fail ++ // instead of generating COPY relocations. + // +- // In both cases, switch to gold. +- altLinker = "gold" +- +- // If gold is not installed, gcc will silently switch +- // back to ld.bfd. So we parse the version information +- // and provide a useful error if gold is missing. ++ // In both cases, switch to gold if gold is available. + name, args := flagExtld[0], flagExtld[1:] + args = append(args, "-fuse-ld=gold", "-Wl,--version") + cmd := exec.Command(name, args...) + if out, err := cmd.CombinedOutput(); err == nil { +- if !bytes.Contains(out, []byte("GNU gold")) { +- log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out) ++ if bytes.Contains(out, []byte("GNU gold")) { ++ altLinker = "gold" + } + } + } From 7eaf573d6049dc09c5eba22aeb0a311afcd23bc8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Apr 2023 21:01:25 +0200 Subject: [PATCH 0935/2059] Update v2ray --- v2ray-core/Makefile | 332 +++++++++----------------------------------- 1 file changed, 67 insertions(+), 265 deletions(-) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 08a9d018d..8fbc65d69 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -1,309 +1,111 @@ +# SPDX-License-Identifier: GPL-3.0-only # -# Copyright (C) 2019 Xingwang Liao -# Copyright (C) 2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# +# Copyright (C) 2021-2022 ImmortalWrt.org include $(TOPDIR)/rules.mk PKG_NAME:=v2ray-core -PKG_VERSION:=4.45.2 +PKG_VERSION:=5.4.1 PKG_RELEASE:=1 -#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE:=v$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/refs/tags/ -PKG_HASH:=7a126bac7df32f627f34331778cb39ac99db18d7edcd45628db06e123fa0694b +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=e208bca255c4689a30104e965039d73fa138a7a6e902f820cff94b5b772b042b PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE -PKG_MAINTAINER:=Yannick Chabanois - -PKG_CONFIG_DEPENDS := \ - CONFIG_V2RAY_JSON_V2CTL \ - CONFIG_V2RAY_JSON_INTERNAL \ - CONFIG_V2RAY_JSON_NONE \ - CONFIG_V2RAY_EXCLUDE_V2CTL \ - CONFIG_V2RAY_EXCLUDE_ASSETS \ - CONFIG_V2RAY_COMPRESS_UPX \ - CONFIG_V2RAY_DISABLE_NONE \ - CONFIG_V2RAY_DISABLE_CUSTOM \ - CONFIG_V2RAY_DISABLE_DNS \ - CONFIG_V2RAY_DISABLE_LOG \ - CONFIG_V2RAY_DISABLE_POLICY \ - CONFIG_V2RAY_DISABLE_REVERSE \ - CONFIG_V2RAY_DISABLE_ROUTING \ - CONFIG_V2RAY_DISABLE_STATISTICS \ - CONFIG_V2RAY_DISABLE_BLACKHOLE_PROTO \ - CONFIG_V2RAY_DISABLE_DNS_PROXY \ - CONFIG_V2RAY_DISABLE_DOKODEMO_PROTO \ - CONFIG_V2RAY_DISABLE_FREEDOM_PROTO \ - CONFIG_V2RAY_DISABLE_MTPROTO_PROXY \ - CONFIG_V2RAY_DISABLE_HTTP_PROTO \ - CONFIG_V2RAY_DISABLE_SHADOWSOCKS_PROTO \ - CONFIG_V2RAY_DISABLE_SOCKS_PROTO \ - CONFIG_V2RAY_DISABLE_VMESS_PROTO \ - CONFIG_V2RAY_DISABLE_TCP_TRANS \ - CONFIG_V2RAY_DISABLE_MKCP_TRANS \ - CONFIG_V2RAY_DISABLE_WEBSOCKET_TRANS \ - CONFIG_V2RAY_DISABLE_HTTP2_TRANS \ - CONFIG_V2RAY_DISABLE_DOMAIN_SOCKET_TRANS \ - CONFIG_V2RAY_DISABLE_QUIC_TRANS +PKG_MAINTAINER:=Tianling Shen PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 PKG_USE_MIPS16:=0 -GO_PKG:=github.com/v2fly/v2ray-core/v4 -GO_PKG_LDFLAGS:=-s -w +GO_PKG:=github.com/v2fly/v2ray-core/v5 +GO_PKG_BUILD_PKG:=$(GO_PKG)/main +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG).build=OpenWrt \ + $(GO_PKG).version=$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk -#include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk include $(TOPDIR)/feeds/openmptcprouter/golang/golang-package.mk -define Package/v2ray-core - TITLE:=A platform for building proxies - URL:=https://www.v2fly.org +define Package/v2ray/template + TITLE:=A platform for building proxies to bypass network restrictions SECTION:=net CATEGORY:=Network - SUBMENU:=Project V - DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +protobuf + URL:=https://www.v2fly.org endef -define Package/v2ray-core/config - source "$(SOURCE)/Config.in" +define Package/v2ray-core + $(call Package/v2ray/template) + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +endef + +define Package/v2ray-example + $(call Package/v2ray/template) + TITLE+= (example configs) + DEPENDS:=v2ray-core + PKGARCH:=all +endef + +define Package/v2ray-extra + $(call Package/v2ray/template) + TITLE+= (extra resources) + DEPENDS:=v2ray-core + PKGARCH:=all +endef + +define Package/v2ray/description + Project V is a set of network tools that help you to build your own computer network. + It secures your network connections and thus protects your privacy. endef define Package/v2ray-core/description -Project V is a set of network tools that help you to build your own computer network. -It secures your network connections and thus protects your privacy. - - This package contains v2ray, v2ctl and v2ray-assets. + $(call Package/v2ray/description) endef -V2RAY_SED_ARGS:= +define Package/v2ray-example/description + $(call Package/v2ray/description) -ifeq ($(CONFIG_V2RAY_JSON_INTERNAL),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/main\/json"/\/\/ &/; \ - /\/\/ _ "github.com\/v2fly\/v2ray-core\/v4\/main\/jsonem"/s/\/\/ //; -else ifeq ($(CONFIG_V2RAY_JSON_NONE),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/main\/json"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_CUSTOM),y) - -ifeq ($(CONFIG_V2RAY_DISABLE_DNS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/dns"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_LOG),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/log"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/log\/command"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_POLICY),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/policy"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_REVERSE),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/reverse"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_ROUTING),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/router"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_STATISTICS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/stats"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/app\/stats\/command"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_BLACKHOLE_PROTO),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/blackhole"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_DNS_PROXY),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/dns"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_DOKODEMO_PROTO),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/dokodemo"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_FREEDOM_PROTO),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/freedom"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_MTPROTO_PROXY),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/mtproto"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_HTTP_PROTO),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/http"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_SHADOWSOCKS_PROTO),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/shadowsocks"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_SOCKS_PROTO),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/socks"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_VMESS_PROTO),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/vmess\/inbound"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/proxy\/vmess\/outbound"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_TCP_TRANS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/tcp"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_MKCP_TRANS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/kcp"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_WEBSOCKET_TRANS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/websocket"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_HTTP2_TRANS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/http"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/headers\/http"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_DOMAIN_SOCKET_TRANS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/domainsocket"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_QUIC_TRANS),y) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/quic"/\/\/ &/; -endif - -ifeq ($(CONFIG_V2RAY_DISABLE_MKCP_TRANS)$(CONFIG_V2RAY_DISABLE_QUIC_TRANS),yy) -V2RAY_SED_ARGS += \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/headers\/noop"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/headers\/srtp"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/headers\/tls"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/headers\/utp"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/headers\/wechat"/\/\/ &/; \ - s/_ "github.com\/v2fly\/v2ray-core\/v4\/transport\/internet\/headers\/wireguard"/\/\/ &/; -endif - -endif - -GEOIP_VER:=latest -GEOIP_FILE:=geoip-$(GEOIP_VER).dat - -define Download/geoip.dat - URL:=https://github.com/v2ray/geoip/releases/$(GEOIP_VER)/download - URL_FILE:=geoip.dat - FILE:=$(GEOIP_FILE) - HASH:=skip + This includes example configuration files for v2ray-core. endef -GEOSITE_VER:=latest -GEOSITE_FILE:=geosite-$(GEOSITE_VER).dat +define Package/v2ray-extra/description + $(call Package/v2ray/description) -define Download/geosite.dat - URL:=https://github.com/v2ray/domain-list-community/releases/$(GEOSITE_VER)/download - URL_FILE:=dlc.dat - FILE:=$(GEOSITE_FILE) - HASH:=skip + This includes extra resources for v2ray-core. endef -define Build/Prepare - $(Build/Prepare/Default) - -ifneq ($(CONFIG_V2RAY_EXCLUDE_ASSETS),y) - # move file to make sure download new file every build - mv -f $(DL_DIR)/$(GEOIP_FILE) $(PKG_BUILD_DIR)/release/config/geoip.dat - mv -f $(DL_DIR)/$(GEOSITE_FILE) $(PKG_BUILD_DIR)/release/config/geosite.dat -endif - - ( \ - sed -i \ - 's/\(version[[:space:]]*=[[:space:]]*"\).*\("\)/\1$(PKG_VERSION)\2/; \ - s/\(build[[:space:]]*=[[:space:]]*"\).*\("\)/\1OpenWrt R$(PKG_RELEASE)\2/' \ - $(PKG_BUILD_DIR)/core.go ; \ - ) -ifneq ($(V2RAY_SED_ARGS),) - ( \ - sed -i \ - '$(V2RAY_SED_ARGS)' \ - $(PKG_BUILD_DIR)/main/distro/all/all.go ; \ - ) -endif -endef - -define Build/Compile - $(eval GO_PKG_BUILD_PKG:=$(GO_PKG)/main) - $(call GoPackage/Build/Compile) - mv -f $(GO_PKG_BUILD_BIN_DIR)/main $(GO_PKG_BUILD_BIN_DIR)/v2ray - -ifeq ($(CONFIG_V2RAY_COMPRESS_UPX),y) - upx --ultra-brute $(GO_PKG_BUILD_BIN_DIR)/v2ray -endif - -ifneq ($(CONFIG_V2RAY_EXCLUDE_V2CTL),y) - $(eval GO_PKG_BUILD_PKG:=$(GO_PKG)/infra/control/main) - $(call GoPackage/Build/Compile) - mv -f $(GO_PKG_BUILD_BIN_DIR)/main $(GO_PKG_BUILD_BIN_DIR)/v2ctl - -ifeq ($(CONFIG_V2RAY_COMPRESS_UPX),y) - upx --ultra-brute $(GO_PKG_BUILD_BIN_DIR)/v2ctl -endif -endif +define Package/v2ray-core/conffiles +/etc/config/v2ray +/etc/v2ray/ endef define Package/v2ray-core/install $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + $(INSTALL_DIR) $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/main $(1)/usr/bin/v2ray - $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_DIR) $(1)/etc/v2ray/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/config.json $(1)/etc/v2ray/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/v2ray $(1)/usr/bin - $(CP) ./files/* $(1)/ - -ifneq ($(CONFIG_V2RAY_EXCLUDE_V2CTL),y) - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/v2ctl $(1)/usr/bin -endif - -ifneq ($(CONFIG_V2RAY_EXCLUDE_ASSETS),y) - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/release/config/{geoip,geosite}.dat \ - $(1)/usr/bin -endif +# $(INSTALL_DIR) $(1)/etc/config/ +# $(INSTALL_CONF) $(CURDIR)/files/v2ray.conf $(1)/etc/config/v2ray +# $(INSTALL_DIR) $(1)/etc/init.d/ +# $(INSTALL_BIN) $(CURDIR)/files/v2ray.init $(1)/etc/init.d/v2ray endef -ifneq ($(CONFIG_V2RAY_EXCLUDE_ASSETS),y) -$(eval $(call Download,geoip.dat)) -$(eval $(call Download,geosite.dat)) -endif +define Package/v2ray-example/install + $(INSTALL_DIR) $(1)/etc/v2ray/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/vpoint_socks_vmess.json $(1)/etc/v2ray/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/vpoint_vmess_freedom.json $(1)/etc/v2ray/ +endef + +define Package/v2ray-extra/install + $(INSTALL_DIR) $(1)/usr/share/v2ray/ + $(CP) $(PKG_BUILD_DIR)/release/extra/* $(1)/usr/share/v2ray/ +endef -$(eval $(call GoBinPackage,v2ray-core)) $(eval $(call BuildPackage,v2ray-core)) +$(eval $(call BuildPackage,v2ray-example)) +$(eval $(call BuildPackage,v2ray-extra)) From 997d74cba8958493aa09d954dddde7aa2cc74b2a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Apr 2023 21:01:59 +0200 Subject: [PATCH 0936/2059] Remove v2ray-plugin --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 6f0ec53b9..57aa34c3d 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -69,7 +69,7 @@ MY_DEPENDS := \ ca-bundle openssl-util \ dejavu-fonts-ttf-DejaVuSerif dejavu-fonts-ttf-DejaVuSerif-Bold dejavu-fonts-ttf-DejaVuSerif-Italic dejavu-fonts-ttf-DejaVuSerif-BoldItalic \ luci-app-snmpd \ - iputils-tracepath !TARGET_mvebu:v2ray-plugin netcat simple-obfs \ + iputils-tracepath netcat simple-obfs \ (TARGET_x86||TARGET_x86_64):kmod-iwlwifi (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl1000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl100 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl105 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl135 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl2000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl2030 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl3160 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl3168 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl5000 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl5150 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2a (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6000g2b (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl6050 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7260 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7265 (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl7265d (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl8260c (TARGET_x86||TARGET_x86_64):iwlwifi-firmware-iwl8265 \ (TARGET_x86||TARGET_x86_64):kmod-e1000 (TARGET_x86||TARGET_x86_64):kmod-e1000e (TARGET_x86||TARGET_x86_64):kmod-igb (TARGET_x86||TARGET_x86_64):kmod-ne2k-pci (TARGET_x86||TARGET_x86_64):kmod-r8169 (TARGET_x86||TARGET_x86_64):kmod-8139too (TARGET_x86||TARGET_x86_64):kmod-bnx2 \ TARGET_mvebu:kmod-mwlwifi TARGET_mvebu:mwlwifi-firmware-88w8864 TARGET_mvebu:mwlwifi-firmware-88w8897 TARGET_mvebu:mwlwifi-firmware-88w8964 TARGET_mvebu:mwlwifi-firmware-88w8997 \ From 0133a320e232ebae1e9fdcb408621af9f408d324 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Apr 2023 21:02:45 +0200 Subject: [PATCH 0937/2059] Update v2ray-plugin --- shadowsocks-v2ray-plugin/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-v2ray-plugin/Makefile b/shadowsocks-v2ray-plugin/Makefile index 5cc81054e..f4cb4c2dc 100644 --- a/shadowsocks-v2ray-plugin/Makefile +++ b/shadowsocks-v2ray-plugin/Makefile @@ -15,7 +15,7 @@ PKG_SOURCE_PROTO:=git #PKG_SOURCE_URL:=https://github.com/shadowsocks/v2ray-plugin.git PKG_SOURCE_URL:=https://github.com/teddysun/v2ray-plugin.git #PKG_SOURCE_VERSION:=63a74bef9e9f639bc199255db9d452d96f01d11a -PKG_SOURCE_VERSION:=5cafcf9a0ae316cb268120eb1994adf5255eb7f0 +PKG_SOURCE_VERSION:=87488f188689234956407631e728faae143f3e65 PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 From 9df5d2048e97acc4718b9f8b9dcbda966f2b44fd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 22 Apr 2023 08:08:34 +0200 Subject: [PATCH 0938/2059] ndpi-netfilter not available for kernel 6.1 other than x86_64 for now --- luci-app-omr-bypass/Makefile | 2 +- ndpi-netfilter2/Makefile | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index cbce20358..876d61e14 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains -LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +iptables-mod-ndpi +iptables-mod-extra +kmod-ipt-ndpi +iptables +LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables PKG_LICENSE:=GPLv3 diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 23baad9a3..a4216acdb 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 -PKG_REV:=845399a0acb423e940c67a881a10f30f4c6a5fb7 +PKG_REV:=2fc0c86e58d56c8f9c5da3883a09732fc902e5e7 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git @@ -31,7 +31,7 @@ define Package/iptables-mod-ndpi TITLE:=ndpi successor of OpenDPI URL:=http://www.ntop.org/products/ndpi/ # DEPENDS:=+iptables +iptables-mod-conntrack-extra +kmod-ipt-ndpi +libpcap - DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap + DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) MAINTAINER:=Ycarus (Yannick Chabanois) endef @@ -51,13 +51,15 @@ MAKE_FLAGS += \ KERNEL_RELEASE="$(KERNEL_PATCHVER)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ CC="$(TARGET_CC)" \ - NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter +#MAKE_FLAGS += \ +# NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter define Build/Compile (cd $(PKG_BUILD_DIR)/src/lib &&\ gcc -g -O2 -fPIC -DPIC -DNDPI_LIB_COMPILATION -I../../src/include/ -I../../src/lib/third_party/include/ ndpi_network_list_compile.c -o ndpi_network_list_compile &&\ ./ndpi_network_list_compile -o ndpi_network_list.c.inc ndpi_network_list_*.yaml) - $(MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter +# $(MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter + +$(KERNEL_MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter endef define Package/iptables-mod-ndpi/install @@ -68,11 +70,16 @@ endef define KernelPackage/ipt-ndpi SUBMENU:=Netfilter Extensions TITLE:= nDPI net netfilter module - DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap + DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) KCONFIG:=CONFIG_NF_CONNTRACK_LABELS=y \ CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y FILES:= $(PKG_BUILD_DIR)/ndpi-netfilter/src/xt_ndpi.ko AUTOLOAD:=$(call AutoProbe,xt_ndpi) + KCONFIG:=\ + CONFIG_LIVEPATCH=y \ + CONFIG_NF_CONNTRACK=y \ + CONFIG_NF_CONNTRACK_LABELS=y \ + CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y endef $(eval $(call BuildPackage,iptables-mod-ndpi)) From e752f6369dddcfedc8fd2e648c4f80152525267a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 22 Apr 2023 08:09:36 +0200 Subject: [PATCH 0939/2059] Add qnap-301w image compilation --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0c8fde96e..4171623cc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx, r5s] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx, r5s, qnap-301w] OMR_KERNEL: [5.4, 5.15, 6.1] runs-on: ubuntu-latest continue-on-error: true From 1de632d00033e8cef1841580a0caff7fcb07cb25 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 22 Apr 2023 08:10:10 +0200 Subject: [PATCH 0940/2059] Force offloading to be off --- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 5bab51455..f746af284 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -5,6 +5,8 @@ uci -q batch <<-EOF >/dev/null set firewall.@defaults[0].input='REJECT' set firewall.@defaults[0].output='REJECT' set firewall.@defaults[0].forward='REJECT' + set firewall.@defaults[0].flow_offloading='0' + set firewall.@defaults[0].flow_offloading_hw='0' EOF From 4e8a988a4d3443c8271c34908b6086dfa0d11690 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 23 Apr 2023 08:24:03 +0200 Subject: [PATCH 0941/2059] Add python3-ellftool package --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4171623cc..73ea5f1b7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: - name: Prepare run: | sudo apt-get update - sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc-s1 libc6-dev-i386 subversion flex uglifyjs git-core gcc-multilib p7zip p7zip-full msmtp libssl-dev texinfo libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint device-tree-compiler + sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc-s1 libc6-dev-i386 subversion flex uglifyjs git-core gcc-multilib p7zip p7zip-full msmtp libssl-dev texinfo libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint device-tree-compiler python3-pyelftools - name: Free disk space run: | df -h From adc1ba3d5d61a502e5eed376f05538561bc33879 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 23 Apr 2023 20:22:30 +0200 Subject: [PATCH 0942/2059] Should fix #2825 --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 57aa34c3d..1e011f099 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -82,7 +82,7 @@ MY_DEPENDS := \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ - (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils + (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From 368534b006903ac51224fd2157155242900ca626 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 23 Apr 2023 20:23:11 +0200 Subject: [PATCH 0943/2059] Fix #2824 --- mptcp/files/etc/init.d/mptcp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index b444420f4..f870963e3 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -117,19 +117,19 @@ interface_multipath_settings() { config_get mode "$config" multipath id=$metric [ -n "$iface" ] && { - gro=$(uci -q network.${config}.gro) + gro=$(uci -q get network.${config}.gro) [ "$gro" = "1" ] && ethtool -K $iface gro on 2>&1 >/dev/null [ "$gro" = "0" ] && ethtool -K $iface gro on 2>&1 >/dev/null - gso=$(uci -q network.${config}.gso) + gso=$(uci -q get network.${config}.gso) [ "$gso" = "1" ] && ethtool -K $iface gso on 2>&1 >/dev/null [ "$gso" = "0" ] && ethtool -K $iface gso on 2>&1 >/dev/null - lro=$(uci -q network.${config}.lro) + lro=$(uci -q get network.${config}.lro) [ "$lro" = "1" ] && ethtool -K $iface lro on 2>&1 >/dev/null [ "$lro" = "0" ] && ethtool -K $iface lro on 2>&1 >/dev/null - ufo=$(uci -q network.${config}.ufo) + ufo=$(uci -q get network.${config}.ufo) [ "$ufo" = "1" ] && ethtool -K $iface ufo on 2>&1 >/dev/null [ "$ufo" = "0" ] && ethtool -K $iface ufo on 2>&1 >/dev/null - tso=$(uci -q network.${config}.tso) + tso=$(uci -q get network.${config}.tso) [ "$tso" = "1" ] && ethtool -K $iface tso on 2>&1 >/dev/null [ "$tso" = "0" ] && ethtool -K $iface tso on 2>&1 >/dev/null } From fc6a935c0c2eb6df7ee10ae6d8ad86a1e30a5b46 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 24 Apr 2023 08:30:04 +0200 Subject: [PATCH 0944/2059] Fix v2ray --- v2ray-core/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 8fbc65d69..08d21ae81 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -89,6 +89,7 @@ define Package/v2ray-core/install $(INSTALL_DIR) $(1)/etc/v2ray/ $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/config.json $(1)/etc/v2ray/ + $(CP) ./files/* $(1)/ # $(INSTALL_DIR) $(1)/etc/config/ # $(INSTALL_CONF) $(CURDIR)/files/v2ray.conf $(1)/etc/config/v2ray # $(INSTALL_DIR) $(1)/etc/init.d/ From ccead6d6560e9fc068bea5f9b9ee09e63284ee2e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 24 Apr 2023 08:46:26 +0200 Subject: [PATCH 0945/2059] Disable aquantia on 5.15 and 6.1 kernel --- aquantia/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aquantia/Makefile b/aquantia/Makefile index dc8c8f46a..98b3f970c 100644 --- a/aquantia/Makefile +++ b/aquantia/Makefile @@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/phy-aquantia SUBMENU:=Network Devices TITLE:=aQuantia device support - DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-hwmon-core +kmod-libphy + DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 @KERNEL_5_4 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-hwmon-core +kmod-libphy KCONFIG:=CONFIG_AQUANTIA_PHY HIDDEN:=1 FILES:=$(LINUX_DIR)/drivers/net/phy/aquantia.ko From fceb367f729a3adf686f4ef135744bae028fc871 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 24 Apr 2023 19:45:16 +0200 Subject: [PATCH 0946/2059] Fix aquantia only for 5.4 --- aquantia/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aquantia/Makefile b/aquantia/Makefile index 98b3f970c..f99bb0c90 100644 --- a/aquantia/Makefile +++ b/aquantia/Makefile @@ -24,7 +24,7 @@ endef define KernelPackage/atlantic SUBMENU:=Network Devices TITLE:=aQuantia AQtion(tm) Support - DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-phy-aquantia + DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 @KERNEL_5_4 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-phy-aquantia KCONFIG:=CONFIG_AQTION FILES:=$(LINUX_DIR)/drivers/net/ethernet/aquantia/atlantic/atlantic.ko AUTOLOAD:=$(call AutoProbe,atlantic) From ab0adc0ddd09b5d0cd5bbdce624797df41045a0f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 24 Apr 2023 19:54:37 +0200 Subject: [PATCH 0947/2059] Update openmptcprouter-full --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 1e011f099..dd49c905b 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -81,7 +81,7 @@ MY_DEPENDS := \ !TARGET_mvebu:luci-app-mlvpn !TARGET_mvebu:mlvpn 464xlat kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ - luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic \ + luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From 2ac1c905a9d89b06ac83cec0c3a3de38d5a2f5ff Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 25 Apr 2023 19:44:04 +0200 Subject: [PATCH 0948/2059] Fix ndpi-netfilter2 compilation --- ndpi-netfilter2/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index a4216acdb..13592c178 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -44,15 +44,15 @@ CONFIGURE_ARGS += --with-pic MAKE_PATH:=ndpi-netfilter -MAKE_FLAGS += \ - KERNEL_DIR="$(LINUX_DIR)" \ - MODULES_DIR="$(TARGET_MODULES_DIR)" \ - ARCH="$(LINUX_KARCH)" \ - KERNEL_RELEASE="$(KERNEL_PATCHVER)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CC="$(TARGET_CC)" \ #MAKE_FLAGS += \ -# NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter +# KERNEL_DIR="$(LINUX_DIR)" \ +# MODULES_DIR="$(TARGET_MODULES_DIR)" \ +# ARCH="$(LINUX_KARCH)" \ +# KERNEL_RELEASE="$(KERNEL_PATCHVER)" \ +# CROSS_COMPILE="$(TARGET_CROSS)" \ +# CC="$(TARGET_CC)" \ +MAKE_FLAGS += \ + NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter define Build/Compile (cd $(PKG_BUILD_DIR)/src/lib &&\ From 2d4462794b6990721209e18544221766786a5055 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 25 Apr 2023 21:40:22 +0200 Subject: [PATCH 0949/2059] Fix v2ray init --- v2ray-core/files/etc/init.d/v2ray | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index e0af11346..5eac8c265 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -1972,7 +1972,7 @@ start_instance() { return 1 fi - if ! ( eval "$v2ray_file --test --config=\"$config_file\" >/dev/null 2>&1" ) ; then + if ! ( eval "$v2ray_file test -config \"$config_file\" >/dev/null 2>&1" ) ; then _err "Validate config file failed: $config_file" return 1 fi @@ -2059,7 +2059,8 @@ start_instance() { procd_open_instance "$NAME.$section" procd_set_param command "$v2ray_file" - procd_append_param command "--config=$temp_config" + procd_append_param command run + procd_append_param command -config "$temp_config" procd_set_param respawn if [ -n "$asset_location" ] && [ -d "$asset_location" ] ; then From f4981b7c5902b065cbd06bdca4a8e085567c389c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 25 Apr 2023 21:40:44 +0200 Subject: [PATCH 0950/2059] Fix omr-bypass start --- .../root/etc/init.d/omr-bypass | 86 +++++++++++++------ 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 0c3ba4932..ebab9e1b5 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -65,8 +65,13 @@ _bypass_domains() { config_get domain $1 name config_get intf $1 interface config_get enabled $1 enabled + config_get noipv6 $1 noipv6 + config_get family $1 family + [ -z "$intf" ] && intf="all" [ "$enabled" = "0" ] && return [ -z "$domain" ] && return + [ -z "$family" ] && family="ipv4ipv6" + [ -z "$noipv6" ] && noipv6="0" if [ "$(echo $domain | grep '\.$')" != "" ] || [ "$(echo $domain | grep '\.\*$')" != "" ]; then tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` domain="$(echo '"$domain"' | sed 's:*::')" @@ -91,16 +96,18 @@ _bypass_domains() { | grep $domain `# grep, only keep wanted domain` \ | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate for validdomain in $domainlist; do - _bypass_domain $validdomain $intf + _bypass_domain $validdomain $intf $family $noipv6 done else - _bypass_domain $domain $intf + _bypass_domain $domain $intf $family $noipv6 fi } _bypass_domain() { local domain=$1 local intf=$2 + local family=$3 + local noipv6=$4 intf=$(echo $intf | sed -e 's/\./_/') [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return [ -z "$intf" ] && intf="all" @@ -120,18 +127,34 @@ _bypass_domain() { fi fi if [ "$(uci -q get dhcp.@dnsmasq[0].ipset | grep /$domain/)" = "" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + if [ "$family" = "ipv4ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + elif [ "$family" = "ipv4" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf" + elif [ "$family" = "ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr6_dst_bypass_$intf" + fi add_domains="true" else dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g') for dnsipset in $dnsmasqipset; do if [ "$(echo $dnsipset | cut -d/ -f2)" = "$domain" ]; then uci -q del_list dhcp.@dnsmasq[0].ipset=$dnsipset - uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + if [ "$family" = "ipv4ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + elif [ "$family" = "ipv4" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf" + elif [ "$family" = "ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr6_dst_bypass_$intf" + fi add_domains="true" fi done fi + if [ "$(uci -q get dhcp.@dnsmasq[0].noipv6 | grep /$domain/)" = "" ] && [ "$noipv6" = "1" ]; then + uci -q add_list dhcp.@dnsmasq[0].noipv6="$domain" + fi + #logger -t "omr-bypass" "Get IPs of $domain... Done" fi } @@ -358,7 +381,11 @@ _bypass_proto() { config_get intf $1 interface config_get enabled $1 enabled config_get ndpi $1 ndpi + config_get noipv6 $1 noipv6 + config_get family $1 family [ "$enabled" = "0" ] && return + [ -z "$noipv6" ] && noipv6="0" + [ -z "$family" ] && family="ipv4ipv6" intf=$(echo $intf | sed -e 's/\./_/') [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" @@ -367,13 +394,15 @@ _bypass_proto() { [ -z "$proto" ] && return if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ] && [ "$ndpi" != "0" ]; then if [ "$intf" = "all" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 - -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 + -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 @@ -382,13 +411,15 @@ _bypass_proto() { EOF fi else - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid - -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid + -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid @@ -428,10 +459,10 @@ _bypass_proto() { | grep $domain `# grep, only keep wanted domain` \ | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate for validdomain in $domainlist; do - _bypass_domain $validdomain $intf + _bypass_domain $validdomain $intf $family $noipv6 done else - _bypass_domain $domain $intf + _bypass_domain $domain $intf $family $noipv6 fi fi done @@ -593,9 +624,12 @@ _intf_rule() { COMMIT EOF fi - config_load shadowsocks-libev - config_foreach _intf_rule_ss_rules ss_rules - _intf_rule_v2ray_rules + if [ "$(uci -q openmptcprouter.settings.proxy)" = "shadowsocks" ]; then + config_load shadowsocks-libev + config_foreach _intf_rule_ss_rules ss_rules + else + _intf_rule_v2ray_rules + fi uci -q set omr-bypass.$intf=interface uci -q set omr-bypass.$intf.id=$count @@ -726,9 +760,10 @@ start_service() { #local count logger -t "omr-bypass" "Starting OMR-ByPass..." add_domains="false" - config_load omr-bypass + [ -d /proc/net/xt_ndpi ] && config_load omr-bypass config_foreach _add_proto proto disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" + #noipv6="$(uci -q get omr-bypass.global.noipv6)" [ -n "$RELOAD" ] && [ "$(ipset --list | grep omr_dst_bypass_all)" = "" ] && { unset RELOAD @@ -780,6 +815,7 @@ start_service() { config_foreach _bypass_asn asns dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g' | grep -v dst_bypass) uci -q delete dhcp.@dnsmasq[0].ipset + uci -q delete dhcp.@dnsmasq[0].noipv6 if [ -n "$dnsmasqipset" ]; then for dnsipset in $dnsmasqipset; do ipsets="" @@ -840,7 +876,7 @@ start_service() { EOF fi config_load omr-bypass - config_foreach _bypass_proto dpis + [ -d /proc/net/xt_ndpi/proto ] && config_foreach _bypass_proto dpis uci -q commit omr-bypass [ -z "$RELOAD" ] && [ "$add_domains" = "true" ] && { From 6518d5f09c57a45fe866102ce97bb9d61a0f653c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 26 Apr 2023 08:43:57 +0200 Subject: [PATCH 0951/2059] Revert previous change on ndpi --- ndpi-netfilter2/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 13592c178..a4216acdb 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -44,15 +44,15 @@ CONFIGURE_ARGS += --with-pic MAKE_PATH:=ndpi-netfilter -#MAKE_FLAGS += \ -# KERNEL_DIR="$(LINUX_DIR)" \ -# MODULES_DIR="$(TARGET_MODULES_DIR)" \ -# ARCH="$(LINUX_KARCH)" \ -# KERNEL_RELEASE="$(KERNEL_PATCHVER)" \ -# CROSS_COMPILE="$(TARGET_CROSS)" \ -# CC="$(TARGET_CC)" \ MAKE_FLAGS += \ - NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter + KERNEL_DIR="$(LINUX_DIR)" \ + MODULES_DIR="$(TARGET_MODULES_DIR)" \ + ARCH="$(LINUX_KARCH)" \ + KERNEL_RELEASE="$(KERNEL_PATCHVER)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + CC="$(TARGET_CC)" \ +#MAKE_FLAGS += \ +# NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter define Build/Compile (cd $(PKG_BUILD_DIR)/src/lib &&\ From 19e0b5aab292602c09e89b03f608397568532515 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 26 Apr 2023 20:26:54 +0200 Subject: [PATCH 0952/2059] Limit shortcut-fe to 5.4 kernel --- shortcut-fe/Makefile | 4 ++-- simulated-driver/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shortcut-fe/Makefile b/shortcut-fe/Makefile index dd53042e5..5b03b9d76 100644 --- a/shortcut-fe/Makefile +++ b/shortcut-fe/Makefile @@ -24,7 +24,7 @@ define KernelPackage/shortcut-fe SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support - DEPENDS:=@IPV6 +kmod-nf-conntrack + DEPENDS:=@KERNEL_5_4 @IPV6 +kmod-nf-conntrack TITLE:=Kernel driver for SFE FILES:= \ $(PKG_BUILD_DIR)/shortcut-fe.ko \ @@ -53,7 +53,7 @@ define KernelPackage/shortcut-fe-cm SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support - DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe + DEPENDS:=@KERNEL_5_4 +kmod-ipt-conntrack +kmod-shortcut-fe TITLE:=Kernel driver for SFE FILES:=$(PKG_BUILD_DIR)/shortcut-fe-cm.ko KCONFIG:= \ diff --git a/simulated-driver/Makefile b/simulated-driver/Makefile index ecf9c41bd..7dcb320d9 100644 --- a/simulated-driver/Makefile +++ b/simulated-driver/Makefile @@ -18,7 +18,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=shortcut-fe-simulated-driver PKG_RELEASE:=1 -PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/shortcut-fe +PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/lklm/shortcut-fe.git PKG_SOURCE_PROTO:=git PKG_SOURCE_DATE:=2021-03-17 PKG_SOURCE_VERSION:=697977d8d0ccf0ab596e5692d08608a75dd7f33d @@ -30,7 +30,7 @@ define KernelPackage/shortcut-fe-drv SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support - DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe + DEPENDS:=@KERNEL_5_4 @TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe KCONFIG:= \ CONFIG_NET_CLS_ACT=y \ CONFIG_XFRM=y From 87f4bf706996f6dc8fc967ee75891fed11dc7ed8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 Apr 2023 08:50:09 +0200 Subject: [PATCH 0953/2059] Disable ndpi-netfilter2 on 6.1 for now --- luci-app-omr-bypass/Makefile | 3 ++- ndpi-netfilter2/Makefile | 20 +++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index 876d61e14..0c92a8bf8 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -6,7 +6,8 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains -LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables +#LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables +LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +iptables PKG_LICENSE:=GPLv3 diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index a4216acdb..a764d87de 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -31,7 +31,8 @@ define Package/iptables-mod-ndpi TITLE:=ndpi successor of OpenDPI URL:=http://www.ntop.org/products/ndpi/ # DEPENDS:=+iptables +iptables-mod-conntrack-extra +kmod-ipt-ndpi +libpcap - DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) +# DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) + DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15) MAINTAINER:=Ycarus (Yannick Chabanois) endef @@ -47,22 +48,17 @@ MAKE_PATH:=ndpi-netfilter MAKE_FLAGS += \ KERNEL_DIR="$(LINUX_DIR)" \ MODULES_DIR="$(TARGET_MODULES_DIR)" \ - ARCH="$(LINUX_KARCH)" \ - KERNEL_RELEASE="$(KERNEL_PATCHVER)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CC="$(TARGET_CC)" \ -#MAKE_FLAGS += \ -# NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter + NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter \ + ARCH="$(LINUX_KARCH)" define Build/Compile (cd $(PKG_BUILD_DIR)/src/lib &&\ gcc -g -O2 -fPIC -DPIC -DNDPI_LIB_COMPILATION -I../../src/include/ -I../../src/lib/third_party/include/ ndpi_network_list_compile.c -o ndpi_network_list_compile &&\ ./ndpi_network_list_compile -o ndpi_network_list.c.inc ndpi_network_list_*.yaml) -# $(MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter - +$(KERNEL_MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter + $(MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter endef -define Package/iptables-mod-ndpi/install +define KernelPackage/iptables-mod-ndpi/install $(INSTALL_DIR) $(1)/usr/lib/iptables $(INSTALL_BIN) $(PKG_BUILD_DIR)/ndpi-netfilter/ipt/libxt_ndpi.so $(1)/usr/lib/iptables endef @@ -75,11 +71,13 @@ define KernelPackage/ipt-ndpi CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y FILES:= $(PKG_BUILD_DIR)/ndpi-netfilter/src/xt_ndpi.ko AUTOLOAD:=$(call AutoProbe,xt_ndpi) +# MODPARAMS.xt_ndpi:=ndpi_enable_flow=1 KCONFIG:=\ CONFIG_LIVEPATCH=y \ CONFIG_NF_CONNTRACK=y \ CONFIG_NF_CONNTRACK_LABELS=y \ - CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y + CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y \ + CONFIG_UNUSED_SYMBOLS=y endef $(eval $(call BuildPackage,iptables-mod-ndpi)) From 103031bfb4e2ca3887493196d2dd777490b514d9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 Apr 2023 20:50:04 +0200 Subject: [PATCH 0954/2059] Limit fast-classifier to 5.4 kernel --- fast-classifier/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fast-classifier/Makefile b/fast-classifier/Makefile index 09c1174dd..410a0df28 100644 --- a/fast-classifier/Makefile +++ b/fast-classifier/Makefile @@ -24,7 +24,7 @@ define KernelPackage/fast-classifier/Default SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support - DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe + DEPENDS:=@KERNEL_5_4 +kmod-ipt-conntrack +kmod-shortcut-fe TITLE:=Kernel driver for FAST Classifier FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko KCONFIG:= \ @@ -59,7 +59,7 @@ endef define Package/fast-classifier-example TITLE:=Example user space program for fast-classifier - DEPENDS:=+libnl +kmod-fast-classifier + DEPENDS:=@KERNEL_5_4 +libnl +kmod-fast-classifier endef define Package/fast-classifier-example/description From 78fa50795618f4311c95a2e49ca644ac7d0639c9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 28 Apr 2023 20:50:41 +0200 Subject: [PATCH 0955/2059] Update ndpi-netfilter2 --- ndpi-netfilter2/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index a764d87de..2f55b85c7 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 -PKG_REV:=2fc0c86e58d56c8f9c5da3883a09732fc902e5e7 +PKG_REV:=fbb2104d125a13db3b8c7fdc34ea0e3fcfe92d12 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git @@ -58,7 +58,7 @@ define Build/Compile $(MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter endef -define KernelPackage/iptables-mod-ndpi/install +define Package/iptables-mod-ndpi/install $(INSTALL_DIR) $(1)/usr/lib/iptables $(INSTALL_BIN) $(PKG_BUILD_DIR)/ndpi-netfilter/ipt/libxt_ndpi.so $(1)/usr/lib/iptables endef @@ -66,7 +66,8 @@ endef define KernelPackage/ipt-ndpi SUBMENU:=Netfilter Extensions TITLE:= nDPI net netfilter module - DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) +# DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) + DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15) KCONFIG:=CONFIG_NF_CONNTRACK_LABELS=y \ CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y FILES:= $(PKG_BUILD_DIR)/ndpi-netfilter/src/xt_ndpi.ko From 9d90f36870bbb7780a709153b5c429012cc37c76 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 May 2023 10:53:34 +0200 Subject: [PATCH 0956/2059] Fix ndpi-netfilter2 --- ...le-nf_conntrack-ip_tables-ip6_tables.patch | 20 +++++++++++++++++++ ndpi-netfilter2/patches/outline-atomics.patch | 5 +++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 ndpi-netfilter2/patches/001-remove-request-module-nf_conntrack-ip_tables-ip6_tables.patch diff --git a/ndpi-netfilter2/patches/001-remove-request-module-nf_conntrack-ip_tables-ip6_tables.patch b/ndpi-netfilter2/patches/001-remove-request-module-nf_conntrack-ip_tables-ip6_tables.patch new file mode 100644 index 000000000..5c06b5100 --- /dev/null +++ b/ndpi-netfilter2/patches/001-remove-request-module-nf_conntrack-ip_tables-ip6_tables.patch @@ -0,0 +1,20 @@ +diff --git forkSrcPrefix/ndpi-netfilter/src/main.c forkDstPrefix/ndpi-netfilter/src/main.c +index 8e2766fcbd823d709930af63a38a49535b335665..4f3382eac2293709b57699994dc17bc888b082ea 100644 +--- forkSrcPrefix/ndpi-netfilter/src/main.c ++++ forkDstPrefix/ndpi-netfilter/src/main.c +@@ -3223,6 +3223,7 @@ static int __init ndpi_mt_init(void) + set_ndpi_malloc(malloc_wrapper); + set_ndpi_free(free_wrapper); + ++#if 0 + if(request_module("nf_conntrack") < 0) { + pr_err("xt_ndpi: nf_conntrack required!\n"); + return -EOPNOTSUPP; +@@ -3237,6 +3238,7 @@ static int __init ndpi_mt_init(void) + return -EOPNOTSUPP; + } + #endif ++#endif + #ifdef NF_CT_CUSTOM + ret = nf_ct_extend_custom_register(&ndpi_extend,0x4e445049); /* "NDPI" in hex */ + if(ret < 0) { diff --git a/ndpi-netfilter2/patches/outline-atomics.patch b/ndpi-netfilter2/patches/outline-atomics.patch index ef7f6fd5f..e8f93d0c8 100644 --- a/ndpi-netfilter2/patches/outline-atomics.patch +++ b/ndpi-netfilter2/patches/outline-atomics.patch @@ -1,13 +1,14 @@ --- a/ndpi-netfilter/src/Makefile 2022-08-03 21:27:52.321058402 +0200 +++ b/ndpi-netfilter/src/Makefile 2022-08-03 21:28:27.572452447 +0200 -@@ -5,6 +5,11 @@ +@@ -5,6 +5,12 @@ ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -I${src}/../libre -I${src}/${NDPI_SRC}/lib/third_party/include ccflags-y += -DHAVE_CONFIG_H -DNDPI_LIB_COMPILATION -DOPENDPI_NETFILTER_MODULE -DNDPI_DETECTION_SUPPORT_IPV6 -g ccflags-y += -Wno-declaration-after-statement -+ifeq ($(KERNEL_RELEASE),5.15) +ifeq ($(ARCH),arm64) + ccflags-y += -mno-outline-atomics +endif ++ifeq ($(ARCH),aarch64) ++ ccflags-y += -mno-outline-atomics +endif #ccflags-y += -Wshadow-local # Needed for pahole From 313640cc9ff65fd479a45271ee3a7929112b02f0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 May 2023 19:28:41 +0200 Subject: [PATCH 0957/2059] Fix ndpi --- ndpi-netfilter2/patches/outline-atomics.patch | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ndpi-netfilter2/patches/outline-atomics.patch b/ndpi-netfilter2/patches/outline-atomics.patch index e8f93d0c8..a0935ecea 100644 --- a/ndpi-netfilter2/patches/outline-atomics.patch +++ b/ndpi-netfilter2/patches/outline-atomics.patch @@ -1,14 +1,16 @@ --- a/ndpi-netfilter/src/Makefile 2022-08-03 21:27:52.321058402 +0200 +++ b/ndpi-netfilter/src/Makefile 2022-08-03 21:28:27.572452447 +0200 -@@ -5,6 +5,12 @@ +@@ -5,6 +5,14 @@ ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -I${src}/../libre -I${src}/${NDPI_SRC}/lib/third_party/include ccflags-y += -DHAVE_CONFIG_H -DNDPI_LIB_COMPILATION -DOPENDPI_NETFILTER_MODULE -DNDPI_DETECTION_SUPPORT_IPV6 -g ccflags-y += -Wno-declaration-after-statement ++ifneq ($(KERNEL_RELEASE),5.4) +ifeq ($(ARCH),arm64) + ccflags-y += -mno-outline-atomics +endif +ifeq ($(ARCH),aarch64) + ccflags-y += -mno-outline-atomics ++endif +endif #ccflags-y += -Wshadow-local # Needed for pahole From 84a0fe47b37278a044a4dcb2012da9c035d00837 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 2 May 2023 08:32:19 +0200 Subject: [PATCH 0958/2059] Fix uci on omr-bypass --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index ebab9e1b5..65f308e27 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -624,10 +624,10 @@ _intf_rule() { COMMIT EOF fi - if [ "$(uci -q openmptcprouter.settings.proxy)" = "shadowsocks" ]; then + if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then config_load shadowsocks-libev config_foreach _intf_rule_ss_rules ss_rules - else + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ]; then _intf_rule_v2ray_rules fi From 34c656501698d1787acfc81ae27c9a3cc7005395 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 7 May 2023 08:53:12 +0200 Subject: [PATCH 0959/2059] Some changes for IPv6 support in omr-bypass --- .../resources/view/services/omr-bypass.js | 39 +++++++++++++++++-- .../root/etc/uci-defaults/41_omr-bypass | 7 ++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js index 3119d93f0..59efc4eec 100644 --- a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js +++ b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js @@ -23,6 +23,16 @@ return L.view.extend({ m = new form.Map('omr-bypass', _('OMR-Bypass'),_('OpenMPTCProuter IP must be used as DNS.')); + /* + s = m.section(form.TypedSection, 'global', _('Global settings')); + s.addremove = false; + s.anonymous = true; + + o = s.option(form.Flag, 'noipv6', _('Disable IPv6 AAAA DNS results for bypassed domains')); + o.default = o.disabled; + o.optional = true; + */ + s = m.section(form.GridSection, 'domains', _('Domains')); s.addremove = true; s.anonymous = true; @@ -42,6 +52,17 @@ return L.view.extend({ o = s.option(form.Value, 'note', _('Note')); o.rmempty = true; + o = s.option(form.ListValue, 'family', _('Restrict to address family')); + o.value('ipv4ipv6', _('IPv4 and IPv6')); + o.value('ipv4', _('IPv4 only')); + o.value('ipv4', _('IPv6 only')); + o.default = 'ipv4ipv6'; + o.modalonly = true + + o = s.option(form.Flag, 'noipv6', _('Disable AAAA IPv6 DNS')); + o.default = o.enabled; + o.modalonly = true + s = m.section(form.GridSection, 'ips', _('IPs and Networks')); s.addremove = true; s.anonymous = true; @@ -223,12 +244,24 @@ return L.view.extend({ o.noinactive = true; o.nocreate = true; - o = s.option(form.Flag, 'ndpi', _('Enable ndpi')); - o.default = o.enabled; - o = s.option(form.Value, 'note', _('Note')); o.rmempty = true; + o = s.option(form.ListValue, 'family', _('Restrict to address family')); + o.value('ipv4ipv6', _('IPv4 and IPv6')); + o.value('ipv4', _('IPv4 only')); + o.value('ipv4', _('IPv6 only')); + o.default = 'ipv4ipv6'; + o.modalonly = true + + o = s.option(form.Flag, 'noipv6', _('Disable AAAA IPv6 DNS')); + o.default = o.enabled; + o.modalonly = true + + o = s.option(form.Flag, 'ndpi', _('Enable ndpi')); + o.default = o.enabled; + o.modalonly = true + return m.render(); } }); diff --git a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass index 9ced39f93..394829cc0 100755 --- a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass +++ b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass @@ -118,6 +118,13 @@ if [ "$(uci -q get omr-bypass.amazonvideo)" = "" ]; then commit omr-bypass EOF fi +#if [ "$(uci -q get omr-bypass.global)" = "" ]; then +# uci -q batch <<-EOF >/dev/null +# set omr-bypass.global=global +# set omr-bypass.global.noipv6='0' +# commit omr-bypass +# EOF +#fi if [ ! -f /etc/crontabs/root ] || [ "$(cat /etc/crontabs/root | grep bypass)" = "" ]; then echo "0 2 * * * /etc/init.d/omr-bypass bypass_asn" >> /etc/crontabs/root fi From 35ff6d8e9b430a486471d4f60d1d5a2e3304d5f4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 7 May 2023 08:54:29 +0200 Subject: [PATCH 0960/2059] Modify when mptcp reload is needed --- mptcp/files/etc/hotplug.d/iface/30-mptcp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mptcp/files/etc/hotplug.d/iface/30-mptcp b/mptcp/files/etc/hotplug.d/iface/30-mptcp index c37447553..6363894b0 100644 --- a/mptcp/files/etc/hotplug.d/iface/30-mptcp +++ b/mptcp/files/etc/hotplug.d/iface/30-mptcp @@ -1,11 +1,12 @@ #!/bin/sh - -[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0 +[ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = ifdown -o "$ACTION" = iflink ] || exit 0 [ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0 + /etc/init.d/mptcp enabled || exit 0 -if [ -z "$(echo $DEVICE | grep oip | grep gre)" ]; then + +if [ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = iflink ] && [ -z "$(echo $DEVICE | grep oip | grep gre)" ]; then logger -t "mptcp" "Reloading mptcp config due to $ACTION of $INTERFACE ($DEVICE)" /etc/init.d/mptcp reload "$DEVICE" >/dev/null || exit 0 else From 2d41636606b9df6bb809de004e3ef5f900ab45ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 7 May 2023 08:55:17 +0200 Subject: [PATCH 0961/2059] Force arm64 instead of aarch64 in ndpi --- ndpi-netfilter2/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 2f55b85c7..a91cdaaf7 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -49,7 +49,12 @@ MAKE_FLAGS += \ KERNEL_DIR="$(LINUX_DIR)" \ MODULES_DIR="$(TARGET_MODULES_DIR)" \ NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter \ - ARCH="$(LINUX_KARCH)" + +ifeq ($ARCH),aarch64) + MAKE_FLAGS += ARCH="arm64" +else + MAKE_FLAGS += ARCH="$(LINUX_KARCH)" +endif define Build/Compile (cd $(PKG_BUILD_DIR)/src/lib &&\ From e22b863f26e80500f4cbf9270072943bf8387551 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 May 2023 21:15:28 +0200 Subject: [PATCH 0962/2059] Add Systemtap package --- systemtap/Makefile | 79 +++++++++++++++++++ ...gure-write-a-python-location-into-th.patch | 25 ++++++ ...ython-modules-to-correct-library-dir.patch | 56 +++++++++++++ ...staprun-address-ncurses-6.3-failures.patch | 61 ++++++++++++++ ...-don-t-support-installing-a-non-root.patch | 37 +++++++++ systemtap/patches/basename.patch | 24 ++++++ systemtap/patches/conversion.patch | 15 ++++ systemtap/patches/include-fix.patch | 22 ++++++ systemtap/patches/types.patch | 60 ++++++++++++++ 9 files changed, 379 insertions(+) create mode 100644 systemtap/Makefile create mode 100644 systemtap/patches/0001-Do-not-let-configure-write-a-python-location-into-th.patch create mode 100644 systemtap/patches/0001-Install-python-modules-to-correct-library-dir.patch create mode 100644 systemtap/patches/0001-staprun-address-ncurses-6.3-failures.patch create mode 100644 systemtap/patches/0001-staprun-stapbpf-don-t-support-installing-a-non-root.patch create mode 100644 systemtap/patches/basename.patch create mode 100644 systemtap/patches/conversion.patch create mode 100644 systemtap/patches/include-fix.patch create mode 100644 systemtap/patches/types.patch diff --git a/systemtap/Makefile b/systemtap/Makefile new file mode 100644 index 000000000..6b3a704cc --- /dev/null +++ b/systemtap/Makefile @@ -0,0 +1,79 @@ +# +# Copyright (C) 2018-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# 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:=systemtap +PKG_RELEASE:=1 +PKG_VERSION:=4.9 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://sourceware.org/systemtap/ftp/releases/ +PKG_HASH:=d01033baea9d0af52a65e70167816931f4b856427a53ff2ab30e4b45f6ad3a98 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_BUILD_DEPENDS:=systemtap/host +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/package.mk + +define Package/systemtap + SUBMENU:=System + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Simplify the gathering of information + URL:=http://sourceware.org/systemtap/wiki + DEPENDS:=@(LINUX_5_15||LINUX_6_1) +libelf +libdw + MAINTAINER:=Ycarus (Yannick Chabanois) +endef + +define Package/systemtap/description + SystemTap (stap) is a scripting language and tool for dynamically instrumenting running production Linux-based operating systems. +endef + +CONFIGURE_ARGS += --without-rpm \ + --without-nss --without-avahi --without-dyninst \ + --disable-server --disable-grapher --enable-prologues \ + --without-python2-probes --disable-translator \ + --disable-libvirt --disable-sqlite --disable-monitor --without-python3-probes \ + ac_cv_prog_have_javac=no \ + ac_cv_prog_have_jar=no + +HOST_CONFIGURE_ARGS += --without-rpm \ + --without-nss --without-avahi --without-dyninst \ + --disable-server --disable-grapher --enable-prologues \ + --without-python2-probes \ + --disable-libvirt --disable-sqlite --disable-monitor --without-python3-probes \ + ac_cv_prog_have_javac=no \ + ac_cv_prog_have_jar=no + +define Package/systemtap/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_DIR) $(1)/usr/include + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/share + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/ + $(CP) $(PKG_INSTALL_DIR)/usr/share/* $(1)/usr/share/ +endef + +define Host/install + $(INSTALL_DIR) $(STAGING_DIR_HOST)/usr/bin + $(INSTALL_DIR) $(STAGING_DIR_HOST)/usr/include + $(INSTALL_DIR) $(STAGING_DIR_HOST)/usr/lib + $(INSTALL_DIR) $(STAGING_DIR_HOST)/usr/share + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(STAGING_DIR_HOST)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(STAGING_DIR_HOST)/usr/include/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(STAGING_DIR_HOST)/usr/lib/ + $(CP) $(PKG_INSTALL_DIR)/usr/share/* $(STAGING_DIR_HOST)/usr/share/ +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,systemtap)) diff --git a/systemtap/patches/0001-Do-not-let-configure-write-a-python-location-into-th.patch b/systemtap/patches/0001-Do-not-let-configure-write-a-python-location-into-th.patch new file mode 100644 index 000000000..742b1187f --- /dev/null +++ b/systemtap/patches/0001-Do-not-let-configure-write-a-python-location-into-th.patch @@ -0,0 +1,25 @@ +From ab29615ed6c2e779b472903564dc683dc1015de7 Mon Sep 17 00:00:00 2001 +From: Alexander Kanavin +Date: Wed, 22 Feb 2017 13:37:33 +0200 +Subject: [PATCH] Do not let configure write a python location into the dtrace + binary + +Upstream-Status: Inappropriate [oe-core specific] +Signed-off-by: Alexander Kanavin +--- + dtrace.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dtrace.in b/dtrace.in +index 5e1cf8079..a24229cbc 100644 +--- a/dtrace.in ++++ b/dtrace.in +@@ -1,4 +1,4 @@ +-#!@preferred_python@ ++#!/usr/bin/python3 + # vim: et sta sts=4 sw=4 ts=8 + + # This handles the systemtap equivalent of +-- +2.11.0 + diff --git a/systemtap/patches/0001-Install-python-modules-to-correct-library-dir.patch b/systemtap/patches/0001-Install-python-modules-to-correct-library-dir.patch new file mode 100644 index 000000000..48cf4aee8 --- /dev/null +++ b/systemtap/patches/0001-Install-python-modules-to-correct-library-dir.patch @@ -0,0 +1,56 @@ +From 2ada22f05460223924efe54080cb4419e2b4c276 Mon Sep 17 00:00:00 2001 +From: Alexander Kanavin +Date: Fri, 24 Feb 2017 17:53:02 +0200 +Subject: [PATCH] Install python modules to correct library dir. + +Upstream-Status: Inappropriate [oe-core specific] +Signed-off-by: Alexander Kanavin + +Add OE's CFLAGS which contains `-fdebug-prefix-map' options to +setup.py + +Supply "--root" directory to the "install" command, and use +it as a prefix to strip off the purported filename encoded +in bytecode files. (It strips build path prefix from .pyc files) + +Signed-off-by: Hongxu Jia +--- + python/Makefile.am | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/python/Makefile.am b/python/Makefile.am +index a254480..578602f 100644 +--- a/python/Makefile.am ++++ b/python/Makefile.am +@@ -8,6 +8,10 @@ AUTOMAKE_OPTIONS = subdir-objects + AM_CPPFLAGS = -I$(srcdir)/../includes + AM_CPPFLAGS += -I$(abs_builddir)/../includes/sys + ++# Add OE's CFLAGS which contains `-fdebug-prefix-map' options to ++# fix build path issue ++AM_CPPFLAGS += $(CFLAGS) ++ + # Any script in the following variable will get byte-compiled at + # install time. + pkglibexecpython_PYTHON = +@@ -47,7 +51,7 @@ install-exec-local: + if HAVE_PYTHON2_PROBES + (cd $(srcdir); CFLAGS="$(AM_CPPFLAGS)" $(PYTHON) setup.py build \ + --build-base $(shell readlink -f $(builddir))/py2build \ +- install --prefix $(DESTDIR)$(prefix) \ ++ install --root $(DESTDIR) --prefix $(prefix) --prefix $(prefix) --install-lib=${pythondir} \ + --single-version-externally-managed \ + --record $(shell readlink -f $(builddir))/py2build/install_files.txt \ + --verbose) +@@ -55,7 +59,7 @@ endif + if HAVE_PYTHON3_PROBES + (cd $(srcdir); CFLAGS="$(AM_CPPFLAGS)" $(PYTHON3) setup.py build \ + --build-base $(shell readlink -f $(builddir))/py3build \ +- install --prefix $(DESTDIR)$(prefix) \ ++ install --root $(DESTDIR) --prefix $(prefix) --install-lib=${python3dir} \ + --single-version-externally-managed \ + --record $(shell readlink -f $(builddir))/py3build/install_files.txt \ + --verbose) +-- +2.7.4 + diff --git a/systemtap/patches/0001-staprun-address-ncurses-6.3-failures.patch b/systemtap/patches/0001-staprun-address-ncurses-6.3-failures.patch new file mode 100644 index 000000000..1decf2159 --- /dev/null +++ b/systemtap/patches/0001-staprun-address-ncurses-6.3-failures.patch @@ -0,0 +1,61 @@ +From 191f528da19193d713d94ee252e2485efd9af4d3 Mon Sep 17 00:00:00 2001 +From: Alexander Kanavin +Date: Mon, 25 Oct 2021 17:59:24 +0200 +Subject: [PATCH] staprun: address ncurses 6.3 failures + +Upstream-Status: Submitted [by email to smakarov@redhat.com,systemtap@sourceware.org] +Signed-off-by: Alexander Kanavin +--- + staprun/monitor.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/staprun/monitor.c b/staprun/monitor.c +index 478634c09..f4fbfd686 100644 +--- a/staprun/monitor.c ++++ b/staprun/monitor.c +@@ -448,12 +448,12 @@ void monitor_render(void) + if (active_window == 0) + wattron(status, A_BOLD); + wprintw(status, "\n%*s\t%*s\t%*s\t%*s\t%*s\t%*s\t%s\n", +- width[p_index], HIGHLIGHT("index", p_index, comp_fn_index), +- width[p_state], HIGHLIGHT("state", p_state, comp_fn_index), +- width[p_hits], HIGHLIGHT("hits", p_hits, comp_fn_index), +- width[p_min], HIGHLIGHT("min", p_min, comp_fn_index), +- width[p_avg], HIGHLIGHT("avg", p_avg, comp_fn_index), +- width[p_max], HIGHLIGHT("max", p_max, comp_fn_index), ++ (int)width[p_index], HIGHLIGHT("index", p_index, comp_fn_index), ++ (int)width[p_state], HIGHLIGHT("state", p_state, comp_fn_index), ++ (int)width[p_hits], HIGHLIGHT("hits", p_hits, comp_fn_index), ++ (int)width[p_min], HIGHLIGHT("min", p_min, comp_fn_index), ++ (int)width[p_avg], HIGHLIGHT("avg", p_avg, comp_fn_index), ++ (int)width[p_max], HIGHLIGHT("max", p_max, comp_fn_index), + HIGHLIGHT("name", p_name, comp_fn_index)); + if (active_window == 0) + wattroff(status, A_BOLD); +@@ -466,17 +466,17 @@ void monitor_render(void) + json_object *probe, *field; + probe = json_object_array_get_idx(jso_probe_list, i); + json_object_object_get_ex(probe, "index", &field); +- wprintw(status, "%*s\t", width[p_index], json_object_get_string(field)); ++ wprintw(status, "%*s\t", (int)width[p_index], json_object_get_string(field)); + json_object_object_get_ex(probe, "state", &field); +- wprintw(status, "%*s\t", width[p_state], json_object_get_string(field)); ++ wprintw(status, "%*s\t", (int)width[p_state], json_object_get_string(field)); + json_object_object_get_ex(probe, "hits", &field); +- wprintw(status, "%*s\t", width[p_hits], json_object_get_string(field)); ++ wprintw(status, "%*s\t", (int)width[p_hits], json_object_get_string(field)); + json_object_object_get_ex(probe, "min", &field); +- wprintw(status, "%*s\t", width[p_min], json_object_get_string(field)); ++ wprintw(status, "%*s\t", (int)width[p_min], json_object_get_string(field)); + json_object_object_get_ex(probe, "avg", &field); +- wprintw(status, "%*s\t", width[p_avg], json_object_get_string(field)); ++ wprintw(status, "%*s\t", (int)width[p_avg], json_object_get_string(field)); + json_object_object_get_ex(probe, "max", &field); +- wprintw(status, "%*s\t", width[p_max], json_object_get_string(field)); ++ wprintw(status, "%*s\t", (int)width[p_max], json_object_get_string(field)); + getyx(status, discard, cur_x); + json_object_object_get_ex(probe, "name", &field); + wprintw(status, "%.*s", max_cols-cur_x-1, json_object_get_string(field)); +-- +2.20.1 + diff --git a/systemtap/patches/0001-staprun-stapbpf-don-t-support-installing-a-non-root.patch b/systemtap/patches/0001-staprun-stapbpf-don-t-support-installing-a-non-root.patch new file mode 100644 index 000000000..e2f8b3b05 --- /dev/null +++ b/systemtap/patches/0001-staprun-stapbpf-don-t-support-installing-a-non-root.patch @@ -0,0 +1,37 @@ +From 3e13a006fe3dff9489269274093bf868532036e2 Mon Sep 17 00:00:00 2001 +From: Saul Wold +Date: Tue, 5 Sep 2017 16:02:55 -0700 +Subject: [PATCH] staprun/stapbpf: don't support installing a non-root + +Since we are in a known environment and installing as root and +expect to be running as root, don't create the group or chmod +the binaries. + +Upstream-Status: Inappropriate [Embedded] +Signed-off-by: Saul Wold +--- + stapbpf/Makefile.am | 14 +++++++------- + staprun/Makefile.am | 12 ++++++------ + 2 files changed, 13 insertions(+), 13 deletions(-) + +Index: git/stapbpf/Makefile.am +=================================================================== +--- git.orig/stapbpf/Makefile.am ++++ git/stapbpf/Makefile.am +@@ -41,10 +41,10 @@ + + # Why the "id -u" condition? This way, an unprivileged user can run + # make install, and have "sudo stap ...." or "sudo stapbpf ...." work later. +-install-exec-hook: +- if [ `id -u` -eq 0 ] && (getent group stapusr >/dev/null \ +- || groupadd -f -g 156 -r stapusr); then \ +- chgrp stapusr "$(DESTDIR)$(bindir)/stapbpf" \ +- && chmod 04110 "$(DESTDIR)$(bindir)/stapbpf"; \ +- fi ++#install-exec-hook: ++## if [ `id -u` -eq 0 ] && (getent group stapusr >/dev/null \ ++## || groupadd -f -g 156 -r stapusr); then \ ++## chgrp stapusr "$(DESTDIR)$(bindir)/stapbpf" \ ++# && chmod 04110 "$(DESTDIR)$(bindir)/stapbpf"; \ ++# fi + endif diff --git a/systemtap/patches/basename.patch b/systemtap/patches/basename.patch new file mode 100644 index 000000000..12e072b5d --- /dev/null +++ b/systemtap/patches/basename.patch @@ -0,0 +1,24 @@ +--- a/buildrun.cxx 2023-05-03 10:17:44.338633166 +0200 ++++ b/buildrun.cxx 2023-05-03 10:18:48.465507072 +0200 +@@ -943,7 +943,8 @@ + if (remotedir.empty()) + opt_u.append(s.uprobes_path); + else +- opt_u.append(remotedir + "/" + basename(s.uprobes_path.c_str())); ++ //opt_u.append(remotedir + "/" + basename(s.uprobes_path.c_str())); ++ opt_u.append(remotedir + "/" + s.uprobes_path.substr(s.uprobes_path.rfind('/')+1)); + } + cmd.push_back(opt_u); + } +--- a/remote.cxx 2023-05-03 13:52:06.614257954 +0200 ++++ b/remote.cxx 2023-05-03 13:53:19.784994466 +0200 +@@ -472,7 +472,8 @@ + + if (!s->uprobes_path.empty()) + { +- string remoteuprobes = basename(s->uprobes_path.c_str()); ++ //string remoteuprobes = basename(s->uprobes_path.c_str()); ++ string remoteuprobes = s->uprobes_path.substr(s->uprobes_path.rfind('/')+1); + if ((rc = send_file(s->uprobes_path, remoteuprobes))) + return rc; + diff --git a/systemtap/patches/conversion.patch b/systemtap/patches/conversion.patch new file mode 100644 index 000000000..225d92279 --- /dev/null +++ b/systemtap/patches/conversion.patch @@ -0,0 +1,15 @@ +--- a/util.cxx 2023-05-03 13:20:34.930972141 +0200 ++++ b/util.cxx 2023-05-03 13:21:15.398273958 +0200 +@@ -257,8 +257,10 @@ + { + char *dirc, *basec, *bname, *dname; + +- dirc = strdupa (path.c_str()); +- basec = strdupa (path.c_str()); ++ dirc = strdup (path.c_str()); ++ basec = strdup (path.c_str()); + dname = dirname (dirc); + bname = basename (basec); ++ free(dirc); ++ free(basec); + directory = dname; diff --git a/systemtap/patches/include-fix.patch b/systemtap/patches/include-fix.patch new file mode 100644 index 000000000..d12ab4f33 --- /dev/null +++ b/systemtap/patches/include-fix.patch @@ -0,0 +1,22 @@ +--- a/staprun/staprun.h 2023-05-03 21:59:59.097825632 +0200 ++++ b/staprun/staprun.h 2023-05-03 22:00:06.457699309 +0200 +@@ -30,7 +30,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +--- a/stapbpf/stapbpf.cxx 2023-05-03 22:02:20.483398963 +0200 ++++ b/stapbpf/stapbpf.cxx 2023-05-03 22:02:34.879151884 +0200 +@@ -34,7 +34,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include diff --git a/systemtap/patches/types.patch b/systemtap/patches/types.patch new file mode 100644 index 000000000..b27405fcd --- /dev/null +++ b/systemtap/patches/types.patch @@ -0,0 +1,60 @@ +--- a/util.h 2023-05-03 08:32:15.445228767 +0200 ++++ b/util.h 2023-05-03 08:33:38.683781936 +0200 +@@ -16,6 +16,27 @@ + #include + #include + #include ++#include ++#include ++ ++typedef off_t __off_t; ++typedef signed char __int8_t; ++typedef unsigned char __uint8_t; ++typedef signed short int __int16_t; ++typedef unsigned short int __uint16_t; ++typedef signed int __int32_t; ++typedef unsigned int __uint32_t; ++#if __WORDSIZE == 64 ++typedef signed long int __int64_t; ++typedef unsigned long int __uint64_t; ++#elif defined(__GNUC__) ++__extension__ typedef signed long long int __int64_t; ++__extension__ typedef unsigned long long int __uint64_t; ++#endif ++ ++#ifndef FNM_EXTMATCH ++#define FNM_EXTMATCH 0 ++#endif + + extern "C" { + #if ENABLE_NLS +@@ -415,6 +415,9 @@ + const sigset_t *sigmask); + #endif + ++#ifndef __GLIBC__ ++#define canonicalize_file_name(name) realpath(name,NULL) ++#endif + + int read_from_file (const std::string &fname, int &data); + template +--- a/tapsets.cxx 2023-05-03 09:17:52.009600253 +0200 ++++ b/tapsets.cxx 2023-05-03 09:18:02.989408144 +0200 +@@ -51,7 +51,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/staprun/staprun.h 2023-05-03 21:56:21.277564278 +0200 ++++ b/staprun/staprun.h 2023-05-03 21:57:10.364721740 +0200 +@@ -48,6 +48,7 @@ + #include + #endif + ++typedef off_t __off_t; + + /* define gettext options if NLS is set */ + #if ENABLE_NLS From dfaa6ba1f009e0e762b85c29e29776f11259c9ab Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 May 2023 21:01:36 +0200 Subject: [PATCH 0963/2059] Update golang and enable MPTCP by default --- golang/golang-package.mk | 2 +- golang/golang-values.mk | 2 +- golang/golang/Makefile | 24 +++++++--- ...-ARM-ARM64-only-if-gold-is-available.patch | 48 ------------------- .../patches/001-default-enable-mptcp.patch | 11 +++++ 5 files changed, 31 insertions(+), 56 deletions(-) delete mode 100644 golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch create mode 100644 golang/golang/patches/001-default-enable-mptcp.patch diff --git a/golang/golang-package.mk b/golang/golang-package.mk index 7144a4524..fcc3f3aec 100644 --- a/golang/golang-package.mk +++ b/golang/golang-package.mk @@ -213,7 +213,7 @@ GO_PKG_BUILD_VARS= \ GOPATH="$(GO_PKG_BUILD_DIR)" \ GOCACHE="$(GO_BUILD_CACHE_DIR)" \ GOMODCACHE="$(GO_MOD_CACHE_DIR)" \ - GOENV=off + GOENV=off GOPROXY="direct" GO_PKG_VARS= \ $(GO_PKG_TARGET_VARS) \ diff --git a/golang/golang-values.mk b/golang/golang-values.mk index 3c170f308..f0581f419 100644 --- a/golang/golang-values.mk +++ b/golang/golang-values.mk @@ -30,7 +30,7 @@ unexport \ GOPATH \ GOROOT \ GOTMPDIR \ - GOWORK + GOWORK GOPROXY # Unmodified: # GOINSECURE # GOPRIVATE diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 6f6f28b24..1047d5b6b 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -7,8 +7,10 @@ include $(TOPDIR)/rules.mk +#GO_VERSION_MAJOR_MINOR:=1.20 +#GO_VERSION_PATCH:=3 GO_VERSION_MAJOR_MINOR:=1.20 -GO_VERSION_PATCH:=3 +GO_VERSION_PATCH:=999 PKG_NAME:=golang PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) @@ -18,9 +20,14 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ https://mirrors.ustc.edu.cn/golang/ \ https://mirrors.nju.edu.cn/golang/ -PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz -PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=e447b498cde50215c4f7619e5124b0fc4e25fb5d16ea47271c47f278e7aa763a +#PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz +#PKG_SOURCE_URL:=$(GO_SOURCE_URLS) +#PKG_HASH:=e447b498cde50215c4f7619e5124b0fc4e25fb5d16ea47271c47f278e7aa763a +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/golang/go.git +PKG_SOURCE_VERSION:=a5350558e6e2db16bfe09f2ba8104549c6598c46 +PKG_SOURCE_DATE:=2023-05-05 +PKG_SOURCE_SUBDIR:=go-$(PKG_VERSION) PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause @@ -100,7 +107,7 @@ include ../golang-compiler.mk include ../golang-package.mk PKG_UNPACK:=$(HOST_TAR) -C "$(PKG_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" -HOST_UNPACK:=$(HOST_TAR) -C "$(HOST_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" +#HOST_UNPACK:=$(HOST_TAR) -C "$(HOST_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" BOOTSTRAP_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_SOURCE)" BOOTSTRAP_1_17_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_1_17_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_1_17_SOURCE)" @@ -234,10 +241,13 @@ HOST_GO_VARS= \ CXX="$(HOSTCXX_NOCACHE)" define Host/Configure + sed -i 's/1\.21/1.20/g' $(HOST_BUILD_DIR)/src/go.mod + sed -i 's/21/20/g' $(HOST_BUILD_DIR)/src/internal/goversion/goversion.go $(call GoCompiler/Bootstrap/CheckHost,$(BOOTSTRAP_GO_VALID_OS_ARCH)) $(call GoCompiler/Host/CheckHost,$(HOST_GO_VALID_OS_ARCH)) mkdir -p "$(GO_BUILD_CACHE_DIR)" + echo "go$(PKG_VERSION)" > $(HOST_BUILD_DIR)/VERSION endef define Host/Compile @@ -334,12 +344,14 @@ PKG_GO_INSTALL_ARGS= \ $(if $(filter $(GO_PKG_ENABLE_PIE),1),-buildmode pie) define Build/Configure + sed -i 's/1\.21/1.20/g' $(HOST_BUILD_DIR)/src/go.mod + sed -i 's/21/20/g' $(HOST_BUILD_DIR)/src/internal/goversion/goversion.go mkdir -p "$(GO_BUILD_CACHE_DIR)" + echo "go$(PKG_VERSION)" > $(PKG_BUILD_DIR)/VERSION endef define Build/Compile @echo "Building target Go first stage" - $(call GoCompiler/Package/Make, \ GOROOT_BOOTSTRAP="$(HOST_GO_ROOT)" \ GO_GCC_HELPER_CC="$(HOSTCC)" \ diff --git a/golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch b/golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch deleted file mode 100644 index 683480442..000000000 --- a/golang/golang/patches/001-cmd-link-use-gold-on-ARM-ARM64-only-if-gold-is-available.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 5ccf9f47bf4f5ba53e0ab7338a7fd4626714cfb2 Mon Sep 17 00:00:00 2001 -From: Jeffery To -Date: Tue, 23 Nov 2021 15:05:37 +0800 -Subject: [PATCH] cmd/link: use gold on ARM/ARM64 only if gold is available - -COPY relocation handling on ARM/ARM64 has been fixed in recent versions -of the GNU linker. This switches to gold only if gold is available. - -Fixes #22040. ---- - src/cmd/link/internal/ld/lib.go | 19 +++++++------------ - 1 file changed, 7 insertions(+), 12 deletions(-) - ---- a/src/cmd/link/internal/ld/lib.go -+++ b/src/cmd/link/internal/ld/lib.go -@@ -1535,25 +1535,20 @@ func (ctxt *Link) hostlink() { - } - - if ctxt.Arch.InFamily(sys.ARM, sys.ARM64) && buildcfg.GOOS == "linux" { -- // On ARM, the GNU linker will generate COPY relocations -- // even with -znocopyreloc set. -+ // On ARM, older versions of the GNU linker will generate -+ // COPY relocations even with -znocopyreloc set. - // https://sourceware.org/bugzilla/show_bug.cgi?id=19962 - // -- // On ARM64, the GNU linker will fail instead of -- // generating COPY relocations. -+ // On ARM64, older versions of the GNU linker will fail -+ // instead of generating COPY relocations. - // -- // In both cases, switch to gold. -- altLinker = "gold" -- -- // If gold is not installed, gcc will silently switch -- // back to ld.bfd. So we parse the version information -- // and provide a useful error if gold is missing. -+ // In both cases, switch to gold if gold is available. - name, args := flagExtld[0], flagExtld[1:] - args = append(args, "-fuse-ld=gold", "-Wl,--version") - cmd := exec.Command(name, args...) - if out, err := cmd.CombinedOutput(); err == nil { -- if !bytes.Contains(out, []byte("GNU gold")) { -- log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out) -+ if bytes.Contains(out, []byte("GNU gold")) { -+ altLinker = "gold" - } - } - } diff --git a/golang/golang/patches/001-default-enable-mptcp.patch b/golang/golang/patches/001-default-enable-mptcp.patch new file mode 100644 index 000000000..68de599e2 --- /dev/null +++ b/golang/golang/patches/001-default-enable-mptcp.patch @@ -0,0 +1,11 @@ +--- a/src/net/dial.go 2023-05-06 10:33:54.275030044 +0200 ++++ b/src/net/dial.go 2023-05-06 10:34:29.218440686 +0200 +@@ -18,7 +18,7 @@ + + // For the moment, MultiPath TCP is not used by default + // See go.dev/issue/56539 +- defaultMPTCPEnabled = false ++ defaultMPTCPEnabled = true + ) + + // mptcpStatus is a tristate for Multipath TCP, see go.dev/issue/56539 From 9c1c926ad4885b60f5c5b38cac8f18ebfceb2805 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 May 2023 14:01:23 +0200 Subject: [PATCH 0964/2059] Fix ndpi-netfilter compilation on all platforms --- ndpi-netfilter2/Makefile | 2 ++ ndpi-netfilter2/patches/outline-atomics.patch | 14 +++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index a91cdaaf7..7eee4b671 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -20,6 +20,8 @@ PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_URL:=https://github.com/vel21ripn/nDPI.git PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_BUILD_PARALLEL:=0 + PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk diff --git a/ndpi-netfilter2/patches/outline-atomics.patch b/ndpi-netfilter2/patches/outline-atomics.patch index a0935ecea..72dace62c 100644 --- a/ndpi-netfilter2/patches/outline-atomics.patch +++ b/ndpi-netfilter2/patches/outline-atomics.patch @@ -1,17 +1,13 @@ --- a/ndpi-netfilter/src/Makefile 2022-08-03 21:27:52.321058402 +0200 +++ b/ndpi-netfilter/src/Makefile 2022-08-03 21:28:27.572452447 +0200 -@@ -5,6 +5,14 @@ +@@ -5,6 +5,10 @@ ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -I${src}/../libre -I${src}/${NDPI_SRC}/lib/third_party/include ccflags-y += -DHAVE_CONFIG_H -DNDPI_LIB_COMPILATION -DOPENDPI_NETFILTER_MODULE -DNDPI_DETECTION_SUPPORT_IPV6 -g ccflags-y += -Wno-declaration-after-statement -+ifneq ($(KERNEL_RELEASE),5.4) -+ifeq ($(ARCH),arm64) -+ ccflags-y += -mno-outline-atomics -+endif -+ifeq ($(ARCH),aarch64) -+ ccflags-y += -mno-outline-atomics -+endif -+endif ++cc-option = $(shell if $(CC) -Werror $(1) -S -o /dev/null -xc /dev/null \ ++ > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) ++mno_outline_atomics := $(call cc-option, -mno-outline-atomics, "") ++ccflags-y += $(mno_outline_atomics) #ccflags-y += -Wshadow-local # Needed for pahole #ccflags-y += -femit-struct-debug-detailed=any From 7fcfd3be0702d6f60c27af094abd2a15446a7635 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 25 May 2023 13:09:49 +0200 Subject: [PATCH 0965/2059] omr-bypass: New way to bypass services without nDPI --- luci-app-omr-bypass/Makefile | 2 +- .../resources/view/services/omr-bypass.js | 50 ++++-- .../root/etc/init.d/omr-bypass | 125 ++++++++++++++- .../usr/share/omr-bypass/omr-bypass-proto.lst | 150 ++++++++++++++++++ .../root/usr/share/omr-bypass/omr-bypass.db | Bin 0 -> 2342912 bytes .../share/rpcd/acl.d/luci-app-omr-bypass.json | 3 +- 6 files changed, 310 insertions(+), 20 deletions(-) create mode 100644 luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst create mode 100644 luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index 0c92a8bf8..bca6d24e6 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables -LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +iptables +LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +iptables +sqlite3-cli PKG_LICENSE:=GPLv3 diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js index 59efc4eec..5f6485dde 100644 --- a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js +++ b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js @@ -15,11 +15,15 @@ return L.view.extend({ }), load: function() { - return this.callHostHints(); + return Promise.all([ + L.resolveDefault(fs.stat('/proc/net/xt_ndpi/proto'), null), + this.callHostHints() + ]); }, - render: function(hosts) { - var m, s, o; + render: function(testhosts) { + var m, s, o, hosts; + hosts = testhosts[1]; m = new form.Map('omr-bypass', _('OMR-Bypass'),_('OpenMPTCProuter IP must be used as DNS.')); @@ -215,21 +219,33 @@ return L.view.extend({ o.rmempty = false; o.load = function(section_id) { return Promise.all([ - fs.read_direct('/proc/net/xt_ndpi/proto'), - fs.read_direct('/proc/net/xt_ndpi/host_proto') + L.resolveDefault(fs.read_direct('/proc/net/xt_ndpi/proto'), ''), + L.resolveDefault(fs.read_direct('/proc/net/xt_ndpi/host_proto'), ''), + fs.read_direct('/usr/share/omr-bypass/omr-bypass-proto.lst') ]).then(L.bind(function(filesi) { var proto = filesi[0].split(/\n/), host = filesi[1].split(/\n/), + protofile = filesi[2].split(/\n/), name = []; - for (var i = 0; i < proto.length; i++) { - var m = proto[i].split(/\s+/); - if (m && m[0] != "#id" && m[1] != "disabled") - name.push(m[2]); + if (proto.length > 2) { + for (var i = 0; i < proto.length; i++) { + var m = proto[i].split(/\s+/); + if (m && m[0] != "#id" && m[1] != "disabled") + name.push(m[2]); + } } - for (var i = 0; i < host.length; i++) { - var m = host[i].split(/:/); - if (m && m[0] != "#Proto") - name.push(m[0].toLowerCase()); + if (host.length > 2) { + for (var i = 0; i < host.length; i++) { + var m = host[i].split(/:/); + if (m && m[0] != "#Proto") + name.push(m[0].toLowerCase()); + } + } + if (proto.length == 1 && host.length == 1) { + for (var i = 0; i < protofile.length; i++) { + var m = protofile[i]; + name.push(m); + } } name = Array.from(new Set(name)).sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase())}).reduce(function(a, b){ if (a.slice(-1)[0] !== b) a.push(b);return a;},[]); for (var i = 0; i < name.length; i++) { @@ -258,9 +274,11 @@ return L.view.extend({ o.default = o.enabled; o.modalonly = true - o = s.option(form.Flag, 'ndpi', _('Enable ndpi')); - o.default = o.enabled; - o.modalonly = true + if (testhosts[0]) { + o = s.option(form.Flag, 'ndpi', _('Enable ndpi')); + o.default = o.enabled; + o.modalonly = true + } return m.render(); } diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 65f308e27..5304b1a06 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -45,6 +45,12 @@ _add_proto() { done } +_add_proto_without_ndpi() { + protoname=$1 + [ -z "$protoname" ] && return + echo "$protoname" >> /usr/share/omr-bypass/omr-bypass-proto.lst +} + _bypass_ip() { local ip=$1 local type=$2 @@ -469,6 +475,111 @@ _bypass_proto() { fi } +_bypass_proto_without_ndpi() { + local proto + local intf + local enabled + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + config_get ndpi $1 ndpi + config_get noipv6 $1 noipv6 + config_get family $1 family + [ "$enabled" = "0" ] && return + [ -z "$noipv6" ] && noipv6="0" + [ -z "$family" ] && family="ipv4ipv6" + intf=$(echo $intf | sed -e 's/\./_/') + [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$proto" ] && return + if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ]; then + ipset -q flush bypass_$proto > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create bypass_$proto hash:net hashsize 64 + EOF + ALLIPS=$(sqlite3 omr-bypass.db "select ip from ipproto where proto='"$proto"';" ".exit") + for ip in $ALLIPS; do + ipset -q add bypass_$proto $ip + done + if [ "$intf" = "all" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m set --match-set $proto -j MARK --set-mark 0x539 + -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m set --match-set $proto -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN + COMMIT + EOF + fi + else + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m set --match-set $proto -j MARK --set-mark 0x539$intfid + -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m set --match-set $proto -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN + COMMIT + EOF + fi + fi + fi + # Use dnsmasq ipset to bypass domains of the proto + local domains + #domains="$(cat /proc/net/xt_ndpi/host_proto | grep -i $proto: | sed -e "s/$proto://i" -e 's/*//' -e 's/,/ /g')" + domains=$(sqlite3 omr-bypass.db "select host from hostproto where proto='"$proto"';" ".exit") + if [ -n "$domains" ]; then + tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` + for domain in $domains; do + if [ -n "$domain" ]; then + domain="$(echo $domain | sed 's/^\.//')" + if [ "$(echo $domain | grep '\.$')" != "" ]; then + domainlist="" + # construct list of domains to query + i=0 + for tld in $tlds; do + i=$((i+1)) + # trim off header + if [ "$i" -lt "12" ] || [ "$i" -gt "50" ]; then + continue + fi + # add to command + domainlist="${domainlist} ${domain}${tld}" + done + domainlist="$(echo $domainlist `# Get the list of valid domains, pass it to awk` \ + | awk '{print tolower($0)}' `# awk lowercases the whole string and passes it to ` \ + | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ + dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ + | awk '{print $1}' `# awk, which outputs queried domain to` \ + | sed -e 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com)` to \ + | grep $domain `# grep, only keep wanted domain` \ + | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate + for validdomain in $domainlist; do + _bypass_domain $validdomain $intf $family $noipv6 + done + else + _bypass_domain $domain $intf $family $noipv6 + fi + fi + done + fi +} + _intf_rule_ss_rules() { rule_name=$1 [ "$rule_name" = "ss_rules" ] && rule_name="def" @@ -760,8 +871,10 @@ start_service() { #local count logger -t "omr-bypass" "Starting OMR-ByPass..." add_domains="false" - [ -d /proc/net/xt_ndpi ] && config_load omr-bypass - config_foreach _add_proto proto + [ -d /proc/net/xt_ndpi ] && { + config_load omr-bypass + config_foreach _add_proto proto + } disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" #noipv6="$(uci -q get omr-bypass.global.noipv6)" @@ -877,6 +990,7 @@ start_service() { fi config_load omr-bypass [ -d /proc/net/xt_ndpi/proto ] && config_foreach _bypass_proto dpis + config_foreach _bypass_proto_without_ndpi dpis uci -q commit omr-bypass [ -z "$RELOAD" ] && [ "$add_domains" = "true" ] && { @@ -887,6 +1001,13 @@ start_service() { logger -t "omr-bypass" "Reload dnsmasq..." /etc/init.d/dnsmasq reload } + + # Create a protocol list for UI from a sqlite DB when NDPI is not available + sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst + config_load omr-bypass + config_foreach _add_proto_without_ndpi proto + sort -o /usr/share/omr-bypass/omr-bypass-proto.lst /usr/share/omr-bypass/omr-bypass-proto.lst + logger -t "omr-bypass" "OMR-ByPass is running" } diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst new file mode 100644 index 000000000..8e24f9282 --- /dev/null +++ b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst @@ -0,0 +1,150 @@ +1kxun +accuweather +activision +ads_analytic_track +adultcontent +alibaba +amazon +amazonalexa +amazonaws +amazonvideo +anydesk +apple +appleicloud +appleitunes +applepush +applesiri +applestore +appletvplus +azure +badoo +bittorrent +bloomberg +cachefly +cloudflare +cloudflarewarp +cnn +crashlytics +cybersec +dailymotion +datasaver +dazn +deezer +directv +discord +disneyplus +dnscrypt +doh_dot +dropbox +eaq +ebay +facebook +fbookreelstory +fuze +github +gitlab +gmail +google +googleclassroom +googlecloud +googledocs +googledrive +googlehangout +googlemaps +googleplus +googleservices +goto +hbo +hotspotshield +hulu +icloudprivaterelay +iflix +iheartradio +instagram +kakaotalk +lastfm +likee +line +linkedin +livestream +messenger +microsoft +microsoft365 +ms_onedrive +netflix +nintendo +ntop +ocs +ocsp +ookla +opendns +outlook +pandora +pastebin +pinterest +playstation +playstore +pluralsight +ppstream +psiphon +qq +reddit +riotgames +salesforce +showtime +signal +sina +sina(weibo) +siriusxmradio +skype_teams +slack +snapchat +softether +soundcloud +spotify +steam +syncthing +tailscale +teams +teamviewer +telegram +tencentvideo +tidal +tiktok +tor +tuenti +tumblr +tunein +tunnelbear +twitch +twitter +ubuntuone +vevo +viber +vidto +vimeo +vk +vudu +waze +webex +wechat +whatsapp +whatsappfiles +wikipedia +windowsupdate +worldofwarcraft +xbox +xiaomi +yahoo +yandex +yandexcloud +yandexdirect +yandexdisk +yandexmail +yandexmarket +yandexmetrika +yandexmusic +youtube +youtubeupload +zattoo +zoom \ No newline at end of file diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db new file mode 100644 index 0000000000000000000000000000000000000000..2c0740b08d461188726e968e50ddeaaed0fec8e5 GIT binary patch literal 2342912 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ⅆ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

    -jszj>?WvF1&S%o2e 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 z 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
    $OH!M*_~}LGGvT7wB({@ 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 z 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

    coWn)Yl!jkm;Oj=WZ1OZ^zhdON`3e$r| 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

    !gYmX3lq_t|3CjG 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ԍJfz$gnf~f!%<|6Y8Q-GJ+Hdn+|fdY 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 Date: Thu, 25 May 2023 13:11:37 +0200 Subject: [PATCH 0966/2059] feat: support orange and free bypass (#186) --- contributors/yostyle.md | 9 ++++++++ .../root/etc/uci-defaults/41_omr-bypass | 23 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 contributors/yostyle.md diff --git a/contributors/yostyle.md b/contributors/yostyle.md new file mode 100644 index 000000000..621b22d52 --- /dev/null +++ b/contributors/yostyle.md @@ -0,0 +1,9 @@ +2023-05-23 + +I hereby agree to the terms of the "OpenMPTCProuter Individual Contributor License Agreement", with MD5 checksum bc827a07eb93611d793ddb7c75083c00. + +I furthermore declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +Yoan Pintas https://github.com/yostyle diff --git a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass index 394829cc0..8613d3bc3 100755 --- a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass +++ b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass @@ -118,6 +118,29 @@ if [ "$(uci -q get omr-bypass.amazonvideo)" = "" ]; then commit omr-bypass EOF fi +if [ "$(uci -q get omr-bypass.free)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set omr-bypass.free=proto + add_list omr-bypass.free.url='free.fr' + add_list omr-bypass.free.url='freebox.fr' + add_list omr-bypass.free.url='oqee.tv' + add_list omr-bypass.free.url='oqee.net' + commit omr-bypass + EOF +fi +if [ "$(uci -q get omr-bypass.orange)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set omr-bypass.orange=proto + add_list omr-bypass.orange.url='orange.fr' + add_list omr-bypass.orange.url='sosh.fr' + add_list omr-bypass.orange.url='liveperson.net' + add_list omr-bypass.orange.url='liveperson.com' + add_list omr-bypass.orange.url='lpsn.net' + add_list omr-bypass.orange.url='lpsnmedia.net' + add_list omr-bypass.orange.url='francetelecom.fr' + commit omr-bypass + EOF +fi #if [ "$(uci -q get omr-bypass.global)" = "" ]; then # uci -q batch <<-EOF >/dev/null # set omr-bypass.global=global From 4747aa184baf96154340af3421b18463616d3a45 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 26 May 2023 13:24:32 +0200 Subject: [PATCH 0967/2059] Fix for vnstat --- openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat b/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat index 749b10680..823bc4d74 100755 --- a/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat +++ b/openmptcprouter/files/etc/uci-defaults/1970-omr-vnstat @@ -33,6 +33,7 @@ if [ ! -f /etc/crontabs/root ] || [ "$(cat /etc/crontabs/root | grep vnstat)" = echo "0 */2 * * * /etc/init.d/vnstat_backup backup" >> /etc/crontabs/root fi -ln -sf /usr/lib/libwebp.so /usr/lib/libwebp.so.7 +# Fix libwebp link +ln -sf $(find /usr/lib -type f -name "libwebp.so.*" | tail -1) /usr/lib/libwebp.so exit 0 From 4f52b59d9879ec159438e86239254b4b56cd7936 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 26 May 2023 21:31:06 +0200 Subject: [PATCH 0968/2059] Fix OMR-ByPass --- .../root/etc/init.d/omr-bypass | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 5304b1a06..92b0a6240 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -482,7 +482,7 @@ _bypass_proto_without_ndpi() { config_get proto $1 proto config_get intf $1 interface config_get enabled $1 enabled - config_get ndpi $1 ndpi + config_get ndpi $1 ndpi "0" config_get noipv6 $1 noipv6 config_get family $1 family [ "$enabled" = "0" ] && return @@ -499,7 +499,7 @@ _bypass_proto_without_ndpi() { ipset -q --exist restore <<-EOF create bypass_$proto hash:net hashsize 64 EOF - ALLIPS=$(sqlite3 omr-bypass.db "select ip from ipproto where proto='"$proto"';" ".exit") + ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto='"$proto"';" ".exit") for ip in $ALLIPS; do ipset -q add bypass_$proto $ip done @@ -507,7 +507,7 @@ _bypass_proto_without_ndpi() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m set --match-set $proto -j MARK --set-mark 0x539 + -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539 -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN COMMIT EOF @@ -515,7 +515,7 @@ _bypass_proto_without_ndpi() { if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m set --match-set $proto -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539 -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN COMMIT EOF @@ -524,7 +524,7 @@ _bypass_proto_without_ndpi() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m set --match-set $proto -j MARK --set-mark 0x539$intfid + -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539$intfid -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN COMMIT EOF @@ -532,7 +532,7 @@ _bypass_proto_without_ndpi() { if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m set --match-set $proto -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539$intfid -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN COMMIT EOF @@ -542,7 +542,7 @@ _bypass_proto_without_ndpi() { # Use dnsmasq ipset to bypass domains of the proto local domains #domains="$(cat /proc/net/xt_ndpi/host_proto | grep -i $proto: | sed -e "s/$proto://i" -e 's/*//' -e 's/,/ /g')" - domains=$(sqlite3 omr-bypass.db "select host from hostproto where proto='"$proto"';" ".exit") + domains=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select host from hostproto where proto='"$proto"';" ".exit") if [ -n "$domains" ]; then tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` for domain in $domains; do @@ -555,7 +555,7 @@ _bypass_proto_without_ndpi() { for tld in $tlds; do i=$((i+1)) # trim off header - if [ "$i" -lt "12" ] || [ "$i" -gt "50" ]; then + if [ "$i" -lt "2" ] || [ "${#tld}" -gt "3" ]; then continue fi # add to command @@ -566,7 +566,7 @@ _bypass_proto_without_ndpi() { | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ | awk '{print $1}' `# awk, which outputs queried domain to` \ - | sed -e 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com)` to \ + | sed 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com) to` \ | grep $domain `# grep, only keep wanted domain` \ | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate for validdomain in $domainlist; do @@ -1006,8 +1006,7 @@ start_service() { sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass config_foreach _add_proto_without_ndpi proto - sort -o /usr/share/omr-bypass/omr-bypass-proto.lst /usr/share/omr-bypass/omr-bypass-proto.lst - + sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst logger -t "omr-bypass" "OMR-ByPass is running" } From b80d40f5ec8da7fd9c2ee7a31ebddff198b54e29 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 26 May 2023 21:31:30 +0200 Subject: [PATCH 0969/2059] Fix on route --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 506828a73..5c12d788f 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1147,7 +1147,7 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_route_balancing interface #config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { - ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { + ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n' | sed 's/ *$//')" != "default via $routesbalancing" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n' | sed 's/ *$//')" != "default $routesbalancing" ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Change in routes, set ip route replace default scope global $routesbalancing (omrvpn_intf: $omrvpn_intf)" [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Current route: $(ip r)" ip route replace default scope global metric 1 $routesbalancing 2>&1 >/dev/null @@ -1161,7 +1161,7 @@ if [ "$multipath_config" = "master" ]; then # } #} [ -n "$routesbalancingbackup" ] && { - ([ "$nbintfb" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { + ([ "$nbintfb" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ])) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { _log "Set backup ip route replace default scope global metric 999 $routesbalancingbackup" ip route replace default scope global metric 999 $routesbalancingbackup 2>&1 >/dev/null } @@ -1180,13 +1180,13 @@ if [ "$multipath_config" = "master" ]; then config_load network config_foreach set_route_balancing6 interface [ -n "$routesbalancing6" ] && { - ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { + ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" ip -6 route replace default scope global metric 1 $routesbalancing6 2>&1 >/dev/null } } [ -n "$routesbalancingbackup6" ] && { - ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { + ([ "$nbintfb6" -gt "1" ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup6 " ] && [ "$(ip -6 r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default $routesbalancingbackup6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { _log "Set backup ip -6 route replace default scope global $routesbalancingbackup6" ip -6 route replace default scope global metric 999 $routesbalancingbackup6 2>&1 >/dev/null } From 88e16d51f1a950a1e5fab8a92ef47a221333aea6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 28 May 2023 07:51:38 +0200 Subject: [PATCH 0970/2059] Do no create ipset if there is no empty for a protocol --- .../root/etc/init.d/omr-bypass | 84 ++++++++++--------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 92b0a6240..95c298bb4 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -495,47 +495,49 @@ _bypass_proto_without_ndpi() { [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ]; then - ipset -q flush bypass_$proto > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create bypass_$proto hash:net hashsize 64 - EOF - ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto='"$proto"';" ".exit") - for ip in $ALLIPS; do - ipset -q add bypass_$proto $ip - done - if [ "$intf" = "all" ]; then - if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539 - -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539 - -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN - COMMIT - EOF - fi - else - if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539$intfid - -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539$intfid - -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN - COMMIT - EOF + ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") + if [ -n "$ALLIPS" ]; then + ipset -q flush bypass_$proto > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create bypass_$proto hash:net hashsize 64 + EOF + for ip in $ALLIPS; do + ipset -q add bypass_$proto $ip + done + if [ "$intf" = "all" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539 + -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN + COMMIT + EOF + fi + else + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539$intfid + -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN + COMMIT + EOF + fi fi fi fi From fb63e3779a778619b509684e3e862e8bae060b33 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 29 May 2023 08:10:45 +0200 Subject: [PATCH 0971/2059] remove previsouly created ipset --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 95c298bb4..31045864d 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -1020,6 +1020,9 @@ stop_service() { for setname in $(ipset -n list | grep "omr_"); do ipset -q destroy "$setname" 2>/dev/null || true done + for setname in $(ipset list | awk '/Name: bypass_/ {print $2}'); do + ipset -q destroy "$setname" 2>/dev/null || true + done } service_triggers() { From 06e55401aad5d40caaa4e3d6e070171c30b78242 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 1 Jun 2023 19:54:32 +0200 Subject: [PATCH 0972/2059] Fix & update sqm autorate --- luci-app-sqm-autorate/Makefile | 2 +- .../root/etc/init.d/sqm-autorate | 5 +- .../usr/share/sqm-autorate/cake-autorate.sh | 1674 ++++++++++------- .../sqm-autorate/cake-autorate_defaults.sh | 10 +- .../share/sqm-autorate/cake-autorate_lib.sh | 205 +- .../sqm-autorate/cake-autorate_template.sh | 61 +- tsping/Makefile | 38 + 7 files changed, 1111 insertions(+), 884 deletions(-) create mode 100644 tsping/Makefile diff --git a/luci-app-sqm-autorate/Makefile b/luci-app-sqm-autorate/Makefile index df160a3e5..51c3b4497 100644 --- a/luci-app-sqm-autorate/Makefile +++ b/luci-app-sqm-autorate/Makefile @@ -8,7 +8,7 @@ LUCI_DESCRIPTION:=Luci interface for the SQM scripts queue management package wi PKG_MAINTAINER:=Toke Høiland-Jørgensen -LUCI_DEPENDS:=+sqm-scripts +bash +LUCI_DEPENDS:=+sqm-scripts +bash +tsping LUCI_PKGARCH:=all include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 7ab556492..11b766808 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -29,8 +29,9 @@ _config_autorate() { config_get upload "$1" upload config_get max_upload "$1" max_upload [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return - config_get interface "$1" interface - cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh +# config_get interface "$1" interface +# cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh + cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.$1.sh } _launch_autorate() { diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh index 426c08579..eda0680a4 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh @@ -14,13 +14,32 @@ # Author: @Lynx (OpenWrt forum) # Inspiration taken from: @moeller0 (OpenWrt forum) +cake_autorate_version="2.0.0" + +## cake-autorate uses multiple asynchronous processes including +## main - main process +## monitor_achieved_rates - monitor network transfer rates +## maintain_pingers - manage pingers and active reflectors +## parse_${pinger_binary} - control and parse ping responses +## parse_preprocessor - prepend field for parse_${pinger_binary} +## maintain_log_file - maintain and rotate log file +## +## IPC is facilitated via FIFOs in the form of anonymous pipes +## accessible via fds in the form: ${process_name_fd} +## thereby to enable transferring commands and data between processes + # Initialize file descriptors ## -1 signifies that the log file fd will not be used and ## that the log file will be written to directly log_fd=-1 -## ping_fd should be open for the duration of the script -## as it's integral to the operation of the script -exec {ping_fd}<> <(:) || true +exec {main_fd}<> <(:) || true +exec {monitor_achieved_rates_fd}<> <(:) || true +exec {maintain_pingers_fd}<> <(:) || true +# pinger_fds are set below in dependence upon ping binary and number of pingers + +# process pids are stored below in the form +# proc_pids['process_identifier']=${!} +declare -A proc_pids # Bash correctness options ## Disable globbing (expansion of *). @@ -32,6 +51,9 @@ set -u ## command exited with a non-zero status. set -o pipefail +## Errors are intercepted via intercept_stderr below +## and sent to the log file and system log + # Possible performance improvement export LC_ALL=C @@ -55,13 +77,25 @@ cleanup_and_killall() log_msg "INFO" "Killing all background processes and cleaning up temporary files." - proc_man_stop maintain_pingers - proc_man_stop monitor_achieved_rates - proc_man_stop maintain_log_file + printf "TERMINATE\n" >&"${maintain_pingers_fd}" + printf "TERMINATE\n" >&"${monitor_achieved_rates_fd}" [[ -d "${run_path}" ]] && rm -r "${run_path}" rmdir /var/run/cake-autorate 2>/dev/null + # give some time for processes to gracefully exit + sleep_s 1 + + # terminate any processes that remain, save for main and intercept_stderr + unset proc_pids[main] + intercept_stderr_pid="${proc_pids[intercept_stderr]}" + unset proc_pids[intercept_stderr] + terminate "${proc_pids[@]}" + + # restore original stderr, and terminate intercept_stderr + exec 2>&"${original_stderr_fd}" + terminate "${intercept_stderr_pid}" + log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}" trap - INT TERM EXIT @@ -72,9 +106,9 @@ log_msg() { # send logging message to terminal, log file fifo, log file and/or system logger - local type=${1} - local msg=${2} - local instance_id=${instance_id:-"unknown"} + local type="${1}" + local msg="${2}" + local instance_id="${instance_id:-"unknown"}" case ${type} in @@ -122,7 +156,7 @@ print_headers() ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" ((terminal)) && printf '%s\n' "${header}" - header="REFLECTOR_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; REFLECTOR; DL_MIN_BASELINE_US; DL_BASELINE_US; DL_BASELINE_DELTA_US; DL_BASELINE_DELTA_THR_US; DL_MIN_DELTA_EWMA_US; DL_DELTA_EWMA_US; DL_DELTA_EWMA_DELTA_US; DL_DELTA_EWMA_DELTA_THR; UL_MIN_BASELINE_US; UL_BASELINE_US; UL_BASELINE_DELTA_US; UL_BASELINE_DELTA_THR_US; UL_MIN_DELTA_EWMA_US; UL_DELTA_EWMA_US; UL_DELTA_EWMA_DELTA_US; UL_DELTA_EWMA_DELTA_THR" + header="REFLECTOR_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; REFLECTOR; MIN_SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_DELTA_US; SUM_OWD_BASELINES_DELTA_THR_US; MIN_DL_DELTA_EWMA_US; DL_DELTA_EWMA_US; DL_DELTA_EWMA_DELTA_US; DL_DELTA_EWMA_DELTA_THR; MIN_UL_DELTA_EWMA_US; UL_DELTA_EWMA_US; UL_DELTA_EWMA_DELTA_US; UL_DELTA_EWMA_DELTA_THR" ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" ((terminal)) && printf '%s\n' "${header}" } @@ -141,19 +175,17 @@ rotate_log_file() ((output_processing_stats)) && print_headers } -generate_log_file_exporter() +generate_log_file_scripts() { - cat > "${run_path}/export_log_file" <<- EOT + cat > "${run_path}/log_file_export" <<- EOT #!/bin/bash - . "${PREFIX}/cake-autorate_lib.sh" - PROC_STATE_FILE="${run_path}/proc_state" - PROC_STATE_FILE_LOCK="${run_path}/proc_state.lock" - timeout_s=\${1:-20} - if ! proc_man_signal maintain_log_file "USR1" + if kill -USR1 "${proc_pids['maintain_log_file']}" then + printf "Successfully signalled maintain_log_file process to request log file export.\n" + else printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 exit 1 fi @@ -178,7 +210,19 @@ generate_log_file_exporter() printf "\${log_file_export_path}\n" EOT - chmod +x "${run_path}/export_log_file" + cat > "${run_path}/log_file_rotate" <<- EOT + #!/bin/bash + + if kill -USR2 "${proc_pids['maintain_log_file']}" + then + printf "Successfully signalled maintain_log_file process to request log file rotation.\n" + else + printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 + exit 1 + fi + EOT + + chmod +x "${run_path}/log_file_export" "${run_path}/log_file_rotate" } export_log_file() @@ -238,9 +282,11 @@ maintain_log_file() trap '' INT trap 'kill_maintain_log_file' TERM EXIT trap 'export_log_file' USR1 + trap 'rotate_log_file_signalled=1' USR2 log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + rotate_log_file_signalled=0 t_log_file_start_us=${EPOCHREALTIME/./} get_log_file_size_bytes @@ -260,17 +306,21 @@ maintain_log_file() ((log_file_size_bytes=log_file_size_bytes+${#log_line}+1)) # Verify log file time < configured maximum - if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )); then + if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) + then log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so rotating log file" break - fi - - if (( log_file_size_bytes > log_file_max_size_bytes )); then - + elif (( log_file_size_bytes > log_file_max_size_bytes )) + then log_file_size_KB=$((log_file_size_bytes/1024)) log_msg "DEBUG" "log file size: ${log_file_size_KB} KB has exceeded configured maximum: ${log_file_max_size_KB} KB so rotating log file" break + elif (( rotate_log_file_signalled )) + then + log_msg "DEBUG" "received log file rotation signal so rotating log file." + rotate_log_file_signalled=0 + break fi done @@ -285,64 +335,56 @@ maintain_log_file() get_next_shaper_rate() { - local min_shaper_rate_kbps=${1} - local base_shaper_rate_kbps=${2} - local max_shaper_rate_kbps=${3} - local achieved_rate_kbps=${4} - local load_condition=${5} - local t_next_rate_us=${6} - local -n t_last_bufferbloat_us=${7} - local -n t_last_decay_us=${8} - local -n shaper_rate_kbps=${9} + local direction="${1}" # 'dl' or 'ul' - case ${load_condition} in + case "${load_condition["${direction}"]}" in # upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period ul*sss) - shaper_rate_kbps=${min_shaper_rate_kbps} + shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" ;; # download Starlink satelite switching compensation, so drop down to base rate for download through switching period dl*sss) - shaper_rate_kbps=$(( shaper_rate_kbps > base_shaper_rate_kbps ? base_shaper_rate_kbps : shaper_rate_kbps )) + shaper_rate_kbps["${direction}"]=$(( shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"] ? base_shaper_rate_kbps["${direction}"] : shaper_rate_kbps["${direction}"] )) ;; # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period *bb*) - if (( t_next_rate_us > (t_last_bufferbloat_us+bufferbloat_refractory_period_us) )); then - adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps*achieved_rate_adjust_down_bufferbloat)/1000 )) - adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_down_bufferbloat)/1000 )) - shaper_rate_kbps=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) - t_last_bufferbloat_us=${EPOCHREALTIME/./} + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then + adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps["${direction}"]*achieved_rate_adjust_down_bufferbloat)/1000 )) + adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_bufferbloat)/1000 )) + shaper_rate_kbps["${direction}"]=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps["${direction}"] && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) + t_last_bufferbloat_us["${direction}"]="${EPOCHREALTIME/./}" fi ;; # high load, so increase rate providing not inside bufferbloat refractory period *high*) - if (( t_next_rate_us > (t_last_bufferbloat_us+bufferbloat_refractory_period_us) )); then - shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_up_load_high)/1000 )) + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then + shaper_rate_kbps["${direction}"]=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_high)/1000 )) fi ;; # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate *low*|*idle*) - if (( t_next_rate_us > (t_last_decay_us+decay_refractory_period_us) )); then + if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )); then - if ((shaper_rate_kbps > base_shaper_rate_kbps)); then - decayed_shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_down_load_low)/1000 )) - shaper_rate_kbps=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps ? decayed_shaper_rate_kbps : base_shaper_rate_kbps)) - elif ((shaper_rate_kbps < base_shaper_rate_kbps)); then - decayed_shaper_rate_kbps=$(( (shaper_rate_kbps*shaper_rate_adjust_up_load_low)/1000 )) - shaper_rate_kbps=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps ? decayed_shaper_rate_kbps : base_shaper_rate_kbps)) + if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])); then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_load_low)/1000 )) + shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) + elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])); then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_low)/1000 )) + shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) fi - t_last_decay_us=${EPOCHREALTIME/./} + t_last_decay_us["${direction}"]="${EPOCHREALTIME/./}" fi ;; *) - log_msg "ERROR" "unknown load condition: ${load_condition} in get_next_shaper_rate" + log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in get_next_shaper_rate" exit 1 ;; esac # make sure to only return rates between cur_min_rate and cur_max_rate - ((shaper_rate_kbps < min_shaper_rate_kbps)) && shaper_rate_kbps=${min_shaper_rate_kbps} - ((shaper_rate_kbps > max_shaper_rate_kbps)) && shaper_rate_kbps=${max_shaper_rate_kbps} + ((shaper_rate_kbps["${direction}"] < min_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" + ((shaper_rate_kbps["${direction}"] > max_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${max_shaper_rate_kbps[${direction}]}" } monitor_achieved_rates() @@ -352,87 +394,110 @@ monitor_achieved_rates() # track rx and tx bytes transfered and divide by time since last update # to determine achieved dl and ul transfer rates - local rx_bytes_path=${1} - local tx_bytes_path=${2} - local monitor_achieved_rates_interval_us=${3} # (microseconds) + local rx_bytes_path="${1}" + local tx_bytes_path="${2}" + local monitor_achieved_rates_interval_us="${3}" # (microseconds) log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - compensated_monitor_achieved_rates_interval_us=${monitor_achieved_rates_interval_us} + compensated_monitor_achieved_rates_interval_us="${monitor_achieved_rates_interval_us}" [[ -f "${rx_bytes_path}" ]] && { read -r prev_rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || prev_rx_bytes=0 [[ -f "${tx_bytes_path}" ]] && { read -r prev_tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || prev_tx_bytes=0 + sleep_duration_s=0 + t_start_us=0 + + declare -A achieved_rate_kbps + declare -A load_percent + while true do - t_start_us=${EPOCHREALTIME/./} + t_start_us="${EPOCHREALTIME/./}" + + while read -r -t 0 -u "${monitor_achieved_rates_fd}" + do + unset command + read -r -u "${monitor_achieved_rates_fd}" -a command + case "${command[0]:-}" in + + SET_VAR) + if [[ "${command[1]:-}" && "${command[2]:-}" ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + then + declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + fi + ;; + TERMINATE) + log_msg "DEBUG" "Terminating monitor_achieved_rates." + exit + ;; + *) + : + ;; + esac + done # If rx/tx bytes file exists, read it in, otherwise set to prev_bytes # This addresses interfaces going down and back up - [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes=${prev_rx_bytes} - [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes=${prev_tx_bytes} + [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes="${prev_rx_bytes}" + [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes="${prev_tx_bytes}" - dl_achieved_rate_kbps=$(( ((8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) - ul_achieved_rate_kbps=$(( ((8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) + achieved_rate_kbps[dl]=$(( ((8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) + achieved_rate_kbps[ul]=$(( ((8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) - ((dl_achieved_rate_kbps<0)) && dl_achieved_rate_kbps=0 - ((ul_achieved_rate_kbps<0)) && ul_achieved_rate_kbps=0 + ((achieved_rate_kbps[dl]<0)) && achieved_rate_kbps[dl]=0 + ((achieved_rate_kbps[ul]<0)) && achieved_rate_kbps[ul]=0 - printf '%s' "${dl_achieved_rate_kbps}" > "${run_path}/dl_achieved_rate_kbps" - printf '%s' "${ul_achieved_rate_kbps}" > "${run_path}/ul_achieved_rate_kbps" + printf "SET_ARRAY_ELEMENT achieved_rate_kbps dl %s\n" "${achieved_rate_kbps[dl]}" >&"${main_fd}" + printf "SET_ARRAY_ELEMENT achieved_rate_kbps ul %s\n" "${achieved_rate_kbps[ul]}" >&"${main_fd}" + + load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) + load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) + + for pinger_fd in "${pinger_fds[@]}" + do + printf "SET_ARRAY_ELEMENT load_percent dl %s\n" "${load_percent[dl]}" >&"${pinger_fd}" + printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}" + done if ((output_load_stats)); then - concurrent_read_integer dl_shaper_rate_kbps "${run_path}/dl_shaper_rate_kbps" - concurrent_read_integer ul_shaper_rate_kbps "${run_path}/ul_shaper_rate_kbps" - printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${dl_achieved_rate_kbps}" "${ul_achieved_rate_kbps}" "${dl_shaper_rate_kbps}" "${ul_shaper_rate_kbps}" + printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" log_msg "LOAD" "${load_stats}" fi - prev_rx_bytes=${rx_bytes} - prev_tx_bytes=${tx_bytes} - - # read in the max_wire_packet_rtt_us - concurrent_read_integer max_wire_packet_rtt_us "${run_path}/max_wire_packet_rtt_us" - - compensated_monitor_achieved_rates_interval_us=$(( ((monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) )) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) + prev_rx_bytes="${rx_bytes}" + prev_tx_bytes="${tx_bytes}" + compensated_monitor_achieved_rates_interval_us=$(( monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) + sleep_remaining_tick_time "${t_start_us}" "${compensated_monitor_achieved_rates_interval_us}" + done } -get_loads() -{ - # read in the dl/ul achieved rates and determine the loads - - concurrent_read_integer dl_achieved_rate_kbps "${run_path}/dl_achieved_rate_kbps" - concurrent_read_integer ul_achieved_rate_kbps "${run_path}/ul_achieved_rate_kbps" - - dl_load_percent=$(( (100*dl_achieved_rate_kbps)/dl_shaper_rate_kbps )) - ul_load_percent=$(( (100*ul_achieved_rate_kbps)/ul_shaper_rate_kbps )) - - printf '%s' "${dl_load_percent}" > "${run_path}/dl_load_percent" - printf '%s' "${ul_load_percent}" > "${run_path}/ul_load_percent" -} classify_load() { # classify the load according to high/low/idle and add _delayed if delayed # thus ending up with high_delayed, low_delayed, etc. - local load_percent=${1} - local achieved_rate_kbps=${2} - local bufferbloat_detected=${3} - local -n load_condition=${4} + local direction="${1}" - if (( load_percent > high_load_thr_percent )); then - load_condition="high" - elif (( achieved_rate_kbps > connection_active_thr_kbps )); then - load_condition="low" + if (( load_percent["${direction}"] > high_load_thr_percent )); then + load_condition["${direction}"]="high" + elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )); then + load_condition["${direction}"]="low" else - load_condition="idle" + load_condition["${direction}"]="idle" fi - ((bufferbloat_detected)) && load_condition=${load_condition}"_bb" + ((bufferbloat_detected["${direction}"])) && load_condition["${direction}"]="${load_condition[${direction}]}_bb" if ((sss_compensation)); then # shellcheck disable=SC2154 @@ -440,39 +505,33 @@ classify_load() do ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )); then - load_condition=${load_condition}"_sss" + load_condition[direction]="${load_condition[direction]}_sss" break fi done fi + + load_condition["${direction}"]="${direction}_${load_condition[${direction}]}" } # MAINTAIN PINGERS + ASSOCIATED HELPER FUNCTIONS -# TSPING FUNCTIONS # - -kill_monitor_reflector_responses_tsping() +parse_preprocessor() { - trap - TERM EXIT - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - # Store baselines and ewmas to files ready for next instance (e.g. after sleep) - for (( reflector=0; reflector "${run_path}/reflector_${reflectors[reflector]//./-}_dl_baseline_us" - [[ -n "${ul_owd_baselines_us[${reflectors[reflector]}]}" ]] && printf '%s' "${ul_owd_baselines_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_ul_baseline_us" - [[ -n "${dl_owd_delta_ewmas_us[${reflectors[reflector]}]}" ]] && printf '%s' "${dl_owd_delta_ewmas_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_dl_delta_ewma_us" - [[ -n "${ul_owd_delta_ewmas_us[${reflectors[reflector]}]}" ]] && printf '%s' "${ul_owd_delta_ewmas_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_ul_delta_ewma_us" + printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" done - - exit } -monitor_reflector_responses_tsping() +parse_tsping() { trap '' INT - trap kill_monitor_reflector_responses_tsping TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + local parse_id="${1}" + local reflectors=("${@:2}") log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" @@ -481,266 +540,458 @@ monitor_reflector_responses_tsping() declare -A dl_owd_delta_ewmas_us declare -A ul_owd_delta_ewmas_us - t_start_us=${EPOCHREALTIME/./} - - # Read in baselines if they exist, else just set them to 1s (rapidly converges downwards on new OWDs) - for (( reflector=0; reflector < no_reflectors; reflector++ )) + for (( reflector=0; reflector= dl_owd_baselines_us[${reflector}] )) ? alpha_baseline_increase : alpha_baseline_decrease )) - ul_alpha=$(( (( ul_owd_us >= ul_owd_baselines_us[${reflector}] )) ? alpha_baseline_increase : alpha_baseline_decrease )) + while true + do + unset command + read -r -u "${pinger_fds[pinger]}" -a command + if [[ "${command-}" ]] + then + case "${command[0]}" in - ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" - ewma_iteration "${ul_owd_us}" "${ul_alpha}" "ul_owd_baselines_us[${reflector}]" + REFLECTOR_RESPONSE) + read -r timestamp reflector seq _ _ _ _ _ dl_owd_ms ul_owd_ms checksum <<< "${command[@]:1}" + ;; - dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) - ul_owd_delta_us=$(( ul_owd_us - ul_owd_baselines_us[${reflector}] )) + START_PINGER) + + exec {parse_preprocessor_fd}> >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + # accommodate present tsping interval/sleep handling to prevent ping flood with only one pinger + tsping_sleep_time=$(( no_pingers == 1 ? ping_response_interval_ms : 0 )) + ${ping_prefix_string} tsping ${ping_extra_args} --print-timestamps --machine-readable=' ' --sleep-time "${tsping_sleep_time}" --target-spacing "${ping_response_interval_ms}" "${reflectors[@]:0:${no_pingers}}" 2>/dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; - concurrent_read_integer dl_load_percent "${run_path}/dl_load_percent" - concurrent_read_integer ul_load_percent "${run_path}/ul_load_percent" + KILL_PINGER) - if (( dl_load_percent < high_load_thr_percent && ul_load_percent < high_load_thr_percent)); then - ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" - ewma_iteration "${ul_owd_delta_us}" "${alpha_delta_ewma}" "ul_owd_delta_ewmas_us[${reflector}]" + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; + + SET_REFLECTORS) + + read -r -a reflectors <<< "${command[@]:1}" + log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" + + for (( reflector=0; reflector&"${ping_fd}" + dl_owd_us="${dl_owd_ms}000" + ul_owd_us="${ul_owd_ms}000" - timestamp_us=${timestamp//[.]} + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us=$(( ul_owd_us - ul_owd_baselines_us[${reflector}] )) - printf '%s' "${timestamp_us}" > "${run_path}/reflector_${reflector//./-}_last_timestamp_us" - - printf '%s' "${dl_owd_baselines_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_dl_owd_baseline_us" - printf '%s' "${ul_owd_baselines_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_ul_owd_baseline_us" - - printf '%s' "${dl_owd_delta_ewmas_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_dl_owd_delta_ewma_us" - printf '%s' "${ul_owd_delta_ewmas_us[${reflector}]}" > "${run_path}/reflector_${reflector//./-}_ul_owd_delta_ewma_us" + # tsping employs ICMP type 13 and works with timestamps: Originate; Received; Transmit; and Finished, such that: + # + # dl_owd_us = Finished - Transmit + # ul_owd_us = Received - Originate + # + # The timestamps are supposed to relate to milliseconds past midnight UTC, albeit implementation varies, and, + # in any case, timestamps rollover at the local and/or remote ends, and the rollover may not be synchronized. + # + # Such an event would result in a huge spike in dl_owd_us or ul_owd_us and a lare delta relative to the baseline. + # + # So, to compensate, in the event that delta > 50 mins, immediately reset the baselines to the new dl_owd_us and ul_owd_us. + # + # Happilly, the sum of dl_owd_baseline_us and ul_owd_baseline_us will roughly equal rtt_baseline_us. + # And since Transmit is approximately equal to Received, RTT is approximately equal to Finished - Originate. + # And thus the sum of dl_owd_baseline_us and ul_owd_baseline_us should not be affected by the rollover/compensation. + # Hence working with this sum, rather than the individual components, is useful for the reflector health check in maintain_pingers(). - printf '%s' "${timestamp_us}" > "${run_path}/reflectors_last_timestamp_us" + if (( (${dl_owd_delta_us#-} + ${ul_owd_delta_us#-}) < 3000000000 )) + then + dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + ul_alpha=$(( ul_owd_us >= ul_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ewma_iteration "${ul_owd_us}" "${ul_alpha}" "ul_owd_baselines_us[${reflector}]" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us=$(( ul_owd_us - ul_owd_baselines_us[${reflector}] )) + else + dl_owd_baselines_us[${reflector}]=${dl_owd_us} + ul_owd_baselines_us[${reflector}]=${ul_owd_us} + + dl_owd_delta_us=0 + ul_owd_delta_us=0 + fi + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ewma_iteration "${ul_owd_delta_us}" "${alpha_delta_ewma}" "ul_owd_delta_ewmas_us[${reflector}]" + fi + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]} ${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT reflector_last_timestamps_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + fi done } -# FPING FUNCTIONS # - -kill_monitor_reflector_responses_fping() -{ - trap - TERM EXIT - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - # Store baselines and ewmas to files ready for next instance (e.g. after sleep) - for (( reflector=0; reflector "${run_path}/reflector_${reflectors[reflector]//./-}_baseline_us" - [[ -n "${rtt_delta_ewmas_us[${reflectors[reflector]}]}" ]] && printf '%s' "${rtt_delta_ewmas_us[${reflectors[reflector]}]}" > "${run_path}/reflector_${reflectors[reflector]//./-}_delta_ewma_us" - done - - exit -} - -monitor_reflector_responses_fping() +parse_fping() { trap '' INT - trap kill_monitor_reflector_responses_fping TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + local parse_id="${1}" + + local reflectors=("${@:2}") log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" declare -A rtt_baselines_us declare -A rtt_delta_ewmas_us - t_start_us=${EPOCHREALTIME/./} - - # Read in baselines if they exist, else just set them to 1s (rapidly converges downwards on new RTTs) - for (( reflector=0; reflector < no_reflectors; reflector++ )) + for (( reflector=0; reflector/dev/null - do - t_start_us=${EPOCHREALTIME/./} + declare -A load_percent + load_percent[dl]=0 + load_percent[ul]=0 - [[ ${seq_rtt} =~ \[([0-9]+)\].*[[:space:]]([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + t_start_us="${EPOCHREALTIME/./}" + + while true + do + unset command + read -r -u "${pinger_fds[pinger]}" -a command + if [[ "${command-}" ]] + then + case "${command[0]}" in - seq=${BASH_REMATCH[1]} + REFLECTOR_RESPONSE) - rtt_us=${BASH_REMATCH[3]}000 - rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + read -r timestamp reflector _ seq_rtt <<< "${command[@]:1}" + checksum="${command[@]: -1}" + ;; - alpha=$(( (( rtt_us >= rtt_baselines_us[${reflector}] )) ? alpha_baseline_increase : alpha_baseline_decrease )) + START_PINGER) - ewma_iteration "${rtt_us}" "${alpha}" "rtt_baselines_us[${reflector}]" + exec {parse_preprocessor_fd}> >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + ${ping_prefix_string} fping ${ping_extra_args} --timestamp --loop --period "${reflector_ping_interval_ms}" --interval "${ping_response_interval_ms}" --timeout 10000 "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; - rtt_delta_us=$(( rtt_us-rtt_baselines_us[${reflector}] )) + KILL_PINGER) - concurrent_read_integer dl_load_percent "${run_path}/dl_load_percent" - concurrent_read_integer ul_load_percent "${run_path}/ul_load_percent" + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; - if (( dl_load_percent < high_load_thr_percent && ul_load_percent < high_load_thr_percent)); then - ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" "rtt_delta_ewmas_us[${reflector}]" + SET_REFLECTORS) + + read -r -a reflectors <<< "${command[@]:1}" + log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" + + for (( reflector=0; reflector= rtt_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${rtt_us}" "${alpha}" "rtt_baselines_us[${reflector}]" + + rtt_delta_us=$(( rtt_us-rtt_baselines_us[${reflector}] )) + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)); then + ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" "rtt_delta_ewmas_us[${reflector}]" + fi + + dl_owd_baseline_us=$((rtt_baselines_us[${reflector}]/2)) + ul_owd_baseline_us="${dl_owd_baseline_us}" + + dl_owd_delta_ewma_us=$((rtt_delta_ewmas_us[${reflector}]/2)) + ul_owd_delta_ewma_us="${dl_owd_delta_ewma_us}" + + dl_owd_us=$((rtt_us/2)) + ul_owd_us="${dl_owd_us}" + + dl_owd_delta_us=$((rtt_delta_us/2)) + ul_owd_delta_us="${dl_owd_delta_us}" + + timestamp="${timestamp//[\[\]]}0" + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baseline_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baseline_us}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT reflector_last_timestamps_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi - - dl_owd_baseline_us=$((rtt_baselines_us[${reflector}]/2)) - ul_owd_baseline_us=${dl_owd_baseline_us} - - dl_owd_delta_ewma_us=$((rtt_delta_ewmas_us[${reflector}]/2)) - ul_owd_delta_ewma_us=${dl_owd_delta_ewma_us} - - dl_owd_us=$((rtt_us/2)) - ul_owd_us=${dl_owd_us} - - dl_owd_delta_us=$((rtt_delta_us/2)) - ul_owd_delta_us=${dl_owd_delta_us} - - timestamp=${timestamp//[\[\]]}0 - - printf '%s %s %s %s %s %s %s %s %s %s %s\n' "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${ping_fd}" - - timestamp_us=${timestamp//[.]} - - printf '%s' "${timestamp_us}" > "${run_path}/reflector_${reflector//./-}_last_timestamp_us" - - printf '%s' "${dl_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_baseline_us" - printf '%s' "${ul_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_baseline_us" - - printf '%s' "${dl_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_delta_ewma_us" - printf '%s' "${ul_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_delta_ewma_us" - - printf '%s' "${timestamp_us}" > "${run_path}/reflectors_last_timestamp_us" - - done 2>/dev/null + done } - # IPUTILS-PING FUNCTIONS - -kill_monitor_reflector_responses_ping() -{ - trap - TERM EXIT - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - [[ -n "${rtt_baseline_us:-}" ]] && printf '%s' "${rtt_baseline_us}" > "${run_path}/reflector_${reflectors[pinger]//./-}_baseline_us" - [[ -n "${rtt_delta_ewma_us:-}" ]] && printf '%s' "${rtt_delta_ewma_us}" > "${run_path}/reflector_${reflectors[pinger]//./-}_delta_ewma_us" - exit -} - -monitor_reflector_responses_ping() +parse_ping() { trap '' INT - trap kill_monitor_reflector_responses_ping TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT # ping reflector, maintain baseline and output deltas to a common fifo - local pinger=${1} + local parse_id="${1}" + local reflector="${2}" log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - if [[ -f "${run_path}/reflector_${reflectors[pinger]//./-}_baseline_us" ]]; then - read -r rtt_baseline_us < "${run_path}/reflector_${reflectors[pinger]//./-}_baseline_us" - else - rtt_baseline_us=100000 - fi + declare -A rtt_baselines_us + declare -A rtt_delta_ewmas_us - if [[ -f "${run_path}/reflector_${reflectors[pinger]//./-}_delta_ewma_us" ]]; then - read -r rtt_delta_ewma_us < "${run_path}/reflector_${reflectors[pinger]//./-}_delta_ewma_us" - else - rtt_delta_ewma_us=0 - fi + rtt_baselines_us[${reflector}]=100000 + rtt_delta_ewmas_us[${reflector}]=0 - while read -r -u "${pinger_fds[pinger]}" timestamp _ _ _ reflector seq_rtt 2>/dev/null + declare -A load_percent + load_percent[dl]=0 + load_percent[ul]=0 + + while true do - # If no match then skip onto the next one - [[ ${seq_rtt} =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + unset command + read -r -u "${pinger_fds[pinger]}" -a command + if [[ "${command-}" ]] + then + case "${command[0]}" in - seq=${BASH_REMATCH[1]} + REFLECTOR_RESPONSE) - rtt_us=${BASH_REMATCH[3]}000 - rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + read -r timestamp _ _ _ reflector seq_rtt <<< "${command[@]:1}" + checksum="${command[@]: -1}" + ;; - reflector=${reflector//:/} + START_PINGER) - alpha=$(( (( rtt_us >= rtt_baseline_us )) ? alpha_baseline_increase : alpha_baseline_decrease )) + exec {parse_preprocessor_fd}> >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID %s %s\n" "proc_pids ${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + ${ping_prefix_string} ping ${ping_extra_args} -D -i "${reflector_ping_interval_s}" "${reflector}" 2> /dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; - ewma_iteration "${rtt_us}" "${alpha}" rtt_baseline_us - - rtt_delta_us=$(( rtt_us-rtt_baseline_us )) + KILL_PINGER) - concurrent_read_integer dl_load_percent "${run_path}/dl_load_percent" - concurrent_read_integer ul_load_percent "${run_path}/ul_load_percent" + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; - if (( dl_load_percent < high_load_thr_percent && ul_load_percent < high_load_thr_percent )); then - ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" rtt_delta_ewma_us + SET_REFLECTOR) + + if [[ "${command[1]:-}" ]] + then + reflector="${command[1]}" + log_msg "DEBUG" "Read in new reflector: ${reflector}" + rtt_baselines_us[${reflector}]="${rtt_baselines_us[${reflector}]:-100000}" + rtt_delta_ewmas_us[${reflector}]="${rtt_delta_ewmas_us[${reflector}]:-0}" + continue + fi + ;; + + SET_VAR) + + if [[ "${command[1]:-}" && "${command[2]:-}" ]] + then + export -n "${command[1]}=${command[2]}" + fi + continue + ;; + + SET_ARRAY_ELEMENT) + + if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + then + declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + fi + ;; + + TERMINATE) + + log_msg "DEBUG" "Terminating parse_ping." + exit + ;; + + *) + + : + ;; + + esac + fi + + if [[ "${timestamp:-}" && "${reflector:-}" && "${seq_rtt:-}" && "${checksum:-}" ]] + then + [[ "${checksum}" == "${timestamp}" ]] + # If no match then skip onto the next one + [[ "${seq_rtt}" =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + + seq=${BASH_REMATCH[1]} + + rtt_us=${BASH_REMATCH[3]}000 + rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + + reflector=${reflector//:/} + + alpha=$(( rtt_us >= rtt_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${rtt_us}" "${alpha}" "rtt_baselines_us[${reflector}]" + + rtt_delta_us=$(( rtt_us-rtt_baselines_us[${reflector}] )) + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent )); then + ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" "rtt_delta_ewmas_us[${reflector}]" + fi + + dl_owd_baseline_us=$((rtt_baselines_us[${reflector}]/2)) + ul_owd_baseline_us=${dl_owd_baseline_us} + + dl_owd_delta_ewma_us=$((rtt_delta_ewmas_us[${reflector}]/2)) + ul_owd_delta_ewma_us=${dl_owd_delta_ewma_us} + + dl_owd_us=$((rtt_us/2)) + ul_owd_us="${dl_owd_us}" + + dl_owd_delta_us=$((rtt_delta_us/2)) + ul_owd_delta_us="${dl_owd_delta_us}" + + timestamp="${timestamp//[\[\]]}" + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baseline_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baseline_us}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT reflector_last_timestamps_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi - - dl_owd_baseline_us=$((rtt_baseline_us/2)) - ul_owd_baseline_us=${dl_owd_baseline_us} - - dl_owd_delta_ewma_us=$((rtt_delta_ewma_us/2)) - ul_owd_delta_ewma_us=${dl_owd_delta_ewma_us} - - dl_owd_us=$((rtt_us/2)) - ul_owd_us=${dl_owd_us} - - dl_owd_delta_us=$((rtt_delta_us/2)) - ul_owd_delta_us=${dl_owd_delta_us} - - timestamp=${timestamp//[\[\]]} - - printf '%s %s %s %s %s %s %s %s %s %s %s\n' "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${ping_fd}" - - timestamp_us=${timestamp//[.]} - - printf '%s' "${timestamp_us}" > "${run_path}/reflector_${reflector//./-}_last_timestamp_us" - - printf '%s' "${dl_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_baseline_us" - printf '%s' "${ul_owd_baseline_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_baseline_us" - - printf '%s' "${dl_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_dl_owd_delta_ewma_us" - printf '%s' "${ul_owd_delta_ewma_us}" > "${run_path}/reflector_${reflector//./-}_ul_owd_delta_ewma_us" - - printf '%s' "${timestamp_us}" > "${run_path}/reflectors_last_timestamp_us" - - done 2>/dev/null + done } # END OF IPUTILS-PING FUNCTIONS @@ -749,35 +1000,25 @@ monitor_reflector_responses_ping() start_pinger() { - local pinger=${1} + local pinger="${1}" log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - # shellcheck disable=SC1083,SC2086,SC2261 case ${pinger_binary} in - tsping) + tsping|fping) pinger=0 - exec {pinger_fds[pinger]}<> <(:) || true - proc_man_start "pinger_${pinger}" ${ping_prefix_string} tsping ${ping_extra_args} --print-timestamps --machine-readable=' ' --sleep-time "0" --target-spacing "${ping_response_interval_ms}" "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${pinger_fds[pinger]}" + printf "START_PINGER\n" >&"${pinger_fds[pinger]}" ;; - fping) - pinger=0 - exec {pinger_fds[pinger]}<> <(:) || true - proc_man_start "pinger_${pinger}" ${ping_prefix_string} fping ${ping_extra_args} --timestamp --loop --period "${reflector_ping_interval_ms}" --interval "${ping_response_interval_ms}" --timeout 10000 "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${pinger_fds[pinger]}" - ;; ping) - exec {pinger_fds[pinger]}<> <(:) || true sleep_until_next_pinger_time_slot "${pinger}" - proc_man_start "pinger_${pinger}" ${ping_prefix_string} ping ${ping_extra_args} -D -i "${reflector_ping_interval_s}" "${reflectors[pinger]}" 2> /dev/null >&"${pinger_fds[pinger]}" + printf "START_PINGER\n" >&"${pinger_fds[pinger]}" ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" exit 1 ;; esac - - proc_man_start "monitor_${pinger}" "monitor_reflector_responses_${pinger_binary}" "${pinger}" } start_pingers() @@ -808,7 +1049,7 @@ sleep_until_next_pinger_time_slot() # this allows pingers to be stopped and started (e.g. during sleep or reflector rotation) # whilst ensuring pings will remain spaced out appropriately to maintain granularity - local pinger=${1} + local pinger="${1}" t_start_us=${EPOCHREALTIME/./} time_to_next_time_slot_us=$(( (reflector_ping_interval_us-(t_start_us-pingers_t_start_us)%reflector_ping_interval_us) + pinger*ping_response_interval_us )) @@ -817,11 +1058,11 @@ sleep_until_next_pinger_time_slot() kill_pinger() { - local pinger=${1} + local pinger="${1}" log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - case ${pinger_binary} in + case "${pinger_binary}" in tsping|fping) pinger=0 ;; @@ -831,16 +1072,12 @@ kill_pinger() ;; esac - proc_man_stop "pinger_${pinger}" - proc_man_stop "monitor_${pinger}" - - # shellcheck disable=SC1083 - exec {pinger_fds[pinger]}<&- + printf "KILL_PINGER\n" >&"${pinger_fds[pinger]}" } kill_pingers() { - case ${pinger_binary} in + case "${pinger_binary}" in tsping|fping) log_msg "DEBUG" "Killing ${pinger_binary} instance." @@ -869,12 +1106,10 @@ replace_pinger_reflector() # and the the bad reflector moved to the back of the queue (last element in ${reflectors[]}) # and finally the indices for ${reflectors} are updated to reflect the new order - local pinger=${1} + local pinger="${1}" log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - lock "${run_path}/replace_pinger_reflector_lock" - if ((no_reflectors > no_pingers)); then log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}." kill_pinger "${pinger}" @@ -888,13 +1123,20 @@ replace_pinger_reflector() # reset array indices mapfile -t reflectors < <(for i in "${reflectors[@]}"; do printf '%s\n' "${i}"; done) # set up the new pinger with the new reflector and retain pid + case ${pinger_binary} in + + tsping|fping) + printf "SET_REFLECTORS %s\n" "${reflectors[*]:0:${no_pingers}}" >&"${pinger_fds[0]}" + ;; + ping) + printf "SET_REFLECTOR %s\n" "${reflectors[pinger]}" >&"${pinger_fds[pinger]}" + ;; + esac start_pinger "${pinger}" else log_msg "DEBUG" "No additional reflectors specified so just retaining: ${reflectors[pinger]}." reflector_offences[pinger]=0 fi - - unlock "${run_path}/replace_pinger_reflector_lock" } # END OF GENERIC PINGER START AND STOP FUNCTIONS @@ -905,38 +1147,31 @@ kill_maintain_pingers() log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - lock "${run_path}/replace_pinger_reflector_lock" - log_msg "DEBUG" "Terminating maintain_pingers." - kill_pingers + case "${pinger_binary}" in - unlock "${run_path}/replace_pinger_reflector_lock" + tsping|fping) + printf "TERMINATE\n" >&"${pinger_fds[0]}" + ;; + ping) + for((pinger=0; pinger < no_pingers; pinger++)) + do + printf "TERMINATE\n" >&"${pinger_fds[pinger]}" + done + ;; + esac exit } change_state_maintain_pingers() { - local maintain_pingers_next_state=${1:-unset} + local maintain_pingers_next_state="${1:-unset}" log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - if [[ "${maintain_pingers_next_state}" == "unset" ]]; then - if [[ -f "${run_path}/maintain_pingers_next_state" ]]; then - for ((read_try=1; read_try<11; read_try++)) - do - read -r maintain_pingers_next_state < "${run_path}/maintain_pingers_next_state" - maintain_pingers_next_state=${maintain_pingers_next_state:-unset} - [[ "${maintain_pingers_next_state}" != "unset" ]] && break - done - else - log_msg "ERROR" "Received change signal but ${run_path}/maintain_pingers_next_state does not exist. Exiting now." - kill -INT $$ - fi - fi - - case ${maintain_pingers_next_state} in + case "${maintain_pingers_next_state}" in START|STOP|PAUSED|RUNNING) @@ -944,7 +1179,6 @@ change_state_maintain_pingers() then log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" maintain_pingers_state=${maintain_pingers_next_state} - printf "%s" ${maintain_pingers_state} > ${run_path}/maintain_pingers_state else log_msg "ERROR" "Received request to change maintain_pingers state to existing state." fi @@ -953,7 +1187,7 @@ change_state_maintain_pingers() *) log_msg "ERROR" "Received unrecognized state change request: ${maintain_pingers_next_state}. Exiting now." - kill -INT $$ + kill $$ 2>/dev/null ;; esac } @@ -965,30 +1199,27 @@ maintain_pingers() trap '' INT trap 'kill_maintain_pingers' TERM EXIT - trap 'change_state_maintain_pingers' USR1 - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" declare -A dl_owd_baselines_us declare -A ul_owd_baselines_us declare -A dl_owd_delta_ewmas_us declare -A ul_owd_delta_ewmas_us + declare -A reflector_last_timestamps_us err_silence=0 reflector_offences_idx=0 pingers_active=0 - pingers_t_start_us=${EPOCHREALTIME/./} - t_last_reflector_replacement_us=${EPOCHREALTIME/./} - t_last_reflector_comparison_us=${EPOCHREALTIME/./} + pingers_t_start_us="${EPOCHREALTIME/./}" + t_last_reflector_replacement_us="${EPOCHREALTIME/./}" + t_last_reflector_comparison_us="${EPOCHREALTIME/./}" for ((reflector=0; reflector < no_reflectors; reflector++)) do - printf '%s' "${pingers_t_start_us}" > "${run_path}/reflector_${reflectors[reflector]//./-}_last_timestamp_us" + reflector_last_timestamps_us["${reflectors[reflector]}"]="${pingers_t_start_us}" done - printf '%s' "${pingers_t_start_us}" > "${run_path}/reflectors_last_timestamp_us" - # For each pinger initialize record of offences for ((pinger=0; pinger < no_pingers; pinger++)) do @@ -999,11 +1230,72 @@ maintain_pingers() done maintain_pingers_state="START" + sleep_duration_s=0 + pinger=0 + + case "${pinger_binary}" in + + tsping) + parse_tsping "parse_tsping" "${reflectors[@]:0:${no_pingers}}" & + printf "SET_PROC_PID proc_pids parse_tsping %s\n" "${!}" >&"${main_fd}" + ;; + fping) + parse_fping "parse_fping" "${reflectors[@]:0:${no_pingers}}" & + printf "SET_PROC_PID proc_pids parse_fping %s\n" "${!}" >&"${main_fd}" + ;; + ping) + for((pinger=0; pinger < no_pingers; pinger++)) + do + parse_ping "parse_ping_${pinger}" "${reflectors[pinger]}" & + printf "SET_PROC_PID proc_pids %s %s\n" "parse_ping_${pinger}" "${!}" >&"${main_fd}" + done + ;; + esac + # Reflector maintenance loop - verifies reflectors have not gone stale and rotates reflectors as necessary while true do - case ${maintain_pingers_state} in + t_start_us="${EPOCHREALTIME/./}" + + while read -r -t 0 -u "${maintain_pingers_fd}" + do + unset command + read -r -u "${maintain_pingers_fd}" -a command + case "${command[0]:-}" in + + CHANGE_STATE) + if [[ "${command[1]:-}" ]] + then + change_state_maintain_pingers "${command[1]}" + # break out of reading any new IPC commands to handle next state + # since next state might be to start or stop pingers + break + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + then + declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + fi + ;; + SET_VAR) + if [[ "${command[1]:-}" && "${command[2]:-}" ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + TERMINATE) + log_msg "DEBUG" "Terminating monitor_achieved_rates." + exit + ;; + *) + : + ;; + esac + done + + case "${maintain_pingers_state}" in START) if ((pingers_active==0)) @@ -1027,71 +1319,65 @@ maintain_pingers() ;; RUNNING) - if (( ${EPOCHREALTIME/./}>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000))); then - + + if (( ${t_start_us}>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) + then + pinger=$((RANDOM%no_pingers)) log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." - replace_pinger_reflector $((RANDOM%no_pingers)) + replace_pinger_reflector "${pinger}" t_last_reflector_replacement_us=${EPOCHREALTIME/./} continue fi - if (( ${EPOCHREALTIME/./}>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then + if (( ${t_start_us}>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then t_last_reflector_comparison_us=${EPOCHREALTIME/./} - concurrent_read_integer dl_min_owd_baseline_us "${run_path}/reflector_${reflectors[0]//./-}_dl_owd_baseline_us" 0 || continue - concurrent_read_integer dl_min_owd_delta_ewma_us "${run_path}/reflector_${reflectors[0]//./-}_dl_owd_delta_ewma_us" 0 || continue - concurrent_read_integer ul_min_owd_baseline_us "${run_path}/reflector_${reflectors[0]//./-}_ul_owd_baseline_us" 0 || continue - concurrent_read_integer ul_min_owd_delta_ewma_us "${run_path}/reflector_${reflectors[0]//./-}_ul_owd_delta_ewma_us" 0 || continue - - concurrent_read_integer compensated_dl_delay_thr_us "${run_path}/compensated_dl_delay_thr_us" - concurrent_read_integer compensated_ul_delay_thr_us "${run_path}/compensated_ul_delay_thr_us" + [[ "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" ]] || continue + + min_sum_owd_baselines_us=$(( dl_owd_baselines_us[${reflectors[0]}] + ul_owd_baselines_us[${reflectors[0]}] )) + min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[0]}]}" + min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[0]}]}" for ((pinger=0; pinger < no_pingers; pinger++)) do - concurrent_read_integer "dl_owd_baselines_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_dl_owd_baseline_us" 0 || continue 2 - concurrent_read_integer "dl_owd_delta_ewmas_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_dl_owd_delta_ewma_us" 0 || continue 2 - concurrent_read_integer "ul_owd_baselines_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_ul_owd_baseline_us" 0 || continue 2 - concurrent_read_integer "ul_owd_delta_ewmas_us[${reflectors[pinger]}]" "${run_path}/reflector_${reflectors[pinger]//./-}_ul_owd_delta_ewma_us" 0 || continue 2 - - (( dl_owd_baselines_us[${reflectors[pinger]}] < dl_min_owd_baseline_us )) && dl_min_owd_baseline_us="${dl_owd_baselines_us[${reflectors[pinger]}]}" - (( dl_owd_delta_ewmas_us[${reflectors[pinger]}] < dl_min_owd_delta_ewma_us )) && dl_min_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" - (( ul_owd_baselines_us[${reflectors[pinger]}] < ul_min_owd_baseline_us )) && ul_min_owd_baseline_us="${ul_owd_baselines_us[${reflectors[pinger]}]}" - (( ul_owd_delta_ewmas_us[${reflectors[pinger]}] < ul_min_owd_delta_ewma_us )) && ul_min_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" + [[ "${dl_owd_baselines_us[${reflectors[pinger]}]:-}" && "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" && "${ul_owd_baselines_us[${reflectors[pinger]}]:-}" && "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" ]] || continue 2 + + sum_owd_baselines_us[pinger]=$(( dl_owd_baselines_us[${reflectors[pinger]}] + ul_owd_baselines_us[${reflectors[pinger]}] )) + (( sum_owd_baselines_us[pinger] < min_sum_owd_baselines_us )) && min_sum_owd_baselines_us="${sum_owd_baselines_us[pinger]}" + (( dl_owd_delta_ewmas_us[${reflectors[pinger]}] < min_dl_owd_delta_ewma_us )) && min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" + (( ul_owd_delta_ewmas_us[${reflectors[pinger]}] < min_ul_owd_delta_ewma_us )) && min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" done for ((pinger=0; pinger < no_pingers; pinger++)) do - dl_owd_baseline_delta_us=$(( dl_owd_baselines_us[${reflectors[pinger]}] - dl_min_owd_baseline_us )) - dl_owd_delta_ewma_delta_us=$(( dl_owd_delta_ewmas_us[${reflectors[pinger]}] - dl_min_owd_delta_ewma_us )) - ul_owd_baseline_delta_us=$(( ul_owd_baselines_us[${reflectors[pinger]}] - ul_min_owd_baseline_us )) - ul_owd_delta_ewma_delta_us=$(( ul_owd_delta_ewmas_us[${reflectors[pinger]}] - ul_min_owd_delta_ewma_us )) + sum_owd_baselines_delta_us=$(( sum_owd_baselines_us[pinger] - min_sum_owd_baselines_us )) + dl_owd_delta_ewma_delta_us=$(( dl_owd_delta_ewmas_us[${reflectors[pinger]}] - min_dl_owd_delta_ewma_us )) + ul_owd_delta_ewma_delta_us=$(( ul_owd_delta_ewmas_us[${reflectors[pinger]}] - min_ul_owd_delta_ewma_us )) - if ((output_reflector_stats)); then - printf -v reflector_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${reflectors[pinger]}" "${dl_min_owd_baseline_us}" "${dl_owd_baselines_us[${reflectors[pinger]}]}" "${dl_owd_baseline_delta_us}" "${reflector_owd_baseline_delta_thr_us}" "${dl_min_owd_delta_ewma_us}" "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${dl_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" "${ul_min_owd_baseline_us}" "${ul_owd_baselines_us[${reflectors[pinger]}]}" "${ul_owd_baseline_delta_us}" "${reflector_owd_baseline_delta_thr_us}" "${ul_min_owd_delta_ewma_us}" "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${ul_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" + if ((output_reflector_stats)) + then + printf -v reflector_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${reflectors[pinger]}" "${min_sum_owd_baselines_us}" "${sum_owd_baselines_us[pinger]}" "${sum_owd_baselines_delta_us}" "${reflector_sum_owd_baselines_delta_thr_us}" "${min_dl_owd_delta_ewma_us}" "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${dl_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" "${min_ul_owd_delta_ewma_us}" "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${ul_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" log_msg "REFLECTOR" "${reflector_stats}" fi - if (( dl_owd_baseline_delta_us > reflector_owd_baseline_delta_thr_us )); then - log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} dl_owd_baseline_us exceeds the minimum by set threshold." + if (( sum_owd_baselines_delta_us > reflector_sum_owd_baselines_delta_thr_us )) + then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} sum_owd_baselines_us exceeds the minimum by set threshold." replace_pinger_reflector "${pinger}" continue 2 fi - if (( dl_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )); then + if (( dl_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) + then log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} dl_owd_delta_ewma_us exceeds the minimum by set threshold." replace_pinger_reflector "${pinger}" continue 2 fi - if (( ul_owd_baseline_delta_us > reflector_owd_baseline_delta_thr_us )); then - log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} ul_owd_baseline_us exceeds the minimum by set threshold." - replace_pinger_reflector "${pinger}" - continue 2 - fi - - if (( ul_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )); then + if (( ul_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) + then log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} ul_owd_delta_ewma_us exceeds the minimum by set threshold." replace_pinger_reflector "${pinger}" continue 2 @@ -1104,8 +1390,8 @@ maintain_pingers() for ((pinger=0; pinger < no_pingers; pinger++)) do - reflector_check_time_us=${EPOCHREALTIME/./} - concurrent_read_integer reflector_last_timestamp_us "${run_path}/reflector_${reflectors[pinger]//./-}_last_timestamp_us" + reflector_check_time_us="${EPOCHREALTIME/./}" + reflector_last_timestamp_us="${reflector_last_timestamps_us["${reflectors[pinger]}"]}" # shellcheck disable=SC2178 declare -n reflector_offences="reflector_${pinger}_offences" @@ -1141,26 +1427,22 @@ maintain_pingers() change_maintain_pingers_state ;; esac - - sleep_s "${reflector_health_check_interval_s}" + + sleep_remaining_tick_time "${t_start_us}" "${reflector_health_check_interval_us}" done } set_cake_rate() { - local interface=${1} - local shaper_rate_kbps=${2} - local adjust_shaper_rate=${3} + local interface="${1}" + local shaper_rate_kbps="${2}" + local adjust_shaper_rate="${3}" ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface} cake bandwidth ${shaper_rate_kbps}Kbit" if ((adjust_shaper_rate)); then - if ((debug)); then - tc qdisc change root dev "${interface}" cake bandwidth "${shaper_rate_kbps}Kbit" - else - tc qdisc change root dev "${interface}" cake bandwidth "${shaper_rate_kbps}Kbit" 2> /dev/null - fi + tc qdisc change root dev "${interface}" cake bandwidth "${shaper_rate_kbps}Kbit" 2> /dev/null else ((output_cake_changes)) && log_msg "DEBUG" "adjust_shaper_rate set to 0 in config, so skipping the tc qdisc change call" @@ -1169,18 +1451,18 @@ set_cake_rate() set_shaper_rates() { - if (( dl_shaper_rate_kbps != last_dl_shaper_rate_kbps || ul_shaper_rate_kbps != last_ul_shaper_rate_kbps )); then + if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] || shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then # fire up tc in each direction if there are rates to change, and if rates change in either direction then update max wire calcs - if (( dl_shaper_rate_kbps != last_dl_shaper_rate_kbps )); then - set_cake_rate "${dl_if}" "${dl_shaper_rate_kbps}" adjust_dl_shaper_rate - printf '%s' "${dl_shaper_rate_kbps}" > "${run_path}/dl_shaper_rate_kbps" - last_dl_shaper_rate_kbps=${dl_shaper_rate_kbps} + if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] )); then + set_cake_rate "${dl_if}" "${shaper_rate_kbps[dl]}" adjust_dl_shaper_rate + printf "SET_ARRAY_ELEMENT shaper_rate_kbps dl %s\n" "${shaper_rate_kbps[dl]}" >&${monitor_achieved_rates_fd} + last_shaper_rate_kbps[dl]="${shaper_rate_kbps[dl]}" fi - if (( ul_shaper_rate_kbps != last_ul_shaper_rate_kbps )); then - set_cake_rate "${ul_if}" "${ul_shaper_rate_kbps}" adjust_ul_shaper_rate - printf '%s' "${ul_shaper_rate_kbps}" > "${run_path}/ul_shaper_rate_kbps" - last_ul_shaper_rate_kbps=${ul_shaper_rate_kbps} + if (( shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then + set_cake_rate "${ul_if}" "${shaper_rate_kbps[ul]}" adjust_ul_shaper_rate + printf "SET_ARRAY_ELEMENT shaper_rate_kbps ul %s\n" "${shaper_rate_kbps[ul]}" >&${monitor_achieved_rates_fd} + last_shaper_rate_kbps[ul]="${shaper_rate_kbps[ul]}" fi update_max_wire_packet_compensation @@ -1190,15 +1472,15 @@ set_shaper_rates() set_min_shaper_rates() { log_msg "DEBUG" "Enforcing minimum shaper rates." - dl_shaper_rate_kbps=${min_dl_shaper_rate_kbps} - ul_shaper_rate_kbps=${min_ul_shaper_rate_kbps} + shaper_rate_kbps[dl]=${min_dl_shaper_rate_kbps} + shaper_rate_kbps[ul]=${min_ul_shaper_rate_kbps} set_shaper_rates } get_max_wire_packet_size_bits() { - local interface=${1} - local -n max_wire_packet_size_bits=${2} + local interface="${1}" + local -n max_wire_packet_size_bits="${2}" read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" [[ $(tc qdisc show dev "${interface}" || true) =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] @@ -1213,75 +1495,15 @@ update_max_wire_packet_compensation() # This will serve to increase the delay thr at rates below around 12Mbit/s # compensated OWD delay thresholds in microseconds - compensated_dl_delay_thr_us=$(( dl_delay_thr_us + (1000*dl_max_wire_packet_size_bits)/dl_shaper_rate_kbps )) - compensated_ul_delay_thr_us=$(( ul_delay_thr_us + (1000*ul_max_wire_packet_size_bits)/ul_shaper_rate_kbps )) + compensated_dl_delay_thr_us=$(( dl_delay_thr_us + (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] )) + compensated_ul_delay_thr_us=$(( ul_delay_thr_us + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) + + printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" + printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" + + max_wire_packet_rtt_us=$(( (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) - printf '%s' "${compensated_dl_delay_thr_us}" > "${run_path}/compensated_dl_delay_thr_us" - printf '%s' "${compensated_ul_delay_thr_us}" > "${run_path}/compensated_ul_delay_thr_us" - - # determine and write out ${max_wire_packet_rtt_us} - max_wire_packet_rtt_us=$(( (1000*dl_max_wire_packet_size_bits)/dl_shaper_rate_kbps + (1000*ul_max_wire_packet_size_bits)/ul_shaper_rate_kbps )) - printf '%s' "${max_wire_packet_rtt_us}" > "${run_path}/max_wire_packet_rtt_us" -} - -concurrent_read_integer() -{ - # in the context of a single process that writes to a file and - # a separate process that reads from the file, costly calls to - # the external flock binary can be avoided for the reason that - # the read either reads in a blank value or the last true value - # and so it is possible to just read, test and reread if necessary - - local -n value=${1} - local path=${2} - local exit_on_no_file=${3:-1} - - if ! [[ -f ${path} ]] - then - if ((exit_on_no_file)) - then - log_msg "ERROR" "Non-existent file at: ${path} and exit_on_no_file enabled. Exiting now." - kill -$$ INT - else - log_msg "DEBUG" "Non-existent file at: ${path} but exit_on_no_file disabled. Returning 1." - value=0 - return 1 - fi - fi - - for ((read_try=1; read_try<11; read_try++)) - do - read -r value < "${path}" - value="${value:-unset}" - - # printf '%.0f' is used here to sanitize unsigned integers: - # - it removes any leading zeros whilst preserving the sign; and - # - it returns false if ${value} is not a number - if printf -v sanitized_value '%.0f' "${value}" 2>/dev/null; then - - value=${sanitized_value} - return 0 - - else - if ((debug)); then - read -r caller_output< <(caller) || true - log_msg "DEBUG" "concurrent_read_integer() misfire: ${read_try} of 10, with the following particulars:" - log_msg "DEBUG" "caller=${caller_output}, value=${value} and path=${path}" - fi - sleep_us "${concurrent_read_integer_interval_us}" - continue - fi - done - - if ((debug)); then - read -r caller_output< <(caller) || true - log_msg "ERROR" "If you see this, then please report these messages (ideally with log file)" - log_msg "ERROR" "at the cake-autorate forum of OpenWrt and/or at github.com/lynxthecat/cake-autorate" - log_msg "ERROR" "concurrent_read_integer() 10x misfires, with the following particulars:" - log_msg "ERROR" "caller=${caller_output}, value=${value} and path=${path}" - fi - value=0 - return 1 + printf "SET_VAR max_wire_packet_rtt_us %s\n" "${max_wire_packet_rtt_us}" >&"${maintain_pingers_fd}" } verify_ifs_up() @@ -1300,24 +1522,49 @@ verify_ifs_up() ewma_iteration() { - local value=${1} - local alpha=${2} # alpha must be scaled by factor of 1000000 - local -n ewma=${3} + local value="${1}" + local alpha="${2}" # alpha must be scaled by factor of 1000000 + local -n ewma="${3}" prev_ewma=${ewma} ewma=$(( (alpha*value+(1000000-alpha)*prev_ewma)/1000000 )) } -# redirect stderr to log_msg and exit cake-autorate +change_state_main() +{ + local main_next_state="${1}" + + case ${main_next_state} in + + RUNNING|IDLE|STALL) + + if [[ "${main_state}" != "${main_next_state}" ]] + then + log_msg "DEBUG" "Changing main state from: ${main_state} to: ${main_next_state}" + main_state=${main_next_state} + else + log_msg "ERROR" "Received request to change main state to existing state." + fi + ;; + + *) + + log_msg "ERROR" "Received unrecognized main state change request: ${main_next_state}. Exiting now." + kill $$ 2>/dev/null + ;; + esac +} + intercept_stderr() { - exec 2> >( - while read -r error - do - log_msg "ERROR" "${error}" - kill -INT $$ - done - ) + # send stderr to log_msg and exit cake-autorate + # use with redirection: exec 2> >(intercept_stderr) + + while read -r error + do + log_msg "ERROR" "${error}" + kill $$ 2>/dev/null + done } # Debug command wrapper @@ -1329,9 +1576,9 @@ debug_cmd() # Error messages are output as log_msg ERROR messages # Or set error_silence=1 to output errors as log_msg DEBUG messages - local debug_msg=${1} - local err_silence=${2} - local cmd=${3} + local debug_msg="${1}" + local err_silence="${2}" + local cmd="${3}" log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" @@ -1386,8 +1633,8 @@ log_file_path=/var/log/cake-autorate.log run_path=/var/run/cake-autorate/ # cake-autorate first argument is config file path -if [[ -n ${1:-} ]]; then - config_path=${1} +if [[ -n ${1-} ]]; then + config_path="${1}" else config_path="$PREFIX/cake-autorate_config.primary.sh" fi @@ -1413,10 +1660,7 @@ else exit fi -PROC_STATE_FILE="${run_path}/proc_state" -PROC_STATE_FILE_LOCK="${run_path}/proc_state.lock" - -if [[ -n "${log_file_path_override:-}" ]]; then +if [[ -n "${log_file_path_override-}" ]]; then if [[ ! -d ${log_file_path_override} ]]; then broken_log_file_path_override=${log_file_path_override} log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log @@ -1430,16 +1674,20 @@ fi rotate_log_file # rotate here to force header prints at top of log file -# Intercept stderr, redirect it to log_msg and exit cake-autorate -intercept_stderr +# save stderr fd, redirect stderr to intercept_stderr +# intercept_stderr sends stderr to log_msg and exits cake-autorate +exec {original_stderr_fd}>&2 2> >(intercept_stderr) + +proc_pids['intercept_stderr']=${!} log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${config_path}" # ${run_path}/ is used to store temporary files # it should not exist on startup so if it does exit, else create the directory if [[ -d "${run_path}" ]]; then - if [[ -f "${run_path}/pid" ]] && [[ -d "/proc/$(<"${run_path}/pid")" ]]; then - log_msg "ERROR" "${run_path} already exists and an instance may be running. Exiting script." + if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' ${run_path}/proc_pids) && [[ -d "/proc/${running_main_pid}" ]] + then + log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script." trap - INT TERM EXIT exit else @@ -1451,10 +1699,7 @@ else mkdir -p "${run_path}" fi -# Initialize proc_man -proc_man_initialize - -printf "%s" "${BASHPID}" > "${run_path}/pid" +proc_pids['main']="${BASHPID}" no_reflectors=${#reflectors[@]} @@ -1476,7 +1721,8 @@ if ((log_to_file)); then log_file_max_time_us=$((log_file_max_time_mins*60000000)) log_file_max_size_bytes=$((log_file_max_size_KB*1024)) exec {log_fd}<> <(:) || true - proc_man_start "maintain_log_file" maintain_log_file + maintain_log_file & + proc_pids['maintain_log_file']=${!} fi # test if stdout is a tty (terminal) @@ -1486,7 +1732,7 @@ if ! ((terminal)); then fi # Initialize rx_bytes_path and tx_bytes_path if not set -if [[ -z "${rx_bytes_path:-}" ]]; then +if [[ -z "${rx_bytes_path-}" ]]; then case "${dl_if}" in veth*) rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" @@ -1499,7 +1745,7 @@ if [[ -z "${rx_bytes_path:-}" ]]; then ;; esac fi -if [[ -z "${tx_bytes_path:-}" ]]; then +if [[ -z "${tx_bytes_path-}" ]]; then case "${ul_if}" in veth*) tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" @@ -1545,10 +1791,11 @@ printf -v shaper_rate_adjust_up_load_low %.0f "${shaper_rate_adjust_up_load_low} printf -v high_load_thr_percent %.0f "${high_load_thr}e2" printf -v reflector_ping_interval_ms %.0f "${reflector_ping_interval_s}e3" printf -v reflector_ping_interval_us %.0f "${reflector_ping_interval_s}e6" +printf -v reflector_health_check_interval_us %.0f "${reflector_health_check_interval_s}e6" printf -v monitor_achieved_rates_interval_us %.0f "${monitor_achieved_rates_interval_ms}e3" printf -v sustained_idle_sleep_thr_us %.0f "${sustained_idle_sleep_thr_s}e6" printf -v reflector_response_deadline_us %.0f "${reflector_response_deadline_s}e6" -printf -v reflector_owd_baseline_delta_thr_us %.0f "${reflector_owd_baseline_delta_thr_ms}e3" +printf -v reflector_sum_owd_baselines_delta_thr_us %.0f "${reflector_sum_owd_baselines_delta_thr_ms}e3" printf -v reflector_owd_delta_ewma_delta_thr_us %.0f "${reflector_owd_delta_ewma_delta_thr_ms}e3" printf -v startup_wait_us %.0f "${startup_wait_s}e6" printf -v global_ping_response_timeout_us %.0f "${global_ping_response_timeout_s}e6" @@ -1571,11 +1818,31 @@ stall_detection_timeout_s=$(( 10#${stall_detection_timeout_s::-6})).${stall_dete concurrent_read_integer_interval_us=$((ping_response_interval_us/4)) -dl_shaper_rate_kbps=${base_dl_shaper_rate_kbps} -ul_shaper_rate_kbps=${base_ul_shaper_rate_kbps} +declare -A bufferbloat_detected +declare -A load_percent +declare -A load_condition +declare -A t_last_bufferbloat_us +declare -A t_last_decay_us +declare -A shaper_rate_kbps +declare -A last_shaper_rate_kbps +declare -A base_shaper_rate_kbps +declare -A min_shaper_rate_kbps +declare -A max_shaper_rate_kbps -last_dl_shaper_rate_kbps=0 -last_ul_shaper_rate_kbps=0 +base_shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" +base_shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" + +min_shaper_rate_kbps[dl]="${min_dl_shaper_rate_kbps}" +min_shaper_rate_kbps[ul]="${min_ul_shaper_rate_kbps}" + +max_shaper_rate_kbps[dl]="${max_dl_shaper_rate_kbps}" +max_shaper_rate_kbps[ul]="${max_ul_shaper_rate_kbps}" + +shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" +shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" + +last_shaper_rate_kbps[dl]=0 +last_shaper_rate_kbps[ul]=0 get_max_wire_packet_size_bits "${dl_if}" dl_max_wire_packet_size_bits get_max_wire_packet_size_bits "${ul_if}" ul_max_wire_packet_size_bits @@ -1584,17 +1851,20 @@ set_shaper_rates update_max_wire_packet_compensation -t_start_us=${EPOCHREALTIME/./} -t_end_us=${EPOCHREALTIME/./} +main_state="RUNNING" -t_prev_ul_rate_set_us=${t_start_us} -t_prev_dl_rate_set_us=${t_start_us} -t_ul_last_bufferbloat_us=${t_start_us} -t_ul_last_decay_us=${t_start_us} -t_dl_last_bufferbloat_us=${t_start_us} -t_dl_last_decay_us=${t_start_us} +t_start_us="${EPOCHREALTIME/./}" +t_end_us="${EPOCHREALTIME/./}" + +t_last_bufferbloat_us[dl]="${t_start_us}" +t_last_bufferbloat_us[ul]="${t_start_us}" +t_last_decay_us[dl]="${t_start_us}" +t_last_decay_us[ul]="${t_start_us}" t_sustained_connection_idle_us=0 +reflectors_last_timestamp_us="${EPOCHREALTIME/./}" +dl_achieved_rate_kbps=0 +ul_achieved_rate_kbps=0 mapfile -t dl_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) mapfile -t ul_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) @@ -1625,166 +1895,202 @@ if ((startup_wait_us>0)); then fi # Initiate achieved rate monitor -proc_man_start monitor_achieved_rates monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" +monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" & +proc_pids[monitor_achieved_rates]="${!}" -printf '%s' "0" > "${run_path}/dl_load_percent" -printf '%s' "0" > "${run_path}/ul_load_percent" +case "${pinger_binary}" in -proc_man_start maintain_pingers maintain_pingers + tsping|fping) + exec {pinger_fds[0]}<> <(:) || true + ;; + ping) + for ((pinger=0; pinger<=no_pingers; pinger++)) + do + exec {pinger_fds[pinger]}<> <(:) || true + done + ;; +esac -generate_log_file_exporter +maintain_pingers & +proc_pids['maintain_pingers']="${!}" + +generate_log_file_scripts log_msg "INFO" "Started cake-autorate with PID: ${BASHPID} and config: ${config_path}" while true do - while read -r -t "${stall_detection_timeout_s}" -u "${ping_fd}" timestamp reflector seq dl_owd_baseline_us dl_owd_us dl_owd_delta_ewma_us dl_owd_delta_us ul_owd_baseline_us ul_owd_us ul_owd_delta_ewma_us ul_owd_delta_us - do - t_start_us=${EPOCHREALTIME/./} - if (( (t_start_us - 10#"${timestamp//[.]}")>500000 )); then - log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." - continue - fi + unset command + read -r -u "${main_fd}" -a command - # Keep track of number of dl delays across detection window - # .. for download: - (( dl_delays[delays_idx] )) && ((sum_dl_delays--)) - dl_delays[delays_idx]=$(( dl_owd_delta_us > compensated_dl_delay_thr_us ? 1 : 0 )) - ((dl_delays[delays_idx])) && ((sum_dl_delays++)) - # .. for upload - (( ul_delays[delays_idx] )) && ((sum_ul_delays--)) - ul_delays[delays_idx]=$(( ul_owd_delta_us > compensated_ul_delay_thr_us ? 1 : 0 )) - ((ul_delays[delays_idx])) && ((sum_ul_delays++)) - # .. and move index on - (( delays_idx=(delays_idx+1)%bufferbloat_detection_window )) + if [[ "${command-}" ]] + then - dl_bufferbloat_detected=$(( ((sum_dl_delays >= bufferbloat_detection_thr)) ? 1 : 0 )) - ul_bufferbloat_detected=$(( ((sum_ul_delays >= bufferbloat_detection_thr)) ? 1 : 0 )) + case "${command[0]}" in - get_loads + REFLECTOR_RESPONSE) - classify_load "${dl_load_percent}" "${dl_achieved_rate_kbps}" "${dl_bufferbloat_detected}" dl_load_condition - classify_load "${ul_load_percent}" "${ul_achieved_rate_kbps}" "${ul_bufferbloat_detected}" ul_load_condition + read -r timestamp reflector seq dl_owd_baseline_us dl_owd_us dl_owd_delta_ewma_us dl_owd_delta_us ul_owd_baseline_us ul_owd_us ul_owd_delta_ewma_us ul_owd_delta_us <<< "${command[@]:1}" + ;; - dl_load_condition="dl_"${dl_load_condition} - ul_load_condition="ul_"${ul_load_condition} + SET_VAR) + if [[ ${command[1]:-} && ${command[2]:-} ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + then + declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + fi + ;; + SET_PROC_PID) + if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + then + declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + fi + > "${run_path}/proc_pids" + for proc_pid in "${!proc_pids[@]}" + do + printf "%s=%s\n" "${proc_pid}" "${proc_pids[${proc_pid}]}" >> "${run_path}/proc_pids" + done + ;; + *) + ;; + esac - get_next_shaper_rate "${min_dl_shaper_rate_kbps}" "${base_dl_shaper_rate_kbps}" "${max_dl_shaper_rate_kbps}" "${dl_achieved_rate_kbps}" "${dl_load_condition}" "${t_start_us}" t_dl_last_bufferbloat_us t_dl_last_decay_us dl_shaper_rate_kbps - get_next_shaper_rate "${min_ul_shaper_rate_kbps}" "${base_ul_shaper_rate_kbps}" "${max_ul_shaper_rate_kbps}" "${ul_achieved_rate_kbps}" "${ul_load_condition}" "${t_start_us}" t_ul_last_bufferbloat_us t_ul_last_decay_us ul_shaper_rate_kbps + fi + case "${main_state}" in - set_shaper_rates + RUNNING) - if (( output_processing_stats )); then - printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${dl_achieved_rate_kbps}" "${ul_achieved_rate_kbps}" "${dl_load_percent}" "${ul_load_percent}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${dl_load_condition}" "${ul_load_condition}" "${dl_shaper_rate_kbps}" "${ul_shaper_rate_kbps}" - log_msg "DATA" "${processing_stats}" - fi + if [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" && "${reflector-}" && "${seq-}" && "${dl_owd_baseline_us-}" && "${dl_owd_us-}" && "${dl_owd_delta_ewma_us-}" && "${dl_owd_delta_us-}" && "${ul_owd_baseline_us-}" && "${ul_owd_us-}" && "${ul_owd_delta_ewma_us-}" && "${ul_owd_delta_us-}" ]] + then + + t_start_us=${EPOCHREALTIME/./} + + reflectors_last_timestamp_us="${timestamp//[.]}" + + if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )); then + log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." + continue + fi + + # Keep track of number of dl delays across detection window + # .. for download: + (( dl_delays[delays_idx] )) && ((sum_dl_delays--)) + dl_delays[delays_idx]=$(( dl_owd_delta_us > compensated_dl_delay_thr_us ? 1 : 0 )) + ((dl_delays[delays_idx])) && ((sum_dl_delays++)) + # .. for upload + (( ul_delays[delays_idx] )) && ((sum_ul_delays--)) + ul_delays[delays_idx]=$(( ul_owd_delta_us > compensated_ul_delay_thr_us ? 1 : 0 )) + ((ul_delays[delays_idx])) && ((sum_ul_delays++)) + # .. and move index on + (( delays_idx=(delays_idx+1)%bufferbloat_detection_window )) + + bufferbloat_detected[dl]=$(( sum_dl_delays >= bufferbloat_detection_thr ? 1 : 0 )) + bufferbloat_detected[ul]=$(( sum_ul_delays >= bufferbloat_detection_thr ? 1 : 0 )) + + load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) + load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) + + classify_load "dl" + classify_load "ul" + + get_next_shaper_rate "dl" + get_next_shaper_rate "ul" + + set_shaper_rates + + if (( output_processing_stats )); then + printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${load_percent[dl]}" "${load_percent[ul]}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${load_condition[dl]}" "${load_condition[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" + log_msg "DATA" "${processing_stats}" + fi + + # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) + if (( enable_sleep_function )); then + if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]]; then + ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) + if ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) + then + change_state_main "IDLE" + + log_msg "DEBUG" "Connection idle. Waiting for minimum load." + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + + # update maintain_pingers state + printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" + + # reset idle timer + t_sustained_connection_idle_us=0 + fi + else + # reset timer + t_sustained_connection_idle_us=0 + fi + fi + elif (( (${EPOCHREALTIME/./} - ${reflectors_last_timestamp_us}) > ${stall_detection_timeout_us} )) + then + + log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking loads." + + log_msg "DEBUG" "load check is: (( ${achieved_rate_kbps[dl]} kbps > ${connection_stall_thr_kbps} kbps for download && ${achieved_rate_kbps[ul]} kbps > ${connection_stall_thr_kbps} kbps for upload ))" + + # non-zero load so despite no reflector response within stall interval, the connection not considered to have stalled + # and therefore resume normal operation + if (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) + then + + log_msg "DEBUG" "load above connection stall threshold so resuming normal operation." + else + change_state_main "STALL" + + printf "CHANGE_STATE PAUSED\n" >&"${maintain_pingers_fd}" + + t_connection_stall_time_us="${EPOCHREALTIME//.}" + global_ping_response_timeout=0 + fi - # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) - if (( enable_sleep_function )); then - if [[ ${dl_load_condition} == *idle* && ${ul_load_condition} == *idle* ]]; then - ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) - ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) && break - else - # reset timer - t_sustained_connection_idle_us=0 fi - fi - - t_end_us=${EPOCHREALTIME/./} - - done - - # stall handling procedure - # PIPESTATUS[0] == 142 corresponds with while loop timeout - # i.e. no reflector responses within ${stall_detection_thr} * ${ping_response_interval_us} - if (( PIPESTATUS[0] == 142 )); then - - log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking for loads." - - get_loads - - log_msg "DEBUG" "load check is: ((${dl_achieved_rate_kbps} kbps > ${connection_stall_thr_kbps} kbps && ${ul_achieved_rate_kbps} kbps > ${connection_stall_thr_kbps} kbps))" - - # non-zero load so despite no reflector response within stall interval, the connection not considered to have stalled - # and therefore resume normal operation - if (( dl_achieved_rate_kbps > connection_stall_thr_kbps && ul_achieved_rate_kbps > connection_stall_thr_kbps )); then - - log_msg "DEBUG" "load above connection stall threshold so resuming normal operation." - continue - - fi - - log_msg "DEBUG" "Warning: connection stall detection. Waiting for new ping or increased load" - - # save intial global reflector timestamp to check against for any new reflector response - concurrent_read_integer initial_reflectors_last_timestamp_us "${run_path}/reflectors_last_timestamp_us" - - # update maintain_pingers state - printf "PAUSED" > ${run_path}/maintain_pingers_next_state - proc_man_signal maintain_pingers "USR1" - - t_connection_stall_time_us=${EPOCHREALTIME/./} - - global_ping_response_timeout=0 - - # wait until load resumes or ping response received (or global reflector response timeout) - while true - do - t_start_us=${EPOCHREALTIME/./} - concurrent_read_integer new_reflectors_last_timestamp_us "${run_path}/reflectors_last_timestamp_us" - get_loads + t_end_us="${EPOCHREALTIME/./}" - # shellcheck disable=SC2154 - if (( new_reflectors_last_timestamp_us != initial_reflectors_last_timestamp_us || ( dl_achieved_rate_kbps > connection_stall_thr_kbps && ul_achieved_rate_kbps > connection_stall_thr_kbps) )); then + ;; + IDLE) + if (( achieved_rate_kbps[dl] > connection_active_thr_kbps || achieved_rate_kbps[ul] > connection_active_thr_kbps )) + then + log_msg "DEBUG" "dl achieved rate: ${achieved_rate_kbps[dl]} kbps or ul achieved rate: ${achieved_rate_kbps[ul]} kbps exceeded connection active threshold: ${connection_active_thr_kbps} kbps. Resuming normal operation." + change_state_main "RUNNING" + printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" + t_sustained_connection_idle_us=0 + # Give some time to enable pingers to get set up + reflectors_last_timestamp_us=$(( "${EPOCHREALTIME/./}" + 2*reflector_ping_interval_us )) + fi + ;; + STALL) + + [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" ]] && reflectors_last_timestamp_us=${timestamp//[.]} + + if [[ "${command[0]}" == "REFLECTOR_RESPONSE" ]] || (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) + then log_msg "DEBUG" "Connection stall ended. Resuming normal operation." + printf "CHANGE_STATE RUNNING\n" >&"${maintain_pingers_fd}" + change_state_main "RUNNING" - # update maintain_pingers state - printf "RUNNING" > ${run_path}/maintain_pingers_next_state - proc_man_signal maintain_pingers "USR1" - - # continue main loop (i.e. skip idle/global timeout handling below) - continue 2 fi - sleep_remaining_tick_time "${t_start_us}" "${reflector_ping_interval_us}" - - if (( global_ping_response_timeout==0 && t_start_us > (t_connection_stall_time_us + global_ping_response_timeout_us - stall_detection_timeout_us) )); then - log_msg "SYSLOG" "Warning: Configured global ping response timeout: ${global_ping_response_timeout_s} seconds exceeded." - ((min_shaper_rates_enforcement)) && set_min_shaper_rates + if (( global_ping_response_timeout==0 && ${EPOCHREALTIME/./} > (t_connection_stall_time_us + global_ping_response_timeout_us - stall_detection_timeout_us) )) + then global_ping_response_timeout=1 + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + log_msg "SYSLOG" "Warning: Configured global ping response timeout: ${global_ping_response_timeout_s} seconds exceeded." + log_msg "DEBUG" "Restarting pingers." + printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" + printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" fi - done - - else - log_msg "DEBUG" "Connection idle. Waiting for minimum load." - ((min_shaper_rates_enforcement)) && set_min_shaper_rates - fi - - # update maintain_pingers state - printf "STOP" > ${run_path}/maintain_pingers_next_state - proc_man_signal maintain_pingers "USR1" - - # reset idle timer - t_sustained_connection_idle_us=0 - - # wait until load increases again - while true - do - t_start_us=${EPOCHREALTIME/./} - get_loads - - if (( dl_achieved_rate_kbps > connection_active_thr_kbps || ul_achieved_rate_kbps > connection_active_thr_kbps )); then - log_msg "DEBUG" "dl achieved rate: ${dl_achieved_rate_kbps} kbps or ul achieved rate: ${ul_achieved_rate_kbps} kbps exceeded connection active threshold: ${connection_active_thr_kbps} kbps. Resuming normal operation." - break - fi - sleep_remaining_tick_time "${t_start_us}" "${reflector_ping_interval_us}" - done - - # update maintain_pingers state - printf "START" > ${run_path}/maintain_pingers_next_state - proc_man_signal maintain_pingers "USR1" + ;; + esac - t_end_us=${EPOCHREALTIME/./} done diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh index e6f290d82..06dc9970b 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh @@ -7,8 +7,6 @@ # Author: @Lynx (OpenWrt forum) # Inspiration taken from: @moeller0 (OpenWrt forum) -cake_autorate_version="2.0.0" - # *** OUTPUT AND LOGGING OPTIONS *** output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats @@ -44,7 +42,7 @@ ul_if=wan # upload interface # fping - round robin pinging (rtts) # ping - (iputils-ping) individual pinging (rtts) # hping3 - individidual pinging (owds) -pinger_binary=ping +pinger_binary=fping # list of reflectors to use and number of pingers to initiate # pingers will be initiated with reflectors in the order specified in the list @@ -187,9 +185,9 @@ reflector_misbehaving_detection_thr=3 reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list -reflector_comparison_interval_mins=1 # how often to compare reflectors -reflector_owd_baseline_delta_thr_ms=10 # max increase from min baseline before reflector rotated -reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated +reflector_comparison_interval_mins=1 # how often to compare reflectors +reflector_sum_owd_baselines_delta_thr_ms=20 # max increase from min sum owd baselines before reflector rotated +reflector_owd_delta_ewma_delta_thr_ms=10 # max increase from min delta ewma before reflector rotated # stall is detected when the following two conditions are met: # 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh index 413d191c0..f540e8979 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh @@ -24,17 +24,22 @@ sleep_s() # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460057382 # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460074498 + log_msg "DEBUG" "sleep_s" local sleep_duration_s=${1} # (seconds, e.g. 0.5, 1 or 1.5) - read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : & - wait "${!}" + log_msg "DEBUG" "sleep_s read ${sleep_duration_s} - ${__sleep_fd}" +# read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : + read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || true + log_msg "DEBUG" "sleep_s read done" } sleep_us() { + log_msg "DEBUG" "WTF ?" local sleep_duration_us=${1} # (microseconds) - + log_msg "DEBUG" "sleep_us" sleep_duration_s=000000${sleep_duration_us} sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6} + log_msg "DEBUG" "go to sleep_s" sleep_s "${sleep_duration_s}" } @@ -53,6 +58,19 @@ sleep_remaining_tick_time() fi } +get_remaining_tick_time() +{ + # updates sleep_duration_s remaining to end of tick duration + + local t_start_us=${1} # (microseconds) + local tick_duration_us=${2} # (microseconds) + + sleep_duration_us=$(( t_start_us + tick_duration_us - ${EPOCHREALTIME/./} )) + ((sleep_duration_us<0)) && sleep_duration_us=0 + sleep_duration_s=000000${sleep_duration_us} + sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6} +} + randomize_array() { local -n array=${1} @@ -85,171 +103,32 @@ unlock() rm -f "${path:?}" } -_proc_man_set_key() +terminate() { - local key=${1} - local value=${2} + # Send regular kill to processes and monitor terminations; + # return as soon as all of the active processes terminate; + # if any processes remain active after one second, kill with fire using kill -9; + # and, finally, call wait on all processes to reap any zombie processes. - lock "${PROC_STATE_FILE_LOCK:?}" - trap 'unlock "${PROC_STATE_FILE_LOCK:?}"' RETURN + local pids=("${@:-}") + + kill "${pids[@]}" 2> /dev/null - local entered=0 - while read -r line; do - if [[ ${line} =~ ^${key}= ]]; then - printf '%s\n' "${key}=${value}" - entered=1 - else - printf '%s\n' "${line}" - fi - done < "${PROC_STATE_FILE:?}" > "${PROC_STATE_FILE:?}.tmp" - if (( entered == 0 )); then - printf '%s\n' "${key}=${value}" >> "${PROC_STATE_FILE:?}.tmp" - fi - mv "${PROC_STATE_FILE:?}.tmp" "${PROC_STATE_FILE:?}" - return 0 + for((i=0; i<10; i++)) + do + for process in "${!pids[@]}" + do + kill -0 "${pids[${process}]}" 2> /dev/null || unset "pids[${process}]" + done + [[ "${pids[*]}" ]] || return + sleep_s 0.1 + done + + kill -9 "${pids[@]}" 2> /dev/null + + wait "${@:-}" } -_proc_man_get_key_value() -{ - local key=${1} - - lock "${PROC_STATE_FILE_LOCK:?}" - trap 'unlock "${PROC_STATE_FILE_LOCK:?}"' RETURN - - while read -r line; do - if [[ ${line} =~ ^${key}= ]]; then - printf '%s\n' "${line#*=}" - return 0 - fi - done < "${PROC_STATE_FILE:?}" - return 1 -} - -proc_man() -{ - local action=${1} - local name=${2} - shift 2 - - if [[ ! -f "${PROC_STATE_FILE:?}" ]]; then - return 1 - fi - - # shellcheck disable=SC2311 - case "${action}" in - "start") - pid=$(_proc_man_get_key_value "${name}") - if (( pid && pid > 0 )) && kill -0 "${pid}" 2> /dev/null; then - return 1; - fi - - "${@}" & - local pid=${!} - _proc_man_set_key "${name}" "${pid}" - ;; - "stop") - local pid - pid=$(_proc_man_get_key_value "${name}") - if ! (( pid && pid > 0 )); then - return 0; - fi - - kill "${pid}" 2> /dev/null || true - - # wait for process to die - killed=0 - for ((i=0; i<10; i++)); - do - if kill -0 "${pid}" 2> /dev/null; then - sleep_us 100000 - else - killed=1 - break - fi - done - - # if process still alive, kill it with fire - if (( killed == 0 )); then - kill -9 "${pid}" 2> /dev/null || true - fi - - _proc_man_set_key "${name}" "-1" "${PROC_STATE_FILE:?}" - ;; - "status") - local pid - pid=$(_proc_man_get_key_value "${name}") - if (( pid && pid > 0 )); then - if kill -0 "${pid}" 2> /dev/null; then - printf '%s\n' "running" - else - printf '%s\n' "dead" - fi - else - printf '%s\n' "stopped" - fi - ;; - "wait") - local pid - pid=$(_proc_man_get_key_value "${name}") - if (( pid && pid > 0 )); then - wait "${pid}" && return 0 - fi - - return 1 - ;; - "signal") - shift 3 - - local pid - pid=$(_proc_man_get_key_value "${name}") - if (( pid && pid > 0 )); then - kill -s "${1}" "${pid}" 2>/dev/null && return 0 - fi - - return 1 - ;; - "initialize") - proc_man_initialize - return $? - ;; - *) - printf '%s\n' "unknown action: ${action}" >&2 - return 1 - ;; - esac - - return 0 -} - -proc_man_initialize() -{ - true > "${PROC_STATE_FILE:?}" -} - -proc_man_start() -{ - proc_man start "${@}" -} - -proc_man_stop() -{ - proc_man stop "${@}" -} - -proc_man_status() -{ - proc_man status "${@}" -} - -proc_man_wait() -{ - proc_man wait "${@}" -} - -proc_man_signal() -{ - proc_man signal "${@}" -} if (( __set_e == 1 )); then set +e diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh index 5d3195dff..cc01892d0 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh @@ -7,17 +7,21 @@ # Author: @Lynx (OpenWrt forum) # Inspiration taken from: @moeller0 (OpenWrt forum) -INTERFACE=$(basename "$0" | cut -d. -f2) +INTERFACE=$(basename "$1" | cut -d. -f2) cake_autorate_version="2.0.0" # *** OUTPUT AND LOGGING OPTIONS *** -output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing processing stats -output_load_stats=$(uci -q get sqm.${INTERFACE}.output_load_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing achieved loads +output_processing_stats=1 +#$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing processing stats +output_load_stats=0 +#$(uci -q get sqm.${INTERFACE}.output_load_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing achieved loads output_reflector_stats=$(uci -q get sqm.${INTERFACE}.output_reflector_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing reflector stats -output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo '0') # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes -debug=$(uci -q get sqm.${INTERFACE}.debug || echo '0') # enable (1) or disable (0) out of debug lines +output_cake_changes=0 +#$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo '0') # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +debug=0 +#$(uci -q get sqm.${INTERFACE}.debug || echo '0') # enable (1) or disable (0) out of debug lines # This can generate a LOT of records so be careful: log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. @@ -26,7 +30,7 @@ log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG # every write the cumulative write time and bytes associated with each log line are checked # and if either exceeds the configured values below, the log log file is rotated log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log) -log_file_max_time_mins=10 # maximum time between log file rotations +log_file_max_time_mins=10000 # maximum time between log file rotations log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations # log file path defaults to /var/log/ @@ -46,7 +50,7 @@ ul_if=$(uci -q get sqm.${INTERFACE}.interface) # upload interface # fping - round robin pinging (rtts) # ping - (iputils-ping) individual pinging (rtts) # hping3 - individidual pinging (owds) -pinger_binary=ping +pinger_binary=tsping # list of reflectors to use and number of pingers to initiate # pingers will be initiated with reflectors in the order specified in the list @@ -54,16 +58,16 @@ pinger_binary=ping # so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially # and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad # a bad reflector will go to the back of the queue on reflector rotation -reflectors=($(uci -q get omr-tracker.defaults.hosts)) -#reflectors=( -#"1.1.1.1" "1.0.0.1" # Cloudflare -#"8.8.8.8" "8.8.4.4" # Google -#"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 -#"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard -#"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar -#"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS -#"185.228.168.9" "185.228.168.10" # CleanBrowsing -#) +#reflectors=$(uci -q get omr-tracker.defaults.hosts) +reflectors=( +"1.1.1.1" "1.0.0.1" # Cloudflare +"8.8.8.8" "8.8.4.4" # Google +"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 +"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard +"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar +"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS +"185.228.168.9" "185.228.168.10" # CleanBrowsing +) randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup @@ -71,14 +75,14 @@ randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors o # to avoid excessive CPU use (proportional with ping interval / number of pingers) # and to avoid abusive network activity (excessive ICMP frequency to one reflector) # The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G -no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "6") # number of pingers to maintain -reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.3") # (seconds, e.g. 0.2s or 2s) +no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "4") # number of pingers to maintain +reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "1") # (seconds, e.g. 0.2s or 2s) # delay threshold in ms is the extent of OWD increase to classify as a delay # these are automatically adjusted based on maximum on the wire packet size # (adjustment significant at sub 12Mbit/s rates, else negligible) -dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "30") # (milliseconds) -ul_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "30") # (milliseconds) +dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "100") # (milliseconds) +ul_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "100") # (milliseconds) # Set either of the below to 0 to adjust one direction only # or alternatively set both to 0 to simply use cake-autorate to monitor a connection @@ -97,11 +101,11 @@ max_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_upload || echo "35000" # pausing all active pingers when connection is not in active use enable_sleep_function=$(uci -q get sqm.${INTERFACE}.enable_sleep_functions || echo "1") # enable (1) or disable (0) sleep functonality connection_active_thr_kbps=$(uci -q get sqm.${INTERFACE}.connection_active_thr_kpbs || echo "1000") # threshold in Kbit/s below which dl/ul is considered idle -sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.sustained_idle_sleep_thr || echo "60.0") # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) +sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.sustained_idle_sleep_thr || echo "150.0") # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) min_shaper_rates_enforcement=$(uci -q get sqm.${INTERFACE}.min_shaper_rates_enforcement || echo "0") # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall -startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "60.0") # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) +startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "0.0") # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) # *** ADVANCED CONFIGURATION OPTIONS *** @@ -126,7 +130,8 @@ log_file_export_compress=1 # compress log file exports using gzip and append .gz # Unfortunately, fping does not offer a command line switch to set # the firewall mark. # WARNING: no error checking so use at own risk! -ping_extra_args="- B -I ${INTERFACE}" +#ping_extra_args="-B -I ${INTERFACE}" +ping_extra_args="" # a wrapper for ping binary - used as a prefix for the real command # e.g., when using mwan3, it is recommended to set it like this: @@ -172,13 +177,13 @@ high_load_thr=0.75 # % of currently set bandwidth for detecting high load # the bufferbloat refractory period should be greater than the # average time it would take to replace the bufferbloat # detection window with new samples upon a bufferbloat event -bufferbloat_refractory_period_ms=300 # (milliseconds) +bufferbloat_refractory_period_ms=2000 # (milliseconds) decay_refractory_period_ms=1000 # (milliseconds) # interval for checking reflector health reflector_health_check_interval_s=1.0 # (seconds) # deadline for reflector response not to be classified as an offence against reflector -reflector_response_deadline_s=1.0 # (seconds) +reflector_response_deadline_s=2.0 # (seconds) # reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples # out of the last (reflector misbehaving detection window) samples are offences @@ -190,7 +195,7 @@ reflector_misbehaving_detection_thr=3 reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list reflector_comparison_interval_mins=1 # how often to compare reflectors -reflector_owd_baseline_delta_thr_ms=10 # max increase from min baseline before reflector rotated +reflector_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines before reflector rotated reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated # stall is detected when the following two conditions are met: @@ -199,7 +204,7 @@ reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma be stall_detection_thr=5 connection_stall_thr_kbps=10 -global_ping_response_timeout_s=10.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) +global_ping_response_timeout_s=100.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) diff --git a/tsping/Makefile b/tsping/Makefile new file mode 100644 index 000000000..e26a2e642 --- /dev/null +++ b/tsping/Makefile @@ -0,0 +1,38 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=tsping +PKG_VERSION:=0.2.3 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/Lochnair/tsping +PKG_SOURCE_VERSION:=2560d79c95154d2e2c9aa6725135f6fc5cf091d7 + +PKG_MAINTAINER:=Nils Andreas Svee +PKG_LICENSE:=BSD-3-Clause +PKG_LICENSE_FILES:=LICENSE.md + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 +PKG_BUILD_DEPENDS:=!USE_GLIBC:argp-standalone + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/meson.mk + +define Package/tsping + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Utility for sending timestamp pings + URL:=https://github.com/Lochnair/tsping +endef + +define Package/tsping/description + A simple application to send ICMP echo/timestamp requests +endef + +define Package/tsping/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(MESON_BUILD_DIR)/tsping $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,tsping)) From aaa5499ee91a3dca690faec9b6c9bf728e4b67fd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 3 Jun 2023 08:29:17 +0200 Subject: [PATCH 0973/2059] Fix autorate restart --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 5c12d788f..72ceeb373 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1752,7 +1752,7 @@ if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprout sleep 5 fi -if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "autorate.*${OMR_TRACKER_DEVICE}") ]; then +if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "autorate_config.*${OMR_TRACKER_DEVICE}") ]; then /etc/init.d/sqm-autorate restart >/dev/null 2>&1 sleep 5 fi From f14e11ded3e099efddd0e287e3d0358b6fdf33f9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 3 Jun 2023 08:31:06 +0200 Subject: [PATCH 0974/2059] Fix autorate restart (really) --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 72ceeb373..032c7ae3b 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1752,7 +1752,7 @@ if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprout sleep 5 fi -if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "autorate_config.*${OMR_TRACKER_DEVICE}") ]; then +if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "autorate_config.${OMR_TRACKER_INTERFACE}") ]; then /etc/init.d/sqm-autorate restart >/dev/null 2>&1 sleep 5 fi From 193a98bb7f2f2c03402925fe5939b83fad51bd4d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 4 Jun 2023 20:54:15 +0200 Subject: [PATCH 0975/2059] Fix on sqm autorate --- .../sqm-autorate/cake-autorate_template.sh | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh index cc01892d0..1a9b6105f 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh @@ -13,15 +13,11 @@ cake_autorate_version="2.0.0" # *** OUTPUT AND LOGGING OPTIONS *** -output_processing_stats=1 -#$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing processing stats -output_load_stats=0 -#$(uci -q get sqm.${INTERFACE}.output_load_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing achieved loads +output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing processing stats +output_load_stats=$(uci -q get sqm.${INTERFACE}.output_load_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing achieved loads output_reflector_stats=$(uci -q get sqm.${INTERFACE}.output_reflector_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing reflector stats -output_cake_changes=0 -#$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo '0') # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes -debug=0 -#$(uci -q get sqm.${INTERFACE}.debug || echo '0') # enable (1) or disable (0) out of debug lines +output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo '0') # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +debug=$(uci -q get sqm.${INTERFACE}.debug || echo '0') # enable (1) or disable (0) out of debug lines # This can generate a LOT of records so be careful: log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. @@ -76,13 +72,17 @@ randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors o # and to avoid abusive network activity (excessive ICMP frequency to one reflector) # The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "4") # number of pingers to maintain -reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "1") # (seconds, e.g. 0.2s or 2s) +reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.5") # (seconds, e.g. 0.2s or 2s) # delay threshold in ms is the extent of OWD increase to classify as a delay # these are automatically adjusted based on maximum on the wire packet size -# (adjustment significant at sub 12Mbit/s rates, else negligible) -dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "100") # (milliseconds) -ul_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "100") # (milliseconds) +# (adjustment significant at sub 12Mbit/s rates, else negligible) +latency=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) +[ -z "$latency" ] && latency="$(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30))" +[ -z "$latency" ] && latency="100" +logger -t "sqm" "latency $INTERFACE: $latency" +dl_delay_thr_ms="$latency" # (milliseconds) +ul_delay_thr_ms="$latency" # (milliseconds) # Set either of the below to 0 to adjust one direction only # or alternatively set both to 0 to simply use cake-autorate to monitor a connection @@ -131,7 +131,7 @@ log_file_export_compress=1 # compress log file exports using gzip and append .gz # the firewall mark. # WARNING: no error checking so use at own risk! #ping_extra_args="-B -I ${INTERFACE}" -ping_extra_args="" +ping_extra_args="-i ${ul_if}" # a wrapper for ping binary - used as a prefix for the real command # e.g., when using mwan3, it is recommended to set it like this: From 5f8f4ee4fd87ae58d8a2d312d979348117379c19 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 9 Jun 2023 19:59:35 +0200 Subject: [PATCH 0976/2059] Use Busybox syslogd --- openmptcprouter-full/Makefile | 2 +- syslogd/Makefile | 59 ++++++++++++++++++++++++++++++++ syslogd/files/etc/init.d/syslogd | 24 +++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 syslogd/Makefile create mode 100755 syslogd/files/etc/init.d/syslogd diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index dd49c905b..c9141b684 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -82,7 +82,7 @@ MY_DEPENDS := \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ - (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core + (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ diff --git a/syslogd/Makefile b/syslogd/Makefile new file mode 100644 index 000000000..527d62024 --- /dev/null +++ b/syslogd/Makefile @@ -0,0 +1,59 @@ +# +# Copyright (C) 2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v3 or later. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=syslogd +PKG_VERSION:=1 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Ycarus (Yannick Chabanois) +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/syslogd + SECTION:=utilities + CATEGORY:=Utilities + TITLE:=Busybox syslogd OpenWRT init script + DEPENDS:=+busybox + KCONFIG:=\ + CONFIG_BUSYBOX_CUSTOM=y \ + CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG=y \ + CONFIG_BUSYBOX_CONFIG_LOGREAD=y \ + CONFIG_BUSYBOX_CONFIG_SYSLOGD=y \ + CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOGD_CFG=y \ + CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS=y \ + CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256 \ + CONFIG_BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG=y \ + CONFIG_BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=64 + PKGARCH:=all +endef + +define Package/syslogd/description + Busybox syslogd package with init script for OpenWRT +endef + +define Package/syslogd/conffiles +/etc/syslog.conf +endef + +define Build/Prepare +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/syslogd/install + $(INSTALL_DIR) $(1) + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,syslogd)) diff --git a/syslogd/files/etc/init.d/syslogd b/syslogd/files/etc/init.d/syslogd new file mode 100755 index 000000000..30afc3b66 --- /dev/null +++ b/syslogd/files/etc/init.d/syslogd @@ -0,0 +1,24 @@ +#!/bin/sh /etc/rc.common + +START=11 + +USE_PROCD=1 +NAME=syslogd +PROG=/sbin/syslogd + +start_service() { + local log_size=$(uci -q get system.@system[0].log_size) + local log_ip=$(uci -q get system.@system[0].log_ip) + local log_port=$(uci -q get system.@system[0].log_port || echo '514') + local log_file=$(uci -q get system.@system[0].log_file) + local conloglevel=$(uci -q get system.@system[0].conloglevel) + + procd_open_instance + procd_set_param command "$PROG" -n ${log_size:+-C"$log_size"} ${log_ip:+-R"$log_ip":"$log_port"} ${log_file:+-O "$log_file"} ${conloglevel:+-l "$conloglevel"} + procd_set_param respawn + procd_close_instance +} + +reload_service() { + procd_send_signal syslogd +} From e7699c70a70df71e1f309d5ba239f25485ea5de3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 9 Jun 2023 20:00:01 +0200 Subject: [PATCH 0977/2059] kill all autorate on stop --- luci-app-sqm-autorate/root/etc/init.d/sqm-autorate | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 11b766808..1485c924f 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -53,6 +53,7 @@ start_service() { stop_service() { rm -f /usr/share/sqm-autorate/cake-autorate_config.*.sh + pkill -9 cake-autorate } reload_service() { From cab489f0b078dfb53a51ed1d10cc6766fbe638c5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Jun 2023 09:54:57 +0200 Subject: [PATCH 0978/2059] Update cake-autorate --- .../usr/share/sqm-autorate/cake-autorate.sh | 393 ++++++++++-------- .../share/sqm-autorate/cake-autorate_lib.sh | 12 +- 2 files changed, 216 insertions(+), 189 deletions(-) diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh index eda0680a4..e45c1c306 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh @@ -32,9 +32,9 @@ cake_autorate_version="2.0.0" ## -1 signifies that the log file fd will not be used and ## that the log file will be written to directly log_fd=-1 -exec {main_fd}<> <(:) || true -exec {monitor_achieved_rates_fd}<> <(:) || true -exec {maintain_pingers_fd}<> <(:) || true +exec {main_fd}<> <(:) +exec {monitor_achieved_rates_fd}<> <(:) +exec {maintain_pingers_fd}<> <(:) # pinger_fds are set below in dependence upon ping binary and number of pingers # process pids are stored below in the form @@ -87,9 +87,9 @@ cleanup_and_killall() sleep_s 1 # terminate any processes that remain, save for main and intercept_stderr - unset proc_pids[main] + unset "proc_pids[main]" intercept_stderr_pid="${proc_pids[intercept_stderr]}" - unset proc_pids[intercept_stderr] + unset "proc_pids[intercept_stderr]" terminate "${proc_pids[@]}" # restore original stderr, and terminate intercept_stderr @@ -172,7 +172,22 @@ rotate_log_file() cat "${log_file_path}" > "${log_file_path}.old" true > "${log_file_path}" fi + ((output_processing_stats)) && print_headers + t_log_file_start_us=${EPOCHREALTIME/./} + get_log_file_size_bytes +} + +reset_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + rm -f "${log_file_path}.old" + true > "${log_file_path}" + + ((output_processing_stats)) && print_headers + t_log_file_start_us=${EPOCHREALTIME/./} + get_log_file_size_bytes } generate_log_file_scripts() @@ -210,19 +225,19 @@ generate_log_file_scripts() printf "\${log_file_export_path}\n" EOT - cat > "${run_path}/log_file_rotate" <<- EOT + cat > "${run_path}/log_file_reset" <<- EOT #!/bin/bash if kill -USR2 "${proc_pids['maintain_log_file']}" then - printf "Successfully signalled maintain_log_file process to request log file rotation.\n" + printf "Successfully signalled maintain_log_file process to request log file reset.\n" else printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 exit 1 fi EOT - chmod +x "${run_path}/log_file_export" "${run_path}/log_file_rotate" + chmod +x "${run_path}/log_file_export" "${run_path}/log_file_reset" } export_log_file() @@ -282,53 +297,47 @@ maintain_log_file() trap '' INT trap 'kill_maintain_log_file' TERM EXIT trap 'export_log_file' USR1 - trap 'rotate_log_file_signalled=1' USR2 + trap 'reset_log_file_signalled=1' USR2 log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - rotate_log_file_signalled=0 + reset_log_file_signalled=0 t_log_file_start_us=${EPOCHREALTIME/./} get_log_file_size_bytes - while true + while read -r -u "${log_fd}" log_line do - while read -r -u "${log_fd}" log_line - do - printf '%s\n' "${log_line}" >> "${log_file_path}" + printf '%s\n' "${log_line}" >> "${log_file_path}" - # Verify log file size < configured maximum - # The following two lines with costly call to 'du': - # read log_file_size_bytes< <(du -b ${log_file_path}/cake-autorate.log) - # log_file_size_bytes=${log_file_size_bytes//[!0-9]/} - # can be more efficiently handled with this line: - ((log_file_size_bytes=log_file_size_bytes+${#log_line}+1)) + # Verify log file size < configured maximum + # The following two lines with costly call to 'du': + # read log_file_size_bytes< <(du -b ${log_file_path}/cake-autorate.log) + # log_file_size_bytes=${log_file_size_bytes//[!0-9]/} + # can be more efficiently handled with this line: + ((log_file_size_bytes=log_file_size_bytes+${#log_line}+1)) - # Verify log file time < configured maximum - if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) - then - - log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so rotating log file" - break - elif (( log_file_size_bytes > log_file_max_size_bytes )) - then - log_file_size_KB=$((log_file_size_bytes/1024)) - log_msg "DEBUG" "log file size: ${log_file_size_KB} KB has exceeded configured maximum: ${log_file_max_size_KB} KB so rotating log file" - break - elif (( rotate_log_file_signalled )) - then - log_msg "DEBUG" "received log file rotation signal so rotating log file." - rotate_log_file_signalled=0 - break - fi - - done - - flush_log_fd - rotate_log_file - t_log_file_start_us=${EPOCHREALTIME/./} - get_log_file_size_bytes + # Verify log file time < configured maximum + if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) + then + + log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so flushing and rotating log file." + flush_log_fd + rotate_log_file + elif (( log_file_size_bytes > log_file_max_size_bytes )) + then + log_file_size_KB=$((log_file_size_bytes/1024)) + log_msg "DEBUG" "log file size: ${log_file_size_KB} KB has exceeded configured maximum: ${log_file_max_size_KB} KB so flushing and rotating log file." + flush_log_fd + rotate_log_file + elif (( reset_log_file_signalled )) + then + log_msg "DEBUG" "received log file reset signal so flushing and resetting log file." + flush_log_fd + reset_log_file + reset_log_file_signalled=0 + fi done } @@ -379,7 +388,7 @@ get_next_shaper_rate() ;; *) log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in get_next_shaper_rate" - exit 1 + kill $$ 2>/dev/null ;; esac # make sure to only return rates between cur_min_rate and cur_max_rate @@ -430,7 +439,7 @@ monitor_achieved_rates() SET_ARRAY_ELEMENT) if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] then - declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi ;; TERMINATE) @@ -460,7 +469,7 @@ monitor_achieved_rates() load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) - for pinger_fd in "${pinger_fds[@]}" + for pinger_fd in "${pinger_fds[@]:?}" do printf "SET_ARRAY_ELEMENT load_percent dl %s\n" "${load_percent[dl]}" >&"${pinger_fd}" printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}" @@ -505,7 +514,7 @@ classify_load() do ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )); then - load_condition[direction]="${load_condition[direction]}_sss" + load_condition["${direction}"]="${load_condition[${direction}]}_sss" break fi done @@ -542,10 +551,10 @@ parse_tsping() for (( reflector=0; reflector&"${main_fd}" + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" timestamp_us="${timestamp//[.]}" @@ -689,7 +698,7 @@ parse_tsping() printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT reflector_last_timestamps_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi done } @@ -705,14 +714,18 @@ parse_fping() log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - declare -A rtt_baselines_us - declare -A rtt_delta_ewmas_us + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us for (( reflector=0; reflector= rtt_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) - - ewma_iteration "${rtt_us}" "${alpha}" "rtt_baselines_us[${reflector}]" - - rtt_delta_us=$(( rtt_us-rtt_baselines_us[${reflector}] )) - - if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)); then - ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" "rtt_delta_ewmas_us[${reflector}]" - fi - - dl_owd_baseline_us=$((rtt_baselines_us[${reflector}]/2)) - ul_owd_baseline_us="${dl_owd_baseline_us}" - - dl_owd_delta_ewma_us=$((rtt_delta_ewmas_us[${reflector}]/2)) - ul_owd_delta_ewma_us="${dl_owd_delta_ewma_us}" - + dl_owd_us=$((rtt_us/2)) ul_owd_us="${dl_owd_us}" - dl_owd_delta_us=$((rtt_delta_us/2)) + dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) ul_owd_delta_us="${dl_owd_delta_us}" - + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" + fi + timestamp="${timestamp//[\[\]]}0" - printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${main_fd}" + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" timestamp_us="${timestamp//[.]}" - - printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baseline_us}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baseline_us}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT reflector_last_timestamps_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi done } @@ -857,11 +866,15 @@ parse_ping() log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - declare -A rtt_baselines_us - declare -A rtt_delta_ewmas_us + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us - rtt_baselines_us[${reflector}]=100000 - rtt_delta_ewmas_us[${reflector}]=0 + dl_owd_baselines_us["${reflector}"]=100000 + ul_owd_baselines_us["${reflector}"]=100000 + dl_owd_delta_ewmas_us["${reflector}"]=0 + ul_owd_delta_ewmas_us["${reflector}"]=0 declare -A load_percent load_percent[dl]=0 @@ -878,7 +891,7 @@ parse_ping() REFLECTOR_RESPONSE) read -r timestamp _ _ _ reflector seq_rtt <<< "${command[@]:1}" - checksum="${command[@]: -1}" + checksum="${command[*]: -1}" ;; START_PINGER) @@ -905,8 +918,10 @@ parse_ping() then reflector="${command[1]}" log_msg "DEBUG" "Read in new reflector: ${reflector}" - rtt_baselines_us[${reflector}]="${rtt_baselines_us[${reflector}]:-100000}" - rtt_delta_ewmas_us[${reflector}]="${rtt_delta_ewmas_us[${reflector}]:-0}" + dl_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]:-100000}" + ul_owd_baselines_us["${reflector}"]="${ul_owd_baselines_us[${reflector}]:-100000}" + dl_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]:-0}" + ul_owd_delta_ewmas_us["${reflector}"]="${ul_owd_delta_ewmas_us[${reflector}]:-0}" continue fi ;; @@ -924,8 +939,9 @@ parse_ping() if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] then - declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi + continue ;; TERMINATE) @@ -936,7 +952,7 @@ parse_ping() *) - : + continue ;; esac @@ -948,48 +964,43 @@ parse_ping() # If no match then skip onto the next one [[ "${seq_rtt}" =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + reflector=${reflector//:/} + seq=${BASH_REMATCH[1]} rtt_us=${BASH_REMATCH[3]}000 rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) - reflector=${reflector//:/} - - alpha=$(( rtt_us >= rtt_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) - - ewma_iteration "${rtt_us}" "${alpha}" "rtt_baselines_us[${reflector}]" - - rtt_delta_us=$(( rtt_us-rtt_baselines_us[${reflector}] )) - - if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent )); then - ewma_iteration "${rtt_delta_us}" "${alpha_delta_ewma}" "rtt_delta_ewmas_us[${reflector}]" - fi - - dl_owd_baseline_us=$((rtt_baselines_us[${reflector}]/2)) - ul_owd_baseline_us=${dl_owd_baseline_us} - - dl_owd_delta_ewma_us=$((rtt_delta_ewmas_us[${reflector}]/2)) - ul_owd_delta_ewma_us=${dl_owd_delta_ewma_us} - dl_owd_us=$((rtt_us/2)) ul_owd_us="${dl_owd_us}" - dl_owd_delta_us=$((rtt_delta_us/2)) - ul_owd_delta_us="${dl_owd_delta_us}" + dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us="${dl_owd_delta_us}" + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" + fi timestamp="${timestamp//[\[\]]}" - printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" >&"${main_fd}" - + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" + timestamp_us="${timestamp//[.]}" - printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baseline_us}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baseline_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewma_us}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT reflector_last_timestamps_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi done } @@ -1016,7 +1027,7 @@ start_pinger() ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - exit 1 + kill $$ 2>/dev/null ;; esac } @@ -1038,7 +1049,7 @@ start_pingers() ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - exit 1 + kill $$ 2>/dev/null ;; esac } @@ -1092,7 +1103,7 @@ kill_pingers() ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - exit 1 + kill $$ 2>/dev/null ;; esac } @@ -1131,12 +1142,20 @@ replace_pinger_reflector() ping) printf "SET_REFLECTOR %s\n" "${reflectors[pinger]}" >&"${pinger_fds[pinger]}" ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; esac start_pinger "${pinger}" else log_msg "DEBUG" "No additional reflectors specified so just retaining: ${reflectors[pinger]}." - reflector_offences[pinger]=0 fi + + log_msg "DEBUG" "Resetting reflector offences associated with reflector: ${reflectors[pinger]}." + declare -n reflector_offences="reflector_${pinger}_offences" + for ((i=0; i&"${pinger_fds[pinger]}" done ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; esac exit @@ -1205,7 +1228,7 @@ maintain_pingers() declare -A ul_owd_baselines_us declare -A dl_owd_delta_ewmas_us declare -A ul_owd_delta_ewmas_us - declare -A reflector_last_timestamps_us + declare -A last_timestamp_reflectors_us err_silence=0 reflector_offences_idx=0 @@ -1217,7 +1240,7 @@ maintain_pingers() for ((reflector=0; reflector < no_reflectors; reflector++)) do - reflector_last_timestamps_us["${reflectors[reflector]}"]="${pingers_t_start_us}" + last_timestamp_reflectors_us["${reflectors[reflector]}"]="${pingers_t_start_us}" done # For each pinger initialize record of offences @@ -1250,6 +1273,10 @@ maintain_pingers() printf "SET_PROC_PID proc_pids %s %s\n" "parse_ping_${pinger}" "${!}" >&"${main_fd}" done ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; esac @@ -1269,14 +1296,21 @@ maintain_pingers() then change_state_maintain_pingers "${command[1]}" # break out of reading any new IPC commands to handle next state - # since next state might be to start or stop pingers - break + # if pingers need to be started or stopped + case "${command[1]}" in + START|STOP) + break + ;; + *) + : + ;; + esac fi ;; SET_ARRAY_ELEMENT) if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] then - declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi ;; SET_VAR) @@ -1320,7 +1354,7 @@ maintain_pingers() RUNNING) - if (( ${t_start_us}>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) + if (( t_start_us>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) then pinger=$((RANDOM%no_pingers)) log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." @@ -1329,7 +1363,7 @@ maintain_pingers() continue fi - if (( ${t_start_us}>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then + if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then t_last_reflector_comparison_us=${EPOCHREALTIME/./} @@ -1386,18 +1420,16 @@ maintain_pingers() fi - enable_replace_pinger_reflector=1 + replace_pinger_reflector_enabled=1 for ((pinger=0; pinger < no_pingers; pinger++)) do - reflector_check_time_us="${EPOCHREALTIME/./}" - reflector_last_timestamp_us="${reflector_last_timestamps_us["${reflectors[pinger]}"]}" # shellcheck disable=SC2178 declare -n reflector_offences="reflector_${pinger}_offences" (( reflector_offences[reflector_offences_idx] )) && ((sum_reflector_offences[pinger]--)) # shellcheck disable=SC2154 - reflector_offences[reflector_offences_idx]=$(( (((reflector_check_time_us-reflector_last_timestamp_us) > reflector_response_deadline_us)) ? 1 : 0 )) + reflector_offences[reflector_offences_idx]=$(( (${EPOCHREALTIME/./}-last_timestamp_reflectors_us[${reflectors[pinger]}]) > reflector_response_deadline_us ? 1 : 0 )) if (( reflector_offences[reflector_offences_idx] )); then ((sum_reflector_offences[pinger]++)) @@ -1408,11 +1440,9 @@ maintain_pingers() if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )); then log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving." - if ((enable_replace_pinger_reflector)); then + if ((replace_pinger_reflector_enabled)); then replace_pinger_reflector "${pinger}" - for ((i=0; i&${monitor_achieved_rates_fd} + printf "SET_ARRAY_ELEMENT shaper_rate_kbps dl %s\n" "${shaper_rate_kbps[dl]}" >&"${monitor_achieved_rates_fd}" last_shaper_rate_kbps[dl]="${shaper_rate_kbps[dl]}" fi if (( shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then set_cake_rate "${ul_if}" "${shaper_rate_kbps[ul]}" adjust_ul_shaper_rate - printf "SET_ARRAY_ELEMENT shaper_rate_kbps ul %s\n" "${shaper_rate_kbps[ul]}" >&${monitor_achieved_rates_fd} + printf "SET_ARRAY_ELEMENT shaper_rate_kbps ul %s\n" "${shaper_rate_kbps[ul]}" >&"${monitor_achieved_rates_fd}" last_shaper_rate_kbps[ul]="${shaper_rate_kbps[ul]}" fi @@ -1483,8 +1513,8 @@ get_max_wire_packet_size_bits() local -n max_wire_packet_size_bits="${2}" read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" - [[ $(tc qdisc show dev "${interface}" || true) =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] - [[ -n "${BASH_REMATCH[2]:-}" ]] && max_wire_packet_size_bits=$(( 8*(max_wire_packet_size_bits+BASH_REMATCH[2]) )) + [[ $(tc qdisc show dev "${interface}") =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] + max_wire_packet_size_bits=$(( 8*(max_wire_packet_size_bits+BASH_REMATCH[2]) )) # atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits [[ "${BASH_REMATCH[1]:-}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*((max_wire_packet_size_bits+376)/384) )) } @@ -1636,7 +1666,7 @@ run_path=/var/run/cake-autorate/ if [[ -n ${1-} ]]; then config_path="${1}" else - config_path="$PREFIX/cake-autorate_config.primary.sh" + config_path="${PREFIX}/cake-autorate_config.primary.sh" fi if [[ ! -f "${config_path}" ]]; then @@ -1685,7 +1715,7 @@ log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${conf # ${run_path}/ is used to store temporary files # it should not exist on startup so if it does exit, else create the directory if [[ -d "${run_path}" ]]; then - if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' ${run_path}/proc_pids) && [[ -d "/proc/${running_main_pid}" ]] + if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' "${run_path}/proc_pids") && [[ -d "/proc/${running_main_pid}" ]] then log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script." trap - INT TERM EXIT @@ -1720,7 +1750,7 @@ command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${p if ((log_to_file)); then log_file_max_time_us=$((log_file_max_time_mins*60000000)) log_file_max_size_bytes=$((log_file_max_size_KB*1024)) - exec {log_fd}<> <(:) || true + exec {log_fd}<> <(:) maintain_log_file & proc_pids['maintain_log_file']=${!} fi @@ -1816,8 +1846,6 @@ stall_detection_timeout_us=$(( stall_detection_thr*ping_response_interval_us )) stall_detection_timeout_s=000000${stall_detection_timeout_us} stall_detection_timeout_s=$(( 10#${stall_detection_timeout_s::-6})).${stall_detection_timeout_s: -6} -concurrent_read_integer_interval_us=$((ping_response_interval_us/4)) - declare -A bufferbloat_detected declare -A load_percent declare -A load_condition @@ -1863,8 +1891,6 @@ t_last_decay_us[ul]="${t_start_us}" t_sustained_connection_idle_us=0 reflectors_last_timestamp_us="${EPOCHREALTIME/./}" -dl_achieved_rate_kbps=0 -ul_achieved_rate_kbps=0 mapfile -t dl_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) mapfile -t ul_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) @@ -1894,23 +1920,27 @@ if ((startup_wait_us>0)); then sleep_us "${startup_wait_us}" fi -# Initiate achieved rate monitor -monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" & -proc_pids[monitor_achieved_rates]="${!}" - case "${pinger_binary}" in tsping|fping) - exec {pinger_fds[0]}<> <(:) || true + exec {pinger_fds[0]}<> <(:) ;; ping) for ((pinger=0; pinger<=no_pingers; pinger++)) do - exec {pinger_fds[pinger]}<> <(:) || true + exec {pinger_fds[pinger]}<> <(:) done ;; + + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; esac +monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" & +proc_pids['monitor_achieved_rates']="${!}" + maintain_pingers & proc_pids['maintain_pingers']="${!}" @@ -1942,15 +1972,15 @@ do SET_ARRAY_ELEMENT) if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] then - declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi ;; SET_PROC_PID) if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] then - declare -A "${command[1]}"+="(["${command[2]}"]="${command[3]}")" + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi - > "${run_path}/proc_pids" + true > "${run_path}/proc_pids" for proc_pid in "${!proc_pids[@]}" do printf "%s=%s\n" "${proc_pid}" "${proc_pids[${proc_pid}]}" >> "${run_path}/proc_pids" @@ -1977,7 +2007,7 @@ do continue fi - # Keep track of number of dl delays across detection window + # Keep track of number of delays across detection window # .. for download: (( dl_delays[delays_idx] )) && ((sum_dl_delays--)) dl_delays[delays_idx]=$(( dl_owd_delta_us > compensated_dl_delay_thr_us ? 1 : 0 )) @@ -2030,7 +2060,7 @@ do t_sustained_connection_idle_us=0 fi fi - elif (( (${EPOCHREALTIME/./} - ${reflectors_last_timestamp_us}) > ${stall_detection_timeout_us} )) + elif (( (${EPOCHREALTIME/./} - reflectors_last_timestamp_us) > stall_detection_timeout_us )) then log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking loads." @@ -2091,6 +2121,11 @@ do printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" fi ;; + *) + + log_msg "ERROR" "Unrecognized main state: ${main_state}. Exiting now." + kill $$ 2>/dev/null + ;; esac done diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh index f540e8979..7743b5467 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh @@ -24,22 +24,16 @@ sleep_s() # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460057382 # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460074498 - log_msg "DEBUG" "sleep_s" local sleep_duration_s=${1} # (seconds, e.g. 0.5, 1 or 1.5) - log_msg "DEBUG" "sleep_s read ${sleep_duration_s} - ${__sleep_fd}" -# read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : - read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || true - log_msg "DEBUG" "sleep_s read done" + read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : } sleep_us() { - log_msg "DEBUG" "WTF ?" local sleep_duration_us=${1} # (microseconds) - log_msg "DEBUG" "sleep_us" + sleep_duration_s=000000${sleep_duration_us} sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6} - log_msg "DEBUG" "go to sleep_s" sleep_s "${sleep_duration_s}" } @@ -125,8 +119,6 @@ terminate() done kill -9 "${pids[@]}" 2> /dev/null - - wait "${@:-}" } From 2c80e11f87fb44b9ad1cac8d266cab5203816b89 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Jun 2023 09:55:51 +0200 Subject: [PATCH 0979/2059] Change master connection weight --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 032c7ae3b..56050f14c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -219,7 +219,7 @@ set_routes_intf() { #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$serverip" ] && [ "$(ip route show $serverip | grep $interface_if)" = "" ]; then if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -z "$(echo $interface_gw | grep :)" ]; then if [ "$multipath_config_route" = "master" ]; then - weight=10 + weight=100 else weight=1 fi @@ -292,7 +292,7 @@ set_routes_intf6() { #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$serverip" ] && [ "$(ip -6 route show $serverip | grep $interface_if)" = "" ]; then if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then if [ "$multipath_config_route" = "master" ]; then - weight=10 + weight=100 else weight=1 fi @@ -351,7 +351,7 @@ set_route_balancing() { elif [ "$(uci -q get openmtpcprouter.$INTERFACE.weight)" != "" ]; then weight=$(uci -q get openmtpcprouter.$INTERFACE.weight) elif [ "$multipath_config_route" = "master" ]; then - weight=2 + weight=100 else weight=1 fi @@ -418,7 +418,7 @@ set_route_balancing6() { elif [ "$(uci -q get openmtpcprouter.$INTERFACE.weight)" != "" ]; then weight=$(uci -q get openmtpcprouter.$INTERFACE.weight) elif [ "$multipath_config_route" = "master" ]; then - weight=2 + weight=100 else weight=1 fi From 58699fa807dc013b231019f1ba8a39dd3ece0300 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 21 Jun 2023 13:36:01 +0200 Subject: [PATCH 0980/2059] use ICMP echo instead of ICMP timestamp for sqm autorate --- .../root/usr/share/sqm-autorate/cake-autorate_template.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh index 1a9b6105f..b430d82d0 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh @@ -131,7 +131,7 @@ log_file_export_compress=1 # compress log file exports using gzip and append .gz # the firewall mark. # WARNING: no error checking so use at own risk! #ping_extra_args="-B -I ${INTERFACE}" -ping_extra_args="-i ${ul_if}" +ping_extra_args="-i ${ul_if} -e" # a wrapper for ping binary - used as a prefix for the real command # e.g., when using mwan3, it is recommended to set it like this: From 5a9f66a097590f542ff425d99fe5841fffa5fb5c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 22 Jun 2023 07:17:29 +0200 Subject: [PATCH 0981/2059] Update ndisc6 --- ndisc6/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ndisc6/Makefile b/ndisc6/Makefile index 990ec9a75..bb83a4311 100644 --- a/ndisc6/Makefile +++ b/ndisc6/Makefile @@ -1,6 +1,6 @@ # # Copyright (C) 2006-2012 OpenWrt.org -# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2022 Ycarus (Yannick Chabanois) # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -9,12 +9,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ndisc6 -PKG_VERSION:=1.0.3 +PKG_VERSION:=1.0.7 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.bz2 -PKG_SOURCE_URL:=http://deb.debian.org/debian/pool/main/n/ndisc6 -PKG_HASH:=0f41d6caf5f2edc1a12924956ae8b1d372e3b426bd7b11eed7d38bc974eec821 +PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=https://www.remlab.net/files/ndisc6/$(PKG_SOURCE) +PKG_HASH:=edc431d70510d7321a5a39d243de0d0f63846dc9145b3b549c7348cc2bc96609 PKG_INSTALL:=1 From a013fc112c72bc67d980dbab53a0489f6e689fa1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 22 Jun 2023 16:08:56 +0200 Subject: [PATCH 0982/2059] Remove ndisc6 --- ndisc6/Makefile | 99 ------------------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 ndisc6/Makefile diff --git a/ndisc6/Makefile b/ndisc6/Makefile deleted file mode 100644 index bb83a4311..000000000 --- a/ndisc6/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -# -# Copyright (C) 2006-2012 OpenWrt.org -# Copyright (C) 2018-2022 Ycarus (Yannick Chabanois) -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=ndisc6 -PKG_VERSION:=1.0.7 -PKG_RELEASE:=1 - -PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).tar.bz2 -PKG_SOURCE_URL:=https://www.remlab.net/files/ndisc6/$(PKG_SOURCE) -PKG_HASH:=edc431d70510d7321a5a39d243de0d0f63846dc9145b3b549c7348cc2bc96609 - -PKG_INSTALL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/ndisc - SECTION:=ipv6 - CATEGORY:=IPv6 - SUBMENU:=IPv6 discovery tools - TITLE:=IPv6 discovery tools - URL:=http://www.remlab.net/ndisc6/ - DEPENDS:=+libpthread +librt -endef - -define Package/ndisc/description -IPv6 discovery tools -endef - -define Package/ndisc6 - $(call Package/ndisc) - TITLE:=An ICMPv6 neighbour discovery tool -endef - -define Package/ndisc6/description -An ICMPv6 neighbour discovery tools -endef - -define Package/rdisc6 - $(call Package/ndisc) - TITLE:=An ICMPv6 router discovery tool -endef - -define Package/rdisc6/description -An ICMPv6 router discovery tool -endef - -define Package/traceroute6 - $(call Package/ndisc) - TITLE:=An IPv6-based traceroute implementation -endef - -define Package/traceroute6/description -An IPv6-based traceroute implementation -endef - -define Package/rdnssd - $(call Package/ndisc) - TITLE:=DNS server discovery daemon -endef - -define Package/rdnssd/description -A recursive DNS server discovery daemon gathering -information through stateless IPv6 autoconfiguration (RFC5006) -endef - -TARGET_CFLAGS += -std=c99 - -define Package/ndisc6/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ndisc6 $(1)/usr/bin/ -endef - -define Package/rdisc6/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/rdisc6 $(1)/usr/bin/ -endef - -define Package/traceroute6/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/{rl,tcp}traceroute6 $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tracert6 $(1)/usr/bin/ -endef - -define Package/rdnssd/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/rdnssd $(1)/usr/sbin/ -endef - -$(eval $(call BuildPackage,ndisc6)) -$(eval $(call BuildPackage,rdisc6)) -$(eval $(call BuildPackage,traceroute6)) -$(eval $(call BuildPackage,rdnssd)) From ff90fb808f379fd6966d8f9e2481e170d6f86467 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 23 Jun 2023 08:24:59 +0200 Subject: [PATCH 0983/2059] Change omrvpn interface MTU to jumbo frame (at least for test...) --- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 4 +--- openmptcprouter/files/etc/uci-defaults/2020-omr-vpn | 9 +++++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index f746af284..9a8edfc77 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -241,9 +241,7 @@ done uci -q batch <<-EOF >/dev/null set firewall.zone_lan.mtu_fix='1' - set firewall.zone_vpn.mtu_fix='1' -EOF -uci -q batch <<-EOF >/dev/null + set firewall.zone_vpn.mtu_fix='0' set firewall.@include[0].reload='1' commit firewall EOF diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index 75a947d27..28f19bda0 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -12,7 +12,7 @@ if [ "$(uci -q get network.omrvpn)" = "" ]; then set network.omrvpn.leasetime=12h set network.omrvpn.type=tunnel set network.omrvpn.txqueuelen=100 - set network.omrvpn.metric=1200 + set network.omrvpn.metric=9000 commit network EOF fi @@ -146,7 +146,12 @@ if [ "$(uci -q get glorytun-udp.vpn.key)" = "" ] && [ "$(uci -q get glorytun.vpn uci -q commit glorytun-udp fi - +if [ "$(uci -q get network.omrvpn.metric)" = "1200" ]; then + uci -q batch <<-EOF >/dev/null + set network.omrvpn.metric=9000 + commit network + EOF +fi rm -f /tmp/luci-indexcache exit 0 From 41abdb1b0f7028b923c19110ac5e39a1a9eaa024 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Jun 2023 06:17:38 +0200 Subject: [PATCH 0984/2059] Remove rdisc6 dependancy --- luci-app-openmptcprouter/Makefile | 2 +- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/Makefile b/luci-app-openmptcprouter/Makefile index ae4cb6eea..9e1c5938d 100644 --- a/luci-app-openmptcprouter/Makefile +++ b/luci-app-openmptcprouter/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Support for OpenMPTCProuter -LUCI_DEPENDS:=+luci-lib-json +rdisc6 +curl +bind-dig +tracebox +LUCI_DEPENDS:=+luci-lib-json +curl +bind-dig +tracebox PKG_LICENSE:=GPLv3 #include ../luci/luci.mk diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index cd1b585b9..07f8a7835 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -948,6 +948,7 @@ +

    From 046e93f4a67ef6c55cbc84a60a7660674b19225a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 29 Jul 2023 16:19:26 +0200 Subject: [PATCH 1010/2059] Fix init scripts --- luci-app-openmptcprouter/root/etc/init.d/openmptcprouter | 2 +- macvlan/files/etc/init.d/macvlan | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index e74aced38..615f38ff8 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -2,7 +2,7 @@ # Copyright (C) 2018-2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter # Released under GPL 3. See LICENSE for the full terms. -START=5 +START=05 USE_PROCD=1 diff --git a/macvlan/files/etc/init.d/macvlan b/macvlan/files/etc/init.d/macvlan index 6669a9ff2..d4749a7cc 100755 --- a/macvlan/files/etc/init.d/macvlan +++ b/macvlan/files/etc/init.d/macvlan @@ -1,6 +1,6 @@ #!/bin/sh /etc/rc.common -START=4 +START=04 USE_PROCD=1 _setup_macaddr() { From 9ee90e4546354e37daf8d16b6a376d03cab4e6b8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 29 Jul 2023 16:19:56 +0200 Subject: [PATCH 1011/2059] Add kmod-mlx4-core --- openmptcprouter-full/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index c9141b684..a5c25eefe 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -82,7 +82,8 @@ MY_DEPENDS := \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ - (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd + (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd \ + (TARGET_x86||TARGET_x86_64):kmod-mlx4-core # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From 1085ee50d93de74d4dd2748eafe54fb6d19f41f9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 1 Aug 2023 20:54:21 +0200 Subject: [PATCH 1012/2059] Update iperf3 and add MPTCP support --- iperf3/Makefile | 6 +- iperf3/patches/add-MPTCP-support.patch | 208 +++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 iperf3/patches/add-MPTCP-support.patch diff --git a/iperf3/Makefile b/iperf3/Makefile index 4501eede8..f9dea85eb 100644 --- a/iperf3/Makefile +++ b/iperf3/Makefile @@ -8,14 +8,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iperf -PKG_VERSION:=3.12 +PKG_VERSION:=3.14 PKG_RELEASE:=10 PKG_SOURCE:=$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/esnet/iperf/archive/refs/tags/ -PKG_HASH:=e38e0a97b30a97b4355da93467160a20dea10932f6c17473774802e03d61d4a7 +PKG_HASH:=bbafa2c9687f0f7fe00947dc779b83c91663911e22460005c0ad4623797b3dbd -PKG_MAINTAINER:=Felix Fietkau +PKG_MAINTAINER:=Yannick Chabanois PKG_LICENSE:=BSD-3-Clause PKG_BUILD_PARALLEL:=1 diff --git a/iperf3/patches/add-MPTCP-support.patch b/iperf3/patches/add-MPTCP-support.patch new file mode 100644 index 000000000..7dd024657 --- /dev/null +++ b/iperf3/patches/add-MPTCP-support.patch @@ -0,0 +1,208 @@ +From 26b066b9d4e92442d55950689dbd9fd101b429a7 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Mon, 14 Jun 2021 16:13:02 +0200 +Subject: [PATCH] Add MPTCP support with the --multipath flag + +Also available with the short option '-m'. +The MPTCP protocol is really a TCP variant, so this change +does not implement a new 'struct protocol'. Instead it just +extend the TCP support to optionally enable multipath. + +The only required dependency is IPPROTO_MPTCP definition, +which should be provided by the netinet/in.h header. +To keep things simple, just conditionally provide the required +protocol, if the system header does not have it yet +--- + src/iperf.h | 1 + + src/iperf3.1 | 4 ++++ + src/iperf_api.c | 11 ++++++++++- + src/iperf_locale.c | 1 + + src/iperf_tcp.c | 18 +++++++++++++++--- + 5 files changed, 31 insertions(+), 4 deletions(-) + +diff --git a/src/iperf.h b/src/iperf.h +index 3fc91d0c0..e753df944 100644 +--- a/src/iperf.h ++++ b/src/iperf.h +@@ -315,6 +315,7 @@ struct iperf_test + int udp_counters_64bit; /* --use-64-bit-udp-counters */ + int forceflush; /* --forceflush - flushing output at every interval */ + int multisend; ++ int multipath; /* -m option - multi-path variant */ + int repeating_payload; /* --repeating-payload */ + int timestamps; /* --timestamps */ + char *timestamp_format; +diff --git a/src/iperf3.1 b/src/iperf3.1 +index f5eef6eb3..205a8337e 100644 +--- a/src/iperf3.1 ++++ b/src/iperf3.1 +@@ -228,6 +228,10 @@ run in client mode, connecting to the specified server. + By default, a test consists of sending data from the client to the + server, unless the \-R flag is specified. + .TP ++.BR -m ", " --multipath " " ++use multipath variant for the current protocol. This only applies to ++TCP and enables MPTCP usage. ++.TP + .BR --sctp + use SCTP rather than TCP (FreeBSD and Linux) + .TP +diff --git a/src/iperf_api.c b/src/iperf_api.c +index f8f2321ec..bea53e397 100644 +--- a/src/iperf_api.c ++++ b/src/iperf_api.c +@@ -1007,7 +1007,8 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) + {"connect-timeout", required_argument, NULL, OPT_CONNECT_TIMEOUT}, + {"idle-timeout", required_argument, NULL, OPT_IDLE_TIMEOUT}, + {"rcv-timeout", required_argument, NULL, OPT_RCV_TIMEOUT}, + {"snd-timeout", required_argument, NULL, OPT_SND_TIMEOUT}, ++ {"multipath", no_argument, NULL, 'm'}, + {"debug", optional_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} +@@ -1030,7 +1031,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) + char *client_username = NULL, *client_rsa_public_key = NULL, *server_rsa_private_key = NULL; + #endif /* HAVE_SSL */ + +- while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) { ++ while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:mM:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) { + switch (flag) { + case 'p': + portno = atoi(optarg); +@@ -1103,6 +1104,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) + iperf_set_test_role(test, 'c'); + iperf_set_test_server_hostname(test, optarg); + break; ++ case 'm': ++ set_protocol(test, Ptcp); ++ test->multipath = 1; ++ break; + case 'u': + set_protocol(test, Pudp); + client_flag = 1; +@@ -2000,6 +2005,8 @@ send_parameters(struct iperf_test *test) + cJSON_AddTrueToObject(j, "reverse"); + if (test->bidirectional) + cJSON_AddTrueToObject(j, "bidirectional"); ++ if (test->multipath) ++ cJSON_AddTrueToObject(j, "multipath"); + if (test->settings->socket_bufsize) + cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize); + if (test->settings->blksize) +@@ -2112,6 +2119,8 @@ get_parameters(struct iperf_test *test) + iperf_set_test_reverse(test, 1); + if ((j_p = cJSON_GetObjectItem(j, "bidirectional")) != NULL) + iperf_set_test_bidirectional(test, 1); ++ if ((j_p = cJSON_GetObjectItem(j, "multipath")) != NULL) ++ test->multipath = 1; + if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL) + test->settings->socket_bufsize = j_p->valueint; + if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL) +diff --git a/src/iperf_locale.c b/src/iperf_locale.c +index e1e9dc5b6..a70bd73b9 100644 +--- a/src/iperf_locale.c ++++ b/src/iperf_locale.c +@@ -146,6 +146,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n" + " --nstreams # number of SCTP streams\n" + #endif /* HAVE_SCTP_H */ + " -u, --udp use UDP rather than TCP\n" ++ " -m, --multipath use MPTCP rather than plain TCP\n" + " --connect-timeout # timeout for control connection setup (ms)\n" + " -b, --bitrate #[KMG][/#] target bitrate in bits/sec (0 for unlimited)\n" + " (default %d Mbit/sec for UDP, unlimited for TCP)\n" +--- a/src/iperf_tcp.c 2023-07-07 23:47:41.000000000 +0200 ++++ b/src/iperf_tcp.c 2023-08-01 14:53:57.832072168 +0200 +@@ -44,6 +44,10 @@ + #include "net.h" + #include "cjson.h" + ++#ifndef IPPROTO_MPTCP ++#define IPPROTO_MPTCP 262 ++#endif ++ + #if defined(HAVE_FLOWLABEL) + #include "flowlabel.h" + #endif /* HAVE_FLOWLABEL */ +@@ -154,6 +158,7 @@ + socklen_t optlen; + int saved_errno; + int rcvbuf_actual, sndbuf_actual; ++ int protocol = 0; + + s = test->listener; + +@@ -166,7 +171,7 @@ + * + * It's not clear whether this is a requirement or a convenience. + */ +- if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) { ++ if (test->multipath || test->no_delay || test->settings->mss || test->settings->socket_bufsize) { + struct addrinfo hints, *res; + char portstr[6]; + +@@ -194,7 +199,10 @@ + return -1; + } + +- if ((s = socket(res->ai_family, SOCK_STREAM, 0)) < 0) { ++ if (test->multipath) ++ protocol = IPPROTO_MPTCP; ++ ++ if ((s = socket(res->ai_family, SOCK_STREAM, protocol)) < 0) { + freeaddrinfo(res); + i_errno = IESTREAMLISTEN; + return -1; +@@ -374,8 +382,12 @@ + socklen_t optlen; + int saved_errno; + int rcvbuf_actual, sndbuf_actual; ++ int protocol = 0; ++ ++ if (test->multipath) ++ protocol = IPPROTO_MPTCP; + +- s = create_socket(test->settings->domain, SOCK_STREAM, test->bind_address, test->bind_dev, test->bind_port, test->server_hostname, test->server_port, &server_res); ++ s = create_socket(test->settings->domain, SOCK_STREAM, test->bind_address, test->bind_dev, test->bind_port, test->server_hostname, test->server_port, &server_res, protocol); + if (s < 0) { + i_errno = IESTREAMCONNECT; + return -1; +--- a/src/net.c 2023-08-01 14:54:14.175802546 +0200 ++++ b/src/net.c 2023-08-01 14:54:40.831362812 +0200 +@@ -121,7 +121,7 @@ + + /* create a socket */ + int +-create_socket(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, struct addrinfo **server_res_out) ++create_socket(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, struct addrinfo **server_res_out, int protocol) + { + struct addrinfo hints, *local_res = NULL, *server_res = NULL; + int s, saved_errno; +@@ -145,7 +145,7 @@ + return -1; + } + +- s = socket(server_res->ai_family, proto, 0); ++ s = socket(server_res->ai_family, proto, protocol); + if (s < 0) { + if (local) + freeaddrinfo(local_res); +@@ -235,7 +235,7 @@ + struct addrinfo *server_res = NULL; + int s, saved_errno; + +- s = create_socket(domain, proto, local, bind_dev, local_port, server, port, &server_res); ++ s = create_socket(domain, proto, local, bind_dev, local_port, server, port, &server_res, 0); + if (s < 0) { + return -1; + } +--- a/src/net.h 2023-08-01 15:01:58.208159540 +0200 ++++ b/src/net.h 2023-08-01 15:00:46.521337885 +0200 +@@ -28,7 +28,7 @@ + #define __NET_H + + int timeout_connect(int s, const struct sockaddr *name, socklen_t namelen, int timeout); +-int create_socket(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, struct addrinfo **server_res_out); ++int create_socket(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, struct addrinfo **server_res_out, int protocol); + int netdial(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, int timeout); + int netannounce(int domain, int proto, const char *local, const char *bind_dev, int port); + int Nread(int fd, char *buf, size_t count, int prot); From 1cff3b1faa530b77dd52441685f912c0552cb5ce Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Aug 2023 12:51:03 +0200 Subject: [PATCH 1013/2059] Update v2ray and add kernel 6.1 MPTCP aggregation support --- golang-protobuf/Makefile | 6 +- protobuf/Makefile | 10 +- v2ray-core/Makefile | 9 +- v2ray-core/files/etc/init.d/v2ray | 27 +- v2ray-core/patches/add-mptcp-support.patch | 2923 ++++++++++++++++++++ 5 files changed, 2952 insertions(+), 23 deletions(-) create mode 100644 v2ray-core/patches/add-mptcp-support.patch diff --git a/golang-protobuf/Makefile b/golang-protobuf/Makefile index 04cc930f4..58acdc042 100644 --- a/golang-protobuf/Makefile +++ b/golang-protobuf/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2019 Ycarus (Yannick Chabanois) +# Copyright (C) 2019-2023 Ycarus (Yannick Chabanois) # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -12,8 +12,8 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/golang/protobuf.git -PKG_SOURCE_VERSION:=347cf4a86c1cb8d262994d8ef5924d4576c5b331 -PKG_SOURCE_DATE:=20190109 +PKG_SOURCE_VERSION:=5d5e8c018a13017f9d5b8bf4fad64aaa42a87308 +PKG_SOURCE_DATE:=20210916 PKG_LICENSE:=BSD-3-Clause PKG_LICENSE_FILES:=LICENSE diff --git a/protobuf/Makefile b/protobuf/Makefile index cc314bbea..03320781f 100644 --- a/protobuf/Makefile +++ b/protobuf/Makefile @@ -1,21 +1,23 @@ # # Copyright (C) 2007-2015 OpenWrt.org +# Copyright (C) 2017-2023 Yannick Chabanois for OpenMPTCProuter # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # - +# Original ebuild from Ken Keys +# Updated by Yannick Chabanois for OpenMPTCProuter include $(TOPDIR)/rules.mk PKG_NAME:=protobuf -PKG_VERSION:=3.14.0 +PKG_VERSION:=3.17.3 PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-cpp-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/google/protobuf/releases/download/v$(PKG_VERSION) -PKG_HASH:=50ec5a07c0c55d4ec536dd49021f2e194a26bfdbc531d03d1e9d4d3e27175659 +PKG_HASH:=51cec99f108b83422b7af1170afd7aeb2dd77d2bcbb7b6bad1f92509e9ccf8cb -PKG_MAINTAINER:=Ken Keys +PKG_MAINTAINER:=Yannick Chabanois PKG_LICENSE:=BSD-3-Clause PKG_LICENSE_FILES:=LICENSE PKG_CPE_ID:=cpe:/a:google:protobuf diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 113c70f2e..e2195cd56 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -8,9 +8,12 @@ PKG_NAME:=v2ray-core PKG_VERSION:=5.7.0 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=599fcd264537e39178b6008a11af68816dfd1609e19a9cf8adc8b2a4240ee370 +#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +#PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)? +#PKG_HASH:=599fcd264537e39178b6008a11af68816dfd1609e19a9cf8adc8b2a4240ee370 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core.git +PKG_SOURCE_VERSION:=d58649764e3afa52234ada9a28b7ae79577a23a9 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index d704c337f..654858c19 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -51,6 +51,17 @@ _err() { _log "err" $@ } +version_over_5_4() { + MAJOR_VERSION=$(uname -r | awk -F '.' '{print $1}') + MINOR_VERSION=$(uname -r | awk -F '.' '{print $2}') + if [ $MAJOR_VERSION -ge 5 ] && [ $MINOR_VERSION -gt 13 ] || [ $MAJOR_VERSION -gt 5 ] ; then + return 0 + else + return 1 + fi +} + + get_value_from_json() { local json="$1" local key="$2" @@ -1295,6 +1306,9 @@ add_inbound_setting() { test -n "$ss_sockopt_tproxy" && \ json_add_string "tproxy" "$ss_sockopt_tproxy" # fi + if version_over_5_4; then + json_add_boolean "mptcp" "1" + fi json_close_object # sockopt @@ -1944,16 +1958,6 @@ clear_transparent_proxy() { fi } -version_over_5_4() { - MAJOR_VERSION=$(uname -r | awk -F '.' '{print $1}') - MINOR_VERSION=$(uname -r | awk -F '.' '{print $2}') - if [ $MAJOR_VERSION -ge 5 ] && [ $MINOR_VERSION -gt 13 ] || [ $MAJOR_VERSION -gt 5 ] ; then - return 0 - else - return 1 - fi -} - start_instance() { local section="$1" @@ -2068,9 +2072,6 @@ start_instance() { PROG="$NAME.$section" TRANSPARENT_PROXY_EXPECTED=1 - if version_over_5_4; then - PROG="mptcpize run ${PROG}" - fi procd_open_instance "$PROG" procd_set_param command "$v2ray_file" procd_append_param command run diff --git a/v2ray-core/patches/add-mptcp-support.patch b/v2ray-core/patches/add-mptcp-support.patch new file mode 100644 index 000000000..e03a247a7 --- /dev/null +++ b/v2ray-core/patches/add-mptcp-support.patch @@ -0,0 +1,2923 @@ +From 036cf19338137e3919b4c5d63b684ef3987ba253 Mon Sep 17 00:00:00 2001 +From: Luo Chongjun +Date: Sat, 29 Jul 2023 14:56:58 +0800 +Subject: [PATCH] support mptcp + +--- +diff --git a/go.mod b/go.mod +index e3881e5aa..73599d927 100644 +--- a/go.mod ++++ b/go.mod +@@ -16,7 +16,7 @@ require ( + github.com/mustafaturan/bus v1.0.2 + github.com/pelletier/go-toml v1.9.5 + github.com/pires/go-proxyproto v0.7.0 +- github.com/quic-go/quic-go v0.36.2 ++ github.com/quic-go/quic-go v0.37.0 + github.com/refraction-networking/utls v1.3.3 + github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb + github.com/stretchr/testify v1.8.4 +@@ -65,8 +65,7 @@ require ( + github.com/pion/sctp v1.8.7 // indirect + github.com/pion/transport/v2 v2.2.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect +- github.com/quic-go/qtls-go1-19 v0.3.2 // indirect +- github.com/quic-go/qtls-go1-20 v0.2.2 // indirect ++ github.com/quic-go/qtls-go1-20 v0.3.0 // indirect + github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect + github.com/secure-io/siv-go v0.0.0-20180922214919-5ff40651e2c4 // indirect + github.com/xtaci/smux v1.5.24 // indirect +diff --git a/go.sum b/go.sum +index 0ce21101c..63298b0c1 100644 +--- a/go.sum ++++ b/go.sum +@@ -260,12 +260,10 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 + github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= + github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= + github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +-github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= +-github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +-github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= +-github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +-github.com/quic-go/quic-go v0.36.2 h1:ZX/UNQ4gvpCv2RmwdbA6lrRjF6EBm5yZ7TMoT4NQVrA= +-github.com/quic-go/quic-go v0.36.2/go.mod h1:zPetvwDlILVxt15n3hr3Gf/I3mDf7LpLKPhR4Ez0AZQ= ++github.com/quic-go/qtls-go1-20 v0.3.0 h1:NrCXmDl8BddZwO67vlvEpBTwT89bJfKYygxv4HQvuDk= ++github.com/quic-go/qtls-go1-20 v0.3.0/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= ++github.com/quic-go/quic-go v0.37.0 h1:wf/Ym2yeWi98oQn4ahiBSqdnaXVxNQGj2oBQFgiVChc= ++github.com/quic-go/quic-go v0.37.0/go.mod h1:XtCUOCALTTWbPyd0IxFfHf6h0sEMubRFvEYHl3QxKw8= + github.com/refraction-networking/utls v1.3.3 h1:f/TBLX7KBciRyFH3bwupp+CE4fzoYKCirhdRcC490sw= + github.com/refraction-networking/utls v1.3.3/go.mod h1:DlecWW1LMlMJu+9qpzzQqdHDT/C2LAe03EdpLUz/RL8= + github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= +diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go +index 314664a78..96bb0eca1 100644 +--- a/transport/internet/system_dialer.go ++++ b/transport/internet/system_dialer.go +@@ -72,6 +72,12 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne + LocalAddr: resolveSrcAddr(dest.Network, src), + KeepAlive: goStdKeepAlive, + } ++ if dialer.MultipathTCP() { ++ newError("Outbound MultipathTCP is enable").WriteToLog(session.ExportIDToError(ctx)) ++ } else { ++ newError("Outbound MultipathTCP is disable,we are enable it").WriteToLog(session.ExportIDToError(ctx)) ++ dialer.SetMultipathTCP(true) // 主动启用mptcp ++ } + + if sockopt != nil || len(d.controllers) > 0 { + dialer.Control = func(network, address string, c syscall.RawConn) error { +diff --git a/transport/internet/system_listener.go b/transport/internet/system_listener.go +index 5ddb4814e..74e48130a 100644 +--- a/transport/internet/system_listener.go ++++ b/transport/internet/system_listener.go +@@ -45,6 +45,12 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S + var l net.Listener + var err error + var network, address string ++ if lc.MultipathTCP() { ++ newError("MultipathTCP is enable").WriteToLog(session.ExportIDToError(ctx)) ++ } else { ++ newError("MultipathTCP is disable,we are enable it").WriteToLog(session.ExportIDToError(ctx)) ++ lc.SetMultipathTCP(true) // 主动启用mptcp ++ } + switch addr := addr.(type) { + case *net.TCPAddr: + network = addr.Network() +diff --git a/app/browserforwarder/config.pb.go b/app/browserforwarder/config.pb.go +index 912ba0f5c..f3b3ef659 100644 +--- a/app/browserforwarder/config.pb.go ++++ b/app/browserforwarder/config.pb.go +@@ -80,22 +80,22 @@ var file_app_browserforwarder_config_proto_rawDesc = []byte{ + 0x61, 0x70, 0x70, 0x2e, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x65, 0x72, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x66, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x62, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, + 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x50, 0x6f, +- 0x72, 0x74, 0x3a, 0x1a, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, +- 0x65, 0x82, 0xb5, 0x18, 0x09, 0x12, 0x07, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x42, 0x7e, +- 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x77, +- 0x61, 0x72, 0x64, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, +- 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, +- 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x62, 0x72, 0x6f, 0x77, +- 0x73, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0xaa, 0x02, 0x1f, 0x56, +- 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x42, 0x72, +- 0x6f, 0x77, 0x73, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x62, 0x06, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x72, 0x74, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x12, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, ++ 0x65, 0x12, 0x07, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, ++ 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, ++ 0x2e, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, ++ 0x72, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, ++ 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, ++ 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x66, ++ 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, ++ 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x65, ++ 0x72, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x33, + } + + var ( +diff --git a/app/commander/config.pb.go b/app/commander/config.pb.go +index 221b42621..bac9fa6bf 100644 +--- a/app/commander/config.pb.go ++++ b/app/commander/config.pb.go +@@ -184,23 +184,22 @@ var file_app_commander_config_proto_rawDesc = []byte{ + 0x2e, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, +- 0x35, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x3a, 0x21, 0x82, 0xb5, 0x18, 0x0d, 0x0a, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x73, +- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x0c, 0x12, 0x0a, 0x72, 0x65, 0x66, 0x6c, +- 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, +- 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, +- 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, +- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, +- 0x3a, 0x1c, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, +- 0xb5, 0x18, 0x0b, 0x12, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x42, 0x69, +- 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x01, +- 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, +- 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, +- 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0xaa, 0x02, +- 0x18, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, +- 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x33, ++ 0x31, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x3a, 0x1d, 0x82, 0xb5, 0x18, 0x19, 0x0a, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x73, ++ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x0a, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, ++ 0x6f, 0x6e, 0x22, 0x52, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, ++ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, ++ 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, ++ 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x18, 0x82, 0xb5, ++ 0x18, 0x14, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x09, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x42, 0x69, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0xaa, 0x02, 0x18, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, ++ 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, ++ 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/dns/config.pb.go b/app/dns/config.pb.go +index a32c3cd54..beae96661 100644 +--- a/app/dns/config.pb.go ++++ b/app/dns/config.pb.go +@@ -1332,7 +1326,7 @@ var file_app_dns_config_proto_rawDesc = []byte{ + 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, +- 0x08, 0x07, 0x10, 0x08, 0x22, 0xed, 0x05, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, ++ 0x08, 0x07, 0x10, 0x08, 0x22, 0xe9, 0x05, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, + 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, + 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, +@@ -1376,102 +1370,102 @@ var file_app_dns_config_proto_rawDesc = []byte{ + 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, + 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, +- 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x09, +- 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x05, 0x12, 0x03, 0x64, +- 0x6e, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, +- 0x08, 0x07, 0x10, 0x08, 0x22, 0xa2, 0x01, 0x0a, 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, +- 0x69, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3a, +- 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, +- 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, +- 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, +- 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, +- 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, +- 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, +- 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, +- 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, +- 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0xc8, 0x07, 0x0a, 0x14, 0x53, 0x69, +- 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, +- 0x65, 0x72, 0x12, 0x39, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, +- 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, +- 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, +- 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, +- 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, +- 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x66, 0x0a, 0x12, +- 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, +- 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x53, 0x69, +- 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, +- 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, +- 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, +- 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, +- 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, +- 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, +- 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x5c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, +- 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, +- 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, +- 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, +- 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, +- 0x6c, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x61, 0x6b, 0x65, 0x5f, 0x64, 0x6e, 0x73, 0x18, +- 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +- 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, +- 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x75, +- 0x6c, 0x74, 0x69, 0x52, 0x07, 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0c, +- 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, +- 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, +- 0x62, 0x61, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, +- 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, +- 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, +- 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, +- 0x00, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, +- 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, +- 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, +- 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x01, +- 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, +- 0x01, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, +- 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, +- 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, +- 0x65, 0x67, 0x79, 0x48, 0x02, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, +- 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x1a, 0x64, 0x0a, 0x0e, 0x50, 0x72, +- 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x04, +- 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, +- 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, +- 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, +- 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, +- 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, +- 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, +- 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, +- 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x71, 0x75, 0x65, +- 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x11, 0x0a, 0x0f, 0x5f, +- 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x14, +- 0x0a, 0x12, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, +- 0x74, 0x65, 0x67, 0x79, 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, +- 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, +- 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, +- 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, +- 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x35, 0x0a, 0x0d, 0x51, +- 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, +- 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, +- 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, +- 0x10, 0x02, 0x2a, 0x34, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, +- 0x65, 0x67, 0x79, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x6e, 0x61, 0x62, +- 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x69, +- 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x01, 0x2a, 0x45, 0x0a, 0x10, 0x46, 0x61, 0x6c, 0x6c, +- 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0b, 0x0a, 0x07, +- 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x69, 0x73, +- 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, +- 0x6c, 0x65, 0x64, 0x49, 0x66, 0x41, 0x6e, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x42, +- 0x57, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, +- 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, +- 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, +- 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x12, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, +- 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x3a, 0x12, 0x82, 0xb5, 0x18, 0x0e, ++ 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x03, 0x64, 0x6e, 0x73, 0x4a, 0x04, ++ 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, ++ 0x22, 0xa2, 0x01, 0x0a, 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x48, ++ 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, ++ 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, ++ 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, ++ 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, ++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, ++ 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, ++ 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, ++ 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, ++ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0xc8, 0x07, 0x0a, 0x14, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, ++ 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, ++ 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, ++ 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, ++ 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, ++ 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, ++ 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, ++ 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x66, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, ++ 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, ++ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, ++ 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, ++ 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, ++ 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, ++ 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, ++ 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, ++ 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, ++ 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, ++ 0x70, 0x12, 0x5c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, ++ 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x53, ++ 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, ++ 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, ++ 0x47, 0x0a, 0x08, 0x66, 0x61, 0x6b, 0x65, 0x5f, 0x64, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, ++ 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, ++ 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x46, ++ 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x52, ++ 0x07, 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, ++ 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, ++ 0x18, 0x01, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, ++ 0x12, 0x4d, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, ++ 0x67, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, ++ 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x00, 0x52, 0x0d, 0x71, ++ 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, ++ 0x4d, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, ++ 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, ++ 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x61, 0x63, ++ 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x01, 0x52, 0x0d, 0x63, 0x61, ++ 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x56, ++ 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, ++ 0x65, 0x67, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, ++ 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, ++ 0x02, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, ++ 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x1a, 0x64, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, ++ 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, ++ 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, ++ 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, ++ 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, ++ 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, ++ 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, ++ 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, ++ 0x73, 0x69, 0x7a, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, ++ 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x61, 0x63, 0x68, ++ 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x66, ++ 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, ++ 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, ++ 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, ++ 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, ++ 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, ++ 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, ++ 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, ++ 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, ++ 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x2a, 0x34, ++ 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, ++ 0x10, 0x0a, 0x0c, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, ++ 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, ++ 0x65, 0x64, 0x10, 0x01, 0x2a, 0x45, 0x0a, 0x10, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, ++ 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, ++ 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, ++ 0x64, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x49, ++ 0x66, 0x41, 0x6e, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x42, 0x57, 0x0a, 0x16, 0x63, ++ 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, ++ 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, ++ 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, ++ 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, ++ 0x02, 0x12, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, ++ 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/dns/fakedns/fakedns.pb.go b/app/dns/fakedns/fakedns.pb.go +index 870a44fbd..759743ba1 100644 +--- a/app/dns/fakedns/fakedns.pb.go ++++ b/app/dns/fakedns/fakedns.pb.go +@@ -125,28 +125,27 @@ var file_app_dns_fakedns_fakedns_proto_rawDesc = []byte{ + 0x1a, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x1a, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, +- 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5c, 0x0a, ++ 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x58, 0x0a, + 0x0b, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, + 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, + 0x70, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x3a, +- 0x1a, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, +- 0x18, 0x09, 0x12, 0x07, 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x22, 0x72, 0x0a, 0x10, 0x46, +- 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x12, +- 0x3d, 0x0a, 0x05, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, +- 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, +- 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, +- 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x05, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x3a, 0x1f, +- 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, +- 0x0e, 0x12, 0x0c, 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x42, +- 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, +- 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, +- 0x73, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, +- 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, +- 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, +- 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, +- 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, +- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x16, 0x82, 0xb5, 0x18, 0x12, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x07, ++ 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x46, 0x61, 0x6b, 0x65, 0x44, ++ 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x12, 0x3d, 0x0a, 0x05, 0x70, ++ 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x76, 0x32, 0x72, ++ 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, ++ 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, ++ 0x6f, 0x6f, 0x6c, 0x52, 0x05, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x3a, 0x1b, 0x82, 0xb5, 0x18, 0x17, ++ 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x0c, 0x66, 0x61, 0x6b, 0x65, 0x44, ++ 0x6e, 0x73, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x42, 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, ++ 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, ++ 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, ++ 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x1a, 0x56, 0x32, ++ 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, ++ 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/instman/command/command.pb.go b/app/instman/command/command.pb.go +index 6c507470c..ecdb7dfe0 100644 +--- a/app/instman/command/command.pb.go ++++ b/app/instman/command/command.pb.go +@@ -349,41 +349,41 @@ var file_app_instman_command_command_proto_rawDesc = []byte{ + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x13, 0x0a, + 0x11, 0x53, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, +- 0x73, 0x70, 0x22, 0x28, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1e, 0x82, 0xb5, +- 0x18, 0x0d, 0x0a, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, +- 0xb5, 0x18, 0x09, 0x12, 0x07, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x32, 0xf4, 0x02, 0x0a, +- 0x19, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, +- 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x4c, 0x69, +- 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x76, 0x32, 0x72, ++ 0x73, 0x70, 0x22, 0x24, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1a, 0x82, 0xb5, ++ 0x18, 0x16, 0x0a, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, ++ 0x07, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x32, 0xf4, 0x02, 0x0a, 0x19, 0x49, 0x6e, 0x73, ++ 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, ++ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, ++ 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, ++ 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, ++ 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x30, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, ++ 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, ++ 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x6e, 0x0a, 0x0b, 0x41, 0x64, 0x64, ++ 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2e, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, ++ 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x73, ++ 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x2f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, ++ 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x73, ++ 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x74, 0x0a, 0x0d, 0x53, 0x74, 0x61, ++ 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x30, 0x2e, 0x76, 0x32, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, 0x74, +- 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, +- 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x30, 0x2e, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, +- 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, +- 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x6e, 0x0a, +- 0x0b, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2e, 0x2e, 0x76, ++ 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x72, ++ 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x31, 0x2e, 0x76, + 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, +- 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, +- 0x64, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x2f, 0x2e, 0x76, +- 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, +- 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, +- 0x64, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x74, 0x0a, +- 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x30, +- 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, +- 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, +- 0x53, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, +- 0x1a, 0x31, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, +- 0x70, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, +- 0x64, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, +- 0x65, 0x73, 0x70, 0x42, 0x7f, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, +- 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, +- 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, +- 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, +- 0x61, 0x70, 0x70, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, +- 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x1e, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, +- 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, +- 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x74, ++ 0x61, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x42, ++ 0x7f, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, ++ 0x79, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, ++ 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, ++ 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, ++ 0x02, 0x1e, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, ++ 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, ++ 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/instman/command/command_grpc.pb.go b/app/instman/command/command_grpc.pb.go +index 5d6852f5b..9574a2826 100644 +--- a/app/instman/command/command_grpc.pb.go ++++ b/app/instman/command/command_grpc.pb.go +@@ -12,6 +12,12 @@ import ( + // Requires gRPC-Go v1.32.0 or later. + const _ = grpc.SupportPackageIsVersion7 + ++const ( ++ InstanceManagementService_ListInstance_FullMethodName = "/v2ray.core.app.instman.command.InstanceManagementService/ListInstance" ++ InstanceManagementService_AddInstance_FullMethodName = "/v2ray.core.app.instman.command.InstanceManagementService/AddInstance" ++ InstanceManagementService_StartInstance_FullMethodName = "/v2ray.core.app.instman.command.InstanceManagementService/StartInstance" ++) ++ + // InstanceManagementServiceClient is the client API for InstanceManagementService service. + // + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +@@ -31,7 +37,7 @@ func NewInstanceManagementServiceClient(cc grpc.ClientConnInterface) InstanceMan + + func (c *instanceManagementServiceClient) ListInstance(ctx context.Context, in *ListInstanceReq, opts ...grpc.CallOption) (*ListInstanceResp, error) { + out := new(ListInstanceResp) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.instman.command.InstanceManagementService/ListInstance", in, out, opts...) ++ err := c.cc.Invoke(ctx, InstanceManagementService_ListInstance_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -40,7 +46,7 @@ func (c *instanceManagementServiceClient) ListInstance(ctx context.Context, in * + + func (c *instanceManagementServiceClient) AddInstance(ctx context.Context, in *AddInstanceReq, opts ...grpc.CallOption) (*AddInstanceResp, error) { + out := new(AddInstanceResp) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.instman.command.InstanceManagementService/AddInstance", in, out, opts...) ++ err := c.cc.Invoke(ctx, InstanceManagementService_AddInstance_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -49,7 +55,7 @@ func (c *instanceManagementServiceClient) AddInstance(ctx context.Context, in *A + + func (c *instanceManagementServiceClient) StartInstance(ctx context.Context, in *StartInstanceReq, opts ...grpc.CallOption) (*StartInstanceResp, error) { + out := new(StartInstanceResp) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.instman.command.InstanceManagementService/StartInstance", in, out, opts...) ++ err := c.cc.Invoke(ctx, InstanceManagementService_StartInstance_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -103,7 +109,7 @@ func _InstanceManagementService_ListInstance_Handler(srv interface{}, ctx contex + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.instman.command.InstanceManagementService/ListInstance", ++ FullMethod: InstanceManagementService_ListInstance_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InstanceManagementServiceServer).ListInstance(ctx, req.(*ListInstanceReq)) +@@ -121,7 +127,7 @@ func _InstanceManagementService_AddInstance_Handler(srv interface{}, ctx context + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.instman.command.InstanceManagementService/AddInstance", ++ FullMethod: InstanceManagementService_AddInstance_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InstanceManagementServiceServer).AddInstance(ctx, req.(*AddInstanceReq)) +@@ -139,7 +145,7 @@ func _InstanceManagementService_StartInstance_Handler(srv interface{}, ctx conte + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.instman.command.InstanceManagementService/StartInstance", ++ FullMethod: InstanceManagementService_StartInstance_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InstanceManagementServiceServer).StartInstance(ctx, req.(*StartInstanceReq)) +diff --git a/app/instman/config.pb.go b/app/instman/config.pb.go +index 10451e44b..dccbc7a0d 100644 +--- a/app/instman/config.pb.go ++++ b/app/instman/config.pb.go +@@ -61,16 +61,16 @@ var file_app_instman_config_proto_rawDesc = []byte{ + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, + 0x61, 0x6e, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x24, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1a, +- 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, +- 0x09, 0x12, 0x07, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x42, 0x63, 0x0a, 0x1a, 0x63, 0x6f, +- 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, +- 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, +- 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x69, +- 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x16, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, +- 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x62, +- 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x20, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x16, ++ 0x82, 0xb5, 0x18, 0x12, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x07, 0x69, ++ 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x42, 0x63, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x69, 0x6e, 0x73, ++ 0x74, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, ++ 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x6d, ++ 0x61, 0x6e, 0xaa, 0x02, 0x16, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, ++ 0x41, 0x70, 0x70, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/log/command/config_grpc.pb.go b/app/log/command/config_grpc.pb.go +index 24a0fe6ed..f1830f1ac 100644 +--- a/app/log/command/config_grpc.pb.go ++++ b/app/log/command/config_grpc.pb.go +@@ -12,6 +12,11 @@ import ( + // Requires gRPC-Go v1.32.0 or later. + const _ = grpc.SupportPackageIsVersion7 + ++const ( ++ LoggerService_RestartLogger_FullMethodName = "/v2ray.core.app.log.command.LoggerService/RestartLogger" ++ LoggerService_FollowLog_FullMethodName = "/v2ray.core.app.log.command.LoggerService/FollowLog" ++) ++ + // LoggerServiceClient is the client API for LoggerService service. + // + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +@@ -31,7 +36,7 @@ func NewLoggerServiceClient(cc grpc.ClientConnInterface) LoggerServiceClient { + + func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLoggerRequest, opts ...grpc.CallOption) (*RestartLoggerResponse, error) { + out := new(RestartLoggerResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.log.command.LoggerService/RestartLogger", in, out, opts...) ++ err := c.cc.Invoke(ctx, LoggerService_RestartLogger_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -39,7 +44,7 @@ func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLogg + } + + func (c *loggerServiceClient) FollowLog(ctx context.Context, in *FollowLogRequest, opts ...grpc.CallOption) (LoggerService_FollowLogClient, error) { +- stream, err := c.cc.NewStream(ctx, &LoggerService_ServiceDesc.Streams[0], "/v2ray.core.app.log.command.LoggerService/FollowLog", opts...) ++ stream, err := c.cc.NewStream(ctx, &LoggerService_ServiceDesc.Streams[0], LoggerService_FollowLog_FullMethodName, opts...) + if err != nil { + return nil, err + } +@@ -113,7 +118,7 @@ func _LoggerService_RestartLogger_Handler(srv interface{}, ctx context.Context, + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.log.command.LoggerService/RestartLogger", ++ FullMethod: LoggerService_RestartLogger_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(LoggerServiceServer).RestartLogger(ctx, req.(*RestartLoggerRequest)) +diff --git a/app/log/config.pb.go b/app/log/config.pb.go +index aac56a4f3..aab3a40dd 100644 +--- a/app/log/config.pb.go ++++ b/app/log/config.pb.go +@@ -204,7 +204,7 @@ var file_app_log_config_proto_rawDesc = []byte{ + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, + 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, +- 0x61, 0x74, 0x68, 0x22, 0xb8, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, ++ 0x61, 0x74, 0x68, 0x22, 0xb4, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, + 0x6f, 0x67, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, +@@ -212,20 +212,20 @@ var file_app_log_config_proto_rawDesc = []byte{ + 0x63, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, + 0x4c, 0x6f, 0x67, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +- 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, +- 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x05, 0x12, 0x03, 0x6c, 0x6f, 0x67, +- 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, +- 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x2a, 0x35, +- 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, +- 0x65, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, +- 0x12, 0x08, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, +- 0x65, 0x6e, 0x74, 0x10, 0x03, 0x42, 0x57, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x50, +- 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, +- 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, +- 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x12, 0x56, 0x32, 0x52, 0x61, +- 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x3a, 0x12, 0x82, 0xb5, 0x18, 0x0e, 0x0a, 0x07, ++ 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x03, 0x6c, 0x6f, 0x67, 0x4a, 0x04, 0x08, 0x01, ++ 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, ++ 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x2a, 0x35, 0x0a, 0x07, 0x4c, 0x6f, ++ 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, ++ 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, ++ 0x46, 0x69, 0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x10, ++ 0x03, 0x42, 0x57, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x50, 0x01, 0x5a, 0x26, 0x67, ++ 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, ++ 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, ++ 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x12, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, ++ 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x33, + } + + var ( +diff --git a/app/observatory/burst/config.pb.go b/app/observatory/burst/config.pb.go +index e6c988cdf..9a751fa95 100644 +--- a/app/observatory/burst/config.pb.go ++++ b/app/observatory/burst/config.pb.go +@@ -165,7 +165,7 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{ + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, + 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, +- 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xad, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, ++ 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa9, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x53, +@@ -174,29 +174,29 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{ + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, + 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x3a, 0x23, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, +- 0x63, 0x65, 0x82, 0xb5, 0x18, 0x12, 0x12, 0x10, 0x62, 0x75, 0x72, 0x73, 0x74, 0x4f, 0x62, 0x73, +- 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x22, 0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, +- 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, +- 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, +- 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, +- 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, +- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, +- 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, +- 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, +- 0x24, 0x0a, 0x0d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, +- 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, +- 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, +- 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, +- 0x81, 0x01, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +- 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, +- 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, +- 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, +- 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x62, 0x75, 0x72, 0x73, 0x74, +- 0xaa, 0x02, 0x20, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, +- 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x42, 0x75, +- 0x72, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x66, 0x69, 0x67, 0x3a, 0x1f, 0x82, 0xb5, 0x18, 0x1b, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, ++ 0x63, 0x65, 0x12, 0x10, 0x62, 0x75, 0x72, 0x73, 0x74, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, ++ 0x74, 0x6f, 0x72, 0x79, 0x22, 0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, ++ 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, ++ 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, ++ 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, ++ 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, ++ 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, ++ 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, ++ 0x03, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x73, ++ 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, ++ 0x28, 0x05, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, ++ 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, ++ 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x81, 0x01, 0x0a, 0x24, ++ 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, ++ 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, ++ 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, ++ 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, ++ 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x62, 0x75, 0x72, 0x73, 0x74, 0xaa, 0x02, 0x20, 0x56, ++ 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, ++ 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x42, 0x75, 0x72, 0x73, 0x74, 0x62, ++ 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/observatory/command/command_grpc.pb.go b/app/observatory/command/command_grpc.pb.go +index 58bd2b5df..d1262641c 100644 +--- a/app/observatory/command/command_grpc.pb.go ++++ b/app/observatory/command/command_grpc.pb.go +@@ -12,6 +12,10 @@ import ( + // Requires gRPC-Go v1.32.0 or later. + const _ = grpc.SupportPackageIsVersion7 + ++const ( ++ ObservatoryService_GetOutboundStatus_FullMethodName = "/v2ray.core.app.observatory.command.ObservatoryService/GetOutboundStatus" ++) ++ + // ObservatoryServiceClient is the client API for ObservatoryService service. + // + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +@@ -29,7 +33,7 @@ func NewObservatoryServiceClient(cc grpc.ClientConnInterface) ObservatoryService + + func (c *observatoryServiceClient) GetOutboundStatus(ctx context.Context, in *GetOutboundStatusRequest, opts ...grpc.CallOption) (*GetOutboundStatusResponse, error) { + out := new(GetOutboundStatusResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.observatory.command.ObservatoryService/GetOutboundStatus", in, out, opts...) ++ err := c.cc.Invoke(ctx, ObservatoryService_GetOutboundStatus_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -74,7 +78,7 @@ func _ObservatoryService_GetOutboundStatus_Handler(srv interface{}, ctx context. + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.observatory.command.ObservatoryService/GetOutboundStatus", ++ FullMethod: ObservatoryService_GetOutboundStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ObservatoryServiceServer).GetOutboundStatus(ctx, req.(*GetOutboundStatusRequest)) +diff --git a/app/observatory/config.pb.go b/app/observatory/config.pb.go +index f6b77557f..97683b55c 100644 +--- a/app/observatory/config.pb.go ++++ b/app/observatory/config.pb.go +@@ -493,25 +493,24 @@ var file_app_observatory_config_proto_rawDesc = []byte{ + 0x22, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a, + 0x0e, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65, +- 0x72, 0x76, 0x61, 0x6c, 0x22, 0xa1, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, ++ 0x72, 0x76, 0x61, 0x6c, 0x22, 0x9d, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x29, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, + 0x6f, 0x62, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x72, 0x6f, 0x62, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x62, 0x65, + 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, +- 0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x3a, 0x28, +- 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, +- 0x17, 0x12, 0x15, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x4f, 0x62, 0x73, +- 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, +- 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, +- 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, +- 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, +- 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0xaa, 0x02, 0x1a, 0x56, +- 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, +- 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x33, ++ 0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x3a, 0x24, ++ 0x82, 0xb5, 0x18, 0x20, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x15, 0x62, ++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, ++ 0x74, 0x6f, 0x72, 0x79, 0x42, 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, ++ 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, ++ 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, ++ 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, ++ 0x61, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/observatory/multiobservatory/config.pb.go b/app/observatory/multiobservatory/config.pb.go +index 24ea73180..ded513f77 100644 +--- a/app/observatory/multiobservatory/config.pb.go ++++ b/app/observatory/multiobservatory/config.pb.go +@@ -76,25 +76,24 @@ var file_app_observatory_multiobservatory_config_proto_rawDesc = []byte{ + 0x72, 0x65, 0x73, 0x2f, 0x73, 0x6b, 0x65, 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x71, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, ++ 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6d, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, + 0x0a, 0x07, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x74, 0x61, 0x67, 0x67, 0x65, 0x64, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x68, 0x6f, 0x6c, 0x64, 0x65, +- 0x72, 0x73, 0x3a, 0x23, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, +- 0x65, 0x82, 0xb5, 0x18, 0x12, 0x12, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6f, 0x62, 0x73, 0x65, +- 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x42, 0xa2, 0x01, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, +- 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, +- 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x01, 0x5a, 0x3f, 0x67, +- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, +- 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x75, +- 0x6c, 0x74, 0x69, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0xaa, 0x02, +- 0x2b, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, +- 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4d, 0x75, 0x6c, 0x74, +- 0x69, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, +- 0x6f, 0x74, 0x6f, 0x33, ++ 0x72, 0x73, 0x3a, 0x1f, 0x82, 0xb5, 0x18, 0x1b, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, ++ 0x65, 0x12, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, ++ 0x6f, 0x72, 0x79, 0x42, 0xa2, 0x01, 0x0a, 0x2f, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, ++ 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4f, 0x62, 0x73, 0x65, ++ 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, ++ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, ++ 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6f, ++ 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0xaa, 0x02, 0x2b, 0x56, 0x32, 0x52, ++ 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, ++ 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x4f, 0x62, 0x73, ++ 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/policy/config.pb.go b/app/policy/config.pb.go +index a9908fac8..f78c6779b 100644 +--- a/app/policy/config.pb.go ++++ b/app/policy/config.pb.go +@@ -548,7 +548,7 @@ var file_app_policy_config_proto_rawDesc = []byte{ + 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, +- 0x6e, 0x6b, 0x22, 0xf9, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, ++ 0x6e, 0x6b, 0x22, 0xf5, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, + 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x76, + 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x65, 0x76, 0x65, +@@ -562,15 +562,15 @@ var file_app_policy_config_proto_rawDesc = []byte{ + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, +- 0x02, 0x38, 0x01, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, +- 0x63, 0x65, 0x82, 0xb5, 0x18, 0x08, 0x12, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x60, +- 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x01, 0x5a, 0x29, 0x67, +- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, +- 0x70, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xaa, 0x02, 0x15, 0x56, 0x32, 0x52, 0x61, 0x79, +- 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, +- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x02, 0x38, 0x01, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, ++ 0x63, 0x65, 0x12, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x60, 0x0a, 0x19, 0x63, 0x6f, ++ 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, ++ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, ++ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x6f, ++ 0x6c, 0x69, 0x63, 0x79, 0xaa, 0x02, 0x15, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, ++ 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x62, 0x06, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/proxyman/command/command.pb.go b/app/proxyman/command/command.pb.go +index a6b14681c..4c7297ade 100644 +--- a/app/proxyman/command/command.pb.go ++++ b/app/proxyman/command/command.pb.go +@@ -733,67 +733,67 @@ var file_app_proxyman_command_command_proto_rawDesc = []byte{ + 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, +- 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x06, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1f, 0x82, 0xb5, 0x18, 0x0d, 0x0a, 0x0b, 0x67, 0x72, 0x70, 0x63, +- 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x0a, 0x12, 0x08, 0x70, 0x72, 0x6f, +- 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x32, 0x90, 0x06, 0x0a, 0x0e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, +- 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, +- 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x32, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x0a, 0x06, 0x43, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1b, 0x82, 0xb5, 0x18, 0x17, 0x0a, 0x0b, 0x67, 0x72, 0x70, 0x63, ++ 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, ++ 0x6e, 0x32, 0x90, 0x06, 0x0a, 0x0e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, ++ 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, ++ 0x6e, 0x64, 0x12, 0x32, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, ++ 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, ++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, +- 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, +- 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, +- 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, +- 0x00, 0x12, 0x80, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, ++ 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, ++ 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, ++ 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, ++ 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, ++ 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, ++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, ++ 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, ++ 0x12, 0x7d, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, ++ 0x12, 0x34, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, ++ 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, ++ 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, ++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, ++ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, ++ 0x7a, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, ++ 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, ++ 0x2e, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, ++ 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, ++ 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, ++ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, ++ 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x83, 0x01, 0x0a, 0x0e, ++ 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x36, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, ++ 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, ++ 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, ++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, ++ 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, ++ 0x00, 0x12, 0x80, 0x01, 0x0a, 0x0d, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x12, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, +- 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, ++ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x76, 0x32, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, +- 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, +- 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, +- 0x73, 0x65, 0x22, 0x00, 0x12, 0x7d, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, +- 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x34, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, +- 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, +- 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, +- 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, +- 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, +- 0x65, 0x22, 0x00, 0x12, 0x7a, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, +- 0x6e, 0x64, 0x12, 0x33, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, +- 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, +- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, +- 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, +- 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, +- 0x83, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, +- 0x6e, 0x64, 0x12, 0x36, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, +- 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, +- 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, +- 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, +- 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, +- 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x0d, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, +- 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, +- 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, +- 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, +- 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, +- 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, +- 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, +- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, +- 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, +- 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, +- 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, +- 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63, +- 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, +- 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, +- 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, ++ 0x73, 0x65, 0x22, 0x00, 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, ++ 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x33, 0x67, ++ 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, ++ 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, ++ 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, ++ 0x6e, 0x64, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, ++ 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, ++ 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/proxyman/command/command_grpc.pb.go b/app/proxyman/command/command_grpc.pb.go +index 29b8146b9..60cab0575 100644 +--- a/app/proxyman/command/command_grpc.pb.go ++++ b/app/proxyman/command/command_grpc.pb.go +@@ -12,6 +12,15 @@ import ( + // Requires gRPC-Go v1.32.0 or later. + const _ = grpc.SupportPackageIsVersion7 + ++const ( ++ HandlerService_AddInbound_FullMethodName = "/v2ray.core.app.proxyman.command.HandlerService/AddInbound" ++ HandlerService_RemoveInbound_FullMethodName = "/v2ray.core.app.proxyman.command.HandlerService/RemoveInbound" ++ HandlerService_AlterInbound_FullMethodName = "/v2ray.core.app.proxyman.command.HandlerService/AlterInbound" ++ HandlerService_AddOutbound_FullMethodName = "/v2ray.core.app.proxyman.command.HandlerService/AddOutbound" ++ HandlerService_RemoveOutbound_FullMethodName = "/v2ray.core.app.proxyman.command.HandlerService/RemoveOutbound" ++ HandlerService_AlterOutbound_FullMethodName = "/v2ray.core.app.proxyman.command.HandlerService/AlterOutbound" ++) ++ + // HandlerServiceClient is the client API for HandlerService service. + // + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +@@ -34,7 +43,7 @@ func NewHandlerServiceClient(cc grpc.ClientConnInterface) HandlerServiceClient { + + func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error) { + out := new(AddInboundResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.proxyman.command.HandlerService/AddInbound", in, out, opts...) ++ err := c.cc.Invoke(ctx, HandlerService_AddInbound_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -43,7 +52,7 @@ func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundReq + + func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error) { + out := new(RemoveInboundResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.proxyman.command.HandlerService/RemoveInbound", in, out, opts...) ++ err := c.cc.Invoke(ctx, HandlerService_RemoveInbound_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -52,7 +61,7 @@ func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInbo + + func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error) { + out := new(AlterInboundResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.proxyman.command.HandlerService/AlterInbound", in, out, opts...) ++ err := c.cc.Invoke(ctx, HandlerService_AlterInbound_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -61,7 +70,7 @@ func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboun + + func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) { + out := new(AddOutboundResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.proxyman.command.HandlerService/AddOutbound", in, out, opts...) ++ err := c.cc.Invoke(ctx, HandlerService_AddOutbound_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -70,7 +79,7 @@ func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundR + + func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error) { + out := new(RemoveOutboundResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.proxyman.command.HandlerService/RemoveOutbound", in, out, opts...) ++ err := c.cc.Invoke(ctx, HandlerService_RemoveOutbound_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -79,7 +88,7 @@ func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOut + + func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error) { + out := new(AlterOutboundResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.proxyman.command.HandlerService/AlterOutbound", in, out, opts...) ++ err := c.cc.Invoke(ctx, HandlerService_AlterOutbound_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -144,7 +153,7 @@ func _HandlerService_AddInbound_Handler(srv interface{}, ctx context.Context, de + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.proxyman.command.HandlerService/AddInbound", ++ FullMethod: HandlerService_AddInbound_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).AddInbound(ctx, req.(*AddInboundRequest)) +@@ -162,7 +171,7 @@ func _HandlerService_RemoveInbound_Handler(srv interface{}, ctx context.Context, + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.proxyman.command.HandlerService/RemoveInbound", ++ FullMethod: HandlerService_RemoveInbound_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).RemoveInbound(ctx, req.(*RemoveInboundRequest)) +@@ -180,7 +189,7 @@ func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.Context, + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.proxyman.command.HandlerService/AlterInbound", ++ FullMethod: HandlerService_AlterInbound_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).AlterInbound(ctx, req.(*AlterInboundRequest)) +@@ -198,7 +207,7 @@ func _HandlerService_AddOutbound_Handler(srv interface{}, ctx context.Context, d + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.proxyman.command.HandlerService/AddOutbound", ++ FullMethod: HandlerService_AddOutbound_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).AddOutbound(ctx, req.(*AddOutboundRequest)) +@@ -216,7 +225,7 @@ func _HandlerService_RemoveOutbound_Handler(srv interface{}, ctx context.Context + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.proxyman.command.HandlerService/RemoveOutbound", ++ FullMethod: HandlerService_RemoveOutbound_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).RemoveOutbound(ctx, req.(*RemoveOutboundRequest)) +@@ -234,7 +243,7 @@ func _HandlerService_AlterOutbound_Handler(srv interface{}, ctx context.Context, + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.proxyman.command.HandlerService/AlterOutbound", ++ FullMethod: HandlerService_AlterOutbound_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).AlterOutbound(ctx, req.(*AlterOutboundRequest)) +diff --git a/app/restfulapi/config.pb.go b/app/restfulapi/config.pb.go +index 63ea2eeff..e7a29987c 100644 +--- a/app/restfulapi/config.pb.go ++++ b/app/restfulapi/config.pb.go +@@ -86,22 +86,22 @@ var file_app_restfulapi_config_proto_rawDesc = []byte{ + 0x32, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x65, 0x73, 0x74, 0x66, 0x75, 0x6c, + 0x61, 0x70, 0x69, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x88, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x84, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, + 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, +- 0x6e, 0x3a, 0x1d, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, +- 0x82, 0xb5, 0x18, 0x0c, 0x12, 0x0a, 0x72, 0x65, 0x73, 0x74, 0x66, 0x75, 0x6c, 0x61, 0x70, 0x69, +- 0x42, 0x61, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +- 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x65, 0x73, 0x74, 0x61, 0x70, 0x69, 0x50, 0x01, +- 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, +- 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, +- 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x66, 0x75, 0x6c, 0x61, 0x70, 0x69, 0xaa, +- 0x02, 0x11, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x65, 0x73, 0x74, +- 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6e, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, ++ 0x12, 0x0a, 0x72, 0x65, 0x73, 0x74, 0x66, 0x75, 0x6c, 0x61, 0x70, 0x69, 0x42, 0x61, 0x0a, 0x1a, ++ 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, ++ 0x70, 0x70, 0x2e, 0x72, 0x65, 0x73, 0x74, 0x61, 0x70, 0x69, 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, ++ 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, ++ 0x2f, 0x72, 0x65, 0x73, 0x74, 0x66, 0x75, 0x6c, 0x61, 0x70, 0x69, 0xaa, 0x02, 0x11, 0x56, 0x32, ++ 0x52, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x70, 0x69, 0x62, ++ 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/reverse/config.pb.go b/app/reverse/config.pb.go +index 386aee560..763176225 100644 +--- a/app/reverse/config.pb.go ++++ b/app/reverse/config.pb.go +@@ -304,7 +304,7 @@ var file_app_reverse_config_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x50, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, + 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, + 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, +- 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0xba, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, ++ 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0xb6, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x0d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x65, 0x76, 0x65, +@@ -314,16 +314,16 @@ var file_app_reverse_config_proto_rawDesc = []byte{ + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x2e, 0x50, + 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x70, 0x6f, 0x72, +- 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1a, 0x82, 0xb5, 0x18, 0x09, 0x0a, +- 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x09, 0x12, 0x07, 0x72, 0x65, +- 0x76, 0x65, 0x72, 0x73, 0x65, 0x42, 0x67, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x72, 0x65, +- 0x76, 0x65, 0x72, 0x73, 0x65, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, +- 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, +- 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x65, 0x76, 0x65, +- 0x72, 0x73, 0x65, 0xaa, 0x02, 0x18, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, +- 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x62, 0x06, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x12, 0x0a, ++ 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x07, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, ++ 0x65, 0x42, 0x67, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, ++ 0x65, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, ++ 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, ++ 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0xaa, ++ 0x02, 0x18, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, ++ 0x78, 0x79, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x33, + } + + var ( +diff --git a/app/router/command/command.pb.go b/app/router/command/command.pb.go +index 88d671a87..b0db9c2d2 100644 +--- a/app/router/command/command.pb.go ++++ b/app/router/command/command.pb.go +@@ -758,52 +758,52 @@ var file_app_router_command_command_proto_rawDesc = []byte{ + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x20, 0x0a, + 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, +- 0x27, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1d, 0x82, 0xb5, 0x18, 0x0d, 0x0a, +- 0x0b, 0x67, 0x72, 0x70, 0x63, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x08, +- 0x12, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x32, 0xa8, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75, +- 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x87, 0x01, 0x0a, 0x15, +- 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, +- 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x3b, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +- 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, +- 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, +- 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, +- 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, +- 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, +- 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x6d, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, +- 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, +- 0x6e, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, +- 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, +- 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, +- 0x78, 0x74, 0x22, 0x00, 0x12, 0x82, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, +- 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, +- 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, +- 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, +- 0x36, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, ++ 0x23, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, ++ 0x0b, 0x67, 0x72, 0x70, 0x63, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x06, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x72, 0x32, 0xa8, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, ++ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x87, 0x01, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, ++ 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, ++ 0x73, 0x12, 0x3b, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, ++ 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, ++ 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, ++ 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, ++ 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x30, ++ 0x01, 0x12, 0x6d, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x2f, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, ++ 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, ++ 0x2d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, +- 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, +- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, 0x0a, 0x16, 0x4f, 0x76, +- 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, +- 0x72, 0x67, 0x65, 0x74, 0x12, 0x3c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, ++ 0x12, 0x82, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, ++ 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, ++ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, ++ 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, ++ 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, 0x0a, 0x16, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, ++ 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, ++ 0x12, 0x3c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, ++ 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, ++ 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, ++ 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, ++ 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, ++ 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, ++ 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, ++ 0x78, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, +- 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, +- 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, +- 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, +- 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, +- 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, +- 0x65, 0x22, 0x00, 0x42, 0x78, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, +- 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, +- 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x1d, +- 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, +- 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, ++ 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, ++ 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x1d, 0x56, 0x32, 0x52, 0x61, ++ 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, ++ 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x33, + } + + var ( +diff --git a/app/router/command/command_grpc.pb.go b/app/router/command/command_grpc.pb.go +index bd359fbed..cae34f05f 100644 +--- a/app/router/command/command_grpc.pb.go ++++ b/app/router/command/command_grpc.pb.go +@@ -12,6 +12,13 @@ import ( + // Requires gRPC-Go v1.32.0 or later. + const _ = grpc.SupportPackageIsVersion7 + ++const ( ++ RoutingService_SubscribeRoutingStats_FullMethodName = "/v2ray.core.app.router.command.RoutingService/SubscribeRoutingStats" ++ RoutingService_TestRoute_FullMethodName = "/v2ray.core.app.router.command.RoutingService/TestRoute" ++ RoutingService_GetBalancerInfo_FullMethodName = "/v2ray.core.app.router.command.RoutingService/GetBalancerInfo" ++ RoutingService_OverrideBalancerTarget_FullMethodName = "/v2ray.core.app.router.command.RoutingService/OverrideBalancerTarget" ++) ++ + // RoutingServiceClient is the client API for RoutingService service. + // + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +@@ -31,7 +38,7 @@ func NewRoutingServiceClient(cc grpc.ClientConnInterface) RoutingServiceClient { + } + + func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (RoutingService_SubscribeRoutingStatsClient, error) { +- stream, err := c.cc.NewStream(ctx, &RoutingService_ServiceDesc.Streams[0], "/v2ray.core.app.router.command.RoutingService/SubscribeRoutingStats", opts...) ++ stream, err := c.cc.NewStream(ctx, &RoutingService_ServiceDesc.Streams[0], RoutingService_SubscribeRoutingStats_FullMethodName, opts...) + if err != nil { + return nil, err + } +@@ -64,7 +71,7 @@ func (x *routingServiceSubscribeRoutingStatsClient) Recv() (*RoutingContext, err + + func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error) { + out := new(RoutingContext) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.router.command.RoutingService/TestRoute", in, out, opts...) ++ err := c.cc.Invoke(ctx, RoutingService_TestRoute_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -73,7 +80,7 @@ func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteReque + + func (c *routingServiceClient) GetBalancerInfo(ctx context.Context, in *GetBalancerInfoRequest, opts ...grpc.CallOption) (*GetBalancerInfoResponse, error) { + out := new(GetBalancerInfoResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.router.command.RoutingService/GetBalancerInfo", in, out, opts...) ++ err := c.cc.Invoke(ctx, RoutingService_GetBalancerInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -82,7 +89,7 @@ func (c *routingServiceClient) GetBalancerInfo(ctx context.Context, in *GetBalan + + func (c *routingServiceClient) OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error) { + out := new(OverrideBalancerTargetResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.router.command.RoutingService/OverrideBalancerTarget", in, out, opts...) ++ err := c.cc.Invoke(ctx, RoutingService_OverrideBalancerTarget_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -160,7 +167,7 @@ func _RoutingService_TestRoute_Handler(srv interface{}, ctx context.Context, dec + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.router.command.RoutingService/TestRoute", ++ FullMethod: RoutingService_TestRoute_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoutingServiceServer).TestRoute(ctx, req.(*TestRouteRequest)) +@@ -178,7 +185,7 @@ func _RoutingService_GetBalancerInfo_Handler(srv interface{}, ctx context.Contex + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.router.command.RoutingService/GetBalancerInfo", ++ FullMethod: RoutingService_GetBalancerInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoutingServiceServer).GetBalancerInfo(ctx, req.(*GetBalancerInfoRequest)) +@@ -196,7 +203,7 @@ func _RoutingService_OverrideBalancerTarget_Handler(srv interface{}, ctx context + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.router.command.RoutingService/OverrideBalancerTarget", ++ FullMethod: RoutingService_OverrideBalancerTarget_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoutingServiceServer).OverrideBalancerTarget(ctx, req.(*OverrideBalancerTargetRequest)) +diff --git a/app/router/config.pb.go b/app/router/config.pb.go +index c1b383bfe..7d077d468 100644 +--- a/app/router/config.pb.go ++++ b/app/router/config.pb.go +@@ -1047,106 +1047,105 @@ var file_app_router_config_proto_rawDesc = []byte{ + 0x67, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, +- 0x22, 0x32, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x61, 0x6e, 0x64, +- 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1a, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, +- 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x82, 0xb5, 0x18, 0x08, 0x12, 0x06, 0x72, 0x61, +- 0x6e, 0x64, 0x6f, 0x6d, 0x22, 0x5b, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, +- 0x4c, 0x65, 0x61, 0x73, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, +- 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x18, +- 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, +- 0x61, 0x67, 0x3a, 0x1d, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, +- 0x65, 0x72, 0x82, 0xb5, 0x18, 0x0b, 0x12, 0x09, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x70, 0x69, 0x6e, +- 0x67, 0x22, 0x88, 0x02, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, +- 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, +- 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, +- 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, +- 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, +- 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, +- 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, +- 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, +- 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, +- 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, +- 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, +- 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, +- 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x62, +- 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, +- 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x67, 0x3a, 0x1d, 0x82, +- 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x82, 0xb5, 0x18, +- 0x0b, 0x12, 0x09, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xdd, 0x01, 0x0a, +- 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, +- 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, +- 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, +- 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, +- 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, +- 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x36, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, +- 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +- 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, +- 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, +- 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, +- 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, +- 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, +- 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0xab, 0x05, 0x0a, +- 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, +- 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, +- 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0d, 0x62, 0x61, +- 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, +- 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x54, 0x61, +- 0x67, 0x12, 0x42, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, +- 0x0b, 0x32, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, +- 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, +- 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, +- 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, +- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, +- 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, +- 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, +- 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, +- 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, +- 0x69, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, +- 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +- 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, +- 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, +- 0x72, 0x6b, 0x73, 0x12, 0x4c, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x65, +- 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x22, 0x2e, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x61, 0x6e, 0x64, ++ 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x12, 0x0a, 0x08, ++ 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, ++ 0x22, 0x57, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, ++ 0x74, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6f, ++ 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, ++ 0x09, 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x67, 0x3a, 0x19, ++ 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x09, ++ 0x6c, 0x65, 0x61, 0x73, 0x74, 0x70, 0x69, 0x6e, 0x67, 0x22, 0x84, 0x02, 0x0a, 0x17, 0x53, 0x74, ++ 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, ++ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, ++ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, ++ 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, ++ 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, ++ 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, ++ 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, ++ 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, ++ 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, ++ 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, ++ 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, ++ 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, ++ 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, ++ 0x65, 0x72, 0x54, 0x61, 0x67, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x08, 0x62, 0x61, 0x6c, ++ 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x09, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x6c, 0x6f, 0x61, 0x64, ++ 0x22, 0xdd, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x0f, 0x64, ++ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, ++ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, ++ 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, ++ 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x36, 0x0a, 0x04, 0x72, ++ 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, +- 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, +- 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x65, 0x6f, 0x69, +- 0x70, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, +- 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, +- 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, +- 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, +- 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, +- 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, +- 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, +- 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x74, 0x74, +- 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, +- 0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, +- 0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4c, +- 0x0a, 0x0a, 0x67, 0x65, 0x6f, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0xa1, 0x93, 0x04, +- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, +- 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, +- 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, +- 0x65, 0x52, 0x09, 0x67, 0x65, 0x6f, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, +- 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0x8c, 0x02, 0x0a, 0x10, 0x53, +- 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, +- 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, +- 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, ++ 0x75, 0x6c, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, ++ 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, ++ 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, ++ 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, ++ 0x22, 0xab, 0x05, 0x0a, 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x52, ++ 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, ++ 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, ++ 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, ++ 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, ++ 0x6e, 0x67, 0x54, 0x61, 0x67, 0x12, 0x42, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, ++ 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, ++ 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, ++ 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, ++ 0x69, 0x70, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, +- 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, +- 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, +- 0x40, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, ++ 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, ++ 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, ++ 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, ++ 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, ++ 0x72, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, ++ 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x6e, ++ 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x4c, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, ++ 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, + 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, +- 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, +- 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, +- 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, +- 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, +- 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, +- 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, +- 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x3a, 0x19, +- 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, +- 0x08, 0x12, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2a, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, ++ 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, ++ 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, ++ 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, ++ 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, ++ 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, ++ 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, ++ 0x03, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, ++ 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, ++ 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, ++ 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, ++ 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x61, ++ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, ++ 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, ++ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, ++ 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, ++ 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0a, 0x67, 0x65, 0x6f, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, ++ 0x18, 0xa1, 0x93, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, ++ 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, ++ 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52, 0x09, 0x67, 0x65, 0x6f, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, ++ 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0x88, ++ 0x02, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, ++ 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, ++ 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, ++ 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, ++ 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, ++ 0x65, 0x67, 0x79, 0x12, 0x40, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, ++ 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, ++ 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, ++ 0x66, 0x69, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, ++ 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, ++ 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, ++ 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, ++ 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, ++ 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, ++ 0x6c, 0x65, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, ++ 0x65, 0x12, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2a, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, + 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, + 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, +diff --git a/app/stats/command/command.pb.go b/app/stats/command/command.pb.go +index 7deb254ca..73903d35b 100644 +--- a/app/stats/command/command.pb.go ++++ b/app/stats/command/command.pb.go +@@ -540,40 +540,39 @@ var file_app_stats_command_command_proto_rawDesc = []byte{ + 0x22, 0x0a, 0x0c, 0x50, 0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x50, 0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, + 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, +- 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x06, 0x43, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1c, 0x82, 0xb5, 0x18, 0x0d, 0x0a, 0x0b, 0x67, 0x72, 0x70, +- 0x63, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x07, 0x12, 0x05, 0x73, 0x74, +- 0x61, 0x74, 0x73, 0x32, 0xde, 0x02, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, +- 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, +- 0x12, 0x2d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, +- 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, +- 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, +- 0x2e, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, +- 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, +- 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, +- 0x00, 0x12, 0x71, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, +- 0x2f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, +- 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, +- 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, +- 0x1a, 0x30, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, +- 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, +- 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, +- 0x73, 0x65, 0x22, 0x00, 0x12, 0x6e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, +- 0x61, 0x74, 0x73, 0x12, 0x2d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, +- 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, +- 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, +- 0x64, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, +- 0x73, 0x65, 0x22, 0x00, 0x42, 0x75, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, +- 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, +- 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, +- 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, +- 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x1c, 0x56, +- 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x53, 0x74, +- 0x61, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, +- 0x74, 0x6f, 0x33, ++ 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x22, 0x0a, 0x06, 0x43, ++ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x14, 0x0a, 0x0b, 0x67, 0x72, 0x70, ++ 0x63, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x32, ++ 0xde, 0x02, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, ++ 0x12, 0x6b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2d, 0x2e, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, ++ 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, ++ 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, ++ 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, ++ 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x71, 0x0a, ++ 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2f, 0x2e, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, ++ 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, ++ 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, ++ 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, ++ 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, ++ 0x12, 0x6e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, ++ 0x2d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, ++ 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, ++ 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, ++ 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, ++ 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, ++ 0x42, 0x75, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, ++ 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, ++ 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, ++ 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, ++ 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x1c, 0x56, 0x32, 0x52, 0x61, 0x79, ++ 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, ++ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/app/stats/command/command_grpc.pb.go b/app/stats/command/command_grpc.pb.go +index a0fb52a27..3a301c2ae 100644 +--- a/app/stats/command/command_grpc.pb.go ++++ b/app/stats/command/command_grpc.pb.go +@@ -12,6 +12,12 @@ import ( + // Requires gRPC-Go v1.32.0 or later. + const _ = grpc.SupportPackageIsVersion7 + ++const ( ++ StatsService_GetStats_FullMethodName = "/v2ray.core.app.stats.command.StatsService/GetStats" ++ StatsService_QueryStats_FullMethodName = "/v2ray.core.app.stats.command.StatsService/QueryStats" ++ StatsService_GetSysStats_FullMethodName = "/v2ray.core.app.stats.command.StatsService/GetSysStats" ++) ++ + // StatsServiceClient is the client API for StatsService service. + // + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +@@ -31,7 +37,7 @@ func NewStatsServiceClient(cc grpc.ClientConnInterface) StatsServiceClient { + + func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) { + out := new(GetStatsResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.stats.command.StatsService/GetStats", in, out, opts...) ++ err := c.cc.Invoke(ctx, StatsService_GetStats_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -40,7 +46,7 @@ func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest, + + func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error) { + out := new(QueryStatsResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.stats.command.StatsService/QueryStats", in, out, opts...) ++ err := c.cc.Invoke(ctx, StatsService_QueryStats_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -49,7 +55,7 @@ func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsReque + + func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error) { + out := new(SysStatsResponse) +- err := c.cc.Invoke(ctx, "/v2ray.core.app.stats.command.StatsService/GetSysStats", in, out, opts...) ++ err := c.cc.Invoke(ctx, StatsService_GetSysStats_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } +@@ -102,7 +108,7 @@ func _StatsService_GetStats_Handler(srv interface{}, ctx context.Context, dec fu + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.stats.command.StatsService/GetStats", ++ FullMethod: StatsService_GetStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StatsServiceServer).GetStats(ctx, req.(*GetStatsRequest)) +@@ -120,7 +126,7 @@ func _StatsService_QueryStats_Handler(srv interface{}, ctx context.Context, dec + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.stats.command.StatsService/QueryStats", ++ FullMethod: StatsService_QueryStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StatsServiceServer).QueryStats(ctx, req.(*QueryStatsRequest)) +@@ -138,7 +144,7 @@ func _StatsService_GetSysStats_Handler(srv interface{}, ctx context.Context, dec + } + info := &grpc.UnaryServerInfo{ + Server: srv, +- FullMethod: "/v2ray.core.app.stats.command.StatsService/GetSysStats", ++ FullMethod: StatsService_GetSysStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StatsServiceServer).GetSysStats(ctx, req.(*SysStatsRequest)) +diff --git a/app/stats/config.pb.go b/app/stats/config.pb.go +index e9eb82b92..d5ce1d97b 100644 +--- a/app/stats/config.pb.go ++++ b/app/stats/config.pb.go +@@ -124,23 +124,22 @@ var file_app_stats_config_proto_rawDesc = []byte{ + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x1a, 0x20, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x22, 0x22, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x09, +- 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x07, 0x12, 0x05, 0x73, +- 0x74, 0x61, 0x74, 0x73, 0x22, 0x75, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, +- 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, +- 0x67, 0x12, 0x28, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x4c, +- 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x53, 0x75, 0x62, 0x73, +- 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x42, +- 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, +- 0x0a, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x5d, 0x0a, 0x18, 0x63, +- 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, +- 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, +- 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, +- 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x74, +- 0x61, 0x74, 0x73, 0xaa, 0x02, 0x14, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, +- 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, +- 0x6f, 0x33, ++ 0x22, 0x1e, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x14, 0x82, 0xb5, 0x18, 0x10, ++ 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, ++ 0x22, 0x75, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, ++ 0x01, 0x28, 0x08, 0x52, 0x08, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x12, 0x28, 0x0a, ++ 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x4c, 0x69, 0x6d, 0x69, 0x74, ++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, ++ 0x65, 0x72, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x42, 0x75, 0x66, 0x66, 0x65, ++ 0x72, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x42, 0x75, 0x66, ++ 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x5d, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, ++ 0x61, 0x74, 0x73, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, ++ 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, ++ 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0xaa, ++ 0x02, 0x14, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, ++ 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/common/protoext/testing/test.pb.go b/common/protoext/testing/test.pb.go +index 84f577254..52fdc5c8a 100644 +--- a/common/protoext/testing/test.pb.go ++++ b/common/protoext/testing/test.pb.go +@@ -71,22 +71,21 @@ var file_common_protoext_testing_test_proto_rawDesc = []byte{ + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, +- 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x0e, 0x54, 0x65, +- 0x73, 0x74, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x34, 0x0a, 0x0a, ++ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x0e, 0x54, 0x65, ++ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x0a, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, +- 0x42, 0x15, 0x82, 0xb5, 0x18, 0x06, 0x12, 0x04, 0x74, 0x65, 0x73, 0x74, 0x82, 0xb5, 0x18, 0x07, +- 0x12, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x52, 0x09, 0x74, 0x65, 0x73, 0x74, 0x46, 0x69, 0x65, +- 0x6c, 0x64, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x06, 0x0a, 0x04, 0x64, 0x65, 0x6d, 0x6f, 0x82, 0xb5, +- 0x18, 0x07, 0x0a, 0x05, 0x64, 0x65, 0x6d, 0x6f, 0x32, 0x42, 0x84, 0x01, 0x0a, 0x26, 0x63, 0x6f, +- 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, +- 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x73, +- 0x74, 0x69, 0x6e, 0x67, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, +- 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, +- 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0xaa, 0x02, 0x22, 0x56, 0x32, +- 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, +- 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x45, 0x78, 0x74, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, +- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x42, 0x11, 0x82, 0xb5, 0x18, 0x0d, 0x12, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x05, 0x74, 0x65, ++ 0x73, 0x74, 0x32, 0x52, 0x09, 0x74, 0x65, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x3a, 0x11, ++ 0x82, 0xb5, 0x18, 0x0d, 0x0a, 0x04, 0x64, 0x65, 0x6d, 0x6f, 0x0a, 0x05, 0x64, 0x65, 0x6d, 0x6f, ++ 0x32, 0x42, 0x84, 0x01, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, ++ 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x01, 0x5a, 0x33, ++ 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, ++ 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, ++ 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x73, 0x74, ++ 0x69, 0x6e, 0x67, 0xaa, 0x02, 0x22, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, ++ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x45, 0x78, 0x74, ++ 0x2e, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/infra/conf/cfgcommon/socketcfg/socket.go b/infra/conf/cfgcommon/socketcfg/socket.go +index ab6996f7d..b9ca6d83e 100644 +--- a/infra/conf/cfgcommon/socketcfg/socket.go ++++ b/infra/conf/cfgcommon/socketcfg/socket.go +@@ -18,6 +18,7 @@ type SocketConfig struct { + RxBufSize uint64 `json:"rxBufSize"` + TxBufSize uint64 `json:"txBufSize"` + ForceBufSize bool `json:"forceBufSize"` ++ Mptcp bool `json:"mptcp"` + } + + // Build implements Buildable. +@@ -58,5 +59,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { + TxBufSize: int64(c.TxBufSize), + ForceBufSize: c.ForceBufSize, + BindToDevice: c.BindToDevice, ++ Mptcp: c.Mptcp, + }, nil + } +diff --git a/proxy/blackhole/config.pb.go b/proxy/blackhole/config.pb.go +index 4121e61c9..222ef1063 100644 +--- a/proxy/blackhole/config.pb.go ++++ b/proxy/blackhole/config.pb.go +@@ -193,17 +193,17 @@ var file_proxy_blackhole_config_proto_rawDesc = []byte{ + 0x67, 0x12, 0x30, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, +- 0x6e, 0x73, 0x65, 0x22, 0x31, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, +- 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x1d, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, +- 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x0b, 0x12, 0x09, 0x62, 0x6c, 0x61, +- 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x65, 0x42, 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x62, +- 0x6c, 0x61, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x65, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, +- 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, +- 0x2f, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x65, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, +- 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x42, 0x6c, +- 0x61, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, ++ 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x08, 0x6f, ++ 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x09, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x68, 0x6f, ++ 0x6c, 0x65, 0x42, 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, ++ 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x62, 0x6c, 0x61, 0x63, 0x6b, ++ 0x68, 0x6f, 0x6c, 0x65, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, ++ 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x62, 0x6c, 0x61, ++ 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x65, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, ++ 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x42, 0x6c, 0x61, 0x63, 0x6b, 0x68, ++ 0x6f, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/dns/config.pb.go b/proxy/dns/config.pb.go +index de45d5d95..d3f0380e8 100644 +--- a/proxy/dns/config.pb.go ++++ b/proxy/dns/config.pb.go +@@ -127,16 +127,15 @@ var file_proxy_dns_config_proto_rawDesc = []byte{ + 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, +- 0x22, 0x2b, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x17, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, +- 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x05, 0x12, 0x03, 0x64, 0x6e, 0x73, 0x42, 0x5d, 0x0a, +- 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, +- 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, +- 0x79, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x14, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, +- 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, +- 0x6f, 0x74, 0x6f, 0x33, ++ 0x22, 0x27, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, ++ 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x13, 0x82, 0xb5, 0x18, 0x0f, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, ++ 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x03, 0x64, 0x6e, 0x73, 0x42, 0x5d, 0x0a, 0x18, 0x63, 0x6f, 0x6d, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, ++ 0x79, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, ++ 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, ++ 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x64, 0x6e, ++ 0x73, 0xaa, 0x02, 0x14, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, ++ 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/dokodemo/config.pb.go b/proxy/dokodemo/config.pb.go +index fd68e7160..e7debc4ab 100644 +--- a/proxy/dokodemo/config.pb.go ++++ b/proxy/dokodemo/config.pb.go +@@ -222,7 +222,7 @@ var file_proxy_dokodemo_config_proto_rawDesc = []byte{ + 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, +- 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xee, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, ++ 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xea, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, + 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, +@@ -235,16 +235,16 @@ var file_proxy_dokodemo_config_proto_rawDesc = []byte{ + 0x69, 0x73, 0x74, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x27, 0x0a, + 0x0f, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, +- 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x3a, 0x20, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x69, 0x6e, +- 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x0f, 0x12, 0x0d, 0x64, 0x6f, 0x6b, 0x6f, 0x64, +- 0x65, 0x6d, 0x6f, 0x2d, 0x64, 0x6f, 0x6f, 0x72, 0x42, 0x6c, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, +- 0x2e, 0x64, 0x6f, 0x6b, 0x6f, 0x64, 0x65, 0x6d, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, 0x74, +- 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, +- 0x79, 0x2f, 0x64, 0x6f, 0x6b, 0x6f, 0x64, 0x65, 0x6d, 0x6f, 0xaa, 0x02, 0x19, 0x56, 0x32, 0x52, +- 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x44, 0x6f, +- 0x6b, 0x6f, 0x64, 0x65, 0x6d, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x3a, 0x1c, 0x82, 0xb5, 0x18, 0x18, 0x0a, 0x07, 0x69, 0x6e, ++ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0d, 0x64, 0x6f, 0x6b, 0x6f, 0x64, 0x65, 0x6d, 0x6f, 0x2d, ++ 0x64, 0x6f, 0x6f, 0x72, 0x42, 0x6c, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x64, 0x6f, 0x6b, ++ 0x6f, 0x64, 0x65, 0x6d, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, ++ 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, ++ 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x64, 0x6f, ++ 0x6b, 0x6f, 0x64, 0x65, 0x6d, 0x6f, 0xaa, 0x02, 0x19, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, ++ 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x44, 0x6f, 0x6b, 0x6f, 0x64, 0x65, ++ 0x6d, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/freedom/config.pb.go b/proxy/freedom/config.pb.go +index b6c6d4561..0669c70fd 100644 +--- a/proxy/freedom/config.pb.go ++++ b/proxy/freedom/config.pb.go +@@ -262,18 +262,17 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{ + 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, + 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, + 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, +- 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x22, 0x2f, 0x0a, ++ 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x22, 0x2b, 0x0a, + 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x3a, 0x1b, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, +- 0x64, 0x82, 0xb5, 0x18, 0x09, 0x12, 0x07, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x42, 0x69, +- 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, +- 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, +- 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, +- 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, +- 0x18, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, +- 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x33, ++ 0x67, 0x3a, 0x17, 0x82, 0xb5, 0x18, 0x13, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, ++ 0x64, 0x12, 0x07, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x42, 0x69, 0x0a, 0x1c, 0x63, 0x6f, ++ 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, ++ 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, ++ 0x78, 0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x18, 0x56, 0x32, 0x52, ++ 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, ++ 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/loopback/config.pb.go b/proxy/loopback/config.pb.go +index 53876241f..c428b7fba 100644 +--- a/proxy/loopback/config.pb.go ++++ b/proxy/loopback/config.pb.go +@@ -70,19 +70,19 @@ var file_proxy_loopback_config_proto_rawDesc = []byte{ + 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, + 0x6c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, +- 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x47, 0x0a, 0x06, 0x43, 0x6f, ++ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x43, 0x0a, 0x06, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, + 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, +- 0x6e, 0x64, 0x54, 0x61, 0x67, 0x3a, 0x1c, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, 0x75, 0x74, +- 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x0a, 0x12, 0x08, 0x6c, 0x6f, 0x6f, 0x70, 0x62, +- 0x61, 0x63, 0x6b, 0x42, 0x6c, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, +- 0x62, 0x61, 0x63, 0x6b, 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, +- 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, +- 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x6c, 0x6f, 0x6f, +- 0x70, 0x62, 0x61, 0x63, 0x6b, 0xaa, 0x02, 0x19, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, +- 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, +- 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6e, 0x64, 0x54, 0x61, 0x67, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x14, 0x0a, 0x08, 0x6f, 0x75, 0x74, ++ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x08, 0x6c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x42, ++ 0x6c, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, ++ 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, ++ 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, ++ 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, ++ 0x6b, 0xaa, 0x02, 0x19, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, ++ 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x62, 0x06, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/socks/simplified/config.pb.go b/proxy/socks/simplified/config.pb.go +index cf0b16918..ccadf744e 100644 +--- a/proxy/socks/simplified/config.pb.go ++++ b/proxy/socks/simplified/config.pb.go +@@ -148,7 +148,7 @@ var file_proxy_socks_simplified_config_proto_rawDesc = []byte{ + 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, + 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, +- 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xda, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, ++ 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, +@@ -160,25 +160,25 @@ var file_proxy_socks_simplified_config_proto_rawDesc = []byte{ + 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6e, 0x65, + 0x74, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x2e, 0x50, 0x61, 0x63, + 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0e, 0x70, 0x61, 0x63, +- 0x6b, 0x65, 0x74, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x18, 0x82, 0xb5, 0x18, +- 0x09, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x07, 0x12, 0x05, +- 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x22, 0x7a, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, +- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, +- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, +- 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, +- 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, +- 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, +- 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, 0x75, +- 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x07, 0x12, 0x05, 0x73, 0x6f, 0x63, 0x6b, +- 0x73, 0x42, 0x84, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x6f, 0x63, 0x6b, 0x73, +- 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x01, 0x5a, 0x35, 0x67, +- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, +- 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, +- 0x66, 0x69, 0x65, 0x64, 0xaa, 0x02, 0x21, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, +- 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x2e, 0x53, 0x69, +- 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6b, 0x65, 0x74, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x14, 0x82, 0xb5, 0x18, ++ 0x10, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x05, 0x73, 0x6f, 0x63, 0x6b, ++ 0x73, 0x22, 0x76, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, ++ 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, ++ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, ++ 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, ++ 0x72, 0x74, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, ++ 0x6e, 0x64, 0x12, 0x05, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x42, 0x84, 0x01, 0x0a, 0x25, 0x63, 0x6f, ++ 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x78, 0x79, 0x2e, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, ++ 0x69, 0x65, 0x64, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, ++ 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, ++ 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x6f, 0x63, 0x6b, ++ 0x73, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0xaa, 0x02, 0x21, 0x56, ++ 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, ++ 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, ++ 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/trojan/simplified/config.pb.go b/proxy/trojan/simplified/config.pb.go +index 1e3e2f884..f066681cd 100644 +--- a/proxy/trojan/simplified/config.pb.go ++++ b/proxy/trojan/simplified/config.pb.go +@@ -154,7 +148,7 @@ var file_proxy_trojan_simplified_config_proto_rawDesc = []byte{ + 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, + 0x65, 0x74, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x2f, 0x63, 0x6f, +- 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x93, 0x01, 0x0a, 0x0c, 0x53, ++ 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8f, 0x01, 0x0a, 0x0c, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x75, + 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, + 0x73, 0x12, 0x52, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x65, 0x6e, 0x63, 0x6f, +@@ -162,27 +156,27 @@ var file_proxy_trojan_simplified_config_proto_rawDesc = []byte{ + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x70, 0x61, 0x63, 0x6b, + 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, + 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x45, 0x6e, 0x63, +- 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x69, 0x6e, 0x62, +- 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x08, 0x12, 0x06, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, +- 0x22, 0x97, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, +- 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, +- 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, +- 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, +- 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, +- 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, +- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x1a, +- 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, +- 0x18, 0x08, 0x12, 0x06, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x42, 0x87, 0x01, 0x0a, 0x26, 0x63, +- 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, +- 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, +- 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, +- 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, +- 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x74, 0x72, +- 0x6f, 0x6a, 0x61, 0x6e, 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0xaa, +- 0x02, 0x22, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, +- 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, +- 0x66, 0x69, 0x65, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, 0x07, 0x69, 0x6e, 0x62, ++ 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x06, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x22, 0x93, 0x01, 0x0a, ++ 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, ++ 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, ++ 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, ++ 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, ++ 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, ++ 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, ++ 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, ++ 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x12, ++ 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x06, 0x74, 0x72, 0x6f, 0x6a, ++ 0x61, 0x6e, 0x42, 0x87, 0x01, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, ++ 0x61, 0x6e, 0x2e, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x01, 0x5a, ++ 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, ++ 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, ++ 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x2f, 0x73, 0x69, 0x6d, ++ 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0xaa, 0x02, 0x22, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, ++ 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, ++ 0x6e, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x62, 0x06, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/vless/inbound/config.pb.go b/proxy/vless/inbound/config.pb.go +index 96b291316..95dfae868 100644 +--- a/proxy/vless/inbound/config.pb.go ++++ b/proxy/vless/inbound/config.pb.go +@@ -236,19 +236,19 @@ var file_proxy_vless_inbound_config_proto_rawDesc = []byte{ + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, + 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, 0x61, 0x6c, 0x6c, + 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x22, +- 0x42, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, ++ 0x3e, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, +- 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x09, 0x0a, +- 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x07, 0x12, 0x05, 0x76, 0x6c, +- 0x65, 0x73, 0x73, 0x42, 0x7b, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, +- 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, +- 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, +- 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, +- 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, +- 0x02, 0x1e, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, +- 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, +- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3a, 0x14, 0x82, 0xb5, 0x18, 0x10, 0x0a, ++ 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x05, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x42, ++ 0x7b, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, ++ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, ++ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, ++ 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, ++ 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, ++ 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1e, 0x56, 0x32, ++ 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, ++ 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/vless/outbound/config.pb.go b/proxy/vless/outbound/config.pb.go +index e71df8bb6..3b5278990 100644 +--- a/proxy/vless/outbound/config.pb.go ++++ b/proxy/vless/outbound/config.pb.go +@@ -145,24 +145,24 @@ var file_proxy_vless_outbound_config_proto_rawDesc = []byte{ + 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x22, +- 0x92, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, ++ 0x8e, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, + 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, +- 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x0a, 0x0a, +- 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x07, 0x12, 0x05, 0x76, +- 0x6c, 0x65, 0x73, 0x73, 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, +- 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, +- 0x73, 0x73, 0x2e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x33, 0x67, +- 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, +- 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, +- 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, +- 0x6e, 0x64, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, +- 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x4f, 0x75, 0x74, 0x62, +- 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, ++ 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x05, 0x76, 0x6c, 0x65, 0x73, 0x73, ++ 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, ++ 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x6f, ++ 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, ++ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, ++ 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, ++ 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, ++ 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, ++ 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/vlite/inbound/config.pb.go b/proxy/vlite/inbound/config.pb.go +index 047a025b1..8643949a9 100644 +--- a/proxy/vlite/inbound/config.pb.go ++++ b/proxy/vlite/inbound/config.pb.go +@@ -111,7 +111,7 @@ var file_proxy_vlite_inbound_config_proto_rawDesc = []byte{ + 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x69, 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, +- 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbd, 0x02, 0x0a, 0x11, 0x55, 0x44, 0x50, 0x50, 0x72, 0x6f, 0x74, ++ 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x02, 0x0a, 0x11, 0x55, 0x44, 0x50, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x63, 0x72, 0x61, 0x6d, 0x62, +@@ -129,17 +129,17 @@ var file_proxy_vlite_inbound_config_proto_rawDesc = []byte{ + 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, + 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1b, 0x68, 0x61, + 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x69, 0x6e, 0x67, 0x50, 0x61, +- 0x64, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x09, 0x0a, +- 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x08, 0x12, 0x06, 0x76, 0x6c, +- 0x69, 0x74, 0x65, 0x75, 0x42, 0x7b, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, +- 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x69, +- 0x74, 0x65, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, +- 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, +- 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, +- 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x69, 0x74, 0x65, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, +- 0xaa, 0x02, 0x1e, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, +- 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x69, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, +- 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, ++ 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x06, 0x76, 0x6c, 0x69, 0x74, 0x65, 0x75, ++ 0x42, 0x7b, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, ++ 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x69, 0x74, 0x65, 0x2e, 0x69, ++ 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, ++ 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, ++ 0x6c, 0x69, 0x74, 0x65, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1e, 0x56, ++ 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, ++ 0x56, 0x6c, 0x69, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/vlite/outbound/config.pb.go b/proxy/vlite/outbound/config.pb.go +index b4e4e79cf..443e4f99c 100644 +--- a/proxy/vlite/outbound/config.pb.go ++++ b/proxy/vlite/outbound/config.pb.go +@@ -130,7 +130,7 @@ var file_proxy_vlite_outbound_config_proto_rawDesc = []byte{ + 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x22, 0x8f, 0x03, 0x0a, 0x11, 0x55, 0x44, 0x50, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, ++ 0x22, 0x8b, 0x03, 0x0a, 0x11, 0x55, 0x44, 0x50, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, +@@ -153,17 +153,17 @@ var file_proxy_vlite_outbound_config_proto_rawDesc = []byte{ + 0x61, 0x73, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1b, 0x68, 0x61, 0x6e, 0x64, 0x73, + 0x68, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x64, 0x64, 0x69, +- 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x3a, 0x1a, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, 0x75, +- 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, 0xb5, 0x18, 0x08, 0x12, 0x06, 0x76, 0x6c, 0x69, 0x74, +- 0x65, 0x75, 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, +- 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x69, 0x74, 0x65, +- 0x2e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, +- 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, +- 0x79, 0x2f, 0x76, 0x6c, 0x69, 0x74, 0x65, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, +- 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, +- 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x69, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, +- 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x12, 0x0a, 0x08, 0x6f, 0x75, ++ 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x06, 0x76, 0x6c, 0x69, 0x74, 0x65, 0x75, 0x42, 0x7e, ++ 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, ++ 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x69, 0x74, 0x65, 0x2e, 0x6f, 0x75, 0x74, ++ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, ++ 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, ++ 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, ++ 0x69, 0x74, 0x65, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1f, 0x56, ++ 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, ++ 0x56, 0x6c, 0x69, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/vmess/inbound/config.pb.go b/proxy/vmess/inbound/config.pb.go +index e69ea4942..ab0b3b605 100644 +--- a/proxy/vmess/inbound/config.pb.go ++++ b/proxy/vmess/inbound/config.pb.go +@@ -269,20 +269,19 @@ var file_proxy_vmess_inbound_config_proto_rawDesc = []byte{ + 0x75, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x65, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x14, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, +- 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x42, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, ++ 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x3e, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, + 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, + 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x65, +- 0x72, 0x73, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, +- 0x64, 0x82, 0xb5, 0x18, 0x07, 0x12, 0x05, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x42, 0x7b, 0x0a, 0x22, +- 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, +- 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, +- 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, +- 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, +- 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6d, 0x65, 0x73, 0x73, +- 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1e, 0x56, 0x32, 0x52, 0x61, 0x79, +- 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73, +- 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x33, ++ 0x72, 0x73, 0x3a, 0x14, 0x82, 0xb5, 0x18, 0x10, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, ++ 0x64, 0x12, 0x05, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x42, 0x7b, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, ++ 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, ++ 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, ++ 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, ++ 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, ++ 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, ++ 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1e, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, ++ 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x49, 0x6e, ++ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/proxy/vmess/outbound/config.pb.go b/proxy/vmess/outbound/config.pb.go +index 46c4d62ad..1ac3ba66c 100644 +--- a/proxy/vmess/outbound/config.pb.go ++++ b/proxy/vmess/outbound/config.pb.go +@@ -145,7 +145,7 @@ var file_proxy_vmess_outbound_config_proto_rawDesc = []byte{ + 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x52, 0x65, 0x63, +- 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x92, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, ++ 0x65, 0x69, 0x76, 0x65, 0x72, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, + 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, + 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, +@@ -153,17 +153,16 @@ var file_proxy_vmess_outbound_config_proto_rawDesc = []byte{ + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, + 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x3a, +- 0x19, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x82, +- 0xb5, 0x18, 0x07, 0x12, 0x05, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, +- 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, +- 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, +- 0x64, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, +- 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, +- 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2f, +- 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, +- 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73, +- 0x73, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, +- 0x6f, 0x33, ++ 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, ++ 0x05, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x42, 0x7e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, ++ 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, ++ 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, ++ 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, ++ 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2f, 0x6f, 0x75, 0x74, 0x62, ++ 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, ++ 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x4f, 0x75, ++ 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/config.pb.go b/transport/internet/config.pb.go +index 729899015..41f70be7b 100644 +--- a/transport/internet/config.pb.go ++++ b/transport/internet/config.pb.go +@@ -421,6 +421,7 @@ type SocketConfig struct { + RxBufSize int64 `protobuf:"varint,12,opt,name=rx_buf_size,json=rxBufSize,proto3" json:"rx_buf_size,omitempty"` + TxBufSize int64 `protobuf:"varint,13,opt,name=tx_buf_size,json=txBufSize,proto3" json:"tx_buf_size,omitempty"` + ForceBufSize bool `protobuf:"varint,14,opt,name=force_buf_size,json=forceBufSize,proto3" json:"force_buf_size,omitempty"` ++ Mptcp bool `protobuf:"varint,15,opt,name=mptcp,proto3" json:"mptcp,omitempty"` + } + + func (x *SocketConfig) Reset() { +@@ -553,6 +554,13 @@ func (x *SocketConfig) GetForceBufSize() bool { + return false + } + ++func (x *SocketConfig) GetMptcp() bool { ++ if x != nil { ++ return x.Mptcp ++ } ++ return false ++} ++ + var File_transport_internet_config_proto protoreflect.FileDescriptor + + var file_transport_internet_config_proto_rawDesc = []byte{ +@@ -605,7 +613,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, +- 0x22, 0xfd, 0x05, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x22, 0x93, 0x06, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x4e, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +@@ -646,27 +654,29 @@ var file_transport_internet_config_proto_rawDesc = []byte{ + 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x78, 0x42, 0x75, 0x66, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x66, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, +- 0x65, 0x42, 0x75, 0x66, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x35, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x46, +- 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, +- 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, +- 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x22, +- 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, +- 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, +- 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, +- 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, +- 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, +- 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, +- 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, +- 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, +- 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x42, 0x78, 0x0a, 0x21, +- 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, +- 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, +- 0x74, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, +- 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, +- 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, +- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x1d, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, +- 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, +- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x65, 0x42, 0x75, 0x66, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x70, 0x74, 0x63, ++ 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6d, 0x70, 0x74, 0x63, 0x70, 0x22, 0x35, ++ 0x0a, 0x10, 0x54, 0x43, 0x50, 0x46, 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, ++ 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, ++ 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61, ++ 0x62, 0x6c, 0x65, 0x10, 0x02, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, ++ 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, ++ 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, ++ 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, ++ 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, ++ 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, ++ 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f, ++ 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04, ++ 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, ++ 0x10, 0x05, 0x42, 0x78, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, ++ 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, ++ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, ++ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, ++ 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x1d, 0x56, ++ 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, ++ 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/config.proto b/transport/internet/config.proto +index 2478c6f2e..fb0209413 100644 +--- a/transport/internet/config.proto ++++ b/transport/internet/config.proto +@@ -103,4 +103,5 @@ message SocketConfig { + int64 rx_buf_size = 12; + int64 tx_buf_size = 13; + bool force_buf_size = 14; ++ bool mptcp = 15; + } +diff --git a/transport/internet/grpc/config.pb.go b/transport/internet/grpc/config.pb.go +index b424476d9..14035c9db 100644 +--- a/transport/internet/grpc/config.pb.go ++++ b/transport/internet/grpc/config.pb.go +@@ -80,22 +80,22 @@ var file_transport_internet_grpc_config_proto_rawDesc = []byte{ + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x65, 0x6e, 0x63, 0x6f, 0x64, + 0x69, 0x6e, 0x67, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x65, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x6f, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, +- 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x24, 0x82, 0xb5, 0x18, 0x0b, 0x0a, 0x09, 0x74, 0x72, +- 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x82, 0xb5, 0x18, 0x06, 0x12, 0x04, 0x67, 0x72, 0x70, +- 0x63, 0x82, 0xb5, 0x18, 0x07, 0x8a, 0xff, 0x29, 0x03, 0x67, 0x75, 0x6e, 0x42, 0x85, 0x01, 0x0a, +- 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, +- 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, +- 0x65, 0x74, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, +- 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, +- 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, +- 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, +- 0x02, 0x22, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, +- 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, +- 0x47, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x1c, 0x82, 0xb5, 0x18, 0x18, 0x0a, 0x09, 0x74, 0x72, ++ 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x04, 0x67, 0x72, 0x70, 0x63, 0x8a, 0xff, 0x29, ++ 0x03, 0x67, 0x75, 0x6e, 0x42, 0x85, 0x01, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, ++ 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, ++ 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, ++ 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, ++ 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, ++ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, ++ 0x65, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, 0x02, 0x22, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, ++ 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, ++ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x47, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/grpc/encoding/stream_grpc.pb.go b/transport/internet/grpc/encoding/stream_grpc.pb.go +index c4464eb7c..2859c424e 100644 +--- a/transport/internet/grpc/encoding/stream_grpc.pb.go ++++ b/transport/internet/grpc/encoding/stream_grpc.pb.go +@@ -12,6 +12,10 @@ import ( + // Requires gRPC-Go v1.32.0 or later. + const _ = grpc.SupportPackageIsVersion7 + ++const ( ++ GunService_Tun_FullMethodName = "/v2ray.core.transport.internet.grpc.encoding.GunService/Tun" ++) ++ + // GunServiceClient is the client API for GunService service. + // + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +@@ -28,7 +32,7 @@ func NewGunServiceClient(cc grpc.ClientConnInterface) GunServiceClient { + } + + func (c *gunServiceClient) Tun(ctx context.Context, opts ...grpc.CallOption) (GunService_TunClient, error) { +- stream, err := c.cc.NewStream(ctx, &GunService_ServiceDesc.Streams[0], "/v2ray.core.transport.internet.grpc.encoding.GunService/Tun", opts...) ++ stream, err := c.cc.NewStream(ctx, &GunService_ServiceDesc.Streams[0], GunService_Tun_FullMethodName, opts...) + if err != nil { + return nil, err + } +diff --git a/transport/internet/kcp/config.pb.go b/transport/internet/kcp/config.pb.go +index 1f422e8f2..e9c171632 100644 +--- a/transport/internet/kcp/config.pb.go ++++ b/transport/internet/kcp/config.pb.go +@@ -539,7 +539,7 @@ var file_transport_internet_kcp_config_proto_rawDesc = []byte{ + 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x22, 0x24, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x65, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x09, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x22, 0xab, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, ++ 0x09, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x22, 0xa3, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x38, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, +@@ -579,19 +579,18 @@ var file_transport_internet_kcp_config_proto_rawDesc = []byte{ + 0x32, 0x31, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, + 0x2e, 0x6b, 0x63, 0x70, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, +- 0x65, 0x65, 0x64, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x3a, 0x24, 0x82, 0xb5, 0x18, 0x0b, 0x0a, +- 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x82, 0xb5, 0x18, 0x05, 0x12, 0x03, +- 0x6b, 0x63, 0x70, 0x82, 0xb5, 0x18, 0x08, 0x8a, 0xff, 0x29, 0x04, 0x6d, 0x6b, 0x63, 0x70, 0x4a, +- 0x04, 0x08, 0x09, 0x10, 0x0a, 0x42, 0x84, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, +- 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x6b, 0x63, 0x70, 0x50, +- 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, +- 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, +- 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, +- 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x63, 0x70, 0xaa, 0x02, 0x21, 0x56, 0x32, 0x52, 0x61, 0x79, +- 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, +- 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x4b, 0x63, 0x70, 0x62, 0x06, 0x70, 0x72, +- 0x6f, 0x74, 0x6f, 0x33, ++ 0x65, 0x65, 0x64, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x3a, 0x1c, 0x82, 0xb5, 0x18, 0x18, 0x0a, ++ 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x03, 0x6b, 0x63, 0x70, 0x8a, ++ 0xff, 0x29, 0x04, 0x6d, 0x6b, 0x63, 0x70, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x42, 0x84, 0x01, ++ 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, ++ 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, ++ 0x6e, 0x65, 0x74, 0x2e, 0x6b, 0x63, 0x70, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, ++ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, ++ 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, ++ 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x63, 0x70, ++ 0xaa, 0x02, 0x21, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, ++ 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, ++ 0x2e, 0x4b, 0x63, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/quic/config.pb.go b/transport/internet/quic/config.pb.go +index 020769035..77d44ee36 100644 +--- a/transport/internet/quic/config.pb.go ++++ b/transport/internet/quic/config.pb.go +@@ -93,7 +93,7 @@ var file_transport_internet_quic_config_proto_rawDesc = []byte{ + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xab, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +@@ -102,18 +102,18 @@ var file_transport_internet_quic_config_proto_rawDesc = []byte{ + 0x67, 0x52, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, +- 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x0b, 0x0a, +- 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x82, 0xb5, 0x18, 0x06, 0x12, 0x04, +- 0x71, 0x75, 0x69, 0x63, 0x42, 0x87, 0x01, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, +- 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, +- 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x71, 0x75, 0x69, 0x63, 0x50, +- 0x01, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, +- 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, +- 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, +- 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x71, 0x75, 0x69, 0x63, 0xaa, 0x02, 0x22, 0x56, 0x32, 0x52, 0x61, +- 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, +- 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x51, 0x75, 0x69, 0x63, 0x62, 0x06, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, ++ 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x04, 0x71, 0x75, 0x69, 0x63, ++ 0x42, 0x87, 0x01, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, ++ 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, ++ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x71, 0x75, 0x69, 0x63, 0x50, 0x01, 0x5a, 0x36, 0x67, ++ 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, ++ 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, ++ 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, ++ 0x2f, 0x71, 0x75, 0x69, 0x63, 0xaa, 0x02, 0x22, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, ++ 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, ++ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x51, 0x75, 0x69, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go +index 96bb0eca1..6d1ef7392 100644 +--- a/transport/internet/system_dialer.go ++++ b/transport/internet/system_dialer.go +@@ -72,17 +72,19 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne + LocalAddr: resolveSrcAddr(dest.Network, src), + KeepAlive: goStdKeepAlive, + } +- if dialer.MultipathTCP() { +- newError("Outbound MultipathTCP is enable").WriteToLog(session.ExportIDToError(ctx)) +- } else { +- newError("Outbound MultipathTCP is disable,we are enable it").WriteToLog(session.ExportIDToError(ctx)) +- dialer.SetMultipathTCP(true) // 主动启用mptcp +- } + + if sockopt != nil || len(d.controllers) > 0 { + dialer.Control = func(network, address string, c syscall.RawConn) error { + return c.Control(func(fd uintptr) { + if sockopt != nil { ++ if dest.Network == net.Network_TCP && sockopt.Mptcp { ++ if dialer.MultipathTCP() { ++ newError("Dialer MultipathTCP is enable").WriteToLog(session.ExportIDToError(ctx)) ++ } else { ++ newError("Dialer MultipathTCP is disable,we are enable it").WriteToLog(session.ExportIDToError(ctx)) ++ dialer.SetMultipathTCP(true) // 主动启用mptcp ++ } ++ } + if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil { + newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx)) + } +diff --git a/transport/internet/system_listener.go b/transport/internet/system_listener.go +index 74e48130a..d9d97647a 100644 +--- a/transport/internet/system_listener.go ++++ b/transport/internet/system_listener.go +@@ -45,12 +45,6 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S + var l net.Listener + var err error + var network, address string +- if lc.MultipathTCP() { +- newError("MultipathTCP is enable").WriteToLog(session.ExportIDToError(ctx)) +- } else { +- newError("MultipathTCP is disable,we are enable it").WriteToLog(session.ExportIDToError(ctx)) +- lc.SetMultipathTCP(true) // 主动启用mptcp +- } + switch addr := addr.(type) { + case *net.TCPAddr: + network = addr.Network() +@@ -59,6 +53,14 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S + if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) { + lc.KeepAlive = time.Duration(-1) + } ++ if sockopt != nil && sockopt.Mptcp { ++ if lc.MultipathTCP() { ++ newError("Listener MultipathTCP is enable").WriteToLog(session.ExportIDToError(ctx)) ++ } else { ++ newError("Listener MultipathTCP is disable,we are enable it").WriteToLog(session.ExportIDToError(ctx)) ++ lc.SetMultipathTCP(true) // 主动启用mptcp ++ } ++ } + case *net.UnixAddr: + lc.Control = nil + network = addr.Network() +diff --git a/transport/internet/tcp/config.pb.go b/transport/internet/tcp/config.pb.go +index 34fbfd43c..5d3da8994 100644 +--- a/transport/internet/tcp/config.pb.go ++++ b/transport/internet/tcp/config.pb.go +@@ -82,7 +82,7 @@ var file_transport_internet_tcp_config_proto_rawDesc = []byte{ + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9b, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x97, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x3d, 0x0a, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, +@@ -90,18 +90,17 @@ var file_transport_internet_tcp_config_proto_rawDesc = []byte{ + 0x32, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, + 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, +- 0x63, 0x6f, 0x6c, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x0b, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, +- 0x70, 0x6f, 0x72, 0x74, 0x82, 0xb5, 0x18, 0x05, 0x12, 0x03, 0x74, 0x63, 0x70, 0x4a, 0x04, 0x08, +- 0x01, 0x10, 0x02, 0x42, 0x84, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, +- 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, +- 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x63, 0x70, 0x50, 0x01, 0x5a, +- 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, +- 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, +- 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, +- 0x65, 0x74, 0x2f, 0x74, 0x63, 0x70, 0xaa, 0x02, 0x21, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, +- 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, +- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x63, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, +- 0x6f, 0x33, ++ 0x63, 0x6f, 0x6c, 0x3a, 0x14, 0x82, 0xb5, 0x18, 0x10, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, ++ 0x70, 0x6f, 0x72, 0x74, 0x12, 0x03, 0x74, 0x63, 0x70, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x42, ++ 0x84, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, ++ 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, ++ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x63, 0x70, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, ++ 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, ++ 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, ++ 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, ++ 0x63, 0x70, 0xaa, 0x02, 0x21, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, ++ 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, ++ 0x65, 0x74, 0x2e, 0x54, 0x63, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/tls/config.pb.go b/transport/internet/tls/config.pb.go +index 09ca99b63..3c399854d 100644 +--- a/transport/internet/tls/config.pb.go ++++ b/transport/internet/tls/config.pb.go +@@ -294,7 +294,7 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{ + 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, + 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x41, 0x55, 0x54, 0x48, + 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x5f, 0x43, 0x4c, 0x49, +- 0x45, 0x4e, 0x54, 0x10, 0x03, 0x22, 0xe0, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, ++ 0x45, 0x4e, 0x54, 0x10, 0x03, 0x22, 0xdc, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x2d, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x06, 0x82, 0xb5, 0x18, 0x02, 0x28, 0x01, + 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, +@@ -323,17 +323,17 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{ + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, +- 0x17, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x82, +- 0xb5, 0x18, 0x05, 0x12, 0x03, 0x74, 0x6c, 0x73, 0x42, 0x84, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, +- 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, +- 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, +- 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, +- 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, +- 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, +- 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x21, 0x56, 0x32, +- 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, +- 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, 0x62, +- 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x13, 0x82, 0xb5, 0x18, 0x0f, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, ++ 0x03, 0x74, 0x6c, 0x73, 0x42, 0x84, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, ++ 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, ++ 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x50, 0x01, ++ 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, ++ 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, ++ 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, ++ 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x21, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, ++ 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, ++ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/tls/utls/config.pb.go b/transport/internet/tls/utls/config.pb.go +index 295e2eadf..057eeb7d8 100644 +--- a/transport/internet/tls/utls/config.pb.go ++++ b/transport/internet/tls/utls/config.pb.go +@@ -148,7 +148,7 @@ var file_transport_internet_tls_utls_config_proto_rawDesc = []byte{ + 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x6e, +- 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xef, 0x01, 0x0a, 0x06, 0x43, 0x6f, ++ 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xeb, 0x01, 0x0a, 0x06, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x48, 0x0a, 0x0a, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, +@@ -162,23 +162,23 @@ var file_transport_internet_tls_utls_config_proto_rawDesc = []byte{ + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x2e, 0x75, 0x74, 0x6c, 0x73, 0x2e, 0x46, 0x6f, 0x72, 0x63, + 0x65, 0x64, 0x41, 0x4c, 0x50, 0x4e, 0x52, 0x09, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x41, 0x6c, 0x70, +- 0x6e, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, +- 0x79, 0x82, 0xb5, 0x18, 0x06, 0x12, 0x04, 0x75, 0x74, 0x6c, 0x73, 0x2a, 0x52, 0x0a, 0x0a, 0x46, +- 0x6f, 0x72, 0x63, 0x65, 0x64, 0x41, 0x4c, 0x50, 0x4e, 0x12, 0x26, 0x0a, 0x22, 0x54, 0x52, 0x41, +- 0x4e, 0x53, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, +- 0x45, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, +- 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x4f, 0x5f, 0x41, 0x4c, 0x50, 0x4e, 0x10, 0x01, 0x12, 0x0f, +- 0x0a, 0x0b, 0x55, 0x54, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x42, +- 0x93, 0x01, 0x0a, 0x2a, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, +- 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, +- 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x2e, 0x75, 0x74, 0x6c, 0x73, 0x50, 0x01, +- 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, +- 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, +- 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, +- 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0x2f, 0x75, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x26, 0x56, +- 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, +- 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, +- 0x2e, 0x55, 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x6e, 0x3a, 0x14, 0x82, 0xb5, 0x18, 0x10, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, ++ 0x79, 0x12, 0x04, 0x75, 0x74, 0x6c, 0x73, 0x2a, 0x52, 0x0a, 0x0a, 0x46, 0x6f, 0x72, 0x63, 0x65, ++ 0x64, 0x41, 0x4c, 0x50, 0x4e, 0x12, 0x26, 0x0a, 0x22, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x4f, ++ 0x52, 0x54, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x5f, 0x54, 0x41, ++ 0x4b, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x00, 0x12, 0x0b, 0x0a, ++ 0x07, 0x4e, 0x4f, 0x5f, 0x41, 0x4c, 0x50, 0x4e, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x54, ++ 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x42, 0x93, 0x01, 0x0a, 0x2a, ++ 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, ++ 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, ++ 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x2e, 0x75, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, ++ 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, ++ 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, ++ 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, ++ 0x74, 0x6c, 0x73, 0x2f, 0x75, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x26, 0x56, 0x32, 0x52, 0x61, 0x79, ++ 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, ++ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, 0x2e, 0x55, 0x54, 0x6c, ++ 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( +diff --git a/transport/internet/websocket/config.pb.go b/transport/internet/websocket/config.pb.go +index 5b03acb7e..ff62bc2fa 100644 +--- a/transport/internet/websocket/config.pb.go ++++ b/transport/internet/websocket/config.pb.go +@@ -171,7 +171,7 @@ var file_transport_internet_websocket_config_proto_rawDesc = []byte{ + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x30, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, +- 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xda, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, ++ 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd2, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x47, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, +@@ -190,20 +190,19 @@ var file_transport_internet_websocket_config_proto_rawDesc = []byte{ + 0x12, 0x33, 0x0a, 0x16, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x13, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x44, 0x61, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, +- 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x28, 0x82, 0xb5, 0x18, 0x0b, 0x0a, 0x09, 0x74, 0x72, 0x61, +- 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x82, 0xb5, 0x18, 0x04, 0x12, 0x02, 0x77, 0x73, 0x82, 0xb5, +- 0x18, 0x0d, 0x8a, 0xff, 0x29, 0x09, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4a, +- 0x04, 0x08, 0x01, 0x10, 0x02, 0x42, 0x96, 0x01, 0x0a, 0x2b, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, +- 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, +- 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x77, 0x65, 0x62, 0x73, +- 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, +- 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, +- 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, +- 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, +- 0x63, 0x6b, 0x65, 0x74, 0xaa, 0x02, 0x27, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, +- 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, +- 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x62, 0x06, +- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ++ 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x82, 0xb5, 0x18, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x61, ++ 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x02, 0x77, 0x73, 0x8a, 0xff, 0x29, 0x09, 0x77, 0x65, ++ 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x42, 0x96, 0x01, ++ 0x0a, 0x2b, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, ++ 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, ++ 0x6e, 0x65, 0x74, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x01, 0x5a, ++ 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, ++ 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, ++ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, ++ 0x65, 0x74, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0xaa, 0x02, 0x27, 0x56, ++ 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, ++ 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x57, 0x65, 0x62, ++ 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + } + + var ( From 2ea4a49e4ad58d1d6f6dc14b6c7d3fb7601471b6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Aug 2023 12:51:50 +0200 Subject: [PATCH 1014/2059] Remove warning about v2ray on 6.1 --- .../luasrc/view/openmptcprouter/wizard.htm | 3 --- 1 file changed, 3 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index d81f88551..69d7b5a81 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -240,9 +240,6 @@
    <%:Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and UDP when V2Ray is enabled.%> <%:Only ShadowSocks is supported with server multiple IPs for now.%> - <% if uname.release:sub(1,4) == "5.15" or uname.release:sub(1,1) == "6" then %> -
    <%:V2Ray doesn't support aggregation on Kernel > 5.4 yet.%> - <% end %>
    From 466e3762ce5d66c80700a1792f3b470bb5063a1d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Aug 2023 19:36:00 +0200 Subject: [PATCH 1015/2059] Use latest glorytun fork changes --- glorytun/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glorytun/Makefile b/glorytun/Makefile index 95d7ed3aa..e197e17fa 100644 --- a/glorytun/Makefile +++ b/glorytun/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=glorytun PKG_RELEASE:=6 PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=6d58536f4232fea8eaa10fb60aace8ba11f29ed6 +PKG_SOURCE_VERSION:=1af1e26ad7a325d891c27f5cf9832c1ce4b4d0e9 PKG_SOURCE:=glorytun-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/Ysurac/glorytun.git PKG_VERSION:=0.0.35-$(PKG_SOURCE_VERSION) From c6f95542661da02c6d86fda7d53eed6280d517ce Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Aug 2023 19:36:35 +0200 Subject: [PATCH 1016/2059] Fix depends for om-bypass --- luci-app-omr-bypass/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index 2969ef549..7b83f4c8c 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +iptables-mod-extra +iptables +sqlite3-cli -ifneq ($(CONFIG_TARGET_ramips),) +ifneq ($(CONFIG_TARGET_ramips),y) #LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi LUCI_DEPENDS+=+iptables-mod-ndpi +kmod-ipt-ndpi endif From 83719131be7ff86de19618793d6fa7bb84f766ff Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 2 Aug 2023 19:36:55 +0200 Subject: [PATCH 1017/2059] Increase OMRVPN MTU --- mptcp/files/etc/init.d/mptcp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index f870963e3..d83b12b1d 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -77,9 +77,9 @@ interface_max_metric() { fi elif [ "$1" = "omrvpn" ]; then uci -q batch <<-EOF >/dev/null - set network.${config}.metric=1200 + set network.${config}.metric=9000 commit network - set openmptcprouter.${config}.metric=1200 + set openmptcprouter.${config}.metric=9000 commit openmptcprouter EOF elif [ "$1" = "omr6in4" ]; then From e8f8d6c5b682ec4f1718492d955f9d8ae023f506 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 3 Aug 2023 19:15:41 +0200 Subject: [PATCH 1018/2059] Fix and add entry in json for status page --- luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index cec97258f..8dade3146 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -744,6 +744,7 @@ function interfaces_status() mArray.openmptcprouter["latest_version_omr"] = uci:get("openmptcprouter", "latest_versions", "omr") or "" mArray.openmptcprouter["latest_version_vps"] = uci:get("openmptcprouter", "latest_versions", "vps") or "" + mArray.openmptcprouter["proxy"] = uci:get("openmptcprouter", "settings", "proxy") or "" mArray.openmptcprouter["service_addr"] = uci:get("shadowsocks-libev", "sss0", "server") or "" if mArray.openmptcprouter["service_addr"] == "" or mArray.openmptcprouter["service_addr"] == "192.168.1.3" then @@ -761,7 +762,7 @@ function interfaces_status() mArray.openmptcprouter["local_addr"] = ipaddr --mArray.openmptcprouter["local_addr"] = uci:get("network", "lan", "ipaddr") mArray.openmptcprouter["hostname"] = "OpenMPTCProuter" - mArray.openmptcprouter["kernel"] = sys.exec("uname -r") + mArray.openmptcprouter["kernel"] = sys.exec("uname -r | tr -d '\n'") ucic:foreach("system", "system", function(s) mArray.openmptcprouter["hostname"] = uci:get("system",s[".name"],"hostname") or "OpenMPTCProuter" end) From 2883f879fddc84c46662741a23fea04dcbf7cdb0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 3 Aug 2023 19:16:25 +0200 Subject: [PATCH 1019/2059] Fix issue when v2ray already set on router with fresh VPS install --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 8bb124ac0..2a953d748 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1360,8 +1360,8 @@ _set_config_from_vps() { fi # Shadowsocks settings - shadowsocks_disabled="$(uci -q get openmptcprouter.settings.shadowsocks_disable)" - [ -z "$shadowsocks_disabled" ] && shadowsocks_disabled=0 + #shadowsocks_disabled="$(uci -q get openmptcprouter.settings.shadowsocks_disable)" + #[ -z "$shadowsocks_disabled" ] && shadowsocks_disabled=0 ss_key="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.key')" ss_key="$(echo $ss_key | sed 's/-/+/g; s/_/\//g;')" if [ -n "$ss_key" ] && [ "$ss_key" != "$(uci -q get shadowsocks-libev.sss0.key)" ]; then @@ -1397,7 +1397,6 @@ _set_config_from_vps() { set shadowsocks-libev.sss0.key=$ss_key set shadowsocks-libev.sss0.server_port=$ss_port set shadowsocks-libev.sss0.method=$ss_method - set shadowsocks-libev.sss0.disabled=$shadowsocks_disabled set shadowsocks-libev.sss0.obfs=$ss_obfs set shadowsocks-libev.sss0.obfs_plugin=$ss_obfs_plugin set shadowsocks-libev.sss0.obfs_type=$ss_obfs_type From 89f028597d4e205d12e79983f58439e885c647c2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Aug 2023 22:19:59 +0200 Subject: [PATCH 1020/2059] Various changes for 6.1 kernel in MPTCP interface --- luci-app-mptcp/luasrc/controller/mptcp.lua | 6 ++++-- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 16 ++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index 842adc6ef..89bc92c13 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -15,8 +15,10 @@ function index() entry({"admin", "network", "mptcp", "mptcp_check_trace"}, post("mptcp_check_trace")).leaf = true entry({"admin", "network", "mptcp", "mptcp_fullmesh"}, template("mptcp/mptcp_fullmesh"), _("MPTCP Fullmesh"), 5).leaf = true entry({"admin", "network", "mptcp", "mptcp_fullmesh_data"}, post("mptcp_fullmesh_data")).leaf = true - entry({"admin", "network", "mptcp", "mptcp_connections"}, template("mptcp/mptcp_connections"), _("Established connections"), 6).leaf = true - entry({"admin", "network", "mptcp", "mptcp_connections_data"}, post("mptcp_connections_data")).leaf = true + if nixio.uname().release:sub(1,4) ~= "5.15" and nixio.uname().release:sub(1,1) ~= "6" then + entry({"admin", "network", "mptcp", "mptcp_connections"}, template("mptcp/mptcp_connections"), _("Established connections"), 6).leaf = true + entry({"admin", "network", "mptcp", "mptcp_connections_data"}, post("mptcp_connections_data")).leaf = true + end entry({"admin", "network", "mptcp", "mptcp_monitor"}, template("mptcp/mptcp_monitor"), _("MPTCP monitoring"), 6).leaf = true entry({"admin", "network", "mptcp", "mptcp_monitor_data"}, post("mptcp_monitor_data")).leaf = true end diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index a36c3d391..d5fe52f9c 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -61,22 +61,22 @@ end -- if tonumber(uname.release:sub(1,4)) >= 5.15 then if uname.release:sub(1,4) == "5.15" or uname.release:sub(1,1) == "6" then - o = s:option(Value, "mptcp_subflows", translate("specifies the maximum number of additional subflows allowed for each MPTCP connection")) + o = s:option(Value, "mptcp_subflows", translate("Max subflows"),translate("specifies the maximum number of additional subflows allowed for each MPTCP connection")) o.datatype = "uinteger" o.rmempty = false o.default = 3 - - o = s:option(Value, "mptcp_add_addr_accepted", translate("specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP connection")) - o.datatype = "uinteger" - o.rmempty = false - o.default = 1 - o = s:option(Value, "mptcp_stale_loss_cnt", translate("The number of MPTCP-level retransmission intervals with no traffic and pending outstanding data on a given subflow required to declare it stale")) + o = s:option(Value, "mptcp_stale_loss_cnt", translate("Retranmission intervals"),translate("The number of MPTCP-level retransmission intervals with no traffic and pending outstanding data on a given subflow required to declare it stale")) o.datatype = "uinteger" o.rmempty = false o.default = 4 - o = s:option(Value, "mptcp_add_addr_timeout", translate("Set the timeout after which an ADD_ADDR control message will be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR message.")) + o = s:option(Value, "mptcp_add_addr_accepted", translate("Max add address"),translate("specifies the maximum number of ADD_ADDR (add address) suboptions accepted for each MPTCP connection")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 1 + + o = s:option(Value, "mptcp_add_addr_timeout", translate("Control message timeout"),translate("Set the timeout after which an ADD_ADDR (add address) control message will be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR message.")) o.datatype = "uinteger" o.rmempty = false o.default = 120 From 2b59c7ae22fb7d0bfee56e369900825e49428034 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Aug 2023 22:22:51 +0200 Subject: [PATCH 1021/2059] Fix, add proxy in status json and add encryption in uci settings --- .../luasrc/controller/openmptcprouter.lua | 10 ++++++++-- .../luasrc/view/openmptcprouter/wizard.htm | 9 +++++++-- .../root/usr/libexec/rpcd/openmptcprouter | 4 +++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 5a0cb0566..592abcc89 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -552,7 +552,7 @@ function wizard_add() ucic:set("network","omrvpn","proto","bonding") end if downloadmax ~= 0 and uploadmax ~= 0 then - ucic:set("sqm","omrvpn","enabled","1") + --ucic:set("sqm","omrvpn","enabled","1") ucic:set("sqm","omrvpn","max_download",downloadmax) ucic:set("sqm","omrvpn","max_upload",uploadmax) ucic:set("sqm","omrvpn","download",math.ceil(downloadmax*50/100)) @@ -619,7 +619,7 @@ function wizard_add() ucic:set("openmptcprouter",server,"username",openmptcprouter_vps_username:gsub("%s+", "")) ucic:set("openmptcprouter",server,"password",openmptcprouter_vps_key:gsub("%s+", "")) ucic:set("openmptcprouter",server,"disabled",openmptcprouter_vps_disabled) - if ucic:get("openmptcprouter",server,"ip") ~= aserverips then + if ucic:get_list("openmptcprouter",server,"ip") ~= aserverips then ucic:set_list("openmptcprouter",server,"ip",aserverips) if ucic:get("openmptcprouter",server,"master") == "1" then ucic:set("openmptcprouter",server,"get_config","1") @@ -805,6 +805,7 @@ function wizard_add() local encryption = luci.http.formvalue("encryption") if encryption == "none" then + ucic:set("openmptcprouter","settings","encryption","none") ucic:set("shadowsocks-libev","sss0","method","none") ucic:set("shadowsocks-libev","sss1","method","none") ucic:set("openvpn","omr","cipher","none") @@ -812,6 +813,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_vmess_user_security","none") ucic:set("v2ray","omrout","s_vless_user_security","none") elseif encryption == "aes-256-gcm" then + ucic:set("openmptcprouter","settings","encryption","aes-256-gcm") ucic:set("shadowsocks-libev","sss0","method","aes-256-gcm") ucic:set("shadowsocks-libev","sss1","method","aes-256-gcm") ucic:set("glorytun","vpn","chacha20","0") @@ -821,6 +823,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_vmess_user_security","aes-128-gcm") ucic:set("v2ray","omrout","s_vless_user_security","aes-128-gcm") elseif encryption == "aes-256-cfb" then + ucic:set("openmptcprouter","settings","encryption","aes-256-cfb") ucic:set("shadowsocks-libev","sss0","method","aes-256-cfb") ucic:set("shadowsocks-libev","sss1","method","aes-256-cfb") ucic:set("glorytun","vpn","chacha20","0") @@ -830,6 +833,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_vmess_user_security","aes-128-gcm") ucic:set("v2ray","omrout","s_vless_user_security","aes-128-gcm") elseif encryption == "chacha20-ietf-poly1305" then + ucic:set("openmptcprouter","settings","encryption","chacha20") ucic:set("shadowsocks-libev","sss0","method","chacha20-ietf-poly1305") ucic:set("shadowsocks-libev","sss1","method","chacha20-ietf-poly1305") ucic:set("glorytun","vpn","chacha20","1") @@ -838,6 +842,8 @@ function wizard_add() ucic:set("mlvpn","general","cleartext_data","0") ucic:set("v2ray","omrout","s_vmess_user_security","chacha20-poly1305") ucic:set("v2ray","omrout","s_vless_user_security","chacha20-poly1305") + else + ucic:set("openmptcprouter","settings","encryption","other") end ucic:save("openvpn") ucic:save("glorytun") diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 69d7b5a81..6b005fe5b 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -269,13 +269,18 @@

    diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 8dade3146..fc7a71dec 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1035,7 +1035,9 @@ function interfaces_status() mArray.openmptcprouter["multi_vpn"] = true end end - + if uci:get("openmptcprouter","settings","vpn") ~= "none" then + mArray.openmptcprouter["vpn"]= uci:get("openmptcprouter","settings","vpn") + end -- check Shadowsocks is running mArray.openmptcprouter["shadowsocks_service"] = false if string.find(sys.exec("/usr/bin/pgrep ss-redir"), "%d+") then From 8e2f33ac32df446f200c5e25a05fe454b64434c9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Aug 2023 22:23:43 +0200 Subject: [PATCH 1022/2059] Some fix on encryption --- .../files/etc/init.d/openmptcprouter-vps | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 2a953d748..8955b5ff2 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -107,6 +107,7 @@ _set_json() { _set_glorytun_vps() { local enabled port key enabled="$(uci -q get glorytun.vpn.enable)" + [ "$enabled" != "1" ] && enabled="$(uci -q get glorytun-udp.vpn.enable)" [ "$enabled" != "1" ] && echo "Glorytun disabled" && return port="$(uci -q get glorytun.vpn.port)" key="$(uci -q get glorytun.vpn.key)" @@ -1909,17 +1910,16 @@ _config_service() { [ "$(uci -q get openmptcprouter.${servername}.master)" = "1" ] && { _get_vps_config } - [ -z "$vps_config" ] && vps_config=$(_get_json "config") - [ -z "$vps_config" ] && return - user_permission="$(echo "$vps_config" | jsonfilter -q -e '@.user.permission')" if [ "$(uci -q get openmptcprouter.settings.firstboot)" != "0" ]; then - [ -n "$vps_config" ] && [ -n "$(cat /proc/cpuinfo | grep aes)" ] && { + [ -n "$(cat /proc/cpuinfo | grep aes)" ] && { vps_aes="$(echo "$vps_config" | jsonfilter -q -e '@.vps.aes')" if [ "$vps_aes" != "false" ] && [ "$user_permission" != "ro" ]; then logger -t "OMR-VPS" "CPU support AES, set it by default" method="$(uci -q get shadowsocks-libev.sss0.method)" uci -q batch <<-EOF >/dev/null + set openmptcprouter.settings.encryption="aes-256-gcm" + commit openmptcprouter set glorytun.vpn.chacha20="0" commit glorytun set glorytun-udp.vpn.chacha="0" @@ -1934,6 +1934,11 @@ _config_service() { fi } fi + + [ -z "$vps_config" ] && vps_config=$(_get_json "config") + [ -z "$vps_config" ] && return + user_permission="$(echo "$vps_config" | jsonfilter -q -e '@.user.permission')" + if [ "$user_permission" != "ro" ]; then #config_load shadowsocks-libev #config_foreach _set_ss_server_vps server From b67619a38ba8d6dc807256938d0aa622fcdc5704 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 4 Aug 2023 22:24:01 +0200 Subject: [PATCH 1023/2059] Change diag website --- openmptcprouter/files/etc/uci-defaults/1950-omr-diag | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1950-omr-diag b/openmptcprouter/files/etc/uci-defaults/1950-omr-diag index cd944c24f..efefd08a7 100755 --- a/openmptcprouter/files/etc/uci-defaults/1950-omr-diag +++ b/openmptcprouter/files/etc/uci-defaults/1950-omr-diag @@ -2,9 +2,9 @@ uci -q batch <<-EOF >/dev/null set luci.diag=internal - set luci.diag.ping="openmptcprouter.com" - set luci.diag.dns="openmptcprouter.com" - set luci.diag.route="openmptcprouter.com" + set luci.diag.ping="www.openmptcprouter.com" + set luci.diag.dns="www.openmptcprouter.com" + set luci.diag.route="www.openmptcprouter.com" set luci.diag.iperf3="ping-ams1.online.net" set luci.diag.getip="ip.openmptcprouter.com" commit luci From 7adc290974b7089b39b23a32dbb4f218002d7a64 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 8 Aug 2023 12:49:14 +0200 Subject: [PATCH 1024/2059] Various changes for 6.1 in MPTCP Luci interface --- luci-app-mptcp/luasrc/controller/mptcp.lua | 6 ++---- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index 89bc92c13..842adc6ef 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -15,10 +15,8 @@ function index() entry({"admin", "network", "mptcp", "mptcp_check_trace"}, post("mptcp_check_trace")).leaf = true entry({"admin", "network", "mptcp", "mptcp_fullmesh"}, template("mptcp/mptcp_fullmesh"), _("MPTCP Fullmesh"), 5).leaf = true entry({"admin", "network", "mptcp", "mptcp_fullmesh_data"}, post("mptcp_fullmesh_data")).leaf = true - if nixio.uname().release:sub(1,4) ~= "5.15" and nixio.uname().release:sub(1,1) ~= "6" then - entry({"admin", "network", "mptcp", "mptcp_connections"}, template("mptcp/mptcp_connections"), _("Established connections"), 6).leaf = true - entry({"admin", "network", "mptcp", "mptcp_connections_data"}, post("mptcp_connections_data")).leaf = true - end + entry({"admin", "network", "mptcp", "mptcp_connections"}, template("mptcp/mptcp_connections"), _("Established connections"), 6).leaf = true + entry({"admin", "network", "mptcp", "mptcp_connections_data"}, post("mptcp_connections_data")).leaf = true entry({"admin", "network", "mptcp", "mptcp_monitor"}, template("mptcp/mptcp_monitor"), _("MPTCP monitoring"), 6).leaf = true entry({"admin", "network", "mptcp", "mptcp_monitor_data"}, post("mptcp_monitor_data")).leaf = true end diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index d5fe52f9c..e8f827bee 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -15,9 +15,13 @@ o:value("disable", translate("disable")) o = s:option(ListValue, "mptcp_checksum", translate("Multipath TCP checksum")) o:value(1, translate("enable")) o:value(0, translate("disable")) -o = s:option(ListValue, "mptcp_debug", translate("Multipath Debug")) -o:value(1, translate("enable")) -o:value(0, translate("disable")) + +if uname.release:sub(1,4) ~= "5.15" and uname.release:sub(1,1) ~= "6" then + o = s:option(ListValue, "mptcp_debug", translate("Multipath Debug")) + o:value(1, translate("enable")) + o:value(0, translate("disable")) +end + o = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager"), translate("Default is fullmesh")) o:value("default", translate("default")) o:value("fullmesh", "fullmesh") @@ -61,12 +65,17 @@ end -- if tonumber(uname.release:sub(1,4)) >= 5.15 then if uname.release:sub(1,4) == "5.15" or uname.release:sub(1,1) == "6" then + o = s:option(ListValue, "mptcp_pm_type", translate("Path Manager type")) + o:value(0, translate("In-kernel path manager")) + o:value(1, translate("Userspace path manager")) + o.default = 0 + o = s:option(Value, "mptcp_subflows", translate("Max subflows"),translate("specifies the maximum number of additional subflows allowed for each MPTCP connection")) o.datatype = "uinteger" o.rmempty = false o.default = 3 - o = s:option(Value, "mptcp_stale_loss_cnt", translate("Retranmission intervals"),translate("The number of MPTCP-level retransmission intervals with no traffic and pending outstanding data on a given subflow required to declare it stale")) + o = s:option(Value, "mptcp_stale_loss_cnt", translate("Retranmission intervals"),translate("The number of MPTCP-level retransmission intervals with no traffic and pending outstanding data on a given subflow required to declare it stale. A low stale_loss_cnt value allows for fast active-backup switch-over, an high value maximize links utilization on edge scenarios e.g. lossy link with high BER or peer pausing the data processing.")) o.datatype = "uinteger" o.rmempty = false o.default = 4 From 19b447669e8cdab1124adb1a38d1aa138e0f9717 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 8 Aug 2023 12:49:45 +0200 Subject: [PATCH 1025/2059] Fix on MPTCP settings --- mptcp/files/etc/init.d/mptcp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index d83b12b1d..5c0c43d8e 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -50,6 +50,10 @@ global_multipath_settings() { elif [ -f /proc/sys/net/mptcp/enabled ]; then sysctl -qew net.mptcp.enabled="$multipath_status" ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null + #[ -z "$mptcp_debug" ] || sysctl -qew net.mptcp.mptcp_debug="$mptcp_debug" + [ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.mptcp_checksum="$mptcp_checksum" + [ -z "$mptcp_path_manager" ] || sysctl -qew net.mptcp.mptcp_path_manager="$mptcp_path_manager" + [ -z "$mptcp_scheduler" ] || sysctl -qew net.mptcp.mptcp_scheduler="$mptcp_scheduler" [ -z "$mptcp_add_addr_timeout" ] || sysctl -qew net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" [ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.checksum_enabled="$mptcp_checksum" [ -z "$mptcp_stale_loss_cnt" ] || sysctl -qew net.mptcp.stale_loss_cnt="$mptcp_stale_loss_cnt" From da603e93109584d86da7c27c62334c170f75d27c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 8 Aug 2023 12:50:39 +0200 Subject: [PATCH 1026/2059] Add upload support to server speed test --- openmptcprouter/files/bin/omr-test-speed | 29 +++++++++---- .../files/bin/omr-test-speed-server | 42 ++++++++++++++----- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index ab8e1a929..2aaf3b72b 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -1,19 +1,25 @@ #!/bin/sh -# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : +# (c) Yannick Chabanois (ycarus@zugaina.org) for OpenMPTCProuter +# +# + FORCEVPS=false +FASTTEST=false if [ "$1" = "forcevps" ]; then - INTERFACE="$2" FORCEVPS=true -else - INTERFACE="$1" fi +if [ "$1" = "fasttest" ]; then + FASTTEST=true +fi +for i in $@; do :; done +INTERFACE="$i" [ -n "$INTERFACE" ] && [ ! -d "/sys/class/net/$INTERFACE" ] && { echo "You must use a real interface. You wan find them using 'ip a' for example" exit 0 } -echo "Select best test server..." +[ "$FASTTEST" ] || echo "Select best test server..." HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://speedtest.milkywan.fr/files/10G.iso" bestping="9999" for pinghost in $HOSTLST; do @@ -23,7 +29,7 @@ for pinghost in $HOSTLST; do else ping=$(ping -4 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') fi - echo "host: $domain - ping: $ping" + [ "$FASTTEST" ] || echo "host: $domain - ping: $ping" if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then bestping=$ping HOST=$pinghost @@ -32,11 +38,12 @@ done [ -z "$HOST" ] && HOST="https://speed.hetzner.de/10GB.bin" -echo "Best server is $HOST, running test:" +[ "$FASTTEST" ] || echo "Best server is $HOST, running test:" trap : HUP INT TERM if [ -z "$INTERFACE" ]; then curl -4 -o /dev/null $HOST || echo else + : /etc/init.d/sqm stop $INTERFACE domain=$(echo $HOST | awk -F/ '{print $3}') hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ') if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then @@ -44,10 +51,16 @@ else ipset add ss_rules_dst_bypass_all $ip done fi - curl -4 -o /dev/null --interface $INTERFACE $HOST || echo + if [ "$FASTTEST" ]; then + avg_speed=$(curl -4 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE $HOST 2>/dev/null) + echo "$avg_speed" + else + curl -4 --max-time 4 -o /dev/null --interface $INTERFACE $HOST || echo + fi if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then for ip in $hostip; do ipset del ss_rules_dst_bypass_all $ip done fi + : /etc/init.d/sqm start $INTERFACE fi diff --git a/openmptcprouter/files/bin/omr-test-speed-server b/openmptcprouter/files/bin/omr-test-speed-server index df61352ec..a937a6763 100755 --- a/openmptcprouter/files/bin/omr-test-speed-server +++ b/openmptcprouter/files/bin/omr-test-speed-server @@ -1,6 +1,10 @@ #!/bin/sh SERVER=$1 INTERFACE=$2 +[ "$3" = "upload" ] && UPLOAD=$3 +[ "$3" = "fasttest" ] && FASTTEST=$3 +[ "$4" = "upload" ] && UPLOAD=$4 +[ "$4" = "fasttest" ] && FASTTEST=$4 [ -z "$SERVER" ] && SERVER="vps" KEY=$(uci -q get openmptcprouter.$SERVER.token) HOST=$(uci -q get openmptcprouter.$SERVER.ip | awk '{print $1}') @@ -8,19 +12,37 @@ PORT=$(uci -q get openmptcprouter.$SERVER.port) MP=false if [ -n "$KEY" ] && [ -n "$HOST" ] && [ -n "$PORT" ]; then trap : HUP INT TERM - echo "Download test via server ${SERVER}:" + [ -z "$FASTTEST" ] && echo "Disable SQM bandwidth limit on $INTERFACE" + : /etc/init.d/sqm stop $INTERFACE 2>&1 >/dev/null + [ -z "$FASTTEST" ] && echo "Download test via server ${SERVER}:" if [ -n "$INTERFACE" ]; then - if [ "$(multipath ${INTERFACE} | grep default)" ]; then - MP=true - /etc/init.d/omr-tracker stop 2>&1 >/dev/null - multipath ${INTERFACE} off - fi - curl -k -o /dev/null --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo - if [ $MP ]; then - multipath ${INTERFACE} on - /etc/init.d/omr-tracker start & 2>&1 >/dev/null + #if [ "$(multipath ${INTERFACE} | grep default)" ]; then + # MP=true + # /etc/init.d/omr-tracker stop 2>&1 >/dev/null + # multipath ${INTERFACE} off + #fi + if [ -n "$FASTTEST" ]; then + if [ -n "$UPLOAD" ]; then + avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_upload}' -X POST -d @/boot/vmlinuz -d @/boot/vmlinuz --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) + echo -n "$avg_speed" + else + avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) + echo -n "$avg_speed" + fi + else + if [ -n "$UPLOAD" ]; then + curl -k -o /dev/null -X POST -d @/boot/vmlinuz -d @/boot/vmlinuz --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + else + curl -k -o /dev/null --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + fi fi + #if [ $MP ]; then + # multipath ${INTERFACE} on + # /etc/init.d/omr-tracker start & 2>&1 >/dev/null + #fi else curl -k -o /dev/null -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo fi + [ -z "$FASTTEST" ] && echo "Restart SQM on $INTERFACE" + : /etc/init.d/sqm start $INTERFACE 2>&1 >/dev/null fi \ No newline at end of file From 2d3b37888d2069da879507d5b304239a921673a8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 8 Aug 2023 12:51:50 +0200 Subject: [PATCH 1027/2059] Add automatic speedtest in wizard --- .../luasrc/controller/openmptcprouter.lua | 7 +++- .../luasrc/view/openmptcprouter/wizard.htm | 18 ++++++-- .../share/omr/post-tracking.d/post-tracking | 42 +++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 592abcc89..b760b205c 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -415,6 +415,7 @@ function wizard_add() local downloadspeed = luci.http.formvalue("cbid.sqm.%s.download" % intf) or "0" local uploadspeed = luci.http.formvalue("cbid.sqm.%s.upload" % intf) or "0" + local testspeed = luci.http.formvalue("cbid.sqm.%s.testspeed" % intf) or "0" if not ucic:get("qos",intf) ~= "" then ucic:set("qos",intf,"interface") @@ -438,7 +439,7 @@ function wizard_add() ucic:set("sqm",intf,"script","piece_of_cake.qos") ucic:set("sqm",intf,"qdisc_advanced","0") ucic:set("sqm",intf,"linklayer","atm") - ucic:set("sqm",intf,"overhead","40") + ucic:set("sqm",intf,"overhead","44") ucic:set("sqm",intf,"enabled","0") ucic:set("sqm",intf,"debug_logging","0") ucic:set("sqm",intf,"verbosity","5") @@ -454,6 +455,10 @@ function wizard_add() ucic:set("sqm",intf,"qdisc","cake") ucic:set("sqm",intf,"script","piece_of_cake.qos") end + ucic:set("openmptcprouter",intf,"testspeed",testspeed) + if testspeed == "1" then + ucic:set("openmptcprouter",intf,"testspeed_lc") + end if downloadspeed ~= "0" and downloadspeed ~= "" then if sqmautorate == "1" and (ucic:get("network",intf,"downloadspeed") ~= downloadspeed or ucic:get("sqm",intf,"max_download") == "" or ucic:get("sqm",intf,"download") == "0") then ucic:set("sqm",intf,"download",math.ceil(downloadspeed*65/100)) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 6b005fe5b..159c22fc5 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -272,7 +272,7 @@ local method=uci:get("openmptcprouter","settings","encryption") if method == nil and ut.trim(sys.exec("cat /proc/cpuinfo | grep aes")) ~= "" then method="aes-256-gcm" - else + elseif method == nil then method="chacha20" end %> @@ -993,12 +993,22 @@ end %>
    + +
    + checked<% end %> /> +
    +
    + <%:Run an automatic speedtest to calculate max speed.%> +
    +
    +
    +

    - <%:Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value.%> + <%:Used by Glorytun UDP and SQM/QoS if enabled.%>
    -
    +

    - <%:Used by Glorytun UDP and SQM/QoS if enabled. 0 to use default value.%> + <%:Used by Glorytun UDP and SQM/QoS if enabled.%>
    @@ -297,7 +315,7 @@ <% else %> <%:There is no Advanced Encryption Standard (AES) instruction set integrated in the processor, you should use chacha20.%> <% end %> - <%:Encryption method is used for Shadowsocks, V2Ray, Glorytun and OpenVPN.%> + <%:Encryption method is used for Shadowsocks, V2Ray/XRay, Glorytun and OpenVPN.%>
    diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 56edc9e66..b7af3d727 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -334,6 +334,10 @@ function server_settings(server,server_ip,openmptcprouter_vps_key) ucic:set("v2ray","omrout","s_vless_address",server_ip) ucic:set("v2ray","omrout","s_socks_address",server_ip) ucic:set("v2ray","omrout","s_trojan_address",server_ip) + ucic:set("xray","omrout","s_vmess_address",server_ip) + ucic:set("xray","omrout","s_vless_address",server_ip) + ucic:set("xray","omrout","s_socks_address",server_ip) + ucic:set("xray","omrout","s_trojan_address",server_ip) ucic:save("qos") ucic:commit("qos") ucic:save("mlvpn") @@ -341,7 +345,9 @@ function server_settings(server,server_ip,openmptcprouter_vps_key) ucic:save("dsvpn") ucic:commit("dsvpn") ucic:save("v2ray") + ucic:save("xray") ucic:commit("v2ray") + ucic:commit("xray") ucic:save("glorytun") ucic:commit("glorytun") ucic:save("shadowsocks-libev") @@ -428,6 +434,7 @@ function restart_all() sys.exec("/etc/init.d/mptcpovervpn restart >/dev/null 2>/dev/null") sys.exec("/etc/init.d/vnstat restart >/dev/null 2>/dev/null") sys.exec("/etc/init.d/v2ray restart >/dev/null 2>/dev/null") + sys.exec("/etc/init.d/xray restart >/dev/null 2>/dev/null") end function redirectports(server,redirect_ports) @@ -822,9 +829,9 @@ function interfaces_status() -- shadowsocksaddr mArray.openmptcprouter["proxy_addr"] = uci:get("openmptcprouter","omr","detected_ss_ipv4") or "" if mArray.openmptcprouter["proxy_addr"] == "" and mArray.openmptcprouter["service_addr"] ~= "" then - tracker_ip = uci:get("shadowsocks-libev","tracker_sss0","local_address") or "" + tracker_ip = uci:get("shadowsocks-libev","tracker_sss0","local_address") or "127.0.0.1" if tracker_ip ~= "" then - local tracker_port = uci:get("shadowsocks-libev","tracker_sss0","local_port") + local tracker_port = uci:get("shadowsocks-libev","tracker_sss0","local_port") or "1111" if mArray.openmptcprouter["external_check"] ~= false then mArray.openmptcprouter["proxy_addr"] = ut.trim(sys.exec("curl -s -4 --socks5 " .. tracker_ip .. ":" .. tracker_port .. " -m " .. timeout .. " " .. check_ipv4_website)) if mArray.openmptcprouter["proxy_addr"] == "" then @@ -930,7 +937,16 @@ function interfaces_status() mArray.openmptcprouter["v2ray_traffic_tx"] = "0" mArray.openmptcprouter["v2ray_traffic"] = "0" end - mArray.openmptcprouter["proxy_traffic"] = mArray.openmptcprouter["ss_traffic"] + mArray.openmptcprouter["v2ray_traffic"] + if status and vpsinfo.xray ~= nil then + mArray.openmptcprouter["xray_traffic_rx"] = vpsinfo.xray.rx or "0" + mArray.openmptcprouter["xray_traffic_tx"] = vpsinfo.xray.tx or "0" + mArray.openmptcprouter["xray_traffic"] = mArray.openmptcprouter["xray_traffic_tx"] + mArray.openmptcprouter["xray_traffic_rx"] + else + mArray.openmptcprouter["xray_traffic_rx"] = "0" + mArray.openmptcprouter["xray_traffic_tx"] = "0" + mArray.openmptcprouter["xray_traffic"] = "0" + end + mArray.openmptcprouter["proxy_traffic"] = mArray.openmptcprouter["ss_traffic"] + mArray.openmptcprouter["v2ray_traffic"] + mArray.openmptcprouter["xray_traffic"] mArray.openmptcprouter["total_traffic"] = mArray.openmptcprouter["proxy_traffic"] + mArray.openmptcprouter["vpn_traffic"] else mArray.openmptcprouter["vps_admin"] = false @@ -1048,6 +1064,11 @@ function interfaces_status() if string.find(sys.exec("/usr/bin/pgrep ss-redir"), "%d+") then mArray.openmptcprouter["shadowsocks_service"] = true end + -- check Shadowsocks Rust is running + mArray.openmptcprouter["shadowsocksrust_service"] = false + if string.find(sys.exec("/usr/bin/pgrep sslocal"), "%d+") then + mArray.openmptcprouter["shadowsocksrust_service"] = true + end mArray.openmptcprouter["shadowsocks_enabled"] = true local ss_server = "1" @@ -1061,6 +1082,18 @@ function interfaces_status() mArray.openmptcprouter["shadowsocks_enabled"] = false end + mArray.openmptcprouter["shadowsocksrust_enabled"] = true + local ss_server = "1" + ucic:foreach("shadowsocks-rust", "server", function(s) + local ss_server_disabled = uci:get("shadowsocks-rust",s[".name"],"disabled") or "0" + if ss_server_disabled == "0" then + ss_server = "0" + end + end) + if ss_server == "1" then + mArray.openmptcprouter["shadowsocksrust_enabled"] = false + end + -- check V2Ray is running mArray.openmptcprouter["v2ray_service"] = false if string.find(sys.exec("/usr/bin/pgrep v2ray"), "%d+") then @@ -1071,6 +1104,16 @@ function interfaces_status() if v2ray == "1" then mArray.openmptcprouter["v2ray_enabled"] = true end + -- check XRay is running + mArray.openmptcprouter["xray_service"] = false + if string.find(sys.exec("/usr/bin/pgrep xray"), "%d+") then + mArray.openmptcprouter["xray_service"] = true + end + mArray.openmptcprouter["xray_enabled"] = false + local xray = uci:get("xray","main","enabled") or "0" + if xray == "1" then + mArray.openmptcprouter["xray_enabled"] = true + end local ss_key = uci:get("shadowsocks-libev","sss0","key") or "" mArray.openmptcprouter["shadowsocks_service_method"] = uci:get("shadowsocks-libev","sss0","method") if ss_key == "" then @@ -1078,6 +1121,13 @@ function interfaces_status() else mArray.openmptcprouter["shadowsocks_service_key"] = true end + local ssr_key = uci:get("shadowsocks-rust","sss0","key") or "" + mArray.openmptcprouter["shadowsocksrust_service_method"] = uci:get("shadowsocks-rust","sss0","method") + if ssr_key == "" then + mArray.openmptcprouter["shadowsocksrust_service_key"] = false + else + mArray.openmptcprouter["shadowsocksrust_service_key"] = true + end -- Add DHCP infos by parsing dnsmasq config file mArray.openmptcprouter.dhcpd = {} From cc2df89ed3b334b9c16e9fbe74cf3b7b2cab2f55 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Sep 2023 15:03:16 +0200 Subject: [PATCH 1109/2059] Add XRay and Shadowsocks Rust support for omr-tracker --- omr-tracker/files/bin/omr-tracker-ss | 45 +++++-- omr-tracker/files/bin/omr-tracker-xray | 150 +++++++++++++++++++++++ omr-tracker/files/etc/init.d/omr-tracker | 109 +++++++++++++++- 3 files changed, 289 insertions(+), 15 deletions(-) create mode 100755 omr-tracker/files/bin/omr-tracker-xray diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index b0d7e2ab4..c1f00a345 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -65,7 +65,7 @@ proxy=${OMR_TRACKER_PROXY:-127.0.0.1:1111} hosts=${OMR_TRACKER_HOSTS:-1.1.1.1 1.0.0.1} wait_test=${OMR_TRACKER_WAIT_TEST:-0} server=${OMR_TRACKER_SERVER:-sss0} - +type=${OMR_TRACKER_SS_TYPE:-libev} nodns=0 last=0 @@ -103,10 +103,16 @@ while true; do script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" [ -n "$script_alert_up" ] && eval $script_alert_up } - if [ -z "$($IPTABLESSAVE 2>/dev/null | grep :ssr)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then - _log "Reload Shadowsocks rules" - /etc/init.d/shadowsocks-libev rules_up 2> /dev/null - _get_ip + if [ -z "$($IPTABLESSAVE 2>/dev/null | grep :ssr)" ]; then + if [ "$type" = "libev" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then + _log "Reload Shadowsocks rules" + /etc/init.d/shadowsocks-libev rules_up 2> /dev/null + _get_ip + elif [ "$type" = "rust" ] && [ "$(uci -q get shadowsocks-rust.ss_rules.disabled)" != "1" ]; then + _log "Reload Shadowsocks Rust rules" + /etc/init.d/shadowsocks-rust rules_up 2> /dev/null + _get_ip + fi fi [ "$(uci -q get openmptcprouter.omr.detected_public_ipv4)" = "" ] || ([ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.detected_public_ipv6)" = "" ]) && _get_ip last=0 @@ -119,11 +125,19 @@ while true; do OMR_TRACKER_STATUS_MSG="Shadowsocks ${server} is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.ss_${server}="down" uci -q commit openmptcprouter.omr - [ "$(uci show openmptcprouter.omr | grep ss_ | grep up)" = "" ] && /etc/init.d/shadowsocks-libev rules_down 2> /dev/null + if [ "$(uci show openmptcprouter.omr | grep ss_ | grep up)" = "" ]; then + [ "$type" = "libev" ] && /etc/init.d/shadowsocks-libev rules_down 2> /dev/null + [ "$type" = "rust" ] && /etc/init.d/shadowsocks-rust rules_down 2> /dev/null + fi _get_ip server_ping=false - serverip="$(uci -q get shadowsocks-libev.${server}.server)" - disabled="$(uci -q get shadowsocks-libev.${server}.disabled)" + if [ "$type" = "libev" ]; then + serverip="$(uci -q get shadowsocks-libev.${server}.server)" + disabled="$(uci -q get shadowsocks-libev.${server}.disabled)" + elif [ "$type" = "rust" ]; then + serverip="$(uci -q get shadowsocks-rust.${server}.server)" + disabled="$(uci -q get shadowsocks-rust.${server}.disabled)" + fi _ping_server $serverip if [ "$server_ping" = false ]; then _log "Server $server ($serverip) seems down, no answer to ping" @@ -146,10 +160,17 @@ while true; do script_alert_down="$(uci -q get omr-tracker.proxy.script_alert_down)" [ -n "$script_alert_down" ] && eval $script_alert_down - if [ "$disabled" != "1" ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(uci -q get shadowsocks-libev.${server}.key)" != "" ]; then - _log "Can't find shadowsocks, restart it..." - /etc/init.d/shadowsocks-libev restart - sleep 5 + if [ "$disabled" != "1" ]; then + if [ "$type" = "libev" ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(uci -q get shadowsocks-libev.${server}.key)" != "" ]; then + _log "Can't find shadowsocks, restart it..." + /etc/init.d/shadowsocks-libev restart + sleep 5 + fi + if [ "$type" = "rust" ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(uci -q get shadowsocks-libev.${server}.key)" != "" ]; then + _log "Can't find shadowsocks rust, restart it..." + /etc/init.d/shadowsocks-rust restart + sleep 5 + fi fi sleep $wait_test fi diff --git a/omr-tracker/files/bin/omr-tracker-xray b/omr-tracker/files/bin/omr-tracker-xray new file mode 100755 index 000000000..21272b1e6 --- /dev/null +++ b/omr-tracker/files/bin/omr-tracker-xray @@ -0,0 +1,150 @@ +#!/bin/sh +# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : + +name=$0 +basename="$(basename $0)" + +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" +else + IPTABLES="/usr/sbin/iptables" +fi + + +_log() { + logger -p daemon.info -t "${basename}" "$@" +} + +_ping_server() { + local host=$1 + ret=$(ping \ + -w "$OMR_TRACKER_TIMEOUT" \ + -c 1 \ + -q \ + "${host}" + ) && echo "$ret" | grep -sq " 0% packet loss" && { + server_ping=true + } +} + +_get_ip() { + uci -q set openmptcprouter.omr=router + if [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ]; then + check_ipv4_website="$(uci -q get openmptcprouter.settings.check_ipv4_website)" + [ -z "$check_ipv4_website" ] && check_ipv4_website="http://ip.openmptcprouter.com" + check_ipv6_website="$(uci -q get openmptcprouter.settings.check_ipv6_website)" + [ -z "$check_ipv6_website" ] && check_ipv6_website="http://ipv6.openmptcprouter.com" + public_ipv4="$(curl -s -4 -m 3 $check_ipv4_website)" + uci -q set openmptcprouter.omr.detected_public_ipv4="${public_ipv4}" + [ -n "${public_ipv4}" ] && { + uci -q set upnpd.config.external_ip="${public_ipv4}" + uci -q commit upnpd + } + if [ "$(uci -q get openmptcprouter.omr.xray)" != "down" ]; then + uci -q set openmptcprouter.omr.detected_ss_ipv4="$(curl -s -4 --socks5 "${proxy}" --max-time 3 $check_ipv4_website)" + else + uci -q del openmptcprouter.omr.detected_ss_ipv4 + fi + if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ]; then + uci -q set openmptcprouter.omr.detected_public_ipv6="$(curl -s -6 -m 3 $check_ipv6_website)" + else + uci -q del openmptcprouter.omr.detected_public_ipv6 + # uci -q set openmptcprouter.omr.detected_ss_ipv6=$(curl -s -6 --socks5 ":::1111" --max-time 3 http://ip.openmptcprouter.com) + fi + fi + uci -q commit openmptcprouter +} + +timeout=${OMR_TRACKER_TIMEOUT:-5} +interval=${OMR_TRACKER_INTERVAL:-10} +retry=${OMR_TRACKER_TRIES:-4} +proxy=${OMR_TRACKER_PROXY:-127.0.0.1:1111} +hosts=${OMR_TRACKER_HOSTS:-1.1.1.1 1.0.0.1} +wait_test=${OMR_TRACKER_WAIT_TEST:-0} + +nodns=0 + +last=0 +nocontact="" +uci -q set openmptcprouter.omr=router +uci -q delete openmptcprouter.omr.xray +_get_ip + +while true; do + host="${hosts%% *}" + [ "$host" = "$hosts" ] || { + hosts="${hosts#* } $host" + } + if [ "$(curl -s -I -w %{http_code} --socks5 ${proxy} --max-time ${timeout} $host -o /dev/null)" != "000" ]; then + nocontact="" + [ "${last}" -ge "${retry}" ] || [ "$(uci -q get openmptcprouter.omr.xray)" = "" ] && { + _log "xray is up (can contact via http ${host})" + OMR_TRACKER_STATUS_MSG="xray is up (can contact via http ${host})" + uci -q set openmptcprouter.omr.xray="up" + uci -q commit openmptcprouter.omr + /etc/init.d/openmptcprouter-vps set_vps_firewall + mail_alert="$(uci -q get omr-tracker.proxy.mail_alert)" + #[ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" + [ "$mail_alert" = "1" ] && [ -n "$(uci -q get mail.default.to)" ] && { + OMR_SYSNAME="$(uci -q get system.@system[0].hostname)" + if [ "$(uci -q get omr-tracker.defaults.mail_up_subject)" != "" ] && [ "$(uci -q get omr-tracker.defaults.mail_up_message)" != "" ]; then + mail_subject="$(uci -q get omr-tracker.defaults.mail_up_subject)" + mail_subject=`echo $mail_subject | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/xray Proxy/g" -e "s/%DEVICE%/Shadowsocks Proxy/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + mail_message="$(uci -q get omr-tracker.defaults.mail_up_message)" + mail_message=`echo $mail_message | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/xray Proxy/g" -e "s/%DEVICE%/Shadowsocks Proxy/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + echo -e "Subject: ${mail_subject}\n\n${mail_message}" | sendmail $(uci -q get mail.default.to) + else + echo -e "Subject: $OMR_SYSNAME: xray Proxy is UP." | sendmail $(uci -q get mail.default.to) + fi + } + script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" + [ -n "$script_alert_up" ] && eval $script_alert_up + } + if [ -z "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^xr)" ]; then + _log "Reload xray rules" + /etc/init.d/xray rules_up 2> /dev/null + _get_ip + fi + [ "$(uci -q get openmptcprouter.omr.detected_public_ipv4)" = "" ] || ([ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.detected_public_ipv6)" = "" ]) && _get_ip + last=0 + else + last=$((last + 1 )) + [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" + [ "${last}" -ge "${retry}" ] && { + if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^xr)" ]; then + _log "xray is down (can't contact via http ${nocontact})" + OMR_TRACKER_STATUS_MSG="xray is down (can't contact via http ${nocontact})" + uci -q set openmptcprouter.omr.xray="down" + uci -q commit openmptcprouter.omr + /etc/init.d/openmptcprouter-vps set_vps_firewall + /etc/init.d/xray rules_down 2> /dev/null + _get_ip + server_ping=false + server="$(uci -q get xray.omrout.s_vless_address)" + _ping_server $server + if [ "$server_ping" = false ]; then + _log "Server ($server) seems down, no answer to ping" + OMR_TRACKER_STATUS_MSG="${OMR_TRACKER_STATUS_MSG} - Server ($server) seems down, no answer to ping" + fi + mail_alert="$(uci -q get omr-tracker.proxy.mail_alert)" + #[ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" + [ "$mail_alert" = "1" ] && [ -n "$(uci -q get mail.default.to)" ] && { + OMR_SYSNAME="$(uci -q get system.@system[0].hostname)" + if [ "$(uci -q get omr-tracker.defaults.mail_down_subject)" != "" ] && [ "$(uci -q get omr-tracker.defaults.mail_down_message)" != "" ]; then + mail_subject="$(uci -q get omr-tracker.defaults.mail_down_subject)" + mail_subject=`echo $mail_subject | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/xray Proxy/g" -e "s/%DEVICE%/xray Proxy/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + mail_message="$(uci -q get omr-tracker.defaults.mail_down_message)" + mail_message=`echo $mail_message | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/xray Proxy/g" -e "s/%DEVICE%/xray Proxy/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"` + echo -e "Subject: ${mail_subject}\n\n${mail_message}" | sendmail $(uci -q get mail.default.to) + else + echo -e "Subject: $OMR_SYSNAME: xray Proxy is down\n\nConnection failure of xray proxy detected. The reason is \"$OMR_TRACKER_STATUS_MSG\"." | sendmail $(uci -q get mail.default.to) + fi + } + script_alert_down="$(uci -q get omr-tracker.proxy.script_alert_down)" + [ -n "$script_alert_down" ] && eval $script_alert_down + sleep $wait_test + fi + } + fi + sleep "${interval}" +done diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 0f80614ed..9a78b2378 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -187,6 +187,38 @@ _initialize_shadowsocks_tracker() { # } } +_initialize_shadowsocks_rust_tracker() { + local redir_tcp server tracker_server + server=$1 + + [ -n "$(echo $server | grep sss)" ] || return + [ -z "$server" ] && return + + #redir_tcp=$(uci -q get shadowsocks-libev.ss_rules.redir_tcp) + #config_get tracker_server ss_rules server + config_get ss_rust_disabled $server disabled 0 + [ "$ss_rust_disabled" = "0" ] && ss_rust_enable="1" + [ -z "$(uci -q get shadowsocks-rust.tracker_${server})" ] && [ "$ss_rust_disabled" != "1" ] && { + logger -t "omr-tracker" "Create ShadowSock tracker ss_local..." + uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.tracker_${server}=ss_local + set shadowsocks-rust.tracker_${server}.server=$server + set shadowsocks-rust.tracker_${server}.local_address="127.0.0.1" + set shadowsocks-rust.tracker_${server}.local_port=1111 + set shadowsocks-rust.tracker_${server}.mode=tcp_and_udp + set shadowsocks-rust.tracker_${server}.timeout=600 + set shadowsocks-rust.tracker_${server}.fast_open=0 + set shadowsocks-rust.tracker_${server}.syslog=0 + set shadowsocks-rust.tracker_${server}.reuse_port=1 + set shadowsocks-rust.tracker_${server}.mptcp=1 + set shadowsocks-rust.tracker_${server}.verbose=0 + commit shadowsocks-rust + EOF + logger -t "omr-tracker" "Restart ShadowSocks" + /etc/init.d/shadowsocks-rust restart + } +} + _launch_shadowsocks_tracker() { local hosts timeout tries interval local_port enabled server wait_test @@ -201,7 +233,7 @@ _launch_shadowsocks_tracker() { [ "$enabled" = "0" ] || [ "$disabled" = "1" ] || [ -z "$hosts" ] && return [ -z "$server" ] && return - [ "$(uci -q get shadowsocks-libev.$server.server)" = "192.168.1.3" ] || [ "$(uci -q get shadowsocks-libev.$server.server)" = "" ] && return + [ "$server" = "192.168.1.3" ] || [ "$server" = "" ] && return procd_open_instance # shellcheck disable=SC2086 @@ -211,8 +243,43 @@ _launch_shadowsocks_tracker() { procd_append_param env "OMR_TRACKER_TRIES=$tries" procd_append_param env "OMR_TRACKER_INTERVAL=$interval" procd_append_param env "OMR_TRACKER_PROXY=127.0.0.1:$local_port" - procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" + procd_append_param env "OMR_TRACKER_WAIT_TEST=$type" procd_append_param env "OMR_TRACKER_SERVER=$server" + procd_append_param env "OMR_TRACKER_SS_TYPE=libev" + procd_set_param limits nofile="51200 51200" + procd_set_param respawn 0 10 0 + procd_set_param stderr 1 + procd_close_instance + sleep 1 +} + +_launch_shadowsocks_rust_tracker() { + local hosts timeout tries interval local_port enabled server wait_test + + [ "$(echo $1 | grep tracker)" != "" ] || return + + _validate_section "proxy" "proxy" + + config_get local_port "$1" local_port + local disabled + config_get disabled "$1" disabled 0 + config_get server "$1" server + + [ "$enabled" = "0" ] || [ "$disabled" = "1" ] || [ -z "$hosts" ] && return + [ -z "$server" ] && return + [ "$server" = "192.168.1.3" ] || [ "$server" = "" ] && return + + procd_open_instance + # shellcheck disable=SC2086 + procd_set_param command /bin/omr-tracker-ss "$1" + procd_append_param env "OMR_TRACKER_HOSTS=$hosts" + procd_append_param env "OMR_TRACKER_TIMEOUT=$timeout" + procd_append_param env "OMR_TRACKER_TRIES=$tries" + procd_append_param env "OMR_TRACKER_INTERVAL=$interval" + procd_append_param env "OMR_TRACKER_PROXY=127.0.0.1:$local_port" + procd_append_param env "OMR_TRACKER_WAIT_TEST=$type" + procd_append_param env "OMR_TRACKER_SERVER=$server" + procd_append_param env "OMR_TRACKER_SS_TYPE=rust" procd_set_param limits nofile="51200 51200" procd_set_param respawn 0 10 0 procd_set_param stderr 1 @@ -242,6 +309,28 @@ _launch_v2ray_tracker() { sleep 1 } +_launch_xray_tracker() { + local hosts timeout tries interval local_port enabled server wait_test + + _validate_section "proxy" "proxy" + [ "$enabled" = "0" ] || [ -z "$hosts" ] && return + + procd_open_instance + # shellcheck disable=SC2086 + procd_set_param command /bin/omr-tracker-xray "$1" + procd_append_param env "OMR_TRACKER_HOSTS=$hosts" + procd_append_param env "OMR_TRACKER_TIMEOUT=$timeout" + procd_append_param env "OMR_TRACKER_TRIES=$tries" + procd_append_param env "OMR_TRACKER_INTERVAL=$interval" + procd_append_param env "OMR_TRACKER_PROXY=127.0.0.1:1111" + procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" + procd_set_param limits nofile="51200 51200" + procd_set_param respawn 0 10 0 + procd_set_param stderr 1 + procd_close_instance + sleep 1 +} + _multi_server() { config_get backup $1 backup [ "$backup" = "1" ] && multiserver=true @@ -254,10 +343,14 @@ _gre_tunnel() { start_service() { local ss_enable=0 + local ss_rust_enable=0 logger -t "omr-tracker" "Launching..." config_load shadowsocks-libev config_foreach _initialize_shadowsocks_tracker server + config_load shadowsocks-rust + config_foreach _initialize_shadowsocks_rust_tracker server + config_load network config_foreach _launch_tracker interface @@ -267,11 +360,21 @@ start_service() { #elif [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ]; then # /etc/init.d/shadowsocks-libev rules_down fi + if [ "$ss_rust_enable" = "1" ]; then + config_load shadowsocks-rust + config_foreach _launch_shadowsocks_rust_tracker ss_local + fi config_load v2ray config_get v2rayenabled main enabled if [ "$v2rayenabled" = "1" ]; then _launch_v2ray_tracker fi + + config_load xray + config_get xrayenabled main enabled + if [ "$xrayenabled" = "1" ]; then + _launch_xray_tracker + fi multiserver=false config_load openmptcprouter @@ -285,7 +388,7 @@ start_service() { } service_triggers() { - procd_add_reload_trigger omr-tracker network shadowsocks-libev v2ray + procd_add_reload_trigger omr-tracker network shadowsocks-libev v2ray xray } reload_service() { From a1232136d8c38c70fecf5b353df01dc213d9b2c0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Sep 2023 15:03:44 +0200 Subject: [PATCH 1110/2059] Add XRay and Shadowsocks Rust support for openmptcprouter-vps --- .../files/etc/init.d/openmptcprouter-vps | 252 ++++++++++++++++-- 1 file changed, 236 insertions(+), 16 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index e14113ce6..48398be4e 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -293,6 +293,44 @@ _set_ss_server_vps() { fi } +_set_ssgo_server_vps() { + local disabled port key method + config_load shadowsocks-rust + config_get disabled sss0 disabled + [ "$disabled" = "1" ] && return + config_get port sss0 server_port + #config_get server $1 server + config_get key sss0 key + key="$(echo $key | sed 's/+/-/g; s/\//_/g;')" + [ -z "$key" ] && return + config_get method sss0 method + local current_port current_key current_method + [ -z "$vps_config" ] && vps_config=$(_get_json "config") + [ -z "$vps_config" ] && return + current_port="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-go.port')" + current_key="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-go.key')" + current_method="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-go.method')" + current_fast_open="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-go.fast_open')" + current_mptcp="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-go.mptcp')" + + ebpf="false" + fast_open="false" + no_delay="false" + mptcp="false" + obfs="false" + obfs_plugin="v2ray" + obfs_type="http" + config_load shadowsocks-rust + config_foreach _get_ss_redir ss_redir + config_foreach _get_ss_server server + + if [ "$current_mptcp" != "$mptcp" ] || [ "$current_port" != "$port" ] || [ "$current_method" != "$method" ] || [ "$current_fast_open" != "$fast_open" ]; then + local settings + settings='{"port": '$port',"method":"'$method'","fast_open":'$fast_open',"reuse_port":true,"mptcp":'$mptcp'}' + result=$(_set_json "shadowsocks-go" "$settings") + fi +} + _set_v2ray_server_vps() { enabled=$(uci -q get v2ray.main.enabled) [ "$enabled" != "1" ] && return @@ -309,6 +347,22 @@ _set_v2ray_server_vps() { fi } +_set_xray_server_vps() { + enabled=$(uci -q get xray.main.enabled) + [ "$enabled" != "1" ] && return + userid=$(uci -q get xray.omrout.s_vless_user_id) + [ -z "$userid" ] && return + [ -z "$vps_config" ] && vps_config=$(_get_json "config") + [ -z "$vps_config" ] && return + current_userid="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.key')" + + if [ "$current_userid" != "$userid" ]; then + local settings + settings='{"userid": "'$userid'"}' + echo $(_set_json "xray" "$settings") + fi +} + _get_vps_config() { [ -z "$vps_config" ] && vps_config=$(_get_json "config") [ -z "$vps_config" ] && return @@ -450,6 +504,17 @@ _get_vps_config() { /etc/init.d/shadowsocks-libev restart fi fi + if [ "$(uci -q get shadowsocks-rust.sss0.server)" != "127.0.0.1" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + config_foreach _set_ssrust_server server "server" $vpsip + uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.sss0.server="$vpsip" + commit shadowsocks-rust + EOF + if [ "$(uci -q get shadowsocks-rust.sss0.disabled)" = "0" ]; then + logger -t "OMR-VPS" "Restart shadowsocks Rust..." + /etc/init.d/shadowsocks-rust restart + fi + fi if [ "$(uci -q get v2ray.omrout.s_vmess_address)" != "127.0.0.1" ] && [ "$(uci -q get v2ray.omrout.s_vmess_address)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then uci -q batch <<-EOF >/dev/null set v2ray.omrout.s_vmess_address="$vpsip" @@ -461,6 +526,17 @@ _get_vps_config() { /etc/init.d/v2ray restart fi fi + if [ "$(uci -q get xray.omrout.s_vmess_address)" != "127.0.0.1" ] && [ "$(uci -q get xray.omrout.s_vmess_address)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + uci -q batch <<-EOF >/dev/null + set xray.omrout.s_vmess_address="$vpsip" + set xray.omrout.s_vless_address="$vpsip" + commit xray + EOF + if [ "$(uci -q get xray.main.enabled)" = "1" ]; then + logger -t "OMR-VPS" "Restart XRay..." + /etc/init.d/xray restart + fi + fi if [ "$(uci -q get openvpn.omr.remote)" != "127.0.0.1" ] && [ "$(uci -q get openvpn.omr.remote)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then uci -q batch <<-EOF >/dev/null set openvpn.omr.remote="$vpsip" @@ -942,12 +1018,14 @@ _vps_firewall_redirect_port() { #uci -q delete firewall.$1 #return fi + xray="$v2ray" [ "$(uci -q get v2ray.main.enabled)" = "0" ] && [ "$(uci -q get openmptcprouter.omr.v2ray)" != "down" ] && v2ray="0" + [ "$(uci -q get xray.main.enabled)" = "0" ] && [ "$(uci -q get openmptcprouter.omr.xray)" != "down" ] && xray="0" [ "$proto" = "all" ] && proto="tcp udp" [ "$proto" = "" ] && proto="tcp udp" [ "$src" = "vpn" ] && [ -n "$proto" ] && [ -n "$src_dport" ] && [ "$enabled" != "0" ] && [ "$name" != "Allow-DHCP-Request-VPN" ] && { for protoi in $proto; do - if [ "$v2ray" = "0" ]; then + if [ "$v2ray" = "0" ] && [ "$xray" = "0" ]; then checkfw="" if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then @@ -1045,7 +1123,8 @@ _vps_firewall_redirect_port() { checkfw="" if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- V2Ray to ${dest_ip}:${dest_port}") + [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- XRay to ${dest_ip}:${dest_port}") else comment="" [ -n "$src_dip" ] && { @@ -1065,45 +1144,58 @@ _vps_firewall_redirect_port() { } } [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}") fi fi if [ "$checkfw" = "" ]; then - settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "V2Ray to '${dest_ip}':'${dest_port}'"}' + [ "$v2ray" == "1" ] && settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "V2Ray to '${dest_ip}':'${dest_port}'"}' + [ "$xray" == "1" ] && settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "XRay to '${dest_ip}':'${dest_port}'"}' result=$(_set_json "shorewallopen" "$settings") [ -z "$dest_port" ] && dest_port="$src_dport" settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","destip" : "'$dest_ip'","destport" : "'$dest_port'","proto" : "'${protoi}'"}' - result=$(_set_json "v2rayredirect" "$settings") + [ "$v2ray" == "1" ] && result=$(_set_json "v2rayredirect" "$settings") + [ "$xray" == "1" ] && result=$(_set_json "xrayredirect" "$settings") fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1"] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") else [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") fi fi fi @@ -1136,6 +1228,7 @@ _vps_firewall_close_port() { destport=$(echo $comment | awk '{print $3}' | awk -F: '{print $2}') settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","destip" : "'$destip'","destport": "'$destport'"}' result=$(_set_json "v2rayunredirect" "$settings") + result=$(_set_json "xrayunredirect" "$settings") } } done @@ -1162,6 +1255,7 @@ _vps_firewall_close_port() { [ "$type" = "ACCEPT" ] && { settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","proto" : "'$proto'","comment" : "'$comment'"}' result=$(_set_json "v2rayunredirect" "$settings") + result=$(_set_json "xrayunredirect" "$settings") } } done @@ -1276,6 +1370,30 @@ _set_ss_server() { fi } +_set_ssrust_redir() { + local option=$2 + local value=$3 + if [ "$value" = "true" ]; then + value=1 + elif [ "$value" = "false" ]; then + value=0 + fi + uci -q set shadowsocks-rust.$1.$option=$value +} + +_set_ssrust_server() { + local option=$2 + local value=$3 + if [ "$value" = "true" ]; then + value=1 + elif [ "$value" = "false" ]; then + value=0 + fi + if [ "$(echo $1 | grep omr)" != "" ] || [ "$(echo $1 | grep sss)" ]; then + uci -q set shadowsocks-rust.$1.$option=$value + fi +} + _set_config_from_vps() { local shadowsocks_disabled vpn glorytun_state redirect shorewall_redirect mlvpn_key openvpn_key dsvpn_key [ -z "$vps_config" ] && vps_config=$(_get_json "config") @@ -1331,28 +1449,66 @@ _set_config_from_vps() { EOF if [ "$current_proxy" = "shadowsocks" ]; then uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.sss0.disabled=1 + commit shadowsocks-rust set shadowsocks-libev.sss0.disabled=0 commit shadowsocks-libev set v2ray.main.enabled=0 commit v2ray + set xray.main.enabled=0 + commit xray + set openmptcprouter.settings.shadowsocks_disable=0 + commit openmptcprouter + EOF + elif [ "$current_proxy" = "shadowsocks-rust" ]; then + uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.sss0.disabled=0 + commit shadowsocks-rust + set shadowsocks-libev.sss0.disabled=1 + commit shadowsocks-libev + set v2ray.main.enabled=0 + commit v2ray + set xray.main.enabled=0 + commit xray set openmptcprouter.settings.shadowsocks_disable=0 commit openmptcprouter EOF elif [ "$current_proxy" = "v2ray" ]; then uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.sss0.disabled=1 + commit shadowsocks-rust set shadowsocks-libev.sss0.disabled=1 commit shadowsocks-libev set v2ray.main.enabled=1 commit v2ray + set xray.main.enabled=0 + commit xray + set openmptcprouter.settings.shadowsocks_disable=1 + commit openmptcprouter + EOF + elif [ "$current_proxy" = "xray" ]; then + uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.sss0.disabled=1 + commit shadowsocks-rust + set shadowsocks-libev.sss0.disabled=1 + commit shadowsocks-libev + set v2ray.main.enabled=0 + commit v2ray + set xray.main.enabled=1 + commit xray set openmptcprouter.settings.shadowsocks_disable=1 commit openmptcprouter EOF elif [ "$current_proxy" = "none" ]; then uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.sss0.disabled=1 + commit shadowsocks-rust set shadowsocks-libev.sss0.disabled=1 commit shadowsocks-libev set v2ray.main.enabled=0 commit v2ray + set xray.main.enabled=0 + commit xray set openmptcprouter.settings.shadowsocks_disable=1 commit openmptcprouter EOF @@ -1419,6 +1575,34 @@ _set_config_from_vps() { fi fi + # Shadowsocks Rust settings + #shadowsocks_disabled="$(uci -q get openmptcprouter.settings.shadowsocks_disable)" + #[ -z "$shadowsocks_disabled" ] && shadowsocks_disabled=0 + ssgo_sskey="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks_go.config.password')" + if [ -n "$ssgo_sskey" ] && [ "$ssgo_sskey" != "$(uci -q get shadowsocks-rust.sss0.password)" ]; then + ss_method="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks_go.config.protocol')" + ss_port="65280" + #ss_fast_open="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-rust.fast_open')" + config_load shadowsocks-rust + #config_foreach _set_ss_redir ss_redir "fast_open" $ss_fast_open + #config_foreach _set_ss_redir ss_local "fast_open" $ss_fast_open + uci -q batch <<-EOF >/dev/null + set shadowsocks-rust.sss0.password=$ssgo_sskey + set shadowsocks-rust.sss0.server_port=$ss_port + set shadowsocks-rust.sss0.method=$ss_method + EOF + config_foreach _set_ss_server server "key" $ssgo_sskey + config_foreach _set_ss_server server "method" $ss_method + if [ "$(uci -q get shadowsocks-rust.sss0.server)" != "127.0.0.1" ]; then + config_foreach _set_ss_server server "server" $vpsip + fi + uci -q commit shadowsocks-rust + if [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]; then + logger -t "OMR-VPS" "Shadowsocks Rust restart..." + /etc/init.d/shadowsocks-rust restart >/dev/null 2>&1 + fi + fi + # V2Ray settings v2ray_key="$(echo "$vps_config" | jsonfilter -q -e '@.v2ray.config.key')" #v2ray_port="$(echo "$vps_config" | jsonfilter -q -e '@.v2ray.config.port')" @@ -1445,6 +1629,37 @@ _set_config_from_vps() { /etc/init.d/v2ray restart >/dev/null 2>&1 fi + # XRay settings + xray_key="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.key')" + xray_sskey="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.sskey')" + #v2ray_port="$(echo "$vps_config" | jsonfilter -q -e '@.v2ray.config.port')" + xray_port="65248" + if ([ -n "$xray_key" ] && [ "$xray_key" != "$(uci -q get xray.omrout.s_vmess_user_id)" ]) || ([ -n "$xray_port" ] && [ "$xray_port" != "$(uci -q get xray.omrout.s_vmess.port)" ]); then + uci -q batch <<-EOF >/dev/null + set xray.omrout.s_shadowsocks_port="$((xray_port+4))" + set xray.omrout.s_shadowsocks_password="$xray_sskey" + set xray.omrout.s_socks_user_id="$xray_key" + set xray.omrout.s_socks_port="$((xray_port+3))" + set xray.omrout.s_trojan_user_id="$xray_key" + set xray.omrout.s_trojan_port="$((xray_port+1))" + set xray.omrout.s_vmess_user_id="$xray_key" + set xray.omrout.s_vmess_port="$((xray_port+2))" + set xray.omrout.s_vless_user_id="$xray_key" + set xray.omrout.s_vless_port="$xray_port" + EOF + uci -q set xray.omrout.s_shadowsocks_password=$ss_key + if [ "$(uci -q get xray.omrout.s_vmess_address)" != "127.0.0.1" ]; then + uci -q set xray.omrout.s_vmess_address="$vpsip" + uci -q set xray.omrout.s_vless_address="$vpsip" + uci -q set xray.omrout.s_trojan_address="$vpsip" + uci -q set xray.omrout.s_socks_address="$vpsip" + uci -q set xray.omrout.s_shadowsocks_address="$vpsip" + fi + uci -q commit v2ray + logger -t "OMR-VPS" "Xray restart..." + /etc/init.d/xray restart >/dev/null 2>&1 + fi + # Glorytun settings glorytun_key="$(echo "$vps_config" | jsonfilter -q -e '@.glorytun.key')" glorytun_port="$(echo "$vps_config" | jsonfilter -q -e '@.glorytun.port')" @@ -1951,9 +2166,12 @@ _config_service() { EOF config_foreach _set_ss_server server "method" "aes-256-gcm" uci -q commit shadowsocks-libev + config_foreach _set_ssrust_server server "method" "2022-blake3-aes-256-gcm" + uci -q commit shadowsocks-rust [ "$method" != "aes-256-gcm" ] && { logger -t "OMR-VPS" "Shadowsocks restart" /etc/init.d/shadowsocks-libev restart + /etc/init.d/shadowsocks-rust restart } fi } @@ -1967,7 +2185,9 @@ _config_service() { #config_load shadowsocks-libev #config_foreach _set_ss_server_vps server _set_ss_server_vps + _set_ssgo_server_vps _set_v2ray_server_vps + _set_xray_server_vps [ -z "$(_set_glorytun_vps)" ] && error=1 [ -z "$(_set_openvpn_vps)" ] && error=1 [ -z "$(_set_mlvpn_vps)" ] && error=1 @@ -2063,7 +2283,7 @@ start_service() { service_triggers() { #procd_add_reload_trigger openmptcprouter network shadowsocks-libev v2ray glorytun glorytun-udp mlvpn openvpn dsvpn - procd_add_reload_trigger shadowsocks-libev v2ray glorytun glorytun-udp mlvpn dsvpn + procd_add_reload_trigger shadowsocks-libev shadowsocks-rust v2ray xray glorytun glorytun-udp mlvpn dsvpn procd_add_config_trigger "config.change" "firewall" /etc/init.d/openmptcprouter-vps set_vps_firewall #procd_add_config_trigger "config.change" "network" /etc/init.d/openmptcprouter-vps set_gre_tunnel #procd_add_reload_trigger openmptcprouter shadowsocks-libev network upnpd From ec85665ba85fbdbe193e628958803fcbee47a369 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Sep 2023 15:04:17 +0200 Subject: [PATCH 1111/2059] Compile XRay and Shadowsock Rust by default --- openmptcprouter-full/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 0dce36853..2e288627c 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -84,7 +84,8 @@ MY_DEPENDS := \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ - !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc + !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ + xray-core shadowsocks-rust-sslocal shadowsocks-rust-ssservice shadowsocks-rust-config luci-app-shadowsocks-rust # (TARGET_x86_64||aarch64):kmod-tcp-bbr2 # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From 4296ac92e92fe77bd654117f678967abf8981eea Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Sep 2023 17:06:13 +0200 Subject: [PATCH 1112/2059] Replace RUTX by RUTX12 and RUTX50 arch --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 150ce71da..3f5f60cfc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx, r5s, qnap-301w] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w] OMR_KERNEL: [5.4, 6.1] runs-on: ubuntu-latest continue-on-error: true From d07ccb47ff789db25482e9168e40bafdfd3e897d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Sep 2023 21:32:42 +0200 Subject: [PATCH 1113/2059] Add Rust language --- rust/Makefile | 104 ++++++++++++++++++ rust/files/cargo-config | 8 ++ .../0001-Update-xz2-and-use-it-static.patch | 48 ++++++++ rust/patches/0002-Bumped-libc-version.patch | 35 ++++++ rust/rust-host-build.mk | 45 ++++++++ rust/rust-package.mk | 51 +++++++++ rust/rust-values.mk | 59 ++++++++++ 7 files changed, 350 insertions(+) create mode 100644 rust/Makefile create mode 100644 rust/files/cargo-config create mode 100644 rust/patches/0001-Update-xz2-and-use-it-static.patch create mode 100644 rust/patches/0002-Bumped-libc-version.patch create mode 100644 rust/rust-host-build.mk create mode 100644 rust/rust-package.mk create mode 100644 rust/rust-values.mk diff --git a/rust/Makefile b/rust/Makefile new file mode 100644 index 000000000..60df0e5cd --- /dev/null +++ b/rust/Makefile @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2023 Luca Barbato and Donald Hoskins + +include $(TOPDIR)/rules.mk +include ./rust-values.mk + +PKG_NAME:=rust +PKG_VERSION:=1.71.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.gz +PKG_SOURCE_URL:=https://static.rust-lang.org/dist/ +PKG_HASH:=6fa90d50d1d529a75f6cc349784de57d7ec0ba2419b09bde7d335c25bd4e472e +HOST_BUILD_DIR:=$(BUILD_DIR)/host/rust-$(RUSTC_TARGET_ARCH)/rustc-$(PKG_VERSION)-src + +PKG_MAINTAINER:=Luca Barbato +PKG_LICENSE:=Apache-2.0 MIT +PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT + +HOST_BUILD_DEPENDS:=python3/host +PKG_HOST_ONLY:=1 + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/package.mk + +define Package/rust + SECTION:=lang + CATEGORY:=Languages + SUBMENU:=Rust + TITLE:=Rust Programming Language Compiler + URL:=https://www.rust-lang.org/ + DEPENDS:=$(RUST_ARCH_DEPENDS) +endef + +define Package/rust/description + Rust is a multi-paradigm, general-purpose programming language designed for performance + and safety, especially safe concurrency. Rust is syntactically similar to C++, but can + guarantee memory safety by using a borrow checker to validate references. +endef + +# Rust-lang has an uninstall script +RUST_UNINSTALL:=$(CARGO_HOME)/lib/rustlib/uninstall.sh + +# Target Flags +TARGET_CONFIGURE_ARGS = \ + --set=target.$(RUSTC_TARGET_ARCH).ar=$(TARGET_AR) \ + --set=target.$(RUSTC_TARGET_ARCH).cc=$(TARGET_CC_NOCACHE) \ + --set=target.$(RUSTC_TARGET_ARCH).cxx=$(TARGET_CXX_NOCACHE) \ + --set=target.$(RUSTC_TARGET_ARCH).linker=$(TARGET_CC_NOCACHE) \ + --set=target.$(RUSTC_TARGET_ARCH).ranlib=$(TARGET_RANLIB) \ + $(if $(CONFIG_USE_MUSL),--set=target.$(RUSTC_TARGET_ARCH).musl-root=$(TOOLCHAIN_DIR)) + +# CARGO_HOME is an environmental +HOST_CONFIGURE_OPTS += CARGO_HOME="$(CARGO_HOME)" + +# Rust Configuration Arguments +HOST_CONFIGURE_ARGS = \ + --build=$(RUSTC_HOST_ARCH) \ + --target=$(RUSTC_TARGET_ARCH),$(RUSTC_HOST_ARCH) \ + --host=$(RUSTC_HOST_ARCH) \ + --prefix=$(CARGO_HOME) \ + --bindir=$(CARGO_HOME)/bin \ + --libdir=$(CARGO_HOME)/lib \ + --sysconfdir=$(CARGO_HOME)/etc \ + --datadir=$(CARGO_HOME)/share \ + --mandir=$(CARGO_HOME)/man \ + --dist-compression-formats=xz \ + --enable-missing-tools \ + --disable-sanitizers \ + --release-channel=stable \ + --enable-cargo-native-static \ + --set=llvm.download-ci-llvm=true \ + $(TARGET_CONFIGURE_ARGS) + +define Host/Uninstall + # Call the Uninstall script + [ -f $(RUST_UNINSTALL) ] && \ + $(BASH) $(RUST_UNINSTALL) || echo No Uninstall +endef + +define Host/Compile + ( \ + cd $(HOST_BUILD_DIR) ; \ + $(PYTHON) x.py --config ./config.toml dist build-manifest cargo llvm-tools \ + rustc rust-std rust-src ; \ + ) +endef + +define Host/Install + ( \ + cd $(HOST_BUILD_DIR)/build/dist ; \ + find -iname "*.xz" -exec tar -xJf {} \; ; \ + find ./* -type f -name install.sh -execdir sh {} --prefix=$(CARGO_HOME) --disable-ldconfig \; ; \ + \ + sed -e 's|@RUSTC_TARGET_ARCH@|$(RUSTC_TARGET_ARCH)|g' \ + -e 's|@TARGET_CC_NOCACHE@|$(TARGET_CC_NOCACHE)|g' \ + -e 's|@RUSTC_LDFLAGS@|$(RUSTC_LDFLAGS)|g' \ + $(CURDIR)/files/cargo-config > $(CARGO_HOME)/config ; \ + ) +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,rust)) diff --git a/rust/files/cargo-config b/rust/files/cargo-config new file mode 100644 index 000000000..2ed512931 --- /dev/null +++ b/rust/files/cargo-config @@ -0,0 +1,8 @@ +[target.@RUSTC_TARGET_ARCH@] +linker = "@TARGET_CC_NOCACHE@" +rustflags = ["-Ctarget-feature=-crt-static", "-Clink-args=@RUSTC_LDFLAGS@"] + +[profile.stripped] +inherits = "release" +opt-level = "s" +strip = true diff --git a/rust/patches/0001-Update-xz2-and-use-it-static.patch b/rust/patches/0001-Update-xz2-and-use-it-static.patch new file mode 100644 index 000000000..8d0c4b042 --- /dev/null +++ b/rust/patches/0001-Update-xz2-and-use-it-static.patch @@ -0,0 +1,48 @@ +From d3000458501d339ea2043006924d431ead18769e Mon Sep 17 00:00:00 2001 +From: Luca Barbato +Date: Sun, 4 Jun 2023 19:32:28 +0000 +Subject: [PATCH] Update xz2 and use it static + +--- + Cargo.lock | 8 ++++---- + src/bootstrap/Cargo.lock | 8 ++++---- + src/bootstrap/Cargo.toml | 2 +- + 3 files changed, 9 insertions(+), 9 deletions(-) + +--- a/src/bootstrap/Cargo.lock ++++ b/src/bootstrap/Cargo.lock +@@ -443,9 +443,9 @@ dependencies = [ + + [[package]] + name = "lzma-sys" +-version = "0.1.17" ++version = "0.1.20" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "bdb4b7c3eddad11d3af9e86c487607d2d2442d185d848575365c4856ba96d619" ++checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" + dependencies = [ + "cc", + "libc", +@@ -912,9 +912,9 @@ dependencies = [ + + [[package]] + name = "xz2" +-version = "0.1.6" ++version = "0.1.7" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "c179869f34fc7c01830d3ce7ea2086bc3a07e0d35289b667d0a8bf910258926c" ++checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" + dependencies = [ + "lzma-sys", + ] +--- a/src/bootstrap/Cargo.toml ++++ b/src/bootstrap/Cargo.toml +@@ -50,7 +50,7 @@ toml = "0.5" + ignore = "0.4.10" + opener = "0.5" + once_cell = "1.7.2" +-xz2 = "0.1" ++xz2 = { version = "0.1", features = ["static"] } + walkdir = "2" + + # Dependencies needed by the build-metrics feature diff --git a/rust/patches/0002-Bumped-libc-version.patch b/rust/patches/0002-Bumped-libc-version.patch new file mode 100644 index 000000000..52c8a245c --- /dev/null +++ b/rust/patches/0002-Bumped-libc-version.patch @@ -0,0 +1,35 @@ +From 032857e7e403f654129c45dc7e6718a9ad49e377 Mon Sep 17 00:00:00 2001 +From: Nikolay Arhipov +Date: Tue, 6 Jun 2023 16:09:05 +0300 +Subject: [PATCH] Bumped libc version + +--- + Cargo.lock | 4 ++-- + library/std/Cargo.toml | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -1988,9 +1988,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0e + + [[package]] + name = "libc" +-version = "0.2.143" ++version = "0.2.146" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" ++checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" + dependencies = [ + "rustc-std-workspace-core", + ] +--- a/library/std/Cargo.toml ++++ b/library/std/Cargo.toml +@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = [ + panic_unwind = { path = "../panic_unwind", optional = true } + panic_abort = { path = "../panic_abort" } + core = { path = "../core" } +-libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } ++libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'] } + compiler_builtins = { version = "0.1.92" } + profiler_builtins = { path = "../profiler_builtins", optional = true } + unwind = { path = "../unwind" } diff --git a/rust/rust-host-build.mk b/rust/rust-host-build.mk new file mode 100644 index 000000000..39cf1f23c --- /dev/null +++ b/rust/rust-host-build.mk @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2023 Luca Barbato and Donald Hoskins + +ifeq ($(origin RUST_INCLUDE_DIR),undefined) + RUST_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) +endif +include $(RUST_INCLUDE_DIR)/rust-values.mk + +# $(1) path to the package (optional) +# $(2) additional arguments to cargo (optional) +define Host/Compile/Cargo + ( \ + cd $(HOST_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + CC=$(HOSTCC_NOCACHE) \ + cargo install -v \ + --profile stripped \ + $(if $(RUST_PKG_FEATURES),--features "$(RUST_PKG_FEATURES)") \ + --root $(HOST_INSTALL_DIR) \ + --path "$(if $(strip $(1)),$(strip $(1)),.)" $(2) ; \ + ) +endef + +define Host/Uninstall/Cargo + ( \ + cd $(HOST_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + CC=$(HOSTCC_NOCACHE) \ + cargo uninstall -v \ + --root $(HOST_INSTALL_DIR) || true ; \ + ) +endef + +define RustBinHostBuild + define Host/Install + $(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/bin + $(INSTALL_BIN) $(HOST_INSTALL_DIR)/bin/* $(STAGING_DIR_HOSTPKG)/bin/ + endef +endef + +Host/Compile=$(call Host/Compile/Cargo) +Host/Uninstall=$(call Host/Uninstall/Cargo) diff --git a/rust/rust-package.mk b/rust/rust-package.mk new file mode 100644 index 000000000..955b37c29 --- /dev/null +++ b/rust/rust-package.mk @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2023 Luca Barbato and Donald Hoskins + +# Variables (all optional) to be set in package Makefiles: +# +# RUST_PKG_FEATURES - list of options, default empty +# +# Space or comma separated list of features to activate +# +# e.g. RUST_PKG_FEATURES:=enable-foo,with-bar + +ifeq ($(origin RUST_INCLUDE_DIR),undefined) + RUST_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) +endif +include $(RUST_INCLUDE_DIR)/rust-values.mk + +# Support only a subset for now. +RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) + +# $(1) path to the package (optional) +# $(2) additional arguments to cargo (optional) +define Build/Compile/Cargo + ( \ + cd $(PKG_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUST_CFLAGS)" \ + TARGET_CC=$(TARGET_CC_NOCACHE) \ + CC=$(HOSTCC_NOCACHE) \ + $(CARGO_VARS) \ + cargo install -v \ + --profile stripped \ + --target $(RUSTC_TARGET_ARCH) \ + $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ + --root $(PKG_INSTALL_DIR) \ + --path "$(if $(strip $(1)),$(strip $(1)),.)" \ + $(2) ; \ + ) +endef + +define RustBinPackage + ifndef Package/$(1)/install + define Package/$(1)/install + $$(INSTALL_DIR) $$(1)/usr/bin/ + $$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/bin/* $$(1)/usr/bin/ + endef + endif +endef + +Build/Compile=$(call Build/Compile/Cargo) diff --git a/rust/rust-values.mk b/rust/rust-values.mk new file mode 100644 index 000000000..26935c0f6 --- /dev/null +++ b/rust/rust-values.mk @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2023 Luca Barbato and Donald Hoskins + +# Rust Environmental Vars +CONFIG_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) +RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(CONFIG_HOST_SUFFIX) +CARGO_HOME:=$(STAGING_DIR)/host/cargo +CARGO_VARS:= + +ifeq ($(CONFIG_USE_MUSL),y) +# Force linking of the SSP library for musl +ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS += -lssp_nonshared + endif +endif +ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG + ifeq ($(strip $(PKG_SSP)),1) + TARGET_CFLAGS += -lssp_nonshared + endif +endif +endif + +ifeq ($(HOST_OS),Darwin) + ifeq ($(HOST_ARCH),arm64) + RUSTC_HOST_ARCH:=aarch64-apple-darwin + endif +endif + +# mips64 openwrt has a specific targed in rustc +ifeq ($(ARCH),mips64) + RUSTC_TARGET_ARCH:=$(REAL_GNU_TARGET_NAME) +else + RUSTC_TARGET_ARCH:=$(subst openwrt,unknown,$(REAL_GNU_TARGET_NAME)) +endif + +RUSTC_TARGET_ARCH:=$(subst muslgnueabi,musleabi,$(RUSTC_TARGET_ARCH)) + +ifeq ($(ARCH),i386) + RUSTC_TARGET_ARCH:=$(subst i486,i586,$(RUSTC_TARGET_ARCH)) +else ifeq ($(ARCH),riscv64) + RUSTC_TARGET_ARCH:=$(subst riscv64,riscv64gc,$(RUSTC_TARGET_ARCH)) +endif + +# ARM Logic +ifeq ($(ARCH),arm) + ifeq ($(CONFIG_arm_v7),y) + RUSTC_TARGET_ARCH:=$(subst arm,armv7,$(RUSTC_TARGET_ARCH)) + endif + + ifeq ($(CONFIG_HAS_FPU),y) + RUSTC_TARGET_ARCH:=$(subst musleabi,musleabihf,$(RUSTC_TARGET_ARCH)) + endif +endif + +ifeq ($(ARCH),aarch64) + RUST_CFLAGS:=-mno-outline-atomics +endif From a049f0f415c4d90abd04ce0310e2c07a167bfed4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Sep 2023 21:33:48 +0200 Subject: [PATCH 1114/2059] Add shadowsocks-Rust luci interface --- luci-app-shadowsocks-rust/Makefile | 18 + .../luci-static/resources/shadowsocks-rust.js | 294 ++++++++++++++ .../view/shadowsocks-rust/instances.js | 163 ++++++++ .../resources/view/shadowsocks-rust/rules.js | 141 +++++++ .../view/shadowsocks-rust/servers.js | 82 ++++ .../luasrc/controller/shadowsocks-rust.lua | 22 ++ .../po/bg/shadowsocks-rust.po | 327 +++++++++++++++ .../po/ca/shadowsocks-rust.po | 336 ++++++++++++++++ .../po/cs/shadowsocks-rust.po | 327 +++++++++++++++ .../po/de/shadowsocks-rust.po | 341 ++++++++++++++++ .../po/el/shadowsocks-rust.po | 327 +++++++++++++++ .../po/en/shadowsocks-rust.po | 327 +++++++++++++++ .../po/es/shadowsocks-rust.po | 373 ++++++++++++++++++ .../po/fr/shadowsocks-rust.po | 346 ++++++++++++++++ .../po/he/shadowsocks-rust.po | 327 +++++++++++++++ .../po/hi/shadowsocks-rust.po | 327 +++++++++++++++ .../po/hu/shadowsocks-rust.po | 327 +++++++++++++++ .../po/it/shadowsocks-rust.po | 327 +++++++++++++++ .../po/ja/shadowsocks-rust.po | 327 +++++++++++++++ .../po/ko/shadowsocks-rust.po | 327 +++++++++++++++ .../po/ms/shadowsocks-rust.po | 327 +++++++++++++++ .../po/nb_NO/shadowsocks-rust.po | 333 ++++++++++++++++ .../po/pl/shadowsocks-rust.po | 335 ++++++++++++++++ .../po/pt/shadowsocks-rust.po | 339 ++++++++++++++++ .../po/pt_BR/shadowsocks-rust.po | 327 +++++++++++++++ .../po/ro/shadowsocks-rust.po | 327 +++++++++++++++ .../po/ru/shadowsocks-rust.po | 337 ++++++++++++++++ .../po/sk/shadowsocks-rust.po | 327 +++++++++++++++ .../po/sv/shadowsocks-rust.po | 339 ++++++++++++++++ .../po/templates/shadowsocks-rust.pot | 359 +++++++++++++++++ .../po/tr/shadowsocks-rust.po | 327 +++++++++++++++ .../po/uk/shadowsocks-rust.po | 341 ++++++++++++++++ .../po/vi/shadowsocks-rust.po | 327 +++++++++++++++ .../po/zh-cn/shadowsocks-rust.po | 352 +++++++++++++++++ .../po/zh-tw/shadowsocks-rust.po | 327 +++++++++++++++ .../etc/uci-defaults/40_luci-shadowsocks-rust | 13 + .../menu.d/luci-app-shadowsocks-rust.json | 39 ++ .../rpcd/acl.d/luci-app-shadowsocks-rust.json | 17 + 38 files changed, 10479 insertions(+) create mode 100644 luci-app-shadowsocks-rust/Makefile create mode 100644 luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js create mode 100644 luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js create mode 100644 luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js create mode 100644 luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js create mode 100644 luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua create mode 100644 luci-app-shadowsocks-rust/po/bg/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/ca/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/cs/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/de/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/el/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/en/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/es/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/fr/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/he/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/hi/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/hu/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/it/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/ja/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/ko/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/ms/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/nb_NO/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/pl/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/pt/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/pt_BR/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/ro/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/ru/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/sk/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/sv/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/templates/shadowsocks-rust.pot create mode 100644 luci-app-shadowsocks-rust/po/tr/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/uk/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/vi/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/zh-cn/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/po/zh-tw/shadowsocks-rust.po create mode 100644 luci-app-shadowsocks-rust/root/etc/uci-defaults/40_luci-shadowsocks-rust create mode 100644 luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json create mode 100644 luci-app-shadowsocks-rust/root/usr/share/rpcd/acl.d/luci-app-shadowsocks-rust.json diff --git a/luci-app-shadowsocks-rust/Makefile b/luci-app-shadowsocks-rust/Makefile new file mode 100644 index 000000000..2a9bc5180 --- /dev/null +++ b/luci-app-shadowsocks-rust/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2017 Yousong Zhou +# Copyright (C) 2019-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI Support for shadowsocks-rust +LUCI_DEPENDS:=+luci-compat + +PKG_LICENSE:=Apache-2.0 +PKG_VERSION:=omr-202309 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js new file mode 100644 index 000000000..2c9ac0684 --- /dev/null +++ b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js @@ -0,0 +1,294 @@ +'use strict'; +'require baseclass'; +'require uci'; +'require form'; +'require network'; + +var names_options_server = [ + 'server', + 'server_port', + 'method', + 'password', + 'plugin', + 'plugin_opts', +]; + +var names_options_client = [ + 'server', + 'local_address', + 'local_port', +]; + +var names_options_common = [ + 'verbose', + 'ipv6_first', + 'fast_open', + 'no_delay', + 'reuse_port', + 'mode', + 'mtu', + 'timeout', + 'user', + 'mptcp', +]; + +var modes = [ + 'tcp_only', + 'tcp_and_udp', + 'udp_only', +]; + +var methods = [ + 'none', + // aead + 'aes-128-gcm', + 'aes-256-gcm', + 'chacha20-ietf-poly1305', + '2022-blake3-aes-128-gcm', + '2022-blake3-aes-256-gcm', + '2022-blake3-chacha8-poly1305', + '2022-blake3-chacha20-poly1305', +]; + +function ucival_to_bool(val) { + return val === 'true' || val === '1' || val === 'yes' || val === 'on'; +} + +return L.Class.extend({ + values_actions: function(o) { + o.value('bypass'); + o.value('forward'); + if (o.option !== 'dst_default') { + o.value('checkdst'); + } + }, + values_redir: function(o, xmode) { + uci.sections('shadowsocks-rust', 'ss_redir', function(sdata) { + var disabled = ucival_to_bool(sdata['disabled']), + sname = sdata['.name'], + mode = sdata['mode'] || 'tcp_only'; + if (!disabled && mode.indexOf(xmode) !== -1) { + o.value(sname, sname + ' - ' + mode); + } + }); + o.value('', ''); + o.value('all', 'all'); + o.default = ''; + }, + values_serverlist: function(o) { + uci.sections('shadowsocks-rust', 'server', function(sdata) { + var sname = sdata['.name'], + server = sdata['server'], + server_port = sdata['server_port']; + if (server && server_port) { + var disabled = ucival_to_bool(sdata['.disabled']) ? ' - disabled' : '', + desc = '%s - %s:%s%s'.format(sname, server, server_port, disabled); + o.value(sname, desc); + } + }); + }, + values_ipaddr: function(o, netDevs) { + netDevs.forEach(function(v) { + v.getIPAddrs().forEach(function(a) { + var host = a.split('/')[0]; + o.value(host, '%s (%s)'.format(host, v.getShortName())); + }); + }); + }, + options_client: function(s, tab, netDevs) { + var o = s.taboption(tab, form.ListValue, 'server', _('Remote server')); + this.values_serverlist(o); + o = s.taboption(tab, form.Value, 'local_address', _('Local address')); + o.datatype = 'ipaddr'; + o.placeholder = '0.0.0.0'; + this.values_ipaddr(o, netDevs); + o = s.taboption(tab, form.Value, 'local_port', _('Local port')); + o.datatype = 'port'; + }, + options_server: function(s, opts) { + var o, optfunc, + tab = opts && opts.tab || null; + + if (!tab) { + optfunc = function(/* ... */) { + var o = s.option.apply(s, arguments); + o.editable = true; + return o; + }; + } else { + optfunc = function(/* ... */) { + var o = s.taboption.apply(s, L.varargs(arguments, 0, tab)); + o.editable = true; + return o; + }; + } + + o = optfunc(form.Value, 'label', _('Label')); + + o = optfunc(form.Value, 'server', _('Server')); + o.datatype = 'host'; + o.size = 16; + + o = optfunc(form.Value, 'server_port', _('Server port')); + o.datatype = 'port'; + o.size = 5; + + o = optfunc(form.ListValue, 'method', _('Method')); + methods.forEach(function(m) { + o.value(m); + }); + + o = optfunc(form.Value, 'password', _('Password (Base64)')); + o.datatype = 'base64'; + o.password = true; + o.size = 12; + + optfunc(form.Value, 'plugin', _('Plugin')).modalonly = true; + + optfunc(form.Value, 'plugin_opts', _('Plugin Options')).modalonly = true; + }, + options_common: function(s, tab) { + var o = s.taboption(tab, form.ListValue, 'mode', _('Mode of operation')); + modes.forEach(function(m) { + o.value(m); + }); + o.default = 'tcp_and_udp'; + o = s.taboption(tab, form.Value, 'mtu', _('MTU')); + o.datatype = 'uinteger'; + o = s.taboption(tab, form.Value, 'timeout', _('Timeout (sec)')); + o.datatype = 'uinteger'; + s.taboption(tab, form.Value, 'user', _('Run as')); + + s.taboption(tab, form.Flag, 'verbose', _('Verbose')); + s.taboption(tab, form.Flag, 'ipv6_first', _('IPv6 First'), _('Prefer IPv6 addresses when resolving names')); + s.taboption(tab, form.Flag, 'fast_open', _('Enable TCP Fast Open')); + s.taboption(tab, form.Flag, 'no_delay', _('Enable TCP_NODELAY')); + s.taboption(tab, form.Flag, 'reuse_port', _('Enable SO_REUSEPORT')); + s.taboption(tab, form.Flag, 'mptcp', _('Enable MPTCP')); + }, + ucival_to_bool: function(val) { + return ucival_to_bool(val); + }, + cfgvalue_overview: function(sdata) { + var stype = sdata['.type'], + lines = []; + + if (stype === 'ss_server') { + this.cfgvalue_overview_(sdata, lines, names_options_server); + this.cfgvalue_overview_(sdata, lines, names_options_common); + this.cfgvalue_overview_(sdata, lines, ['bind_address']); + } else if (stype === 'ss_local' || stype === 'ss_redir' || stype === 'ss_tunnel') { + this.cfgvalue_overview_(sdata, lines, names_options_client); + if (stype === 'ss_tunnel') { + this.cfgvalue_overview_(sdata, lines, ['tunnel_address']); + } + this.cfgvalue_overview_(sdata, lines, names_options_common); + } else { + return []; + } + + return lines; + }, + cfgvalue_overview_: function(sdata, lines, names) { + names.forEach(function(n) { + var v = sdata[n]; + if (v) { + if (n === 'password') { + v = _(''); + } + var fv = E('var', [v]); + if (sdata['.type'] !== 'ss_server' && n === 'server') { + fv = E('a', { + class: 'label', + href: L.url('admin/services/shadowsocks-rust/servers') + '#edit=' + v, + target: '_blank', + rel: 'noopener' + }, fv); + } + lines.push(n + ': ', fv, E('br')); + } + }); + }, + option_install_package: function(s, tab) { + var bin = s.sectiontype.replace('_', '-'), + opkg_package = 'shadowsocks-rust-' + bin, o; + if (tab) { + o = s.taboption(tab, form.Button, '_install'); + } else { + o = s.option(form.Button, '_install'); + } + o.title = _('Package is not installed'); + o.inputtitle = _('Install package ' + opkg_package); + o.inputstyle = 'apply'; + o.onclick = function() { + window.open(L.url('admin/system/opkg') + + '?query=' + opkg_package, '_blank', 'noopener'); + }; + }, + parse_uri: function(uri) { + var scheme = 'ss://'; + if (uri && uri.indexOf(scheme) === 0) { + var atPos = uri.indexOf('@'), hashPos = uri.lastIndexOf('#'), tag; + if (hashPos === -1) { + hashPos = undefined; + } else { + tag = uri.slice(hashPos + 1); + } + + if (atPos !== -1) { // SIP002 format https://shadowsocks.org/en/spec/SIP002-URI-Scheme.html + var colonPos = uri.indexOf(':', atPos + 1), slashPos = uri.indexOf('/', colonPos + 1); + if (colonPos === -1) return null; + if (slashPos === -1) slashPos = undefined; + + var userinfo = atob(uri.slice(scheme.length, atPos) + .replace(/-/g, '+').replace(/_/g, '/')), + i = userinfo.indexOf(':'); + if (i === -1) return null; + + var config = { + server: uri.slice(atPos + 1, colonPos), + server_port: uri.slice(colonPos + 1, slashPos ? slashPos : hashPos), + password: userinfo.slice(i + 1), + method: userinfo.slice(0, i) + }; + + if (slashPos) { + var search = uri.slice(slashPos + 1, hashPos); + if (search[0] === '?') search = search.slice(1); + search.split('&').forEach(function(s) { + var j = s.indexOf('='); + if (j !== -1) { + var k = s.slice(0, j), v = s.slice(j + 1); + if (k === 'plugin') { + v = decodeURIComponent(v); + var k = v.indexOf(';'); + if (k !== -1) { + config['plugin'] = v.slice(0, k); + config['plugin_opts'] = v.slice(k + 1); + } + } + } + }); + } + return [config, tag]; + } else { // Legacy format https://shadowsocks.org/en/config/quick-guide.html + var plain = atob(uri.slice(scheme.length, hashPos)), + firstColonPos = plain.indexOf(':'), + lastColonPos = plain.lastIndexOf(':'), + atPos = plain.lastIndexOf('@', lastColonPos); + if (firstColonPos === -1 || + lastColonPos === -1 || + atPos === -1) return null; + + var config = { + server: plain.slice(atPos + 1, lastColonPos), + server_port: plain.slice(lastColonPos + 1), + password: plain.slice(firstColonPos + 1, atPos), + method: plain.slice(0, firstColonPos) + }; + return [config, tag]; + } + } + return null; + } +}); diff --git a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js new file mode 100644 index 000000000..66b18163d --- /dev/null +++ b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js @@ -0,0 +1,163 @@ +'use strict'; +'require form'; +'require uci'; +'require fs'; +'require network'; +'require rpc'; +'require shadowsocks-rust as ss'; + +var conf = 'shadowsocks-rust'; +var cfgtypes = ['ss_local', 'ss_redir', 'ss_server', 'ss_tunnel']; + +var callServiceList = rpc.declare({ + object: 'service', + method: 'list', + params: [ 'name' ], + expect: { '': {} } +}); + +return L.view.extend({ + render: function(stats) { + var m, s, o; + + m = new form.Map(conf, + _('Local Instances'), + _('Instances of shadowsocks-rust components, e.g. ss-local, \ + ss-redir, ss-tunnel, ss-server, etc. To enable an instance it \ + is required to enable both the instance itself and the remote \ + server it refers to.')); + + s = m.section(form.GridSection); + s.addremove = true; + s.cfgsections = function() { + return this.map.data.sections(this.map.config) + .filter(function(s) { return cfgtypes.indexOf(s['.type']) !== -1; }) + .map(function(s) { return s['.name']; }); + }; + s.sectiontitle = function(section_id) { + var s = uci.get(conf, section_id); + return (s ? s['.type'] + '.' : '') + section_id; + }; + s.renderSectionAdd = function(extra_class) { + var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments), + optionEl = [E('option', { value: '_dummy' }, [_('-- instance type --')])]; + cfgtypes.forEach(function(t) { + optionEl.push(E('option', { value: t }, [t.replace('_', '-')])); + }); + var selectEl = E('select', { + class: 'cbi-input-select', + change: function(ev) { + ev.target.parentElement.nextElementSibling.nextElementSibling + .toggleAttribute('disabled', ev.target.value === '_dummy'); + } + }, optionEl); + el.lastElementChild.setAttribute('disabled', ''); + el.prepend(E('div', {}, selectEl)); + return el; + }; + s.handleAdd = function(ev, name) { + var selectEl = ev.target.parentElement.firstElementChild.firstElementChild, + type = selectEl.value; + this.sectiontype = type; + var promise = form.GridSection.prototype.handleAdd.apply(this, arguments); + this.sectiontype = undefined; + return promise; + }; + s.addModalOptions = function(s, section_id, ev) { + var sdata = uci.get(conf, section_id), + stype = sdata ? sdata['.type'] : null; + if (stype) { + s.sectiontype = stype; + return Promise.all([ + L.resolveDefault(fs.stat('/usr/bin/' + stype.replace('_', '-')), null), + network.getDevices() + ]).then(L.bind(function(res) { + s.tab('general', _('General Settings')); + s.tab('advanced', _('Advanced Settings')); + s.taboption('general', form.Value, 'label', _('Label')); + s.taboption('general', form.Flag, 'disabled', _('Disable')); + if (!res[0]) { + ss.option_install_package(s, 'general'); + } + ss.options_common(s, 'advanced'); + + if (stype === 'ss_server') { + ss.options_server(s, { tab: 'general' }); + o = s.taboption('general', form.Value, 'bind_address', + _('Bind address'), + _('The address ss-server will initiate connection from')); + o.datatype = 'ipaddr'; + o.placeholder = '0.0.0.0'; + ss.values_ipaddr(o, res[1]); + } else { + ss.options_client(s, 'general', res[1]); + if (stype === 'ss_tunnel') { + o = s.taboption('general', form.Value, 'tunnel_address', + _('Tunnel address'), + _('The address ss-tunnel will forward traffic to')); + o.datatype = 'hostport'; + } + } + }, this)); + } + }; + + o = s.option(form.DummyValue, 'overview', _('Overview')); + o.modalonly = false; + o.editable = true; + o.rawhtml = true; + o.renderWidget = function(section_id, option_index, cfgvalue) { + var sdata = uci.get(conf, section_id); + if (sdata) { + return form.DummyValue.prototype.renderWidget.call(this, section_id, option_index, ss.cfgvalue_overview(sdata)); + } + return null; + }; + + o = s.option(form.DummyValue, 'running', _('Running')); + o.modalonly = false; + o.editable = true; + o.default = ''; + + o = s.option(form.Button, 'disabled', _('Enable/Disable')); + o.modalonly = false; + o.editable = true; + o.inputtitle = function(section_id) { + var s = uci.get(conf, section_id); + if (ss.ucival_to_bool(s['disabled'])) { + this.inputstyle = 'reset'; + return _('Disabled'); + } + this.inputstyle = 'save'; + return _('Enabled'); + } + o.onclick = function(ev) { + var inputEl = ev.target.parentElement.nextElementSibling; + inputEl.value = ss.ucival_to_bool(inputEl.value) ? '0' : '1'; + return this.map.save(); + } + + return m.render().finally(function() { + L.Poll.add(function() { + return L.resolveDefault(callServiceList(conf), {}) + .then(function(res) { + var instances = null; + try { + instances = res[conf]['instances']; + } catch (e) {} + if (!instances) return; + uci.sections(conf) + .filter(function(s) { return cfgtypes.indexOf(s['.type']) !== -1; }) + .forEach(function(s) { + var el = document.getElementById('cbi-shadowsocks-rust-' + s['.name'] + '-running'); + if (el) { + var name = s['.type'] + '.' + s['.name'], + running = instances.hasOwnProperty(name)? instances[name].running : false; + el.innerText = running ? 'yes' : 'no'; + } + }); + }); + }); + }); + }, +}); diff --git a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js new file mode 100644 index 000000000..26aa47fd2 --- /dev/null +++ b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js @@ -0,0 +1,141 @@ +'use strict'; +'require view'; +'require uci'; +'require fs'; +'require form'; +'require tools.widgets as widgets'; +'require shadowsocks-rust as ss'; + +var conf = 'shadowsocks-rust'; +var cfgtypes = ['ss_rules']; + +function src_dst_option(s /*, ... */) { + var o = s.taboption.apply(s, L.varargs(arguments, 1)); + o.datatype = 'or(ipaddr,cidr)'; +} + +return L.view.extend({ + load: function() { + return Promise.all([ + L.resolveDefault(fs.stat('/usr/lib/iptables/libxt_recent.so'), {}), + L.resolveDefault(fs.stat('/usr/bin/ss-rules'), null), + uci.load(conf).then(function() { + if (!uci.get_first(conf, 'ss_rules')) { + uci.set(conf, uci.add(conf, 'ss_rules', 'ss_rules'), 'disabled', '1'); + } + }) + ]); + }, + render: function(stats) { + var m, s, o; + + m = new form.Map(conf, _('Redir Rules'), + _('On this page you can configure how traffics are to be \ + forwarded to ss-redir instances. \ + If enabled, packets will first have their src ip addresses checked \ + against Src ip/net bypass, Src ip/net forward, \ + Src ip/net checkdst and if none matches Src default \ + will give the default action to be taken. \ + If the prior check results in action checkdst, packets will continue \ + to have their dst addresses checked.')); + + s = m.section(form.GridSection); + s.addremove = true; + s.addbtntitle = _('Add a new rule...'); + s.cfgsections = function() { + return this.map.data.sections(this.map.config) + .filter(function(s) { return cfgtypes.indexOf(s['.type']) !== -1; }) + .map(function(s) { return s['.name']; }); + }; + s.tab('general', _('General Settings')); + s.tab('src', _('Source Settings')); + s.tab('dst', _('Destination Settings')); + s.sectiontype = 'ss_rules'; + + s.addModalOptions = function(s, section_id, ev) { + s.taboption('general', form.Flag, 'disabled', _('Disable')); + s.taboption('general', form.Value, 'label', _('Label')); + + //o = s.taboption('general', form.ListValue, 'server', _('server')); + //ss.values_serverlist(o, ''); + o = s.taboption('general', form.ListValue, 'redir_tcp', + _('ss-redir for TCP')); + ss.values_redir(o, 'tcp'); + o = s.taboption('general', form.ListValue, 'redir_udp', + _('ss-redir for UDP')); + ss.values_redir(o, 'udp'); + + o = s.taboption('general', form.ListValue, 'local_default', + _('Local-out default'), + _('Default action for locally generated TCP packets')); + ss.values_actions(o); + o = s.taboption('general', widgets.DeviceSelect, 'ifnames', + _('Ingress interfaces'), + _('Only apply rules on packets from these network interfaces')); + o.multiple = true; + o.noaliases = true; + o.noinactive = true; + s.taboption('general', form.Value, 'ipt_args', + _('Extra arguments'), + _('Passes additional arguments to iptables. Use with care!')); + + src_dst_option(s, 'src', form.DynamicList, 'src_ips_bypass', + _('Src ip/net bypass'), + _('Bypass ss-redir for packets with src address in this list')); + src_dst_option(s, 'src', form.DynamicList, 'src_ips_forward', + _('Src ip/net forward'), + _('Forward through ss-redir for packets with src address in this list')); + src_dst_option(s, 'src', form.DynamicList, 'src_ips_checkdst', + _('Src ip/net checkdst'), + _('Continue to have dst address checked for packets with src address in this list')); + o = s.taboption('src', form.ListValue, 'src_default', + _('Src default'), + _('Default action for packets whose src address do not match any of the src ip/net list')); + ss.values_actions(o); + + src_dst_option(s, 'dst', form.DynamicList, 'dst_ips_bypass', + _('Dst ip/net bypass'), + _('Bypass ss-redir for packets with dst address in this list')); + src_dst_option(s, 'dst', form.DynamicList, 'dst_ips_forward', + _('Dst ip/net forward'), + _('Forward through ss-redir for packets with dst address in this list')); + + var dir = '/etc/shadowsocks-rust'; + o = s.taboption('dst', form.FileUpload, 'dst_ips_bypass_file', + _('Dst ip/net bypass file'), + _('File containing ip/net for the purposes as with Dst ip/net bypass')); + o.root_directory = dir; + o = s.taboption('dst', form.FileUpload, 'dst_ips_forward_file', + _('Dst ip/net forward file'), + _('File containing ip/net for the purposes as with Dst ip/net forward')); + o.root_directory = dir; + o = s.taboption('dst', form.ListValue, 'dst_default', + _('Dst default'), + _('Default action for packets whose dst address do not match any of the dst ip list')); + ss.values_actions(o); + + o = s.taboption('dst', form.Flag, 'dst_forward_recentrst'); + o.title = _('Forward recentrst'); + o.description = _('Forward those packets whose dst have recently sent to us multiple tcp-rst'); + }; + + o = s.option(form.Button, 'disabled', _('Enable/Disable')); + o.modalonly = false; + o.editable = true; + o.inputtitle = function(section_id) { + var s = uci.get(conf, section_id); + if (ss.ucival_to_bool(s['disabled'])) { + this.inputstyle = 'reset'; + return _('Disabled'); + } + this.inputstyle = 'save'; + return _('Enabled'); + }; + o.onclick = function(ev) { + var inputEl = ev.target.parentElement.nextElementSibling; + inputEl.value = ss.ucival_to_bool(inputEl.value) ? '0' : '1'; + return this.map.save(); + }; + return m.render(); + }, +}); diff --git a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js new file mode 100644 index 000000000..f053ca667 --- /dev/null +++ b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js @@ -0,0 +1,82 @@ +'use strict'; +'require form'; +'require uci'; +'require ui'; +'require shadowsocks-rust as ss'; + +var conf = 'shadowsocks-rust'; + +return L.view.extend({ + render: function() { + var m, s, o; + + m = new form.Map(conf, _('Remote Servers'), + _('Definition of remote shadowsocks servers. \ + Disable any of them will also disable instances referring to it.')); + + s = m.section(form.GridSection, 'server'); + s.addremove = true; + s.handleLinkImport = function() { + var textarea = new ui.Textarea(); + ui.showModal(_('Import Links'), [ + textarea.render(), + E('div', { class: 'right' }, [ + E('button', { + class: 'btn', + click: ui.hideModal + }, [ _('Cancel') ]), + ' ', + E('button', { + class: 'btn cbi-button-action', + click: ui.createHandlerFn(this, function() { + textarea.getValue().split('\n').forEach(function(s) { + var config = ss.parse_uri(s); + if (config) { + var tag = config[1]; + if (tag && !tag.match(/^[a-zA-Z0-9_]+$/)) tag = null; + var sid = uci.add(conf, 'server', tag); + config = config[0]; + Object.keys(config).forEach(function(k) { + uci.set(conf, sid, k, config[k]); + }); + } + }); + return uci.save() + .then(L.bind(this.map.load, this.map)) + .then(L.bind(this.map.reset, this.map)) + .then(L.ui.hideModal) + .catch(function() {}); + }) + }, [ _('Import') ]) + ]) + ]); + }; + s.renderSectionAdd = function(extra_class) { + var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments); + el.appendChild(E('button', { + 'class': 'cbi-button cbi-button-add', + 'title': _('Import Links'), + 'click': ui.createHandlerFn(this, 'handleLinkImport') + }, [ _('Import Links') ])); + return el; + }; + + o = s.option(form.Flag, 'disabled', _('Disable')); + o.editable = true; + + ss.options_server(s); + + return m.render(); + }, + addFooter: function() { + var p = '#edit='; + if (location.hash.indexOf(p) === 0) { + var section_id = location.hash.substring(p.length); + var editBtn = document.querySelector('#cbi-shadowsocks-rust-' + section_id + ' button.cbi-button-edit'); + if (editBtn) + editBtn.click(); + } + //return this.super('addFooter', arguments); + return null; + } +}); diff --git a/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua b/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua new file mode 100644 index 000000000..fce506149 --- /dev/null +++ b/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua @@ -0,0 +1,22 @@ +-- Copyright 2017 Yousong Zhou +-- Licensed to the public under the Apache License 2.0. +-- +module("luci.controller.shadowsocks-rust", package.seeall) + +function index() + entry({"admin", "services", "shadowsocks-rust"}, + alias("admin", "services", "shadowsocks-rust", "instances"), + _("Shadowsocks-rust"), 59) + + entry({"admin", "services", "shadowsocks-rust", "instances"}, + view("shadowsocks-rust/instances"), + _("Local Instances"), 10).leaf = true + + entry({"admin", "services", "shadowsocks-rust", "servers"}, + view("shadowsocks-rust/servers"), + _("Remote Servers"), 20).leaf = true + + entry({"admin", "services", "shadowsocks-rust", "rules"}, + view("shadowsocks-rust/rules"), + _("Redir Rules"), 30).leaf = true +end diff --git a/luci-app-shadowsocks-rust/po/bg/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/bg/shadowsocks-rust.po new file mode 100644 index 000000000..a2af6b1c1 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/bg/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: bg\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/ca/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/ca/shadowsocks-rust.po new file mode 100644 index 000000000..94c06d5e2 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/ca/shadowsocks-rust.po @@ -0,0 +1,336 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-10-25 18:01+0000\n" +"Last-Translator: Adolfo Jayme Barrientos \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.9.1-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Activat" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Visió de conjunt" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Contrasenya" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" + +#~ msgid "Name" +#~ msgstr "Nom" diff --git a/luci-app-shadowsocks-rust/po/cs/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/cs/shadowsocks-rust.po new file mode 100644 index 000000000..d1e7a4df7 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/cs/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: cs\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/de/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/de/shadowsocks-rust.po new file mode 100644 index 000000000..8091ca1a9 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/de/shadowsocks-rust.po @@ -0,0 +1,341 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-11-05 01:57+0000\n" +"Last-Translator: Paul Spooren \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.10-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Erweiterte Einstellungen" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "Deaktivieren" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "Deaktiviert" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "Aktivieren/Deaktivieren" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Aktiviert" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "Zusätzliche Argumente" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "Allgemeine Einstellungen" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "MTU" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Übersicht" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" +"Gibt zusätzliche Kommandozeilenargumente an iptables weiter. Mit Vorsicht " +"benutzen!" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Passwort" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "Server" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" + +#~ msgid "Add" +#~ msgstr "Hinzufügen" + +#~ msgid "Name" +#~ msgstr "Name" diff --git a/luci-app-shadowsocks-rust/po/el/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/el/shadowsocks-rust.po new file mode 100644 index 000000000..7b4a7e212 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/el/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: el\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/en/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/en/shadowsocks-rust.po new file mode 100644 index 000000000..c18e1b221 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/en/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: en\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/es/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/es/shadowsocks-rust.po new file mode 100644 index 000000000..634997d5c --- /dev/null +++ b/luci-app-shadowsocks-rust/po/es/shadowsocks-rust.po @@ -0,0 +1,373 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2019-11-13 23:06+0000\n" +"Last-Translator: Franco Castillo \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.10-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "-- tipo de instancia --" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Configuración avanzada" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "Dirección de enlace" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "Omitir ss-redir para paquetes con dirección dst en esta lista" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "Omitir ss-redir para paquetes con dirección src en esta lista" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" +"Continuar con la verificación de la dirección dst para paquetes con " +"dirección src en esta lista" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "Acción predeterminada para paquetes TCP generados localmente" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" +"Acción predeterminada para paquetes cuya dirección dst no coincide con " +"ninguna de la lista dst ip" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" +"Acción predeterminada para paquetes cuya dirección src no coincide con " +"ninguna de la lista src ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" +"Definición de servidores shadowsocks remotos. Deshabilitar cualquiera de " +"ellos también deshabilitará las instancias que lo refieran." + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "Configuración de destino" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "Desactivar" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "Desactivado" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "Dst predeterminado" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "Omitir Dst ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "Omitir archivo Dst ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "Reenviar Dst ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "Reenviar archivo Dst ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "Activar SO_REUSEPORT" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "Activar TCP Fast Open" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "Activar TCP_NODELAY" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "Activar/Desactivar" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Activado" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "Argumentos extra" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" +"Archivo que contiene ip/net para los fines como con Omitir Dst ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" +"Archivo que contiene ip / net para los fines como con Reenviar Dst ip/" +"net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "Reenviar recentrst" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" +"Reenviar aquellos paquetes cuyos archivos dst nos hayan enviado " +"recientemente múltiples tcp-rst" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" +"Reenviar a través de ss-redir para paquetes con dirección dst en esta lista" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" +"Reenviar a través de ss-redir para paquetes con dirección src en esta lista" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "Configuración general" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "IPv6 primero" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "Interfaces de ingreso" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "Instalar paquete" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "Instalar el paquete iptables-mod-conntrack-extra" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" +"Instancias de componentes de shadowsocks-rust, ej. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. Para habilitar una instancia, se requiere habilitar " +"tanto la instancia como el servidor remoto al que hace referencia." + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "Clave (base64)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "Instancias locales" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "Dirección local" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "Puerto local" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "Salida local predeterminada" + +# Maximum Transmission Unit +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "MTU" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "Método" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "Modo de operación" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" +"En esta página puede configurar cómo se reenviará el tráfico a las " +"instancias de ss-redir. Si están habilitados, los paquetes tendrán primero " +"sus direcciones src ip verificadas con Omitir Src ip / net, " +"Reenviar Src ip / net, Src ip / net checkdst y si ninguno " +"coincide con Src predeterminado dará la acción predeterminada que " +"se debe realizar. Si la verificación anterior resulta en la acción " +"checkdst, los paquetes continuarán teniendo sus direcciones dst " +"marcadas." + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "Solo aplicar reglas en paquetes desde estas interfaces de red" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Vista general" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "Paquete no instalado" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "Pasa argumentos adicionales a iptables. ¡Utilícelo con cuidado!" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Contraseña" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "Plugin" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "Opciones de plugin" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "Preferir direcciones IPv6 al resolver nombres" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "Reglas de redireccionamiento" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "Servidores remotos" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "Servidor remoto" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "Correr como" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "Corriendo" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "Servidor" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "Puerto del servidor" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "Shadowsocks-rust" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "Configuración de fuente" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "Src predeterminado" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "Omitir Src ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "Src ip/net checkdst" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "Reenviar Src ip/net" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "La dirección ss-server iniciará la conexión desde" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "La dirección ss-tunnel reenviará el tráfico a" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "Tiempo de espera (seg)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "Direccion del tunel" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "Verbosidad" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "ss-redir para TCP" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "ss-redir para UDP" + +#~ msgid "Add" +#~ msgstr "Añadir" + +#~ msgid "Install package %q" +#~ msgstr "Instalar paquete %q" + +#~ msgid "Name" +#~ msgstr "Nombre" diff --git a/luci-app-shadowsocks-rust/po/fr/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/fr/shadowsocks-rust.po new file mode 100644 index 000000000..6e1941062 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/fr/shadowsocks-rust.po @@ -0,0 +1,346 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-10-24 13:55+0000\n" +"Last-Translator: Nathan \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.9.1-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Paramètres avancés" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +#, fuzzy +msgid "Bind address" +msgstr "Adresse de liaison" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "Action par défaut pour les paquets TCP générés localement" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "Paramètres de destination" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "Désactiver" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "Désactivé" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "Activer SO_REUSEPORT" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "Activer TCP_NODELAY" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "Activer/Désactiver" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Activé" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "Arguments supplémentaires" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "Paramètres généraux" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "IPv6 en priorité" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "Interfaces d'entrée" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "Clé (base64)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "Instances locales" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "Adresse locale" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "Port local" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "Méthode" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "Mode de fonctionnement" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" +"Appliquer les règles uniquement sur les paquets de ces interfaces réseau" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Vue d'ensemble" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "Le paquet n'est pas installé" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" +"Passe des arguments supplémentaires aux tables d'adresses IP. A utiliser " +"avec précaution !" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Mot de passe" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "Plugin" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "Options de plugin" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "Préférer les adresses IPv6 lors de la résolution des noms" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "Règles de redirection" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "Serveurs distants" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "Serveur distant" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "Exécuter comme" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "En cours d'exécution" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "Serveur" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "Port serveur" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "Délai d'attente (s)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "Adresse du tunnel" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "Verbeux" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" + +#~ msgid "Add" +#~ msgstr "Ajouter" + +#~ msgid "Install package %q" +#~ msgstr "Installer le paquet %q" + +#~ msgid "Name" +#~ msgstr "Nom" diff --git a/luci-app-shadowsocks-rust/po/he/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/he/shadowsocks-rust.po new file mode 100644 index 000000000..17ad865d1 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/he/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: he\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/hi/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/hi/shadowsocks-rust.po new file mode 100644 index 000000000..ffcad7bbd --- /dev/null +++ b/luci-app-shadowsocks-rust/po/hi/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: hi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/hu/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/hu/shadowsocks-rust.po new file mode 100644 index 000000000..eaa18b7f1 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/hu/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: hu\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/it/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/it/shadowsocks-rust.po new file mode 100644 index 000000000..dacd912f6 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/it/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/ja/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/ja/shadowsocks-rust.po new file mode 100644 index 000000000..54b2cc42c --- /dev/null +++ b/luci-app-shadowsocks-rust/po/ja/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: ja\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/ko/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/ko/shadowsocks-rust.po new file mode 100644 index 000000000..4eeec8b74 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/ko/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: ko\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/ms/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/ms/shadowsocks-rust.po new file mode 100644 index 000000000..3a6469ab7 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/ms/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: ms\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/nb_NO/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/nb_NO/shadowsocks-rust.po new file mode 100644 index 000000000..9520f8dae --- /dev/null +++ b/luci-app-shadowsocks-rust/po/nb_NO/shadowsocks-rust.po @@ -0,0 +1,333 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-10-30 03:22+0000\n" +"Last-Translator: Allan Nordhøy \n" +"Language-Team: Norwegian Bokmål \n" +"Language: nb_NO\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.9.1\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Påskrudd" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/pl/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/pl/shadowsocks-rust.po new file mode 100644 index 000000000..d44593cd9 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/pl/shadowsocks-rust.po @@ -0,0 +1,335 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-11-17 11:07+0000\n" +"Last-Translator: Marcin Net \n" +"Language-Team: Polish \n" +"Language: pl\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.10-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Ustawienia zaawansowane" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "Wyłącz" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "Wyłączone" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "Włącz/Wyłącz" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Włączone" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "Dodatkowe argumenty" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "Ustawienia główne" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "MTU" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Przegląd" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" +"Przekazuje dodatkowe argumenty do iptables. Zachowaj szczególną ostrożność!" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Hasło" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "Serwer" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "Port serwera" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/pt/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/pt/shadowsocks-rust.po new file mode 100644 index 000000000..e6f9a8dae --- /dev/null +++ b/luci-app-shadowsocks-rust/po/pt/shadowsocks-rust.po @@ -0,0 +1,339 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-11-02 16:07+0000\n" +"Last-Translator: ssantos \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.10-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Definições Avançadas" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "Desativar" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "Desativado" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "Ativar/Desativar" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Ativado" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "Argumentos adicionais" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "Configurações Gerais" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "MTU" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Visão Geral" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "Passa argumentos adicionais para o iptables. Usar com cuidado!" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Palavra-passe" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "Servidor" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "Porta do servidor" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" + +#~ msgid "Add" +#~ msgstr "Adicionar" + +#~ msgid "Name" +#~ msgstr "Nome" diff --git a/luci-app-shadowsocks-rust/po/pt_BR/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/pt_BR/shadowsocks-rust.po new file mode 100644 index 000000000..be94ef323 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/pt_BR/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: pt_BR\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/ro/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/ro/shadowsocks-rust.po new file mode 100644 index 000000000..dfa8a011e --- /dev/null +++ b/luci-app-shadowsocks-rust/po/ro/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: ro\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/ru/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/ru/shadowsocks-rust.po new file mode 100644 index 000000000..a9a28cfe0 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/ru/shadowsocks-rust.po @@ -0,0 +1,337 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-10-19 18:26+0000\n" +"Last-Translator: Anton Kikin \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=" +"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.9.1-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Дополнительные настройки" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" + +#~ msgid "Add" +#~ msgstr "Добавить" diff --git a/luci-app-shadowsocks-rust/po/sk/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/sk/shadowsocks-rust.po new file mode 100644 index 000000000..cd806a2f8 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/sk/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: sk\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/sv/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/sv/shadowsocks-rust.po new file mode 100644 index 000000000..862d1cfae --- /dev/null +++ b/luci-app-shadowsocks-rust/po/sv/shadowsocks-rust.po @@ -0,0 +1,339 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-10-17 20:24+0000\n" +"Last-Translator: Mattias Münster \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.9.1-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Avancerade inställningar" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "Bindningsadress" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "Inaktivera" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "Inaktiverad" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "Aktivera/Inaktivera" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Aktiverad" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "Extra argument" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "Generella inställningar" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "MTU" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Översikt" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Lösenord" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "Server" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "Server-port" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" + +#~ msgid "Add" +#~ msgstr "Lägg till" + +#~ msgid "Name" +#~ msgstr "Namn" diff --git a/luci-app-shadowsocks-rust/po/templates/shadowsocks-rust.pot b/luci-app-shadowsocks-rust/po/templates/shadowsocks-rust.pot new file mode 100644 index 000000000..6c65b1d2d --- /dev/null +++ b/luci-app-shadowsocks-rust/po/templates/shadowsocks-rust.pot @@ -0,0 +1,359 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:218 +msgid "" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:44 +msgid "Add a new rule..." +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "Bind address" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:84 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:27 +msgid "Cancel" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:70 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:114 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:93 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:52 +msgid "Destination Settings" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:78 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:56 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:64 +msgid "Disable" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:129 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:129 +msgid "Disabled" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:113 +msgid "Dst default" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:97 +msgid "Dst ip/net bypass" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:105 +msgid "Dst ip/net bypass file" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:100 +msgid "Dst ip/net forward" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:109 +msgid "Dst ip/net forward file" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:188 +msgid "Enable MPTCP" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:187 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:185 +msgid "Enable TCP Fast Open" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:186 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:122 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:122 +msgid "Enable/Disable" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:132 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:132 +msgid "Enabled" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "Extra arguments" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:106 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:110 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:101 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:50 +msgid "General Settings" +msgstr "" + +#: luci-app-shadowsocks-rust/root/usr/share/rpcd/acl.d/luci-app-shadowsocks-rust.json:3 +msgid "Grant service list access to LuCI app shadowsocks-rust" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:184 +msgid "IPv6 First" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:50 +msgid "Import" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:21 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:58 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:60 +msgid "Import Links" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Ingress interfaces" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:242 +msgid "Install package" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Key (base64)" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:57 +msgid "Label" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +#: luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json:14 +msgid "Local Instances" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local address" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:121 +msgid "Local port" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Local-out default" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "MTU" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:152 +msgid "Method" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:172 +msgid "Mode of operation" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:33 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:74 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:105 +msgid "Overview" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:241 +msgid "Package is not installed" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:80 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:157 +msgid "Password" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:167 +msgid "Plugin" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:169 +msgid "Plugin Options" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:184 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:32 +#: luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +#: luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json:32 +msgid "Redir Rules" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +#: luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json:23 +msgid "Remote Servers" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:115 +msgid "Remote server" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Run as" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:117 +msgid "Running" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:144 +msgid "Server" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:148 +msgid "Server port" +msgstr "" + +#: luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +#: luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json:3 +msgid "Shadowsocks-rust" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "Source Settings" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:92 +msgid "Src default" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:83 +msgid "Src ip/net bypass" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Src ip/net checkdst" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Src ip/net forward" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:88 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:97 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Timeout (sec)" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "Tunnel address" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:183 +msgid "Verbose" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "ss-redir for TCP" +msgstr "" + +#: luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:65 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/tr/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/tr/shadowsocks-rust.po new file mode 100644 index 000000000..c453bec19 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/tr/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: tr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/uk/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/uk/shadowsocks-rust.po new file mode 100644 index 000000000..ac46a2cc5 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/uk/shadowsocks-rust.po @@ -0,0 +1,341 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-11-05 01:57+0000\n" +"Last-Translator: Yurii Petrashko \n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=" +"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.10-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "Додаткові параметри" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "Увімкнути/Вимкнути" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "Увімкнено" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "Додаткові аргументи" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "Загальні параметри" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "MTU" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "Огляд" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" +"Передача додаткових аргументів для IPTables. Використовуйте з обережністю!" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "Пароль" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" + +#~ msgid "Add" +#~ msgstr "Додати" + +#~ msgid "Name" +#~ msgstr "Ім'я" diff --git a/luci-app-shadowsocks-rust/po/vi/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/vi/shadowsocks-rust.po new file mode 100644 index 000000000..3fe59c284 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/vi/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: vi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/po/zh-cn/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/zh-cn/shadowsocks-rust.po new file mode 100644 index 000000000..0a0361f18 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/zh-cn/shadowsocks-rust.po @@ -0,0 +1,352 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-11-08 21:05+0000\n" +"Last-Translator: Meano Lee \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh-cn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.10-dev\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "-- 实例类型 --" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "<已隐藏>" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "高级设置" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "绑定地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "对于目的地址在列表中的报文,绕过ss-redir" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "对于源地址在列表中的报文,绕过ss-redir" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "对于源地址在列表中的报文,继续检查其目的地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "对于设备本身产生的TCP报文的默认行为" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "对于目的地址不在列表中的报文的默认行为" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "对于源地址不在列表中的报文的默认行为" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" +"在此页面设定访问远端shadowsocks服务器的参数。请注意,禁用远端服务器会同时停止" +"与之关联的shadowsocks-rust组件" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "目的地址设定" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "禁用" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "已禁用" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "目的未匹配时默认行为" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "绕过" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "绕过(文件)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "转发" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "转发(文件)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "启用SO_REUSEPORT" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "启用TCP Fast Open" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "启用TCP_NODELAY" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "启用/禁用" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "已启用" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "额外参数" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "文件列出需要绕过ss-redir转发的地址和网段" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "文件列出需要使用ss-redir转发的地址和网段" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "转发被连接重置的地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "若近期多次收到某地址的连接重置报文,则将其加入到转发列表中" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "对于目的地址在列表中的报文,通过ss-redir转发" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "对于源地址在列表中的报文,通过ss-redir转发" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "基本设置" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "IPv6优先" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "入口网卡" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "安装软件包" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "安装iptables-mod-conntrack-extra" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" +"此页面展示本地运行的shadowsocks-rust各组件实例,如ss-local、ss-redir、ss-" +"tunnel、ss-server等。请注意,实际启用一个实例要求实例本身及所关联的远端服务器" +"都是启用状态。" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "密钥(base64)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "本地实例" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "监听地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "监听端口" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "本地报文默认行为" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "MTU" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "加密方法" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "工作模式" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" +"在此页面,您可以配置指定报文是否通过ss-redir转发。启用后,规则会先将报文的源" +"地址与相应的地址集进行匹配,依次决定是否“绕过(bypass)”、“转发" +"(forward)”,或“继续匹配目的地址(checkdst)”;若未在集合" +"中找到匹配,则执行指定的默认动作。继续匹配目的地址时同理。" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "仅对来自指定网卡的报文应用规则" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "概览" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "依赖包未安装" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "给iptables的额外参数。请小心使用" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "密码" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "启用插件" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "插件选项" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "名字解析时优先取用IPv6地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "转发规则" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "远端服务器" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "服务器" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "运行时用户" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "运行中" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "监听地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "监听端口" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "源地址设定" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "源未匹配默认行为" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "绕过" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "继续匹配目的地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "转发" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "ss-server建立连接时使用的源地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "ss-tunnel所建立隧道的对端地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "超时时间(秒)" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "隧道对端地址" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "记录详细日志" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "用于TCP转发的ss-redir" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "用于UDP转发的ss-redir" + +#~ msgid "Add" +#~ msgstr "添加" + +#~ msgid "Install package %q" +#~ msgstr "安装%q" + +#~ msgid "Name" +#~ msgstr "名称" diff --git a/luci-app-shadowsocks-rust/po/zh-tw/shadowsocks-rust.po b/luci-app-shadowsocks-rust/po/zh-tw/shadowsocks-rust.po new file mode 100644 index 000000000..3d44a0aa0 --- /dev/null +++ b/luci-app-shadowsocks-rust/po/zh-tw/shadowsocks-rust.po @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"Language: zh_Hant\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:43 +msgid "-- instance type --" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:211 +msgid "" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:76 +msgid "Advanced Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:86 +msgid "Bind address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:87 +msgid "Bypass ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:73 +msgid "Bypass ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:79 +msgid "" +"Continue to have dst address checked for packets with src address in this " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:59 +msgid "Default action for locally generated TCP packets" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:103 +msgid "" +"Default action for packets whose dst address do not match any of the dst ip " +"list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:82 +msgid "" +"Default action for packets whose src address do not match any of the src ip/" +"net list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:14 +msgid "" +"Definition of remote shadowsocks servers. Disable any of them will also " +"disable instances referring to it." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:43 +msgid "Destination Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:77 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:45 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:20 +msgid "Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:128 +msgid "Disabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:102 +msgid "Dst default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:86 +msgid "Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:94 +msgid "Dst ip/net bypass file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:89 +msgid "Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:98 +msgid "Dst ip/net forward file" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:181 +msgid "Enable SO_REUSEPORT" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:179 +msgid "Enable TCP Fast Open" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:180 +msgid "Enable TCP_NODELAY" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:121 +msgid "Enable/Disable" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:131 +msgid "Enabled" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:68 +msgid "Extra arguments" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:95 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:99 +msgid "" +"File containing ip/net for the purposes as with Dst ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:118 +msgid "Forward recentrst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:119 +msgid "" +"Forward those packets whose dst have recently sent to us multiple tcp-rst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:90 +msgid "Forward through ss-redir for packets with dst address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:76 +msgid "Forward through ss-redir for packets with src address in this list" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:75 +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:41 +msgid "General Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "IPv6 First" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:62 +msgid "Ingress interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:235 +msgid "Install package" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:111 +msgid "Install package iptables-mod-conntrack-extra" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:25 +msgid "" +"Instances of shadowsocks-rust components, e.g. ss-local, ss-redir, ss-" +"tunnel, ss-server, etc. To enable an instance it is required to enable both " +"the instance itself and the remote server it refers to." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:155 +msgid "Key (base64)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:24 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:13 +msgid "Local Instances" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:113 +msgid "Local address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:117 +msgid "Local port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:58 +msgid "Local-out default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:171 +msgid "MTU" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:146 +msgid "Method" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:166 +msgid "Mode of operation" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:31 +msgid "" +"On this page you can configure how traffics are to be forwarded to ss-redir " +"instances. If enabled, packets will first have their src ip addresses " +"checked against Src ip/net bypass, Src ip/net forward, " +"Src ip/net checkdst and if none matches Src default will " +"give the default action to be taken. If the prior check results in action " +"checkdst, packets will continue to have their dst addresses checked." +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:63 +msgid "Only apply rules on packets from these network interfaces" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:104 +msgid "Overview" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:234 +msgid "Package is not installed" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:69 +msgid "Passes additional arguments to iptables. Use with care!" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:151 +msgid "Password" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:161 +msgid "Plugin" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:163 +msgid "Plugin Options" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:178 +msgid "Prefer IPv6 addresses when resolving names" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:30 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:21 +msgid "Redir Rules" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/servers.js:13 +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:17 +msgid "Remote Servers" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:111 +msgid "Remote server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:175 +msgid "Run as" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:116 +msgid "Running" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:138 +msgid "Server" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:142 +msgid "Server port" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/luasrc/controller/shadowsocks-rust.lua:9 +msgid "Shadowsocks-rust" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:42 +msgid "Source Settings" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:81 +msgid "Src default" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:72 +msgid "Src ip/net bypass" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:78 +msgid "Src ip/net checkdst" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:75 +msgid "Src ip/net forward" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:87 +msgid "The address ss-server will initiate connection from" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:96 +msgid "The address ss-tunnel will forward traffic to" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:173 +msgid "Timeout (sec)" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/instances.js:95 +msgid "Tunnel address" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js:177 +msgid "Verbose" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:51 +msgid "ss-redir for TCP" +msgstr "" + +#: applications/luci-app-shadowsocks-rust/htdocs/luci-static/resources/view/shadowsocks-rust/rules.js:54 +msgid "ss-redir for UDP" +msgstr "" diff --git a/luci-app-shadowsocks-rust/root/etc/uci-defaults/40_luci-shadowsocks-rust b/luci-app-shadowsocks-rust/root/etc/uci-defaults/40_luci-shadowsocks-rust new file mode 100644 index 000000000..2ca303ff8 --- /dev/null +++ b/luci-app-shadowsocks-rust/root/etc/uci-defaults/40_luci-shadowsocks-rust @@ -0,0 +1,13 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@shadowsocks-rust[-1] + add ucitrack shadowsocks-rust + set ucitrack.@shadowsocks-rust[-1].init=shadowsocks-rust + commit ucitrack +EOF + +rm -f /tmp/luci-indexcache +mkdir -p /etc/shadowsocks-rust +/etc/init.d/rpcd reload +exit 0 diff --git a/luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json b/luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json new file mode 100644 index 000000000..5a3a575b6 --- /dev/null +++ b/luci-app-shadowsocks-rust/root/usr/share/luci/menu.d/luci-app-shadowsocks-rust.json @@ -0,0 +1,39 @@ +{ + "admin/services/shadowsocks-rust": { + "title": "Shadowsocks-rust", + "order": 59, + "action": { + "type": "firstchild" + }, + "depends": { + "acl": [ "luci-app-shadowsocks-rust" ] + } + }, + + "admin/services/shadowsocks-rust/instances": { + "title": "Local Instances", + "order": 10, + "action": { + "type": "view", + "path": "shadowsocks-rust/instances" + } + }, + + "admin/services/shadowsocks-rust/servers": { + "title": "Remote Servers", + "order": 20, + "action": { + "type": "view", + "path": "shadowsocks-rust/servers" + } + }, + + "admin/services/shadowsocks-rust/rules": { + "title": "Redir Rules", + "order": 30, + "action": { + "type": "view", + "path": "shadowsocks-rust/rules" + } + } +} diff --git a/luci-app-shadowsocks-rust/root/usr/share/rpcd/acl.d/luci-app-shadowsocks-rust.json b/luci-app-shadowsocks-rust/root/usr/share/rpcd/acl.d/luci-app-shadowsocks-rust.json new file mode 100644 index 000000000..9f75c1661 --- /dev/null +++ b/luci-app-shadowsocks-rust/root/usr/share/rpcd/acl.d/luci-app-shadowsocks-rust.json @@ -0,0 +1,17 @@ +{ + "luci-app-shadowsocks-rust": { + "description": "Grant service list access to LuCI app shadowsocks-rust", + "read": { + "ubus": { + "service": [ "list" ] + }, + "uci": [ "shadowsocks-rust" ] + }, + "write": { + "file": { + "/etc/shadowsocks-rust/*": [ "write" ] + }, + "uci": [ "shadowsocks-rust" ] + } + } +} From 6d89898a842f7d31512b842741cc9b4d4af86731 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 1 Oct 2023 07:39:51 +0200 Subject: [PATCH 1115/2059] Remove mno-outlin-atomics for Rust --- rust/rust-values.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/rust-values.mk b/rust/rust-values.mk index 26935c0f6..aaa520d57 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -54,6 +54,6 @@ ifeq ($(ARCH),arm) endif endif -ifeq ($(ARCH),aarch64) - RUST_CFLAGS:=-mno-outline-atomics -endif +#ifeq ($(ARCH),aarch64) +# RUST_CFLAGS:=-mno-outline-atomics +#endif From 8746eaf337a1e68530f09a3b5d6bf09f3f820a2a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 2 Oct 2023 21:24:32 +0200 Subject: [PATCH 1116/2059] Fixes on MPTCP support with 6.1 kernel and XRay --- xray-core/files/etc/init.d/xray | 2 +- xray-core/files/etc/uci-defaults/3010-omr-xray | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/xray-core/files/etc/init.d/xray b/xray-core/files/etc/init.d/xray index f3c0566c3..5d6b49d37 100755 --- a/xray-core/files/etc/init.d/xray +++ b/xray-core/files/etc/init.d/xray @@ -1375,7 +1375,7 @@ add_inbound_setting() { json_add_boolean "tcpFastOpen" "$ss_sockopt_tcp_fast_open" if version_over_5_4; then test -n "$ss_sockopt_mptcp" && \ - json_add_boolean "mptcp" "$ss_sockopt_mptcp" + json_add_boolean "tcpMptcp" "$ss_sockopt_mptcp" fi test -n "$ss_sockopt_tproxy" && \ json_add_string "tproxy" "$ss_sockopt_tproxy" diff --git a/xray-core/files/etc/uci-defaults/3010-omr-xray b/xray-core/files/etc/uci-defaults/3010-omr-xray index 7897ae2cf..69cce605e 100644 --- a/xray-core/files/etc/uci-defaults/3010-omr-xray +++ b/xray-core/files/etc/uci-defaults/3010-omr-xray @@ -67,6 +67,7 @@ if [ -z "$(uci -q get xray.main)" ]; then set xray.omrout.ss_tls_key_file='/etc/luci-uploads/client.key' set xray.omrout.s_shadowsocks_port='65252' set xray.omrout.mux_concurrency='8' + set xray.omrout.ss_sockopt_mptcp='1' set xray.omr=inbound set xray.omr.tag='omrtunnel' set xray.omr.listen='0.0.0.0' @@ -199,4 +200,11 @@ if [ "$(uci -q get xray.omrout.s_socks_port)" = "" ]; then EOF fi +if [ "$(uci -q get xray.omrout.ss_sockopt_mptcp)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set xray.omrout.ss_sockopt_mptcp='1' + commit xray + EOF +fi + exit 0 \ No newline at end of file From cd69bc64549cb021e38251a380e4226b4926617c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 2 Oct 2023 21:25:23 +0200 Subject: [PATCH 1117/2059] Add services check for XRay and Shadowsocks-Rust --- .../share/omr/post-tracking.d/010-services | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index 4d92a4923..9a20c4796 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -12,6 +12,11 @@ if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] /etc/init.d/shadowsocks-libev restart 2>&1 >/dev/null sleep 5 fi +if [ -f /etc/init.d/shadowsocks-rust ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f sslocal)" = "" ] && [ "$(pgrep -f sslocal)" = "" ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "192.18.1.3" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" != "" ]; then + _log "Can't find Shadowsocks Rust, restart it..." + /etc/init.d/shadowsocks-rust restart 2>&1 >/dev/null + sleep 5 +fi if [ -f /etc/init.d/glorytun ] && [ "$(pgrep glorytun)" = "" ] && [ "$(uci -q get glorytun.vpn.enable)" = "1" ] && [ -f /etc/init.d/glorytun ] && [ "$(uci -q get glorytun.vpn.key)" != "" ]; then _log "Can't find Glorytun, restart it..." /etc/init.d/glorytun restart 2>&1 >/dev/null @@ -63,6 +68,11 @@ if [ "$(pgrep -f v2ray)" = "" ] && [ "$(uci -q get v2ray.main.enabled)" = "1" ] /etc/init.d/v2ray restart 2>&1 >/dev/null sleep 5 fi +if [ "$(pgrep -f xray)" = "" ] && [ "$(uci -q get xray.main.enabled)" = "1" ] && [ -f /etc/init.d/xray ]; then + _log "Can't find XRay, restart it..." + /etc/init.d/xray restart 2>&1 >/dev/null + sleep 5 +fi if [ "$(pgrep miniupnpd)" = "" ] && [ "$(uci -q get upnpd.config.enabled)" = "1" ] && [ -f /etc/init.d/miniupnpd ]; then _log "Can't find miniupnpd, restart it..." /etc/init.d/miniupnpd restart 2>&1 >/dev/null @@ -95,13 +105,17 @@ if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ _log "Can't find omr-tracker-v2ray, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi +if [ "$(uci -q get xray.main.enabled)" = "1" ] && [ -f /etc/init.d/xray ] && [ "$(pgrep -f omr-tracker-xray)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then + _log "Can't find omr-tracker-xray, restart omr-tracker..." + /etc/init.d/omr-tracker restart 2>&1 >/dev/null +fi set_get_config() { local server=$1 [ -n "$server" ] && uci -q set openmptcprouter.${server}.get_config=1 } -if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ]; then +if ([ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ]) || ([ -f /etc/init.d/shadowsocks-rust ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "192.18.1.3" ]); then config_load openmptcprouter config_foreach set_get_config server [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter @@ -112,6 +126,11 @@ if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi +if [ -f /etc/init.d/shadowsocks-rust ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.rust.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then + _log "Can't find omr-tracker-ss, restart omr-tracker..." + /etc/init.d/omr-tracker restart 2>&1 >/dev/null +fi + if [ "$(uci -q get glorytun.vpn.enable)" = "1" ] && [ "$(uci -q get glorytun.vpn.key)" = "" ]; then config_load openmptcprouter config_foreach set_get_config server @@ -124,6 +143,12 @@ if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ "$(uci -q get v2ray.omrout. [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi +if [ "$(uci -q get xray.main.enabled)" = "1" ] && [ "$(uci -q get xray.omrout.s_vless_user_id)" = "" ]; then + config_load openmptcprouter + config_foreach set_get_config server + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter +fi + if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then _log "Workaround Ring expansion failed problem" echo 1 > /sys/bus/pci/devices/0000:00:00.0/remove From 84f0cf5782694f6546c167e5f6a2210cacdb518f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 3 Oct 2023 11:53:06 +0200 Subject: [PATCH 1118/2059] Changes for RUTX support on 6.1 kernel --- mptcp/files/usr/share/omr/post-tracking.d/050-rutx | 2 +- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/050-rutx b/mptcp/files/usr/share/omr/post-tracking.d/050-rutx index 1ea024164..c815264a9 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/050-rutx +++ b/mptcp/files/usr/share/omr/post-tracking.d/050-rutx @@ -6,7 +6,7 @@ # # This script set lights on RUTX device -if [ -n "$(grep RUTX /etc/board.json)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then +if [ -n "$(grep RUTX /etc/board.json)" ] && [ -z "$(grep RUTX50 /etc/board.json)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then if [ "$OMR_TRACKER_DEVICE" = "wwan0" ]; then modemdata=$(omr-modemmanager '/sys/devices/platform/soc/60f8800.usb2/6000000.dwc3/xhci-hcd.1.auto/usb3/3-1' all) gen=$(echo $modemdata | cut -d ';' -f 5 | tr -d '\n') diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 9e80c2a5d..20e278230 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -351,7 +351,7 @@ uci -q delete network.loopback.ifname uci -q set network.loopback.device='lo' local board=$(board_name) -if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then +if ([ "$board" = "teltonika,rutx" ] || [ "$board" = "teltonika,rutx12" ] || [ "$board" = "teltonika,rutx50" ]) && [ -f /sbin/mnf_info ]; then # Same part for RUTX12 and RUTX11, maybe other RUTX ? uci -q batch <<-EOF set network.modem1=interface @@ -388,6 +388,11 @@ if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then commit firewall EOF fi + if [ "$(mnf_info -n)" = "RUTX5000XXXX" ]; then + uci -q batch <<-EOF + set network.modem1.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb2/2-1' + EOF + fi uci -q batch <<-EOF set network.wifi24=interface set network.wifi24.proto='none' From 1f152e63c9bc0683aa3a472b8910d6529fb5a075 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 3 Oct 2023 17:51:43 +0200 Subject: [PATCH 1119/2059] Fixes on Shadowsocks to VPS --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 48398be4e..44df06797 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1584,17 +1584,17 @@ _set_config_from_vps() { ss_port="65280" #ss_fast_open="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-rust.fast_open')" config_load shadowsocks-rust - #config_foreach _set_ss_redir ss_redir "fast_open" $ss_fast_open - #config_foreach _set_ss_redir ss_local "fast_open" $ss_fast_open + #config_foreach _set_ssrust_redir ss_redir "fast_open" $ss_fast_open + #config_foreach _set_ssrust_redir ss_local "fast_open" $ss_fast_open uci -q batch <<-EOF >/dev/null set shadowsocks-rust.sss0.password=$ssgo_sskey set shadowsocks-rust.sss0.server_port=$ss_port set shadowsocks-rust.sss0.method=$ss_method EOF - config_foreach _set_ss_server server "key" $ssgo_sskey - config_foreach _set_ss_server server "method" $ss_method + config_foreach _set_ssrust_server server "key" $ssgo_sskey + config_foreach _set_ssrust_server server "method" $ss_method if [ "$(uci -q get shadowsocks-rust.sss0.server)" != "127.0.0.1" ]; then - config_foreach _set_ss_server server "server" $vpsip + config_foreach _set_ssrust_server server "server" $vpsip fi uci -q commit shadowsocks-rust if [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]; then From bea73de8fc524272a521867ad87fbab2c3d16f9d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 4 Oct 2023 11:25:47 +0200 Subject: [PATCH 1120/2059] Force disable Fast Open for Shadowsocks Rust/Go --- .../files/etc/init.d/openmptcprouter-vps | 4 +++- .../files/shadowsocks-rust.config | 21 +++---------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 44df06797..4bf424048 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -323,10 +323,12 @@ _set_ssgo_server_vps() { config_load shadowsocks-rust config_foreach _get_ss_redir ss_redir config_foreach _get_ss_server server + # Force disable fast open for now du to problem on 6.1 with MPTCP + fast_open="false" if [ "$current_mptcp" != "$mptcp" ] || [ "$current_port" != "$port" ] || [ "$current_method" != "$method" ] || [ "$current_fast_open" != "$fast_open" ]; then local settings - settings='{"port": '$port',"method":"'$method'","fast_open":'$fast_open',"reuse_port":true,"mptcp":'$mptcp'}' + settings='{"port": '$port',"method":"'$method'","fast_open":'$fast_open',"reuse_port":false,"mptcp":'$mptcp'}' result=$(_set_json "shadowsocks-go" "$settings") fi } diff --git a/shadowsocks-rust/files/shadowsocks-rust.config b/shadowsocks-rust/files/shadowsocks-rust.config index 82d13a389..8dfa5197a 100644 --- a/shadowsocks-rust/files/shadowsocks-rust.config +++ b/shadowsocks-rust/files/shadowsocks-rust.config @@ -7,25 +7,10 @@ config ss_redir hi1 option fast_open 0 option verbose 0 option syslog 1 - option reuse_port 1 + option reuse_port 0 option mptcp 1 option ipv6_first 1 - option no_delay 1 - -config ss_redir hi2 - option server 'sss0' - option local_address '0.0.0.0' - option local_port '1100' - option mode 'tcp_and_udp' - option timeout '1000' - option fast_open 1 - option verbose 0 - option syslog 1 - option reuse_port 1 - option mptcp 1 - option ipv6_first 1 - option no_delay 1 - option disabled 1 + option no_delay 0 config ss_rules 'ss_rules' option disabled 0 @@ -39,7 +24,7 @@ config server 'sss0' option disabled 1 option server '192.168.1.3' option server_port '65280' - option key '' + option password '' option method '2022-blake3-aes-256-gcm' option obfs 0 From 9519b730512ae0c9cf504d780a563891ead4365c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 4 Oct 2023 12:00:52 +0200 Subject: [PATCH 1121/2059] Fix Xray Shadowsocks 2022 key --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 4bf424048..a575b5645 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1649,7 +1649,7 @@ _set_config_from_vps() { set xray.omrout.s_vless_user_id="$xray_key" set xray.omrout.s_vless_port="$xray_port" EOF - uci -q set xray.omrout.s_shadowsocks_password=$ss_key + #uci -q set xray.omrout.s_shadowsocks_password=$xray_sskey if [ "$(uci -q get xray.omrout.s_vmess_address)" != "127.0.0.1" ]; then uci -q set xray.omrout.s_vmess_address="$vpsip" uci -q set xray.omrout.s_vless_address="$vpsip" From 23d024beb7f2ea9971c13a9f5b787343d79a6fc7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 4 Oct 2023 12:03:25 +0200 Subject: [PATCH 1122/2059] Fix Shadowsocks Rust password --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index a575b5645..3ac9c4304 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1593,7 +1593,7 @@ _set_config_from_vps() { set shadowsocks-rust.sss0.server_port=$ss_port set shadowsocks-rust.sss0.method=$ss_method EOF - config_foreach _set_ssrust_server server "key" $ssgo_sskey + config_foreach _set_ssrust_server server "password" $ssgo_sskey config_foreach _set_ssrust_server server "method" $ss_method if [ "$(uci -q get shadowsocks-rust.sss0.server)" != "127.0.0.1" ]; then config_foreach _set_ssrust_server server "server" $vpsip From 4804de524140d024e137668f68744f66ac514891 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 5 Oct 2023 07:51:57 +0200 Subject: [PATCH 1123/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/2989 --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm index 83016ce63..0b66c1662 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm @@ -28,7 +28,7 @@ menuentry = ucic:get("openmptcprouter","settings","menu") or "openmptcprouter" lastmodif="" allbackup=luci.model.uci.cursor():get("openmptcprouter",servername,"allbackup") for _, backup in pairs(allbackup) do - filemodif=split(backup, '|') + filemodif=luci.util.split(backup, '|') if filemodif[2] ~= lastmodif then lastmodif=filemodif[2] %> From fbcbcc80ab7f94d90a358a1f6fbb5ac6e86492bd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 5 Oct 2023 17:45:21 +0200 Subject: [PATCH 1124/2059] Fix Shadowsocks Rust crypto change --- .../luasrc/controller/openmptcprouter.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 45a55985a..299e3bd95 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -926,8 +926,8 @@ function wizard_add() ucic:set("xray","omrout","s_trojan_user_security","aes-128-gcm") ucic:set("xray","omrout","s_socks_user_security","aes-128-gcm") ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-aes-256-gcm") - ucic:set("shadowsocks-rust","sss0","s_shadowsocks_method","2022-blake3-aes-256-gcm") - ucic:set("shadowsocks-rust","sss1","s_shadowsocks_method","2022-blake3-aes-256-gcm") + ucic:set("shadowsocks-rust","sss0","method","2022-blake3-aes-256-gcm") + ucic:set("shadowsocks-rust","sss1","method","2022-blake3-aes-256-gcm") elseif encryption == "aes-256-cfb" then ucic:set("openmptcprouter","settings","encryption","aes-256-cfb") ucic:set("shadowsocks-libev","sss0","method","aes-256-cfb") @@ -945,15 +945,15 @@ function wizard_add() ucic:set("xray","omrout","s_trojan_user_security","aes-128-gcm") ucic:set("xray","omrout","s_socks_user_security","aes-128-gcm") ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-aes-256-gcm") - ucic:set("shadowsocks-rust","sss0","s_shadowsocks_method","2022-blake3-aes-256-gcm") - ucic:set("shadowsocks-rust","sss1","s_shadowsocks_method","2022-blake3-aes-256-gcm") + ucic:set("shadowsocks-rust","sss0","method","2022-blake3-aes-256-gcm") + ucic:set("shadowsocks-rust","sss1","method","2022-blake3-aes-256-gcm") elseif encryption == "chacha20-ietf-poly1305" then ucic:set("openmptcprouter","settings","encryption","chacha20") ucic:set("shadowsocks-libev","sss0","method","chacha20-ietf-poly1305") ucic:set("shadowsocks-libev","sss1","method","chacha20-ietf-poly1305") ucic:set("glorytun","vpn","chacha20","1") ucic:set("glorytun-udp","vpn","chacha","1") - ucic:set("openvpn","omr","cipher","AES-256-CBC") + ucic:set("openvpn","omr","cipher","AES-256-GCM") ucic:set("mlvpn","general","cleartext_data","0") ucic:set("v2ray","omrout","s_vmess_user_security","chacha20-poly1305") ucic:set("v2ray","omrout","s_vless_user_security","chacha20-poly1305") @@ -964,8 +964,10 @@ function wizard_add() ucic:set("xray","omrout","s_trojan_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_socks_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-chacha20-poly1305") - ucic:set("shadowsocks-rust","sss0","s_shadowsocks_method","2022-blake3-chacha20-poly1305") - ucic:set("shadowsocks-rust","sss1","s_shadowsocks_method","2022-blake3-chacha20-poly1305") + --ucic:set("shadowsocks-rust","sss0","method","2022-blake3-chacha20-poly1305") + --ucic:set("shadowsocks-rust","sss1","method","2022-blake3-chacha20-poly1305") + ucic:set("shadowsocks-rust","sss0","method","2022-blake3-aes-256-gcm") + ucic:set("shadowsocks-rust","sss1","method","2022-blake3-aes-256-gcm") else ucic:set("openmptcprouter","settings","encryption","other") end From 4f7efcd9115173d6ed9025e4377f7600c6110545 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 6 Oct 2023 11:16:52 +0200 Subject: [PATCH 1125/2059] Fix Shadowsocks Rust tracker --- omr-tracker/files/bin/omr-tracker-ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index c1f00a345..82b7ad3ce 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -166,7 +166,7 @@ while true; do /etc/init.d/shadowsocks-libev restart sleep 5 fi - if [ "$type" = "rust" ] && [ "$(pgrep ss-redir)" = "" ] && [ "$(uci -q get shadowsocks-libev.${server}.key)" != "" ]; then + if [ "$type" = "rust" ] && [ "$(pgrep sslocal)" = "" ] && [ "$(uci -q get shadowsocks-libev.${server}.key)" != "" ]; then _log "Can't find shadowsocks rust, restart it..." /etc/init.d/shadowsocks-rust restart sleep 5 From 5869e2f6041bc789e67803bd2c778bd52cce334b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 6 Oct 2023 11:17:44 +0200 Subject: [PATCH 1126/2059] Fix RUTX50 Leds --- .../usr/share/omr/post-tracking.d/050-rutx | 35 +++++++++++++++ .../files/etc/uci-defaults/2060-omr-system | 45 ++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/050-rutx b/mptcp/files/usr/share/omr/post-tracking.d/050-rutx index c815264a9..c4a2bc2dc 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/050-rutx +++ b/mptcp/files/usr/share/omr/post-tracking.d/050-rutx @@ -93,3 +93,38 @@ if [ -n "$(grep RUTX /etc/board.json)" ] && [ -z "$(grep RUTX50 /etc/board.json) fi fi fi +if [ -n "$(grep RUTX /etc/board.json)" ] && [ -n "$(grep RUTX50 /etc/board.json)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + if [ "$OMR_TRACKER_DEVICE" = "wwan0" ]; then + modemdata=$(omr-modemmanager '/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb2/2-1' all) + gen=$(echo $modemdata | cut -d ';' -f 5 | tr -d '\n') + if [ "$gen" = "gsm" ]; then + echo "default-on" > /sys/class/leds/green:3g/trigger + echo "none" > /sys/class/leds/green:4g/trigger + echo "none" > /sys/class/leds/green:5g/trigger + elif [ "$gen" = "umts" ]; then + echo "none" > /sys/class/leds/green:3g/trigger + echo "default-on" > /sys/class/leds/green:4g/trigger + echo "none" > /sys/class/leds/green:5g/trigger + elif [ "$gen" = "lte" ]; then + echo "none" > /sys/class/leds/green:3g/trigger + echo "none" > /sys/class/leds/green:4g/trigger + echo "default-on" > /sys/class/leds/green:5g/trigger + fi + bar=$(echo $modemdata | cut -d ';' -f 1 | tr -d '\n') + if [ "$bar" -gt "10" ]; then + echo "default-on" > /sys/class/leds/green:rssi0/trigger + else + echo "none" > /sys/class/leds/green:rssi0/trigger + fi + if [ "$bar" -gt "50" ]; then + echo "default-on" > /sys/class/leds/green:rssi1/trigger + else + echo "none" > /sys/class/leds/green:rssi1/trigger + fi + if [ "$bar" -gt "70" ]; then + echo "default-on" > /sys/class/leds/green:rssi2/trigger + else + echo "none" > /sys/class/leds/green:rssi2/trigger + fi + fi +fi diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index fbb1a6912..ec8de8d5b 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -39,7 +39,50 @@ fi EOF } -if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" ] && [ -z "$(uci show system | grep WAN_ETH)" ]; then +if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx50)" ] && [ -z "$(uci show system | grep WAN_ETH)" ]; then + uci -q batch <<-EOF >/dev/null + add system led + set system.@led[-1].sysfs='green:eth' + set system.@led[-1].name='WAN_ETH' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='eth0' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' + add system led + set system.@led[-1].sysfs='green:wifi' + set system.@led[-1].name='WAN_WIFI' + set system.@led[-1].trigger='netdev' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' + add system led + set system.@led[-1].sysfs='green:sim1' + set system.@led[-1].name='WAN_MODEM1' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='wwan0' + set system.@led[-1].mode='rx' + add system led + set system.@led[-1].name='WAN_MODEM2' + set system.@led[-1].sysfs='green:sim2' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='wwan1' + set system.@led[-1].mode='rx' + add system led + set system.@led[-1].name='WIFI24' + set system.@led[-1].sysfs='green:wifi2g' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='radio0.network1' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' + add system led + set system.@led[-1].name='WIFI5' + set system.@led[-1].sysfs='green:wifi5g' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='radio1.network1' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' + commit system + EOF +elif [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" ] && [ -z "$(uci show system | grep WAN_ETH)" ]; then uci -q batch <<-EOF >/dev/null add system led set system.@led[-1].sysfs='wan_wifi_4' From 2ee3878886873648e03d57a79af008288810dfbe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 6 Oct 2023 11:28:08 +0200 Subject: [PATCH 1127/2059] Fix wait_test parameter on omr-tracker --- omr-tracker/files/etc/init.d/omr-tracker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 9a78b2378..31be2a0d5 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -243,7 +243,7 @@ _launch_shadowsocks_tracker() { procd_append_param env "OMR_TRACKER_TRIES=$tries" procd_append_param env "OMR_TRACKER_INTERVAL=$interval" procd_append_param env "OMR_TRACKER_PROXY=127.0.0.1:$local_port" - procd_append_param env "OMR_TRACKER_WAIT_TEST=$type" + procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" procd_append_param env "OMR_TRACKER_SERVER=$server" procd_append_param env "OMR_TRACKER_SS_TYPE=libev" procd_set_param limits nofile="51200 51200" @@ -277,7 +277,7 @@ _launch_shadowsocks_rust_tracker() { procd_append_param env "OMR_TRACKER_TRIES=$tries" procd_append_param env "OMR_TRACKER_INTERVAL=$interval" procd_append_param env "OMR_TRACKER_PROXY=127.0.0.1:$local_port" - procd_append_param env "OMR_TRACKER_WAIT_TEST=$type" + procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" procd_append_param env "OMR_TRACKER_SERVER=$server" procd_append_param env "OMR_TRACKER_SS_TYPE=rust" procd_set_param limits nofile="51200 51200" From e56c73bf7d7fbca4287ef96ce7828e8bfa1242a1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 6 Oct 2023 15:04:05 +0200 Subject: [PATCH 1128/2059] Fix issue when bypassing a proto without ndpi --- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 29bb9b35c..cfb3beb6d 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -498,11 +498,19 @@ _bypass_proto_without_ndpi() { ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") if [ -n "$ALLIPS" ]; then ipset -q flush bypass_$proto > /dev/null 2>&1 + ipset -q flush bypass6_$proto > /dev/null 2>&1 ipset -q --exist restore <<-EOF create bypass_$proto hash:net hashsize 64 + create bypass6_$proto hash:net hashsize 64 EOF for ip in $ALLIPS; do - ipset -q add bypass_$proto $ip + valid_ip4=$( valid_subnet4 $ip) + valid_ip6=$( valid_subnet6 $ip) + if [ "$valid_ip4" = "ok" ]; then + ipset -q add bypass_$proto $ip + elif [ "$valid_ip6" = "ok" ]; then + ipset -q add bypass6_$proto $ip + fi done if [ "$intf" = "all" ]; then if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then @@ -516,7 +524,7 @@ _bypass_proto_without_ndpi() { if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539 -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN COMMIT EOF @@ -533,7 +541,7 @@ _bypass_proto_without_ndpi() { if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539$intfid -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN COMMIT EOF From 7aec8f94709c842ed9de5720c8533e106d5e257e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 6 Oct 2023 16:51:34 +0200 Subject: [PATCH 1129/2059] Fix error when VPN is set to none --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 3ac9c4304..6da45ffc5 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -927,6 +927,7 @@ _set_vpn_ip() { local settings [ -z "$vps_config" ] && vps_config=$(_get_json "config") [ -z "$vps_config" ] && return + [ "$(uci -q get openmptcprouter.settings.vpn)" = "none" ] && return vpnifname="$(uci -q get network.omrvpn.device)" vpnip_local_current="$(echo "$vps_config" | jsonfilter -q -e '@.vpn.remoteip')" vpnip_local=$(ip -4 -br addr ls dev ${vpnifname} | awk -F'[ /]+' '{print $3}') From e93e2a6ab0242357f77dddf997cc4e944c668a1a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 6 Oct 2023 16:52:16 +0200 Subject: [PATCH 1130/2059] Fix loop restart of openmptcprouter-vps when shadowsocks-rust is used --- mptcp/files/usr/share/omr/post-tracking.d/010-services | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index 9a20c4796..f2407ea01 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -115,7 +115,7 @@ set_get_config() { [ -n "$server" ] && uci -q set openmptcprouter.${server}.get_config=1 } -if ([ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ]) || ([ -f /etc/init.d/shadowsocks-rust ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "192.18.1.3" ]); then +if ([ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ]) || ([ -f /etc/init.d/shadowsocks-rust ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.password)" = "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "192.18.1.3" ]); then config_load openmptcprouter config_foreach set_get_config server [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter From 4c19132ebd5c9f0872c7f46dbd801397c4c507f9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 9 Oct 2023 18:50:00 +0200 Subject: [PATCH 1131/2059] Add Shadowsocks-go traffic --- .../root/usr/libexec/rpcd/openmptcprouter | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index b7af3d727..a73a9c33d 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -928,6 +928,15 @@ function interfaces_status() else mArray.openmptcprouter["ss_traffic"] = "0" end + if status and vpsinfo.shadowsocks_go ~= nil then + mArray.openmptcprouter["ss_go_traffic_rx"] = vpsinfo.shadowsocks_go.rx or "0" + mArray.openmptcprouter["ss_go_traffic_tx"] = vpsinfo.shadowsocks_go.tx or "0" + mArray.openmptcprouter["ss_go_traffic"] = mArray.openmptcprouter["ss_go_traffic_tx"] + mArray.openmptcprouter["ss_go_traffic_rx"] + else + mArray.openmptcprouter["ss_go_traffic_rx"] = "0" + mArray.openmptcprouter["ss_go_traffic_tx"] = "0" + mArray.openmptcprouter["ss_go_traffic"] = "0" + end if status and vpsinfo.v2ray ~= nil then mArray.openmptcprouter["v2ray_traffic_rx"] = vpsinfo.v2ray.rx or "0" mArray.openmptcprouter["v2ray_traffic_tx"] = vpsinfo.v2ray.tx or "0" @@ -946,7 +955,7 @@ function interfaces_status() mArray.openmptcprouter["xray_traffic_tx"] = "0" mArray.openmptcprouter["xray_traffic"] = "0" end - mArray.openmptcprouter["proxy_traffic"] = mArray.openmptcprouter["ss_traffic"] + mArray.openmptcprouter["v2ray_traffic"] + mArray.openmptcprouter["xray_traffic"] + mArray.openmptcprouter["proxy_traffic"] = mArray.openmptcprouter["ss_traffic"] + mArray.openmptcprouter["v2ray_traffic"] + mArray.openmptcprouter["xray_traffic"] + mArray.openmptcprouter["ss_go_traffic"] mArray.openmptcprouter["total_traffic"] = mArray.openmptcprouter["proxy_traffic"] + mArray.openmptcprouter["vpn_traffic"] else mArray.openmptcprouter["vps_admin"] = false From a3fd1e880e796470a0c1c322c8e65c2157671c29 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 9 Oct 2023 18:50:25 +0200 Subject: [PATCH 1132/2059] Add info that Shadowsocks-go doesn't support chacha20 --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 62f8e04cd..370bfeb2e 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -316,6 +316,7 @@ <%:There is no Advanced Encryption Standard (AES) instruction set integrated in the processor, you should use chacha20.%> <% end %> <%:Encryption method is used for Shadowsocks, V2Ray/XRay, Glorytun and OpenVPN.%> + <%:Shadowsocks-go, used on server side when Shadowsocks-Rust is used, doesn't support chacha20, AES-256-GCM is used instead.%>
    From c52f0816474d5aa961765bbb72f5ce4bfb257f8e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 13 Oct 2023 21:48:24 +0200 Subject: [PATCH 1133/2059] Try to get more space on github actions --- .github/workflows/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3f5f60cfc..dd3bbf058 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,6 +34,9 @@ jobs: sudo apt-get autoclean -y >/dev/null 2>&1 || true sudo rm -rf "/usr/local/share/boost" >/dev/null 2>&1 || true sudo rm -rf "$AGENT_TOOLSDIRECTORY" >/dev/null 2>&1 || true + sudo rm -rf /usr/share/dotnet >/dev/null 2>&1 || true + sudo rm -rf /usr/local/lib/android >/dev/null 2>&1 || true + sudo rm -rf /opt/ghc >/dev/null 2>&1 || true sudo docker rmi $(docker images -qf "dangling=true") >/dev/null 2>&1 || true df -h - name: Clone source code From 8369094924ef5e0a4791a0f1620d2e76ed8710f0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 17 Oct 2023 17:35:03 +0200 Subject: [PATCH 1134/2059] Add XRay VLESS REALITY protocol support --- .../luasrc/controller/openmptcprouter.lua | 11 +++- .../luasrc/view/openmptcprouter/wizard.htm | 1 + .../files/etc/init.d/openmptcprouter-vps | 22 ++++++- xray-core/files/etc/init.d/xray | 64 ++++++++++++++++++- .../files/etc/uci-defaults/3010-omr-xray | 35 +++++++--- 5 files changed, 119 insertions(+), 14 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 299e3bd95..222036652 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -716,12 +716,14 @@ function wizard_add() local sectionname = s[".name"] ucic:set("shadowsocks-rust",sectionname,"disabled","1") end) - elseif (default_proxy == "xray" or default_proxy == "xray-vmess" or default_proxy == "xray-trojan" or default_proxy == "xray-shadowsocks" or default_proxy == "xray-socks") and serversnb > 0 and serversnb > disablednb then + elseif (default_proxy == "xray" or default_proxy == "xray-vless-reality" or default_proxy == "xray-vmess" or default_proxy == "xray-trojan" or default_proxy == "xray-shadowsocks" or default_proxy == "xray-socks") and serversnb > 0 and serversnb > disablednb then --ucic:set("shadowsocks-libev","sss0","disabled","1") ucic:set("v2ray","main","enabled","0") ucic:set("xray","main","enabled","1") if default_proxy == "xray" then ucic:set("xray","omrout","protocol","vless") + elseif default_proxy == "xray-vless-reality" then + ucic:set("xray","omrout","protocol","vless-reality") elseif default_proxy == "xray-vmess" then ucic:set("xray","omrout","protocol","vmess") elseif default_proxy == "xray-trojan" then @@ -800,6 +802,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_socks_address",server_ip) ucic:set("xray","omrout","s_vmess_address",server_ip) ucic:set("xray","omrout","s_vless_address",server_ip) + ucic:set("xray","omrout","s_vless_reality_address",server_ip) ucic:set("xray","omrout","s_trojan_address",server_ip) ucic:set("xray","omrout","s_socks_address",server_ip) ucic:set("xray","omrout","s_shadowsocks_address",server_ip) @@ -845,6 +848,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_socks_address",server_ip) ucic:set("xray","omrout","s_vmess_address",server_ip) ucic:set("xray","omrout","s_vless_address",server_ip) + ucic:set("xray","omrout","s_vless_reality_address",server_ip) ucic:set("xray","omrout","s_trojan_address",server_ip) ucic:set("xray","omrout","s_socks_address",server_ip) ucic:set("xray","omrout","s_shadowsocks_address",server_ip) @@ -906,6 +910,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_socks_user_security","none") ucic:set("xray","omrout","s_vmess_user_security","none") ucic:set("xray","omrout","s_vless_user_security","none") + ucic:set("xray","omrout","s_vless_reality_user_security","none") ucic:set("xray","omrout","s_trojan_user_security","none") ucic:set("xray","omrout","s_socks_user_security","none") ucic:set("xray","omrout","s_shadowsocks_method","none") @@ -923,6 +928,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_socks_user_security","aes-128-gcm") ucic:set("xray","omrout","s_vmess_user_security","aes-128-gcm") ucic:set("xray","omrout","s_vless_user_security","aes-128-gcm") + ucic:set("xray","omrout","s_vless_reality_user_security","aes-128-gcm") ucic:set("xray","omrout","s_trojan_user_security","aes-128-gcm") ucic:set("xray","omrout","s_socks_user_security","aes-128-gcm") ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-aes-256-gcm") @@ -942,6 +948,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_socks_user_security","aes-128-gcm") ucic:set("xray","omrout","s_vmess_user_security","aes-128-gcm") ucic:set("xray","omrout","s_vless_user_security","aes-128-gcm") + ucic:set("xray","omrout","s_vless_reality_user_security","aes-128-gcm") ucic:set("xray","omrout","s_trojan_user_security","aes-128-gcm") ucic:set("xray","omrout","s_socks_user_security","aes-128-gcm") ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-aes-256-gcm") @@ -961,6 +968,7 @@ function wizard_add() ucic:set("v2ray","omrout","s_socks_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_vmess_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_vless_user_security","chacha20-poly1305") + ucic:set("xray","omrout","s_vless_reality_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_trojan_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_socks_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-chacha20-poly1305") @@ -1040,6 +1048,7 @@ function wizard_add() ucic:commit("v2ray") ucic:set("xray","omrout","s_vmess_user_id",v2ray_user) ucic:set("xray","omrout","s_vless_user_id",v2ray_user) + ucic:set("xray","omrout","s_vless_reality_user_id",v2ray_user) ucic:set("xray","omrout","s_trojan_user_id",v2ray_user) ucic:set("xray","omrout","s_socks_user_id",v2ray_user) ucic:save("xray") diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 370bfeb2e..47a95a5f2 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -238,6 +238,7 @@ <% if nixio.fs.access("/etc/init.d/v2ray") then %><% end %> <% if nixio.fs.access("/etc/init.d/v2ray") then %><% end %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> + <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 6da45ffc5..1138bab2b 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -351,16 +351,22 @@ _set_v2ray_server_vps() { _set_xray_server_vps() { enabled=$(uci -q get xray.main.enabled) - [ "$enabled" != "1" ] && return userid=$(uci -q get xray.omrout.s_vless_user_id) + protocol=$(uci -q get xray.omrout.protocol) + if [ "$protocol" = "vless-reality" ] && [ "$enabled" = "1" ]; then + vless_reality='true' + else + vless_reality='false' + fi [ -z "$userid" ] && return [ -z "$vps_config" ] && vps_config=$(_get_json "config") [ -z "$vps_config" ] && return current_userid="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.key')" + current_vlessreality="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.vless_reality')" - if [ "$current_userid" != "$userid" ]; then + if [ "$current_userid" != "$userid" ] || [ "$current_vlessreality" != "$vless_reality" ]; then local settings - settings='{"userid": "'$userid'"}' + settings='{"userid": "'$userid'","vless_reality": '$vless_reality'}' echo $(_set_json "xray" "$settings") fi } @@ -521,6 +527,8 @@ _get_vps_config() { uci -q batch <<-EOF >/dev/null set v2ray.omrout.s_vmess_address="$vpsip" set v2ray.omrout.s_vless_address="$vpsip" + set v2ray.omrout.s_trojan_address="$vpsip" + set v2ray.omrout.s_socks_address="$vpsip" commit v2ray EOF if [ "$(uci -q get v2ray.main.enabled)" = "1" ]; then @@ -532,6 +540,10 @@ _get_vps_config() { uci -q batch <<-EOF >/dev/null set xray.omrout.s_vmess_address="$vpsip" set xray.omrout.s_vless_address="$vpsip" + set xray.omrout.s_trojan_address="$vpsip" + set xray.omrout.s_socks_address="$vpsip" + set xray.omrout.s_shadowsocks_address="$vpsip" + set xray.omrout.s_vless_reality_address="$vpsip" commit xray EOF if [ "$(uci -q get xray.main.enabled)" = "1" ]; then @@ -1635,6 +1647,7 @@ _set_config_from_vps() { # XRay settings xray_key="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.key')" xray_sskey="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.sskey')" + xray_vless_reality_key="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.vless_reality_key')" #v2ray_port="$(echo "$vps_config" | jsonfilter -q -e '@.v2ray.config.port')" xray_port="65248" if ([ -n "$xray_key" ] && [ "$xray_key" != "$(uci -q get xray.omrout.s_vmess_user_id)" ]) || ([ -n "$xray_port" ] && [ "$xray_port" != "$(uci -q get xray.omrout.s_vmess.port)" ]); then @@ -1649,11 +1662,14 @@ _set_config_from_vps() { set xray.omrout.s_vmess_port="$((xray_port+2))" set xray.omrout.s_vless_user_id="$xray_key" set xray.omrout.s_vless_port="$xray_port" + set xray.omrout.s_vless_reality_user_id="$xray_key" + set xray.omrout.s_vless_reality_public_key="$xray_vless_reality_key" EOF #uci -q set xray.omrout.s_shadowsocks_password=$xray_sskey if [ "$(uci -q get xray.omrout.s_vmess_address)" != "127.0.0.1" ]; then uci -q set xray.omrout.s_vmess_address="$vpsip" uci -q set xray.omrout.s_vless_address="$vpsip" + uci -q set xray.omrout.s_vless_reality_address="$vpsip" uci -q set xray.omrout.s_trojan_address="$vpsip" uci -q set xray.omrout.s_socks_address="$vpsip" uci -q set xray.omrout.s_shadowsocks_address="$vpsip" diff --git a/xray-core/files/etc/init.d/xray b/xray-core/files/etc/init.d/xray index 5d6b49d37..216ef152f 100755 --- a/xray-core/files/etc/init.d/xray +++ b/xray-core/files/etc/init.d/xray @@ -379,6 +379,15 @@ outbound_section_validate() { 's_vless_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ 's_vless_user_encryption:or("auto", "none")' \ 's_vless_user_level:uinteger' \ + 's_vless_reality_address:host' \ + 's_vless_reality_port:port' \ + 's_vless_reality_user_id:string' \ + 's_vless_reality_user_alter_id:and(uinteger, max(65535))' \ + 's_vless_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_vless_reality_user_encryption:or("auto", "none")' \ + 's_vless_reality_flow:string' \ + 's_vless_reality_public_key:string' \ + 's_vless_reality_user_level:uinteger' \ 's_trojan_address:host' \ 's_trojan_port:port' \ 's_trojan_user_id:string' \ @@ -455,7 +464,7 @@ add_xray_redirect_rules() { [ "$(uci -q get xray.main.inbounds | grep omr6)" != "" ] && [ -n "$OUTBOUND_SERVERS_V6" ] && { xray-rules6 -f commandline="-l $((port+1)) -L $((port+1)) -s $OUTBOUND_SERVERS_V6 --rule-name def --src-default forward --dst-default forward --local-default forward" - [ "$(uci -q get xray.main_transparent_proxy.redirect_udp)" = "1" ] && ([ "$(uci -q get xray.omrout.protocol)" = "vless" ] || [ "$(uci -q get xray.omrout.protocol)" = "vmess" ]) && commandline="$commandline -L ${port+1}" + [ "$(uci -q get xray.main_transparent_proxy.redirect_udp)" = "1" ] && ([ "$(uci -q get xray.omrout.protocol)" = "vless-reality" ] || [ "$(uci -q get xray.omrout.protocol)" = "vless" ] || [ "$(uci -q get xray.omrout.protocol)" = "vmess" ]) && commandline="$commandline -L ${port+1}" xray-rules6 $commandline } [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { @@ -1428,7 +1437,11 @@ add_outbound_setting() { test -n "$send_through" && \ json_add_string "sendThrough" "$send_through" - json_add_string "protocol" "$protocol" + if [ "$protocol" = "vless-reality" ]; then + json_add_string "protocol" "vless" + else + json_add_string "protocol" "$protocol" + fi case "${protocol:-x}" in "blackhole") @@ -1576,6 +1589,37 @@ add_outbound_setting() { json_close_object + json_close_array # vnext + json_close_object # settings + ;; + "vless-reality") + json_add_object "settings" + + json_add_array "vnext" + json_add_object "" + + json_add_string "address" "$s_vless_reality_address" + append_server_address "$s_vless_reality_address" + + json_add_int "port" "$s_vless_reality_port" + + json_add_array "users" + json_add_object "" + json_add_string "id" "$s_vless_reality_user_id" + json_add_int "alterId" "$s_vless_reality_user_alter_id" + test -n "$s_vless_reality_user_security" && \ + json_add_string "security" "$s_vless_reality_user_security" + test -n "$s_vless_reality_user_encryption" && \ + json_add_string "encryption" "$s_vless_reality_user_encryption" + test -n "$s_vless_reality_user_level" && \ + json_add_int "level" "$s_vless_reality_user_level" + test -n "$s_vless_reality_flow" && \ + json_add_string "flow" "$s_vless_reality_flow" + json_close_object + json_close_array # users + + json_close_object + json_close_array # vnext json_close_object # settings ;; @@ -1660,6 +1704,16 @@ add_outbound_setting() { json_close_object # tlsSettings fi fi + if [ "x$protocol" = "xvless-reality" ]; then + json_add_string "security" "reality" + json_add_object "realitySettings" + json_add_string "fingerprint" "chrome" + json_add_string "serverName" "" + json_add_string "publicKey" "$s_vless_reality_public_key" + json_add_string "spiderX" "" + json_add_string "shortId" "" + json_close_object + fi case "${ss_network:-x}" in "tcp") @@ -2206,6 +2260,9 @@ rules_up() { if [ "$(uci -q get xray.omrout.protocol)" = "vless" ]; then OUTBOUND_SERVERS_V4="$(uci -q get xray.omrout.s_vless_address)" OUTBOUND_SERVERS_V6="$(uci -q get xray.omrout.s_vless_address)" + elif [ "$(uci -q get xray.omrout.protocol)" = "vless-reality" ]; then + OUTBOUND_SERVERS_V4="$(uci -q get xray.omrout.s_vless_reality_address)" + OUTBOUND_SERVERS_V6="$(uci -q get xray.omrout.s_vless_reality_address)" elif [ "$(uci -q get xray.omrout.protocol)" = "vmess" ]; then OUTBOUND_SERVERS_V4="$(uci -q get xray.omrout.s_vmess_address)" OUTBOUND_SERVERS_V6="$(uci -q get xray.omrout.s_vmess_address)" @@ -2215,6 +2272,9 @@ rules_up() { elif [ "$(uci -q get xray.omrout.protocol)" = "socks" ]; then OUTBOUND_SERVERS_V4="$(uci -q get xray.omrout.s_socks_address)" OUTBOUND_SERVERS_V6="$(uci -q get xray.omrout.s_socks_address)" + elif [ "$(uci -q get xray.omrout.protocol)" = "shadowsocks" ]; then + OUTBOUND_SERVERS_V4="$(uci -q get xray.omrout.s_shadowsocks_address)" + OUTBOUND_SERVERS_V6="$(uci -q get xray.omrout.s_shadowsocks_address)" fi TRANSPARENT_PROXY_PORT="$(uci -q get xray.omr.port)" [ -n "$OUTBOUND_SERVERS_V4" ] || [ -n "$OUTBOUND_SERVERS_V6" ] && { diff --git a/xray-core/files/etc/uci-defaults/3010-omr-xray b/xray-core/files/etc/uci-defaults/3010-omr-xray index 69cce605e..361f1dbfd 100644 --- a/xray-core/files/etc/uci-defaults/3010-omr-xray +++ b/xray-core/files/etc/uci-defaults/3010-omr-xray @@ -36,24 +36,24 @@ if [ -z "$(uci -q get xray.main)" ]; then set xray.omrout.tag='omrout_tunnel' set xray.omrout.protocol='vless' set xray.omrout.s_vmess_address='' - set xray.omrout.s_vmess_port='65230' + set xray.omrout.s_vmess_port='65250' set xray.omrout.s_vmess_user_id='' set xray.omrout.s_vmess_user_security='none' set xray.omrout.s_vmess_user_alter_id='0' set xray.omrout.s_vless_address='' - set xray.omrout.s_vless_port='65228' + set xray.omrout.s_vless_port='65248' set xray.omrout.s_vless_user_id='' set xray.omrout.s_vless_user_security='none' set xray.omrout.s_vless_user_encryption='none' set xray.omrout.s_vless_user_alter_id='0' set xray.omrout.s_trojan_address='' - set xray.omrout.s_trojan_port='65229' + set xray.omrout.s_trojan_port='65249' set xray.omrout.s_trojan_user_id='' set xray.omrout.s_trojan_user_security='none' set xray.omrout.s_trojan_user_encryption='none' set xray.omrout.s_trojan_user_alter_id='0' set xray.omrout.s_socks_address='' - set xray.omrout.s_socks_port='65231' + set xray.omrout.s_socks_port='65251' set xray.omrout.s_socks_user_id='' set xray.omrout.s_socks_user_security='none' set xray.omrout.s_socks_user_encryption='none' @@ -170,9 +170,9 @@ if [ "$(uci -q get xray.policy_level_0.conn_idle)" = "2400" ]; then EOF fi -if [ "$(uci -q get xray.omrout.s_vmess_port)" = "65228" ]; then +if [ "$(uci -q get xray.omrout.s_vmess_port)" = "65230" ]; then uci -q batch <<-EOF >/dev/null - set xray.omrout.s_vmess_port='65230' + set xray.omrout.s_vmess_port='65250' commit xray EOF fi @@ -180,7 +180,7 @@ fi if [ "$(uci -q get xray.omrout.s_trojan_port)" = "" ]; then uci -q batch <<-EOF >/dev/null set xray.omrout.s_trojan_address='' - set xray.omrout.s_trojan_port='65229' + set xray.omrout.s_trojan_port='65249' set xray.omrout.s_trojan_user_id='' set xray.omrout.s_trojan_user_security='none' set xray.omrout.s_trojan_user_encryption='none' @@ -191,7 +191,7 @@ fi if [ "$(uci -q get xray.omrout.s_socks_port)" = "" ]; then uci -q batch <<-EOF >/dev/null set xray.omrout.s_socks_address='' - set xray.omrout.s_socks_port='65231' + set xray.omrout.s_socks_port='65251' set xray.omrout.s_socks_user_id='' set xray.omrout.s_socks_user_security='none' set xray.omrout.s_socks_user_encryption='none' @@ -199,6 +199,25 @@ if [ "$(uci -q get xray.omrout.s_socks_port)" = "" ]; then commit xray EOF fi +if [ "$(uci -q get xray.omrout.s_shadowsocks_port)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set xray.omrout.s_shadowsocks_address='' + set xray.omrout.s_shadowsocks_port='65252' + commit xray + EOF +fi +if [ "$(uci -q get xray.omrout.s_vless_reality_port)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set xray.omrout.s_vless_reality_address='' + set xray.omrout.s_vless_reality_port='443' + set xray.omrout.s_vless_reality_flow='xtls-rprx-vision' + set xray.omrout.s_vless_reality_user_id='' + set xray.omrout.s_vless_reality_user_security='none' + set xray.omrout.s_vless_reality_user_encryption='none' + set xray.omrout.s_vless_reality_user_alter_id='0' + commit xray + EOF +fi if [ "$(uci -q get xray.omrout.ss_sockopt_mptcp)" = "" ]; then uci -q batch <<-EOF >/dev/null From 05a4db152329a5c81920aee61eab0846414ba655 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 18 Oct 2023 11:00:33 +0200 Subject: [PATCH 1135/2059] Remove from luci packages some files that can work without luci interface --- luci-app-omr-bypass/Makefile | 10 +- luci-app-openmptcprouter/Makefile | 2 +- luci-app-sqm-autorate/Makefile | 4 +- omr-bypass/Makefile | 34 + .../files}/etc/config/omr-bypass | 0 .../files}/etc/firewall.omr-bypass | 0 .../files}/etc/init.d/omr-bypass | 0 .../files}/etc/uci-defaults/41_omr-bypass | 0 .../usr/share/omr-bypass/omr-bypass-proto.lst | 0 .../files}/usr/share/omr-bypass/omr-bypass.db | Bin openmptcprouter-api/Makefile | 34 + .../files}/bin/omr-3g | 0 .../files}/bin/omr-huawei | 0 .../files}/bin/omr-ip-intf | 0 .../files}/bin/omr-ip6-intf | 0 .../files}/bin/omr-modemmanager | 0 .../files}/bin/omr-mptcp-intf | 0 .../files}/bin/omr-qmi | 0 .../files}/bin/omr-routing-loop | 0 .../files}/bin/omr-tracebox-mptcp | 0 .../files}/usr/libexec/rpcd/openmptcprouter | 0 .../luci/menu.d/luci-app-openmptcprouter.json | 13 + .../rpcd/acl.d/luci-app-openmptcprouter.json | 14 + sqm-autorate/Makefile | 34 + .../files}/etc/init.d/sqm-autorate | 0 .../files/etc/uci-defaults/50-sqm-autorate | 0 .../files}/root/cake-autorate | 0 .../usr/share/sqm-autorate/cake-autorate.sh | 0 .../share/sqm-autorate/cake-autorate.sh.anc | 2270 +++++++++++++++++ .../files}/usr/share/sqm-autorate/config.sh | 0 .../usr/share/sqm-autorate/config_template.sh | 0 .../files}/usr/share/sqm-autorate/defaults.sh | 0 .../usr/share/sqm-autorate/defaults.sh.anc | 209 ++ .../files}/usr/share/sqm-autorate/launcher.sh | 0 .../files}/usr/share/sqm-autorate/lib.sh | 0 35 files changed, 2616 insertions(+), 8 deletions(-) create mode 100644 omr-bypass/Makefile rename {luci-app-omr-bypass/root => omr-bypass/files}/etc/config/omr-bypass (100%) rename {luci-app-omr-bypass/root => omr-bypass/files}/etc/firewall.omr-bypass (100%) rename {luci-app-omr-bypass/root => omr-bypass/files}/etc/init.d/omr-bypass (100%) rename {luci-app-omr-bypass/root => omr-bypass/files}/etc/uci-defaults/41_omr-bypass (100%) rename {luci-app-omr-bypass/root => omr-bypass/files}/usr/share/omr-bypass/omr-bypass-proto.lst (100%) rename {luci-app-omr-bypass/root => omr-bypass/files}/usr/share/omr-bypass/omr-bypass.db (100%) create mode 100644 openmptcprouter-api/Makefile rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-3g (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-huawei (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-ip-intf (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-ip6-intf (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-modemmanager (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-mptcp-intf (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-qmi (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-routing-loop (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/bin/omr-tracebox-mptcp (100%) rename {luci-app-openmptcprouter/root => openmptcprouter-api/files}/usr/libexec/rpcd/openmptcprouter (100%) create mode 100644 openmptcprouter-api/files/usr/share/luci/menu.d/luci-app-openmptcprouter.json create mode 100644 openmptcprouter-api/files/usr/share/rpcd/acl.d/luci-app-openmptcprouter.json create mode 100644 sqm-autorate/Makefile rename {luci-app-sqm-autorate/root => sqm-autorate/files}/etc/init.d/sqm-autorate (100%) rename luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm => sqm-autorate/files/etc/uci-defaults/50-sqm-autorate (100%) rename {luci-app-sqm-autorate/root => sqm-autorate/files}/root/cake-autorate (100%) rename {luci-app-sqm-autorate/root => sqm-autorate/files}/usr/share/sqm-autorate/cake-autorate.sh (100%) create mode 100755 sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc rename {luci-app-sqm-autorate/root => sqm-autorate/files}/usr/share/sqm-autorate/config.sh (100%) rename {luci-app-sqm-autorate/root => sqm-autorate/files}/usr/share/sqm-autorate/config_template.sh (100%) rename {luci-app-sqm-autorate/root => sqm-autorate/files}/usr/share/sqm-autorate/defaults.sh (100%) create mode 100755 sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc rename {luci-app-sqm-autorate/root => sqm-autorate/files}/usr/share/sqm-autorate/launcher.sh (100%) rename {luci-app-sqm-autorate/root => sqm-autorate/files}/usr/share/sqm-autorate/lib.sh (100%) diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index 7b83f4c8c..9dcd62369 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -7,11 +7,11 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables -LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +iptables-mod-extra +iptables +sqlite3-cli -ifneq ($(CONFIG_TARGET_ramips),y) - #LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi - LUCI_DEPENDS+=+iptables-mod-ndpi +kmod-ipt-ndpi -endif +LUCI_DEPENDS:=+omr-bypass +#ifneq ($(CONFIG_TARGET_ramips),y) +# #LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +# LUCI_DEPENDS+=+iptables-mod-ndpi +kmod-ipt-ndpi +#endif PKG_LICENSE:=GPLv3 diff --git a/luci-app-openmptcprouter/Makefile b/luci-app-openmptcprouter/Makefile index 9e1c5938d..38a5aab6a 100644 --- a/luci-app-openmptcprouter/Makefile +++ b/luci-app-openmptcprouter/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Support for OpenMPTCProuter -LUCI_DEPENDS:=+luci-lib-json +curl +bind-dig +tracebox +LUCI_DEPENDS:=+luci-lib-json +openmptcprouter-api PKG_LICENSE:=GPLv3 #include ../luci/luci.mk diff --git a/luci-app-sqm-autorate/Makefile b/luci-app-sqm-autorate/Makefile index 51c3b4497..ef3f81c26 100644 --- a/luci-app-sqm-autorate/Makefile +++ b/luci-app-sqm-autorate/Makefile @@ -6,9 +6,9 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Support for SQM Scripts with autorate LUCI_DESCRIPTION:=Luci interface for the SQM scripts queue management package with SQM autorate -PKG_MAINTAINER:=Toke Høiland-Jørgensen +PKG_MAINTAINER:=Yannick Chabanoois -LUCI_DEPENDS:=+sqm-scripts +bash +tsping +LUCI_DEPENDS:=+sqm-scripts +sqm-autorate LUCI_PKGARCH:=all include $(TOPDIR)/feeds/luci/luci.mk diff --git a/omr-bypass/Makefile b/omr-bypass/Makefile new file mode 100644 index 000000000..b0f813a45 --- /dev/null +++ b/omr-bypass/Makefile @@ -0,0 +1,34 @@ +# +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=omr-bypass +PKG_VERSION:=0.1 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) +SECTION:=net +CATEGORY:=Network +DEPENDS:=+curl +dnsmasq-full +sqlite3-cli +iptables +iptables-mod-extra +TITLE:=OMR-ByPass +endef + +define Package/$(PKG_NAME)/description +OMR-ByPass +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) \ No newline at end of file diff --git a/luci-app-omr-bypass/root/etc/config/omr-bypass b/omr-bypass/files/etc/config/omr-bypass similarity index 100% rename from luci-app-omr-bypass/root/etc/config/omr-bypass rename to omr-bypass/files/etc/config/omr-bypass diff --git a/luci-app-omr-bypass/root/etc/firewall.omr-bypass b/omr-bypass/files/etc/firewall.omr-bypass similarity index 100% rename from luci-app-omr-bypass/root/etc/firewall.omr-bypass rename to omr-bypass/files/etc/firewall.omr-bypass diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/omr-bypass/files/etc/init.d/omr-bypass similarity index 100% rename from luci-app-omr-bypass/root/etc/init.d/omr-bypass rename to omr-bypass/files/etc/init.d/omr-bypass diff --git a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass b/omr-bypass/files/etc/uci-defaults/41_omr-bypass similarity index 100% rename from luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass rename to omr-bypass/files/etc/uci-defaults/41_omr-bypass diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst b/omr-bypass/files/usr/share/omr-bypass/omr-bypass-proto.lst similarity index 100% rename from luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst rename to omr-bypass/files/usr/share/omr-bypass/omr-bypass-proto.lst diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db b/omr-bypass/files/usr/share/omr-bypass/omr-bypass.db similarity index 100% rename from luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db rename to omr-bypass/files/usr/share/omr-bypass/omr-bypass.db diff --git a/openmptcprouter-api/Makefile b/openmptcprouter-api/Makefile new file mode 100644 index 000000000..f06d2279f --- /dev/null +++ b/openmptcprouter-api/Makefile @@ -0,0 +1,34 @@ +# +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=openmptcprouter-api +PKG_VERSION:=0.1 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) +SECTION:=OMR +CATEGORY:=OpenMPTCProuter +DEPENDS:=+tracebox +bind-dig +curl +TITLE:=OpenMPTCProuter API +endef + +define Package/$(PKG_NAME)/description +OpenMPTCProuter API package +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) \ No newline at end of file diff --git a/luci-app-openmptcprouter/root/bin/omr-3g b/openmptcprouter-api/files/bin/omr-3g similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-3g rename to openmptcprouter-api/files/bin/omr-3g diff --git a/luci-app-openmptcprouter/root/bin/omr-huawei b/openmptcprouter-api/files/bin/omr-huawei similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-huawei rename to openmptcprouter-api/files/bin/omr-huawei diff --git a/luci-app-openmptcprouter/root/bin/omr-ip-intf b/openmptcprouter-api/files/bin/omr-ip-intf similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-ip-intf rename to openmptcprouter-api/files/bin/omr-ip-intf diff --git a/luci-app-openmptcprouter/root/bin/omr-ip6-intf b/openmptcprouter-api/files/bin/omr-ip6-intf similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-ip6-intf rename to openmptcprouter-api/files/bin/omr-ip6-intf diff --git a/luci-app-openmptcprouter/root/bin/omr-modemmanager b/openmptcprouter-api/files/bin/omr-modemmanager similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-modemmanager rename to openmptcprouter-api/files/bin/omr-modemmanager diff --git a/luci-app-openmptcprouter/root/bin/omr-mptcp-intf b/openmptcprouter-api/files/bin/omr-mptcp-intf similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-mptcp-intf rename to openmptcprouter-api/files/bin/omr-mptcp-intf diff --git a/luci-app-openmptcprouter/root/bin/omr-qmi b/openmptcprouter-api/files/bin/omr-qmi similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-qmi rename to openmptcprouter-api/files/bin/omr-qmi diff --git a/luci-app-openmptcprouter/root/bin/omr-routing-loop b/openmptcprouter-api/files/bin/omr-routing-loop similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-routing-loop rename to openmptcprouter-api/files/bin/omr-routing-loop diff --git a/luci-app-openmptcprouter/root/bin/omr-tracebox-mptcp b/openmptcprouter-api/files/bin/omr-tracebox-mptcp similarity index 100% rename from luci-app-openmptcprouter/root/bin/omr-tracebox-mptcp rename to openmptcprouter-api/files/bin/omr-tracebox-mptcp diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter similarity index 100% rename from luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter rename to openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter diff --git a/openmptcprouter-api/files/usr/share/luci/menu.d/luci-app-openmptcprouter.json b/openmptcprouter-api/files/usr/share/luci/menu.d/luci-app-openmptcprouter.json new file mode 100644 index 000000000..eea51e8f9 --- /dev/null +++ b/openmptcprouter-api/files/usr/share/luci/menu.d/luci-app-openmptcprouter.json @@ -0,0 +1,13 @@ +{ + "admin/system/openmptcprouter": { + "title": "OpenMPTCProuter", + "order": 1, + "action": { + "type": "template", + "path": "openmptcprouter/wizard" + }, + "depends": { + "acl": [ "luci-app-openmptcprouter" ] + } + } +} diff --git a/openmptcprouter-api/files/usr/share/rpcd/acl.d/luci-app-openmptcprouter.json b/openmptcprouter-api/files/usr/share/rpcd/acl.d/luci-app-openmptcprouter.json new file mode 100644 index 000000000..a1d3b99a3 --- /dev/null +++ b/openmptcprouter-api/files/usr/share/rpcd/acl.d/luci-app-openmptcprouter.json @@ -0,0 +1,14 @@ +{ + "luci-app-openmptcprouter": { + "description": "Grant UCI access for luci-app-openmptcprouter", + "read": { + "uci": [ "*" ], + "ubus": { + "openmptcprouter": [ "*" ] + } + }, + "write": { + "uci": [ "*" ] + } + } +} \ No newline at end of file diff --git a/sqm-autorate/Makefile b/sqm-autorate/Makefile new file mode 100644 index 000000000..ac0ae79fb --- /dev/null +++ b/sqm-autorate/Makefile @@ -0,0 +1,34 @@ +# +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=sqm-autorate +PKG_VERSION:=0.1 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) +SECTION:=net +CATEGORY:=Network +DEPENDS:=+bash +tsping +TITLE:=SQM Autorate +endef + +define Package/$(PKG_NAME)/description +SQM Autorate +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) \ No newline at end of file diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/sqm-autorate/files/etc/init.d/sqm-autorate similarity index 100% rename from luci-app-sqm-autorate/root/etc/init.d/sqm-autorate rename to sqm-autorate/files/etc/init.d/sqm-autorate diff --git a/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm b/sqm-autorate/files/etc/uci-defaults/50-sqm-autorate similarity index 100% rename from luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm rename to sqm-autorate/files/etc/uci-defaults/50-sqm-autorate diff --git a/luci-app-sqm-autorate/root/root/cake-autorate b/sqm-autorate/files/root/cake-autorate similarity index 100% rename from luci-app-sqm-autorate/root/root/cake-autorate rename to sqm-autorate/files/root/cake-autorate diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh similarity index 100% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh rename to sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh diff --git a/sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc b/sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc new file mode 100755 index 000000000..68edafd1c --- /dev/null +++ b/sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc @@ -0,0 +1,2270 @@ +#!/bin/bash + +# cake-autorate automatically adjusts CAKE bandwidth(s) +# in dependence on: a) receive and transmit transfer rates; and b) latency +# (or can just be used to monitor and log transfer rates and latency) + +# requires: bash; and one of the supported ping binaries + +# each cake-autorate instance must be configured using a corresponding config file + +# Project homepage: https://github.com/lynxthecat/cake-autorate +# Licence details: https://github.com/lynxthecat/cake-autorate/blob/master/LICENCE.md + +# Author and maintainer: lynxthecat +# Contributors: rany2; moeller0; richb-hanover + +cake_autorate_version="2.0.0" + +## cake-autorate uses multiple asynchronous processes including: +## main - main process +## monitor_achieved_rates - monitor network transfer rates +## maintain_pingers - manage pingers and active reflectors +## parse_${pinger_binary} - control and parse ping responses +## parse_preprocessor - prepend field for parse_${pinger_binary} +## maintain_log_file - maintain and rotate log file +## +## IPC is facilitated via FIFOs in the form of anonymous pipes +## accessible via fds in the form: ${process_name_fd} +## thereby to enable transferring instructions and data between processes + +# Initialize file descriptors +## -1 signifies that the log file fd will not be used and +## that the log file will be written to directly +log_fd=-1 +exec {main_fd}<> <(:) +exec {monitor_achieved_rates_fd}<> <(:) +exec {maintain_pingers_fd}<> <(:) +# pinger_fds are set below in dependence upon ping binary and number of pingers + +# process pids are stored below in the form +# proc_pids['process_identifier']=${!} +declare -A proc_pids + +# Bash correctness options +## Disable globbing (expansion of *). +set -f +## Forbid using unset variables. +set -u +## The exit status of a pipeline is the status of the last +## command to exit with a non-zero status, or zero if no +## command exited with a non-zero status. +set -o pipefail + +## Errors are intercepted via intercept_stderr below +## and sent to the log file and system log + +# Possible performance improvement +export LC_ALL=C + +# Set PREFIX +PREFIX=/root/cake-autorate + +# shellcheck source=lib.sh +. "${PREFIX}/lib.sh" +# shellcheck source=defaults.sh +. "${PREFIX}/defaults.sh" +# get valid config overrides +mapfile -t valid_config_entries < <(grep -E '^[^(#| )].*=' "${PREFIX}/defaults.sh" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') + +trap cleanup_and_killall INT TERM EXIT + +cleanup_and_killall() +{ + # Do not fail on error for this critical cleanup code + set +e + + trap true INT TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + log_msg "INFO" "Stopping cake-autorate with PID: ${BASHPID} and config: ${config_path}" + + log_msg "INFO" "Killing all background processes and cleaning up temporary files." + + printf "TERMINATE\n" >&"${maintain_pingers_fd}" + printf "TERMINATE\n" >&"${monitor_achieved_rates_fd}" + + [[ -d "${run_path}" ]] && rm -r "${run_path}" + rmdir /var/run/cake-autorate 2>/dev/null + + # give some time for processes to gracefully exit + sleep_s 1 + + # terminate any processes that remain, save for main and intercept_stderr + unset "proc_pids[main]" + intercept_stderr_pid="${proc_pids[intercept_stderr]:-}" + if [[ -n "${intercept_stderr_pid}" ]] + then + unset "proc_pids[intercept_stderr]" + fi + terminate "${proc_pids[@]}" + + # restore original stderr, and terminate intercept_stderr + if [[ -n "${intercept_stderr_pid}" ]] + then + exec 2>&"${original_stderr_fd}" + terminate "${intercept_stderr_pid}" + fi + + log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}" + + trap - INT TERM EXIT + exit +} + +log_msg() +{ + # send logging message to terminal, log file fifo, log file and/or system logger + + local type="${1}" + local msg="${2}" + local instance_id="${instance_id:-"unknown"}" + local log_timestamp=${EPOCHREALTIME} + + case ${type} in + + DEBUG) + ((debug == 0)) && return # skip over DEBUG messages where debug disabled + ((log_DEBUG_messages_to_syslog)) && ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" + ;; + + ERROR) + ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" + ;; + + SYSLOG) + ((use_logger)) && logger -t "cake-autorate.${instance_id}" "INFO: ${log_timestamp} ${msg}" + ;; + + *) + ;; + esac + + # Output to the log file fifo if available (for rotation handling) + # else output directly to the log file + if (( log_fd >= 0 )) + then + ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >&"${log_fd}" + else + ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >> "${log_file_path}" + fi + + ((terminal)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" +} + +print_headers() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + header="DATA_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; DL_LOAD_PERCENT; UL_LOAD_PERCENT; RTT_TIMESTAMP; REFLECTOR; SEQUENCE; DL_OWD_BASELINE; DL_OWD_US; DL_OWD_DELTA_EWMA_US; DL_OWD_DELTA_US; DL_ADJ_DELAY_THR; UL_OWD_BASELINE; UL_OWD_US; UL_OWD_DELTA_EWMA_US; UL_OWD_DELTA_US; UL_ADJ_DELAY_THR; SUM_DL_DELAYS; SUM_UL_DELAYS; DL_LOAD_CONDITION; UL_LOAD_CONDITION; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" + + header="LOAD_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" + + header="REFLECTOR_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; REFLECTOR; MIN_SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_DELTA_US; SUM_OWD_BASELINES_DELTA_THR_US; MIN_DL_DELTA_EWMA_US; DL_DELTA_EWMA_US; DL_DELTA_EWMA_DELTA_US; DL_DELTA_EWMA_DELTA_THR; MIN_UL_DELTA_EWMA_US; UL_DELTA_EWMA_US; UL_DELTA_EWMA_DELTA_US; UL_DELTA_EWMA_DELTA_THR" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" +} + +# MAINTAIN_LOG_FILE + HELPER FUNCTIONS + +rotate_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + if [[ -f ${log_file_path} ]] + then + cat "${log_file_path}" > "${log_file_path}.old" + true > "${log_file_path}" + fi + + ((output_processing_stats)) && print_headers + t_log_file_start_us=${EPOCHREALTIME/./} + get_log_file_size_bytes +} + +reset_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + rm -f "${log_file_path}.old" + true > "${log_file_path}" + + ((output_processing_stats)) && print_headers + t_log_file_start_us=${EPOCHREALTIME/./} + get_log_file_size_bytes +} + +generate_log_file_scripts() +{ + cat > "${run_path}/log_file_export" <<- EOT + #!/bin/bash + + timeout_s=\${1:-20} + + if kill -USR1 "${proc_pids['maintain_log_file']}" + then + printf "Successfully signalled maintain_log_file process to request log file export.\n" + else + printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 + exit 1 + fi + rm -f "${run_path}/last_log_file_export" + + read_try=0 + + while [[ ! -f "${run_path}/last_log_file_export" ]] + do + sleep 1 + if (( ++read_try >= \${timeout_s} )) + then + printf "ERROR: Timeout (\${timeout_s}s) reached before new log file export identified.\n" >&2 + exit 1 + fi + done + + read -r log_file_export_path < "${run_path}/last_log_file_export" + + printf "Log file export complete.\n" + + printf "Log file available at location: " + printf "\${log_file_export_path}\n" + EOT + + cat > "${run_path}/log_file_reset" <<- EOT + #!/bin/bash + + if kill -USR2 "${proc_pids['maintain_log_file']}" + then + printf "Successfully signalled maintain_log_file process to request log file reset.\n" + else + printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 + exit 1 + fi + EOT + + chmod +x "${run_path}/log_file_export" "${run_path}/log_file_reset" +} + +export_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + printf -v log_file_export_datetime '%(%Y_%m_%d_%H_%M_%S)T' + log_file_export_path="${log_file_path/.log/_${log_file_export_datetime}.log}" + log_msg "DEBUG" "Exporting log file with path: ${log_file_path/.log/_${log_file_export_datetime}.log}" + + # Now export with or without compression to the appropriate export path + if ((log_file_export_compress)) + then + log_file_export_path="${log_file_export_path}.gz" + if [[ -f "${log_file_path}.old" ]] + then + gzip -c "${log_file_path}.old" > "${log_file_export_path}" + gzip -c "${log_file_path}" >> "${log_file_export_path}" + else + gzip -c "${log_file_path}" > "${log_file_export_path}" + fi + else + if [[ -f "${log_file_path}.old" ]] + then + cp "${log_file_path}.old" "${log_file_export_path}" + cat "${log_file_path}" >> "${log_file_export_path}" + else + cp "${log_file_path}" "${log_file_export_path}" + fi + fi + + printf '%s' "${log_file_export_path}" > "${run_path}/last_log_file_export" +} + +flush_log_fd() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + while read -r -t 0 -u "${log_fd}" + do + read -r -u "${log_fd}" log_line + printf '%s\n' "${log_line}" >> "${log_file_path}" + done +} + +get_log_file_size_bytes() +{ + log_file_size_bytes=$(wc -c "${log_file_path}" 2>/dev/null | awk '{print $1}') + log_file_size_bytes=${log_file_size_bytes:-0} +} + +kill_maintain_log_file() +{ + trap - TERM EXIT + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + flush_log_fd + exit +} + +maintain_log_file() +{ + trap '' INT + trap 'kill_maintain_log_file' TERM EXIT + trap 'export_log_file' USR1 + trap 'reset_log_file_signalled=1' USR2 + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + reset_log_file_signalled=0 + t_log_file_start_us=${EPOCHREALTIME/./} + + get_log_file_size_bytes + + while read -r -u "${log_fd}" log_line + do + + printf '%s\n' "${log_line}" >> "${log_file_path}" + + # Verify log file size < configured maximum + # The following two lines with costly call to 'du': + # read log_file_size_bytes< <(du -b ${log_file_path}/cake-autorate.log) + # log_file_size_bytes=${log_file_size_bytes//[!0-9]/} + # can be more efficiently handled with this line: + ((log_file_size_bytes=log_file_size_bytes+${#log_line}+1)) + + # Verify log file time < configured maximum + if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) + then + + log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so flushing and rotating log file." + flush_log_fd + rotate_log_file + elif (( log_file_size_bytes > log_file_max_size_bytes )) + then + log_file_size_KB=$((log_file_size_bytes/1024)) + log_msg "DEBUG" "log file size: ${log_file_size_KB} KB has exceeded configured maximum: ${log_file_max_size_KB} KB so flushing and rotating log file." + flush_log_fd + rotate_log_file + elif (( reset_log_file_signalled )) + then + log_msg "DEBUG" "received log file reset signal so flushing and resetting log file." + flush_log_fd + reset_log_file + reset_log_file_signalled=0 + fi + + done +} + +update_shaper_rate() +{ + local direction="${1}" # 'dl' or 'ul' + + case "${load_condition["${direction}"]}" in + + # upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period + ul*sss) + shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" + ;; + # download Starlink satelite switching compensation, so drop down to base rate for download through switching period + dl*sss) + shaper_rate_kbps["${direction}"]=$(( shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"] ? base_shaper_rate_kbps["${direction}"] : shaper_rate_kbps["${direction}"] )) + ;; + # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period + *bb*) + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then + adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps["${direction}"]*achieved_rate_adjust_down_bufferbloat)/1000 )) + adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_bufferbloat)/1000 )) + shaper_rate_kbps["${direction}"]=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps["${direction}"] && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) + t_last_bufferbloat_us["${direction}"]="${EPOCHREALTIME/./}" + fi + ;; + # high load, so increase rate providing not inside bufferbloat refractory period + *high*) + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then + shaper_rate_kbps["${direction}"]=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_high)/1000 )) + fi + ;; + # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate + *low*|*idle*) + if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )) + then + + if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])) + then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_load_low)/1000 )) + shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) + elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])) + then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_low)/1000 )) + shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) + fi + + t_last_decay_us["${direction}"]="${EPOCHREALTIME/./}" + fi + ;; + *) + log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in update_shaper_rate" + kill $$ 2>/dev/null + ;; + esac + # make sure to only return rates between cur_min_rate and cur_max_rate + ((shaper_rate_kbps["${direction}"] < min_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" + ((shaper_rate_kbps["${direction}"] > max_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${max_shaper_rate_kbps[${direction}]}" +} + +monitor_achieved_rates() +{ + trap '' INT + + # track rx and tx bytes transfered and divide by time since last update + # to determine achieved dl and ul transfer rates + + local rx_bytes_path="${1}" + local tx_bytes_path="${2}" + local monitor_achieved_rates_interval_us="${3}" # (microseconds) + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + compensated_monitor_achieved_rates_interval_us="${monitor_achieved_rates_interval_us}" + + [[ -f "${rx_bytes_path}" ]] && { read -r prev_rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || prev_rx_bytes=0 + [[ -f "${tx_bytes_path}" ]] && { read -r prev_tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || prev_tx_bytes=0 + + sleep_duration_s=0 + t_start_us=0 + + declare -A achieved_rate_kbps + declare -A load_percent + + while true + do + t_start_us="${EPOCHREALTIME/./}" + + while read -r -t 0 -u "${monitor_achieved_rates_fd}" + do + unset command + read -r -u "${monitor_achieved_rates_fd}" -a command + case "${command[0]:-}" in + + SET_VAR) + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; + TERMINATE) + log_msg "DEBUG" "Terminating monitor_achieved_rates." + exit + ;; + *) + : + ;; + esac + done + + # If rx/tx bytes file exists, read it in, otherwise set to prev_bytes + # This addresses interfaces going down and back up + [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes="${prev_rx_bytes}" + [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes="${prev_tx_bytes}" + + achieved_rate_kbps[dl]=$(( (8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us )) + achieved_rate_kbps[ul]=$(( (8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us )) + + ((achieved_rate_kbps[dl]<0)) && achieved_rate_kbps[dl]=0 + ((achieved_rate_kbps[ul]<0)) && achieved_rate_kbps[ul]=0 + + printf "SET_ARRAY_ELEMENT achieved_rate_kbps dl %s\n" "${achieved_rate_kbps[dl]}" >&"${main_fd}" + printf "SET_ARRAY_ELEMENT achieved_rate_kbps ul %s\n" "${achieved_rate_kbps[ul]}" >&"${main_fd}" + + load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) + load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) + + for pinger_fd in "${pinger_fds[@]:?}" + do + printf "SET_ARRAY_ELEMENT load_percent dl %s\n" "${load_percent[dl]}" >&"${pinger_fd}" + printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}" + done + + if ((output_load_stats)) + then + + printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" + log_msg "LOAD" "${load_stats}" + fi + + prev_rx_bytes="${rx_bytes}" + prev_tx_bytes="${tx_bytes}" + + compensated_monitor_achieved_rates_interval_us=$(( monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) + + sleep_remaining_tick_time "${t_start_us}" "${compensated_monitor_achieved_rates_interval_us}" + + done +} + + +classify_load() +{ + # classify the load according to high/low/idle and add _delayed if delayed + # thus ending up with high_delayed, low_delayed, etc. + local direction="${1}" + + if (( load_percent["${direction}"] > high_load_thr_percent )) + then + load_condition["${direction}"]="high" + elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )) + then + load_condition["${direction}"]="low" + else + load_condition["${direction}"]="idle" + fi + + ((bufferbloat_detected["${direction}"])) && load_condition["${direction}"]="${load_condition[${direction}]}_bb" + + if ((sss_compensation)) + then + # shellcheck disable=SC2154 + for sss_time_us in "${sss_times_us[@]}" + do + ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) + if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )) + then + load_condition["${direction}"]="${load_condition[${direction}]}_sss" + break + fi + done + fi + + load_condition["${direction}"]="${direction}_${load_condition[${direction}]}" +} + +# MAINTAIN PINGERS + ASSOCIATED HELPER FUNCTIONS + +parse_preprocessor() +{ + # prepend REFLECTOR_RESPONSE and append timestamp as a checksum + while read -r timestamp remainder + do + printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" + done +} + +parse_tsping() +{ + trap '' INT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + local parse_id="${1}" + local reflectors=("${@:2}") + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + for (( reflector=0; reflector >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + # accommodate present tsping interval/sleep handling to prevent ping flood with only one pinger + tsping_sleep_time=$(( no_pingers == 1 ? ping_response_interval_ms : 0 )) + ${ping_prefix_string} tsping ${ping_extra_args} --print-timestamps --machine-readable=' ' --sleep-time "${tsping_sleep_time}" --target-spacing "${ping_response_interval_ms}" "${reflectors[@]:0:${no_pingers}}" 2>/dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; + + KILL_PINGER) + + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; + + SET_REFLECTORS) + + read -r -a reflectors <<< "${command[@]:1}" + log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" + for (( reflector=0; reflector 50 mins, immediately reset the baselines to the new dl_owd_us and ul_owd_us. + # + # Happilly, the sum of dl_owd_baseline_us and ul_owd_baseline_us will roughly equal rtt_baseline_us. + # And since Transmit is approximately equal to Received, RTT is approximately equal to Finished - Originate. + # And thus the sum of dl_owd_baseline_us and ul_owd_baseline_us should not be affected by the rollover/compensation. + # Hence working with this sum, rather than the individual components, is useful for the reflector health check in maintain_pingers(). + + if (( (${dl_owd_delta_us#-} + ${ul_owd_delta_us#-}) < 3000000000 )) + then + + dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + ul_alpha=$(( ul_owd_us >= ul_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ewma_iteration "${ul_owd_us}" "${ul_alpha}" "ul_owd_baselines_us[${reflector}]" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us=$(( ul_owd_us - ul_owd_baselines_us[${reflector}] )) + else + dl_owd_baselines_us[${reflector}]=${dl_owd_us} + ul_owd_baselines_us[${reflector}]=${ul_owd_us} + + dl_owd_delta_us=0 + ul_owd_delta_us=0 + fi + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ewma_iteration "${ul_owd_delta_us}" "${alpha_delta_ewma}" "ul_owd_delta_ewmas_us[${reflector}]" + fi + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + fi + done +} + +parse_fping() +{ + trap '' INT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + local parse_id="${1}" + + local reflectors=("${@:2}") + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + for (( reflector=0; reflector >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + ${ping_prefix_string} fping ${ping_extra_args} --timestamp --loop --period "${reflector_ping_interval_ms}" --interval "${ping_response_interval_ms}" --timeout 10000 "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; + + KILL_PINGER) + + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; + + SET_REFLECTORS) + + read -r -a reflectors <<< "${command[@]:1}" + log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" + for (( reflector=0; reflector= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us="${dl_owd_delta_us}" + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" + fi + + timestamp="${timestamp//[\[\]]}0" + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + fi + done +} +# IPUTILS-PING FUNCTIONS +parse_ping() +{ + trap '' INT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + # ping reflector, maintain baseline and output deltas to a common fifo + + local parse_id="${1}" + local reflector="${2}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + dl_owd_baselines_us["${reflector}"]=100000 + ul_owd_baselines_us["${reflector}"]=100000 + dl_owd_delta_ewmas_us["${reflector}"]=0 + ul_owd_delta_ewmas_us["${reflector}"]=0 + + declare -A load_percent + load_percent[dl]=0 + load_percent[ul]=0 + + while true + do + unset command + read -r -u "${pinger_fds[pinger]}" -a command + if [[ "${command-}" ]] + then + case "${command[0]}" in + + REFLECTOR_RESPONSE) + + read -r timestamp _ _ _ reflector seq_rtt <<< "${command[@]:1}" + checksum="${command[*]: -1}" + ;; + + START_PINGER) + + exec {parse_preprocessor_fd}> >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID %s %s\n" "proc_pids ${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + ${ping_prefix_string} ping ${ping_extra_args} -D -i "${reflector_ping_interval_s}" "${reflector}" 2> /dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; + + KILL_PINGER) + + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; + + SET_REFLECTOR) + + if [[ "${#command[@]}" -eq 2 ]] + then + reflector="${command[1]}" + log_msg "DEBUG" "Read in new reflector: ${reflector}" + dl_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]:-100000}" + ul_owd_baselines_us["${reflector}"]="${ul_owd_baselines_us[${reflector}]:-100000}" + dl_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]:-0}" + ul_owd_delta_ewmas_us["${reflector}"]="${ul_owd_delta_ewmas_us[${reflector}]:-0}" + continue + fi + ;; + + SET_VAR) + + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + continue + ;; + + SET_ARRAY_ELEMENT) + + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + continue + ;; + + TERMINATE) + + log_msg "DEBUG" "Terminating parse_ping." + exit + ;; + + *) + + continue + ;; + + esac + fi + + if [[ "${timestamp:-}" && "${reflector:-}" && "${seq_rtt:-}" && "${checksum:-}" ]] + then + [[ "${checksum}" == "${timestamp}" ]] + # If no match then skip onto the next one + [[ "${seq_rtt}" =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + + reflector=${reflector//:/} + + seq=${BASH_REMATCH[1]} + + rtt_us=${BASH_REMATCH[3]}000 + rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + + dl_owd_us=$((rtt_us/2)) + ul_owd_us="${dl_owd_us}" + + dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us="${dl_owd_delta_us}" + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" + fi + + timestamp="${timestamp//[\[\]]}" + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + fi + done +} + +# END OF IPUTILS-PING FUNCTIONS + +# GENERIC PINGER START AND STOP FUNCTIONS + +start_pinger() +{ + local pinger="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case ${pinger_binary} in + + tsping|fping) + pinger=0 + printf "START_PINGER\n" >&"${pinger_fds[pinger]}" + ;; + ping) + sleep_until_next_pinger_time_slot "${pinger}" + printf "START_PINGER\n" >&"${pinger_fds[pinger]}" + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac +} + +start_pingers() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case ${pinger_binary} in + + tsping|fping) + start_pinger 0 + ;; + ping) + for ((pinger=0; pinger < no_pingers; pinger++)) + do + start_pinger "${pinger}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac +} + +sleep_until_next_pinger_time_slot() +{ + # wait until next pinger time slot and start pinger in its slot + # this allows pingers to be stopped and started (e.g. during sleep or reflector rotation) + # whilst ensuring pings will remain spaced out appropriately to maintain granularity + + local pinger="${1}" + + t_start_us=${EPOCHREALTIME/./} + time_to_next_time_slot_us=$(( (reflector_ping_interval_us-(t_start_us-pingers_t_start_us)%reflector_ping_interval_us) + pinger*ping_response_interval_us )) + sleep_remaining_tick_time "${t_start_us}" "${time_to_next_time_slot_us}" +} + +kill_pinger() +{ + local pinger="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case "${pinger_binary}" in + tsping|fping) + pinger=0 + ;; + + *) + ;; + esac + + printf "KILL_PINGER\n" >&"${pinger_fds[pinger]}" +} + +kill_pingers() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case "${pinger_binary}" in + + tsping|fping) + log_msg "DEBUG" "Killing ${pinger_binary} instance." + kill_pinger 0 + ;; + ping) + for (( pinger=0; pinger < no_pingers; pinger++)) + do + log_msg "DEBUG" "Killing pinger instance: ${pinger}" + kill_pinger "${pinger}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac +} + +replace_pinger_reflector() +{ + # pingers always use reflectors[0]..[no_pingers-1] as the initial set + # and the additional reflectors are spare reflectors should any from initial set go stale + # a bad reflector in the initial set is replaced with ${reflectors[no_pingers]} + # ${reflectors[no_pingers]} is then unset + # and the the bad reflector moved to the back of the queue (last element in ${reflectors[]}) + # and finally the indices for ${reflectors} are updated to reflect the new order + + local pinger="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + if ((no_reflectors > no_pingers)) + then + log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}." + kill_pinger "${pinger}" + bad_reflector=${reflectors[pinger]} + # overwrite the bad reflector with the reflector that is next in the queue (the one after 0..${no_pingers}-1) + reflectors[pinger]=${reflectors[no_pingers]} + # remove the new reflector from the list of additional reflectors beginning from ${reflectors[no_pingers]} + unset "reflectors[no_pingers]" + # bad reflector goes to the back of the queue + reflectors+=("${bad_reflector}") + # reset array indices + mapfile -t reflectors < <(for i in "${reflectors[@]}"; do printf '%s\n' "${i}"; done) + # set up the new pinger with the new reflector and retain pid + case ${pinger_binary} in + + tsping|fping) + printf "SET_REFLECTORS %s\n" "${reflectors[*]:0:${no_pingers}}" >&"${pinger_fds[0]}" + ;; + ping) + printf "SET_REFLECTOR %s\n" "${reflectors[pinger]}" >&"${pinger_fds[pinger]}" + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac + start_pinger "${pinger}" + else + log_msg "DEBUG" "No additional reflectors specified so just retaining: ${reflectors[pinger]}." + fi + + log_msg "DEBUG" "Resetting reflector offences associated with reflector: ${reflectors[pinger]}." + declare -n reflector_offences="reflector_${pinger}_offences" + for ((i=0; i&"${pinger_fds[0]}" + ;; + ping) + for((pinger=0; pinger < no_pingers; pinger++)) + do + printf "TERMINATE\n" >&"${pinger_fds[pinger]}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac + + exit +} + +change_state_maintain_pingers() +{ + local maintain_pingers_next_state="${1:-unset}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case "${maintain_pingers_next_state}" in + + START|STOP|PAUSED|RUNNING) + + if [[ "${maintain_pingers_state}" == "${maintain_pingers_next_state}" ]] + then + log_msg "ERROR" "Received request to change maintain_pingers state to existing state." + return + fi + + log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" + maintain_pingers_state=${maintain_pingers_next_state} + ;; + + *) + + log_msg "ERROR" "Received unrecognized state change request: ${maintain_pingers_next_state}. Exiting now." + kill $$ 2>/dev/null + ;; + esac +} + +maintain_pingers() +{ + # this initiates the pingers and monitors reflector health, rotating reflectors as necessary + + trap '' INT + trap 'kill_maintain_pingers' TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + declare -A last_timestamp_reflectors_us + + err_silence=0 + reflector_offences_idx=0 + pingers_active=0 + + pingers_t_start_us="${EPOCHREALTIME/./}" + t_last_reflector_replacement_us="${EPOCHREALTIME/./}" + t_last_reflector_comparison_us="${EPOCHREALTIME/./}" + + for ((reflector=0; reflector < no_reflectors; reflector++)) + do + last_timestamp_reflectors_us["${reflectors[reflector]}"]="${pingers_t_start_us}" + done + + # For each pinger initialize record of offences + for ((pinger=0; pinger < no_pingers; pinger++)) + do + # shellcheck disable=SC2178 + declare -n reflector_offences="reflector_${pinger}_offences" + for ((i=0; i&"${main_fd}" + ;; + fping) + parse_fping "parse_fping" "${reflectors[@]:0:${no_pingers}}" & + printf "SET_PROC_PID proc_pids parse_fping %s\n" "${!}" >&"${main_fd}" + ;; + ping) + for((pinger=0; pinger < no_pingers; pinger++)) + do + parse_ping "parse_ping_${pinger}" "${reflectors[pinger]}" & + printf "SET_PROC_PID proc_pids %s %s\n" "parse_ping_${pinger}" "${!}" >&"${main_fd}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac + + + # Reflector maintenance loop - verifies reflectors have not gone stale and rotates reflectors as necessary + while true + do + t_start_us="${EPOCHREALTIME/./}" + + while read -r -t 0 -u "${maintain_pingers_fd}" + do + unset command + read -r -u "${maintain_pingers_fd}" -a command + case "${command[0]:-}" in + + CHANGE_STATE) + if [[ "${#command[@]}" -eq 2 ]] + then + change_state_maintain_pingers "${command[1]}" + # break out of reading any new IPC commands to handle next state + # if pingers need to be started or stopped + case "${command[1]}" in + START|STOP) + break + ;; + *) + : + ;; + esac + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; + SET_VAR) + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + TERMINATE) + log_msg "DEBUG" "Terminating monitor_achieved_rates." + exit + ;; + *) + : + ;; + esac + done + + case "${maintain_pingers_state}" in + + START) + if ((pingers_active==0)) + then + start_pingers + pingers_active=1 + fi + change_state_maintain_pingers "RUNNING" + ;; + + STOP) + if ((pingers_active)) + then + kill_pingers + pingers_active=0 + fi + change_state_maintain_pingers "PAUSED" + ;; + + PAUSED) + ;; + + RUNNING) + + if (( t_start_us>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) + then + pinger=$((RANDOM%no_pingers)) + log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." + replace_pinger_reflector "${pinger}" + t_last_reflector_replacement_us=${EPOCHREALTIME/./} + continue + fi + + if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )) + then + + t_last_reflector_comparison_us=${EPOCHREALTIME/./} + + [[ "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" ]] || continue + + min_sum_owd_baselines_us=$(( dl_owd_baselines_us[${reflectors[0]}] + ul_owd_baselines_us[${reflectors[0]}] )) + min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[0]}]}" + min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[0]}]}" + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + [[ "${dl_owd_baselines_us[${reflectors[pinger]}]:-}" && "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" && "${ul_owd_baselines_us[${reflectors[pinger]}]:-}" && "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" ]] || continue 2 + + sum_owd_baselines_us[pinger]=$(( dl_owd_baselines_us[${reflectors[pinger]}] + ul_owd_baselines_us[${reflectors[pinger]}] )) + (( sum_owd_baselines_us[pinger] < min_sum_owd_baselines_us )) && min_sum_owd_baselines_us="${sum_owd_baselines_us[pinger]}" + (( dl_owd_delta_ewmas_us[${reflectors[pinger]}] < min_dl_owd_delta_ewma_us )) && min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" + (( ul_owd_delta_ewmas_us[${reflectors[pinger]}] < min_ul_owd_delta_ewma_us )) && min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" + done + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + + sum_owd_baselines_delta_us=$(( sum_owd_baselines_us[pinger] - min_sum_owd_baselines_us )) + dl_owd_delta_ewma_delta_us=$(( dl_owd_delta_ewmas_us[${reflectors[pinger]}] - min_dl_owd_delta_ewma_us )) + ul_owd_delta_ewma_delta_us=$(( ul_owd_delta_ewmas_us[${reflectors[pinger]}] - min_ul_owd_delta_ewma_us )) + + if ((output_reflector_stats)) + then + printf -v reflector_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${reflectors[pinger]}" "${min_sum_owd_baselines_us}" "${sum_owd_baselines_us[pinger]}" "${sum_owd_baselines_delta_us}" "${reflector_sum_owd_baselines_delta_thr_us}" "${min_dl_owd_delta_ewma_us}" "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${dl_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" "${min_ul_owd_delta_ewma_us}" "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${ul_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" + log_msg "REFLECTOR" "${reflector_stats}" + fi + + if (( sum_owd_baselines_delta_us > reflector_sum_owd_baselines_delta_thr_us )) + then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} sum_owd_baselines_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + + if (( dl_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) + then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} dl_owd_delta_ewma_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + + if (( ul_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) + then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} ul_owd_delta_ewma_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + done + + fi + + replace_pinger_reflector_enabled=1 + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + # shellcheck disable=SC2178 + declare -n reflector_offences="reflector_${pinger}_offences" + + (( reflector_offences[reflector_offences_idx] )) && ((sum_reflector_offences[pinger]--)) + # shellcheck disable=SC2154 + reflector_offences[reflector_offences_idx]=$(( (${EPOCHREALTIME/./}-last_timestamp_reflectors_us[${reflectors[pinger]}]) > reflector_response_deadline_us ? 1 : 0 )) + + if (( reflector_offences[reflector_offences_idx] )) + then + ((sum_reflector_offences[pinger]++)) + log_msg "DEBUG" "no ping response from reflector: ${reflectors[pinger]} within reflector_response_deadline: ${reflector_response_deadline_s}s" + log_msg "DEBUG" "reflector=${reflectors[pinger]}, sum_reflector_offences=${sum_reflector_offences[pinger]} and reflector_misbehaving_detection_thr=${reflector_misbehaving_detection_thr}" + fi + + if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )) + then + + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving." + if ((replace_pinger_reflector_enabled)) + then + replace_pinger_reflector "${pinger}" + replace_pinger_reflector_enabled=0 + else + log_msg "DEBUG" "Warning: skipping replacement of reflector: ${reflectors[pinger]} given prior replacement within this reflector health check cycle." + fi + fi + done + ((reflector_offences_idx=(reflector_offences_idx+1)%reflector_misbehaving_detection_window)) + ;; + *) + log_msg "ERROR" "Unrecognized maintain pingers state: ${maintain_pingers_state}." + log_msg "ERROR" "Setting state to RUNNING" + maintain_pingers_next_state="RUNNING" + change_maintain_pingers_state + ;; + esac + + sleep_remaining_tick_time "${t_start_us}" "${reflector_health_check_interval_us}" + done +} + +set_shaper_rate() +{ + # fire up tc and update max_wire_packet_compensation if there are rates to change for the given direction + + local direction="${1}" # 'dl' or 'ul' + + if (( shaper_rate_kbps["${direction}"] != last_shaper_rate_kbps["${direction}"] )) + then + ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface[${direction}]} cake bandwidth ${shaper_rate_kbps[${direction}]}Kbit" + + if ((adjust_shaper_rate["${direction}"])) + then + tc qdisc change root dev "${interface[${direction}]}" cake bandwidth "${shaper_rate_kbps[${direction}]}Kbit" 2> /dev/null + else + ((output_cake_changes)) && log_msg "DEBUG" "adjust_${direction}_shaper_rate set to 0 in config, so skipping the corresponding tc qdisc change call." + fi + + printf "SET_ARRAY_ELEMENT shaper_rate_kbps ${direction} %s\n" "${shaper_rate_kbps[${direction}]}" >&"${monitor_achieved_rates_fd}" + last_shaper_rate_kbps["${direction}"]="${shaper_rate_kbps[${direction}]}" + + update_max_wire_packet_compensation + fi +} + +set_min_shaper_rates() +{ + log_msg "DEBUG" "Enforcing minimum shaper rates." + shaper_rate_kbps[dl]=${min_dl_shaper_rate_kbps} + shaper_rate_kbps[ul]=${min_ul_shaper_rate_kbps} + set_shaper_rate "dl" + set_shaper_rate "ul" +} + +get_max_wire_packet_size_bits() +{ + local interface="${1}" + local -n max_wire_packet_size_bits="${2}" + + read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" + [[ $(tc qdisc show dev "${interface}") =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] + max_wire_packet_size_bits=$(( 8*(max_wire_packet_size_bits+BASH_REMATCH[2]) )) + # atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits + [[ "${BASH_REMATCH[1]:-}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*((max_wire_packet_size_bits+376)/384) )) +} + +update_max_wire_packet_compensation() +{ + # Compensate for delays imposed by active traffic shaper + # This will serve to increase the delay thr at rates below around 12Mbit/s + + # compensated OWD delay thresholds in microseconds + compensated_dl_delay_thr_us=$(( dl_delay_thr_us + (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] )) + compensated_ul_delay_thr_us=$(( ul_delay_thr_us + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) + + printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" + printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" + + max_wire_packet_rtt_us=$(( (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) + + printf "SET_VAR max_wire_packet_rtt_us %s\n" "${max_wire_packet_rtt_us}" >&"${maintain_pingers_fd}" +} + +verify_ifs_up() +{ + # Check the rx/tx paths exist and give extra time for ifb's to come up if needed + # This will block if ifs never come up + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + while [[ ! -f ${rx_bytes_path} || ! -f ${tx_bytes_path} ]] + do + [[ ! -f ${rx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured download interface: '${dl_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." + [[ ! -f ${tx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured upload interface: '${ul_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." + sleep_s "${if_up_check_interval_s}" + done +} + +ewma_iteration() +{ + local value="${1}" + local alpha="${2}" # alpha must be scaled by factor of 1000000 + local -n ewma="${3}" + + prev_ewma=${ewma} + ewma=$(( (alpha*value+(1000000-alpha)*prev_ewma)/1000000 )) +} + +change_state_main() +{ + local main_next_state="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case ${main_next_state} in + + RUNNING|IDLE|STALL) + + if [[ "${main_state}" != "${main_next_state}" ]] + then + log_msg "DEBUG" "Changing main state from: ${main_state} to: ${main_next_state}" + main_state=${main_next_state} + else + log_msg "ERROR" "Received request to change main state to existing state." + fi + ;; + + *) + + log_msg "ERROR" "Received unrecognized main state change request: ${main_next_state}. Exiting now." + kill $$ 2>/dev/null + ;; + esac +} + +intercept_stderr() +{ + # send stderr to log_msg and exit cake-autorate + # use with redirection: exec 2> >(intercept_stderr) + + while read -r error + do + log_msg "ERROR" "${error}" + kill $$ 2>/dev/null + done +} + +# Debug command wrapper +# Inspired by cmd_wrapper of sqm-script +debug_cmd() +{ + # Usage: debug_cmd debug_msg err_silence cmd arg1 arg2, etc. + + # Error messages are output as log_msg ERROR messages + # Or set error_silence=1 to output errors as log_msg DEBUG messages + + local debug_msg="${1}" + local err_silence="${2}" + local cmd="${3}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + shift 3 + + local args=("${@}") + + local caller_id + local err_type + + local ret + local stderr + + err_type="ERROR" + + if ((err_silence)) + then + err_type="DEBUG" + fi + + stderr=$(${cmd} "${args[@]}" 2>&1) + ret=${?} + + caller_id=$(caller) + + if ((ret==0)) + then + log_msg "DEBUG" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=SUCCESS" + else + [[ "${err_type}" == "DEBUG" && "${debug}" == "0" ]] && return # if debug disabled, then skip on DEBUG but not on ERROR + + log_msg "${err_type}" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=FAILURE (${ret})" + log_msg "${err_type}" "debug_cmd: LAST ERROR (${stderr})" + + frame=1 + while caller_output=$(caller "${frame}") + do + log_msg "${err_type}" "debug_cmd: CALL CHAIN: ${caller_output}" + ((++frame)) + done + fi +} + +# shellcheck disable=SC1090,SC2311 +validate_config_entry() { + # Must be called before loading config_path into the global scope. + # + # When the entry is invalid, two types are returned with the first type + # being the invalid user type and second type is the default type with + # the user needing to adapt the config file so that the entry uses the + # default type. + # + # When the entry is valid, one type is returned and it will be the + # the type of either the default or user type. However because in that + # case they are both valid. It doesn't matter as they'd both have the + # same type. + + local config_path="${1}" + + local user_type + local valid_type + + user_type=$(unset "${2}" && . "${config_path}" && typeof "${2}") + valid_type=$(typeof "${2}") + + if [[ "${user_type}" != "${valid_type}" ]] + then + printf '%s' "${user_type} ${valid_type}" + return + elif [[ "${user_type}" != "string" ]] + then + printf '%s' "${valid_type}" + return + fi + + # extra validation for string, check for empty string + local -n default_value=${2} + local user_value + user_value=$(. "${config_path}" && local -n x="${2}" && printf '%s' "${x}") + + # if user is empty but default is not, invalid entry + if [[ -z "${user_value}" && -n "${default_value}" ]] + then + printf '%s' "${user_type} ${valid_type}" + else + printf '%s' "${valid_type}" + fi +} + +# ======= Start of the Main Routine ======== + +[[ -t 1 ]] && terminal=1 || terminal=0 + +type logger &> /dev/null && use_logger=1 || use_logger=0 # only perform the test once. + +log_file_path=/var/log/cake-autorate.log + +# *** WARNING: take great care if attempting to alter the run_path! *** +# *** cake-autorate issues mkdir -p ${run_path} and rm -r ${run_path} on exit. *** +run_path=/var/run/cake-autorate/ + +# cake-autorate first argument is config file path +if [[ -n "${1-}" ]] +then + config_path="${1}" +else + config_path="${PREFIX}/config.primary.sh" +fi + +if [[ ! -f "${config_path}" ]] +then + log_msg "ERROR" "No config file found. Exiting now." + exit 1 +fi + +# validate config entries before loading +mapfile -t user_config < <(grep -E '^[^(#| )].*=' "${config_path}" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') +config_error_count=0 +for key in "${user_config[@]}" +do + # Despite the fact that config_file_check is no longer required, + # we make an exemption just in this case as that variable in + # particular does not have any real impact to the operation + # of the script. + [[ "${key}" == "config_file_check" ]] && continue + + # shellcheck disable=SC2076 + if [[ ! " ${valid_config_entries[*]} " =~ " ${key} " ]] + then + ((config_error_count++)) + log_msg "ERROR" "The key: '${key}' in config file: '${config_path}' is not a valid config entry." + else + # shellcheck disable=SC2311 + read -r user supposed <<< "$(validate_config_entry "${config_path}" "${key}")" + if [[ -n "${supposed}" ]] + then + error_msg="The value of '${key}' in config file: '${config_path}' is not a valid value of type: '${supposed}'." + + case "${user}" in + negative-*) error_msg="${error_msg} Also, negative numbers are not supported." ;; + *) ;; + esac + + log_msg "ERROR" "${error_msg}" + unset error_msg + + ((config_error_count++)) + fi + unset user supposed + fi +done +if ((config_error_count)) +then + log_msg "ERROR" "The config file: '${config_path}' contains ${config_error_count} error(s). Exiting now." + exit 1 +fi +unset valid_config_entries user_config config_error_count key + +# shellcheck source=config.primary.sh +. "${config_path}" + +if [[ ${config_path} =~ config\.(.*)\.sh ]] +then + instance_id="${BASH_REMATCH[1]}" + run_path="/var/run/cake-autorate/${instance_id}" +else + log_msg "ERROR" "Instance identifier 'X' set by config.X.sh cannot be empty. Exiting now." + exit 1 +fi + +if [[ -n "${log_file_path_override-}" ]] +then + if [[ ! -d ${log_file_path_override} ]] + then + broken_log_file_path_override=${log_file_path_override} + log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log + log_msg "ERROR" "Log file path override: '${broken_log_file_path_override}' does not exist. Exiting now." + exit + fi + log_file_path=${log_file_path_override}/cake-autorate${instance_id:+.${instance_id}}.log +else + log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log +fi + +rotate_log_file # rotate here to force header prints at top of log file + +# save stderr fd, redirect stderr to intercept_stderr +# intercept_stderr sends stderr to log_msg and exits cake-autorate +exec {original_stderr_fd}>&2 2> >(intercept_stderr) + +proc_pids['intercept_stderr']=${!} + +log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${config_path}" + +# ${run_path}/ is used to store temporary files +# it should not exist on startup so if it does exit, else create the directory +if [[ -d "${run_path}" ]] +then + if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' "${run_path}/proc_pids") && [[ -d "/proc/${running_main_pid}" ]] + then + log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script." + trap - INT TERM EXIT + exit + else + log_msg "DEBUG" "${run_path} already exists but no instance is running. Removing and recreating." + rm -r "${run_path}" + mkdir -p "${run_path}" + fi +else + mkdir -p "${run_path}" +fi + +proc_pids['main']="${BASHPID}" + +no_reflectors=${#reflectors[@]} + +# Check ping binary exists +command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${pinger_binary} does not exist. Exiting script."; exit; } + +# Check no_pingers <= no_reflectors +(( no_pingers > no_reflectors )) && { log_msg "ERROR" "number of pingers cannot be greater than number of reflectors. Exiting script."; exit; } + +# Check dl/if interface not the same +[[ "${dl_if}" == "${ul_if}" ]] && { log_msg "ERROR" "download interface and upload interface are both set to: '${dl_if}', but cannot be the same. Exiting script."; exit; } + +# Check bufferbloat detection threshold not greater than window length +(( bufferbloat_detection_thr > bufferbloat_detection_window )) && { log_msg "ERROR" "bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } + +# Passed error checks + +if ((log_to_file)) +then + log_file_max_time_us=$((log_file_max_time_mins*60000000)) + log_file_max_size_bytes=$((log_file_max_size_KB*1024)) + exec {log_fd}<> <(:) + maintain_log_file & + proc_pids['maintain_log_file']=${!} +fi + +# test if stdout is a tty (terminal) +if ! ((terminal)) +then + echo "stdout not a terminal so redirecting output to: ${log_file_path}" + ((log_to_file)) && exec 1>&"${log_fd}" +fi + +# Initialize rx_bytes_path and tx_bytes_path if not set +if [[ -z "${rx_bytes_path-}" ]] +then + case "${dl_if}" in + veth*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + ifb*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + *) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + esac +fi +if [[ -z "${tx_bytes_path-}" ]] +then + case "${ul_if}" in + veth*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + ifb*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + *) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/tx_bytes" + ;; + esac +fi + +if ((debug)) +then + log_msg "DEBUG" "CAKE-autorate version: ${cake_autorate_version}" + log_msg "DEBUG" "config_path: ${config_path}" + log_msg "DEBUG" "run_path: ${run_path}" + log_msg "DEBUG" "log_file_path: ${log_file_path}" + log_msg "DEBUG" "pinger_binary:${pinger_binary}" + log_msg "DEBUG" "download interface: ${dl_if} (${min_dl_shaper_rate_kbps} / ${base_dl_shaper_rate_kbps} / ${max_dl_shaper_rate_kbps})" + log_msg "DEBUG" "upload interface: ${ul_if} (${min_ul_shaper_rate_kbps} / ${base_ul_shaper_rate_kbps} / ${max_ul_shaper_rate_kbps})" + log_msg "DEBUG" "rx_bytes_path: ${rx_bytes_path}" + log_msg "DEBUG" "tx_bytes_path: ${tx_bytes_path}" +fi + +# Check interfaces are up and wait if necessary for them to come up +verify_ifs_up + +# Initialize variables + +# Convert human readable parameters to values that work with integer arithmetic + +printf -v dl_delay_thr_us %.0f "${dl_delay_thr_ms}e3" +printf -v ul_delay_thr_us %.0f "${ul_delay_thr_ms}e3" +printf -v alpha_baseline_increase %.0f "${alpha_baseline_increase}e6" +printf -v alpha_baseline_decrease %.0f "${alpha_baseline_decrease}e6" +printf -v alpha_delta_ewma %.0f "${alpha_delta_ewma}e6" +printf -v achieved_rate_adjust_down_bufferbloat %.0f "${achieved_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_down_bufferbloat %.0f "${shaper_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_up_load_high %.0f "${shaper_rate_adjust_up_load_high}e3" +printf -v shaper_rate_adjust_down_load_low %.0f "${shaper_rate_adjust_down_load_low}e3" +printf -v shaper_rate_adjust_up_load_low %.0f "${shaper_rate_adjust_up_load_low}e3" +printf -v high_load_thr_percent %.0f "${high_load_thr}e2" +printf -v reflector_ping_interval_ms %.0f "${reflector_ping_interval_s}e3" +printf -v reflector_ping_interval_us %.0f "${reflector_ping_interval_s}e6" +printf -v reflector_health_check_interval_us %.0f "${reflector_health_check_interval_s}e6" +printf -v monitor_achieved_rates_interval_us %.0f "${monitor_achieved_rates_interval_ms}e3" +printf -v sustained_idle_sleep_thr_us %.0f "${sustained_idle_sleep_thr_s}e6" +printf -v reflector_response_deadline_us %.0f "${reflector_response_deadline_s}e6" +printf -v reflector_sum_owd_baselines_delta_thr_us %.0f "${reflector_sum_owd_baselines_delta_thr_ms}e3" +printf -v reflector_owd_delta_ewma_delta_thr_us %.0f "${reflector_owd_delta_ewma_delta_thr_ms}e3" +printf -v startup_wait_us %.0f "${startup_wait_s}e6" +printf -v global_ping_response_timeout_us %.0f "${global_ping_response_timeout_s}e6" +printf -v bufferbloat_refractory_period_us %.0f "${bufferbloat_refractory_period_ms}e3" +printf -v decay_refractory_period_us %.0f "${decay_refractory_period_ms}e3" + +for (( i=0; i<${#sss_times_s[@]}; i++ )); +do + printf -v sss_times_us[i] %.0f\\n "${sss_times_s[i]}e6" +done +printf -v sss_compensation_pre_duration_us %.0f "${sss_compensation_pre_duration_ms}e3" +printf -v sss_compensation_post_duration_us %.0f "${sss_compensation_post_duration_ms}e3" + +ping_response_interval_us=$(( reflector_ping_interval_us/no_pingers )) +ping_response_interval_ms=$(( ping_response_interval_us/1000 )) + +stall_detection_timeout_us=$(( stall_detection_thr*ping_response_interval_us )) +stall_detection_timeout_s=000000${stall_detection_timeout_us} +stall_detection_timeout_s=$(( 10#${stall_detection_timeout_s::-6})).${stall_detection_timeout_s: -6} + +declare -A bufferbloat_detected +declare -A load_percent +declare -A load_condition +declare -A t_last_bufferbloat_us +declare -A t_last_decay_us +declare -A shaper_rate_kbps +declare -A last_shaper_rate_kbps +declare -A base_shaper_rate_kbps +declare -A min_shaper_rate_kbps +declare -A max_shaper_rate_kbps +declare -A interface +declare -A adjust_shaper_rate + +base_shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" +base_shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" + +min_shaper_rate_kbps[dl]="${min_dl_shaper_rate_kbps}" +min_shaper_rate_kbps[ul]="${min_ul_shaper_rate_kbps}" + +max_shaper_rate_kbps[dl]="${max_dl_shaper_rate_kbps}" +max_shaper_rate_kbps[ul]="${max_ul_shaper_rate_kbps}" + +shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" +shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" + +last_shaper_rate_kbps[dl]=0 +last_shaper_rate_kbps[ul]=0 + +interface[dl]="${dl_if}" +interface[ul]="${ul_if}" + +adjust_shaper_rate[dl]="${adjust_dl_shaper_rate}" +adjust_shaper_rate[ul]="${adjust_ul_shaper_rate}" + +dl_max_wire_packet_size_bits=0 +ul_max_wire_packet_size_bits=0 +get_max_wire_packet_size_bits "${dl_if}" dl_max_wire_packet_size_bits +get_max_wire_packet_size_bits "${ul_if}" ul_max_wire_packet_size_bits + +set_shaper_rate "dl" +set_shaper_rate "ul" + +update_max_wire_packet_compensation + +main_state="RUNNING" + +t_start_us="${EPOCHREALTIME/./}" +t_end_us="${EPOCHREALTIME/./}" + +t_last_bufferbloat_us[dl]="${t_start_us}" +t_last_bufferbloat_us[ul]="${t_start_us}" +t_last_decay_us[dl]="${t_start_us}" +t_last_decay_us[ul]="${t_start_us}" + +t_sustained_connection_idle_us=0 +reflectors_last_timestamp_us="${EPOCHREALTIME/./}" + +mapfile -t dl_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) +mapfile -t ul_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) + +delays_idx=0 +sum_dl_delays=0 +sum_ul_delays=0 + +if ((debug)) +then + if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )) + then + log_msg "DEBUG" "Warning: bufferbloat refractory period: ${bufferbloat_refractory_period_us} us." + log_msg "DEBUG" "Warning: but expected time to overwrite samples in bufferbloat detection window is: $((bufferbloat_detection_window*ping_response_interval_us)) us." + log_msg "DEBUG" "Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." + fi + if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )) + then + log_msg "DEBUG" "Warning: reflector_response_deadline_s < 2*reflector_ping_interval_s" + log_msg "DEBUG" "Warning: consider setting an increased reflector_response_deadline." + fi +fi + +# Randomize reflectors array providing randomize_reflectors set to 1 +((randomize_reflectors)) && randomize_array reflectors + +# Wait if ${startup_wait_s} > 0 +if ((startup_wait_us>0)) +then + log_msg "DEBUG" "Waiting ${startup_wait_s} seconds before startup." + sleep_us "${startup_wait_us}" +fi + +case "${pinger_binary}" in + + tsping|fping) + exec {pinger_fds[0]}<> <(:) + ;; + + ping) + for ((pinger=0; pinger<=no_pingers; pinger++)) + do + exec {pinger_fds[pinger]}<> <(:) + done + ;; + + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + exit + ;; +esac + +monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" & +proc_pids['monitor_achieved_rates']="${!}" + +maintain_pingers & +proc_pids['maintain_pingers']="${!}" + +generate_log_file_scripts + +log_msg "INFO" "Started cake-autorate with PID: ${BASHPID} and config: ${config_path}" + +while true +do + unset command + read -r -u "${main_fd}" -a command + + if [[ "${command-}" ]] + then + + case "${command[0]}" in + + REFLECTOR_RESPONSE) + + read -r timestamp reflector seq dl_owd_baseline_us dl_owd_us dl_owd_delta_ewma_us dl_owd_delta_us ul_owd_baseline_us ul_owd_us ul_owd_delta_ewma_us ul_owd_delta_us <<< "${command[@]:1}" + ;; + + SET_VAR) + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; + SET_PROC_PID) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + true > "${run_path}/proc_pids" + for proc_pid in "${!proc_pids[@]}" + do + printf "%s=%s\n" "${proc_pid}" "${proc_pids[${proc_pid}]}" >> "${run_path}/proc_pids" + done + ;; + *) + ;; + esac + + fi + case "${main_state}" in + + RUNNING) + + if [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" && "${reflector-}" && "${seq-}" && "${dl_owd_baseline_us-}" && "${dl_owd_us-}" && "${dl_owd_delta_ewma_us-}" && "${dl_owd_delta_us-}" && "${ul_owd_baseline_us-}" && "${ul_owd_us-}" && "${ul_owd_delta_ewma_us-}" && "${ul_owd_delta_us-}" ]] + then + + t_start_us=${EPOCHREALTIME/./} + + reflectors_last_timestamp_us="${timestamp//[.]}" + + if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )) + then + log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." + continue + fi + + # Keep track of number of delays across detection window + # .. for download: + (( dl_delays[delays_idx] )) && ((sum_dl_delays--)) + dl_delays[delays_idx]=$(( dl_owd_delta_us > compensated_dl_delay_thr_us ? 1 : 0 )) + ((dl_delays[delays_idx])) && ((sum_dl_delays++)) + # .. for upload + (( ul_delays[delays_idx] )) && ((sum_ul_delays--)) + ul_delays[delays_idx]=$(( ul_owd_delta_us > compensated_ul_delay_thr_us ? 1 : 0 )) + ((ul_delays[delays_idx])) && ((sum_ul_delays++)) + # .. and move index on + (( delays_idx=(delays_idx+1)%bufferbloat_detection_window )) + + bufferbloat_detected[dl]=$(( sum_dl_delays >= bufferbloat_detection_thr ? 1 : 0 )) + bufferbloat_detected[ul]=$(( sum_ul_delays >= bufferbloat_detection_thr ? 1 : 0 )) + + load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) + load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) + + classify_load "dl" + classify_load "ul" + + update_shaper_rate "dl" + update_shaper_rate "ul" + + set_shaper_rate "dl" + set_shaper_rate "ul" + + if (( output_processing_stats )) + then + printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${load_percent[dl]}" "${load_percent[ul]}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${load_condition[dl]}" "${load_condition[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" + log_msg "DATA" "${processing_stats}" + fi + + # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) + if (( enable_sleep_function )) + then + if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]] + then + ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) + if ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) + then + change_state_main "IDLE" + + log_msg "DEBUG" "Connection idle. Waiting for minimum load." + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + + # update maintain_pingers state + printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" + + # reset idle timer + t_sustained_connection_idle_us=0 + fi + else + # reset timer + t_sustained_connection_idle_us=0 + fi + fi + elif (( (${EPOCHREALTIME/./} - reflectors_last_timestamp_us) > stall_detection_timeout_us )) + then + + log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking loads." + + #log_msg "DEBUG" "load check is: (( ${achieved_rate_kbps[dl]} kbps > ${connection_stall_thr_kbps} kbps for download && ${achieved_rate_kbps[ul]} kbps > ${connection_stall_thr_kbps} kbps for upload ))" + + # non-zero load so despite no reflector response within stall interval, the connection not considered to have stalled + # and therefore resume normal operation + if (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) + then + + log_msg "DEBUG" "load above connection stall threshold so resuming normal operation." + else + change_state_main "STALL" + + printf "CHANGE_STATE PAUSED\n" >&"${maintain_pingers_fd}" + + t_connection_stall_time_us="${EPOCHREALTIME//.}" + global_ping_response_timeout=0 + fi + + fi + + t_end_us="${EPOCHREALTIME/./}" + + ;; + IDLE) + if (( achieved_rate_kbps[dl] > connection_active_thr_kbps || achieved_rate_kbps[ul] > connection_active_thr_kbps )) + then + log_msg "DEBUG" "dl achieved rate: ${achieved_rate_kbps[dl]} kbps or ul achieved rate: ${achieved_rate_kbps[ul]} kbps exceeded connection active threshold: ${connection_active_thr_kbps} kbps. Resuming normal operation." + change_state_main "RUNNING" + printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" + t_sustained_connection_idle_us=0 + # Give some time to enable pingers to get set up + reflectors_last_timestamp_us=$(( "${EPOCHREALTIME/./}" + 2*reflector_ping_interval_us )) + fi + ;; + STALL) + + [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" ]] && reflectors_last_timestamp_us=${timestamp//[.]} + + if [[ "${command[0]}" == "REFLECTOR_RESPONSE" ]] || (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) + then + + log_msg "DEBUG" "Connection stall ended. Resuming normal operation." + printf "CHANGE_STATE RUNNING\n" >&"${maintain_pingers_fd}" + change_state_main "RUNNING" + + fi + + if (( global_ping_response_timeout==0 && ${EPOCHREALTIME/./} > (t_connection_stall_time_us + global_ping_response_timeout_us - stall_detection_timeout_us) )) + then + global_ping_response_timeout=1 + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + log_msg "SYSLOG" "Warning: Configured global ping response timeout: ${global_ping_response_timeout_s} seconds exceeded." + log_msg "DEBUG" "Restarting pingers." + printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" + printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" + fi + ;; + *) + + log_msg "ERROR" "Unrecognized main state: ${main_state}. Exiting now." + exit 1 + ;; + esac + +done diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh b/sqm-autorate/files/usr/share/sqm-autorate/config.sh similarity index 100% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh rename to sqm-autorate/files/usr/share/sqm-autorate/config.sh diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh similarity index 100% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh rename to sqm-autorate/files/usr/share/sqm-autorate/config_template.sh diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh b/sqm-autorate/files/usr/share/sqm-autorate/defaults.sh similarity index 100% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh rename to sqm-autorate/files/usr/share/sqm-autorate/defaults.sh diff --git a/sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc b/sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc new file mode 100755 index 000000000..7c953290f --- /dev/null +++ b/sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc @@ -0,0 +1,209 @@ +#!/bin/bash + +# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT + +# cake-autorate_config.sh is a script that sets up defaults for cake-autorate + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) + +INTERFACE="" + +# *** OUTPUT AND LOGGING OPTIONS *** + +output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats +output_load_stats=1 # enable (1) or disable (0) output monitoring lines showing achieved loads +output_reflector_stats=1 # enable (1) or disable (0) output monitoring lines showing reflector stats +output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +debug=1 # enable (1) or disable (0) out of debug lines + +# This can generate a LOT of records so be careful: +log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. + +# ** Take care with these settings to ensure you won't run into OOM issues on your router *** +# every write the cumulative write time and bytes associated with each log line are checked +# and if either exceeds the configured values below, the log log file is rotated +log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log) +log_file_max_time_mins=10 # maximum time between log file rotations +log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations + +# log file path defaults to /var/log/ +# or, if set below, then ${log_file_path_override} +log_file_path_override="" + +# *** STANDARD CONFIGURATION OPTIONS *** + +### For multihomed setups, it is the responsibility of the user to ensure that the probes +### sent by this instance of cake-autorate actually travel through these interfaces. +### See ping_extra_args and ping_prefix_string + +dl_if=ifb-wan # download interface +ul_if=wan # upload interface + +# pinger selection can be any of: +# fping - round robin pinging (rtts) +# ping - (iputils-ping) individual pinging (rtts) +# hping3 - individidual pinging (owds) +pinger_binary=fping + +# list of reflectors to use and number of pingers to initiate +# pingers will be initiated with reflectors in the order specified in the list +# additional reflectors will be used to replace any reflectors that go stale +# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially +# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad +# a bad reflector will go to the back of the queue on reflector rotation +reflectors=( +"1.1.1.1" "1.0.0.1" # Cloudflare +"8.8.8.8" "8.8.4.4" # Google +"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 +"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard +"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar +"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS +"185.228.168.9" "185.228.168.10" # CleanBrowsing +) + +randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup + +# Think carefully about the following settings +# to avoid excessive CPU use (proportional with ping interval / number of pingers) +# and to avoid abusive network activity (excessive ICMP frequency to one reflector) +# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G +no_pingers=6 # number of pingers to maintain +reflector_ping_interval_s=0.3 # (seconds, e.g. 0.2s or 2s) + +# delay threshold in ms is the extent of OWD increase to classify as a delay +# these are automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +dl_delay_thr_ms=30 # (milliseconds) +ul_delay_thr_ms=30 # (milliseconds) + +# Set either of the below to 0 to adjust one direction only +# or alternatively set both to 0 to simply use cake-autorate to monitor a connection +adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate +adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate + +min_dl_shaper_rate_kbps=5000 # minimum bandwidth for download (Kbit/s) +base_dl_shaper_rate_kbps=20000 # steady state bandwidth for download (Kbit/s) +max_dl_shaper_rate_kbps=80000 # maximum bandwidth for download (Kbit/s) + +min_ul_shaper_rate_kbps=5000 # minimum bandwidth for upload (Kbit/s) +base_ul_shaper_rate_kbps=20000 # steady state bandwidth for upload (KBit/s) +max_ul_shaper_rate_kbps=35000 # maximum bandwidth for upload (Kbit/s) + +# sleep functionality saves unecessary pings and CPU cycles by +# pausing all active pingers when connection is not in active use +enable_sleep_function=1 # enable (1) or disable (0) sleep functonality +connection_active_thr_kbps=1000 # threshold in Kbit/s below which dl/ul is considered idle +sustained_idle_sleep_thr_s=60.0 # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) + +min_shaper_rates_enforcement=0 # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall + +startup_wait_s=0.0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) + +# *** ADVANCED CONFIGURATION OPTIONS *** + +log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename + +### In multi-homed setups, it is mandatory to use either ping_extra_args +### or ping_prefix_string to direct the pings through $dl_if and $ul_if. +### No universal recommendation exists, because there are multiple +### policy-routing packages available (e.g. vpn-policy-routing and mwan3). +### Typically they either react to a firewall mark set on the pings, or +### provide a convenient wrapper. +### +### In a traditional single-homed setup, there is usually no need for these parameters. +### +### These arguments can also be used for any other purpose - e.g. for setting a +### particular QoS mark. + +# extra arguments for ping or fping +# e.g., here is how you can set the correct outgoing interface and +# the firewall mark for ping: +# ping_extra_args="-I wwan0 -m $((0x300))" +# Unfortunately, fping does not offer a command line switch to set +# the firewall mark. +# WARNING: no error checking so use at own risk! +ping_extra_args="" + +# a wrapper for ping binary - used as a prefix for the real command +# e.g., when using mwan3, it is recommended to set it like this: +# ping_prefix_string="mwan3 use gpon exec" +# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess. +# Running ping or fping as a subprocess will lead to problems stopping it. +# WARNING: no error checking - so use at own risk! +ping_prefix_string="" + +# interval in ms for monitoring achieved rx/tx rates +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +monitor_achieved_rates_interval_ms=200 # (milliseconds) + +# bufferbloat is detected when (bufferbloat_detection_thr) samples +# out of the last (bufferbloat detection window) samples are delayed +bufferbloat_detection_window=6 # number of samples to retain in detection window +bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection + +# OWD baseline against which to measure delays +# the idea is that the baseline is allowed to increase slowly to allow for path changes +# and slowly enough such that bufferbloat will be corrected well before the baseline increases, +# but it will decrease very rapidly to ensure delays are measured against the shortest path +alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase +alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease + +# OWD delta from baseline is tracked using ewma with alpha set below +alpha_delta_ewma=0.095 + +# rate adjustment parameters +# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate +# to exploit that transfer rates during bufferbloat provide an indication of line capacity +# otherwise shaper rate is adjusted up on load high, and down on load idle or low +achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat +shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat +shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected +shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected +shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected + +# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate +high_load_thr=0.75 # % of currently set bandwidth for detecting high load + +# refractory periods between successive bufferbloat/decay rate changes +# the bufferbloat refractory period should be greater than the +# average time it would take to replace the bufferbloat +# detection window with new samples upon a bufferbloat event +bufferbloat_refractory_period_ms=300 # (milliseconds) +decay_refractory_period_ms=1000 # (milliseconds) + +# interval for checking reflector health +reflector_health_check_interval_s=1.0 # (seconds) +# deadline for reflector response not to be classified as an offence against reflector +reflector_response_deadline_s=1.0 # (seconds) + +# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples +# out of the last (reflector misbehaving detection window) samples are offences +# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to +# 3 offences within the last 60s +reflector_misbehaving_detection_window=60 +reflector_misbehaving_detection_thr=3 + +reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list + +reflector_comparison_interval_mins=1 # how often to compare reflectors +reflector_sum_owd_baselines_delta_thr_ms=20 # max increase from min sum owd baselines before reflector rotated +reflector_owd_delta_ewma_delta_thr_ms=10 # max increase from min delta ewma before reflector rotated + +# stall is detected when the following two conditions are met: +# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and +# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr +stall_detection_thr=5 +connection_stall_thr_kbps=10 + +global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no ping response whatsoever (seconds) + +if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) + +# Starlink satellite switch (sss) compensation options +sss_compensation=0 # enable (1) or disable (0) Starlink handling +# satellite switch compensation start times in seconds of each minute +sss_times_s=("12.0" "27.0" "42.0" "57.0") +sss_compensation_pre_duration_ms=300 +sss_compensation_post_duration_ms=200 diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh b/sqm-autorate/files/usr/share/sqm-autorate/launcher.sh similarity index 100% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh rename to sqm-autorate/files/usr/share/sqm-autorate/launcher.sh diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh b/sqm-autorate/files/usr/share/sqm-autorate/lib.sh similarity index 100% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh rename to sqm-autorate/files/usr/share/sqm-autorate/lib.sh From 513e71aee8471cfc099821f50bc520577f1af1f8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 18 Oct 2023 11:01:10 +0200 Subject: [PATCH 1136/2059] Change when modemmanager device fail --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 4f7a018ce..aef6be050 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -736,9 +736,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then _log "Set $OMR_TRACKER_INTERFACE up" ifup $OMR_TRACKER_INTERFACE sleep 20 - fi - - if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "dhcp" ]; then + elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "dhcp" ]); then for modem in $(mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then modem_device=$(mmcli -m $modem -K | grep 'modem.generic.device ' | awk '{print $3}') From b2f4ad38ee333094937cbcd132d635698a4fe7b0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 19 Oct 2023 07:15:43 +0200 Subject: [PATCH 1137/2059] Add ipset dependency to omr-bypass --- omr-bypass/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-bypass/Makefile b/omr-bypass/Makefile index b0f813a45..b75dcf46e 100644 --- a/omr-bypass/Makefile +++ b/omr-bypass/Makefile @@ -16,7 +16,7 @@ include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) SECTION:=net CATEGORY:=Network -DEPENDS:=+curl +dnsmasq-full +sqlite3-cli +iptables +iptables-mod-extra +DEPENDS:=+curl +dnsmasq-full +sqlite3-cli +iptables +iptables-mod-extra +ipset TITLE:=OMR-ByPass endef From b8ca72b4109bbf7108d76d886a53ef7ed0b94ea3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 19 Oct 2023 12:05:34 +0200 Subject: [PATCH 1138/2059] Changes needed for kernel 6.6 support --- ndpi-netfilter2/Makefile | 3 ++- openmptcprouter/files/etc/uci-defaults/1980-omr-firewall | 3 +++ r8152/Makefile | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 81a815641..406f647ac 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -77,7 +77,8 @@ define KernelPackage/ipt-ndpi TITLE:= nDPI net netfilter module # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15) @!TARGET_ramips - DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @!TARGET_ramips + DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +(LINUX_5_4||LINUX_6_1):kmod-ipt-compat-xtables +libpcap @!TARGET_ramips +# DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap KCONFIG:=CONFIG_NF_CONNTRACK_LABELS=y \ CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y FILES:= $(PKG_BUILD_DIR)/ndpi-netfilter/src/xt_ndpi.ko diff --git a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall index 0dd4b0a57..486951646 100755 --- a/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall +++ b/openmptcprouter/files/etc/uci-defaults/1980-omr-firewall @@ -262,6 +262,9 @@ if [ "$(uci -q get openmptcprouter.settings.sipalg)" = "0" ]; then [ -n "$(lsmod | grep nf_conntrack_sip)" ] && rmmod nf_conntrack_sip 2>&1 >/dev/null fi +# Remove mtu_fix check, doesn't work on kernel 6.6 +sed -i 's/if (zone\.mtu_fix && this\.kernel < 0x040a0000) {/if (zone.mtu_fix \&\& this.kernel < 0x040a0000 \&\& false) {/' /usr/share/ucode/fw4.uc + rm -f /tmp/luci-indexcache exit 0 diff --git a/r8152/Makefile b/r8152/Makefile index 5921bdcc7..f07c14969 100644 --- a/r8152/Makefile +++ b/r8152/Makefile @@ -26,7 +26,7 @@ define KernelPackage/usb-net-rtl8152-vendor VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) TITLE:=Kernel module for USB-to-Ethernet Realtek convertors SUBMENU:=USB Support - DEPENDS:=+kmod-usb-net + DEPENDS:=+kmod-usb-net @(LINUX_5_4||LINUX_6_1) FILES:=$(PKG_BUILD_DIR)/r8152.ko AUTOLOAD:=$(call AutoProbe,r8152) CONFLICTS:=kmod-usb-net-rtl8152 From 666b8fbbdddd278ddb5732227c81ee0468936f27 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 21 Oct 2023 07:27:46 +0200 Subject: [PATCH 1139/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/3005 --- openmptcprouter/files/etc/hotplug.d/iface/00-nego | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/hotplug.d/iface/00-nego b/openmptcprouter/files/etc/hotplug.d/iface/00-nego index 9ad0cb927..24ef81106 100644 --- a/openmptcprouter/files/etc/hotplug.d/iface/00-nego +++ b/openmptcprouter/files/etc/hotplug.d/iface/00-nego @@ -1,3 +1,3 @@ #!/bin/sh # Needed for some device, like rtl8156 2.5G USB adapter -[ "$ACTION" = "ifup" ] && [ -n "$DEVICE" ] && ([ -n "$(lsusb | grep 8156)" ] || [ -n "$(ethtool $DEVICE | grep 2500)" ]) && ethtool -s $DEVICE autoneg on \ No newline at end of file +[ "$ACTION" = "ifup" ] && [ -n "$DEVICE" ] && [ -n "$(lsusb | grep 8156)" ] && [ -n "$(ethtool $DEVICE | grep 2500)" ] && ethtool -s $DEVICE autoneg on \ No newline at end of file From 987c7ff911caca117efd2cf632085eb75b12f9ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 23 Oct 2023 14:40:22 +0200 Subject: [PATCH 1140/2059] Fix on shadowsocks-libev install --- shadowsocks-libev/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shadowsocks-libev/Makefile b/shadowsocks-libev/Makefile index 1cef501f0..6eea8b25c 100644 --- a/shadowsocks-libev/Makefile +++ b/shadowsocks-libev/Makefile @@ -88,8 +88,9 @@ define Package/shadowsocks-libev-ss-rules/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) ./files/ss-rules $(1)/usr/bin $(INSTALL_BIN) ./files/ss-rules6 $(1)/usr/bin - $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/etc $(INSTALL_DATA) ./files/firewall.ss-rules $(1)/etc + $(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_BIN) ./files/ss-rules.defaults $(1)/etc/uci-defaults $(INSTALL_DIR) $(1)/etc/sysctl.d $(INSTALL_DATA) ./files/shadowsocks.conf $(1)/etc/sysctl.d From b49db635eef61ef3e1860deb5f1c72a35754edad Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 23 Oct 2023 14:40:44 +0200 Subject: [PATCH 1141/2059] Check that server is not disabled on VPS script before using it --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 1138bab2b..bff3342a3 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2145,6 +2145,7 @@ _get_token() { _config_service() { servername=$1 + [ "$(uci -q get openmptcprouter.${servername}.disabled)" = "1" ] && return vps_config="" tokenserver=$(_get_token $servername) server="$(echo $tokenserver | cut -f1 -d:)" From 982b856db291720a6be3b252887522204066ab92 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 23 Oct 2023 14:41:31 +0200 Subject: [PATCH 1142/2059] Changes on xtables for 6.6 kernel --- xtables-addons/Makefile | 238 + .../001-fix-kernel-version-detection.patch | 11 + .../patches/100-add-rtsp-conntrack.patch | 1742 ++ .../patches/200-add-lua-packetscript.patch | 18168 ++++++++++++++++ .../patches/201-fix-lua-packetscript.patch | 147 + .../patches/210-freebsd-build-fix.patch | 11 + .../patches/900-remove-checksumh.patch | 33 + 7 files changed, 20350 insertions(+) create mode 100644 xtables-addons/Makefile create mode 100644 xtables-addons/patches/001-fix-kernel-version-detection.patch create mode 100644 xtables-addons/patches/100-add-rtsp-conntrack.patch create mode 100644 xtables-addons/patches/200-add-lua-packetscript.patch create mode 100644 xtables-addons/patches/201-fix-lua-packetscript.patch create mode 100644 xtables-addons/patches/210-freebsd-build-fix.patch create mode 100644 xtables-addons/patches/900-remove-checksumh.patch diff --git a/xtables-addons/Makefile b/xtables-addons/Makefile new file mode 100644 index 000000000..fc4b39c36 --- /dev/null +++ b/xtables-addons/Makefile @@ -0,0 +1,238 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2009-2013 OpenWrt.org +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=xtables-addons +PKG_VERSION:=3.24 +PKG_RELEASE:=1 +PKG_HASH:=3e823f71720519ced31c4c7d2bfaf7120d9c01c59a0843dfcbe93c95c64d81c1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://inai.de/files/xtables-addons/ +PKG_BUILD_DEPENDS:=iptables + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +PKG_MAINTAINER:=Jo-Philipp Wich +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=COPYING + +PKG_FIXUP:=autoreconf +PKG_ASLR_PIE:=0 + +include $(INCLUDE_DIR)/package.mk + +define Package/xtables-addons + SECTION:=net + CATEGORY:=Network + SUBMENU:=Firewall + TITLE:=Extensions not distributed in the main Xtables + URL:=https://inai.de/projects/xtables-addons/ +endef + +# uses GNU configure + +CONFIGURE_ARGS+= \ + --with-kbuild="$(LINUX_DIR)" \ + --with-xtlibdir="/usr/lib/iptables" + +ifdef CONFIG_EXTERNAL_TOOLCHAIN +MAKE_FLAGS:= \ + $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ + DEPMOD="/bin/true" + +MAKE_INSTALL_FLAGS:= \ + $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ + DEPMOD="/bin/true" +else +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + $(KERNEL_MAKE_FLAGS) \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + DEPMOD="/bin/true" \ + all +endef + +define Build/Install + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(KERNEL_MAKE_FLAGS) \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + DEPMOD="/bin/true" \ + install +endef +endif + +# 1: extension/module suffix used in package name +# 2: extension/module display name used in package title/description +# 3: list of extensions to package +# 4: list of modules to package +# 5: module load priority +# 6: module depends +define BuildTemplate + + ifneq ($(3),) + define Package/iptables-mod-$(1) + $$(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=$(2) iptables extension + DEPENDS:=iptables $(if $(4),+kmod-ipt-$(1)) + endef + + define Package/iptables-mod-$(1)/install + $(INSTALL_DIR) $$(1)/usr/lib/iptables + for m in $(3); do \ + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so \ + $$(1)/usr/lib/iptables/ ; \ + done + endef + + $$(eval $$(call BuildPackage,iptables-mod-$(1))) + endif + + ifneq ($(4),) + define KernelPackage/ipt-$(1) + SUBMENU:=Netfilter Extensions + TITLE:=$(2) netfilter module + DEPENDS:=+kmod-ipt-core $(5) + FILES:=$(foreach mod,$(4),$(PKG_BUILD_DIR)/extensions/$(mod).$(LINUX_KMOD_SUFFIX)) + AUTOLOAD:=$(call AutoProbe,$(notdir $(4))) + endef + + $$(eval $$(call KernelPackage,ipt-$(1))) + endif + +endef + + +define Package/iptaccount + $(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=iptables-mod-account control utility + DEPENDS:=iptables +iptables-mod-account +endef + +define Package/iptaccount/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libxt_ACCOUNT_cl.so* \ + $(1)/usr/lib/ + $(CP) \ + $(PKG_INSTALL_DIR)/usr/sbin/iptaccount \ + $(1)/usr/sbin/ +endef + + +define Package/iptasn + $(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=iptables-mod-asn support scripts for MaxMind ASN databases + DEPENDS:=iptables +iptables-mod-asn \ + +perl +perlbase-getopt +perlbase-io +perl-text-csv_xs \ + +perl-net-cidr-lite \ + +wget-ssl +!BUSYBOX_CONFIG_ZCAT:gzip +endef + +define Package/iptasn/config + menu "Select iptasn options" + config IPTASN_PRESERVE + bool "Preserve across sysupgrades" + default n + help + Backup and restore during sysupgrade (requires >7MB) + endmenu +endef + +ifeq ($(CONFIG_IPTASN_PRESERVE),y) +define Package/iptasn/conffiles +/usr/share/xt_asn/ +endef +endif + +define Package/iptasn/install + $(INSTALL_DIR) $(1)/usr/lib/xtables-addons + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/xtables-addons/xt_asn_{build,dl} \ + $(1)/usr/lib/xtables-addons/ + $(INSTALL_DIR) $(1)/usr/share/xt_asn + touch $(1)/usr/share/xt_asn/.keep +endef + + +define Package/iptgeoip + $(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=iptables-mod-geoip support scripts for MaxMind GeoIP databases + DEPENDS:=iptables +iptables-mod-geoip \ + +perl +perlbase-getopt +perlbase-io +perl-text-csv_xs \ + +perl-net-cidr-lite \ + +wget-ssl +!BUSYBOX_CONFIG_ZCAT:gzip +endef + +define Package/iptgeoip/config + menu "Select iptgeoip options" + config IPTGEOIP_PRESERVE + bool "Preserve across sysupgrades" + default n + help + Backup and restore during sysupgrade (requires >7MB) + endmenu +endef + +ifeq ($(CONFIG_IPTGEOIP_PRESERVE),y) +define Package/iptgeoip/conffiles +/usr/share/xt_geoip/ +endef +endif + +define Package/iptgeoip/install + $(INSTALL_DIR) $(1)/usr/lib/xtables-addons + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/xtables-addons/xt_geoip_{build,dl}{,_maxmind} \ + $(1)/usr/lib/xtables-addons/ + $(INSTALL_DIR) $(1)/usr/bin + $(CP) \ + $(PKG_INSTALL_DIR)/usr/bin/xt_geoip_query \ + $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/usr/share/xt_geoip + touch $(1)/usr/share/xt_geoip/.keep +endef + + +#$(eval $(call BuildTemplate,SUFFIX,DESCRIPTION,EXTENSION,MODULE,PRIORITY,DEPENDS)) + +$(eval $(call BuildTemplate,compat-xtables,API compatibilty layer,,compat_xtables,+IPV6:kmod-ip6tables)) +$(eval $(call BuildTemplate,nathelper-rtsp,RTSP Conntrack and NAT,,rtsp/nf_conntrack_rtsp rtsp/nf_nat_rtsp,+kmod-ipt-conntrack-extra +kmod-ipt-nat)) + +$(eval $(call BuildTemplate,account,ACCOUNT,xt_ACCOUNT,ACCOUNT/xt_ACCOUNT,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,asn,asn,xt_asn,xt_asn,)) +$(eval $(call BuildTemplate,chaos,CHAOS,xt_CHAOS,xt_CHAOS,+kmod-ipt-compat-xtables +kmod-ipt-delude +kmod-ipt-tarpit)) +$(eval $(call BuildTemplate,condition,Condition,xt_condition,xt_condition,)) +$(eval $(call BuildTemplate,delude,DELUDE,xt_DELUDE,xt_DELUDE,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,dhcpmac,DHCPMAC,xt_DHCPMAC,xt_DHCPMAC,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,dnetmap,DNETMAP,xt_DNETMAP,xt_DNETMAP,+kmod-ipt-compat-xtables +kmod-ipt-nat)) +$(eval $(call BuildTemplate,fuzzy,fuzzy,xt_fuzzy,xt_fuzzy,)) +$(eval $(call BuildTemplate,geoip,geoip,xt_geoip,xt_geoip,)) +$(eval $(call BuildTemplate,iface,iface,xt_iface,xt_iface,)) +$(eval $(call BuildTemplate,ipmark,IPMARK,xt_IPMARK,xt_IPMARK,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,ipp2p,IPP2P,xt_ipp2p,xt_ipp2p,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,ipv4options,ipv4options,xt_ipv4options,xt_ipv4options,)) +$(eval $(call BuildTemplate,length2,length2,xt_length2,xt_length2,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,logmark,LOGMARK,xt_LOGMARK,xt_LOGMARK,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,lscan,lscan,xt_lscan,xt_lscan,)) +$(eval $(call BuildTemplate,lua,Lua PacketScript,xt_LUA,LUA/xt_LUA,+kmod-ipt-conntrack-extra)) +$(eval $(call BuildTemplate,proto,PROTO,xt_PROTO,xt_PROTO,)) +$(eval $(call BuildTemplate,psd,psd,xt_psd,xt_psd,)) +$(eval $(call BuildTemplate,quota2,quota2,xt_quota2,xt_quota2,)) +$(eval $(call BuildTemplate,sysrq,SYSRQ,xt_SYSRQ,xt_SYSRQ,+kmod-ipt-compat-xtables +kmod-crypto-hash)) +$(eval $(call BuildTemplate,tarpit,TARPIT,xt_TARPIT,xt_TARPIT,+kmod-ipt-compat-xtables)) + +$(eval $(call BuildPackage,iptaccount)) +$(eval $(call BuildPackage,iptasn)) +$(eval $(call BuildPackage,iptgeoip)) diff --git a/xtables-addons/patches/001-fix-kernel-version-detection.patch b/xtables-addons/patches/001-fix-kernel-version-detection.patch new file mode 100644 index 000000000..e29b3925c --- /dev/null +++ b/xtables-addons/patches/001-fix-kernel-version-detection.patch @@ -0,0 +1,11 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -41,7 +41,7 @@ regular_CFLAGS="-Wall -Waggregate-return + + AS_IF([test -n "$kbuilddir"], [ + AC_MSG_CHECKING([kernel version that we will build against]) +- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" ++ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" + save_IFS="$IFS" + IFS='.' + set x $krel diff --git a/xtables-addons/patches/100-add-rtsp-conntrack.patch b/xtables-addons/patches/100-add-rtsp-conntrack.patch new file mode 100644 index 000000000..befcd06a3 --- /dev/null +++ b/xtables-addons/patches/100-add-rtsp-conntrack.patch @@ -0,0 +1,1742 @@ +--- /dev/null ++++ b/extensions/rtsp/Kbuild +@@ -0,0 +1,4 @@ ++# -*- Makefile -*- ++ ++obj-m += nf_nat_rtsp.o ++obj-m += nf_conntrack_rtsp.o +--- /dev/null ++++ b/extensions/rtsp/netfilter_helpers.h +@@ -0,0 +1,144 @@ ++/* ++ * Helpers for netfiler modules. This file provides implementations for basic ++ * functions such as strncasecmp(), etc. ++ * ++ * gcc will warn for defined but unused functions, so we only include the ++ * functions requested. The following macros are used: ++ * NF_NEED_STRNCASECMP nf_strncasecmp() ++ * NF_NEED_STRTOU16 nf_strtou16() ++ * NF_NEED_STRTOU32 nf_strtou32() ++ */ ++#ifndef _NETFILTER_HELPERS_H ++#define _NETFILTER_HELPERS_H ++ ++/* Only include these functions for kernel code. */ ++#ifdef __KERNEL__ ++ ++#include ++ ++#include ++#define iseol(c) ( (c) == '\r' || (c) == '\n' ) ++ ++/* ++ * The standard strncasecmp() ++ */ ++#ifdef NF_NEED_STRNCASECMP ++static int ++nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) ++{ ++ if (s1 == NULL || s2 == NULL) ++ { ++ if (s1 == NULL && s2 == NULL) ++ { ++ return 0; ++ } ++ return (s1 == NULL) ? -1 : 1; ++ } ++ while (len > 0 && tolower(*s1) == tolower(*s2)) ++ { ++ len--; ++ s1++; ++ s2++; ++ } ++ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); ++} ++#endif /* NF_NEED_STRNCASECMP */ ++ ++/* ++ * Parse a string containing a 16-bit unsigned integer. ++ * Returns the number of chars used, or zero if no number is found. ++ */ ++#ifdef NF_NEED_STRTOU16 ++static int ++nf_strtou16(const char* pbuf, u_int16_t* pval) ++{ ++ int n = 0; ++ ++ *pval = 0; ++ while (isdigit(pbuf[n])) ++ { ++ *pval = (*pval * 10) + (pbuf[n] - '0'); ++ n++; ++ } ++ ++ return n; ++} ++#endif /* NF_NEED_STRTOU16 */ ++ ++/* ++ * Parse a string containing a 32-bit unsigned integer. ++ * Returns the number of chars used, or zero if no number is found. ++ */ ++#ifdef NF_NEED_STRTOU32 ++static int ++nf_strtou32(const char* pbuf, u_int32_t* pval) ++{ ++ int n = 0; ++ ++ *pval = 0; ++ while (pbuf[n] >= '0' && pbuf[n] <= '9') ++ { ++ *pval = (*pval * 10) + (pbuf[n] - '0'); ++ n++; ++ } ++ ++ return n; ++} ++#endif /* NF_NEED_STRTOU32 */ ++ ++/* ++ * Given a buffer and length, advance to the next line and mark the current ++ * line. ++ */ ++#ifdef NF_NEED_NEXTLINE ++static int ++nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) ++{ ++ uint off = *poff; ++ uint physlen = 0; ++ ++ if (off >= len) ++ { ++ return 0; ++ } ++ ++ while (p[off] != '\n') ++ { ++ if (len-off <= 1) ++ { ++ return 0; ++ } ++ ++ physlen++; ++ off++; ++ } ++ ++ /* if we saw a crlf, physlen needs adjusted */ ++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') ++ { ++ physlen--; ++ } ++ ++ /* advance past the newline */ ++ off++; ++ ++ *plineoff = *poff; ++ *plinelen = physlen; ++ *poff = off; ++ ++ return 1; ++} ++#endif /* NF_NEED_NEXTLINE */ ++ ++static inline int rtsp_nf_ct_expect_related(struct nf_conntrack_expect *expect) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) ++ return nf_ct_expect_related(expect, 0); ++#else ++ return nf_ct_expect_related(expect); ++#endif ++} ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _NETFILTER_HELPERS_H */ +--- /dev/null ++++ b/extensions/rtsp/netfilter_mime.h +@@ -0,0 +1,89 @@ ++/* ++ * MIME functions for netfilter modules. This file provides implementations ++ * for basic MIME parsing. MIME headers are used in many protocols, such as ++ * HTTP, RTSP, SIP, etc. ++ * ++ * gcc will warn for defined but unused functions, so we only include the ++ * functions requested. The following macros are used: ++ * NF_NEED_MIME_NEXTLINE nf_mime_nextline() ++ */ ++#ifndef _NETFILTER_MIME_H ++#define _NETFILTER_MIME_H ++ ++/* Only include these functions for kernel code. */ ++#ifdef __KERNEL__ ++ ++#include ++ ++/* ++ * Given a buffer and length, advance to the next line and mark the current ++ * line. If the current line is empty, *plinelen will be set to zero. If ++ * not, it will be set to the actual line length (including CRLF). ++ * ++ * 'line' in this context means logical line (includes LWS continuations). ++ * Returns 1 on success, 0 on failure. ++ */ ++#ifdef NF_NEED_MIME_NEXTLINE ++static int ++nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) ++{ ++ uint off = *poff; ++ uint physlen = 0; ++ int is_first_line = 1; ++ ++ if (off >= len) ++ { ++ return 0; ++ } ++ ++ do ++ { ++ while (p[off] != '\n') ++ { ++ if (len-off <= 1) ++ { ++ return 0; ++ } ++ ++ physlen++; ++ off++; ++ } ++ ++ /* if we saw a crlf, physlen needs adjusted */ ++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') ++ { ++ physlen--; ++ } ++ ++ /* advance past the newline */ ++ off++; ++ ++ /* check for an empty line */ ++ if (physlen == 0) ++ { ++ break; ++ } ++ ++ /* check for colon on the first physical line */ ++ if (is_first_line) ++ { ++ is_first_line = 0; ++ if (memchr(p+(*poff), ':', physlen) == NULL) ++ { ++ return 0; ++ } ++ } ++ } ++ while (p[off] == ' ' || p[off] == '\t'); ++ ++ *plineoff = *poff; ++ *plinelen = (physlen == 0) ? 0 : (off - *poff); ++ *poff = off; ++ ++ return 1; ++} ++#endif /* NF_NEED_MIME_NEXTLINE */ ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _NETFILTER_MIME_H */ +--- /dev/null ++++ b/extensions/rtsp/nf_conntrack_rtsp.c +@@ -0,0 +1,756 @@ ++/* ++ * RTSP extension for IP connection tracking ++ * (C) 2003 by Tom Marshall ++ * ++ * 2005-02-13: Harald Welte ++ * - port to 2.6 ++ * - update to recent post-2.6.11 api changes ++ * 2006-09-14: Steven Van Acker ++ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack ++ * 2007-04-18: Michael Guntsche ++ * - Port to new NF API ++ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd ++ * - fixed rtcp nat mapping and other port mapping fixes ++ * - simple TEARDOWN request handling ++ * - codestyle fixes and other less significant bug fixes ++ * 2018-04-17: Alin Nastac ++ * Hans Dedecker ++ * - use IP address read from SETUP URI in expected connections ++ * 2018-04-18: Hans Dedecker ++ * - update RTP expected connection source IP based on SOURCE ++ * in the SETUP reply message ++ * 2018-08-03: Alin Nastac ++ * Hans Dedecker ++ * - parse non-standard destination=address:port format ++ * ++ * based on ip_conntrack_irc.c ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Module load syntax: ++ * insmod nf_conntrack_rtsp.o ports=port1,port2,...port ++ * max_outstanding=n setup_timeout=secs ++ * ++ * If no ports are specified, the default will be port 554. ++ * ++ * With max_outstanding you can define the maximum number of not yet ++ * answered SETUP requests per RTSP session (default 8). ++ * With setup_timeout you can specify how long the system waits for ++ * an expected data channel (default 300 seconds). ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "nf_conntrack_rtsp.h" ++ ++#define NF_NEED_STRNCASECMP ++#define NF_NEED_STRTOU16 ++#define NF_NEED_STRTOU32 ++#define NF_NEED_NEXTLINE ++#include "netfilter_helpers.h" ++#define NF_NEED_MIME_NEXTLINE ++#include "netfilter_mime.h" ++ ++#include ++ ++#define MAX_PORTS 8 ++static int ports[MAX_PORTS]; ++static int num_ports = 0; ++static int max_outstanding = 8; ++static unsigned int setup_timeout = 300; ++ ++MODULE_AUTHOR("Tom Marshall "); ++MODULE_DESCRIPTION("RTSP connection tracking module"); ++MODULE_LICENSE("GPL"); ++module_param_array(ports, int, &num_ports, 0400); ++MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); ++module_param(max_outstanding, int, 0400); ++MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); ++module_param(setup_timeout, uint, 0400); ++MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); ++ ++static char *rtsp_buffer; ++static DEFINE_SPINLOCK(rtsp_buffer_lock); ++ ++static struct nf_conntrack_expect_policy rtsp_exp_policy; ++ ++unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, ++ enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect *rtp_exp, ++ struct nf_conntrack_expect *rtcp_exp); ++ ++EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); ++ ++/* ++ * Max mappings we will allow for one RTSP connection (for RTP, the number ++ * of allocated ports is twice this value). Note that SMIL burns a lot of ++ * ports so keep this reasonably high. If this is too low, you will see a ++ * lot of "no free client map entries" messages. ++ */ ++#define MAX_PORT_MAPS 16 ++ ++/*** default port list was here in the masq code: 554, 3030, 4040 ***/ ++ ++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } ++ ++/* ++ * Parse an RTSP packet. ++ * ++ * Returns zero if parsing failed. ++ * ++ * Parameters: ++ * IN ptcp tcp data pointer ++ * IN tcplen tcp data len ++ * IN/OUT ptcpoff points to current tcp offset ++ * OUT phdrsoff set to offset of rtsp headers ++ * OUT phdrslen set to length of rtsp headers ++ * OUT pcseqoff set to offset of CSeq header ++ * OUT pcseqlen set to length of CSeq header ++ */ ++static int ++rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, ++ uint* phdrsoff, uint* phdrslen, ++ uint* pcseqoff, uint* pcseqlen, ++ uint* transoff, uint* translen) ++{ ++ uint entitylen = 0; ++ uint lineoff; ++ uint linelen; ++ ++ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) ++ return 0; ++ ++ *phdrsoff = *ptcpoff; ++ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) { ++ if (linelen == 0) { ++ if (entitylen > 0) ++ *ptcpoff += min(entitylen, tcplen - *ptcpoff); ++ break; ++ } ++ if (lineoff+linelen > tcplen) { ++ pr_info("!! overrun !!\n"); ++ break; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { ++ *pcseqoff = lineoff; ++ *pcseqlen = linelen; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { ++ *transoff = lineoff; ++ *translen = linelen; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) { ++ uint off = lineoff+15; ++ SKIP_WSPACE(ptcp+lineoff, linelen, off); ++ nf_strtou32(ptcp+off, &entitylen); ++ } ++ } ++ *phdrslen = (*ptcpoff) - (*phdrsoff); ++ ++ return 1; ++} ++ ++/* ++ * Find lo/hi client ports and/or source (if any) in transport header ++ * In: ++ * ptcp, tcplen = packet ++ * tranoff, tranlen = buffer to search ++ * ++ * Out: ++ * pport_lo, pport_hi = lo/hi ports (host endian) ++ * srvaddr ++ * ++ * Returns nonzero if any client ports found ++ * ++ * Note: it is valid (and expected) for the client to request multiple ++ * transports, so we need to parse the entire line. ++ */ ++static int ++rtsp_parse_transport(char* ptran, uint tranlen, ++ struct ip_ct_rtsp_expect* prtspexp) ++{ ++ int rc = 0; ++ uint off = 0; ++ ++ if (tranlen < 10 || !iseol(ptran[tranlen-1]) || ++ nf_strncasecmp(ptran, "Transport:", 10) != 0) { ++ pr_info("sanity check failed\n"); ++ return 0; ++ } ++ ++ pr_debug("tran='%.*s'\n", (int)tranlen, ptran); ++ off += 10; ++ SKIP_WSPACE(ptran, tranlen, off); ++ ++ /* Transport: tran;field;field=val,tran;field;field=val,... */ ++ while (off < tranlen) { ++ const char* pparamend; ++ uint nextparamoff; ++ ++ pparamend = memchr(ptran+off, ',', tranlen-off); ++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; ++ nextparamoff = pparamend-ptran; ++ ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ ++ if (strncmp(ptran+off, "client_port=", 12) == 0) { ++ u_int16_t port; ++ uint numlen; ++ ++ off += 12; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ if (prtspexp->loport != 0 && prtspexp->loport != port) ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ else { ++ pr_debug("lo port found : %hu\n", port); ++ prtspexp->loport = prtspexp->hiport = port; ++ if (ptran[off] == '-') { ++ off++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ prtspexp->pbtype = pb_range; ++ prtspexp->hiport = port; ++ ++ // If we have a range, assume rtp: ++ // loport must be even, hiport must be loport+1 ++ if ((prtspexp->loport & 0x0001) != 0 || ++ prtspexp->hiport != prtspexp->loport+1) { ++ pr_debug("incorrect range: %hu-%hu, correcting\n", ++ prtspexp->loport, prtspexp->hiport); ++ prtspexp->loport &= 0xfffe; ++ prtspexp->hiport = prtspexp->loport+1; ++ } ++ } else if (ptran[off] == '/') { ++ off++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ prtspexp->pbtype = pb_discon; ++ prtspexp->hiport = port; ++ } ++ rc = 1; ++ } ++ } else if (strncmp(ptran+off, "source=", 7) == 0) { ++ uint srcaddrlen; ++ ++ off += 7; ++ srcaddrlen = nextfieldoff - off - 1; ++ ++ if (in4_pton(ptran + off, srcaddrlen, ++ (u8 *)&prtspexp->srvaddr.in, ++ -1, NULL)) ++ pr_debug("source found : %pI4\n", ++ &prtspexp->srvaddr.ip); ++ } else if (nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { ++ const char *psep; ++ u_int16_t port; ++ ++ off += 12; ++ ++ if (in4_pton(ptran+off, nextfieldoff - off - 1, (u8 *)&prtspexp->cltaddr.in, -1, NULL)) { ++ pr_debug("destination found : %pI4\n", &prtspexp->cltaddr.ip); ++ ++ /* ++ * Some RTSP clients(mostly STBs) use non-standard destination parameters: ++ * destination=address:port ++ */ ++ psep = memchr(ptran+off, ':', nextfieldoff-off); ++ if (psep != NULL && nf_strtou16(psep + 1, &port)) { ++ if (prtspexp->loport != 0 && prtspexp->loport != port) ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ else { ++ pr_debug("lo port found : %hu\n", port); ++ prtspexp->loport = prtspexp->hiport = port; ++ } ++ } ++ } ++ } ++ ++ /* ++ * Note we don't look for the destination parameter here. ++ * If we are using NAT, the NAT module will handle it. If not, ++ * and the client is sending packets elsewhere, the expectation ++ * will quietly time out. ++ */ ++ ++ off = nextfieldoff; ++ } ++ ++ off = nextparamoff; ++ } ++ ++ return rc; ++} ++ ++ ++/*** conntrack functions ***/ ++ ++/* outbound packet: client->server */ ++ ++static inline int ++help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo, ++ unsigned int protoff) ++#else ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++#endif ++{ ++ struct ip_ct_rtsp_expect expinfo; ++ ++ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ ++ //struct tcphdr* tcph = (void*)iph + iph->ihl * 4; ++ //uint tcplen = pktlen - iph->ihl * 4; ++ char* pdata = rb_ptr; ++ //uint datalen = tcplen - tcph->doff * 4; ++ uint dataoff = 0; ++ int ret = NF_ACCEPT; ++ ++ struct nf_conntrack_expect *rtp_exp; ++ struct nf_conntrack_expect *rtcp_exp = NULL; ++ ++ __be16 be_loport; ++ __be16 be_hiport; ++ ++ typeof(nf_nat_rtsp_hook) nf_nat_rtsp; ++ ++ memset(&expinfo, 0, sizeof(expinfo)); ++ ++ while (dataoff < datalen) { ++ uint cmdoff = dataoff; ++ uint hdrsoff = 0; ++ uint hdrslen = 0; ++ uint cseqoff = 0; ++ uint cseqlen = 0; ++ uint transoff = 0; ++ uint translen = 0; ++ uint off; ++ union nf_inet_addr srvaddr; ++ ++ if (!rtsp_parse_message(pdata, datalen, &dataoff, ++ &hdrsoff, &hdrslen, ++ &cseqoff, &cseqlen, ++ &transoff, &translen)) ++ break; /* not a valid message */ ++ ++ if (strncmp(pdata+cmdoff, "TEARDOWN ", 9) == 0) { ++ pr_debug("teardown handled\n"); ++ nf_ct_remove_expectations(ct); /* FIXME must be session id aware */ ++ break; ++ } ++ ++ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) ++ continue; /* not a SETUP message */ ++ ++ srvaddr = ct->tuplehash[!dir].tuple.src.u3; ++ ++ /* try to get RTP media source from SETUP URI */ ++ off = cmdoff + 6; ++ while (off < datalen) { ++ if (strncmp(pdata+off, "://", 3) == 0) { ++ off += 3; ++ cmdoff = off; ++ ++ while (off < datalen) { ++ if (pdata[off] == ':' || ++ pdata[off] == '/' || ++ pdata[off] == ' ') { ++ in4_pton(pdata + cmdoff, ++ off - cmdoff, ++ (u8 *)&srvaddr.in, ++ -1, NULL); ++ break; ++ } ++ off++; ++ } ++ break; ++ } ++ off++; ++ } ++ ++ pr_debug("found a setup message\n"); ++ ++ off = 0; ++ if(translen) ++ rtsp_parse_transport(pdata+transoff, translen, &expinfo); ++ ++ if (expinfo.loport == 0) { ++ pr_debug("no udp transports found\n"); ++ continue; /* no udp transports found */ ++ } ++ ++ pr_debug("udp transport found, ports=(%d,%hu,%hu)\n", ++ (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); ++ ++ ++ be_loport = htons(expinfo.loport); ++ ++ rtp_exp = nf_ct_expect_alloc(ct); ++ if (rtp_exp == NULL) { ++ ret = NF_DROP; ++ goto out; ++ } ++ ++ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, ++ nf_ct_l3num(ct), NULL, ++ &ct->tuplehash[!dir].tuple.dst.u3, ++ IPPROTO_UDP, NULL, &be_loport); ++ ++ rtp_exp->flags = 0; ++ ++ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { ++ pr_debug("setup expectation for rtcp\n"); ++ ++ be_hiport = htons(expinfo.hiport); ++ rtcp_exp = nf_ct_expect_alloc(ct); ++ if (rtcp_exp == NULL) { ++ ret = NF_DROP; ++ goto out1; ++ } ++ ++ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, ++ nf_ct_l3num(ct), NULL, ++ &ct->tuplehash[!dir].tuple.dst.u3, ++ IPPROTO_UDP, NULL, &be_hiport); ++ ++ rtcp_exp->flags = 0; ++ ++ pr_debug("expect_related %pI4:%u-%u-%pI4:%u-%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ ntohs(rtcp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port), ++ ntohs(rtcp_exp->tuple.dst.u.udp.port)); ++ } else { ++ pr_debug("expect_related %pI4:%u-%pI4:%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port)); ++ } ++ ++ nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook); ++ if (nf_nat_rtsp && ct->status & IPS_NAT_MASK) ++ /* pass the request off to the nat helper */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen, ++ &expinfo, rtp_exp, rtcp_exp); ++#else ++ ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, ++ &expinfo, rtp_exp, rtcp_exp); ++#endif ++ else { ++ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { ++ if (rtcp_exp && rtsp_nf_ct_expect_related(rtcp_exp) != 0) { ++ nf_ct_unexpect_related(rtp_exp); ++ pr_info("nf_conntrack_expect_related failed for rtcp\n"); ++ ret = NF_DROP; ++ } ++ } else { ++ pr_info("nf_conntrack_expect_related failed for rtp\n"); ++ ret = NF_DROP; ++ } ++ } ++ if (rtcp_exp) { ++ nf_ct_expect_put(rtcp_exp); ++ } ++out1: ++ nf_ct_expect_put(rtp_exp); ++ goto out; ++ } ++out: ++ ++ return ret; ++} ++ ++ ++static inline int ++help_in(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo, ++ unsigned int protoff) ++#else ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++#endif ++ { ++ struct ip_ct_rtsp_expect expinfo; ++ union nf_inet_addr srvaddr; ++ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ ++ int len; ++ char* pdata = rb_ptr; ++ uint dataoff = 0; ++ int ret = NF_ACCEPT; ++ u_int8_t family; ++ struct nf_conntrack_expect *exp_ct = NULL; ++ struct nf_conntrack_tuple t; ++ struct net *net = nf_ct_net(ct); ++ ++ memset(&expinfo, 0, sizeof(expinfo)); ++ ++ while (dataoff < datalen) { ++ uint cmdoff = dataoff; ++ uint hdrsoff = 0; ++ uint hdrslen = 0; ++ uint cseqoff = 0; ++ uint cseqlen = 0; ++ uint transoff = 0; ++ uint translen = 0; ++ ++ if (!rtsp_parse_message(pdata, datalen, &dataoff, ++ &hdrsoff, &hdrslen, ++ &cseqoff, &cseqlen, ++ &transoff, &translen)) ++ break; /* not a valid message */ ++ ++ if (strncmp(pdata+cmdoff, "RTSP/", 5) == 0 && translen) { ++ union nf_inet_addr zeroaddr; ++ ++ memset(&zeroaddr, 0, sizeof(zeroaddr)); ++ ++ if (!rtsp_parse_transport(pdata+transoff, translen, &expinfo)) ++ continue; ++ ++ srvaddr = expinfo.srvaddr; ++ ++ if (nf_inet_addr_cmp(&srvaddr, &ct->tuplehash[dir].tuple.src.u3) || ++ nf_inet_addr_cmp(&srvaddr, &zeroaddr)) ++ continue; ++ } else ++ continue; /* not valid RTSP reply */ ++ ++ if (expinfo.loport == 0) { ++ pr_debug("no udp transports found\n"); ++ continue; /* no udp transports found */ ++ } ++ ++ family = nf_ct_l3num(ct); ++ if (family == AF_INET) ++ len = 4; ++ else ++ len = 16; ++ ++ /* replace rtp expect src addr */ ++ t.src.l3num = family; ++ t.dst.protonum = IPPROTO_UDP; ++ ++ memcpy(&t.src.u3, &ct->tuplehash[dir].tuple.src.u3, len); ++ if (sizeof(t.src.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&t.src.u3 + len, 0, sizeof(t.src.u3) - len); ++ ++ t.src.u.all = 0; ++ ++ memcpy(&t.dst.u3, &ct->tuplehash[dir].tuple.dst.u3, len); ++ if (sizeof(t.dst.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&t.dst.u3 + len, 0, sizeof(t.dst.u3) - len); ++ ++ t.dst.u.all = htons(expinfo.loport); ++ ++ /* get the rtp expect and replace the srcaddr with RTP server addr */ ++ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); ++ if (exp_ct) { ++ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); ++ if (sizeof(exp_ct->tuple.src.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&exp_ct->tuple.src.u3 + len, 0, ++ sizeof(exp_ct->tuple.src.u3) - len); ++ } else ++ goto out; ++ ++ /* replace rtcp expect src addr */ ++ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { ++ t.dst.u.all = htons(expinfo.hiport); ++ ++ /* get the rtcp expect and replace the srcaddr with RTP server addr */ ++ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); ++ if (exp_ct) { ++ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); ++ if (sizeof(exp_ct->tuple.src.u3) > len) ++ /* address needs to be cleared for nf_ct_tuple_equal */ ++ memset((void *)&exp_ct->tuple.src.u3 + len, 0, ++ sizeof(exp_ct->tuple.src.u3) - len); ++ } else ++ goto out; ++ } ++ ++ goto out; ++ } ++out: ++ return ret; ++ } ++ ++static int help(struct sk_buff *skb, unsigned int protoff, ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++{ ++ struct tcphdr _tcph, *th; ++ unsigned int dataoff, datalen; ++ char *rb_ptr; ++ int ret = NF_DROP; ++ ++ /* Until there's been traffic both ways, don't look in packets. */ ++ if (ctinfo != IP_CT_ESTABLISHED && ++ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { ++ pr_debug("conntrackinfo = %u\n", ctinfo); ++ return NF_ACCEPT; ++ } ++ ++ /* Not whole TCP header? */ ++ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); ++ ++ if (!th) ++ return NF_ACCEPT; ++ ++ /* No data ? */ ++ dataoff = protoff + th->doff*4; ++ datalen = skb->len - dataoff; ++ if (dataoff >= skb->len) ++ return NF_ACCEPT; ++ ++ spin_lock_bh(&rtsp_buffer_lock); ++ rb_ptr = skb_header_pointer(skb, dataoff, ++ skb->len - dataoff, rtsp_buffer); ++ BUG_ON(rb_ptr == NULL); ++ ++#if 0 ++ /* Checksum invalid? Ignore. */ ++ /* FIXME: Source route IP option packets --RR */ ++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, ++ csum_partial((char*)tcph, tcplen, 0))) ++ { ++ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", ++ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); ++ return NF_ACCEPT; ++ } ++#endif ++ ++ switch (CTINFO2DIR(ctinfo)) { ++ case IP_CT_DIR_ORIGINAL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff); ++#else ++ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo); ++#endif ++ break; ++ case IP_CT_DIR_REPLY: ++ pr_debug("IP_CT_DIR_REPLY\n"); ++ /* inbound packet: server->client */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo, protoff); ++#else ++ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo); ++#endif ++ break; ++ default: ++ break; ++ } ++ ++ spin_unlock_bh(&rtsp_buffer_lock); ++ ++ return ret; ++} ++ ++static struct nf_conntrack_helper rtsp_helpers[MAX_PORTS]; ++static char rtsp_names[MAX_PORTS][10]; ++ ++/* This function is intentionally _NOT_ defined as __exit */ ++static void ++fini(void) ++{ ++ int i; ++ for (i = 0; i < num_ports; i++) { ++ pr_debug("unregistering port %d\n", ports[i]); ++ nf_conntrack_helper_unregister(&rtsp_helpers[i]); ++ } ++ kfree(rtsp_buffer); ++} ++ ++static int __init ++init(void) ++{ ++ int i, ret; ++ struct nf_conntrack_helper *hlpr; ++ char *tmpname; ++ ++ printk("nf_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); ++ ++ if (max_outstanding < 1) { ++ printk("nf_conntrack_rtsp: max_outstanding must be a positive integer\n"); ++ return -EBUSY; ++ } ++ ++ rtsp_exp_policy.max_expected = max_outstanding; ++ rtsp_exp_policy.timeout = setup_timeout; ++ ++ rtsp_buffer = kmalloc(65536, GFP_KERNEL); ++ if (!rtsp_buffer) ++ return -ENOMEM; ++ ++ /* If no port given, default to standard rtsp port */ ++ if (ports[0] == 0) { ++ ports[0] = RTSP_PORT; ++ num_ports = 1; ++ } ++ ++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { ++ hlpr = &rtsp_helpers[i]; ++ memset(hlpr, 0, sizeof(struct nf_conntrack_helper)); ++ hlpr->tuple.src.l3num = AF_INET; ++ hlpr->tuple.src.u.tcp.port = htons(ports[i]); ++ hlpr->tuple.dst.protonum = IPPROTO_TCP; ++ hlpr->expect_policy = &rtsp_exp_policy; ++ hlpr->me = THIS_MODULE; ++ hlpr->help = help; ++ ++ tmpname = &rtsp_names[i][0]; ++ if (ports[i] == RTSP_PORT) { ++ sprintf(tmpname, "rtsp"); ++ } else { ++ sprintf(tmpname, "rtsp-%d", i); ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ strlcpy(hlpr->name, tmpname, sizeof(hlpr->name)); ++#else ++ hlpr->name = tmpname; ++#endif ++ pr_debug("port #%d: %d\n", i, ports[i]); ++ ++ ret = nf_conntrack_helper_register(hlpr); ++ ++ if (ret) { ++ printk("nf_conntrack_rtsp: ERROR registering port %d\n", ports[i]); ++ fini(); ++ return -EBUSY; ++ } ++ } ++ return 0; ++} ++ ++module_init(init); ++module_exit(fini); +--- /dev/null ++++ b/extensions/rtsp/nf_conntrack_rtsp.h +@@ -0,0 +1,74 @@ ++/* ++ * RTSP extension for IP connection tracking. ++ * (C) 2003 by Tom Marshall ++ * based on ip_conntrack_irc.h ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd ++ * - conditional compilation for kernel 3.7 ++ * - port mapping improvements ++*/ ++#ifndef _IP_CONNTRACK_RTSP_H ++#define _IP_CONNTRACK_RTSP_H ++ ++#include ++ ++//#define IP_NF_RTSP_DEBUG 1 ++#define IP_NF_RTSP_VERSION "0.7" ++ ++#ifdef __KERNEL__ ++/* port block types */ ++typedef enum { ++ pb_single, /* client_port=x */ ++ pb_range, /* client_port=x-y */ ++ pb_discon /* client_port=x/y (rtspbis) */ ++} portblock_t; ++ ++/* We record seq number and length of rtsp headers here, all in host order. */ ++ ++/* ++ * This structure is per expected connection. It is a member of struct ++ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored ++ * there and we are expected to only store the length of the data which ++ * needs replaced. If a packet contains multiple RTSP messages, we create ++ * one expected connection per message. ++ * ++ * We use these variables to mark the entire header block. This may seem ++ * like overkill, but the nature of RTSP requires it. A header may appear ++ * multiple times in a message. We must treat two Transport headers the ++ * same as one Transport header with two entries. ++ */ ++struct ip_ct_rtsp_expect ++{ ++ u_int32_t len; /* length of header block */ ++ portblock_t pbtype; /* Type of port block that was requested */ ++ u_int16_t loport; /* Port that was requested, low or first */ ++ u_int16_t hiport; /* Port that was requested, high or second */ ++ union nf_inet_addr srvaddr; /* src address in SETUP reply */ ++ union nf_inet_addr cltaddr; /* destination address */ ++#if 0 ++ uint method; /* RTSP method */ ++ uint cseq; /* CSeq from request */ ++#endif ++}; ++ ++extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, ++ enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, ++ unsigned int matchlen, ++ struct ip_ct_rtsp_expect *prtspexp, ++ struct nf_conntrack_expect *rtp_exp, ++ struct nf_conntrack_expect *rtcp_exp); ++ ++#define RTSP_PORT 554 ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _IP_CONNTRACK_RTSP_H */ +--- /dev/null ++++ b/extensions/rtsp/nf_nat_rtsp.c +@@ -0,0 +1,640 @@ ++/* ++ * RTSP extension for TCP NAT alteration ++ * (C) 2003 by Tom Marshall ++ * ++ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd ++ * - fixed rtcp nat mapping and other port mapping fixes ++ * - fixed system hard lock because of bug in the parser ++ * - codestyle fixes and less significant fixes ++ * ++ * based on ip_nat_irc.c ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Module load syntax: ++ * insmod nf_nat_rtsp.o ports=port1,port2,...port ++ * stunaddr=
    ++ * destaction=[auto|strip|none] ++ * ++ * If no ports are specified, the default will be port 554 only. ++ * ++ * stunaddr specifies the address used to detect that a client is using STUN. ++ * If this address is seen in the destination parameter, it is assumed that ++ * the client has already punched a UDP hole in the firewall, so we don't ++ * mangle the client_port. If none is specified, it is autodetected. It ++ * only needs to be set if you have multiple levels of NAT. It should be ++ * set to the external address that the STUN clients detect. Note that in ++ * this case, it will not be possible for clients to use UDP with servers ++ * between the NATs. ++ * ++ * If no destaction is specified, auto is used. ++ * destaction=auto: strip destination parameter if it is not stunaddr. ++ * destaction=strip: always strip destination parameter (not recommended). ++ * destaction=none: do not touch destination parameter (not recommended). ++ */ ++ ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++# include ++#else ++# include ++#endif ++#include ++#include "nf_conntrack_rtsp.h" ++ ++#include ++#include ++#define NF_NEED_STRNCASECMP ++#define NF_NEED_STRTOU16 ++#include "netfilter_helpers.h" ++#define NF_NEED_MIME_NEXTLINE ++#include "netfilter_mime.h" ++ ++#define MAX_PORTS 8 ++#define DSTACT_AUTO 0 ++#define DSTACT_STRIP 1 ++#define DSTACT_NONE 2 ++ ++static char* stunaddr = NULL; ++static char* destaction = NULL; ++ ++static u_int32_t extip = 0; ++static int dstact = 0; ++ ++static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp); ++ ++MODULE_AUTHOR("Tom Marshall "); ++MODULE_DESCRIPTION("RTSP network address translation module"); ++MODULE_LICENSE("GPL"); ++module_param(stunaddr, charp, 0644); ++MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); ++module_param(destaction, charp, 0644); ++MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); ++ ++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } ++ ++/*** helper functions ***/ ++ ++static void ++get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) ++{ ++ struct iphdr* iph = ip_hdr(skb); ++ struct tcphdr* tcph = (void *)iph + ip_hdrlen(skb); ++ ++ *pptcpdata = (char*)tcph + tcph->doff*4; ++ *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++/* copy of sip_sprintf_addr */ ++static int rtsp_sprintf_addr(const struct nf_conn *ct, char *buffer, ++ const union nf_inet_addr *addr, bool delim) ++{ ++ if (nf_ct_l3num(ct) == NFPROTO_IPV4) { ++ return sprintf(buffer, "%pI4", &addr->ip); ++ } else { ++ if (delim) ++ return sprintf(buffer, "[%pI6c]", &addr->ip6); ++ else ++ return sprintf(buffer, "%pI6c", &addr->ip6); ++ } ++} ++#endif ++ ++/*** nat functions ***/ ++ ++/* ++ * Mangle the "Transport:" header: ++ * - Replace all occurences of "client_port=" ++ * - Handle destination parameter ++ * ++ * In: ++ * ct, ctinfo = conntrack context ++ * skb = packet ++ * tranoff = Transport header offset from TCP data ++ * tranlen = Transport header length (incl. CRLF) ++ * rport_lo = replacement low port (host endian) ++ * rport_hi = replacement high port (host endian) ++ * ++ * Returns packet size difference. ++ * ++ * Assumes that a complete transport header is present, ending with CR or LF ++ */ ++static int ++rtsp_mangle_tran(enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct sk_buff* skb, uint tranoff, uint tranlen) ++{ ++ char* ptcp; ++ uint tcplen; ++ char* ptran; ++ char rbuf1[16]; /* Replacement buffer (one port) */ ++ uint rbuf1len; /* Replacement len (one port) */ ++ char rbufa[16]; /* Replacement buffer (all ports) */ ++ uint rbufalen; /* Replacement len (all ports) */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ union nf_inet_addr newip; ++#else ++ u_int32_t newip; ++#endif ++ u_int16_t loport, hiport; ++ uint off = 0; ++ uint diff; /* Number of bytes we removed */ ++ ++ struct nf_conn *ct = rtp_exp->master; ++ /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */ ++ struct nf_conntrack_tuple *rtp_t; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ char szextaddr[INET6_ADDRSTRLEN + 16]; ++#else ++ char szextaddr[INET_ADDRSTRLEN + 16]; ++#endif ++ uint extaddrlen; ++ int is_stun; ++ ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ ++ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || ++ tranlen < 10 || !iseol(ptran[tranlen-1]) || ++ nf_strncasecmp(ptran, "Transport:", 10) != 0) { ++ pr_info("sanity check failed\n"); ++ return 0; ++ } ++ off += 10; ++ SKIP_WSPACE(ptcp+tranoff, tranlen, off); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3; ++ rtp_t = &rtp_exp->tuple; ++ rtp_t->dst.u3 = newip; ++ if (rtcp_exp) { ++ rtcp_exp->tuple.dst.u3 = newip; ++ } ++ extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip ++ pr_debug("stunaddr=%s (auto)\n", szextaddr); ++#else ++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; ++ rtp_t = &rtp_exp->tuple; ++ rtp_t->dst.u3.ip = newip; ++ if (rtcp_exp) { ++ rtcp_exp->tuple.dst.u3.ip = newip; ++ } ++ extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) ++ : sprintf(szextaddr, "%pI4", &newip); ++ pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); ++#endif ++ hiport = 0; ++ rbuf1len = rbufalen = 0; ++ switch (prtspexp->pbtype) { ++ case pb_single: ++ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { ++ pr_debug("using port %hu\n", loport); ++ break; ++ } ++ } ++ if (loport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, "%hu", loport); ++ } ++ break; ++ case pb_range: ++ for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (rtsp_nf_ct_expect_related(rtp_exp) != 0) { ++ continue; ++ } ++ hiport = loport + 1; ++ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); ++ if (rtsp_nf_ct_expect_related(rtcp_exp) != 0) { ++ nf_ct_unexpect_related(rtp_exp); ++ continue; ++ } ++ ++ /* FIXME: invalid print in case of ipv6 */ ++ pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ ntohs(rtcp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port), ++ ntohs(rtcp_exp->tuple.dst.u.udp.port)); ++ break; ++ } ++ if (loport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); ++ } ++ break; ++ case pb_discon: ++ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { ++ pr_debug("using port %hu (1 of 2)\n", loport); ++ break; ++ } ++ } ++ for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */ ++ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); ++ if (rtsp_nf_ct_expect_related(rtcp_exp) == 0) { ++ pr_debug("using port %hu (2 of 2)\n", hiport); ++ break; ++ } ++ } ++ if (loport != 0 && hiport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, hiport == loport+1 ? ++ "%hu-%hu":"%hu/%hu", loport, hiport); ++ } else { ++ if (loport != 0) ++ nf_ct_unexpect_related(rtp_exp); ++ if (hiport != 0) ++ nf_ct_unexpect_related(rtcp_exp); ++ } ++ break; ++ } ++ ++ if (rbuf1len == 0) ++ return 0; /* cannot get replacement port(s) */ ++ ++ /* Transport: tran;field;field=val,tran;field;field=val,... ++ `off` is set to the start of Transport value from start of line ++ */ ++ while (off < tranlen) { ++ uint saveoff; ++ const char* pparamend; ++ uint nextparamoff; ++ ++ pparamend = memchr(ptran+off, ',', tranlen-off); ++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; ++ nextparamoff = pparamend-ptran; ++ ++ /* ++ * We pass over each param twice. On the first pass, we look for a ++ * destination= field. It is handled by the security policy. If it ++ * is present, allowed, and equal to our external address, we assume ++ * that STUN is being used and we leave the client_port= field alone. ++ */ ++ is_stun = 0; ++ saveoff = off; ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ SKIP_WSPACE(ptran, nextfieldoff, off); ++ ++ if (dstact != DSTACT_NONE && nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { ++ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) ++ is_stun = 1; ++ ++ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { ++ uint dstoff = (ptran-ptcp)+off; ++ uint dstlen = nextfieldoff-off; ++ char* pdstrep = NULL; ++ uint dstreplen = 0; ++ diff = dstlen; ++ if (dstact == DSTACT_AUTO && !is_stun) { ++ const char* psep = memchr(ptran+off, ':', dstlen); ++ u_int16_t port; ++ ++ dstoff += 12; ++ dstlen -= 13; ++ pdstrep = szextaddr; ++ ++ if (psep != NULL && nf_strtou16(psep + 1, &port)) { ++ pr_debug("RTSP: replace dst addr&port\n"); ++ ++ if (port != prtspexp->loport) { ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ dstreplen = extaddrlen; ++ } else { ++ sprintf(szextaddr+extaddrlen, ":%s", rbuf1); ++ dstreplen = extaddrlen+1+rbuf1len; ++ } ++ } else { ++ pr_debug("RTSP: replace dst addr\n"); ++ dstreplen = extaddrlen; ++ } ++ diff = nextfieldoff-off-13-dstreplen; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, ++ dstoff, dstlen, pdstrep, dstreplen)) { ++#else ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, ++ dstoff, dstlen, pdstrep, dstreplen)) { ++#endif ++ /* mangle failed, all we can do is bail */ ++ nf_ct_unexpect_related(rtp_exp); ++ if (rtcp_exp) ++ nf_ct_unexpect_related(rtcp_exp); ++ return 0; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ tranlen -= diff; ++ nextparamoff -= diff; ++ nextfieldoff -= diff; ++ } ++ } ++ ++ off = nextfieldoff; ++ } ++ ++ if (is_stun) ++ continue; ++ ++ off = saveoff; ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ ++ if (nextfieldoff - off > 12 && strncmp(ptran+off, "client_port=", 12) == 0) { ++ u_int16_t port; ++ uint numlen; ++ uint origoff; ++ uint origlen; ++ char* rbuf = rbuf1; ++ uint rbuflen = rbuf1len; ++ ++ off += 12; ++ origoff = (ptran-ptcp)+off; ++ origlen = 0; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ origlen += numlen; ++ if (port != prtspexp->loport) { ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ } else { ++ if (ptran[off] == '-' || ptran[off] == '/') { ++ off++; ++ origlen++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ origlen += numlen; ++ rbuf = rbufa; ++ rbuflen = rbufalen; ++ } ++ ++ /* ++ * note we cannot just memcpy() if the sizes are the same. ++ * the mangle function does skb resizing, checks for a ++ * cloned skb, and updates the checksums. ++ * ++ * parameter 4 below is offset from start of tcp data. ++ */ ++ diff = origlen-rbuflen; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, ++ origoff, origlen, rbuf, rbuflen)) { ++#else ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, ++ origoff, origlen, rbuf, rbuflen)) { ++#endif ++ /* mangle failed, all we can do is bail */ ++ nf_ct_unexpect_related(rtp_exp); ++ if (rtcp_exp) ++ nf_ct_unexpect_related(rtcp_exp); ++ return 0; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ tranlen -= diff; ++ nextparamoff -= diff; ++ nextfieldoff -= diff; ++ } ++ } ++ ++ off = nextfieldoff; ++ } ++ ++ off = nextparamoff; ++ } ++ ++ return 1; ++} ++ ++static uint ++help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp) ++{ ++ char* ptcp; ++ uint tcplen; ++ uint hdrsoff; ++ uint hdrslen; ++ uint lineoff; ++ uint linelen; ++ uint off; ++ int dir = CTINFO2DIR(ctinfo); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3; ++#else ++ __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip; ++#endif ++ ++ //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; ++ //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); ++ ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); ++ hdrslen = matchlen; ++ off = hdrsoff; ++ pr_debug("NAT rtsp help_out\n"); ++ ++ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) { ++ if (linelen == 0) ++ break; ++ ++ if (off > hdrsoff+hdrslen) { ++ pr_info("!! overrun !!"); ++ break; ++ } ++ pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { ++ uint oldtcplen = tcplen; ++ pr_debug("hdr: Transport\n"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp, ++ prtspexp, skb, lineoff, linelen)) { ++#else ++ if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp, ++ skb, lineoff, linelen)) { ++#endif ++ pr_debug("hdr: Transport mangle failed"); ++ break; ++ } ++ rtp_exp->expectfn = nf_nat_rtsp_expected; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rtp_exp->saved_addr = saddr; ++#else ++ rtp_exp->saved_ip = saddr; ++#endif ++ rtp_exp->saved_proto.udp.port = htons(prtspexp->loport); ++ rtp_exp->dir = !dir; ++ if (rtcp_exp) { ++ rtcp_exp->expectfn = nf_nat_rtsp_expected; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rtcp_exp->saved_addr = saddr; ++#else ++ rtcp_exp->saved_ip = saddr; ++#endif ++ rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport); ++ rtcp_exp->dir = !dir; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ hdrslen -= (oldtcplen-tcplen); ++ off -= (oldtcplen-tcplen); ++ lineoff -= (oldtcplen-tcplen); ++ linelen -= (oldtcplen-tcplen); ++ pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); ++ } ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static unsigned int ++nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp) ++{ ++ int dir = CTINFO2DIR(ctinfo); ++ int rc = NF_ACCEPT; ++ ++ switch (dir) { ++ case IP_CT_DIR_ORIGINAL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, ++ rtp_exp, rtcp_exp); ++#else ++ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, ++ rtp_exp, rtcp_exp); ++#endif ++ break; ++ case IP_CT_DIR_REPLY: ++ pr_debug("unmangle ! %u\n", ctinfo); ++ /* XXX: unmangle */ ++ rc = NF_ACCEPT; ++ break; ++ } ++ //UNLOCK_BH(&ip_rtsp_lock); ++ ++ return rc; ++} ++ ++static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0) ++ struct nf_nat_range2 range; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_nat_range range; ++#else ++ struct nf_nat_ipv4_range range; ++#endif ++ ++ /* This must be a fresh one. */ ++ BUG_ON(ct->status & IPS_NAT_DONE_MASK); ++ ++ /* For DST manip, map port here to where it's expected. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ range.min_proto = range.max_proto = exp->saved_proto; ++ range.min_addr = range.max_addr = exp->saved_addr; ++#else ++ range.min = range.max = exp->saved_proto; ++ range.min_ip = range.max_ip = exp->saved_ip; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); ++ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); ++#else ++ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); ++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); ++#endif ++ ++ /* Change src to where master sends to, but only if the connection ++ * actually came from the same source. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, ++ &ct->master->tuplehash[exp->dir].tuple.src.u3)) { ++ range.min_addr = range.max_addr ++ = ct->master->tuplehash[!exp->dir].tuple.dst.u3; ++#else ++ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == ++ ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { ++ range.min_ip = range.max_ip ++ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ range.flags = NF_NAT_RANGE_MAP_IPS; ++ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); ++#else ++ range.flags = IP_NAT_RANGE_MAP_IPS; ++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); ++#endif ++ } ++} ++ ++ ++static void __exit fini(void) ++{ ++ rcu_assign_pointer(nf_nat_rtsp_hook, NULL); ++ synchronize_net(); ++} ++ ++static int __init init(void) ++{ ++ printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); ++ ++ BUG_ON(nf_nat_rtsp_hook); ++ rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp); ++ ++ if (stunaddr != NULL) ++ extip = in_aton(stunaddr); ++ ++ if (destaction != NULL) { ++ if (strcmp(destaction, "auto") == 0) ++ dstact = DSTACT_AUTO; ++ ++ if (strcmp(destaction, "strip") == 0) ++ dstact = DSTACT_STRIP; ++ ++ if (strcmp(destaction, "none") == 0) ++ dstact = DSTACT_NONE; ++ } ++ ++ return 0; ++} ++ ++module_init(init); ++module_exit(fini); +--- a/extensions/Kbuild ++++ b/extensions/Kbuild +@@ -28,6 +28,7 @@ obj-${build_lscan} += xt_lscan.o + obj-${build_pknock} += pknock/ + obj-${build_psd} += xt_psd.o + obj-${build_quota2} += xt_quota2.o ++obj-${build_rtsp} += rtsp/ + + -include ${M}/*.Kbuild + -include ${M}/Kbuild.* +--- a/mconfig ++++ b/mconfig +@@ -24,3 +24,4 @@ build_lscan=m + build_pknock=m + build_psd=m + build_quota2=m ++build_rtsp=m diff --git a/xtables-addons/patches/200-add-lua-packetscript.patch b/xtables-addons/patches/200-add-lua-packetscript.patch new file mode 100644 index 000000000..2a97f54d7 --- /dev/null +++ b/xtables-addons/patches/200-add-lua-packetscript.patch @@ -0,0 +1,18168 @@ +--- /dev/null ++++ b/extensions/LUA/byte_array.c +@@ -0,0 +1,161 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++#include "controller.h" ++ ++/* Initialization helper function. This function should be used whenever ++ * a new byte array need to be initialized. Depending on the arguments it ++ * initializes the array in a different way. Have a look at the inline ++ * comments */ ++lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy) ++{ ++ lua_packet_segment *array; ++ ++ if (length < 0) ++ luaL_error(L, "init_byte_array, requested size < 0"); ++ ++ if (start && do_copy) { ++ /* we have a start address where we copy from */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); ++ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ ++ memcpy(array->start, start, length); ++ }else if (start && !do_copy) { ++ /* just link the start pointer, in this case you have to free the memory yourself */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment)); ++ array->start = start; ++ }else{ ++ /* create an empty array, fully managed by Lua */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); ++ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ ++ memset(array->start, 0, length); ++ } ++ ++ array->length = length; ++ array->offset = 0; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ ++ return array; ++} ++ ++ ++ ++/* LUA_API: get one byte of the given byte array ++ * access-pattern: array[] */ ++static int32_t get_byte_array(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ ++ ++ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); ++ lua_pushinteger(L, (array->start + array->offset)[index]); ++ ++ return 1; ++} ++ ++/* LUA_API: set one byte of the given byte array ++ * access-pattern: array[]= 0xFF */ ++static int32_t set_byte_array(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ uint8_t byte; ++ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ ++ int32_t val = luaL_checkinteger(L, 3); ++ uint32_t nob = 1 << CHAR_BIT; /* we should use something like 1 << CHAR_BIT */ ++ ++ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); ++ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); ++ ++ byte = (uint8_t)val; ++ ++ (array->start + array->offset)[index] = byte; ++ ++ return 0; ++} ++ ++/* LUA_API: get size of the given byte array ++ * access-pattern: #array (__length meta-method) */ ++static int32_t get_byte_array_size(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ ++ lua_pushnumber(L, array->length); ++ ++ return 1; ++} ++ ++ ++/* LUA_API: converts a given byte array to a string. ++ * access-pattern: implicit through functions calling the ++ * __to_string() metamethod , e.g. print32_t */ ++static int32_t byte_array_to_string(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ uint8_t hexval[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; ++ uint8_t * buf; ++ char * res; ++ int32_t i, n; ++ uint8_t *ptr = array->start + array->offset; ++ ++ buf = kcalloc((array->length * 3) + 255, sizeof(*buf), GFP_KERNEL); ++ ++ if (!buf) { ++ return luaL_error(L, "byte_array_to_string, failed alloc buf buffer"); ++ } ++ ++ /* make sure the buffer is big enough*/ ++ res = kcalloc((array->length * 3) + 255, sizeof(*res), GFP_KERNEL); ++ ++ if (!res) { ++ kfree(buf); ++ return luaL_error(L, "byte_array_to_string, failed alloc res buffer"); ++ } ++ ++ for (i = 0; i < array->length; i++) { ++ buf[i * 3] = hexval[(ptr[i] >> 4) & 0xF]; ++ buf[(i * 3) + 1] = hexval[ptr[i] & 0x0F]; ++ buf[(i * 3) + 2] = ' '; /* seperator */ ++ } ++ ++ buf[array->length * 3] = '\0'; ++ n = sprintf(res, "byte_array: length: %d value: %s", array->length, buf); ++ ++ lua_pushlstring(L, res, n); ++ kfree(res); ++ kfree(buf); ++ ++ return 1; ++} ++ ++static const struct luaL_Reg bytearray_lib_m [] = { ++ { "__len", get_byte_array_size }, ++ { "__newindex", set_byte_array }, ++ { "__index", get_byte_array }, ++ { "__tostring", byte_array_to_string }, ++ { NULL, NULL } ++}; ++ ++void luaopen_bytearraylib(lua_State *L) ++{ ++ luaL_newmetatable(L, LUA_BYTE_ARRAY); ++ luaL_register(L, NULL, bytearray_lib_m); ++ lua_pop(L, 1); ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/controller.c +@@ -0,0 +1,604 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++#endif ++#include "controller.h" ++ ++/* the array 'supported_protocols' holds all pointers to the ++ * static and dynamic protocol buffers. It is filled by the ++ * call to register_protbuf */ ++static struct protocol_buf * supported_protocols[MAX_NR_OF_PROTOCOLS]; ++ ++/* C_API: the function 'get_protocol_buf' returns the pointer ++ * to the protocol buffer of a given protocol id. */ ++struct protocol_buf * get_protocol_buf(uint32_t protocol_id) ++{ ++ return (struct protocol_buf *)supported_protocols[protocol_id]; ++} ++ ++ ++/* LUA_INT: the function 'gc_packet_segment' is triggered by the ++ * garbage collector whenever a userdata annotated with one of ++ * the protocol buffer metatable should be collected. */ ++static int32_t gc_packet_segment(lua_State *L) ++{ ++ lua_packet_segment * seg = (lua_packet_segment *)lua_touserdata(L, 1); ++ if (seg && seg->changes) { ++ seg->changes->ref_count--; ++ if (seg->changes->ref_count <= 0) { ++ kfree(seg->changes->field_length_changes); ++ kfree(seg->changes->field_offset_changes); ++ kfree(seg->changes); ++ seg->changes = NULL; ++ } ++ } ++ return 0; ++} ++ ++ ++/* LUA_API: the function 'set_raw' is used to set the bytes of a segment ++ * in 'raw' mode. The function is per default available in each protocol ++ * buffer until it gets overridden by a specific setter function inside ++ * a protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * 2. int32_t byte_value ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: void ++ */ ++static int32_t set_raw(lua_State *L) ++{ ++ int32_t i; ++ uint32_t nob; ++ uint8_t byte; ++ uint8_t *ptr; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t val = luaL_checkinteger(L, 2); ++ ++ nob = 1 << CHAR_BIT; ++ ++ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); ++ ++ byte = (uint8_t)val; ++ ptr = seg->start + seg->offset; ++ ++ for (i = 0; i < seg->length; i++) ++ ptr[i] = byte; ++ ++ return 0; ++} ++ ++/* LUA_API: the function 'get_raw' is used to get the bytes of a segment ++ * in 'raw' mode. The function is per default available in each protocol ++ * buffer until it gets overridden by a specific getter function inside ++ * a protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * 2. uint32_t offset ++ * 3. uint32_t length ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * the byte array representing the given array ++ */ ++static int32_t get_raw(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ init_byte_array(L, seg->start + seg->offset, seg->length, 1); ++ ++ return 1; ++} ++/* LUA_API: The function 'get_segment' is used to get a new segment in 'raw' mode. ++ * Typically this function is applied on another raw segment in order ++ * to extract a part of the segment as new segment. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * 2. uint32_t offset, this indicates where to start the new segment, see e.g below. ++ * 3. uint32_t length, this indicates the size of the new segment ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. A lua_packet_segment annotated with the according metatable or False in ++ * case the input data is not valid ++ * ++ * Example: ++ * ++ * +------------------------+---------------------------------------+ ++ * | function call | resulting lua_packet_segment | ++ * +========================+===+===+===+===+===+===+===+===+===+===+ ++ * | seg = packet:raw(0,10) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ++ * +------------------------+---+---+---+---+---+---+---+---+---+---+ ++ * | 1st_half = seg:raw(0,5)| 0 | 1 | 2 | 3 | 4 | | ++ * +------------------------+---+---+---+---+---+---+---+---+---+---+ ++ * | 2nd_half = seg:raw(5,5)| | 5 | 6 | 7 | 8 | 9 | ++ * +------------------------+-------------------+---+---+---+---+---+ ++ */ ++static int32_t get_segment(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint32_t offset = luaL_checkinteger(L, 2); ++ uint32_t length = luaL_checkinteger(L, 3); ++ lua_packet_segment * new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ ++ new->start = seg->start; ++ new->offset = seg->offset + offset; ++ new->changes = NULL; ++ /* we allow a seg->length == 0 , this enables processing packets where the packetsize is not fixed (0 = not fixed)*/ ++ if (seg->length != 0 && length > seg->length) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ new->length = length; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ ++ return 1; ++} ++ ++/* LUA_API: the function 'get_segment_size' is used to get the size of a segment. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. Size as lua_Number ++ */ ++static int32_t get_segment_size(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushnumber(L, seg->length); ++ return 1; ++} ++ ++/* LUA_API: the function 'get_segment_offset' is used to get the real offset ++ * of a segment. This function returns the offset of the segment to the start ++ * of the buffer. This means the following ++ * seg1 = packet:raw(2,10) ++ * seg2 = seg1:raw(3,5) ++ * offset = seg2:get_offset() ++ * ++ * will give an offset of 5, since the seg1 starts at offset 2, and seg2 starts ++ * at offset (seg1:get_offset() + 3). ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. Offset as lua_Number ++ */ ++static int32_t get_segment_offset(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushnumber(L, seg->offset); ++ return 1; ++} ++ ++/* LUA_API: overwrites the __tostring function of a lua_packet_segment. ++ * this will print32_t a nicely formated string, including length, ++ * offset and name of the protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * ++ * Returns: ++ * 1. the representing string ++ */ ++static int32_t packet_segment_tostring(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ int32_t n; ++ char buf[128]; ++ ++ n = sprintf(buf, "type: %s, offset: %d, length: %d", prot_buf->name, seg->offset, seg->length); ++ lua_pushlstring(L, buf, n); ++ ++ return 1; ++} ++ ++ ++static const struct luaL_Reg seg_access_functions [] = { ++ { "set", set_raw }, ++ { "get", get_raw }, ++ { "raw", get_segment }, ++ { "get_offset", get_segment_offset }, ++ { "get_size", get_segment_size }, ++ { "to_bytes", get_raw }, ++ { "__tostring", packet_segment_tostring }, ++ { "__gc", gc_packet_segment }, ++ { NULL, NULL } ++}; ++ ++/* C_API: the function 'get_metatable_from_protocol_type' is a helper ++ * used in controller.c as well as it may find usage in the static ++ * protocol buffers and byte array implementation. */ ++void get_metatable_from_protocol_type(lua_State *L, int32_t type) ++{ ++ char * table; ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ lua_rawgeti(L, -1, type); ++ table = (char *)luaL_checkstring(L, -1); ++ lua_pop(L, 2); /* pop the table SUPPORTED_PROTOCOL_TABLE and the string pushed by lua_gettable */ ++ luaL_getmetatable(L, table); ++ return; ++} ++ ++/* C_INT: the function 'payload_contains_protocol' is used internally. ++ * Depending if static or dynamic protocol buffer it calls the right ++ * validation function. */ ++static int32_t payload_contains_protocol(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment *seg, uint32_t prot_type) ++{ ++ if (prot_buf->is_dynamic) ++ return has_protocol_dynamic(L, prot_buf, seg, prot_type); ++ else ++ return prot_buf->has_protocol(L, prot_buf, seg, prot_type); ++} ++ ++/* C_INT: the function 'protocol_get_field_changes' is used interally. ++ * It requests the field_changes struct calling the protocol buffers ++ * 'get_field_changes' function. This funciton is called, whenever ++ * the payload field with a given protocol type is requested inside ++ * the function 'get_protocol_field' */ ++static struct field_changes * protocol_get_field_changes(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) ++{ ++ struct field_changes * changes = NULL; ++ ++ if (prot_buf->get_field_changes) { ++ if (prot_buf->is_dynamic) ++ changes = get_field_changes_dynamic(L, prot_buf, seg); ++ else ++ changes = prot_buf->get_field_changes(L, seg); ++ /* is already 1 when set by helper 'get_allocated_field_changes, ++ * since not every prot_buf may use this function we enforce it. */ ++ changes->ref_count = 1; ++ } ++ return changes; ++} ++ ++/* C_INT: the function 'get_field_offset_in_bytes' wrapps the logic of ++ * calculating the new length with considering the optional field_changes. */ ++static int32_t get_field_offset_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) ++{ ++ uint32_t nr_of_bits, nr_of_bytes, field_offset; ++ ++ field_offset = field->offset; ++ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ ++ if (seg->changes) ++ field_offset += seg->changes->field_offset_changes[field_index]; ++ /* how many bits remain */ ++ nr_of_bits = field_offset & (CHAR_BIT - 1); ++ /* assuming CHAR_BIT == 2 ^ 3 */ ++ nr_of_bytes = (field_offset - nr_of_bits) >> 3; ++ ++ return seg->offset + nr_of_bytes; ++} ++ ++/* C_INT: the function 'get_field_length_in_bytes' wrapps the logic of ++ * calculating the new offset with considering the optional field_changes. */ ++static int32_t get_field_length_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) ++{ ++ uint32_t nr_of_bits, nr_of_bytes, field_length; ++ ++ field_length = field->length; ++ /* if the field length is smaller than 1 byte, we take the size of one byte ++ * we treat the case where field_length == 0 in a special way ...*/ ++ if (field_length < CHAR_BIT && field_length > 0) ++ field_length = CHAR_BIT; ++ ++ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ ++ if (seg->changes) ++ field_length += seg->changes->field_length_changes[field_index]; ++ /* how many bits remain */ ++ nr_of_bits = field_length & (CHAR_BIT - 1); ++ /* assuming CHAR_BIT == 2 ^ 3 */ ++ nr_of_bytes = (field_length - nr_of_bits) >> 3; ++ return nr_of_bytes; ++} ++ ++/* C_INT: the function 'initialize_field_getter_and_setter' initializes ++ * the setter and getter function of the field, considering the optional ++ * field manipulator functions defined inside the protocol buffers. */ ++static void initialize_field_getter_and_setter(lua_State *L, struct protocol_buf *prot_buf, int32_t field_index) ++{ ++ /* lets check if there is a metatable on top of the stack */ ++ struct protocol_field * f = (struct protocol_field *)&prot_buf->protocol_fields[field_index]; ++ ++ if (!lua_istable(L, -1)) luaL_error(L, "cannot initialize getter and setter for field %s->%s, " ++ "not a table on top of the stack, is '%s'", prot_buf->name, f->name, lua_typename(L, lua_type(L, -1))); ++ ++ /* is there a 'getter' to initialize ? */ ++ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ ++ lua_pushinteger(L, field_index); /* push upvalue 2 */ ++ if (f->get) { ++ if (prot_buf->is_dynamic) ++ lua_pushcclosure(L, field_dynamic_getter, 2); ++ else ++ lua_pushcclosure(L, f->get, 2); ++ }else ++ /* there is no specific getter defined - fall back to 'get_raw' */ ++ lua_pushcclosure(L, get_raw, 2); ++ /* set the metatable field 'get' */ ++ lua_setfield(L, -2, "get"); ++ ++ /* is there a 'setter' to initialize ? */ ++ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ ++ lua_pushinteger(L, field_index); /* push upvalue 2 */ ++ if (f->set) { ++ if (prot_buf->is_dynamic) ++ lua_pushcclosure(L, field_dynamic_setter, 2); ++ else ++ lua_pushcclosure(L, f->set, 2); ++ }else ++ /* there is no specific setter defined - fall back to 'set_raw' */ ++ lua_pushcclosure(L, set_raw, 2); ++ /* set the metatable field 'set' */ ++ lua_setfield(L, -2, "set"); ++} ++ ++/* LUA_API: 'get_protocol_field' is used in Lua as a closure for each field of a protocol ++ * buffer. E.g a call to ip = packet:data(packet_ip) will go to this function, ++ * and trigger the conversion of the raw packet to a ip packet. Each call ++ * to a field function of an IP packet, like ip:daddr() uses this function ++ * to to return the right data. In each case you will end up either with a ++ * new packet segment (annotated with the proper metatable) or a boolean ++ * value (False) if something went wrong. In the case everything went fine, ++ * the newly created lua_packet_segment is annotated with the proper ++ * metatable where the fields get and set also contain the specific getter ++ * and setter functions given by the protocol buffer. E.g. the function call ++ * ip:daddr():get() or ip:daddr():set(...) will call the proper function ++ * defined inside the corresponding field definition. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * 2. type of the protocol buffer, optional, and only used if the accessed ++ * field is the payload field. If a type is provided for the access of the ++ * payload field, the function tries to convert the data pointed to by the ++ * payload field to the given type. To check if such a conversion is ++ * possible, it calls the function pointed to by the protocol buffer member ++ * has_protocol. If this function returns True, the conversion takes place. ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index ++ * ++ * Return: ++ * 1. A lua_packet_segment annotated with the according metatable or False in ++ * case the input data is not valid ++ */ ++static int32_t get_protocol_field(lua_State *L) ++{ ++ int32_t prot_type; ++ lua_packet_segment * seg, *new; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ struct protocol_field * field = &prot_buf->protocol_fields[field_index]; ++ ++ /* get the current packet segment */ ++ seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ /* initialize the new packet segment */ ++ new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ new->start = seg->start; /* the start is unchanged */ ++ new->offset = get_field_offset_in_bytes(field, seg, field_index); ++ new->length = get_field_length_in_bytes(field, seg, field_index); ++ ++ /* if new->length == 0 then no configuration was done, we guess the size by subtracting the ++ * new offset from the packet length. since the old length is getting initialized by the ++ * netfilter extension this assumption holds for the very last field of the protocol. ++ * this 'feature' should be used by protocol buffers containing a payload, whereas the ++ * payload field is the last field of the buffer. However, at compile-time unknown field ++ * sizes (and offsets) of fields not being placed at the end of the protocol should be ++ * initialized using the 'get_field_changes' hook system. */ ++ if (new->length == 0) ++ new->length = (seg->length + seg->offset) - (new->offset); ++ /* ++ printf("%s->%s:: seg->offset %i, seg->length %i, new->offset %i, new->length %i\n", ++ prot_buf->name, field->name, seg->offset, seg->length, new->offset, new->length); ++ */ ++ /* special care for packet payload requests */ ++ if (prot_buf->payload_field != NULL && strcmp(prot_buf->payload_field, field->name) == 0) { ++ /* we know the payload field is requested */ ++ /* the requested payload can be delivered either as a common segment or as ++ * an other packet type, such a conversion needs an extra protocol parameter ++ * ... so lets check */ ++ ++ if (lua_isnumber(L, 2)) { ++ /* we have an extra parameter, ... lets see if it is a valid protocol ++ * the parameter is the index of the 'supported_protocols'-array member */ ++ prot_type = lua_tointeger(L, 2); ++ if (prot_type >= 0 && prot_type < PACKET_SENTINEL) { ++ /* we are sure the purpose of the request is to get the payload data, ++ * converted to the given protocol. lets check if the payload contains ++ * data of the given protocol */ ++ if (payload_contains_protocol(L, prot_buf, seg, prot_type)) { ++ /* success, we can push the metatable for the given protocol */ ++ get_metatable_from_protocol_type(L, prot_type); ++ if (!lua_isnil(L, -1)) /* check if the metatable was found */ ++ /* perhaps the field offsets and lengths of the containing protocol ++ * are not set correctly. request the optional 'field_changes' structure ++ * holding the changes for lengths and offsets. */ ++ new->changes = protocol_get_field_changes(L, get_protocol_buf(prot_type), new); ++ else{ ++ /* failed, the requested protocol is not available ++ * we push false and return */ ++ lua_pop(L, 1); /* pop the userdata */ ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ }else{ ++ /* payload does not carry the provided protocol */ ++ /* we push false and return */ ++ lua_pop(L, 1); /* pop the userdata */ ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ }else{ ++ /* unknown protocol */ ++ lua_pop(L, 1); /* pop the userdata */ ++ luaL_error(L, "provided protocol is unknown"); ++ } ++ } ++ } ++ ++ /* if there is still the 'new' userdata on the top, we push our own metatable */ ++ if (lua_isuserdata(L, -1)) { ++ luaL_getmetatable(L, prot_buf->name); ++ new->changes = seg->changes; ++ if (seg->changes) ++ new->changes->ref_count++; ++ } ++ ++ /* a new packet segment is at index -2 , and the proper metatable at index -1 of the stack ++ * lets set the propper setter and getter function for the requested field */ ++ initialize_field_getter_and_setter(L, prot_buf, field_index); ++ ++ lua_setmetatable(L, -2); ++ return 1; ++} ++ ++/* C_API: 'register_protbuf' is only used internally. This function takes a ++ * pointer to a fully initialized protocol buffer struct and registers it ++ * inside the Lua state. Registering means: ++ * ++ * 1. it creates a new metatable with the name of the protocol buffer. ++ * 2. it registers the default functions which are stored in the luaL_Reg ++ * array seg_access_functions. ++ * 3. it loops over the protocol fields stored at prot_buf->protocol_fields ++ * and registers a new function (using the field name) inside the ++ * metatable. Each field points to the function 'get_protocol_field' ++ * which acts as a closure taking a pointer to the protocol buffer as ++ * well as the index of the field as upvalues. ++ * 4. The protocol index, serves as numerical identifier of this protocol ++ * buffer or even of the protocol itself. This index is stored as a ++ * global value inside the Lua state as well as inside the Lua table ++ * 'supported_protocols'. Assuming the name of a procotol buffer is ++ * "packet_ip" the following statements are true: ++ * ++ * supported_protocols[protocol_index] == "packet_ip" ++ * packet_ip == protocol_index ++ * ++ * This allows you to get all registered protocols from within Lua. This ++ * is especially usefull for the dynamic protocol buffers where you have ++ * to provide your own "has_protocol"-function, which probably needs the ++ * information on which protocols it is able to contain. ++ */ ++void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, uint32_t protocol_index) ++{ ++ int32_t field_index; ++ luaL_Reg *reg = (struct luaL_Reg *)seg_access_functions; ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ luaL_newmetatable(L, prot_buf->name); ++ ++ /* metatable.__index = metatable */ ++ lua_pushvalue(L, -1); /* duplicates the metatable */ ++ lua_setfield(L, -2, "__index"); ++ ++ /* pushing default functions */ ++ for (; reg->name; reg++) { ++ lua_pushlightuserdata(L, (void *)prot_buf); ++ lua_pushcclosure(L, reg->func, 1); ++ lua_setfield(L, -2, reg->name); ++ } ++ ++ /* pushing functions specific to the protocol buffer */ ++ for (field_index = 0; field->name; field++, field_index++) { ++ lua_pushlightuserdata(L, (void *)prot_buf); /* upvalue: prot_buf */ ++ lua_pushinteger(L, field_index); /* upvalue: index of protocol field */ ++ lua_pushcclosure(L, get_protocol_field, 2); ++ lua_setfield(L, -2, field->name); ++ } ++ /* pop the metatable */ ++ lua_pop(L, 1); ++ ++ /* registering the array-index as the protocol_id*/ ++ lua_getglobal(L, "_G"); ++ lua_pushinteger(L, protocol_index); ++ lua_setfield(L, -2, prot_buf->name); ++ lua_pop(L, 1); /* pop _G */ ++ ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ lua_pushstring(L, prot_buf->name); ++ lua_rawseti(L, -2, protocol_index); ++ ++ lua_pop(L, 1); /* pop SUPPORTED_PROTOCOL_TABLE */ ++ ++ supported_protocols[protocol_index] = prot_buf; ++} ++ ++void luaopen_controller(lua_State *L) ++{ ++ /* registering a table inside the _G with table[protocol_index] = prot_buf->name */ ++ lua_getglobal(L, "_G"); ++ lua_newtable(L); ++ lua_setfield(L, -2, SUPPORTED_PROTOCOL_TABLE); ++ lua_pop(L, 1); /* pop _G */ ++ ++ luaopen_protbuf_raw(L); ++ luaopen_protbuf_eth(L); ++ luaopen_protbuf_ip(L); ++ luaopen_protbuf_icmp(L); ++ luaopen_protbuf_tcp(L); ++ luaopen_protbuf_tcp_options(L); ++ luaopen_protbuf_udp(L); ++ luaopen_protbuf_tftp(L); ++ luaopen_protbuf_dynamic(L); ++ /* should follow all other static buffers */ ++#if defined(__KERNEL__) ++ luaopen_nflib(L); ++#endif ++ ++ luaopen_bytearraylib(L); ++} ++ ++ ++ ++ +--- /dev/null ++++ b/extensions/LUA/controller.h +@@ -0,0 +1,264 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#ifndef CONTROLLER_H_ ++#define CONTROLLER_H_ ++ ++#include "stdlib.h" /* wrapper */ ++#include "string.h" /* wrapper */ ++#include "lua.h" ++#include "lualib.h" ++#include "lauxlib.h" ++ ++#if defined(__KERNEL__) ++#include ++#include ++#include ++#endif ++ ++ ++/* to compile the stuff in userspace (for testing)*/ ++#if !defined(__KERNEL__) ++#include ++#define pr_debug printf; ++ ++#define kmalloc(size, type) malloc(size) ++#define kfree(ptr) free(ptr) ++ ++#endif ++ ++ ++/**********************************************************************/ ++/* nf Lua configuration */ ++/**********************************************************************/ ++#define MAX_NR_OF_PROTOCOLS 16 ++#define SUPPORTED_PROTOCOL_TABLE "supported_protocols" ++ ++#define MAX_NR_OF_FIELDS_IN_DYN_PROT_BUF 32 ++ ++ ++/**********************************************************************/ ++/* Static Protocol Buffer configuration */ ++/**********************************************************************/ ++ ++/* the definitions of the stringified expression of the prot_bufs... ++ * make sure all static prot_bufs are listed and are unique */ ++#define LUA_PACKET_SEG_RAW "packet_raw" ++#define LUA_PACKET_SEG_ETH "packet_eth" ++#define LUA_PACKET_SEG_ICMP "packet_icmp" ++#define LUA_PACKET_SEG_IP "packet_ip" ++#define LUA_PACKET_SEG_TCP "packet_tcp" ++#define LUA_PACKET_SEG_TCP_OPT "packet_tcp_opt" ++#define LUA_PACKET_SEG_UDP "packet_udp" ++#define LUA_PACKET_SEG_TFTP "packet_tftp" ++ ++/* the enum holding all static prot_bufs... make sure it contains all ++ * static prot_bufs */ ++enum PROT_BUF { ++ PACKET_RAW, ++ PACKET_ETH, ++ PACKET_IP, ++ PACKET_ICMP, ++ PACKET_TCP, ++ PACKET_TCP_OPTIONS, ++ PACKET_UDP, ++ PACKET_TFTP, ++ PACKET_DYNAMIC, ++ PACKET_SENTINEL ++}; ++ ++/* the luaopen-function of the prot_bufs... make sure it is called ++ * inside luaopen_controller */ ++void luaopen_protbuf_raw(lua_State *L); ++void luaopen_protbuf_eth(lua_State *L); ++void luaopen_protbuf_ip(lua_State *L); ++void luaopen_protbuf_icmp(lua_State *L); ++void luaopen_protbuf_tcp(lua_State *L); ++void luaopen_protbuf_tcp_options(lua_State *L); ++void luaopen_protbuf_udp(lua_State *L); ++void luaopen_protbuf_tftp(lua_State *L); ++void luaopen_protbuf_dynamic(lua_State *L); ++ ++/**********************************************************************/ ++/* field changes */ ++/**********************************************************************/ ++struct field_changes { ++ int ref_count; ++ int *field_length_changes; ++ int *field_offset_changes; ++}; ++ ++/**********************************************************************/ ++/* lua packet segment */ ++/* ------------------ */ ++/* The struct lua_packet_segment is the integral part of a Lua packet.*/ ++/* At the very beginning, when a new packet arrives in `lua_tg`_ such */ ++/* a struct is initialized. The field start then points to the lowest */ ++/* available header inside the sk_buff structure. During packet */ ++/* processing the start pointer remains the same, only the offset and */ ++/* length value change. */ ++/**********************************************************************/ ++#define checkpacketseg(L, i, seg_type) \ ++ (lua_packet_segment *)luaL_checkudata(L, i, seg_type) ++ ++typedef struct lua_packet_segment { ++ unsigned int offset; ++ unsigned int length; ++ struct field_changes * changes; ++ unsigned char * start; /* need to be at the end because of the memory alignment */ ++} lua_packet_segment; ++ ++/**********************************************************************/ ++/* protocol field */ ++/* -------------- */ ++/* This structure is a container for the field definitions used by the*/ ++/* protocol buffer. Each protocol field is expressed using this struct*/ ++/* Have a look at the protocol buffers to see how the struct gets */ ++/* initialized. */ ++/* */ ++/* name: */ ++/* This member expresses the name of the field, ending */ ++/* in its own Lua function to access the field. */ ++/* offset / length: */ ++/* These members do specify the position inside the protocol header */ ++/* in bits (not bytes!). */ ++/* get / set: */ ++/* The get and set functions take a function pointer pointing to the*/ ++/* specific getter and setter function for this field. */ ++/**********************************************************************/ ++struct protocol_field { ++ const char * name; ++ uint32_t offset; ++ uint32_t length; ++ lua_CFunction get; ++ lua_CFunction set; ++}; ++#define PROT_FIELD_SENTINEL { NULL, 0, 0, NULL, NULL } ++ ++ ++/**********************************************************************/ ++/* protocol_buf */ ++/**********************************************************************/ ++/* This structure is a container for all the information needed for a ++ * protocol buffer. It gets initialized in each protocol buffer header ++ * file or for the dynamic protocol buffers on runtime using the ++ * 'register_dynamic_protocol_buffer' function. ++ * ++ * name: ++ * This member is used throughout the system. It is also exported ++ * to Lua as a variable name holding the index of the 'supported_protocols' ++ * array. The name is also used as the name of the generated Lua ++ * metatable, that is why inside the macro checkpacketseg_ it ++ * is always the name of a protocol buffer that is passed as the ++ * second parameter. ++ * payload_field: ++ * This member holds the string of the field responsible for payload ++ * data. The payload field of a protocol has an extra property, since ++ * it can be used to invoke another protocol buffer that is applied to ++ * the payload content. ++ * has_protocol: ++ * This member is used together with the payload_field. Since we must ++ * be sure that the payload content does really contain a protocol ++ * of type X. The function pointed to by has_protocol checks if the ++ * protocol buffer X can be applied on the payload_data. ++ * protocol_fields: ++ * This member points to the array of 'protocol_field' structures ++ * get_field_changes: ++ * This member is optional. It is used to return a pointer to an initialized ++ * field_changes struct. The function is called, whenever the payload field ++ * is requested with a given protocol type. Usually this function will ++ * initialize the field_changes struct depending on the content of the ++ * payload data. e.g. ++ * tcp = ip:data(packet_tcp) ++ * such a request will call the 'get_field_changes' function of the tcp ++ * protocol buffer. This enables, that the tcp options field have the proper ++ * length as well as the tcp data start at the right offset. ++ */ ++struct protocol_buf { ++ int is_dynamic; ++ const char * name; ++ char * payload_field; ++ int (*has_protocol)(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg, int type); ++ struct protocol_field * protocol_fields; ++ struct field_changes * (*get_field_changes)(lua_State *L, lua_packet_segment * seg); ++}; ++ ++/**********************************************************************/ ++/* lua byte array library */ ++/**********************************************************************/ ++#define LUA_BYTE_ARRAY "byte_array" ++#define checkbytearray(L, i) \ ++ (lua_packet_segment *)luaL_checkudata(L, i, LUA_BYTE_ARRAY) ++lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy); ++void luaopen_bytearraylib(lua_State *L); ++ ++ ++/**********************************************************************/ ++/* lua netfilter environment library */ ++/**********************************************************************/ ++#define NETFILTER_LIB "nf" ++#if defined(__KERNEL__) ++ struct lua_env { ++ lua_State *L; ++ /* perhaps more to come here (e.g. a state per CPU) */ ++ }; ++ #define LUA_ENV "lua_env" ++ #define checkluaenv(L, i) \ ++ (struct lua_env *)luaL_checkudata(L, i, LUA_ENV) ++ ++ void luaopen_nflib(lua_State *L); ++#endif ++ ++void cleanup_dynamic_prot_bufs(void); /* freeing all dynamic prot bufs */ ++/**********************************************************************/ ++/* lua protbuf helpers */ ++/**********************************************************************/ ++int get_1_bit_generic(lua_State *L); ++int set_1_bit_generic(lua_State *L); ++int get_lower_4_bit_generic(lua_State *L); ++int set_lower_4_bit_generic(lua_State *L); ++int get_upper_4_bit_generic(lua_State *L); ++int set_upper_4_bit_generic(lua_State *L); ++int get_8_bit_generic(lua_State *L); ++int set_8_bit_generic(lua_State *L); ++int get_16_bit_generic(lua_State *L); ++int set_16_bit_generic(lua_State *L); ++int get_32_bit_generic(lua_State *L); ++int set_32_bit_generic(lua_State *L); ++int set_data_generic(lua_State *L); ++int get_string_generic(lua_State *L); ++int get_byte_generic_str(lua_State *L); ++struct field_changes * get_allocated_field_changes(lua_State *L, int nr_of_fields); ++ ++/* only used by the dynamic prot buf subsystem */ ++#define MAX_NR_OF_DYN_PROT_BUFS 16 ++int field_dynamic_setter(lua_State *L); ++int field_dynamic_getter(lua_State *L); ++int has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int type); ++struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg); ++ ++/**********************************************************************/ ++/* lua controller API */ ++/**********************************************************************/ ++void luaopen_controller(lua_State *L); ++struct protocol_buf * get_protocol_buf(unsigned int protocol_id); ++void get_metatable_from_protocol_type(lua_State *L, int type); ++void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, unsigned int protocol_index); ++ ++ ++#endif /* CONTROLLER_H_ */ +--- /dev/null ++++ b/extensions/LUA/Kbuild +@@ -0,0 +1,49 @@ ++# -*- Makefile -*- ++ ++# Adding debug options ++EXTRA_CFLAGS += -DDEBUG ++ ++obj-m += xt_LUA.o ++ ++EXTRA_CFLAGS += -I$(src)/prot_buf_new ++xt_LUA-y += xt_LUA_target.o \ ++ ++xt_LUA-y += nf_lua.o \ ++ prot_buf_helpers.o \ ++ byte_array.o \ ++ controller.o \ ++ prot_buf_ethernet.o \ ++ prot_buf_icmp.o \ ++ prot_buf_ip.o \ ++ prot_buf_raw.o \ ++ prot_buf_tcp.o \ ++ prot_buf_udp.o \ ++ prot_buf_tftp.o \ ++ prot_buf_dynamic.o \ ++ ++ ++# Adding Lua Support ++EXTRA_CFLAGS += -I$(src)/lua -I$(src)/lua/include ++xt_LUA-y += lua/lapi.o \ ++ lua/lbaselib.o \ ++ lua/lcode.o \ ++ lua/ldebug.o \ ++ lua/ldo.o \ ++ lua/ldump.o \ ++ lua/lfunc.o \ ++ lua/lgc.o \ ++ lua/llex.o \ ++ lua/lmem.o \ ++ lua/lobject.o \ ++ lua/lopcodes.o \ ++ lua/lparser.o \ ++ lua/lstate.o \ ++ lua/lstring.o \ ++ lua/lstrlib.o \ ++ lua/ltable.o \ ++ lua/ltablib.o \ ++ lua/ltm.o \ ++ lua/lundump.o \ ++ lua/lvm.o \ ++ lua/lzio.o \ ++ lua/lauxlib.o \ +--- /dev/null ++++ b/extensions/LUA/libxt_LUA.c +@@ -0,0 +1,191 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "xt_LUA.h" ++ ++enum { ++ FLAG_SCRIPT = 1 << 0, ++ FLAG_STATE = 1 << 1, ++ FLAG_FUNCTION = 1 << 2, ++}; ++ ++static const struct option lua_tg_opts[] = { ++ { .name = "script", .has_arg = true, .val = 's' }, ++ { .name = "state", .has_arg = true, .val = 'l' }, ++ { .name = "function", .has_arg = true, .val = 'f' }, ++ { NULL }, ++}; ++ ++ ++static void lua_tg_help(void) ++{ ++ printf( ++ "LUA target options:\n" ++ " --script SCRIPT Process packet with the Lua script given by SCRIPT\n" ++ " \n" ++ " --state ID Process packet within the Lua state given by ID.\n" ++ " Omitting --state infers the ID 0, which can be\n" ++ " refered to the 'global' state.\n" ++ " \n" ++ " --function FUNCTION Name of the function that processes the Lua packet\n" ++ "\n"); ++} ++ ++static void ++lua_tg_init(struct xt_entry_target *target) ++{ ++ struct xt_lua_tginfo *info = (void *)target->data; ++ ++ info->state_id = 0; ++ strcpy(info->function, "process_packet\0"); ++} ++ ++static int ++lua_tg_parse(int32_t c, char **argv, int32_t invert, uint32_t *flags, ++ const void *entry, struct xt_entry_target **target) ++{ ++ struct xt_lua_tginfo *info = (void *)(*target)->data; ++ char buf[MAX_SCRIPT_SIZE]; ++ long script_size; ++ uint32_t state_id; ++ FILE *file; ++ ++ switch (c) { ++ case 's': ++ if (*flags & FLAG_SCRIPT) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --script more than once"); ++ ++ if (strlen(optarg) > sizeof(info->filename)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Maximum script length is %zu", ++ sizeof(info->filename)); ++ ++ if (strchr(optarg, '\n')) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Newlines not allowed in script name"); ++ file = fopen(optarg, "rb"); ++ if (file != NULL) { ++ fseek(file, 0, SEEK_END); ++ script_size = ftell(file); ++ if (script_size > MAX_SCRIPT_SIZE) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: The size of the script is too big"); ++ ++ fseek(file, 0, SEEK_SET); ++ fread(buf, script_size, 1, file); ++ fclose(file); ++ } else ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot open script %s", optarg); ++ ++ strncpy(info->filename, optarg, sizeof(info->filename)); ++ strncpy(info->buf, buf, sizeof(info->buf)); ++ info->script_size = script_size; ++ ++ *flags |= FLAG_SCRIPT; ++ return true; ++ ++ case 'l': ++ if (*flags & FLAG_STATE) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --state more than once"); ++ ++ if (!xtables_strtoui(optarg, NULL, &state_id, 0, 8)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Invalid --state %s", optarg); ++ ++ info->state_id = state_id; ++ *flags |= FLAG_STATE; ++ return true; ++ ++ case 'f': ++ if (*flags & FLAG_FUNCTION) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --function more than once"); ++ if (strlen(optarg) > sizeof(info->function)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Maximum function length is %zu", ++ sizeof(info->function)); ++ ++ if (strchr(optarg, '\n')) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Newlines not allowed in function name"); ++ ++ strncpy(info->function, optarg, sizeof(info->function)); ++ ++ *flags |= FLAG_FUNCTION; ++ return true; ++ } ++ ++ return false; ++} ++ ++static void ++lua_tg_check(uint32_t flags) ++{ ++ if (flags == 0) ++ xtables_error(PARAMETER_PROBLEM, "LUA: --script parameter required"); ++} ++ ++static void ++lua_tg_print(const void *entry, const struct xt_entry_target *target, ++ int32_t numeric) ++{ ++ const struct xt_lua_tginfo *info = (const void *)target->data; ++ ++ printf("LUA script: %s ", info->filename); ++} ++ ++static void ++lua_tg_save(const void *entry, const struct xt_entry_target *target) ++{ ++ const struct xt_lua_tginfo *info = (const void *)target->data; ++ ++ printf("--script %s ", info->filename); ++} ++ ++static struct xtables_target lua_tg_reg = { ++ .name = "LUA", ++ .version = XTABLES_VERSION, ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .size = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .help = lua_tg_help, ++ .init = lua_tg_init, ++ .parse = lua_tg_parse, ++ .final_check = lua_tg_check, ++ .print = lua_tg_print, ++ .save = lua_tg_save, ++ .extra_opts = lua_tg_opts, ++}; ++ ++static __attribute__((constructor)) void lua_tg_ldr(void) ++{ ++ xtables_register_target(&lua_tg_reg); ++} ++ +--- /dev/null ++++ b/extensions/LUA/libxt_LUA.man +@@ -0,0 +1 @@ ++Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +--- /dev/null ++++ b/extensions/LUA/lua/include/ctype.h +@@ -0,0 +1,11 @@ ++#include ++#undef isalnum ++#define isalnum(c) (((__ismask(c)&(_U|_L|_D)) != 0) && (c > 0)) ++#undef isalpha ++#define isalpha(c) (((__ismask(c)&(_U|_L)) != 0) && (c > 0)) ++#undef iscntrl ++#define iscntrl(c) (((__ismask(c)&(_C)) != 0) && (c > 0)) ++#undef isdigit ++#define isdigit(c) (((__ismask(c)&(_D)) != 0) && (c > 0)) ++#undef isspace ++#define isspace(c) (((__ismask(c)&(_S)) != 0) && (c > 0)) +--- /dev/null ++++ b/extensions/LUA/lua/include/errno.h +@@ -0,0 +1 @@ ++#include +--- /dev/null ++++ b/extensions/LUA/lua/include/locale.h +@@ -0,0 +1,5 @@ ++struct lconv { ++ char * decimal_point ; ++} ; ++ ++#define localeconv() NULL +--- /dev/null ++++ b/extensions/LUA/lua/include/setjmp.h +@@ -0,0 +1,26 @@ ++/* ++ * arch/um/include/sysdep-i386/archsetjmp.h ++ */ ++ ++#ifndef _KLIBC_ARCHSETJMP_H ++#define _KLIBC_ARCHSETJMP_H ++ ++struct __jmp_buf { ++ unsigned int __ebx; ++ unsigned int __esp; ++ unsigned int __ebp; ++ unsigned int __esi; ++ unsigned int __edi; ++ unsigned int __eip; ++}; ++ ++typedef struct __jmp_buf jmp_buf[1]; ++ ++#define JB_IP __eip ++#define JB_SP __esp ++ ++int setjmp(jmp_buf); ++void longjmp(jmp_buf, int); ++ ++#endif /* _SETJMP_H */ ++ +--- /dev/null ++++ b/extensions/LUA/lua/include/stdio.h +@@ -0,0 +1 @@ ++#include +--- /dev/null ++++ b/extensions/LUA/lua/include/stdlib.h +@@ -0,0 +1,7 @@ ++#include ++ ++#define exit(E) return ++#define strtoul simple_strtoul ++#define strcoll strcmp ++ ++#define CHAR_BIT 8 +--- /dev/null ++++ b/extensions/LUA/lua/include/string.h +@@ -0,0 +1 @@ ++#include +--- /dev/null ++++ b/extensions/LUA/lua/lapi.c +@@ -0,0 +1,1086 @@ ++/* ++** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ ++** Lua API ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#define lapi_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lapi.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lundump.h" ++#include "lvm.h" ++ ++ ++ ++const char lua_ident[] = ++ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" ++ "$Authors: " LUA_AUTHORS " $\n" ++ "$URL: www.lua.org $\n"; ++ ++ ++ ++#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) ++ ++#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) ++ ++#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} ++ ++ ++ ++static TValue *index2adr (lua_State *L, int idx) { ++ if (idx > 0) { ++ TValue *o = L->base + (idx - 1); ++ api_check(L, idx <= L->ci->top - L->base); ++ if (o >= L->top) return cast(TValue *, luaO_nilobject); ++ else return o; ++ } ++ else if (idx > LUA_REGISTRYINDEX) { ++ api_check(L, idx != 0 && -idx <= L->top - L->base); ++ return L->top + idx; ++ } ++ else switch (idx) { /* pseudo-indices */ ++ case LUA_REGISTRYINDEX: return registry(L); ++ case LUA_ENVIRONINDEX: { ++ Closure *func = curr_func(L); ++ sethvalue(L, &L->env, func->c.env); ++ return &L->env; ++ } ++ case LUA_GLOBALSINDEX: return gt(L); ++ default: { ++ Closure *func = curr_func(L); ++ idx = LUA_GLOBALSINDEX - idx; ++ return (idx <= func->c.nupvalues) ++ ? &func->c.upvalue[idx-1] ++ : cast(TValue *, luaO_nilobject); ++ } ++ } ++} ++ ++ ++static Table *getcurrenv (lua_State *L) { ++ if (L->ci == L->base_ci) /* no enclosing function? */ ++ return hvalue(gt(L)); /* use global table as environment */ ++ else { ++ Closure *func = curr_func(L); ++ return func->c.env; ++ } ++} ++ ++ ++void luaA_pushobject (lua_State *L, const TValue *o) { ++ setobj2s(L, L->top, o); ++ api_incr_top(L); ++} ++ ++ ++LUA_API int lua_checkstack (lua_State *L, int size) { ++ int res = 1; ++ lua_lock(L); ++ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) ++ res = 0; /* stack overflow */ ++ else if (size > 0) { ++ luaD_checkstack(L, size); ++ if (L->ci->top < L->top + size) ++ L->ci->top = L->top + size; ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { ++ int i; ++ if (from == to) return; ++ lua_lock(to); ++ api_checknelems(from, n); ++ api_check(from, G(from) == G(to)); ++ api_check(from, to->ci->top - to->top >= n); ++ from->top -= n; ++ for (i = 0; i < n; i++) { ++ setobj2s(to, to->top++, from->top + i); ++ } ++ lua_unlock(to); ++} ++ ++ ++LUA_API void lua_setlevel (lua_State *from, lua_State *to) { ++ to->nCcalls = from->nCcalls; ++} ++ ++ ++LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { ++ lua_CFunction old; ++ lua_lock(L); ++ old = G(L)->panic; ++ G(L)->panic = panicf; ++ lua_unlock(L); ++ return old; ++} ++ ++ ++LUA_API lua_State *lua_newthread (lua_State *L) { ++ lua_State *L1; ++ lua_lock(L); ++ luaC_checkGC(L); ++ L1 = luaE_newthread(L); ++ setthvalue(L, L->top, L1); ++ api_incr_top(L); ++ lua_unlock(L); ++ luai_userstatethread(L, L1); ++ return L1; ++} ++ ++ ++ ++/* ++** basic stack manipulation ++*/ ++ ++ ++LUA_API int lua_gettop (lua_State *L) { ++ return cast_int(L->top - L->base); ++} ++ ++ ++LUA_API void lua_settop (lua_State *L, int idx) { ++ lua_lock(L); ++ if (idx >= 0) { ++ api_check(L, idx <= L->stack_last - L->base); ++ while (L->top < L->base + idx) ++ setnilvalue(L->top++); ++ L->top = L->base + idx; ++ } ++ else { ++ api_check(L, -(idx+1) <= (L->top - L->base)); ++ L->top += idx+1; /* `subtract' index (index is negative) */ ++ } ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_remove (lua_State *L, int idx) { ++ StkId p; ++ lua_lock(L); ++ p = index2adr(L, idx); ++ api_checkvalidindex(L, p); ++ while (++p < L->top) setobjs2s(L, p-1, p); ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_insert (lua_State *L, int idx) { ++ StkId p; ++ StkId q; ++ lua_lock(L); ++ p = index2adr(L, idx); ++ api_checkvalidindex(L, p); ++ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); ++ setobjs2s(L, p, L->top); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_replace (lua_State *L, int idx) { ++ StkId o; ++ lua_lock(L); ++ /* explicit test for incompatible code */ ++ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) ++ luaG_runerror(L, "no calling environment"); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ if (idx == LUA_ENVIRONINDEX) { ++ Closure *func = curr_func(L); ++ api_check(L, ttistable(L->top - 1)); ++ func->c.env = hvalue(L->top - 1); ++ luaC_barrier(L, func, L->top - 1); ++ } ++ else { ++ setobj(L, o, L->top - 1); ++ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ ++ luaC_barrier(L, curr_func(L), L->top - 1); ++ } ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushvalue (lua_State *L, int idx) { ++ lua_lock(L); ++ setobj2s(L, L->top, index2adr(L, idx)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++ ++/* ++** access functions (stack -> C) ++*/ ++ ++ ++LUA_API int lua_type (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); ++} ++ ++ ++LUA_API const char *lua_typename (lua_State *L, int t) { ++ UNUSED(L); ++ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; ++} ++ ++ ++LUA_API int lua_iscfunction (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return iscfunction(o); ++} ++ ++ ++LUA_API int lua_isnumber (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ return tonumber(o, &n); ++} ++ ++ ++LUA_API int lua_isstring (lua_State *L, int idx) { ++ int t = lua_type(L, idx); ++ return (t == LUA_TSTRING || t == LUA_TNUMBER); ++} ++ ++ ++LUA_API int lua_isuserdata (lua_State *L, int idx) { ++ const TValue *o = index2adr(L, idx); ++ return (ttisuserdata(o) || ttislightuserdata(o)); ++} ++ ++ ++LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { ++ StkId o1 = index2adr(L, index1); ++ StkId o2 = index2adr(L, index2); ++ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 ++ : luaO_rawequalObj(o1, o2); ++} ++ ++ ++LUA_API int lua_equal (lua_State *L, int index1, int index2) { ++ StkId o1, o2; ++ int i; ++ lua_lock(L); /* may call tag method */ ++ o1 = index2adr(L, index1); ++ o2 = index2adr(L, index2); ++ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); ++ lua_unlock(L); ++ return i; ++} ++ ++ ++LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { ++ StkId o1, o2; ++ int i; ++ lua_lock(L); /* may call tag method */ ++ o1 = index2adr(L, index1); ++ o2 = index2adr(L, index2); ++ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 ++ : luaV_lessthan(L, o1, o2); ++ lua_unlock(L); ++ return i; ++} ++ ++ ++ ++LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) ++ return nvalue(o); ++ else ++ return 0; ++} ++ ++ ++LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) { ++ lua_Integer res; ++ lua_Number num = nvalue(o); ++ lua_number2integer(res, num); ++ return res; ++ } ++ else ++ return 0; ++} ++ ++ ++LUA_API int lua_toboolean (lua_State *L, int idx) { ++ const TValue *o = index2adr(L, idx); ++ return !l_isfalse(o); ++} ++ ++ ++LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { ++ StkId o = index2adr(L, idx); ++ if (!ttisstring(o)) { ++ lua_lock(L); /* `luaV_tostring' may create a new string */ ++ if (!luaV_tostring(L, o)) { /* conversion failed? */ ++ if (len != NULL) *len = 0; ++ lua_unlock(L); ++ return NULL; ++ } ++ luaC_checkGC(L); ++ o = index2adr(L, idx); /* previous call may reallocate the stack */ ++ lua_unlock(L); ++ } ++ if (len != NULL) *len = tsvalue(o)->len; ++ return svalue(o); ++} ++ ++ ++LUA_API size_t lua_objlen (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TSTRING: return tsvalue(o)->len; ++ case LUA_TUSERDATA: return uvalue(o)->len; ++ case LUA_TTABLE: return luaH_getn(hvalue(o)); ++ case LUA_TNUMBER: { ++ size_t l; ++ lua_lock(L); /* `luaV_tostring' may create a new string */ ++ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); ++ lua_unlock(L); ++ return l; ++ } ++ default: return 0; ++ } ++} ++ ++ ++LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; ++} ++ ++ ++LUA_API void *lua_touserdata (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TUSERDATA: return (rawuvalue(o) + 1); ++ case LUA_TLIGHTUSERDATA: return pvalue(o); ++ default: return NULL; ++ } ++} ++ ++ ++LUA_API lua_State *lua_tothread (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (!ttisthread(o)) ? NULL : thvalue(o); ++} ++ ++ ++LUA_API const void *lua_topointer (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TTABLE: return hvalue(o); ++ case LUA_TFUNCTION: return clvalue(o); ++ case LUA_TTHREAD: return thvalue(o); ++ case LUA_TUSERDATA: ++ case LUA_TLIGHTUSERDATA: ++ return lua_touserdata(L, idx); ++ default: return NULL; ++ } ++} ++ ++ ++ ++/* ++** push functions (C -> stack) ++*/ ++ ++ ++LUA_API void lua_pushnil (lua_State *L) { ++ lua_lock(L); ++ setnilvalue(L->top); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { ++ lua_lock(L); ++ setnvalue(L->top, n); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { ++ lua_lock(L); ++ setnvalue(L->top, cast_num(n)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { ++ lua_lock(L); ++ luaC_checkGC(L); ++ setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushstring (lua_State *L, const char *s) { ++ if (s == NULL) ++ lua_pushnil(L); ++ else ++ lua_pushlstring(L, s, strlen(s)); ++} ++ ++ ++LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, ++ va_list argp) { ++ const char *ret; ++ lua_lock(L); ++ luaC_checkGC(L); ++ ret = luaO_pushvfstring(L, fmt, argp); ++ lua_unlock(L); ++ return ret; ++} ++ ++ ++LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { ++ const char *ret; ++ va_list argp; ++ lua_lock(L); ++ luaC_checkGC(L); ++ va_start(argp, fmt); ++ ret = luaO_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ lua_unlock(L); ++ return ret; ++} ++ ++ ++LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { ++ Closure *cl; ++ lua_lock(L); ++ luaC_checkGC(L); ++ api_checknelems(L, n); ++ cl = luaF_newCclosure(L, n, getcurrenv(L)); ++ cl->c.f = fn; ++ L->top -= n; ++ while (n--) ++ setobj2n(L, &cl->c.upvalue[n], L->top+n); ++ setclvalue(L, L->top, cl); ++ lua_assert(iswhite(obj2gco(cl))); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushboolean (lua_State *L, int b) { ++ lua_lock(L); ++ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { ++ lua_lock(L); ++ setpvalue(L->top, p); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_pushthread (lua_State *L) { ++ lua_lock(L); ++ setthvalue(L, L->top, L); ++ api_incr_top(L); ++ lua_unlock(L); ++ return (G(L)->mainthread == L); ++} ++ ++ ++ ++/* ++** get functions (Lua -> stack) ++*/ ++ ++ ++LUA_API void lua_gettable (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ luaV_gettable(L, t, L->top - 1, L->top - 1); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { ++ StkId t; ++ TValue key; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ setsvalue(L, &key, luaS_new(L, k)); ++ luaV_gettable(L, t, &key, L->top); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawget (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { ++ StkId o; ++ lua_lock(L); ++ o = index2adr(L, idx); ++ api_check(L, ttistable(o)); ++ setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { ++ lua_lock(L); ++ luaC_checkGC(L); ++ sethvalue(L, L->top, luaH_new(L, narray, nrec)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_getmetatable (lua_State *L, int objindex) { ++ const TValue *obj; ++ Table *mt = NULL; ++ int res; ++ lua_lock(L); ++ obj = index2adr(L, objindex); ++ switch (ttype(obj)) { ++ case LUA_TTABLE: ++ mt = hvalue(obj)->metatable; ++ break; ++ case LUA_TUSERDATA: ++ mt = uvalue(obj)->metatable; ++ break; ++ default: ++ mt = G(L)->mt[ttype(obj)]; ++ break; ++ } ++ if (mt == NULL) ++ res = 0; ++ else { ++ sethvalue(L, L->top, mt); ++ api_incr_top(L); ++ res = 1; ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++LUA_API void lua_getfenv (lua_State *L, int idx) { ++ StkId o; ++ lua_lock(L); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ switch (ttype(o)) { ++ case LUA_TFUNCTION: ++ sethvalue(L, L->top, clvalue(o)->c.env); ++ break; ++ case LUA_TUSERDATA: ++ sethvalue(L, L->top, uvalue(o)->env); ++ break; ++ case LUA_TTHREAD: ++ setobj2s(L, L->top, gt(thvalue(o))); ++ break; ++ default: ++ setnilvalue(L->top); ++ break; ++ } ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++/* ++** set functions (stack -> Lua) ++*/ ++ ++ ++LUA_API void lua_settable (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ api_checknelems(L, 2); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ luaV_settable(L, t, L->top - 2, L->top - 1); ++ L->top -= 2; /* pop index and value */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { ++ StkId t; ++ TValue key; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ setsvalue(L, &key, luaS_new(L, k)); ++ luaV_settable(L, t, &key, L->top - 1); ++ L->top--; /* pop value */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawset (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ api_checknelems(L, 2); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); ++ luaC_barriert(L, hvalue(t), L->top-1); ++ L->top -= 2; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawseti (lua_State *L, int idx, int n) { ++ StkId o; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_check(L, ttistable(o)); ++ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); ++ luaC_barriert(L, hvalue(o), L->top-1); ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_setmetatable (lua_State *L, int objindex) { ++ TValue *obj; ++ Table *mt; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ obj = index2adr(L, objindex); ++ api_checkvalidindex(L, obj); ++ if (ttisnil(L->top - 1)) ++ mt = NULL; ++ else { ++ api_check(L, ttistable(L->top - 1)); ++ mt = hvalue(L->top - 1); ++ } ++ switch (ttype(obj)) { ++ case LUA_TTABLE: { ++ hvalue(obj)->metatable = mt; ++ if (mt) ++ luaC_objbarriert(L, hvalue(obj), mt); ++ break; ++ } ++ case LUA_TUSERDATA: { ++ uvalue(obj)->metatable = mt; ++ if (mt) ++ luaC_objbarrier(L, rawuvalue(obj), mt); ++ break; ++ } ++ default: { ++ G(L)->mt[ttype(obj)] = mt; ++ break; ++ } ++ } ++ L->top--; ++ lua_unlock(L); ++ return 1; ++} ++ ++ ++LUA_API int lua_setfenv (lua_State *L, int idx) { ++ StkId o; ++ int res = 1; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ api_check(L, ttistable(L->top - 1)); ++ switch (ttype(o)) { ++ case LUA_TFUNCTION: ++ clvalue(o)->c.env = hvalue(L->top - 1); ++ break; ++ case LUA_TUSERDATA: ++ uvalue(o)->env = hvalue(L->top - 1); ++ break; ++ case LUA_TTHREAD: ++ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); ++ break; ++ default: ++ res = 0; ++ break; ++ } ++ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); ++ L->top--; ++ lua_unlock(L); ++ return res; ++} ++ ++ ++/* ++** `load' and `call' functions (run Lua code) ++*/ ++ ++ ++#define adjustresults(L,nres) \ ++ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } ++ ++ ++#define checkresults(L,na,nr) \ ++ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) ++ ++ ++LUA_API void lua_call (lua_State *L, int nargs, int nresults) { ++ StkId func; ++ lua_lock(L); ++ api_checknelems(L, nargs+1); ++ checkresults(L, nargs, nresults); ++ func = L->top - (nargs+1); ++ luaD_call(L, func, nresults); ++ adjustresults(L, nresults); ++ lua_unlock(L); ++} ++ ++ ++ ++/* ++** Execute a protected call. ++*/ ++struct CallS { /* data to `f_call' */ ++ StkId func; ++ int nresults; ++}; ++ ++ ++static void f_call (lua_State *L, void *ud) { ++ struct CallS *c = cast(struct CallS *, ud); ++ luaD_call(L, c->func, c->nresults); ++} ++ ++ ++ ++LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { ++ struct CallS c; ++ int status; ++ ptrdiff_t func; ++ lua_lock(L); ++ api_checknelems(L, nargs+1); ++ checkresults(L, nargs, nresults); ++ if (errfunc == 0) ++ func = 0; ++ else { ++ StkId o = index2adr(L, errfunc); ++ api_checkvalidindex(L, o); ++ func = savestack(L, o); ++ } ++ c.func = L->top - (nargs+1); /* function to be called */ ++ c.nresults = nresults; ++ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); ++ adjustresults(L, nresults); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++/* ++** Execute a protected C call. ++*/ ++struct CCallS { /* data to `f_Ccall' */ ++ lua_CFunction func; ++ void *ud; ++}; ++ ++ ++static void f_Ccall (lua_State *L, void *ud) { ++ struct CCallS *c = cast(struct CCallS *, ud); ++ Closure *cl; ++ cl = luaF_newCclosure(L, 0, getcurrenv(L)); ++ cl->c.f = c->func; ++ setclvalue(L, L->top, cl); /* push function */ ++ api_incr_top(L); ++ setpvalue(L->top, c->ud); /* push only argument */ ++ api_incr_top(L); ++ luaD_call(L, L->top - 2, 0); ++} ++ ++ ++LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { ++ struct CCallS c; ++ int status; ++ lua_lock(L); ++ c.func = func; ++ c.ud = ud; ++ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, ++ const char *chunkname) { ++ ZIO z; ++ int status; ++ lua_lock(L); ++ if (!chunkname) chunkname = "?"; ++ luaZ_init(L, &z, reader, data); ++ status = luaD_protectedparser(L, &z, chunkname); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { ++ int status; ++ TValue *o; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = L->top - 1; ++ if (isLfunction(o)) ++ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); ++ else ++ status = 1; ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_status (lua_State *L) { ++ return L->status; ++} ++ ++ ++/* ++** Garbage-collection function ++*/ ++ ++LUA_API int lua_gc (lua_State *L, int what, int data) { ++ int res = 0; ++ global_State *g; ++ lua_lock(L); ++ g = G(L); ++ switch (what) { ++ case LUA_GCSTOP: { ++ g->GCthreshold = MAX_LUMEM; ++ break; ++ } ++ case LUA_GCRESTART: { ++ g->GCthreshold = g->totalbytes; ++ break; ++ } ++ case LUA_GCCOLLECT: { ++ luaC_fullgc(L); ++ break; ++ } ++ case LUA_GCCOUNT: { ++ /* GC values are expressed in Kbytes: #bytes/2^10 */ ++ res = cast_int(g->totalbytes >> 10); ++ break; ++ } ++ case LUA_GCCOUNTB: { ++ res = cast_int(g->totalbytes & 0x3ff); ++ break; ++ } ++ case LUA_GCSTEP: { ++ lu_mem a = (cast(lu_mem, data) << 10); ++ if (a <= g->totalbytes) ++ g->GCthreshold = g->totalbytes - a; ++ else ++ g->GCthreshold = 0; ++ while (g->GCthreshold <= g->totalbytes) { ++ luaC_step(L); ++ if (g->gcstate == GCSpause) { /* end of cycle? */ ++ res = 1; /* signal it */ ++ break; ++ } ++ } ++ break; ++ } ++ case LUA_GCSETPAUSE: { ++ res = g->gcpause; ++ g->gcpause = data; ++ break; ++ } ++ case LUA_GCSETSTEPMUL: { ++ res = g->gcstepmul; ++ g->gcstepmul = data; ++ break; ++ } ++ default: res = -1; /* invalid option */ ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++ ++/* ++** miscellaneous functions ++*/ ++ ++ ++LUA_API int lua_error (lua_State *L) { ++ lua_lock(L); ++ api_checknelems(L, 1); ++ luaG_errormsg(L); ++ lua_unlock(L); ++ return 0; /* to avoid warnings */ ++} ++ ++ ++LUA_API int lua_next (lua_State *L, int idx) { ++ StkId t; ++ int more; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ more = luaH_next(L, hvalue(t), L->top - 1); ++ if (more) { ++ api_incr_top(L); ++ } ++ else /* no more elements */ ++ L->top -= 1; /* remove key */ ++ lua_unlock(L); ++ return more; ++} ++ ++ ++LUA_API void lua_concat (lua_State *L, int n) { ++ lua_lock(L); ++ api_checknelems(L, n); ++ if (n >= 2) { ++ luaC_checkGC(L); ++ luaV_concat(L, n, cast_int(L->top - L->base) - 1); ++ L->top -= (n-1); ++ } ++ else if (n == 0) { /* push empty string */ ++ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); ++ api_incr_top(L); ++ } ++ /* else n == 1; nothing to do */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { ++ lua_Alloc f; ++ lua_lock(L); ++ if (ud) *ud = G(L)->ud; ++ f = G(L)->frealloc; ++ lua_unlock(L); ++ return f; ++} ++ ++ ++LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { ++ lua_lock(L); ++ G(L)->ud = ud; ++ G(L)->frealloc = f; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void *lua_newuserdata (lua_State *L, size_t size) { ++ Udata *u; ++ lua_lock(L); ++ luaC_checkGC(L); ++ u = luaS_newudata(L, size, getcurrenv(L)); ++ setuvalue(L, L->top, u); ++ api_incr_top(L); ++ lua_unlock(L); ++ return u + 1; ++} ++ ++ ++ ++ ++static const char *aux_upvalue (StkId fi, int n, TValue **val) { ++ Closure *f; ++ if (!ttisfunction(fi)) return NULL; ++ f = clvalue(fi); ++ if (f->c.isC) { ++ if (!(1 <= n && n <= f->c.nupvalues)) return NULL; ++ *val = &f->c.upvalue[n-1]; ++ return ""; ++ } ++ else { ++ Proto *p = f->l.p; ++ if (!(1 <= n && n <= p->sizeupvalues)) return NULL; ++ *val = f->l.upvals[n-1]->v; ++ return getstr(p->upvalues[n-1]); ++ } ++} ++ ++ ++LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { ++ const char *name; ++ TValue *val; ++ lua_lock(L); ++ name = aux_upvalue(index2adr(L, funcindex), n, &val); ++ if (name) { ++ setobj2s(L, L->top, val); ++ api_incr_top(L); ++ } ++ lua_unlock(L); ++ return name; ++} ++ ++ ++LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { ++ const char *name; ++ TValue *val; ++ StkId fi; ++ lua_lock(L); ++ fi = index2adr(L, funcindex); ++ api_checknelems(L, 1); ++ name = aux_upvalue(fi, n, &val); ++ if (name) { ++ L->top--; ++ setobj(L, val, L->top); ++ luaC_barrier(L, clvalue(fi), L->top); ++ } ++ lua_unlock(L); ++ return name; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lapi.h +@@ -0,0 +1,16 @@ ++/* ++** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions from Lua API ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lapi_h ++#define lapi_h ++ ++ ++#include "lobject.h" ++ ++ ++LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lauxlib.c +@@ -0,0 +1,672 @@ ++/* ++** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ ++** Auxiliary functions for building Lua libraries ++** See Copyright Notice in lua.h ++*/ ++ ++#if !defined(__KERNEL__) ++#include ++#include ++#include ++#include ++#include ++#else ++#include ++#include ++#include ++#include ++#include ++#endif ++ ++/* This file uses only the official API of Lua. ++** Any function declared here could be written as an application function. ++*/ ++ ++#define lauxlib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++ ++ ++#define FREELIST_REF 0 /* free list of references */ ++ ++ ++/* convert a stack index to positive */ ++#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ ++ lua_gettop(L) + (i) + 1) ++ ++ ++/* ++** {====================================================== ++** Error-report functions ++** ======================================================= ++*/ ++ ++ ++LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { ++ lua_Debug ar; ++ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ ++ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); ++ lua_getinfo(L, "n", &ar); ++ if (strcmp(ar.namewhat, "method") == 0) { ++ narg--; /* do not count `self' */ ++ if (narg == 0) /* error is in the self argument itself? */ ++ return luaL_error(L, "calling " LUA_QS " on bad self (%s)", ++ ar.name, extramsg); ++ } ++ if (ar.name == NULL) ++ ar.name = "?"; ++ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", ++ narg, ar.name, extramsg); ++} ++ ++ ++LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { ++ const char *msg = lua_pushfstring(L, "%s expected, got %s", ++ tname, luaL_typename(L, narg)); ++ return luaL_argerror(L, narg, msg); ++} ++ ++ ++static void tag_error (lua_State *L, int narg, int tag) { ++ luaL_typerror(L, narg, lua_typename(L, tag)); ++} ++ ++ ++LUALIB_API void luaL_where (lua_State *L, int level) { ++ lua_Debug ar; ++ if (lua_getstack(L, level, &ar)) { /* check function at level */ ++ lua_getinfo(L, "Sl", &ar); /* get info about it */ ++ if (ar.currentline > 0) { /* is there info? */ ++ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); ++ return; ++ } ++ } ++ lua_pushliteral(L, ""); /* else, no information available... */ ++} ++ ++ ++LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { ++ va_list argp; ++ va_start(argp, fmt); ++ luaL_where(L, 1); ++ lua_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ lua_concat(L, 2); ++ return lua_error(L); ++} ++ ++/* }====================================================== */ ++ ++ ++LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, ++ const char *const lst[]) { ++ const char *name = (def) ? luaL_optstring(L, narg, def) : ++ luaL_checkstring(L, narg); ++ int i; ++ for (i=0; lst[i]; i++) ++ if (strcmp(lst[i], name) == 0) ++ return i; ++ return luaL_argerror(L, narg, ++ lua_pushfstring(L, "invalid option " LUA_QS, name)); ++} ++ ++ ++LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { ++ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ ++ if (!lua_isnil(L, -1)) /* name already in use? */ ++ return 0; /* leave previous value on top, but return 0 */ ++ lua_pop(L, 1); ++ lua_newtable(L); /* create metatable */ ++ lua_pushvalue(L, -1); ++ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ ++ return 1; ++} ++ ++ ++LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { ++ void *p = lua_touserdata(L, ud); ++ if (p != NULL) { /* value is a userdata? */ ++ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ ++ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ ++ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ ++ lua_pop(L, 2); /* remove both metatables */ ++ return p; ++ } ++ } ++ } ++ luaL_typerror(L, ud, tname); /* else error */ ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { ++ if (!lua_checkstack(L, space)) ++ luaL_error(L, "stack overflow (%s)", mes); ++} ++ ++ ++LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { ++ if (lua_type(L, narg) != t) ++ tag_error(L, narg, t); ++} ++ ++ ++LUALIB_API void luaL_checkany (lua_State *L, int narg) { ++ if (lua_type(L, narg) == LUA_TNONE) ++ luaL_argerror(L, narg, "value expected"); ++} ++ ++ ++LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { ++ const char *s = lua_tolstring(L, narg, len); ++ if (!s) tag_error(L, narg, LUA_TSTRING); ++ return s; ++} ++ ++ ++LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, ++ const char *def, size_t *len) { ++ if (lua_isnoneornil(L, narg)) { ++ if (len) ++ *len = (def ? strlen(def) : 0); ++ return def; ++ } ++ else return luaL_checklstring(L, narg, len); ++} ++ ++ ++LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { ++ lua_Number d = lua_tonumber(L, narg); ++ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return d; ++} ++ ++ ++LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { ++ return luaL_opt(L, luaL_checknumber, narg, def); ++} ++ ++ ++LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { ++ lua_Integer d = lua_tointeger(L, narg); ++ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return d; ++} ++ ++ ++LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, ++ lua_Integer def) { ++ return luaL_opt(L, luaL_checkinteger, narg, def); ++} ++ ++ ++LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { ++ if (!lua_getmetatable(L, obj)) /* no metatable? */ ++ return 0; ++ lua_pushstring(L, event); ++ lua_rawget(L, -2); ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 2); /* remove metatable and metafield */ ++ return 0; ++ } ++ else { ++ lua_remove(L, -2); /* remove only metatable */ ++ return 1; ++ } ++} ++ ++ ++LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { ++ obj = abs_index(L, obj); ++ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ ++ return 0; ++ lua_pushvalue(L, obj); ++ lua_call(L, 1, 1); ++ return 1; ++} ++ ++ ++LUALIB_API void (luaL_register) (lua_State *L, const char *libname, ++ const luaL_Reg *l) { ++ luaI_openlib(L, libname, l, 0); ++} ++ ++ ++static int libsize (const luaL_Reg *l) { ++ int size = 0; ++ for (; l->name; l++) size++; ++ return size; ++} ++ ++ ++LUALIB_API void luaI_openlib (lua_State *L, const char *libname, ++ const luaL_Reg *l, int nup) { ++ if (libname) { ++ int size = libsize(l); ++ /* check whether lib already exists */ ++ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); ++ lua_getfield(L, -1, libname); /* get _LOADED[libname] */ ++ if (!lua_istable(L, -1)) { /* not found? */ ++ lua_pop(L, 1); /* remove previous result */ ++ /* try global variable (and create one if it does not exist) */ ++ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) ++ luaL_error(L, "name conflict for module " LUA_QS, libname); ++ lua_pushvalue(L, -1); ++ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ ++ } ++ lua_remove(L, -2); /* remove _LOADED table */ ++ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ ++ } ++ for (; l->name; l++) { ++ int i; ++ for (i=0; ifunc, nup); ++ lua_setfield(L, -(nup+2), l->name); ++ } ++ lua_pop(L, nup); /* remove upvalues */ ++} ++ ++ ++ ++/* ++** {====================================================== ++** getn-setn: size for arrays ++** ======================================================= ++*/ ++ ++#if defined(LUA_COMPAT_GETN) ++ ++static int checkint (lua_State *L, int topop) { ++ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; ++ lua_pop(L, topop); ++ return n; ++} ++ ++ ++static void getsizes (lua_State *L) { ++ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); ++ if (lua_isnil(L, -1)) { /* no `size' table? */ ++ lua_pop(L, 1); /* remove nil */ ++ lua_newtable(L); /* create it */ ++ lua_pushvalue(L, -1); /* `size' will be its own metatable */ ++ lua_setmetatable(L, -2); ++ lua_pushliteral(L, "kv"); ++ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ ++ lua_pushvalue(L, -1); ++ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ ++ } ++} ++ ++ ++LUALIB_API void luaL_setn (lua_State *L, int t, int n) { ++ t = abs_index(L, t); ++ lua_pushliteral(L, "n"); ++ lua_rawget(L, t); ++ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ ++ lua_pushliteral(L, "n"); /* use it */ ++ lua_pushinteger(L, n); ++ lua_rawset(L, t); ++ } ++ else { /* use `sizes' */ ++ getsizes(L); ++ lua_pushvalue(L, t); ++ lua_pushinteger(L, n); ++ lua_rawset(L, -3); /* sizes[t] = n */ ++ lua_pop(L, 1); /* remove `sizes' */ ++ } ++} ++ ++ ++LUALIB_API int luaL_getn (lua_State *L, int t) { ++ int n; ++ t = abs_index(L, t); ++ lua_pushliteral(L, "n"); /* try t.n */ ++ lua_rawget(L, t); ++ if ((n = checkint(L, 1)) >= 0) return n; ++ getsizes(L); /* else try sizes[t] */ ++ lua_pushvalue(L, t); ++ lua_rawget(L, -2); ++ if ((n = checkint(L, 2)) >= 0) return n; ++ return (int)lua_objlen(L, t); ++} ++ ++#endif ++ ++/* }====================================================== */ ++ ++ ++ ++LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, ++ const char *r) { ++ const char *wild; ++ size_t l = strlen(p); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "luaL_gsub: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while ((wild = strstr(s, p)) != NULL) { ++ luaL_addlstring(b, s, wild - s); /* push prefix */ ++ luaL_addstring(b, r); /* push replacement in place of pattern */ ++ s = wild + l; /* continue after `p' */ ++ } ++ luaL_addstring(b, s); /* push last suffix */ ++ luaL_pushresult(b); ++ kfree(b); ++ return lua_tostring(L, -1); ++} ++ ++ ++LUALIB_API const char *luaL_findtable (lua_State *L, int idx, ++ const char *fname, int szhint) { ++ const char *e; ++ lua_pushvalue(L, idx); ++ do { ++ e = strchr(fname, '.'); ++ if (e == NULL) e = fname + strlen(fname); ++ lua_pushlstring(L, fname, e - fname); ++ lua_rawget(L, -2); ++ if (lua_isnil(L, -1)) { /* no such field? */ ++ lua_pop(L, 1); /* remove this nil */ ++ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ ++ lua_pushlstring(L, fname, e - fname); ++ lua_pushvalue(L, -2); ++ lua_settable(L, -4); /* set new table into field */ ++ } ++ else if (!lua_istable(L, -1)) { /* field has a non-table value? */ ++ lua_pop(L, 2); /* remove table and value */ ++ return fname; /* return problematic part of the name */ ++ } ++ lua_remove(L, -2); /* remove previous table */ ++ fname = e + 1; ++ } while (*e == '.'); ++ return NULL; ++} ++ ++ ++ ++/* ++** {====================================================== ++** Generic Buffer manipulation ++** ======================================================= ++*/ ++ ++ ++#define bufflen(B) ((B)->p - (B)->buffer) ++#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) ++ ++#define LIMIT (LUA_MINSTACK/2) ++ ++ ++static int emptybuffer (luaL_Buffer *B) { ++ size_t l = bufflen(B); ++ if (l == 0) return 0; /* put nothing on stack */ ++ else { ++ lua_pushlstring(B->L, B->buffer, l); ++ B->p = B->buffer; ++ B->lvl++; ++ return 1; ++ } ++} ++ ++ ++static void adjuststack (luaL_Buffer *B) { ++ if (B->lvl > 1) { ++ lua_State *L = B->L; ++ int toget = 1; /* number of levels to concat */ ++ size_t toplen = lua_strlen(L, -1); ++ do { ++ size_t l = lua_strlen(L, -(toget+1)); ++ if (B->lvl - toget + 1 >= LIMIT || toplen > l) { ++ toplen += l; ++ toget++; ++ } ++ else break; ++ } while (toget < B->lvl); ++ lua_concat(L, toget); ++ B->lvl = B->lvl - toget + 1; ++ } ++} ++ ++ ++LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { ++ if (emptybuffer(B)) ++ adjuststack(B); ++ return B->buffer; ++} ++ ++ ++LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { ++ while (l--) ++ luaL_addchar(B, *s++); ++} ++ ++ ++LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { ++ luaL_addlstring(B, s, strlen(s)); ++} ++ ++ ++LUALIB_API void luaL_pushresult (luaL_Buffer *B) { ++ emptybuffer(B); ++ lua_concat(B->L, B->lvl); ++ B->lvl = 1; ++} ++ ++ ++LUALIB_API void luaL_addvalue (luaL_Buffer *B) { ++ lua_State *L = B->L; ++ size_t vl; ++ const char *s = lua_tolstring(L, -1, &vl); ++ if (vl <= bufffree(B)) { /* fit into buffer? */ ++ memcpy(B->p, s, vl); /* put it there */ ++ B->p += vl; ++ lua_pop(L, 1); /* remove from stack */ ++ } ++ else { ++ if (emptybuffer(B)) ++ lua_insert(L, -2); /* put buffer before new value */ ++ B->lvl++; /* add new value into B stack */ ++ adjuststack(B); ++ } ++} ++ ++ ++LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { ++ B->L = L; ++ B->p = B->buffer; ++ B->lvl = 0; ++} ++ ++/* }====================================================== */ ++ ++ ++LUALIB_API int luaL_ref (lua_State *L, int t) { ++ int ref; ++ t = abs_index(L, t); ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* remove from stack */ ++ return LUA_REFNIL; /* `nil' has a unique fixed reference */ ++ } ++ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ ++ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ ++ lua_pop(L, 1); /* remove it from stack */ ++ if (ref != 0) { /* any free element? */ ++ lua_rawgeti(L, t, ref); /* remove it from list */ ++ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ ++ } ++ else { /* no free elements */ ++ ref = (int)lua_objlen(L, t); ++ ref++; /* create new reference */ ++ } ++ lua_rawseti(L, t, ref); ++ return ref; ++} ++ ++ ++LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { ++ if (ref >= 0) { ++ t = abs_index(L, t); ++ lua_rawgeti(L, t, FREELIST_REF); ++ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ ++ lua_pushinteger(L, ref); ++ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ ++ } ++} ++ ++ ++ ++/* ++** {====================================================== ++** Load functions ++** ======================================================= ++*/ ++ ++#if !defined(__KERNEL__) ++typedef struct LoadF { ++ int extraline; ++ FILE *f; ++ char buff[LUAL_BUFFERSIZE]; ++} LoadF; ++ ++ ++static const char *getF (lua_State *L, void *ud, size_t *size) { ++ LoadF *lf = (LoadF *)ud; ++ (void)L; ++ if (lf->extraline) { ++ lf->extraline = 0; ++ *size = 1; ++ return "\n"; ++ } ++ if (feof(lf->f)) return NULL; ++ *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); ++ return (*size > 0) ? lf->buff : NULL; ++} ++ ++ ++static int errfile (lua_State *L, const char *what, int fnameindex) { ++ const char *serr = strerror(errno); ++ const char *filename = lua_tostring(L, fnameindex) + 1; ++ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); ++ lua_remove(L, fnameindex); ++ return LUA_ERRFILE; ++} ++ ++ ++LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { ++ LoadF lf; ++ int status, readstatus; ++ int c; ++ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ ++ lf.extraline = 0; ++ if (filename == NULL) { ++ lua_pushliteral(L, "=stdin"); ++ lf.f = stdin; ++ } ++ else { ++ lua_pushfstring(L, "@%s", filename); ++ lf.f = fopen(filename, "r"); ++ if (lf.f == NULL) return errfile(L, "open", fnameindex); ++ } ++ c = getc(lf.f); ++ if (c == '#') { /* Unix exec. file? */ ++ lf.extraline = 1; ++ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ ++ if (c == '\n') c = getc(lf.f); ++ } ++ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ ++ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ ++ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); ++ /* skip eventual `#!...' */ ++ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; ++ lf.extraline = 0; ++ } ++ ungetc(c, lf.f); ++ status = lua_load(L, getF, &lf, lua_tostring(L, -1)); ++ readstatus = ferror(lf.f); ++ if (filename) fclose(lf.f); /* close file (even in case of errors) */ ++ if (readstatus) { ++ lua_settop(L, fnameindex); /* ignore results from `lua_load' */ ++ return errfile(L, "read", fnameindex); ++ } ++ lua_remove(L, fnameindex); ++ return status; ++} ++#endif ++ ++typedef struct LoadS { ++ const char *s; ++ size_t size; ++} LoadS; ++ ++ ++static const char *getS (lua_State *L, void *ud, size_t *size) { ++ LoadS *ls = (LoadS *)ud; ++ (void)L; ++ if (ls->size == 0) return NULL; ++ *size = ls->size; ++ ls->size = 0; ++ return ls->s; ++} ++ ++ ++LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, ++ const char *name) { ++ LoadS ls; ++ ls.s = buff; ++ ls.size = size; ++ return lua_load(L, getS, &ls, name); ++} ++ ++ ++LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { ++ return luaL_loadbuffer(L, s, strlen(s), s); ++} ++ ++ ++ ++/* }====================================================== */ ++ ++ ++static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { ++ (void)ud; ++ (void)osize; ++ if (nsize == 0) { ++#if !defined(__KERNEL__) ++ free(ptr); ++#else ++ kfree(ptr); ++#endif ++ return NULL; ++ } ++ else ++#if !defined(__KERNEL__) ++ return realloc(ptr, nsize); ++#else ++ return krealloc(ptr, nsize, GFP_ATOMIC); ++#endif ++} ++ ++ ++static int lpanic (lua_State *L) { ++ (void)L; /* to avoid warnings */ ++#if !defined(__KERNEL__) ++ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", ++#else ++ printk( "PANIC: unprotected error in call to Lua API (%s)\n", ++#endif ++ lua_tostring(L, -1)); ++ return 0; ++} ++ ++ ++LUALIB_API lua_State *luaL_newstate (void) { ++ lua_State *L = lua_newstate(l_alloc, NULL); ++ if (L) lua_atpanic(L, &lpanic); ++ return L; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lauxlib.h +@@ -0,0 +1,184 @@ ++/* ++** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions for building Lua libraries ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lauxlib_h ++#define lauxlib_h ++ ++ ++#include ++#include /* for kmalloc and kfree when allocating luaL_Buffer */ ++ ++#if !defined(__KERNEL__) ++#include ++#endif ++ ++#include "lua.h" ++ ++ ++#if defined(LUA_COMPAT_GETN) ++LUALIB_API int (luaL_getn) (lua_State *L, int t); ++LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); ++#else ++#define luaL_getn(L,i) ((int)lua_objlen(L, i)) ++#define luaL_setn(L,i,j) ((void)0) /* no op! */ ++#endif ++ ++#if defined(LUA_COMPAT_OPENLIB) ++#define luaI_openlib luaL_openlib ++#endif ++ ++ ++/* extra error code for `luaL_load' */ ++#define LUA_ERRFILE (LUA_ERRERR+1) ++ ++ ++typedef struct luaL_Reg { ++ const char *name; ++ lua_CFunction func; ++} luaL_Reg; ++ ++ ++ ++LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, ++ const luaL_Reg *l, int nup); ++LUALIB_API void (luaL_register) (lua_State *L, const char *libname, ++ const luaL_Reg *l); ++LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); ++LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); ++LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); ++LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); ++LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, ++ size_t *l); ++LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, ++ const char *def, size_t *l); ++LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); ++LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); ++ ++LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); ++LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, ++ lua_Integer def); ++ ++LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); ++LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); ++LUALIB_API void (luaL_checkany) (lua_State *L, int narg); ++ ++LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); ++LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); ++ ++LUALIB_API void (luaL_where) (lua_State *L, int lvl); ++LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); ++ ++LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, ++ const char *const lst[]); ++ ++LUALIB_API int (luaL_ref) (lua_State *L, int t); ++LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); ++ ++#if !defined(__KERNEL__) ++LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); ++#endif ++ ++LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, ++ const char *name); ++LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); ++ ++LUALIB_API lua_State *(luaL_newstate) (void); ++ ++ ++LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, ++ const char *r); ++ ++LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, ++ const char *fname, int szhint); ++ ++ ++ ++ ++/* ++** =============================================================== ++** some useful macros ++** =============================================================== ++*/ ++ ++#define luaL_argcheck(L, cond,numarg,extramsg) \ ++ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) ++#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) ++#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) ++#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) ++#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) ++#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) ++#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) ++ ++#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) ++ ++#if !defined(__KERNEL__) ++#define luaL_dofile(L, fn) \ ++ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) ++#endif ++ ++#define luaL_dostring(L, s) \ ++ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) ++ ++#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) ++ ++#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) ++ ++/* ++** {====================================================== ++** Generic Buffer manipulation ++** ======================================================= ++*/ ++ ++ ++ ++typedef struct luaL_Buffer { ++ char *p; /* current position in buffer */ ++ int lvl; /* number of strings in the stack (level) */ ++ lua_State *L; ++ char buffer[LUAL_BUFFERSIZE]; ++} luaL_Buffer; ++ ++#define luaL_addchar(B,c) \ ++ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ ++ (*(B)->p++ = (char)(c))) ++ ++/* compatibility only */ ++#define luaL_putchar(B,c) luaL_addchar(B,c) ++ ++#define luaL_addsize(B,n) ((B)->p += (n)) ++ ++ ++LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); ++LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); ++LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); ++LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); ++LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); ++LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); ++ ++ ++/* }====================================================== */ ++ ++ ++/* compatibility with ref system */ ++ ++/* pre-defined references */ ++#define LUA_NOREF (-2) ++#define LUA_REFNIL (-1) ++ ++#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ ++ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) ++ ++#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) ++ ++#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) ++ ++ ++#define luaL_reg luaL_Reg ++ ++#endif ++ ++ +--- /dev/null ++++ b/extensions/LUA/lua/lbaselib.c +@@ -0,0 +1,647 @@ ++/* ++** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ ++** Basic library ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++#include ++#include ++ ++#define lbaselib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++ ++ ++/* ++** If your system does not support `stdout', you can just remove this function. ++** If you need, you can define your own `print' function, following this ++** model but changing `fputs' to put the strings at a proper place ++** (a console window or a log file, for instance). ++*/ ++static int luaB_print (lua_State *L) { ++ int n = lua_gettop(L); /* number of arguments */ ++ int i; ++ lua_getglobal(L, "tostring"); ++ for (i=1; i<=n; i++) { ++ const char *s; ++ lua_pushvalue(L, -1); /* function to be called */ ++ lua_pushvalue(L, i); /* value to print */ ++ lua_call(L, 1, 1); ++ s = lua_tostring(L, -1); /* get result */ ++ if (s == NULL) ++ return luaL_error(L, LUA_QL("tostring") " must return a string to " ++ LUA_QL("print")); ++ printk(KERN_INFO "LUA[print]: %s", s); ++ lua_pop(L, 1); /* pop result */ ++ } ++ return 0; ++} ++ ++ ++static int luaB_tonumber (lua_State *L) { ++ int base = luaL_optint(L, 2, 10); ++ if (base == 10) { /* standard conversion */ ++ luaL_checkany(L, 1); ++ if (lua_isnumber(L, 1)) { ++ lua_pushnumber(L, lua_tonumber(L, 1)); ++ return 1; ++ } ++ } ++ else { ++ const char *s1 = luaL_checkstring(L, 1); ++ char *s2; ++ unsigned long n; ++ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); ++ n = simple_strtoul(s1, &s2, base); ++ if (s1 != s2) { /* at least one valid digit? */ ++ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ ++ if (*s2 == '\0') { /* no invalid trailing characters? */ ++ lua_pushnumber(L, (lua_Number)n); ++ return 1; ++ } ++ } ++ } ++ lua_pushnil(L); /* else not a number */ ++ return 1; ++} ++ ++ ++static int luaB_error (lua_State *L) { ++ int level = luaL_optint(L, 2, 1); ++ lua_settop(L, 1); ++ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ ++ luaL_where(L, level); ++ lua_pushvalue(L, 1); ++ lua_concat(L, 2); ++ } ++ return lua_error(L); ++} ++ ++ ++static int luaB_getmetatable (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (!lua_getmetatable(L, 1)) { ++ lua_pushnil(L); ++ return 1; /* no metatable */ ++ } ++ luaL_getmetafield(L, 1, "__metatable"); ++ return 1; /* returns either __metatable field (if present) or metatable */ ++} ++ ++ ++static int luaB_setmetatable (lua_State *L) { ++ int t = lua_type(L, 2); ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, ++ "nil or table expected"); ++ if (luaL_getmetafield(L, 1, "__metatable")) ++ luaL_error(L, "cannot change a protected metatable"); ++ lua_settop(L, 2); ++ lua_setmetatable(L, 1); ++ return 1; ++} ++ ++ ++static void getfunc (lua_State *L, int opt) { ++ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); ++ else { ++ lua_Debug ar; ++ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); ++ luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); ++ if (lua_getstack(L, level, &ar) == 0) ++ luaL_argerror(L, 1, "invalid level"); ++ lua_getinfo(L, "f", &ar); ++ if (lua_isnil(L, -1)) ++ luaL_error(L, "no function environment for tail call at level %d", ++ level); ++ } ++} ++ ++ ++static int luaB_getfenv (lua_State *L) { ++ getfunc(L, 1); ++ if (lua_iscfunction(L, -1)) /* is a C function? */ ++ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ ++ else ++ lua_getfenv(L, -1); ++ return 1; ++} ++ ++ ++static int luaB_setfenv (lua_State *L) { ++ luaL_checktype(L, 2, LUA_TTABLE); ++ getfunc(L, 0); ++ lua_pushvalue(L, 2); ++ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { ++ /* change environment of current thread */ ++ lua_pushthread(L); ++ lua_insert(L, -2); ++ lua_setfenv(L, -2); ++ return 0; ++ } ++ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) ++ luaL_error(L, ++ LUA_QL("setfenv") " cannot change environment of given object"); ++ return 1; ++} ++ ++ ++static int luaB_rawequal (lua_State *L) { ++ luaL_checkany(L, 1); ++ luaL_checkany(L, 2); ++ lua_pushboolean(L, lua_rawequal(L, 1, 2)); ++ return 1; ++} ++ ++ ++static int luaB_rawget (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checkany(L, 2); ++ lua_settop(L, 2); ++ lua_rawget(L, 1); ++ return 1; ++} ++ ++static int luaB_rawset (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checkany(L, 2); ++ luaL_checkany(L, 3); ++ lua_settop(L, 3); ++ lua_rawset(L, 1); ++ return 1; ++} ++ ++ ++static int luaB_gcinfo (lua_State *L) { ++ lua_pushinteger(L, lua_getgccount(L)); ++ return 1; ++} ++ ++static int luaB_collectgarbage (lua_State *L) { ++ static const char *const opts[] = {"stop", "restart", "collect", ++ "count", "step", "setpause", "setstepmul", NULL}; ++ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, ++ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; ++ int o = luaL_checkoption(L, 1, "collect", opts); ++ int ex = luaL_optint(L, 2, 0); ++ int res = lua_gc(L, optsnum[o], ex); ++ switch (optsnum[o]) { ++ case LUA_GCCOUNT: { ++ int b = lua_gc(L, LUA_GCCOUNTB, 0); ++ lua_pushnumber(L, res + ((lua_Number)b/1024)); ++ return 1; ++ } ++ case LUA_GCSTEP: { ++ lua_pushboolean(L, res); ++ return 1; ++ } ++ default: { ++ lua_pushnumber(L, res); ++ return 1; ++ } ++ } ++} ++ ++ ++static int luaB_type (lua_State *L) { ++ luaL_checkany(L, 1); ++ lua_pushstring(L, luaL_typename(L, 1)); ++ return 1; ++} ++ ++ ++static int luaB_next (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_settop(L, 2); /* create a 2nd argument if there isn't one */ ++ if (lua_next(L, 1)) ++ return 2; ++ else { ++ lua_pushnil(L); ++ return 1; ++ } ++} ++ ++ ++static int luaB_pairs (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ ++ lua_pushvalue(L, 1); /* state, */ ++ lua_pushnil(L); /* and initial value */ ++ return 3; ++} ++ ++ ++static int ipairsaux (lua_State *L) { ++ int i = luaL_checkint(L, 2); ++ luaL_checktype(L, 1, LUA_TTABLE); ++ i++; /* next value */ ++ lua_pushinteger(L, i); ++ lua_rawgeti(L, 1, i); ++ return (lua_isnil(L, -1)) ? 0 : 2; ++} ++ ++ ++static int luaB_ipairs (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ ++ lua_pushvalue(L, 1); /* state, */ ++ lua_pushinteger(L, 0); /* and initial value */ ++ return 3; ++} ++ ++ ++static int load_aux (lua_State *L, int status) { ++ if (status == 0) /* OK? */ ++ return 1; ++ else { ++ lua_pushnil(L); ++ lua_insert(L, -2); /* put before error message */ ++ return 2; /* return nil plus error message */ ++ } ++} ++ ++ ++static int luaB_loadstring (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ const char *chunkname = luaL_optstring(L, 2, s); ++ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); ++} ++ ++/* ++static int luaB_loadfile (lua_State *L) { ++ const char *fname = luaL_optstring(L, 1, NULL); ++ return load_aux(L, luaL_loadfile(L, fname)); ++} ++*/ ++ ++/* ++** Reader for generic `load' function: `lua_load' uses the ++** stack for internal stuff, so the reader cannot change the ++** stack top. Instead, it keeps its resulting string in a ++** reserved slot inside the stack. ++*/ ++static const char *generic_reader (lua_State *L, void *ud, size_t *size) { ++ (void)ud; /* to avoid warnings */ ++ luaL_checkstack(L, 2, "too many nested functions"); ++ lua_pushvalue(L, 1); /* get function */ ++ lua_call(L, 0, 1); /* call it */ ++ if (lua_isnil(L, -1)) { ++ *size = 0; ++ return NULL; ++ } ++ else if (lua_isstring(L, -1)) { ++ lua_replace(L, 3); /* save string in a reserved stack slot */ ++ return lua_tolstring(L, 3, size); ++ } ++ else luaL_error(L, "reader function must return a string"); ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++static int luaB_load (lua_State *L) { ++ int status; ++ const char *cname = luaL_optstring(L, 2, "=(load)"); ++ luaL_checktype(L, 1, LUA_TFUNCTION); ++ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ ++ status = lua_load(L, generic_reader, NULL, cname); ++ return load_aux(L, status); ++} ++ ++/* ++static int luaB_dofile (lua_State *L) { ++ const char *fname = luaL_optstring(L, 1, NULL); ++ int n = lua_gettop(L); ++ if (luaL_loadfile(L, fname) != 0) lua_error(L); ++ lua_call(L, 0, LUA_MULTRET); ++ return lua_gettop(L) - n; ++} ++*/ ++ ++static int luaB_assert (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (!lua_toboolean(L, 1)) ++ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); ++ return lua_gettop(L); ++} ++ ++ ++static int luaB_unpack (lua_State *L) { ++ int i, e, n; ++ luaL_checktype(L, 1, LUA_TTABLE); ++ i = luaL_optint(L, 2, 1); ++ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); ++ if (i > e) return 0; /* empty range */ ++ n = e - i + 1; /* number of elements */ ++ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ ++ return luaL_error(L, "too many results to unpack"); ++ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ ++ while (i++ < e) /* push arg[i + 1...e] */ ++ lua_rawgeti(L, 1, i); ++ return n; ++} ++ ++ ++static int luaB_select (lua_State *L) { ++ int n = lua_gettop(L); ++ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { ++ lua_pushinteger(L, n-1); ++ return 1; ++ } ++ else { ++ int i = luaL_checkint(L, 1); ++ if (i < 0) i = n + i; ++ else if (i > n) i = n; ++ luaL_argcheck(L, 1 <= i, 1, "index out of range"); ++ return n - i; ++ } ++} ++ ++ ++static int luaB_pcall (lua_State *L) { ++ int status; ++ luaL_checkany(L, 1); ++ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); ++ lua_pushboolean(L, (status == 0)); ++ lua_insert(L, 1); ++ return lua_gettop(L); /* return status + all results */ ++} ++ ++ ++static int luaB_xpcall (lua_State *L) { ++ int status; ++ luaL_checkany(L, 2); ++ lua_settop(L, 2); ++ lua_insert(L, 1); /* put error function under function to be called */ ++ status = lua_pcall(L, 0, LUA_MULTRET, 1); ++ lua_pushboolean(L, (status == 0)); ++ lua_replace(L, 1); ++ return lua_gettop(L); /* return status + all results */ ++} ++ ++ ++static int luaB_tostring (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ ++ return 1; /* use its value */ ++ switch (lua_type(L, 1)) { ++ case LUA_TNUMBER: ++ lua_pushstring(L, lua_tostring(L, 1)); ++ break; ++ case LUA_TSTRING: ++ lua_pushvalue(L, 1); ++ break; ++ case LUA_TBOOLEAN: ++ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); ++ break; ++ case LUA_TNIL: ++ lua_pushliteral(L, "nil"); ++ break; ++ default: ++ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); ++ break; ++ } ++ return 1; ++} ++ ++ ++static int luaB_newproxy (lua_State *L) { ++ lua_settop(L, 1); ++ lua_newuserdata(L, 0); /* create proxy */ ++ if (lua_toboolean(L, 1) == 0) ++ return 1; /* no metatable */ ++ else if (lua_isboolean(L, 1)) { ++ lua_newtable(L); /* create a new metatable `m' ... */ ++ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ ++ lua_pushboolean(L, 1); ++ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ ++ } ++ else { ++ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ ++ if (lua_getmetatable(L, 1)) { ++ lua_rawget(L, lua_upvalueindex(1)); ++ validproxy = lua_toboolean(L, -1); ++ lua_pop(L, 1); /* remove value */ ++ } ++ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); ++ lua_getmetatable(L, 1); /* metatable is valid; get it */ ++ } ++ lua_setmetatable(L, 2); ++ return 1; ++} ++ ++ ++static const luaL_Reg base_funcs[] = { ++ {"assert", luaB_assert}, ++ {"collectgarbage", luaB_collectgarbage}, ++// {"dofile", luaB_dofile}, ++ {"error", luaB_error}, ++ {"gcinfo", luaB_gcinfo}, ++ {"getfenv", luaB_getfenv}, ++ {"getmetatable", luaB_getmetatable}, ++// {"loadfile", luaB_loadfile}, ++ {"load", luaB_load}, ++ {"loadstring", luaB_loadstring}, ++ {"next", luaB_next}, ++ {"pcall", luaB_pcall}, ++ {"print", luaB_print}, ++ {"rawequal", luaB_rawequal}, ++ {"rawget", luaB_rawget}, ++ {"rawset", luaB_rawset}, ++ {"select", luaB_select}, ++ {"setfenv", luaB_setfenv}, ++ {"setmetatable", luaB_setmetatable}, ++ {"tonumber", luaB_tonumber}, ++ {"tostring", luaB_tostring}, ++ {"type", luaB_type}, ++ {"unpack", luaB_unpack}, ++ {"xpcall", luaB_xpcall}, ++ {NULL, NULL} ++}; ++ ++ ++/* ++** {====================================================== ++** Coroutine library ++** ======================================================= ++*/ ++ ++#define CO_RUN 0 /* running */ ++#define CO_SUS 1 /* suspended */ ++#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ ++#define CO_DEAD 3 ++ ++static const char *const statnames[] = ++ {"running", "suspended", "normal", "dead"}; ++ ++static int costatus (lua_State *L, lua_State *co) { ++ if (L == co) return CO_RUN; ++ switch (lua_status(co)) { ++ case LUA_YIELD: ++ return CO_SUS; ++ case 0: { ++ lua_Debug ar; ++ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ ++ return CO_NOR; /* it is running */ ++ else if (lua_gettop(co) == 0) ++ return CO_DEAD; ++ else ++ return CO_SUS; /* initial state */ ++ } ++ default: /* some error occured */ ++ return CO_DEAD; ++ } ++} ++ ++ ++static int luaB_costatus (lua_State *L) { ++ lua_State *co = lua_tothread(L, 1); ++ luaL_argcheck(L, co, 1, "coroutine expected"); ++ lua_pushstring(L, statnames[costatus(L, co)]); ++ return 1; ++} ++ ++ ++static int auxresume (lua_State *L, lua_State *co, int narg) { ++ int status = costatus(L, co); ++ if (!lua_checkstack(co, narg)) ++ luaL_error(L, "too many arguments to resume"); ++ if (status != CO_SUS) { ++ lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); ++ return -1; /* error flag */ ++ } ++ lua_xmove(L, co, narg); ++ lua_setlevel(L, co); ++ status = lua_resume(co, narg); ++ if (status == 0 || status == LUA_YIELD) { ++ int nres = lua_gettop(co); ++ if (!lua_checkstack(L, nres + 1)) ++ luaL_error(L, "too many results to resume"); ++ lua_xmove(co, L, nres); /* move yielded values */ ++ return nres; ++ } ++ else { ++ lua_xmove(co, L, 1); /* move error message */ ++ return -1; /* error flag */ ++ } ++} ++ ++ ++static int luaB_coresume (lua_State *L) { ++ lua_State *co = lua_tothread(L, 1); ++ int r; ++ luaL_argcheck(L, co, 1, "coroutine expected"); ++ r = auxresume(L, co, lua_gettop(L) - 1); ++ if (r < 0) { ++ lua_pushboolean(L, 0); ++ lua_insert(L, -2); ++ return 2; /* return false + error message */ ++ } ++ else { ++ lua_pushboolean(L, 1); ++ lua_insert(L, -(r + 1)); ++ return r + 1; /* return true + `resume' returns */ ++ } ++} ++ ++ ++static int luaB_auxwrap (lua_State *L) { ++ lua_State *co = lua_tothread(L, lua_upvalueindex(1)); ++ int r = auxresume(L, co, lua_gettop(L)); ++ if (r < 0) { ++ if (lua_isstring(L, -1)) { /* error object is a string? */ ++ luaL_where(L, 1); /* add extra info */ ++ lua_insert(L, -2); ++ lua_concat(L, 2); ++ } ++ lua_error(L); /* propagate error */ ++ } ++ return r; ++} ++ ++ ++static int luaB_cocreate (lua_State *L) { ++ lua_State *NL = lua_newthread(L); ++ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, ++ "Lua function expected"); ++ lua_pushvalue(L, 1); /* move function to top */ ++ lua_xmove(L, NL, 1); /* move function from L to NL */ ++ return 1; ++} ++ ++ ++static int luaB_cowrap (lua_State *L) { ++ luaB_cocreate(L); ++ lua_pushcclosure(L, luaB_auxwrap, 1); ++ return 1; ++} ++ ++ ++static int luaB_yield (lua_State *L) { ++ return lua_yield(L, lua_gettop(L)); ++} ++ ++ ++static int luaB_corunning (lua_State *L) { ++ if (lua_pushthread(L)) ++ lua_pushnil(L); /* main thread is not a coroutine */ ++ return 1; ++} ++ ++ ++static const luaL_Reg co_funcs[] = { ++ {"create", luaB_cocreate}, ++ {"resume", luaB_coresume}, ++ {"running", luaB_corunning}, ++ {"status", luaB_costatus}, ++ {"wrap", luaB_cowrap}, ++ {"yield", luaB_yield}, ++ {NULL, NULL} ++}; ++ ++/* }====================================================== */ ++ ++ ++static void auxopen (lua_State *L, const char *name, ++ lua_CFunction f, lua_CFunction u) { ++ lua_pushcfunction(L, u); ++ lua_pushcclosure(L, f, 1); ++ lua_setfield(L, -2, name); ++} ++ ++ ++static void base_open (lua_State *L) { ++ /* set global _G */ ++ lua_pushvalue(L, LUA_GLOBALSINDEX); ++ lua_setglobal(L, "_G"); ++ /* open lib into global table */ ++ luaL_register(L, "_G", base_funcs); ++ lua_pushliteral(L, LUA_VERSION); ++ lua_setglobal(L, "_VERSION"); /* set global _VERSION */ ++ /* `ipairs' and `pairs' need auxliliary functions as upvalues */ ++ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); ++ auxopen(L, "pairs", luaB_pairs, luaB_next); ++ /* `newproxy' needs a weaktable as upvalue */ ++ lua_createtable(L, 0, 1); /* new table `w' */ ++ lua_pushvalue(L, -1); /* `w' will be its own metatable */ ++ lua_setmetatable(L, -2); ++ lua_pushliteral(L, "kv"); ++ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ ++ lua_pushcclosure(L, luaB_newproxy, 1); ++ lua_setglobal(L, "newproxy"); /* set global `newproxy' */ ++} ++ ++ ++LUALIB_API int luaopen_base (lua_State *L) { ++ base_open(L); ++ luaL_register(L, LUA_COLIBNAME, co_funcs); ++ return 2; ++} +--- /dev/null ++++ b/extensions/LUA/lua/lcode.c +@@ -0,0 +1,838 @@ ++/* ++** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Code generator for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lcode_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lgc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "ltable.h" ++ ++ ++#define hasjumps(e) ((e)->t != (e)->f) ++ ++ ++static int isnumeral(expdesc *e) { ++ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); ++} ++ ++ ++void luaK_nil (FuncState *fs, int from, int n) { ++ Instruction *previous; ++ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ ++ if (fs->pc == 0) { /* function start? */ ++ if (from >= fs->nactvar) ++ return; /* positions are already clean */ ++ } ++ else { ++ previous = &fs->f->code[fs->pc-1]; ++ if (GET_OPCODE(*previous) == OP_LOADNIL) { ++ int pfrom = GETARG_A(*previous); ++ int pto = GETARG_B(*previous); ++ if (pfrom <= from && from <= pto+1) { /* can connect both? */ ++ if (from+n-1 > pto) ++ SETARG_B(*previous, from+n-1); ++ return; ++ } ++ } ++ } ++ } ++ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ ++} ++ ++ ++int luaK_jump (FuncState *fs) { ++ int jpc = fs->jpc; /* save list of jumps to here */ ++ int j; ++ fs->jpc = NO_JUMP; ++ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); ++ luaK_concat(fs, &j, jpc); /* keep them on hold */ ++ return j; ++} ++ ++ ++void luaK_ret (FuncState *fs, int first, int nret) { ++ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); ++} ++ ++ ++static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { ++ luaK_codeABC(fs, op, A, B, C); ++ return luaK_jump(fs); ++} ++ ++ ++static void fixjump (FuncState *fs, int pc, int dest) { ++ Instruction *jmp = &fs->f->code[pc]; ++ int offset = dest-(pc+1); ++ lua_assert(dest != NO_JUMP); ++ if (abs(offset) > MAXARG_sBx) ++ luaX_syntaxerror(fs->ls, "control structure too long"); ++ SETARG_sBx(*jmp, offset); ++} ++ ++ ++/* ++** returns current `pc' and marks it as a jump target (to avoid wrong ++** optimizations with consecutive instructions not in the same basic block). ++*/ ++int luaK_getlabel (FuncState *fs) { ++ fs->lasttarget = fs->pc; ++ return fs->pc; ++} ++ ++ ++static int getjump (FuncState *fs, int pc) { ++ int offset = GETARG_sBx(fs->f->code[pc]); ++ if (offset == NO_JUMP) /* point to itself represents end of list */ ++ return NO_JUMP; /* end of list */ ++ else ++ return (pc+1)+offset; /* turn offset into absolute position */ ++} ++ ++ ++static Instruction *getjumpcontrol (FuncState *fs, int pc) { ++ Instruction *pi = &fs->f->code[pc]; ++ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) ++ return pi-1; ++ else ++ return pi; ++} ++ ++ ++/* ++** check whether list has any jump that do not produce a value ++** (or produce an inverted value) ++*/ ++static int need_value (FuncState *fs, int list) { ++ for (; list != NO_JUMP; list = getjump(fs, list)) { ++ Instruction i = *getjumpcontrol(fs, list); ++ if (GET_OPCODE(i) != OP_TESTSET) return 1; ++ } ++ return 0; /* not found */ ++} ++ ++ ++static int patchtestreg (FuncState *fs, int node, int reg) { ++ Instruction *i = getjumpcontrol(fs, node); ++ if (GET_OPCODE(*i) != OP_TESTSET) ++ return 0; /* cannot patch other instructions */ ++ if (reg != NO_REG && reg != GETARG_B(*i)) ++ SETARG_A(*i, reg); ++ else /* no register to put value or register already has the value */ ++ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); ++ ++ return 1; ++} ++ ++ ++static void removevalues (FuncState *fs, int list) { ++ for (; list != NO_JUMP; list = getjump(fs, list)) ++ patchtestreg(fs, list, NO_REG); ++} ++ ++ ++static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, ++ int dtarget) { ++ while (list != NO_JUMP) { ++ int next = getjump(fs, list); ++ if (patchtestreg(fs, list, reg)) ++ fixjump(fs, list, vtarget); ++ else ++ fixjump(fs, list, dtarget); /* jump to default target */ ++ list = next; ++ } ++} ++ ++ ++static void dischargejpc (FuncState *fs) { ++ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); ++ fs->jpc = NO_JUMP; ++} ++ ++ ++void luaK_patchlist (FuncState *fs, int list, int target) { ++ if (target == fs->pc) ++ luaK_patchtohere(fs, list); ++ else { ++ lua_assert(target < fs->pc); ++ patchlistaux(fs, list, target, NO_REG, target); ++ } ++} ++ ++ ++void luaK_patchtohere (FuncState *fs, int list) { ++ luaK_getlabel(fs); ++ luaK_concat(fs, &fs->jpc, list); ++} ++ ++ ++void luaK_concat (FuncState *fs, int *l1, int l2) { ++ if (l2 == NO_JUMP) return; ++ else if (*l1 == NO_JUMP) ++ *l1 = l2; ++ else { ++ int list = *l1; ++ int next; ++ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ ++ list = next; ++ fixjump(fs, list, l2); ++ } ++} ++ ++ ++void luaK_checkstack (FuncState *fs, int n) { ++ int newstack = fs->freereg + n; ++ if (newstack > fs->f->maxstacksize) { ++ if (newstack >= MAXSTACK) ++ luaX_syntaxerror(fs->ls, "function or expression too complex"); ++ fs->f->maxstacksize = cast_byte(newstack); ++ } ++} ++ ++ ++void luaK_reserveregs (FuncState *fs, int n) { ++ luaK_checkstack(fs, n); ++ fs->freereg += n; ++} ++ ++ ++static void freereg (FuncState *fs, int reg) { ++ if (!ISK(reg) && reg >= fs->nactvar) { ++ fs->freereg--; ++ lua_assert(reg == fs->freereg); ++ } ++} ++ ++ ++static void freeexp (FuncState *fs, expdesc *e) { ++ if (e->k == VNONRELOC) ++ freereg(fs, e->u.s.info); ++} ++ ++ ++static int addk (FuncState *fs, TValue *k, TValue *v) { ++ lua_State *L = fs->L; ++ TValue *idx = luaH_set(L, fs->h, k); ++ Proto *f = fs->f; ++ int oldsize = f->sizek; ++ if (ttisnumber(idx)) { ++ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); ++ return cast_int(nvalue(idx)); ++ } ++ else { /* constant not found; create a new entry */ ++ setnvalue(idx, cast_num(fs->nk)); ++ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, ++ MAXARG_Bx, "constant table overflow"); ++ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); ++ setobj(L, &f->k[fs->nk], v); ++ luaC_barrier(L, f, v); ++ return fs->nk++; ++ } ++} ++ ++ ++int luaK_stringK (FuncState *fs, TString *s) { ++ TValue o; ++ setsvalue(fs->L, &o, s); ++ return addk(fs, &o, &o); ++} ++ ++ ++int luaK_numberK (FuncState *fs, lua_Number r) { ++ TValue o; ++ setnvalue(&o, r); ++ return addk(fs, &o, &o); ++} ++ ++ ++static int boolK (FuncState *fs, int b) { ++ TValue o; ++ setbvalue(&o, b); ++ return addk(fs, &o, &o); ++} ++ ++ ++static int nilK (FuncState *fs) { ++ TValue k, v; ++ setnilvalue(&v); ++ /* cannot use nil as key; instead use table itself to represent nil */ ++ sethvalue(fs->L, &k, fs->h); ++ return addk(fs, &k, &v); ++} ++ ++ ++void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { ++ if (e->k == VCALL) { /* expression is an open function call? */ ++ SETARG_C(getcode(fs, e), nresults+1); ++ } ++ else if (e->k == VVARARG) { ++ SETARG_B(getcode(fs, e), nresults+1); ++ SETARG_A(getcode(fs, e), fs->freereg); ++ luaK_reserveregs(fs, 1); ++ } ++} ++ ++ ++void luaK_setoneret (FuncState *fs, expdesc *e) { ++ if (e->k == VCALL) { /* expression is an open function call? */ ++ e->k = VNONRELOC; ++ e->u.s.info = GETARG_A(getcode(fs, e)); ++ } ++ else if (e->k == VVARARG) { ++ SETARG_B(getcode(fs, e), 2); ++ e->k = VRELOCABLE; /* can relocate its simple result */ ++ } ++} ++ ++ ++void luaK_dischargevars (FuncState *fs, expdesc *e) { ++ switch (e->k) { ++ case VLOCAL: { ++ e->k = VNONRELOC; ++ break; ++ } ++ case VUPVAL: { ++ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VGLOBAL: { ++ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VINDEXED: { ++ freereg(fs, e->u.s.aux); ++ freereg(fs, e->u.s.info); ++ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VVARARG: ++ case VCALL: { ++ luaK_setoneret(fs, e); ++ break; ++ } ++ default: break; /* there is one value available (somewhere) */ ++ } ++} ++ ++ ++static int code_label (FuncState *fs, int A, int b, int jump) { ++ luaK_getlabel(fs); /* those instructions may be jump targets */ ++ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); ++} ++ ++ ++static void discharge2reg (FuncState *fs, expdesc *e, int reg) { ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: { ++ luaK_nil(fs, reg, 1); ++ break; ++ } ++ case VFALSE: case VTRUE: { ++ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); ++ break; ++ } ++ case VK: { ++ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); ++ break; ++ } ++ case VKNUM: { ++ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); ++ break; ++ } ++ case VRELOCABLE: { ++ Instruction *pc = &getcode(fs, e); ++ SETARG_A(*pc, reg); ++ break; ++ } ++ case VNONRELOC: { ++ if (reg != e->u.s.info) ++ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); ++ break; ++ } ++ default: { ++ lua_assert(e->k == VVOID || e->k == VJMP); ++ return; /* nothing to do... */ ++ } ++ } ++ e->u.s.info = reg; ++ e->k = VNONRELOC; ++} ++ ++ ++static void discharge2anyreg (FuncState *fs, expdesc *e) { ++ if (e->k != VNONRELOC) { ++ luaK_reserveregs(fs, 1); ++ discharge2reg(fs, e, fs->freereg-1); ++ } ++} ++ ++ ++static void exp2reg (FuncState *fs, expdesc *e, int reg) { ++ discharge2reg(fs, e, reg); ++ if (e->k == VJMP) ++ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ ++ if (hasjumps(e)) { ++ int final; /* position after whole expression */ ++ int p_f = NO_JUMP; /* position of an eventual LOAD false */ ++ int p_t = NO_JUMP; /* position of an eventual LOAD true */ ++ if (need_value(fs, e->t) || need_value(fs, e->f)) { ++ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); ++ p_f = code_label(fs, reg, 0, 1); ++ p_t = code_label(fs, reg, 1, 0); ++ luaK_patchtohere(fs, fj); ++ } ++ final = luaK_getlabel(fs); ++ patchlistaux(fs, e->f, final, reg, p_f); ++ patchlistaux(fs, e->t, final, reg, p_t); ++ } ++ e->f = e->t = NO_JUMP; ++ e->u.s.info = reg; ++ e->k = VNONRELOC; ++} ++ ++ ++void luaK_exp2nextreg (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ freeexp(fs, e); ++ luaK_reserveregs(fs, 1); ++ exp2reg(fs, e, fs->freereg - 1); ++} ++ ++ ++int luaK_exp2anyreg (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ if (e->k == VNONRELOC) { ++ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ ++ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ ++ exp2reg(fs, e, e->u.s.info); /* put value on it */ ++ return e->u.s.info; ++ } ++ } ++ luaK_exp2nextreg(fs, e); /* default */ ++ return e->u.s.info; ++} ++ ++ ++void luaK_exp2val (FuncState *fs, expdesc *e) { ++ if (hasjumps(e)) ++ luaK_exp2anyreg(fs, e); ++ else ++ luaK_dischargevars(fs, e); ++} ++ ++ ++int luaK_exp2RK (FuncState *fs, expdesc *e) { ++ luaK_exp2val(fs, e); ++ switch (e->k) { ++ case VKNUM: ++ case VTRUE: ++ case VFALSE: ++ case VNIL: { ++ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ ++ e->u.s.info = (e->k == VNIL) ? nilK(fs) : ++ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : ++ boolK(fs, (e->k == VTRUE)); ++ e->k = VK; ++ return RKASK(e->u.s.info); ++ } ++ else break; ++ } ++ case VK: { ++ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ ++ return RKASK(e->u.s.info); ++ else break; ++ } ++ default: break; ++ } ++ /* not a constant in the right range: put it in a register */ ++ return luaK_exp2anyreg(fs, e); ++} ++ ++ ++void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { ++ switch (var->k) { ++ case VLOCAL: { ++ freeexp(fs, ex); ++ exp2reg(fs, ex, var->u.s.info); ++ return; ++ } ++ case VUPVAL: { ++ int e = luaK_exp2anyreg(fs, ex); ++ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); ++ break; ++ } ++ case VGLOBAL: { ++ int e = luaK_exp2anyreg(fs, ex); ++ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); ++ break; ++ } ++ case VINDEXED: { ++ int e = luaK_exp2RK(fs, ex); ++ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); ++ break; ++ } ++ default: { ++ lua_assert(0); /* invalid var kind to store */ ++ break; ++ } ++ } ++ freeexp(fs, ex); ++} ++ ++ ++void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { ++ int func; ++ luaK_exp2anyreg(fs, e); ++ freeexp(fs, e); ++ func = fs->freereg; ++ luaK_reserveregs(fs, 2); ++ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); ++ freeexp(fs, key); ++ e->u.s.info = func; ++ e->k = VNONRELOC; ++} ++ ++ ++static void invertjump (FuncState *fs, expdesc *e) { ++ Instruction *pc = getjumpcontrol(fs, e->u.s.info); ++ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && ++ GET_OPCODE(*pc) != OP_TEST); ++ SETARG_A(*pc, !(GETARG_A(*pc))); ++} ++ ++ ++static int jumponcond (FuncState *fs, expdesc *e, int cond) { ++ if (e->k == VRELOCABLE) { ++ Instruction ie = getcode(fs, e); ++ if (GET_OPCODE(ie) == OP_NOT) { ++ fs->pc--; /* remove previous OP_NOT */ ++ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); ++ } ++ /* else go through */ ++ } ++ discharge2anyreg(fs, e); ++ freeexp(fs, e); ++ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); ++} ++ ++ ++void luaK_goiftrue (FuncState *fs, expdesc *e) { ++ int pc; /* pc of last jump */ ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VK: case VKNUM: case VTRUE: { ++ pc = NO_JUMP; /* always true; do nothing */ ++ break; ++ } ++ case VFALSE: { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ case VJMP: { ++ invertjump(fs, e); ++ pc = e->u.s.info; ++ break; ++ } ++ default: { ++ pc = jumponcond(fs, e, 0); ++ break; ++ } ++ } ++ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ ++ luaK_patchtohere(fs, e->t); ++ e->t = NO_JUMP; ++} ++ ++ ++static void luaK_goiffalse (FuncState *fs, expdesc *e) { ++ int pc; /* pc of last jump */ ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: case VFALSE: { ++ pc = NO_JUMP; /* always false; do nothing */ ++ break; ++ } ++ case VTRUE: { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ case VJMP: { ++ pc = e->u.s.info; ++ break; ++ } ++ default: { ++ pc = jumponcond(fs, e, 1); ++ break; ++ } ++ } ++ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ ++ luaK_patchtohere(fs, e->f); ++ e->f = NO_JUMP; ++} ++ ++ ++static void codenot (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: case VFALSE: { ++ e->k = VTRUE; ++ break; ++ } ++ case VK: case VKNUM: case VTRUE: { ++ e->k = VFALSE; ++ break; ++ } ++ case VJMP: { ++ invertjump(fs, e); ++ break; ++ } ++ case VRELOCABLE: ++ case VNONRELOC: { ++ discharge2anyreg(fs, e); ++ freeexp(fs, e); ++ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); ++ e->k = VRELOCABLE; ++ break; ++ } ++ default: { ++ lua_assert(0); /* cannot happen */ ++ break; ++ } ++ } ++ /* interchange true and false lists */ ++ { int temp = e->f; e->f = e->t; e->t = temp; } ++ removevalues(fs, e->f); ++ removevalues(fs, e->t); ++} ++ ++ ++void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { ++ t->u.s.aux = luaK_exp2RK(fs, k); ++ t->k = VINDEXED; ++} ++ ++ ++static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { ++ lua_Number v1, v2, r; ++ if (!isnumeral(e1) || !isnumeral(e2)) return 0; ++ v1 = e1->u.nval; ++ v2 = e2->u.nval; ++ switch (op) { ++ case OP_ADD: r = luai_numadd(v1, v2); break; ++ case OP_SUB: r = luai_numsub(v1, v2); break; ++ case OP_MUL: r = luai_nummul(v1, v2); break; ++ case OP_DIV: ++ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++ r = luai_numdiv(v1, v2); break; ++ case OP_MOD: ++ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++ r = luai_nummod(v1, v2); break; ++ case OP_POW: r = luai_numpow(v1, v2); break; ++ case OP_UNM: r = luai_numunm(v1); break; ++ case OP_LEN: return 0; /* no constant folding for 'len' */ ++ default: lua_assert(0); r = 0; break; ++ } ++ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ ++ e1->u.nval = r; ++ return 1; ++} ++ ++ ++static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { ++ if (constfolding(op, e1, e2)) ++ return; ++ else { ++ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; ++ int o1 = luaK_exp2RK(fs, e1); ++ if (o1 > o2) { ++ freeexp(fs, e1); ++ freeexp(fs, e2); ++ } ++ else { ++ freeexp(fs, e2); ++ freeexp(fs, e1); ++ } ++ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); ++ e1->k = VRELOCABLE; ++ } ++} ++ ++ ++static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, ++ expdesc *e2) { ++ int o1 = luaK_exp2RK(fs, e1); ++ int o2 = luaK_exp2RK(fs, e2); ++ freeexp(fs, e2); ++ freeexp(fs, e1); ++ if (cond == 0 && op != OP_EQ) { ++ int temp; /* exchange args to replace by `<' or `<=' */ ++ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ ++ cond = 1; ++ } ++ e1->u.s.info = condjump(fs, op, cond, o1, o2); ++ e1->k = VJMP; ++} ++ ++ ++void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { ++ expdesc e2; ++ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; ++ switch (op) { ++ case OPR_MINUS: { ++ if (!isnumeral(e)) ++ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ ++ codearith(fs, OP_UNM, e, &e2); ++ break; ++ } ++ case OPR_NOT: codenot(fs, e); break; ++ case OPR_LEN: { ++ luaK_exp2anyreg(fs, e); /* cannot operate on constants */ ++ codearith(fs, OP_LEN, e, &e2); ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { ++ switch (op) { ++ case OPR_AND: { ++ luaK_goiftrue(fs, v); ++ break; ++ } ++ case OPR_OR: { ++ luaK_goiffalse(fs, v); ++ break; ++ } ++ case OPR_CONCAT: { ++ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ ++ break; ++ } ++ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: ++ case OPR_MOD: case OPR_POW: { ++ if (!isnumeral(v)) luaK_exp2RK(fs, v); ++ break; ++ } ++ default: { ++ luaK_exp2RK(fs, v); ++ break; ++ } ++ } ++} ++ ++ ++void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { ++ switch (op) { ++ case OPR_AND: { ++ lua_assert(e1->t == NO_JUMP); /* list must be closed */ ++ luaK_dischargevars(fs, e2); ++ luaK_concat(fs, &e2->f, e1->f); ++ *e1 = *e2; ++ break; ++ } ++ case OPR_OR: { ++ lua_assert(e1->f == NO_JUMP); /* list must be closed */ ++ luaK_dischargevars(fs, e2); ++ luaK_concat(fs, &e2->t, e1->t); ++ *e1 = *e2; ++ break; ++ } ++ case OPR_CONCAT: { ++ luaK_exp2val(fs, e2); ++ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { ++ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); ++ freeexp(fs, e1); ++ SETARG_B(getcode(fs, e2), e1->u.s.info); ++ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; ++ } ++ else { ++ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ ++ codearith(fs, OP_CONCAT, e1, e2); ++ } ++ break; ++ } ++ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; ++ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; ++ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; ++ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; ++ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; ++ case OPR_POW: codearith(fs, OP_POW, e1, e2); break; ++ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; ++ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; ++ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; ++ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; ++ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; ++ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; ++ default: lua_assert(0); ++ } ++} ++ ++ ++void luaK_fixline (FuncState *fs, int line) { ++ fs->f->lineinfo[fs->pc - 1] = line; ++} ++ ++ ++static int luaK_code (FuncState *fs, Instruction i, int line) { ++ Proto *f = fs->f; ++ dischargejpc(fs); /* `pc' will change */ ++ /* put new instruction in code array */ ++ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, ++ MAX_INT, "code size overflow"); ++ f->code[fs->pc] = i; ++ /* save corresponding line information */ ++ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, ++ MAX_INT, "code size overflow"); ++ f->lineinfo[fs->pc] = line; ++ return fs->pc++; ++} ++ ++ ++int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { ++ lua_assert(getOpMode(o) == iABC); ++ lua_assert(getBMode(o) != OpArgN || b == 0); ++ lua_assert(getCMode(o) != OpArgN || c == 0); ++ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); ++} ++ ++ ++int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { ++ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); ++ lua_assert(getCMode(o) == OpArgN); ++ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); ++} ++ ++ ++void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { ++ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; ++ int b = (tostore == LUA_MULTRET) ? 0 : tostore; ++ lua_assert(tostore != 0); ++ if (c <= MAXARG_C) ++ luaK_codeABC(fs, OP_SETLIST, base, b, c); ++ else { ++ luaK_codeABC(fs, OP_SETLIST, base, b, 0); ++ luaK_code(fs, cast(Instruction, c), fs->ls->lastline); ++ } ++ fs->freereg = base + 1; /* free registers with list values */ ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lcode.h +@@ -0,0 +1,76 @@ ++/* ++** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Code generator for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lcode_h ++#define lcode_h ++ ++#include "llex.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++ ++ ++/* ++** Marks the end of a patch list. It is an invalid value both as an absolute ++** address, and as a list link (would link an element to itself). ++*/ ++#define NO_JUMP (-1) ++ ++ ++/* ++** grep "ORDER OPR" if you change these enums ++*/ ++typedef enum BinOpr { ++ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, ++ OPR_CONCAT, ++ OPR_NE, OPR_EQ, ++ OPR_LT, OPR_LE, OPR_GT, OPR_GE, ++ OPR_AND, OPR_OR, ++ OPR_NOBINOPR ++} BinOpr; ++ ++ ++typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; ++ ++ ++#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) ++ ++#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) ++ ++#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) ++ ++LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); ++LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); ++LUAI_FUNC void luaK_fixline (FuncState *fs, int line); ++LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); ++LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); ++LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); ++LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); ++LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); ++LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); ++LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); ++LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); ++LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); ++LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_jump (FuncState *fs); ++LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); ++LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); ++LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); ++LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); ++LUAI_FUNC int luaK_getlabel (FuncState *fs); ++LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); ++LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); ++LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); ++LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ldebug.c +@@ -0,0 +1,636 @@ ++/* ++** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ ++** Debug Interface ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++#include ++ ++#define ldebug_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lapi.h" ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lvm.h" ++ ++ ++ ++static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); ++ ++ ++static int currentpc (lua_State *L, CallInfo *ci) { ++ if (!isLua(ci)) return -1; /* function is not a Lua function? */ ++ if (ci == L->ci) ++ ci->savedpc = L->savedpc; ++ return pcRel(ci->savedpc, ci_func(ci)->l.p); ++} ++ ++ ++static int currentline (lua_State *L, CallInfo *ci) { ++ int pc = currentpc(L, ci); ++ if (pc < 0) ++ return -1; /* only active lua functions have current-line information */ ++ else ++ return getline(ci_func(ci)->l.p, pc); ++} ++ ++ ++/* ++** this function can be called asynchronous (e.g. during a signal) ++*/ ++LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { ++ if (func == NULL || mask == 0) { /* turn off hooks? */ ++ mask = 0; ++ func = NULL; ++ } ++ L->hook = func; ++ L->basehookcount = count; ++ resethookcount(L); ++ L->hookmask = cast_byte(mask); ++ return 1; ++} ++ ++ ++LUA_API lua_Hook lua_gethook (lua_State *L) { ++ return L->hook; ++} ++ ++ ++LUA_API int lua_gethookmask (lua_State *L) { ++ return L->hookmask; ++} ++ ++ ++LUA_API int lua_gethookcount (lua_State *L) { ++ return L->basehookcount; ++} ++ ++ ++LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { ++ int status; ++ CallInfo *ci; ++ lua_lock(L); ++ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { ++ level--; ++ if (f_isLua(ci)) /* Lua function? */ ++ level -= ci->tailcalls; /* skip lost tail calls */ ++ } ++ if (level == 0 && ci > L->base_ci) { /* level found? */ ++ status = 1; ++ ar->i_ci = cast_int(ci - L->base_ci); ++ } ++ else if (level < 0) { /* level is of a lost tail call? */ ++ status = 1; ++ ar->i_ci = 0; ++ } ++ else status = 0; /* no such level */ ++ lua_unlock(L); ++ return status; ++} ++ ++ ++static Proto *getluaproto (CallInfo *ci) { ++ return (isLua(ci) ? ci_func(ci)->l.p : NULL); ++} ++ ++ ++static const char *findlocal (lua_State *L, CallInfo *ci, int n) { ++ const char *name; ++ Proto *fp = getluaproto(ci); ++ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) ++ return name; /* is a local variable in a Lua function */ ++ else { ++ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; ++ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ ++ return "(*temporary)"; ++ else ++ return NULL; ++ } ++} ++ ++ ++LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { ++ CallInfo *ci = L->base_ci + ar->i_ci; ++ const char *name = findlocal(L, ci, n); ++ lua_lock(L); ++ if (name) ++ luaA_pushobject(L, ci->base + (n - 1)); ++ lua_unlock(L); ++ return name; ++} ++ ++ ++LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { ++ CallInfo *ci = L->base_ci + ar->i_ci; ++ const char *name = findlocal(L, ci, n); ++ lua_lock(L); ++ if (name) ++ setobjs2s(L, ci->base + (n - 1), L->top - 1); ++ L->top--; /* pop value */ ++ lua_unlock(L); ++ return name; ++} ++ ++ ++static void funcinfo (lua_Debug *ar, Closure *cl) { ++ if (cl->c.isC) { ++ ar->source = "=[C]"; ++ ar->linedefined = -1; ++ ar->lastlinedefined = -1; ++ ar->what = "C"; ++ } ++ else { ++ ar->source = getstr(cl->l.p->source); ++ ar->linedefined = cl->l.p->linedefined; ++ ar->lastlinedefined = cl->l.p->lastlinedefined; ++ ar->what = (ar->linedefined == 0) ? "main" : "Lua"; ++ } ++ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); ++} ++ ++ ++static void info_tailcall (lua_Debug *ar) { ++ ar->name = ar->namewhat = ""; ++ ar->what = "tail"; ++ ar->lastlinedefined = ar->linedefined = ar->currentline = -1; ++ ar->source = "=(tail call)"; ++ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); ++ ar->nups = 0; ++} ++ ++ ++static void collectvalidlines (lua_State *L, Closure *f) { ++ if (f == NULL || f->c.isC) { ++ setnilvalue(L->top); ++ } ++ else { ++ Table *t = luaH_new(L, 0, 0); ++ int *lineinfo = f->l.p->lineinfo; ++ int i; ++ for (i=0; il.p->sizelineinfo; i++) ++ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); ++ sethvalue(L, L->top, t); ++ } ++ incr_top(L); ++} ++ ++ ++static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, ++ Closure *f, CallInfo *ci) { ++ int status = 1; ++ if (f == NULL) { ++ info_tailcall(ar); ++ return status; ++ } ++ for (; *what; what++) { ++ switch (*what) { ++ case 'S': { ++ funcinfo(ar, f); ++ break; ++ } ++ case 'l': { ++ ar->currentline = (ci) ? currentline(L, ci) : -1; ++ break; ++ } ++ case 'u': { ++ ar->nups = f->c.nupvalues; ++ break; ++ } ++ case 'n': { ++ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; ++ if (ar->namewhat == NULL) { ++ ar->namewhat = ""; /* not found */ ++ ar->name = NULL; ++ } ++ break; ++ } ++ case 'L': ++ case 'f': /* handled by lua_getinfo */ ++ break; ++ default: status = 0; /* invalid option */ ++ } ++ } ++ return status; ++} ++ ++ ++LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { ++ int status; ++ Closure *f = NULL; ++ CallInfo *ci = NULL; ++ lua_lock(L); ++ if (*what == '>') { ++ StkId func = L->top - 1; ++ luai_apicheck(L, ttisfunction(func)); ++ what++; /* skip the '>' */ ++ f = clvalue(func); ++ L->top--; /* pop function */ ++ } ++ else if (ar->i_ci != 0) { /* no tail call? */ ++ ci = L->base_ci + ar->i_ci; ++ lua_assert(ttisfunction(ci->func)); ++ f = clvalue(ci->func); ++ } ++ status = auxgetinfo(L, what, ar, f, ci); ++ if (strchr(what, 'f')) { ++ if (f == NULL) setnilvalue(L->top); ++ else setclvalue(L, L->top, f); ++ incr_top(L); ++ } ++ if (strchr(what, 'L')) ++ collectvalidlines(L, f); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++/* ++** {====================================================== ++** Symbolic Execution and code checker ++** ======================================================= ++*/ ++ ++#define check(x) if (!(x)) return 0; ++ ++#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) ++ ++#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) ++ ++ ++ ++static int precheck (const Proto *pt) { ++ check(pt->maxstacksize <= MAXSTACK); ++ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); ++ check(!(pt->is_vararg & VARARG_NEEDSARG) || ++ (pt->is_vararg & VARARG_HASARG)); ++ check(pt->sizeupvalues <= pt->nups); ++ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); ++ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); ++ return 1; ++} ++ ++ ++#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) ++ ++int luaG_checkopenop (Instruction i) { ++ switch (GET_OPCODE(i)) { ++ case OP_CALL: ++ case OP_TAILCALL: ++ case OP_RETURN: ++ case OP_SETLIST: { ++ check(GETARG_B(i) == 0); ++ return 1; ++ } ++ default: return 0; /* invalid instruction after an open call */ ++ } ++} ++ ++ ++static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { ++ switch (mode) { ++ case OpArgN: check(r == 0); break; ++ case OpArgU: break; ++ case OpArgR: checkreg(pt, r); break; ++ case OpArgK: ++ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); ++ break; ++ } ++ return 1; ++} ++ ++ ++static Instruction symbexec (const Proto *pt, int lastpc, int reg) { ++ int pc; ++ int last; /* stores position of last instruction that changed `reg' */ ++ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ ++ check(precheck(pt)); ++ for (pc = 0; pc < lastpc; pc++) { ++ Instruction i = pt->code[pc]; ++ OpCode op = GET_OPCODE(i); ++ int a = GETARG_A(i); ++ int b = 0; ++ int c = 0; ++ check(op < NUM_OPCODES); ++ checkreg(pt, a); ++ switch (getOpMode(op)) { ++ case iABC: { ++ b = GETARG_B(i); ++ c = GETARG_C(i); ++ check(checkArgMode(pt, b, getBMode(op))); ++ check(checkArgMode(pt, c, getCMode(op))); ++ break; ++ } ++ case iABx: { ++ b = GETARG_Bx(i); ++ if (getBMode(op) == OpArgK) check(b < pt->sizek); ++ break; ++ } ++ case iAsBx: { ++ b = GETARG_sBx(i); ++ if (getBMode(op) == OpArgR) { ++ int dest = pc+1+b; ++ check(0 <= dest && dest < pt->sizecode); ++ if (dest > 0) { ++ int j; ++ /* check that it does not jump to a setlist count; this ++ is tricky, because the count from a previous setlist may ++ have the same value of an invalid setlist; so, we must ++ go all the way back to the first of them (if any) */ ++ for (j = 0; j < dest; j++) { ++ Instruction d = pt->code[dest-1-j]; ++ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; ++ } ++ /* if 'j' is even, previous value is not a setlist (even if ++ it looks like one) */ ++ check((j&1) == 0); ++ } ++ } ++ break; ++ } ++ } ++ if (testAMode(op)) { ++ if (a == reg) last = pc; /* change register `a' */ ++ } ++ if (testTMode(op)) { ++ check(pc+2 < pt->sizecode); /* check skip */ ++ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); ++ } ++ switch (op) { ++ case OP_LOADBOOL: { ++ if (c == 1) { /* does it jump? */ ++ check(pc+2 < pt->sizecode); /* check its jump */ ++ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || ++ GETARG_C(pt->code[pc+1]) != 0); ++ } ++ break; ++ } ++ case OP_LOADNIL: { ++ if (a <= reg && reg <= b) ++ last = pc; /* set registers from `a' to `b' */ ++ break; ++ } ++ case OP_GETUPVAL: ++ case OP_SETUPVAL: { ++ check(b < pt->nups); ++ break; ++ } ++ case OP_GETGLOBAL: ++ case OP_SETGLOBAL: { ++ check(ttisstring(&pt->k[b])); ++ break; ++ } ++ case OP_SELF: { ++ checkreg(pt, a+1); ++ if (reg == a+1) last = pc; ++ break; ++ } ++ case OP_CONCAT: { ++ check(b < c); /* at least two operands */ ++ break; ++ } ++ case OP_TFORLOOP: { ++ check(c >= 1); /* at least one result (control variable) */ ++ checkreg(pt, a+2+c); /* space for results */ ++ if (reg >= a+2) last = pc; /* affect all regs above its base */ ++ break; ++ } ++ case OP_FORLOOP: ++ case OP_FORPREP: ++ checkreg(pt, a+3); ++ fallthrough; ++ case OP_JMP: { ++ int dest = pc+1+b; ++ /* not full check and jump is forward and do not skip `lastpc'? */ ++ if (reg != NO_REG && pc < dest && dest <= lastpc) ++ pc += b; /* do the jump */ ++ break; ++ } ++ case OP_CALL: ++ case OP_TAILCALL: { ++ if (b != 0) { ++ checkreg(pt, a+b-1); ++ } ++ c--; /* c = num. returns */ ++ if (c == LUA_MULTRET) { ++ check(checkopenop(pt, pc)); ++ } ++ else if (c != 0) ++ checkreg(pt, a+c-1); ++ if (reg >= a) last = pc; /* affect all registers above base */ ++ break; ++ } ++ case OP_RETURN: { ++ b--; /* b = num. returns */ ++ if (b > 0) checkreg(pt, a+b-1); ++ break; ++ } ++ case OP_SETLIST: { ++ if (b > 0) checkreg(pt, a + b); ++ if (c == 0) { ++ pc++; ++ check(pc < pt->sizecode - 1); ++ } ++ break; ++ } ++ case OP_CLOSURE: { ++ int nup, j; ++ check(b < pt->sizep); ++ nup = pt->p[b]->nups; ++ check(pc + nup < pt->sizecode); ++ for (j = 1; j <= nup; j++) { ++ OpCode op1 = GET_OPCODE(pt->code[pc + j]); ++ check(op1 == OP_GETUPVAL || op1 == OP_MOVE); ++ } ++ if (reg != NO_REG) /* tracing? */ ++ pc += nup; /* do not 'execute' these pseudo-instructions */ ++ break; ++ } ++ case OP_VARARG: { ++ check((pt->is_vararg & VARARG_ISVARARG) && ++ !(pt->is_vararg & VARARG_NEEDSARG)); ++ b--; ++ if (b == LUA_MULTRET) check(checkopenop(pt, pc)); ++ checkreg(pt, a+b-1); ++ break; ++ } ++ default: break; ++ } ++ } ++ return pt->code[last]; ++} ++ ++#undef check ++#undef checkjump ++#undef checkreg ++ ++/* }====================================================== */ ++ ++ ++int luaG_checkcode (const Proto *pt) { ++ return (symbexec(pt, pt->sizecode, NO_REG) != 0); ++} ++ ++ ++static const char *kname (Proto *p, int c) { ++ if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) ++ return svalue(&p->k[INDEXK(c)]); ++ else ++ return "?"; ++} ++ ++ ++static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, ++ const char **name) { ++ if (isLua(ci)) { /* a Lua function? */ ++ Proto *p = ci_func(ci)->l.p; ++ int pc = currentpc(L, ci); ++ Instruction i; ++ *name = luaF_getlocalname(p, stackpos+1, pc); ++ if (*name) /* is a local? */ ++ return "local"; ++ i = symbexec(p, pc, stackpos); /* try symbolic execution */ ++ lua_assert(pc != -1); ++ switch (GET_OPCODE(i)) { ++ case OP_GETGLOBAL: { ++ int g = GETARG_Bx(i); /* global index */ ++ lua_assert(ttisstring(&p->k[g])); ++ *name = svalue(&p->k[g]); ++ return "global"; ++ } ++ case OP_MOVE: { ++ int a = GETARG_A(i); ++ int b = GETARG_B(i); /* move from `b' to `a' */ ++ if (b < a) ++ return getobjname(L, ci, b, name); /* get name for `b' */ ++ break; ++ } ++ case OP_GETTABLE: { ++ int k = GETARG_C(i); /* key index */ ++ *name = kname(p, k); ++ return "field"; ++ } ++ case OP_GETUPVAL: { ++ int u = GETARG_B(i); /* upvalue index */ ++ *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; ++ return "upvalue"; ++ } ++ case OP_SELF: { ++ int k = GETARG_C(i); /* key index */ ++ *name = kname(p, k); ++ return "method"; ++ } ++ default: break; ++ } ++ } ++ return NULL; /* no useful name found */ ++} ++ ++ ++static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { ++ Instruction i; ++ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) ++ return NULL; /* calling function is not Lua (or is unknown) */ ++ ci--; /* calling function */ ++ i = ci_func(ci)->l.p->code[currentpc(L, ci)]; ++ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || ++ GET_OPCODE(i) == OP_TFORLOOP) ++ return getobjname(L, ci, GETARG_A(i), name); ++ else ++ return NULL; /* no useful name can be found */ ++} ++ ++ ++/* only ANSI way to check whether a pointer points to an array */ ++static int isinstack (CallInfo *ci, const TValue *o) { ++ StkId p; ++ for (p = ci->base; p < ci->top; p++) ++ if (o == p) return 1; ++ return 0; ++} ++ ++ ++void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { ++ const char *name = NULL; ++ const char *t = luaT_typenames[ttype(o)]; ++ const char *kind = (isinstack(L->ci, o)) ? ++ getobjname(L, L->ci, cast_int(o - L->base), &name) : ++ NULL; ++ if (kind) ++ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", ++ op, kind, name, t); ++ else ++ luaG_runerror(L, "attempt to %s a %s value", op, t); ++} ++ ++ ++void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { ++ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; ++ lua_assert(!ttisstring(p1) && !ttisnumber(p1)); ++ luaG_typeerror(L, p1, "concatenate"); ++} ++ ++ ++void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { ++ TValue temp; ++ if (luaV_tonumber(p1, &temp) == NULL) ++ p2 = p1; /* first operand is wrong */ ++ luaG_typeerror(L, p2, "perform arithmetic on"); ++} ++ ++ ++int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { ++ const char *t1 = luaT_typenames[ttype(p1)]; ++ const char *t2 = luaT_typenames[ttype(p2)]; ++ if (t1[2] == t2[2]) ++ luaG_runerror(L, "attempt to compare two %s values", t1); ++ else ++ luaG_runerror(L, "attempt to compare %s with %s", t1, t2); ++ return 0; ++} ++ ++ ++static void addinfo (lua_State *L, const char *msg) { ++ CallInfo *ci = L->ci; ++ if (isLua(ci)) { /* is Lua code? */ ++ char buff[LUA_IDSIZE]; /* add file:line information */ ++ int line = currentline(L, ci); ++ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); ++ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); ++ } ++} ++ ++ ++void luaG_errormsg (lua_State *L) { ++ if (L->errfunc != 0) { /* is there an error handling function? */ ++ StkId errfunc = restorestack(L, L->errfunc); ++ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); ++ setobjs2s(L, L->top, L->top - 1); /* move argument */ ++ setobjs2s(L, L->top - 1, errfunc); /* push function */ ++ incr_top(L); ++ luaD_call(L, L->top - 2, 1); /* call it */ ++ } ++ luaD_throw(L, LUA_ERRRUN); ++} ++ ++ ++void luaG_runerror (lua_State *L, const char *fmt, ...) { ++ va_list argp; ++ va_start(argp, fmt); ++ addinfo(L, luaO_pushvfstring(L, fmt, argp)); ++ va_end(argp); ++ luaG_errormsg(L); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldebug.h +@@ -0,0 +1,33 @@ ++/* ++** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions from Debug Interface module ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ldebug_h ++#define ldebug_h ++ ++ ++#include "lstate.h" ++ ++ ++#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) ++ ++#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) ++ ++#define resethookcount(L) (L->hookcount = L->basehookcount) ++ ++ ++LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, ++ const char *opname); ++LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); ++LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, ++ const TValue *p2); ++LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, ++ const TValue *p2); ++LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); ++LUAI_FUNC void luaG_errormsg (lua_State *L); ++LUAI_FUNC int luaG_checkcode (const Proto *pt); ++LUAI_FUNC int luaG_checkopenop (Instruction i); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ldo.c +@@ -0,0 +1,515 @@ ++/* ++** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ ++** Stack and Call structure of Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++ ++#define ldo_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lundump.h" ++#include "lvm.h" ++#include "lzio.h" ++ ++ ++ ++/* ++** {====================================================== ++** Error-recovery functions ++** ======================================================= ++*/ ++ ++ ++/* chain list of long jump buffers */ ++struct lua_longjmp { ++ struct lua_longjmp *previous; ++ luai_jmpbuf b; ++ volatile int status; /* error code */ ++}; ++ ++ ++void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { ++ switch (errcode) { ++ case LUA_ERRMEM: { ++ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); ++ break; ++ } ++ case LUA_ERRERR: { ++ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); ++ break; ++ } ++ case LUA_ERRSYNTAX: ++ case LUA_ERRRUN: { ++ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ ++ break; ++ } ++ } ++ L->top = oldtop + 1; ++} ++ ++ ++static void restore_stack_limit (lua_State *L) { ++ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); ++ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ ++ int inuse = cast_int(L->ci - L->base_ci); ++ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ ++ luaD_reallocCI(L, LUAI_MAXCALLS); ++ } ++} ++ ++ ++static void resetstack (lua_State *L, int status) { ++ L->ci = L->base_ci; ++ L->base = L->ci->base; ++ luaF_close(L, L->base); /* close eventual pending closures */ ++ luaD_seterrorobj(L, status, L->base); ++ L->nCcalls = L->baseCcalls; ++ L->allowhook = 1; ++ restore_stack_limit(L); ++ L->errfunc = 0; ++ L->errorJmp = NULL; ++} ++ ++ ++void luaD_throw (lua_State *L, int errcode) { ++ if (L->errorJmp) { ++ L->errorJmp->status = errcode; ++ LUAI_THROW(L, L->errorJmp); ++ } ++ else { ++ L->status = cast_byte(errcode); ++ if (G(L)->panic) { ++ resetstack(L, errcode); ++ lua_unlock(L); ++ G(L)->panic(L); ++ } ++ exit(EXIT_FAILURE); ++ } ++} ++ ++ ++int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ++ struct lua_longjmp lj; ++ lj.status = 0; ++ lj.previous = L->errorJmp; /* chain new error handler */ ++ L->errorJmp = &lj; ++ LUAI_TRY(L, &lj, ++ (*f)(L, ud); ++ ); ++ L->errorJmp = lj.previous; /* restore old error handler */ ++ return lj.status; ++} ++ ++/* }====================================================== */ ++ ++ ++static void correctstack (lua_State *L, TValue *oldstack) { ++ CallInfo *ci; ++ GCObject *up; ++ L->top = (L->top - oldstack) + L->stack; ++ for (up = L->openupval; up != NULL; up = up->gch.next) ++ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; ++ for (ci = L->base_ci; ci <= L->ci; ci++) { ++ ci->top = (ci->top - oldstack) + L->stack; ++ ci->base = (ci->base - oldstack) + L->stack; ++ ci->func = (ci->func - oldstack) + L->stack; ++ } ++ L->base = (L->base - oldstack) + L->stack; ++} ++ ++ ++void luaD_reallocstack (lua_State *L, int newsize) { ++ TValue *oldstack = L->stack; ++ int realsize = newsize + 1 + EXTRA_STACK; ++ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); ++ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); ++ L->stacksize = realsize; ++ L->stack_last = L->stack+newsize; ++ correctstack(L, oldstack); ++} ++ ++ ++void luaD_reallocCI (lua_State *L, int newsize) { ++ CallInfo *oldci = L->base_ci; ++ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); ++ L->size_ci = newsize; ++ L->ci = (L->ci - oldci) + L->base_ci; ++ L->end_ci = L->base_ci + L->size_ci - 1; ++} ++ ++ ++void luaD_growstack (lua_State *L, int n) { ++ if (n <= L->stacksize) /* double size is enough? */ ++ luaD_reallocstack(L, 2*L->stacksize); ++ else ++ luaD_reallocstack(L, L->stacksize + n); ++} ++ ++ ++static CallInfo *growCI (lua_State *L) { ++ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ ++ luaD_throw(L, LUA_ERRERR); ++ else { ++ luaD_reallocCI(L, 2*L->size_ci); ++ if (L->size_ci > LUAI_MAXCALLS) ++ luaG_runerror(L, "stack overflow"); ++ } ++ return ++L->ci; ++} ++ ++ ++void luaD_callhook (lua_State *L, int event, int line) { ++ lua_Hook hook = L->hook; ++ if (hook && L->allowhook) { ++ ptrdiff_t top = savestack(L, L->top); ++ ptrdiff_t ci_top = savestack(L, L->ci->top); ++ lua_Debug ar; ++ ar.event = event; ++ ar.currentline = line; ++ if (event == LUA_HOOKTAILRET) ++ ar.i_ci = 0; /* tail call; no debug information about it */ ++ else ++ ar.i_ci = cast_int(L->ci - L->base_ci); ++ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ++ L->ci->top = L->top + LUA_MINSTACK; ++ lua_assert(L->ci->top <= L->stack_last); ++ L->allowhook = 0; /* cannot call hooks inside a hook */ ++ lua_unlock(L); ++ (*hook)(L, &ar); ++ lua_lock(L); ++ lua_assert(!L->allowhook); ++ L->allowhook = 1; ++ L->ci->top = restorestack(L, ci_top); ++ L->top = restorestack(L, top); ++ } ++} ++ ++ ++static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { ++ int i; ++ int nfixargs = p->numparams; ++ Table *htab = NULL; ++ StkId base, fixed; ++ for (; actual < nfixargs; ++actual) ++ setnilvalue(L->top++); ++#if defined(LUA_COMPAT_VARARG) ++ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ ++ int nvar = actual - nfixargs; /* number of extra arguments */ ++ lua_assert(p->is_vararg & VARARG_HASARG); ++ luaC_checkGC(L); ++ htab = luaH_new(L, nvar, 1); /* create `arg' table */ ++ for (i=0; itop - nvar + i); ++ /* store counter in field `n' */ ++ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); ++ } ++#endif ++ /* move fixed parameters to final position */ ++ fixed = L->top - actual; /* first fixed argument */ ++ base = L->top; /* final position of first argument */ ++ for (i=0; itop++, fixed+i); ++ setnilvalue(fixed+i); ++ } ++ /* add `arg' parameter */ ++ if (htab) { ++ sethvalue(L, L->top++, htab); ++ lua_assert(iswhite(obj2gco(htab))); ++ } ++ return base; ++} ++ ++ ++static StkId tryfuncTM (lua_State *L, StkId func) { ++ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); ++ StkId p; ++ ptrdiff_t funcr = savestack(L, func); ++ if (!ttisfunction(tm)) ++ luaG_typeerror(L, func, "call"); ++ /* Open a hole inside the stack at `func' */ ++ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); ++ incr_top(L); ++ func = restorestack(L, funcr); /* previous call may change stack */ ++ setobj2s(L, func, tm); /* tag method is the new function to be called */ ++ return func; ++} ++ ++ ++ ++#define inc_ci(L) \ ++ ((L->ci == L->end_ci) ? growCI(L) : \ ++ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) ++ ++ ++int luaD_precall (lua_State *L, StkId func, int nresults) { ++ LClosure *cl; ++ ptrdiff_t funcr; ++ if (!ttisfunction(func)) /* `func' is not a function? */ ++ func = tryfuncTM(L, func); /* check the `function' tag method */ ++ funcr = savestack(L, func); ++ cl = &clvalue(func)->l; ++ L->ci->savedpc = L->savedpc; ++ if (!cl->isC) { /* Lua function? prepare its call */ ++ CallInfo *ci; ++ StkId st, base; ++ Proto *p = cl->p; ++ luaD_checkstack(L, p->maxstacksize); ++ func = restorestack(L, funcr); ++ if (!p->is_vararg) { /* no varargs? */ ++ base = func + 1; ++ if (L->top > base + p->numparams) ++ L->top = base + p->numparams; ++ } ++ else { /* vararg function */ ++ int nargs = cast_int(L->top - func) - 1; ++ base = adjust_varargs(L, p, nargs); ++ func = restorestack(L, funcr); /* previous call may change the stack */ ++ } ++ ci = inc_ci(L); /* now `enter' new function */ ++ ci->func = func; ++ L->base = ci->base = base; ++ ci->top = L->base + p->maxstacksize; ++ lua_assert(ci->top <= L->stack_last); ++ L->savedpc = p->code; /* starting point */ ++ ci->tailcalls = 0; ++ ci->nresults = nresults; ++ for (st = L->top; st < ci->top; st++) ++ setnilvalue(st); ++ L->top = ci->top; ++ if (L->hookmask & LUA_MASKCALL) { ++ L->savedpc++; /* hooks assume 'pc' is already incremented */ ++ luaD_callhook(L, LUA_HOOKCALL, -1); ++ L->savedpc--; /* correct 'pc' */ ++ } ++ return PCRLUA; ++ } ++ else { /* if is a C function, call it */ ++ CallInfo *ci; ++ int n; ++ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ++ ci = inc_ci(L); /* now `enter' new function */ ++ ci->func = restorestack(L, funcr); ++ L->base = ci->base = ci->func + 1; ++ ci->top = L->top + LUA_MINSTACK; ++ lua_assert(ci->top <= L->stack_last); ++ ci->nresults = nresults; ++ if (L->hookmask & LUA_MASKCALL) ++ luaD_callhook(L, LUA_HOOKCALL, -1); ++ lua_unlock(L); ++ n = (*curr_func(L)->c.f)(L); /* do the actual call */ ++ lua_lock(L); ++ if (n < 0) /* yielding? */ ++ return PCRYIELD; ++ else { ++ luaD_poscall(L, L->top - n); ++ return PCRC; ++ } ++ } ++} ++ ++ ++static StkId callrethooks (lua_State *L, StkId firstResult) { ++ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ ++ luaD_callhook(L, LUA_HOOKRET, -1); ++ if (f_isLua(L->ci)) { /* Lua function? */ ++ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ ++ luaD_callhook(L, LUA_HOOKTAILRET, -1); ++ } ++ return restorestack(L, fr); ++} ++ ++ ++int luaD_poscall (lua_State *L, StkId firstResult) { ++ StkId res; ++ int wanted, i; ++ CallInfo *ci; ++ if (L->hookmask & LUA_MASKRET) ++ firstResult = callrethooks(L, firstResult); ++ ci = L->ci--; ++ res = ci->func; /* res == final position of 1st result */ ++ wanted = ci->nresults; ++ L->base = (ci - 1)->base; /* restore base */ ++ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ ++ /* move results to correct place */ ++ for (i = wanted; i != 0 && firstResult < L->top; i--) ++ setobjs2s(L, res++, firstResult++); ++ while (i-- > 0) ++ setnilvalue(res++); ++ L->top = res; ++ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ ++} ++ ++ ++/* ++** Call a function (C or Lua). The function to be called is at *func. ++** The arguments are on the stack, right after the function. ++** When returns, all the results are on the stack, starting at the original ++** function position. ++*/ ++void luaD_call (lua_State *L, StkId func, int nResults) { ++ if (++L->nCcalls >= LUAI_MAXCCALLS) { ++ if (L->nCcalls == LUAI_MAXCCALLS) ++ luaG_runerror(L, "C stack overflow"); ++ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) ++ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ ++ } ++ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ ++ luaV_execute(L, 1); /* call it */ ++ L->nCcalls--; ++ luaC_checkGC(L); ++} ++ ++ ++static void resume (lua_State *L, void *ud) { ++ StkId firstArg = cast(StkId, ud); ++ CallInfo *ci = L->ci; ++ if (L->status == 0) { /* start coroutine? */ ++ lua_assert(ci == L->base_ci && firstArg > L->base); ++ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) ++ return; ++ } ++ else { /* resuming from previous yield */ ++ lua_assert(L->status == LUA_YIELD); ++ L->status = 0; ++ if (!f_isLua(ci)) { /* `common' yield? */ ++ /* finish interrupted execution of `OP_CALL' */ ++ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || ++ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); ++ if (luaD_poscall(L, firstArg)) /* complete it... */ ++ L->top = L->ci->top; /* and correct top if not multiple results */ ++ } ++ else /* yielded inside a hook: just continue its execution */ ++ L->base = L->ci->base; ++ } ++ luaV_execute(L, cast_int(L->ci - L->base_ci)); ++} ++ ++ ++static int resume_error (lua_State *L, const char *msg) { ++ L->top = L->ci->base; ++ setsvalue2s(L, L->top, luaS_new(L, msg)); ++ incr_top(L); ++ lua_unlock(L); ++ return LUA_ERRRUN; ++} ++ ++ ++LUA_API int lua_resume (lua_State *L, int nargs) { ++ int status; ++ lua_lock(L); ++ if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) ++ return resume_error(L, "cannot resume non-suspended coroutine"); ++ if (L->nCcalls >= LUAI_MAXCCALLS) ++ return resume_error(L, "C stack overflow"); ++ luai_userstateresume(L, nargs); ++ lua_assert(L->errfunc == 0); ++ L->baseCcalls = ++L->nCcalls; ++ status = luaD_rawrunprotected(L, resume, L->top - nargs); ++ if (status != 0) { /* error? */ ++ L->status = cast_byte(status); /* mark thread as `dead' */ ++ luaD_seterrorobj(L, status, L->top); ++ L->ci->top = L->top; ++ } ++ else { ++ lua_assert(L->nCcalls == L->baseCcalls); ++ status = L->status; ++ } ++ --L->nCcalls; ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_yield (lua_State *L, int nresults) { ++ luai_userstateyield(L, nresults); ++ lua_lock(L); ++ if (L->nCcalls > L->baseCcalls) ++ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); ++ L->base = L->top - nresults; /* protect stack slots below */ ++ L->status = LUA_YIELD; ++ lua_unlock(L); ++ return -1; ++} ++ ++ ++int luaD_pcall (lua_State *L, Pfunc func, void *u, ++ ptrdiff_t old_top, ptrdiff_t ef) { ++ int status; ++ unsigned short oldnCcalls = L->nCcalls; ++ ptrdiff_t old_ci = saveci(L, L->ci); ++ lu_byte old_allowhooks = L->allowhook; ++ ptrdiff_t old_errfunc = L->errfunc; ++ L->errfunc = ef; ++ status = luaD_rawrunprotected(L, func, u); ++ if (status != 0) { /* an error occurred? */ ++ StkId oldtop = restorestack(L, old_top); ++ luaF_close(L, oldtop); /* close eventual pending closures */ ++ luaD_seterrorobj(L, status, oldtop); ++ L->nCcalls = oldnCcalls; ++ L->ci = restoreci(L, old_ci); ++ L->base = L->ci->base; ++ L->savedpc = L->ci->savedpc; ++ L->allowhook = old_allowhooks; ++ restore_stack_limit(L); ++ } ++ L->errfunc = old_errfunc; ++ return status; ++} ++ ++ ++ ++/* ++** Execute a protected parser. ++*/ ++struct SParser { /* data to `f_parser' */ ++ ZIO *z; ++ Mbuffer buff; /* buffer to be used by the scanner */ ++ const char *name; ++}; ++ ++static void f_parser (lua_State *L, void *ud) { ++ int i; ++ Proto *tf; ++ Closure *cl; ++ struct SParser *p = cast(struct SParser *, ud); ++ int c = luaZ_lookahead(p->z); ++ luaC_checkGC(L); ++ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, ++ &p->buff, p->name); ++ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); ++ cl->l.p = tf; ++ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ ++ cl->l.upvals[i] = luaF_newupval(L); ++ setclvalue(L, L->top, cl); ++ incr_top(L); ++} ++ ++ ++int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { ++ struct SParser p; ++ int status; ++ p.z = z; p.name = name; ++ luaZ_initbuffer(L, &p.buff); ++ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); ++ luaZ_freebuffer(L, &p.buff); ++ return status; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldo.h +@@ -0,0 +1,57 @@ ++/* ++** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Stack and Call structure of Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ldo_h ++#define ldo_h ++ ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lzio.h" ++ ++ ++#define luaD_checkstack(L,n) \ ++ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ ++ luaD_growstack(L, n); \ ++ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); ++ ++ ++#define incr_top(L) {luaD_checkstack(L,1); L->top++;} ++ ++#define savestack(L,p) ((char *)(p) - (char *)L->stack) ++#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) ++ ++#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) ++#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) ++ ++ ++/* results from luaD_precall */ ++#define PCRLUA 0 /* initiated a call to a Lua function */ ++#define PCRC 1 /* did a call to a C function */ ++#define PCRYIELD 2 /* C funtion yielded */ ++ ++ ++/* type of protected functions, to be ran by `runprotected' */ ++typedef void (*Pfunc) (lua_State *L, void *ud); ++ ++LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); ++LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); ++LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); ++LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); ++LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ++ ptrdiff_t oldtop, ptrdiff_t ef); ++LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); ++LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); ++LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); ++LUAI_FUNC void luaD_growstack (lua_State *L, int n); ++ ++LUAI_FUNC void luaD_throw (lua_State *L, int errcode); ++LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); ++ ++LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldump.c +@@ -0,0 +1,164 @@ ++/* ++** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ++** save precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define ldump_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lundump.h" ++ ++typedef struct { ++ lua_State* L; ++ lua_Writer writer; ++ void* data; ++ int strip; ++ int status; ++} DumpState; ++ ++#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) ++#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) ++ ++static void DumpBlock(const void* b, size_t size, DumpState* D) ++{ ++ if (D->status==0) ++ { ++ lua_unlock(D->L); ++ D->status=(*D->writer)(D->L,b,size,D->data); ++ lua_lock(D->L); ++ } ++} ++ ++static void DumpChar(int y, DumpState* D) ++{ ++ char x=(char)y; ++ DumpVar(x,D); ++} ++ ++static void DumpInt(int x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ ++static void DumpNumber(lua_Number x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ ++static void DumpVector(const void* b, int n, size_t size, DumpState* D) ++{ ++ DumpInt(n,D); ++ DumpMem(b,n,size,D); ++} ++ ++static void DumpString(const TString* s, DumpState* D) ++{ ++ if (s==NULL) ++ { ++ size_t size=0; ++ DumpVar(size,D); ++ } ++ else ++ { ++ size_t size=s->tsv.len+1; /* include trailing '\0' */ ++ DumpVar(size,D); ++ DumpBlock(getstr(s),size,D); ++ } ++} ++ ++#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) ++ ++static void DumpFunction(const Proto* f, const TString* p, DumpState* D); ++ ++static void DumpConstants(const Proto* f, DumpState* D) ++{ ++ int i,n=f->sizek; ++ DumpInt(n,D); ++ for (i=0; ik[i]; ++ DumpChar(ttype(o),D); ++ switch (ttype(o)) ++ { ++ case LUA_TNIL: ++ break; ++ case LUA_TBOOLEAN: ++ DumpChar(bvalue(o),D); ++ break; ++ case LUA_TNUMBER: ++ DumpNumber(nvalue(o),D); ++ break; ++ case LUA_TSTRING: ++ DumpString(rawtsvalue(o),D); ++ break; ++ default: ++ lua_assert(0); /* cannot happen */ ++ break; ++ } ++ } ++ n=f->sizep; ++ DumpInt(n,D); ++ for (i=0; ip[i],f->source,D); ++} ++ ++static void DumpDebug(const Proto* f, DumpState* D) ++{ ++ int i,n; ++ n= (D->strip) ? 0 : f->sizelineinfo; ++ DumpVector(f->lineinfo,n,sizeof(int),D); ++ n= (D->strip) ? 0 : f->sizelocvars; ++ DumpInt(n,D); ++ for (i=0; ilocvars[i].varname,D); ++ DumpInt(f->locvars[i].startpc,D); ++ DumpInt(f->locvars[i].endpc,D); ++ } ++ n= (D->strip) ? 0 : f->sizeupvalues; ++ DumpInt(n,D); ++ for (i=0; iupvalues[i],D); ++} ++ ++static void DumpFunction(const Proto* f, const TString* p, DumpState* D) ++{ ++ DumpString((f->source==p || D->strip) ? NULL : f->source,D); ++ DumpInt(f->linedefined,D); ++ DumpInt(f->lastlinedefined,D); ++ DumpChar(f->nups,D); ++ DumpChar(f->numparams,D); ++ DumpChar(f->is_vararg,D); ++ DumpChar(f->maxstacksize,D); ++ DumpCode(f,D); ++ DumpConstants(f,D); ++ DumpDebug(f,D); ++} ++ ++static void DumpHeader(DumpState* D) ++{ ++ char h[LUAC_HEADERSIZE]; ++ luaU_header(h); ++ DumpBlock(h,LUAC_HEADERSIZE,D); ++} ++ ++/* ++** dump Lua function as precompiled chunk ++*/ ++int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) ++{ ++ DumpState D; ++ D.L=L; ++ D.writer=w; ++ D.data=data; ++ D.strip=strip; ++ D.status=0; ++ DumpHeader(&D); ++ DumpFunction(f,NULL,&D); ++ return D.status; ++} +--- /dev/null ++++ b/extensions/LUA/lua/lfunc.c +@@ -0,0 +1,174 @@ ++/* ++** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ ++** Auxiliary functions to manipulate prototypes and closures ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lfunc_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++ ++Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { ++ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); ++ luaC_link(L, obj2gco(c), LUA_TFUNCTION); ++ c->c.isC = 1; ++ c->c.env = e; ++ c->c.nupvalues = cast_byte(nelems); ++ return c; ++} ++ ++ ++Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { ++ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); ++ luaC_link(L, obj2gco(c), LUA_TFUNCTION); ++ c->l.isC = 0; ++ c->l.env = e; ++ c->l.nupvalues = cast_byte(nelems); ++ while (nelems--) c->l.upvals[nelems] = NULL; ++ return c; ++} ++ ++ ++UpVal *luaF_newupval (lua_State *L) { ++ UpVal *uv = luaM_new(L, UpVal); ++ luaC_link(L, obj2gco(uv), LUA_TUPVAL); ++ uv->v = &uv->u.value; ++ setnilvalue(uv->v); ++ return uv; ++} ++ ++ ++UpVal *luaF_findupval (lua_State *L, StkId level) { ++ global_State *g = G(L); ++ GCObject **pp = &L->openupval; ++ UpVal *p; ++ UpVal *uv; ++ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { ++ lua_assert(p->v != &p->u.value); ++ if (p->v == level) { /* found a corresponding upvalue? */ ++ if (isdead(g, obj2gco(p))) /* is it dead? */ ++ changewhite(obj2gco(p)); /* ressurect it */ ++ return p; ++ } ++ pp = &p->next; ++ } ++ uv = luaM_new(L, UpVal); /* not found: create a new one */ ++ uv->tt = LUA_TUPVAL; ++ uv->marked = luaC_white(g); ++ uv->v = level; /* current value lives in the stack */ ++ uv->next = *pp; /* chain it in the proper position */ ++ *pp = obj2gco(uv); ++ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ ++ uv->u.l.next = g->uvhead.u.l.next; ++ uv->u.l.next->u.l.prev = uv; ++ g->uvhead.u.l.next = uv; ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ return uv; ++} ++ ++ ++static void unlinkupval (UpVal *uv) { ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ ++ uv->u.l.prev->u.l.next = uv->u.l.next; ++} ++ ++ ++void luaF_freeupval (lua_State *L, UpVal *uv) { ++ if (uv->v != &uv->u.value) /* is it open? */ ++ unlinkupval(uv); /* remove from open list */ ++ luaM_free(L, uv); /* free upvalue */ ++} ++ ++ ++void luaF_close (lua_State *L, StkId level) { ++ UpVal *uv; ++ global_State *g = G(L); ++ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { ++ GCObject *o = obj2gco(uv); ++ lua_assert(!isblack(o) && uv->v != &uv->u.value); ++ L->openupval = uv->next; /* remove from `open' list */ ++ if (isdead(g, o)) ++ luaF_freeupval(L, uv); /* free upvalue */ ++ else { ++ unlinkupval(uv); ++ setobj(L, &uv->u.value, uv->v); ++ uv->v = &uv->u.value; /* now current value lives here */ ++ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ ++ } ++ } ++} ++ ++ ++Proto *luaF_newproto (lua_State *L) { ++ Proto *f = luaM_new(L, Proto); ++ luaC_link(L, obj2gco(f), LUA_TPROTO); ++ f->k = NULL; ++ f->sizek = 0; ++ f->p = NULL; ++ f->sizep = 0; ++ f->code = NULL; ++ f->sizecode = 0; ++ f->sizelineinfo = 0; ++ f->sizeupvalues = 0; ++ f->nups = 0; ++ f->upvalues = NULL; ++ f->numparams = 0; ++ f->is_vararg = 0; ++ f->maxstacksize = 0; ++ f->lineinfo = NULL; ++ f->sizelocvars = 0; ++ f->locvars = NULL; ++ f->linedefined = 0; ++ f->lastlinedefined = 0; ++ f->source = NULL; ++ return f; ++} ++ ++ ++void luaF_freeproto (lua_State *L, Proto *f) { ++ luaM_freearray(L, f->code, f->sizecode, Instruction); ++ luaM_freearray(L, f->p, f->sizep, Proto *); ++ luaM_freearray(L, f->k, f->sizek, TValue); ++ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); ++ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); ++ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); ++ luaM_free(L, f); ++} ++ ++ ++void luaF_freeclosure (lua_State *L, Closure *c) { ++ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : ++ sizeLclosure(c->l.nupvalues); ++ luaM_freemem(L, c, size); ++} ++ ++ ++/* ++** Look for n-th local variable at line `line' in function `func'. ++** Returns NULL if not found. ++*/ ++const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { ++ int i; ++ for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { ++ if (pc < f->locvars[i].endpc) { /* is variable active? */ ++ local_number--; ++ if (local_number == 0) ++ return getstr(f->locvars[i].varname); ++ } ++ } ++ return NULL; /* not found */ ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lfunc.h +@@ -0,0 +1,34 @@ ++/* ++** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions to manipulate prototypes and closures ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lfunc_h ++#define lfunc_h ++ ++ ++#include "lobject.h" ++ ++ ++#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ ++ cast(int, sizeof(TValue)*((n)-1))) ++ ++#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ ++ cast(int, sizeof(TValue *)*((n)-1))) ++ ++ ++LUAI_FUNC Proto *luaF_newproto (lua_State *L); ++LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); ++LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); ++LUAI_FUNC UpVal *luaF_newupval (lua_State *L); ++LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); ++LUAI_FUNC void luaF_close (lua_State *L, StkId level); ++LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); ++LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); ++LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); ++LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, ++ int pc); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lgc.c +@@ -0,0 +1,711 @@ ++/* ++** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Garbage Collector ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lgc_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++#define GCSTEPSIZE 1024u ++#define GCSWEEPMAX 40 ++#define GCSWEEPCOST 10 ++#define GCFINALIZECOST 100 ++ ++ ++#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) ++ ++#define makewhite(g,x) \ ++ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) ++ ++#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) ++#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) ++ ++#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) ++ ++ ++#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) ++#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) ++ ++ ++#define KEYWEAK bitmask(KEYWEAKBIT) ++#define VALUEWEAK bitmask(VALUEWEAKBIT) ++ ++ ++ ++#define markvalue(g,o) { checkconsistency(o); \ ++ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } ++ ++#define markobject(g,t) { if (iswhite(obj2gco(t))) \ ++ reallymarkobject(g, obj2gco(t)); } ++ ++ ++#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) ++ ++ ++static void removeentry (Node *n) { ++ lua_assert(ttisnil(gval(n))); ++ if (iscollectable(gkey(n))) ++ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ ++} ++ ++ ++static void reallymarkobject (global_State *g, GCObject *o) { ++ lua_assert(iswhite(o) && !isdead(g, o)); ++ white2gray(o); ++ switch (o->gch.tt) { ++ case LUA_TSTRING: { ++ return; ++ } ++ case LUA_TUSERDATA: { ++ Table *mt = gco2u(o)->metatable; ++ gray2black(o); /* udata are never gray */ ++ if (mt) markobject(g, mt); ++ markobject(g, gco2u(o)->env); ++ return; ++ } ++ case LUA_TUPVAL: { ++ UpVal *uv = gco2uv(o); ++ markvalue(g, uv->v); ++ if (uv->v == &uv->u.value) /* closed? */ ++ gray2black(o); /* open upvalues are never black */ ++ return; ++ } ++ case LUA_TFUNCTION: { ++ gco2cl(o)->c.gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TTABLE: { ++ gco2h(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TTHREAD: { ++ gco2th(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TPROTO: { ++ gco2p(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++static void marktmu (global_State *g) { ++ GCObject *u = g->tmudata; ++ if (u) { ++ do { ++ u = u->gch.next; ++ makewhite(g, u); /* may be marked, if left from previous GC */ ++ reallymarkobject(g, u); ++ } while (u != g->tmudata); ++ } ++} ++ ++ ++/* move `dead' udata that need finalization to list `tmudata' */ ++size_t luaC_separateudata (lua_State *L, int all) { ++ global_State *g = G(L); ++ size_t deadmem = 0; ++ GCObject **p = &g->mainthread->next; ++ GCObject *curr; ++ while ((curr = *p) != NULL) { ++ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) ++ p = &curr->gch.next; /* don't bother with them */ ++ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { ++ markfinalized(gco2u(curr)); /* don't need finalization */ ++ p = &curr->gch.next; ++ } ++ else { /* must call its gc method */ ++ deadmem += sizeudata(gco2u(curr)); ++ markfinalized(gco2u(curr)); ++ *p = curr->gch.next; ++ /* link `curr' at the end of `tmudata' list */ ++ if (g->tmudata == NULL) /* list is empty? */ ++ g->tmudata = curr->gch.next = curr; /* creates a circular list */ ++ else { ++ curr->gch.next = g->tmudata->gch.next; ++ g->tmudata->gch.next = curr; ++ g->tmudata = curr; ++ } ++ } ++ } ++ return deadmem; ++} ++ ++ ++static int traversetable (global_State *g, Table *h) { ++ int i; ++ int weakkey = 0; ++ int weakvalue = 0; ++ const TValue *mode; ++ if (h->metatable) ++ markobject(g, h->metatable); ++ mode = gfasttm(g, h->metatable, TM_MODE); ++ if (mode && ttisstring(mode)) { /* is there a weak mode? */ ++ weakkey = (strchr(svalue(mode), 'k') != NULL); ++ weakvalue = (strchr(svalue(mode), 'v') != NULL); ++ if (weakkey || weakvalue) { /* is really weak? */ ++ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ ++ h->marked |= cast_byte((weakkey << KEYWEAKBIT) | ++ (weakvalue << VALUEWEAKBIT)); ++ h->gclist = g->weak; /* must be cleared after GC, ... */ ++ g->weak = obj2gco(h); /* ... so put in the appropriate list */ ++ } ++ } ++ if (weakkey && weakvalue) return 1; ++ if (!weakvalue) { ++ i = h->sizearray; ++ while (i--) ++ markvalue(g, &h->array[i]); ++ } ++ i = sizenode(h); ++ while (i--) { ++ Node *n = gnode(h, i); ++ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); ++ if (ttisnil(gval(n))) ++ removeentry(n); /* remove empty entries */ ++ else { ++ lua_assert(!ttisnil(gkey(n))); ++ if (!weakkey) markvalue(g, gkey(n)); ++ if (!weakvalue) markvalue(g, gval(n)); ++ } ++ } ++ return weakkey || weakvalue; ++} ++ ++ ++/* ++** All marks are conditional because a GC may happen while the ++** prototype is still being created ++*/ ++static void traverseproto (global_State *g, Proto *f) { ++ int i; ++ if (f->source) stringmark(f->source); ++ for (i=0; isizek; i++) /* mark literals */ ++ markvalue(g, &f->k[i]); ++ for (i=0; isizeupvalues; i++) { /* mark upvalue names */ ++ if (f->upvalues[i]) ++ stringmark(f->upvalues[i]); ++ } ++ for (i=0; isizep; i++) { /* mark nested protos */ ++ if (f->p[i]) ++ markobject(g, f->p[i]); ++ } ++ for (i=0; isizelocvars; i++) { /* mark local-variable names */ ++ if (f->locvars[i].varname) ++ stringmark(f->locvars[i].varname); ++ } ++} ++ ++ ++ ++static void traverseclosure (global_State *g, Closure *cl) { ++ markobject(g, cl->c.env); ++ if (cl->c.isC) { ++ int i; ++ for (i=0; ic.nupvalues; i++) /* mark its upvalues */ ++ markvalue(g, &cl->c.upvalue[i]); ++ } ++ else { ++ int i; ++ lua_assert(cl->l.nupvalues == cl->l.p->nups); ++ markobject(g, cl->l.p); ++ for (i=0; il.nupvalues; i++) /* mark its upvalues */ ++ markobject(g, cl->l.upvals[i]); ++ } ++} ++ ++ ++static void checkstacksizes (lua_State *L, StkId max) { ++ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ ++ int s_used = cast_int(max - L->stack); /* part of stack in use */ ++ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ ++ return; /* do not touch the stacks */ ++ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) ++ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ ++ condhardstacktests(luaD_reallocCI(L, ci_used + 1)); ++ if (4*s_used < L->stacksize && ++ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) ++ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ ++ condhardstacktests(luaD_reallocstack(L, s_used)); ++} ++ ++ ++static void traversestack (global_State *g, lua_State *l) { ++ StkId o, lim; ++ CallInfo *ci; ++ markvalue(g, gt(l)); ++ lim = l->top; ++ for (ci = l->base_ci; ci <= l->ci; ci++) { ++ lua_assert(ci->top <= l->stack_last); ++ if (lim < ci->top) lim = ci->top; ++ } ++ for (o = l->stack; o < l->top; o++) ++ markvalue(g, o); ++ for (; o <= lim; o++) ++ setnilvalue(o); ++ checkstacksizes(l, lim); ++} ++ ++ ++/* ++** traverse one gray object, turning it to black. ++** Returns `quantity' traversed. ++*/ ++static l_mem propagatemark (global_State *g) { ++ GCObject *o = g->gray; ++ lua_assert(isgray(o)); ++ gray2black(o); ++ switch (o->gch.tt) { ++ case LUA_TTABLE: { ++ Table *h = gco2h(o); ++ g->gray = h->gclist; ++ if (traversetable(g, h)) /* table is weak? */ ++ black2gray(o); /* keep it gray */ ++ return sizeof(Table) + sizeof(TValue) * h->sizearray + ++ sizeof(Node) * sizenode(h); ++ } ++ case LUA_TFUNCTION: { ++ Closure *cl = gco2cl(o); ++ g->gray = cl->c.gclist; ++ traverseclosure(g, cl); ++ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : ++ sizeLclosure(cl->l.nupvalues); ++ } ++ case LUA_TTHREAD: { ++ lua_State *th = gco2th(o); ++ g->gray = th->gclist; ++ th->gclist = g->grayagain; ++ g->grayagain = o; ++ black2gray(o); ++ traversestack(g, th); ++ return sizeof(lua_State) + sizeof(TValue) * th->stacksize + ++ sizeof(CallInfo) * th->size_ci; ++ } ++ case LUA_TPROTO: { ++ Proto *p = gco2p(o); ++ g->gray = p->gclist; ++ traverseproto(g, p); ++ return sizeof(Proto) + sizeof(Instruction) * p->sizecode + ++ sizeof(Proto *) * p->sizep + ++ sizeof(TValue) * p->sizek + ++ sizeof(int) * p->sizelineinfo + ++ sizeof(LocVar) * p->sizelocvars + ++ sizeof(TString *) * p->sizeupvalues; ++ } ++ default: lua_assert(0); return 0; ++ } ++} ++ ++ ++static size_t propagateall (global_State *g) { ++ size_t m = 0; ++ while (g->gray) m += propagatemark(g); ++ return m; ++} ++ ++ ++/* ++** The next function tells whether a key or value can be cleared from ++** a weak table. Non-collectable objects are never removed from weak ++** tables. Strings behave as `values', so are never removed too. for ++** other objects: if really collected, cannot keep them; for userdata ++** being finalized, keep them in keys, but not in values ++*/ ++static int iscleared (const TValue *o, int iskey) { ++ if (!iscollectable(o)) return 0; ++ if (ttisstring(o)) { ++ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ ++ return 0; ++ } ++ return iswhite(gcvalue(o)) || ++ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); ++} ++ ++ ++/* ++** clear collected entries from weaktables ++*/ ++static void cleartable (GCObject *l) { ++ while (l) { ++ Table *h = gco2h(l); ++ int i = h->sizearray; ++ lua_assert(testbit(h->marked, VALUEWEAKBIT) || ++ testbit(h->marked, KEYWEAKBIT)); ++ if (testbit(h->marked, VALUEWEAKBIT)) { ++ while (i--) { ++ TValue *o = &h->array[i]; ++ if (iscleared(o, 0)) /* value was collected? */ ++ setnilvalue(o); /* remove value */ ++ } ++ } ++ i = sizenode(h); ++ while (i--) { ++ Node *n = gnode(h, i); ++ if (!ttisnil(gval(n)) && /* non-empty entry? */ ++ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { ++ setnilvalue(gval(n)); /* remove value ... */ ++ removeentry(n); /* remove entry from table */ ++ } ++ } ++ l = h->gclist; ++ } ++} ++ ++ ++static void freeobj (lua_State *L, GCObject *o) { ++ switch (o->gch.tt) { ++ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; ++ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; ++ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; ++ case LUA_TTABLE: luaH_free(L, gco2h(o)); break; ++ case LUA_TTHREAD: { ++ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); ++ luaE_freethread(L, gco2th(o)); ++ break; ++ } ++ case LUA_TSTRING: { ++ G(L)->strt.nuse--; ++ luaM_freemem(L, o, sizestring(gco2ts(o))); ++ break; ++ } ++ case LUA_TUSERDATA: { ++ luaM_freemem(L, o, sizeudata(gco2u(o))); ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++ ++#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) ++ ++ ++static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { ++ GCObject *curr; ++ global_State *g = G(L); ++ int deadmask = otherwhite(g); ++ while ((curr = *p) != NULL && count-- > 0) { ++ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ ++ sweepwholelist(L, &gco2th(curr)->openupval); ++ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ ++ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); ++ makewhite(g, curr); /* make it white (for next cycle) */ ++ p = &curr->gch.next; ++ } ++ else { /* must erase `curr' */ ++ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); ++ *p = curr->gch.next; ++ if (curr == g->rootgc) /* is the first element of the list? */ ++ g->rootgc = curr->gch.next; /* adjust first */ ++ freeobj(L, curr); ++ } ++ } ++ return p; ++} ++ ++ ++static void checkSizes (lua_State *L) { ++ global_State *g = G(L); ++ /* check size of string hash */ ++ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && ++ g->strt.size > MINSTRTABSIZE*2) ++ luaS_resize(L, g->strt.size/2); /* table is too big */ ++ /* check size of buffer */ ++ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ ++ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; ++ luaZ_resizebuffer(L, &g->buff, newsize); ++ } ++} ++ ++ ++static void GCTM (lua_State *L) { ++ global_State *g = G(L); ++ GCObject *o = g->tmudata->gch.next; /* get first element */ ++ Udata *udata = rawgco2u(o); ++ const TValue *tm; ++ /* remove udata from `tmudata' */ ++ if (o == g->tmudata) /* last element? */ ++ g->tmudata = NULL; ++ else ++ g->tmudata->gch.next = udata->uv.next; ++ udata->uv.next = g->mainthread->next; /* return it to `root' list */ ++ g->mainthread->next = o; ++ makewhite(g, o); ++ tm = fasttm(L, udata->uv.metatable, TM_GC); ++ if (tm != NULL) { ++ lu_byte oldah = L->allowhook; ++ lu_mem oldt = g->GCthreshold; ++ L->allowhook = 0; /* stop debug hooks during GC tag method */ ++ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ ++ setobj2s(L, L->top, tm); ++ setuvalue(L, L->top+1, udata); ++ L->top += 2; ++ luaD_call(L, L->top - 2, 0); ++ L->allowhook = oldah; /* restore hooks */ ++ g->GCthreshold = oldt; /* restore threshold */ ++ } ++} ++ ++ ++/* ++** Call all GC tag methods ++*/ ++void luaC_callGCTM (lua_State *L) { ++ while (G(L)->tmudata) ++ GCTM(L); ++} ++ ++ ++void luaC_freeall (lua_State *L) { ++ global_State *g = G(L); ++ int i; ++ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ ++ sweepwholelist(L, &g->rootgc); ++ for (i = 0; i < g->strt.size; i++) /* free all string lists */ ++ sweepwholelist(L, &g->strt.hash[i]); ++} ++ ++ ++static void markmt (global_State *g) { ++ int i; ++ for (i=0; imt[i]) markobject(g, g->mt[i]); ++} ++ ++ ++/* mark root set */ ++static void markroot (lua_State *L) { ++ global_State *g = G(L); ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ markobject(g, g->mainthread); ++ /* make global table be traversed before main stack */ ++ markvalue(g, gt(g->mainthread)); ++ markvalue(g, registry(L)); ++ markmt(g); ++ g->gcstate = GCSpropagate; ++} ++ ++ ++static void remarkupvals (global_State *g) { ++ UpVal *uv; ++ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ if (isgray(obj2gco(uv))) ++ markvalue(g, uv->v); ++ } ++} ++ ++ ++static void atomic (lua_State *L) { ++ global_State *g = G(L); ++ size_t udsize; /* total size of userdata to be finalized */ ++ /* remark occasional upvalues of (maybe) dead threads */ ++ remarkupvals(g); ++ /* traverse objects cautch by write barrier and by 'remarkupvals' */ ++ propagateall(g); ++ /* remark weak tables */ ++ g->gray = g->weak; ++ g->weak = NULL; ++ lua_assert(!iswhite(obj2gco(g->mainthread))); ++ markobject(g, L); /* mark running thread */ ++ markmt(g); /* mark basic metatables (again) */ ++ propagateall(g); ++ /* remark gray again */ ++ g->gray = g->grayagain; ++ g->grayagain = NULL; ++ propagateall(g); ++ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ ++ marktmu(g); /* mark `preserved' userdata */ ++ udsize += propagateall(g); /* remark, to propagate `preserveness' */ ++ cleartable(g->weak); /* remove collected objects from weak tables */ ++ /* flip current white */ ++ g->currentwhite = cast_byte(otherwhite(g)); ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ g->gcstate = GCSsweepstring; ++ g->estimate = g->totalbytes - udsize; /* first estimate */ ++} ++ ++ ++static l_mem singlestep (lua_State *L) { ++ global_State *g = G(L); ++ /*lua_checkmemory(L);*/ ++ switch (g->gcstate) { ++ case GCSpause: { ++ markroot(L); /* start a new collection */ ++ return 0; ++ } ++ case GCSpropagate: { ++ if (g->gray) ++ return propagatemark(g); ++ else { /* no more `gray' objects */ ++ atomic(L); /* finish mark phase */ ++ return 0; ++ } ++ } ++ case GCSsweepstring: { ++ lu_mem old = g->totalbytes; ++ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); ++ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ ++ g->gcstate = GCSsweep; /* end sweep-string phase */ ++ lua_assert(old >= g->totalbytes); ++ g->estimate -= old - g->totalbytes; ++ return GCSWEEPCOST; ++ } ++ case GCSsweep: { ++ lu_mem old = g->totalbytes; ++ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); ++ if (*g->sweepgc == NULL) { /* nothing more to sweep? */ ++ checkSizes(L); ++ g->gcstate = GCSfinalize; /* end sweep phase */ ++ } ++ lua_assert(old >= g->totalbytes); ++ g->estimate -= old - g->totalbytes; ++ return GCSWEEPMAX*GCSWEEPCOST; ++ } ++ case GCSfinalize: { ++ if (g->tmudata) { ++ GCTM(L); ++ if (g->estimate > GCFINALIZECOST) ++ g->estimate -= GCFINALIZECOST; ++ return GCFINALIZECOST; ++ } ++ else { ++ g->gcstate = GCSpause; /* end collection */ ++ g->gcdept = 0; ++ return 0; ++ } ++ } ++ default: lua_assert(0); return 0; ++ } ++} ++ ++ ++void luaC_step (lua_State *L) { ++ global_State *g = G(L); ++ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; ++ if (lim == 0) ++ lim = (MAX_LUMEM-1)/2; /* no limit */ ++ g->gcdept += g->totalbytes - g->GCthreshold; ++ do { ++ lim -= singlestep(L); ++ if (g->gcstate == GCSpause) ++ break; ++ } while (lim > 0); ++ if (g->gcstate != GCSpause) { ++ if (g->gcdept < GCSTEPSIZE) ++ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ ++ else { ++ g->gcdept -= GCSTEPSIZE; ++ g->GCthreshold = g->totalbytes; ++ } ++ } ++ else { ++ lua_assert(g->totalbytes >= g->estimate); ++ setthreshold(g); ++ } ++} ++ ++ ++void luaC_fullgc (lua_State *L) { ++ global_State *g = G(L); ++ if (g->gcstate <= GCSpropagate) { ++ /* reset sweep marks to sweep all elements (returning them to white) */ ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ /* reset other collector lists */ ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ g->gcstate = GCSsweepstring; ++ } ++ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); ++ /* finish any pending sweep phase */ ++ while (g->gcstate != GCSfinalize) { ++ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); ++ singlestep(L); ++ } ++ markroot(L); ++ while (g->gcstate != GCSpause) { ++ singlestep(L); ++ } ++ setthreshold(g); ++} ++ ++ ++void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { ++ global_State *g = G(L); ++ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ lua_assert(ttype(&o->gch) != LUA_TTABLE); ++ /* must keep invariant? */ ++ if (g->gcstate == GCSpropagate) ++ reallymarkobject(g, v); /* restore invariant */ ++ else /* don't mind */ ++ makewhite(g, o); /* mark as white just to avoid other barriers */ ++} ++ ++ ++void luaC_barrierback (lua_State *L, Table *t) { ++ global_State *g = G(L); ++ GCObject *o = obj2gco(t); ++ lua_assert(isblack(o) && !isdead(g, o)); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ black2gray(o); /* make table gray (again) */ ++ t->gclist = g->grayagain; ++ g->grayagain = o; ++} ++ ++ ++void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { ++ global_State *g = G(L); ++ o->gch.next = g->rootgc; ++ g->rootgc = o; ++ o->gch.marked = luaC_white(g); ++ o->gch.tt = tt; ++} ++ ++ ++void luaC_linkupval (lua_State *L, UpVal *uv) { ++ global_State *g = G(L); ++ GCObject *o = obj2gco(uv); ++ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ ++ g->rootgc = o; ++ if (isgray(o)) { ++ if (g->gcstate == GCSpropagate) { ++ gray2black(o); /* closed upvalues need barrier */ ++ luaC_barrier(L, uv, uv->v); ++ } ++ else { /* sweep phase: sweep it (turning it into white) */ ++ makewhite(g, o); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ } ++ } ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lgc.h +@@ -0,0 +1,110 @@ ++/* ++** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Garbage Collector ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lgc_h ++#define lgc_h ++ ++ ++#include "lobject.h" ++ ++ ++/* ++** Possible states of the Garbage Collector ++*/ ++#define GCSpause 0 ++#define GCSpropagate 1 ++#define GCSsweepstring 2 ++#define GCSsweep 3 ++#define GCSfinalize 4 ++ ++ ++/* ++** some userful bit tricks ++*/ ++#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) ++#define setbits(x,m) ((x) |= (m)) ++#define testbits(x,m) ((x) & (m)) ++#define bitmask(b) (1<<(b)) ++#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) ++#define l_setbit(x,b) setbits(x, bitmask(b)) ++#define resetbit(x,b) resetbits(x, bitmask(b)) ++#define testbit(x,b) testbits(x, bitmask(b)) ++#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) ++#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) ++#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) ++ ++ ++ ++/* ++** Layout for bit use in `marked' field: ++** bit 0 - object is white (type 0) ++** bit 1 - object is white (type 1) ++** bit 2 - object is black ++** bit 3 - for userdata: has been finalized ++** bit 3 - for tables: has weak keys ++** bit 4 - for tables: has weak values ++** bit 5 - object is fixed (should not be collected) ++** bit 6 - object is "super" fixed (only the main thread) ++*/ ++ ++ ++#define WHITE0BIT 0 ++#define WHITE1BIT 1 ++#define BLACKBIT 2 ++#define FINALIZEDBIT 3 ++#define KEYWEAKBIT 3 ++#define VALUEWEAKBIT 4 ++#define FIXEDBIT 5 ++#define SFIXEDBIT 6 ++#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) ++ ++ ++#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) ++#define isblack(x) testbit((x)->gch.marked, BLACKBIT) ++#define isgray(x) (!isblack(x) && !iswhite(x)) ++ ++#define otherwhite(g) (g->currentwhite ^ WHITEBITS) ++#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) ++ ++#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) ++#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) ++ ++#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) ++ ++#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) ++ ++ ++#define luaC_checkGC(L) { \ ++ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ ++ if (G(L)->totalbytes >= G(L)->GCthreshold) \ ++ luaC_step(L); } ++ ++ ++#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ ++ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } ++ ++#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ ++ luaC_barrierback(L,t); } ++ ++#define luaC_objbarrier(L,p,o) \ ++ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ ++ luaC_barrierf(L,obj2gco(p),obj2gco(o)); } ++ ++#define luaC_objbarriert(L,t,o) \ ++ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } ++ ++LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); ++LUAI_FUNC void luaC_callGCTM (lua_State *L); ++LUAI_FUNC void luaC_freeall (lua_State *L); ++LUAI_FUNC void luaC_step (lua_State *L); ++LUAI_FUNC void luaC_fullgc (lua_State *L); ++LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); ++LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); ++LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); ++LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/llex.c +@@ -0,0 +1,460 @@ ++/* ++** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lexical Analyzer ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++ ++#define llex_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldo.h" ++#include "llex.h" ++#include "lobject.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "lzio.h" ++ ++ ++ ++#define next(ls) (ls->current = zgetc(ls->z)) ++ ++ ++ ++ ++#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') ++ ++ ++/* ORDER RESERVED */ ++const char *const luaX_tokens [] = { ++ "and", "break", "do", "else", "elseif", ++ "end", "false", "for", "function", "if", ++ "in", "local", "nil", "not", "or", "repeat", ++ "return", "then", "true", "until", "while", ++ "..", "...", "==", ">=", "<=", "~=", ++ "", "", "", "", ++ NULL ++}; ++ ++ ++#define save_and_next(ls) (save(ls, ls->current), next(ls)) ++ ++ ++static void save (LexState *ls, int c) { ++ Mbuffer *b = ls->buff; ++ if (b->n + 1 > b->buffsize) { ++ size_t newsize; ++ if (b->buffsize >= MAX_SIZET/2) ++ luaX_lexerror(ls, "lexical element too long", 0); ++ newsize = b->buffsize * 2; ++ luaZ_resizebuffer(ls->L, b, newsize); ++ } ++ b->buffer[b->n++] = cast(char, c); ++} ++ ++ ++void luaX_init (lua_State *L) { ++ int i; ++ for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ ++ } ++} ++ ++ ++#define MAXSRC 80 ++ ++ ++const char *luaX_token2str (LexState *ls, int token) { ++ if (token < FIRST_RESERVED) { ++ lua_assert(token == cast(unsigned char, token)); ++ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : ++ luaO_pushfstring(ls->L, "%c", token); ++ } ++ else ++ return luaX_tokens[token-FIRST_RESERVED]; ++} ++ ++ ++static const char *txtToken (LexState *ls, int token) { ++ switch (token) { ++ case TK_NAME: ++ case TK_STRING: ++ case TK_NUMBER: ++ save(ls, '\0'); ++ return luaZ_buffer(ls->buff); ++ default: ++ return luaX_token2str(ls, token); ++ } ++} ++ ++ ++void luaX_lexerror (LexState *ls, const char *msg, int token) { ++ char buff[MAXSRC]; ++ luaO_chunkid(buff, getstr(ls->source), MAXSRC); ++ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); ++ if (token) ++ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); ++ luaD_throw(ls->L, LUA_ERRSYNTAX); ++} ++ ++ ++void luaX_syntaxerror (LexState *ls, const char *msg) { ++ luaX_lexerror(ls, msg, ls->t.token); ++} ++ ++ ++TString *luaX_newstring (LexState *ls, const char *str, size_t l) { ++ lua_State *L = ls->L; ++ TString *ts = luaS_newlstr(L, str, l); ++ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ ++ if (ttisnil(o)) ++ setbvalue(o, 1); /* make sure `str' will not be collected */ ++ return ts; ++} ++ ++ ++static void inclinenumber (LexState *ls) { ++ int old = ls->current; ++ lua_assert(currIsNewline(ls)); ++ next(ls); /* skip `\n' or `\r' */ ++ if (currIsNewline(ls) && ls->current != old) ++ next(ls); /* skip `\n\r' or `\r\n' */ ++ if (++ls->linenumber >= MAX_INT) ++ luaX_syntaxerror(ls, "chunk has too many lines"); ++} ++ ++ ++void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { ++ ls->decpoint = '.'; ++ ls->L = L; ++ ls->lookahead.token = TK_EOS; /* no look-ahead token */ ++ ls->z = z; ++ ls->fs = NULL; ++ ls->linenumber = 1; ++ ls->lastline = 1; ++ ls->source = source; ++ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ ++ next(ls); /* read first char */ ++} ++ ++ ++ ++/* ++** ======================================================= ++** LEXICAL ANALYZER ++** ======================================================= ++*/ ++ ++ ++ ++static int check_next (LexState *ls, const char *set) { ++ if (!strchr(set, ls->current)) ++ return 0; ++ save_and_next(ls); ++ return 1; ++} ++ ++ ++static void buffreplace (LexState *ls, char from, char to) { ++ size_t n = luaZ_bufflen(ls->buff); ++ char *p = luaZ_buffer(ls->buff); ++ while (n--) ++ if (p[n] == from) p[n] = to; ++} ++ ++ ++static void trydecpoint (LexState *ls, SemInfo *seminfo) { ++ /* format error: try to update decimal point separator */ ++ char old = ls->decpoint; ++ struct lconv *cv = localeconv(); ++ ls->decpoint = (cv ? cv->decimal_point[0] : '.'); ++ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ ++ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { ++ /* format error with correct decimal point: no more options */ ++ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ ++ luaX_lexerror(ls, "malformed number", TK_NUMBER); ++ } ++} ++ ++ ++/* LUA_NUMBER */ ++static void read_numeral (LexState *ls, SemInfo *seminfo) { ++ lua_assert(isdigit(ls->current)); ++ do { ++ save_and_next(ls); ++ } while (isdigit(ls->current) || ls->current == '.'); ++ if (check_next(ls, "Ee")) /* `E'? */ ++ check_next(ls, "+-"); /* optional exponent sign */ ++ while (isalnum(ls->current) || ls->current == '_') ++ save_and_next(ls); ++ save(ls, '\0'); ++ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ ++ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ ++ trydecpoint(ls, seminfo); /* try to update decimal point separator */ ++} ++ ++ ++static int skip_sep (LexState *ls) { ++ int count = 0; ++ int s = ls->current; ++ lua_assert(s == '[' || s == ']'); ++ save_and_next(ls); ++ while (ls->current == '=') { ++ save_and_next(ls); ++ count++; ++ } ++ return (ls->current == s) ? count : (-count) - 1; ++} ++ ++ ++static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { ++ int cont = 0; ++ (void)(cont); /* avoid warnings when `cont' is not used */ ++ save_and_next(ls); /* skip 2nd `[' */ ++ if (currIsNewline(ls)) /* string starts with a newline? */ ++ inclinenumber(ls); /* skip it */ ++ for (;;) { ++ switch (ls->current) { ++ case EOZ: ++ luaX_lexerror(ls, (seminfo) ? "unfinished long string" : ++ "unfinished long comment", TK_EOS); ++ break; /* to avoid warnings */ ++#if defined(LUA_COMPAT_LSTR) ++ case '[': { ++ if (skip_sep(ls) == sep) { ++ save_and_next(ls); /* skip 2nd `[' */ ++ cont++; ++#if LUA_COMPAT_LSTR == 1 ++ if (sep == 0) ++ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); ++#endif ++ } ++ break; ++ } ++#endif ++ case ']': { ++ if (skip_sep(ls) == sep) { ++ save_and_next(ls); /* skip 2nd `]' */ ++#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 ++ cont--; ++ if (sep == 0 && cont >= 0) break; ++#endif ++ goto endloop; ++ } ++ break; ++ } ++ case '\n': ++ case '\r': { ++ save(ls, '\n'); ++ inclinenumber(ls); ++ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ ++ break; ++ } ++ default: { ++ if (seminfo) save_and_next(ls); ++ else next(ls); ++ } ++ } ++ } endloop: ++ if (seminfo) ++ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), ++ luaZ_bufflen(ls->buff) - 2*(2 + sep)); ++} ++ ++ ++static void read_string (LexState *ls, int del, SemInfo *seminfo) { ++ save_and_next(ls); ++ while (ls->current != del) { ++ switch (ls->current) { ++ case EOZ: ++ luaX_lexerror(ls, "unfinished string", TK_EOS); ++ continue; /* to avoid warnings */ ++ case '\n': ++ case '\r': ++ luaX_lexerror(ls, "unfinished string", TK_STRING); ++ continue; /* to avoid warnings */ ++ case '\\': { ++ int c; ++ next(ls); /* do not save the `\' */ ++ switch (ls->current) { ++ case 'a': c = '\a'; break; ++ case 'b': c = '\b'; break; ++ case 'f': c = '\f'; break; ++ case 'n': c = '\n'; break; ++ case 'r': c = '\r'; break; ++ case 't': c = '\t'; break; ++ case 'v': c = '\v'; break; ++ case '\n': /* go through */ ++ case '\r': save(ls, '\n'); inclinenumber(ls); continue; ++ case EOZ: continue; /* will raise an error next loop */ ++ default: { ++ if (!isdigit(ls->current)) ++ save_and_next(ls); /* handles \\, \", \', and \? */ ++ else { /* \xxx */ ++ int i = 0; ++ c = 0; ++ do { ++ c = 10*c + (ls->current-'0'); ++ next(ls); ++ } while (++i<3 && isdigit(ls->current)); ++ if (c > UCHAR_MAX) ++ luaX_lexerror(ls, "escape sequence too large", TK_STRING); ++ save(ls, c); ++ } ++ continue; ++ } ++ } ++ save(ls, c); ++ next(ls); ++ continue; ++ } ++ default: ++ save_and_next(ls); ++ } ++ } ++ save_and_next(ls); /* skip delimiter */ ++ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, ++ luaZ_bufflen(ls->buff) - 2); ++} ++ ++ ++static int llex (LexState *ls, SemInfo *seminfo) { ++ luaZ_resetbuffer(ls->buff); ++ for (;;) { ++ switch (ls->current) { ++ case '\n': ++ case '\r': { ++ inclinenumber(ls); ++ continue; ++ } ++ case '-': { ++ next(ls); ++ if (ls->current != '-') return '-'; ++ /* else is a comment */ ++ next(ls); ++ if (ls->current == '[') { ++ int sep = skip_sep(ls); ++ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ ++ if (sep >= 0) { ++ read_long_string(ls, NULL, sep); /* long comment */ ++ luaZ_resetbuffer(ls->buff); ++ continue; ++ } ++ } ++ /* else short comment */ ++ while (!currIsNewline(ls) && ls->current != EOZ) ++ next(ls); ++ continue; ++ } ++ case '[': { ++ int sep = skip_sep(ls); ++ if (sep >= 0) { ++ read_long_string(ls, seminfo, sep); ++ return TK_STRING; ++ } ++ else if (sep == -1) return '['; ++ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); ++ fallthrough; ++ } ++ case '=': { ++ next(ls); ++ if (ls->current != '=') return '='; ++ else { next(ls); return TK_EQ; } ++ } ++ case '<': { ++ next(ls); ++ if (ls->current != '=') return '<'; ++ else { next(ls); return TK_LE; } ++ } ++ case '>': { ++ next(ls); ++ if (ls->current != '=') return '>'; ++ else { next(ls); return TK_GE; } ++ } ++ case '~': { ++ next(ls); ++ if (ls->current != '=') return '~'; ++ else { next(ls); return TK_NE; } ++ } ++ case '"': ++ case '\'': { ++ read_string(ls, ls->current, seminfo); ++ return TK_STRING; ++ } ++ case '.': { ++ save_and_next(ls); ++ if (check_next(ls, ".")) { ++ if (check_next(ls, ".")) ++ return TK_DOTS; /* ... */ ++ else return TK_CONCAT; /* .. */ ++ } ++ else if (!isdigit(ls->current)) return '.'; ++ else { ++ read_numeral(ls, seminfo); ++ return TK_NUMBER; ++ } ++ } ++ case EOZ: { ++ return TK_EOS; ++ } ++ default: { ++ if (isspace(ls->current)) { ++ lua_assert(!currIsNewline(ls)); ++ next(ls); ++ continue; ++ } ++ else if (isdigit(ls->current)) { ++ read_numeral(ls, seminfo); ++ return TK_NUMBER; ++ } ++ else if (isalpha(ls->current) || ls->current == '_') { ++ /* identifier or reserved word */ ++ TString *ts; ++ do { ++ save_and_next(ls); ++ } while (isalnum(ls->current) || ls->current == '_'); ++ ts = luaX_newstring(ls, luaZ_buffer(ls->buff), ++ luaZ_bufflen(ls->buff)); ++ if (ts->tsv.reserved > 0) /* reserved word? */ ++ return ts->tsv.reserved - 1 + FIRST_RESERVED; ++ else { ++ seminfo->ts = ts; ++ return TK_NAME; ++ } ++ } ++ else { ++ int c = ls->current; ++ next(ls); ++ return c; /* single-char tokens (+ - / ...) */ ++ } ++ } ++ } ++ } ++} ++ ++ ++void luaX_next (LexState *ls) { ++ ls->lastline = ls->linenumber; ++ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ ++ ls->t = ls->lookahead; /* use this one */ ++ ls->lookahead.token = TK_EOS; /* and discharge it */ ++ } ++ else ++ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ ++} ++ ++ ++void luaX_lookahead (LexState *ls) { ++ lua_assert(ls->lookahead.token == TK_EOS); ++ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); ++} +--- /dev/null ++++ b/extensions/LUA/lua/llex.h +@@ -0,0 +1,81 @@ ++/* ++** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lexical Analyzer ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef llex_h ++#define llex_h ++ ++#include "lobject.h" ++#include "lzio.h" ++ ++ ++#define FIRST_RESERVED 257 ++ ++/* maximum length of a reserved word */ ++#define TOKEN_LEN (sizeof("function")/sizeof(char)) ++ ++ ++/* ++* WARNING: if you change the order of this enumeration, ++* grep "ORDER RESERVED" ++*/ ++enum RESERVED { ++ /* terminal symbols denoted by reserved words */ ++ TK_AND = FIRST_RESERVED, TK_BREAK, ++ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, ++ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, ++ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, ++ /* other terminal symbols */ ++ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, ++ TK_NAME, TK_STRING, TK_EOS ++}; ++ ++/* number of reserved words */ ++#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) ++ ++ ++/* array with token `names' */ ++LUAI_DATA const char *const luaX_tokens []; ++ ++ ++typedef union { ++ lua_Number r; ++ TString *ts; ++} SemInfo; /* semantics information */ ++ ++ ++typedef struct Token { ++ int token; ++ SemInfo seminfo; ++} Token; ++ ++ ++typedef struct LexState { ++ int current; /* current character (charint) */ ++ int linenumber; /* input line counter */ ++ int lastline; /* line of last token `consumed' */ ++ Token t; /* current token */ ++ Token lookahead; /* look ahead token */ ++ struct FuncState *fs; /* `FuncState' is private to the parser */ ++ struct lua_State *L; ++ ZIO *z; /* input stream */ ++ Mbuffer *buff; /* buffer for tokens */ ++ TString *source; /* current source name */ ++ char decpoint; /* locale decimal point */ ++} LexState; ++ ++ ++LUAI_FUNC void luaX_init (lua_State *L); ++LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, ++ TString *source); ++LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); ++LUAI_FUNC void luaX_next (LexState *ls); ++LUAI_FUNC void luaX_lookahead (LexState *ls); ++LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); ++LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); ++LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/llimits.h +@@ -0,0 +1,125 @@ ++/* ++** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Limits, basic types, and some other `installation-dependent' definitions ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef llimits_h ++#define llimits_h ++ ++#include ++#include ++ ++#include "lua.h" ++ ++typedef LUAI_UINT32 lu_int32; ++ ++typedef LUAI_UMEM lu_mem; ++ ++typedef LUAI_MEM l_mem; ++ ++ ++ ++/* chars used as small naturals (so that `char' is reserved for characters) */ ++typedef unsigned char lu_byte; ++ ++ ++#define MAX_SIZET ((size_t)(~(size_t)0)-2) ++ ++#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) ++ ++ ++#define MAX_INT (LUA_INT_MAX-2) /* maximum value of an int (-2 for safety) */ ++ ++/* ++** conversion of pointer to integer ++** this is for hashing only; there is no problem if the integer ++** cannot hold the whole pointer value ++*/ ++#define IntPoint(p) ((unsigned int)(lu_mem)(p)) ++ ++ ++ ++/* type to ensure maximum alignment */ ++typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; ++ ++ ++/* result of a `usual argument conversion' over lua_Number */ ++typedef LUAI_UACNUMBER l_uacNumber; ++ ++ ++/* internal assertions for in-house debugging */ ++#ifdef lua_assert ++ ++#define check_exp(c,e) (lua_assert(c), (e)) ++#define api_check(l,e) lua_assert(e) ++ ++#else ++ ++#define lua_assert(c) ((void)0) ++#define check_exp(c,e) (e) ++#define api_check luai_apicheck ++ ++#endif ++ ++ ++#ifndef UNUSED ++#define UNUSED(x) ((void)(x)) /* to avoid warnings */ ++#endif ++ ++ ++#ifndef cast ++#define cast(t, exp) ((t)(exp)) ++#endif ++ ++#define cast_byte(i) cast(lu_byte, (i)) ++#define cast_num(i) cast(lua_Number, (i)) ++#define cast_int(i) cast(int, (i)) ++ ++ ++ ++/* ++** type for virtual-machine instructions ++** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) ++*/ ++typedef lu_int32 Instruction; ++ ++ ++ ++/* maximum stack for a Lua function */ ++#define MAXSTACK 250 ++ ++ ++ ++/* minimum size for the string table (must be power of 2) */ ++#ifndef MINSTRTABSIZE ++#define MINSTRTABSIZE 32 ++#endif ++ ++ ++/* minimum size for string buffer */ ++#ifndef LUA_MINBUFFER ++#define LUA_MINBUFFER 32 ++#endif ++ ++ ++#ifndef lua_lock ++#define lua_lock(L) ((void) 0) ++#define lua_unlock(L) ((void) 0) ++#endif ++ ++#ifndef luai_threadyield ++#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} ++#endif ++ ++ ++/* ++** macro to control inclusion of some hard tests on stack reallocation ++*/ ++#ifndef HARDSTACKTESTS ++#define condhardstacktests(x) ((void)0) ++#else ++#define condhardstacktests(x) x ++#endif ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lmem.c +@@ -0,0 +1,86 @@ ++/* ++** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Interface to Memory Manager ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lmem_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++ ++/* ++** About the realloc function: ++** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ++** (`osize' is the old size, `nsize' is the new size) ++** ++** Lua ensures that (ptr == NULL) iff (osize == 0). ++** ++** * frealloc(ud, NULL, 0, x) creates a new block of size `x' ++** ++** * frealloc(ud, p, x, 0) frees the block `p' ++** (in this specific case, frealloc must return NULL). ++** particularly, frealloc(ud, NULL, 0, 0) does nothing ++** (which is equivalent to free(NULL) in ANSI C) ++** ++** frealloc returns NULL if it cannot create or reallocate the area ++** (any reallocation to an equal or smaller size cannot fail!) ++*/ ++ ++ ++ ++#define MINSIZEARRAY 4 ++ ++ ++void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, ++ int limit, const char *errormsg) { ++ void *newblock; ++ int newsize; ++ if (*size >= limit/2) { /* cannot double it? */ ++ if (*size >= limit) /* cannot grow even a little? */ ++ luaG_runerror(L, errormsg); ++ newsize = limit; /* still have at least one free place */ ++ } ++ else { ++ newsize = (*size)*2; ++ if (newsize < MINSIZEARRAY) ++ newsize = MINSIZEARRAY; /* minimum size */ ++ } ++ newblock = luaM_reallocv(L, block, *size, newsize, size_elems); ++ *size = newsize; /* update only when everything else is OK */ ++ return newblock; ++} ++ ++ ++void *luaM_toobig (lua_State *L) { ++ luaG_runerror(L, "memory allocation error: block too big"); ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++ ++/* ++** generic allocation routine. ++*/ ++void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { ++ global_State *g = G(L); ++ lua_assert((osize == 0) == (block == NULL)); ++ block = (*g->frealloc)(g->ud, block, osize, nsize); ++ if (block == NULL && nsize > 0) ++ luaD_throw(L, LUA_ERRMEM); ++ lua_assert((nsize == 0) == (block == NULL)); ++ g->totalbytes = (g->totalbytes - osize) + nsize; ++ return block; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lmem.h +@@ -0,0 +1,49 @@ ++/* ++** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Interface to Memory Manager ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lmem_h ++#define lmem_h ++ ++ ++#include ++ ++#include "llimits.h" ++#include "lua.h" ++ ++#define MEMERRMSG "not enough memory" ++ ++ ++#define luaM_reallocv(L,b,on,n,e) \ ++ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ ++ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ ++ luaM_toobig(L)) ++ ++#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) ++#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) ++#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) ++ ++#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) ++#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) ++#define luaM_newvector(L,n,t) \ ++ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) ++ ++#define luaM_growvector(L,v,nelems,size,t,limit,e) \ ++ if ((nelems)+1 > (size)) \ ++ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) ++ ++#define luaM_reallocvector(L, v,oldn,n,t) \ ++ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) ++ ++ ++LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, ++ size_t size); ++LUAI_FUNC void *luaM_toobig (lua_State *L); ++LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, ++ size_t size_elem, int limit, ++ const char *errormsg); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lobject.c +@@ -0,0 +1,213 @@ ++/* ++** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Some generic functions over Lua objects ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#define lobject_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldo.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "lvm.h" ++ ++ ++ ++const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; ++ ++ ++/* ++** converts an integer to a "floating point byte", represented as ++** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if ++** eeeee != 0 and (xxx) otherwise. ++*/ ++int luaO_int2fb (unsigned int x) { ++ int e = 0; /* expoent */ ++ while (x >= 16) { ++ x = (x+1) >> 1; ++ e++; ++ } ++ if (x < 8) return x; ++ else return ((e+1) << 3) | (cast_int(x) - 8); ++} ++ ++ ++/* converts back */ ++int luaO_fb2int (int x) { ++ int e = (x >> 3) & 31; ++ if (e == 0) return x; ++ else return ((x & 7)+8) << (e - 1); ++} ++ ++ ++int luaO_log2 (unsigned int x) { ++ static const lu_byte log_2[256] = { ++ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, ++ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 ++ }; ++ int l = -1; ++ while (x >= 256) { l += 8; x >>= 8; } ++ return l + log_2[x]; ++ ++} ++ ++ ++int luaO_rawequalObj (const TValue *t1, const TValue *t2) { ++ if (ttype(t1) != ttype(t2)) return 0; ++ else switch (ttype(t1)) { ++ case LUA_TNIL: ++ return 1; ++ case LUA_TNUMBER: ++ return luai_numeq(nvalue(t1), nvalue(t2)); ++ case LUA_TBOOLEAN: ++ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: ++ return pvalue(t1) == pvalue(t2); ++ default: ++ lua_assert(iscollectable(t1)); ++ return gcvalue(t1) == gcvalue(t2); ++ } ++} ++ ++ ++int luaO_str2d (const char *s, lua_Number *result) { ++ char *endptr; ++ *result = lua_str2number(s, &endptr); ++ if (endptr == s) return 0; /* conversion failed */ ++ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ ++ *result = cast_num(strtoul(s, &endptr, 16)); ++ if (*endptr == '\0') return 1; /* most common case */ ++ while (isspace(cast(unsigned char, *endptr))) endptr++; ++ if (*endptr != '\0') return 0; /* invalid trailing characters? */ ++ return 1; ++} ++ ++ ++ ++static void pushstr (lua_State *L, const char *str) { ++ setsvalue2s(L, L->top, luaS_new(L, str)); ++ incr_top(L); ++} ++ ++ ++/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ ++const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { ++ int n = 1; ++ pushstr(L, ""); ++ for (;;) { ++ const char *e = strchr(fmt, '%'); ++ if (e == NULL) break; ++ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); ++ incr_top(L); ++ switch (*(e+1)) { ++ case 's': { ++ const char *s = va_arg(argp, char *); ++ if (s == NULL) s = "(null)"; ++ pushstr(L, s); ++ break; ++ } ++ case 'c': { ++ char buff[2]; ++ buff[0] = cast(char, va_arg(argp, int)); ++ buff[1] = '\0'; ++ pushstr(L, buff); ++ break; ++ } ++ case 'd': { ++ setnvalue(L->top, cast_num(va_arg(argp, int))); ++ incr_top(L); ++ break; ++ } ++ case 'f': { ++ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); ++ incr_top(L); ++ break; ++ } ++ case 'p': { ++ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ ++ sprintf(buff, "%p", va_arg(argp, void *)); ++ pushstr(L, buff); ++ break; ++ } ++ case '%': { ++ pushstr(L, "%"); ++ break; ++ } ++ default: { ++ char buff[3]; ++ buff[0] = '%'; ++ buff[1] = *(e+1); ++ buff[2] = '\0'; ++ pushstr(L, buff); ++ break; ++ } ++ } ++ n += 2; ++ fmt = e+2; ++ } ++ pushstr(L, fmt); ++ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); ++ L->top -= n; ++ return svalue(L->top - 1); ++} ++ ++ ++const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { ++ const char *msg; ++ va_list argp; ++ va_start(argp, fmt); ++ msg = luaO_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ return msg; ++} ++ ++ ++void luaO_chunkid (char *out, const char *source, size_t bufflen) { ++ if (*source == '=') { ++ strncpy(out, source+1, bufflen); /* remove first char */ ++ out[bufflen-1] = '\0'; /* ensures null termination */ ++ } ++ else { /* out = "source", or "...source" */ ++ if (*source == '@') { ++ size_t l; ++ source++; /* skip the `@' */ ++ bufflen -= sizeof(" '...' "); ++ l = strlen(source); ++ strcpy(out, ""); ++ if (l > bufflen) { ++ source += (l-bufflen); /* get last part of file name */ ++ strcat(out, "..."); ++ } ++ strcat(out, source); ++ } ++ else { /* out = [string "string"] */ ++ size_t len = strcspn(source, "\n\r"); /* stop at first newline */ ++ bufflen -= sizeof(" [string \"...\"] "); ++ if (len > bufflen) len = bufflen; ++ strcpy(out, "[string \""); ++ if (source[len] != '\0') { /* must truncate? */ ++ strncat(out, source, len); ++ strcat(out, "..."); ++ } ++ else ++ strcat(out, source); ++ strcat(out, "\"]"); ++ } ++ } ++} +--- /dev/null ++++ b/extensions/LUA/lua/lobject.h +@@ -0,0 +1,381 @@ ++/* ++** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ ++** Type definitions for Lua objects ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lobject_h ++#define lobject_h ++ ++ ++#include ++ ++ ++#include "llimits.h" ++#include "lua.h" ++ ++ ++/* tags for values visible from Lua */ ++#define LAST_TAG LUA_TTHREAD ++ ++#define NUM_TAGS (LAST_TAG+1) ++ ++ ++/* ++** Extra tags for non-values ++*/ ++#define LUA_TPROTO (LAST_TAG+1) ++#define LUA_TUPVAL (LAST_TAG+2) ++#define LUA_TDEADKEY (LAST_TAG+3) ++ ++ ++/* ++** Union of all collectable objects ++*/ ++typedef union GCObject GCObject; ++ ++ ++/* ++** Common Header for all collectable objects (in macro form, to be ++** included in other objects) ++*/ ++#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked ++ ++ ++/* ++** Common header in struct form ++*/ ++typedef struct GCheader { ++ CommonHeader; ++} GCheader; ++ ++ ++ ++ ++/* ++** Union of all Lua values ++*/ ++typedef union { ++ GCObject *gc; ++ void *p; ++ lua_Number n; ++ int b; ++} Value; ++ ++ ++/* ++** Tagged Values ++*/ ++ ++#define TValuefields Value value; int tt ++ ++typedef struct lua_TValue { ++ TValuefields; ++} TValue; ++ ++ ++/* Macros to test type */ ++#define ttisnil(o) (ttype(o) == LUA_TNIL) ++#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) ++#define ttisstring(o) (ttype(o) == LUA_TSTRING) ++#define ttistable(o) (ttype(o) == LUA_TTABLE) ++#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) ++#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) ++#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) ++#define ttisthread(o) (ttype(o) == LUA_TTHREAD) ++#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) ++ ++/* Macros to access values */ ++#define ttype(o) ((o)->tt) ++#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) ++#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) ++#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) ++#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) ++#define tsvalue(o) (&rawtsvalue(o)->tsv) ++#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) ++#define uvalue(o) (&rawuvalue(o)->uv) ++#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) ++#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) ++#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) ++#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) ++ ++#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) ++ ++/* ++** for internal debug only ++*/ ++#define checkconsistency(obj) \ ++ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) ++ ++#define checkliveness(g,obj) \ ++ lua_assert(!iscollectable(obj) || \ ++ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) ++ ++ ++/* Macros to set values */ ++#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) ++ ++#define setnvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } ++ ++#define setpvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } ++ ++#define setbvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } ++ ++#define setsvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ ++ checkliveness(G(L),i_o); } ++ ++#define setuvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ ++ checkliveness(G(L),i_o); } ++ ++#define setthvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ ++ checkliveness(G(L),i_o); } ++ ++#define setclvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ ++ checkliveness(G(L),i_o); } ++ ++#define sethvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ ++ checkliveness(G(L),i_o); } ++ ++#define setptvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ ++ checkliveness(G(L),i_o); } ++ ++ ++ ++ ++#define setobj(L,obj1,obj2) \ ++ { const TValue *o2=(obj2); TValue *o1=(obj1); \ ++ o1->value = o2->value; o1->tt=o2->tt; \ ++ checkliveness(G(L),o1); } ++ ++ ++/* ++** different types of sets, according to destination ++*/ ++ ++/* from stack to (same) stack */ ++#define setobjs2s setobj ++/* to stack (not from same stack) */ ++#define setobj2s setobj ++#define setsvalue2s setsvalue ++#define sethvalue2s sethvalue ++#define setptvalue2s setptvalue ++/* from table to same table */ ++#define setobjt2t setobj ++/* to table */ ++#define setobj2t setobj ++/* to new object */ ++#define setobj2n setobj ++#define setsvalue2n setsvalue ++ ++#define setttype(obj, tt) (ttype(obj) = (tt)) ++ ++ ++#define iscollectable(o) (ttype(o) >= LUA_TSTRING) ++ ++ ++ ++typedef TValue *StkId; /* index to stack elements */ ++ ++ ++/* ++** String headers for string table ++*/ ++typedef union TString { ++ L_Umaxalign dummy; /* ensures maximum alignment for strings */ ++ struct { ++ CommonHeader; ++ lu_byte reserved; ++ unsigned int hash; ++ size_t len; ++ } tsv; ++} TString; ++ ++ ++#define getstr(ts) cast(const char *, (ts) + 1) ++#define svalue(o) getstr(rawtsvalue(o)) ++ ++ ++ ++typedef union Udata { ++ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ ++ struct { ++ CommonHeader; ++ struct Table *metatable; ++ struct Table *env; ++ size_t len; ++ } uv; ++} Udata; ++ ++ ++ ++ ++/* ++** Function Prototypes ++*/ ++typedef struct Proto { ++ CommonHeader; ++ TValue *k; /* constants used by the function */ ++ Instruction *code; ++ struct Proto **p; /* functions defined inside the function */ ++ int *lineinfo; /* map from opcodes to source lines */ ++ struct LocVar *locvars; /* information about local variables */ ++ TString **upvalues; /* upvalue names */ ++ TString *source; ++ int sizeupvalues; ++ int sizek; /* size of `k' */ ++ int sizecode; ++ int sizelineinfo; ++ int sizep; /* size of `p' */ ++ int sizelocvars; ++ int linedefined; ++ int lastlinedefined; ++ GCObject *gclist; ++ lu_byte nups; /* number of upvalues */ ++ lu_byte numparams; ++ lu_byte is_vararg; ++ lu_byte maxstacksize; ++} Proto; ++ ++ ++/* masks for new-style vararg */ ++#define VARARG_HASARG 1 ++#define VARARG_ISVARARG 2 ++#define VARARG_NEEDSARG 4 ++ ++ ++typedef struct LocVar { ++ TString *varname; ++ int startpc; /* first point where variable is active */ ++ int endpc; /* first point where variable is dead */ ++} LocVar; ++ ++ ++ ++/* ++** Upvalues ++*/ ++ ++typedef struct UpVal { ++ CommonHeader; ++ TValue *v; /* points to stack or to its own value */ ++ union { ++ TValue value; /* the value (when closed) */ ++ struct { /* double linked list (when open) */ ++ struct UpVal *prev; ++ struct UpVal *next; ++ } l; ++ } u; ++} UpVal; ++ ++ ++/* ++** Closures ++*/ ++ ++#define ClosureHeader \ ++ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ ++ struct Table *env ++ ++typedef struct CClosure { ++ ClosureHeader; ++ lua_CFunction f; ++ TValue upvalue[1]; ++} CClosure; ++ ++ ++typedef struct LClosure { ++ ClosureHeader; ++ struct Proto *p; ++ UpVal *upvals[1]; ++} LClosure; ++ ++ ++typedef union Closure { ++ CClosure c; ++ LClosure l; ++} Closure; ++ ++ ++#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) ++#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) ++ ++ ++/* ++** Tables ++*/ ++ ++typedef union TKey { ++ struct { ++ TValuefields; ++ struct Node *next; /* for chaining */ ++ } nk; ++ TValue tvk; ++} TKey; ++ ++ ++typedef struct Node { ++ TValue i_val; ++ TKey i_key; ++} Node; ++ ++ ++typedef struct Table { ++ CommonHeader; ++ lu_byte flags; /* 1<

    lsizenode)) ++ ++ ++#define luaO_nilobject (&luaO_nilobject_) ++ ++LUAI_DATA const TValue luaO_nilobject_; ++ ++#define ceillog2(x) (luaO_log2((x)-1) + 1) ++ ++LUAI_FUNC int luaO_log2 (unsigned int x); ++LUAI_FUNC int luaO_int2fb (unsigned int x); ++LUAI_FUNC int luaO_fb2int (int x); ++LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); ++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); ++LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, ++ va_list argp); ++LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); ++LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); ++ ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lopcodes.c +@@ -0,0 +1,102 @@ ++/* ++** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#define lopcodes_c ++#define LUA_CORE ++ ++ ++#include "lopcodes.h" ++ ++ ++/* ORDER OP */ ++ ++const char *const luaP_opnames[NUM_OPCODES+1] = { ++ "MOVE", ++ "LOADK", ++ "LOADBOOL", ++ "LOADNIL", ++ "GETUPVAL", ++ "GETGLOBAL", ++ "GETTABLE", ++ "SETGLOBAL", ++ "SETUPVAL", ++ "SETTABLE", ++ "NEWTABLE", ++ "SELF", ++ "ADD", ++ "SUB", ++ "MUL", ++ "DIV", ++ "MOD", ++ "POW", ++ "UNM", ++ "NOT", ++ "LEN", ++ "CONCAT", ++ "JMP", ++ "EQ", ++ "LT", ++ "LE", ++ "TEST", ++ "TESTSET", ++ "CALL", ++ "TAILCALL", ++ "RETURN", ++ "FORLOOP", ++ "FORPREP", ++ "TFORLOOP", ++ "SETLIST", ++ "CLOSE", ++ "CLOSURE", ++ "VARARG", ++ NULL ++}; ++ ++ ++#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) ++ ++const lu_byte luaP_opmodes[NUM_OPCODES] = { ++/* T A B C mode opcode */ ++ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ ++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ ++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ ++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ ++ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ ++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ++ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ ++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ ++ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ ++ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ ++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ ++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ ++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ ++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ ++ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ ++ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ ++ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ ++}; ++ +--- /dev/null ++++ b/extensions/LUA/lua/lopcodes.h +@@ -0,0 +1,268 @@ ++/* ++** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Opcodes for Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lopcodes_h ++#define lopcodes_h ++ ++#include "llimits.h" ++ ++ ++/*=========================================================================== ++ We assume that instructions are unsigned numbers. ++ All instructions have an opcode in the first 6 bits. ++ Instructions can have the following fields: ++ `A' : 8 bits ++ `B' : 9 bits ++ `C' : 9 bits ++ `Bx' : 18 bits (`B' and `C' together) ++ `sBx' : signed Bx ++ ++ A signed argument is represented in excess K; that is, the number ++ value is the unsigned value minus K. K is exactly the maximum value ++ for that argument (so that -max is represented by 0, and +max is ++ represented by 2*max), which is half the maximum for the corresponding ++ unsigned argument. ++===========================================================================*/ ++ ++ ++enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ ++ ++ ++/* ++** size and position of opcode arguments. ++*/ ++#define SIZE_C 9 ++#define SIZE_B 9 ++#define SIZE_Bx (SIZE_C + SIZE_B) ++#define SIZE_A 8 ++ ++#define SIZE_OP 6 ++ ++#define POS_OP 0 ++#define POS_A (POS_OP + SIZE_OP) ++#define POS_C (POS_A + SIZE_A) ++#define POS_B (POS_C + SIZE_C) ++#define POS_Bx POS_C ++ ++ ++/* ++** limits for opcode arguments. ++** we use (signed) int to manipulate most arguments, ++** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) ++*/ ++#if SIZE_Bx < LUAI_BITSINT-1 ++#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ ++#else ++#define MAXARG_Bx MAX_INT ++#define MAXARG_sBx MAX_INT ++#endif ++ ++ ++#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) ++#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ ++ ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) ++#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ ++ ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) ++#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ ++ ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) ++#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ ++ ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) ++#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ ++ ((cast(Instruction, b)< C) then pc++ */ ++OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ ++ ++OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ ++OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ ++OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ ++ ++OP_FORLOOP,/* A sBx R(A)+=R(A+2); ++ if R(A) =) R(A)*/ ++OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ ++ ++OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ ++} OpCode; ++ ++ ++#define NUM_OPCODES (cast(int, OP_VARARG) + 1) ++ ++ ++ ++/*=========================================================================== ++ Notes: ++ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, ++ and can be 0: OP_CALL then sets `top' to last_result+1, so ++ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. ++ ++ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and ++ set top (like in OP_CALL with C == 0). ++ ++ (*) In OP_RETURN, if (B == 0) then return up to `top' ++ ++ (*) In OP_SETLIST, if (B == 0) then B = `top'; ++ if (C == 0) then next `instruction' is real C ++ ++ (*) For comparisons, A specifies what condition the test should accept ++ (true or false). ++ ++ (*) All `skips' (pc++) assume that next instruction is a jump ++===========================================================================*/ ++ ++ ++/* ++** masks for instruction properties. The format is: ++** bits 0-1: op mode ++** bits 2-3: C arg mode ++** bits 4-5: B arg mode ++** bit 6: instruction set register A ++** bit 7: operator is a test ++*/ ++ ++enum OpArgMask { ++ OpArgN, /* argument is not used */ ++ OpArgU, /* argument is used */ ++ OpArgR, /* argument is a register or a jump offset */ ++ OpArgK /* argument is a constant or register/constant */ ++}; ++ ++LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; ++ ++#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) ++#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) ++#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) ++#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) ++#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) ++ ++ ++LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ ++ ++ ++/* number of list items to accumulate before a SETLIST instruction */ ++#define LFIELDS_PER_FLUSH 50 ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lparser.c +@@ -0,0 +1,1339 @@ ++/* ++** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Lua Parser ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lparser_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++ ++ ++ ++#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) ++ ++#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) ++ ++#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) ++ ++ ++/* ++** nodes for block list (list of active blocks) ++*/ ++typedef struct BlockCnt { ++ struct BlockCnt *previous; /* chain */ ++ int breaklist; /* list of jumps out of this loop */ ++ lu_byte nactvar; /* # active locals outside the breakable structure */ ++ lu_byte upval; /* true if some variable in the block is an upvalue */ ++ lu_byte isbreakable; /* true if `block' is a loop */ ++} BlockCnt; ++ ++ ++ ++/* ++** prototypes for recursive non-terminal functions ++*/ ++static void chunk (LexState *ls); ++static void expr (LexState *ls, expdesc *v); ++ ++ ++static void anchor_token (LexState *ls) { ++ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { ++ TString *ts = ls->t.seminfo.ts; ++ luaX_newstring(ls, getstr(ts), ts->tsv.len); ++ } ++} ++ ++ ++static void error_expected (LexState *ls, int token) { ++ luaX_syntaxerror(ls, ++ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); ++} ++ ++ ++static void errorlimit (FuncState *fs, int limit, const char *what) { ++ const char *msg = (fs->f->linedefined == 0) ? ++ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : ++ luaO_pushfstring(fs->L, "function at line %d has more than %d %s", ++ fs->f->linedefined, limit, what); ++ luaX_lexerror(fs->ls, msg, 0); ++} ++ ++ ++static int testnext (LexState *ls, int c) { ++ if (ls->t.token == c) { ++ luaX_next(ls); ++ return 1; ++ } ++ else return 0; ++} ++ ++ ++static void check (LexState *ls, int c) { ++ if (ls->t.token != c) ++ error_expected(ls, c); ++} ++ ++static void checknext (LexState *ls, int c) { ++ check(ls, c); ++ luaX_next(ls); ++} ++ ++ ++#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } ++ ++ ++ ++static void check_match (LexState *ls, int what, int who, int where) { ++ if (!testnext(ls, what)) { ++ if (where == ls->linenumber) ++ error_expected(ls, what); ++ else { ++ luaX_syntaxerror(ls, luaO_pushfstring(ls->L, ++ LUA_QS " expected (to close " LUA_QS " at line %d)", ++ luaX_token2str(ls, what), luaX_token2str(ls, who), where)); ++ } ++ } ++} ++ ++ ++static TString *str_checkname (LexState *ls) { ++ TString *ts; ++ check(ls, TK_NAME); ++ ts = ls->t.seminfo.ts; ++ luaX_next(ls); ++ return ts; ++} ++ ++ ++static void init_exp (expdesc *e, expkind k, int i) { ++ e->f = e->t = NO_JUMP; ++ e->k = k; ++ e->u.s.info = i; ++} ++ ++ ++static void codestring (LexState *ls, expdesc *e, TString *s) { ++ init_exp(e, VK, luaK_stringK(ls->fs, s)); ++} ++ ++ ++static void checkname(LexState *ls, expdesc *e) { ++ codestring(ls, e, str_checkname(ls)); ++} ++ ++ ++static int registerlocalvar (LexState *ls, TString *varname) { ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int oldsize = f->sizelocvars; ++ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, ++ LocVar, SHRT_MAX, "too many local variables"); ++ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; ++ f->locvars[fs->nlocvars].varname = varname; ++ luaC_objbarrier(ls->L, f, varname); ++ return fs->nlocvars++; ++} ++ ++ ++#define new_localvarliteral(ls,v,n) \ ++ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) ++ ++ ++static void new_localvar (LexState *ls, TString *name, int n) { ++ FuncState *fs = ls->fs; ++ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); ++ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); ++} ++ ++ ++static void adjustlocalvars (LexState *ls, int nvars) { ++ FuncState *fs = ls->fs; ++ fs->nactvar = cast_byte(fs->nactvar + nvars); ++ for (; nvars; nvars--) { ++ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; ++ } ++} ++ ++ ++static void removevars (LexState *ls, int tolevel) { ++ FuncState *fs = ls->fs; ++ while (fs->nactvar > tolevel) ++ getlocvar(fs, --fs->nactvar).endpc = fs->pc; ++} ++ ++ ++static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { ++ int i; ++ Proto *f = fs->f; ++ int oldsize = f->sizeupvalues; ++ for (i=0; inups; i++) { ++ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { ++ lua_assert(f->upvalues[i] == name); ++ return i; ++ } ++ } ++ /* new one */ ++ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); ++ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, ++ TString *, MAX_INT, ""); ++ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; ++ f->upvalues[f->nups] = name; ++ luaC_objbarrier(fs->L, f, name); ++ lua_assert(v->k == VLOCAL || v->k == VUPVAL); ++ fs->upvalues[f->nups].k = cast_byte(v->k); ++ fs->upvalues[f->nups].info = cast_byte(v->u.s.info); ++ return f->nups++; ++} ++ ++ ++static int searchvar (FuncState *fs, TString *n) { ++ int i; ++ for (i=fs->nactvar-1; i >= 0; i--) { ++ if (n == getlocvar(fs, i).varname) ++ return i; ++ } ++ return -1; /* not found */ ++} ++ ++ ++static void markupval (FuncState *fs, int level) { ++ BlockCnt *bl = fs->bl; ++ while (bl && bl->nactvar > level) bl = bl->previous; ++ if (bl) bl->upval = 1; ++} ++ ++ ++static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { ++ if (fs == NULL) { /* no more levels? */ ++ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ ++ return VGLOBAL; ++ } ++ else { ++ int v = searchvar(fs, n); /* look up at current level */ ++ if (v >= 0) { ++ init_exp(var, VLOCAL, v); ++ if (!base) ++ markupval(fs, v); /* local will be used as an upval */ ++ return VLOCAL; ++ } ++ else { /* not found at current level; try upper one */ ++ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) ++ return VGLOBAL; ++ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ ++ var->k = VUPVAL; /* upvalue in this level */ ++ return VUPVAL; ++ } ++ } ++} ++ ++ ++static void singlevar (LexState *ls, expdesc *var) { ++ TString *varname = str_checkname(ls); ++ FuncState *fs = ls->fs; ++ if (singlevaraux(fs, varname, var, 1) == VGLOBAL) ++ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ ++} ++ ++ ++static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { ++ FuncState *fs = ls->fs; ++ int extra = nvars - nexps; ++ if (hasmultret(e->k)) { ++ extra++; /* includes call itself */ ++ if (extra < 0) extra = 0; ++ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ ++ if (extra > 1) luaK_reserveregs(fs, extra-1); ++ } ++ else { ++ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ ++ if (extra > 0) { ++ int reg = fs->freereg; ++ luaK_reserveregs(fs, extra); ++ luaK_nil(fs, reg, extra); ++ } ++ } ++} ++ ++ ++static void enterlevel (LexState *ls) { ++ if (++ls->L->nCcalls > LUAI_MAXCCALLS) ++ luaX_lexerror(ls, "chunk has too many syntax levels", 0); ++} ++ ++ ++#define leavelevel(ls) ((ls)->L->nCcalls--) ++ ++ ++static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { ++ bl->breaklist = NO_JUMP; ++ bl->isbreakable = isbreakable; ++ bl->nactvar = fs->nactvar; ++ bl->upval = 0; ++ bl->previous = fs->bl; ++ fs->bl = bl; ++ lua_assert(fs->freereg == fs->nactvar); ++} ++ ++ ++static void leaveblock (FuncState *fs) { ++ BlockCnt *bl = fs->bl; ++ fs->bl = bl->previous; ++ removevars(fs->ls, bl->nactvar); ++ if (bl->upval) ++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); ++ /* a block either controls scope or breaks (never both) */ ++ lua_assert(!bl->isbreakable || !bl->upval); ++ lua_assert(bl->nactvar == fs->nactvar); ++ fs->freereg = fs->nactvar; /* free registers */ ++ luaK_patchtohere(fs, bl->breaklist); ++} ++ ++ ++static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int oldsize = f->sizep; ++ int i; ++ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, ++ MAXARG_Bx, "constant table overflow"); ++ while (oldsize < f->sizep) f->p[oldsize++] = NULL; ++ f->p[fs->np++] = func->f; ++ luaC_objbarrier(ls->L, f, func->f); ++ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); ++ for (i=0; if->nups; i++) { ++ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; ++ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); ++ } ++} ++ ++ ++static void open_func (LexState *ls, FuncState *fs) { ++ lua_State *L = ls->L; ++ Proto *f = luaF_newproto(L); ++ fs->f = f; ++ fs->prev = ls->fs; /* linked list of funcstates */ ++ fs->ls = ls; ++ fs->L = L; ++ ls->fs = fs; ++ fs->pc = 0; ++ fs->lasttarget = -1; ++ fs->jpc = NO_JUMP; ++ fs->freereg = 0; ++ fs->nk = 0; ++ fs->np = 0; ++ fs->nlocvars = 0; ++ fs->nactvar = 0; ++ fs->bl = NULL; ++ f->source = ls->source; ++ f->maxstacksize = 2; /* registers 0/1 are always valid */ ++ fs->h = luaH_new(L, 0, 0); ++ /* anchor table of constants and prototype (to avoid being collected) */ ++ sethvalue2s(L, L->top, fs->h); ++ incr_top(L); ++ setptvalue2s(L, L->top, f); ++ incr_top(L); ++} ++ ++ ++static void close_func (LexState *ls) { ++ lua_State *L = ls->L; ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ removevars(ls, 0); ++ luaK_ret(fs, 0, 0); /* final return */ ++ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); ++ f->sizecode = fs->pc; ++ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); ++ f->sizelineinfo = fs->pc; ++ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); ++ f->sizek = fs->nk; ++ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); ++ f->sizep = fs->np; ++ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); ++ f->sizelocvars = fs->nlocvars; ++ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); ++ f->sizeupvalues = f->nups; ++ lua_assert(luaG_checkcode(f)); ++ lua_assert(fs->bl == NULL); ++ ls->fs = fs->prev; ++ L->top -= 2; /* remove table and prototype from the stack */ ++ /* last token read was anchored in defunct function; must reanchor it */ ++ if (fs) anchor_token(ls); ++} ++ ++ ++Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { ++ struct LexState lexstate; ++ struct FuncState funcstate; ++ lexstate.buff = buff; ++ luaX_setinput(L, &lexstate, z, luaS_new(L, name)); ++ open_func(&lexstate, &funcstate); ++ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ ++ luaX_next(&lexstate); /* read first token */ ++ chunk(&lexstate); ++ check(&lexstate, TK_EOS); ++ close_func(&lexstate); ++ lua_assert(funcstate.prev == NULL); ++ lua_assert(funcstate.f->nups == 0); ++ lua_assert(lexstate.fs == NULL); ++ return funcstate.f; ++} ++ ++ ++ ++/*============================================================*/ ++/* GRAMMAR RULES */ ++/*============================================================*/ ++ ++ ++static void field (LexState *ls, expdesc *v) { ++ /* field -> ['.' | ':'] NAME */ ++ FuncState *fs = ls->fs; ++ expdesc key; ++ luaK_exp2anyreg(fs, v); ++ luaX_next(ls); /* skip the dot or colon */ ++ checkname(ls, &key); ++ luaK_indexed(fs, v, &key); ++} ++ ++ ++static void yindex (LexState *ls, expdesc *v) { ++ /* index -> '[' expr ']' */ ++ luaX_next(ls); /* skip the '[' */ ++ expr(ls, v); ++ luaK_exp2val(ls->fs, v); ++ checknext(ls, ']'); ++} ++ ++ ++/* ++** {====================================================================== ++** Rules for Constructors ++** ======================================================================= ++*/ ++ ++ ++struct ConsControl { ++ expdesc v; /* last list item read */ ++ expdesc *t; /* table descriptor */ ++ int nh; /* total number of `record' elements */ ++ int na; /* total number of array elements */ ++ int tostore; /* number of array elements pending to be stored */ ++}; ++ ++ ++static void recfield (LexState *ls, struct ConsControl *cc) { ++ /* recfield -> (NAME | `['exp1`]') = exp1 */ ++ FuncState *fs = ls->fs; ++ int reg = ls->fs->freereg; ++ expdesc key, val; ++ int rkkey; ++ if (ls->t.token == TK_NAME) { ++ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); ++ checkname(ls, &key); ++ } ++ else /* ls->t.token == '[' */ ++ yindex(ls, &key); ++ cc->nh++; ++ checknext(ls, '='); ++ rkkey = luaK_exp2RK(fs, &key); ++ expr(ls, &val); ++ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); ++ fs->freereg = reg; /* free registers */ ++} ++ ++ ++static void closelistfield (FuncState *fs, struct ConsControl *cc) { ++ if (cc->v.k == VVOID) return; /* there is no list item */ ++ luaK_exp2nextreg(fs, &cc->v); ++ cc->v.k = VVOID; ++ if (cc->tostore == LFIELDS_PER_FLUSH) { ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ ++ cc->tostore = 0; /* no more items pending */ ++ } ++} ++ ++ ++static void lastlistfield (FuncState *fs, struct ConsControl *cc) { ++ if (cc->tostore == 0) return; ++ if (hasmultret(cc->v.k)) { ++ luaK_setmultret(fs, &cc->v); ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); ++ cc->na--; /* do not count last expression (unknown number of elements) */ ++ } ++ else { ++ if (cc->v.k != VVOID) ++ luaK_exp2nextreg(fs, &cc->v); ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); ++ } ++} ++ ++ ++static void listfield (LexState *ls, struct ConsControl *cc) { ++ expr(ls, &cc->v); ++ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); ++ cc->na++; ++ cc->tostore++; ++} ++ ++ ++static void constructor (LexState *ls, expdesc *t) { ++ /* constructor -> ?? */ ++ FuncState *fs = ls->fs; ++ int line = ls->linenumber; ++ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); ++ struct ConsControl cc; ++ cc.na = cc.nh = cc.tostore = 0; ++ cc.t = t; ++ init_exp(t, VRELOCABLE, pc); ++ init_exp(&cc.v, VVOID, 0); /* no value (yet) */ ++ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ ++ checknext(ls, '{'); ++ do { ++ lua_assert(cc.v.k == VVOID || cc.tostore > 0); ++ if (ls->t.token == '}') break; ++ closelistfield(fs, &cc); ++ switch(ls->t.token) { ++ case TK_NAME: { /* may be listfields or recfields */ ++ luaX_lookahead(ls); ++ if (ls->lookahead.token != '=') /* expression? */ ++ listfield(ls, &cc); ++ else ++ recfield(ls, &cc); ++ break; ++ } ++ case '[': { /* constructor_item -> recfield */ ++ recfield(ls, &cc); ++ break; ++ } ++ default: { /* constructor_part -> listfield */ ++ listfield(ls, &cc); ++ break; ++ } ++ } ++ } while (testnext(ls, ',') || testnext(ls, ';')); ++ check_match(ls, '}', '{', line); ++ lastlistfield(fs, &cc); ++ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ ++ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ ++} ++ ++/* }====================================================================== */ ++ ++ ++ ++static void parlist (LexState *ls) { ++ /* parlist -> [ param { `,' param } ] */ ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int nparams = 0; ++ f->is_vararg = 0; ++ if (ls->t.token != ')') { /* is `parlist' not empty? */ ++ do { ++ switch (ls->t.token) { ++ case TK_NAME: { /* param -> NAME */ ++ new_localvar(ls, str_checkname(ls), nparams++); ++ break; ++ } ++ case TK_DOTS: { /* param -> `...' */ ++ luaX_next(ls); ++#if defined(LUA_COMPAT_VARARG) ++ /* use `arg' as default name */ ++ new_localvarliteral(ls, "arg", nparams++); ++ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; ++#endif ++ f->is_vararg |= VARARG_ISVARARG; ++ break; ++ } ++ default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); ++ } ++ } while (!f->is_vararg && testnext(ls, ',')); ++ } ++ adjustlocalvars(ls, nparams); ++ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); ++ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ ++} ++ ++ ++static void body (LexState *ls, expdesc *e, int needself, int line) { ++ /* body -> `(' parlist `)' chunk END */ ++ FuncState new_fs; ++ open_func(ls, &new_fs); ++ new_fs.f->linedefined = line; ++ checknext(ls, '('); ++ if (needself) { ++ new_localvarliteral(ls, "self", 0); ++ adjustlocalvars(ls, 1); ++ } ++ parlist(ls); ++ checknext(ls, ')'); ++ chunk(ls); ++ new_fs.f->lastlinedefined = ls->linenumber; ++ check_match(ls, TK_END, TK_FUNCTION, line); ++ close_func(ls); ++ pushclosure(ls, &new_fs, e); ++} ++ ++ ++static int explist1 (LexState *ls, expdesc *v) { ++ /* explist1 -> expr { `,' expr } */ ++ int n = 1; /* at least one expression */ ++ expr(ls, v); ++ while (testnext(ls, ',')) { ++ luaK_exp2nextreg(ls->fs, v); ++ expr(ls, v); ++ n++; ++ } ++ return n; ++} ++ ++ ++static void funcargs (LexState *ls, expdesc *f) { ++ FuncState *fs = ls->fs; ++ expdesc args; ++ int base, nparams; ++ int line = ls->linenumber; ++ switch (ls->t.token) { ++ case '(': { /* funcargs -> `(' [ explist1 ] `)' */ ++ if (line != ls->lastline) ++ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); ++ luaX_next(ls); ++ if (ls->t.token == ')') /* arg list is empty? */ ++ args.k = VVOID; ++ else { ++ explist1(ls, &args); ++ luaK_setmultret(fs, &args); ++ } ++ check_match(ls, ')', '(', line); ++ break; ++ } ++ case '{': { /* funcargs -> constructor */ ++ constructor(ls, &args); ++ break; ++ } ++ case TK_STRING: { /* funcargs -> STRING */ ++ codestring(ls, &args, ls->t.seminfo.ts); ++ luaX_next(ls); /* must use `seminfo' before `next' */ ++ break; ++ } ++ default: { ++ luaX_syntaxerror(ls, "function arguments expected"); ++ return; ++ } ++ } ++ lua_assert(f->k == VNONRELOC); ++ base = f->u.s.info; /* base register for call */ ++ if (hasmultret(args.k)) ++ nparams = LUA_MULTRET; /* open call */ ++ else { ++ if (args.k != VVOID) ++ luaK_exp2nextreg(fs, &args); /* close last argument */ ++ nparams = fs->freereg - (base+1); ++ } ++ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); ++ luaK_fixline(fs, line); ++ fs->freereg = base+1; /* call remove function and arguments and leaves ++ (unless changed) one result */ ++} ++ ++ ++ ++ ++/* ++** {====================================================================== ++** Expression parsing ++** ======================================================================= ++*/ ++ ++ ++static void prefixexp (LexState *ls, expdesc *v) { ++ /* prefixexp -> NAME | '(' expr ')' */ ++ switch (ls->t.token) { ++ case '(': { ++ int line = ls->linenumber; ++ luaX_next(ls); ++ expr(ls, v); ++ check_match(ls, ')', '(', line); ++ luaK_dischargevars(ls->fs, v); ++ return; ++ } ++ case TK_NAME: { ++ singlevar(ls, v); ++ return; ++ } ++ default: { ++ luaX_syntaxerror(ls, "unexpected symbol"); ++ return; ++ } ++ } ++} ++ ++ ++static void primaryexp (LexState *ls, expdesc *v) { ++ /* primaryexp -> ++ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ ++ FuncState *fs = ls->fs; ++ prefixexp(ls, v); ++ for (;;) { ++ switch (ls->t.token) { ++ case '.': { /* field */ ++ field(ls, v); ++ break; ++ } ++ case '[': { /* `[' exp1 `]' */ ++ expdesc key; ++ luaK_exp2anyreg(fs, v); ++ yindex(ls, &key); ++ luaK_indexed(fs, v, &key); ++ break; ++ } ++ case ':': { /* `:' NAME funcargs */ ++ expdesc key; ++ luaX_next(ls); ++ checkname(ls, &key); ++ luaK_self(fs, v, &key); ++ funcargs(ls, v); ++ break; ++ } ++ case '(': case TK_STRING: case '{': { /* funcargs */ ++ luaK_exp2nextreg(fs, v); ++ funcargs(ls, v); ++ break; ++ } ++ default: return; ++ } ++ } ++} ++ ++ ++static void simpleexp (LexState *ls, expdesc *v) { ++ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | ++ constructor | FUNCTION body | primaryexp */ ++ switch (ls->t.token) { ++ case TK_NUMBER: { ++ init_exp(v, VKNUM, 0); ++ v->u.nval = ls->t.seminfo.r; ++ break; ++ } ++ case TK_STRING: { ++ codestring(ls, v, ls->t.seminfo.ts); ++ break; ++ } ++ case TK_NIL: { ++ init_exp(v, VNIL, 0); ++ break; ++ } ++ case TK_TRUE: { ++ init_exp(v, VTRUE, 0); ++ break; ++ } ++ case TK_FALSE: { ++ init_exp(v, VFALSE, 0); ++ break; ++ } ++ case TK_DOTS: { /* vararg */ ++ FuncState *fs = ls->fs; ++ check_condition(ls, fs->f->is_vararg, ++ "cannot use " LUA_QL("...") " outside a vararg function"); ++ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ ++ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); ++ break; ++ } ++ case '{': { /* constructor */ ++ constructor(ls, v); ++ return; ++ } ++ case TK_FUNCTION: { ++ luaX_next(ls); ++ body(ls, v, 0, ls->linenumber); ++ return; ++ } ++ default: { ++ primaryexp(ls, v); ++ return; ++ } ++ } ++ luaX_next(ls); ++} ++ ++ ++static UnOpr getunopr (int op) { ++ switch (op) { ++ case TK_NOT: return OPR_NOT; ++ case '-': return OPR_MINUS; ++ case '#': return OPR_LEN; ++ default: return OPR_NOUNOPR; ++ } ++} ++ ++ ++static BinOpr getbinopr (int op) { ++ switch (op) { ++ case '+': return OPR_ADD; ++ case '-': return OPR_SUB; ++ case '*': return OPR_MUL; ++ case '/': return OPR_DIV; ++ case '%': return OPR_MOD; ++ case '^': return OPR_POW; ++ case TK_CONCAT: return OPR_CONCAT; ++ case TK_NE: return OPR_NE; ++ case TK_EQ: return OPR_EQ; ++ case '<': return OPR_LT; ++ case TK_LE: return OPR_LE; ++ case '>': return OPR_GT; ++ case TK_GE: return OPR_GE; ++ case TK_AND: return OPR_AND; ++ case TK_OR: return OPR_OR; ++ default: return OPR_NOBINOPR; ++ } ++} ++ ++ ++static const struct { ++ lu_byte left; /* left priority for each binary operator */ ++ lu_byte right; /* right priority */ ++} priority[] = { /* ORDER OPR */ ++ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ ++ {10, 9}, {5, 4}, /* power and concat (right associative) */ ++ {3, 3}, {3, 3}, /* equality and inequality */ ++ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ ++ {2, 2}, {1, 1} /* logical (and/or) */ ++}; ++ ++#define UNARY_PRIORITY 8 /* priority for unary operators */ ++ ++ ++/* ++** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ++** where `binop' is any binary operator with a priority higher than `limit' ++*/ ++static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { ++ BinOpr op; ++ UnOpr uop; ++ enterlevel(ls); ++ uop = getunopr(ls->t.token); ++ if (uop != OPR_NOUNOPR) { ++ luaX_next(ls); ++ subexpr(ls, v, UNARY_PRIORITY); ++ luaK_prefix(ls->fs, uop, v); ++ } ++ else simpleexp(ls, v); ++ /* expand while operators have priorities higher than `limit' */ ++ op = getbinopr(ls->t.token); ++ while (op != OPR_NOBINOPR && priority[op].left > limit) { ++ expdesc v2; ++ BinOpr nextop; ++ luaX_next(ls); ++ luaK_infix(ls->fs, op, v); ++ /* read sub-expression with higher priority */ ++ nextop = subexpr(ls, &v2, priority[op].right); ++ luaK_posfix(ls->fs, op, v, &v2); ++ op = nextop; ++ } ++ leavelevel(ls); ++ return op; /* return first untreated operator */ ++} ++ ++ ++static void expr (LexState *ls, expdesc *v) { ++ subexpr(ls, v, 0); ++} ++ ++/* }==================================================================== */ ++ ++ ++ ++/* ++** {====================================================================== ++** Rules for Statements ++** ======================================================================= ++*/ ++ ++ ++static int block_follow (int token) { ++ switch (token) { ++ case TK_ELSE: case TK_ELSEIF: case TK_END: ++ case TK_UNTIL: case TK_EOS: ++ return 1; ++ default: return 0; ++ } ++} ++ ++ ++static void block (LexState *ls) { ++ /* block -> chunk */ ++ FuncState *fs = ls->fs; ++ BlockCnt bl; ++ enterblock(fs, &bl, 0); ++ chunk(ls); ++ lua_assert(bl.breaklist == NO_JUMP); ++ leaveblock(fs); ++} ++ ++ ++/* ++** structure to chain all variables in the left-hand side of an ++** assignment ++*/ ++struct LHS_assign { ++ struct LHS_assign *prev; ++ expdesc v; /* variable (global, local, upvalue, or indexed) */ ++}; ++ ++ ++/* ++** check whether, in an assignment to a local variable, the local variable ++** is needed in a previous assignment (to a table). If so, save original ++** local value in a safe place and use this safe copy in the previous ++** assignment. ++*/ ++static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { ++ FuncState *fs = ls->fs; ++ int extra = fs->freereg; /* eventual position to save local variable */ ++ int conflict = 0; ++ for (; lh; lh = lh->prev) { ++ if (lh->v.k == VINDEXED) { ++ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ ++ conflict = 1; ++ lh->v.u.s.info = extra; /* previous assignment will use safe copy */ ++ } ++ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ ++ conflict = 1; ++ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ ++ } ++ } ++ } ++ if (conflict) { ++ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ ++ luaK_reserveregs(fs, 1); ++ } ++} ++ ++ ++static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { ++ expdesc e; ++ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, ++ "syntax error"); ++ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ ++ struct LHS_assign nv; ++ nv.prev = lh; ++ primaryexp(ls, &nv.v); ++ if (nv.v.k == VLOCAL) ++ check_conflict(ls, lh, &nv.v); ++ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, ++ "variables in assignment"); ++ assignment(ls, &nv, nvars+1); ++ } ++ else { /* assignment -> `=' explist1 */ ++ int nexps; ++ checknext(ls, '='); ++ nexps = explist1(ls, &e); ++ if (nexps != nvars) { ++ adjust_assign(ls, nvars, nexps, &e); ++ if (nexps > nvars) ++ ls->fs->freereg -= nexps - nvars; /* remove extra values */ ++ } ++ else { ++ luaK_setoneret(ls->fs, &e); /* close last expression */ ++ luaK_storevar(ls->fs, &lh->v, &e); ++ return; /* avoid default */ ++ } ++ } ++ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ ++ luaK_storevar(ls->fs, &lh->v, &e); ++} ++ ++ ++static int cond (LexState *ls) { ++ /* cond -> exp */ ++ expdesc v; ++ expr(ls, &v); /* read condition */ ++ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ ++ luaK_goiftrue(ls->fs, &v); ++ return v.f; ++} ++ ++ ++static void breakstat (LexState *ls) { ++ FuncState *fs = ls->fs; ++ BlockCnt *bl = fs->bl; ++ int upval = 0; ++ while (bl && !bl->isbreakable) { ++ upval |= bl->upval; ++ bl = bl->previous; ++ } ++ if (!bl) ++ luaX_syntaxerror(ls, "no loop to break"); ++ if (upval) ++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); ++ luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); ++} ++ ++ ++static void whilestat (LexState *ls, int line) { ++ /* whilestat -> WHILE cond DO block END */ ++ FuncState *fs = ls->fs; ++ int whileinit; ++ int condexit; ++ BlockCnt bl; ++ luaX_next(ls); /* skip WHILE */ ++ whileinit = luaK_getlabel(fs); ++ condexit = cond(ls); ++ enterblock(fs, &bl, 1); ++ checknext(ls, TK_DO); ++ block(ls); ++ luaK_patchlist(fs, luaK_jump(fs), whileinit); ++ check_match(ls, TK_END, TK_WHILE, line); ++ leaveblock(fs); ++ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ ++} ++ ++ ++static void repeatstat (LexState *ls, int line) { ++ /* repeatstat -> REPEAT block UNTIL cond */ ++ int condexit; ++ FuncState *fs = ls->fs; ++ int repeat_init = luaK_getlabel(fs); ++ BlockCnt bl1, bl2; ++ enterblock(fs, &bl1, 1); /* loop block */ ++ enterblock(fs, &bl2, 0); /* scope block */ ++ luaX_next(ls); /* skip REPEAT */ ++ chunk(ls); ++ check_match(ls, TK_UNTIL, TK_REPEAT, line); ++ condexit = cond(ls); /* read condition (inside scope block) */ ++ if (!bl2.upval) { /* no upvalues? */ ++ leaveblock(fs); /* finish scope */ ++ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ ++ } ++ else { /* complete semantics when there are upvalues */ ++ breakstat(ls); /* if condition then break */ ++ luaK_patchtohere(ls->fs, condexit); /* else... */ ++ leaveblock(fs); /* finish scope... */ ++ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ ++ } ++ leaveblock(fs); /* finish loop */ ++} ++ ++ ++static int exp1 (LexState *ls) { ++ expdesc e; ++ int k; ++ expr(ls, &e); ++ k = e.k; ++ luaK_exp2nextreg(ls->fs, &e); ++ return k; ++} ++ ++ ++static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { ++ /* forbody -> DO block */ ++ BlockCnt bl; ++ FuncState *fs = ls->fs; ++ int prep, endfor; ++ adjustlocalvars(ls, 3); /* control variables */ ++ checknext(ls, TK_DO); ++ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); ++ enterblock(fs, &bl, 0); /* scope for declared variables */ ++ adjustlocalvars(ls, nvars); ++ luaK_reserveregs(fs, nvars); ++ block(ls); ++ leaveblock(fs); /* end of scope for declared variables */ ++ luaK_patchtohere(fs, prep); ++ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : ++ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); ++ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ ++ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); ++} ++ ++ ++static void fornum (LexState *ls, TString *varname, int line) { ++ /* fornum -> NAME = exp1,exp1[,exp1] forbody */ ++ FuncState *fs = ls->fs; ++ int base = fs->freereg; ++ new_localvarliteral(ls, "(for index)", 0); ++ new_localvarliteral(ls, "(for limit)", 1); ++ new_localvarliteral(ls, "(for step)", 2); ++ new_localvar(ls, varname, 3); ++ checknext(ls, '='); ++ exp1(ls); /* initial value */ ++ checknext(ls, ','); ++ exp1(ls); /* limit */ ++ if (testnext(ls, ',')) ++ exp1(ls); /* optional step */ ++ else { /* default step = 1 */ ++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); ++ luaK_reserveregs(fs, 1); ++ } ++ forbody(ls, base, line, 1, 1); ++} ++ ++ ++static void forlist (LexState *ls, TString *indexname) { ++ /* forlist -> NAME {,NAME} IN explist1 forbody */ ++ FuncState *fs = ls->fs; ++ expdesc e; ++ int nvars = 0; ++ int line; ++ int base = fs->freereg; ++ /* create control variables */ ++ new_localvarliteral(ls, "(for generator)", nvars++); ++ new_localvarliteral(ls, "(for state)", nvars++); ++ new_localvarliteral(ls, "(for control)", nvars++); ++ /* create declared variables */ ++ new_localvar(ls, indexname, nvars++); ++ while (testnext(ls, ',')) ++ new_localvar(ls, str_checkname(ls), nvars++); ++ checknext(ls, TK_IN); ++ line = ls->linenumber; ++ adjust_assign(ls, 3, explist1(ls, &e), &e); ++ luaK_checkstack(fs, 3); /* extra space to call generator */ ++ forbody(ls, base, line, nvars - 3, 0); ++} ++ ++ ++static void forstat (LexState *ls, int line) { ++ /* forstat -> FOR (fornum | forlist) END */ ++ FuncState *fs = ls->fs; ++ TString *varname; ++ BlockCnt bl; ++ enterblock(fs, &bl, 1); /* scope for loop and control variables */ ++ luaX_next(ls); /* skip `for' */ ++ varname = str_checkname(ls); /* first variable name */ ++ switch (ls->t.token) { ++ case '=': fornum(ls, varname, line); break; ++ case ',': case TK_IN: forlist(ls, varname); break; ++ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); ++ } ++ check_match(ls, TK_END, TK_FOR, line); ++ leaveblock(fs); /* loop scope (`break' jumps to this point) */ ++} ++ ++ ++static int test_then_block (LexState *ls) { ++ /* test_then_block -> [IF | ELSEIF] cond THEN block */ ++ int condexit; ++ luaX_next(ls); /* skip IF or ELSEIF */ ++ condexit = cond(ls); ++ checknext(ls, TK_THEN); ++ block(ls); /* `then' part */ ++ return condexit; ++} ++ ++ ++static void ifstat (LexState *ls, int line) { ++ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ ++ FuncState *fs = ls->fs; ++ int flist; ++ int escapelist = NO_JUMP; ++ flist = test_then_block(ls); /* IF cond THEN block */ ++ while (ls->t.token == TK_ELSEIF) { ++ luaK_concat(fs, &escapelist, luaK_jump(fs)); ++ luaK_patchtohere(fs, flist); ++ flist = test_then_block(ls); /* ELSEIF cond THEN block */ ++ } ++ if (ls->t.token == TK_ELSE) { ++ luaK_concat(fs, &escapelist, luaK_jump(fs)); ++ luaK_patchtohere(fs, flist); ++ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ ++ block(ls); /* `else' part */ ++ } ++ else ++ luaK_concat(fs, &escapelist, flist); ++ luaK_patchtohere(fs, escapelist); ++ check_match(ls, TK_END, TK_IF, line); ++} ++ ++ ++static void localfunc (LexState *ls) { ++ expdesc v, b; ++ FuncState *fs = ls->fs; ++ new_localvar(ls, str_checkname(ls), 0); ++ init_exp(&v, VLOCAL, fs->freereg); ++ luaK_reserveregs(fs, 1); ++ adjustlocalvars(ls, 1); ++ body(ls, &b, 0, ls->linenumber); ++ luaK_storevar(fs, &v, &b); ++ /* debug information will only see the variable after this point! */ ++ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; ++} ++ ++ ++static void localstat (LexState *ls) { ++ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ ++ int nvars = 0; ++ int nexps; ++ expdesc e; ++ do { ++ new_localvar(ls, str_checkname(ls), nvars++); ++ } while (testnext(ls, ',')); ++ if (testnext(ls, '=')) ++ nexps = explist1(ls, &e); ++ else { ++ e.k = VVOID; ++ nexps = 0; ++ } ++ adjust_assign(ls, nvars, nexps, &e); ++ adjustlocalvars(ls, nvars); ++} ++ ++ ++static int funcname (LexState *ls, expdesc *v) { ++ /* funcname -> NAME {field} [`:' NAME] */ ++ int needself = 0; ++ singlevar(ls, v); ++ while (ls->t.token == '.') ++ field(ls, v); ++ if (ls->t.token == ':') { ++ needself = 1; ++ field(ls, v); ++ } ++ return needself; ++} ++ ++ ++static void funcstat (LexState *ls, int line) { ++ /* funcstat -> FUNCTION funcname body */ ++ int needself; ++ expdesc v, b; ++ luaX_next(ls); /* skip FUNCTION */ ++ needself = funcname(ls, &v); ++ body(ls, &b, needself, line); ++ luaK_storevar(ls->fs, &v, &b); ++ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ ++} ++ ++ ++static void exprstat (LexState *ls) { ++ /* stat -> func | assignment */ ++ FuncState *fs = ls->fs; ++ struct LHS_assign v; ++ primaryexp(ls, &v.v); ++ if (v.v.k == VCALL) /* stat -> func */ ++ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ ++ else { /* stat -> assignment */ ++ v.prev = NULL; ++ assignment(ls, &v, 1); ++ } ++} ++ ++ ++static void retstat (LexState *ls) { ++ /* stat -> RETURN explist */ ++ FuncState *fs = ls->fs; ++ expdesc e; ++ int first, nret; /* registers with returned values */ ++ luaX_next(ls); /* skip RETURN */ ++ if (block_follow(ls->t.token) || ls->t.token == ';') ++ first = nret = 0; /* return no values */ ++ else { ++ nret = explist1(ls, &e); /* optional return values */ ++ if (hasmultret(e.k)) { ++ luaK_setmultret(fs, &e); ++ if (e.k == VCALL && nret == 1) { /* tail call? */ ++ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); ++ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); ++ } ++ first = fs->nactvar; ++ nret = LUA_MULTRET; /* return all values */ ++ } ++ else { ++ if (nret == 1) /* only one single value? */ ++ first = luaK_exp2anyreg(fs, &e); ++ else { ++ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ ++ first = fs->nactvar; /* return all `active' values */ ++ lua_assert(nret == fs->freereg - first); ++ } ++ } ++ } ++ luaK_ret(fs, first, nret); ++} ++ ++ ++static int statement (LexState *ls) { ++ int line = ls->linenumber; /* may be needed for error messages */ ++ switch (ls->t.token) { ++ case TK_IF: { /* stat -> ifstat */ ++ ifstat(ls, line); ++ return 0; ++ } ++ case TK_WHILE: { /* stat -> whilestat */ ++ whilestat(ls, line); ++ return 0; ++ } ++ case TK_DO: { /* stat -> DO block END */ ++ luaX_next(ls); /* skip DO */ ++ block(ls); ++ check_match(ls, TK_END, TK_DO, line); ++ return 0; ++ } ++ case TK_FOR: { /* stat -> forstat */ ++ forstat(ls, line); ++ return 0; ++ } ++ case TK_REPEAT: { /* stat -> repeatstat */ ++ repeatstat(ls, line); ++ return 0; ++ } ++ case TK_FUNCTION: { ++ funcstat(ls, line); /* stat -> funcstat */ ++ return 0; ++ } ++ case TK_LOCAL: { /* stat -> localstat */ ++ luaX_next(ls); /* skip LOCAL */ ++ if (testnext(ls, TK_FUNCTION)) /* local function? */ ++ localfunc(ls); ++ else ++ localstat(ls); ++ return 0; ++ } ++ case TK_RETURN: { /* stat -> retstat */ ++ retstat(ls); ++ return 1; /* must be last statement */ ++ } ++ case TK_BREAK: { /* stat -> breakstat */ ++ luaX_next(ls); /* skip BREAK */ ++ breakstat(ls); ++ return 1; /* must be last statement */ ++ } ++ default: { ++ exprstat(ls); ++ return 0; /* to avoid warnings */ ++ } ++ } ++} ++ ++ ++static void chunk (LexState *ls) { ++ /* chunk -> { stat [`;'] } */ ++ int islast = 0; ++ enterlevel(ls); ++ while (!islast && !block_follow(ls->t.token)) { ++ islast = statement(ls); ++ testnext(ls, ';'); ++ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && ++ ls->fs->freereg >= ls->fs->nactvar); ++ ls->fs->freereg = ls->fs->nactvar; /* free registers */ ++ } ++ leavelevel(ls); ++} ++ ++/* }====================================================================== */ +--- /dev/null ++++ b/extensions/LUA/lua/lparser.h +@@ -0,0 +1,82 @@ ++/* ++** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua Parser ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lparser_h ++#define lparser_h ++ ++#include "llimits.h" ++#include "lobject.h" ++#include "lzio.h" ++ ++ ++/* ++** Expression descriptor ++*/ ++ ++typedef enum { ++ VVOID, /* no value */ ++ VNIL, ++ VTRUE, ++ VFALSE, ++ VK, /* info = index of constant in `k' */ ++ VKNUM, /* nval = numerical value */ ++ VLOCAL, /* info = local register */ ++ VUPVAL, /* info = index of upvalue in `upvalues' */ ++ VGLOBAL, /* info = index of table; aux = index of global name in `k' */ ++ VINDEXED, /* info = table register; aux = index register (or `k') */ ++ VJMP, /* info = instruction pc */ ++ VRELOCABLE, /* info = instruction pc */ ++ VNONRELOC, /* info = result register */ ++ VCALL, /* info = instruction pc */ ++ VVARARG /* info = instruction pc */ ++} expkind; ++ ++typedef struct expdesc { ++ expkind k; ++ union { ++ struct { int info, aux; } s; ++ lua_Number nval; ++ } u; ++ int t; /* patch list of `exit when true' */ ++ int f; /* patch list of `exit when false' */ ++} expdesc; ++ ++ ++typedef struct upvaldesc { ++ lu_byte k; ++ lu_byte info; ++} upvaldesc; ++ ++ ++struct BlockCnt; /* defined in lparser.c */ ++ ++ ++/* state needed to generate code for a given function */ ++typedef struct FuncState { ++ Proto *f; /* current function header */ ++ Table *h; /* table to find (and reuse) elements in `k' */ ++ struct FuncState *prev; /* enclosing function */ ++ struct LexState *ls; /* lexical state */ ++ struct lua_State *L; /* copy of the Lua state */ ++ struct BlockCnt *bl; /* chain of current blocks */ ++ int pc; /* next position to code (equivalent to `ncode') */ ++ int lasttarget; /* `pc' of last `jump target' */ ++ int jpc; /* list of pending jumps to `pc' */ ++ int freereg; /* first free register */ ++ int nk; /* number of elements in `k' */ ++ int np; /* number of elements in `p' */ ++ short nlocvars; /* number of elements in `locvars' */ ++ lu_byte nactvar; /* number of active local variables */ ++ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ ++ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ ++} FuncState; ++ ++ ++LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, ++ const char *name); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lstate.c +@@ -0,0 +1,214 @@ ++/* ++** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ ++** Global State ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define lstate_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) ++#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) ++#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) ++ ++ ++/* ++** Main thread combines a thread state and the global state ++*/ ++typedef struct LG { ++ lua_State l; ++ global_State g; ++} LG; ++ ++ ++ ++static void stack_init (lua_State *L1, lua_State *L) { ++ /* initialize CallInfo array */ ++ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); ++ L1->ci = L1->base_ci; ++ L1->size_ci = BASIC_CI_SIZE; ++ L1->end_ci = L1->base_ci + L1->size_ci - 1; ++ /* initialize stack array */ ++ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); ++ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; ++ L1->top = L1->stack; ++ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; ++ /* initialize first ci */ ++ L1->ci->func = L1->top; ++ setnilvalue(L1->top++); /* `function' entry for this `ci' */ ++ L1->base = L1->ci->base = L1->top; ++ L1->ci->top = L1->top + LUA_MINSTACK; ++} ++ ++ ++static void freestack (lua_State *L, lua_State *L1) { ++ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); ++ luaM_freearray(L, L1->stack, L1->stacksize, TValue); ++} ++ ++ ++/* ++** open parts that may cause memory-allocation errors ++*/ ++static void f_luaopen (lua_State *L, void *ud) { ++ global_State *g = G(L); ++ UNUSED(ud); ++ stack_init(L, L); /* init stack */ ++ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ ++ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ ++ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ ++ luaT_init(L); ++ luaX_init(L); ++ luaS_fix(luaS_newliteral(L, MEMERRMSG)); ++ g->GCthreshold = 4*g->totalbytes; ++} ++ ++ ++static void preinit_state (lua_State *L, global_State *g) { ++ G(L) = g; ++ L->stack = NULL; ++ L->stacksize = 0; ++ L->errorJmp = NULL; ++ L->hook = NULL; ++ L->hookmask = 0; ++ L->basehookcount = 0; ++ L->allowhook = 1; ++ resethookcount(L); ++ L->openupval = NULL; ++ L->size_ci = 0; ++ L->nCcalls = L->baseCcalls = 0; ++ L->status = 0; ++ L->base_ci = L->ci = NULL; ++ L->savedpc = NULL; ++ L->errfunc = 0; ++ setnilvalue(gt(L)); ++} ++ ++ ++static void close_state (lua_State *L) { ++ global_State *g = G(L); ++ luaF_close(L, L->stack); /* close all upvalues for this thread */ ++ luaC_freeall(L); /* collect all objects */ ++ lua_assert(g->rootgc == obj2gco(L)); ++ lua_assert(g->strt.nuse == 0); ++ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); ++ luaZ_freebuffer(L, &g->buff); ++ freestack(L, L); ++ lua_assert(g->totalbytes == sizeof(LG)); ++ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); ++} ++ ++ ++lua_State *luaE_newthread (lua_State *L) { ++ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); ++ luaC_link(L, obj2gco(L1), LUA_TTHREAD); ++ preinit_state(L1, G(L)); ++ stack_init(L1, L); /* init stack */ ++ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ ++ L1->hookmask = L->hookmask; ++ L1->basehookcount = L->basehookcount; ++ L1->hook = L->hook; ++ resethookcount(L1); ++ lua_assert(iswhite(obj2gco(L1))); ++ return L1; ++} ++ ++ ++void luaE_freethread (lua_State *L, lua_State *L1) { ++ luaF_close(L1, L1->stack); /* close all upvalues for this thread */ ++ lua_assert(L1->openupval == NULL); ++ luai_userstatefree(L1); ++ freestack(L, L1); ++ luaM_freemem(L, fromstate(L1), state_size(lua_State)); ++} ++ ++ ++LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { ++ int i; ++ lua_State *L; ++ global_State *g; ++ void *l = (*f)(ud, NULL, 0, state_size(LG)); ++ if (l == NULL) return NULL; ++ L = tostate(l); ++ g = &((LG *)L)->g; ++ L->next = NULL; ++ L->tt = LUA_TTHREAD; ++ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); ++ L->marked = luaC_white(g); ++ set2bits(L->marked, FIXEDBIT, SFIXEDBIT); ++ preinit_state(L, g); ++ g->frealloc = f; ++ g->ud = ud; ++ g->mainthread = L; ++ g->uvhead.u.l.prev = &g->uvhead; ++ g->uvhead.u.l.next = &g->uvhead; ++ g->GCthreshold = 0; /* mark it as unfinished state */ ++ g->strt.size = 0; ++ g->strt.nuse = 0; ++ g->strt.hash = NULL; ++ setnilvalue(registry(L)); ++ luaZ_initbuffer(L, &g->buff); ++ g->panic = NULL; ++ g->gcstate = GCSpause; ++ g->rootgc = obj2gco(L); ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ g->tmudata = NULL; ++ g->totalbytes = sizeof(LG); ++ g->gcpause = LUAI_GCPAUSE; ++ g->gcstepmul = LUAI_GCMUL; ++ g->gcdept = 0; ++ for (i=0; imt[i] = NULL; ++ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { ++ /* memory allocation error: free partial state */ ++ close_state(L); ++ L = NULL; ++ } ++ else ++ luai_userstateopen(L); ++ return L; ++} ++ ++ ++static void callallgcTM (lua_State *L, void *ud) { ++ UNUSED(ud); ++ luaC_callGCTM(L); /* call GC metamethods for all udata */ ++} ++ ++ ++LUA_API void lua_close (lua_State *L) { ++ L = G(L)->mainthread; /* only the main thread can be closed */ ++ lua_lock(L); ++ luaF_close(L, L->stack); /* close all upvalues for this thread */ ++ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ ++ L->errfunc = 0; /* no error function during GC metamethods */ ++ do { /* repeat until no more errors */ ++ L->ci = L->base_ci; ++ L->base = L->top = L->ci->base; ++ L->nCcalls = L->baseCcalls = 0; ++ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); ++ lua_assert(G(L)->tmudata == NULL); ++ luai_userstateclose(L); ++ close_state(L); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstate.h +@@ -0,0 +1,169 @@ ++/* ++** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ ++** Global State ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lstate_h ++#define lstate_h ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "ltm.h" ++#include "lzio.h" ++ ++ ++ ++struct lua_longjmp; /* defined in ldo.c */ ++ ++ ++/* table of globals */ ++#define gt(L) (&L->l_gt) ++ ++/* registry */ ++#define registry(L) (&G(L)->l_registry) ++ ++ ++/* extra stack space to handle TM calls and some other extras */ ++#define EXTRA_STACK 5 ++ ++ ++#define BASIC_CI_SIZE 8 ++ ++#define BASIC_STACK_SIZE (2*LUA_MINSTACK) ++ ++ ++ ++typedef struct stringtable { ++ GCObject **hash; ++ lu_int32 nuse; /* number of elements */ ++ int size; ++} stringtable; ++ ++ ++/* ++** informations about a call ++*/ ++typedef struct CallInfo { ++ StkId base; /* base for this function */ ++ StkId func; /* function index in the stack */ ++ StkId top; /* top for this function */ ++ const Instruction *savedpc; ++ int nresults; /* expected number of results from this function */ ++ int tailcalls; /* number of tail calls lost under this entry */ ++} CallInfo; ++ ++ ++ ++#define curr_func(L) (clvalue(L->ci->func)) ++#define ci_func(ci) (clvalue((ci)->func)) ++#define f_isLua(ci) (!ci_func(ci)->c.isC) ++#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) ++ ++ ++/* ++** `global state', shared by all threads of this state ++*/ ++typedef struct global_State { ++ stringtable strt; /* hash table for strings */ ++ lua_Alloc frealloc; /* function to reallocate memory */ ++ void *ud; /* auxiliary data to `frealloc' */ ++ lu_byte currentwhite; ++ lu_byte gcstate; /* state of garbage collector */ ++ int sweepstrgc; /* position of sweep in `strt' */ ++ GCObject *rootgc; /* list of all collectable objects */ ++ GCObject **sweepgc; /* position of sweep in `rootgc' */ ++ GCObject *gray; /* list of gray objects */ ++ GCObject *grayagain; /* list of objects to be traversed atomically */ ++ GCObject *weak; /* list of weak tables (to be cleared) */ ++ GCObject *tmudata; /* last element of list of userdata to be GC */ ++ Mbuffer buff; /* temporary buffer for string concatentation */ ++ lu_mem GCthreshold; ++ lu_mem totalbytes; /* number of bytes currently allocated */ ++ lu_mem estimate; /* an estimate of number of bytes actually in use */ ++ lu_mem gcdept; /* how much GC is `behind schedule' */ ++ int gcpause; /* size of pause between successive GCs */ ++ int gcstepmul; /* GC `granularity' */ ++ lua_CFunction panic; /* to be called in unprotected errors */ ++ TValue l_registry; ++ struct lua_State *mainthread; ++ UpVal uvhead; /* head of double-linked list of all open upvalues */ ++ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ ++ TString *tmname[TM_N]; /* array with tag-method names */ ++} global_State; ++ ++ ++/* ++** `per thread' state ++*/ ++struct lua_State { ++ CommonHeader; ++ lu_byte status; ++ StkId top; /* first free slot in the stack */ ++ StkId base; /* base of current function */ ++ global_State *l_G; ++ CallInfo *ci; /* call info for current function */ ++ const Instruction *savedpc; /* `savedpc' of current function */ ++ StkId stack_last; /* last free slot in the stack */ ++ StkId stack; /* stack base */ ++ CallInfo *end_ci; /* points after end of ci array*/ ++ CallInfo *base_ci; /* array of CallInfo's */ ++ int stacksize; ++ int size_ci; /* size of array `base_ci' */ ++ unsigned short nCcalls; /* number of nested C calls */ ++ unsigned short baseCcalls; /* nested C calls when resuming coroutine */ ++ lu_byte hookmask; ++ lu_byte allowhook; ++ int basehookcount; ++ int hookcount; ++ lua_Hook hook; ++ TValue l_gt; /* table of globals */ ++ TValue env; /* temporary place for environments */ ++ GCObject *openupval; /* list of open upvalues in this stack */ ++ GCObject *gclist; ++ struct lua_longjmp *errorJmp; /* current error recover point */ ++ ptrdiff_t errfunc; /* current error handling function (stack index) */ ++}; ++ ++ ++#define G(L) (L->l_G) ++ ++ ++/* ++** Union of all collectable objects ++*/ ++union GCObject { ++ GCheader gch; ++ union TString ts; ++ union Udata u; ++ union Closure cl; ++ struct Table h; ++ struct Proto p; ++ struct UpVal uv; ++ struct lua_State th; /* thread */ ++}; ++ ++ ++/* macros to convert a GCObject into a specific value */ ++#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) ++#define gco2ts(o) (&rawgco2ts(o)->tsv) ++#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) ++#define gco2u(o) (&rawgco2u(o)->uv) ++#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) ++#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) ++#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) ++#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) ++#define ngcotouv(o) \ ++ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) ++#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) ++ ++/* macro to convert any Lua object into a GCObject */ ++#define obj2gco(v) (cast(GCObject *, (v))) ++ ++ ++LUAI_FUNC lua_State *luaE_newthread (lua_State *L); ++LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstring.c +@@ -0,0 +1,110 @@ ++/* ++** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ++** String table (keeps all strings handled by Lua) ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lstring_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++ ++ ++ ++void luaS_resize (lua_State *L, int newsize) { ++ GCObject **newhash; ++ stringtable *tb; ++ int i; ++ if (G(L)->gcstate == GCSsweepstring) ++ return; /* cannot resize during GC traverse */ ++ newhash = luaM_newvector(L, newsize, GCObject *); ++ tb = &G(L)->strt; ++ for (i=0; isize; i++) { ++ GCObject *p = tb->hash[i]; ++ while (p) { /* for each node in the list */ ++ GCObject *next = p->gch.next; /* save next */ ++ unsigned int h = gco2ts(p)->hash; ++ int h1 = lmod(h, newsize); /* new position */ ++ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); ++ p->gch.next = newhash[h1]; /* chain it */ ++ newhash[h1] = p; ++ p = next; ++ } ++ } ++ luaM_freearray(L, tb->hash, tb->size, TString *); ++ tb->size = newsize; ++ tb->hash = newhash; ++} ++ ++ ++static TString *newlstr (lua_State *L, const char *str, size_t l, ++ unsigned int h) { ++ TString *ts; ++ stringtable *tb; ++ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) ++ luaM_toobig(L); ++ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); ++ ts->tsv.len = l; ++ ts->tsv.hash = h; ++ ts->tsv.marked = luaC_white(G(L)); ++ ts->tsv.tt = LUA_TSTRING; ++ ts->tsv.reserved = 0; ++ memcpy(ts+1, str, l*sizeof(char)); ++ ((char *)(ts+1))[l] = '\0'; /* ending 0 */ ++ tb = &G(L)->strt; ++ h = lmod(h, tb->size); ++ ts->tsv.next = tb->hash[h]; /* chain new entry */ ++ tb->hash[h] = obj2gco(ts); ++ tb->nuse++; ++ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) ++ luaS_resize(L, tb->size*2); /* too crowded */ ++ return ts; ++} ++ ++ ++TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { ++ GCObject *o; ++ unsigned int h = cast(unsigned int, l); /* seed */ ++ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ ++ size_t l1; ++ for (l1=l; l1>=step; l1-=step) /* compute hash */ ++ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); ++ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; ++ o != NULL; ++ o = o->gch.next) { ++ TString *ts = rawgco2ts(o); ++ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { ++ /* string may be dead */ ++ if (isdead(G(L), o)) changewhite(o); ++ return ts; ++ } ++ } ++ return newlstr(L, str, l, h); /* not found */ ++} ++ ++ ++Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { ++ Udata *u; ++ if (s > MAX_SIZET - sizeof(Udata)) ++ luaM_toobig(L); ++ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); ++ u->uv.marked = luaC_white(G(L)); /* is not finalized */ ++ u->uv.tt = LUA_TUSERDATA; ++ u->uv.len = s; ++ u->uv.metatable = NULL; ++ u->uv.env = e; ++ /* chain it on udata list (after main thread) */ ++ u->uv.next = G(L)->mainthread->next; ++ G(L)->mainthread->next = obj2gco(u); ++ return u; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstring.h +@@ -0,0 +1,31 @@ ++/* ++** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ ++** String table (keep all strings handled by Lua) ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lstring_h ++#define lstring_h ++ ++ ++#include "lgc.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) ++ ++#define sizeudata(u) (sizeof(union Udata)+(u)->len) ++ ++#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) ++#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ ++ (sizeof(s)/sizeof(char))-1)) ++ ++#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) ++ ++LUAI_FUNC void luaS_resize (lua_State *L, int newsize); ++LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); ++LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lstrlib.c +@@ -0,0 +1,883 @@ ++/* ++** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ ++** Standard library for string operations and pattern-matching ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define lstrlib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++/* macro to `unsign' a character */ ++#define uchar(c) ((unsigned char)(c)) ++ ++ ++ ++static int str_len (lua_State *L) { ++ size_t l; ++ luaL_checklstring(L, 1, &l); ++ lua_pushinteger(L, l); ++ return 1; ++} ++ ++ ++static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { ++ /* relative string position: negative means back from end */ ++ if (pos < 0) pos += (ptrdiff_t)len + 1; ++ return (pos >= 0) ? pos : 0; ++} ++ ++ ++static int str_sub (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); ++ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); ++ if (start < 1) start = 1; ++ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; ++ if (start <= end) ++ lua_pushlstring(L, s+start-1, end-start+1); ++ else lua_pushliteral(L, ""); ++ return 1; ++} ++ ++ ++static int str_reverse (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_reverse: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while (l--) luaL_addchar(b, s[l]); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int str_lower (lua_State *L) { ++ size_t l; ++ size_t i; ++ const char *s = luaL_checklstring(L, 1, &l); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_lower: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ for (i=0; i 0) ++ luaL_addlstring(b, s, l); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int str_byte (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); ++ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); ++ int n, i; ++ if (posi <= 0) posi = 1; ++ if ((size_t)pose > l) pose = l; ++ if (posi > pose) return 0; /* empty interval; return no values */ ++ n = (int)(pose - posi + 1); ++ if (posi + n <= pose) /* overflow? */ ++ luaL_error(L, "string slice too long"); ++ luaL_checkstack(L, n, "string slice too long"); ++ for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) ++ return luaL_error(ms->L, "invalid capture index"); ++ return l; ++} ++ ++ ++static int capture_to_close (MatchState *ms) { ++ int level = ms->level; ++ for (level--; level>=0; level--) ++ if (ms->capture[level].len == CAP_UNFINISHED) return level; ++ return luaL_error(ms->L, "invalid pattern capture"); ++} ++ ++ ++static const char *classend (MatchState *ms, const char *p) { ++ switch (*p++) { ++ case L_ESC: { ++ if (*p == '\0') ++ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); ++ return p+1; ++ } ++ case '[': { ++ if (*p == '^') p++; ++ do { /* look for a `]' */ ++ if (*p == '\0') ++ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); ++ if (*(p++) == L_ESC && *p != '\0') ++ p++; /* skip escapes (e.g. `%]') */ ++ } while (*p != ']'); ++ return p+1; ++ } ++ default: { ++ return p; ++ } ++ } ++} ++ ++ ++static int match_class (int c, int cl) { ++ int res; ++ switch (tolower(cl)) { ++ case 'a' : res = isalpha(c); break; ++ case 'c' : res = iscntrl(c); break; ++ case 'd' : res = isdigit(c); break; ++ case 'l' : res = islower(c); break; ++ case 'p' : res = ispunct(c); break; ++ case 's' : res = isspace(c); break; ++ case 'u' : res = isupper(c); break; ++ case 'w' : res = isalnum(c); break; ++ case 'x' : res = isxdigit(c); break; ++ case 'z' : res = (c == 0); break; ++ default: return (cl == c); ++ } ++ return (islower(cl) ? res : !res); ++} ++ ++ ++static int matchbracketclass (int c, const char *p, const char *ec) { ++ int sig = 1; ++ if (*(p+1) == '^') { ++ sig = 0; ++ p++; /* skip the `^' */ ++ } ++ while (++p < ec) { ++ if (*p == L_ESC) { ++ p++; ++ if (match_class(c, uchar(*p))) ++ return sig; ++ } ++ else if ((*(p+1) == '-') && (p+2 < ec)) { ++ p+=2; ++ if (uchar(*(p-2)) <= c && c <= uchar(*p)) ++ return sig; ++ } ++ else if (uchar(*p) == c) return sig; ++ } ++ return !sig; ++} ++ ++ ++static int singlematch (int c, const char *p, const char *ep) { ++ switch (*p) { ++ case '.': return 1; /* matches any char */ ++ case L_ESC: return match_class(c, uchar(*(p+1))); ++ case '[': return matchbracketclass(c, p, ep-1); ++ default: return (uchar(*p) == c); ++ } ++} ++ ++ ++static const char *match (MatchState *ms, const char *s, const char *p); ++ ++ ++static const char *matchbalance (MatchState *ms, const char *s, ++ const char *p) { ++ if (*p == 0 || *(p+1) == 0) ++ luaL_error(ms->L, "unbalanced pattern"); ++ if (*s != *p) return NULL; ++ else { ++ int b = *p; ++ int e = *(p+1); ++ int cont = 1; ++ while (++s < ms->src_end) { ++ if (*s == e) { ++ if (--cont == 0) return s+1; ++ } ++ else if (*s == b) cont++; ++ } ++ } ++ return NULL; /* string ends out of balance */ ++} ++ ++ ++static const char *max_expand (MatchState *ms, const char *s, ++ const char *p, const char *ep) { ++ ptrdiff_t i = 0; /* counts maximum expand for item */ ++ while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) ++ i++; ++ /* keeps trying to match with the maximum repetitions */ ++ while (i>=0) { ++ const char *res = match(ms, (s+i), ep+1); ++ if (res) return res; ++ i--; /* else didn't match; reduce 1 repetition to try again */ ++ } ++ return NULL; ++} ++ ++ ++static const char *min_expand (MatchState *ms, const char *s, ++ const char *p, const char *ep) { ++ for (;;) { ++ const char *res = match(ms, s, ep+1); ++ if (res != NULL) ++ return res; ++ else if (ssrc_end && singlematch(uchar(*s), p, ep)) ++ s++; /* try with one more repetition */ ++ else return NULL; ++ } ++} ++ ++ ++static const char *start_capture (MatchState *ms, const char *s, ++ const char *p, int what) { ++ const char *res; ++ int level = ms->level; ++ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); ++ ms->capture[level].init = s; ++ ms->capture[level].len = what; ++ ms->level = level+1; ++ if ((res=match(ms, s, p)) == NULL) /* match failed? */ ++ ms->level--; /* undo capture */ ++ return res; ++} ++ ++ ++static const char *end_capture (MatchState *ms, const char *s, ++ const char *p) { ++ int l = capture_to_close(ms); ++ const char *res; ++ ms->capture[l].len = s - ms->capture[l].init; /* close capture */ ++ if ((res = match(ms, s, p)) == NULL) /* match failed? */ ++ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ ++ return res; ++} ++ ++ ++static const char *match_capture (MatchState *ms, const char *s, int l) { ++ size_t len; ++ l = check_capture(ms, l); ++ len = ms->capture[l].len; ++ if ((size_t)(ms->src_end-s) >= len && ++ memcmp(ms->capture[l].init, s, len) == 0) ++ return s+len; ++ else return NULL; ++} ++ ++ ++static const char *match (MatchState *ms, const char *s, const char *p) { ++ init: /* using goto's to optimize tail recursion */ ++ switch (*p) { ++ case '(': { /* start capture */ ++ if (*(p+1) == ')') /* position capture? */ ++ return start_capture(ms, s, p+2, CAP_POSITION); ++ else ++ return start_capture(ms, s, p+1, CAP_UNFINISHED); ++ } ++ case ')': { /* end capture */ ++ return end_capture(ms, s, p+1); ++ } ++ case L_ESC: { ++ switch (*(p+1)) { ++ case 'b': { /* balanced string? */ ++ s = matchbalance(ms, s, p+2); ++ if (s == NULL) return NULL; ++ p+=4; goto init; /* else return match(ms, s, p+4); */ ++ } ++ case 'f': { /* frontier? */ ++ const char *ep; char previous; ++ p += 2; ++ if (*p != '[') ++ luaL_error(ms->L, "missing " LUA_QL("[") " after " ++ LUA_QL("%%f") " in pattern"); ++ ep = classend(ms, p); /* points to what is next */ ++ previous = (s == ms->src_init) ? '\0' : *(s-1); ++ if (matchbracketclass(uchar(previous), p, ep-1) || ++ !matchbracketclass(uchar(*s), p, ep-1)) return NULL; ++ p=ep; goto init; /* else return match(ms, s, ep); */ ++ } ++ default: { ++ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ ++ s = match_capture(ms, s, uchar(*(p+1))); ++ if (s == NULL) return NULL; ++ p+=2; goto init; /* else return match(ms, s, p+2) */ ++ } ++ goto dflt; /* case default */ ++ } ++ } ++ } ++ case '\0': { /* end of pattern */ ++ return s; /* match succeeded */ ++ } ++ case '$': { ++ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ ++ return (s == ms->src_end) ? s : NULL; /* check end of string */ ++ else goto dflt; ++ } ++ default: dflt: { /* it is a pattern item */ ++ const char *ep = classend(ms, p); /* points to what is next */ ++ int m = ssrc_end && singlematch(uchar(*s), p, ep); ++ switch (*ep) { ++ case '?': { /* optional */ ++ const char *res; ++ if (m && ((res=match(ms, s+1, ep+1)) != NULL)) ++ return res; ++ p=ep+1; goto init; /* else return match(ms, s, ep+1); */ ++ } ++ case '*': { /* 0 or more repetitions */ ++ return max_expand(ms, s, p, ep); ++ } ++ case '+': { /* 1 or more repetitions */ ++ return (m ? max_expand(ms, s+1, p, ep) : NULL); ++ } ++ case '-': { /* 0 or more repetitions (minimum) */ ++ return min_expand(ms, s, p, ep); ++ } ++ default: { ++ if (!m) return NULL; ++ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ ++ } ++ } ++ } ++ } ++} ++ ++ ++ ++static const char *lmemfind (const char *s1, size_t l1, ++ const char *s2, size_t l2) { ++ if (l2 == 0) return s1; /* empty strings are everywhere */ ++ else if (l2 > l1) return NULL; /* avoids a negative `l1' */ ++ else { ++ const char *init; /* to search for a `*s2' inside `s1' */ ++ l2--; /* 1st char will be checked by `memchr' */ ++ l1 = l1-l2; /* `s2' cannot be found after that */ ++ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { ++ init++; /* 1st char is already checked */ ++ if (memcmp(init, s2+1, l2) == 0) ++ return init-1; ++ else { /* correct `l1' and `s1' to try again */ ++ l1 -= init-s1; ++ s1 = init; ++ } ++ } ++ return NULL; /* not found */ ++ } ++} ++ ++ ++static void push_onecapture (MatchState *ms, int i, const char *s, ++ const char *e) { ++ if (i >= ms->level) { ++ if (i == 0) /* ms->level == 0, too */ ++ lua_pushlstring(ms->L, s, e - s); /* add whole match */ ++ else ++ luaL_error(ms->L, "invalid capture index"); ++ } ++ else { ++ ptrdiff_t l = ms->capture[i].len; ++ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); ++ if (l == CAP_POSITION) ++ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); ++ else ++ lua_pushlstring(ms->L, ms->capture[i].init, l); ++ } ++} ++ ++ ++static int push_captures (MatchState *ms, const char *s, const char *e) { ++ int i; ++ int nlevels = (ms->level == 0 && s) ? 1 : ms->level; ++ luaL_checkstack(ms->L, nlevels, "too many captures"); ++ for (i = 0; i < nlevels; i++) ++ push_onecapture(ms, i, s, e); ++ return nlevels; /* number of strings pushed */ ++} ++ ++ ++static int str_find_aux (lua_State *L, int find) { ++ size_t l1, l2; ++ const char *s = luaL_checklstring(L, 1, &l1); ++ const char *p = luaL_checklstring(L, 2, &l2); ++ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; ++ if (init < 0) init = 0; ++ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; ++ if (find && (lua_toboolean(L, 4) || /* explicit request? */ ++ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ ++ /* do a plain search */ ++ const char *s2 = lmemfind(s+init, l1-init, p, l2); ++ if (s2) { ++ lua_pushinteger(L, s2-s+1); ++ lua_pushinteger(L, s2-s+l2); ++ return 2; ++ } ++ } ++ else { ++ MatchState ms; ++ int anchor = (*p == '^') ? (p++, 1) : 0; ++ const char *s1=s+init; ++ ms.L = L; ++ ms.src_init = s; ++ ms.src_end = s+l1; ++ do { ++ const char *res; ++ ms.level = 0; ++ if ((res=match(&ms, s1, p)) != NULL) { ++ if (find) { ++ lua_pushinteger(L, s1-s+1); /* start */ ++ lua_pushinteger(L, res-s); /* end */ ++ return push_captures(&ms, NULL, 0) + 2; ++ } ++ else ++ return push_captures(&ms, s1, res); ++ } ++ } while (s1++ < ms.src_end && !anchor); ++ } ++ lua_pushnil(L); /* not found */ ++ return 1; ++} ++ ++ ++static int str_find (lua_State *L) { ++ return str_find_aux(L, 1); ++} ++ ++ ++static int str_match (lua_State *L) { ++ return str_find_aux(L, 0); ++} ++ ++ ++static int gmatch_aux (lua_State *L) { ++ MatchState ms; ++ size_t ls; ++ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); ++ const char *p = lua_tostring(L, lua_upvalueindex(2)); ++ const char *src; ++ ms.L = L; ++ ms.src_init = s; ++ ms.src_end = s+ls; ++ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); ++ src <= ms.src_end; ++ src++) { ++ const char *e; ++ ms.level = 0; ++ if ((e = match(&ms, src, p)) != NULL) { ++ lua_Integer newstart = e-s; ++ if (e == src) newstart++; /* empty match? go at least one position */ ++ lua_pushinteger(L, newstart); ++ lua_replace(L, lua_upvalueindex(3)); ++ return push_captures(&ms, src, e); ++ } ++ } ++ return 0; /* not found */ ++} ++ ++ ++static int gmatch (lua_State *L) { ++ luaL_checkstring(L, 1); ++ luaL_checkstring(L, 2); ++ lua_settop(L, 2); ++ lua_pushinteger(L, 0); ++ lua_pushcclosure(L, gmatch_aux, 3); ++ return 1; ++} ++ ++ ++static int gfind_nodef (lua_State *L) { ++ return luaL_error(L, LUA_QL("string.gfind") " was renamed to " ++ LUA_QL("string.gmatch")); ++} ++ ++ ++static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, ++ const char *e) { ++ size_t l, i; ++ const char *news = lua_tolstring(ms->L, 3, &l); ++ for (i = 0; i < l; i++) { ++ if (news[i] != L_ESC) ++ luaL_addchar(b, news[i]); ++ else { ++ i++; /* skip ESC */ ++ if (!isdigit(uchar(news[i]))) ++ luaL_addchar(b, news[i]); ++ else if (news[i] == '0') ++ luaL_addlstring(b, s, e - s); ++ else { ++ push_onecapture(ms, news[i] - '1', s, e); ++ luaL_addvalue(b); /* add capture to accumulated result */ ++ } ++ } ++ } ++} ++ ++ ++static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, ++ const char *e) { ++ lua_State *L = ms->L; ++ switch (lua_type(L, 3)) { ++ case LUA_TNUMBER: ++ case LUA_TSTRING: { ++ add_s(ms, b, s, e); ++ return; ++ } ++ case LUA_TFUNCTION: { ++ int n; ++ lua_pushvalue(L, 3); ++ n = push_captures(ms, s, e); ++ lua_call(L, n, 1); ++ break; ++ } ++ case LUA_TTABLE: { ++ push_onecapture(ms, 0, s, e); ++ lua_gettable(L, 3); ++ break; ++ } ++ } ++ if (!lua_toboolean(L, -1)) { /* nil or false? */ ++ lua_pop(L, 1); ++ lua_pushlstring(L, s, e - s); /* keep original text */ ++ } ++ else if (!lua_isstring(L, -1)) ++ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); ++ luaL_addvalue(b); /* add result to accumulator */ ++} ++ ++ ++static int str_gsub (lua_State *L) { ++ size_t srcl; ++ const char *src = luaL_checklstring(L, 1, &srcl); ++ const char *p = luaL_checkstring(L, 2); ++ int tr = lua_type(L, 3); ++ int max_s = luaL_optint(L, 4, srcl+1); ++ int anchor = (*p == '^') ? (p++, 1) : 0; ++ int n = 0; ++ MatchState ms; ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_gsub: cannot allocate memory"); ++ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || ++ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, ++ "string/function/table expected"); ++ luaL_buffinit(L, b); ++ ms.L = L; ++ ms.src_init = src; ++ ms.src_end = src+srcl; ++ while (n < max_s) { ++ const char *e; ++ ms.level = 0; ++ e = match(&ms, src, p); ++ if (e) { ++ n++; ++ add_value(&ms, b, src, e); ++ } ++ if (e && e>src) /* non empty match? */ ++ src = e; /* skip it */ ++ else if (src < ms.src_end) ++ luaL_addchar(b, *src++); ++ else break; ++ if (anchor) break; ++ } ++ luaL_addlstring(b, src, ms.src_end-src); ++ luaL_pushresult(b); ++ lua_pushinteger(L, n); /* number of substitutions */ ++ kfree(b); ++ return 2; ++} ++ ++/* }====================================================== */ ++ ++ ++/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ ++#define MAX_ITEM 512 ++/* valid flags in a format specification */ ++#define FLAGS "-+ #0" ++/* ++** maximum size of each format specification (such as '%-099.99d') ++** (+10 accounts for %99.99x plus margin of error) ++*/ ++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) ++ ++ ++static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { ++ size_t l; ++ const char *s = luaL_checklstring(L, arg, &l); ++ luaL_addchar(b, '"'); ++ while (l--) { ++ switch (*s) { ++ case '"': case '\\': case '\n': { ++ luaL_addchar(b, '\\'); ++ luaL_addchar(b, *s); ++ break; ++ } ++ case '\r': { ++ luaL_addlstring(b, "\\r", 2); ++ break; ++ } ++ case '\0': { ++ luaL_addlstring(b, "\\000", 4); ++ break; ++ } ++ default: { ++ luaL_addchar(b, *s); ++ break; ++ } ++ } ++ s++; ++ } ++ luaL_addchar(b, '"'); ++} ++ ++static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { ++ const char *p = strfrmt; ++ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ ++ if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) ++ luaL_error(L, "invalid format (repeated flags)"); ++ if (isdigit(uchar(*p))) p++; /* skip width */ ++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ ++ if (*p == '.') { ++ p++; ++ if (isdigit(uchar(*p))) p++; /* skip precision */ ++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ ++ } ++ if (isdigit(uchar(*p))) ++ luaL_error(L, "invalid format (width or precision too long)"); ++ *(form++) = '%'; ++ strncpy(form, strfrmt, p - strfrmt + 1); ++ form += p - strfrmt + 1; ++ *form = '\0'; ++ return p; ++} ++ ++ ++static void addintlen (char *form) { ++ size_t l = strlen(form); ++ char spec = form[l - 1]; ++ strcpy(form + l - 1, LUA_INTFRMLEN); ++ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; ++ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; ++} ++ ++ ++static int str_format (lua_State *L) { ++ int arg = 1; ++ size_t sfl; ++ const char *strfrmt = luaL_checklstring(L, arg, &sfl); ++ const char *strfrmt_end = strfrmt+sfl; ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_format: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while (strfrmt < strfrmt_end) { ++ if (*strfrmt != L_ESC) ++ luaL_addchar(b, *strfrmt++); ++ else if (*++strfrmt == L_ESC) ++ luaL_addchar(b, *strfrmt++); /* %% */ ++ else { /* format item */ ++ char form[MAX_FORMAT]; /* to store the format (`%...') */ ++ char buff[MAX_ITEM]; /* to store the formatted item */ ++ arg++; ++ strfrmt = scanformat(L, strfrmt, form); ++ switch (*strfrmt++) { ++ case 'c': { ++ sprintf(buff, form, (int)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'd': case 'i': { ++ addintlen(form); ++ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'o': case 'u': case 'x': case 'X': { ++ addintlen(form); ++ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'q': { ++ addquoted(L, b, arg); ++ continue; /* skip the 'addsize' at the end */ ++ } ++ case 's': { ++ size_t l; ++ const char *s = luaL_checklstring(L, arg, &l); ++ if (!strchr(form, '.') && l >= 100) { ++ /* no precision and string is too long to be formatted; ++ keep original string */ ++ lua_pushvalue(L, arg); ++ luaL_addvalue(b); ++ continue; /* skip the `addsize' at the end */ ++ } ++ else { ++ sprintf(buff, form, s); ++ break; ++ } ++ } ++ default: { /* also treat cases `pnLlh' */ ++ kfree(b); ++ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " ++ LUA_QL("format"), *(strfrmt - 1)); ++ } ++ } ++ luaL_addlstring(b, buff, strlen(buff)); ++ } ++ } ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static const luaL_Reg strlib[] = { ++ {"byte", str_byte}, ++ {"char", str_char}, ++ {"dump", str_dump}, ++ {"find", str_find}, ++ {"format", str_format}, ++ {"gfind", gfind_nodef}, ++ {"gmatch", gmatch}, ++ {"gsub", str_gsub}, ++ {"len", str_len}, ++ {"lower", str_lower}, ++ {"match", str_match}, ++ {"rep", str_rep}, ++ {"reverse", str_reverse}, ++ {"sub", str_sub}, ++ {"upper", str_upper}, ++ {NULL, NULL} ++}; ++ ++ ++static void createmetatable (lua_State *L) { ++ lua_createtable(L, 0, 1); /* create metatable for strings */ ++ lua_pushliteral(L, ""); /* dummy string */ ++ lua_pushvalue(L, -2); ++ lua_setmetatable(L, -2); /* set string metatable */ ++ lua_pop(L, 1); /* pop dummy string */ ++ lua_pushvalue(L, -2); /* string library... */ ++ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ ++ lua_pop(L, 1); /* pop metatable */ ++} ++ ++ ++/* ++** Open string library ++*/ ++LUALIB_API int luaopen_string (lua_State *L) { ++ luaL_register(L, LUA_STRLIBNAME, strlib); ++#if defined(LUA_COMPAT_GFIND) ++ lua_getfield(L, -1, "gmatch"); ++ lua_setfield(L, -2, "gfind"); ++#endif ++ createmetatable(L); ++ return 1; ++} +--- /dev/null ++++ b/extensions/LUA/lua/ltable.c +@@ -0,0 +1,588 @@ ++/* ++** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ ++** Lua tables (hash) ++** See Copyright Notice in lua.h ++*/ ++ ++ ++/* ++** Implementation of tables (aka arrays, objects, or hash tables). ++** Tables keep its elements in two parts: an array part and a hash part. ++** Non-negative integer keys are all candidates to be kept in the array ++** part. The actual size of the array is the largest `n' such that at ++** least half the slots between 0 and n are in use. ++** Hash uses a mix of chained scatter table with Brent's variation. ++** A main invariant of these tables is that, if an element is not ++** in its main position (i.e. the `original' position that its hash gives ++** to it), then the colliding element is in its own main position. ++** Hence even when the load factor reaches 100%, performance remains good. ++*/ ++ ++#include ++#include ++ ++#define ltable_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "ltable.h" ++ ++ ++/* ++** max size of array part is 2^MAXBITS ++*/ ++#if LUAI_BITSINT > 26 ++#define MAXBITS 26 ++#else ++#define MAXBITS (LUAI_BITSINT-2) ++#endif ++ ++#define MAXASIZE (1 << MAXBITS) ++ ++ ++#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) ++ ++#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) ++#define hashboolean(t,p) hashpow2(t, p) ++ ++ ++/* ++** for some types, it is better to avoid modulus by power of 2, as ++** they tend to have many 2 factors. ++*/ ++#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) ++ ++ ++#define hashpointer(t,p) hashmod(t, IntPoint(p)) ++ ++ ++/* ++** number of ints inside a lua_Number ++*/ ++#define numints cast_int(sizeof(lua_Number)/sizeof(int)) ++ ++ ++ ++#define dummynode (&dummynode_) ++ ++static const Node dummynode_ = { ++ {{NULL}, LUA_TNIL}, /* value */ ++ {{{NULL}, LUA_TNIL, NULL}} /* key */ ++}; ++ ++ ++/* ++** hash for lua_Numbers ++*/ ++static Node *hashnum (const Table *t, lua_Number n) { ++ unsigned int a[numints]; ++ int i; ++ if (luai_numeq(n, 0)) /* avoid problems with -0 */ ++ return gnode(t, 0); ++ memcpy(a, &n, sizeof(a)); ++ for (i = 1; i < numints; i++) a[0] += a[i]; ++ return hashmod(t, a[0]); ++} ++ ++ ++ ++/* ++** returns the `main' position of an element in a table (that is, the index ++** of its hash value) ++*/ ++static Node *mainposition (const Table *t, const TValue *key) { ++ switch (ttype(key)) { ++ case LUA_TNUMBER: ++ return hashnum(t, nvalue(key)); ++ case LUA_TSTRING: ++ return hashstr(t, rawtsvalue(key)); ++ case LUA_TBOOLEAN: ++ return hashboolean(t, bvalue(key)); ++ case LUA_TLIGHTUSERDATA: ++ return hashpointer(t, pvalue(key)); ++ default: ++ return hashpointer(t, gcvalue(key)); ++ } ++} ++ ++ ++/* ++** returns the index for `key' if `key' is an appropriate key to live in ++** the array part of the table, -1 otherwise. ++*/ ++static int arrayindex (const TValue *key) { ++ if (ttisnumber(key)) { ++ lua_Number n = nvalue(key); ++ int k; ++ lua_number2int(k, n); ++ if (luai_numeq(cast_num(k), n)) ++ return k; ++ } ++ return -1; /* `key' did not match some condition */ ++} ++ ++ ++/* ++** returns the index of a `key' for table traversals. First goes all ++** elements in the array part, then elements in the hash part. The ++** beginning of a traversal is signalled by -1. ++*/ ++static int findindex (lua_State *L, Table *t, StkId key) { ++ int i; ++ if (ttisnil(key)) return -1; /* first iteration */ ++ i = arrayindex(key); ++ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ ++ return i-1; /* yes; that's the index (corrected to C) */ ++ else { ++ Node *n = mainposition(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ /* key may be dead already, but it is ok to use it in `next' */ ++ if (luaO_rawequalObj(key2tval(n), key) || ++ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && ++ gcvalue(gkey(n)) == gcvalue(key))) { ++ i = cast_int(n - gnode(t, 0)); /* key index in hash table */ ++ /* hash elements are numbered after array ones */ ++ return i + t->sizearray; ++ } ++ else n = gnext(n); ++ } while (n); ++ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ ++ return 0; /* to avoid warnings */ ++ } ++} ++ ++ ++int luaH_next (lua_State *L, Table *t, StkId key) { ++ int i = findindex(L, t, key); /* find original element */ ++ for (i++; i < t->sizearray; i++) { /* try first array part */ ++ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ ++ setnvalue(key, cast_num(i+1)); ++ setobj2s(L, key+1, &t->array[i]); ++ return 1; ++ } ++ } ++ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ ++ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ ++ setobj2s(L, key, key2tval(gnode(t, i))); ++ setobj2s(L, key+1, gval(gnode(t, i))); ++ return 1; ++ } ++ } ++ return 0; /* no more elements */ ++} ++ ++ ++/* ++** {============================================================= ++** Rehash ++** ============================================================== ++*/ ++ ++ ++static int computesizes (int nums[], int *narray) { ++ int i; ++ int twotoi; /* 2^i */ ++ int a = 0; /* number of elements smaller than 2^i */ ++ int na = 0; /* number of elements to go to array part */ ++ int n = 0; /* optimal size for array part */ ++ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { ++ if (nums[i] > 0) { ++ a += nums[i]; ++ if (a > twotoi/2) { /* more than half elements present? */ ++ n = twotoi; /* optimal size (till now) */ ++ na = a; /* all elements smaller than n will go to array part */ ++ } ++ } ++ if (a == *narray) break; /* all elements already counted */ ++ } ++ *narray = n; ++ lua_assert(*narray/2 <= na && na <= *narray); ++ return na; ++} ++ ++ ++static int countint (const TValue *key, int *nums) { ++ int k = arrayindex(key); ++ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ ++ nums[ceillog2(k)]++; /* count as such */ ++ return 1; ++ } ++ else ++ return 0; ++} ++ ++ ++static int numusearray (const Table *t, int *nums) { ++ int lg; ++ int ttlg; /* 2^lg */ ++ int ause = 0; /* summation of `nums' */ ++ int i = 1; /* count to traverse all array keys */ ++ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ ++ int lc = 0; /* counter */ ++ int lim = ttlg; ++ if (lim > t->sizearray) { ++ lim = t->sizearray; /* adjust upper limit */ ++ if (i > lim) ++ break; /* no more elements to count */ ++ } ++ /* count elements in range (2^(lg-1), 2^lg] */ ++ for (; i <= lim; i++) { ++ if (!ttisnil(&t->array[i-1])) ++ lc++; ++ } ++ nums[lg] += lc; ++ ause += lc; ++ } ++ return ause; ++} ++ ++ ++static int numusehash (const Table *t, int *nums, int *pnasize) { ++ int totaluse = 0; /* total number of elements */ ++ int ause = 0; /* summation of `nums' */ ++ int i = sizenode(t); ++ while (i--) { ++ Node *n = &t->node[i]; ++ if (!ttisnil(gval(n))) { ++ ause += countint(key2tval(n), nums); ++ totaluse++; ++ } ++ } ++ *pnasize += ause; ++ return totaluse; ++} ++ ++ ++static void setarrayvector (lua_State *L, Table *t, int size) { ++ int i; ++ luaM_reallocvector(L, t->array, t->sizearray, size, TValue); ++ for (i=t->sizearray; iarray[i]); ++ t->sizearray = size; ++} ++ ++ ++static void setnodevector (lua_State *L, Table *t, int size) { ++ int lsize; ++ if (size == 0) { /* no elements to hash part? */ ++ t->node = cast(Node *, dummynode); /* use common `dummynode' */ ++ lsize = 0; ++ } ++ else { ++ int i; ++ lsize = ceillog2(size); ++ if (lsize > MAXBITS) ++ luaG_runerror(L, "table overflow"); ++ size = twoto(lsize); ++ t->node = luaM_newvector(L, size, Node); ++ for (i=0; ilsizenode = cast_byte(lsize); ++ t->lastfree = gnode(t, size); /* all positions are free */ ++} ++ ++ ++static void resize (lua_State *L, Table *t, int nasize, int nhsize) { ++ int i; ++ int oldasize = t->sizearray; ++ int oldhsize = t->lsizenode; ++ Node *nold = t->node; /* save old hash ... */ ++ if (nasize > oldasize) /* array part must grow? */ ++ setarrayvector(L, t, nasize); ++ /* create new hash part with appropriate size */ ++ setnodevector(L, t, nhsize); ++ if (nasize < oldasize) { /* array part must shrink? */ ++ t->sizearray = nasize; ++ /* re-insert elements from vanishing slice */ ++ for (i=nasize; iarray[i])) ++ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); ++ } ++ /* shrink array */ ++ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); ++ } ++ /* re-insert elements from hash part */ ++ for (i = twoto(oldhsize) - 1; i >= 0; i--) { ++ Node *old = nold+i; ++ if (!ttisnil(gval(old))) ++ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); ++ } ++ if (nold != dummynode) ++ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ ++} ++ ++ ++void luaH_resizearray (lua_State *L, Table *t, int nasize) { ++ int nsize = (t->node == dummynode) ? 0 : sizenode(t); ++ resize(L, t, nasize, nsize); ++} ++ ++ ++static void rehash (lua_State *L, Table *t, const TValue *ek) { ++ int nasize, na; ++ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ ++ int i; ++ int totaluse; ++ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ ++ nasize = numusearray(t, nums); /* count keys in array part */ ++ totaluse = nasize; /* all those keys are integer keys */ ++ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ ++ /* count extra key */ ++ nasize += countint(ek, nums); ++ totaluse++; ++ /* compute new size for array part */ ++ na = computesizes(nums, &nasize); ++ /* resize the table to new computed sizes */ ++ resize(L, t, nasize, totaluse - na); ++} ++ ++ ++ ++/* ++** }============================================================= ++*/ ++ ++ ++Table *luaH_new (lua_State *L, int narray, int nhash) { ++ Table *t = luaM_new(L, Table); ++ luaC_link(L, obj2gco(t), LUA_TTABLE); ++ t->metatable = NULL; ++ t->flags = cast_byte(~0); ++ /* temporary values (kept only if some malloc fails) */ ++ t->array = NULL; ++ t->sizearray = 0; ++ t->lsizenode = 0; ++ t->node = cast(Node *, dummynode); ++ setarrayvector(L, t, narray); ++ setnodevector(L, t, nhash); ++ return t; ++} ++ ++ ++void luaH_free (lua_State *L, Table *t) { ++ if (t->node != dummynode) ++ luaM_freearray(L, t->node, sizenode(t), Node); ++ luaM_freearray(L, t->array, t->sizearray, TValue); ++ luaM_free(L, t); ++} ++ ++ ++static Node *getfreepos (Table *t) { ++ while (t->lastfree-- > t->node) { ++ if (ttisnil(gkey(t->lastfree))) ++ return t->lastfree; ++ } ++ return NULL; /* could not find a free place */ ++} ++ ++ ++ ++/* ++** inserts a new key into a hash table; first, check whether key's main ++** position is free. If not, check whether colliding node is in its main ++** position or not: if it is not, move colliding node to an empty place and ++** put new key in its main position; otherwise (colliding node is in its main ++** position), new key goes to an empty position. ++*/ ++static TValue *newkey (lua_State *L, Table *t, const TValue *key) { ++ Node *mp = mainposition(t, key); ++ if (!ttisnil(gval(mp)) || mp == dummynode) { ++ Node *othern; ++ Node *n = getfreepos(t); /* get a free place */ ++ if (n == NULL) { /* cannot find a free place? */ ++ rehash(L, t, key); /* grow table */ ++ return luaH_set(L, t, key); /* re-insert key into grown table */ ++ } ++ lua_assert(n != dummynode); ++ othern = mainposition(t, key2tval(mp)); ++ if (othern != mp) { /* is colliding node out of its main position? */ ++ /* yes; move colliding node into free position */ ++ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ ++ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ ++ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ ++ gnext(mp) = NULL; /* now `mp' is free */ ++ setnilvalue(gval(mp)); ++ } ++ else { /* colliding node is in its own main position */ ++ /* new node will go into free position */ ++ gnext(n) = gnext(mp); /* chain new position */ ++ gnext(mp) = n; ++ mp = n; ++ } ++ } ++ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; ++ luaC_barriert(L, t, key); ++ lua_assert(ttisnil(gval(mp))); ++ return gval(mp); ++} ++ ++ ++/* ++** search function for integers ++*/ ++const TValue *luaH_getnum (Table *t, int key) { ++ /* (1 <= key && key <= t->sizearray) */ ++ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) ++ return &t->array[key-1]; ++ else { ++ lua_Number nk = cast_num(key); ++ Node *n = hashnum(t, nk); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++ } ++} ++ ++ ++/* ++** search function for strings ++*/ ++const TValue *luaH_getstr (Table *t, TString *key) { ++ Node *n = hashstr(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++} ++ ++ ++/* ++** main search function ++*/ ++const TValue *luaH_get (Table *t, const TValue *key) { ++ switch (ttype(key)) { ++ case LUA_TNIL: return luaO_nilobject; ++ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); ++ case LUA_TNUMBER: { ++ int k; ++ lua_Number n = nvalue(key); ++ lua_number2int(k, n); ++ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ ++ return luaH_getnum(t, k); /* use specialized version */ ++ fallthrough; ++ } ++ default: { ++ Node *n = mainposition(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (luaO_rawequalObj(key2tval(n), key)) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++ } ++ } ++} ++ ++ ++TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { ++ const TValue *p = luaH_get(t, key); ++ t->flags = 0; ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ if (ttisnil(key)) luaG_runerror(L, "table index is nil"); ++ else if (ttisnumber(key) && luai_numisnan(nvalue(key))) ++ luaG_runerror(L, "table index is NaN"); ++ return newkey(L, t, key); ++ } ++} ++ ++ ++TValue *luaH_setnum (lua_State *L, Table *t, int key) { ++ const TValue *p = luaH_getnum(t, key); ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ TValue k; ++ setnvalue(&k, cast_num(key)); ++ return newkey(L, t, &k); ++ } ++} ++ ++ ++TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { ++ const TValue *p = luaH_getstr(t, key); ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ TValue k; ++ setsvalue(L, &k, key); ++ return newkey(L, t, &k); ++ } ++} ++ ++ ++static int unbound_search (Table *t, unsigned int j) { ++ unsigned int i = j; /* i is zero or a present index */ ++ j++; ++ /* find `i' and `j' such that i is present and j is not */ ++ while (!ttisnil(luaH_getnum(t, j))) { ++ i = j; ++ j *= 2; ++ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ ++ /* table was built with bad purposes: resort to linear search */ ++ i = 1; ++ while (!ttisnil(luaH_getnum(t, i))) i++; ++ return i - 1; ++ } ++ } ++ /* now do a binary search between them */ ++ while (j - i > 1) { ++ unsigned int m = (i+j)/2; ++ if (ttisnil(luaH_getnum(t, m))) j = m; ++ else i = m; ++ } ++ return i; ++} ++ ++ ++/* ++** Try to find a boundary in table `t'. A `boundary' is an integer index ++** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). ++*/ ++int luaH_getn (Table *t) { ++ unsigned int j = t->sizearray; ++ if (j > 0 && ttisnil(&t->array[j - 1])) { ++ /* there is a boundary in the array part: (binary) search for it */ ++ unsigned int i = 0; ++ while (j - i > 1) { ++ unsigned int m = (i+j)/2; ++ if (ttisnil(&t->array[m - 1])) j = m; ++ else i = m; ++ } ++ return i; ++ } ++ /* else must find a boundary in hash part */ ++ else if (t->node == dummynode) /* hash part is empty? */ ++ return j; /* that is easy... */ ++ else return unbound_search(t, j); ++} ++ ++ ++ ++#if defined(LUA_DEBUG) ++ ++Node *luaH_mainposition (const Table *t, const TValue *key) { ++ return mainposition(t, key); ++} ++ ++int luaH_isdummy (Node *n) { return n == dummynode; } ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ltable.h +@@ -0,0 +1,40 @@ ++/* ++** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua tables (hash) ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ltable_h ++#define ltable_h ++ ++#include "lobject.h" ++ ++ ++#define gnode(t,i) (&(t)->node[i]) ++#define gkey(n) (&(n)->i_key.nk) ++#define gval(n) (&(n)->i_val) ++#define gnext(n) ((n)->i_key.nk.next) ++ ++#define key2tval(n) (&(n)->i_key.tvk) ++ ++ ++LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); ++LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); ++LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); ++LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); ++LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); ++LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); ++LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); ++LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); ++LUAI_FUNC void luaH_free (lua_State *L, Table *t); ++LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); ++LUAI_FUNC int luaH_getn (Table *t); ++ ++ ++#if defined(LUA_DEBUG) ++LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); ++LUAI_FUNC int luaH_isdummy (Node *n); ++#endif ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ltablib.c +@@ -0,0 +1,288 @@ ++/* ++** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ ++** Library for Table Manipulation ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include ++ ++#define ltablib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) ++ ++ ++static int foreachi (lua_State *L) { ++ int i; ++ int n = aux_getn(L, 1); ++ luaL_checktype(L, 2, LUA_TFUNCTION); ++ for (i=1; i <= n; i++) { ++ lua_pushvalue(L, 2); /* function */ ++ lua_pushinteger(L, i); /* 1st argument */ ++ lua_rawgeti(L, 1, i); /* 2nd argument */ ++ lua_call(L, 2, 1); ++ if (!lua_isnil(L, -1)) ++ return 1; ++ lua_pop(L, 1); /* remove nil result */ ++ } ++ return 0; ++} ++ ++ ++static int foreach (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checktype(L, 2, LUA_TFUNCTION); ++ lua_pushnil(L); /* first key */ ++ while (lua_next(L, 1)) { ++ lua_pushvalue(L, 2); /* function */ ++ lua_pushvalue(L, -3); /* key */ ++ lua_pushvalue(L, -3); /* value */ ++ lua_call(L, 2, 1); ++ if (!lua_isnil(L, -1)) ++ return 1; ++ lua_pop(L, 2); /* remove value and result */ ++ } ++ return 0; ++} ++ ++ ++static int maxn (lua_State *L) { ++ lua_Number max = 0; ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushnil(L); /* first key */ ++ while (lua_next(L, 1)) { ++ lua_pop(L, 1); /* remove value */ ++ if (lua_type(L, -1) == LUA_TNUMBER) { ++ lua_Number v = lua_tonumber(L, -1); ++ if (v > max) max = v; ++ } ++ } ++ lua_pushnumber(L, max); ++ return 1; ++} ++ ++ ++static int getn (lua_State *L) { ++ lua_pushinteger(L, aux_getn(L, 1)); ++ return 1; ++} ++ ++ ++static int setn (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++#ifndef luaL_setn ++ luaL_setn(L, 1, luaL_checkint(L, 2)); ++#else ++ luaL_error(L, LUA_QL("setn") " is obsolete"); ++#endif ++ lua_pushvalue(L, 1); ++ return 1; ++} ++ ++ ++static int tinsert (lua_State *L) { ++ int e = aux_getn(L, 1) + 1; /* first empty element */ ++ int pos; /* where to insert new element */ ++ switch (lua_gettop(L)) { ++ case 2: { /* called with only 2 arguments */ ++ pos = e; /* insert new element at the end */ ++ break; ++ } ++ case 3: { ++ int i; ++ pos = luaL_checkint(L, 2); /* 2nd argument is the position */ ++ if (pos > e) e = pos; /* `grow' array if necessary */ ++ for (i = e; i > pos; i--) { /* move up elements */ ++ lua_rawgeti(L, 1, i-1); ++ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ ++ } ++ break; ++ } ++ default: { ++ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); ++ } ++ } ++ luaL_setn(L, 1, e); /* new size */ ++ lua_rawseti(L, 1, pos); /* t[pos] = v */ ++ return 0; ++} ++ ++ ++static int tremove (lua_State *L) { ++ int e = aux_getn(L, 1); ++ int pos = luaL_optint(L, 2, e); ++ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ ++ return 0; /* nothing to remove */ ++ luaL_setn(L, 1, e - 1); /* t.n = n-1 */ ++ lua_rawgeti(L, 1, pos); /* result = t[pos] */ ++ for ( ;pos= P */ ++ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { ++ if (i>u) luaL_error(L, "invalid order function for sorting"); ++ lua_pop(L, 1); /* remove a[i] */ ++ } ++ /* repeat --j until a[j] <= P */ ++ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { ++ if (j ++ ++#define ltm_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++ ++const char *const luaT_typenames[] = { ++ "nil", "boolean", "userdata", "number", ++ "string", "table", "function", "userdata", "thread", ++ "proto", "upval" ++}; ++ ++ ++void luaT_init (lua_State *L) { ++ static const char *const luaT_eventname[] = { /* ORDER TM */ ++ "__index", "__newindex", ++ "__gc", "__mode", "__eq", ++ "__add", "__sub", "__mul", "__div", "__mod", ++ "__pow", "__unm", "__len", "__lt", "__le", ++ "__concat", "__call" ++ }; ++ int i; ++ for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); ++ luaS_fix(G(L)->tmname[i]); /* never collect these names */ ++ } ++} ++ ++ ++/* ++** function to be used with macro "fasttm": optimized for absence of ++** tag methods ++*/ ++const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { ++ const TValue *tm = luaH_getstr(events, ename); ++ lua_assert(event <= TM_EQ); ++ if (ttisnil(tm)) { /* no tag method? */ ++ events->flags |= cast_byte(1u<metatable; ++ break; ++ case LUA_TUSERDATA: ++ mt = uvalue(o)->metatable; ++ break; ++ default: ++ mt = G(L)->mt[ttype(o)]; ++ } ++ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ltm.h +@@ -0,0 +1,54 @@ ++/* ++** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Tag methods ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ltm_h ++#define ltm_h ++ ++ ++#include "lobject.h" ++ ++ ++/* ++* WARNING: if you change the order of this enumeration, ++* grep "ORDER TM" ++*/ ++typedef enum { ++ TM_INDEX, ++ TM_NEWINDEX, ++ TM_GC, ++ TM_MODE, ++ TM_EQ, /* last tag method with `fast' access */ ++ TM_ADD, ++ TM_SUB, ++ TM_MUL, ++ TM_DIV, ++ TM_MOD, ++ TM_POW, ++ TM_UNM, ++ TM_LEN, ++ TM_LT, ++ TM_LE, ++ TM_CONCAT, ++ TM_CALL, ++ TM_N /* number of elements in the enum */ ++} TMS; ++ ++ ++ ++#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ ++ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) ++ ++#define fasttm(l,et,e) gfasttm(G(l), et, e) ++ ++LUAI_DATA const char *const luaT_typenames[]; ++ ++ ++LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); ++LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, ++ TMS event); ++LUAI_FUNC void luaT_init (lua_State *L); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/luaconf.h +@@ -0,0 +1,797 @@ ++/* ++** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ ++** Configuration file for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lconfig_h ++#define lconfig_h ++ ++#include ++ ++#if !defined(__KERNEL__) ++#include ++#else ++#define UCHAR_MAX 255 ++#define SHRT_MAX 32767 ++#define BUFSIZ 8192 ++#define NO_FPU ++#endif ++ ++/* ++** ================================================================== ++** Search for "@@" to find all configurable definitions. ++** =================================================================== ++*/ ++ ++ ++/* ++@@ LUA_ANSI controls the use of non-ansi features. ++** CHANGE it (define it) if you want Lua to avoid the use of any ++** non-ansi feature or library. ++*/ ++#if defined(__STRICT_ANSI__) ++#define LUA_ANSI ++#endif ++ ++ ++#if !defined(LUA_ANSI) && defined(_WIN32) ++#define LUA_WIN ++#endif ++ ++#if defined(LUA_USE_LINUX) ++#define LUA_USE_POSIX ++#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ ++#define LUA_USE_READLINE /* needs some extra libraries */ ++#endif ++ ++#if defined(LUA_USE_MACOSX) ++#define LUA_USE_POSIX ++#define LUA_DL_DYLD /* does not need extra library */ ++#endif ++ ++ ++ ++/* ++@@ LUA_USE_POSIX includes all functionallity listed as X/Open System ++@* Interfaces Extension (XSI). ++** CHANGE it (define it) if your system is XSI compatible. ++*/ ++#if defined(LUA_USE_POSIX) ++#define LUA_USE_MKSTEMP ++#define LUA_USE_ISATTY ++#define LUA_USE_POPEN ++#define LUA_USE_ULONGJMP ++#endif ++ ++ ++/* ++@@ LUA_PATH and LUA_CPATH are the names of the environment variables that ++@* Lua check to set its paths. ++@@ LUA_INIT is the name of the environment variable that Lua ++@* checks for initialization code. ++** CHANGE them if you want different names. ++*/ ++#define LUA_PATH "LUA_PATH" ++#define LUA_CPATH "LUA_CPATH" ++#define LUA_INIT "LUA_INIT" ++ ++ ++/* ++@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for ++@* Lua libraries. ++@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for ++@* C libraries. ++** CHANGE them if your machine has a non-conventional directory ++** hierarchy or if you want to install your libraries in ++** non-conventional directories. ++*/ ++#if defined(_WIN32) ++/* ++** In Windows, any exclamation mark ('!') in the path is replaced by the ++** path of the directory of the executable file of the current process. ++*/ ++#define LUA_LDIR "!\\lua\\" ++#define LUA_CDIR "!\\" ++#define LUA_PATH_DEFAULT \ ++ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ ++ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" ++#define LUA_CPATH_DEFAULT \ ++ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" ++ ++#else ++#define LUA_ROOT "/usr/local/" ++#define LUA_LDIR LUA_ROOT "share/lua/5.1/" ++#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" ++#define LUA_PATH_DEFAULT \ ++ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ ++ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" ++#define LUA_CPATH_DEFAULT \ ++ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" ++#endif ++ ++ ++/* ++@@ LUA_DIRSEP is the directory separator (for submodules). ++** CHANGE it if your machine does not use "/" as the directory separator ++** and is not Windows. (On Windows Lua automatically uses "\".) ++*/ ++#if defined(_WIN32) ++#define LUA_DIRSEP "\\" ++#else ++#define LUA_DIRSEP "/" ++#endif ++ ++ ++/* ++@@ LUA_PATHSEP is the character that separates templates in a path. ++@@ LUA_PATH_MARK is the string that marks the substitution points in a ++@* template. ++@@ LUA_EXECDIR in a Windows path is replaced by the executable's ++@* directory. ++@@ LUA_IGMARK is a mark to ignore all before it when bulding the ++@* luaopen_ function name. ++** CHANGE them if for some reason your system cannot use those ++** characters. (E.g., if one of those characters is a common character ++** in file/directory names.) Probably you do not need to change them. ++*/ ++#define LUA_PATHSEP ";" ++#define LUA_PATH_MARK "?" ++#define LUA_EXECDIR "!" ++#define LUA_IGMARK "-" ++ ++ ++/* ++@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. ++** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ++** machines, ptrdiff_t gives a good choice between int or long.) ++*/ ++#define LUA_INTEGER ptrdiff_t ++ ++ ++/* ++@@ LUA_API is a mark for all core API functions. ++@@ LUALIB_API is a mark for all standard library functions. ++** CHANGE them if you need to define those functions in some special way. ++** For instance, if you want to create one Windows DLL with the core and ++** the libraries, you may want to use the following definition (define ++** LUA_BUILD_AS_DLL to get it). ++*/ ++#if defined(LUA_BUILD_AS_DLL) ++ ++#if defined(LUA_CORE) || defined(LUA_LIB) ++#define LUA_API __declspec(dllexport) ++#else ++#define LUA_API __declspec(dllimport) ++#endif ++ ++#else ++ ++#define LUA_API extern ++ ++#endif ++ ++/* more often than not the libs go together with the core */ ++#define LUALIB_API LUA_API ++ ++ ++/* ++@@ LUAI_FUNC is a mark for all extern functions that are not to be ++@* exported to outside modules. ++@@ LUAI_DATA is a mark for all extern (const) variables that are not to ++@* be exported to outside modules. ++** CHANGE them if you need to mark them in some special way. Elf/gcc ++** (versions 3.2 and later) mark them as "hidden" to optimize access ++** when Lua is compiled as a shared library. ++*/ ++#if defined(luaall_c) ++#define LUAI_FUNC static ++#define LUAI_DATA /* empty */ ++ ++#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ ++ defined(__ELF__) ++#define LUAI_FUNC __attribute__((visibility("hidden"))) extern ++#define LUAI_DATA LUAI_FUNC ++ ++#else ++#define LUAI_FUNC extern ++#define LUAI_DATA extern ++#endif ++ ++ ++ ++/* ++@@ LUA_QL describes how error messages quote program elements. ++** CHANGE it if you want a different appearance. ++*/ ++#define LUA_QL(x) "'" x "'" ++#define LUA_QS LUA_QL("%s") ++ ++ ++/* ++@@ LUA_IDSIZE gives the maximum size for the description of the source ++@* of a function in debug information. ++** CHANGE it if you want a different size. ++*/ ++#define LUA_IDSIZE 60 ++ ++ ++/* ++** {================================================================== ++** Stand-alone configuration ++** =================================================================== ++*/ ++ ++#if defined(lua_c) || defined(luaall_c) ++ ++/* ++@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that ++@* is, whether we're running lua interactively). ++** CHANGE it if you have a better definition for non-POSIX/non-Windows ++** systems. ++*/ ++#if defined(LUA_USE_ISATTY) ++#include ++#define lua_stdin_is_tty() isatty(0) ++#elif defined(LUA_WIN) ++#include ++#include ++#define lua_stdin_is_tty() _isatty(_fileno(stdin)) ++#else ++#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ ++#endif ++ ++ ++/* ++@@ LUA_PROMPT is the default prompt used by stand-alone Lua. ++@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. ++** CHANGE them if you want different prompts. (You can also change the ++** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) ++*/ ++#define LUA_PROMPT "> " ++#define LUA_PROMPT2 ">> " ++ ++ ++/* ++@@ LUA_PROGNAME is the default name for the stand-alone Lua program. ++** CHANGE it if your stand-alone interpreter has a different name and ++** your system is not able to detect that name automatically. ++*/ ++#define LUA_PROGNAME "lua" ++ ++ ++/* ++@@ LUA_MAXINPUT is the maximum length for an input line in the ++@* stand-alone interpreter. ++** CHANGE it if you need longer lines. ++*/ ++#define LUA_MAXINPUT 512 ++ ++ ++/* ++@@ lua_readline defines how to show a prompt and then read a line from ++@* the standard input. ++@@ lua_saveline defines how to "save" a read line in a "history". ++@@ lua_freeline defines how to free a line read by lua_readline. ++** CHANGE them if you want to improve this functionality (e.g., by using ++** GNU readline and history facilities). ++*/ ++#if defined(LUA_USE_READLINE) ++#include ++#include ++#include ++#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) ++#define lua_saveline(L,idx) \ ++ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ ++ add_history(lua_tostring(L, idx)); /* add it to history */ ++#define lua_freeline(L,b) ((void)L, free(b)) ++#else ++#define lua_readline(L,b,p) \ ++ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ ++ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ ++#define lua_saveline(L,idx) { (void)L; (void)idx; } ++#define lua_freeline(L,b) { (void)L; (void)b; } ++#endif ++ ++#endif ++ ++/* }================================================================== */ ++ ++ ++/* ++@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles ++@* as a percentage. ++** CHANGE it if you want the GC to run faster or slower (higher values ++** mean larger pauses which mean slower collection.) You can also change ++** this value dynamically. ++*/ ++#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ ++ ++ ++/* ++@@ LUAI_GCMUL defines the default speed of garbage collection relative to ++@* memory allocation as a percentage. ++** CHANGE it if you want to change the granularity of the garbage ++** collection. (Higher values mean coarser collections. 0 represents ++** infinity, where each step performs a full collection.) You can also ++** change this value dynamically. ++*/ ++#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ ++ ++ ++ ++/* ++@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. ++** CHANGE it (define it) if you want exact compatibility with the ++** behavior of setn/getn in Lua 5.0. ++*/ ++#undef LUA_COMPAT_GETN ++ ++/* ++@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. ++** CHANGE it to undefined as soon as you do not need a global 'loadlib' ++** function (the function is still available as 'package.loadlib'). ++*/ ++#undef LUA_COMPAT_LOADLIB ++ ++/* ++@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. ++** CHANGE it to undefined as soon as your programs use only '...' to ++** access vararg parameters (instead of the old 'arg' table). ++*/ ++#define LUA_COMPAT_VARARG ++ ++/* ++@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. ++** CHANGE it to undefined as soon as your programs use 'math.fmod' or ++** the new '%' operator instead of 'math.mod'. ++*/ ++#define LUA_COMPAT_MOD ++ ++/* ++@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting ++@* facility. ++** CHANGE it to 2 if you want the old behaviour, or undefine it to turn ++** off the advisory error when nesting [[...]]. ++*/ ++#define LUA_COMPAT_LSTR 1 ++ ++/* ++@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. ++** CHANGE it to undefined as soon as you rename 'string.gfind' to ++** 'string.gmatch'. ++*/ ++#define LUA_COMPAT_GFIND ++ ++/* ++@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' ++@* behavior. ++** CHANGE it to undefined as soon as you replace to 'luaL_register' ++** your uses of 'luaL_openlib' ++*/ ++#define LUA_COMPAT_OPENLIB ++ ++ ++ ++/* ++@@ luai_apicheck is the assert macro used by the Lua-C API. ++** CHANGE luai_apicheck if you want Lua to perform some checks in the ++** parameters it gets from API calls. This may slow down the interpreter ++** a bit, but may be quite useful when debugging C code that interfaces ++** with Lua. A useful redefinition is to use assert.h. ++*/ ++#if defined(LUA_USE_APICHECK) ++#include ++#define luai_apicheck(L,o) { (void)L; assert(o); } ++#else ++#define luai_apicheck(L,o) { (void)L; } ++#endif ++ ++ ++/* ++@@ LUAI_BITSINT defines the number of bits in an int. ++** CHANGE here if Lua cannot automatically detect the number of bits of ++** your machine. Probably you do not need to change this. ++*/ ++/* avoid overflows in comparison */ ++#if !defined(__KERNEL__) ++#include ++#define LUA_INT_MAX INT_MAX ++#else ++#define LUA_INT_MAX (~0U>>1) ++#endif ++ ++#if LUA_INT_MAX-20 < 32760 ++#define LUAI_BITSINT 16 ++#elif LUA_INT_MAX > 2147483640L ++/* int has at least 32 bits */ ++#define LUAI_BITSINT 32 ++#else ++#error "you must define LUA_BITSINT with number of bits in an integer" ++#endif ++ ++ ++/* ++@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. ++@@ LUAI_INT32 is an signed integer with at least 32 bits. ++@@ LUAI_UMEM is an unsigned integer big enough to count the total ++@* memory used by Lua. ++@@ LUAI_MEM is a signed integer big enough to count the total memory ++@* used by Lua. ++** CHANGE here if for some weird reason the default definitions are not ++** good enough for your machine. (The definitions in the 'else' ++** part always works, but may waste space on machines with 64-bit ++** longs.) Probably you do not need to change this. ++*/ ++#if LUAI_BITSINT >= 32 ++#define LUAI_UINT32 unsigned int ++#define LUAI_INT32 int ++#define LUAI_MAXINT32 INT_MAX ++#define LUAI_UMEM size_t ++#define LUAI_MEM ptrdiff_t ++#else ++/* 16-bit ints */ ++#define LUAI_UINT32 unsigned long ++#define LUAI_INT32 long ++#define LUAI_MAXINT32 LONG_MAX ++#define LUAI_UMEM unsigned long ++#define LUAI_MEM long ++#endif ++ ++ ++/* ++@@ LUAI_MAXCALLS limits the number of nested calls. ++** CHANGE it if you need really deep recursive calls. This limit is ++** arbitrary; its only purpose is to stop infinite recursion before ++** exhausting memory. ++*/ ++#define LUAI_MAXCALLS 20000 ++ ++ ++/* ++@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function ++@* can use. ++** CHANGE it if you need lots of (Lua) stack space for your C ++** functions. This limit is arbitrary; its only purpose is to stop C ++** functions to consume unlimited stack space. (must be smaller than ++** -LUA_REGISTRYINDEX) ++*/ ++#define LUAI_MAXCSTACK 8000 ++ ++ ++ ++/* ++** {================================================================== ++** CHANGE (to smaller values) the following definitions if your system ++** has a small C stack. (Or you may want to change them to larger ++** values if your system has a large C stack and these limits are ++** too rigid for you.) Some of these constants control the size of ++** stack-allocated arrays used by the compiler or the interpreter, while ++** others limit the maximum number of recursive calls that the compiler ++** or the interpreter can perform. Values too large may cause a C stack ++** overflow for some forms of deep constructs. ++** =================================================================== ++*/ ++ ++ ++/* ++@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and ++@* syntactical nested non-terminals in a program. ++*/ ++#define LUAI_MAXCCALLS 200 ++ ++ ++/* ++@@ LUAI_MAXVARS is the maximum number of local variables per function ++@* (must be smaller than 250). ++*/ ++#define LUAI_MAXVARS 200 ++ ++ ++/* ++@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function ++@* (must be smaller than 250). ++*/ ++#define LUAI_MAXUPVALUES 60 ++ ++ ++/* ++@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. ++*/ ++#define LUAL_BUFFERSIZE BUFSIZ ++ ++/* }================================================================== */ ++ ++ ++ ++ ++/* ++** {================================================================== ++@@ LUA_NUMBER is the type of numbers in Lua. ++** CHANGE the following definitions only if you want to build Lua ++** with a number type different from double. You may also need to ++** change lua_number2int & lua_number2integer. ++** =================================================================== ++*/ ++#if !defined(NO_FPU) ++#define LUA_NUMBER_DOUBLE ++#define LUA_NUMBER double ++#else ++#define LUA_NUMBER long ++#endif ++ ++/* ++@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' ++@* over a number. ++*/ ++#define LUAI_UACNUMBER LUA_NUMBER ++ ++ ++/* ++@@ LUA_NUMBER_SCAN is the format for reading numbers. ++@@ LUA_NUMBER_FMT is the format for writing numbers. ++@@ lua_number2str converts a number to a string. ++@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. ++@@ lua_str2number converts a string to a number. ++*/ ++#if !defined(NO_FPU) ++#define LUA_NUMBER_SCAN "%lf" ++#define LUA_NUMBER_FMT "%.14g" ++#define lua_str2number(s,p) strtod((s), (p)) ++#else ++#define LUA_NUMBER_SCAN "%ld" ++#define LUA_NUMBER_FMT "%ld" ++#if !defined(__KERNEL__) ++#define lua_str2number(s,p) strtol((s), (p), 10) ++#else ++#define lua_str2number(s,p) simple_strtol((s), (p), 10) ++#endif ++#endif ++ ++#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ ++#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) ++ ++/* ++@@ The luai_num* macros define the primitive operations over numbers. ++*/ ++#if defined(LUA_CORE) ++#define luai_numadd(a,b) ((a)+(b)) ++#define luai_numsub(a,b) ((a)-(b)) ++#define luai_nummul(a,b) ((a)*(b)) ++#define luai_numdiv(a,b) ((a)/(b)) ++#define luai_numunm(a) (-(a)) ++#define luai_numeq(a,b) ((a)==(b)) ++#define luai_numlt(a,b) ((a)<(b)) ++#define luai_numle(a,b) ((a)<=(b)) ++#define luai_numisnan(a) (!luai_numeq((a), (a))) ++#if !defined(NO_FPU) ++#include ++#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) ++#define luai_numpow(a,b) (pow(a,b)) ++#else ++#define luai_nummod(a,b) ((a)%(b)) ++#define luai_numpow(a,b) luai_nummul(a,b) ++#endif ++#endif ++ ++ ++/* ++@@ lua_number2int is a macro to convert lua_Number to int. ++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ++** CHANGE them if you know a faster way to convert a lua_Number to ++** int (with any rounding method and without throwing errors) in your ++** system. In Pentium machines, a naive typecast from double to int ++** in C is extremely slow, so any alternative is worth trying. ++*/ ++ ++/* On a Pentium, resort to a trick */ ++#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ ++ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) ++ ++/* On a Microsoft compiler, use assembler */ ++#if defined(_MSC_VER) ++ ++#define lua_number2int(i,d) __asm fld d __asm fistp i ++#define lua_number2integer(i,n) lua_number2int(i, n) ++ ++/* the next trick should work on any Pentium, but sometimes clashes ++ with a DirectX idiosyncrasy */ ++#else ++ ++union luai_Cast { double l_d; long l_l; }; ++#define lua_number2int(i,d) \ ++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } ++#define lua_number2integer(i,n) lua_number2int(i, n) ++ ++#endif ++ ++ ++/* this option always works, but may be slow */ ++#else ++#define lua_number2int(i,d) ((i)=(int)(d)) ++#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) ++ ++#endif ++ ++/* }================================================================== */ ++ ++ ++/* ++@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. ++** CHANGE it if your system requires alignments larger than double. (For ++** instance, if your system supports long doubles and they must be ++** aligned in 16-byte boundaries, then you should add long double in the ++** union.) Probably you do not need to change this. ++*/ ++#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } ++ ++ ++/* ++@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. ++** CHANGE them if you prefer to use longjmp/setjmp even with C++ ++** or if want/don't to use _longjmp/_setjmp instead of regular ++** longjmp/setjmp. By default, Lua handles errors with exceptions when ++** compiling as C++ code, with _longjmp/_setjmp when asked to use them, ++** and with longjmp/setjmp otherwise. ++*/ ++#if defined(__KERNEL__) ++#undef LUA_USE_ULONGJMP ++#endif ++ ++#if defined(__cplusplus) ++/* C++ exceptions */ ++#define LUAI_THROW(L,c) throw(c) ++#define LUAI_TRY(L,c,a) try { a } catch(...) \ ++ { if ((c)->status == 0) (c)->status = -1; } ++#define luai_jmpbuf int /* dummy variable */ ++ ++#elif defined(LUA_USE_ULONGJMP) ++/* in Unix, try _longjmp/_setjmp (more efficient) */ ++#define LUAI_THROW(L,c) _longjmp((c)->b, 1) ++#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } ++#define luai_jmpbuf jmp_buf ++ ++#else ++/* default handling with long jumps */ ++#define LUAI_THROW(L,c) longjmp((c)->b, 1) ++#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } ++#define luai_jmpbuf jmp_buf ++ ++#endif ++ ++ ++/* ++@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern ++@* can do during pattern-matching. ++** CHANGE it if you need more captures. This limit is arbitrary. ++*/ ++#define LUA_MAXCAPTURES 32 ++ ++ ++/* ++@@ lua_tmpnam is the function that the OS library uses to create a ++@* temporary name. ++@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. ++** CHANGE them if you have an alternative to tmpnam (which is considered ++** insecure) or if you want the original tmpnam anyway. By default, Lua ++** uses tmpnam except when POSIX is available, where it uses mkstemp. ++*/ ++#if defined(loslib_c) || defined(luaall_c) ++ ++#if defined(LUA_USE_MKSTEMP) ++#include ++#define LUA_TMPNAMBUFSIZE 32 ++#define lua_tmpnam(b,e) { \ ++ strcpy(b, "/tmp/lua_XXXXXX"); \ ++ e = mkstemp(b); \ ++ if (e != -1) close(e); \ ++ e = (e == -1); } ++ ++#else ++#define LUA_TMPNAMBUFSIZE L_tmpnam ++#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } ++#endif ++ ++#endif ++ ++ ++/* ++@@ lua_popen spawns a new process connected to the current one through ++@* the file streams. ++** CHANGE it if you have a way to implement it in your system. ++*/ ++#if defined(LUA_USE_POPEN) ++ ++#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) ++#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) ++ ++#elif defined(LUA_WIN) ++ ++#define lua_popen(L,c,m) ((void)L, _popen(c,m)) ++#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) ++ ++#else ++ ++#define lua_popen(L,c,m) ((void)((void)c, m), \ ++ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) ++#define lua_pclose(L,file) ((void)((void)L, file), 0) ++ ++#endif ++ ++/* ++@@ LUA_DL_* define which dynamic-library system Lua should use. ++** CHANGE here if Lua has problems choosing the appropriate ++** dynamic-library system for your platform (either Windows' DLL, Mac's ++** dyld, or Unix's dlopen). If your system is some kind of Unix, there ++** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for ++** it. To use dlopen you also need to adapt the src/Makefile (probably ++** adding -ldl to the linker options), so Lua does not select it ++** automatically. (When you change the makefile to add -ldl, you must ++** also add -DLUA_USE_DLOPEN.) ++** If you do not want any kind of dynamic library, undefine all these ++** options. ++** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. ++*/ ++#if defined(LUA_USE_DLOPEN) ++#define LUA_DL_DLOPEN ++#endif ++ ++#if defined(LUA_WIN) ++#define LUA_DL_DLL ++#endif ++ ++ ++/* ++@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State ++@* (the data goes just *before* the lua_State pointer). ++** CHANGE (define) this if you really need that. This value must be ++** a multiple of the maximum alignment required for your machine. ++*/ ++#define LUAI_EXTRASPACE 0 ++ ++ ++/* ++@@ luai_userstate* allow user-specific actions on threads. ++** CHANGE them if you defined LUAI_EXTRASPACE and need to do something ++** extra when a thread is created/deleted/resumed/yielded. ++*/ ++#define luai_userstateopen(L) ((void)L) ++#define luai_userstateclose(L) ((void)L) ++#define luai_userstatethread(L,L1) ((void)L) ++#define luai_userstatefree(L) ((void)L) ++#define luai_userstateresume(L,n) ((void)L) ++#define luai_userstateyield(L,n) ((void)L) ++ ++ ++/* ++@@ LUA_INTFRMLEN is the length modifier for integer conversions ++@* in 'string.format'. ++@@ LUA_INTFRM_T is the integer type correspoding to the previous length ++@* modifier. ++** CHANGE them if your system supports long long or does not support long. ++*/ ++ ++#if defined(LUA_USELONGLONG) ++ ++#define LUA_INTFRMLEN "ll" ++#define LUA_INTFRM_T long long ++ ++#else ++ ++#define LUA_INTFRMLEN "l" ++#define LUA_INTFRM_T long ++ ++#endif ++ ++/* =================================================================== */ ++ ++/* ++** Local configuration. You can use this space to add your redefinitions ++** without modifying the main part of the file. ++*/ ++ ++ ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lua.h +@@ -0,0 +1,386 @@ ++/* ++** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ ++** Lua - An Extensible Extension Language ++** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ++** See Copyright Notice at the end of this file ++*/ ++ ++ ++#ifndef lua_h ++#define lua_h ++ ++#include ++ ++#include "luaconf.h" ++ ++ ++#define LUA_VERSION "Lua 5.1" ++#define LUA_RELEASE "Lua 5.1.4" ++#define LUA_VERSION_NUM 501 ++#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" ++#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" ++ ++ ++/* mark for precompiled code (`Lua') */ ++#define LUA_SIGNATURE "\033Lua" ++ ++/* option for multiple returns in `lua_pcall' and `lua_call' */ ++#define LUA_MULTRET (-1) ++ ++ ++/* ++** pseudo-indices ++*/ ++#define LUA_REGISTRYINDEX (-10000) ++#define LUA_ENVIRONINDEX (-10001) ++#define LUA_GLOBALSINDEX (-10002) ++#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) ++ ++ ++/* thread status; 0 is OK */ ++#define LUA_YIELD 1 ++#define LUA_ERRRUN 2 ++#define LUA_ERRSYNTAX 3 ++#define LUA_ERRMEM 4 ++#define LUA_ERRERR 5 ++ ++ ++typedef struct lua_State lua_State; ++ ++typedef int (*lua_CFunction) (lua_State *L); ++ ++ ++/* ++** functions that read/write blocks when loading/dumping Lua chunks ++*/ ++typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); ++ ++typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); ++ ++ ++/* ++** prototype for memory-allocation functions ++*/ ++typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); ++ ++ ++/* ++** basic types ++*/ ++#define LUA_TNONE (-1) ++ ++#define LUA_TNIL 0 ++#define LUA_TBOOLEAN 1 ++#define LUA_TLIGHTUSERDATA 2 ++#define LUA_TNUMBER 3 ++#define LUA_TSTRING 4 ++#define LUA_TTABLE 5 ++#define LUA_TFUNCTION 6 ++#define LUA_TUSERDATA 7 ++#define LUA_TTHREAD 8 ++ ++ ++ ++/* minimum Lua stack available to a C function */ ++#define LUA_MINSTACK 20 ++ ++ ++/* ++** generic extra include file ++*/ ++#if defined(LUA_USER_H) ++#include LUA_USER_H ++#endif ++ ++ ++/* type of numbers in Lua */ ++typedef LUA_NUMBER lua_Number; ++ ++ ++/* type for integer functions */ ++typedef LUA_INTEGER lua_Integer; ++ ++ ++ ++/* ++** state manipulation ++*/ ++LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); ++LUA_API void (lua_close) (lua_State *L); ++LUA_API lua_State *(lua_newthread) (lua_State *L); ++ ++LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); ++ ++ ++/* ++** basic stack manipulation ++*/ ++LUA_API int (lua_gettop) (lua_State *L); ++LUA_API void (lua_settop) (lua_State *L, int idx); ++LUA_API void (lua_pushvalue) (lua_State *L, int idx); ++LUA_API void (lua_remove) (lua_State *L, int idx); ++LUA_API void (lua_insert) (lua_State *L, int idx); ++LUA_API void (lua_replace) (lua_State *L, int idx); ++LUA_API int (lua_checkstack) (lua_State *L, int sz); ++ ++LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); ++ ++ ++/* ++** access functions (stack -> C) ++*/ ++ ++LUA_API int (lua_isnumber) (lua_State *L, int idx); ++LUA_API int (lua_isstring) (lua_State *L, int idx); ++LUA_API int (lua_iscfunction) (lua_State *L, int idx); ++LUA_API int (lua_isuserdata) (lua_State *L, int idx); ++LUA_API int (lua_type) (lua_State *L, int idx); ++LUA_API const char *(lua_typename) (lua_State *L, int tp); ++ ++LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); ++LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); ++LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); ++ ++LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); ++LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); ++LUA_API int (lua_toboolean) (lua_State *L, int idx); ++LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); ++LUA_API size_t (lua_objlen) (lua_State *L, int idx); ++LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); ++LUA_API void *(lua_touserdata) (lua_State *L, int idx); ++LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); ++LUA_API const void *(lua_topointer) (lua_State *L, int idx); ++ ++ ++/* ++** push functions (C -> stack) ++*/ ++LUA_API void (lua_pushnil) (lua_State *L); ++LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); ++LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); ++LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); ++LUA_API void (lua_pushstring) (lua_State *L, const char *s); ++LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, ++ va_list argp); ++LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); ++LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); ++LUA_API void (lua_pushboolean) (lua_State *L, int b); ++LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); ++LUA_API int (lua_pushthread) (lua_State *L); ++ ++ ++/* ++** get functions (Lua -> stack) ++*/ ++LUA_API void (lua_gettable) (lua_State *L, int idx); ++LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); ++LUA_API void (lua_rawget) (lua_State *L, int idx); ++LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); ++LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); ++LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); ++LUA_API int (lua_getmetatable) (lua_State *L, int objindex); ++LUA_API void (lua_getfenv) (lua_State *L, int idx); ++ ++ ++/* ++** set functions (stack -> Lua) ++*/ ++LUA_API void (lua_settable) (lua_State *L, int idx); ++LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); ++LUA_API void (lua_rawset) (lua_State *L, int idx); ++LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); ++LUA_API int (lua_setmetatable) (lua_State *L, int objindex); ++LUA_API int (lua_setfenv) (lua_State *L, int idx); ++ ++ ++/* ++** `load' and `call' functions (load and run Lua code) ++*/ ++LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); ++LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); ++LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); ++LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, ++ const char *chunkname); ++ ++LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); ++ ++ ++/* ++** coroutine functions ++*/ ++LUA_API int (lua_yield) (lua_State *L, int nresults); ++LUA_API int (lua_resume) (lua_State *L, int narg); ++LUA_API int (lua_status) (lua_State *L); ++ ++/* ++** garbage-collection function and options ++*/ ++ ++#define LUA_GCSTOP 0 ++#define LUA_GCRESTART 1 ++#define LUA_GCCOLLECT 2 ++#define LUA_GCCOUNT 3 ++#define LUA_GCCOUNTB 4 ++#define LUA_GCSTEP 5 ++#define LUA_GCSETPAUSE 6 ++#define LUA_GCSETSTEPMUL 7 ++ ++LUA_API int (lua_gc) (lua_State *L, int what, int data); ++ ++ ++/* ++** miscellaneous functions ++*/ ++ ++LUA_API int (lua_error) (lua_State *L); ++ ++LUA_API int (lua_next) (lua_State *L, int idx); ++ ++LUA_API void (lua_concat) (lua_State *L, int n); ++ ++LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); ++LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); ++ ++ ++ ++/* ++** =============================================================== ++** some useful macros ++** =============================================================== ++*/ ++ ++#define lua_pop(L,n) lua_settop(L, -(n)-1) ++ ++#define lua_newtable(L) lua_createtable(L, 0, 0) ++ ++#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) ++ ++#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) ++ ++#define lua_strlen(L,i) lua_objlen(L, (i)) ++ ++#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) ++#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) ++#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) ++#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) ++#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) ++#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) ++#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) ++#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) ++ ++#define lua_pushliteral(L, s) \ ++ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) ++ ++#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) ++#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) ++ ++#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) ++ ++ ++ ++/* ++** compatibility macros and functions ++*/ ++ ++#define lua_open() luaL_newstate() ++ ++#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) ++ ++#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) ++ ++#define lua_Chunkreader lua_Reader ++#define lua_Chunkwriter lua_Writer ++ ++ ++/* hack */ ++LUA_API void lua_setlevel (lua_State *from, lua_State *to); ++ ++ ++/* ++** {====================================================================== ++** Debug API ++** ======================================================================= ++*/ ++ ++ ++/* ++** Event codes ++*/ ++#define LUA_HOOKCALL 0 ++#define LUA_HOOKRET 1 ++#define LUA_HOOKLINE 2 ++#define LUA_HOOKCOUNT 3 ++#define LUA_HOOKTAILRET 4 ++ ++ ++/* ++** Event masks ++*/ ++#define LUA_MASKCALL (1 << LUA_HOOKCALL) ++#define LUA_MASKRET (1 << LUA_HOOKRET) ++#define LUA_MASKLINE (1 << LUA_HOOKLINE) ++#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) ++ ++typedef struct lua_Debug lua_Debug; /* activation record */ ++ ++ ++/* Functions to be called by the debuger in specific events */ ++typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); ++ ++ ++LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); ++LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); ++LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); ++LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); ++LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); ++LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); ++ ++LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); ++LUA_API lua_Hook lua_gethook (lua_State *L); ++LUA_API int lua_gethookmask (lua_State *L); ++LUA_API int lua_gethookcount (lua_State *L); ++ ++ ++struct lua_Debug { ++ int event; ++ const char *name; /* (n) */ ++ const char *namewhat; /* (n) `global', `local', `field', `method' */ ++ const char *what; /* (S) `Lua', `C', `main', `tail' */ ++ const char *source; /* (S) */ ++ int currentline; /* (l) */ ++ int nups; /* (u) number of upvalues */ ++ int linedefined; /* (S) */ ++ int lastlinedefined; /* (S) */ ++ char short_src[LUA_IDSIZE]; /* (S) */ ++ /* private part */ ++ int i_ci; /* active function */ ++}; ++ ++/* }====================================================================== */ ++ ++ ++/****************************************************************************** ++* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. ++* ++* Permission is hereby granted, free of charge, to any person obtaining ++* a copy of this software and associated documentation files (the ++* "Software"), to deal in the Software without restriction, including ++* without limitation the rights to use, copy, modify, merge, publish, ++* distribute, sublicense, and/or sell copies of the Software, and to ++* permit persons to whom the Software is furnished to do so, subject to ++* the following conditions: ++* ++* The above copyright notice and this permission notice shall be ++* included in all copies or substantial portions of the Software. ++* ++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ++* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ++* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ++* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++******************************************************************************/ ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lualib.h +@@ -0,0 +1,55 @@ ++/* ++** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua standard libraries ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lualib_h ++#define lualib_h ++ ++#include "lua.h" ++ ++ ++/* Key to file-handle type */ ++#define LUA_FILEHANDLE "FILE*" ++ ++ ++#define LUA_COLIBNAME "coroutine" ++LUALIB_API int (luaopen_base) (lua_State *L); ++ ++#define LUA_TABLIBNAME "table" ++LUALIB_API int (luaopen_table) (lua_State *L); ++/* ++#define LUA_IOLIBNAME "io" ++LUALIB_API int (luaopen_io) (lua_State *L); ++ ++#define LUA_OSLIBNAME "os" ++LUALIB_API int (luaopen_os) (lua_State *L); ++*/ ++ ++#define LUA_STRLIBNAME "string" ++LUALIB_API int (luaopen_string) (lua_State *L); ++ ++/* ++#define LUA_MATHLIBNAME "math" ++LUALIB_API int (luaopen_math) (lua_State *L); ++ ++#define LUA_DBLIBNAME "debug" ++LUALIB_API int (luaopen_debug) (lua_State *L); ++ ++#define LUA_LOADLIBNAME "package" ++LUALIB_API int (luaopen_package) (lua_State *L); ++*/ ++ ++/* open all previous libraries */ ++LUALIB_API void (luaL_openlibs) (lua_State *L); ++ ++ ++ ++#ifndef lua_assert ++#define lua_assert(x) ((void)0) ++#endif ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lundump.c +@@ -0,0 +1,227 @@ ++/* ++** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ ++** load precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lundump_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstring.h" ++#include "lundump.h" ++#include "lzio.h" ++ ++typedef struct { ++ lua_State* L; ++ ZIO* Z; ++ Mbuffer* b; ++ const char* name; ++} LoadState; ++ ++#ifdef LUAC_TRUST_BINARIES ++#define IF(c,s) ++#define error(S,s) ++#else ++#define IF(c,s) if (c) error(S,s) ++ ++static void error(LoadState* S, const char* why) ++{ ++ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); ++ luaD_throw(S->L,LUA_ERRSYNTAX); ++} ++#endif ++ ++#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) ++#define LoadByte(S) (lu_byte)LoadChar(S) ++#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) ++#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) ++ ++static void LoadBlock(LoadState* S, void* b, size_t size) ++{ ++ size_t r=luaZ_read(S->Z,b,size); ++ IF (r!=0, "unexpected end"); ++} ++ ++static int LoadChar(LoadState* S) ++{ ++ char x; ++ LoadVar(S,x); ++ return x; ++} ++ ++static int LoadInt(LoadState* S) ++{ ++ int x; ++ LoadVar(S,x); ++ IF (x<0, "bad integer"); ++ return x; ++} ++ ++static lua_Number LoadNumber(LoadState* S) ++{ ++ lua_Number x; ++ LoadVar(S,x); ++ return x; ++} ++ ++static TString* LoadString(LoadState* S) ++{ ++ size_t size; ++ LoadVar(S,size); ++ if (size==0) ++ return NULL; ++ else ++ { ++ char* s=luaZ_openspace(S->L,S->b,size); ++ LoadBlock(S,s,size); ++ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ ++ } ++} ++ ++static void LoadCode(LoadState* S, Proto* f) ++{ ++ int n=LoadInt(S); ++ f->code=luaM_newvector(S->L,n,Instruction); ++ f->sizecode=n; ++ LoadVector(S,f->code,n,sizeof(Instruction)); ++} ++ ++static Proto* LoadFunction(LoadState* S, TString* p); ++ ++static void LoadConstants(LoadState* S, Proto* f) ++{ ++ int i,n; ++ n=LoadInt(S); ++ f->k=luaM_newvector(S->L,n,TValue); ++ f->sizek=n; ++ for (i=0; ik[i]); ++ for (i=0; ik[i]; ++ int t=LoadChar(S); ++ switch (t) ++ { ++ case LUA_TNIL: ++ setnilvalue(o); ++ break; ++ case LUA_TBOOLEAN: ++ setbvalue(o,LoadChar(S)!=0); ++ break; ++ case LUA_TNUMBER: ++ setnvalue(o,LoadNumber(S)); ++ break; ++ case LUA_TSTRING: ++ setsvalue2n(S->L,o,LoadString(S)); ++ break; ++ default: ++ error(S,"bad constant"); ++ break; ++ } ++ } ++ n=LoadInt(S); ++ f->p=luaM_newvector(S->L,n,Proto*); ++ f->sizep=n; ++ for (i=0; ip[i]=NULL; ++ for (i=0; ip[i]=LoadFunction(S,f->source); ++} ++ ++static void LoadDebug(LoadState* S, Proto* f) ++{ ++ int i,n; ++ n=LoadInt(S); ++ f->lineinfo=luaM_newvector(S->L,n,int); ++ f->sizelineinfo=n; ++ LoadVector(S,f->lineinfo,n,sizeof(int)); ++ n=LoadInt(S); ++ f->locvars=luaM_newvector(S->L,n,LocVar); ++ f->sizelocvars=n; ++ for (i=0; ilocvars[i].varname=NULL; ++ for (i=0; ilocvars[i].varname=LoadString(S); ++ f->locvars[i].startpc=LoadInt(S); ++ f->locvars[i].endpc=LoadInt(S); ++ } ++ n=LoadInt(S); ++ f->upvalues=luaM_newvector(S->L,n,TString*); ++ f->sizeupvalues=n; ++ for (i=0; iupvalues[i]=NULL; ++ for (i=0; iupvalues[i]=LoadString(S); ++} ++ ++static Proto* LoadFunction(LoadState* S, TString* p) ++{ ++ Proto* f; ++ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); ++ f=luaF_newproto(S->L); ++ setptvalue2s(S->L,S->L->top,f); incr_top(S->L); ++ f->source=LoadString(S); if (f->source==NULL) f->source=p; ++ f->linedefined=LoadInt(S); ++ f->lastlinedefined=LoadInt(S); ++ f->nups=LoadByte(S); ++ f->numparams=LoadByte(S); ++ f->is_vararg=LoadByte(S); ++ f->maxstacksize=LoadByte(S); ++ LoadCode(S,f); ++ LoadConstants(S,f); ++ LoadDebug(S,f); ++ IF (!luaG_checkcode(f), "bad code"); ++ S->L->top--; ++ S->L->nCcalls--; ++ return f; ++} ++ ++static void LoadHeader(LoadState* S) ++{ ++ char h[LUAC_HEADERSIZE]; ++ char s[LUAC_HEADERSIZE]; ++ luaU_header(h); ++ LoadBlock(S,s,LUAC_HEADERSIZE); ++ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); ++} ++ ++/* ++** load precompiled chunk ++*/ ++Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) ++{ ++ LoadState S; ++ if (*name=='@' || *name=='=') ++ S.name=name+1; ++ else if (*name==LUA_SIGNATURE[0]) ++ S.name="binary string"; ++ else ++ S.name=name; ++ S.L=L; ++ S.Z=Z; ++ S.b=buff; ++ LoadHeader(&S); ++ return LoadFunction(&S,luaS_newliteral(L,"=?")); ++} ++ ++/* ++* make header ++*/ ++void luaU_header (char* h) ++{ ++ int x=1; ++ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); ++ h+=sizeof(LUA_SIGNATURE)-1; ++ *h++=(char)LUAC_VERSION; ++ *h++=(char)LUAC_FORMAT; ++ *h++=(char)*(char*)&x; /* endianness */ ++ *h++=(char)sizeof(int); ++ *h++=(char)sizeof(size_t); ++ *h++=(char)sizeof(Instruction); ++ *h++=(char)sizeof(lua_Number); ++ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ ++} +--- /dev/null ++++ b/extensions/LUA/lua/lundump.h +@@ -0,0 +1,36 @@ ++/* ++** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ++** load precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lundump_h ++#define lundump_h ++ ++#include "lobject.h" ++#include "lzio.h" ++ ++/* load one chunk; from lundump.c */ ++LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); ++ ++/* make header; from lundump.c */ ++LUAI_FUNC void luaU_header (char* h); ++ ++/* dump one chunk; from ldump.c */ ++LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); ++ ++#ifdef luac_c ++/* print one chunk; from print.c */ ++LUAI_FUNC void luaU_print (const Proto* f, int full); ++#endif ++ ++/* for header of binary files -- this is Lua 5.1 */ ++#define LUAC_VERSION 0x51 ++ ++/* for header of binary files -- this is the official format */ ++#define LUAC_FORMAT 0 ++ ++/* size of header of binary files */ ++#define LUAC_HEADERSIZE 12 ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lvm.c +@@ -0,0 +1,762 @@ ++/* ++** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++#include ++#include ++ ++#define lvm_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lvm.h" ++ ++ ++ ++/* limit for table tag-method chains (to avoid loops) */ ++#define MAXTAGLOOP 100 ++ ++ ++const TValue *luaV_tonumber (const TValue *obj, TValue *n) { ++ lua_Number num; ++ if (ttisnumber(obj)) return obj; ++ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { ++ setnvalue(n, num); ++ return n; ++ } ++ else ++ return NULL; ++} ++ ++ ++int luaV_tostring (lua_State *L, StkId obj) { ++ if (!ttisnumber(obj)) ++ return 0; ++ else { ++ char s[LUAI_MAXNUMBER2STR]; ++ lua_Number n = nvalue(obj); ++ lua_number2str(s, n); ++ setsvalue2s(L, obj, luaS_new(L, s)); ++ return 1; ++ } ++} ++ ++ ++static void traceexec (lua_State *L, const Instruction *pc) { ++ lu_byte mask = L->hookmask; ++ const Instruction *oldpc = L->savedpc; ++ L->savedpc = pc; ++ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { ++ resethookcount(L); ++ luaD_callhook(L, LUA_HOOKCOUNT, -1); ++ } ++ if (mask & LUA_MASKLINE) { ++ Proto *p = ci_func(L->ci)->l.p; ++ int npc = pcRel(pc, p); ++ int newline = getline(p, npc); ++ /* call linehook when enter a new function, when jump back (loop), ++ or when enter a new line */ ++ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) ++ luaD_callhook(L, LUA_HOOKLINE, newline); ++ } ++} ++ ++ ++static void callTMres (lua_State *L, StkId res, const TValue *f, ++ const TValue *p1, const TValue *p2) { ++ ptrdiff_t result = savestack(L, res); ++ setobj2s(L, L->top, f); /* push function */ ++ setobj2s(L, L->top+1, p1); /* 1st argument */ ++ setobj2s(L, L->top+2, p2); /* 2nd argument */ ++ luaD_checkstack(L, 3); ++ L->top += 3; ++ luaD_call(L, L->top - 3, 1); ++ res = restorestack(L, result); ++ L->top--; ++ setobjs2s(L, res, L->top); ++} ++ ++ ++ ++static void callTM (lua_State *L, const TValue *f, const TValue *p1, ++ const TValue *p2, const TValue *p3) { ++ setobj2s(L, L->top, f); /* push function */ ++ setobj2s(L, L->top+1, p1); /* 1st argument */ ++ setobj2s(L, L->top+2, p2); /* 2nd argument */ ++ setobj2s(L, L->top+3, p3); /* 3th argument */ ++ luaD_checkstack(L, 4); ++ L->top += 4; ++ luaD_call(L, L->top - 4, 0); ++} ++ ++ ++void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { ++ int loop; ++ for (loop = 0; loop < MAXTAGLOOP; loop++) { ++ const TValue *tm; ++ if (ttistable(t)) { /* `t' is a table? */ ++ Table *h = hvalue(t); ++ const TValue *res = luaH_get(h, key); /* do a primitive get */ ++ if (!ttisnil(res) || /* result is no nil? */ ++ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ ++ setobj2s(L, val, res); ++ return; ++ } ++ /* else will try the tag method */ ++ } ++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) ++ luaG_typeerror(L, t, "index"); ++ if (ttisfunction(tm)) { ++ callTMres(L, val, tm, t, key); ++ return; ++ } ++ t = tm; /* else repeat with `tm' */ ++ } ++ luaG_runerror(L, "loop in gettable"); ++} ++ ++ ++void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { ++ int loop; ++ for (loop = 0; loop < MAXTAGLOOP; loop++) { ++ const TValue *tm; ++ if (ttistable(t)) { /* `t' is a table? */ ++ Table *h = hvalue(t); ++ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ ++ if (!ttisnil(oldval) || /* result is no nil? */ ++ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ ++ setobj2t(L, oldval, val); ++ luaC_barriert(L, h, val); ++ return; ++ } ++ /* else will try the tag method */ ++ } ++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) ++ luaG_typeerror(L, t, "index"); ++ if (ttisfunction(tm)) { ++ callTM(L, tm, t, key, val); ++ return; ++ } ++ t = tm; /* else repeat with `tm' */ ++ } ++ luaG_runerror(L, "loop in settable"); ++} ++ ++ ++static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, ++ StkId res, TMS event) { ++ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ ++ if (ttisnil(tm)) ++ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ ++ if (ttisnil(tm)) return 0; ++ callTMres(L, res, tm, p1, p2); ++ return 1; ++} ++ ++ ++static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, ++ TMS event) { ++ const TValue *tm1 = fasttm(L, mt1, event); ++ const TValue *tm2; ++ if (tm1 == NULL) return NULL; /* no metamethod */ ++ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ ++ tm2 = fasttm(L, mt2, event); ++ if (tm2 == NULL) return NULL; /* no metamethod */ ++ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ ++ return tm1; ++ return NULL; ++} ++ ++ ++static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, ++ TMS event) { ++ const TValue *tm1 = luaT_gettmbyobj(L, p1, event); ++ const TValue *tm2; ++ if (ttisnil(tm1)) return -1; /* no metamethod? */ ++ tm2 = luaT_gettmbyobj(L, p2, event); ++ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ ++ return -1; ++ callTMres(L, L->top, tm1, p1, p2); ++ return !l_isfalse(L->top); ++} ++ ++ ++static int l_strcmp (const TString *ls, const TString *rs) { ++ const char *l = getstr(ls); ++ size_t ll = ls->tsv.len; ++ const char *r = getstr(rs); ++ size_t lr = rs->tsv.len; ++ for (;;) { ++ int temp = strcoll(l, r); ++ if (temp != 0) return temp; ++ else { /* strings are equal up to a `\0' */ ++ size_t len = strlen(l); /* index of first `\0' in both strings */ ++ if (len == lr) /* r is finished? */ ++ return (len == ll) ? 0 : 1; ++ else if (len == ll) /* l is finished? */ ++ return -1; /* l is smaller than r (because r is not finished) */ ++ /* both strings longer than `len'; go on comparing (after the `\0') */ ++ len++; ++ l += len; ll -= len; r += len; lr -= len; ++ } ++ } ++} ++ ++ ++int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { ++ int res; ++ if (ttype(l) != ttype(r)) ++ return luaG_ordererror(L, l, r); ++ else if (ttisnumber(l)) ++ return luai_numlt(nvalue(l), nvalue(r)); ++ else if (ttisstring(l)) ++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; ++ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) ++ return res; ++ return luaG_ordererror(L, l, r); ++} ++ ++ ++static int lessequal (lua_State *L, const TValue *l, const TValue *r) { ++ int res; ++ if (ttype(l) != ttype(r)) ++ return luaG_ordererror(L, l, r); ++ else if (ttisnumber(l)) ++ return luai_numle(nvalue(l), nvalue(r)); ++ else if (ttisstring(l)) ++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; ++ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ ++ return res; ++ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ ++ return !res; ++ return luaG_ordererror(L, l, r); ++} ++ ++ ++int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { ++ const TValue *tm; ++ lua_assert(ttype(t1) == ttype(t2)); ++ switch (ttype(t1)) { ++ case LUA_TNIL: return 1; ++ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); ++ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); ++ case LUA_TUSERDATA: { ++ if (uvalue(t1) == uvalue(t2)) return 1; ++ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, ++ TM_EQ); ++ break; /* will try TM */ ++ } ++ case LUA_TTABLE: { ++ if (hvalue(t1) == hvalue(t2)) return 1; ++ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); ++ break; /* will try TM */ ++ } ++ default: return gcvalue(t1) == gcvalue(t2); ++ } ++ if (tm == NULL) return 0; /* no TM? */ ++ callTMres(L, L->top, tm, t1, t2); /* call TM */ ++ return !l_isfalse(L->top); ++} ++ ++ ++void luaV_concat (lua_State *L, int total, int last) { ++ do { ++ StkId top = L->base + last + 1; ++ int n = 2; /* number of elements handled in this pass (at least 2) */ ++ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { ++ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) ++ luaG_concaterror(L, top-2, top-1); ++ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ ++ (void)tostring(L, top - 2); /* result is first op (as string) */ ++ else { ++ /* at least two string values; get as many as possible */ ++ size_t tl = tsvalue(top-1)->len; ++ char *buffer; ++ int i; ++ /* collect total length */ ++ for (n = 1; n < total && tostring(L, top-n-1); n++) { ++ size_t l = tsvalue(top-n-1)->len; ++ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); ++ tl += l; ++ } ++ buffer = luaZ_openspace(L, &G(L)->buff, tl); ++ tl = 0; ++ for (i=n; i>0; i--) { /* concat all strings */ ++ size_t l = tsvalue(top-i)->len; ++ memcpy(buffer+tl, svalue(top-i), l); ++ tl += l; ++ } ++ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); ++ } ++ total -= n-1; /* got `n' strings to create 1 new */ ++ last -= n-1; ++ } while (total > 1); /* repeat until only 1 result left */ ++} ++ ++ ++static void Arith (lua_State *L, StkId ra, const TValue *rb, ++ const TValue *rc, TMS op) { ++ TValue tempb, tempc; ++ const TValue *b, *c; ++ if ((b = luaV_tonumber(rb, &tempb)) != NULL && ++ (c = luaV_tonumber(rc, &tempc)) != NULL) { ++ lua_Number nb = nvalue(b), nc = nvalue(c); ++ switch (op) { ++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; ++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; ++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; ++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; ++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; ++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; ++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; ++ default: lua_assert(0); break; ++ } ++ } ++ else if (!call_binTM(L, rb, rc, ra, op)) ++ luaG_aritherror(L, rb, rc); ++} ++ ++ ++ ++/* ++** some macros for common tasks in `luaV_execute' ++*/ ++ ++#define runtime_check(L, c) { if (!(c)) break; } ++ ++#define RA(i) (base+GETARG_A(i)) ++/* to be used after possible stack reallocation */ ++#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) ++#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) ++#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ ++ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) ++#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ ++ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) ++#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) ++ ++ ++#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} ++ ++ ++#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } ++ ++ ++#define arith_op(op,tm) { \ ++ TValue *rb = RKB(i); \ ++ TValue *rc = RKC(i); \ ++ if (ttisnumber(rb) && ttisnumber(rc)) { \ ++ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ ++ setnvalue(ra, op(nb, nc)); \ ++ } \ ++ else \ ++ Protect(Arith(L, ra, rb, rc, tm)); \ ++ } ++ ++ ++ ++void luaV_execute (lua_State *L, int nexeccalls) { ++ LClosure *cl; ++ StkId base; ++ TValue *k; ++ const Instruction *pc; ++ reentry: /* entry point */ ++ lua_assert(isLua(L->ci)); ++ pc = L->savedpc; ++ cl = &clvalue(L->ci->func)->l; ++ base = L->base; ++ k = cl->p->k; ++ /* main loop of interpreter */ ++ for (;;) { ++ const Instruction i = *pc++; ++ StkId ra; ++ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && ++ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { ++ traceexec(L, pc); ++ if (L->status == LUA_YIELD) { /* did hook yield? */ ++ L->savedpc = pc - 1; ++ return; ++ } ++ base = L->base; ++ } ++ /* warning!! several calls may realloc the stack and invalidate `ra' */ ++ ra = RA(i); ++ lua_assert(base == L->base && L->base == L->ci->base); ++ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); ++ lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); ++ switch (GET_OPCODE(i)) { ++ case OP_MOVE: { ++ setobjs2s(L, ra, RB(i)); ++ continue; ++ } ++ case OP_LOADK: { ++ setobj2s(L, ra, KBx(i)); ++ continue; ++ } ++ case OP_LOADBOOL: { ++ setbvalue(ra, GETARG_B(i)); ++ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ ++ continue; ++ } ++ case OP_LOADNIL: { ++ TValue *rb = RB(i); ++ do { ++ setnilvalue(rb--); ++ } while (rb >= ra); ++ continue; ++ } ++ case OP_GETUPVAL: { ++ int b = GETARG_B(i); ++ setobj2s(L, ra, cl->upvals[b]->v); ++ continue; ++ } ++ case OP_GETGLOBAL: { ++ TValue g; ++ TValue *rb = KBx(i); ++ sethvalue(L, &g, cl->env); ++ lua_assert(ttisstring(rb)); ++ Protect(luaV_gettable(L, &g, rb, ra)); ++ continue; ++ } ++ case OP_GETTABLE: { ++ Protect(luaV_gettable(L, RB(i), RKC(i), ra)); ++ continue; ++ } ++ case OP_SETGLOBAL: { ++ TValue g; ++ sethvalue(L, &g, cl->env); ++ lua_assert(ttisstring(KBx(i))); ++ Protect(luaV_settable(L, &g, KBx(i), ra)); ++ continue; ++ } ++ case OP_SETUPVAL: { ++ UpVal *uv = cl->upvals[GETARG_B(i)]; ++ setobj(L, uv->v, ra); ++ luaC_barrier(L, uv, ra); ++ continue; ++ } ++ case OP_SETTABLE: { ++ Protect(luaV_settable(L, ra, RKB(i), RKC(i))); ++ continue; ++ } ++ case OP_NEWTABLE: { ++ int b = GETARG_B(i); ++ int c = GETARG_C(i); ++ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); ++ Protect(luaC_checkGC(L)); ++ continue; ++ } ++ case OP_SELF: { ++ StkId rb = RB(i); ++ setobjs2s(L, ra+1, rb); ++ Protect(luaV_gettable(L, rb, RKC(i), ra)); ++ continue; ++ } ++ case OP_ADD: { ++ arith_op(luai_numadd, TM_ADD); ++ continue; ++ } ++ case OP_SUB: { ++ arith_op(luai_numsub, TM_SUB); ++ continue; ++ } ++ case OP_MUL: { ++ arith_op(luai_nummul, TM_MUL); ++ continue; ++ } ++ case OP_DIV: { ++ arith_op(luai_numdiv, TM_DIV); ++ continue; ++ } ++ case OP_MOD: { ++ arith_op(luai_nummod, TM_MOD); ++ continue; ++ } ++ case OP_POW: { ++ arith_op(luai_numpow, TM_POW); ++ continue; ++ } ++ case OP_UNM: { ++ TValue *rb = RB(i); ++ if (ttisnumber(rb)) { ++ lua_Number nb = nvalue(rb); ++ setnvalue(ra, luai_numunm(nb)); ++ } ++ else { ++ Protect(Arith(L, ra, rb, rb, TM_UNM)); ++ } ++ continue; ++ } ++ case OP_NOT: { ++ int res = l_isfalse(RB(i)); /* next assignment may change this value */ ++ setbvalue(ra, res); ++ continue; ++ } ++ case OP_LEN: { ++ const TValue *rb = RB(i); ++ switch (ttype(rb)) { ++ case LUA_TTABLE: { ++ setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); ++ break; ++ } ++ case LUA_TSTRING: { ++ setnvalue(ra, cast_num(tsvalue(rb)->len)); ++ break; ++ } ++ default: { /* try metamethod */ ++ Protect( ++ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) ++ luaG_typeerror(L, rb, "get length of"); ++ ) ++ } ++ } ++ continue; ++ } ++ case OP_CONCAT: { ++ int b = GETARG_B(i); ++ int c = GETARG_C(i); ++ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); ++ setobjs2s(L, RA(i), base+b); ++ continue; ++ } ++ case OP_JMP: { ++ dojump(L, pc, GETARG_sBx(i)); ++ continue; ++ } ++ case OP_EQ: { ++ TValue *rb = RKB(i); ++ TValue *rc = RKC(i); ++ Protect( ++ if (equalobj(L, rb, rc) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_LT: { ++ Protect( ++ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_LE: { ++ Protect( ++ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_TEST: { ++ if (l_isfalse(ra) != GETARG_C(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ pc++; ++ continue; ++ } ++ case OP_TESTSET: { ++ TValue *rb = RB(i); ++ if (l_isfalse(rb) != GETARG_C(i)) { ++ setobjs2s(L, ra, rb); ++ dojump(L, pc, GETARG_sBx(*pc)); ++ } ++ pc++; ++ continue; ++ } ++ case OP_CALL: { ++ int b = GETARG_B(i); ++ int nresults = GETARG_C(i) - 1; ++ if (b != 0) L->top = ra+b; /* else previous instruction set top */ ++ L->savedpc = pc; ++ switch (luaD_precall(L, ra, nresults)) { ++ case PCRLUA: { ++ nexeccalls++; ++ goto reentry; /* restart luaV_execute over new Lua function */ ++ } ++ case PCRC: { ++ /* it was a C function (`precall' called it); adjust results */ ++ if (nresults >= 0) L->top = L->ci->top; ++ base = L->base; ++ continue; ++ } ++ default: { ++ return; /* yield */ ++ } ++ } ++ } ++ case OP_TAILCALL: { ++ int b = GETARG_B(i); ++ if (b != 0) L->top = ra+b; /* else previous instruction set top */ ++ L->savedpc = pc; ++ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); ++ switch (luaD_precall(L, ra, LUA_MULTRET)) { ++ case PCRLUA: { ++ /* tail call: put new frame in place of previous one */ ++ CallInfo *ci = L->ci - 1; /* previous frame */ ++ int aux; ++ StkId func = ci->func; ++ StkId pfunc = (ci+1)->func; /* previous function index */ ++ if (L->openupval) luaF_close(L, ci->base); ++ L->base = ci->base = ci->func + ((ci+1)->base - pfunc); ++ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ ++ setobjs2s(L, func+aux, pfunc+aux); ++ ci->top = L->top = func+aux; /* correct top */ ++ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); ++ ci->savedpc = L->savedpc; ++ ci->tailcalls++; /* one more call lost */ ++ L->ci--; /* remove new frame */ ++ goto reentry; ++ } ++ case PCRC: { /* it was a C function (`precall' called it) */ ++ base = L->base; ++ continue; ++ } ++ default: { ++ return; /* yield */ ++ } ++ } ++ } ++ case OP_RETURN: { ++ int b = GETARG_B(i); ++ if (b != 0) L->top = ra+b-1; ++ if (L->openupval) luaF_close(L, base); ++ L->savedpc = pc; ++ b = luaD_poscall(L, ra); ++ if (--nexeccalls == 0) /* was previous function running `here'? */ ++ return; /* no: return */ ++ else { /* yes: continue its execution */ ++ if (b) L->top = L->ci->top; ++ lua_assert(isLua(L->ci)); ++ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); ++ goto reentry; ++ } ++ } ++ case OP_FORLOOP: { ++ lua_Number step = nvalue(ra+2); ++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ ++ lua_Number limit = nvalue(ra+1); ++ if (luai_numlt(0, step) ? luai_numle(idx, limit) ++ : luai_numle(limit, idx)) { ++ dojump(L, pc, GETARG_sBx(i)); /* jump back */ ++ setnvalue(ra, idx); /* update internal index... */ ++ setnvalue(ra+3, idx); /* ...and external index */ ++ } ++ continue; ++ } ++ case OP_FORPREP: { ++ const TValue *init = ra; ++ const TValue *plimit = ra+1; ++ const TValue *pstep = ra+2; ++ L->savedpc = pc; /* next steps may throw errors */ ++ if (!tonumber(init, ra)) ++ luaG_runerror(L, LUA_QL("for") " initial value must be a number"); ++ else if (!tonumber(plimit, ra+1)) ++ luaG_runerror(L, LUA_QL("for") " limit must be a number"); ++ else if (!tonumber(pstep, ra+2)) ++ luaG_runerror(L, LUA_QL("for") " step must be a number"); ++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); ++ dojump(L, pc, GETARG_sBx(i)); ++ continue; ++ } ++ case OP_TFORLOOP: { ++ StkId cb = ra + 3; /* call base */ ++ setobjs2s(L, cb+2, ra+2); ++ setobjs2s(L, cb+1, ra+1); ++ setobjs2s(L, cb, ra); ++ L->top = cb+3; /* func. + 2 args (state and index) */ ++ Protect(luaD_call(L, cb, GETARG_C(i))); ++ L->top = L->ci->top; ++ cb = RA(i) + 3; /* previous call may change the stack */ ++ if (!ttisnil(cb)) { /* continue loop? */ ++ setobjs2s(L, cb-1, cb); /* save control variable */ ++ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ ++ } ++ pc++; ++ continue; ++ } ++ case OP_SETLIST: { ++ int n = GETARG_B(i); ++ int c = GETARG_C(i); ++ int last; ++ Table *h; ++ if (n == 0) { ++ n = cast_int(L->top - ra) - 1; ++ L->top = L->ci->top; ++ } ++ if (c == 0) c = cast_int(*pc++); ++ runtime_check(L, ttistable(ra)); ++ h = hvalue(ra); ++ last = ((c-1)*LFIELDS_PER_FLUSH) + n; ++ if (last > h->sizearray) /* needs more space? */ ++ luaH_resizearray(L, h, last); /* pre-alloc it at once */ ++ for (; n > 0; n--) { ++ TValue *val = ra+n; ++ setobj2t(L, luaH_setnum(L, h, last--), val); ++ luaC_barriert(L, h, val); ++ } ++ continue; ++ } ++ case OP_CLOSE: { ++ luaF_close(L, ra); ++ continue; ++ } ++ case OP_CLOSURE: { ++ Proto *p; ++ Closure *ncl; ++ int nup, j; ++ p = cl->p->p[GETARG_Bx(i)]; ++ nup = p->nups; ++ ncl = luaF_newLclosure(L, nup, cl->env); ++ ncl->l.p = p; ++ for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; ++ else { ++ lua_assert(GET_OPCODE(*pc) == OP_MOVE); ++ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); ++ } ++ } ++ setclvalue(L, ra, ncl); ++ Protect(luaC_checkGC(L)); ++ continue; ++ } ++ case OP_VARARG: { ++ int b = GETARG_B(i) - 1; ++ int j; ++ CallInfo *ci = L->ci; ++ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; ++ if (b == LUA_MULTRET) { ++ Protect(luaD_checkstack(L, n)); ++ ra = RA(i); /* previous call may change the stack */ ++ b = n; ++ L->top = ra + n; ++ } ++ for (j = 0; j < b; j++) { ++ if (j < n) { ++ setobjs2s(L, ra + j, ci->base - n + j); ++ } ++ else { ++ setnilvalue(ra + j); ++ } ++ } ++ continue; ++ } ++ } ++ } ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lvm.h +@@ -0,0 +1,36 @@ ++/* ++** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lvm_h ++#define lvm_h ++ ++ ++#include "ldo.h" ++#include "lobject.h" ++#include "ltm.h" ++ ++ ++#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) ++ ++#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ ++ (((o) = luaV_tonumber(o,n)) != NULL)) ++ ++#define equalobj(L,o1,o2) \ ++ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) ++ ++ ++LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); ++LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); ++LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); ++LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); ++LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, ++ StkId val); ++LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, ++ StkId val); ++LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); ++LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lzio.c +@@ -0,0 +1,81 @@ ++/* ++** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ++** a generic input stream interface ++** See Copyright Notice in lua.h ++*/ ++ ++#include ++ ++#define lzio_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "llimits.h" ++#include "lmem.h" ++#include "lstate.h" ++#include "lzio.h" ++ ++ ++int luaZ_fill (ZIO *z) { ++ size_t size; ++ lua_State *L = z->L; ++ const char *buff; ++ lua_unlock(L); ++ buff = z->reader(L, z->data, &size); ++ lua_lock(L); ++ if (buff == NULL || size == 0) return EOZ; ++ z->n = size - 1; ++ z->p = buff; ++ return char2int(*(z->p++)); ++} ++ ++ ++int luaZ_lookahead (ZIO *z) { ++ if (z->n == 0) { ++ if (luaZ_fill(z) == EOZ) ++ return EOZ; ++ else { ++ z->n++; /* luaZ_fill removed first byte; put back it */ ++ z->p--; ++ } ++ } ++ return char2int(*z->p); ++} ++ ++ ++void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { ++ z->L = L; ++ z->reader = reader; ++ z->data = data; ++ z->n = 0; ++ z->p = NULL; ++} ++ ++ ++/* --------------------------------------------------------------- read --- */ ++size_t luaZ_read (ZIO *z, void *b, size_t n) { ++ while (n) { ++ size_t m; ++ if (luaZ_lookahead(z) == EOZ) ++ return n; /* return number of missing bytes */ ++ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ ++ memcpy(b, z->p, m); ++ z->n -= m; ++ z->p += m; ++ b = (char *)b + m; ++ n -= m; ++ } ++ return 0; ++} ++ ++/* ------------------------------------------------------------------------ */ ++char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { ++ if (n > buff->buffsize) { ++ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; ++ luaZ_resizebuffer(L, buff, n); ++ } ++ return buff->buffer; ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/lua/lzio.h +@@ -0,0 +1,67 @@ ++/* ++** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Buffered streams ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lzio_h ++#define lzio_h ++ ++#include "lua.h" ++ ++#include "lmem.h" ++ ++ ++#define EOZ (-1) /* end of stream */ ++ ++typedef struct Zio ZIO; ++ ++#define char2int(c) cast(int, cast(unsigned char, (c))) ++ ++#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) ++ ++typedef struct Mbuffer { ++ char *buffer; ++ size_t n; ++ size_t buffsize; ++} Mbuffer; ++ ++#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) ++ ++#define luaZ_buffer(buff) ((buff)->buffer) ++#define luaZ_sizebuffer(buff) ((buff)->buffsize) ++#define luaZ_bufflen(buff) ((buff)->n) ++ ++#define luaZ_resetbuffer(buff) ((buff)->n = 0) ++ ++ ++#define luaZ_resizebuffer(L, buff, size) \ ++ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ ++ (buff)->buffsize = size) ++ ++#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) ++ ++ ++LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); ++LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, ++ void *data); ++LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ ++LUAI_FUNC int luaZ_lookahead (ZIO *z); ++ ++ ++ ++/* --------- Private Part ------------------ */ ++ ++struct Zio { ++ size_t n; /* bytes still unread */ ++ const char *p; /* current position in buffer */ ++ lua_Reader reader; ++ void* data; /* additional data */ ++ lua_State *L; /* Lua state (for reader) */ ++}; ++ ++ ++LUAI_FUNC int luaZ_fill (ZIO *z); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/Makefile +@@ -0,0 +1,389 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# extensions/LUA/Makefile. Generated from Makefile.in by configure. ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++ ++ ++# -*- Makefile -*- ++# AUTOMAKE ++ ++pkgdatadir = $(datadir)/xtables-addons ++pkgincludedir = $(includedir)/xtables-addons ++pkglibdir = $(libdir)/xtables-addons ++pkglibexecdir = $(libexecdir)/xtables-addons ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = i686-pc-linux-gnu ++host_triplet = i686-pc-linux-gnu ++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ ++ $(srcdir)/Makefile.in ++subdir = extensions/LUA ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ ++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ ++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++SOURCES = ++DIST_SOURCES = ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run aclocal-1.11 ++AMTAR = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run tar ++AR = ar ++AUTOCONF = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoconf ++AUTOHEADER = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoheader ++AUTOMAKE = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run automake-1.11 ++AWK = mawk ++CC = gcc ++CCDEPMODE = depmode=gcc3 ++CFLAGS = -g -O2 ++CPP = gcc -E ++CPPFLAGS = ++CYGPATH_W = echo ++DEFS = -DHAVE_CONFIG_H ++DEPDIR = .deps ++DSYMUTIL = ++DUMPBIN = ++ECHO_C = ++ECHO_N = -n ++ECHO_T = ++EGREP = /bin/grep -E ++EXEEXT = ++FGREP = /bin/grep -F ++GREP = /bin/grep ++INSTALL = /usr/bin/install -c ++INSTALL_DATA = ${INSTALL} -m 644 ++INSTALL_PROGRAM = ${INSTALL} ++INSTALL_SCRIPT = ${INSTALL} ++INSTALL_STRIP_PROGRAM = $(install_sh) -c -s ++LD = /usr/bin/ld ++LDFLAGS = ++LIBOBJS = ++LIBS = ++LIBTOOL = $(SHELL) $(top_builddir)/libtool ++LIPO = ++LN_S = ln -s ++LTLIBOBJS = ++MAKEINFO = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run makeinfo ++MKDIR_P = /bin/mkdir -p ++NM = /usr/bin/nm -B ++NMEDIT = ++OBJDUMP = objdump ++OBJEXT = o ++OTOOL = ++OTOOL64 = ++PACKAGE = xtables-addons ++PACKAGE_BUGREPORT = ++PACKAGE_NAME = xtables-addons ++PACKAGE_STRING = xtables-addons 1.21 ++PACKAGE_TARNAME = xtables-addons ++PACKAGE_URL = ++PACKAGE_VERSION = 1.21 ++PATH_SEPARATOR = : ++PKG_CONFIG = /usr/bin/pkg-config ++RANLIB = ranlib ++SED = /bin/sed ++SET_MAKE = ++SHELL = /bin/bash ++STRIP = strip ++VERSION = 1.21 ++abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA ++abs_srcdir = /home/andre/Dropbox/xtables-addons/extensions/LUA ++abs_top_builddir = /home/andre/Dropbox/xtables-addons ++abs_top_srcdir = /home/andre/Dropbox/xtables-addons ++ac_ct_CC = gcc ++ac_ct_DUMPBIN = ++am__include = include ++am__leading_dot = . ++am__quote = ++am__tar = ${AMTAR} chof - "$$tardir" ++am__untar = ${AMTAR} xf - ++bindir = ${exec_prefix}/bin ++build = i686-pc-linux-gnu ++build_alias = ++build_cpu = i686 ++build_os = linux-gnu ++build_vendor = pc ++builddir = . ++datadir = ${datarootdir} ++datarootdir = ${prefix}/share ++docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} ++dvidir = ${docdir} ++exec_prefix = ${prefix} ++host = i686-pc-linux-gnu ++host_alias = ++host_cpu = i686 ++host_os = linux-gnu ++host_vendor = pc ++htmldir = ${docdir} ++includedir = ${prefix}/include ++infodir = ${datarootdir}/info ++install_sh = ${SHELL} /home/andre/Dropbox/xtables-addons/install-sh ++kbuilddir = /lib/modules/2.6.33-020633-generic/build ++kinclude_CFLAGS = -I /lib/modules/2.6.33-020633-generic/build/include ++ksourcedir = ++libdir = ${exec_prefix}/lib ++libexecdir = ${exec_prefix}/libexec ++libxtables_CFLAGS = ++libxtables_LIBS = -L/lib -lxtables ++localedir = ${datarootdir}/locale ++localstatedir = ${prefix}/var ++lt_ECHO = echo ++mandir = ${datarootdir}/man ++mkdir_p = /bin/mkdir -p ++oldincludedir = /usr/include ++pdfdir = ${docdir} ++prefix = /usr/local ++program_transform_name = s,x,x, ++psdir = ${docdir} ++regular_CFLAGS = -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Winline -pipe -DXTABLES_LIBDIR=\"${xtlibdir}\" ++sbindir = ${exec_prefix}/sbin ++sharedstatedir = ${prefix}/com ++srcdir = . ++sysconfdir = ${prefix}/etc ++target_alias = ++top_build_prefix = ../../ ++top_builddir = ../.. ++top_srcdir = ../.. ++xtlibdir = ${libexecdir}/xtables ++XA_SRCDIR = ${srcdir} ++XA_TOPSRCDIR = ${top_srcdir} ++XA_ABSTOPSRCDIR = ${abs_top_srcdir} ++_mcall = -f ${top_builddir}/Makefile.iptrules ++all: all-am ++ ++.SUFFIXES: ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --foreign extensions/LUA/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++tags: TAGS ++TAGS: ++ ++ctags: CTAGS ++CTAGS: ++ ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile all-local ++installdirs: ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-local mostlyclean-am ++ ++distclean: distclean-am ++ -rm -f Makefile ++distclean-am: clean-am distclean-generic ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: install-exec-local ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-generic mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: ++ ++.MAKE: install-am install-strip ++ ++.PHONY: all all-am all-local check check-am clean clean-generic \ ++ clean-libtool clean-local distclean distclean-generic \ ++ distclean-libtool distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am install-dvi \ ++ install-dvi-am install-exec install-exec-am install-exec-local \ ++ install-html install-html-am install-info install-info-am \ ++ install-man install-pdf install-pdf-am install-ps \ ++ install-ps-am install-strip installcheck installcheck-am \ ++ installdirs maintainer-clean maintainer-clean-generic \ ++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ++ ps ps-am uninstall uninstall-am ++ ++export XA_SRCDIR ++export XA_TOPSRCDIR ++export XA_ABSTOPSRCDIR ++ ++all-local: user-all-local ++ ++install-exec-local: user-install-local ++ ++clean-local: user-clean-local ++ ++user-all-local: ++ ${MAKE} ${_mcall} all; ++ ++# Have no user-install-data-local ATM ++user-install-local: user-install-exec-local ++ ++user-install-exec-local: ++ ${MAKE} ${_mcall} install; ++ ++user-clean-local: ++ ${MAKE} ${_mcall} clean; ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: ++ +--- /dev/null ++++ b/extensions/LUA/Makefile.am +@@ -0,0 +1 @@ ++include ../../Makefile.extra +--- /dev/null ++++ b/extensions/LUA/Makefile.in +@@ -0,0 +1,389 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# @configure_input@ ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++@SET_MAKE@ ++ ++# -*- Makefile -*- ++# AUTOMAKE ++VPATH = @srcdir@ ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkglibexecdir = $(libexecdir)/@PACKAGE@ ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = @build@ ++host_triplet = @host@ ++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ ++ $(srcdir)/Makefile.in ++subdir = extensions/LUA ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ ++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ ++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++SOURCES = ++DIST_SOURCES = ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = @ACLOCAL@ ++AMTAR = @AMTAR@ ++AR = @AR@ ++AUTOCONF = @AUTOCONF@ ++AUTOHEADER = @AUTOHEADER@ ++AUTOMAKE = @AUTOMAKE@ ++AWK = @AWK@ ++CC = @CC@ ++CCDEPMODE = @CCDEPMODE@ ++CFLAGS = @CFLAGS@ ++CPP = @CPP@ ++CPPFLAGS = @CPPFLAGS@ ++CYGPATH_W = @CYGPATH_W@ ++DEFS = @DEFS@ ++DEPDIR = @DEPDIR@ ++DSYMUTIL = @DSYMUTIL@ ++DUMPBIN = @DUMPBIN@ ++ECHO_C = @ECHO_C@ ++ECHO_N = @ECHO_N@ ++ECHO_T = @ECHO_T@ ++EGREP = @EGREP@ ++EXEEXT = @EXEEXT@ ++FGREP = @FGREP@ ++GREP = @GREP@ ++INSTALL = @INSTALL@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ ++LD = @LD@ ++LDFLAGS = @LDFLAGS@ ++LIBOBJS = @LIBOBJS@ ++LIBS = @LIBS@ ++LIBTOOL = @LIBTOOL@ ++LIPO = @LIPO@ ++LN_S = @LN_S@ ++LTLIBOBJS = @LTLIBOBJS@ ++MAKEINFO = @MAKEINFO@ ++MKDIR_P = @MKDIR_P@ ++NM = @NM@ ++NMEDIT = @NMEDIT@ ++OBJDUMP = @OBJDUMP@ ++OBJEXT = @OBJEXT@ ++OTOOL = @OTOOL@ ++OTOOL64 = @OTOOL64@ ++PACKAGE = @PACKAGE@ ++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_STRING = @PACKAGE_STRING@ ++PACKAGE_TARNAME = @PACKAGE_TARNAME@ ++PACKAGE_URL = @PACKAGE_URL@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++PATH_SEPARATOR = @PATH_SEPARATOR@ ++PKG_CONFIG = @PKG_CONFIG@ ++RANLIB = @RANLIB@ ++SED = @SED@ ++SET_MAKE = @SET_MAKE@ ++SHELL = @SHELL@ ++STRIP = @STRIP@ ++VERSION = @VERSION@ ++abs_builddir = @abs_builddir@ ++abs_srcdir = @abs_srcdir@ ++abs_top_builddir = @abs_top_builddir@ ++abs_top_srcdir = @abs_top_srcdir@ ++ac_ct_CC = @ac_ct_CC@ ++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ++am__include = @am__include@ ++am__leading_dot = @am__leading_dot@ ++am__quote = @am__quote@ ++am__tar = @am__tar@ ++am__untar = @am__untar@ ++bindir = @bindir@ ++build = @build@ ++build_alias = @build_alias@ ++build_cpu = @build_cpu@ ++build_os = @build_os@ ++build_vendor = @build_vendor@ ++builddir = @builddir@ ++datadir = @datadir@ ++datarootdir = @datarootdir@ ++docdir = @docdir@ ++dvidir = @dvidir@ ++exec_prefix = @exec_prefix@ ++host = @host@ ++host_alias = @host_alias@ ++host_cpu = @host_cpu@ ++host_os = @host_os@ ++host_vendor = @host_vendor@ ++htmldir = @htmldir@ ++includedir = @includedir@ ++infodir = @infodir@ ++install_sh = @install_sh@ ++kbuilddir = @kbuilddir@ ++kinclude_CFLAGS = @kinclude_CFLAGS@ ++ksourcedir = @ksourcedir@ ++libdir = @libdir@ ++libexecdir = @libexecdir@ ++libxtables_CFLAGS = @libxtables_CFLAGS@ ++libxtables_LIBS = @libxtables_LIBS@ ++localedir = @localedir@ ++localstatedir = @localstatedir@ ++lt_ECHO = @lt_ECHO@ ++mandir = @mandir@ ++mkdir_p = @mkdir_p@ ++oldincludedir = @oldincludedir@ ++pdfdir = @pdfdir@ ++prefix = @prefix@ ++program_transform_name = @program_transform_name@ ++psdir = @psdir@ ++regular_CFLAGS = @regular_CFLAGS@ ++sbindir = @sbindir@ ++sharedstatedir = @sharedstatedir@ ++srcdir = @srcdir@ ++sysconfdir = @sysconfdir@ ++target_alias = @target_alias@ ++top_build_prefix = @top_build_prefix@ ++top_builddir = @top_builddir@ ++top_srcdir = @top_srcdir@ ++xtlibdir = @xtlibdir@ ++XA_SRCDIR = ${srcdir} ++XA_TOPSRCDIR = ${top_srcdir} ++XA_ABSTOPSRCDIR = ${abs_top_srcdir} ++_mcall = -f ${top_builddir}/Makefile.iptrules ++all: all-am ++ ++.SUFFIXES: ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --foreign extensions/LUA/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++tags: TAGS ++TAGS: ++ ++ctags: CTAGS ++CTAGS: ++ ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile all-local ++installdirs: ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-local mostlyclean-am ++ ++distclean: distclean-am ++ -rm -f Makefile ++distclean-am: clean-am distclean-generic ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: install-exec-local ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-generic mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: ++ ++.MAKE: install-am install-strip ++ ++.PHONY: all all-am all-local check check-am clean clean-generic \ ++ clean-libtool clean-local distclean distclean-generic \ ++ distclean-libtool distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am install-dvi \ ++ install-dvi-am install-exec install-exec-am install-exec-local \ ++ install-html install-html-am install-info install-info-am \ ++ install-man install-pdf install-pdf-am install-ps \ ++ install-ps-am install-strip installcheck installcheck-am \ ++ installdirs maintainer-clean maintainer-clean-generic \ ++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ++ ps ps-am uninstall uninstall-am ++ ++export XA_SRCDIR ++export XA_TOPSRCDIR ++export XA_ABSTOPSRCDIR ++ ++all-local: user-all-local ++ ++install-exec-local: user-install-local ++ ++clean-local: user-clean-local ++ ++user-all-local: ++ ${MAKE} ${_mcall} all; ++ ++# Have no user-install-data-local ATM ++user-install-local: user-install-exec-local ++ ++user-install-exec-local: ++ ${MAKE} ${_mcall} install; ++ ++user-clean-local: ++ ${MAKE} ${_mcall} clean; ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: ++ +--- /dev/null ++++ b/extensions/LUA/Mbuild +@@ -0,0 +1,3 @@ ++# -*- Makefile -*- ++ ++obj-${build_LUA} += libxt_LUA.so +--- /dev/null ++++ b/extensions/LUA/nf_lua.c +@@ -0,0 +1,64 @@ ++#if defined(__KERNEL__) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#endif ++ ++#include "lua.h" ++#include "lobject.h" /*sizeof(udata) */ ++#include "lauxlib.h" ++#include "controller.h" ++ ++#if defined(__KERNEL__) /* reachs until luaopen_nflib */ ++ ++ ++static int32_t nf_get_random(lua_State *L) ++{ ++ uint32_t rand = 0; ++ ++ get_random_bytes(&rand, sizeof(uint32_t )); ++ lua_pushnumber(L, rand); ++ return 1; ++} ++ ++static int32_t nf_get_time(lua_State *L) ++{ ++ lua_pushnumber(L, jiffies_to_msecs(jiffies_64)); ++ return 1; ++} ++ ++static const struct luaL_Reg nf_lua_lib_f [] = { ++ { "get_random", nf_get_random }, ++ { "get_time", nf_get_time }, ++ { NULL, NULL } ++}; ++ ++void luaopen_nflib(lua_State *L) ++{ ++ int32_t top; ++ ++ luaL_register(L, NETFILTER_LIB, nf_lua_lib_f); ++ lua_pop(L, 1); ++ ++ /* registering verdicts inside the _G */ ++ lua_getglobal(L, "_G"); ++ top = lua_gettop(L); ++ ++ lua_pushinteger(L, XT_CONTINUE); ++ lua_setfield(L, top, "XT_CONTINUE"); /* continiue with next rule */ ++ ++ lua_pushinteger(L, NF_DROP); ++ lua_setfield(L, top, "NF_DROP"); /* stop traversal in the current table hook and drop packet */ ++ ++ lua_pushinteger(L, NF_ACCEPT); ++ lua_setfield(L, top, "NF_ACCEPT"); /* stop traversal in the current table hook and accept packet */ ++ ++ lua_pop(L, 1); /* pop _G */ ++} ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/prot_buf_dynamic.c +@@ -0,0 +1,486 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++ ++ ++ ++struct protocol_buf * dyn_prot_buf_array[MAX_NR_OF_DYN_PROT_BUFS] = { NULL }; ++ ++ ++/* LUA_API: the function 'field_dynamic_setter' acts as a wrapper around ++ * a given Lua field setter function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'set' ++ * member of the protocol_field. We call this function passing the actual ++ * segment as byte array and the set value. ++ * ++ * Paramters: ++ * 1. lua_packet_segment (implicit) ++ * 2. some lua value ++ * ++ * Upvalues: ++ * 1. pointer to the protocol buffer ++ * 2. field index ++ * ++ * Returns: ++ * 1. true or false if the 'set' was successful ++ */ ++int32_t field_dynamic_setter(lua_State *L) ++{ ++ size_t nbytes; ++ lua_packet_segment * array; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].set); ++ if (!lua_isfunction(L, -1)) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); ++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); ++ array->length = seg->length; ++ array->start = seg->start + seg->offset; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ lua_pushvalue(L, 2); /* push value to set */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ pr_debug("Error: %s \n", lua_tostring(L, -1)); ++ lua_pop(L, 1); ++ lua_pushboolean(L, 0); ++ } ++ return 1; ++} ++ ++/* LUA_API: the function 'field_dynamic_getter' acts as a wrapper around ++ * a given Lua field getter function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'get' ++ * member of the protocol_field. We call this function passing the actual ++ * segment as byte array. ++ * ++ * Paramters: ++ * 1. lua_packet_segment (implicit) ++ * ++ * Upvalues: ++ * 1. pointer to the protocol buffer ++ * 2. field index ++ * ++ * Returns: ++ * 1. true or false if the 'get' was successful ++ */ ++int32_t field_dynamic_getter(lua_State *L) ++{ ++ size_t nbytes; ++ lua_packet_segment * array; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].get); ++ if (!lua_isfunction(L, -1)) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); ++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); ++ array->length = seg->length; ++ array->start = seg->start + seg->offset; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ if (lua_pcall(L, 1, 1, 0) != 0) { ++ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); ++ lua_pop(L, 1); ++ lua_pushboolean(L, 0); ++ } ++ return 1; ++} ++ ++/* LUA_API: the function 'has_protocol_dynamic' acts as a wrapper around ++ * a given lua has_protocol function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'has_protocol' ++ * member of the protocol_buffer. We call this function passing the actual ++ * segment. ++ * ++ * Paramters: ++ * 1. lua_packet_segment ++ * 2. protocol type ++ * ++ * Returns: ++ * 1. true or false if the payload field contains the given protocol ++ */ ++int32_t has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t type) ++{ ++ lua_packet_segment *seg_new; ++ int32_t res = 0; ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->has_protocol); ++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ seg_new->start = seg->start; ++ seg_new->offset = seg->offset; ++ seg_new->length = seg->length; ++ seg_new->changes = NULL; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ lua_pushinteger(L, type); /* push the protocol type */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); ++ lua_pop(L, 1); ++ return 0; ++ } ++ res = lua_toboolean(L, -1); ++ lua_pop(L, 1); ++ ++ return res; ++} ++ ++/* LUA_API: the function 'get_field_changes_dynamic' acts as a wrapper around ++ * a given lua get_field_changes function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'get_field_changes' ++ * member of the protocol_buffer. We call this function passing the actual ++ * segment. The lua function must return two lua table containing the offset ++ * and length changes (in bits). ++ * ++ * Paramters: ++ * 1. lua_packet_segment ++ * ++ * Returns: ++ * 1. new allocated field_changes struct ++ */ ++struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) ++{ ++ lua_packet_segment *seg_new; ++ struct field_changes * changes; ++ int32_t nr_of_changes, i; ++ ++ lua_getglobal(L, (char *)prot_buf->get_field_changes); ++ ++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ seg_new->start = seg->start; ++ seg_new->offset = seg->offset; ++ seg_new->length = seg->length; ++ seg_new->changes = NULL; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ ++ if (lua_pcall(L, 1, 2, 0) != 0) ++ luaL_error(L, "inside get_field_changes_dynamic. %s\n", lua_tostring(L, -1)); ++ ++ /* the function call must return a table containing length changes */ ++ luaL_checktype(L, -1, LUA_TTABLE); ++ /* the function call must return a table containing offset changes */ ++ luaL_checktype(L, -2, LUA_TTABLE); ++ /* both tables have to be of same size */ ++ if (lua_objlen(L, -1) != lua_objlen(L, -2)) ++ luaL_error(L, "the provided tables are not of equal size"); ++ ++ nr_of_changes = lua_objlen(L, -1); ++ changes = get_allocated_field_changes(L, nr_of_changes); ++ ++ /* loop over the tables */ ++ for (i = 1; i < nr_of_changes; i++) { ++ lua_rawgeti(L, -1, i); /* push length value of field at index i */ ++ changes->field_length_changes[i - 1] = luaL_checkinteger(L, -1); ++ lua_pop(L, 1); /* pop offset value */ ++ ++ lua_rawgeti(L, -2, i); /* push offset value of field at index i */ ++ changes->field_offset_changes[i - 1] = luaL_checkinteger(L, -1); ++ lua_pop(L, 1); /* pop length value */ ++ } ++ ++ /* pop both tables */ ++ lua_pop(L, 2); ++ ++ return changes; ++} ++ ++/* C_INT: 'get_free_protocol_index' is only used internally. This function ++ * gets a free slot inside the array holding all the protocol buffers. ++ * There are several ways to get to this information. In this case I take ++ * the way over the reflected array SUPPORTED_PROTOCOL_TABLE inside the ++ * Lua state. Since this function is called at laodtime, we do not have ++ * to care about performance. ++ */ ++static int32_t get_free_protocol_index(lua_State *L) ++{ ++ int32_t protocol_index; ++ ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ protocol_index = lua_objlen(L, -1) + 1; ++ lua_pop(L, 1); ++ return protocol_index; ++} ++ ++/* C_API: 'free_dynamic_prot_buf' frees the allocated memory of a given ++ * dynamic protocol buffer. this function is normally called inside a ++ * cleanup routine. Be aware, before running this function you must be ++ * sure that no references to the dynamic protocol buffers were available. ++ * It's recomended to close the Lua state before calling the function. */ ++void free_dynamic_prot_buf(struct protocol_buf * prot_buf) ++{ ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ for (; field->name != NULL; field++) { ++ if (field->get) kfree(field->get); ++ if (field->set) kfree(field->set); ++ if (field->name) kfree((char *)field->name); ++ } ++ ++ if (prot_buf->payload_field) kfree(prot_buf->payload_field); ++ if (prot_buf->has_protocol) kfree(prot_buf->has_protocol); ++ ++ if (prot_buf->get_field_changes) kfree(prot_buf->get_field_changes); ++ kfree((char *)prot_buf->name); ++ kfree(prot_buf); ++ return; ++} ++ ++void cleanup_dynamic_prot_bufs(void) ++{ ++ int32_t i; ++ ++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { ++ if (dyn_prot_buf_array[i]) { ++ free_dynamic_prot_buf(dyn_prot_buf_array[i]); ++ dyn_prot_buf_array[i] = NULL; ++ } ++ } ++ return; ++} ++ ++ ++/* C_INT: 'free_protocol_fields' is used internally as a helper function for ++ * 'register_dynamic_protbuf'. It is used when durin registration an error ++ * occurs and the afore allocated fields needed to be freed. */ ++static inline void free_protocol_fields(struct protocol_field * prot_fields, int32_t i) ++{ ++ struct protocol_field * f; ++ ++ while (i >= 0) { ++ f = &prot_fields[i]; ++ if (f->name) kfree((void *)f->name); ++ if (f->get) kfree((void *)f->get); ++ if (f->set) kfree((void *)f->set); ++ kfree((void *)f); ++ i--; ++ } ++} ++ ++/* LUA_API: 'register_dynamic_protbuf' is called from within the Lua script. ++ * it takes a Lua table representing the dynamic protocol buffer as parameter. ++ * e.g.: ++ * eth_prot_buf = { ++ * name = "packet_eth_dyn", ++ * payload_field = "data", ++ * protocol_fields = { ++ * {"dmac", 0, 48, nil, nil }, ++ * {"smac", 48, 48, nil, nil }, ++ * {"type", 96, 16, nil, nil }, ++ * {"data", 112, 0, nil, nil }, ++ * }, ++ * has_protocol = "eth_dyn_has_protocol", ++ * get_field_changes = "eth_dyn_get_field_changes" ++ * } ++ * register_dynamic_protbuf(eth_prot_buf) ++ * ++ * the table gets parsed and a new protocol_buf struct is allocated and ++ * initialized using 'register_protbuf', which is also used for the static ++ * protocol buffers. This enables an identical behavior like the static ++ * protocol buffers. The dynamic protocol buffers are not garbage collected, ++ * use 'free_dynamic_protbuf' to free them after closing the Lua state. ++ */ ++static int32_t register_dynamic_protbuf(lua_State *L) ++{ ++ struct protocol_buf *prot_buf; ++ struct protocol_field *field, sentinel = PROT_FIELD_SENTINEL; ++ int32_t nr_of_fields, i; ++ ++ prot_buf = (struct protocol_buf *)kmalloc(sizeof(struct protocol_buf), GFP_KERNEL); ++ prot_buf->is_dynamic = 1; ++ ++ /* check if parameter is a table */ ++ luaL_checktype(L, 1, LUA_TTABLE); ++ ++ /* initialize prot_buf.name */ ++ lua_getfield(L, 1, "name"); ++ prot_buf->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->name, luaL_checkstring(L, -1)); ++ lua_pop(L, 1); /* pop res from lua_getfield */ ++ ++ /* check if protocol buffer is already registered */ ++ lua_getglobal(L, prot_buf->name); ++ if (!lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop res from lua_getglobal */ ++ pr_debug("protocol_buf '%s' already registered.\n", prot_buf->name); ++ goto free_prot_buf; ++ } ++ lua_pop(L, 1); /* pop res from lua_getglobal */ ++ ++ /* initialize payload field */ ++ lua_getfield(L, 1, "payload_field"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->payload_field = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy(prot_buf->payload_field, lua_tostring(L, -1)); ++ }else ++ prot_buf->payload_field = NULL; ++ lua_pop(L, 1); /* pop res from lua_getfield */ ++ ++ /* initialize protocol_fields field*/ ++ lua_getfield(L, 1, "protocol_fields"); ++ if (!lua_istable(L, -1)) { ++ pr_debug("invalid protocol_fields table.\n"); ++ goto err2; ++ ++ } ++ ++ nr_of_fields = lua_objlen(L, -1); ++ prot_buf->protocol_fields = (struct protocol_field *)kmalloc((nr_of_fields + 1) * sizeof(struct protocol_field), GFP_KERNEL); ++ ++ for (i = 1; i <= nr_of_fields; i++) { ++ field = &prot_buf->protocol_fields[i - 1]; ++ /* initialize protocol field */ ++ lua_rawgeti(L, -1, i); /* push field-table */ ++ if (!lua_istable(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field at %i.\n", i); ++ goto err; ++ } ++ ++ /* initialize protocol field name */ ++ lua_rawgeti(L, -1, 1); ++ if (!lua_isstring(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field name at %i.\n", i); ++ goto err; ++ } ++ ++ field->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char*)field->name, lua_tostring(L, -1)); ++ lua_pop(L, 1); /* pop field name */ ++ ++ /* initialize protocol field offset */ ++ lua_rawgeti(L, -1, 2); ++ if (!lua_isnumber(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field offset at %i.\n", i); ++ goto err; ++ } ++ field->offset = lua_tointeger(L, -1); ++ lua_pop(L, 1); /* pop field offset */ ++ ++ /* initialize protocol field length */ ++ lua_rawgeti(L, -1, 3); ++ if (!lua_isnumber(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field length at %i.\n", i); ++ goto err; ++ } ++ field->length = lua_tointeger(L, -1); ++ lua_pop(L, 1); /* pop field length */ ++ ++ /* initialize protocol field getter */ ++ lua_rawgeti(L, -1, 4); ++ if (lua_isstring(L, -1)) { ++ field->get = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)field->get, lua_tostring(L, -1)); /* the get-wrapper knows about the piggybacked string */ ++ }else ++ field->get = NULL; ++ lua_pop(L, 1); /* pop field getter */ ++ ++ /* initialize protocol field setter */ ++ lua_rawgeti(L, -1, 5); ++ if (lua_isstring(L, -1)) { ++ field->set = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)field->set, lua_tostring(L, -1)); /* the set-wrapper knows about the piggybacked string */ ++ }else ++ field->set = NULL; ++ lua_pop(L, 1); /* pop field setter */ ++ ++ /* field initialization completed */ ++ lua_pop(L, 1); /* pop field-table */ ++ } ++ ++ /* put sentinel at the end of protocol_fields */ ++ memcpy(&prot_buf->protocol_fields[nr_of_fields], &sentinel, sizeof(sentinel)); ++ lua_pop(L, 1); /* pop protocol-fields-table */ ++ ++ /* initialize has_protocol field */ ++ lua_getfield(L, 1, "has_protocol"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->has_protocol = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->has_protocol, lua_tostring(L, -1)); /* the has_protocol-wrapper knows about the piggybacked string */ ++ }else ++ prot_buf->has_protocol = NULL; ++ lua_pop(L, 1); /* pop has_protocol */ ++ ++ /* initialize get_field_changes field */ ++ lua_getfield(L, 1, "get_field_changes"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->get_field_changes = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->get_field_changes, lua_tostring(L, -1)); /* the get_field_changes-wrapper knows about the piggybacked string */ ++ }else ++ prot_buf->get_field_changes = NULL; ++ lua_pop(L, 1); /* pop get_field_changes */ ++ ++ /* Storing the pointer to the DYNAMIC protbuf within dyn_prot_buf_array, in order to free it at cleanup */ ++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { ++ if (!dyn_prot_buf_array[i]) { ++ dyn_prot_buf_array[i] = prot_buf; ++ break; ++ }else ++ goto err; ++ } ++ ++ /* call the "common" register_protbuf */ ++ register_protbuf(L, prot_buf, get_free_protocol_index(L)); /* register prot_buf as it is done with the static ones */ ++ ++ return 0; ++ ++err: ++ kfree(prot_buf->protocol_fields); ++err2: ++ if (prot_buf->payload_field) kfree(prot_buf->payload_field); ++free_prot_buf: ++ kfree((void *)prot_buf->name); ++ kfree(prot_buf); ++ ++ luaL_error(L, "one or more error happend while registering a dynamic protocol buffer, please consult the debug log"); ++ ++ return 0; ++ ++} ++ ++void luaopen_protbuf_dynamic(lua_State *L) ++{ ++ lua_getglobal(L, "_G"); ++ lua_pushcclosure(L, register_dynamic_protbuf, 0); ++ lua_setfield(L, -2, "register_dynamic_protbuf"); ++ lua_pop(L, 1); /* pop _G */ ++ return; ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_ethernet.c +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++ ++ ++static int32_t eth_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ uint8_t *embedded_protocol = seg->start + seg->offset + 12 /*bytes*/; ++ unsigned short res = (unsigned short)((embedded_protocol[1] << CHAR_BIT) | (embedded_protocol[0] << CHAR_BIT)); ++ ++ switch (res) { ++ case 0x0800: /* 1: Internet Protocol (IP) */ ++ if (protocol_type == PACKET_IP) return 1; ++ break; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static const struct protocol_field eth_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "dmac", 0, 48, NULL, NULL }, ++ { "smac", 48, 48, NULL, NULL }, ++ { "type", 96, 16, NULL, NULL }, ++ { "data", 112, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf eth_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_ETH, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)ð_protocol_fields, ++ .has_protocol = ð_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++ ++void luaopen_protbuf_eth(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)ð_protocol_buf, PACKET_ETH); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_helpers.c +@@ -0,0 +1,216 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++#include ++#include /* kmalloc */ ++#endif ++ ++#include "controller.h" ++ ++int32_t get_header_size(struct protocol_buf * prot_buf) ++{ ++ int32_t bit_counter = 0; ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ for (; field->name; field++) ++ bit_counter += field->length; ++ ++ return bit_counter >> 3; ++} ++ ++ ++int32_t set_32_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint32_t *)(seg->start + seg->offset) = (uint32_t )htonl(luaL_checkinteger(L, 2)); ++ return 0; ++} ++int32_t get_32_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, ntohl(*((uint32_t *)(seg->start + seg->offset)))); ++ return 1; ++} ++ ++int32_t set_16_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint16_t *)(seg->start + seg->offset) = (uint16_t)htons(luaL_checkinteger(L, 2)); ++ return 0; ++} ++int32_t get_16_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, ntohs(*((uint16_t *)(seg->start + seg->offset)))); ++ return 1; ++} ++ ++int32_t set_lower_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; ++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); ++ ++ *pos &= 0x0F; /* reset lower 4 bits*/ ++ *pos |= b; ++ ++ return 0; ++} ++ ++int32_t get_lower_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) >> 4); ++ return 1; ++} ++ ++int32_t set_upper_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; ++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); ++ ++ *pos &= 0xF0; /* reset upper 4 bits*/ ++ *pos |= (b >> 4); ++ ++ return 0; ++} ++ ++int32_t get_upper_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) & 0x0F); ++ return 1; ++} ++ ++ ++int32_t set_8_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint8_t *)(seg->start + seg->offset) = (uint8_t)luaL_checkinteger(L, 2); ++ return 0; ++} ++ ++int32_t get_8_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, *(uint8_t *)(seg->start + seg->offset)); ++ return 1; ++} ++ ++int32_t set_1_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ unsigned long l = 0; ++ ++ memcpy(&l, (seg->start + seg->offset), seg->length); ++ l |= (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); ++ memcpy((seg->start + seg->offset), &l, seg->length); ++ ++ return 0; ++} ++ ++int32_t get_1_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ unsigned long l = 0; ++ uint32_t bit = 0; ++ ++ memcpy(&l, (seg->start + seg->offset), seg->length); ++ bit = l & (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); ++ ++ lua_pushboolean(L, bit); ++ return 1; ++} ++ ++int32_t get_string_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ /* Warning we cast from uchar to char */ ++ lua_pushlstring(L, (char *)seg->start + seg->offset, seg->length); ++ return 1; ++} ++ ++int32_t set_data_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ lua_packet_segment * data = checkbytearray(L, 2); ++ ++ pr_debug("seg->length %u, data->length %u\n", seg->length, data->length); ++ ++ if (seg->length >= data->length) ++ memcpy((seg->start + seg->offset), data->start, data->length); ++ else ++ luaL_error(L, "provided byte array too big for given packet segment"); ++ return 0; ++} ++ ++struct field_changes * get_allocated_field_changes(lua_State *L, int32_t nr_of_fields) ++{ ++ struct field_changes * changes; ++ ++ changes = kmalloc(sizeof(struct field_changes), GFP_ATOMIC); ++ ++ if (!changes) ++ goto failure; ++ ++ changes->field_length_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); ++ if (!changes->field_length_changes) ++ goto free1; ++ ++ changes->field_offset_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); ++ if (!changes->field_offset_changes) ++ goto free2; ++ ++ memset(changes->field_length_changes, 0, nr_of_fields * sizeof(int)); ++ memset(changes->field_offset_changes, 0, nr_of_fields * sizeof(int)); ++ ++ changes->ref_count = 1; ++ ++ return changes; ++ ++free2: kfree(changes->field_length_changes); ++free1: kfree(changes); ++failure: ++ if (!changes) luaL_error(L, "couldnt allocate memory inside 'get_allocated_field_changes'"); ++ return NULL; /* only to omit warnings */ ++} +\ No newline at end of file +--- /dev/null ++++ b/extensions/LUA/prot_buf_icmp.c +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++ ++static int32_t icmp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 0; ++} ++ ++static const struct protocol_field icmp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "type", 0, 8, NULL, NULL }, ++ { "code", 8, 8, NULL, NULL }, ++ { "checksum", 16, 16, NULL, NULL }, ++ { "id", 32, 16, NULL, NULL }, ++ { "sequence", 48, 16, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf icmp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_ICMP, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&icmp_protocol_fields, ++ .has_protocol = &icmp_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_icmp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&icmp_protocol_buf, PACKET_ICMP); ++} ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_ip.c +@@ -0,0 +1,209 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++ #include ++#endif ++ ++#include "controller.h" ++ ++ ++#define IP_FMT "%u.%u.%u.%u" ++#define IP_ACC(buf) buf[0], buf[1], buf[2], buf[3] ++ ++ ++static int32_t ip_version_set(lua_State *L) ++{ ++ uint8_t version_checked; ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *version_seg = seg->start + seg->offset; ++ int32_t version = luaL_checkinteger(L, 2); ++ ++ luaL_argcheck(L, version >= 0 && version <= 15, 1, "version number invalid"); ++ ++ version_checked = (uint8_t)version; ++ ++ version_seg[0] &= (uint8_t)0x0F; /* reset version bits */ ++ version_seg[0] |= version_checked << 4; ++ ++ return 0; ++} ++static int32_t ip_version_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *version_seg = seg->start + seg->offset; ++ uint8_t v = version_seg[0] & 0xF0; ++ ++ v >>= 4; ++ ++ lua_pushinteger(L, v); ++ return 1; ++} ++ ++static int32_t ip_ihl_set(lua_State *L) ++{ ++ uint8_t ihl_checked; ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *ihl_seg = seg->start + seg->offset; ++ int32_t ihl = luaL_checkinteger(L, 2); ++ ++ luaL_argcheck(L, ihl >= 5 && ihl <= 15, 1, "ip header length invalid"); // RFC 791 5x32 = 160 bits ++ ++ ihl_checked = (uint8_t)ihl; ++ ++ ihl_seg[0] &= (uint8_t)0xF0; /* reset ihl bits */ ++ ihl_seg[0] |= ihl_checked; ++ ++ return 0; ++} ++static int32_t ip_ihl_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *ihl_seg = seg->start + seg->offset; ++ uint8_t v = ihl_seg[0] & 0x0F; ++ ++ lua_pushinteger(L, v); ++ return 1; ++} ++ ++static int32_t ip_addr_set(lua_State *L) ++{ ++ int32_t field_id = lua_tointeger(L, lua_upvalueindex(2)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *addr_seg = seg->start + seg->offset; ++ uint32_t old_addr; ++ char *ip = (char *)luaL_checkstring(L, 2); ++ uint32_t a, b, c, d; ++ struct sk_buff * skb = (struct sk_buff *)lua_touserdata(L, 3); ++ ++ /* for tcp / udp checksumming*/ ++ uint32_t prot_offset; ++ uint8_t *check, *protocol_seg; ++ ++ /* end */ ++ ++ sscanf(ip, IP_FMT, &a, &b, &c, &d); ++ ++ luaL_argcheck(L, a < 256 && b < 256 && c < 256 && d < 256, 1, "invalid ip addr"); ++ ++ old_addr = *((uint32_t *)addr_seg); ++ addr_seg[0] = (uint8_t)a; ++ addr_seg[1] = (uint8_t)b; ++ addr_seg[2] = (uint8_t)c; ++ addr_seg[3] = (uint8_t)d; ++ ++#if defined(__KERNEL__) ++ if (old_addr != *(uint32_t *)addr_seg) { ++ int32_t offset = (field_id == 10) ? -2 : -6; /* offset from saddr or daddr */ ++ ++ csum_replace4((uint16_t *)(addr_seg + offset), old_addr, *(uint32_t *)addr_seg); ++ ++ prot_offset = (field_id == 10) ? -3 : -7; /* offset from saddr or daddr */ ++ protocol_seg = seg->start + seg->offset + prot_offset; ++ ++ if (skb && (protocol_seg[0] == 0x06 || protocol_seg[0] == 0x11)) { /* is payload TCP or UDP ? */ ++ ++ check = seg->start + seg->offset; /* tmp res */ ++ check += (field_id == 10) ? 8 : 16; /* the start of the payload, depending saddr or daddr */ ++ check += (protocol_seg[0] == 0x06) ? 16 : 6; /* the start of the checksum, depending on TCP or UDP */ ++ ++ inet_proto_csum_replace4((__sum16 *)check, skb, old_addr, *(uint32_t *)addr_seg, 1); ++ ++ lua_pop(L, 1); ++ } ++ } ++#endif ++ return 0; ++} ++ ++ ++ ++ ++ ++static int32_t ip_addr_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *addr_seg = seg->start + seg->offset; ++ ++ char buf[16]; /*max: 255.255.255.255\0 --> 16 chars */ ++ ++ sprintf(buf, IP_FMT, IP_ACC(addr_seg)); ++ lua_pushstring(L, buf); ++ return 1; ++} ++ ++static int32_t ip_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ uint8_t * embedded_protocol = seg->start + seg->offset + 9 /*bytes*/; ++ ++ switch (embedded_protocol[0]) { ++ case 0x01: /* 1: Internet Control Message Protocol (ICMP) */ ++ if (protocol_type == PACKET_ICMP) return 1; ++ break; ++ case 0x02: /* 2: Internet Group Management Protocol (IGMP) */ ++ break; ++ case 0x06: /* 6: Transmission Control Protocol (TCP) */ ++ if (protocol_type == PACKET_TCP) return 1; ++ break; ++ case 0x11: /* 17: User Datagram Protocol (UDP) */ ++ if (protocol_type == PACKET_UDP) return 1; ++ break; ++ case 0x59: /* 89: Open Shortest Path First (OSPF) */ ++ break; ++ case 0x84: /* 132: Stream Control Transmission Protocol (SCTP) */ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const struct protocol_field ip_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "version", 0, 4, ip_version_get, ip_version_set }, ++ { "ihl", 4, 4, ip_ihl_get, ip_ihl_set }, ++ { "tos", 8, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "tot_len", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "id", 32, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "flags", 48, 3, get_1_bit_generic, set_1_bit_generic }, ++ { "frag_off", 51, 13, NULL, NULL }, ++ { "ttl", 64, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "protocol", 72, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "check", 80, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "saddr", 96, 32, ip_addr_get, ip_addr_set }, ++ { "daddr", 128, 32, ip_addr_get, ip_addr_set }, ++ { "data", 160, 0, NULL, set_data_generic }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf ip_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_IP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&ip_protocol_fields, ++ .has_protocol = &ip_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_ip(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&ip_protocol_buf, PACKET_IP); ++} ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_raw.c +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "controller.h" ++static int32_t raw_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static const struct protocol_field raw_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "data", 0, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf raw_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_RAW, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&raw_protocol_fields, ++ .has_protocol = &raw_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_raw(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&raw_protocol_buf, PACKET_RAW); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_tcp.c +@@ -0,0 +1,188 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++ #include ++#endif ++#include "controller.h" ++ ++ ++static int32_t tcp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static int32_t tcp_set_checksum(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++#if defined(__KERNEL__) ++ uint8_t * check_seg = seg->start + seg->offset; ++ uint8_t * tcp_hdr = check_seg - 16; ++ uint8_t * saddr = tcp_hdr - 8; ++ uint8_t * daddr = saddr + 4; ++ uint32_t len = 20 + (seg->changes->field_length_changes[11] / 8) + (seg->changes->field_length_changes[10] / 8); ++ unsigned short checksum = tcp_v4_check(len, *(uint32_t *)saddr, *(uint32_t *)daddr, ++ csum_partial(tcp_hdr, len, 0)); ++ ++ memcpy(check_seg, &checksum, sizeof(unsigned short)); ++#endif ++ return 0; ++} ++ ++ ++static const struct protocol_field tcp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "seq", 32, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "ack", 64, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "data_off", 96, 4, get_lower_4_bit_generic, set_lower_4_bit_generic }, ++ { "reserved", 100, 4, get_upper_4_bit_generic, set_upper_4_bit_generic }, ++ { "flags", 104, 8, get_1_bit_generic, set_1_bit_generic }, ++ { "window_size", 112, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "check", 128, 16, get_16_bit_generic, tcp_set_checksum }, ++ { "urgent", 144, 16, NULL, NULL }, ++ { "options", 160, 0, NULL, set_data_generic }, ++ { "data", 160, 0, NULL, set_data_generic }, /* begin of data depends on options */ ++ PROT_FIELD_SENTINEL, ++}; ++ ++ ++static const struct protocol_field tcp_options_and_data[] = { ++ /* field name offset length getter setter */ ++ { "MSS", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "WS", 0, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "SACK", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "TSVAL", 0, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "TSER", 0, 32, get_32_bit_generic, set_32_bit_generic }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++ ++static struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg); ++ ++static const struct protocol_buf tcp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TCP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&tcp_protocol_fields, ++ .has_protocol = &tcp_has_protocol, ++ .get_field_changes = &tcp_get_field_changes, ++}; ++ ++ ++static struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg); ++ ++static const struct protocol_buf tcp_options_and_data_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TCP_OPT, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&tcp_options_and_data, ++ .has_protocol = NULL, ++ .get_field_changes = &tcp_options_get_field_changes, ++}; ++ ++struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'data_off'-field, the length of ++ * the 'options' field has to be changed, as well as the length and offset ++ * of the 'data' field */ ++ uint8_t *tcp_hdr = seg->start + seg->offset; ++ ++ /* get the pointer to the 'data_off' field */ ++ uint8_t * data_off_field = tcp_hdr + 12; /* 12 bytes offset */ ++ /* extract the stored header length in bits */ ++ uint32_t tcp_hdr_len = ((*(uint8_t *)data_off_field) >> 4) * 32; ++ ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 12); ++ ++ /* depending on the tcp header length, change the length of the options*/ ++ changes->field_length_changes[10] = tcp_hdr_len - 160; ++ /* depending on the options length, change the offset of the data */ ++ changes->field_offset_changes[11] = changes->field_length_changes[10]; ++ changes->field_length_changes[11] = (seg->length * 8) - tcp_hdr_len; ++ ++ return changes; ++ ++} ++ ++struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'data_off'-field, the length of ++ * the 'options' field has to be changed, as well as the length and offset ++ * of the 'data' field */ ++ uint8_t *tcp_opt_hdr = seg->start + seg->offset; ++ ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 5); ++ ++ int32_t MSS = 0, WS = 0, SACK = 0, TS = 0, i; ++ ++ uint8_t b1, b2; ++ ++ for (i = 0; i < seg->length; i++) { ++ b1 = tcp_opt_hdr[i]; ++ b2 = tcp_opt_hdr[i + 1]; ++ ++ if (b1 == 0x00) ++ break; ++ ++ /* test for MSS */ ++ if (!MSS && (b1 == 0x02 && b2 == 0x04)) { ++ changes->field_offset_changes[0] = (i + 2) * CHAR_BIT; ++ MSS = 1; ++ } ++ ++ /* test for WS --- yet buggy somehow */ ++ if (!WS && (b1 == 0x03 && b2 == 0x03)) { ++ changes->field_offset_changes[1] = (i + 2) * CHAR_BIT; ++ WS = 1; ++ } ++ ++ /* test for SACK*/ ++ if (!SACK && (b1 == 0x04 && b2 == 0x02)) { ++ changes->field_offset_changes[2] = i * CHAR_BIT; /* has no value */ ++ SACK = 1; ++ } ++ ++ /* test for TS */ ++ if (!TS && (b1 == 0x08 && b2 == 0x0A)) { ++ changes->field_offset_changes[3] = (i + 2) * CHAR_BIT; ++ changes->field_offset_changes[4] = (i + 2 + 4) * CHAR_BIT; ++ TS = 1; ++ } ++ } ++ ++ return changes; ++ ++} ++ ++void luaopen_protbuf_tcp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tcp_protocol_buf, PACKET_TCP); ++} ++void luaopen_protbuf_tcp_options(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tcp_options_and_data_buf, PACKET_TCP_OPTIONS); ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_tftp.c +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++#include "controller.h" ++ ++static const struct protocol_field tftp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "opcode", 0, 16, get_16_bit_generic, NULL}, ++ { "filename", 0, 0, get_string_generic, NULL}, ++ { "mode", 0, 0, get_string_generic, NULL}, ++ { "block_nr", 0, 16, get_16_bit_generic, NULL}, ++ { "data", 0, 0, NULL, NULL}, ++ PROT_FIELD_SENTINEL, ++}; ++ ++struct field_changes * tftp_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'opcode'-field we have to change ++ * offsets and lengths */ ++ uint8_t *tftp_hdr = seg->start + seg->offset; ++ short opcode = ntohs(*((uint16_t *)tftp_hdr)); ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 5); ++ switch (opcode) { ++ case 1: /* Read Request (RRQ) */ ++ /* setting offset and length of field 'filename' */ ++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; ++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; ++ /* setting offset and length of field 'mode' */ ++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; ++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); ++ break; ++ case 2: /* Write Request (WRQ) */ ++ /* setting offset and length of field 'filename' */ ++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; ++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; ++ /* setting offset and length of field 'mode' */ ++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; ++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); ++ break; ++ case 3: /* Data (DATA) */ ++ /* setting offset of field 'block_nr' */ ++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; ++ /* setting offset of field 'data' */ ++ changes->field_offset_changes[4] = changes->field_offset_changes[3] + (sizeof(unsigned short) << 3); ++ break; ++ case 4: /* Acknowledgment (ACK) */ ++ /* setting offset of field 'block_nr' */ ++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; ++ break; ++ case 5: /* Error (ERROR) */ ++ /* we don't care ... yet */ ++ break; ++ default: ++ break; ++ } ++ ++ return changes; ++} ++ ++static const struct protocol_buf tftp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TFTP, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&tftp_protocol_fields, ++ .has_protocol = NULL, /* we don't need it, since we don't provide a payload field */ ++ .get_field_changes = tftp_get_field_changes, ++}; ++ ++void luaopen_protbuf_tftp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tftp_protocol_buf, PACKET_TFTP); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_udp.c +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#if defined(__KERNEL__) ++ #include ++#endif ++ ++#include "controller.h" ++ ++ ++static int32_t udp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static const struct protocol_field udp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "length", 32, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "check", 48, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "data", 64, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf udp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_UDP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&udp_protocol_fields, ++ .has_protocol = &udp_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_udp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&udp_protocol_buf, PACKET_UDP); ++} +--- /dev/null ++++ b/extensions/LUA/xt_LUA.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#ifndef XT_LUA_H_ ++#define XT_LUA_H_ ++ ++#define MAX_FILENAME_SIZE 256 ++#define MAX_FUNCTION_SIZE 256 ++#define MAX_SCRIPT_SIZE 32768 ++#define LUA_STATE_ARRAY_SIZE 128 ++ ++/* the targetsize is stored in a u16, so max size of the xt_lua_tginfo cannot exceed 64K*/ ++struct xt_lua_tginfo { ++ char buf[MAX_SCRIPT_SIZE]; ++ char filename[MAX_FILENAME_SIZE]; ++ char function[MAX_FUNCTION_SIZE]; ++ __u64 script_size; ++ __u32 state_id; ++}; ++ ++#endif /* XT_LUA_H_ */ +--- /dev/null ++++ b/extensions/LUA/xt_LUA_target.c +@@ -0,0 +1,286 @@ ++/* ++ * Copyright (C) 2010 University of Basel ++ * by Andre Graf ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "xt_LUA.h" ++ ++#include "controller.h" ++ ++/*::* ++ * lua_envs ++ * ---------- ++ * This array holds a defined number of `lua_envs`_ structures. ++ * The used array index is also used as the Lua state identifier. ++ * The size of the array is defined in `LUA_STATE_ARRAY_SIZE`_. ++ */ ++struct lua_env * lua_envs[LUA_STATE_ARRAY_SIZE]; ++ ++/*::* ++ * lua_state_refs ++ * -------------- ++ * This array holds the reference counts of the several `lua_nf_state`_s ++ * which are stored inside the array `lua_states`_. ++ */ ++uint32_t lua_state_refs[LUA_STATE_ARRAY_SIZE] = { 0 }; ++ ++/*::* ++ * lua_tg ++ * ------ ++ * This function is called whenever a packet matches all matching conditions ++ * inside a rule. It is the target. It extracts the state identifier comming ++ * inside the *xt_target_param* structure and uses it to access the proper ++ * Lua state inside the `lua_states`_ array. ++ * ++ * It then constructs a new Lua userdata of type *lua_packet_segment* and ++ * initializes it with the lowest network header available. This userdata ++ * is annotated with the Lua metatable `LUA_PACKET_SEG_RAW`_ which converts ++ * the userdata to a raw lua packet having all raw functions available. ++ * This raw packet is the single parameter to the Lua function *process_packet* ++ * which must be defined inside the Lua script provided by the user. So far ++ * hardcoded, may be later configured by Lua - subject to change. ++ * ++ * The process_packet function must return an integer value, the verdict. For ++ * convenience reasons xt_LUA exports the verdicts NF_ACCEPT, NF_DROP and ++ * XT_CONTINUE inside the *register_lua_packet_lib* function. ++ */ ++ ++spinlock_t lock = SPIN_LOCK_UNLOCKED; ++ ++static uint32_t ++lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) ++{ ++ uint32_t verdict; ++ lua_packet_segment *p; ++ const struct xt_lua_tginfo *info = par->targinfo; ++ lua_State * L; ++ ++ /* START critical section on SMP, PacketScript is on the sequential trail at the moment TODO*/ ++ spin_lock_irq(&lock); ++ ++ L = lua_envs[info->state_id]->L; ++ ++ if (!skb_make_writable(pskb, pskb->len)) ++ return NF_DROP; ++ ++ /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ ++ lua_getglobal(L, info->function); ++ ++ /* push the lua_packet_segment as a parameter */ ++ p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ if (pskb->mac_header) ++ p->start = pskb->mac_header; ++ else if (pskb->network_header) ++ p->start = pskb->network_header; ++ else if (pskb->transport_header) ++ p->start = pskb->transport_header; ++ p->offset = 0; ++ p->length = (unsigned long)pskb->tail - (unsigned long)p->start; ++ p->changes = NULL; ++ ++ /* marking userdata 'lua_packet_seg' with the corresponding metatable */ ++ luaL_getmetatable(L, LUA_PACKET_SEG_RAW); ++ lua_setmetatable(L, -2); ++ ++ /* push a reference to the skb as a parameter, needed at the moment for calculating TCP checksum, but I am not happy with it*/ ++ lua_pushlightuserdata(L, (void *)skb_get(pskb)); ++ ++ /* do the function call (2 argument, 1 result) */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ printk(KERN_ERR "LUA [%d]: pcall '%s' failed: %s\n", info->state_id, info->function, lua_tostring(L, -1)); ++ lua_pop(L, 1); ++ return NF_DROP; ++ } ++ ++ if (!lua_isnumber(L, -1)) { ++ printk(KERN_ERR "LUA [%d]: function '%s' must return a verdict\n", info->state_id, info->function); ++ lua_pop(L, 1); ++ return NF_DROP; ++ } ++ ++ verdict = lua_tonumber(L, -1); ++ lua_pop(L, 1); ++ ++ kfree_skb(pskb); ++ ++ /* END critical section on SMP */ ++ spin_unlock_irq(&lock); ++ ++ ++ return verdict; ++ ++} ++/* Helper for checkentry */ ++static bool load_script_into_state(uint32_t state_id, unsigned long script_size, char *script_buf) ++{ ++ char *buf = kmalloc(script_size, GFP_KERNEL); ++ int32_t ret; ++ struct lua_env * env = kmalloc(sizeof(struct lua_env), GFP_KERNEL); ++ ++ if (!script_size) { ++ pr_debug("LUA [%d]: script_size %lu < 0\n", state_id, script_size); ++ return false; ++ } ++ ++ env->L = lua_open(); ++ luaopen_base(env->L); ++ luaopen_controller(env->L); ++ ++ lua_getglobal(env->L, "_G"); ++ lua_pushinteger(env->L, state_id); ++ lua_setfield(env->L, -2, "STATE_ID"); ++ lua_pop(env->L, 1); /* pop _G */ ++ ++ strncpy(buf, script_buf, script_size); ++ ret = luaL_loadbuffer(env->L, buf, script_size, "PacketScript, loadbuffer") || ++ lua_pcall(env->L, 0, 1, 0); ++ ++ if (ret != 0) { ++ printk(KERN_ERR "LUA [%d]: failure loading script, error %s \n", state_id, lua_tostring(env->L, -1)); ++ lua_pop(env->L, 1); ++ kfree(buf); ++ kfree(env); ++ return false; ++ } ++ ++ lua_envs[state_id] = env; ++ ++ kfree(buf); ++ ++ return true; ++} ++/*::* ++ * lua_tg_checkentry ++ * ----------------- ++ * This function is used as a kernel-side sanity check of the data comming ++ * from the iptables userspace program. Since this is the function which is ++ * called everytime a new rule (with -j xt_LUA) is injected, this function ++ * is used to do the bookkeeping work, such as counting the reference of ++ * several Lua states and the initialization of new states if needed. As an ++ * extra initialization step it loads the provided Lua script into the Lua ++ * state. ++ * ++ * Lua state initialization ++ * ~~~~~~~~~~~~~~~~~~~~~~~~ ++ * 1. If a new rule is inserted and there is no existing state for the given ++ * state identifier (default state identifier is 0) a new Lua state is ++ * initialized using *lua_open*. ++ * 2. The Lua base library is registered inside the newly initialized state. ++ * Have a look at *lua/lbaselib.c* to see what functions of the Lua base ++ * library are available inside Lua. ++ * 3. The Lua packet library is registered inside the Lua state using the ++ * function *register_lua_packet_lib*. So far this function only registers ++ * the Netfilter verdicts NF_ACCEPT, NF_DROP and XT_CONTINUE inside the ++ * global environment of the given Lua state. ++ * 4. All the protocol Buffers, and the functions for accessing the bytes are ++ * registered using *register_protocols*. ++ * ++ * Lua state reference counting ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * Bookkeeping of the Lua states inside the *lua_state_refs* array. The ++ * state identifier is mapped to the array index, which holds an integer ++ * counting the several initialized states. ++ * ++ * Loading the Lua script ++ * ~~~~~~~~~~~~~~~~~~~~~~ ++ * Copying the buffer which was initialized by the userspace program to a ++ * buffer with the proper size. The script is then loaded by the function ++ * xt_LUA_loadcode, which wrapps the *luaL_loadbuffer* function and does ++ * some workqueue initialization. So far this is done each time this function ++ * is called, subject to change. ++ */ ++static bool ++lua_tg_checkentry(const struct xt_tgchk_param *par) ++{ ++ const struct xt_lua_tginfo *info = par->targinfo; ++ ++ if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { ++ lua_state_refs[info->state_id]++; ++ return true; ++ } ++ return false; ++} ++ ++/*::* ++ * lua_tg_destroy ++ * -------------- ++ * This function is the counterpart of the `lua_tg_checkentry`_ function. It is ++ * responsible to free all the resources alocated inside the checkentry process. ++ * To be more specific it frees the Lua state using *lua_close* and kfree on all ++ * the dynamically allocated pointers to the registered dynamic protocol buffers. ++ * ++ * Additionally the function cares about decrementing the reference counters ++ * inside the array `lua_states`_. ++ */ ++static void ++lua_tg_destroy(const struct xt_tgdtor_param *par) ++{ ++ const struct xt_lua_tginfo *info = par->targinfo; ++ struct lua_env * env = lua_envs[info->state_id]; ++ ++ if (lua_state_refs[info->state_id] == 1) { ++ lua_close(env->L); ++ cleanup_dynamic_prot_bufs(); /* clean memory allocated by protocols defined in Lua */ ++ kfree(env); ++ pr_debug("LUA [%d]: Rule removed, close Lua state\n", info->state_id); ++ } else ++ pr_debug("LUA [%d]: Rule removed, Lua state stays open, referenced %d time(s)\n", ++ info->state_id, lua_state_refs[info->state_id] - 1); ++ ++ lua_state_refs[info->state_id]--; ++} ++ ++static struct xt_target lua_tg_reg __read_mostly = { ++ .name = "LUA", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .targetsize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .target = lua_tg, ++ .checkentry = lua_tg_checkentry, ++ .destroy = lua_tg_destroy, ++ .me = THIS_MODULE, ++}; ++ ++ ++static int32_t lua_tg_init(void) ++{ ++ return xt_register_target(&lua_tg_reg); ++} ++ ++static void lua_tg_exit(void) ++{ ++ xt_unregister_target(&lua_tg_reg); ++} ++ ++module_init(lua_tg_init); ++module_exit(lua_tg_exit); ++ ++MODULE_AUTHOR("Andre Graf "); ++MODULE_DESCRIPTION("Xtables: Processing of matched packets using the Lua scripting environment"); ++MODULE_ALIAS("ipt_LUA"); ++MODULE_ALIAS("ipt6t_LUA"); ++MODULE_ALIAS("arpt_LUA"); ++MODULE_ALIAS("ebt_LUA"); ++MODULE_LICENSE("GPL"); ++ ++ ++ +--- a/extensions/Kbuild ++++ b/extensions/Kbuild +@@ -29,6 +29,7 @@ obj-${build_pknock} += pknock/ + obj-${build_psd} += xt_psd.o + obj-${build_quota2} += xt_quota2.o + obj-${build_rtsp} += rtsp/ ++obj-${build_LUA} += LUA/ + + -include ${M}/*.Kbuild + -include ${M}/Kbuild.* +--- a/extensions/Mbuild ++++ b/extensions/Mbuild +@@ -24,3 +24,4 @@ obj-${build_pknock} += pknock/ + obj-${build_psd} += libxt_psd.so + obj-${build_quota2} += libxt_quota2.so + obj-${build_gradm} += libxt_gradm.so ++obj-${build_LUA} += LUA/ +--- a/mconfig ++++ b/mconfig +@@ -25,3 +25,4 @@ build_pknock=m + build_psd=m + build_quota2=m + build_rtsp=m ++build_LUA=m diff --git a/xtables-addons/patches/201-fix-lua-packetscript.patch b/xtables-addons/patches/201-fix-lua-packetscript.patch new file mode 100644 index 000000000..64130121c --- /dev/null +++ b/xtables-addons/patches/201-fix-lua-packetscript.patch @@ -0,0 +1,147 @@ +--- a/extensions/LUA/Kbuild ++++ b/extensions/LUA/Kbuild +@@ -22,6 +22,8 @@ xt_LUA-y += nf_lua.o \ + prot_buf_dynamic.o \ + + ++# Enable ++EXTRA_CFLAGS += -isystem $(shell $(CC) -print-file-name=include) + # Adding Lua Support + EXTRA_CFLAGS += -I$(src)/lua -I$(src)/lua/include + xt_LUA-y += lua/lapi.o \ +--- a/extensions/LUA/xt_LUA_target.c ++++ b/extensions/LUA/xt_LUA_target.c +@@ -19,7 +19,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include "xt_LUA.h" +@@ -64,10 +64,10 @@ uint32_t lua_state_refs[LUA_STATE_ARRAY + * XT_CONTINUE inside the *register_lua_packet_lib* function. + */ + +-spinlock_t lock = SPIN_LOCK_UNLOCKED; ++DEFINE_SPINLOCK(lock); + + static uint32_t +-lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) ++lua_tg(struct sk_buff *pskb, const struct xt_action_param *par) + { + uint32_t verdict; + lua_packet_segment *p; +@@ -79,7 +79,7 @@ lua_tg(struct sk_buff *pskb, const struc + + L = lua_envs[info->state_id]->L; + +- if (!skb_make_writable(pskb, pskb->len)) ++ if (skb_ensure_writable(pskb, pskb->len)) + return NF_DROP; + + /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ +@@ -88,11 +88,11 @@ lua_tg(struct sk_buff *pskb, const struc + /* push the lua_packet_segment as a parameter */ + p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); + if (pskb->mac_header) +- p->start = pskb->mac_header; ++ p->start = skb_mac_header(pskb); + else if (pskb->network_header) +- p->start = pskb->network_header; ++ p->start = skb_network_header(pskb); + else if (pskb->transport_header) +- p->start = pskb->transport_header; ++ p->start = skb_transport_header(pskb); + p->offset = 0; + p->length = (unsigned long)pskb->tail - (unsigned long)p->start; + p->changes = NULL; +@@ -208,16 +208,16 @@ static bool load_script_into_state(uint3 + * some workqueue initialization. So far this is done each time this function + * is called, subject to change. + */ +-static bool ++static int + lua_tg_checkentry(const struct xt_tgchk_param *par) + { + const struct xt_lua_tginfo *info = par->targinfo; + + if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { + lua_state_refs[info->state_id]++; +- return true; ++ return 0; + } +- return false; ++ return -EINVAL; + } + + /*::* +--- a/extensions/LUA/lua/llimits.h ++++ b/extensions/LUA/lua/llimits.h +@@ -8,7 +8,6 @@ + #define llimits_h + + #include +-#include + + #include "lua.h" + +--- a/extensions/LUA/lua/lapi.c ++++ b/extensions/LUA/lua/lapi.c +@@ -4,9 +4,6 @@ + ** See Copyright Notice in lua.h + */ + +-#include +-#include +-#include + #include + + #define lapi_c +--- a/extensions/LUA/lua/ltable.c ++++ b/extensions/LUA/lua/ltable.c +@@ -18,7 +18,6 @@ + ** Hence even when the load factor reaches 100%, performance remains good. + */ + +-#include + #include + + #define ltable_c +--- a/extensions/LUA/lua/luaconf.h ++++ b/extensions/LUA/lua/luaconf.h +@@ -13,8 +13,12 @@ + #if !defined(__KERNEL__) + #include + #else ++#include ++ ++#undef UCHAR_MAX ++#undef BUFSIZ ++#undef NO_FPU + #define UCHAR_MAX 255 +-#define SHRT_MAX 32767 + #define BUFSIZ 8192 + #define NO_FPU + #endif +@@ -637,6 +641,8 @@ union luai_Cast { double l_d; long l_l; + */ + #if defined(__KERNEL__) + #undef LUA_USE_ULONGJMP ++#define setjmp __builtin_setjmp ++#define longjmp __builtin_longjmp + #endif + + #if defined(__cplusplus) +--- a/extensions/LUA/lua/llex.h ++++ b/extensions/LUA/lua/llex.h +@@ -10,6 +10,8 @@ + #include "lobject.h" + #include "lzio.h" + ++/* prevent conflict with definition from asm/current.h */ ++#undef current + + #define FIRST_RESERVED 257 + diff --git a/xtables-addons/patches/210-freebsd-build-fix.patch b/xtables-addons/patches/210-freebsd-build-fix.patch new file mode 100644 index 000000000..4f05d60eb --- /dev/null +++ b/xtables-addons/patches/210-freebsd-build-fix.patch @@ -0,0 +1,11 @@ +--- a/extensions/LUA/Makefile ++++ b/extensions/LUA/Makefile +@@ -110,7 +110,7 @@ PKG_CONFIG = /usr/bin/pkg-config + RANLIB = ranlib + SED = /bin/sed + SET_MAKE = +-SHELL = /bin/bash ++SHELL = /bin/sh + STRIP = strip + VERSION = 1.21 + abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA diff --git a/xtables-addons/patches/900-remove-checksumh.patch b/xtables-addons/patches/900-remove-checksumh.patch new file mode 100644 index 000000000..4af1688f5 --- /dev/null +++ b/xtables-addons/patches/900-remove-checksumh.patch @@ -0,0 +1,33 @@ +--- a/extensions/LUA/prot_buf_ip.c 2023-10-20 16:55:00.658340536 +0200 ++++ b/extensions/LUA/prot_buf_ip.c 2023-10-20 16:55:11.030165998 +0200 +@@ -17,7 +17,6 @@ + */ + + #if defined(__KERNEL__) +- #include + #include + #endif + +--- a/extensions/LUA/prot_buf_tcp.c 2023-10-20 17:05:44.507457150 +0200 ++++ v/extensions/LUA/prot_buf_tcp.c 2023-10-20 17:06:08.907041173 +0200 +@@ -17,7 +17,6 @@ + */ + + #if defined(__KERNEL__) +- #include + #include + #endif + #include "controller.h" +--- a/extensions/LUA/prot_buf_udp.c 2023-10-20 17:05:54.411288304 +0200 ++++ b/extensions/LUA/prot_buf_udp.c 2023-10-20 17:06:15.758924360 +0200 +@@ -16,10 +16,9 @@ + * along with this program; if not, see . + */ + + #if defined(__KERNEL__) +- #include + #endif + + #include "controller.h" + + From 954faf55158c82ec9624b9a4b00ebcefb49aed0b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 24 Oct 2023 11:28:33 +0200 Subject: [PATCH 1143/2059] Fix OMR-ByPass proto with IPv6 --- omr-bypass/files/etc/init.d/omr-bypass | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass b/omr-bypass/files/etc/init.d/omr-bypass index cfb3beb6d..faceac0de 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass +++ b/omr-bypass/files/etc/init.d/omr-bypass @@ -501,7 +501,7 @@ _bypass_proto_without_ndpi() { ipset -q flush bypass6_$proto > /dev/null 2>&1 ipset -q --exist restore <<-EOF create bypass_$proto hash:net hashsize 64 - create bypass6_$proto hash:net hashsize 64 + create bypass6_$proto hash:net family inet6 hashsize 64 EOF for ip in $ALLIPS; do valid_ip4=$( valid_subnet4 $ip) From 66478adfacc8fbf1663229aea295b494b9377539 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 25 Oct 2023 17:03:00 +0200 Subject: [PATCH 1144/2059] Fix Xray VLESS Reality init --- xray-core/files/etc/init.d/xray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xray-core/files/etc/init.d/xray b/xray-core/files/etc/init.d/xray index 216ef152f..d69dcc585 100755 --- a/xray-core/files/etc/init.d/xray +++ b/xray-core/files/etc/init.d/xray @@ -383,7 +383,7 @@ outbound_section_validate() { 's_vless_reality_port:port' \ 's_vless_reality_user_id:string' \ 's_vless_reality_user_alter_id:and(uinteger, max(65535))' \ - 's_vless_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_vless_reality_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ 's_vless_reality_user_encryption:or("auto", "none")' \ 's_vless_reality_flow:string' \ 's_vless_reality_public_key:string' \ From 5b3bddd53e2c8e452b5c562c5313821b47d4c58c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 31 Oct 2023 12:37:17 +0100 Subject: [PATCH 1145/2059] No need to change tc on glorytun-udp --- glorytun-udp/init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glorytun-udp/init b/glorytun-udp/init index 6b5522129..c9452e734 100755 --- a/glorytun-udp/init +++ b/glorytun-udp/init @@ -81,7 +81,7 @@ start_instance() { procd_close_instance - tc qdisc replace dev ${dev} root cake + #tc qdisc replace dev ${dev} root cake #ip link set $dev txqlen 100 #config_load network From dc450ffccd4192e68a01925b7f99c975828bf7a4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 31 Oct 2023 12:37:39 +0100 Subject: [PATCH 1146/2059] Force shadowsocks-redir and shadowsocks-rules in openmptpcrouter-full --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 2e288627c..e33cb87d3 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -44,7 +44,7 @@ MY_DEPENDS := \ luci-app-uhttpd \ luci-mod-rpc rpcd-mod-rpcsys rpcd-mod-file rpcd-mod-iwinfo \ luci-app-openvpn \ - shadowsocks-libev-ss-server shadowsocks-libev-ss-tunnel \ + shadowsocks-libev-ss-server shadowsocks-libev-ss-redir shadowsocks-libev-ss-rules shadowsocks-libev-ss-tunnel \ omr-6in4 ip6tables-mod-nat luci-proto-ipv6 6to4 6in4 6rd ip6tables \ !TARGET_mvebu:speedtestcpp \ iftop \ From 47ac658fd472fd11e0e8214fd40db3edb5a360db Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 31 Oct 2023 15:30:07 +0100 Subject: [PATCH 1147/2059] Remove 00-nego, make more issues than fixes --- openmptcprouter/files/etc/hotplug.d/iface/00-nego | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 openmptcprouter/files/etc/hotplug.d/iface/00-nego diff --git a/openmptcprouter/files/etc/hotplug.d/iface/00-nego b/openmptcprouter/files/etc/hotplug.d/iface/00-nego deleted file mode 100644 index 24ef81106..000000000 --- a/openmptcprouter/files/etc/hotplug.d/iface/00-nego +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -# Needed for some device, like rtl8156 2.5G USB adapter -[ "$ACTION" = "ifup" ] && [ -n "$DEVICE" ] && [ -n "$(lsusb | grep 8156)" ] && [ -n "$(ethtool $DEVICE | grep 2500)" ] && ethtool -s $DEVICE autoneg on \ No newline at end of file From 1101daba602413ef1cf6d287c2189d1011c64f84 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Nov 2023 09:48:21 +0100 Subject: [PATCH 1148/2059] Fix ModemManager restart loop --- .../omr/post-tracking.d/001-post-tracking | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index aef6be050..a34e5475a 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -736,17 +736,18 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then _log "Set $OMR_TRACKER_INTERFACE up" ifup $OMR_TRACKER_INTERFACE sleep 20 - elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "dhcp" ]); then - for modem in $(mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do - if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then - modem_device=$(mmcli -m $modem -K | grep 'modem.generic.device ' | awk '{print $3}') - [ -n "$modem_device" ] && modem_interface=$(uci show network | grep $modem_device | awk -F. '{print $2}') - [ -n "$modem_interface" ] && { - _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart associed interface $modem_interface" - ifup $modem_interface - } - fi - done + #elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "dhcp" ]); then + # for modem in $(mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do + # if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then + # modem_device=$(mmcli -m $modem -K | grep 'modem.generic.device ' | awk '{print $3}') + # [ -n "$modem_device" ] && modem_interface=$(uci show network | grep $modem_device | awk -F. '{print $2}') + # [ -n "$modem_interface" ] && { + # _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart associed interface $modem_interface" + # ifup $modem_interface + # sleep 30 + # } + # fi + # done fi # This part must be done after modems restart because we have no idea when modems will be ready again... (another solution would be to check ModemManager status) From 8826903b5fe2c81b7525d72601a250eb39ae8e1a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 2 Nov 2023 14:15:16 +0100 Subject: [PATCH 1149/2059] Update iproute2 --- iproute2/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iproute2/Makefile b/iproute2/Makefile index 194edcb35..7f4556e7d 100644 --- a/iproute2/Makefile +++ b/iproute2/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iproute2 -PKG_VERSION:=6.4.0 +PKG_VERSION:=6.5.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 -PKG_HASH:=4c51b8decbc7e4da159ffb066f590cfb93dbf9af7ff86b1647ce42b7c179a272 +PKG_HASH:=a70179085fa1b96d3c33b040c809b75e2b57563adc505a4ad05e2609df373463 PKG_BUILD_PARALLEL:=1 PKG_BUILD_DEPENDS:=iptables PKG_LICENSE:=GPL-2.0 From 107f8ef0e5c678217c2248f84e63f4b2dc9140b5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:20:26 +0100 Subject: [PATCH 1150/2059] Update libmbim --- libmbim/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index cfcb5ba96..85024008e 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -8,12 +8,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_SOURCE_VERSION:=1.29.2 +PKG_SOURCE_VERSION:=1.30.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -#PKG_MIRROR_HASH:=0b0b46016738fc22355d5a58c8a2d1b2f04906c49c51a50b57a09640d13b00b7 +PKG_MIRROR_HASH:=8fc4e2d78d6a1003bf89303d3ce779283b176d74e84a241ba8efb0d468605268 + +PKG_BUILD_FLAGS:=gc-sections PKG_MAINTAINER:=Nicholas Smith @@ -21,8 +23,7 @@ include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk include $(INCLUDE_DIR)/meson.mk -TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants -TARGET_LDFLAGS += -Wl,--gc-sections +TARGET_CFLAGS += -fno-merge-all-constants -fmerge-constants MESON_ARGS += \ -Dintrospection=false \ From 8845bb446ad78e1d76a367c8f6d2c41c2f16743e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:20:40 +0100 Subject: [PATCH 1151/2059] Update libqmi --- libqmi/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libqmi/Makefile b/libqmi/Makefile index cecee6cb6..5652332fe 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -8,12 +8,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqmi -PKG_SOURCE_VERSION:=1.33.3 +PKG_SOURCE_VERSION:=1.34.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -#PKG_MIRROR_HASH:=711d16d75a6a9afaefcf2be1bc845a4a6181dff786dfbd079e41e91279a0be91 +PKG_MIRROR_HASH:=af3dc760d0c40ef8af1f8b424435daa12bff698ed45b1cc9a9e38ea62ed047f0 + +PKG_BUILD_FLAGS:=gc-sections PKG_MAINTAINER:=Nicholas Smith @@ -21,8 +23,7 @@ include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk include $(INCLUDE_DIR)/meson.mk -TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants -TARGET_LDFLAGS += -Wl,--gc-sections +TARGET_CFLAGS += -fno-merge-all-constants -fmerge-constants define Package/libqmi/config source "$(SOURCE)/Config.in" From 77d8d7084bb8b1a315f0ba08851a0eeedf189a32 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:21:31 +0100 Subject: [PATCH 1152/2059] Add chacha20 suport to OpenVPN --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 222036652..018b3365f 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -960,7 +960,7 @@ function wizard_add() ucic:set("shadowsocks-libev","sss1","method","chacha20-ietf-poly1305") ucic:set("glorytun","vpn","chacha20","1") ucic:set("glorytun-udp","vpn","chacha","1") - ucic:set("openvpn","omr","cipher","AES-256-GCM") + ucic:set("openvpn","omr","cipher","chacha20-poly1305") ucic:set("mlvpn","general","cleartext_data","0") ucic:set("v2ray","omrout","s_vmess_user_security","chacha20-poly1305") ucic:set("v2ray","omrout","s_vless_user_security","chacha20-poly1305") From 5f51b9229cdd83024bb02104cc3f7d0a859e2645 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:22:10 +0100 Subject: [PATCH 1153/2059] Update ModemManager --- modemmanager/Makefile | 6 +- modemmanager/files/modemmanager.common | 92 ++++++++++--------- modemmanager/files/modemmanager.init | 7 -- .../files/usr/sbin/ModemManager-wrapper | 2 +- 4 files changed, 52 insertions(+), 55 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 8a4958404..d30b1a2e9 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_SOURCE_VERSION:=1.20.6 -PKG_RELEASE:=8 +PKG_SOURCE_VERSION:=1.22.0 +PKG_RELEASE:=5 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_MIRROR_HASH:=e90103e2e42bb826bbbac83937a9a69f50348cd6ce0d8da655a12b65494ce7c9 +PKG_MIRROR_HASH:=98daa1a15075c88afb3ed0de20dc83fe51d2ba3c66318ce3f731da4616a2e192 PKG_MAINTAINER:=Nicholas Smith PKG_LICENSE:=GPL-2.0-or-later diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common index 6a59ae6e1..2ba2036ce 100644 --- a/modemmanager/files/modemmanager.common +++ b/modemmanager/files/modemmanager.common @@ -6,6 +6,7 @@ . /lib/functions.sh . /lib/netifd/netifd-proto.sh +INCLUDE_ONLY=1 . /lib/netifd/proto/modemmanager.sh ################################################################################ # Runtime state @@ -20,7 +21,8 @@ MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" # Common logging mm_log() { - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && logger -t "ModemManager" "hotplug: $*" + local level="$1"; shift + logger -p "daemon.${level}" -t "ModemManager[$$]" "hotplug: $*" } ################################################################################ @@ -39,14 +41,14 @@ mm_find_physdev_sysfs_path() { # avoid infinite loops iterating [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return - # for USB devices, the physical device will be that with a idVendor - # and idProduct pair of files + # For USB devices, the physical device will be that with a idVendor + # and idProduct pair of files [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { tmp_path=$(readlink -f "$tmp_path") echo "${tmp_path}" return } - + # For PCI devices, the physical device will be that with a vendor # and device pair of files [ -f "${tmp_path}"/vendor ] && [ -f "${tmp_path}"/device ] && { @@ -138,10 +140,6 @@ mm_get_modem_config_foreach_cb() { local cfg="$1" local sysfspath="$2" - local proto - config_get proto "${cfg}" proto - [ "${proto}" = modemmanager ] || return 0 - local dev dev=$(uci_get network "${cfg}" device) [ "${dev}" = "${sysfspath}" ] || return 0 @@ -169,7 +167,7 @@ mm_wait_for_modem() { while [ $n -ge 0 ]; do [ -d "${sysfspath}" ] || { - mm_log "error: ignoring modem detection request: no device at ${sysfspath}" + mm_log "error" "ignoring modem detection request: no device at ${sysfspath}" proto_set_available "${cfg}" 0 return 1 } @@ -177,10 +175,10 @@ mm_wait_for_modem() { # Check if the modem exists at the given sysfs path if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 then - mm_log "error: modem not detected at sysfs path" + mm_log "error" "modem not detected at sysfs path" else - mm_log "modem exported successfully at ${sysfspath}" - mm_log "setting interface '${cfg}' as available" + mm_log "info" "modem exported successfully at ${sysfspath}" + mm_log "info" "setting interface '${cfg}' as available" proto_set_available "${cfg}" 1 return 0 fi @@ -189,7 +187,7 @@ mm_wait_for_modem() { n=$((n-step)) done - mm_log "error: timed out waiting for the modem to get exported at ${sysfspath}" + mm_log "error" "timed out waiting for the modem to get exported at ${sysfspath}" proto_set_available "${cfg}" 0 return 2 } @@ -201,7 +199,7 @@ mm_report_modem_wait() { parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") [ -n "${parent_sysfspath}" ] || { - mm_log "error: parent device sysfspath not found" + mm_log "error" "parent device sysfspath not found" return } @@ -212,23 +210,23 @@ mm_report_modem_wait() { cfg=$(mm_get_modem_config "${parent_sysfspath}") if [ -n "${cfg}" ]; then - mm_log "interface '${cfg}' is set to configure device '${parent_sysfspath}'" - mm_log "now waiting for modem at sysfs path ${parent_sysfspath}" + mm_log "info" "interface '${cfg}' is set to configure device '${parent_sysfspath}'" + mm_log "info" "now waiting for modem at sysfs path ${parent_sysfspath}" mm_set_modem_wait_status "${parent_sysfspath}" "processed" # Launch subshell for the explicit wait ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & else - mm_log "no need to wait for modem at sysfs path ${parent_sysfspath}" + mm_log "info" "no need to wait for modem at sysfs path ${parent_sysfspath}" mm_set_modem_wait_status "${parent_sysfspath}" "ignored" fi ;; "processed") - mm_log "already waiting for modem at sysfs path ${parent_sysfspath}" + mm_log "info" "already waiting for modem at sysfs path ${parent_sysfspath}" ;; "ignored") ;; *) - mm_log "error: unknown status read for device at sysfs path ${parent_sysfspath}" + mm_log "error" "unknown status read for device at sysfs path ${parent_sysfspath}" ;; esac } @@ -236,19 +234,21 @@ mm_report_modem_wait() { ################################################################################ # Cleanup interfaces -mm_cleanup_interface_cb() { - local cfg="$1" - - local proto - config_get proto "${cfg}" proto - [ "${proto}" = modemmanager ] || return 0 - - proto_set_available "${cfg}" 0 -} - mm_cleanup_interfaces() { - config_load network - config_foreach mm_cleanup_interface_cb interface + local sysfs_path status + + # Do nothing if there is no sysfs cache + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return + + while IFS= read -r sysfs_cache_line; do + sysfs_path=$(echo "${sysfs_cache_line}" | awk '{print $1}') + status=$(echo "${sysfs_cache_line}" | awk '{print $2}') + + if [ "${status}" = "processed" ]; then + mm_log "debug" "call cleanup for: ${sysfs_path}" + mm_cleanup_interface_by_sysfspath "${sysfs_path}" + fi + done < ${MODEMMANAGER_SYSFS_CACHE} } mm_cleanup_interface_by_sysfspath() { @@ -258,7 +258,7 @@ mm_cleanup_interface_by_sysfspath() { cfg=$(mm_get_modem_config "$dev") [ -n "${cfg}" ] || return - mm_log "setting interface '$cfg' as unavailable" + mm_log "info" "setting interface '$cfg' as unavailable" proto_set_available "${cfg}" 0 } @@ -273,7 +273,7 @@ mm_report_event() { local sysfspath="$4" # Do not save virtual devices - local virtual + local virtual result virtual="$(echo "$sysfspath" | cut -d'/' -f4)" [ "$virtual" = "virtual" ] && { mm_log "debug" "sysfspath is a virtual device ($sysfspath)" @@ -294,11 +294,15 @@ mm_report_event() { esac # Report the event - mm_log "event reported: action=${action}, name=${name}, subsystem=${subsystem}" - mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 1>/dev/null 2>&1 & + mm_log "debug" "Report event: action=${action}, name=${name}, subsystem=${subsystem}" + result=$(mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 2>&1) + if [ "$?" -eq "0" ]; then + # Wait for added modem if a sysfspath is given + [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" + else + mm_log "error" "Couldn't report kernel event: ${result}" + fi - # Wait for added modem if a sysfspath is given - [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" } mm_report_event_from_cache_line() { @@ -310,14 +314,11 @@ mm_report_event_from_cache_line() { subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }') sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }') - mm_log "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" + mm_log "debug" "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}" } mm_report_events_from_cache() { - # Remove the sysfs cache - rm -f "${MODEMMANAGER_SYSFS_CACHE}" - local n=60 local step=1 local mmrunning=0 @@ -325,11 +326,11 @@ mm_report_events_from_cache() { # Wait for ModemManager to be available in the bus while [ $n -ge 0 ]; do sleep $step - mm_log "checking if ModemManager is available..." + mm_log "info" "checking if ModemManager is available..." if ! mmcli -L >/dev/null 2>&1 then - mm_log "ModemManager not yet available" + mm_log "info" "ModemManager not yet available" else mmrunning=1 break @@ -338,10 +339,13 @@ mm_report_events_from_cache() { done [ ${mmrunning} -eq 1 ] || { - mm_log "error: couldn't report initial kernel events: ModemManager not running" + mm_log "error" "couldn't report initial kernel events: ModemManager not running" return } + # Remove the sysfs cache + rm -f "${MODEMMANAGER_SYSFS_CACHE}" + # Report cached kernel events while IFS= read -r event_line; do mm_report_event_from_cache_line "${event_line}" diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init index a3f6c1b12..c19022031 100644 --- a/modemmanager/files/modemmanager.init +++ b/modemmanager/files/modemmanager.init @@ -4,13 +4,6 @@ USE_PROCD=1 START=70 -stop_service() { - # Load common utils - . /usr/share/ModemManager/modemmanager.common - # Set all configured interfaces as unavailable - mm_cleanup_interfaces -} - start_service() { # Setup ModemManager service # diff --git a/modemmanager/files/usr/sbin/ModemManager-wrapper b/modemmanager/files/usr/sbin/ModemManager-wrapper index 4fd64227f..e06d943e9 100755 --- a/modemmanager/files/usr/sbin/ModemManager-wrapper +++ b/modemmanager/files/usr/sbin/ModemManager-wrapper @@ -20,7 +20,6 @@ main() { mkdir -p "${MODEMMANAGER_RUNDIR}" chmod 0755 "${MODEMMANAGER_RUNDIR}" - mm_cleanup_interfaces /usr/sbin/ModemManager "$@" 1>/dev/null 2>/dev/null & CHILD="$!" @@ -28,6 +27,7 @@ main() { mm_report_events_from_cache wait "$CHILD" + mm_cleanup_interfaces } main "$@" From 696b9e1d0e39eeda87bcc02c7580c1934cc0cded Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:22:38 +0100 Subject: [PATCH 1154/2059] Add support for IPv6 in multipath for 6.x kernels --- mptcp/files/usr/bin/multipath | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index d7fa77354..a44d7f24b 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -141,7 +141,9 @@ else ID=$(ip mptcp endpoint show | grep -m 1 "dev $DEVICE" | awk '{print $3}') IFF=$(ip mptcp endpoint show | grep -m 1 "dev $DEVICE" | awk '{print $4}') - IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') + #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') + [ -f /usr/bin/jsonfilter ] && IP=$(ip -j a show $DEVICE | jsonfilter -e '@[0].addr_info[*].local') + [ -f /usr/bin/jq ] && IP=$(ip -j a show $DEVICE | jq -r '.[0].addr_info[].local') [ -z "$ID" ] && [ -n "$IP" ] && ID=$(ip mptcp endpoint show | grep "$IP" | awk '{print $3}') RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null From d8cdc0b88edfce71bf116f13953f75183c999f0d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:23:14 +0100 Subject: [PATCH 1155/2059] Add xray and v2ray protocols support to omr-tracker-server --- omr-tracker/files/bin/omr-tracker-server | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 9990647fb..940c119b8 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -79,9 +79,18 @@ _check_master() { EOF if [ "$count" -eq "0" ]; then uci -q batch <<-EOF >/dev/null + set xray.omrout.s_vmess_address=$ip + set xray.omrout.s_vless_address=$ip + set xray.omrout.s_vless_reality_address=$ip + set xray.omrout.s_trojan_address=$ip + set xray.omrout.s_socks_address=$ip + set xray.omrout.s_shadowsocks_address=$ip set v2ray.omrout.s_vmess_address=$ip set v2ray.omrout.s_vless_address=$ip + set v2ray.omrout.s_trojan_address=$ip + set v2ray.omrout.s_socks_address=$ip commit v2ray + commit xray set glorytun.vpn.host=$ip commit glorytun glorytun-udp.vpn.host=$ip @@ -98,6 +107,7 @@ _check_master() { EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null + /etc/init.d/xray restart >/dev/null 2>/dev/null /etc/init.d/glorytun restart >/dev/null 2>/dev/null /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null /etc/init.d/mlvpn restart >/dev/null 2>/dev/null @@ -194,9 +204,18 @@ _check_backup() { EOF if [ "$count" -eq "0" ]; then uci -q batch <<-EOF >/dev/null + set xray.omrout.s_vmess_address=$ip + set xray.omrout.s_vless_address=$ip + set xray.omrout.s_vless_reality_address=$ip + set xray.omrout.s_trojan_address=$ip + set xray.omrout.s_socks_address=$ip + set xray.omrout.s_shadowsocks_address=$ip set v2ray.omrout.s_vmess_address=$ip set v2ray.omrout.s_vless_address=$ip + set v2ray.omrout.s_trojan_address=$ip + set v2ray.omrout.s_socks_address=$ip commit v2ray + commit xray set glorytun.vpn.host=$ip commit glorytun glorytun-udp.vpn.host=$ip From 0df8928298c78c71ded6b78722651c4eb6bd7313 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:23:49 +0100 Subject: [PATCH 1156/2059] Fix for OpenVPN in openmptcprouter-vps --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index bff3342a3..e9a3c420c 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -135,7 +135,7 @@ _set_glorytun_vps() { _set_openvpn_vps() { local enabled port key - enabled="$(uci -q get openvpn.omr.enable)" + enabled="$(uci -q get openvpn.omr.enabled)" [ "$enabled" != "1" ] && echo "OpenVPN disabled" && return port="$(uci -q get openvpn.omr.port)" cipher="$(uci -q get openvpn.omr.cipher)" From cc789dbafcb7e87f1f708a14a1d45e7caee98385 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 4 Nov 2023 08:24:55 +0100 Subject: [PATCH 1157/2059] Set OpenVPN as default VPN --- openmptcprouter/files/etc/uci-defaults/2020-omr-vpn | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index 5e1e38c7a..a8a84193c 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -154,9 +154,10 @@ if [ "$(uci -q get network.tun0.mtu)" = "1200" ] || [ -z "$(uci -q get network.t EOF fi +# Set the default VPN if [ "$(uci -q get openmptcprouter.settings.vpn)" = "" ]; then uci -q batch <<-EOF >/dev/null - set openmptcprouter.settings.vpn='glorytun_tcp' + set openmptcprouter.settings.vpn='openvpn' set glorytun.vpn.enable='1' commit glorytun commit openmptcprouter From bd629c7b836da1702900335a2d3af80c08b6731b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 5 Nov 2023 19:10:14 +0100 Subject: [PATCH 1158/2059] Force ModemManager to be less verbose --- modemmanager/files/modemmanager.common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common index 2ba2036ce..e47e0e025 100644 --- a/modemmanager/files/modemmanager.common +++ b/modemmanager/files/modemmanager.common @@ -22,7 +22,7 @@ MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" mm_log() { local level="$1"; shift - logger -p "daemon.${level}" -t "ModemManager[$$]" "hotplug: $*" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && logger -p "daemon.${level}" -t "ModemManager[$$]" "hotplug: $*" } ################################################################################ From da6e20600eeb7592c73043bda11829bab4508cd4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 5 Nov 2023 19:11:08 +0100 Subject: [PATCH 1159/2059] Fixes on redirection when using XRray or V2Ray --- .../files/etc/init.d/openmptcprouter-vps | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index e9a3c420c..3852d4155 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1138,8 +1138,8 @@ _vps_firewall_redirect_port() { checkfw="" if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- V2Ray to ${dest_ip}:${dest_port}") - [ "$xray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- XRay to ${dest_ip}:${dest_port}") + [ "$v2ray" = "1" ] && checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" = "1" ] && checkfw=$(echo "$vpsfwlist" | grep "$src_dport # OMR $username open router $src_dport port $protoi --- XRay to ${dest_ip}:${dest_port}") else comment="" [ -n "$src_dip" ] && { @@ -1159,58 +1159,58 @@ _vps_firewall_redirect_port() { } } [ -n "$src_ip" ] && comment=" from $src_ip" - [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") - [ "$xray" == "1" ] && checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}") + [ "$v2ray" = "1" ] && checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" = "1" ] && checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}") - [ "$xray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}") + [ "$v2ray" = "1" ] && checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" = "1" ] && checkfw=$(echo "$vpsfw6list" | grep "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - [ "$v2ray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") - [ "$xray" == "1" ] && checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}") + [ "$v2ray" = "1" ] && checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") + [ "$xray" = "1" ] && checkfw=$(echo "$vpsfw6list" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}") fi fi if [ "$checkfw" = "" ]; then - [ "$v2ray" == "1" ] && settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "V2Ray to '${dest_ip}':'${dest_port}'"}' - [ "$xray" == "1" ] && settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "XRay to '${dest_ip}':'${dest_port}'"}' + [ "$v2ray" = "1" ] && settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "V2Ray to '${dest_ip}':'${dest_port}'"}' + [ "$xray" = "1" ] && settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","source_dip" : "'$src_dip'","source_ip" : "'$src_ip'","proto" : "'${protoi}'","fwtype" : "ACCEPT","ipproto" : "'$family'","comment" : "XRay to '${dest_ip}':'${dest_port}'"}' result=$(_set_json "shorewallopen" "$settings") [ -z "$dest_port" ] && dest_port="$src_dport" settings='{"name" : "router '$src_dport'","port" : "'$src_dport'","destip" : "'$dest_ip'","destport" : "'$dest_port'","proto" : "'${protoi}'"}' - [ "$v2ray" == "1" ] && result=$(_set_json "v2rayredirect" "$settings") - [ "$xray" == "1" ] && result=$(_set_json "xrayredirect" "$settings") + [ "$v2ray" = "1" ] && result=$(_set_json "v2rayredirect" "$settings") + [ "$xray" = "1" ] && result=$(_set_json "xrayredirect" "$settings") fi if [ "$family" = "ipv4" ]; then if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - [ "$v2ray" == "1"] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") - [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1"] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") else comment="" [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - [ "$v2ray" == "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") - [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfwlist=$(echo "$vpsfwlist" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") fi else if [ "$src_dip" = "" ] && [ "$src_ip" = "" ]; then - [ "$v2ray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") - [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR $username open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "$src_dport # OMR open router $src_dport port ${protoi} --- XRay to ${dest_ip}:${dest_port}$") else [ -n "$src_dip" ] && comment=" to $src_dip" [ -n "$src_ip" ] && comment=" from $src_ip" - [ "$v2ray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") - [ "$v2ray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") - [ "$xray" == "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR $username open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") + [ "$v2ray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}$") + [ "$xray" = "1" ] && [ "$username" = "openmptcprouter" ] && vpsfw6list=$(echo "$vpsfw6list" | grep -v "# OMR open router $src_dport port ${protoi}${comment} --- XRay to ${dest_ip}:${dest_port}$") fi fi fi From c6835d325bf69b45da7f3e10534797106505aa84 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 5 Nov 2023 19:11:30 +0100 Subject: [PATCH 1160/2059] Fix on sqm-autorate --- sqm-autorate/files/usr/share/sqm-autorate/config_template.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh index 0cce4cc1c..a4fe7f42e 100755 --- a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh +++ b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh @@ -78,7 +78,7 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # these are automatically adjusted based on maximum on the wire packet size # (adjustment significant at sub 12Mbit/s rates, else negligible) #logger -t "sqm-autorate" "ping for ${INTERFACE} (${ul_if}): $(echo $(/sbin/uci -q get sqm.${INTERFACE}.delay_thr_ms || echo '100'))" -dl_owd_delta_thr_ms=$(echo $(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(($(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | tr -d '\n' 2>/dev/null)+30)) || echo "100")) + "0.1" | bc) # (milliseconds) +dl_owd_delta_thr_ms=$(echo $(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(echo "$(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | tr -d '\n' 2>/dev/null)+30" | bc) || echo "100")) + "0.1" | bc) # (milliseconds) ul_owd_delta_thr_ms=${dl_owd_delta_thr_ms} # average owd delta threshold in ms at which maximum adjust_down_bufferbloat is applied From 170ef44489aa6de154281a97837a3bcaa9ac74c2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 5 Nov 2023 19:42:51 +0100 Subject: [PATCH 1161/2059] Add z8102 watchdog package --- z8102/Makefile | 38 +++++++++++++++++++++++++++++++ z8102/files/etc/init.d/z8102 | 30 ++++++++++++++++++++++++ z8102/files/usr/lib/custom/wdg.sh | 13 +++++++++++ 3 files changed, 81 insertions(+) create mode 100644 z8102/Makefile create mode 100755 z8102/files/etc/init.d/z8102 create mode 100755 z8102/files/usr/lib/custom/wdg.sh diff --git a/z8102/Makefile b/z8102/Makefile new file mode 100644 index 000000000..c2b1ab0e0 --- /dev/null +++ b/z8102/Makefile @@ -0,0 +1,38 @@ +# +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# Originally made by DairyMan@Whirlpool come from https://github.com/ofmodemsandmen/ROOterSource2305/tree/main/package/rooter/0routerspecfic/z8102 +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=z8102 +PKG_VERSION:=0.1 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Yannick Chabanois + +include $(INCLUDE_DIR)/package.mk + +define Package/z8102 + SECTION:=OMR + CATEGORY:=OpenMPTCProuter + TITLE:=Install scripts for z8102 + PKGARCH:=all +endef + +define Package/z8102/description + Helper scripts to install scripts for z8102 +endef + + +define Build/Compile +endef + +define Package/z8102/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,z8102)) diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 new file mode 100755 index 000000000..6a0e133cd --- /dev/null +++ b/z8102/files/etc/init.d/z8102 @@ -0,0 +1,30 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=58 +USE_PROCD=1 + +log() { + logger -t "z8102" "$@" +} + +start_service() +{ + i=459 + echo $i > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio${i}/direction + echo "1" > /sys/class/gpio/gpio${i}/value + i=460 + echo $i > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio${i}/direction + echo "1" > /sys/class/gpio/gpio${i}/value + i=461 + echo $i > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio${i}/direction + echo "0" > /sys/class/gpio/gpio${i}/value + i=462 + echo $i > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio${i}/direction + echo "0" > /sys/class/gpio/gpio${i}/value + /usr/lib/custom/wdg.sh & +} diff --git a/z8102/files/usr/lib/custom/wdg.sh b/z8102/files/usr/lib/custom/wdg.sh new file mode 100755 index 000000000..c583dac72 --- /dev/null +++ b/z8102/files/usr/lib/custom/wdg.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +i=457 +echo $i > /sys/class/gpio/export +echo "out" > /sys/class/gpio/gpio${i}/direction + +while true +do + echo "1" > /sys/class/gpio/gpio${i}/value + sleep 1 + echo "0" > /sys/class/gpio/gpio${i}/value + sleep 1 +done \ No newline at end of file From 5b32c33c0530b3fce4951d5807b6bcc62c3379ef Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 6 Nov 2023 16:21:28 +0100 Subject: [PATCH 1162/2059] Fix when VPS contact is a DNS --- omr-tracker/files/bin/omr-tracker-server | 2 +- omr-tracker/files/etc/init.d/omr-tracker | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 940c119b8..cff94206b 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -66,7 +66,7 @@ _check_master() { set_ip() { local ip=$1 ipresolve="$(resolveip -4 $ip | head -n 1)" - [ -z "$ipresolve" ] && ip="$ipresolve" + [ -n "$ipresolve" ] && ip="$ipresolve" #_ping_server $ip _check_server $ip $port if [ "$server_ping" = true ]; then diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 31be2a0d5..1b7699ea7 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -9,6 +9,7 @@ START=90 STOP=10 USE_PROCD=1 + EXTRA_COMMAND="start_interface" } . /usr/lib/unbound/iptools.sh @@ -331,9 +332,16 @@ _launch_xray_tracker() { sleep 1 } +_dns_server() { + local ip=$1 + resolv=$(resolveip -4 ${ip} | head -n 1) + [ -n "${resolv}" ] && [ "${resolv}" != "${ip}" ] && multiserver=true +} + _multi_server() { config_get backup $1 backup [ "$backup" = "1" ] && multiserver=true + config_list_foreach $1 ip _dns_server } _gre_tunnel() { @@ -341,6 +349,11 @@ _gre_tunnel() { [ "$proto" = "gre" ] && gretunnel=true } +start_interface() { + [ -z "$1" ] && return + _launch_tracker $1 +} + start_service() { local ss_enable=0 local ss_rust_enable=0 From 9ad0d58e81e413b5ef08bc015f97a6cf732e3f4b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 6 Nov 2023 16:22:15 +0100 Subject: [PATCH 1163/2059] Force remove of ncp-disable option in openvpn --- openmptcprouter/files/etc/init.d/openvpnbonding | 1 - openvpn/files/openvpn.config | 11 ----------- openvpn/files/openvpn.options | 1 - 3 files changed, 13 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openvpnbonding b/openmptcprouter/files/etc/init.d/openvpnbonding index 77d0b8c75..2ee974896 100755 --- a/openmptcprouter/files/etc/init.d/openvpnbonding +++ b/openmptcprouter/files/etc/init.d/openvpnbonding @@ -30,7 +30,6 @@ _openvpnbonding() { set openvpn.omr_bonding_${interface}.remote="${remoteip}" set openvpn.omr_bonding_${interface}.local="${localip}" set openvpn.omr_bonding_${interface}.lport='0' - set openvpn.omr_bonding_${interface}.ncp_disable='1' set openvpn.omr_bonding_${interface}.auth_nocache='1' set openvpn.omr_bonding_${interface}.proto='udp' set openvpn.omr_bonding_${interface}.client='1' diff --git a/openvpn/files/openvpn.config b/openvpn/files/openvpn.config index ea442c765..9b5a42655 100644 --- a/openvpn/files/openvpn.config +++ b/openvpn/files/openvpn.config @@ -279,17 +279,6 @@ config openvpn sample_server # Use BF-CBC as fallback # option data_ciphers_fallback 'BF-CBC' - # OpenVPN versions 2.4 and later will attempt to - # automatically negotiate the most secure cipher - # between the client and server, regardless of a - # configured "option cipher" (see below). - # Automatic negotiation is recommended. - # - # Uncomment this option to disable this behavior, - # and force all OpenVPN peers to use the configured - # cipher option instead (not recommended). -# option ncp_disable - # Enable compression on the VPN link. # If you enable it here, you must also # enable it in the client config file. diff --git a/openvpn/files/openvpn.options b/openvpn/files/openvpn.options index 7e3aedb0d..5b8d55a07 100644 --- a/openvpn/files/openvpn.options +++ b/openvpn/files/openvpn.options @@ -166,7 +166,6 @@ mlock mtu_test multihome mute_replay_warnings -ncp_disable nobind opt_verify passtos From 7dd7b50596008febb52a470f1783c209461bf308 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 6 Nov 2023 16:22:29 +0100 Subject: [PATCH 1164/2059] Force remove of ncp-disable option in openvpn --- openmptcprouter/files/etc/uci-defaults/2020-omr-vpn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index a8a84193c..962c03d39 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -37,7 +37,6 @@ if [ "$(uci -q get openvpn.omr.proto)" != "tcp-client" ]; then set openvpn.omr.port=65301 set openvpn.omr.cipher=AES-256-CBC set openvpn.omr.proto=tcp-client - set openvpn.omr.ncp_disable=0 set openvpn.omr.auth_nocache=1 set openvpn.omr.client=1 set openvpn.omr.tls_client=1 @@ -51,6 +50,7 @@ if [ "$(uci -q get openvpn.omr.proto)" != "tcp-client" ]; then fi uci -q delete openvpn.omr.secret +uci -q delete openvpn.omr.ncp_disable=0 #if [ "$(uci -q get openvpn.omr.com_lzo)" = "" ]; then # uci -q batch <<-EOF >/dev/null From 510c13a8419af0046e992ba6639cc8a6b29cfd57 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 6 Nov 2023 21:29:20 +0100 Subject: [PATCH 1165/2059] Restart missing WAN tracker when needed --- .../usr/share/omr/post-tracking.d/010-services | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index f2407ea01..8973c0cca 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -121,6 +121,19 @@ if ([ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.ss [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter fi +restart_omrtracker() { + [ -n "$(pgrep -f "omr-tracker $1)" ] && return + config_get multipath "$1" multipath + config_get ifenabled "$1" auto + [ -z "$multipath" ] || [ "$multipath" = "off" ] && return + [ "$ifenabled" = "0" ] && return + /etc/init.d/omr-tracker start_interface "$1" + sleep 10 +} + +config_load network +config_foreach restart_omrtracker interface + if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-ss, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null From c5320984f197bd45f1544488294255ca8257fea6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 7 Nov 2023 15:39:22 +0100 Subject: [PATCH 1166/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3028#issuecomment-1798648176 --- openmptcprouter-full/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index e33cb87d3..ccdf4110c 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -85,8 +85,7 @@ MY_DEPENDS := \ (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ - xray-core shadowsocks-rust-sslocal shadowsocks-rust-ssservice shadowsocks-rust-config luci-app-shadowsocks-rust -# (TARGET_x86_64||aarch64):kmod-tcp-bbr2 + xray-core shadowsocks-rust-sslocal shadowsocks-rust-ssservice shadowsocks-rust-config luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From 2d6ddd92aae2c82a6d9908737ae65b79227994a0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 7 Nov 2023 19:26:53 +0100 Subject: [PATCH 1167/2059] Fix gateway for OpenVPN in some case --- omr-tracker/files/bin/omr-tracker | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 72decbe1a..81a37258b 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -286,7 +286,10 @@ while true; do OMR_TRACKER_DEVICE_ROUTE=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep via | grep -v default | grep -v metric | grep -v / | awk '{print $1; exit}' | tr -d "\n") fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | awk '/proto kernel/ {print $1}' | tr -d "\n") + OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | grep -v '.0/' | awk '/proto kernel/ {print $1}' | tr -d "\n") + fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -m 1 default | awk '/via/ {print $3}' | tr -d "\n") fi fi if [ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ]; then From 6a4820663f8b500220a7a2fff4b81a5065f404cc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 8 Nov 2023 20:29:56 +0100 Subject: [PATCH 1168/2059] Add missing patch for modemmanager --- .../100-ublox-remove-ID_MM_PROCESS-tags.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch diff --git a/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch b/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch new file mode 100644 index 000000000..d1f67537b --- /dev/null +++ b/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch @@ -0,0 +1,13 @@ +--- a/src/plugins/ublox/77-mm-ublox-port-types.rules ++++ b/src/plugins/ublox/77-mm-ublox-port-types.rules +@@ -88,8 +88,8 @@ SUBSYSTEMS=="usb", ATTRS{bInterfaceNumbe + # ttyUSB2 (if #2): secondary + # ttyUSB3 (if #3): unused (ignore) + ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" +-ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" +-ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" ++ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" ++ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" + ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" + + LABEL="mm_ublox_port_types_end" From f358304707481ac27fd1d44c25a1a2bc532e413e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 10 Nov 2023 10:13:08 +0100 Subject: [PATCH 1169/2059] Fix issue when server use IPv6 --- omr-tracker/files/bin/omr-tracker-server | 16 +++++++++++++--- .../files/etc/init.d/openmptcprouter-vps | 7 +++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index cff94206b..d7124a555 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -25,7 +25,7 @@ _check_server() { local port=$2 local k=0 while [ "$server_ping" = false ] && [ "$k" -le "$retry" ]; do - ret=$(curl -4 \ + ret=$(curl \ --max-time "$OMR_TRACKER_TIMEOUT" \ -s \ -k \ @@ -66,7 +66,12 @@ _check_master() { set_ip() { local ip=$1 ipresolve="$(resolveip -4 $ip | head -n 1)" - [ -n "$ipresolve" ] && ip="$ipresolve" + if [ -n "$ipresolve" ]; then + ip="$ipresolve" + else + ip6resolve="$(resolveip -6 $ip | head -n 1)" + [ -n "$ip6resolve" ] && ip="$ip6resolve" + fi #_ping_server $ip _check_server $ip $port if [ "$server_ping" = true ]; then @@ -191,7 +196,12 @@ _check_backup() { set_ip() { local ip=$1 ipresolve="$(resolveip -4 $ip | head -n 1)" - [ -z "$ipresolve" ] && ip="$ipresolve" + if [ -n "$ipresolve" ]; then + ip="$ipresolve" + else + ip6resolve="$(resolveip -6 $ip | head -n 1)" + [ -n "$ip6resolve" ] && ip="$ip6resolve" + fi #_ping_server $ip _check_server $ip $port #[ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" = "$ip" ] && break diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 3852d4155..939a0ed7b 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -501,6 +501,13 @@ _get_vps_config() { fi fi vpsip="$(uci -q get openmptcprouter.${servername}.ip | awk '{print $1}')" + ipresolve="$(resolveip -4 $vpsip | head -n 1)" + if [ -n "$ipresolve" ]; then + vpsip="$ipresolve" + else + ip6resolve="$(resolveip -6 $vpsip | head -n 1)" + [ -n "$ip6resolve" ] && vpsip="$ip6resolve" + fi if [ "$(uci -q get shadowsocks-libev.sss0.server)" != "127.0.0.1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then config_foreach _set_ss_server server "server" $vpsip uci -q batch <<-EOF >/dev/null From c7f53f2840bcc571ce0320ca5fec98a172c7e56e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 10 Nov 2023 10:14:34 +0100 Subject: [PATCH 1170/2059] Fix network, fix modems and add modems LEDs for ZBT Z8102AX --- .../files/etc/uci-defaults/1920-omr-network | 49 ++++++++++++++++++- .../files/etc/uci-defaults/2060-omr-system | 22 +++++++++ z8102/files/etc/init.d/z8102 | 33 ++++++++++--- 3 files changed, 95 insertions(+), 9 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 20e278230..f5a57cee0 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -85,6 +85,8 @@ fi lanif="eth0" if [ "$(grep rockchip /etc/os-release)" != "" ]; then lanif="eth1" +elif [ "$(grep filogic /etc/os-release)" != "" ]; then + lanif="eth1" elif [ -d /sys/class/net/lan0 -o -n "$(ip link | grep ' lan0')" ] && [ -d /sys/class/net/wan -o -n "$(ip link | grep ' wan@')" -o -n "$(ip link | grep ' wan:')" ]; then lanif="wan" elif [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/class/net/wan -o -n "$(ip link | grep ' wan@')" -o -n "$(ip link | grep ' wan:')" ]; then @@ -273,6 +275,19 @@ if [ "$(uci -q show network.wan1 | grep multipath)" = "" ] && [ -z "$(uci -q get _setup_macvlan wan1 _setup_macvlan wan2 fi + elif [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/class/net/lan2 -o -n "$(ip link | grep ' lan2')" ] && [ -d /sys/class/net/lan3 -o -n "$(ip link | grep ' lan3')" ] && [ -d /sys/class/net/lan4 -o -n "$(ip link | grep ' lan4')" ]; then + _setup_wan_interface wan1 lan1 master + _setup_wan_interface wan2 lan2 on + _macaddr=$(uci -q get "network.lan1.macaddr") + _setup_macaddr "wan1" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" + _macaddr=$(uci -q get "network.lan2.macaddr") + _setup_macaddr "wan2" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" + _setup_wan_interface wan3 lan3 on + _macaddr=$(uci -q get "network.lan3.macaddr") + _setup_macaddr "wan3" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" + _setup_wan_interface wan4 lan4 on + _macaddr=$(uci -q get "network.lan4.macaddr") + _setup_macaddr "wan4" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" elif [ -d /sys/class/net/wan1 ] || [ -n "$(ip link | grep ' wan1')" ]; then if [ -d /sys/class/net/wan2 ] || [ -n "$(ip link | grep ' wan2')" ]; then _setup_wan_interface wan1 wan1 master @@ -412,7 +427,39 @@ if ([ "$board" = "teltonika,rutx" ] || [ "$board" = "teltonika,rutx12" ] || [ "$ EOF fi - +if [ "$board" = "z8102ax" ]; then + uci -q batch <<-EOF + set network.modem1=interface + set network.modem1.proto='modemmanager' + set network.modem1.apn='' + set network.modem1.auth='none' + set network.modem1.iptype='ipv4v6' + set network.modem1.addlatency='0' + set network.modem1.force_link='1' + set network.modem1.device='/sys/devices/platform/11200000.usb/usb1/1-1/1-1.1' + set network.modem1.peerdns='0' + set network.modem1.multipath='oncd' + set network.modem1.defaultroute='0' + set network.modem2=interface + set network.modem2.proto='modemmanager' + set network.modem2.apn='' + set network.modem2.auth='none' + set network.modem2.iptype='ipv4v6' + set network.modem2.addlatency='0' + set network.modem2.force_link='1' + set network.modem2.device='/sys/devices/platform/11200000.usb/usb1/1-1/1-1.2' + set network.modem2.peerdns='0' + set network.modem2.multipath='on' + set network.modem2.defaultroute='0' + commit network + add_list firewall.@zone[1].network='modem1' + add_list firewall.@zone[1].network='modem2' + commit firewall + EOF + # /sys/bus/devices/1-1.1 +fi +# set network.lan.ipaddr='192.168.5.10' +# set network.lan.gateway='192.168.5.1' uci -q commit macvlan uci -q commit network diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index ec8de8d5b..5b8162cd7 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -127,6 +127,28 @@ elif [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" EOF fi +elif [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep z8102ax)" ] && [ -z "$(uci show system | grep modem1)" ]; then + uci -q batch <<-EOF >/dev/null + add system led + set system.@led[-1].name='modem1' + set system.@led[-1].sysfs='4g:status' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='wwan0' + add_list system.@led[-1].mode='link' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' + add system led + set system.@led[-1].name='modem2' + set system.@led[-1].sysfs='4g2:status' + set system.@led[-1].trigger='netdev' + set system.@led[-1].dev='wwan1' + add_list system.@led[-1].mode='link' + add_list system.@led[-1].mode='tx' + add_list system.@led[-1].mode='rx' + commit system + EOF +fi + #sed -i 's/^\tlogger -t/\t[ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] \&\& logger -t/g' /usr/share/ModemManager/modemmanager.common exit 0 \ No newline at end of file diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index 6a0e133cd..59b22fa03 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -1,5 +1,6 @@ #!/bin/sh /etc/rc.common # Copyright (C) 2013 OpenWrt.org +# Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter START=58 USE_PROCD=1 @@ -10,21 +11,37 @@ log() { start_service() { - i=459 - echo $i > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio${i}/direction - echo "1" > /sys/class/gpio/gpio${i}/value - i=460 - echo $i > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio${i}/direction - echo "1" > /sys/class/gpio/gpio${i}/value + # sim 1 i=461 echo $i > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio${i}/direction echo "0" > /sys/class/gpio/gpio${i}/value + # sim 2 i=462 echo $i > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio${i}/direction echo "0" > /sys/class/gpio/gpio${i}/value + + # stop modem 1 + i=459 + echo $i > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio${i}/direction + echo "0" > /sys/class/gpio/gpio${i}/value + # stop modem 2 + i=460 + echo $i > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio${i}/direction + echo "0" > /sys/class/gpio/gpio${i}/value + + sleep 1 + # run modem 1 + i=459 + echo "1" > /sys/class/gpio/gpio${i}/value + sleep 3 + # run modem 2 + i=460 + echo "1" > /sys/class/gpio/gpio${i}/value + + # watchdog /usr/lib/custom/wdg.sh & } From 6162e15c0c789a0524c3de376a219bce4b9b5d4c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 10 Nov 2023 11:22:39 +0100 Subject: [PATCH 1171/2059] Fix z8102ax leds --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 5b8162cd7..3e30f8d5b 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -127,7 +127,7 @@ elif [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" EOF fi -elif [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep z8102ax)" ] && [ -z "$(uci show system | grep modem1)" ]; then +if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep z8102ax)" ] && [ -z "$(uci show system | grep modem1)" ]; then uci -q batch <<-EOF >/dev/null add system led set system.@led[-1].name='modem1' From d3715ded3671a1a6fe6f188d3123d9e8d4552b6a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 12 Nov 2023 19:52:31 +0100 Subject: [PATCH 1172/2059] Force a delay threshold in ms for sqm autorate as calculation doesn't always work --- sqm-autorate/files/usr/share/sqm-autorate/config_template.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh index a4fe7f42e..dcc51c0db 100755 --- a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh +++ b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh @@ -78,7 +78,8 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # these are automatically adjusted based on maximum on the wire packet size # (adjustment significant at sub 12Mbit/s rates, else negligible) #logger -t "sqm-autorate" "ping for ${INTERFACE} (${ul_if}): $(echo $(/sbin/uci -q get sqm.${INTERFACE}.delay_thr_ms || echo '100'))" -dl_owd_delta_thr_ms=$(echo $(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(echo "$(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | tr -d '\n' 2>/dev/null)+30" | bc) || echo "100")) + "0.1" | bc) # (milliseconds) +#dl_owd_delta_thr_ms=$(echo $(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(echo "$(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | tr -d '\n' 2>/dev/null)+30" | bc) || echo "100")) + "0.1" | bc) # (milliseconds) +dl_owd_delta_thr_mss=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "250") ul_owd_delta_thr_ms=${dl_owd_delta_thr_ms} # average owd delta threshold in ms at which maximum adjust_down_bufferbloat is applied From 8515a680aac6075d8bba4f59cfa0cbd0ebccd3fa Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 13 Nov 2023 14:54:26 +0100 Subject: [PATCH 1173/2059] Remove random pause after connection failure --- .../usr/share/omr/post-tracking.d/001-post-tracking | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index a34e5475a..650471be7 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -898,11 +898,11 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then #ubus call network reload # Set a little sleep after an interface error - if [ -n "$RANDOM" ]; then - sleep `expr $RANDOM % 100` - else - sleep `awk 'BEGIN{srand();print int(rand()*20)}'` - fi +# if [ -n "$RANDOM" ]; then +# sleep `expr $RANDOM % 100` +# else +# sleep `awk 'BEGIN{srand();print int(rand()*20)}'` +# fi exit 0 fi From a5e026d6eb02f876f44d01027868caafff18c13d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 13 Nov 2023 14:55:38 +0100 Subject: [PATCH 1174/2059] Update netifd --- netifd/Makefile | 8 ++++---- netifd/files/lib/netifd/dhcp.script | 5 +++-- netifd/patches/001-init-pause.patch | 13 ------------- 3 files changed, 7 insertions(+), 19 deletions(-) delete mode 100644 netifd/patches/001-init-pause.patch diff --git a/netifd/Makefile b/netifd/Makefile index 808432756..826889aca 100644 --- a/netifd/Makefile +++ b/netifd/Makefile @@ -1,13 +1,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=netifd -PKG_RELEASE:=3 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2023-08-31 -PKG_SOURCE_VERSION:=1a07f1dff32b3af49e39533e33e8964b59535662 -PKG_MIRROR_HASH:=dc621dd04c3c9631002f929cf10a4620f57af8b0baf614c590bda17957fa6201 +PKG_SOURCE_DATE:=2023-11-10 +PKG_SOURCE_VERSION:=35facc8306f590a7330789ab6d5785c0d43073ef +PKG_MIRROR_HASH:=4f73591ae1873e18df235349e478f2196ca0d3123c313a04149dc9d5e2bfb403 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 diff --git a/netifd/files/lib/netifd/dhcp.script b/netifd/files/lib/netifd/dhcp.script index 02a95dd76..053dd75b6 100755 --- a/netifd/files/lib/netifd/dhcp.script +++ b/netifd/files/lib/netifd/dhcp.script @@ -19,12 +19,13 @@ setup_interface() { # TODO: apply $broadcast local ip_net - eval "$(ipcalc.sh "$ip/$mask")";ip_net="$NETWORK" + local ip_net IP PREFIX NETWORK NETMASK BROADCAST + ipcalc "$ip/$mask" && ip_net="$NETWORK" local i for i in $router; do local gw_net - eval "$(ipcalc.sh "$i/$mask")";gw_net="$NETWORK" + ipcalc "$i/$mask" && gw_net="$NETWORK" [ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip" #[ "$DEFAULTROUTE" = 0 ] || proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" diff --git a/netifd/patches/001-init-pause.patch b/netifd/patches/001-init-pause.patch deleted file mode 100644 index 0c09aab73..000000000 --- a/netifd/patches/001-init-pause.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/system-linux.c 2023-09-13 10:44:22.163111635 +0200 -+++ b/system-linux.c 2023-09-13 10:44:47.562696256 +0200 -@@ -2720,7 +2720,9 @@ - system_if_dump_info(struct device *dev, struct blob_buf *b) - { - __u32 *supported, *advertising, *lp_advertising; -- bool rx_pause, tx_pause, pause_autoneg; -+ bool rx_pause = false; -+ bool tx_pause = false; -+ bool pause_autoneg = false; - struct { - struct ethtool_link_settings req; - __u32 link_mode_data[3 * 127]; From a4cd28a5d16e08bec12091407c3e50e2772d96e6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 15 Nov 2023 16:28:39 +0100 Subject: [PATCH 1175/2059] Separate watchdog and modem init for z8102 --- z8102/Makefile | 4 +--- z8102/files/etc/init.d/z8102 | 3 --- z8102/files/etc/init.d/z8102-wdg | 19 +++++++++++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) create mode 100755 z8102/files/etc/init.d/z8102-wdg diff --git a/z8102/Makefile b/z8102/Makefile index c2b1ab0e0..4d1c7dfb4 100644 --- a/z8102/Makefile +++ b/z8102/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=z8102 PKG_VERSION:=0.1 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_MAINTAINER:=Yannick Chabanois @@ -31,8 +31,6 @@ endef define Package/z8102/install $(CP) ./files/* $(1)/ - - endef $(eval $(call BuildPackage,z8102)) diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index 59b22fa03..e08ee0b2d 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -41,7 +41,4 @@ start_service() # run modem 2 i=460 echo "1" > /sys/class/gpio/gpio${i}/value - - # watchdog - /usr/lib/custom/wdg.sh & } diff --git a/z8102/files/etc/init.d/z8102-wdg b/z8102/files/etc/init.d/z8102-wdg new file mode 100755 index 000000000..ed69d4db6 --- /dev/null +++ b/z8102/files/etc/init.d/z8102-wdg @@ -0,0 +1,19 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org +# Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter + +START=30 +USE_PROCD=1 + +log() { + logger -t "z8102-wdg" "$@" +} + +start_service() +{ + # watchdog + procd_open_instance + procd_set_param command /usr/lib/custom/wdg.sh + procd_set_param respawn + procd_close_instance +} From b52d3584e5ce7016c57ee1208e7fa344ea62de8c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 17 Nov 2023 17:34:51 +0100 Subject: [PATCH 1176/2059] Fix backup server getting keys --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 939a0ed7b..0b3512f6e 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2168,12 +2168,12 @@ _config_service() { return fi fi - [ "$(uci -q get openmptcprouter.${servername}.get_config)" = "1" ] && [ "$(uci -q get openmptcprouter.${servername}.master)" = "1" ] && { + [ "$(uci -q get openmptcprouter.${servername}.get_config)" = "1" ] && ([ "$(uci -q get openmptcprouter.${servername}.master)" = "1" ] || [ "$(uci -q get openmptcprouter.${servername}.current)" = "1" ]) && { _set_config_from_vps _get_gre_tunnel } - [ "$(uci -q get openmptcprouter.${servername}.master)" = "1" ] && { + ([ "$(uci -q get openmptcprouter.${servername}.master)" = "1" ] || [ "$(uci -q get openmptcprouter.${servername}.current)" = "1" ]) && { _get_vps_config } From a567f7f8a26769666263e9aedb1f7c84552aaff1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 17 Nov 2023 17:35:19 +0100 Subject: [PATCH 1177/2059] Fix XRay remove rules --- xray-core/files/etc/init.d/xray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xray-core/files/etc/init.d/xray b/xray-core/files/etc/init.d/xray index d69dcc585..3fa53a12f 100755 --- a/xray-core/files/etc/init.d/xray +++ b/xray-core/files/etc/init.d/xray @@ -2244,7 +2244,7 @@ start_instance() { } rules_exist() { - [ -n "$(iptables -w -t nat -L -n 2>/dev/null | grep v2r_)" ] && return 0 + [ -n "$(iptables -w -t nat -L -n 2>/dev/null | grep xr_)" ] && return 0 return 1 } From 0b6cb9e64c96194782b09b0d0de112195e1ff5aa Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 17 Nov 2023 17:36:20 +0100 Subject: [PATCH 1178/2059] Compile image for RPI5 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dd3bbf058..89227b20e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w, rpi5] OMR_KERNEL: [5.4, 6.1] runs-on: ubuntu-latest continue-on-error: true From d9c47c8c524219d9756dd25b57d36dcac98d389a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 20 Nov 2023 20:13:17 +0100 Subject: [PATCH 1179/2059] Keep LAN gateway setting when Wizard is saved --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 47a95a5f2..05476a980 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -478,6 +478,7 @@

    + "> ">
    From d5aaf2393801e92fb0478f6ef92689d175830d26 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 21 Nov 2023 15:17:29 +0100 Subject: [PATCH 1180/2059] Disable IPv6 delegation on default WAN interfaces and created via Wizard, fix typo on z8102 network config --- .../luasrc/controller/openmptcprouter.lua | 1 + openmptcprouter/files/etc/uci-defaults/1920-omr-network | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 018b3365f..8d07c1d95 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -378,6 +378,7 @@ function wizard_add() end ucic:set("network",intf,"defaultroute",0) ucic:set("network",intf,"peerdns",0) + ucic:set("network",intf,"delegate",0) if ipaddr ~= "" then ucic:set("network",intf,"ipaddr",ipaddr:gsub("%s+", "")) ucic:set("network",intf,"netmask",netmask:gsub("%s+", "")) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index f5a57cee0..4d2572a6e 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -63,6 +63,7 @@ _setup_wan_interface() { set network.$1.ip4table=wan set network.$1.multipath=$3 set network.$1.defaultroute=0 + set network.$1.delegate=0 set network.$1.addlatency=0 set network.${1}_dev=device set network.${1}_dev.name=$2 @@ -380,6 +381,7 @@ if ([ "$board" = "teltonika,rutx" ] || [ "$board" = "teltonika,rutx12" ] || [ "$ set network.modem1.peerdns='0' set network.modem1.multipath='on' set network.modem1.defaultroute='0' + set network.modem1.delegate='0' commit network add_list firewall.@zone[1].network='modem1' commit firewall @@ -395,6 +397,7 @@ if ([ "$board" = "teltonika,rutx" ] || [ "$board" = "teltonika,rutx12" ] || [ "$ set network.modem2.force_link='1' set network.modem2.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' set network.modem2.peerdns='0' + set network.modem2.delegate='0' set network.modem2.multipath='on' set network.modem2.defaultroute='0' set network.modem2.ip4table=wan @@ -438,7 +441,8 @@ if [ "$board" = "z8102ax" ]; then set network.modem1.force_link='1' set network.modem1.device='/sys/devices/platform/11200000.usb/usb1/1-1/1-1.1' set network.modem1.peerdns='0' - set network.modem1.multipath='oncd' + set network.modem1.delegate='0' + set network.modem1.multipath='on' set network.modem1.defaultroute='0' set network.modem2=interface set network.modem2.proto='modemmanager' @@ -449,6 +453,7 @@ if [ "$board" = "z8102ax" ]; then set network.modem2.force_link='1' set network.modem2.device='/sys/devices/platform/11200000.usb/usb1/1-1/1-1.2' set network.modem2.peerdns='0' + set network.modem2.delegate='0' set network.modem2.multipath='on' set network.modem2.defaultroute='0' commit network @@ -456,7 +461,6 @@ if [ "$board" = "z8102ax" ]; then add_list firewall.@zone[1].network='modem2' commit firewall EOF - # /sys/bus/devices/1-1.1 fi # set network.lan.ipaddr='192.168.5.10' # set network.lan.gateway='192.168.5.1' From 9b30e900fc8b9f9cbc7ba0dc6c2fe121aa11e732 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 11:33:48 +0100 Subject: [PATCH 1181/2059] Fix V2Ray default configuration to use MPTCP --- v2ray-core/files/etc/uci-defaults/3010-omr-v2ray | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/v2ray-core/files/etc/uci-defaults/3010-omr-v2ray b/v2ray-core/files/etc/uci-defaults/3010-omr-v2ray index 64d18278d..27b115a15 100644 --- a/v2ray-core/files/etc/uci-defaults/3010-omr-v2ray +++ b/v2ray-core/files/etc/uci-defaults/3010-omr-v2ray @@ -59,6 +59,7 @@ if [ -z "$(uci -q get v2ray.main)" ]; then set v2ray.omrout.s_socks_user_encryption='none' set v2ray.omrout.s_socks_user_alter_id='0' set v2ray.omrout.ss_network='tcp' + set v2ray.omrout.ss_sockopt_mptcp='1' set v2ray.omrout.ss_security='tls' set v2ray.omrout.ss_tls_allow_insecure='1' set v2ray.omrout.ss_tls_disable_system_root='1' @@ -199,7 +200,8 @@ if [ "$(uci -q get v2ray.omrout.s_socks_port)" = "" ]; then fi if [ "$(uci -q get v2ray.omrout.ss_sockopt_mptcp)" = "" ]; then uci -q batch <<-EOF >/dev/null - set v2ray.omr.ss_sockopt_mptcp='1' + set v2ray.omrout.ss_sockopt_mptcp='1' + commit v2ray EOF fi From c207315fb9d5b8ee4510033457a36f6d371226fa Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 11:34:44 +0100 Subject: [PATCH 1182/2059] Fix restart omr-tracker when not available for an interface --- mptcp/files/usr/share/omr/post-tracking.d/010-services | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index 8973c0cca..eab51b480 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -122,7 +122,7 @@ if ([ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.ss fi restart_omrtracker() { - [ -n "$(pgrep -f "omr-tracker $1)" ] && return + [ -n "$(pgrep -f $1)" ] && return config_get multipath "$1" multipath config_get ifenabled "$1" auto [ -z "$multipath" ] || [ "$multipath" = "off" ] && return @@ -135,12 +135,12 @@ config_load network config_foreach restart_omrtracker interface if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then - _log "Can't find omr-tracker-ss, restart omr-tracker..." + _log "Can't find omr-tracker-ss for Shadowsocks libev, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi if [ -f /etc/init.d/shadowsocks-rust ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.rust.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then - _log "Can't find omr-tracker-ss, restart omr-tracker..." + _log "Can't find omr-tracker-ss for Shadowsocks Rust, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi From 9bbd30da5b32e42450edb0728031e5ce39743781 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 14:58:37 +0100 Subject: [PATCH 1183/2059] Fix omr-test-speed when SQM is disabled --- openmptcprouter/files/bin/omr-test-speed | 2 +- openmptcprouter/files/bin/omr-test-speed-server | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 54b761cca..36480fcb6 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -43,7 +43,7 @@ trap : HUP INT TERM if [ -z "$INTERFACE" ]; then curl -4 -o /dev/null $HOST || echo else - /etc/init.d/sqm stop $INTERFACE + [ -n "$(tc qdisc show dev $INTERFACE | grep ingress)" ] && /etc/init.d/sqm stop $INTERFACE domain=$(echo $HOST | awk -F/ '{print $3}') hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ') if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then diff --git a/openmptcprouter/files/bin/omr-test-speed-server b/openmptcprouter/files/bin/omr-test-speed-server index 10ca604e1..74d110d1e 100755 --- a/openmptcprouter/files/bin/omr-test-speed-server +++ b/openmptcprouter/files/bin/omr-test-speed-server @@ -35,7 +35,7 @@ if [ -n "$HOST" ] && [ -n "$PORT" ] && [ -n "$USERNAME" ] && [ -n "$PASSWORD" ]; [ -z "$FASTTEST" ] && echo "Disable SQM bandwidth limit on $INTERFACE" [ -z "$FASTTEST" ] && echo "Download test via server ${SERVER}:" if [ -n "$INTERFACE" ]; then - [ -n "$(tc qdisc | grep $INTERFACE | grep bandwidth)" ] && { + [ -n "$(tc qdisc show dev $INTERFACE | grep bandwidth)" ] && { export SQM_VERBOSITY_MIN=10 export SQM_VERBOSITY_MAX=0 export SQM_SYSLOG=1 From fc01eb03815481c23675632ac419b11c59a06cfb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 16:39:28 +0100 Subject: [PATCH 1184/2059] Remove not needed file for sqm-autorate --- .../share/sqm-autorate/cake-autorate.sh.anc | 2270 ----------------- .../usr/share/sqm-autorate/defaults.sh.anc | 209 -- 2 files changed, 2479 deletions(-) delete mode 100755 sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc delete mode 100755 sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc diff --git a/sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc b/sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc deleted file mode 100755 index 68edafd1c..000000000 --- a/sqm-autorate/files/usr/share/sqm-autorate/cake-autorate.sh.anc +++ /dev/null @@ -1,2270 +0,0 @@ -#!/bin/bash - -# cake-autorate automatically adjusts CAKE bandwidth(s) -# in dependence on: a) receive and transmit transfer rates; and b) latency -# (or can just be used to monitor and log transfer rates and latency) - -# requires: bash; and one of the supported ping binaries - -# each cake-autorate instance must be configured using a corresponding config file - -# Project homepage: https://github.com/lynxthecat/cake-autorate -# Licence details: https://github.com/lynxthecat/cake-autorate/blob/master/LICENCE.md - -# Author and maintainer: lynxthecat -# Contributors: rany2; moeller0; richb-hanover - -cake_autorate_version="2.0.0" - -## cake-autorate uses multiple asynchronous processes including: -## main - main process -## monitor_achieved_rates - monitor network transfer rates -## maintain_pingers - manage pingers and active reflectors -## parse_${pinger_binary} - control and parse ping responses -## parse_preprocessor - prepend field for parse_${pinger_binary} -## maintain_log_file - maintain and rotate log file -## -## IPC is facilitated via FIFOs in the form of anonymous pipes -## accessible via fds in the form: ${process_name_fd} -## thereby to enable transferring instructions and data between processes - -# Initialize file descriptors -## -1 signifies that the log file fd will not be used and -## that the log file will be written to directly -log_fd=-1 -exec {main_fd}<> <(:) -exec {monitor_achieved_rates_fd}<> <(:) -exec {maintain_pingers_fd}<> <(:) -# pinger_fds are set below in dependence upon ping binary and number of pingers - -# process pids are stored below in the form -# proc_pids['process_identifier']=${!} -declare -A proc_pids - -# Bash correctness options -## Disable globbing (expansion of *). -set -f -## Forbid using unset variables. -set -u -## The exit status of a pipeline is the status of the last -## command to exit with a non-zero status, or zero if no -## command exited with a non-zero status. -set -o pipefail - -## Errors are intercepted via intercept_stderr below -## and sent to the log file and system log - -# Possible performance improvement -export LC_ALL=C - -# Set PREFIX -PREFIX=/root/cake-autorate - -# shellcheck source=lib.sh -. "${PREFIX}/lib.sh" -# shellcheck source=defaults.sh -. "${PREFIX}/defaults.sh" -# get valid config overrides -mapfile -t valid_config_entries < <(grep -E '^[^(#| )].*=' "${PREFIX}/defaults.sh" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') - -trap cleanup_and_killall INT TERM EXIT - -cleanup_and_killall() -{ - # Do not fail on error for this critical cleanup code - set +e - - trap true INT TERM EXIT - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - log_msg "INFO" "Stopping cake-autorate with PID: ${BASHPID} and config: ${config_path}" - - log_msg "INFO" "Killing all background processes and cleaning up temporary files." - - printf "TERMINATE\n" >&"${maintain_pingers_fd}" - printf "TERMINATE\n" >&"${monitor_achieved_rates_fd}" - - [[ -d "${run_path}" ]] && rm -r "${run_path}" - rmdir /var/run/cake-autorate 2>/dev/null - - # give some time for processes to gracefully exit - sleep_s 1 - - # terminate any processes that remain, save for main and intercept_stderr - unset "proc_pids[main]" - intercept_stderr_pid="${proc_pids[intercept_stderr]:-}" - if [[ -n "${intercept_stderr_pid}" ]] - then - unset "proc_pids[intercept_stderr]" - fi - terminate "${proc_pids[@]}" - - # restore original stderr, and terminate intercept_stderr - if [[ -n "${intercept_stderr_pid}" ]] - then - exec 2>&"${original_stderr_fd}" - terminate "${intercept_stderr_pid}" - fi - - log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}" - - trap - INT TERM EXIT - exit -} - -log_msg() -{ - # send logging message to terminal, log file fifo, log file and/or system logger - - local type="${1}" - local msg="${2}" - local instance_id="${instance_id:-"unknown"}" - local log_timestamp=${EPOCHREALTIME} - - case ${type} in - - DEBUG) - ((debug == 0)) && return # skip over DEBUG messages where debug disabled - ((log_DEBUG_messages_to_syslog)) && ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" - ;; - - ERROR) - ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" - ;; - - SYSLOG) - ((use_logger)) && logger -t "cake-autorate.${instance_id}" "INFO: ${log_timestamp} ${msg}" - ;; - - *) - ;; - esac - - # Output to the log file fifo if available (for rotation handling) - # else output directly to the log file - if (( log_fd >= 0 )) - then - ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >&"${log_fd}" - else - ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >> "${log_file_path}" - fi - - ((terminal)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" -} - -print_headers() -{ - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - header="DATA_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; DL_LOAD_PERCENT; UL_LOAD_PERCENT; RTT_TIMESTAMP; REFLECTOR; SEQUENCE; DL_OWD_BASELINE; DL_OWD_US; DL_OWD_DELTA_EWMA_US; DL_OWD_DELTA_US; DL_ADJ_DELAY_THR; UL_OWD_BASELINE; UL_OWD_US; UL_OWD_DELTA_EWMA_US; UL_OWD_DELTA_US; UL_ADJ_DELAY_THR; SUM_DL_DELAYS; SUM_UL_DELAYS; DL_LOAD_CONDITION; UL_LOAD_CONDITION; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" - ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" - ((terminal)) && printf '%s\n' "${header}" - - header="LOAD_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" - ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" - ((terminal)) && printf '%s\n' "${header}" - - header="REFLECTOR_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; REFLECTOR; MIN_SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_DELTA_US; SUM_OWD_BASELINES_DELTA_THR_US; MIN_DL_DELTA_EWMA_US; DL_DELTA_EWMA_US; DL_DELTA_EWMA_DELTA_US; DL_DELTA_EWMA_DELTA_THR; MIN_UL_DELTA_EWMA_US; UL_DELTA_EWMA_US; UL_DELTA_EWMA_DELTA_US; UL_DELTA_EWMA_DELTA_THR" - ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" - ((terminal)) && printf '%s\n' "${header}" -} - -# MAINTAIN_LOG_FILE + HELPER FUNCTIONS - -rotate_log_file() -{ - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - if [[ -f ${log_file_path} ]] - then - cat "${log_file_path}" > "${log_file_path}.old" - true > "${log_file_path}" - fi - - ((output_processing_stats)) && print_headers - t_log_file_start_us=${EPOCHREALTIME/./} - get_log_file_size_bytes -} - -reset_log_file() -{ - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - rm -f "${log_file_path}.old" - true > "${log_file_path}" - - ((output_processing_stats)) && print_headers - t_log_file_start_us=${EPOCHREALTIME/./} - get_log_file_size_bytes -} - -generate_log_file_scripts() -{ - cat > "${run_path}/log_file_export" <<- EOT - #!/bin/bash - - timeout_s=\${1:-20} - - if kill -USR1 "${proc_pids['maintain_log_file']}" - then - printf "Successfully signalled maintain_log_file process to request log file export.\n" - else - printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 - exit 1 - fi - rm -f "${run_path}/last_log_file_export" - - read_try=0 - - while [[ ! -f "${run_path}/last_log_file_export" ]] - do - sleep 1 - if (( ++read_try >= \${timeout_s} )) - then - printf "ERROR: Timeout (\${timeout_s}s) reached before new log file export identified.\n" >&2 - exit 1 - fi - done - - read -r log_file_export_path < "${run_path}/last_log_file_export" - - printf "Log file export complete.\n" - - printf "Log file available at location: " - printf "\${log_file_export_path}\n" - EOT - - cat > "${run_path}/log_file_reset" <<- EOT - #!/bin/bash - - if kill -USR2 "${proc_pids['maintain_log_file']}" - then - printf "Successfully signalled maintain_log_file process to request log file reset.\n" - else - printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 - exit 1 - fi - EOT - - chmod +x "${run_path}/log_file_export" "${run_path}/log_file_reset" -} - -export_log_file() -{ - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - printf -v log_file_export_datetime '%(%Y_%m_%d_%H_%M_%S)T' - log_file_export_path="${log_file_path/.log/_${log_file_export_datetime}.log}" - log_msg "DEBUG" "Exporting log file with path: ${log_file_path/.log/_${log_file_export_datetime}.log}" - - # Now export with or without compression to the appropriate export path - if ((log_file_export_compress)) - then - log_file_export_path="${log_file_export_path}.gz" - if [[ -f "${log_file_path}.old" ]] - then - gzip -c "${log_file_path}.old" > "${log_file_export_path}" - gzip -c "${log_file_path}" >> "${log_file_export_path}" - else - gzip -c "${log_file_path}" > "${log_file_export_path}" - fi - else - if [[ -f "${log_file_path}.old" ]] - then - cp "${log_file_path}.old" "${log_file_export_path}" - cat "${log_file_path}" >> "${log_file_export_path}" - else - cp "${log_file_path}" "${log_file_export_path}" - fi - fi - - printf '%s' "${log_file_export_path}" > "${run_path}/last_log_file_export" -} - -flush_log_fd() -{ - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - while read -r -t 0 -u "${log_fd}" - do - read -r -u "${log_fd}" log_line - printf '%s\n' "${log_line}" >> "${log_file_path}" - done -} - -get_log_file_size_bytes() -{ - log_file_size_bytes=$(wc -c "${log_file_path}" 2>/dev/null | awk '{print $1}') - log_file_size_bytes=${log_file_size_bytes:-0} -} - -kill_maintain_log_file() -{ - trap - TERM EXIT - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - flush_log_fd - exit -} - -maintain_log_file() -{ - trap '' INT - trap 'kill_maintain_log_file' TERM EXIT - trap 'export_log_file' USR1 - trap 'reset_log_file_signalled=1' USR2 - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - reset_log_file_signalled=0 - t_log_file_start_us=${EPOCHREALTIME/./} - - get_log_file_size_bytes - - while read -r -u "${log_fd}" log_line - do - - printf '%s\n' "${log_line}" >> "${log_file_path}" - - # Verify log file size < configured maximum - # The following two lines with costly call to 'du': - # read log_file_size_bytes< <(du -b ${log_file_path}/cake-autorate.log) - # log_file_size_bytes=${log_file_size_bytes//[!0-9]/} - # can be more efficiently handled with this line: - ((log_file_size_bytes=log_file_size_bytes+${#log_line}+1)) - - # Verify log file time < configured maximum - if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) - then - - log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so flushing and rotating log file." - flush_log_fd - rotate_log_file - elif (( log_file_size_bytes > log_file_max_size_bytes )) - then - log_file_size_KB=$((log_file_size_bytes/1024)) - log_msg "DEBUG" "log file size: ${log_file_size_KB} KB has exceeded configured maximum: ${log_file_max_size_KB} KB so flushing and rotating log file." - flush_log_fd - rotate_log_file - elif (( reset_log_file_signalled )) - then - log_msg "DEBUG" "received log file reset signal so flushing and resetting log file." - flush_log_fd - reset_log_file - reset_log_file_signalled=0 - fi - - done -} - -update_shaper_rate() -{ - local direction="${1}" # 'dl' or 'ul' - - case "${load_condition["${direction}"]}" in - - # upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period - ul*sss) - shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" - ;; - # download Starlink satelite switching compensation, so drop down to base rate for download through switching period - dl*sss) - shaper_rate_kbps["${direction}"]=$(( shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"] ? base_shaper_rate_kbps["${direction}"] : shaper_rate_kbps["${direction}"] )) - ;; - # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period - *bb*) - if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) - then - adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps["${direction}"]*achieved_rate_adjust_down_bufferbloat)/1000 )) - adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_bufferbloat)/1000 )) - shaper_rate_kbps["${direction}"]=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps["${direction}"] && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) - t_last_bufferbloat_us["${direction}"]="${EPOCHREALTIME/./}" - fi - ;; - # high load, so increase rate providing not inside bufferbloat refractory period - *high*) - if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) - then - shaper_rate_kbps["${direction}"]=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_high)/1000 )) - fi - ;; - # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate - *low*|*idle*) - if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )) - then - - if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])) - then - decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_load_low)/1000 )) - shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) - elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])) - then - decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_low)/1000 )) - shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) - fi - - t_last_decay_us["${direction}"]="${EPOCHREALTIME/./}" - fi - ;; - *) - log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in update_shaper_rate" - kill $$ 2>/dev/null - ;; - esac - # make sure to only return rates between cur_min_rate and cur_max_rate - ((shaper_rate_kbps["${direction}"] < min_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" - ((shaper_rate_kbps["${direction}"] > max_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${max_shaper_rate_kbps[${direction}]}" -} - -monitor_achieved_rates() -{ - trap '' INT - - # track rx and tx bytes transfered and divide by time since last update - # to determine achieved dl and ul transfer rates - - local rx_bytes_path="${1}" - local tx_bytes_path="${2}" - local monitor_achieved_rates_interval_us="${3}" # (microseconds) - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - compensated_monitor_achieved_rates_interval_us="${monitor_achieved_rates_interval_us}" - - [[ -f "${rx_bytes_path}" ]] && { read -r prev_rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || prev_rx_bytes=0 - [[ -f "${tx_bytes_path}" ]] && { read -r prev_tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || prev_tx_bytes=0 - - sleep_duration_s=0 - t_start_us=0 - - declare -A achieved_rate_kbps - declare -A load_percent - - while true - do - t_start_us="${EPOCHREALTIME/./}" - - while read -r -t 0 -u "${monitor_achieved_rates_fd}" - do - unset command - read -r -u "${monitor_achieved_rates_fd}" -a command - case "${command[0]:-}" in - - SET_VAR) - if [[ "${#command[@]}" -eq 3 ]] - then - export -n "${command[1]}=${command[2]}" - fi - ;; - SET_ARRAY_ELEMENT) - if [[ "${#command[@]}" -eq 4 ]] - then - declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" - fi - ;; - TERMINATE) - log_msg "DEBUG" "Terminating monitor_achieved_rates." - exit - ;; - *) - : - ;; - esac - done - - # If rx/tx bytes file exists, read it in, otherwise set to prev_bytes - # This addresses interfaces going down and back up - [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes="${prev_rx_bytes}" - [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes="${prev_tx_bytes}" - - achieved_rate_kbps[dl]=$(( (8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us )) - achieved_rate_kbps[ul]=$(( (8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us )) - - ((achieved_rate_kbps[dl]<0)) && achieved_rate_kbps[dl]=0 - ((achieved_rate_kbps[ul]<0)) && achieved_rate_kbps[ul]=0 - - printf "SET_ARRAY_ELEMENT achieved_rate_kbps dl %s\n" "${achieved_rate_kbps[dl]}" >&"${main_fd}" - printf "SET_ARRAY_ELEMENT achieved_rate_kbps ul %s\n" "${achieved_rate_kbps[ul]}" >&"${main_fd}" - - load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) - load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) - - for pinger_fd in "${pinger_fds[@]:?}" - do - printf "SET_ARRAY_ELEMENT load_percent dl %s\n" "${load_percent[dl]}" >&"${pinger_fd}" - printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}" - done - - if ((output_load_stats)) - then - - printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" - log_msg "LOAD" "${load_stats}" - fi - - prev_rx_bytes="${rx_bytes}" - prev_tx_bytes="${tx_bytes}" - - compensated_monitor_achieved_rates_interval_us=$(( monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) - - sleep_remaining_tick_time "${t_start_us}" "${compensated_monitor_achieved_rates_interval_us}" - - done -} - - -classify_load() -{ - # classify the load according to high/low/idle and add _delayed if delayed - # thus ending up with high_delayed, low_delayed, etc. - local direction="${1}" - - if (( load_percent["${direction}"] > high_load_thr_percent )) - then - load_condition["${direction}"]="high" - elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )) - then - load_condition["${direction}"]="low" - else - load_condition["${direction}"]="idle" - fi - - ((bufferbloat_detected["${direction}"])) && load_condition["${direction}"]="${load_condition[${direction}]}_bb" - - if ((sss_compensation)) - then - # shellcheck disable=SC2154 - for sss_time_us in "${sss_times_us[@]}" - do - ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) - if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )) - then - load_condition["${direction}"]="${load_condition[${direction}]}_sss" - break - fi - done - fi - - load_condition["${direction}"]="${direction}_${load_condition[${direction}]}" -} - -# MAINTAIN PINGERS + ASSOCIATED HELPER FUNCTIONS - -parse_preprocessor() -{ - # prepend REFLECTOR_RESPONSE and append timestamp as a checksum - while read -r timestamp remainder - do - printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" - done -} - -parse_tsping() -{ - trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT - - local parse_id="${1}" - local reflectors=("${@:2}") - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - declare -A dl_owd_baselines_us - declare -A ul_owd_baselines_us - declare -A dl_owd_delta_ewmas_us - declare -A ul_owd_delta_ewmas_us - - for (( reflector=0; reflector >(parse_preprocessor) - parse_preprocessor_pid="${!}" - printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" - # accommodate present tsping interval/sleep handling to prevent ping flood with only one pinger - tsping_sleep_time=$(( no_pingers == 1 ? ping_response_interval_ms : 0 )) - ${ping_prefix_string} tsping ${ping_extra_args} --print-timestamps --machine-readable=' ' --sleep-time "${tsping_sleep_time}" --target-spacing "${ping_response_interval_ms}" "${reflectors[@]:0:${no_pingers}}" 2>/dev/null >&"${parse_preprocessor_fd}" & - pinger_pid="${!}" - printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" - continue - ;; - - KILL_PINGER) - - terminate "${pinger_pid}" "${parse_preprocessor_pid}" - exec {parse_preprocessor_fd}>&- - continue - ;; - - SET_REFLECTORS) - - read -r -a reflectors <<< "${command[@]:1}" - log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" - for (( reflector=0; reflector 50 mins, immediately reset the baselines to the new dl_owd_us and ul_owd_us. - # - # Happilly, the sum of dl_owd_baseline_us and ul_owd_baseline_us will roughly equal rtt_baseline_us. - # And since Transmit is approximately equal to Received, RTT is approximately equal to Finished - Originate. - # And thus the sum of dl_owd_baseline_us and ul_owd_baseline_us should not be affected by the rollover/compensation. - # Hence working with this sum, rather than the individual components, is useful for the reflector health check in maintain_pingers(). - - if (( (${dl_owd_delta_us#-} + ${ul_owd_delta_us#-}) < 3000000000 )) - then - - dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) - ul_alpha=$(( ul_owd_us >= ul_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) - - ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" - ewma_iteration "${ul_owd_us}" "${ul_alpha}" "ul_owd_baselines_us[${reflector}]" - - dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) - ul_owd_delta_us=$(( ul_owd_us - ul_owd_baselines_us[${reflector}] )) - else - dl_owd_baselines_us[${reflector}]=${dl_owd_us} - ul_owd_baselines_us[${reflector}]=${ul_owd_us} - - dl_owd_delta_us=0 - ul_owd_delta_us=0 - fi - - if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) - then - ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" - ewma_iteration "${ul_owd_delta_us}" "${alpha_delta_ewma}" "ul_owd_delta_ewmas_us[${reflector}]" - fi - - printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" - - timestamp_us="${timestamp//[.]}" - - printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" - fi - done -} - -parse_fping() -{ - trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT - - local parse_id="${1}" - - local reflectors=("${@:2}") - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - declare -A dl_owd_baselines_us - declare -A ul_owd_baselines_us - declare -A dl_owd_delta_ewmas_us - declare -A ul_owd_delta_ewmas_us - - for (( reflector=0; reflector >(parse_preprocessor) - parse_preprocessor_pid="${!}" - printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" - ${ping_prefix_string} fping ${ping_extra_args} --timestamp --loop --period "${reflector_ping_interval_ms}" --interval "${ping_response_interval_ms}" --timeout 10000 "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${parse_preprocessor_fd}" & - pinger_pid="${!}" - printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" - continue - ;; - - KILL_PINGER) - - terminate "${pinger_pid}" "${parse_preprocessor_pid}" - exec {parse_preprocessor_fd}>&- - continue - ;; - - SET_REFLECTORS) - - read -r -a reflectors <<< "${command[@]:1}" - log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" - for (( reflector=0; reflector= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) - - ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" - ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" - - dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) - ul_owd_delta_us="${dl_owd_delta_us}" - - if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) - then - ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" - ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" - fi - - timestamp="${timestamp//[\[\]]}0" - - printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" - - timestamp_us="${timestamp//[.]}" - - printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" - fi - done -} -# IPUTILS-PING FUNCTIONS -parse_ping() -{ - trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT - - # ping reflector, maintain baseline and output deltas to a common fifo - - local parse_id="${1}" - local reflector="${2}" - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - declare -A dl_owd_baselines_us - declare -A ul_owd_baselines_us - declare -A dl_owd_delta_ewmas_us - declare -A ul_owd_delta_ewmas_us - - dl_owd_baselines_us["${reflector}"]=100000 - ul_owd_baselines_us["${reflector}"]=100000 - dl_owd_delta_ewmas_us["${reflector}"]=0 - ul_owd_delta_ewmas_us["${reflector}"]=0 - - declare -A load_percent - load_percent[dl]=0 - load_percent[ul]=0 - - while true - do - unset command - read -r -u "${pinger_fds[pinger]}" -a command - if [[ "${command-}" ]] - then - case "${command[0]}" in - - REFLECTOR_RESPONSE) - - read -r timestamp _ _ _ reflector seq_rtt <<< "${command[@]:1}" - checksum="${command[*]: -1}" - ;; - - START_PINGER) - - exec {parse_preprocessor_fd}> >(parse_preprocessor) - parse_preprocessor_pid="${!}" - printf "SET_PROC_PID %s %s\n" "proc_pids ${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" - ${ping_prefix_string} ping ${ping_extra_args} -D -i "${reflector_ping_interval_s}" "${reflector}" 2> /dev/null >&"${parse_preprocessor_fd}" & - pinger_pid="${!}" - printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" - continue - ;; - - KILL_PINGER) - - terminate "${pinger_pid}" "${parse_preprocessor_pid}" - exec {parse_preprocessor_fd}>&- - continue - ;; - - SET_REFLECTOR) - - if [[ "${#command[@]}" -eq 2 ]] - then - reflector="${command[1]}" - log_msg "DEBUG" "Read in new reflector: ${reflector}" - dl_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]:-100000}" - ul_owd_baselines_us["${reflector}"]="${ul_owd_baselines_us[${reflector}]:-100000}" - dl_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]:-0}" - ul_owd_delta_ewmas_us["${reflector}"]="${ul_owd_delta_ewmas_us[${reflector}]:-0}" - continue - fi - ;; - - SET_VAR) - - if [[ "${#command[@]}" -eq 3 ]] - then - export -n "${command[1]}=${command[2]}" - fi - continue - ;; - - SET_ARRAY_ELEMENT) - - if [[ "${#command[@]}" -eq 4 ]] - then - declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" - fi - continue - ;; - - TERMINATE) - - log_msg "DEBUG" "Terminating parse_ping." - exit - ;; - - *) - - continue - ;; - - esac - fi - - if [[ "${timestamp:-}" && "${reflector:-}" && "${seq_rtt:-}" && "${checksum:-}" ]] - then - [[ "${checksum}" == "${timestamp}" ]] - # If no match then skip onto the next one - [[ "${seq_rtt}" =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue - - reflector=${reflector//:/} - - seq=${BASH_REMATCH[1]} - - rtt_us=${BASH_REMATCH[3]}000 - rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) - - dl_owd_us=$((rtt_us/2)) - ul_owd_us="${dl_owd_us}" - - dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) - - ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" - ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" - - dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) - ul_owd_delta_us="${dl_owd_delta_us}" - - if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) - then - ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" - ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" - fi - - timestamp="${timestamp//[\[\]]}" - - printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" - - timestamp_us="${timestamp//[.]}" - - printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - - printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" - fi - done -} - -# END OF IPUTILS-PING FUNCTIONS - -# GENERIC PINGER START AND STOP FUNCTIONS - -start_pinger() -{ - local pinger="${1}" - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - case ${pinger_binary} in - - tsping|fping) - pinger=0 - printf "START_PINGER\n" >&"${pinger_fds[pinger]}" - ;; - ping) - sleep_until_next_pinger_time_slot "${pinger}" - printf "START_PINGER\n" >&"${pinger_fds[pinger]}" - ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null - ;; - esac -} - -start_pingers() -{ - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - case ${pinger_binary} in - - tsping|fping) - start_pinger 0 - ;; - ping) - for ((pinger=0; pinger < no_pingers; pinger++)) - do - start_pinger "${pinger}" - done - ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null - ;; - esac -} - -sleep_until_next_pinger_time_slot() -{ - # wait until next pinger time slot and start pinger in its slot - # this allows pingers to be stopped and started (e.g. during sleep or reflector rotation) - # whilst ensuring pings will remain spaced out appropriately to maintain granularity - - local pinger="${1}" - - t_start_us=${EPOCHREALTIME/./} - time_to_next_time_slot_us=$(( (reflector_ping_interval_us-(t_start_us-pingers_t_start_us)%reflector_ping_interval_us) + pinger*ping_response_interval_us )) - sleep_remaining_tick_time "${t_start_us}" "${time_to_next_time_slot_us}" -} - -kill_pinger() -{ - local pinger="${1}" - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - case "${pinger_binary}" in - tsping|fping) - pinger=0 - ;; - - *) - ;; - esac - - printf "KILL_PINGER\n" >&"${pinger_fds[pinger]}" -} - -kill_pingers() -{ - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - case "${pinger_binary}" in - - tsping|fping) - log_msg "DEBUG" "Killing ${pinger_binary} instance." - kill_pinger 0 - ;; - ping) - for (( pinger=0; pinger < no_pingers; pinger++)) - do - log_msg "DEBUG" "Killing pinger instance: ${pinger}" - kill_pinger "${pinger}" - done - ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null - ;; - esac -} - -replace_pinger_reflector() -{ - # pingers always use reflectors[0]..[no_pingers-1] as the initial set - # and the additional reflectors are spare reflectors should any from initial set go stale - # a bad reflector in the initial set is replaced with ${reflectors[no_pingers]} - # ${reflectors[no_pingers]} is then unset - # and the the bad reflector moved to the back of the queue (last element in ${reflectors[]}) - # and finally the indices for ${reflectors} are updated to reflect the new order - - local pinger="${1}" - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - if ((no_reflectors > no_pingers)) - then - log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}." - kill_pinger "${pinger}" - bad_reflector=${reflectors[pinger]} - # overwrite the bad reflector with the reflector that is next in the queue (the one after 0..${no_pingers}-1) - reflectors[pinger]=${reflectors[no_pingers]} - # remove the new reflector from the list of additional reflectors beginning from ${reflectors[no_pingers]} - unset "reflectors[no_pingers]" - # bad reflector goes to the back of the queue - reflectors+=("${bad_reflector}") - # reset array indices - mapfile -t reflectors < <(for i in "${reflectors[@]}"; do printf '%s\n' "${i}"; done) - # set up the new pinger with the new reflector and retain pid - case ${pinger_binary} in - - tsping|fping) - printf "SET_REFLECTORS %s\n" "${reflectors[*]:0:${no_pingers}}" >&"${pinger_fds[0]}" - ;; - ping) - printf "SET_REFLECTOR %s\n" "${reflectors[pinger]}" >&"${pinger_fds[pinger]}" - ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null - ;; - esac - start_pinger "${pinger}" - else - log_msg "DEBUG" "No additional reflectors specified so just retaining: ${reflectors[pinger]}." - fi - - log_msg "DEBUG" "Resetting reflector offences associated with reflector: ${reflectors[pinger]}." - declare -n reflector_offences="reflector_${pinger}_offences" - for ((i=0; i&"${pinger_fds[0]}" - ;; - ping) - for((pinger=0; pinger < no_pingers; pinger++)) - do - printf "TERMINATE\n" >&"${pinger_fds[pinger]}" - done - ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null - ;; - esac - - exit -} - -change_state_maintain_pingers() -{ - local maintain_pingers_next_state="${1:-unset}" - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - case "${maintain_pingers_next_state}" in - - START|STOP|PAUSED|RUNNING) - - if [[ "${maintain_pingers_state}" == "${maintain_pingers_next_state}" ]] - then - log_msg "ERROR" "Received request to change maintain_pingers state to existing state." - return - fi - - log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" - maintain_pingers_state=${maintain_pingers_next_state} - ;; - - *) - - log_msg "ERROR" "Received unrecognized state change request: ${maintain_pingers_next_state}. Exiting now." - kill $$ 2>/dev/null - ;; - esac -} - -maintain_pingers() -{ - # this initiates the pingers and monitors reflector health, rotating reflectors as necessary - - trap '' INT - trap 'kill_maintain_pingers' TERM EXIT - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - declare -A dl_owd_baselines_us - declare -A ul_owd_baselines_us - declare -A dl_owd_delta_ewmas_us - declare -A ul_owd_delta_ewmas_us - declare -A last_timestamp_reflectors_us - - err_silence=0 - reflector_offences_idx=0 - pingers_active=0 - - pingers_t_start_us="${EPOCHREALTIME/./}" - t_last_reflector_replacement_us="${EPOCHREALTIME/./}" - t_last_reflector_comparison_us="${EPOCHREALTIME/./}" - - for ((reflector=0; reflector < no_reflectors; reflector++)) - do - last_timestamp_reflectors_us["${reflectors[reflector]}"]="${pingers_t_start_us}" - done - - # For each pinger initialize record of offences - for ((pinger=0; pinger < no_pingers; pinger++)) - do - # shellcheck disable=SC2178 - declare -n reflector_offences="reflector_${pinger}_offences" - for ((i=0; i&"${main_fd}" - ;; - fping) - parse_fping "parse_fping" "${reflectors[@]:0:${no_pingers}}" & - printf "SET_PROC_PID proc_pids parse_fping %s\n" "${!}" >&"${main_fd}" - ;; - ping) - for((pinger=0; pinger < no_pingers; pinger++)) - do - parse_ping "parse_ping_${pinger}" "${reflectors[pinger]}" & - printf "SET_PROC_PID proc_pids %s %s\n" "parse_ping_${pinger}" "${!}" >&"${main_fd}" - done - ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null - ;; - esac - - - # Reflector maintenance loop - verifies reflectors have not gone stale and rotates reflectors as necessary - while true - do - t_start_us="${EPOCHREALTIME/./}" - - while read -r -t 0 -u "${maintain_pingers_fd}" - do - unset command - read -r -u "${maintain_pingers_fd}" -a command - case "${command[0]:-}" in - - CHANGE_STATE) - if [[ "${#command[@]}" -eq 2 ]] - then - change_state_maintain_pingers "${command[1]}" - # break out of reading any new IPC commands to handle next state - # if pingers need to be started or stopped - case "${command[1]}" in - START|STOP) - break - ;; - *) - : - ;; - esac - fi - ;; - SET_ARRAY_ELEMENT) - if [[ "${#command[@]}" -eq 4 ]] - then - declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" - fi - ;; - SET_VAR) - if [[ "${#command[@]}" -eq 3 ]] - then - export -n "${command[1]}=${command[2]}" - fi - ;; - TERMINATE) - log_msg "DEBUG" "Terminating monitor_achieved_rates." - exit - ;; - *) - : - ;; - esac - done - - case "${maintain_pingers_state}" in - - START) - if ((pingers_active==0)) - then - start_pingers - pingers_active=1 - fi - change_state_maintain_pingers "RUNNING" - ;; - - STOP) - if ((pingers_active)) - then - kill_pingers - pingers_active=0 - fi - change_state_maintain_pingers "PAUSED" - ;; - - PAUSED) - ;; - - RUNNING) - - if (( t_start_us>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) - then - pinger=$((RANDOM%no_pingers)) - log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." - replace_pinger_reflector "${pinger}" - t_last_reflector_replacement_us=${EPOCHREALTIME/./} - continue - fi - - if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )) - then - - t_last_reflector_comparison_us=${EPOCHREALTIME/./} - - [[ "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" ]] || continue - - min_sum_owd_baselines_us=$(( dl_owd_baselines_us[${reflectors[0]}] + ul_owd_baselines_us[${reflectors[0]}] )) - min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[0]}]}" - min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[0]}]}" - - for ((pinger=0; pinger < no_pingers; pinger++)) - do - [[ "${dl_owd_baselines_us[${reflectors[pinger]}]:-}" && "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" && "${ul_owd_baselines_us[${reflectors[pinger]}]:-}" && "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" ]] || continue 2 - - sum_owd_baselines_us[pinger]=$(( dl_owd_baselines_us[${reflectors[pinger]}] + ul_owd_baselines_us[${reflectors[pinger]}] )) - (( sum_owd_baselines_us[pinger] < min_sum_owd_baselines_us )) && min_sum_owd_baselines_us="${sum_owd_baselines_us[pinger]}" - (( dl_owd_delta_ewmas_us[${reflectors[pinger]}] < min_dl_owd_delta_ewma_us )) && min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" - (( ul_owd_delta_ewmas_us[${reflectors[pinger]}] < min_ul_owd_delta_ewma_us )) && min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" - done - - for ((pinger=0; pinger < no_pingers; pinger++)) - do - - sum_owd_baselines_delta_us=$(( sum_owd_baselines_us[pinger] - min_sum_owd_baselines_us )) - dl_owd_delta_ewma_delta_us=$(( dl_owd_delta_ewmas_us[${reflectors[pinger]}] - min_dl_owd_delta_ewma_us )) - ul_owd_delta_ewma_delta_us=$(( ul_owd_delta_ewmas_us[${reflectors[pinger]}] - min_ul_owd_delta_ewma_us )) - - if ((output_reflector_stats)) - then - printf -v reflector_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${reflectors[pinger]}" "${min_sum_owd_baselines_us}" "${sum_owd_baselines_us[pinger]}" "${sum_owd_baselines_delta_us}" "${reflector_sum_owd_baselines_delta_thr_us}" "${min_dl_owd_delta_ewma_us}" "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${dl_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" "${min_ul_owd_delta_ewma_us}" "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${ul_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" - log_msg "REFLECTOR" "${reflector_stats}" - fi - - if (( sum_owd_baselines_delta_us > reflector_sum_owd_baselines_delta_thr_us )) - then - log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} sum_owd_baselines_us exceeds the minimum by set threshold." - replace_pinger_reflector "${pinger}" - continue 2 - fi - - if (( dl_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) - then - log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} dl_owd_delta_ewma_us exceeds the minimum by set threshold." - replace_pinger_reflector "${pinger}" - continue 2 - fi - - if (( ul_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) - then - log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} ul_owd_delta_ewma_us exceeds the minimum by set threshold." - replace_pinger_reflector "${pinger}" - continue 2 - fi - done - - fi - - replace_pinger_reflector_enabled=1 - - for ((pinger=0; pinger < no_pingers; pinger++)) - do - # shellcheck disable=SC2178 - declare -n reflector_offences="reflector_${pinger}_offences" - - (( reflector_offences[reflector_offences_idx] )) && ((sum_reflector_offences[pinger]--)) - # shellcheck disable=SC2154 - reflector_offences[reflector_offences_idx]=$(( (${EPOCHREALTIME/./}-last_timestamp_reflectors_us[${reflectors[pinger]}]) > reflector_response_deadline_us ? 1 : 0 )) - - if (( reflector_offences[reflector_offences_idx] )) - then - ((sum_reflector_offences[pinger]++)) - log_msg "DEBUG" "no ping response from reflector: ${reflectors[pinger]} within reflector_response_deadline: ${reflector_response_deadline_s}s" - log_msg "DEBUG" "reflector=${reflectors[pinger]}, sum_reflector_offences=${sum_reflector_offences[pinger]} and reflector_misbehaving_detection_thr=${reflector_misbehaving_detection_thr}" - fi - - if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )) - then - - log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving." - if ((replace_pinger_reflector_enabled)) - then - replace_pinger_reflector "${pinger}" - replace_pinger_reflector_enabled=0 - else - log_msg "DEBUG" "Warning: skipping replacement of reflector: ${reflectors[pinger]} given prior replacement within this reflector health check cycle." - fi - fi - done - ((reflector_offences_idx=(reflector_offences_idx+1)%reflector_misbehaving_detection_window)) - ;; - *) - log_msg "ERROR" "Unrecognized maintain pingers state: ${maintain_pingers_state}." - log_msg "ERROR" "Setting state to RUNNING" - maintain_pingers_next_state="RUNNING" - change_maintain_pingers_state - ;; - esac - - sleep_remaining_tick_time "${t_start_us}" "${reflector_health_check_interval_us}" - done -} - -set_shaper_rate() -{ - # fire up tc and update max_wire_packet_compensation if there are rates to change for the given direction - - local direction="${1}" # 'dl' or 'ul' - - if (( shaper_rate_kbps["${direction}"] != last_shaper_rate_kbps["${direction}"] )) - then - ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface[${direction}]} cake bandwidth ${shaper_rate_kbps[${direction}]}Kbit" - - if ((adjust_shaper_rate["${direction}"])) - then - tc qdisc change root dev "${interface[${direction}]}" cake bandwidth "${shaper_rate_kbps[${direction}]}Kbit" 2> /dev/null - else - ((output_cake_changes)) && log_msg "DEBUG" "adjust_${direction}_shaper_rate set to 0 in config, so skipping the corresponding tc qdisc change call." - fi - - printf "SET_ARRAY_ELEMENT shaper_rate_kbps ${direction} %s\n" "${shaper_rate_kbps[${direction}]}" >&"${monitor_achieved_rates_fd}" - last_shaper_rate_kbps["${direction}"]="${shaper_rate_kbps[${direction}]}" - - update_max_wire_packet_compensation - fi -} - -set_min_shaper_rates() -{ - log_msg "DEBUG" "Enforcing minimum shaper rates." - shaper_rate_kbps[dl]=${min_dl_shaper_rate_kbps} - shaper_rate_kbps[ul]=${min_ul_shaper_rate_kbps} - set_shaper_rate "dl" - set_shaper_rate "ul" -} - -get_max_wire_packet_size_bits() -{ - local interface="${1}" - local -n max_wire_packet_size_bits="${2}" - - read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" - [[ $(tc qdisc show dev "${interface}") =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] - max_wire_packet_size_bits=$(( 8*(max_wire_packet_size_bits+BASH_REMATCH[2]) )) - # atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits - [[ "${BASH_REMATCH[1]:-}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*((max_wire_packet_size_bits+376)/384) )) -} - -update_max_wire_packet_compensation() -{ - # Compensate for delays imposed by active traffic shaper - # This will serve to increase the delay thr at rates below around 12Mbit/s - - # compensated OWD delay thresholds in microseconds - compensated_dl_delay_thr_us=$(( dl_delay_thr_us + (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] )) - compensated_ul_delay_thr_us=$(( ul_delay_thr_us + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) - - printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" - printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" - - max_wire_packet_rtt_us=$(( (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) - - printf "SET_VAR max_wire_packet_rtt_us %s\n" "${max_wire_packet_rtt_us}" >&"${maintain_pingers_fd}" -} - -verify_ifs_up() -{ - # Check the rx/tx paths exist and give extra time for ifb's to come up if needed - # This will block if ifs never come up - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - while [[ ! -f ${rx_bytes_path} || ! -f ${tx_bytes_path} ]] - do - [[ ! -f ${rx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured download interface: '${dl_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." - [[ ! -f ${tx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured upload interface: '${ul_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." - sleep_s "${if_up_check_interval_s}" - done -} - -ewma_iteration() -{ - local value="${1}" - local alpha="${2}" # alpha must be scaled by factor of 1000000 - local -n ewma="${3}" - - prev_ewma=${ewma} - ewma=$(( (alpha*value+(1000000-alpha)*prev_ewma)/1000000 )) -} - -change_state_main() -{ - local main_next_state="${1}" - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - case ${main_next_state} in - - RUNNING|IDLE|STALL) - - if [[ "${main_state}" != "${main_next_state}" ]] - then - log_msg "DEBUG" "Changing main state from: ${main_state} to: ${main_next_state}" - main_state=${main_next_state} - else - log_msg "ERROR" "Received request to change main state to existing state." - fi - ;; - - *) - - log_msg "ERROR" "Received unrecognized main state change request: ${main_next_state}. Exiting now." - kill $$ 2>/dev/null - ;; - esac -} - -intercept_stderr() -{ - # send stderr to log_msg and exit cake-autorate - # use with redirection: exec 2> >(intercept_stderr) - - while read -r error - do - log_msg "ERROR" "${error}" - kill $$ 2>/dev/null - done -} - -# Debug command wrapper -# Inspired by cmd_wrapper of sqm-script -debug_cmd() -{ - # Usage: debug_cmd debug_msg err_silence cmd arg1 arg2, etc. - - # Error messages are output as log_msg ERROR messages - # Or set error_silence=1 to output errors as log_msg DEBUG messages - - local debug_msg="${1}" - local err_silence="${2}" - local cmd="${3}" - - log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - - shift 3 - - local args=("${@}") - - local caller_id - local err_type - - local ret - local stderr - - err_type="ERROR" - - if ((err_silence)) - then - err_type="DEBUG" - fi - - stderr=$(${cmd} "${args[@]}" 2>&1) - ret=${?} - - caller_id=$(caller) - - if ((ret==0)) - then - log_msg "DEBUG" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=SUCCESS" - else - [[ "${err_type}" == "DEBUG" && "${debug}" == "0" ]] && return # if debug disabled, then skip on DEBUG but not on ERROR - - log_msg "${err_type}" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=FAILURE (${ret})" - log_msg "${err_type}" "debug_cmd: LAST ERROR (${stderr})" - - frame=1 - while caller_output=$(caller "${frame}") - do - log_msg "${err_type}" "debug_cmd: CALL CHAIN: ${caller_output}" - ((++frame)) - done - fi -} - -# shellcheck disable=SC1090,SC2311 -validate_config_entry() { - # Must be called before loading config_path into the global scope. - # - # When the entry is invalid, two types are returned with the first type - # being the invalid user type and second type is the default type with - # the user needing to adapt the config file so that the entry uses the - # default type. - # - # When the entry is valid, one type is returned and it will be the - # the type of either the default or user type. However because in that - # case they are both valid. It doesn't matter as they'd both have the - # same type. - - local config_path="${1}" - - local user_type - local valid_type - - user_type=$(unset "${2}" && . "${config_path}" && typeof "${2}") - valid_type=$(typeof "${2}") - - if [[ "${user_type}" != "${valid_type}" ]] - then - printf '%s' "${user_type} ${valid_type}" - return - elif [[ "${user_type}" != "string" ]] - then - printf '%s' "${valid_type}" - return - fi - - # extra validation for string, check for empty string - local -n default_value=${2} - local user_value - user_value=$(. "${config_path}" && local -n x="${2}" && printf '%s' "${x}") - - # if user is empty but default is not, invalid entry - if [[ -z "${user_value}" && -n "${default_value}" ]] - then - printf '%s' "${user_type} ${valid_type}" - else - printf '%s' "${valid_type}" - fi -} - -# ======= Start of the Main Routine ======== - -[[ -t 1 ]] && terminal=1 || terminal=0 - -type logger &> /dev/null && use_logger=1 || use_logger=0 # only perform the test once. - -log_file_path=/var/log/cake-autorate.log - -# *** WARNING: take great care if attempting to alter the run_path! *** -# *** cake-autorate issues mkdir -p ${run_path} and rm -r ${run_path} on exit. *** -run_path=/var/run/cake-autorate/ - -# cake-autorate first argument is config file path -if [[ -n "${1-}" ]] -then - config_path="${1}" -else - config_path="${PREFIX}/config.primary.sh" -fi - -if [[ ! -f "${config_path}" ]] -then - log_msg "ERROR" "No config file found. Exiting now." - exit 1 -fi - -# validate config entries before loading -mapfile -t user_config < <(grep -E '^[^(#| )].*=' "${config_path}" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') -config_error_count=0 -for key in "${user_config[@]}" -do - # Despite the fact that config_file_check is no longer required, - # we make an exemption just in this case as that variable in - # particular does not have any real impact to the operation - # of the script. - [[ "${key}" == "config_file_check" ]] && continue - - # shellcheck disable=SC2076 - if [[ ! " ${valid_config_entries[*]} " =~ " ${key} " ]] - then - ((config_error_count++)) - log_msg "ERROR" "The key: '${key}' in config file: '${config_path}' is not a valid config entry." - else - # shellcheck disable=SC2311 - read -r user supposed <<< "$(validate_config_entry "${config_path}" "${key}")" - if [[ -n "${supposed}" ]] - then - error_msg="The value of '${key}' in config file: '${config_path}' is not a valid value of type: '${supposed}'." - - case "${user}" in - negative-*) error_msg="${error_msg} Also, negative numbers are not supported." ;; - *) ;; - esac - - log_msg "ERROR" "${error_msg}" - unset error_msg - - ((config_error_count++)) - fi - unset user supposed - fi -done -if ((config_error_count)) -then - log_msg "ERROR" "The config file: '${config_path}' contains ${config_error_count} error(s). Exiting now." - exit 1 -fi -unset valid_config_entries user_config config_error_count key - -# shellcheck source=config.primary.sh -. "${config_path}" - -if [[ ${config_path} =~ config\.(.*)\.sh ]] -then - instance_id="${BASH_REMATCH[1]}" - run_path="/var/run/cake-autorate/${instance_id}" -else - log_msg "ERROR" "Instance identifier 'X' set by config.X.sh cannot be empty. Exiting now." - exit 1 -fi - -if [[ -n "${log_file_path_override-}" ]] -then - if [[ ! -d ${log_file_path_override} ]] - then - broken_log_file_path_override=${log_file_path_override} - log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log - log_msg "ERROR" "Log file path override: '${broken_log_file_path_override}' does not exist. Exiting now." - exit - fi - log_file_path=${log_file_path_override}/cake-autorate${instance_id:+.${instance_id}}.log -else - log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log -fi - -rotate_log_file # rotate here to force header prints at top of log file - -# save stderr fd, redirect stderr to intercept_stderr -# intercept_stderr sends stderr to log_msg and exits cake-autorate -exec {original_stderr_fd}>&2 2> >(intercept_stderr) - -proc_pids['intercept_stderr']=${!} - -log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${config_path}" - -# ${run_path}/ is used to store temporary files -# it should not exist on startup so if it does exit, else create the directory -if [[ -d "${run_path}" ]] -then - if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' "${run_path}/proc_pids") && [[ -d "/proc/${running_main_pid}" ]] - then - log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script." - trap - INT TERM EXIT - exit - else - log_msg "DEBUG" "${run_path} already exists but no instance is running. Removing and recreating." - rm -r "${run_path}" - mkdir -p "${run_path}" - fi -else - mkdir -p "${run_path}" -fi - -proc_pids['main']="${BASHPID}" - -no_reflectors=${#reflectors[@]} - -# Check ping binary exists -command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${pinger_binary} does not exist. Exiting script."; exit; } - -# Check no_pingers <= no_reflectors -(( no_pingers > no_reflectors )) && { log_msg "ERROR" "number of pingers cannot be greater than number of reflectors. Exiting script."; exit; } - -# Check dl/if interface not the same -[[ "${dl_if}" == "${ul_if}" ]] && { log_msg "ERROR" "download interface and upload interface are both set to: '${dl_if}', but cannot be the same. Exiting script."; exit; } - -# Check bufferbloat detection threshold not greater than window length -(( bufferbloat_detection_thr > bufferbloat_detection_window )) && { log_msg "ERROR" "bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } - -# Passed error checks - -if ((log_to_file)) -then - log_file_max_time_us=$((log_file_max_time_mins*60000000)) - log_file_max_size_bytes=$((log_file_max_size_KB*1024)) - exec {log_fd}<> <(:) - maintain_log_file & - proc_pids['maintain_log_file']=${!} -fi - -# test if stdout is a tty (terminal) -if ! ((terminal)) -then - echo "stdout not a terminal so redirecting output to: ${log_file_path}" - ((log_to_file)) && exec 1>&"${log_fd}" -fi - -# Initialize rx_bytes_path and tx_bytes_path if not set -if [[ -z "${rx_bytes_path-}" ]] -then - case "${dl_if}" in - veth*) - rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" - ;; - ifb*) - rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" - ;; - *) - rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" - ;; - esac -fi -if [[ -z "${tx_bytes_path-}" ]] -then - case "${ul_if}" in - veth*) - tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" - ;; - ifb*) - tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" - ;; - *) - tx_bytes_path="/sys/class/net/${ul_if}/statistics/tx_bytes" - ;; - esac -fi - -if ((debug)) -then - log_msg "DEBUG" "CAKE-autorate version: ${cake_autorate_version}" - log_msg "DEBUG" "config_path: ${config_path}" - log_msg "DEBUG" "run_path: ${run_path}" - log_msg "DEBUG" "log_file_path: ${log_file_path}" - log_msg "DEBUG" "pinger_binary:${pinger_binary}" - log_msg "DEBUG" "download interface: ${dl_if} (${min_dl_shaper_rate_kbps} / ${base_dl_shaper_rate_kbps} / ${max_dl_shaper_rate_kbps})" - log_msg "DEBUG" "upload interface: ${ul_if} (${min_ul_shaper_rate_kbps} / ${base_ul_shaper_rate_kbps} / ${max_ul_shaper_rate_kbps})" - log_msg "DEBUG" "rx_bytes_path: ${rx_bytes_path}" - log_msg "DEBUG" "tx_bytes_path: ${tx_bytes_path}" -fi - -# Check interfaces are up and wait if necessary for them to come up -verify_ifs_up - -# Initialize variables - -# Convert human readable parameters to values that work with integer arithmetic - -printf -v dl_delay_thr_us %.0f "${dl_delay_thr_ms}e3" -printf -v ul_delay_thr_us %.0f "${ul_delay_thr_ms}e3" -printf -v alpha_baseline_increase %.0f "${alpha_baseline_increase}e6" -printf -v alpha_baseline_decrease %.0f "${alpha_baseline_decrease}e6" -printf -v alpha_delta_ewma %.0f "${alpha_delta_ewma}e6" -printf -v achieved_rate_adjust_down_bufferbloat %.0f "${achieved_rate_adjust_down_bufferbloat}e3" -printf -v shaper_rate_adjust_down_bufferbloat %.0f "${shaper_rate_adjust_down_bufferbloat}e3" -printf -v shaper_rate_adjust_up_load_high %.0f "${shaper_rate_adjust_up_load_high}e3" -printf -v shaper_rate_adjust_down_load_low %.0f "${shaper_rate_adjust_down_load_low}e3" -printf -v shaper_rate_adjust_up_load_low %.0f "${shaper_rate_adjust_up_load_low}e3" -printf -v high_load_thr_percent %.0f "${high_load_thr}e2" -printf -v reflector_ping_interval_ms %.0f "${reflector_ping_interval_s}e3" -printf -v reflector_ping_interval_us %.0f "${reflector_ping_interval_s}e6" -printf -v reflector_health_check_interval_us %.0f "${reflector_health_check_interval_s}e6" -printf -v monitor_achieved_rates_interval_us %.0f "${monitor_achieved_rates_interval_ms}e3" -printf -v sustained_idle_sleep_thr_us %.0f "${sustained_idle_sleep_thr_s}e6" -printf -v reflector_response_deadline_us %.0f "${reflector_response_deadline_s}e6" -printf -v reflector_sum_owd_baselines_delta_thr_us %.0f "${reflector_sum_owd_baselines_delta_thr_ms}e3" -printf -v reflector_owd_delta_ewma_delta_thr_us %.0f "${reflector_owd_delta_ewma_delta_thr_ms}e3" -printf -v startup_wait_us %.0f "${startup_wait_s}e6" -printf -v global_ping_response_timeout_us %.0f "${global_ping_response_timeout_s}e6" -printf -v bufferbloat_refractory_period_us %.0f "${bufferbloat_refractory_period_ms}e3" -printf -v decay_refractory_period_us %.0f "${decay_refractory_period_ms}e3" - -for (( i=0; i<${#sss_times_s[@]}; i++ )); -do - printf -v sss_times_us[i] %.0f\\n "${sss_times_s[i]}e6" -done -printf -v sss_compensation_pre_duration_us %.0f "${sss_compensation_pre_duration_ms}e3" -printf -v sss_compensation_post_duration_us %.0f "${sss_compensation_post_duration_ms}e3" - -ping_response_interval_us=$(( reflector_ping_interval_us/no_pingers )) -ping_response_interval_ms=$(( ping_response_interval_us/1000 )) - -stall_detection_timeout_us=$(( stall_detection_thr*ping_response_interval_us )) -stall_detection_timeout_s=000000${stall_detection_timeout_us} -stall_detection_timeout_s=$(( 10#${stall_detection_timeout_s::-6})).${stall_detection_timeout_s: -6} - -declare -A bufferbloat_detected -declare -A load_percent -declare -A load_condition -declare -A t_last_bufferbloat_us -declare -A t_last_decay_us -declare -A shaper_rate_kbps -declare -A last_shaper_rate_kbps -declare -A base_shaper_rate_kbps -declare -A min_shaper_rate_kbps -declare -A max_shaper_rate_kbps -declare -A interface -declare -A adjust_shaper_rate - -base_shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" -base_shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" - -min_shaper_rate_kbps[dl]="${min_dl_shaper_rate_kbps}" -min_shaper_rate_kbps[ul]="${min_ul_shaper_rate_kbps}" - -max_shaper_rate_kbps[dl]="${max_dl_shaper_rate_kbps}" -max_shaper_rate_kbps[ul]="${max_ul_shaper_rate_kbps}" - -shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" -shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" - -last_shaper_rate_kbps[dl]=0 -last_shaper_rate_kbps[ul]=0 - -interface[dl]="${dl_if}" -interface[ul]="${ul_if}" - -adjust_shaper_rate[dl]="${adjust_dl_shaper_rate}" -adjust_shaper_rate[ul]="${adjust_ul_shaper_rate}" - -dl_max_wire_packet_size_bits=0 -ul_max_wire_packet_size_bits=0 -get_max_wire_packet_size_bits "${dl_if}" dl_max_wire_packet_size_bits -get_max_wire_packet_size_bits "${ul_if}" ul_max_wire_packet_size_bits - -set_shaper_rate "dl" -set_shaper_rate "ul" - -update_max_wire_packet_compensation - -main_state="RUNNING" - -t_start_us="${EPOCHREALTIME/./}" -t_end_us="${EPOCHREALTIME/./}" - -t_last_bufferbloat_us[dl]="${t_start_us}" -t_last_bufferbloat_us[ul]="${t_start_us}" -t_last_decay_us[dl]="${t_start_us}" -t_last_decay_us[ul]="${t_start_us}" - -t_sustained_connection_idle_us=0 -reflectors_last_timestamp_us="${EPOCHREALTIME/./}" - -mapfile -t dl_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) -mapfile -t ul_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) - -delays_idx=0 -sum_dl_delays=0 -sum_ul_delays=0 - -if ((debug)) -then - if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )) - then - log_msg "DEBUG" "Warning: bufferbloat refractory period: ${bufferbloat_refractory_period_us} us." - log_msg "DEBUG" "Warning: but expected time to overwrite samples in bufferbloat detection window is: $((bufferbloat_detection_window*ping_response_interval_us)) us." - log_msg "DEBUG" "Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." - fi - if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )) - then - log_msg "DEBUG" "Warning: reflector_response_deadline_s < 2*reflector_ping_interval_s" - log_msg "DEBUG" "Warning: consider setting an increased reflector_response_deadline." - fi -fi - -# Randomize reflectors array providing randomize_reflectors set to 1 -((randomize_reflectors)) && randomize_array reflectors - -# Wait if ${startup_wait_s} > 0 -if ((startup_wait_us>0)) -then - log_msg "DEBUG" "Waiting ${startup_wait_s} seconds before startup." - sleep_us "${startup_wait_us}" -fi - -case "${pinger_binary}" in - - tsping|fping) - exec {pinger_fds[0]}<> <(:) - ;; - - ping) - for ((pinger=0; pinger<=no_pingers; pinger++)) - do - exec {pinger_fds[pinger]}<> <(:) - done - ;; - - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - exit - ;; -esac - -monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" & -proc_pids['monitor_achieved_rates']="${!}" - -maintain_pingers & -proc_pids['maintain_pingers']="${!}" - -generate_log_file_scripts - -log_msg "INFO" "Started cake-autorate with PID: ${BASHPID} and config: ${config_path}" - -while true -do - unset command - read -r -u "${main_fd}" -a command - - if [[ "${command-}" ]] - then - - case "${command[0]}" in - - REFLECTOR_RESPONSE) - - read -r timestamp reflector seq dl_owd_baseline_us dl_owd_us dl_owd_delta_ewma_us dl_owd_delta_us ul_owd_baseline_us ul_owd_us ul_owd_delta_ewma_us ul_owd_delta_us <<< "${command[@]:1}" - ;; - - SET_VAR) - if [[ "${#command[@]}" -eq 3 ]] - then - export -n "${command[1]}=${command[2]}" - fi - ;; - SET_ARRAY_ELEMENT) - if [[ "${#command[@]}" -eq 4 ]] - then - declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" - fi - ;; - SET_PROC_PID) - if [[ "${#command[@]}" -eq 4 ]] - then - declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" - fi - true > "${run_path}/proc_pids" - for proc_pid in "${!proc_pids[@]}" - do - printf "%s=%s\n" "${proc_pid}" "${proc_pids[${proc_pid}]}" >> "${run_path}/proc_pids" - done - ;; - *) - ;; - esac - - fi - case "${main_state}" in - - RUNNING) - - if [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" && "${reflector-}" && "${seq-}" && "${dl_owd_baseline_us-}" && "${dl_owd_us-}" && "${dl_owd_delta_ewma_us-}" && "${dl_owd_delta_us-}" && "${ul_owd_baseline_us-}" && "${ul_owd_us-}" && "${ul_owd_delta_ewma_us-}" && "${ul_owd_delta_us-}" ]] - then - - t_start_us=${EPOCHREALTIME/./} - - reflectors_last_timestamp_us="${timestamp//[.]}" - - if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )) - then - log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." - continue - fi - - # Keep track of number of delays across detection window - # .. for download: - (( dl_delays[delays_idx] )) && ((sum_dl_delays--)) - dl_delays[delays_idx]=$(( dl_owd_delta_us > compensated_dl_delay_thr_us ? 1 : 0 )) - ((dl_delays[delays_idx])) && ((sum_dl_delays++)) - # .. for upload - (( ul_delays[delays_idx] )) && ((sum_ul_delays--)) - ul_delays[delays_idx]=$(( ul_owd_delta_us > compensated_ul_delay_thr_us ? 1 : 0 )) - ((ul_delays[delays_idx])) && ((sum_ul_delays++)) - # .. and move index on - (( delays_idx=(delays_idx+1)%bufferbloat_detection_window )) - - bufferbloat_detected[dl]=$(( sum_dl_delays >= bufferbloat_detection_thr ? 1 : 0 )) - bufferbloat_detected[ul]=$(( sum_ul_delays >= bufferbloat_detection_thr ? 1 : 0 )) - - load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) - load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) - - classify_load "dl" - classify_load "ul" - - update_shaper_rate "dl" - update_shaper_rate "ul" - - set_shaper_rate "dl" - set_shaper_rate "ul" - - if (( output_processing_stats )) - then - printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${load_percent[dl]}" "${load_percent[ul]}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${load_condition[dl]}" "${load_condition[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" - log_msg "DATA" "${processing_stats}" - fi - - # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) - if (( enable_sleep_function )) - then - if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]] - then - ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) - if ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) - then - change_state_main "IDLE" - - log_msg "DEBUG" "Connection idle. Waiting for minimum load." - ((min_shaper_rates_enforcement)) && set_min_shaper_rates - - # update maintain_pingers state - printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" - - # reset idle timer - t_sustained_connection_idle_us=0 - fi - else - # reset timer - t_sustained_connection_idle_us=0 - fi - fi - elif (( (${EPOCHREALTIME/./} - reflectors_last_timestamp_us) > stall_detection_timeout_us )) - then - - log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking loads." - - #log_msg "DEBUG" "load check is: (( ${achieved_rate_kbps[dl]} kbps > ${connection_stall_thr_kbps} kbps for download && ${achieved_rate_kbps[ul]} kbps > ${connection_stall_thr_kbps} kbps for upload ))" - - # non-zero load so despite no reflector response within stall interval, the connection not considered to have stalled - # and therefore resume normal operation - if (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) - then - - log_msg "DEBUG" "load above connection stall threshold so resuming normal operation." - else - change_state_main "STALL" - - printf "CHANGE_STATE PAUSED\n" >&"${maintain_pingers_fd}" - - t_connection_stall_time_us="${EPOCHREALTIME//.}" - global_ping_response_timeout=0 - fi - - fi - - t_end_us="${EPOCHREALTIME/./}" - - ;; - IDLE) - if (( achieved_rate_kbps[dl] > connection_active_thr_kbps || achieved_rate_kbps[ul] > connection_active_thr_kbps )) - then - log_msg "DEBUG" "dl achieved rate: ${achieved_rate_kbps[dl]} kbps or ul achieved rate: ${achieved_rate_kbps[ul]} kbps exceeded connection active threshold: ${connection_active_thr_kbps} kbps. Resuming normal operation." - change_state_main "RUNNING" - printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" - t_sustained_connection_idle_us=0 - # Give some time to enable pingers to get set up - reflectors_last_timestamp_us=$(( "${EPOCHREALTIME/./}" + 2*reflector_ping_interval_us )) - fi - ;; - STALL) - - [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" ]] && reflectors_last_timestamp_us=${timestamp//[.]} - - if [[ "${command[0]}" == "REFLECTOR_RESPONSE" ]] || (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) - then - - log_msg "DEBUG" "Connection stall ended. Resuming normal operation." - printf "CHANGE_STATE RUNNING\n" >&"${maintain_pingers_fd}" - change_state_main "RUNNING" - - fi - - if (( global_ping_response_timeout==0 && ${EPOCHREALTIME/./} > (t_connection_stall_time_us + global_ping_response_timeout_us - stall_detection_timeout_us) )) - then - global_ping_response_timeout=1 - ((min_shaper_rates_enforcement)) && set_min_shaper_rates - log_msg "SYSLOG" "Warning: Configured global ping response timeout: ${global_ping_response_timeout_s} seconds exceeded." - log_msg "DEBUG" "Restarting pingers." - printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" - printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" - fi - ;; - *) - - log_msg "ERROR" "Unrecognized main state: ${main_state}. Exiting now." - exit 1 - ;; - esac - -done diff --git a/sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc b/sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc deleted file mode 100755 index 7c953290f..000000000 --- a/sqm-autorate/files/usr/share/sqm-autorate/defaults.sh.anc +++ /dev/null @@ -1,209 +0,0 @@ -#!/bin/bash - -# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT - -# cake-autorate_config.sh is a script that sets up defaults for cake-autorate - -# Author: @Lynx (OpenWrt forum) -# Inspiration taken from: @moeller0 (OpenWrt forum) - -INTERFACE="" - -# *** OUTPUT AND LOGGING OPTIONS *** - -output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats -output_load_stats=1 # enable (1) or disable (0) output monitoring lines showing achieved loads -output_reflector_stats=1 # enable (1) or disable (0) output monitoring lines showing reflector stats -output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes -debug=1 # enable (1) or disable (0) out of debug lines - -# This can generate a LOT of records so be careful: -log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. - -# ** Take care with these settings to ensure you won't run into OOM issues on your router *** -# every write the cumulative write time and bytes associated with each log line are checked -# and if either exceeds the configured values below, the log log file is rotated -log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log) -log_file_max_time_mins=10 # maximum time between log file rotations -log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations - -# log file path defaults to /var/log/ -# or, if set below, then ${log_file_path_override} -log_file_path_override="" - -# *** STANDARD CONFIGURATION OPTIONS *** - -### For multihomed setups, it is the responsibility of the user to ensure that the probes -### sent by this instance of cake-autorate actually travel through these interfaces. -### See ping_extra_args and ping_prefix_string - -dl_if=ifb-wan # download interface -ul_if=wan # upload interface - -# pinger selection can be any of: -# fping - round robin pinging (rtts) -# ping - (iputils-ping) individual pinging (rtts) -# hping3 - individidual pinging (owds) -pinger_binary=fping - -# list of reflectors to use and number of pingers to initiate -# pingers will be initiated with reflectors in the order specified in the list -# additional reflectors will be used to replace any reflectors that go stale -# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially -# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad -# a bad reflector will go to the back of the queue on reflector rotation -reflectors=( -"1.1.1.1" "1.0.0.1" # Cloudflare -"8.8.8.8" "8.8.4.4" # Google -"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 -"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard -"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar -"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS -"185.228.168.9" "185.228.168.10" # CleanBrowsing -) - -randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup - -# Think carefully about the following settings -# to avoid excessive CPU use (proportional with ping interval / number of pingers) -# and to avoid abusive network activity (excessive ICMP frequency to one reflector) -# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G -no_pingers=6 # number of pingers to maintain -reflector_ping_interval_s=0.3 # (seconds, e.g. 0.2s or 2s) - -# delay threshold in ms is the extent of OWD increase to classify as a delay -# these are automatically adjusted based on maximum on the wire packet size -# (adjustment significant at sub 12Mbit/s rates, else negligible) -dl_delay_thr_ms=30 # (milliseconds) -ul_delay_thr_ms=30 # (milliseconds) - -# Set either of the below to 0 to adjust one direction only -# or alternatively set both to 0 to simply use cake-autorate to monitor a connection -adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate -adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate - -min_dl_shaper_rate_kbps=5000 # minimum bandwidth for download (Kbit/s) -base_dl_shaper_rate_kbps=20000 # steady state bandwidth for download (Kbit/s) -max_dl_shaper_rate_kbps=80000 # maximum bandwidth for download (Kbit/s) - -min_ul_shaper_rate_kbps=5000 # minimum bandwidth for upload (Kbit/s) -base_ul_shaper_rate_kbps=20000 # steady state bandwidth for upload (KBit/s) -max_ul_shaper_rate_kbps=35000 # maximum bandwidth for upload (Kbit/s) - -# sleep functionality saves unecessary pings and CPU cycles by -# pausing all active pingers when connection is not in active use -enable_sleep_function=1 # enable (1) or disable (0) sleep functonality -connection_active_thr_kbps=1000 # threshold in Kbit/s below which dl/ul is considered idle -sustained_idle_sleep_thr_s=60.0 # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) - -min_shaper_rates_enforcement=0 # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall - -startup_wait_s=0.0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) - -# *** ADVANCED CONFIGURATION OPTIONS *** - -log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename - -### In multi-homed setups, it is mandatory to use either ping_extra_args -### or ping_prefix_string to direct the pings through $dl_if and $ul_if. -### No universal recommendation exists, because there are multiple -### policy-routing packages available (e.g. vpn-policy-routing and mwan3). -### Typically they either react to a firewall mark set on the pings, or -### provide a convenient wrapper. -### -### In a traditional single-homed setup, there is usually no need for these parameters. -### -### These arguments can also be used for any other purpose - e.g. for setting a -### particular QoS mark. - -# extra arguments for ping or fping -# e.g., here is how you can set the correct outgoing interface and -# the firewall mark for ping: -# ping_extra_args="-I wwan0 -m $((0x300))" -# Unfortunately, fping does not offer a command line switch to set -# the firewall mark. -# WARNING: no error checking so use at own risk! -ping_extra_args="" - -# a wrapper for ping binary - used as a prefix for the real command -# e.g., when using mwan3, it is recommended to set it like this: -# ping_prefix_string="mwan3 use gpon exec" -# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess. -# Running ping or fping as a subprocess will lead to problems stopping it. -# WARNING: no error checking - so use at own risk! -ping_prefix_string="" - -# interval in ms for monitoring achieved rx/tx rates -# this is automatically adjusted based on maximum on the wire packet size -# (adjustment significant at sub 12Mbit/s rates, else negligible) -monitor_achieved_rates_interval_ms=200 # (milliseconds) - -# bufferbloat is detected when (bufferbloat_detection_thr) samples -# out of the last (bufferbloat detection window) samples are delayed -bufferbloat_detection_window=6 # number of samples to retain in detection window -bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection - -# OWD baseline against which to measure delays -# the idea is that the baseline is allowed to increase slowly to allow for path changes -# and slowly enough such that bufferbloat will be corrected well before the baseline increases, -# but it will decrease very rapidly to ensure delays are measured against the shortest path -alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase -alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease - -# OWD delta from baseline is tracked using ewma with alpha set below -alpha_delta_ewma=0.095 - -# rate adjustment parameters -# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate -# to exploit that transfer rates during bufferbloat provide an indication of line capacity -# otherwise shaper rate is adjusted up on load high, and down on load idle or low -achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat -shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat -shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected -shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected -shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected - -# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate -high_load_thr=0.75 # % of currently set bandwidth for detecting high load - -# refractory periods between successive bufferbloat/decay rate changes -# the bufferbloat refractory period should be greater than the -# average time it would take to replace the bufferbloat -# detection window with new samples upon a bufferbloat event -bufferbloat_refractory_period_ms=300 # (milliseconds) -decay_refractory_period_ms=1000 # (milliseconds) - -# interval for checking reflector health -reflector_health_check_interval_s=1.0 # (seconds) -# deadline for reflector response not to be classified as an offence against reflector -reflector_response_deadline_s=1.0 # (seconds) - -# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples -# out of the last (reflector misbehaving detection window) samples are offences -# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to -# 3 offences within the last 60s -reflector_misbehaving_detection_window=60 -reflector_misbehaving_detection_thr=3 - -reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list - -reflector_comparison_interval_mins=1 # how often to compare reflectors -reflector_sum_owd_baselines_delta_thr_ms=20 # max increase from min sum owd baselines before reflector rotated -reflector_owd_delta_ewma_delta_thr_ms=10 # max increase from min delta ewma before reflector rotated - -# stall is detected when the following two conditions are met: -# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and -# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr -stall_detection_thr=5 -connection_stall_thr_kbps=10 - -global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no ping response whatsoever (seconds) - -if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) - -# Starlink satellite switch (sss) compensation options -sss_compensation=0 # enable (1) or disable (0) Starlink handling -# satellite switch compensation start times in seconds of each minute -sss_times_s=("12.0" "27.0" "42.0" "57.0") -sss_compensation_pre_duration_ms=300 -sss_compensation_post_duration_ms=200 From a5afa39b39496d823063371b775c56814d540fe0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 17:10:13 +0100 Subject: [PATCH 1185/2059] Update Realtek r8125 driver --- r8125/Makefile | 6 ++++-- r8125/patches/021-6.1-suppot.patch | 14 -------------- 2 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 r8125/patches/021-6.1-suppot.patch diff --git a/r8125/Makefile b/r8125/Makefile index befd2aabb..b72462a66 100644 --- a/r8125/Makefile +++ b/r8125/Makefile @@ -7,14 +7,16 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=r8125 -PKG_VERSION:=9.010.01-1 +PKG_VERSION:=9.012.03-1 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/awesometic/realtek-r8125-dkms/tar.gz/$(PKG_VERSION)? -PKG_HASH:=81fb9a100e6cefb421557639b476fd03af61a99c55bc8fb03c6e396532bd0944 +PKG_HASH:=7964aacf4a2873cbe4133aeca830bd0725f819ea286bab162026ff283510144f PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/realtek-$(PKG_NAME)-dkms-$(PKG_VERSION) +PKG_LICENSE:=GPL-2.0-only +PKG_LICENSE_FILES:=LICENSE include $(INCLUDE_DIR)/package.mk diff --git a/r8125/patches/021-6.1-suppot.patch b/r8125/patches/021-6.1-suppot.patch deleted file mode 100644 index c460ce33b..000000000 --- a/r8125/patches/021-6.1-suppot.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/src/r8125.h -+++ b/src/r8125.h -@@ -633,7 +633,11 @@ - typedef struct napi_struct *napi_ptr; - typedef int napi_budget; - -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -+#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add_weight(ndev, &priv->napi, function, weight) -+#else - #define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -+#endif - #define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) - #define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) - #define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; From 5feb37f7998fe251ddb109945342122baffcb244 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 20:07:08 +0100 Subject: [PATCH 1186/2059] Update cryptodev-linux --- cryptodev-linux/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cryptodev-linux/Makefile b/cryptodev-linux/Makefile index 0c1f63a60..e0b56e17b 100644 --- a/cryptodev-linux/Makefile +++ b/cryptodev-linux/Makefile @@ -1,5 +1,6 @@ # # Copyright (C) 2014 OpenWrt.org +# Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -10,18 +11,17 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=cryptodev-linux -PKG_VERSION:=1.12 PKG_RELEASE:=1 -PKG_SOURCE_URL:=https://codeload.github.com/$(PKG_NAME)/$(PKG_NAME)/tar.gz/$(PKG_NAME)-$(PKG_VERSION)? -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_HASH:=f51c2254749233b1b1d7ec9445158bd709f124f88e1c650fe2faac83c3a81938 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/$(PKG_NAME)/$(PKG_NAME).git +PKG_SOURCE_VERSION:=bb8bc7cf60d2c0b097c8b3b0e807f805b577a53f +PKG_VERSION:=1.13-$(PKG_SOURCE_VERSION) PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING -PKG_MAINTAINER:=Ansuel Smith +PKG_MAINTAINER:=Yannick Chabanois -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_NAME)-$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk From c8226e5abc411a44d1155b2ab3db17e0f61d42d1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 20:07:54 +0100 Subject: [PATCH 1187/2059] Update ipcalc --- ipcalc/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ipcalc/Makefile b/ipcalc/Makefile index f2d752d59..3d95869ff 100644 --- a/ipcalc/Makefile +++ b/ipcalc/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -10,11 +10,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ipcalc PKG_RELEASE:=1 -PKG_SOURCE_URL:=https://github.com/nmav/ipcalc.git +PKG_SOURCE_URL:=https://gitlab.com/ipcalc/ipcalc.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=e9f88461f2585575d12fc95f5eeb9996b863f5af +PKG_SOURCE_VERSION:=d8a2fe29a89f0f9f0d44a7b15e260c74f0e8388b PKG_MAINTAINER:=Ycarus (Yannick Chabanois) PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILE:=COPYING include $(INCLUDE_DIR)/package.mk From 4194e2ab6158b25bd6f7d599114c39b216243933 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 20:08:29 +0100 Subject: [PATCH 1188/2059] Update Realtek r8152 --- r8152/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/r8152/Makefile b/r8152/Makefile index f07c14969..b8e5b99f0 100644 --- a/r8152/Makefile +++ b/r8152/Makefile @@ -7,12 +7,14 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=r8152 -PKG_VERSION:=2.16.3.20220914 +PKG_VERSION:=2.17.1.20230903 PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/wget/realtek-r8152-linux/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=61ed7af34c8882c6028ddd1a27bb78fb5bfba41211f84dd7a06e4dc84dbe9a9a +PKG_HASH:=be19d9a984459762283f1ddc77f58746133a79051c01bb73f0b35fa843d47622 + +PKG_LICENSE:=GPL-2.0-only PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/realtek-$(PKG_NAME)-linux-$(PKG_VERSION) From 00164ca23f4cffc2ae771cd804a3432d84dd1737 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 20:09:56 +0100 Subject: [PATCH 1189/2059] Update Realtek r8168 --- r8168/Makefile | 7 ++++--- r8168/patches/900-6.6-support.patch | 13 +++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 r8168/patches/900-6.6-support.patch diff --git a/r8168/Makefile b/r8168/Makefile index 8f810c518..a3f688eae 100644 --- a/r8168/Makefile +++ b/r8168/Makefile @@ -7,13 +7,14 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=r8168 -PKG_VERSION:=8.051.02 +PKG_VERSION:=8.052.01 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/BROBIRD/openwrt-r8168.git -PKG_SOURCE_VERSION:=4f6cfe1ca12fb772deed57f1d2d1062af041ad07 -PKG_MIRROR_HASH:=6b149f5eb3b9e1dc50867a694984d253aa58d97dd5fbab30eb405d2d7b2be587 +PKG_SOURCE_VERSION:=a1d4d30ce44c6d1d5de559d8dfdda7a65b1918a3 + +PKG_LICENSE:=GPPL-2.0-only PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) diff --git a/r8168/patches/900-6.6-support.patch b/r8168/patches/900-6.6-support.patch new file mode 100644 index 000000000..00d1adade --- /dev/null +++ b/r8168/patches/900-6.6-support.patch @@ -0,0 +1,13 @@ +--- a/src/r8168_n.c 2023-10-20 17:46:41.593467802 +0200 ++++ b/src/r8168_n.c 2023-10-20 17:47:59.460123974 +0200 +@@ -82,6 +82,10 @@ + #include + #endif + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,5,0) ++#include ++#endif ++ + #include + #include + From 8ba0e21376071ed79ea54421680cf0a7364adff1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 20:10:17 +0100 Subject: [PATCH 1190/2059] Update systemtap --- systemtap/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/systemtap/Makefile b/systemtap/Makefile index c25cd3467..dc97b42b2 100644 --- a/systemtap/Makefile +++ b/systemtap/Makefile @@ -10,16 +10,18 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=systemtap PKG_RELEASE:=1 -PKG_VERSION:=4.9 +PKG_VERSION:=5.0 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://sourceware.org/systemtap/ftp/releases/ -PKG_HASH:=d01033baea9d0af52a65e70167816931f4b856427a53ff2ab30e4b45f6ad3a98 +PKG_HASH:=a8b43408895fee2b0023483b02f861700b0139629050666dfe4dfa1e49d59939 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) PKG_BUILD_DEPENDS:=systemtap/host PKG_INSTALL:=1 +PKG_LICENSE:=GPL-2.0-or-later + include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk From 8221386432d021a25065d79b34a06596eb6be2ef Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 22 Nov 2023 20:11:43 +0100 Subject: [PATCH 1191/2059] Add some missing license information in packages --- dsvpn/Makefile | 2 ++ glorytun-udp/Makefile | 2 ++ glorytun/Makefile | 3 ++- mptcpd/Makefile | 5 ++++- ndpi-netfilter2/Makefile | 3 +++ tracebox/Makefile | 5 ++++- 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/dsvpn/Makefile b/dsvpn/Makefile index 0aed2bc5c..8bfae704f 100644 --- a/dsvpn/Makefile +++ b/dsvpn/Makefile @@ -15,6 +15,8 @@ PKG_SOURCE_VERSION:=4333aa705efd9c86c76809614d20dc5ebf43da7f PKG_NAME:=dsvpn PKG_VERSION:=0.1.5-$(PKG_SOURCE_VERSION) PKG_RELEASE:=1 +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE include $(INCLUDE_DIR)/package.mk diff --git a/glorytun-udp/Makefile b/glorytun-udp/Makefile index c2dd9da15..27fa65c17 100644 --- a/glorytun-udp/Makefile +++ b/glorytun-udp/Makefile @@ -14,6 +14,8 @@ PKG_SOURCE_VERSION:=32267e86a6da05b285bb3bf2b136c105dc0af4bb PKG_NAME:=glorytun-udp PKG_VERSION:=0.3.4-$(PKG_SOURCE_VERSION) PKG_RELEASE:=23 +PKG_LICENSE:=BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE PKG_FIXUP:=autoreconf diff --git a/glorytun/Makefile b/glorytun/Makefile index 837f1903f..63a8fe52c 100644 --- a/glorytun/Makefile +++ b/glorytun/Makefile @@ -15,7 +15,8 @@ PKG_SOURCE_VERSION:=0c3b03cf0215e0896fd8e7e91be92efa77f6a2d1 PKG_SOURCE:=glorytun-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/Ysurac/glorytun.git PKG_VERSION:=0.0.35-$(PKG_SOURCE_VERSION) - +PKG_LICENSE:=BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE PKG_FIXUP:=autoreconf include $(INCLUDE_DIR)/package.mk diff --git a/mptcpd/Makefile b/mptcpd/Makefile index f1cef84dd..04e44706c 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -15,6 +15,9 @@ PKG_VERSION:=0.12-$(PKG_SOURCE_VERSION) PKG_RELEASE:=1 PKG_MAINTAINER:=Ycarus (Yannick Chabanois) +PKG_LICENSE:=BSD-3-Clause +PKG_LICENSE_FILES:=COPYING + PKG_FORTIFY_SOURCE:=2 PKG_INSTALL:=1 PKG_BUILD_PARALLEL:=1 @@ -25,7 +28,7 @@ include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) SECTION:=net CATEGORY:=Network -DEPENDS:=+libell @(LINUX_5_15||LINUX_6_1) +DEPENDS:=+libell @(LINUX_5_15||LINUX_6_1||LINUX_6_6) TITLE:=mptcpd URL:=https://github.com/intel/mptcpd endef diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 406f647ac..ab0ada4ce 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -20,6 +20,9 @@ PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_URL:=https://github.com/vel21ripn/nDPI.git PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + PKG_BUILD_PARALLEL:=0 PKG_FORTIFY_SOURCE:=0 diff --git a/tracebox/Makefile b/tracebox/Makefile index 9c8117df7..62fb89ec9 100644 --- a/tracebox/Makefile +++ b/tracebox/Makefile @@ -22,6 +22,9 @@ PKG_SOURCE_PROTO:=git PKG_SOURCE_VERSION:=4ad40ea43354038a04ad90aedae5874801c223e8 #v0.4.4 +PKG_LICENSE:=GPL-2.0-only +PKG_LICENSE_FILES:=LICENSE + PKG_FIXUP:=autoreconf include $(INCLUDE_DIR)/package.mk @@ -43,7 +46,7 @@ CONFIGURE_VARS += \ ac_cv_header_lua_h=no \ ax_header_version_match=yes -CONFIGURE_ARGS += --enable-sniffer --enable-curl --with-libpcap="$(STAGING_DIR)/usr/include/" +CONFIGURE_ARGS += --enable-sniffer --enable-curl --with-libpcap="$(STAGING_DIR)/usr/include/" --disable-tests EXTRA_CPPFLAGS += -fpermissive -Wno-variadic-macros -std=c++14 From 9fd78af7ea7f458d047ebd4332d28638534b3806 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 23 Nov 2023 20:02:33 +0100 Subject: [PATCH 1192/2059] Restart modemmanager when modem stay in a pending mode --- .../share/omr/post-tracking.d/001-post-tracking | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 650471be7..86490fa01 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -723,26 +723,31 @@ default_gw6=$(ip -6 route get 2606:4700:4700::1111 | grep via | awk '{print $3}' #current_interface_gw=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway") interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') +interface_available=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["available"]') +interface_pending=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["pending"]') initcwrwnd="" # An interface in error will never be used in MPTCP if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then - if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then + #if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then + if [ "$interface_available" = "true" ] && ([ "$interface_pending" = "true" ] || [ "$interface_up" = "true" ]) && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart interface" _log "Set $OMR_TRACKER_INTERFACE down" ifdown $OMR_TRACKER_INTERFACE sleep 5 _log "Set $OMR_TRACKER_INTERFACE up" ifup $OMR_TRACKER_INTERFACE - sleep 20 - #elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "dhcp" ]); then - # for modem in $(mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do + sleep 30 + #elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ]; then + # for modem in $(timeout 3 mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do # if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then - # modem_device=$(mmcli -m $modem -K | grep 'modem.generic.device ' | awk '{print $3}') - # [ -n "$modem_device" ] && modem_interface=$(uci show network | grep $modem_device | awk -F. '{print $2}') + # modem_device=$(timeout 2 mmcli -m $modem -K | grep 'modem.generic.device ' | awk '{print $3}') + # [ -n "$modem_device" ] && modem_interface=$(uci -q show network | grep $modem_device | awk -F. '{print $2}') # [ -n "$modem_interface" ] && { # _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart associed interface $modem_interface" + # ifdown $modem_interface + # sleep 5 # ifup $modem_interface # sleep 30 # } From 30f04aeaf260f72e9e0b2e7763eddaee86b81b7d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 23 Nov 2023 20:02:47 +0100 Subject: [PATCH 1193/2059] Update golang --- golang/golang/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/golang/golang/Makefile b/golang/golang/Makefile index e91f34654..55da6587b 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk GO_VERSION_MAJOR_MINOR:=1.21 -GO_VERSION_PATCH:=1 +GO_VERSION_PATCH:=4 PKG_NAME:=golang PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=bfa36bf75e9a1e9cbbdb9abcf9d1707e479bd3a07880a8ae3564caee5711cb99 +PKG_HASH:=47b26a83d2b65a3c1c1bcace273b69bee49a7a7b5168a7604ded3d26a37bd787 PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause From c019b885fea1bd630a259bfeb9f4c76becdd71a3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 23 Nov 2023 20:03:18 +0100 Subject: [PATCH 1194/2059] Fix Shadowsocks* issue when rules are not fully applied --- shadowsocks-libev/files/shadowsocks-libev.init | 2 +- shadowsocks-rust/files/shadowsocks-rust.init | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 7c7e39d6e..34cc62000 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -329,7 +329,7 @@ reload_service() { } rules_exist() { - [ -n "$(iptables-save 2>/dev/null | grep 'A ssr')" ] && return 0 + [ -n "$(iptables-save 2>/dev/null | grep 'A ssr_def_local_out')" ] && return 0 return 1 } diff --git a/shadowsocks-rust/files/shadowsocks-rust.init b/shadowsocks-rust/files/shadowsocks-rust.init index ef9e77704..7af70018d 100644 --- a/shadowsocks-rust/files/shadowsocks-rust.init +++ b/shadowsocks-rust/files/shadowsocks-rust.init @@ -326,7 +326,7 @@ reload_service() { } rules_exist() { - [ -n "$(iptables-save 2>/dev/null | grep 'A ssr')" ] && return 0 + [ -n "$(iptables-save 2>/dev/null | grep 'A ssr_def_local_out')" ] && return 0 return 1 } From 62676ca47ddfcf04765a7200ba2c63149a2304e5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 24 Nov 2023 17:31:52 +0100 Subject: [PATCH 1195/2059] Update netifd and add patch to compile on 6.6 --- netifd/Makefile | 10 +++++++--- netifd/patches/001-defin-RTN_POLICY_FAILED.patch | 12 ++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 netifd/patches/001-defin-RTN_POLICY_FAILED.patch diff --git a/netifd/Makefile b/netifd/Makefile index 826889aca..2a9d4cc1b 100644 --- a/netifd/Makefile +++ b/netifd/Makefile @@ -5,9 +5,12 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2023-11-10 -PKG_SOURCE_VERSION:=35facc8306f590a7330789ab6d5785c0d43073ef -PKG_MIRROR_HASH:=4f73591ae1873e18df235349e478f2196ca0d3123c313a04149dc9d5e2bfb403 +#PKG_SOURCE_DATE:=2023-11-20 +#PKG_SOURCE_VERSION:=f3e06e81b347bbdec1c6c71603328b6e442728d4 +#PKG_MIRROR_HASH:=f16dd61aede5597fd7b5ee8e7752a916494281bc981b35c16e788ddb7409584a +PKG_SOURCE_DATE:=2023-11-14 +PKG_SOURCE_VERSION:=8587c074f1eb2064c42adb0a6aa5073f695ab89d +PKG_MIRROR_HASH:=f5ceb771badd7a23cceb53537299580d4b483e2b3ec5de09b9c3c54692893dd9 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 @@ -21,6 +24,7 @@ include $(INCLUDE_DIR)/cmake.mk define Package/netifd SECTION:=base CATEGORY:=Base system +# DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox +libudebug DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox TITLE:=OpenWrt Network Interface Configuration Daemon endef diff --git a/netifd/patches/001-defin-RTN_POLICY_FAILED.patch b/netifd/patches/001-defin-RTN_POLICY_FAILED.patch new file mode 100644 index 000000000..d7b530393 --- /dev/null +++ b/netifd/patches/001-defin-RTN_POLICY_FAILED.patch @@ -0,0 +1,12 @@ +--- a/system-linux.c 2023-11-24 16:49:37.715537192 +0100 ++++ b/system-linux.c 2023-11-24 16:50:23.002742488 +0100 +@@ -53,6 +53,9 @@ + #ifndef RTN_FAILED_POLICY + #define RTN_FAILED_POLICY 12 + #endif ++#ifndef RTN_POLICY_FAILED ++#define RTN_POLICY_FAILED 12 ++#endif + + #ifndef IFA_F_NOPREFIXROUTE + #define IFA_F_NOPREFIXROUTE 0x200 From 6920f7227f565cd1096ccb1fbd290736bca49f2f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Nov 2023 16:35:32 +0100 Subject: [PATCH 1196/2059] Fix TTL display https://github.com/Ysurac/openmptcprouter/issues/3045 --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 1 + luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 1 + 2 files changed, 2 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 8d07c1d95..ec876228c 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -358,6 +358,7 @@ function wizard_add() uci_device = uci_device_from_interface(intf) if uci_device == "" then uci_device = intf .. "_dev" + ucic:set("network",uci_device,"device") end ucic:set("network",uci_device,"ttl",ttl) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 05476a980..1d8eba66a 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -573,6 +573,7 @@ for _, iface in ipairs(net:get_networks()) do local ifname = iface:name() local firewall_wan = luci.util.trim(luci.sys.exec("uci -q get firewall.zone_wan.network | tr ' ' '\n' | grep \'^" .. ifname .. "$\'")) + local ttl = uci:get("network",ifname .. "_dev","ttl") if firewall_wan ~= "" then -- local multipath = uci:get("network",ifname,"multipath") From 53a6411d5b05e9bcda377535f35c4dd29141a294 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Nov 2023 16:37:15 +0100 Subject: [PATCH 1197/2059] Update luci-mod-network --- .../luci-static/resources/tools/network.js | 162 +++- .../resources/view/network/dhcp.js | 881 +++++++++++++----- .../resources/view/network/diagnostics.js | 64 +- .../resources/view/network/hosts.js | 50 - .../resources/view/network/interfaces.js | 203 +++- .../resources/view/network/routes.js | 227 +++-- .../resources/view/network/switch.js | 26 +- .../resources/view/network/wireless.js | 203 +++- .../share/luci/menu.d/luci-mod-network.json | 46 +- .../share/rpcd/acl.d/luci-mod-network.json | 7 +- 10 files changed, 1329 insertions(+), 540 deletions(-) delete mode 100644 luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js diff --git a/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/luci-mod-network/htdocs/luci-static/resources/tools/network.js index 6f16713fe..dfe9796c4 100644 --- a/luci-mod-network/htdocs/luci-static/resources/tools/network.js +++ b/luci-mod-network/htdocs/luci-static/resources/tools/network.js @@ -1,4 +1,5 @@ 'use strict'; +'require fs'; 'require ui'; 'require dom'; 'require uci'; @@ -149,25 +150,77 @@ function updatePlaceholders(opt, section_id) { } } +var cbiFlagTristate = form.ListValue.extend({ + __init__: function(/* ... */) { + this.super('__init__', arguments); + this.keylist = [ '', '0!', '1!' ]; + this.vallist = [ _('automatic'), _('disabled'), _('enabled') ]; + }, + + load: function(section_id) { + var invert = false, sysfs = this.sysfs; + + if (sysfs) { + if (sysfs.charAt(0) == '!') { + invert = true; + sysfs = sysfs.substring(1); + } + + return L.resolveDefault(fs.read(sysfs), '').then(L.bind(function(res) { + res = (res || '').trim(); + + if (res == '0') + this.sysfs_default = invert; + else if (res == '1') + this.sysfs_default = !invert; + + return this.super('load', [section_id]); + }, this)); + } + + return this.super('load', [section_id]); + }, + + write: function(section_id, formvalue) { + if (formvalue == '1!') + return this.super('write', [section_id, '1']); + else if (formvalue == '0!') + return this.super('write', [section_id, '0']); + else + return this.super('remove', [section_id]); + }, + + renderWidget: function(section_id, option_index, cfgvalue) { + var sysdef = this.sysfs_default; + + if (this.sysfs_default !== null) { + this.keylist[0] = sysdef ? '1' : '0'; + this.vallist[0] = sysdef ? _('automatic (enabled)') : _('automatic (disabled)'); + } + + return this.super('renderWidget', [section_id, option_index, cfgvalue]); + } +}); + var cbiTagValue = form.Value.extend({ renderWidget: function(section_id, option_index, cfgvalue) { var widget = new ui.Dropdown(cfgvalue || ['-'], { '-': E([], [ E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ '—' ]), - E('span', { 'class': 'hide-close' }, [ _('Do not participate', 'VLAN port state') ]) + E('span', { 'class': 'hide-close' }, [ _('Not Member', 'VLAN port state') ]) ]), 'u': E([], [ - E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ 'u' ]), - E('span', { 'class': 'hide-close' }, [ _('Egress untagged', 'VLAN port state') ]) + E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ 'U' ]), + E('span', { 'class': 'hide-close' }, [ _('Untagged', 'VLAN port state') ]) ]), 't': E([], [ - E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ 't' ]), - E('span', { 'class': 'hide-close' }, [ _('Egress tagged', 'VLAN port state') ]) + E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ 'T' ]), + E('span', { 'class': 'hide-close' }, [ _('Tagged', 'VLAN port state') ]) ]), '*': E([], [ E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ '*' ]), - E('span', { 'class': 'hide-close' }, [ _('Primary VLAN ID', 'VLAN port state') ]) + E('span', { 'class': 'hide-close' }, [ _('Is Primary VLAN', 'VLAN port state') ]) ]) }, { id: this.cbid(section_id), @@ -274,7 +327,7 @@ var cbiTagValue = form.Value.extend({ var t = /t/.test(s[1] || '') ? 't' : 'u'; - return /\*/.test(s[1] || '') ? [t, '*'] : [t]; + return /\x2a/.test(s[1] || '') ? [t, '*'] : [t]; } return ['-']; @@ -304,7 +357,7 @@ var cbiTagValue = form.Value.extend({ } } - uci.set('network', section_id, 'ports', ports); + uci.set('network', section_id, 'ports', ports.length ? ports : null); }, remove: function() {} @@ -331,6 +384,7 @@ return baseclass.extend({ addDeviceOptions: function(s, dev, isNew) { var parent_dev = dev ? dev.getParent() : null, + devname = dev ? dev.getName() : null, o, ss; s.tab('devgeneral', _('General device options')); @@ -421,7 +475,7 @@ return baseclass.extend({ vid = this.section.formvalue(section_id, 'vid'), name = this.section.getUIElement(section_id, 'name_complex'); - if (base && vid && name && !name.isChanged()) { + if (base && vid && name && !name.isChanged() && isNew) { name.setValue('%s.%d'.format(base, vid)); name.triggerValidation(); } @@ -659,8 +713,8 @@ return baseclass.extend({ o.value('', _('disabled')); o.value('loose', _('Loose filtering')); o.value('strict', _('Strict filtering')); - o.cfgvalue = function(section_id) { - var val = form.ListValue.prototype.cfgvalue.apply(this, [section_id]); + o.cfgvalue = function(/* ... */) { + var val = form.ListValue.prototype.cfgvalue.apply(this, arguments); switch (val || '') { case 'loose': @@ -676,11 +730,17 @@ return baseclass.extend({ } }; - o = this.replaceOption(s, 'devadvanced', form.Flag, 'acceptlocal', _('Accept local'), _('Accept packets with local source addresses')); - o.default = o.disabled; + o = this.replaceOption(s, 'devadvanced', cbiFlagTristate, 'acceptlocal', _('Accept local'), _('Accept packets with local source addresses')); + o.sysfs = '/proc/sys/net/ipv4/conf/%s/accept_local'.format(devname || 'default'); - o = this.replaceOption(s, 'devadvanced', form.Flag, 'sendredirects', _('Send ICMP redirects')); - o.default = o.enabled; + o = this.replaceOption(s, 'devadvanced', cbiFlagTristate, 'sendredirects', _('Send ICMP redirects')); + o.sysfs = '/proc/sys/net/ipv4/conf/%s/send_redirects'.format(devname || 'default'); + + o = this.replaceOption(s, 'devadvanced', cbiFlagTristate, 'arp_accept ', _('Honor gratuitous ARP'), _('When enabled, new ARP table entries are added from received gratuitous APR requests or replies, otherwise only preexisting table entries are updated, but no new hosts are learned.')); + o.sysfs = '/proc/sys/net/ipv4/conf/%s/arp_accept'.format(devname || 'default'); + + o = this.replaceOption(s, 'devadvanced', cbiFlagTristate, 'drop_gratuitous_arp', _('Drop gratuitous ARP'), _('Drop all gratuitous ARP frames, for example if there’s a known good ARP proxy on the network and such frames need not be used or in the case of 802.11, must not be used to prevent attacks.')); + o.sysfs = '/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp'.format(devname || 'default'); o = this.replaceOption(s, 'devadvanced', form.Value, 'neighreachabletime', _('Neighbour cache validity'), _('Time in milliseconds')); o.placeholder = '30000'; @@ -698,59 +758,77 @@ return baseclass.extend({ o.placeholder = '65'; o.datatype = 'uinteger'; - o = this.replaceOption(s, 'devgeneral', form.Flag, 'ipv6', _('Enable IPv6')); + o = this.replaceOption(s, 'devgeneral', cbiFlagTristate, 'ipv6', _('Enable IPv6')); + o.sysfs = '!/proc/sys/net/ipv6/conf/%s/disable_ipv6'.format(devname || 'default'); o.migrate = false; - o.default = o.enabled; + //o.default = o.enabled; + + o = this.replaceOption(s, 'devadvanced', cbiFlagTristate, 'ip6segmentrouting', _('Enable IPv6 segment routing')); + o.sysfs = '/proc/sys/net/ipv6/conf/%s/seg6_enabled'.format(devname || 'default'); + o.depends('ipv6', /1/); + + o = this.replaceOption(s, 'devadvanced', cbiFlagTristate, 'drop_unsolicited_na', _('Drop unsolicited NA'), _('Drop all unsolicited neighbor advertisements, for example if there’s a known good NA proxy on the network and such frames need not be used or in the case of 802.11, must not be used to prevent attacks.')); + o.sysfs = '/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na'.format(devname || 'default'); + o.depends('ipv6', /1/); o = this.replaceOption(s, 'devgeneral', form.Value, 'mtu6', _('IPv6 MTU')); o.datatype = 'max(9200)'; - o.depends('ipv6', '1'); + o.depends('ipv6', /1/); o = this.replaceOption(s, 'devgeneral', form.Value, 'dadtransmits', _('DAD transmits'), _('Amount of Duplicate Address Detection probes to send')); o.placeholder = '1'; o.datatype = 'uinteger'; - o.depends('ipv6', '1'); + o.depends('ipv6', /1/); - o = this.replaceOption(s, 'devadvanced', form.Flag, 'multicast', _('Enable multicast support')); - o.default = o.enabled; + o = this.replaceOption(s, 'devadvanced', cbiFlagTristate, 'multicast', _('Enable multicast support')); + o.sysfs_default = (dev && dev.dev && dev.dev.flags) ? dev.dev.flags.multicast : null; o = this.replaceOption(s, 'devadvanced', form.ListValue, 'igmpversion', _('Force IGMP version')); o.value('', _('No enforcement')); o.value('1', _('Enforce IGMPv1')); o.value('2', _('Enforce IGMPv2')); o.value('3', _('Enforce IGMPv3')); - o.depends('multicast', '1'); + o.depends('multicast', /1/); o = this.replaceOption(s, 'devadvanced', form.ListValue, 'mldversion', _('Force MLD version')); o.value('', _('No enforcement')); o.value('1', _('Enforce MLD version 1')); o.value('2', _('Enforce MLD version 2')); - o.depends('multicast', '1'); + o.depends('multicast', /1/); if (isBridgePort(dev)) { o = this.replaceOption(s, 'brport', form.Flag, 'learning', _('Enable MAC address learning')); - o.default = o.enabled; + o = this.replaceOption(s, 'brport', cbiFlagTristate, 'learning', _('Enable MAC address learning')); + o.sysfs = '/sys/class/net/%s/brport/learning'.format(devname || 'default'); - o = this.replaceOption(s, 'brport', form.Flag, 'unicast_flood', _('Enable unicast flooding')); - o.default = o.enabled; + o = this.replaceOption(s, 'brport', cbiFlagTristate, 'unicast_flood', _('Enable unicast flooding')); + o.sysfs = '/sys/class/net/%s/brport/unicast_flood'.format(devname || 'default'); - o = this.replaceOption(s, 'brport', form.Flag, 'isolated', _('Port isolation'), _('Only allow communication with non-isolated bridge ports when enabled')); - o.default = o.disabled; + o = this.replaceOption(s, 'brport', cbiFlagTristate, 'isolate', _('Port isolation'), _('Only allow communication with non-isolated bridge ports when enabled')); + o.sysfs = '/sys/class/net/%s/brport/isolated'.format(devname || 'default'); o = this.replaceOption(s, 'brport', form.ListValue, 'multicast_router', _('Multicast routing')); o.value('', _('Never')); o.value('1', _('Learn')); o.value('2', _('Always')); - o.depends('multicast', '1'); + o.depends('multicast', /1/); - o = this.replaceOption(s, 'brport', form.Flag, 'multicast_to_unicast', _('Multicast to unicast'), _('Forward multicast packets as unicast packets on this device.')); - o.default = o.disabled; - o.depends('multicast', '1'); + o = this.replaceOption(s, 'brport', cbiFlagTristate, 'multicast_to_unicast', _('Multicast to unicast'), _('Forward multicast packets as unicast packets on this device.')); + o.sysfs = '/sys/class/net/%s/brport/multicast_to_unicast'.format(devname || 'default'); + o.depends('multicast', /1/); - o = this.replaceOption(s, 'brport', form.Flag, 'multicast_fast_leave', _('Enable multicast fast leave')); - o.default = o.disabled; - o.depends('multicast', '1'); + o = this.replaceOption(s, 'brport', cbiFlagTristate, 'multicast_fast_leave', _('Enable multicast fast leave')); + o.sysfs = '/sys/class/net/%s/brport/multicast_fast_leave'.format(devname || 'default'); + o.depends('multicast', /1/); + + o = this.replaceOption(s, 'brport', cbiFlagTristate, 'drop_v4_unicast_in_l2_multicast', _('Drop nested IPv4 unicast'), _('Drop layer 2 multicast frames containing IPv4 unicast packets.')); + o.sysfs = '/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast'.format(devname || 'default'); + o.depends('multicast', /1/); + + o = this.replaceOption(s, 'brport', cbiFlagTristate, 'drop_v6_unicast_in_l2_multicast', _('Drop nested IPv6 unicast'), _('Drop layer 2 multicast frames containing IPv6 unicast packets.')); + o.sysfs = '/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast'.format(devname || 'default'); + o.depends('multicast', /1/); } o = this.replaceOption(s, 'bridgevlan', form.Flag, 'vlan_filtering', _('Enable VLAN filtering')); @@ -816,6 +894,8 @@ return baseclass.extend({ return network.instantiateDevice(port) }).filter(function(dev) { return dev.getType() != 'wifi' || dev.isUp(); + }).sort(function(a, b) { + return L.naturalCompare(a.getName(), b.getName()); }); this.children = this.children.filter(function(opt) { return !opt.option.match(/^port_/) }); @@ -929,18 +1009,6 @@ return baseclass.extend({ for (var port_name in seen_ports) ports.push(port_name); - ports.sort(function(a, b) { - var m1 = a.match(/^(.+?)([0-9]*)$/), - m2 = b.match(/^(.+?)([0-9]*)$/); - - if (m1[1] < m2[1]) - return -1; - else if (m1[1] > m2[1]) - return 1; - else - return +(m1[2] || 0) - +(m2[2] || 0); - }); - ss.updatePorts(ports); }, diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js index 6c6163c7c..da0eeabb5 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js @@ -5,7 +5,9 @@ 'require rpc'; 'require uci'; 'require form'; +'require network'; 'require validation'; +'require tools.widgets as widgets'; var callHostHints, callDUIDHints, callDHCPLeases, CBILeaseStatus, CBILease6Status; @@ -65,6 +67,58 @@ CBILease6Status = form.DummyValue.extend({ } }); +function calculateNetwork(addr, mask) { + addr = validation.parseIPv4(String(addr)); + + if (!isNaN(mask)) + mask = validation.parseIPv4(network.prefixToMask(+mask)); + else + mask = validation.parseIPv4(String(mask)); + + if (addr == null || mask == null) + return null; + + return [ + [ + addr[0] & (mask[0] >>> 0 & 255), + addr[1] & (mask[1] >>> 0 & 255), + addr[2] & (mask[2] >>> 0 & 255), + addr[3] & (mask[3] >>> 0 & 255) + ].join('.'), + mask.join('.') + ]; +} + +function getDHCPPools() { + return uci.load('dhcp').then(function() { + let sections = uci.sections('dhcp', 'dhcp'), + tasks = [], pools = []; + + for (var i = 0; i < sections.length; i++) { + if (sections[i].ignore == '1' || !sections[i].interface) + continue; + + tasks.push(network.getNetwork(sections[i].interface).then(L.bind(function(section_id, net) { + var cidr = net ? (net.getIPAddrs()[0] || '').split('/') : null; + + if (cidr && cidr.length == 2) { + var net_mask = calculateNetwork(cidr[0], cidr[1]); + + pools.push({ + section_id: section_id, + network: net_mask[0], + netmask: net_mask[1] + }); + } + }, null, sections[i]['.name']))); + } + + return Promise.all(tasks).then(function() { + return pools; + }); + }); +} + function validateHostname(sid, s) { if (s == null || s == '') return true; @@ -72,7 +126,7 @@ function validateHostname(sid, s) { if (s.length > 256) return _('Expecting: %s').format(_('valid hostname')); - var labels = s.replace(/^\.+|\.$/g, '').split(/\./); + var labels = s.replace(/^\*?\.?|\.$/g, '').split(/\./); for (var i = 0; i < labels.length; i++) if (!labels[i].match(/^[a-z0-9_](?:[a-z0-9-]{0,61}[a-z0-9])?$/i)) @@ -102,13 +156,15 @@ function validateServerSpec(sid, s) { if (s == null || s == '') return true; - var m = s.match(/^(?:\/(.+)\/)?(.*)$/); + var m = s.match(/^(\/.*\/)?(.*)$/); if (!m) return _('Expecting: %s').format(_('valid hostname')); - var res = validateAddressList(sid, m[1]); - if (res !== true) - return res; + if (m[1] != '//' && m[1] != '/#/') { + var res = validateAddressList(sid, m[1]); + if (res !== true) + return res; + } if (m[2] == '' || m[2] == '#') return true; @@ -138,285 +194,596 @@ function validateServerSpec(sid, s) { return true; } +function validateMACAddr(pools, sid, s) { + if (s == null || s == '') + return true; + + var leases = uci.sections('dhcp', 'host'), + this_macs = L.toArray(s).map(function(m) { return m.toUpperCase() }); + + for (var i = 0; i < pools.length; i++) { + var this_net_mask = calculateNetwork(this.section.formvalue(sid, 'ip'), pools[i].netmask); + + if (!this_net_mask) + continue; + + for (var j = 0; j < leases.length; j++) { + if (leases[j]['.name'] == sid || !leases[j].ip) + continue; + + var lease_net_mask = calculateNetwork(leases[j].ip, pools[i].netmask); + + if (!lease_net_mask || this_net_mask[0] != lease_net_mask[0]) + continue; + + var lease_macs = L.toArray(leases[j].mac).map(function(m) { return m.toUpperCase() }); + + for (var k = 0; k < lease_macs.length; k++) + for (var l = 0; l < this_macs.length; l++) + if (lease_macs[k] == this_macs[l]) + return _('The MAC address %h is already used by another static lease in the same DHCP pool').format(this_macs[l]); + } + } + + return true; +} + return view.extend({ load: function() { return Promise.all([ callHostHints(), - callDUIDHints() + callDUIDHints(), + getDHCPPools(), + network.getNetworks() ]); }, - render: function(hosts_duids) { + render: function(hosts_duids_pools) { var has_dhcpv6 = L.hasSystemFeature('dnsmasq', 'dhcpv6') || L.hasSystemFeature('odhcpd'), - hosts = hosts_duids[0], - duids = hosts_duids[1], + hosts = hosts_duids_pools[0], + duids = hosts_duids_pools[1], + pools = hosts_duids_pools[2], + networks = hosts_duids_pools[3], m, s, o, ss, so; - m = new form.Map('dhcp', _('DHCP and DNS'), _('Dnsmasq is a combined DHCP-Server and DNS-Forwarder for NAT firewalls')); + m = new form.Map('dhcp', _('DHCP and DNS'), + _('Dnsmasq is a lightweight DHCP server and DNS forwarder.')); - s = m.section(form.TypedSection, 'dnsmasq', _('Server Settings')); + s = m.section(form.TypedSection, 'dnsmasq'); s.anonymous = true; s.addremove = false; s.tab('general', _('General Settings')); - s.tab('files', _('Resolv and Hosts Files')); - s.tab('tftp', _('TFTP Settings')); s.tab('advanced', _('Advanced Settings')); s.tab('leases', _('Static Leases')); + s.tab('files', _('Resolv and Hosts Files')); + s.tab('hosts', _('Hostnames')); + s.tab('ipsets', _('IP Sets')); + s.tab('relay', _('Relay')); + s.tab('srvhosts', _('SRV')); + s.tab('mxhosts', _('MX')); + s.tab('cnamehosts', _('CNAME')); + s.tab('pxe_tftp', _('PXE/TFTP Settings')); s.taboption('general', form.Flag, 'domainneeded', _('Domain required'), - _('Don\'t forward DNS-Requests without DNS-Name')); + _('Do not forward DNS queries without dots or domain parts.')); s.taboption('general', form.Flag, 'authoritative', _('Authoritative'), - _('This is the only DHCP in the local network')); - - - s.taboption('files', form.Flag, 'readethers', - _('Use /etc/ethers'), - _('Read /etc/ethers to configure the DHCP-Server')); - - s.taboption('files', form.Value, 'leasefile', - _('Leasefile'), - _('file where given DHCP-leases will be stored')); - - s.taboption('files', form.Flag, 'noresolv', - _('Ignore resolve file')).optional = true; - - o = s.taboption('files', form.Value, 'resolvfile', - _('Resolve file'), - _('local DNS file')); - - o.depends('noresolv', '0'); - o.placeholder = '/tmp/resolv.conf.d/resolv.conf.auto'; - o.optional = true; - - - s.taboption('files', form.Flag, 'nohosts', - _('Ignore /etc/hosts')).optional = true; - - s.taboption('files', form.DynamicList, 'addnhosts', - _('Additional Hosts files')).optional = true; - - o = s.taboption('advanced', form.Flag, 'quietdhcp', - _('Suppress logging'), - _('Suppress logging of the routine operation of these protocols')); - o.optional = true; - - o = s.taboption('advanced', form.Flag, 'sequential_ip', - _('Allocate IP sequentially'), - _('Allocate IP addresses sequentially, starting from the lowest available address')); - o.optional = true; - - o = s.taboption('advanced', form.Flag, 'boguspriv', - _('Filter private'), - _('Do not forward reverse lookups for local networks')); - o.default = o.enabled; - - s.taboption('advanced', form.Flag, 'filterwin2k', - _('Filter useless'), - _('Do not forward requests that cannot be answered by public name servers')); - - - s.taboption('advanced', form.Flag, 'localise_queries', - _('Localise queries'), - _('Localise hostname depending on the requesting subnet if multiple IPs are available')); - - if (L.hasSystemFeature('dnsmasq', 'dnssec')) { - o = s.taboption('advanced', form.Flag, 'dnssec', - _('DNSSEC')); - o.optional = true; - - o = s.taboption('advanced', form.Flag, 'dnsseccheckunsigned', - _('DNSSEC check unsigned'), - _('Requires upstream supports DNSSEC; verify unsigned domain responses really come from unsigned domains')); - o.default = o.enabled; - o.optional = true; - } + _('This is the only DHCP server in the local network.')); s.taboption('general', form.Value, 'local', _('Local server'), - _('Local domain specification. Names matching this domain are never forwarded and are resolved from DHCP or hosts files only')); + _('Never forward matching domains and subdomains, resolve from DHCP or hosts files only.')); s.taboption('general', form.Value, 'domain', _('Local domain'), - _('Local domain suffix appended to DHCP names and hosts file entries')); + _('Local domain suffix appended to DHCP names and hosts file entries.')); - s.taboption('advanced', form.Flag, 'expandhosts', - _('Expand hosts'), - _('Add local domain suffix to names served from hosts files')); - - s.taboption('advanced', form.Flag, 'nonegcache', - _('No negative cache'), - _('Do not cache negative replies, e.g. for not existing domains')); - - s.taboption('advanced', form.Value, 'serversfile', - _('Additional servers file'), - _('This file may contain lines like \'server=/domain/1.2.3.4\' or \'server=1.2.3.4\' for domain-specific or full upstream DNS servers.')); - - s.taboption('advanced', form.Flag, 'strictorder', - _('Strict order'), - _('DNS servers will be queried in the order of the resolvfile')).optional = true; - - s.taboption('advanced', form.Flag, 'allservers', - _('All Servers'), - _('Query all available upstream DNS servers')).optional = true; - - o = s.taboption('advanced', form.DynamicList, 'bogusnxdomain', _('Bogus NX Domain Override'), - _('List of hosts that supply bogus NX domain results')); - - o.optional = true; - o.placeholder = '67.215.65.132'; - - - s.taboption('general', form.Flag, 'logqueries', + o = s.taboption('general', form.Flag, 'logqueries', _('Log queries'), - _('Write received DNS requests to syslog')).optional = true; - - o = s.taboption('general', form.DynamicList, 'server', _('DNS forwardings'), - _('List of DNS servers to forward requests to')); + _('Write received DNS queries to syslog.')); + o.optional = true; + o = s.taboption('general', form.DynamicList, 'server', + _('DNS forwardings'), + _('List of upstream resolvers to forward queries to.')); o.optional = true; o.placeholder = '/example.org/10.1.2.3'; o.validate = validateServerSpec; - - o = s.taboption('general', form.DynamicList, 'address', _('Addresses'), - _('List of domains to force to an IP address.')); - + o = s.taboption('general', form.DynamicList, 'address', + _('Addresses'), + _('Resolve specified FQDNs to an IP.') + '
    ' + + _('Syntax: /fqdn[/fqdn…]/[ipaddr].') + '
    ' + + _('/#/ matches any domain. /example.com/ returns NXDOMAIN.') + '
    ' + + _('/example.com/# returns NULL addresses (0.0.0.0 and ::) for example.com and its subdomains.')); o.optional = true; - o.placeholder = '/router.local/192.168.0.1'; + o.placeholder = '/router.local/router.lan/192.168.0.1'; + o = s.taboption('general', form.DynamicList, 'ipset', + _('IP sets'), + _('List of IP sets to populate with the IPs of DNS lookup results of the FQDNs also specified here.')); + o.optional = true; + o.placeholder = '/example.org/ipset,ipset6'; o = s.taboption('general', form.Flag, 'rebind_protection', _('Rebind protection'), - _('Discard upstream RFC1918 responses')); - + _('Discard upstream responses containing
    RFC1918 addresses.').format('https://datatracker.ietf.org/doc/html/rfc1918')); o.rmempty = false; - o = s.taboption('general', form.Flag, 'rebind_localhost', _('Allow localhost'), - _('Allow upstream responses in the 127.0.0.0/8 range, e.g. for RBL services')); - + _('Exempt 127.0.0.0/8 and ::1 from rebinding checks, e.g. for RBL services.')); o.depends('rebind_protection', '1'); - o = s.taboption('general', form.DynamicList, 'rebind_domain', _('Domain whitelist'), - _('List of domains to allow RFC1918 responses for')); - o.optional = true; - + _('List of domains to allow RFC1918 responses for.')); o.depends('rebind_protection', '1'); + o.optional = true; o.placeholder = 'ihost.netflix.com'; o.validate = validateAddressList; + o = s.taboption('general', form.Flag, 'localservice', + _('Local service only'), + _('Accept DNS queries only from hosts whose address is on a local subnet.')); + o.optional = false; + o.rmempty = false; + + o = s.taboption('general', form.Flag, 'nonwildcard', + _('Non-wildcard'), + _('Bind dynamically to interfaces rather than wildcard address.')); + o.default = o.enabled; + o.optional = false; + o.rmempty = true; + + o = s.taboption('general', form.DynamicList, 'interface', + _('Listen interfaces'), + _('Listen only on the specified interfaces, and loopback if not excluded explicitly.')); + o.optional = true; + o.placeholder = 'lan'; + + o = s.taboption('general', form.DynamicList, 'notinterface', + _('Exclude interfaces'), + _('Do not listen on the specified interfaces.')); + o.optional = true; + o.placeholder = 'loopback'; + + o = s.taboption('relay', form.SectionValue, '__relays__', form.TableSection, 'relay', null, + _('Relay DHCP requests elsewhere. OK: v4↔v4, v6↔v6. Not OK: v4↔v6, v6↔v4.') + + '
    ' + _('Note: you may also need a DHCP Proxy (currently unavailable) when specifying a non-standard Relay To port(addr#port).') + + '
    ' + _('You may add multiple unique Relay To on the same Listen addr.')); + + ss = o.subsection; + + ss.addremove = true; + ss.anonymous = true; + ss.sortable = true; + ss.rowcolors = true; + ss.nodescriptions = true; + + so = ss.option(form.Value, 'local_addr', _('Relay from')); + so.rmempty = false; + so.datatype = 'ipaddr'; + + for (var family = 4; family <= 6; family += 2) { + for (var i = 0; i < networks.length; i++) { + if (networks[i].getName() != 'loopback') { + var addrs = (family == 6) ? networks[i].getIP6Addrs() : networks[i].getIPAddrs(); + for (var j = 0; j < addrs.length; j++) { + var addr = addrs[j].split('/')[0]; + so.value(addr, E([], [ + addr, ' (', + widgets.NetworkSelect.prototype.renderIfaceBadge(networks[i]), + ')' + ])); + } + } + } + } + + so = ss.option(form.Value, 'server_addr', _('Relay to address')); + so.rmempty = false; + so.optional = false; + so.placeholder = '192.168.10.1#535'; + + so.validate = function(section, value) { + var m = this.section.formvalue(section, 'local_addr'), + n = this.section.formvalue(section, 'server_addr'), + p; + if (n != null && n != '') + p = n.split('#'); + if (p.length > 1 && !/^[0-9]+$/.test(p[1])) + return _('Expected port number.'); + else + n = p[0]; + + if ((m == null || m == '') && (n == null || n == '')) + return _('Both "Relay from" and "Relay to address" must be specified.'); + + if ((validation.parseIPv6(m) && validation.parseIPv6(n)) || + validation.parseIPv4(m) && validation.parseIPv4(n)) + return true; + else + return _('Address families of "Relay from" and "Relay to address" must match.') + }; + + so = ss.option(widgets.NetworkSelect, 'interface', _('Only accept replies via')); + so.optional = true; + so.rmempty = false; + so.placeholder = 'lan'; + + s.taboption('files', form.Flag, 'readethers', + _('Use /etc/ethers'), + _('Read /etc/ethers to configure the DHCP server.')); + + s.taboption('files', form.Value, 'leasefile', + _('Lease file'), + _('File to store DHCP lease information.')); + + o = s.taboption('files', form.Flag, 'noresolv', + _('Ignore resolv file')); + o.optional = true; + + o = s.taboption('files', form.Value, 'resolvfile', + _('Resolv file'), + _('File with upstream resolvers.')); + o.depends('noresolv', '0'); + o.placeholder = '/tmp/resolv.conf.d/resolv.conf.auto'; + o.optional = true; + + o = s.taboption('files', form.Flag, 'nohosts', + _('Ignore /etc/hosts')); + o.optional = true; + + o = s.taboption('files', form.DynamicList, 'addnhosts', + _('Additional hosts files')); + o.optional = true; + o.placeholder = '/etc/dnsmasq.hosts'; + + o = s.taboption('advanced', form.Flag, 'quietdhcp', + _('Suppress logging'), + _('Suppress logging of the routine operation for the DHCP protocol.')); + o.optional = true; + + o = s.taboption('advanced', form.Flag, 'sequential_ip', + _('Allocate IPs sequentially'), + _('Allocate IP addresses sequentially, starting from the lowest available address.')); + o.optional = true; + + o = s.taboption('advanced', form.Flag, 'boguspriv', + _('Filter private'), + _('Do not forward reverse lookups for local networks.')); + o.default = o.enabled; + + s.taboption('advanced', form.Flag, 'filterwin2k', + _('Filter SRV/SOA service discovery'), + _('Filters SRV/SOA service discovery, to avoid triggering dial-on-demand links.') + '
    ' + + _('May prevent VoIP or other services from working.')); + + o = s.taboption('advanced', form.Flag, 'filter_aaaa', + _('Filter IPv6 AAAA records'), + _('Remove IPv6 addresses from the results and only return IPv4 addresses.') + '
    ' + + _('Can be useful if ISP has IPv6 nameservers but does not provide IPv6 routing.')); + o.optional = true; + + o = s.taboption('advanced', form.Flag, 'filter_a', + _('Filter IPv4 A records'), + _('Remove IPv4 addresses from the results and only return IPv6 addresses.')); + o.optional = true; + + s.taboption('advanced', form.Flag, 'localise_queries', + _('Localise queries'), + _('Return answers to DNS queries matching the subnet from which the query was received if multiple IPs are available.')); + + if (L.hasSystemFeature('dnsmasq', 'dnssec')) { + o = s.taboption('advanced', form.Flag, 'dnssec', + _('DNSSEC'), + _('Validate DNS replies and cache DNSSEC data, requires upstream to support DNSSEC.')); + o.optional = true; + + o = s.taboption('advanced', form.Flag, 'dnsseccheckunsigned', + _('DNSSEC check unsigned'), + _('Verify unsigned domain responses really come from unsigned domains.')); + o.default = o.enabled; + o.optional = true; + } + + s.taboption('advanced', form.Flag, 'expandhosts', + _('Expand hosts'), + _('Add local domain suffix to names served from hosts files.')); + + s.taboption('advanced', form.Flag, 'nonegcache', + _('No negative cache'), + _('Do not cache negative replies, e.g. for non-existent domains.')); + + o = s.taboption('advanced', form.Value, 'serversfile', + _('Additional servers file'), + _('File listing upstream resolvers, optionally domain-specific, e.g. server=1.2.3.4, server=/domain/1.2.3.4.')); + o.placeholder = '/etc/dnsmasq.servers'; + + o = s.taboption('advanced', form.Flag, 'strictorder', + _('Strict order'), + _('Upstream resolvers will be queried in the order of the resolv file.')); + o.optional = true; + + o = s.taboption('advanced', form.Flag, 'allservers', + _('All servers'), + _('Query all available upstream resolvers.')); + o.optional = true; + + o = s.taboption('advanced', form.DynamicList, 'bogusnxdomain', + _('IPs to override with NXDOMAIN'), + _('List of IP addresses to convert into NXDOMAIN responses.')); + o.optional = true; + o.placeholder = '64.94.110.11'; o = s.taboption('advanced', form.Value, 'port', - _('DNS server port'), - _('Listening port for inbound DNS queries')); - + _('DNS server port'), + _('Listening port for inbound DNS queries.')); o.optional = true; o.datatype = 'port'; o.placeholder = 53; - o = s.taboption('advanced', form.Value, 'queryport', - _('DNS query port'), - _('Fixed source port for outbound DNS queries')); - + _('DNS query port'), + _('Fixed source port for outbound DNS queries.')); o.optional = true; o.datatype = 'port'; o.placeholder = _('any'); - o = s.taboption('advanced', form.Value, 'dhcpleasemax', - _('Max. DHCP leases'), - _('Maximum allowed number of active DHCP leases')); - + _('Max. DHCP leases'), + _('Maximum allowed number of active DHCP leases.')); o.optional = true; o.datatype = 'uinteger'; o.placeholder = _('unlimited'); - o = s.taboption('advanced', form.Value, 'ednspacket_max', - _('Max. EDNS0 packet size'), - _('Maximum allowed size of EDNS.0 UDP packets')); - + _('Max. EDNS0 packet size'), + _('Maximum allowed size of EDNS0 UDP packets.')); o.optional = true; o.datatype = 'uinteger'; o.placeholder = 1280; - o = s.taboption('advanced', form.Value, 'dnsforwardmax', - _('Max. concurrent queries'), - _('Maximum allowed number of concurrent DNS queries')); - + _('Max. concurrent queries'), + _('Maximum allowed number of concurrent DNS queries.')); o.optional = true; o.datatype = 'uinteger'; o.placeholder = 150; o = s.taboption('advanced', form.Value, 'cachesize', _('Size of DNS query cache'), - _('Number of cached DNS entries (max is 10000, 0 is no caching)')); + _('Number of cached DNS entries, 10000 is maximum, 0 is no caching.')); o.optional = true; o.datatype = 'range(0,10000)'; - o.placeholder = 150; - - s.taboption('tftp', form.Flag, 'enable_tftp', - _('Enable TFTP server')).optional = true; - - o = s.taboption('tftp', form.Value, 'tftp_root', - _('TFTP server root'), - _('Root directory for files served via TFTP')); + o.placeholder = 1000; + o = s.taboption('pxe_tftp', form.Flag, 'enable_tftp', + _('Enable TFTP server'), + _('Enable the built-in single-instance TFTP server.')); o.optional = true; + + o = s.taboption('pxe_tftp', form.Value, 'tftp_root', + _('TFTP server root'), + _('Root directory for files served via TFTP. Enable TFTP server and TFTP server root turn on the TFTP server and serve files from TFTP server root.')); o.depends('enable_tftp', '1'); + o.optional = true; o.placeholder = '/'; - - o = s.taboption('tftp', form.Value, 'dhcp_boot', + o = s.taboption('pxe_tftp', form.Value, 'dhcp_boot', _('Network boot image'), - _('Filename of the boot image advertised to clients')); - - o.optional = true; + _('Filename of the boot image advertised to clients.')); o.depends('enable_tftp', '1'); + o.optional = true; o.placeholder = 'pxelinux.0'; - o = s.taboption('general', form.Flag, 'localservice', - _('Local Service Only'), - _('Limit DNS service to subnets interfaces on which we are serving DNS.')); - o.optional = false; - o.rmempty = false; + /* PXE - https://openwrt.org/docs/guide-user/base-system/dhcp#booting_options */ + o = s.taboption('pxe_tftp', form.SectionValue, '__pxe__', form.GridSection, 'boot', null, + _('Special PXE boot options for Dnsmasq.')); + ss = o.subsection; + ss.addremove = true; + ss.anonymous = true; + ss.nodescriptions = true; - o = s.taboption('general', form.Flag, 'nonwildcard', - _('Non-wildcard'), - _('Bind dynamically to interfaces rather than wildcard address (recommended as linux default)')); - o.default = o.enabled; - o.optional = false; - o.rmempty = true; + so = ss.option(form.Value, 'filename', + _('Filename'), + _('Host requests this filename from the boot server.')); + so.optional = false; + so.placeholder = 'pxelinux.0'; - o = s.taboption('general', form.DynamicList, 'interface', - _('Listen Interfaces'), - _('Limit listening to these interfaces, and loopback.')); - o.optional = true; + so = ss.option(form.Value, 'servername', + _('Server name'), + _('The hostname of the boot server')); + so.optional = false; + so.placeholder = 'myNAS'; - o = s.taboption('general', form.DynamicList, 'notinterface', - _('Exclude interfaces'), - _('Prevent listening on these interfaces.')); - o.optional = true; + so = ss.option(form.Value, 'serveraddress', + _('Server address'), + _('The IP address of the boot server')); + so.optional = false; + so.placeholder = '192.168.1.2'; - o = s.taboption('leases', form.SectionValue, '__leases__', form.GridSection, 'host', null, - _('Static leases are used to assign fixed IP addresses and symbolic hostnames to DHCP clients. They are also required for non-dynamic interface configurations where only hosts with a corresponding lease are served.') + '
    ' + - _('Use the Add Button to add a new lease entry. The MAC address identifies the host, the IPv4 address specifies the fixed address to use, and the Hostname is assigned as a symbolic name to the requesting host. The optional Lease time can be used to set non-standard host-specific lease time, e.g. 12h, 3d or infinite.')); + so = ss.option(form.DynamicList, 'dhcp_option', + _('DHCP Options'), + _('Options for the Network-ID. (Note: needs also Network-ID.) E.g. "42,192.168.1.4" for NTP server, "3,192.168.4.4" for default route. 0.0.0.0 means "the address of the system running dnsmasq".')); + so.optional = true; + so.placeholder = '42,192.168.1.4'; + + so = ss.option(widgets.DeviceSelect, 'networkid', + _('Network-ID'), + _('Apply DHCP Options to this net. (Empty = all clients).')); + so.optional = true; + so.noaliases = true; + + so = ss.option(form.Flag, 'force', + _('Force'), + _('Always send DHCP Options. Sometimes needed, with e.g. PXELinux.')); + so.optional = true; + + so = ss.option(form.Value, 'instance', + _('Instance'), + _('Dnsmasq instance to which this boot section is bound. If unspecified, the section is valid for all dnsmasq instances.')); + so.optional = true; + + Object.values(L.uci.sections('dhcp', 'dnsmasq')).forEach(function(val, index) { + so.value(index, '%s (Domain: %s, Local: %s)'.format(index, val.domain || '?', val.local || '?')); + }); + + o = s.taboption('srvhosts', form.SectionValue, '__srvhosts__', form.TableSection, 'srvhost', null, + _('Bind service records to a domain name: specify the location of services. See RFC2782.').format('https://datatracker.ietf.org/doc/html/rfc2782') + + '
    ' + _('_service: _sip, _ldap, _imap, _stun, _xmpp-client, … . (Note: while _http is possible, no browsers support SRV records.)') + + '
    ' + _('_proto: _tcp, _udp, _sctp, _quic, … .') + + '
    ' + _('You may add multiple records for the same Target.') + + '
    ' + _('Larger weights (of the same prio) are given a proportionately higher probability of being selected.')); ss = o.subsection; ss.addremove = true; ss.anonymous = true; + ss.sortable = true; + ss.rowcolors = true; + + so = ss.option(form.Value, 'srv', _('SRV'), _('Syntax: _service._proto.example.com.')); + so.rmempty = false; + so.datatype = 'hostname'; + so.placeholder = '_sip._tcp.example.com'; + + so = ss.option(form.Value, 'target', _('Target'), _('CNAME or fqdn')); + so.rmempty = false; + so.datatype = 'hostname'; + so.placeholder = 'sip.example.com'; + + so = ss.option(form.Value, 'port', _('Port')); + so.rmempty = false; + so.datatype = 'port'; + so.placeholder = '5060'; + + so = ss.option(form.Value, 'class', _('Priority'), _('Ordinal: lower comes first.')); + so.rmempty = true; + so.datatype = 'range(0,65535)'; + so.placeholder = '10'; + + so = ss.option(form.Value, 'weight', _('Weight')); + so.rmempty = true; + so.datatype = 'range(0,65535)'; + so.placeholder = '50'; + + o = s.taboption('mxhosts', form.SectionValue, '__mxhosts__', form.TableSection, 'mxhost', null, + _('Bind service records to a domain name: specify the location of services.') + + '
    ' + _('You may add multiple records for the same domain.')); + + ss = o.subsection; + + ss.addremove = true; + ss.anonymous = true; + ss.sortable = true; + ss.rowcolors = true; + ss.nodescriptions = true; + + so = ss.option(form.Value, 'domain', _('Domain')); + so.rmempty = false; + so.datatype = 'hostname'; + so.placeholder = 'example.com'; + + so = ss.option(form.Value, 'relay', _('Relay')); + so.rmempty = false; + so.datatype = 'hostname'; + so.placeholder = 'relay.example.com'; + + so = ss.option(form.Value, 'pref', _('Priority'), _('Ordinal: lower comes first.')); + so.rmempty = true; + so.datatype = 'range(0,65535)'; + so.placeholder = '0'; + + o = s.taboption('cnamehosts', form.SectionValue, '__cname__', form.TableSection, 'cname', null, + _('Set an alias for a hostname.')); + + ss = o.subsection; + + ss.addremove = true; + ss.anonymous = true; + ss.sortable = true; + ss.rowcolors = true; + ss.nodescriptions = true; + + so = ss.option(form.Value, 'cname', _('Domain')); + so.rmempty = false; + so.datatype = 'hostname'; + so.placeholder = 'www.example.com'; + + so = ss.option(form.Value, 'target', _('Target')); + so.rmempty = false; + so.datatype = 'hostname'; + so.placeholder = 'example.com'; + + o = s.taboption('hosts', form.SectionValue, '__hosts__', form.GridSection, 'domain', null, + _('Hostnames are used to bind a domain name to an IP address. This setting is redundant for hostnames already configured with static leases, but it can be useful to rebind an FQDN.')); + + ss = o.subsection; + + ss.addremove = true; + ss.anonymous = true; + ss.sortable = true; so = ss.option(form.Value, 'name', _('Hostname')); + so.rmempty = false; + so.datatype = 'hostname'; + + so = ss.option(form.Value, 'ip', _('IP address')); + so.rmempty = false; + so.datatype = 'ipaddr'; + + var ipaddrs = {}; + + Object.keys(hosts).forEach(function(mac) { + var addrs = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4); + + for (var i = 0; i < addrs.length; i++) + ipaddrs[addrs[i]] = hosts[mac].name || mac; + }); + + L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ipv4) { + so.value(ipv4, '%s (%s)'.format(ipv4, ipaddrs[ipv4])); + }); + + o = s.taboption('ipsets', form.SectionValue, '__ipsets__', form.GridSection, 'ipset', null, + _('List of IP sets to populate with the IPs of DNS lookup results of the FQDNs also specified here.')); + + ss = o.subsection; + + ss.addremove = true; + ss.anonymous = true; + ss.sortable = true; + + so = ss.option(form.DynamicList, 'name', _('IP set')); + so.rmempty = false; + so.datatype = 'string'; + + so = ss.option(form.DynamicList, 'domain', _('Domain')); + so.rmempty = false; + so.datatype = 'hostname'; + + o = s.taboption('leases', form.SectionValue, '__leases__', form.GridSection, 'host', null, + _('Static leases are used to assign fixed IP addresses and symbolic hostnames to DHCP clients. They are also required for non-dynamic interface configurations where only hosts with a corresponding lease are served.') + '

    ' + + _('Use the Add Button to add a new lease entry. The MAC address identifies the host, the IPv4 address specifies the fixed address to use, and the Hostname is assigned as a symbolic name to the requesting host. The optional Lease time can be used to set non-standard host-specific lease time, e.g. 12h, 3d or infinite.') + '

    ' + + _('The tag construct filters which host directives are used; more than one tag can be provided, in this case the request must match all of them. Tagged directives are used in preference to untagged ones. Note that one of mac, duid or hostname still needs to be specified (can be a wildcard).')); + + ss = o.subsection; + + ss.addremove = true; + ss.anonymous = true; + ss.sortable = true; + ss.nodescriptions = true; + ss.max_cols = 8; + ss.modaltitle = _('Edit static lease'); + + so = ss.option(form.Value, 'name', + _('Hostname'), + _('Optional hostname to assign')); so.validate = validateHostname; so.rmempty = true; so.write = function(section, value) { @@ -428,20 +795,35 @@ return view.extend({ uci.unset('dhcp', section, 'dns'); }; - so = ss.option(form.Value, 'mac', _('MAC-Address')); - so.datatype = 'list(unique(macaddr))'; + so = ss.option(form.Value, 'mac', + _('MAC address(es)'), + _('The hardware address(es) of this entry/host, separated by spaces.') + '

    ' + + _('In DHCPv4, it is possible to include more than one mac address. This allows an IP address to be associated with multiple macaddrs, and dnsmasq abandons a DHCP lease to one of the macaddrs when another asks for a lease. It only works reliably if only one of the macaddrs is active at any time.')); + //As a special case, in DHCPv4, it is possible to include more than one hardware address. eg: --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2 This allows an IP address to be associated with multiple hardware addresses, and gives dnsmasq permission to abandon a DHCP lease to one of the hardware addresses when another one asks for a lease + so.validate = function(section_id, value) { + var macaddrs = L.toArray(value); + + for (var i = 0; i < macaddrs.length; i++) + if (!macaddrs[i].match(/^([a-fA-F0-9]{2}|\*):([a-fA-F0-9]{2}:|\*:){4}(?:[a-fA-F0-9]{2}|\*)$/)) + return _('Expecting a valid MAC address, optionally including wildcards'); + + return true; + }; so.rmempty = true; so.cfgvalue = function(section) { var macs = L.toArray(uci.get('dhcp', section, 'mac')), result = []; for (var i = 0, mac; (mac = macs[i]) != null; i++) - if (/^([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2})$/.test(mac)) - result.push('%02X:%02X:%02X:%02X:%02X:%02X'.format( + if (/^([0-9a-fA-F]{1,2}|\*):([0-9a-fA-F]{1,2}|\*):([0-9a-fA-F]{1,2}|\*):([0-9a-fA-F]{1,2}|\*):([0-9a-fA-F]{1,2}|\*):([0-9a-fA-F]{1,2}|\*)$/.test(mac)) { + var m = [ parseInt(RegExp.$1, 16), parseInt(RegExp.$2, 16), parseInt(RegExp.$3, 16), parseInt(RegExp.$4, 16), - parseInt(RegExp.$5, 16), parseInt(RegExp.$6, 16))); + parseInt(RegExp.$5, 16), parseInt(RegExp.$6, 16) + ]; + result.push(m.map(function(n) { return isNaN(n) ? '*' : '%02X'.format(n) }).join(':')); + } return result.length ? result.join(' ') : null; }; so.renderWidget = function(section_id, option_index, cfgvalue) { @@ -468,75 +850,99 @@ return view.extend({ return node; }; + so.validate = validateMACAddr.bind(so, pools); Object.keys(hosts).forEach(function(mac) { var hint = hosts[mac].name || L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0]; so.value(mac, hint ? '%s (%s)'.format(mac, hint) : mac); }); - so.write = function(section, value) { - var ip = this.map.lookupOption('ip', section)[0].formvalue(section); - var hosts = uci.sections('dhcp', 'host'); - var section_removed = false; - - for (var i = 0; i < hosts.length; i++) { - if (ip == hosts[i].ip) { - uci.set('dhcp', hosts[i]['.name'], 'mac', [hosts[i].mac, value].join(' ')); - uci.remove('dhcp', section); - section_removed = true; - break; - } - } - - if (!section_removed) { - uci.set('dhcp', section, 'mac', value); - } - } - - so = ss.option(form.Value, 'ip', _('IPv4-Address')); + so = ss.option(form.Value, 'ip', _('IPv4 address'), _('The IP address to be used for this host, or ignore to ignore any DHCP request from this host.')); + so.value('ignore', _('Ignore')); so.datatype = 'or(ip4addr,"ignore")'; so.validate = function(section, value) { - var mac = this.map.lookupOption('mac', section), - name = this.map.lookupOption('name', section), - m = mac ? mac[0].formvalue(section) : null, - n = name ? name[0].formvalue(section) : null; + var m = this.section.formvalue(section, 'mac'), + n = this.section.formvalue(section, 'name'); if ((m == null || m == '') && (n == null || n == '')) - return _('One of hostname or mac address must be specified!'); + return _('One of hostname or MAC address must be specified!'); - return true; + if (value == null || value == '' || value == 'ignore') + return true; + + var leases = uci.sections('dhcp', 'host'); + + for (var i = 0; i < leases.length; i++) + if (leases[i]['.name'] != section && leases[i].ip == value) + return _('The IP address %h is already used by another static lease').format(value); + + for (var i = 0; i < pools.length; i++) { + var net_mask = calculateNetwork(value, pools[i].netmask); + + if (net_mask && net_mask[0] == pools[i].network) + return true; + } + + return _('The IP address is outside of any DHCP pool address range'); }; - var ipaddrs = {}; - - Object.keys(hosts).forEach(function(mac) { - var addrs = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4); - - for (var i = 0; i < addrs.length; i++) - ipaddrs[addrs[i]] = hosts[mac].name; - }); - L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ipv4) { so.value(ipv4, ipaddrs[ipv4] ? '%s (%s)'.format(ipv4, ipaddrs[ipv4]) : ipv4); }); - so = ss.option(form.Value, 'gw', _('Gateway IPv4 Address')); + so = ss.option(form.Value, 'leasetime', + _('Lease time'), + _('Host-specific lease time, e.g. 5m, 3h, 7d.')); so.rmempty = true; - so.datatype = 'or(ip4addr,"ignore")'; - Object.keys(hosts).forEach(function(mac) { - if (hosts[mac].ipv4) - so.value(hosts[mac].ipv4); - }); + so.value('5m', _('5m (5 minutes)')); + so.value('3h', _('3h (3 hours)')); + so.value('12h', _('12h (12 hours - default)')); + so.value('7d', _('7d (7 days)')); + so.value('infinite', _('infinite (lease does not expire)')); - so = ss.option(form.Value, 'leasetime', _('Lease time')); - so.rmempty = true; - - so = ss.option(form.Value, 'duid', _('DUID')); + so = ss.option(form.Value, 'duid', + _('DUID'), + _('The DHCPv6-DUID (DHCP unique identifier) of this host.')); so.datatype = 'and(rangelength(20,36),hexstring)'; Object.keys(duids).forEach(function(duid) { so.value(duid, '%s (%s)'.format(duid, duids[duid].hostname || duids[duid].macaddr || duids[duid].ip6addr || '?')); }); - so = ss.option(form.Value, 'hostid', _('IPv6-Suffix (hex)')); + so = ss.option(form.Value, 'hostid', + _('IPv6-Suffix (hex)'), + _('The IPv6 interface identifier (address suffix) as hexadecimal number (max. 16 chars).')); + so.datatype = 'and(rangelength(0,16),hexstring)'; + + so = ss.option(form.DynamicList, 'tag', + _('Tag'), + _('Assign new, freeform tags to this entry.')); + + so = ss.option(form.DynamicList, 'match_tag', + _('Match Tag'), + _('When a host matches an entry then the special tag known is set. Use known to match all known hosts.') + '

    ' + + _('Ignore requests from unknown machines using !known.') + '

    ' + + _('If a host matches an entry which cannot be used because it specifies an address on a different subnet, the tag known-othernet is set.')); + so.value('known', _('known')); + so.value('!known', _('!known (not known)')); + so.value('known-othernet', _('known-othernet (on different subnet)')); + so.optional = true; + + so = ss.option(form.Value, 'instance', + _('Instance'), + _('Dnsmasq instance to which this DHCP host section is bound. If unspecified, the section is valid for all dnsmasq instances.')); + so.optional = true; + + Object.values(L.uci.sections('dhcp', 'dnsmasq')).forEach(function(val, index) { + so.value(index, '%s (Domain: %s, Local: %s)'.format(index, val.domain || '?', val.local || '?')); + }); + + + so = ss.option(form.Flag, 'broadcast', + _('Broadcast'), + _('Force broadcast DHCP response.')); + + so = ss.option(form.Flag, 'dns', + _('Forward/reverse DNS'), + _('Add static forward and reverse DNS entries for this host.')); o = s.taboption('leases', CBILeaseStatus, '__status__'); @@ -560,8 +966,17 @@ return view.extend({ else exp = '%t'.format(lease.expires); + var hint = lease.macaddr ? hosts[lease.macaddr] : null, + name = hint ? hint.name : null, + host = null; + + if (name && lease.hostname && lease.hostname != name) + host = '%s (%s)'.format(lease.hostname, name); + else if (lease.hostname) + host = lease.hostname; + return [ - lease.hostname || '?', + host || '-', lease.ipaddr, lease.macaddr, exp diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js b/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js index 5d6bd4765..1bfa95501 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js @@ -4,6 +4,7 @@ 'require fs'; 'require ui'; 'require uci'; +'require network'; return view.extend({ handleCommand: function(exec, args) { @@ -13,8 +14,7 @@ return view.extend({ buttons[i].setAttribute('disabled', 'true'); return fs.exec(exec, args).then(function(res) { - var out = document.querySelector('.command-output'); - out.style.display = ''; + var out = document.querySelector('textarea'); dom.content(out, [ res.stdout || '', res.stderr || '' ]); }).catch(function(err) { @@ -36,7 +36,7 @@ return view.extend({ handleTraceroute: function(ev, cmd) { var exec = cmd || 'traceroute', addr = ev.currentTarget.parentNode.previousSibling.value, - args = (exec == 'traceroute') ? [ '-q', '1', '-w', '1', '-n', addr ] : [ '-q', '1', '-w', '2', '-n', addr ]; + args = (exec == 'traceroute') ? [ '-4', '-q', '1', '-w', '1', '-n', '-m', String(L.env.rpctimeout || 20), addr ] : [ '-q', '1', '-w', '2', '-n', addr ]; return this.handleCommand(exec, args); }, @@ -47,12 +47,20 @@ return view.extend({ return this.handleCommand('nslookup', [ addr ]); }, + handleArpScan: function(ev, cmd) { + var addr = ev.currentTarget.parentNode.previousSibling.value; + + return this.handleCommand('arp-scan', [ '-l', '-I', addr ]); + }, + load: function() { return Promise.all([ L.resolveDefault(fs.stat('/bin/ping6'), {}), L.resolveDefault(fs.stat('/usr/bin/ping6'), {}), L.resolveDefault(fs.stat('/bin/traceroute6'), {}), L.resolveDefault(fs.stat('/usr/bin/traceroute6'), {}), + L.resolveDefault(fs.stat('/usr/bin/arp-scan'), {}), + network.getDevices(), uci.load('luci') ]); }, @@ -60,15 +68,15 @@ return view.extend({ render: function(res) { var has_ping6 = res[0].path || res[1].path, has_traceroute6 = res[2].path || res[3].path, + has_arpscan = res[4].path, + devices = res[5], dns_host = uci.get('luci', 'diag', 'dns') || 'openwrt.org', ping_host = uci.get('luci', 'diag', 'ping') || 'openwrt.org', route_host = uci.get('luci', 'diag', 'route') || 'openwrt.org'; - return E([], [ - E('h2', {}, [ _('Network Utilities') ]), - E('table', { 'class': 'table' }, [ + var table = E('table', { 'class': 'table' }, [ E('tr', { 'class': 'tr' }, [ - E('td', { 'class': 'td left' }, [ + E('td', { 'class': 'td left', 'style': 'overflow:initial' }, [ E('input', { 'style': 'margin:5px 0', 'type': 'text', @@ -91,7 +99,7 @@ return view.extend({ ]) ]), - E('td', { 'class': 'td left' }, [ + E('td', { 'class': 'td left', 'style': 'overflow:initial' }, [ E('input', { 'style': 'margin:5px 0', 'type': 'text', @@ -126,11 +134,45 @@ return view.extend({ 'click': ui.createHandlerFn(this, 'handleNslookup') }, [ _('Nslookup') ]) ]) - ]) + ]), + + has_arpscan ? E('td', { 'class': 'td left' }, [ + E('select', { + 'style': 'margin:5px 0' + }, devices.map(function(device) { + if (!device.isUp()) + return E([]); + + return E('option', { 'value': device.getName() }, [ device.getI18n() ]); + })), + E('span', { 'class': 'diag-action' }, [ + E('button', { + 'class': 'cbi-button cbi-button-action', + 'click': ui.createHandlerFn(this, 'handleArpScan') + }, [ _('Arp-scan') ]) + ]) + ]) : E([]), ]) - ]), - E('pre', { 'class': 'command-output', 'style': 'display:none' }) + ]); + + var view = E('div', { 'class': 'cbi-map'}, [ + E('h2', {}, [ _('Diagnostics') ]), + E('div', { 'class': 'cbi-map-descr'}, _('Execution of various network commands to check the connection and name resolution to other systems.')), + table, + E('div', {'class': 'cbi-section'}, [ + E('div', { 'id' : 'command-output'}, + E('textarea', { + 'id': 'widget.command-output', + 'style': 'width: 100%; font-family:monospace; white-space:pre', + 'readonly': true, + 'wrap': 'off', + 'rows': '20' + }) + ) + ]) ]); + + return view; }, handleSaveApply: null, diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js b/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js deleted file mode 100644 index 93ebf5ba6..000000000 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; -'require view'; -'require rpc'; -'require form'; - -return view.extend({ - callHostHints: rpc.declare({ - object: 'luci-rpc', - method: 'getHostHints', - expect: { '': {} } - }), - - load: function() { - return this.callHostHints(); - }, - - render: function(hosts) { - var m, s, o; - - m = new form.Map('dhcp', _('Hostnames')); - - s = m.section(form.GridSection, 'domain', _('Host entries')); - s.addremove = true; - s.anonymous = true; - s.sortable = true; - - o = s.option(form.Value, 'name', _('Hostname')); - o.datatype = 'hostname'; - o.rmempty = true; - - o = s.option(form.Value, 'ip', _('IP address')); - o.datatype = 'ipaddr'; - o.rmempty = true; - - var ipaddrs = {}; - - Object.keys(hosts).forEach(function(mac) { - var addrs = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4); - - for (var i = 0; i < addrs.length; i++) - ipaddrs[addrs[i]] = hosts[mac].name || mac; - }); - - L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ipv4) { - o.value(ipv4, '%s (%s)'.format(ipv4, ipaddrs[ipv4])); - }); - - return m.render(); - } -}); diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js index ff179d404..2a952f263 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js @@ -228,6 +228,23 @@ function get_netmask(s, use_cfgvalue) { return subnetmask; } +function has_peerdns(proto) { + switch (proto) { + case 'dhcp': + case 'dhcpv6': + case 'qmi': + case 'ppp': + case 'pppoe': + case 'pppoa': + case 'pptp': + case 'openvpn': + case 'sstp': + return true; + } + + return false; +} + var cbiRichListValue = form.ListValue.extend({ renderWidget: function(section_id, option_index, cfgvalue) { var choices = this.transformChoices(); @@ -488,7 +505,7 @@ return view.extend({ }; s.modaltitle = function(section_id) { - return _('Interfaces') + ' » ' + section_id.toUpperCase(); + return _('Interfaces') + ' » ' + section_id; }; s.renderRowActions = function(section_id) { @@ -535,7 +552,7 @@ return view.extend({ var protocols = network.getProtocols(); protocols.sort(function(a, b) { - return a.getProtocol() > b.getProtocol(); + return L.naturalCompare(a.getProtocol(), b.getProtocol()); }); o = s.taboption('general', form.DummyValue, '_ifacestat_modal', _('Status')); @@ -643,7 +660,7 @@ return view.extend({ E('p', _('No DHCP Server configured for this interface') + '   '), E('button', { 'class': 'cbi-button cbi-button-add', - 'title': _('Setup DHCP Server'), + 'title': _('Set up DHCP Server'), 'click': ui.createHandlerFn(this, function(section_id, ev) { this.map.save(function() { uci.add('dhcp', 'dhcp', section_id); @@ -659,7 +676,7 @@ return view.extend({ } }); }, ifc.getName()) - }, _('Setup DHCP Server')) + }, _('Set up DHCP Server')) ]); }; @@ -723,12 +740,35 @@ return view.extend({ var hybrid_downstream_desc = _('Operate in relay mode if a designated master interface is configured and active, otherwise fall back to server mode.'), ndp_downstream_desc = _('Operate in relay mode if a designated master interface is configured and active, otherwise disable NDP proxying.'), hybrid_master_desc = _('Operate in relay mode if an upstream IPv6 prefix is present, otherwise disable service.'), + ra_server_allowed = true, checked = this.formvalue(section_id), dhcpv6 = this.section.getOption('dhcpv6').getUIElement(section_id), ndp = this.section.getOption('ndp').getUIElement(section_id), ra = this.section.getOption('ra').getUIElement(section_id); - if (checked == '1' || protoval != 'static') { + /* Assume that serving RAs by default is fine, but disallow it for certain + interface protocols such as DHCP, DHCPv6 or the various PPP flavors. + The intent is to only allow RA serving for interface protocols doing + some kind of static IP config over something resembling a layer 2 + ethernet device. */ + switch (protoval) { + case 'dhcp': + case 'dhcpv6': + case '3g': + case 'l2tp': + case 'ppp': + case 'pppoa': + case 'pppoe': + case 'pptp': + case 'pppossh': + case 'ipip': + case 'gre': + case 'grev6': + ra_server_allowed = false; + break; + } + + if (checked == '1' || !ra_server_allowed) { dhcpv6.node.querySelector('li[data-value="server"]').setAttribute('unselectable', ''); if (dhcpv6.getValue() == 'server') @@ -746,7 +786,7 @@ return view.extend({ ndp.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_master_desc; } else { - if (protoval == 'static') { + if (ra_server_allowed) { dhcpv6.node.querySelector('li[data-value="server"]').removeAttribute('unselectable'); ra.node.querySelector('li[data-value="server"]').removeAttribute('unselectable'); } @@ -805,9 +845,23 @@ return view.extend({ return flags.length ? flags : [ 'other-config' ]; }; so.remove = function(section_id) { - uci.set('dhcp', section_id, 'ra_flags', [ 'none' ]); + var existing = L.toArray(uci.get('dhcp', section_id, 'ra_flags')); + if (this.isActive(section_id)) { + if (existing.length != 1 || existing[0] != 'none') + uci.set('dhcp', section_id, 'ra_flags', [ 'none' ]); + } + else if (existing.length) { + uci.unset('dhcp', section_id, 'ra_flags'); + } }; + so = ss.taboption('ipv6-ra', form.Value, 'ra_pref64', _('NAT64 prefix'), _('Announce NAT64 prefix in RA messages.')); + so.optional = true; + so.datatype = 'cidr6'; + so.placeholder = '64:ff9b::/96'; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); + so = ss.taboption('ipv6-ra', form.Value, 'ra_maxinterval', _('Max RA interval'), _('Maximum time allowed between sending unsolicited RA. Default is 600 seconds.')); so.optional = true; so.datatype = 'uinteger'; @@ -835,15 +889,17 @@ return view.extend({ so.depends('ra', 'server'); so.depends({ ra: 'hybrid', master: '0' }); so.load = function(section_id) { - var dev = ifc.getL3Device(); + var dev = ifc.getL3Device(), + path = dev ? "/proc/sys/net/ipv6/conf/%s/mtu".format(dev.getName()) : null; - if (dev) { - var path = "/proc/sys/net/ipv6/conf/%s/mtu".format(dev.getName()); + return Promise.all([ + dev ? L.resolveDefault(fs.read(path), dev.getMTU()) : null, + this.super('load', [section_id]) + ]).then(L.bind(function(res) { + this.placeholder = +res[0]; - return L.resolveDefault(fs.read(path), dev.getMTU()).then(L.bind(function(data) { - this.placeholder = data; - }, this)); - } + return res[1]; + }, this)); }; so = ss.taboption('ipv6-ra', form.Value, 'ra_hoplimit', _('RA Hop Limit'), _('The maximum hops to be published in RA messages. Maximum is 255 hops.')); @@ -852,15 +908,17 @@ return view.extend({ so.depends('ra', 'server'); so.depends({ ra: 'hybrid', master: '0' }); so.load = function(section_id) { - var dev = ifc.getL3Device(); + var dev = ifc.getL3Device(), + path = dev ? "/proc/sys/net/ipv6/conf/%s/hop_limit".format(dev.getName()) : null; - if (dev) { - var path = "/proc/sys/net/ipv6/conf/%s/hop_limit".format(dev.getName()); + return Promise.all([ + dev ? L.resolveDefault(fs.read(path), 64) : null, + this.super('load', [section_id]) + ]).then(L.bind(function(res) { + this.placeholder = +res[0]; - return L.resolveDefault(fs.read(path), 64).then(L.bind(function(data) { - this.placeholder = data; - }, this)); - } + return res[1]; + }, this)); }; @@ -874,22 +932,32 @@ return view.extend({ _('Forward DHCPv6 messages between the designated master interface and downstream interfaces.')); so.value('hybrid', _('hybrid mode'), ' '); + so = ss.taboption('ipv6', form.Value, 'dhcpv6_pd_min_len', _('PD minimum length'), + _('Configures the minimum delegated prefix length assigned to a requesting downstream router, potentially overriding a requested prefix length. If left unspecified, the device will assign the smallest available prefix greater than or equal to the requested prefix.')); + so.datatype = 'range(1,62)'; + so.depends('dhcpv6', 'server'); so = ss.taboption('ipv6', form.DynamicList, 'dns', _('Announced IPv6 DNS servers'), _('Specifies a fixed list of IPv6 DNS server addresses to announce via DHCPv6. If left unspecified, the device will announce itself as IPv6 DNS server unless the Local IPv6 DNS server option is disabled.')); so.datatype = 'ip6addr("nomask")'; /* restrict to IPv6 only for now since dnsmasq (DHCPv4) does not honour this option */ + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); so.depends('dhcpv6', 'server'); so.depends({ dhcpv6: 'hybrid', master: '0' }); so = ss.taboption('ipv6', form.Flag, 'dns_service', _('Local IPv6 DNS server'), _('Announce this device as IPv6 DNS server.')); so.default = so.enabled; + so.depends({ ra: 'server', dns: /^$/ }); + so.depends({ ra: 'hybrid', dns: /^$/, master: '0' }); so.depends({ dhcpv6: 'server', dns: /^$/ }); so.depends({ dhcpv6: 'hybrid', dns: /^$/, master: '0' }); so = ss.taboption('ipv6', form.DynamicList, 'domain', _('Announced DNS domains'), _('Specifies a fixed list of DNS search domains to announce via DHCPv6. If left unspecified, the local device DNS search domain will be announced.')); so.datatype = 'hostname'; + so.depends('ra', 'server'); + so.depends({ ra: 'hybrid', master: '0' }); so.depends('dhcpv6', 'server'); so.depends({ dhcpv6: 'hybrid', master: '0' }); @@ -903,7 +971,7 @@ return view.extend({ so.value('hybrid', _('hybrid mode'), ' '); - so = ss.taboption('ipv6', form.Flag, 'ndproxy_routing', _('Learn routes'), _('Setup routes for proxied IPv6 neighbours.')); + so = ss.taboption('ipv6', form.Flag, 'ndproxy_routing', _('Learn routes'), _('Set up routes for proxied IPv6 neighbours.')); so.default = so.enabled; so.depends('ndp', 'relay'); so.depends('ndp', 'hybrid'); @@ -911,6 +979,18 @@ return view.extend({ so = ss.taboption('ipv6', form.Flag, 'ndproxy_slave', _('NDP-Proxy slave'), _('Set interface as NDP-Proxy external slave. Default is off.')); so.depends({ ndp: 'relay', master: '0' }); so.depends({ ndp: 'hybrid', master: '0' }); + + so = ss.taboption('ipv6', form.Value, 'preferred_lifetime', _('IPv6 Prefix Lifetime'), _('Preferred lifetime for a prefix.')); + so.optional = true; + so.placeholder = '12h'; + so.value('5m', _('5m (5 minutes)')); + so.value('3h', _('3h (3 hours)')); + so.value('12h', _('12h (12 hours - default)')); + so.value('7d', _('7d (7 days)')); + + //This is a ra_* setting, but its placement is more logical/findable under IPv6 settings. + so = ss.taboption('ipv6', form.Flag, 'ra_useleasetime', _('Follow IPv4 Lifetime'), _('DHCPv4 leasetime is used as limit and preferred lifetime of the IPv6 prefix.')); + so.optional = true; } ifc.renderFormOptions(s); @@ -919,13 +999,13 @@ return view.extend({ o = nettools.replaceOption(s, 'advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured')); o.default = o.enabled; - if (protoval != 'static') { + if (has_peerdns(protoval)) { o = nettools.replaceOption(s, 'advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored')); o.default = o.enabled; } o = nettools.replaceOption(s, 'advanced', form.DynamicList, 'dns', _('Use custom DNS servers')); - if (protoval != 'static') + if (has_peerdns(protoval)) o.depends('peerdns', '0'); o.datatype = 'ipaddr'; @@ -961,7 +1041,12 @@ return view.extend({ o = nettools.replaceOption(s, 'advanced', form.Value, 'ip6table', _('Override IPv6 routing table')); o.datatype = 'or(uinteger, string)'; for (var i = 0; i < rtTables.length; i++) - o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][0], rtTables[i][1])); + o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0])); + + if (protoval == 'dhcpv6') { + o = nettools.replaceOption(s, 'advanced', form.Flag, 'sourcefilter', _('IPv6 source routing'), _('Automatically handle multiple uplink interfaces using source-based policy routing.')); + o.default = o.enabled; + } o = nettools.replaceOption(s, 'advanced', form.Flag, 'delegate', _('Delegate IPv6 prefixes'), _('Enable downstream delegation of IPv6 prefixes available on this interface')); o.default = o.enabled; @@ -1080,7 +1165,7 @@ return view.extend({ proto, name, device; protocols.sort(function(a, b) { - return a.getProtocol() > b.getProtocol(); + return L.naturalCompare(a.getProtocol(), b.getProtocol()); }); s2.render = function() { @@ -1154,6 +1239,9 @@ return view.extend({ protoclass.addDevice(device.formvalue('_new_')); m.children[0].addedSection = section_id; + + ui.hideModal(); + ui.showModal(null, E('p', { 'class': 'spinning' }, [ _('Loading data…') ])); }).then(L.bind(m.children[0].renderMoreOptionsModal, m.children[0], nameval)); }); }) @@ -1183,9 +1271,9 @@ return view.extend({ var node = E('div', { 'class': 'ifacebox' }, [ E('div', { 'class': 'ifacebox-head', - 'style': 'background-color:%s'.format(zone ? zone.getColor() : '#EEEEEE'), + 'style': firewall.getZoneColorStyle(zone), 'title': zone ? _('Part of zone %q').format(zone.getName()) : _('No zone assigned') - }, E('strong', net.getName().toUpperCase())), + }, E('strong', net.getName())), E('div', { 'class': 'ifacebox-body', 'id': '%s-ifc-devices'.format(section_id), @@ -1239,7 +1327,7 @@ return view.extend({ s.cfgsections = function() { var sections = uci.sections('network', 'device'), - section_ids = sections.sort(function(a, b) { return a.name > b.name }).map(function(s) { return s['.name'] }); + section_ids = sections.sort(function(a, b) { return L.naturalCompare(a.name, b.name) }).map(function(s) { return s['.name'] }); for (var i = 0; i < netDevs.length; i++) { if (sections.filter(function(s) { return s.name == netDevs[i].getName() }).length) @@ -1284,7 +1372,7 @@ return view.extend({ var trEl = this.super('renderRowActions', [ section_id, _('Configure…') ]), deleteBtn = trEl.querySelector('button:last-child'); - deleteBtn.firstChild.data = _('Reset'); + deleteBtn.firstChild.data = _('Unconfigure'); deleteBtn.setAttribute('title', _('Remove related device settings from the configuration')); deleteBtn.disabled = section_id.match(/^dev:/) ? true : null; @@ -1317,9 +1405,26 @@ return view.extend({ for (var i = 0; i < map.addedVLANs.length; i++) uci.remove('network', map.addedVLANs[i]); + if (this.addedSection) + uci.remove('network', this.addedSection); + return form.GridSection.prototype.handleModalCancel.apply(this, arguments); }; + s.handleRemove = function(section_id /*, ... */) { + var name = uci.get('network', section_id, 'name'), + type = uci.get('network', section_id, 'type'); + + if (name != null && type == 'bridge') { + uci.sections('network', 'bridge-vlan', function(bvs) { + if (bvs.device == name) + uci.remove('network', bvs['.name']); + }); + } + + return form.GridSection.prototype.handleRemove.apply(this, arguments); + }; + function getDevice(section_id) { var m = section_id.match(/^dev:(.+)$/), name = m ? m[1] : uci.get('network', section_id, 'name'); @@ -1422,7 +1527,7 @@ return view.extend({ mac = dev ? dev.getMAC() : null; return val ? E('strong', { - 'data-tooltip': _('The value is overridden by configuration. Original: %s').format(mac || _('unknown')) + 'data-tooltip': _('The value is overridden by configuration.') }, [ val.toUpperCase() ]) : (mac || '-'); }; @@ -1434,7 +1539,7 @@ return view.extend({ mtu = dev ? dev.getMTU() : null; return val ? E('strong', { - 'data-tooltip': _('The value is overridden by configuration. Original: %s').format(mtu || _('unknown')) + 'data-tooltip': _('The value is overridden by configuration.') }, [ val ]) : (mtu || '-').toString(); }; @@ -1454,21 +1559,27 @@ return view.extend({ s.anonymous = true; o = s.option(form.ListValue, 'annex', _('Annex')); - o.value('a', _('Annex A + L + M (all)')); - o.value('b', _('Annex B (all)')); - o.value('j', _('Annex J (all)')); - o.value('m', _('Annex M (all)')); - o.value('bdmt', _('Annex B G.992.1')); - o.value('b2', _('Annex B G.992.3')); - o.value('b2p', _('Annex B G.992.5')); + if (dslModemType == 'vdsl') { + o.value('a', _('ADSL (all variants) Annex A/L/M + VDSL2 Annex A/B/C')); + o.value('b', _('ADSL (all variants) Annex B + VDSL2 Annex A/B/C')); + o.value('j', _('ADSL (all variants) Annex B/J + VDSL2 Annex A/B/C')); + } else { + o.value('a', _('ADSL (all variants) Annex A/L/M')); + o.value('b', _('ADSL (all variants) Annex B')); + o.value('j', _('ADSL (all variants) Annex B/J')); + } + o.value('m', _('ADSL (all variants) Annex M')); o.value('at1', _('ANSI T1.413')); - o.value('admt', _('Annex A G.992.1')); - o.value('alite', _('Annex A G.992.2')); - o.value('a2', _('Annex A G.992.3')); - o.value('a2p', _('Annex A G.992.5')); - o.value('l', _('Annex L G.992.3 POTS 1')); - o.value('m2', _('Annex M G.992.3')); - o.value('m2p', _('Annex M G.992.5')); + o.value('admt', _('ADSL (G.992.1) Annex A')); + o.value('bdmt', _('ADSL (G.992.1) Annex B')); + o.value('alite', _('Splitterless ADSL (G.992.2) Annex A')); + o.value('a2', _('ADSL2 (G.992.3) Annex A')); + o.value('b2', _('ADSL2 (G.992.3) Annex B')); + o.value('l', _('ADSL2 (G.992.3) Annex L')); + o.value('m2', _('ADSL2 (G.992.3) Annex M')); + o.value('a2p', _('ADSL2+ (G.992.5) Annex A')); + o.value('b2p', _('ADSL2+ (G.992.5) Annex B')); + o.value('m2p', _('ADSL2+ (G.992.5) Annex M')); o = s.option(form.ListValue, 'tone', _('Tone')); o.value('', _('auto')); diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js b/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js index 7e11a3cb4..4004be219 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js @@ -1,22 +1,35 @@ 'use strict'; 'require view'; +'require fs'; +'require uci'; 'require form'; 'require network'; 'require tools.widgets as widgets'; return view.extend({ load: function() { - return network.getDevices(); + return Promise.all([ + network.getDevices(), + fs.lines('/etc/iproute2/rt_tables') + ]); }, - render: function(netdevs) { - var m, s, o; + render: function(data) { + var netDevs = data[0], + m, s, o; - m = new form.Map('network', _('Routes'), _('Routes specify over which interface and gateway a certain host or network can be reached.')); + var rtTables = data[1].map(function(l) { + var m = l.trim().match(/^(\d+)\s+(\S+)$/); + return m ? [ +m[1], m[2] ] : null; + }).filter(function(e) { + return e && e[0] > 0; + }); + + m = new form.Map('network', _('Routing'), _('Routing defines over which interface and gateway a certain host or network can be reached.')); m.tabbed = true; - for (var i = 4; i <= 6; i += 2) { - s = m.section(form.GridSection, (i == 4) ? 'route' : 'route6', (i == 4) ? _('Static IPv4 Routes') : _('Static IPv6 Routes')); + for (var family = 4; family <= 6; family += 2) { + s = m.section(form.GridSection, (family == 6) ? 'route6' : 'route', (family == 6) ? _('Static IPv6 Routes') : _('Static IPv4 Routes')); s.anonymous = true; s.addremove = true; s.sortable = true; @@ -25,44 +38,13 @@ return view.extend({ s.tab('general', _('General Settings')); s.tab('advanced', _('Advanced Settings')); - o = s.taboption('general', widgets.NetworkSelect, 'interface', _('Interface')); - o.rmempty = false; + o = s.taboption('general', widgets.NetworkSelect, 'interface', _('Interface'), _('Specifies the logical interface name of the parent (or master) interface this route belongs to')); + o.loopback = true; o.nocreate = true; - - o = s.taboption('general', form.Flag, 'disabled', _('Disable'), _('Disable this route')); - o.rmempty = true; - o.default = o.disabled; - - o = s.taboption('general', form.Value, 'target', _('Target'), (i == 4) ? _('Host-IP or Network') : _('IPv6-Address or Network (CIDR)')); - o.datatype = (i == 4) ? 'ip4addr' : 'ip6addr'; o.rmempty = false; - if (i == 4) { - o = s.taboption('general', form.Value, 'netmask', _('IPv4-Netmask'), _('if target is a network')); - o.placeholder = '255.255.255.255'; - o.datatype = 'ip4addr'; - o.rmempty = true; - } - - o = s.taboption('general', form.Value, 'gateway', (i == 4) ? _('IPv4-Gateway') : _('IPv6-Gateway')); - o.datatype = (i == 4) ? 'ip4addr' : 'ip6addr'; - o.rmempty = true; - - o = s.taboption('advanced', form.Value, 'metric', _('Metric')); - o.placeholder = 0; - o.datatype = (i == 4) ? 'range(0,255)' : 'range(0,65535)'; - o.rmempty = true; - o.textvalue = function(section_id) { - return this.cfgvalue(section_id) || 0; - }; - - o = s.taboption('advanced', form.Value, 'mtu', _('MTU')); - o.placeholder = 1500; - o.datatype = 'range(64,9000)'; - o.rmempty = true; + o = s.taboption('general', form.ListValue, 'type', _('Route type'), _('Specifies the route type to be created')); o.modalonly = true; - - o = s.taboption('advanced', form.ListValue, 'type', _('Route type')); o.value('', 'unicast'); o.value('local'); o.value('broadcast'); @@ -71,36 +53,155 @@ return view.extend({ o.value('prohibit'); o.value('blackhole'); o.value('anycast'); - o.default = ''; - o.rmempty = true; - o.modalonly = true; + o.value('throw'); - o = s.taboption('advanced', form.Value, 'table', _('Route table')); - o.value('local', 'local (255)'); - o.value('main', 'main (254)'); - o.value('default', 'default (253)'); - o.rmempty = true; - o.modalonly = true; + o = s.taboption('general', form.Value, 'target', _('Target'), _('Network address')); + o.rmempty = false; + o.datatype = (family == 6) ? 'cidr6' : 'cidr4'; + o.placeholder = (family == 6) ? '::/0' : '0.0.0.0/0'; o.cfgvalue = function(section_id) { - var cfgvalue = this.map.data.get('network', section_id, 'table'); - return cfgvalue || 'main'; + var section_type = uci.get('network', section_id, '.type'), + target = uci.get('network', section_id, 'target'), + mask = uci.get('network', section_id, 'netmask'), + v6 = (section_type == 'route6') ? true : false, + bits = mask ? network.maskToPrefix(mask, v6) : (v6 ? 128 : 32); + if (target) { + return target.split('/')[1] ? target : target + '/' + bits; + } + } + o.write = function(section_id, formvalue) { + uci.set('network', section_id, 'target', formvalue); + uci.unset('network', section_id, 'netmask'); + } + + o = s.taboption('general', form.Value, 'gateway', _('Gateway'), _('Specifies the network gateway. If omitted, the gateway from the parent interface is taken if any, otherwise creates a link scope route. If set to 0.0.0.0 no gateway will be specified for the route')); + o.datatype = (family == 6) ? 'ip6addr("nomask")' : 'ip4addr("nomask")'; + o.placeholder = (family == 6) ? 'fe80::1' : '192.168.0.1'; + + o = s.taboption('advanced', form.Value, 'metric', _('Metric'), _('Specifies the route metric to use')); + o.datatype = 'uinteger'; + o.placeholder = 0; + o.textvalue = function(section_id) { + return this.cfgvalue(section_id) || E('em', _('auto')); }; - o = s.taboption('advanced', form.Value, 'source', _('Source Address')); - o.placeholder = E('em', _('automatic')); - for (var j = 0; j < netdevs.length; j++) { - var addrs = netdevs[j].getIPAddrs(); - for (var k = 0; k < addrs.length; k++) - o.value(addrs[k].split('/')[0]); - } - o.datatype = (i == 4) ? 'ip4addr' : 'ip6addr'; - o.default = ''; - o.rmempty = true; + o = s.taboption('advanced', form.Value, 'mtu', _('MTU'), _('Defines a specific MTU for this route')); o.modalonly = true; + o.datatype = 'and(uinteger,range(64,9000))'; + o.placeholder = 1500; - o = s.taboption('advanced', form.Flag, 'onlink', _('On-Link route')); + o = s.taboption('advanced', form.Value, 'table', _('Table'), _('The rule target is a table lookup ID: a numeric table index ranging from 0 to 65535 or symbol alias declared in /etc/iproute2/rt_tables. Special aliases local (255), main (254) and default (253) are also valid')); + o.datatype = 'or(uinteger, string)'; + for (var i = 0; i < rtTables.length; i++) + o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0])); + o.textvalue = function(section_id) { + return this.cfgvalue(section_id) || E('em', _('auto')); + }; + + o = s.taboption('advanced', form.Value, 'source', _('Source'), _('Specifies the preferred source address when sending to destinations covered by the target')); + o.modalonly = true; + o.datatype = (family == 6) ? 'ip6addr' : 'ip4addr'; + for (var i = 0; i < netDevs.length; i++) { + var addrs = (family == 6) ? netDevs[i].getIP6Addrs() : netDevs[i].getIPAddrs(); + for (var j = 0; j < addrs.length; j++) + o.value(addrs[j].split('/')[0]); + } + + o = s.taboption('advanced', form.Flag, 'onlink', _('On-link'), _('When enabled, gateway is on-link even if the gateway does not match any interface prefix')); + o.modalonly = true; + o.default = o.disabled; + + o = s.taboption('advanced', form.Flag, 'disabled', _('Disable')); + o.modalonly = false; + o.editable = true; + o.default = o.disabled; + } + + for (var family = 4; family <= 6; family += 2) { + s = m.section(form.GridSection, (family == 6) ? 'rule6' : 'rule', (family == 6) ? _('IPv6 Rules') : _('IPv4 Rules')); + s.anonymous = true; + s.addremove = true; + s.sortable = true; + s.nodescriptions = true; + + s.tab('general', _('General Settings')); + s.tab('advanced', _('Advanced Settings')); + + o = s.taboption('general', form.Value, 'priority', _('Priority'), _('Specifies the ordering of the IP rules')); + o.datatype = 'uinteger'; + o.placeholder = 30000; + o.textvalue = function(section_id) { + return this.cfgvalue(section_id) || E('em', _('auto')); + }; + + o = s.taboption('general', form.ListValue, 'action', _('Rule type'), _('Specifies the rule target routing action')); + o.modalonly = true; + o.value('', 'unicast'); + o.value('unreachable'); + o.value('prohibit'); + o.value('blackhole'); + o.value('throw'); + + o = s.taboption('general', widgets.NetworkSelect, 'in', _('Incoming interface'), _('Specifies the incoming logical interface name')); + o.loopback = true; + o.nocreate = true; + + o = s.taboption('general', form.Value, 'src', _('Source'), _('Specifies the source subnet to match (CIDR notation)')); + o.datatype = (family == 6) ? 'cidr6' : 'cidr4'; + o.placeholder = (family == 6) ? '::/0' : '0.0.0.0/0'; + o.textvalue = function(section_id) { + return this.cfgvalue(section_id) || E('em', _('any')); + }; + + o = s.taboption('general', widgets.NetworkSelect, 'out', _('Outgoing interface'), _('Specifies the outgoing logical interface name')); + o.loopback = true; + o.nocreate = true; + + o = s.taboption('general', form.Value, 'dest', _('Destination'), _('Specifies the destination subnet to match (CIDR notation)')); + o.datatype = (family == 6) ? 'cidr6' : 'cidr4'; + o.placeholder = (family == 6) ? '::/0' : '0.0.0.0/0'; + o.textvalue = function(section_id) { + return this.cfgvalue(section_id) || E('em', _('any')); + }; + + o = s.taboption('general', form.Value, 'lookup', _('Table'), _('The rule target is a table lookup ID: a numeric table index ranging from 0 to 65535 or symbol alias declared in /etc/iproute2/rt_tables. Special aliases local (255), main (254) and default (253) are also valid')); + o.datatype = 'or(uinteger, string)'; + for (var i = 0; i < rtTables.length; i++) + o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0])); + + o = s.taboption('advanced', form.Value, 'goto', _('Jump to rule'), _('The rule target is a jump to another rule specified by its priority value')); + o.modalonly = true; + o.datatype = 'uinteger'; + o.placeholder = 80000; + + o = s.taboption('advanced', form.Value, 'mark', _('Firewall mark'), _('Specifies the fwmark and optionally its mask to match, e.g. 0xFF to match mark 255 or 0x0/0x1 to match any even mark value')); + o.modalonly = true; + o.datatype = 'string'; + o.placeholder = '0x1/0xf'; + + o = s.taboption('advanced', form.Value, 'tos', _('Type of service'), _('Specifies the TOS value to match in IP headers')); + o.modalonly = true; + o.datatype = 'uinteger'; + o.placeholder = 10; + + o = s.taboption('advanced', form.Value, 'uidrange', _('User identifier'), _('Specifies an individual UID or range of UIDs to match, e.g. 1000 to match corresponding UID or 1000-1005 to inclusively match all UIDs within the corresponding range')); + o.modalonly = true; + o.datatype = 'string'; + o.placeholder = '1000-1005'; + + o = s.taboption('advanced', form.Value, 'suppress_prefixlength', _('Prefix suppressor'), _('Reject routing decisions that have a prefix length less than or equal to the specified value')); + o.modalonly = true; + o.datatype = (family == 6) ? 'ip6prefix' : 'ip4prefix'; + o.placeholder = (family == 6) ? 64 : 24; + + o = s.taboption('advanced', form.Flag, 'invert', _('Invert match'), _('If set, the meaning of the match options is inverted')); + o.modalonly = true; + o.default = o.disabled; + + o = s.taboption('advanced', form.Flag, 'disabled', _('Disable')); + o.modalonly = false; + o.editable = true; o.default = o.disabled; - o.rmempty = true; } return m.render(); diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js b/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js index 3133d2725..535a133e7 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js @@ -180,8 +180,10 @@ return view.extend({ s = m.section(form.NamedSection, sid, 'switch', switch_title); s.addremove = false; - if (feat.vlan_option) - s.option(form.Flag, feat.vlan_option, _('Enable VLAN functionality')); + if (feat.vlan_option) { + o = s.option(form.Flag, feat.vlan_option, _('Enable VLAN functionality')); + o.rmempty = false; + } if (feat.learning_option) { o = s.option(form.Flag, feat.learning_option, _('Enable learning and aging')); @@ -222,7 +224,7 @@ return view.extend({ s.filter = function(section_id) { var device = uci.get('network', section_id, 'device'); - return (device == switch_name); + return (device == this.device); }; s.cfgsections = function() { @@ -246,7 +248,7 @@ return view.extend({ max_vid = 0; for (var j = 0; j < sections.length; j++) { - if (sections[j].device != s.device) + if (sections[j].device != this.device) continue; var vlan = +sections[j].vlan, @@ -259,7 +261,7 @@ return view.extend({ max_vid = vid; } - uci.set('network', section_id, 'device', s.device); + uci.set('network', section_id, 'device', this.device); uci.set('network', section_id, 'vlan', max_vlan + 1); if (feat.vid_option) @@ -268,8 +270,6 @@ return view.extend({ return this.map.save(null, true); }; - var port_opts = []; - o = s.option(form.Value, feat.vid_option || 'vlan', 'VLAN ID'); o.rmempty = false; o.forcewrite = true; @@ -297,21 +297,23 @@ return view.extend({ return true; }; + var port_opts = o.port_opts = []; + o.write = function(section_id, value) { var topology = this.section.topology, values = []; - for (var i = 0; i < port_opts.length; i++) { - var tagging = port_opts[i].formvalue(section_id), + for (var i = 0; i < this.port_opts.length; i++) { + var tagging = this.port_opts[i].formvalue(section_id), portspec = Array.isArray(topology.ports) ? topology.ports[i] : null; if (tagging == 't') - values.push(port_opts[i].option + tagging); + values.push(this.port_opts[i].option + tagging); else if (tagging == 'u') - values.push(port_opts[i].option); + values.push(this.port_opts[i].option); if (portspec && portspec.device) { - var old_tag = port_opts[i].cfgvalue(section_id), + var old_tag = this.port_opts[i].cfgvalue(section_id), old_vid = this.cfgvalue(section_id); if (old_tag != tagging || old_vid != value) { diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js b/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js index 5115a69eb..4c2daf588 100644 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js @@ -314,24 +314,16 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.channels = { '2g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], '5g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], - '6g': [], + '6g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], '60g': [] }; for (var i = 0; i < data[1].length; i++) { - var band; - - if (data[1][i].mhz >= 2412 && data[1][i].mhz <= 2484) - band = '2g'; - else if (data[1][i].mhz >= 5160 && data[1][i].mhz <= 5885) - band = '5g'; - else if (data[1][i].mhz >= 5925 && data[1][i].mhz <= 7125) - band = '6g'; - else if (data[1][i].mhz >= 58329 && data[1][i].mhz <= 69120) - band = '60g'; - else + if (!data[1][i].band) continue; + var band = '%dg'.format(data[1][i].band); + this.channels[band].push( data[1][i].channel, '%d (%d Mhz)'.format(data[1][i].channel, data[1][i].mhz), @@ -343,10 +335,10 @@ var CBIWifiFrequencyValue = form.Value.extend({ .reduce(function(o, v) { o[v] = true; return o }, {}); this.modes = [ - '', 'Legacy', true, + '', 'Legacy', hwmodelist.a || hwmodelist.b || hwmodelist.g, 'n', 'N', hwmodelist.n, - 'ac', 'AC', hwmodelist.ac, - 'ax', 'AX', hwmodelist.ax + 'ac', 'AC', L.hasSystemFeature('hostapd', '11ac') && hwmodelist.ac, + 'ax', 'AX', L.hasSystemFeature('hostapd', '11ax') && hwmodelist.ax ]; var htmodelist = L.toArray(data[0] ? data[0].getHTModes() : null) @@ -375,7 +367,8 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.bands = { '': [ '2g', '2.4 GHz', this.channels['2g'].length > 3, - '5g', '5 GHz', this.channels['5g'].length > 3 + '5g', '5 GHz', this.channels['5g'].length > 3, + '60g', '60 GHz', this.channels['60g'].length > 0 ], 'n': [ '2g', '2.4 GHz', this.channels['2g'].length > 3, @@ -386,7 +379,8 @@ var CBIWifiFrequencyValue = form.Value.extend({ ], 'ax': [ '2g', '2.4 GHz', this.channels['2g'].length > 3, - '5g', '5 GHz', this.channels['5g'].length > 3 + '5g', '5 GHz', this.channels['5g'].length > 3, + '6g', '6 GHz', this.channels['6g'].length > 3 ] }; }, this)); @@ -479,7 +473,7 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.toggleWifiBand(elem); bwdt.value = htval; - chan.value = chval || chan.options[0].value; + chan.value = chval || (chan.options[0] ? chan.options[0].value : 'auto'); return elem; }, @@ -741,7 +735,8 @@ return view.extend({ load: function() { return Promise.all([ uci.changes(), - uci.load('wireless') + uci.load('wireless'), + uci.load('system') ]); }, @@ -941,7 +936,7 @@ return view.extend({ if (hwtype == 'mac80211') { o = ss.taboption('general', form.Flag, 'legacy_rates', _('Allow legacy 802.11b rates'), _('Legacy or badly behaving devices may require legacy 802.11b rates to interoperate. Airtime efficiency may be significantly reduced where these are used. It is recommended to not allow 802.11b rates where possible.')); - o.depends({'_freq': '11g', '!contains': true}); + o.depends({'_freq': '2g', '!contains': true}); o = ss.taboption('general', CBIWifiTxPowerValue, 'txpower', _('Maximum transmit power'), _('Specifies the maximum transmit power the wireless radio may use. Depending on regulatory requirements and wireless usage, the actual transmit power may be reduced by the driver.')); o.wifiNetwork = radioNet; @@ -985,6 +980,7 @@ return view.extend({ ss.tab('encryption', _('Wireless Security')); ss.tab('macfilter', _('MAC-Filter')); ss.tab('advanced', _('Advanced Settings')); + ss.tab('roaming', _('WLAN roaming'), _('Settings for assisting wireless clients in roaming between multiple APs: 802.11r, 802.11k and 802.11v')); o = ss.taboption('general', form.ListValue, 'mode', _('Mode')); o.value('ap', _('Access Point')); @@ -1089,6 +1085,7 @@ return view.extend({ o = ss.taboption('macfilter', form.DynamicList, 'maclist', _('MAC-List')); o.datatype = 'macaddr'; + o.retain = true; o.depends('macfilter', 'allow'); o.depends('macfilter', 'deny'); o.load = function(section_id) { @@ -1144,16 +1141,28 @@ return view.extend({ o.depends('mode', 'ap-wds'); o.default = o.enabled; + /* https://w1.fi/cgit/hostap/commit/?id=34f7c699a6bcb5c45f82ceb6743354ad79296078 */ + /* multicast_to_unicast https://github.com/openwrt/openwrt/commit/7babb978ad9d7fc29acb1ff86afb1eb343af303a */ + o = ss.taboption('advanced', form.Flag, 'multicast_to_unicast_all', _('Multi To Unicast'), _('ARP, IPv4 and IPv6 (even 802.1Q) with multicast destination MACs are unicast to the STA MAC address. Note: This is not Directed Multicast Service (DMS) in 802.11v. Note: might break receiver STA multicast expectations.')); + o.rmempty = true; + o = ss.taboption('advanced', form.Flag, 'isolate', _('Isolate Clients'), _('Prevents client-to-client communication')); o.depends('mode', 'ap'); o.depends('mode', 'ap-wds'); o = ss.taboption('advanced', form.Value, 'ifname', _('Interface name'), _('Override default interface name')); o.optional = true; + o.datatype = 'netdevname'; o.placeholder = radioNet.getIfname(); if (/^radio\d+\.network/.test(o.placeholder)) o.placeholder = ''; + var macaddr = uci.get('wireless', radioNet.getName(), 'macaddr'); + o = ss.taboption('advanced', form.Value, 'macaddr', _('MAC address'), _('Override default MAC address - the range of usable addresses might be limited by the driver')); + o.value('', _('driver default (%s)').format(!macaddr ? radioNet.getActiveBSSID() : _('no override'))); + o.value('random', _('randomly generated')); + o.datatype = "or('random',macaddr)"; + o = ss.taboption('advanced', form.Flag, 'short_preamble', _('Short Preamble')); o.default = o.enabled; @@ -1171,7 +1180,7 @@ return view.extend({ o.optional = true; o.datatype = 'uinteger'; - o = ss.taboption('advanced', form.Value, 'max_inactivity', _('Station inactivity limit'), _('sec')); + o = ss.taboption('advanced', form.Value, 'max_inactivity', _('Station inactivity limit'), _('802.11v: BSS Max Idle. Units: seconds.')); o.optional = true; o.placeholder = 300; o.datatype = 'uinteger'; @@ -1274,7 +1283,7 @@ return view.extend({ if (has_hostapd || has_supplicant) { crypto_modes.push(['psk2', 'WPA2-PSK', 35]); crypto_modes.push(['psk-mixed', 'WPA-PSK/WPA2-PSK Mixed Mode', 22]); - crypto_modes.push(['psk', 'WPA-PSK', 21]); + crypto_modes.push(['psk', 'WPA-PSK', 12]); } else { encr.description = _('WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP and ad-hoc mode) to be installed.'); @@ -1374,7 +1383,7 @@ return view.extend({ else if (hwtype == 'broadcom') { crypto_modes.push(['psk2', 'WPA2-PSK', 33]); crypto_modes.push(['psk+psk2', 'WPA-PSK/WPA2-PSK Mixed Mode', 22]); - crypto_modes.push(['psk', 'WPA-PSK', 21]); + crypto_modes.push(['psk', 'WPA-PSK', 12]); crypto_modes.push(['wep-open', _('WEP Open System'), 11]); crypto_modes.push(['wep-shared', _('WEP Shared Key'), 10]); } @@ -1392,51 +1401,89 @@ return view.extend({ } - o = ss.taboption('encryption', form.Value, 'auth_server', _('Radius-Authentication-Server')); + o = ss.taboption('encryption', form.Value, 'auth_server', _('RADIUS Authentication Server')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.datatype = 'host(0)'; - o = ss.taboption('encryption', form.Value, 'auth_port', _('Radius-Authentication-Port'), _('Default %d').format(1812)); + o = ss.taboption('encryption', form.Value, 'auth_port', _('RADIUS Authentication Port')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.datatype = 'port'; + o.placeholder = '1812'; - o = ss.taboption('encryption', form.Value, 'auth_secret', _('Radius-Authentication-Secret')); + o = ss.taboption('encryption', form.Value, 'auth_secret', _('RADIUS Authentication Secret')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.password = true; - o = ss.taboption('encryption', form.Value, 'acct_server', _('Radius-Accounting-Server')); + o = ss.taboption('encryption', form.Value, 'acct_server', _('RADIUS Accounting Server')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.datatype = 'host(0)'; - o = ss.taboption('encryption', form.Value, 'acct_port', _('Radius-Accounting-Port'), _('Default %d').format(1813)); + o = ss.taboption('encryption', form.Value, 'acct_port', _('RADIUS Accounting Port')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.datatype = 'port'; + o.placeholder = '1813'; - o = ss.taboption('encryption', form.Value, 'acct_secret', _('Radius-Accounting-Secret')); + o = ss.taboption('encryption', form.Value, 'acct_secret', _('RADIUS Accounting Secret')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.password = true; - o = ss.taboption('encryption', form.Value, 'dae_client', _('DAE-Client')); + /* extra RADIUS settings start */ + o = ss.taboption('encryption', form.ListValue, 'dynamic_vlan', _('RADIUS Dynamic VLAN Assignment'), _('Required: Rejects auth if RADIUS server does not provide appropriate VLAN attributes.')); + add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); + o.value('0', _('Disabled')); + o.value('1', _('Optional')); + o.value('2', _('Required')); + o.write = function (section_id, value) { + return this.super('write', [section_id, (value == 0) ? null: value]); + } + + o = ss.taboption('encryption', form.Flag, 'per_sta_vif', _('RADIUS Per STA VLAN'), _('Each STA is assigned its own AP_VLAN interface.')); + add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); + + //hostapd internally defaults to vlan_naming=1 even with dynamic VLAN off + o = ss.taboption('encryption', form.Flag, 'vlan_naming', _('RADIUS VLAN Naming'), _('Off: vlanXXX, e.g., vlan1. On: vlan_tagged_interface.XXX, e.g. eth0.1.')); + add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); + + o = ss.taboption('encryption', widgets.DeviceSelect, 'vlan_tagged_interface', _('RADIUS VLAN Tagged Interface'), _('E.g. eth0, eth1')); + add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); + o.size = 1; + o.rmempty = true; + o.multiple = false; + o.noaliases = true; + o.nocreate = true; + o.noinactive = true; + + o = ss.taboption('encryption', form.Value, 'vlan_bridge', _('RADIUS VLAN Bridge Naming Scheme'), _('E.g. br-vlan or brvlan.')); + add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); + o.rmempty = true; + /* extra RADIUS settings end */ + + o = ss.taboption('encryption', form.Value, 'dae_client', _('DAE-Client'), _('Dynamic Authorization Extension client.')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.datatype = 'host(0)'; - o = ss.taboption('encryption', form.Value, 'dae_port', _('DAE-Port'), _('Default %d').format(3799)); + o = ss.taboption('encryption', form.Value, 'dae_port', _('DAE-Port'), _('Dynamic Authorization Extension port.')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.datatype = 'port'; + o.placeholder = '3799'; - o = ss.taboption('encryption', form.Value, 'dae_secret', _('DAE-Secret')); + o = ss.taboption('encryption', form.Value, 'dae_secret', _('DAE-Secret'), _('Dynamic Authorization Extension secret.')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.rmempty = true; o.password = true; + //WPA(1) has only WPA IE. Only >= WPA2 has RSN IE Preauth frames. + o = ss.taboption('encryption', form.Flag, 'rsn_preauth', _('RSN Preauth'), _('Robust Security Network (RSN): Allow roaming preauth for WPA2-EAP networks (and advertise it in WLAN beacons). Only works if the specified network interface is a bridge. Shortens the time-critical reassociation process.')); + add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa2', 'wpa3', 'wpa3-mixed'] }); + o = ss.taboption('encryption', form.Value, '_wpa_key', _('Key')); o.depends('encryption', 'psk'); @@ -1500,66 +1547,117 @@ return view.extend({ // Probe 802.11r support (and EAP support as a proxy for Openwrt) var has_80211r = L.hasSystemFeature('hostapd', '11r') || L.hasSystemFeature('hostapd', 'eap'); - o = ss.taboption('encryption', form.Flag, 'ieee80211r', _('802.11r Fast Transition'), _('Enables fast roaming among access points that belong to the same Mobility Domain')); + o = ss.taboption('roaming', form.Flag, 'ieee80211r', _('802.11r Fast Transition'), _('Enables fast roaming among access points that belong to the same Mobility Domain')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); if (has_80211r) add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['psk', 'psk2', 'psk-mixed', 'sae', 'sae-mixed'] }); o.rmempty = true; - o = ss.taboption('encryption', form.Value, 'nasid', _('NAS ID'), _('Used for two different purposes: RADIUS NAS ID and 802.11r R0KH-ID. Not needed with normal WPA(2)-PSK.')); + o = ss.taboption('roaming', form.Value, 'nasid', _('NAS ID'), _('Used for two different purposes: RADIUS NAS ID and 802.11r R0KH-ID. Not needed with normal WPA(2)-PSK.')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa', 'wpa2', 'wpa3', 'wpa3-mixed'] }); o.depends({ ieee80211r: '1' }); o.rmempty = true; - o = ss.taboption('encryption', form.Value, 'mobility_domain', _('Mobility Domain'), _('4-character hexadecimal ID')); + o = ss.taboption('roaming', form.Value, 'mobility_domain', _('Mobility Domain'), _('4-character hexadecimal ID')); o.depends({ ieee80211r: '1' }); o.placeholder = '4f57'; o.datatype = 'and(hexstring,length(4))'; o.rmempty = true; - o = ss.taboption('encryption', form.Value, 'reassociation_deadline', _('Reassociation Deadline'), _('time units (TUs / 1.024 ms) [1000-65535]')); + o = ss.taboption('roaming', form.Value, 'reassociation_deadline', _('Reassociation Deadline'), _('time units (TUs / 1.024 ms) [1000-65535]')); o.depends({ ieee80211r: '1' }); o.placeholder = '1000'; o.datatype = 'range(1000,65535)'; o.rmempty = true; - o = ss.taboption('encryption', form.ListValue, 'ft_over_ds', _('FT protocol')); + o = ss.taboption('roaming', form.ListValue, 'ft_over_ds', _('FT protocol')); o.depends({ ieee80211r: '1' }); - o.value('1', _('FT over DS')); o.value('0', _('FT over the Air')); + o.value('1', _('FT over DS')); o.rmempty = true; - o = ss.taboption('encryption', form.Flag, 'ft_psk_generate_local', _('Generate PMK locally'), _('When using a PSK, the PMK can be automatically generated. When enabled, the R0/R1 key options below are not applied. Disable this to use the R0 and R1 key options.')); + o = ss.taboption('roaming', form.Flag, 'ft_psk_generate_local', _('Generate PMK locally'), _('When using a PSK, the PMK can be automatically generated. When enabled, the R0/R1 key options below are not applied. Disable this to use the R0 and R1 key options.')); o.depends({ ieee80211r: '1' }); o.default = o.enabled; o.rmempty = false; - o = ss.taboption('encryption', form.Value, 'r0_key_lifetime', _('R0 Key Lifetime'), _('minutes')); + o = ss.taboption('roaming', form.Value, 'r0_key_lifetime', _('R0 Key Lifetime'), _('minutes')); o.depends({ ieee80211r: '1' }); o.placeholder = '10000'; o.datatype = 'uinteger'; o.rmempty = true; - o = ss.taboption('encryption', form.Value, 'r1_key_holder', _('R1 Key Holder'), _('6-octet identifier as a hex string - no colons')); + o = ss.taboption('roaming', form.Value, 'r1_key_holder', _('R1 Key Holder'), _('6-octet identifier as a hex string - no colons')); o.depends({ ieee80211r: '1' }); o.placeholder = '00004f577274'; o.datatype = 'and(hexstring,length(12))'; o.rmempty = true; - o = ss.taboption('encryption', form.Flag, 'pmk_r1_push', _('PMK R1 Push')); + o = ss.taboption('roaming', form.Flag, 'pmk_r1_push', _('PMK R1 Push')); o.depends({ ieee80211r: '1' }); o.placeholder = '0'; o.rmempty = true; - o = ss.taboption('encryption', form.DynamicList, 'r0kh', _('External R0 Key Holder List'), _('List of R0KHs in the same Mobility Domain.
    Format: MAC-address,NAS-Identifier,128-bit key as hex string.
    This list is used to map R0KH-ID (NAS Identifier) to a destination MAC address when requesting PMK-R1 key from the R0KH that the STA used during the Initial Mobility Domain Association.')); + o = ss.taboption('roaming', form.DynamicList, 'r0kh', _('External R0 Key Holder List'), _('List of R0KHs in the same Mobility Domain.
    Format: MAC-address,NAS-Identifier,256-bit key as hex string.
    This list is used to map R0KH-ID (NAS Identifier) to a destination MAC address when requesting PMK-R1 key from the R0KH that the STA used during the Initial Mobility Domain Association.')); o.depends({ ieee80211r: '1' }); o.rmempty = true; - o = ss.taboption('encryption', form.DynamicList, 'r1kh', _('External R1 Key Holder List'), _ ('List of R1KHs in the same Mobility Domain.
    Format: MAC-address,R1KH-ID as 6 octets with colons,128-bit key as hex string.
    This list is used to map R1KH-ID to a destination MAC address when sending PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD that can request PMK-R1 keys.')); + o = ss.taboption('roaming', form.DynamicList, 'r1kh', _('External R1 Key Holder List'), _ ('List of R1KHs in the same Mobility Domain.
    Format: MAC-address,R1KH-ID as 6 octets with colons,256-bit key as hex string.
    This list is used to map R1KH-ID to a destination MAC address when sending PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD that can request PMK-R1 keys.')); o.depends({ ieee80211r: '1' }); o.rmempty = true; // End of 802.11r options + // Probe 802.11k and 802.11v support via EAP support (full hostapd has EAP) + if (L.hasSystemFeature('hostapd', 'eap')) { + /* 802.11k settings start */ o = + ss.taboption('roaming', form.Flag, 'ieee80211k', _('802.11k RRM'), _('Radio Resource Measurement - Sends beacons to assist roaming. Not all clients support this.')); + // add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['psk', 'psk2', 'psk-mixed', 'sae', 'sae-mixed'] }); + o.depends('mode', 'ap'); + o.depends('mode', 'ap-wds'); + + o = ss.taboption('roaming', form.Flag, 'rrm_neighbor_report', _('Neighbour Report'), _('802.11k: Enable neighbor report via radio measurements.')); + o.depends({ ieee80211k: '1' }); + o.default = o.enabled; + + o = ss.taboption('roaming', form.Flag, 'rrm_beacon_report', _('Beacon Report'), _('802.11k: Enable beacon report via radio measurements.')); + o.depends({ ieee80211k: '1' }); + o.default = o.enabled; + /* 802.11k settings end */ + + /* 802.11v settings start */ + o = ss.taboption('roaming', form.ListValue, 'time_advertisement', _('Time advertisement'), _('802.11v: Time Advertisement in management frames.')); + o.value('0', _('Disabled')); + o.value('2', _('Enabled')); + o.write = function (section_id, value) { + return this.super('write', [section_id, (value == 2) ? value: null]); + } + + //Pull current System TZ setting + var tz = uci.get('system', '@system[0]', 'timezone'); + o = ss.taboption('roaming', form.Value, 'time_zone', _('Time zone'), _('802.11v: Local Time Zone Advertisement in management frames.')); + o.value(tz); + o.rmempty = true; + + o = ss.taboption('roaming', form.Flag, 'wnm_sleep_mode', _('WNM Sleep Mode'), _('802.11v: Wireless Network Management (WNM) Sleep Mode (extended sleep mode for stations).')); + o.rmempty = true; + + /* wnm_sleep_mode_no_keys: https://git.openwrt.org/?p=openwrt/openwrt.git;a=commitdiff;h=bf98faaac8ed24cf7d3d93dd4fcd7304d109363b */ + o = ss.taboption('roaming', form.Flag, 'wnm_sleep_mode_no_keys', _('WNM Sleep Mode Fixes'), _('802.11v: Wireless Network Management (WNM) Sleep Mode Fixes: Prevents reinstallation attacks.')); + o.rmempty = true; + + o = ss.taboption('roaming', form.Flag, 'bss_transition', _('BSS Transition'), _('802.11v: Basic Service Set (BSS) transition management.')); + o.rmempty = true; + + /* in master, but not 21.02.1: proxy_arp */ + o = ss.taboption('roaming', form.Flag, 'proxy_arp', _('ProxyARP'), _('802.11v: Proxy ARP enables non-AP STA to remain in power-save for longer.')); + o.rmempty = true; + + /* TODO: na_mcast_to_ucast is missing: needs adding to hostapd.sh - nice to have */ + } + /* 802.11v settings end */ + } + + if (hwtype == 'mac80211') { o = ss.taboption('encryption', form.ListValue, 'eap_type', _('EAP-Method')); o.value('tls', 'TLS'); o.value('ttls', 'TTLS'); @@ -1676,7 +1774,7 @@ return view.extend({ if (hwtype == 'mac80211') { // ieee802.11w options o = ss.taboption('encryption', form.ListValue, 'ieee80211w', _('802.11w Management Frame Protection'), _("Note: Some wireless drivers do not fully support 802.11w. E.g. mwlwifi may have problems")); - o.value('', _('Disabled')); + o.value('0', _('Disabled')); o.value('1', _('Optional')); o.value('2', _('Required')); add_dependency_permutations(o, { mode: ['ap', 'ap-wds', 'sta', 'sta-wds'], encryption: ['owe', 'psk2', 'psk-mixed', 'sae', 'sae-mixed', 'wpa2', 'wpa3', 'wpa3-mixed'] }); @@ -1684,7 +1782,14 @@ return view.extend({ o.defaults = { '2': [{ encryption: 'sae' }, { encryption: 'owe' }, { encryption: 'wpa3' }, { encryption: 'wpa3-mixed' }], '1': [{ encryption: 'sae-mixed'}], - '': [] + '0': [] + }; + + o.write = function(section_id, value) { + if (value != this.default) + return form.ListValue.prototype.write.call(this, section_id, value); + else + return form.ListValue.prototype.remove.call(this, section_id); }; o = ss.taboption('encryption', form.Value, 'ieee80211w_max_timeout', _('802.11w maximum timeout'), _('802.11w Association SA Query maximum timeout')); @@ -1956,6 +2061,8 @@ return view.extend({ }); }); }).then(L.bind(function() { + ui.showModal(null, E('p', { 'class': 'spinning' }, [ _('Loading data…') ])); + return this.renderMoreOptionsModal(section_id); }, this)); }; @@ -2157,5 +2264,7 @@ return view.extend({ return E([ nodes, E('h3', _('Associated Stations')), table ]); }, this, m)); - } + }, + + handleReset: null }); diff --git a/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json b/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json index 188c695f3..2fa3cf6ab 100644 --- a/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json +++ b/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json @@ -46,35 +46,9 @@ } }, - "admin/network/dhcp": { - "title": "DHCP and DNS", - "order": 30, - "action": { - "type": "view", - "path": "network/dhcp" - }, - "depends": { - "acl": [ "luci-mod-network-dhcp" ], - "uci": { "dhcp": true } - } - }, - - "admin/network/hosts": { - "title": "Hostnames", - "order": 40, - "action": { - "type": "view", - "path": "network/hosts" - }, - "depends": { - "acl": [ "luci-mod-network-dhcp" ], - "uci": { "dhcp": true } - } - }, - "admin/network/routes": { - "title": "Static Routes", - "order": 50, + "title": "Routing", + "order": 30, "action": { "type": "view", "path": "network/routes" @@ -84,9 +58,23 @@ } }, + "admin/network/dhcp": { + "title": "DHCP and DNS", + "order": 40, + "action": { + "type": "view", + "path": "network/dhcp" + }, + "depends": { + "acl": [ "luci-mod-network-dhcp" ], + "fs": { "/usr/sbin/dnsmasq": "executable" }, + "uci": { "dhcp": true } + } + }, + "admin/network/diagnostics": { "title": "Diagnostics", - "order": 60, + "order": 50, "action": { "type": "view", "path": "network/diagnostics" diff --git a/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json b/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json index 6943d9563..b377f395f 100644 --- a/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json +++ b/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json @@ -8,7 +8,9 @@ "/proc/sys/net/ipv6/conf/*/mtu": [ "read" ], "/proc/sys/net/ipv6/conf/*/hop_limit": [ "read" ], "/usr/libexec/luci-peeraddr": [ "exec" ], - "/usr/lib/opkg/info/netifd.control": [ "read" ] + "/usr/lib/opkg/info/netifd.control": [ "read" ], + "/proc/sys/net/ipv[46]/conf/*": [ "read" ], + "/sys/class/net/*/brport/*": [ "read" ] }, "ubus": { "file": [ "exec" ], @@ -58,7 +60,8 @@ "/usr/bin/ping": [ "exec" ], "/usr/bin/ping6": [ "exec", "list" ], "/usr/bin/traceroute": [ "exec" ], - "/usr/bin/traceroute6": [ "exec", "list" ] + "/usr/bin/traceroute6": [ "exec", "list" ], + "/usr/bin/arp-scan": [ "exec", "list" ] }, "ubus": { "file": [ "exec", "stat" ] From 480b6575ee3139c7984acfcc24d65349659f0403 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 27 Nov 2023 17:57:30 +0100 Subject: [PATCH 1198/2059] Remove no more needed patch for r8152 --- r8152/patches/020-6.1-support.patch | 38 ----------------------------- 1 file changed, 38 deletions(-) delete mode 100644 r8152/patches/020-6.1-support.patch diff --git a/r8152/patches/020-6.1-support.patch b/r8152/patches/020-6.1-support.patch deleted file mode 100644 index 756aba51f..000000000 --- a/r8152/patches/020-6.1-support.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/compatibility.h -+++ b/compatibility.h -@@ -237,9 +237,15 @@ - #define napi_disable(napi_ptr) netif_poll_disable(container_of(napi_ptr, struct r8152, napi)->netdev) - #define napi_schedule(napi_ptr) netif_rx_schedule(container_of(napi_ptr, struct r8152, napi)->netdev) - #define napi_complete(napi_ptr) netif_rx_complete(container_of(napi_ptr, struct r8152, napi)->netdev) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -+ #define netif_napi_add_weight(ndev, napi_ptr, function, weight_t) \ -+ ndev->poll = function; \ -+ ndev->weight = weight_t; -+#else - #define netif_napi_add(ndev, napi_ptr, function, weight_t) \ - ndev->poll = function; \ - ndev->weight = weight_t; -+#endif - typedef unsigned long uintptr_t; - #define DMA_BIT_MASK(value) \ - (value < 64 ? ((1ULL << value) - 1) : 0xFFFFFFFFFFFFFFFFULL) ---- a/r8152.c -+++ b/r8152.c -@@ -20718,10 +20718,17 @@ - - usb_set_intfdata(intf, tp); - -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -+ if (tp->support_2500full) -+ netif_napi_add_weight(netdev, &tp->napi, r8152_poll, 256); -+ else -+ netif_napi_add_weight(netdev, &tp->napi, r8152_poll, 64); -+#else - if (tp->support_2500full) - netif_napi_add(netdev, &tp->napi, r8152_poll, 256); - else - netif_napi_add(netdev, &tp->napi, r8152_poll, 64); -+#endif - - ret = register_netdev(netdev); - if (ret != 0) { From d40c0c29ad171762d0f1489d2bf5f7bef5e8a6fe Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 1 Dec 2023 09:46:00 +0100 Subject: [PATCH 1199/2059] Fix on multi servers for Shadowsocks-Rust and XRay --- omr-tracker/files/bin/omr-tracker-server | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index d7124a555..ef80e9086 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -81,6 +81,7 @@ _check_master() { #logger -t "OMR-Tracker-Server" "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n') - $ip" uci -q batch <<-EOF >/dev/null set shadowsocks-libev.sss${count}.server=$ip + set shadowsocks-rust.sss${count}.server=$ip EOF if [ "$count" -eq "0" ]; then uci -q batch <<-EOF >/dev/null @@ -123,6 +124,8 @@ _check_master() { fi config_load shadowsocks-libev config_foreach _enable_redir ss_redir + config_load shadowsocks-rust + config_foreach _enable_redir ss_redir OMR_TRACKER_STATUS_MSG="Answer to ping and to API check" mail_alert="$(uci -q get omr-tracker.server.mail_alert)" #[ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" @@ -150,6 +153,8 @@ _check_master() { EOF config_load shadowsocks-libev config_foreach _disable_redir ss_redir + config_load shadowsocks-rust + config_foreach _disable_redir ss_redir mail_alert="$(uci -q get omr-tracker.server.mail_alert)" #[ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" [ "$mail_alert" = "1" ] && [ -n "$(uci -q get mail.default.to)" ] && { @@ -178,7 +183,11 @@ _check_master() { # config_foreach _enable_redir ss_redir #fi uci -q commit shadowsocks-libev - [ "$changes" = "1" ] && /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null + uci -q commit shadowsocks-rust + [ "$changes" = "1" ] && { + /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null + /etc/init.d/shadowsocks-rust restart >/dev/null 2>/dev/null + } break } } @@ -211,6 +220,7 @@ _check_backup() { changes="1" uci -q batch <<-EOF >/dev/null set shadowsocks-libev.sss${count}.server=$ip + set shadowsocks-rust.sss${count}.server=$ip EOF if [ "$count" -eq "0" ]; then uci -q batch <<-EOF >/dev/null @@ -242,6 +252,7 @@ _check_backup() { EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null + /etc/init.d/xray restart >/dev/null 2>/dev/null /etc/init.d/glorytun restart >/dev/null 2>/dev/null /etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null /etc/init.d/mlvpn restart >/dev/null 2>/dev/null @@ -253,6 +264,8 @@ _check_backup() { fi config_load shadowsocks-libev config_foreach _enable_redir ss_redir + config_load shadowsocks-rust + config_foreach _enable_redir ss_redir OMR_TRACKER_STATUS_MSG="Answer to ping and to API check" mail_alert="$(uci -q get omr-tracker.server.mail_alert)" #[ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" @@ -278,6 +291,8 @@ _check_backup() { EOF config_load shadowsocks-libev config_foreach _disable_redir ss_redir + config_load shadowsocks-rust + config_foreach _disable_redir ss_redir OMR_TRACKER_STATUS_MSG="No answer to ping and to API check" mail_alert="$(uci -q get omr-tracker.server.mail_alert)" #[ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" @@ -307,7 +322,11 @@ _check_backup() { # config_foreach _enable_redir ss_redir #fi uci -q commit shadowsocks-libev - [ "$changes" = "1" ] && /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null + uci -q commit shadowsocks-rust + [ "$changes" = "1" ] && { + /etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null + /etc/init.d/shadowsocks-rust restart >/dev/null 2>/dev/null + } [ "$server_ping" = true ] && break } } From b129ad30ae7c15f4b8bccbc85b731f27bb82b6fd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 1 Dec 2023 22:55:26 +0100 Subject: [PATCH 1200/2059] Make shadowsocks-libev not remove rust rules --- shadowsocks-libev/files/shadowsocks-libev.init | 4 ++++ shadowsocks-rust/files/shadowsocks-rust.init | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 34cc62000..59d2fe856 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -369,6 +369,10 @@ rules_up() { rules_down() { rules_exist || return 0 + enabled="0" + config_load shadowsocks-rust + config_foreach server_state server + [ "$enabled" = "1" ] && return logger -t "Shadowsocks" "Rules DOWN" local bin="$ss_bindir/ss-rules" [ -x "$bin" ] && { diff --git a/shadowsocks-rust/files/shadowsocks-rust.init b/shadowsocks-rust/files/shadowsocks-rust.init index 7af70018d..a1689bba2 100644 --- a/shadowsocks-rust/files/shadowsocks-rust.init +++ b/shadowsocks-rust/files/shadowsocks-rust.init @@ -364,6 +364,10 @@ rules_up() { rules_down() { rules_exist || return 0 + enabled="0" + config_load shadowsocks-libev + config_foreach server_state server + [ "$enabled" = "1" ] && return logger -t "Shadowsocks-rust" "Rules DOWN" local bin="$ss_bindir/ssr-rules" [ -x "$bin" ] && { From 8ec0bdff9b04d6231b64458120c56de17132f895 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Dec 2023 16:35:47 +0100 Subject: [PATCH 1201/2059] Add debug mode to modemamanger to be able to run AT commands --- modemmanager/files/modemmanager.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init index c19022031..16610bcd8 100644 --- a/modemmanager/files/modemmanager.init +++ b/modemmanager/files/modemmanager.init @@ -20,7 +20,7 @@ start_service() { # . /usr/share/ModemManager/modemmanager.common procd_open_instance - procd_set_param command /usr/sbin/ModemManager-wrapper + procd_set_param command /usr/sbin/ModemManager-wrapper --debug procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" procd_close_instance From 6dbc29ae7baa74cabc925f0bff6d5c73a9915dbb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Dec 2023 16:36:14 +0100 Subject: [PATCH 1202/2059] Restart OpenVPN only if not started and with a CA --- mptcp/files/usr/share/omr/post-tracking.d/010-services | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index eab51b480..4268caa61 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -42,7 +42,7 @@ fi if [ "$(pgrep openvpn)" = "" ] && [ -f /etc/init.d/openvpn ]; then openvpn_enable=0 openvpn_enabled() { - [ "$(uci -q get openvpn.$1.enabled)" = "1" ] && openvpn_enable=1 + [ "$(uci -q get openvpn.$1.enabled)" = "1" ] && [ -n "$(uci -q get openvpn.$1.ca)" ] && openvpn_enable=1 } config_load openvpn config_foreach openvpn_enabled openvpn From 8c8ae48f707280513cd7911dd443b7fe54def42a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Dec 2023 17:49:43 +0100 Subject: [PATCH 1203/2059] Add netxen-nix fix https://github.com/Ysurac/openmptcprouter/issues/3065 --- netxen-nic/Makefile | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 netxen-nic/Makefile diff --git a/netxen-nic/Makefile b/netxen-nic/Makefile new file mode 100644 index 000000000..399970c87 --- /dev/null +++ b/netxen-nic/Makefile @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME := netxen-nic +PKG_RELEASE := 1 + +PKG_SOURCE := $(LINUX_SOURCE) +PKG_SOURCE_URL := $(LINUX_SITE) +PKG_HASH := $(LINUX_KERNEL_HASH) + +PKG_LICENSE := GPL-2.0 + +PKG_FLAGS := nonshared +PKG_BUILD_PARALLEL := 1 + +include $(INCLUDE_DIR)/package.mk + +TAR_CMD=$(HOST_TAR) -C $(1) --strip-components=1 $(TAR_OPTIONS) + +define Build/Compile + $(KERNEL_MAKE) \ + $(PKG_JOBS) \ + CONFIG_NETXEN_NIC=m \ + M=$(PKG_BUILD_DIR)/drivers/net/ethernet/qlogic/netxen \ + modules +endef + +KernelPackage/hooks := : + +define KernelPackage/netxen-nic + TITLE := NetXen Multi port (1/10) Gigabit Ethernet NIC + KCONFIG := CONFIG_NETXEN_NIC=m + FILES := $(PKG_BUILD_DIR)/drivers/net/ethernet/qlogic/netxen/netxen_nic.ko + AUTOLOAD := $(call AutoProbe,netxen_nic) + DEPENDS := @PCI_SUPPORT +endef +$(eval $(call KernelPackage,netxen-nic)) From a277c1c7b2a320687130675d219bb87ccfd93731 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Dec 2023 14:25:39 +0100 Subject: [PATCH 1204/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3050 --- .../omr/post-tracking.d/001-post-tracking | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 86490fa01..737415ae9 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -722,6 +722,7 @@ default_gw=$(ip route get 1.1.1.1 | grep via | awk '{print $3}') default_gw6=$(ip -6 route get 2606:4700:4700::1111 | grep via | awk '{print $3}') #current_interface_gw=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway") +interface_autostart=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["autostart"]') interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') interface_available=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["available"]') interface_pending=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["pending"]') @@ -739,7 +740,20 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then _log "Set $OMR_TRACKER_INTERFACE up" ifup $OMR_TRACKER_INTERFACE sleep 30 - #elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ]; then + elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] && [ "$interface_up" = "false" ] && [ "$interface_available" = "false" ] && [ "$interface_pending" = "false" ] && [ "$interface_autostart" = "true" ]; then + modemfind="0" + for modem in $(timeout 3 mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do + if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then + modemfind="1" + fi + done + if [ "$modemfind" = "0" ]; then + _log "Can't find $OMR_TRACKER_INTERFACE in ModemManager, restart modemmanager..." + /etc/init.d/modemmanager restart + sleep 30 + fi + fi + #elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] && [ "$interface_available" = "false" ]; then # for modem in $(timeout 3 mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do # if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then # modem_device=$(timeout 2 mmcli -m $modem -K | grep 'modem.generic.device ' | awk '{print $3}') @@ -753,7 +767,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then # } # fi # done - fi + #fi # This part must be done after modems restart because we have no idea when modems will be ready again... (another solution would be to check ModemManager status) if [ "$OMR_TRACKER_PREV_STATUS" = "$OMR_TRACKER_STATUS" ]; then From 9eca2b3ed78897df0b981ed086757a80b0a9d23a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Dec 2023 14:26:26 +0100 Subject: [PATCH 1205/2059] Less logs by default --- openmptcprouter/files/etc/uci-defaults/2060-omr-system | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 3e30f8d5b..01d8b66b2 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -7,6 +7,7 @@ uci -q batch <<-EOF >/dev/null set system.ntp.enabled='1' del system.ntp.server set system.@system[-1].cronloglevel=9 + set system.@system[-1].conloglevel=7 add_list system.ntp.server='0.pool.ntp.org' add_list system.ntp.server='1.pool.ntp.org' add_list system.ntp.server='2.pool.ntp.org' From 4a660fdd729dbb4fde923e921126eea3348249de Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Dec 2023 18:04:53 +0100 Subject: [PATCH 1206/2059] Only display VPS available proxy --- .../luasrc/view/openmptcprouter/wizard.htm | 39 +++++++++++++++++++ .../files/etc/init.d/openmptcprouter-vps | 15 +++++++ 2 files changed, 54 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 1d8eba66a..128199904 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -232,6 +232,42 @@

    diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 0b3512f6e..0176273ea 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1936,8 +1936,10 @@ _set_config_from_vps() { # Get available server available_vpn="$(echo "$vps_config" | jsonfilter -q -e '@.vpn.available' | sed -e 's/\[ //' -e 's/ \]//' -e 's/,//g')" + available_proxy="$(echo "$vps_config" | jsonfilter -q -e '@.proxy.available' | sed -e 's/\[ //' -e 's/ \]//' -e 's/,//g')" uci -q batch <<-EOF >/dev/null del openmptcprouter.${servername}.available_vpn + del openmptcprouter.${servername}.available_proxy EOF if [ "$user_permission" = "ro" ]; then @@ -1947,6 +1949,12 @@ _set_config_from_vps() { set openmptcprouter.${servername}.available_vpn=${current_vpn} EOF fi + current_proxy="$(echo "$vps_config" | jsonfilter -q -e '@.proxy.current')" + if [ -n "$current_proxy" ]; then + uci -q batch <<-EOF >/dev/null + set openmptcprouter.${servername}.available_proxy=${current_proxy} + EOF + fi else if [ -n "$available_vpn" ]; then @@ -1956,6 +1964,13 @@ _set_config_from_vps() { EOF done fi + if [ -n "$available_proxy" ]; then + for proxy in $available_proxy; do + uci -q batch <<-EOF >/dev/null + add_list openmptcprouter.${servername}.available_proxy=$proxy + EOF + done + fi fi if [ "$noerror" = "1" ]; then uci -q batch <<-EOF >/dev/null From a57a418be60a59232f730bddfbd6ab1ed04c3a55 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 7 Dec 2023 14:58:48 +0100 Subject: [PATCH 1207/2059] Remove r8168 not needed patch --- r8168/patches/030-6.1-support.patch | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 r8168/patches/030-6.1-support.patch diff --git a/r8168/patches/030-6.1-support.patch b/r8168/patches/030-6.1-support.patch deleted file mode 100644 index 44ab2be19..000000000 --- a/r8168/patches/030-6.1-support.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/src/r8168.h ---- b/src/r8168.h -@@ -566,7 +566,11 @@ - typedef struct napi_struct *napi_ptr; - typedef int napi_budget; - -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -+#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add_weight(ndev, &priv->napi, function, weight) -+#else - #define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -+#endif - #define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) - #define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) - #define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; From 007374410e4950b05fc2cf4f89ba66d8a4f8b8e8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 8 Dec 2023 11:01:25 +0100 Subject: [PATCH 1208/2059] Add back Shadowsocks-Rust in wizard --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 128199904..24ead847c 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -261,7 +261,7 @@ <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> <% elseif proxy == "xray-shadowsocks" then %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> - <% elseif proxy == "shadowsocks-rust" then %> + <% elseif proxy == "shadowsocks-rust" or proxy == "shadowsocks-go" then %> <% if nixio.fs.access("/etc/init.d/shadowsocks-rust") then %><% end %> <% end end %> From f1ea9f3db163a929a1e34f8a067ca090d5fb029f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 8 Dec 2023 11:02:12 +0100 Subject: [PATCH 1209/2059] Fix partially issue when LAN interfance doesn't exist --- openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index a73a9c33d..340fbf77c 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -767,7 +767,10 @@ function interfaces_status() end) end local net = ntm:get_network("lan") - local ipaddr = net:ipaddr() or "" + local ipaddr = "" + if net then + ipaddr = net:ipaddr() + end mArray.openmptcprouter["local_addr"] = ipaddr --mArray.openmptcprouter["local_addr"] = uci:get("network", "lan", "ipaddr") mArray.openmptcprouter["hostname"] = "OpenMPTCProuter" From 7d567cd23d8944f8a52942ceae52efa0684357f7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 10 Dec 2023 18:47:17 +0100 Subject: [PATCH 1210/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/3069 --- omr-tracker/files/bin/omr-tracker-server | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index ef80e9086..fcab8b2d4 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -64,14 +64,16 @@ _check_master() { config_get disabled $1 disabled [ "$master" = "1" ] && [ -n "$ip" ] && [ "$disabled" != "1" ] && { set_ip() { - local ip=$1 - ipresolve="$(resolveip -4 $ip | head -n 1)" + local ipd=$1 + local ip="" + ipresolve="$(resolveip -4 $ipd | head -n 1)" if [ -n "$ipresolve" ]; then ip="$ipresolve" else - ip6resolve="$(resolveip -6 $ip | head -n 1)" + ip6resolve="$(resolveip -6 $ipd | head -n 1)" [ -n "$ip6resolve" ] && ip="$ip6resolve" fi + [ -z "$ip" ] && return #_ping_server $ip _check_server $ip $port if [ "$server_ping" = true ]; then From ba464a917abe1a2c15face0fa4857ef9e4672c6c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 10 Dec 2023 18:48:06 +0100 Subject: [PATCH 1211/2059] Remove MPTCP test for > 5.4 --- luci-app-mptcp/luasrc/controller/mptcp.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index 842adc6ef..98e07b492 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -5,13 +5,17 @@ module("luci.controller.mptcp", package.seeall) +local uname = nixio.uname() + function index() entry({"admin", "network", "mptcp"}, alias("admin", "network", "mptcp", "settings"), _("MPTCP")) entry({"admin", "network", "mptcp", "settings"}, cbi("mptcp"), _("Settings"),2).leaf = true entry({"admin", "network", "mptcp", "bandwidth"}, template("mptcp/multipath"), _("Bandwidth"), 3).leaf = true entry({"admin", "network", "mptcp", "multipath_bandwidth"}, call("multipath_bandwidth")).leaf = true entry({"admin", "network", "mptcp", "interface_bandwidth"}, call("interface_bandwidth")).leaf = true - entry({"admin", "network", "mptcp", "mptcp_check"}, template("mptcp/mptcp_check"), _("MPTCP Support Check"), 4).leaf = true + if uname.release:sub(1,1) == "5" then + entry({"admin", "network", "mptcp", "mptcp_check"}, template("mptcp/mptcp_check"), _("MPTCP Support Check"), 4).leaf = true + end entry({"admin", "network", "mptcp", "mptcp_check_trace"}, post("mptcp_check_trace")).leaf = true entry({"admin", "network", "mptcp", "mptcp_fullmesh"}, template("mptcp/mptcp_fullmesh"), _("MPTCP Fullmesh"), 5).leaf = true entry({"admin", "network", "mptcp", "mptcp_fullmesh_data"}, post("mptcp_fullmesh_data")).leaf = true From 0e383c542c28b627ac3c604dba02d0ccbc973670 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 10 Dec 2023 18:48:28 +0100 Subject: [PATCH 1212/2059] Force reload mptcp --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index c4756ad65..ef54c1499 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -183,5 +183,8 @@ o:value("backup", translate("backup")) --o:value("handover", translate("handover")) o.default = "off" +function m.on_after_apply(self,map) + sys.call('/etc/init.d/mptcp reload') +end return m From 6c2ffa6cf05ef0209e029c8c938a01633879907a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 10 Dec 2023 18:49:51 +0100 Subject: [PATCH 1213/2059] Display core temp when available in all cases --- .../files/usr/libexec/rpcd/openmptcprouter | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index 340fbf77c..f28df60c1 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -8,6 +8,11 @@ local net = require "luci.model.network".init() local ucic = require "luci.model.uci".cursor() local jsonc = require "luci.jsonc" +function file_exists(name) + local f = io.open(name, "r") + return f ~= nil and io.close(f) +end + function interface_from_device(dev) for _, iface in ipairs(net:get_networks()) do local ifacen = iface:name() @@ -1183,7 +1188,8 @@ function interfaces_status() mArray.openmptcprouter['model'] = sys.exec("ubus call system board | jsonfilter -q -e '@.model' 2>/dev/null | tr -d '\n'") local board_name = sys.exec("ubus call system board | jsonfilter -q -e '@.board_name' 2>/dev/null | tr -d '\n'") -- retrieve core temperature - if board_name:match("^raspberrypi.*") then + --if board_name:match("^raspberrypi.*") then + if file_exists("/sys/class/thermal/thermal_zone0/temp") then mArray.openmptcprouter["core_temp"] = sys.exec("cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null"):match("%d+") end mArray.openmptcprouter["loadavg"] = sys.exec("cat /proc/loadavg 2>/dev/null"):match("[%d%.]+ [%d%.]+ [%d%.]+") From e9fda36208dc0d9dfe473a56a1209ca9da48c73c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 10 Dec 2023 18:50:14 +0100 Subject: [PATCH 1214/2059] Force disable MPTCP when needed --- mptcp/files/usr/share/omr/post-tracking.d/010-services | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index 4268caa61..4cc11015b 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -134,6 +134,16 @@ restart_omrtracker() { config_load network config_foreach restart_omrtracker interface +mutlipath_fix() { + config_get multipath "$1" multipath + [ "$multipath" != "off" ] && return + interface="$(ifstatus $1 | jsonfilter -q -e '@.l3_device' | tr -d '\n')" + [ -n "$interface"] && [ -z "$(multipath $interface | grep deactivated)" ] && /etc/init.d/mptcp reload $interface 2>&1 >/dev/null +} + +config_load network +config_foreach multipath_fix interface + if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-ss for Shadowsocks libev, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null From 231597a7a27568bf789944daa8816b82f9102551 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 11 Dec 2023 09:18:58 +0100 Subject: [PATCH 1215/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3070 --- luci-app-mptcp/luasrc/controller/mptcp.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua index 98e07b492..227d26602 100644 --- a/luci-app-mptcp/luasrc/controller/mptcp.lua +++ b/luci-app-mptcp/luasrc/controller/mptcp.lua @@ -1,19 +1,19 @@ -- Copyright 2008 Steven Barth -- Copyright 2011 Jo-Philipp Wich --- Copyright 2018 Ycarus (Yannick Chabanois) +-- Copyright 2018-2023 Ycarus (Yannick Chabanois) -- Licensed to the public under the Apache License 2.0. module("luci.controller.mptcp", package.seeall) -local uname = nixio.uname() function index() + local uname = nixio.uname() entry({"admin", "network", "mptcp"}, alias("admin", "network", "mptcp", "settings"), _("MPTCP")) entry({"admin", "network", "mptcp", "settings"}, cbi("mptcp"), _("Settings"),2).leaf = true entry({"admin", "network", "mptcp", "bandwidth"}, template("mptcp/multipath"), _("Bandwidth"), 3).leaf = true entry({"admin", "network", "mptcp", "multipath_bandwidth"}, call("multipath_bandwidth")).leaf = true entry({"admin", "network", "mptcp", "interface_bandwidth"}, call("interface_bandwidth")).leaf = true - if uname.release:sub(1,1) == "5" then + if uname ~= nil and uname.release:sub(1,1) == "5" then entry({"admin", "network", "mptcp", "mptcp_check"}, template("mptcp/mptcp_check"), _("MPTCP Support Check"), 4).leaf = true end entry({"admin", "network", "mptcp", "mptcp_check_trace"}, post("mptcp_check_trace")).leaf = true From e1b86c3118b9466f63fccc0245d7075181a3fafd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 10:55:30 +0100 Subject: [PATCH 1216/2059] Check if unbound is working, else restart it --- .../usr/share/omr/post-tracking.d/010-services | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index 4cc11015b..7f2368b74 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -33,10 +33,16 @@ if [ "$(pgrep -f dnsmasq)" = "" ] && [ -f /etc/init.d/dnsmasq ]; then /etc/init.d/dnsmasq restart 2>&1 >/dev/null sleep 5 fi -if [ "$(pgrep -f unbound)" = "" ] && [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then - _log "Can't find unbound, restart it..." - /etc/init.d/unbound restart 2>&1 >/dev/null - sleep 5 +if [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then + if [ "$(pgrep -f unbound)" = "" ]; then + _log "Can't find unbound, restart it..." + /etc/init.d/unbound restart 2>&1 >/dev/null + sleep 5 + elif [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ] && [ "$(uci -q get unbound.ub_main.listen_port)" = "5353" ] && [ -n "$(dig +timeout=4 +tries=1 openmptcprouter.com -p 5353 | grep 'ANSWER: 0')" ]; then + _log "Can't resolve via unbound, restart it..." + /etc/init.d/unbound restart 2>&1 >/dev/null + sleep 5 + fi fi if [ "$(pgrep openvpn)" = "" ] && [ -f /etc/init.d/openvpn ]; then From 63d19c4861941414320b4baa7acf9e688bd3201c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 10:56:25 +0100 Subject: [PATCH 1217/2059] Add OpenVPN DCO --- openmptcprouter-full/Makefile | 2 +- .../files/etc/uci-defaults/2020-omr-vpn | 9 +++ openvpn/files/openvpn.options | 1 + ovpn-dco/Makefile | 63 +++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 ovpn-dco/Makefile diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index ccdf4110c..898ecef82 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -85,7 +85,7 @@ MY_DEPENDS := \ (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ - xray-core shadowsocks-rust-sslocal shadowsocks-rust-ssservice shadowsocks-rust-config luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 + xray-core shadowsocks-rust-sslocal shadowsocks-rust-ssservice shadowsocks-rust-config luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index 962c03d39..334cf75d8 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -45,9 +45,18 @@ if [ "$(uci -q get openvpn.omr.proto)" != "tcp-client" ]; then set openvpn.omr.sndbuf=0 set openvpn.omr.rcvbuf=0 set openvpn.omr.route_delay=5 + set openvpn.omr.disable_dco=1 commit openvpn EOF fi +if [ -z "$(uci -q get openvpn.omr.disable_dco)" ]; then + uci -q batch <<-EOF >/dev/null + set openvpn.omr.disable_dco=1 + commit openvpn + EOF + +fi + uci -q delete openvpn.omr.secret uci -q delete openvpn.omr.ncp_disable=0 diff --git a/openvpn/files/openvpn.options b/openvpn/files/openvpn.options index 5b8d55a07..1dbc4b8fd 100644 --- a/openvpn/files/openvpn.options +++ b/openvpn/files/openvpn.options @@ -149,6 +149,7 @@ client client_to_client comp_noadapt disable +disable_dco disable_occ down_pre duplicate_cn diff --git a/ovpn-dco/Makefile b/ovpn-dco/Makefile new file mode 100644 index 000000000..1f0181825 --- /dev/null +++ b/ovpn-dco/Makefile @@ -0,0 +1,63 @@ +# +# Copyright (C) 2021 Jianhui Zhao +# Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter +# +# 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:=ovpn-dco +PKG_VERSION:=0.2.20231127 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/OpenVPN/ovpn-dco.git +PKG_SOURCE_VERSION:=c24380cdb8f5eef5a04059bbe82ad4ba4d3616c3 + +PKG_MAINTAINER:=Yannick Chabanois +PKG_LICENSE:=GPL-2.0-only + + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ovpn-dco-v2 + SUBMENU:=Network Support + TITLE:=OpenVPN data channel offload + DEPENDS:=+kmod-crypto-aead +kmod-udptunnel4 +IPV6:kmod-udptunnel6 + FILES:=$(PKG_BUILD_DIR)/drivers/net/ovpn-dco/ovpn-dco-v2.ko + AUTOLOAD:=$(call AutoLoad,30,ovpn-dco-v2) +endef + +define KernelPackage/ovpn-dco-v2/description + This module enhances the performance of the OpenVPN userspace software + by offloading the data channel processing to kernelspace. +endef + +NOSTDINC_FLAGS += \ + $(KERNEL_NOSTDINC_FLAGS) \ + -I$(PKG_BUILD_DIR)/include \ + -include $(PKG_BUILD_DIR)/linux-compat.h \ + -I$(PKG_BUILD_DIR)/compat-include/ + +EXTRA_KCONFIG:= \ + CONFIG_OVPN_DCO_V2=m + +PKG_EXTMOD_SUBDIRS = drivers/net/ovpn-dco + +MAKE_OPTS:= \ + $(KERNEL_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)/drivers/net/ovpn-dco" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + $(EXTRA_KCONFIG) + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,ovpn-dco-v2)) From 7139a5db51ba29c4cb5ffb720c5ed0d3d7c5d2d7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 10:57:05 +0100 Subject: [PATCH 1218/2059] Fix on omr-test-speed for fasttest --- openmptcprouter/files/bin/omr-test-speed | 10 ++++++++-- openmptcprouter/files/bin/omr-test-speedv6 | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index 36480fcb6..a1de53264 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -13,9 +13,10 @@ if [ "$1" = "fasttest" ]; then fi for i in $@; do :; done INTERFACE="$i" +[ "$INTERFACE" = "forcevps" ] || [ "$INTERFACE" = "fasttest" ] && INTERFACE="" [ -n "$INTERFACE" ] && [ ! -d "/sys/class/net/$INTERFACE" ] && { - echo "You must use a real interface. You wan find them using 'ip a' for example" + echo "You must use a real interface. You wan find them using 'ip a' for example (not $INTERFACE)" exit 0 } @@ -41,7 +42,12 @@ done [ "$FASTTEST" = true ] || echo "Best server is $HOST, running test:" trap : HUP INT TERM if [ -z "$INTERFACE" ]; then - curl -4 -o /dev/null $HOST || echo + if [ "$FASTTEST" = true ]; then + avg_speed=$(curl -4 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' $HOST 2>/dev/null) + echo "$avg_speed" + else + curl -4 -o /dev/null $HOST || echo + fi else [ -n "$(tc qdisc show dev $INTERFACE | grep ingress)" ] && /etc/init.d/sqm stop $INTERFACE domain=$(echo $HOST | awk -F/ '{print $3}') diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index 62653aea7..07fa36c54 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -1,5 +1,4 @@ #!/bin/sh -#!/bin/sh # (c) Yannick Chabanois (ycarus@zugaina.org) for OpenMPTCProuter # # @@ -14,6 +13,7 @@ if [ "$1" = "fasttest" ]; then fi for i in $@; do :; done INTERFACE="$i" +[ "$INTERFACE" = "forcevps" ] || [ "$INTERFACE" = "fasttest" ] && INTERFACE="" [ -n "$INTERFACE" ] && [ ! -d "/sys/class/net/$INTERFACE" ] && { echo "You must use a real interface. You wan find them using 'ip a' for example" From e41723e2959bd09e81b3b854fd4d29050ab150b3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 10:57:47 +0100 Subject: [PATCH 1219/2059] Check DNS only if external tests are not disabled --- openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index f28df60c1..3dfda3661 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -789,7 +789,10 @@ function interfaces_status() -- dns mArray.openmptcprouter["dns"] = false local timeout = uci:get("openmptcprouter","settings","status_getip_timeout") or "1" - local dns_test = sys.exec("dig +timeout=" .. timeout .. " +tries=1 openmptcprouter.com | grep 'ANSWER: 0'") + local dns_test = "" + if uci:get("openmptcprouter","settings","external_check") ~= "0" then + dns_test = sys.exec("dig +timeout=" .. timeout .. " +tries=1 openmptcprouter.com | grep 'ANSWER: 0'") + end if dns_test == "" then mArray.openmptcprouter["dns"] = true end From b8d2414f51f0672c42cae39af75a326c2fdd3ba6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 10:58:47 +0100 Subject: [PATCH 1220/2059] Allow to change encryption on XRay Shadowsocks --- .../luasrc/controller/openmptcprouter.lua | 4 +++- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index ec876228c..5f7b1487a 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -915,7 +915,8 @@ function wizard_add() ucic:set("xray","omrout","s_vless_reality_user_security","none") ucic:set("xray","omrout","s_trojan_user_security","none") ucic:set("xray","omrout","s_socks_user_security","none") - ucic:set("xray","omrout","s_shadowsocks_method","none") + --ucic:set("xray","omrout","s_shadowsocks_method","none") + ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-aes-256-gcm") elseif encryption == "aes-256-gcm" then ucic:set("openmptcprouter","settings","encryption","aes-256-gcm") ucic:set("shadowsocks-libev","sss0","method","aes-256-gcm") @@ -974,6 +975,7 @@ function wizard_add() ucic:set("xray","omrout","s_trojan_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_socks_user_security","chacha20-poly1305") ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-chacha20-poly1305") + --ucic:set("xray","omrout","s_shadowsocks_method","2022-blake3-aes-256-gcm") --ucic:set("shadowsocks-rust","sss0","method","2022-blake3-chacha20-poly1305") --ucic:set("shadowsocks-rust","sss1","method","2022-blake3-chacha20-poly1305") ucic:set("shadowsocks-rust","sss0","method","2022-blake3-aes-256-gcm") diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 0176273ea..110b0e87d 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -353,6 +353,7 @@ _set_xray_server_vps() { enabled=$(uci -q get xray.main.enabled) userid=$(uci -q get xray.omrout.s_vless_user_id) protocol=$(uci -q get xray.omrout.protocol) + ss_method=$(uci -q get xray.omrout.s_shadowsocks_method) if [ "$protocol" = "vless-reality" ] && [ "$enabled" = "1" ]; then vless_reality='true' else @@ -363,10 +364,11 @@ _set_xray_server_vps() { [ -z "$vps_config" ] && return current_userid="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.key')" current_vlessreality="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.vless_reality')" + current_method="$(echo "$vps_config" | jsonfilter -q -e '@.xray.config.ss_method')" - if [ "$current_userid" != "$userid" ] || [ "$current_vlessreality" != "$vless_reality" ]; then + if [ "$current_userid" != "$userid" ] || [ "$current_vlessreality" != "$vless_reality" ] || [ "$current_method" != "$ss_method" ]; then local settings - settings='{"userid": "'$userid'","vless_reality": '$vless_reality'}' + settings='{"userid": "'$userid'","vless_reality": '$vless_reality',"ss_method": "'$ss_method'"}' echo $(_set_json "xray" "$settings") fi } From 4e8f5847f6ed0768cf0dfcbde4f47d6c2dcd08c0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 10:59:20 +0100 Subject: [PATCH 1221/2059] Double quote for sqm-autorate config --- sqm-autorate/files/usr/share/sqm-autorate/config.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sqm-autorate/files/usr/share/sqm-autorate/config.sh b/sqm-autorate/files/usr/share/sqm-autorate/config.sh index 509dee635..2dcf3f7ba 100755 --- a/sqm-autorate/files/usr/share/sqm-autorate/config.sh +++ b/sqm-autorate/files/usr/share/sqm-autorate/config.sh @@ -10,7 +10,7 @@ # Modified by Ycarus (Yannick Chabanois) for OpenMPTCProuter: # * Get configuration via uci -INTERFACE=$1 +INTERFACE="$1" # *** OUTPUT OPTIONS *** @@ -26,10 +26,10 @@ debug=1 #dl_if=ifb4eth1 # download interface #dl_if=$(uci -q get sqm.${INTERFACE}.download_interface) -dl_if=ifb4$(uci -q get sqm.${INTERFACE}.interface) +dl_if="ifb4$(uci -q get sqm.${INTERFACE}.interface)" #ul_if=eth1 # upload interface #ul_if=$(uci -q get sqm.${INTERFACE}.upload_interface) -ul_if=$(uci -q get sqm.${INTERFACE}.interface) +ul_if="$(uci -q get sqm.${INTERFACE}.interface)" #reflector_ping_interval_s=0.2 # (seconds, e.g. 0.2s or 2s) reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.2") From 9656539d48c827171a7931ad9bdb42d9826a32e5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 14:24:46 +0100 Subject: [PATCH 1222/2059] Ignore routes when nexthop link is down --- shadowsocks-libev/files/shadowsocks.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shadowsocks-libev/files/shadowsocks.conf b/shadowsocks-libev/files/shadowsocks.conf index c9aedd2de..f02474433 100644 --- a/shadowsocks-libev/files/shadowsocks.conf +++ b/shadowsocks-libev/files/shadowsocks.conf @@ -52,6 +52,9 @@ net.ipv4.tcp_mtu_probing = 0 # Default conntrack is too small net.netfilter.nf_conntrack_max = 131072 +net.ipv4.conf.all.ignore_routes_with_linkdown = 1 +net.ipv4.conf.default.ignore_routes_with_linkdown = 1 + net.ipv4.tcp_ecn = 2 #net.ipv4.tcp_sack = 0 #net.ipv4.tcp_dsack = 0 From f5b2a50a11132d3be409ec4b2887a7d6502edabc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Dec 2023 21:39:19 +0100 Subject: [PATCH 1223/2059] Fix token request loop --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 110b0e87d..9edb82557 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2124,7 +2124,7 @@ _get_token() { [ "$(uci -q get openmptcprouter.${servername}.disabled)" = "1" ] && return token="" _login - [ -z "$token" ] && { + if [ -z "$token" ]; then reason="" test_ping() { _ping_server $1 @@ -2163,7 +2163,12 @@ _get_token() { uci -q batch <<-EOF >/dev/null set openmptcprouter.${servername}.admin_error=1 EOF - } + else + uci -q batch <<-EOF >/dev/null + set openmptcprouter.${servername}.token_error=0 + commit openmptcprouter + EOF + fi echo "$server:$serverport:$token" } From 59953aff5f26402b7cb57dfee70ea02f0e0ff1de Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Dec 2023 16:22:12 +0100 Subject: [PATCH 1224/2059] Fix test upload speed to server --- openmptcprouter/files/bin/omr-test-speed-server | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed-server b/openmptcprouter/files/bin/omr-test-speed-server index 74d110d1e..92f9334b5 100755 --- a/openmptcprouter/files/bin/omr-test-speed-server +++ b/openmptcprouter/files/bin/omr-test-speed-server @@ -48,9 +48,22 @@ if [ -n "$HOST" ] && [ -n "$PORT" ] && [ -n "$USERNAME" ] && [ -n "$PASSWORD" ]; # /etc/init.d/omr-tracker stop 2>&1 >/dev/null # multipath ${INTERFACE} off #fi + if [ -n "$UPLOAD" ]; then + if [ -f /usr/bin/v2ray ]; then + upload_file="/usr/bin/v2ray" + elif [ -f /usr/bin/xray ]; then + upload_file="/usr/bin/xray" + elif [ -f /boot/vmlinuz ]; then + upload_file="/boot/vmlinuz" + elif [ -f /bin/bash ]; then + upload_file="/bin/bash" + else + upload_file="/bin/busybox" + fi + fi if [ -n "$FASTTEST" ]; then if [ -n "$UPLOAD" ]; then - avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_upload}' -X POST -d @/boot/vmlinuz -d @/boot/vmlinuz --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) + avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_upload}' -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) echo -n "$avg_speed" else avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) @@ -58,7 +71,7 @@ if [ -n "$HOST" ] && [ -n "$PORT" ] && [ -n "$USERNAME" ] && [ -n "$PASSWORD" ]; fi else if [ -n "$UPLOAD" ]; then - curl -k -o /dev/null -X POST -d @/boot/vmlinuz -d @/boot/vmlinuz --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + curl -k -o /dev/null -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo else curl -k -o /dev/null --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo fi From fd35a9040f3adf4922e272c7dcc27986fe994f18 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 14 Dec 2023 16:22:36 +0100 Subject: [PATCH 1225/2059] Dirty fix for openmptcprouter config --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 9edb82557..f11cfe5fa 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2311,6 +2311,10 @@ token() { config_foreach _get_token server } +_fix_server() { + uci -q rename openmptcprouter.$1=server +} + start_service() { serversnb=0 wanips="" @@ -2318,6 +2322,7 @@ start_service() { [ -z "$serial" ] && [ -f "/usr/sbin/dmidecode" ] && serial=$(/usr/sbin/dmidecode -t 1 | egrep 'Serial' | awk '{print $3}') uci -q set openmptcprouter.settings.serial=${serial} config_load openmptcprouter + config_foreach _fix_server openmptcprouter config_foreach _count_server server config_foreach _get_local_wan_ip interface config_foreach _config_service server From 081d432ea4177b76c068390393bde25df9d1fc8b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Dec 2023 08:48:11 +0100 Subject: [PATCH 1226/2059] Add more log --- mptcp/files/etc/hotplug.d/iface/30-mptcp | 1 + mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mptcp/files/etc/hotplug.d/iface/30-mptcp b/mptcp/files/etc/hotplug.d/iface/30-mptcp index 6363894b0..607718dd1 100644 --- a/mptcp/files/etc/hotplug.d/iface/30-mptcp +++ b/mptcp/files/etc/hotplug.d/iface/30-mptcp @@ -10,6 +10,7 @@ if [ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = iflink ] && [ -z "$ logger -t "mptcp" "Reloading mptcp config due to $ACTION of $INTERFACE ($DEVICE)" /etc/init.d/mptcp reload "$DEVICE" >/dev/null || exit 0 else + logger -t "mptcp" "Set multipath off on $DEVICE ($INTERFACE) due to $ACTION" multipath $DEVICE off 2>&1 >/dev/null fi diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 737415ae9..a6e347037 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -1246,7 +1246,7 @@ fi _log "Reload MPTCP config for $OMR_TRACKER_DEVICE" /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" fi - _log "Multipath $OMR_TRACKER_DEVICE switched to $multipath_config (from $multipath_status)" + _log "Multipath $OMR_TRACKER_DEVICE ($OMR_TRACKER_INTERFACE) switched to $multipath_config (from $multipath_status)" multipath "$OMR_TRACKER_DEVICE" "$multipath_config" fi } From e374f7cb2e582965cde792b4366d8bb825852e40 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Dec 2023 08:58:10 +0100 Subject: [PATCH 1227/2059] More log for MPTCP --- mptcp/files/etc/init.d/mptcp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index d5dcf5f90..d3f6e1072 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -206,8 +206,9 @@ interface_multipath_settings() { #echo "îface: $iface" if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then + _logger -t "MPTCP" "Set $iface to $mode" if [ "$mode" = "master" ]; then - multipath "$iface" "on" + multipath "$iface" "on" else multipath "$iface" "$mode" fi @@ -428,7 +429,8 @@ set_multipath() { exist=1 fi done - [ "$exist" = "0" ] && { + [ "$exist" = "0" ] && [ -z "$(multipath $iface | grep deactivated)" ] && { + logger -t "MPTCP" "Disabling MPTCP on interface $iface not found in enabled multipath list" multipath $iface off } done From ced4a76faa1a8d3170b1a591d0462f489fae1907 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Dec 2023 19:30:31 +0100 Subject: [PATCH 1228/2059] Add test count as setting for OMR-Tracker --- .../luasrc/model/cbi/omr-tracker.lua | 14 +++++++++++++- omr-tracker/files/bin/omr-tracker | 15 ++++++++------- omr-tracker/files/etc/config/omr-tracker | 2 +- omr-tracker/files/etc/init.d/omr-tracker | 10 +++++++--- omr-tracker/files/etc/uci-defaults/omr-tracker | 6 ++++++ 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua b/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua index d81df88be..0e22a0e94 100644 --- a/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua +++ b/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua @@ -110,12 +110,18 @@ o.default = "1" o.datatype = "range(1, 100)" o.rmempty = false -o = s:option(Value, "tries", translate("Tries")) +o = s:option(Value, "tries", translate("Tries"), translate("How many times repeat test")) o.placeholder = "4" o.default = "4" o.datatype = "range(1, 10)" o.rmempty = false +o = s:option(Value, "count", translate("Count"), translate("How many packets send on each test")) +o.placeholder = "2" +o.default = "2" +o.datatype = "range(1, 100)" +o.rmempty = false + o = s:option(Value, "interval", translate("Retry interval (s)")) o.placeholder = "2" o.default = "2" @@ -191,6 +197,12 @@ o.default = "4" o.datatype = "range(1, 10)" o.rmempty = false +o = s:option(Value, "count", translate("Count"), translate("How many packets send on each test, one wrong make test fail, one wrong make tail fail")) +o.placeholder = "2" +o.default = "2" +o.datatype = "range(1, 100)" +o.rmempty = false + o = s:option(Value, "interval", translate("Retry interval (s)")) o.placeholder = "2" o.default = "2" diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 81a37258b..75dc32ea2 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -148,10 +148,10 @@ _ping() { if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "3g" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "qmi" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "ncm" ]); then ret=$(ping -I "${device}" \ -w "$OMR_TRACKER_TIMEOUT" \ - -c 2 \ + -c "$OMR_TRACKER_COUNT" \ -Q 184 \ "${host}" 2>&1 - ) && echo "$ret" | grep -sq "bytes from" && { + ) && echo "$ret" | grep -sq " 0% packet loss" && { if [ "$localip" = "yes" ]; then OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') _update_rto "$OMR_TRACKER_LATENCY" @@ -161,16 +161,17 @@ _ping() { else ret=$(ping -B -I "${device}" \ -w "$OMR_TRACKER_TIMEOUT" \ - -c 2 \ + -c "$OMR_TRACKER_COUNT" \ -Q 184 \ "${host}" 2>&1 - ) && echo "$ret" | grep -sq "bytes from" && { + ) && echo "$ret" | grep -sq " 0% packet loss" && { if [ "$localip" = "yes" ]; then OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') _update_rto "$OMR_TRACKER_LATENCY" fi return } + #) && echo "$ret" | grep -sq "bytes from" && { fi false } @@ -184,7 +185,7 @@ _httping() { ret=$(httping "${host}" \ -y "${deviceip}" \ -t "$OMR_TRACKER_TIMEOUT" \ - -c 1 2>&1 + -c "$OMR_TRACKER_COUNT" 2>&1 ) && echo "$ret" | grep -sq "1 ok" && { if [ "$localip" = "yes" ]; then OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') @@ -196,7 +197,7 @@ _httping() { ret=$(httping -l "${host}" \ -y "${deviceip}" \ -t "$OMR_TRACKER_TIMEOUT" \ - -c 1 2>&1 + -c "$OMR_TRACKER_COUNT" 2>&1 ) && echo "$ret" | grep -sq "1 ok" && { if [ "$localip" = "yes" ]; then OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') @@ -214,7 +215,7 @@ _dns() { ret=$(dig @"${host}" \ -b "${deviceip}" \ +time="$OMR_TRACKER_TIMEOUT" \ - +tries=1 \ + +tries="$OMR_TRACKER_COUNT" \ one.one.one.one ) && echo "$ret" | grep -sq "1.1.1.1" && { OMR_TRACKER_LATENCY=$(echo "$ret" | awk '/Query time/{print $4}') diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index a2666586a..c8e484e08 100644 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -18,6 +18,7 @@ config defaults 'defaults' list hosts6 '2001:4860:4860::8888' list hosts6 '2001:4860:4860::8844' option timeout '2' + option count '2' option tries '3' option interval '2' option interval_tries '1' @@ -29,7 +30,6 @@ config defaults 'defaults' config proxy 'proxy' option enabled '1' - list hosts '1.0.0.1' list hosts '212.27.48.10' list hosts '198.27.92.1' list hosts '151.101.129.164' diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 1b7699ea7..76044c99a 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -16,13 +16,14 @@ . /lib/functions/network.sh _validate_section() { - local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_tries=$tries + local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_count=$count tmp_tries=$tries local tmp_interval=$interval tmp_interval_tries=$interval_tries tmp_options=$options tmp_type=$type tmp_enabled=$enabled tmp_wait_test=$wait_test tmp_server_http_test=$server_http_test uci_validate_section omr-tracker "$1" "$2" \ 'hosts:list(host)' \ 'hosts6:list(host)' \ 'timeout:uinteger' \ + 'count:uinteger' \ 'tries:uinteger' \ 'interval:uinteger' \ 'interval_tries:uinteger' \ @@ -35,6 +36,7 @@ _validate_section() { [ -z "$hosts" ] && hosts=$tmp_hosts [ -z "$hosts6" ] && hosts6=$tmp_hosts6 [ -z "$timeout" ] && timeout=$tmp_timeout + [ -z "$count" ] && count=$tmp_count [ -z "$tries" ] && tries=$tmp_tries [ -z "$interval" ] && interval=$tmp_interval [ -z "$interval_tries" ] && interval_tries=$tmp_interval_tries @@ -50,7 +52,7 @@ _launch_tracker() { loopback|lan*|if0*) return;; esac [ -z "$1" ] && return - local hosts hosts6 timeout tries interval interval_tries options type enabled wait_test ipv6 proto server_http_test + local hosts hosts6 timeout count tries interval interval_tries options type enabled wait_test ipv6 proto server_http_test _validate_section "defaults" "defaults" _validate_section "interface" "$1" @@ -75,8 +77,9 @@ _launch_tracker() { [ -z "${hosts}" ] && [ "$type" != "none" ] && return ifstatus=$(ifstatus "$1" | jsonfilter -q -e '@["up"]') ifdevice=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') - [ "${ifstatus}" = "false" ] && [ -z "${ifdevice}" ] && return + #[ "${ifstatus}" = "false" ] && [ -z "${ifdevice}" ] && return [ -z "${interval_tries}" ] && interval_tries=1 + [ -z "${count}" ] && count=2 procd_open_instance # shellcheck disable=SC2086 @@ -84,6 +87,7 @@ _launch_tracker() { procd_append_param env "OMR_TRACKER_HOSTS=$hosts" procd_append_param env "OMR_TRACKER_HOSTS6=$hosts6" procd_append_param env "OMR_TRACKER_TIMEOUT=$timeout" + procd_append_param env "OMR_TRACKER_COUNT=$count" procd_append_param env "OMR_TRACKER_TRIES=$tries" procd_append_param env "OMR_TRACKER_INTERVAL=$interval" procd_append_param env "OMR_TRACKER_INTERVAL_TRIES=$interval_tries" diff --git a/omr-tracker/files/etc/uci-defaults/omr-tracker b/omr-tracker/files/etc/uci-defaults/omr-tracker index 7ae77dddf..55d8d4ee6 100755 --- a/omr-tracker/files/etc/uci-defaults/omr-tracker +++ b/omr-tracker/files/etc/uci-defaults/omr-tracker @@ -64,6 +64,12 @@ if [ "$(uci -q get omr-tracker.proxy.hosts | grep '176.103.130.130')" != "" ]; t commit omr-tracker EOF fi +if [ "$(uci -q get omr-tracker.proxy.hosts | grep '1.0.0.1')" != "" ]; then + uci -q batch <<-EOF >/dev/null + del_list omr-tracker.proxy.hosts='1.0.0.1' + commit omr-tracker + EOF +fi if [ "$(uci -q get omr-tracker.proxy.hosts | grep '198.41.212.162')" = "" ]; then uci -q batch <<-EOF >/dev/null From 5d4c0e2d22c49b233691c9843ea3261db63ab03b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Dec 2023 19:31:07 +0100 Subject: [PATCH 1229/2059] Fix omr-test-speed-server --- .../files/bin/omr-test-speed-server | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/openmptcprouter/files/bin/omr-test-speed-server b/openmptcprouter/files/bin/omr-test-speed-server index 92f9334b5..39a0a878f 100755 --- a/openmptcprouter/files/bin/omr-test-speed-server +++ b/openmptcprouter/files/bin/omr-test-speed-server @@ -27,8 +27,8 @@ if [ -n "$HOST" ] && [ -n "$PORT" ] && [ -n "$USERNAME" ] && [ -n "$PASSWORD" ]; [ -z "$FASTTEST" ] && echo "No answer to API request..." exit 1 } - KEY="$(echo '$auth' | jsonfilter -q -e '@.access_token')" - [ -n "$KEY" ] && { + KEY=$(echo "$auth" | jsonfilter -q -e '@.access_token') + [ -z "$KEY" ] && { [ -z "$FASTTEST" ] && echo "No token..." exit 1 } @@ -63,17 +63,33 @@ if [ -n "$HOST" ] && [ -n "$PORT" ] && [ -n "$USERNAME" ] && [ -n "$PASSWORD" ]; fi if [ -n "$FASTTEST" ]; then if [ -n "$UPLOAD" ]; then - avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_upload}' -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) + if [ "$resolve" != "${HOST}" ] || [ "$valid_ip6" != "ok" ]; then + avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_upload}' -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) + else + avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_upload}' -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://[${HOST}]:${PORT}/speedtest 2>/dev/null) + fi echo -n "$avg_speed" else - avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) + if [ "$resolve" != "${HOST}" ] || [ "$valid_ip6" != "ok" ]; then + avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest 2>/dev/null) + else + avg_speed=$(curl -k --max-time 30 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://[${HOST}]:${PORT}/speedtest 2>/dev/null) + fi echo -n "$avg_speed" fi else if [ -n "$UPLOAD" ]; then - curl -k -o /dev/null -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + if [ "$resolve" != "${HOST}" ] || [ "$valid_ip6" != "ok" ]; then + curl -k -o /dev/null -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + else + curl -k -o /dev/null -X POST -d @${upload_file} -d @${upload_file} --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://[${HOST}]:${PORT}/speedtest || echo + fi else - curl -k -o /dev/null --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + if [ "$resolve" != "${HOST}" ] || [ "$valid_ip6" != "ok" ]; then + curl -k -o /dev/null --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + else + curl -k -o /dev/null --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://[${HOST}]:${PORT}/speedtest || echo + fi fi fi #if [ $MP ]; then @@ -83,6 +99,10 @@ if [ -n "$HOST" ] && [ -n "$PORT" ] && [ -n "$USERNAME" ] && [ -n "$PASSWORD" ]; [ -z "$FASTTEST" ] && echo "Restart SQM on $INTERFACE" /etc/init.d/sqm start $INTERFACE 2>&1 >/dev/null else - curl -k -o /dev/null -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + if [ "$resolve" != "${HOST}" ] || [ "$valid_ip6" != "ok" ]; then + curl -k -o /dev/null -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + else + curl -k -o /dev/null -H "Authorization: Bearer ${KEY}" https://[${HOST}]:${PORT}/speedtest || echo + fi fi fi \ No newline at end of file From 57a0cf4e672f3415cc93021b290fa61efef25037 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 18 Dec 2023 09:42:29 +0100 Subject: [PATCH 1230/2059] Update XRay --- xray-core/Makefile | 4 +- xray-core/patches/001-fix-wireguard-go.patch | 97 -------------------- 2 files changed, 2 insertions(+), 99 deletions(-) delete mode 100644 xray-core/patches/001-fix-wireguard-go.patch diff --git a/xray-core/Makefile b/xray-core/Makefile index 4caa7ef87..8952c64e7 100644 --- a/xray-core/Makefile +++ b/xray-core/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=xray-core -PKG_VERSION:=1.8.5 +PKG_VERSION:=1.8.6 PKG_RELEASE:=1 PKG_LICENSE:=MPLv2 @@ -9,7 +9,7 @@ PKG_LICENSE_FILES:=LICENSE PKG_MAINTAINER:=Yannick Chabanois PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/XTLS/Xray-core.git -PKG_SOURCE_VERSION:=585d5ba7c8b64f6da60837546a70bbcfd2350c64 +PKG_SOURCE_VERSION:=5a5e615b46369579240dac1fdfe2b5e122c4c4ce PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 diff --git a/xray-core/patches/001-fix-wireguard-go.patch b/xray-core/patches/001-fix-wireguard-go.patch deleted file mode 100644 index 421febce6..000000000 --- a/xray-core/patches/001-fix-wireguard-go.patch +++ /dev/null @@ -1,97 +0,0 @@ -diff -aurN xray-core-1.8.5.old/go.mod xray-core-1.8.5/go.mod ---- a/go.mod 2023-09-18 16:14:12.554956393 +0200 -+++ b/go.mod 2023-09-18 16:16:56.304259547 +0200 -@@ -12,13 +12,13 @@ - github.com/pires/go-proxyproto v0.7.0 - github.com/quic-go/quic-go v0.38.1 - github.com/refraction-networking/utls v1.4.3 -- github.com/sagernet/sing v0.2.9 -+ github.com/sagernet/sing v0.2.10-0.20230807080248-4db0062caa0a - github.com/sagernet/sing-shadowsocks v0.2.4 -- github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c - github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb - github.com/stretchr/testify v1.8.4 - github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e - github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6 -+ github.com/xtls/wireguard-go v0.0.0-20230303120718-56f003b3a66e - go4.org/netipx v0.0.0-20230824141953-6213f710f925 - golang.org/x/crypto v0.12.0 - golang.org/x/net v0.14.0 -@@ -47,7 +47,7 @@ - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.3 // indirect - github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect -- go.uber.org/atomic v1.11.0 // indirect -+ go.uber.org/atomic v1.10.0 // indirect - golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/text v0.12.0 // indirect -diff -aurN xray-core-1.8.5.old/go.sum xray-core-1.8.5/go.sum ---- a/go.sum 2023-09-18 16:14:12.554956393 +0200 -+++ b/go.sum 2023-09-18 16:16:56.304259547 +0200 -@@ -123,12 +123,10 @@ - github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= - github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= - github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= --github.com/sagernet/sing v0.2.9 h1:3wsTz+JG5Wzy65eZnh6AuCrD2QqcRF6Iq6f7ttmJsAo= --github.com/sagernet/sing v0.2.9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= -+github.com/sagernet/sing v0.2.10-0.20230807080248-4db0062caa0a h1:b89t6Mjgk4rJ5lrNMnCzy1/J116XkhgdB3YNd9FHyF4= -+github.com/sagernet/sing v0.2.10-0.20230807080248-4db0062caa0a/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA= - github.com/sagernet/sing-shadowsocks v0.2.4 h1:s/CqXlvFAZhlIoHWUwPw5CoNnQ9Ibki9pckjuugtVfY= - github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM= --github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo= --github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI= - github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U= - github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= - github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -@@ -168,10 +166,12 @@ - github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= - github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6 h1:T+YCYGfFdzyaKTDCdZn/hEiKvsw6yUfd+e4hze0rCUw= - github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y= -+github.com/xtls/wireguard-go v0.0.0-20230303120718-56f003b3a66e h1:Y0CxNt+TeOhFUS2J/EF6osq9RukduvGYUNk2xPdKW60= -+github.com/xtls/wireguard-go v0.0.0-20230303120718-56f003b3a66e/go.mod h1:XFvPXP1gUqy/12j+KbdShku+YWiZJjaYLEAn4ZXaRGU= - github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= - go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= --go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= --go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -+go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -+go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= - go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= - go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ= - go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -diff -aurN xray-core-1.8.5.old/proxy/wireguard/bind.go xray-core-1.8.5/proxy/wireguard/bind.go ---- a/proxy/wireguard/bind.go 2023-09-18 16:14:12.562956262 +0200 -+++ b/proxy/wireguard/bind.go 2023-09-18 16:15:43.597456179 +0200 -@@ -9,7 +9,7 @@ - "strconv" - "sync" - -- "github.com/sagernet/wireguard-go/conn" -+ "github.com/xtls/wireguard-go/conn" - xnet "github.com/xtls/xray-core/common/net" - "github.com/xtls/xray-core/features/dns" - "github.com/xtls/xray-core/transport/internet" -diff -aurN xray-core-1.8.5.old/proxy/wireguard/tun.go xray-core-1.8.5/proxy/wireguard/tun.go ---- a/proxy/wireguard/tun.go 2023-09-18 16:14:12.562956262 +0200 -+++ b/proxy/wireguard/tun.go 2023-09-18 16:15:52.413310983 +0200 -@@ -12,7 +12,7 @@ - "net/netip" - "os" - -- "github.com/sagernet/wireguard-go/tun" -+ "github.com/xtls/wireguard-go/tun" - "github.com/xtls/xray-core/features/dns" - "gvisor.dev/gvisor/pkg/buffer" - "gvisor.dev/gvisor/pkg/tcpip" -diff -aurN xray-core-1.8.5.old/proxy/wireguard/wireguard.go xray-core-1.8.5/proxy/wireguard/wireguard.go ---- a/proxy/wireguard/wireguard.go 2023-09-18 16:14:12.562956262 +0200 -+++ b/proxy/wireguard/wireguard.go 2023-09-18 16:16:01.109167878 +0200 -@@ -27,7 +27,7 @@ - "net/netip" - "strings" - -- "github.com/sagernet/wireguard-go/device" -+ "github.com/xtls/wireguard-go/device" - "github.com/xtls/xray-core/common" - "github.com/xtls/xray-core/common/buf" - "github.com/xtls/xray-core/common/log" From 437436c553ea31ed3bddffec19a161b836c25be5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Dec 2023 10:55:43 +0100 Subject: [PATCH 1231/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3082 --- mptcp/files/usr/bin/multipath | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index a44d7f24b..3e75eb5e7 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -139,12 +139,12 @@ else done } - ID=$(ip mptcp endpoint show | grep -m 1 "dev $DEVICE" | awk '{print $3}') - IFF=$(ip mptcp endpoint show | grep -m 1 "dev $DEVICE" | awk '{print $4}') + ID=$(ip mptcp endpoint show | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $3}') + IFF=$(ip mptcp endpoint show | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') [ -f /usr/bin/jsonfilter ] && IP=$(ip -j a show $DEVICE | jsonfilter -e '@[0].addr_info[*].local') [ -f /usr/bin/jq ] && IP=$(ip -j a show $DEVICE | jq -r '.[0].addr_info[].local') - [ -z "$ID" ] && [ -n "$IP" ] && ID=$(ip mptcp endpoint show | grep "$IP" | awk '{print $3}') + [ -z "$ID" ] && [ -n "$IP" ] && ID=$(ip mptcp endpoint show | grep "$IP " | awk '{print $3}') RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null case $TYPE in From 3d2f1df9ab394bd3533400213ed139bf68963bfc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Dec 2023 10:56:14 +0100 Subject: [PATCH 1232/2059] Fix omr-tracker launch for specified interface --- omr-tracker/files/etc/init.d/omr-tracker | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 76044c99a..35d2c4e1c 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -9,7 +9,7 @@ START=90 STOP=10 USE_PROCD=1 - EXTRA_COMMAND="start_interface" + EXTRA_COMMANDS="start_interface" } . /usr/lib/unbound/iptools.sh @@ -355,6 +355,7 @@ _gre_tunnel() { start_interface() { [ -z "$1" ] && return + config_load network _launch_tracker $1 } From 6001c2f1a7e7e2549e7f76accf1b9d3b33dc7a94 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Dec 2023 10:58:56 +0100 Subject: [PATCH 1233/2059] Doesn't remove multipath when not needed --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index d3f6e1072..8ea4f225b 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -429,7 +429,7 @@ set_multipath() { exist=1 fi done - [ "$exist" = "0" ] && [ -z "$(multipath $iface | grep deactivated)" ] && { + [ "$exist" = "0" ] && [ -z "$(multipath $iface | grep deactivated)" ] && [ "$iface" != "bonding_master" ] && [ -n "$(multipath $iface)" ] && { logger -t "MPTCP" "Disabling MPTCP on interface $iface not found in enabled multipath list" multipath $iface off } From 0db896540ceff6a57815e47c2f71510cd911f552 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Dec 2023 15:30:43 +0100 Subject: [PATCH 1234/2059] Fix find gateway in some cases --- omr-tracker/files/bin/omr-tracker | 3 +++ 1 file changed, 3 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 75dc32ea2..7f185d395 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -292,6 +292,9 @@ while true; do if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -m 1 default | awk '/via/ {print $3}' | tr -d "\n") fi + if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | awk '/via/ {print $3}' | tr -d "\n") + fi fi if [ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ]; then #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') From 9ab72fc773be5f6cf25f54ef8ac317fb4c9f74d4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Dec 2023 15:31:14 +0100 Subject: [PATCH 1235/2059] Fix Multipath to use all IPs --- mptcp/files/usr/bin/multipath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 3e75eb5e7..014c3a8af 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -139,7 +139,7 @@ else done } - ID=$(ip mptcp endpoint show | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $3}') + ID=$(ip mptcp endpoint show | sort | grep "dev $DEVICE " | awk '{print $3}') IFF=$(ip mptcp endpoint show | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') [ -f /usr/bin/jsonfilter ] && IP=$(ip -j a show $DEVICE | jsonfilter -e '@[0].addr_info[*].local') From 2b5c9591ca823cb1577ff84c24e80b929d0ce031 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Dec 2023 20:20:01 +0100 Subject: [PATCH 1236/2059] Update cryptodev --- cryptodev-linux/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cryptodev-linux/Makefile b/cryptodev-linux/Makefile index e0b56e17b..f03cc528e 100644 --- a/cryptodev-linux/Makefile +++ b/cryptodev-linux/Makefile @@ -15,7 +15,7 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/$(PKG_NAME)/$(PKG_NAME).git -PKG_SOURCE_VERSION:=bb8bc7cf60d2c0b097c8b3b0e807f805b577a53f +PKG_SOURCE_VERSION:=5e7121e45ff283d30097da381fd7e97c4bb61364 PKG_VERSION:=1.13-$(PKG_SOURCE_VERSION) PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING From 9c8645ae28d981845db938cf8506e879e80540c2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Dec 2023 20:20:29 +0100 Subject: [PATCH 1237/2059] Fix for DSCP --- luci-app-omr-dscp/root/etc/init.d/omr-dscp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/luci-app-omr-dscp/root/etc/init.d/omr-dscp b/luci-app-omr-dscp/root/etc/init.d/omr-dscp index 63dd5e19b..bed7c3bad 100755 --- a/luci-app-omr-dscp/root/etc/init.d/omr-dscp +++ b/luci-app-omr-dscp/root/etc/init.d/omr-dscp @@ -11,6 +11,14 @@ USE_PROCD=1 # shellcheck disable=SC1091 . /lib/functions.sh +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IP6TABLES="/usr/sbin/ip6tables-legacy" +else + IPTABLES="/usr/sbin/iptables" + IP6TABLES="/usr/sbin/ip6tables" +fi + # Get the lan interface name lan_device= config_load network @@ -19,10 +27,10 @@ config_get lan_device lan ifname config_load dscp _ipt4() { - iptables -w -t mangle "$@" 2>&1 >/dev/null + $IPTABLES -w -t mangle "$@" 2>&1 >/dev/null } _ipt6() { - ip6tables -w -t mangle "$@" 2>&1 >/dev/null + $IP6TABLES -w -t mangle "$@" 2>&1 >/dev/null } _add_dscp_rule() { From 4cd56cfc911ceecdf460f5ddbb38f7bc8b8e8dde Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Dec 2023 20:21:23 +0100 Subject: [PATCH 1238/2059] Shadowsocks-Rust can use only aes-256-gcm on OMR with Shadowsocks-go server for now --- .../htdocs/luci-static/resources/shadowsocks-rust.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js index 2c9ac0684..86c6ab0f8 100644 --- a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js +++ b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js @@ -133,7 +133,7 @@ return L.Class.extend({ o.datatype = 'port'; o.size = 5; - o = optfunc(form.ListValue, 'method', _('Method')); + o = optfunc(form.ListValue, 'method', _('Method'),_('Only 2022-blake3-aes-256-gcm is supported by OpenMPTCProuter Shadowsocks-GO')); methods.forEach(function(m) { o.value(m); }); From 554267c72764237267b8a7a27253c11ec9a351f7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Dec 2023 20:25:35 +0100 Subject: [PATCH 1239/2059] Update NDPI --- ndpi-netfilter2/Makefile | 12 +- .../patches/002-no-livepatch-required.patch | 194 +------------- ...3-bittorrent-compilation-remove-ipv6.patch | 237 ------------------ ...003-fix-compilation-for-kernel-6.7.0.patch | 26 ++ 4 files changed, 43 insertions(+), 426 deletions(-) delete mode 100644 ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch create mode 100644 ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index ab0ada4ce..0d2466d7e 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,7 +11,8 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 -PKG_REV:=3deea541af037b663b1b83a055b80d9a06a0afd2 +#PKG_REV:=3deea541af037b663b1b83a055b80d9a06a0afd2 +PKG_REV:=5cf35a64c8296b69099d3bd4c8cb9222f3174901 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git @@ -55,7 +56,8 @@ MAKE_PATH:=ndpi-netfilter MAKE_FLAGS += \ KERNEL_DIR="$(LINUX_DIR)" \ MODULES_DIR="$(TARGET_MODULES_DIR)" \ - NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter + NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter \ + CONFIG_NDPI_HOOK="yes" ifeq ($ARCH),aarch64) MAKE_FLAGS += ARCH="arm64" @@ -64,9 +66,9 @@ else endif define Build/Compile - (cd $(PKG_BUILD_DIR)/src/lib &&\ - gcc -g -O2 -fPIC -DPIC -DNDPI_LIB_COMPILATION -I../../src/include/ -I../../src/lib/third_party/include/ ndpi_network_list_compile.c -o ndpi_network_list_compile &&\ - ./ndpi_network_list_compile -o ndpi_network_list.c.inc ndpi_network_list_*.yaml) +# (cd $(PKG_BUILD_DIR)/src/lib &&\ +# gcc -g -O2 -fPIC -DPIC -DNDPI_LIB_COMPILATION -I../../src/include/ -I../../src/lib/third_party/include/ ndpi_network_list_compile.c -o ndpi_network_list_compile &&\ +# ./ndpi_network_list_compile -o ndpi_network_list.c.inc ndpi_network_list_*.yaml) $(MAKE) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR)/ndpi-netfilter endef diff --git a/ndpi-netfilter2/patches/002-no-livepatch-required.patch b/ndpi-netfilter2/patches/002-no-livepatch-required.patch index a97f001b2..8403ffb74 100644 --- a/ndpi-netfilter2/patches/002-no-livepatch-required.patch +++ b/ndpi-netfilter2/patches/002-no-livepatch-required.patch @@ -1,190 +1,16 @@ -From 9e2bc31b8c330dc6ad0e6e478103652cd72dc3c8 Mon Sep 17 00:00:00 2001 -From: Sebastian Gottschall -Date: Sun, 9 Jul 2023 12:22:02 +0600 -Subject: [PATCH] add ndpi support for arm/arm64 etc. in 6.1 - -ndpi is not supported in more recent kernels without livepatch support -however. livepatch is only supported for x86_64 architectures. -so ndpi cannot be used on any other platform anymore. -we solve this by adding a simple hook to nf_ct_destroy - -Signed-off-by: Sebastian Gottschall ---- - ndpi-netfilter/kernel-patch/v6.1.38.diff | 81 ++++++++++++++++++++++++ - ndpi-netfilter/src/main.c | 23 +++++-- - 2 files changed, 98 insertions(+), 6 deletions(-) - create mode 100644 ndpi-netfilter/kernel-patch/v6.1.38.diff - -diff --git a/ndpi-netfilter/kernel-patch/v6.1.38.diff b/ndpi-netfilter/kernel-patch/v6.1.38.diff -new file mode 100644 -index 0000000000..6846dc84fc ---- /dev/null -+++ b/ndpi-netfilter/kernel-patch/v6.1.38.diff -@@ -0,0 +1,81 @@ -+diff -urpN linux-6.1.38.old/include/net/netfilter/nf_conntrack.h linux-6.1.38/include/net/netfilter/nf_conntrack.h -+--- linux-6.1.38.old/include/net/netfilter/nf_conntrack.h 2023-07-05 23:27:38.000000000 +0600 -++++ linux-6.1.38/include/net/netfilter/nf_conntrack.h 2023-07-14 12:34:56.663750711 +0600 -+@@ -362,6 +362,11 @@ static inline struct nf_conntrack_net *n -+ return net_generic(net, nf_conntrack_net_id); -+ } -+ -++#ifdef CONFIG_NDPI_HOOK -++void register_ndpi_hook(void (*hook)(struct nf_conn *)); -++void unregister_ndpi_hook(void); -++#endif -++ -+ #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) -+ #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) -+ #define NF_CT_STAT_ADD_ATOMIC(net, count, v) this_cpu_add((net)->ct.stat->count, (v)) -+diff -urpN linux-6.1.38.old/net/netfilter/Kconfig linux-6.1.38/net/netfilter/Kconfig -+--- linux-6.1.38.old/net/netfilter/Kconfig 2023-07-05 23:27:38.000000000 +0600 -++++ linux-6.1.38/net/netfilter/Kconfig 2023-07-14 12:34:11.966879899 +0600 -+@@ -76,11 +76,15 @@ config NETFILTER_NETLINK_OSF -+ If this option is enabled, the kernel will include support -+ for passive OS fingerprint via NFNETLINK. -+ -++config NDPI_HOOK -++ bool -++ -+ config NF_CONNTRACK -+ tristate "Netfilter connection tracking support" -+ default m if NETFILTER_ADVANCED=n -+ select NF_DEFRAG_IPV4 -+ select NF_DEFRAG_IPV6 if IPV6 != n -++ select NDPI_HOOK -+ help -+ Connection tracking keeps a record of what packets have passed -+ through your machine, in order to figure out how they are related -+diff -urpN linux-6.1.38.old/net/netfilter/nf_conntrack_core.c linux-6.1.38/net/netfilter/nf_conntrack_core.c -+--- linux-6.1.38.old/net/netfilter/nf_conntrack_core.c 2023-07-05 23:27:38.000000000 +0600 -++++ linux-6.1.38/net/netfilter/nf_conntrack_core.c 2023-07-14 12:33:45.580092713 +0600 -+@@ -582,9 +582,30 @@ static void destroy_gre_conntrack(struct -+ #endif -+ } -+ -++#ifdef CONFIG_NDPI_HOOK -++ -++static void (*ndpi_hook)(struct nf_conn *) __rcu __read_mostly = NULL; -++ -++void register_ndpi_hook(void (*hook)(struct nf_conn *)) -++{ -++ rcu_assign_pointer(ndpi_hook, hook); -++} -++EXPORT_SYMBOL(register_ndpi_hook); -++ -++void unregister_ndpi_hook(void) -++{ -++ rcu_assign_pointer(ndpi_hook, NULL); -++} -++ -++EXPORT_SYMBOL(unregister_ndpi_hook); -++#endif -++ -+ void nf_ct_destroy(struct nf_conntrack *nfct) -+ { -+ struct nf_conn *ct = (struct nf_conn *)nfct; -++#ifdef CONFIG_NDPI_HOOK -++ void (*hook)(struct nf_conn *); -++#endif -+ -+ pr_debug("%s(%p)\n", __func__, ct); -+ WARN_ON(refcount_read(&nfct->use) != 0); -+@@ -594,6 +615,12 @@ void nf_ct_destroy(struct nf_conntrack * -+ return; -+ } -+ -++#ifdef CONFIG_NDPI_HOOK -++ hook = rcu_dereference(ndpi_hook); -++ if (hook) -++ hook(ct); -++#endif -++ -+ if (unlikely(nf_ct_protonum(ct) == IPPROTO_GRE)) -+ destroy_gre_conntrack(ct); -+ -diff --git a/ndpi-netfilter/src/main.c b/ndpi-netfilter/src/main.c -index 024ca4bb79..e8ae3912d7 100644 ---- a/ndpi-netfilter/src/main.c -+++ b/ndpi-netfilter/src/main.c -@@ -102,7 +102,9 @@ static char proto_name[]="proto"; +--- a/ndpi-netfilter/src/main.c 2023-12-22 18:09:04.107421950 +0100 ++++ b/ndpi-netfilter/src/main.c 2023-12-22 18:10:11.038240353 +0100 +@@ -103,13 +103,7 @@ static char debug_name[]="debug"; static char risk_name[]="risks"; --#if LINUX_VERSION_CODE > KERNEL_VERSION(5,19,0) -+#ifdef CONFIG_NDPI_HOOK -+#define USE_NDPI_HOOK -+#elif LINUX_VERSION_CODE > KERNEL_VERSION(5,19,0) - #ifndef USE_LIVEPATCH - #define USE_LIVEPATCH - #endif -@@ -162,15 +164,17 @@ static inline const struct net_device *xt_out(const struct xt_action_param *par) - // for testing only! - // #define USE_CONNLABELS - --#if !defined(USE_CONNLABELS) && defined(CONFIG_NF_CONNTRACK_CUSTOM) && CONFIG_NF_CONNTRACK_CUSTOM > 0 -+#if !defined(USE_CONNLABELS) && !defined(USE_NDPI_HOOK) && defined(CONFIG_NF_CONNTRACK_CUSTOM) && CONFIG_NF_CONNTRACK_CUSTOM > 0 - #define NF_CT_CUSTOM - #else -+#ifndef USE_NDPI_HOOK - #undef NF_CT_CUSTOM - #include - #ifndef CONFIG_NF_CONNTRACK_LABELS - #error NF_CONNTRACK_LABELS not defined - #endif - #endif -+#endif - - #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0) - #define nf_ct_l3proto_try_module_get(a) 0 -@@ -3187,7 +3191,7 @@ static int __net_init ndpi_net_init(struct net *net) - return -ENOMEM; - } - +-#ifdef CONFIG_NF_CONNTRACK_DESTROY_HOOK + #define USE_NF_CONNTRACK_DESTROY_HOOK +-#elif LINUX_VERSION_CODE > KERNEL_VERSION(5,19,0) -#ifndef USE_LIVEPATCH -+#if !defined(USE_LIVEPATCH) && !defined(USE_NDPI_HOOK) - static struct nf_ct_ext_type ndpi_extend = { - #if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) - .seq_print = seq_print_ndpi, -@@ -3197,7 +3201,7 @@ static struct nf_ct_ext_type ndpi_extend = { - .align = __alignof__(uint32_t), - .id = 0, - }; --#else -+#elif !defined(USE_NDPI_HOOK) +-#define USE_LIVEPATCH +-#endif +-#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(5,17,0) - #error "not implemented" -@@ -3266,6 +3270,8 @@ static int __init ndpi_mt_init(void) - return -EBUSY; - } - nf_ct_ext_id_ndpi = ndpi_extend.id; -+#elif defined(USE_NDPI_HOOK) -+ register_ndpi_hook(&nf_ndpi_free_flow); - #else #ifdef USE_LIVEPATCH - nf_ct_ext_id_ndpi = NF_CT_EXT_LABELS; -@@ -3389,8 +3395,11 @@ static int __init ndpi_mt_init(void) - unreg_pernet: - unregister_pernet_subsys(&ndpi_net_ops); - unreg_ext: --#ifndef USE_LIVEPATCH -+#if !defined(USE_LIVEPATCH) && !defined(USE_NDPI_HOOK) - nf_ct_extend_unregister(&ndpi_extend); -+#endif -+#if defined(USE_NDPI_HOOK) -+ unregister_ndpi_hook(); - #endif - return ret; - } -@@ -3401,8 +3410,10 @@ static void __exit ndpi_mt_exit(void) - xt_unregister_target(&ndpi_tg_reg); - xt_unregister_match(&ndpi_mt_reg); - unregister_pernet_subsys(&ndpi_net_ops); --#ifndef USE_LIVEPATCH -+#if !defined(USE_LIVEPATCH) && !defined(USE_NDPI_HOOK) - nf_ct_extend_unregister(&ndpi_extend); -+#elif defined(USE_NDPI_HOOK) -+ unregister_ndpi_hook(); - #else - rcu_assign_pointer(nf_conntrack_destroy_cb,NULL); - #endif + #if IS_ENABLED(CONFIG_LIVEPATCH) diff --git a/ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch b/ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch deleted file mode 100644 index b72b4271f..000000000 --- a/ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch +++ /dev/null @@ -1,237 +0,0 @@ ---- a/src/lib/protocols/bittorrent.c.old 2023-07-15 11:45:44.566446059 +0200 -+++ b/src/lib/protocols/bittorrent.c 2023-07-15 11:49:25.498828807 +0200 -@@ -263,19 +263,6 @@ - return key % (size-1); - } - --#ifdef NDPI_DETECTION_SUPPORT_IPV6 --static inline u_int32_t hash_calc6(ndpi_ip_addr_t *ip,u_int16_t port,u_int32_t size) { -- u_int32_t M,I; -- u_int8_t *ipp = (u_int8_t *)&I; -- u_int32_t key; -- M=103; -- I = ip->ipv6.u6_addr.u6_addr32[0] + ip->ipv6.u6_addr.u6_addr32[1] + ip->ipv6.u6_addr.u6_addr32[2] + ip->ipv6.u6_addr.u6_addr32[3]; -- key = (((ipp[0] * M) + ipp[1] * M) + ipp[2]) * M +ipp[3]; -- ipp = (u_int8_t *)&port; -- key = ((key * M) + ipp[0] * M) + ipp[1]; -- return key % (size-1); --} --#endif - - // ndpi_ip_addr_t - static struct hash_ip4p_node *hash_ip4p_add(struct hash_ip4p_table *ht, -@@ -283,9 +270,6 @@ - struct hash_ip4p_node *n,*t; - - u_int32_t key = --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- ht->ipv6 ? hash_calc6(ip,port,ht->size) : --#endif - hash_calc(ip,port,ht->size); - - n = NULL; -@@ -293,22 +277,6 @@ - spin_lock(&ht->tbl[key].lock); - - n = ht->tbl[key].top; --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- if(ht->ipv6) { -- while(n) { -- if(!memcmp(&n->ip,ip->ipv6.u6_addr.u6_addr8,16) && n->port == port) { -- n->lchg = lchg; -- n->flag |= flag; -- move_up(&ht->tbl[key],n); -- goto unlock; -- } -- n = n->next; -- } -- n = BT_N_MALLOC(sizeof(struct hash_ip4p_node)+12); -- if(!n) goto unlock; -- memcpy(&n->ip,ip->ipv6.u6_addr.u6_addr8,16); -- } else { --#endif - while(n) { - if(n->ip == ip->ipv4 && n->port == port) { - n->lchg = lchg; -@@ -321,9 +289,6 @@ - n = BT_N_MALLOC(sizeof(struct hash_ip4p_node)); - if(!n) goto unlock; - n->ip = ip->ipv4; --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- } --#endif - t = ht->tbl[key].top; - n->next = t; - n->prev = NULL; -@@ -347,31 +312,16 @@ - struct hash_ip4p_node *n; - - u_int16_t key = --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- ht->ipv6 ? hash_calc6(ip,port,ht->size) : --#endif - hash_calc(ip,port,ht->size); - - n = NULL; - spin_lock(&ht->tbl[key].lock); - - n = ht->tbl[key].top; --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- if(ht->ipv6) { -- while(n) { -- if(!memcmp(&n->ip,ip->ipv6.u6_addr.u6_addr8,16) && n->port == port) -- break; -- n = n->next; -- } -- } else { --#endif - while(n) { - if(n->ip == ip->ipv4 && n->port == port) break; - n = n->next; - } --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- } --#endif - if(n) { - #ifdef __KERNEL__ - diagram(ndpi_btp_tm,sizeof(ndpi_btp_tm)/sizeof(ndpi_btp_tm[0]),lchg - n->lchg); -@@ -805,13 +755,6 @@ - u_int16_t s_port = packet->udp ? packet->udp->source : - packet->tcp ? packet->tcp->source : 0; - --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- if(packet->iphv6) -- bt_add_announce(ndpi_struct, -- ndpi_struct->bt_ann, ndpi_struct->bt_ann_len, -- 1, (ndpi_ip_addr_t *)&packet->iphv6->ip6_src, -- s_port, &x.p,p_now); --#endif - if(packet->iph) - bt_add_announce(ndpi_struct, - ndpi_struct->bt_ann, ndpi_struct->bt_ann_len, -@@ -819,39 +762,6 @@ - s_port, &x.p,p_now); - } - #endif --#ifdef NDPI_DETECTION_SUPPORT_IPV6 --if(packet->iphv6 && ndpi_struct->bt6_ht) { --NDPI_LOG_DBG2(ndpi_struct, -- "BT: detected valid DHT6 %d %d\n", -- x.p.r.nn6,x.p.r.nv6); --#ifndef __KERNEL__ --if(bt_parse_debug) dump_bt_proto_struct(&x.p); --#endif -- if(x.p.r.nodes6 && x.p.r.nn6) { -- struct bt_nodes6_data *n = x.p.r.nodes6; -- for(i=0; i < x.p.r.nn6; i++,n++) { -- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&n->ip,n->port,p_now,0x2); -- -- NDPI_LOG_DBG2(ndpi_struct, -- "BT: nodes6 add DHT peer %s:%d\n", -- inet_ntop(AF_INET6,(void *)&n->ip, ip6buf,sizeof(ip6buf)), -- htons(n->port)); -- } -- } -- if(x.p.r.values6 && x.p.r.nv6) { -- struct bt_ipv6p2 *n = (struct bt_ipv6p2 *)x.p.r.values6; -- for(i=0; i < x.p.r.nv6; i++,n++) { -- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&n->d.ip,n->d.port,p_now,0x4); -- -- NDPI_LOG_DBG2(ndpi_struct, -- "BT: values6 add DHT peer %s:%d\n", -- inet_ntop(AF_INET6,(void *)&n->d.ip, ip6buf,sizeof(ip6buf)), -- htons(n->d.port)); -- } -- } -- return r >= 0; --} --#endif - - if(!ndpi_struct->bt_ht) return r >= 0; - -@@ -899,16 +809,6 @@ - static void ndpi_bt_add_peer_cache(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_packet_struct *packet, uint16_t p_src, uint16_t p_dst) { - --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- if(ndpi_struct->bt6_ht && packet->iphv6) { -- if(packet->packet_direction) -- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_src, -- p_src, packet->current_time,1); -- else -- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_dst, -- p_dst, packet->current_time,1); -- } else --#endif - if(ndpi_struct->bt_ht && packet->iph) { - if(packet->packet_direction) - hash_ip4p_add(ndpi_struct->bt_ht,(ndpi_ip_addr_t *)&packet->iph->saddr, -@@ -1073,19 +973,6 @@ - if(!packet->tcp) return 0; - source = packet->tcp->source; - dest = packet->tcp->dest; --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- if(ndpi_struct->bt6_ht && packet->iphv6) { -- f1 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_src,source, -- packet->current_time); -- f2 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_dst,dest, -- packet->current_time); --#ifdef __KERNEL__ -- if(f1) ndpi_ptss++; -- if(f2) ndpi_ptdd++; --#endif -- return f1 != NULL || f2 != NULL; -- } --#endif - if(ndpi_struct->bt_ht && packet->iph) { - f1 = hash_ip4p_find(ndpi_struct->bt_ht,(ndpi_ip_addr_t *)&packet->iph->saddr,source, - packet->current_time); -@@ -1110,23 +997,6 @@ - if(!packet->udp) return 0; - source = packet->udp->source; - dest = packet->udp->dest; --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- if(ndpi_struct->bt6_ht && packet->iphv6) { -- f1 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_src,source, -- packet->current_time); -- f2 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_dst,dest, -- packet->current_time); --#ifdef __KERNEL__ -- if(f1) { -- DIRC(ndpi_pusr,ndpi_pusf); -- } -- if(f2) { -- DIRC(ndpi_pudr,ndpi_pudf); -- } --#endif -- return f1 != NULL || f2 != NULL; -- } --#endif - if(ndpi_struct->bt_ht && packet->iph) { - f1 = hash_ip4p_find(ndpi_struct->bt_ht,(ndpi_ip_addr_t *)&packet->iph->saddr,source, - packet->current_time); -@@ -1653,11 +1523,6 @@ - u_int32_t size,u_int32_t size6,u_int32_t tmo,int logsize) { - - ndpi_struct->bt_ht = hash_ip4p_init(size); --#ifdef NDPI_DETECTION_SUPPORT_IPV6 -- ndpi_struct->bt6_ht = hash_ip4p_init(size6); -- if(ndpi_struct->bt6_ht) -- ndpi_struct->bt6_ht->ipv6=1; --#endif - ndpi_bt_node_expire = tmo; - #ifdef BT_ANNOUNCE - if(logsize > 0) { -@@ -1679,12 +1544,6 @@ - hash_ip4p_del(ndpi_struct->bt_ht); - ndpi_struct->bt_ht = NULL; - } --#ifdef NDPI_DETECTION_SUPPORT_IPV6 --if(ndpi_struct->bt6_ht) { -- hash_ip4p_del(ndpi_struct->bt6_ht); -- ndpi_struct->bt6_ht = NULL; --} --#endif - } - - void init_bittorrent_dissector(struct ndpi_detection_module_struct *ndpi_struct, diff --git a/ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch b/ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch new file mode 100644 index 000000000..aa7cab996 --- /dev/null +++ b/ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch @@ -0,0 +1,26 @@ +--- a/ndpi-netfilter/src/main.c 2023-12-22 18:46:47.999596865 +0100 ++++ b/ndpi-netfilter/src/main.c 2023-12-22 18:48:52.981393673 +0100 +@@ -2840,7 +2840,11 @@ + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) + net->ct.label_words = n->labels_word; + #endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) + net->ct.labels_used--; ++#else ++ atomic_dec_return_relaxed(&net->ct.labels_used); ++#endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) + struct nf_ct_iter_data iter_data = { +@@ -3138,7 +3142,11 @@ + n->labels_word = ACCESS_ONCE(net->ct.label_words); + net->ct.label_words = 2; + #endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) + net->ct.labels_used++; ++#else ++ atomic_inc_return_relaxed(&net->ct.labels_used); ++#endif + #endif + if( ndpi_enable_flow && + nf_register_net_hooks(net, nf_nat_ipv4_ops, From 0f9be6e08d6d7217920ebac5c6e7513cdacecd53 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Dec 2023 21:33:51 +0100 Subject: [PATCH 1240/2059] Fix OMR-Tracker when launched without device on interface ready --- omr-tracker/files/bin/omr-tracker | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 7f185d395..110eda0ea 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -6,6 +6,7 @@ . /lib/functions.sh . /usr/lib/unbound/iptools.sh +. /lib/functions/network.sh # retrieve args OMR_TRACKER_INTERFACE="$1" @@ -246,6 +247,14 @@ while true; do OMR_TRACKER_DEVICE_GATEWAY= OMR_TRACKER_DEVICE_GATEWAY6= serverip_ping=false + [ -z "$OMR_TRACKER_DEVICE" ] && { + network_get_device OMR_TRACKER_DEVICE $OMR_TRACKER_INTERFACE + [ -z "$OMR_TRACKER_DEVICE" ] && network_get_physdev OMR_TRACKER_DEVICE $1 + [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1_4" | jsonfilter -q -e '@["l3_device"]') + [ -z "$OMR_TRACKER_DEVICE" ] && config_get OMR_TRACKER_DEVICE "$1" device + [ -n "$(echo $OMR_TRACKER_DEVICE | grep '@')" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') + } if [ -n "$OMR_TRACKER_DEVICE" ] && [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep UP)" ]; then From 9971a1c0930b1f32e842f0fcedc8fcf0436f86a3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 23 Dec 2023 08:43:04 +0100 Subject: [PATCH 1241/2059] Add kernel 6.7 restrictions --- luci-app-firewall/Makefile | 2 +- mptcpd/Makefile | 2 +- openmptcprouter-full/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/luci-app-firewall/Makefile b/luci-app-firewall/Makefile index b255cd140..a9e47df9b 100644 --- a/luci-app-firewall/Makefile +++ b/luci-app-firewall/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Firewall and Portforwarding application -LUCI_DEPENDS:=+@LINUX_5_4:firewall +@(LINUX_5_15||LINUX_6_1):uci-firewall +LUCI_DEPENDS:=+@LINUX_5_4:firewall +@(LINUX_5_15||LINUX_6_1||LINUX_6_6||LINUX_6_7):uci-firewall PKG_LICENSE:=Apache-2.0 PKG_VERSION:=omr-202103 diff --git a/mptcpd/Makefile b/mptcpd/Makefile index 04e44706c..36c3af633 100644 --- a/mptcpd/Makefile +++ b/mptcpd/Makefile @@ -28,7 +28,7 @@ include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) SECTION:=net CATEGORY:=Network -DEPENDS:=+libell @(LINUX_5_15||LINUX_6_1||LINUX_6_6) +DEPENDS:=+libell @!(LINUX_5_4) TITLE:=mptcpd URL:=https://github.com/intel/mptcpd endef diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 898ecef82..d598ef975 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -82,7 +82,7 @@ MY_DEPENDS := \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ - (LINUX_5_15||LINUX_6_1):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd \ + !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ xray-core shadowsocks-rust-sslocal shadowsocks-rust-ssservice shadowsocks-rust-config luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 From f1d429e0ee651735dc4146e5a2957ccb3f4ef4c4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 24 Dec 2023 10:54:04 +0100 Subject: [PATCH 1242/2059] Fix NDPI patch for kernel 5.4 --- ndpi-netfilter2/patches/002-no-livepatch-required.patch | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ndpi-netfilter2/patches/002-no-livepatch-required.patch b/ndpi-netfilter2/patches/002-no-livepatch-required.patch index 8403ffb74..e99b373bd 100644 --- a/ndpi-netfilter2/patches/002-no-livepatch-required.patch +++ b/ndpi-netfilter2/patches/002-no-livepatch-required.patch @@ -1,9 +1,10 @@ --- a/ndpi-netfilter/src/main.c 2023-12-22 18:09:04.107421950 +0100 +++ b/ndpi-netfilter/src/main.c 2023-12-22 18:10:11.038240353 +0100 -@@ -103,13 +103,7 @@ +@@ -103,13 +103,9 @@ static char debug_name[]="debug"; static char risk_name[]="risks"; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(5,19,0) -#ifdef CONFIG_NF_CONNTRACK_DESTROY_HOOK #define USE_NF_CONNTRACK_DESTROY_HOOK -#elif LINUX_VERSION_CODE > KERNEL_VERSION(5,19,0) @@ -11,6 +12,7 @@ -#define USE_LIVEPATCH -#endif -#endif ++#endif #ifdef USE_LIVEPATCH #if IS_ENABLED(CONFIG_LIVEPATCH) From 95cdac78e22ee139024861a49a4cec04ea1cca00 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Dec 2023 09:24:59 +0100 Subject: [PATCH 1243/2059] Rescan instead of restart ModemManager when modem missing, restart OpenPVN if not working --- .../usr/share/omr/post-tracking.d/001-post-tracking | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index a6e347037..3a315231d 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -748,8 +748,10 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi done if [ "$modemfind" = "0" ]; then - _log "Can't find $OMR_TRACKER_INTERFACE in ModemManager, restart modemmanager..." - /etc/init.d/modemmanager restart + _log "Can't find $OMR_TRACKER_INTERFACE in ModemManager, rescan modem..." + /usr/bin/mmcli -S 2>&1 >/dev/null + #_log "Can't find $OMR_TRACKER_INTERFACE in ModemManager, restart modemmanager..." + #/etc/init.d/modemmanager restart sleep 30 fi fi @@ -901,6 +903,10 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then _log "Glorytun UDP VPN down, restart it" /etc/init.d/glorytun-udp restart 2>&1 >/dev/null fi + if [ "$(uci -q get openvpn.omr.enabled)" = "1" ]; then + _log "OpenVPN down, restart it" + /etc/init.d/openvpn restart 2>&1 >/dev/null + fi config_load openmptcprouter config_foreach disable_pihole server #if [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ] || [ "$(uci -q get openmptcprouter.settings.vpn)" = "mlvpn" ]; then From 8d88557722ab57d30e31b6d85a37155df6f8b722 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Dec 2023 09:33:20 +0100 Subject: [PATCH 1244/2059] Fix NDPI on ARM --- .../patches/004-fix-compilation-on-arm.patch | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 ndpi-netfilter2/patches/004-fix-compilation-on-arm.patch diff --git a/ndpi-netfilter2/patches/004-fix-compilation-on-arm.patch b/ndpi-netfilter2/patches/004-fix-compilation-on-arm.patch new file mode 100644 index 000000000..7e7218e3e --- /dev/null +++ b/ndpi-netfilter2/patches/004-fix-compilation-on-arm.patch @@ -0,0 +1,10 @@ +--- a/src/include/ndpi_define.h.in 2023-12-25 08:45:56.692170223 +0100 ++++ b/src/include/ndpi_define.h.in 2023-12-25 08:46:11.595904820 +0100 +@@ -326,7 +326,6 @@ + #define get_u_int16_t(X,O) (*(u_int16_t *)((&(((u_int8_t *)X)[O])))) + #define get_u_int32_t(X,O) (*(u_int32_t *)((&(((u_int8_t *)X)[O])))) + #if defined(__arm__) +-#include + static inline uint64_t get_u_int64_t(const uint8_t* X, int O) + { + uint64_t tmp; From 4a23a992f4904725c22ef2302fb45da60ae58632 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 25 Dec 2023 09:54:32 +0100 Subject: [PATCH 1245/2059] Only indicate that modem is not in ModemManager for now... --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 3a315231d..12f10e425 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -748,9 +748,10 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi done if [ "$modemfind" = "0" ]; then - _log "Can't find $OMR_TRACKER_INTERFACE in ModemManager, rescan modem..." - /usr/bin/mmcli -S 2>&1 >/dev/null + #_log "Can't find $OMR_TRACKER_INTERFACE in ModemManager, rescan modem..." + #/usr/bin/mmcli -S 2>&1 >/dev/null #_log "Can't find $OMR_TRACKER_INTERFACE in ModemManager, restart modemmanager..." + _log "Can't find $OMR_TRACKER_INTERFACE in ModemManager" #/etc/init.d/modemmanager restart sleep 30 fi From cd85e5fb59cfb86d9dbbd3df2c2d50b96fa7fa8e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 26 Dec 2023 15:38:55 +0100 Subject: [PATCH 1246/2059] Don't use wrong device on OMR-Tracker when not yet available --- omr-bypass/files/etc/init.d/omr-bypass | 8 ++++++++ omr-tracker/files/bin/omr-tracker | 2 +- omr-tracker/files/etc/init.d/omr-tracker | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass b/omr-bypass/files/etc/init.d/omr-bypass index faceac0de..413165173 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass +++ b/omr-bypass/files/etc/init.d/omr-bypass @@ -73,7 +73,9 @@ _bypass_domains() { config_get enabled $1 enabled config_get noipv6 $1 noipv6 config_get family $1 family + config_get vpn $1 vpn [ -z "$intf" ] && intf="all" + [ "$vpn" = "1" ] && intf="srv_vpn1" [ "$enabled" = "0" ] && return [ -z "$domain" ] && return [ -z "$family" ] && family="ipv4ipv6" @@ -995,6 +997,12 @@ start_service() { create omr_dst_bypass_all hash:net hashsize 64 create omr6_dst_bypass_all hash:net family inet6 hashsize 64 EOF + ipset -q flush omr_dst_bypass_srv_vpn1 > /dev/null 2>&1 + ipset -q flush omr6_dst_bypass_srv_vpn1 > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create omr_dst_bypass_srv_vpn1 hash:net hashsize 64 + create omr6_dst_bypass_srv_vpn1 hash:net family inet6 hashsize 64 + EOF } $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 110eda0ea..7f0799eee 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -252,7 +252,7 @@ while true; do [ -z "$OMR_TRACKER_DEVICE" ] && network_get_physdev OMR_TRACKER_DEVICE $1 [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1_4" | jsonfilter -q -e '@["l3_device"]') - [ -z "$OMR_TRACKER_DEVICE" ] && config_get OMR_TRACKER_DEVICE "$1" device + #[ -z "$OMR_TRACKER_DEVICE" ] && config_get OMR_TRACKER_DEVICE "$1" device [ -n "$(echo $OMR_TRACKER_DEVICE | grep '@')" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') } diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 35d2c4e1c..2b1655ef5 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -61,7 +61,7 @@ _launch_tracker() { [ -z "$ifname" ] && network_get_physdev ifname $1 [ -z "$ifname" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -z "$ifname" ] && ifname=$(ifstatus "$1_4" | jsonfilter -q -e '@["l3_device"]') - [ -z "$ifname" ] && config_get ifname "$1" device + #[ -z "$ifname" ] && config_get ifname "$1" device [ -n "$(echo $ifname | grep '@')" ] && ifname=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') config_get multipath "$1" multipath From dfc9ea66c9d0728da4251b3e728384923621c895 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 26 Dec 2023 20:06:44 +0100 Subject: [PATCH 1247/2059] Fix default config for z8102ax --- openmptcprouter/files/etc/uci-defaults/1920-omr-network | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 4d2572a6e..5889afb48 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -430,7 +430,7 @@ if ([ "$board" = "teltonika,rutx" ] || [ "$board" = "teltonika,rutx12" ] || [ "$ EOF fi -if [ "$board" = "z8102ax" ]; then +if [ "$board" = "z8102ax-128m" ] || [ "$board" = "z8102ax-64m" ] || [ "$board" = "z8102ax" ]; then uci -q batch <<-EOF set network.modem1=interface set network.modem1.proto='modemmanager' From 01f17f82f699dfbc56f67f083a10897f8d6bd693 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 26 Dec 2023 20:23:11 +0100 Subject: [PATCH 1248/2059] Fix typo in mptcp init --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 8ea4f225b..2ca1050af 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -206,7 +206,7 @@ interface_multipath_settings() { #echo "îface: $iface" if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then - _logger -t "MPTCP" "Set $iface to $mode" + logger -t "MPTCP" "Set $iface to $mode" if [ "$mode" = "master" ]; then multipath "$iface" "on" else From a04b44f56bab6af546aedd79ad3e0e83cd6f57b3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Dec 2023 15:44:05 +0100 Subject: [PATCH 1249/2059] Fix mptcp init due to latest ipcalc.sh changes --- mptcp/files/etc/init.d/mptcp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 2ca1050af..781cf49cc 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -230,8 +230,8 @@ interface_multipath_settings() { config_get ipaddr $config ipaddr config_get gateway $config gateway config_get netmask $config netmask - [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr $netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` - [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr/$netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr/$netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` elif [ "$proto" != "gre" ]; then network_get_ipaddr ipaddr $config [ -z "$ipaddr" ] && ipaddr=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") @@ -257,8 +257,8 @@ interface_multipath_settings() { [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep peer | awk '{print $4}' | cut -d/ -f2 | tr -d "\n") [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") [ -n "$ipaddr" ] && ipaddr=$(echo $ipaddr | cut -d/ -f1 | tr -d "\n") - [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr $netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` - [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr/$netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr/$netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null @@ -443,8 +443,8 @@ add_route() { routeset="$target" config_get netmask "$1" netmask [ -n "$target" ] && [ -n "$netmask" ] && { - netmask=`ipcalc.sh $target $netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` - network=`ipcalc.sh $target $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + netmask=`ipcalc.sh $target/$netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` + network=`ipcalc.sh $target/$netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` [ -n "$netmask" ] && [ "$target" = "$network" ] && routeset="$routeset/$netmask" } config_get gateway "$1" gateway From 08157799fbcdc919527b4c7195d4feb4ce8089dc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Dec 2023 15:44:33 +0100 Subject: [PATCH 1250/2059] Reset modem when in failed state --- .../files/usr/share/omr/post-tracking.d/001-post-tracking | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 12f10e425..40c4308bf 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -743,8 +743,14 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then elif [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] && [ "$interface_up" = "false" ] && [ "$interface_available" = "false" ] && [ "$interface_pending" = "false" ] && [ "$interface_autostart" = "true" ]; then modemfind="0" for modem in $(timeout 3 mmcli -L | awk -F/ '{ print $6}' | awk '{print $1}'); do - if [ -n "$(timeout 2 mmcli -m $modem -K | grep $OMR_TRACKER_DEVICE)" ]; then + modeminfo="$(timeout 2 mmcli -m $modem -K)" + if [ -n "$(echo $modeminfo | grep $OMR_TRACKER_DEVICE)" ]; then modemfind="1" + if [ -n "$(echo $modeminfo | grep 'modem.generic.state ' | grep failed)" ] && [ -n "$(echo $modeminfo | grep 'modem.generic.state-failed-reason' | grep 'unknown-capabilities')" ]; then + _log "Interface $OMR_TRACKER_INTERFACE in failed state in ModemManager, reset modem..." + /usr/bin/mmcli -m ${modem} -r 2>&1 >/dev/null + sleep 30 + fi fi done if [ "$modemfind" = "0" ]; then From 20c219fdf26a7b48efcfddfde84d40b67b3ea3ef Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Dec 2023 15:44:57 +0100 Subject: [PATCH 1251/2059] Increase omr-tracker interval test for proxy --- omr-tracker/files/etc/config/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index c8e484e08..6f1e926a5 100644 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -41,7 +41,7 @@ config proxy 'proxy' option tries '3' option wait_test '0' option interval_tries '1' - option interval '5' + option interval '10' option mail_alert '0' config server 'server' From 1cf24d2475b8dddde4930aed0ff6361ae1c43a40 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Dec 2023 15:45:20 +0100 Subject: [PATCH 1252/2059] Remove ipset migration --- openmptcprouter/files/etc/uci-defaults/0000-omr-update | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/0000-omr-update b/openmptcprouter/files/etc/uci-defaults/0000-omr-update index 82a2cee3b..03f36123e 100755 --- a/openmptcprouter/files/etc/uci-defaults/0000-omr-update +++ b/openmptcprouter/files/etc/uci-defaults/0000-omr-update @@ -1,6 +1,9 @@ #!/bin/sh cd /etc/uci-defaults || exit 0 +# Keep dnsmasq ipset with old method +rm -f /etc/uci-defaults/50-dnsmasq-migrate-ipset.sh + source /etc/os-release files="$(ls /etc/uci-defaults/)" From 4c5361b2158ca57dbed9049961cef9a876e214ce Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Dec 2023 18:21:12 +0100 Subject: [PATCH 1253/2059] Remove aquantia module --- aquantia/Makefile | 41 ----------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 aquantia/Makefile diff --git a/aquantia/Makefile b/aquantia/Makefile deleted file mode 100644 index f99bb0c90..000000000 --- a/aquantia/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=kmod-aquantia -PKG_VERSION:=1.0 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/phy-aquantia - SUBMENU:=Network Devices - TITLE:=aQuantia device support - DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 @KERNEL_5_4 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-hwmon-core +kmod-libphy - KCONFIG:=CONFIG_AQUANTIA_PHY - HIDDEN:=1 - FILES:=$(LINUX_DIR)/drivers/net/phy/aquantia.ko - AUTOLOAD:=$(call AutoProbe,aquantia) -endef - -define KernelPackage/phy-aquantia/description - Kernel modules for aQuantia Ethernet adapters. -endef - -define KernelPackage/atlantic - SUBMENU:=Network Devices - TITLE:=aQuantia AQtion(tm) Support - DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 @KERNEL_5_4 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-phy-aquantia - KCONFIG:=CONFIG_AQTION - FILES:=$(LINUX_DIR)/drivers/net/ethernet/aquantia/atlantic/atlantic.ko - AUTOLOAD:=$(call AutoProbe,atlantic) -endef - -define KernelPackage/atlantic/description - Kernel modules for the aQuantia AQtion(tm) Ethernet card -endef - -define Build/Compile -endef - -$(eval $(call KernelPackage,phy-aquantia)) -$(eval $(call KernelPackage,atlantic)) \ No newline at end of file From 2160d47f4f20fe06a23c62e2958d0c306ff235c0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 30 Dec 2023 08:49:43 +0100 Subject: [PATCH 1254/2059] Update OMR-ByPass IP list --- .../usr/share/omr-bypass/omr-bypass-proto.lst | 26 ++++++++++++++++-- .../files/usr/share/omr-bypass/omr-bypass.db | Bin 2338816 -> 282624 bytes 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/omr-bypass/files/usr/share/omr-bypass/omr-bypass-proto.lst b/omr-bypass/files/usr/share/omr-bypass/omr-bypass-proto.lst index 8e24f9282..5229d7c7b 100644 --- a/omr-bypass/files/usr/share/omr-bypass/omr-bypass-proto.lst +++ b/omr-bypass/files/usr/share/omr-bypass/omr-bypass-proto.lst @@ -6,6 +6,7 @@ adultcontent alibaba amazon amazonalexa +amazon_aws amazonaws amazonvideo anydesk @@ -16,6 +17,7 @@ applepush applesiri applestore appletvplus +avast azure badoo bittorrent @@ -38,20 +40,24 @@ doh_dot dropbox eaq ebay +edgecast +epicgames +ethereum facebook fbookreelstory fuze +geforcenow github gitlab gmail google googleclassroom +google_cloud googlecloud googledocs googledrive googlehangout googlemaps -googleplus googleservices goto hbo @@ -69,15 +75,22 @@ linkedin livestream messenger microsoft +microsoft_365 microsoft365 +microsoft_azure +ms_one_drive ms_onedrive +ms_outlook +mullvad netflix nintendo ntop +nvidia ocs ocsp ookla opendns +operavpn outlook pandora pastebin @@ -86,15 +99,17 @@ playstation playstore pluralsight ppstream +protonvpn psiphon qq reddit riotgames +roblox salesforce showtime signal sina -sina(weibo) +sinaweibo siriusxmradio skype_teams slack @@ -102,13 +117,17 @@ snapchat softether soundcloud spotify +starcraft steam syncthing tailscale teams teamviewer telegram +tencent tencentvideo +teslaservices +threema tidal tiktok tor @@ -137,6 +156,7 @@ xbox xiaomi yahoo yandex +yandex_cloud yandexcloud yandexdirect yandexdisk @@ -147,4 +167,4 @@ yandexmusic youtube youtubeupload zattoo -zoom \ No newline at end of file +zoom diff --git a/omr-bypass/files/usr/share/omr-bypass/omr-bypass.db b/omr-bypass/files/usr/share/omr-bypass/omr-bypass.db index 1c03dc910688b0de0eea1497b88101f77a2407f0..f9cec43f4dacf44136df5b9f3e2e779dc75b594f 100644 GIT binary patch literal 282624 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 literal 2338816 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

    From 55cf527c17a6f9d3ebbe60b8b5dfb21945595965 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Jun 2023 06:25:01 +0200 Subject: [PATCH 0985/2059] Update v2ray --- v2ray-core/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 08d21ae81..f9254e896 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=v2ray-core -PKG_VERSION:=5.4.1 +PKG_VERSION:=5.7.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=e208bca255c4689a30104e965039d73fa138a7a6e902f820cff94b5b772b042b +PKG_HASH:=599fcd264537e39178b6008a11af68816dfd1609e19a9cf8adc8b2a4240ee370 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE From 9c253a282393d11ff3e2040b4b0007a572d7b690 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Jun 2023 08:12:10 +0200 Subject: [PATCH 0986/2059] Remove xtables-addons --- xtables-addons/Makefile | 200 - .../001-fix-kernel-version-detection.patch | 11 - .../patches/100-add-rtsp-conntrack.patch | 1742 -- .../patches/200-add-lua-packetscript.patch | 18158 ---------------- .../patches/201-fix-lua-packetscript.patch | 136 - ...-packetscript-kernel-5.16-no-isystem.patch | 284 - .../patches/210-freebsd-build-fix.patch | 11 - 7 files changed, 20542 deletions(-) delete mode 100644 xtables-addons/Makefile delete mode 100644 xtables-addons/patches/001-fix-kernel-version-detection.patch delete mode 100644 xtables-addons/patches/100-add-rtsp-conntrack.patch delete mode 100644 xtables-addons/patches/200-add-lua-packetscript.patch delete mode 100644 xtables-addons/patches/201-fix-lua-packetscript.patch delete mode 100644 xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch delete mode 100644 xtables-addons/patches/210-freebsd-build-fix.patch diff --git a/xtables-addons/Makefile b/xtables-addons/Makefile deleted file mode 100644 index cba09357d..000000000 --- a/xtables-addons/Makefile +++ /dev/null @@ -1,200 +0,0 @@ -# -# Copyright (C) 2009-2013 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=xtables-addons -PKG_VERSION:=3.22 -PKG_RELEASE:=$(AUTORELEASE) -PKG_HASH:=faa16a27166275afbfe8df605f55c3a81ac693bf19da674d45ceded4137ae217 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=https://inai.de/files/xtables-addons/ -PKG_BUILD_DEPENDS:=iptables -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - -PKG_MAINTAINER:=Jo-Philipp Wich -PKG_LICENSE:=GPL-2.0 - -PKG_FIXUP:=autoreconf -PKG_ASLR_PIE:=0 - -include $(INCLUDE_DIR)/package.mk - -define Package/xtables-addons - SECTION:=net - CATEGORY:=Network - SUBMENU:=Firewall - TITLE:=Extensions not distributed in the main Xtables - URL:=https://inai.de/projects/xtables-addons/ -endef - -# uses GNU configure - -CONFIGURE_ARGS+= \ - --with-kbuild="$(LINUX_DIR)" \ - --with-xtlibdir="/usr/lib/iptables" - -ifdef CONFIG_EXTERNAL_TOOLCHAIN -MAKE_FLAGS:= \ - $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ - DEPMOD="/bin/true" - -MAKE_INSTALL_FLAGS:= \ - $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ - DEPMOD="/bin/true" -else -define Build/Compile - +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ - $(KERNEL_MAKE_FLAGS) \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - DEPMOD="/bin/true" \ - all -endef - -define Build/Install - $(MAKE) -C $(PKG_BUILD_DIR) \ - $(KERNEL_MAKE_FLAGS) \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - DEPMOD="/bin/true" \ - install -endef -endif - -# 1: extension/module suffix used in package name -# 2: extension/module display name used in package title/description -# 3: list of extensions to package -# 4: list of modules to package -# 5: module load priority -# 6: module depends -define BuildTemplate - - ifneq ($(3),) - define Package/iptables-mod-$(1) - $$(call Package/xtables-addons) - CATEGORY:=Network - TITLE:=$(2) iptables extension - DEPENDS:=iptables $(if $(4),+kmod-ipt-$(1)) - endef - - define Package/iptables-mod-$(1)/install - $(INSTALL_DIR) $$(1)/usr/lib/iptables - for m in $(3); do \ - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so \ - $$(1)/usr/lib/iptables/ ; \ - done - endef - - $$(eval $$(call BuildPackage,iptables-mod-$(1))) - endif - - ifneq ($(4),) - define KernelPackage/ipt-$(1) - SUBMENU:=Netfilter Extensions - TITLE:=$(2) netfilter module - DEPENDS:=+kmod-ipt-core $(5) - FILES:=$(foreach mod,$(4),$(PKG_BUILD_DIR)/extensions/$(mod).$(LINUX_KMOD_SUFFIX)) - AUTOLOAD:=$(call AutoProbe,$(notdir $(4))) - endef - - $$(eval $$(call KernelPackage,ipt-$(1))) - endif - -endef - - -define Package/iptaccount - $(call Package/xtables-addons) - CATEGORY:=Network - TITLE:=iptables-mod-account control utility - DEPENDS:=iptables +iptables-mod-account -endef - -define Package/iptaccount/install - $(INSTALL_DIR) $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/sbin - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libxt_ACCOUNT_cl.so* \ - $(1)/usr/lib/ - $(CP) \ - $(PKG_INSTALL_DIR)/usr/sbin/iptaccount \ - $(1)/usr/sbin/ -endef - - -define Package/iptgeoip - $(call Package/xtables-addons) - CATEGORY:=Network - TITLE:=iptables-mod-geoip support scripts for MaxMind GeoIP databases - DEPENDS:=iptables +iptables-mod-geoip \ - +perl +perlbase-getopt +perlbase-io +perl-text-csv_xs \ - +perl-net-cidr-lite \ - +wget-ssl +!BUSYBOX_CONFIG_ZCAT:gzip -endef - -define Package/iptgeoip/config - menu "Select iptgeoip options" - config IPTGEOIP_PRESERVE - bool "Preserve across sysupgrades" - default n - help - Backup and restore during sysupgrade (requires >7MB) - endmenu -endef - -ifeq ($(CONFIG_IPTGEOIP_PRESERVE),y) -define Package/iptgeoip/conffiles -/usr/share/xt_geoip/ -endef -endif - -define Package/iptgeoip/install - $(INSTALL_DIR) $(1)/usr/lib/xtables-addons - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/xtables-addons/xt_geoip_{build,dl} \ - $(1)/usr/lib/xtables-addons/ - $(INSTALL_DIR) $(1)/usr/bin - $(CP) \ - $(PKG_INSTALL_DIR)/usr/bin/xt_geoip_fetch \ - $(1)/usr/bin/ - $(INSTALL_DIR) $(1)/usr/share/xt_geoip - touch $(1)/usr/share/xt_geoip/.keep -endef - - -#$(eval $(call BuildTemplate,SUFFIX,DESCRIPTION,EXTENSION,MODULE,PRIORITY,DEPENDS)) - -$(eval $(call BuildTemplate,compat-xtables,API compatibilty layer,,compat_xtables,+IPV6:kmod-ip6tables)) -$(eval $(call BuildTemplate,nathelper-rtsp,RTSP Conntrack and NAT,,rtsp/nf_conntrack_rtsp rtsp/nf_nat_rtsp,+kmod-ipt-conntrack-extra +kmod-ipt-nat)) - -$(eval $(call BuildTemplate,account,ACCOUNT,xt_ACCOUNT,ACCOUNT/xt_ACCOUNT,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,chaos,CHAOS,xt_CHAOS,xt_CHAOS,+kmod-ipt-compat-xtables +kmod-ipt-delude +kmod-ipt-tarpit)) -$(eval $(call BuildTemplate,condition,Condition,xt_condition,xt_condition,)) -$(eval $(call BuildTemplate,delude,DELUDE,xt_DELUDE,xt_DELUDE,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,dhcpmac,DHCPMAC,xt_DHCPMAC,xt_DHCPMAC,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,dnetmap,DNETMAP,xt_DNETMAP,xt_DNETMAP,+kmod-ipt-compat-xtables +kmod-ipt-nat)) -$(eval $(call BuildTemplate,fuzzy,fuzzy,xt_fuzzy,xt_fuzzy,)) -$(eval $(call BuildTemplate,geoip,geoip,xt_geoip,xt_geoip,)) -$(eval $(call BuildTemplate,iface,iface,xt_iface,xt_iface,)) -$(eval $(call BuildTemplate,ipmark,IPMARK,xt_IPMARK,xt_IPMARK,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,ipp2p,IPP2P,xt_ipp2p,xt_ipp2p,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,ipv4options,ipv4options,xt_ipv4options,xt_ipv4options,)) -$(eval $(call BuildTemplate,length2,length2,xt_length2,xt_length2,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,logmark,LOGMARK,xt_LOGMARK,xt_LOGMARK,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,lscan,lscan,xt_lscan,xt_lscan,)) -$(eval $(call BuildTemplate,lua,Lua PacketScript,xt_LUA,LUA/xt_LUA,+kmod-ipt-conntrack-extra)) -$(eval $(call BuildTemplate,proto,PROTO,xt_PROTO,xt_PROTO,)) -$(eval $(call BuildTemplate,psd,psd,xt_psd,xt_psd,)) -$(eval $(call BuildTemplate,quota2,quota2,xt_quota2,xt_quota2,)) -$(eval $(call BuildTemplate,sysrq,SYSRQ,xt_SYSRQ,xt_SYSRQ,+kmod-ipt-compat-xtables +kmod-crypto-hash)) -$(eval $(call BuildTemplate,tarpit,TARPIT,xt_TARPIT,xt_TARPIT,+kmod-ipt-compat-xtables)) - -$(eval $(call BuildPackage,iptaccount)) -$(eval $(call BuildPackage,iptgeoip)) diff --git a/xtables-addons/patches/001-fix-kernel-version-detection.patch b/xtables-addons/patches/001-fix-kernel-version-detection.patch deleted file mode 100644 index 775ccf657..000000000 --- a/xtables-addons/patches/001-fix-kernel-version-detection.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/configure.ac -+++ b/configure.ac -@@ -44,7 +44,7 @@ regular_CFLAGS="-Wall -Waggregate-return - - if test -n "$kbuilddir"; then - AC_MSG_CHECKING([kernel version that we will build against]) -- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" -+ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" - save_IFS="$IFS" - IFS='.' - set x $krel diff --git a/xtables-addons/patches/100-add-rtsp-conntrack.patch b/xtables-addons/patches/100-add-rtsp-conntrack.patch deleted file mode 100644 index dbdc52e94..000000000 --- a/xtables-addons/patches/100-add-rtsp-conntrack.patch +++ /dev/null @@ -1,1742 +0,0 @@ ---- /dev/null -+++ b/extensions/rtsp/Kbuild -@@ -0,0 +1,4 @@ -+# -*- Makefile -*- -+ -+obj-m += nf_nat_rtsp.o -+obj-m += nf_conntrack_rtsp.o ---- /dev/null -+++ b/extensions/rtsp/netfilter_helpers.h -@@ -0,0 +1,144 @@ -+/* -+ * Helpers for netfiler modules. This file provides implementations for basic -+ * functions such as strncasecmp(), etc. -+ * -+ * gcc will warn for defined but unused functions, so we only include the -+ * functions requested. The following macros are used: -+ * NF_NEED_STRNCASECMP nf_strncasecmp() -+ * NF_NEED_STRTOU16 nf_strtou16() -+ * NF_NEED_STRTOU32 nf_strtou32() -+ */ -+#ifndef _NETFILTER_HELPERS_H -+#define _NETFILTER_HELPERS_H -+ -+/* Only include these functions for kernel code. */ -+#ifdef __KERNEL__ -+ -+#include -+ -+#include -+#define iseol(c) ( (c) == '\r' || (c) == '\n' ) -+ -+/* -+ * The standard strncasecmp() -+ */ -+#ifdef NF_NEED_STRNCASECMP -+static int -+nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) -+{ -+ if (s1 == NULL || s2 == NULL) -+ { -+ if (s1 == NULL && s2 == NULL) -+ { -+ return 0; -+ } -+ return (s1 == NULL) ? -1 : 1; -+ } -+ while (len > 0 && tolower(*s1) == tolower(*s2)) -+ { -+ len--; -+ s1++; -+ s2++; -+ } -+ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); -+} -+#endif /* NF_NEED_STRNCASECMP */ -+ -+/* -+ * Parse a string containing a 16-bit unsigned integer. -+ * Returns the number of chars used, or zero if no number is found. -+ */ -+#ifdef NF_NEED_STRTOU16 -+static int -+nf_strtou16(const char* pbuf, u_int16_t* pval) -+{ -+ int n = 0; -+ -+ *pval = 0; -+ while (isdigit(pbuf[n])) -+ { -+ *pval = (*pval * 10) + (pbuf[n] - '0'); -+ n++; -+ } -+ -+ return n; -+} -+#endif /* NF_NEED_STRTOU16 */ -+ -+/* -+ * Parse a string containing a 32-bit unsigned integer. -+ * Returns the number of chars used, or zero if no number is found. -+ */ -+#ifdef NF_NEED_STRTOU32 -+static int -+nf_strtou32(const char* pbuf, u_int32_t* pval) -+{ -+ int n = 0; -+ -+ *pval = 0; -+ while (pbuf[n] >= '0' && pbuf[n] <= '9') -+ { -+ *pval = (*pval * 10) + (pbuf[n] - '0'); -+ n++; -+ } -+ -+ return n; -+} -+#endif /* NF_NEED_STRTOU32 */ -+ -+/* -+ * Given a buffer and length, advance to the next line and mark the current -+ * line. -+ */ -+#ifdef NF_NEED_NEXTLINE -+static int -+nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -+{ -+ uint off = *poff; -+ uint physlen = 0; -+ -+ if (off >= len) -+ { -+ return 0; -+ } -+ -+ while (p[off] != '\n') -+ { -+ if (len-off <= 1) -+ { -+ return 0; -+ } -+ -+ physlen++; -+ off++; -+ } -+ -+ /* if we saw a crlf, physlen needs adjusted */ -+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') -+ { -+ physlen--; -+ } -+ -+ /* advance past the newline */ -+ off++; -+ -+ *plineoff = *poff; -+ *plinelen = physlen; -+ *poff = off; -+ -+ return 1; -+} -+#endif /* NF_NEED_NEXTLINE */ -+ -+static inline int rtsp_nf_ct_expect_related(struct nf_conntrack_expect *expect) -+{ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) -+ return nf_ct_expect_related(expect, 0); -+#else -+ return nf_ct_expect_related(expect); -+#endif -+} -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _NETFILTER_HELPERS_H */ ---- /dev/null -+++ b/extensions/rtsp/netfilter_mime.h -@@ -0,0 +1,89 @@ -+/* -+ * MIME functions for netfilter modules. This file provides implementations -+ * for basic MIME parsing. MIME headers are used in many protocols, such as -+ * HTTP, RTSP, SIP, etc. -+ * -+ * gcc will warn for defined but unused functions, so we only include the -+ * functions requested. The following macros are used: -+ * NF_NEED_MIME_NEXTLINE nf_mime_nextline() -+ */ -+#ifndef _NETFILTER_MIME_H -+#define _NETFILTER_MIME_H -+ -+/* Only include these functions for kernel code. */ -+#ifdef __KERNEL__ -+ -+#include -+ -+/* -+ * Given a buffer and length, advance to the next line and mark the current -+ * line. If the current line is empty, *plinelen will be set to zero. If -+ * not, it will be set to the actual line length (including CRLF). -+ * -+ * 'line' in this context means logical line (includes LWS continuations). -+ * Returns 1 on success, 0 on failure. -+ */ -+#ifdef NF_NEED_MIME_NEXTLINE -+static int -+nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -+{ -+ uint off = *poff; -+ uint physlen = 0; -+ int is_first_line = 1; -+ -+ if (off >= len) -+ { -+ return 0; -+ } -+ -+ do -+ { -+ while (p[off] != '\n') -+ { -+ if (len-off <= 1) -+ { -+ return 0; -+ } -+ -+ physlen++; -+ off++; -+ } -+ -+ /* if we saw a crlf, physlen needs adjusted */ -+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') -+ { -+ physlen--; -+ } -+ -+ /* advance past the newline */ -+ off++; -+ -+ /* check for an empty line */ -+ if (physlen == 0) -+ { -+ break; -+ } -+ -+ /* check for colon on the first physical line */ -+ if (is_first_line) -+ { -+ is_first_line = 0; -+ if (memchr(p+(*poff), ':', physlen) == NULL) -+ { -+ return 0; -+ } -+ } -+ } -+ while (p[off] == ' ' || p[off] == '\t'); -+ -+ *plineoff = *poff; -+ *plinelen = (physlen == 0) ? 0 : (off - *poff); -+ *poff = off; -+ -+ return 1; -+} -+#endif /* NF_NEED_MIME_NEXTLINE */ -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _NETFILTER_MIME_H */ ---- /dev/null -+++ b/extensions/rtsp/nf_conntrack_rtsp.c -@@ -0,0 +1,756 @@ -+/* -+ * RTSP extension for IP connection tracking -+ * (C) 2003 by Tom Marshall -+ * -+ * 2005-02-13: Harald Welte -+ * - port to 2.6 -+ * - update to recent post-2.6.11 api changes -+ * 2006-09-14: Steven Van Acker -+ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack -+ * 2007-04-18: Michael Guntsche -+ * - Port to new NF API -+ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd -+ * - fixed rtcp nat mapping and other port mapping fixes -+ * - simple TEARDOWN request handling -+ * - codestyle fixes and other less significant bug fixes -+ * 2018-04-17: Alin Nastac -+ * Hans Dedecker -+ * - use IP address read from SETUP URI in expected connections -+ * 2018-04-18: Hans Dedecker -+ * - update RTP expected connection source IP based on SOURCE -+ * in the SETUP reply message -+ * 2018-08-03: Alin Nastac -+ * Hans Dedecker -+ * - parse non-standard destination=address:port format -+ * -+ * based on ip_conntrack_irc.c -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Module load syntax: -+ * insmod nf_conntrack_rtsp.o ports=port1,port2,...port -+ * max_outstanding=n setup_timeout=secs -+ * -+ * If no ports are specified, the default will be port 554. -+ * -+ * With max_outstanding you can define the maximum number of not yet -+ * answered SETUP requests per RTSP session (default 8). -+ * With setup_timeout you can specify how long the system waits for -+ * an expected data channel (default 300 seconds). -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "nf_conntrack_rtsp.h" -+ -+#define NF_NEED_STRNCASECMP -+#define NF_NEED_STRTOU16 -+#define NF_NEED_STRTOU32 -+#define NF_NEED_NEXTLINE -+#include "netfilter_helpers.h" -+#define NF_NEED_MIME_NEXTLINE -+#include "netfilter_mime.h" -+ -+#include -+ -+#define MAX_PORTS 8 -+static int ports[MAX_PORTS]; -+static int num_ports = 0; -+static int max_outstanding = 8; -+static unsigned int setup_timeout = 300; -+ -+MODULE_AUTHOR("Tom Marshall "); -+MODULE_DESCRIPTION("RTSP connection tracking module"); -+MODULE_LICENSE("GPL"); -+module_param_array(ports, int, &num_ports, 0400); -+MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); -+module_param(max_outstanding, int, 0400); -+MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); -+module_param(setup_timeout, uint, 0400); -+MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); -+ -+static char *rtsp_buffer; -+static DEFINE_SPINLOCK(rtsp_buffer_lock); -+ -+static struct nf_conntrack_expect_policy rtsp_exp_policy; -+ -+unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, -+ enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, unsigned int matchlen, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect *rtp_exp, -+ struct nf_conntrack_expect *rtcp_exp); -+ -+EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); -+ -+/* -+ * Max mappings we will allow for one RTSP connection (for RTP, the number -+ * of allocated ports is twice this value). Note that SMIL burns a lot of -+ * ports so keep this reasonably high. If this is too low, you will see a -+ * lot of "no free client map entries" messages. -+ */ -+#define MAX_PORT_MAPS 16 -+ -+/*** default port list was here in the masq code: 554, 3030, 4040 ***/ -+ -+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } -+ -+/* -+ * Parse an RTSP packet. -+ * -+ * Returns zero if parsing failed. -+ * -+ * Parameters: -+ * IN ptcp tcp data pointer -+ * IN tcplen tcp data len -+ * IN/OUT ptcpoff points to current tcp offset -+ * OUT phdrsoff set to offset of rtsp headers -+ * OUT phdrslen set to length of rtsp headers -+ * OUT pcseqoff set to offset of CSeq header -+ * OUT pcseqlen set to length of CSeq header -+ */ -+static int -+rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, -+ uint* phdrsoff, uint* phdrslen, -+ uint* pcseqoff, uint* pcseqlen, -+ uint* transoff, uint* translen) -+{ -+ uint entitylen = 0; -+ uint lineoff; -+ uint linelen; -+ -+ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) -+ return 0; -+ -+ *phdrsoff = *ptcpoff; -+ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) { -+ if (linelen == 0) { -+ if (entitylen > 0) -+ *ptcpoff += min(entitylen, tcplen - *ptcpoff); -+ break; -+ } -+ if (lineoff+linelen > tcplen) { -+ pr_info("!! overrun !!\n"); -+ break; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { -+ *pcseqoff = lineoff; -+ *pcseqlen = linelen; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { -+ *transoff = lineoff; -+ *translen = linelen; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) { -+ uint off = lineoff+15; -+ SKIP_WSPACE(ptcp+lineoff, linelen, off); -+ nf_strtou32(ptcp+off, &entitylen); -+ } -+ } -+ *phdrslen = (*ptcpoff) - (*phdrsoff); -+ -+ return 1; -+} -+ -+/* -+ * Find lo/hi client ports and/or source (if any) in transport header -+ * In: -+ * ptcp, tcplen = packet -+ * tranoff, tranlen = buffer to search -+ * -+ * Out: -+ * pport_lo, pport_hi = lo/hi ports (host endian) -+ * srvaddr -+ * -+ * Returns nonzero if any client ports found -+ * -+ * Note: it is valid (and expected) for the client to request multiple -+ * transports, so we need to parse the entire line. -+ */ -+static int -+rtsp_parse_transport(char* ptran, uint tranlen, -+ struct ip_ct_rtsp_expect* prtspexp) -+{ -+ int rc = 0; -+ uint off = 0; -+ -+ if (tranlen < 10 || !iseol(ptran[tranlen-1]) || -+ nf_strncasecmp(ptran, "Transport:", 10) != 0) { -+ pr_info("sanity check failed\n"); -+ return 0; -+ } -+ -+ pr_debug("tran='%.*s'\n", (int)tranlen, ptran); -+ off += 10; -+ SKIP_WSPACE(ptran, tranlen, off); -+ -+ /* Transport: tran;field;field=val,tran;field;field=val,... */ -+ while (off < tranlen) { -+ const char* pparamend; -+ uint nextparamoff; -+ -+ pparamend = memchr(ptran+off, ',', tranlen-off); -+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; -+ nextparamoff = pparamend-ptran; -+ -+ while (off < nextparamoff) { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ -+ if (strncmp(ptran+off, "client_port=", 12) == 0) { -+ u_int16_t port; -+ uint numlen; -+ -+ off += 12; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ if (prtspexp->loport != 0 && prtspexp->loport != port) -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ else { -+ pr_debug("lo port found : %hu\n", port); -+ prtspexp->loport = prtspexp->hiport = port; -+ if (ptran[off] == '-') { -+ off++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ prtspexp->pbtype = pb_range; -+ prtspexp->hiport = port; -+ -+ // If we have a range, assume rtp: -+ // loport must be even, hiport must be loport+1 -+ if ((prtspexp->loport & 0x0001) != 0 || -+ prtspexp->hiport != prtspexp->loport+1) { -+ pr_debug("incorrect range: %hu-%hu, correcting\n", -+ prtspexp->loport, prtspexp->hiport); -+ prtspexp->loport &= 0xfffe; -+ prtspexp->hiport = prtspexp->loport+1; -+ } -+ } else if (ptran[off] == '/') { -+ off++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ prtspexp->pbtype = pb_discon; -+ prtspexp->hiport = port; -+ } -+ rc = 1; -+ } -+ } else if (strncmp(ptran+off, "source=", 7) == 0) { -+ uint srcaddrlen; -+ -+ off += 7; -+ srcaddrlen = nextfieldoff - off - 1; -+ -+ if (in4_pton(ptran + off, srcaddrlen, -+ (u8 *)&prtspexp->srvaddr.in, -+ -1, NULL)) -+ pr_debug("source found : %pI4\n", -+ &prtspexp->srvaddr.ip); -+ } else if (nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { -+ const char *psep; -+ u_int16_t port; -+ -+ off += 12; -+ -+ if (in4_pton(ptran+off, nextfieldoff - off - 1, (u8 *)&prtspexp->cltaddr.in, -1, NULL)) { -+ pr_debug("destination found : %pI4\n", &prtspexp->cltaddr.ip); -+ -+ /* -+ * Some RTSP clients(mostly STBs) use non-standard destination parameters: -+ * destination=address:port -+ */ -+ psep = memchr(ptran+off, ':', nextfieldoff-off); -+ if (psep != NULL && nf_strtou16(psep + 1, &port)) { -+ if (prtspexp->loport != 0 && prtspexp->loport != port) -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ else { -+ pr_debug("lo port found : %hu\n", port); -+ prtspexp->loport = prtspexp->hiport = port; -+ } -+ } -+ } -+ } -+ -+ /* -+ * Note we don't look for the destination parameter here. -+ * If we are using NAT, the NAT module will handle it. If not, -+ * and the client is sending packets elsewhere, the expectation -+ * will quietly time out. -+ */ -+ -+ off = nextfieldoff; -+ } -+ -+ off = nextparamoff; -+ } -+ -+ return rc; -+} -+ -+ -+/*** conntrack functions ***/ -+ -+/* outbound packet: client->server */ -+ -+static inline int -+help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo, -+ unsigned int protoff) -+#else -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+#endif -+{ -+ struct ip_ct_rtsp_expect expinfo; -+ -+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ -+ //struct tcphdr* tcph = (void*)iph + iph->ihl * 4; -+ //uint tcplen = pktlen - iph->ihl * 4; -+ char* pdata = rb_ptr; -+ //uint datalen = tcplen - tcph->doff * 4; -+ uint dataoff = 0; -+ int ret = NF_ACCEPT; -+ -+ struct nf_conntrack_expect *rtp_exp; -+ struct nf_conntrack_expect *rtcp_exp = NULL; -+ -+ __be16 be_loport; -+ __be16 be_hiport; -+ -+ typeof(nf_nat_rtsp_hook) nf_nat_rtsp; -+ -+ memset(&expinfo, 0, sizeof(expinfo)); -+ -+ while (dataoff < datalen) { -+ uint cmdoff = dataoff; -+ uint hdrsoff = 0; -+ uint hdrslen = 0; -+ uint cseqoff = 0; -+ uint cseqlen = 0; -+ uint transoff = 0; -+ uint translen = 0; -+ uint off; -+ union nf_inet_addr srvaddr; -+ -+ if (!rtsp_parse_message(pdata, datalen, &dataoff, -+ &hdrsoff, &hdrslen, -+ &cseqoff, &cseqlen, -+ &transoff, &translen)) -+ break; /* not a valid message */ -+ -+ if (strncmp(pdata+cmdoff, "TEARDOWN ", 9) == 0) { -+ pr_debug("teardown handled\n"); -+ nf_ct_remove_expectations(ct); /* FIXME must be session id aware */ -+ break; -+ } -+ -+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) -+ continue; /* not a SETUP message */ -+ -+ srvaddr = ct->tuplehash[!dir].tuple.src.u3; -+ -+ /* try to get RTP media source from SETUP URI */ -+ off = cmdoff + 6; -+ while (off < datalen) { -+ if (strncmp(pdata+off, "://", 3) == 0) { -+ off += 3; -+ cmdoff = off; -+ -+ while (off < datalen) { -+ if (pdata[off] == ':' || -+ pdata[off] == '/' || -+ pdata[off] == ' ') { -+ in4_pton(pdata + cmdoff, -+ off - cmdoff, -+ (u8 *)&srvaddr.in, -+ -1, NULL); -+ break; -+ } -+ off++; -+ } -+ break; -+ } -+ off++; -+ } -+ -+ pr_debug("found a setup message\n"); -+ -+ off = 0; -+ if(translen) -+ rtsp_parse_transport(pdata+transoff, translen, &expinfo); -+ -+ if (expinfo.loport == 0) { -+ pr_debug("no udp transports found\n"); -+ continue; /* no udp transports found */ -+ } -+ -+ pr_debug("udp transport found, ports=(%d,%hu,%hu)\n", -+ (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); -+ -+ -+ be_loport = htons(expinfo.loport); -+ -+ rtp_exp = nf_ct_expect_alloc(ct); -+ if (rtp_exp == NULL) { -+ ret = NF_DROP; -+ goto out; -+ } -+ -+ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, -+ nf_ct_l3num(ct), NULL, -+ &ct->tuplehash[!dir].tuple.dst.u3, -+ IPPROTO_UDP, NULL, &be_loport); -+ -+ rtp_exp->flags = 0; -+ -+ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { -+ pr_debug("setup expectation for rtcp\n"); -+ -+ be_hiport = htons(expinfo.hiport); -+ rtcp_exp = nf_ct_expect_alloc(ct); -+ if (rtcp_exp == NULL) { -+ ret = NF_DROP; -+ goto out1; -+ } -+ -+ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, -+ nf_ct_l3num(ct), NULL, -+ &ct->tuplehash[!dir].tuple.dst.u3, -+ IPPROTO_UDP, NULL, &be_hiport); -+ -+ rtcp_exp->flags = 0; -+ -+ pr_debug("expect_related %pI4:%u-%u-%pI4:%u-%u\n", -+ &rtp_exp->tuple.src.u3.ip, -+ ntohs(rtp_exp->tuple.src.u.udp.port), -+ ntohs(rtcp_exp->tuple.src.u.udp.port), -+ &rtp_exp->tuple.dst.u3.ip, -+ ntohs(rtp_exp->tuple.dst.u.udp.port), -+ ntohs(rtcp_exp->tuple.dst.u.udp.port)); -+ } else { -+ pr_debug("expect_related %pI4:%u-%pI4:%u\n", -+ &rtp_exp->tuple.src.u3.ip, -+ ntohs(rtp_exp->tuple.src.u.udp.port), -+ &rtp_exp->tuple.dst.u3.ip, -+ ntohs(rtp_exp->tuple.dst.u.udp.port)); -+ } -+ -+ nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook); -+ if (nf_nat_rtsp && ct->status & IPS_NAT_MASK) -+ /* pass the request off to the nat helper */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen, -+ &expinfo, rtp_exp, rtcp_exp); -+#else -+ ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, -+ &expinfo, rtp_exp, rtcp_exp); -+#endif -+ else { -+ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { -+ if (rtcp_exp && rtsp_nf_ct_expect_related(rtcp_exp) != 0) { -+ nf_ct_unexpect_related(rtp_exp); -+ pr_info("nf_conntrack_expect_related failed for rtcp\n"); -+ ret = NF_DROP; -+ } -+ } else { -+ pr_info("nf_conntrack_expect_related failed for rtp\n"); -+ ret = NF_DROP; -+ } -+ } -+ if (rtcp_exp) { -+ nf_ct_expect_put(rtcp_exp); -+ } -+out1: -+ nf_ct_expect_put(rtp_exp); -+ goto out; -+ } -+out: -+ -+ return ret; -+} -+ -+ -+static inline int -+help_in(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo, -+ unsigned int protoff) -+#else -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+#endif -+ { -+ struct ip_ct_rtsp_expect expinfo; -+ union nf_inet_addr srvaddr; -+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ -+ int len; -+ char* pdata = rb_ptr; -+ uint dataoff = 0; -+ int ret = NF_ACCEPT; -+ u_int8_t family; -+ struct nf_conntrack_expect *exp_ct = NULL; -+ struct nf_conntrack_tuple t; -+ struct net *net = nf_ct_net(ct); -+ -+ memset(&expinfo, 0, sizeof(expinfo)); -+ -+ while (dataoff < datalen) { -+ uint cmdoff = dataoff; -+ uint hdrsoff = 0; -+ uint hdrslen = 0; -+ uint cseqoff = 0; -+ uint cseqlen = 0; -+ uint transoff = 0; -+ uint translen = 0; -+ -+ if (!rtsp_parse_message(pdata, datalen, &dataoff, -+ &hdrsoff, &hdrslen, -+ &cseqoff, &cseqlen, -+ &transoff, &translen)) -+ break; /* not a valid message */ -+ -+ if (strncmp(pdata+cmdoff, "RTSP/", 5) == 0 && translen) { -+ union nf_inet_addr zeroaddr; -+ -+ memset(&zeroaddr, 0, sizeof(zeroaddr)); -+ -+ if (!rtsp_parse_transport(pdata+transoff, translen, &expinfo)) -+ continue; -+ -+ srvaddr = expinfo.srvaddr; -+ -+ if (nf_inet_addr_cmp(&srvaddr, &ct->tuplehash[dir].tuple.src.u3) || -+ nf_inet_addr_cmp(&srvaddr, &zeroaddr)) -+ continue; -+ } else -+ continue; /* not valid RTSP reply */ -+ -+ if (expinfo.loport == 0) { -+ pr_debug("no udp transports found\n"); -+ continue; /* no udp transports found */ -+ } -+ -+ family = nf_ct_l3num(ct); -+ if (family == AF_INET) -+ len = 4; -+ else -+ len = 16; -+ -+ /* replace rtp expect src addr */ -+ t.src.l3num = family; -+ t.dst.protonum = IPPROTO_UDP; -+ -+ memcpy(&t.src.u3, &ct->tuplehash[dir].tuple.src.u3, len); -+ if (sizeof(t.src.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&t.src.u3 + len, 0, sizeof(t.src.u3) - len); -+ -+ t.src.u.all = 0; -+ -+ memcpy(&t.dst.u3, &ct->tuplehash[dir].tuple.dst.u3, len); -+ if (sizeof(t.dst.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&t.dst.u3 + len, 0, sizeof(t.dst.u3) - len); -+ -+ t.dst.u.all = htons(expinfo.loport); -+ -+ /* get the rtp expect and replace the srcaddr with RTP server addr */ -+ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); -+ if (exp_ct) { -+ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); -+ if (sizeof(exp_ct->tuple.src.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&exp_ct->tuple.src.u3 + len, 0, -+ sizeof(exp_ct->tuple.src.u3) - len); -+ } else -+ goto out; -+ -+ /* replace rtcp expect src addr */ -+ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { -+ t.dst.u.all = htons(expinfo.hiport); -+ -+ /* get the rtcp expect and replace the srcaddr with RTP server addr */ -+ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); -+ if (exp_ct) { -+ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); -+ if (sizeof(exp_ct->tuple.src.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&exp_ct->tuple.src.u3 + len, 0, -+ sizeof(exp_ct->tuple.src.u3) - len); -+ } else -+ goto out; -+ } -+ -+ goto out; -+ } -+out: -+ return ret; -+ } -+ -+static int help(struct sk_buff *skb, unsigned int protoff, -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+{ -+ struct tcphdr _tcph, *th; -+ unsigned int dataoff, datalen; -+ char *rb_ptr; -+ int ret = NF_DROP; -+ -+ /* Until there's been traffic both ways, don't look in packets. */ -+ if (ctinfo != IP_CT_ESTABLISHED && -+ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { -+ pr_debug("conntrackinfo = %u\n", ctinfo); -+ return NF_ACCEPT; -+ } -+ -+ /* Not whole TCP header? */ -+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); -+ -+ if (!th) -+ return NF_ACCEPT; -+ -+ /* No data ? */ -+ dataoff = protoff + th->doff*4; -+ datalen = skb->len - dataoff; -+ if (dataoff >= skb->len) -+ return NF_ACCEPT; -+ -+ spin_lock_bh(&rtsp_buffer_lock); -+ rb_ptr = skb_header_pointer(skb, dataoff, -+ skb->len - dataoff, rtsp_buffer); -+ BUG_ON(rb_ptr == NULL); -+ -+#if 0 -+ /* Checksum invalid? Ignore. */ -+ /* FIXME: Source route IP option packets --RR */ -+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, -+ csum_partial((char*)tcph, tcplen, 0))) -+ { -+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", -+ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); -+ return NF_ACCEPT; -+ } -+#endif -+ -+ switch (CTINFO2DIR(ctinfo)) { -+ case IP_CT_DIR_ORIGINAL: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff); -+#else -+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo); -+#endif -+ break; -+ case IP_CT_DIR_REPLY: -+ pr_debug("IP_CT_DIR_REPLY\n"); -+ /* inbound packet: server->client */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo, protoff); -+#else -+ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo); -+#endif -+ break; -+ default: -+ break; -+ } -+ -+ spin_unlock_bh(&rtsp_buffer_lock); -+ -+ return ret; -+} -+ -+static struct nf_conntrack_helper rtsp_helpers[MAX_PORTS]; -+static char rtsp_names[MAX_PORTS][10]; -+ -+/* This function is intentionally _NOT_ defined as __exit */ -+static void -+fini(void) -+{ -+ int i; -+ for (i = 0; i < num_ports; i++) { -+ pr_debug("unregistering port %d\n", ports[i]); -+ nf_conntrack_helper_unregister(&rtsp_helpers[i]); -+ } -+ kfree(rtsp_buffer); -+} -+ -+static int __init -+init(void) -+{ -+ int i, ret; -+ struct nf_conntrack_helper *hlpr; -+ char *tmpname; -+ -+ printk("nf_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); -+ -+ if (max_outstanding < 1) { -+ printk("nf_conntrack_rtsp: max_outstanding must be a positive integer\n"); -+ return -EBUSY; -+ } -+ -+ rtsp_exp_policy.max_expected = max_outstanding; -+ rtsp_exp_policy.timeout = setup_timeout; -+ -+ rtsp_buffer = kmalloc(65536, GFP_KERNEL); -+ if (!rtsp_buffer) -+ return -ENOMEM; -+ -+ /* If no port given, default to standard rtsp port */ -+ if (ports[0] == 0) { -+ ports[0] = RTSP_PORT; -+ num_ports = 1; -+ } -+ -+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { -+ hlpr = &rtsp_helpers[i]; -+ memset(hlpr, 0, sizeof(struct nf_conntrack_helper)); -+ hlpr->tuple.src.l3num = AF_INET; -+ hlpr->tuple.src.u.tcp.port = htons(ports[i]); -+ hlpr->tuple.dst.protonum = IPPROTO_TCP; -+ hlpr->expect_policy = &rtsp_exp_policy; -+ hlpr->me = THIS_MODULE; -+ hlpr->help = help; -+ -+ tmpname = &rtsp_names[i][0]; -+ if (ports[i] == RTSP_PORT) { -+ sprintf(tmpname, "rtsp"); -+ } else { -+ sprintf(tmpname, "rtsp-%d", i); -+ } -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) -+ strlcpy(hlpr->name, tmpname, sizeof(hlpr->name)); -+#else -+ hlpr->name = tmpname; -+#endif -+ pr_debug("port #%d: %d\n", i, ports[i]); -+ -+ ret = nf_conntrack_helper_register(hlpr); -+ -+ if (ret) { -+ printk("nf_conntrack_rtsp: ERROR registering port %d\n", ports[i]); -+ fini(); -+ return -EBUSY; -+ } -+ } -+ return 0; -+} -+ -+module_init(init); -+module_exit(fini); ---- /dev/null -+++ b/extensions/rtsp/nf_conntrack_rtsp.h -@@ -0,0 +1,74 @@ -+/* -+ * RTSP extension for IP connection tracking. -+ * (C) 2003 by Tom Marshall -+ * based on ip_conntrack_irc.h -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd -+ * - conditional compilation for kernel 3.7 -+ * - port mapping improvements -+*/ -+#ifndef _IP_CONNTRACK_RTSP_H -+#define _IP_CONNTRACK_RTSP_H -+ -+#include -+ -+//#define IP_NF_RTSP_DEBUG 1 -+#define IP_NF_RTSP_VERSION "0.7" -+ -+#ifdef __KERNEL__ -+/* port block types */ -+typedef enum { -+ pb_single, /* client_port=x */ -+ pb_range, /* client_port=x-y */ -+ pb_discon /* client_port=x/y (rtspbis) */ -+} portblock_t; -+ -+/* We record seq number and length of rtsp headers here, all in host order. */ -+ -+/* -+ * This structure is per expected connection. It is a member of struct -+ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored -+ * there and we are expected to only store the length of the data which -+ * needs replaced. If a packet contains multiple RTSP messages, we create -+ * one expected connection per message. -+ * -+ * We use these variables to mark the entire header block. This may seem -+ * like overkill, but the nature of RTSP requires it. A header may appear -+ * multiple times in a message. We must treat two Transport headers the -+ * same as one Transport header with two entries. -+ */ -+struct ip_ct_rtsp_expect -+{ -+ u_int32_t len; /* length of header block */ -+ portblock_t pbtype; /* Type of port block that was requested */ -+ u_int16_t loport; /* Port that was requested, low or first */ -+ u_int16_t hiport; /* Port that was requested, high or second */ -+ union nf_inet_addr srvaddr; /* src address in SETUP reply */ -+ union nf_inet_addr cltaddr; /* destination address */ -+#if 0 -+ uint method; /* RTSP method */ -+ uint cseq; /* CSeq from request */ -+#endif -+}; -+ -+extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, -+ enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, -+ unsigned int matchlen, -+ struct ip_ct_rtsp_expect *prtspexp, -+ struct nf_conntrack_expect *rtp_exp, -+ struct nf_conntrack_expect *rtcp_exp); -+ -+#define RTSP_PORT 554 -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _IP_CONNTRACK_RTSP_H */ ---- /dev/null -+++ b/extensions/rtsp/nf_nat_rtsp.c -@@ -0,0 +1,640 @@ -+/* -+ * RTSP extension for TCP NAT alteration -+ * (C) 2003 by Tom Marshall -+ * -+ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd -+ * - fixed rtcp nat mapping and other port mapping fixes -+ * - fixed system hard lock because of bug in the parser -+ * - codestyle fixes and less significant fixes -+ * -+ * based on ip_nat_irc.c -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Module load syntax: -+ * insmod nf_nat_rtsp.o ports=port1,port2,...port -+ * stunaddr=
    -+ * destaction=[auto|strip|none] -+ * -+ * If no ports are specified, the default will be port 554 only. -+ * -+ * stunaddr specifies the address used to detect that a client is using STUN. -+ * If this address is seen in the destination parameter, it is assumed that -+ * the client has already punched a UDP hole in the firewall, so we don't -+ * mangle the client_port. If none is specified, it is autodetected. It -+ * only needs to be set if you have multiple levels of NAT. It should be -+ * set to the external address that the STUN clients detect. Note that in -+ * this case, it will not be possible for clients to use UDP with servers -+ * between the NATs. -+ * -+ * If no destaction is specified, auto is used. -+ * destaction=auto: strip destination parameter if it is not stunaddr. -+ * destaction=strip: always strip destination parameter (not recommended). -+ * destaction=none: do not touch destination parameter (not recommended). -+ */ -+ -+#include -+#include -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+# include -+#else -+# include -+#endif -+#include -+#include "nf_conntrack_rtsp.h" -+ -+#include -+#include -+#define NF_NEED_STRNCASECMP -+#define NF_NEED_STRTOU16 -+#include "netfilter_helpers.h" -+#define NF_NEED_MIME_NEXTLINE -+#include "netfilter_mime.h" -+ -+#define MAX_PORTS 8 -+#define DSTACT_AUTO 0 -+#define DSTACT_STRIP 1 -+#define DSTACT_NONE 2 -+ -+static char* stunaddr = NULL; -+static char* destaction = NULL; -+ -+static u_int32_t extip = 0; -+static int dstact = 0; -+ -+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp); -+ -+MODULE_AUTHOR("Tom Marshall "); -+MODULE_DESCRIPTION("RTSP network address translation module"); -+MODULE_LICENSE("GPL"); -+module_param(stunaddr, charp, 0644); -+MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); -+module_param(destaction, charp, 0644); -+MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); -+ -+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } -+ -+/*** helper functions ***/ -+ -+static void -+get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) -+{ -+ struct iphdr* iph = ip_hdr(skb); -+ struct tcphdr* tcph = (void *)iph + ip_hdrlen(skb); -+ -+ *pptcpdata = (char*)tcph + tcph->doff*4; -+ *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+/* copy of sip_sprintf_addr */ -+static int rtsp_sprintf_addr(const struct nf_conn *ct, char *buffer, -+ const union nf_inet_addr *addr, bool delim) -+{ -+ if (nf_ct_l3num(ct) == NFPROTO_IPV4) { -+ return sprintf(buffer, "%pI4", &addr->ip); -+ } else { -+ if (delim) -+ return sprintf(buffer, "[%pI6c]", &addr->ip6); -+ else -+ return sprintf(buffer, "%pI6c", &addr->ip6); -+ } -+} -+#endif -+ -+/*** nat functions ***/ -+ -+/* -+ * Mangle the "Transport:" header: -+ * - Replace all occurences of "client_port=" -+ * - Handle destination parameter -+ * -+ * In: -+ * ct, ctinfo = conntrack context -+ * skb = packet -+ * tranoff = Transport header offset from TCP data -+ * tranlen = Transport header length (incl. CRLF) -+ * rport_lo = replacement low port (host endian) -+ * rport_hi = replacement high port (host endian) -+ * -+ * Returns packet size difference. -+ * -+ * Assumes that a complete transport header is present, ending with CR or LF -+ */ -+static int -+rtsp_mangle_tran(enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ struct nf_conntrack_expect* rtp_exp, -+ struct nf_conntrack_expect* rtcp_exp, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct sk_buff* skb, uint tranoff, uint tranlen) -+{ -+ char* ptcp; -+ uint tcplen; -+ char* ptran; -+ char rbuf1[16]; /* Replacement buffer (one port) */ -+ uint rbuf1len; /* Replacement len (one port) */ -+ char rbufa[16]; /* Replacement buffer (all ports) */ -+ uint rbufalen; /* Replacement len (all ports) */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ union nf_inet_addr newip; -+#else -+ u_int32_t newip; -+#endif -+ u_int16_t loport, hiport; -+ uint off = 0; -+ uint diff; /* Number of bytes we removed */ -+ -+ struct nf_conn *ct = rtp_exp->master; -+ /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */ -+ struct nf_conntrack_tuple *rtp_t; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ char szextaddr[INET6_ADDRSTRLEN + 16]; -+#else -+ char szextaddr[INET_ADDRSTRLEN + 16]; -+#endif -+ uint extaddrlen; -+ int is_stun; -+ -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ -+ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || -+ tranlen < 10 || !iseol(ptran[tranlen-1]) || -+ nf_strncasecmp(ptran, "Transport:", 10) != 0) { -+ pr_info("sanity check failed\n"); -+ return 0; -+ } -+ off += 10; -+ SKIP_WSPACE(ptcp+tranoff, tranlen, off); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3; -+ rtp_t = &rtp_exp->tuple; -+ rtp_t->dst.u3 = newip; -+ if (rtcp_exp) { -+ rtcp_exp->tuple.dst.u3 = newip; -+ } -+ extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip -+ pr_debug("stunaddr=%s (auto)\n", szextaddr); -+#else -+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; -+ rtp_t = &rtp_exp->tuple; -+ rtp_t->dst.u3.ip = newip; -+ if (rtcp_exp) { -+ rtcp_exp->tuple.dst.u3.ip = newip; -+ } -+ extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) -+ : sprintf(szextaddr, "%pI4", &newip); -+ pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); -+#endif -+ hiport = 0; -+ rbuf1len = rbufalen = 0; -+ switch (prtspexp->pbtype) { -+ case pb_single: -+ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ -+ rtp_t->dst.u.udp.port = htons(loport); -+ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { -+ pr_debug("using port %hu\n", loport); -+ break; -+ } -+ } -+ if (loport != 0) { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, "%hu", loport); -+ } -+ break; -+ case pb_range: -+ for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */ -+ rtp_t->dst.u.udp.port = htons(loport); -+ if (rtsp_nf_ct_expect_related(rtp_exp) != 0) { -+ continue; -+ } -+ hiport = loport + 1; -+ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); -+ if (rtsp_nf_ct_expect_related(rtcp_exp) != 0) { -+ nf_ct_unexpect_related(rtp_exp); -+ continue; -+ } -+ -+ /* FIXME: invalid print in case of ipv6 */ -+ pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n", -+ &rtp_exp->tuple.src.u3.ip, -+ ntohs(rtp_exp->tuple.src.u.udp.port), -+ ntohs(rtcp_exp->tuple.src.u.udp.port), -+ &rtp_exp->tuple.dst.u3.ip, -+ ntohs(rtp_exp->tuple.dst.u.udp.port), -+ ntohs(rtcp_exp->tuple.dst.u.udp.port)); -+ break; -+ } -+ if (loport != 0) { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); -+ } -+ break; -+ case pb_discon: -+ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ -+ rtp_t->dst.u.udp.port = htons(loport); -+ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { -+ pr_debug("using port %hu (1 of 2)\n", loport); -+ break; -+ } -+ } -+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */ -+ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); -+ if (rtsp_nf_ct_expect_related(rtcp_exp) == 0) { -+ pr_debug("using port %hu (2 of 2)\n", hiport); -+ break; -+ } -+ } -+ if (loport != 0 && hiport != 0) { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, hiport == loport+1 ? -+ "%hu-%hu":"%hu/%hu", loport, hiport); -+ } else { -+ if (loport != 0) -+ nf_ct_unexpect_related(rtp_exp); -+ if (hiport != 0) -+ nf_ct_unexpect_related(rtcp_exp); -+ } -+ break; -+ } -+ -+ if (rbuf1len == 0) -+ return 0; /* cannot get replacement port(s) */ -+ -+ /* Transport: tran;field;field=val,tran;field;field=val,... -+ `off` is set to the start of Transport value from start of line -+ */ -+ while (off < tranlen) { -+ uint saveoff; -+ const char* pparamend; -+ uint nextparamoff; -+ -+ pparamend = memchr(ptran+off, ',', tranlen-off); -+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; -+ nextparamoff = pparamend-ptran; -+ -+ /* -+ * We pass over each param twice. On the first pass, we look for a -+ * destination= field. It is handled by the security policy. If it -+ * is present, allowed, and equal to our external address, we assume -+ * that STUN is being used and we leave the client_port= field alone. -+ */ -+ is_stun = 0; -+ saveoff = off; -+ while (off < nextparamoff) { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ SKIP_WSPACE(ptran, nextfieldoff, off); -+ -+ if (dstact != DSTACT_NONE && nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { -+ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) -+ is_stun = 1; -+ -+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { -+ uint dstoff = (ptran-ptcp)+off; -+ uint dstlen = nextfieldoff-off; -+ char* pdstrep = NULL; -+ uint dstreplen = 0; -+ diff = dstlen; -+ if (dstact == DSTACT_AUTO && !is_stun) { -+ const char* psep = memchr(ptran+off, ':', dstlen); -+ u_int16_t port; -+ -+ dstoff += 12; -+ dstlen -= 13; -+ pdstrep = szextaddr; -+ -+ if (psep != NULL && nf_strtou16(psep + 1, &port)) { -+ pr_debug("RTSP: replace dst addr&port\n"); -+ -+ if (port != prtspexp->loport) { -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ dstreplen = extaddrlen; -+ } else { -+ sprintf(szextaddr+extaddrlen, ":%s", rbuf1); -+ dstreplen = extaddrlen+1+rbuf1len; -+ } -+ } else { -+ pr_debug("RTSP: replace dst addr\n"); -+ dstreplen = extaddrlen; -+ } -+ diff = nextfieldoff-off-13-dstreplen; -+ } -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, -+ dstoff, dstlen, pdstrep, dstreplen)) { -+#else -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, -+ dstoff, dstlen, pdstrep, dstreplen)) { -+#endif -+ /* mangle failed, all we can do is bail */ -+ nf_ct_unexpect_related(rtp_exp); -+ if (rtcp_exp) -+ nf_ct_unexpect_related(rtcp_exp); -+ return 0; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ tranlen -= diff; -+ nextparamoff -= diff; -+ nextfieldoff -= diff; -+ } -+ } -+ -+ off = nextfieldoff; -+ } -+ -+ if (is_stun) -+ continue; -+ -+ off = saveoff; -+ while (off < nextparamoff) { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ -+ if (nextfieldoff - off > 12 && strncmp(ptran+off, "client_port=", 12) == 0) { -+ u_int16_t port; -+ uint numlen; -+ uint origoff; -+ uint origlen; -+ char* rbuf = rbuf1; -+ uint rbuflen = rbuf1len; -+ -+ off += 12; -+ origoff = (ptran-ptcp)+off; -+ origlen = 0; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ origlen += numlen; -+ if (port != prtspexp->loport) { -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ } else { -+ if (ptran[off] == '-' || ptran[off] == '/') { -+ off++; -+ origlen++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ origlen += numlen; -+ rbuf = rbufa; -+ rbuflen = rbufalen; -+ } -+ -+ /* -+ * note we cannot just memcpy() if the sizes are the same. -+ * the mangle function does skb resizing, checks for a -+ * cloned skb, and updates the checksums. -+ * -+ * parameter 4 below is offset from start of tcp data. -+ */ -+ diff = origlen-rbuflen; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, -+ origoff, origlen, rbuf, rbuflen)) { -+#else -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, -+ origoff, origlen, rbuf, rbuflen)) { -+#endif -+ /* mangle failed, all we can do is bail */ -+ nf_ct_unexpect_related(rtp_exp); -+ if (rtcp_exp) -+ nf_ct_unexpect_related(rtcp_exp); -+ return 0; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ tranlen -= diff; -+ nextparamoff -= diff; -+ nextfieldoff -= diff; -+ } -+ } -+ -+ off = nextfieldoff; -+ } -+ -+ off = nextparamoff; -+ } -+ -+ return 1; -+} -+ -+static uint -+help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, unsigned int matchlen, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect* rtp_exp, -+ struct nf_conntrack_expect* rtcp_exp) -+{ -+ char* ptcp; -+ uint tcplen; -+ uint hdrsoff; -+ uint hdrslen; -+ uint lineoff; -+ uint linelen; -+ uint off; -+ int dir = CTINFO2DIR(ctinfo); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3; -+#else -+ __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip; -+#endif -+ -+ //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; -+ //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); -+ -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); -+ hdrslen = matchlen; -+ off = hdrsoff; -+ pr_debug("NAT rtsp help_out\n"); -+ -+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) { -+ if (linelen == 0) -+ break; -+ -+ if (off > hdrsoff+hdrslen) { -+ pr_info("!! overrun !!"); -+ break; -+ } -+ pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { -+ uint oldtcplen = tcplen; -+ pr_debug("hdr: Transport\n"); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp, -+ prtspexp, skb, lineoff, linelen)) { -+#else -+ if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp, -+ skb, lineoff, linelen)) { -+#endif -+ pr_debug("hdr: Transport mangle failed"); -+ break; -+ } -+ rtp_exp->expectfn = nf_nat_rtsp_expected; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ rtp_exp->saved_addr = saddr; -+#else -+ rtp_exp->saved_ip = saddr; -+#endif -+ rtp_exp->saved_proto.udp.port = htons(prtspexp->loport); -+ rtp_exp->dir = !dir; -+ if (rtcp_exp) { -+ rtcp_exp->expectfn = nf_nat_rtsp_expected; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ rtcp_exp->saved_addr = saddr; -+#else -+ rtcp_exp->saved_ip = saddr; -+#endif -+ rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport); -+ rtcp_exp->dir = !dir; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ hdrslen -= (oldtcplen-tcplen); -+ off -= (oldtcplen-tcplen); -+ lineoff -= (oldtcplen-tcplen); -+ linelen -= (oldtcplen-tcplen); -+ pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); -+ } -+ } -+ -+ return NF_ACCEPT; -+} -+ -+static unsigned int -+nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, unsigned int matchlen, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect* rtp_exp, -+ struct nf_conntrack_expect* rtcp_exp) -+{ -+ int dir = CTINFO2DIR(ctinfo); -+ int rc = NF_ACCEPT; -+ -+ switch (dir) { -+ case IP_CT_DIR_ORIGINAL: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, -+ rtp_exp, rtcp_exp); -+#else -+ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, -+ rtp_exp, rtcp_exp); -+#endif -+ break; -+ case IP_CT_DIR_REPLY: -+ pr_debug("unmangle ! %u\n", ctinfo); -+ /* XXX: unmangle */ -+ rc = NF_ACCEPT; -+ break; -+ } -+ //UNLOCK_BH(&ip_rtsp_lock); -+ -+ return rc; -+} -+ -+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) -+{ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0) -+ struct nf_nat_range2 range; -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ struct nf_nat_range range; -+#else -+ struct nf_nat_ipv4_range range; -+#endif -+ -+ /* This must be a fresh one. */ -+ BUG_ON(ct->status & IPS_NAT_DONE_MASK); -+ -+ /* For DST manip, map port here to where it's expected. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ range.min_proto = range.max_proto = exp->saved_proto; -+ range.min_addr = range.max_addr = exp->saved_addr; -+#else -+ range.min = range.max = exp->saved_proto; -+ range.min_ip = range.max_ip = exp->saved_ip; -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) -+ range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); -+ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); -+#else -+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); -+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); -+#endif -+ -+ /* Change src to where master sends to, but only if the connection -+ * actually came from the same source. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, -+ &ct->master->tuplehash[exp->dir].tuple.src.u3)) { -+ range.min_addr = range.max_addr -+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3; -+#else -+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == -+ ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { -+ range.min_ip = range.max_ip -+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) -+ range.flags = NF_NAT_RANGE_MAP_IPS; -+ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); -+#else -+ range.flags = IP_NAT_RANGE_MAP_IPS; -+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); -+#endif -+ } -+} -+ -+ -+static void __exit fini(void) -+{ -+ rcu_assign_pointer(nf_nat_rtsp_hook, NULL); -+ synchronize_net(); -+} -+ -+static int __init init(void) -+{ -+ printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); -+ -+ BUG_ON(nf_nat_rtsp_hook); -+ rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp); -+ -+ if (stunaddr != NULL) -+ extip = in_aton(stunaddr); -+ -+ if (destaction != NULL) { -+ if (strcmp(destaction, "auto") == 0) -+ dstact = DSTACT_AUTO; -+ -+ if (strcmp(destaction, "strip") == 0) -+ dstact = DSTACT_STRIP; -+ -+ if (strcmp(destaction, "none") == 0) -+ dstact = DSTACT_NONE; -+ } -+ -+ return 0; -+} -+ -+module_init(init); -+module_exit(fini); ---- a/extensions/Kbuild -+++ b/extensions/Kbuild -@@ -27,6 +27,7 @@ obj-${build_lscan} += xt_lscan.o - obj-${build_pknock} += pknock/ - obj-${build_psd} += xt_psd.o - obj-${build_quota2} += xt_quota2.o -+obj-${build_rtsp} += rtsp/ - - -include ${M}/*.Kbuild - -include ${M}/Kbuild.* ---- a/mconfig -+++ b/mconfig -@@ -23,3 +23,4 @@ build_lscan=m - build_pknock=m - build_psd=m - build_quota2=m -+build_rtsp=m diff --git a/xtables-addons/patches/200-add-lua-packetscript.patch b/xtables-addons/patches/200-add-lua-packetscript.patch deleted file mode 100644 index 8dd926712..000000000 --- a/xtables-addons/patches/200-add-lua-packetscript.patch +++ /dev/null @@ -1,18158 +0,0 @@ ---- /dev/null -+++ b/extensions/LUA/byte_array.c -@@ -0,0 +1,145 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+#include "controller.h" -+ -+/* Initialization helper function. This function should be used whenever -+ * a new byte array need to be initialized. Depending on the arguments it -+ * initializes the array in a different way. Have a look at the inline -+ * comments */ -+lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy) -+{ -+ lua_packet_segment *array; -+ -+ if (length < 0) -+ luaL_error(L, "init_byte_array, requested size < 0"); -+ -+ if (start && do_copy) { -+ /* we have a start address where we copy from */ -+ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); -+ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ -+ memcpy(array->start, start, length); -+ }else if (start && !do_copy) { -+ /* just link the start pointer, in this case you have to free the memory yourself */ -+ array = lua_newuserdata(L, sizeof(lua_packet_segment)); -+ array->start = start; -+ }else{ -+ /* create an empty array, fully managed by Lua */ -+ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); -+ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ -+ memset(array->start, 0, length); -+ } -+ -+ array->length = length; -+ array->offset = 0; -+ array->changes = NULL; -+ -+ luaL_getmetatable(L, LUA_BYTE_ARRAY); -+ lua_setmetatable(L, -2); -+ -+ return array; -+} -+ -+ -+ -+/* LUA_API: get one byte of the given byte array -+ * access-pattern: array[] */ -+static int32_t get_byte_array(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ -+ -+ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); -+ lua_pushinteger(L, (array->start + array->offset)[index]); -+ -+ return 1; -+} -+ -+/* LUA_API: set one byte of the given byte array -+ * access-pattern: array[]= 0xFF */ -+static int32_t set_byte_array(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ uint8_t byte; -+ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ -+ int32_t val = luaL_checkinteger(L, 3); -+ uint32_t nob = 1 << CHAR_BIT; /* we should use something like 1 << CHAR_BIT */ -+ -+ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); -+ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); -+ -+ byte = (uint8_t)val; -+ -+ (array->start + array->offset)[index] = byte; -+ -+ return 0; -+} -+ -+/* LUA_API: get size of the given byte array -+ * access-pattern: #array (__length meta-method) */ -+static int32_t get_byte_array_size(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ -+ lua_pushnumber(L, array->length); -+ -+ return 1; -+} -+ -+ -+/* LUA_API: converts a given byte array to a string. -+ * access-pattern: implicit through functions calling the -+ * __to_string() metamethod , e.g. print32_t */ -+static int32_t byte_array_to_string(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ uint8_t buf[(array->length * 3) + 255]; -+ uint8_t hexval[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; -+ char res[255 + (array->length * 3)]; /* make sure the buffer is big enough*/ -+ int32_t i, n; -+ uint8_t *ptr = array->start + array->offset; -+ -+ for (i = 0; i < array->length; i++) { -+ buf[i * 3] = hexval[(ptr[i] >> 4) & 0xF]; -+ buf[(i * 3) + 1] = hexval[ptr[i] & 0x0F]; -+ buf[(i * 3) + 2] = ' '; /* seperator */ -+ } -+ -+ buf[array->length * 3] = '\0'; -+ n = sprintf(res, "byte_array: length: %d value: %s", array->length, buf); -+ -+ lua_pushlstring(L, res, n); -+ -+ return 1; -+} -+ -+static const struct luaL_Reg bytearray_lib_m [] = { -+ { "__len", get_byte_array_size }, -+ { "__newindex", set_byte_array }, -+ { "__index", get_byte_array }, -+ { "__tostring", byte_array_to_string }, -+ { NULL, NULL } -+}; -+ -+void luaopen_bytearraylib(lua_State *L) -+{ -+ luaL_newmetatable(L, LUA_BYTE_ARRAY); -+ luaL_register(L, NULL, bytearray_lib_m); -+ lua_pop(L, 1); -+} -+ -+ ---- /dev/null -+++ b/extensions/LUA/controller.c -@@ -0,0 +1,604 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+#endif -+#include "controller.h" -+ -+/* the array 'supported_protocols' holds all pointers to the -+ * static and dynamic protocol buffers. It is filled by the -+ * call to register_protbuf */ -+static struct protocol_buf * supported_protocols[MAX_NR_OF_PROTOCOLS]; -+ -+/* C_API: the function 'get_protocol_buf' returns the pointer -+ * to the protocol buffer of a given protocol id. */ -+struct protocol_buf * get_protocol_buf(uint32_t protocol_id) -+{ -+ return (struct protocol_buf *)supported_protocols[protocol_id]; -+} -+ -+ -+/* LUA_INT: the function 'gc_packet_segment' is triggered by the -+ * garbage collector whenever a userdata annotated with one of -+ * the protocol buffer metatable should be collected. */ -+static int32_t gc_packet_segment(lua_State *L) -+{ -+ lua_packet_segment * seg = (lua_packet_segment *)lua_touserdata(L, 1); -+ if (seg && seg->changes) { -+ seg->changes->ref_count--; -+ if (seg->changes->ref_count <= 0) { -+ kfree(seg->changes->field_length_changes); -+ kfree(seg->changes->field_offset_changes); -+ kfree(seg->changes); -+ seg->changes = NULL; -+ } -+ } -+ return 0; -+} -+ -+ -+/* LUA_API: the function 'set_raw' is used to set the bytes of a segment -+ * in 'raw' mode. The function is per default available in each protocol -+ * buffer until it gets overridden by a specific setter function inside -+ * a protocol buffer. -+ * -+ * Parameters: -+ * 1. lua_packet_segment (implicit) -+ * 2. int32_t byte_value -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: void -+ */ -+static int32_t set_raw(lua_State *L) -+{ -+ int32_t i; -+ uint32_t nob; -+ uint8_t byte; -+ uint8_t *ptr; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ int32_t val = luaL_checkinteger(L, 2); -+ -+ nob = 1 << CHAR_BIT; -+ -+ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); -+ -+ byte = (uint8_t)val; -+ ptr = seg->start + seg->offset; -+ -+ for (i = 0; i < seg->length; i++) -+ ptr[i] = byte; -+ -+ return 0; -+} -+ -+/* LUA_API: the function 'get_raw' is used to get the bytes of a segment -+ * in 'raw' mode. The function is per default available in each protocol -+ * buffer until it gets overridden by a specific getter function inside -+ * a protocol buffer. -+ * -+ * Parameters: -+ * 1. lua_packet_segment (implicit) -+ * 2. uint32_t offset -+ * 3. uint32_t length -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * the byte array representing the given array -+ */ -+static int32_t get_raw(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ init_byte_array(L, seg->start + seg->offset, seg->length, 1); -+ -+ return 1; -+} -+/* LUA_API: The function 'get_segment' is used to get a new segment in 'raw' mode. -+ * Typically this function is applied on another raw segment in order -+ * to extract a part of the segment as new segment. -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * 2. uint32_t offset, this indicates where to start the new segment, see e.g below. -+ * 3. uint32_t length, this indicates the size of the new segment -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * 1. A lua_packet_segment annotated with the according metatable or False in -+ * case the input data is not valid -+ * -+ * Example: -+ * -+ * +------------------------+---------------------------------------+ -+ * | function call | resulting lua_packet_segment | -+ * +========================+===+===+===+===+===+===+===+===+===+===+ -+ * | seg = packet:raw(0,10) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -+ * +------------------------+---+---+---+---+---+---+---+---+---+---+ -+ * | 1st_half = seg:raw(0,5)| 0 | 1 | 2 | 3 | 4 | | -+ * +------------------------+---+---+---+---+---+---+---+---+---+---+ -+ * | 2nd_half = seg:raw(5,5)| | 5 | 6 | 7 | 8 | 9 | -+ * +------------------------+-------------------+---+---+---+---+---+ -+ */ -+static int32_t get_segment(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ uint32_t offset = luaL_checkinteger(L, 2); -+ uint32_t length = luaL_checkinteger(L, 3); -+ lua_packet_segment * new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ -+ new->start = seg->start; -+ new->offset = seg->offset + offset; -+ new->changes = NULL; -+ /* we allow a seg->length == 0 , this enables processing packets where the packetsize is not fixed (0 = not fixed)*/ -+ if (seg->length != 0 && length > seg->length) { -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ -+ new->length = length; -+ luaL_getmetatable(L, prot_buf->name); -+ lua_setmetatable(L, -2); -+ -+ return 1; -+} -+ -+/* LUA_API: the function 'get_segment_size' is used to get the size of a segment. -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * 1. Size as lua_Number -+ */ -+static int32_t get_segment_size(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushnumber(L, seg->length); -+ return 1; -+} -+ -+/* LUA_API: the function 'get_segment_offset' is used to get the real offset -+ * of a segment. This function returns the offset of the segment to the start -+ * of the buffer. This means the following -+ * seg1 = packet:raw(2,10) -+ * seg2 = seg1:raw(3,5) -+ * offset = seg2:get_offset() -+ * -+ * will give an offset of 5, since the seg1 starts at offset 2, and seg2 starts -+ * at offset (seg1:get_offset() + 3). -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * 1. Offset as lua_Number -+ */ -+static int32_t get_segment_offset(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushnumber(L, seg->offset); -+ return 1; -+} -+ -+/* LUA_API: overwrites the __tostring function of a lua_packet_segment. -+ * this will print32_t a nicely formated string, including length, -+ * offset and name of the protocol buffer. -+ * -+ * Parameters: -+ * 1. lua_packet_segment (implicit) -+ * -+ * Returns: -+ * 1. the representing string -+ */ -+static int32_t packet_segment_tostring(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ int32_t n; -+ char buf[128]; -+ -+ n = sprintf(buf, "type: %s, offset: %d, length: %d", prot_buf->name, seg->offset, seg->length); -+ lua_pushlstring(L, buf, n); -+ -+ return 1; -+} -+ -+ -+static const struct luaL_Reg seg_access_functions [] = { -+ { "set", set_raw }, -+ { "get", get_raw }, -+ { "raw", get_segment }, -+ { "get_offset", get_segment_offset }, -+ { "get_size", get_segment_size }, -+ { "to_bytes", get_raw }, -+ { "__tostring", packet_segment_tostring }, -+ { "__gc", gc_packet_segment }, -+ { NULL, NULL } -+}; -+ -+/* C_API: the function 'get_metatable_from_protocol_type' is a helper -+ * used in controller.c as well as it may find usage in the static -+ * protocol buffers and byte array implementation. */ -+void get_metatable_from_protocol_type(lua_State *L, int32_t type) -+{ -+ char * table; -+ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); -+ lua_rawgeti(L, -1, type); -+ table = (char *)luaL_checkstring(L, -1); -+ lua_pop(L, 2); /* pop the table SUPPORTED_PROTOCOL_TABLE and the string pushed by lua_gettable */ -+ luaL_getmetatable(L, table); -+ return; -+} -+ -+/* C_INT: the function 'payload_contains_protocol' is used internally. -+ * Depending if static or dynamic protocol buffer it calls the right -+ * validation function. */ -+static int32_t payload_contains_protocol(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment *seg, uint32_t prot_type) -+{ -+ if (prot_buf->is_dynamic) -+ return has_protocol_dynamic(L, prot_buf, seg, prot_type); -+ else -+ return prot_buf->has_protocol(L, prot_buf, seg, prot_type); -+} -+ -+/* C_INT: the function 'protocol_get_field_changes' is used interally. -+ * It requests the field_changes struct calling the protocol buffers -+ * 'get_field_changes' function. This funciton is called, whenever -+ * the payload field with a given protocol type is requested inside -+ * the function 'get_protocol_field' */ -+static struct field_changes * protocol_get_field_changes(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) -+{ -+ struct field_changes * changes = NULL; -+ -+ if (prot_buf->get_field_changes) { -+ if (prot_buf->is_dynamic) -+ changes = get_field_changes_dynamic(L, prot_buf, seg); -+ else -+ changes = prot_buf->get_field_changes(L, seg); -+ /* is already 1 when set by helper 'get_allocated_field_changes, -+ * since not every prot_buf may use this function we enforce it. */ -+ changes->ref_count = 1; -+ } -+ return changes; -+} -+ -+/* C_INT: the function 'get_field_offset_in_bytes' wrapps the logic of -+ * calculating the new length with considering the optional field_changes. */ -+static int32_t get_field_offset_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) -+{ -+ uint32_t nr_of_bits, nr_of_bytes, field_offset; -+ -+ field_offset = field->offset; -+ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ -+ if (seg->changes) -+ field_offset += seg->changes->field_offset_changes[field_index]; -+ /* how many bits remain */ -+ nr_of_bits = field_offset & (CHAR_BIT - 1); -+ /* assuming CHAR_BIT == 2 ^ 3 */ -+ nr_of_bytes = (field_offset - nr_of_bits) >> 3; -+ -+ return seg->offset + nr_of_bytes; -+} -+ -+/* C_INT: the function 'get_field_length_in_bytes' wrapps the logic of -+ * calculating the new offset with considering the optional field_changes. */ -+static int32_t get_field_length_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) -+{ -+ uint32_t nr_of_bits, nr_of_bytes, field_length; -+ -+ field_length = field->length; -+ /* if the field length is smaller than 1 byte, we take the size of one byte -+ * we treat the case where field_length == 0 in a special way ...*/ -+ if (field_length < CHAR_BIT && field_length > 0) -+ field_length = CHAR_BIT; -+ -+ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ -+ if (seg->changes) -+ field_length += seg->changes->field_length_changes[field_index]; -+ /* how many bits remain */ -+ nr_of_bits = field_length & (CHAR_BIT - 1); -+ /* assuming CHAR_BIT == 2 ^ 3 */ -+ nr_of_bytes = (field_length - nr_of_bits) >> 3; -+ return nr_of_bytes; -+} -+ -+/* C_INT: the function 'initialize_field_getter_and_setter' initializes -+ * the setter and getter function of the field, considering the optional -+ * field manipulator functions defined inside the protocol buffers. */ -+static void initialize_field_getter_and_setter(lua_State *L, struct protocol_buf *prot_buf, int32_t field_index) -+{ -+ /* lets check if there is a metatable on top of the stack */ -+ struct protocol_field * f = (struct protocol_field *)&prot_buf->protocol_fields[field_index]; -+ -+ if (!lua_istable(L, -1)) luaL_error(L, "cannot initialize getter and setter for field %s->%s, " -+ "not a table on top of the stack, is '%s'", prot_buf->name, f->name, lua_typename(L, lua_type(L, -1))); -+ -+ /* is there a 'getter' to initialize ? */ -+ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ -+ lua_pushinteger(L, field_index); /* push upvalue 2 */ -+ if (f->get) { -+ if (prot_buf->is_dynamic) -+ lua_pushcclosure(L, field_dynamic_getter, 2); -+ else -+ lua_pushcclosure(L, f->get, 2); -+ }else -+ /* there is no specific getter defined - fall back to 'get_raw' */ -+ lua_pushcclosure(L, get_raw, 2); -+ /* set the metatable field 'get' */ -+ lua_setfield(L, -2, "get"); -+ -+ /* is there a 'setter' to initialize ? */ -+ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ -+ lua_pushinteger(L, field_index); /* push upvalue 2 */ -+ if (f->set) { -+ if (prot_buf->is_dynamic) -+ lua_pushcclosure(L, field_dynamic_setter, 2); -+ else -+ lua_pushcclosure(L, f->set, 2); -+ }else -+ /* there is no specific setter defined - fall back to 'set_raw' */ -+ lua_pushcclosure(L, set_raw, 2); -+ /* set the metatable field 'set' */ -+ lua_setfield(L, -2, "set"); -+} -+ -+/* LUA_API: 'get_protocol_field' is used in Lua as a closure for each field of a protocol -+ * buffer. E.g a call to ip = packet:data(packet_ip) will go to this function, -+ * and trigger the conversion of the raw packet to a ip packet. Each call -+ * to a field function of an IP packet, like ip:daddr() uses this function -+ * to to return the right data. In each case you will end up either with a -+ * new packet segment (annotated with the proper metatable) or a boolean -+ * value (False) if something went wrong. In the case everything went fine, -+ * the newly created lua_packet_segment is annotated with the proper -+ * metatable where the fields get and set also contain the specific getter -+ * and setter functions given by the protocol buffer. E.g. the function call -+ * ip:daddr():get() or ip:daddr():set(...) will call the proper function -+ * defined inside the corresponding field definition. -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * 2. type of the protocol buffer, optional, and only used if the accessed -+ * field is the payload field. If a type is provided for the access of the -+ * payload field, the function tries to convert the data pointed to by the -+ * payload field to the given type. To check if such a conversion is -+ * possible, it calls the function pointed to by the protocol buffer member -+ * has_protocol. If this function returns True, the conversion takes place. -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index -+ * -+ * Return: -+ * 1. A lua_packet_segment annotated with the according metatable or False in -+ * case the input data is not valid -+ */ -+static int32_t get_protocol_field(lua_State *L) -+{ -+ int32_t prot_type; -+ lua_packet_segment * seg, *new; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); -+ struct protocol_field * field = &prot_buf->protocol_fields[field_index]; -+ -+ /* get the current packet segment */ -+ seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ /* initialize the new packet segment */ -+ new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ new->start = seg->start; /* the start is unchanged */ -+ new->offset = get_field_offset_in_bytes(field, seg, field_index); -+ new->length = get_field_length_in_bytes(field, seg, field_index); -+ -+ /* if new->length == 0 then no configuration was done, we guess the size by subtracting the -+ * new offset from the packet length. since the old length is getting initialized by the -+ * netfilter extension this assumption holds for the very last field of the protocol. -+ * this 'feature' should be used by protocol buffers containing a payload, whereas the -+ * payload field is the last field of the buffer. However, at compile-time unknown field -+ * sizes (and offsets) of fields not being placed at the end of the protocol should be -+ * initialized using the 'get_field_changes' hook system. */ -+ if (new->length == 0) -+ new->length = (seg->length + seg->offset) - (new->offset); -+ /* -+ printf("%s->%s:: seg->offset %i, seg->length %i, new->offset %i, new->length %i\n", -+ prot_buf->name, field->name, seg->offset, seg->length, new->offset, new->length); -+ */ -+ /* special care for packet payload requests */ -+ if (prot_buf->payload_field != NULL && strcmp(prot_buf->payload_field, field->name) == 0) { -+ /* we know the payload field is requested */ -+ /* the requested payload can be delivered either as a common segment or as -+ * an other packet type, such a conversion needs an extra protocol parameter -+ * ... so lets check */ -+ -+ if (lua_isnumber(L, 2)) { -+ /* we have an extra parameter, ... lets see if it is a valid protocol -+ * the parameter is the index of the 'supported_protocols'-array member */ -+ prot_type = lua_tointeger(L, 2); -+ if (prot_type >= 0 && prot_type < PACKET_SENTINEL) { -+ /* we are sure the purpose of the request is to get the payload data, -+ * converted to the given protocol. lets check if the payload contains -+ * data of the given protocol */ -+ if (payload_contains_protocol(L, prot_buf, seg, prot_type)) { -+ /* success, we can push the metatable for the given protocol */ -+ get_metatable_from_protocol_type(L, prot_type); -+ if (!lua_isnil(L, -1)) /* check if the metatable was found */ -+ /* perhaps the field offsets and lengths of the containing protocol -+ * are not set correctly. request the optional 'field_changes' structure -+ * holding the changes for lengths and offsets. */ -+ new->changes = protocol_get_field_changes(L, get_protocol_buf(prot_type), new); -+ else{ -+ /* failed, the requested protocol is not available -+ * we push false and return */ -+ lua_pop(L, 1); /* pop the userdata */ -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ }else{ -+ /* payload does not carry the provided protocol */ -+ /* we push false and return */ -+ lua_pop(L, 1); /* pop the userdata */ -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ }else{ -+ /* unknown protocol */ -+ lua_pop(L, 1); /* pop the userdata */ -+ luaL_error(L, "provided protocol is unknown"); -+ } -+ } -+ } -+ -+ /* if there is still the 'new' userdata on the top, we push our own metatable */ -+ if (lua_isuserdata(L, -1)) { -+ luaL_getmetatable(L, prot_buf->name); -+ new->changes = seg->changes; -+ if (seg->changes) -+ new->changes->ref_count++; -+ } -+ -+ /* a new packet segment is at index -2 , and the proper metatable at index -1 of the stack -+ * lets set the propper setter and getter function for the requested field */ -+ initialize_field_getter_and_setter(L, prot_buf, field_index); -+ -+ lua_setmetatable(L, -2); -+ return 1; -+} -+ -+/* C_API: 'register_protbuf' is only used internally. This function takes a -+ * pointer to a fully initialized protocol buffer struct and registers it -+ * inside the Lua state. Registering means: -+ * -+ * 1. it creates a new metatable with the name of the protocol buffer. -+ * 2. it registers the default functions which are stored in the luaL_Reg -+ * array seg_access_functions. -+ * 3. it loops over the protocol fields stored at prot_buf->protocol_fields -+ * and registers a new function (using the field name) inside the -+ * metatable. Each field points to the function 'get_protocol_field' -+ * which acts as a closure taking a pointer to the protocol buffer as -+ * well as the index of the field as upvalues. -+ * 4. The protocol index, serves as numerical identifier of this protocol -+ * buffer or even of the protocol itself. This index is stored as a -+ * global value inside the Lua state as well as inside the Lua table -+ * 'supported_protocols'. Assuming the name of a procotol buffer is -+ * "packet_ip" the following statements are true: -+ * -+ * supported_protocols[protocol_index] == "packet_ip" -+ * packet_ip == protocol_index -+ * -+ * This allows you to get all registered protocols from within Lua. This -+ * is especially usefull for the dynamic protocol buffers where you have -+ * to provide your own "has_protocol"-function, which probably needs the -+ * information on which protocols it is able to contain. -+ */ -+void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, uint32_t protocol_index) -+{ -+ int32_t field_index; -+ luaL_Reg *reg = (struct luaL_Reg *)seg_access_functions; -+ struct protocol_field * field = prot_buf->protocol_fields; -+ -+ luaL_newmetatable(L, prot_buf->name); -+ -+ /* metatable.__index = metatable */ -+ lua_pushvalue(L, -1); /* duplicates the metatable */ -+ lua_setfield(L, -2, "__index"); -+ -+ /* pushing default functions */ -+ for (; reg->name; reg++) { -+ lua_pushlightuserdata(L, (void *)prot_buf); -+ lua_pushcclosure(L, reg->func, 1); -+ lua_setfield(L, -2, reg->name); -+ } -+ -+ /* pushing functions specific to the protocol buffer */ -+ for (field_index = 0; field->name; field++, field_index++) { -+ lua_pushlightuserdata(L, (void *)prot_buf); /* upvalue: prot_buf */ -+ lua_pushinteger(L, field_index); /* upvalue: index of protocol field */ -+ lua_pushcclosure(L, get_protocol_field, 2); -+ lua_setfield(L, -2, field->name); -+ } -+ /* pop the metatable */ -+ lua_pop(L, 1); -+ -+ /* registering the array-index as the protocol_id*/ -+ lua_getglobal(L, "_G"); -+ lua_pushinteger(L, protocol_index); -+ lua_setfield(L, -2, prot_buf->name); -+ lua_pop(L, 1); /* pop _G */ -+ -+ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); -+ lua_pushstring(L, prot_buf->name); -+ lua_rawseti(L, -2, protocol_index); -+ -+ lua_pop(L, 1); /* pop SUPPORTED_PROTOCOL_TABLE */ -+ -+ supported_protocols[protocol_index] = prot_buf; -+} -+ -+void luaopen_controller(lua_State *L) -+{ -+ /* registering a table inside the _G with table[protocol_index] = prot_buf->name */ -+ lua_getglobal(L, "_G"); -+ lua_newtable(L); -+ lua_setfield(L, -2, SUPPORTED_PROTOCOL_TABLE); -+ lua_pop(L, 1); /* pop _G */ -+ -+ luaopen_protbuf_raw(L); -+ luaopen_protbuf_eth(L); -+ luaopen_protbuf_ip(L); -+ luaopen_protbuf_icmp(L); -+ luaopen_protbuf_tcp(L); -+ luaopen_protbuf_tcp_options(L); -+ luaopen_protbuf_udp(L); -+ luaopen_protbuf_tftp(L); -+ luaopen_protbuf_dynamic(L); -+ /* should follow all other static buffers */ -+#if defined(__KERNEL__) -+ luaopen_nflib(L); -+#endif -+ -+ luaopen_bytearraylib(L); -+} -+ -+ -+ -+ ---- /dev/null -+++ b/extensions/LUA/controller.h -@@ -0,0 +1,264 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#ifndef CONTROLLER_H_ -+#define CONTROLLER_H_ -+ -+#include "stdlib.h" /* wrapper */ -+#include "string.h" /* wrapper */ -+#include "lua.h" -+#include "lualib.h" -+#include "lauxlib.h" -+ -+#if defined(__KERNEL__) -+#include -+#include -+#include -+#endif -+ -+ -+/* to compile the stuff in userspace (for testing)*/ -+#if !defined(__KERNEL__) -+#include -+#define pr_debug printf; -+ -+#define kmalloc(size, type) malloc(size) -+#define kfree(ptr) free(ptr) -+ -+#endif -+ -+ -+/**********************************************************************/ -+/* nf Lua configuration */ -+/**********************************************************************/ -+#define MAX_NR_OF_PROTOCOLS 16 -+#define SUPPORTED_PROTOCOL_TABLE "supported_protocols" -+ -+#define MAX_NR_OF_FIELDS_IN_DYN_PROT_BUF 32 -+ -+ -+/**********************************************************************/ -+/* Static Protocol Buffer configuration */ -+/**********************************************************************/ -+ -+/* the definitions of the stringified expression of the prot_bufs... -+ * make sure all static prot_bufs are listed and are unique */ -+#define LUA_PACKET_SEG_RAW "packet_raw" -+#define LUA_PACKET_SEG_ETH "packet_eth" -+#define LUA_PACKET_SEG_ICMP "packet_icmp" -+#define LUA_PACKET_SEG_IP "packet_ip" -+#define LUA_PACKET_SEG_TCP "packet_tcp" -+#define LUA_PACKET_SEG_TCP_OPT "packet_tcp_opt" -+#define LUA_PACKET_SEG_UDP "packet_udp" -+#define LUA_PACKET_SEG_TFTP "packet_tftp" -+ -+/* the enum holding all static prot_bufs... make sure it contains all -+ * static prot_bufs */ -+enum PROT_BUF { -+ PACKET_RAW, -+ PACKET_ETH, -+ PACKET_IP, -+ PACKET_ICMP, -+ PACKET_TCP, -+ PACKET_TCP_OPTIONS, -+ PACKET_UDP, -+ PACKET_TFTP, -+ PACKET_DYNAMIC, -+ PACKET_SENTINEL -+}; -+ -+/* the luaopen-function of the prot_bufs... make sure it is called -+ * inside luaopen_controller */ -+void luaopen_protbuf_raw(lua_State *L); -+void luaopen_protbuf_eth(lua_State *L); -+void luaopen_protbuf_ip(lua_State *L); -+void luaopen_protbuf_icmp(lua_State *L); -+void luaopen_protbuf_tcp(lua_State *L); -+void luaopen_protbuf_tcp_options(lua_State *L); -+void luaopen_protbuf_udp(lua_State *L); -+void luaopen_protbuf_tftp(lua_State *L); -+void luaopen_protbuf_dynamic(lua_State *L); -+ -+/**********************************************************************/ -+/* field changes */ -+/**********************************************************************/ -+struct field_changes { -+ int ref_count; -+ int *field_length_changes; -+ int *field_offset_changes; -+}; -+ -+/**********************************************************************/ -+/* lua packet segment */ -+/* ------------------ */ -+/* The struct lua_packet_segment is the integral part of a Lua packet.*/ -+/* At the very beginning, when a new packet arrives in `lua_tg`_ such */ -+/* a struct is initialized. The field start then points to the lowest */ -+/* available header inside the sk_buff structure. During packet */ -+/* processing the start pointer remains the same, only the offset and */ -+/* length value change. */ -+/**********************************************************************/ -+#define checkpacketseg(L, i, seg_type) \ -+ (lua_packet_segment *)luaL_checkudata(L, i, seg_type) -+ -+typedef struct lua_packet_segment { -+ unsigned int offset; -+ unsigned int length; -+ struct field_changes * changes; -+ unsigned char * start; /* need to be at the end because of the memory alignment */ -+} lua_packet_segment; -+ -+/**********************************************************************/ -+/* protocol field */ -+/* -------------- */ -+/* This structure is a container for the field definitions used by the*/ -+/* protocol buffer. Each protocol field is expressed using this struct*/ -+/* Have a look at the protocol buffers to see how the struct gets */ -+/* initialized. */ -+/* */ -+/* name: */ -+/* This member expresses the name of the field, ending */ -+/* in its own Lua function to access the field. */ -+/* offset / length: */ -+/* These members do specify the position inside the protocol header */ -+/* in bits (not bytes!). */ -+/* get / set: */ -+/* The get and set functions take a function pointer pointing to the*/ -+/* specific getter and setter function for this field. */ -+/**********************************************************************/ -+struct protocol_field { -+ const char * name; -+ uint32_t offset; -+ uint32_t length; -+ lua_CFunction get; -+ lua_CFunction set; -+}; -+#define PROT_FIELD_SENTINEL { NULL, 0, 0, NULL, NULL } -+ -+ -+/**********************************************************************/ -+/* protocol_buf */ -+/**********************************************************************/ -+/* This structure is a container for all the information needed for a -+ * protocol buffer. It gets initialized in each protocol buffer header -+ * file or for the dynamic protocol buffers on runtime using the -+ * 'register_dynamic_protocol_buffer' function. -+ * -+ * name: -+ * This member is used throughout the system. It is also exported -+ * to Lua as a variable name holding the index of the 'supported_protocols' -+ * array. The name is also used as the name of the generated Lua -+ * metatable, that is why inside the macro checkpacketseg_ it -+ * is always the name of a protocol buffer that is passed as the -+ * second parameter. -+ * payload_field: -+ * This member holds the string of the field responsible for payload -+ * data. The payload field of a protocol has an extra property, since -+ * it can be used to invoke another protocol buffer that is applied to -+ * the payload content. -+ * has_protocol: -+ * This member is used together with the payload_field. Since we must -+ * be sure that the payload content does really contain a protocol -+ * of type X. The function pointed to by has_protocol checks if the -+ * protocol buffer X can be applied on the payload_data. -+ * protocol_fields: -+ * This member points to the array of 'protocol_field' structures -+ * get_field_changes: -+ * This member is optional. It is used to return a pointer to an initialized -+ * field_changes struct. The function is called, whenever the payload field -+ * is requested with a given protocol type. Usually this function will -+ * initialize the field_changes struct depending on the content of the -+ * payload data. e.g. -+ * tcp = ip:data(packet_tcp) -+ * such a request will call the 'get_field_changes' function of the tcp -+ * protocol buffer. This enables, that the tcp options field have the proper -+ * length as well as the tcp data start at the right offset. -+ */ -+struct protocol_buf { -+ int is_dynamic; -+ const char * name; -+ char * payload_field; -+ int (*has_protocol)(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg, int type); -+ struct protocol_field * protocol_fields; -+ struct field_changes * (*get_field_changes)(lua_State *L, lua_packet_segment * seg); -+}; -+ -+/**********************************************************************/ -+/* lua byte array library */ -+/**********************************************************************/ -+#define LUA_BYTE_ARRAY "byte_array" -+#define checkbytearray(L, i) \ -+ (lua_packet_segment *)luaL_checkudata(L, i, LUA_BYTE_ARRAY) -+lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy); -+void luaopen_bytearraylib(lua_State *L); -+ -+ -+/**********************************************************************/ -+/* lua netfilter environment library */ -+/**********************************************************************/ -+#define NETFILTER_LIB "nf" -+#if defined(__KERNEL__) -+ struct lua_env { -+ lua_State *L; -+ /* perhaps more to come here (e.g. a state per CPU) */ -+ }; -+ #define LUA_ENV "lua_env" -+ #define checkluaenv(L, i) \ -+ (struct lua_env *)luaL_checkudata(L, i, LUA_ENV) -+ -+ void luaopen_nflib(lua_State *L); -+#endif -+ -+void cleanup_dynamic_prot_bufs(void); /* freeing all dynamic prot bufs */ -+/**********************************************************************/ -+/* lua protbuf helpers */ -+/**********************************************************************/ -+int get_1_bit_generic(lua_State *L); -+int set_1_bit_generic(lua_State *L); -+int get_lower_4_bit_generic(lua_State *L); -+int set_lower_4_bit_generic(lua_State *L); -+int get_upper_4_bit_generic(lua_State *L); -+int set_upper_4_bit_generic(lua_State *L); -+int get_8_bit_generic(lua_State *L); -+int set_8_bit_generic(lua_State *L); -+int get_16_bit_generic(lua_State *L); -+int set_16_bit_generic(lua_State *L); -+int get_32_bit_generic(lua_State *L); -+int set_32_bit_generic(lua_State *L); -+int set_data_generic(lua_State *L); -+int get_string_generic(lua_State *L); -+int get_byte_generic_str(lua_State *L); -+struct field_changes * get_allocated_field_changes(lua_State *L, int nr_of_fields); -+ -+/* only used by the dynamic prot buf subsystem */ -+#define MAX_NR_OF_DYN_PROT_BUFS 16 -+int field_dynamic_setter(lua_State *L); -+int field_dynamic_getter(lua_State *L); -+int has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int type); -+struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg); -+ -+/**********************************************************************/ -+/* lua controller API */ -+/**********************************************************************/ -+void luaopen_controller(lua_State *L); -+struct protocol_buf * get_protocol_buf(unsigned int protocol_id); -+void get_metatable_from_protocol_type(lua_State *L, int type); -+void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, unsigned int protocol_index); -+ -+ -+#endif /* CONTROLLER_H_ */ ---- /dev/null -+++ b/extensions/LUA/Kbuild -@@ -0,0 +1,49 @@ -+# -*- Makefile -*- -+ -+# Adding debug options -+EXTRA_CFLAGS += -DDEBUG -+ -+obj-m += xt_LUA.o -+ -+EXTRA_CFLAGS += -I$(src)/prot_buf_new -+xt_LUA-y += xt_LUA_target.o \ -+ -+xt_LUA-y += nf_lua.o \ -+ prot_buf_helpers.o \ -+ byte_array.o \ -+ controller.o \ -+ prot_buf_ethernet.o \ -+ prot_buf_icmp.o \ -+ prot_buf_ip.o \ -+ prot_buf_raw.o \ -+ prot_buf_tcp.o \ -+ prot_buf_udp.o \ -+ prot_buf_tftp.o \ -+ prot_buf_dynamic.o \ -+ -+ -+# Adding Lua Support -+EXTRA_CFLAGS += -I$(src)/lua -I$(src)/lua/include -+xt_LUA-y += lua/lapi.o \ -+ lua/lbaselib.o \ -+ lua/lcode.o \ -+ lua/ldebug.o \ -+ lua/ldo.o \ -+ lua/ldump.o \ -+ lua/lfunc.o \ -+ lua/lgc.o \ -+ lua/llex.o \ -+ lua/lmem.o \ -+ lua/lobject.o \ -+ lua/lopcodes.o \ -+ lua/lparser.o \ -+ lua/lstate.o \ -+ lua/lstring.o \ -+ lua/lstrlib.o \ -+ lua/ltable.o \ -+ lua/ltablib.o \ -+ lua/ltm.o \ -+ lua/lundump.o \ -+ lua/lvm.o \ -+ lua/lzio.o \ -+ lua/lauxlib.o \ ---- /dev/null -+++ b/extensions/LUA/libxt_LUA.c -@@ -0,0 +1,191 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "xt_LUA.h" -+ -+enum { -+ FLAG_SCRIPT = 1 << 0, -+ FLAG_STATE = 1 << 1, -+ FLAG_FUNCTION = 1 << 2, -+}; -+ -+static const struct option lua_tg_opts[] = { -+ { .name = "script", .has_arg = true, .val = 's' }, -+ { .name = "state", .has_arg = true, .val = 'l' }, -+ { .name = "function", .has_arg = true, .val = 'f' }, -+ { NULL }, -+}; -+ -+ -+static void lua_tg_help(void) -+{ -+ printf( -+ "LUA target options:\n" -+ " --script SCRIPT Process packet with the Lua script given by SCRIPT\n" -+ " \n" -+ " --state ID Process packet within the Lua state given by ID.\n" -+ " Omitting --state infers the ID 0, which can be\n" -+ " refered to the 'global' state.\n" -+ " \n" -+ " --function FUNCTION Name of the function that processes the Lua packet\n" -+ "\n"); -+} -+ -+static void -+lua_tg_init(struct xt_entry_target *target) -+{ -+ struct xt_lua_tginfo *info = (void *)target->data; -+ -+ info->state_id = 0; -+ strncpy(info->function, "process_packet\0", sizeof("process_packet\0")); -+} -+ -+static int -+lua_tg_parse(int32_t c, char **argv, int32_t invert, uint32_t *flags, -+ const void *entry, struct xt_entry_target **target) -+{ -+ struct xt_lua_tginfo *info = (void *)(*target)->data; -+ char buf[MAX_SCRIPT_SIZE]; -+ long script_size; -+ uint32_t state_id; -+ FILE *file; -+ -+ switch (c) { -+ case 's': -+ if (*flags & FLAG_SCRIPT) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot specify --script more than once"); -+ -+ if (strlen(optarg) > sizeof(info->filename)) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Maximum script length is %zu", -+ sizeof(info->filename)); -+ -+ if (strchr(optarg, '\n')) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Newlines not allowed in script name"); -+ file = fopen(optarg, "rb"); -+ if (file != NULL) { -+ fseek(file, 0, SEEK_END); -+ script_size = ftell(file); -+ if (script_size > MAX_SCRIPT_SIZE) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: The size of the script is too big"); -+ -+ fseek(file, 0, SEEK_SET); -+ fread(buf, script_size, 1, file); -+ fclose(file); -+ } else -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot open script %s", optarg); -+ -+ strncpy(info->filename, optarg, sizeof(info->filename)); -+ strncpy(info->buf, buf, sizeof(info->buf)); -+ info->script_size = script_size; -+ -+ *flags |= FLAG_SCRIPT; -+ return true; -+ -+ case 'l': -+ if (*flags & FLAG_STATE) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot specify --state more than once"); -+ -+ if (!xtables_strtoui(optarg, NULL, &state_id, 0, 8)) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Invalid --state %s", optarg); -+ -+ info->state_id = state_id; -+ *flags |= FLAG_STATE; -+ return true; -+ -+ case 'f': -+ if (*flags & FLAG_FUNCTION) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot specify --function more than once"); -+ if (strlen(optarg) > sizeof(info->function)) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Maximum function length is %zu", -+ sizeof(info->function)); -+ -+ if (strchr(optarg, '\n')) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Newlines not allowed in function name"); -+ -+ strncpy(info->function, optarg, sizeof(info->function)); -+ -+ *flags |= FLAG_FUNCTION; -+ return true; -+ } -+ -+ return false; -+} -+ -+static void -+lua_tg_check(uint32_t flags) -+{ -+ if (flags == 0) -+ xtables_error(PARAMETER_PROBLEM, "LUA: --script parameter required"); -+} -+ -+static void -+lua_tg_print(const void *entry, const struct xt_entry_target *target, -+ int32_t numeric) -+{ -+ const struct xt_lua_tginfo *info = (const void *)target->data; -+ -+ printf("LUA script: %s ", info->filename); -+} -+ -+static void -+lua_tg_save(const void *entry, const struct xt_entry_target *target) -+{ -+ const struct xt_lua_tginfo *info = (const void *)target->data; -+ -+ printf("--script %s ", info->filename); -+} -+ -+static struct xtables_target lua_tg_reg = { -+ .name = "LUA", -+ .version = XTABLES_VERSION, -+ .revision = 0, -+ .family = NFPROTO_UNSPEC, -+ .size = XT_ALIGN(sizeof(struct xt_lua_tginfo)), -+ .userspacesize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), -+ .help = lua_tg_help, -+ .init = lua_tg_init, -+ .parse = lua_tg_parse, -+ .final_check = lua_tg_check, -+ .print = lua_tg_print, -+ .save = lua_tg_save, -+ .extra_opts = lua_tg_opts, -+}; -+ -+static __attribute__((constructor)) void lua_tg_ldr(void) -+{ -+ xtables_register_target(&lua_tg_reg); -+} -+ ---- /dev/null -+++ b/extensions/LUA/libxt_LUA.man -@@ -0,0 +1 @@ -+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ---- /dev/null -+++ b/extensions/LUA/lua/include/ctype.h -@@ -0,0 +1,11 @@ -+#include -+#undef isalnum -+#define isalnum(c) (((__ismask(c)&(_U|_L|_D)) != 0) && (c > 0)) -+#undef isalpha -+#define isalpha(c) (((__ismask(c)&(_U|_L)) != 0) && (c > 0)) -+#undef iscntrl -+#define iscntrl(c) (((__ismask(c)&(_C)) != 0) && (c > 0)) -+#undef isdigit -+#define isdigit(c) (((__ismask(c)&(_D)) != 0) && (c > 0)) -+#undef isspace -+#define isspace(c) (((__ismask(c)&(_S)) != 0) && (c > 0)) ---- /dev/null -+++ b/extensions/LUA/lua/include/errno.h -@@ -0,0 +1 @@ -+#include ---- /dev/null -+++ b/extensions/LUA/lua/include/locale.h -@@ -0,0 +1,5 @@ -+struct lconv { -+ char * decimal_point ; -+} ; -+ -+#define localeconv() NULL ---- /dev/null -+++ b/extensions/LUA/lua/include/setjmp.h -@@ -0,0 +1,26 @@ -+/* -+ * arch/um/include/sysdep-i386/archsetjmp.h -+ */ -+ -+#ifndef _KLIBC_ARCHSETJMP_H -+#define _KLIBC_ARCHSETJMP_H -+ -+struct __jmp_buf { -+ unsigned int __ebx; -+ unsigned int __esp; -+ unsigned int __ebp; -+ unsigned int __esi; -+ unsigned int __edi; -+ unsigned int __eip; -+}; -+ -+typedef struct __jmp_buf jmp_buf[1]; -+ -+#define JB_IP __eip -+#define JB_SP __esp -+ -+int setjmp(jmp_buf); -+void longjmp(jmp_buf, int); -+ -+#endif /* _SETJMP_H */ -+ ---- /dev/null -+++ b/extensions/LUA/lua/include/stdio.h -@@ -0,0 +1 @@ -+#include ---- /dev/null -+++ b/extensions/LUA/lua/include/stdlib.h -@@ -0,0 +1,7 @@ -+#include -+ -+#define exit(E) return -+#define strtoul simple_strtoul -+#define strcoll strcmp -+ -+#define CHAR_BIT 8 ---- /dev/null -+++ b/extensions/LUA/lua/include/string.h -@@ -0,0 +1 @@ -+#include ---- /dev/null -+++ b/extensions/LUA/lua/lapi.c -@@ -0,0 +1,1086 @@ -+/* -+** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ -+** Lua API -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+#include -+ -+#define lapi_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lapi.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lundump.h" -+#include "lvm.h" -+ -+ -+ -+const char lua_ident[] = -+ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" -+ "$Authors: " LUA_AUTHORS " $\n" -+ "$URL: www.lua.org $\n"; -+ -+ -+ -+#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) -+ -+#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) -+ -+#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} -+ -+ -+ -+static TValue *index2adr (lua_State *L, int idx) { -+ if (idx > 0) { -+ TValue *o = L->base + (idx - 1); -+ api_check(L, idx <= L->ci->top - L->base); -+ if (o >= L->top) return cast(TValue *, luaO_nilobject); -+ else return o; -+ } -+ else if (idx > LUA_REGISTRYINDEX) { -+ api_check(L, idx != 0 && -idx <= L->top - L->base); -+ return L->top + idx; -+ } -+ else switch (idx) { /* pseudo-indices */ -+ case LUA_REGISTRYINDEX: return registry(L); -+ case LUA_ENVIRONINDEX: { -+ Closure *func = curr_func(L); -+ sethvalue(L, &L->env, func->c.env); -+ return &L->env; -+ } -+ case LUA_GLOBALSINDEX: return gt(L); -+ default: { -+ Closure *func = curr_func(L); -+ idx = LUA_GLOBALSINDEX - idx; -+ return (idx <= func->c.nupvalues) -+ ? &func->c.upvalue[idx-1] -+ : cast(TValue *, luaO_nilobject); -+ } -+ } -+} -+ -+ -+static Table *getcurrenv (lua_State *L) { -+ if (L->ci == L->base_ci) /* no enclosing function? */ -+ return hvalue(gt(L)); /* use global table as environment */ -+ else { -+ Closure *func = curr_func(L); -+ return func->c.env; -+ } -+} -+ -+ -+void luaA_pushobject (lua_State *L, const TValue *o) { -+ setobj2s(L, L->top, o); -+ api_incr_top(L); -+} -+ -+ -+LUA_API int lua_checkstack (lua_State *L, int size) { -+ int res = 1; -+ lua_lock(L); -+ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) -+ res = 0; /* stack overflow */ -+ else if (size > 0) { -+ luaD_checkstack(L, size); -+ if (L->ci->top < L->top + size) -+ L->ci->top = L->top + size; -+ } -+ lua_unlock(L); -+ return res; -+} -+ -+ -+LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { -+ int i; -+ if (from == to) return; -+ lua_lock(to); -+ api_checknelems(from, n); -+ api_check(from, G(from) == G(to)); -+ api_check(from, to->ci->top - to->top >= n); -+ from->top -= n; -+ for (i = 0; i < n; i++) { -+ setobj2s(to, to->top++, from->top + i); -+ } -+ lua_unlock(to); -+} -+ -+ -+LUA_API void lua_setlevel (lua_State *from, lua_State *to) { -+ to->nCcalls = from->nCcalls; -+} -+ -+ -+LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { -+ lua_CFunction old; -+ lua_lock(L); -+ old = G(L)->panic; -+ G(L)->panic = panicf; -+ lua_unlock(L); -+ return old; -+} -+ -+ -+LUA_API lua_State *lua_newthread (lua_State *L) { -+ lua_State *L1; -+ lua_lock(L); -+ luaC_checkGC(L); -+ L1 = luaE_newthread(L); -+ setthvalue(L, L->top, L1); -+ api_incr_top(L); -+ lua_unlock(L); -+ luai_userstatethread(L, L1); -+ return L1; -+} -+ -+ -+ -+/* -+** basic stack manipulation -+*/ -+ -+ -+LUA_API int lua_gettop (lua_State *L) { -+ return cast_int(L->top - L->base); -+} -+ -+ -+LUA_API void lua_settop (lua_State *L, int idx) { -+ lua_lock(L); -+ if (idx >= 0) { -+ api_check(L, idx <= L->stack_last - L->base); -+ while (L->top < L->base + idx) -+ setnilvalue(L->top++); -+ L->top = L->base + idx; -+ } -+ else { -+ api_check(L, -(idx+1) <= (L->top - L->base)); -+ L->top += idx+1; /* `subtract' index (index is negative) */ -+ } -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_remove (lua_State *L, int idx) { -+ StkId p; -+ lua_lock(L); -+ p = index2adr(L, idx); -+ api_checkvalidindex(L, p); -+ while (++p < L->top) setobjs2s(L, p-1, p); -+ L->top--; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_insert (lua_State *L, int idx) { -+ StkId p; -+ StkId q; -+ lua_lock(L); -+ p = index2adr(L, idx); -+ api_checkvalidindex(L, p); -+ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); -+ setobjs2s(L, p, L->top); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_replace (lua_State *L, int idx) { -+ StkId o; -+ lua_lock(L); -+ /* explicit test for incompatible code */ -+ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) -+ luaG_runerror(L, "no calling environment"); -+ api_checknelems(L, 1); -+ o = index2adr(L, idx); -+ api_checkvalidindex(L, o); -+ if (idx == LUA_ENVIRONINDEX) { -+ Closure *func = curr_func(L); -+ api_check(L, ttistable(L->top - 1)); -+ func->c.env = hvalue(L->top - 1); -+ luaC_barrier(L, func, L->top - 1); -+ } -+ else { -+ setobj(L, o, L->top - 1); -+ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ -+ luaC_barrier(L, curr_func(L), L->top - 1); -+ } -+ L->top--; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushvalue (lua_State *L, int idx) { -+ lua_lock(L); -+ setobj2s(L, L->top, index2adr(L, idx)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+ -+/* -+** access functions (stack -> C) -+*/ -+ -+ -+LUA_API int lua_type (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); -+} -+ -+ -+LUA_API const char *lua_typename (lua_State *L, int t) { -+ UNUSED(L); -+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; -+} -+ -+ -+LUA_API int lua_iscfunction (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return iscfunction(o); -+} -+ -+ -+LUA_API int lua_isnumber (lua_State *L, int idx) { -+ TValue n; -+ const TValue *o = index2adr(L, idx); -+ return tonumber(o, &n); -+} -+ -+ -+LUA_API int lua_isstring (lua_State *L, int idx) { -+ int t = lua_type(L, idx); -+ return (t == LUA_TSTRING || t == LUA_TNUMBER); -+} -+ -+ -+LUA_API int lua_isuserdata (lua_State *L, int idx) { -+ const TValue *o = index2adr(L, idx); -+ return (ttisuserdata(o) || ttislightuserdata(o)); -+} -+ -+ -+LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { -+ StkId o1 = index2adr(L, index1); -+ StkId o2 = index2adr(L, index2); -+ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 -+ : luaO_rawequalObj(o1, o2); -+} -+ -+ -+LUA_API int lua_equal (lua_State *L, int index1, int index2) { -+ StkId o1, o2; -+ int i; -+ lua_lock(L); /* may call tag method */ -+ o1 = index2adr(L, index1); -+ o2 = index2adr(L, index2); -+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); -+ lua_unlock(L); -+ return i; -+} -+ -+ -+LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { -+ StkId o1, o2; -+ int i; -+ lua_lock(L); /* may call tag method */ -+ o1 = index2adr(L, index1); -+ o2 = index2adr(L, index2); -+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 -+ : luaV_lessthan(L, o1, o2); -+ lua_unlock(L); -+ return i; -+} -+ -+ -+ -+LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { -+ TValue n; -+ const TValue *o = index2adr(L, idx); -+ if (tonumber(o, &n)) -+ return nvalue(o); -+ else -+ return 0; -+} -+ -+ -+LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { -+ TValue n; -+ const TValue *o = index2adr(L, idx); -+ if (tonumber(o, &n)) { -+ lua_Integer res; -+ lua_Number num = nvalue(o); -+ lua_number2integer(res, num); -+ return res; -+ } -+ else -+ return 0; -+} -+ -+ -+LUA_API int lua_toboolean (lua_State *L, int idx) { -+ const TValue *o = index2adr(L, idx); -+ return !l_isfalse(o); -+} -+ -+ -+LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { -+ StkId o = index2adr(L, idx); -+ if (!ttisstring(o)) { -+ lua_lock(L); /* `luaV_tostring' may create a new string */ -+ if (!luaV_tostring(L, o)) { /* conversion failed? */ -+ if (len != NULL) *len = 0; -+ lua_unlock(L); -+ return NULL; -+ } -+ luaC_checkGC(L); -+ o = index2adr(L, idx); /* previous call may reallocate the stack */ -+ lua_unlock(L); -+ } -+ if (len != NULL) *len = tsvalue(o)->len; -+ return svalue(o); -+} -+ -+ -+LUA_API size_t lua_objlen (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ switch (ttype(o)) { -+ case LUA_TSTRING: return tsvalue(o)->len; -+ case LUA_TUSERDATA: return uvalue(o)->len; -+ case LUA_TTABLE: return luaH_getn(hvalue(o)); -+ case LUA_TNUMBER: { -+ size_t l; -+ lua_lock(L); /* `luaV_tostring' may create a new string */ -+ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); -+ lua_unlock(L); -+ return l; -+ } -+ default: return 0; -+ } -+} -+ -+ -+LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; -+} -+ -+ -+LUA_API void *lua_touserdata (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ switch (ttype(o)) { -+ case LUA_TUSERDATA: return (rawuvalue(o) + 1); -+ case LUA_TLIGHTUSERDATA: return pvalue(o); -+ default: return NULL; -+ } -+} -+ -+ -+LUA_API lua_State *lua_tothread (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return (!ttisthread(o)) ? NULL : thvalue(o); -+} -+ -+ -+LUA_API const void *lua_topointer (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ switch (ttype(o)) { -+ case LUA_TTABLE: return hvalue(o); -+ case LUA_TFUNCTION: return clvalue(o); -+ case LUA_TTHREAD: return thvalue(o); -+ case LUA_TUSERDATA: -+ case LUA_TLIGHTUSERDATA: -+ return lua_touserdata(L, idx); -+ default: return NULL; -+ } -+} -+ -+ -+ -+/* -+** push functions (C -> stack) -+*/ -+ -+ -+LUA_API void lua_pushnil (lua_State *L) { -+ lua_lock(L); -+ setnilvalue(L->top); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { -+ lua_lock(L); -+ setnvalue(L->top, n); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { -+ lua_lock(L); -+ setnvalue(L->top, cast_num(n)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { -+ lua_lock(L); -+ luaC_checkGC(L); -+ setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushstring (lua_State *L, const char *s) { -+ if (s == NULL) -+ lua_pushnil(L); -+ else -+ lua_pushlstring(L, s, strlen(s)); -+} -+ -+ -+LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, -+ va_list argp) { -+ const char *ret; -+ lua_lock(L); -+ luaC_checkGC(L); -+ ret = luaO_pushvfstring(L, fmt, argp); -+ lua_unlock(L); -+ return ret; -+} -+ -+ -+LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { -+ const char *ret; -+ va_list argp; -+ lua_lock(L); -+ luaC_checkGC(L); -+ va_start(argp, fmt); -+ ret = luaO_pushvfstring(L, fmt, argp); -+ va_end(argp); -+ lua_unlock(L); -+ return ret; -+} -+ -+ -+LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { -+ Closure *cl; -+ lua_lock(L); -+ luaC_checkGC(L); -+ api_checknelems(L, n); -+ cl = luaF_newCclosure(L, n, getcurrenv(L)); -+ cl->c.f = fn; -+ L->top -= n; -+ while (n--) -+ setobj2n(L, &cl->c.upvalue[n], L->top+n); -+ setclvalue(L, L->top, cl); -+ lua_assert(iswhite(obj2gco(cl))); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushboolean (lua_State *L, int b) { -+ lua_lock(L); -+ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { -+ lua_lock(L); -+ setpvalue(L->top, p); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API int lua_pushthread (lua_State *L) { -+ lua_lock(L); -+ setthvalue(L, L->top, L); -+ api_incr_top(L); -+ lua_unlock(L); -+ return (G(L)->mainthread == L); -+} -+ -+ -+ -+/* -+** get functions (Lua -> stack) -+*/ -+ -+ -+LUA_API void lua_gettable (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ luaV_gettable(L, t, L->top - 1, L->top - 1); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { -+ StkId t; -+ TValue key; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ setsvalue(L, &key, luaS_new(L, k)); -+ luaV_gettable(L, t, &key, L->top); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawget (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_check(L, ttistable(t)); -+ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { -+ StkId o; -+ lua_lock(L); -+ o = index2adr(L, idx); -+ api_check(L, ttistable(o)); -+ setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { -+ lua_lock(L); -+ luaC_checkGC(L); -+ sethvalue(L, L->top, luaH_new(L, narray, nrec)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API int lua_getmetatable (lua_State *L, int objindex) { -+ const TValue *obj; -+ Table *mt = NULL; -+ int res; -+ lua_lock(L); -+ obj = index2adr(L, objindex); -+ switch (ttype(obj)) { -+ case LUA_TTABLE: -+ mt = hvalue(obj)->metatable; -+ break; -+ case LUA_TUSERDATA: -+ mt = uvalue(obj)->metatable; -+ break; -+ default: -+ mt = G(L)->mt[ttype(obj)]; -+ break; -+ } -+ if (mt == NULL) -+ res = 0; -+ else { -+ sethvalue(L, L->top, mt); -+ api_incr_top(L); -+ res = 1; -+ } -+ lua_unlock(L); -+ return res; -+} -+ -+ -+LUA_API void lua_getfenv (lua_State *L, int idx) { -+ StkId o; -+ lua_lock(L); -+ o = index2adr(L, idx); -+ api_checkvalidindex(L, o); -+ switch (ttype(o)) { -+ case LUA_TFUNCTION: -+ sethvalue(L, L->top, clvalue(o)->c.env); -+ break; -+ case LUA_TUSERDATA: -+ sethvalue(L, L->top, uvalue(o)->env); -+ break; -+ case LUA_TTHREAD: -+ setobj2s(L, L->top, gt(thvalue(o))); -+ break; -+ default: -+ setnilvalue(L->top); -+ break; -+ } -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+/* -+** set functions (stack -> Lua) -+*/ -+ -+ -+LUA_API void lua_settable (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ api_checknelems(L, 2); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ luaV_settable(L, t, L->top - 2, L->top - 1); -+ L->top -= 2; /* pop index and value */ -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { -+ StkId t; -+ TValue key; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ setsvalue(L, &key, luaS_new(L, k)); -+ luaV_settable(L, t, &key, L->top - 1); -+ L->top--; /* pop value */ -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawset (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ api_checknelems(L, 2); -+ t = index2adr(L, idx); -+ api_check(L, ttistable(t)); -+ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); -+ luaC_barriert(L, hvalue(t), L->top-1); -+ L->top -= 2; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawseti (lua_State *L, int idx, int n) { -+ StkId o; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ o = index2adr(L, idx); -+ api_check(L, ttistable(o)); -+ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); -+ luaC_barriert(L, hvalue(o), L->top-1); -+ L->top--; -+ lua_unlock(L); -+} -+ -+ -+LUA_API int lua_setmetatable (lua_State *L, int objindex) { -+ TValue *obj; -+ Table *mt; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ obj = index2adr(L, objindex); -+ api_checkvalidindex(L, obj); -+ if (ttisnil(L->top - 1)) -+ mt = NULL; -+ else { -+ api_check(L, ttistable(L->top - 1)); -+ mt = hvalue(L->top - 1); -+ } -+ switch (ttype(obj)) { -+ case LUA_TTABLE: { -+ hvalue(obj)->metatable = mt; -+ if (mt) -+ luaC_objbarriert(L, hvalue(obj), mt); -+ break; -+ } -+ case LUA_TUSERDATA: { -+ uvalue(obj)->metatable = mt; -+ if (mt) -+ luaC_objbarrier(L, rawuvalue(obj), mt); -+ break; -+ } -+ default: { -+ G(L)->mt[ttype(obj)] = mt; -+ break; -+ } -+ } -+ L->top--; -+ lua_unlock(L); -+ return 1; -+} -+ -+ -+LUA_API int lua_setfenv (lua_State *L, int idx) { -+ StkId o; -+ int res = 1; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ o = index2adr(L, idx); -+ api_checkvalidindex(L, o); -+ api_check(L, ttistable(L->top - 1)); -+ switch (ttype(o)) { -+ case LUA_TFUNCTION: -+ clvalue(o)->c.env = hvalue(L->top - 1); -+ break; -+ case LUA_TUSERDATA: -+ uvalue(o)->env = hvalue(L->top - 1); -+ break; -+ case LUA_TTHREAD: -+ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); -+ break; -+ default: -+ res = 0; -+ break; -+ } -+ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); -+ L->top--; -+ lua_unlock(L); -+ return res; -+} -+ -+ -+/* -+** `load' and `call' functions (run Lua code) -+*/ -+ -+ -+#define adjustresults(L,nres) \ -+ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } -+ -+ -+#define checkresults(L,na,nr) \ -+ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) -+ -+ -+LUA_API void lua_call (lua_State *L, int nargs, int nresults) { -+ StkId func; -+ lua_lock(L); -+ api_checknelems(L, nargs+1); -+ checkresults(L, nargs, nresults); -+ func = L->top - (nargs+1); -+ luaD_call(L, func, nresults); -+ adjustresults(L, nresults); -+ lua_unlock(L); -+} -+ -+ -+ -+/* -+** Execute a protected call. -+*/ -+struct CallS { /* data to `f_call' */ -+ StkId func; -+ int nresults; -+}; -+ -+ -+static void f_call (lua_State *L, void *ud) { -+ struct CallS *c = cast(struct CallS *, ud); -+ luaD_call(L, c->func, c->nresults); -+} -+ -+ -+ -+LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { -+ struct CallS c; -+ int status; -+ ptrdiff_t func; -+ lua_lock(L); -+ api_checknelems(L, nargs+1); -+ checkresults(L, nargs, nresults); -+ if (errfunc == 0) -+ func = 0; -+ else { -+ StkId o = index2adr(L, errfunc); -+ api_checkvalidindex(L, o); -+ func = savestack(L, o); -+ } -+ c.func = L->top - (nargs+1); /* function to be called */ -+ c.nresults = nresults; -+ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); -+ adjustresults(L, nresults); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+/* -+** Execute a protected C call. -+*/ -+struct CCallS { /* data to `f_Ccall' */ -+ lua_CFunction func; -+ void *ud; -+}; -+ -+ -+static void f_Ccall (lua_State *L, void *ud) { -+ struct CCallS *c = cast(struct CCallS *, ud); -+ Closure *cl; -+ cl = luaF_newCclosure(L, 0, getcurrenv(L)); -+ cl->c.f = c->func; -+ setclvalue(L, L->top, cl); /* push function */ -+ api_incr_top(L); -+ setpvalue(L->top, c->ud); /* push only argument */ -+ api_incr_top(L); -+ luaD_call(L, L->top - 2, 0); -+} -+ -+ -+LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { -+ struct CCallS c; -+ int status; -+ lua_lock(L); -+ c.func = func; -+ c.ud = ud; -+ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, -+ const char *chunkname) { -+ ZIO z; -+ int status; -+ lua_lock(L); -+ if (!chunkname) chunkname = "?"; -+ luaZ_init(L, &z, reader, data); -+ status = luaD_protectedparser(L, &z, chunkname); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { -+ int status; -+ TValue *o; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ o = L->top - 1; -+ if (isLfunction(o)) -+ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); -+ else -+ status = 1; -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_status (lua_State *L) { -+ return L->status; -+} -+ -+ -+/* -+** Garbage-collection function -+*/ -+ -+LUA_API int lua_gc (lua_State *L, int what, int data) { -+ int res = 0; -+ global_State *g; -+ lua_lock(L); -+ g = G(L); -+ switch (what) { -+ case LUA_GCSTOP: { -+ g->GCthreshold = MAX_LUMEM; -+ break; -+ } -+ case LUA_GCRESTART: { -+ g->GCthreshold = g->totalbytes; -+ break; -+ } -+ case LUA_GCCOLLECT: { -+ luaC_fullgc(L); -+ break; -+ } -+ case LUA_GCCOUNT: { -+ /* GC values are expressed in Kbytes: #bytes/2^10 */ -+ res = cast_int(g->totalbytes >> 10); -+ break; -+ } -+ case LUA_GCCOUNTB: { -+ res = cast_int(g->totalbytes & 0x3ff); -+ break; -+ } -+ case LUA_GCSTEP: { -+ lu_mem a = (cast(lu_mem, data) << 10); -+ if (a <= g->totalbytes) -+ g->GCthreshold = g->totalbytes - a; -+ else -+ g->GCthreshold = 0; -+ while (g->GCthreshold <= g->totalbytes) { -+ luaC_step(L); -+ if (g->gcstate == GCSpause) { /* end of cycle? */ -+ res = 1; /* signal it */ -+ break; -+ } -+ } -+ break; -+ } -+ case LUA_GCSETPAUSE: { -+ res = g->gcpause; -+ g->gcpause = data; -+ break; -+ } -+ case LUA_GCSETSTEPMUL: { -+ res = g->gcstepmul; -+ g->gcstepmul = data; -+ break; -+ } -+ default: res = -1; /* invalid option */ -+ } -+ lua_unlock(L); -+ return res; -+} -+ -+ -+ -+/* -+** miscellaneous functions -+*/ -+ -+ -+LUA_API int lua_error (lua_State *L) { -+ lua_lock(L); -+ api_checknelems(L, 1); -+ luaG_errormsg(L); -+ lua_unlock(L); -+ return 0; /* to avoid warnings */ -+} -+ -+ -+LUA_API int lua_next (lua_State *L, int idx) { -+ StkId t; -+ int more; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_check(L, ttistable(t)); -+ more = luaH_next(L, hvalue(t), L->top - 1); -+ if (more) { -+ api_incr_top(L); -+ } -+ else /* no more elements */ -+ L->top -= 1; /* remove key */ -+ lua_unlock(L); -+ return more; -+} -+ -+ -+LUA_API void lua_concat (lua_State *L, int n) { -+ lua_lock(L); -+ api_checknelems(L, n); -+ if (n >= 2) { -+ luaC_checkGC(L); -+ luaV_concat(L, n, cast_int(L->top - L->base) - 1); -+ L->top -= (n-1); -+ } -+ else if (n == 0) { /* push empty string */ -+ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); -+ api_incr_top(L); -+ } -+ /* else n == 1; nothing to do */ -+ lua_unlock(L); -+} -+ -+ -+LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { -+ lua_Alloc f; -+ lua_lock(L); -+ if (ud) *ud = G(L)->ud; -+ f = G(L)->frealloc; -+ lua_unlock(L); -+ return f; -+} -+ -+ -+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { -+ lua_lock(L); -+ G(L)->ud = ud; -+ G(L)->frealloc = f; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void *lua_newuserdata (lua_State *L, size_t size) { -+ Udata *u; -+ lua_lock(L); -+ luaC_checkGC(L); -+ u = luaS_newudata(L, size, getcurrenv(L)); -+ setuvalue(L, L->top, u); -+ api_incr_top(L); -+ lua_unlock(L); -+ return u + 1; -+} -+ -+ -+ -+ -+static const char *aux_upvalue (StkId fi, int n, TValue **val) { -+ Closure *f; -+ if (!ttisfunction(fi)) return NULL; -+ f = clvalue(fi); -+ if (f->c.isC) { -+ if (!(1 <= n && n <= f->c.nupvalues)) return NULL; -+ *val = &f->c.upvalue[n-1]; -+ return ""; -+ } -+ else { -+ Proto *p = f->l.p; -+ if (!(1 <= n && n <= p->sizeupvalues)) return NULL; -+ *val = f->l.upvals[n-1]->v; -+ return getstr(p->upvalues[n-1]); -+ } -+} -+ -+ -+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { -+ const char *name; -+ TValue *val; -+ lua_lock(L); -+ name = aux_upvalue(index2adr(L, funcindex), n, &val); -+ if (name) { -+ setobj2s(L, L->top, val); -+ api_incr_top(L); -+ } -+ lua_unlock(L); -+ return name; -+} -+ -+ -+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { -+ const char *name; -+ TValue *val; -+ StkId fi; -+ lua_lock(L); -+ fi = index2adr(L, funcindex); -+ api_checknelems(L, 1); -+ name = aux_upvalue(fi, n, &val); -+ if (name) { -+ L->top--; -+ setobj(L, val, L->top); -+ luaC_barrier(L, clvalue(fi), L->top); -+ } -+ lua_unlock(L); -+ return name; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lapi.h -@@ -0,0 +1,16 @@ -+/* -+** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions from Lua API -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lapi_h -+#define lapi_h -+ -+ -+#include "lobject.h" -+ -+ -+LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lauxlib.c -@@ -0,0 +1,674 @@ -+/* -+** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ -+** Auxiliary functions for building Lua libraries -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#if !defined(__KERNEL__) -+#include -+#include -+#include -+#include -+#include -+#else -+#include -+#include -+#include -+#include -+#include -+#endif -+ -+/* This file uses only the official API of Lua. -+** Any function declared here could be written as an application function. -+*/ -+ -+#define lauxlib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+ -+ -+#define FREELIST_REF 0 /* free list of references */ -+ -+ -+/* convert a stack index to positive */ -+#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ -+ lua_gettop(L) + (i) + 1) -+ -+ -+/* -+** {====================================================== -+** Error-report functions -+** ======================================================= -+*/ -+ -+ -+LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { -+ lua_Debug ar; -+ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ -+ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); -+ lua_getinfo(L, "n", &ar); -+ if (strcmp(ar.namewhat, "method") == 0) { -+ narg--; /* do not count `self' */ -+ if (narg == 0) /* error is in the self argument itself? */ -+ return luaL_error(L, "calling " LUA_QS " on bad self (%s)", -+ ar.name, extramsg); -+ } -+ if (ar.name == NULL) -+ ar.name = "?"; -+ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", -+ narg, ar.name, extramsg); -+} -+ -+ -+LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { -+ const char *msg = lua_pushfstring(L, "%s expected, got %s", -+ tname, luaL_typename(L, narg)); -+ return luaL_argerror(L, narg, msg); -+} -+ -+ -+static void tag_error (lua_State *L, int narg, int tag) { -+ luaL_typerror(L, narg, lua_typename(L, tag)); -+} -+ -+ -+LUALIB_API void luaL_where (lua_State *L, int level) { -+ lua_Debug ar; -+ if (lua_getstack(L, level, &ar)) { /* check function at level */ -+ lua_getinfo(L, "Sl", &ar); /* get info about it */ -+ if (ar.currentline > 0) { /* is there info? */ -+ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); -+ return; -+ } -+ } -+ lua_pushliteral(L, ""); /* else, no information available... */ -+} -+ -+ -+LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { -+ va_list argp; -+ va_start(argp, fmt); -+ luaL_where(L, 1); -+ lua_pushvfstring(L, fmt, argp); -+ va_end(argp); -+ lua_concat(L, 2); -+ return lua_error(L); -+} -+ -+/* }====================================================== */ -+ -+ -+LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, -+ const char *const lst[]) { -+ const char *name = (def) ? luaL_optstring(L, narg, def) : -+ luaL_checkstring(L, narg); -+ int i; -+ for (i=0; lst[i]; i++) -+ if (strcmp(lst[i], name) == 0) -+ return i; -+ return luaL_argerror(L, narg, -+ lua_pushfstring(L, "invalid option " LUA_QS, name)); -+} -+ -+ -+LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { -+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ -+ if (!lua_isnil(L, -1)) /* name already in use? */ -+ return 0; /* leave previous value on top, but return 0 */ -+ lua_pop(L, 1); -+ lua_newtable(L); /* create metatable */ -+ lua_pushvalue(L, -1); -+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ -+ return 1; -+} -+ -+ -+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { -+ void *p = lua_touserdata(L, ud); -+ if (p != NULL) { /* value is a userdata? */ -+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ -+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ -+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ -+ lua_pop(L, 2); /* remove both metatables */ -+ return p; -+ } -+ } -+ } -+ luaL_typerror(L, ud, tname); /* else error */ -+ return NULL; /* to avoid warnings */ -+} -+ -+ -+LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { -+ if (!lua_checkstack(L, space)) -+ luaL_error(L, "stack overflow (%s)", mes); -+} -+ -+ -+LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { -+ if (lua_type(L, narg) != t) -+ tag_error(L, narg, t); -+} -+ -+ -+LUALIB_API void luaL_checkany (lua_State *L, int narg) { -+ if (lua_type(L, narg) == LUA_TNONE) -+ luaL_argerror(L, narg, "value expected"); -+} -+ -+ -+LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { -+ const char *s = lua_tolstring(L, narg, len); -+ if (!s) tag_error(L, narg, LUA_TSTRING); -+ return s; -+} -+ -+ -+LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, -+ const char *def, size_t *len) { -+ if (lua_isnoneornil(L, narg)) { -+ if (len) -+ *len = (def ? strlen(def) : 0); -+ return def; -+ } -+ else return luaL_checklstring(L, narg, len); -+} -+ -+ -+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { -+ lua_Number d = lua_tonumber(L, narg); -+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ -+ tag_error(L, narg, LUA_TNUMBER); -+ return d; -+} -+ -+ -+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { -+ return luaL_opt(L, luaL_checknumber, narg, def); -+} -+ -+ -+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { -+ lua_Integer d = lua_tointeger(L, narg); -+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ -+ tag_error(L, narg, LUA_TNUMBER); -+ return d; -+} -+ -+ -+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, -+ lua_Integer def) { -+ return luaL_opt(L, luaL_checkinteger, narg, def); -+} -+ -+ -+LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { -+ if (!lua_getmetatable(L, obj)) /* no metatable? */ -+ return 0; -+ lua_pushstring(L, event); -+ lua_rawget(L, -2); -+ if (lua_isnil(L, -1)) { -+ lua_pop(L, 2); /* remove metatable and metafield */ -+ return 0; -+ } -+ else { -+ lua_remove(L, -2); /* remove only metatable */ -+ return 1; -+ } -+} -+ -+ -+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { -+ obj = abs_index(L, obj); -+ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ -+ return 0; -+ lua_pushvalue(L, obj); -+ lua_call(L, 1, 1); -+ return 1; -+} -+ -+ -+LUALIB_API void (luaL_register) (lua_State *L, const char *libname, -+ const luaL_Reg *l) { -+ luaI_openlib(L, libname, l, 0); -+} -+ -+ -+static int libsize (const luaL_Reg *l) { -+ int size = 0; -+ for (; l->name; l++) size++; -+ return size; -+} -+ -+ -+LUALIB_API void luaI_openlib (lua_State *L, const char *libname, -+ const luaL_Reg *l, int nup) { -+ if (libname) { -+ int size = libsize(l); -+ /* check whether lib already exists */ -+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); -+ lua_getfield(L, -1, libname); /* get _LOADED[libname] */ -+ if (!lua_istable(L, -1)) { /* not found? */ -+ lua_pop(L, 1); /* remove previous result */ -+ /* try global variable (and create one if it does not exist) */ -+ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) -+ luaL_error(L, "name conflict for module " LUA_QS, libname); -+ lua_pushvalue(L, -1); -+ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ -+ } -+ lua_remove(L, -2); /* remove _LOADED table */ -+ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ -+ } -+ for (; l->name; l++) { -+ int i; -+ for (i=0; ifunc, nup); -+ lua_setfield(L, -(nup+2), l->name); -+ } -+ lua_pop(L, nup); /* remove upvalues */ -+} -+ -+ -+ -+/* -+** {====================================================== -+** getn-setn: size for arrays -+** ======================================================= -+*/ -+ -+#if defined(LUA_COMPAT_GETN) -+ -+static int checkint (lua_State *L, int topop) { -+ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; -+ lua_pop(L, topop); -+ return n; -+} -+ -+ -+static void getsizes (lua_State *L) { -+ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); -+ if (lua_isnil(L, -1)) { /* no `size' table? */ -+ lua_pop(L, 1); /* remove nil */ -+ lua_newtable(L); /* create it */ -+ lua_pushvalue(L, -1); /* `size' will be its own metatable */ -+ lua_setmetatable(L, -2); -+ lua_pushliteral(L, "kv"); -+ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ -+ lua_pushvalue(L, -1); -+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ -+ } -+} -+ -+ -+LUALIB_API void luaL_setn (lua_State *L, int t, int n) { -+ t = abs_index(L, t); -+ lua_pushliteral(L, "n"); -+ lua_rawget(L, t); -+ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ -+ lua_pushliteral(L, "n"); /* use it */ -+ lua_pushinteger(L, n); -+ lua_rawset(L, t); -+ } -+ else { /* use `sizes' */ -+ getsizes(L); -+ lua_pushvalue(L, t); -+ lua_pushinteger(L, n); -+ lua_rawset(L, -3); /* sizes[t] = n */ -+ lua_pop(L, 1); /* remove `sizes' */ -+ } -+} -+ -+ -+LUALIB_API int luaL_getn (lua_State *L, int t) { -+ int n; -+ t = abs_index(L, t); -+ lua_pushliteral(L, "n"); /* try t.n */ -+ lua_rawget(L, t); -+ if ((n = checkint(L, 1)) >= 0) return n; -+ getsizes(L); /* else try sizes[t] */ -+ lua_pushvalue(L, t); -+ lua_rawget(L, -2); -+ if ((n = checkint(L, 2)) >= 0) return n; -+ return (int)lua_objlen(L, t); -+} -+ -+#endif -+ -+/* }====================================================== */ -+ -+ -+ -+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, -+ const char *r) { -+ const char *wild; -+ size_t l = strlen(p); -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "luaL_gsub: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ while ((wild = strstr(s, p)) != NULL) { -+ luaL_addlstring(b, s, wild - s); /* push prefix */ -+ luaL_addstring(b, r); /* push replacement in place of pattern */ -+ s = wild + l; /* continue after `p' */ -+ } -+ luaL_addstring(b, s); /* push last suffix */ -+ luaL_pushresult(b); -+ kfree(b); -+ return lua_tostring(L, -1); -+} -+ -+ -+LUALIB_API const char *luaL_findtable (lua_State *L, int idx, -+ const char *fname, int szhint) { -+ const char *e; -+ lua_pushvalue(L, idx); -+ do { -+ e = strchr(fname, '.'); -+ if (e == NULL) e = fname + strlen(fname); -+ lua_pushlstring(L, fname, e - fname); -+ lua_rawget(L, -2); -+ if (lua_isnil(L, -1)) { /* no such field? */ -+ lua_pop(L, 1); /* remove this nil */ -+ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ -+ lua_pushlstring(L, fname, e - fname); -+ lua_pushvalue(L, -2); -+ lua_settable(L, -4); /* set new table into field */ -+ } -+ else if (!lua_istable(L, -1)) { /* field has a non-table value? */ -+ lua_pop(L, 2); /* remove table and value */ -+ return fname; /* return problematic part of the name */ -+ } -+ lua_remove(L, -2); /* remove previous table */ -+ fname = e + 1; -+ } while (*e == '.'); -+ return NULL; -+} -+ -+ -+ -+/* -+** {====================================================== -+** Generic Buffer manipulation -+** ======================================================= -+*/ -+ -+ -+#define bufflen(B) ((B)->p - (B)->buffer) -+#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) -+ -+#define LIMIT (LUA_MINSTACK/2) -+ -+ -+static int emptybuffer (luaL_Buffer *B) { -+ size_t l = bufflen(B); -+ if (l == 0) return 0; /* put nothing on stack */ -+ else { -+ lua_pushlstring(B->L, B->buffer, l); -+ B->p = B->buffer; -+ B->lvl++; -+ return 1; -+ } -+} -+ -+ -+static void adjuststack (luaL_Buffer *B) { -+ if (B->lvl > 1) { -+ lua_State *L = B->L; -+ int toget = 1; /* number of levels to concat */ -+ size_t toplen = lua_strlen(L, -1); -+ do { -+ size_t l = lua_strlen(L, -(toget+1)); -+ if (B->lvl - toget + 1 >= LIMIT || toplen > l) { -+ toplen += l; -+ toget++; -+ } -+ else break; -+ } while (toget < B->lvl); -+ lua_concat(L, toget); -+ B->lvl = B->lvl - toget + 1; -+ } -+} -+ -+ -+LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { -+ if (emptybuffer(B)) -+ adjuststack(B); -+ return B->buffer; -+} -+ -+ -+LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { -+ while (l--) -+ luaL_addchar(B, *s++); -+} -+ -+ -+LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { -+ luaL_addlstring(B, s, strlen(s)); -+} -+ -+ -+LUALIB_API void luaL_pushresult (luaL_Buffer *B) { -+ emptybuffer(B); -+ lua_concat(B->L, B->lvl); -+ B->lvl = 1; -+} -+ -+ -+LUALIB_API void luaL_addvalue (luaL_Buffer *B) { -+ lua_State *L = B->L; -+ size_t vl; -+ const char *s = lua_tolstring(L, -1, &vl); -+ if (vl <= bufffree(B)) { /* fit into buffer? */ -+ memcpy(B->p, s, vl); /* put it there */ -+ B->p += vl; -+ lua_pop(L, 1); /* remove from stack */ -+ } -+ else { -+ if (emptybuffer(B)) -+ lua_insert(L, -2); /* put buffer before new value */ -+ B->lvl++; /* add new value into B stack */ -+ adjuststack(B); -+ } -+} -+ -+ -+LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { -+ B->L = L; -+ B->p = B->buffer; -+ B->lvl = 0; -+} -+ -+/* }====================================================== */ -+ -+ -+LUALIB_API int luaL_ref (lua_State *L, int t) { -+ int ref; -+ t = abs_index(L, t); -+ if (lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* remove from stack */ -+ return LUA_REFNIL; /* `nil' has a unique fixed reference */ -+ } -+ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ -+ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ -+ lua_pop(L, 1); /* remove it from stack */ -+ if (ref != 0) { /* any free element? */ -+ lua_rawgeti(L, t, ref); /* remove it from list */ -+ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ -+ } -+ else { /* no free elements */ -+ ref = (int)lua_objlen(L, t); -+ ref++; /* create new reference */ -+ } -+ lua_rawseti(L, t, ref); -+ return ref; -+} -+ -+ -+LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { -+ if (ref >= 0) { -+ t = abs_index(L, t); -+ lua_rawgeti(L, t, FREELIST_REF); -+ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ -+ lua_pushinteger(L, ref); -+ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ -+ } -+} -+ -+ -+ -+/* -+** {====================================================== -+** Load functions -+** ======================================================= -+*/ -+ -+#if !defined(__KERNEL__) -+typedef struct LoadF { -+ int extraline; -+ FILE *f; -+ char buff[LUAL_BUFFERSIZE]; -+} LoadF; -+ -+ -+static const char *getF (lua_State *L, void *ud, size_t *size) { -+ LoadF *lf = (LoadF *)ud; -+ (void)L; -+ if (lf->extraline) { -+ lf->extraline = 0; -+ *size = 1; -+ return "\n"; -+ } -+ if (feof(lf->f)) return NULL; -+ *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); -+ return (*size > 0) ? lf->buff : NULL; -+} -+ -+ -+static int errfile (lua_State *L, const char *what, int fnameindex) { -+ const char *serr = strerror(errno); -+ const char *filename = lua_tostring(L, fnameindex) + 1; -+ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); -+ lua_remove(L, fnameindex); -+ return LUA_ERRFILE; -+} -+ -+ -+LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { -+ LoadF lf; -+ int status, readstatus; -+ int c; -+ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ -+ lf.extraline = 0; -+ if (filename == NULL) { -+ lua_pushliteral(L, "=stdin"); -+ lf.f = stdin; -+ } -+ else { -+ lua_pushfstring(L, "@%s", filename); -+ lf.f = fopen(filename, "r"); -+ if (lf.f == NULL) return errfile(L, "open", fnameindex); -+ } -+ c = getc(lf.f); -+ if (c == '#') { /* Unix exec. file? */ -+ lf.extraline = 1; -+ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ -+ if (c == '\n') c = getc(lf.f); -+ } -+ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ -+ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ -+ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); -+ /* skip eventual `#!...' */ -+ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; -+ lf.extraline = 0; -+ } -+ ungetc(c, lf.f); -+ status = lua_load(L, getF, &lf, lua_tostring(L, -1)); -+ readstatus = ferror(lf.f); -+ if (filename) fclose(lf.f); /* close file (even in case of errors) */ -+ if (readstatus) { -+ lua_settop(L, fnameindex); /* ignore results from `lua_load' */ -+ return errfile(L, "read", fnameindex); -+ } -+ lua_remove(L, fnameindex); -+ return status; -+} -+#endif -+ -+typedef struct LoadS { -+ const char *s; -+ size_t size; -+} LoadS; -+ -+ -+static const char *getS (lua_State *L, void *ud, size_t *size) { -+ LoadS *ls = (LoadS *)ud; -+ (void)L; -+ if (ls->size == 0) return NULL; -+ *size = ls->size; -+ ls->size = 0; -+ return ls->s; -+} -+ -+ -+LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, -+ const char *name) { -+ LoadS ls; -+ ls.s = buff; -+ ls.size = size; -+ return lua_load(L, getS, &ls, name); -+} -+ -+ -+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { -+ return luaL_loadbuffer(L, s, strlen(s), s); -+} -+ -+ -+ -+/* }====================================================== */ -+ -+ -+static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { -+ (void)ud; -+ (void)osize; -+ if (nsize == 0) { -+#if !defined(__KERNEL__) -+ free(ptr); -+#else -+ kfree(ptr); -+#endif -+ return NULL; -+ } -+ else -+#if !defined(__KERNEL__) -+ return realloc(ptr, nsize); -+#else -+ return krealloc(ptr, nsize, GFP_ATOMIC); -+#endif -+} -+ -+ -+static int lpanic (lua_State *L) { -+ (void)L; /* to avoid warnings */ -+#if !defined(__KERNEL__) -+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", -+#else -+ printk( "PANIC: unprotected error in call to Lua API (%s)\n", -+#endif -+ lua_tostring(L, -1)); -+ return 0; -+} -+ -+ -+LUALIB_API lua_State *luaL_newstate (void) { -+ lua_State *L = lua_newstate(l_alloc, NULL); -+ if (L) lua_atpanic(L, &lpanic); -+ return L; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lauxlib.h -@@ -0,0 +1,184 @@ -+/* -+** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions for building Lua libraries -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lauxlib_h -+#define lauxlib_h -+ -+ -+#include -+#include /* for kmalloc and kfree when allocating luaL_Buffer */ -+ -+#if !defined(__KERNEL__) -+#include -+#endif -+ -+#include "lua.h" -+ -+ -+#if defined(LUA_COMPAT_GETN) -+LUALIB_API int (luaL_getn) (lua_State *L, int t); -+LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); -+#else -+#define luaL_getn(L,i) ((int)lua_objlen(L, i)) -+#define luaL_setn(L,i,j) ((void)0) /* no op! */ -+#endif -+ -+#if defined(LUA_COMPAT_OPENLIB) -+#define luaI_openlib luaL_openlib -+#endif -+ -+ -+/* extra error code for `luaL_load' */ -+#define LUA_ERRFILE (LUA_ERRERR+1) -+ -+ -+typedef struct luaL_Reg { -+ const char *name; -+ lua_CFunction func; -+} luaL_Reg; -+ -+ -+ -+LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, -+ const luaL_Reg *l, int nup); -+LUALIB_API void (luaL_register) (lua_State *L, const char *libname, -+ const luaL_Reg *l); -+LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -+LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -+LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); -+LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -+LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, -+ size_t *l); -+LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, -+ const char *def, size_t *l); -+LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); -+LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); -+ -+LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); -+LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, -+ lua_Integer def); -+ -+LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -+LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); -+LUALIB_API void (luaL_checkany) (lua_State *L, int narg); -+ -+LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -+LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); -+ -+LUALIB_API void (luaL_where) (lua_State *L, int lvl); -+LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); -+ -+LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, -+ const char *const lst[]); -+ -+LUALIB_API int (luaL_ref) (lua_State *L, int t); -+LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); -+ -+#if !defined(__KERNEL__) -+LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); -+#endif -+ -+LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, -+ const char *name); -+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); -+ -+LUALIB_API lua_State *(luaL_newstate) (void); -+ -+ -+LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, -+ const char *r); -+ -+LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, -+ const char *fname, int szhint); -+ -+ -+ -+ -+/* -+** =============================================================== -+** some useful macros -+** =============================================================== -+*/ -+ -+#define luaL_argcheck(L, cond,numarg,extramsg) \ -+ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -+#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -+#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -+#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -+#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -+#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -+#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) -+ -+#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) -+ -+#if !defined(__KERNEL__) -+#define luaL_dofile(L, fn) \ -+ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) -+#endif -+ -+#define luaL_dostring(L, s) \ -+ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) -+ -+#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) -+ -+#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) -+ -+/* -+** {====================================================== -+** Generic Buffer manipulation -+** ======================================================= -+*/ -+ -+ -+ -+typedef struct luaL_Buffer { -+ char *p; /* current position in buffer */ -+ int lvl; /* number of strings in the stack (level) */ -+ lua_State *L; -+ char buffer[LUAL_BUFFERSIZE]; -+} luaL_Buffer; -+ -+#define luaL_addchar(B,c) \ -+ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ -+ (*(B)->p++ = (char)(c))) -+ -+/* compatibility only */ -+#define luaL_putchar(B,c) luaL_addchar(B,c) -+ -+#define luaL_addsize(B,n) ((B)->p += (n)) -+ -+ -+LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -+LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); -+LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -+LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -+LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -+LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); -+ -+ -+/* }====================================================== */ -+ -+ -+/* compatibility with ref system */ -+ -+/* pre-defined references */ -+#define LUA_NOREF (-2) -+#define LUA_REFNIL (-1) -+ -+#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ -+ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) -+ -+#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) -+ -+#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) -+ -+ -+#define luaL_reg luaL_Reg -+ -+#endif -+ -+ ---- /dev/null -+++ b/extensions/LUA/lua/lbaselib.c -@@ -0,0 +1,647 @@ -+/* -+** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ -+** Basic library -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+#include -+#include -+ -+#define lbaselib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+#include "lualib.h" -+ -+ -+ -+ -+/* -+** If your system does not support `stdout', you can just remove this function. -+** If you need, you can define your own `print' function, following this -+** model but changing `fputs' to put the strings at a proper place -+** (a console window or a log file, for instance). -+*/ -+static int luaB_print (lua_State *L) { -+ int n = lua_gettop(L); /* number of arguments */ -+ int i; -+ lua_getglobal(L, "tostring"); -+ for (i=1; i<=n; i++) { -+ const char *s; -+ lua_pushvalue(L, -1); /* function to be called */ -+ lua_pushvalue(L, i); /* value to print */ -+ lua_call(L, 1, 1); -+ s = lua_tostring(L, -1); /* get result */ -+ if (s == NULL) -+ return luaL_error(L, LUA_QL("tostring") " must return a string to " -+ LUA_QL("print")); -+ printk(KERN_INFO "LUA[print]: %s", s); -+ lua_pop(L, 1); /* pop result */ -+ } -+ return 0; -+} -+ -+ -+static int luaB_tonumber (lua_State *L) { -+ int base = luaL_optint(L, 2, 10); -+ if (base == 10) { /* standard conversion */ -+ luaL_checkany(L, 1); -+ if (lua_isnumber(L, 1)) { -+ lua_pushnumber(L, lua_tonumber(L, 1)); -+ return 1; -+ } -+ } -+ else { -+ const char *s1 = luaL_checkstring(L, 1); -+ char *s2; -+ unsigned long n; -+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); -+ n = simple_strtoul(s1, &s2, base); -+ if (s1 != s2) { /* at least one valid digit? */ -+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ -+ if (*s2 == '\0') { /* no invalid trailing characters? */ -+ lua_pushnumber(L, (lua_Number)n); -+ return 1; -+ } -+ } -+ } -+ lua_pushnil(L); /* else not a number */ -+ return 1; -+} -+ -+ -+static int luaB_error (lua_State *L) { -+ int level = luaL_optint(L, 2, 1); -+ lua_settop(L, 1); -+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ -+ luaL_where(L, level); -+ lua_pushvalue(L, 1); -+ lua_concat(L, 2); -+ } -+ return lua_error(L); -+} -+ -+ -+static int luaB_getmetatable (lua_State *L) { -+ luaL_checkany(L, 1); -+ if (!lua_getmetatable(L, 1)) { -+ lua_pushnil(L); -+ return 1; /* no metatable */ -+ } -+ luaL_getmetafield(L, 1, "__metatable"); -+ return 1; /* returns either __metatable field (if present) or metatable */ -+} -+ -+ -+static int luaB_setmetatable (lua_State *L) { -+ int t = lua_type(L, 2); -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, -+ "nil or table expected"); -+ if (luaL_getmetafield(L, 1, "__metatable")) -+ luaL_error(L, "cannot change a protected metatable"); -+ lua_settop(L, 2); -+ lua_setmetatable(L, 1); -+ return 1; -+} -+ -+ -+static void getfunc (lua_State *L, int opt) { -+ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); -+ else { -+ lua_Debug ar; -+ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); -+ luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); -+ if (lua_getstack(L, level, &ar) == 0) -+ luaL_argerror(L, 1, "invalid level"); -+ lua_getinfo(L, "f", &ar); -+ if (lua_isnil(L, -1)) -+ luaL_error(L, "no function environment for tail call at level %d", -+ level); -+ } -+} -+ -+ -+static int luaB_getfenv (lua_State *L) { -+ getfunc(L, 1); -+ if (lua_iscfunction(L, -1)) /* is a C function? */ -+ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ -+ else -+ lua_getfenv(L, -1); -+ return 1; -+} -+ -+ -+static int luaB_setfenv (lua_State *L) { -+ luaL_checktype(L, 2, LUA_TTABLE); -+ getfunc(L, 0); -+ lua_pushvalue(L, 2); -+ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { -+ /* change environment of current thread */ -+ lua_pushthread(L); -+ lua_insert(L, -2); -+ lua_setfenv(L, -2); -+ return 0; -+ } -+ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) -+ luaL_error(L, -+ LUA_QL("setfenv") " cannot change environment of given object"); -+ return 1; -+} -+ -+ -+static int luaB_rawequal (lua_State *L) { -+ luaL_checkany(L, 1); -+ luaL_checkany(L, 2); -+ lua_pushboolean(L, lua_rawequal(L, 1, 2)); -+ return 1; -+} -+ -+ -+static int luaB_rawget (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_checkany(L, 2); -+ lua_settop(L, 2); -+ lua_rawget(L, 1); -+ return 1; -+} -+ -+static int luaB_rawset (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_checkany(L, 2); -+ luaL_checkany(L, 3); -+ lua_settop(L, 3); -+ lua_rawset(L, 1); -+ return 1; -+} -+ -+ -+static int luaB_gcinfo (lua_State *L) { -+ lua_pushinteger(L, lua_getgccount(L)); -+ return 1; -+} -+ -+static int luaB_collectgarbage (lua_State *L) { -+ static const char *const opts[] = {"stop", "restart", "collect", -+ "count", "step", "setpause", "setstepmul", NULL}; -+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, -+ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; -+ int o = luaL_checkoption(L, 1, "collect", opts); -+ int ex = luaL_optint(L, 2, 0); -+ int res = lua_gc(L, optsnum[o], ex); -+ switch (optsnum[o]) { -+ case LUA_GCCOUNT: { -+ int b = lua_gc(L, LUA_GCCOUNTB, 0); -+ lua_pushnumber(L, res + ((lua_Number)b/1024)); -+ return 1; -+ } -+ case LUA_GCSTEP: { -+ lua_pushboolean(L, res); -+ return 1; -+ } -+ default: { -+ lua_pushnumber(L, res); -+ return 1; -+ } -+ } -+} -+ -+ -+static int luaB_type (lua_State *L) { -+ luaL_checkany(L, 1); -+ lua_pushstring(L, luaL_typename(L, 1)); -+ return 1; -+} -+ -+ -+static int luaB_next (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_settop(L, 2); /* create a 2nd argument if there isn't one */ -+ if (lua_next(L, 1)) -+ return 2; -+ else { -+ lua_pushnil(L); -+ return 1; -+ } -+} -+ -+ -+static int luaB_pairs (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ -+ lua_pushvalue(L, 1); /* state, */ -+ lua_pushnil(L); /* and initial value */ -+ return 3; -+} -+ -+ -+static int ipairsaux (lua_State *L) { -+ int i = luaL_checkint(L, 2); -+ luaL_checktype(L, 1, LUA_TTABLE); -+ i++; /* next value */ -+ lua_pushinteger(L, i); -+ lua_rawgeti(L, 1, i); -+ return (lua_isnil(L, -1)) ? 0 : 2; -+} -+ -+ -+static int luaB_ipairs (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ -+ lua_pushvalue(L, 1); /* state, */ -+ lua_pushinteger(L, 0); /* and initial value */ -+ return 3; -+} -+ -+ -+static int load_aux (lua_State *L, int status) { -+ if (status == 0) /* OK? */ -+ return 1; -+ else { -+ lua_pushnil(L); -+ lua_insert(L, -2); /* put before error message */ -+ return 2; /* return nil plus error message */ -+ } -+} -+ -+ -+static int luaB_loadstring (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ const char *chunkname = luaL_optstring(L, 2, s); -+ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); -+} -+ -+/* -+static int luaB_loadfile (lua_State *L) { -+ const char *fname = luaL_optstring(L, 1, NULL); -+ return load_aux(L, luaL_loadfile(L, fname)); -+} -+*/ -+ -+/* -+** Reader for generic `load' function: `lua_load' uses the -+** stack for internal stuff, so the reader cannot change the -+** stack top. Instead, it keeps its resulting string in a -+** reserved slot inside the stack. -+*/ -+static const char *generic_reader (lua_State *L, void *ud, size_t *size) { -+ (void)ud; /* to avoid warnings */ -+ luaL_checkstack(L, 2, "too many nested functions"); -+ lua_pushvalue(L, 1); /* get function */ -+ lua_call(L, 0, 1); /* call it */ -+ if (lua_isnil(L, -1)) { -+ *size = 0; -+ return NULL; -+ } -+ else if (lua_isstring(L, -1)) { -+ lua_replace(L, 3); /* save string in a reserved stack slot */ -+ return lua_tolstring(L, 3, size); -+ } -+ else luaL_error(L, "reader function must return a string"); -+ return NULL; /* to avoid warnings */ -+} -+ -+ -+static int luaB_load (lua_State *L) { -+ int status; -+ const char *cname = luaL_optstring(L, 2, "=(load)"); -+ luaL_checktype(L, 1, LUA_TFUNCTION); -+ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ -+ status = lua_load(L, generic_reader, NULL, cname); -+ return load_aux(L, status); -+} -+ -+/* -+static int luaB_dofile (lua_State *L) { -+ const char *fname = luaL_optstring(L, 1, NULL); -+ int n = lua_gettop(L); -+ if (luaL_loadfile(L, fname) != 0) lua_error(L); -+ lua_call(L, 0, LUA_MULTRET); -+ return lua_gettop(L) - n; -+} -+*/ -+ -+static int luaB_assert (lua_State *L) { -+ luaL_checkany(L, 1); -+ if (!lua_toboolean(L, 1)) -+ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); -+ return lua_gettop(L); -+} -+ -+ -+static int luaB_unpack (lua_State *L) { -+ int i, e, n; -+ luaL_checktype(L, 1, LUA_TTABLE); -+ i = luaL_optint(L, 2, 1); -+ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); -+ if (i > e) return 0; /* empty range */ -+ n = e - i + 1; /* number of elements */ -+ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ -+ return luaL_error(L, "too many results to unpack"); -+ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ -+ while (i++ < e) /* push arg[i + 1...e] */ -+ lua_rawgeti(L, 1, i); -+ return n; -+} -+ -+ -+static int luaB_select (lua_State *L) { -+ int n = lua_gettop(L); -+ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { -+ lua_pushinteger(L, n-1); -+ return 1; -+ } -+ else { -+ int i = luaL_checkint(L, 1); -+ if (i < 0) i = n + i; -+ else if (i > n) i = n; -+ luaL_argcheck(L, 1 <= i, 1, "index out of range"); -+ return n - i; -+ } -+} -+ -+ -+static int luaB_pcall (lua_State *L) { -+ int status; -+ luaL_checkany(L, 1); -+ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); -+ lua_pushboolean(L, (status == 0)); -+ lua_insert(L, 1); -+ return lua_gettop(L); /* return status + all results */ -+} -+ -+ -+static int luaB_xpcall (lua_State *L) { -+ int status; -+ luaL_checkany(L, 2); -+ lua_settop(L, 2); -+ lua_insert(L, 1); /* put error function under function to be called */ -+ status = lua_pcall(L, 0, LUA_MULTRET, 1); -+ lua_pushboolean(L, (status == 0)); -+ lua_replace(L, 1); -+ return lua_gettop(L); /* return status + all results */ -+} -+ -+ -+static int luaB_tostring (lua_State *L) { -+ luaL_checkany(L, 1); -+ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ -+ return 1; /* use its value */ -+ switch (lua_type(L, 1)) { -+ case LUA_TNUMBER: -+ lua_pushstring(L, lua_tostring(L, 1)); -+ break; -+ case LUA_TSTRING: -+ lua_pushvalue(L, 1); -+ break; -+ case LUA_TBOOLEAN: -+ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); -+ break; -+ case LUA_TNIL: -+ lua_pushliteral(L, "nil"); -+ break; -+ default: -+ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); -+ break; -+ } -+ return 1; -+} -+ -+ -+static int luaB_newproxy (lua_State *L) { -+ lua_settop(L, 1); -+ lua_newuserdata(L, 0); /* create proxy */ -+ if (lua_toboolean(L, 1) == 0) -+ return 1; /* no metatable */ -+ else if (lua_isboolean(L, 1)) { -+ lua_newtable(L); /* create a new metatable `m' ... */ -+ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ -+ lua_pushboolean(L, 1); -+ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ -+ } -+ else { -+ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ -+ if (lua_getmetatable(L, 1)) { -+ lua_rawget(L, lua_upvalueindex(1)); -+ validproxy = lua_toboolean(L, -1); -+ lua_pop(L, 1); /* remove value */ -+ } -+ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); -+ lua_getmetatable(L, 1); /* metatable is valid; get it */ -+ } -+ lua_setmetatable(L, 2); -+ return 1; -+} -+ -+ -+static const luaL_Reg base_funcs[] = { -+ {"assert", luaB_assert}, -+ {"collectgarbage", luaB_collectgarbage}, -+// {"dofile", luaB_dofile}, -+ {"error", luaB_error}, -+ {"gcinfo", luaB_gcinfo}, -+ {"getfenv", luaB_getfenv}, -+ {"getmetatable", luaB_getmetatable}, -+// {"loadfile", luaB_loadfile}, -+ {"load", luaB_load}, -+ {"loadstring", luaB_loadstring}, -+ {"next", luaB_next}, -+ {"pcall", luaB_pcall}, -+ {"print", luaB_print}, -+ {"rawequal", luaB_rawequal}, -+ {"rawget", luaB_rawget}, -+ {"rawset", luaB_rawset}, -+ {"select", luaB_select}, -+ {"setfenv", luaB_setfenv}, -+ {"setmetatable", luaB_setmetatable}, -+ {"tonumber", luaB_tonumber}, -+ {"tostring", luaB_tostring}, -+ {"type", luaB_type}, -+ {"unpack", luaB_unpack}, -+ {"xpcall", luaB_xpcall}, -+ {NULL, NULL} -+}; -+ -+ -+/* -+** {====================================================== -+** Coroutine library -+** ======================================================= -+*/ -+ -+#define CO_RUN 0 /* running */ -+#define CO_SUS 1 /* suspended */ -+#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ -+#define CO_DEAD 3 -+ -+static const char *const statnames[] = -+ {"running", "suspended", "normal", "dead"}; -+ -+static int costatus (lua_State *L, lua_State *co) { -+ if (L == co) return CO_RUN; -+ switch (lua_status(co)) { -+ case LUA_YIELD: -+ return CO_SUS; -+ case 0: { -+ lua_Debug ar; -+ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ -+ return CO_NOR; /* it is running */ -+ else if (lua_gettop(co) == 0) -+ return CO_DEAD; -+ else -+ return CO_SUS; /* initial state */ -+ } -+ default: /* some error occured */ -+ return CO_DEAD; -+ } -+} -+ -+ -+static int luaB_costatus (lua_State *L) { -+ lua_State *co = lua_tothread(L, 1); -+ luaL_argcheck(L, co, 1, "coroutine expected"); -+ lua_pushstring(L, statnames[costatus(L, co)]); -+ return 1; -+} -+ -+ -+static int auxresume (lua_State *L, lua_State *co, int narg) { -+ int status = costatus(L, co); -+ if (!lua_checkstack(co, narg)) -+ luaL_error(L, "too many arguments to resume"); -+ if (status != CO_SUS) { -+ lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); -+ return -1; /* error flag */ -+ } -+ lua_xmove(L, co, narg); -+ lua_setlevel(L, co); -+ status = lua_resume(co, narg); -+ if (status == 0 || status == LUA_YIELD) { -+ int nres = lua_gettop(co); -+ if (!lua_checkstack(L, nres + 1)) -+ luaL_error(L, "too many results to resume"); -+ lua_xmove(co, L, nres); /* move yielded values */ -+ return nres; -+ } -+ else { -+ lua_xmove(co, L, 1); /* move error message */ -+ return -1; /* error flag */ -+ } -+} -+ -+ -+static int luaB_coresume (lua_State *L) { -+ lua_State *co = lua_tothread(L, 1); -+ int r; -+ luaL_argcheck(L, co, 1, "coroutine expected"); -+ r = auxresume(L, co, lua_gettop(L) - 1); -+ if (r < 0) { -+ lua_pushboolean(L, 0); -+ lua_insert(L, -2); -+ return 2; /* return false + error message */ -+ } -+ else { -+ lua_pushboolean(L, 1); -+ lua_insert(L, -(r + 1)); -+ return r + 1; /* return true + `resume' returns */ -+ } -+} -+ -+ -+static int luaB_auxwrap (lua_State *L) { -+ lua_State *co = lua_tothread(L, lua_upvalueindex(1)); -+ int r = auxresume(L, co, lua_gettop(L)); -+ if (r < 0) { -+ if (lua_isstring(L, -1)) { /* error object is a string? */ -+ luaL_where(L, 1); /* add extra info */ -+ lua_insert(L, -2); -+ lua_concat(L, 2); -+ } -+ lua_error(L); /* propagate error */ -+ } -+ return r; -+} -+ -+ -+static int luaB_cocreate (lua_State *L) { -+ lua_State *NL = lua_newthread(L); -+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, -+ "Lua function expected"); -+ lua_pushvalue(L, 1); /* move function to top */ -+ lua_xmove(L, NL, 1); /* move function from L to NL */ -+ return 1; -+} -+ -+ -+static int luaB_cowrap (lua_State *L) { -+ luaB_cocreate(L); -+ lua_pushcclosure(L, luaB_auxwrap, 1); -+ return 1; -+} -+ -+ -+static int luaB_yield (lua_State *L) { -+ return lua_yield(L, lua_gettop(L)); -+} -+ -+ -+static int luaB_corunning (lua_State *L) { -+ if (lua_pushthread(L)) -+ lua_pushnil(L); /* main thread is not a coroutine */ -+ return 1; -+} -+ -+ -+static const luaL_Reg co_funcs[] = { -+ {"create", luaB_cocreate}, -+ {"resume", luaB_coresume}, -+ {"running", luaB_corunning}, -+ {"status", luaB_costatus}, -+ {"wrap", luaB_cowrap}, -+ {"yield", luaB_yield}, -+ {NULL, NULL} -+}; -+ -+/* }====================================================== */ -+ -+ -+static void auxopen (lua_State *L, const char *name, -+ lua_CFunction f, lua_CFunction u) { -+ lua_pushcfunction(L, u); -+ lua_pushcclosure(L, f, 1); -+ lua_setfield(L, -2, name); -+} -+ -+ -+static void base_open (lua_State *L) { -+ /* set global _G */ -+ lua_pushvalue(L, LUA_GLOBALSINDEX); -+ lua_setglobal(L, "_G"); -+ /* open lib into global table */ -+ luaL_register(L, "_G", base_funcs); -+ lua_pushliteral(L, LUA_VERSION); -+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */ -+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */ -+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); -+ auxopen(L, "pairs", luaB_pairs, luaB_next); -+ /* `newproxy' needs a weaktable as upvalue */ -+ lua_createtable(L, 0, 1); /* new table `w' */ -+ lua_pushvalue(L, -1); /* `w' will be its own metatable */ -+ lua_setmetatable(L, -2); -+ lua_pushliteral(L, "kv"); -+ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ -+ lua_pushcclosure(L, luaB_newproxy, 1); -+ lua_setglobal(L, "newproxy"); /* set global `newproxy' */ -+} -+ -+ -+LUALIB_API int luaopen_base (lua_State *L) { -+ base_open(L); -+ luaL_register(L, LUA_COLIBNAME, co_funcs); -+ return 2; -+} ---- /dev/null -+++ b/extensions/LUA/lua/lcode.c -@@ -0,0 +1,838 @@ -+/* -+** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ -+** Code generator for Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lcode_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lcode.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lgc.h" -+#include "llex.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+#include "ltable.h" -+ -+ -+#define hasjumps(e) ((e)->t != (e)->f) -+ -+ -+static int isnumeral(expdesc *e) { -+ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); -+} -+ -+ -+void luaK_nil (FuncState *fs, int from, int n) { -+ Instruction *previous; -+ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ -+ if (fs->pc == 0) { /* function start? */ -+ if (from >= fs->nactvar) -+ return; /* positions are already clean */ -+ } -+ else { -+ previous = &fs->f->code[fs->pc-1]; -+ if (GET_OPCODE(*previous) == OP_LOADNIL) { -+ int pfrom = GETARG_A(*previous); -+ int pto = GETARG_B(*previous); -+ if (pfrom <= from && from <= pto+1) { /* can connect both? */ -+ if (from+n-1 > pto) -+ SETARG_B(*previous, from+n-1); -+ return; -+ } -+ } -+ } -+ } -+ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ -+} -+ -+ -+int luaK_jump (FuncState *fs) { -+ int jpc = fs->jpc; /* save list of jumps to here */ -+ int j; -+ fs->jpc = NO_JUMP; -+ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); -+ luaK_concat(fs, &j, jpc); /* keep them on hold */ -+ return j; -+} -+ -+ -+void luaK_ret (FuncState *fs, int first, int nret) { -+ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -+} -+ -+ -+static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { -+ luaK_codeABC(fs, op, A, B, C); -+ return luaK_jump(fs); -+} -+ -+ -+static void fixjump (FuncState *fs, int pc, int dest) { -+ Instruction *jmp = &fs->f->code[pc]; -+ int offset = dest-(pc+1); -+ lua_assert(dest != NO_JUMP); -+ if (abs(offset) > MAXARG_sBx) -+ luaX_syntaxerror(fs->ls, "control structure too long"); -+ SETARG_sBx(*jmp, offset); -+} -+ -+ -+/* -+** returns current `pc' and marks it as a jump target (to avoid wrong -+** optimizations with consecutive instructions not in the same basic block). -+*/ -+int luaK_getlabel (FuncState *fs) { -+ fs->lasttarget = fs->pc; -+ return fs->pc; -+} -+ -+ -+static int getjump (FuncState *fs, int pc) { -+ int offset = GETARG_sBx(fs->f->code[pc]); -+ if (offset == NO_JUMP) /* point to itself represents end of list */ -+ return NO_JUMP; /* end of list */ -+ else -+ return (pc+1)+offset; /* turn offset into absolute position */ -+} -+ -+ -+static Instruction *getjumpcontrol (FuncState *fs, int pc) { -+ Instruction *pi = &fs->f->code[pc]; -+ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) -+ return pi-1; -+ else -+ return pi; -+} -+ -+ -+/* -+** check whether list has any jump that do not produce a value -+** (or produce an inverted value) -+*/ -+static int need_value (FuncState *fs, int list) { -+ for (; list != NO_JUMP; list = getjump(fs, list)) { -+ Instruction i = *getjumpcontrol(fs, list); -+ if (GET_OPCODE(i) != OP_TESTSET) return 1; -+ } -+ return 0; /* not found */ -+} -+ -+ -+static int patchtestreg (FuncState *fs, int node, int reg) { -+ Instruction *i = getjumpcontrol(fs, node); -+ if (GET_OPCODE(*i) != OP_TESTSET) -+ return 0; /* cannot patch other instructions */ -+ if (reg != NO_REG && reg != GETARG_B(*i)) -+ SETARG_A(*i, reg); -+ else /* no register to put value or register already has the value */ -+ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); -+ -+ return 1; -+} -+ -+ -+static void removevalues (FuncState *fs, int list) { -+ for (; list != NO_JUMP; list = getjump(fs, list)) -+ patchtestreg(fs, list, NO_REG); -+} -+ -+ -+static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, -+ int dtarget) { -+ while (list != NO_JUMP) { -+ int next = getjump(fs, list); -+ if (patchtestreg(fs, list, reg)) -+ fixjump(fs, list, vtarget); -+ else -+ fixjump(fs, list, dtarget); /* jump to default target */ -+ list = next; -+ } -+} -+ -+ -+static void dischargejpc (FuncState *fs) { -+ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); -+ fs->jpc = NO_JUMP; -+} -+ -+ -+void luaK_patchlist (FuncState *fs, int list, int target) { -+ if (target == fs->pc) -+ luaK_patchtohere(fs, list); -+ else { -+ lua_assert(target < fs->pc); -+ patchlistaux(fs, list, target, NO_REG, target); -+ } -+} -+ -+ -+void luaK_patchtohere (FuncState *fs, int list) { -+ luaK_getlabel(fs); -+ luaK_concat(fs, &fs->jpc, list); -+} -+ -+ -+void luaK_concat (FuncState *fs, int *l1, int l2) { -+ if (l2 == NO_JUMP) return; -+ else if (*l1 == NO_JUMP) -+ *l1 = l2; -+ else { -+ int list = *l1; -+ int next; -+ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ -+ list = next; -+ fixjump(fs, list, l2); -+ } -+} -+ -+ -+void luaK_checkstack (FuncState *fs, int n) { -+ int newstack = fs->freereg + n; -+ if (newstack > fs->f->maxstacksize) { -+ if (newstack >= MAXSTACK) -+ luaX_syntaxerror(fs->ls, "function or expression too complex"); -+ fs->f->maxstacksize = cast_byte(newstack); -+ } -+} -+ -+ -+void luaK_reserveregs (FuncState *fs, int n) { -+ luaK_checkstack(fs, n); -+ fs->freereg += n; -+} -+ -+ -+static void freereg (FuncState *fs, int reg) { -+ if (!ISK(reg) && reg >= fs->nactvar) { -+ fs->freereg--; -+ lua_assert(reg == fs->freereg); -+ } -+} -+ -+ -+static void freeexp (FuncState *fs, expdesc *e) { -+ if (e->k == VNONRELOC) -+ freereg(fs, e->u.s.info); -+} -+ -+ -+static int addk (FuncState *fs, TValue *k, TValue *v) { -+ lua_State *L = fs->L; -+ TValue *idx = luaH_set(L, fs->h, k); -+ Proto *f = fs->f; -+ int oldsize = f->sizek; -+ if (ttisnumber(idx)) { -+ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); -+ return cast_int(nvalue(idx)); -+ } -+ else { /* constant not found; create a new entry */ -+ setnvalue(idx, cast_num(fs->nk)); -+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, -+ MAXARG_Bx, "constant table overflow"); -+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); -+ setobj(L, &f->k[fs->nk], v); -+ luaC_barrier(L, f, v); -+ return fs->nk++; -+ } -+} -+ -+ -+int luaK_stringK (FuncState *fs, TString *s) { -+ TValue o; -+ setsvalue(fs->L, &o, s); -+ return addk(fs, &o, &o); -+} -+ -+ -+int luaK_numberK (FuncState *fs, lua_Number r) { -+ TValue o; -+ setnvalue(&o, r); -+ return addk(fs, &o, &o); -+} -+ -+ -+static int boolK (FuncState *fs, int b) { -+ TValue o; -+ setbvalue(&o, b); -+ return addk(fs, &o, &o); -+} -+ -+ -+static int nilK (FuncState *fs) { -+ TValue k, v; -+ setnilvalue(&v); -+ /* cannot use nil as key; instead use table itself to represent nil */ -+ sethvalue(fs->L, &k, fs->h); -+ return addk(fs, &k, &v); -+} -+ -+ -+void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { -+ if (e->k == VCALL) { /* expression is an open function call? */ -+ SETARG_C(getcode(fs, e), nresults+1); -+ } -+ else if (e->k == VVARARG) { -+ SETARG_B(getcode(fs, e), nresults+1); -+ SETARG_A(getcode(fs, e), fs->freereg); -+ luaK_reserveregs(fs, 1); -+ } -+} -+ -+ -+void luaK_setoneret (FuncState *fs, expdesc *e) { -+ if (e->k == VCALL) { /* expression is an open function call? */ -+ e->k = VNONRELOC; -+ e->u.s.info = GETARG_A(getcode(fs, e)); -+ } -+ else if (e->k == VVARARG) { -+ SETARG_B(getcode(fs, e), 2); -+ e->k = VRELOCABLE; /* can relocate its simple result */ -+ } -+} -+ -+ -+void luaK_dischargevars (FuncState *fs, expdesc *e) { -+ switch (e->k) { -+ case VLOCAL: { -+ e->k = VNONRELOC; -+ break; -+ } -+ case VUPVAL: { -+ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); -+ e->k = VRELOCABLE; -+ break; -+ } -+ case VGLOBAL: { -+ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); -+ e->k = VRELOCABLE; -+ break; -+ } -+ case VINDEXED: { -+ freereg(fs, e->u.s.aux); -+ freereg(fs, e->u.s.info); -+ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); -+ e->k = VRELOCABLE; -+ break; -+ } -+ case VVARARG: -+ case VCALL: { -+ luaK_setoneret(fs, e); -+ break; -+ } -+ default: break; /* there is one value available (somewhere) */ -+ } -+} -+ -+ -+static int code_label (FuncState *fs, int A, int b, int jump) { -+ luaK_getlabel(fs); /* those instructions may be jump targets */ -+ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -+} -+ -+ -+static void discharge2reg (FuncState *fs, expdesc *e, int reg) { -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VNIL: { -+ luaK_nil(fs, reg, 1); -+ break; -+ } -+ case VFALSE: case VTRUE: { -+ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); -+ break; -+ } -+ case VK: { -+ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); -+ break; -+ } -+ case VKNUM: { -+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); -+ break; -+ } -+ case VRELOCABLE: { -+ Instruction *pc = &getcode(fs, e); -+ SETARG_A(*pc, reg); -+ break; -+ } -+ case VNONRELOC: { -+ if (reg != e->u.s.info) -+ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); -+ break; -+ } -+ default: { -+ lua_assert(e->k == VVOID || e->k == VJMP); -+ return; /* nothing to do... */ -+ } -+ } -+ e->u.s.info = reg; -+ e->k = VNONRELOC; -+} -+ -+ -+static void discharge2anyreg (FuncState *fs, expdesc *e) { -+ if (e->k != VNONRELOC) { -+ luaK_reserveregs(fs, 1); -+ discharge2reg(fs, e, fs->freereg-1); -+ } -+} -+ -+ -+static void exp2reg (FuncState *fs, expdesc *e, int reg) { -+ discharge2reg(fs, e, reg); -+ if (e->k == VJMP) -+ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ -+ if (hasjumps(e)) { -+ int final; /* position after whole expression */ -+ int p_f = NO_JUMP; /* position of an eventual LOAD false */ -+ int p_t = NO_JUMP; /* position of an eventual LOAD true */ -+ if (need_value(fs, e->t) || need_value(fs, e->f)) { -+ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); -+ p_f = code_label(fs, reg, 0, 1); -+ p_t = code_label(fs, reg, 1, 0); -+ luaK_patchtohere(fs, fj); -+ } -+ final = luaK_getlabel(fs); -+ patchlistaux(fs, e->f, final, reg, p_f); -+ patchlistaux(fs, e->t, final, reg, p_t); -+ } -+ e->f = e->t = NO_JUMP; -+ e->u.s.info = reg; -+ e->k = VNONRELOC; -+} -+ -+ -+void luaK_exp2nextreg (FuncState *fs, expdesc *e) { -+ luaK_dischargevars(fs, e); -+ freeexp(fs, e); -+ luaK_reserveregs(fs, 1); -+ exp2reg(fs, e, fs->freereg - 1); -+} -+ -+ -+int luaK_exp2anyreg (FuncState *fs, expdesc *e) { -+ luaK_dischargevars(fs, e); -+ if (e->k == VNONRELOC) { -+ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ -+ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ -+ exp2reg(fs, e, e->u.s.info); /* put value on it */ -+ return e->u.s.info; -+ } -+ } -+ luaK_exp2nextreg(fs, e); /* default */ -+ return e->u.s.info; -+} -+ -+ -+void luaK_exp2val (FuncState *fs, expdesc *e) { -+ if (hasjumps(e)) -+ luaK_exp2anyreg(fs, e); -+ else -+ luaK_dischargevars(fs, e); -+} -+ -+ -+int luaK_exp2RK (FuncState *fs, expdesc *e) { -+ luaK_exp2val(fs, e); -+ switch (e->k) { -+ case VKNUM: -+ case VTRUE: -+ case VFALSE: -+ case VNIL: { -+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ -+ e->u.s.info = (e->k == VNIL) ? nilK(fs) : -+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : -+ boolK(fs, (e->k == VTRUE)); -+ e->k = VK; -+ return RKASK(e->u.s.info); -+ } -+ else break; -+ } -+ case VK: { -+ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ -+ return RKASK(e->u.s.info); -+ else break; -+ } -+ default: break; -+ } -+ /* not a constant in the right range: put it in a register */ -+ return luaK_exp2anyreg(fs, e); -+} -+ -+ -+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { -+ switch (var->k) { -+ case VLOCAL: { -+ freeexp(fs, ex); -+ exp2reg(fs, ex, var->u.s.info); -+ return; -+ } -+ case VUPVAL: { -+ int e = luaK_exp2anyreg(fs, ex); -+ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); -+ break; -+ } -+ case VGLOBAL: { -+ int e = luaK_exp2anyreg(fs, ex); -+ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); -+ break; -+ } -+ case VINDEXED: { -+ int e = luaK_exp2RK(fs, ex); -+ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); -+ break; -+ } -+ default: { -+ lua_assert(0); /* invalid var kind to store */ -+ break; -+ } -+ } -+ freeexp(fs, ex); -+} -+ -+ -+void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { -+ int func; -+ luaK_exp2anyreg(fs, e); -+ freeexp(fs, e); -+ func = fs->freereg; -+ luaK_reserveregs(fs, 2); -+ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); -+ freeexp(fs, key); -+ e->u.s.info = func; -+ e->k = VNONRELOC; -+} -+ -+ -+static void invertjump (FuncState *fs, expdesc *e) { -+ Instruction *pc = getjumpcontrol(fs, e->u.s.info); -+ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && -+ GET_OPCODE(*pc) != OP_TEST); -+ SETARG_A(*pc, !(GETARG_A(*pc))); -+} -+ -+ -+static int jumponcond (FuncState *fs, expdesc *e, int cond) { -+ if (e->k == VRELOCABLE) { -+ Instruction ie = getcode(fs, e); -+ if (GET_OPCODE(ie) == OP_NOT) { -+ fs->pc--; /* remove previous OP_NOT */ -+ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); -+ } -+ /* else go through */ -+ } -+ discharge2anyreg(fs, e); -+ freeexp(fs, e); -+ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); -+} -+ -+ -+void luaK_goiftrue (FuncState *fs, expdesc *e) { -+ int pc; /* pc of last jump */ -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VK: case VKNUM: case VTRUE: { -+ pc = NO_JUMP; /* always true; do nothing */ -+ break; -+ } -+ case VFALSE: { -+ pc = luaK_jump(fs); /* always jump */ -+ break; -+ } -+ case VJMP: { -+ invertjump(fs, e); -+ pc = e->u.s.info; -+ break; -+ } -+ default: { -+ pc = jumponcond(fs, e, 0); -+ break; -+ } -+ } -+ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ -+ luaK_patchtohere(fs, e->t); -+ e->t = NO_JUMP; -+} -+ -+ -+static void luaK_goiffalse (FuncState *fs, expdesc *e) { -+ int pc; /* pc of last jump */ -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VNIL: case VFALSE: { -+ pc = NO_JUMP; /* always false; do nothing */ -+ break; -+ } -+ case VTRUE: { -+ pc = luaK_jump(fs); /* always jump */ -+ break; -+ } -+ case VJMP: { -+ pc = e->u.s.info; -+ break; -+ } -+ default: { -+ pc = jumponcond(fs, e, 1); -+ break; -+ } -+ } -+ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ -+ luaK_patchtohere(fs, e->f); -+ e->f = NO_JUMP; -+} -+ -+ -+static void codenot (FuncState *fs, expdesc *e) { -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VNIL: case VFALSE: { -+ e->k = VTRUE; -+ break; -+ } -+ case VK: case VKNUM: case VTRUE: { -+ e->k = VFALSE; -+ break; -+ } -+ case VJMP: { -+ invertjump(fs, e); -+ break; -+ } -+ case VRELOCABLE: -+ case VNONRELOC: { -+ discharge2anyreg(fs, e); -+ freeexp(fs, e); -+ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); -+ e->k = VRELOCABLE; -+ break; -+ } -+ default: { -+ lua_assert(0); /* cannot happen */ -+ break; -+ } -+ } -+ /* interchange true and false lists */ -+ { int temp = e->f; e->f = e->t; e->t = temp; } -+ removevalues(fs, e->f); -+ removevalues(fs, e->t); -+} -+ -+ -+void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { -+ t->u.s.aux = luaK_exp2RK(fs, k); -+ t->k = VINDEXED; -+} -+ -+ -+static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { -+ lua_Number v1, v2, r; -+ if (!isnumeral(e1) || !isnumeral(e2)) return 0; -+ v1 = e1->u.nval; -+ v2 = e2->u.nval; -+ switch (op) { -+ case OP_ADD: r = luai_numadd(v1, v2); break; -+ case OP_SUB: r = luai_numsub(v1, v2); break; -+ case OP_MUL: r = luai_nummul(v1, v2); break; -+ case OP_DIV: -+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ -+ r = luai_numdiv(v1, v2); break; -+ case OP_MOD: -+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ -+ r = luai_nummod(v1, v2); break; -+ case OP_POW: r = luai_numpow(v1, v2); break; -+ case OP_UNM: r = luai_numunm(v1); break; -+ case OP_LEN: return 0; /* no constant folding for 'len' */ -+ default: lua_assert(0); r = 0; break; -+ } -+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ -+ e1->u.nval = r; -+ return 1; -+} -+ -+ -+static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { -+ if (constfolding(op, e1, e2)) -+ return; -+ else { -+ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; -+ int o1 = luaK_exp2RK(fs, e1); -+ if (o1 > o2) { -+ freeexp(fs, e1); -+ freeexp(fs, e2); -+ } -+ else { -+ freeexp(fs, e2); -+ freeexp(fs, e1); -+ } -+ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); -+ e1->k = VRELOCABLE; -+ } -+} -+ -+ -+static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, -+ expdesc *e2) { -+ int o1 = luaK_exp2RK(fs, e1); -+ int o2 = luaK_exp2RK(fs, e2); -+ freeexp(fs, e2); -+ freeexp(fs, e1); -+ if (cond == 0 && op != OP_EQ) { -+ int temp; /* exchange args to replace by `<' or `<=' */ -+ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ -+ cond = 1; -+ } -+ e1->u.s.info = condjump(fs, op, cond, o1, o2); -+ e1->k = VJMP; -+} -+ -+ -+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { -+ expdesc e2; -+ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; -+ switch (op) { -+ case OPR_MINUS: { -+ if (!isnumeral(e)) -+ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ -+ codearith(fs, OP_UNM, e, &e2); -+ break; -+ } -+ case OPR_NOT: codenot(fs, e); break; -+ case OPR_LEN: { -+ luaK_exp2anyreg(fs, e); /* cannot operate on constants */ -+ codearith(fs, OP_LEN, e, &e2); -+ break; -+ } -+ default: lua_assert(0); -+ } -+} -+ -+ -+void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { -+ switch (op) { -+ case OPR_AND: { -+ luaK_goiftrue(fs, v); -+ break; -+ } -+ case OPR_OR: { -+ luaK_goiffalse(fs, v); -+ break; -+ } -+ case OPR_CONCAT: { -+ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ -+ break; -+ } -+ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: -+ case OPR_MOD: case OPR_POW: { -+ if (!isnumeral(v)) luaK_exp2RK(fs, v); -+ break; -+ } -+ default: { -+ luaK_exp2RK(fs, v); -+ break; -+ } -+ } -+} -+ -+ -+void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { -+ switch (op) { -+ case OPR_AND: { -+ lua_assert(e1->t == NO_JUMP); /* list must be closed */ -+ luaK_dischargevars(fs, e2); -+ luaK_concat(fs, &e2->f, e1->f); -+ *e1 = *e2; -+ break; -+ } -+ case OPR_OR: { -+ lua_assert(e1->f == NO_JUMP); /* list must be closed */ -+ luaK_dischargevars(fs, e2); -+ luaK_concat(fs, &e2->t, e1->t); -+ *e1 = *e2; -+ break; -+ } -+ case OPR_CONCAT: { -+ luaK_exp2val(fs, e2); -+ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { -+ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); -+ freeexp(fs, e1); -+ SETARG_B(getcode(fs, e2), e1->u.s.info); -+ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; -+ } -+ else { -+ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ -+ codearith(fs, OP_CONCAT, e1, e2); -+ } -+ break; -+ } -+ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; -+ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; -+ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; -+ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; -+ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; -+ case OPR_POW: codearith(fs, OP_POW, e1, e2); break; -+ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; -+ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; -+ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; -+ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; -+ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; -+ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; -+ default: lua_assert(0); -+ } -+} -+ -+ -+void luaK_fixline (FuncState *fs, int line) { -+ fs->f->lineinfo[fs->pc - 1] = line; -+} -+ -+ -+static int luaK_code (FuncState *fs, Instruction i, int line) { -+ Proto *f = fs->f; -+ dischargejpc(fs); /* `pc' will change */ -+ /* put new instruction in code array */ -+ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, -+ MAX_INT, "code size overflow"); -+ f->code[fs->pc] = i; -+ /* save corresponding line information */ -+ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, -+ MAX_INT, "code size overflow"); -+ f->lineinfo[fs->pc] = line; -+ return fs->pc++; -+} -+ -+ -+int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { -+ lua_assert(getOpMode(o) == iABC); -+ lua_assert(getBMode(o) != OpArgN || b == 0); -+ lua_assert(getCMode(o) != OpArgN || c == 0); -+ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); -+} -+ -+ -+int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { -+ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); -+ lua_assert(getCMode(o) == OpArgN); -+ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); -+} -+ -+ -+void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { -+ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; -+ int b = (tostore == LUA_MULTRET) ? 0 : tostore; -+ lua_assert(tostore != 0); -+ if (c <= MAXARG_C) -+ luaK_codeABC(fs, OP_SETLIST, base, b, c); -+ else { -+ luaK_codeABC(fs, OP_SETLIST, base, b, 0); -+ luaK_code(fs, cast(Instruction, c), fs->ls->lastline); -+ } -+ fs->freereg = base + 1; /* free registers with list values */ -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lcode.h -@@ -0,0 +1,76 @@ -+/* -+** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Code generator for Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lcode_h -+#define lcode_h -+ -+#include "llex.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+ -+ -+/* -+** Marks the end of a patch list. It is an invalid value both as an absolute -+** address, and as a list link (would link an element to itself). -+*/ -+#define NO_JUMP (-1) -+ -+ -+/* -+** grep "ORDER OPR" if you change these enums -+*/ -+typedef enum BinOpr { -+ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, -+ OPR_CONCAT, -+ OPR_NE, OPR_EQ, -+ OPR_LT, OPR_LE, OPR_GT, OPR_GE, -+ OPR_AND, OPR_OR, -+ OPR_NOBINOPR -+} BinOpr; -+ -+ -+typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; -+ -+ -+#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) -+ -+#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) -+ -+#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) -+ -+LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -+LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -+LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -+LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -+LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -+LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -+LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -+LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); -+LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -+LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -+LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -+LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -+LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -+LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -+LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -+LUAI_FUNC int luaK_jump (FuncState *fs); -+LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -+LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -+LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -+LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -+LUAI_FUNC int luaK_getlabel (FuncState *fs); -+LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); -+LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -+LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); -+LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ldebug.c -@@ -0,0 +1,637 @@ -+/* -+** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ -+** Debug Interface -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+#include -+#include -+ -+#define ldebug_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lapi.h" -+#include "lcode.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lvm.h" -+ -+ -+ -+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); -+ -+ -+static int currentpc (lua_State *L, CallInfo *ci) { -+ if (!isLua(ci)) return -1; /* function is not a Lua function? */ -+ if (ci == L->ci) -+ ci->savedpc = L->savedpc; -+ return pcRel(ci->savedpc, ci_func(ci)->l.p); -+} -+ -+ -+static int currentline (lua_State *L, CallInfo *ci) { -+ int pc = currentpc(L, ci); -+ if (pc < 0) -+ return -1; /* only active lua functions have current-line information */ -+ else -+ return getline(ci_func(ci)->l.p, pc); -+} -+ -+ -+/* -+** this function can be called asynchronous (e.g. during a signal) -+*/ -+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { -+ if (func == NULL || mask == 0) { /* turn off hooks? */ -+ mask = 0; -+ func = NULL; -+ } -+ L->hook = func; -+ L->basehookcount = count; -+ resethookcount(L); -+ L->hookmask = cast_byte(mask); -+ return 1; -+} -+ -+ -+LUA_API lua_Hook lua_gethook (lua_State *L) { -+ return L->hook; -+} -+ -+ -+LUA_API int lua_gethookmask (lua_State *L) { -+ return L->hookmask; -+} -+ -+ -+LUA_API int lua_gethookcount (lua_State *L) { -+ return L->basehookcount; -+} -+ -+ -+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { -+ int status; -+ CallInfo *ci; -+ lua_lock(L); -+ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { -+ level--; -+ if (f_isLua(ci)) /* Lua function? */ -+ level -= ci->tailcalls; /* skip lost tail calls */ -+ } -+ if (level == 0 && ci > L->base_ci) { /* level found? */ -+ status = 1; -+ ar->i_ci = cast_int(ci - L->base_ci); -+ } -+ else if (level < 0) { /* level is of a lost tail call? */ -+ status = 1; -+ ar->i_ci = 0; -+ } -+ else status = 0; /* no such level */ -+ lua_unlock(L); -+ return status; -+} -+ -+ -+static Proto *getluaproto (CallInfo *ci) { -+ return (isLua(ci) ? ci_func(ci)->l.p : NULL); -+} -+ -+ -+static const char *findlocal (lua_State *L, CallInfo *ci, int n) { -+ const char *name; -+ Proto *fp = getluaproto(ci); -+ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) -+ return name; /* is a local variable in a Lua function */ -+ else { -+ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; -+ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ -+ return "(*temporary)"; -+ else -+ return NULL; -+ } -+} -+ -+ -+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { -+ CallInfo *ci = L->base_ci + ar->i_ci; -+ const char *name = findlocal(L, ci, n); -+ lua_lock(L); -+ if (name) -+ luaA_pushobject(L, ci->base + (n - 1)); -+ lua_unlock(L); -+ return name; -+} -+ -+ -+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { -+ CallInfo *ci = L->base_ci + ar->i_ci; -+ const char *name = findlocal(L, ci, n); -+ lua_lock(L); -+ if (name) -+ setobjs2s(L, ci->base + (n - 1), L->top - 1); -+ L->top--; /* pop value */ -+ lua_unlock(L); -+ return name; -+} -+ -+ -+static void funcinfo (lua_Debug *ar, Closure *cl) { -+ if (cl->c.isC) { -+ ar->source = "=[C]"; -+ ar->linedefined = -1; -+ ar->lastlinedefined = -1; -+ ar->what = "C"; -+ } -+ else { -+ ar->source = getstr(cl->l.p->source); -+ ar->linedefined = cl->l.p->linedefined; -+ ar->lastlinedefined = cl->l.p->lastlinedefined; -+ ar->what = (ar->linedefined == 0) ? "main" : "Lua"; -+ } -+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -+} -+ -+ -+static void info_tailcall (lua_Debug *ar) { -+ ar->name = ar->namewhat = ""; -+ ar->what = "tail"; -+ ar->lastlinedefined = ar->linedefined = ar->currentline = -1; -+ ar->source = "=(tail call)"; -+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -+ ar->nups = 0; -+} -+ -+ -+static void collectvalidlines (lua_State *L, Closure *f) { -+ if (f == NULL || f->c.isC) { -+ setnilvalue(L->top); -+ } -+ else { -+ Table *t = luaH_new(L, 0, 0); -+ int *lineinfo = f->l.p->lineinfo; -+ int i; -+ for (i=0; il.p->sizelineinfo; i++) -+ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); -+ sethvalue(L, L->top, t); -+ } -+ incr_top(L); -+} -+ -+ -+static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, -+ Closure *f, CallInfo *ci) { -+ int status = 1; -+ if (f == NULL) { -+ info_tailcall(ar); -+ return status; -+ } -+ for (; *what; what++) { -+ switch (*what) { -+ case 'S': { -+ funcinfo(ar, f); -+ break; -+ } -+ case 'l': { -+ ar->currentline = (ci) ? currentline(L, ci) : -1; -+ break; -+ } -+ case 'u': { -+ ar->nups = f->c.nupvalues; -+ break; -+ } -+ case 'n': { -+ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; -+ if (ar->namewhat == NULL) { -+ ar->namewhat = ""; /* not found */ -+ ar->name = NULL; -+ } -+ break; -+ } -+ case 'L': -+ case 'f': /* handled by lua_getinfo */ -+ break; -+ default: status = 0; /* invalid option */ -+ } -+ } -+ return status; -+} -+ -+ -+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { -+ int status; -+ Closure *f = NULL; -+ CallInfo *ci = NULL; -+ lua_lock(L); -+ if (*what == '>') { -+ StkId func = L->top - 1; -+ luai_apicheck(L, ttisfunction(func)); -+ what++; /* skip the '>' */ -+ f = clvalue(func); -+ L->top--; /* pop function */ -+ } -+ else if (ar->i_ci != 0) { /* no tail call? */ -+ ci = L->base_ci + ar->i_ci; -+ lua_assert(ttisfunction(ci->func)); -+ f = clvalue(ci->func); -+ } -+ status = auxgetinfo(L, what, ar, f, ci); -+ if (strchr(what, 'f')) { -+ if (f == NULL) setnilvalue(L->top); -+ else setclvalue(L, L->top, f); -+ incr_top(L); -+ } -+ if (strchr(what, 'L')) -+ collectvalidlines(L, f); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+/* -+** {====================================================== -+** Symbolic Execution and code checker -+** ======================================================= -+*/ -+ -+#define check(x) if (!(x)) return 0; -+ -+#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) -+ -+#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) -+ -+ -+ -+static int precheck (const Proto *pt) { -+ check(pt->maxstacksize <= MAXSTACK); -+ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); -+ check(!(pt->is_vararg & VARARG_NEEDSARG) || -+ (pt->is_vararg & VARARG_HASARG)); -+ check(pt->sizeupvalues <= pt->nups); -+ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); -+ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); -+ return 1; -+} -+ -+ -+#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) -+ -+int luaG_checkopenop (Instruction i) { -+ switch (GET_OPCODE(i)) { -+ case OP_CALL: -+ case OP_TAILCALL: -+ case OP_RETURN: -+ case OP_SETLIST: { -+ check(GETARG_B(i) == 0); -+ return 1; -+ } -+ default: return 0; /* invalid instruction after an open call */ -+ } -+} -+ -+ -+static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { -+ switch (mode) { -+ case OpArgN: check(r == 0); break; -+ case OpArgU: break; -+ case OpArgR: checkreg(pt, r); break; -+ case OpArgK: -+ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); -+ break; -+ } -+ return 1; -+} -+ -+ -+static Instruction symbexec (const Proto *pt, int lastpc, int reg) { -+ int pc; -+ int last; /* stores position of last instruction that changed `reg' */ -+ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ -+ check(precheck(pt)); -+ for (pc = 0; pc < lastpc; pc++) { -+ Instruction i = pt->code[pc]; -+ OpCode op = GET_OPCODE(i); -+ int a = GETARG_A(i); -+ int b = 0; -+ int c = 0; -+ check(op < NUM_OPCODES); -+ checkreg(pt, a); -+ switch (getOpMode(op)) { -+ case iABC: { -+ b = GETARG_B(i); -+ c = GETARG_C(i); -+ check(checkArgMode(pt, b, getBMode(op))); -+ check(checkArgMode(pt, c, getCMode(op))); -+ break; -+ } -+ case iABx: { -+ b = GETARG_Bx(i); -+ if (getBMode(op) == OpArgK) check(b < pt->sizek); -+ break; -+ } -+ case iAsBx: { -+ b = GETARG_sBx(i); -+ if (getBMode(op) == OpArgR) { -+ int dest = pc+1+b; -+ check(0 <= dest && dest < pt->sizecode); -+ if (dest > 0) { -+ int j; -+ /* check that it does not jump to a setlist count; this -+ is tricky, because the count from a previous setlist may -+ have the same value of an invalid setlist; so, we must -+ go all the way back to the first of them (if any) */ -+ for (j = 0; j < dest; j++) { -+ Instruction d = pt->code[dest-1-j]; -+ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; -+ } -+ /* if 'j' is even, previous value is not a setlist (even if -+ it looks like one) */ -+ check((j&1) == 0); -+ } -+ } -+ break; -+ } -+ } -+ if (testAMode(op)) { -+ if (a == reg) last = pc; /* change register `a' */ -+ } -+ if (testTMode(op)) { -+ check(pc+2 < pt->sizecode); /* check skip */ -+ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); -+ } -+ switch (op) { -+ case OP_LOADBOOL: { -+ if (c == 1) { /* does it jump? */ -+ check(pc+2 < pt->sizecode); /* check its jump */ -+ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || -+ GETARG_C(pt->code[pc+1]) != 0); -+ } -+ break; -+ } -+ case OP_LOADNIL: { -+ if (a <= reg && reg <= b) -+ last = pc; /* set registers from `a' to `b' */ -+ break; -+ } -+ case OP_GETUPVAL: -+ case OP_SETUPVAL: { -+ check(b < pt->nups); -+ break; -+ } -+ case OP_GETGLOBAL: -+ case OP_SETGLOBAL: { -+ check(ttisstring(&pt->k[b])); -+ break; -+ } -+ case OP_SELF: { -+ checkreg(pt, a+1); -+ if (reg == a+1) last = pc; -+ break; -+ } -+ case OP_CONCAT: { -+ check(b < c); /* at least two operands */ -+ break; -+ } -+ case OP_TFORLOOP: { -+ check(c >= 1); /* at least one result (control variable) */ -+ checkreg(pt, a+2+c); /* space for results */ -+ if (reg >= a+2) last = pc; /* affect all regs above its base */ -+ break; -+ } -+ case OP_FORLOOP: -+ case OP_FORPREP: -+ checkreg(pt, a+3); -+ /* go through */ -+ case OP_JMP: { -+ int dest = pc+1+b; -+ /* not full check and jump is forward and do not skip `lastpc'? */ -+ if (reg != NO_REG && pc < dest && dest <= lastpc) -+ pc += b; /* do the jump */ -+ break; -+ } -+ case OP_CALL: -+ case OP_TAILCALL: { -+ if (b != 0) { -+ checkreg(pt, a+b-1); -+ } -+ c--; /* c = num. returns */ -+ if (c == LUA_MULTRET) { -+ check(checkopenop(pt, pc)); -+ } -+ else if (c != 0) -+ checkreg(pt, a+c-1); -+ if (reg >= a) last = pc; /* affect all registers above base */ -+ break; -+ } -+ case OP_RETURN: { -+ b--; /* b = num. returns */ -+ if (b > 0) checkreg(pt, a+b-1); -+ break; -+ } -+ case OP_SETLIST: { -+ if (b > 0) checkreg(pt, a + b); -+ if (c == 0) { -+ pc++; -+ check(pc < pt->sizecode - 1); -+ } -+ break; -+ } -+ case OP_CLOSURE: { -+ int nup, j; -+ check(b < pt->sizep); -+ nup = pt->p[b]->nups; -+ check(pc + nup < pt->sizecode); -+ for (j = 1; j <= nup; j++) { -+ OpCode op1 = GET_OPCODE(pt->code[pc + j]); -+ check(op1 == OP_GETUPVAL || op1 == OP_MOVE); -+ } -+ if (reg != NO_REG) /* tracing? */ -+ pc += nup; /* do not 'execute' these pseudo-instructions */ -+ break; -+ } -+ case OP_VARARG: { -+ check((pt->is_vararg & VARARG_ISVARARG) && -+ !(pt->is_vararg & VARARG_NEEDSARG)); -+ b--; -+ if (b == LUA_MULTRET) check(checkopenop(pt, pc)); -+ checkreg(pt, a+b-1); -+ break; -+ } -+ default: break; -+ } -+ } -+ return pt->code[last]; -+} -+ -+#undef check -+#undef checkjump -+#undef checkreg -+ -+/* }====================================================== */ -+ -+ -+int luaG_checkcode (const Proto *pt) { -+ return (symbexec(pt, pt->sizecode, NO_REG) != 0); -+} -+ -+ -+static const char *kname (Proto *p, int c) { -+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) -+ return svalue(&p->k[INDEXK(c)]); -+ else -+ return "?"; -+} -+ -+ -+static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, -+ const char **name) { -+ if (isLua(ci)) { /* a Lua function? */ -+ Proto *p = ci_func(ci)->l.p; -+ int pc = currentpc(L, ci); -+ Instruction i; -+ *name = luaF_getlocalname(p, stackpos+1, pc); -+ if (*name) /* is a local? */ -+ return "local"; -+ i = symbexec(p, pc, stackpos); /* try symbolic execution */ -+ lua_assert(pc != -1); -+ switch (GET_OPCODE(i)) { -+ case OP_GETGLOBAL: { -+ int g = GETARG_Bx(i); /* global index */ -+ lua_assert(ttisstring(&p->k[g])); -+ *name = svalue(&p->k[g]); -+ return "global"; -+ } -+ case OP_MOVE: { -+ int a = GETARG_A(i); -+ int b = GETARG_B(i); /* move from `b' to `a' */ -+ if (b < a) -+ return getobjname(L, ci, b, name); /* get name for `b' */ -+ break; -+ } -+ case OP_GETTABLE: { -+ int k = GETARG_C(i); /* key index */ -+ *name = kname(p, k); -+ return "field"; -+ } -+ case OP_GETUPVAL: { -+ int u = GETARG_B(i); /* upvalue index */ -+ *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; -+ return "upvalue"; -+ } -+ case OP_SELF: { -+ int k = GETARG_C(i); /* key index */ -+ *name = kname(p, k); -+ return "method"; -+ } -+ default: break; -+ } -+ } -+ return NULL; /* no useful name found */ -+} -+ -+ -+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { -+ Instruction i; -+ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) -+ return NULL; /* calling function is not Lua (or is unknown) */ -+ ci--; /* calling function */ -+ i = ci_func(ci)->l.p->code[currentpc(L, ci)]; -+ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || -+ GET_OPCODE(i) == OP_TFORLOOP) -+ return getobjname(L, ci, GETARG_A(i), name); -+ else -+ return NULL; /* no useful name can be found */ -+} -+ -+ -+/* only ANSI way to check whether a pointer points to an array */ -+static int isinstack (CallInfo *ci, const TValue *o) { -+ StkId p; -+ for (p = ci->base; p < ci->top; p++) -+ if (o == p) return 1; -+ return 0; -+} -+ -+ -+void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { -+ const char *name = NULL; -+ const char *t = luaT_typenames[ttype(o)]; -+ const char *kind = (isinstack(L->ci, o)) ? -+ getobjname(L, L->ci, cast_int(o - L->base), &name) : -+ NULL; -+ if (kind) -+ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", -+ op, kind, name, t); -+ else -+ luaG_runerror(L, "attempt to %s a %s value", op, t); -+} -+ -+ -+void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { -+ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; -+ lua_assert(!ttisstring(p1) && !ttisnumber(p1)); -+ luaG_typeerror(L, p1, "concatenate"); -+} -+ -+ -+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { -+ TValue temp; -+ if (luaV_tonumber(p1, &temp) == NULL) -+ p2 = p1; /* first operand is wrong */ -+ luaG_typeerror(L, p2, "perform arithmetic on"); -+} -+ -+ -+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { -+ const char *t1 = luaT_typenames[ttype(p1)]; -+ const char *t2 = luaT_typenames[ttype(p2)]; -+ if (t1[2] == t2[2]) -+ luaG_runerror(L, "attempt to compare two %s values", t1); -+ else -+ luaG_runerror(L, "attempt to compare %s with %s", t1, t2); -+ return 0; -+} -+ -+ -+static void addinfo (lua_State *L, const char *msg) { -+ CallInfo *ci = L->ci; -+ if (isLua(ci)) { /* is Lua code? */ -+ char buff[LUA_IDSIZE]; /* add file:line information */ -+ int line = currentline(L, ci); -+ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); -+ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); -+ } -+} -+ -+ -+void luaG_errormsg (lua_State *L) { -+ if (L->errfunc != 0) { /* is there an error handling function? */ -+ StkId errfunc = restorestack(L, L->errfunc); -+ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); -+ setobjs2s(L, L->top, L->top - 1); /* move argument */ -+ setobjs2s(L, L->top - 1, errfunc); /* push function */ -+ incr_top(L); -+ luaD_call(L, L->top - 2, 1); /* call it */ -+ } -+ luaD_throw(L, LUA_ERRRUN); -+} -+ -+ -+void luaG_runerror (lua_State *L, const char *fmt, ...) { -+ va_list argp; -+ va_start(argp, fmt); -+ addinfo(L, luaO_pushvfstring(L, fmt, argp)); -+ va_end(argp); -+ luaG_errormsg(L); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/ldebug.h -@@ -0,0 +1,33 @@ -+/* -+** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions from Debug Interface module -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ldebug_h -+#define ldebug_h -+ -+ -+#include "lstate.h" -+ -+ -+#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) -+ -+#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) -+ -+#define resethookcount(L) (L->hookcount = L->basehookcount) -+ -+ -+LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, -+ const char *opname); -+LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); -+LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, -+ const TValue *p2); -+LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, -+ const TValue *p2); -+LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); -+LUAI_FUNC void luaG_errormsg (lua_State *L); -+LUAI_FUNC int luaG_checkcode (const Proto *pt); -+LUAI_FUNC int luaG_checkopenop (Instruction i); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ldo.c -@@ -0,0 +1,515 @@ -+/* -+** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ -+** Stack and Call structure of Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+ -+#define ldo_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lundump.h" -+#include "lvm.h" -+#include "lzio.h" -+ -+ -+ -+/* -+** {====================================================== -+** Error-recovery functions -+** ======================================================= -+*/ -+ -+ -+/* chain list of long jump buffers */ -+struct lua_longjmp { -+ struct lua_longjmp *previous; -+ luai_jmpbuf b; -+ volatile int status; /* error code */ -+}; -+ -+ -+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { -+ switch (errcode) { -+ case LUA_ERRMEM: { -+ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); -+ break; -+ } -+ case LUA_ERRERR: { -+ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); -+ break; -+ } -+ case LUA_ERRSYNTAX: -+ case LUA_ERRRUN: { -+ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ -+ break; -+ } -+ } -+ L->top = oldtop + 1; -+} -+ -+ -+static void restore_stack_limit (lua_State *L) { -+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); -+ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ -+ int inuse = cast_int(L->ci - L->base_ci); -+ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ -+ luaD_reallocCI(L, LUAI_MAXCALLS); -+ } -+} -+ -+ -+static void resetstack (lua_State *L, int status) { -+ L->ci = L->base_ci; -+ L->base = L->ci->base; -+ luaF_close(L, L->base); /* close eventual pending closures */ -+ luaD_seterrorobj(L, status, L->base); -+ L->nCcalls = L->baseCcalls; -+ L->allowhook = 1; -+ restore_stack_limit(L); -+ L->errfunc = 0; -+ L->errorJmp = NULL; -+} -+ -+ -+void luaD_throw (lua_State *L, int errcode) { -+ if (L->errorJmp) { -+ L->errorJmp->status = errcode; -+ LUAI_THROW(L, L->errorJmp); -+ } -+ else { -+ L->status = cast_byte(errcode); -+ if (G(L)->panic) { -+ resetstack(L, errcode); -+ lua_unlock(L); -+ G(L)->panic(L); -+ } -+ exit(EXIT_FAILURE); -+ } -+} -+ -+ -+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { -+ struct lua_longjmp lj; -+ lj.status = 0; -+ lj.previous = L->errorJmp; /* chain new error handler */ -+ L->errorJmp = &lj; -+ LUAI_TRY(L, &lj, -+ (*f)(L, ud); -+ ); -+ L->errorJmp = lj.previous; /* restore old error handler */ -+ return lj.status; -+} -+ -+/* }====================================================== */ -+ -+ -+static void correctstack (lua_State *L, TValue *oldstack) { -+ CallInfo *ci; -+ GCObject *up; -+ L->top = (L->top - oldstack) + L->stack; -+ for (up = L->openupval; up != NULL; up = up->gch.next) -+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; -+ for (ci = L->base_ci; ci <= L->ci; ci++) { -+ ci->top = (ci->top - oldstack) + L->stack; -+ ci->base = (ci->base - oldstack) + L->stack; -+ ci->func = (ci->func - oldstack) + L->stack; -+ } -+ L->base = (L->base - oldstack) + L->stack; -+} -+ -+ -+void luaD_reallocstack (lua_State *L, int newsize) { -+ TValue *oldstack = L->stack; -+ int realsize = newsize + 1 + EXTRA_STACK; -+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); -+ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); -+ L->stacksize = realsize; -+ L->stack_last = L->stack+newsize; -+ correctstack(L, oldstack); -+} -+ -+ -+void luaD_reallocCI (lua_State *L, int newsize) { -+ CallInfo *oldci = L->base_ci; -+ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); -+ L->size_ci = newsize; -+ L->ci = (L->ci - oldci) + L->base_ci; -+ L->end_ci = L->base_ci + L->size_ci - 1; -+} -+ -+ -+void luaD_growstack (lua_State *L, int n) { -+ if (n <= L->stacksize) /* double size is enough? */ -+ luaD_reallocstack(L, 2*L->stacksize); -+ else -+ luaD_reallocstack(L, L->stacksize + n); -+} -+ -+ -+static CallInfo *growCI (lua_State *L) { -+ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ -+ luaD_throw(L, LUA_ERRERR); -+ else { -+ luaD_reallocCI(L, 2*L->size_ci); -+ if (L->size_ci > LUAI_MAXCALLS) -+ luaG_runerror(L, "stack overflow"); -+ } -+ return ++L->ci; -+} -+ -+ -+void luaD_callhook (lua_State *L, int event, int line) { -+ lua_Hook hook = L->hook; -+ if (hook && L->allowhook) { -+ ptrdiff_t top = savestack(L, L->top); -+ ptrdiff_t ci_top = savestack(L, L->ci->top); -+ lua_Debug ar; -+ ar.event = event; -+ ar.currentline = line; -+ if (event == LUA_HOOKTAILRET) -+ ar.i_ci = 0; /* tail call; no debug information about it */ -+ else -+ ar.i_ci = cast_int(L->ci - L->base_ci); -+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ -+ L->ci->top = L->top + LUA_MINSTACK; -+ lua_assert(L->ci->top <= L->stack_last); -+ L->allowhook = 0; /* cannot call hooks inside a hook */ -+ lua_unlock(L); -+ (*hook)(L, &ar); -+ lua_lock(L); -+ lua_assert(!L->allowhook); -+ L->allowhook = 1; -+ L->ci->top = restorestack(L, ci_top); -+ L->top = restorestack(L, top); -+ } -+} -+ -+ -+static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { -+ int i; -+ int nfixargs = p->numparams; -+ Table *htab = NULL; -+ StkId base, fixed; -+ for (; actual < nfixargs; ++actual) -+ setnilvalue(L->top++); -+#if defined(LUA_COMPAT_VARARG) -+ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ -+ int nvar = actual - nfixargs; /* number of extra arguments */ -+ lua_assert(p->is_vararg & VARARG_HASARG); -+ luaC_checkGC(L); -+ htab = luaH_new(L, nvar, 1); /* create `arg' table */ -+ for (i=0; itop - nvar + i); -+ /* store counter in field `n' */ -+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); -+ } -+#endif -+ /* move fixed parameters to final position */ -+ fixed = L->top - actual; /* first fixed argument */ -+ base = L->top; /* final position of first argument */ -+ for (i=0; itop++, fixed+i); -+ setnilvalue(fixed+i); -+ } -+ /* add `arg' parameter */ -+ if (htab) { -+ sethvalue(L, L->top++, htab); -+ lua_assert(iswhite(obj2gco(htab))); -+ } -+ return base; -+} -+ -+ -+static StkId tryfuncTM (lua_State *L, StkId func) { -+ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); -+ StkId p; -+ ptrdiff_t funcr = savestack(L, func); -+ if (!ttisfunction(tm)) -+ luaG_typeerror(L, func, "call"); -+ /* Open a hole inside the stack at `func' */ -+ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); -+ incr_top(L); -+ func = restorestack(L, funcr); /* previous call may change stack */ -+ setobj2s(L, func, tm); /* tag method is the new function to be called */ -+ return func; -+} -+ -+ -+ -+#define inc_ci(L) \ -+ ((L->ci == L->end_ci) ? growCI(L) : \ -+ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) -+ -+ -+int luaD_precall (lua_State *L, StkId func, int nresults) { -+ LClosure *cl; -+ ptrdiff_t funcr; -+ if (!ttisfunction(func)) /* `func' is not a function? */ -+ func = tryfuncTM(L, func); /* check the `function' tag method */ -+ funcr = savestack(L, func); -+ cl = &clvalue(func)->l; -+ L->ci->savedpc = L->savedpc; -+ if (!cl->isC) { /* Lua function? prepare its call */ -+ CallInfo *ci; -+ StkId st, base; -+ Proto *p = cl->p; -+ luaD_checkstack(L, p->maxstacksize); -+ func = restorestack(L, funcr); -+ if (!p->is_vararg) { /* no varargs? */ -+ base = func + 1; -+ if (L->top > base + p->numparams) -+ L->top = base + p->numparams; -+ } -+ else { /* vararg function */ -+ int nargs = cast_int(L->top - func) - 1; -+ base = adjust_varargs(L, p, nargs); -+ func = restorestack(L, funcr); /* previous call may change the stack */ -+ } -+ ci = inc_ci(L); /* now `enter' new function */ -+ ci->func = func; -+ L->base = ci->base = base; -+ ci->top = L->base + p->maxstacksize; -+ lua_assert(ci->top <= L->stack_last); -+ L->savedpc = p->code; /* starting point */ -+ ci->tailcalls = 0; -+ ci->nresults = nresults; -+ for (st = L->top; st < ci->top; st++) -+ setnilvalue(st); -+ L->top = ci->top; -+ if (L->hookmask & LUA_MASKCALL) { -+ L->savedpc++; /* hooks assume 'pc' is already incremented */ -+ luaD_callhook(L, LUA_HOOKCALL, -1); -+ L->savedpc--; /* correct 'pc' */ -+ } -+ return PCRLUA; -+ } -+ else { /* if is a C function, call it */ -+ CallInfo *ci; -+ int n; -+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ -+ ci = inc_ci(L); /* now `enter' new function */ -+ ci->func = restorestack(L, funcr); -+ L->base = ci->base = ci->func + 1; -+ ci->top = L->top + LUA_MINSTACK; -+ lua_assert(ci->top <= L->stack_last); -+ ci->nresults = nresults; -+ if (L->hookmask & LUA_MASKCALL) -+ luaD_callhook(L, LUA_HOOKCALL, -1); -+ lua_unlock(L); -+ n = (*curr_func(L)->c.f)(L); /* do the actual call */ -+ lua_lock(L); -+ if (n < 0) /* yielding? */ -+ return PCRYIELD; -+ else { -+ luaD_poscall(L, L->top - n); -+ return PCRC; -+ } -+ } -+} -+ -+ -+static StkId callrethooks (lua_State *L, StkId firstResult) { -+ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ -+ luaD_callhook(L, LUA_HOOKRET, -1); -+ if (f_isLua(L->ci)) { /* Lua function? */ -+ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ -+ luaD_callhook(L, LUA_HOOKTAILRET, -1); -+ } -+ return restorestack(L, fr); -+} -+ -+ -+int luaD_poscall (lua_State *L, StkId firstResult) { -+ StkId res; -+ int wanted, i; -+ CallInfo *ci; -+ if (L->hookmask & LUA_MASKRET) -+ firstResult = callrethooks(L, firstResult); -+ ci = L->ci--; -+ res = ci->func; /* res == final position of 1st result */ -+ wanted = ci->nresults; -+ L->base = (ci - 1)->base; /* restore base */ -+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ -+ /* move results to correct place */ -+ for (i = wanted; i != 0 && firstResult < L->top; i--) -+ setobjs2s(L, res++, firstResult++); -+ while (i-- > 0) -+ setnilvalue(res++); -+ L->top = res; -+ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ -+} -+ -+ -+/* -+** Call a function (C or Lua). The function to be called is at *func. -+** The arguments are on the stack, right after the function. -+** When returns, all the results are on the stack, starting at the original -+** function position. -+*/ -+void luaD_call (lua_State *L, StkId func, int nResults) { -+ if (++L->nCcalls >= LUAI_MAXCCALLS) { -+ if (L->nCcalls == LUAI_MAXCCALLS) -+ luaG_runerror(L, "C stack overflow"); -+ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) -+ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ -+ } -+ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ -+ luaV_execute(L, 1); /* call it */ -+ L->nCcalls--; -+ luaC_checkGC(L); -+} -+ -+ -+static void resume (lua_State *L, void *ud) { -+ StkId firstArg = cast(StkId, ud); -+ CallInfo *ci = L->ci; -+ if (L->status == 0) { /* start coroutine? */ -+ lua_assert(ci == L->base_ci && firstArg > L->base); -+ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) -+ return; -+ } -+ else { /* resuming from previous yield */ -+ lua_assert(L->status == LUA_YIELD); -+ L->status = 0; -+ if (!f_isLua(ci)) { /* `common' yield? */ -+ /* finish interrupted execution of `OP_CALL' */ -+ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || -+ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); -+ if (luaD_poscall(L, firstArg)) /* complete it... */ -+ L->top = L->ci->top; /* and correct top if not multiple results */ -+ } -+ else /* yielded inside a hook: just continue its execution */ -+ L->base = L->ci->base; -+ } -+ luaV_execute(L, cast_int(L->ci - L->base_ci)); -+} -+ -+ -+static int resume_error (lua_State *L, const char *msg) { -+ L->top = L->ci->base; -+ setsvalue2s(L, L->top, luaS_new(L, msg)); -+ incr_top(L); -+ lua_unlock(L); -+ return LUA_ERRRUN; -+} -+ -+ -+LUA_API int lua_resume (lua_State *L, int nargs) { -+ int status; -+ lua_lock(L); -+ if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) -+ return resume_error(L, "cannot resume non-suspended coroutine"); -+ if (L->nCcalls >= LUAI_MAXCCALLS) -+ return resume_error(L, "C stack overflow"); -+ luai_userstateresume(L, nargs); -+ lua_assert(L->errfunc == 0); -+ L->baseCcalls = ++L->nCcalls; -+ status = luaD_rawrunprotected(L, resume, L->top - nargs); -+ if (status != 0) { /* error? */ -+ L->status = cast_byte(status); /* mark thread as `dead' */ -+ luaD_seterrorobj(L, status, L->top); -+ L->ci->top = L->top; -+ } -+ else { -+ lua_assert(L->nCcalls == L->baseCcalls); -+ status = L->status; -+ } -+ --L->nCcalls; -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_yield (lua_State *L, int nresults) { -+ luai_userstateyield(L, nresults); -+ lua_lock(L); -+ if (L->nCcalls > L->baseCcalls) -+ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); -+ L->base = L->top - nresults; /* protect stack slots below */ -+ L->status = LUA_YIELD; -+ lua_unlock(L); -+ return -1; -+} -+ -+ -+int luaD_pcall (lua_State *L, Pfunc func, void *u, -+ ptrdiff_t old_top, ptrdiff_t ef) { -+ int status; -+ unsigned short oldnCcalls = L->nCcalls; -+ ptrdiff_t old_ci = saveci(L, L->ci); -+ lu_byte old_allowhooks = L->allowhook; -+ ptrdiff_t old_errfunc = L->errfunc; -+ L->errfunc = ef; -+ status = luaD_rawrunprotected(L, func, u); -+ if (status != 0) { /* an error occurred? */ -+ StkId oldtop = restorestack(L, old_top); -+ luaF_close(L, oldtop); /* close eventual pending closures */ -+ luaD_seterrorobj(L, status, oldtop); -+ L->nCcalls = oldnCcalls; -+ L->ci = restoreci(L, old_ci); -+ L->base = L->ci->base; -+ L->savedpc = L->ci->savedpc; -+ L->allowhook = old_allowhooks; -+ restore_stack_limit(L); -+ } -+ L->errfunc = old_errfunc; -+ return status; -+} -+ -+ -+ -+/* -+** Execute a protected parser. -+*/ -+struct SParser { /* data to `f_parser' */ -+ ZIO *z; -+ Mbuffer buff; /* buffer to be used by the scanner */ -+ const char *name; -+}; -+ -+static void f_parser (lua_State *L, void *ud) { -+ int i; -+ Proto *tf; -+ Closure *cl; -+ struct SParser *p = cast(struct SParser *, ud); -+ int c = luaZ_lookahead(p->z); -+ luaC_checkGC(L); -+ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, -+ &p->buff, p->name); -+ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); -+ cl->l.p = tf; -+ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ -+ cl->l.upvals[i] = luaF_newupval(L); -+ setclvalue(L, L->top, cl); -+ incr_top(L); -+} -+ -+ -+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { -+ struct SParser p; -+ int status; -+ p.z = z; p.name = name; -+ luaZ_initbuffer(L, &p.buff); -+ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); -+ luaZ_freebuffer(L, &p.buff); -+ return status; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/ldo.h -@@ -0,0 +1,57 @@ -+/* -+** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Stack and Call structure of Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ldo_h -+#define ldo_h -+ -+ -+#include "lobject.h" -+#include "lstate.h" -+#include "lzio.h" -+ -+ -+#define luaD_checkstack(L,n) \ -+ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ -+ luaD_growstack(L, n); \ -+ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); -+ -+ -+#define incr_top(L) {luaD_checkstack(L,1); L->top++;} -+ -+#define savestack(L,p) ((char *)(p) - (char *)L->stack) -+#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) -+ -+#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) -+#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) -+ -+ -+/* results from luaD_precall */ -+#define PCRLUA 0 /* initiated a call to a Lua function */ -+#define PCRC 1 /* did a call to a C function */ -+#define PCRYIELD 2 /* C funtion yielded */ -+ -+ -+/* type of protected functions, to be ran by `runprotected' */ -+typedef void (*Pfunc) (lua_State *L, void *ud); -+ -+LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); -+LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); -+LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); -+LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, -+ ptrdiff_t oldtop, ptrdiff_t ef); -+LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); -+LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); -+LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -+LUAI_FUNC void luaD_growstack (lua_State *L, int n); -+ -+LUAI_FUNC void luaD_throw (lua_State *L, int errcode); -+LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); -+ -+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/ldump.c -@@ -0,0 +1,164 @@ -+/* -+** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -+** save precompiled Lua chunks -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define ldump_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lobject.h" -+#include "lstate.h" -+#include "lundump.h" -+ -+typedef struct { -+ lua_State* L; -+ lua_Writer writer; -+ void* data; -+ int strip; -+ int status; -+} DumpState; -+ -+#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -+#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) -+ -+static void DumpBlock(const void* b, size_t size, DumpState* D) -+{ -+ if (D->status==0) -+ { -+ lua_unlock(D->L); -+ D->status=(*D->writer)(D->L,b,size,D->data); -+ lua_lock(D->L); -+ } -+} -+ -+static void DumpChar(int y, DumpState* D) -+{ -+ char x=(char)y; -+ DumpVar(x,D); -+} -+ -+static void DumpInt(int x, DumpState* D) -+{ -+ DumpVar(x,D); -+} -+ -+static void DumpNumber(lua_Number x, DumpState* D) -+{ -+ DumpVar(x,D); -+} -+ -+static void DumpVector(const void* b, int n, size_t size, DumpState* D) -+{ -+ DumpInt(n,D); -+ DumpMem(b,n,size,D); -+} -+ -+static void DumpString(const TString* s, DumpState* D) -+{ -+ if (s==NULL || getstr(s)==NULL) -+ { -+ size_t size=0; -+ DumpVar(size,D); -+ } -+ else -+ { -+ size_t size=s->tsv.len+1; /* include trailing '\0' */ -+ DumpVar(size,D); -+ DumpBlock(getstr(s),size,D); -+ } -+} -+ -+#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) -+ -+static void DumpFunction(const Proto* f, const TString* p, DumpState* D); -+ -+static void DumpConstants(const Proto* f, DumpState* D) -+{ -+ int i,n=f->sizek; -+ DumpInt(n,D); -+ for (i=0; ik[i]; -+ DumpChar(ttype(o),D); -+ switch (ttype(o)) -+ { -+ case LUA_TNIL: -+ break; -+ case LUA_TBOOLEAN: -+ DumpChar(bvalue(o),D); -+ break; -+ case LUA_TNUMBER: -+ DumpNumber(nvalue(o),D); -+ break; -+ case LUA_TSTRING: -+ DumpString(rawtsvalue(o),D); -+ break; -+ default: -+ lua_assert(0); /* cannot happen */ -+ break; -+ } -+ } -+ n=f->sizep; -+ DumpInt(n,D); -+ for (i=0; ip[i],f->source,D); -+} -+ -+static void DumpDebug(const Proto* f, DumpState* D) -+{ -+ int i,n; -+ n= (D->strip) ? 0 : f->sizelineinfo; -+ DumpVector(f->lineinfo,n,sizeof(int),D); -+ n= (D->strip) ? 0 : f->sizelocvars; -+ DumpInt(n,D); -+ for (i=0; ilocvars[i].varname,D); -+ DumpInt(f->locvars[i].startpc,D); -+ DumpInt(f->locvars[i].endpc,D); -+ } -+ n= (D->strip) ? 0 : f->sizeupvalues; -+ DumpInt(n,D); -+ for (i=0; iupvalues[i],D); -+} -+ -+static void DumpFunction(const Proto* f, const TString* p, DumpState* D) -+{ -+ DumpString((f->source==p || D->strip) ? NULL : f->source,D); -+ DumpInt(f->linedefined,D); -+ DumpInt(f->lastlinedefined,D); -+ DumpChar(f->nups,D); -+ DumpChar(f->numparams,D); -+ DumpChar(f->is_vararg,D); -+ DumpChar(f->maxstacksize,D); -+ DumpCode(f,D); -+ DumpConstants(f,D); -+ DumpDebug(f,D); -+} -+ -+static void DumpHeader(DumpState* D) -+{ -+ char h[LUAC_HEADERSIZE]; -+ luaU_header(h); -+ DumpBlock(h,LUAC_HEADERSIZE,D); -+} -+ -+/* -+** dump Lua function as precompiled chunk -+*/ -+int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -+{ -+ DumpState D; -+ D.L=L; -+ D.writer=w; -+ D.data=data; -+ D.strip=strip; -+ D.status=0; -+ DumpHeader(&D); -+ DumpFunction(f,NULL,&D); -+ return D.status; -+} ---- /dev/null -+++ b/extensions/LUA/lua/lfunc.c -@@ -0,0 +1,174 @@ -+/* -+** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ -+** Auxiliary functions to manipulate prototypes and closures -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lfunc_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+ -+ -+ -+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { -+ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); -+ luaC_link(L, obj2gco(c), LUA_TFUNCTION); -+ c->c.isC = 1; -+ c->c.env = e; -+ c->c.nupvalues = cast_byte(nelems); -+ return c; -+} -+ -+ -+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { -+ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); -+ luaC_link(L, obj2gco(c), LUA_TFUNCTION); -+ c->l.isC = 0; -+ c->l.env = e; -+ c->l.nupvalues = cast_byte(nelems); -+ while (nelems--) c->l.upvals[nelems] = NULL; -+ return c; -+} -+ -+ -+UpVal *luaF_newupval (lua_State *L) { -+ UpVal *uv = luaM_new(L, UpVal); -+ luaC_link(L, obj2gco(uv), LUA_TUPVAL); -+ uv->v = &uv->u.value; -+ setnilvalue(uv->v); -+ return uv; -+} -+ -+ -+UpVal *luaF_findupval (lua_State *L, StkId level) { -+ global_State *g = G(L); -+ GCObject **pp = &L->openupval; -+ UpVal *p; -+ UpVal *uv; -+ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { -+ lua_assert(p->v != &p->u.value); -+ if (p->v == level) { /* found a corresponding upvalue? */ -+ if (isdead(g, obj2gco(p))) /* is it dead? */ -+ changewhite(obj2gco(p)); /* ressurect it */ -+ return p; -+ } -+ pp = &p->next; -+ } -+ uv = luaM_new(L, UpVal); /* not found: create a new one */ -+ uv->tt = LUA_TUPVAL; -+ uv->marked = luaC_white(g); -+ uv->v = level; /* current value lives in the stack */ -+ uv->next = *pp; /* chain it in the proper position */ -+ *pp = obj2gco(uv); -+ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ -+ uv->u.l.next = g->uvhead.u.l.next; -+ uv->u.l.next->u.l.prev = uv; -+ g->uvhead.u.l.next = uv; -+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); -+ return uv; -+} -+ -+ -+static void unlinkupval (UpVal *uv) { -+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); -+ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ -+ uv->u.l.prev->u.l.next = uv->u.l.next; -+} -+ -+ -+void luaF_freeupval (lua_State *L, UpVal *uv) { -+ if (uv->v != &uv->u.value) /* is it open? */ -+ unlinkupval(uv); /* remove from open list */ -+ luaM_free(L, uv); /* free upvalue */ -+} -+ -+ -+void luaF_close (lua_State *L, StkId level) { -+ UpVal *uv; -+ global_State *g = G(L); -+ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { -+ GCObject *o = obj2gco(uv); -+ lua_assert(!isblack(o) && uv->v != &uv->u.value); -+ L->openupval = uv->next; /* remove from `open' list */ -+ if (isdead(g, o)) -+ luaF_freeupval(L, uv); /* free upvalue */ -+ else { -+ unlinkupval(uv); -+ setobj(L, &uv->u.value, uv->v); -+ uv->v = &uv->u.value; /* now current value lives here */ -+ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ -+ } -+ } -+} -+ -+ -+Proto *luaF_newproto (lua_State *L) { -+ Proto *f = luaM_new(L, Proto); -+ luaC_link(L, obj2gco(f), LUA_TPROTO); -+ f->k = NULL; -+ f->sizek = 0; -+ f->p = NULL; -+ f->sizep = 0; -+ f->code = NULL; -+ f->sizecode = 0; -+ f->sizelineinfo = 0; -+ f->sizeupvalues = 0; -+ f->nups = 0; -+ f->upvalues = NULL; -+ f->numparams = 0; -+ f->is_vararg = 0; -+ f->maxstacksize = 0; -+ f->lineinfo = NULL; -+ f->sizelocvars = 0; -+ f->locvars = NULL; -+ f->linedefined = 0; -+ f->lastlinedefined = 0; -+ f->source = NULL; -+ return f; -+} -+ -+ -+void luaF_freeproto (lua_State *L, Proto *f) { -+ luaM_freearray(L, f->code, f->sizecode, Instruction); -+ luaM_freearray(L, f->p, f->sizep, Proto *); -+ luaM_freearray(L, f->k, f->sizek, TValue); -+ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); -+ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); -+ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); -+ luaM_free(L, f); -+} -+ -+ -+void luaF_freeclosure (lua_State *L, Closure *c) { -+ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : -+ sizeLclosure(c->l.nupvalues); -+ luaM_freemem(L, c, size); -+} -+ -+ -+/* -+** Look for n-th local variable at line `line' in function `func'. -+** Returns NULL if not found. -+*/ -+const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { -+ int i; -+ for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { -+ if (pc < f->locvars[i].endpc) { /* is variable active? */ -+ local_number--; -+ if (local_number == 0) -+ return getstr(f->locvars[i].varname); -+ } -+ } -+ return NULL; /* not found */ -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lfunc.h -@@ -0,0 +1,34 @@ -+/* -+** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions to manipulate prototypes and closures -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lfunc_h -+#define lfunc_h -+ -+ -+#include "lobject.h" -+ -+ -+#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ -+ cast(int, sizeof(TValue)*((n)-1))) -+ -+#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ -+ cast(int, sizeof(TValue *)*((n)-1))) -+ -+ -+LUAI_FUNC Proto *luaF_newproto (lua_State *L); -+LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); -+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); -+LUAI_FUNC UpVal *luaF_newupval (lua_State *L); -+LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -+LUAI_FUNC void luaF_close (lua_State *L, StkId level); -+LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -+LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); -+LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); -+LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, -+ int pc); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lgc.c -@@ -0,0 +1,711 @@ -+/* -+** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Garbage Collector -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lgc_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+ -+ -+#define GCSTEPSIZE 1024u -+#define GCSWEEPMAX 40 -+#define GCSWEEPCOST 10 -+#define GCFINALIZECOST 100 -+ -+ -+#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) -+ -+#define makewhite(g,x) \ -+ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) -+ -+#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -+#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) -+ -+#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) -+ -+ -+#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -+#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) -+ -+ -+#define KEYWEAK bitmask(KEYWEAKBIT) -+#define VALUEWEAK bitmask(VALUEWEAKBIT) -+ -+ -+ -+#define markvalue(g,o) { checkconsistency(o); \ -+ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } -+ -+#define markobject(g,t) { if (iswhite(obj2gco(t))) \ -+ reallymarkobject(g, obj2gco(t)); } -+ -+ -+#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) -+ -+ -+static void removeentry (Node *n) { -+ lua_assert(ttisnil(gval(n))); -+ if (iscollectable(gkey(n))) -+ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ -+} -+ -+ -+static void reallymarkobject (global_State *g, GCObject *o) { -+ lua_assert(iswhite(o) && !isdead(g, o)); -+ white2gray(o); -+ switch (o->gch.tt) { -+ case LUA_TSTRING: { -+ return; -+ } -+ case LUA_TUSERDATA: { -+ Table *mt = gco2u(o)->metatable; -+ gray2black(o); /* udata are never gray */ -+ if (mt) markobject(g, mt); -+ markobject(g, gco2u(o)->env); -+ return; -+ } -+ case LUA_TUPVAL: { -+ UpVal *uv = gco2uv(o); -+ markvalue(g, uv->v); -+ if (uv->v == &uv->u.value) /* closed? */ -+ gray2black(o); /* open upvalues are never black */ -+ return; -+ } -+ case LUA_TFUNCTION: { -+ gco2cl(o)->c.gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ case LUA_TTABLE: { -+ gco2h(o)->gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ case LUA_TTHREAD: { -+ gco2th(o)->gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ case LUA_TPROTO: { -+ gco2p(o)->gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ default: lua_assert(0); -+ } -+} -+ -+ -+static void marktmu (global_State *g) { -+ GCObject *u = g->tmudata; -+ if (u) { -+ do { -+ u = u->gch.next; -+ makewhite(g, u); /* may be marked, if left from previous GC */ -+ reallymarkobject(g, u); -+ } while (u != g->tmudata); -+ } -+} -+ -+ -+/* move `dead' udata that need finalization to list `tmudata' */ -+size_t luaC_separateudata (lua_State *L, int all) { -+ global_State *g = G(L); -+ size_t deadmem = 0; -+ GCObject **p = &g->mainthread->next; -+ GCObject *curr; -+ while ((curr = *p) != NULL) { -+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) -+ p = &curr->gch.next; /* don't bother with them */ -+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { -+ markfinalized(gco2u(curr)); /* don't need finalization */ -+ p = &curr->gch.next; -+ } -+ else { /* must call its gc method */ -+ deadmem += sizeudata(gco2u(curr)); -+ markfinalized(gco2u(curr)); -+ *p = curr->gch.next; -+ /* link `curr' at the end of `tmudata' list */ -+ if (g->tmudata == NULL) /* list is empty? */ -+ g->tmudata = curr->gch.next = curr; /* creates a circular list */ -+ else { -+ curr->gch.next = g->tmudata->gch.next; -+ g->tmudata->gch.next = curr; -+ g->tmudata = curr; -+ } -+ } -+ } -+ return deadmem; -+} -+ -+ -+static int traversetable (global_State *g, Table *h) { -+ int i; -+ int weakkey = 0; -+ int weakvalue = 0; -+ const TValue *mode; -+ if (h->metatable) -+ markobject(g, h->metatable); -+ mode = gfasttm(g, h->metatable, TM_MODE); -+ if (mode && ttisstring(mode)) { /* is there a weak mode? */ -+ weakkey = (strchr(svalue(mode), 'k') != NULL); -+ weakvalue = (strchr(svalue(mode), 'v') != NULL); -+ if (weakkey || weakvalue) { /* is really weak? */ -+ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ -+ h->marked |= cast_byte((weakkey << KEYWEAKBIT) | -+ (weakvalue << VALUEWEAKBIT)); -+ h->gclist = g->weak; /* must be cleared after GC, ... */ -+ g->weak = obj2gco(h); /* ... so put in the appropriate list */ -+ } -+ } -+ if (weakkey && weakvalue) return 1; -+ if (!weakvalue) { -+ i = h->sizearray; -+ while (i--) -+ markvalue(g, &h->array[i]); -+ } -+ i = sizenode(h); -+ while (i--) { -+ Node *n = gnode(h, i); -+ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); -+ if (ttisnil(gval(n))) -+ removeentry(n); /* remove empty entries */ -+ else { -+ lua_assert(!ttisnil(gkey(n))); -+ if (!weakkey) markvalue(g, gkey(n)); -+ if (!weakvalue) markvalue(g, gval(n)); -+ } -+ } -+ return weakkey || weakvalue; -+} -+ -+ -+/* -+** All marks are conditional because a GC may happen while the -+** prototype is still being created -+*/ -+static void traverseproto (global_State *g, Proto *f) { -+ int i; -+ if (f->source) stringmark(f->source); -+ for (i=0; isizek; i++) /* mark literals */ -+ markvalue(g, &f->k[i]); -+ for (i=0; isizeupvalues; i++) { /* mark upvalue names */ -+ if (f->upvalues[i]) -+ stringmark(f->upvalues[i]); -+ } -+ for (i=0; isizep; i++) { /* mark nested protos */ -+ if (f->p[i]) -+ markobject(g, f->p[i]); -+ } -+ for (i=0; isizelocvars; i++) { /* mark local-variable names */ -+ if (f->locvars[i].varname) -+ stringmark(f->locvars[i].varname); -+ } -+} -+ -+ -+ -+static void traverseclosure (global_State *g, Closure *cl) { -+ markobject(g, cl->c.env); -+ if (cl->c.isC) { -+ int i; -+ for (i=0; ic.nupvalues; i++) /* mark its upvalues */ -+ markvalue(g, &cl->c.upvalue[i]); -+ } -+ else { -+ int i; -+ lua_assert(cl->l.nupvalues == cl->l.p->nups); -+ markobject(g, cl->l.p); -+ for (i=0; il.nupvalues; i++) /* mark its upvalues */ -+ markobject(g, cl->l.upvals[i]); -+ } -+} -+ -+ -+static void checkstacksizes (lua_State *L, StkId max) { -+ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ -+ int s_used = cast_int(max - L->stack); /* part of stack in use */ -+ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ -+ return; /* do not touch the stacks */ -+ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) -+ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ -+ condhardstacktests(luaD_reallocCI(L, ci_used + 1)); -+ if (4*s_used < L->stacksize && -+ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) -+ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ -+ condhardstacktests(luaD_reallocstack(L, s_used)); -+} -+ -+ -+static void traversestack (global_State *g, lua_State *l) { -+ StkId o, lim; -+ CallInfo *ci; -+ markvalue(g, gt(l)); -+ lim = l->top; -+ for (ci = l->base_ci; ci <= l->ci; ci++) { -+ lua_assert(ci->top <= l->stack_last); -+ if (lim < ci->top) lim = ci->top; -+ } -+ for (o = l->stack; o < l->top; o++) -+ markvalue(g, o); -+ for (; o <= lim; o++) -+ setnilvalue(o); -+ checkstacksizes(l, lim); -+} -+ -+ -+/* -+** traverse one gray object, turning it to black. -+** Returns `quantity' traversed. -+*/ -+static l_mem propagatemark (global_State *g) { -+ GCObject *o = g->gray; -+ lua_assert(isgray(o)); -+ gray2black(o); -+ switch (o->gch.tt) { -+ case LUA_TTABLE: { -+ Table *h = gco2h(o); -+ g->gray = h->gclist; -+ if (traversetable(g, h)) /* table is weak? */ -+ black2gray(o); /* keep it gray */ -+ return sizeof(Table) + sizeof(TValue) * h->sizearray + -+ sizeof(Node) * sizenode(h); -+ } -+ case LUA_TFUNCTION: { -+ Closure *cl = gco2cl(o); -+ g->gray = cl->c.gclist; -+ traverseclosure(g, cl); -+ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : -+ sizeLclosure(cl->l.nupvalues); -+ } -+ case LUA_TTHREAD: { -+ lua_State *th = gco2th(o); -+ g->gray = th->gclist; -+ th->gclist = g->grayagain; -+ g->grayagain = o; -+ black2gray(o); -+ traversestack(g, th); -+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize + -+ sizeof(CallInfo) * th->size_ci; -+ } -+ case LUA_TPROTO: { -+ Proto *p = gco2p(o); -+ g->gray = p->gclist; -+ traverseproto(g, p); -+ return sizeof(Proto) + sizeof(Instruction) * p->sizecode + -+ sizeof(Proto *) * p->sizep + -+ sizeof(TValue) * p->sizek + -+ sizeof(int) * p->sizelineinfo + -+ sizeof(LocVar) * p->sizelocvars + -+ sizeof(TString *) * p->sizeupvalues; -+ } -+ default: lua_assert(0); return 0; -+ } -+} -+ -+ -+static size_t propagateall (global_State *g) { -+ size_t m = 0; -+ while (g->gray) m += propagatemark(g); -+ return m; -+} -+ -+ -+/* -+** The next function tells whether a key or value can be cleared from -+** a weak table. Non-collectable objects are never removed from weak -+** tables. Strings behave as `values', so are never removed too. for -+** other objects: if really collected, cannot keep them; for userdata -+** being finalized, keep them in keys, but not in values -+*/ -+static int iscleared (const TValue *o, int iskey) { -+ if (!iscollectable(o)) return 0; -+ if (ttisstring(o)) { -+ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ -+ return 0; -+ } -+ return iswhite(gcvalue(o)) || -+ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); -+} -+ -+ -+/* -+** clear collected entries from weaktables -+*/ -+static void cleartable (GCObject *l) { -+ while (l) { -+ Table *h = gco2h(l); -+ int i = h->sizearray; -+ lua_assert(testbit(h->marked, VALUEWEAKBIT) || -+ testbit(h->marked, KEYWEAKBIT)); -+ if (testbit(h->marked, VALUEWEAKBIT)) { -+ while (i--) { -+ TValue *o = &h->array[i]; -+ if (iscleared(o, 0)) /* value was collected? */ -+ setnilvalue(o); /* remove value */ -+ } -+ } -+ i = sizenode(h); -+ while (i--) { -+ Node *n = gnode(h, i); -+ if (!ttisnil(gval(n)) && /* non-empty entry? */ -+ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { -+ setnilvalue(gval(n)); /* remove value ... */ -+ removeentry(n); /* remove entry from table */ -+ } -+ } -+ l = h->gclist; -+ } -+} -+ -+ -+static void freeobj (lua_State *L, GCObject *o) { -+ switch (o->gch.tt) { -+ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; -+ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; -+ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; -+ case LUA_TTABLE: luaH_free(L, gco2h(o)); break; -+ case LUA_TTHREAD: { -+ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); -+ luaE_freethread(L, gco2th(o)); -+ break; -+ } -+ case LUA_TSTRING: { -+ G(L)->strt.nuse--; -+ luaM_freemem(L, o, sizestring(gco2ts(o))); -+ break; -+ } -+ case LUA_TUSERDATA: { -+ luaM_freemem(L, o, sizeudata(gco2u(o))); -+ break; -+ } -+ default: lua_assert(0); -+ } -+} -+ -+ -+ -+#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -+ -+ -+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { -+ GCObject *curr; -+ global_State *g = G(L); -+ int deadmask = otherwhite(g); -+ while ((curr = *p) != NULL && count-- > 0) { -+ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ -+ sweepwholelist(L, &gco2th(curr)->openupval); -+ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ -+ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); -+ makewhite(g, curr); /* make it white (for next cycle) */ -+ p = &curr->gch.next; -+ } -+ else { /* must erase `curr' */ -+ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); -+ *p = curr->gch.next; -+ if (curr == g->rootgc) /* is the first element of the list? */ -+ g->rootgc = curr->gch.next; /* adjust first */ -+ freeobj(L, curr); -+ } -+ } -+ return p; -+} -+ -+ -+static void checkSizes (lua_State *L) { -+ global_State *g = G(L); -+ /* check size of string hash */ -+ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && -+ g->strt.size > MINSTRTABSIZE*2) -+ luaS_resize(L, g->strt.size/2); /* table is too big */ -+ /* check size of buffer */ -+ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ -+ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; -+ luaZ_resizebuffer(L, &g->buff, newsize); -+ } -+} -+ -+ -+static void GCTM (lua_State *L) { -+ global_State *g = G(L); -+ GCObject *o = g->tmudata->gch.next; /* get first element */ -+ Udata *udata = rawgco2u(o); -+ const TValue *tm; -+ /* remove udata from `tmudata' */ -+ if (o == g->tmudata) /* last element? */ -+ g->tmudata = NULL; -+ else -+ g->tmudata->gch.next = udata->uv.next; -+ udata->uv.next = g->mainthread->next; /* return it to `root' list */ -+ g->mainthread->next = o; -+ makewhite(g, o); -+ tm = fasttm(L, udata->uv.metatable, TM_GC); -+ if (tm != NULL) { -+ lu_byte oldah = L->allowhook; -+ lu_mem oldt = g->GCthreshold; -+ L->allowhook = 0; /* stop debug hooks during GC tag method */ -+ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ -+ setobj2s(L, L->top, tm); -+ setuvalue(L, L->top+1, udata); -+ L->top += 2; -+ luaD_call(L, L->top - 2, 0); -+ L->allowhook = oldah; /* restore hooks */ -+ g->GCthreshold = oldt; /* restore threshold */ -+ } -+} -+ -+ -+/* -+** Call all GC tag methods -+*/ -+void luaC_callGCTM (lua_State *L) { -+ while (G(L)->tmudata) -+ GCTM(L); -+} -+ -+ -+void luaC_freeall (lua_State *L) { -+ global_State *g = G(L); -+ int i; -+ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ -+ sweepwholelist(L, &g->rootgc); -+ for (i = 0; i < g->strt.size; i++) /* free all string lists */ -+ sweepwholelist(L, &g->strt.hash[i]); -+} -+ -+ -+static void markmt (global_State *g) { -+ int i; -+ for (i=0; imt[i]) markobject(g, g->mt[i]); -+} -+ -+ -+/* mark root set */ -+static void markroot (lua_State *L) { -+ global_State *g = G(L); -+ g->gray = NULL; -+ g->grayagain = NULL; -+ g->weak = NULL; -+ markobject(g, g->mainthread); -+ /* make global table be traversed before main stack */ -+ markvalue(g, gt(g->mainthread)); -+ markvalue(g, registry(L)); -+ markmt(g); -+ g->gcstate = GCSpropagate; -+} -+ -+ -+static void remarkupvals (global_State *g) { -+ UpVal *uv; -+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { -+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); -+ if (isgray(obj2gco(uv))) -+ markvalue(g, uv->v); -+ } -+} -+ -+ -+static void atomic (lua_State *L) { -+ global_State *g = G(L); -+ size_t udsize; /* total size of userdata to be finalized */ -+ /* remark occasional upvalues of (maybe) dead threads */ -+ remarkupvals(g); -+ /* traverse objects cautch by write barrier and by 'remarkupvals' */ -+ propagateall(g); -+ /* remark weak tables */ -+ g->gray = g->weak; -+ g->weak = NULL; -+ lua_assert(!iswhite(obj2gco(g->mainthread))); -+ markobject(g, L); /* mark running thread */ -+ markmt(g); /* mark basic metatables (again) */ -+ propagateall(g); -+ /* remark gray again */ -+ g->gray = g->grayagain; -+ g->grayagain = NULL; -+ propagateall(g); -+ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ -+ marktmu(g); /* mark `preserved' userdata */ -+ udsize += propagateall(g); /* remark, to propagate `preserveness' */ -+ cleartable(g->weak); /* remove collected objects from weak tables */ -+ /* flip current white */ -+ g->currentwhite = cast_byte(otherwhite(g)); -+ g->sweepstrgc = 0; -+ g->sweepgc = &g->rootgc; -+ g->gcstate = GCSsweepstring; -+ g->estimate = g->totalbytes - udsize; /* first estimate */ -+} -+ -+ -+static l_mem singlestep (lua_State *L) { -+ global_State *g = G(L); -+ /*lua_checkmemory(L);*/ -+ switch (g->gcstate) { -+ case GCSpause: { -+ markroot(L); /* start a new collection */ -+ return 0; -+ } -+ case GCSpropagate: { -+ if (g->gray) -+ return propagatemark(g); -+ else { /* no more `gray' objects */ -+ atomic(L); /* finish mark phase */ -+ return 0; -+ } -+ } -+ case GCSsweepstring: { -+ lu_mem old = g->totalbytes; -+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); -+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ -+ g->gcstate = GCSsweep; /* end sweep-string phase */ -+ lua_assert(old >= g->totalbytes); -+ g->estimate -= old - g->totalbytes; -+ return GCSWEEPCOST; -+ } -+ case GCSsweep: { -+ lu_mem old = g->totalbytes; -+ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); -+ if (*g->sweepgc == NULL) { /* nothing more to sweep? */ -+ checkSizes(L); -+ g->gcstate = GCSfinalize; /* end sweep phase */ -+ } -+ lua_assert(old >= g->totalbytes); -+ g->estimate -= old - g->totalbytes; -+ return GCSWEEPMAX*GCSWEEPCOST; -+ } -+ case GCSfinalize: { -+ if (g->tmudata) { -+ GCTM(L); -+ if (g->estimate > GCFINALIZECOST) -+ g->estimate -= GCFINALIZECOST; -+ return GCFINALIZECOST; -+ } -+ else { -+ g->gcstate = GCSpause; /* end collection */ -+ g->gcdept = 0; -+ return 0; -+ } -+ } -+ default: lua_assert(0); return 0; -+ } -+} -+ -+ -+void luaC_step (lua_State *L) { -+ global_State *g = G(L); -+ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; -+ if (lim == 0) -+ lim = (MAX_LUMEM-1)/2; /* no limit */ -+ g->gcdept += g->totalbytes - g->GCthreshold; -+ do { -+ lim -= singlestep(L); -+ if (g->gcstate == GCSpause) -+ break; -+ } while (lim > 0); -+ if (g->gcstate != GCSpause) { -+ if (g->gcdept < GCSTEPSIZE) -+ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ -+ else { -+ g->gcdept -= GCSTEPSIZE; -+ g->GCthreshold = g->totalbytes; -+ } -+ } -+ else { -+ lua_assert(g->totalbytes >= g->estimate); -+ setthreshold(g); -+ } -+} -+ -+ -+void luaC_fullgc (lua_State *L) { -+ global_State *g = G(L); -+ if (g->gcstate <= GCSpropagate) { -+ /* reset sweep marks to sweep all elements (returning them to white) */ -+ g->sweepstrgc = 0; -+ g->sweepgc = &g->rootgc; -+ /* reset other collector lists */ -+ g->gray = NULL; -+ g->grayagain = NULL; -+ g->weak = NULL; -+ g->gcstate = GCSsweepstring; -+ } -+ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); -+ /* finish any pending sweep phase */ -+ while (g->gcstate != GCSfinalize) { -+ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); -+ singlestep(L); -+ } -+ markroot(L); -+ while (g->gcstate != GCSpause) { -+ singlestep(L); -+ } -+ setthreshold(g); -+} -+ -+ -+void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { -+ global_State *g = G(L); -+ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); -+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); -+ lua_assert(ttype(&o->gch) != LUA_TTABLE); -+ /* must keep invariant? */ -+ if (g->gcstate == GCSpropagate) -+ reallymarkobject(g, v); /* restore invariant */ -+ else /* don't mind */ -+ makewhite(g, o); /* mark as white just to avoid other barriers */ -+} -+ -+ -+void luaC_barrierback (lua_State *L, Table *t) { -+ global_State *g = G(L); -+ GCObject *o = obj2gco(t); -+ lua_assert(isblack(o) && !isdead(g, o)); -+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); -+ black2gray(o); /* make table gray (again) */ -+ t->gclist = g->grayagain; -+ g->grayagain = o; -+} -+ -+ -+void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { -+ global_State *g = G(L); -+ o->gch.next = g->rootgc; -+ g->rootgc = o; -+ o->gch.marked = luaC_white(g); -+ o->gch.tt = tt; -+} -+ -+ -+void luaC_linkupval (lua_State *L, UpVal *uv) { -+ global_State *g = G(L); -+ GCObject *o = obj2gco(uv); -+ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ -+ g->rootgc = o; -+ if (isgray(o)) { -+ if (g->gcstate == GCSpropagate) { -+ gray2black(o); /* closed upvalues need barrier */ -+ luaC_barrier(L, uv, uv->v); -+ } -+ else { /* sweep phase: sweep it (turning it into white) */ -+ makewhite(g, o); -+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); -+ } -+ } -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lgc.h -@@ -0,0 +1,110 @@ -+/* -+** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Garbage Collector -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lgc_h -+#define lgc_h -+ -+ -+#include "lobject.h" -+ -+ -+/* -+** Possible states of the Garbage Collector -+*/ -+#define GCSpause 0 -+#define GCSpropagate 1 -+#define GCSsweepstring 2 -+#define GCSsweep 3 -+#define GCSfinalize 4 -+ -+ -+/* -+** some userful bit tricks -+*/ -+#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -+#define setbits(x,m) ((x) |= (m)) -+#define testbits(x,m) ((x) & (m)) -+#define bitmask(b) (1<<(b)) -+#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -+#define l_setbit(x,b) setbits(x, bitmask(b)) -+#define resetbit(x,b) resetbits(x, bitmask(b)) -+#define testbit(x,b) testbits(x, bitmask(b)) -+#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) -+#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) -+#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) -+ -+ -+ -+/* -+** Layout for bit use in `marked' field: -+** bit 0 - object is white (type 0) -+** bit 1 - object is white (type 1) -+** bit 2 - object is black -+** bit 3 - for userdata: has been finalized -+** bit 3 - for tables: has weak keys -+** bit 4 - for tables: has weak values -+** bit 5 - object is fixed (should not be collected) -+** bit 6 - object is "super" fixed (only the main thread) -+*/ -+ -+ -+#define WHITE0BIT 0 -+#define WHITE1BIT 1 -+#define BLACKBIT 2 -+#define FINALIZEDBIT 3 -+#define KEYWEAKBIT 3 -+#define VALUEWEAKBIT 4 -+#define FIXEDBIT 5 -+#define SFIXEDBIT 6 -+#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) -+ -+ -+#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -+#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -+#define isgray(x) (!isblack(x) && !iswhite(x)) -+ -+#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -+#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) -+ -+#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -+#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) -+ -+#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) -+ -+#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) -+ -+ -+#define luaC_checkGC(L) { \ -+ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ -+ if (G(L)->totalbytes >= G(L)->GCthreshold) \ -+ luaC_step(L); } -+ -+ -+#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ -+ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } -+ -+#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ -+ luaC_barrierback(L,t); } -+ -+#define luaC_objbarrier(L,p,o) \ -+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ -+ luaC_barrierf(L,obj2gco(p),obj2gco(o)); } -+ -+#define luaC_objbarriert(L,t,o) \ -+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } -+ -+LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); -+LUAI_FUNC void luaC_callGCTM (lua_State *L); -+LUAI_FUNC void luaC_freeall (lua_State *L); -+LUAI_FUNC void luaC_step (lua_State *L); -+LUAI_FUNC void luaC_fullgc (lua_State *L); -+LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); -+LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); -+LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); -+LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/llex.c -@@ -0,0 +1,460 @@ -+/* -+** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lexical Analyzer -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+ -+#define llex_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldo.h" -+#include "llex.h" -+#include "lobject.h" -+#include "lparser.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "lzio.h" -+ -+ -+ -+#define next(ls) (ls->current = zgetc(ls->z)) -+ -+ -+ -+ -+#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') -+ -+ -+/* ORDER RESERVED */ -+const char *const luaX_tokens [] = { -+ "and", "break", "do", "else", "elseif", -+ "end", "false", "for", "function", "if", -+ "in", "local", "nil", "not", "or", "repeat", -+ "return", "then", "true", "until", "while", -+ "..", "...", "==", ">=", "<=", "~=", -+ "", "", "", "", -+ NULL -+}; -+ -+ -+#define save_and_next(ls) (save(ls, ls->current), next(ls)) -+ -+ -+static void save (LexState *ls, int c) { -+ Mbuffer *b = ls->buff; -+ if (b->n + 1 > b->buffsize) { -+ size_t newsize; -+ if (b->buffsize >= MAX_SIZET/2) -+ luaX_lexerror(ls, "lexical element too long", 0); -+ newsize = b->buffsize * 2; -+ luaZ_resizebuffer(ls->L, b, newsize); -+ } -+ b->buffer[b->n++] = cast(char, c); -+} -+ -+ -+void luaX_init (lua_State *L) { -+ int i; -+ for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ -+ } -+} -+ -+ -+#define MAXSRC 80 -+ -+ -+const char *luaX_token2str (LexState *ls, int token) { -+ if (token < FIRST_RESERVED) { -+ lua_assert(token == cast(unsigned char, token)); -+ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : -+ luaO_pushfstring(ls->L, "%c", token); -+ } -+ else -+ return luaX_tokens[token-FIRST_RESERVED]; -+} -+ -+ -+static const char *txtToken (LexState *ls, int token) { -+ switch (token) { -+ case TK_NAME: -+ case TK_STRING: -+ case TK_NUMBER: -+ save(ls, '\0'); -+ return luaZ_buffer(ls->buff); -+ default: -+ return luaX_token2str(ls, token); -+ } -+} -+ -+ -+void luaX_lexerror (LexState *ls, const char *msg, int token) { -+ char buff[MAXSRC]; -+ luaO_chunkid(buff, getstr(ls->source), MAXSRC); -+ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); -+ if (token) -+ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); -+ luaD_throw(ls->L, LUA_ERRSYNTAX); -+} -+ -+ -+void luaX_syntaxerror (LexState *ls, const char *msg) { -+ luaX_lexerror(ls, msg, ls->t.token); -+} -+ -+ -+TString *luaX_newstring (LexState *ls, const char *str, size_t l) { -+ lua_State *L = ls->L; -+ TString *ts = luaS_newlstr(L, str, l); -+ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ -+ if (ttisnil(o)) -+ setbvalue(o, 1); /* make sure `str' will not be collected */ -+ return ts; -+} -+ -+ -+static void inclinenumber (LexState *ls) { -+ int old = ls->current; -+ lua_assert(currIsNewline(ls)); -+ next(ls); /* skip `\n' or `\r' */ -+ if (currIsNewline(ls) && ls->current != old) -+ next(ls); /* skip `\n\r' or `\r\n' */ -+ if (++ls->linenumber >= MAX_INT) -+ luaX_syntaxerror(ls, "chunk has too many lines"); -+} -+ -+ -+void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { -+ ls->decpoint = '.'; -+ ls->L = L; -+ ls->lookahead.token = TK_EOS; /* no look-ahead token */ -+ ls->z = z; -+ ls->fs = NULL; -+ ls->linenumber = 1; -+ ls->lastline = 1; -+ ls->source = source; -+ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ -+ next(ls); /* read first char */ -+} -+ -+ -+ -+/* -+** ======================================================= -+** LEXICAL ANALYZER -+** ======================================================= -+*/ -+ -+ -+ -+static int check_next (LexState *ls, const char *set) { -+ if (!strchr(set, ls->current)) -+ return 0; -+ save_and_next(ls); -+ return 1; -+} -+ -+ -+static void buffreplace (LexState *ls, char from, char to) { -+ size_t n = luaZ_bufflen(ls->buff); -+ char *p = luaZ_buffer(ls->buff); -+ while (n--) -+ if (p[n] == from) p[n] = to; -+} -+ -+ -+static void trydecpoint (LexState *ls, SemInfo *seminfo) { -+ /* format error: try to update decimal point separator */ -+ char old = ls->decpoint; -+ struct lconv *cv = localeconv(); -+ ls->decpoint = (cv ? cv->decimal_point[0] : '.'); -+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ -+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { -+ /* format error with correct decimal point: no more options */ -+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ -+ luaX_lexerror(ls, "malformed number", TK_NUMBER); -+ } -+} -+ -+ -+/* LUA_NUMBER */ -+static void read_numeral (LexState *ls, SemInfo *seminfo) { -+ lua_assert(isdigit(ls->current)); -+ do { -+ save_and_next(ls); -+ } while (isdigit(ls->current) || ls->current == '.'); -+ if (check_next(ls, "Ee")) /* `E'? */ -+ check_next(ls, "+-"); /* optional exponent sign */ -+ while (isalnum(ls->current) || ls->current == '_') -+ save_and_next(ls); -+ save(ls, '\0'); -+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ -+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ -+ trydecpoint(ls, seminfo); /* try to update decimal point separator */ -+} -+ -+ -+static int skip_sep (LexState *ls) { -+ int count = 0; -+ int s = ls->current; -+ lua_assert(s == '[' || s == ']'); -+ save_and_next(ls); -+ while (ls->current == '=') { -+ save_and_next(ls); -+ count++; -+ } -+ return (ls->current == s) ? count : (-count) - 1; -+} -+ -+ -+static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { -+ int cont = 0; -+ (void)(cont); /* avoid warnings when `cont' is not used */ -+ save_and_next(ls); /* skip 2nd `[' */ -+ if (currIsNewline(ls)) /* string starts with a newline? */ -+ inclinenumber(ls); /* skip it */ -+ for (;;) { -+ switch (ls->current) { -+ case EOZ: -+ luaX_lexerror(ls, (seminfo) ? "unfinished long string" : -+ "unfinished long comment", TK_EOS); -+ break; /* to avoid warnings */ -+#if defined(LUA_COMPAT_LSTR) -+ case '[': { -+ if (skip_sep(ls) == sep) { -+ save_and_next(ls); /* skip 2nd `[' */ -+ cont++; -+#if LUA_COMPAT_LSTR == 1 -+ if (sep == 0) -+ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); -+#endif -+ } -+ break; -+ } -+#endif -+ case ']': { -+ if (skip_sep(ls) == sep) { -+ save_and_next(ls); /* skip 2nd `]' */ -+#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 -+ cont--; -+ if (sep == 0 && cont >= 0) break; -+#endif -+ goto endloop; -+ } -+ break; -+ } -+ case '\n': -+ case '\r': { -+ save(ls, '\n'); -+ inclinenumber(ls); -+ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ -+ break; -+ } -+ default: { -+ if (seminfo) save_and_next(ls); -+ else next(ls); -+ } -+ } -+ } endloop: -+ if (seminfo) -+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), -+ luaZ_bufflen(ls->buff) - 2*(2 + sep)); -+} -+ -+ -+static void read_string (LexState *ls, int del, SemInfo *seminfo) { -+ save_and_next(ls); -+ while (ls->current != del) { -+ switch (ls->current) { -+ case EOZ: -+ luaX_lexerror(ls, "unfinished string", TK_EOS); -+ continue; /* to avoid warnings */ -+ case '\n': -+ case '\r': -+ luaX_lexerror(ls, "unfinished string", TK_STRING); -+ continue; /* to avoid warnings */ -+ case '\\': { -+ int c; -+ next(ls); /* do not save the `\' */ -+ switch (ls->current) { -+ case 'a': c = '\a'; break; -+ case 'b': c = '\b'; break; -+ case 'f': c = '\f'; break; -+ case 'n': c = '\n'; break; -+ case 'r': c = '\r'; break; -+ case 't': c = '\t'; break; -+ case 'v': c = '\v'; break; -+ case '\n': /* go through */ -+ case '\r': save(ls, '\n'); inclinenumber(ls); continue; -+ case EOZ: continue; /* will raise an error next loop */ -+ default: { -+ if (!isdigit(ls->current)) -+ save_and_next(ls); /* handles \\, \", \', and \? */ -+ else { /* \xxx */ -+ int i = 0; -+ c = 0; -+ do { -+ c = 10*c + (ls->current-'0'); -+ next(ls); -+ } while (++i<3 && isdigit(ls->current)); -+ if (c > UCHAR_MAX) -+ luaX_lexerror(ls, "escape sequence too large", TK_STRING); -+ save(ls, c); -+ } -+ continue; -+ } -+ } -+ save(ls, c); -+ next(ls); -+ continue; -+ } -+ default: -+ save_and_next(ls); -+ } -+ } -+ save_and_next(ls); /* skip delimiter */ -+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, -+ luaZ_bufflen(ls->buff) - 2); -+} -+ -+ -+static int llex (LexState *ls, SemInfo *seminfo) { -+ luaZ_resetbuffer(ls->buff); -+ for (;;) { -+ switch (ls->current) { -+ case '\n': -+ case '\r': { -+ inclinenumber(ls); -+ continue; -+ } -+ case '-': { -+ next(ls); -+ if (ls->current != '-') return '-'; -+ /* else is a comment */ -+ next(ls); -+ if (ls->current == '[') { -+ int sep = skip_sep(ls); -+ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ -+ if (sep >= 0) { -+ read_long_string(ls, NULL, sep); /* long comment */ -+ luaZ_resetbuffer(ls->buff); -+ continue; -+ } -+ } -+ /* else short comment */ -+ while (!currIsNewline(ls) && ls->current != EOZ) -+ next(ls); -+ continue; -+ } -+ case '[': { -+ int sep = skip_sep(ls); -+ if (sep >= 0) { -+ read_long_string(ls, seminfo, sep); -+ return TK_STRING; -+ } -+ else if (sep == -1) return '['; -+ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); -+ } -+ case '=': { -+ next(ls); -+ if (ls->current != '=') return '='; -+ else { next(ls); return TK_EQ; } -+ } -+ case '<': { -+ next(ls); -+ if (ls->current != '=') return '<'; -+ else { next(ls); return TK_LE; } -+ } -+ case '>': { -+ next(ls); -+ if (ls->current != '=') return '>'; -+ else { next(ls); return TK_GE; } -+ } -+ case '~': { -+ next(ls); -+ if (ls->current != '=') return '~'; -+ else { next(ls); return TK_NE; } -+ } -+ case '"': -+ case '\'': { -+ read_string(ls, ls->current, seminfo); -+ return TK_STRING; -+ } -+ case '.': { -+ save_and_next(ls); -+ if (check_next(ls, ".")) { -+ if (check_next(ls, ".")) -+ return TK_DOTS; /* ... */ -+ else return TK_CONCAT; /* .. */ -+ } -+ else if (!isdigit(ls->current)) return '.'; -+ else { -+ read_numeral(ls, seminfo); -+ return TK_NUMBER; -+ } -+ } -+ case EOZ: { -+ return TK_EOS; -+ } -+ default: { -+ if (isspace(ls->current)) { -+ lua_assert(!currIsNewline(ls)); -+ next(ls); -+ continue; -+ } -+ else if (isdigit(ls->current)) { -+ read_numeral(ls, seminfo); -+ return TK_NUMBER; -+ } -+ else if (isalpha(ls->current) || ls->current == '_') { -+ /* identifier or reserved word */ -+ TString *ts; -+ do { -+ save_and_next(ls); -+ } while (isalnum(ls->current) || ls->current == '_'); -+ ts = luaX_newstring(ls, luaZ_buffer(ls->buff), -+ luaZ_bufflen(ls->buff)); -+ if (ts->tsv.reserved > 0) /* reserved word? */ -+ return ts->tsv.reserved - 1 + FIRST_RESERVED; -+ else { -+ seminfo->ts = ts; -+ return TK_NAME; -+ } -+ } -+ else { -+ int c = ls->current; -+ next(ls); -+ return c; /* single-char tokens (+ - / ...) */ -+ } -+ } -+ } -+ } -+} -+ -+ -+void luaX_next (LexState *ls) { -+ ls->lastline = ls->linenumber; -+ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ -+ ls->t = ls->lookahead; /* use this one */ -+ ls->lookahead.token = TK_EOS; /* and discharge it */ -+ } -+ else -+ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -+} -+ -+ -+void luaX_lookahead (LexState *ls) { -+ lua_assert(ls->lookahead.token == TK_EOS); -+ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/llex.h -@@ -0,0 +1,81 @@ -+/* -+** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lexical Analyzer -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef llex_h -+#define llex_h -+ -+#include "lobject.h" -+#include "lzio.h" -+ -+ -+#define FIRST_RESERVED 257 -+ -+/* maximum length of a reserved word */ -+#define TOKEN_LEN (sizeof("function")/sizeof(char)) -+ -+ -+/* -+* WARNING: if you change the order of this enumeration, -+* grep "ORDER RESERVED" -+*/ -+enum RESERVED { -+ /* terminal symbols denoted by reserved words */ -+ TK_AND = FIRST_RESERVED, TK_BREAK, -+ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, -+ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, -+ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, -+ /* other terminal symbols */ -+ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, -+ TK_NAME, TK_STRING, TK_EOS -+}; -+ -+/* number of reserved words */ -+#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) -+ -+ -+/* array with token `names' */ -+LUAI_DATA const char *const luaX_tokens []; -+ -+ -+typedef union { -+ lua_Number r; -+ TString *ts; -+} SemInfo; /* semantics information */ -+ -+ -+typedef struct Token { -+ int token; -+ SemInfo seminfo; -+} Token; -+ -+ -+typedef struct LexState { -+ int current; /* current character (charint) */ -+ int linenumber; /* input line counter */ -+ int lastline; /* line of last token `consumed' */ -+ Token t; /* current token */ -+ Token lookahead; /* look ahead token */ -+ struct FuncState *fs; /* `FuncState' is private to the parser */ -+ struct lua_State *L; -+ ZIO *z; /* input stream */ -+ Mbuffer *buff; /* buffer for tokens */ -+ TString *source; /* current source name */ -+ char decpoint; /* locale decimal point */ -+} LexState; -+ -+ -+LUAI_FUNC void luaX_init (lua_State *L); -+LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, -+ TString *source); -+LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -+LUAI_FUNC void luaX_next (LexState *ls); -+LUAI_FUNC void luaX_lookahead (LexState *ls); -+LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); -+LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); -+LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/llimits.h -@@ -0,0 +1,125 @@ -+/* -+** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Limits, basic types, and some other `installation-dependent' definitions -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef llimits_h -+#define llimits_h -+ -+#include -+#include -+ -+#include "lua.h" -+ -+typedef LUAI_UINT32 lu_int32; -+ -+typedef LUAI_UMEM lu_mem; -+ -+typedef LUAI_MEM l_mem; -+ -+ -+ -+/* chars used as small naturals (so that `char' is reserved for characters) */ -+typedef unsigned char lu_byte; -+ -+ -+#define MAX_SIZET ((size_t)(~(size_t)0)-2) -+ -+#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) -+ -+ -+#define MAX_INT (LUA_INT_MAX-2) /* maximum value of an int (-2 for safety) */ -+ -+/* -+** conversion of pointer to integer -+** this is for hashing only; there is no problem if the integer -+** cannot hold the whole pointer value -+*/ -+#define IntPoint(p) ((unsigned int)(lu_mem)(p)) -+ -+ -+ -+/* type to ensure maximum alignment */ -+typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; -+ -+ -+/* result of a `usual argument conversion' over lua_Number */ -+typedef LUAI_UACNUMBER l_uacNumber; -+ -+ -+/* internal assertions for in-house debugging */ -+#ifdef lua_assert -+ -+#define check_exp(c,e) (lua_assert(c), (e)) -+#define api_check(l,e) lua_assert(e) -+ -+#else -+ -+#define lua_assert(c) ((void)0) -+#define check_exp(c,e) (e) -+#define api_check luai_apicheck -+ -+#endif -+ -+ -+#ifndef UNUSED -+#define UNUSED(x) ((void)(x)) /* to avoid warnings */ -+#endif -+ -+ -+#ifndef cast -+#define cast(t, exp) ((t)(exp)) -+#endif -+ -+#define cast_byte(i) cast(lu_byte, (i)) -+#define cast_num(i) cast(lua_Number, (i)) -+#define cast_int(i) cast(int, (i)) -+ -+ -+ -+/* -+** type for virtual-machine instructions -+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -+*/ -+typedef lu_int32 Instruction; -+ -+ -+ -+/* maximum stack for a Lua function */ -+#define MAXSTACK 250 -+ -+ -+ -+/* minimum size for the string table (must be power of 2) */ -+#ifndef MINSTRTABSIZE -+#define MINSTRTABSIZE 32 -+#endif -+ -+ -+/* minimum size for string buffer */ -+#ifndef LUA_MINBUFFER -+#define LUA_MINBUFFER 32 -+#endif -+ -+ -+#ifndef lua_lock -+#define lua_lock(L) ((void) 0) -+#define lua_unlock(L) ((void) 0) -+#endif -+ -+#ifndef luai_threadyield -+#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -+#endif -+ -+ -+/* -+** macro to control inclusion of some hard tests on stack reallocation -+*/ -+#ifndef HARDSTACKTESTS -+#define condhardstacktests(x) ((void)0) -+#else -+#define condhardstacktests(x) x -+#endif -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lmem.c -@@ -0,0 +1,86 @@ -+/* -+** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Interface to Memory Manager -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lmem_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+ -+ -+ -+/* -+** About the realloc function: -+** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -+** (`osize' is the old size, `nsize' is the new size) -+** -+** Lua ensures that (ptr == NULL) iff (osize == 0). -+** -+** * frealloc(ud, NULL, 0, x) creates a new block of size `x' -+** -+** * frealloc(ud, p, x, 0) frees the block `p' -+** (in this specific case, frealloc must return NULL). -+** particularly, frealloc(ud, NULL, 0, 0) does nothing -+** (which is equivalent to free(NULL) in ANSI C) -+** -+** frealloc returns NULL if it cannot create or reallocate the area -+** (any reallocation to an equal or smaller size cannot fail!) -+*/ -+ -+ -+ -+#define MINSIZEARRAY 4 -+ -+ -+void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, -+ int limit, const char *errormsg) { -+ void *newblock; -+ int newsize; -+ if (*size >= limit/2) { /* cannot double it? */ -+ if (*size >= limit) /* cannot grow even a little? */ -+ luaG_runerror(L, errormsg); -+ newsize = limit; /* still have at least one free place */ -+ } -+ else { -+ newsize = (*size)*2; -+ if (newsize < MINSIZEARRAY) -+ newsize = MINSIZEARRAY; /* minimum size */ -+ } -+ newblock = luaM_reallocv(L, block, *size, newsize, size_elems); -+ *size = newsize; /* update only when everything else is OK */ -+ return newblock; -+} -+ -+ -+void *luaM_toobig (lua_State *L) { -+ luaG_runerror(L, "memory allocation error: block too big"); -+ return NULL; /* to avoid warnings */ -+} -+ -+ -+ -+/* -+** generic allocation routine. -+*/ -+void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { -+ global_State *g = G(L); -+ lua_assert((osize == 0) == (block == NULL)); -+ block = (*g->frealloc)(g->ud, block, osize, nsize); -+ if (block == NULL && nsize > 0) -+ luaD_throw(L, LUA_ERRMEM); -+ lua_assert((nsize == 0) == (block == NULL)); -+ g->totalbytes = (g->totalbytes - osize) + nsize; -+ return block; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lmem.h -@@ -0,0 +1,49 @@ -+/* -+** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Interface to Memory Manager -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lmem_h -+#define lmem_h -+ -+ -+#include -+ -+#include "llimits.h" -+#include "lua.h" -+ -+#define MEMERRMSG "not enough memory" -+ -+ -+#define luaM_reallocv(L,b,on,n,e) \ -+ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ -+ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ -+ luaM_toobig(L)) -+ -+#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -+#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -+#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) -+ -+#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) -+#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) -+#define luaM_newvector(L,n,t) \ -+ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) -+ -+#define luaM_growvector(L,v,nelems,size,t,limit,e) \ -+ if ((nelems)+1 > (size)) \ -+ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) -+ -+#define luaM_reallocvector(L, v,oldn,n,t) \ -+ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) -+ -+ -+LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, -+ size_t size); -+LUAI_FUNC void *luaM_toobig (lua_State *L); -+LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, -+ size_t size_elem, int limit, -+ const char *errormsg); -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lobject.c -@@ -0,0 +1,215 @@ -+/* -+** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Some generic functions over Lua objects -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define lobject_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldo.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "lvm.h" -+ -+ -+ -+const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; -+ -+ -+/* -+** converts an integer to a "floating point byte", represented as -+** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if -+** eeeee != 0 and (xxx) otherwise. -+*/ -+int luaO_int2fb (unsigned int x) { -+ int e = 0; /* expoent */ -+ while (x >= 16) { -+ x = (x+1) >> 1; -+ e++; -+ } -+ if (x < 8) return x; -+ else return ((e+1) << 3) | (cast_int(x) - 8); -+} -+ -+ -+/* converts back */ -+int luaO_fb2int (int x) { -+ int e = (x >> 3) & 31; -+ if (e == 0) return x; -+ else return ((x & 7)+8) << (e - 1); -+} -+ -+ -+int luaO_log2 (unsigned int x) { -+ static const lu_byte log_2[256] = { -+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 -+ }; -+ int l = -1; -+ while (x >= 256) { l += 8; x >>= 8; } -+ return l + log_2[x]; -+ -+} -+ -+ -+int luaO_rawequalObj (const TValue *t1, const TValue *t2) { -+ if (ttype(t1) != ttype(t2)) return 0; -+ else switch (ttype(t1)) { -+ case LUA_TNIL: -+ return 1; -+ case LUA_TNUMBER: -+ return luai_numeq(nvalue(t1), nvalue(t2)); -+ case LUA_TBOOLEAN: -+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ -+ case LUA_TLIGHTUSERDATA: -+ return pvalue(t1) == pvalue(t2); -+ default: -+ lua_assert(iscollectable(t1)); -+ return gcvalue(t1) == gcvalue(t2); -+ } -+} -+ -+ -+int luaO_str2d (const char *s, lua_Number *result) { -+ char *endptr; -+ *result = lua_str2number(s, &endptr); -+ if (endptr == s) return 0; /* conversion failed */ -+ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ -+ *result = cast_num(strtoul(s, &endptr, 16)); -+ if (*endptr == '\0') return 1; /* most common case */ -+ while (isspace(cast(unsigned char, *endptr))) endptr++; -+ if (*endptr != '\0') return 0; /* invalid trailing characters? */ -+ return 1; -+} -+ -+ -+ -+static void pushstr (lua_State *L, const char *str) { -+ setsvalue2s(L, L->top, luaS_new(L, str)); -+ incr_top(L); -+} -+ -+ -+/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ -+const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { -+ int n = 1; -+ pushstr(L, ""); -+ for (;;) { -+ const char *e = strchr(fmt, '%'); -+ if (e == NULL) break; -+ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); -+ incr_top(L); -+ switch (*(e+1)) { -+ case 's': { -+ const char *s = va_arg(argp, char *); -+ if (s == NULL) s = "(null)"; -+ pushstr(L, s); -+ break; -+ } -+ case 'c': { -+ char buff[2]; -+ buff[0] = cast(char, va_arg(argp, int)); -+ buff[1] = '\0'; -+ pushstr(L, buff); -+ break; -+ } -+ case 'd': { -+ setnvalue(L->top, cast_num(va_arg(argp, int))); -+ incr_top(L); -+ break; -+ } -+ case 'f': { -+ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); -+ incr_top(L); -+ break; -+ } -+ case 'p': { -+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ -+ sprintf(buff, "%p", va_arg(argp, void *)); -+ pushstr(L, buff); -+ break; -+ } -+ case '%': { -+ pushstr(L, "%"); -+ break; -+ } -+ default: { -+ char buff[3]; -+ buff[0] = '%'; -+ buff[1] = *(e+1); -+ buff[2] = '\0'; -+ pushstr(L, buff); -+ break; -+ } -+ } -+ n += 2; -+ fmt = e+2; -+ } -+ pushstr(L, fmt); -+ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); -+ L->top -= n; -+ return svalue(L->top - 1); -+} -+ -+ -+const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { -+ const char *msg; -+ va_list argp; -+ va_start(argp, fmt); -+ msg = luaO_pushvfstring(L, fmt, argp); -+ va_end(argp); -+ return msg; -+} -+ -+ -+void luaO_chunkid (char *out, const char *source, size_t bufflen) { -+ if (*source == '=') { -+ strncpy(out, source+1, bufflen); /* remove first char */ -+ out[bufflen-1] = '\0'; /* ensures null termination */ -+ } -+ else { /* out = "source", or "...source" */ -+ if (*source == '@') { -+ size_t l; -+ source++; /* skip the `@' */ -+ bufflen -= sizeof(" '...' "); -+ l = strlen(source); -+ strcpy(out, ""); -+ if (l > bufflen) { -+ source += (l-bufflen); /* get last part of file name */ -+ strcat(out, "..."); -+ } -+ strcat(out, source); -+ } -+ else { /* out = [string "string"] */ -+ size_t len = strcspn(source, "\n\r"); /* stop at first newline */ -+ bufflen -= sizeof(" [string \"...\"] "); -+ if (len > bufflen) len = bufflen; -+ strcpy(out, "[string \""); -+ if (source[len] != '\0') { /* must truncate? */ -+ strncat(out, source, len); -+ strcat(out, "..."); -+ } -+ else -+ strcat(out, source); -+ strcat(out, "\"]"); -+ } -+ } -+} ---- /dev/null -+++ b/extensions/LUA/lua/lobject.h -@@ -0,0 +1,381 @@ -+/* -+** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ -+** Type definitions for Lua objects -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lobject_h -+#define lobject_h -+ -+ -+#include -+ -+ -+#include "llimits.h" -+#include "lua.h" -+ -+ -+/* tags for values visible from Lua */ -+#define LAST_TAG LUA_TTHREAD -+ -+#define NUM_TAGS (LAST_TAG+1) -+ -+ -+/* -+** Extra tags for non-values -+*/ -+#define LUA_TPROTO (LAST_TAG+1) -+#define LUA_TUPVAL (LAST_TAG+2) -+#define LUA_TDEADKEY (LAST_TAG+3) -+ -+ -+/* -+** Union of all collectable objects -+*/ -+typedef union GCObject GCObject; -+ -+ -+/* -+** Common Header for all collectable objects (in macro form, to be -+** included in other objects) -+*/ -+#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked -+ -+ -+/* -+** Common header in struct form -+*/ -+typedef struct GCheader { -+ CommonHeader; -+} GCheader; -+ -+ -+ -+ -+/* -+** Union of all Lua values -+*/ -+typedef union { -+ GCObject *gc; -+ void *p; -+ lua_Number n; -+ int b; -+} Value; -+ -+ -+/* -+** Tagged Values -+*/ -+ -+#define TValuefields Value value; int tt -+ -+typedef struct lua_TValue { -+ TValuefields; -+} TValue; -+ -+ -+/* Macros to test type */ -+#define ttisnil(o) (ttype(o) == LUA_TNIL) -+#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) -+#define ttisstring(o) (ttype(o) == LUA_TSTRING) -+#define ttistable(o) (ttype(o) == LUA_TTABLE) -+#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) -+#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) -+#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) -+#define ttisthread(o) (ttype(o) == LUA_TTHREAD) -+#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) -+ -+/* Macros to access values */ -+#define ttype(o) ((o)->tt) -+#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) -+#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) -+#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) -+#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) -+#define tsvalue(o) (&rawtsvalue(o)->tsv) -+#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) -+#define uvalue(o) (&rawuvalue(o)->uv) -+#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) -+#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) -+#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) -+#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) -+ -+#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) -+ -+/* -+** for internal debug only -+*/ -+#define checkconsistency(obj) \ -+ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) -+ -+#define checkliveness(g,obj) \ -+ lua_assert(!iscollectable(obj) || \ -+ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) -+ -+ -+/* Macros to set values */ -+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) -+ -+#define setnvalue(obj,x) \ -+ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } -+ -+#define setpvalue(obj,x) \ -+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } -+ -+#define setbvalue(obj,x) \ -+ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } -+ -+#define setsvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ -+ checkliveness(G(L),i_o); } -+ -+#define setuvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ -+ checkliveness(G(L),i_o); } -+ -+#define setthvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ -+ checkliveness(G(L),i_o); } -+ -+#define setclvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ -+ checkliveness(G(L),i_o); } -+ -+#define sethvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ -+ checkliveness(G(L),i_o); } -+ -+#define setptvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ -+ checkliveness(G(L),i_o); } -+ -+ -+ -+ -+#define setobj(L,obj1,obj2) \ -+ { const TValue *o2=(obj2); TValue *o1=(obj1); \ -+ o1->value = o2->value; o1->tt=o2->tt; \ -+ checkliveness(G(L),o1); } -+ -+ -+/* -+** different types of sets, according to destination -+*/ -+ -+/* from stack to (same) stack */ -+#define setobjs2s setobj -+/* to stack (not from same stack) */ -+#define setobj2s setobj -+#define setsvalue2s setsvalue -+#define sethvalue2s sethvalue -+#define setptvalue2s setptvalue -+/* from table to same table */ -+#define setobjt2t setobj -+/* to table */ -+#define setobj2t setobj -+/* to new object */ -+#define setobj2n setobj -+#define setsvalue2n setsvalue -+ -+#define setttype(obj, tt) (ttype(obj) = (tt)) -+ -+ -+#define iscollectable(o) (ttype(o) >= LUA_TSTRING) -+ -+ -+ -+typedef TValue *StkId; /* index to stack elements */ -+ -+ -+/* -+** String headers for string table -+*/ -+typedef union TString { -+ L_Umaxalign dummy; /* ensures maximum alignment for strings */ -+ struct { -+ CommonHeader; -+ lu_byte reserved; -+ unsigned int hash; -+ size_t len; -+ } tsv; -+} TString; -+ -+ -+#define getstr(ts) cast(const char *, (ts) + 1) -+#define svalue(o) getstr(rawtsvalue(o)) -+ -+ -+ -+typedef union Udata { -+ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ -+ struct { -+ CommonHeader; -+ struct Table *metatable; -+ struct Table *env; -+ size_t len; -+ } uv; -+} Udata; -+ -+ -+ -+ -+/* -+** Function Prototypes -+*/ -+typedef struct Proto { -+ CommonHeader; -+ TValue *k; /* constants used by the function */ -+ Instruction *code; -+ struct Proto **p; /* functions defined inside the function */ -+ int *lineinfo; /* map from opcodes to source lines */ -+ struct LocVar *locvars; /* information about local variables */ -+ TString **upvalues; /* upvalue names */ -+ TString *source; -+ int sizeupvalues; -+ int sizek; /* size of `k' */ -+ int sizecode; -+ int sizelineinfo; -+ int sizep; /* size of `p' */ -+ int sizelocvars; -+ int linedefined; -+ int lastlinedefined; -+ GCObject *gclist; -+ lu_byte nups; /* number of upvalues */ -+ lu_byte numparams; -+ lu_byte is_vararg; -+ lu_byte maxstacksize; -+} Proto; -+ -+ -+/* masks for new-style vararg */ -+#define VARARG_HASARG 1 -+#define VARARG_ISVARARG 2 -+#define VARARG_NEEDSARG 4 -+ -+ -+typedef struct LocVar { -+ TString *varname; -+ int startpc; /* first point where variable is active */ -+ int endpc; /* first point where variable is dead */ -+} LocVar; -+ -+ -+ -+/* -+** Upvalues -+*/ -+ -+typedef struct UpVal { -+ CommonHeader; -+ TValue *v; /* points to stack or to its own value */ -+ union { -+ TValue value; /* the value (when closed) */ -+ struct { /* double linked list (when open) */ -+ struct UpVal *prev; -+ struct UpVal *next; -+ } l; -+ } u; -+} UpVal; -+ -+ -+/* -+** Closures -+*/ -+ -+#define ClosureHeader \ -+ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ -+ struct Table *env -+ -+typedef struct CClosure { -+ ClosureHeader; -+ lua_CFunction f; -+ TValue upvalue[1]; -+} CClosure; -+ -+ -+typedef struct LClosure { -+ ClosureHeader; -+ struct Proto *p; -+ UpVal *upvals[1]; -+} LClosure; -+ -+ -+typedef union Closure { -+ CClosure c; -+ LClosure l; -+} Closure; -+ -+ -+#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) -+#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) -+ -+ -+/* -+** Tables -+*/ -+ -+typedef union TKey { -+ struct { -+ TValuefields; -+ struct Node *next; /* for chaining */ -+ } nk; -+ TValue tvk; -+} TKey; -+ -+ -+typedef struct Node { -+ TValue i_val; -+ TKey i_key; -+} Node; -+ -+ -+typedef struct Table { -+ CommonHeader; -+ lu_byte flags; /* 1<

    lsizenode)) -+ -+ -+#define luaO_nilobject (&luaO_nilobject_) -+ -+LUAI_DATA const TValue luaO_nilobject_; -+ -+#define ceillog2(x) (luaO_log2((x)-1) + 1) -+ -+LUAI_FUNC int luaO_log2 (unsigned int x); -+LUAI_FUNC int luaO_int2fb (unsigned int x); -+LUAI_FUNC int luaO_fb2int (int x); -+LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); -+LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); -+LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, -+ va_list argp); -+LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -+LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); -+ -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lopcodes.c -@@ -0,0 +1,102 @@ -+/* -+** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#define lopcodes_c -+#define LUA_CORE -+ -+ -+#include "lopcodes.h" -+ -+ -+/* ORDER OP */ -+ -+const char *const luaP_opnames[NUM_OPCODES+1] = { -+ "MOVE", -+ "LOADK", -+ "LOADBOOL", -+ "LOADNIL", -+ "GETUPVAL", -+ "GETGLOBAL", -+ "GETTABLE", -+ "SETGLOBAL", -+ "SETUPVAL", -+ "SETTABLE", -+ "NEWTABLE", -+ "SELF", -+ "ADD", -+ "SUB", -+ "MUL", -+ "DIV", -+ "MOD", -+ "POW", -+ "UNM", -+ "NOT", -+ "LEN", -+ "CONCAT", -+ "JMP", -+ "EQ", -+ "LT", -+ "LE", -+ "TEST", -+ "TESTSET", -+ "CALL", -+ "TAILCALL", -+ "RETURN", -+ "FORLOOP", -+ "FORPREP", -+ "TFORLOOP", -+ "SETLIST", -+ "CLOSE", -+ "CLOSURE", -+ "VARARG", -+ NULL -+}; -+ -+ -+#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) -+ -+const lu_byte luaP_opmodes[NUM_OPCODES] = { -+/* T A B C mode opcode */ -+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ -+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ -+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ -+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ -+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ -+ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ -+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ -+ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ -+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ -+ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ -+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ -+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ -+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ -+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ -+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ -+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ -+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ -+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ -+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ -+ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ -+ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ -+ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ -+ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ -+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ -+}; -+ ---- /dev/null -+++ b/extensions/LUA/lua/lopcodes.h -@@ -0,0 +1,268 @@ -+/* -+** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Opcodes for Lua virtual machine -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lopcodes_h -+#define lopcodes_h -+ -+#include "llimits.h" -+ -+ -+/*=========================================================================== -+ We assume that instructions are unsigned numbers. -+ All instructions have an opcode in the first 6 bits. -+ Instructions can have the following fields: -+ `A' : 8 bits -+ `B' : 9 bits -+ `C' : 9 bits -+ `Bx' : 18 bits (`B' and `C' together) -+ `sBx' : signed Bx -+ -+ A signed argument is represented in excess K; that is, the number -+ value is the unsigned value minus K. K is exactly the maximum value -+ for that argument (so that -max is represented by 0, and +max is -+ represented by 2*max), which is half the maximum for the corresponding -+ unsigned argument. -+===========================================================================*/ -+ -+ -+enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ -+ -+ -+/* -+** size and position of opcode arguments. -+*/ -+#define SIZE_C 9 -+#define SIZE_B 9 -+#define SIZE_Bx (SIZE_C + SIZE_B) -+#define SIZE_A 8 -+ -+#define SIZE_OP 6 -+ -+#define POS_OP 0 -+#define POS_A (POS_OP + SIZE_OP) -+#define POS_C (POS_A + SIZE_A) -+#define POS_B (POS_C + SIZE_C) -+#define POS_Bx POS_C -+ -+ -+/* -+** limits for opcode arguments. -+** we use (signed) int to manipulate most arguments, -+** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) -+*/ -+#if SIZE_Bx < LUAI_BITSINT-1 -+#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ -+#else -+#define MAXARG_Bx MAX_INT -+#define MAXARG_sBx MAX_INT -+#endif -+ -+ -+#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) -+#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ -+ ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) -+#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ -+ ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) -+#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ -+ ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) -+#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ -+ ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) -+#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ -+ ((cast(Instruction, b)< C) then pc++ */ -+OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ -+ -+OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -+OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -+OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ -+ -+OP_FORLOOP,/* A sBx R(A)+=R(A+2); -+ if R(A) =) R(A)*/ -+OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ -+ -+OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ -+} OpCode; -+ -+ -+#define NUM_OPCODES (cast(int, OP_VARARG) + 1) -+ -+ -+ -+/*=========================================================================== -+ Notes: -+ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, -+ and can be 0: OP_CALL then sets `top' to last_result+1, so -+ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. -+ -+ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and -+ set top (like in OP_CALL with C == 0). -+ -+ (*) In OP_RETURN, if (B == 0) then return up to `top' -+ -+ (*) In OP_SETLIST, if (B == 0) then B = `top'; -+ if (C == 0) then next `instruction' is real C -+ -+ (*) For comparisons, A specifies what condition the test should accept -+ (true or false). -+ -+ (*) All `skips' (pc++) assume that next instruction is a jump -+===========================================================================*/ -+ -+ -+/* -+** masks for instruction properties. The format is: -+** bits 0-1: op mode -+** bits 2-3: C arg mode -+** bits 4-5: B arg mode -+** bit 6: instruction set register A -+** bit 7: operator is a test -+*/ -+ -+enum OpArgMask { -+ OpArgN, /* argument is not used */ -+ OpArgU, /* argument is used */ -+ OpArgR, /* argument is a register or a jump offset */ -+ OpArgK /* argument is a constant or register/constant */ -+}; -+ -+LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; -+ -+#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) -+#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) -+#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -+#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -+#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) -+ -+ -+LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ -+ -+ -+/* number of list items to accumulate before a SETLIST instruction */ -+#define LFIELDS_PER_FLUSH 50 -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lparser.c -@@ -0,0 +1,1339 @@ -+/* -+** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ -+** Lua Parser -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lparser_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lcode.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "llex.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+ -+ -+ -+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) -+ -+#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) -+ -+#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) -+ -+ -+/* -+** nodes for block list (list of active blocks) -+*/ -+typedef struct BlockCnt { -+ struct BlockCnt *previous; /* chain */ -+ int breaklist; /* list of jumps out of this loop */ -+ lu_byte nactvar; /* # active locals outside the breakable structure */ -+ lu_byte upval; /* true if some variable in the block is an upvalue */ -+ lu_byte isbreakable; /* true if `block' is a loop */ -+} BlockCnt; -+ -+ -+ -+/* -+** prototypes for recursive non-terminal functions -+*/ -+static void chunk (LexState *ls); -+static void expr (LexState *ls, expdesc *v); -+ -+ -+static void anchor_token (LexState *ls) { -+ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { -+ TString *ts = ls->t.seminfo.ts; -+ luaX_newstring(ls, getstr(ts), ts->tsv.len); -+ } -+} -+ -+ -+static void error_expected (LexState *ls, int token) { -+ luaX_syntaxerror(ls, -+ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); -+} -+ -+ -+static void errorlimit (FuncState *fs, int limit, const char *what) { -+ const char *msg = (fs->f->linedefined == 0) ? -+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : -+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s", -+ fs->f->linedefined, limit, what); -+ luaX_lexerror(fs->ls, msg, 0); -+} -+ -+ -+static int testnext (LexState *ls, int c) { -+ if (ls->t.token == c) { -+ luaX_next(ls); -+ return 1; -+ } -+ else return 0; -+} -+ -+ -+static void check (LexState *ls, int c) { -+ if (ls->t.token != c) -+ error_expected(ls, c); -+} -+ -+static void checknext (LexState *ls, int c) { -+ check(ls, c); -+ luaX_next(ls); -+} -+ -+ -+#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } -+ -+ -+ -+static void check_match (LexState *ls, int what, int who, int where) { -+ if (!testnext(ls, what)) { -+ if (where == ls->linenumber) -+ error_expected(ls, what); -+ else { -+ luaX_syntaxerror(ls, luaO_pushfstring(ls->L, -+ LUA_QS " expected (to close " LUA_QS " at line %d)", -+ luaX_token2str(ls, what), luaX_token2str(ls, who), where)); -+ } -+ } -+} -+ -+ -+static TString *str_checkname (LexState *ls) { -+ TString *ts; -+ check(ls, TK_NAME); -+ ts = ls->t.seminfo.ts; -+ luaX_next(ls); -+ return ts; -+} -+ -+ -+static void init_exp (expdesc *e, expkind k, int i) { -+ e->f = e->t = NO_JUMP; -+ e->k = k; -+ e->u.s.info = i; -+} -+ -+ -+static void codestring (LexState *ls, expdesc *e, TString *s) { -+ init_exp(e, VK, luaK_stringK(ls->fs, s)); -+} -+ -+ -+static void checkname(LexState *ls, expdesc *e) { -+ codestring(ls, e, str_checkname(ls)); -+} -+ -+ -+static int registerlocalvar (LexState *ls, TString *varname) { -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ int oldsize = f->sizelocvars; -+ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, -+ LocVar, SHRT_MAX, "too many local variables"); -+ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; -+ f->locvars[fs->nlocvars].varname = varname; -+ luaC_objbarrier(ls->L, f, varname); -+ return fs->nlocvars++; -+} -+ -+ -+#define new_localvarliteral(ls,v,n) \ -+ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) -+ -+ -+static void new_localvar (LexState *ls, TString *name, int n) { -+ FuncState *fs = ls->fs; -+ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); -+ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); -+} -+ -+ -+static void adjustlocalvars (LexState *ls, int nvars) { -+ FuncState *fs = ls->fs; -+ fs->nactvar = cast_byte(fs->nactvar + nvars); -+ for (; nvars; nvars--) { -+ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; -+ } -+} -+ -+ -+static void removevars (LexState *ls, int tolevel) { -+ FuncState *fs = ls->fs; -+ while (fs->nactvar > tolevel) -+ getlocvar(fs, --fs->nactvar).endpc = fs->pc; -+} -+ -+ -+static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { -+ int i; -+ Proto *f = fs->f; -+ int oldsize = f->sizeupvalues; -+ for (i=0; inups; i++) { -+ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { -+ lua_assert(f->upvalues[i] == name); -+ return i; -+ } -+ } -+ /* new one */ -+ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); -+ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, -+ TString *, MAX_INT, ""); -+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; -+ f->upvalues[f->nups] = name; -+ luaC_objbarrier(fs->L, f, name); -+ lua_assert(v->k == VLOCAL || v->k == VUPVAL); -+ fs->upvalues[f->nups].k = cast_byte(v->k); -+ fs->upvalues[f->nups].info = cast_byte(v->u.s.info); -+ return f->nups++; -+} -+ -+ -+static int searchvar (FuncState *fs, TString *n) { -+ int i; -+ for (i=fs->nactvar-1; i >= 0; i--) { -+ if (n == getlocvar(fs, i).varname) -+ return i; -+ } -+ return -1; /* not found */ -+} -+ -+ -+static void markupval (FuncState *fs, int level) { -+ BlockCnt *bl = fs->bl; -+ while (bl && bl->nactvar > level) bl = bl->previous; -+ if (bl) bl->upval = 1; -+} -+ -+ -+static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { -+ if (fs == NULL) { /* no more levels? */ -+ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ -+ return VGLOBAL; -+ } -+ else { -+ int v = searchvar(fs, n); /* look up at current level */ -+ if (v >= 0) { -+ init_exp(var, VLOCAL, v); -+ if (!base) -+ markupval(fs, v); /* local will be used as an upval */ -+ return VLOCAL; -+ } -+ else { /* not found at current level; try upper one */ -+ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) -+ return VGLOBAL; -+ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ -+ var->k = VUPVAL; /* upvalue in this level */ -+ return VUPVAL; -+ } -+ } -+} -+ -+ -+static void singlevar (LexState *ls, expdesc *var) { -+ TString *varname = str_checkname(ls); -+ FuncState *fs = ls->fs; -+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL) -+ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ -+} -+ -+ -+static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { -+ FuncState *fs = ls->fs; -+ int extra = nvars - nexps; -+ if (hasmultret(e->k)) { -+ extra++; /* includes call itself */ -+ if (extra < 0) extra = 0; -+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ -+ if (extra > 1) luaK_reserveregs(fs, extra-1); -+ } -+ else { -+ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ -+ if (extra > 0) { -+ int reg = fs->freereg; -+ luaK_reserveregs(fs, extra); -+ luaK_nil(fs, reg, extra); -+ } -+ } -+} -+ -+ -+static void enterlevel (LexState *ls) { -+ if (++ls->L->nCcalls > LUAI_MAXCCALLS) -+ luaX_lexerror(ls, "chunk has too many syntax levels", 0); -+} -+ -+ -+#define leavelevel(ls) ((ls)->L->nCcalls--) -+ -+ -+static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { -+ bl->breaklist = NO_JUMP; -+ bl->isbreakable = isbreakable; -+ bl->nactvar = fs->nactvar; -+ bl->upval = 0; -+ bl->previous = fs->bl; -+ fs->bl = bl; -+ lua_assert(fs->freereg == fs->nactvar); -+} -+ -+ -+static void leaveblock (FuncState *fs) { -+ BlockCnt *bl = fs->bl; -+ fs->bl = bl->previous; -+ removevars(fs->ls, bl->nactvar); -+ if (bl->upval) -+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); -+ /* a block either controls scope or breaks (never both) */ -+ lua_assert(!bl->isbreakable || !bl->upval); -+ lua_assert(bl->nactvar == fs->nactvar); -+ fs->freereg = fs->nactvar; /* free registers */ -+ luaK_patchtohere(fs, bl->breaklist); -+} -+ -+ -+static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ int oldsize = f->sizep; -+ int i; -+ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, -+ MAXARG_Bx, "constant table overflow"); -+ while (oldsize < f->sizep) f->p[oldsize++] = NULL; -+ f->p[fs->np++] = func->f; -+ luaC_objbarrier(ls->L, f, func->f); -+ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); -+ for (i=0; if->nups; i++) { -+ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; -+ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); -+ } -+} -+ -+ -+static void open_func (LexState *ls, FuncState *fs) { -+ lua_State *L = ls->L; -+ Proto *f = luaF_newproto(L); -+ fs->f = f; -+ fs->prev = ls->fs; /* linked list of funcstates */ -+ fs->ls = ls; -+ fs->L = L; -+ ls->fs = fs; -+ fs->pc = 0; -+ fs->lasttarget = -1; -+ fs->jpc = NO_JUMP; -+ fs->freereg = 0; -+ fs->nk = 0; -+ fs->np = 0; -+ fs->nlocvars = 0; -+ fs->nactvar = 0; -+ fs->bl = NULL; -+ f->source = ls->source; -+ f->maxstacksize = 2; /* registers 0/1 are always valid */ -+ fs->h = luaH_new(L, 0, 0); -+ /* anchor table of constants and prototype (to avoid being collected) */ -+ sethvalue2s(L, L->top, fs->h); -+ incr_top(L); -+ setptvalue2s(L, L->top, f); -+ incr_top(L); -+} -+ -+ -+static void close_func (LexState *ls) { -+ lua_State *L = ls->L; -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ removevars(ls, 0); -+ luaK_ret(fs, 0, 0); /* final return */ -+ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); -+ f->sizecode = fs->pc; -+ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); -+ f->sizelineinfo = fs->pc; -+ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); -+ f->sizek = fs->nk; -+ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); -+ f->sizep = fs->np; -+ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); -+ f->sizelocvars = fs->nlocvars; -+ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); -+ f->sizeupvalues = f->nups; -+ lua_assert(luaG_checkcode(f)); -+ lua_assert(fs->bl == NULL); -+ ls->fs = fs->prev; -+ L->top -= 2; /* remove table and prototype from the stack */ -+ /* last token read was anchored in defunct function; must reanchor it */ -+ if (fs) anchor_token(ls); -+} -+ -+ -+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { -+ struct LexState lexstate; -+ struct FuncState funcstate; -+ lexstate.buff = buff; -+ luaX_setinput(L, &lexstate, z, luaS_new(L, name)); -+ open_func(&lexstate, &funcstate); -+ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ -+ luaX_next(&lexstate); /* read first token */ -+ chunk(&lexstate); -+ check(&lexstate, TK_EOS); -+ close_func(&lexstate); -+ lua_assert(funcstate.prev == NULL); -+ lua_assert(funcstate.f->nups == 0); -+ lua_assert(lexstate.fs == NULL); -+ return funcstate.f; -+} -+ -+ -+ -+/*============================================================*/ -+/* GRAMMAR RULES */ -+/*============================================================*/ -+ -+ -+static void field (LexState *ls, expdesc *v) { -+ /* field -> ['.' | ':'] NAME */ -+ FuncState *fs = ls->fs; -+ expdesc key; -+ luaK_exp2anyreg(fs, v); -+ luaX_next(ls); /* skip the dot or colon */ -+ checkname(ls, &key); -+ luaK_indexed(fs, v, &key); -+} -+ -+ -+static void yindex (LexState *ls, expdesc *v) { -+ /* index -> '[' expr ']' */ -+ luaX_next(ls); /* skip the '[' */ -+ expr(ls, v); -+ luaK_exp2val(ls->fs, v); -+ checknext(ls, ']'); -+} -+ -+ -+/* -+** {====================================================================== -+** Rules for Constructors -+** ======================================================================= -+*/ -+ -+ -+struct ConsControl { -+ expdesc v; /* last list item read */ -+ expdesc *t; /* table descriptor */ -+ int nh; /* total number of `record' elements */ -+ int na; /* total number of array elements */ -+ int tostore; /* number of array elements pending to be stored */ -+}; -+ -+ -+static void recfield (LexState *ls, struct ConsControl *cc) { -+ /* recfield -> (NAME | `['exp1`]') = exp1 */ -+ FuncState *fs = ls->fs; -+ int reg = ls->fs->freereg; -+ expdesc key, val; -+ int rkkey; -+ if (ls->t.token == TK_NAME) { -+ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); -+ checkname(ls, &key); -+ } -+ else /* ls->t.token == '[' */ -+ yindex(ls, &key); -+ cc->nh++; -+ checknext(ls, '='); -+ rkkey = luaK_exp2RK(fs, &key); -+ expr(ls, &val); -+ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); -+ fs->freereg = reg; /* free registers */ -+} -+ -+ -+static void closelistfield (FuncState *fs, struct ConsControl *cc) { -+ if (cc->v.k == VVOID) return; /* there is no list item */ -+ luaK_exp2nextreg(fs, &cc->v); -+ cc->v.k = VVOID; -+ if (cc->tostore == LFIELDS_PER_FLUSH) { -+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ -+ cc->tostore = 0; /* no more items pending */ -+ } -+} -+ -+ -+static void lastlistfield (FuncState *fs, struct ConsControl *cc) { -+ if (cc->tostore == 0) return; -+ if (hasmultret(cc->v.k)) { -+ luaK_setmultret(fs, &cc->v); -+ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); -+ cc->na--; /* do not count last expression (unknown number of elements) */ -+ } -+ else { -+ if (cc->v.k != VVOID) -+ luaK_exp2nextreg(fs, &cc->v); -+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); -+ } -+} -+ -+ -+static void listfield (LexState *ls, struct ConsControl *cc) { -+ expr(ls, &cc->v); -+ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); -+ cc->na++; -+ cc->tostore++; -+} -+ -+ -+static void constructor (LexState *ls, expdesc *t) { -+ /* constructor -> ?? */ -+ FuncState *fs = ls->fs; -+ int line = ls->linenumber; -+ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); -+ struct ConsControl cc; -+ cc.na = cc.nh = cc.tostore = 0; -+ cc.t = t; -+ init_exp(t, VRELOCABLE, pc); -+ init_exp(&cc.v, VVOID, 0); /* no value (yet) */ -+ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ -+ checknext(ls, '{'); -+ do { -+ lua_assert(cc.v.k == VVOID || cc.tostore > 0); -+ if (ls->t.token == '}') break; -+ closelistfield(fs, &cc); -+ switch(ls->t.token) { -+ case TK_NAME: { /* may be listfields or recfields */ -+ luaX_lookahead(ls); -+ if (ls->lookahead.token != '=') /* expression? */ -+ listfield(ls, &cc); -+ else -+ recfield(ls, &cc); -+ break; -+ } -+ case '[': { /* constructor_item -> recfield */ -+ recfield(ls, &cc); -+ break; -+ } -+ default: { /* constructor_part -> listfield */ -+ listfield(ls, &cc); -+ break; -+ } -+ } -+ } while (testnext(ls, ',') || testnext(ls, ';')); -+ check_match(ls, '}', '{', line); -+ lastlistfield(fs, &cc); -+ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ -+ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ -+} -+ -+/* }====================================================================== */ -+ -+ -+ -+static void parlist (LexState *ls) { -+ /* parlist -> [ param { `,' param } ] */ -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ int nparams = 0; -+ f->is_vararg = 0; -+ if (ls->t.token != ')') { /* is `parlist' not empty? */ -+ do { -+ switch (ls->t.token) { -+ case TK_NAME: { /* param -> NAME */ -+ new_localvar(ls, str_checkname(ls), nparams++); -+ break; -+ } -+ case TK_DOTS: { /* param -> `...' */ -+ luaX_next(ls); -+#if defined(LUA_COMPAT_VARARG) -+ /* use `arg' as default name */ -+ new_localvarliteral(ls, "arg", nparams++); -+ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; -+#endif -+ f->is_vararg |= VARARG_ISVARARG; -+ break; -+ } -+ default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); -+ } -+ } while (!f->is_vararg && testnext(ls, ',')); -+ } -+ adjustlocalvars(ls, nparams); -+ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); -+ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ -+} -+ -+ -+static void body (LexState *ls, expdesc *e, int needself, int line) { -+ /* body -> `(' parlist `)' chunk END */ -+ FuncState new_fs; -+ open_func(ls, &new_fs); -+ new_fs.f->linedefined = line; -+ checknext(ls, '('); -+ if (needself) { -+ new_localvarliteral(ls, "self", 0); -+ adjustlocalvars(ls, 1); -+ } -+ parlist(ls); -+ checknext(ls, ')'); -+ chunk(ls); -+ new_fs.f->lastlinedefined = ls->linenumber; -+ check_match(ls, TK_END, TK_FUNCTION, line); -+ close_func(ls); -+ pushclosure(ls, &new_fs, e); -+} -+ -+ -+static int explist1 (LexState *ls, expdesc *v) { -+ /* explist1 -> expr { `,' expr } */ -+ int n = 1; /* at least one expression */ -+ expr(ls, v); -+ while (testnext(ls, ',')) { -+ luaK_exp2nextreg(ls->fs, v); -+ expr(ls, v); -+ n++; -+ } -+ return n; -+} -+ -+ -+static void funcargs (LexState *ls, expdesc *f) { -+ FuncState *fs = ls->fs; -+ expdesc args; -+ int base, nparams; -+ int line = ls->linenumber; -+ switch (ls->t.token) { -+ case '(': { /* funcargs -> `(' [ explist1 ] `)' */ -+ if (line != ls->lastline) -+ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); -+ luaX_next(ls); -+ if (ls->t.token == ')') /* arg list is empty? */ -+ args.k = VVOID; -+ else { -+ explist1(ls, &args); -+ luaK_setmultret(fs, &args); -+ } -+ check_match(ls, ')', '(', line); -+ break; -+ } -+ case '{': { /* funcargs -> constructor */ -+ constructor(ls, &args); -+ break; -+ } -+ case TK_STRING: { /* funcargs -> STRING */ -+ codestring(ls, &args, ls->t.seminfo.ts); -+ luaX_next(ls); /* must use `seminfo' before `next' */ -+ break; -+ } -+ default: { -+ luaX_syntaxerror(ls, "function arguments expected"); -+ return; -+ } -+ } -+ lua_assert(f->k == VNONRELOC); -+ base = f->u.s.info; /* base register for call */ -+ if (hasmultret(args.k)) -+ nparams = LUA_MULTRET; /* open call */ -+ else { -+ if (args.k != VVOID) -+ luaK_exp2nextreg(fs, &args); /* close last argument */ -+ nparams = fs->freereg - (base+1); -+ } -+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); -+ luaK_fixline(fs, line); -+ fs->freereg = base+1; /* call remove function and arguments and leaves -+ (unless changed) one result */ -+} -+ -+ -+ -+ -+/* -+** {====================================================================== -+** Expression parsing -+** ======================================================================= -+*/ -+ -+ -+static void prefixexp (LexState *ls, expdesc *v) { -+ /* prefixexp -> NAME | '(' expr ')' */ -+ switch (ls->t.token) { -+ case '(': { -+ int line = ls->linenumber; -+ luaX_next(ls); -+ expr(ls, v); -+ check_match(ls, ')', '(', line); -+ luaK_dischargevars(ls->fs, v); -+ return; -+ } -+ case TK_NAME: { -+ singlevar(ls, v); -+ return; -+ } -+ default: { -+ luaX_syntaxerror(ls, "unexpected symbol"); -+ return; -+ } -+ } -+} -+ -+ -+static void primaryexp (LexState *ls, expdesc *v) { -+ /* primaryexp -> -+ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ -+ FuncState *fs = ls->fs; -+ prefixexp(ls, v); -+ for (;;) { -+ switch (ls->t.token) { -+ case '.': { /* field */ -+ field(ls, v); -+ break; -+ } -+ case '[': { /* `[' exp1 `]' */ -+ expdesc key; -+ luaK_exp2anyreg(fs, v); -+ yindex(ls, &key); -+ luaK_indexed(fs, v, &key); -+ break; -+ } -+ case ':': { /* `:' NAME funcargs */ -+ expdesc key; -+ luaX_next(ls); -+ checkname(ls, &key); -+ luaK_self(fs, v, &key); -+ funcargs(ls, v); -+ break; -+ } -+ case '(': case TK_STRING: case '{': { /* funcargs */ -+ luaK_exp2nextreg(fs, v); -+ funcargs(ls, v); -+ break; -+ } -+ default: return; -+ } -+ } -+} -+ -+ -+static void simpleexp (LexState *ls, expdesc *v) { -+ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | -+ constructor | FUNCTION body | primaryexp */ -+ switch (ls->t.token) { -+ case TK_NUMBER: { -+ init_exp(v, VKNUM, 0); -+ v->u.nval = ls->t.seminfo.r; -+ break; -+ } -+ case TK_STRING: { -+ codestring(ls, v, ls->t.seminfo.ts); -+ break; -+ } -+ case TK_NIL: { -+ init_exp(v, VNIL, 0); -+ break; -+ } -+ case TK_TRUE: { -+ init_exp(v, VTRUE, 0); -+ break; -+ } -+ case TK_FALSE: { -+ init_exp(v, VFALSE, 0); -+ break; -+ } -+ case TK_DOTS: { /* vararg */ -+ FuncState *fs = ls->fs; -+ check_condition(ls, fs->f->is_vararg, -+ "cannot use " LUA_QL("...") " outside a vararg function"); -+ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ -+ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); -+ break; -+ } -+ case '{': { /* constructor */ -+ constructor(ls, v); -+ return; -+ } -+ case TK_FUNCTION: { -+ luaX_next(ls); -+ body(ls, v, 0, ls->linenumber); -+ return; -+ } -+ default: { -+ primaryexp(ls, v); -+ return; -+ } -+ } -+ luaX_next(ls); -+} -+ -+ -+static UnOpr getunopr (int op) { -+ switch (op) { -+ case TK_NOT: return OPR_NOT; -+ case '-': return OPR_MINUS; -+ case '#': return OPR_LEN; -+ default: return OPR_NOUNOPR; -+ } -+} -+ -+ -+static BinOpr getbinopr (int op) { -+ switch (op) { -+ case '+': return OPR_ADD; -+ case '-': return OPR_SUB; -+ case '*': return OPR_MUL; -+ case '/': return OPR_DIV; -+ case '%': return OPR_MOD; -+ case '^': return OPR_POW; -+ case TK_CONCAT: return OPR_CONCAT; -+ case TK_NE: return OPR_NE; -+ case TK_EQ: return OPR_EQ; -+ case '<': return OPR_LT; -+ case TK_LE: return OPR_LE; -+ case '>': return OPR_GT; -+ case TK_GE: return OPR_GE; -+ case TK_AND: return OPR_AND; -+ case TK_OR: return OPR_OR; -+ default: return OPR_NOBINOPR; -+ } -+} -+ -+ -+static const struct { -+ lu_byte left; /* left priority for each binary operator */ -+ lu_byte right; /* right priority */ -+} priority[] = { /* ORDER OPR */ -+ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ -+ {10, 9}, {5, 4}, /* power and concat (right associative) */ -+ {3, 3}, {3, 3}, /* equality and inequality */ -+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ -+ {2, 2}, {1, 1} /* logical (and/or) */ -+}; -+ -+#define UNARY_PRIORITY 8 /* priority for unary operators */ -+ -+ -+/* -+** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -+** where `binop' is any binary operator with a priority higher than `limit' -+*/ -+static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { -+ BinOpr op; -+ UnOpr uop; -+ enterlevel(ls); -+ uop = getunopr(ls->t.token); -+ if (uop != OPR_NOUNOPR) { -+ luaX_next(ls); -+ subexpr(ls, v, UNARY_PRIORITY); -+ luaK_prefix(ls->fs, uop, v); -+ } -+ else simpleexp(ls, v); -+ /* expand while operators have priorities higher than `limit' */ -+ op = getbinopr(ls->t.token); -+ while (op != OPR_NOBINOPR && priority[op].left > limit) { -+ expdesc v2; -+ BinOpr nextop; -+ luaX_next(ls); -+ luaK_infix(ls->fs, op, v); -+ /* read sub-expression with higher priority */ -+ nextop = subexpr(ls, &v2, priority[op].right); -+ luaK_posfix(ls->fs, op, v, &v2); -+ op = nextop; -+ } -+ leavelevel(ls); -+ return op; /* return first untreated operator */ -+} -+ -+ -+static void expr (LexState *ls, expdesc *v) { -+ subexpr(ls, v, 0); -+} -+ -+/* }==================================================================== */ -+ -+ -+ -+/* -+** {====================================================================== -+** Rules for Statements -+** ======================================================================= -+*/ -+ -+ -+static int block_follow (int token) { -+ switch (token) { -+ case TK_ELSE: case TK_ELSEIF: case TK_END: -+ case TK_UNTIL: case TK_EOS: -+ return 1; -+ default: return 0; -+ } -+} -+ -+ -+static void block (LexState *ls) { -+ /* block -> chunk */ -+ FuncState *fs = ls->fs; -+ BlockCnt bl; -+ enterblock(fs, &bl, 0); -+ chunk(ls); -+ lua_assert(bl.breaklist == NO_JUMP); -+ leaveblock(fs); -+} -+ -+ -+/* -+** structure to chain all variables in the left-hand side of an -+** assignment -+*/ -+struct LHS_assign { -+ struct LHS_assign *prev; -+ expdesc v; /* variable (global, local, upvalue, or indexed) */ -+}; -+ -+ -+/* -+** check whether, in an assignment to a local variable, the local variable -+** is needed in a previous assignment (to a table). If so, save original -+** local value in a safe place and use this safe copy in the previous -+** assignment. -+*/ -+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { -+ FuncState *fs = ls->fs; -+ int extra = fs->freereg; /* eventual position to save local variable */ -+ int conflict = 0; -+ for (; lh; lh = lh->prev) { -+ if (lh->v.k == VINDEXED) { -+ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ -+ conflict = 1; -+ lh->v.u.s.info = extra; /* previous assignment will use safe copy */ -+ } -+ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ -+ conflict = 1; -+ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ -+ } -+ } -+ } -+ if (conflict) { -+ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ -+ luaK_reserveregs(fs, 1); -+ } -+} -+ -+ -+static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { -+ expdesc e; -+ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, -+ "syntax error"); -+ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ -+ struct LHS_assign nv; -+ nv.prev = lh; -+ primaryexp(ls, &nv.v); -+ if (nv.v.k == VLOCAL) -+ check_conflict(ls, lh, &nv.v); -+ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, -+ "variables in assignment"); -+ assignment(ls, &nv, nvars+1); -+ } -+ else { /* assignment -> `=' explist1 */ -+ int nexps; -+ checknext(ls, '='); -+ nexps = explist1(ls, &e); -+ if (nexps != nvars) { -+ adjust_assign(ls, nvars, nexps, &e); -+ if (nexps > nvars) -+ ls->fs->freereg -= nexps - nvars; /* remove extra values */ -+ } -+ else { -+ luaK_setoneret(ls->fs, &e); /* close last expression */ -+ luaK_storevar(ls->fs, &lh->v, &e); -+ return; /* avoid default */ -+ } -+ } -+ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ -+ luaK_storevar(ls->fs, &lh->v, &e); -+} -+ -+ -+static int cond (LexState *ls) { -+ /* cond -> exp */ -+ expdesc v; -+ expr(ls, &v); /* read condition */ -+ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ -+ luaK_goiftrue(ls->fs, &v); -+ return v.f; -+} -+ -+ -+static void breakstat (LexState *ls) { -+ FuncState *fs = ls->fs; -+ BlockCnt *bl = fs->bl; -+ int upval = 0; -+ while (bl && !bl->isbreakable) { -+ upval |= bl->upval; -+ bl = bl->previous; -+ } -+ if (!bl) -+ luaX_syntaxerror(ls, "no loop to break"); -+ if (upval) -+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); -+ luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); -+} -+ -+ -+static void whilestat (LexState *ls, int line) { -+ /* whilestat -> WHILE cond DO block END */ -+ FuncState *fs = ls->fs; -+ int whileinit; -+ int condexit; -+ BlockCnt bl; -+ luaX_next(ls); /* skip WHILE */ -+ whileinit = luaK_getlabel(fs); -+ condexit = cond(ls); -+ enterblock(fs, &bl, 1); -+ checknext(ls, TK_DO); -+ block(ls); -+ luaK_patchlist(fs, luaK_jump(fs), whileinit); -+ check_match(ls, TK_END, TK_WHILE, line); -+ leaveblock(fs); -+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -+} -+ -+ -+static void repeatstat (LexState *ls, int line) { -+ /* repeatstat -> REPEAT block UNTIL cond */ -+ int condexit; -+ FuncState *fs = ls->fs; -+ int repeat_init = luaK_getlabel(fs); -+ BlockCnt bl1, bl2; -+ enterblock(fs, &bl1, 1); /* loop block */ -+ enterblock(fs, &bl2, 0); /* scope block */ -+ luaX_next(ls); /* skip REPEAT */ -+ chunk(ls); -+ check_match(ls, TK_UNTIL, TK_REPEAT, line); -+ condexit = cond(ls); /* read condition (inside scope block) */ -+ if (!bl2.upval) { /* no upvalues? */ -+ leaveblock(fs); /* finish scope */ -+ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ -+ } -+ else { /* complete semantics when there are upvalues */ -+ breakstat(ls); /* if condition then break */ -+ luaK_patchtohere(ls->fs, condexit); /* else... */ -+ leaveblock(fs); /* finish scope... */ -+ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ -+ } -+ leaveblock(fs); /* finish loop */ -+} -+ -+ -+static int exp1 (LexState *ls) { -+ expdesc e; -+ int k; -+ expr(ls, &e); -+ k = e.k; -+ luaK_exp2nextreg(ls->fs, &e); -+ return k; -+} -+ -+ -+static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { -+ /* forbody -> DO block */ -+ BlockCnt bl; -+ FuncState *fs = ls->fs; -+ int prep, endfor; -+ adjustlocalvars(ls, 3); /* control variables */ -+ checknext(ls, TK_DO); -+ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); -+ enterblock(fs, &bl, 0); /* scope for declared variables */ -+ adjustlocalvars(ls, nvars); -+ luaK_reserveregs(fs, nvars); -+ block(ls); -+ leaveblock(fs); /* end of scope for declared variables */ -+ luaK_patchtohere(fs, prep); -+ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : -+ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); -+ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ -+ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); -+} -+ -+ -+static void fornum (LexState *ls, TString *varname, int line) { -+ /* fornum -> NAME = exp1,exp1[,exp1] forbody */ -+ FuncState *fs = ls->fs; -+ int base = fs->freereg; -+ new_localvarliteral(ls, "(for index)", 0); -+ new_localvarliteral(ls, "(for limit)", 1); -+ new_localvarliteral(ls, "(for step)", 2); -+ new_localvar(ls, varname, 3); -+ checknext(ls, '='); -+ exp1(ls); /* initial value */ -+ checknext(ls, ','); -+ exp1(ls); /* limit */ -+ if (testnext(ls, ',')) -+ exp1(ls); /* optional step */ -+ else { /* default step = 1 */ -+ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); -+ luaK_reserveregs(fs, 1); -+ } -+ forbody(ls, base, line, 1, 1); -+} -+ -+ -+static void forlist (LexState *ls, TString *indexname) { -+ /* forlist -> NAME {,NAME} IN explist1 forbody */ -+ FuncState *fs = ls->fs; -+ expdesc e; -+ int nvars = 0; -+ int line; -+ int base = fs->freereg; -+ /* create control variables */ -+ new_localvarliteral(ls, "(for generator)", nvars++); -+ new_localvarliteral(ls, "(for state)", nvars++); -+ new_localvarliteral(ls, "(for control)", nvars++); -+ /* create declared variables */ -+ new_localvar(ls, indexname, nvars++); -+ while (testnext(ls, ',')) -+ new_localvar(ls, str_checkname(ls), nvars++); -+ checknext(ls, TK_IN); -+ line = ls->linenumber; -+ adjust_assign(ls, 3, explist1(ls, &e), &e); -+ luaK_checkstack(fs, 3); /* extra space to call generator */ -+ forbody(ls, base, line, nvars - 3, 0); -+} -+ -+ -+static void forstat (LexState *ls, int line) { -+ /* forstat -> FOR (fornum | forlist) END */ -+ FuncState *fs = ls->fs; -+ TString *varname; -+ BlockCnt bl; -+ enterblock(fs, &bl, 1); /* scope for loop and control variables */ -+ luaX_next(ls); /* skip `for' */ -+ varname = str_checkname(ls); /* first variable name */ -+ switch (ls->t.token) { -+ case '=': fornum(ls, varname, line); break; -+ case ',': case TK_IN: forlist(ls, varname); break; -+ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); -+ } -+ check_match(ls, TK_END, TK_FOR, line); -+ leaveblock(fs); /* loop scope (`break' jumps to this point) */ -+} -+ -+ -+static int test_then_block (LexState *ls) { -+ /* test_then_block -> [IF | ELSEIF] cond THEN block */ -+ int condexit; -+ luaX_next(ls); /* skip IF or ELSEIF */ -+ condexit = cond(ls); -+ checknext(ls, TK_THEN); -+ block(ls); /* `then' part */ -+ return condexit; -+} -+ -+ -+static void ifstat (LexState *ls, int line) { -+ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ -+ FuncState *fs = ls->fs; -+ int flist; -+ int escapelist = NO_JUMP; -+ flist = test_then_block(ls); /* IF cond THEN block */ -+ while (ls->t.token == TK_ELSEIF) { -+ luaK_concat(fs, &escapelist, luaK_jump(fs)); -+ luaK_patchtohere(fs, flist); -+ flist = test_then_block(ls); /* ELSEIF cond THEN block */ -+ } -+ if (ls->t.token == TK_ELSE) { -+ luaK_concat(fs, &escapelist, luaK_jump(fs)); -+ luaK_patchtohere(fs, flist); -+ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ -+ block(ls); /* `else' part */ -+ } -+ else -+ luaK_concat(fs, &escapelist, flist); -+ luaK_patchtohere(fs, escapelist); -+ check_match(ls, TK_END, TK_IF, line); -+} -+ -+ -+static void localfunc (LexState *ls) { -+ expdesc v, b; -+ FuncState *fs = ls->fs; -+ new_localvar(ls, str_checkname(ls), 0); -+ init_exp(&v, VLOCAL, fs->freereg); -+ luaK_reserveregs(fs, 1); -+ adjustlocalvars(ls, 1); -+ body(ls, &b, 0, ls->linenumber); -+ luaK_storevar(fs, &v, &b); -+ /* debug information will only see the variable after this point! */ -+ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; -+} -+ -+ -+static void localstat (LexState *ls) { -+ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ -+ int nvars = 0; -+ int nexps; -+ expdesc e; -+ do { -+ new_localvar(ls, str_checkname(ls), nvars++); -+ } while (testnext(ls, ',')); -+ if (testnext(ls, '=')) -+ nexps = explist1(ls, &e); -+ else { -+ e.k = VVOID; -+ nexps = 0; -+ } -+ adjust_assign(ls, nvars, nexps, &e); -+ adjustlocalvars(ls, nvars); -+} -+ -+ -+static int funcname (LexState *ls, expdesc *v) { -+ /* funcname -> NAME {field} [`:' NAME] */ -+ int needself = 0; -+ singlevar(ls, v); -+ while (ls->t.token == '.') -+ field(ls, v); -+ if (ls->t.token == ':') { -+ needself = 1; -+ field(ls, v); -+ } -+ return needself; -+} -+ -+ -+static void funcstat (LexState *ls, int line) { -+ /* funcstat -> FUNCTION funcname body */ -+ int needself; -+ expdesc v, b; -+ luaX_next(ls); /* skip FUNCTION */ -+ needself = funcname(ls, &v); -+ body(ls, &b, needself, line); -+ luaK_storevar(ls->fs, &v, &b); -+ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ -+} -+ -+ -+static void exprstat (LexState *ls) { -+ /* stat -> func | assignment */ -+ FuncState *fs = ls->fs; -+ struct LHS_assign v; -+ primaryexp(ls, &v.v); -+ if (v.v.k == VCALL) /* stat -> func */ -+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ -+ else { /* stat -> assignment */ -+ v.prev = NULL; -+ assignment(ls, &v, 1); -+ } -+} -+ -+ -+static void retstat (LexState *ls) { -+ /* stat -> RETURN explist */ -+ FuncState *fs = ls->fs; -+ expdesc e; -+ int first, nret; /* registers with returned values */ -+ luaX_next(ls); /* skip RETURN */ -+ if (block_follow(ls->t.token) || ls->t.token == ';') -+ first = nret = 0; /* return no values */ -+ else { -+ nret = explist1(ls, &e); /* optional return values */ -+ if (hasmultret(e.k)) { -+ luaK_setmultret(fs, &e); -+ if (e.k == VCALL && nret == 1) { /* tail call? */ -+ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); -+ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); -+ } -+ first = fs->nactvar; -+ nret = LUA_MULTRET; /* return all values */ -+ } -+ else { -+ if (nret == 1) /* only one single value? */ -+ first = luaK_exp2anyreg(fs, &e); -+ else { -+ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ -+ first = fs->nactvar; /* return all `active' values */ -+ lua_assert(nret == fs->freereg - first); -+ } -+ } -+ } -+ luaK_ret(fs, first, nret); -+} -+ -+ -+static int statement (LexState *ls) { -+ int line = ls->linenumber; /* may be needed for error messages */ -+ switch (ls->t.token) { -+ case TK_IF: { /* stat -> ifstat */ -+ ifstat(ls, line); -+ return 0; -+ } -+ case TK_WHILE: { /* stat -> whilestat */ -+ whilestat(ls, line); -+ return 0; -+ } -+ case TK_DO: { /* stat -> DO block END */ -+ luaX_next(ls); /* skip DO */ -+ block(ls); -+ check_match(ls, TK_END, TK_DO, line); -+ return 0; -+ } -+ case TK_FOR: { /* stat -> forstat */ -+ forstat(ls, line); -+ return 0; -+ } -+ case TK_REPEAT: { /* stat -> repeatstat */ -+ repeatstat(ls, line); -+ return 0; -+ } -+ case TK_FUNCTION: { -+ funcstat(ls, line); /* stat -> funcstat */ -+ return 0; -+ } -+ case TK_LOCAL: { /* stat -> localstat */ -+ luaX_next(ls); /* skip LOCAL */ -+ if (testnext(ls, TK_FUNCTION)) /* local function? */ -+ localfunc(ls); -+ else -+ localstat(ls); -+ return 0; -+ } -+ case TK_RETURN: { /* stat -> retstat */ -+ retstat(ls); -+ return 1; /* must be last statement */ -+ } -+ case TK_BREAK: { /* stat -> breakstat */ -+ luaX_next(ls); /* skip BREAK */ -+ breakstat(ls); -+ return 1; /* must be last statement */ -+ } -+ default: { -+ exprstat(ls); -+ return 0; /* to avoid warnings */ -+ } -+ } -+} -+ -+ -+static void chunk (LexState *ls) { -+ /* chunk -> { stat [`;'] } */ -+ int islast = 0; -+ enterlevel(ls); -+ while (!islast && !block_follow(ls->t.token)) { -+ islast = statement(ls); -+ testnext(ls, ';'); -+ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && -+ ls->fs->freereg >= ls->fs->nactvar); -+ ls->fs->freereg = ls->fs->nactvar; /* free registers */ -+ } -+ leavelevel(ls); -+} -+ -+/* }====================================================================== */ ---- /dev/null -+++ b/extensions/LUA/lua/lparser.h -@@ -0,0 +1,82 @@ -+/* -+** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua Parser -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lparser_h -+#define lparser_h -+ -+#include "llimits.h" -+#include "lobject.h" -+#include "lzio.h" -+ -+ -+/* -+** Expression descriptor -+*/ -+ -+typedef enum { -+ VVOID, /* no value */ -+ VNIL, -+ VTRUE, -+ VFALSE, -+ VK, /* info = index of constant in `k' */ -+ VKNUM, /* nval = numerical value */ -+ VLOCAL, /* info = local register */ -+ VUPVAL, /* info = index of upvalue in `upvalues' */ -+ VGLOBAL, /* info = index of table; aux = index of global name in `k' */ -+ VINDEXED, /* info = table register; aux = index register (or `k') */ -+ VJMP, /* info = instruction pc */ -+ VRELOCABLE, /* info = instruction pc */ -+ VNONRELOC, /* info = result register */ -+ VCALL, /* info = instruction pc */ -+ VVARARG /* info = instruction pc */ -+} expkind; -+ -+typedef struct expdesc { -+ expkind k; -+ union { -+ struct { int info, aux; } s; -+ lua_Number nval; -+ } u; -+ int t; /* patch list of `exit when true' */ -+ int f; /* patch list of `exit when false' */ -+} expdesc; -+ -+ -+typedef struct upvaldesc { -+ lu_byte k; -+ lu_byte info; -+} upvaldesc; -+ -+ -+struct BlockCnt; /* defined in lparser.c */ -+ -+ -+/* state needed to generate code for a given function */ -+typedef struct FuncState { -+ Proto *f; /* current function header */ -+ Table *h; /* table to find (and reuse) elements in `k' */ -+ struct FuncState *prev; /* enclosing function */ -+ struct LexState *ls; /* lexical state */ -+ struct lua_State *L; /* copy of the Lua state */ -+ struct BlockCnt *bl; /* chain of current blocks */ -+ int pc; /* next position to code (equivalent to `ncode') */ -+ int lasttarget; /* `pc' of last `jump target' */ -+ int jpc; /* list of pending jumps to `pc' */ -+ int freereg; /* first free register */ -+ int nk; /* number of elements in `k' */ -+ int np; /* number of elements in `p' */ -+ short nlocvars; /* number of elements in `locvars' */ -+ lu_byte nactvar; /* number of active local variables */ -+ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ -+ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ -+} FuncState; -+ -+ -+LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, -+ const char *name); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lstate.c -@@ -0,0 +1,214 @@ -+/* -+** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ -+** Global State -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lstate_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "llex.h" -+#include "lmem.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+ -+ -+#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -+#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) -+#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) -+ -+ -+/* -+** Main thread combines a thread state and the global state -+*/ -+typedef struct LG { -+ lua_State l; -+ global_State g; -+} LG; -+ -+ -+ -+static void stack_init (lua_State *L1, lua_State *L) { -+ /* initialize CallInfo array */ -+ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); -+ L1->ci = L1->base_ci; -+ L1->size_ci = BASIC_CI_SIZE; -+ L1->end_ci = L1->base_ci + L1->size_ci - 1; -+ /* initialize stack array */ -+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); -+ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; -+ L1->top = L1->stack; -+ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; -+ /* initialize first ci */ -+ L1->ci->func = L1->top; -+ setnilvalue(L1->top++); /* `function' entry for this `ci' */ -+ L1->base = L1->ci->base = L1->top; -+ L1->ci->top = L1->top + LUA_MINSTACK; -+} -+ -+ -+static void freestack (lua_State *L, lua_State *L1) { -+ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); -+ luaM_freearray(L, L1->stack, L1->stacksize, TValue); -+} -+ -+ -+/* -+** open parts that may cause memory-allocation errors -+*/ -+static void f_luaopen (lua_State *L, void *ud) { -+ global_State *g = G(L); -+ UNUSED(ud); -+ stack_init(L, L); /* init stack */ -+ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ -+ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ -+ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ -+ luaT_init(L); -+ luaX_init(L); -+ luaS_fix(luaS_newliteral(L, MEMERRMSG)); -+ g->GCthreshold = 4*g->totalbytes; -+} -+ -+ -+static void preinit_state (lua_State *L, global_State *g) { -+ G(L) = g; -+ L->stack = NULL; -+ L->stacksize = 0; -+ L->errorJmp = NULL; -+ L->hook = NULL; -+ L->hookmask = 0; -+ L->basehookcount = 0; -+ L->allowhook = 1; -+ resethookcount(L); -+ L->openupval = NULL; -+ L->size_ci = 0; -+ L->nCcalls = L->baseCcalls = 0; -+ L->status = 0; -+ L->base_ci = L->ci = NULL; -+ L->savedpc = NULL; -+ L->errfunc = 0; -+ setnilvalue(gt(L)); -+} -+ -+ -+static void close_state (lua_State *L) { -+ global_State *g = G(L); -+ luaF_close(L, L->stack); /* close all upvalues for this thread */ -+ luaC_freeall(L); /* collect all objects */ -+ lua_assert(g->rootgc == obj2gco(L)); -+ lua_assert(g->strt.nuse == 0); -+ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); -+ luaZ_freebuffer(L, &g->buff); -+ freestack(L, L); -+ lua_assert(g->totalbytes == sizeof(LG)); -+ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); -+} -+ -+ -+lua_State *luaE_newthread (lua_State *L) { -+ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); -+ luaC_link(L, obj2gco(L1), LUA_TTHREAD); -+ preinit_state(L1, G(L)); -+ stack_init(L1, L); /* init stack */ -+ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ -+ L1->hookmask = L->hookmask; -+ L1->basehookcount = L->basehookcount; -+ L1->hook = L->hook; -+ resethookcount(L1); -+ lua_assert(iswhite(obj2gco(L1))); -+ return L1; -+} -+ -+ -+void luaE_freethread (lua_State *L, lua_State *L1) { -+ luaF_close(L1, L1->stack); /* close all upvalues for this thread */ -+ lua_assert(L1->openupval == NULL); -+ luai_userstatefree(L1); -+ freestack(L, L1); -+ luaM_freemem(L, fromstate(L1), state_size(lua_State)); -+} -+ -+ -+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { -+ int i; -+ lua_State *L; -+ global_State *g; -+ void *l = (*f)(ud, NULL, 0, state_size(LG)); -+ if (l == NULL) return NULL; -+ L = tostate(l); -+ g = &((LG *)L)->g; -+ L->next = NULL; -+ L->tt = LUA_TTHREAD; -+ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); -+ L->marked = luaC_white(g); -+ set2bits(L->marked, FIXEDBIT, SFIXEDBIT); -+ preinit_state(L, g); -+ g->frealloc = f; -+ g->ud = ud; -+ g->mainthread = L; -+ g->uvhead.u.l.prev = &g->uvhead; -+ g->uvhead.u.l.next = &g->uvhead; -+ g->GCthreshold = 0; /* mark it as unfinished state */ -+ g->strt.size = 0; -+ g->strt.nuse = 0; -+ g->strt.hash = NULL; -+ setnilvalue(registry(L)); -+ luaZ_initbuffer(L, &g->buff); -+ g->panic = NULL; -+ g->gcstate = GCSpause; -+ g->rootgc = obj2gco(L); -+ g->sweepstrgc = 0; -+ g->sweepgc = &g->rootgc; -+ g->gray = NULL; -+ g->grayagain = NULL; -+ g->weak = NULL; -+ g->tmudata = NULL; -+ g->totalbytes = sizeof(LG); -+ g->gcpause = LUAI_GCPAUSE; -+ g->gcstepmul = LUAI_GCMUL; -+ g->gcdept = 0; -+ for (i=0; imt[i] = NULL; -+ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { -+ /* memory allocation error: free partial state */ -+ close_state(L); -+ L = NULL; -+ } -+ else -+ luai_userstateopen(L); -+ return L; -+} -+ -+ -+static void callallgcTM (lua_State *L, void *ud) { -+ UNUSED(ud); -+ luaC_callGCTM(L); /* call GC metamethods for all udata */ -+} -+ -+ -+LUA_API void lua_close (lua_State *L) { -+ L = G(L)->mainthread; /* only the main thread can be closed */ -+ lua_lock(L); -+ luaF_close(L, L->stack); /* close all upvalues for this thread */ -+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ -+ L->errfunc = 0; /* no error function during GC metamethods */ -+ do { /* repeat until no more errors */ -+ L->ci = L->base_ci; -+ L->base = L->top = L->ci->base; -+ L->nCcalls = L->baseCcalls = 0; -+ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); -+ lua_assert(G(L)->tmudata == NULL); -+ luai_userstateclose(L); -+ close_state(L); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lstate.h -@@ -0,0 +1,169 @@ -+/* -+** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ -+** Global State -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lstate_h -+#define lstate_h -+ -+#include "lua.h" -+ -+#include "lobject.h" -+#include "ltm.h" -+#include "lzio.h" -+ -+ -+ -+struct lua_longjmp; /* defined in ldo.c */ -+ -+ -+/* table of globals */ -+#define gt(L) (&L->l_gt) -+ -+/* registry */ -+#define registry(L) (&G(L)->l_registry) -+ -+ -+/* extra stack space to handle TM calls and some other extras */ -+#define EXTRA_STACK 5 -+ -+ -+#define BASIC_CI_SIZE 8 -+ -+#define BASIC_STACK_SIZE (2*LUA_MINSTACK) -+ -+ -+ -+typedef struct stringtable { -+ GCObject **hash; -+ lu_int32 nuse; /* number of elements */ -+ int size; -+} stringtable; -+ -+ -+/* -+** informations about a call -+*/ -+typedef struct CallInfo { -+ StkId base; /* base for this function */ -+ StkId func; /* function index in the stack */ -+ StkId top; /* top for this function */ -+ const Instruction *savedpc; -+ int nresults; /* expected number of results from this function */ -+ int tailcalls; /* number of tail calls lost under this entry */ -+} CallInfo; -+ -+ -+ -+#define curr_func(L) (clvalue(L->ci->func)) -+#define ci_func(ci) (clvalue((ci)->func)) -+#define f_isLua(ci) (!ci_func(ci)->c.isC) -+#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) -+ -+ -+/* -+** `global state', shared by all threads of this state -+*/ -+typedef struct global_State { -+ stringtable strt; /* hash table for strings */ -+ lua_Alloc frealloc; /* function to reallocate memory */ -+ void *ud; /* auxiliary data to `frealloc' */ -+ lu_byte currentwhite; -+ lu_byte gcstate; /* state of garbage collector */ -+ int sweepstrgc; /* position of sweep in `strt' */ -+ GCObject *rootgc; /* list of all collectable objects */ -+ GCObject **sweepgc; /* position of sweep in `rootgc' */ -+ GCObject *gray; /* list of gray objects */ -+ GCObject *grayagain; /* list of objects to be traversed atomically */ -+ GCObject *weak; /* list of weak tables (to be cleared) */ -+ GCObject *tmudata; /* last element of list of userdata to be GC */ -+ Mbuffer buff; /* temporary buffer for string concatentation */ -+ lu_mem GCthreshold; -+ lu_mem totalbytes; /* number of bytes currently allocated */ -+ lu_mem estimate; /* an estimate of number of bytes actually in use */ -+ lu_mem gcdept; /* how much GC is `behind schedule' */ -+ int gcpause; /* size of pause between successive GCs */ -+ int gcstepmul; /* GC `granularity' */ -+ lua_CFunction panic; /* to be called in unprotected errors */ -+ TValue l_registry; -+ struct lua_State *mainthread; -+ UpVal uvhead; /* head of double-linked list of all open upvalues */ -+ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ -+ TString *tmname[TM_N]; /* array with tag-method names */ -+} global_State; -+ -+ -+/* -+** `per thread' state -+*/ -+struct lua_State { -+ CommonHeader; -+ lu_byte status; -+ StkId top; /* first free slot in the stack */ -+ StkId base; /* base of current function */ -+ global_State *l_G; -+ CallInfo *ci; /* call info for current function */ -+ const Instruction *savedpc; /* `savedpc' of current function */ -+ StkId stack_last; /* last free slot in the stack */ -+ StkId stack; /* stack base */ -+ CallInfo *end_ci; /* points after end of ci array*/ -+ CallInfo *base_ci; /* array of CallInfo's */ -+ int stacksize; -+ int size_ci; /* size of array `base_ci' */ -+ unsigned short nCcalls; /* number of nested C calls */ -+ unsigned short baseCcalls; /* nested C calls when resuming coroutine */ -+ lu_byte hookmask; -+ lu_byte allowhook; -+ int basehookcount; -+ int hookcount; -+ lua_Hook hook; -+ TValue l_gt; /* table of globals */ -+ TValue env; /* temporary place for environments */ -+ GCObject *openupval; /* list of open upvalues in this stack */ -+ GCObject *gclist; -+ struct lua_longjmp *errorJmp; /* current error recover point */ -+ ptrdiff_t errfunc; /* current error handling function (stack index) */ -+}; -+ -+ -+#define G(L) (L->l_G) -+ -+ -+/* -+** Union of all collectable objects -+*/ -+union GCObject { -+ GCheader gch; -+ union TString ts; -+ union Udata u; -+ union Closure cl; -+ struct Table h; -+ struct Proto p; -+ struct UpVal uv; -+ struct lua_State th; /* thread */ -+}; -+ -+ -+/* macros to convert a GCObject into a specific value */ -+#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) -+#define gco2ts(o) (&rawgco2ts(o)->tsv) -+#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -+#define gco2u(o) (&rawgco2u(o)->uv) -+#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) -+#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -+#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -+#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -+#define ngcotouv(o) \ -+ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -+#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) -+ -+/* macro to convert any Lua object into a GCObject */ -+#define obj2gco(v) (cast(GCObject *, (v))) -+ -+ -+LUAI_FUNC lua_State *luaE_newthread (lua_State *L); -+LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lstring.c -@@ -0,0 +1,110 @@ -+/* -+** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -+** String table (keeps all strings handled by Lua) -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lstring_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+ -+ -+ -+void luaS_resize (lua_State *L, int newsize) { -+ GCObject **newhash; -+ stringtable *tb; -+ int i; -+ if (G(L)->gcstate == GCSsweepstring) -+ return; /* cannot resize during GC traverse */ -+ newhash = luaM_newvector(L, newsize, GCObject *); -+ tb = &G(L)->strt; -+ for (i=0; isize; i++) { -+ GCObject *p = tb->hash[i]; -+ while (p) { /* for each node in the list */ -+ GCObject *next = p->gch.next; /* save next */ -+ unsigned int h = gco2ts(p)->hash; -+ int h1 = lmod(h, newsize); /* new position */ -+ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); -+ p->gch.next = newhash[h1]; /* chain it */ -+ newhash[h1] = p; -+ p = next; -+ } -+ } -+ luaM_freearray(L, tb->hash, tb->size, TString *); -+ tb->size = newsize; -+ tb->hash = newhash; -+} -+ -+ -+static TString *newlstr (lua_State *L, const char *str, size_t l, -+ unsigned int h) { -+ TString *ts; -+ stringtable *tb; -+ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) -+ luaM_toobig(L); -+ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); -+ ts->tsv.len = l; -+ ts->tsv.hash = h; -+ ts->tsv.marked = luaC_white(G(L)); -+ ts->tsv.tt = LUA_TSTRING; -+ ts->tsv.reserved = 0; -+ memcpy(ts+1, str, l*sizeof(char)); -+ ((char *)(ts+1))[l] = '\0'; /* ending 0 */ -+ tb = &G(L)->strt; -+ h = lmod(h, tb->size); -+ ts->tsv.next = tb->hash[h]; /* chain new entry */ -+ tb->hash[h] = obj2gco(ts); -+ tb->nuse++; -+ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) -+ luaS_resize(L, tb->size*2); /* too crowded */ -+ return ts; -+} -+ -+ -+TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { -+ GCObject *o; -+ unsigned int h = cast(unsigned int, l); /* seed */ -+ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ -+ size_t l1; -+ for (l1=l; l1>=step; l1-=step) /* compute hash */ -+ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); -+ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; -+ o != NULL; -+ o = o->gch.next) { -+ TString *ts = rawgco2ts(o); -+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { -+ /* string may be dead */ -+ if (isdead(G(L), o)) changewhite(o); -+ return ts; -+ } -+ } -+ return newlstr(L, str, l, h); /* not found */ -+} -+ -+ -+Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { -+ Udata *u; -+ if (s > MAX_SIZET - sizeof(Udata)) -+ luaM_toobig(L); -+ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); -+ u->uv.marked = luaC_white(G(L)); /* is not finalized */ -+ u->uv.tt = LUA_TUSERDATA; -+ u->uv.len = s; -+ u->uv.metatable = NULL; -+ u->uv.env = e; -+ /* chain it on udata list (after main thread) */ -+ u->uv.next = G(L)->mainthread->next; -+ G(L)->mainthread->next = obj2gco(u); -+ return u; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lstring.h -@@ -0,0 +1,31 @@ -+/* -+** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ -+** String table (keep all strings handled by Lua) -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lstring_h -+#define lstring_h -+ -+ -+#include "lgc.h" -+#include "lobject.h" -+#include "lstate.h" -+ -+ -+#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) -+ -+#define sizeudata(u) (sizeof(union Udata)+(u)->len) -+ -+#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -+#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ -+ (sizeof(s)/sizeof(char))-1)) -+ -+#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) -+ -+LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); -+LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lstrlib.c -@@ -0,0 +1,883 @@ -+/* -+** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ -+** Standard library for string operations and pattern-matching -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define lstrlib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+#include "lualib.h" -+ -+ -+/* macro to `unsign' a character */ -+#define uchar(c) ((unsigned char)(c)) -+ -+ -+ -+static int str_len (lua_State *L) { -+ size_t l; -+ luaL_checklstring(L, 1, &l); -+ lua_pushinteger(L, l); -+ return 1; -+} -+ -+ -+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { -+ /* relative string position: negative means back from end */ -+ if (pos < 0) pos += (ptrdiff_t)len + 1; -+ return (pos >= 0) ? pos : 0; -+} -+ -+ -+static int str_sub (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); -+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); -+ if (start < 1) start = 1; -+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; -+ if (start <= end) -+ lua_pushlstring(L, s+start-1, end-start+1); -+ else lua_pushliteral(L, ""); -+ return 1; -+} -+ -+ -+static int str_reverse (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_reverse: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ while (l--) luaL_addchar(b, s[l]); -+ luaL_pushresult(b); -+ kfree(b); -+ return 1; -+} -+ -+ -+static int str_lower (lua_State *L) { -+ size_t l; -+ size_t i; -+ const char *s = luaL_checklstring(L, 1, &l); -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_lower: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ for (i=0; i 0) -+ luaL_addlstring(b, s, l); -+ luaL_pushresult(b); -+ kfree(b); -+ return 1; -+} -+ -+ -+static int str_byte (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); -+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); -+ int n, i; -+ if (posi <= 0) posi = 1; -+ if ((size_t)pose > l) pose = l; -+ if (posi > pose) return 0; /* empty interval; return no values */ -+ n = (int)(pose - posi + 1); -+ if (posi + n <= pose) /* overflow? */ -+ luaL_error(L, "string slice too long"); -+ luaL_checkstack(L, n, "string slice too long"); -+ for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) -+ return luaL_error(ms->L, "invalid capture index"); -+ return l; -+} -+ -+ -+static int capture_to_close (MatchState *ms) { -+ int level = ms->level; -+ for (level--; level>=0; level--) -+ if (ms->capture[level].len == CAP_UNFINISHED) return level; -+ return luaL_error(ms->L, "invalid pattern capture"); -+} -+ -+ -+static const char *classend (MatchState *ms, const char *p) { -+ switch (*p++) { -+ case L_ESC: { -+ if (*p == '\0') -+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); -+ return p+1; -+ } -+ case '[': { -+ if (*p == '^') p++; -+ do { /* look for a `]' */ -+ if (*p == '\0') -+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); -+ if (*(p++) == L_ESC && *p != '\0') -+ p++; /* skip escapes (e.g. `%]') */ -+ } while (*p != ']'); -+ return p+1; -+ } -+ default: { -+ return p; -+ } -+ } -+} -+ -+ -+static int match_class (int c, int cl) { -+ int res; -+ switch (tolower(cl)) { -+ case 'a' : res = isalpha(c); break; -+ case 'c' : res = iscntrl(c); break; -+ case 'd' : res = isdigit(c); break; -+ case 'l' : res = islower(c); break; -+ case 'p' : res = ispunct(c); break; -+ case 's' : res = isspace(c); break; -+ case 'u' : res = isupper(c); break; -+ case 'w' : res = isalnum(c); break; -+ case 'x' : res = isxdigit(c); break; -+ case 'z' : res = (c == 0); break; -+ default: return (cl == c); -+ } -+ return (islower(cl) ? res : !res); -+} -+ -+ -+static int matchbracketclass (int c, const char *p, const char *ec) { -+ int sig = 1; -+ if (*(p+1) == '^') { -+ sig = 0; -+ p++; /* skip the `^' */ -+ } -+ while (++p < ec) { -+ if (*p == L_ESC) { -+ p++; -+ if (match_class(c, uchar(*p))) -+ return sig; -+ } -+ else if ((*(p+1) == '-') && (p+2 < ec)) { -+ p+=2; -+ if (uchar(*(p-2)) <= c && c <= uchar(*p)) -+ return sig; -+ } -+ else if (uchar(*p) == c) return sig; -+ } -+ return !sig; -+} -+ -+ -+static int singlematch (int c, const char *p, const char *ep) { -+ switch (*p) { -+ case '.': return 1; /* matches any char */ -+ case L_ESC: return match_class(c, uchar(*(p+1))); -+ case '[': return matchbracketclass(c, p, ep-1); -+ default: return (uchar(*p) == c); -+ } -+} -+ -+ -+static const char *match (MatchState *ms, const char *s, const char *p); -+ -+ -+static const char *matchbalance (MatchState *ms, const char *s, -+ const char *p) { -+ if (*p == 0 || *(p+1) == 0) -+ luaL_error(ms->L, "unbalanced pattern"); -+ if (*s != *p) return NULL; -+ else { -+ int b = *p; -+ int e = *(p+1); -+ int cont = 1; -+ while (++s < ms->src_end) { -+ if (*s == e) { -+ if (--cont == 0) return s+1; -+ } -+ else if (*s == b) cont++; -+ } -+ } -+ return NULL; /* string ends out of balance */ -+} -+ -+ -+static const char *max_expand (MatchState *ms, const char *s, -+ const char *p, const char *ep) { -+ ptrdiff_t i = 0; /* counts maximum expand for item */ -+ while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) -+ i++; -+ /* keeps trying to match with the maximum repetitions */ -+ while (i>=0) { -+ const char *res = match(ms, (s+i), ep+1); -+ if (res) return res; -+ i--; /* else didn't match; reduce 1 repetition to try again */ -+ } -+ return NULL; -+} -+ -+ -+static const char *min_expand (MatchState *ms, const char *s, -+ const char *p, const char *ep) { -+ for (;;) { -+ const char *res = match(ms, s, ep+1); -+ if (res != NULL) -+ return res; -+ else if (ssrc_end && singlematch(uchar(*s), p, ep)) -+ s++; /* try with one more repetition */ -+ else return NULL; -+ } -+} -+ -+ -+static const char *start_capture (MatchState *ms, const char *s, -+ const char *p, int what) { -+ const char *res; -+ int level = ms->level; -+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); -+ ms->capture[level].init = s; -+ ms->capture[level].len = what; -+ ms->level = level+1; -+ if ((res=match(ms, s, p)) == NULL) /* match failed? */ -+ ms->level--; /* undo capture */ -+ return res; -+} -+ -+ -+static const char *end_capture (MatchState *ms, const char *s, -+ const char *p) { -+ int l = capture_to_close(ms); -+ const char *res; -+ ms->capture[l].len = s - ms->capture[l].init; /* close capture */ -+ if ((res = match(ms, s, p)) == NULL) /* match failed? */ -+ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ -+ return res; -+} -+ -+ -+static const char *match_capture (MatchState *ms, const char *s, int l) { -+ size_t len; -+ l = check_capture(ms, l); -+ len = ms->capture[l].len; -+ if ((size_t)(ms->src_end-s) >= len && -+ memcmp(ms->capture[l].init, s, len) == 0) -+ return s+len; -+ else return NULL; -+} -+ -+ -+static const char *match (MatchState *ms, const char *s, const char *p) { -+ init: /* using goto's to optimize tail recursion */ -+ switch (*p) { -+ case '(': { /* start capture */ -+ if (*(p+1) == ')') /* position capture? */ -+ return start_capture(ms, s, p+2, CAP_POSITION); -+ else -+ return start_capture(ms, s, p+1, CAP_UNFINISHED); -+ } -+ case ')': { /* end capture */ -+ return end_capture(ms, s, p+1); -+ } -+ case L_ESC: { -+ switch (*(p+1)) { -+ case 'b': { /* balanced string? */ -+ s = matchbalance(ms, s, p+2); -+ if (s == NULL) return NULL; -+ p+=4; goto init; /* else return match(ms, s, p+4); */ -+ } -+ case 'f': { /* frontier? */ -+ const char *ep; char previous; -+ p += 2; -+ if (*p != '[') -+ luaL_error(ms->L, "missing " LUA_QL("[") " after " -+ LUA_QL("%%f") " in pattern"); -+ ep = classend(ms, p); /* points to what is next */ -+ previous = (s == ms->src_init) ? '\0' : *(s-1); -+ if (matchbracketclass(uchar(previous), p, ep-1) || -+ !matchbracketclass(uchar(*s), p, ep-1)) return NULL; -+ p=ep; goto init; /* else return match(ms, s, ep); */ -+ } -+ default: { -+ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ -+ s = match_capture(ms, s, uchar(*(p+1))); -+ if (s == NULL) return NULL; -+ p+=2; goto init; /* else return match(ms, s, p+2) */ -+ } -+ goto dflt; /* case default */ -+ } -+ } -+ } -+ case '\0': { /* end of pattern */ -+ return s; /* match succeeded */ -+ } -+ case '$': { -+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ -+ return (s == ms->src_end) ? s : NULL; /* check end of string */ -+ else goto dflt; -+ } -+ default: dflt: { /* it is a pattern item */ -+ const char *ep = classend(ms, p); /* points to what is next */ -+ int m = ssrc_end && singlematch(uchar(*s), p, ep); -+ switch (*ep) { -+ case '?': { /* optional */ -+ const char *res; -+ if (m && ((res=match(ms, s+1, ep+1)) != NULL)) -+ return res; -+ p=ep+1; goto init; /* else return match(ms, s, ep+1); */ -+ } -+ case '*': { /* 0 or more repetitions */ -+ return max_expand(ms, s, p, ep); -+ } -+ case '+': { /* 1 or more repetitions */ -+ return (m ? max_expand(ms, s+1, p, ep) : NULL); -+ } -+ case '-': { /* 0 or more repetitions (minimum) */ -+ return min_expand(ms, s, p, ep); -+ } -+ default: { -+ if (!m) return NULL; -+ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ -+ } -+ } -+ } -+ } -+} -+ -+ -+ -+static const char *lmemfind (const char *s1, size_t l1, -+ const char *s2, size_t l2) { -+ if (l2 == 0) return s1; /* empty strings are everywhere */ -+ else if (l2 > l1) return NULL; /* avoids a negative `l1' */ -+ else { -+ const char *init; /* to search for a `*s2' inside `s1' */ -+ l2--; /* 1st char will be checked by `memchr' */ -+ l1 = l1-l2; /* `s2' cannot be found after that */ -+ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { -+ init++; /* 1st char is already checked */ -+ if (memcmp(init, s2+1, l2) == 0) -+ return init-1; -+ else { /* correct `l1' and `s1' to try again */ -+ l1 -= init-s1; -+ s1 = init; -+ } -+ } -+ return NULL; /* not found */ -+ } -+} -+ -+ -+static void push_onecapture (MatchState *ms, int i, const char *s, -+ const char *e) { -+ if (i >= ms->level) { -+ if (i == 0) /* ms->level == 0, too */ -+ lua_pushlstring(ms->L, s, e - s); /* add whole match */ -+ else -+ luaL_error(ms->L, "invalid capture index"); -+ } -+ else { -+ ptrdiff_t l = ms->capture[i].len; -+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); -+ if (l == CAP_POSITION) -+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); -+ else -+ lua_pushlstring(ms->L, ms->capture[i].init, l); -+ } -+} -+ -+ -+static int push_captures (MatchState *ms, const char *s, const char *e) { -+ int i; -+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level; -+ luaL_checkstack(ms->L, nlevels, "too many captures"); -+ for (i = 0; i < nlevels; i++) -+ push_onecapture(ms, i, s, e); -+ return nlevels; /* number of strings pushed */ -+} -+ -+ -+static int str_find_aux (lua_State *L, int find) { -+ size_t l1, l2; -+ const char *s = luaL_checklstring(L, 1, &l1); -+ const char *p = luaL_checklstring(L, 2, &l2); -+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; -+ if (init < 0) init = 0; -+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; -+ if (find && (lua_toboolean(L, 4) || /* explicit request? */ -+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ -+ /* do a plain search */ -+ const char *s2 = lmemfind(s+init, l1-init, p, l2); -+ if (s2) { -+ lua_pushinteger(L, s2-s+1); -+ lua_pushinteger(L, s2-s+l2); -+ return 2; -+ } -+ } -+ else { -+ MatchState ms; -+ int anchor = (*p == '^') ? (p++, 1) : 0; -+ const char *s1=s+init; -+ ms.L = L; -+ ms.src_init = s; -+ ms.src_end = s+l1; -+ do { -+ const char *res; -+ ms.level = 0; -+ if ((res=match(&ms, s1, p)) != NULL) { -+ if (find) { -+ lua_pushinteger(L, s1-s+1); /* start */ -+ lua_pushinteger(L, res-s); /* end */ -+ return push_captures(&ms, NULL, 0) + 2; -+ } -+ else -+ return push_captures(&ms, s1, res); -+ } -+ } while (s1++ < ms.src_end && !anchor); -+ } -+ lua_pushnil(L); /* not found */ -+ return 1; -+} -+ -+ -+static int str_find (lua_State *L) { -+ return str_find_aux(L, 1); -+} -+ -+ -+static int str_match (lua_State *L) { -+ return str_find_aux(L, 0); -+} -+ -+ -+static int gmatch_aux (lua_State *L) { -+ MatchState ms; -+ size_t ls; -+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); -+ const char *p = lua_tostring(L, lua_upvalueindex(2)); -+ const char *src; -+ ms.L = L; -+ ms.src_init = s; -+ ms.src_end = s+ls; -+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); -+ src <= ms.src_end; -+ src++) { -+ const char *e; -+ ms.level = 0; -+ if ((e = match(&ms, src, p)) != NULL) { -+ lua_Integer newstart = e-s; -+ if (e == src) newstart++; /* empty match? go at least one position */ -+ lua_pushinteger(L, newstart); -+ lua_replace(L, lua_upvalueindex(3)); -+ return push_captures(&ms, src, e); -+ } -+ } -+ return 0; /* not found */ -+} -+ -+ -+static int gmatch (lua_State *L) { -+ luaL_checkstring(L, 1); -+ luaL_checkstring(L, 2); -+ lua_settop(L, 2); -+ lua_pushinteger(L, 0); -+ lua_pushcclosure(L, gmatch_aux, 3); -+ return 1; -+} -+ -+ -+static int gfind_nodef (lua_State *L) { -+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to " -+ LUA_QL("string.gmatch")); -+} -+ -+ -+static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, -+ const char *e) { -+ size_t l, i; -+ const char *news = lua_tolstring(ms->L, 3, &l); -+ for (i = 0; i < l; i++) { -+ if (news[i] != L_ESC) -+ luaL_addchar(b, news[i]); -+ else { -+ i++; /* skip ESC */ -+ if (!isdigit(uchar(news[i]))) -+ luaL_addchar(b, news[i]); -+ else if (news[i] == '0') -+ luaL_addlstring(b, s, e - s); -+ else { -+ push_onecapture(ms, news[i] - '1', s, e); -+ luaL_addvalue(b); /* add capture to accumulated result */ -+ } -+ } -+ } -+} -+ -+ -+static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, -+ const char *e) { -+ lua_State *L = ms->L; -+ switch (lua_type(L, 3)) { -+ case LUA_TNUMBER: -+ case LUA_TSTRING: { -+ add_s(ms, b, s, e); -+ return; -+ } -+ case LUA_TFUNCTION: { -+ int n; -+ lua_pushvalue(L, 3); -+ n = push_captures(ms, s, e); -+ lua_call(L, n, 1); -+ break; -+ } -+ case LUA_TTABLE: { -+ push_onecapture(ms, 0, s, e); -+ lua_gettable(L, 3); -+ break; -+ } -+ } -+ if (!lua_toboolean(L, -1)) { /* nil or false? */ -+ lua_pop(L, 1); -+ lua_pushlstring(L, s, e - s); /* keep original text */ -+ } -+ else if (!lua_isstring(L, -1)) -+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); -+ luaL_addvalue(b); /* add result to accumulator */ -+} -+ -+ -+static int str_gsub (lua_State *L) { -+ size_t srcl; -+ const char *src = luaL_checklstring(L, 1, &srcl); -+ const char *p = luaL_checkstring(L, 2); -+ int tr = lua_type(L, 3); -+ int max_s = luaL_optint(L, 4, srcl+1); -+ int anchor = (*p == '^') ? (p++, 1) : 0; -+ int n = 0; -+ MatchState ms; -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_gsub: cannot allocate memory"); -+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || -+ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, -+ "string/function/table expected"); -+ luaL_buffinit(L, b); -+ ms.L = L; -+ ms.src_init = src; -+ ms.src_end = src+srcl; -+ while (n < max_s) { -+ const char *e; -+ ms.level = 0; -+ e = match(&ms, src, p); -+ if (e) { -+ n++; -+ add_value(&ms, b, src, e); -+ } -+ if (e && e>src) /* non empty match? */ -+ src = e; /* skip it */ -+ else if (src < ms.src_end) -+ luaL_addchar(b, *src++); -+ else break; -+ if (anchor) break; -+ } -+ luaL_addlstring(b, src, ms.src_end-src); -+ luaL_pushresult(b); -+ lua_pushinteger(L, n); /* number of substitutions */ -+ kfree(b); -+ return 2; -+} -+ -+/* }====================================================== */ -+ -+ -+/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -+#define MAX_ITEM 512 -+/* valid flags in a format specification */ -+#define FLAGS "-+ #0" -+/* -+** maximum size of each format specification (such as '%-099.99d') -+** (+10 accounts for %99.99x plus margin of error) -+*/ -+#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) -+ -+ -+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { -+ size_t l; -+ const char *s = luaL_checklstring(L, arg, &l); -+ luaL_addchar(b, '"'); -+ while (l--) { -+ switch (*s) { -+ case '"': case '\\': case '\n': { -+ luaL_addchar(b, '\\'); -+ luaL_addchar(b, *s); -+ break; -+ } -+ case '\r': { -+ luaL_addlstring(b, "\\r", 2); -+ break; -+ } -+ case '\0': { -+ luaL_addlstring(b, "\\000", 4); -+ break; -+ } -+ default: { -+ luaL_addchar(b, *s); -+ break; -+ } -+ } -+ s++; -+ } -+ luaL_addchar(b, '"'); -+} -+ -+static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { -+ const char *p = strfrmt; -+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ -+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) -+ luaL_error(L, "invalid format (repeated flags)"); -+ if (isdigit(uchar(*p))) p++; /* skip width */ -+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ -+ if (*p == '.') { -+ p++; -+ if (isdigit(uchar(*p))) p++; /* skip precision */ -+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ -+ } -+ if (isdigit(uchar(*p))) -+ luaL_error(L, "invalid format (width or precision too long)"); -+ *(form++) = '%'; -+ strncpy(form, strfrmt, p - strfrmt + 1); -+ form += p - strfrmt + 1; -+ *form = '\0'; -+ return p; -+} -+ -+ -+static void addintlen (char *form) { -+ size_t l = strlen(form); -+ char spec = form[l - 1]; -+ strcpy(form + l - 1, LUA_INTFRMLEN); -+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; -+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; -+} -+ -+ -+static int str_format (lua_State *L) { -+ int arg = 1; -+ size_t sfl; -+ const char *strfrmt = luaL_checklstring(L, arg, &sfl); -+ const char *strfrmt_end = strfrmt+sfl; -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_format: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ while (strfrmt < strfrmt_end) { -+ if (*strfrmt != L_ESC) -+ luaL_addchar(b, *strfrmt++); -+ else if (*++strfrmt == L_ESC) -+ luaL_addchar(b, *strfrmt++); /* %% */ -+ else { /* format item */ -+ char form[MAX_FORMAT]; /* to store the format (`%...') */ -+ char buff[MAX_ITEM]; /* to store the formatted item */ -+ arg++; -+ strfrmt = scanformat(L, strfrmt, form); -+ switch (*strfrmt++) { -+ case 'c': { -+ sprintf(buff, form, (int)luaL_checknumber(L, arg)); -+ break; -+ } -+ case 'd': case 'i': { -+ addintlen(form); -+ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); -+ break; -+ } -+ case 'o': case 'u': case 'x': case 'X': { -+ addintlen(form); -+ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); -+ break; -+ } -+ case 'q': { -+ addquoted(L, b, arg); -+ continue; /* skip the 'addsize' at the end */ -+ } -+ case 's': { -+ size_t l; -+ const char *s = luaL_checklstring(L, arg, &l); -+ if (!strchr(form, '.') && l >= 100) { -+ /* no precision and string is too long to be formatted; -+ keep original string */ -+ lua_pushvalue(L, arg); -+ luaL_addvalue(b); -+ continue; /* skip the `addsize' at the end */ -+ } -+ else { -+ sprintf(buff, form, s); -+ break; -+ } -+ } -+ default: { /* also treat cases `pnLlh' */ -+ kfree(b); -+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " -+ LUA_QL("format"), *(strfrmt - 1)); -+ } -+ } -+ luaL_addlstring(b, buff, strlen(buff)); -+ } -+ } -+ luaL_pushresult(b); -+ kfree(b); -+ return 1; -+} -+ -+ -+static const luaL_Reg strlib[] = { -+ {"byte", str_byte}, -+ {"char", str_char}, -+ {"dump", str_dump}, -+ {"find", str_find}, -+ {"format", str_format}, -+ {"gfind", gfind_nodef}, -+ {"gmatch", gmatch}, -+ {"gsub", str_gsub}, -+ {"len", str_len}, -+ {"lower", str_lower}, -+ {"match", str_match}, -+ {"rep", str_rep}, -+ {"reverse", str_reverse}, -+ {"sub", str_sub}, -+ {"upper", str_upper}, -+ {NULL, NULL} -+}; -+ -+ -+static void createmetatable (lua_State *L) { -+ lua_createtable(L, 0, 1); /* create metatable for strings */ -+ lua_pushliteral(L, ""); /* dummy string */ -+ lua_pushvalue(L, -2); -+ lua_setmetatable(L, -2); /* set string metatable */ -+ lua_pop(L, 1); /* pop dummy string */ -+ lua_pushvalue(L, -2); /* string library... */ -+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ -+ lua_pop(L, 1); /* pop metatable */ -+} -+ -+ -+/* -+** Open string library -+*/ -+LUALIB_API int luaopen_string (lua_State *L) { -+ luaL_register(L, LUA_STRLIBNAME, strlib); -+#if defined(LUA_COMPAT_GFIND) -+ lua_getfield(L, -1, "gmatch"); -+ lua_setfield(L, -2, "gfind"); -+#endif -+ createmetatable(L); -+ return 1; -+} ---- /dev/null -+++ b/extensions/LUA/lua/ltable.c -@@ -0,0 +1,588 @@ -+/* -+** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ -+** Lua tables (hash) -+** See Copyright Notice in lua.h -+*/ -+ -+ -+/* -+** Implementation of tables (aka arrays, objects, or hash tables). -+** Tables keep its elements in two parts: an array part and a hash part. -+** Non-negative integer keys are all candidates to be kept in the array -+** part. The actual size of the array is the largest `n' such that at -+** least half the slots between 0 and n are in use. -+** Hash uses a mix of chained scatter table with Brent's variation. -+** A main invariant of these tables is that, if an element is not -+** in its main position (i.e. the `original' position that its hash gives -+** to it), then the colliding element is in its own main position. -+** Hence even when the load factor reaches 100%, performance remains good. -+*/ -+ -+#include -+#include -+ -+#define ltable_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "ltable.h" -+ -+ -+/* -+** max size of array part is 2^MAXBITS -+*/ -+#if LUAI_BITSINT > 26 -+#define MAXBITS 26 -+#else -+#define MAXBITS (LUAI_BITSINT-2) -+#endif -+ -+#define MAXASIZE (1 << MAXBITS) -+ -+ -+#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) -+ -+#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -+#define hashboolean(t,p) hashpow2(t, p) -+ -+ -+/* -+** for some types, it is better to avoid modulus by power of 2, as -+** they tend to have many 2 factors. -+*/ -+#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) -+ -+ -+#define hashpointer(t,p) hashmod(t, IntPoint(p)) -+ -+ -+/* -+** number of ints inside a lua_Number -+*/ -+#define numints cast_int(sizeof(lua_Number)/sizeof(int)) -+ -+ -+ -+#define dummynode (&dummynode_) -+ -+static const Node dummynode_ = { -+ {{NULL}, LUA_TNIL}, /* value */ -+ {{{NULL}, LUA_TNIL, NULL}} /* key */ -+}; -+ -+ -+/* -+** hash for lua_Numbers -+*/ -+static Node *hashnum (const Table *t, lua_Number n) { -+ unsigned int a[numints]; -+ int i; -+ if (luai_numeq(n, 0)) /* avoid problems with -0 */ -+ return gnode(t, 0); -+ memcpy(a, &n, sizeof(a)); -+ for (i = 1; i < numints; i++) a[0] += a[i]; -+ return hashmod(t, a[0]); -+} -+ -+ -+ -+/* -+** returns the `main' position of an element in a table (that is, the index -+** of its hash value) -+*/ -+static Node *mainposition (const Table *t, const TValue *key) { -+ switch (ttype(key)) { -+ case LUA_TNUMBER: -+ return hashnum(t, nvalue(key)); -+ case LUA_TSTRING: -+ return hashstr(t, rawtsvalue(key)); -+ case LUA_TBOOLEAN: -+ return hashboolean(t, bvalue(key)); -+ case LUA_TLIGHTUSERDATA: -+ return hashpointer(t, pvalue(key)); -+ default: -+ return hashpointer(t, gcvalue(key)); -+ } -+} -+ -+ -+/* -+** returns the index for `key' if `key' is an appropriate key to live in -+** the array part of the table, -1 otherwise. -+*/ -+static int arrayindex (const TValue *key) { -+ if (ttisnumber(key)) { -+ lua_Number n = nvalue(key); -+ int k; -+ lua_number2int(k, n); -+ if (luai_numeq(cast_num(k), n)) -+ return k; -+ } -+ return -1; /* `key' did not match some condition */ -+} -+ -+ -+/* -+** returns the index of a `key' for table traversals. First goes all -+** elements in the array part, then elements in the hash part. The -+** beginning of a traversal is signalled by -1. -+*/ -+static int findindex (lua_State *L, Table *t, StkId key) { -+ int i; -+ if (ttisnil(key)) return -1; /* first iteration */ -+ i = arrayindex(key); -+ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ -+ return i-1; /* yes; that's the index (corrected to C) */ -+ else { -+ Node *n = mainposition(t, key); -+ do { /* check whether `key' is somewhere in the chain */ -+ /* key may be dead already, but it is ok to use it in `next' */ -+ if (luaO_rawequalObj(key2tval(n), key) || -+ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && -+ gcvalue(gkey(n)) == gcvalue(key))) { -+ i = cast_int(n - gnode(t, 0)); /* key index in hash table */ -+ /* hash elements are numbered after array ones */ -+ return i + t->sizearray; -+ } -+ else n = gnext(n); -+ } while (n); -+ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ -+ return 0; /* to avoid warnings */ -+ } -+} -+ -+ -+int luaH_next (lua_State *L, Table *t, StkId key) { -+ int i = findindex(L, t, key); /* find original element */ -+ for (i++; i < t->sizearray; i++) { /* try first array part */ -+ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ -+ setnvalue(key, cast_num(i+1)); -+ setobj2s(L, key+1, &t->array[i]); -+ return 1; -+ } -+ } -+ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ -+ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ -+ setobj2s(L, key, key2tval(gnode(t, i))); -+ setobj2s(L, key+1, gval(gnode(t, i))); -+ return 1; -+ } -+ } -+ return 0; /* no more elements */ -+} -+ -+ -+/* -+** {============================================================= -+** Rehash -+** ============================================================== -+*/ -+ -+ -+static int computesizes (int nums[], int *narray) { -+ int i; -+ int twotoi; /* 2^i */ -+ int a = 0; /* number of elements smaller than 2^i */ -+ int na = 0; /* number of elements to go to array part */ -+ int n = 0; /* optimal size for array part */ -+ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { -+ if (nums[i] > 0) { -+ a += nums[i]; -+ if (a > twotoi/2) { /* more than half elements present? */ -+ n = twotoi; /* optimal size (till now) */ -+ na = a; /* all elements smaller than n will go to array part */ -+ } -+ } -+ if (a == *narray) break; /* all elements already counted */ -+ } -+ *narray = n; -+ lua_assert(*narray/2 <= na && na <= *narray); -+ return na; -+} -+ -+ -+static int countint (const TValue *key, int *nums) { -+ int k = arrayindex(key); -+ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ -+ nums[ceillog2(k)]++; /* count as such */ -+ return 1; -+ } -+ else -+ return 0; -+} -+ -+ -+static int numusearray (const Table *t, int *nums) { -+ int lg; -+ int ttlg; /* 2^lg */ -+ int ause = 0; /* summation of `nums' */ -+ int i = 1; /* count to traverse all array keys */ -+ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ -+ int lc = 0; /* counter */ -+ int lim = ttlg; -+ if (lim > t->sizearray) { -+ lim = t->sizearray; /* adjust upper limit */ -+ if (i > lim) -+ break; /* no more elements to count */ -+ } -+ /* count elements in range (2^(lg-1), 2^lg] */ -+ for (; i <= lim; i++) { -+ if (!ttisnil(&t->array[i-1])) -+ lc++; -+ } -+ nums[lg] += lc; -+ ause += lc; -+ } -+ return ause; -+} -+ -+ -+static int numusehash (const Table *t, int *nums, int *pnasize) { -+ int totaluse = 0; /* total number of elements */ -+ int ause = 0; /* summation of `nums' */ -+ int i = sizenode(t); -+ while (i--) { -+ Node *n = &t->node[i]; -+ if (!ttisnil(gval(n))) { -+ ause += countint(key2tval(n), nums); -+ totaluse++; -+ } -+ } -+ *pnasize += ause; -+ return totaluse; -+} -+ -+ -+static void setarrayvector (lua_State *L, Table *t, int size) { -+ int i; -+ luaM_reallocvector(L, t->array, t->sizearray, size, TValue); -+ for (i=t->sizearray; iarray[i]); -+ t->sizearray = size; -+} -+ -+ -+static void setnodevector (lua_State *L, Table *t, int size) { -+ int lsize; -+ if (size == 0) { /* no elements to hash part? */ -+ t->node = cast(Node *, dummynode); /* use common `dummynode' */ -+ lsize = 0; -+ } -+ else { -+ int i; -+ lsize = ceillog2(size); -+ if (lsize > MAXBITS) -+ luaG_runerror(L, "table overflow"); -+ size = twoto(lsize); -+ t->node = luaM_newvector(L, size, Node); -+ for (i=0; ilsizenode = cast_byte(lsize); -+ t->lastfree = gnode(t, size); /* all positions are free */ -+} -+ -+ -+static void resize (lua_State *L, Table *t, int nasize, int nhsize) { -+ int i; -+ int oldasize = t->sizearray; -+ int oldhsize = t->lsizenode; -+ Node *nold = t->node; /* save old hash ... */ -+ if (nasize > oldasize) /* array part must grow? */ -+ setarrayvector(L, t, nasize); -+ /* create new hash part with appropriate size */ -+ setnodevector(L, t, nhsize); -+ if (nasize < oldasize) { /* array part must shrink? */ -+ t->sizearray = nasize; -+ /* re-insert elements from vanishing slice */ -+ for (i=nasize; iarray[i])) -+ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); -+ } -+ /* shrink array */ -+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); -+ } -+ /* re-insert elements from hash part */ -+ for (i = twoto(oldhsize) - 1; i >= 0; i--) { -+ Node *old = nold+i; -+ if (!ttisnil(gval(old))) -+ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); -+ } -+ if (nold != dummynode) -+ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ -+} -+ -+ -+void luaH_resizearray (lua_State *L, Table *t, int nasize) { -+ int nsize = (t->node == dummynode) ? 0 : sizenode(t); -+ resize(L, t, nasize, nsize); -+} -+ -+ -+static void rehash (lua_State *L, Table *t, const TValue *ek) { -+ int nasize, na; -+ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ -+ int i; -+ int totaluse; -+ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ -+ nasize = numusearray(t, nums); /* count keys in array part */ -+ totaluse = nasize; /* all those keys are integer keys */ -+ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ -+ /* count extra key */ -+ nasize += countint(ek, nums); -+ totaluse++; -+ /* compute new size for array part */ -+ na = computesizes(nums, &nasize); -+ /* resize the table to new computed sizes */ -+ resize(L, t, nasize, totaluse - na); -+} -+ -+ -+ -+/* -+** }============================================================= -+*/ -+ -+ -+Table *luaH_new (lua_State *L, int narray, int nhash) { -+ Table *t = luaM_new(L, Table); -+ luaC_link(L, obj2gco(t), LUA_TTABLE); -+ t->metatable = NULL; -+ t->flags = cast_byte(~0); -+ /* temporary values (kept only if some malloc fails) */ -+ t->array = NULL; -+ t->sizearray = 0; -+ t->lsizenode = 0; -+ t->node = cast(Node *, dummynode); -+ setarrayvector(L, t, narray); -+ setnodevector(L, t, nhash); -+ return t; -+} -+ -+ -+void luaH_free (lua_State *L, Table *t) { -+ if (t->node != dummynode) -+ luaM_freearray(L, t->node, sizenode(t), Node); -+ luaM_freearray(L, t->array, t->sizearray, TValue); -+ luaM_free(L, t); -+} -+ -+ -+static Node *getfreepos (Table *t) { -+ while (t->lastfree-- > t->node) { -+ if (ttisnil(gkey(t->lastfree))) -+ return t->lastfree; -+ } -+ return NULL; /* could not find a free place */ -+} -+ -+ -+ -+/* -+** inserts a new key into a hash table; first, check whether key's main -+** position is free. If not, check whether colliding node is in its main -+** position or not: if it is not, move colliding node to an empty place and -+** put new key in its main position; otherwise (colliding node is in its main -+** position), new key goes to an empty position. -+*/ -+static TValue *newkey (lua_State *L, Table *t, const TValue *key) { -+ Node *mp = mainposition(t, key); -+ if (!ttisnil(gval(mp)) || mp == dummynode) { -+ Node *othern; -+ Node *n = getfreepos(t); /* get a free place */ -+ if (n == NULL) { /* cannot find a free place? */ -+ rehash(L, t, key); /* grow table */ -+ return luaH_set(L, t, key); /* re-insert key into grown table */ -+ } -+ lua_assert(n != dummynode); -+ othern = mainposition(t, key2tval(mp)); -+ if (othern != mp) { /* is colliding node out of its main position? */ -+ /* yes; move colliding node into free position */ -+ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ -+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ -+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ -+ gnext(mp) = NULL; /* now `mp' is free */ -+ setnilvalue(gval(mp)); -+ } -+ else { /* colliding node is in its own main position */ -+ /* new node will go into free position */ -+ gnext(n) = gnext(mp); /* chain new position */ -+ gnext(mp) = n; -+ mp = n; -+ } -+ } -+ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; -+ luaC_barriert(L, t, key); -+ lua_assert(ttisnil(gval(mp))); -+ return gval(mp); -+} -+ -+ -+/* -+** search function for integers -+*/ -+const TValue *luaH_getnum (Table *t, int key) { -+ /* (1 <= key && key <= t->sizearray) */ -+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) -+ return &t->array[key-1]; -+ else { -+ lua_Number nk = cast_num(key); -+ Node *n = hashnum(t, nk); -+ do { /* check whether `key' is somewhere in the chain */ -+ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) -+ return gval(n); /* that's it */ -+ else n = gnext(n); -+ } while (n); -+ return luaO_nilobject; -+ } -+} -+ -+ -+/* -+** search function for strings -+*/ -+const TValue *luaH_getstr (Table *t, TString *key) { -+ Node *n = hashstr(t, key); -+ do { /* check whether `key' is somewhere in the chain */ -+ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) -+ return gval(n); /* that's it */ -+ else n = gnext(n); -+ } while (n); -+ return luaO_nilobject; -+} -+ -+ -+/* -+** main search function -+*/ -+const TValue *luaH_get (Table *t, const TValue *key) { -+ switch (ttype(key)) { -+ case LUA_TNIL: return luaO_nilobject; -+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); -+ case LUA_TNUMBER: { -+ int k; -+ lua_Number n = nvalue(key); -+ lua_number2int(k, n); -+ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ -+ return luaH_getnum(t, k); /* use specialized version */ -+ /* else go through */ -+ } -+ default: { -+ Node *n = mainposition(t, key); -+ do { /* check whether `key' is somewhere in the chain */ -+ if (luaO_rawequalObj(key2tval(n), key)) -+ return gval(n); /* that's it */ -+ else n = gnext(n); -+ } while (n); -+ return luaO_nilobject; -+ } -+ } -+} -+ -+ -+TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { -+ const TValue *p = luaH_get(t, key); -+ t->flags = 0; -+ if (p != luaO_nilobject) -+ return cast(TValue *, p); -+ else { -+ if (ttisnil(key)) luaG_runerror(L, "table index is nil"); -+ else if (ttisnumber(key) && luai_numisnan(nvalue(key))) -+ luaG_runerror(L, "table index is NaN"); -+ return newkey(L, t, key); -+ } -+} -+ -+ -+TValue *luaH_setnum (lua_State *L, Table *t, int key) { -+ const TValue *p = luaH_getnum(t, key); -+ if (p != luaO_nilobject) -+ return cast(TValue *, p); -+ else { -+ TValue k; -+ setnvalue(&k, cast_num(key)); -+ return newkey(L, t, &k); -+ } -+} -+ -+ -+TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { -+ const TValue *p = luaH_getstr(t, key); -+ if (p != luaO_nilobject) -+ return cast(TValue *, p); -+ else { -+ TValue k; -+ setsvalue(L, &k, key); -+ return newkey(L, t, &k); -+ } -+} -+ -+ -+static int unbound_search (Table *t, unsigned int j) { -+ unsigned int i = j; /* i is zero or a present index */ -+ j++; -+ /* find `i' and `j' such that i is present and j is not */ -+ while (!ttisnil(luaH_getnum(t, j))) { -+ i = j; -+ j *= 2; -+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ -+ /* table was built with bad purposes: resort to linear search */ -+ i = 1; -+ while (!ttisnil(luaH_getnum(t, i))) i++; -+ return i - 1; -+ } -+ } -+ /* now do a binary search between them */ -+ while (j - i > 1) { -+ unsigned int m = (i+j)/2; -+ if (ttisnil(luaH_getnum(t, m))) j = m; -+ else i = m; -+ } -+ return i; -+} -+ -+ -+/* -+** Try to find a boundary in table `t'. A `boundary' is an integer index -+** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -+*/ -+int luaH_getn (Table *t) { -+ unsigned int j = t->sizearray; -+ if (j > 0 && ttisnil(&t->array[j - 1])) { -+ /* there is a boundary in the array part: (binary) search for it */ -+ unsigned int i = 0; -+ while (j - i > 1) { -+ unsigned int m = (i+j)/2; -+ if (ttisnil(&t->array[m - 1])) j = m; -+ else i = m; -+ } -+ return i; -+ } -+ /* else must find a boundary in hash part */ -+ else if (t->node == dummynode) /* hash part is empty? */ -+ return j; /* that is easy... */ -+ else return unbound_search(t, j); -+} -+ -+ -+ -+#if defined(LUA_DEBUG) -+ -+Node *luaH_mainposition (const Table *t, const TValue *key) { -+ return mainposition(t, key); -+} -+ -+int luaH_isdummy (Node *n) { return n == dummynode; } -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ltable.h -@@ -0,0 +1,40 @@ -+/* -+** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua tables (hash) -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ltable_h -+#define ltable_h -+ -+#include "lobject.h" -+ -+ -+#define gnode(t,i) (&(t)->node[i]) -+#define gkey(n) (&(n)->i_key.nk) -+#define gval(n) (&(n)->i_val) -+#define gnext(n) ((n)->i_key.nk.next) -+ -+#define key2tval(n) (&(n)->i_key.tvk) -+ -+ -+LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); -+LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); -+LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -+LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); -+LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -+LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -+LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); -+LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); -+LUAI_FUNC void luaH_free (lua_State *L, Table *t); -+LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -+LUAI_FUNC int luaH_getn (Table *t); -+ -+ -+#if defined(LUA_DEBUG) -+LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -+LUAI_FUNC int luaH_isdummy (Node *n); -+#endif -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ltablib.c -@@ -0,0 +1,288 @@ -+/* -+** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ -+** Library for Table Manipulation -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define ltablib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+#include "lualib.h" -+ -+ -+#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) -+ -+ -+static int foreachi (lua_State *L) { -+ int i; -+ int n = aux_getn(L, 1); -+ luaL_checktype(L, 2, LUA_TFUNCTION); -+ for (i=1; i <= n; i++) { -+ lua_pushvalue(L, 2); /* function */ -+ lua_pushinteger(L, i); /* 1st argument */ -+ lua_rawgeti(L, 1, i); /* 2nd argument */ -+ lua_call(L, 2, 1); -+ if (!lua_isnil(L, -1)) -+ return 1; -+ lua_pop(L, 1); /* remove nil result */ -+ } -+ return 0; -+} -+ -+ -+static int foreach (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_checktype(L, 2, LUA_TFUNCTION); -+ lua_pushnil(L); /* first key */ -+ while (lua_next(L, 1)) { -+ lua_pushvalue(L, 2); /* function */ -+ lua_pushvalue(L, -3); /* key */ -+ lua_pushvalue(L, -3); /* value */ -+ lua_call(L, 2, 1); -+ if (!lua_isnil(L, -1)) -+ return 1; -+ lua_pop(L, 2); /* remove value and result */ -+ } -+ return 0; -+} -+ -+ -+static int maxn (lua_State *L) { -+ lua_Number max = 0; -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_pushnil(L); /* first key */ -+ while (lua_next(L, 1)) { -+ lua_pop(L, 1); /* remove value */ -+ if (lua_type(L, -1) == LUA_TNUMBER) { -+ lua_Number v = lua_tonumber(L, -1); -+ if (v > max) max = v; -+ } -+ } -+ lua_pushnumber(L, max); -+ return 1; -+} -+ -+ -+static int getn (lua_State *L) { -+ lua_pushinteger(L, aux_getn(L, 1)); -+ return 1; -+} -+ -+ -+static int setn (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+#ifndef luaL_setn -+ luaL_setn(L, 1, luaL_checkint(L, 2)); -+#else -+ luaL_error(L, LUA_QL("setn") " is obsolete"); -+#endif -+ lua_pushvalue(L, 1); -+ return 1; -+} -+ -+ -+static int tinsert (lua_State *L) { -+ int e = aux_getn(L, 1) + 1; /* first empty element */ -+ int pos; /* where to insert new element */ -+ switch (lua_gettop(L)) { -+ case 2: { /* called with only 2 arguments */ -+ pos = e; /* insert new element at the end */ -+ break; -+ } -+ case 3: { -+ int i; -+ pos = luaL_checkint(L, 2); /* 2nd argument is the position */ -+ if (pos > e) e = pos; /* `grow' array if necessary */ -+ for (i = e; i > pos; i--) { /* move up elements */ -+ lua_rawgeti(L, 1, i-1); -+ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ -+ } -+ break; -+ } -+ default: { -+ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); -+ } -+ } -+ luaL_setn(L, 1, e); /* new size */ -+ lua_rawseti(L, 1, pos); /* t[pos] = v */ -+ return 0; -+} -+ -+ -+static int tremove (lua_State *L) { -+ int e = aux_getn(L, 1); -+ int pos = luaL_optint(L, 2, e); -+ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ -+ return 0; /* nothing to remove */ -+ luaL_setn(L, 1, e - 1); /* t.n = n-1 */ -+ lua_rawgeti(L, 1, pos); /* result = t[pos] */ -+ for ( ;pos= P */ -+ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { -+ if (i>u) luaL_error(L, "invalid order function for sorting"); -+ lua_pop(L, 1); /* remove a[i] */ -+ } -+ /* repeat --j until a[j] <= P */ -+ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { -+ if (j -+ -+#define ltm_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+ -+ -+ -+const char *const luaT_typenames[] = { -+ "nil", "boolean", "userdata", "number", -+ "string", "table", "function", "userdata", "thread", -+ "proto", "upval" -+}; -+ -+ -+void luaT_init (lua_State *L) { -+ static const char *const luaT_eventname[] = { /* ORDER TM */ -+ "__index", "__newindex", -+ "__gc", "__mode", "__eq", -+ "__add", "__sub", "__mul", "__div", "__mod", -+ "__pow", "__unm", "__len", "__lt", "__le", -+ "__concat", "__call" -+ }; -+ int i; -+ for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); -+ luaS_fix(G(L)->tmname[i]); /* never collect these names */ -+ } -+} -+ -+ -+/* -+** function to be used with macro "fasttm": optimized for absence of -+** tag methods -+*/ -+const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { -+ const TValue *tm = luaH_getstr(events, ename); -+ lua_assert(event <= TM_EQ); -+ if (ttisnil(tm)) { /* no tag method? */ -+ events->flags |= cast_byte(1u<metatable; -+ break; -+ case LUA_TUSERDATA: -+ mt = uvalue(o)->metatable; -+ break; -+ default: -+ mt = G(L)->mt[ttype(o)]; -+ } -+ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/ltm.h -@@ -0,0 +1,54 @@ -+/* -+** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Tag methods -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ltm_h -+#define ltm_h -+ -+ -+#include "lobject.h" -+ -+ -+/* -+* WARNING: if you change the order of this enumeration, -+* grep "ORDER TM" -+*/ -+typedef enum { -+ TM_INDEX, -+ TM_NEWINDEX, -+ TM_GC, -+ TM_MODE, -+ TM_EQ, /* last tag method with `fast' access */ -+ TM_ADD, -+ TM_SUB, -+ TM_MUL, -+ TM_DIV, -+ TM_MOD, -+ TM_POW, -+ TM_UNM, -+ TM_LEN, -+ TM_LT, -+ TM_LE, -+ TM_CONCAT, -+ TM_CALL, -+ TM_N /* number of elements in the enum */ -+} TMS; -+ -+ -+ -+#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ -+ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) -+ -+#define fasttm(l,et,e) gfasttm(G(l), et, e) -+ -+LUAI_DATA const char *const luaT_typenames[]; -+ -+ -+LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -+LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, -+ TMS event); -+LUAI_FUNC void luaT_init (lua_State *L); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/luaconf.h -@@ -0,0 +1,797 @@ -+/* -+** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ -+** Configuration file for Lua -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lconfig_h -+#define lconfig_h -+ -+#include -+ -+#if !defined(__KERNEL__) -+#include -+#else -+#define UCHAR_MAX 255 -+#define SHRT_MAX 32767 -+#define BUFSIZ 8192 -+#define NO_FPU -+#endif -+ -+/* -+** ================================================================== -+** Search for "@@" to find all configurable definitions. -+** =================================================================== -+*/ -+ -+ -+/* -+@@ LUA_ANSI controls the use of non-ansi features. -+** CHANGE it (define it) if you want Lua to avoid the use of any -+** non-ansi feature or library. -+*/ -+#if defined(__STRICT_ANSI__) -+#define LUA_ANSI -+#endif -+ -+ -+#if !defined(LUA_ANSI) && defined(_WIN32) -+#define LUA_WIN -+#endif -+ -+#if defined(LUA_USE_LINUX) -+#define LUA_USE_POSIX -+#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -+#define LUA_USE_READLINE /* needs some extra libraries */ -+#endif -+ -+#if defined(LUA_USE_MACOSX) -+#define LUA_USE_POSIX -+#define LUA_DL_DYLD /* does not need extra library */ -+#endif -+ -+ -+ -+/* -+@@ LUA_USE_POSIX includes all functionallity listed as X/Open System -+@* Interfaces Extension (XSI). -+** CHANGE it (define it) if your system is XSI compatible. -+*/ -+#if defined(LUA_USE_POSIX) -+#define LUA_USE_MKSTEMP -+#define LUA_USE_ISATTY -+#define LUA_USE_POPEN -+#define LUA_USE_ULONGJMP -+#endif -+ -+ -+/* -+@@ LUA_PATH and LUA_CPATH are the names of the environment variables that -+@* Lua check to set its paths. -+@@ LUA_INIT is the name of the environment variable that Lua -+@* checks for initialization code. -+** CHANGE them if you want different names. -+*/ -+#define LUA_PATH "LUA_PATH" -+#define LUA_CPATH "LUA_CPATH" -+#define LUA_INIT "LUA_INIT" -+ -+ -+/* -+@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -+@* Lua libraries. -+@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -+@* C libraries. -+** CHANGE them if your machine has a non-conventional directory -+** hierarchy or if you want to install your libraries in -+** non-conventional directories. -+*/ -+#if defined(_WIN32) -+/* -+** In Windows, any exclamation mark ('!') in the path is replaced by the -+** path of the directory of the executable file of the current process. -+*/ -+#define LUA_LDIR "!\\lua\\" -+#define LUA_CDIR "!\\" -+#define LUA_PATH_DEFAULT \ -+ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ -+ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" -+#define LUA_CPATH_DEFAULT \ -+ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" -+ -+#else -+#define LUA_ROOT "/usr/local/" -+#define LUA_LDIR LUA_ROOT "share/lua/5.1/" -+#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" -+#define LUA_PATH_DEFAULT \ -+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ -+ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" -+#define LUA_CPATH_DEFAULT \ -+ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" -+#endif -+ -+ -+/* -+@@ LUA_DIRSEP is the directory separator (for submodules). -+** CHANGE it if your machine does not use "/" as the directory separator -+** and is not Windows. (On Windows Lua automatically uses "\".) -+*/ -+#if defined(_WIN32) -+#define LUA_DIRSEP "\\" -+#else -+#define LUA_DIRSEP "/" -+#endif -+ -+ -+/* -+@@ LUA_PATHSEP is the character that separates templates in a path. -+@@ LUA_PATH_MARK is the string that marks the substitution points in a -+@* template. -+@@ LUA_EXECDIR in a Windows path is replaced by the executable's -+@* directory. -+@@ LUA_IGMARK is a mark to ignore all before it when bulding the -+@* luaopen_ function name. -+** CHANGE them if for some reason your system cannot use those -+** characters. (E.g., if one of those characters is a common character -+** in file/directory names.) Probably you do not need to change them. -+*/ -+#define LUA_PATHSEP ";" -+#define LUA_PATH_MARK "?" -+#define LUA_EXECDIR "!" -+#define LUA_IGMARK "-" -+ -+ -+/* -+@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -+** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -+** machines, ptrdiff_t gives a good choice between int or long.) -+*/ -+#define LUA_INTEGER ptrdiff_t -+ -+ -+/* -+@@ LUA_API is a mark for all core API functions. -+@@ LUALIB_API is a mark for all standard library functions. -+** CHANGE them if you need to define those functions in some special way. -+** For instance, if you want to create one Windows DLL with the core and -+** the libraries, you may want to use the following definition (define -+** LUA_BUILD_AS_DLL to get it). -+*/ -+#if defined(LUA_BUILD_AS_DLL) -+ -+#if defined(LUA_CORE) || defined(LUA_LIB) -+#define LUA_API __declspec(dllexport) -+#else -+#define LUA_API __declspec(dllimport) -+#endif -+ -+#else -+ -+#define LUA_API extern -+ -+#endif -+ -+/* more often than not the libs go together with the core */ -+#define LUALIB_API LUA_API -+ -+ -+/* -+@@ LUAI_FUNC is a mark for all extern functions that are not to be -+@* exported to outside modules. -+@@ LUAI_DATA is a mark for all extern (const) variables that are not to -+@* be exported to outside modules. -+** CHANGE them if you need to mark them in some special way. Elf/gcc -+** (versions 3.2 and later) mark them as "hidden" to optimize access -+** when Lua is compiled as a shared library. -+*/ -+#if defined(luaall_c) -+#define LUAI_FUNC static -+#define LUAI_DATA /* empty */ -+ -+#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ -+ defined(__ELF__) -+#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -+#define LUAI_DATA LUAI_FUNC -+ -+#else -+#define LUAI_FUNC extern -+#define LUAI_DATA extern -+#endif -+ -+ -+ -+/* -+@@ LUA_QL describes how error messages quote program elements. -+** CHANGE it if you want a different appearance. -+*/ -+#define LUA_QL(x) "'" x "'" -+#define LUA_QS LUA_QL("%s") -+ -+ -+/* -+@@ LUA_IDSIZE gives the maximum size for the description of the source -+@* of a function in debug information. -+** CHANGE it if you want a different size. -+*/ -+#define LUA_IDSIZE 60 -+ -+ -+/* -+** {================================================================== -+** Stand-alone configuration -+** =================================================================== -+*/ -+ -+#if defined(lua_c) || defined(luaall_c) -+ -+/* -+@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that -+@* is, whether we're running lua interactively). -+** CHANGE it if you have a better definition for non-POSIX/non-Windows -+** systems. -+*/ -+#if defined(LUA_USE_ISATTY) -+#include -+#define lua_stdin_is_tty() isatty(0) -+#elif defined(LUA_WIN) -+#include -+#include -+#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -+#else -+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ -+#endif -+ -+ -+/* -+@@ LUA_PROMPT is the default prompt used by stand-alone Lua. -+@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. -+** CHANGE them if you want different prompts. (You can also change the -+** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) -+*/ -+#define LUA_PROMPT "> " -+#define LUA_PROMPT2 ">> " -+ -+ -+/* -+@@ LUA_PROGNAME is the default name for the stand-alone Lua program. -+** CHANGE it if your stand-alone interpreter has a different name and -+** your system is not able to detect that name automatically. -+*/ -+#define LUA_PROGNAME "lua" -+ -+ -+/* -+@@ LUA_MAXINPUT is the maximum length for an input line in the -+@* stand-alone interpreter. -+** CHANGE it if you need longer lines. -+*/ -+#define LUA_MAXINPUT 512 -+ -+ -+/* -+@@ lua_readline defines how to show a prompt and then read a line from -+@* the standard input. -+@@ lua_saveline defines how to "save" a read line in a "history". -+@@ lua_freeline defines how to free a line read by lua_readline. -+** CHANGE them if you want to improve this functionality (e.g., by using -+** GNU readline and history facilities). -+*/ -+#if defined(LUA_USE_READLINE) -+#include -+#include -+#include -+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -+#define lua_saveline(L,idx) \ -+ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ -+ add_history(lua_tostring(L, idx)); /* add it to history */ -+#define lua_freeline(L,b) ((void)L, free(b)) -+#else -+#define lua_readline(L,b,p) \ -+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ -+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -+#define lua_saveline(L,idx) { (void)L; (void)idx; } -+#define lua_freeline(L,b) { (void)L; (void)b; } -+#endif -+ -+#endif -+ -+/* }================================================================== */ -+ -+ -+/* -+@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles -+@* as a percentage. -+** CHANGE it if you want the GC to run faster or slower (higher values -+** mean larger pauses which mean slower collection.) You can also change -+** this value dynamically. -+*/ -+#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ -+ -+ -+/* -+@@ LUAI_GCMUL defines the default speed of garbage collection relative to -+@* memory allocation as a percentage. -+** CHANGE it if you want to change the granularity of the garbage -+** collection. (Higher values mean coarser collections. 0 represents -+** infinity, where each step performs a full collection.) You can also -+** change this value dynamically. -+*/ -+#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ -+ -+ -+ -+/* -+@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. -+** CHANGE it (define it) if you want exact compatibility with the -+** behavior of setn/getn in Lua 5.0. -+*/ -+#undef LUA_COMPAT_GETN -+ -+/* -+@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. -+** CHANGE it to undefined as soon as you do not need a global 'loadlib' -+** function (the function is still available as 'package.loadlib'). -+*/ -+#undef LUA_COMPAT_LOADLIB -+ -+/* -+@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. -+** CHANGE it to undefined as soon as your programs use only '...' to -+** access vararg parameters (instead of the old 'arg' table). -+*/ -+#define LUA_COMPAT_VARARG -+ -+/* -+@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. -+** CHANGE it to undefined as soon as your programs use 'math.fmod' or -+** the new '%' operator instead of 'math.mod'. -+*/ -+#define LUA_COMPAT_MOD -+ -+/* -+@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting -+@* facility. -+** CHANGE it to 2 if you want the old behaviour, or undefine it to turn -+** off the advisory error when nesting [[...]]. -+*/ -+#define LUA_COMPAT_LSTR 1 -+ -+/* -+@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. -+** CHANGE it to undefined as soon as you rename 'string.gfind' to -+** 'string.gmatch'. -+*/ -+#define LUA_COMPAT_GFIND -+ -+/* -+@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' -+@* behavior. -+** CHANGE it to undefined as soon as you replace to 'luaL_register' -+** your uses of 'luaL_openlib' -+*/ -+#define LUA_COMPAT_OPENLIB -+ -+ -+ -+/* -+@@ luai_apicheck is the assert macro used by the Lua-C API. -+** CHANGE luai_apicheck if you want Lua to perform some checks in the -+** parameters it gets from API calls. This may slow down the interpreter -+** a bit, but may be quite useful when debugging C code that interfaces -+** with Lua. A useful redefinition is to use assert.h. -+*/ -+#if defined(LUA_USE_APICHECK) -+#include -+#define luai_apicheck(L,o) { (void)L; assert(o); } -+#else -+#define luai_apicheck(L,o) { (void)L; } -+#endif -+ -+ -+/* -+@@ LUAI_BITSINT defines the number of bits in an int. -+** CHANGE here if Lua cannot automatically detect the number of bits of -+** your machine. Probably you do not need to change this. -+*/ -+/* avoid overflows in comparison */ -+#if !defined(__KERNEL__) -+#include -+#define LUA_INT_MAX INT_MAX -+#else -+#define LUA_INT_MAX (~0U>>1) -+#endif -+ -+#if LUA_INT_MAX-20 < 32760 -+#define LUAI_BITSINT 16 -+#elif LUA_INT_MAX > 2147483640L -+/* int has at least 32 bits */ -+#define LUAI_BITSINT 32 -+#else -+#error "you must define LUA_BITSINT with number of bits in an integer" -+#endif -+ -+ -+/* -+@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. -+@@ LUAI_INT32 is an signed integer with at least 32 bits. -+@@ LUAI_UMEM is an unsigned integer big enough to count the total -+@* memory used by Lua. -+@@ LUAI_MEM is a signed integer big enough to count the total memory -+@* used by Lua. -+** CHANGE here if for some weird reason the default definitions are not -+** good enough for your machine. (The definitions in the 'else' -+** part always works, but may waste space on machines with 64-bit -+** longs.) Probably you do not need to change this. -+*/ -+#if LUAI_BITSINT >= 32 -+#define LUAI_UINT32 unsigned int -+#define LUAI_INT32 int -+#define LUAI_MAXINT32 INT_MAX -+#define LUAI_UMEM size_t -+#define LUAI_MEM ptrdiff_t -+#else -+/* 16-bit ints */ -+#define LUAI_UINT32 unsigned long -+#define LUAI_INT32 long -+#define LUAI_MAXINT32 LONG_MAX -+#define LUAI_UMEM unsigned long -+#define LUAI_MEM long -+#endif -+ -+ -+/* -+@@ LUAI_MAXCALLS limits the number of nested calls. -+** CHANGE it if you need really deep recursive calls. This limit is -+** arbitrary; its only purpose is to stop infinite recursion before -+** exhausting memory. -+*/ -+#define LUAI_MAXCALLS 20000 -+ -+ -+/* -+@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function -+@* can use. -+** CHANGE it if you need lots of (Lua) stack space for your C -+** functions. This limit is arbitrary; its only purpose is to stop C -+** functions to consume unlimited stack space. (must be smaller than -+** -LUA_REGISTRYINDEX) -+*/ -+#define LUAI_MAXCSTACK 8000 -+ -+ -+ -+/* -+** {================================================================== -+** CHANGE (to smaller values) the following definitions if your system -+** has a small C stack. (Or you may want to change them to larger -+** values if your system has a large C stack and these limits are -+** too rigid for you.) Some of these constants control the size of -+** stack-allocated arrays used by the compiler or the interpreter, while -+** others limit the maximum number of recursive calls that the compiler -+** or the interpreter can perform. Values too large may cause a C stack -+** overflow for some forms of deep constructs. -+** =================================================================== -+*/ -+ -+ -+/* -+@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and -+@* syntactical nested non-terminals in a program. -+*/ -+#define LUAI_MAXCCALLS 200 -+ -+ -+/* -+@@ LUAI_MAXVARS is the maximum number of local variables per function -+@* (must be smaller than 250). -+*/ -+#define LUAI_MAXVARS 200 -+ -+ -+/* -+@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function -+@* (must be smaller than 250). -+*/ -+#define LUAI_MAXUPVALUES 60 -+ -+ -+/* -+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -+*/ -+#define LUAL_BUFFERSIZE BUFSIZ -+ -+/* }================================================================== */ -+ -+ -+ -+ -+/* -+** {================================================================== -+@@ LUA_NUMBER is the type of numbers in Lua. -+** CHANGE the following definitions only if you want to build Lua -+** with a number type different from double. You may also need to -+** change lua_number2int & lua_number2integer. -+** =================================================================== -+*/ -+#if !defined(NO_FPU) -+#define LUA_NUMBER_DOUBLE -+#define LUA_NUMBER double -+#else -+#define LUA_NUMBER long -+#endif -+ -+/* -+@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -+@* over a number. -+*/ -+#define LUAI_UACNUMBER LUA_NUMBER -+ -+ -+/* -+@@ LUA_NUMBER_SCAN is the format for reading numbers. -+@@ LUA_NUMBER_FMT is the format for writing numbers. -+@@ lua_number2str converts a number to a string. -+@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -+@@ lua_str2number converts a string to a number. -+*/ -+#if !defined(NO_FPU) -+#define LUA_NUMBER_SCAN "%lf" -+#define LUA_NUMBER_FMT "%.14g" -+#define lua_str2number(s,p) strtod((s), (p)) -+#else -+#define LUA_NUMBER_SCAN "%ld" -+#define LUA_NUMBER_FMT "%ld" -+#if !defined(__KERNEL__) -+#define lua_str2number(s,p) strtol((s), (p), 10) -+#else -+#define lua_str2number(s,p) simple_strtol((s), (p), 10) -+#endif -+#endif -+ -+#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ -+#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -+ -+/* -+@@ The luai_num* macros define the primitive operations over numbers. -+*/ -+#if defined(LUA_CORE) -+#define luai_numadd(a,b) ((a)+(b)) -+#define luai_numsub(a,b) ((a)-(b)) -+#define luai_nummul(a,b) ((a)*(b)) -+#define luai_numdiv(a,b) ((a)/(b)) -+#define luai_numunm(a) (-(a)) -+#define luai_numeq(a,b) ((a)==(b)) -+#define luai_numlt(a,b) ((a)<(b)) -+#define luai_numle(a,b) ((a)<=(b)) -+#define luai_numisnan(a) (!luai_numeq((a), (a))) -+#if !defined(NO_FPU) -+#include -+#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -+#define luai_numpow(a,b) (pow(a,b)) -+#else -+#define luai_nummod(a,b) ((a)%(b)) -+#define luai_numpow(a,b) luai_nummul(a,b) -+#endif -+#endif -+ -+ -+/* -+@@ lua_number2int is a macro to convert lua_Number to int. -+@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. -+** CHANGE them if you know a faster way to convert a lua_Number to -+** int (with any rounding method and without throwing errors) in your -+** system. In Pentium machines, a naive typecast from double to int -+** in C is extremely slow, so any alternative is worth trying. -+*/ -+ -+/* On a Pentium, resort to a trick */ -+#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ -+ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) -+ -+/* On a Microsoft compiler, use assembler */ -+#if defined(_MSC_VER) -+ -+#define lua_number2int(i,d) __asm fld d __asm fistp i -+#define lua_number2integer(i,n) lua_number2int(i, n) -+ -+/* the next trick should work on any Pentium, but sometimes clashes -+ with a DirectX idiosyncrasy */ -+#else -+ -+union luai_Cast { double l_d; long l_l; }; -+#define lua_number2int(i,d) \ -+ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } -+#define lua_number2integer(i,n) lua_number2int(i, n) -+ -+#endif -+ -+ -+/* this option always works, but may be slow */ -+#else -+#define lua_number2int(i,d) ((i)=(int)(d)) -+#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) -+ -+#endif -+ -+/* }================================================================== */ -+ -+ -+/* -+@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. -+** CHANGE it if your system requires alignments larger than double. (For -+** instance, if your system supports long doubles and they must be -+** aligned in 16-byte boundaries, then you should add long double in the -+** union.) Probably you do not need to change this. -+*/ -+#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } -+ -+ -+/* -+@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. -+** CHANGE them if you prefer to use longjmp/setjmp even with C++ -+** or if want/don't to use _longjmp/_setjmp instead of regular -+** longjmp/setjmp. By default, Lua handles errors with exceptions when -+** compiling as C++ code, with _longjmp/_setjmp when asked to use them, -+** and with longjmp/setjmp otherwise. -+*/ -+#if defined(__KERNEL__) -+#undef LUA_USE_ULONGJMP -+#endif -+ -+#if defined(__cplusplus) -+/* C++ exceptions */ -+#define LUAI_THROW(L,c) throw(c) -+#define LUAI_TRY(L,c,a) try { a } catch(...) \ -+ { if ((c)->status == 0) (c)->status = -1; } -+#define luai_jmpbuf int /* dummy variable */ -+ -+#elif defined(LUA_USE_ULONGJMP) -+/* in Unix, try _longjmp/_setjmp (more efficient) */ -+#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -+#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -+#define luai_jmpbuf jmp_buf -+ -+#else -+/* default handling with long jumps */ -+#define LUAI_THROW(L,c) longjmp((c)->b, 1) -+#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -+#define luai_jmpbuf jmp_buf -+ -+#endif -+ -+ -+/* -+@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern -+@* can do during pattern-matching. -+** CHANGE it if you need more captures. This limit is arbitrary. -+*/ -+#define LUA_MAXCAPTURES 32 -+ -+ -+/* -+@@ lua_tmpnam is the function that the OS library uses to create a -+@* temporary name. -+@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. -+** CHANGE them if you have an alternative to tmpnam (which is considered -+** insecure) or if you want the original tmpnam anyway. By default, Lua -+** uses tmpnam except when POSIX is available, where it uses mkstemp. -+*/ -+#if defined(loslib_c) || defined(luaall_c) -+ -+#if defined(LUA_USE_MKSTEMP) -+#include -+#define LUA_TMPNAMBUFSIZE 32 -+#define lua_tmpnam(b,e) { \ -+ strcpy(b, "/tmp/lua_XXXXXX"); \ -+ e = mkstemp(b); \ -+ if (e != -1) close(e); \ -+ e = (e == -1); } -+ -+#else -+#define LUA_TMPNAMBUFSIZE L_tmpnam -+#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } -+#endif -+ -+#endif -+ -+ -+/* -+@@ lua_popen spawns a new process connected to the current one through -+@* the file streams. -+** CHANGE it if you have a way to implement it in your system. -+*/ -+#if defined(LUA_USE_POPEN) -+ -+#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -+#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) -+ -+#elif defined(LUA_WIN) -+ -+#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -+#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) -+ -+#else -+ -+#define lua_popen(L,c,m) ((void)((void)c, m), \ -+ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -+#define lua_pclose(L,file) ((void)((void)L, file), 0) -+ -+#endif -+ -+/* -+@@ LUA_DL_* define which dynamic-library system Lua should use. -+** CHANGE here if Lua has problems choosing the appropriate -+** dynamic-library system for your platform (either Windows' DLL, Mac's -+** dyld, or Unix's dlopen). If your system is some kind of Unix, there -+** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for -+** it. To use dlopen you also need to adapt the src/Makefile (probably -+** adding -ldl to the linker options), so Lua does not select it -+** automatically. (When you change the makefile to add -ldl, you must -+** also add -DLUA_USE_DLOPEN.) -+** If you do not want any kind of dynamic library, undefine all these -+** options. -+** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. -+*/ -+#if defined(LUA_USE_DLOPEN) -+#define LUA_DL_DLOPEN -+#endif -+ -+#if defined(LUA_WIN) -+#define LUA_DL_DLL -+#endif -+ -+ -+/* -+@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State -+@* (the data goes just *before* the lua_State pointer). -+** CHANGE (define) this if you really need that. This value must be -+** a multiple of the maximum alignment required for your machine. -+*/ -+#define LUAI_EXTRASPACE 0 -+ -+ -+/* -+@@ luai_userstate* allow user-specific actions on threads. -+** CHANGE them if you defined LUAI_EXTRASPACE and need to do something -+** extra when a thread is created/deleted/resumed/yielded. -+*/ -+#define luai_userstateopen(L) ((void)L) -+#define luai_userstateclose(L) ((void)L) -+#define luai_userstatethread(L,L1) ((void)L) -+#define luai_userstatefree(L) ((void)L) -+#define luai_userstateresume(L,n) ((void)L) -+#define luai_userstateyield(L,n) ((void)L) -+ -+ -+/* -+@@ LUA_INTFRMLEN is the length modifier for integer conversions -+@* in 'string.format'. -+@@ LUA_INTFRM_T is the integer type correspoding to the previous length -+@* modifier. -+** CHANGE them if your system supports long long or does not support long. -+*/ -+ -+#if defined(LUA_USELONGLONG) -+ -+#define LUA_INTFRMLEN "ll" -+#define LUA_INTFRM_T long long -+ -+#else -+ -+#define LUA_INTFRMLEN "l" -+#define LUA_INTFRM_T long -+ -+#endif -+ -+/* =================================================================== */ -+ -+/* -+** Local configuration. You can use this space to add your redefinitions -+** without modifying the main part of the file. -+*/ -+ -+ -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lua.h -@@ -0,0 +1,387 @@ -+/* -+** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ -+** Lua - An Extensible Extension Language -+** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -+** See Copyright Notice at the end of this file -+*/ -+ -+ -+#ifndef lua_h -+#define lua_h -+ -+#include -+#include -+ -+#include "luaconf.h" -+ -+ -+#define LUA_VERSION "Lua 5.1" -+#define LUA_RELEASE "Lua 5.1.4" -+#define LUA_VERSION_NUM 501 -+#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" -+#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" -+ -+ -+/* mark for precompiled code (`Lua') */ -+#define LUA_SIGNATURE "\033Lua" -+ -+/* option for multiple returns in `lua_pcall' and `lua_call' */ -+#define LUA_MULTRET (-1) -+ -+ -+/* -+** pseudo-indices -+*/ -+#define LUA_REGISTRYINDEX (-10000) -+#define LUA_ENVIRONINDEX (-10001) -+#define LUA_GLOBALSINDEX (-10002) -+#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) -+ -+ -+/* thread status; 0 is OK */ -+#define LUA_YIELD 1 -+#define LUA_ERRRUN 2 -+#define LUA_ERRSYNTAX 3 -+#define LUA_ERRMEM 4 -+#define LUA_ERRERR 5 -+ -+ -+typedef struct lua_State lua_State; -+ -+typedef int (*lua_CFunction) (lua_State *L); -+ -+ -+/* -+** functions that read/write blocks when loading/dumping Lua chunks -+*/ -+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); -+ -+typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); -+ -+ -+/* -+** prototype for memory-allocation functions -+*/ -+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); -+ -+ -+/* -+** basic types -+*/ -+#define LUA_TNONE (-1) -+ -+#define LUA_TNIL 0 -+#define LUA_TBOOLEAN 1 -+#define LUA_TLIGHTUSERDATA 2 -+#define LUA_TNUMBER 3 -+#define LUA_TSTRING 4 -+#define LUA_TTABLE 5 -+#define LUA_TFUNCTION 6 -+#define LUA_TUSERDATA 7 -+#define LUA_TTHREAD 8 -+ -+ -+ -+/* minimum Lua stack available to a C function */ -+#define LUA_MINSTACK 20 -+ -+ -+/* -+** generic extra include file -+*/ -+#if defined(LUA_USER_H) -+#include LUA_USER_H -+#endif -+ -+ -+/* type of numbers in Lua */ -+typedef LUA_NUMBER lua_Number; -+ -+ -+/* type for integer functions */ -+typedef LUA_INTEGER lua_Integer; -+ -+ -+ -+/* -+** state manipulation -+*/ -+LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -+LUA_API void (lua_close) (lua_State *L); -+LUA_API lua_State *(lua_newthread) (lua_State *L); -+ -+LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); -+ -+ -+/* -+** basic stack manipulation -+*/ -+LUA_API int (lua_gettop) (lua_State *L); -+LUA_API void (lua_settop) (lua_State *L, int idx); -+LUA_API void (lua_pushvalue) (lua_State *L, int idx); -+LUA_API void (lua_remove) (lua_State *L, int idx); -+LUA_API void (lua_insert) (lua_State *L, int idx); -+LUA_API void (lua_replace) (lua_State *L, int idx); -+LUA_API int (lua_checkstack) (lua_State *L, int sz); -+ -+LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); -+ -+ -+/* -+** access functions (stack -> C) -+*/ -+ -+LUA_API int (lua_isnumber) (lua_State *L, int idx); -+LUA_API int (lua_isstring) (lua_State *L, int idx); -+LUA_API int (lua_iscfunction) (lua_State *L, int idx); -+LUA_API int (lua_isuserdata) (lua_State *L, int idx); -+LUA_API int (lua_type) (lua_State *L, int idx); -+LUA_API const char *(lua_typename) (lua_State *L, int tp); -+ -+LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); -+LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -+LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); -+ -+LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); -+LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); -+LUA_API int (lua_toboolean) (lua_State *L, int idx); -+LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -+LUA_API size_t (lua_objlen) (lua_State *L, int idx); -+LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -+LUA_API void *(lua_touserdata) (lua_State *L, int idx); -+LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -+LUA_API const void *(lua_topointer) (lua_State *L, int idx); -+ -+ -+/* -+** push functions (C -> stack) -+*/ -+LUA_API void (lua_pushnil) (lua_State *L); -+LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -+LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -+LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); -+LUA_API void (lua_pushstring) (lua_State *L, const char *s); -+LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, -+ va_list argp); -+LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -+LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -+LUA_API void (lua_pushboolean) (lua_State *L, int b); -+LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -+LUA_API int (lua_pushthread) (lua_State *L); -+ -+ -+/* -+** get functions (Lua -> stack) -+*/ -+LUA_API void (lua_gettable) (lua_State *L, int idx); -+LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); -+LUA_API void (lua_rawget) (lua_State *L, int idx); -+LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); -+LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -+LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -+LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -+LUA_API void (lua_getfenv) (lua_State *L, int idx); -+ -+ -+/* -+** set functions (stack -> Lua) -+*/ -+LUA_API void (lua_settable) (lua_State *L, int idx); -+LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -+LUA_API void (lua_rawset) (lua_State *L, int idx); -+LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); -+LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -+LUA_API int (lua_setfenv) (lua_State *L, int idx); -+ -+ -+/* -+** `load' and `call' functions (load and run Lua code) -+*/ -+LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); -+LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); -+LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); -+LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, -+ const char *chunkname); -+ -+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); -+ -+ -+/* -+** coroutine functions -+*/ -+LUA_API int (lua_yield) (lua_State *L, int nresults); -+LUA_API int (lua_resume) (lua_State *L, int narg); -+LUA_API int (lua_status) (lua_State *L); -+ -+/* -+** garbage-collection function and options -+*/ -+ -+#define LUA_GCSTOP 0 -+#define LUA_GCRESTART 1 -+#define LUA_GCCOLLECT 2 -+#define LUA_GCCOUNT 3 -+#define LUA_GCCOUNTB 4 -+#define LUA_GCSTEP 5 -+#define LUA_GCSETPAUSE 6 -+#define LUA_GCSETSTEPMUL 7 -+ -+LUA_API int (lua_gc) (lua_State *L, int what, int data); -+ -+ -+/* -+** miscellaneous functions -+*/ -+ -+LUA_API int (lua_error) (lua_State *L); -+ -+LUA_API int (lua_next) (lua_State *L, int idx); -+ -+LUA_API void (lua_concat) (lua_State *L, int n); -+ -+LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); -+ -+ -+ -+/* -+** =============================================================== -+** some useful macros -+** =============================================================== -+*/ -+ -+#define lua_pop(L,n) lua_settop(L, -(n)-1) -+ -+#define lua_newtable(L) lua_createtable(L, 0, 0) -+ -+#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) -+ -+#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) -+ -+#define lua_strlen(L,i) lua_objlen(L, (i)) -+ -+#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -+#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -+#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -+#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -+#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -+#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -+#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -+#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) -+ -+#define lua_pushliteral(L, s) \ -+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) -+ -+#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) -+#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) -+ -+#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) -+ -+ -+ -+/* -+** compatibility macros and functions -+*/ -+ -+#define lua_open() luaL_newstate() -+ -+#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) -+ -+#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) -+ -+#define lua_Chunkreader lua_Reader -+#define lua_Chunkwriter lua_Writer -+ -+ -+/* hack */ -+LUA_API void lua_setlevel (lua_State *from, lua_State *to); -+ -+ -+/* -+** {====================================================================== -+** Debug API -+** ======================================================================= -+*/ -+ -+ -+/* -+** Event codes -+*/ -+#define LUA_HOOKCALL 0 -+#define LUA_HOOKRET 1 -+#define LUA_HOOKLINE 2 -+#define LUA_HOOKCOUNT 3 -+#define LUA_HOOKTAILRET 4 -+ -+ -+/* -+** Event masks -+*/ -+#define LUA_MASKCALL (1 << LUA_HOOKCALL) -+#define LUA_MASKRET (1 << LUA_HOOKRET) -+#define LUA_MASKLINE (1 << LUA_HOOKLINE) -+#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) -+ -+typedef struct lua_Debug lua_Debug; /* activation record */ -+ -+ -+/* Functions to be called by the debuger in specific events */ -+typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); -+ -+ -+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); -+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); -+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); -+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); -+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); -+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); -+ -+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); -+LUA_API lua_Hook lua_gethook (lua_State *L); -+LUA_API int lua_gethookmask (lua_State *L); -+LUA_API int lua_gethookcount (lua_State *L); -+ -+ -+struct lua_Debug { -+ int event; -+ const char *name; /* (n) */ -+ const char *namewhat; /* (n) `global', `local', `field', `method' */ -+ const char *what; /* (S) `Lua', `C', `main', `tail' */ -+ const char *source; /* (S) */ -+ int currentline; /* (l) */ -+ int nups; /* (u) number of upvalues */ -+ int linedefined; /* (S) */ -+ int lastlinedefined; /* (S) */ -+ char short_src[LUA_IDSIZE]; /* (S) */ -+ /* private part */ -+ int i_ci; /* active function */ -+}; -+ -+/* }====================================================================== */ -+ -+ -+/****************************************************************************** -+* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. -+* -+* Permission is hereby granted, free of charge, to any person obtaining -+* a copy of this software and associated documentation files (the -+* "Software"), to deal in the Software without restriction, including -+* without limitation the rights to use, copy, modify, merge, publish, -+* distribute, sublicense, and/or sell copies of the Software, and to -+* permit persons to whom the Software is furnished to do so, subject to -+* the following conditions: -+* -+* The above copyright notice and this permission notice shall be -+* included in all copies or substantial portions of the Software. -+* -+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+******************************************************************************/ -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lualib.h -@@ -0,0 +1,55 @@ -+/* -+** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua standard libraries -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lualib_h -+#define lualib_h -+ -+#include "lua.h" -+ -+ -+/* Key to file-handle type */ -+#define LUA_FILEHANDLE "FILE*" -+ -+ -+#define LUA_COLIBNAME "coroutine" -+LUALIB_API int (luaopen_base) (lua_State *L); -+ -+#define LUA_TABLIBNAME "table" -+LUALIB_API int (luaopen_table) (lua_State *L); -+/* -+#define LUA_IOLIBNAME "io" -+LUALIB_API int (luaopen_io) (lua_State *L); -+ -+#define LUA_OSLIBNAME "os" -+LUALIB_API int (luaopen_os) (lua_State *L); -+*/ -+ -+#define LUA_STRLIBNAME "string" -+LUALIB_API int (luaopen_string) (lua_State *L); -+ -+/* -+#define LUA_MATHLIBNAME "math" -+LUALIB_API int (luaopen_math) (lua_State *L); -+ -+#define LUA_DBLIBNAME "debug" -+LUALIB_API int (luaopen_debug) (lua_State *L); -+ -+#define LUA_LOADLIBNAME "package" -+LUALIB_API int (luaopen_package) (lua_State *L); -+*/ -+ -+/* open all previous libraries */ -+LUALIB_API void (luaL_openlibs) (lua_State *L); -+ -+ -+ -+#ifndef lua_assert -+#define lua_assert(x) ((void)0) -+#endif -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lundump.c -@@ -0,0 +1,227 @@ -+/* -+** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ -+** load precompiled Lua chunks -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lundump_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstring.h" -+#include "lundump.h" -+#include "lzio.h" -+ -+typedef struct { -+ lua_State* L; -+ ZIO* Z; -+ Mbuffer* b; -+ const char* name; -+} LoadState; -+ -+#ifdef LUAC_TRUST_BINARIES -+#define IF(c,s) -+#define error(S,s) -+#else -+#define IF(c,s) if (c) error(S,s) -+ -+static void error(LoadState* S, const char* why) -+{ -+ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); -+ luaD_throw(S->L,LUA_ERRSYNTAX); -+} -+#endif -+ -+#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -+#define LoadByte(S) (lu_byte)LoadChar(S) -+#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -+#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) -+ -+static void LoadBlock(LoadState* S, void* b, size_t size) -+{ -+ size_t r=luaZ_read(S->Z,b,size); -+ IF (r!=0, "unexpected end"); -+} -+ -+static int LoadChar(LoadState* S) -+{ -+ char x; -+ LoadVar(S,x); -+ return x; -+} -+ -+static int LoadInt(LoadState* S) -+{ -+ int x; -+ LoadVar(S,x); -+ IF (x<0, "bad integer"); -+ return x; -+} -+ -+static lua_Number LoadNumber(LoadState* S) -+{ -+ lua_Number x; -+ LoadVar(S,x); -+ return x; -+} -+ -+static TString* LoadString(LoadState* S) -+{ -+ size_t size; -+ LoadVar(S,size); -+ if (size==0) -+ return NULL; -+ else -+ { -+ char* s=luaZ_openspace(S->L,S->b,size); -+ LoadBlock(S,s,size); -+ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ -+ } -+} -+ -+static void LoadCode(LoadState* S, Proto* f) -+{ -+ int n=LoadInt(S); -+ f->code=luaM_newvector(S->L,n,Instruction); -+ f->sizecode=n; -+ LoadVector(S,f->code,n,sizeof(Instruction)); -+} -+ -+static Proto* LoadFunction(LoadState* S, TString* p); -+ -+static void LoadConstants(LoadState* S, Proto* f) -+{ -+ int i,n; -+ n=LoadInt(S); -+ f->k=luaM_newvector(S->L,n,TValue); -+ f->sizek=n; -+ for (i=0; ik[i]); -+ for (i=0; ik[i]; -+ int t=LoadChar(S); -+ switch (t) -+ { -+ case LUA_TNIL: -+ setnilvalue(o); -+ break; -+ case LUA_TBOOLEAN: -+ setbvalue(o,LoadChar(S)!=0); -+ break; -+ case LUA_TNUMBER: -+ setnvalue(o,LoadNumber(S)); -+ break; -+ case LUA_TSTRING: -+ setsvalue2n(S->L,o,LoadString(S)); -+ break; -+ default: -+ error(S,"bad constant"); -+ break; -+ } -+ } -+ n=LoadInt(S); -+ f->p=luaM_newvector(S->L,n,Proto*); -+ f->sizep=n; -+ for (i=0; ip[i]=NULL; -+ for (i=0; ip[i]=LoadFunction(S,f->source); -+} -+ -+static void LoadDebug(LoadState* S, Proto* f) -+{ -+ int i,n; -+ n=LoadInt(S); -+ f->lineinfo=luaM_newvector(S->L,n,int); -+ f->sizelineinfo=n; -+ LoadVector(S,f->lineinfo,n,sizeof(int)); -+ n=LoadInt(S); -+ f->locvars=luaM_newvector(S->L,n,LocVar); -+ f->sizelocvars=n; -+ for (i=0; ilocvars[i].varname=NULL; -+ for (i=0; ilocvars[i].varname=LoadString(S); -+ f->locvars[i].startpc=LoadInt(S); -+ f->locvars[i].endpc=LoadInt(S); -+ } -+ n=LoadInt(S); -+ f->upvalues=luaM_newvector(S->L,n,TString*); -+ f->sizeupvalues=n; -+ for (i=0; iupvalues[i]=NULL; -+ for (i=0; iupvalues[i]=LoadString(S); -+} -+ -+static Proto* LoadFunction(LoadState* S, TString* p) -+{ -+ Proto* f; -+ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); -+ f=luaF_newproto(S->L); -+ setptvalue2s(S->L,S->L->top,f); incr_top(S->L); -+ f->source=LoadString(S); if (f->source==NULL) f->source=p; -+ f->linedefined=LoadInt(S); -+ f->lastlinedefined=LoadInt(S); -+ f->nups=LoadByte(S); -+ f->numparams=LoadByte(S); -+ f->is_vararg=LoadByte(S); -+ f->maxstacksize=LoadByte(S); -+ LoadCode(S,f); -+ LoadConstants(S,f); -+ LoadDebug(S,f); -+ IF (!luaG_checkcode(f), "bad code"); -+ S->L->top--; -+ S->L->nCcalls--; -+ return f; -+} -+ -+static void LoadHeader(LoadState* S) -+{ -+ char h[LUAC_HEADERSIZE]; -+ char s[LUAC_HEADERSIZE]; -+ luaU_header(h); -+ LoadBlock(S,s,LUAC_HEADERSIZE); -+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); -+} -+ -+/* -+** load precompiled chunk -+*/ -+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -+{ -+ LoadState S; -+ if (*name=='@' || *name=='=') -+ S.name=name+1; -+ else if (*name==LUA_SIGNATURE[0]) -+ S.name="binary string"; -+ else -+ S.name=name; -+ S.L=L; -+ S.Z=Z; -+ S.b=buff; -+ LoadHeader(&S); -+ return LoadFunction(&S,luaS_newliteral(L,"=?")); -+} -+ -+/* -+* make header -+*/ -+void luaU_header (char* h) -+{ -+ int x=1; -+ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); -+ h+=sizeof(LUA_SIGNATURE)-1; -+ *h++=(char)LUAC_VERSION; -+ *h++=(char)LUAC_FORMAT; -+ *h++=(char)*(char*)&x; /* endianness */ -+ *h++=(char)sizeof(int); -+ *h++=(char)sizeof(size_t); -+ *h++=(char)sizeof(Instruction); -+ *h++=(char)sizeof(lua_Number); -+ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ -+} ---- /dev/null -+++ b/extensions/LUA/lua/lundump.h -@@ -0,0 +1,36 @@ -+/* -+** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -+** load precompiled Lua chunks -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lundump_h -+#define lundump_h -+ -+#include "lobject.h" -+#include "lzio.h" -+ -+/* load one chunk; from lundump.c */ -+LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); -+ -+/* make header; from lundump.c */ -+LUAI_FUNC void luaU_header (char* h); -+ -+/* dump one chunk; from ldump.c */ -+LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); -+ -+#ifdef luac_c -+/* print one chunk; from print.c */ -+LUAI_FUNC void luaU_print (const Proto* f, int full); -+#endif -+ -+/* for header of binary files -- this is Lua 5.1 */ -+#define LUAC_VERSION 0x51 -+ -+/* for header of binary files -- this is the official format */ -+#define LUAC_FORMAT 0 -+ -+/* size of header of binary files */ -+#define LUAC_HEADERSIZE 12 -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lvm.c -@@ -0,0 +1,762 @@ -+/* -+** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ -+** Lua virtual machine -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+ -+#define lvm_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lvm.h" -+ -+ -+ -+/* limit for table tag-method chains (to avoid loops) */ -+#define MAXTAGLOOP 100 -+ -+ -+const TValue *luaV_tonumber (const TValue *obj, TValue *n) { -+ lua_Number num; -+ if (ttisnumber(obj)) return obj; -+ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { -+ setnvalue(n, num); -+ return n; -+ } -+ else -+ return NULL; -+} -+ -+ -+int luaV_tostring (lua_State *L, StkId obj) { -+ if (!ttisnumber(obj)) -+ return 0; -+ else { -+ char s[LUAI_MAXNUMBER2STR]; -+ lua_Number n = nvalue(obj); -+ lua_number2str(s, n); -+ setsvalue2s(L, obj, luaS_new(L, s)); -+ return 1; -+ } -+} -+ -+ -+static void traceexec (lua_State *L, const Instruction *pc) { -+ lu_byte mask = L->hookmask; -+ const Instruction *oldpc = L->savedpc; -+ L->savedpc = pc; -+ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { -+ resethookcount(L); -+ luaD_callhook(L, LUA_HOOKCOUNT, -1); -+ } -+ if (mask & LUA_MASKLINE) { -+ Proto *p = ci_func(L->ci)->l.p; -+ int npc = pcRel(pc, p); -+ int newline = getline(p, npc); -+ /* call linehook when enter a new function, when jump back (loop), -+ or when enter a new line */ -+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) -+ luaD_callhook(L, LUA_HOOKLINE, newline); -+ } -+} -+ -+ -+static void callTMres (lua_State *L, StkId res, const TValue *f, -+ const TValue *p1, const TValue *p2) { -+ ptrdiff_t result = savestack(L, res); -+ setobj2s(L, L->top, f); /* push function */ -+ setobj2s(L, L->top+1, p1); /* 1st argument */ -+ setobj2s(L, L->top+2, p2); /* 2nd argument */ -+ luaD_checkstack(L, 3); -+ L->top += 3; -+ luaD_call(L, L->top - 3, 1); -+ res = restorestack(L, result); -+ L->top--; -+ setobjs2s(L, res, L->top); -+} -+ -+ -+ -+static void callTM (lua_State *L, const TValue *f, const TValue *p1, -+ const TValue *p2, const TValue *p3) { -+ setobj2s(L, L->top, f); /* push function */ -+ setobj2s(L, L->top+1, p1); /* 1st argument */ -+ setobj2s(L, L->top+2, p2); /* 2nd argument */ -+ setobj2s(L, L->top+3, p3); /* 3th argument */ -+ luaD_checkstack(L, 4); -+ L->top += 4; -+ luaD_call(L, L->top - 4, 0); -+} -+ -+ -+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { -+ int loop; -+ for (loop = 0; loop < MAXTAGLOOP; loop++) { -+ const TValue *tm; -+ if (ttistable(t)) { /* `t' is a table? */ -+ Table *h = hvalue(t); -+ const TValue *res = luaH_get(h, key); /* do a primitive get */ -+ if (!ttisnil(res) || /* result is no nil? */ -+ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ -+ setobj2s(L, val, res); -+ return; -+ } -+ /* else will try the tag method */ -+ } -+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) -+ luaG_typeerror(L, t, "index"); -+ if (ttisfunction(tm)) { -+ callTMres(L, val, tm, t, key); -+ return; -+ } -+ t = tm; /* else repeat with `tm' */ -+ } -+ luaG_runerror(L, "loop in gettable"); -+} -+ -+ -+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { -+ int loop; -+ for (loop = 0; loop < MAXTAGLOOP; loop++) { -+ const TValue *tm; -+ if (ttistable(t)) { /* `t' is a table? */ -+ Table *h = hvalue(t); -+ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ -+ if (!ttisnil(oldval) || /* result is no nil? */ -+ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ -+ setobj2t(L, oldval, val); -+ luaC_barriert(L, h, val); -+ return; -+ } -+ /* else will try the tag method */ -+ } -+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) -+ luaG_typeerror(L, t, "index"); -+ if (ttisfunction(tm)) { -+ callTM(L, tm, t, key, val); -+ return; -+ } -+ t = tm; /* else repeat with `tm' */ -+ } -+ luaG_runerror(L, "loop in settable"); -+} -+ -+ -+static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, -+ StkId res, TMS event) { -+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ -+ if (ttisnil(tm)) -+ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ -+ if (ttisnil(tm)) return 0; -+ callTMres(L, res, tm, p1, p2); -+ return 1; -+} -+ -+ -+static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, -+ TMS event) { -+ const TValue *tm1 = fasttm(L, mt1, event); -+ const TValue *tm2; -+ if (tm1 == NULL) return NULL; /* no metamethod */ -+ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ -+ tm2 = fasttm(L, mt2, event); -+ if (tm2 == NULL) return NULL; /* no metamethod */ -+ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ -+ return tm1; -+ return NULL; -+} -+ -+ -+static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, -+ TMS event) { -+ const TValue *tm1 = luaT_gettmbyobj(L, p1, event); -+ const TValue *tm2; -+ if (ttisnil(tm1)) return -1; /* no metamethod? */ -+ tm2 = luaT_gettmbyobj(L, p2, event); -+ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ -+ return -1; -+ callTMres(L, L->top, tm1, p1, p2); -+ return !l_isfalse(L->top); -+} -+ -+ -+static int l_strcmp (const TString *ls, const TString *rs) { -+ const char *l = getstr(ls); -+ size_t ll = ls->tsv.len; -+ const char *r = getstr(rs); -+ size_t lr = rs->tsv.len; -+ for (;;) { -+ int temp = strcoll(l, r); -+ if (temp != 0) return temp; -+ else { /* strings are equal up to a `\0' */ -+ size_t len = strlen(l); /* index of first `\0' in both strings */ -+ if (len == lr) /* r is finished? */ -+ return (len == ll) ? 0 : 1; -+ else if (len == ll) /* l is finished? */ -+ return -1; /* l is smaller than r (because r is not finished) */ -+ /* both strings longer than `len'; go on comparing (after the `\0') */ -+ len++; -+ l += len; ll -= len; r += len; lr -= len; -+ } -+ } -+} -+ -+ -+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { -+ int res; -+ if (ttype(l) != ttype(r)) -+ return luaG_ordererror(L, l, r); -+ else if (ttisnumber(l)) -+ return luai_numlt(nvalue(l), nvalue(r)); -+ else if (ttisstring(l)) -+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; -+ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) -+ return res; -+ return luaG_ordererror(L, l, r); -+} -+ -+ -+static int lessequal (lua_State *L, const TValue *l, const TValue *r) { -+ int res; -+ if (ttype(l) != ttype(r)) -+ return luaG_ordererror(L, l, r); -+ else if (ttisnumber(l)) -+ return luai_numle(nvalue(l), nvalue(r)); -+ else if (ttisstring(l)) -+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; -+ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ -+ return res; -+ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ -+ return !res; -+ return luaG_ordererror(L, l, r); -+} -+ -+ -+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { -+ const TValue *tm; -+ lua_assert(ttype(t1) == ttype(t2)); -+ switch (ttype(t1)) { -+ case LUA_TNIL: return 1; -+ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); -+ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ -+ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); -+ case LUA_TUSERDATA: { -+ if (uvalue(t1) == uvalue(t2)) return 1; -+ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, -+ TM_EQ); -+ break; /* will try TM */ -+ } -+ case LUA_TTABLE: { -+ if (hvalue(t1) == hvalue(t2)) return 1; -+ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); -+ break; /* will try TM */ -+ } -+ default: return gcvalue(t1) == gcvalue(t2); -+ } -+ if (tm == NULL) return 0; /* no TM? */ -+ callTMres(L, L->top, tm, t1, t2); /* call TM */ -+ return !l_isfalse(L->top); -+} -+ -+ -+void luaV_concat (lua_State *L, int total, int last) { -+ do { -+ StkId top = L->base + last + 1; -+ int n = 2; /* number of elements handled in this pass (at least 2) */ -+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { -+ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) -+ luaG_concaterror(L, top-2, top-1); -+ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ -+ (void)tostring(L, top - 2); /* result is first op (as string) */ -+ else { -+ /* at least two string values; get as many as possible */ -+ size_t tl = tsvalue(top-1)->len; -+ char *buffer; -+ int i; -+ /* collect total length */ -+ for (n = 1; n < total && tostring(L, top-n-1); n++) { -+ size_t l = tsvalue(top-n-1)->len; -+ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); -+ tl += l; -+ } -+ buffer = luaZ_openspace(L, &G(L)->buff, tl); -+ tl = 0; -+ for (i=n; i>0; i--) { /* concat all strings */ -+ size_t l = tsvalue(top-i)->len; -+ memcpy(buffer+tl, svalue(top-i), l); -+ tl += l; -+ } -+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); -+ } -+ total -= n-1; /* got `n' strings to create 1 new */ -+ last -= n-1; -+ } while (total > 1); /* repeat until only 1 result left */ -+} -+ -+ -+static void Arith (lua_State *L, StkId ra, const TValue *rb, -+ const TValue *rc, TMS op) { -+ TValue tempb, tempc; -+ const TValue *b, *c; -+ if ((b = luaV_tonumber(rb, &tempb)) != NULL && -+ (c = luaV_tonumber(rc, &tempc)) != NULL) { -+ lua_Number nb = nvalue(b), nc = nvalue(c); -+ switch (op) { -+ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; -+ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; -+ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; -+ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; -+ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; -+ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; -+ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; -+ default: lua_assert(0); break; -+ } -+ } -+ else if (!call_binTM(L, rb, rc, ra, op)) -+ luaG_aritherror(L, rb, rc); -+} -+ -+ -+ -+/* -+** some macros for common tasks in `luaV_execute' -+*/ -+ -+#define runtime_check(L, c) { if (!(c)) break; } -+ -+#define RA(i) (base+GETARG_A(i)) -+/* to be used after possible stack reallocation */ -+#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -+#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -+#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ -+ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -+#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ -+ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -+#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) -+ -+ -+#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} -+ -+ -+#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } -+ -+ -+#define arith_op(op,tm) { \ -+ TValue *rb = RKB(i); \ -+ TValue *rc = RKC(i); \ -+ if (ttisnumber(rb) && ttisnumber(rc)) { \ -+ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ -+ setnvalue(ra, op(nb, nc)); \ -+ } \ -+ else \ -+ Protect(Arith(L, ra, rb, rc, tm)); \ -+ } -+ -+ -+ -+void luaV_execute (lua_State *L, int nexeccalls) { -+ LClosure *cl; -+ StkId base; -+ TValue *k; -+ const Instruction *pc; -+ reentry: /* entry point */ -+ lua_assert(isLua(L->ci)); -+ pc = L->savedpc; -+ cl = &clvalue(L->ci->func)->l; -+ base = L->base; -+ k = cl->p->k; -+ /* main loop of interpreter */ -+ for (;;) { -+ const Instruction i = *pc++; -+ StkId ra; -+ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && -+ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { -+ traceexec(L, pc); -+ if (L->status == LUA_YIELD) { /* did hook yield? */ -+ L->savedpc = pc - 1; -+ return; -+ } -+ base = L->base; -+ } -+ /* warning!! several calls may realloc the stack and invalidate `ra' */ -+ ra = RA(i); -+ lua_assert(base == L->base && L->base == L->ci->base); -+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); -+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); -+ switch (GET_OPCODE(i)) { -+ case OP_MOVE: { -+ setobjs2s(L, ra, RB(i)); -+ continue; -+ } -+ case OP_LOADK: { -+ setobj2s(L, ra, KBx(i)); -+ continue; -+ } -+ case OP_LOADBOOL: { -+ setbvalue(ra, GETARG_B(i)); -+ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ -+ continue; -+ } -+ case OP_LOADNIL: { -+ TValue *rb = RB(i); -+ do { -+ setnilvalue(rb--); -+ } while (rb >= ra); -+ continue; -+ } -+ case OP_GETUPVAL: { -+ int b = GETARG_B(i); -+ setobj2s(L, ra, cl->upvals[b]->v); -+ continue; -+ } -+ case OP_GETGLOBAL: { -+ TValue g; -+ TValue *rb = KBx(i); -+ sethvalue(L, &g, cl->env); -+ lua_assert(ttisstring(rb)); -+ Protect(luaV_gettable(L, &g, rb, ra)); -+ continue; -+ } -+ case OP_GETTABLE: { -+ Protect(luaV_gettable(L, RB(i), RKC(i), ra)); -+ continue; -+ } -+ case OP_SETGLOBAL: { -+ TValue g; -+ sethvalue(L, &g, cl->env); -+ lua_assert(ttisstring(KBx(i))); -+ Protect(luaV_settable(L, &g, KBx(i), ra)); -+ continue; -+ } -+ case OP_SETUPVAL: { -+ UpVal *uv = cl->upvals[GETARG_B(i)]; -+ setobj(L, uv->v, ra); -+ luaC_barrier(L, uv, ra); -+ continue; -+ } -+ case OP_SETTABLE: { -+ Protect(luaV_settable(L, ra, RKB(i), RKC(i))); -+ continue; -+ } -+ case OP_NEWTABLE: { -+ int b = GETARG_B(i); -+ int c = GETARG_C(i); -+ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); -+ Protect(luaC_checkGC(L)); -+ continue; -+ } -+ case OP_SELF: { -+ StkId rb = RB(i); -+ setobjs2s(L, ra+1, rb); -+ Protect(luaV_gettable(L, rb, RKC(i), ra)); -+ continue; -+ } -+ case OP_ADD: { -+ arith_op(luai_numadd, TM_ADD); -+ continue; -+ } -+ case OP_SUB: { -+ arith_op(luai_numsub, TM_SUB); -+ continue; -+ } -+ case OP_MUL: { -+ arith_op(luai_nummul, TM_MUL); -+ continue; -+ } -+ case OP_DIV: { -+ arith_op(luai_numdiv, TM_DIV); -+ continue; -+ } -+ case OP_MOD: { -+ arith_op(luai_nummod, TM_MOD); -+ continue; -+ } -+ case OP_POW: { -+ arith_op(luai_numpow, TM_POW); -+ continue; -+ } -+ case OP_UNM: { -+ TValue *rb = RB(i); -+ if (ttisnumber(rb)) { -+ lua_Number nb = nvalue(rb); -+ setnvalue(ra, luai_numunm(nb)); -+ } -+ else { -+ Protect(Arith(L, ra, rb, rb, TM_UNM)); -+ } -+ continue; -+ } -+ case OP_NOT: { -+ int res = l_isfalse(RB(i)); /* next assignment may change this value */ -+ setbvalue(ra, res); -+ continue; -+ } -+ case OP_LEN: { -+ const TValue *rb = RB(i); -+ switch (ttype(rb)) { -+ case LUA_TTABLE: { -+ setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); -+ break; -+ } -+ case LUA_TSTRING: { -+ setnvalue(ra, cast_num(tsvalue(rb)->len)); -+ break; -+ } -+ default: { /* try metamethod */ -+ Protect( -+ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) -+ luaG_typeerror(L, rb, "get length of"); -+ ) -+ } -+ } -+ continue; -+ } -+ case OP_CONCAT: { -+ int b = GETARG_B(i); -+ int c = GETARG_C(i); -+ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); -+ setobjs2s(L, RA(i), base+b); -+ continue; -+ } -+ case OP_JMP: { -+ dojump(L, pc, GETARG_sBx(i)); -+ continue; -+ } -+ case OP_EQ: { -+ TValue *rb = RKB(i); -+ TValue *rc = RKC(i); -+ Protect( -+ if (equalobj(L, rb, rc) == GETARG_A(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ ) -+ pc++; -+ continue; -+ } -+ case OP_LT: { -+ Protect( -+ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ ) -+ pc++; -+ continue; -+ } -+ case OP_LE: { -+ Protect( -+ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ ) -+ pc++; -+ continue; -+ } -+ case OP_TEST: { -+ if (l_isfalse(ra) != GETARG_C(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ pc++; -+ continue; -+ } -+ case OP_TESTSET: { -+ TValue *rb = RB(i); -+ if (l_isfalse(rb) != GETARG_C(i)) { -+ setobjs2s(L, ra, rb); -+ dojump(L, pc, GETARG_sBx(*pc)); -+ } -+ pc++; -+ continue; -+ } -+ case OP_CALL: { -+ int b = GETARG_B(i); -+ int nresults = GETARG_C(i) - 1; -+ if (b != 0) L->top = ra+b; /* else previous instruction set top */ -+ L->savedpc = pc; -+ switch (luaD_precall(L, ra, nresults)) { -+ case PCRLUA: { -+ nexeccalls++; -+ goto reentry; /* restart luaV_execute over new Lua function */ -+ } -+ case PCRC: { -+ /* it was a C function (`precall' called it); adjust results */ -+ if (nresults >= 0) L->top = L->ci->top; -+ base = L->base; -+ continue; -+ } -+ default: { -+ return; /* yield */ -+ } -+ } -+ } -+ case OP_TAILCALL: { -+ int b = GETARG_B(i); -+ if (b != 0) L->top = ra+b; /* else previous instruction set top */ -+ L->savedpc = pc; -+ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); -+ switch (luaD_precall(L, ra, LUA_MULTRET)) { -+ case PCRLUA: { -+ /* tail call: put new frame in place of previous one */ -+ CallInfo *ci = L->ci - 1; /* previous frame */ -+ int aux; -+ StkId func = ci->func; -+ StkId pfunc = (ci+1)->func; /* previous function index */ -+ if (L->openupval) luaF_close(L, ci->base); -+ L->base = ci->base = ci->func + ((ci+1)->base - pfunc); -+ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ -+ setobjs2s(L, func+aux, pfunc+aux); -+ ci->top = L->top = func+aux; /* correct top */ -+ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); -+ ci->savedpc = L->savedpc; -+ ci->tailcalls++; /* one more call lost */ -+ L->ci--; /* remove new frame */ -+ goto reentry; -+ } -+ case PCRC: { /* it was a C function (`precall' called it) */ -+ base = L->base; -+ continue; -+ } -+ default: { -+ return; /* yield */ -+ } -+ } -+ } -+ case OP_RETURN: { -+ int b = GETARG_B(i); -+ if (b != 0) L->top = ra+b-1; -+ if (L->openupval) luaF_close(L, base); -+ L->savedpc = pc; -+ b = luaD_poscall(L, ra); -+ if (--nexeccalls == 0) /* was previous function running `here'? */ -+ return; /* no: return */ -+ else { /* yes: continue its execution */ -+ if (b) L->top = L->ci->top; -+ lua_assert(isLua(L->ci)); -+ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); -+ goto reentry; -+ } -+ } -+ case OP_FORLOOP: { -+ lua_Number step = nvalue(ra+2); -+ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ -+ lua_Number limit = nvalue(ra+1); -+ if (luai_numlt(0, step) ? luai_numle(idx, limit) -+ : luai_numle(limit, idx)) { -+ dojump(L, pc, GETARG_sBx(i)); /* jump back */ -+ setnvalue(ra, idx); /* update internal index... */ -+ setnvalue(ra+3, idx); /* ...and external index */ -+ } -+ continue; -+ } -+ case OP_FORPREP: { -+ const TValue *init = ra; -+ const TValue *plimit = ra+1; -+ const TValue *pstep = ra+2; -+ L->savedpc = pc; /* next steps may throw errors */ -+ if (!tonumber(init, ra)) -+ luaG_runerror(L, LUA_QL("for") " initial value must be a number"); -+ else if (!tonumber(plimit, ra+1)) -+ luaG_runerror(L, LUA_QL("for") " limit must be a number"); -+ else if (!tonumber(pstep, ra+2)) -+ luaG_runerror(L, LUA_QL("for") " step must be a number"); -+ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); -+ dojump(L, pc, GETARG_sBx(i)); -+ continue; -+ } -+ case OP_TFORLOOP: { -+ StkId cb = ra + 3; /* call base */ -+ setobjs2s(L, cb+2, ra+2); -+ setobjs2s(L, cb+1, ra+1); -+ setobjs2s(L, cb, ra); -+ L->top = cb+3; /* func. + 2 args (state and index) */ -+ Protect(luaD_call(L, cb, GETARG_C(i))); -+ L->top = L->ci->top; -+ cb = RA(i) + 3; /* previous call may change the stack */ -+ if (!ttisnil(cb)) { /* continue loop? */ -+ setobjs2s(L, cb-1, cb); /* save control variable */ -+ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ -+ } -+ pc++; -+ continue; -+ } -+ case OP_SETLIST: { -+ int n = GETARG_B(i); -+ int c = GETARG_C(i); -+ int last; -+ Table *h; -+ if (n == 0) { -+ n = cast_int(L->top - ra) - 1; -+ L->top = L->ci->top; -+ } -+ if (c == 0) c = cast_int(*pc++); -+ runtime_check(L, ttistable(ra)); -+ h = hvalue(ra); -+ last = ((c-1)*LFIELDS_PER_FLUSH) + n; -+ if (last > h->sizearray) /* needs more space? */ -+ luaH_resizearray(L, h, last); /* pre-alloc it at once */ -+ for (; n > 0; n--) { -+ TValue *val = ra+n; -+ setobj2t(L, luaH_setnum(L, h, last--), val); -+ luaC_barriert(L, h, val); -+ } -+ continue; -+ } -+ case OP_CLOSE: { -+ luaF_close(L, ra); -+ continue; -+ } -+ case OP_CLOSURE: { -+ Proto *p; -+ Closure *ncl; -+ int nup, j; -+ p = cl->p->p[GETARG_Bx(i)]; -+ nup = p->nups; -+ ncl = luaF_newLclosure(L, nup, cl->env); -+ ncl->l.p = p; -+ for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; -+ else { -+ lua_assert(GET_OPCODE(*pc) == OP_MOVE); -+ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); -+ } -+ } -+ setclvalue(L, ra, ncl); -+ Protect(luaC_checkGC(L)); -+ continue; -+ } -+ case OP_VARARG: { -+ int b = GETARG_B(i) - 1; -+ int j; -+ CallInfo *ci = L->ci; -+ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; -+ if (b == LUA_MULTRET) { -+ Protect(luaD_checkstack(L, n)); -+ ra = RA(i); /* previous call may change the stack */ -+ b = n; -+ L->top = ra + n; -+ } -+ for (j = 0; j < b; j++) { -+ if (j < n) { -+ setobjs2s(L, ra + j, ci->base - n + j); -+ } -+ else { -+ setnilvalue(ra + j); -+ } -+ } -+ continue; -+ } -+ } -+ } -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lvm.h -@@ -0,0 +1,36 @@ -+/* -+** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua virtual machine -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lvm_h -+#define lvm_h -+ -+ -+#include "ldo.h" -+#include "lobject.h" -+#include "ltm.h" -+ -+ -+#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) -+ -+#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ -+ (((o) = luaV_tonumber(o,n)) != NULL)) -+ -+#define equalobj(L,o1,o2) \ -+ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) -+ -+ -+LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -+LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); -+LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); -+LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); -+LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, -+ StkId val); -+LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, -+ StkId val); -+LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); -+LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lzio.c -@@ -0,0 +1,81 @@ -+/* -+** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -+** a generic input stream interface -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lzio_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "llimits.h" -+#include "lmem.h" -+#include "lstate.h" -+#include "lzio.h" -+ -+ -+int luaZ_fill (ZIO *z) { -+ size_t size; -+ lua_State *L = z->L; -+ const char *buff; -+ lua_unlock(L); -+ buff = z->reader(L, z->data, &size); -+ lua_lock(L); -+ if (buff == NULL || size == 0) return EOZ; -+ z->n = size - 1; -+ z->p = buff; -+ return char2int(*(z->p++)); -+} -+ -+ -+int luaZ_lookahead (ZIO *z) { -+ if (z->n == 0) { -+ if (luaZ_fill(z) == EOZ) -+ return EOZ; -+ else { -+ z->n++; /* luaZ_fill removed first byte; put back it */ -+ z->p--; -+ } -+ } -+ return char2int(*z->p); -+} -+ -+ -+void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { -+ z->L = L; -+ z->reader = reader; -+ z->data = data; -+ z->n = 0; -+ z->p = NULL; -+} -+ -+ -+/* --------------------------------------------------------------- read --- */ -+size_t luaZ_read (ZIO *z, void *b, size_t n) { -+ while (n) { -+ size_t m; -+ if (luaZ_lookahead(z) == EOZ) -+ return n; /* return number of missing bytes */ -+ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ -+ memcpy(b, z->p, m); -+ z->n -= m; -+ z->p += m; -+ b = (char *)b + m; -+ n -= m; -+ } -+ return 0; -+} -+ -+/* ------------------------------------------------------------------------ */ -+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { -+ if (n > buff->buffsize) { -+ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; -+ luaZ_resizebuffer(L, buff, n); -+ } -+ return buff->buffer; -+} -+ -+ ---- /dev/null -+++ b/extensions/LUA/lua/lzio.h -@@ -0,0 +1,67 @@ -+/* -+** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Buffered streams -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lzio_h -+#define lzio_h -+ -+#include "lua.h" -+ -+#include "lmem.h" -+ -+ -+#define EOZ (-1) /* end of stream */ -+ -+typedef struct Zio ZIO; -+ -+#define char2int(c) cast(int, cast(unsigned char, (c))) -+ -+#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) -+ -+typedef struct Mbuffer { -+ char *buffer; -+ size_t n; -+ size_t buffsize; -+} Mbuffer; -+ -+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) -+ -+#define luaZ_buffer(buff) ((buff)->buffer) -+#define luaZ_sizebuffer(buff) ((buff)->buffsize) -+#define luaZ_bufflen(buff) ((buff)->n) -+ -+#define luaZ_resetbuffer(buff) ((buff)->n = 0) -+ -+ -+#define luaZ_resizebuffer(L, buff, size) \ -+ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ -+ (buff)->buffsize = size) -+ -+#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) -+ -+ -+LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); -+LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, -+ void *data); -+LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ -+LUAI_FUNC int luaZ_lookahead (ZIO *z); -+ -+ -+ -+/* --------- Private Part ------------------ */ -+ -+struct Zio { -+ size_t n; /* bytes still unread */ -+ const char *p; /* current position in buffer */ -+ lua_Reader reader; -+ void* data; /* additional data */ -+ lua_State *L; /* Lua state (for reader) */ -+}; -+ -+ -+LUAI_FUNC int luaZ_fill (ZIO *z); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/Makefile -@@ -0,0 +1,389 @@ -+# Makefile.in generated by automake 1.11.1 from Makefile.am. -+# extensions/LUA/Makefile. Generated from Makefile.in by configure. -+ -+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -+# Inc. -+# This Makefile.in is free software; the Free Software Foundation -+# gives unlimited permission to copy and/or distribute it, -+# with or without modifications, as long as this notice is preserved. -+ -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -+# PARTICULAR PURPOSE. -+ -+ -+ -+# -*- Makefile -*- -+# AUTOMAKE -+ -+pkgdatadir = $(datadir)/xtables-addons -+pkgincludedir = $(includedir)/xtables-addons -+pkglibdir = $(libdir)/xtables-addons -+pkglibexecdir = $(libexecdir)/xtables-addons -+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -+install_sh_DATA = $(install_sh) -c -m 644 -+install_sh_PROGRAM = $(install_sh) -c -+install_sh_SCRIPT = $(install_sh) -c -+INSTALL_HEADER = $(INSTALL_DATA) -+transform = $(program_transform_name) -+NORMAL_INSTALL = : -+PRE_INSTALL = : -+POST_INSTALL = : -+NORMAL_UNINSTALL = : -+PRE_UNINSTALL = : -+POST_UNINSTALL = : -+build_triplet = i686-pc-linux-gnu -+host_triplet = i686-pc-linux-gnu -+DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ -+ $(srcdir)/Makefile.in -+subdir = extensions/LUA -+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ -+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ -+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ -+ $(top_srcdir)/configure.ac -+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ -+ $(ACLOCAL_M4) -+mkinstalldirs = $(install_sh) -d -+CONFIG_HEADER = $(top_builddir)/config.h -+CONFIG_CLEAN_FILES = -+CONFIG_CLEAN_VPATH_FILES = -+SOURCES = -+DIST_SOURCES = -+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -+ACLOCAL = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run aclocal-1.11 -+AMTAR = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run tar -+AR = ar -+AUTOCONF = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoconf -+AUTOHEADER = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoheader -+AUTOMAKE = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run automake-1.11 -+AWK = mawk -+CC = gcc -+CCDEPMODE = depmode=gcc3 -+CFLAGS = -g -O2 -+CPP = gcc -E -+CPPFLAGS = -+CYGPATH_W = echo -+DEFS = -DHAVE_CONFIG_H -+DEPDIR = .deps -+DSYMUTIL = -+DUMPBIN = -+ECHO_C = -+ECHO_N = -n -+ECHO_T = -+EGREP = /bin/grep -E -+EXEEXT = -+FGREP = /bin/grep -F -+GREP = /bin/grep -+INSTALL = /usr/bin/install -c -+INSTALL_DATA = ${INSTALL} -m 644 -+INSTALL_PROGRAM = ${INSTALL} -+INSTALL_SCRIPT = ${INSTALL} -+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s -+LD = /usr/bin/ld -+LDFLAGS = -+LIBOBJS = -+LIBS = -+LIBTOOL = $(SHELL) $(top_builddir)/libtool -+LIPO = -+LN_S = ln -s -+LTLIBOBJS = -+MAKEINFO = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run makeinfo -+MKDIR_P = /bin/mkdir -p -+NM = /usr/bin/nm -B -+NMEDIT = -+OBJDUMP = objdump -+OBJEXT = o -+OTOOL = -+OTOOL64 = -+PACKAGE = xtables-addons -+PACKAGE_BUGREPORT = -+PACKAGE_NAME = xtables-addons -+PACKAGE_STRING = xtables-addons 1.21 -+PACKAGE_TARNAME = xtables-addons -+PACKAGE_URL = -+PACKAGE_VERSION = 1.21 -+PATH_SEPARATOR = : -+PKG_CONFIG = /usr/bin/pkg-config -+RANLIB = ranlib -+SED = /bin/sed -+SET_MAKE = -+SHELL = /bin/bash -+STRIP = strip -+VERSION = 1.21 -+abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA -+abs_srcdir = /home/andre/Dropbox/xtables-addons/extensions/LUA -+abs_top_builddir = /home/andre/Dropbox/xtables-addons -+abs_top_srcdir = /home/andre/Dropbox/xtables-addons -+ac_ct_CC = gcc -+ac_ct_DUMPBIN = -+am__include = include -+am__leading_dot = . -+am__quote = -+am__tar = ${AMTAR} chof - "$$tardir" -+am__untar = ${AMTAR} xf - -+bindir = ${exec_prefix}/bin -+build = i686-pc-linux-gnu -+build_alias = -+build_cpu = i686 -+build_os = linux-gnu -+build_vendor = pc -+builddir = . -+datadir = ${datarootdir} -+datarootdir = ${prefix}/share -+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} -+dvidir = ${docdir} -+exec_prefix = ${prefix} -+host = i686-pc-linux-gnu -+host_alias = -+host_cpu = i686 -+host_os = linux-gnu -+host_vendor = pc -+htmldir = ${docdir} -+includedir = ${prefix}/include -+infodir = ${datarootdir}/info -+install_sh = ${SHELL} /home/andre/Dropbox/xtables-addons/install-sh -+kbuilddir = /lib/modules/2.6.33-020633-generic/build -+kinclude_CFLAGS = -I /lib/modules/2.6.33-020633-generic/build/include -+ksourcedir = -+libdir = ${exec_prefix}/lib -+libexecdir = ${exec_prefix}/libexec -+libxtables_CFLAGS = -+libxtables_LIBS = -L/lib -lxtables -+localedir = ${datarootdir}/locale -+localstatedir = ${prefix}/var -+lt_ECHO = echo -+mandir = ${datarootdir}/man -+mkdir_p = /bin/mkdir -p -+oldincludedir = /usr/include -+pdfdir = ${docdir} -+prefix = /usr/local -+program_transform_name = s,x,x, -+psdir = ${docdir} -+regular_CFLAGS = -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Winline -pipe -DXTABLES_LIBDIR=\"${xtlibdir}\" -+sbindir = ${exec_prefix}/sbin -+sharedstatedir = ${prefix}/com -+srcdir = . -+sysconfdir = ${prefix}/etc -+target_alias = -+top_build_prefix = ../../ -+top_builddir = ../.. -+top_srcdir = ../.. -+xtlibdir = ${libexecdir}/xtables -+XA_SRCDIR = ${srcdir} -+XA_TOPSRCDIR = ${top_srcdir} -+XA_ABSTOPSRCDIR = ${abs_top_srcdir} -+_mcall = -f ${top_builddir}/Makefile.iptrules -+all: all-am -+ -+.SUFFIXES: -+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) -+ @for dep in $?; do \ -+ case '$(am__configure_deps)' in \ -+ *$$dep*) \ -+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ -+ && { if test -f $@; then exit 0; else break; fi; }; \ -+ exit 1;; \ -+ esac; \ -+ done; \ -+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ -+ $(am__cd) $(top_srcdir) && \ -+ $(AUTOMAKE) --foreign extensions/LUA/Makefile -+.PRECIOUS: Makefile -+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status -+ @case '$?' in \ -+ *config.status*) \ -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ -+ *) \ -+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ -+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ -+ esac; -+ -+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+ -+$(top_srcdir)/configure: $(am__configure_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(ACLOCAL_M4): $(am__aclocal_m4_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(am__aclocal_m4_deps): -+ -+mostlyclean-libtool: -+ -rm -f *.lo -+ -+clean-libtool: -+ -rm -rf .libs _libs -+tags: TAGS -+TAGS: -+ -+ctags: CTAGS -+CTAGS: -+ -+ -+distdir: $(DISTFILES) -+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ list='$(DISTFILES)'; \ -+ dist_files=`for file in $$list; do echo $$file; done | \ -+ sed -e "s|^$$srcdirstrip/||;t" \ -+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ -+ case $$dist_files in \ -+ */*) $(MKDIR_P) `echo "$$dist_files" | \ -+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ -+ sort -u` ;; \ -+ esac; \ -+ for file in $$dist_files; do \ -+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ -+ if test -d $$d/$$file; then \ -+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ -+ if test -d "$(distdir)/$$file"; then \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ -+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ -+ else \ -+ test -f "$(distdir)/$$file" \ -+ || cp -p $$d/$$file "$(distdir)/$$file" \ -+ || exit 1; \ -+ fi; \ -+ done -+check-am: all-am -+check: check-am -+all-am: Makefile all-local -+installdirs: -+install: install-am -+install-exec: install-exec-am -+install-data: install-data-am -+uninstall: uninstall-am -+ -+install-am: all-am -+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -+ -+installcheck: installcheck-am -+install-strip: -+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ -+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ -+ `test -z '$(STRIP)' || \ -+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -+mostlyclean-generic: -+ -+clean-generic: -+ -+distclean-generic: -+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -+ -+maintainer-clean-generic: -+ @echo "This command is intended for maintainers to use" -+ @echo "it deletes files that may require special tools to rebuild." -+clean: clean-am -+ -+clean-am: clean-generic clean-libtool clean-local mostlyclean-am -+ -+distclean: distclean-am -+ -rm -f Makefile -+distclean-am: clean-am distclean-generic -+ -+dvi: dvi-am -+ -+dvi-am: -+ -+html: html-am -+ -+html-am: -+ -+info: info-am -+ -+info-am: -+ -+install-data-am: -+ -+install-dvi: install-dvi-am -+ -+install-dvi-am: -+ -+install-exec-am: install-exec-local -+ -+install-html: install-html-am -+ -+install-html-am: -+ -+install-info: install-info-am -+ -+install-info-am: -+ -+install-man: -+ -+install-pdf: install-pdf-am -+ -+install-pdf-am: -+ -+install-ps: install-ps-am -+ -+install-ps-am: -+ -+installcheck-am: -+ -+maintainer-clean: maintainer-clean-am -+ -rm -f Makefile -+maintainer-clean-am: distclean-am maintainer-clean-generic -+ -+mostlyclean: mostlyclean-am -+ -+mostlyclean-am: mostlyclean-generic mostlyclean-libtool -+ -+pdf: pdf-am -+ -+pdf-am: -+ -+ps: ps-am -+ -+ps-am: -+ -+uninstall-am: -+ -+.MAKE: install-am install-strip -+ -+.PHONY: all all-am all-local check check-am clean clean-generic \ -+ clean-libtool clean-local distclean distclean-generic \ -+ distclean-libtool distdir dvi dvi-am html html-am info info-am \ -+ install install-am install-data install-data-am install-dvi \ -+ install-dvi-am install-exec install-exec-am install-exec-local \ -+ install-html install-html-am install-info install-info-am \ -+ install-man install-pdf install-pdf-am install-ps \ -+ install-ps-am install-strip installcheck installcheck-am \ -+ installdirs maintainer-clean maintainer-clean-generic \ -+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ -+ ps ps-am uninstall uninstall-am -+ -+export XA_SRCDIR -+export XA_TOPSRCDIR -+export XA_ABSTOPSRCDIR -+ -+all-local: user-all-local -+ -+install-exec-local: user-install-local -+ -+clean-local: user-clean-local -+ -+user-all-local: -+ ${MAKE} ${_mcall} all; -+ -+# Have no user-install-data-local ATM -+user-install-local: user-install-exec-local -+ -+user-install-exec-local: -+ ${MAKE} ${_mcall} install; -+ -+user-clean-local: -+ ${MAKE} ${_mcall} clean; -+ -+# Tell versions [3.59,3.63) of GNU make to not export all variables. -+# Otherwise a system limit (for SysV at least) may be exceeded. -+.NOEXPORT: -+ ---- /dev/null -+++ b/extensions/LUA/Makefile.am -@@ -0,0 +1 @@ -+include ../../Makefile.extra ---- /dev/null -+++ b/extensions/LUA/Makefile.in -@@ -0,0 +1,389 @@ -+# Makefile.in generated by automake 1.11.1 from Makefile.am. -+# @configure_input@ -+ -+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -+# Inc. -+# This Makefile.in is free software; the Free Software Foundation -+# gives unlimited permission to copy and/or distribute it, -+# with or without modifications, as long as this notice is preserved. -+ -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -+# PARTICULAR PURPOSE. -+ -+@SET_MAKE@ -+ -+# -*- Makefile -*- -+# AUTOMAKE -+VPATH = @srcdir@ -+pkgdatadir = $(datadir)/@PACKAGE@ -+pkgincludedir = $(includedir)/@PACKAGE@ -+pkglibdir = $(libdir)/@PACKAGE@ -+pkglibexecdir = $(libexecdir)/@PACKAGE@ -+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -+install_sh_DATA = $(install_sh) -c -m 644 -+install_sh_PROGRAM = $(install_sh) -c -+install_sh_SCRIPT = $(install_sh) -c -+INSTALL_HEADER = $(INSTALL_DATA) -+transform = $(program_transform_name) -+NORMAL_INSTALL = : -+PRE_INSTALL = : -+POST_INSTALL = : -+NORMAL_UNINSTALL = : -+PRE_UNINSTALL = : -+POST_UNINSTALL = : -+build_triplet = @build@ -+host_triplet = @host@ -+DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ -+ $(srcdir)/Makefile.in -+subdir = extensions/LUA -+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ -+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ -+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ -+ $(top_srcdir)/configure.ac -+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ -+ $(ACLOCAL_M4) -+mkinstalldirs = $(install_sh) -d -+CONFIG_HEADER = $(top_builddir)/config.h -+CONFIG_CLEAN_FILES = -+CONFIG_CLEAN_VPATH_FILES = -+SOURCES = -+DIST_SOURCES = -+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -+ACLOCAL = @ACLOCAL@ -+AMTAR = @AMTAR@ -+AR = @AR@ -+AUTOCONF = @AUTOCONF@ -+AUTOHEADER = @AUTOHEADER@ -+AUTOMAKE = @AUTOMAKE@ -+AWK = @AWK@ -+CC = @CC@ -+CCDEPMODE = @CCDEPMODE@ -+CFLAGS = @CFLAGS@ -+CPP = @CPP@ -+CPPFLAGS = @CPPFLAGS@ -+CYGPATH_W = @CYGPATH_W@ -+DEFS = @DEFS@ -+DEPDIR = @DEPDIR@ -+DSYMUTIL = @DSYMUTIL@ -+DUMPBIN = @DUMPBIN@ -+ECHO_C = @ECHO_C@ -+ECHO_N = @ECHO_N@ -+ECHO_T = @ECHO_T@ -+EGREP = @EGREP@ -+EXEEXT = @EXEEXT@ -+FGREP = @FGREP@ -+GREP = @GREP@ -+INSTALL = @INSTALL@ -+INSTALL_DATA = @INSTALL_DATA@ -+INSTALL_PROGRAM = @INSTALL_PROGRAM@ -+INSTALL_SCRIPT = @INSTALL_SCRIPT@ -+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -+LD = @LD@ -+LDFLAGS = @LDFLAGS@ -+LIBOBJS = @LIBOBJS@ -+LIBS = @LIBS@ -+LIBTOOL = @LIBTOOL@ -+LIPO = @LIPO@ -+LN_S = @LN_S@ -+LTLIBOBJS = @LTLIBOBJS@ -+MAKEINFO = @MAKEINFO@ -+MKDIR_P = @MKDIR_P@ -+NM = @NM@ -+NMEDIT = @NMEDIT@ -+OBJDUMP = @OBJDUMP@ -+OBJEXT = @OBJEXT@ -+OTOOL = @OTOOL@ -+OTOOL64 = @OTOOL64@ -+PACKAGE = @PACKAGE@ -+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -+PACKAGE_NAME = @PACKAGE_NAME@ -+PACKAGE_STRING = @PACKAGE_STRING@ -+PACKAGE_TARNAME = @PACKAGE_TARNAME@ -+PACKAGE_URL = @PACKAGE_URL@ -+PACKAGE_VERSION = @PACKAGE_VERSION@ -+PATH_SEPARATOR = @PATH_SEPARATOR@ -+PKG_CONFIG = @PKG_CONFIG@ -+RANLIB = @RANLIB@ -+SED = @SED@ -+SET_MAKE = @SET_MAKE@ -+SHELL = @SHELL@ -+STRIP = @STRIP@ -+VERSION = @VERSION@ -+abs_builddir = @abs_builddir@ -+abs_srcdir = @abs_srcdir@ -+abs_top_builddir = @abs_top_builddir@ -+abs_top_srcdir = @abs_top_srcdir@ -+ac_ct_CC = @ac_ct_CC@ -+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -+am__include = @am__include@ -+am__leading_dot = @am__leading_dot@ -+am__quote = @am__quote@ -+am__tar = @am__tar@ -+am__untar = @am__untar@ -+bindir = @bindir@ -+build = @build@ -+build_alias = @build_alias@ -+build_cpu = @build_cpu@ -+build_os = @build_os@ -+build_vendor = @build_vendor@ -+builddir = @builddir@ -+datadir = @datadir@ -+datarootdir = @datarootdir@ -+docdir = @docdir@ -+dvidir = @dvidir@ -+exec_prefix = @exec_prefix@ -+host = @host@ -+host_alias = @host_alias@ -+host_cpu = @host_cpu@ -+host_os = @host_os@ -+host_vendor = @host_vendor@ -+htmldir = @htmldir@ -+includedir = @includedir@ -+infodir = @infodir@ -+install_sh = @install_sh@ -+kbuilddir = @kbuilddir@ -+kinclude_CFLAGS = @kinclude_CFLAGS@ -+ksourcedir = @ksourcedir@ -+libdir = @libdir@ -+libexecdir = @libexecdir@ -+libxtables_CFLAGS = @libxtables_CFLAGS@ -+libxtables_LIBS = @libxtables_LIBS@ -+localedir = @localedir@ -+localstatedir = @localstatedir@ -+lt_ECHO = @lt_ECHO@ -+mandir = @mandir@ -+mkdir_p = @mkdir_p@ -+oldincludedir = @oldincludedir@ -+pdfdir = @pdfdir@ -+prefix = @prefix@ -+program_transform_name = @program_transform_name@ -+psdir = @psdir@ -+regular_CFLAGS = @regular_CFLAGS@ -+sbindir = @sbindir@ -+sharedstatedir = @sharedstatedir@ -+srcdir = @srcdir@ -+sysconfdir = @sysconfdir@ -+target_alias = @target_alias@ -+top_build_prefix = @top_build_prefix@ -+top_builddir = @top_builddir@ -+top_srcdir = @top_srcdir@ -+xtlibdir = @xtlibdir@ -+XA_SRCDIR = ${srcdir} -+XA_TOPSRCDIR = ${top_srcdir} -+XA_ABSTOPSRCDIR = ${abs_top_srcdir} -+_mcall = -f ${top_builddir}/Makefile.iptrules -+all: all-am -+ -+.SUFFIXES: -+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) -+ @for dep in $?; do \ -+ case '$(am__configure_deps)' in \ -+ *$$dep*) \ -+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ -+ && { if test -f $@; then exit 0; else break; fi; }; \ -+ exit 1;; \ -+ esac; \ -+ done; \ -+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ -+ $(am__cd) $(top_srcdir) && \ -+ $(AUTOMAKE) --foreign extensions/LUA/Makefile -+.PRECIOUS: Makefile -+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status -+ @case '$?' in \ -+ *config.status*) \ -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ -+ *) \ -+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ -+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ -+ esac; -+ -+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+ -+$(top_srcdir)/configure: $(am__configure_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(ACLOCAL_M4): $(am__aclocal_m4_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(am__aclocal_m4_deps): -+ -+mostlyclean-libtool: -+ -rm -f *.lo -+ -+clean-libtool: -+ -rm -rf .libs _libs -+tags: TAGS -+TAGS: -+ -+ctags: CTAGS -+CTAGS: -+ -+ -+distdir: $(DISTFILES) -+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ list='$(DISTFILES)'; \ -+ dist_files=`for file in $$list; do echo $$file; done | \ -+ sed -e "s|^$$srcdirstrip/||;t" \ -+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ -+ case $$dist_files in \ -+ */*) $(MKDIR_P) `echo "$$dist_files" | \ -+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ -+ sort -u` ;; \ -+ esac; \ -+ for file in $$dist_files; do \ -+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ -+ if test -d $$d/$$file; then \ -+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ -+ if test -d "$(distdir)/$$file"; then \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ -+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ -+ else \ -+ test -f "$(distdir)/$$file" \ -+ || cp -p $$d/$$file "$(distdir)/$$file" \ -+ || exit 1; \ -+ fi; \ -+ done -+check-am: all-am -+check: check-am -+all-am: Makefile all-local -+installdirs: -+install: install-am -+install-exec: install-exec-am -+install-data: install-data-am -+uninstall: uninstall-am -+ -+install-am: all-am -+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -+ -+installcheck: installcheck-am -+install-strip: -+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ -+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ -+ `test -z '$(STRIP)' || \ -+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -+mostlyclean-generic: -+ -+clean-generic: -+ -+distclean-generic: -+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -+ -+maintainer-clean-generic: -+ @echo "This command is intended for maintainers to use" -+ @echo "it deletes files that may require special tools to rebuild." -+clean: clean-am -+ -+clean-am: clean-generic clean-libtool clean-local mostlyclean-am -+ -+distclean: distclean-am -+ -rm -f Makefile -+distclean-am: clean-am distclean-generic -+ -+dvi: dvi-am -+ -+dvi-am: -+ -+html: html-am -+ -+html-am: -+ -+info: info-am -+ -+info-am: -+ -+install-data-am: -+ -+install-dvi: install-dvi-am -+ -+install-dvi-am: -+ -+install-exec-am: install-exec-local -+ -+install-html: install-html-am -+ -+install-html-am: -+ -+install-info: install-info-am -+ -+install-info-am: -+ -+install-man: -+ -+install-pdf: install-pdf-am -+ -+install-pdf-am: -+ -+install-ps: install-ps-am -+ -+install-ps-am: -+ -+installcheck-am: -+ -+maintainer-clean: maintainer-clean-am -+ -rm -f Makefile -+maintainer-clean-am: distclean-am maintainer-clean-generic -+ -+mostlyclean: mostlyclean-am -+ -+mostlyclean-am: mostlyclean-generic mostlyclean-libtool -+ -+pdf: pdf-am -+ -+pdf-am: -+ -+ps: ps-am -+ -+ps-am: -+ -+uninstall-am: -+ -+.MAKE: install-am install-strip -+ -+.PHONY: all all-am all-local check check-am clean clean-generic \ -+ clean-libtool clean-local distclean distclean-generic \ -+ distclean-libtool distdir dvi dvi-am html html-am info info-am \ -+ install install-am install-data install-data-am install-dvi \ -+ install-dvi-am install-exec install-exec-am install-exec-local \ -+ install-html install-html-am install-info install-info-am \ -+ install-man install-pdf install-pdf-am install-ps \ -+ install-ps-am install-strip installcheck installcheck-am \ -+ installdirs maintainer-clean maintainer-clean-generic \ -+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ -+ ps ps-am uninstall uninstall-am -+ -+export XA_SRCDIR -+export XA_TOPSRCDIR -+export XA_ABSTOPSRCDIR -+ -+all-local: user-all-local -+ -+install-exec-local: user-install-local -+ -+clean-local: user-clean-local -+ -+user-all-local: -+ ${MAKE} ${_mcall} all; -+ -+# Have no user-install-data-local ATM -+user-install-local: user-install-exec-local -+ -+user-install-exec-local: -+ ${MAKE} ${_mcall} install; -+ -+user-clean-local: -+ ${MAKE} ${_mcall} clean; -+ -+# Tell versions [3.59,3.63) of GNU make to not export all variables. -+# Otherwise a system limit (for SysV at least) may be exceeded. -+.NOEXPORT: -+ ---- /dev/null -+++ b/extensions/LUA/Mbuild -@@ -0,0 +1,3 @@ -+# -*- Makefile -*- -+ -+obj-${build_LUA} += libxt_LUA.so ---- /dev/null -+++ b/extensions/LUA/nf_lua.c -@@ -0,0 +1,64 @@ -+#if defined(__KERNEL__) -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#endif -+ -+#include "lua.h" -+#include "lobject.h" /*sizeof(udata) */ -+#include "lauxlib.h" -+#include "controller.h" -+ -+#if defined(__KERNEL__) /* reachs until luaopen_nflib */ -+ -+ -+static int32_t nf_get_random(lua_State *L) -+{ -+ uint32_t rand = 0; -+ -+ get_random_bytes(&rand, sizeof(uint32_t )); -+ lua_pushnumber(L, rand); -+ return 1; -+} -+ -+static int32_t nf_get_time(lua_State *L) -+{ -+ lua_pushnumber(L, jiffies_to_msecs(jiffies_64)); -+ return 1; -+} -+ -+static const struct luaL_Reg nf_lua_lib_f [] = { -+ { "get_random", nf_get_random }, -+ { "get_time", nf_get_time }, -+ { NULL, NULL } -+}; -+ -+void luaopen_nflib(lua_State *L) -+{ -+ int32_t top; -+ -+ luaL_register(L, NETFILTER_LIB, nf_lua_lib_f); -+ lua_pop(L, 1); -+ -+ /* registering verdicts inside the _G */ -+ lua_getglobal(L, "_G"); -+ top = lua_gettop(L); -+ -+ lua_pushinteger(L, XT_CONTINUE); -+ lua_setfield(L, top, "XT_CONTINUE"); /* continiue with next rule */ -+ -+ lua_pushinteger(L, NF_DROP); -+ lua_setfield(L, top, "NF_DROP"); /* stop traversal in the current table hook and drop packet */ -+ -+ lua_pushinteger(L, NF_ACCEPT); -+ lua_setfield(L, top, "NF_ACCEPT"); /* stop traversal in the current table hook and accept packet */ -+ -+ lua_pop(L, 1); /* pop _G */ -+} -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/prot_buf_dynamic.c -@@ -0,0 +1,486 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+ -+ -+ -+struct protocol_buf * dyn_prot_buf_array[MAX_NR_OF_DYN_PROT_BUFS] = { NULL }; -+ -+ -+/* LUA_API: the function 'field_dynamic_setter' acts as a wrapper around -+ * a given Lua field setter function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'set' -+ * member of the protocol_field. We call this function passing the actual -+ * segment as byte array and the set value. -+ * -+ * Paramters: -+ * 1. lua_packet_segment (implicit) -+ * 2. some lua value -+ * -+ * Upvalues: -+ * 1. pointer to the protocol buffer -+ * 2. field index -+ * -+ * Returns: -+ * 1. true or false if the 'set' was successful -+ */ -+int32_t field_dynamic_setter(lua_State *L) -+{ -+ size_t nbytes; -+ lua_packet_segment * array; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); -+ -+ /* the function name is piggybacked as a string */ -+ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].set); -+ if (!lua_isfunction(L, -1)) { -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ -+ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); -+ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); -+ array->length = seg->length; -+ array->start = seg->start + seg->offset; -+ array->changes = NULL; -+ -+ luaL_getmetatable(L, LUA_BYTE_ARRAY); -+ lua_setmetatable(L, -2); -+ lua_pushvalue(L, 2); /* push value to set */ -+ if (lua_pcall(L, 2, 1, 0) != 0) { -+ pr_debug("Error: %s \n", lua_tostring(L, -1)); -+ lua_pop(L, 1); -+ lua_pushboolean(L, 0); -+ } -+ return 1; -+} -+ -+/* LUA_API: the function 'field_dynamic_getter' acts as a wrapper around -+ * a given Lua field getter function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'get' -+ * member of the protocol_field. We call this function passing the actual -+ * segment as byte array. -+ * -+ * Paramters: -+ * 1. lua_packet_segment (implicit) -+ * -+ * Upvalues: -+ * 1. pointer to the protocol buffer -+ * 2. field index -+ * -+ * Returns: -+ * 1. true or false if the 'get' was successful -+ */ -+int32_t field_dynamic_getter(lua_State *L) -+{ -+ size_t nbytes; -+ lua_packet_segment * array; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); -+ -+ /* the function name is piggybacked as a string */ -+ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].get); -+ if (!lua_isfunction(L, -1)) { -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ -+ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); -+ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); -+ array->length = seg->length; -+ array->start = seg->start + seg->offset; -+ array->changes = NULL; -+ -+ luaL_getmetatable(L, LUA_BYTE_ARRAY); -+ lua_setmetatable(L, -2); -+ if (lua_pcall(L, 1, 1, 0) != 0) { -+ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); -+ lua_pop(L, 1); -+ lua_pushboolean(L, 0); -+ } -+ return 1; -+} -+ -+/* LUA_API: the function 'has_protocol_dynamic' acts as a wrapper around -+ * a given lua has_protocol function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'has_protocol' -+ * member of the protocol_buffer. We call this function passing the actual -+ * segment. -+ * -+ * Paramters: -+ * 1. lua_packet_segment -+ * 2. protocol type -+ * -+ * Returns: -+ * 1. true or false if the payload field contains the given protocol -+ */ -+int32_t has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t type) -+{ -+ lua_packet_segment *seg_new; -+ int32_t res = 0; -+ -+ /* the function name is piggybacked as a string */ -+ lua_getglobal(L, (char *)prot_buf->has_protocol); -+ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ seg_new->start = seg->start; -+ seg_new->offset = seg->offset; -+ seg_new->length = seg->length; -+ seg_new->changes = NULL; -+ luaL_getmetatable(L, prot_buf->name); -+ lua_setmetatable(L, -2); -+ lua_pushinteger(L, type); /* push the protocol type */ -+ if (lua_pcall(L, 2, 1, 0) != 0) { -+ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); -+ lua_pop(L, 1); -+ return 0; -+ } -+ res = lua_toboolean(L, -1); -+ lua_pop(L, 1); -+ -+ return res; -+} -+ -+/* LUA_API: the function 'get_field_changes_dynamic' acts as a wrapper around -+ * a given lua get_field_changes function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'get_field_changes' -+ * member of the protocol_buffer. We call this function passing the actual -+ * segment. The lua function must return two lua table containing the offset -+ * and length changes (in bits). -+ * -+ * Paramters: -+ * 1. lua_packet_segment -+ * -+ * Returns: -+ * 1. new allocated field_changes struct -+ */ -+struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) -+{ -+ lua_packet_segment *seg_new; -+ struct field_changes * changes; -+ int32_t nr_of_changes, i; -+ -+ lua_getglobal(L, (char *)prot_buf->get_field_changes); -+ -+ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ seg_new->start = seg->start; -+ seg_new->offset = seg->offset; -+ seg_new->length = seg->length; -+ seg_new->changes = NULL; -+ luaL_getmetatable(L, prot_buf->name); -+ lua_setmetatable(L, -2); -+ -+ if (lua_pcall(L, 1, 2, 0) != 0) -+ luaL_error(L, "inside get_field_changes_dynamic. %s\n", lua_tostring(L, -1)); -+ -+ /* the function call must return a table containing length changes */ -+ luaL_checktype(L, -1, LUA_TTABLE); -+ /* the function call must return a table containing offset changes */ -+ luaL_checktype(L, -2, LUA_TTABLE); -+ /* both tables have to be of same size */ -+ if (lua_objlen(L, -1) != lua_objlen(L, -2)) -+ luaL_error(L, "the provided tables are not of equal size"); -+ -+ nr_of_changes = lua_objlen(L, -1); -+ changes = get_allocated_field_changes(L, nr_of_changes); -+ -+ /* loop over the tables */ -+ for (i = 1; i < nr_of_changes; i++) { -+ lua_rawgeti(L, -1, i); /* push length value of field at index i */ -+ changes->field_length_changes[i - 1] = luaL_checkinteger(L, -1); -+ lua_pop(L, 1); /* pop offset value */ -+ -+ lua_rawgeti(L, -2, i); /* push offset value of field at index i */ -+ changes->field_offset_changes[i - 1] = luaL_checkinteger(L, -1); -+ lua_pop(L, 1); /* pop length value */ -+ } -+ -+ /* pop both tables */ -+ lua_pop(L, 2); -+ -+ return changes; -+} -+ -+/* C_INT: 'get_free_protocol_index' is only used internally. This function -+ * gets a free slot inside the array holding all the protocol buffers. -+ * There are several ways to get to this information. In this case I take -+ * the way over the reflected array SUPPORTED_PROTOCOL_TABLE inside the -+ * Lua state. Since this function is called at laodtime, we do not have -+ * to care about performance. -+ */ -+static int32_t get_free_protocol_index(lua_State *L) -+{ -+ int32_t protocol_index; -+ -+ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); -+ protocol_index = lua_objlen(L, -1) + 1; -+ lua_pop(L, 1); -+ return protocol_index; -+} -+ -+/* C_API: 'free_dynamic_prot_buf' frees the allocated memory of a given -+ * dynamic protocol buffer. this function is normally called inside a -+ * cleanup routine. Be aware, before running this function you must be -+ * sure that no references to the dynamic protocol buffers were available. -+ * It's recomended to close the Lua state before calling the function. */ -+void free_dynamic_prot_buf(struct protocol_buf * prot_buf) -+{ -+ struct protocol_field * field = prot_buf->protocol_fields; -+ -+ for (; field->name != NULL; field++) { -+ if (field->get) kfree(field->get); -+ if (field->set) kfree(field->set); -+ if (field->name) kfree((char *)field->name); -+ } -+ -+ if (prot_buf->payload_field) kfree(prot_buf->payload_field); -+ if (prot_buf->has_protocol) kfree(prot_buf->has_protocol); -+ -+ if (prot_buf->get_field_changes) kfree(prot_buf->get_field_changes); -+ kfree((char *)prot_buf->name); -+ kfree(prot_buf); -+ return; -+} -+ -+void cleanup_dynamic_prot_bufs(void) -+{ -+ int32_t i; -+ -+ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { -+ if (dyn_prot_buf_array[i]) { -+ free_dynamic_prot_buf(dyn_prot_buf_array[i]); -+ dyn_prot_buf_array[i] = NULL; -+ } -+ } -+ return; -+} -+ -+ -+/* C_INT: 'free_protocol_fields' is used internally as a helper function for -+ * 'register_dynamic_protbuf'. It is used when durin registration an error -+ * occurs and the afore allocated fields needed to be freed. */ -+static inline void free_protocol_fields(struct protocol_field * prot_fields, int32_t i) -+{ -+ struct protocol_field * f; -+ -+ while (i >= 0) { -+ f = &prot_fields[i]; -+ if (f->name) kfree((void *)f->name); -+ if (f->get) kfree((void *)f->get); -+ if (f->set) kfree((void *)f->set); -+ kfree((void *)f); -+ i--; -+ } -+} -+ -+/* LUA_API: 'register_dynamic_protbuf' is called from within the Lua script. -+ * it takes a Lua table representing the dynamic protocol buffer as parameter. -+ * e.g.: -+ * eth_prot_buf = { -+ * name = "packet_eth_dyn", -+ * payload_field = "data", -+ * protocol_fields = { -+ * {"dmac", 0, 48, nil, nil }, -+ * {"smac", 48, 48, nil, nil }, -+ * {"type", 96, 16, nil, nil }, -+ * {"data", 112, 0, nil, nil }, -+ * }, -+ * has_protocol = "eth_dyn_has_protocol", -+ * get_field_changes = "eth_dyn_get_field_changes" -+ * } -+ * register_dynamic_protbuf(eth_prot_buf) -+ * -+ * the table gets parsed and a new protocol_buf struct is allocated and -+ * initialized using 'register_protbuf', which is also used for the static -+ * protocol buffers. This enables an identical behavior like the static -+ * protocol buffers. The dynamic protocol buffers are not garbage collected, -+ * use 'free_dynamic_protbuf' to free them after closing the Lua state. -+ */ -+static int32_t register_dynamic_protbuf(lua_State *L) -+{ -+ struct protocol_buf *prot_buf; -+ struct protocol_field *field, sentinel = PROT_FIELD_SENTINEL; -+ int32_t nr_of_fields, i; -+ -+ prot_buf = (struct protocol_buf *)kmalloc(sizeof(struct protocol_buf), GFP_KERNEL); -+ prot_buf->is_dynamic = 1; -+ -+ /* check if parameter is a table */ -+ luaL_checktype(L, 1, LUA_TTABLE); -+ -+ /* initialize prot_buf.name */ -+ lua_getfield(L, 1, "name"); -+ prot_buf->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)prot_buf->name, luaL_checkstring(L, -1)); -+ lua_pop(L, 1); /* pop res from lua_getfield */ -+ -+ /* check if protocol buffer is already registered */ -+ lua_getglobal(L, prot_buf->name); -+ if (!lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop res from lua_getglobal */ -+ pr_debug("protocol_buf '%s' already registered.\n", prot_buf->name); -+ goto free_prot_buf; -+ } -+ lua_pop(L, 1); /* pop res from lua_getglobal */ -+ -+ /* initialize payload field */ -+ lua_getfield(L, 1, "payload_field"); -+ if (lua_isstring(L, -1)) { -+ prot_buf->payload_field = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy(prot_buf->payload_field, lua_tostring(L, -1)); -+ }else -+ prot_buf->payload_field = NULL; -+ lua_pop(L, 1); /* pop res from lua_getfield */ -+ -+ /* initialize protocol_fields field*/ -+ lua_getfield(L, 1, "protocol_fields"); -+ if (!lua_istable(L, -1)) { -+ pr_debug("invalid protocol_fields table.\n"); -+ goto err2; -+ -+ } -+ -+ nr_of_fields = lua_objlen(L, -1); -+ prot_buf->protocol_fields = (struct protocol_field *)kmalloc((nr_of_fields + 1) * sizeof(struct protocol_field), GFP_KERNEL); -+ -+ for (i = 1; i <= nr_of_fields; i++) { -+ field = &prot_buf->protocol_fields[i - 1]; -+ /* initialize protocol field */ -+ lua_rawgeti(L, -1, i); /* push field-table */ -+ if (!lua_istable(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field at %i.\n", i); -+ goto err; -+ } -+ -+ /* initialize protocol field name */ -+ lua_rawgeti(L, -1, 1); -+ if (!lua_isstring(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field name at %i.\n", i); -+ goto err; -+ } -+ -+ field->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char*)field->name, lua_tostring(L, -1)); -+ lua_pop(L, 1); /* pop field name */ -+ -+ /* initialize protocol field offset */ -+ lua_rawgeti(L, -1, 2); -+ if (!lua_isnumber(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field offset at %i.\n", i); -+ goto err; -+ } -+ field->offset = lua_tointeger(L, -1); -+ lua_pop(L, 1); /* pop field offset */ -+ -+ /* initialize protocol field length */ -+ lua_rawgeti(L, -1, 3); -+ if (!lua_isnumber(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field length at %i.\n", i); -+ goto err; -+ } -+ field->length = lua_tointeger(L, -1); -+ lua_pop(L, 1); /* pop field length */ -+ -+ /* initialize protocol field getter */ -+ lua_rawgeti(L, -1, 4); -+ if (lua_isstring(L, -1)) { -+ field->get = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)field->get, lua_tostring(L, -1)); /* the get-wrapper knows about the piggybacked string */ -+ }else -+ field->get = NULL; -+ lua_pop(L, 1); /* pop field getter */ -+ -+ /* initialize protocol field setter */ -+ lua_rawgeti(L, -1, 5); -+ if (lua_isstring(L, -1)) { -+ field->set = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)field->set, lua_tostring(L, -1)); /* the set-wrapper knows about the piggybacked string */ -+ }else -+ field->set = NULL; -+ lua_pop(L, 1); /* pop field setter */ -+ -+ /* field initialization completed */ -+ lua_pop(L, 1); /* pop field-table */ -+ } -+ -+ /* put sentinel at the end of protocol_fields */ -+ memcpy(&prot_buf->protocol_fields[nr_of_fields], &sentinel, sizeof(sentinel)); -+ lua_pop(L, 1); /* pop protocol-fields-table */ -+ -+ /* initialize has_protocol field */ -+ lua_getfield(L, 1, "has_protocol"); -+ if (lua_isstring(L, -1)) { -+ prot_buf->has_protocol = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)prot_buf->has_protocol, lua_tostring(L, -1)); /* the has_protocol-wrapper knows about the piggybacked string */ -+ }else -+ prot_buf->has_protocol = NULL; -+ lua_pop(L, 1); /* pop has_protocol */ -+ -+ /* initialize get_field_changes field */ -+ lua_getfield(L, 1, "get_field_changes"); -+ if (lua_isstring(L, -1)) { -+ prot_buf->get_field_changes = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)prot_buf->get_field_changes, lua_tostring(L, -1)); /* the get_field_changes-wrapper knows about the piggybacked string */ -+ }else -+ prot_buf->get_field_changes = NULL; -+ lua_pop(L, 1); /* pop get_field_changes */ -+ -+ /* Storing the pointer to the DYNAMIC protbuf within dyn_prot_buf_array, in order to free it at cleanup */ -+ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { -+ if (!dyn_prot_buf_array[i]) { -+ dyn_prot_buf_array[i] = prot_buf; -+ break; -+ }else -+ goto err; -+ } -+ -+ /* call the "common" register_protbuf */ -+ register_protbuf(L, prot_buf, get_free_protocol_index(L)); /* register prot_buf as it is done with the static ones */ -+ -+ return 0; -+ -+err: -+ kfree(prot_buf->protocol_fields); -+err2: -+ if (prot_buf->payload_field) kfree(prot_buf->payload_field); -+free_prot_buf: -+ kfree((void *)prot_buf->name); -+ kfree(prot_buf); -+ -+ luaL_error(L, "one or more error happend while registering a dynamic protocol buffer, please consult the debug log"); -+ -+ return 0; -+ -+} -+ -+void luaopen_protbuf_dynamic(lua_State *L) -+{ -+ lua_getglobal(L, "_G"); -+ lua_pushcclosure(L, register_dynamic_protbuf, 0); -+ lua_setfield(L, -2, "register_dynamic_protbuf"); -+ lua_pop(L, 1); /* pop _G */ -+ return; -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_ethernet.c -@@ -0,0 +1,60 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+ -+ -+static int32_t eth_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ uint8_t *embedded_protocol = seg->start + seg->offset + 12 /*bytes*/; -+ unsigned short res = (unsigned short)((embedded_protocol[1] << CHAR_BIT) | (embedded_protocol[0] << CHAR_BIT)); -+ -+ switch (res) { -+ case 0x0800: /* 1: Internet Protocol (IP) */ -+ if (protocol_type == PACKET_IP) return 1; -+ break; -+ default: -+ return 0; -+ } -+ -+ return 0; -+} -+ -+static const struct protocol_field eth_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "dmac", 0, 48, NULL, NULL }, -+ { "smac", 48, 48, NULL, NULL }, -+ { "type", 96, 16, NULL, NULL }, -+ { "data", 112, 0, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf eth_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_ETH, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)ð_protocol_fields, -+ .has_protocol = ð_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+ -+void luaopen_protbuf_eth(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)ð_protocol_buf, PACKET_ETH); -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_helpers.c -@@ -0,0 +1,216 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+#include -+#include /* kmalloc */ -+#endif -+ -+#include "controller.h" -+ -+int32_t get_header_size(struct protocol_buf * prot_buf) -+{ -+ int32_t bit_counter = 0; -+ struct protocol_field * field = prot_buf->protocol_fields; -+ -+ for (; field->name; field++) -+ bit_counter += field->length; -+ -+ return bit_counter >> 3; -+} -+ -+ -+int32_t set_32_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ *(uint32_t *)(seg->start + seg->offset) = (uint32_t )htonl(luaL_checkinteger(L, 2)); -+ return 0; -+} -+int32_t get_32_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, ntohl(*((uint32_t *)(seg->start + seg->offset)))); -+ return 1; -+} -+ -+int32_t set_16_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ *(uint16_t *)(seg->start + seg->offset) = (uint16_t)htons(luaL_checkinteger(L, 2)); -+ return 0; -+} -+int32_t get_16_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, ntohs(*((uint16_t *)(seg->start + seg->offset)))); -+ return 1; -+} -+ -+int32_t set_lower_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; -+ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); -+ -+ *pos &= 0x0F; /* reset lower 4 bits*/ -+ *pos |= b; -+ -+ return 0; -+} -+ -+int32_t get_lower_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) >> 4); -+ return 1; -+} -+ -+int32_t set_upper_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; -+ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); -+ -+ *pos &= 0xF0; /* reset upper 4 bits*/ -+ *pos |= (b >> 4); -+ -+ return 0; -+} -+ -+int32_t get_upper_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) & 0x0F); -+ return 1; -+} -+ -+ -+int32_t set_8_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ *(uint8_t *)(seg->start + seg->offset) = (uint8_t)luaL_checkinteger(L, 2); -+ return 0; -+} -+ -+int32_t get_8_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, *(uint8_t *)(seg->start + seg->offset)); -+ return 1; -+} -+ -+int32_t set_1_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ unsigned long l = 0; -+ -+ memcpy(&l, (seg->start + seg->offset), seg->length); -+ l |= (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); -+ memcpy((seg->start + seg->offset), &l, seg->length); -+ -+ return 0; -+} -+ -+int32_t get_1_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ unsigned long l = 0; -+ uint32_t bit = 0; -+ -+ memcpy(&l, (seg->start + seg->offset), seg->length); -+ bit = l & (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); -+ -+ lua_pushboolean(L, bit); -+ return 1; -+} -+ -+int32_t get_string_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ /* Warning we cast from uchar to char */ -+ lua_pushlstring(L, (char *)seg->start + seg->offset, seg->length); -+ return 1; -+} -+ -+int32_t set_data_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ lua_packet_segment * data = checkbytearray(L, 2); -+ -+ pr_debug("seg->length %u, data->length %u\n", seg->length, data->length); -+ -+ if (seg->length >= data->length) -+ memcpy((seg->start + seg->offset), data->start, data->length); -+ else -+ luaL_error(L, "provided byte array too big for given packet segment"); -+ return 0; -+} -+ -+struct field_changes * get_allocated_field_changes(lua_State *L, int32_t nr_of_fields) -+{ -+ struct field_changes * changes; -+ -+ changes = kmalloc(sizeof(struct field_changes), GFP_ATOMIC); -+ -+ if (!changes) -+ goto failure; -+ -+ changes->field_length_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); -+ if (!changes->field_length_changes) -+ goto free1; -+ -+ changes->field_offset_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); -+ if (!changes->field_offset_changes) -+ goto free2; -+ -+ memset(changes->field_length_changes, 0, nr_of_fields * sizeof(int)); -+ memset(changes->field_offset_changes, 0, nr_of_fields * sizeof(int)); -+ -+ changes->ref_count = 1; -+ -+ return changes; -+ -+free2: kfree(changes->field_length_changes); -+free1: kfree(changes); -+failure: -+ if (!changes) luaL_error(L, "couldnt allocate memory inside 'get_allocated_field_changes'"); -+ return NULL; /* only to omit warnings */ -+} -\ No newline at end of file ---- /dev/null -+++ b/extensions/LUA/prot_buf_icmp.c -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+ -+static int32_t icmp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 0; -+} -+ -+static const struct protocol_field icmp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "type", 0, 8, NULL, NULL }, -+ { "code", 8, 8, NULL, NULL }, -+ { "checksum", 16, 16, NULL, NULL }, -+ { "id", 32, 16, NULL, NULL }, -+ { "sequence", 48, 16, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf icmp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_ICMP, -+ .payload_field = NULL, -+ .protocol_fields = (struct protocol_field *)&icmp_protocol_fields, -+ .has_protocol = &icmp_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_icmp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&icmp_protocol_buf, PACKET_ICMP); -+} -+ ---- /dev/null -+++ b/extensions/LUA/prot_buf_ip.c -@@ -0,0 +1,209 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+ #include -+#endif -+ -+#include "controller.h" -+ -+ -+#define IP_FMT "%u.%u.%u.%u" -+#define IP_ACC(buf) buf[0], buf[1], buf[2], buf[3] -+ -+ -+static int32_t ip_version_set(lua_State *L) -+{ -+ uint8_t version_checked; -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *version_seg = seg->start + seg->offset; -+ int32_t version = luaL_checkinteger(L, 2); -+ -+ luaL_argcheck(L, version >= 0 && version <= 15, 1, "version number invalid"); -+ -+ version_checked = (uint8_t)version; -+ -+ version_seg[0] &= (uint8_t)0x0F; /* reset version bits */ -+ version_seg[0] |= version_checked << 4; -+ -+ return 0; -+} -+static int32_t ip_version_get(lua_State *L) -+{ -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *version_seg = seg->start + seg->offset; -+ uint8_t v = version_seg[0] & 0xF0; -+ -+ v >>= 4; -+ -+ lua_pushinteger(L, v); -+ return 1; -+} -+ -+static int32_t ip_ihl_set(lua_State *L) -+{ -+ uint8_t ihl_checked; -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *ihl_seg = seg->start + seg->offset; -+ int32_t ihl = luaL_checkinteger(L, 2); -+ -+ luaL_argcheck(L, ihl >= 5 && ihl <= 15, 1, "ip header length invalid"); // RFC 791 5x32 = 160 bits -+ -+ ihl_checked = (uint8_t)ihl; -+ -+ ihl_seg[0] &= (uint8_t)0xF0; /* reset ihl bits */ -+ ihl_seg[0] |= ihl_checked; -+ -+ return 0; -+} -+static int32_t ip_ihl_get(lua_State *L) -+{ -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *ihl_seg = seg->start + seg->offset; -+ uint8_t v = ihl_seg[0] & 0x0F; -+ -+ lua_pushinteger(L, v); -+ return 1; -+} -+ -+static int32_t ip_addr_set(lua_State *L) -+{ -+ int32_t field_id = lua_tointeger(L, lua_upvalueindex(2)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *addr_seg = seg->start + seg->offset; -+ uint32_t old_addr; -+ char *ip = (char *)luaL_checkstring(L, 2); -+ uint32_t a, b, c, d; -+ struct sk_buff * skb = (struct sk_buff *)lua_touserdata(L, 3); -+ -+ /* for tcp / udp checksumming*/ -+ uint32_t prot_offset; -+ uint8_t *check, *protocol_seg; -+ -+ /* end */ -+ -+ sscanf(ip, IP_FMT, &a, &b, &c, &d); -+ -+ luaL_argcheck(L, a < 256 && b < 256 && c < 256 && d < 256, 1, "invalid ip addr"); -+ -+ old_addr = *((uint32_t *)addr_seg); -+ addr_seg[0] = (uint8_t)a; -+ addr_seg[1] = (uint8_t)b; -+ addr_seg[2] = (uint8_t)c; -+ addr_seg[3] = (uint8_t)d; -+ -+#if defined(__KERNEL__) -+ if (old_addr != *(uint32_t *)addr_seg) { -+ int32_t offset = (field_id == 10) ? -2 : -6; /* offset from saddr or daddr */ -+ -+ csum_replace4((uint16_t *)(addr_seg + offset), old_addr, *(uint32_t *)addr_seg); -+ -+ prot_offset = (field_id == 10) ? -3 : -7; /* offset from saddr or daddr */ -+ protocol_seg = seg->start + seg->offset + prot_offset; -+ -+ if (skb && (protocol_seg[0] == 0x06 || protocol_seg[0] == 0x11)) { /* is payload TCP or UDP ? */ -+ -+ check = seg->start + seg->offset; /* tmp res */ -+ check += (field_id == 10) ? 8 : 16; /* the start of the payload, depending saddr or daddr */ -+ check += (protocol_seg[0] == 0x06) ? 16 : 6; /* the start of the checksum, depending on TCP or UDP */ -+ -+ inet_proto_csum_replace4((__sum16 *)check, skb, old_addr, *(uint32_t *)addr_seg, 1); -+ -+ lua_pop(L, 1); -+ } -+ } -+#endif -+ return 0; -+} -+ -+ -+ -+ -+ -+static int32_t ip_addr_get(lua_State *L) -+{ -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *addr_seg = seg->start + seg->offset; -+ -+ char buf[16]; /*max: 255.255.255.255\0 --> 16 chars */ -+ -+ sprintf(buf, IP_FMT, IP_ACC(addr_seg)); -+ lua_pushstring(L, buf); -+ return 1; -+} -+ -+static int32_t ip_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ uint8_t * embedded_protocol = seg->start + seg->offset + 9 /*bytes*/; -+ -+ switch (embedded_protocol[0]) { -+ case 0x01: /* 1: Internet Control Message Protocol (ICMP) */ -+ if (protocol_type == PACKET_ICMP) return 1; -+ break; -+ case 0x02: /* 2: Internet Group Management Protocol (IGMP) */ -+ break; -+ case 0x06: /* 6: Transmission Control Protocol (TCP) */ -+ if (protocol_type == PACKET_TCP) return 1; -+ break; -+ case 0x11: /* 17: User Datagram Protocol (UDP) */ -+ if (protocol_type == PACKET_UDP) return 1; -+ break; -+ case 0x59: /* 89: Open Shortest Path First (OSPF) */ -+ break; -+ case 0x84: /* 132: Stream Control Transmission Protocol (SCTP) */ -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static const struct protocol_field ip_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "version", 0, 4, ip_version_get, ip_version_set }, -+ { "ihl", 4, 4, ip_ihl_get, ip_ihl_set }, -+ { "tos", 8, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "tot_len", 16, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "id", 32, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "flags", 48, 3, get_1_bit_generic, set_1_bit_generic }, -+ { "frag_off", 51, 13, NULL, NULL }, -+ { "ttl", 64, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "protocol", 72, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "check", 80, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "saddr", 96, 32, ip_addr_get, ip_addr_set }, -+ { "daddr", 128, 32, ip_addr_get, ip_addr_set }, -+ { "data", 160, 0, NULL, set_data_generic }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf ip_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_IP, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&ip_protocol_fields, -+ .has_protocol = &ip_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_ip(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&ip_protocol_buf, PACKET_IP); -+} -+ ---- /dev/null -+++ b/extensions/LUA/prot_buf_raw.c -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+static int32_t raw_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 1; -+} -+ -+static const struct protocol_field raw_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "data", 0, 0, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf raw_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_RAW, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&raw_protocol_fields, -+ .has_protocol = &raw_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_raw(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&raw_protocol_buf, PACKET_RAW); -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_tcp.c -@@ -0,0 +1,188 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+ #include -+#endif -+#include "controller.h" -+ -+ -+static int32_t tcp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 1; -+} -+ -+static int32_t tcp_set_checksum(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+#if defined(__KERNEL__) -+ uint8_t * check_seg = seg->start + seg->offset; -+ uint8_t * tcp_hdr = check_seg - 16; -+ uint8_t * saddr = tcp_hdr - 8; -+ uint8_t * daddr = saddr + 4; -+ uint32_t len = 20 + (seg->changes->field_length_changes[11] / 8) + (seg->changes->field_length_changes[10] / 8); -+ unsigned short checksum = tcp_v4_check(len, *(uint32_t *)saddr, *(uint32_t *)daddr, -+ csum_partial(tcp_hdr, len, 0)); -+ -+ memcpy(check_seg, &checksum, sizeof(unsigned short)); -+#endif -+ return 0; -+} -+ -+ -+static const struct protocol_field tcp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "seq", 32, 32, get_32_bit_generic, set_32_bit_generic }, -+ { "ack", 64, 32, get_32_bit_generic, set_32_bit_generic }, -+ { "data_off", 96, 4, get_lower_4_bit_generic, set_lower_4_bit_generic }, -+ { "reserved", 100, 4, get_upper_4_bit_generic, set_upper_4_bit_generic }, -+ { "flags", 104, 8, get_1_bit_generic, set_1_bit_generic }, -+ { "window_size", 112, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "check", 128, 16, get_16_bit_generic, tcp_set_checksum }, -+ { "urgent", 144, 16, NULL, NULL }, -+ { "options", 160, 0, NULL, set_data_generic }, -+ { "data", 160, 0, NULL, set_data_generic }, /* begin of data depends on options */ -+ PROT_FIELD_SENTINEL, -+}; -+ -+ -+static const struct protocol_field tcp_options_and_data[] = { -+ /* field name offset length getter setter */ -+ { "MSS", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "WS", 0, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "SACK", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "TSVAL", 0, 32, get_32_bit_generic, set_32_bit_generic }, -+ { "TSER", 0, 32, get_32_bit_generic, set_32_bit_generic }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+ -+static struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg); -+ -+static const struct protocol_buf tcp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_TCP, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&tcp_protocol_fields, -+ .has_protocol = &tcp_has_protocol, -+ .get_field_changes = &tcp_get_field_changes, -+}; -+ -+ -+static struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg); -+ -+static const struct protocol_buf tcp_options_and_data_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_TCP_OPT, -+ .payload_field = NULL, -+ .protocol_fields = (struct protocol_field *)&tcp_options_and_data, -+ .has_protocol = NULL, -+ .get_field_changes = &tcp_options_get_field_changes, -+}; -+ -+struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg) -+{ -+ /* depending on the value stored inside the 'data_off'-field, the length of -+ * the 'options' field has to be changed, as well as the length and offset -+ * of the 'data' field */ -+ uint8_t *tcp_hdr = seg->start + seg->offset; -+ -+ /* get the pointer to the 'data_off' field */ -+ uint8_t * data_off_field = tcp_hdr + 12; /* 12 bytes offset */ -+ /* extract the stored header length in bits */ -+ uint32_t tcp_hdr_len = ((*(uint8_t *)data_off_field) >> 4) * 32; -+ -+ /* get an allocated 'field_changes' structure */ -+ struct field_changes * changes = get_allocated_field_changes(L, 12); -+ -+ /* depending on the tcp header length, change the length of the options*/ -+ changes->field_length_changes[10] = tcp_hdr_len - 160; -+ /* depending on the options length, change the offset of the data */ -+ changes->field_offset_changes[11] = changes->field_length_changes[10]; -+ changes->field_length_changes[11] = (seg->length * 8) - tcp_hdr_len; -+ -+ return changes; -+ -+} -+ -+struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg) -+{ -+ /* depending on the value stored inside the 'data_off'-field, the length of -+ * the 'options' field has to be changed, as well as the length and offset -+ * of the 'data' field */ -+ uint8_t *tcp_opt_hdr = seg->start + seg->offset; -+ -+ /* get an allocated 'field_changes' structure */ -+ struct field_changes * changes = get_allocated_field_changes(L, 5); -+ -+ int32_t MSS = 0, WS = 0, SACK = 0, TS = 0, i; -+ -+ uint8_t b1, b2; -+ -+ for (i = 0; i < seg->length; i++) { -+ b1 = tcp_opt_hdr[i]; -+ b2 = tcp_opt_hdr[i + 1]; -+ -+ if (b1 == 0x00) -+ break; -+ -+ /* test for MSS */ -+ if (!MSS && (b1 == 0x02 && b2 == 0x04)) { -+ changes->field_offset_changes[0] = (i + 2) * CHAR_BIT; -+ MSS = 1; -+ } -+ -+ /* test for WS --- yet buggy somehow */ -+ if (!WS && (b1 == 0x03 && b2 == 0x03)) { -+ changes->field_offset_changes[1] = (i + 2) * CHAR_BIT; -+ WS = 1; -+ } -+ -+ /* test for SACK*/ -+ if (!SACK && (b1 == 0x04 && b2 == 0x02)) { -+ changes->field_offset_changes[2] = i * CHAR_BIT; /* has no value */ -+ SACK = 1; -+ } -+ -+ /* test for TS */ -+ if (!TS && (b1 == 0x08 && b2 == 0x0A)) { -+ changes->field_offset_changes[3] = (i + 2) * CHAR_BIT; -+ changes->field_offset_changes[4] = (i + 2 + 4) * CHAR_BIT; -+ TS = 1; -+ } -+ } -+ -+ return changes; -+ -+} -+ -+void luaopen_protbuf_tcp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&tcp_protocol_buf, PACKET_TCP); -+} -+void luaopen_protbuf_tcp_options(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&tcp_options_and_data_buf, PACKET_TCP_OPTIONS); -+} -+ -+ ---- /dev/null -+++ b/extensions/LUA/prot_buf_tftp.c -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+#include "controller.h" -+ -+static const struct protocol_field tftp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "opcode", 0, 16, get_16_bit_generic, NULL}, -+ { "filename", 0, 0, get_string_generic, NULL}, -+ { "mode", 0, 0, get_string_generic, NULL}, -+ { "block_nr", 0, 16, get_16_bit_generic, NULL}, -+ { "data", 0, 0, NULL, NULL}, -+ PROT_FIELD_SENTINEL, -+}; -+ -+struct field_changes * tftp_get_field_changes(lua_State *L, lua_packet_segment * seg) -+{ -+ /* depending on the value stored inside the 'opcode'-field we have to change -+ * offsets and lengths */ -+ uint8_t *tftp_hdr = seg->start + seg->offset; -+ short opcode = ntohs(*((uint16_t *)tftp_hdr)); -+ /* get an allocated 'field_changes' structure */ -+ struct field_changes * changes = get_allocated_field_changes(L, 5); -+ switch (opcode) { -+ case 1: /* Read Request (RRQ) */ -+ /* setting offset and length of field 'filename' */ -+ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; -+ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; -+ /* setting offset and length of field 'mode' */ -+ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; -+ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); -+ break; -+ case 2: /* Write Request (WRQ) */ -+ /* setting offset and length of field 'filename' */ -+ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; -+ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; -+ /* setting offset and length of field 'mode' */ -+ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; -+ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); -+ break; -+ case 3: /* Data (DATA) */ -+ /* setting offset of field 'block_nr' */ -+ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; -+ /* setting offset of field 'data' */ -+ changes->field_offset_changes[4] = changes->field_offset_changes[3] + (sizeof(unsigned short) << 3); -+ break; -+ case 4: /* Acknowledgment (ACK) */ -+ /* setting offset of field 'block_nr' */ -+ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; -+ break; -+ case 5: /* Error (ERROR) */ -+ /* we don't care ... yet */ -+ break; -+ default: -+ break; -+ } -+ -+ return changes; -+} -+ -+static const struct protocol_buf tftp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_TFTP, -+ .payload_field = NULL, -+ .protocol_fields = (struct protocol_field *)&tftp_protocol_fields, -+ .has_protocol = NULL, /* we don't need it, since we don't provide a payload field */ -+ .get_field_changes = tftp_get_field_changes, -+}; -+ -+void luaopen_protbuf_tftp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&tftp_protocol_buf, PACKET_TFTP); -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_udp.c -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+#endif -+ -+#include "controller.h" -+ -+ -+static int32_t udp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 1; -+} -+ -+static const struct protocol_field udp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "length", 32, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "check", 48, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "data", 64, 0, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf udp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_UDP, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&udp_protocol_fields, -+ .has_protocol = &udp_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_udp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&udp_protocol_buf, PACKET_UDP); -+} ---- /dev/null -+++ b/extensions/LUA/xt_LUA.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#ifndef XT_LUA_H_ -+#define XT_LUA_H_ -+ -+#define MAX_FILENAME_SIZE 256 -+#define MAX_FUNCTION_SIZE 256 -+#define MAX_SCRIPT_SIZE 32768 -+#define LUA_STATE_ARRAY_SIZE 128 -+ -+/* the targetsize is stored in a u16, so max size of the xt_lua_tginfo cannot exceed 64K*/ -+struct xt_lua_tginfo { -+ char buf[MAX_SCRIPT_SIZE]; -+ char filename[MAX_FILENAME_SIZE]; -+ char function[MAX_FUNCTION_SIZE]; -+ __u64 script_size; -+ __u32 state_id; -+}; -+ -+#endif /* XT_LUA_H_ */ ---- /dev/null -+++ b/extensions/LUA/xt_LUA_target.c -@@ -0,0 +1,286 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "xt_LUA.h" -+ -+#include "controller.h" -+ -+/*::* -+ * lua_envs -+ * ---------- -+ * This array holds a defined number of `lua_envs`_ structures. -+ * The used array index is also used as the Lua state identifier. -+ * The size of the array is defined in `LUA_STATE_ARRAY_SIZE`_. -+ */ -+struct lua_env * lua_envs[LUA_STATE_ARRAY_SIZE]; -+ -+/*::* -+ * lua_state_refs -+ * -------------- -+ * This array holds the reference counts of the several `lua_nf_state`_s -+ * which are stored inside the array `lua_states`_. -+ */ -+uint32_t lua_state_refs[LUA_STATE_ARRAY_SIZE] = { 0 }; -+ -+/*::* -+ * lua_tg -+ * ------ -+ * This function is called whenever a packet matches all matching conditions -+ * inside a rule. It is the target. It extracts the state identifier comming -+ * inside the *xt_target_param* structure and uses it to access the proper -+ * Lua state inside the `lua_states`_ array. -+ * -+ * It then constructs a new Lua userdata of type *lua_packet_segment* and -+ * initializes it with the lowest network header available. This userdata -+ * is annotated with the Lua metatable `LUA_PACKET_SEG_RAW`_ which converts -+ * the userdata to a raw lua packet having all raw functions available. -+ * This raw packet is the single parameter to the Lua function *process_packet* -+ * which must be defined inside the Lua script provided by the user. So far -+ * hardcoded, may be later configured by Lua - subject to change. -+ * -+ * The process_packet function must return an integer value, the verdict. For -+ * convenience reasons xt_LUA exports the verdicts NF_ACCEPT, NF_DROP and -+ * XT_CONTINUE inside the *register_lua_packet_lib* function. -+ */ -+ -+spinlock_t lock = SPIN_LOCK_UNLOCKED; -+ -+static uint32_t -+lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) -+{ -+ uint32_t verdict; -+ lua_packet_segment *p; -+ const struct xt_lua_tginfo *info = par->targinfo; -+ lua_State * L; -+ -+ /* START critical section on SMP, PacketScript is on the sequential trail at the moment TODO*/ -+ spin_lock_irq(&lock); -+ -+ L = lua_envs[info->state_id]->L; -+ -+ if (!skb_make_writable(pskb, pskb->len)) -+ return NF_DROP; -+ -+ /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ -+ lua_getglobal(L, info->function); -+ -+ /* push the lua_packet_segment as a parameter */ -+ p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ if (pskb->mac_header) -+ p->start = pskb->mac_header; -+ else if (pskb->network_header) -+ p->start = pskb->network_header; -+ else if (pskb->transport_header) -+ p->start = pskb->transport_header; -+ p->offset = 0; -+ p->length = (unsigned long)pskb->tail - (unsigned long)p->start; -+ p->changes = NULL; -+ -+ /* marking userdata 'lua_packet_seg' with the corresponding metatable */ -+ luaL_getmetatable(L, LUA_PACKET_SEG_RAW); -+ lua_setmetatable(L, -2); -+ -+ /* push a reference to the skb as a parameter, needed at the moment for calculating TCP checksum, but I am not happy with it*/ -+ lua_pushlightuserdata(L, (void *)skb_get(pskb)); -+ -+ /* do the function call (2 argument, 1 result) */ -+ if (lua_pcall(L, 2, 1, 0) != 0) { -+ printk(KERN_ERR "LUA [%d]: pcall '%s' failed: %s\n", info->state_id, info->function, lua_tostring(L, -1)); -+ lua_pop(L, 1); -+ return NF_DROP; -+ } -+ -+ if (!lua_isnumber(L, -1)) { -+ printk(KERN_ERR "LUA [%d]: function '%s' must return a verdict\n", info->state_id, info->function); -+ lua_pop(L, 1); -+ return NF_DROP; -+ } -+ -+ verdict = lua_tonumber(L, -1); -+ lua_pop(L, 1); -+ -+ kfree_skb(pskb); -+ -+ /* END critical section on SMP */ -+ spin_unlock_irq(&lock); -+ -+ -+ return verdict; -+ -+} -+/* Helper for checkentry */ -+static bool load_script_into_state(uint32_t state_id, unsigned long script_size, char *script_buf) -+{ -+ char *buf = kmalloc(script_size, GFP_KERNEL); -+ int32_t ret; -+ struct lua_env * env = kmalloc(sizeof(struct lua_env), GFP_KERNEL); -+ -+ if (!script_size > 0) { -+ pr_debug("LUA [%d]: script_size %lu < 0\n", state_id, script_size); -+ return false; -+ } -+ -+ env->L = lua_open(); -+ luaopen_base(env->L); -+ luaopen_controller(env->L); -+ -+ lua_getglobal(env->L, "_G"); -+ lua_pushinteger(env->L, state_id); -+ lua_setfield(env->L, -2, "STATE_ID"); -+ lua_pop(env->L, 1); /* pop _G */ -+ -+ strncpy(buf, script_buf, script_size); -+ ret = luaL_loadbuffer(env->L, buf, script_size, "PacketScript, loadbuffer") || -+ lua_pcall(env->L, 0, 1, 0); -+ -+ if (ret != 0) { -+ printk(KERN_ERR "LUA [%d]: failure loading script, error %s \n", state_id, lua_tostring(env->L, -1)); -+ lua_pop(env->L, 1); -+ kfree(buf); -+ kfree(env); -+ return false; -+ } -+ -+ lua_envs[state_id] = env; -+ -+ kfree(buf); -+ -+ return true; -+} -+/*::* -+ * lua_tg_checkentry -+ * ----------------- -+ * This function is used as a kernel-side sanity check of the data comming -+ * from the iptables userspace program. Since this is the function which is -+ * called everytime a new rule (with -j xt_LUA) is injected, this function -+ * is used to do the bookkeeping work, such as counting the reference of -+ * several Lua states and the initialization of new states if needed. As an -+ * extra initialization step it loads the provided Lua script into the Lua -+ * state. -+ * -+ * Lua state initialization -+ * ~~~~~~~~~~~~~~~~~~~~~~~~ -+ * 1. If a new rule is inserted and there is no existing state for the given -+ * state identifier (default state identifier is 0) a new Lua state is -+ * initialized using *lua_open*. -+ * 2. The Lua base library is registered inside the newly initialized state. -+ * Have a look at *lua/lbaselib.c* to see what functions of the Lua base -+ * library are available inside Lua. -+ * 3. The Lua packet library is registered inside the Lua state using the -+ * function *register_lua_packet_lib*. So far this function only registers -+ * the Netfilter verdicts NF_ACCEPT, NF_DROP and XT_CONTINUE inside the -+ * global environment of the given Lua state. -+ * 4. All the protocol Buffers, and the functions for accessing the bytes are -+ * registered using *register_protocols*. -+ * -+ * Lua state reference counting -+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+ * Bookkeeping of the Lua states inside the *lua_state_refs* array. The -+ * state identifier is mapped to the array index, which holds an integer -+ * counting the several initialized states. -+ * -+ * Loading the Lua script -+ * ~~~~~~~~~~~~~~~~~~~~~~ -+ * Copying the buffer which was initialized by the userspace program to a -+ * buffer with the proper size. The script is then loaded by the function -+ * xt_LUA_loadcode, which wrapps the *luaL_loadbuffer* function and does -+ * some workqueue initialization. So far this is done each time this function -+ * is called, subject to change. -+ */ -+static bool -+lua_tg_checkentry(const struct xt_tgchk_param *par) -+{ -+ const struct xt_lua_tginfo *info = par->targinfo; -+ -+ if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { -+ lua_state_refs[info->state_id]++; -+ return true; -+ } -+ return false; -+} -+ -+/*::* -+ * lua_tg_destroy -+ * -------------- -+ * This function is the counterpart of the `lua_tg_checkentry`_ function. It is -+ * responsible to free all the resources alocated inside the checkentry process. -+ * To be more specific it frees the Lua state using *lua_close* and kfree on all -+ * the dynamically allocated pointers to the registered dynamic protocol buffers. -+ * -+ * Additionally the function cares about decrementing the reference counters -+ * inside the array `lua_states`_. -+ */ -+static void -+lua_tg_destroy(const struct xt_tgdtor_param *par) -+{ -+ const struct xt_lua_tginfo *info = par->targinfo; -+ struct lua_env * env = lua_envs[info->state_id]; -+ -+ if (lua_state_refs[info->state_id] == 1) { -+ lua_close(env->L); -+ cleanup_dynamic_prot_bufs(); /* clean memory allocated by protocols defined in Lua */ -+ kfree(env); -+ pr_debug("LUA [%d]: Rule removed, close Lua state\n", info->state_id); -+ } else -+ pr_debug("LUA [%d]: Rule removed, Lua state stays open, referenced %d time(s)\n", -+ info->state_id, lua_state_refs[info->state_id] - 1); -+ -+ lua_state_refs[info->state_id]--; -+} -+ -+static struct xt_target lua_tg_reg __read_mostly = { -+ .name = "LUA", -+ .revision = 0, -+ .family = NFPROTO_UNSPEC, -+ .targetsize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), -+ .target = lua_tg, -+ .checkentry = lua_tg_checkentry, -+ .destroy = lua_tg_destroy, -+ .me = THIS_MODULE, -+}; -+ -+ -+static int32_t lua_tg_init(void) -+{ -+ return xt_register_target(&lua_tg_reg); -+} -+ -+static void lua_tg_exit(void) -+{ -+ xt_unregister_target(&lua_tg_reg); -+} -+ -+module_init(lua_tg_init); -+module_exit(lua_tg_exit); -+ -+MODULE_AUTHOR("Andre Graf "); -+MODULE_DESCRIPTION("Xtables: Processing of matched packets using the Lua scripting environment"); -+MODULE_ALIAS("ipt_LUA"); -+MODULE_ALIAS("ipt6t_LUA"); -+MODULE_ALIAS("arpt_LUA"); -+MODULE_ALIAS("ebt_LUA"); -+MODULE_LICENSE("GPL"); -+ -+ -+ ---- a/extensions/Kbuild -+++ b/extensions/Kbuild -@@ -28,6 +28,7 @@ obj-${build_pknock} += pknock/ - obj-${build_psd} += xt_psd.o - obj-${build_quota2} += xt_quota2.o - obj-${build_rtsp} += rtsp/ -+obj-${build_LUA} += LUA/ - - -include ${M}/*.Kbuild - -include ${M}/Kbuild.* ---- a/extensions/Mbuild -+++ b/extensions/Mbuild -@@ -23,3 +23,4 @@ obj-${build_pknock} += pknock/ - obj-${build_psd} += libxt_psd.so - obj-${build_quota2} += libxt_quota2.so - obj-${build_gradm} += libxt_gradm.so -+obj-${build_LUA} += LUA/ ---- a/mconfig -+++ b/mconfig -@@ -24,3 +24,4 @@ build_pknock=m - build_psd=m - build_quota2=m - build_rtsp=m -+build_LUA=m diff --git a/xtables-addons/patches/201-fix-lua-packetscript.patch b/xtables-addons/patches/201-fix-lua-packetscript.patch deleted file mode 100644 index 5a016e2ae..000000000 --- a/xtables-addons/patches/201-fix-lua-packetscript.patch +++ /dev/null @@ -1,136 +0,0 @@ ---- a/extensions/LUA/xt_LUA_target.c -+++ b/extensions/LUA/xt_LUA_target.c -@@ -19,7 +19,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include "xt_LUA.h" -@@ -64,10 +64,10 @@ uint32_t lua_state_refs[LUA_STATE_ARRAY - * XT_CONTINUE inside the *register_lua_packet_lib* function. - */ - --spinlock_t lock = SPIN_LOCK_UNLOCKED; -+DEFINE_SPINLOCK(lock); - - static uint32_t --lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) -+lua_tg(struct sk_buff *pskb, const struct xt_action_param *par) - { - uint32_t verdict; - lua_packet_segment *p; -@@ -79,7 +79,7 @@ lua_tg(struct sk_buff *pskb, const struc - - L = lua_envs[info->state_id]->L; - -- if (!skb_make_writable(pskb, pskb->len)) -+ if (skb_ensure_writable(pskb, pskb->len)) - return NF_DROP; - - /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ -@@ -88,11 +88,11 @@ lua_tg(struct sk_buff *pskb, const struc - /* push the lua_packet_segment as a parameter */ - p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); - if (pskb->mac_header) -- p->start = pskb->mac_header; -+ p->start = skb_mac_header(pskb); - else if (pskb->network_header) -- p->start = pskb->network_header; -+ p->start = skb_network_header(pskb); - else if (pskb->transport_header) -- p->start = pskb->transport_header; -+ p->start = skb_transport_header(pskb); - p->offset = 0; - p->length = (unsigned long)pskb->tail - (unsigned long)p->start; - p->changes = NULL; -@@ -208,16 +208,16 @@ static bool load_script_into_state(uint3 - * some workqueue initialization. So far this is done each time this function - * is called, subject to change. - */ --static bool -+static int - lua_tg_checkentry(const struct xt_tgchk_param *par) - { - const struct xt_lua_tginfo *info = par->targinfo; - - if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { - lua_state_refs[info->state_id]++; -- return true; -+ return 0; - } -- return false; -+ return -EINVAL; - } - - /*::* ---- a/extensions/LUA/lua/llimits.h -+++ b/extensions/LUA/lua/llimits.h -@@ -8,7 +8,6 @@ - #define llimits_h - - #include --#include - - #include "lua.h" - ---- a/extensions/LUA/lua/lapi.c -+++ b/extensions/LUA/lua/lapi.c -@@ -4,9 +4,6 @@ - ** See Copyright Notice in lua.h - */ - --#include --#include --#include - #include - - #define lapi_c ---- a/extensions/LUA/lua/ltable.c -+++ b/extensions/LUA/lua/ltable.c -@@ -18,7 +18,6 @@ - ** Hence even when the load factor reaches 100%, performance remains good. - */ - --#include - #include - - #define ltable_c ---- a/extensions/LUA/lua/luaconf.h -+++ b/extensions/LUA/lua/luaconf.h -@@ -13,8 +13,12 @@ - #if !defined(__KERNEL__) - #include - #else -+#include -+ -+#undef UCHAR_MAX -+#undef BUFSIZ -+#undef NO_FPU - #define UCHAR_MAX 255 --#define SHRT_MAX 32767 - #define BUFSIZ 8192 - #define NO_FPU - #endif -@@ -637,6 +641,8 @@ union luai_Cast { double l_d; long l_l; - */ - #if defined(__KERNEL__) - #undef LUA_USE_ULONGJMP -+#define setjmp __builtin_setjmp -+#define longjmp __builtin_longjmp - #endif - - #if defined(__cplusplus) ---- a/extensions/LUA/lua/llex.h -+++ b/extensions/LUA/lua/llex.h -@@ -10,6 +10,8 @@ - #include "lobject.h" - #include "lzio.h" - -+/* prevent conflict with definition from asm/current.h */ -+#undef current - - #define FIRST_RESERVED 257 - diff --git a/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch b/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch deleted file mode 100644 index 5279619da..000000000 --- a/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch +++ /dev/null @@ -1,284 +0,0 @@ -Linux 5.16 includes 04e85bbf71c9 ("isystem: delete global -isystem compile option") - -compile error on >=5.16 -xtables-addons-3.21/extensions/LUA/lua/lua.h:12:10: fatal error: stdarg.h: No such file or directory - 12 | #include - | ^~~~~~~~~~ - -Generated with coccinelle: - -cat <cocci-xtables-lua-linux-5.16.spatch -@include_arg@ -@@ - #include - -@include_def@ -@@ - #include - -@include_both depends on include_arg && include_def@ -@@ - #include - -@add_include_linux_stdheaders_both depends on include_both@ -@@ -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) -?#include -?#include -+#else -+#include -+#include -+#endif - -@add_include_linux_stdheaders depends on !include_both@ -@@ -( -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif -| -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif -) -EOF -spatch --in-place --include-headers --no-includes --sp-file cocci-xtables-lua-linux-5.16.spatch --dir extensions/LUA/lua/ - ---- - ---- a/extensions/LUA/lua/lauxlib.c -+++ b/extensions/LUA/lua/lauxlib.c -@@ -4,7 +4,12 @@ - ** See Copyright Notice in lua.h - */ - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #if !defined(__KERNEL__) - #include ---- a/extensions/LUA/lua/lauxlib.h -+++ b/extensions/LUA/lua/lauxlib.h -@@ -9,7 +9,12 @@ - #define lauxlib_h - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - #include /* for kmalloc and kfree when allocating luaL_Buffer */ - - #if !defined(__KERNEL__) ---- a/extensions/LUA/lua/ldebug.c -+++ b/extensions/LUA/lua/ldebug.c -@@ -5,8 +5,14 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include - #include -+#else -+#include -+#include -+#endif - #include - - #define ldebug_c ---- a/extensions/LUA/lua/ldump.c -+++ b/extensions/LUA/lua/ldump.c -@@ -4,7 +4,12 @@ - ** See Copyright Notice in lua.h - */ - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define ldump_c - #define LUA_CORE ---- a/extensions/LUA/lua/lfunc.c -+++ b/extensions/LUA/lua/lfunc.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define lfunc_c - #define LUA_CORE ---- a/extensions/LUA/lua/llimits.h -+++ b/extensions/LUA/lua/llimits.h -@@ -7,7 +7,12 @@ - #ifndef llimits_h - #define llimits_h - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #include "lua.h" - ---- a/extensions/LUA/lua/lmem.c -+++ b/extensions/LUA/lua/lmem.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define lmem_c - #define LUA_CORE ---- a/extensions/LUA/lua/lmem.h -+++ b/extensions/LUA/lua/lmem.h -@@ -8,7 +8,12 @@ - #define lmem_h - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #include "llimits.h" - #include "lua.h" ---- a/extensions/LUA/lua/lobject.c -+++ b/extensions/LUA/lua/lobject.c -@@ -4,7 +4,12 @@ - ** See Copyright Notice in lua.h - */ - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #include - #include ---- a/extensions/LUA/lua/lobject.h -+++ b/extensions/LUA/lua/lobject.h -@@ -9,7 +9,12 @@ - #define lobject_h - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - - #include "llimits.h" ---- a/extensions/LUA/lua/lstate.c -+++ b/extensions/LUA/lua/lstate.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define lstate_c - #define LUA_CORE ---- a/extensions/LUA/lua/lstrlib.c -+++ b/extensions/LUA/lua/lstrlib.c -@@ -6,7 +6,12 @@ - - - #include -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - #include - #include - #include ---- a/extensions/LUA/lua/ltablib.c -+++ b/extensions/LUA/lua/ltablib.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define ltablib_c - #define LUA_LIB ---- a/extensions/LUA/lua/lua.h -+++ b/extensions/LUA/lua/lua.h -@@ -9,8 +9,14 @@ - #ifndef lua_h - #define lua_h - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include - #include -+#else -+#include -+#include -+#endif - - #include "luaconf.h" - ---- a/extensions/LUA/lua/luaconf.h -+++ b/extensions/LUA/lua/luaconf.h -@@ -8,7 +8,12 @@ - #ifndef lconfig_h - #define lconfig_h - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #if !defined(__KERNEL__) - #include diff --git a/xtables-addons/patches/210-freebsd-build-fix.patch b/xtables-addons/patches/210-freebsd-build-fix.patch deleted file mode 100644 index 4f05d60eb..000000000 --- a/xtables-addons/patches/210-freebsd-build-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/extensions/LUA/Makefile -+++ b/extensions/LUA/Makefile -@@ -110,7 +110,7 @@ PKG_CONFIG = /usr/bin/pkg-config - RANLIB = ranlib - SED = /bin/sed - SET_MAKE = --SHELL = /bin/bash -+SHELL = /bin/sh - STRIP = strip - VERSION = 1.21 - abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA From 2549ddcff2500951afd07cc3f67ba3d80e1f725d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 28 Jun 2023 18:26:23 +0200 Subject: [PATCH 0987/2059] Use PKG_BUILD_FLAGS:=no-mips16 insed of PKG_USE_MIPS6:=0 --- golang/golang/Makefile | 3 ++- v2ray-core/Makefile | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 1047d5b6b..1f5ecffcc 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -37,7 +37,8 @@ PKG_CPE_ID:=cpe:/a:golang:go PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_DIR:=$(BUILD_DIR)/go-$(PKG_VERSION) PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 +#PKG_USE_MIPS16:=0 +PKG_BUILD_FLAGS:=no-mips16 PKG_GO_PREFIX:=/usr PKG_GO_VERSION_ID:=$(GO_VERSION_MAJOR_MINOR) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index f9254e896..113c70f2e 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -18,7 +18,8 @@ PKG_MAINTAINER:=Tianling Shen PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 +♯PKG_USE_MIPS16:=0 +PKG_BUILD_FLAGS:=no-mips16 GO_PKG:=github.com/v2fly/v2ray-core/v5 GO_PKG_BUILD_PKG:=$(GO_PKG)/main From 5ce0bcc714b6a237f38c6365bab8734ea23ccb98 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Jun 2023 13:21:14 +0200 Subject: [PATCH 0988/2059] Update omr-bypass db --- .../root/usr/share/omr-bypass/omr-bypass.db | Bin 2342912 -> 2338816 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db index 2c0740b08d461188726e968e50ddeaaed0fec8e5..1c03dc910688b0de0eea1497b88101f77a2407f0 100644 GIT binary patch delta 620553 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

    ^JBfv)({8|LF~{Y97@A_GQ-B8bV!q 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%0DFjg;F?3naz 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�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 dfN;_qG_j2zTg@(JDejF(%g;>_ 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%0AfG*!*7t6kaF%|bt>nsg6NJb=dP`>S4cfI9*S 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%0DoblsA#b+nwFXvbk{(g{&e)t!hR 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%0DEts?MEq5Unh=& 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%0AWVfa*Q~Q+wUaIt!sQjdrRK3*O zm+MF?!Lo`sw0E(-S_ysURzhFJO0db$2Sco}T%_ynmxY?Tip|6Y?yr*gek$Bzy?s~D z*U6z)7^~;$>s7QgS9}XIW^)b~I;~Jt&sO)a6s32c#Sjq?n>O-|tShw5xR z2`Obi=jN)XseCoirt0QUHz9Op;7T5HVfI%kCch=<=^Tj7V|wu#nNJzSY? zgoi0}9WA8kgH*&2TRK!H*8w|KH_c;+7Q2xgtfciAQR7?-J-0z)mEsqG5gn*i>nS-v zFY*ZJ59Ou+8{RtGo)~x^u4mymtSy5Z2=>+0wouPoAEmVMjpHa(b#JrvKyfyf|7PQj zR`=4%4M6OveH);rhdwm_x+|+K+^1?c1#Bd}tK!YjNJ1BUuR-syjf{EC+hSoz>!iJ= zP)D8F$bMu8_kJYnVWrIQuk&0T6KvM`EgvebY=ZilIy8V0t$Gt8)W(Ipcxs4?bPqK~ zT9oNxFq=5UD)2^~b|H7CT*%#{y>ZyTdDD7z8AmCv&6LU@ROd^^cFYD!fv6HUlhYGr(dVrClZ+6H$`ZkD??CO~O)booH2Ui4K{Z ze?Lki*B?by@U}^g?wg{?lNg0JZ^}@g$58S`TEIi|AA_2g$*CE)dD8+Ne++hT+Uqg4 zP>gdeGZeOOrR!TbJC3f;)f>hRVZP=lZ43OKt*OQgpxd)lZ-T{vQ(qHUWo+JLe6X9r zrd1oWI+^xKNEoe8m*3+Mkob`L4VeS}xZYqsd_wlge z_7m`?&d^8}I-56*Oi<90mAqo}`ZNR``kcqOEW( zZYx~tI@%&VSeaWXI!LQWTlxp$M2L2dZKY2BRw%r&m5wfU7w)HTkOD(WU)94Z(loI# z24ciEZ|aS&SGs=RHj4j$M7?!jl}FnDU4kSh3gn!)2M7+qg9LX11a}DT?hrx_4sl4n zIHgYUtxz1=tw52o+ihu!l*+bHDA29p?`P)l{N8`geeRKKE+4sP=DKMl0$176V$yy# zY0>KtbxU;|ZZS;N6#i)7I?T81aPC5PFJ*c(+|x@m)1`Ib)KrgK*}^G`$wB69X&H{1 zCAyb3)+7=%F$X%X_P2C2)ZrY2-#}M$s9Il3`uQZ5cA0KgxAuV`l`K0b~RKh4>43%XC=oM|ZU? z6Ntwo73V?ZuC7)|xd5Xp#`=v(>hmm|@9gH^`^Py?yfl$h!KhH@d{Q#=gF^!1k-7Ph z(|{EQ?y9&LM%Nan_wr%fAyepfe((eI{q#I&k9B8HmVY55m`R#G*9ah+3lZlTE@e+p z`aJr|cz5>r=c?bZ0fQCd`h{qFA)FYyz)B^X&&h=V|D_P%Q40+X*`w8@28qGY02#3X?^a=vPpnpK0Njxch_06c zGkmxy!JVD1w7EvrvU@7Ln7TcbS`4J_#F0m1hZo~>if0*B%I>Cvvsff|XLr@*S;nEd zv%4sFtOw!FiYq|?u_cIb@;K`{vO8*G37|SCk1W1ZoEvAnt~p9#fl9pQO8%8RoPD>SvI;na`(A`4cm`8J!+6d%kDmB&ev#Gjm zL#0x%rwxAYW5) z9Xvd)q3N506Md_D%)l)2-ml=tQja^EgN*&G0ITZCW>#*Jo)=*lw}WUb?rcJNx3$hR zn>Zp{pt+K!Z-LR%w$SpX4#qIDIi=VEIUm{rTDP|#-8lW#!J-hWh>l3H@>bZ8*3rim zEJ>Yw2+e5H(mH|MJN!Fzdk14* zhA%r7`XuVE8YkxJEa_m@Mn--R+eAGQ4Q3xi7=LIWN=5?w9FJT5Iuqqs;DB+Bx5- zhP$PLUO}q^U!ker=kuL`7Fgqbh1$)v^p)T$KFy44Vj+@A}lF(Q!US*ZPk>Lg9IhJ2fg}?JH8J0EFv?Z3b1{@xyy}hr3($Axf(B1X4WW2R= zcd}w$gS5IHJ!Sn?JHImD<=t);!ZIzsOd~yiYH=$e?5wG(OKe7sk}TUmbw$6cpH;`PS zE*bX&@@$lOgQns&`3=a7)08>3#aJDB1Ma^21~u+b!x2rJW{_E5t$*TBJ!nU%#x6J+ zsh+z4z)`Z<$S~3E4%g;gRNb_Ts-Nwmu~4Qkw%2lpDBw+G@Bb!qtRF`DM5xZ2c-R*g z`^17IHy$nKd%N3h*2(O|91_)fHQ%z`?h0~b`o!^v!%}ae=|L*Ln@6BJ(GRG>ZghIm zZrUPd`gmLiXt4S_$9h1wug>oVLx=9~hA;PaGbw&C!vZ6o-5zqvDPs>9kJy9UO7@^i zWwd_}L)hngXv{9_x}#ZPxwwbnf$u05J7V4LQi|Fe9Pj0RK`r;fhAe$M*Xn2X60I`{ znL1z|i&Y~Nm+-H>7|n=GYysc3P}4@k5Zvbib=n64^EKH#=BdCu=IZV^BZTZZ`f48_ zX6q>rpIOhPuAXniMUgvGo%d6E1_y`HiRnf&&G^zpdN}wCr;+mZqW~xO2gm5peh9n0 zKlm{Y|KP#WS}osq-t^VWnrNtbZ>)?%_PvqzzGsEGjN`lqsn9@=ju@1d)mQ9M z$O-=koak}X^lregNC=f#>j4{(? zHPrnrsH@KYR{PHNU7kNxb&?FfB+uY8#q5Q>Q5?(Qb6FMnyba0R4D>dVtnoHoY=?Em zg)Ad>@;ZxPg0`6=@jCrBsGKrIK0j-WU>V_D-=V!2HFyV#qBYn&*na+|Ph3E}dzsmq zYx+=xU12$ctz{AVl=3?J4%9q+hutW5-(ktS!73k^zbusa3f4g^3*j^;1iDmk%#+~M zn)lsk;{~q07IS&=}o2c%UXe)rSTu*NK zTc+eNAWG}n2iDgv^U}EwsSET{+F63Xo_v^fn%k&pQ z_e(G!vgWAzCaX8@**dui+o|Ms&(iXv>~fu{Jx2jEgXo+KPtfpSJu&IrvSF;8^nvPll5~OsnMZ#GEihK*?x!Osk>=r(!GVWvpA2@CGP}!n z8%Mu9UJ<9kBTlKO(Ue#$fdFP^LG8Z3cW6+ed-?xevRIEx-SL|)Gof4_t$nBIq@s-f z#1-&;ovWM|`Ee-3y*yG648#aUzt6yd9^-x9!ZdH6rDb`j*1QkSA=+oMxoD9$efB;I z&s`2&=YOo%7Jp4y)SIn zW#55&c^Ng`V_8&ML-*J&Y`K?S{17OmIKBokvF_zBXr~*ApxIgS{|K^{D4B=qeuVlB znqj@cVl6T`i}d10G`$c+tmh+4=0~7DUpN106?oY^HT{?Zb2Z{)sGp%v&V7P89Qy== z`}q?V<0mQNJ*z9rCaU@w*jeoipog5n#K$Yv<9f$wi^NevcIJ|h=w8-N2QScATV1{Y>^2+~ z=B>2`?uFrT?q#ji=MAsYQ`%x8tYzBMsHlgkV+Hjme#!VC$Mz)6802-fhldGd&LV% z{TEqT8uKrJF43BQL1L!%nZ(8Vk9jQ8V;%v|&*&1aw;tcUZj25K^IA?UZKLc7?&b3} z_1`o-Ppd7@md|B^YbjekN0+i$3HbWoXno#tpGZCXH~q%j%W=OL(oA*voQBze_&JiC z@;OBhb!Vs*fC74zhouNTp4eiLIb{6W`{(0EoVjRORKd9dFa5Gc&6{a zq{|wpN0i6y#$P5q?s9OMa&+(}jN<8o@z$C2)1=Grps(^TQ?QSAuC%oD=DaV-L}a@h zT*WutGww=GsjrN^bjOg`Q(eCTp&qKW1+u1n#pv_3uV^t%C%%HL<6l8m_7>x3mUq=w z${2=sQS#S7?aYkPdcjUQv6Vsj{I4PO&97l<2TuP&M|)2H@@S`^Z$PRohxu&rHadls z0JQuG_iE@N?e$cyM-q+gmib+JkrRGFkzX1jl)bnM_z7^wjZHI-uf-p$mF{U1i zrv1NzcK5H94fS)cFjs(>sVUBMSu6rxK~SXc05eM8QU&*WeHAe90QldPbVB?aq3++~ z3x;dP_mp54?MucyRuB`3cOCm4WjXtj;oFMA^8NuL2C0^L4AjPrmiH?L=*laWs{SR0 zdSLcb{;Rf&ThUkl{Q&6)~ept~=dw!<#ZK}M(9)6@K(|GTA_lhQ*P6Eru8ieU$Wh;o?L0`py zWko~f-lSFoy>k;4tWTs{9`#iE7KzEKaf`OA-(q4k{1%p5NAqq0r?$452RCV%>{GXx zDvm5Nn!BQg0)Bx#)wQe0GLG3wktMmRvVH+@lET+pUQ|&kj@aNE2>g7x znKrC|HMfDEpp4tl8LtW}ZJjvnHp#L2>^5!0=uh(&t;joYAxf!tfFH>e&314rSY*0G z<#6r2Lt(BJyl4>$)x$eb7NTnxX+F`t!lgS0JPPkr%0Umig0=LZ#k!)NF^UDF3hdhj z8oTrF(q@n*tU*zz9jMNCX*NL9N!PTyi1DS3cILZ+ZPj-{%=ggMyTQSw7|-6n2O|A+ zVw)jmWnZdReQT>b0qVNd-PQRwpr&csZ{XEUPd#(Ym0cD8npN19U39~g=q&I5QKFM-{tr4js^|asG~WTs z#Y)Yt6Ww2FY-?qE?V~qDE-TyVq^Z$XamzgkZRGPiM0)>D^G$z88#wVg!=l_$^M0p| zRBihm;4O68yfxRfnXnVQn`!UIhWRU->cM%-;gu=+>VmD>M45k}LyP}lt4Y1$`(b9_ zwX%`UkjPGxyMKT|13iA-vZ%h|->{-uSx*^%lEcZ)T{fq#_WVhOI@-C{D%Hx`YHm$! zWi5^1k0SmG_V;SoK!qP!8(UdJZxkEBuB@(ge^IlV4*o^2T2*0dt%0me(w?+g z>RQTaK4Z-=j}*nlkRI<|)r4cQ&PqOwpN|@tf|})}RgLuIfkAUsL&ZO27+KxR>E~r) z2OSL!_gYn7dt449idFTr)eCsZx*XzxS64T^oF*7jU}@4h%opovzm_r`o+>q!O_r9H zcKUGdsl&9!vDH9Fyv~$%`e}X;=cL`Ms%q+AhM-kRYEi~%PH5XzPqX7!Gj1DEud1wW ze_MrE#fHQO3})P`56;uFbgz0r=O0lO3&~Q9uhU%PZubqC(`Gv- z_=E|? zkHO7la~?vNqcF5e1%6IWrn|T@-@S5{M!1j{ZfU0aI~|otnxQ40KhyOpvLt1i7WzAr zSQonQbX0=lE2n6x;Vg|#);)h3oun5ZBUMP5sFpuipTmqL0KFd%;bvi*xL~2tUMsnP zB>?2d>NE2gqr+&g{ukh^s5=})Hn2zOMSt7sNR1B!=?vut(!vNG45Y?z4gW7Zquek( zHVH#@^cj9SHpt0I=Vx~5Yvo`~4kBxiPCfOB_ou8mZ36c>mR#TT8JTKPYtFRR0~n?G7r5k!wvbVjmn|3yXU z3*lg`vkEtsdOm&7SM7;3D6V$u#nKk1U`-1~(iL^Pv|-HZ3LGzW7(Cdu9Sog8oUn-TZw7t|yKP+1xp;v^hx2=w>* z%Zxf#WpdgU92V=6DX>U?nzx0D3I*o{THCUDl@tydlav-tp>E+$Uyc@3xM7Aet0w3dKf~Wu<8{>J9w8SiLu6xBHiF7y z^y~(o^Kd<*k(!+g5|W4&fF2PD*BwF0k=h;s5*d2%2VGXId({Zte`H3wtA@)rlAK|x z6A1!Cwd+TZ`xv5yk#KH7q>~M9k$@PaPfWpqx?>&#bf=7Ug#DEg#d|*ui$dS}YEW4u zk?3C4M{h)d8;3+pdM{;_vl3dBuEqWy&(>3^(PZ^da)9+v-L)zj6w-9y4042F$N9G8uB6K(qoO_LrhL{9zEsb|p4tTyQZz6-ThMVkig?gythQO{ieRY=hkbo0@zU`Dv<{L0G*|lM+#tiHYd_=0vzMUmd@*hA~f{;;{fTS5FgB+&PM`MDw#X zHP%}9EKN1D&@gwgE?$s*mWeZMKjmn@=y)p_i#LE$`9+mOq%PXTQ zxZldKX`<@lA&fVgpxc$9dA!P3A$^>-d0D$1tHD(m84Ridmg}lGBek>&V}yNGoH0zW z&sU)ar=2K)-d6B-n9=;|5o(qMh~XNMMEWp7vs*|*wa2^R{GMC#yqgM|Fs?h;$$j7p=jy_NrThoOVp4poN6CT4)m5XnPF+wbs7hj0vx9rJrg5 zsHOaC@<>&(d9={M5PC-tvI~5r^tZu4X#+ndmihix>tnA;!Gw@{V zVG|B^)Z!etdv#+yWE8`nMv8vq!GeHoxDLaP23luEfk3FQ^R>|YdY(3tIhM?}wS(~- z#dohxW*0d;46BX4c4zM_r}(T8>@m^!&E@fNt7~g5WtfQ{s15ElHP#plaBJv+Nw2Qh zIuKq>b3NT+Rc#HkyiU?7`bWkKtE=cxs2MM;uFQd2C+BGigj5$;d@yZp#js|&swaa- zwPa_Ih9x`Ap4EHhtrJ;8(AU>1L_S{rv|(Y(o`M}v)vlSgSU0FxKJqG zy=H(8Hvn#bUE`sv4KTrSHR-+GYx-(oZQB&PJ!;c`B)ZqA+5ksoFP=RHK&={5_|t~q z*i-lGJJ6&xJ>+OaYu#0chYDL-47+JjBP?TKBjh))qr>d2Thm2nOu^2&+lbZ)`q~&q zf=)-JG$x?~H$B+4+iPWg(|4_D$9Z#xRDLtARC)N}vR#z`J1z;V0 zTL;$z&9(Jw1?vXZ)Kd9o0AOO%z!FzOgPT#by0V)AshV0Od1_SEQd5HtB1!j}p(j<8 zTgBGks8AK_(AKcSx;d2+mED|y+S2AUU%Hlq?MiEyACbfq=8k#9szM9O#VEX%g%C}I zIv~J;C}NEupUf7hoc=U3r8N;cM-uby%YPatz9vkM|1>KXYltzOO4-y@wC%eXN0hAfI)k#=e%v z-1FPg`515ebt{qwl(gozzaI88l33eMvHf93yn8LW*~nVn+CEZi5Tam^&b4-iF;WOZ zTcK-hx_sM^u`|kRZ8x23Lz`Vy zt%=c|wOy3f#5UepE!qODd0WN_H(PS8FKBesy0%!&+O{zLcw0O|dmXFeX}q0kbVVKh zGFdg-p$=`-sU3h@)A68HtD@I{;x+2N0^SMJ8dPN!Uw*c64AK zb+Lh&MX#-^I}I#tbyU71K)7r?-V$9)gUowPWpzZSmUM*V1vM~SNUpBcL!dChy|$We zcLa~BdOQq5gE}FA_MMy&YSIZkn$!uB34zkl!mp%f9UZK(tToeZGgZZI`5be^j~-$z z=alMMC0`q_sLp1x(HUgZIy*zq*?vaMaqhJ-T0<7o?!D#_#i<5l@mXhQ8NEHs@-Bj) zwO|vjYs0OLtqs$)R(ATZHdH=sJSc}~XIqPqOIN!9;7S)z{j06R%y`xY>jF;9&{$DD zx8#-D{2ZnjxNAZw*C7f^?khfIzd0l7nz{+2GYs_sT_td#w%7jd0-PRFp)SM$8X$<_YiY2j)^uk^rSnQQBv71EV$I_Djh76CzpcTUMEAM|y3*WmbscBS zTNql_)zh>VHYHiUy=kh?xY>S$trjG~&--q7)kG-7`#MAYWB>mFiwO?R1&gunbus#~FXQKEJ?snjAN0k3YWIU`rd@R` zKt6{IwtBlRT!sB;JxquCfmx{T46;;(s7!y7U8>&SndI+8AI(J->=jJb(%bQ2>fRrP zIXoD{rMZfFu|LgKP`35|>o_pf9~QBQH~?II2S8EE0E{+3U7A@A`D=PJywQRISpV(; zXrr&*Yi1F1=xQ@#bnARnejo^W>vVUUQBH#gf)JNW4TMWe2U7Fxfz&Lmizea1K&M~H zAZHYFmFPjv1g~{3sP!Q9oBN{%!Q&+=Fpo^)A{c0E7b~wL3ikCNsBjKOOKPMT#MUlQ z`e0D*IoMfN3kN&nm}PGnOtW)!nsg>4Lo0afc(#0pkT6SihLAl|ea&NrhO`6f{2|VO z(#gbM%1(BgZIx@MX?jy5|Fu)~t0^}{^E{@@J?fr6lZaf4q=pYgQaM%OD#kZKdxk>U z?x74ze21BCckMXE4MPvG@v;1)LhLXq^cjX|x&D6`m`^eZJBC3~!7xl+!#ur7hQ2Ym zUz^;(;kduyDwS%T+b|usy190!rVfXqA?lQBSu|KvJbwlet(F?->4^lBlT%qy8O;7F z{r_9N(~BabymE+MVX4VUP<{rW;?-)X#Wsge|I{cITQZX57^StgaH7@KyhmyJNJyDB zl74^NNJg0vIyMqvg>%8XK`|#xE%}2V%?VY_Q7Bf3dXA!^OD{IGR*~aWol2e(!8&D1 zR8)nkR=;!Dt~r{f%d3ug5X3K-^h9?~pvn(2BF_oX&e7EH*JsK0oq04R9nY`lV_0$O zQ%6`}tUJfynewysn+3)X!b81sd^B(j5*jcDW6T}n3|H0|)bgz{*1cXB1H;doEdQ3a zf6FPY%z;J?a=f&EsO3N@Wwb|OMvTQRZ5oRdvvhDQXf9D?JxkBJOg$b8c8e7^&WL-Q z5%)L>E@X$k5%)OYZ#N0^HK?M2xsG+Aiq?YWmW-#$vvG_DuCz1ivu?J!jfZcuG-Et{ z;q>t!d%F_2CAilym8LXP>FZ?i?RsiwI2-3)H&xXpP`2s>$_|`BJCiko1g6ox3_XE4 zQ8mpN6lXUueDmt*f3tqd0m_1&$7-*^CU; zPGjZWF^QT((;SRn)(uymNvOgwE#eVi_FLGm4=i4=)YaS9>?d0{M0;OgA^pMk^sZfx<*Vv%)_TpX?ZsciblCJdJ2%c>r|Sjcv^{>%8}De(NoFk%8^tA)M_dM`sbJB z%>ZXzXRR}7Yo}tFN2bD>j+)!UaJ@q-PJQLzi%>?I1^BfWSaVFx4oCWroYBAsH z^I~PpxB9$D*|X5OrL*XU-<(C4ut4WYKsl=|u?6O-JAV{18?JPj4U9S3nPK^sGh1tC z)AB6so6T%}CeFnyY7(#mQQ!F0Y1Z>|X6O-_XleW$I`3)E$4+d`FSH~7oT-{P2NI_! zpM2%b0q1rT9U;uYb0+EUJj2YKiMlb%8u|oz&$cTBIpY@y2k2RN!=ZLVVMo6FK5n*0A+{!nPI>WVN z9z+e(w_{-^9&D&?nuH+=n9rw}PDi{{i<bwlVReVb+VB6p%Dx+yzB`EGC@PXKISP;i{SHU-D3)G}w~l4YP? zYnd|^y-r((N^<(1WW2GKQ7A(vc=(M#+#Zk1!bGw!c9A<=r)L}0${nWU-jTKmlnXRUzYRbAi3mb1*0{&{ncm%rTb}!dGuAlSc)uJf&BKa zU<}Y(=T?AJFWnI>( zrCdW|Gj*9sH3~OncMI7m$~6y`Bi8`6vA!^+8tJilG}MVHM#a{GT%BnSv#C9|z9z3l zIQ7^D;E{bYSLCAi@2!PDzpQ15T}Oo&zF|{s)mg_kgj$~I6$fXVXojD!nI7cU)Pi+j zRYP0NgAd*mWNE0$JP%L;@_8hh#4&r!tWFNx8<}Hg-Ai(qo>pRlX{Oo@xxyz!>4}VT zX)sY+@u%=GL8s@Sq>ve}TVv2k{>7vYoY*cV(?-z!Tlf*Qr<51|UUl0P{o5 zj1}j#)nt=2X#?7o-rScZo4nSV-khik?z~niX>P%{)QRR671r&GA-!%f)1s^-P64>{ znk$ne;;fpPA)#R#>15-GD6hPxdQ#cf^agp{W%3y9xl;`Ommbqs#Jlqvt9c3Z6S=Yk zyhoIfwV{MzKm+Y3fhDCcN>GA&dd!2PrF4A(FF9O_6$JJZYfK#l4U6Oq(-hI)^?Mb= z0B$WE5pcO+PiR>U?bv9$m%Qpq+GuqcZO*W~7*xr1YPyP?^+hr1Lz!k)gtC zKN}a2S4pRTHoBKbAihmNOHleIV6%dB-D-7SoVJy8X7L)kmS*sNt>JCp{c0r{UY+Tv-Lafe_u>sBvT)HA?H! zHeh;b-J6zyrPv>9U11(G?(H4Y8Y{{t{4YuT!S6=;BI$gNo5ffF z#Q%K>$XpTh64<=>64+dN32f@?j!CblukRSD^OH+{HEheTtD!H$wmQmw8KEtG8EcyN zs~r~Q*CNmc6xJkw7mpg6@lr&hSAKOhe}$6GUIFr?S5TU&x^~>b^%(B_Bu#n6@FKs8 z3SWV1XI??o-+#psrn|3T%eP)JAHDJumHH~EwRn}JCa?0LA>N%I&j)?mujI$+#Ue+1 zfIC0dvj)g+7>=xU^)qD0=vI+MK3e71Tc4UAr3s0a?no7Q{zT}I39aJJ57$*sN|>&{ z1_7a}Uda{>QM%`kOY51-qqCUKiNQ3nv5AApz)Vh}Ob?Kk4BZnuiqvPeZwu}WE zqyuHB1i69Acms7F@dlhos7l8KA^zI+25k1zg*SlbtDYZQgdK|913>UY$kUXHOjK(43_QR1E*#mW%CTo(@ zI_&8>Ym(0Fp$~bqhat*c^Y3e?b=_0cd@t1|a|Qs_o22VyZ3`2%doOaDpi3rqy#6$A z;}o@z$Jml@Z1*!p>~jV(?ucj3q67Odk&xHzAS*9}lb&GkWFL$k zv)&kU-f(5Fw?q!pwEgJt)cxdj-fB5BM1HTK-g$#n_qB+Gl2bnARPKQDXO=kc9)Jy1 zG~tGkWC54t^M_5q&H!^-=e~b9!?uH1&B*VKt1C#*zJq|?dl2te`A6n5@$P~+)wyZf zEg+)gKgf*w2bo2;ZTV;&xD7#+ic&6_3>@D3)e+~H;4X;pj0zg-dQ6zQy z@0pJ2ZFuHx<{zrIZ_`CBc$hgewPa++Z4 z2RS2o2yxBRy+cqiSBt(hs}uQiwEas%LjG)(zicgXmKt5Q-Z_7!9(?8TJu}quee1ub zEB(EQN<@N1XV<@P@tLaq?;E)vW`@laxp6?Kh8;%ium9706Ud*WeTUJuy@wIQku#=i z%b%c!hpisR9s#3qia861+8!}XK4Ro_greKczx*R`ZSz@MX_US`0&Bi9nE^-XtupkO zdVm|D_)k4Pk5iLJnX?bWGcdCuHWyoRcMi9{b*Pdzf#thLjU0~RMFuN#lO<`8c5bq8 z2CDlphLr<|I0JUv)e&Z$Vm}=}2AX||R$$#+A9hqRz=QFK=y~-goQ_BtKo5 z$I*nI+IbvoUp$U%s~^L#MtA?DQfi7B8**4Hw`^^fh zJHL}YBSRNYU=&M(eWQ#&?x2{H6mG8zp|)^4O)~FowJDsgF#jZaawgn%g{===JLxQ6 z%53*M1x5i%ehio5-Gz)9zBdFH`f2ECG{#p8ZW>M$a!}G*W1)}EnGA3J%)9QMhG${7 z9HDZ)kNfZZK88?68Sg{-i1(py)h(k3gj0JGVS0%;%*K$c*{` zQg&QqsVVgXR3vF9A5}+x0MJbzFaTWl0oWh^fC1ov4}iOQr?rU%dh`MK&sXd}!HGrt zSNXbz!9I_qr;OkHtq+)^{C~pN+1g&y*U(u&tVj}c`JbTg_aR8n(CxP(Ob1mkT~~fJ zBo|C8xoe+ORrn!g3qGXmwRgB_2pcA1$%nK!Nu@pl?nHh4wYBI8I$_39KpC&;AA#98 z4wBlOu{y%L4u1q0w?3l5(W?2HozN7F(u8=V4OVQ4qidz<49)nMVfyrsDg9R^BeDYK z-z2f5l==xKTrgDSKS8!b)Yv=*YnXWq(uz;OYM^%WrZ+!!}s7mnoL4K@8@2Vxl}_&4qpZ#qJmy}?+iE}Is@T1&tO(POU^=V4=p}! zJY09(cnb=^J56ziQHBX;k=FLJG}BcR4_n@K;lzw}7zLg6)Ku=IYRCCb7xyU$^gC|M zuYmKCpOVvFd7pwji$?owRgO!VcaBT)2r$9%uv`0avym=^+nTM^`5Z-BYT7vfq-tOb zI|V6dp(7@}xxO`zW-50c<}_6;^WZ?T%ksF17Vxh5=h4aC=kd9X^znI$6R11{bGdaM zXHq}J4p0i}>uMN^ljts}r(qX>lC0X%#>NWjYWD>y)zKyMsI3uC%tW%FmSQdfJo+MJ z9(iJQwT32>#I*bI6RQ!`boe3~QuWZ)i*&}Uh~EAT2($I^Kk-FDmyG29NuSX06233` zFlvW+&QQvS9z&h3Zf0OvI8E1&!TL`xfo;8GhAV|rH2q~(5M2Kvsnfr(oo4?6*kt~p zs8?P#uDy_u4KG_eAFp%&vU*zhAL`sOb?TpCxKucXXsSpq!ClBv$qyZg<=us&JZoH> zLu9zb9S?5DeSE~pV^|lwrv_fP*5d{c<0@edhGAt?mH2||tvX!ao z*EBceYeoqTbo8VJS6|opgKsLVrxRbZrkm{fuw~+PWQUon)e7qp3kKBds0I&J{|2On ze8V`Y=QmKg@*4zLQ`^1)ry4pfk9?}@zb2uY?w`jk6%y<#z}Q70;l2V)M^(r&#T8&y z))G%fC4G7Y=AFF)TmKW_%l7BO1f^bJ0t*+3-*}b6aq9AoM@?ci^&KnI7#+BZFWP^V zuEFPB%cv-A_Dos}BNcUxY7uG?=$qj0E(}LW%o?Ft7aC>nuP6*t?ltfXRjG48rl}Bh zy9isqxCYAtuA>c39eT$yDp=pV(|Y6l<>QM8{CQp zDg7Y$C%TIUYOycF{q{HD{-PUjZt4w8?+afufG_H&`@V)ZMSYd(XLwW8N50T2>cwX12!&$L!m**~M>OMiwP2Y<%8*@9uxD{DJ58r}ODhP^V8o4(@QMVy(u zNlmU}y9r+LD%_48#kz|)G=-tLTGmA~AcA$Fx4wFvRYEwc6>!;boLHZow?&IU&3cO-Q$mv%)iiIDc<#0 zXSi3<3rebJC@RcS8h?V^g-f2##5twVxUSOQ4m2G^rsOHMSjQ{+ay-gFsBxE(_dKvgBb^WL!;5CRdLQvMRjJ>Qe~PO721lBx zn|U-={*Q)(>l;bGQK+GgnnDfq?Qihn`fs3g|4X|RxxSui|BtL>9e)ew5$9fCSM&Zy zl{(sD(rfFKd8?)TqZVLIIerHXpWpGZO@D{->Lv8!v{X$C$v{6}{2h_)_#OLuw!ut# z*E5_bwnZu{=nskz1-;nl%6dL|78^gXK7l|dv=y(c%{C*B-~u#q<_~Cn`UkYe=>BF~ zGFnal1VofZ{7HpKjo4z7xy5*yZ6aJ3$k6#eF}`-o%@}@ts75Tec_G|9PhFRGd)}S; z%=0H$d&wXc2Qu4S-4~-{Ld+*Zu~^e?N(c@LKOsod=}Uet`0het=Ky_W=3lJzy%Z#H77V8uR6g52#&6 ze^QoJpqPiqC;A~k(jSstN|QA~aOMT?dE z2;%ELqQ|YY+w5yBTBt=PY2hRIvFj0jbjKqchjyEesA!&UnarCeDf}@Q20o@(**%7B zMYB1rWUX5B z3G@tng0kd1q4lLtU_rrETXmu?K7qv(bm6M?9OD)F6e&bJ1yt9kcs7E|T{D6!8p9D! z`p|VxVau_nsKY4j_2i7y19F%)M?a&TsAp8|{)}B!!#Utd!o+7Z?B~x%4Y)H@ho7M{ zLv-z#^GT_y#aCSB?D^gc$ag~(`QK*~2+C1W!%DeA(a}No>1Ah?a&chxK0}mErCeN7 zeV>8t$x^QJ`s%(JvTle|pqHz%0=!)QO8m_*bwi9&f1_r9FBi8`dATCc)wRDFGB!kN zKRNtCTfJN++DFzOrl;9pPNGLt_S+DO{j>hgSqPn&%npGB_l6LyElmS!O1s#CQQ8%W zV|Dz)U>wYuV4C^6G%Z&zLmY|Fn?3V zm8h>xmS0)u^wTCgCfnevV+ZLSXwso8e_J$tINu4H-W*c4??n1AO@39@708_9{zGS2 zNjcC;F6W9;QaKmnwsHj2PAdoDdmmc%l+xyMt^}_QFL1)smB?k2fEL*3VRH&z~78FjH0Rce)}SFf_se=3N~yrxjnu)b_T; zYl?Cmv^!Z#?XuDONjmVZG5?8rVk$j$xXPD&WjgNltej?3)k1L4GHyHKa#+xWMn9vhkE+Cyfx>TSz1~@T-*F8 zyVVc;dY!QAFYAZu;hP@c%(|sNj2f&u{;o>?gPzYV8*_@(M4&K^YoHd8#YAK~53V7$ zR|yg4hr=}$%bWd2>-*`y21Z}`2Jq;k+UC();VhpUoO|gB9~m&1^@QCD0F@m9u)h~e zK|t@JTLIwRUF8F@o-}oTnek(+dwsW(6PAHpl@&gW#R`HKSxKFesUS_N9@b!U`@%CfZs7(i}Qf0VbcUfQG)|W!9^Uy>-fq zPTEls>;7YONQhT4ArU?|8d+RMnH8y2T01L3h?hE-7>z70rD^;Lau>hgLB+(G=0fU> zJ>j7$9}I*3Sz@h!iLRGeW6xA}Fq~Sfi(BmbBAqkuTq5snX7L+19_ej7`iA*Rb&|nZ zGH<(dwqdT;InnyHPLM0^RX$kzoOq?5oGzl(mbfT7Qvq+;#hMK>H2rNmo!Ky5Q(eev ziVL;ru)(4-RqvV7Q*@1ou9}=sZ!>=0FiF)zNU9csJ`M@NU?wQl$0EaFoDd{1PB}hi zG_zr>ZkhKnst`(r@}anP+Yop}OZI5_HDoCH;@(uzR7% zx>A@cLSbR>stf<{!;>!BE_K6TtqTLxT9b9mWDV4pVYE6xPfhxhFu)A{-E>MD`l(Ae zNu9%yc2>A6MAO2_d@&p?>aAmBnKKW6Sca#|JA(I~sukg?(|nBpAQ9``P|SABevJp=+cmiT)hy12>z;RRAxgL1x5m{vnD^a;5!ir($?;% ztVlGagRVR^3b~}l%IQp83>vWu}qZ9`k9Xk8&Y*43i+Oog4|}WJHjZ`+(QzD;wMCz z&-NRdsd+TI+f*Z>@eV2f*PGy#bZ{%f+zm}wR)c+SM#JeV(Qvwv{-P+u!>AZ4HsJgx zjkJtGTJP;Lo%9B_1icbr*2*>{YcH8>CyxoTs!~S}Vqi#Z#l|A5TIvwXTTM-lrBDqO zn#AgQ&m>kmbS>6ZrWEV*gYEim@f>A){>)aLc*@OEru`mTJX4wR;I}y5<)gk{<|}{k zbe$oI9iDg1W2#bqG3+m%qG7+#7d1|ReNz(HOfx(I&bi-A643AQ zinwjfnD0x8G!U6cHJ|^`Nw!Qx#I^ooXe}PCJd>H5NVWMSL3J_l5Ijr@!M&rS2Oj$Qia>9UFkDycGM2Pln) zx>a^@K?GNZ_lPF1pEjAqjg=A7*~$p1kA5_Td&{p1k6udVp}JKt-o;hyGGB2|WmbXh zJrq=nj&OSwJYZHW-#C3(1?nDGp`Y)jPsoBu;%AjIrd`}c!;=7qLfcQo#htV}iJ`%p zNsJXPC($ei&(1(uqPw`g!m1)BZiugnmb6tjkJBk`qrVSXQd?_JRTO7;Rijr`xmEYG zsxH5hY5+;qsX|+%g<4gka&x_AKgtz1<1$k#lBU{U4Lnk`cY_^Q7dKIB(-pz|#!4?| zk#3|;)hR=;tm?+eRY%mj%!fa4V}-M&?b(Y7HI#%?zfv8>TuNfhm*6h0t7~;^S5jO@ z={2CCwjwK7@@uJe1*6BsH8tLoQiDL-xG!p{RJboESBp7FZp&6x>ra`26>|WhCTLXA z>owtaWt}r`mDJrX92B!&Sc?`Ch>c1z*Qk1u2Cp8Ofv% zQ1^+XS8|v1*Pdiol6EJf6IYX6F$@|WC%dZn^})3yr?3mOegiG-$YiIaw>sAYLNC>w zVpvv^uDP9z=t_EOODCjqs2+XTXPwycbG07kRr+Nvyoh&~q^V|oTI{Cu`siNI`V7Uc zxAEl~)sikHZG9OkmT+UCDZzb(^&$G(`e@h>!GXqsmvm6A2DHg;p)}hR+mQKVa@uOU z$!VkWU2P8G3(R{f1vLcwmLA91z+8uNdONEHC8@g9z^-GIv`|(QkEsDl1BQrvE>CRjUb_c z{?iBzsISMA^{+<@_Nr#PC2c&Le&gIF$y(jO*Q{NaaASBQ4=wDFYYgmy#(m?kSR1MDPxsq_W=}l;&nv&~NnSxcdy$M}Gl7}3#B&u~o%Qa@@CMRC~>l;fciPI7T7VKhmKLu9A=omhRO>eOH5XKsMCgsCpv2{PO`+mKQ(V*HCib&mNvNjP^E4TvJ!y#X!xC1~td^w>obI@g)w`YC&TJ#XfK5VI|%=b__c&;bQF;;9QoqVdJ7o%IJ=H zFU@kVF{l!*8AwG1nxvwPlTsPg3`@o59J^pQ(iCTDUn&jlO-0Xt+DA8nac1fc?iWIe zIT_IsrY;gUjF>TQG1m*U1o#5o46*)bKEo_SY4JQ_oVt8V;csuYqDC79wg%bO+B6aG znCMn34QWlqmTayEQk+|<+SM8E+{9(A@(oPWgR6 z(z^plw&;L>>UN;e%|2$mMA6FX0K_O&?`sS|T*KZMvJ>25UQUkgb#Rr{@P207pu&{h z&%+arPFjzq5Y_VhaS<~B-Z*usBmDlXBkVlh-WsUTLtHEME2vc`SE9c;Hpzg_Tw_sJ z2QOP|SCG22hm@6_z;a=GNZHj1kzMY@bo#SSE*~#0K6x%bmS;MHvM(W8csSH~pa&-o zoeiQPF^}-9i~btuM6_X>EiM! z%LhtECrjVriqw)UUG73VOZ2o063JB4*49%j)(Fp^MViqSeOai7X$D})0>yL(AspCz zecKh5%q!_&Ys^*kZZNc3HwjM+Mdp*wJRZ)ZbkW)cRO-@!H z;Iyq39^thS&q)SndOf#08NJ|u!5ij7+r|Jz^re!&TJ?n(_FD8d64~ghbtc)NgMEQ@ zpfCRa)n2T4|EDi%=+_Uy6YHv%qpfxn%)mWOY62L*-OX!0il$d^hN{;?u{?V zr$3zZ?vI_f=f=_=@;Yka5!Uiaj4;n zxOT|Y8?A_8_I;FE4Z}ru91Qh~2V=Y$s)gG#9(jaPlkpnw4u-WiP1Z1#8Uo^M2C}B4 zAxawpYJ;`0gGFtSj$3QgK%Fod19WquF(~y{1q=#(XRGo-4;g)lK}wN6$}*4MdeuC7 z=~Es$I~4EqXeip>6Z7z}v4^Hl#?ht>Lmyw7%&N|aVW4$(vURis?-@pQ?wzCz?RC-9 zVXh>Ogi>B&-PI;v zmCvx_txXQK97&dsT8%fYZSvL{^G?jnkyI>8Y($IBrZRdo67?;u*ioc=sVeCdFQvLO z0Tk!n^n&WlHxM>vsrwB3XNkTT1t?BNj>0?_D|R%GMe4Q~0k<4&ywYOpC>AJZG@$3} zz-WrI)aijUSLq8aoH>daB^dI zZEl(#oA;@TA4>yM^y_S+7#k;RqIsXBJRXjT{}1lz_90=~Hx@y@HlHJl035G}V*xOZ z1D#YDEAIss?ig)1RL8nEj#lnCs3Po?DKJtuvV3FxNzZtG2DM(v!&oEfjUyB>o`S>G zVmttc>EwLhIId*dXpTx6s)zvJqJnjGL%5g4%4XwWT^tWb2I)brZFZm{Cs28ST1}v9 z?a$~Vncm9;S}#coVE(_cpVpZIeRY5WDD##Dh&#r;v9}gy_{JDCda36~6b_G?u9g!i z)KgtXS>Qe3on?1-?KK%`x?~>RbakY)-i=)qISJrh)M^sxopoZNWo9R>G4CBUeUu05 z4!Sf6toc@*>yb)3MNOt+TeY5yHMN?IpP}^NfUJ%Z3$_t$(}!4kvH1X z*ictNQmIp2ehm6{{wE5rU!P;1U{~+|BkH^ZvnrOqe-mmtEzc9u8#N&iTIeM79zbcK z1eD%Fk>2F7ARR1xO;3RIkbn(oDs}`xuJ>9%DSEG0y4V$g_p|%p@BQnXvuAg9c6N4l zc6N70)$>6mQJRy5{)4PQ4M!* ze#%lSbEUH1F>T6Rp|{@gj`DG3K8XDa|0eb@PUJF|$?IK%Xy#J2de`8WxkQ&2(t^jd z>|I-Sv2xy}tx>MbMH;qn`_opo94GBb4GDGOk}K7Y!BoTob=0?4_F zeA*3S4!8OMk-9jrPEBrWvWb5-ocSCkt(w;vNGp z;%6T6j`nk9KI)#IfzqCcq9%4$<|E2{43cmi&E%Y{@7y5LF$!4__=bDYjmJc#E+OXx zLKq=hVqBTymAwRF|cEmO}3_YQ2;qqjhzycLbyy#gH|(-RMI{ zv=IfF4{NiL0mz|;^yX4V^+>X~Es1BojA%@m5pJA~Y4QC?L;m54Uk1=rjaWwWhc9CZ zzICQqf@cm@)l4_89M~X_*I>7ZAg09R@-Uo=ETb2;&ain0s%nO1^UMKCT@JkdYO@#? zh;U{0)9Pi0KQsI4*mC%@k1p}>F;>yPuj);i=0HmKQu7s*OwrI4&@NdE%~wxuq}tLw z2)`0$*2bCL_4Nw0BV+$`8*2kjL^13$yXx?EcjF1lwh|DXwP0mnv@%wLXPv3u!M?7{ zqzCk1B)zr9RN9fCrBu^F_g6A=v*p6(Y z>r3qm4r7+tmjvB6Ia+DlGIy`VYlM}PnQ@x88W1hDb2TG>$7=MJw^yULG}qTA;p_t{ zH`R;G7^co9I=;ff#DDY}V8$rV%v0g6%xJy7hOG_arLF;Dr0$tVgpwgX6bM(pweU%p z=B|as=d7iooVBcsLNsJModNBFwQU>bm@n5dVW%wNTz{-9Gf3yQp$E`aPQsExu+(*| zJKMYCgu_&Uy0FR)1cJ}4qq>F%FRo*JAm%IXn)IwG`o#S*St;vb;dI>f(vWCZ)+9Dt ztsuynh?jYrd4dLBHiI;4yzZIIX}Wg8a!%Gb4RX=gvC42+X1}xF<{Pc31D2DrM(MH( z2Esq~3$`^`4-r6ytVr`Gz-xpqWxFdIuB<13l&UvP`Y;X4wUCC&>q)+csMVAF9js%y zC{n3ULZz#@W(v;2jhy*|8#(jnuhxD(C@xw3IZaQ9wJYN1Z zol^cZ{nbS)c3X@)D}T4Ushw1B132I+=sR1cqsDItZ0ctm!Z2@|iy&?BDAkfMb!#_Z zt^4L>&f*zs#~(;F=} ztCcFu?|34QQg@sNTy%FtONDNvK`qpCBc`n8ZjsWSEitZ**1p6HYk#@n-!zbO>|APk~dKk*GR4W&WhBgO@N6|wfP&ak~%(y z;lgyPj*sD?P=#;ie~6rQeQ;i|83WMJx;~8%g;_X?;g@!7X7Kkr##9mO%5v)bX3R=B z)~RKS2dc#u24M3o^yv645Wb-n*0x>VKso$Dy?mp#4||7O0vqbjErCuOddhA2)QC5& zg)7TnX?1KFKdlEn!}h)!@uTfO&M|KVac`a3%EIXMR_fXKsvUJ%T%xGq6HAoOtU5*# z+B=CDB{4Aear-(odOq`DF;s^ z>A}Hhf!WCq4s7C*t78P?EW4*RKMVi#P}Q?^(Y|L_~ zC)VyqZ{s5%yR&9JN6R~D$8+$i5#;7hZ;}>1hqvlTS2mLTo}I3;JLoQ1kYFpnv8^MD z&NmiEg!uCib>8z3^{;QZ@%8NUaLmc)A#ZDS{nijP8*j7U+98+SO08dj2jVr#JmR$K z1*&hU_rF4M&wqij`s-Ileaq&W=GVy7D=!3EcMRXxcFKPjWAOcV%^1vXqDi};C60yO zvlYas&3oV(?aGeUsa>?P^@rZk&@IwEl#@E4k<|${Es9V#S+<`n5D3%Lf@q;C6O9Ye zY5wVB1$uij@~05jS2qPx4SvOhlO3ckFOtit^cR8P(B)GoB&S zfVUE#H(ZzPrL-)5)a6VU**F6Hye(E+$K4rg=~@=3)l@(>_0~`a^YB#R5lbWwqQKC+ zb=i!V-;NkEXRTBHqmcQ-Y&!2=HoM_#H1Vi`nYCKoa;R#RrsM!)r8Xa<&{_hVniHtHya8ifO~WVZ1M9%~Rs5?lC!6lXjYuy;*bI0{g%gOT|z!Io}qpIR-zDbEuV%>(;x2dsfrBnu@mc~ zoEZFjBo_o;K*GEITy#=mt%k;{U{0dE3n|-1tqUOvr}=97m<4rCf>swo_f{(4w^#fF zhUl!xCv1aq;&jCnXsLkRWNV?f-Zn(ZX|A#6yBQZwf!dS{r(|lP56oAruJ2}8UE2-C zBlkdYs)<&YJ>-wlq&?6wk_)GSQTUy(3M(w$`m{Zil@qQ%)?4^t3b$e_Csg(J0uvYV zH|&pKRl8p}F143BgNW8)e>fF!lYahSFRXcIFZ>XwSvL*yf2A8jfI zHE&fH!<$vbC=S;s#8A$utG_-0(9gvHiYuWHYiqz+TN56@N>CB#k(%0GLh%|}aonmY zIi5Oa5j*OnA=eUSl)P)S(|oPg^7jn%>{ZHr z4<+XFQkr`5J#VMKD|^NN2ZNvE)9erfWx2fHx8rk}65KCKwY>}mSn_`i5czGGSwm#A zDgPYYi`-tUyJd9VA|gFPtA*-c4h9P}mxtz*8|AW`IdeV-0MK^({@z`Mten z4R}l&(`PQ&d_Hcz&lQor->xhfwY8Z5BHMxGO4R;LD zg8x|D1|R&oIxx_KV+*bAbkdNJo^Gl!=poK5dfeT(jF?#Hx zIb@N`Et@lN@9QtYMb};m4Dt4Hi>t(r@ZsE0<3TFdn@gyW+e@i0L)^M*T?OA|yiD7c z1l2NENpfrJ@XO2H~ zf2_?2%l(J4$)T)QFg2chB{0Ox9K*JmG^GRUF-F=N`Me4c&bqz|I;%A5Rl1Ffp(b&K z4xk4zQn?svz6qXb{w`JMABF-sOO(Qk8H>pH*P!lV#sAmvOwJ~p(e5D+u3~c_g6*F_Sg=B3$$Vh1aiZ}E(Z)0Dff2e^VnkM&5;Pur7`Dn8p=XYeb-4B&A#1A6 zny+E{)qD-rq-V`w&KaWh&sxF_)|8_#%OIl3TKW%E*-`Qj(CMSB8~TG0ilV)iC67I| znB;T%sqrxy*H=A{k&%Gag?4$B)0;^hNWFBqz|ua2s}&Yxvf^1y8Ekth{0)lskPk~H zKy_D}-R?i#w9WkKs&pS8WAD!CqOaZnJdsY`1ZXFX@0%~BShiBeDb{)s~`1d`0Tu`B8Hn6T?a@T6majILR1;>H0S}%|j zMm=N_SL&ikT%o=UIBLpWuDG}9wU%$wjg#JHM#h1zenwlsQE7z z>=X_Ag}HXgd*EO89=6JKD>{wuO$-};jrGQRsMyY5jbO~3sMf#QF3Fvsdg#m~jn}yM zftRLr?^|9iHeX|P>V4K}WAwB68m-_D_%})^AHa>tAHd&>KVSeoq^%}>q+TJN)&Dv3 z7{2R6@K4p9vr(-0Cg_(K%(l^?QsF+^`!Q(W#~9sZCu4$=ivVj#{_Yy)w??SAR6 z!6%^8pcB-$>I4G}`&Fi;U?1+6QnI(cGLK%nK7!6E`t_h0&AG{3Ua>DdweTbGUGNd* zm%eUP*xc^g@w#`6uPfJ_FM;*j;(u-b6P%yP?W*&yTi9K8G5Gvkxt;$n2d;<%ICY&DKJ zo2XT%XftlPPtkzZgp_no6$zR^Au_bmdcYX|j91Wgn-r(+*DYjRbAJp)AO9G52i@?R z>*UAKz8ME50Lul28-qWnBFP?_Bk=oCa zoMD_B!3|WlA5EBEvnQR%mU(AI9SNjyVfy5Erm2}{kcK&D7$G4_`wlcI6@2i*8O9~z z_Wmc-G(+D1!Wt9d%A4+1;#eZxevaS*k*>UH8kWb@HRCK$GS3DEc|8gd-G;;iKUu9b z?-6bI-84FHiYk8xV@gfd!t>ry{;s@qItDF`a1;qi+WAbNQLpkQ>F{~-#kle&YRf-i z$_cC;Erjv<;-AnYO?S;>oP2f}BIb=%;x0Q9^2Q(xy`%jBGTPmlxZg?o`;0&y-o433 zfrpjHi@x}j{`C15mWYvV1|hfB_iJEQzTQ*3!H{%`9Hm*cKsW5Ap97MdKxiE!~RVp2I}%zi!FA6f78GHb^PBD zx1Wyx)3&Xzyg%c+j}ks3cW;gQj7+_>$~;n3XcCk4q50~mo1eimH$Fq=oH}fHIIp`V zeQu$2)5On#(pBp}2b(TB^|@_uXZ`TGtsD)EAG-B9m=E~E$dSB`>hc9+u7f6iLCN-7 z{{V>6nNNHXQLaMi9C<( zerW1b^ax0qZn6Sgw~u7Z0Z|M zU)uSy1IOT_t~YG#nHQ!zX07|dc_yeHr9l%Xdh=;zM{2G z)!)K!k9FlaxXsFjY~TakGYP+fH3@Zd>nkMoDXuJlbwee8jS%bkHG{p;H zucrfF12#Yb7;wq!uRqPVpCT?GH?N`#aDj&ocRYtaMKip$;Q}n-r79jib>UyDVke>= ze#Mb&a@5hECP!^WUF6JmEyKH*c!+{Le12nd9VV})=3WGyITslPOV44z*?!TC;&Uip zuU-tSfABg#Jdpl>U84W+Om>;sJK{0|_@T>)iy>TV<#69%vtvkawoSx2^m}M)(XRYK zI>Il*@jP_tvVs4-rDuMBwfcr;VFboB0on5VYQ;CKB9?yxneJG#Reo=s_y)v#>4$GD z?`QvLrhxopb^q3K|Mx!{isko^-%s{OcU7Ao-IVr|6|?zW_1CvB`JHc}SNwmN+&XLE zpEheJE%+1p;L1;OcT?MTc(K#*M1p#QcSjxl)38^52VMLRShm+aOz(WRQ}h2)Lt72| zFUg6Tci$$r(N1HKk96g?*0KLWBz6?Zr%V53JrnRJj;)psaoaSy~?qOp~vWaBa~ z#+Bbv%fF+UEtLNqMVl)FE3(0&nZBnCg5UptG{WzHG-CP7-VR@?d0^?~49oFXh!W$< zkI`x}Vd*XWA4Q^+&)SUSNL@4Egl70YFuHcQ8F1~i=0=?mFW`q6ouZvCe{6J=e1bH5 zPc>`4r|aMOB|Ol_m2aHqxR(iuPc;nn%x|olWMR?%_Ywn#>ND#YA(`(~=PMxZ(8Md4 zHjP2dU2y$>4R_}^BFw8LXhVH`g|;?;Ds~3QudnfC7FDhul)>AbuTuZ)t4v;8^umat zbysQkq4jnO$w$szrI|jueU-uRgZXvjNjnbmy>?x(JzH0kuYpM&4ZdP)tgVGtESqpC z@EWwJsiS-|r1NVihnxwIoi}IDWM%^ zt`_VUBTZH-_y&W2mAc;`?@CR%K@BUk;RXPftMW!*Q~zaVys`OZW;deNME%OCqP(U0 zgMa9vkvAEVkNsa3_sBuqEY=+UU?kXalY9$x@FwsVDBzlRthXyK<3RxxZem%BD4j3w zPYo6G<|*M*D@O3pe2XG;wCqzWC}%6zorAM8yzKfR@EdliXGLIIk8%}skk@UhYp(?J zXr~<^sPr+eg0@<9n^jKYgZhk|&r+W+9D5Qq5-xajhjoYwx0`z&X5<&nt>Nphe zBVF0+M?^%twnwm&koF_;?u`f^bG)>mr7C`eSS@tcJTQcXp{Yc;3YsbWCrH{*s{4>o7*Mgt< zjV&yK{E@DLP#yUh+Jxxh&q$mLKcmFf`vs#zW3~PTNfzYh-Xx=nq%_6!Sm4wOe!$)N zzXV468p&=b!F6)ZWt<3 z7qA{=8D46#_$#j1Lh;k^VhhFh|7WTHt{F-NJ{pn(|Hilqyp{eN?e)^rztPINy73ok zT_zEI~$bye&>W) zvoq}IGN9K%1aM=P_~fkBgYt1l{s&ZBqn>|IX0=vgu{L6gLpK|#_?bU|d-xCTOs>$2 z8|{!@uA}^6_%9=5CqX8y7H$O znwUHZI{O0m$R|qDT^RV!yWrUBUSMOd@otJ@{3*;t zXhyj5(=_KEtUgZL?vZorJ^1k59OHN)e~d2YxaH$$rXEN)O7runAmTnM$*B7*Jo?{f zGF^QiIXP07^2tk2jL_@%0d&y(x_&?K7g+vAJ3B-QL$UOj&ACFZ%XTCw%2gPw#8^8X z3LC3cOCO|1VUR|&G-JBZskb~F(Ok-P_-Ic{vng8`sM?+mbLKJL)6rB1CmD-SVFRu3 zbP(&n(}B}IPe)_orcq*CH)Gf>4AA%dM2`E_pdg-aTDx(3Qo4^hF;noE&ex{E;$3wdv0i_BDQ~aTTMaP$6)e<{I>1?=uoRkrtjpl$ zEr90h%{nv<8Qt8SK3DN^Zc#Nyt?N2seP_dkOfm#GV+-zbCqgL4xC&-zMP0znRDsDd z16gdCkjtm2pJQyzq5}CJ5?}M9lR(+82C{PxmZ`hBN{!L#o^;# zj(XZW+9yb*=Iv$k_KBAxK<7pq|BwZf^y_GMfr%RA?P$iD>#c59&X1RGcRP9u()5Nm zu*az|267-!afC+SQhJQ?>eDCGKYCX$!yyHuw8F=5h>zhAA4g-~zkN%w0wp%a9S#x} zjMNqKU~BOAbu{rA{(s_^V{0dwN80#0{4~Ya5sdD++Lw$&RY*n@Pp^1e>tOjcwX9Vz zNcH^qgV}*U28{t4?+2>=mCR&?(-~N!!VlKKE1DmW`eo0E;BRzb#-povBYPqtbm? z<`u4121&fEQgR<3mZXI%4O=iNwe6te)eVA`-T-C@it%B&QMg=fV%Q3+FiBHm*vOA` z6)x4E4d6wNKQ?qU@p}xuGmC=ua1{~CXVx_b6bp&u3Cpbc4p@WL|U%YxM-x)MkwQ{?Xe zxyhQ=(dJCoCL`gfbduIOKyxCObL^i9`p7|n@w#OmY4U#{9LFiF6Wv9Lu}XJRVvMfE zSb;cN0kJ;ZSSTE&Q%>0Uq|@Q8Kb;P9G4{&=wv$Hg8i;DsCCK5gwgW9*!!^t#J!6s{ zcP9-~&Op=Kg+p~e2p%8eZapODY{zfrj9cMgF5yDCL7LwfBFt-y91R*|;SC_5Du4Rx zLSu02r%Qb;Zx!}cTrlnEqv64nNDZbNy!z4&w4;{-`ZHGP!xRE7K@GYlS>Fc(hVwEZ zl)?c@h-KvU?JaG(X|+l2szM$r2m$v|lPvdiRt6R7`w%D}914>s$-6BW0FvV}p@8h5 zb)mrGqN}?HhzZt|5+8(8qP(e(6MdpE(LMXMPa>0VkioHyI)%}m)=D>z1U(%Fj8@v( z$H&|nE{unvjpD~C`N0i2Hd7d(jz*gX&1gD2+Hv2-Cvm%8aw}xv-fw zk_9Dl=NQ|%CVGt*Q)?^(5=Q(z9BRcyI6}B+3zl1Z+Zij07^99@zXxXq5{fNQP=z^>MD$a zX{PI#`8`eR2EiZ~qo{e%U>_#@-H)nGG@aNw8cCcz*wB6V6s?X1$Yd3mKl$d*nj!Yj zBwdfDldeV6N#QXLvq>>*nBmvmAT(8>G8T&43@MsLq!Ab`MZkQ!wj~Moor(y3)YNuibs++tA0DV|MpZ zWm6#bR%HiDM7wr#54I^FQxx9J(ZoBsMiV11+P6%9t+gsZP^0A$nn{|0Ahe39?Q`ZUZwqXuvL3N2lQG>~1UAx<8*m&mJ z7g_-R;}#5=1m%slWNsz@mX2ofYf0DrG2SrU?l?`JVEcv@(FDuByIUwD)pieuU|PcJ z&D<@3A33SEsF5)N>~8vZ8g5VQnabVlDaAQr)FqC-n-k}7QsLis0tnmws&O^3J6a{= zVX1U7j&6w54{?qt%mc4?LAD0OGe2DKVp%Lqlj32qiSgjsv8zoA(Xg)2tSFvFor{O- z8tcWbJ}ixQ2btLem4*JndBf6BW1`#bRF_tCpF@*dQDLAa_J=m4H&VGtZ>UdNF*eS$ zLe4cAV8=jxg(uLV^)zdMZ9HdV23Vr`Ye#}3*4vNfm}-c&oOp;U4iMUxh-R!*0qY}= z){Z8-T03g0UT-*xBrgpm357B*mZ~FMyX&Y;Gs|_giJ}No*E)EyHSK`ue``ZV6zL2* zTkRR4lteHYu9=CXr)ryd43qa9gU+6zYBR^SWzUdZZTT@+P1{1^Ie}4-#!pAGK)5pWfO(-zT~rS$jc9Bl9qIwjl&fAVO_V ziq1U*R?)6K$vV~!$USxMAw!=%Jyf?nr0uTw_9S=HCv(l1+tXD?GVBQ2(?!|lPiGzH zp|{#QYSuDCsFUii4>JA__9V%#0|<2FDu5f;4jO9`+G|Y*AhY>qzS?SA6zuU%2iW7! z4iK!3&P5rH-P2kg(Uv3$O7954S`qQjq86`;j+BhkCnlNL64783;o8$ep-B+Fxq2q? zo0y~RZE-G=C4ne0N6jNvpCwUyjQ%uvqt&{h4;TLT7;COEDq*NYXQ*-pdG3kSS7R)I z2yN>`$#8j$w}^%5y!j55M`!8}(OI`l*%PdA)09D-Y09S|4x%4;( zdphcPz`!Gh`Wl^OZ&xnmBK01~?Y3=b_WI?xxoML^r!>ABVO)Le?WD+K5k|4uo1}si z;C9r(JQ5;Ydpqb#3N2+lmKtIt!QOUi-HWbjs{`#qVm$XIYGp4fZlnBOlxwZ+xo$uS zTrv+aTN-;?X-XH0@)obixQGZpsxeLk&Dtyp zVqv4KAL)(Yyx!YEc#_@_@43%wHzHvC-XU2GPD^MyWu7~4FgvFF}!HSY_~VH(nx{GnRNmlpJ;=X{=yK)~+}R`TEo+lI!w zTDqGMw5uP~z)MgZje~NC&9+LcQ@3)fywc=hL>zZUeT{*3Pn>M_uM9EJSaTSxQxqj>|+_Xjoz3Gv)pYu7+G?llP?2hKHge*kRgsjVZ>W+Af& zVOt&1o_q1xKMF6M+x>T12QR@;7o^7k!^O#x=CVjDn4W|4e^?w*K8ROcsP+5Z! z5}AXc`^mwMP`zc|Hq0^8*q-?c7~*K^HSfV})m9kp%n`6XbCouP`sZlf5TMQ0WaPCO zU93tU<;Q$GxWp0|cLYH7!OAIwO5rmNFXa!=EwpS~>HGJVpTq zq^9VXnO68sR;ZbJ5CG}i*>yzwO?n_55FwZq&c4G%w8_I@sb`0wlTJ|8FhtCFlgF$8 zxz98!)a>5uNmJxV_p~rhk*Sy-#=7&E!!86r>{`bN$1$42FBHlhsh~MZucgvq4LPEQe3(A+(k=6-t2gpOqCJc1C}|X* zwKebQh$xL6#ZZacfCvMJnw<2HKmr%l&<*Wk~aq5 zQoY;Nm%8^Z(bcZLO?Y`sx5vQLKa4>v4CrR*wU=0AV}Z0#nJYsKhwfdVO=D?IhVmap zFjbDFH9PMaHN;Baxe6NxVsn(t!(M=d@33&w!4L6iba7Z3-PhdH;>`VBPv2_CTm=Y z>7u>q@}Fl!=p>!p7-0s%-igZF23LDNPc zY?v}8Ldu~U`c#COD2C|FCi{YSw=t9fzd^euk#V5rwTpm{_YTmxmTtuRYqt5*PZ!gn zF**Bc^DbHfnthln4dT6tk_`*pnFQCiOlQfLq91yP#Cq;cmT!k>)6qS(BOQ+Kq1V#s z=2z1l^$uQ7chvVlN4Yl{=svnMKa>Vff#J^j<1?w)OS7jyrMlWW1+L#>ehfMi;Z*e$ z<_jG)^G$IrB5;PHs!f3t;va!wBOf8#cMq`$h;$WuYR)5IHTw~;%6tUI-fI3X9~H`| zTBkynAwbbuZvRsM8gBpcSgj9-GEkBq1z`CwQ%BKCwMn)8R8bVe^Y5x@H9GczUKP-8uhDao<>iDWOKE88aY-?1NTZU)gikt4MJ6kaTU!{M5-?= zTr^YtQVmZO&CuLb3wOG9x_=S#)SW`iQ}U=}I_&c9x5i*l^oYU};e15X6ot>AlCT+& zs{KXg`l58rG$}J?fLPWH5SysThLo?KL2JL6f$Scyh?*qanE}9u{QQm4u88|yGvPDt zd(DKJV{~G@CGuz;G~c6i-u!)7$4`Ys>)uQ%Tl7SjIT=wjQo)Ia?}|ofq2W7V4cE3= zV6b%-+1`CM$~f#P8m2F1L6f1xc7=`Z&Z6q}vq5gK{FhkPFB+r;vniD^o0ZPGr6FOS zMFUj*41IcVHi-YRIl{paqN08e%s03JP79;8ef2{^M0gEq)%=%W+@jw4x}7f$ql$Ex zZ;v8fd?}=1Uf28GHD;p zWhvfS=MIK6@hs{jkJm%EJ~EF6ykCtLN6j1niFQv99kga1c2TqNXI8{lgSo$TU~_%b zXYKUSJeq!jlDp>9@isVILuzV5Ybk-s&E?7ikc9^#hcw_VI;v!Uk~9Q%3;P! z@kHf>LMo)j1g_XSV%RWiW>&*&n(z3W`1Slq<79|0BBOYmB5L^>vr+L_`7NO{e3yWw zZyiIs;?Wwvgf@-R<2-Dct|9;BXvx9cq<|7}+UhUww~ zI{t*2>z4s@<1%3OQ}U1K0>ypx!7>J6A6+w#-U?U_I{wQkIeLJVrYV~Eo5`50_4dg< z-Q^ha@|M$I>)RrF-&_tI`!|m;r}vAysqPBkbk+O-c%{V(NHA#y9o1Q{2hhulSJ0c+ z1MEy*oTNW~KU8dVa7`u2ur* z^OcSu)=EE+Rkv2s{5|<~ZKt$Sw^d*fugR-`5~tH0tw1X#v_*H&DqRJbgdTwT*u1^_ zn^`6l6Lhc#Kb@;d%H=0Xcx*jk)&<4Hy<1I}Y*-EX4y|TN*|(bNrmbeuD8`xf>d+>h z#gU3w1L_evxjNM7bH(AB(1bQmUjwSSYuI22{aabZp=~9)WO0bjnx(3=@%d%~K_7Z8ypmnsQ zNdm;CV*+&F3y6@|Um3qzHK5q<;H7nDnL9z>KMoq><+q+kn%>F_HOsY*rb7RR6#XkWWgEis_s51Ns2j1_vka(C& zE94reL5oeU0ot)R)TmG;{dK!mL?rhsOZr)JjM*>Z_ElkHY~&?<)%;1&ZT2Lz9rq;c z(p#V03*oTtlL+6WmzX~&m!h}G#1Y1BuNd90g#C!8;5MJ9Kr-ikNU&!~ccqbnJz)J) z@Y>@~LD<)xayV3M-o7$#r_9?c4nMl%DWqGor;#v0Pm?z6X@>(tz_h37s}9=yG;P}S zG}s&=hi^MpWX8JI*;w^QEUxF!C#Foz4M6<$X;5r#-hwyqHpIO3*g(nMJ?g@oB?;QF z0boy?pRb#r<>u`x-u&X+Vv6G;ors-r;Mba9wE?)%&wxt{b$*5c-02xW%`^$kwC)+2 z-&Fno#Xv9N)ZM>O-%6OZ`Xe%~J_8kkHzIZFZA2<8`FDte+k_=iI?db&o0mjt)kfMD zp~8*q&4z33U^DZTgz1NkkStUelMGXqgs9slvIVPUC(GF-jrBAMdTJ8_`S2#lRj~;a z+x4o=MV(EMu+C=M^qWa*W!}OzlkcI+jUApP4K;f+pc-)J7n@9dYXq^quJxbRF*30P zzulYRK-|Q1V-ERqGlY4zn=gW}#80UIdF z{dLu<1LL}+j#_VpJhk=p0m~h=RAAF<>VpmxEZ9oHI~_v7%TqT^P7mFFIm#@`Oa7rr z9YdQaX&VyYtyiLqNLj1OjzBM7qqFw8T4%SxYoBZbN_-MfidPaM8z?K(^L2}8@p7GR zLMx_khbZ~mA=LKmWR7cUCB>417q&YZdT@2u?oF{(x-iXQ{6v=aQI~MUPvA}}pC68} z>$;O3-x1DMSCp$XMVodqFgEUlG)H&RY+@84AZoZud+0a*V8ac47M--4dOpinS9QH( zwfoX8>UNz08|f;=ljpM#nXBCIw1t{AgE&7v4{;`v6yPdt_P3bDFyB!g*YSc_N-TsgAbV*Ot=|fEn_pngTKZ*Z zsCQ}1|0#X;0u;DK>)e-M8RIIA(%p0PU+^y4vL}iyVF(vNC@J~{0*7n+E*N;*E*SHS z8=Fv_Ckd;7hiFK!D*kj64JwpdLttr;3g5PJtJJB#+@_^chjKd@HMcZSIq&e3TCfTn zjUeuXs5$OMN3eGTxZD^^Iv@(uqtN+E>udIlkiVX`y$A^dbl^q$bN`DF`<+u9VJP*J zN4}NwrM`;HL{da#qWv!UIMi~7w|qK7%4wM(-@P+&0yk$u)M=e9QR`?;XJ4~zR9bsi z7K6H$nrAUoYAQ90Eyfy#V&)99j=vOX=G#(FwRzo652YSzb=c7PAG(x9l^3(1^X|j= zohezX=GmaTMnkeem(v2~frGg>VJ3#kN>zr_kFR9Yk2kX6$L0DH_GQE_Q)C2~HqQaS z^c>iKcn(Ba9%1~HmEhGYhd#*3p&9Q-801S9=|Tj^BLx;JAeSl^aFxDTu3*L_$>mxwG7klAC|+) zI5gNTEJh~_sjO{xyL>9ciE*k0UdCyF-Lx!5$FVyoZ8t63up1-c8e=8Y_5+uQ{Jt z7Nl*w`MAoQH4@#vW3@2J*LY7Ya}ZvZ(GjRAdqJj=p4toihAJmfWqawt3wt4Cef_!@ zo~x(uA~FXkCCS)=$_RE^L^8&mB-Xh=+{(_ z-%veV0{`6$M2@aBZ>*&n5mA=j@8>WROX(Wjq9}}=9b`b2uF`Q{)TtC^om0xnV{$1Q zftyO<`sLbJ$~ZEY)EUwQc3r>79I-3qhI$=3pmd3P@>Jt8P#;)^vc6c!-eHWYMXES# zIHGi+s!32q8Nlm5!I>-uVTJ}j@0K?6wcp2NpQq$<7^Y`AGU0LU8 z#d?;`(hOf}`lOszzTeNVROt*o?r)Hot{xTSoTeR^ew1DTEK~+m)f5^~ zP4};5Ux%x~_)xV2A6V6J6h_^oqC|}+{TMoc+^>yF?eX{=meR6Jt{S%-+4nPZkoUeqjk}T)isM{u3jvqUA zdLVE)tJjTTocbyE))cf|rigMceex0j>uPfsGeFAgDC}i4iO`p!%atxh6qeVL2NqS6 z88?hu!)SeZja`S07E|u23okpGa5vX|$|{M~vlcdrG?@NFEncCC&0hie@vqQpYjt^% zDO|QjCpR0@P1$N4eT9x*rAx1%N?v>gDe}$Yu*P6ownFoIhedjpE!XzmMnqPCa&j}iT2m+4R z*@qdaWoZf-WuD{kx5>Ev;1Hz$^AH?;;}Bfhw8F0R%SNlyVG51no-Zsk{xEZEW0vO^dz9YxIST7`KI#ba?*HHbOj3f5pTqw#u!->M zL2o0T`)ZD#rDh-P^kdWG$We!PjrO=1Zk_0T7M!ofMg5XhJ|>R;qKdPel&j*B8+mnS)m3@=}zxbLkDcucF`rbUaDPfqN^;o(tc zx3PSo((MQ=$9?WQFoEAY;2*dw%#8N=x_QzJit>3{^$yj{Re^cT(cEyBBhjw%*<8SY z1;CySk9Wbo-n(Gm|6Q=3q4akV2h+_^L2YJD%9$cpEwim%K27EC0%xkun8%|^{kKK& z5uG$kf(Tdn6m@$KWG8Eiot?@FnedqvHj{Lt#4Q>p>hyb{`|*49?ZJ%^4&8i@5$n0h z*vHG61-1Z*=8eE?L z{Uuv`pb9>O-}662y8UYGThOAvGG4Jiv7c3#skpqa+MIwaeYACh;mq>h1et~jAxkgi zo`5V^7fgm^-Eyy>%6rP|BNBQj!92R_E{sS)PRqEr$;-Pc`y&eCfWFjCz0R6wP3GmD zh{&%99MV?IP~^mL+EX!I31=C3)7&GEqs3faMW=~&RZP_v1MQNh;!$Ov zMbUgjtp{60vto*_o~4af&eF#4e{zT|-B=uqCsK}m9siW&WyK_={S(rT`zP%E%s)YN zf_Aj^jR*j+*~Na~wv0fKMN6Vn4{zK_l*%>7!zd(mo}}Xs!K} z!?~mA-3K{zdm!EiVq6su>%^xJ^dbEK4Bh$^8U^AzTJ?ez|EcvcM2VY7qt>%SoB&4z}g6@yf}k?FIFfr@WrjfNEiwEf?7 zTYvp-E#npV?R6RzucEK+{Tt%k{Wrb#c1V!Zv!b^KeMZ(^M9ZY=lozgAP|2$20SZyB zik`a6e_i^F67Qekz!PcRwWT%|%jTcMS8vp|=HZI2y4X0}RMAD-e@9g7a|)dJoJsN6 z=a6}HaJW+!KS%tnJg60@g>l&eMw)p z(2cEDs8lppi&~c9h>Se|ln0)pl9jc>gEa3Pxi<|pI(S8_eBFD875ECT6>jVy716qX z4q0>W99%rE71MpVt0Gd9>x858RYd5LQK6tyxHg}sjhoKXjAQ4SEUV4iA!3D*jWcCF z*hy$lu=cx8yi_zs$e1~y0`Cv6p(suL3JPa_J*aB;$ z$-%J2ov&bvUxKU+xuSupcNtMtQD5tkN1F3Bjk@y(Ypd;FBc|Km31b0K;jeRFGbiKp z);xR_egV?@=srsV^}GN<7F=MT&`ZfbWBlKE!SwhATC)EFEz!@$6kmZi=AX?np`sQS zglTW&MgG;Xr+F%BXu&;1R*b7cp9K5j@4QKLJ#D!Nn9sg3(yoFKir<8}{YPJNe8Ft+ z*2eHiA6Mn@|5I#^x57tpl&dmTzIMW_9Hujz|55+Tv?q9lVVKGxy7($nZj7sv2=^<( z&5E;fkT$i1CKoS5lQ-PkSCs>F+iYLOeM1_ycCfGPr|t>XB4628`QNb6>+`p4R`RrP zGmTXCR@PoC+ADi$yIVP^OwnMsy{0l*er(nNsi#K3b6Wl_c$IzYXzbP9Z3V&}UVk85 z^``kT4X%QPD!c0bi10|&{SPD#?g0PC{fAB&^B zIgM1=L6`o+Ainq?B;0qunl7kpr+dHBKP~#H@`oQrGBEF5bCz>%`*;>c{ zOYgk(U+P)j&X+m5vXy+kV;+fD!gt7kIIZt!qgn=0UcX#2*8{jXBT{VT|fmprVMwX&XuT&2L^ zt59+ERm9GMtMo+9Rkk_V0l3P*@YO{gx^R_&f4q*bVLfksWe)&V67;yP+5W1mOORc_ zWL%^0n_1z^ag_{_3O5JU(#2~4s;LTDAyHWauX#prR(fg;#~C#6I$W~yI)Zclb=LX6 z<%XMKx=xoc@AI-&UtOpCnq4;#K=-eM$HqKFYvc`ZUNo9R6NsXfn&dvgP_aUr$%hG} z>IS2GnLfF}`e&(`Ax5$v2@izRTU;i?r1jN$|`~NPg@l zU9mu)yZ>b9uKNZ5<+s3So|s%W%X@(D&sbEY517G*&o~2 zR)Z$+_f_+E|U1k`j*cYY5pJ@%7Ei(*D?2Ax7F9vitjs{`a{GZ7jHq&Ads_Q?a8iZ)V zOj~KNI{!kJPQQ?4-Y--dq|@#{?7IBI04V>3CbgVJlg|7??R9>oNx%OBdE$R%<0s-* z{^s+SdK+l|ui#N%U(Ygqv#*|xnC}2x{*@a2HDb1{(N77#Ihy*KyTWGaO~ zNW!gCK!91I?5m-36X}`a-$B%Ol5Zmp$L{lZU@>pYQQcr87k;Nb?@aOy@^n?|>q!R9 z%C(yO2ZU*!ZfmVvt-EP99lP{AdgcM$-YqpTpBtf6CU z;dK2)VT>5lZEsXg)K+@K2;>RMxW}LI8ssKunifoQ{~4#t<`0K{ezOae$}yVwG|CS0 zel)Rr5obg1BVj5wSQV`DVO`x2Zq|U6#CN<8K3sjc&$XtA7cM%DEqdP)z{a?$!qn2k z*;Fk&ob@!>!^v)dhqIQNl$ilq#jR@(r-@(Q&1E~ZDo9sN0--xSozeK#vlkL^SR3hY z_sFUOwR4+kVO1lo^CV+K6?sx!1AXM_jDg8-lBgS=PG5aH&5)#uIcA!XCRP4QuR#`E z0bBZ3ah0@&)9faGQiCFAYEZ5`s=Zp&JZ|zM@?#~rE?4h z;MLqU&%&*-s}|+&*QEUDdA>%`ukz3klQyW9(@)=LFtIS`*Xf7hrrf@@daD-ouF?N^ z=(}2wC9F1N@vF^SAM@6}wzIzG)^<8H-lVmEv7y6r-*T1L1})@wZCbHZ_a3$~a)}7k z5v!m&R5hrMlR%`p$cUt#McPn@oD20PETPgmz`R(;>EzhuZzg@d>W?EmsIIethS#O8 z2)Vk!&u1nt8DjR33Arv&ZfjU$7>Qdj`y3RT^JK@Pf$BP1-W%!-^!mhWAWe@uqXqg=2F_x6k8xwm)!q{>6rOHRF{3hYKXdzfDdZ;L8oqh^iI4V z_+^gp#SXG>pjP=&$p97l(U%2&G|p$FmHz#7%lzp}7$GYT`>2~gS-SeeCPgEC3CH3O zz)waZS~mCt@R+}oHGn?=LLP#NXkbqia3FBUa;zPn`?_mz014f+FaW%|>c&`$cNZNt z$(;{g3UD^?fIsJLHR;tgwbT7lLtX3BP)}|KJ7YAlJ{Z*5=4<@^RR2R;iVb>I>-2Gb zm~ySo6$lYZ9c!-wz(=p35^&ytr|Hw6Tg>% z6YHv)r&&HAhn_+@fVR*MOZ(eP%Ilm@{6T5;%pl+y-&2nyD#9qC~o? zFq8#4V|Kd=xRU_nE zWWf#Bn?c}{s_)EWm~NK)5)Zj*=mWF8agBxXv|EsE^AL44)QfUe4c6n0>4!loYD_Z* z>SSYRIlxUzJKfxV9djaN>MutyIr^zvF!}pxiuvNq@FKU!=C&mXe!bkyH36-;(KF@a zMh?%a6!y(%)=$CChH4e!bZ};Xuh4&4_R|)AR`XI3Etd zq;@cZB9R2)b#keHj&4PQ&uk8184^{`Qr9Sc&*VT75F=gH#D3mng=+P5RYs9@nz}7P zJf4nndh2eKGaOTIXf)}MNR=ShGa9jZqS6kd>dD#>P3_yG8E)~FMgUh&(j}5$;02Y8 zEGob?UJOI!fs+wj7joH^h@QT#>NInPm7&Ad=M+z;xvNz@PI)o3Z>%n6T6D+gN(^Oc`!Y<)O#nYs z=iT2!L7GcP@iI{NngIB26K7q8Eisx^b$<2@ zooEL9ZrWZArLQ$Zn7>zT=B(;2`nuX(MQ4p)Z>#8}jm_bsXPVO=N18K->}w8t57=o1 zO?3zT-kkZSy+T_65tm*q5R1tzoL=g)(Kp1jI8ob4V;TRNc@VrVCV4T?n<^oW8e7G|86{7|XkJ@k zXOOP1!hLQk*HcCUf9EGqupj}h^4EINSjzk9QUX)n#RR9fXU8NRzf*@vyV^(1TT`Jo zH+y;DCgKUk(EQc_&ui@r!)eUX))YF@nn87?wev1|?X^XgQu{~9FA+-lCNhFEN_~ln zus>DfN%9>Ain>6@xXExfW*MKS)010E~3)AE@NE z{2HK2_l&l`zc#gnR{eCKEkx?8->VF#@9(1scq+iP--PC|rWRy68*^8!+p_(=bd%YG zd?{Mcj&jNB`n>(_$!%ZS*h3ra=-S_%P|l|J_je;eFB!XP#|xHJ`@3j)doby&oc8oW zc6%ECQG3L1lIA@Hu2HW29k~MnEFwj8a7L?52WQPX#)8nnc%OL5T&CaOPIVVr=v-G@ zY&c+lqLLOHJ%4{2r7gCA8&`HI%9LQ zwdoXWwovxt{P0D(yi+HXn7N%$eJ6FI_7`5X9U7*}7h$Xz*ZxqQ?nG~Y+zIB7e9@PS zbo+x9+8G=gE4edN>e(5dsaRy>!G5PUkpvf4cLoDa_q#QEFGFF>`Fj+=WU?(84G?7WQ*3 zG8-YZt1GS8l5Ir${yHkPV{m_MozC_(K1}!5Vt%$FoP~W9&QbA?vA?EaTO-yL+1}4c z_5C%prW;LL-HoO-&$UhS(AHerW&h9tUW~Y2r+VE%X{`pMCYnLag-J#c{xYjq8~n^! zGu8%E%Ds&$RgI4%s~J_V)XDBNZH0c|;br2DnLbX^Cyo8hVf5-{nzPJKmeou3R*7#D zjqicx@Oueb@)JFrjr3*@bcn^OdICy;#v=XI12h&Yaa#h%gE6UEgmCR=+tytm5*g24-t|@$X)Z`Rkc2LlbU}M2Q&|c>k z`Y~n>wA-}^uO6-gZ8hZ6;3(ZpL8=(99UUUgO~(Um)U6is?Q;qPI!42m`$Z|T4~+0=xsSQZa{!}% zAF@XhS(rzJF64s->EQ~$8ElSm9|+sk*BQ+fR;wR(!ljbx-!b=!4uohxU&;h)Uf=)6 z)O!b3S#06nCe*Z@1W2+|NFnqZkls;xuhI!f3y{z|1Y}zQ0r4F3Pz1!|(W8J6NJuXP zLgGh~peR+o-^}LT`~CIKJF{lZYO|)#z!+1ZAG!;4D%(VGEV&bvfeY<6xluAp z(i!+l>eHF{iV93XZWP5bw41p=t@$a;*h^}FR;}|hrj+WhIQgNxREOfa&>Qj768<%) z3+?cVE;!QUE^u>3EPuFCz4g2Ns;a~!KJ9|HC@*JMGL_>kUqn+@-PT)GmC;lJMkJ-R z4t1DV2x9{@aT-?m{p6D#v?asK3s$t{`3>^YH+&u3e*4xYaf>BlX)>i+6A!?XT_XhP)J>3NA2fablceCw7>>8{9+Y8zC3YV0a#=8$b_O%(N=eBF0 zw#=~ZWfIfs2K~SssnIL_XiIii)`ETrI6|BHQRzSI zhwn;X=*Q~D?l9dTiZ>kGgD2|zOZHBv-A-M&fcaN(?GDk%{vZpM*CuP;yE$aC(w0|= z@wqkRkatlOpzL2ijS0oLcJp}j09fRjk<-?ocl&GAT&wNf4y6ttm!G2N*=n(y1+}px zMY(qSD0(1mXVgFlJU_uN*w3}w3)4f@jT>?S(U>B30qzJ;Nt>rZRJCVgkRj%%;v$`N6aa#Nsoantk{F={Y`zH;3+{OBvECh4^yP>`r8 zZ&2qy8G_BlUk?lROr5L^OKhe|>M+I%FEv4Jhr-K5-u#7_(L+PZY3_wEa}8+fcx@Ys z3diY``EU)=The3y6aTz0c@fQUS z*Tiu)Wf-r&S{{dLr#ohd-WyKd!HQaDRh-Hzy{D+0se^d%7by%>?l<7Vw+>Lx5fI&9 z(?)=@pN>qVqC-YsefV2gHP6&OiuyXN3cC(cO%D=7pxtDU(ZLaF2J5N4RBI#!^;Cyf z{dm?g)jacPti`k|`zmvCBGQ%GU7;XFnBCNBqMv#BE48aGjD(CX@)$*_omKstu&SP^ zoz&qhLV&}L^0-Lj27NE$T?`|!6?*U zCq5)x(eb#xy>qNbZljYV`nXcfn~#vj0CDth9Q+|)D@B|(<+jYY7$3qu>GHZe8fBML zoi~kK_mov%0!U*|8D*e!&W$(Ca+9I7b5es>s!CgNWXw*$Kw0pir7!WEm7c-8fjJZ1Y zjv;6F9Nm4#dg0x(m78q+$}Ihm421yCRQpqCl+X-C&9G%o*NkzHI!))lHndEY2fYHM zyE}=yooL{H7>9+f9c!+^*gb_K#~>ncvigiiCzG_R*pQQ;z|HOwCNi<@4oy%k)1KpH z#>;yGMT}E}2~av#VG}G_ud3|?OTrj!nECc^zlHJnJk5gI&^ z$l*L5X|oU0M<$vxzQzb(X^5_y2%K^P!hJ1LbN0SH~rlP zUI1|I?yqA8x}Pd4PX2m7OonTff+d&BkOBIPks(F6Y9G=YwKhR4R*fB$NAs$oQy_Zz6c8<)!dT|?6!ZM>?zTEI1;Mo8$Ukyxt-wUE zwo>y%yj`$HznA~k(iLs5YOH0 z0CE|ZvYWf>lHln@ZFXVJD7z8Q{!$J%T$@jv>bl$lYQSPONFOADwDwd+S@qZxZc)@# z(o|5?(WuugH?>*6wq9vB*Lj_@9n#%3m9yB5r-mNBW(}dbW|%6zo0fDYNfcdGUyh;Q zLmLpQ+-dM!CFAlm2J6`C!|57l75(h z^(3gwObDB(Ix}Hqg8G=h@v2>5tMWK)m_old%Da2drWyxH?>%3Bf2VnA-RF+qEp|aqFC3S z&RV_563|KE^T5+l9n9xt#Za?B@{-;&u3}FIMJ-qfEg}c%pNtkiBr2`Ota2H;`UE7m1a+U zT{azAP}S4sg>hh=Pf|MvF;_QQsw$hQUPhdbV2)QTlQ*gzi{Oo!<7AC91NP z-Y~L^P;@f#2v^|SRxe?iZ2m*FIyt0zd2jh(UfZuCYCc@p7$(|)Ek){{4(kSn;-AdC!+ z)a@-YG*rOHRxWW)YIW3)U{`CQP&yPQU}&T6mtl-1OF!KpkzZGB(Qehr?gQQAYZz3uxpJZQi-thSX7b{#_IZ~4r z$QxzGv88cRbtNv(Uwu|WBK!UJ!W0GjX}yW})#?NE%(GTv9{UbhA+e>2D6)E~;ky)4 zo>vO(=p(J1Ja(HNUs~DcLl<)cbD-HImsW|kO#u|en_b1W;?7di8YUWN zx?L^PgCDJ{6ydpNhO*Yc?{rS-hE(#PtI*@DB_zGIy8j3-!E3Rw#XtHv)p{-JO21+Z zG`)pZuZ8U9dUVCF8vo67aV-sMQ-%DD)S_JJO;q=NR9xqMn#LjTWB#NScpsSwx{tJG%QSP(_tE2VizjjK7 z9}fnk*K+HG6ACF*RI=4nj|}Jsa}C`&=vT$xm0tb1z#8+sAFaz82dlX0)wJN>;Hj!j z=EJeWe^WTuCgxdvrpL(l10tfe>bSLn^eA~yv&k5#r5`|7WqtAi0*KJj56I6;HRdl& z=MPz_r-$mFT~x#7DQGb%g|#m(W!h`=2WwjjIoQXPLJp2$Wm~=~ikG8}BW`a#ff|DK zQCfhOzytw*?Ghesr&uOAb&$EsXjeKLSOqE$&#vR+!+WT1&3Wr9V}%pfVcwh8vCjV9 zI_Bnc*J1hPba@?om6cDH^Fk^U#w z^xx7Z%ee`%CaLu%SYlOu6VoXZpV$0``s&?~2zrA%Hc|3;#hKcVTN$T?xwhp_8>@i* z)(yU@4x6dQ?KeYA-Q%X~kTzOtHiI)>la9MR!zg{2>E>mmo^D18Pc|ckQf`MdT#*N? zI@5+}+7?V@sJ4OH6gNb9ThQfT&f|vom$2hBJC>wKWU!|;oXtFF&efN zuA;SME5#&lrI;xIhjd=Q}24$4wALyY}+r?M-VRd&4yHV|eAFo$qOGUi+Aw zyFW$-Av*an7=yL-C!?ypK??g%NDWpL+)mk!>eptNWslZ~jZE;J*maQ@@%&5BYw|*m^HF#`9%tT_0CO4O^l` zp8}Pvgl`Z+tSf!7N=(Ee-ToBO-1-zFT=9<}60b8? z+dqT2IXd+j$Y*QODI=crS&H}{IcDmR`+tV+oPwz;uJq|zV^XH+-CI_P=~Hd9NIT^#*8+3e1OtQeV5NiC5~k?$9VT*hcXq zc~Z|EF+!7X6T%S<*XC_-J4~yL=8*voT8;H$r?xv+PY&CX ztB20G8ERuNsa+Wd1X+*K+Qw0F{~Z{4o2qn??hmsKA0Cg~;h z+zDGOGMZ0&HEHTJ~MYN8MDywF7 z92jIq8I5qql-3WaWGcnY(iXx~b#}vV?cFr73CkVS%#0VbU^nC})fV$v!fjjza&NNo z2RCi#Wj_*O_$M#^W`+J%uaPJ&l z>}gTXR+}{JxOEymly<({J+^nIM)}%{3HQ#>muYBnx=sOtl`ehAQqUi1OkCDVr&&u< zhjh@kPe+sgduTn%6kUD>%-iV@n4OMtC&}-TG2p!kN`6d@{mZ1(-V5oGdqc{XHb=sA zH_2R#xp%y#?4_7-TDunu9;;0A_o^=Or;B?bJz|j~RGt~ksJ6al?vAitIl)1}zkU$@ITs;E;IPJLk(<@eR_@+f0X7V=nA-hr3j+gq2i$lFWD%Uccf zRIO|@-9x?2r@J;kvaYF{)@5TqtrW%SueJD!Ab>?nr< z!tb$o7VFykvgYSN)=S!AJ{@$>eA?@l`Lxs8JJ#^`ww1>@Lcq7t=v#9_7q|i{&`M|_!im7IZu7Q&BVU%9oHS6>1soyng6m@w3m)%r#Oec-L z1ziMo=s$led~a<%J#E{{y|vV{07L6hfT1laK&#UWu+~ilY+$IaoC4V4bVxzS6D;*Y zAtg`K(O|2zjH#-*kCKzri;r)jyZdXld-EdMabtBEQ+RL)PGVgdlbK9IRFm}cK6AY8k7^7@??Ijw%7J409OIPAhZ#oa@X}!@Oxi zGlnVY9@7W-l%ZN%%X*9<%BY3u&pd$X->StC0TN$PqMuD1q-zJDVW0vgJGcfsV}M(q zjT$#%yT+LDKIVy>jQ%=084QDqsgCa!Q)ON&hSq9R9A;u9qmND&gQB-~O|d9@Df}S+ zOwAue4;`91Xx1{i>s=zX@*p*5eNzYTP9Frtj|Z9J>!N=E#L>pZP(z|is4}mVu$IzM z(@MbevX)J@F7YKElfczbVh3F|Ded*FsZD98+J``1>k#yfJQTv^(T7YE+{|HCw=-Jn z!$T0V(WIU@MAa`ep+5+*(!I&)z~N-DTi0ocZ>Haz7H3o4c}RVldl;#Gd6-;V4nul( zZ#T~`>XJY8`>IL3^SfV={Esk@Tm6(3gJ@SqoJJkN&KhXs6I-z|>Z?^~xUuexdOCRo zX6tH&as5QpQRq>qa~_4J9!Dvs%~6zn)Zs8jR8#L9WkmS4NzCGP6m2u1izamPDDoTT zZ*79x#UDd!@G%m*9s@_KV3YBTj<u#IX>{vu zucBU}ZWaf}II5(?IlbidRmfes2MzwV6TX>)6m^QKI?(M6TQoI2oV)8elb<<2lTIPI zgi{o-{uCm4*M#y2@dA?doj|isXc>oCV_cbi^aw=QaMaf*j%Q?i(N3%@v!@cihL#>$ zV?N!r_iMQ5rVC$F>AR}*H~e+c#V9W8t^N(B5dRIv*Y_L5ur!g12I7v|@(qYz)=eL- z#mwX_@PNJ8z2-GCCYaey8;Q~2Z=v&OBiumpx2W@8BO{#5*7AGN=4++9 z-$G$ag|@cYTc}-Y46*rll$rD$3U9`Bh1~C%$&8Un_}_P+JNF$r;l&aj8gaPGf?@J>4ACS6(SwbUk^T35iWPL$+_Ombcv1QMWU2 zS6fp_;mH`gS)he^c4u@Ro8MzynKk8DZcF7-pEHP%joz!#Dk;^}b1pVg^Lym>=SJ{V zab?CTE&&485}x`89qFV-@0QGE4HwSA*$cP3Z7j~=g2tn9L>ZPZ@UpHvyyh!beL(` z%!(TQXIM2IIfs?cs>g+Hcg{gv_48PM=y|a9IL{czUkT?S!J*aX;n7dO*`_A(ExoMn2-YlfAuhn8N1kK~IC{QpRHFh%P&htfo3j8k>;rT!Dec8ac`^ zkoBTk{|E!EengIra^c*;|07zuGzzcu=8qUy-jBG<9VWGQylnxq>g$oo@zBK8{|WNz zs_#q2&a>)h%1`iKTOYn;*vYCTpYl}jw4cCp>nDt|25+F)9z#}j-o1s>YU=kh)Kt|x z^B1cRe}=>=Dm0NX`qlhJtF;%VSnd~!OY(9ABaTS7AENivqKN`sJ_t37{Tjbec7#6q zg}mWf6OS?M|AmsD{DPg_`~|LV8V+JzSx&Y3m3rLrSK{h+fYbP2fm`=0aPOG70z!D= zGrz*->0c?==Qom`n9xnYDJ@Xlej~B#Z$u@Nh#i0M8ywIbH}P2}{EKl|7hfgwBO-L;Dz?0Guo+2Yl~(g>@K;Ll z*Wk}npLVw*_Rui``rkG1|8NaeeRYk_(zqrLhI5%qRQWmxBd$~1GMYFTR%b5Or0dvT z!gb7NhWzJQP8)WZ(gY3yS zAaU9ah+Q3Q+T6@p@^C;)#to>xegmg*`3ALOh{HOK>8g7Z0ZmgsKI(fjq;zTeV2w5U zFYcg-b!8@L<4yQWRMsqT6x^hM>$7lERb82r6~D+)O+L3!&A%5}Yzf-A$X4BnI!zjd zPtZT^z<5<(Y#Zs!ae8tKlw-Az2wt?MpV7ONed{4}jHca&jH$PomAc-{N+w=y{p@%w zbCj00wDKD%k2?r^1e^SwCzd}O1mr&{L-o<8$?qU0< zS;@LtnoCNv7ITChMf2w16zhi;>fB#oT%czrdcLav4K>yNhW6oqqnf#z{Wm4e(FWp~ zKiX&hX6ZKr_3PiTQ~3e9^?N|5BO!)60aZ+Umo-hVJpk`iovd$tXOeFH!Gd8{q9Phl z$?rU%64rc3j>&5O5c6vH5Lw0~1q7qwtOTtfj+vvK59tC;&=~`9`XN&AdPJ6SJVlFy zqaTrFb{k{lS+8nM8#F)p5$3kPjrBXDb-s-yC0@_kAjNZ!LL98Qj%gVj;+Zv4-P&5G zz{|`>5dqxi|)V>{qPv^UVa?n&5FW|a%C-zuPEX!&2H8pO|urC zHBh~90h;y%5&gIKy~M14zpXRR>NowVy8fIFsG50v$?o|@m6w8Go% zJb6Cw8DQ--{TX7M_KbRb^=~tAnAKLoLtxB z;pAdJ4`*r2&TMtcDXm2wPBW3Y)x*gd1rH~Og`S0(8J`>vH8hhdzj`>i3e3|P;gXunzTg2Je}rh%O&Qsm>C+|CTA~FiHTUK8=g*MlL4ii+;LC}62ivYiZoAK zD>I56Q3~t{M9Edk$*JM-j!K*+b#iLh4K|A_o&kGcz~V|nd~|7W)R{nrPNe}`LLBaO z@&xqtuhIZ*Cdtp0on((}nR5g@o3%3_RF_JFzGo!YzGP2PTp1^?`;~F}tNBDQ4Jbp# zQ4?tcZ*3qUB(%%!zML)tfhLq!pb_UW40a2BDJxaX#O}p%%4`3b^7UA z1hMCGcd1S&S?$^_2#2q<(v+Us?4hb*-UVngkfsxzC4h(JZ;&pXb4eEAtjdwV4$`dfR7Bof#D&r#RR8G@23DSRO#>KW~-8De;2Xf4mU!Z7-}K+S?hy$fb=p z;H|x#z6u{@3_QDwmV3idgG~)LbuPQ39(zO1BX6?S_Hl+`w9ygP^L5Y^A5td! zkg|akt?_~6O%ax-wmL^5YlF{xkV0$4&2W42R*IfxbGKCIX;iW4zHn2zRCuJ;`6A_G zzUZaU*I8Z_2RkAR6HVps2U*M@m9@=yHqT9sv=}(P)&mSn{m^2DpOcq%{lIX+4;th2 zw;xQfiO7KfA{+>%zr*QdX)u}5lM);NZg2otMWVLz1*#>HH{@z(N#UH`E+}Lzg zvTJB$V=Id4n(oh2ujVcfx)=?aO4r@H0Y-MbSn39e<*7ABsH1(kxFNv#HNLf9Jv+0T z!@ZSW440n-pp4F)ZO1KVin<5F8&{YGqKxT*kon(0%sxSRL^visKT#HEPABqa!ms7c zBuvf(rFt=kKt&$Uo3><(s{lJ=D>y^3+vEz?Za*QO`J`uFj5Tvc>#q5Y*XSCCkDO6z zT@gcSRgr9o6)A6o%G5UQFK4*w);3be8KzSek=$1Xq~u;$i2key-P>y$OUW6mlG;|A zIj?9-H|po4N~oY(TYKAm4#zUP*C1p%)hN;)1y-Rh}+vn@3}LbkYBU zq4+bCaw!&*EI~*dFanXj0!_g zQ|B>D_C^?d<%U_4z0}W2g_+JU%BiK8aOke7-u*2fHIx_*RlLa>PAY3ncBq+Cl~bcc z$EHNU-Lr78HH|>^G3rf(SG0TmuQ8{C<9Rea+LaTfyN_^O&={$&7`ZDuf;^>Hm@1JI zA)m^i@vaPSDRUsNL1n~MFvr2nV-5$qDnpP{|ID#Q#r}8$e5^8jKMN0!@XQHff0QGZ z#nzlk)Fp0oX9~ATW5opW*kDdYZJcPjt2q_4A`(1Y{2xj7ospQ)kCDic>k5cqY;rLc zD}+=(^@zfryGKFIq9~a1(Z;{o{74P)R%R49*i;ndWCS`;x1*iayv*C!W+9C8Zdcjs zUd5H$UrVpBr>l7kJWh=PMPEH*pi|0~+ebTMD6O}84K-5F?WOoKRI1#bykP?79x5Da z;doG(eqBZF>YBP6jD01Uh#Daz{o90khuGnHE`3N3OI%g? z)I>DiH7UAnP27E4O?o?h4pffTz?xX!#Xs#vk=$tc_XgcZH9>N=Cio+DmyE1ehtxtF z5xf)wA#G|QiOao>!RChPU6aCsbst-jQ)kV8NJ?!4AFP;$R^mbGR-4#Lnr@;is(u*@ zTtWV3eJi6jB;2Zv-?>~HiF{thN`zU4Iuz|t-#Un+PaQ}PFAHCY$d`5&nW_%R zB@s~BdH}bo=M47DeL zW(r`*i~w)uk%nh&{}e}@$MdOw&?&9r%6n0%Hl~rzJf-5txbhmRM8JAwOwE; zTVAw&XpBij>39wMAIXah);iAxSRNy^fPc+zf?9VpK~`b9{H{$2)r}??pi{pw{s$9d zx@0S|V2x}FiXaVf|5s9SGM$cSS6)ROZ%QLjL3aVr?@g&NUweedc;<26^fWt8&hyup zX6S2lGpshEOt=}y=lN-8Gj#A}GkSL0%ya-E_R+&;;CNu*YB#617ulRp%W9+|x$^4c zL_7)25zm`WTXXYxT;e{95$Vm5;_c=%YNa(K)Dp}IN&>3U0_lus0goOk3AH@Epj$SO zyHtfO(BBgE{tH#-Cesv>qkKz*-LfU}T%`YnnH;$bb;2E3psg**F<*lDCmO+hM5jVLNCC}2OD7Vj=sVxuK75`}~Ol5d!GclJt-Q6lSZ)CR3 zt-Z&FiQH*gSK3yxsmgN)l6a2;!Nj*lSQX0Hk$mnHZEuYLx0$%}ts!@key4r$%w?kI zsafsJov03N$ko0L5J9DRjwN?I_tj9}R6RL>)(!6b%>_6Lwti7h%&mQ$zbnAJF*PY<#x`e*zeBs4(4w2qussV=A6cA zq+Rm@xE!uMqAq&@QCICisE!GB>wtilcA(Nv?|{l?UvLELUnXwj1;&Ay2JTh|<19N+ z{?Ftn<;r*J$psu*jh9HQchOOa!h+cdN>`i0n((?ZH<$qyq=^@eRPrn7T>{E@3A6=n z_zM4*IIfHxbFiY*Ge1y|4OI1)4c1GL*29Ee-*2`_=5w3RB@#a{Q6G{>k-qK;Zc`-J zzWrIw96rtWQQ3~jtxQKMWy_AxU8f^C+NPSio?l+`JEH7)9bx4Q5}CT+l4@)-zl^Su zg5CRdBDZfRa!2mAyn1S=i5k)gG^;x~gFN$J(0_?x@5WJ+aHJC|e9{TaNmf9%Z5Hwt zD?Z1LCGr+&bZ1}}D!iigAq({7pP26Fohe{;MNE(yIZw|>)Pv5{$cZfxdSn;s;Ru>u zT*qu4l%>*7>q7CLc7dOiE@VB{g;q7s#QjMePTIGtvzp(u=QhVxM!ZAd@k$w*%)F_3 zXR58RN&0fCgDsPJW|iE`X93ozg-%T_M-M1(ijo-Q5#Smca8V5onSBv>rUboL5oI^; zM!8eEQQ8EZi?GgNyq?+dW!^ZQ=;o~IHx|T9t#X-rBf6*0jXv*Hg?2}@W7M`gcsV%n z&{V6ucr7>o+&g1FBXyoGIME~I@r=IsgYMX3ogP^GFpc@q_7L-iYR76bgz14571ay~ z(wZLVvCbOPPs@8nJ42~j&^t&|)|hTU-avh1S6TA7bfza|^w+H!c0wqxpEmZyKlfFO zB~~1AVYDZl&$xe8$Yu<-RabPPa?@qqKsus@D(PWz?#S{V%PB z{m8eV9~QE!A6D~GKgcL7<6lX|{V=X){V?Q$7xa$>&tIxG{h_*be^fl*%iq+uWWDF* zUsZ4Q$0!T>L;fON^71!TWucz-2ltcy*nLxPe`db&=c~s6$eE`F-WFu8wh+MM<(uSMoq0r|HYT?YdX~R9*kgdXFUC9tieC zUAk=jfBqD;8U!fs1)C42&x(w`^Aq&B`Jbp0gJ?-7=<-R-_Vyrp4a>3}k<_&Oaa!Z+ zAIt50`D6djD2l6g2m6Ki67?!k3^iDe-a3wBT@XJ;@9w7>6B@0rUIBHy$~`f<%O9nB zPb_UC)qXH+v>S}%-g;sk2GdCZ`MdImJ+F>zj^`AlM+G*q=MU9267}t1#2WdOy8dV| zN^k$v*l<42^gT7>sr*4&@)Tz`X$b1uJOuTR~c%g#7-*F+cgS{rDbl414oq7p}a3nJ3eisXF?SK>*HfQSRHM4u=HqW#*8Do!Xd-HB-zeIR!ckz`a?Vm#Q$F!n zL=DBo(~dWY2Z{H2B-l3|n0kajS5@mx;yROfD4uQ=$JXMVLFU+6?_xt{!BmBf0deRU zAbO0U)0?O~cghqk9|Mh(wPOq@wi|#8V?dFho(FB#iJCz`L9Zg3?ypio$1CTckwL*Y zU3P7`1bm>*Jbkc-Ilo;X)Mk{QrDS9ko>^YYFqm)--F^|-8lk(13fOE%^ zZHIwramYxqV3_(HqS*UmQCFRDBu0#bw9gJ#ND*;k=Jlj|XPec+fkK7^hg!OAU`$ z3VCzVq&*oA^6GmmUES4o58k1QtDu{vd-zx3CWHd>d`iPO`_xCfU}kZux(d1|a{{xR zo%MtHbmH1Y>n}U1!9?`@vW|J;w?Oie78Bvu!OZKKXMN07TioMW(R8p2+Uu}^Zl^mF zafG)gG6PUK!5M|OZj*qcYOM#Dk47iZ2CPkRMrwHiJmerN-*dp%RMX}-tNNPPA>ej(^y$RD02=nxi!Zb;@jx|0X5W^ z4}#1BSYbm&9=F}l!Z`Jv3!x2kC)*NUUmNC90`HZXPhA!GnVMW!M}G4_>pPG6tUmV~ z>?boIBvJSN^gEutmZhun|M%9Y$+j zTJ#XO>We9L$3ts2Z!^3#N@nr+cqw<)om%FoTX{zGgD#vtcRSTcKd8+ zu3&n`<)zLt9$u~79loY5)L>Q_v*Tf3OL;9L4-v~SHLiTRVzTaQruoaz*Suvgylok* zZ(c^dI<<^$KQ}a*q?^l7<@TS9D)%)~D;H5MT|_-{N5yHm3o74nfgs1lT*Q;G8msL1I$|Ap8lcH0&UM-dcwbFzJZ+@6uZH%Ww&byQ zz#W6xpFw>!-oOnEe*-%Eyg@M&&RDXlXbFi9*S?tN^^84QjZ%gL1}py!$~oeQ zIE#~O_7;hK+)+WAKon_}wDK&(e)<;Rh3>QpIztp`fqH84Io}3-ueYgk?cRo^f#)nE z4y||_-?sd1bddcvt%a}t{>PZyJ|9Isvje<+-giuL1_Rxam&MKb!UeKoHWctuRg#5-3 zuW&hP{bM=SkSzZd7|vpLW?3(~NL$^3g<7-%tP58_&yE#zw&pA9JGd`e0r!tq(1u-K z0k6?32?eZ#)DOR-UNv4xYNCl7u@W`h_|CeDnTmN}>-`L!TuF7BuBi{;^$!DF_g#b) z@h%;b(vKb7@m83`u3lgg)#EY6t$7!i*B)bA>F=VFn?N&s%6m+`h;`oRbNHY zs8zHveO5tJ;#HJ7dleaXtOEHa6PIn`idIpxpR9tq8z!#&HR1wR1J}TWnyrT7q}3SV zXcJm|&3Xq$`>Uy7BUSyjWnqMR-ZsK59IhDz6tRX*V%k2|lkxpSwbgV>CanSI=_3%m zW(|}*J_7c1;xcZnadJQ|Mi1Y^5kxC;EuSbJc{2!$B9&nND{B=Wy}K5X+)b+(p^IEW+PHjkm_gJ4rWm$T_%xrg@im? zR0WPqKzogUA%zkDLZksY<4*C{6L-L&n0!ET{sjXA^G)3-;*egxF_I!5ts#woxBC5? z#j(Es#;|_OH{Q3Xyq>s$$|>*Pw6taE2$&vi<0kdlJM(sc+5b^gMm@^<8%(9uubgQF zi%MzG2T+y^g4M>nL)X;_qUC1J^;rDk7A;4xMD)rILMY;?5K2J>~zl zTx=ZVkn_IDsz*(We?Lb{y5qSw%r@ydx(w_uOl15_6&IazLB~8{A*^Qzi*JPT!YetB*TgiF@u~B@hbgv=(;hGeSLL{fF7EZTASD#(p#f$SkKo>Nt>X7t?x{Q zXw4?L`=H2;uDeogYrC(TVh&K9o^pIb{SS~B?b_ExJvZa9I&1o7vUgHqI=z1c*-`(b zTTlG5E|H>(o1Nv#Fwx2;;Fu$3*XzCxT99cW+G`8-g2!W=-i%7#`?-?2`*2@dUCXrX zNE`Xll_x{%jLTctoXFJGm5*r9%eh;jW{tIWdznx)w7;zCZiR?4>SsQsHFqnNmC}Z- zNY#@I+7NodRv5dt)fwiw{{=ZdCSj?jRrEJgG(}6e6_r}_5@GSBuyd_V}9?y0!`$Rd(0LOv zKIKzV$En7rAR4Pn;P-bGy$T%-TcD^HU!*S{eWOeequ!!1x=`1@8pV%R!KbW*<$nq* zP3rlF8xf3>|7S>gq#VIk5+gMDGw=`BV)GfMt)EfAP(}J$2Dq_?f8F>D`Ofl1zK;J9 zYWF{exy}BE6(|0WD#4Xu53EZYpeqmT+*DD2o%kPk`e`yvG?Z|`k~`2x?LSAg?LMbI z-F#-(ql$Xz?hlyi%Fn4pF;{GVu&9U5eGWa{_3U%-bW^o2`0J|feAMj=Xjt%tGtAc< zvZJ4f1bB+PLx{gwb}8zlECbw8m%d*@axj+M*SEt*_zv5zY_l#1G$rzSibC z!nAY;BFW4(y_cdmo!9~12715xw{E9_e5m5mV7oyY0$#DsOlI#Ntc50p zdzehhrZl*IxXw%u?jNYDM42O_>7@9kQ^BXK_Yd-R?eFKFPUbrM+1CH<@2f@WAnBtm z=}hNvsQGP6P%mwH+w#&=etV(JcQ5q(^)}TgZZGN!f5+d9L-u#mQc|(*M`2bxuTitn4W3!S=tzaanvr2kpuLOM5m!*-5Sa?ex?{v{f&j z285qB>Y53Wt(BO`Tvsc+kU6AD-N4N^+{tzM(XRb1QzHG%-lF|2bRiR@&3WU%a?nh* zvOvcBk6Fm1iLx31M~23V3nGL==bHWq2qKQVnX;U*?n~<_A+A}<7Qavf5~n)Z1kJS+mjgsi9do*isG)@>zPdJ>c&-kM z@Hcl8?ysur_253rwV&5YbI}F2J?BzZj9xLHXf4il*6@jWZdJ9URdwx;)KOAA zDyLL7UU7efLh`^Lu2$wluQt@5D@yi<;wOyXZ`dT|zt&IfcWPUx+b+39A&(-0d0@gS zFGxEHI9&V9Rw{c@vAN8tUuXL+!TyRm5@-d>Bt<^vwJIO~Q9lYF4Hp6WJ|E%JgUAP? zL)8lSFlB5$+|*P6%Q)dMOR2ZA&A(U1YmeJG%Nk+sbOy;Qjf;GX*PBPwqDA}Y>|B4?B) z6;b^@Dx#9TS44H&ywyKg=|v0??iAq-FPYR^TbXbxwV$fqdOxj1C)NGfmfuke_e1f^ z+Oi+aFR9r4b_jsP00PUaJ&DMt|6;cwX%VUFe!g?pH-9w!k~_miY0pCsE%Ztt`R zxq|5=B{AuAlDP^Na36k!*jg&`6!4W#QGJep3r32Y^TJGk8OIbi)0$K8vicMhe^J@& zTP|**^JMU7obt61_bHfc^p|PTiyNu;*Whoc`F|NsisQ8DFXL{C8>rAE)Yo-)LOuEa zjVFwD71!lnEO>124LrU|*9Ob{YL8)~nCB6{p_G~mPs4{pNex~51|*yt_!b#gQ&aQd z;N`cFH{x6J|Mapqm7=(cJ|_x`JZV1Bx^F&F3jYplk=mMPu~$}!Y3#>-hw7iw*lUFe zReFUxa*M;%I-j)fzjHb~*}^l%!|C)ac4|ew&B^i+0ZhL*SP%ZRd&4H13s z8*LO<)V0$T%Rav|P#LJE=7Tk!A<|#pXIim1^eofj^wU=+og3V;&~L1(*hiJWC&F6= zSr))clfOqtlfK9F*MIK}^D$!1C~O@g(|EVV21Pu7O3DHY|hs&=EKWy=lRT4!}FL++-iG(#RX<6KED8I=S<3E9%Ho*bdpwIw3!ps@*%ch8xNKX^17qb?3_bTQLTTG#f2K+fj8TV6;A($~>hNZEr^FLSUl}D(+B!=tPD@Zp?zCTh8e13HLc(TAB zP?Irctm~jtLw-c)gMTE~${!JEus#J2PkPM6AN>)h%j@Rre0US^N64@K6EGFj;U{1M zHSs432+(T&wCX1oF+TSSU=iaW*W8(?vp*pNpP!jlduBon3E@$D{_L#o@P6LHH#Rq+ z#cAtJAEt{BdTIU7ATF;0V3hwe7;E_i;2jT^mESLkEK!WVi7rmoaQ-#yS2Dc&E0n$VD|$`)l?lX8f2DGs z=OHIX+?V|WOkc2gKBp6H|FC$TTK`7Hn5!|rk$?1W&eAEDj1d*j)(&DY(QcP)RiCM; z?!XLHz6y!c)#0kKhpUux?UHH8i@C5E`yr5|oma`5s9RV8|5Nmse@?YhiR)Zr{x|v> zp-Cmi>WUMTbPeE%+E#)wy>|^~yyvh#;w~PqQ-`slbJr-s^N95>V^#Tx+bO=PUf0Ps zMj0oqOBt<8CvC61I9`Rkk0!r$y+F6O=YZ8ld=Ex$#)ZpHnBYHP)c2vWn1gdUW@&_e zaE^LEw30hGoAbe#%C0}~DeZ0?mH{9$0_GN z^366$ckaW{INnZ$=dm1I<@2ig{l$dG8225W4I4J(z4&upL2Pz9INII6ZOqjG?}vqX z9*kEmIe1JJR&W1>WBlPSs>zSO=AndxBUI;aWISB`{>G|@X+D3N_cv1e;%{tuh`QDd zpvQ4=u%;2j9q6Z!AnRZHs!fnh z>Z6#45EK275gF9gVt*@82y=%TsKI8CqiU^6{& zf_m>0ioNp$Nnd^f>Q_QdFYjPu%?Py^Uz9>Ey^WOb4m8v+?xZ;Rgjq}t6c=WJ>+>4D zjj5+a#Hh(Xu)Q;k9g@TU0r#meO9x)A|*frC{tEWSo3cNF3rB z%8vCEe{NLqBa>`NCaxMJ|f_7mBc@vcWKPIB-7%V(-tM8bS=fS1tlZpC;GWV zOM$<&{DYVUC>gH18~k~Xy=0iXRy3id>|>r>FX7Z@snDvrW}qWVhlb#cmud^ zpRko)mU464Q5{ptLD|cyR*o{c*^ZBTl%s^#(ruRZ+E6ak_~SxSyv-AEcCwl)iI4b% z>Zfv{6%<|`mRqagUdwVTy_;#9w33$M-sh@JVm6Ira1!GxX|5wg=y3T^CdSH#hA{=S ztH^4-iCTJL4=ub9!xS$B67L0x|MmiLBW*WH+q|GDc|XqYqzRSr4s|m56X{I>_4V38 z|7br~Nj-FGI*M$s(Uq0vQqK~uUh;U+1vyK?J%x&}$dfR172-gk*D(`2k%MUq(>Y>XDmqV8jdjK(mb$-ckjo z$(xqKAoY5a#H)T#6zQPSu+{rV%T5K2aGU?5LIQ|Cg0o+M;+#ODlr1gZ^-D0wGw>qs)XIO;xMnitwiBIK~Vn0 z#Jx=%(C|;Bl%KjDYF} zBl!N0?exx}`dVb-76v1h>3;axEx}mT_rVx?9sM4R3Ec^%+@Jo8GX01{wN&>WT5J}A zWRpUW?C20OF283qbf~(vn#AoU@!NZ*r+J9%_pq!-A#f421m?&*0pbRHALf0}3TRr*6*u$X+)e8-+#+A;`Z}#P(74DR7!kM%xu0vs(Pa;OU zITU7{DmH)I{9-=A3JgOKL24StUnPwQ3$5;`XvP<2_7*fv7{Vv|jsQQfxV&Z45=dh&MDM=W8u5=DljD6nR1HySOO&fGlSXc~uG zL%qxqx<{`YN)B^`?hSP369b+BZy1MjxS0}7)L;{}Dh7crjiKO!Z_tmg;yT<|$6~;J z)Wkhl1TlAFASQA#sj;rZ4b`>^oX2TfBrSc6>u>|bry6THTwgn@knhVXq2)NGVkV9b zvpR$u)q^US?u2Y(Wru4k@^uSdOH*TEy`~agH-b7`L+`p1c(3hs20_uT!_`u%!ckRu z+XaoojI7^A4^gheRWz+?XceY{MlAQ|K+|FFC0=fkMCp5zB~njJdSyjb3$4nv%=U7X zMhp*{#{HjDJcq+IsT#JxW>NDAReCkp;*~4&2~pS?D?DELK4Ym3Qt#^2xn9)~O67CL zwI8mib=4`0JM0+Q@gJxw)#3k#>gc5UA)}MSJW_wi;&Eu=A?w=@b0|5_n#^HeZLR^z zO*K&Kpiix0yfqbLA)}YZto5(r?K)iEJs;FuqpJt}e^i|Zbe6^P|4kr}4uL?DH>442 zAc4?ZfY1pwbOHf_^bmRtB@!#rugX`YDED3)3d--QD2m9nK?o`IlIpbs0#>BR|1-~v z<$un5&a?0C%};R4UE!nEHM$A>R@15`WbUP1_OGh8Wka6YsG`eFkgBJGnov{A(r8kAO@l9#JgPYZK8s}=gLL3@f*c2`bEXl9AV}4gCEDjpk>KX@)(DP^_VKtwH2Hw$`xB%xj+$ z?XTZkL&%TEd7b~h>fZ)1AI)tO*1*pcl!0Dr9CoWR#0#y@tFCuRK}E~jFsv+XgSeWX z!+_mwgS~0pmf=JdrL;wRd55hn6_V8!h&yYXRfIfLb)C}$a#U(CtL4!ytijfHNaoZ! zvwcTb>e@QSrv2Jcq805ZK(@a5k`irhhx8-9avIVyRknl2r5gVgDOKB3)};1;F4pd^ ztPn>RY0KAU$&W77J6}673smNg!L@dKaObJnH%eOaJg@M`Y9W zTL_ol(e~!7Epm#daa=6*niF__}LLxOfhlOnI z46$~d5p#kDKcC zuY7S3n?$~yk2^Jew7&|IAly$Yo%z7gzS{LRyw&XrxdC12DZ6!rsXK2w71~Q1yCSWg z>ayP{c@Iru&`m~+=(-}T?%M7C-%UmP9S*uGs~bX@-3`s@m1}M4XcuKLdbYB4-e2A= zth${PT8~|>l6#ET0}04G8S~U38MEP~8}1am^B#3Ts;Ij=;Hg8&Fz%tXN6kVUyHCk^ zj)lm}QS%;%d$q3r%aki`m9l%l^-4Y81B4a&_1{i(wjy7!UD~|m?pabIK3zH}reSSs zJe(9umZ`|zBt`TN^Jhr9Wf3Y`KR0itW)W+rf_j5K zT^s-5@WY`X{_8?-CS|^T7<}FBO-=bdVHKap?c_eNFj-lBOz3^c>wjPHqJ7>Zy=yV= z^a1vAA2e=)y!t{tUCsC?t}oS-);Fx49d3KpDlRWg4?K%XKGT<0^TxB*L6 z>plU z?O#_Nwoj4{eB_9Nz2}b*h0j0;{;+`E?iK^FE}cHM@kbu}`XATev~`}{jlcwR+Nd?x zXl`@LKCiuw4uotwUE7RSe>X79w`$uC3GJ0Qh$o(M^V+DxAd*`veGr59Rwg4mmBD4* zmRm!8L%E1b9p8V`IT(<~kZBO3KJi;+NA;Z;P9e2QQT*% z7!np_OG49^SVqUPcsSIAb8NPfQbEns9sX-lD(pR#N(If-9^&;{Dw?%qsWtp#)AgH0 z-AJX1;)c<>r>cCZLu86(4I|^3!>Fho!?2i>c@o%3$7?w#~MTHF(FPAx1U;>YU zI_c@k98UUpZ5mGcI1OIzM5pP)Y^v~Ke}%*NXbl)aRw*NpZMLP1)XEhO zO>Pmda7Mhx@RBqFqQm4d5~8VUG?Eey)jMt3Y_=~yax&sb(G&y9t>g0ZldsLNyF_tIEuF!s1tumaNv^-KdjK@-vtW4y}l zq9HkHko`{@X0MqFEj~^Ol}^nxm1`XTo2c73IBl#;-Nr+Uo84*QcoTK< zcd7J}gT`89I&xi^4s_egPL3hC6Lo;<>Uug_a4j7zc)^_(tPkC3wUse}0@UIL1UBix z2~^8_6Ohtt6Oh+y=dC>*4?-1edHaT>w#n4MEG*w5@>VED;YYUPlHE?MYHLS&oB zVQGg3&%jP&v^;SdEIl+Zl6Ur|p~g#g+UO@go|k_dsOB2Ko_26`8q$oNj*7>r>vY7M zG#z7iW<879lcv)!Hck(V)T7e@Ixrnm{F;UOZ*Vef$ZKK_DNcsWKnC?@pilcZI5Ors zxJAvF0T0j4fO@o|Haen=(uElaFj9Bz6QPY89UAqNGLzi<&jcZRW>}c!%p@njO-@c> zdY42dC}lGdXNcx(a!A!x(^*6_p`JxvgJx06%bOSxBKg|7GtZ&Rbsb=IXcp8)&UdKc z$9%rohD;PPDU%)**Z1=sf&nUX2mJMXCOL6%eSwqUtHBFE`6d%_N6kj{ym@ugNvWxbUBADkCSnXnfOBW!XR~Ar7Ep%x>&H6|i zjw1%Liur|w!WN>GehXo_Dgm4o*(Am~?k7JV;BHQl_ zCvp*%t>z-6(R&ft4OAnMxp&$kM8!_amZ?@N$LnjH#lE^3Ia{@(Fuy_Dz>k5axn zfG@B_Tl761q0m-Npq{!B(Bq3~wToNXMEGVOy8L!rjGW+^9cAiCu!u475=H zCFJt2_P%xtmcB)yqC3euxrVCDWa*qloE7W3g0!gbqJyvvJ~7SL!7MG zcN|hPT2C8H-clxG{%T9!7`fvNxtC!ZeU<^;eHr3wxeOUkSwmpj#DUU1w~#|Riz4^13IahETrxK9moR5m|Hkx3@= z{MEX)9FDIpr@%{-%wI!3zKD~YRlocdJm*R&vlVsBX&B43I~yjJsVJMQmg=W$O#2dr zuOM=kHuTXfnSKfqa#VmPb5@#sxk|;@GZEVlB<@>aY@|H4l>W0}qn( zQFmGmRd%fzqay}>%MibRklJb6&CQm-+CKzaeoB7`#(kC00R_x?2&upG5U?*lL|1b0 zA!bp955aM@hl%^eLh*!{lwa=vPdy$6Jo{lPY1YGJ@|-1k>S`xbjsg#rJRFAUd>D@W z9|8UD!(>0BGufl@tJUujYGReB+CK)Bc8@`2=3`J9 zXQ7RRn9uAROe3tHdpt{dkHO1q?l=H@)gZnIaURk*K1-d}lF>{}TuZB(fva|>T~AjT z7Tj>B>G)deEq^Uy_yAJ`b5l5y49@-P`Zyd+R&hti{$%L!$LT26K2EcE=W%SyM2+i* zEDIl}emC{Qiv4V%=Ih{Xyh6J;NaK{$#o5n4o~DiKkkp2CNa}cslhGKJ5amDGy+5AV zvSk8y6Sjtjcpe|6#_K6cqxBSJ?0N`}(ERma&sz`nOGHQ(DzKzfeYKv_<7#^YD1IA2 z>AC@kmKM675Cg^)Br(Bxegia~+dw@W-w+n9Pd7m0j=^5BP=k%Y_EVRQ$fNT{wCM9z zwk3DGkM6Xh(?VFixfx1Uz0|p_Q*AwU+y3{^WA6XS+B1lz(q|LYR&0W9)+U7IG1wu~ zRrLnDWuC-Kr;G#9U5_pB<-@od8P(4%^wxka(5tSr-speUmaytxw#m#4>yl3xW~h*R zXFVNp7V>=C77A0o1(ApRgK4LylE>DJ;Wdv!k3ZIg+S(n72ZDKivG6{Xjc{yx0k66J z165ef(NA~8Dt&7aD;4lWSR-tcn#HI+(RoEPrgo@}g93-cA?pUPBy08^qGq&QF zl-YY@kvLK5eI4KlTGQ9D66tt4qxr$cc)e>N<5VWvN2#dtCFAgFADde+R!c{krWB0P zP69P@3r63QFNNX!V{tFGQXnx(&pZu@k^10iavq`8ecYsnYY#jcrD2MHhWc*)3N5}=sPB8bDGkuNv8ZO-XTd)>)-l2T^?f>` zAp3r5I-bNAo<*6)kFRO7@q#`&axb;F>Y-W2L@y<6Lnb}7d7N8@c%0vc?j&pPHW=xy zr+YXO?53Kdp!e%G>}J#LbW=%skqCws1zj|2I~ceKn+Q!JI_Wzq5fOEiZ!ZVCgIW@U z1FVAfZp(mgDs4IHLt89pr=`gdipnj(3C#`~5pI6dXe;Y?(6K(;+eQKfoJOKFRtB3J zg*EhV=_b>vm2EM^bm1|8f)<(y8o&w4+zIRP+OiY2n(Im**aEegE?9ir*5?o-JB=e8 z)_B|3{x{Y<`!v$K6P;+L_`}_$X~2u9EJdQ%cbv zq^aejYVEt?#UU7So53jiKQTG?as%p_(gcF@xn4%3YQmX#iXAu1~bUKt8ZzB&=%M%Q!(81WyQ|vE{9~s6GF*1mqgjrqd5dtE zyZB7gUk0wTwq?2_P(_RAs2Z<;*g>65PVm(p@1{;qTi8xHmef|s(;T~2$W}KII`#_c z*Kr0m=jtoyeEr?55wXv`o1~=OVSdbSg37$@aC~74J-(a9x^_2>^?d`2*Ezt@yx)mu zCe!d${>5nkAEmqs)XG-Brt;+W`p~}dU|b`y9UFxY7d#Z^z&3m!F-tV zEFx6b_mBnM=1{jn)a5EC?W_*AjsB_~ix-KSl#9E}!eAAfw5i0}+Os#Tv0mG2>kLyF z0mCxmhG{ip0ugadnyB4czSPfkx{-1nc? z*;Kyrde~*ObkasESkb7h`w-pTH)upH_aWdB8fXy%_7UN^$wv4^!xXv6;k+nS2T5e` z5U{~P9wMLrZhRp zfYVo9mOG^SaL*HM?yX0bV+&XRhn?d8uB^#ngQA|?^MptbWv{ie6yaoXt%K5C$!}5> z-E`UgzpK{235g`VVV^FFT;afX)~z?e@1&TwfbOV1Z}G1K_u~1q*VUyCt#-ON$z8^_ zDz%h0YPQ%ZOlu8YOiD~{5!3FsIo^cE zh@hU<+b3N6-UZL4E$bY@Jc0ghSS+W59kn#SRJfSES=*GWC`6r>Im%U3S6K(>Na|?w z0dm`PfF}3&QZv3qwN-KevbE -kmJdXJ*v$nHIIuAzDFkyoJJ$aWaQcbWnDtI~k{ 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Ⓢh8 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�{nF~4v^*3}e&OUT@1RT;406OH8za-6 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%0Ahz06)_6J4@IVH7KQ?V9`wmuPT~dVW@A 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 DamB+> delta 619849 zcmeEv_kUDH_kZqg>XvLm5|ZrRyPMEMNwVnyLhl`=_t1NhUc~hu&&((^o(obe%PdyAug_o zGczkOB@O?Qvl5e=#0~2?YFJx-zF^8?cg>J+c&6pi^?|JS{Qjr!{{L+6|BTE3jLZLw z%l|jyQai+Gf=B2lS?+TA#bHy;Zhf9JEo}*EpXHad0JxT442MzrPkzw@0H5X;&H%WY zU$7S7N`65Ez~%h>1b|QSwJrdc^3@RlALp;13-D3?dVhe6+P_wS54C@s03T?7_W^ic z`)dNg1?|tJ0Pksk8UfzT)Bb1*cwW1k4RB7oGZ^3E2G4s!`*u3O3)(m90G`*ri2`^|`Mt__3u?gU5?W5)ZPiYsK7F)FshXXvR zeJ~$ji}pbXz-I0JW&lrU7r4tN?LFS6$F+AC06eC>%Uw2V=bPjKKB}GT06^M1!vHpD zZ}ZX~(cTUMcvyQY4nSycGM)ZUdxNQ7tG&)$YP8n_0jjmL+@(r;tvx`c_9~B3p}oS$ zlxwf>C}rBq+@(}I!(B?Wm$*x@_TqfMJU^*Ody)GTYNxqRfp&^#%GXXl2%u>vcqUal z!ClsCFYvDAY0oph>$K;1*=x1qyrwnUabDAE?HKdZD(xuq@k;FocUhqwW@MIYhk2A` z+Os^-QteQdpI@G|L_0VX)y3L@*#Hk|2Y5#pY5VN}3$=Zj01LFeLjdM$du9O4({?j^ z%++=?d(6>xwFQ{1?d$P_6*}RP20w3Pt~4g8cxxkngftG zS$j$kn5%7-0VZirrUOjWwhRK8pl#*}$7@gUHjUGshyfU@ZDOe!qdndiV6^rabJ-|u zBXikEZ6k}y2<_2U0K+w6mK~;TV4NP*9$5fcu=amr00wEb zO8^FHwPt_;S`9N|f33PRKtHW&G(cail9$#;t7Jy(tyM51_R`9kS9@w@%&R@L(nSE> zwNe8>H?4$M-&J#ImM&TmGh%10kT5nLj#c8t;93O=X>ut*N{t zS=xF9AXEJ}10X~FhXpoW{d*=rn)MDFTghHuM+`UtG}!SNKk)i1kg(TndQEv`crp+7V2##VsrIJCQvi= zM+m6ZQM90P*TAreU1=9d~i4-!Yx->P_AXMZLjWA*gkMM#iju%A=UntK7w?US(tq>J^?SM7_+r6|8Pc{*U*3P!lZ?&h>Iq=ucU^s<1HfnM^E}fv z^*P9>-+$ES7@1Gic0Mf@2PvI1H7y5SqpGp-4g|HPTk!O;2m{W zPk^`8of81wQg?t!{oYh}L;$>@ZU>Y4y{jk~<2KD`{^RrTp`fLGL~xXa7x zRvzVy`s74_m((rG0A5t{wt#p1POF;}08Xh-@GvLUO+3sA_3;$|FQ|`mm*>^Tz=3|x zsT;ch99JKOr28FH39RFHR3%8d-w|~K^TlEH5#G>e)rXmehg88EdQcTX00-3ngP{BE zS8JKf`_!5|-iy6zHFU4v9<>^(&~LX|#T445Rwe`NR4bT>JJfQAH z@62J9zcFW2{5lh5`7b;}*)P1GrL0i=N`C5$viSCJltn-0@xlv#WHv4MAsS`=_q^xY zEhrs7^*cso{mn%v^KL@){MOxIPG0*hqq623UefBX8I@IELCpPDeq}_t;!6k0cTJr+>toH0@$4tLj+ssy@-eNs5@-2UqBi^*39R3DRGwgMq z=E1Y$Q9kh65|l$W&zcDcgCw^PJBxnsrBY&C=;G&g|gKqW~G*oGjF$eECprrjTtDLJ=z{+Q_4Zv zWJ4E}@sIRC8TW86ln%knYyZDND3w}xA%1dR&2Ru)^=OpVs_`geD<`3hshEl~x_k!8 z#%0W;QKj=xMwTo@8Bxr1YE-lwWq9E#lwk$yP+AI@TA}$YHD(Q_;=iyFW>oT}P(RBT zmNzVWE!CEXEW<5X7F*~)q1Qw6UJcz5S{6DlbVz7wXk+tT^HuYU=BLbs=9%XH=0tNN z)9(vu3(*CC5qvgyXK-2Y+~7gM$-#|+ehvC0=v0@WtwH%g z(}H>jB?K7*Zw0;^cqmW=E)5(Rm>p;f_&eZQz?p!j0}2CX1oRDP6JYlL!T*B)VgE<` zm-~8!LqO-Xd7WO%f$5f`>9!t_+Q_!lF#eyWkMKV_0uiZ)Lv(hAY{DOuz{72Yo`+2fUE z7|@vo)G|{NQ_|Bgo#%i{?`!o$W{G&|DMkE=X?}RhBx0Wq7pAApA``GR;P9s#iM~&p z#xC$2BP|1jNb{I~zE^8HNaQ*Hy!%=`-<>NCKCOtGnCmj;4B6I5{Qa~^v;?$mGl`zt z!bR3LvzW3COZI$iy62#&n9^&>)9!2aT=G=$@bZT>@kKj8~o(Owu8J{!M4d+9y~DczE)3y3=j)Ehdr^u$c?l;>==KKcZ-ftQmZb^sY!B7CPTEIZAj{myXF4saA;f52rs8;RLFO;UHU ze5WFw-Px#(C;N3}#5lX04lZHg@ZzH`;=)cv>MVZ1o2_?+3hS;gDMz%~rAQq`-(7Nc z2Sza?J2Bmvn3R7Mq=e|(?BOLCLMd90{Uk`+CATtlYLs9 z*&c+jCNa8r7o9#dFb?;a_l%O0DQA;#^A6=U|8+a&0l z*A2kB##7*8TX{F7i2ZwPV&5K?GkI)7j3N%~ zjm?xXcxG~9YF1*p56NO}Xo6B_y`G$mmm4_RY8C(PwTaAqVWRauvlzB7T=dyzN{YtT zrGgW9Byg112G|;VH-i4+$$hfevd<*mz&Ix`&X<6f_L&nKd3JU2cf-`SaNkCeykEgT zlNgPEefGoR;NR^1rVeJ0o@wADrw8S1CZEP+PaZUiL;GcM1LOQ>zex%aH&JVL0J`UZ zDJjU~#Z;Db&ldxI8VX$cO!8G1hSQ0T*Tmwa{DyhAxxzf( zJj9%0jx_ydx@3C6w8^y2G|4o;lxb>eG8um{UNOFE+zY>AjWO5Q*O+XKGW==yui-7j zK?51q7^WEd84?YRLVgRm9C9k;$&kGKkm(_PL)wOf2LBlRe(;fC3SJdFF1TxO)8OEs zZ-dSUJsb2$(5j$`LEVE|1sUL5d>D8l@TtJEz(s+h1G@w^4-5&o8E`J(U_foaLjl7B z(gULW@AzNwKk2{4f4%=C|E~UV{{H%}^sno8>C5%=^n>(CdW-J1?tR^19qCr+#lfAUP{3)!EQ4 zYkqX*C!MUfsd*y)Sw&hWIzKB*YsI){?a~_h>?d8UURGBNLUk3D0f&AzbtU+L=K~Wn zNJ>p<7*J7HV8S|V;6yny(!JVcb-7DtF+%j&hq}mk)#c38W0;Zbg`iDcDuy0bM8#pF zSa~=?S}ZCLE7C(^&tbc?NW6u=7t&vhrCnVh{Ex&LU9L%bGE`m)-CiX{G*RcdDByYm zae*@Onm|_P(zQi;InJui0UfiUE;AD$0-&SEvSf9(c=Cu{nk8O5B1<#HRg^Qt-6IZZ zx`;jMkfw?3qp~zrj5um$~mG8^b)RVTAzbTwyWBqoa&kH(4@jz&t8 z#JfioX`;Aw)Fw@!p+DsW41hPY;; z4>zYc-OXdfd^C?nvonL$R&ruSvTH@$+*lnYwj7JGj^t*nH#Ng`5X%eZW~(|vTsS66 z!^QW<6ls_+9k*sZs83L!F<}ksNRvEm>Wpbqau+X&Q6JE^RA6Y6(-Je>C^R$;6%&qI zr6FSFaXD)+hDb?HP0UP784djgVF-3V*xzO}>qnQ>f#Te8yEH(2hk^Qwpyw31 zpQ|$#jjl|Qtb60w)V`w2bBfeQOn6R~dW+R4dx=M%Q^xkxw^N)>Z~&_|*dtzQ!&^PL z)n#s+Y$Ux9u&LekNj4Y#*_&WmLx56p=dYYPZSfqd+D(K#FN?m5;J35V6X989rvi0XbBvlH zCcR)yOXp@V2&9;OrF+fMYMQ=HT|-(L7E#~QSWOlCUxJ-;r zh)qw{w~Ge*yT}b2&bxgNtt8Cogji(5D@f-z(_L>ysfnW9iDRNk#w)921w5v8^kH7BBD;I6nxm5p5j%O|@U8>_9vizi}Y zTQbI=qpJ~4)Oep(__ehsWl?=HRGc^&CiVe-auV+ONx0|u_Z9w*Iu#~@PKAop zQ{g!t4vI~+dX5Ee($hP&sj(id>_NlfQ%@;k{VB89gMW{m3KwtU-%0%aHD>q(GX$It z7k5sX6C*rd#S%ORj#V4MXS%mQNNI)`eA+4oo(`45#JJNo@$l&|QGD9mArzYJUN=nd zIfhj=do*HyJe^6aY7+0BmWAO(#Db^IBH_hwVS6!D^Z{%SI0Mheyl56h_YJM<;`+4_O{M17d9|83m|x+A)WbxU+3by+&A^oR7R^pf<9R3y!i`br5{eEomc z`~WsTtV^8WU?1C^?=K8z*sExLMv-))&l$TUi5V#U=$u&}D^8vg<=*SFAycK*lqLm z@$sp!I*?c|=g6+j6K7tDn>5$ML11(0-AmEtc(gmQ4)1nZo6QD4Ed?`hh{xJ4yTRZq z+APuaRR?^A+*j@J8P>n5z-QR}s$E=u)gaEk8VRrA3Z6|7cVCsI$)fRVj&ZrzBRAC$ zF8at_73eo!nTIRm&_;;$XXB;eG{^PQFmVP$JSeW6jgubu zzt`>3P~mu8f%(tD--E@t*KN`uu>yY&6!f~iemTZDm%k#omQ z+KbQLRHSTragkop+qEoVe=APP6rEAR)V>uTm(EP$_Dk6od+(}UOA}k)iffXpPeSAi z%L!+LgZ^YV2OeIiO-mv5HvE5^<`mM~ij*uIZ!2Ql+eXp*?Igmu~A6hX%744_gdYaWlRLoo!kRG58%tYA)uX zY$nRzaY#+Yo_FG;CgPoU>{7hAiRW=NrMWK9vd=j@U!)}K=(o7jxMt>V-vg9oT4E{I$&-w57ul8T;Kf*u5KSqC7e@XwGexrV+ew032AFI2oyR18@dqTHf zH$~T7*IXAMeJ#Bq?Ly*wo-`1Nb3R+~v(y_J{9!GS=vIi{+D|F)YlsOssh;i4)=GY! zM?1W`WOh^=1m2pzu1+D+g-!Yhy_~;REWCjDR8*r}E%u{aCC*(?V0vy|VAErKUy+uJ zg!diNGBOzSHe>!$w+JKt6}cZqbXwxxWscF{jQGT8w*1BQ>Hz+`kJ^*-9}+LU&(Y^K zjK5I)i*kW*d|;R6i%uWJN%O?S4;<25k%uR9#Af_GTb#!8S>hU=%oP88puh~sA9Co} z@k2Ry8k{RA>@*5rp^uo5Kh=YIk%sgMR`XrKrQ0StftwF+=TCMc&IT1}M(qv*Xq zpjB-7BSp|hiZp`$Ht4Oo{NbYOM>2xM2`C>Ft3R@f=RdNDogalm`M>ay1IqvMN38ts z;+;Vv`eOykKmFr)1au=mb|9cz{&AetPdxguV@zKr1Gd9$rk&{x+ppyJsb>$4&zzaw zHqV;hyN*3l6SLsec-i>a{9Ypbl1&V_WE7c~qF@#VUUEp?X^|0&lk>ZYic5Cbg*}&K zsf&06e|HvNqwFLCKe1D_QSXrQ>3~tM0Gu=G?Q!|-L1Ey@At8v2$vhZU&d(N4equ+K z^Tkgb(EisxQK0?*Mwu>bm*tQ&WG@3=ciCB6DKC}o%fix zjyN6)%a)%k4qjHIBys+-9Two$<#?%`uv~FSZAH=*yVOPu!r!gM{3{A{f82*i^(gtR z#GWe-@$D6(xOgQ}Y9Vf*V{;L5)ebG+>Z&X?rM^Xa#gfl~joa=anVKPLuG#`zi3oA< zYOL6OH453-m++EZT)V1BiufCU%R>ItA=&6N6a0vLEB$MNJEr8vij{aALyB1sot+;o zj-lFEeDtY3Fp3wKMaiReQQegMNSCkWvJ;%5%}zn0pn()|+Q-`9`!t`1vRV9pH|5IF#0WgBWs6Mgn)gBexmag>Yw%rJp4U;m)t2mqMQpeLQqc=tNh7HNgCZ`4#gv zbFq0Aj&0kTEv6q#@0t$a&~_ohom5kV@n_>j<1yo-IItOrYq1*)^*i2(dl7`-jsGrmC}4^kd!Rp zA{d|8d;DiBSm&m8RtgP$UKe4s6|BVr@N`Nlsq>|XP^DlE_RH-yr=*EPzeU6stOlpK zpJXG_PIh{mq=HrS;`{JFXzM zBczeyi7#QI#0iwc#V23N?T5J)C{zK|8HCNlfsZYC5L;2FYi4k8# zi3-5wfcw4*6PvyYheg}}RU9nZyI;wiqWsDZi)Q@VF7>0WE_(E(7lWYh>;-+qw6Eh3 zq!fM4LCSWNJ;m9t?PGg*Ei2u}*cWv7YEJWRjxFfs_8dTAUw_+L(3QF@(p$xfZ;(Fu zCIVJ%^*69;WGsT&vlZls=fB|t&yT-R#&rO#>z40M%z6+FtpJM&c%#!bR}+3Q}z?zPIOCT*eZ1k+V16L9<*C zT0afb!0Af^vrsXPiMoaWeQSYHoc^Apm@9Y~LX+UA>k5KtO^7}QO9~RnKg3CaV(1TX zcFq{VRIx#IIXoVQGPb~9RR3U;^zwrFNxAEe$4NWHxqa3G*2 zU`fEpfc61a|3CddMe6Nw|Ft;U>w=>_o&F2`Yx-yOh58x#KKj;rlkS%8ZQWj7wQiwq zsLrVimwuMsmySv#t(3+}ouoLnK@_O!tzB?mt8i7ltl%8qS5^vF)~hIY$m$`5w!#&n z%WXxhzHJt>Z->LathuegzC3nYhJ87Ho9)XbJb6g`cAM=>#u zNuv2Lj*b)SF~fO^H)giN3H3Bh$?&DAqj0=f|4V#48=HIHAo7ep88chqSeoe%>s2^L zeD;f78ZG|)#UYInj$dUMl8(R1!6V#}Ng7FtKEhbY_ikXDoX%|OI$VlqtrQOPwq{wG zUe+$Q&}Cq7G~gOQSNMQzO+=8y)_HGeqEw!(p8&Tk3~N-4_z zV#jYVDB|pIc01pm!OS>iz##@G;SqUQ3;WP}7uX*u>@6I>+r^mQjiS%*jbLZS{w^cx zS@F9aQO~Ulx|nWCVK*S0g1j3ifm3k6gRwmFK60V!1`Q|DkS0=VmrMLc>3#|?K(;^>`7DOAcS@1L*1{NO{VZ|thsL_XXmK6yH5UJ(j1tP1&;2p^G{xQkqFObW)r&gN%9!dXy6M5)>)*1)yTR6iUnVQaH3}i5_oHrc-w4 zvZ7qNV%OW^ZAFtB@Zn1YUXG8gXd+4e7<2+T{PFU5>f|rkq;WKcYh!7pKjs}nkNIQ5 z(e#2pP##5B{ekO9y2}qoP;3CeaLNVNXzhW+yf2s^W= zY)o8~&SbX?r@fxyUNnSXb~ihHwYyw2m~ICE&p{Lx2$Tj=yFk@zO>tcG@z}BZyCCTpKy*9(Nrnw-M|m7Py`$9p;zUiUi5}TFL#xTdN$w+zTw1# z2d;7vyYg;akpTB~lw*s!Q*IDw+l|%&_;-bv(~}YU#voJ|a!PuoiCol~S&K7E5L0(H z$ivgJ7ImVb66?yM910J{N;^_=Fjm@u1~F()bAvH{HkAZRvLTC+f&R{N(xF%>qO)9- zS&ts;bstJwi!$nstXt`MEX`Jwz99rNq>(*DvdXErdWS86HsRg$AeFr+g@%QIW1O@! z1gw%w#I+=Pj%$f@IRvcIjyhc8(6*@U1|81pirNq^je%cVQwLW)ffgFDj8;@(z!F<- zK+Z8Fwy1?W(4m^y`pEdA=I+HYo$f!4vlTU?0~iWZG^IGBB-0q9WT0L~NK!nFHDV!g zw9<&d9du3ypSQ?P-|F-VG>1~JeAv3*7f2V$ygz7y!Q@*6zOrp|H$!nap;+MGdGe99 z$m%xUu5j2#4s1oSdKzK^uH`1+y3B;bjotj$Blt^dOnXc~H;Ue35J}&fu!aZ=;7Xp+GE{*6H=pJ(Qv#kTHeNu=v(E zPSd<)-d+^QDjk<_z-Z1C)|B3HilZoi4u^tc{OMw-nPMiB;+C;glwpygaZdfCo?W>-nri{Z>!{2ERM*lDbi;MF1Mo3)g{$ct;IS~tC`n7m6poII zX%Hk!SNsso1=QP%7txGxFz-U@2diSV6)&h$8|gIkO$jFu#q+5gJzLs}=hd~~W|I@H znb)qz7SDBauIO?!Qdc~O?2UlOY|3c_I?kf;T$@R28UceD^caKb^jsrgJdGqcf}wJ; z>omZv0W;`~Rf>pfxLt;uUA}54ws)oF0y>Uu$!;u3^voq62YKnU|kimV>;z1;Z}vnYpanKUj2LuJq!ewa=hV}N2B9S0cI;C|!YwU7HP z7pH*ubtrRS0OEVtiRfZy-8~E6Jfc#ZOl@N^WfG}al&(0Dw(#QQ;&xOT3yj**P6lo0 zb?()gPGfDl;sm;aJOz5SqIfHsTT&M*5N<)^xz?Q4aIG0_WYCn3;bB}8MzAjNk09Hd zI~~RG^otd=jH5f4+*s^DZ&zZ&Nz!0_1gL2THSq+mvJ>n5x~*8DMK+L1rfM4yu+e_5 zS*ZrOAzg7S?Ng8?Qi@|JM22zcBZIFqWT_F&l;O&aL>`AqWGK-kGI%|bO3?{2uuH}m zji@unZua7E`a+iC;=)|ZaLFLTFCQ0HF1FA)OcYlfTF*haFXtPK6q_km0h%USk8lH8 zdou$AokSple9u*`1rq`!1a3s70dBFr-ueMm@3G}#ool&->$S0xMCTC~L6IW~2frYXLXcCN!1;SOQd-X@rJGQG_pmrj4Lv&NOUe0(^s9Nf9ik~~6I zrDP&)jpjQkB@?JeQz_0do~czQBffcKrDPnPiH3qH8B5or`Q)x-44r8zIW{zdJ^rF8 zP#8s0Gc0Z-#Ww@%jG)d8hSPX{IE>bE?Lm5+YY&hTfZE4kxv?ev$ykl^3b~{o9c+&2 z`_jA3fqx(Rj%&Ti*aEd)boqPuqe@9n>eT``_n_%5Bzqnw-tQSXC)j;ho6AAcs1%lw#vLy5@A} z-M}zF$wT+rN;=TLAM50}512#PTvw7o z@5VqQD<$dFrWNRrM*UmCe@Ladtw5|4DsKg1IcaAryq!#Exl0m#1rVCZ?t^PJI8RF^ zXMz+PmCm^n9|YS{*95%Wh9)Lp#MZPf0plmomITOLD>}muTheFfLUL)|j~owMKoMt%R@Ey61*y`3SzPB(A;{o{|qf))GfO-pCw!Q!}Q- zPCvAktiZ+41~|*K9()8&veBOfE-G1RdK(}TOIv_QoVCQ2sBuUAI4JiDvgML!dZ`Uo z(U`8a!I)9>M;k0TlH|4^Km_Hq1!Wu2pdWBDZ!Za_mHar29&3whSJ5hn9WST zGB8n8JIRq_1V7X%4#YueUI);NttAFt9#jJRNLZfd?K-(6gch{}M!{6WAczhC(9L$R z4j;FJaSEXC+F^EoG9+R?J%vNz=}L6eClS3Rn!&)2iU4%Qd9)p!f?XGMAh1-sMjw$Y z7xNddbppiSh(e*yynwxU6?IJll~z&`FoTb@ zg484_-nhI$HSnoWL^FHwGEe1?pgP0*q){$jdi;wdDN*Xo->fn@5!(SceY%y-t*5pV zfp4}?hPQMM4Ru0PXVW|<_G=b}MY7^6ok=^Kpw$dI3t(`4!RlfXS~Sr=!YP-!zFKv& zjnf^%d88th(y3llN=c)kDN;-(Oc>M5+fvA-lj|rBr~H13TT63EO#y0?Xmbj-b|Rfj z!PZWot6UpTe{gLaSySP-j828K&?6O*=NKA;2T1*_O2sNhQ9G<^g00kbClpw_ZV)3r z@QiciQrAbT?ll2T_PafH)>b;)Wqn+(4Vu08T`3(#;c1xhL2{;H#s_Ff8mKyy=B5G5 zAykHk9S7GrnZB`yy%b+td0n1N^>#vRr2}b8BsjTr09|px{uGyvY5Gy;bd2AZ#&fL? ztwAlYHv%`@4&X#=tJu_@6rsZvDBF=GN1=K(SAIKl0VO#JJNzEaE`UK0~s=*cY0+)2c&00 z6=qZKO!Uj584NP1I1}A7s3J;lGs~r}%cU+QoF#5wis({`?>FvgWmW>-$F_2*>*A5C zKfa3b%?8DkrcitqRF#uDW?`~q8kdFjB+)9aCDLOI+R^oob++Kx(zYC*XHo4`Dbf*J z+QuF4;%k!o9Ffx26qb!Q6DXNMD;koGQCrgdY^7W_y(Zx>1{7|9oT$AZ60~>t>FqS`-s8ceK7hgu?k0rP@1s-!?#QWG8M z2y)!&2mARArzVeiuBEa8Oh9%8bRIn%fa(Nnw^6+1W<8~q>N|x-K}u> zd$IfYMPJ{{_wRhNhqh8z*5AcWP)Iw#Y>l;S zCQW#Rm3!F?THY1YPNxk3In(MH1|;yA&sH|Iq4hrU#g+g+g|CX=}vq%N0Qb;E>{ zsAo5@%|x2f4Kgr+O1fdP@wB5Gh&GO12T;bc=()aE^v%Uu%f`@KNeD~JMpImOjE(D? zxA6UF*+?4G9pj9kmE9#Jc(_|y(`aidGD~H{>O{h&*nO_N*~%WI3wQ@gd1yG?YFpV* zGWI}y2qiEWOuc(Z_73=x@1EgyW&1sRRBPG5hDKkP%U(8sp6r2z_NOyFr1*GF-`w-^ zalbCxTY9Z!eQ7oCLTp(ditCB>^`?#tdeNw!h-7+!z60l zN3wTHWQnOa>--U<2Tg5d?dloab*atE_gBi=(r4j%rKi2Dji);X1(@aS0NBe~dv<_? z@?pKl8H1xNfj;a5v1moV^#P78DY`F~(SkDi0`cZFf@{q-G=h~cYl>_uSj1M=gbwz_ zLgMK>x5m*et~toq598RWT|fLiyC1aX?gD)yU71XC`k~!MrTx&`N;^>ti3MeGG~+~~ z2zLNy~*sB3>99!a_VFrjdsAUV32U3=mV3GX{?Rmw~rGKBfFd`W4f zeN}o#ysgZD&2#6$>P(@>*4oQL=*R#mE+qJ#Op&t&^QZm;K>$6ygFS;%)lu0%kU*kc43GtC1RH8A&7;!=$VSAL zt|McFKDM<|y4F3r%T(e^P@fn)wsehq_6)l4s}!LtT}=}PL9ABMBp4D5xRM?ngk4@i z#|B}Z<+L^eN#@dJw27PL(xntW7|)kb@?iAB>A+yT{1ClcrH_rXmM#J}-~fz&Ucxs& z?kHVI+XhSV4n8obi^K2x1Vt{LfBcKVQVWR>b%$b}>C~D54s`+KsrOFUT&l~1`{nW} zw7!jAZtf_b>~XBaH=KPBs_o^u^y*M4t_y!HR5VVHJ zO%Pl81lrO@Z*#+yA#(161)K#v4jQ+9EMkK7>ibdVGAf>#21J|-pW_yP(w(@?o*EL*U+Byuz zxDTBihBfu3PliF=^rAn8ValEqI~tKrNHdSbXFN4U(h zr>ZXRLI=r0OdN+z!8`Q2fHKCmQ9uXFpKsu$fP&9 zX9j)CAe}-+0;EyGNVKI=?~!;fg}SuEJ%T4j!UO!WQXi=+Po^y+F=rB;WROUoaJP1J zhhJ(-jYmn2j&1I(1xH!FS7WT@t$AVWGUL;BAFFCBPoPDk;D_%W1;_KzQOF{+q<#G0 zyHSXEJ{pCHr#amkg~c`_%V;d9DQ^5@{w6dSfGS5L8?kgWPAhP|ax@m>p#7tPm!00> zUJBjhnoJ>M&}O5AF_Ij@C#oN9QeMDTj%cFM(LHDP_%VS6#gOQ@?$uStIF`dQ` zaNWZa^)V);JQ8f-z7a*qCOx9V@(5~^$jOEBMwC7lXou6tv3Ng>mW>7W7V4L%w@y^b zeeTw9nBgU{tfQeN-7dW=-Ri;Z)^Zcpz)BQ%om@=fC7ebI8;9i@D0v)a4xz#0K!~z& zc(8072pmM^cn}!qlBEqvxCL7tz|vm#C92yE^*9c)mHWGu67JDC5%xgVJy2E3^(2kQ zbUKP>AW_%xppYL;KuuScM|tCc#5&r{jce)jcu;W-U1hMEt|sz{d)X?AnSggz(jOp> zu51Mjoq%_i)4~aOXBpKnSV{*cfPhQr!UV|IV)_nUsP#lJN#luF)FNs#5xo{t|A}~Y z0nMHWw{AWaacv$wgSI%%#nibX97n+c^H_#lHis6%Q$IFIvPjZY3d;q8Qz$VP?@y+I zT+5|7xxjJ~mE>ZkiL{f!1bTzJjHj=;HjaWOOZI+z4c#3k;Ml<@gD6+FHt%fj^0Sxg0Z0rPfrFG!|4jwhS47k9;DbQ2qqqIZ7H<6ufn!h z4E1!7;M`_(%YKI75sBubq9qwQu6tx#8xqYZchPi z`jcfU*58kk81$vVQ}M75&6^73dQ-(z$rjuTM8QYUxTN_D3ra;#I?Js+=u3X3I|WQb zcG8t0cgrH2V4r}|TG6$hHtySp9=cJk=t8;EFkoj|KMj+2qRrDlryM!~KzF8rQT{s( zWb8n9r-6^!lXW_JWz*JH9Fps!Cj>B5KLPI z|B#l=t?cmGx{s@2t!PY>W&_Jjv#}M$v$6I_dSW)VB7(ZM=G8W$iLG6$45vG@vC1%t zo&#W^HLdlwBwIzpX(*Q98-Z8w&t|!W6=cuOpe=Kdz27(o(-`Rhk7JpY;}hItY^pgj5!3)kDq*HI@tfYOb-rHdgnhLSc926Z)UoQJUH@;u1I z*?CZ&E9uHSP;3SLIS-<-oaFg z`PO)y(BL#O-8;&QEnnbvs^K{KGDmFrd`eybD$Jt+4Cd0z1(pg2p_AxrUR{4B2XHrR!GWz5VdE6-woU;OIJ2 z!Z~%{tKpTd+lwv)>(2Q+#Kl%Qlzzli)OInLCwejP8cgjL1BF2}V6hZybe&XkIxRg} z)czJ}sN}mVF6&H({)V-dEBiCK-CS0uB|Q=m)=K=+5$^`4C|O**zKN~uOV<};)qO}> z0??b{8T6vAOR)H!^j`sqzYd89?8PmVAD}B5Kcy^)RmVo6uQ_ND- z@NrOc4z?x_)UI<#ck1Lmr&_6W zc(b6-Z8%#cUrBK*uDUSSg9T$N6-r)-Ib|BK605h-{FR`Tm8w>Pim`NHB}f!Q=K#pK z3exl2N^ogoGOa>$6t!E0&XF{56}y$Iz{E>dp>g*r=+up?aOMzBd$>m!y}b%dWT9`+ z5xOUEHSYDg^r?GMP`6N!9&W9zlD}@PlPlJPUUo#T6tTP#_y7^E^zlRXjvP z(FN*w!8(kxkbcN#EnTsIcCUk3|7IP?|M5C(%{=;c9Y&l>_?kh{Rm`E5d8p2&UU^`H zSu`^b8$6Rr^Dy}gn)jU!eWugKmTX6-(bh`6_1JnTM1q1fsCaK2C8(HnEcFI(jH%~1 z7;>L%zO8CB?b2AZsz%XP6*!Kh(<){eLH}Veoc`efhY@~wkS~IC&`^7T#&B&Ytza;O zHfZQMn2rJD4RY@ye+P}<81>#oxr&`u4<+M$DyvitsMA4wk_aacUvYb0e^aXJf_+wB z&Qz#zpF0Uv{q)McMDhIrk+rHXEy~9V`%qOrR?(aGajh4<1werX*ot5B!ALzQr~vEf zPAv;0`#4SxyTuhh>WY$W;wDLtIBZ-p6vbsxA#L-~V+HdwzD%Z_Fx482!vU=~6t;$J5i?FrHw4ewxB~cXsy0cHITKW|Gn z8MGloF+gidD25TARg7N4@r@ds-`T}LuqBlhW2_dm6TL!QKO@WOMG<~BqEl6~2Gs$i zeekeWHFY~*xc7eF`J-IbgyKptZ#*50hkmY#qjP|IxynJS__>`nmSBGsI#vQKWcrAK zjc&&4t)1m6c8%+F7XRS3x94W9;si08`S*%kSa~?Ua#aisF2w}VG`|!JYfKfTlH4`Q z72~;n2N~4#=&w{ox=eyQubYBVy{T=jieSGWjk;WsqJVxQ!f&wP+aHQ61M=g`pfRU6 z;V%oSEHt4EYY3%v49qlXBjmrzL?_V^YVdLymTRCVns9tr6~YXGvtlf+?uSJ@euBeR z6-?jV(Al~vRUTc)=Q}#;mJ$r;O)COs)v)PmEuE(x!Bvya#@*ly%z4lk&dvt z)eq2n9r;Fe^-xx}?xPGi!zn&jWR&V54ek8l6@O*sg~{NCcHjXK_42WlYQFeaH$LCE z_Rh>UT`X6-jDZUQe&6R-tgU(g9r`~Iy+6Inpda00(3gw?6zxN;1!}#i4}gO+7;YVn zLv|kn7gODn+T`G8CaQbT7JjEYonp|9t}y6IcNuh{=!Y?EXUcdO=dhjJ2A!Q`$f}n? zug;+-b6Cq%ccdDAr2`#c(4NjejB&E*I}AW=9)UPEegrh{&wpj$FR1GQkANl8Y3?K7 zlQc?()$L@hPGv>oib&jd06e@wTXjnP!dMk~Tf69LC!NmG<8o(pGX3=kxH*ZG4VWR3 zau~Fu@f)B6AKw5+uWSQcj5f3h&*}08V03l^1P1r9(F1Dw5ANTRtOUebP$o(Cu`V_3 zLJPlu2Yuy%mR#*p+OEcXCng@vw(6$!Si?s9Y=^xXr*{No(6)4WGv25l7HNpEd!t#+k|?*)I}PQ6_1`YPXzGdV9y5%JZWz^L=J z@4uPpsE)?3QAqJ|e5QBrNaeooTa@Z33aZ3GMRg=4cH)#&bp);32n0`T1Z8(`grdH( z5o-6fjfmjG=;}tGZK1z50_{+Wc?<+LQziowjR3$szkAGz3&Or0Of?_f)wvt@B|RL~ zA#~_5DZX>Chmzpmkq3=EMblax1g7Hawvbz2|5vUKr0~aqP5>n{@Tb9#gZx#GgYqjM z2jz8C%@5vr9BX>+aj*$~EAnw%-LA@`n~!5r>nLaw_HQkn>BL&RY7Gry|1qX&HC+RJ zXwxRF)Nliux@sjkZr~QAwQ2>O+Js$RPM0@f%4KwS6J%v6ML!`ariNecO3$VXTcik& zs~)gj_qkm48XYOE`);<_s}@o16H;8$g`VeW_^Cr&ze!5~g^yZ^quurHsv3-yE9jc8h0IY-hbKu4)!`rY@I;AC&er;WO#rW~^`qo!g8RPNzk9 zhgxpoq}CQ30QcPj@}_M8d8bgnEtq98&EA5Jxm3CZq?kly8XKUhiFB49PdNVN7OABK z@7uf;&BLh8R=o2d_2=3HG;6CQw;IZv0<{27`+i5eW{8{f@zt}){Wu~dwq`JN8W@Y7 zTp>m3YVc_~4>gd6e5;G4%%?zu=1*a-`&0X;u=sv7_9-;?rIk-%-afREL2r8gDd5(N zE}^YyPq%|~FPD+xL0fB050_FCahGwMt)@FAKaIh<(V(X>N>`fyG-l{R)eJh*!KZQ2 z6F;GRPXZ}^iyogX)#Nlh0w4Qc%dpjWBs1>&VKiG!2TI-s5uLjYy!e>FHGrCInzs!a zX3sWk#D;Cyh)mkM4ftfxqHLJ@nslnphN-VfqrHG}H4Pumz-{(nLZv2!_Ed0grN&9K za7|lRlT7QM!6K7r^E04PBAwz|JG#Q4E!}+vGqs`E?EtMQdpo)$(5UT_Jg!x}hJvr= zn^(8haF)ZZ4j>A?%A%(3({@--*jb-eYfW={4>KUgJh445tSPN&uUDw|4k)ZFE@tfj zafa`}uE){r9l*>%WjlbGopv!$=#3rNA(_72;mSl9cjBRyHnm3-ZmWr<-a92FfbU7C z(~qTaPvx3uD*G0JX-#9=iZ&R(7k6URNV-nO>mvB?v6M-yc&BA(h|F|>_7_Zze0NTGB>-VSk__3aDb4^DPdjKR#--EAv z{4g0iI&fkDaBk#zex+3B(b7FQNSkIdtr6w-5xo6 zxq3C--UD*B+l%AE#(VLJa-6Vwt%h!S6%gd zTD=c*&ZB=oD_!+mQs7y_HJU@=8b6p#zvF$=toqGJ#Si5@CPg@AVpjL|z+v+dE^GA+ z>IhF2e$8}RupdO9Ml}qk(xLrQynPB-4jALi)BUTf9+6gT^5 z+qU01L0LV4W}=1^NeP2-wDSO5$A%L@xH3Mzid;SB_!kFwpC6#WLwIK>4NAwlYlqOB zbRcN09ZZuBK|&rs1f^1Z2$D3AHXXvm1L(vd>`8z6glqli4r;yo)-M{F1RrU&)$(`j zbtJjZX_9Mu*OSmmT?rRpYJ1V5XCW;;sp?rw(S!Cq3lepw^Uq>lIe7$h+i?WSIF(LuuN3<92)55jcaH%7yMwV{1SfkSJ0=O{2rpc@QY zk%Gx|wJj+-L$7p~Yg_Q7u&wxPkW=EIkf)lcZSLWM@qHb>3FgtkR@;n5XTYx1Hl_Z! zR}EfiLN6V|qT=b(W0*aT{yK&QJLp0NbCjL3j{^&ZMglnG2J+*7h~u49Qfh51 zt(6WRm*R1k%_YK!m!$>xF;!b_41JG5^>S@Ag+GV68dEZZC>s16=7^+u&tc{Ws^nTD z+Jm;ha94=!x*d=A!sshJ%ya#6u3Hn`f4Nzy<(m?9ii)#+zKMfcz9~`H4h`-7i;9co zT9a2Z&ab`cho9(l@gVS z>*=npuCA`GuC8il3m19FA2m-|qGSAI8a(_fn+)>QLvruu;(y}X2kO(L0^g@e1)bn{ zn$yt{HS|G9q;TLWdk^i9uz2@=Lb2Lp8lWC5#5MWxUUWH0 zL>C}}xeT zpCKAnA@&S&D=}cWNLDMb{tP?I#GfQtjwboI43qiM>NvO*Uz{Q5S^}SEh$)J#m3ddS@*bq(GO3+_h*TT@#y+2aX1cxo+aVjj;WFxi>zmftTDLn zSrWj@&r)>y%d;e}QFw&~M_w)M#ShC{ zLl=JC?lL?!1^qBhGNc7Mgn5oro`g>lL=rrli0f<-Nzaq;dOuIX8;ar2v)&NQf1W)h zVEgmjZ{pdsYXR}FV%|{>4{lvv)EKl|UWXZD#QkHQcT6;BKOBeepC>j3qVo$J=K#b> z5{nrx5H~T%eStvq$9_rr;g}Tm#VapZ)IvjgCdNri?c_lHaPKzmM($xX*=A*8f2WugpfJg@xyTNMJkm4^r9h-SH4IvBXR0QBKG== zMC_L@azb_d`XYy>L3@egRWafvj>(RBFR`)>n}%4`mHOd`wq+o=G;8G!hqrwfG9GFs z^X?ws<*B;K;^A-@c$YvQ#)m^&xdsJa(yNCGNIM*Y!7mf4ZkQoSFmhie;9YS*k}h~$ z3WM>S4y&VgqFI&q#9}ap@KI*a0^sXNBWccBLTsRaUWJ0TYZKD%|K$A&Oolh%8V{zW9omJA*9h58 zYY+SLdYwbqgr^Dp zDD{xoD7zLJjkL{+>`-p&B9oWtCT*gACgYo3TYqICGt_@>% zHog7V56y170Zvlnog!gv5a-On;-`gaSAI?*>>;E>_Rm9soRF6i?+a#7znEW;?rei%5zclw^ z8HV%AsF`!7;;m^``wHEeLXd9>aqX?&b*ET`vksD7Ke<$ z<(HL^Sf}uCPP1XlD@O;D7QrbzT)xvYWJaWTPIC6ZwSTa;Xmoj(4M$;+B$1f$E_Xx+ z?wl^Os-u$K`P!YDAUzSE(DsdUEO9EO6W(kI7x6sQJMH-RT|#feZ|`#9k9?1G+wVPY zrQt|^j~#T!qWAbY4EgV|^H7v9SrXE^5_pC-9Vazsx7NijJkqphYEC1fhM_8_Zmr$( zKxbE6m@fR#*#+_MTcXAWd1_O|&y#QukCm!BJ>8>=vncZj1MxFk?5jDAXYOu>>3YlM zvBd07dFIZm(99ewuR@)E`0jlU+!sL?hz1|TUEr*C!i)>V(*6s?QvL<*F%MthD!>IY zN-G|biVEIf4YKyD7f2zu!S@52-yJSQ-w)W>UW{j=78v#+?#b|=S;yf$DExrk>_)~6 zDlrb{W77<>3j5(*_~-*Rw-eXp^A4yVva9V#{?MXzGNMro$BYM*?g57ljkb$xi3hIW z!&_P>gL?=k17|;^Qw3@;Ow*|Ibt;1Ext%d(bOx7SXo@X2V@M?_vh+kJ>^+#-VCGM54D^L(`RsHRU zB{-41n=`zzDTkNivV2}v{4twf3dhGJ?IjrbG0PTXffO#nj*r>gLO_xQI3dY=yvHhw zZ@ncKzbxj9ZuRh7p;=;vT8DN<2ijqA#Om6$TY-H;u1fSill$C_O^eL>8|=GnQk(+|C8TGV)`Vj z7N{K=Aw!W}HVJo)mA9@(h9hT^$je8PaP6OLF%expC6vPu_bGEjG4)dpY6$kRQsfav z<8zrPxi@ML*~WGx9yOnGP6p%DrySlOTw<57ea0QG(`Q@*1EGCJPzE67Ga@Dy3qE5v zF}P^}-XH2@D-X0s+VsvOLo)+VkMza)&j?l@e8*p7;OCUjY@c)c?1i|`*?3P(mxPYA zKWF37c;ItZj>1Eqvqv65q|kvcCDGC83)a-oM-mm|ndo-1Lh@Bc5jKl;>Jb~xP3Ce_ zk3^v63$_}LGheWs?)c~nHcn?7QW%PeFD(v-*iEUA`ejt-ye9 zxSBGtX{s2ZIG1D9Hw1ba{`ie0GGM7O35FR3y58i?nR5xQy-UA5&c*D?2slBiF-wYe z=OS3XW#bFs_?AOofE3Bi$AWL!|2*tu;t)ww+%dadD|o)ARGo7WHO;C;It^oI3Jp9$ zn3sy~oQ3bcWGKG< zHya*;p#LzJfPqY~;XkC!x&I+;4n~%g55m6xaGY^ymSiAa{11OK0AI+rSakfs64fWh zO%1%4q2T3xayUFY1ToKk%o0QTPMf>x0T4*j{g(mRv7<_ygB6A0Usn z+5*&~9`1&R;ZSY|a*Lv94E~YzqA>kO^0@ncB&=J1B&rraF%7@MkP_bKX%rG3Khi~P{_XF}?WxSt8P52i7}zMrWJ z*!D9~*%9|kc?Seeu-XfYtU^%YbW|(^1c{!~XpxI|x()7(>p@R>TQ73)PS8XFn9&g&4Gq8%|pXuITdDq+a`J=H7WN4B|*n+>Y= zc;6d&WGf!H&LzDCk4dr_=dZJCy1%&2t~Vj*SF*Z|i20SdT>Q4rYKycT$#Lz*JO~(r z@sc&NQ7AvjLiw)*dIPRa5bq1WhEZXh$;f)(yh59N$T@3_-uK?otexDB|vs zC7AG=CDO5&%gnIz=H_a;oQOQK2zUR+78j!NH!ht8c!|FtgZ@%-^Wb~aqNj+kdW*vw zi1yIj*pJMSeabjYwl@$xG8>sU3D_*$d6UiFff`9N@VA@f4!_)_RB`1dg~l1U&VHzn zj`*FQr(yW-eEn%e(HtTNpzg|%DX8Uul_QgJ@OMtbBs}~(o1KW)BsT%0zEEsWC_Lzl z0&Onk^>MO=;po$_(4vT{H{ZgKe0}^AwMANSGM?nuL89apR!j-qWoGX&;r3#~ABD`O z5nq);GNKiwJ8X&)iYbcXk0ky@;dQFQriWpJ!j6VwpX7$1Sy7_s++693_Z6iZ5AjzO zMf^s0w(|2J#4_m=C)CDPdn=(`0uc zctC0}hD=9Ag3@)iLdaN}xtvIx8 z_Nb2YK4q)LhEBjWx4dHDm6`|g?8V(s+lf>XjAzDJBk*%4B?zB&Qo8dD^J^#0QxJ3? zVyQDydxCG5-l$_y|^wNh~E;zC8!SG@FfzT_9g0W!<)V|vMDOWH@<{o zFFN}XiUJJqWA}S7S#rCvUUK<(Y%Ety(Js6`mdrpa+KIpMGk)_UFJ?8slN@n zKkIKrvOmYZ1xx%n=*`&c&u@9Clw=c5NwN_i%C}tHkRRm09zY~!BPoEOWMQ5pyhsaB z9EGAJb?t@i=0+%**xS?Rl7!6rt)YHJGdL_!V7Z>v+KZ;+tswR{4F^6~C|^#6Ul-2F z6!c}{Gnp-O!@;$B@#tMN37K68;zZmjbta&y3&9_czezIg#6Ph(`qt;`rZ1 zQgRVuGH%e&_9&XN2nXQxYdaEgEtu#UhM;ath9b5bF);*_BuT*9ZbVN!GM7-*r(!Tp zS8;Q-VG!pmWHsfKlX;Ot$y^g!VdbPVu@8v zjzAyUS5aD|JRunM7?2%?VKJA1A>VqBRs~&2gtEDw^i0S;dSGfOTaCv0P;$&D{4tb0 zM&fDq5oL#iq|xdqo4t5AM$n++6Se?7Oz}a-FeQTA*Ad1h?MMw%G#?w`BUX`-W)1O! z;p|h0EIyq|UJc>sx|Ar<&>hF+M`3s?i~xk<>o5Wkg23)fx?w5eqIUMF1mMB zBC+14bisU^5=#&!dGEhk@ygbD}C!OP-k3N#j!+2eZ>LY=$#90uZnaDcz*if`$QO3ITX0YUoFZE*aCg+}f z9=yEQwWD|z{>CQBpKdVtF&| znq5(jn@nr8Vlk^|oqY2lLn}7SDqPYa`J?IAYH^!Y9jDav)mA*giouZta6G0&Dyl>f7ch2d$P?wh+0Uc zc}Z`iFQiVOq!*Sf6cf}E!*;;{TGRsO%cGJWxZIOHL>KpB%Tb8x#d(j!=w58nfu+6p zNyqU|DF#2)OX-ZpUKE2r?8UYJYA>$+Uwd)wf59?}z&E6U2xz?(RS$RJjSjZWT+m+9 z9d8jZr6de_y$OCO4)kVUA$VAF-S8@NlY?8C#Bf6{_B2N*>Do#}ysb9VfxW~C!f1?F z-Wg&>9|}H``Vj1bK3rn!_!q_Dy?r>a095uN%>FpthlBRR$CC5K%{~Og2X`$J9ZN|k zjOfdJN6cfAZYX|@#^ptZ>DpZ@v9^LnvDo}sFHumn$f{3slz4~QGORK^B|t~XZJrj1 z9HlA1tqS4%a)qBDVeUes7~aLTo<%=mSQ&b#P&5=EqaO#n2b=nFh`Vu6l6*Wa$u7Lr zkJPjiUo(f8{+!Y7{ki3AM{IxoW*a8==lHkcgGHP*Y{7#iR&}(7wwD{S0hv~#28qPw zUMk!UO*#)cTE%5)bt8W7&&kiFS8;ZggX9I!kV_O`dnS>%qCZc6A-%McwULmjw#^cIjtCprgoGZIdg_LHEOPgVBMm;v%E?j^D zhMNm`e6wRLrVk=!?i<|+1xwnA&j%?(E##{9c!Dwv zBPAJ%loHW>eiSE3P-z;jQB1ojdKTLNi|fvytx zc>oqBD4HXd+{S>jyaoD|(tbFfz;65Enk0P?JcMg$ z<`51pc?gNM7cy8tQ8;f1yX}GFbA`8*(lyW!Vm}J!=32wiVJNBO-$Mwc13p6urH=kX z`6~^RBvG+`C@b4>?@+d3L!%T%;6*0M;=IR25%g;6{Wf!pt+YGmL7t0K1QeOnLk!YN z!{}w3&4tp-HnAOo#gglW-I5DN$uRcO6@Qha3*H|_pn`B+a-CsMB%uT%Igz;lEJ`G7 z{LbQh6&PMkrb*d2>M(SjG*d`xLFj;EFDOLoZ&YU;}zdUK_(9qc+S=J>|5LO+<(= zqy!%1rgjKbN;cy72u?^Y-Wow3orAAODE8EBWKEj@EvMyS zp7%s!c5Km0+9Ys!+L$oZ+vw6>vPzbv!34R(kaRp)w_36i(aD^I6-bvP6HAhbrsdcp zxn(GmWGVidOe$W2V;pgyS|XQxZXx*Wk2HHLk=R=7Kn_60!tjzZ7GiJ;n_PeyDQsju zvQyaPJnT#1Jj_L7iV_*=;Vqv>0B;#uE18Wm^F<(|i34{`tG(n7M5nT;45X#9shL>J zT<;lfUu9@DO}c3F)kt7(R&|)&~d25V^f^oJoMo zV%WHJa-RQBh_Ag&yjzeF9Ehji2eqsRx{M`Q(HJo*Ss+MOH z?e;PqS^rd2rA)(1te>I^fCl_zX>ioXY6xVjPDYj7TO}JdQ)Y zeH@Rrd&ZGxuN_C89fX2$9DHX~jw5l=)x|h2rT}Em=5z3}w#U+ZJZZjRD)VcdSXy-y z^37D4FXG25(LH=T;pC)>FF_BLjH9d*wvH!WI>P@xYb3$!fD_}XHWg2Bx0Z!z?K;X7 z47ktgh*rxioR3?_WHXNJWw#-I0w=GOzAz?mTzio_f#WK`0~3gcJ$Q&8DQthj;YHa? z4S)IM?S`(*TbrPl?t*0^Tc9_LiQMlNO;r5DsHHR!fLgj8izl+_ZTM}rHKI@}bs49* zu0GotE~urlH@R;<=`6^5SvpEL3kP@a0E0;(rtnsJsq9v__JF}7j8lathaX?M$(zL| zd0*jZr5j!QyIePuf=v2Sd#OY6owro5wiGu#ClXzJB%On!b2E4`s z9ss_Q&+FhjnYp#-JDJxMqT(?o5r=+PLWpG1oXeiUSH9-yvX!pFos&5uD^bDUa_e|n zl1#iW$#VR}c2nCdk~vK#B2-J4wyw_qak?vAf{ZDg!^Oy(qC|~dKs3Di~44&q4DvZ#?56q9++cDt&HU>x@EO= zDwhAKsF_-+XnkZO71xrkxK^GkuynEznp>8jbYnOV@eq5|Qh7`%LnM}%kWM{BRK0W} zE>9y~C%`hD;#lf*s?7RM=S|l*q)q33dOH?P=LC+$uIYq%3|)t_@@V{3a-;AblhkyX zH|dyiiuv+aElq2i)pifBBT7?Y`BaIpI!aS8Z3g*BGID3IgOPY}274WW)VWsGr&OH# zllhM>u!i~COOp&LEbgI%JvmdMquW8~nn6@g%OHYBWDwQa8L}T_DB;}3?#$&jRvwFL zBc+QxR;7yP)eJV@4_74D7e05e>pnP>OHS)3?~MtP?}c@DD3N~Rp+i&wyk~yU5;9pW zzh%)Pc4pME4odJidFkcR-V|esy{VN)38!_PsWx?>BgAqE#OT_SXya#AYN+LoHuSZ( z3@FzzY8FSJVc9Ism5PsYc{DvSi|4VrS)4;2Q)iL3B5-jQhZ~OTQkgf@vzdfpxFn&N zH=Ex=ux&Q+-VH@eQVazVp^+EbCho14cXds-T#AcTqPH|s-UZ)FLqX^|hs}0I+#Kct zF?|mE3P8>rg5!?^bI2(C@X#Cr?TeS0_`44)3GwumxZfIDSl-ElJ-S~$d$32XT--h1 zqG}f}_dGI|cW9dj%Et_r=e2L?Ph}no;z``s{T%hRvH?&eJ zee9a{R;^49L@qMtX%0$Aa9Nv43Y&XWy{+TVsLbCgs5e*MH$nEPbM>ePlCBW@kTNZPRnT|7yIZxAY@D4%NR6NWy*;Y11)ZeZ*d|bJn)^xTq<4V|A^v0U^ zK%Z7dXV^?OukK$GOg;e{niq+v9E%QFz|#Jt~!sAb$hXbY;8jX~5b zIj@zC#;Bzvo>5q`l#r$)?w?dNl%*lf^*I$!^RpwxEpgBU!r-+Yr&L>6GT!_X#eB7F zB)TpmBqI>FjBO3a^koD#2{}@ji2Efs47+EE=BsQdc_KGjd)bf^Uo2B%EY$u7XR=-l z24!-V`eSA$tM|i3DeQ{}G6`fK9Ao0&TWHwDyKDQ3>2pOd{Jw!ySkV)D78}(ndLViQ ze;$odl0;#dB$3#=g00ZO)C%^Xo-58Wj>e0*d z5xAD+yRf8Eq_y&$n9dJM`3|g=^6l84EjM-L@-p2;D&)@Xcgd~fLhjGh5SjhOY30T% z7=zLz-l6FwnZ10o0PgxcIL@18+spH;h+fD2brb!mb5=KE(K^m?F7l-?2f4pf-qOpn zaeN&C&cgY1O0=KwZjtnd^Ua$OcKLb)ujh}~VbFTkT8kOXVgGs(;*Rx77#?0vPE)d; zoMsgsks2%U#(MU$0$)p#iGU3(q)(9zq~>LqxPgUBu~rI~ATmdk^W}@tz`WsAkdR6=EZ=cJOe*wDN&I#Z;hXlfH7O1L{>fn`8Yfs$KbmhtG+@nAMJ&>c$1~SUOuYryO82A z?-i((r?;*!xv7_s3m&*p%hNDAm*YsqGD%X!|`J-XaAP5JMVy8gYei4ZRLqrdRehqZRNu-VrgkR|nr4Mef0*z_x+gQCLMrfVXhq?~?1wiD9r@ZZ5?8)9~_a4RP5 zAh=twR&twhk9^BRBXe?t68>8Oxg8cs_t6(6xOnb{4=B}3cG7WiCe zui{wfwpk&VW~*nlLJU|)w4z9&Wu}S6REYiIEs?-A(;h3pUXh67(#Z{B65IhNz9>|NTgb{H?;;s2yo+Qo z?k1T)<+IjS69IyBn9dJFY>mF_{=q-)cV^(w7x zZxQLuWOJ!isj02Y(1;i5y{W5J^1#QnN@))=)O%;LSJ{yF2afQOKaeGs{DC73$D@BB z2D;-M%gH#e{(<8Sh5!FC2|<5Jx?v&{E!cg>XIxWwUaZ-xy5iLelB!nK1=XyIkN%JB z@P+^5`v2|!*wK~$qxhrWO$|%H-Q>anaNNx<{gHMzTld3~yVWWq7mxpu;~+QwBbm=0{7Z7X(dixzCm+4`qauDD7=U0*p5p1{WhGshs$#-K9<5QxN#5L-i)t* z<5bSMm$zTz`5%SX`S%j98?p0V8v7gWI9vxWYNA7x${ak&a&qC!)jR-3R%YSay-IZE z1`m4tA3=O7*L!>?)tdrz>y_)|JM~&}iIqUlAKpt?tz3(O)s$Ve$~8FjC-%P@kN=5- zScP+cBCsp*Eem?E$E(DL z_7S7Aae5y+^QaKKX_7h9Dq7$u;H&N-8!}y&{&aefbS-qggL(!>L4#l#Y3az*+#r?H#L%E%l zRy@|by)uCTIyv5WeElG4YB2l{5Ep|GbAW|$m~cRGEH>iQx=xKQ*UcW?Xq5xnaKpXd zyaiVp(GgvA+0HoAQ5l1?2S{}NPyF+MGQh$;rpqB>JqmG$xYTK?bBMq=u;~!%=r|-f z4aW}=P!(@Vp&j2#&W51F{9Occ3q@L}4#(ufEM~yMdqrBP4#U07_YW0NTL)r7m{uL) z{!BBEv!NDRmR5Ibr9Uy?q4?{;pS0>=Se)#&E25m7;4T>HBz%0bE`^=3OOilDW)cFe zIsk{rsH~1^9_pM*l%JoFDd%LUVMM^LeBA}YUd$RRd$kYJGC4APbtlX`!kOuaoFi<$ z1NI-`I2o>`g1y+P6})mpQRC!#)Xi0?iT8fks8zT5*%M<)vA-#z{S7Vc%&OC>y%<%* z<_j3To71recNP)lyHP8J`FN&?fb7D>A_BtbS(5C4y_ny&V|X!h+i;#hM^$Zg4Ndk8 zF?RAIK(%TM4#{se<1zV79?lgLi<|JR6mG;O*;Cc3Tm-BT23nOvb2nDY#u_GLvswpA zC6IZbRU29?|rSBCFQnBXE#w@w+5z5M9D@DOy3P z;t2a6=Jr(!afqL&Cw{z?fXv6aQX+jGKDw7@CbeoVQs0$#hgA$AlV{bis*I<|zqIv$zmh&IBzkiH#g2Jo;OleF0&Td?c&6i z)FkDpRkt|1d^cOLs8v(2yqpkE#@=$mF$tBDFfwd8u{!}DmlKiW@jDAKvVxLk-wK|Q zZbxzjZMVjXfnox>hVXQ(R*gaYN~;=RuafwOTrxuw5nn+|gQ`(D^aC}+Rq1%6f<2|- zY6ZJUMGmVgRVmoFk`tmD#NXaQ6k2|rY$MFYPew; zL_SJF_6#oOs7k`AN{%WKA5{{=!|+=rp&AOcick%~!xf}owJHJgs}wygUdF=aZ^bk6 z&9R z3S#KQRf45{*e9iZ(Naxd`G#{9l>$}0v1k=d?rW4DmQ=l!WW|AoiM`uvv{rJb7SLOk zjI2?ytd_DwO|8-qf2`$Vv7xq>uteajB;mMR%g(zOA7$TRa7Yr0l%p)8Z@WE|GHSZf zJ36y8d6c9pPOwfu7vjeicb1HLEA`PeL72|!J@p!SNiWYzM0YAWF)|wu#gJMPh@3sN zlh$kG&Ad1@HGEuf#dVcMI{`IsS5{nk$^z@fu?7p7zbj_{jnB@9m?&l?o+iGY`xkv6PYHmYSJxRT~ z5U1FrWiLLE4hry#Bzq9iz{1@~Y)~Ad@>|KBGJ%PsJF0hip3I0Q>Cyv1k<~k~;9hHF zkiB{b!8U9-;O*4cr#`;5(jzM z#B%cS1C1oNjd-|`)1Ql%r7#CyG6~3Tg)|XyO^QB*8-!_ns?}|mgLD;O`l?m0$MPmN zxDJI(aJq@7tB0C+x>|!XO$1^!K9ZVxMtF@j5L{U*{hczg$*L0gs0!1OJDaj7I;5xkrq`l!u9}bYw|k8umTRU#6m2aw%BA8A(&Cg}1w)cDr%+I11aV zN4i&@L^hBm>>>Bssz)H|5#nPwQXXN8Nm%p<+fT$@d#!4qT0P8#aXvW3*=skJp&DX5TE-Gd(8m0lJK=M_6e=%}@!-*NUB zfr-c2e>m10XOG=+awpY+wPCV@kfx{;po3hcHWbfDtq^=9zv+hGq;fEpmWv!++ZDa>a zTHYgjut>euPrh^Okc0j(8u)ml$6o7;;9V42^;#dy{4y!_rSFi&$wb>DNv+wA>3<;@ z+mQVi!nPIr|3an8%YPvsd-5-2rxuo#>E%HJ-+gMVd{3-Rb*xh@vqHA&{@6#ODWRy!X34eW>L!XFu`K_N= zsJpg1IsBT8NNdKo4#04UAEMXDRit~w!WKphM&?N+RCVEiCBwZJl2$Voc_#_O7#uvw zUPt56lf>UBoIA<6PsjI6{KW{+xKdzL@YzDusTh2Ul~XYN6ah{~)+x3y68lc^rz3Do zlHqt&swCkGtN11o3q;`%myf{knqkP?O$Q}<%}}JAX6+$Ze470wVDD-EC>|A3NWXuQ z48lbzjKlTQ>}4QqXP6s+Bqr&xGJa#nmH-VVxmc@-Y5gphqo#*;T1|iK-fh)-IcoZe zK-R`gs0s3t0qr$?QMQ}h#8%S>-=85H>5af=DCN(>&~dxc+d|$veJhuodbB(Go#kM|kh7KN zgrlL@$8zOp2<|$|Ub>-1z6Rrrhx{$JekkP7uaL37bx-4y~ztK z--1Oiu#3%@$_cQlwRr&Zew)~sm{}*nqH`i@#rWF2N)mX$^geg!wYj(^jpZQtMJCyZ ze~~?BVdjf$dINH$a6KM;k%L%=$K=~u1aIfb-|r>z!vDTVUGZuJzQl3{2zZHV*$pp| zPUgHs#H>IT3n=vt-Y&91ErSF|ei>eRiES^%)a~N(p>~PD>oUqUL}3r1NvmCqsF&IH zBBZ~})wd9fUnWH^z|NPsg65;_WwtjDPruCe=Hh)x=HMqOoQ>|UD3N{S;?Fhda@z5x zbX)BmE{aV;@J_DuTHXh~!oFtWfFv{UC|jTudrorG5bY8NrXuiF=BFU`RrWR+lO&mh zwNf|{sXMH8t#*QOV&`CpY|j(BUOOJAUS*@>aPd_RfH!`xa#XzWdreU>_capkxYtOy zqcQI_)*6K!lB5H#@eG>Qy1waR`Gz$ly;iQI+(J6JpIOGMO=;!mByy7suh%9c_;ofu z67jDSqa!d)a&%|y+UWaqM;O^TS+-f@O*LORgP?$98aS)(*j_a?vr= zCLrn!qJa-~BpHmwZ*X*juvZcWCzHZ~I3vjbT$Cgh*WXYaBVs5&BvMK2!j$LwtL;y! zkmE2tS{P{bI3Ve@{g82v;PyqHBz4CsEnM5P@P2M;} zVf>q{5{WgEIB?IKBx@Z_lGCt!Clyz8AwLSS3K_@f%P$Mg}*YR28dCnA{MV=?N zy5SAQ%DCO-sY9e{cm$s`J(1+LhgfS-sa-}|JULp3J$@8qw4-~Sh3^QPEpXm^hq|q! zVzxlZFP^cRo~NXDbT^{@&i3;0Ng!pcqr0&5?`&qLGv|{0Y6l+cEHiy{yYttxn*UKT z8so8qFVg6_jJ7gIw>qnyC#sHaalZZn_l~2Ror_gz95~zv_*NjdUMnFEA0t`7twG8Tx7dRh`GpxO3!r{i6cf~y~wWVxlR&#u9Lz9ynIp7`o|Mv zT%pDjW7jU|DT*H*-1-@LhpeH>(Ltyt#4GfpaTGFLTZow7^F^+gxTGH)*!Eqnw@oTZ z?Wl2E)h3dfkr|8Hj|glGp81F@qCYNv#9{SA@D0VLhac_hb_r?Lc56rbApT?4?2VZp zla6{J?_-X&Ck{y=gRy?hHluM)3Zw9?6h@-+B^Ejmdx?d#48O!eKB<<3-c2R3qnTBV z&{G^ST}sr1QP+7i;>2f{lvGPpmLrCLUS%ingv$e5E)j{?WGynR|gaH=(IU-5znkLB?0N z+vRD&UY9R!yyVj^@ops>!cOrw#UJeu&r4FUT|61dVR;b!+9-8f#j%a8hgK)Hx3_Re zJ({;$*($we z8?F>=by?z_RR*;I(O+;->%~Q-N_I@=>bg?57B!bGvZ1XJx7%`sMJL;mUnSn4^?%Ou_~TI+jYP0AjmtiOUtfR<{^0 zeMxT_i##UUeB#jR#9qO5PfspjEGQ4xpK2X1yk29gYTbMZ#3HPm0Z!z|&G;rFR#r%E zwnP-sdE{n%KAFWkB)}Z^xw;Gq!$zOTb#jh2uqWqH)0Eii$l?D*)J>O2qJpAn5?oVw zJY#FBei3z3Tt*YFqi5Y@31dw{m{j}~D@~NRyAEDurAb1UcXwMND4LAJPKM*vZg>6C zt@8Jfq1C#vc>F8wa96+Lb``TvwyV0)5+`0KcV@J8?z(m9U?_9}C=FG4`;UmaI7EHJ)kl9F-|*)H zut1VnOq**^L<}C7YxLe9*G3!g^ut?Hqc6VwhTZo;=Wm(xMqDDl+Ut5@@<05a@;Vn&NPX@vNK}`O?z>+XGo@Ly&XE>zdNg*_rb?!DU}^Oyx5H zw!2mAx;3SKi@aNt7B|cDUb|ACC(lwv_T2j;>u(enA_7OQxQbBI?e#fw#4v6kc%kgg zJhl347iEaNKxK-2_K+9s^;zNsPg>g`j(Byf|A~uh-cN*boj8k?FKfjMtYCn5L)S<} zw))lLNu0>3UnO3#<bP+G3S}tK>q{=c^c+&c%IPhQMlbnjiGvrObzNlPwLvdv9k1*0tH(!M{d|o2nX^3) zXL=jcHW#mPLHpIqJ&`nt(LY#2@z&4e3!`&L}UdpH8w1Wb0{ZxGD;P*?vu%!+ijFu*2x-a=${iNdS1Yx3c;D21)(;n9G=eir z6#{iIltTyJU_Zk|BO`JswH165P)}8$D8|+L1komQpz)$k7UNi|&cuf@Z#E^owDubl zvbf(^NERnateEkah;nm+r1?x(bZv4_$EE0vsiG`sfqQ19#Cuk?k z*z3vn9x!OLr&wy~6cqUmK&7Bat9qh5O3cs+9)s)drr@E~JH!^5TW-BBFVBP;HF;mA zTIvzS2VInk?D9&-P8P>!H{3t!Bhd6aHMzI^5DCLDc5)BgYW3oAf(ws=r13=L32UgO zgLsNVO$cA4>y6zJZ?Q)5^qpa`YCMMJTC8$Cv)^JBxw6?}6}i&kC$!VZ>zVfjvc@j- zG%ROqU14SF0wouSP5u_U(injK{ubS@(ch)V;C#gJ%-iUP$E32a9OqT?yMHOx$X=Zc z^zn3KoIyO)4r-&k6Ekk8ArXKA8pR2mXxjOpUL4yhjaGUJW48*uuvu-C3h4(<)8&rE z#i|V|^I#)dLm|#vIU2s@vJ#L2=csGs+k2eX{>@~!EC7;VLq67Z;MZNwPk!JLyJ4p@ z@<;9tJDe#$lFc-1m$Rk_htx5!c&jKGC>Jzrad!EcoTXv2^D86G!^Vz;Z4;eWv-(Eo z@n6|TuJcVva-1AD0bSF;6dSrGYlGZshZjvAx z)?#KE`Gl=ujq{Dm!tYl*_x)3IG_2xash*b04lXILXPXTx(bb1dFgAw|A;@%Qel86x z7YzpCT;_c93mMN+)XL{2c*cj|E_TlRmyBYO^V@%MbPLG_w15WTWTN66Ar}4C5NZN5 zd|7!Oa(xNvTs-JYq|U)3QaIZg{|$#Y%Q@p4Uf?#!b5)m>K|HV0yt%%;A>&rVoP2@b zWBRp*nHcTIb{QVpkHeTQniadledi&!qz0jTOs}nBs`J2i+$5*qEk8ms8Q(}U3I6_8 z&3~eFMaDIFIF5JW7$!J>f7_unjCV#-Pop)Ab6#SqH{9;j{;vDm8eAqyakSnOU1h@< zeC$tHM&mbs!ZOOa^j%^n-TA@0TBNNZO~{;g(A>6U5FR#GT0<)G0{Fue91I|;lJPi0 z@{+Bclfn`BMshq`2NKRC^b2HRqO;3~glm{{5OrZ{!%%1LheYQPr{6_AvOz)`8M<2z z#Dq+(AzpMz!sULaN{L)f?`+lRDPE=ygBK{>m4<mxNse_sbcw@=5oMFy z8o$xmYPa-r)}CcyU+0;#JS8>sadvr*RM{J&g9u|UEDd7Sp4bz_1=j<`LF_QvIr@1* z9OcY>o;4$#r=KT(XmB_mqh?BL&@reBD`}YCg$=04lAPUn_C=}0U?@@=;hgz0t=$^J zWfOR^tF^m@(%Y`F7R}M*_Gl?81QTv;P2G_};hKCaY8<&v6D^CFMm2?yGkicqQ)hA|=lRQF{ne&G7X{0s7b<_e z1ru9SfQ!WqOXA6sROOGyyAdQmyxxt&^u^U~?7{~D+@gIuxvD1O{Ey^@O&zgxI_1)) z4zhu3JmD6E@FxnLKr?5-Q%oYoR^PpP+S!cS8VivTFYI6@dNpGMedk{aAa&O~q z%p7X51%x-|8v-b`M|g8V_AT#ai|c@=_r`Ns?6LEOg4{HBJp*-RYhAtGVpaye1(a-?w?YQtH3Db7l= z1efJUi}AZ8i=gvV!P}3K^s?Z$z>U5UxRV^Zntn=fD#F^0Oz=(q z&2#Ir{yZt!8)s2&Wm9+1c{7s?Ij|5lGvOag0jzNb?&SSFSzEPyorX)X++*#HQ;|Br z!q|t6Q(TMprVqndG)_h^$(HPFke$Doi0P7>fNaT)$NiEpt|eJI?>Y8#vryt{94o(< zs~%eIm==QCI0lp^MR6D(B8RlbQAnml;hXM8tMl5=++owOJXB8JjkLP_PK2w*6gK2wQ(5kVg(9p)$*$$I71Fh#UUA< z*s1@_Z~menH137tVVNNhj~fRePZgxa;eaaiJrIu?`2jen^LGqL&qsz-?7hL)yJTin zG$H4&`r)GdVQ=h~- z0A6x%jYo?_E#4#3Iv9wH#KjKAbU9qpb@r+f#^34a+KKDCk%25C36YBXC9&gJB!6t9 z>tp637#PB0dos#Ozlt_Iat}Lhj=<|i8jh>?SQsO?xx0H7#jUQ)qQ|)mjbxoFp0CLSgXLC8Z#VQ=orHfb<3>O;DK(we)#vX8T@HwR%^54P4B z%S(B7XbwbW4>rdGP!IAiw=|c8^D`LzwAl~Q4{&_VzM|C7$m9n0y4a5oGu)*}W z7wX@%=hm#@_;1#*^rqdcAe>Qb)x@^Q+g{DyBwoKn=KUW|P;E_gz1xd4OxL@;2;>d~ z^yZ-HcUO{an9`ddZ$;)#*;KZmz(_Zvwm0F+lk=MJIF}x#X(JxnCFIqVYnt%0@Mr6BtdCVomFR4;ffI1!a==sSXeUu>YPdz8D zX$>k1WY=J5pS{x0Ds0>e6E`?AO7$jY?X`)N(f1b;5>D`t=+ zBab6OMAK433LlC?&(mf-rXNW?ydSrT#TdYQ8ZyNFt1NcErd#J-Ih=<1HW^}JQX(?X zD`860eAM>ii09#SKdZbl`dEHB2RHgrQsDJ)f3i}!9yYc!9Jg6Q{OwJ57-YzuDf*A( z;c8O`^7`{vyb_j#Pel6@=hKn9UWPmkE$b~>T9X9#p(7c2Q)9>k9`~49le{-_Ih&-` zv7Oa#(`1Z}Vat=SEQT#l#2(2_z~F4+(AG2_+5E%5Nqm@dyN@Sa0hIolZpZgA#O+v7 zirJK=F^Gxf&qibLMj??=m};cyxHFcu(oij5Q*k<$U8LZHSW;CouE$zcZKV6K?UxCt=e7Hj;=3B^ic?B^ip^+1wzsrXd(U$D&6yB@mzPN#&TmS%ccd z{oc^hH4Vn7ft;B^;6opI^OHB9B&#(Iq*Tbo*fan$7I5{eO|gcCA$$5G6bSQSI!iU(Q4q6}XsuInn}Hq48^+M9ZzmOr2fc_xlS z>Vb=rMB{oKA&f%CQh_KE2bo$UnjAR4lpAJ~j!lEunT7+Bs4lIey~&PO2eB=BU>r*> zI@sD%OcFCLQtD{o6VQt?r!5hpw3gTN4Ad$Qh8T*~W{qeGlK`mPY+FJl_Nl70gh=pH zF??a{Q!#w$`Ya)7>54(mvKhUl3+{VX+6{vLa~2*DTI7a=LjMT-jh=RR@;&<;X`v+m zpCk|>e|-Nuf2OwhA@>D~nrv(FbqjxPIo5+_Z7n|hMp~uWoLR@!8T_j0r=D7{*meA;OSIyYw;^E|%p+x9T2@g(zsCkD(0T&r^`Y`@x8?q$XipVE8 zgIY6V0zJVtZOxnU(G$c_a~^(qf&e#fDo$j*jiS((JCPBIY&r)E64_L?+!T|kHfP~) zPfFbl_~=Oku=O}EzgmZHrQTZP{FQUkyao^OGQii?Ebrxc%{jQ4cjWeFT7^F?zg`K4 zk*+{Z68p-;sU)kWEhohqY69aJ>A_=d&C8&lCXv{h>EcQLP@Cypd^kI#ck$sw#3D?o zCGTxsi1oD=HKlohYZ=PztP86i>&4bQ-!;4cBQlAtd7j))5Gix9=%{QX&2#A7n9IqC zSUCh;11b15&q7W;N3S;1!T1P5k%0rOLnisKBs1`e6i&yT4Fc0NR5i#BJJq=Ip!8tK zkYXp%{)laFo{VK9*~TR78AxYEHkE{~s3sYI9ogBL*5$aXFcA zrQl{V@tq7lvJhD_C545&k$#kuqBjpm>|+)^($<_r49k8>rXzNzo@}+5kLTsL!|;|Q zLvj4DU}*^6Jj{+FniCM4N@f<1YPtDoX80Z>9fS{!l*Tlv91D$UQn`x_z%>X@X^urs ziO_Nkg3}05f5fGcu=?Rfsl`T=_ay>FCrp)=Sx2EY(?@x^Oi*tOE;nYi7tW@!kDj=c zMo4<#dKv+ZhAo}vzbInMy_+$v2l4JfS@z~gJYFSSrrCkKbT*;8?x?h84L9zVK2)fG zH0alU;`4NCx}~oK%`_wr!Lsg%7O3m4V9rX1^z zze;(Sgrd`Yj)lsibH}0!KNce4;cR513#9bhzFiJV?Set&Vt3-R_vHw^Xx90v> zki=F~m1CVHxSAb%d=yIF#{wi?nywu4mq=;spRtB~X@_!5?wQ@lN#qU2SPJP|XfdK3 z>x4sNiH?pE#Z26gFo>B-8I+;Qxa}RIw$NXivq)evE~{g=NlY>xg<1+F9GOn0x>urq zQ7UaIkT70kgpA_FgJH{V3CyJjYAyMcGF+yNt`J)-Vo@ku*AQg|vQF-!RdQPz4C@X#b_;Revf}i7kkPVQ!gdPcR!Oi-ZcDsy`BhkH%L+UtjbutF zOrADdmP-^&@c_kOlwzF7sFNy>;S(paaIu7r)RdM*63mh5LJ8og(F~FC8>OxJ61tI_ z?L4^{w@0_k^}t^{4?gymITCN2ib)A8F5x5@LR?Pd|DUe&fRC#<9zW7O7gbxf+TFW5 zxq!Q5pX4IR9dPe}dqW2I-n)fU!1NHnV|oY#Y<0=DWJ$JcK|(Jf4G5toB-9Z9@=M5% z`v1;*?@sSd`F}q8Xy5JZ&hF0c&d$!x&hkjO8B_(NH6e7D9PLTndt$b}5$pq?LzjdF^^WT0Bk$JuwiC~((-whe3>I2@?c8b2>?aT3=n5;eX-yi5cF-afj*3%Xq zIs)#bLRnTl}34-ngT}YgVSs(PpI*aty$7-M${(5JW;HVO`|M6QKSz#>m3@NYi4;m zF+$3wgLJq&I~}CM^kHU@Vrcz$OWG;W(=>e)jTe%2C%;&OA<~7_9C{3f9`=fBEg`N^ zY@W!IO|L2EKanfH)=Yz>=WiADKzZeF=vQBfv`CXwax9bJc+VbDHg=F zEVU2F+kdpiFrISWiZeT%P^O6rb=K|bR@T!u4lxubmx1_lQ@vc8N#)8oRa_o1LVA9Q zYOma@9x46t<-EQ=he~IuM@p4FaY(6r6Ni(!W5;hKNMM+YIqx;gyD1jOMPyI2T%TOm zSx@h@J1O^;cUAw5CTdIEH>%na?~9a|qV5;H@#V?3OU3deb*ZS&L*P0wfKn3ghY+W{ zvwA$#1Lym%rXn5H?V(;cf1N~$hSe4|tg^QGoyx7-jgEVDZ+X1>Pd8Cdj-CLg^p;;@ zIT4R9E0rVHc<=+K4!FytOuciL9Z(P4>Kz29*}jgtA-A1QXU3Q9RcF)wB(rP}#o0ST zbtLV{F59iXkCDsEcB$KAl_z^*4-{XvL!Ay2VuWqk2bFEJ{R0QewyI-bxON$C?dBmn zZMHjm{6TdIT&7HKSiZUhma2K4jvXu;SME5X!6?Ji9U0i8^9+a=w#PdkjMK8UjMM-A zY)7DMjXup0j4xZQZ*%C{WgA7tm#x$%IP@YpFL3C)k-Umwc37b!het88;>$|(@d~rE zS$3`VD<*>9#1p$*hAe=b*k&*A_!89`(w_FB4<#g)EwL((5<}kq-?;9b%NE-lg>6=P zeAyy>=RhxxThAP1l`W937x1w5{IKT4dA@);&eL}ZSUBhE!vw(|WqRAtp8Nl0Xq8>9 zFB6zBNZuasA#Cz;mant7Y&K={2)g|~R@p3xTV!#>9t5&v5ekDTi_nct*VnJq#T^e> zAt{wj)px0U!LliK&DjuITO5~&<|~`54^ye%JIi*fY@*t3(bE(3Wh!cYr9Mri^2ZhW zLKG2~%i+bOAFq!(sns^mD6yiHjn$Wul;P<^N&FtI4;X=Gl)e*$a;t2lzWJjj*jty- zKHNoVP^fS0=zg0gcJvJ~Uf5A-kwJbdDECxE|Ic(W_C$TJ7$An4>_B)AXgY=z5>!q;_b^>Js^nFAfSpD@) zL|WTVA4T-Zg=L_ZI(hf?iUz+!N^2Q~T_{ zKTTJr?xvl=7RS?cOuZa^XwDm77Su=Oln+|wZ)JYV{H^|43Ly?}7rGC}S%n_v;G-fC zU*S_H6UMz+tw_T;Dy4L_T_6N1x~QuI^}q2Z9uE>y96AOU!+@ZXa5l^L}ZtjT8&f(=PI7L2EM->XG)6YpuEbZe0JNPb7Q~b zer=cKJ}EQ4e4qM4g0b&aXGl=8e2-ckn5ZmqH>7)RybPJa?DCyfA^*+!Px%gY{)5d# z`F8d1V{&~3_dWp>nRxfn>)Vs{*JgE|1M$l@sgE4=Bjp>_n~jgHIL>U8MdCaLI+m|f zzcIc9U%9^0%VKW1QY^;?XEoCI`qdtc>9-<+m#6L|ZNz)xcF<#%FH^^ZjF|GJwx>aV`4V*-80@^5;v-%F z6TRh&Z2p3VY?v;<3)StOFTQ+%`rT8{NBwb&hfXqYug1<*FL^2u;v^5ppE$+yb;>Tk zN@-~64*L7c_4Xbt^8e%Mu3W7Sb@Hf#J5&wjv($^7YASJFr=~Y}mP2V&&L;dIli623 zOI5R6bd~3B%*cC#l%uj#Lry%R}n0ls+7y9!nXe zgZ09I-loIBXbziZJbtPqXM5@_AE=%>y*b|U0d`-hs)Q*KbzENFU)}PnK{j6bRk?`c zeKobgd%a$a!&yDWT&mvcb!_!kKk*#tl=q^y>>ZNc64%?5E-r1B_p~k5vdep@=X4+T zg!n)YBJbhBoTDUlVD78mLY4XMv6av-<8ZbDe_Og0RkrW$cYni~QlgARHuRVWd z7q#d2$5*DRLBB7)GDS`K)z1+2`1)vzWdUVYCaTdrXMB|jI+S#a&Gt{p>CzDRD?6)I zy-Io*y@Ru(TD`+YDmyp^@0Etd36*(8?>haJ9yNGJTC9xM8-vR0xG3o7qKkD;u%c9N z1_G`)q?ZC&1aMsclvb$1a?ttzx#m}~U$6Q3Q6-MqiQKSnC$e`UH%8(s_UPR_J&?YS zpz|&or46z#=mjcv>dm}hV#N;Pb@8sSY_uH`%YKIO10Nid68>c{`iXP^q!V3R4XK54+JXF>r~u~ zuE10Bt1QYD%k{dHo>y~QN;k?}ybrQb=7zl=edHSios|cwUdOgCs931C)b&O)m($rb zSIoy#C{Je0v)3d04td2~HI*}Ag}*SdeqxUeoDoADLa4P?S8^0$4IF?zlk;|{to3wiP!Zlex+C{zon&Yh)Z_`tKOU7`KK*cz@xF2GTm9zuo z9HXvgbPJ3N8RddFh*2(x=M@t!h~E-ld_|EuE}^!C>QIDmgv1>r)o}G7qOLdb`=L*N zG0Qs8E+_ZTyOH z=4MwF1Jp-_+T-BkLA8o_aq!3cDr7xjVnrWk3JkH0>MD2_>n;nax^%Fmdfm}S-{v+e zdduumkoHmsYWf;DW{%nM6+P6YSunmLM}3-6L$34Q9q+Hd!P84mQZ{@M=MQ96d9AUH zB130{OYv(~Wy=jOvrDhalCkLYlgz42yAE7siQDYyKESNX&@lshL3(a~7o^H^*JeTQ zE_og6(keCGp$+PrvYl6de^ob0`vEMUb_2+cal68+Uta(8Q+ zJIFEpX~@Cv8t9j%YMxoTU7S>RlqUmasl#SC&f3<(zF*9+F!pqK~LNC^b`9 za+-hS;SSu7Xx4sd`4Rc{Ntdyz)2Q4lUn_z=;`=etyJb^%y#Z0VtBq#18vs`W%}O3k z#QuSG!eX6vOLfAykAKa|?NSX+`Siz>{pOE7-6ZiwM7b}2%wceU{mQ(NugQGfEpMbz zl}$3`Myj$=*4*d`jIlgF*r@Rh5slklxgMVD41rK6R*9WcxlXUG_K2@stM^t>Sl{GH z$Y_5-HM`Ps5#ftlrCu8_^r&2^evEp;KyiZ;F*Wl5m0@%;XqCO%;P$nvx3Uy z>V#U^C;p$=3sx?*-Mo7%m*|r--ZB2l#ad0Q1#~TKcaGq#ROZUc!|GtM8yAhel?(N? z2@_7sgKR;BO&&b!iLl92X6ie_daA7Q8d=9PXmHqDG`LFNMpTc;Jhh9QTRB_brPTv( zo>zy#RL+!2jN0QXXUOv%ND!!;E)Ss$PpZ`8ZB=0u6v_B)C`|m7Q>7H0bbRF$c{l}O zta7rvdkd&0$+x#qr-|~#UryW$4j4=(S25qlWS|yl?5ut%Eeo0&=?$cLIQj^+{TRI`IDapHrF!4tbvn!; zY*%*CPb*dC%VEtIl1Fc+*dfxQzXr=Y`YTT!nXl6;SF-QmCk}I##RWaS%7OSi`7nBW5eRR z_3~F+m-=+;%;afz+taM>C@&pFC*!Z~AY1OHTtf$fUh1pTAYNY9AWlBh;1Wr?#}kaN zDwTovK=4B{=^k2eP*xMm9{ENM_RBAbOw>~t9T6-ya~k8jkMURSB_`~qSLMej@5SCK zJ(aQBXR$yRv-el+mYjP*y-UX2OL;qWbm%cQgTs&KhhrMKP0nbNt@8T4%&;x;FCzO{ z?j9VnwD*Z#wF&M_k-8$j!yV>LM?D=oIulqUJpQT;vh^sPQ+d?WOYT0(vDe4?^(tQ+ zx#*U`V^*zFsT*f|;z^Zf_jbZRjku$kC6PYNg_rA@_qJ$)rs)?gv9-JYVbeYtj8+xE1K#i$3p4 z`YCFe%n+-ZtoFtM`OE#hlJ$ zs*QgtH2}wtlGbmWdL9ZOV&dV3jd_(`Zi#rIN%mJc&LY&m*w5nP(|cAq9)>MFqJ96x zwT75gBh}9>v@BLnuWC?HB|lW2W0d^&}hIz z^me|!F~rWeDx|N_C@183k|3P$K7RRC52-sn`?j~MbbnQ@KI*FPa`UvPUV=$|m|p|* zy+M^jd7L>rm|fM+$**=Q(I?SWedX}Ol-EZe5!ZWv=QQJ`QkuoeRMlI)(x1I#u%F7A zRXruegGwm7ss{)$Q<2w@72~UNWXmJq;6&yTa0H~{5sw$EQp;=&`AiP~3jf|!detw^ ztpAxOKCaYyDpkctcmQrKVs&r+nuvT!0$cy)?%^6`u$E*3Sl=R!YE%$IZanum=+&Kx zUd(qh*>N>#ZUmgcM(g)#oLksfUU0(_A3#x-P-aaRoMh5{-#+T;BA-9%=?Yi=?opba zEPdY+Ojn-Fz~X$@_NwL5AeuGmWH=18eAc<3z8ZD7V?ilieKQS_^FQ}w;9`@* zE?6?yJ6qQb!7lo2)l##@I{raRPjfBr?{0$wv&Lgj81*k?-ywIA)2vZfm#U#ws6|Z| z)L#=P*FHw$E|Jp5aClK&Di1#fOFbklk0B);ly@~aaP)DK?3Wx3&=EY&u-Pk19{1$P z{g1;eZhYL6E{%^f{hxdsW9wbgqzQM*n;Ptp|ByamyVgQQ1*t7zO)#tV_}q%HJSgDe z*=6qQtKO;%LX#_$R}5So9IW0Vn}0#IHp@?bK>?ejnqTsdU%-Fg{e>qD<>*Bs)>&_V z+bBXq8HVZ^##KhJdYuj=SAt8Q!a z;n=&6Q^4xu6fj@*9QOqJ>g%X>0c;pXps#b$%U`X}j95^4)MKQlnbmq=rPOanYiI(7|oC;_1AQHhM=DsMcD{#a=WID zzuNJXNdu89$D>ZJo+3TV$UIrbl`%0V$@j_3Ybk(1y%l7L2qcH&Xs(9 zsb78dE3=ZXiIt=qUP+G)mPwVgBTrUUdU8tDQ@j!m4q@--T>~{xJ;**Tv!ME_2TxbH z;AXX>_i*4eF$y{W+^W+@aBJ@qxw^k@NyMl^ChR9Ysvu@x8Bb8!M`xEZSZspTEI7t7 zlfT+FNVOBRyMq>}wq6u>@-y5EsdUt6)H~~8{PuK+8ZE4A?^i*fo=2-;Q)8>4TV6E; z&yjINu$*11K|pTMz%M_mCao#wtJyU88s66+M-{?);LPUOCYq}Nv$l)$tYxsI%Gg>u zaDOdxcx^4*FIf&~JdX$y&q-Hft;Y-`FgX=f`$uR3wVmZ+Ep_N5X?5i5D1+;uWe1s7 zM|MNj)iJa^audIj;%Tyd0$w1YKgM-0t<~4`oEY{S`s|#GQTl7uc3w~HP|PQXs}n#pJd2?eGsgky69V|x`MKb5g zxb8VMYDeJ2Sokafk#u<9RI77r-$vi`G z*T`@Uu9kUcsKZsVQ-95od(TjZ*-}sBnpsZuQ3G;NR2aQ7`)g)Kfn!#XK#k?u9unEP zaX%8JV)fTdk7SoEEr>*08a*l9VW=5>H8KO90Y7Og>AY z`LgP)Cufr5cbKO~@_7Csc8KU5D@(v-O6xtDDD|hmW^e>7bMjyUfg1JAWM#mIoHFWY zvIc6@H${?De57=Hpk_c@f_$uNWAswNn*KV4RAg5% zj8kRmApSP2U&{tYJ<9dHbBFlXPgIKmK`+?!8Ppw$M+PN?#3n z%j6cw-%C~#B=!uGZkSy7L0o!ijT-WXD;DeSHBgfiZq`s9i*Gma12w^DxUQ=%Zsf0V zT=?rosG$AQS>sQ3pT4#tY5*W82^}_Jq4;bnf(+vE|JXyQu!3q<{T-YW>qpoB2<(jkx7$xYXXKNw^#5qM&;IX>y*?h@J9+X4xU1kcH)< z^DilIoAf1+RllUbxxXaU7FqpE+O%1Y{L&LBRXvY(Fp4_5AV!9$)pN%-s5*;vjY@y5 zIzMRx<96N+4sx(>k7{ru(6g0|-aiCu*Lg~#Q|JhZD#2Qb?CL2B`r9RX1#8#1OK2~- z`D=B{;ndK%RPD+is9mM*Yl~UFBd<+H@3glTEDCs+kUZv zwJW6OGoBua>cq-PI%hX3f!b@O0BS8CVZF6OHzHIA!U0Hp#*rsB@ za>H|;jTF=Xb?)uzTz~B}t{5=^ zrb_Db2#ix?!1Eq|g1S>62foZ7JsjUXr&ceGSie~pl&`x^H2t*`8bCy=U-Z&{hGi6!s9=;`jaeusvr(ug(E)l2@`kX(F`+6|GeFEMro z%aE5CJ9#okf91+nex(l5@uw@8njIEMZ5`fcEpOD3IGw;z6t=uk+hE75o{M^cTFj;u zKYk8hCg>}nm!VT1ne{RRx=c3cuS?|?ekEGF9r`eTs9KkImk-EL>aTScG@@xztZ77` zwue2vEih}ZPJb8s3Di0ZTo@j+#|qRs3tR+F^IZ8$1GUzBl2*0YeXzfYRv83p^*u?L zLKuPa7Z-v+tr-oE;lP1fUo^0E-ME_lQ zjb*9oH3aJS6#6Pq*1Gp!<4B~gRN{U^_Z^a+zoC$WGVV7NazIKna=#q@4P~(_(#XAX zL6hu}cYovYb<&3c(0|LLlkf&uw@WgA%R)K#x1hiBx1ir4^N3)b+oi!aIr>{qFjajR z>h=LCD?fiYHcg)3$aZJDb=KjBol0L7q1)V>j5_OeMhh$#?uJ#@ZIsaOJUx0?>z$L$ z=0>h55~y1*TYpDQ*2!JJqY-PRhCJN)drh-i3lUi@MiyJ4VBIQ7`@N?}*OgA~;ZGKW zmur8|l0WzNoT*$VTYeAL6>{hADWgQH`6Yk?|8$xN>jTvf-~&kBGW*ISHZ%d9W_L?7)IU-1frd zM${lK4c0AiN^nxdE=*>fx~0$(SmIF-Mt4V`Zl2Qsc#DefF=C`yXC2>=+lG_dwG5bb z?Am6(4j;Vjb@=VR*WrU#$?dO0$~jW;Ivq4yUe;f;aNEo9>i-7YpsY7YHA4ox!N{C0 zlL_RaGm88-D-_XT5isu>|X`aL7t=3Xdg>zwUCU`4D;SO^?4j!e2C7t{W@wzX?so9Q`AVcC-Zk2q8wvNPcx5>7bCG?Z5{^psrYU z|B(S%BtoLmx*{?CR1>dv=VH3TdK=w_wwrZ|ZtnLYK zGtj>L6Qx}$iEk6%Tl&8ZiF(PDx4BE-(>jhqhKk+Tdh2?~4WvK?_u$*mJt&O?2?1-7 z4{@n~E9`uXS?3Q&AWg;M@YU(9A0`P9Zo5Gf7l-oI`DE}rVD`%Ncc@pktk+*zazuY+ z%9HOf9Wvy(cc^T-eDn@P>+>!{JmX!MNjK^HF5ono{I18pRF8;sq_gdF4S4b{n2rn9rAVuml-%&ayB?l>HpG0N>UpI2eL5abx*EjEuJ>8s z9sOMhoi~g%X7%)+bo6%)nBxog;_5%?=S{r%H?$LkpfM;O91&`r+ z=E?mM`Tz=U`~azO{s;Jm+AEtrVBl1I0RMR414z1CDnDSrfBXRh{`C(SFFWOv4?O;2 zHF@H^KxeeIQnDY{2BUfl6r!? zjW%xjq#eWYom9VWmf;LQC1#=Y_zMo~&A(9Db&~rRu&tG88my7EfARQ})w7Y6L4EX9 z5hK^!b`X-l0mYJl|?CNBn;y za<&xzjU=;V{@;k?bz%ap9)fpx9&0Td2JHk_@B2?$3cxTlwo<;6)}{F{IC}D%C#Q1X zl2WHg%12D_$&&jKzb45v{WVe6>#qrNvj$hnlOHisKm3T1`n!)H^X2kaO*LLRe$0TK z_%Tdj*vG_=l}R5nRmaGhk7>bZxk-PGlH;UeAM>34DwdBmPybKIll=*+=2ZPE;tQ4F zv`{S+BgnpAQVxn`ZR2E-^ zqW4{7EFZZDMGwmT7a3Uxq=}U5Ki&e&{^KhR_KNp^fbEf@|Dl$r#3N+0>9>G+wvKt^f#AIjM-za}^Pk}ou>|34WqS^s3jY>@%~^!Q8lm_~E* zf>o@KGyf@T17ZR7%6g2x+JDMX%aK>XG3sjnDMu~mfYEBWnW+DiW!Nge`X`%;b(qT2 z(6#a%Rf4IT|4WTmOY#45m%;K=M;+v6Gvm_7oU*ni{M4g9yGky`ZlzWvDHGO zphBu^Z)~1YuTE{y=vJDi7Rvje5dXiK`bqzW?-c7-f4)$Bjr=!-%$0@zX2rVq-;9hO zX^PW)-TnJFFvB`^mDK;+lQT;7R`fd#z1kf^n5XnIl>=-?5dW!JlJ+I7oGC*zm?5*i zq{!*A@k?4cO>WU&Q|0)VG<}LZr@to4U-?yP?IElpbq@;K(!~JiEG-L zr!3R32%Owe&?~7if;WfBp>`f7%~N`Nf0+E}KPa{@mxupDt;fr`|4_kk^7en2Dr4ol z|4{icV*Ven(Ng?>)OwUG_&<-o*GLG(b8d{rb_X)PQ~KOxfxH(~$1JCcq*}8V$}8k! z3HVg843~tjh#V&UG#DzA2nN{-D(g5Tc8hMF%BQkSIu>ZlkW{L^@?^`2uh=dB@hkLQ z&whn6A8#mMA?&LwQB7*SDlqF*E>l*;0R#hPbo5!xcK@kCQQ#P<&U04=|*J9tPKJq>(#QzOrFZml5#F5|V===u$ z&|5}*1H;;*5v#ueTTj{h4K(T@LOh#;dV-PavrqTJ%nobWb4ee*Q-KH&2_aT1$@-2(?v)@vq2L1Q9Z>iuPzNHo!@{xl2eMdy*cQkj( zcfbq31Jq5Xe#iL0!tpzBbd_5)=prXHNR{UlmLebPuVm@`J-?Eq|M%cp`#l&Id=G{M zSx3Aa{~ih+{T?E8k`v$Kw4);pK^Db4qP>CssSXW)`Q9@i4o==B&QSBKyf~u=oP1WC z5s=&Cj4rZ2&gdppaRx^%afZs<)tX|L{F?NV9B(AZmvKgh42U<9B|F~e2G1TCZv;}d z>Bd@>HEI?tuYJT`^hmssCVS(JuJG?$;*A`{>N1kzoWy2AT=}}!lfLA%^VTGG8G7Ud z?cI#$UInIvM9N{Ibtuq{vzi%~>P+J%)Ody3a%N zSIHT`rFzJ&cDj1r5_|j~IDI|r0|ua)65d#`%5bS;gQu^f;VyW)1L)H$m>pIEkhIf) znWsyFTD-0g49!?^EO7c-*=j(#<#Lxn2fSh!sdCPsB}?U1BH;ReH|V;79q2k=2jUmW zpbkckZ0JA_F4l+zvatg_IA8AQ0D_k_{w(qGcg^yr4)owP@&zd*w|`WLr%pyDygk^7BBsbF4JON?PBd_m?CoUu5w?%=Ym|EHQ_P_}Tj}6p^yX=0)iyBS z?nl=+3Y@+|{?Q3SUM^ibgLb?O?#!=oGOIJ>yREa1{LWBojNGpAqj7KzwLa|(Aztrn zq$8Psrt!s+oIu@*WIzJH3T3MP8X;>m7%n#^7{RH-oLVrN+o>7?r-w3{w2nH~>F}5% z1K(+zf#)L=u#-$qq;5%xbWuoxd?U<{N~B!8`{}Pd*_TKq8xk24PbAW%f6%XA@r7CM z>wpm5|4sVq``cAw@ToGB3FhK_{?q*|?rj+>GmTu=xr1Nw zVlrLQluTPpd5L&QPGKniJK4yT+!Us>m)qDfGerk#ijjdrW>yMg_zsQOpTc;}kULW# z&Wjq+n8Hy0SifH93*P%l3MKSSrG(5>=r&2ehU?dA{hG%YOn6NywMmg9sfItzEiMS_8ekO$UaK@cLMH=lvi)=i3V#yAtxiqq=Lsx3$KDi=82Nu?D# zgPt13sDT2fJ4VB`Kv!=DPj^s0+?L-GcU%bqSDZH5FsQ;Yrpm$7o;C~$*X2Iy0P1vn z!(X}>L*mw1H!vuwkiCm)AEIjFuixWP#s`s^`RR!8urOotkS~?F6xE1b@ACSkaasx?9cqRZgcD z;&(NV;Zwg-?&?l$u9uqbhRI3AOWomeE9B$u%!Cr@l+HSNt8)Re`(`jLl>-_qkz?tGf0X)8fZY_TEUwBr*UDwq>t-Mfj9s?8^$X=6Ad>zW zOt$O{X2g6MkU{0<$z%=Y%Bl<_*y$R(0D1q@`1BNi{na+J;N%(iXv?&nS4pcTpCj*P zK=s-3z5bddflL}dQ$}U-YlbY+U(;o;2GitNCMl=NnN0d;ioB`8Wcex+`b?6nEF;im zqE=jKtug_(E=sZte>~p8O9|y*7W23wi&{Ux7yQ1GEb#jmH5ex!XMudIBxF<680nV{ z(^!+uq@SNn;!(0To1t?;BP1K9@j^DsWutVb{p1UeJ{Deq^Ee!iJ+hd6H2=XLsz|a z*v>kuJ|`x@@F9}nhxXn5R5Ku#`N8FviGCxPtM*G4E{ug^cQx7dK5NIIM?KcgPb&RJ zmK;|s+0x`U%r03@0()yX0#`6bwtPbZ84!Rjz5oJhx(o~${-W;IP6e}`c8u3s->nT6 z!yUZ!obLvhbY0~^4KOVVK;%^UL%;|wO0lK{qCmdd2*ex|n)S)rI6c_-uajDz90)^U zDN)^#C^LhMncIR4)_pV{Mo8<9xb*%F z*V^tP#1%#W$;-c%D!JHOXvHBU!3OMAsDzmCt%JY~Jb(#gV?jj}ATgQkuC) z242c+TXiW^pL;0;T_CG9e!kpDfWtD27bEturbTzAzd`RoP=o??g^AWt_!_Q}_Z78y z86_uPMz0m=S3kbsti_ix40c^csVj*{P;*)f)!nmOGvXU&%F)Xx-L?s`3b0h5E}6jJ zpek~^bj#>3dZF+)Op}YCkla3$>F-17)A~@@$Ug9?wfePCziv|KE}+QjNBS6newJQ^ zl|Xlds@#mys5M+kk!+`cN_C!*flJTuZ{6p`oL2`LtXs;utS}p3PbzG<*0Mmucoi3b zt58jv7-=KeFiscvHh8R16DVyM8^!?h<7MQSIUZ~n6UJb}W3T@B8?0-9niERmmLXaK z2sVr&zjYhb2FEn9WV^pXkBP%6FbW5OYkT8wC=P?wEHicq@i!EO38>p-&IqFgn1(_b z-_PjLZG_VbjNw%43}2Reh-WKvx*v1@WIy_EsQgN!3goZ-jNla28d)91efik!slOo< zE*1Gg*>jW(7-$&c5S2S^++alf?a`o*5jyzDK_jC^B91irGi7q+5e)`OOMk}pSN&OZ z|JomcZ-9KQ@%_a&fcOOi7=^8iAl+mse}`?bXBh;O%9PC-uwl_4U8)CBcz1b4 zlXR2M^jDfBlk>pcQC8=XrGp&Fqd-HRATr6L-KuhMVV;b~$aidm-V+H8 z(|LiFO|16aY>3ld4TF_F?!9-zCDL=S5sa@dmGOhA8HU)nGyoHLDuN6^>T9vtn1{2{#q+9@JkZ&>GS^! z(cJ^{bQ@tA$lx#KgY;VYEFZEgm&5{c zE|Y-;l)F@>764l!>oiy_w=BPtNEKICun>pUOI8xWE}l!dAOb$PFKKvsLrVRr2Uiik~CrDHn139e#;# z7)&~080{+>M*I2?WBkvM;$ftiE(?c|ewyqaMpLGWXyg>B=a>9T6aPiCWekUy9ry=t z&m2y|2{L@R5$x+|T&&9IFn8P9m}gWuZZ*UbFQsBQwRmtiWALTnjN>N0kjGyhPVr;q zQ_xA@5v0f(K{2DH-w5JI$;1&xuv8hNO%b&`8%mp9Ha-3`${1bXXpBz!}^N6;sh(vZWY$ zR2I{!2a6dbFBj9ubNcV|V*2r|VtP7dBtO5^xLo}T=)W2IZ?yi~IFh_eMw0h-{drLT zRchRW8uzmPJg5IY*SJ4vT*@eZeyef0qloj5B5sC$jnc1;3SG)S_~xcjjNtN747B@3 zG0?h7#VCl}MPAS#RX!SJ1V^f0NhRZOJuZvpS-vyL5uiN_T^i27nIsuM8X6=@$!KWs zz-UyMM@GY!JIjNkSu;9Gqk=oio1^LA4)Py@{P&k+XE21-A^H z?W>V)4&S)e8dEm3y>`NET;s}ZEr>4JKhU^Z?xG0zbFBv4Z5~g(u9ts|r&YKWznsVw zl6N_gB{D;QT`L>)*K)Z{e=U;={k2qHB#?wFXzqV5XFT-3Lix!RjKe7!S9k?;Z=p=R zf-DPU-4$e+FE{J2d2-?kikd6WYH*EwNaSdJ!3I%MRrl>)d^H=@cs~qncjnkQN5)?X z-q}*3!7Mqf!AyDdO3=@c^Zb&puVid~awS!oCf{7ipqVP(3GkUIGHe2gC(B%dz$ANA z@VY>(7~yZ6D0fYu4HKkh0@<&WmnVSz3i(ujT`rv`8vcQ{ojn_!kS%Muq!wS}IBSHn z%rgOov;gvNLnJi;u|3qpsT4W+R_fd8-OtBf8%o116nT>jrnPm)Md;h|L#$vfR zk+yJUc@kACl)(hDVUp2Vu9;+H!%{a+0?d8oNfb9!P7qj%6U7+9Mk1b@XpQ;y&_eFe zmv=4IoLls73`N6Z3^N0bDuY@Gt^BHTcQ2WN#=+5WyeGJXyVUK0M!gEB2-u^`qd(_K zxIm-cej`d3jRNbiYfz(Jcne2CZ_5coN#tT|piwWpIdH|2-lI`3L2C?0Pjo``Lhozr zFL6`o$bJ%>0?`&tVJJ_T!f5Fui>J`*m&rcBS6pg$4s_urQsn-cbr;ucv=lZlcm>An zH@5p4ZQB~`T<1IwJMuU7lrKQctB6b$|5RnHQ(>p0_20&+l)iW>Ln9!YrqX48xnruT z8Z`c_rubwkV&$8ftMfD!I{8BXk}!>>EQ=~4Ijc)HYb|og`+>$xsG>l$AG!n&k8OhE zRF30!Ju`_OeSyYwa_f!>TQ%L##GIxC8oL88R)rQjog&LRJZih)YjhkdK_BcDVtXJ> z-knAdbd_&th7?X`zFvkdPv%djg%hSjjTBih-3VI7I2eCf$=clZqaa{xcag2W9e1CgK5EHIq)< zFE}8ZH*j7ydbuEOxGkfS<3(6X*1atudXLif?TFx%XnT0I8 zQ^w7r4m)JI{@N}#Xuw-*1U_uNjhb z4Fh<(^t*-((`52BL{61e{2HlliBYO@MauRh=#mh9P1cPsfUFC#%TAzal3Y-96LI+u z@(H;7r^GA8KbOcWWYk>4-}!O}xwQ7e-MGJLyzH851ec6sq-mM>?Zu2FhEe;Q#=61Q zWOj`KUz6o_$<7_iErU&?R%DXdX>1mRb6%NH*&)94zrmUYN)9I5Uq) zFw}Uy%=zxCIn7P;wUVYk-X9mmF9?_0}xlfZ@Rf%=w!ZU~F+#cT^5mOoPG`F3mcd5izvt|C5xCY*-RH}nNm*8nx|U^SKkDi zvSJd%+``%=K7lqiCfC3@JNrPR3%=b+TRT26a6$&>u*q4u9nf!wr-ISchSZfN++ za$`nZDpsU9T&J?6g@O^Xw1h&Jlu+KSC9JRe^y@?k1xX40{;bB;6Nl32IZ_V7>qjKF zZPZt=V#DUm8&|B{w%Tmwh&TepPsrdERC2h?Adu-RK)inih}W(F@qH^md_?0K^y>+} z*!i3xep*$58r*p)h)Yp-36N=6Mo#J%g|KdRp55dN5xjBZ**5 zTR!&&XiBCH+(+qkg`IU3iDdK{Vwj% zl3gX+cVsqCm*7ex+r-0amRc`_SOt+hsB6BJAgg(*%vou8*^8|w=rY-po25_M>lR1d zu~rc&6)TNY7QyC~hL6`4j10^EyPX%-`x zBLI704_V-h=3@C`m67G;a(8%BAfW>&D>D4iwLVf zZ6sVyv!lc6XFHlJ4NmlsyyQrO(wlRo#~SK8$O5xJwGGB>YGgJKl$mRc>{6VJWLdj7 z?)I^&L6A^k$(Ah}R%SM1G?k@S*f=7z9R?OyfQ;sTP!QEC78ACg$$TfCrvR;ZRTe0s zVOD&%=02XDS!{2JBi6?5ZN^cR$?I$%QbjI8e6z+d^SF*}>cJ?sG&m5{zR54yuy#es zijwT+UY`D8nC0t~F?H=)WQ2ulk#Kv+y0wNcC8sS7m*y+hGST1X528Eh+t{~X!n!oVdY0_t>tQ~})V65DUtQ9Ar!82 zg1kox)Oz25c|<2Cp=FHVPMF=?(FTz}WKX-czUv?}HjvrS`Y@iDw~jKVAVNJJ-cp#} z)O8e*b_KGUu~u)DBb&&&MV{1Pvpl20Ci#$5 zobq(oOr8zWXETxOWrF@%C#(3iT%DZgzEc^j8s$Z8-~3JLe#-@pJ`xBtt#)>2PVN}- zBha*};m@0q253=eE5mZP%+z3)tl!GO;{J+hQCDTLAyTu|@TJ*?yF;&EyZyS&+phPX z-OjrqjGJxp7C|8w>`h&VSZeYe=H;Z!KD!07>Uk}Va2(b}K$|6R8{-)V?Ar`8fB<8v z4n?VteZ0M#f!TH%zEY+TbioqZ%3x#6m%Fwb*&X1HLxxBdpK@Y5`iT-br&+F*KZ2kb zdBo0wG{mgYx#g7MJG(554%LXRH#(Lh6<8{RcTj;PGHnN}jY};S8rB^2Rd?**xc0~n zwnGc$Ax*VF8h2p5GhYjXZ>Vo1XLX9;;{?vsX_wDLw`GBFS-!J#C3PoNzD5QTq;SAy zD*p{(+{_b3JB{oNy2qhjTc$a3nAFm=6Iz$=G`b*qG!v0JlkC>|tvg(djdmGX=@8$p zPq^{kv(u&PE^0na1`(uAC6me_ddmdae#?V+I4GpY+Jj>dln~`dtlpZ_CVxC{6kz`OGIFplP6@IQCosYK{yZZ zLTR2iG|vl~Ctu#wJRx@;M;jN;Glch3$TN8_Y^i83otY<7hzOwO_2v&zQApQhdu_1u zWS((fuUK!(~eZyG_EOVeCCzAZKxri<$tg}3Se9*}DH`*^I$BKuaFu`lq~i$jJ2R z;zW$I35x9K{LQ=N;vts(UDCCbV5bZ&Wplc&lo`6Pl#SzdS+5aKmNLzcYQ$DKt_iou zv&6@3Zuqd&$c+me@bnKT^R+w~S<`Oi^{ZE2$BxE4w_gSyR-A_w=V3OyM-GE*&tX(J zPw3ZCzVvjIM5A|kaveNcVS8`dhH0l8O6!^4p*H9aiTeRn+AcW+vgijCH{}Nux90~G zvgQXAcT~S_N%NR+$Dg-~Bw0AWEJ!i`bTkbM6GR-$h~i3HH)hm z2<8Pp1T*dj0AV$G6T#?JZWL(TqYJ==Tcowl7C*nO`0M3;EyVm0a&+R4D5UU56xZ)Z z6jCBZKVlz`k|L7dKDLR}-ggd}AOf^^coACp&MlLlfIyyCjE#zMiM&9>z{Rdiw)pA7 zxX1;>NHg!pV95P3nHR_yzB%Px{A0r`!u>#`V4H=8+vGimKb#26<{e>}dF~os%z<)O z%gbOv@BT43N6yhQ;RMVN)yP4=q2V09bFH_& z$UZk#x*TB{93umc7-k9*K>+TrhD$^9WfPEY_TY*T$9rz193m;p|NR7cMVbRP!xXjE zMXr>X=7eF6%qHI-LH7HsH}3j({6(pZDBQ7tHPj*?cog-q-+njlAauwZR-2sI6`TWy~#5 zVSp^U1ySM7TZ|-X^uR4F4ENna?fObN@oBsO=G4G$9IsH`f~@z6CP8gLlHvGI2v^b? z)Dik+o$KYf%mG<7i$Hwmddl=$4gZK9W9F+sCrnFg7%|2D(x=gilV zSxngjo$Y3dlxmPHk7$r2=QT)_cQr_m?=|QwId>3r zlCc_el;s+9kWvi{d4xdTxq}(_;vMXS;^ke92;50T(w*#eFOlG#Mj-xdsf@nU@D?9p z|C5ij7NY*T22#ne@a;W|BONxGDo?5s#9}Xw{Omh>Kz?#3MA$EtcQS(Z$@BVaZ^K{j z4UqHDWq4mtC7sIq$Pjx{@1WValWL3gp4I>@NhcSTip9wJ-rGSa=O<6;-+jImWE z*R5Q!dGmT-%YM1xE^zOYhcwtLO#}<3iT)pr!E9HGK+4zp#qvMp5r>88#W^oE3? zzLs5@6)0LRN82_c3^ZF<;(rP=TlZ5q;i8|iDjxYMl-vDN*xC~sca%6*`6o$~yTw|d zRA-|K7n^ytVcHx8&6h5BgE#eVvTu|ezELTR)?mFXz8eazlimDEVzV3wsk^m;p;G%( zqdU*jMj~Lt_Nv}i$ZB~_ajcRr2xP!L)YW?rb)9?6|;Vivfeb`K2=L%l8YrS@J(GEZKfYCP;JKAg*J8R>?`EFxx0aTGL~Pn#`8()B)wJMBJ* zTYMkHU3(v8FT4-p-lSi<`Qr5Z2#FRCbz^dN;cc}ja6_FPK^qhUt+p1xvlsvo7H_tM zj^0ltM&7R{KKFCBweWt5o^n5x*sWiy`NAM}4~Z6ILKQ)zXEM=7eI04P*^(r)ABOcN$|eFi{xGCF_AvGDEGHgDH0K=Mk>xoCiyn@? zmX2;#pxk&f7M~vxl!8Fx?>iL99zxL5X!R9S1H(kGJyYE6*ne!->x#dwRv+q#` z%ai&gd_ke(fJSmDy)C=N$wNhv>`75TtD!?9z(o08agX>p82kO)=u*@faU)z4=Oolg z?7aXvBQVo zF)H!mW03bt&HfSDQxR|?*>Tm?^KtmT!xAHCcFB;(DRcGXWLoez6x`v;Vt1FigYj^Q+|*GWT26 zmcm(cBj{JUK*MC<6A*d86X;d1lVbhe{DhH=S=Isl-mmf3%B_6+my=DkM=ZDw#!V}C ztlF@4Pxkp`(n<>K_x?msxP*kd-ol?OQ6N<0B=nv~Qviqwg^22irx7HJB=1RbFVx(6 zEW)B|Q8_=78`}nl%Ic6!ht7~l?)h>9xsiV9cu=*^BdqG= zZ&cJL04rjjxsrJp!PiRwIXNbmn=a zD%wQ9F^rv4pEWx-?94om%|r%jy3N*Mg0mO5A^7A~hy`#q;x+)^ycU3yP{&LDPz9u) z$Fx0zU6pF7?fI|KS?9UqnGt)|AZcaDeMx0T^03ivu)QN2x_a}D%~|IW(%LdQ)7ysd zgi9IZL=v+S*e4Ppxr0c#9i(}MZisWvW@jA{1+nWX?`v(|(%Nvy(T37-C1YnqSZjko zO69UPq(J=ThS!&G(b%2?&Vi%CGtP%(R=JUt%4;wguG5O!%jx^u%8lfec`ks{1)4GQ zJRZOzIh^wg8-VYxHh{g@+5o)RM*#LrDzE_q?a~{bpAghF2&wl*oE|#3ZlH&O+=E}{L}{bl(zx035TPH%AF*<%9dYjD9Vs9)T)rx ztn~97n>f*q$YiJH&?Fpf>lp3mOnDEy*&LaKq3$BmCAG@P%*C031GS}L&D#AuZVa5* zw&F9+r^%cu4nUCHGNMm7G*ia;E^-)fN@^Pzb>KOo_W2HSgchmsz7 zv>MvPD{br(j5f+;o{y7PtGRh{NyA6gMp2xJO-hz>H1)sWaEk3aR+en^wWiCcT2|EV zvXEd&H%=~e#jqHS&4;(|DA{)1wvtsl%vQ8bK$&hFKHGO>hDMjJjn;m_AlauPY|r{sGfS9uv)B2JBHR{P zs=;R2OE3y2cRAL!9*+R_Oxw10^N!Ue8&_^OFJQ}I0abo*6iX4P@4^Q8^=W!%y?lO} z&R!?U^$dr}^=ukP)Kl}-^^kLJJvCn~YwEecf!EO-%XuziSl5F52rmBxPIBlyEhZwS z6uH2dbXc9MdNkYCDk}GNJQ7D0Rvc|$yHz5=21HbRP3JIDct_dloq`B9-vz|C9Bai_ zSJ=@t$-b~mwvrtI?zRS~v_y_KU{bOeq1Mtxasa_Giu{Afu2$BFYvP94e0}s)rTT3yP{qQTipBf(Hqx4QR`G;T@Ro!bm9r z0Y^HAG$@h>nlWlAR8iU?c;N_nui5a$7Z%7jgz{B0+rD9vbk;Bj4|Sz;ju4zuy%!2x zFh^LFt!L3!tUpV=L$Y5HAk9Py!lH}jhiT@$z{7SCm_2j3q@@VnQUtm3sUkpzi6n~I z=v_dJiNKttS>~Jr!L)NA=r4=UfuNr|kt5E7Z?2s&oh3q+?gDK z)hXY1feRpQ#W|}?1c>ho5Xf_iu~9L0m*(=ns^Tt(iBYLu*!j4+6n9;qVVLMiC zx^CsB9lob{j0k{EXx$WB3~6WtNRwMZ!UZu60&=1iV^8#IRu0tIj)8)cKIhMUyY{`3y1Dq`F3Ee_*3Jg2a1twCq)m+Aln*D|MUk=dw zRE8XW3LcowYj$k%Fl+%0yOo&MWk1zTUV93bnI@kRj6gUe9jsh85n5WfLfKEDRRhF9 zvFZif6v}=oRYpGz*G{qO${OFc9gI{bISh*|5hEN}_ESmn6S5x&-j zyKPA(KZ2#Ry#F+f>LlN4&{4dp5k@9PPsT%rU8eRKcq7Bx3T>R7-AEA79E9YMk&=C2CQsgVLaH%Ef zSIjiTi!j*PjD_3Ux?jeVg43=g1m@mw)eus&?ginxx9*X@Wy3T7&!{alnbvrrLTru4EaDQgCa;4=Nlr~#Qpq@ariB?wG z`V16U_YBS1Ec>6KIfxmW1bz@U*o`!2qtuduv#ys2M&KydN$8NXFp_Xx8^~F5BA~Sr zc-HU@TVq#*QXK2^2rYQc!a-}T_>q3dYF#B8o`pOsBMBU-Dw6ej`56g@U#Gefs|8jY z!&AuHx`GkF+zV?HU0smfia&Jfh1w|bIl~uFD^ry_P6$s|~MqRU6v* z@*SBI@&09D#}s|!^PCUG4EU_pYh*g{MQVPkwXkfKtf3u7G<7N7bj7W4tRszlFrh~V2tlaP-wHYH1k`C)u3V~g6 zk0GYJvs*_|Q>L6+PCMtJk&YNCpTEf6qhejMY^{{Lkc`$M>G=}ZwhN``C8SbxK!Fg$ z-*S?Ocy_}}MmmZN%ck98J3Qs~62ij$FR^_ZDitr$dVB;2RC~r`wYX|%$I1;WS8prX znBAJ+2C{O)aBYyUH6-6rAZ}^Qm)UMEco}(O;>&Cz@?;?qdIYDzAQ24)Npx%ZvZE4+{pq; zKF6&#yK3@gxAu$z4VTYJFQ2`_6|Efkif=zp5VqxY1YIX@K!&^uWAV#00>2rRP)CbX z!R%I_9M*(hdGJ-nRJK+ZZ7%YwRw|M%t2Il0O@g@0hEHBKCdNVL&}%dtiPO1v6t*QT z*u8Sa$~{?6BX33^_Rz|AAOqykYtYoXm&Bq#NsiEA!84!kC$*q1K;F#KYN(`OCCDFQ zCCGRhW1=j&iK*r2%pJs+$v27^88qwvk#!zmRUb?L4+qYXjt8ZKa40sgUXAYSAzVH8ec=(;)?(EF$ z?9A-$Z21wZW!?3*^;aWKQIkUi%ZR1j&i|iyBe!|@EFrhBWoF(HB80uEfPQA(OLU!8` zL5n(6J0pXRA(^{L?Nc$fVcQzPlDTc|FaaS(Yk%cdDXTX(Qsc>G>2vX6zd8eI+k6-< zZR=6BWj9+iaZ&!lMFsg&;Yl^j;bmVv&~2EP@XMM`;T(a za_cI*p{ZVV2ar{bBx-AsZXKoXs6Lp4(5rVM{sq8zEygR2+iK&L#-!;nTUV%G8S60Y zI0nFESsiq!28iCucHry>i#@J&CWs$USX7gL=TyLGzy zRrtkc*|5*fK$+BFKJ#`b8@qL?w`N$u|36BK-8w}ZDXn7_bUu44Y|+(zeaA1hNc~P0 zUpX_uSaB2W|C%&JZ=C>NmWf$ZIf>iziI}b9)vpr4jMI!tzxXy|5sclNW(P9<@62qB zQ82ZoU%K6KRCnI7TSw~)%Io(^*!sQ_wnpj?656t9>c54m0>!t-@v&Qn|F2AMW8P*g zcIz+=JO;)Gjxn`eevE1J%l1qB%3$NvUq~~nH!A$aiG{0fv&q~-7mqQW`tcYti#-m4 zpyM_JKMtGqj>BeuWgUl2i&p(rsLJda98}MhEn4;8Os_pO|0}bP)`5V_LEhw%-OKBO z5T2Q}weRh*aO_rA2dkV89^wBCi(&AnCS{Vz?8+S*QyPBJ;1aFQu1yT<;%S$-Skkxw*h#Yt$e7n#tCeS7i$ z)H-@=Yi|~`P2&GkTG3lu>A*=wuvMaZdT?8wQCnLWe^{E`i2Ogx#%yh_gj4wE zW>(gEI%1aNPWi>u!eRX{$mp$2Rd5Q2-b4@b&=;rtT#+=+|E*E<)<*i$;4*aF;A)=s z3#erQ$p1+;dTT?uPXp9I8K+G;r$I)YZS?oQ;p!>R;OeT7M|PTVX-nF-o9XuKB6chL zsmMY+X3}1}{qO8(Yl?~?8L>JI0;t*dDE!k#3Jxe1%<1{>p}3D*B4@5gVf1DUR*6 zwd*UtRE7P=uZFICMMyhbHUHz662d;5bR=x|KJdxVjpGBNwBkQptui>u9jE91gUuDj zyK6hPhiW6>EYN%s_rge#yZcZZ#5iDgY9V!yb9V(&>2ENZK}2 zH{w89I!%r2F;xS90MisLvd3iQMq3>x>2osWJV%RM`oS-Pi@h7A zTPNF;4ZFdy>UR#AWu9aHGF}7E`K1Ppqc-GoT|!H_pK?X(({tR6Q#TT+CT|;~&w&YG zzlg!KYOT_40WqYHQe1>_JyIFxsniG!JkPn~;hM)IWteZHG#gWRk1=`249%J?%gdiU zW$E}yvkMkYPTV$B|31%+wL?^Po?YRC^_!I*q^Ju#a+PI|ff{L#0a|_mkp6n|0xb8_ zM;C}sGST*qckm_E1A}V(QQP|H(gk$7w*r48=+TR_iFj7b>Muu}RmDlvww}uQ5y&1I z&4X!mdW;ROvEkdks|qlBTQ@xdE~eFQ@Zi{JdW?;$ZBXLvmHV!6@sxsZ>=TUp0G)-quEMlOM`)QSY3ynN>Semw)oBg@3Xy5m}0j`MvXw=xwca z3-}hTz~|kqPGG@!uAU7=ZEI;0Ed~hOI(NIW)g@b~-$lRJ39LN;;I)Nnmb1M8QQO#F z@mEfDZL23cnM|>&%XkIUx*BCu??e)@!sqQa(AkUZb~tvCW0;LM|6mWotiNAEBvat^jq1W?k{a z>8;WuysGjFKJlN2k|K2N3O0ZC3jK7UZUPd@mN>6lA(YKJwJyIC7~$ByT-|>L*)q-g znbPn743X!5CJ=G#X9gbIf5!M1>$pKI+VBh17OL(qyev?kU*LSc3V74zUx0n#7g(FC z4=uewCjjP>ohDv_-pkUnwZ29;%PGGijI3XQovr@ALh|unA$gZ2%+wRVf_sKOC!KR_ zU-PE)-xvi&{zf*3)PKWeOwoYf@a3#%8g3S=3BBuVOn4;jd6FLg4Ga_YnL+0143Gp5 z{jTyDuliR>9H&0^HdX~ZwD~HWcS&>BrtoNec-1d;!|!;GudgDtk@EQ+$Pr4j$8h!f z9a|oznZJW&sMgwJh~6PjSAREIt&gGW7^L3~ny=XY!DFC0{eiRPrhelUooLxo^ZaW@ z(v|hseFo7_Z`h-+ig^V0sj3vCb@n5EF(xe9vAwsV|AfT&KM_N(KWUDhnm|GTd$bHE zaL*UjiVoS%=B%oBKCdnx0CoOPxGMV-$#vBQim;4W^BNKzbq&4faE%(~X!JEC-ASuS zXOQ*sHK00ZuO)KP8i|4JVBHp>T5wwZsn}@5)K=Nofo`L5*Zoq0va9o%cPZzZUsO=i zc1BRv%VM;p!$V>m+goeTb!62_7pxo(`i5U}AX}T#ZO+A=0%7bR0dI4Syg`056_L-9 z-^Lr%vT0RM$dG8@tI^Sn2%7MzJ+d1s=q9{2Qj?n?cOAgI_fq&KOL><8Y?3BcQv(nd~w=kn zn(Lx&ef5erw~zK^#3t*y%NeXcGh$;LJ9_D+3mNuQyGDk+hw>U(@$Q;k!7@9^R=T5R_#@&?{s`|ee`hS_ z@s2-W?etD#W3sKT@~V!ALWu#+Bux%**3^IiX9NM@DFI+=tp@|3-%4-srmF!?wVY8mSsVmE4fIeDjMUerAduJ7Q65SRMt-hf zv?5JO!Oqk`;=bBnhE}R=o&q^uo8ERu71-tzMy2 zuyLp}fdPKsP-j{I*9TSsac6W=oIVVtRxgE8t6KUblv;)BR46pu@(trrQ}x40l4nU8ez^_+7$+(pv@=4oKZe>5Wm($qGJ@}<}q6B-3XT3 zK#jaN=F?0*X*O)$Ia2qzp)x|RyP+~%`|XVzJt+`;Tm4yEd&_LzESc09J)# z^)tc|z##oC+?gDlTaDbLu6H+wN9%kzGAs{=s{#6vGQs_;-IaCV%G|=Xw&b1t)UppxZ|)d9#Z~j8WTP#lXe-gWCGO7HwQy%V|fW&RdZls#)8a63no%8n#uIHXaM6 zciP!aBgmrTD69=&7j5J%i0Qil+N4Kkhx$i5cIM~@%kQMn2xm$NyKc>>yg}Sdz9$+U z<=ELl!y~Bd^AXM(x--IA2aDNg3Fjhc*^&rntimFl{<;!D8*`2+5^Py&$wMn6DKa6F zbS`y@gggVessViC7IME(BP!UllPx9b78k?uZ;6SDR%jGuhIp{Zoz3Kqa@N(@C_K@t zp4fQD&ZZg{g&H=|Po7xjoI4xq^(gAtNC%^!$|e2DSo%&pZZdvjXG67%#vJdCM#BoC zX@dH?CmOhVdYyEp!v~|CX~A5vpU!l*ncYgPc^}3`t6dBQ>c!BkDe4e|&ai;t1@Q** z)oDwB>3~P~lgBi;PD*U5V`rke@l<>)ox{?USmc(VI%$bQ4O@9qjH_7rq#Bno z+7wG&qSc>Q)rq5=D-P?8R8k!25$YaC>DroQk6L=f62tXD9Gts#%-(8hb(&!c(<^C^ zo)eEb9#4ynaO@0GK|D48FrJDWJ{(F)kUom12xnyDX_)#6PavrS_ zjZ-Yr6LlcDQeV`;s0wwKQfiQh(wvP5#LF+&$$I9PmuWyE_?D`EeS2M^{@&+eeP+pv zHlIy|J2d_GB(M>$^6==Ut{&>~kOyoFJV>pJ)_Q>MtanMr^_O|Dq)z(7-a4vIGDbq^ z$;%-_mgZW&i|)^}tG%X@g+@P^3}9Pr;w^*?;$A>vAo$*#TFxjwQ3WBN6laXury!1c zDfr_Fmew-`!L(9d3cV|#qv~=hnG_i9*wsR>q=3D-_NBlx2f|YzlBvj45}T?`Dl9h9 zSbJ-%)w~5af^xOjXO7#mc9hPg(x^vMVWDOkhVgSM#zfdBjWP|?GR=%E4K^mHA%l7< zB0ZQ(Y77Z6CC&<9!dA~T?IcSfburY-Y0h{wJG3qanOp_SM&g#*vN0H*JsL)ao-xSP zb%9LOvzG8pT^PA*k*l_2SAxDJ1;q}m$0JUS>(Se=&|{v3n+ueg?;jnUyeo#vcvJXz z@ExcSi>p$wo*H%aavaZxe8lkG$0Bj*@WshKuX#j~Jt>#Vp4C>tm;11A!OQ-e?s5a-M zyl#+btJY5sU`VserR;{Zhf`x3g2qpG+QV0`Hl&n82Y3thsh$hjDsy%#3qD2qrtG>y zG3ibmz$$g*$-ddi>D212bmX@#9dB8vx6_?zfn3*SB#8*}Rl6vLXgindszJ8T05UlP zpT1NbGGJke@-j$&Ed$;!4RtbL-?>PyXMlU5ipdGK!78X2?h#F))uNQu2)U#+Vn{l+ z5n7Vd$QiG{H3ILHM&K>b>PCzbxi8g}cl%J<$Xn#_O{t5FfYsbQ5QQ59aYhQ;IcFXePWg zh8I(5ZYq+`u$qxUp52XZYp!zpIb(c1yEC*5P?p1=$)qj~^`*Tv(ASxusjq-$JnE@& zGg`H-hS-B^`Rzf^)(oMhR7r;gZ02L`0ZxVmyOZ^OGjMqn)Ew6M>~eEFUE*JI;Y*Oc zgQE0!bL#p+3u~y|33?J3Oyi5@;ABnITU$a_E$M&#qk?u0*>$EwFFHkw*_*V#PLT2vn1fK=oDcj->ZdK}Tl_W7aC(ELz0Zf7icHc>Y93MiM(Z zI-`SGkMeSExypSsIBG*vf0taHoL|w2tgGivb?jj*nFBu~bEx$6mhKo82EpCH2=t|DQvdpEvwC}Z%>5gbtK@tr?x`F-5$rDS_<{GK2+?Lu-ODs5r(Jpt-d-_ZE$sV>0P(C1`_ zxTuJEG3vqOiojKr8gzx@f3$VuRrmNQy(>t3HJ~eQ!=ZWh=7TtmzdQ6{S7)MQH^+<{ z5ui`(hU9B>Ly{}C%XmoIU8vQyAfC8;g=Thhdh~WTo3VDI(UxgbH@H};gmwh&lXfrB zrCQ+Jy;w2bsq-Rr=#JM}SjC;G7NLwe^lqNr3)H5zx5#|G(cP>42Mu(tnNHO{lGeIh zKNxRQpx+x2Qs14gI*n~*VD}uAwy}iSy4nU&?4G5|+4h{N{XM`mLl=91i6f|9OoY9f zsWiMMerB3JwwBpFl^}sVr>LkWTu#=BdLZ`fo}>{}*s*(}R)(9fcjqaz7t-Z&4MWBF zg~b_d@kGPbc)glou;X+f1F3!43$6G)!yQXUz&=4QIA;56NR0e@BhX3NZu7>YbgGFp z>+X?i+M6~Qq2rC+Nsisal~v2I4bxa8ty8_x&~qtn=R6!r=KS0x4nRxo^;Z|OG5#4BQ34J&8btVV&L0!Gm8*MCbM){`h z?#<^&nAEK6OPFD9U#ERN=#jn%um>awKQ+SxbCu=%8s^cvtD-Lwq4sBPq++Q()+}&Ivhw<+x_Q>3PdH~%WL#%59A?zzpE~OocZ%dQx z^-)e+TW#8Vht}pgQyhC%5koR{*;Ax45|lUyzWfG(p-@SKK(Iog*~oj(a@{nAP1&quASAgc1^AgZ`T#|A-Sv2G25{vrjVj=(L{8!d?lChu9G{K4eU*ML;sQ})c$M}t8; zSEmO9U!dvrSmf(71ihM;VS2S^j`|OwL1vpotaD;nqN#j7^N-ZWLri`{Fz1>26d26o z>=1DA9o%g5Z>*UOC3UJMm@Vy@!pAmvovgkMEH=4klC}(`j)B9#@@TS~&FjOU8ZnI8 zPT)HkAR5oy*30xb<|^)#kUi|5sG4+GcrNDy!WqeX#>l5WEC&w<&9B2~sZp9+-<;1# zWe&$BjnJBQUV6i|Y&i737>-O|84lo3eL0+A8s9a%?WxhUKSCoNdj`uj0#*kpeFQ?u z)d1dtxIC?jIBlJ?Fo|*Wo&kD%1WM6gN$oM0TO&}wZ$`j>U-^urU>{XrF3KNC`k;{v z-+O89Nb1#78|=|TpN@n|cbzrhZn~I;^X@&0dNdzJOLkGeQ6TTExueL=(TFr_`A#}T zbsc-qagx0{Zi7XJMttxoH`ZKodp*$rzcFVtmfo|GJKC|Qt>%t~QX3_8fS(hiaVT3x zqwQHbH5%Nl)ubT>dW@lfZ#{REW{&|PwVs;`z{b!fOUF24f>?I)4ofX^;ORl{Sz%fC zGz9$m7)IYOHFU>2_HZ4|7%(KHQwp#6TrUp zs-dRbA<5CImq#5R?MG~@Z=S^t@(8uf(ttc?YJf$%ZBUw}cejQ!Cf_?lkLRIZXY%NM z_vX?2PSaTc(SO%OsysyvC-OE~19$leY}DnMt+N zHFhSfUoSvVJJB!s$fC-PEpUtEuT3@=|sTwl}iFcU;Q;`}s2dD`3apQvy%)#Q{oDYZyqwYn0Pe^o8A+MBW|7trGL(&H3#eCd7v4jQ}etw;xnJ=>cDE8Yy?nA zi?A5Sz5(hvAF%$KJs-CEY5jac6n)Kx`1&rp<&}FYAW~Q7!{^!gaMxRZ0zr3?uz-P% zO(ncG*;=_D#mDM_1#tMUv|4z^eciQY0hqgK6OaL2Z$oO}$vUx$TS#^N79yg~st%dYqZI!Ty z_L{y3W^M4~o3bxkGf1L0S+@vwTi-6+OmpLEGKARIN)==6hAZJ%H`$*o`NcERcBt!j{ zfH__BmcU0t$sP^#8F>MmfvhT~wS!_~9sBCZwG{LNm%@M6QiPqR+@lK5Jg67#&WnBv>a|YLb{w%oIKQSey`1}&fiaK7fPLU3$<_9Dd2 zchq1;u?nH=S_Q#^&8JqO3E0t%zcCoTJ@sI6&$amTrV!GYx!PKAH7Gl3&T8Do?b!z~ zt+eHt&}hg0_S(D}V(oMs0H3xS?!-yAfj5hAu)HUqA0nvk{%rNQlj^R!6DAkmNo`u| z5kP}m!Cf^dd*JF>P;-AvRg#5G-JnP?_u<`!AWR<-kBRJWrXF{Bt!nmNxRj<^cNex) zy*O+0n=Ee!u4{MEtpB+SYK?T`E>LF3b2ln7?QVo#>p?Wpv%jIH-%SoHvgFu`?A_4h zo6pt5VkW~?(cb-a^@jnbDd8RfQ`PAn>T~}+PNvPR!Wt98APT1RNyeO`n6Yf&OwtA`O!NZwyd zuiOX!7wu!Yv7z9dddBv8goCyxxe*(8~{_L z`ymi?yAWq1t71mM573eQc0XnmpwI_USN|$DZA`DsgK^PX_5dQ7@&J@wDtv%yIrTh% z`oT&bwsc=E{iTr|3VRTH8~z~aOGYL|IQHM65u`ZwtB= zLg43zATURvYn`e7HuE$F^wx1#oR+UOS*)c7GgU}7lg^E6(bMnOQZwha5OZMD^n>M0 zRp`T5*p%w>ED_25FPkClo2+5v5UyYTFh#$77{*?I7?gS1Lb^ZKgjZ2~z9GY%#C_ux zu#OfSr}TA{8mj?3f-MwdY+<`Zk^jjG&PVHD;l*{R^{I78b;mlYI#Q?CIj_?top^+i zNQ3pxU(U0rt zezN|KxbwDz6HPwgQTE?Sy8G{lB>(S#Ch8s%nBBbbcj}*@5_^l+Z-0mFIK@6nVyrqo ziXzq`!UQUQ0pE;ohlxKv8|6$&|j4#5Qe-7RG@_+tAf^=+c+@Ralok_8_4$4>b~@G7;iqM7Dl&N%PeD& zo_!oeu@I#BVOz1!JE$p!k395s0YHHmlvRiCG(Pf+>gPk>|66Ns8))K9>EzBXF= zxhIhLp(p6LXX`u(%t32D33D^m;z^)pXq3H8SJ9K~rI=={qLp;oTqCE|&FP&kJW0cp zKZ#VQ=qG^G`YC4!y~f$#8j+6ula%!oNGEFSQ=rMy>Zd?DL9f_jybh2TXgijxkm_JM z`)jhFhSTJy(eN>9_cQ_;{a>mG$hLzx_K(v2PlI=)-g=q_9-)$_5eKJIyqMS*)J$6* ztQDnp&p5+X{~4GYs*cYCTd3>EptUS_?xTYXOmHnhLDjswk5+vhn* z_IeIi(EK@Ua?W$K&5-A)V0Yy|2jAWPi;qva1VlvX*mLl`6JVb%n@>{7MM85t_-q>$j_NVB;#PHHXG!PjVR*R8=(@cn;Q`lbD0+a3slxy z76?2Tpc(egg47FCt%k-nCv0-irE+_9az7=ReoFc$-3Djkyc1O}1(w?nxjyhuOI7?L!=xpMf{A78OwD~cBv#okLFcZv1WCr(uLo9G-0;9c<-G*X1xngv zI9@`q@4p0&c`CN_xq8j2a-cxP%`FCcAYbiXCVh_bUWTLDDuxx`!~?T5_j7lmF1!p6 zM_$HMh{3;1rKjtiF2?ILwSI-ysTzyG90#Uo^;_=bzyp(g)4X%v*2+2Oj0{aaV2e;T z8Mf`~@>xdn1-=TiLr>632l6!UgfTNgI>FR(*{cxS>CG9Z6|ch8SUvwLRL1D?lSXB< zzIzoWM=9_%Qb(%sYxoeGN*V?4X4ukFLOM^rW|e-5IqiXADtXE%4ApN>LBaoZD5O12 z&@;n+_2!r3z#uh#9dx;R@M$A5P;Yym1Q{*4zdn5(n*DUz-ukN3Gl;e48MgpyeQ&|(yKm8e+1hWVvi>T?AT(1sZJbe#1FaSPHsWrj_HV<= z{clsobA{Pb%7GSofF!n;Y2qOeH^7iraU6guhPLM{In4Yokf z{0jv0Iml*)KTqHO3$$|;_#UYRYVsa$`AY0U09o(BY>f(cgyZ0BC03v(r{BZ7?R$^y zTr+j{J+RHtLlxHU|0eyj3O75Z{*5Gt{Tq+9&VDWbH?ULm$iIP|tWK4{UNzXETo|L6 z_rdRapYFNC`!w8>4eusY007l(;tj(0^+iE)ZPX6sc4$0{+;BBck% zD5saVqN8>BeW;Am#TI732S@5cGjGNSjro9#;ac?pf*Gcb_BK@GTEI-eX4Lf32WVI0 z&A7hWn^A~CYO&Vy1N7N*?nDy$>yyo(?5C5P5nf;2 z`jog&uMa`l^g|H!R-X@%W-o5qVri|~0Ehu|OoCmd)W>tMhd%m@Y9t-(uHzrV7P@am zx@y-hP|f%Vg}b^7V?5YdvpymtN9#U$$`!krv+&?as;8BY4hr!YENV?PB^*H2kL)L~dO8pp95KK+I5keRI?zJ!BW3f)34 zJ$wr~`^90je}(;;x&`Z>u9cRx(-QtZKeU#9*n(piegvSft)vwmA^z85D;_OrD+VxX zD@L)~(uyqYqQU*seyy|IJ(k<%D7imcS|w?W{x5EYK-M<0-n6VS+sNv)({jS2#XVJXCvDL~<(*N^;_kY}Q%~&#!-k#)&{dmy zn$;I~(U%69VQEwLz+lvgMlTH?)$N9Tpu*ND*5qgR{Xzngx+pFC}z*g>p+_qhW zr*7?{I!iw_R@-dYjiF~(1$b<~VeYd*Bxh;Xo#;xj#W}oWTWKwT*v7lNQLGjkD^#es zx&Fp8sF;(dCX4LWY%3aUEB?iqdZ-@?U9<;EpY(G_>UsP1;2vjGK;tT6cmSU<5mAAO z#f_>Hv~fdxOi*z~H8Q-;ygO?|`6d>pD_}1>5&G=~MXS9uUIX>ti$LpZ-d z<`tIR`UR5(!NeCBqQvb(I<9>bV2A5I_)b=*ebfS{XI`v0Ng2;sEfbZ?JGZeQpgx6$ zAVHV*Ig|b4t5|8R)e{3_HGDtlhQ3T?mfNpo_UoDbi2JVnSbMad+Ye7sI>YEFusD+8 z4kBrlt-NKCks(RNe5BK{D%rAwB?~;hJ**ByK%&0CsC?)h=)) z7Kc?ysHNT+5fvSjR2*7`ixrZMeNb)3%Pp8 zvi`7yv!(dK0lH>I`YZ7eb3?wy?Ty1{>)=dw^(U3|)oVMki;_M%u+!XN38&8w0pCj{ zhalKf37^o8B|Q{%nAGlSdl*9@Yw4gx{!5KFFt z;Pj18XE)t!Nhgi%i_wfeg6E4G!uZ)!(m`X7fWEy}AHnVHJp%JD%*S7pwAE+x@xCQ( zbjbj+<-fp;rX)*q^Np|8T#*5}R{GmfvRmp*K9xUz6wHT?((l$RL+HQpi=`-c8SxRm zH05Q;roMT5*iN5V(o|0rprTJ1=$&O0`l1ZQ`~Eo?ODf^Cb{T=&YQy2S1?8==NMlL5 zikd;HZ#k^CEXVTamQ!k2Ii#?iazs~8mzJ4i>#EPIm_$jM@?SNUQ+30#QI zT^k5AZOuY+LUeFaiKj{fEoJ>+!g!vNB&{}q?XRG@1A3z$C3RFxVS1s<75JEHTjJD& zJl#B2B2HPAxZt8n1TnP|KN+Lvhj;}St*Z;swR4sD^YlfGzDgo>p^~8_3r4Tdn|n&Q z+sp=gDJ8Wu>KGZ}`r9#N>(=$fwzZ(7ruN!T zjPoau^Pv-r{cD~C)$b>$(;af3B-~fLO1s}gJS$H!3ZH55n3qn1<>8a`F8fZ>J-JHh zz%HGn!j0@#@(Q6i#a;m(T9lEC=^MK{;B}H#r-jk=mcJvfDzBt98^P1&$ zJVb8NX>x;4liTAoxepxz+iXi4K^o)T{L>)&@HA|^aGHWA4QRJz&DnhFwA06jG1i$g zNU5W4Orn;h9n^0-tx|B7x(z>z)wa{Tv*>kOeZC#>ojgnJcUU?-;#taNY1v?F&eGQU zc)X3lN?WP-R}^Teg0IMLp{YF$Z*y(_3TZb}TN)iGK2vB=O*M1}XlMNgw1fWx+Qypm zABr{7`u_l)!51n`6-v_;!YEgXUjyg*8r5zf&)42%CU4-FFzNamVR4SqdYbh$#o7Es zE(5C$Z&T{euTj3cchLXW`G#Mw@yk(~tfX&%^yqXI+ew=K4Ho~-H&A%|8ydBa-Zg*( z^_XK7h}Y~nv~9<45zLqkc!W~!8~7F?1ZOu;B~K|^X-rW{qqND=BlXA}suuqpBpu(; zdDK>&?^wmCg`HJLFk83gg7?_Sz)~)hu1Zthg``-$`5hKKI3I=&eg`|7ze6xw4E-HL z)adU?*!=*Www?V-`5svWtHbvY4AQwyaQLdF51q#npr8-8Eq>wp7nO2<6e|QN(WNv8u%yd!F<~ za$WNvvqTx3H(P&`2L7oW@_DJ+qY6OgDs!rthJnlmNQN3ex$@yz5gTSr|6iyP2TVm z1bh8Ndv#i4yie4aHKwd3c`6`_*xWONc~2=BuaADBz&M?@r5M=AJcid?yZV#X@;XS&FkDkZdgJ6do6d15%%Rs2kQ z)g6bnABs}WIAne(Qq#ww5Qif4@HiCWP;H(68T7SO^B2gD`UUCb%|x||eu2>aGp%S% z{p}Y(!q_!ID_r;mx>o`5^&AS(Prp$2VD)*7j&Jy{2(H~$D-x(tzfvSXtA0h$Y;)qF zi@$=h{8t3)(k07w>gHzZH10R*+U+;m)mIaKBc1)Q9~y5ydd*(%&_N!K(pAcv1q1D` zf+qDU6<^6mo2@4)<>>o;W+yB3;8hAN*Cu-`(-C_t)gM=3Vu=!e=WVfueq>5jx`;F0 zyf4(c-`SSDpjvp`vqr#HxdS*6RXSh4L(ow=PjzN{edAmu{Xv-mRhleI^EZq)eJY)! zNB)4qY<*ylSvp}rGdYjP+YHtFleg*W`zMl`rn&YuRge9N)lJcd_L!{WmN!Y4wi?!n zirPjs^RH3Op4-gVP0-wHpc=0=mT~%;btBstlRB@{ja<4$zmRbq;Gpg1)<&z*b%00d z#Qgw2bsgE>c^%n~&@y=@2!(0XKt{djoC;X=8Vk z{*xOh#0xhV%$%`byKbP719a9P`fD!Lca-*1gPXkeRll3y=laN=(EaEp(2vcwFq-f>^9tUQc7pnyUl8l)^VNq| zsIi~Ru66n7b5t|s&@w&001gguubCfp`rePa{;>cz5#og8Wj|K}j@Lso0=rP3boKsN zpwUk1J724va6L~i+uL02cY?V<@2+$w2PYk}je5pS^Hys5s_jHSG)Gx3AZBZf3;0g4J>i2d>Ha!=GBl{F7SN3E-DA08}HD6hPS# z>TZwWnjHW)!}Lf1@Rb2BzUm2-ZrZP}4SujXy=XKCX(~_64s-?R(HCi%%}$_0tJ^^xY8TN>iU8(0shw9qTyMTYX7k>T+|nJ0<8)Pm`K=ZAiJ_abDqM z5N)_42!h>p#sIrKn4H2FQgZn36v$css4L6_S%?H2Qe}?s|hnK3R8_*?uvKu=tbW@>; zZdW|Y>5~b@!wXf9Cx8po_zg>#uZwO-%+oUO>s&qOeHN%_BK^QC;k5fZ6VZ*sbF_b= zwA#TS;W7H{U#3|RF<$oJOWHlyyuSI5Xq14BOpIa$H;LU9=hS* z_TXmVNUAVcb0cBu<46$onPiA^^+_a@2I{P3q(_kvG14;nD|4hdq<$JP(lGQ@(MS~F za34Jx!J>KSN~|QqW1AJ(N**QZ793w zi)fhV`_R0qQ4Bms#DJ-jn#7RaQJL=>r4CvW1JCXCR16B)PGO^f_K$^3r%}kWaV+Jg zk1}4f)if6Qt+2cgyeX|!ND33{KSmkzEtNQ$!ZqUnxEhOqn``!H%V?(7agfZ^m^esr zcdorP(M!DPLL5~*90y~K^rK~G$Q=*Tbmeyi+27(pHZ2}x4Oj_575B!w!t`D|@bz@S z0PCvLKLBi>0Hdi10H&&A0(?G@0N{{cW7z+2I9bR4;Zr?6tpy@fkO;Bb%KE@wYiaxkHqRgY;YN-kJXiqz-Qhjca zOB2p=Qsqc&KD>6T?}}y`Jgz?JjTFF)!*L`-jcw+U zbR=DKiZQ4o4Yi&p2@Q1PVLFKs4X90dUo7ZIJ&kGrfx24N00E`Rv(DQpCRHJooIy9p6dOGltDz-<2>f`p+E(0@2%>cNTI%WXOZ5;1V z`L{Db@|dO9#>#1v57c z{_95Isi9i{s#jxIO|@M>gz1P=y&F@;kIgJ#@Kqkc2*(kJK57iNK00Zscc^qBdT@A^ z0^We#{3f6q+5~hfHMa@*g?g8MY zT9gU%U9>Kf?9O^;IHix~=(vG(+RzNj9W~9Ge|9r~hcpAYz4Du(K73_`Whd{)@tUb= z7?&1%j<(f@R-}ziH1qcDx0<=?s&8{jHfs(W9FCsmPIDY>rIFKU?v$e~IW7#{7W%R| zfFUgq{x8iT(M+K&Ty;^vmiB0>F)dtaVNFci?Q{f33^H4B$lzR1g!Z<;xE`8Dmw2fK zWGY%vIz#(GueL2oNNx$;hHBpuG7Xe{3gI2Cukoi)yVRrg^j1so*H!-OxQ9BeAn$4g ze5yRHfKTB7Fk(p7Y4&D&Vo?568}y@ zbT;+L{ksvUsX3%Lj`CIbY#Q>xY(S5`g+qDAV6MG|i%UHktXFm$p&%9SHekM_nvInE zw1LkCd+?AcNBz~e4V=}GhherpX@i>fn(mHs9Chk5G8E7j#6SMsnDbR&TbOewvn?fj zG~6C{sOV95TIi8grVDoWGPmJzY5d2GRW4Z3BW;o9N?kPALPfOWu|jRzfoHig83S>; zmmXwYJ69bhvY!2Ld1Q%t?l(`jSoz-fMM`Xs^cQNxMA|I*$O3)h&7ZHc`^`S)$%Rwq zWG@xpe9D|~fv#JLe2(@~g;^a?kf*1cfz8(J4rI*IdNOPZJA;BZJ5ccVyR6`J`E*2k zrzykh=BIMBm)9xE??|c1+W)BWHAy$jMvhF}e5xaDgL00$X*0~SCW_5L=^Lwkjw?05 zj_2EgRF<~9?H?Ol#x3gJcP@`t?k09Zm8C23C!FKO9E4t$gPa=Zat>qN>donPx4Ci) zY6DqM*`48_uC`paF1svEtL;5?!xbdrDZ`LK1P95w*x8jFSbeP#(==t~CNW1XV`=Iq zWL1`^QC+A}9Tjzf(*!OcaM_;p%RhVZ#A((o@Oa8%b@_sI(`7N7z&D|nMJwqXKa$Fr z7ByzUWN}(^K6j z6RIz|!EQ*EWNeLp{qMoiA)d0}suawe-C$?g99I^khTW-gpa$>=3GjLzySO})k7DKA z#WfU3W&V2hyjMCk^r^wRbhbN0oO1Ty;im@n;COxyYVOcn-a>q;@Nm%9?roU2Jv7Qu zc84DP!MHuTN+)~Jjz#do;yU}9njEYV6XH3#vO2+bpPtPLBVKm2P>F2}?_K)3O)K(+kXtpkB52rqic2Fu8@A)e9CEXk9O~bG|+u zWZKya?fj+}+A()SZ;}gC*B<%m+Z!XAqnW+w1wQT#(38C_c6W4^e5RUHn#n<4u+5OO z4>mur4-i>>=)0#Ww-2oF#gjY+2gygL=ox#TtRW{kSQFeAxcg3eF-=rxUvl#FxfkIC zjpz&I@ha*I!o7WQBH!Ifk9M&y_Epgr)a-;Zh|$Wu3vV@{AE0`yUinLX@{c5)Pdpz9oN`tm^FqxJG12(mm%`~N^8Qp!23lnXNv`tt{)UC!ry z?47epH)*KoLGa*niwc#ym2k@jGvyq;7z8G^DPl!>a}XpS8wC3y+B68y^rsd1@f=<| zaWG!ccQ8YYkXF@--aR7%2zqR zGF~cosOJ#Ce3Wmgcj)@BRH1B@J{$rcMLJ=rE9Em3Ei6>lO;9J7tGk)`J*+R2!*(W)e!7~_qRFh-PS6xRCJ zp)h4m0xG#|xMq^h{CC|bpoS8-q>cX=g>Za+vKy4k2J5;343cLw*m7Cqpgx|mftqgb z1N6{n%JtW#(Tt_I4BflDiOb`}|HW`Dxva1LAPc>%GX{8W(!D_q*Nj1D+TK9T%6e+; z7$nex%OynuTVeLl3y?aCKxxhovemoHMkC@Z{B7bn8{0;am~P(EL4>Ui_#aUr7R&sEVR z@(a|<&+_v%ho^!kBl=$^;g)7AY%=+?6knV4Ws?zXuiESnFJ~zy9e`;i3J!`4$)e`4Sxpv$n z>m|`vHD}Qywo&HKMk!n4W&xh15c3QBW+9SyW+4(TxwrI|(zm#}a&CmZg4&ihSNqxc zw)mjX5v%Eb&LA6W)qfzET;51YbHJ3LhSx1UT?4Nh#)d4c z;x72yP&)T9)9y(TkufxPeSLBb`%fybr|WZ&P+cYFQ#?&`%%3Hfr)q}1GnV5Knp_ph zw>$Zou_fyAeRk7UIXkHGVTD@-3^Y+0U(u7zDsZ_qtN>0Ebn6>qAzpQD)Rs~nr^4^x z)l(kJ$yOJ4HqX{ib16AX<7?60DHSvINJMz5qhf}}&0}0O9WP|DQ#%31$m@z72CbN; zSINWi9+(H)Q*>z_tv*@xBEwlRosTYk8xbC(RrYJ@e2jym0`q~GpqK11p1V!LlN7pu z>|f^70BqY@fEJFlgyXfsxxIb?ZIicvtWhdjz^H5_qO&6vnGDM~7utslGm|Sus2scZ zO{y5K^9$f(m_iqVekj2#bTg@9h_}gzH>=37Bdu!k>%|4UceC z43PgK3iemVBJ%qw*WUVS5f6R32&S%Puxb7DA~bZ@BKqoHI%`=C7Gr%ueuklk8ZM@2 zcMVwVN(t;%#VtpEsy1JKwAjVfJARmHMHij+GqbATLUKS|Io^&&;~fDBBzDp#fo9(o z9o2sc644SUta2NL_Ilh>&Mbk6ghs?=D%$Go61b?p)C?!mQnK}FB<`YuC{H96Pp)XK zxl3WIl^$D4jaurXrKm~^owh{wH$-5h70nbDjK?ZihLsIp#^S<;WeBDYcUn6tnn=q4 zZLE`t;plfoBmI%!Rgw&CszZvWB3+G^gSw$|mxH>2me`}do>`8<)~oV!cKJBpRI6HH ztf;GR$wSA3R`5tw(-qj*iWPKBQ)-0AJ1U5(lfuNhp}C*riX=UsfmYQl1mfov%n9r0 za=hthg0cz$jMunAY>O{lnUClDtaaLj(P3A_aa>`H8VWfNCO^Z;;(5l+m zky|#iXP)*)UaUyEyzLjPr;ET5q%B3R6inZ>h!l{lt$@kNzmhQXx%qk0x4$-CdmR>nn9n%1;9HjQEU8zCUo1)<+OQi{R z9IZ!?u0~dok=#WsqCfIcLLZ` z6%FV*F5F4Qf9S~Y!&BK^KN(~XA-r9FsS-UWhA`mmuF ztfS6ZatDRnO>%p^*@5Kb%68gobxEphtHQgh##$9J?r#-UtOD|y zs`z_RnI_uqLU~gw8*|ICVQZvy_hL!q_ac&IAy`snx+?CaKttWIj2`!4zkfz^pYELd zu#JQm`t{0sD!30e>nbk>b*xNdTLUFhb=Fe3SUcKMlhycshH`e#NcBBN-2ZbT3ZW-y z>HUZ@QBMPaQg5-h1buTq)oStp%I<6u9_OfxQ_}}PU^nDhY}0!xE@u`OA$cleIPXar z0>(hFQ@U!k*1o9Vy>Bp5fe+%kHaf$>VZS0CWG+#gl>#&6%38Wv6Z5YOSJ8vW#H|Af}BM1T&g0oW{C5PN7!#7{Cfuto?sXop*fI#q#&f0dh_%Bq0?@auRw82`!=bP6)jdn)HtJ zD%X4Mf>`qLiXhkp1@Wp>LG-F92x2FsLkI~e#EyVG?>Pzg_xzF9$#-{lc6N4lcDBt> z9`{C1pcDseq2q3PAe^^pp+ok$T-lb%QzJB=25qHO+pR28 zmukpXTD3$=wgRuR! zVXxY~WlEc)tz>!qlb3gyNqX%mwA8hypy`{ZU_@(`l7MEe{WQxJbCGH#Iw-eI6xuJd zrN)uYY0-N7X|7%T1epEd*<4_211AJ{F>z!z)zzn|xrqXv0bOGyKEoHD4q5~^(ynK` zy;aa090e7RSN!eHjS;whXjrcwCBBR$q^SE&8S_k;m-rQPJhK3 zh6`)esi_TtH9G!0J+NB&&x3H49&Ln(4&4r!pEowU{K5(i+fL4Mt+1c_bgrqX|7ALE zpG$SabgKKp61iSLw9;On#>5xAW7riMMuNSOh9n(%!P^%*;K1m*tUE5u*RdBU%(jq~ zX}*K;5VV6GlVLmHZu=eB;_M9Vpxv`{3vxiu&d?69-HW3Fl4q!B2j!>Be=&tIZc`?w*bAc%=Dq0c^1=uy-bFo46|ftI zHc{ek>S(@&M{CJTOzRD*ECBR!$F?2^1CERJb&wo3`7;fUiyHP7Dfi3XZeFK(?%pGz z8lDpn8W?>s{C_E2VOSbetFHgWuqry4$8qLp4)0NK)DCxC^wBsnwDVQAbsu<@0#3d7D$TCGc#NZuHqh8PD9rz2t!ipW5*~yi z92aZK=QXIUp_Z?~2#1Ef=I!?P`X3lie}_L98SZznIwX{N4VgA0l5Wi0q{CK{jj7kX zW7(LxZ3x!O{W`R+Q$PDztNE{!h)+9y{8v}A46hw54R}w3{#&IV3}U7JvY!=-egmz1 z*9W9|;)=!bLgsy%^9DV={|$Qj-*3P?7W)8tJV3%+j+K%-=)gLdk-1nm-T>1gHFy(i zi@=4(eUGEk%A=tXj?4v`^(OiA^(gs_sQvul2=#wpi5+mmRL4l0qd$REw>_o;_b~g+ zQujUHaXti^Hk=&Uo^M|}JRmmn-l}%72cE3mxmYEcGxR!;D%*poe!IuBt}5SyFqj_# zisGW<`0fDqqcaI8?MX0~B1!G>qLP`e341BJYp=Ic5A4Mdn55l%A)|P&iNjvReu7H& zLi%{sev1~40|PS(fs)#2b2e{O*Sy6XJmW3s9i#Pc(bUn}^_F*>pLxYIK=Z`)PDeZh zyE8}X3IIxYn-dm0R!NhVdeZ!o4<61`Dga8Mq`c~l0LyVS!O>S z-UrEjmA#K{=~JE0Q9)v|>MRco)4=`czNGzN?WMu{p{S>p?5EyC`(aNk6RxuDzyBIU zw}UzRy}i9W-iDcKa1-9a<9}IA4*)`_kw~Q;0A2C{+=MMT;9XP051@!^Yv}<-k7qkI?G>K2dJFw!gmpDU+DBmglzyK0j#{Ud^GS~AY57mM1Yem z0S^SrV&3nx4iDFbcd7d0ccHVEvVifbneiVERBFI`4$s$9%3(U&>!Te>wEM>!}q|yPTk&vhPBn0xrRlY1sua8 z0vFflA@Z2b_Pz(TtMv7In6>rZr=br{cGgw*_nGJ8-uI62U0&4!i**$ExedyT49fQ* zhz+>+Dawd^pGuZgvBKkMs)M#&2@X^J4-m+jA3z9RSwG-z)WW-{%ud#Uesz$aiwiXG z0|=R~Er95!59pzhckm}2cX6&Rd_VFX?g`eD+?YCY+JW2#$W-m93ZdJe<`$hE_e^TT1t8Kp8x1&;jxfKbBQ zY|muk5!%-4h-bJ>K7yDJs|I3lv}v!N=bbo#I|9$%I|8DiI(-B#r>gu2tQ%4dN+040 zBI(zf5t?)qrP%){po5ftl)*W$x(gEVMYVf0ZUasoWs~VWgXpi*N8w37T?f#|c0Uj` zPC4KCDmGH%kAbMqG4F6~ItH_59iy$ibpJ6%*JsB}r`Qx*WI&g*eCi?qtQL_D*NOto&jF$qA?#*ddG*b?!gb)EBs^TH zTPKms{vSj353P8=Gyh|G zPwPoQmnHEqZPeo}4*L^!hM=`cB*9cF(*ub5|Jqm<))o)Yd34D-*L zT}`}2%sROuGFy|p}M*7EQ&8Wh{-XiYRakvwgHC>rN zGP>^Y<8MxntrpLK-gY0+BeJGw;HLnjYtg6BIk~z{EU=Cm?u|12;Zp?ZyS}v%q%6*C zKBXgKK4ZqH^%)((vCU@)&g{>CsTJmr^UJKUnnMzE+T))gb8H=c#zx^Noj171&w<0; zjzzMG`kY#atNZ8FYHw_9je-2&J!>=~nU$u8KBxRp?fD#zr|N6I7**AqmhG6G6x81y z%4ZE$_$i2*e2UT9_Y`6=Q0b>YYR>yWYQoDyxdN0|TvmTBYfx=JodJT`>pCTQIq1P^ zL6GPh`~lX8$?C1-FQB`Z#(x17J+=M|;Ct}86()ACf;TTw>NT)#m?Mi=24|?Ng?5q=U>+{55)71fEM~j&IKcH4us>Vjrt`OE1v;q0W*#~BaAhtlPFKL8R%hWv*jcnptP;-B zQ8Cq^SPy8`ad;kk&OkPwh5QfCGUj)mW#gm1jsxsx!43?s=_B_*48^P{d7lGq>Ny(P z{v5Ot>xP88KF6vYOa?Uzh|uA4pnVAt<(vcU$LB!HJNI+g5=={XzGmsa*9tN4c`t&AdXtbq<=;^I_uqhsXY0T)io(9-XSBL}3oWCn zOSGf$`1YDs9EoL+JyMT+OV^Ch+kg^Vp6k`D83wo_pmUi1q98k#?(aZ@n;!c~)xz&6 zFhtwzYp@P}2T_BR#g{)ZME~!$A_^j01HMNcw*MYA+@C=3l;g<-KOV0<|MMh%KC~{w zE4z;leGjhQ%KjeV?UnHZA3fFR2TJwOz#pisyB71M4}L&gUcTW|*WaCO^HJ3;Lj}!l z5TV;Ypj`@nV5aY!@goR2snL%#Y{`%4j`2StHaIRPf$2w<-GQg|;ODjNkBnuzZCSmo zm!$hwAa>bp)#N7t+Gy}klp^@jPn1ejhW)hGQTs_yp5?WY_XQOCunY7;@&#nMg@#|C z>g^ZMyPGa>Y2qWxdgFp;K%4}Y0dd8OBxaHxo=K5LO3I|jx=d!~X_@pSP8c%*j3Zzc z4KK-L-uW(*$)e6hiu_?k@b!9;+M|iy4c8iIf_)KLR9%uVspA{-X(b4 zO;2263EoxvE`hC!7PSp_`{Z<{>7JRd=f%)^klsn|Hn!Q7(^1_ovyQbX!tz;-9l$G| zJ11Fl#sT2Y>7Wf=_$MZ(z0O@`x@xD&%jn3qRSRFl0ROh%_=jnHA=22R5NS-(^-+|F z&Pmj!LP%+?U4;}((Al2BZoinEY99@3_HDaq5gv0|%5{Y%;{`dzPX2P5EA0vensH~1 zCNx!KFE-6`ny6bZPj+KvTXrMeu~G!@8^|8noFari^cE(BJ10)_ix>y*6d}LQ7a`ZN zI#5K37*+NNcKhZ;SJ6%s(aL}OqEm7js6_|%C)2MoTzn_mp-E0XO}mN)imKv2mt#4> zOxo%j=E#ZU=_`DW;5`7Ftg$)aDzk4!TQP%aTrs^~zbl6uIdwI@7&3Miqia6z%~n88 zu=0Cze3cWVlf^K-4vNGCoSRgAqd8j6sV!Ftr~=i(egZVK1giZBQNRvej-OURB&7Lf zOn}%sCGfkbgt6_C*EPVMIxxp73Qsp?uU4lr=wGEtWn{0^{bf+OLI?WWrgHXj)%TRXPi2 zE0}w+{4`eal4pq?bmnu+<*%kEkrvQ1)JeX5~v1^Z+CLy%(xr~fT)WG~o z&=gLzP2AiREvQ5gx%p8Ei5;|Xd~lpIw<<=OmVAfH!3ICWW1pYlaa+P61H|&g(7AI7 zn`z&Pdi-aoZ>{}5!;%D@{~3g>)NC>g%x$T($#5>Wg}VPja&tXDnX+-Y&2(fEd$Q+# zft2D&kmAm5qVvBn`fOvg%Esnostb4Ka~mn*SL$h~F27O_A$sj6j<+qGhUU7JIl(H5 z)t3eo!*f`uh*q87_-eqtLF8%eZ!l-(Z!qV@->C1w-{4!6b^+m6{bJWF&5U2L=W`=; z)k^ZX_jl+GQ_}Cq`I_HB(C0#Qs3W(o)>;Ok{@Mh``{v$#c1~o4Ti#KQ+@Op!qpFVl z{s4-T**`!QsKsgYd~7c7-ccWpTz}m^%82ImoaOuKG|6i6C*vz6opbJ77XbuFS@I{t zeC(en9&cTwK1VLGoKSko{u9;y#h)I*&-)Y6XnKRPpHE?dIrs*%?UgCS;C1KTqg=>g z^lj488!&C7B9q|y#T#&8KoWPa4ynWgIlP|n+!^md5^lV*a=BDIbq6~uhc%!y73k)n0<>9b9MhMO3dN4WpE7h z#q8=bi7DFE$2Qz^X6dRyaB1l_lyGUOU9dYaXGXOuvb7_~aSHCpnXaiFL4NEu?Rfn* zGvrjAxD5lUJ&9p+pZq?WbF!RtHD|19z~2n2kpoT9P0~V?vLk1rwhgq=o-;vSgXo%^ z@jCQ3)s9ov-wd+GcMzHPzONrjtYcd6@*v~(XeA~a=qN3{1L#Oi8$)MayaVzt2HAMb z8O}>vo3P{Y0B;&GFHY=po0Em^Ud}kQ{qcLP(!3aDEd4VoUXV7`a5l#Bx#{_=tuyvXxPVTa)pe`s^izCI zXML1>kDAU#dbB3=obJS#Xr8Ygs|h_mdWQ^j{15iy)UBG%#u`w|8KBa(^k;ltEe)(i zPE9SYZ!jHg~1= z+gu%&yF$C1pkA(l%vp|H_BbYZ(wE8KMfy@Dxt#H?B_J@1S|7FdtIv>JthecNiZ9ZO zfcY*o!_D>+SdZ<9Wgj$mK?ZW=$ephMA9`b+5`7?Ou1>VKrsmGkIv=pl)-E6Va+dZn zpeZy{CH8%<0)2s=p^F2kBtCb#_VlBxa;NEhKZ?iaPSx&YOPHcBe1T6_8SqN>bK+Fu zpJ5n=xs!A_%>z17ll`2HI1sDa10on+8%-@|B^IAMUN^=ud@B5$LAvPY3=6pH8x_l# zDc`FGm(+8|D0aM6HCkQ$p?H)o45iFoe<$vx`y%Y|xg)gCpW6TQr^|!-GPrVw>4w3k zDLQ~=4ArN7De^=B`M>wI?ir%3WavTw!qvN6=5gja3Q4Y35JqRw(LIa6V1TyA&ndRvihiWzDM zyXshNx}(d%+}aEUqznUeWpyGq9*^v2f@s5g zLCz?|{ag^T>a5aAo^W_x%gt2F_g2;nGu48fKI$FpY=GcT3#Lsq^yoB{ush$u`&=jP zl!L+bV=(lyNxlVLl($JiA3J_NbW7|xA>y!F}?0wcJYI^48% z-dcS@2~Moe&b6VuTEESu>Irq}oZfYvwwX7%uCrml3NYSXrLqnWrRmF6I?E(6?>;>- z9}eX$)AhQ}_yBW3Z!4z`{3R*BBfAR=RT2Pl(V_8+>>Ghyi` zcRhwiU%3|;`aZ-i=Ce1ki=B-KJ?)u@EyAKUKWEW*^Lpw+J&O0xZG-Es>vKF3)J;Dz zjX3hUYF>RR>7pmrV* z=t$6-XlEQ@jOo%>={mN(KeGH5gjDem++400zMH9K4D>c7o-uuBK>#4o4o-0*Ml4^X zsIhWJFc`99sPK~*#HiuHycj2oOaln2DtcJuf!v0*!ESSGoL*r0B|Bf?GEaN`shjGpj?TK@Svg`d3 zSqy}z`#_iwkD85&XS~lvtp0w?DjcI?OC8N4VQ`I7Vq-E#>c%ur znGssum|Tuw*V2Hv{9!slz6#d{$9v_=7m}ePRjry(c8G>I0d}ym9><`}AEY~v!~Kg* z7?+MqL=nJ1#wSp zTnVPAW=_A1W{6dH)o%uo-PE%gxm}gC4q9XKyJ*@n#P3Wqr%UfNLp^oUSp(>(K``*DYa2LzS%zj#2woFzLtj zNa*-hNa#)ebL8XKuN5G%+Sm$8VzhdNDWH7ZrW$Kv^BZW=dRWssfrf`AIP2ZL^veEs z(EG&uS)D+w(-P>Uoe6Z;zxdB9B4ZPVRlfOAHN{|-(Ualq_Qd9gY0xJ0Q+}uxZ34YJ zzpi$!Fb$9&!bvi81Z&a;syoyg=DpII{;Z>;ts$&7&xf7CUP!msW;!$_iG1(NZnjGb zrmA!|N%tqwrUowshXxd+S8F5=hl#M(&K2fgFu6L3sZ&e4vOyhPFiEG9oUz;qDo&ze zEc_!jGzvH)ZNmh-rVS0wc$A(l7^?%1(me%Z)blYDmx9r1xtB*31*57ufVVQ*yt-DH zUrfQsyD8fJS$&F*&|8P-(SqSR@A)03C2grJO^N>qj`J96#M4Lc8RNL6%u#J5I!#JrE*c?3%1 z3VQ3uomP&}FrMF@db~Xav4GlRpV%plZHX|sWgOxGp}T;GH|@dSRrNa{K3&wa19%_l z04uKi%UID#UJn|+j@nNS+swC~wa;Yz3A}nF1K2d#8NpU_&t&r3Y0m>5`rGOZlGm!XPlosTlFklI1EhcN<@Q#mK^?4#@|PdwkNg)j(V2rL#|4cwrK2;>w-MN?t)`PFaHJhmz%e>~ zNa$e-9h{E&R1l}~j_B$~rZcI<6~r=Fs{<$J|D$%4Hg;n0_-$p#6h!O(PSkg*69PAS zD@*x;`dYNrXs@U8P7oBOpw6sBc=5l=?974))mg=Wh%2!BvQ?&*&X2>BSbRa4?qBbL z3Dw!ou)MA!rg;P)L=7NBQ@Wr}wr*g|KG=oo{x#<1 z(*^Z~tGj7NkDuzVW^#GdG8T7r)+hEb%u`o7z(uq|y6ms6G;8H*YnHdR7;v9%D7)6( z7lPQGN<}89P5{T>mjq8)X`&A9SHW+{hPKJc}$6V@rHwC-oWJtK< zQXe(xMGKbnf|C<^(ZXI@+6yu5$qjSH(WM?bOg@uDuBCReBUH05Y-uylS3(Y-`mRx*53s&tH9E3utnA`v57bzZY6_)-ULe9A*DH)i@k!}dOO z#A&2hC;GsWJ$=B>OP4-$iEm%p_-fBE+L$Q+*G(EOaqQn0k`k0<`oMjumBv2}4IlNT zFZTAOYzrND#zf*$b6xFAXEjqmKdKqm59H=0U+eoJ18qJCt`Em}zkP&`z0^ookI>^~ z{iyKAehgcjUi71IoI?9k8xdUW2Sctui7~2u6uaWf{@{71KT4*7D&8`#)z|g@7-by> zz>n`6)kh^?isC{jbjDta)WiYwGOa{w2gF{gj;W3ZTJBYR5=x(h>5Vtwvj0E`&3wZ; zmiW;FsV_tk4`U2m3RY*&Z;%F}8XcF2CUb%*oiZhz$|c{Y`etEDiaz?pKT`b$(~Q|i4X&m(p>Q0R zYN*ucA_&tn;|C8l5vPDq??HAtl{?^F!oRfOaZENYfiLE5#3rQxv=eg%vFFX3d7-K84}*)xYCD+{%L zD2!R47l$(c&DTeK`OT{a=T?JyZXn=a<1~nC*Tk3m0|j%mU_U%ultw4L@GsMNv$Qk~ zSv_n(FQmL zBl+$q9T^VhSBHZqNymm$koa1|8EdWC_~Iu)twxa8N}WGMUY{R<2+sWwoqf55Ua*Yj ztR9he-;oTs$`NQc&f-Tx4QKKE1T;pgn9+=##+``a&(;pt_K}FmKSr{I;H2v~a&vhk z^6}$y^!sJJ7d%Hw>ru4ri@m{-ftO=V!+Dmew)Igt30K_lmvJyZ3fiKziD6JD?s9|b zS}b-9j^CCx_6r57zD^kwGs7qdjnbkFV*|JKgqU3B%F}3)!?k%dLD0q)S3Z!vDa7zdNy9S6(r(HYVmmx$gn4y+rM{R&K+Fdp)Hj%Ss<$^M%) z9>{gNe>|(fyBCklJoIY7-Ggi6Y3C2)5rWk!8&6fMRNE}OaT92Dj|r4qp$QYHd$~4F zU~zaKRufRmRLbyFz(nx>Jb~G7iRw(Gor~2Sn+t8UNG}{QK3pPv%fD?PFVKVkwt+og zd-#>#B!+R*e<4qo<|<$k70gl6BxjueYDn=wLX&lpZ26|cxnCv|w6JwL@?19^l{!I* z=`0kgA0FCMzRLG(m49iR)}+JKv3emL3}f^WU@W{I`=>Qy6tV7Lz|bkC`KHkSBQ$&p zV8eClDa#+mvklu@x|D|VVbX^ZPS{z;3yoeem3}Z6Mpc#;ZazMZ#;JN?1C)U$NtH9B zBOQhHH6)*=6xPGbF@|qUVH8uV0T98apF6^QWr z8OX?|lL-YGU+Ax64>FAv`sw%#c9s3^rS^!2=%qp*-biDBxd_ci$2Tl=5=$=_CliI< z+ITO>Y7s%n)KXzheQw`1R0_OOW>W1VPcx+#da2_~Wau7EnTb$e-lWK#Y$jjcsGd9N z%Z8UX=mRS(9ViujTT2Iabch)RA`GJ3!(pstP zSj?2r{Y&P`Vr=hcfSY|db*I&5If?vzs6}7?~mzS!+9@7m= z^dTVfnFGly_OQEkd69hQK+-}b%>l&%jj^BkS~rI-pQk)esk!pri>Ua`WmF%1(?<1d z1<>16=%#A_vJCVe?GO1*3xb8 zH~#V{eK8;Y<7x7F^5ZX$(9-Q@-&`K9A+K7=VVb&t0%_Xufv3Pwy}5t_sXDiSnuln% z^;7(1E;E>^b9s=uFC=}Snrybu0UEm5u=LmNf7o|Fox%b{C*rhVA#&J9>2G+-_tw6B z2GC1$7EvARr$yA#LvABG?s9jP9W^}Ni1ti{N|$ZaMEDF<^FI|IDX%Q=66kv2JR;9v*e9>n@`oh4~2JU znKK&sjlK`dbzRlu-_acP>?9ay;ac3Qn>ZA%(WCc)cD451hsNbjHD5j}kxQ&}HXibe zn2VwdS14jRro?h(evX;2VL9jv@7S(o;WFL7obpSx^!?x%zrz2|N^!Sf7L6@jtfRTM zs4iSY_!MlPLge=(k``OIfG5#(#e9{156y>HAn1jEb00mnaITJ8&K%{eKwHkPGV?8x zgT*LCJI%VAqRnrx3NM_g{wsmMSMye4I_+DDIA*NGLY%JsmOf2Cou#wm3a9Fil?cfc z)n7$&y1K6dyN(PtyM`U>kJm8k4JL*!*am4@p%q8c*V2{&`unVX_Sa(j z?5Dkjo~HKIVf*f*oVC>1TVCs^s~6EKIM*ojM1k;}@&xt8S42!<56vZC`_>`5&#XhK z5sG;oQ-|G4gDPH&aC|s{8@q*Fh-6^`*ICiu(B#;{PO8W<0y=8ydbpWVRl>GR-0K4( zb$UIW@$Pz1;t*jy^z#Se^`tb{BFT`ZCvVVhb%I1XE8+vUb&oiVP?; zKdXFKJ@D9kz^0tmI<)~D2`bw_<65cCMjD4N%O8T>0fjA~z~DW1Lw2v=olRkLeN<*d zH`9)dl*4!|w@)sv*(Wp0CeSoe!Y1frEWc;H6|bE4OkCsS^*&Qy_9pcGsZH49u{@fl zJFr#$zMo>t<=)I5^nFli<|lU$Sf7rD$}7uoSc)~fZ!?1J`yTt|SC;6V%@kQo1T7o9 zi?rxHPRXUUzw}@mT&i@tMa{$$8hW7 z%544d4@jS-dJoW^nd-nvCCXCHu!%v+{ers->go2u<41~5hQO(3tN zYwPDm)?`ilCw>1vZ#A4E^z7uM+(hjmgYj_opR|I}z}H=OHJr-d|9osc$Ca__^e=$M zDE(g?7FCBYx2vk001+#x<=fUG#$-{ ze>)#Uf=cr3a=?{T?E=Kdb`f9zd$LQ$+D)}9gH`{wkv>QP4}oH!68Z5w;<+2+Jm@iM z=r89rYjHod#GC8>B&f`ovZg%xajg{9E5Ha`(y6dGv9wx?J ziPn%O$Z4RZPe4t5ZMbN~>glkhMkxn)HqjzYJ6<7@xaXJ9v|Fe%OiQ=eyt;)Bh<_rK zMe3EhI&3*1%GyG?V10?+sS$rANR7AhU5Dq^R8pJg)*uhm*1xT;0OI13>3=YHs}q;Y zQ&jpSDAHAX8?ciVjlgT|Hd{DvLp~;I%cqnonxNg=sQlVC`1#E?7(7m;+n7c@C*-VZ zxgwd?ofDL}qA{9pU9ssY8h!6msD)8VIfED!jno@YQN;+Ic?xodtMV!89j5yKMdZgn z4RnvESq}`=q^E&O)%{OHY&Q=eh`x6d=2W%bvz zXDHTB1HLugS=3j1?7NT78eHVFpr7!aEh3A0Y078ex5dR4|Mt2w8w9n3p%>dQ>3{W-C#riDjNT^%DQ}k@Er_N;M=E8q>Q3p-A zVoYnVI~g!-py;vpub^j&+Uooj!`Vhl1bInnP()7`CF-z!w$?^k8(5UUkg~OR)zzM9 zPXvTJidyN*OE7BTb5MKZl2O}2i=Tt8=IV6WDr=@g&w-<WfjG?^zHP zMf0fEh-CL=^ESUQM^OVEy$Xfe~}V>=9KvK<`~ zuD?AD2-EECK!)n^?X;n;-rsHTc7y9Q6N>2im9BDKCnUR00P&feCs_r50 zm-y+f7WUJP$Y|tsRjZ$k3s<{HaUpSztDSX>UlKYg_a&<8sJB{$a1?emMW@?@xE)uM zRnf)(xk>plb+p&kmzn6=Ap-P2OXBknhhn8(#n;Us%DJz$A&xD0l2q>%eiGIF6>4v- zd+jSh5A&n5ufY2EUx5oPiDJv#)PnBDLcy~n4;6l8Bm8P}PNP8=ceR;1y$S++$G%Fn zO|W$V}j5t?)PaR}ON>>|ca-)!V$JK@^e-(Zwzs7tT{TemJX~+TAv{yM~ zcny59dj0@>zZ#>D4lpXO60+(wmXi%s`(2bykJnLxO<$*2JxzYsibZMe>-2sk@1ZG; z+wFH4_wiSG3~I??y7M~C3zhemhODjzzQJdR7QVqDwq2;KI$ObZaKFlf^Z2VlI!G33 zI@iKez|_YigH45T~l#n&IGOGoN0%?)kh&o%TA>Nt-lvFRkCG zhxU@YL0c+d!XJBKLfj&r%`_}pN1z(pQYc!h*te)^?pw%ljq`T;TEs<4l2|QmeT%(L zTP;-|`nZRON9eD&Am#ERp4!D1E!XY0V2A~yufBrAlQPfXUZw$W(_LHNrUfhChVCVL z@@@2h1*9jehFvGa3|I;8;))jO0$Hs5|9%@;>c0=wlEFE!qiDVkob{;pd0Mm&w$4@Q z51w!0q}(yhFq=z?)@?g{$9 zZn<`SQ_q?(O-Cr{HT7WLeg*@E``=v|Ju$^?b*M{7tmYq}0fk*cA{@m@8RR&M6SeIC zMw$f+#pu9}&ui)z#0 z#myAd(8fe@Q@!;rWOBXuU5IF`?yU?J*UtX1IjERDUXNNRj#v7B0N}LvKd{5CokO5C zt~gd-{DmbQp`!PYidOFf5c)o^VAJfspZr32IakbH*!xg{XP-b1t3q_6en^ZizE8)s z7{nU0I7m6~Lr@(pjbrQ<*Vf_Io(2bMLx`ur0b2Y4(opT7wk@P~tnxDGF80%*4-kXD zKcK?G50D%mxnqnSE(LX@zSv@?`X5B|d28N5DygNd2O+(tu6GP^`xn=!>KF4vAg^Dz zhhF~>_J-FX8tJ9zLqOi6g*TY=Vy{{p7TCgOw^tc4aotxpYTFHu`rW{}H!WPRvlQ@I zSB0_-egVD@Wj%Ryt@68vup@bOjh<{0g7>Y%44#>XVbhC;q52{I<1A#?VNl>kp{Xfb z?%Ov&oSGj2azF!kbak0p9)X&r>KO)0Vy`aI#c)&4i*+YFB-U|tkq#Yk#_F#lU@SNS z#s#{0gjH-b(x=e4UdKPB%sQR_ zgXySvtxo)go-JOZgwIG`Ex+HHM|OM$s?DEa!6W3BzCw38LrL*+mDuNfs`I%s&a?e% z4M@bx1W$Rtb#k6mjMJT=@Uxg0S!vdF#f!Pc84~ATZ1*m!p$VVE!=#wvg(~?RfloMv zc-B3IT{mB?PjMTf`mE0ul1YC98DBhCD^5}I9Bn@ZV`l5bDf)`A^&L(7%#_a;u;X5} z{DRCG8fIV9bqY1@TRiPoip=ZE?lh8AW22MilYlzkiq1wzdOytMxqCzo#LeGF>pw6`< zW8hcN^X{vx+lzVK_7&)O-S!pvyl(pnVzR%2n2*1rqkAid1Pshw{jIj1YJ3*x9vXZW z=GDOOXv&jVLOpPh#ShrX_7 zy5O3Z0=^;l9wqV^VAy(n_zi1*Q{B}Io0A8; zBLZSe)-wF6Rv8@IxtPylOV+5_w;*4w#a-Y<$to?e&y`x(6(v=&Lfg8cxo>_;2N!&c z6yB$k$sV<`Ol1rQl*CdE_zp%8hx0pVU#u}HhG!AaZb@CJY*KkX;@Q-(mFu? zM|wB$N7_Y%t)ZUkCTj7I;GLkfAebLl!d95|cL~o%euOb&b;q*D=&ew|V@gJI;hotq zu4I&Mg&EvPZT*Qgz=$e>Y|qe+KiS|a8Lny8pK&EzqW=jTT%x}~pYf9O4{Z06RL$m7 z`!7IJWG$xTxRSwo=K=%q&kJyWsV@)5>t*uav-ORC1N2UP<41q>%!ICf+TvxOef6+? z_R-!?qogzO ze5{K);eil(JL-I>VM)=%EQBms8!WYhHr2A!_WC@Fvh9c-3+A>8%m#*#9@z+@ZTs4$ zCQ9FH9oHG2%SQ0W*TyBtv26P3rEF(C4Q=)}7dqN~DLM*x zW`tbGBlJlwaBe-GU`^oaqJ75j5n(!1KzrWzrajjP zzvT@D*X~sk7}fj|btUGVsakyrsrbl%-nfMJNY}|r5IUJ_ z%v2nAZIXO1L&!w6zD)fS@XhB*9-t=r{jDDtL{m9M?vxb|Lfl_(Jgh z=8KG78>u>eM%D-((^6!(UM&Q{Fnw7_b!jTMuc7Lhz(|O{ma60{01Z)k+mQIcYlBVs zu-NEeJ1g?)hnKDRYlF0Cu%`_Jb><3%2dL7@^jCNhKmF9Th{V1+2ZkE%Yki3A2kO{s zy$KiV5#w`~&vsWk#PV7X?QB5{CSPU1^uCIT+f7rilHU~{IGzS~!C5=sopG8Dzaooi zmwOq01LCiBR8%n)rYNW-*1^M;)3c>9xq~K?;<(lxhtUAE)7uTKDt5d0g|%(8(X_!e zw#`e(Pt>Dm4ecvoRhUtN8sVJD(p%}r5^8R#x7#t0uC-9?HBy`FMmv+2W{PcZNSbQf zH5f@i-}cM~H?Kj(^X+*R<-XQPw=IVVGNqu2SHDueaAIg*Zf&)%SiRrgki{sgy@&tN zx?Re-^WB>)9_xuE75AFwm4SIg8OBpREhwXGl%6buo=APbkM5Mgz$=y=o>5LN+q2AN znqQ7&j4DUISnF7Nh_;mjo>dOE%Mr${po~Z(p^l!9v}V@UiAZZ#poUZcAHXYE_inEeY! zG^MH9{0o}4bcpiE;n3|IfYdZd!+*B)fm+3{UibwA<6pnPkN$e`7clqJr@sK-SEau| zeIEt=N@8y%+Yb>8TbV?c676UZQrEDwhu-)V=Gj=R9{k}J>f?AP5UZ3%u(7^ z;lEL`i@N>>KxbN0^(GFNe)&bX7JKtI>Q9bm0G6_SWuQc$_88=)$+(lGYkK_7QT1P` z2GL%jLqi%lO53TcnU@!Ihe}~11y7N0Uwbr`d*(+T52UFsRKj?y1 zTJi_bEp^jjEN+1>J}cE+d6wLa*Ek5~;6IV>_J1M>O*HgRur-#~V2px;e?sSd5m*s% zr9|oblM&UwDx`|N`Ql*00v_qzTW^e{;;7y7L5jU1oJ$nIfJ2Au);Q(|Uz9QmEYwJ)T{QdhT z47!qLW@~9c#x2VDE2lLz#h3aiyN;3Kt0lKU;$sGtA;BI~&sFA}?G|kh31)bdvXRB& z!%^xjuiMN3weD8P#))>X4dm@kX-y66#?UFPp+(&clzY0jF#;~!W=M{xVMy-Lq8j8} z+oU_U5rvI9%BL3m&AfTFhMgu~Tdzfb!=!b}>1MiWt-Nc}Yq$Rf#eFd$I6S?!I^zyS zSLsa_ypC%tb(UWWuF&E;&iFv{sAihl;~kq>nH61UESmA6mn%@8c)6m`$~l(a zMcXHuaxd$w<_?!VM2ejPKg&9*{}h^8mO{)251wQlcL2``#5iWeRyAC#|7w7zom$s$ zndjS0V`)rT8?Cm_B<-jHHqIgW^0V!!yPN5|eRy8cyrwHab!)mJkocJKm<;h{Ej6sB zs}UPi9xEd$iS42Mhgmz6@dUo6%PyvWSQCs*m2Y27ba)C{)?L4P${9DWAr!lpl zr=gbCf&gBCz%ab7NQ>k zSBwipSErb{QWm6G7a(=?L~mFdS5}*tBt|O-X)ag1e?XO8Ty?1K)snX!?lOP7zk zTUL^IGCts(?E@FvG>Qy$l({s=2evr%7#S?a_uEe`rA@S1vaF^aPqzwcsJ<`h4)yQ_ zi`5G-n;*8JRcf@My_@Y{6Kn?w8ZW?EwqO|>%! zx|`^vec^RK2$m%T!-vpdm-)SF9qcl{SDuwz3e3fK>N*z;Dv#5eU`o36LNLvV)kl2! z#X!B;{OuAjp8i=U+`l}!iZ)gO?RCBe4T>#qpynZzB+^|7#MQG+A693Hn2hZd^d9qD zd6b?bOL-x5-6tU~ixHY1LM`E{RTnbD)VwZVDE_+OsjH=Yd5+sWyD6Cb%1;T0b>%qc zH$e7gDdt;;Rscbu0d0DZ*Ie=C9FT;fZUQwllx8c`Ra+yx?GkXgzn-%kE-Hq)+zf@h zP+Dht9|UMYYDmDw8W4tXCWW~ov@pztcZe`L#aoNQAjkARu(;Ia3FGcXb;A7IcwSyvcC?s`2+rz^BRBu=UiMF0A(P__jolfY7HbA6=n zOG|$OtSYb1xR^H*n*3yJxIgH>LY9=mkm>7w9EXN^@v8~hH935rRvEEHboB6!3ii5ciCY56ip3- zh@1^5K?#8w3B@O-ABiXbiFS9Ri0 zUcb2!`r6vD5H(m4sACibCr9OR(BQ94_T#6_d8X7W2-rA}Iidn56LUk{fpHZs<42Vk z@M`P^zFsPvn87sETNCZ4mNvzMfladErhqGI=yOYU=!He7)r5vnP`4oz+@qw1F1Mqc zqwB>i7|J(7yhju1zyo2X3pVJZMUWO>&OTW~xU^1wiw$G>TKNwrBer~vnm3~PtCiY_ z8dfm?sdy!U5N(QX#8~}xxG5*X0~pwS8I95A%j9nCit}As!{fBu2A|isP=@Uiomh;n ze!Vdg5IMs3+{zbe51`2ZSB>f41^TryRPdO%36;%LwBeb51~ydrI3j_7Wvp&Bqn%?E(;WVdRv-HrrMbuJw^0$35 zD-FLoXmc^af?~^u>xbqPW1FlwB&R8+1sc&VQJPK1Q*}r&HA<^eHKzq2L$n2uz`=Jx zY~P*m9vkb>u0i^-1+@;;E&CZDcS{Q3eZqeFX<n%GYdrM9B!-K#5PlOMn8R!)anVer1xihk;Mrl3W(fdvRB8gPO(9?})g|j$5_K^FA^Ri&H0_mT+3j>E0n@uJ?6Ud2 zjqQpBt>r+qyp0C71|UfbTDuwrCejuU0NMaPC7t7rWO-}eZS0tMqsqTDem1w1I>bdTRzFET&?)Zdm#IRIe?$ z%hbIsZCI)UTg+yvSfb?FD6G?M(YNzvqi-whzs$Da!yyqRGzC57TQR??S{}SquE5M+ z+YYFo41Q-jr1X#3A-sgIn4?|oKt5XukD#fX?PHv{XcS$k*|2QB? zYwwElpI*fQIxLyJtCwnr2F6rOtFFtFw(WzUy1p?LQ>)W-{hDv2qk<>;?P*QAZi9p| z6x)F&PST*qXv-rVsBPn8A$9e32dI3m18o`4OI+Z`Dfcl`nPc@w2g;36R5Gj@t?v8; zjH1WQ(y+rYf>gH+2y;}7)W0A1sA-&HCR1X#z6Mm0DKulv)({}l6qN#wq3X_$9!{a| zvaKN@uy%;DmO#$eDG+fq1tJEi$x^F*poZ{^ULBx%9ia+$6dhf0daxsar>8NKR`kWc z5ZJ!9lp`G}+FR!>A)*s{run@F(o>P0C^V%LluTM-Dcv=-6WF>bZ9|CLr=n{WXSvznbGb8r`$-=PZxCn>cHwI%Afr^&6A(FIw`=|Y1}S$-?! zlF!!j{~0_>zw-}wRJ2f&uF%(9gYBmo4{{j;P1TaAPT5@BU z_~{wPAZAOq8}$-qqZ`GE7qP%N?v^YyR>$loM)}?7%V-T|LZurTsQX-l;{8r{3f0q+ z?m$IpF=b&~q>k8kL&E_i&XkdsOzIMIC$Ea(Oy))b%-PJ)L>>`fN?<$-FYF zTHkX2KX(NeIpeR-)SF~5XPoN^z8U(}ex~ch<5p@Kjt|M4s<&4oG;jC9)_JZM{qkKe zSbCiQkn-<=U_Am4eR`8HQL()dig~?(c>f8;;#T|b;uDDF^>NzP8+2n;Z;N5)Q9i#l z;;xU@DTvhIK8Vd<94EMo!9vM z^5B*(b<2(^HQQjL<9aWh>PPK8RZ6lt^apipe>gI!KW4vUYY1<2uXp3s zEu?kTRO8y2{*bnIy^+>gXDy?X4zI^}y53RQ>j9WD03?G3KwmO0PQbcn0Q5a$3GKC) z1hoIx11Q&4zuQ+E)f)&2N$NfjVNI-_S(q0U)D17Ydk4bBz00ig6SNNy{cb5YmKg=y zq`wdGio4!I^#*~fxq1vjU>+I-#Ps)ThicCt>JD28+s@j5o%zpky|KOqiUXC^D-p@- z_(0~DhQ_PwVCcd-^?k-Yw;mY`&RFfU)EJ%jq(KvntzvZEN~M;fRCrlOwbzl*cPI(7W|=q!YSS!}!vHNDO7r}+Z73tq zPvx_$m0bDZlcRcw@=0@rbAIbigUSVIXd))VNDR}3Bw(0EuSaOI(wK8TO2aa$q4U&~ zkqAxR!(0WZ^5S7oG)jTPQCuUHIGnE$TJ#jvR1Vjg;Z#0MJ1jL#Uv0-0jjbH2t}pOU zOl7L-@4&ttG6IWWzz$Xr?#jU${&a{tAg1!JLm@Ncg7)}^`o&fbgfSQZ+@G(y4qiDx z2S>p7J0n;@7mR?qeiSx1g0;yS z@En9!c0gurNsRf5mmq9?JwBS|J+p%a)jOl%_x8~c(pGoGjQ!_mD5w!vD?$y%@ZWP{ zTeLD!v17p7TJP*IZCRP1zjyLaY-KAwF@~C2>YXtd>oz$Th9))nt+TuqUNJr~Q{r^-g!@}TujL!B850+y{nA?O#XYT>rQi;UpPSRNyK zs*Tacall1u_c*$^fo?u%+4VK=K{_$6vYy_007vOW!T&}w9RmGM}8aqGJgUicFY9W6r_a{sJafzL>B9{ z>Hn%-BQ~U2tNF!M2GTZLS@A6R$NC(9RtE5(8!q&i$WD}dqAS+N&juK4jW)`A*)E<| z`s%}(Mz4<^o9Jq+A11=DO*4&OPW?C$#(V1)Kk7G$!IU@&Dr&0#B*dbI7TS+P8&=si zZzXpZ7=?~X{7p<^QFeV(#$?pZz{wPQZG#Q;4LZI7$k^-b`#nT&e=wPGzLg=Jd2DI_lN z`ck-J3z>G@jAM&?9EAr=q3~y$jE2R^0SeWzC}SF|J!m=YFnN?^|4lIC=lXme-nx9e z5dRycbi>cx)SwI=rcFa`JAHsi{@g{wr+LP}x(`ewe(t2MKN%$P4t}x=b3dmj#{iPG z>N3sx89U~(<+s;K&v!d5o=!GOK8x~k|BtEn0I#xW{=ZEq$vJ62P6!F<3B88idoO_? zz4sn^hX99ORK$|6G?B*wh=4p6K$<8@lctY_E_P5*dJS;qYrb2F{j-a#=Z-m%}IBcH?b&KVm5n;OWxy#!?o?}XzV?lOsqqp z-z%d^>)`x7oQAJ6Qc(xP!H5Uo;i%>RCrDvEC1-P}?p~b6zh-TVRoV#J5~H;v(3qD; z(1fES*xrg#+HN>pW+Z$K8HrAf)QXMP{r9+4KN2a%b?!(6WWND?`5IktZ6v15AFpA_ zC*BLwk0TK-4>5>gOxID!LH$u6DWTL+RI|YnzT8ZqBlhc0e!+zh9X05H(Ih=E=pb!+ z8Fk%bG*!&-!;fady#S48O!?k(Yu;$u=hBwZ5OH%fWJkPWee0)NmQhq8W2mV27{=bq z$BW`?b_^P6*ckr^y5Y5$aBD0xSH*St9KVDcq~ZftKK3qW{su( z8Xheopt$YzD=?{#3PI3Du8e}y9#UB=U@+T+le2@TR9VYE`yV8XgI@N|0}-z;}WYW(Yr zg==Xr<9Hg9I$Sr>Ks1b)e2C56p(;NCeomM`S8jNnUWvOqSQ96(&>DmcI;JuLjBf@m zCfyyVy%VT?fUZ!+r+>yoXy~VCn+e8Fq=NhFIjnHEkBV(@Xzs0ROryFy5jOXFjO+Bo zyFK?_orswDS1Qo5^;B(hKt#a(iceozDcH$i-}@ERb~4DzYwTonb~!!AL+2-B$9*)J zVNymHEIUan|6&Z>PgJQX5X9%xowPN53Va_qg|?c5@6Z^1I)%>KI)!pE%D=;5l>5ST`yO_&P4Qd;?6Lm#eP{{=dGDqOwvUu5n+V*In^coa7c zI&eMrCH77H{Sw-R2GX`^aC7Z6C@7{K1`wjN(?A%kMpvvDp1rOxqr~42RQ>6s2WZW< z&_uuc1wo=T@Ns-pp}6}lbvQy7-6uX2Pka$k{ln?BqNs|`pc{&4hl8!K`r2zDEtmoA zi1-Xp`f!B}n*C=&$=w<34%}OyfSHgoUsY$4pDzDjAm!dXRYB7gioG{i>t|AYjt&~s zY+aw}pXB;?AG#g^Jfb;ad~c>wz5(s{S)eWXF?Q^|>6$PLeAD#(F0{wRSrGZ!E;EJh zO;PSH=#HHYtp9A7F^RK3rm7~&=epHBL1Si9Wtvvc2E%ym=HdTz-ym6Cmc}x=$7;-B zDr_)^K8>A&i8NY`=dkuR9}-NQgd?_nA)k7zKJJZF{e#REarZ{(y*V_3brYb0!w@b5 z<=ZYhPd2~QpG&{jeapxnqK0!}-e3)$3k`#`=`EY;?+sM+AJG2STqLL6ANDQxUVq&I z1aE!?lXzX_FUBP5HIKo2Z#ymo?)A~Qzn$5kx6WTNmDNiZZX^FU=fQyU^H8xp6m`ck zx~o_^wGsCBJ=!)qo&40^mkE*W5%x({cfq96*!+#od{XXTgQy; z5V(FmEopm(gPup`!})R-9nQBSpec}Tb$O@pxlIQB;CrvNDldTDt(39=uCy#*ATdg6 z@XhCIwh#9$0N1f&XpMW#b?ulLNB5fTy|#cwGGB3q{0Zd`Jc{yCd8nFunPp1A3o~fz zRjtXlmR~Je--F^>L6**X>9CKy^m>TSdHF13A(jo+cE`Ai5gru(An0ilC%;vk-q3(W zaH8WO+K})dK!X-hlUqTTtzwt9FEYiUbBk!1pB7w33pZK}#Yu~)q==d<2D-2&e2x^p zyO>USWihAn&Ml?`KU~b9@!|F@C7;oAhv0erB|s!BVR9I}1Z%Fv61E7^xqu6fc}jWH z2I*X`-SRp|=j<_CN8W_r^_N27ekjxc`_+0Wy*fjKm%MuImcwo^w64RKWdz4;m8yXUhssV8!0&sPT0(itZ26Yb)r=A6HQMmn&%L0KUV6 z)(+aUM6kg1N4MbhE#ZDYRa^-l{s1>b*fd+ztUtI{gk^sG`=0nkn3PMF$D)tVEwlD*$mc_%`X0`7M~Vr?Io0G&fN z`D1k4Pf^E{)|%DS*KjrSUnjkG5^1^LQ8QOVPX}#W&BjXm0(xydReTyDd=u`s)8Uiw zt@3k_7xo-{Biz~B+|r1<-x`s2D#2T42~4*8t(1Jq$Z5&O9w@o__8bf*D)uQ8l4e?P z+Q$6-rds_w)W+XuH|==<8tZC4l6c^G=Dz$Nu_W%}-|Tr1V0zxbe!E{^t`~T%r>ZXi zURS$sgeC^uf4cgztFFmI!Xk9!1>|(=3;vOWm-#nN2%{xFIw1nDd9ZNwmo^{OP|zBX zC2QN!(Aa?3`_&8PQ!cL*-x(Jk5O=>?L9;k!d8B0&1*&S@8mg_LLu*)yRVF4focDdO zKm(6jD;~^O#kJ(8D`hPP+G}g!(|)v!?}NEow-!(i;FH0qh(Bv4;sd;~oP|pdW~$0d zq|eagZ_E^WFkOf2N8*ENTK^K|Fo0eH?-cp{xaW*6Y&0|J^|u<{et^=0xW=-bc0 zoA4k_RSYoU!FU~cnH`mJv;(7r4{EraO)kw6>cLZA$80nwA0%3Q?1M3?{0i2>q*oYC zy)s;vN8JT*4l_rbF|_%#D%jnH7fe{ECH zgH){*RPyy@hnWu#y6Ep;jnEY32nsqY{x$zHT+?^7G8aaNBsr?IqsG2Qb_bn*$5d&1 z4f)MVwbQl#*n3;$zQ*utqqub-Z>`qbEVq?5USf#sUPtvOF0t5s&_a9Gfu_0M`^}0q zQ^;w$ChkE~#jW>Ga5Z6gqTuV+&v>Ok-m{wODP{wB>#F@u69G;wf8w;RHYfF=;Oqui^5;1-O&`?M`3;a-Ly>z7G+9md z0MTzFyl%M>&Q{ZajpTD)=qIb8iu}w>dr(=Ge>V6^9NKkAu1IWTOxy}jNp^yXd0TTS zYwjjc4c&yUE2s2L5L;GTHbGn&!YvxcB>nw~VM*OXV8q3i4LA;v%*OKEj(~@H` zr748v`8w1@tKI>lB1!|CXKB6hkpV|?F_*7r5d}opM9igu_)Z+c-oF{9ZP`qN!nvgj z!jgNhZ}!Kf&1l_z0~s5oCRfeEeu%}hh3pX;u!V|-YoWaj)5@#he>jv7$WSo^Kdz(> zR0hy9?+S(Vpeky1KR?l&0( zk504g`mhfdTj65j!`@1M6KZ;C^;UZNb%WTy6^VaHIN3MB*D1eZ$Yc%1HUuO z&Gha&@Q4$k??6}+wKutW*jN*PvfM`S)!rLw$W{s=xQFc(!R1Ny^>p+@lc$Gubz`5g zypAHbfv2{bYy-ZQPFXv5Y=be6Z*k$_y#4xU8|ynREgv#e)%AEA^;gq*D$T_`B0 z4bCgO1^XS=m(lZd7^-Wa{O z13IJC%q-d*OaE~P)_7^TT{>$p%%42rb}_xM6I3A@g%PbMJDK!1 z+`-6*+XYvP?1IWbUAzNm;==&F__qm?TWPx};v%w-(_#L~J5SmCU5u~acQL*=|G68w zif97U4-#5flg``%ijwNj)X_8wTUT-AFWuE0*U{u|3Y31{qMi*AH{t@d-m?YDsA-)wSf`JgKs{=tPd=d1hPw6vs2ZsB2cev`epFv? zd`ullkLsz*hrriW#VrRZhs6kTVv9NKAZ` zta$-pd;9{e3_m*oz{16shm_nsDtyxPINol+OkH zeIRVVpPH)eM*wiOy&qb`wDtpN-M62jZ&*5ezZbDZi++N^_s@Qo9#ucFPWb`+&wfIu zH2nnoG(k_7 z@1vsHVYx+A*_2QGqr$q*{s0|_ud;){ai;SiNPOrvRyx}bLQwykp&s9d3$(*BIMxYR zkQ2CzQz~}&jqT@?;o)j@h-TNngthu`u2Px)83=Q9^9^c!I9tUWU5LxFLr^*sw@+64 z!x_pt1k&k>K1|)ybn;!;vg$Cr{m)IC3#Q;j!^%(AZ_aa)E*=JcqH=*Jss#hbh+sLP zyZ>+=FyUdEPGZ&YV?06sOs9?0+9OmsR@qmP$A@F~UOVECZ)296pHgK#6+Mb9q#UIu z>K%p2b=2i3`m%Px43=zexG@%YhLqHSqyBi2H<+3_d=!*5^b4S9WB<>1tFEe_aaN_; z(^E6J14zb*N^M0LyY-*J#buvSvWhl+2KVd=l%qi%mswl(hBHbZSJH3fAevW0a=yN2ctTvIrr|5$3rv&||sjgpzl=6Md=T9q|(v`0x*Zw$1Ub< zi`9G_`n<=X&#jHeIVa-+*}rE^IalFx2nyXN;NCyS{Y$I5{VI6^@S;jS0j)*UlZReE z!RFwi6Y!^yHlM%(|KkK*cC3!6!pA-2GqmYxVvwNOI%olGc%J%Z3`RaX=(r=uE z1FKHbzw`L)L+P6*q3Xg(G{79)0)nMZ$SD>evy3=cV#jIT_}0V1_R&oBIR)|=S^xms z00jV?TF3FU#ZLb76jJxYDL#2j)g3@o_cZlCXzcQ+-)S^Ji_P`bX| zO5tC{9~Z{)^P>scdKzA)>GWxMIbL^8vkV!hVqeioV__*2aSFv8NF6A~S(~p=pd$#e zsm))pxv}UgCLw|z0nE`fXL)Pl!Lg{L^7jPBJsMGvSOZslTZ-_#vC0`Z7jecpb5rdM z1kXGJ!l9NhM6=Goox^9~&bBkKYmkndVFI)ZoVLftw1pp?qaKTX@@Rnk&H|irmL98p z7U}AzE+ho>r9K0$!MU;_W4PA-sE;zp;Iz#r_UNT+XQ{Q^Icjb3jf=Q!=aBts=V(TE zg6+cOXA7#cGpse$>|@5xqi)hU%BHet;L(-Xy66bU+YrpbmBNczp{3oK2?fkTA#|tv1*Ob)P>_C;&Kbfer%rG?!2W8YZ7zl;F zAtO|=-#A0+{TNSzZ)S0gwAW&aeaQOntbu*_4RRf<3*W%bi2uRP&pkvP%VbIl@PIKu zP5(!YZv9@`5a6aY%AR;2wq!gI{|^B!s;n3TE~402539$_!Wxu|ft6WEgTE!;m%BIi z>Z9%7QtBBF(s~ku9@~{>I*TK~tWlk@SnoT;cf`E#FyF`NYVaLJ=V{P)6q&2^BGmhM zj<(wCY@Pm&cFfY9?~vA+D)v2zoYai+#0SJbw(T-And&HhR}mb^e2+ve`<{_7Ra?Gi z>)F1M6nr|X&c#sQ$CGu7WX4Iz59m2_*OH96h4N&#ZOavWLp`3L-efUI(tn_$@!Dc< z5hmlpby3Q&5`C&mo8X@TPE)ZW?wGAswmoi?0Xlh!%GfaGO${zHnvyOvR{E;pWvsR3myzqQ zFESs!cNw`}bD6!zUfOjT*i6e>JjGbsLs^$W(p@oE7&4B)7tE7to>q!ItjFCn>IwwD zf5pGB)?9(ZUA2b`_yYThreuVAqI|OoYb~RyP+V3a%_(hIeD!*1hDDZ-cKrnMXLSB2uE1n2P`#oI z(gr_+BjIPnGF^>-X1LG$S3}g*mMlU>Z!>@w0noXhk(7@Nbhgd|8u)aos9{$OHTh0V zDK-8DAxruNkQv0+g>OIjc@nh!7Ya`C_eA<;PStzA(9kJ5{|j<7S>;@wM4wFVdD+0l z@%FE<)=Vawfl#0L(W&Ao<(rwNRpcP@@Bd2k$LV#q4gayq`jw6yqp07&Ia*xc(8hZW6FE&H~MUZzN+F$^35Es9}IGsa)3n82Nbo`A!_$KuY)z=cZQCA6|~xu zS*X?1p5mP0yZk!>UOvX-$@qhYw2Sd@N+Gkq8b830?(hfVRQnG{_&fapaeXxT59;Wx zTZKJwzL~ugRK!DfWcF15;-*!5Xkl?rVsPfuvy~h!vmj6=qHf>J6y@HeF1E#PvHjPnpy$Ad;W(YUN0}Wp`WE>e zh%{>8?YSV#Ydft%4MS2}Wm696kNy+F@rCB+i4BO$Z1uFdTKXqF4kg@D{WDqnXSUG0 ze*)fIXZ{3BGu{0YacU}efG0jMHnT~=jx0x{H93O?duC(x`3ty4`X|RqH`E({(Ut}U z?5)Km=BxNt3A_zQ@Bf9s)Kk2_Cm|rS?$g?tp`7U^F0+mnI`!AqtlQ98OPg+kmpBl& zp{9o33%4fB?5rG|OR z_+)8Tm?ud`?jgO~?tyKr`jxZ+JVxG0rf4Cv z*s=)iWjVt%v5*lkl-tA9H-y{6@Mf@nEM)iwX-GlKA^i};pd+novfu>P(I*_fFV?P}fo8BhYPgA4ARX$27ma=0E1MWIF`MG5i(3 zk?p#hmR~axBO$Aex_)!~}h5X{Sj9m6w0&_eSqy}8y$S}U6ANTerD0a-}i z-Av4mCJN4iuEshOZ53ykIa0#I{oAaDN+-wN0CBMO1g6;0Y8?2xm4!Yi8tMu2&0=de z)RPpDRTt`>f}9@~5~04?%yTWXslB!aWV4M>%eFks$ss0aAOG;ctf!~xN#Lg7l)zHH zSv9n|uo0N7+u6{=LE*c$Ws_A+e-%T8#Aj7iXBR&bvZ`qQ6Cf&UjGvQHNynei!ixIy z2^_4T;2aocM{KB(?V7diIbfevPP3Rae6z}G9@%X8zL5hCe9toyz?sMeb>^73tONz; zf+b$bx%A}hT-dZW2z9zCm)WscFrDHyo9&=IY#C$6K-9>N2 zXBEfi9N*8MF2(AyQ_g9*gsc#)&bEbmR`A~I`Tm3_81(8tE;|Unp(7+_6E&eDBxZA) z%Ex7=ITrf3>_guE-Zqx9`{)!#H0t_}CHK-lm5k8ro^p4xQa#kym-Oyh;Ok2G*DAMN zu<99)i-hYBUssSGG-8U%PE|-_YixE`Rc{H7gzPSIbvFu9hzMfO&YD+`KxKa1oc?hMxPF{fX=*danrB8|#9lHqv8zG*om^ zKpUueQS$0*<2}@2c0H{wN+u4ci&9}7{a|mkbslTFP-1p1TqiK|jq`H_DAmsug$|zJ zN9kmZs|E*>va4&aALXj)nk83#^>0rZrTDvoRmb0Djw-wQgRYWh*rTF0`a?hkeaag$ zTdiR8Uf%dfIybwV0$t!Jt7I2Y_^J&zPA2KaYW7Ujo^0Fj%T7>Cwn=ezylxtNoCcLZ z17*kRkxi)CF^clD_h>C}yOIK<;5~aAc5|LhnX^UUJ^Q?1@XaQwClH8ku>hzmrBT6F zE?h4J8=jK#T5^~!JFndJ53%e}-Mq(2rhXtCIsce_@IisJwrwDt#!2-@#{Cej2n27i zb_RkVh3cNZM)#ArIwC%VuvCz+oh&eQP8`BTrRc9 zvQysKetJI$JVh03gEk?%h$i2)o-3@lVA2bz4G+B-Oo?g1bditN22=eriua)7@`I6` zpM#N|`LqD|bQMDvGg9a2`KkzSV%A(uu#7pH;K72s9OB|gbBHUed{uSKPm1irq^nsA)mC?`!zwG@T8S)6o-VCs@912_$Mt?u>>WW zE2RV#HPc_+spvonSBP#+^k5@DX`;g=C_qfPRCxcSk^DmeY^bWCq&Co+RN&W#BJ|!+ zSEN1-b@}N(p{^Lj_9zgpIt7zBMqKrYr6YZx)K*>-8}d)M#qV(?2GlGtSe&cc)w^)f zNFM55JjV^u$yx`9u6r1J>AkHP)%2ssmEfvcV4bk2`}BaTR8Z`bDg{{BEg?SOP`1U# zhJmF=n9D+IJ>S}Cc}2Y#2FVrFp{djI@|pt+6kF0&TvdA+_Ofczi`I-PN!i+cJYia0 zlAi0{#}lbtmbShmtWUrthATlQDti)qp6D+gzE5K1tz^#_H4aC+vGW^_ZZY}BhDDBu zPGz2tbut`2y!^2UGe|kDI=aFC(~~P5)bK7X$bf;3E1p; z$|?;u0@Y)K5`43#>roUW zHjGAG%0$D2scIBWcTB;_8;gMK$@1FkB>mo&w%v@T2R!XCU9u;rdOHVW8ewaZ$?*k@ z=4vx8FUzy*lRZwoVkkORb7J7%7;OfO<-N1DP>)-WT)SP{(qe68a|oc15i?TmSUP3| zp=>EQoKUvR7K%k7%{E!f9;&syoH~c-U@R@i0c)%))W=l|q-J2%(2?WCBGoV+e#gZ- z>b-G1b+cF3pK+K|UCZNX?74U(^kQSofyA7uIv>x_tfD%+(#kGei8VzB@t!0o6F6+WpG9YhRm=~zm%TgIJ6UJhz-*3#U@O^%N$lqdNab>4~lRPu>yo7w=iq>$sAR#0Or|B ztpLJVnvi77elk-zJ+YUsRe(XKDj?j`bprsEuLzQZ<>A6ZD zgSbKq&F!l|bG>*JY+4ois&Bjl(_a&-0Mk$ImPT$BxOFqd+SMnci_y|sK2;&27jf*! zA6FGd^sEXadMK?b<+|&77n9Z}&&pL6fE)w3+`|-6DmQ1Twrw@4{i8b7j;lts?qn?6 z7pno)xU45E@QHm~wJirWJhXN+cTFxCeEXW#vW{D?R&)8F*soQGNm06Fb75}jjBXH? z8>!C85P)lX?i zse~qVGsMNUp#~U>=~K%M(Qa}JCFb&tqbBconW#zGK#l3Z+@Bkuxt8kImYN9FpEYUP z9}Q4zx&HdgGW_&yq9HA+Cp@*V762n_xk?8YeoB~ygRjn>SUj`usalvAA-!RHuCLD2 zf(RdV>TP_@eTJK|aB)y=G}5tdjJzeaft^&FV1w_~Mhm^v)6qin6rTiHIdj#{BsV^1 zj;^2)Q2?_EOG^jNQqwx%SzZUu`#1M^w4)9f%QXk%c}uIBV#;Zn+N4;cbEfJ=Yi7d~{^>M<6^sB>+Mx{vCCVR3EKJEQQxhWO+g$R7qWLgo8nCC268z2#X3R$R_7 zU56#UIYTv}KGh6S7XWm*z74SYlo+I|mOfCwg2^{$fZTP+pV$D5&$maMa{6godr-#b z^i{F;$jtQy6usDyplU{EGd`ImXU`isVgO2t!BHPQ= zm;zlJQ=ma(hE-doHbzITYYe{^TS9Bi?Pu01)u4I)22hl@=BKE3qny2Qu18_mF5SVfwHw~#6}r>VZ`YHvQ8 zZjWcQzPXEGus}zeyAp!un})XC1ZHmzY+ks?E%{tdtGA%wJXLMsN(y-D_u4*^smsZT zQogx!G_wVwd!z-k#eZ5b#AoSKAlZTXm2`HXTrGJ_R~36qQ))|BLcqU%Qq1Mqmb086 z&z&M!{$w3!NoDLpwFCvbP_1~IpvtWWlMU}t>S1brPHO~aSZhaa(_6dja4vD`3hwx$@4O>R&xZG)7iwL#zr7&M4IrQ8AXwql56wxO3kXoba^klRn$Z9vgiv2A(u z(b-m%e4#CpGP5l;_tM(7EQPPOg_My!*viUfyR`>6%C`f@e|y;GSnji`*p3!;Q`dF~ z(~&ZWR$^{ft+&K3`qUEL?ZFsPgRx$%JxZ%#4F*VVCndKBq@!k6v>}w+LFw(`W_xXE zPmx;&_-z6LpW9adBp74bs8|OIwAPmH47KzQjP%hRkmr_KVCgO7U(s}Lb5*GbtCMn@ z>2?SB(Nvy}G_Hv%wuMdcxm@M#NZ)Vo2u(|_5V|}ux1rwc2!;k)+r}!Yuf1)kpV^E*zI=Mmd%P9eC}g=wUBwY$*rvwouImw-s{95d(a7@u6J^Uan8k=ENaxQ z&E*B+RyXd9lG|F*wtI4`t666#s;2to9GM`-GL{q>RkWK7WpxJ2!Oo_;E8!au$|@=@ zg^bZD^ywVtQmsybJsVPtJ>~R#3KW#po)jR<=&!o;VO$rw%)bkL$PMy(^w{_=i2BHS z9uB(Y#xwH*iV-phLAz|A6&o0;7^23yI5s#*n@6D+^Cl`Jm3G?~1hWVkWwn%i9OqgI zd1)Fu&eT`lc+F2`M32Lj3sj6%^ZC}Bd1Dkki^j#};Y+I<`J=RPt|vAmF>hqSc&)*= zJdEws1*J;)=8e#tZZKrHHuKQ$-5}`ON|9j%lBJc)MkA{6c|#QVEENn^^=F}dkS-0T ztMUeB3^C5-4bYZn86!_mnwuhcf0PS@C9j`uk%5GVbf;J!Zi7K}LSApZKf%hg=}Njz zc4r)Re1XX}kDb@<6kz9-huglRnRelPwG$dXF|V8I_W)C>2K7LnbtPgfRCVEIzK07v zc_|t@#c6hD-ReQJJ1M9q`5l$qleZ3pCvctAIc>z`S#h*jFJ-BL>*G$F67+_Of?nQ-7lsc4# z#^*KGgau%V%_CyaEEZ3B4K=nmHL&2fM}5s4YExleJ*^tfG*!9}98a2HjHsiSK47Y? zo1+|vTKXOY+GY@I`yg30w4)C+CF`ugRoAZJNK@Uu44QQ#&=q-A)u1o=RWzV4HQ_*Y zveWiTYLE`X_`Hfb*_VP9besHu@&#)(C*Hx@dR#!vBY6CDlftqZKhbGR8O`s)bE;f&i)wz6W$V({LKH!_>p2y~9EswBmV;Ra_`a@OS{;tTtSXhVXIcq(o zP7X4l7|rYtA<^1kk0>4K551+;te~$5qCJ3S5Jf)Sp`w)b%%-6lz*ziwwx^_TUP z^Kcr%0(E_jBL>*tgUE2J^B{x{r#*u}=&x4>A&GuOlO?Yxms)LSs*kG81y_D=#SMY% zUij{S+SNm#cG?hnt%qJ1g2Z1O;tKGEf*aQuU5WY6>Jq6aai6JHI92aDjm__>4nslS zMK6wHoF(R`$U6r0a&;)<<+GtooH$?|N6SIA;ZDcQs>h>i6II3|L2pELnj=k3PqOko9oCBr+hPQ z91i}bIy#(co9K6YYn-vh7@prq$s=H~`C+w9KO7O!z*O8RCFD2IsVC&wOXNcOyEaBRAu#^XEj#R{CSArol%J3>7jpJ)1YU^7${vk#$^HGca8ynlrD^6%dIq{r@*4S`;)trJ2u~92wMWjFT;ovKbGO$ zax9DPg<~OP6u(&ic*lZ(<-rVNfkBj+34y`mfN0Mz-~3P&8wXoUXvIwX=$T)jsCX*A^- z9VFd1ZvnSj!89L+I(r>xc-<`@7_LqesI2A$CVlR8O@N5GYHA|#$ppHu`x;i7KN`fG zHMZ2vo2ADy;dOe%iTlWjosm{yROr&w_NG2-mY4%5dT~LU-)nKpX1-dznZ_x z?`OY5e)5~_*TFBbXkO8aML#I|e9_TGTNaHel2zoJBD;#LEHbP}<09dO?-u^5@YcfK z!u<=^EnK3|?Lx;3Z7DRjP>({@3b}lL_C4&o-gky?H{WW$Zl7O$KK0q)Gu@|alut#U z!p~fPrr69KSmfP)e01)7GC3@X_A8u&MG6Fl4<8n>+=xFFAE|!G%)x zE^Ms!2a!zgLOeu&>Cn3nYupT05wPMn1 zvTw04O`n3Xb}t75a{Uyl56y-9-i5VQHP;hY7`*K5Phso?Ohu5YhlO#=dMe%3D=aJm z;*twgK6}c^oHxJFm=NdlEc>l6?sj<>GJeCt5_Np4E10>==Qx2lybG%+pk!Erp{}fd zrXmKFboMvIp#L-qwwi``RM4Plq?gChxzosUde`2|>KqS6OovRLFLB}0cseCkD$@9c zyXWahe}YEx(EHPo%5~G(i{jq#bhg-SZYns!l>Aprq@rhF2IeZ#V`M}teg=5Q&Y;Y* zGbmG9<1FE$8E|Iv49s9$fX{H1$(V_vzh&>?@|g)hrhF!f;Bi+IM~tx;cx+pP$8ecI!3(0WQSDknpb|!T#ZeYabp>V2W#rFQSy8f9wBojdx!Aa*LN;GGzS6g^*TW``(7;6fY$G z@wN>;Z&}nB4PI|awccUB>5!M9*Zmz&B*N-V)TiVk=glI*;tD5tz1&D$1fn=qvq!8B zzhh&@8>6|4fQ!}}i{RDGMbPzA!+;21Z)x2!z(^HaOf7vE!z};JrX#$i)Ne64OiAQ0 zCB0(+|175DcZ(U79^EBd4VO@2RuLQD-V$oG1kmE#)+Oh?C3MlD2rfx@y&*VY02c@H ze_?1xE(M9tQYOqmMK7g906`QSGTj=z6gZb&SV|B26F~v+?4>k4bSo1=+%lS8XRD{Q zwX}%xV#2I#xC38Cp+cI-L;IIO(B@@O=%Y`Tf&3X=Uq+kDFLwp{(oa5}QLQP!UtIfTsCT8~w=kZ?vTKsi&@S5V^&eX`sE zo3882v6;LJr)l#F;HN4e$9bQkYUo)qCKHC%6A#%7CnTCsa0_LhhIH#dLf~^99AwI zuDh$iJ4_9JbBYhuVALuQLo|3b(ml9fBH;|a&IN^=&Kx9fA*YoCb#67Z4A55v?`$(~ zc8c~>)91+OtALD1L)Ays`C+ZIq3$!ST;irn~yBrZ1m+ z9#WrM?U33{Yo3R~RGlD)0$p|6Kw@72$M%fK@Br_^lz%5hZRr~jValwt8eMc)+ew2j zIt}ZnwJ#uo{Qq|bCNY85@FczP;Uk5(0 zfx3vphGZhrPd+dL7jYPJnGv{%kd15MO^26gSC8e!n?*Q|Kynzsi~KbCB}x_5+P91e zi`bTXDbk8_cf>LZDgP}8ov+Hjj3MWvl$VY7i=NRW-u3azU~TuAG1NO>gFiD^Z@R7+ z>^$Ya42rq>>NAIa?;MRefaJt^y|b0}3Qe3v*i=Zn@(M_fy@K60Lsu=K{Hx4donK}9 zqtmM}uEwj(FjLj#Rr+&^Vn4KIc_(Ybt6-m`PhVwt`DMU~FF$tZn4oJPJ9MO}at3sa zSCr zT0n+Qy+*62z7-Ls+g9r0Ys}nzb=R^Qu7i$*b=c;E*CAGI)y`TYcoTT*>GCGX z#}Nk)|2hTjOJ+G-%*L>{w%Wc~t>Nrr9K(bzMvM#+2f2wC}W+`SD z2kt4Jta zS0SIExdoKq2m=4VN`1blCm_zd$l`k;mmq(&L}}kevo&vLq|K#^W+`P0WX#mM$Bdd- z@1hx6w*`5gu7g`3d>S!!d7G-_KOJ?vXo~VfF=Z(^SzZ2v7_Ivc-BNs2pz&tWL@u3E zYJ!f~BTYAVI^%e}f_G6J*vF~Lo8TL(u5ZE}z9;&I@onr)lfP17kqr4!I%GK`b;ID; z%G>2=is5>lA4+?R$?@5@7^#H!dJ79}NI|=}k&j{94B0Ar0Vun(#J6_tpDnSYZF~wlVf?jM%)lsq>e&ozap1 zHnjEB`rQsuJ#?5KTJ;VbnD!2u0 z!bN8W+RCleQg|+Rao*dCd}=Ghv!iyC70}@+(Og&3-B3nX#5N?tcN=uHQ}i|pkF!tqJGISxi-o0kQFFy@r?t(r_7g_O zYRj3io!Xml-50+8>y6bpuKX?rFX1_Uc9eHR;!B}~n!XFx3giUTFCdijCpc-J5(Iba zY1F&O6bE!26}hMm*M51gt@NF6HhKp`e8)~_KB=j=9Z*q2R|~k4tYW*6GZ%S0x zaRE1;~UMQf~-EOL_=WX;@*Vk zC99WGw?!JBo?P~&Nj6&%!;*M&1jSni`#T|4l zBrJj3qoC^d#MJTPcG~hGn&z($8QK>$=b1>_8r`AqkeH&y|-Q8l;RISVQEEU{~2E*H31V}9~eac z4ZvPJK!c7RfWhIqVz7jxIS8d;DsK;ux*UYybqA@X&wG&`9XyEjFu$^y8jFkT(}R#s zeB}2c*+xA?&OepIShXxBNbDhUf>fo7BU6D&KLoY_9emFbRkz-#5@yolBBCyU{<>Z8 z?x!Y)sc+?By1i9Zb|iNlMy|&33*f?B@CHjExpqccVP93>8JVbdM*z-xnd5yEjzB`+ zBd(IZi-@vx7Jj0c)ck`2wZnOxBlP6Fy*G~V$s4VF`%~K6R(@YPQ_B)u21kcssxHA= zi8ecK3HC}%SX@AYcZvDGvaLd04=%;>^e99XebWZQlIDtk6OCN^GdSA)P5PnlXY|9Y zH?4D*G|`K1dg6PMf^O%1Vzp{#-a`HaRl_#DAm`W-ga zfX{(w^EsV^KjF`j+8v+M)R#WT20Z^cv)o6YGq~{k|2d^1kCBj1f|?#t10<-BK&q;bJ z{{+gV(Mc%jZE1roEj^p@uvE;Ia+7i}L*`@@R1nNe%?M*H*|ElJ;s~(f*K+O@7PLf@mTF7 z52G>b4g(CGI$D2y>U7@XQHnZ83rFg^Wd#W%ROw4+IvK7P&r#Wxb9Bw}FCBzKxi#)d z%y{1)C(P$vclhKoD4ZFm$pt`e9zhi+dY4ww-)~s?rIj`20!^)?H9WY83(ZF^xJqYy z%_8FG3yg{K^7$Hoaw_*V6qHqpy_Hd^=&&Rm{u;)0jt&dcFZS!)*RT*{E829}(s=FR zhkAa4fP{W$Y*-qrzTZ$fMhm}z38%iHvQc{w?A!M1{+p4A;nLE&YcP=t{~r$&+7>p$ z6TC}H6(|IPLU9D|XjaK^ZT}yo9=zmiqAe|{3!6;-mvX*#ld*a!_TcL_R59Pe z*b*wsfFq~4Iu-mVrZtukBK>4NuoMrH%N#*l8l>EBxe{P|wTxbTApTt;ILdb^A8@{d zDz}Eb#=SG|Qj3P<OZ~N-Jmr0dD*F99&W4x!o?o+1FjhK#4=XmFFd<)bTJ<`pV*E#T1_<_>d?|Z^*Sj^Yix143ol60m1K=BPf zz=9JiVBz5(=-ur<&;jgs{XnB;tIA4i)RI|B<%j8+nW}b?oEeJ#4+-F#uGtr<3iqj& zK2=}sVXkvug39|Bv56-u=o0CZ)abwHp*fe3*>V4Mv=19zmmoDwJISGr@i?&pa-42k z@>s5%nFuTyqxzRg9<70wA$I#^h#gzPrlut$^)5-Qf6g1ga9t>Ygf_lH4M|rRxkJ_L z3ME!up@gy=>tV@Yt-b>6AnxRn_2deSYvfqjOK=rN5;ub1$aSdcr?yvt?5putN$#T^ z;m$PGTj#8P@>op#d+$=yBITxawu6dCzKs<#f~Y|8WqeYTq@qW&SnD z`Ry8<>5_3BzNP2@a-*@=k^R>{awf1&y6|?S?S?GrsLLNY+NpzlK6bFQ-+S%4%g+bh zyU#4ZYBw+#OW&Z!FdFV+!ld5-&uB|1p@lbS7P7w8`J z3lqe~Um&cH%O=RB>6+wX`2Y3`_z6X5GCx-bN#e&Gh5QPcv*qV@-e;+bn{{NOcj-*F zi%~N(@JV7O%hKsO^D8ZxrhP|DV=tYmYe$^j%B4h3`OQS+H(GKuDmYv_e?u#;`wjL@ z)E>*q`Hk+XSt;DMYnG-dmo&Dqetd)SvEHTQ)c$w0`isBQj9I_K%Q0H}J6h?|@02QD zi~ChMmi5c;h~vnNKOlDm5nZh#mk!r8e%N3irb(7FRH<9cv|c(ypZviRigUkzP}v}E zLo;wX+yqbZP4Em*=bL;ba)JxlVRydq;G>}kEB2-RwC*OD`sy$c$ZY%rI=b>L_!)kS zCiPOaTM#$<7TTcBBXr3o%j);Yb|RN{*BiGe^sLrDa@1HiuKhSaQWg9swm?^QH^ALR z6(2kFr>M(gXESkWXRUqUVdrJ3UEj5?x63~|y2-_-#=q#e-yfJ%FYTcG2L%P%EBP-_ zwNucWD56B~(zcrO7ai6{TmFKC);eyFR=Q21>feUiV}FJgof({`NOKLoP43Ry zu%+S=M;kWPE|OTYj6dScN{y9s8$6A)|A;dcE^Vmb07q0BX#5=r;9lV!0P1N$fLWeP z>k^%p5m_hWZ&GWk5i2rMYiV$hlTG-x8;@C@Cf&|4C0J`+{~8$xE^2} zJoyJ4bBN7LJ+n2_$1p6LrHwv@bJf#1k=?Q$TQ)+C9>CDyx61c2E;NJ*N>3X4Ub^Kr$xey1w9BM=O~Wu+8Tx4b3dlv z|0v?9qiza%45n0_Ebe?iUe;B89@9iT);)%n6g4UA6z#0jyemADqIHUz6}_yZx)ycv zI;cq|u?&l65j0(&k<;X5?gFXCPspk8x06#xO`ecbTkfwJ-n%WQ!PhLrzI#GNU4c>V6Bs_@Z<~geC1>QA zIOU+>zCC20#Ftf53Q4R-rsqII6>Z3Y?8-Wl1J5e4G&G&L3tsMQTJ_hXKHDKTs}ypeca~tqq&c}Eb=(o-umkWAGh6>IP;0Mb$MR}UNvf$ z_sQ^emsKZUH(xq@-L});+1Fhrs3!*6)615G{Y-re*LTZ%NMy0&f5;b9&no^pO1fep zcd$wnqGT#Dcim+IyIQ*ou4yLY-`CH~=H*>9yAZ^raEq3ropo}nHG6p{d}UZ$mUmR~ z!tOHaU)aqTvW+%smbcdcOWIZ#%D&xbQm~vOx*Hv$+vps5Xw62OFvt?U%Uh|+AqQhi zH80{$(sM;9wd9aV!*ZPB7UVV4@k5L@z?*WVBg}SbmN$`4Q7|=DIeRox=b~_9eNlHY zeR7=H;z&_Ck%)Kvj+L2cQbkb-`R&1NS-W+vSyX)t@>-qMUxM zpzrXl}xyQ35y;4YRC;0|YzTq*znmiz$}T@^r^ zCkD`h2(2c8OIdpYpe$Uo)8@5E8g@xH$4srZ|8t)V#R6oYoX~7g1Vq zcLMw9FBYfjrrJw7^YnGzRJjDwS-b@BjZ~!s33E!op$_@zhD7g*2Ksw%B%U2g(3BNh znJAOIE9&V~3Ca`AJ>TjJB`Yb^Z3hXPhgyB1Aeva!ecFTiAr0->&UMviB4?IYH1s&bXJ@7$caH9P_Q>81) zssAqPofT!ZGK|t?v^xx3N&3zniORLa1QkPuHNGT_X4%#HY zB1Q*E;$TL4Nymy^5hcHHkd)Ss&XKMakt%u!G@HVqXK}dOV)gQ;H3h198Fx~E6Pk%F zWQ(J{_I7dGTv_SXYO+|^zF&sU$t?q(-4(;4tTlcLp`B`57Gb_vk!9(GvM8f&Wf}d2 zHMy(}SxZ<^Aof;D`u%uc@k#AQ7W0C8TK|^@0Tseo~EOg zFjZGU4Vo!B{MZ?qll5!Ck4frVffjD7fY_#a&5&3zLE9^!JJWQ592T;f_BKv&6@i;j zk@0$ak8fT`q4YURm|m3;or2p4cNvaga95$=##hL&F#C$MqLVHH zN-&RV^g;)n+KY)B?_JSe3-X*Du@&t!(X!fVL8h}KwxW&pSEEB)6EM~tY{!NU)xy9^ z^sXwVyatH>fMjZIlkAQ_W(OxjIdO&?@~z-(GTb^a5c}zoLHuODqH7>;g$Fs}xr&Ls z2Bi3FQzN7)&b!J_X*H;cLqj#(Wn4uVE_^$!gXhFY&`y3~U9tQ^88w-HeRZKOwT!Mw zH~%*oPu$Pdq&H{R#9hQn{0!7|C%T`;uH`JJ?k>bJy?150exR)4YQe*q&CNnu$RzHN!m*p_F;a6H(;NTQ3vE5>p)2DMsQ|g9oo^CUwr9V z`SeJUIm)#!0PFA_wsI_CVnHxQhbV|BAMWHZZRIFksE5L%ijk^P7l;wM*aTbewYnhm z)V8@ms)qc3Or3XNRYmjnO@NepQwSs>jTCx^P(m-E_uhNxJ%rwQ zu0EoWLINS*P?K0e1jGW01yE73fLM_#RuBZSU_s#h%(>zDy?>o^c4ud2XJ==3=j_ht zXfs$>rv(rdS|C5;RKEo!#}Yx-A#RKo@vS2*XwEY&C^$+-ThJvVkth3|-MC<5Pz*h? zc7%dkf)Ky#Eh*0iqm(G3JU4ML;h3Eq*WglR!ts<#cCs952kDBH8K{s}vC*2UTZt+wW}o)^3i_Kpc%-Diac;U2Wjd zhBk1hgZ8w6toAz91{Cd7--{AoC~f&}qtvzxx7OZPnlsO|Kz2v8vXwFoprxL(M+@b& za@6J8=K7~C__!j~jxAX;8>hIuv^fvobA@=HTH91J$g)*mJ4!ZIhc4b;PF6iH(d^x- zdU?}OAM|lrh@5+0>T6DWO4Y+_gp*NMTRS-|t)nBn6yU5zfgN1GqK@0QGl+GIG}-&I zP?_y)%3HTU>8U7{S5s|0pJKLwb@SxY(SgQMU`NBZZmxRsLI(QLq=84IwEF}qjR09zio<*@O5K!-jZr}p&@H& zi28Jaf@WQyV5ItY0q+Pc>H@mq+HPONbfde&fuZ`zzK5uMSEw7Tv>wc+tGa@Da#t4Q z1Lf(;82+#;WB9+_oT~b(2)R^5H&;bf>SjjYb$!*Kn?rLSweN=3C^ai`G6|KRT!kR? zo^`#nmMqlq-fpg{fjy80$MC2|Uk1kcuIsKnR18=*#dim+tN!ZYw7Ls7!=0DT%I=Od zb<%$Fb-Ozat=iJ*u~Y&#dl}O~TRJ+eYOfwWXjMBMr7v}`2h9m=?@*7M_8#DGt&8?( zr4a~|`t(F)ujv!P7H?e(_3ufGxAvsPRT`tU4)>&Vx5iFY%?R}Ekl9rG8are)QE)G6 zYOMZEO&P39*05fzb&7hq{N?GzDx{%`dqHsbanuvk8>)Zp#R{mN%J-&zE=+WWbo725 zjp|MFYHKy=&OJZ-eQa?~lSfyG_FY#~$E`pOZnc3Zr4Q2-*RXD2MjYJ-<^AqBJ8G~F z_d(;FwZ=M*26k{LP13GD5SXZw_DIk@FFWHE)0b~z5A+3XoYH$agLYl4*7b!Bd;s-j z0*clt%Z}3dCJtXKsd7KQBUPLEQCa=aoeTRRW8uo}=c?hV=)JaTH%pHW4Yjr6I`%Kk z7>rK9=Kii9P{Tj>2k}^yA3!x@bbBD$ZgBYQ?Ga^{g zXAalDgPfOPiW%;_3{~6V5S`%39HRaMK{{A3&yL`nS|%6uW?OG$;?#1a^D;o^2h!aB zN*ElGVD@^vnvc6hwnsK$)dMnO~JCJv)@a zkT(?3O(CW%6I(NCG|deWmr^+_N|C1eYba9Qei$q9ZX=wPOD5`jn5$|~=|v)Q5RVVx zRzcCenT@oL97e+4VKlgbPL1+XMd;cw5sCC7`-lT$%xaujR~?1}T1RUKqGO&J&d}R9 z909APy`%@$^pb+3no9#K+1Z248VZ~OHr}dpFPDz2rqmJ0LRC!~!K##F>-I>}i}pyw zIftu;+qvF~6Wzv5n(9BzV{BuP8LzY?8_=1R)psP*mASL>E-SHt>gF5%*ziZv+U+B0 z_vMk$_0dRItjdpqS-*~iS@^RWMHQ9Q(jJjY8-+gJGm54SsNyt@u!gL@(BGLAH9Fab zQ)UIOqdQ#}rlip*XI7hiBdQrlsOFNO*GE&)8CL$oHyGuAB2pBlJDBHDuq>L6*iV~W%N;7r_H_^&9`=r zMdwv*$4&_f9*|FO@5HoP9~<;4-Ll6@yi&Mo1g>DH+x5|Ax}ZeUo69w09NEj1OSWt2 z{p?0ctsG6yuEUAjI7sFnQotYjv*Y2vhUj@bZW_4C!8U;G( z^)wpZQLj&BuvhhDrE2SB<6c$=HJX5|wAV8O$Vu{KwNosTrNa|w^ivZY`_$nnh&@@( zZCA|MP4W8pXA;9NtCjjqbLeQPMiZf^?q|o0MtO#*Y!zYsHYi2orO+T zU7eZX6seDL5LR-%qiVS5ld6~X;u3X&DC@>4-pS@*oi<1}I_ z06Pre;i>4c7#tlqb3t!3v9Tpe^`<&>@DFPmMI+UaN8o+enk_l~ni#FZX^7+7%_1Z8 zs=Ylq4OA6$*b0OxVVFa2dHGL=Q^cm8PI8C_*jKQg8{y>QyurQ+rE9qaenF{Q69Sbz z4875J1{59~=4hWRJXy_v20z%x#MwMqdG*6gU1yae?6ZTdtlpU6suoxVjyO}R#&4+{ zg+|TtMX6Yd_Dx1+d{k#9ee{6(&2%OCX0F!kS=4o4CQT@wNfTD;&`hXVp$i7KT(71h zH9ck_a@9sN&SuX7aOf=fx5Ed3ca~Vdq%=Th9Fjf!Ds_C&jL+FOw?;O zL%r4zHhJl@8HUZL&@OT_&}xo!XU$;S1}biFu$gJ_B0xPA)VehmJSi)4_-=lMfhO1 zeffrIw``np-k`0Cp6mwt_hZ`6TYXK1mQZ#L+z^?g*R=PzPMP4z zPEzcAAQIJXJ{S{lQy7t;o%1oRzW2DP&Fsp=1Gi05c3deLEWehxVtlg+W&4EFmKgPa z!g?V)TB!>V&M19&hThw=0FM8A#!doeN9wr+P#U4QWhQvp;atdc%5orSAsH34ZkdB3 zO#7C>!#xWryJ;aj2<3_^I0;;AaKYSbhfEx_FQT2(7ayC-^X*6E8EArbpv<4sVF;jik>iZek&-M@ZceK?i)m{Se zE7fNStDY7ABg^wS7nxsPLQ{_~;HC^}gs8YnXx~y@T0*Db=}9$1xq8wsoqPB z)Sp*Sw$Et$#gH{dzgU^k_@H#=w^3@l5(-A%H=r>q6jTakW*nhRuTIDsuDyWhua!`J zZn#Nb)=>Su5-dZMu!@{%tB{rNM>{!#baymEr-~Gl z_BeQPwHec5)PAXLSv+hO=6^=mpV1z;l(!UHa*`*flE!*iV@84m-PF_qzCO+zNh(t%XYs9|GCZhtM27uGl!r3DB~KsD@<|IaudDSZiC1oN~Ip*4U6! zR>A)TcNr!BmzsPva-Eax!!1q+@BwWj-#2@;jvCx5U0vsl{gn!Q7`!Xg@L_6P@-XCo z`=<4F_A=dh)2qmq5~DdHiE;LSfuaBNk}KAgz1YhXHX}#($2((sk=$!Qw@}GztO09i z*bDD*Y+=h91mM4GkjZ)4u?7M%IO80_QN`@JjAz@wuz2^RRIm}6oldk{K<20+kHFao zfdSxMwqJ~ON%kx)eFP>D@xZ`lsO}`EDbw`>$!hQ@ZHRmnZcbIhM?o;fJ2P;k>E=U( zV<@!zAul`HX_7KtHa=xf)Db`#4u@WLaHZ)28S1;11~gv_+2c5^h>|O`gki5Zx_FGz zUvYp(6Y&;$MiCdx`5vir-j@-&vzeYolMxhsUqqE4h#%%{FL9cZ|EORyXf|%O^I&wm zCz~TF8zbT^4fl!bm?H*x8SJ<|J-X8s$t;;Yury6a+-|1xObo6gGO>2{S4JjOaGGkq zqgDH=|9pp>KKeQnUDMmk1{TE0HEf2=?xoBJz0~zo?<{()hfZZ7jt8@7qpsWJn%zyW zT25D8%7Q&zv}L}-uFg8_#obALv&rwMzy(fSxb0d1-!5ds<9D)IWVF|%Y)ZD%768;U z2Z=6sgV}ga4tixo4!y*+kE4#7%x3sP9 z+vqqum76n7bsvYZ6rHL&6b&kM+Jze|Jn9@BNHAqj&Sdr4L{lbd?k4zhXcOfpY;cfI z(5se{rmrohP60Us3!R*Cs#`$LSoJSppE0IXpmDAh_98l(`bKMO0i^y|0I5TFI%P&` z?oJcSoDm8Uc_T&Mac|x*;bqifM0?0#V%RB|K3E@$N(Sks0jqq1$MA z=giPZ-<+n}JjszZ;@&wbGN-YMx4EhXBzsjsGZn|Uo%V3pa63zy`rA#yw}Y&K8f}OB z^%Z-?slFcJnH-Ais%SerBB}!43fzHI#GGdD08?tIAMysRHPvv3t7ySVZh&)B zE~mNzcTwo@4r*z$DfxwL`lo~u+wyrc8LywH{?9XryF5n6KIBbG(-!&~b-sSQW|>BQT6Z6V%u%}h1#Fn{I2{%JrHzjD zBQ*PQ$QrKLr;W?&hbi@GW5N2NI{!FrsPzPV*3-7`SU*^`pP+Sv)XyFRb@fq@z5WE| z+=#Uim93Heb>s=K_0wH1lD^7%(-v&&`>@bPORRVj7M@+{VC$uoPcrCwa(0KNQMiYW z1H&M=Zt2|=w-iAqy{lS0MS2&Fd5S@Ajt%HHi(UN7glH7W`cB$u`5pBU`GMwf$jO(7 zN#DwMP}I}pw^!SzS*4k)A#ZuJ^X+m)a}k#&ZhV^lYok3t2LA6yjxw^#M{y08ZuHs7 zh{qf0PE&+CX~oJzY%jCzZGmMG@NFmTI6xZcabshUd2ew z+6B6yRLm}L?k*O1rLoc*Ge4G;1lp;(^$qmOE_hI1Uju+qr0)c$PwJ}QYDXonuS3vY zhq1Nw-aGWd8_&?Cf4}2&X-yq{hEg?D{}ZQFb-8zgteP_Sco|w%dCR?Ms%Yg04w@vD z?1sv#yP+~G(?OGRrjz{iByL@5EY@cEO6}E!$2(D!*J(v73o10yi2X*md!9W`25CJ zuJT?$0`>w@o`|~;GGi~ec5mRfL-t-M=(^k1QR{=1x0m{Y^yqGB#fc*j2;5 z-(7S@*5KUEx~GVwP)}|r8sT7RK(q?o%qeG6ac)O-FLV%K8+-u-9dzUcR;KOm11q^f z0L!gh&hoxU``W7hi?pMSE~Po8T5Iu(lxoE(BXV2nh~>7>*fmaWbGcsPJ4KCNB9~v) z-m02v$xC$Dk(cPOr(Z%)nDYU^{{24+3ElGs|J3UopeMr*0Mbwm4uGS9)^B!rQvZKE zN&K|389Q?8Y3l(VYHF?JY(B`)eC4u6U=hkUxB8FUqM||QpqbcCQ=_? za|%T0s(pv6{2>@xQ7MPe+7&e75Q$-0bqMa2FD0AnUMWiJ5)cs#RiXb&RM-zuc4{m) zL_YzJi6rDza9|jDl`nU}Hm;$1a$TiefE&3}j&(3MP}>b4fGfPz<*z&dO<*ljwauxy zYv3c;=@(Al`>NHW4(UD`_o$QdfG)k}N_4Nc2#&@({)1;s=5K$zXZ`g@D>VCcl(o68FwjOSiDf;&z+9%D^9=3!r8)-$wvQ8wnGCzXK|eRf z?8Oqd*Bc;MsPs2jl`LQ$1Oa~oQReGim3-IF*Fo}$_KWa+Zv`@lo(|!2m2{YL>FRPA zWjKd>6=27`@?&5>a~MUgpMbVVPLM}$!nteZ=z)vzlj)J zecOaKFIh|81R)prju{j48tSNhH<0Tc`XSMiS6{BTpu3(LyhVClWn6UN>S*y>5LTPm zzU0=@QOm8Vdq9Yx4rt`aOyex%xf&+Fv7&J0<bMDUUOA%dIw;EO z#(SVBLy%o(>zC)NSk}2(eVkc&>T&*C?KfQh(ZG zg(|-fFQ&dvk!2^j!jkzul+1shHUCoX=K`@r7fw26-Q2|m`;C&^MVL7pjlNJrye|v1 zoEICh^SP$W0CysgGEp%THOK7in8kB5bcj5p_reD>xz2~CK&~~E`fTlI@56OOkMgMR{!`RB%b;ZR!`^VE)1H+&0X+}`iO3<@P)0zayd7|qAoHXD-V@0F(#LE&pF2kTEoZb^c@^F$jk^|6mD5hScB+UWY}Z&(Y)LTzcG^96gu0)E zk;66TB+G+gr7&i0#Dh$*{ol+Ts-F8DmJZQem|XB&1x~em?E0Nwns+~@u0%Csy;8=r zAwfM(fh%6=rx*>donm3p^>=^7W&_K2OA7o1LVJE>%-j&eO%#Bm)#wv&aQ);Vlba1h zIsODeh*Sy5y7mb;R{qySZ$r3#ww#K3?Z1rtv7f^6ZlA(&9L9YLtM_~g=!G2)XsGsn z3TTKb7r~x{&j9uR4C`z6&wyE4+4eSKB|QMLzoID|#}?v*7_Xxat(o zTdmM9kgio~#%hgWvQi_z0RIYkzM$Z8jauv^FXN6OHl(Vay!$^dn<(sMS1ic#mMG>+ zU^z+jCDpI{5>7t!vUBk_kF!LUwLs5(NhR~ud#f`9=P6^WckE?oJ&PDkK5g3alrxai zHSILS&QaQVN8!%aBj*9Ra~ixao{xxy3wbjOzJkaZ8h_Rqah*>gGg_C|@()Z*|(%&RoORhlt!PW{UhZelj9mY z&qC&Kov_4VO7?2Yp^7@k_Ym&-k~>(Q*JW8xcCR!6*swxdzk$Ka)%H_oyf4$`Z=iaq zg1;qsiS~Ju7i*+_6D8_fN-xxi0}k{8tv+BKyJ5bb@}|twhX*36m-lSQKpsl}0@&~T zywm_2R&y0|&?%6v)PoL+IhyKynXPQHC^_r@FUj)veIi$Fn5kOdQ}Yb<{T}kBYx_&a z>kZR%##?%7!OP4<<$k~v@Wt?8yCb?`vI2jg$RsuVfhzzLG1-;=VZf9A&6ja!wEYLT z_{a}PN}5UxbiCfR2ZxC$5o9)j|NWD&e^wg#Bc0ggM>>%Zj6VX&-S91R;`=|s-o;yN zy}V(B@<4X~ILh9ChDOMOcQwo2p}GBHDVDk@Dv*M}M|g`DY@M%A+yOXi$0tgFj}e z_3bjlhPJwVm8P{(&^21pntQ-}wbGg&9jaR5!Iq|0^=#m;@-^sduJbU}s7c{6Fw}6p z0Z@Zz%Ee$Hns5ymdq87v)043%_8%J^qmO=u+yg(;#f|ha0PK}go#}Q%1I1nEyFR`& zC|*y~>`_;q9W>;N>ojD+L!lA+=Q^Y6o9hgmTDp538f&W7=T4jPUBN1Wrc~GL8)Q^d z-VF$=s-0jkN~;{aaKly6ho6Ew?>MAxoT*WFz&`dS`nc;&a86hJw-E`P$l5r~Yum%3 zrjkwk(fr^hKeNhTiip*Xn+)PFZ?ZnZ==+`3xDm7OcSgfTmKArLJ@m#2TKc`ipp9vI z?k;aho{i(R_g7jtPOpB4dQ0?d9IHQnh0-yK{f+d|>hK$LZ1!)+^s4RX{1<+6g%f(0 zt>yXOX!Y^!Y;vl3Hu4kXH-6m>Q_fyQz0dEAu-6`p2-p1IDLC$TjyMn2Uk^IEeB&T( z{T*F&#emj*ViviL1DN&gF3HCJI{pcqsp{F-Pc8od>XAP{F!v8eQy-mt!-46o=g2_; zpIz>Jb5;BgXzY0l9yD8F<7Q)b^;_XIzMC>`0ozsE_|~_#I5&FY7RWm5rxi}&P6}lW z6Xe-wN0XDCgIOA|kEsa~QZ@2V3U`p_Pdcr=p8gY#w9|+7)mHJ#X=&@fXhe;_z}T8Q z!2shR2%`{PyRjw4IEMzJYFkcotZ&YDif-^?6*N=zziH##zoC5i-)QwF+zO_S#wsA4 zJ7}-}%}%(HQRdt-aNOL$#@*&J$DZ4C_lDaDBxfCN zbCS*MyIwEGO_ll~ztt(l$xpIaA13`vGq?xzp~K_^C7v?vvoT)Xyf2kC=Tt=1V9&-l zBd^pKva=+BxLCb<$~zeF6MhGL(Q+@O`*z%6#I;>$s$(Pj`#V$-sdo$jUz~TKvDIA| z`RgsT_Sm}&>8^KK`mMQ3q4c}-P?!?eI~`D-E5sBc`p$Z1s9@N$?_ed~L%#);wu}G4 zgaB+>0e7wU5Syjz$NhcWc%AWa+jZWCf0<=0 zzrUg490)5OP7T&_7T)>&w8Y148hMA0yPDg)cp3-`C*{5BZzpx~du#Z=48|&+{9bbV z0^3u`zV2#T=IeIrpSqDu==t5XoFsH|v9G%-^1U_$5(3J&X}_;K8u<eLz|cWOJcz^#^>01N|6EsD-hL}XJNSiB)@{Equqrtx z85*^9$NJ{C*6_06Zl&dAp^e*gWuc&jj@egpT`lXb5u8#wM>NI<6~FbKa(p%AH&e@U zz%?}Id_eaWN(S&rnr>nUfRvtQMOCTZ=}BssG$=4+|_~`7!b@fQ(_DJ zsya6v^6P6RnP}%+KX+9}-fbCbGb%9{9t^9bJAQ6|UGRhE+Vb&tS66R;H+Q!EX<|+F zv4lc@cc>nJ(~s>&KCTl;Ldp-@qpH65ch_Jy9~9uO9&9($sl0I`{sJ(Vj^dgzKT*R2 zfJo5l0C&}(c>2@GYut=IX361Tvk~T3*1P1Xe4sl(zXrJDG3je?Ga6=5?B}| zk9}3bWhKpt)Q5ZpN5FjWIc#YzpL%{~UCj?yB^NLi)y5tbl;(0*b%%MU2dCW@;FY$N z*G>b#Q{Q(s5c64BeDAyjtFoKAf^_#=8<_cSHMFUrnkV0-T(`R>BHrMVGi&4r=sci7 z{t!|+LnrG$en={G_^DP9_{*t}J<96zw>H4?%c$L5XMW4~)!`uO@loox&WO%`K<;37 z^^lEreCK{wHd01gm!s5HX?QTaT&bjc&PZLMZr+#Wntjh1tIPBYKpbOsFDR#gEV0IJ!Nr!p>`zH9p^Kf3(E{BRw1kWB5lsz)LQXj^h_(SEZF@r92J~$N7~rk)KZ84 zv^Dc4?xFz2fVfsY5}s^I(U~xsMzpC4Br^tTM8fz@O$Y}J9gKn+kxbj0lJ&7Sqmd4i zp}>kr<~v1bp#~KZ+VG0*SPikXb`{-~koln%!B$r*DuRT678Tu918aK;Ysq5f@mRY? zw5gV^l7X;?hP#vaZ;>31=Be(LtQK64ljkbu{5KI+C7eNmq77$ETn^pFU5bytE{$T_H`uu}o3qfPPJTszWK)~3q3Qz^1aNP=fmoL3$RdWbpox?iN* zvnke_)QlL#h5nTk7)cdt{^dVUgGl%t9_g;^E_LaNsI}D1NQP)75ko9d+YI($ONdZ$ zq`O)`cquNWzGn-~O%?TzFC@@hyvS9exnXKliRP3i>}zBKw%ko-%eAot**?Q7*bm7~ zA=*-jb_MG&4@dQT0ocUuZ&NBvnp#pN&6<`~+& zM6bm_iC-*yyVfw$x-ox|E|dp9iglst#UeQi6jw9SE+yp8SFbRKefjgaI1SnimHg`r zjr_SPZ;Mla(iIp-)*RK3LxN^|`N^$;=JHGkk7S>cKkI%Pj-c369*T39SGQOW;$DnH ze5b`m;`J%N^fah*-Qehxfl)#ErN=>?6owLOxcsU5Al8ON{uKQZ8)-*p@+T{!GA*5? z_x+gd&Q=EZyOkLR6LhgM3NX#fU5?Z=<2ZB$1Sg*Pu<9SS1I{0(c7J#qF;=getb%Wh zPB(xZkUd(j#?!D-x)=}ZM(TVN6?9La_~-tSNLT)F-Sqc@4pT+~phJ}!Ndj1g=uiSw zajqx9{V(&zxkP5bs$RvDOpAy~op;%p*$b*@ZbR$nf+Y1xg8dv~weKpP0vvQj@_(cN zSFMq@WhtmEpW2STDTotyJn|e)^baTQgIdNsifO~u=V0NJIfhA zTO$-iD1=~K{PU>mqBTpaqBZ_|+t$Yg6}02FtxyWW?(0X>VaYF5h}PAr^i!GC7()=M zpA7-GGC{z1u!7vyB?bKSaGO>ua1&}62$xoPGYH*Y(}4(J9SYI@TF19h>!&u=fh@-v zQKWKrbvF}Db(Go1_VyBQcH`6_d^9S^sqF!+4sulIYDOEXaBU3)KfQ*V`$09BNb_pA zD>DT4k;QKgubSs_U+ao-zMGcmACi5R7NCo%eA5z*s|yPrtx1Q@tBE>aq^z2BG$)~J zMq--Xv;eVXo-m)8MEuV2XY$-MUw_wxv4lgdMN2YNnI)DXo2zNHK%TB_d(6R?gG1$P zyg4{3e3tIiq8ul9YLh=hU2D_e+}dz|S#5VDX0$xgb*45Q^;T_nCEcq{yS}fDW}944 zhnyaD`2O`*=b-AQiRwuj5}wW@sMI$%|K_m`-yF`BpR;w`VS1+ygJ7I4)S;qUb-_C` zjuF?ZF0E}+7rdj@w=PIkW*5zNF?c1h7+FXx`Y@m*iE_Z#z<(GPNUw;MFCmpj{q<1Fht6-EPvb+i7nSW$e zy;C3j?y@+Y`nf(${G>h|*i*mMhw3&B7|ZXKjbs6~sk^=|8_5BxP2IdRR5EdGd{ohN zJnP&B5Yt6_8_*@4Rj-^gST=Q1;w@XpZ0e|_hM=3(5d1Ccc-3zQ%_fcg+ZCX7wjo?u ze9QS?w5jdE3k}^E({OfM2TWBw3RLA}fCJ#EGy3GO_%hbN@>6ayb>o}D`(0LN?Ym4t zV_NO2mcJXjAav~S&gM=J;5y4_Dp;+b>mWH*Jq4@SxjLBzEA?!ocXY2%a1$sV(F8u0 z4UNRrXA`(oFVq>qOXX<-c4AY9dNC~4xL{j16fDx3U}pp_R7_I{UZ4(5S+`_0Wn@gQ z7ipnR3g#)Btl$jq%FS6?bDhYf=5|wrWR%OPBVBh5!5p2v*m9YMhuJyY3f_-K91 zizSUxtIG6jyB5e$%@)Y}2*t-ch=vn@82p$eT0rek<;ElC{~Fx)1~<5%B|PiX(#Avk4RvjcD14d&{eO8ISR6iI<&S9YfW#rt6+j(&`H^?!P-$PDnRBxt?8p) z4HzwnZK&G64P&f5J_ww~w^MNi=cTRE+rZRU+5kMiY@(rQtwU{SbSqtK!=|HV+yBdH zp;~RpX|6tP8U87n+tyu`D|X(?L_~DS_=8w*1x@v`K{e6&woubpW5OMRlU1u7-;LC_ z9ons-@S0=`zJdnY8Sao$UnjyNS%4JO)6He(LbwUlm; znmQ5VV8`!Ud(c)tc)mS4lHYODlANI}Y`{r$bCO4Rv`t0hWTnE}z?PBx^wKP4r^4Nt z_;zqsF`A(-Q$d5jIzSQ6#Ey_WRj;*jmNuHA86C-Utk5@>?% zbfjdOR#vy3)p$IX7=aq6nVl#)R*CH+v7c%TqHb$N{LW`Yakx{Xb;ba2S=R{!BNb51 zK`=tyI#U<^>N=A=jQilm5DitmYF>>)yhm#)4IC_=F2D>@33Y2`7uq?wZKT~K(g3A* z0eOG<{fZ&vd>53(yZ>;Cy{boj^>r6`&__%Eatt==tp;7)HMO!U9Y3)vV%?KV)g*k> z6)}3gD`M1LCrCgjZ*`?)R~7%o$gk#67xnzdxdW)q8tdcbdM82*!}YV>pyo(73a9E^ zHyYGI!_n^Q+1*`1DczZW+Np1MByn?h1lkM<$cEYwWf)ij9CSz4-94b_cY|%IpdPf8 zgVH@9pt*8tnFJ|CtL&Rozf7sR(Svb%x(5wtqA8U~Xxo#7pKF`uAihg#Pf%v}gcI|7 z0@F}AJ*ldJTA&xL?)o}w3H9XD3!HUzwiaBbk#*F!7mcs2Bhiu7!Bk5-dO`QqUJw_{ zik+kyx@I8N72cbo)d(~Uv4ke$OV9L%5yPXM-JbB+-J5RVf^%=GO291-WVY)AOSV;t z#IVV!hSWYF&*}qHYMhC4m=ddOOZ&2q4a|i$WEHK`eW-$;p_bFFFFAXOZ%0m~y7wg~ zLbL5bPzxWg)Kt{VeW|j7E?9b)mN9>+dp~-(aX-$E&*=wWhV_HhAxiJ(uA-MMYtThD z9STzKKamuq%6;(bez;k85BE;A{5ooS-|tP~F!>JvGjckB9p8}BjZ0&W^4m&3$x}GE zv=9L%wsG1$(Nl;w&;e+iuLodmd3ylLZveqPsk`<-x0_B)B~oS?Pa&t+2SRyY?oG3z z>Ep$MKMA`AljfMF3VUk{d02Q48%R&@NaGp-zep@1EMujx2eF3%>8^%60=s#49r%^V z9T8~9Tnf8tiRE|E_Cd@frDqzOU;yJN^K>_U76-$Rn}ZOXjtUw~AEv6&VD>Z}y!5ba zXIDI$2*sYl_F6^`@?A98T_w=G#53-(KgBN(usaKdZFJf4TPt`7TD6rL4WW50HFOAx zEwp?H$eXK(Jj`NPa_zP=vtvsgb#pG&HI(J=jUlXrni7ea);96N;H$z&-EY7D3ma?r zP_QIxg*}LLJd_$5>K%JD&@~=Gjsf_-sd2zqEMrwXh4s{87$9{ub{M9qIy8;i*|qbJ ze?SAAU=-HY)593tH-@ol_;eUOR#U$iXbmqBPDDm|hT2X4;mBm?;f()k8b2JQRkg+* zRrKs|TAiem_LZnVhBIOk6gL8z;=xjCGHR@(y8hOb%9@G(Gf?A4)7Js`mvNfrufDArr4;eg$D`@7a;o7> zB86qu%llGBb9pfkU)CQsQ55;W{~9ywl{K@DQhe>FV%BnY3%K>*u6TmjWo9iTCCjmj=Ei>1MRJi zTB!4+7=i_wJC3Hz*Pn^hLc%<~Y6%$!zaHl<Q%hroGMWzMu0hOSZ=VnvmzW2YxtqVamENOecD7HO+ZqdAA5!ZTS=ou&iVJv z$%>wcfHqQ_iBQqdONDs{;kV2RhDoAla|5lN2(RjEk3rVc#}mO-_r45qi1Fq`q%O&` zxsKu{!Hn8UorE#S0%AK-rZhih=>*T_n#!64h8o&8$z8)`1~#)qoAdY~ehvbhhZq9F zzfY#ZD(XC$(U(1$(KmN8Dj-ogBoJoQDToXBuunit#qm0Akcm^^i2oG!uS5-*f~uWC z0{lz%OJruplOa#l!F*fxOihixOz>6 zriw}j#9hHlf{7lX&B{gT+*HQTTT|h6d0m`}NY$PO((ppZ1izX1^wVfpF!$Oi9K=8| z{C3QVI7@6NH@mr#4QU(#G=M;669b^Dl(Z5@^E5F)e$%14|8(?W)9G}&A2+foQcjC4 z{jjA!Ih{6?(UIvGdwfmhmmbF7|6oO{#76-$D8cEQ8I)Ku!ySa;E&0bx8HKB~%<@*M zcm_WS%!2?*oD<>Bv4fhyl@vS^VfteR4P2(MnSd@;^O}OvIi*FtCS|5NjMoG<{jglHP8%E5~oY{25q1kQ%h2yOV zaNojddKIX^son|E?!^34ISOlRVd+&l?!>Tks>u1mo^wFdcn*jrsm~m`exfqwz_&wl zpsJX3U7Q2Y-=0I=;|Z!vzm4-Yz(PGakPrn8wCUAj(S0Qx)`8>s{7 zG~OqPE70(1Bv-cK(+FKm$54imeJ=d1u6uKln|b!8}uSJ30oJ@qyJgt zj`7{RTH7q;r$sdW{J?3ln5=ePv3FEbyEL^xv8=T9u%(>jqW37P95kP`3jzM|GDn;OrKuv&>*ao8!cm+B{23$YEbtv=nM)=$Jh?p}CX};)Lch zwD(l6T;TsVb)~tb-aJL4NM~>8Sw_)G+G&r8I!U5pmotCfSq7WZ6t~=6!)?LBOsZPg zt~oZ$ndru8I$7)xbC*-(>~h$4bU8y~w9b(bJgT&ajX+MUtY-r2y#lliSAcee`mO-R z7UG81`=|EimP*(mHxJY170^9YZy3msQZy#(92Y2?XeO4;gXLOD-9*bVQU*zN1X56esc0iNHL9v;M~@-WKn$Gpiq)ikBoS_ed+E4I3| z*kD}R4h%nNoPo)O#eG-Hu{_xtpv#u+uaE~pVS(wrD3Wp0vH$mSkpwt~)`<_&xUyRP zAQQhi>F~m&DC{%%li=CvtK$!%t9*0~EKD$A522T~*!rv#TVr{q`q>Y_Evtxz%s^PF zRS)s6Z3UOQ5nnro52SY_-aH*>lyBh_-9wPJR3ZO`@+J2{bfRuhlxc|4E7(o>ce%td zJ8fB{<^QF`LY4fNoyY=j_2hTh;BU)>E%S8+R9LJ-9){Ws++hMeSHm8Lpma_{quq}^ zjGo>5u)EUz%h&viI`yPKtlBb5*9;JA-x}n1)EeYBbq(@6U870B8-deWQ~qfG^PEC~ z#;JOG4P~Zqy@QI0A`B#BC-M<6jDLi6O{YgtX%m$82-#^`!$TiG0_FpcfO(uw0mz8? z)3V1X?okAMbZI^2z>UCJGeT^6uw|5{J_^i8Wj#uLBlH}g7*)Qo$1weCi9?mR7Pbtz zUtV*E6PR<$V6JA8J4jjNV&dDk7S%Z5J`m?6RkGful>YkL;ILn>gNnXhNoi^UGZ;mF zM1Rg&2i^16L3eNEtOH4@e=cB}B+D~{m>OGp>NGiwj5{DXq=ssLy#D{Y2|`rU0X_n zO7i{7q5xZBZfT>lS>S42knOJGZsirKCM{WsojMjuq`GW0a{p{5_Z)j$oQ;K`IRTaV zZCn~}wMmPDr@0A>d^XdU*$~iFcd}`$?Mtm@$7On${V(3qSlx4|Dp|90+|>gbmDYtR zJ~mokeUi)gquW zUo~}Uz55;uu}irmE|y;&iHo@0&DTOMck{JCi}Nrvyq-s!p30+5xVOz?++{$MP30{b zG-GDjX{VC6&XwN=N~Wvs26|wQ`fdPlHhlF0vNukf;ry-JI!hvtfXYmo$2QRKGxRk@ zgY5UE7nox`CHwe+Fio{Lf^#ZSmf@sX!7aa$8m{+`)uD~ZP02EkrjvB!Az&8L=eUMO=$+(Jj5B;3rQds(Z?f0V^BC-&5Nid zaGtA75^fv|Ft@cRfSUuk4i4QmXuSFN2633;jRLy(=>kT^_x5(eAp7cv0_y97k%@|W zW2Qq9;AT5Slf0PUimg$llik)fT1FoB znxf6D1DqjZ`v~nnlfXf>W%_2=L)AG|y5UgcI?IFrM= z`Xj(y)k-UAfeC7Yzbyr}R#ohFSU-6?oz{0dy^^_|PB^-{e3bTXhmQr@-La0JIz!xo zz)Y8ZBCzV;+mYh0w=<`6!h`ZGti5aC7EK#8Yp$?GevzDT*jjqR!v@BhC+<9j%kXYs$VunL(H}z>h>7e26HJKrVmoyV^lFv2kbF`tKa1H zm(SyT^;3<<`Rc3Qe5v4Zn7jIMnETq}5cEWw}m zKE)W@^b|EUCrTrbDf+@5&Ghe6FtNweWM@R1W9@BC)bnYoqa&XNAel?;d^OS=_SI0| z*@IhmJ4vjs}6Opd>cfx_^NYF3#_Jw8DLau>ryNiS>yXfy4YPSm< z)irq+7`b%Kmrn0;2SZw3nXo9`-9?}OxC^~h;~CyUpP?7}JVRAYo&jHi`aVPPcrAQ} zemeXNXrHw7I30Nge6jk$9^ALy%{Dq38F%2fRXp3GG-5aTm9%;{Mu^D!`HYg( z|FTF+@@$LH@!c>#T-N~%s(7EH%@C@R^$<1YS=3nSvn-1^8T~BNqTM@nD#7-lSytbVem5c((Dkdk>?BdhCrme0UOdIPMHd6f3pfzb#+)=*UTdURcRMbl2o`;y0diZ&W zX`x+~*jy(pF-5;Wk2H070dzH9fLBa~FOc3uQ(pk8v9kDb+>AQNS@>~Hi<$YK7Z~o} zT7ibT3y8YE2!?Ok5<+6ei|~EWi)7W)oEI6+j$zSAbM}FG2lyR-#-NYBh;FT|3&3z7 z+iTF^p47)b`^BjDOX#ZPm)I!QQ2&>}zwITCeXMzj9~p1i+a7!S=_QExAsL-fkmhY+d<^e^e^{;E6J7Xy>e2>zXHTcw__Qf8$xUIoz#74Xp4uhLP+UZu=3 zU3wK<1RQ(~s3mIf8m(JwWHEmD-Ic;#`Bpg=q}vv0DS0eqi(W%KY*$wb(v0!_Sg37( zwz0D#({^^RL&)&g8D*IE9*VN^b2Z|1^3t`6JZy+wm1V!nxa}E8)3?pm`vx&fH(tkf zVV>ul8ZfjUVH;|-FZ!mJF5?zagzbv6i13$CQZJVsWNnP9NlfGZ5v)6Z7}mXY7-<`K@WNqcGz9yvBY@RX!ciVI)%7T7bC1HU zMMnXvuDqkL@9a_PdHX08SJgQnf~%B@1Ko|`$CDfu<+~$Ewce!gf;W-qF>ksnaU8YO z{KwSu1a9TucoQs7zv+$%F((2hDOMb>rpfDrDkktL-yVCHCy*VmGRl_He&9=){iJ@~Omx$l{1yaxx~vV;Y?Kmz8!a>sehQ@!I* zX->0@O2c8Ui?}&}9-6DA29vI0V07&`I6ps*l+4!8mOe}2@AH_c*6%~j45iuEbUkX1 zY1(IxsrtemQ*;Lq_4vT~H!wHYe(-LeL@;Oauz!C*@d=VW(um~De01N?2R-Px!}yZg zK28B20x(t$K7=1jKJ<>o@30|kAFZX9HA+SH7)eZL_&-8F+1GGxhO=THR?1@#s(5Kd zr+Gs)@*@bqN8CpM6133125}u6Qln2Wl8d51It7LRT>~)0-%CkjyCTxKrF_mZjgS5WayxwjP&tkLgi=p`!dSH( z9y+S1jCPWSIDhnsBhJnwVCC&E$M4*#Iv7* zEB{lFb7=Han!8+|+hZBg)IhsbiJ$ScL|yH%ShIM9EGlJ}S-UX zz7X3lpkun$e8JxK9#>}X6ZDEW7PFDU!yhiG#cZ+IU3stIws=^OO>;y;n16>=}dmn0E5W- zeZ^y#>VHL_F8vB-Hf5c{f2JKnw9K*wtAs3M^<8@m)X!f*d&(J9M8X;C&@*&s$1^ad zpT?X4$4(MhWqCefwCw1kU8G?pIB8kYXH8aPSa>9PcJx%tS!nH{_B`|`SuA8uRVZJ{ zcSkp^wXCk%dzMmvpXCoItFUjJD@Hpy>mO2COeUU#x{m5*k5tV$2k0y3_)*58iqr$q zm300bUGw%iSk_Kolgq-trYKMxft=b^Z@2An6ol@^oEa&a49x_q8K|1H`s3hijF zE9b$UqVg9gIO+lgJ6r%^Q;ohr=kL7WY)Mj&I@aDDjkW6n=#q7khhi^Mz0XCeX{fl1 z3JZbJa_G~)zlN}dioe8)(GD=%Ju>F> zOMA*kYwacavf8fjaMnge^OSiBamdiVOKcMOrP3r4Uo}PP>>`{p%6-?*oG2B|QPels z(Z+p)<@U?RI4;1jo2BvJ(7s*YfN*Jw9ZD*ip}Z95s6x?no%{w0i3+>TjuaFT7j_$G z*T#K|1oZkA2{@d?-HoTeWsTZ-NpPfZ(M0Y37OE%c<8NU@%y%I5%Vs~{?mJU%-=W;b zsl#{Fx7M=WIN{VcM(apIa`$~lp}#Gs!AU1)r2es-5lZ-;GE={Yt1Fsw_Id615U}8T z2-x>Mr;#>%58@$u?t8c}n3FjUt%I~;h@ICc8mN*X&iRR=0ScPoee193KY+NOa(+Of zzx)Ao*FSTr?4#2^(B$5_3xK-)2r*+nr^*>Wx?Ko^{jyiik2HAMk5qra@>}d7|EnJ% zZX^dAsIjZg{Rs9h^0|!hvGjCOifz2PWA4YQxTuqQl7$4%xy+BW*DkYXEV@i1I_UMw ztl?}A={&j{*TLJbAi0lRK^L`B$rT#V zQt#TMg?r?ifq>FX|h>Ne3D;5GE^OYrJ^BP-;=?(`&Wcfzk*?q_F4Ks&F*c2 zUpzp68#s|kej~Y`&i8hNzqqgV6!MnnDegl!fk^xV7n_S&Hveq6O;_mFZ&W($j9t_z z?x~D3Kv(e;_fW#`aNB+e8Z3WsIF@jS!xfpoBYZKFW5c!2-nRbEs=W)+;)NoDZBVrS z{+&teQvD$NkzL$Lw|{rUKj9B|l^}CD2q>pf>~=;xoB84ndi4yN<=H&?TQHQI9v9&Nq_ zk2qm)i*fz$E$ED!>~OW2?%blMnrhT!Z#$dlKb=g46gO7-pKvZ&7vTWkxSjtKvK#80 zC36PiFMbEqhkECviae{F|8&Lm)blU$>nfdm&gEf9bxyJ{@{;fIXQjBdUNL}Lx~Mqg zzQrE#qB#0kVwAf54RP`~#1TZ)<8)>j~uc|-2-&GX%pdB?XPEts+1CgkEe?w1# zA!8skQr@JvC{6nZ7QXqQotY@+blyMI8>ifV+*Jea+j3R%QBssE-cuaoy^5yPEx3f{ zn@;AMg-Wt)K%tfT+bT%oBapmOFtI63GZlk+moxkvg^jxdpa z_8t|zbC1R@K6v4tn;YX@^zwwrYHH{c6sDgiz@Q=aHd(wax3`uPt)h}t4VcJ~f7g;8 z_9nI0_KD8PypneM#V4p5>i&%aP>u5irl&9a+edtZLOD>I?~ zX_+HZ$*f$4%%!PLW{MKa1XbsJop*E496y;)I8Fpgnrc>=pc=tVN_S=ajIs?WN2+wb z3>Cgth6>A-1?P3%F!uVD4KibIy|O`7wb0VXmIY#K*`Poj^VU^Q7apfg-<1u*B|8@u z6j+Y8lqZ}9*H+&r;A~Y-Ni8Lp3nG+wIdDuV2kshLRSw+M6}l6aUMm+=L8nPqgdY%h z?X9&RElN&jG>`QQ3Q}jkAUjca1rE~w1cgp=UgEXaFQ}US^a~1MvkfC+{Hed3KUKu4 zvVTxD*L{0HN;6LX+ckrdXa#nJ=I8yXbUTnbYh~WHGQ=P02>WXUz>P^AokoOf1<(|$ zsD1(Pd`kcn-mwmO!=QErP^`R;T2@dXjG12ObV7)N18HC|uAu1PDxQ)cjj#l_R`byD zKnULSv@6oLBv9`M((?hj!9y)wpf6LMT^b>Dg4M+p6eE1ShiZ;1sFKUPFgJH}*g+_{2kaI9fgNRplQEO|ijZhCH-8#*iPhvFPJO>V~<%3-DQ+(56u z3QG_81O-)8;)_nsGW_D(LDJ%-8uucMS`Y+#zMWUjwr$0W^~{UTfLf$&L6E&rM}uhA z0$uOO{# zAFHGOPbF2+#4so*z7Y%O9;>CfZ^u>BzA(^i4hxEM)hI2*fBPfxNvP2<(AL}>AF0X} zU|m3kpePi1QU%ymMSFK9Fw z17e>Z%oIH;LPge>)=Q7Ys!v5&5Tli2907YQTJL{pe0(fQzwi>|d90FGS{n1mdG+YP z7}XD_iXNw(;t@(a&BbodW8wFS=dZd>rSOwzhk-pB4!3D?IKp~0oR-dh+bLIG*DNU| z0vZ<%bCN=|xq!Z36#;QGB4GN{5x{Ss?PR*OGXnVEBfxpyGGiloD_ZSj1}H8PwJ3~dT1d?hXA2>2)*O6iz0B9e5@dy&_hWAf{OK`6!F^VV3#UfMO4b~JVKLJ{=tJho-m*VI`gzM zjOWYm8K~_Oj==Ao9}=cT;lP~AGJ@93(akI*=~GLpI>bqurB*|Xn`>r1)Et&g0_AORofzIuw~iyx?@%8iK<|!macuu+}~W{z*}g**^+s!UILQ zs$h!Xta>^3d@qGH*tsY;@<9}eGh3I)4;=O|pF_p<(PrkhW~g=!p~bVJLG{xB#@g%A zknl`2NC#_mG$dS(ras>5HU13L6_Qx1hQ!d|{%XWWkHr8mE`}0)IlrgGXEFa1jy1h` zVF{*GiUt1zgXtwtEGRP7GM2K>#8UR-p)_WzL0lc`2*H{jde9~;shoGs!(%XF1JkOs zcD6)a(@o1yIc)68liASGMR&5DzD-x`a4Opq2dX#Y*lV1PgMD+El2?95tKJ$ORw=iq ztF%hTyM7A@VHR|r6V`kGsSxA8uDoIsplECY6x}&&eZMYP<==M(*E+YBB|tUzI$t@9 z#&tnz{<77%E>PJov;1hENKGGnz$x9hL=?@)_l?qZWwhvhTS~6O-INFx9E2^~fJVKW z2!nn|bVcEBnnb_&BU%nA%*M;g+9qQi2AoMq3?T&g_^(~8ps#KDw|0@Htc@}SvQX#n z>_D#H_Who(i)*9M+H2>jXJts`1S~Ys0O#O<0pM&s^)kF6wp@scUUr7xOnpvLIR>2t z)^G?gN14Ov*!jeJ*G|_JhxoPARPF;uS2zLQ*b}n1<@of99ZRp}q3I8-iEFvB_#liR zKx-!>WyQ#Jv#I0Yvv!gaJPtJzmHf5!-P#HAR)s7S`UGdVkJIt0^yOIHemSfP`C}Bj z5>}0_248zrLq(6$#Fb9YNFLOtpb&k%3pk8WS(-H9+8<8Ghd+Pa`u4=q0PFrfP zL)h=vgqUAzg15W;YSEZ(czQFoXVwB@NG)o9!~T1U|2Q>!(;zzQ!&)Hiq|3EH)ugto zd~RnjWz|LtrPX%Da`QT@HgN6qjD6ZFb8uK9yF<#qR zF?GP&iYFu-(p&1%N|?2?4z+Lp8vI|{e|_F(uXm>o+T_;PXujBF(gKp94V1}@neoXG zarkGfdR|P1VRJ02p_W_LsbogOAD_mt|6W^Pr%B?f>w)ETP9f+0Pnhr~q)@0&3SE|> z$th$NT2`e^VOFS)ib&!-;lhT5B;V+*>pF)xU-;YPXx%IYq%yLIfRRdP&rr`)pr@(X6&d7UU1&f@4N|Fwd7$?Q(_2A}V8o+JX$0C{>T91& zEo|hf;_e9nwlT$=xG{GHd1isME<;BeQLcxs1L9Z{+jbMfx)48$)UvLdnl>iCtA;cN zMHfaD`4%yW{qN1jj_caGbZsRQ89v#V+B)fu{pzULCa%i7*XV3u8#cwH!rVuQjkm6S z@un67xD_AboJmqUJ=cVOZmVq+;t=>`6Hv6#pY}nDo4P9VRsrni)Rd};Avp>5Ki3px zFs&&))Iv)E(Kk)$vS;SvF!6U&gzkIGYO0iajw)}WE;cNZyz3fk>Os>j>o7uZMg>I6 z9`ArO!1);N)yGAdhSbyRhfN8rOI1p9eskV8*ZG~o8`}uTXU!3zCF2=Jzcokgo^Fna z*VYkGp%vEEQe+E;@|YHobhmz#@w$dwRT3@8!n*2uv4yKD&y=S6P6m}z&1ElcuB*xe zxv05nEzuw!Wq`UzOB(WPMwrKnB`LEdgdn{K9eNYAir>1@5<(&lIg?tPQV%iXH);h% zqkTy+TsDLAiB{m8+={^)Mf_B!{gK+#JR|Ls4l{p))u_%`j|+>Qlchuf@pPP7BTgxg`E<-F^=BEB}FOnmWRjp2rH zeHU%H?P!MeoQSojC7sp%ALH)&PMXl3hIZ8Q_6P-0GyefD-n+iNKEG}1XMH=}2O!AI zV8F_8KF6h-%0*~=2NdS?Yiw?pcAy>NKcHJ{c?a;c(wd(g^euI|1L#}u5;(OsSCx(| zuBLQ!l~u2fEb5wSYDYwRe@9wfr2N{^6@lD7^QS{d16At;j{53u zpL)7`&DSDg;{D?Lj|f$kl|pDOlwY0BNQdizgB1I&&g9fqzs^usOY=L^AvM+YfkR{s zphy(m7Fm7U2-Z8)&8y&sHF2jwKfbthrfcaCTUs&jXemUoB$bGrjWT$}E$ zBq!P$gkx-vTJ?K?0RWVj)@guQ5sS5wJ&epoc5bf8Amn#wk4XS7&f8RE-QMUZCz7AfB)8%#gT>)3kLN5HnYATlSp7 z3mGoAS!!MD>8j#tSFEsckV@5CW7$3p%S1TaXF@=lvNK_S8$Fu|!q(cJ$tI(fPdD?( z^GzNg3Xb<~C^lPf!ZEorM`F~mp@kxQQ58`%d!e(NDZ3Y4&{WUZr-`;(9-h4X3T))- zQ!|IVG{a@qD;pXr`cbOGSnE+&Qc!(g>&?W4yFRRg;=CK`>A6S2o2qU0sjCx@A{{9{ zOirN3H8=1`-H@!v-sIO&%ic7!whs~Gkh#l=Fub9bo*@TW-rk#0Y7gex^ua(?&h=PE zZ zE(llZ4-RUN=J$h?Fs<$f>QJ?~YJ+b>B_2C;@++!be{fgO)gMrDi~BS1#`i}zZt4&2 zPCqhVd}e8r_>W@2Iu5iV2O#tZEVK0hGHYNFrLhAbq0~>Nq6VNJQ+{#^1mM>VIb}8Z zC#SkHI%mI2>uulfQo8h$$>IjyzZeJ|C6tUVV;pYqS2m=Uqkqlv&^g57a#We$VA8bV z5&b&QRoQ<%0oDgW&%i+t+innKKQ;($H+&GQ7=o;mg;eML*U{|r^!b0`o@cPjo%_4_ zeXpOR=--W~^|RGxFiL;vV2ysQa+WJly|P@fA_JS>EXK`bDGSg^I+O+0z#*iU$Os8l@(@=gMGc|j`VWDBZ(W9e z3y08|<1B5Xr7asm8;;q31@_S|Hi`KOxZ zW7LTB+a3xpuAekFIx*zJXX+_Lbb7)Q+XvF^`-DAXEhHK=0-N@QPgo{B(;B7!ejbiBL^VAaXSEQ=6Go%R3Y`E zEV#f%URWIk1#Yz%Mb$24^Gn-CG0>i<>Om$p25LJ=jw6{BOjX_L&eN0|%PJ(;#|lD1 zjRr?)mA~c0wAolnUBckNj?rl3JkSJrHdbmIb)e%-yRG9SB*uF%+$fLY-Im$^RAPnaMr0a4!I8=N0&@f z>Nr<5ECmLP1M^fZ9*3k&(MJ1B)-gV~$`s!c)MHXj`w_!|B=3faiX0Ef1f`9q+<1+# z&p0g|@2cz`%Y0$V7+YK}f73!LnNQG$F*;>1qj`KBrEX7S7z~$E{QWGfs`k%KmTJFkGZJ4E$e`FQB|!lVJ8OE7V`Xlc;RKB$xTyCro2N zF5rJ>{l<$PWhFou*tNdr&>;CBFKPuHZda=!I<@KnT){v zYclw|YsX|-X+hbYe6Cr;+!n@pLs$K62)Za?3VLV46e_)010%=fQ=o0u6jxMGr-y|I z&T{w!H*<(lM->5%wbr>QHgi{0w-U&1f_GB|mCpgsz?}azgwEJhUW0O=nOAJdTc6o)0=!vnkXGMBe-4=jCp%7KrU_8?G;nR122CIQMdNpgS(66&$#Bc@A0Z+D$mvWMaX}}zkhiVZY zMuD>qv@i$qD}fWw)j4Q_^axKhWDeG{2oHBAbE)FJ2#*Qd#(`=vxA>I65km{Y8q&i0 zb7OzSmGLpUpDr|alyP5`YT^9TN3~iw)%R9UQm_TtSp2*#&d$nwfR$sMcVjQ5R`JAX z+dL{#m}c{-E=41V_{u4cGdX#u)rb) zLI?@zS`g*S>a1^L9NpT9_?d8+%#KP}0CWf4P4-Djdqqe1%C*yS%W6yXWQXcB-HmbD z(MAszP-SZ(#=`vZ3z=E3#(64f=|bq5wGfh9XvIQ`Hdk{$Pdu+(Bk$w<%u9P?Q{A;3 zyuTKKqOoe!a!@wX#6@%n-ZYlnK$mZ_!oI%*+ zPJF_Rb+y=8A8t(1hFi7@*_fY`VVUqxi?sDy1K%r8!D?oPA>U2^+a8IoJLMi=_f!nUbUYfah&|h+IZMB zmiMhm9)l}1>y>LyfbhfKO!Nk^pX zFhmvk6zuVT3YD3q*r&+mg@RBYF@unCAAtk4{3(hI&_09cuQT@PC%>nuzx&hF|CGl# zx2ccHIm?Poz17fJR&07y14%KJNPNquDV3>cM>aMQ-trl!%h32B0Fu0$dT5{}beH!T z>guNQrrJpFsuR(k%E8`E4{dFUTZF$ATG4XT74a;kI;+jIi2gIr(wd3YJ%kF|)KSlp zgureCKzE*Hx%W;DC#RkMdKOaJD(*QxX-cT+qo9qBSN9Mob5rZ$$&uNUmxk>Ya#Jg< zs_1aBr7loPHJ32RFoTUyk0r=QL?v77Y-*;=C1k$7gkJwM%F)}zvx{~LGSQNUMcZJS z18hSDKhN(5%8T|SY0>jgKI(b;0T+ztA^6zyRIu9;>gqUvig*E}G&@`^U!cayFOXG7 zZC(Heo-i~4oVE1A3$(eWcD>+iryNHpc6JsD40RQ~6co?Yc0{?FVwVDAFVFg>Z9+=% zgqMr1vh9_VrufQkTWf9N&|oQelax;x-CfF-;EMoHv~@rN?#y&RyyjF!caRW=7c&X5 zx)|$8pxa`o0o~8;7FC}XhIh~D7a^lw94)zT|MiV?co!+ZWe^lm4BmuJP92M5$fj`R zxSZB`@McCd!nnM4I2x)0%V>QiU0mk+!z{f}<%rtmEZtoW!_rrv36`<=Y_rIv6kEVoKKW*-<0smqN_o%%8 zqFavt3*KL4T})1?yi%;4wi1(%>4_Jw7IMH zzXbj+I{y;2rR&+!%o;sj2JQaR#)!?Gl=(6_9d$ebop|VF2yIf*$!V{{meWr8t6{Y0ThD(1ytWczZpbx%`52;-ApZW zX+%?v%%zo0^n(3rtYdyqbuSkV{*udHs9`P>D6-ndpNc0Fyk8mOEanx_f3s5@;!^dh zX#LNk%;!W5SGiYU_Fp)cVz^cQ6_D4FJHcT_Z4G?|&~2|!dUOJE@cAoj@J^bF93TOoBGYXj3J6A>O+=T5S?-hT9ya>j2}l;=7Bo=bi{_Q=3q7S+7H0yVpS& zuI$%A=pn{E%|HG+d@p#N;TNi}TfyJxH_$C_RB*U}4aXbMR6!RjIPB%Il{aYWAxt&2 z_6^FE(>o-vCOnX0LcH0nz&Gg+mr~wDX6L<0SGD#yG8?G*B(W-7^Ckt#>OzX6mp7Nu zH4@Zx745|$m)8zfA#hm1SdiMyB{ggnrAlZ?qE96JwS5&8_$i+RDtttD0Px?mSaGYV zaolRqWUOX}TBsB^&D*`24fLwjbl_RbdT%uXHm~s9YG_B9{`D5f+beDjn}T+}sWvs0 zhchp|S&<=;*OoV=$w~7qlv3;BMtwMpL7dk{1#4VYa@Qg`->-qCt#HL+0bhJ@MFgic zu5eqXb^&y$3L%; zYODjIp}Ma_pEU465Y>mE>O|gif#czc7Ao&vf?3|>)zjPSTnU_Kom<`&=m{0GeVCQx!& zn^MIc=ARd#F`ED&76$-svsN(xi{gd9xi(_nQ!b(A>>bT}jpKQ&BxObD(Gb zhfV>DdXSk?&Z9${P0ly78o?sVAW=N_30Ap0NajHy`?xg7J_I|@qlus9!I-^y4E_Lp zMgpS#8`(i+ip7iDB&B|Xk!;o$8<1OI4pGmyfS{zF*#dkCZR3}2Z-LgAlFONuRGy#y zBuj0!l2&7@E6jiMVx?^bc#%eLrRYMvu$4h{YAf361M)f6I&BG6w?Ry~ZAgE&ZAgFW zHpG68x^F{8n6n|RZAy0$r8d8DdGjRPJWH=^1MN&50*2>ZogD%(A)BbpD}*zP^KPE5 zGTYIW-L|9R8*S%cYRYy-LGSHgo~o&21)1Z3^@Tw}Pj82;kAUUO>+E(oZO^j- zfi*b~jOFA-gsaOA1f$^&#A&>`?_hg3&PQH73x=sRr(I6nW2GHzsmAC4ARG={*x@RE z%N+r>KvxNz9?*)Bs5!2G|hWE>E5Au8@odM z(CIgKA@Q{pnos#!YL-v=n#$rA$GJX%OU14CL@YC4inNmj7H za-{1!V#lc)MWDXB>9;n!F$Gw-8@7$!O*<2{Xg8a?1Rqvs_$3Su^0>Fy+s81+#1=2P zYR+4ZTjF$OHx$LH{2o_QfH^L541}JkTRD=6c}uhg?m-Nq^w=I+8cFSBW6c_-4Sa*8Yj-j*;m+Y5?N4cp6}z^u3o1;RS4T_rm-*g^y|a+nKF z@NtC{18^ACM1I}O7;g(#g8M*$%HIdSf@v8jFv~{q{F~^MTevB;d>0PMV6YHomQOny zY1nqIUtnXP?(Adb+ok|%ty+K@FUui4$jbPd1TaUGGd&({Er9vC1u(Ldb`)?YQqo6I zW0r^5@-{8y;h8|hu2dl){)#DNNR2II#ASYq|I1SQZ+an*bmT48GV%hK zmn^H+ek85@e#XcQ)!q*mrz>+mMBAwWwfcgtI!{1RagJUikJ0oFkc=j$GXcT;dxh!2 z$trVzS|_Q_0rKrh4MSnaAZz{#uxB>%CKRV}JTckk@x1YR&5DfEdlVs7ldlN3{CK1| zZo+wE6!125jaKs82-qn4hH=7Ud)d96upoInL~HpYc&-|5*-M?ySmJ@o@=Ph&`qgrW zDfl2Gawx4L7hegL|H{^+c|+9iAo*EZa1hOG?{xZ{Ll7`LT=DkG8>Ax#p>UvX@Cg`T zTNd;4)Xm*4TL|R!SBpc;GX07(@I+^#*2$KlQWHA1{DMAe~~@&dTRVTfZ)aR4t4f`YO+x`5BfTfkLGpPDax{WyAN1USGZ>R z7J)Q%u$eOCby3H6QOnEUWtyA*E}FbE4$e^0Nrm?5Sa|MT@H3|T4)c@QhL5HmMgZ=c-uHBaMVg6g@=@eKPIrl!Kft^31=*)$&>}|HpR{BRUYnG;bgdm!c zq)}Z@<;Dd@>&!>!h4%?sm-{g+`Sl|znrhi z=ws@rTG@HmbIT;{CykSd3qauV?kj7?YAdp_dg<~Bunj(8Bv1W>3j2Nnn|R;$6BOf^ z|G_HZD9NLBfMiZ9E_^~IHU5oW*>?>Wlr1Av^WS6)R|X#@A4j+lK^AuTUpR3KwhYs& z|Ava8dKZv@ArC=xGZ*D(I0N)Oqapm4-S3Wm5xcp41-+FSj}V{k0^l$ouUR)328{`x7H53ixQuFp`J ze}0NtNruXQMjbuW=rbT5`wSr%`x)uo7*7%A+n>gk3!_Oqu_b@D0tdyI|%{peEnO$aqfbO7C~i8Tm3~k#~5+P(7J6NW;=)C ze_=hbrL`s;17RyI2SBHf(LZTj%0=k@F{=FW80=}DdmNgY71Pw%u6M3;zPzQWx*VtN zO*EPOfa0|_4r*yc(RVSy6<-~b;vMOU%sm0AzZ}Q%sk;652+M1ahDp5C;8pX>~-$9kZ6Yw;S6U=e;nSnnr# zx6aZ%3I)yd^*zumo)1S_?4_+Ue8UmoldJ%k(YH?5_%C4PG%fqW89|PSVvDK6?0Fui$8|!4B4ruUtv^ zHaiVveyLZNXZqF$p;rg$Ptd6K*VJ6)YdW~U+I($Ca9`8dj}8S^H1hiDS<;wiwtY>j zd+Ve@M0|q;R=Dd}k8JIw$ZyEXRBJwgJ&VbPqnS4dcLjytD*A?A=H1e7 zT!~!mJX|yDWb^Xj?ybeq1DQivUmb3R-!om8B~tTvPbyfaUbwK*Zehr{VRH)98=VXDELCG{qaM%o$)C zsm>YrI?K{~FAlHdMl6c=uomLr@FLE%-#J6^yfdzFCqlQi$l^+eoT2|y^$W#0GjyLt zSy*^(C)+v6)4a0~F!C${T1Sh{GDd3qI+o&Gp%Dp~pf_h}^w(!;bWL3cg_@p&koRwu z4AtOsWOY7ARy7Sf2dP!{G#`C_j{Yn-hX_>G$#aNSQZZI`qVk(lAwsRsQ*ZV2P(IrJ z%Qz2?c#Sy^jyNqn4~SzBCf8=~OvsC~e9;JRHYD9nG` zU=1V%^U%k>qtbys##=1b!zn@LCbVsUj(rFI{yw>N4o%Xoq9PlA&uA;&wr=aIX5Z83 zK6rd11bN?senev)D?DyMMc>0W9;W`DdNOs}0DCIx2X?JvegJUoT6dUU_yNFKKLFTW zFaE%U@bC(hqZo$nXa*Iubk*q}D9ua1Kd}8wFK)7()~pGr4%P5_9I0)_=-6BCvQcB1%b4^kI_xFb05)Xo!55CK> z(zd1=`!n3&amb(lZ-(M2(dB-L5&H9IbjGEh9V@(lent&6Q0y=C+PGif*7TnO=(Tzp zPYR=E`7e-I9C8!$f$~|-vlrV^^zARuk*s@s9-jO-hFYo5L^!OhtxmrJQA-nlWx&<+ z^)Bv{Cj$dK!L-C|nvk6)jhX5FJgoZu{*@m3=~rhM-TxKU*6H&9$U%Eth8$k5zYIqT zFT;@%x63;m!H$eHESk;%;V$0tn!#7yM$B%!^AYFW7Ke8@&5TvID}cr*=ZdRJ*=S!^ z@nCMnN)b4NqdNY5h1w%^5hzu^3X{J0p^Pnnw}s;;4!?=-b`^Gp6_;d!xE&SlLhQ{K zo5m0VEbUx{XkEApty~+qzf>`T8v?yl}%+&X3jGjo&zKv@0muZ|~LO43jg-d9`(Wx|-dj=FS>= z6Y1J=la?>LiGJy*tt4=0dXj8K-=evtZb5K6#oS_3XYraHWQI?0!VNT`!v;?|ApmEe7qxI zCbE}ynh3E0zf<7mf1$0B+`pq8%taL%45X1Ropa*KZ*QOhze7WPEi#be3spM?;!u!? zd;Z%~b%Y!ynH%;=QRp9hlGXeVO4ZRYerf9;)b!FH%xkr9DhG|dmg3Y@pVOes)!{5j zZqtMQw;`swVsE3xCftTYy>G*zs+vfGb3*ErVGW0;{LL{D+zfBW;Fe4dNH5+tk^2)Y z75`)^?P>ot>U0!o(<^sQ2j+Iwybe~!Fqc! zrI>OSvLgaaRcyyOk32lIm;D9(Sfu?$fpR*_FV*-Pd0q27h80QP?QYflo3vSfL+8-H zsTWtxzkwwv_un-6=f9z6-Pxc}|Luh1whY2?{{za>YWNSoh+*{)^_0|OBeAn z2kYJgtm{!S)711nC2};BPteq2xv^8=gdOFWiKb}FeGpI9$@{c&l5X3tiHdnZBPpRi%B-Y(1}?UeI{8v4 z`+YyROLhI+k;r*hKet68nBwQQN3)%S5p&%ppxl~2i4MG@jt-E;Dd+_NUFO2dzSUG6 zXK#eE@ZV8W)%^jeq3-@*s;(USRZY46?kc+I?=GYF{oS!#Z(Sl?HA}eBq9xpD(Gu>m zs#n4t!{KMo5>T1oL(SRM!>D9C;`JIi2>ZKy0&O8h-2iCKN*oLmygOnPP!fP>C6}bO zxh374wtHCLzERT6F0G_HinY{RmUX$LJCJ=^HgRv|Dn;fWC24(_%9o<%P$mOIY$qrA zHHl3K=1Lks7RrB7DL2niT9My7gxHdGhn;r%zYAhjz4XG$x( z3>Zr3=`x@#scrVFgii8HF=gT3{W9)2j$&fVx~m300$Iohwy(3m z?g~6P&Z^n=LTdt7G&yfz{hSg6bXX81PK4F)Y+evd-1~KiEgQCv*L>2D z{kMW>o|z6hW!V)DGT-m*V|0xS*XZJQb1s^y!!3wK3f-gB#0A|WHPi(!^IWiEh07hz zf_aMzoY^`-IuYHRO=-PUv)cCNSMd06AF2p9EE%HKZU#(Naiw*g)AhqQxaQjGc8BN{ zw>ymW@=iBHW?*ssz;FOx#kn}yK0tTe?nJc?rmL$2)4+ae6AT9}u&}kl&J{zxVcv$; zK3WnCt-X~Gg#HPJTR(6&$8z~@FhtsErc=b`xfQLPpBprQ~u!gn{Y6CVeX zm<=viPR$DLAl9gUF+4z%Q32ALRDg{k%B(=<8T*7T0FX>Dg29kG18yZP{z z$wS)^iz&0SR4D7moh8+@5)6N=5&|@?5)}D!aZWq^w2_Z~v-EFC_usKtH!DGV^H91b zA(XCJs1~6>F5tBoy3^igF#5O;!BppXP$+k-JLV}b)SaN;LSfU_lu=k1`0j_g!vk#8 z7(Bs*I`9f3`eT+_hS5;R<=Zk)=}jDeIBf}|Q~ni3ozt})m>|0na0(+jw!u-j2fVDc zBh|(OY;_OJ=GjXRu#<}ks|T#_NP5R4Eg^@&v(v-)o$x}V%3QuJs9tr@1t5x@`C$_QudyltN>U5cRCV3mp_Z;)z7x~l}+<`UhS$`zPh zI9$3<7`Gh*G>1G+VO9aDE0J`}iAZ-eXPZ|^aGp7F%CNZRaPw%OUB~R`t)@{FdQ?NB zP~e-QjFua*L|l%7gS(@ks;7=cxhuOeXduOlgWDx~LfP8vu=9UQw8xV}jT*j_Ie=(QT#dv2EH4EV!RteOEF2dhcxfSxT`oX4qBbu)avjhCl1?= z*6JLKU@wcMvN^HzWlNr}rCBYCTfn@A(MNJQUh*}NA7W{FGd%z#$U=Dg&=IJ1B*ASa z#32xU9|FN9dcLY4AbX# zQ9t)u#Rx4)psHyJP(Gh0OF?uhfkwTbK%*Ymf4}gb-<;e;a=InLn|g^*HA~$S>CTzx zRJ-o6+x{jx`BYGZ|IQhDJrNE~*Sl6EFsWD@DLIMtMY$w*0vBYdNp#K>^-F@N$y&rO z_aq|<*)?Ou-x_z=WxeB!pvxZQ+FTC!_gJlRM z$b*CW6#E2~u1f7Us=$UUm8lBlgH@+0sOMPv6M61Xy-^k3KUS4W2I#G-Cip~q)d`-d zVzRhuu#Ky+f{5ouG7eRmRD+D(8d?qhY^??k4%S1B@?P3T7VndT&5v{S65gFX^|wK1 zD4{x7CRT?dy*6Mh0(5s`M*zLQx;x0fF>3wGvJhRJYCfrsRCLkB>X4eQ(lz*WR_z*; zpIrm)Wz~RtJfv9zyu_ln^vg9URwm!>adx)T6>@M@^y$J>cBN|u#IQ!$nWiQ+8J~~U zL}13%q$vcXuZe87D((UUJ=vF4+qIfB>g$?R(?U0EGT}FWsF)gYyvKrmXf5hXuLTNj z&T7Gi?X{3*)nY(4){a`V>YrNH_uVQuEhQ>FX)Zf|v`%8et*6xCWlg{Btgp_sX$T>^ z_ypRyz7IqvXY$6;`PxwOac$PHW$Wcc-=|Z`eX_cwmum)6Sh7Xp-R#&e(CRI z81;QJ=o9phrN=8ih4cw2q?Zh05HC*w)$9~^q{|6u>}wlakgc3no=t(ckFkaFi{d$R zCS3&hPF*S)q1aSJ)~<5xD4c-f#1juGRl(N6yRtPtm70cW88B$^eW_44L}&Ts$|^2V z-wZr%eu`UkmwHfAuO4H6kb2YuWT15vNLg3$|$8i zLSCUhi{Cz~Tc50X^+7kHKAc@$pHcU?W%bfq^&u!zAMsJS1{Aqv>D*H_Kr&2un+Cy) zaM$Jvk^Z~7YY^#nUDW`}yK1w2y66NSMK?q!{2D@TXT>xmy_4G8r=uqDad+^w50`b@ zIp$ZQug*4P5A$9_>T9R-4dI$2*3@U#3q*y!hJjs=Ml`5iBQ`#5l-US$t$Em-4==+u zqEVL{(MQ-%+f22qg|3jsIY&riAeyO3V}3QoIZ4e? zdHC!$r>~!HPN5miDHOwd=wLb3oa&ubFBL@L1y2Q-+qQtf2vuuAQ^M7)1#<`2xArSc zD=jZnZ`-GmE?Htlm2OG73aZl*{>*8~sQhA%6SjI65nf1R{kocuZ~aP7;|JPUnHzDx z*yYCm9RPMUt)OpUD+o?&#mEZOAQD)!KGq7HM_Yk&Z!09ejE=Q}?#R|Oq(o~PQc6*+ zY5l{n+)T&_T4p4%{dV!FLTd`|GuTzY>MXks?XAP{EUkS67kD==@SXKr8zy}7?J?UA zrcGXe4P=`?Bn{{eX^3_QWv78?OB$WMegP+{@!tG)+L{Jm+A2Q_TinpLbl!;A0JL>} z8%4CGNv+koEtEdr7IB}_mOf~y7f9EswnqA+OfQwa`OS5@t-D%qGy2XKWRxuiN2nhW zW2}2SMtP%ltX1dOfBrQ%>|fmu3LbCAxFB$5J9jmt_eeWf-$1{$V}WDA;~vH;y)-k# zZZY%gsbzZxS*kU!_$k3uU*HC+udCl2mDgk4)jIc4m7`(x^-Y| zSoB0+oKwa|&dmfip&giyH+O)uKXsr{C-^V0n$dtwC62r+u3;k%354h92>L2&z(

    9M8r5I27 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˄uYaB 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 Date: Fri, 30 Jun 2023 12:50:43 +0200 Subject: [PATCH 0989/2059] Fix log error on gre tunnel fw --- openmptcprouter/files/etc/firewall.gre-tunnel | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/firewall.gre-tunnel b/openmptcprouter/files/etc/firewall.gre-tunnel index 59d161781..b68ecd63a 100644 --- a/openmptcprouter/files/etc/firewall.gre-tunnel +++ b/openmptcprouter/files/etc/firewall.gre-tunnel @@ -6,7 +6,7 @@ if [ -f /usr/sbin/iptables-legacy ]; then IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" else IPTABLESSAVE="/usr/sbin/iptables-save" - IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESRESTORE="/usr/sbin/iptables-restore --noflush" fi _setup_rules() { @@ -39,7 +39,7 @@ _setup_fw() { [ -n "$ifnames" ] && rule="$rule -i $(echo "${ifnames}" | sed 's/ /-i /g')" if [ -n "$rule" ] && [ -n "$lookup" ]; then $IPTABLESAVE --counters | grep -v "0x${lookup}" | $IPTABLERESTORE -w --counters - $IPTABLERESTORE --noflush <<-EOF + $IPTABLERESTORE <<-EOF *mangle -A omr-gre-tunnel ${rule} -j MARK --set-mark 0x${lookup} COMMIT @@ -48,7 +48,7 @@ _setup_fw() { } if [ -z "$($IPTABLESAVE | grep omr-gre-tunnel)" ]; then - $IPTABLERESTORE --noflush <<-EOF + $IPTABLERESTORE <<-EOF *mangle :omr-gre-tunnel - -I PREROUTING 1 -m addrtype ! --dst-type LOCAL -j omr-gre-tunnel From cca347992ce2607d2d67445aea0516c5f93bd34e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 4 Jul 2023 18:31:37 +0200 Subject: [PATCH 0990/2059] Disable LUA header check for tracebox --- tracebox/patches/105-configure-header.patch | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tracebox/patches/105-configure-header.patch diff --git a/tracebox/patches/105-configure-header.patch b/tracebox/patches/105-configure-header.patch new file mode 100644 index 000000000..cd5433395 --- /dev/null +++ b/tracebox/patches/105-configure-header.patch @@ -0,0 +1,10 @@ +--- a/configure.ac 2023-07-04 18:25:34.419067107 +0200 ++++ b/configure.ac 2023-07-04 18:25:42.558931140 +0200 +@@ -58,7 +58,6 @@ + esac ], + [ + AX_PROG_LUA +- AX_LUA_HEADERS + AX_LUA_LIBS + if test x"$LUA_LIB" = x; then + AC_MSG_ERROR([Lua library not found. You may try option --with-lua-suffix.]) From b8e40b5cde23688e259eb3ca2784becae7a36ecd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Jul 2023 08:47:58 +0200 Subject: [PATCH 0991/2059] Fix sqm-autorate init --- luci-app-sqm-autorate/root/etc/init.d/sqm-autorate | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 1485c924f..97c44e92e 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -21,13 +21,13 @@ _config_autorate() { config_get autorate "$1" autorate [ "${autorate}" != "1" ] && return - config_get min_download "$1" min_download - config_get download "$1" download - config_get max_download "$1" max_download + config_get min_download "$1" min_download "0" + config_get download "$1" download "0" + config_get max_download "$1" max_download "0" [ "${min_download}" == "0" ] || [ "${max_download}" == "0" ] || [ "${download}" == "0" ] && return - config_get min_upload "$1" min_upload - config_get upload "$1" upload - config_get max_upload "$1" max_upload + config_get min_upload "$1" min_upload "0" + config_get upload "$1" upload "0" + config_get max_upload "$1" max_upload "0" [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return # config_get interface "$1" interface # cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh From 8b270e72647b29763f3facf739c138a93f6fd374 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 7 Jul 2023 17:24:11 +0200 Subject: [PATCH 0992/2059] Fix omr-bypass --- luci-app-omr-bypass/Makefile | 6 +++++- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index bca6d24e6..8d166a2e4 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -7,7 +7,11 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables -LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +iptables +sqlite3-cli +LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +iptables-mod-extra +iptables +sqlite3-cli +ifneq ($(CONFIG_TARGET_ramips),) + LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +endif + PKG_LICENSE:=GPLv3 diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 31045864d..c59107f8d 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -1008,7 +1008,8 @@ start_service() { sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass config_foreach _add_proto_without_ndpi proto - sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst + sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst.new + mv /usr/share/omr-bypass/omr-bypass-proto.lst.new /usr/share/omr-bypass/omr-bypass-proto.lst logger -t "omr-bypass" "OMR-ByPass is running" } From ecf0b8979861a7c14c017acb6ee316e29e5eae9a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 7 Jul 2023 20:02:40 +0200 Subject: [PATCH 0993/2059] Update sqm autorate --- .../root/etc/init.d/sqm-autorate | 10 +- .../usr/share/sqm-autorate/cake-autorate.sh | 535 +++++++++++------- ...utorate_template.sh => config_template.sh} | 14 +- ...{cake-autorate_defaults.sh => defaults.sh} | 2 + ...{cake-autorate_launcher.sh => launcher.sh} | 4 +- .../{cake-autorate_lib.sh => lib.sh} | 95 ++-- 6 files changed, 407 insertions(+), 253 deletions(-) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_template.sh => config_template.sh} (95%) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_defaults.sh => defaults.sh} (99%) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_launcher.sh => launcher.sh} (77%) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_lib.sh => lib.sh} (66%) diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 97c44e92e..3f2d5c87d 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -31,14 +31,14 @@ _config_autorate() { [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return # config_get interface "$1" interface # cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh - cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.$1.sh + cp /usr/share/sqm-autorate/config_template.sh /usr/share/sqm-autorate/config.$1.sh } _launch_autorate() { logger -t "SQM-autorate" "Launch..." procd_open_instance # shellcheck disable=SC2086 - procd_set_param command /usr/share/sqm-autorate/cake-autorate_launcher.sh + procd_set_param command /usr/share/sqm-autorate/launcher.sh procd_set_param limits nofile="51200 51200" procd_set_param respawn 0 10 0 procd_set_param stderr 1 @@ -46,16 +46,12 @@ _launch_autorate() { } start_service() { + rm -f /usr/share/sqm-autorate/config.*.sh config_load sqm config_foreach _config_autorate queue _launch_autorate } -stop_service() { - rm -f /usr/share/sqm-autorate/cake-autorate_config.*.sh - pkill -9 cake-autorate -} - reload_service() { stop start diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh index e45c1c306..6067cdca8 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh @@ -1,22 +1,22 @@ #!/bin/bash -# CAKE-autorate automatically adjusts CAKE bandwidth(s) +# cake-autorate automatically adjusts CAKE bandwidth(s) # in dependence on: a) receive and transmit transfer rates; and b) latency # (or can just be used to monitor and log transfer rates and latency) -# requires packages: bash; and one of the supported ping binaries +# requires: bash; and one of the supported ping binaries # each cake-autorate instance must be configured using a corresponding config file # Project homepage: https://github.com/lynxthecat/cake-autorate # Licence details: https://github.com/lynxthecat/cake-autorate/blob/master/LICENCE.md -# Author: @Lynx (OpenWrt forum) -# Inspiration taken from: @moeller0 (OpenWrt forum) +# Author and maintainer: lynxthecat +# Contributors: rany2; moeller0; richb-hanover cake_autorate_version="2.0.0" -## cake-autorate uses multiple asynchronous processes including +## cake-autorate uses multiple asynchronous processes including: ## main - main process ## monitor_achieved_rates - monitor network transfer rates ## maintain_pingers - manage pingers and active reflectors @@ -26,7 +26,7 @@ cake_autorate_version="2.0.0" ## ## IPC is facilitated via FIFOs in the form of anonymous pipes ## accessible via fds in the form: ${process_name_fd} -## thereby to enable transferring commands and data between processes +## thereby to enable transferring instructions and data between processes # Initialize file descriptors ## -1 signifies that the log file fd will not be used and @@ -60,15 +60,20 @@ export LC_ALL=C # Set PREFIX PREFIX=/root/cake-autorate -# shellcheck source=cake-autorate_lib.sh -. "${PREFIX}/cake-autorate_lib.sh" -# shellcheck source=cake-autorate_defaults.sh -. "${PREFIX}/cake-autorate_defaults.sh" +# shellcheck source=lib.sh +. "${PREFIX}/lib.sh" +# shellcheck source=defaults.sh +. "${PREFIX}/defaults.sh" +# get valid config overrides +mapfile -t valid_config_entries < <(grep -E '^[^(#| )].*=' "${PREFIX}/defaults.sh" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') trap cleanup_and_killall INT TERM EXIT cleanup_and_killall() { + # Do not fail on error for this critical cleanup code + set +e + trap true INT TERM EXIT log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" @@ -88,13 +93,19 @@ cleanup_and_killall() # terminate any processes that remain, save for main and intercept_stderr unset "proc_pids[main]" - intercept_stderr_pid="${proc_pids[intercept_stderr]}" - unset "proc_pids[intercept_stderr]" + intercept_stderr_pid="${proc_pids[intercept_stderr]:-}" + if [[ -n "${intercept_stderr_pid}" ]] + then + unset "proc_pids[intercept_stderr]" + fi terminate "${proc_pids[@]}" # restore original stderr, and terminate intercept_stderr - exec 2>&"${original_stderr_fd}" - terminate "${intercept_stderr_pid}" + if [[ -n "${intercept_stderr_pid}" ]] + then + exec 2>&"${original_stderr_fd}" + terminate "${intercept_stderr_pid}" + fi log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}" @@ -109,38 +120,36 @@ log_msg() local type="${1}" local msg="${2}" local instance_id="${instance_id:-"unknown"}" + local log_timestamp=${EPOCHREALTIME} case ${type} in DEBUG) - [[ "${debug}" == "0" ]] && return # skip over DEBUG messages where debug disabled - log_timestamp=${EPOCHREALTIME} + ((debug == 0)) && return # skip over DEBUG messages where debug disabled ((log_DEBUG_messages_to_syslog)) && ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" ;; - + ERROR) - log_timestamp=${EPOCHREALTIME} ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" ;; SYSLOG) - log_timestamp=${EPOCHREALTIME} ((use_logger)) && logger -t "cake-autorate.${instance_id}" "INFO: ${log_timestamp} ${msg}" ;; *) - log_timestamp=${EPOCHREALTIME} ;; esac - + # Output to the log file fifo if available (for rotation handling) # else output directly to the log file - if (( log_fd >= 0 )); then + if (( log_fd >= 0 )) + then ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >&"${log_fd}" else ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >> "${log_file_path}" fi - + ((terminal)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" } @@ -172,7 +181,7 @@ rotate_log_file() cat "${log_file_path}" > "${log_file_path}.old" true > "${log_file_path}" fi - + ((output_processing_stats)) && print_headers t_log_file_start_us=${EPOCHREALTIME/./} get_log_file_size_bytes @@ -211,14 +220,15 @@ generate_log_file_scripts() while [[ ! -f "${run_path}/last_log_file_export" ]] do sleep 1 - if (( ++read_try >= \${timeout_s} )); then + if (( ++read_try >= \${timeout_s} )) + then printf "ERROR: Timeout (\${timeout_s}s) reached before new log file export identified.\n" >&2 exit 1 fi done read -r log_file_export_path < "${run_path}/last_log_file_export" - + printf "Log file export complete.\n" printf "Log file available at location: " @@ -249,31 +259,35 @@ export_log_file() log_msg "DEBUG" "Exporting log file with path: ${log_file_path/.log/_${log_file_export_datetime}.log}" # Now export with or without compression to the appropriate export path - if ((log_file_export_compress)); then + if ((log_file_export_compress)) + then log_file_export_path="${log_file_export_path}.gz" - if [[ -f "${log_file_path}.old" ]]; then + if [[ -f "${log_file_path}.old" ]] + then gzip -c "${log_file_path}.old" > "${log_file_export_path}" gzip -c "${log_file_path}" >> "${log_file_export_path}" else gzip -c "${log_file_path}" > "${log_file_export_path}" fi else - if [[ -f "${log_file_path}.old" ]]; then + if [[ -f "${log_file_path}.old" ]] + then cp "${log_file_path}.old" "${log_file_export_path}" cat "${log_file_path}" >> "${log_file_export_path}" else cp "${log_file_path}" "${log_file_export_path}" fi fi - + printf '%s' "${log_file_export_path}" > "${run_path}/last_log_file_export" } flush_log_fd() { log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - while read -r -t 0.01 -u "${log_fd}" log_line + while read -r -t 0 -u "${log_fd}" do + read -r -u "${log_fd}" log_line printf '%s\n' "${log_line}" >> "${log_file_path}" done } @@ -321,7 +335,7 @@ maintain_log_file() # Verify log file time < configured maximum if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) then - + log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so flushing and rotating log file." flush_log_fd rotate_log_file @@ -342,7 +356,7 @@ maintain_log_file() done } -get_next_shaper_rate() +update_shaper_rate() { local direction="${1}" # 'dl' or 'ul' @@ -358,7 +372,8 @@ get_next_shaper_rate() ;; # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period *bb*) - if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps["${direction}"]*achieved_rate_adjust_down_bufferbloat)/1000 )) adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_bufferbloat)/1000 )) shaper_rate_kbps["${direction}"]=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps["${direction}"] && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) @@ -366,19 +381,23 @@ get_next_shaper_rate() fi ;; # high load, so increase rate providing not inside bufferbloat refractory period - *high*) - if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then + *high*) + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then shaper_rate_kbps["${direction}"]=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_high)/1000 )) fi ;; # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate *low*|*idle*) - if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )); then + if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )) + then - if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])); then + if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])) + then decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_load_low)/1000 )) shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) - elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])); then + elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])) + then decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_low)/1000 )) shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) fi @@ -387,7 +406,7 @@ get_next_shaper_rate() fi ;; *) - log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in get_next_shaper_rate" + log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in update_shaper_rate" kill $$ 2>/dev/null ;; esac @@ -431,17 +450,17 @@ monitor_achieved_rates() case "${command[0]:-}" in SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi ;; SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] - then - declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" - fi - ;; + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; TERMINATE) log_msg "DEBUG" "Terminating monitor_achieved_rates." exit @@ -457,8 +476,8 @@ monitor_achieved_rates() [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes="${prev_rx_bytes}" [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes="${prev_tx_bytes}" - achieved_rate_kbps[dl]=$(( ((8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) - achieved_rate_kbps[ul]=$(( ((8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) + achieved_rate_kbps[dl]=$(( (8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us )) + achieved_rate_kbps[ul]=$(( (8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us )) ((achieved_rate_kbps[dl]<0)) && achieved_rate_kbps[dl]=0 ((achieved_rate_kbps[ul]<0)) && achieved_rate_kbps[ul]=0 @@ -468,14 +487,15 @@ monitor_achieved_rates() load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) - + for pinger_fd in "${pinger_fds[@]:?}" do printf "SET_ARRAY_ELEMENT load_percent dl %s\n" "${load_percent[dl]}" >&"${pinger_fd}" printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}" done - if ((output_load_stats)); then + if ((output_load_stats)) + then printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" log_msg "LOAD" "${load_stats}" @@ -485,7 +505,7 @@ monitor_achieved_rates() prev_tx_bytes="${tx_bytes}" compensated_monitor_achieved_rates_interval_us=$(( monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) - + sleep_remaining_tick_time "${t_start_us}" "${compensated_monitor_achieved_rates_interval_us}" done @@ -498,26 +518,30 @@ classify_load() # thus ending up with high_delayed, low_delayed, etc. local direction="${1}" - if (( load_percent["${direction}"] > high_load_thr_percent )); then - load_condition["${direction}"]="high" - elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )); then + if (( load_percent["${direction}"] > high_load_thr_percent )) + then + load_condition["${direction}"]="high" + elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )) + then load_condition["${direction}"]="low" - else + else load_condition["${direction}"]="idle" fi - + ((bufferbloat_detected["${direction}"])) && load_condition["${direction}"]="${load_condition[${direction}]}_bb" - if ((sss_compensation)); then + if ((sss_compensation)) + then # shellcheck disable=SC2154 for sss_time_us in "${sss_times_us[@]}" do ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) - if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )); then + if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )) + then load_condition["${direction}"]="${load_condition[${direction}]}_sss" break fi - done + done fi load_condition["${direction}"]="${direction}_${load_condition[${direction}]}" @@ -530,14 +554,14 @@ parse_preprocessor() # prepend REFLECTOR_RESPONSE and append timestamp as a checksum while read -r timestamp remainder do - printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" + printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" done } parse_tsping() { trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT local parse_id="${1}" local reflectors=("${@:2}") @@ -560,7 +584,7 @@ parse_tsping() declare -A load_percent load_percent[dl]=0 load_percent[ul]=0 - + while true do unset command @@ -574,7 +598,7 @@ parse_tsping() ;; START_PINGER) - + exec {parse_preprocessor_fd}> >(parse_preprocessor) parse_preprocessor_pid="${!}" printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" @@ -609,7 +633,7 @@ parse_tsping() SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -617,8 +641,8 @@ parse_tsping() ;; SET_ARRAY_ELEMENT) - - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -697,7 +721,7 @@ parse_tsping() printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi done @@ -706,7 +730,7 @@ parse_tsping() parse_fping() { trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT local parse_id="${1}" @@ -732,7 +756,7 @@ parse_fping() load_percent[ul]=0 t_start_us="${EPOCHREALTIME/./}" - + while true do unset command @@ -781,7 +805,7 @@ parse_fping() SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -790,7 +814,7 @@ parse_fping() SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -807,7 +831,7 @@ parse_fping() continue ;; esac - fi + fi if [[ "${timestamp:-}" && "${reflector:-}" && "${seq_rtt:-}" && "${checksum:-}" ]] then @@ -819,7 +843,7 @@ parse_fping() rtt_us="${BASH_REMATCH[3]}000" rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) - + dl_owd_us=$((rtt_us/2)) ul_owd_us="${dl_owd_us}" @@ -842,28 +866,28 @@ parse_fping() printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" timestamp_us="${timestamp//[.]}" - + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi done } # IPUTILS-PING FUNCTIONS -parse_ping() +parse_ping() { trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT # ping reflector, maintain baseline and output deltas to a common fifo local parse_id="${1}" local reflector="${2}" - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" declare -A dl_owd_baselines_us @@ -879,7 +903,7 @@ parse_ping() declare -A load_percent load_percent[dl]=0 load_percent[ul]=0 - + while true do unset command @@ -914,9 +938,9 @@ parse_ping() SET_REFLECTOR) - if [[ "${command[1]:-}" ]] + if [[ "${#command[@]}" -eq 2 ]] then - reflector="${command[1]}" + reflector="${command[1]}" log_msg "DEBUG" "Read in new reflector: ${reflector}" dl_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]:-100000}" ul_owd_baselines_us["${reflector}"]="${ul_owd_baselines_us[${reflector}]:-100000}" @@ -928,7 +952,7 @@ parse_ping() SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -937,7 +961,7 @@ parse_ping() SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -1034,23 +1058,23 @@ start_pinger() start_pingers() { - # Initiate pingers - log_msg "DEBUG" "Starting pingers." + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + case ${pinger_binary} in tsping|fping) start_pinger 0 - ;; + ;; ping) for ((pinger=0; pinger < no_pingers; pinger++)) do start_pinger "${pinger}" done - ;; + ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" kill $$ 2>/dev/null - ;; + ;; esac } @@ -1061,7 +1085,7 @@ sleep_until_next_pinger_time_slot() # whilst ensuring pings will remain spaced out appropriately to maintain granularity local pinger="${1}" - + t_start_us=${EPOCHREALTIME/./} time_to_next_time_slot_us=$(( (reflector_ping_interval_us-(t_start_us-pingers_t_start_us)%reflector_ping_interval_us) + pinger*ping_response_interval_us )) sleep_remaining_tick_time "${t_start_us}" "${time_to_next_time_slot_us}" @@ -1070,7 +1094,7 @@ sleep_until_next_pinger_time_slot() kill_pinger() { local pinger="${1}" - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" case "${pinger_binary}" in @@ -1079,7 +1103,6 @@ kill_pinger() ;; *) - : ;; esac @@ -1088,6 +1111,8 @@ kill_pinger() kill_pingers() { + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + case "${pinger_binary}" in tsping|fping) @@ -1116,12 +1141,13 @@ replace_pinger_reflector() # ${reflectors[no_pingers]} is then unset # and the the bad reflector moved to the back of the queue (last element in ${reflectors[]}) # and finally the indices for ${reflectors} are updated to reflect the new order - + local pinger="${1}" - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - if ((no_reflectors > no_pingers)); then + if ((no_reflectors > no_pingers)) + then log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}." kill_pinger "${pinger}" bad_reflector=${reflectors[pinger]} @@ -1133,19 +1159,19 @@ replace_pinger_reflector() reflectors+=("${bad_reflector}") # reset array indices mapfile -t reflectors < <(for i in "${reflectors[@]}"; do printf '%s\n' "${i}"; done) - # set up the new pinger with the new reflector and retain pid + # set up the new pinger with the new reflector and retain pid case ${pinger_binary} in tsping|fping) printf "SET_REFLECTORS %s\n" "${reflectors[*]:0:${no_pingers}}" >&"${pinger_fds[0]}" - ;; + ;; ping) printf "SET_REFLECTOR %s\n" "${reflectors[pinger]}" >&"${pinger_fds[pinger]}" - ;; + ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" kill $$ 2>/dev/null - ;; + ;; esac start_pinger "${pinger}" else @@ -1183,7 +1209,7 @@ kill_maintain_pingers() log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" kill $$ 2>/dev/null ;; - esac + esac exit } @@ -1197,18 +1223,19 @@ change_state_maintain_pingers() case "${maintain_pingers_next_state}" in START|STOP|PAUSED|RUNNING) - - if [[ "${maintain_pingers_state}" != "${maintain_pingers_next_state}" ]] + + if [[ "${maintain_pingers_state}" == "${maintain_pingers_next_state}" ]] then - log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" - maintain_pingers_state=${maintain_pingers_next_state} - else log_msg "ERROR" "Received request to change maintain_pingers state to existing state." + return fi + + log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" + maintain_pingers_state=${maintain_pingers_next_state} ;; *) - + log_msg "ERROR" "Received unrecognized state change request: ${maintain_pingers_next_state}. Exiting now." kill $$ 2>/dev/null ;; @@ -1221,7 +1248,7 @@ maintain_pingers() trap '' INT trap 'kill_maintain_pingers' TERM EXIT - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" declare -A dl_owd_baselines_us @@ -1234,9 +1261,9 @@ maintain_pingers() reflector_offences_idx=0 pingers_active=0 - pingers_t_start_us="${EPOCHREALTIME/./}" - t_last_reflector_replacement_us="${EPOCHREALTIME/./}" - t_last_reflector_comparison_us="${EPOCHREALTIME/./}" + pingers_t_start_us="${EPOCHREALTIME/./}" + t_last_reflector_replacement_us="${EPOCHREALTIME/./}" + t_last_reflector_comparison_us="${EPOCHREALTIME/./}" for ((reflector=0; reflector < no_reflectors; reflector++)) do @@ -1292,7 +1319,7 @@ maintain_pingers() case "${command[0]:-}" in CHANGE_STATE) - if [[ "${command[1]:-}" ]] + if [[ "${#command[@]}" -eq 2 ]] then change_state_maintain_pingers "${command[1]}" # break out of reading any new IPC commands to handle next state @@ -1308,13 +1335,13 @@ maintain_pingers() fi ;; SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi ;; SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -1327,8 +1354,8 @@ maintain_pingers() : ;; esac - done - + done + case "${maintain_pingers_state}" in START) @@ -1348,24 +1375,25 @@ maintain_pingers() fi change_state_maintain_pingers "PAUSED" ;; - + PAUSED) ;; - + RUNNING) if (( t_start_us>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) then - pinger=$((RANDOM%no_pingers)) + pinger=$((RANDOM%no_pingers)) log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." replace_pinger_reflector "${pinger}" - t_last_reflector_replacement_us=${EPOCHREALTIME/./} + t_last_reflector_replacement_us=${EPOCHREALTIME/./} continue fi - if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then + if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )) + then - t_last_reflector_comparison_us=${EPOCHREALTIME/./} + t_last_reflector_comparison_us=${EPOCHREALTIME/./} [[ "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" ]] || continue @@ -1431,16 +1459,19 @@ maintain_pingers() # shellcheck disable=SC2154 reflector_offences[reflector_offences_idx]=$(( (${EPOCHREALTIME/./}-last_timestamp_reflectors_us[${reflectors[pinger]}]) > reflector_response_deadline_us ? 1 : 0 )) - if (( reflector_offences[reflector_offences_idx] )); then + if (( reflector_offences[reflector_offences_idx] )) + then ((sum_reflector_offences[pinger]++)) log_msg "DEBUG" "no ping response from reflector: ${reflectors[pinger]} within reflector_response_deadline: ${reflector_response_deadline_s}s" log_msg "DEBUG" "reflector=${reflectors[pinger]}, sum_reflector_offences=${sum_reflector_offences[pinger]} and reflector_misbehaving_detection_thr=${reflector_misbehaving_detection_thr}" fi - if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )); then + if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )) + then log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving." - if ((replace_pinger_reflector_enabled)); then + if ((replace_pinger_reflector_enabled)) + then replace_pinger_reflector "${pinger}" replace_pinger_reflector_enabled=0 else @@ -1462,39 +1493,26 @@ maintain_pingers() done } -set_cake_rate() +set_shaper_rate() { - local interface="${1}" - local shaper_rate_kbps="${2}" - local adjust_shaper_rate="${3}" - - ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface} cake bandwidth ${shaper_rate_kbps}Kbit" + # fire up tc and update max_wire_packet_compensation if there are rates to change for the given direction - if ((adjust_shaper_rate)); then + local direction="${1}" # 'dl' or 'ul' - tc qdisc change root dev "${interface}" cake bandwidth "${shaper_rate_kbps}Kbit" 2> /dev/null + if (( shaper_rate_kbps["${direction}"] != last_shaper_rate_kbps["${direction}"] )) + then + ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface[${direction}]} cake bandwidth ${shaper_rate_kbps[${direction}]}Kbit" - else - ((output_cake_changes)) && log_msg "DEBUG" "adjust_shaper_rate set to 0 in config, so skipping the tc qdisc change call" - fi -} - -set_shaper_rates() -{ - if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] || shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then - - # fire up tc in each direction if there are rates to change, and if rates change in either direction then update max wire calcs - if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] )); then - set_cake_rate "${dl_if}" "${shaper_rate_kbps[dl]}" adjust_dl_shaper_rate - printf "SET_ARRAY_ELEMENT shaper_rate_kbps dl %s\n" "${shaper_rate_kbps[dl]}" >&"${monitor_achieved_rates_fd}" - last_shaper_rate_kbps[dl]="${shaper_rate_kbps[dl]}" - fi - if (( shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then - set_cake_rate "${ul_if}" "${shaper_rate_kbps[ul]}" adjust_ul_shaper_rate - printf "SET_ARRAY_ELEMENT shaper_rate_kbps ul %s\n" "${shaper_rate_kbps[ul]}" >&"${monitor_achieved_rates_fd}" - last_shaper_rate_kbps[ul]="${shaper_rate_kbps[ul]}" + if ((adjust_shaper_rate["${direction}"])) + then + tc qdisc change root dev "${interface[${direction}]}" cake bandwidth "${shaper_rate_kbps[${direction}]}Kbit" 2> /dev/null + else + ((output_cake_changes)) && log_msg "DEBUG" "adjust_${direction}_shaper_rate set to 0 in config, so skipping the corresponding tc qdisc change call." fi + printf "SET_ARRAY_ELEMENT shaper_rate_kbps ${direction} %s\n" "${shaper_rate_kbps[${direction}]}" >&"${monitor_achieved_rates_fd}" + last_shaper_rate_kbps["${direction}"]="${shaper_rate_kbps[${direction}]}" + update_max_wire_packet_compensation fi } @@ -1504,7 +1522,8 @@ set_min_shaper_rates() log_msg "DEBUG" "Enforcing minimum shaper rates." shaper_rate_kbps[dl]=${min_dl_shaper_rate_kbps} shaper_rate_kbps[ul]=${min_ul_shaper_rate_kbps} - set_shaper_rates + set_shaper_rate "dl" + set_shaper_rate "ul" } get_max_wire_packet_size_bits() @@ -1564,6 +1583,8 @@ change_state_main() { local main_next_state="${1}" + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + case ${main_next_state} in RUNNING|IDLE|STALL) @@ -1624,7 +1645,8 @@ debug_cmd() err_type="ERROR" - if ((err_silence)); then + if ((err_silence)) + then err_type="DEBUG" fi @@ -1633,7 +1655,8 @@ debug_cmd() caller_id=$(caller) - if ((ret==0)); then + if ((ret==0)) + then log_msg "DEBUG" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=SUCCESS" else [[ "${err_type}" == "DEBUG" && "${debug}" == "0" ]] && return # if debug disabled, then skip on DEBUG but not on ERROR @@ -1650,6 +1673,52 @@ debug_cmd() fi } +# shellcheck disable=SC1090,SC2311 +validate_config_entry() { + # Must be called before loading config_path into the global scope. + # + # When the entry is invalid, two types are returned with the first type + # being the invalid user type and second type is the default type with + # the user needing to adapt the config file so that the entry uses the + # default type. + # + # When the entry is valid, one type is returned and it will be the + # the type of either the default or user type. However because in that + # case they are both valid. It doesn't matter as they'd both have the + # same type. + + local config_path="${1}" + + local user_type + local valid_type + + user_type=$(unset "${2}" && . "${config_path}" && typeof "${2}") + valid_type=$(typeof "${2}") + + if [[ "${user_type}" != "${valid_type}" ]] + then + printf '%s' "${user_type} ${valid_type}" + return + elif [[ "${user_type}" != "string" ]] + then + printf '%s' "${valid_type}" + return + fi + + # extra validation for string, check for empty string + local -n default_value=${2} + local user_value + user_value=$(. "${config_path}" && local -n x="${2}" && printf '%s' "${x}") + + # if user is empty but default is not, invalid entry + if [[ -z "${user_value}" && -n "${default_value}" ]] + then + printf '%s' "${user_type} ${valid_type}" + else + printf '%s' "${valid_type}" + fi +} + # ======= Start of the Main Routine ======== [[ -t 1 ]] && terminal=1 || terminal=0 @@ -1663,35 +1732,78 @@ log_file_path=/var/log/cake-autorate.log run_path=/var/run/cake-autorate/ # cake-autorate first argument is config file path -if [[ -n ${1-} ]]; then +if [[ -n "${1-}" ]] +then config_path="${1}" else - config_path="${PREFIX}/cake-autorate_config.primary.sh" + config_path="${PREFIX}/config.primary.sh" fi -if [[ ! -f "${config_path}" ]]; then +if [[ ! -f "${config_path}" ]] +then log_msg "ERROR" "No config file found. Exiting now." - exit + exit 1 fi -# shellcheck source=cake-autorate_config.primary.sh +# validate config entries before loading +mapfile -t user_config < <(grep -E '^[^(#| )].*=' "${config_path}" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') +config_error_count=0 +for key in "${user_config[@]}" +do + # Despite the fact that config_file_check is no longer required, + # we make an exemption just in this case as that variable in + # particular does not have any real impact to the operation + # of the script. + [[ "${key}" == "config_file_check" ]] && continue + + # shellcheck disable=SC2076 + if [[ ! " ${valid_config_entries[*]} " =~ " ${key} " ]] + then + ((config_error_count++)) + log_msg "ERROR" "The key: '${key}' in config file: '${config_path}' is not a valid config entry." + else + # shellcheck disable=SC2311 + read -r user supposed <<< "$(validate_config_entry "${config_path}" "${key}")" + if [[ -n "${supposed}" ]] + then + error_msg="The value of '${key}' in config file: '${config_path}' is not a valid value of type: '${supposed}'." + + case "${user}" in + negative-*) error_msg="${error_msg} Also, negative numbers are not supported." ;; + *) ;; + esac + + log_msg "ERROR" "${error_msg}" + unset error_msg + + ((config_error_count++)) + fi + unset user supposed + fi +done +if ((config_error_count)) +then + log_msg "ERROR" "The config file: '${config_path}' contains ${config_error_count} error(s). Exiting now." + exit 1 +fi +unset valid_config_entries user_config config_error_count key + +# shellcheck source=config.primary.sh . "${config_path}" -if [[ ${config_file_check} != "cake-autorate" ]]; then - log_msg "ERROR" "Config file error. Please check config file entries." - exit -fi - -if [[ ${config_path} =~ cake-autorate_config\.(.*)\.sh ]]; then - instance_id=${BASH_REMATCH[1]} - run_path=/var/run/cake-autorate/${instance_id} +if [[ ${config_path} =~ config\.(.*)\.sh ]] +then + instance_id="${BASH_REMATCH[1]}" + run_path="/var/run/cake-autorate/${instance_id}" else - log_msg "ERROR" "Instance identifier 'X' set by cake-autorate_config.X.sh cannot be empty. Exiting now." - exit + log_msg "ERROR" "Instance identifier 'X' set by config.X.sh cannot be empty. Exiting now." + exit 1 fi -if [[ -n "${log_file_path_override-}" ]]; then - if [[ ! -d ${log_file_path_override} ]]; then +if [[ -n "${log_file_path_override-}" ]] +then + if [[ ! -d ${log_file_path_override} ]] + then broken_log_file_path_override=${log_file_path_override} log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log log_msg "ERROR" "Log file path override: '${broken_log_file_path_override}' does not exist. Exiting now." @@ -1714,7 +1826,8 @@ log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${conf # ${run_path}/ is used to store temporary files # it should not exist on startup so if it does exit, else create the directory -if [[ -d "${run_path}" ]]; then +if [[ -d "${run_path}" ]] +then if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' "${run_path}/proc_pids") && [[ -d "/proc/${running_main_pid}" ]] then log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script." @@ -1731,7 +1844,7 @@ fi proc_pids['main']="${BASHPID}" -no_reflectors=${#reflectors[@]} +no_reflectors=${#reflectors[@]} # Check ping binary exists command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${pinger_binary} does not exist. Exiting script."; exit; } @@ -1745,9 +1858,10 @@ command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${p # Check bufferbloat detection threshold not greater than window length (( bufferbloat_detection_thr > bufferbloat_detection_window )) && { log_msg "ERROR" "bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } -# Passed error checks +# Passed error checks -if ((log_to_file)); then +if ((log_to_file)) +then log_file_max_time_us=$((log_file_max_time_mins*60000000)) log_file_max_size_bytes=$((log_file_max_size_KB*1024)) exec {log_fd}<> <(:) @@ -1756,13 +1870,15 @@ if ((log_to_file)); then fi # test if stdout is a tty (terminal) -if ! ((terminal)); then +if ! ((terminal)) +then echo "stdout not a terminal so redirecting output to: ${log_file_path}" ((log_to_file)) && exec 1>&"${log_fd}" fi # Initialize rx_bytes_path and tx_bytes_path if not set -if [[ -z "${rx_bytes_path-}" ]]; then +if [[ -z "${rx_bytes_path-}" ]] +then case "${dl_if}" in veth*) rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" @@ -1775,7 +1891,8 @@ if [[ -z "${rx_bytes_path-}" ]]; then ;; esac fi -if [[ -z "${tx_bytes_path-}" ]]; then +if [[ -z "${tx_bytes_path-}" ]] +then case "${ul_if}" in veth*) tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" @@ -1789,7 +1906,8 @@ if [[ -z "${tx_bytes_path-}" ]]; then esac fi -if ((debug)) ; then +if ((debug)) +then log_msg "DEBUG" "CAKE-autorate version: ${cake_autorate_version}" log_msg "DEBUG" "config_path: ${config_path}" log_msg "DEBUG" "run_path: ${run_path}" @@ -1856,6 +1974,8 @@ declare -A last_shaper_rate_kbps declare -A base_shaper_rate_kbps declare -A min_shaper_rate_kbps declare -A max_shaper_rate_kbps +declare -A interface +declare -A adjust_shaper_rate base_shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" base_shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" @@ -1872,10 +1992,19 @@ shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" last_shaper_rate_kbps[dl]=0 last_shaper_rate_kbps[ul]=0 +interface[dl]="${dl_if}" +interface[ul]="${ul_if}" + +adjust_shaper_rate[dl]="${adjust_dl_shaper_rate}" +adjust_shaper_rate[ul]="${adjust_ul_shaper_rate}" + +dl_max_wire_packet_size_bits=0 +ul_max_wire_packet_size_bits=0 get_max_wire_packet_size_bits "${dl_if}" dl_max_wire_packet_size_bits get_max_wire_packet_size_bits "${ul_if}" ul_max_wire_packet_size_bits -set_shaper_rates +set_shaper_rate "dl" +set_shaper_rate "ul" update_max_wire_packet_compensation @@ -1899,13 +2028,16 @@ delays_idx=0 sum_dl_delays=0 sum_ul_delays=0 -if ((debug)); then - if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )); then +if ((debug)) +then + if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )) + then log_msg "DEBUG" "Warning: bufferbloat refractory period: ${bufferbloat_refractory_period_us} us." log_msg "DEBUG" "Warning: but expected time to overwrite samples in bufferbloat detection window is: $((bufferbloat_detection_window*ping_response_interval_us)) us." log_msg "DEBUG" "Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." fi - if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )); then + if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )) + then log_msg "DEBUG" "Warning: reflector_response_deadline_s < 2*reflector_ping_interval_s" log_msg "DEBUG" "Warning: consider setting an increased reflector_response_deadline." fi @@ -1915,7 +2047,8 @@ fi ((randomize_reflectors)) && randomize_array reflectors # Wait if ${startup_wait_s} > 0 -if ((startup_wait_us>0)); then +if ((startup_wait_us>0)) +then log_msg "DEBUG" "Waiting ${startup_wait_s} seconds before startup." sleep_us "${startup_wait_us}" fi @@ -1924,7 +2057,8 @@ case "${pinger_binary}" in tsping|fping) exec {pinger_fds[0]}<> <(:) - ;; + ;; + ping) for ((pinger=0; pinger<=no_pingers; pinger++)) do @@ -1932,9 +2066,9 @@ case "${pinger_binary}" in done ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + exit ;; esac @@ -1964,19 +2098,19 @@ do ;; SET_VAR) - if [[ ${command[1]:-} && ${command[2]:-} ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi ;; SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi ;; SET_PROC_PID) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -2002,7 +2136,8 @@ do reflectors_last_timestamp_us="${timestamp//[.]}" - if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )); then + if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )) + then log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." continue fi @@ -2028,19 +2163,23 @@ do classify_load "dl" classify_load "ul" - get_next_shaper_rate "dl" - get_next_shaper_rate "ul" + update_shaper_rate "dl" + update_shaper_rate "ul" - set_shaper_rates + set_shaper_rate "dl" + set_shaper_rate "ul" - if (( output_processing_stats )); then + if (( output_processing_stats )) + then printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${load_percent[dl]}" "${load_percent[ul]}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${load_condition[dl]}" "${load_condition[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" log_msg "DATA" "${processing_stats}" fi # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) - if (( enable_sleep_function )); then - if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]]; then + if (( enable_sleep_function )) + then + if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]] + then ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) if ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) then @@ -2124,7 +2263,7 @@ do *) log_msg "ERROR" "Unrecognized main state: ${main_state}. Exiting now." - kill $$ 2>/dev/null + exit 1 ;; esac diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh similarity index 95% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh index b430d82d0..04a366a63 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh @@ -9,7 +9,7 @@ INTERFACE=$(basename "$1" | cut -d. -f2) -cake_autorate_version="2.0.0" +#cake_autorate_version="2.0.0" # *** OUTPUT AND LOGGING OPTIONS *** @@ -46,7 +46,7 @@ ul_if=$(uci -q get sqm.${INTERFACE}.interface) # upload interface # fping - round robin pinging (rtts) # ping - (iputils-ping) individual pinging (rtts) # hping3 - individidual pinging (owds) -pinger_binary=tsping +pinger_binary=$(uci -q get sqm.${INTERFACE}.pinger || echo 'tsping') # list of reflectors to use and number of pingers to initiate # pingers will be initiated with reflectors in the order specified in the list @@ -77,12 +77,8 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # delay threshold in ms is the extent of OWD increase to classify as a delay # these are automatically adjusted based on maximum on the wire packet size # (adjustment significant at sub 12Mbit/s rates, else negligible) -latency=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) -[ -z "$latency" ] && latency="$(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30))" -[ -z "$latency" ] && latency="100" -logger -t "sqm" "latency $INTERFACE: $latency" -dl_delay_thr_ms="$latency" # (milliseconds) -ul_delay_thr_ms="$latency" # (milliseconds) +dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) || $(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30)) || echo 100 # (milliseconds) +ul_delay_thr_ms=${dl_delay_thr_ms} # Set either of the below to 0 to adjust one direction only # or alternatively set both to 0 to simply use cake-autorate to monitor a connection @@ -195,7 +191,7 @@ reflector_misbehaving_detection_thr=3 reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list reflector_comparison_interval_mins=1 # how often to compare reflectors -reflector_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines before reflector rotated +#reflector_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines before reflector rotated reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated # stall is detected when the following two conditions are met: diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh similarity index 99% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh index 06dc9970b..1ef1af429 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh @@ -7,6 +7,8 @@ # Author: @Lynx (OpenWrt forum) # Inspiration taken from: @moeller0 (OpenWrt forum) +INTERFACE="" + # *** OUTPUT AND LOGGING OPTIONS *** output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh similarity index 77% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh index f708f328a..7cb3567df 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh @@ -1,6 +1,6 @@ #!/bin/bash -cake_instances=(/usr/share/sqm-autorate/cake-autorate_config*sh) +cake_instances=(/root/cake-autorate/config.*.sh) cake_instance_pids=() trap kill_cake_instances INT TERM EXIT @@ -20,7 +20,7 @@ kill_cake_instances() for cake_instance in "${cake_instances[@]}" do - /usr/share/sqm-autorate/cake-autorate.sh "${cake_instance}" & + /root/cake-autorate/cake-autorate.sh "${cake_instance}" & cake_instance_pids+=(${!}) done wait diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh similarity index 66% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh index 7743b5467..19141fc74 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh @@ -1,14 +1,63 @@ #!/bin/bash -# cake-autorate_lib.sh -- common functions for use by cake-autorate.sh + +# lib.sh -- common functions for use by cake-autorate.sh +# # This file is part of cake-autorate. __set_e=0 -if [[ ! ${-} =~ e ]]; then +if [[ ! ${-} =~ e ]] +then set -e __set_e=1 fi -exec {__sleep_fd}<> <(:) || true +if [[ -z "${__sleep_fd:-}" ]] +then + exec {__sleep_fd}<> <(:) +fi + +typeof() { + # typeof -- returns the type of a variable + + local type_sig + type_sig=$(declare -p "${1}" 2>/dev/null) + if [[ "${type_sig}" =~ "declare --" ]] + then + str_type "${1}" + elif [[ "${type_sig}" =~ "declare -a" ]] + then + printf "array" + elif [[ "${type_sig}" =~ "declare -A" ]] + then + printf "map" + else + printf "none" + fi +} + +str_type() { + # str_type -- returns the type of a string + + local -n str="${1}" + + if [[ "${str}" =~ ^[0-9]+$ ]] + then + printf "integer" + elif [[ "${str}" =~ ^[0-9]*\.[0-9]+$ ]] + then + printf "float" + elif [[ "${str}" =~ ^-[0-9]+$ ]] + then + printf "negative-integer" + elif [[ "${str}" =~ ^-[0-9]*\.[0-9]+$ ]] + then + printf "negative-float" + else + # technically not validated, user is just trusted to call + # this function with valid strings + printf "string" + fi +} sleep_s() { @@ -25,7 +74,7 @@ sleep_s() # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460074498 local sleep_duration_s=${1} # (seconds, e.g. 0.5, 1 or 1.5) - read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : + read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || true } sleep_us() @@ -52,21 +101,10 @@ sleep_remaining_tick_time() fi } -get_remaining_tick_time() -{ - # updates sleep_duration_s remaining to end of tick duration - - local t_start_us=${1} # (microseconds) - local tick_duration_us=${2} # (microseconds) - - sleep_duration_us=$(( t_start_us + tick_duration_us - ${EPOCHREALTIME/./} )) - ((sleep_duration_us<0)) && sleep_duration_us=0 - sleep_duration_s=000000${sleep_duration_us} - sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6} -} - randomize_array() { + # randomize the order of the elements of an array + local -n array=${1} subset=("${array[@]}") @@ -80,23 +118,6 @@ randomize_array() done } -lock() -{ - local path=${1} - - while true; do - ( set -o noclobber; echo "$$" > "${path:?}" ) 2> /dev/null && return 0 - sleep_us 100000 - done -} - -unlock() -{ - local path=${1} - - rm -f "${path:?}" -} - terminate() { # Send regular kill to processes and monitor terminations; @@ -105,7 +126,7 @@ terminate() # and, finally, call wait on all processes to reap any zombie processes. local pids=("${@:-}") - + kill "${pids[@]}" 2> /dev/null for((i=0; i<10; i++)) @@ -121,8 +142,8 @@ terminate() kill -9 "${pids[@]}" 2> /dev/null } - -if (( __set_e == 1 )); then +if (( __set_e == 1 )) +then set +e fi unset __set_e From 099c6cd947f5f35e676849bcb21e845238530df7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 11 Jul 2023 17:12:52 +0200 Subject: [PATCH 0994/2059] Fix DNS reset issue on IP 10.2* --- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 56050f14c..6c9667395 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -657,9 +657,9 @@ del_server_route6() { disable_pihole() { local server=$1 - if [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep '#53' | grep '10.2')" ]; then + if [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep '#53' | grep '10.255.25')" ]; then _log "Disable Pi-Hole..." - uci -q del_list dhcp.@dnsmasq[0].server="$(uci -q get dhcp.@dnsmasq[0].server | tr ' ' '\n' | grep '#53' | grep '10.2')" + uci -q del_list dhcp.@dnsmasq[0].server="$(uci -q get dhcp.@dnsmasq[0].server | tr ' ' '\n' | grep '#53' | grep '10.255.25')" if [ -z "$(uci -q get dhcp.@dnsmasq[0].server | grep '127.0.0.1#5353')" ]; then uci -q batch <<-EOF >/dev/null add_list dhcp.@dnsmasq[0].server='127.0.0.1#5353' From 377c34fd05e883b9ee11e58edf2c79e8595b3dc9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 14 Jul 2023 08:26:14 +0200 Subject: [PATCH 0995/2059] Disable sqm on VPN interface if not download/upload speed --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index ba87c23ee..7f3d51ac2 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -552,12 +552,15 @@ function wizard_add() ucic:set("network","omrvpn","proto","bonding") end if downloadmax ~= 0 and uploadmax ~= 0 then + ucic:set("sqm","omrvpn","enabled","1") ucic:set("sqm","omrvpn","max_download",downloadmax) ucic:set("sqm","omrvpn","max_upload",uploadmax) ucic:set("sqm","omrvpn","download",math.ceil(downloadmax*50/100)) ucic:set("sqm","omrvpn","min_download",math.ceil(downloadmax*8/100)) ucic:set("sqm","omrvpn","upload",math.ceil(uploadmax*50/100)) ucic:set("sqm","omrvpn","min_upload",math.ceil(uploadmax*8/100)) + else + ucic:set("sqm","omrvpn","enabled","0") end if vpn_intf ~= "" then ucic:set("network","omrvpn","device",vpn_intf) From e613de8cff77554f48ea9da17fcff0d7649dd091 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 14 Jul 2023 08:27:29 +0200 Subject: [PATCH 0996/2059] Some sqm-autorate fixes --- .../htdocs/luci-static/resources/view/network/sqm.js | 3 ++- luci-app-sqm-autorate/root/etc/init.d/sqm-autorate | 2 +- .../root/usr/share/sqm-autorate/cake-autorate.sh | 2 +- .../root/usr/share/sqm-autorate/config_template.sh | 2 +- luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js index c367e660c..40abf47d9 100644 --- a/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js +++ b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js @@ -289,7 +289,8 @@ return view.extend({ o.depends("autorate","1"); o = s.taboption("tab_autorate", form.Value, "startup_wait_s",_("Number of seconds to wait on startup:")); - o.default = "60"; + o.default = "60.0"; + o.datatype = 'float' o.depends("autorate","1"); diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 3f2d5c87d..6c2ee9495 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -49,7 +49,7 @@ start_service() { rm -f /usr/share/sqm-autorate/config.*.sh config_load sqm config_foreach _config_autorate queue - _launch_autorate + [ -n "$(ls /usr/share/sqm-autorate/config.*.sh 2>/dev/null)" ] && _launch_autorate } reload_service() { diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh index 6067cdca8..68edafd1c 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh @@ -2204,7 +2204,7 @@ do log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking loads." - log_msg "DEBUG" "load check is: (( ${achieved_rate_kbps[dl]} kbps > ${connection_stall_thr_kbps} kbps for download && ${achieved_rate_kbps[ul]} kbps > ${connection_stall_thr_kbps} kbps for upload ))" + #log_msg "DEBUG" "load check is: (( ${achieved_rate_kbps[dl]} kbps > ${connection_stall_thr_kbps} kbps for download && ${achieved_rate_kbps[ul]} kbps > ${connection_stall_thr_kbps} kbps for upload ))" # non-zero load so despite no reflector response within stall interval, the connection not considered to have stalled # and therefore resume normal operation diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh index 04a366a63..455089d54 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh @@ -200,7 +200,7 @@ reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma be stall_detection_thr=5 connection_stall_thr_kbps=10 -global_ping_response_timeout_s=100.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) +global_ping_response_timeout_s=${dl_delay_thr_ms} # timeout to set shaper rates to min on no ping response whatsoever (seconds) if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh index 1ef1af429..7c953290f 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh @@ -197,7 +197,7 @@ reflector_owd_delta_ewma_delta_thr_ms=10 # max increase from min delta ewma befo stall_detection_thr=5 connection_stall_thr_kbps=10 -global_ping_response_timeout_s=10.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) +global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no ping response whatsoever (seconds) if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) From 715c0cd0bc56f2f68b743b476d1b06ab0b6f79ff Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 14 Jul 2023 08:28:20 +0200 Subject: [PATCH 0997/2059] Some VPN interfaces default config changes --- openmptcprouter/files/etc/uci-defaults/2020-omr-vpn | 7 ++++--- openmptcprouter/files/etc/uci-defaults/2040-omr-sqm | 8 +------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index 28f19bda0..b571574d9 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -12,7 +12,6 @@ if [ "$(uci -q get network.omrvpn)" = "" ]; then set network.omrvpn.leasetime=12h set network.omrvpn.type=tunnel set network.omrvpn.txqueuelen=100 - set network.omrvpn.metric=9000 commit network EOF fi @@ -146,9 +145,11 @@ if [ "$(uci -q get glorytun-udp.vpn.key)" = "" ] && [ "$(uci -q get glorytun.vpn uci -q commit glorytun-udp fi -if [ "$(uci -q get network.omrvpn.metric)" = "1200" ]; then +if [ "$(uci -q get network.tun0.metric)" = "1200" ] || [ -z "$(uci -q get network.tun0.metric)" ]; then uci -q batch <<-EOF >/dev/null - set network.omrvpn.metric=9000 + set network.tun0=device + set network.tun0.name='tun0' + set network.tun0.metric=9000 commit network EOF fi diff --git a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm index 6d3a09a12..c8d7c8e27 100755 --- a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm +++ b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm @@ -81,7 +81,7 @@ if [ "$(uci -q get sqm.omrvpn)" = "" ] || [ -z "$(uci -q get sqm.omrvpn.delay_th set sqm.omrvpn.script="piece_of_cake.qos" set sqm.omrvpn.qdisc_advanced='0' set sqm.omrvpn.linklayer='none' - set sqm.omrvpn.enabled='1' + set sqm.omrvpn.enabled='0' set sqm.omrvpn.interface=tun0 set sqm.omrvpn.download='0' set sqm.omrvpn.upload='0' @@ -91,12 +91,6 @@ if [ "$(uci -q get sqm.omrvpn)" = "" ] || [ -z "$(uci -q get sqm.omrvpn.delay_th set sqm.omrvpn.iqdisc_opts='autorate-ingress' set sqm.omrvpn.delay_thr_ms='300' set sqm.omrvpn.reflector_ping_interval_s='0.5' - set sqm.omrvpn.download='20000' - set sqm.omrvpn.min_download='1000' - set sqm.omrvpn.max_download='60000' - set sqm.omrvpn.upload='20000' - set sqm.omrvpn.min_upload='1000' - set sqm.omrvpn.max_upload='60000' set sqm.omrvpn.enable_sleep_function='0' set sqm.omrvpn.autorate='1' commit sqm From 00267a8e86b169d3c3a4ecd9a740809da7d666ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 15 Jul 2023 14:35:21 +0200 Subject: [PATCH 0998/2059] Make ndpi-netfilter work on all arch --- luci-app-omr-bypass/Makefile | 3 +- ndpi-netfilter2/Makefile | 13 +- .../patches/002-no-livepatch-required.patch | 190 ++++++++++++++ ...3-bittorrent-compilation-remove-ipv6.patch | 237 ++++++++++++++++++ ndpi-netfilter2/patches/outline-atomics.patch | 2 +- .../patches/skbuff-check_fix.patch | 4 +- 6 files changed, 440 insertions(+), 9 deletions(-) create mode 100644 ndpi-netfilter2/patches/002-no-livepatch-required.patch create mode 100644 ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index 8d166a2e4..2969ef549 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -9,7 +9,8 @@ LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +iptables-mod-extra +iptables +sqlite3-cli ifneq ($(CONFIG_TARGET_ramips),) - LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi + #LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi + LUCI_DEPENDS+=+iptables-mod-ndpi +kmod-ipt-ndpi endif diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 7eee4b671..81a815641 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 -PKG_REV:=fbb2104d125a13db3b8c7fdc34ea0e3fcfe92d12 +PKG_REV:=3deea541af037b663b1b83a055b80d9a06a0afd2 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git @@ -21,6 +21,7 @@ PKG_SOURCE_URL:=https://github.com/vel21ripn/nDPI.git PKG_SOURCE_VERSION:=$(PKG_REV) PKG_BUILD_PARALLEL:=0 +PKG_FORTIFY_SOURCE:=0 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) @@ -34,7 +35,8 @@ define Package/iptables-mod-ndpi URL:=http://www.ntop.org/products/ndpi/ # DEPENDS:=+iptables +iptables-mod-conntrack-extra +kmod-ipt-ndpi +libpcap # DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) - DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15) +# DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15) @!TARGET_ramips + DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @!TARGET_ramips MAINTAINER:=Ycarus (Yannick Chabanois) endef @@ -50,7 +52,7 @@ MAKE_PATH:=ndpi-netfilter MAKE_FLAGS += \ KERNEL_DIR="$(LINUX_DIR)" \ MODULES_DIR="$(TARGET_MODULES_DIR)" \ - NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter \ + NDPI_PATH=$(PKG_BUILD_DIR)/ndpi-netfilter ifeq ($ARCH),aarch64) MAKE_FLAGS += ARCH="arm64" @@ -74,14 +76,15 @@ define KernelPackage/ipt-ndpi SUBMENU:=Netfilter Extensions TITLE:= nDPI net netfilter module # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) - DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15) +# DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15) @!TARGET_ramips + DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @!TARGET_ramips KCONFIG:=CONFIG_NF_CONNTRACK_LABELS=y \ CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y FILES:= $(PKG_BUILD_DIR)/ndpi-netfilter/src/xt_ndpi.ko AUTOLOAD:=$(call AutoProbe,xt_ndpi) # MODPARAMS.xt_ndpi:=ndpi_enable_flow=1 KCONFIG:=\ - CONFIG_LIVEPATCH=y \ + CONFIG_NDPI_HOOK=y \ CONFIG_NF_CONNTRACK=y \ CONFIG_NF_CONNTRACK_LABELS=y \ CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y \ diff --git a/ndpi-netfilter2/patches/002-no-livepatch-required.patch b/ndpi-netfilter2/patches/002-no-livepatch-required.patch new file mode 100644 index 000000000..a97f001b2 --- /dev/null +++ b/ndpi-netfilter2/patches/002-no-livepatch-required.patch @@ -0,0 +1,190 @@ +From 9e2bc31b8c330dc6ad0e6e478103652cd72dc3c8 Mon Sep 17 00:00:00 2001 +From: Sebastian Gottschall +Date: Sun, 9 Jul 2023 12:22:02 +0600 +Subject: [PATCH] add ndpi support for arm/arm64 etc. in 6.1 + +ndpi is not supported in more recent kernels without livepatch support +however. livepatch is only supported for x86_64 architectures. +so ndpi cannot be used on any other platform anymore. +we solve this by adding a simple hook to nf_ct_destroy + +Signed-off-by: Sebastian Gottschall +--- + ndpi-netfilter/kernel-patch/v6.1.38.diff | 81 ++++++++++++++++++++++++ + ndpi-netfilter/src/main.c | 23 +++++-- + 2 files changed, 98 insertions(+), 6 deletions(-) + create mode 100644 ndpi-netfilter/kernel-patch/v6.1.38.diff + +diff --git a/ndpi-netfilter/kernel-patch/v6.1.38.diff b/ndpi-netfilter/kernel-patch/v6.1.38.diff +new file mode 100644 +index 0000000000..6846dc84fc +--- /dev/null ++++ b/ndpi-netfilter/kernel-patch/v6.1.38.diff +@@ -0,0 +1,81 @@ ++diff -urpN linux-6.1.38.old/include/net/netfilter/nf_conntrack.h linux-6.1.38/include/net/netfilter/nf_conntrack.h ++--- linux-6.1.38.old/include/net/netfilter/nf_conntrack.h 2023-07-05 23:27:38.000000000 +0600 +++++ linux-6.1.38/include/net/netfilter/nf_conntrack.h 2023-07-14 12:34:56.663750711 +0600 ++@@ -362,6 +362,11 @@ static inline struct nf_conntrack_net *n ++ return net_generic(net, nf_conntrack_net_id); ++ } ++ +++#ifdef CONFIG_NDPI_HOOK +++void register_ndpi_hook(void (*hook)(struct nf_conn *)); +++void unregister_ndpi_hook(void); +++#endif +++ ++ #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) ++ #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) ++ #define NF_CT_STAT_ADD_ATOMIC(net, count, v) this_cpu_add((net)->ct.stat->count, (v)) ++diff -urpN linux-6.1.38.old/net/netfilter/Kconfig linux-6.1.38/net/netfilter/Kconfig ++--- linux-6.1.38.old/net/netfilter/Kconfig 2023-07-05 23:27:38.000000000 +0600 +++++ linux-6.1.38/net/netfilter/Kconfig 2023-07-14 12:34:11.966879899 +0600 ++@@ -76,11 +76,15 @@ config NETFILTER_NETLINK_OSF ++ If this option is enabled, the kernel will include support ++ for passive OS fingerprint via NFNETLINK. ++ +++config NDPI_HOOK +++ bool +++ ++ config NF_CONNTRACK ++ tristate "Netfilter connection tracking support" ++ default m if NETFILTER_ADVANCED=n ++ select NF_DEFRAG_IPV4 ++ select NF_DEFRAG_IPV6 if IPV6 != n +++ select NDPI_HOOK ++ help ++ Connection tracking keeps a record of what packets have passed ++ through your machine, in order to figure out how they are related ++diff -urpN linux-6.1.38.old/net/netfilter/nf_conntrack_core.c linux-6.1.38/net/netfilter/nf_conntrack_core.c ++--- linux-6.1.38.old/net/netfilter/nf_conntrack_core.c 2023-07-05 23:27:38.000000000 +0600 +++++ linux-6.1.38/net/netfilter/nf_conntrack_core.c 2023-07-14 12:33:45.580092713 +0600 ++@@ -582,9 +582,30 @@ static void destroy_gre_conntrack(struct ++ #endif ++ } ++ +++#ifdef CONFIG_NDPI_HOOK +++ +++static void (*ndpi_hook)(struct nf_conn *) __rcu __read_mostly = NULL; +++ +++void register_ndpi_hook(void (*hook)(struct nf_conn *)) +++{ +++ rcu_assign_pointer(ndpi_hook, hook); +++} +++EXPORT_SYMBOL(register_ndpi_hook); +++ +++void unregister_ndpi_hook(void) +++{ +++ rcu_assign_pointer(ndpi_hook, NULL); +++} +++ +++EXPORT_SYMBOL(unregister_ndpi_hook); +++#endif +++ ++ void nf_ct_destroy(struct nf_conntrack *nfct) ++ { ++ struct nf_conn *ct = (struct nf_conn *)nfct; +++#ifdef CONFIG_NDPI_HOOK +++ void (*hook)(struct nf_conn *); +++#endif ++ ++ pr_debug("%s(%p)\n", __func__, ct); ++ WARN_ON(refcount_read(&nfct->use) != 0); ++@@ -594,6 +615,12 @@ void nf_ct_destroy(struct nf_conntrack * ++ return; ++ } ++ +++#ifdef CONFIG_NDPI_HOOK +++ hook = rcu_dereference(ndpi_hook); +++ if (hook) +++ hook(ct); +++#endif +++ ++ if (unlikely(nf_ct_protonum(ct) == IPPROTO_GRE)) ++ destroy_gre_conntrack(ct); ++ +diff --git a/ndpi-netfilter/src/main.c b/ndpi-netfilter/src/main.c +index 024ca4bb79..e8ae3912d7 100644 +--- a/ndpi-netfilter/src/main.c ++++ b/ndpi-netfilter/src/main.c +@@ -102,7 +102,9 @@ static char proto_name[]="proto"; + static char debug_name[]="debug"; + static char risk_name[]="risks"; + +-#if LINUX_VERSION_CODE > KERNEL_VERSION(5,19,0) ++#ifdef CONFIG_NDPI_HOOK ++#define USE_NDPI_HOOK ++#elif LINUX_VERSION_CODE > KERNEL_VERSION(5,19,0) + #ifndef USE_LIVEPATCH + #define USE_LIVEPATCH + #endif +@@ -162,15 +164,17 @@ static inline const struct net_device *xt_out(const struct xt_action_param *par) + // for testing only! + // #define USE_CONNLABELS + +-#if !defined(USE_CONNLABELS) && defined(CONFIG_NF_CONNTRACK_CUSTOM) && CONFIG_NF_CONNTRACK_CUSTOM > 0 ++#if !defined(USE_CONNLABELS) && !defined(USE_NDPI_HOOK) && defined(CONFIG_NF_CONNTRACK_CUSTOM) && CONFIG_NF_CONNTRACK_CUSTOM > 0 + #define NF_CT_CUSTOM + #else ++#ifndef USE_NDPI_HOOK + #undef NF_CT_CUSTOM + #include + #ifndef CONFIG_NF_CONNTRACK_LABELS + #error NF_CONNTRACK_LABELS not defined + #endif + #endif ++#endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0) + #define nf_ct_l3proto_try_module_get(a) 0 +@@ -3187,7 +3191,7 @@ static int __net_init ndpi_net_init(struct net *net) + return -ENOMEM; + } + +-#ifndef USE_LIVEPATCH ++#if !defined(USE_LIVEPATCH) && !defined(USE_NDPI_HOOK) + static struct nf_ct_ext_type ndpi_extend = { + #if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) + .seq_print = seq_print_ndpi, +@@ -3197,7 +3201,7 @@ static struct nf_ct_ext_type ndpi_extend = { + .align = __alignof__(uint32_t), + .id = 0, + }; +-#else ++#elif !defined(USE_NDPI_HOOK) + + #if LINUX_VERSION_CODE < KERNEL_VERSION(5,17,0) + #error "not implemented" +@@ -3266,6 +3270,8 @@ static int __init ndpi_mt_init(void) + return -EBUSY; + } + nf_ct_ext_id_ndpi = ndpi_extend.id; ++#elif defined(USE_NDPI_HOOK) ++ register_ndpi_hook(&nf_ndpi_free_flow); + #else + #ifdef USE_LIVEPATCH + nf_ct_ext_id_ndpi = NF_CT_EXT_LABELS; +@@ -3389,8 +3395,11 @@ static int __init ndpi_mt_init(void) + unreg_pernet: + unregister_pernet_subsys(&ndpi_net_ops); + unreg_ext: +-#ifndef USE_LIVEPATCH ++#if !defined(USE_LIVEPATCH) && !defined(USE_NDPI_HOOK) + nf_ct_extend_unregister(&ndpi_extend); ++#endif ++#if defined(USE_NDPI_HOOK) ++ unregister_ndpi_hook(); + #endif + return ret; + } +@@ -3401,8 +3410,10 @@ static void __exit ndpi_mt_exit(void) + xt_unregister_target(&ndpi_tg_reg); + xt_unregister_match(&ndpi_mt_reg); + unregister_pernet_subsys(&ndpi_net_ops); +-#ifndef USE_LIVEPATCH ++#if !defined(USE_LIVEPATCH) && !defined(USE_NDPI_HOOK) + nf_ct_extend_unregister(&ndpi_extend); ++#elif defined(USE_NDPI_HOOK) ++ unregister_ndpi_hook(); + #else + rcu_assign_pointer(nf_conntrack_destroy_cb,NULL); + #endif diff --git a/ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch b/ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch new file mode 100644 index 000000000..b72b4271f --- /dev/null +++ b/ndpi-netfilter2/patches/003-bittorrent-compilation-remove-ipv6.patch @@ -0,0 +1,237 @@ +--- a/src/lib/protocols/bittorrent.c.old 2023-07-15 11:45:44.566446059 +0200 ++++ b/src/lib/protocols/bittorrent.c 2023-07-15 11:49:25.498828807 +0200 +@@ -263,19 +263,6 @@ + return key % (size-1); + } + +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +-static inline u_int32_t hash_calc6(ndpi_ip_addr_t *ip,u_int16_t port,u_int32_t size) { +- u_int32_t M,I; +- u_int8_t *ipp = (u_int8_t *)&I; +- u_int32_t key; +- M=103; +- I = ip->ipv6.u6_addr.u6_addr32[0] + ip->ipv6.u6_addr.u6_addr32[1] + ip->ipv6.u6_addr.u6_addr32[2] + ip->ipv6.u6_addr.u6_addr32[3]; +- key = (((ipp[0] * M) + ipp[1] * M) + ipp[2]) * M +ipp[3]; +- ipp = (u_int8_t *)&port; +- key = ((key * M) + ipp[0] * M) + ipp[1]; +- return key % (size-1); +-} +-#endif + + // ndpi_ip_addr_t + static struct hash_ip4p_node *hash_ip4p_add(struct hash_ip4p_table *ht, +@@ -283,9 +270,6 @@ + struct hash_ip4p_node *n,*t; + + u_int32_t key = +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- ht->ipv6 ? hash_calc6(ip,port,ht->size) : +-#endif + hash_calc(ip,port,ht->size); + + n = NULL; +@@ -293,22 +277,6 @@ + spin_lock(&ht->tbl[key].lock); + + n = ht->tbl[key].top; +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- if(ht->ipv6) { +- while(n) { +- if(!memcmp(&n->ip,ip->ipv6.u6_addr.u6_addr8,16) && n->port == port) { +- n->lchg = lchg; +- n->flag |= flag; +- move_up(&ht->tbl[key],n); +- goto unlock; +- } +- n = n->next; +- } +- n = BT_N_MALLOC(sizeof(struct hash_ip4p_node)+12); +- if(!n) goto unlock; +- memcpy(&n->ip,ip->ipv6.u6_addr.u6_addr8,16); +- } else { +-#endif + while(n) { + if(n->ip == ip->ipv4 && n->port == port) { + n->lchg = lchg; +@@ -321,9 +289,6 @@ + n = BT_N_MALLOC(sizeof(struct hash_ip4p_node)); + if(!n) goto unlock; + n->ip = ip->ipv4; +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- } +-#endif + t = ht->tbl[key].top; + n->next = t; + n->prev = NULL; +@@ -347,31 +312,16 @@ + struct hash_ip4p_node *n; + + u_int16_t key = +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- ht->ipv6 ? hash_calc6(ip,port,ht->size) : +-#endif + hash_calc(ip,port,ht->size); + + n = NULL; + spin_lock(&ht->tbl[key].lock); + + n = ht->tbl[key].top; +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- if(ht->ipv6) { +- while(n) { +- if(!memcmp(&n->ip,ip->ipv6.u6_addr.u6_addr8,16) && n->port == port) +- break; +- n = n->next; +- } +- } else { +-#endif + while(n) { + if(n->ip == ip->ipv4 && n->port == port) break; + n = n->next; + } +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- } +-#endif + if(n) { + #ifdef __KERNEL__ + diagram(ndpi_btp_tm,sizeof(ndpi_btp_tm)/sizeof(ndpi_btp_tm[0]),lchg - n->lchg); +@@ -805,13 +755,6 @@ + u_int16_t s_port = packet->udp ? packet->udp->source : + packet->tcp ? packet->tcp->source : 0; + +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- if(packet->iphv6) +- bt_add_announce(ndpi_struct, +- ndpi_struct->bt_ann, ndpi_struct->bt_ann_len, +- 1, (ndpi_ip_addr_t *)&packet->iphv6->ip6_src, +- s_port, &x.p,p_now); +-#endif + if(packet->iph) + bt_add_announce(ndpi_struct, + ndpi_struct->bt_ann, ndpi_struct->bt_ann_len, +@@ -819,39 +762,6 @@ + s_port, &x.p,p_now); + } + #endif +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +-if(packet->iphv6 && ndpi_struct->bt6_ht) { +-NDPI_LOG_DBG2(ndpi_struct, +- "BT: detected valid DHT6 %d %d\n", +- x.p.r.nn6,x.p.r.nv6); +-#ifndef __KERNEL__ +-if(bt_parse_debug) dump_bt_proto_struct(&x.p); +-#endif +- if(x.p.r.nodes6 && x.p.r.nn6) { +- struct bt_nodes6_data *n = x.p.r.nodes6; +- for(i=0; i < x.p.r.nn6; i++,n++) { +- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&n->ip,n->port,p_now,0x2); +- +- NDPI_LOG_DBG2(ndpi_struct, +- "BT: nodes6 add DHT peer %s:%d\n", +- inet_ntop(AF_INET6,(void *)&n->ip, ip6buf,sizeof(ip6buf)), +- htons(n->port)); +- } +- } +- if(x.p.r.values6 && x.p.r.nv6) { +- struct bt_ipv6p2 *n = (struct bt_ipv6p2 *)x.p.r.values6; +- for(i=0; i < x.p.r.nv6; i++,n++) { +- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&n->d.ip,n->d.port,p_now,0x4); +- +- NDPI_LOG_DBG2(ndpi_struct, +- "BT: values6 add DHT peer %s:%d\n", +- inet_ntop(AF_INET6,(void *)&n->d.ip, ip6buf,sizeof(ip6buf)), +- htons(n->d.port)); +- } +- } +- return r >= 0; +-} +-#endif + + if(!ndpi_struct->bt_ht) return r >= 0; + +@@ -899,16 +809,6 @@ + static void ndpi_bt_add_peer_cache(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_packet_struct *packet, uint16_t p_src, uint16_t p_dst) { + +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- if(ndpi_struct->bt6_ht && packet->iphv6) { +- if(packet->packet_direction) +- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_src, +- p_src, packet->current_time,1); +- else +- hash_ip4p_add(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_dst, +- p_dst, packet->current_time,1); +- } else +-#endif + if(ndpi_struct->bt_ht && packet->iph) { + if(packet->packet_direction) + hash_ip4p_add(ndpi_struct->bt_ht,(ndpi_ip_addr_t *)&packet->iph->saddr, +@@ -1073,19 +973,6 @@ + if(!packet->tcp) return 0; + source = packet->tcp->source; + dest = packet->tcp->dest; +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- if(ndpi_struct->bt6_ht && packet->iphv6) { +- f1 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_src,source, +- packet->current_time); +- f2 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_dst,dest, +- packet->current_time); +-#ifdef __KERNEL__ +- if(f1) ndpi_ptss++; +- if(f2) ndpi_ptdd++; +-#endif +- return f1 != NULL || f2 != NULL; +- } +-#endif + if(ndpi_struct->bt_ht && packet->iph) { + f1 = hash_ip4p_find(ndpi_struct->bt_ht,(ndpi_ip_addr_t *)&packet->iph->saddr,source, + packet->current_time); +@@ -1110,23 +997,6 @@ + if(!packet->udp) return 0; + source = packet->udp->source; + dest = packet->udp->dest; +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- if(ndpi_struct->bt6_ht && packet->iphv6) { +- f1 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_src,source, +- packet->current_time); +- f2 = hash_ip4p_find(ndpi_struct->bt6_ht,(ndpi_ip_addr_t *)&packet->iphv6->ip6_dst,dest, +- packet->current_time); +-#ifdef __KERNEL__ +- if(f1) { +- DIRC(ndpi_pusr,ndpi_pusf); +- } +- if(f2) { +- DIRC(ndpi_pudr,ndpi_pudf); +- } +-#endif +- return f1 != NULL || f2 != NULL; +- } +-#endif + if(ndpi_struct->bt_ht && packet->iph) { + f1 = hash_ip4p_find(ndpi_struct->bt_ht,(ndpi_ip_addr_t *)&packet->iph->saddr,source, + packet->current_time); +@@ -1653,11 +1523,6 @@ + u_int32_t size,u_int32_t size6,u_int32_t tmo,int logsize) { + + ndpi_struct->bt_ht = hash_ip4p_init(size); +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +- ndpi_struct->bt6_ht = hash_ip4p_init(size6); +- if(ndpi_struct->bt6_ht) +- ndpi_struct->bt6_ht->ipv6=1; +-#endif + ndpi_bt_node_expire = tmo; + #ifdef BT_ANNOUNCE + if(logsize > 0) { +@@ -1679,12 +1544,6 @@ + hash_ip4p_del(ndpi_struct->bt_ht); + ndpi_struct->bt_ht = NULL; + } +-#ifdef NDPI_DETECTION_SUPPORT_IPV6 +-if(ndpi_struct->bt6_ht) { +- hash_ip4p_del(ndpi_struct->bt6_ht); +- ndpi_struct->bt6_ht = NULL; +-} +-#endif + } + + void init_bittorrent_dissector(struct ndpi_detection_module_struct *ndpi_struct, diff --git a/ndpi-netfilter2/patches/outline-atomics.patch b/ndpi-netfilter2/patches/outline-atomics.patch index 72dace62c..8055bd41a 100644 --- a/ndpi-netfilter2/patches/outline-atomics.patch +++ b/ndpi-netfilter2/patches/outline-atomics.patch @@ -7,7 +7,7 @@ +cc-option = $(shell if $(CC) -Werror $(1) -S -o /dev/null -xc /dev/null \ + > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) +mno_outline_atomics := $(call cc-option, -mno-outline-atomics, "") -+ccflags-y += $(mno_outline_atomics) ++ccflags-y += $(mno_outline_atomics) -Wframe-larger-than=2600 #ccflags-y += -Wshadow-local # Needed for pahole #ccflags-y += -femit-struct-debug-detailed=any diff --git a/ndpi-netfilter2/patches/skbuff-check_fix.patch b/ndpi-netfilter2/patches/skbuff-check_fix.patch index f5fe4defc..f089d87e1 100644 --- a/ndpi-netfilter2/patches/skbuff-check_fix.patch +++ b/ndpi-netfilter2/patches/skbuff-check_fix.patch @@ -4,8 +4,8 @@ KERNEL_DIR := /lib/modules/$(shell uname -r)/build endif --ifeq ($(shell test -f $(KERNEL_DIR)/source/include/linux/skbuff.h && grep -qc userid $(KERNEL_DIR)/source/include/linux/skbuff.h),1) -+ifeq ($(shell test -f $(KERNEL_DIR)/include/linux/skbuff.h && shell grep -qc userid $(KERNEL_DIR)/include/linux/skbuff.h),1) +-ifeq ($(shell test -f $(KERNEL_DIR)/source/include/linux/skbuff.h && grep -c userid $(KERNEL_DIR)/source/include/linux/skbuff.h),1) ++ifeq ($(shell test -f $(KERNEL_DIR)/include/linux/skbuff.h && shell grep -c userid $(KERNEL_DIR)/include/linux/skbuff.h),1) ccflags-y += -DUSE_HACK_USERID=1 endif From 75694cfc65af93e52d77627e5ce228ce14bce246 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 18 Jul 2023 09:14:34 +0200 Subject: [PATCH 0999/2059] Fix for SQM autorate --- .../root/usr/share/sqm-autorate/config_template.sh | 5 ++--- mptcp/files/usr/share/omr/post-tracking.d/post-tracking | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh index 455089d54..a3ac23966 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh @@ -8,7 +8,6 @@ # Inspiration taken from: @moeller0 (OpenWrt forum) INTERFACE=$(basename "$1" | cut -d. -f2) - #cake_autorate_version="2.0.0" # *** OUTPUT AND LOGGING OPTIONS *** @@ -77,9 +76,9 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # delay threshold in ms is the extent of OWD increase to classify as a delay # these are automatically adjusted based on maximum on the wire packet size # (adjustment significant at sub 12Mbit/s rates, else negligible) -dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) || $(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30)) || echo 100 # (milliseconds) +#logger -t "sqm-autorate" "ping for ${INTERFACE} (${ul_if}): $(echo $(/sbin/uci -q get sqm.${INTERFACE}.delay_thr_ms || echo '100'))" +dl_delay_thr_ms=$(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(($(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30)) || echo "100")) # (milliseconds) ul_delay_thr_ms=${dl_delay_thr_ms} - # Set either of the below to 0 to adjust one direction only # or alternatively set both to 0 to simply use cake-autorate to monitor a connection adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 6c9667395..4598bd39c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -1752,7 +1752,8 @@ if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprout sleep 5 fi -if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "autorate_config.${OMR_TRACKER_INTERFACE}") ]; then +if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "config.${OMR_TRACKER_INTERFACE}") ]; then + _log "Restart SQM Autorate" /etc/init.d/sqm-autorate restart >/dev/null 2>&1 sleep 5 fi From b362091628ac2ace4c9a883a69d7caa7622d197c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 Jul 2023 21:40:19 +0200 Subject: [PATCH 1000/2059] Fix MPTCP menu display on kernel 6.1 --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index 7d2e8ffaf..efa878923 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -22,7 +22,7 @@ o = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-mana o:value("default", translate("default")) o:value("fullmesh", "fullmesh") --if tonumber(uname.release:sub(1,4)) <= 5.15 then -if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then +if uname.release:sub(1,4) ~= "5.15" and uname.release:sub(1,1) ~= "6" then o:value("ndiffports", "ndiffports") o:value("binder", "binder") if uname.release:sub(1,4) ~= "4.14" then @@ -32,7 +32,7 @@ end o = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler")) o:value("default", translate("default")) -- if tonumber(uname.release:sub(1,4)) <= 5.15 then -if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then +if uname.release:sub(1,4) ~= "5.15" and uname.release:sub(1,1) ~= "6" then o:value("roundrobin", "round-robin") o:value("redundant", "redundant") if uname.release:sub(1,4) ~= "4.14" then @@ -41,13 +41,13 @@ if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then end end -- if tonumber(uname.release:sub(1,4)) <= 5.15 then -if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then +if uname.release:sub(1,4) ~= "5.15" and uname.release:sub(1,1) ~= "6" then o = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) o.datatype = "uinteger" o.rmempty = false end -- if tonumber(uname.release:sub(1,4)) <= 5.15 then -if uname.release:sub(1,4) ~= "5.15" or uname.release:sub(1,1) ~= "6" then +if uname.release:sub(1,4) ~= "5.15" and uname.release:sub(1,1) ~= "6" then o = s:option(ListValue, "mptcp_version", translate("Multipath TCP version")) o:value(0, translate("0")) o:value(1, translate("1")) From 1b02c5f1749ab6c7b8e6be5e5ebdc87ab7a0950a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 21 Jul 2023 21:40:54 +0200 Subject: [PATCH 1001/2059] Fix firewall redirection with destination IP --- .../files/etc/init.d/openmptcprouter-vps | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index db37d8045..8bb124ac0 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -956,6 +956,18 @@ _vps_firewall_redirect_port() { [ -n "$src_dip" ] && { comment=" to $src_dip" $IPTABLESSAVE --counters | sed "s:-d $src_dip/32::g" | $IPTABLESRESTORE -w + [ -f /usr/sbin/nft ] && { + rule=$(nft -a list table inet fw4 | grep -m1 "ip daddr $src_dip") + [ -n "$rule" ] && { + handle=$(echo $rule | awk '{ print $NF }') + nft replace rule inet fw4 dstnat_lan handle ${handle} $(echo $rule | awk '{ sub(" comment.*$",""); print }' | sed "s/ip daddr ${src_dip}//") 2>&1 >/dev/null + } + rule=$(nft -a list table inet fw4 | grep -m1 "ip daddr $src_dip") + [ -n "$rule" ] && { + handle=$(echo $rule | awk '{ print $NF }') + nft replace rule inet fw4 dstnat_vpn handle $handle $(echo $rule | awk '{ sub(" comment.*$",""); print }' | sed "s/ip daddr ${src_dip}/meta nfproto ipv4/") 2>&1 >/dev/null + } + } } [ -n "$src_ip" ] && comment=" from $src_ip" if [ "$target" = "ACCEPT" ]; then @@ -1038,6 +1050,18 @@ _vps_firewall_redirect_port() { [ -n "$src_dip" ] && { comment=" to $src_dip" $IPTABLESSAVE --counters | sed "s:-d $src_dip/32::g" | $IPTABLESRESTORE -w + [ -f /usr/sbin/nft ] && { + rule=$(nft -a list table inet fw4 | grep -m1 "ip daddr $src_dip") + [ -n "$rule" ] && { + handle=$(echo $rule | awk '{ print $NF }') + nft replace rule inet fw4 dstnat_lan handle ${handle} $(echo $rule | awk '{ sub(" comment.*$",""); print }' | sed "s/ip daddr ${src_dip}//") 2>&1 >/dev/null + } + rule=$(nft -a list table inet fw4 | grep -m1 "ip daddr $src_dip") + [ -n "$rule" ] && { + handle=$(echo $rule | awk '{ print $NF }') + nft replace rule inet fw4 dstnat_vpn handle $handle $(echo $rule | awk '{ sub(" comment.*$",""); print }' | sed "s/ip daddr ${src_dip}/meta nfproto ipv4/") 2>&1 >/dev/null + } + } } [ -n "$src_ip" ] && comment=" from $src_ip" checkfw=$(echo "$vpsfwlist" | grep "# OMR $username open router $src_dport port ${protoi}${comment} --- V2Ray to ${dest_ip}:${dest_port}") From 6365cfcc8082ac0310139dbc312dc1d71eeb5dcc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 23 Jul 2023 08:17:43 +0200 Subject: [PATCH 1002/2059] Fix tun0 mtu --- openmptcprouter/files/etc/uci-defaults/2020-omr-vpn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index b571574d9..23e00009c 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -145,11 +145,11 @@ if [ "$(uci -q get glorytun-udp.vpn.key)" = "" ] && [ "$(uci -q get glorytun.vpn uci -q commit glorytun-udp fi -if [ "$(uci -q get network.tun0.metric)" = "1200" ] || [ -z "$(uci -q get network.tun0.metric)" ]; then +if [ "$(uci -q get network.tun0.mtu)" = "1200" ] || [ -z "$(uci -q get network.tun0.mtu)" ]; then uci -q batch <<-EOF >/dev/null set network.tun0=device set network.tun0.name='tun0' - set network.tun0.metric=9000 + set network.tun0.mtu=9000 commit network EOF fi From 3959237a3d1b77417d3c8aac3ad1c640c5cb4ed4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 23 Jul 2023 09:12:27 +0200 Subject: [PATCH 1003/2059] Should add MPTCP support to v2ray... --- v2ray-core/files/etc/init.d/v2ray | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index 5eac8c265..d704c337f 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -1944,6 +1944,16 @@ clear_transparent_proxy() { fi } +version_over_5_4() { + MAJOR_VERSION=$(uname -r | awk -F '.' '{print $1}') + MINOR_VERSION=$(uname -r | awk -F '.' '{print $2}') + if [ $MAJOR_VERSION -ge 5 ] && [ $MINOR_VERSION -gt 13 ] || [ $MAJOR_VERSION -gt 5 ] ; then + return 0 + else + return 1 + fi +} + start_instance() { local section="$1" @@ -2054,10 +2064,14 @@ start_instance() { return 1 fi fi + + PROG="$NAME.$section" TRANSPARENT_PROXY_EXPECTED=1 - - procd_open_instance "$NAME.$section" + if version_over_5_4; then + PROG="mptcpize run ${PROG}" + fi + procd_open_instance "$PROG" procd_set_param command "$v2ray_file" procd_append_param command run procd_append_param command -config "$temp_config" From d31ae36737c01bb43e2ca84845eed1fe364f1237 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 27 Jul 2023 13:21:27 +0200 Subject: [PATCH 1004/2059] Update ModemManager --- modemmanager/Makefile | 10 +++--- modemmanager/files/modemmanager.common | 8 +++++ modemmanager/files/modemmanager.proto | 43 ++++++++++++++++++++------ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/modemmanager/Makefile b/modemmanager/Makefile index 30e17b657..8a4958404 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,25 +8,25 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_SOURCE_VERSION:=1.20.4 -PKG_RELEASE:=1 +PKG_SOURCE_VERSION:=1.20.6 +PKG_RELEASE:=8 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -#PKG_MIRROR_HASH:=f138effc693456c5040ec22e17c0a8b41143c3b17b62437462995c297a9150dc +PKG_MIRROR_HASH:=e90103e2e42bb826bbbac83937a9a69f50348cd6ce0d8da655a12b65494ce7c9 PKG_MAINTAINER:=Nicholas Smith PKG_LICENSE:=GPL-2.0-or-later PKG_LICENSE_FILES:=COPYING PKG_BUILD_DEPENDS:=glib2/host libxslt/host +PKG_BUILD_FLAGS:=gc-sections include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk include $(INCLUDE_DIR)/meson.mk -TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants -TARGET_LDFLAGS += -Wl,--gc-sections +TARGET_CFLAGS += -fno-merge-all-constants -fmerge-constants define Package/modemmanager/config source "$(SOURCE)/Config.in" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common index a439179de..6a59ae6e1 100644 --- a/modemmanager/files/modemmanager.common +++ b/modemmanager/files/modemmanager.common @@ -272,6 +272,14 @@ mm_report_event() { local subsystem="$3" local sysfspath="$4" + # Do not save virtual devices + local virtual + virtual="$(echo "$sysfspath" | cut -d'/' -f4)" + [ "$virtual" = "virtual" ] && { + mm_log "debug" "sysfspath is a virtual device ($sysfspath)" + return + } + # Track/untrack events in cache case "${action}" in "add") diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto index e6ec9e203..b8ebce924 100644 --- a/modemmanager/files/modemmanager.proto +++ b/modemmanager/files/modemmanager.proto @@ -343,11 +343,22 @@ proto_modemmanager_init_config() { proto_config_add_string password proto_config_add_string pincode proto_config_add_string iptype + proto_config_add_string plmn proto_config_add_int signalrate proto_config_add_boolean lowpower + proto_config_add_boolean allow_roaming proto_config_add_defaults } +# Append param to the global 'connectargs' variable. +append_param() { + local param="$1" + + [ -z "$param" ] && return + [ -z "$connectargs" ] || connectargs="${connectargs}," + connectargs="${connectargs}${param}" +} + proto_modemmanager_setup() { local interface="$1" @@ -355,11 +366,11 @@ proto_modemmanager_setup() { local bearermethod_ipv4 bearermethod_ipv6 auth cliauth local operatorname operatorid registration accesstech signalquality - local device apn allowedauth username password pincode iptype metric signalrate + local device apn allowedauth username password pincode iptype plmn metric signalrate allow_roaming local address prefix gateway mtu dns1 dns2 - json_get_vars device apn allowedauth username password pincode iptype metric signalrate + json_get_vars device apn allowedauth username password pincode iptype plmn metric signalrate allow_roaming # validate sysfs path given in config [ -n "${device}" ] || { @@ -368,11 +379,6 @@ proto_modemmanager_setup() { proto_set_available "${interface}" 0 return 1 } - [ -e "${device}" ] || { - echo "Device not found in sysfs" - proto_set_available "${interface}" 0 - return 1 - } # validate that ModemManager is handling the modem at the sysfs path modemstatus=$(mmcli --modem="${device}" --output-keyvalue) @@ -397,7 +403,24 @@ proto_modemmanager_setup() { echo "starting connection with apn '${apn}'..." proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS - connectargs="apn=${apn}${iptype:+,ip-type=${iptype}}${cliauth:+,allowed-auth=${cliauth}}${username:+,user=${username}}${password:+,password=${password}}${pincode:+,pin=${pincode}}" + # setup allow-roaming parameter + if [ -n "${allow_roaming}" ] && [ "${allow_roaming}" -eq 0 ];then + allow_roaming="no" + else + # allowed unless a user set the opposite + allow_roaming="yes" + fi + + # Append options to 'connectargs' variable + append_param "apn=${apn}" + append_param "allow-roaming=${allow_roaming}" + append_param "${iptype:+ip-type=${iptype}}" + append_param "${plmn:+operator-id=${plmn}}" + append_param "${cliauth:+allowed-auth=${cliauth}}" + append_param "${username:+user=${username}}" + append_param "${password:+password=${password}}" + append_param "${pincode:+pin=${pincode}}" + mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { proto_notify_error "${interface}" MM_CONNECT_FAILED proto_block_restart "${interface}" @@ -509,7 +532,6 @@ proto_modemmanager_teardown() { json_get_vars device lowpower iptype echo "stopping network" - proto_notify_error "${interface}" MM_TEARDOWN_IN_PROGRESS # load connected bearer information, just the first one should be ok modemstatus=$(mmcli --modem="${device}" --output-keyvalue) @@ -544,6 +566,9 @@ proto_modemmanager_teardown() { # low power, only if requested [ "${lowpower:-0}" -lt 1 ] || mmcli --modem="${device}" --set-power-state-low + + proto_init_update "*" 0 + proto_send_update "$interface" } [ -n "$INCLUDE_ONLY" ] || { From d95a4f9ee01fef97cd88b8636e7607c981c680ba Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 27 Jul 2023 13:22:11 +0200 Subject: [PATCH 1005/2059] Make stap available --- systemtap/Makefile | 4 ++-- systemtap/patches/replace-open64.patch | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 systemtap/patches/replace-open64.patch diff --git a/systemtap/Makefile b/systemtap/Makefile index 6b3a704cc..c25cd3467 100644 --- a/systemtap/Makefile +++ b/systemtap/Makefile @@ -40,11 +40,11 @@ endef CONFIGURE_ARGS += --without-rpm \ --without-nss --without-avahi --without-dyninst \ --disable-server --disable-grapher --enable-prologues \ - --without-python2-probes --disable-translator \ + --without-python2-probes \ --disable-libvirt --disable-sqlite --disable-monitor --without-python3-probes \ ac_cv_prog_have_javac=no \ ac_cv_prog_have_jar=no - +# --disable-translator HOST_CONFIGURE_ARGS += --without-rpm \ --without-nss --without-avahi --without-dyninst \ --disable-server --disable-grapher --enable-prologues \ diff --git a/systemtap/patches/replace-open64.patch b/systemtap/patches/replace-open64.patch new file mode 100644 index 000000000..6146fc3bc --- /dev/null +++ b/systemtap/patches/replace-open64.patch @@ -0,0 +1,11 @@ +--- a/setupdwfl.cxx 2023-07-26 20:22:35.427807372 +0200 ++++ b/setupdwfl.cxx 2023-07-26 20:22:43.855666830 +0200 +@@ -762,7 +762,7 @@ + clog << _("Attempting to extract kernel debuginfo build ID from /sys/kernel/notes") << endl; + + const char *notesfile = "/sys/kernel/notes"; +- int fd = open64 (notesfile, O_RDONLY); ++ int fd = open (notesfile, O_RDONLY); + if (fd < 0) + return ""; + From d9e248545c97a05a076ccf033637a88a392d6ed9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 27 Jul 2023 13:22:47 +0200 Subject: [PATCH 1006/2059] Add mptcp_add_addr_timeout option in luci MPTCP interface --- luci-app-mptcp/luasrc/model/cbi/mptcp.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index efa878923..a36c3d391 100644 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -75,6 +75,12 @@ if uname.release:sub(1,4) == "5.15" or uname.release:sub(1,1) == "6" then o.datatype = "uinteger" o.rmempty = false o.default = 4 + + o = s:option(Value, "mptcp_add_addr_timeout", translate("Set the timeout after which an ADD_ADDR control message will be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR message.")) + o.datatype = "uinteger" + o.rmempty = false + o.default = 120 + else o = s:option(Value, "mptcp_fullmesh_num_subflows", translate("Fullmesh subflows for each pair of IP addresses")) o.datatype = "uinteger" From 23bbb48cb027eee68b9652df1739198672a3ca2d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 29 Jul 2023 16:17:25 +0200 Subject: [PATCH 1007/2059] Add fullcone IPv6 --- .../htdocs/luci-static/resources/view/firewall/zones.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js index 5ece96be2..83171dc61 100644 --- a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js +++ b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js @@ -150,6 +150,10 @@ return view.extend({ o.editable = true; o.depends('masq', '1'); + o = s.taboption('general', form.Flag, 'fullcone6', _('Full Cone IPv6')); + o.editable = true; + o.depends('masq', '1'); + o = s.taboption('general', form.Flag, 'mtu_fix', _('MSS clamping')); o.modalonly = true; From 182cb253c1fef9b7e40a2716edbf43c8eb8aac99 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 29 Jul 2023 16:18:03 +0200 Subject: [PATCH 1008/2059] Use cake for new interfaces --- .../luasrc/controller/openmptcprouter.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 7f3d51ac2..5a0cb0566 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -198,8 +198,8 @@ function wizard_add() else ucic:set("sqm","wan" .. i,"interface",defif) end - ucic:set("sqm","wan" .. i,"qdisc","fq_codel") - ucic:set("sqm","wan" .. i,"script","simple.qos") + ucic:set("sqm","wan" .. i,"qdisc","cake") + ucic:set("sqm","wan" .. i,"script","piece_of_cake.qos") ucic:set("sqm","wan" .. i,"qdisc_advanced","0") ucic:set("sqm","wan" .. i,"linklayer","none") ucic:set("sqm","wan" .. i,"enabled","1") @@ -434,8 +434,8 @@ function wizard_add() end ucic:set("sqm",intf,"queue") ucic:set("sqm",intf,"interface",defif) - ucic:set("sqm",intf,"qdisc","fq_codel") - ucic:set("sqm",intf,"script","simple.qos") + ucic:set("sqm",intf,"qdisc","cake") + ucic:set("sqm",intf,"script","piece_of_cake.qos") ucic:set("sqm",intf,"qdisc_advanced","0") ucic:set("sqm",intf,"linklayer","atm") ucic:set("sqm",intf,"overhead","40") From a1a9b90155bb1cf0021369adf10953bb84a6e770 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 29 Jul 2023 16:18:34 +0200 Subject: [PATCH 1009/2059] Add an alert that V2ray doesn't aggregate on 6.1 kernel for now --- .../luasrc/view/openmptcprouter/wizard.htm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 07f8a7835..d81f88551 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -6,6 +6,7 @@ local fs = require "nixio.fs" local sys = require "luci.sys" local ut = require "luci.util" + local uname = nixio.uname() local ifaces = sys.net:devices() local ifttyu = nixio.fs.glob("/dev/ttyUSB*") local ifttyc = nixio.fs.glob("/dev/cdc-wdm*") @@ -239,6 +240,9 @@
    <%:Set the default Proxy used for TCP when ShadowSocks is enabled, for TCP and UDP when V2Ray is enabled.%> <%:Only ShadowSocks is supported with server multiple IPs for now.%> + <% if uname.release:sub(1,4) == "5.15" or uname.release:sub(1,1) == "6" then %> +
    <%:V2Ray doesn't support aggregation on Kernel > 5.4 yet.%> + <% end %>
    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�M|(PMov=p+ZvJ2|Z!@#tmoU140nOpD=x6 zK-hKI&f<9fBxv12|CiSoxr#2q@xc-x`Yijd6XtH*aB;C!Z{l1c)(*kB!U+rSte!ZR z$aE5lSpYS0E)hYo;(D~>8Igv#v0Td*1|#BPz24-gfDS6zWp8J)#myaoc?RC(HFRGf zWAr{wj9j-C1BuxSJ>k1XF0@gZw(dE+Vg7{g8UbSYy=f9437bFRyT&;Rj7!$In#>!v zfEEG)!mg>wp*)XnJnI^Tm4lufVi_k-)JD=OsR^AUL&zYc!Sp2P*20Sp*MdaIn;dAj z&D@4DqIN*Q5HHL)I{Po^;PMbA?@j0$IiBI63lKG-YZO3m76pGrPv{yM3>-S#9Ma{h zCaVD)%&U!;QN1t$^_s4dw1or%4LGJzn4BzdTr_Y z(ut+LioY!Wd+{U1*A#Cko>J6>-xV5#j~CupxTA1JVKx7Ud_DiM{1f@x^Uu$(=Kg^1 z|2>s^B6mmb`8k#SZFW1}0K7hXOZMdKKAHc?{CnmjnOA47%^aWEJ^k~!|9@IMl7!->*#FbZ5x-@f)Xx8f~AKV0( z7;D>~y0SI%#d3f|N5h|98ZZu~QGO~iuBVr{0U`P@)o-+x4dxx$)qR zpyRo$ef+5_Tr-`P*&AJ6PI@;S5Z*dEnp2R&8>6Q$bW9Ng3r%zpr}S?eA!{>-�OP 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%0Ap;W1n3e z_Zc8uJR3Ai<+p_S6((`=z)R2U7*_&0fl$yDQD{ZhDiw5j5##8v(=Lk(Rw3l@#H4(| zUEqoJDtrS#7t!*m z#@H@lY!O4o#1wa-YrU)!Bz!s3zE=jMmvw+Nc=nJ}Bp`L)h#;c9Romm4QEJl1DlPZc zC=}YlO?#i^W)hlk3x&3TD33{dzdU|Gq0kl(2v)x0DsecCH?=73;q8-*Lid26`d

    #tfbZC%SU)Q{+`HbeW=D6{L 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 gtLF}O*gR3r{JqC*%li}M> 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

    p75uWUZQ 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

    c!E%Da``X*@zfLI30Y0Qic^d$xBcLWTITZU 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

    - <% if self.invalid_cts then -%>
    <% end %> - - - <% if self.invalid_cts then %>
    <%:Invalid%>
    <% end %> -
    diff --git a/luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json b/luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json index ed1c7a074..fbe9e0b6c 100644 --- a/luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json +++ b/luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json @@ -1,13 +1,36 @@ { "admin/services/omr-tracker": { - "title": "OMR-Tracker", - "order": 10, + "title": "OMR-Tracker Manager", + "order": 60, "action": { - "type": "cbi", - "path": "omr-tracker" + "type": "firstchild" }, "depends": { "acl": [ "luci-app-omr-tracker" ] } + }, + "admin/services/omr-tracker/interface": { + "title": "Interface", + "order": 10, + "action": { + "type": "view", + "path": "omr-tracker/network/interface" + } + }, + "admin/services/omr-tracker/proxy": { + "title": "Proxy", + "order": 20, + "action": { + "type": "view", + "path": "omr-tracker/network/proxy" + } + }, + "admin/services/omr-tracker/server": { + "title": "Server", + "order": 30, + "action": { + "type": "view", + "path": "omr-tracker/network/server" + } } } diff --git a/luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json b/luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json index c55ce91d4..31a2a4b62 100644 --- a/luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json +++ b/luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json @@ -2,7 +2,13 @@ "luci-app-omr-tracker": { "description": "Grant UCI access for luci-app-omr-tracker", "read": { - "uci": [ "omr-tracker" ] + "uci": [ "omr-tracker" ], + "file": { + "/usr/bin/httping": [ "list" ], + "/usr/bin/dig": [ "list" ], + "/usr/bin/nping": [ "list" ], + "/usr/bin/arping": [ "list" ] + } }, "write": { "uci": [ "omr-tracker" ] diff --git a/omr-tracker/Makefile b/omr-tracker/Makefile index 58fdafdf6..f690f438e 100644 --- a/omr-tracker/Makefile +++ b/omr-tracker/Makefile @@ -1,6 +1,6 @@ # # OpenMPTCProuter tracker is a modified version of OverTheBox tracker from OVH -# Copyright (C) 2017-2019 Ycarus (Yannick Chabanois) +# Copyright (C) 2017-2023 Ycarus (Yannick Chabanois) # # This is free software, licensed under the GNU General Public License v3. # See /LICENSE for more information. @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=omr-tracker -PKG_VERSION:=1.7 +PKG_VERSION:=2.0 PKG_RELEASE:=1 include $(INCLUDE_DIR)/package.mk diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 7f0799eee..12a10d54f 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -17,6 +17,9 @@ export OMR_TRACKER_INTERFACE export OMR_TRACKER_HOST export OMR_TRACKER_HOST6 export OMR_TRACKER_TIMEOUT +export OMR_TRACKER_SIZE +export OMR_TRACKER_MAX_TTL +export OMR_TRACKER_LOSS export OMR_TRACKER_STATUS export OMR_TRACKER_STATUS_MSG export OMR_TRACKER_PREV_STATUS @@ -150,6 +153,8 @@ _ping() { ret=$(ping -I "${device}" \ -w "$OMR_TRACKER_TIMEOUT" \ -c "$OMR_TRACKER_COUNT" \ + -s "$OMR_TRACKER_SIZE" \ + -t "$OMR_TRACKER_MAX_TTL" \ -Q 184 \ "${host}" 2>&1 ) && echo "$ret" | grep -sq " 0% packet loss" && { @@ -163,15 +168,20 @@ _ping() { ret=$(ping -B -I "${device}" \ -w "$OMR_TRACKER_TIMEOUT" \ -c "$OMR_TRACKER_COUNT" \ + -s "$OMR_TRACKER_SIZE" \ + -t "$OMR_TRACKER_MAX_TTL" \ -Q 184 \ "${host}" 2>&1 - ) && echo "$ret" | grep -sq " 0% packet loss" && { + ) + loss=$(echo "$ret" | grep 'packet loss' | sed -ne 's/.*\([0-9]\+\)% packet loss.*/\1/p') + if [ -n "$loss" ] && [ "$loss" -ne 100 ]; then if [ "$localip" = "yes" ]; then OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + OMR_TRACKER_LOSS="$loss" _update_rto "$OMR_TRACKER_LATENCY" fi return - } + fi #) && echo "$ret" | grep -sq "bytes from" && { fi false @@ -242,6 +252,7 @@ while true; do OMR_TRACKER_STATUS="ERROR" OMR_TRACKER_STATUS_MSG="" OMR_TRACKER_LATENCY= + OMR_TRACKER_LOSS= #OMR_TRACKER_TIMEOUT=$((rto / 1000 + (rto % 1000 ? 1 : 0))) OMR_TRACKER_LIST_HOSTS="" OMR_TRACKER_DEVICE_GATEWAY= @@ -259,7 +270,7 @@ while true; do if [ -n "$OMR_TRACKER_DEVICE" ] && [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep UP)" ]; then # retrieve iface ip and gateway - if [ "$OMR_TRACKER_INTERFACE_PROTO" != "dhcpv6" ]; then + if ([ "$OMR_TRACKER_FAMILY" = "ipv4" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]) && [ "$OMR_TRACKER_INTERFACE_PROTO" != "dhcpv6" ]; then OMR_TRACKER_DEVICE_IP=$(ip -4 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') if [ -z "$OMR_TRACKER_DEVICE_IP" ]; then OMR_TRACKER_DEVICE_IP=$(ip -4 addr show dev "$OMR_TRACKER_DEVICE" | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1) @@ -305,7 +316,7 @@ while true; do OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | awk '/via/ {print $3}' | tr -d "\n") fi fi - if [ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ]; then + if ([ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ] || [ -z "$OMR_TRACKER_IPV6" ]) && ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]); then #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1) @@ -331,9 +342,13 @@ while true; do fi # execute specific tracker - if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + if ([ "$OMR_TRACKER_FAMILY" = "ipv4" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then # setup loop variable - tries="$OMR_TRACKER_TRIES" + if [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ]; then + tries="$OMR_TRACKER_TRIES" + else + tries="$OMR_TRACKER_TRIES_UP" + fi # loop until tries attempts have been reached while [ "$tries" -gt 0 ]; do if [ -n "$OMR_TRACKER_DEVICE_ROUTE" ]; then @@ -430,9 +445,14 @@ while true; do sleep "$OMR_TRACKER_INTERVAL_TRIES" done fi - if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + #if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + if ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]) && [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then # setup loop variable - tries="$OMR_TRACKER_TRIES" + if [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ]; then + tries="$OMR_TRACKER_TRIES" + else + tries="$OMR_TRACKER_TRIES_UP" + fi # loop until tries attempts have been reached while [ "$tries" -gt 0 ]; do #if [ -n "$OMR_TRACKER_DEVICE_ROUTE" ]; then @@ -534,7 +554,7 @@ while true; do [ -z "$OMR_TRACKER_STATUS_MSG" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_INTERFACE may have ip issues" [ -z "$OMR_TRACKER_DEVICE_IP" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4" [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4 gateway" - if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ]; then + if ([ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ] || [ -z "$OMR_TRACKER_IPV6" ]) && ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]); then [ -z "$OMR_TRACKER_DEVICE_IP6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6" [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6 gateway" fi @@ -558,6 +578,26 @@ while true; do OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG and $OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS6)" fi fi + if [ "$OMR_TRACKER_CHECK_QUALITY" = "1" ]; then + if [ "$OMR_TRACKER_PREV_STATUS" = "OK" ]; then + if [ -n "$OMR_TRACKER_LOSS" ] && [ "$OMR_TRACKER_LOSS" -ge "$OMR_TRACKER_LOSS_FAILURE" ] && [ "$OMR_TRACKER_STATUS" = "OK" ]; then + OMR_TRACKER_STATUS="ERROR" + OMR_TRACKER_STATUS_MSG="Packet loss is $OMR_TRACKER_LOSS this is more than limit defined at $OMR_TRACKER_LOSS_FAILURE" + fi + if [ -n "$OMR_TRACKER_LATENCY" ] && [ "$OMR_TRACKER_LATENCY" -ge "$OMR_TRACKER_LATENCY_FAILURE" ] && [ "$OMR_TRACKER_STATUS" = "OK" ]; then + OMR_TRACKER_STATUS="ERROR" + OMR_TRACKER_STATUS_MSG="Latency is $OMR_TRACKER_LATENCY this is more than limit defined at $OMR_TRACKER_LATENCY_FAILURE" + fi + elif [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ]; then + OMR_TRACKER_STATUS="ERROR" + if [ -n "$OMR_TRACKER_LOSS" ] && [ "$OMR_TRACKER_LOSS" -le "$OMR_TRACKER_LOSS_RECOVERY" ] && [ "$OMR_TRACKER_STATUS" = "OK" ]; then + OMR_TRACKER_STATUS="OK" + fi + if [ -n "$OMR_TRACKER_LATENCY" ] && [ "$OMR_TRACKER_LATENCY" -ge "$OMR_TRACKER_LATENCY_RECOVERY" ] && [ "$OMR_TRACKER_STATUS" = "OK" ]; then + OMR_TRACKER_STATUS="OK" + fi + fi + fi #[ "$OMR_TRACKER_HOSTS" = "$initial_hosts" ] || [ "$OMR_TRACKER_STATUS" = "OK" ] && _post_tracking #[ "$OMR_TRACKER_STATUS" = "ERROR" ] && _restart @@ -567,5 +607,9 @@ while true; do OMR_TRACKER_PREV_STATUS="$OMR_TRACKER_STATUS" _restart - sleep "$OMR_TRACKER_INTERVAL" + if [ "$OMR_TRACKER_STATUS" = "ERROR" ]; then + sleep "$OMR_TRACKER_FAILURE_INTERVAL" + else + sleep "$OMR_TRACKER_INTERVAL" + fi done diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index 6f1e926a5..842d6bb69 100644 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -1,32 +1,38 @@ config defaults 'defaults' option enabled '1' - list hosts '4.2.2.1' - list hosts '8.8.8.8' - list hosts '80.67.169.12' - list hosts '8.8.4.4' - list hosts '9.9.9.9' - list hosts '1.0.0.1' - list hosts '114.114.115.115' - list hosts '1.2.4.8' - list hosts '80.67.169.40' - list hosts '114.114.114.114' - list hosts '1.1.1.1' - list hosts6 '2606:4700:4700::1111' - list hosts6 '2606:4700:4700::1001' - list hosts6 '2620:fe::fe' - list hosts6 '2620:fe::9' - list hosts6 '2001:4860:4860::8888' - list hosts6 '2001:4860:4860::8844' - option timeout '2' - option count '2' - option tries '3' - option interval '2' - option interval_tries '1' - option type 'ping' - option wait_test '0' - option server_http_test '0' - option restart_down '0' - option mail_alert '0' + list hosts '4.2.2.1' + list hosts '8.8.8.8' + list hosts '80.67.169.12' + list hosts '8.8.4.4' + list hosts '9.9.9.9' + list hosts '1.0.0.1' + list hosts '114.114.115.115' + list hosts '1.2.4.8' + list hosts '80.67.169.40' + list hosts '114.114.114.114' + list hosts '1.1.1.1' + list hosts6 '2606:4700:4700::1111' + list hosts6 '2606:4700:4700::1001' + list hosts6 '2620:fe::fe' + list hosts6 '2620:fe::9' + list hosts6 '2001:4860:4860::8888' + list hosts6 '2001:4860:4860::8844' + option timeout '2' + option count '2' + option tries '3' + option interval '2' + option interval_tries '1' + option type 'ping' + option wait_test '0' + option server_http_test '0' + option restart_down '0' + option mail_alert '0' + option initial_state 'online' + option family 'ipv4' + option reliability '1' + option count '2' + option failure_interval '5' + option tries_up '5' config proxy 'proxy' option enabled '1' @@ -43,6 +49,8 @@ config proxy 'proxy' option interval_tries '1' option interval '10' option mail_alert '0' + option initial_state 'online' + option family 'ipv4ipv6' config server 'server' option enabled '1' @@ -51,3 +59,4 @@ config server 'server' option wait_test '0' option interval '5' option mail_alert '0' + option initial_state 'online' \ No newline at end of file diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 2b1655ef5..009e92dd5 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -16,34 +16,54 @@ . /lib/functions/network.sh _validate_section() { - local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_count=$count tmp_tries=$tries - local tmp_interval=$interval tmp_interval_tries=$interval_tries tmp_options=$options tmp_type=$type tmp_enabled=$enabled tmp_wait_test=$wait_test tmp_server_http_test=$server_http_test + local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_count=$count tmp_tries=$tries tmp_size=$size tmp_max_ttl=$max_ttl tmp_failure_loss=$failure_loss tmp_failure_latency=$failure_latency tmp_recovery_loss=$recovery_loss tmp_recovery_latency=$recovery_latency + local tmp_interval=$interval tmp_interval_tries=$interval_tries tmp_options=$options tmp_type=$type tmp_enabled=$enabled tmp_wait_test=$wait_test tmp_server_http_test=$server_http_test tmp_check_quality=$check_quality tmp_failure_interval=$failure_interval tmp_tries_up=$tries_up tmp_family=$family uci_validate_section omr-tracker "$1" "$2" \ 'hosts:list(host)' \ 'hosts6:list(host)' \ 'timeout:uinteger' \ + 'size:uinteger' \ + 'max_ttl:uinteger' \ + 'failure_loss:uinteger' \ + 'failure_latency:uinteger' \ + 'recovery_loss:uinteger' \ + 'recovery_latency:uinteger' \ + 'check_quality:bool:0' \ 'count:uinteger' \ 'tries:uinteger' \ + 'tries_up:uinteger' \ 'interval:uinteger' \ 'interval_tries:uinteger' \ + 'failure_interval:uinteger' \ 'wait_test:uinteger' \ 'type:string:undef' \ 'enabled:bool:1' \ 'server_http_test:bool:0' \ + 'family:string' \ 'options:string' [ -z "$hosts" ] && hosts=$tmp_hosts [ -z "$hosts6" ] && hosts6=$tmp_hosts6 [ -z "$timeout" ] && timeout=$tmp_timeout [ -z "$count" ] && count=$tmp_count + [ -z "$size" ] && size=$tmp_size + [ -z "$failure_loss" ] && failure_loss=$tmp_failure_loss + [ -z "$failure_latency" ] && failure_latency=$tmp_failure_latency + [ -z "$failure_interval" ] && failure_interval=$tmp_failure_interval + [ -z "$recovery_loss" ] && recovery_loss=$tmp_recovery_loss + [ -z "$recovery_latency" ] && recovery_latency=$tmp_recovery_latency + [ -z "$check_quality" ] && check_quality=$tmp_check_quality + [ -z "$max_ttl" ] && max_ttl=$tmp_max_ttl [ -z "$tries" ] && tries=$tmp_tries + [ -z "$tries_up" ] && tries_up=$tmp_tries_up [ -z "$interval" ] && interval=$tmp_interval [ -z "$interval_tries" ] && interval_tries=$tmp_interval_tries [ -z "$wait_test" ] && wait_test=$tmp_wait_test [ -z "$options" ] && options=$tmp_options [ "$type" = "undef" ] && type=${tmp_type:-ping} [ -z "$server_http_test" ] && server_http_test=$tmp_server_http_test + [ -z "$family" ] && family=$tmp_family [ -z "$enabled" ] && enabled=$tmp_enabled } @@ -52,7 +72,7 @@ _launch_tracker() { loopback|lan*|if0*) return;; esac [ -z "$1" ] && return - local hosts hosts6 timeout count tries interval interval_tries options type enabled wait_test ipv6 proto server_http_test + local hosts hosts6 timeout count tries tries_up interval interval_tries options type enabled wait_test ipv6 proto server_http_test size max_ttl failure_loss failure_interval failure_latency recovery_loss recovery_latency family _validate_section "defaults" "defaults" _validate_section "interface" "$1" @@ -80,6 +100,11 @@ _launch_tracker() { #[ "${ifstatus}" = "false" ] && [ -z "${ifdevice}" ] && return [ -z "${interval_tries}" ] && interval_tries=1 [ -z "${count}" ] && count=2 + [ -z "${max_ttl}" ] && max_ttl=60 + [ -z "${size}" ] && size=56 + [ -z "${check_quality}" ] && check_quality=0 + [ -z "${tries}" ] && tries=5 + [ -z "${tries_up}" ] && tries_up=${tries} procd_open_instance # shellcheck disable=SC2086 @@ -87,14 +112,24 @@ _launch_tracker() { procd_append_param env "OMR_TRACKER_HOSTS=$hosts" procd_append_param env "OMR_TRACKER_HOSTS6=$hosts6" procd_append_param env "OMR_TRACKER_TIMEOUT=$timeout" + procd_append_param env "OMR_TRACKER_SIZE=$size" + procd_append_param env "OMR_TRACKER_CHECK_QUALITY=$check_quality" + procd_append_param env "OMR_TRACKER_MAX_TTL=$max_ttl" + procd_append_param env "OMR_TRACKER_FAILURE_LOSS=$failure_loss" + procd_append_param env "OMR_TRACKER_FAILURE_LATENCY=$failure_latency" + procd_append_param env "OMR_TRACKER_RECOVERY_LOSS=$recovery_loss" + procd_append_param env "OMR_TRACKER_RECOVERY_LATENCY=$recovery_latency" procd_append_param env "OMR_TRACKER_COUNT=$count" procd_append_param env "OMR_TRACKER_TRIES=$tries" + procd_append_param env "OMR_TRACKER_TRIES_UP=$tries_up" procd_append_param env "OMR_TRACKER_INTERVAL=$interval" + procd_append_param env "OMR_TRACKER_FAILURE_INTERVAL=$failure_interval" procd_append_param env "OMR_TRACKER_INTERVAL_TRIES=$interval_tries" procd_append_param env "OMR_TRACKER_TABLE=$ip4table" procd_append_param env "OMR_TRACKER_DEVICE=$ifname" procd_append_param env "OMR_TRACKER_DEVICE_GATEWAY=$gateway" procd_append_param env "OMR_TRACKER_TYPE=$type" + procd_append_param env "OMR_TRACKER_FAMILY=$family" procd_append_param env "OMR_TRACKER_IPV6=$ipv6" procd_append_param env "OMR_TRACKER_PROTO=$proto" procd_append_param env "OMR_TRACKER_WAIT_TEST=$wait_test" diff --git a/omr-tracker/files/etc/uci-defaults/omr-tracker b/omr-tracker/files/etc/uci-defaults/omr-tracker index 55d8d4ee6..4bfe538c6 100755 --- a/omr-tracker/files/etc/uci-defaults/omr-tracker +++ b/omr-tracker/files/etc/uci-defaults/omr-tracker @@ -106,4 +106,26 @@ if [ "$(uci -q get omr-tracker.defaults.server_http_test)" = "" ]; then EOF fi +if [ "$(uci -q get omr-tracker.defaults.family)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set omr-tracker.defaults.initial_state='online' + set omr-tracker.defaults.family='ipv4ipv6' + set omr-tracker.defaults.reliability='1' + set omr-tracker.defaults.interval='1' + set omr-tracker.defaults.failure_interval='5' + set omr-tracker.defaults.count='1' + set omr-tracker.defaults.tries_up='5' + set omr-tracker.omrvpn.initial_state='online' + set omr-tracker.omrvpn.family='ipv4' + set omr-tracker.omrvpn.reliability='1' + set omr-tracker.omrvpn.failure_interval='5' + set omr-tracker.omrvpn.tries_up='5' + set omr-tracker.omrvpn.count='1' + set omr-tracker.proxy.initial_state='online' + set omr-tracker.proxy.family='ipv4ipv6' + set omr-tracker.server.initial_state='online' + commit omr-tracker + EOF +fi + exit 0 \ No newline at end of file diff --git a/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker b/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker index 882e4b0a7..80f104be9 100755 --- a/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker +++ b/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker @@ -15,6 +15,12 @@ if [ "$(uci -q get omr-tracker.omrvpn)" = "" ]; then set omr-tracker.omrvpn.restart_down=0 add_list omr-tracker.omrvpn.hosts='4.2.2.1' add_list omr-tracker.omrvpn.hosts='8.8.8.8' + set omr-tracker.omrvpn.initial_state='online' + set omr-tracker.omrvpn.family='ipv4' + set omr-tracker.omrvpn.reliability='1' + set omr-tracker.omrvpn.count='1' + set omr-tracker.omrvpn.failure_interval='5' + set omr-tracker.omrvpn.tries_up='5 commit omr-tracker EOF fi From e05c057c634e2e9a6f343c47a2fb9dd99380de9c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 17:29:21 +0100 Subject: [PATCH 1290/2059] Commit latencies --- mptcp/files/usr/share/omr/post-tracking.d/021-latencies | 1 + 1 file changed, 1 insertion(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/021-latencies b/mptcp/files/usr/share/omr/post-tracking.d/021-latencies index bc9c08f5b..f89d70288 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/021-latencies +++ b/mptcp/files/usr/share/omr/post-tracking.d/021-latencies @@ -42,6 +42,7 @@ interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e fi fi fi + [ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter } if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then From d2fce4961e3de29ada2f2c9092e01218b6a9beeb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 17:29:57 +0100 Subject: [PATCH 1291/2059] Limit redirections to LAN --- v2ray-core/files/etc/init.d/v2ray-nft | 1 + xray-core/files/etc/init.d/xray-nft | 1 + 2 files changed, 2 insertions(+) diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft index 90d5732f8..4a4d373e5 100755 --- a/v2ray-core/files/etc/init.d/v2ray-nft +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -472,6 +472,7 @@ add_v2ray_redirect_rules() { | sort -u)" [ "$(uci -q get v2ray.main_transparent_proxy.redirect_udp)" = "1" ] && [ "$(uci -q get v2ray.omrout.protocol)" != "socks" ] && portudp="$port" + ifnames="$(uci -q get shadowsocks-libev.ss_rules.ifnames)" local tmp="/tmp/v2rrules" json_init diff --git a/xray-core/files/etc/init.d/xray-nft b/xray-core/files/etc/init.d/xray-nft index 1c0e85af3..5b7d3bb0c 100755 --- a/xray-core/files/etc/init.d/xray-nft +++ b/xray-core/files/etc/init.d/xray-nft @@ -481,6 +481,7 @@ add_xray_redirect_rules() { | sort -u)" [ "$(uci -q get xray.main_transparent_proxy.redirect_udp)" = "1" ] && [ "$(uci -q get xray.omrout.protocol)" != "socks" ] && portudp="$port" + ifnames="$(uci -q get shadowsocks-libev.ss_rules.ifnames)" local tmp="/tmp/xrrules" json_init From 5f95c9896994355a34f6fa47d35e74213d59c05d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 17:37:52 +0100 Subject: [PATCH 1292/2059] Fix output interface when master down --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 40c4308bf..fbd576f8e 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -828,6 +828,10 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then config_load network config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" + elif [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$(ip r show table 991337 | grep "$OMR_TRACKER_DEVICE ")" ]; then + config_load network + config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" fi fi if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then From d707e5cdede91748ba52b54b69b0c7a5ed0af82a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:21:28 +0100 Subject: [PATCH 1293/2059] Restore iptables script of omr-bypass --- omr-bypass/files/etc/init.d/omr-bypass | 751 +++++++++++++++---------- 1 file changed, 442 insertions(+), 309 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass b/omr-bypass/files/etc/init.d/omr-bypass index 8d2ef20c6..1d292c55a 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass +++ b/omr-bypass/files/etc/init.d/omr-bypass @@ -1,5 +1,5 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Copyright (C) 2018-2020 Ycarus (Yannick Chabanois) START=98 STOP=10 @@ -8,14 +8,13 @@ EXTRA_COMMANDS="reload_rules bypass_asn" . /usr/lib/unbound/iptools.sh -# Still used by ndpi -if [ -e /usr/sbin/iptables-nft ]; then - IPTABLES="/usr/sbin/iptables-nft" - IPTABLESRESTORE="/usr/sbin/iptables-nft-restore" - IPTABLESSAVE="/usr/sbin/iptables-nft-save" - IP6TABLES="/usr/sbin/ip6tables-nft" - IP6TABLESRESTORE="/usr/sbin/ip6tables-nft-restore" - IP6TABLESSAVE="/usr/sbin/ip6tables-nft-save" +if [ -f /usr/sbin/iptables-legacy ]; then + IPTABLES="/usr/sbin/iptables-legacy" + IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" + IPTABLESSAVE="/usr/sbin/iptables-legacy-save" + IP6TABLES="/usr/sbin/ip6tables-legacy" + IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" else IPTABLES="/usr/sbin/iptables" IPTABLESRESTORE="/usr/sbin/iptables-restore" @@ -59,13 +58,9 @@ _bypass_ip() { valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then - uci -q add_list firewall.omr_dst_bypass_${type}_4.entry=$ip - uci -q set firewall.omr_dst_bypass_${type}_4.enabled='1' - uci -q set firewall.omr_dst_bypass_${type}_dstip_4.enabled='1' + ipset -q add omr_dst_bypass_$type $ip elif [ "$valid_ip6" = "ok" ]; then - uci -q add_list firewall.omr_dst_bypass_${type}_6.entry=$ip - uci -q set firewall.omr_dst_bypass_${type}_6.enabled='1' - uci -q set firewall.omr_dst_bypass_${type}_dstip_6.enabled='1' + ipset -q add omr6_dst_bypass_$type $ip fi } @@ -81,7 +76,6 @@ _bypass_domains() { [ -z "$intf" ] && intf="all" config_get vpn $1 vpn [ "$vpn" = "1" ] && intf="srv_vpn1" - #echo "bypass $domain $enabled $family $intf $vpn" [ "$enabled" = "0" ] && return [ -z "$domain" ] && return [ -z "$family" ] && family="ipv4ipv6" @@ -113,7 +107,6 @@ _bypass_domains() { _bypass_domain $validdomain $intf $family $noipv6 done else - #echo "_bypass_domain $domain $intf $family $noipv6" _bypass_domain $domain $intf $family $noipv6 fi } @@ -124,6 +117,7 @@ _bypass_domain() { local family=$3 local noipv6=$4 intf=$(echo $intf | sed -e 's/\./_/') + [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return [ -z "$intf" ] && intf="all" if [ -n "$domain" ]; then domain=$(echo $domain | sed 's:^\.::') @@ -140,13 +134,35 @@ _bypass_domain() { done fi fi - if [ "$(uci -q get dhcp.omr_dst_bypass_$intf | grep /$domain/)" = "" ]; then - uci -q add_list dhcp.omr_dst_bypass_$intf.domain=$domain + if [ "$(uci -q get dhcp.@dnsmasq[0].ipset | grep /$domain/)" = "" ]; then + if [ "$family" = "ipv4ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + elif [ "$family" = "ipv4" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf" + elif [ "$family" = "ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr6_dst_bypass_$intf" + fi add_domains="true" + else + dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g') + for dnsipset in $dnsmasqipset; do + if [ "$(echo $dnsipset | cut -d/ -f2)" = "$domain" ]; then + uci -q del_list dhcp.@dnsmasq[0].ipset=$dnsipset + if [ "$family" = "ipv4ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf,omr6_dst_bypass_$intf" + elif [ "$family" = "ipv4" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf" + elif [ "$family" = "ipv6" ]; then + uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr6_dst_bypass_$intf" + fi + add_domains="true" + fi + done fi if [ "$(uci -q get dhcp.@dnsmasq[0].noipv6 | grep /$domain/)" = "" ] && [ "$noipv6" = "1" ]; then uci -q add_list dhcp.@dnsmasq[0].noipv6="$domain" fi + #logger -t "omr-bypass" "Get IPs of $domain... Done" fi } @@ -160,13 +176,38 @@ _bypass_mac() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') + [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$mac" ] && return - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_$intf_mac.src_mac="$mac" - EOF + if [ "$intf" = "all" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539 + COMMIT + EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539 + COMMIT + EOF + fi + else + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539$intfid + COMMIT + EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539$intfid + COMMIT + EOF + fi + fi } _bypass_lan_ip() { @@ -185,16 +226,44 @@ _bypass_lan_ip() { [ -z "$ip" ] && return valid_ip4=$(valid_subnet4 $ip) valid_ip6=$(valid_subnet6 $ip) - if [ "$valid_ip4" = "ok" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_srcip_4.src_ip="$ip" - set firewall.omr_dst_bypass_${intf}_srcip_4.enabled='1' - EOF - elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_srcip_6.src_ip="$ip" - set firewall.omr_dst_bypass_${intf}_srcip_6.enabled='1' - EOF + if [ "$intf" = "all" ]; then + if [ "$valid_ip4" = "ok" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass -s $ip -j MARK --set-mark 0x539 + COMMIT + EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-local -s $ip -j MARK --set-mark 0x539 + COMMIT + EOF + elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539 + COMMIT + EOF + fi + else + if [ "$valid_ip4" = "ok" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass -s $ip -j MARK --set-mark 0x539$intfid + COMMIT + EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-local -s $ip -j MARK --set-mark 0x539$intfid + COMMIT + EOF + elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539$intfid + COMMIT + EOF + fi fi } @@ -209,24 +278,49 @@ _bypass_dest_port() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$dport" ] && return dport="$(echo $dport | sed 's/-/:/')" [ -z "$proto" ] && return - if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dst_port="$dport" - set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' + if [ "$intf" = "all" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 + COMMIT EOF - fi - if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dst_port="$dport" - set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 + COMMIT EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539 + COMMIT + EOF + fi + else + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid + COMMIT + EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid + COMMIT + EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539$intfid + COMMIT + EOF + fi fi } @@ -241,24 +335,49 @@ _bypass_src_port() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$sport" ] && return sport="$(echo $sport | sed 's/-/:/')" [ -z "$proto" ] && return - if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dst_port="$dport" - set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' + if [ "$intf" = "all" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539 + COMMIT EOF - fi - if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dst_port="$dport" - set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539 + COMMIT EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539 + COMMIT + EOF + fi + else + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid + COMMIT + EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid + COMMIT + EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539$intfid + COMMIT + EOF + fi fi } @@ -279,7 +398,7 @@ _bypass_proto() { [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" intf=$(echo $intf | sed -e 's/\./_/') - #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" @@ -289,8 +408,8 @@ _bypass_proto() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539 - -A omr-bypass-dpi -m mark --mark 0x4539 -j RETURN + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 + -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN COMMIT EOF fi @@ -306,8 +425,8 @@ _bypass_proto() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539$intfid - -A omr-bypass-dpi -m mark --mark 0x4539$intfid -j RETURN + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid + -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN COMMIT EOF fi @@ -378,84 +497,74 @@ _bypass_proto_without_ndpi() { [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" intf=$(echo $intf | sed -e 's/\./_/') - #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" - [ "$intf" = "all" ] && intfid="" [ -z "$proto" ] && return if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ] || [ "$vpn" = "1" ]; then ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") if [ -n "$ALLIPS" ]; then if [ "$vpn" != "1" ]; then - uci -q batch <<-EOF >/dev/null - set firewall.bypass_$proto=ipset - set firewall.bypass_$proto.name="bypass_$proto" - set firewall.bypass_$proto.match='dest_ip' - set firewall.bypass_$proto_rule=rule - set firewall.bypass_$proto_rule.name="bypass_$proto" - set firewall.bypass_$proto_rule.src='lan' - set firewall.bypass_$proto_rule.dest='*' - set firewall.bypass_$proto_rule.target='MARK' - set firewall.bypass_$proto_rule.set_xmark="4539${intfid}" - commit firewall + ipset -q flush bypass_$proto > /dev/null 2>&1 + ipset -q flush bypass6_$proto > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create bypass_$proto hash:net hashsize 64 + create bypass6_$proto hash:net family inet6 hashsize 64 EOF - uci -q batch <<-EOF >/dev/null - set firewall.bypass6_$proto=ipset - set firewall.bypass6_$proto.name="bypas6s_$proto" - set firewall.bypass6_$proto.match='dest_ip' - set firewall.bypass6_$proto_rule=rule - set firewall.bypass6_$proto_rule.name="bypass6_$proto" - set firewall.bypass6_$proto_rule.src='lan' - set firewall.bypass6_$proto_rule.dest='*' - set firewall.bypass6_$proto_rule.target='MARK' - set firewall.bypass6_$proto_rule.set_xmark="6539${intfid}" - commit firewall - EOF - #if [ "$intfid" != "" ]; then - # uci -q batch <<-EOF >/dev/null - # delete network.${1}_fw_rule=rule - # set network.${1}_fw_rule=rule - # set network.${1}_fw_rule.priority=1 - # set network.${1}_fw_rule.mark=0x539${intfid} - # set network.${1}_fw_rule.lookup=${intfid} - # delete network.${1}_fw_rule6=rule6 - # set network.${1}_fw_rule6=rule6 - # set network.${1}_fw_rule6.priority=1 - # set network.${1}_fw_rule6.mark=0x6539${intfid} - # set network.${1}_fw_rule6.lookup=${intfid} - # commit network - # EOF - #fi - - #ipset -q flush bypass_$proto > /dev/null 2>&1 - #ipset -q flush bypass6_$proto > /dev/null 2>&1 - #ipset -q --exist restore <<-EOF - #create bypass_$proto hash:net hashsize 64 - #create bypass6_$proto hash:net family inet6 hashsize 64 - #EOF fi for ip in $ALLIPS; do valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then if [ "$vpn" != "1" ]; then - #ipset -q add bypass_$proto $ip - uci -q add_list firewall.bypass_$proto.entry=$ip + ipset -q add bypass_$proto $ip else - #ipset -q add omr_dst_bypass_$intf $ip - uci -q add_list firewall.omr_dst_bypass_$intf_4.entry=$ip + ipset -q add omr_dst_bypass_$intf $ip fi elif [ "$valid_ip6" = "ok" ]; then if [ "$vpn" != "1" ]; then - #ipset -q add bypass6_$proto $ip - uci -q add_list firewall.bypass6_$proto.entry=$ip + ipset -q add bypass6_$proto $ip else - #ipset -q add omr6_dst_bypass_$intf $ip - uci -q add_list firewall.omr6_dst_bypass_$intf_4.entry=$ip + ipset -q add omr6_dst_bypass_$intf $ip fi fi done + if [ "$intf" = "all" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539 + -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN + COMMIT + EOF + fi + elif [ "$vpn" != "1" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539$intfid + -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN + COMMIT + EOF + fi + fi fi fi # Use dnsmasq ipset to bypass domains of the proto @@ -500,16 +609,53 @@ _bypass_proto_without_ndpi() { } _intf_rule_ss_rules() { - cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept - nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept - EOF - if [ "$disableipv6" = "0" ]; then - cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept - nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + rule_name=$1 + [ "$rule_name" = "ss_rules" ] && rule_name="def" + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *nat + -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I ssr_${rule_name}_dst 2 -m mark --mark 0x539$count -j RETURN + COMMIT EOF fi + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *nat + -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539$count -j RETURN + COMMIT + EOF + fi + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *nat + -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539$count -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ]; then + if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep omr6_dst_bypass_$intf)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -I omr-bypass6 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count + COMMIT + EOF + fi + if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLESSAVE 2>/dev/null | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *nat + -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count + -I ssr6_${rule_name}_dst 2 -m mark --mark 0x6539$count -j RETURN + -I ssr6_${rule_name}_local_out 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count + -I ssr6_${rule_name}_local_out 2 -m mark --mark 0x6539$count -j RETURN + -I ssr6_${rule_name}_pre_src 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count + -I ssr6_${rule_name}_pre_src 2 -m mark --mark 0x6539$count -j RETURN + COMMIT + EOF + fi + fi } _intf_rule_v2ray_rules() { @@ -620,133 +766,56 @@ _intf_rule_xray_rules() { _intf_rule() { local intf - [ "$1" = "all" ] && intf="all" - [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') [ -z "$intf" ] && config_get intf $1 device [ -n "$(echo $intf | grep '/')" ] && return #count=$((count+1)) - [ "$intf" != "all" ] && config_get count $1 metric - [ "$intf" = "all" ] && count="" + config_get count $1 metric local mode #config_get mode $1 multipath "off" #[ "$mode" = "off" ] && return - [ "$intf" != "all" ] && [ -z "$count" ] && return + [ -z "$count" ] && return [ -z "$intf" ] && return intf=$(echo $intf | sed -e 's/\./_/') - intf=$(echo $intf | sed -e 's/-/_/') [ "$(echo $1 | grep _dev)" != "" ] && return - [ "$intf" = "lo" ] && return - [ -z "$intf" ] && return -# [ -z "$RELOAD" ] || [ "$(uci show firewall.omr_dst_bypass_$intf_4)" = "" ] && { - #unset RELOAD - #echo "$intf ip set dhcp" - uci batch <<-EOF - set dhcp.omr_dst_bypass_$intf=ipset - set dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4,omr_dst_bypass_${intf}_6" - commit dhcp + [ -z "$RELOAD" ] || [ "$(ipset --list | grep omr_dst_bypass_$intf)" = "" ] && { + unset RELOAD + ipset -q flush omr_dst_bypass_$intf > /dev/null 2>&1 + ipset -q flush omr6_dst_bypass_$intf > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create omr_dst_bypass_$intf hash:net hashsize 64 + create omr6_dst_bypass_$intf hash:net family inet6 hashsize 64 EOF - #echo "firewall omr_dst_bypass ipset" - uci -q batch <<-EOF - set firewall.omr_dst_bypass_${intf}_4=ipset - set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" - set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' - EOF - #echo "firewall omr_dst_bypass rules" - if [ "$disableipv6" = "0" ]; then - protocol="4 6" - else - protocol="4" - fi - for ipv46 in $protocol; do - echo "ipv46: $ipv46 for $intf" - uci batch <<-EOF - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_xmark="${ipv46}539${count}" - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.name="omr_dst_bypass_${intf}_srcip" - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.src='lan' - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="${ipv46}539${count}" - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}=rule - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.name='omr_dst_bypass_${intf}_mac' - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src='lan' - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.target='MARK' - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.set_xmark="${ipv46}539${count}" - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}=rule - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.proto='tcp' - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.src='lan' - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.target='MARK' - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}=rule - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.proto='udp' - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.src='lan' - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.target='MARK' - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.set_xmark="${ipv46}539${count}" - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}=rule - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.src='lan' - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.target='MARK' - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}=rule - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.src='lan' - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.target='MARK' - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="${ipv46}539${count}" - commit firewall - EOF - done - if [ "$intf" = "all" ]; then + if [ "$(uci -q get openmptcprouter.settings.uci_rules)" = "1" ]; then uci -q batch <<-EOF >/dev/null - delete network.${intf}_fw_rule=rule - set network.${intf}_fw_rule=rule - set network.${intf}_fw_rule.priority=1 - set network.${intf}_fw_rule.mark=0x4539 - set network.${intf}_fw_rule.lookup=991337 - delete network.${intf}_fw_rule6=rule6 - set network.${intf}_fw_rule6=rule6 - set network.${intf}_fw_rule6.priority=1 - set network.${intf}_fw_rule6.mark=0x6539 - set network.${intf}_fw_rule6.lookup=6991337 + delete network.${1}_fw_rule=rule + set network.${1}_fw_rule=rule + set network.${1}_fw_rule.priority=1 + set network.${1}_fw_rule.mark=0x539${count} + set network.${1}_fw_rule.lookup=${count} + delete network.${1}_fw_rule6=rule6 + set network.${1}_fw_rule6=rule6 + set network.${1}_fw_rule6.priority=1 + set network.${1}_fw_rule6.mark=0x6539${count} + set network.${1}_fw_rule6.lookup=${count} commit network EOF else - uci -q batch <<-EOF >/dev/null - delete network.${intf}_fw_rule=rule - set network.${intf}_fw_rule=rule - set network.${intf}_fw_rule.priority=1 - set network.${intf}_fw_rule.mark=0x4539${count} - set network.${intf}_fw_rule.lookup=${count} - delete network.${intf}_fw_rule6=rule6 - set network.${intf}_fw_rule6=rule6 - set network.${intf}_fw_rule6.priority=1 - set network.${intf}_fw_rule6.mark=0x6539${count} - set network.${intf}_fw_rule6.lookup=${count} - commit network - EOF + ip rule add prio 1 fwmark 0x539$count lookup $count pref 1 > /dev/null 2>&1 + ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count pref 1 > /dev/null 2>&1 fi - + } + if [ "$($IPTABLESSAVE 2>/dev/null | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I omr-bypass 2 -m mark --mark 0x539$count -j RETURN + -I omr-bypass-local 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count + -I omr-bypass-local 2 -m mark --mark 0x539$count -j RETURN + COMMIT + EOF + fi if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then config_load shadowsocks-libev config_foreach _intf_rule_ss_rules ss_rules @@ -787,6 +856,7 @@ _bypass_asn() { for ip in $asnips; do _bypass_ip $ip $interface done + } bypass_asn() { @@ -802,16 +872,41 @@ _bypass_omr_server() { _ss_rules_config() { - cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept - nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 accept - EOF - if [ "$disableipv6" = "0" ]; then - cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept - nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + rule_name=$1 + [ "$rule_name" = "ss_rules" ] && rule_name="def" + if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLES --wait=40 -t nat -L -n | grep omr_dst_bypass_all)" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *nat + -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 + -I ssr_${rule_name}_dst 2 -m mark --mark 0x539 -j RETURN + -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 + -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539 -j RETURN + -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 + -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539 -j RETURN + COMMIT EOF fi + if [ "$disableipv6" = "0" ]; then + if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 + COMMIT + EOF + fi + if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLES --wait=40 -t nat -L -n | grep omr6_dst_bypass_all)" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *nat + -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 + -I ssr6_${rule_name}_dst 1 -m mark --mark 0x6539 -j RETURN + -I ssr6_${rule_name}_local_out 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 + -I ssr6_${rule_name}_local_out 2 -m mark --mark 0x6539 -j RETURN + -I ssr6_${rule_name}_pre_src 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 + -I ssr6_${rule_name}_pre_src 2 -m mark --mark 0x6539 -j RETURN + COMMIT + EOF + fi + fi } _v2ray_rules_config() { @@ -892,18 +987,6 @@ _xray_rules_config() { fi } -_delete_dhcp_ipset() { - [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { - uci -q delete dhcp.$1 - } -} - -_delete_firewall_rules() { - [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { - uci -q delete firewall.$1 - } -} - boot() { BOOT=1 start "$@" @@ -912,16 +995,6 @@ boot() { start_service() { #local count logger -t "omr-bypass" "Starting OMR-ByPass..." - - config_load dhcp - config_foreach _delete_dhcp_ipset ipset - #uci -q commit dhcp - config_load firewall - config_foreach _delete_firewall_rules rule - config_foreach _delete_firewall_rules ipset - #uci -q commit firewall - - add_domains="false" [ -d /proc/net/xt_ndpi ] && { config_load omr-bypass @@ -930,58 +1003,128 @@ start_service() { disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" #noipv6="$(uci -q get omr-bypass.global.noipv6)" - cat > /etc/firewall.omr-bypass <<-EOF - #!/bin/sh - #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all accept - #nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all accept + [ -n "$RELOAD" ] && [ "$(ipset --list | grep omr_dst_bypass_all)" = "" ] && { + unset RELOAD + } + [ -z "$RELOAD" ] && { + ipset -q flush omr_dst_bypass_all > /dev/null 2>&1 + ipset -q flush omr6_dst_bypass_all > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create omr_dst_bypass_all hash:net hashsize 64 + create omr6_dst_bypass_all hash:net family inet6 hashsize 64 + EOF + ipset -q flush omr_dst_bypass_srv_vpn1 > /dev/null 2>&1 + ipset -q flush omr6_dst_bypass_srv_vpn1 > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create omr_dst_bypass_srv_vpn1 hash:net hashsize 64 + create omr6_dst_bypass_srv_vpn1 hash:net family inet6 hashsize 64 + EOF + } + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass - + -A PREROUTING -j omr-bypass + COMMIT EOF - uci batch <<-EOF - set firewall.omr_bypass=include - set firewall.omr_bypass.enabled='1' - set firewall.omr_bypass.type='script' - set firewall.omr_bypass.path='/etc/firewall.omr-bypass' - set firewall.omr_bypass.fw4_compatible='1' - commit firewall + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass-local - + -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-local + COMMIT EOF - echo "intf_rule" + if [ "$disableipv6" = "0" ]; then + $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass6 - + -A PREROUTING -j omr-bypass6 + COMMIT + EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass6-local - + -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass6-local + COMMIT + EOF + fi + config_load network config_foreach _intf_rule interface - _intf_rule all local ndpi_rules="" - echo "bypass server" if [ "$(uci -q get openmptcprouter.settings.bypass_servers)" = "1" ]; then config_load openmptcprouter config_foreach _bypass_omr_server server fi config_load omr-bypass - echo "bypass ip" config_foreach _bypass_ip_set ips - echo "bypass mac" config_foreach _bypass_mac macs - echo "bypass lan ip" config_foreach _bypass_lan_ip lan_ip - echo "bypass dest port" config_foreach _bypass_dest_port dest_port - echo "bypass src port" config_foreach _bypass_src_port src_port - echo "bypass asn" config_foreach _bypass_asn asns - echo "bypass domains" + dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g' | grep -v dst_bypass) + uci -q delete dhcp.@dnsmasq[0].ipset + uci -q delete dhcp.@dnsmasq[0].noipv6 + if [ -n "$dnsmasqipset" ]; then + for dnsipset in $dnsmasqipset; do + ipsets="" + allipsets=$(echo $dnsipset | cut -d/ -f3 | sed 's/,/\n/g') + for ipset in $allipsets; do + [ "$(echo $ipset | grep -v dst_bypass)" != "" ] && { + [ "$ipsets" != "" ] && ipsets="$ipsets,$ipset" + [ "$ipsets" = "" ] && ipsets="$ipset" + } + done + if [ "$ipsets" != "" ]; then + resultipset="/$(echo $dnsipset | cut -d/ -f2)/$ipsets" + [ -n "$resultipset" ] && uci -q add_list dhcp.@dnsmasq[0].ipset=$resultipset + fi + done + fi config_foreach _bypass_domains domains uci -q commit dhcp -# ip rule add prio 1 fwmark 0x4539 lookup 991337 > /dev/null 2>&1 -# ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 + ip rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 + ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 - #config_load shadowsocks-libev - #config_foreach _ss_rules_config ss_rules - ([ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] || [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]) && _ss_rules_config - #config_load shadowsocks-rust - #config_foreach _ss_rules_config ss_rules + if [ "$($IPTABLES --wait=40 -t mangle -L -n | grep 'match-set omr_dst_bypass_all dst MARK set')" = "" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass -m mark --mark 0x539 -j RETURN + COMMIT + EOF + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-local -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass-local -m mark --mark 0x539 -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ]; then + if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass6 -m mark --mark 0x539 -j RETURN + COMMIT + EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-local -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass6-local -m mark --mark 0x539 -j RETURN + COMMIT + EOF + fi + fi + config_load shadowsocks-libev + config_foreach _ss_rules_config + config_load shadowsocks-rust + config_foreach _ss_rules_config _v2ray_rules_config _xray_rules_config - # NDPI Netfilter is not available for nftables $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass-dpi | $IPTABLESRESTORE -w --counters 2>/dev/null $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle @@ -1013,7 +1156,7 @@ start_service() { logger -t "omr-bypass" "Reload dnsmasq..." /etc/init.d/dnsmasq reload } - fw4 restart + # Create a protocol list for UI from a sqlite DB when NDPI is not available sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass @@ -1025,25 +1168,15 @@ start_service() { stop_service() { $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null -# $IPTABLESSAVE --counters 2>/dev/null | grep -v omr_dst | $IPTABLESRESTORE -w --counters 2>/dev/null + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr_dst | $IPTABLESRESTORE -w --counters 2>/dev/null $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null -# $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr6_dst | $IP6TABLESRESTORE -w --counters 2>/dev/null - #for setname in $(ipset -n list | grep "omr_"); do - # ipset -q destroy "$setname" 2>/dev/null || true - #done - #for setname in $(ipset list | awk '/Name: bypass_/ {print $2}'); do - # ipset -q destroy "$setname" 2>/dev/null || true - #done - # disable all rules ? - uci -q set firewall.omr-bypass.enabled='0' - config_load dhcp - config_foreach _delete_dhcp_ipset ipset - uci -q commit dhcp - config_load firewall - config_foreach _delete_firewall_rules rule - config_foreach _delete_firewall_rules ipset - uci -q commit firewall - exit 0 + $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr6_dst | $IP6TABLESRESTORE -w --counters 2>/dev/null + for setname in $(ipset -n list | grep "omr_"); do + ipset -q destroy "$setname" 2>/dev/null || true + done + for setname in $(ipset list | awk '/Name: bypass_/ {print $2}'); do + ipset -q destroy "$setname" 2>/dev/null || true + done } service_triggers() { From e217e67bff55529627f0355b972cda5faba00031 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:21:52 +0100 Subject: [PATCH 1294/2059] Comment log info in omr-bypass nft --- omr-bypass/files/etc/init.d/omr-bypass-nft | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 3552b3c33..c6a1c9af8 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -580,7 +580,7 @@ _intf_rule() { protocol="4" fi for ipv46 in $protocol; do - echo "ipv46: $ipv46 for $intf" + #echo "ipv46: $ipv46 for $intf" uci batch <<-EOF set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" @@ -812,31 +812,31 @@ start_service() { set firewall.omr_bypass.fw4_compatible='1' commit firewall EOF - echo "intf_rule" + #echo "intf_rule" config_load network config_foreach _intf_rule interface _intf_rule all _intf_rule srv_vpn1 local ndpi_rules="" - echo "bypass server" + #echo "bypass server" if [ "$(uci -q get openmptcprouter.settings.bypass_servers)" = "1" ]; then config_load openmptcprouter config_foreach _bypass_omr_server server fi config_load omr-bypass - echo "bypass ip" + #echo "bypass ip" config_foreach _bypass_ip_set ips - echo "bypass mac" + #echo "bypass mac" config_foreach _bypass_mac macs - echo "bypass lan ip" + #echo "bypass lan ip" config_foreach _bypass_lan_ip lan_ip - echo "bypass dest port" + #echo "bypass dest port" config_foreach _bypass_dest_port dest_port - echo "bypass src port" + #echo "bypass src port" config_foreach _bypass_src_port src_port - echo "bypass asn" + #echo "bypass asn" config_foreach _bypass_asn asns - echo "bypass domains" + #echo "bypass domains" config_foreach _bypass_domains domains uci -q commit dhcp @@ -883,7 +883,7 @@ start_service() { logger -t "omr-bypass" "Reload dnsmasq..." /etc/init.d/dnsmasq reload } - fw4 restart + fw4 -q restart # Create a protocol list for UI from a sqlite DB when NDPI is not available sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass @@ -906,7 +906,7 @@ stop_service() { config_foreach _delete_firewall_rules rule config_foreach _delete_firewall_rules ipset uci -q commit firewall - fw4 restart + fw4 -q restart exit 0 } From 29f02336188f56d5461d73bbf2059a9990ee33a8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:22:15 +0100 Subject: [PATCH 1295/2059] remove fw4 log from omr-dscp --- omr-dscp/files/etc/init.d/omr-dscp-nft | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-dscp/files/etc/init.d/omr-dscp-nft b/omr-dscp/files/etc/init.d/omr-dscp-nft index 69081ac7e..bf764b6e9 100755 --- a/omr-dscp/files/etc/init.d/omr-dscp-nft +++ b/omr-dscp/files/etc/init.d/omr-dscp-nft @@ -152,7 +152,7 @@ _cleanup() { config_foreach _remove_rules uci -q commit dhcp uci -q commit firewall - fw4 restart + fw4 -q restart } start_service() { @@ -171,7 +171,7 @@ start_service() { config_foreach _add_dscp_rules classify config_foreach _add_dscp_domain domains uci -q commit dhcp - fw4 restart + fw4 -q restart } stop_service() { From 6194f82b39bb6c60a906d1fa29ea31786f20eeb0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:22:39 +0100 Subject: [PATCH 1296/2059] Remove fw4 logs from Shadowsocks-libev --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index 3db4bbc56..b53160515 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -181,7 +181,7 @@ ss_rules_nft_gen() { echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" if nft -f "$tmp.nft.chk" -c; then mv "$tmp.nft" "$ssrules_nft" - fw4 restart + fw4 -q restart fi rm -f "$tmp.nft.chk" fi @@ -192,7 +192,7 @@ ss_rules_nft_gen() { ss_rules_nft_reset() { if [ -f "$ssrules_nft" ]; then rm -f "$ssrules_nft" - fw4 restart + fw4 -q restart fi } @@ -205,14 +205,14 @@ ss_rules() { rules_up() { if [ -f "${ssrules_nft}.down" ]; then mv -f "${ssrules_nft}.down" "$ssrules_nft" - fw4 restart + fw4 -q restart fi } rules_down() { if [ -f "${ssrules_nft}" ]; then mv -f "$ssrules_nft" "${ssrules_nft}.down" - fw4 restart + fw4 -q restart fi } @@ -328,8 +328,8 @@ validate_ss_redir_section() { validate_ss_rules_section() { "${2:-ss_validate}" ss_rules "$1" \ 'disabled:bool:0' \ - 'redir_tcp:uci("shadowsocks-libev", "@ss_redir","all")' \ - 'redir_udp:uci("shadowsocks-libev", "@ss_redir","all")' \ + 'redir_tcp:or(uci("shadowsocks-libev", "@ss_redir"),"all")' \ + 'redir_udp:or(uci("shadowsocks-libev", "@ss_redir"),"all")' \ 'src_ips_bypass:or(ipaddr,cidr)' \ 'src_ips_forward:or(ipaddr,cidr)' \ 'src_ips_checkdst:or(ipaddr,cidr)' \ From 07f5ff7684712a29a2186e408a5e7774cccebf36 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:23:02 +0100 Subject: [PATCH 1297/2059] Remove fw4 logs from Shadowsocks-rust --- shadowsocks-rust/files/shadowsocks-rust.init-nft | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index d895c822a..4f9fd0d21 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -163,7 +163,7 @@ ss_rules_nft_gen() { echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" if nft -f "$tmp.nft.chk" -c; then mv "$tmp.nft" "$ssrules_nft" - fw4 restart + fw4 -q restart fi rm -f "$tmp.nft.chk" fi @@ -174,7 +174,7 @@ ss_rules_nft_gen() { ss_rules_nft_reset() { if [ -f "$ssrules_nft" ]; then rm -f "$ssrules_nft" - fw4 restart + fw4 -q restart fi } @@ -187,14 +187,14 @@ ss_rules() { rules_up() { if [ -f "${ssrules_nft}.down" ]; then mv -f "${ssrules_nft}.down" "$ssrules_nft" - fw4 restart + fw4 -q restart fi } rules_down() { if [ -f "${ssrules_nft}" ]; then mv -f "$ssrules_nft" "${ssrules_nft}.down" - fw4 restart + fw4 -q restart fi } From b0129f19e500aa1a0241d0bc89370282613dfe65 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:23:22 +0100 Subject: [PATCH 1298/2059] Remove fw4 logs from v2ray --- v2ray-core/files/etc/init.d/v2ray-nft | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft index 4a4d373e5..3c4e70ea2 100755 --- a/v2ray-core/files/etc/init.d/v2ray-nft +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -499,7 +499,7 @@ add_v2ray_redirect_rules() { echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" if nft -f "$tmp.nft.chk" -c; then mv "$tmp.nft" "$v2rrules_nft" - fw4 restart + fw4 -q restart fi rm -f "$tmp.nft.chk" fi @@ -2087,7 +2087,7 @@ clear_transparent_proxy() { if [ -f "${v2rrules_nft}" ] || [ -f "${v2rrules_nft}.down" ]; then rm -f "$v2rrules_nft" rm -f "${v2rrules_nft}.down" - fw4 restart + fw4 -q restart fi v2ray-rules -f @@ -2253,14 +2253,14 @@ rules_exist() { rules_up() { if [ -f "${v2rrules_nft}.down" ]; then mv -f "${v2rrules_nft}.down" "$v2rrules_nft" - fw4 restart + fw4 -q restart fi } rules_down() { if [ -f "${v2rrules_nft}" ]; then mv -f "$v2rrules_nft" "${v2rrules_nft}.down" - fw4 restart + fw4 -q restart fi } From 97ddfc51f2d7397c5efc6ce3a05bcfc7e8450a83 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:23:32 +0100 Subject: [PATCH 1299/2059] Remove fw4 logs from Xray --- xray-core/files/etc/init.d/xray-nft | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xray-core/files/etc/init.d/xray-nft b/xray-core/files/etc/init.d/xray-nft index 5b7d3bb0c..94d197f76 100755 --- a/xray-core/files/etc/init.d/xray-nft +++ b/xray-core/files/etc/init.d/xray-nft @@ -508,7 +508,7 @@ add_xray_redirect_rules() { echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" if nft -f "$tmp.nft.chk" -c; then mv "$tmp.nft" "$xrrules_nft" - fw4 restart + fw4 -q restart fi rm -f "$tmp.nft.chk" fi @@ -2143,7 +2143,7 @@ clear_transparent_proxy() { if [ -f "${xrrules_nft}" ] || [ -f "${xrrules_nft}.down" ]; then rm -f "$xrrules_nft" rm -f "$xrrules_nft.down" - fw4 restart + fw4 -q restart fi @@ -2308,14 +2308,14 @@ rules_exist() { rules_up() { if [ -f "${xrrules_nft}.down" ]; then mv -f "${xrrules_nft}.down" "$xrrules_nft" - fw4 restart + fw4 -q restart fi } rules_down() { if [ -f "${xrrules_nft}" ]; then mv -f "$xrrules_nft" "${xrrules_nft}.down" - fw4 restart + fw4 -q restart fi } From 72177b29f6b39217ae2bc4a6b010a23c45d6ae4c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 18:58:12 +0100 Subject: [PATCH 1300/2059] Use Shadowsocks-Rust by default --- .../luasrc/view/openmptcprouter/wizard.htm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 4841cc622..6a9c8c0e6 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -240,7 +240,7 @@ end for _, proxy in pairs(available_proxys) do if proxy == "shadowsocks" then %> - <% if nixio.fs.access("/etc/init.d/shadowsocks-libev") then %><% end %> + <% if nixio.fs.access("/etc/init.d/shadowsocks-libev") then %><% end %> <% elseif proxy == "v2ray" then %> <% if nixio.fs.access("/etc/init.d/v2ray") then %><% end %> <% elseif proxy == "v2ray-vmess" then %> @@ -262,13 +262,13 @@ <% elseif proxy == "xray-shadowsocks" then %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> <% elseif proxy == "shadowsocks-rust" or proxy == "shadowsocks-go" then %> - <% if nixio.fs.access("/etc/init.d/shadowsocks-rust") then %><% end %> + <% if nixio.fs.access("/etc/init.d/shadowsocks-rust") then %><% end %> <% end end %> <% else %> - <% if nixio.fs.access("/etc/init.d/shadowsocks-libev") then %><% end %> + <% if nixio.fs.access("/etc/init.d/shadowsocks-libev") then %><% end %> <% if nixio.fs.access("/etc/init.d/v2ray") then %><% end %> <% if nixio.fs.access("/etc/init.d/v2ray") then %><% end %> <% if nixio.fs.access("/etc/init.d/v2ray") then %><% end %> @@ -279,7 +279,7 @@ <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> <% if nixio.fs.access("/etc/init.d/xray") then %><% end %> - <% if nixio.fs.access("/etc/init.d/shadowsocks-rust") then %><% end %> + <% if nixio.fs.access("/etc/init.d/shadowsocks-rust") then %><% end %> <% end %> From 1313e545ccc54bd286e2407f310bc9b970d96902 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 20:16:26 +0100 Subject: [PATCH 1301/2059] Fix OMR-Schedule category --- omr-schedule/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-schedule/Makefile b/omr-schedule/Makefile index 80dbded52..0868f8dd7 100644 --- a/omr-schedule/Makefile +++ b/omr-schedule/Makefile @@ -15,7 +15,7 @@ include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) SECTION:=OMR -CATEGORY:=OMR-Schedule +CATEGORY:=OpenMPTCProuter DEPENDS:=$(foreach p,$(MY_DEPENDS),+$(p)) TITLE:=OpenMPTCProuter schedule scripts endef From d9b345e746be96b100e25dfda81e619429585e8c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 20:16:41 +0100 Subject: [PATCH 1302/2059] Add OMR-Schedule by default --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 3edaa5f55..37901c470 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -87,7 +87,7 @@ MY_DEPENDS := \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ - (TARGET_x86||TARGET_x86_64):luci-app-keepalived luci-proto-external + (TARGET_x86||TARGET_x86_64):luci-app-keepalived luci-proto-external omr-schedule # !TARGET_mvebu:kmod-usb-net-smsc75xx From 37498c1725c97ea60250b8b236ba2ba00c6e46ca Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 20:17:08 +0100 Subject: [PATCH 1303/2059] Fix OMR-Tracker when latency is empty? --- omr-tracker/files/bin/omr-tracker | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 12a10d54f..8dacbc24b 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -176,9 +176,12 @@ _ping() { loss=$(echo "$ret" | grep 'packet loss' | sed -ne 's/.*\([0-9]\+\)% packet loss.*/\1/p') if [ -n "$loss" ] && [ "$loss" -ne 100 ]; then if [ "$localip" = "yes" ]; then - OMR_TRACKER_LATENCY=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + latency=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + [ -n "$latency" ] && { + OMR_TRACKER_LATENCY="$latency" + _update_rto "$OMR_TRACKER_LATENCY" + } OMR_TRACKER_LOSS="$loss" - _update_rto "$OMR_TRACKER_LATENCY" fi return fi From 1a9c152ef97a11bbb63448977b4934245d251ba7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 13 Jan 2024 00:01:43 +0100 Subject: [PATCH 1304/2059] Fix omr-bypass when proxy rules doesn't exist --- omr-bypass/files/etc/init.d/omr-bypass-nft | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index c6a1c9af8..9e67e216c 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -724,6 +724,7 @@ _bypass_omr_server() { _ss_rules_config() { cat >> /etc/firewall.omr-bypass <<-EOF + [ -z "\$(nft list ruleset | grep ss_rules)" ] && exit 0 nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 accept EOF @@ -737,6 +738,7 @@ _ss_rules_config() { _v2ray_rules_config() { cat >> /etc/firewall.omr-bypass <<-EOF + [ -z "\$(nft list ruleset | grep v2r_rules)" ] && exit 0 nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_all_4 accept EOF @@ -750,6 +752,7 @@ _v2ray_rules_config() { _xray_rules_config() { cat >> /etc/firewall.omr-bypass <<-EOF + [ -z "\$(nft list ruleset | grep xr_rules)" ] && exit 0 nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_all_4 accept EOF @@ -798,7 +801,7 @@ start_service() { } disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" #noipv6="$(uci -q get omr-bypass.global.noipv6)" - + rm -f /etc/firewall.omr-bypass cat > /etc/firewall.omr-bypass <<-EOF #!/bin/sh #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all accept @@ -916,11 +919,13 @@ service_triggers() { reload_service() { RELOAD=1 + stop start } reload_rules() { #[ "$( ipset -n list | grep omr_ )" = "" ] && return 0 RELOAD=1 + stop start } From 4ddf032dcd12970892107ca347bc78e35342f922 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 13 Jan 2024 00:11:59 +0100 Subject: [PATCH 1305/2059] Fix shadowsocks-rust password info --- openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index 2301d0c3a..ca526f957 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -1143,7 +1143,7 @@ function interfaces_status() else mArray.openmptcprouter["shadowsocks_service_key"] = true end - local ssr_key = uci:get("shadowsocks-rust","sss0","key") or "" + local ssr_key = uci:get("shadowsocks-rust","sss0","password") or "" mArray.openmptcprouter["shadowsocksrust_service_method"] = uci:get("shadowsocks-rust","sss0","method") if ssr_key == "" then mArray.openmptcprouter["shadowsocksrust_service_key"] = false From 4a21f31791b571cf401d956e4ed27182115f441a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 13 Jan 2024 00:16:56 +0100 Subject: [PATCH 1306/2059] Fix openmptcprouter-vps error for VPN on server --- .../files/etc/init.d/openmptcprouter-vps | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 30e4d73d0..ee5e3e994 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -947,10 +947,15 @@ _set_lan_ip() { _set_bypass_ips() { local settings [ -z "$servername" ] && servername=$1 - bypassipv4s=$(ipset -q -o save list omr_dst_bypass_srv_vpn1_4 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') - [ -z "$bypassipvs4" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') - bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1_6 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') - [ -z "$bypassipvs6" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + bypassipv4s=$(ipset -q -o save list omr_dst_bypass_srv_vpn1_4 2>/dev/null | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs4" ] && { + bypassipv4slst=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" 2>/dev/null) + [ -n "$bypassipv4slst" ] && bypassipv4s=$(echo "$bypassipv4slst" | jsonfilter -q -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1_6 2>/dev/null | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs6" ] && { + bypassipv6slst=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" 2>/dev/null) + [ -n "$bypassipv6slst" ] && bypassipv6s=$(echo "$bypassipv4slst" | jsonfilter -q -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + } # " if [ "$bypassipv4s" != "" ] || [ "$bypassipv6s" != "" ]; then settings='{"ipv4s" : ['$bypassipv4s'],"ipv6s" : ['$bypassipv6s'],"intf" : "vpn1"}' From 52a7f7eb36e1c2438293aa9dd1addfa1d3f5c12f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 13 Jan 2024 09:07:35 +0100 Subject: [PATCH 1307/2059] Flush route cache after route changes --- mptcp/files/etc/init.d/mptcp | 4 ++-- .../files/usr/share/omr/post-tracking.d/001-post-tracking | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 781cf49cc..f1d358bc3 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -305,7 +305,7 @@ interface_multipath_settings() { ip route replace $network/$netmask dev $iface scope link table $id $initcwrwnd 2>&1 >/dev/null ip route replace default via $gateway dev $iface table $id $initcwrwnd 2>&1 >/dev/null [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default via $gateway dev $iface metric $id $initcwrwnd 2>&1 >/dev/null - #ip route flush $id + ip route flush cache $id 2>&1 >/dev/null fi #config_get mode "$config" multipath "" @@ -395,7 +395,7 @@ interface_multipath_settings() { ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id $initcwrwnd 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface table 6$id $initcwrwnd 2>&1 >/dev/null [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip -6 route replace default via $gateway6 dev $iface metric 6$id $initcwrwnd 2>&1 >/dev/null - #ip -6 route flush 6$id 2>&1 >/dev/null + ip -6 route flush cache 6$id 2>&1 >/dev/null fi #config_get mode "$config" multipath "off" diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index fbd576f8e..0a30e6cbc 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -1081,6 +1081,7 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_server_default_route server #config_foreach set_server_default_route6 server fi + ip route flush cache 2>&1 >/dev/null fi if ([ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$default_gw6" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") @@ -1096,6 +1097,7 @@ if [ "$multipath_config" = "master" ]; then #config_foreach set_server_default_route server config_foreach set_server_default_route6 server fi + ip -6 route flush cache 2>&1 >/dev/null fi #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && ([ "$(ip route show default | grep weight)" = "" ] || [ "$(ip -6 route show default | grep weight)" = "" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then @@ -1157,12 +1159,16 @@ if [ "$multipath_config" = "master" ]; then } } fi + ip route flush cache 2>&1 >/dev/null + ip -6 route flush cache 2>&1 >/dev/null fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE " ]; then ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE table 991337 $initcwrwnd 2>&1 >/dev/null + ip route flush cache 2>&1 >/dev/null fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE " ]; then ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 991337 $initcwrwnd 2>&1 >/dev/null + ip -6 route flush cache 2>&1 >/dev/null fi if ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ]) || [ $(($(date +"%s") + $((10 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]; then [ "$(pgrep -f openmptcprouter-vps)" = "" ] && /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & @@ -1181,6 +1187,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then _log "Interface route not yet set, set route ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 + ip route flush cache 2>&1 >/dev/null fi fi if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then @@ -1193,6 +1200,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; th fi if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 + ip -6 route flush cache 2>&1 >/dev/null fi fi From 5074d855f047cadd3ec9a166650c3004f61eb64c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Jan 2024 09:17:44 +0100 Subject: [PATCH 1308/2059] Use same nft file for all proxy --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 2 +- shadowsocks-rust/files/shadowsocks-rust.init-nft | 2 +- v2ray-core/files/etc/init.d/v2ray-nft | 2 +- xray-core/files/etc/init.d/xray-nft | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index b53160515..a42fce5d8 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -15,7 +15,7 @@ ss_confdir=/var/etc/shadowsocks-libev ss_bindir=/usr/bin ssrules_uc="/usr/share/ss-rules/ss-rules.uc" -ssrules_nft="/etc/nftables.d/90-ss-rules.nft" +ssrules_nft="/etc/nftables.d/90-proxy-rules.nft" ss_mkjson_server_conf() { local cfgserver diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index 4f9fd0d21..d1d153deb 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -15,7 +15,7 @@ ss_confdir=/var/etc/shadowsocks-rust ss_bindir=/usr/bin ssrules_uc="/usr/share/ssr-rules/ss-rules.uc" -ssrules_nft="/etc/nftables.d/90-ssr-rules.nft" +ssrules_nft="/etc/nftables.d/90-proxy-rules.nft" ss_mkjson_server_conf() { local cfgserver diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft index 3c4e70ea2..30d342fac 100755 --- a/v2ray-core/files/etc/init.d/v2ray-nft +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -13,7 +13,7 @@ NAME=v2ray CONFIG_FOLDER=/var/etc/$NAME v2rrules_uc="/usr/share/v2ray-rules/v2r-rules.uc" -v2rrules_nft="/etc/nftables.d/90-v2r-rules.nft" +v2rrules_nft="/etc/nftables.d/90-proxy-rules.nft" FILE_V2RAY_DNSMASQ=/tmp/dnsmasq.d/$NAME FILE_V2RAY_DNSMASQ_CACHE=/tmp/$NAME.dnsmasq.cache diff --git a/xray-core/files/etc/init.d/xray-nft b/xray-core/files/etc/init.d/xray-nft index 94d197f76..a92efe7df 100755 --- a/xray-core/files/etc/init.d/xray-nft +++ b/xray-core/files/etc/init.d/xray-nft @@ -13,7 +13,7 @@ NAME=xray CONFIG_FOLDER=/var/etc/$NAME xrrules_uc="/usr/share/xray-rules/xr-rules.uc" -xrrules_nft="/etc/nftables.d/90-xr-rules.nft" +xrrules_nft="/etc/nftables.d/90-proxy-rules.nft" FILE_XRAY_DNSMASQ=/tmp/dnsmasq.d/$NAME FILE_XRAY_DNSMASQ_CACHE=/tmp/$NAME.dnsmasq.cache From f10191f25b903d168e72e15e724718825679b8ef Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Jan 2024 10:27:29 +0100 Subject: [PATCH 1309/2059] Fix tracker on down interface --- omr-tracker/files/bin/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 8dacbc24b..c95d58c61 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -271,7 +271,7 @@ while true; do } if [ -n "$OMR_TRACKER_DEVICE" ] && [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then - if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep UP)" ]; then + if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep 'state UP')" ]; then # retrieve iface ip and gateway if ([ "$OMR_TRACKER_FAMILY" = "ipv4" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]) && [ "$OMR_TRACKER_INTERFACE_PROTO" != "dhcpv6" ]; then OMR_TRACKER_DEVICE_IP=$(ip -4 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') From 2455e4ab5a5634a7a27de71d6f893c7cafe42fbb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Jan 2024 16:27:21 +0100 Subject: [PATCH 1310/2059] Enable MPTCP after routes creation --- mptcp/files/etc/hotplug.d/iface/30-mptcp | 12 ++++++------ mptcp/files/etc/init.d/mptcp | 19 +++++++++++-------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/mptcp/files/etc/hotplug.d/iface/30-mptcp b/mptcp/files/etc/hotplug.d/iface/30-mptcp index 607718dd1..33bc70ebe 100644 --- a/mptcp/files/etc/hotplug.d/iface/30-mptcp +++ b/mptcp/files/etc/hotplug.d/iface/30-mptcp @@ -1,16 +1,16 @@ #!/bin/sh [ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = ifdown -o "$ACTION" = iflink ] || exit 0 -[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0 +#[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0 /etc/init.d/mptcp enabled || exit 0 -if [ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = iflink ] && [ -z "$(echo $DEVICE | grep oip | grep gre)" ]; then - logger -t "mptcp" "Reloading mptcp config due to $ACTION of $INTERFACE ($DEVICE)" - /etc/init.d/mptcp reload "$DEVICE" >/dev/null || exit 0 -else - logger -t "mptcp" "Set multipath off on $DEVICE ($INTERFACE) due to $ACTION" +#if [ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = iflink ] && [ -z "$(echo $DEVICE | grep oip | grep gre)" ]; then +# logger -t "mptcp" "Reloading mptcp config due to $ACTION of $INTERFACE ($DEVICE)" +# /etc/init.d/mptcp reload "$DEVICE" >/dev/null || exit 0 +#else +if [ "$ACTION" = ifdown ]; then multipath $DEVICE off 2>&1 >/dev/null fi diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index f1d358bc3..e2cd16260 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -205,14 +205,6 @@ interface_multipath_settings() { #echo "îface: $iface" - if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then - logger -t "MPTCP" "Set $iface to $mode" - if [ "$mode" = "master" ]; then - multipath "$iface" "on" - else - multipath "$iface" "$mode" - fi - fi #[ "$mode" = "off" ] && { # ip rule del table $id > /dev/null 2>&1 # ip route flush $id > /dev/null 2>&1 @@ -409,6 +401,16 @@ interface_multipath_settings() { #} fi fi + + if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then + logger -t "MPTCP" "Set $iface to $mode" + if [ "$mode" = "master" ]; then + multipath "$iface" "on" + else + multipath "$iface" "$mode" + fi + fi + } load_interfaces() { @@ -502,6 +504,7 @@ start_service() { local id count intfmaster . /lib/functions.sh . /lib/functions/network.sh + [ -n "$intf" ] && multipath "${intf}" off 2>&1 >/dev/null global_multipath_settings [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep '3-model-b')" ] && [ "$(ip link show eth0 | grep UP)" = "" ] && { From 1eae173fdb146b229c1b84b3ee40b6d20427439d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 15 Jan 2024 16:44:17 +0100 Subject: [PATCH 1311/2059] Fix Shadowsocks libev with nft --- shadowsocks-libev/files/nft-rules/chain.uc | 4 +++ shadowsocks-libev/files/nft-rules/set.uc | 5 ++- .../files/shadowsocks-libev.init-nft | 35 +++++++++++++++++-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/shadowsocks-libev/files/nft-rules/chain.uc b/shadowsocks-libev/files/nft-rules/chain.uc index 3047f1663..3b2cc0813 100644 --- a/shadowsocks-libev/files/nft-rules/chain.uc +++ b/shadowsocks-libev/files/nft-rules/chain.uc @@ -93,8 +93,10 @@ chain ss_rules_src_{{ proto }} { chain ss_rules_dst_{{ proto }} { ip daddr @ss_rules_dst_bypass accept; + ip daddr @ss_rules_remote_servers accept; ip daddr @ss_rules_dst_forward goto ss_rules_forward_{{ proto }}; ip6 daddr @ss_rules6_dst_bypass accept; + ip6 daddr @ss_rules6_remote_servers accept; ip6 daddr @ss_rules6_dst_forward goto ss_rules_forward_{{ proto }}; {{ get_dst_default_verdict() }}; } @@ -107,8 +109,10 @@ chain ss_rules_forward_{{ proto }} { chain ss_rules_local_out { type {{ type }} hook output priority -1; meta l4proto != tcp accept; + ip daddr @ss_rules_remote_servers accept; ip daddr @ss_rules_dst_bypass_ accept; ip daddr @ss_rules_dst_bypass accept; + ip6 daddr @ss_rules6_remote_servers accept; ip6 daddr @ss_rules6_dst_bypass_ accept; ip6 daddr @ss_rules6_dst_bypass accept; {{ local_verdict }}; diff --git a/shadowsocks-libev/files/nft-rules/set.uc b/shadowsocks-libev/files/nft-rules/set.uc index 38140e7e1..2698d444a 100644 --- a/shadowsocks-libev/files/nft-rules/set.uc +++ b/shadowsocks-libev/files/nft-rules/set.uc @@ -10,10 +10,10 @@ let o_dst_bypass4_ = " 172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 + 192.168.0.0/16 192.31.196.0/24 192.52.193.0/24 192.88.99.0/24 - 192.168.0.0/16 192.175.48.0/24 198.18.0.0/15 198.51.100.0/24 @@ -43,6 +43,9 @@ let set_suffix = { "src_checkdst": { str: o_src_checkdst, }, + "remote_servers": { + str: o_remote_servers + }, "dst_bypass": { str: o_dst_bypass, file: o_dst_bypass_file, diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index a42fce5d8..340a479d0 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -15,7 +15,7 @@ ss_confdir=/var/etc/shadowsocks-libev ss_bindir=/usr/bin ssrules_uc="/usr/share/ss-rules/ss-rules.uc" -ssrules_nft="/etc/nftables.d/90-proxy-rules.nft" +ssrules_nft="/etc/nftables.d/90-ss-rules.nft" ss_mkjson_server_conf() { local cfgserver @@ -33,10 +33,38 @@ ss_mkjson_server_conf_() { [ -z "$server" ] || json_add_string server "$server" json_add_int server_port "$server_port" [ -z "$method" ] || json_add_string method "$method" - [ -z "$key" ] || json_add_string key "$key" - [ -z "$password" ] || json_add_string password "$password" + [ -z "$key" ] || { + key="$(echo $key | sed 's/+/-/g; s/\//_/g;')" + json_add_string key "$key" + } + [ -z "$password" ] || { + password="$(echo $password | sed 's/+/-/g; s/\//_/g;')" + json_add_string password "$password" + } + [ -z "$password" ] && [ -z "$key" ] && return 1 [ -z "$plugin" ] || json_add_string plugin "$plugin" [ -z "$plugin_opts" ] || json_add_string plugin_opts "$plugin_opts" + if [ "$obfs" = 1 ]; then + if [ "$obfs_plugin" = "obfs" ]; then + obfs_options="obfs=$obfs_type" + [ -z "$obfs_host" ] || obfs_options="$obfs_options;obfs-host=$obfs_host" + [ -z "$obfs_uri" ] || obfs_options="$obfs_options;obfs-uri=$obfs_uri" + [ "$fast_open" = 1 ] && obfs_options="$obfs_options;fast-open" + [ "$mptcp" = 1 ] && obfs_options="$obfs_options;mptcp" + [ -z "$timeout" ] || obfs_options="$obfs_options;t=$timeout" + json_add_string plugin "/usr/bin/obfs-local" + json_add_string plugin_opts "$obfs_options" + fi + if [ "$obfs_plugin" = "v2ray" ]; then + obfs_options="loglevel=default" + [ "$obfs_type" = "tls" ] && obfs_options="tls" + [ -z "$obfs_host" ] || obfs_options="$obfs_options;host=$obfs_host" + [ -z "$obfs_uri" ] || obfs_options="$obfs_options;path=$obfs_uri" + [ "$fast_open" = 1 ] && obfs_options="$obfs_options;fast-open" + json_add_string plugin "/usr/bin/v2ray-plugin" + json_add_string plugin_opts "$obfs_options" + fi + fi } ss_mkjson_ss_local_conf() { @@ -95,6 +123,7 @@ ss_xxx() { procd_append_param command -b "$bind_address" fi procd_set_param file "$confjson" + procd_set_param limits nofile="512000 512000" procd_set_param respawn procd_close_instance ss_rules_cb From 7ea78ed200666e4d4ddeebef124cefc023a21067 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Jan 2024 08:36:13 +0100 Subject: [PATCH 1312/2059] Fix omr-tracker-server --- omr-tracker/files/bin/omr-tracker-server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 8760427eb..69c33a78f 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -47,7 +47,7 @@ _check_server_intf() { --max-time "$OMR_TRACKER_TIMEOUT" \ -s \ -k \ - --interface $intf + --interface $intf \ "https://${host}:${port}/" ) [ -n "$ret" ] && { From abe757bd00f18daebd3a0dc50b7cfe4afc7db46e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Jan 2024 09:30:49 +0100 Subject: [PATCH 1313/2059] Fix OpenMPTCprouter-vps --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 1 + 1 file changed, 1 insertion(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index ee5e3e994..7683774a9 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -951,6 +951,7 @@ _set_bypass_ips() { [ -z "$bypassipvs4" ] && { bypassipv4slst=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" 2>/dev/null) [ -n "$bypassipv4slst" ] && bypassipv4s=$(echo "$bypassipv4slst" | jsonfilter -q -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + } bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1_6 2>/dev/null | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') [ -z "$bypassipvs6" ] && { bypassipv6slst=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" 2>/dev/null) From 9cbeb186f9b487732eef4d32ec945e4447f6222f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Jan 2024 12:48:14 +0100 Subject: [PATCH 1314/2059] Execute omr-schedule every minutes --- omr-schedule/files/bin/omr-schedule | 2 ++ omr-schedule/files/etc/uci-defaults/3000-omr-schedule | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/omr-schedule/files/bin/omr-schedule b/omr-schedule/files/bin/omr-schedule index 846c92703..c18a70434 100755 --- a/omr-schedule/files/bin/omr-schedule +++ b/omr-schedule/files/bin/omr-schedule @@ -2,6 +2,8 @@ . /lib/functions.sh . /lib/functions/network.sh +[ -n "$(pgrep -f 'omr-schedule')" ] && exit 0 + for schedule_bin in /usr/share/omr/schedule.d/*; do [ -x "$schedule_bin" ] && ( _log() { diff --git a/omr-schedule/files/etc/uci-defaults/3000-omr-schedule b/omr-schedule/files/etc/uci-defaults/3000-omr-schedule index bb5556c7a..0915b9040 100755 --- a/omr-schedule/files/etc/uci-defaults/3000-omr-schedule +++ b/omr-schedule/files/etc/uci-defaults/3000-omr-schedule @@ -1,4 +1,4 @@ #!/bin/sh if [ ! -f /etc/crontabs/root ] || [ "$(cat /etc/crontabs/root | grep omr-schedule)" = "" ]; then - echo "*/5 * * * * /bin/omr-schedule" >> /etc/crontabs/root + echo "* * * * * /bin/omr-schedule" >> /etc/crontabs/root fi From 5d0aac0f0dc1c1fde649c858534993b31a02d1e0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Jan 2024 14:42:23 +0100 Subject: [PATCH 1315/2059] Remove keepalived of default --- openmptcprouter-full/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 37901c470..70fb2ae0a 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -87,7 +87,10 @@ MY_DEPENDS := \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ - (TARGET_x86||TARGET_x86_64):luci-app-keepalived luci-proto-external omr-schedule + luci-proto-external omr-schedule + +# keepalived disabled by default because it's running even with no configuration, would need a default OMR config with some changes + (TARGET_x86||TARGET_x86_64):keepalived (TARGET_x86||TARGET_x86_64):keepalived-sync # !TARGET_mvebu:kmod-usb-net-smsc75xx From f350523653120bd410d8f453be0a130e28f41982 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Jan 2024 15:57:00 +0100 Subject: [PATCH 1316/2059] Fix OMR-Tracker for VPN --- omr-tracker/files/bin/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index c95d58c61..3c9676a4e 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -271,7 +271,7 @@ while true; do } if [ -n "$OMR_TRACKER_DEVICE" ] && [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then - if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep 'state UP')" ]; then + if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep 'state UP')" ] || [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep 'state UNKNOWN')" ]; then # retrieve iface ip and gateway if ([ "$OMR_TRACKER_FAMILY" = "ipv4" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]) && [ "$OMR_TRACKER_INTERFACE_PROTO" != "dhcpv6" ]; then OMR_TRACKER_DEVICE_IP=$(ip -4 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') From 08916a77885f63d93bfc00c6289ca432849df5ca Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Jan 2024 18:28:44 +0100 Subject: [PATCH 1317/2059] Set a default value for interval tries in omr-tracker --- omr-tracker/files/etc/init.d/omr-tracker | 1 + 1 file changed, 1 insertion(+) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 009e92dd5..801b1a207 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -105,6 +105,7 @@ _launch_tracker() { [ -z "${check_quality}" ] && check_quality=0 [ -z "${tries}" ] && tries=5 [ -z "${tries_up}" ] && tries_up=${tries} + [ -z "${failure_interval}" ] && failure_interval=5 procd_open_instance # shellcheck disable=SC2086 From e9c8954c83321a9065842ee84aa2608fde7e1823 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 16 Jan 2024 18:38:37 +0100 Subject: [PATCH 1318/2059] Put default values for all sleep in OMR-Tracker --- omr-tracker/files/bin/omr-tracker | 8 ++++---- omr-tracker/files/etc/init.d/omr-tracker | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 3c9676a4e..c3c15a92f 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -445,7 +445,7 @@ while true; do OMR_TRACKER_HOSTS="${OMR_TRACKER_HOSTS#* } $OMR_TRACKER_HOST" } #OMR_TRACKER_TIMEOUT=$((OMR_TRACKER_TIMEOUT * 2)) - sleep "$OMR_TRACKER_INTERVAL_TRIES" + sleep "${OMR_TRACKER_INTERVAL_TRIES:-1}" done fi #if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then @@ -550,7 +550,7 @@ while true; do OMR_TRACKER_HOSTS6="${OMR_TRACKER_HOSTS6#* } $OMR_TRACKER_HOST6" } #OMR_TRACKER_TIMEOUT=$((OMR_TRACKER_TIMEOUT * 2)) - sleep "$OMR_TRACKER_INTERVAL_TRIES" + sleep "${OMR_TRACKER_INTERVAL_TRIES:-1}" done fi if [ -z "$OMR_TRACKER_DEVICE_IP" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ -z "$OMR_TRACKER_DEVICE_IP6" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then @@ -611,8 +611,8 @@ while true; do _restart if [ "$OMR_TRACKER_STATUS" = "ERROR" ]; then - sleep "$OMR_TRACKER_FAILURE_INTERVAL" + sleep "${$OMR_TRACKER_FAILURE_INTERVAL:-5}" else - sleep "$OMR_TRACKER_INTERVAL" + sleep "${OMR_TRACKER_INTERVAL:-2}" fi done diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 801b1a207..51101d8c2 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -98,6 +98,7 @@ _launch_tracker() { ifstatus=$(ifstatus "$1" | jsonfilter -q -e '@["up"]') ifdevice=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') #[ "${ifstatus}" = "false" ] && [ -z "${ifdevice}" ] && return + [ -z "${interval}" ] && interval=2 [ -z "${interval_tries}" ] && interval_tries=1 [ -z "${count}" ] && count=2 [ -z "${max_ttl}" ] && max_ttl=60 From 0dc7679b8facd90f8c35f43575c79ffabc147ec5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 08:15:35 +0100 Subject: [PATCH 1319/2059] Fix typo in openmptcprouter-full --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 70fb2ae0a..21baab06c 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -90,7 +90,7 @@ MY_DEPENDS := \ luci-proto-external omr-schedule # keepalived disabled by default because it's running even with no configuration, would need a default OMR config with some changes - (TARGET_x86||TARGET_x86_64):keepalived (TARGET_x86||TARGET_x86_64):keepalived-sync +# (TARGET_x86||TARGET_x86_64):keepalived (TARGET_x86||TARGET_x86_64):keepalived-sync # !TARGET_mvebu:kmod-usb-net-smsc75xx From cc30b45eede8e30b0d53956688a3b72cb3084861 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 14:13:11 +0100 Subject: [PATCH 1320/2059] fullconenat only for 5.4 for now --- fullconenat/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fullconenat/Makefile b/fullconenat/Makefile index d49155c7e..0fd188e3d 100644 --- a/fullconenat/Makefile +++ b/fullconenat/Makefile @@ -28,7 +28,7 @@ define Package/iptables-mod-fullconenat SECTION:=net CATEGORY:=Network TITLE:=FULLCONENAT iptables extension - DEPENDS:=+iptables +kmod-ipt-fullconenat + DEPENDS:=+iptables +kmod-ipt-fullconenat @LINUX_5_4 endef define Package/iptables-mod-fullconenat/install @@ -39,7 +39,7 @@ endef define KernelPackage/ipt-fullconenat SUBMENU:=Netfilter Extensions TITLE:=FULLCONENAT netfilter module - DEPENDS:=+kmod-nf-ipt +kmod-nf-nat + DEPENDS:=+kmod-nf-ipt +kmod-nf-nat @LINUX_5_4 KCONFIG:= \ CONFIG_NF_CONNTRACK_EVENTS=y \ CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y From 3d500789f70193fbe008a48ff66fe7c2964e95d4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 14:13:46 +0100 Subject: [PATCH 1321/2059] Disable reliability in interface for now, add partly support in OMR-Tracker --- .../resources/view/omr-tracker/network/interface.js | 3 ++- omr-tracker/files/etc/init.d/omr-tracker | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js index 2c11934e6..501a60a4e 100644 --- a/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js +++ b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js @@ -104,11 +104,12 @@ return view.extend({ o.rmempty = false; o.modalonly = true; */ - + /* o = s.option(form.Value, 'reliability', _('Tracking reliability'), _('Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up')); o.datatype = 'range(1, 100)'; o.default = '1'; + */ o = s.option(form.ListValue, 'count', _('Ping count')); o.default = '1'; diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 51101d8c2..202b5881b 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -16,7 +16,7 @@ . /lib/functions/network.sh _validate_section() { - local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_count=$count tmp_tries=$tries tmp_size=$size tmp_max_ttl=$max_ttl tmp_failure_loss=$failure_loss tmp_failure_latency=$failure_latency tmp_recovery_loss=$recovery_loss tmp_recovery_latency=$recovery_latency + local tmp_hosts=$hosts tmp_hosts6=$hosts6 tmp_timeout=$timeout tmp_count=$count tmp_tries=$tries tmp_size=$size tmp_max_ttl=$max_ttl tmp_failure_loss=$failure_loss tmp_failure_latency=$failure_latency tmp_recovery_loss=$recovery_loss tmp_recovery_latency=$recovery_latency tmp_reliability=$reliability local tmp_interval=$interval tmp_interval_tries=$interval_tries tmp_options=$options tmp_type=$type tmp_enabled=$enabled tmp_wait_test=$wait_test tmp_server_http_test=$server_http_test tmp_check_quality=$check_quality tmp_failure_interval=$failure_interval tmp_tries_up=$tries_up tmp_family=$family uci_validate_section omr-tracker "$1" "$2" \ @@ -31,6 +31,7 @@ _validate_section() { 'recovery_latency:uinteger' \ 'check_quality:bool:0' \ 'count:uinteger' \ + 'reliability:uinteger' \ 'tries:uinteger' \ 'tries_up:uinteger' \ 'interval:uinteger' \ @@ -47,6 +48,7 @@ _validate_section() { [ -z "$hosts6" ] && hosts6=$tmp_hosts6 [ -z "$timeout" ] && timeout=$tmp_timeout [ -z "$count" ] && count=$tmp_count + [ -z "$reliability" ] && reliability=$tmp_reliability [ -z "$size" ] && size=$tmp_size [ -z "$failure_loss" ] && failure_loss=$tmp_failure_loss [ -z "$failure_latency" ] && failure_latency=$tmp_failure_latency @@ -72,7 +74,7 @@ _launch_tracker() { loopback|lan*|if0*) return;; esac [ -z "$1" ] && return - local hosts hosts6 timeout count tries tries_up interval interval_tries options type enabled wait_test ipv6 proto server_http_test size max_ttl failure_loss failure_interval failure_latency recovery_loss recovery_latency family + local hosts hosts6 timeout count tries tries_up interval interval_tries options type enabled wait_test ipv6 proto server_http_test size max_ttl failure_loss failure_interval failure_latency recovery_loss recovery_latency family reliability _validate_section "defaults" "defaults" _validate_section "interface" "$1" @@ -105,6 +107,7 @@ _launch_tracker() { [ -z "${size}" ] && size=56 [ -z "${check_quality}" ] && check_quality=0 [ -z "${tries}" ] && tries=5 + [ -z "${reliability}" ] && reliability=1 [ -z "${tries_up}" ] && tries_up=${tries} [ -z "${failure_interval}" ] && failure_interval=5 @@ -122,6 +125,7 @@ _launch_tracker() { procd_append_param env "OMR_TRACKER_RECOVERY_LOSS=$recovery_loss" procd_append_param env "OMR_TRACKER_RECOVERY_LATENCY=$recovery_latency" procd_append_param env "OMR_TRACKER_COUNT=$count" + procd_append_param env "OMR_TRACKER_RELIABILITY=$reliability" procd_append_param env "OMR_TRACKER_TRIES=$tries" procd_append_param env "OMR_TRACKER_TRIES_UP=$tries_up" procd_append_param env "OMR_TRACKER_INTERVAL=$interval" From c9885305cffd4b5f2aeb8bd219dab2964136ab19 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 15:11:32 +0100 Subject: [PATCH 1322/2059] Update iproute2 --- iproute2/Makefile | 4 ++-- iproute2/patches/100-configure.patch | 12 ------------ .../patches/200-drop_libbsd_dependency.patch | 19 ------------------- 3 files changed, 2 insertions(+), 33 deletions(-) delete mode 100644 iproute2/patches/100-configure.patch delete mode 100644 iproute2/patches/200-drop_libbsd_dependency.patch diff --git a/iproute2/Makefile b/iproute2/Makefile index 7f4556e7d..2f9d2f2bc 100644 --- a/iproute2/Makefile +++ b/iproute2/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iproute2 -PKG_VERSION:=6.5.0 +PKG_VERSION:=6.7.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 -PKG_HASH:=a70179085fa1b96d3c33b040c809b75e2b57563adc505a4ad05e2609df373463 +PKG_HASH:=ff942dd9828d7d1f867f61fe72ce433078c31e5d8e4a78e20f02cb5892e8841d PKG_BUILD_PARALLEL:=1 PKG_BUILD_DEPENDS:=iptables PKG_LICENSE:=GPL-2.0 diff --git a/iproute2/patches/100-configure.patch b/iproute2/patches/100-configure.patch deleted file mode 100644 index 0c19b2086..000000000 --- a/iproute2/patches/100-configure.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/configure -+++ b/configure -@@ -34,7 +34,8 @@ int main(int argc, char **argv) { - } - EOF - -- if $CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1; then -+# OpenWrt: disable ATM support even if present on host system -+ if [ 1 -eq 0 ]; then - echo "TC_CONFIG_ATM:=y" >>$CONFIG - echo yes - else diff --git a/iproute2/patches/200-drop_libbsd_dependency.patch b/iproute2/patches/200-drop_libbsd_dependency.patch deleted file mode 100644 index 12a1ccfa3..000000000 --- a/iproute2/patches/200-drop_libbsd_dependency.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/configure -+++ b/configure -@@ -431,14 +431,8 @@ EOF - if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then - echo "no" - else -- if ${PKG_CONFIG} libbsd --exists; then -- echo 'CFLAGS += -DHAVE_LIBBSD' `${PKG_CONFIG} libbsd --cflags` >>$CONFIG -- echo 'LDLIBS +=' `${PKG_CONFIG} libbsd --libs` >> $CONFIG -- echo "no" -- else -- echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG -- echo "yes" -- fi -+ echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG -+ echo "yes" - fi - rm -f $TMPDIR/strtest.c $TMPDIR/strtest - } From bb312b9f3fda05d54312b6cbd19834daa3e4f4ad Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 15:34:32 +0100 Subject: [PATCH 1323/2059] Fix typo in OMR-Tracker --- omr-tracker/files/bin/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index c3c15a92f..8cf858c61 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -611,7 +611,7 @@ while true; do _restart if [ "$OMR_TRACKER_STATUS" = "ERROR" ]; then - sleep "${$OMR_TRACKER_FAILURE_INTERVAL:-5}" + sleep "${OMR_TRACKER_FAILURE_INTERVAL:-5}" else sleep "${OMR_TRACKER_INTERVAL:-2}" fi From 8e2e3920419a922878007d461d579ea4e1bcbaf4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 15:39:29 +0100 Subject: [PATCH 1324/2059] Fix OMR-Schedule --- omr-schedule/files/bin/omr-schedule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-schedule/files/bin/omr-schedule b/omr-schedule/files/bin/omr-schedule index c18a70434..753b53e69 100755 --- a/omr-schedule/files/bin/omr-schedule +++ b/omr-schedule/files/bin/omr-schedule @@ -2,7 +2,7 @@ . /lib/functions.sh . /lib/functions/network.sh -[ -n "$(pgrep -f 'omr-schedule')" ] && exit 0 +#[ -n "$(pgrep -f 'omr-schedule')" ] && exit 0 for schedule_bin in /usr/share/omr/schedule.d/*; do [ -x "$schedule_bin" ] && ( From fef367a27558e9dc5f4123e7f54bf82326e32214 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 15:44:04 +0100 Subject: [PATCH 1325/2059] Don't disable modemmanager --- omr-schedule/files/usr/share/omr/schedule.d/010-services | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/omr-schedule/files/usr/share/omr/schedule.d/010-services b/omr-schedule/files/usr/share/omr/schedule.d/010-services index d1cb77c22..b1976ba2a 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/010-services +++ b/omr-schedule/files/usr/share/omr/schedule.d/010-services @@ -101,10 +101,10 @@ if [ -z "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$( _log "Can't find ModemManager, restart it..." /etc/init.d/modemmanager restart 2>&1 >/dev/null sleep 5 -elif [ -n "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -z "$(uci -q show network | grep modemmanager)" ]; then - _log "ModemManager not used, stop it..." - /etc/init.d/modemmanager stop 2>&1 >/dev/null - sleep 5 +#elif [ -n "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -z "$(uci -q show network | grep modemmanager)" ]; then +# _log "ModemManager not used, stop it..." +# /etc/init.d/modemmanager stop 2>&1 >/dev/null +# sleep 5 fi if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ "$(pgrep -f omr-tracker-v2ray)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then From cc072920adca0ea082a40f5f5ec040f248ffde33 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 15:58:21 +0100 Subject: [PATCH 1326/2059] Doesn't run rules_up if proxy disabled --- shadowsocks-libev/files/firewall.ss-rules | 2 +- shadowsocks-rust/files/firewall.ssr-rules | 2 +- v2ray-core/files/etc/firewall.v2ray-rules | 2 +- xray-core/files/etc/firewall.xray-rules | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shadowsocks-libev/files/firewall.ss-rules b/shadowsocks-libev/files/firewall.ss-rules index 3134150d8..5c8336a83 100644 --- a/shadowsocks-libev/files/firewall.ss-rules +++ b/shadowsocks-libev/files/firewall.ss-rules @@ -1,2 +1,2 @@ #!/bin/sh -/etc/init.d/shadowsocks-libev rules_up +[ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && /etc/init.d/shadowsocks-libev rules_up diff --git a/shadowsocks-rust/files/firewall.ssr-rules b/shadowsocks-rust/files/firewall.ssr-rules index 87e4769b6..c5e7aa863 100644 --- a/shadowsocks-rust/files/firewall.ssr-rules +++ b/shadowsocks-rust/files/firewall.ssr-rules @@ -1,2 +1,2 @@ #!/bin/sh -/etc/init.d/shadowsocks-rust rules_up +[ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && /etc/init.d/shadowsocks-rust rules_up diff --git a/v2ray-core/files/etc/firewall.v2ray-rules b/v2ray-core/files/etc/firewall.v2ray-rules index 2c0ade3dd..a76fa56c0 100644 --- a/v2ray-core/files/etc/firewall.v2ray-rules +++ b/v2ray-core/files/etc/firewall.v2ray-rules @@ -1,2 +1,2 @@ #!/bin/sh -/etc/init.d/v2ray rules_up +[ "$(uci -q get v2ray.main_dns.enabled)" = "1" ] && /etc/init.d/v2ray rules_up diff --git a/xray-core/files/etc/firewall.xray-rules b/xray-core/files/etc/firewall.xray-rules index 2aac68055..064828b3b 100644 --- a/xray-core/files/etc/firewall.xray-rules +++ b/xray-core/files/etc/firewall.xray-rules @@ -1,2 +1,2 @@ #!/bin/sh -/etc/init.d/xray rules_up +[ "$(uci -q get xray.main_dns.enabled)" = "1"] && /etc/init.d/xray rules_up From 289c26ebad9577c4c631edb3daacbc7dec2a41bd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 16:04:55 +0100 Subject: [PATCH 1327/2059] Remove v2ray-rules call --- v2ray-core/files/etc/init.d/v2ray-nft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft index 30d342fac..ed4027673 100755 --- a/v2ray-core/files/etc/init.d/v2ray-nft +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -2090,7 +2090,7 @@ clear_transparent_proxy() { fw4 -q restart fi - v2ray-rules -f + #v2ray-rules -f if [ -s "$FILE_V2RAY_DNSMASQ" ] ; then rm -f "$FILE_V2RAY_DNSMASQ" From 37b059f39afe902ed302345505d84fb952711832 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 16:35:17 +0100 Subject: [PATCH 1328/2059] Remove not used firewall include on all proxy --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 5 ++++- shadowsocks-rust/files/shadowsocks-rust.init-nft | 5 ++++- v2ray-core/files/etc/init.d/v2ray-nft | 4 ++++ xray-core/files/etc/firewall.xray-rules | 2 +- xray-core/files/etc/init.d/xray-nft | 4 ++++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index 340a479d0..39d8a5f7a 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -255,7 +255,10 @@ rules_exist() { start_service() { local cfgtype - + [ -n "$(uci -q get firewall.ss_rules)" ] && { + uci -q del firewall.ss_rules + uci -q commit firewall + } mkdir -p "$ss_confdir" config_load shadowsocks-libev for cfgtype in ss_local ss_redir ss_server ss_tunnel; do diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index d1d153deb..c631ee569 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -210,7 +210,10 @@ rules_exist() { start_service() { local cfgtype - + [ -n "$(uci -q get firewall.ssr_rules)" ] && { + uci -q del firewall.ssr_rules + uci -q commit firewall + } mkdir -p "$ss_confdir" config_load shadowsocks-rust for cfgtype in ss_local ss_redir ss_server ss_tunnel; do diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft index ed4027673..503dd2813 100755 --- a/v2ray-core/files/etc/init.d/v2ray-nft +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -2100,6 +2100,10 @@ clear_transparent_proxy() { start_instance() { local section="$1" + [ -n "$(uci -q get firewall.v2ray)" ] && { + uci -q del firewall.v2ray + uci -q commit firewall + } if ! v2ray_section_validate "$section" ; then _err "Invalid config." diff --git a/xray-core/files/etc/firewall.xray-rules b/xray-core/files/etc/firewall.xray-rules index 064828b3b..2a82fba79 100644 --- a/xray-core/files/etc/firewall.xray-rules +++ b/xray-core/files/etc/firewall.xray-rules @@ -1,2 +1,2 @@ #!/bin/sh -[ "$(uci -q get xray.main_dns.enabled)" = "1"] && /etc/init.d/xray rules_up +[ "$(uci -q get xray.main_dns.enabled)" = "1" ] && /etc/init.d/xray rules_up diff --git a/xray-core/files/etc/init.d/xray-nft b/xray-core/files/etc/init.d/xray-nft index a92efe7df..ad7b70aac 100755 --- a/xray-core/files/etc/init.d/xray-nft +++ b/xray-core/files/etc/init.d/xray-nft @@ -2321,6 +2321,10 @@ rules_down() { start_service() { + [ -n "$(uci -q get firewall.xray)" ] && { + uci -q del firewall.xray + uci -q commit firewall + } clear_transparent_proxy config_load "$NAME" From 6da3a4768a7472c9a962f34367f15c3b1c168790 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 16:44:13 +0100 Subject: [PATCH 1329/2059] Set again custom rules for each proxy, else current rules are removed on another proxy stop --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 5 +++-- shadowsocks-rust/files/shadowsocks-rust.init-nft | 5 +++-- v2ray-core/files/etc/init.d/v2ray-nft | 2 +- xray-core/files/etc/init.d/xray-nft | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index 39d8a5f7a..89cc846b2 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -15,7 +15,7 @@ ss_confdir=/var/etc/shadowsocks-libev ss_bindir=/usr/bin ssrules_uc="/usr/share/ss-rules/ss-rules.uc" -ssrules_nft="/etc/nftables.d/90-ss-rules.nft" +ssrules_nft="/etc/nftables.d/90-proxy-ss-rules.nft" ss_mkjson_server_conf() { local cfgserver @@ -219,8 +219,9 @@ ss_rules_nft_gen() { } ss_rules_nft_reset() { - if [ -f "$ssrules_nft" ]; then + if [ -f "$ssrules_nft" ] || [ -f "${ssrules_nft}.down" ]; then rm -f "$ssrules_nft" + rm -f "${ssrules_nft}.down" fw4 -q restart fi } diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index c631ee569..eaa60035a 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -15,7 +15,7 @@ ss_confdir=/var/etc/shadowsocks-rust ss_bindir=/usr/bin ssrules_uc="/usr/share/ssr-rules/ss-rules.uc" -ssrules_nft="/etc/nftables.d/90-proxy-rules.nft" +ssrules_nft="/etc/nftables.d/90-proxy-ssr-rules.nft" ss_mkjson_server_conf() { local cfgserver @@ -172,8 +172,9 @@ ss_rules_nft_gen() { } ss_rules_nft_reset() { - if [ -f "$ssrules_nft" ]; then + if [ -f "$ssrules_nft" ] || [ -f "${ssrules_nft}.down" ]; then rm -f "$ssrules_nft" + rm -f "${ssrules_nft}.down" fw4 -q restart fi } diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft index 503dd2813..110b3c6ff 100755 --- a/v2ray-core/files/etc/init.d/v2ray-nft +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -13,7 +13,7 @@ NAME=v2ray CONFIG_FOLDER=/var/etc/$NAME v2rrules_uc="/usr/share/v2ray-rules/v2r-rules.uc" -v2rrules_nft="/etc/nftables.d/90-proxy-rules.nft" +v2rrules_nft="/etc/nftables.d/90-proxy-v2ray-rules.nft" FILE_V2RAY_DNSMASQ=/tmp/dnsmasq.d/$NAME FILE_V2RAY_DNSMASQ_CACHE=/tmp/$NAME.dnsmasq.cache diff --git a/xray-core/files/etc/init.d/xray-nft b/xray-core/files/etc/init.d/xray-nft index ad7b70aac..a4033ad3a 100755 --- a/xray-core/files/etc/init.d/xray-nft +++ b/xray-core/files/etc/init.d/xray-nft @@ -13,7 +13,7 @@ NAME=xray CONFIG_FOLDER=/var/etc/$NAME xrrules_uc="/usr/share/xray-rules/xr-rules.uc" -xrrules_nft="/etc/nftables.d/90-proxy-rules.nft" +xrrules_nft="/etc/nftables.d/90-proxy-x2ray-rules.nft" FILE_XRAY_DNSMASQ=/tmp/dnsmasq.d/$NAME FILE_XRAY_DNSMASQ_CACHE=/tmp/$NAME.dnsmasq.cache From 17c84979e2d24e7ad99c1f689d00b75f02a6583e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 18:25:16 +0100 Subject: [PATCH 1330/2059] Set restart and reload as stop/stop on proxy scripts --- omr-bypass/files/etc/init.d/omr-bypass-nft | 5 +++++ shadowsocks-libev/files/shadowsocks-libev.init-nft | 10 ++++++++++ shadowsocks-rust/files/shadowsocks-rust.init-nft | 10 ++++++++++ v2ray-core/files/etc/init.d/v2ray-nft | 10 ++++++++++ xray-core/files/etc/init.d/xray-nft | 11 +++++++++++ 5 files changed, 46 insertions(+) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 9e67e216c..31a2162fc 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -922,6 +922,11 @@ reload_service() { stop start } +restart_service() { + RELOAD=1 + stop + start +} reload_rules() { #[ "$( ipset -n list | grep omr_ )" = "" ] && return 0 diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index 89cc846b2..0abc4855d 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -273,6 +273,16 @@ stop_service() { rm -rf "$ss_confdir" } +restart_service() { + stop + start +} + +reload_service() { + stop + start +} + service_triggers() { procd_add_reload_interface_trigger wan procd_add_reload_trigger shadowsocks-libev diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index eaa60035a..c5b77740e 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -228,6 +228,16 @@ stop_service() { rm -rf "$ss_confdir" } +restart_service() { + stop + start +} + +reload_service() { + stop + start +} + service_triggers() { procd_add_reload_interface_trigger wan procd_add_reload_trigger shadowsocks-rust diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft index 110b3c6ff..006e1428f 100755 --- a/v2ray-core/files/etc/init.d/v2ray-nft +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -2304,6 +2304,16 @@ stop_service() { test -d "$CONFIG_FOLDER" && rm -rf "$CONFIG_FOLDER" } +restart_service() { + stop + start +} + +reload_service() { + stop + start +} + service_triggers() { procd_add_reload_trigger "$NAME" } diff --git a/xray-core/files/etc/init.d/xray-nft b/xray-core/files/etc/init.d/xray-nft index a4033ad3a..76689de1c 100755 --- a/xray-core/files/etc/init.d/xray-nft +++ b/xray-core/files/etc/init.d/xray-nft @@ -2360,6 +2360,17 @@ stop_service() { test -d "$CONFIG_FOLDER" && rm -rf "$CONFIG_FOLDER" } +restart_service() { + stop + start +} + +reload_service() { + stop + start +} + + service_triggers() { procd_add_reload_trigger "$NAME" } From a605265756616881363131d42af740b3cd9732c6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 18:25:35 +0100 Subject: [PATCH 1331/2059] Fix restart of omr-bypass in schedule --- omr-schedule/files/usr/share/omr/schedule.d/010-services | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-schedule/files/usr/share/omr/schedule.d/010-services b/omr-schedule/files/usr/share/omr/schedule.d/010-services index b1976ba2a..ef220bfcd 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/010-services +++ b/omr-schedule/files/usr/share/omr/schedule.d/010-services @@ -202,7 +202,7 @@ fi if [ -f /etc/init.d/omr-bypass ] && (([ -e /usr/sbin/iptables-nft-save ] && [ "$(iptables-nft-save 2>/dev/null | grep omr-bypass)" = "" ]) || [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ]) && [ "$(pgrep -f omr-bypass)" = "" ]; then _log "Can't find omr-bypass rules, restart omr-bypass..." - /etc/init.d/omr-bypass 2>&1 >/dev/null + /etc/init.d/omr-bypass start 2>&1 >/dev/null sleep 5 fi From 4bdbd1a4c8dcf1cf8ef6a90d257ac2c8dfce2736 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 18:26:00 +0100 Subject: [PATCH 1332/2059] Better log when new public ip detected --- mptcp/files/usr/share/omr/post-tracking.d/020-status | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/020-status b/mptcp/files/usr/share/omr/post-tracking.d/020-status index 3d3f28e35..a73ac1069 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/020-status +++ b/mptcp/files/usr/share/omr/post-tracking.d/020-status @@ -65,7 +65,12 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRAC } fi [ -n "$ipaddr" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.publicip)" != "$ipaddr" ] && { - _log "New public ip detected for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE): $ipaddr (previous: $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.publicip))" + previousip="$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.publicip)" + if [ -n "$previousip" ]; then + _log "New public ip detected for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE): $ipaddr (previous: $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.publicip))" + else + _log "New public ip detected for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE): $ipaddr (First public IP detected)" + fi uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.publicip="$ipaddr" /etc/init.d/mptcp enabled && { _log "Reload MPTCP for $OMR_TRACKER_DEVICE" From 9d53bf202f5993272d78bb4a3389db8db55f053f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 18:26:33 +0100 Subject: [PATCH 1333/2059] Reload instead of restart of network in openmptcprouter-vps --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 7683774a9..8b7afd374 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1939,7 +1939,7 @@ _set_config_from_vps() { set network.omr6in4.gateway="$omr6in4_vps_localip" commit network EOF - /etc/init.d/network restart + /etc/init.d/network reload sleep 6 fi From 83643aa07b84cc9da9c947905df19f9581a10aa8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 17 Jan 2024 18:27:20 +0100 Subject: [PATCH 1334/2059] Set ping-restart parameter to 60 instead of 120 for OpenVPN --- openmptcprouter/files/etc/uci-defaults/2020-omr-vpn | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index 334cf75d8..69c3632a7 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -46,6 +46,7 @@ if [ "$(uci -q get openvpn.omr.proto)" != "tcp-client" ]; then set openvpn.omr.rcvbuf=0 set openvpn.omr.route_delay=5 set openvpn.omr.disable_dco=1 + set openvpn.omr.ping_restart=60 commit openvpn EOF fi @@ -54,6 +55,12 @@ if [ -z "$(uci -q get openvpn.omr.disable_dco)" ]; then set openvpn.omr.disable_dco=1 commit openvpn EOF +fi +if [ -z "$(uci -q get openvpn.omr.ping_restart)" ]; then + uci -q batch <<-EOF >/dev/null + set openvpn.omr.ping_restart=60 + commit openvpn + EOF fi From 91316a23a4de19aba6e39027c50a841f9e68c02e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 08:56:10 +0100 Subject: [PATCH 1335/2059] Fix OMR-Tracker ping detection --- omr-tracker/files/bin/omr-tracker | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 8cf858c61..9ab5b40d7 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -173,7 +173,8 @@ _ping() { -Q 184 \ "${host}" 2>&1 ) - loss=$(echo "$ret" | grep 'packet loss' | sed -ne 's/.*\([0-9]\+\)% packet loss.*/\1/p') + #loss=$(echo "$ret" | grep 'packet loss' | sed -ne 's/.*\([0-9]\+\)% packet loss.*/\1/p') + loss=$(echo "$ret" | grep 'packet loss' | cut -d " " -f6 | sed 's/%//' | tr -d '\n') if [ -n "$loss" ] && [ "$loss" -ne 100 ]; then if [ "$localip" = "yes" ]; then latency=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') From c184f30c1076ed88845585917a1b2456e8723413 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 10:03:46 +0100 Subject: [PATCH 1336/2059] Delete old dnsmasq ipset when using dscp nft --- omr-dscp/files/etc/init.d/omr-dscp-nft | 3 ++- openmptcprouter/files/etc/uci-defaults/0000-omr-update | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/omr-dscp/files/etc/init.d/omr-dscp-nft b/omr-dscp/files/etc/init.d/omr-dscp-nft index bf764b6e9..c67af2b02 100755 --- a/omr-dscp/files/etc/init.d/omr-dscp-nft +++ b/omr-dscp/files/etc/init.d/omr-dscp-nft @@ -21,7 +21,7 @@ config_get lan_device lan ifname _add_dscp_domain() { domain=""; config_get domain "$1" name "" class=""; config_get class "$1" class "" - [ -n "$domain" ] && [ -n "$class" ] && [ -z "$(uci -q get dhcp.omr_dscp-$class.domain | grep $domain)" ] && { + [ -n "$domain" ] && [ -n "$class" ] && [ -z "$(uci -q get dhcp.omr_dscp_$class.domain | grep $domain)" ] && { uci -q batch <<-EOF add_list dhcp.omr_dscp_$class.domain="$domain" commit dhcp @@ -146,6 +146,7 @@ _setup_tunnel() { } _cleanup() { + uci -q del dhcp.@dnsmasq[0].ipset config_load dhcp config_foreach _remove_ipset_dnsmasq config_load firewall diff --git a/openmptcprouter/files/etc/uci-defaults/0000-omr-update b/openmptcprouter/files/etc/uci-defaults/0000-omr-update index 03f36123e..b3a1b70b0 100755 --- a/openmptcprouter/files/etc/uci-defaults/0000-omr-update +++ b/openmptcprouter/files/etc/uci-defaults/0000-omr-update @@ -3,6 +3,7 @@ cd /etc/uci-defaults || exit 0 # Keep dnsmasq ipset with old method rm -f /etc/uci-defaults/50-dnsmasq-migrate-ipset.sh +uci -q del dhcp.@dnsmasq[0].ipset source /etc/os-release From 4da4487376cfbc4ee5b03b4ab29c9649373b2d83 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 10:20:35 +0100 Subject: [PATCH 1337/2059] Fix XRay --- xray-core/Makefile | 4 ++-- xray-core/files/etc/init.d/xray | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xray-core/Makefile b/xray-core/Makefile index 23f6786c2..262d926d0 100644 --- a/xray-core/Makefile +++ b/xray-core/Makefile @@ -41,7 +41,7 @@ define Package/$(PKG_NAME)-config-nft TITLE+= (init script with nft) endef -define Package/$(PKG_NAME)/description +define Package/$(PKG_NAME)-core/description Xray-core bare bones binary (compiled without cgo) endef @@ -53,7 +53,7 @@ define Package/$(PKG_NAME)-config-nft/description Xray-core init script with nft support endef -define Package/$(PKG_NAME)/config +define Package/$(PKG_NAME)-core/config menu "Xray Configuration" depends on PACKAGE_$(PKG_NAME)-core diff --git a/xray-core/files/etc/init.d/xray b/xray-core/files/etc/init.d/xray index 3fa53a12f..1ad2ff53a 100755 --- a/xray-core/files/etc/init.d/xray +++ b/xray-core/files/etc/init.d/xray @@ -2114,7 +2114,7 @@ start_instance() { fi if [ -z "$xray_file" ] || [ ! -s "$xray_file" ] ; then - _err "Invalid V2Ray file." + _err "Invalid XRay file." return 1 fi From c4ebf454ad61c71154d5e7a2adda7d609e54e4c1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 14:35:38 +0100 Subject: [PATCH 1338/2059] Call less often ip command in multipath --- mptcp/files/usr/bin/multipath | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 014c3a8af..1b872182c 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -132,20 +132,23 @@ if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then printf "0x%02x" $(($(($IFF^$(($IFF&$IFF_MASK))))|$FLAG)) > $FLAG_PATH else # Remove not needed if* interfaces in MPTCP - oldintfs=$(ip mptcp endpoint show | grep "dev if" | awk '{ print $3 }') + endpoint="$(ip mptcp endpoint show)" + [ -z "$endpoint" ] && exit 0 + oldintfs=$(echo "${endpoint}" | grep "dev if" | awk '{ print $3 }') [ -n "$oldintfs" ] && { for oldintf in $oldintfs; do ip mptcp endpoint delete id $oldintf 2>&1 >/dev/null done } - - ID=$(ip mptcp endpoint show | sort | grep "dev $DEVICE " | awk '{print $3}') - IFF=$(ip mptcp endpoint show | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') + endpoint="$(ip mptcp endpoint show)" + [ -z "$endpoint" ] && exit 0 + ID=$(echo "${endpoint}" | sort | grep "dev $DEVICE " | awk '{print $3}') + IFF=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') [ -f /usr/bin/jsonfilter ] && IP=$(ip -j a show $DEVICE | jsonfilter -e '@[0].addr_info[*].local') [ -f /usr/bin/jq ] && IP=$(ip -j a show $DEVICE | jq -r '.[0].addr_info[].local') - [ -z "$ID" ] && [ -n "$IP" ] && ID=$(ip mptcp endpoint show | grep "$IP " | awk '{print $3}') - RMID=$(ip mptcp endpoint show | grep '::ffff' | awk '{ print $3 }') + [ -z "$ID" ] && [ -n "$IP" ] && ID=$(echo "${endpoint}" show | grep "$IP " | awk '{print $3}') + RMID=$(echo "${endpoint}" | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null case $TYPE in "off") From 99e73464825dfc706ba5f9173a784c3474b4e740 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 14:36:29 +0100 Subject: [PATCH 1339/2059] Fix omr-tracker-server script up/down --- omr-tracker/files/bin/omr-tracker-server | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 69c33a78f..f270d86d5 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -174,8 +174,8 @@ _check_master() { echo -e "Subject: $OMR_SYSNAME: Server ${name} (${ip}) is UP\n. The reason is \"$OMR_TRACKER_STATUS_MSG\"." | sendmail $(uci -q get mail.default.to) fi } - script_alert_down="$(uci -q get omr-tracker.proxy.script_alert_up)" - [ -n "$script_alert_down" ] && eval $script_alert_up + script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" + [ -n "$script_alert_up" ] && eval $script_alert_up count=$((count+1)) else logger -t "OMR-Tracker-Server" "Master server ${name} down ($ip)" @@ -317,8 +317,8 @@ _check_backup() { echo -e "Subject: $OMR_SYSNAME: Server ${name} (${ip}) is UP\n. The reason is \"$OMR_TRACKER_STATUS_MSG\"." | sendmail $(uci -q get mail.default.to) fi } - script_alert_down="$(uci -q get omr-tracker.proxy.script_alert_up)" - [ -n "$script_alert_down" ] && eval $script_alert_up + script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" + [ -n "$script_alert_up" ] && eval $script_alert_up count=$((count+1)) else uci -q batch <<-EOF >/dev/null @@ -374,7 +374,6 @@ interval=${OMR_TRACKER_INTERVAL:-10} intervaltries=${OMR_TRACKER_INTERVAL_TRIES:-2} retry=${OMR_TRACKER_TRIES:-4} waittest=${OMR_TRACKER_WAIT_TEST:-0} - while true; do server_ping=false config_load openmptcprouter From b84118d27dd7cca654ff3054c5d47f52b10be279 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 14:36:46 +0100 Subject: [PATCH 1340/2059] Fix OMR-ByPass check --- omr-bypass/files/etc/init.d/omr-bypass-nft | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 31a2162fc..92dfbf96f 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -807,6 +807,15 @@ start_service() { #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all accept #nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all accept EOF + #config_load shadowsocks-libev + #config_foreach _ss_rules_config ss_rules + ([ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] || [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]) && _ss_rules_config + #config_load shadowsocks-rust + #config_foreach _ss_rules_config ss_rules + [ "$(uci -q get v2ray.main.enabled)" = "1" ] && _v2ray_rules_config + [ "$(uci -q get xray.main.enabled)" = "1" ] && _xray_rules_config + + uci batch <<-EOF set firewall.omr_bypass=include set firewall.omr_bypass.enabled='1' @@ -846,14 +855,6 @@ start_service() { # ip rule add prio 1 fwmark 0x4539 lookup 991337 > /dev/null 2>&1 # ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 - #config_load shadowsocks-libev - #config_foreach _ss_rules_config ss_rules - ([ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] || [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]) && _ss_rules_config - #config_load shadowsocks-rust - #config_foreach _ss_rules_config ss_rules - [ "$(uci -q get v2ray.main.enabled)" = "1" ] && _v2ray_rules_config - [ "$(uci -q get xray.main.enabled)" = "1" ] && _xray_rules_config - # NDPI Netfilter is not available for nftables $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass-dpi | $IPTABLESRESTORE -w --counters 2>/dev/null $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF From 47547dcc81821e316e6a3fd5af2963c3af2773ab Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 17:23:30 +0100 Subject: [PATCH 1341/2059] Fix find gateway in omr-tracker in some case --- omr-tracker/files/bin/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 9ab5b40d7..8c11bcc43 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -317,7 +317,7 @@ while true; do OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -m 1 default | awk '/via/ {print $3}' | tr -d "\n") fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | awk '/via/ {print $3}' | tr -d "\n") + OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | awk '/via/ {print $3;exit}' | tr -d "\n") fi fi if ([ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ] || [ -z "$OMR_TRACKER_IPV6" ]) && ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]); then From 766ee12b7da590ae7fdae86d7b69fff7f8156222 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 18 Jan 2024 17:23:54 +0100 Subject: [PATCH 1342/2059] Fix get gateway in mptcp script --- mptcp/files/etc/init.d/mptcp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index e2cd16260..4761f7b93 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -240,6 +240,9 @@ interface_multipath_settings() { if [ -z "$gateway" ] || [ "$( valid_subnet4 $gateway )" != "ok" ]; then gateway=$(ubus call network.interface.${config}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") fi + if [ -z "$gateway" ] || [ "$( valid_subnet4 $gateway )" != "ok" ]; then + gateway=$(ip -4 r list dev "$iface" | awk '/via/ {print $3;exit}' | tr -d "\n") + fi if [ -z "$gateway" ] || [ "$( valid_subnet4 $gateway )" != "ok" ]; then gateway=$(traceroute -m1 -i $iface 8.8.8.8 2>/dev/null | awk 'FNR==2{ print $2 }') [ "$gateway" = "*" ] && gateway="" @@ -297,7 +300,7 @@ interface_multipath_settings() { ip route replace $network/$netmask dev $iface scope link table $id $initcwrwnd 2>&1 >/dev/null ip route replace default via $gateway dev $iface table $id $initcwrwnd 2>&1 >/dev/null [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip route replace default via $gateway dev $iface metric $id $initcwrwnd 2>&1 >/dev/null - ip route flush cache $id 2>&1 >/dev/null + #ip route flush cache $id 2>&1 >/dev/null fi #config_get mode "$config" multipath "" @@ -387,7 +390,7 @@ interface_multipath_settings() { ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id $initcwrwnd 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface table 6$id $initcwrwnd 2>&1 >/dev/null [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && ip -6 route replace default via $gateway6 dev $iface metric 6$id $initcwrwnd 2>&1 >/dev/null - ip -6 route flush cache 6$id 2>&1 >/dev/null + #ip -6 route flush cache 6$id 2>&1 >/dev/null fi #config_get mode "$config" multipath "off" @@ -528,14 +531,14 @@ start_service() { #config_foreach remove route6 #config_foreach remove rule #config_foreach remove rule6 - [ -z "$intf" ] && [ -n "$(uci -q get network.@route[-1])" ] && { - # logger -t "MPTCP" "Flush main table" - # ip route flush table main - # ip -6 route flush table main - logger -t "MPTCP" "Flush route cache" - ip route flush cache - ip -6 route flush cache - } + #[ -z "$intf" ] && [ -n "$(uci -q get network.@route[-1])" ] && { + ## logger -t "MPTCP" "Flush main table" + ## ip route flush table main + ## ip -6 route flush table main + # logger -t "MPTCP" "Flush route cache" + # ip route flush cache + # ip -6 route flush cache + #} if [ "$(uci -q get network.globals.mptcp_disable_initial_config)" != "1" ]; then config_foreach interface_multipath_settings interface $intf config_foreach add_route route From 9153623fd913cb79b9f6a0a592cba25a9ab2a0d8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 09:09:46 +0100 Subject: [PATCH 1343/2059] Fix OMR-ByPass NFT --- omr-bypass/files/etc/init.d/omr-bypass-nft | 90 ++++++++++++---------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 92dfbf96f..a7ebdb39f 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -397,7 +397,7 @@ _bypass_proto_without_ndpi() { set firewall.bypass_$proto_rule.src='lan' set firewall.bypass_$proto_rule.dest='*' set firewall.bypass_$proto_rule.target='MARK' - set firewall.bypass_$proto_rule.set_xmark="4539${intfid}" + set firewall.bypass_$proto_rule.set_xmark="0x4539${intfid}" commit firewall EOF uci -q batch <<-EOF >/dev/null @@ -409,7 +409,7 @@ _bypass_proto_without_ndpi() { set firewall.bypass6_$proto_rule.src='lan' set firewall.bypass6_$proto_rule.dest='*' set firewall.bypass6_$proto_rule.target='MARK' - set firewall.bypass6_$proto_rule.set_xmark="6539${intfid}" + set firewall.bypass6_$proto_rule.set_xmark="0x6539${intfid}" commit firewall EOF #if [ "$intfid" != "" ]; then @@ -501,12 +501,12 @@ _bypass_proto_without_ndpi() { _intf_rule_ss_rules() { cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept - nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 meta mark set 0x00004539 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 meta mark set 0x00004539 accept EOF if [ "$disableipv6" = "0" ]; then cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 ss_rules_pre_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept EOF fi @@ -514,12 +514,12 @@ _intf_rule_ss_rules() { _intf_rule_v2ray_rules() { cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 v2r_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 accept nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept EOF if [ "$disableipv6" = "0" ]; then cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 v2r_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 v2r_rules_pre_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept EOF fi @@ -527,12 +527,12 @@ _intf_rule_v2ray_rules() { _intf_rule_xray_rules() { cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 xr_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 accept nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept EOF if [ "$disableipv6" = "0" ]; then cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 xr_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 xr_rules_pre_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept EOF fi @@ -585,11 +585,17 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_mark="0x${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept=rule + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.name="omr_dst_bypass_${intf}_rule_accept" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.target='ACCEPT' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.dest='*' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.mark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.name="omr_dst_bypass_${intf}_srcip" set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" @@ -597,14 +603,14 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_mac_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.name='omr_dst_bypass_${intf}_mac' set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.dest='*' set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.set_xmark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.proto='tcp' @@ -612,7 +618,7 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.dest='*' set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.set_xmark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.proto='udp' @@ -620,21 +626,21 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.dest='*' set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.set_xmark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest='*' set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.set_xmark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest='*' set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='0' - set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="0x${ipv46}539${count}" commit firewall EOF done @@ -725,43 +731,45 @@ _bypass_omr_server() { _ss_rules_config() { cat >> /etc/firewall.omr-bypass <<-EOF [ -z "\$(nft list ruleset | grep ss_rules)" ] && exit 0 - nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept - nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 meta mark set 0x00004539 accept + #nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 meta mark set 0x00004539 accept + #nft add chain inet fw4 bypass_prerouting '{ type nat hook prerouting priority filter - 5; policy accept; }' + #nft add chain inet fw4 bypass_local '{ type nat hook output priority filter - 5; policy accept; }' EOF - if [ "$disableipv6" = "0" ]; then - cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept - nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept - EOF - fi + #if [ "$disableipv6" = "0" ]; then + # cat >> /etc/firewall.omr-bypass <<-EOF + # nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + # nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + # EOF + #fi } _v2ray_rules_config() { cat >> /etc/firewall.omr-bypass <<-EOF [ -z "\$(nft list ruleset | grep v2r_rules)" ] && exit 0 - nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept - nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + #nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + #nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_all_4 accept EOF - if [ "$disableipv6" = "0" ]; then - cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 v2r_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept - nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept - EOF - fi + #if [ "$disableipv6" = "0" ]; then + # cat >> /etc/firewall.omr-bypass <<-EOF + # nft insert rule inet fw4 v2r_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + # nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + # EOF + #fi } _xray_rules_config() { cat >> /etc/firewall.omr-bypass <<-EOF [ -z "\$(nft list ruleset | grep xr_rules)" ] && exit 0 - nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept - nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + #nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + #nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_all_4 accept EOF - if [ "$disableipv6" = "0" ]; then - cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 xr_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept - nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept - EOF - fi + #if [ "$disableipv6" = "0" ]; then + # cat >> /etc/firewall.omr-bypass <<-EOF + # nft insert rule inet fw4 xr_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + # nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + # EOF + #fi } _delete_dhcp_ipset() { From 5bc24b9727042fb6abe8736e533ddcb3ee81e3cc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 09:10:12 +0100 Subject: [PATCH 1344/2059] Fix OMR-DSCP nft --- omr-dscp/files/etc/init.d/omr-dscp-nft | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/omr-dscp/files/etc/init.d/omr-dscp-nft b/omr-dscp/files/etc/init.d/omr-dscp-nft index c67af2b02..19aa9d589 100755 --- a/omr-dscp/files/etc/init.d/omr-dscp-nft +++ b/omr-dscp/files/etc/init.d/omr-dscp-nft @@ -46,18 +46,20 @@ _add_dscp_domains_rules() { set firewall.omr_dscp_${class}_6.match='dest_ip' EOF uci -q batch <<-EOF - set firewall.omr_dscp_${class}=rule - set firewall.omr_dscp_${class}.ipset="omr_dscp_${class}_4" - set firewall.omr_dscp_${class}.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" - set firewall.omr_dscp_${class}.target='DSCP' - set firewall.omr_dscp_${class}.src='lan' - set firewall.omr_dscp_${class}.dest='*' - set firewall.omr6_dscp_${class}=rule - set firewall.omr6_dscp_${class}.ipset="omr_dscp_${class}_6" - set firewall.omr6_dscp_${class}.target='DSCP' - set firewall.omr6_dscp_${class}.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" - set firewall.omr6_dscp_${class}.src='lan' - set firewall.omr6_dscp_${class}.dest='*' + set firewall.omr_dscp_rule_${class}_4=rule + set firewall.omr_dscp_rule_${class}_4.name="omr_dscp_${class}_4" + set firewall.omr_dscp_rule_${class}_4.ipset="omr_dscp_${class}_4" + set firewall.omr_dscp_rule_${class}_4.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" + set firewall.omr_dscp_rule_${class}_4.target='DSCP' + set firewall.omr_dscp_rule_${class}_4.src='lan' + set firewall.omr_dscp_rule_${class}_4.dest='*' + set firewall.omr_dscp_rule_${class}_6=rule + set firewall.omr_dscp_rule_${class}_6.name="omr6_dscp_${class}_6" + set firewall.omr_dscp_rule_${class}_6.ipset="omr_dscp_${class}_6" + set firewall.omr_dscp_rule_${class}_6.target='DSCP' + set firewall.omr_dscp_rule_${class}_6.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" + set firewall.omr_dscp_rule_${class}_6.src='lan' + set firewall.omr_dscp_rule_${class}_6.dest='*' commit firewall EOF done From ff2f5f804f2afb2ed298a0150f5db85ac04fa897 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 11:47:12 +0100 Subject: [PATCH 1345/2059] Less log for MPTCP init --- mptcp/files/etc/init.d/mptcp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 4761f7b93..6a4b6ee13 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -406,10 +406,14 @@ interface_multipath_settings() { fi if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then - logger -t "MPTCP" "Set $iface to $mode" - if [ "$mode" = "master" ]; then + if ([ "$mode" = "master" ] || [ "$mode" = "on" ]) && [ -z "$(multipath $iface | grep default)" ]; then + logger -t "MPTCP" "Set $iface to $mode" multipath "$iface" "on" - else + elif [ "$mode" = "off" ] && [ -z "$(multipath $iface | grep deactivated)" ] + logger -t "MPTCP" "Set $iface to $mode" + multipath "$iface" "$mode" + elif [ "$mode" = "backup" ] && [ -z "$(multipath $iface | grep backup)" ] + logger -t "MPTCP" "Set $iface to $mode" multipath "$iface" "$mode" fi fi From 2a13fc8e50eae0738b3c13dcffa19e27cc977a46 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 11:47:39 +0100 Subject: [PATCH 1346/2059] Restart interface in more case with ModemManager --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 0a30e6cbc..4f5ca421d 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -732,7 +732,8 @@ initcwrwnd="" # An interface in error will never be used in MPTCP if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then #if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then - if [ "$interface_available" = "true" ] && ([ "$interface_pending" = "true" ] || [ "$interface_up" = "true" ]) && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then + #if [ "$interface_available" = "true" ] && ([ "$interface_pending" = "true" ] || [ "$interface_up" = "true" ]) && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then + if [ "$interface_available" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart interface" _log "Set $OMR_TRACKER_INTERFACE down" ifdown $OMR_TRACKER_INTERFACE From bc8582e74643f95881d35e5b0b5e27a5e408424e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 11:48:08 +0100 Subject: [PATCH 1347/2059] Fix omr-tracker-server --- omr-tracker/files/bin/omr-tracker-server | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index f270d86d5..f0236e4e9 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -40,8 +40,8 @@ _check_server() { _check_server_intf() { local host=$1 local port=$2 - local k=0 for intf in $(multipath | awk '/default/ {print $1}'); do + local k=0 while [ "$server_ping" = false ] && [ "$k" -le "$retry" ]; do ret=$(curl \ --max-time "$OMR_TRACKER_TIMEOUT" \ @@ -52,7 +52,6 @@ _check_server_intf() { ) [ -n "$ret" ] && { server_ping=true - return } k=$((k+1)) sleep "${intervaltries}" From ba4e77d0649225082530b0290eb84f8a4d5ee9eb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 11:48:32 +0100 Subject: [PATCH 1348/2059] Fix OMR-Tracker delay --- omr-tracker/files/bin/omr-tracker | 10 +++++----- omr-tracker/files/etc/init.d/omr-tracker | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 8c11bcc43..ea488022e 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -311,10 +311,10 @@ while true; do OMR_TRACKER_DEVICE_ROUTE=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep via | grep -v default | grep -v metric | grep -v / | awk '{print $1; exit}' | tr -d "\n") fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | grep -v '.0/' | awk '/proto kernel/ {print $1}' | tr -d "\n") + OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | grep -v '.0/' | awk '/proto kernel/ {print $1;exit}' | tr -d "\n") fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then - OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -m 1 default | awk '/via/ {print $3}' | tr -d "\n") + OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -m 1 default | awk '/via/ {print $3;exit}' | tr -d "\n") fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | awk '/via/ {print $3;exit}' | tr -d "\n") @@ -349,9 +349,9 @@ while true; do if ([ "$OMR_TRACKER_FAMILY" = "ipv4" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then # setup loop variable if [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ]; then - tries="$OMR_TRACKER_TRIES" - else tries="$OMR_TRACKER_TRIES_UP" + else + tries="$OMR_TRACKER_TRIES" fi # loop until tries attempts have been reached while [ "$tries" -gt 0 ]; do @@ -612,7 +612,7 @@ while true; do _restart if [ "$OMR_TRACKER_STATUS" = "ERROR" ]; then - sleep "${OMR_TRACKER_FAILURE_INTERVAL:-5}" + [ -n "$OMR_TRACKER_FAILURE_INTERVAL" ] && sleep "$OMR_TRACKER_FAILURE_INTERVAL" else sleep "${OMR_TRACKER_INTERVAL:-2}" fi diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 202b5881b..252493310 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -92,7 +92,8 @@ _launch_tracker() { config_get ipv6 "$1" ipv6 config_get proto "$1" proto - [ -z "$ifname" ] || [ -z "$multipath" ] || [ "$multipath" = "off" ] && [ "$1" != "glorytun" ] && [ "$1" != "omrvpn" ] && [ "$( uci -q get openmptcprouter.$1.multipathvpn)" != "1" ] && return + #[ -z "$ifname" ] || [ -z "$multipath" ] || [ "$multipath" = "off" ] && [ "$1" != "glorytun" ] && [ "$1" != "omrvpn" ] && [ "$( uci -q get openmptcprouter.$1.multipathvpn)" != "1" ] && return + [ -z "$multipath" ] || [ "$multipath" = "off" ] && [ "$1" != "glorytun" ] && [ "$1" != "omrvpn" ] && [ "$( uci -q get openmptcprouter.$1.multipathvpn)" != "1" ] && return [ "$1" = "omrvpn" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" = "none" ] && return [ "${ifenabled}" = "0" ] && return [ "${enabled}" = "0" ] && return @@ -109,7 +110,7 @@ _launch_tracker() { [ -z "${tries}" ] && tries=5 [ -z "${reliability}" ] && reliability=1 [ -z "${tries_up}" ] && tries_up=${tries} - [ -z "${failure_interval}" ] && failure_interval=5 + #[ -z "${failure_interval}" ] && failure_interval=5 procd_open_instance # shellcheck disable=SC2086 From bc8a5f8b5f82c06e8e75a780c528beb389698f8e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 17:24:40 +0100 Subject: [PATCH 1349/2059] Update Rust --- rust/Config.in | 15 +++ rust/Makefile | 58 +++++----- rust/files/cargo-config | 8 -- .../0001-Update-xz2-and-use-it-static.patch | 14 +-- rust/patches/0002-Bumped-libc-version.patch | 35 ------ rust/patches/0002-rustc-bootstrap-cache.patch | 52 +++++++++ .../0003-bump-libc-deps-to-0.2.146.patch | 100 ++++++++++++++++++ rust/rust-host-build.mk | 44 ++++---- rust/rust-package.mk | 30 +++--- rust/rust-values.mk | 79 +++++++++++--- 10 files changed, 305 insertions(+), 130 deletions(-) create mode 100644 rust/Config.in delete mode 100644 rust/files/cargo-config delete mode 100644 rust/patches/0002-Bumped-libc-version.patch create mode 100644 rust/patches/0002-rustc-bootstrap-cache.patch create mode 100644 rust/patches/0003-bump-libc-deps-to-0.2.146.patch diff --git a/rust/Config.in b/rust/Config.in new file mode 100644 index 000000000..62051af13 --- /dev/null +++ b/rust/Config.in @@ -0,0 +1,15 @@ +menu "Configuration options (for developers)" + +config RUST_SCCACHE + bool "Use sccache" + help + Shared compilation cache; see https://github.com/mozilla/sccache + +config RUST_SCCACHE_DIR + string "Set sccache directory" if RUST_SCCACHE + default "" + help + Store sccache in this directory. + If not set, uses './.sccache' + +endmenu diff --git a/rust/Makefile b/rust/Makefile index 60df0e5cd..46ee84e9d 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -3,26 +3,26 @@ # Copyright (C) 2023 Luca Barbato and Donald Hoskins include $(TOPDIR)/rules.mk -include ./rust-values.mk PKG_NAME:=rust -PKG_VERSION:=1.71.1 +PKG_VERSION:=1.75.0 PKG_RELEASE:=1 PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.gz PKG_SOURCE_URL:=https://static.rust-lang.org/dist/ -PKG_HASH:=6fa90d50d1d529a75f6cc349784de57d7ec0ba2419b09bde7d335c25bd4e472e -HOST_BUILD_DIR:=$(BUILD_DIR)/host/rust-$(RUSTC_TARGET_ARCH)/rustc-$(PKG_VERSION)-src +PKG_HASH:=5b739f45bc9d341e2d1c570d65d2375591e22c2d23ef5b8a37711a0386abc088 +HOST_BUILD_DIR:=$(BUILD_DIR)/host/rustc-$(PKG_VERSION)-src PKG_MAINTAINER:=Luca Barbato PKG_LICENSE:=Apache-2.0 MIT PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT -HOST_BUILD_DEPENDS:=python3/host PKG_HOST_ONLY:=1 +PKG_BUILD_FLAGS:=no-mips16 include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk +include ./rust-values.mk define Package/rust SECTION:=lang @@ -39,8 +39,12 @@ define Package/rust/description guarantee memory safety by using a borrow checker to validate references. endef +define Package/rust/config + source "$(SOURCE)/Config.in" +endef + # Rust-lang has an uninstall script -RUST_UNINSTALL:=$(CARGO_HOME)/lib/rustlib/uninstall.sh +RUST_UNINSTALL:=$(STAGING_DIR)/host/lib/rustlib/uninstall.sh # Target Flags TARGET_CONFIGURE_ARGS = \ @@ -49,23 +53,24 @@ TARGET_CONFIGURE_ARGS = \ --set=target.$(RUSTC_TARGET_ARCH).cxx=$(TARGET_CXX_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).linker=$(TARGET_CC_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).ranlib=$(TARGET_RANLIB) \ + --set=target.$(RUSTC_TARGET_ARCH).crt-static=false \ $(if $(CONFIG_USE_MUSL),--set=target.$(RUSTC_TARGET_ARCH).musl-root=$(TOOLCHAIN_DIR)) # CARGO_HOME is an environmental -HOST_CONFIGURE_OPTS += CARGO_HOME="$(CARGO_HOME)" +HOST_CONFIGURE_VARS += CARGO_HOME="$(CARGO_HOME)" # Rust Configuration Arguments HOST_CONFIGURE_ARGS = \ --build=$(RUSTC_HOST_ARCH) \ --target=$(RUSTC_TARGET_ARCH),$(RUSTC_HOST_ARCH) \ --host=$(RUSTC_HOST_ARCH) \ - --prefix=$(CARGO_HOME) \ - --bindir=$(CARGO_HOME)/bin \ - --libdir=$(CARGO_HOME)/lib \ - --sysconfdir=$(CARGO_HOME)/etc \ - --datadir=$(CARGO_HOME)/share \ - --mandir=$(CARGO_HOME)/man \ - --dist-compression-formats=xz \ + --prefix=$(STAGING_DIR)/host \ + --bindir=$(STAGING_DIR)/host/bin \ + --libdir=$(STAGING_DIR)/host/lib \ + --sysconfdir=$(STAGING_DIR)/host/etc \ + --datadir=$(STAGING_DIR)/host/share \ + --mandir=$(STAGING_DIR)/host/man \ + --dist-compression-formats=gz \ --enable-missing-tools \ --disable-sanitizers \ --release-channel=stable \ @@ -80,23 +85,24 @@ define Host/Uninstall endef define Host/Compile - ( \ - cd $(HOST_BUILD_DIR) ; \ - $(PYTHON) x.py --config ./config.toml dist build-manifest cargo llvm-tools \ - rustc rust-std rust-src ; \ - ) + $(RUST_SCCACHE_VARS) \ + CARGO_HOME=$(CARGO_HOME) \ + TARGET_CFLAGS="$(TARGET_CFLAGS)" \ + OPENWRT_RUSTC_BOOTSTRAP_CACHE=$(DL_DIR)/rustc \ + $(PYTHON) $(HOST_BUILD_DIR)/x.py \ + --build-dir $(HOST_BUILD_DIR)/build \ + --config $(HOST_BUILD_DIR)/config.toml \ + dist build-manifest cargo llvm-tools rustc rust-std rust-src endef define Host/Install ( \ cd $(HOST_BUILD_DIR)/build/dist ; \ - find -iname "*.xz" -exec tar -xJf {} \; ; \ - find ./* -type f -name install.sh -execdir sh {} --prefix=$(CARGO_HOME) --disable-ldconfig \; ; \ - \ - sed -e 's|@RUSTC_TARGET_ARCH@|$(RUSTC_TARGET_ARCH)|g' \ - -e 's|@TARGET_CC_NOCACHE@|$(TARGET_CC_NOCACHE)|g' \ - -e 's|@RUSTC_LDFLAGS@|$(RUSTC_LDFLAGS)|g' \ - $(CURDIR)/files/cargo-config > $(CARGO_HOME)/config ; \ + for targz in *.tar.gz; do \ + $(STAGING_DIR_HOST)/bin/libdeflate-gzip -dc "$$$$targz" | tar -xf - ; \ + done ; \ + find . -mindepth 2 -maxdepth 2 -type f -name install.sh \ + -execdir bash '{}' --prefix=$(STAGING_DIR)/host --disable-ldconfig \; ; \ ) endef diff --git a/rust/files/cargo-config b/rust/files/cargo-config deleted file mode 100644 index 2ed512931..000000000 --- a/rust/files/cargo-config +++ /dev/null @@ -1,8 +0,0 @@ -[target.@RUSTC_TARGET_ARCH@] -linker = "@TARGET_CC_NOCACHE@" -rustflags = ["-Ctarget-feature=-crt-static", "-Clink-args=@RUSTC_LDFLAGS@"] - -[profile.stripped] -inherits = "release" -opt-level = "s" -strip = true diff --git a/rust/patches/0001-Update-xz2-and-use-it-static.patch b/rust/patches/0001-Update-xz2-and-use-it-static.patch index 8d0c4b042..2360136a7 100644 --- a/rust/patches/0001-Update-xz2-and-use-it-static.patch +++ b/rust/patches/0001-Update-xz2-and-use-it-static.patch @@ -11,7 +11,7 @@ Subject: [PATCH] Update xz2 and use it static --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock -@@ -443,9 +443,9 @@ dependencies = [ +@@ -391,9 +391,9 @@ dependencies = [ [[package]] name = "lzma-sys" @@ -23,7 +23,7 @@ Subject: [PATCH] Update xz2 and use it static dependencies = [ "cc", "libc", -@@ -912,9 +912,9 @@ dependencies = [ +@@ -834,9 +834,9 @@ dependencies = [ [[package]] name = "xz2" @@ -37,12 +37,12 @@ Subject: [PATCH] Update xz2 and use it static ] --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml -@@ -50,7 +50,7 @@ toml = "0.5" - ignore = "0.4.10" - opener = "0.5" - once_cell = "1.7.2" +@@ -57,7 +57,7 @@ tar = "0.4" + termcolor = "1.2.0" + toml = "0.5" + walkdir = "2" -xz2 = "0.1" +xz2 = { version = "0.1", features = ["static"] } - walkdir = "2" # Dependencies needed by the build-metrics feature + sysinfo = { version = "0.26.0", optional = true } diff --git a/rust/patches/0002-Bumped-libc-version.patch b/rust/patches/0002-Bumped-libc-version.patch deleted file mode 100644 index 52c8a245c..000000000 --- a/rust/patches/0002-Bumped-libc-version.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 032857e7e403f654129c45dc7e6718a9ad49e377 Mon Sep 17 00:00:00 2001 -From: Nikolay Arhipov -Date: Tue, 6 Jun 2023 16:09:05 +0300 -Subject: [PATCH] Bumped libc version - ---- - Cargo.lock | 4 ++-- - library/std/Cargo.toml | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -1988,9 +1988,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0e - - [[package]] - name = "libc" --version = "0.2.143" -+version = "0.2.146" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" -+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" - dependencies = [ - "rustc-std-workspace-core", - ] ---- a/library/std/Cargo.toml -+++ b/library/std/Cargo.toml -@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = [ - panic_unwind = { path = "../panic_unwind", optional = true } - panic_abort = { path = "../panic_abort" } - core = { path = "../core" } --libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } -+libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'] } - compiler_builtins = { version = "0.1.92" } - profiler_builtins = { path = "../profiler_builtins", optional = true } - unwind = { path = "../unwind" } diff --git a/rust/patches/0002-rustc-bootstrap-cache.patch b/rust/patches/0002-rustc-bootstrap-cache.patch new file mode 100644 index 000000000..959e23487 --- /dev/null +++ b/rust/patches/0002-rustc-bootstrap-cache.patch @@ -0,0 +1,52 @@ +--- a/src/bootstrap/bootstrap.py ++++ b/src/bootstrap/bootstrap.py +@@ -557,7 +557,7 @@ class RustBuild(object): + shutil.rmtree(bin_root) + + key = self.stage0_compiler.date +- cache_dst = os.path.join(self.build_dir, "cache") ++ cache_dst = os.getenv('OPENWRT_RUSTC_BOOTSTRAP_CACHE', os.path.join(self.build_dir, "cache")) + rustc_cache = os.path.join(cache_dst, key) + if not os.path.exists(rustc_cache): + os.makedirs(rustc_cache) +--- a/src/bootstrap/src/core/download.rs ++++ b/src/bootstrap/src/core/download.rs +@@ -208,7 +208,13 @@ impl Config { + Some(other) => panic!("unsupported protocol {other} in {url}"), + None => panic!("no protocol in {url}"), + } +- t!(std::fs::rename(&tempfile, dest_path)); ++ match std::fs::rename(&tempfile, dest_path) { ++ Ok(v) => v, ++ Err(_) => { ++ t!(std::fs::copy(&tempfile, dest_path)); ++ t!(std::fs::remove_file(&tempfile)); ++ } ++ } + } + + fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { +@@ -544,7 +550,10 @@ impl Config { + key: &str, + destination: &str, + ) { +- let cache_dst = self.out.join("cache"); ++ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { ++ Some(v) => PathBuf::from(v), ++ None => self.out.join("cache"), ++ }; + let cache_dir = cache_dst.join(key); + if !cache_dir.exists() { + t!(fs::create_dir_all(&cache_dir)); +@@ -671,7 +680,10 @@ download-rustc = false + let llvm_assertions = self.llvm_assertions; + + let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); +- let cache_dst = self.out.join("cache"); ++ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { ++ Some(v) => PathBuf::from(v), ++ None => self.out.join("cache"), ++ }; + let rustc_cache = cache_dst.join(cache_prefix); + if !rustc_cache.exists() { + t!(fs::create_dir_all(&rustc_cache)); diff --git a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch new file mode 100644 index 000000000..bb131d23f --- /dev/null +++ b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch @@ -0,0 +1,100 @@ +This patch bumps all libc dependencies and checksums to 0.2.147, which includes the fix for musl 1.2.4. + +--- a/vendor/addr2line-0.19.0/Cargo.lock ++++ b/vendor/addr2line-0.19.0/Cargo.lock +@@ -235,9 +235,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.126" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "memchr" +--- a/vendor/backtrace-0.3.67/Cargo.lock ++++ b/vendor/backtrace-0.3.67/Cargo.lock +@@ -64,9 +64,9 @@ checksum = "dec7af912d60cdbd3677c1af9352 + + [[package]] + name = "libc" +-version = "0.2.138" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "libloading" +--- a/vendor/crossbeam-channel/Cargo.lock ++++ b/vendor/crossbeam-channel/Cargo.lock +@@ -50,9 +50,9 @@ dependencies = [ + + [[package]] + name = "libc" +-version = "0.2.141" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "num_cpus" +--- a/vendor/elasticlunr-rs/Cargo.lock ++++ b/vendor/elasticlunr-rs/Cargo.lock +@@ -555,9 +555,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "lindera" +--- a/vendor/handlebars/Cargo.lock ++++ b/vendor/handlebars/Cargo.lock +@@ -550,9 +550,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "lock_api" +--- a/vendor/libffi/Cargo.lock ++++ b/vendor/libffi/Cargo.lock +@@ -10,9 +10,9 @@ checksum = "50d30906286121d95be3d479533b + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "libffi" +--- a/vendor/tracing-tree/Cargo.lock ++++ b/vendor/tracing-tree/Cargo.lock +@@ -296,9 +296,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.141" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "linux-raw-sys" diff --git a/rust/rust-host-build.mk b/rust/rust-host-build.mk index 39cf1f23c..e56292937 100644 --- a/rust/rust-host-build.mk +++ b/rust/rust-host-build.mk @@ -2,36 +2,42 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins +# Variables (all optional) to be set in package Makefiles: +# +# RUST_HOST_FEATURES - list of options, default empty +# +# Space or comma separated list of features to activate +# +# e.g. RUST_HOST_FEATURES:=enable-foo,with-bar + ifeq ($(origin RUST_INCLUDE_DIR),undefined) RUST_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) endif include $(RUST_INCLUDE_DIR)/rust-values.mk +CARGO_HOST_VARS= \ + $(CARGO_HOST_CONFIG_VARS) \ + CC=$(HOSTCC_NOCACHE) \ + MAKEFLAGS="$(HOST_JOBS)" + # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Host/Compile/Cargo - ( \ - cd $(HOST_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - CC=$(HOSTCC_NOCACHE) \ - cargo install -v \ - --profile stripped \ - $(if $(RUST_PKG_FEATURES),--features "$(RUST_PKG_FEATURES)") \ - --root $(HOST_INSTALL_DIR) \ - --path "$(if $(strip $(1)),$(strip $(1)),.)" $(2) ; \ - ) + +$(CARGO_HOST_VARS) \ + cargo install -v \ + --profile $(CARGO_HOST_PROFILE) \ + $(if $(RUST_HOST_FEATURES),--features "$(RUST_HOST_FEATURES)") \ + --root $(HOST_INSTALL_DIR) \ + --path "$(HOST_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ + $(if $(filter --jobserver%,$(HOST_JOBS)),,-j1) \ + $(2) endef define Host/Uninstall/Cargo - ( \ - cd $(HOST_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - CC=$(HOSTCC_NOCACHE) \ - cargo uninstall -v \ - --root $(HOST_INSTALL_DIR) || true ; \ - ) + +$(CARGO_HOST_VARS) \ + cargo uninstall -v \ + --root $(HOST_INSTALL_DIR) \ + || true endef define RustBinHostBuild diff --git a/rust/rust-package.mk b/rust/rust-package.mk index 955b37c29..24341d706 100644 --- a/rust/rust-package.mk +++ b/rust/rust-package.mk @@ -15,28 +15,22 @@ ifeq ($(origin RUST_INCLUDE_DIR),undefined) endif include $(RUST_INCLUDE_DIR)/rust-values.mk -# Support only a subset for now. -RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) +CARGO_PKG_VARS= \ + $(CARGO_PKG_CONFIG_VARS) \ + CC=$(HOSTCC_NOCACHE) \ + MAKEFLAGS="$(PKG_JOBS)" # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Build/Compile/Cargo - ( \ - cd $(PKG_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUST_CFLAGS)" \ - TARGET_CC=$(TARGET_CC_NOCACHE) \ - CC=$(HOSTCC_NOCACHE) \ - $(CARGO_VARS) \ - cargo install -v \ - --profile stripped \ - --target $(RUSTC_TARGET_ARCH) \ - $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ - --root $(PKG_INSTALL_DIR) \ - --path "$(if $(strip $(1)),$(strip $(1)),.)" \ - $(2) ; \ - ) + +$(CARGO_PKG_VARS) \ + cargo install -v \ + --profile $(CARGO_PKG_PROFILE) \ + $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ + --root $(PKG_INSTALL_DIR) \ + --path "$(PKG_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ + $(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \ + $(2) endef define RustBinPackage diff --git a/rust/rust-values.mk b/rust/rust-values.mk index aaa520d57..534aaa02a 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -2,25 +2,32 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins +# Clear environment variables which should be handled internally, +# as users might configure their own env on the host + +# CCache +unexport RUSTC_WRAPPER + # Rust Environmental Vars -CONFIG_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) -RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(CONFIG_HOST_SUFFIX) -CARGO_HOME:=$(STAGING_DIR)/host/cargo -CARGO_VARS:= +RUSTC_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) +RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(RUSTC_HOST_SUFFIX) +CARGO_HOME:=$(DL_DIR)/cargo ifeq ($(CONFIG_USE_MUSL),y) -# Force linking of the SSP library for musl -ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR - ifeq ($(strip $(PKG_SSP)),1) - RUSTC_LDFLAGS += -lssp_nonshared + # Force linking of the SSP library for musl + ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS+=-lssp_nonshared + endif + endif + ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS+=-lssp_nonshared + endif endif endif -ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG - ifeq ($(strip $(PKG_SSP)),1) - TARGET_CFLAGS += -lssp_nonshared - endif -endif -endif + +CARGO_RUSTFLAGS+=-Ctarget-feature=-crt-static $(RUSTC_LDFLAGS) ifeq ($(HOST_OS),Darwin) ifeq ($(HOST_ARCH),arm64) @@ -51,9 +58,47 @@ ifeq ($(ARCH),arm) ifeq ($(CONFIG_HAS_FPU),y) RUSTC_TARGET_ARCH:=$(subst musleabi,musleabihf,$(RUSTC_TARGET_ARCH)) + RUSTC_TARGET_ARCH:=$(subst gnueabi,gnueabihf,$(RUSTC_TARGET_ARCH)) endif endif -#ifeq ($(ARCH),aarch64) -# RUST_CFLAGS:=-mno-outline-atomics -#endif +ifeq ($(ARCH),aarch64) + RUSTC_CFLAGS:=-mno-outline-atomics +endif + +# Support only a subset for now. +RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) + +ifneq ($(CONFIG_RUST_SCCACHE),) + RUST_SCCACHE_DIR:=$(if $(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(TOPDIR)/.sccache) + + RUST_SCCACHE_VARS:= \ + CARGO_INCREMENTAL=0 \ + RUSTC_WRAPPER=sccache \ + SCCACHE_DIR=$(RUST_SCCACHE_DIR) +endif + +CARGO_HOST_CONFIG_VARS= \ + $(RUST_SCCACHE_VARS) \ + CARGO_HOME=$(CARGO_HOME) + +CARGO_HOST_PROFILE:=release + +CARGO_PKG_CONFIG_VARS= \ + $(RUST_SCCACHE_VARS) \ + CARGO_BUILD_TARGET=$(RUSTC_TARGET_ARCH) \ + CARGO_HOME=$(CARGO_HOME) \ + CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ + CARGO_PROFILE_RELEASE_DEBUG=false \ + CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=false \ + CARGO_PROFILE_RELEASE_LTO=true \ + CARGO_PROFILE_RELEASE_OPT_LEVEL=z \ + CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS=true \ + CARGO_PROFILE_RELEASE_PANIC=unwind \ + CARGO_PROFILE_RELEASE_RPATH=false \ + CARGO_TARGET_$(subst -,_,$(call toupper,$(RUSTC_TARGET_ARCH)))_LINKER=$(TARGET_CC_NOCACHE) \ + RUSTFLAGS="$(CARGO_RUSTFLAGS)" \ + TARGET_CC=$(TARGET_CC_NOCACHE) \ + TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUSTC_CFLAGS)" + +CARGO_PKG_PROFILE:=$(if $(CONFIG_DEBUG),dev,release) From 01701d30ae6abc9af21720a04ba2838457758107 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 19 Jan 2024 17:25:08 +0100 Subject: [PATCH 1350/2059] Add a help text in omr-tracker luci --- .../luci-static/resources/view/omr-tracker/network/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js index 501a60a4e..0f2506ff3 100644 --- a/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js +++ b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js @@ -66,7 +66,7 @@ return view.extend({ o.depends('family', 'ipv6'); o.rmempty = false; - o = s.option(form.ListValue, 'type', _('Tracking method')); + o = s.option(form.ListValue, 'type', _('Tracking method'),_('Always ping gateway, then test connection by ping, httping or dns. None mode only ping gateway.')); o.default = 'ping'; o.value('none'); o.value('ping'); From 1013739703dbe85b100ee1abec37525e05c876bc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 20 Jan 2024 11:14:24 +0100 Subject: [PATCH 1351/2059] Update Shadowsocks-Rust --- shadowsocks-rust/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile index 11fb4694b..410dfc772 100644 --- a/shadowsocks-rust/Makefile +++ b/shadowsocks-rust/Makefile @@ -7,12 +7,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=shadowsocks-rust -PKG_VERSION:=1.16.1 +PKG_VERSION:=1.17.1 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/shadowsocks/shadowsocks-rust/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=da4c6256247207b2579721046292bab1a2ac62301878c73ff778c168caa8a990 +PKG_HASH:=97a1c8ebf7fd19de94cd6d0dfee398667e1f4e131ec8a37ecb7c3191af7cc75e PKG_MAINTAINER:=Tianling Shen PKG_LICENSE:=MIT From aa3db5a62e69477a33b70d6bae1b4cb32575d222 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 20 Jan 2024 11:14:50 +0100 Subject: [PATCH 1352/2059] Downgrade Rust for kernel 5.4 --- rust/Config.in | 15 --- rust/Makefile | 58 +++++----- rust/files/cargo-config | 8 ++ .../0001-Update-xz2-and-use-it-static.patch | 14 +-- rust/patches/0002-Bumped-libc-version.patch | 35 ++++++ rust/patches/0002-rustc-bootstrap-cache.patch | 52 --------- .../0003-bump-libc-deps-to-0.2.146.patch | 100 ------------------ rust/rust-host-build.mk | 44 ++++---- rust/rust-package.mk | 30 +++--- rust/rust-values.mk | 79 +++----------- 10 files changed, 130 insertions(+), 305 deletions(-) delete mode 100644 rust/Config.in create mode 100644 rust/files/cargo-config create mode 100644 rust/patches/0002-Bumped-libc-version.patch delete mode 100644 rust/patches/0002-rustc-bootstrap-cache.patch delete mode 100644 rust/patches/0003-bump-libc-deps-to-0.2.146.patch diff --git a/rust/Config.in b/rust/Config.in deleted file mode 100644 index 62051af13..000000000 --- a/rust/Config.in +++ /dev/null @@ -1,15 +0,0 @@ -menu "Configuration options (for developers)" - -config RUST_SCCACHE - bool "Use sccache" - help - Shared compilation cache; see https://github.com/mozilla/sccache - -config RUST_SCCACHE_DIR - string "Set sccache directory" if RUST_SCCACHE - default "" - help - Store sccache in this directory. - If not set, uses './.sccache' - -endmenu diff --git a/rust/Makefile b/rust/Makefile index 46ee84e9d..60df0e5cd 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -3,26 +3,26 @@ # Copyright (C) 2023 Luca Barbato and Donald Hoskins include $(TOPDIR)/rules.mk +include ./rust-values.mk PKG_NAME:=rust -PKG_VERSION:=1.75.0 +PKG_VERSION:=1.71.1 PKG_RELEASE:=1 PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.gz PKG_SOURCE_URL:=https://static.rust-lang.org/dist/ -PKG_HASH:=5b739f45bc9d341e2d1c570d65d2375591e22c2d23ef5b8a37711a0386abc088 -HOST_BUILD_DIR:=$(BUILD_DIR)/host/rustc-$(PKG_VERSION)-src +PKG_HASH:=6fa90d50d1d529a75f6cc349784de57d7ec0ba2419b09bde7d335c25bd4e472e +HOST_BUILD_DIR:=$(BUILD_DIR)/host/rust-$(RUSTC_TARGET_ARCH)/rustc-$(PKG_VERSION)-src PKG_MAINTAINER:=Luca Barbato PKG_LICENSE:=Apache-2.0 MIT PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT +HOST_BUILD_DEPENDS:=python3/host PKG_HOST_ONLY:=1 -PKG_BUILD_FLAGS:=no-mips16 include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk -include ./rust-values.mk define Package/rust SECTION:=lang @@ -39,12 +39,8 @@ define Package/rust/description guarantee memory safety by using a borrow checker to validate references. endef -define Package/rust/config - source "$(SOURCE)/Config.in" -endef - # Rust-lang has an uninstall script -RUST_UNINSTALL:=$(STAGING_DIR)/host/lib/rustlib/uninstall.sh +RUST_UNINSTALL:=$(CARGO_HOME)/lib/rustlib/uninstall.sh # Target Flags TARGET_CONFIGURE_ARGS = \ @@ -53,24 +49,23 @@ TARGET_CONFIGURE_ARGS = \ --set=target.$(RUSTC_TARGET_ARCH).cxx=$(TARGET_CXX_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).linker=$(TARGET_CC_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).ranlib=$(TARGET_RANLIB) \ - --set=target.$(RUSTC_TARGET_ARCH).crt-static=false \ $(if $(CONFIG_USE_MUSL),--set=target.$(RUSTC_TARGET_ARCH).musl-root=$(TOOLCHAIN_DIR)) # CARGO_HOME is an environmental -HOST_CONFIGURE_VARS += CARGO_HOME="$(CARGO_HOME)" +HOST_CONFIGURE_OPTS += CARGO_HOME="$(CARGO_HOME)" # Rust Configuration Arguments HOST_CONFIGURE_ARGS = \ --build=$(RUSTC_HOST_ARCH) \ --target=$(RUSTC_TARGET_ARCH),$(RUSTC_HOST_ARCH) \ --host=$(RUSTC_HOST_ARCH) \ - --prefix=$(STAGING_DIR)/host \ - --bindir=$(STAGING_DIR)/host/bin \ - --libdir=$(STAGING_DIR)/host/lib \ - --sysconfdir=$(STAGING_DIR)/host/etc \ - --datadir=$(STAGING_DIR)/host/share \ - --mandir=$(STAGING_DIR)/host/man \ - --dist-compression-formats=gz \ + --prefix=$(CARGO_HOME) \ + --bindir=$(CARGO_HOME)/bin \ + --libdir=$(CARGO_HOME)/lib \ + --sysconfdir=$(CARGO_HOME)/etc \ + --datadir=$(CARGO_HOME)/share \ + --mandir=$(CARGO_HOME)/man \ + --dist-compression-formats=xz \ --enable-missing-tools \ --disable-sanitizers \ --release-channel=stable \ @@ -85,24 +80,23 @@ define Host/Uninstall endef define Host/Compile - $(RUST_SCCACHE_VARS) \ - CARGO_HOME=$(CARGO_HOME) \ - TARGET_CFLAGS="$(TARGET_CFLAGS)" \ - OPENWRT_RUSTC_BOOTSTRAP_CACHE=$(DL_DIR)/rustc \ - $(PYTHON) $(HOST_BUILD_DIR)/x.py \ - --build-dir $(HOST_BUILD_DIR)/build \ - --config $(HOST_BUILD_DIR)/config.toml \ - dist build-manifest cargo llvm-tools rustc rust-std rust-src + ( \ + cd $(HOST_BUILD_DIR) ; \ + $(PYTHON) x.py --config ./config.toml dist build-manifest cargo llvm-tools \ + rustc rust-std rust-src ; \ + ) endef define Host/Install ( \ cd $(HOST_BUILD_DIR)/build/dist ; \ - for targz in *.tar.gz; do \ - $(STAGING_DIR_HOST)/bin/libdeflate-gzip -dc "$$$$targz" | tar -xf - ; \ - done ; \ - find . -mindepth 2 -maxdepth 2 -type f -name install.sh \ - -execdir bash '{}' --prefix=$(STAGING_DIR)/host --disable-ldconfig \; ; \ + find -iname "*.xz" -exec tar -xJf {} \; ; \ + find ./* -type f -name install.sh -execdir sh {} --prefix=$(CARGO_HOME) --disable-ldconfig \; ; \ + \ + sed -e 's|@RUSTC_TARGET_ARCH@|$(RUSTC_TARGET_ARCH)|g' \ + -e 's|@TARGET_CC_NOCACHE@|$(TARGET_CC_NOCACHE)|g' \ + -e 's|@RUSTC_LDFLAGS@|$(RUSTC_LDFLAGS)|g' \ + $(CURDIR)/files/cargo-config > $(CARGO_HOME)/config ; \ ) endef diff --git a/rust/files/cargo-config b/rust/files/cargo-config new file mode 100644 index 000000000..2ed512931 --- /dev/null +++ b/rust/files/cargo-config @@ -0,0 +1,8 @@ +[target.@RUSTC_TARGET_ARCH@] +linker = "@TARGET_CC_NOCACHE@" +rustflags = ["-Ctarget-feature=-crt-static", "-Clink-args=@RUSTC_LDFLAGS@"] + +[profile.stripped] +inherits = "release" +opt-level = "s" +strip = true diff --git a/rust/patches/0001-Update-xz2-and-use-it-static.patch b/rust/patches/0001-Update-xz2-and-use-it-static.patch index 2360136a7..8d0c4b042 100644 --- a/rust/patches/0001-Update-xz2-and-use-it-static.patch +++ b/rust/patches/0001-Update-xz2-and-use-it-static.patch @@ -11,7 +11,7 @@ Subject: [PATCH] Update xz2 and use it static --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock -@@ -391,9 +391,9 @@ dependencies = [ +@@ -443,9 +443,9 @@ dependencies = [ [[package]] name = "lzma-sys" @@ -23,7 +23,7 @@ Subject: [PATCH] Update xz2 and use it static dependencies = [ "cc", "libc", -@@ -834,9 +834,9 @@ dependencies = [ +@@ -912,9 +912,9 @@ dependencies = [ [[package]] name = "xz2" @@ -37,12 +37,12 @@ Subject: [PATCH] Update xz2 and use it static ] --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml -@@ -57,7 +57,7 @@ tar = "0.4" - termcolor = "1.2.0" - toml = "0.5" - walkdir = "2" +@@ -50,7 +50,7 @@ toml = "0.5" + ignore = "0.4.10" + opener = "0.5" + once_cell = "1.7.2" -xz2 = "0.1" +xz2 = { version = "0.1", features = ["static"] } + walkdir = "2" # Dependencies needed by the build-metrics feature - sysinfo = { version = "0.26.0", optional = true } diff --git a/rust/patches/0002-Bumped-libc-version.patch b/rust/patches/0002-Bumped-libc-version.patch new file mode 100644 index 000000000..52c8a245c --- /dev/null +++ b/rust/patches/0002-Bumped-libc-version.patch @@ -0,0 +1,35 @@ +From 032857e7e403f654129c45dc7e6718a9ad49e377 Mon Sep 17 00:00:00 2001 +From: Nikolay Arhipov +Date: Tue, 6 Jun 2023 16:09:05 +0300 +Subject: [PATCH] Bumped libc version + +--- + Cargo.lock | 4 ++-- + library/std/Cargo.toml | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -1988,9 +1988,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0e + + [[package]] + name = "libc" +-version = "0.2.143" ++version = "0.2.146" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" ++checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" + dependencies = [ + "rustc-std-workspace-core", + ] +--- a/library/std/Cargo.toml ++++ b/library/std/Cargo.toml +@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = [ + panic_unwind = { path = "../panic_unwind", optional = true } + panic_abort = { path = "../panic_abort" } + core = { path = "../core" } +-libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } ++libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'] } + compiler_builtins = { version = "0.1.92" } + profiler_builtins = { path = "../profiler_builtins", optional = true } + unwind = { path = "../unwind" } diff --git a/rust/patches/0002-rustc-bootstrap-cache.patch b/rust/patches/0002-rustc-bootstrap-cache.patch deleted file mode 100644 index 959e23487..000000000 --- a/rust/patches/0002-rustc-bootstrap-cache.patch +++ /dev/null @@ -1,52 +0,0 @@ ---- a/src/bootstrap/bootstrap.py -+++ b/src/bootstrap/bootstrap.py -@@ -557,7 +557,7 @@ class RustBuild(object): - shutil.rmtree(bin_root) - - key = self.stage0_compiler.date -- cache_dst = os.path.join(self.build_dir, "cache") -+ cache_dst = os.getenv('OPENWRT_RUSTC_BOOTSTRAP_CACHE', os.path.join(self.build_dir, "cache")) - rustc_cache = os.path.join(cache_dst, key) - if not os.path.exists(rustc_cache): - os.makedirs(rustc_cache) ---- a/src/bootstrap/src/core/download.rs -+++ b/src/bootstrap/src/core/download.rs -@@ -208,7 +208,13 @@ impl Config { - Some(other) => panic!("unsupported protocol {other} in {url}"), - None => panic!("no protocol in {url}"), - } -- t!(std::fs::rename(&tempfile, dest_path)); -+ match std::fs::rename(&tempfile, dest_path) { -+ Ok(v) => v, -+ Err(_) => { -+ t!(std::fs::copy(&tempfile, dest_path)); -+ t!(std::fs::remove_file(&tempfile)); -+ } -+ } - } - - fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { -@@ -544,7 +550,10 @@ impl Config { - key: &str, - destination: &str, - ) { -- let cache_dst = self.out.join("cache"); -+ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { -+ Some(v) => PathBuf::from(v), -+ None => self.out.join("cache"), -+ }; - let cache_dir = cache_dst.join(key); - if !cache_dir.exists() { - t!(fs::create_dir_all(&cache_dir)); -@@ -671,7 +680,10 @@ download-rustc = false - let llvm_assertions = self.llvm_assertions; - - let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); -- let cache_dst = self.out.join("cache"); -+ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { -+ Some(v) => PathBuf::from(v), -+ None => self.out.join("cache"), -+ }; - let rustc_cache = cache_dst.join(cache_prefix); - if !rustc_cache.exists() { - t!(fs::create_dir_all(&rustc_cache)); diff --git a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch deleted file mode 100644 index bb131d23f..000000000 --- a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch +++ /dev/null @@ -1,100 +0,0 @@ -This patch bumps all libc dependencies and checksums to 0.2.147, which includes the fix for musl 1.2.4. - ---- a/vendor/addr2line-0.19.0/Cargo.lock -+++ b/vendor/addr2line-0.19.0/Cargo.lock -@@ -235,9 +235,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.126" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "memchr" ---- a/vendor/backtrace-0.3.67/Cargo.lock -+++ b/vendor/backtrace-0.3.67/Cargo.lock -@@ -64,9 +64,9 @@ checksum = "dec7af912d60cdbd3677c1af9352 - - [[package]] - name = "libc" --version = "0.2.138" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "libloading" ---- a/vendor/crossbeam-channel/Cargo.lock -+++ b/vendor/crossbeam-channel/Cargo.lock -@@ -50,9 +50,9 @@ dependencies = [ - - [[package]] - name = "libc" --version = "0.2.141" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "num_cpus" ---- a/vendor/elasticlunr-rs/Cargo.lock -+++ b/vendor/elasticlunr-rs/Cargo.lock -@@ -555,9 +555,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.140" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "lindera" ---- a/vendor/handlebars/Cargo.lock -+++ b/vendor/handlebars/Cargo.lock -@@ -550,9 +550,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.140" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "lock_api" ---- a/vendor/libffi/Cargo.lock -+++ b/vendor/libffi/Cargo.lock -@@ -10,9 +10,9 @@ checksum = "50d30906286121d95be3d479533b - - [[package]] - name = "libc" --version = "0.2.140" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "libffi" ---- a/vendor/tracing-tree/Cargo.lock -+++ b/vendor/tracing-tree/Cargo.lock -@@ -296,9 +296,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.141" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "linux-raw-sys" diff --git a/rust/rust-host-build.mk b/rust/rust-host-build.mk index e56292937..39cf1f23c 100644 --- a/rust/rust-host-build.mk +++ b/rust/rust-host-build.mk @@ -2,42 +2,36 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins -# Variables (all optional) to be set in package Makefiles: -# -# RUST_HOST_FEATURES - list of options, default empty -# -# Space or comma separated list of features to activate -# -# e.g. RUST_HOST_FEATURES:=enable-foo,with-bar - ifeq ($(origin RUST_INCLUDE_DIR),undefined) RUST_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) endif include $(RUST_INCLUDE_DIR)/rust-values.mk -CARGO_HOST_VARS= \ - $(CARGO_HOST_CONFIG_VARS) \ - CC=$(HOSTCC_NOCACHE) \ - MAKEFLAGS="$(HOST_JOBS)" - # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Host/Compile/Cargo - +$(CARGO_HOST_VARS) \ - cargo install -v \ - --profile $(CARGO_HOST_PROFILE) \ - $(if $(RUST_HOST_FEATURES),--features "$(RUST_HOST_FEATURES)") \ - --root $(HOST_INSTALL_DIR) \ - --path "$(HOST_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ - $(if $(filter --jobserver%,$(HOST_JOBS)),,-j1) \ - $(2) + ( \ + cd $(HOST_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + CC=$(HOSTCC_NOCACHE) \ + cargo install -v \ + --profile stripped \ + $(if $(RUST_PKG_FEATURES),--features "$(RUST_PKG_FEATURES)") \ + --root $(HOST_INSTALL_DIR) \ + --path "$(if $(strip $(1)),$(strip $(1)),.)" $(2) ; \ + ) endef define Host/Uninstall/Cargo - +$(CARGO_HOST_VARS) \ - cargo uninstall -v \ - --root $(HOST_INSTALL_DIR) \ - || true + ( \ + cd $(HOST_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + CC=$(HOSTCC_NOCACHE) \ + cargo uninstall -v \ + --root $(HOST_INSTALL_DIR) || true ; \ + ) endef define RustBinHostBuild diff --git a/rust/rust-package.mk b/rust/rust-package.mk index 24341d706..955b37c29 100644 --- a/rust/rust-package.mk +++ b/rust/rust-package.mk @@ -15,22 +15,28 @@ ifeq ($(origin RUST_INCLUDE_DIR),undefined) endif include $(RUST_INCLUDE_DIR)/rust-values.mk -CARGO_PKG_VARS= \ - $(CARGO_PKG_CONFIG_VARS) \ - CC=$(HOSTCC_NOCACHE) \ - MAKEFLAGS="$(PKG_JOBS)" +# Support only a subset for now. +RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Build/Compile/Cargo - +$(CARGO_PKG_VARS) \ - cargo install -v \ - --profile $(CARGO_PKG_PROFILE) \ - $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ - --root $(PKG_INSTALL_DIR) \ - --path "$(PKG_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ - $(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \ - $(2) + ( \ + cd $(PKG_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUST_CFLAGS)" \ + TARGET_CC=$(TARGET_CC_NOCACHE) \ + CC=$(HOSTCC_NOCACHE) \ + $(CARGO_VARS) \ + cargo install -v \ + --profile stripped \ + --target $(RUSTC_TARGET_ARCH) \ + $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ + --root $(PKG_INSTALL_DIR) \ + --path "$(if $(strip $(1)),$(strip $(1)),.)" \ + $(2) ; \ + ) endef define RustBinPackage diff --git a/rust/rust-values.mk b/rust/rust-values.mk index 534aaa02a..aaa520d57 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -2,32 +2,25 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins -# Clear environment variables which should be handled internally, -# as users might configure their own env on the host - -# CCache -unexport RUSTC_WRAPPER - # Rust Environmental Vars -RUSTC_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) -RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(RUSTC_HOST_SUFFIX) -CARGO_HOME:=$(DL_DIR)/cargo +CONFIG_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) +RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(CONFIG_HOST_SUFFIX) +CARGO_HOME:=$(STAGING_DIR)/host/cargo +CARGO_VARS:= ifeq ($(CONFIG_USE_MUSL),y) - # Force linking of the SSP library for musl - ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR - ifeq ($(strip $(PKG_SSP)),1) - RUSTC_LDFLAGS+=-lssp_nonshared - endif - endif - ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG - ifeq ($(strip $(PKG_SSP)),1) - RUSTC_LDFLAGS+=-lssp_nonshared - endif +# Force linking of the SSP library for musl +ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS += -lssp_nonshared endif endif - -CARGO_RUSTFLAGS+=-Ctarget-feature=-crt-static $(RUSTC_LDFLAGS) +ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG + ifeq ($(strip $(PKG_SSP)),1) + TARGET_CFLAGS += -lssp_nonshared + endif +endif +endif ifeq ($(HOST_OS),Darwin) ifeq ($(HOST_ARCH),arm64) @@ -58,47 +51,9 @@ ifeq ($(ARCH),arm) ifeq ($(CONFIG_HAS_FPU),y) RUSTC_TARGET_ARCH:=$(subst musleabi,musleabihf,$(RUSTC_TARGET_ARCH)) - RUSTC_TARGET_ARCH:=$(subst gnueabi,gnueabihf,$(RUSTC_TARGET_ARCH)) endif endif -ifeq ($(ARCH),aarch64) - RUSTC_CFLAGS:=-mno-outline-atomics -endif - -# Support only a subset for now. -RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) - -ifneq ($(CONFIG_RUST_SCCACHE),) - RUST_SCCACHE_DIR:=$(if $(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(TOPDIR)/.sccache) - - RUST_SCCACHE_VARS:= \ - CARGO_INCREMENTAL=0 \ - RUSTC_WRAPPER=sccache \ - SCCACHE_DIR=$(RUST_SCCACHE_DIR) -endif - -CARGO_HOST_CONFIG_VARS= \ - $(RUST_SCCACHE_VARS) \ - CARGO_HOME=$(CARGO_HOME) - -CARGO_HOST_PROFILE:=release - -CARGO_PKG_CONFIG_VARS= \ - $(RUST_SCCACHE_VARS) \ - CARGO_BUILD_TARGET=$(RUSTC_TARGET_ARCH) \ - CARGO_HOME=$(CARGO_HOME) \ - CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ - CARGO_PROFILE_RELEASE_DEBUG=false \ - CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=false \ - CARGO_PROFILE_RELEASE_LTO=true \ - CARGO_PROFILE_RELEASE_OPT_LEVEL=z \ - CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS=true \ - CARGO_PROFILE_RELEASE_PANIC=unwind \ - CARGO_PROFILE_RELEASE_RPATH=false \ - CARGO_TARGET_$(subst -,_,$(call toupper,$(RUSTC_TARGET_ARCH)))_LINKER=$(TARGET_CC_NOCACHE) \ - RUSTFLAGS="$(CARGO_RUSTFLAGS)" \ - TARGET_CC=$(TARGET_CC_NOCACHE) \ - TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUSTC_CFLAGS)" - -CARGO_PKG_PROFILE:=$(if $(CONFIG_DEBUG),dev,release) +#ifeq ($(ARCH),aarch64) +# RUST_CFLAGS:=-mno-outline-atomics +#endif From 2f3842962eb2056a07ab78e75511e60ffa1169ee Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 22 Jan 2024 08:42:22 +0100 Subject: [PATCH 1353/2059] Set download-ci-llvm false for Rust --- rust/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/Makefile b/rust/Makefile index 60df0e5cd..7ade00a9e 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -70,7 +70,7 @@ HOST_CONFIGURE_ARGS = \ --disable-sanitizers \ --release-channel=stable \ --enable-cargo-native-static \ - --set=llvm.download-ci-llvm=true \ + --set=llvm.download-ci-llvm=false \ $(TARGET_CONFIGURE_ARGS) define Host/Uninstall From ec6fd52cb504bc99114a667bcce3b433a8d88931 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 22 Jan 2024 16:39:06 +0100 Subject: [PATCH 1354/2059] Fix OMR-Tracker when device not available at launch --- omr-tracker/files/bin/omr-tracker | 10 +++++----- rust/Makefile | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index ea488022e..d8a9d4cec 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -264,11 +264,11 @@ while true; do serverip_ping=false [ -z "$OMR_TRACKER_DEVICE" ] && { network_get_device OMR_TRACKER_DEVICE $OMR_TRACKER_INTERFACE - [ -z "$OMR_TRACKER_DEVICE" ] && network_get_physdev OMR_TRACKER_DEVICE $1 - [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') - [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1_4" | jsonfilter -q -e '@["l3_device"]') - #[ -z "$OMR_TRACKER_DEVICE" ] && config_get OMR_TRACKER_DEVICE "$1" device - [ -n "$(echo $OMR_TRACKER_DEVICE | grep '@')" ] && OMR_TRACKER_DEVICE=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') + [ -z "$OMR_TRACKER_DEVICE" ] && network_get_physdev OMR_TRACKER_DEVICE $OMR_TRACKER_INTERFACE + [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["l3_device"]') + [ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" | jsonfilter -q -e '@["l3_device"]') + #[ -z "$OMR_TRACKER_DEVICE" ] && config_get OMR_TRACKER_DEVICE "$OMR_TRACKER_INTERFACE" device + [ -n "$(echo $OMR_TRACKER_DEVICE | grep '@')" ] && OMR_TRACKER_DEVICE=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') } if [ -n "$OMR_TRACKER_DEVICE" ] && [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then diff --git a/rust/Makefile b/rust/Makefile index 7ade00a9e..5e3b91df9 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -30,7 +30,7 @@ define Package/rust SUBMENU:=Rust TITLE:=Rust Programming Language Compiler URL:=https://www.rust-lang.org/ - DEPENDS:=$(RUST_ARCH_DEPENDS) + DEPENDS:=$(RUST_ARCH_DEPENDS) @LINUX_5_4 endef define Package/rust/description From ee12f0f05d3dd8e300e3a82e95bc2d05192a0034 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 22 Jan 2024 16:39:33 +0100 Subject: [PATCH 1355/2059] Fix IPv6 in route configuration --- mptcp/files/etc/init.d/mptcp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 6a4b6ee13..049176472 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -344,8 +344,8 @@ interface_multipath_settings() { # gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") #fi gateway6=$(echo $gateway6 | cut -d/ -f1 | tr -d "\n") - netmask6=$(ip -6 addr show dev $iface | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") - [ -n "$ip6addr" ] && network6=`ipcalc -n $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + [ -n "$ip6addr" ] && netmask6=$(ip -6 addr show dev $iface | grep $ip6addr | grep -m 1 inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + [ -n "$ip6addr" ] && [ -n "$netmask6" ] && network6=`/usr/sbin/ipcalc -n ${ip6addr}/${netmask6} | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null From 8e5a8f86942a4f37dcaec42aa12822350867635f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 14:55:38 +0100 Subject: [PATCH 1356/2059] Fix MPTCP reload on metric for IPv6 --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 4f5ca421d..c2966ce16 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -1061,7 +1061,7 @@ fi if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then metric="$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" - if [ -z "$metric" ] || [ -z "$(ip route show table $metric | grep $OMR_TRACKER_DEVICE)" ]; then + if [ -z "$metric" ] || ([ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -z "$(ip route show table $metric | grep $OMR_TRACKER_DEVICE)" ]) || ([ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -z "$(ip -6 route show table $metric | grep $OMR_TRACKER_DEVICE)" ]); then /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" fi fi From 086c13516f96dadacf982ac3b4e92789eca00d89 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 14:55:59 +0100 Subject: [PATCH 1357/2059] Fixes for IPv6 in OMR-Tracker --- omr-tracker/files/bin/omr-tracker | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index d8a9d4cec..6314b6c03 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -501,10 +501,10 @@ while true; do _ping "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE" "yes" statusb=$? elif [ "$OMR_TRACKER_TYPE" = "httping" ]; then - _httping "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP" "yes" + _httping "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP6" "yes" statusb=$? elif [ "$OMR_TRACKER_TYPE" = "dns" ]; then - _dns "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP" "yes" + _dns "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP6" "yes" statusb=$? fi ip -6 route del "$OMR_TRACKER_HOST6" via "$OMR_TRACKER_DEVICE_GATEWAY6" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP6" > /dev/null 2>&1 @@ -530,7 +530,7 @@ while true; do if [ "$serverip_ping" != false ] && [ "$OMR_TRACKER_STATUS" = "OK" ] && [ "$OMR_TRACKER_TYPE" != "httping" ] && [ "$OMR_TRACKER_SERVER_HTTP_TEST" = "1" ]; then serverip_ping=false config_load openmptcprouter - config_foreach _httping_server server $OMR_TRACKER_DEVICE_IP + config_foreach _httping_server server $OMR_TRACKER_DEVICE_IP6 if [ "$serverip_ping" = false ]; then OMR_TRACKER_STATUS_MSG="No access to server API" #OMR_TRACKER_STATUS="ERROR" @@ -554,7 +554,7 @@ while true; do sleep "${OMR_TRACKER_INTERVAL_TRIES:-1}" done fi - if [ -z "$OMR_TRACKER_DEVICE_IP" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ -z "$OMR_TRACKER_DEVICE_IP6" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + if [ "$OMR_TRACKER_STATUS" = "ERROR" ] && ([ -z "$OMR_TRACKER_DEVICE_IP" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ -z "$OMR_TRACKER_DEVICE_IP6" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]); then [ -z "$OMR_TRACKER_STATUS_MSG" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_INTERFACE may have ip issues" [ -z "$OMR_TRACKER_DEVICE_IP" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4" [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4 gateway" @@ -577,9 +577,9 @@ while true; do fi if [ "$OMR_TRACKER_LIST_HOSTS6" != "" ]; then if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then - OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS6)" + OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP6 error ($OMR_TRACKER_LIST_HOSTS6)" else - OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG and $OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS6)" + OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG and $OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP6 error ($OMR_TRACKER_LIST_HOSTS6)" fi fi if [ "$OMR_TRACKER_CHECK_QUALITY" = "1" ]; then From fb3cd8be2a39de8cd603a9bc48164a3f3093bdbd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 16:21:48 +0100 Subject: [PATCH 1358/2059] Fix on OMR-DSCP when importing previous config --- omr-dscp/files/etc/init.d/omr-dscp-nft | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/omr-dscp/files/etc/init.d/omr-dscp-nft b/omr-dscp/files/etc/init.d/omr-dscp-nft index 19aa9d589..b1da1b3c7 100755 --- a/omr-dscp/files/etc/init.d/omr-dscp-nft +++ b/omr-dscp/files/etc/init.d/omr-dscp-nft @@ -130,6 +130,9 @@ _add_fwmark_chain() { done } +_remove_old_ipset_dnsmasq() { + [ -n "$(uci -q get dhcp.${1}.name | grep omr)" ] && uci -q delete dhcp.$1 +} _remove_ipset_dnsmasq() { [ -n "$(echo $1 | grep omr_dscp)" ] && uci -q delete dhcp.$1 } @@ -151,6 +154,7 @@ _cleanup() { uci -q del dhcp.@dnsmasq[0].ipset config_load dhcp config_foreach _remove_ipset_dnsmasq + config_foreach _remove_old_ipset_dnsmasq config_load firewall config_foreach _remove_rules uci -q commit dhcp From 530d89c0c11c5169189034e1e389c9b0deb74f71 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 16:23:08 +0100 Subject: [PATCH 1359/2059] Fix retrieve IPv6 in some case for OMR-Tracker --- omr-tracker/files/bin/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index 6314b6c03..cc0bedf9f 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -323,7 +323,7 @@ while true; do if ([ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ] || [ -z "$OMR_TRACKER_IPV6" ]) && ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]); then #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then - OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1) + OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" scope global | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1) #fi if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then OMR_TRACKER_DEVICE_GATEWAY6=$(uci -q get "network.$OMR_TRACKER_INTERFACE.ip6gw") From 8bb06c763b02e2773c35f13318b12e9d971ab77c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 16:23:34 +0100 Subject: [PATCH 1360/2059] Only add IP in global scope in multipath --- mptcp/files/usr/bin/multipath | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 1b872182c..0e3d230ca 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -145,8 +145,11 @@ else ID=$(echo "${endpoint}" | sort | grep "dev $DEVICE " | awk '{print $3}') IFF=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') - [ -f /usr/bin/jsonfilter ] && IP=$(ip -j a show $DEVICE | jsonfilter -e '@[0].addr_info[*].local') - [ -f /usr/bin/jq ] && IP=$(ip -j a show $DEVICE | jq -r '.[0].addr_info[].local') + if [ -f /usr/bin/jsonfilter ]; then + IP=$(ip -j a show $DEVICE scope global | jsonfilter -e '@[0].addr_info[*].local') + elif [ -f /usr/bin/jq ]; then + IP=$(ip -j a show $DEVICE scope global | jq -r '.[0].addr_info[].local') + fi [ -z "$ID" ] && [ -n "$IP" ] && ID=$(echo "${endpoint}" show | grep "$IP " | awk '{print $3}') RMID=$(echo "${endpoint}" | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null From 23556274f03da6c6a97ea1d22f7b6497a5877c6b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 18:00:31 +0100 Subject: [PATCH 1361/2059] Add option to restrict or not to LAN fw zone in interface, disabled by default now --- .../luasrc/controller/openmptcprouter.lua | 4 ++++ .../luasrc/view/openmptcprouter/settings.htm | 10 ++++++++++ .../files/usr/share/omr/schedule.d/010-services | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 5f7b1487a..b6dc76b0f 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1303,6 +1303,10 @@ function settings_add() local externalcheck = luci.http.formvalue("externalcheck") or "1" ucic:set("openmptcprouter","settings","external_check",externalcheck) + -- Enable/disable restrict proxy to LAN + local restricttolan = luci.http.formvalue("restricttolan") or "0" + ucic:set("openmptcprouter","settings","restrict_to_lan",restricttolan) + -- Enable/disable debug local debug = luci.http.formvalue("debug") or "0" ucic:set("openmptcprouter","settings","debug",debug) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index 1de7df32e..af62dca9f 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -331,6 +331,16 @@ +
    + +
    + checked<% end %>> +
    +
    + <%:Authorize access to proxy only from LAN firewall zone%> +
    +
    +
    diff --git a/omr-schedule/files/usr/share/omr/schedule.d/010-services b/omr-schedule/files/usr/share/omr/schedule.d/010-services index ef220bfcd..44e82fe8b 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/010-services +++ b/omr-schedule/files/usr/share/omr/schedule.d/010-services @@ -153,7 +153,7 @@ set_lan_ips() { } config_load network config_foreach restart_omrtracker interface -config_foreach set_lan_ips interface +[ "$(uci -q get openmptcprouter.settings.restrict_to_lan)" = "1" ] && config_foreach set_lan_ips interface uci -q commit shadowsocks-libev.ss_rules uci -q commit shadowsocks-rust.ss_rules multipath_fix() { From e9108a74e6d6528005e62aed27aa74fb8f8644a2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 20:04:02 +0100 Subject: [PATCH 1362/2059] Add a log when MPTCP reload due to incorrect routes --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 1 + 1 file changed, 1 insertion(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index c2966ce16..de4a89c71 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -1062,6 +1062,7 @@ fi if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then metric="$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" if [ -z "$metric" ] || ([ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -z "$(ip route show table $metric | grep $OMR_TRACKER_DEVICE)" ]) || ([ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -z "$(ip -6 route show table $metric | grep $OMR_TRACKER_DEVICE)" ]); then + _log "Routes not correctly set for $OMR_TRACKER_DEVICE (table $metric)" /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" fi fi From 64d3ac4addc7dc1385d89f202b5c90b4db0171ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 20:05:03 +0100 Subject: [PATCH 1363/2059] Simplify code for IPv6 on OMR-Tracker --- omr-tracker/files/bin/omr-tracker | 10 ++++------ omr-tracker/files/etc/init.d/omr-tracker | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index cc0bedf9f..ff1e058ed 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -320,7 +320,7 @@ while true; do OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | awk '/via/ {print $3;exit}' | tr -d "\n") fi fi - if ([ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ] || [ -z "$OMR_TRACKER_IPV6" ]) && ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]); then + if ([ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ]) && ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]); then #OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}') #if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" scope global | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1) @@ -450,7 +450,7 @@ while true; do done fi #if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then - if ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]) && [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then # setup loop variable if [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ]; then tries="$OMR_TRACKER_TRIES" @@ -558,10 +558,8 @@ while true; do [ -z "$OMR_TRACKER_STATUS_MSG" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_INTERFACE may have ip issues" [ -z "$OMR_TRACKER_DEVICE_IP" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4" [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4 gateway" - if ([ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ] || [ -z "$OMR_TRACKER_IPV6" ]) && ([ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]); then - [ -z "$OMR_TRACKER_DEVICE_IP6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6" - [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6 gateway" - fi + [ -z "$OMR_TRACKER_DEVICE_IP6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6" + [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6 gateway" fi else OMR_TRACKER_STATUS_MSG="link down" diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 252493310..7614ed62c 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -110,6 +110,7 @@ _launch_tracker() { [ -z "${tries}" ] && tries=5 [ -z "${reliability}" ] && reliability=1 [ -z "${tries_up}" ] && tries_up=${tries} + [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "1" ] && ipv6="0" #[ -z "${failure_interval}" ] && failure_interval=5 procd_open_instance From d0d987cc20ae74e1884817c8d30c3cadbfaa3a65 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 20:06:11 +0100 Subject: [PATCH 1364/2059] Fix bug on IPv6 gateway display in status page and some commands in API --- .../files/usr/libexec/rpcd/openmptcprouter | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index ca526f957..e0798e6f5 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -328,6 +328,7 @@ function server_settings(server,server_ip,openmptcprouter_vps_key) ucic:save("openmptcprouter") if ucic:get("openmptcprouter",server,"master") == "1" then ucic:set("shadowsocks-libev","sss0","server",server_ip) + ucic:set("shadowsocks-rust","sss0","server",server_ip) ucic:set("glorytun","vpn","host",server_ip) ucic:set("dsvpn","vpn","host",server_ip) ucic:set("mlvpn","general","host",server_ip) @@ -357,6 +358,8 @@ function server_settings(server,server_ip,openmptcprouter_vps_key) ucic:commit("glorytun") ucic:save("shadowsocks-libev") ucic:commit("shadowsocks-libev") + ucic:save("shadowsocks-rust") + ucic:commit("shadowsocks-rust") end end @@ -560,6 +563,20 @@ function update_vps() local vpsgettoken = sys.exec("/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null") end +function get_mptcp_config(interface) + return ucic:get("network",interface,"multipath") +end + +function set_mptcp_config(interface,state) + ucic:set("network",interface,"multipath",state) + ucic:save("network") + ucic:commit("network") + ucic:set("openmptcprouter",interface,"multipath",state) + ucic:save("openmptcprouter") + ucic:commit("openmptcprouter") +end + + function get_rootfs() local rootfs = {} rootfs['format'] = luci.util.trim(sys.exec("mount | awk 'NR==1{print $5}'")) @@ -1364,7 +1381,7 @@ function interfaces_status() end end if ifname ~= nil and not (ifname:match("^tun.*") or interface:match("^ovpn.*") or interface:match("^wg.*")) then - if ipv6 == "1" or ipv6 == "auto" and gateway6 == ""then + if (ipv6 == "1" or ipv6 == "auto") and gateway6 == "" then gateway6 = ut.trim(sys.exec("ip -6 r list dev " .. ifname .. " | grep via | grep -v default | grep -v metric | awk '{print $1}' | tr -d '\n'")) end end @@ -2326,6 +2343,18 @@ local methods = { set_openvpn(args.key) end }, + getmptcpconfig = { + args = { interface = "" }, + call = function(args) + get_mptcp_config(args.interface) + end + }, + setmptcpconfig = { + args = { interface = "", state = "" }, + call = function(args) + set_mptcp_config(args.interface,args.state) + end + }, } From e79804444fa12b8dfbbbea21f5a35d4d0356db66 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 20:21:15 +0100 Subject: [PATCH 1365/2059] Fix check table for IPv6 in omr-tracker scripts --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index de4a89c71..ff6033bbf 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -1061,7 +1061,7 @@ fi if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then metric="$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" - if [ -z "$metric" ] || ([ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -z "$(ip route show table $metric | grep $OMR_TRACKER_DEVICE)" ]) || ([ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -z "$(ip -6 route show table $metric | grep $OMR_TRACKER_DEVICE)" ]); then + if [ -z "$metric" ] || ([ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -z "$(ip route show table $metric | grep $OMR_TRACKER_DEVICE)" ]) || ([ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -z "$(ip -6 route show table 6${metric} | grep $OMR_TRACKER_DEVICE)" ]); then _log "Routes not correctly set for $OMR_TRACKER_DEVICE (table $metric)" /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" fi From ae3c2fe47beeef55e226638812ed3e77cfb3e6e1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 23 Jan 2024 20:21:42 +0100 Subject: [PATCH 1366/2059] Stop/Start multipath after route set --- mptcp/files/etc/init.d/mptcp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 049176472..360d757cb 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -406,6 +406,7 @@ interface_multipath_settings() { fi if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then + multipath "$iface" "off" if ([ "$mode" = "master" ] || [ "$mode" = "on" ]) && [ -z "$(multipath $iface | grep default)" ]; then logger -t "MPTCP" "Set $iface to $mode" multipath "$iface" "on" @@ -511,7 +512,7 @@ start_service() { local id count intfmaster . /lib/functions.sh . /lib/functions/network.sh - [ -n "$intf" ] && multipath "${intf}" off 2>&1 >/dev/null + #[ -n "$intf" ] && multipath "${intf}" off 2>&1 >/dev/null global_multipath_settings [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep '3-model-b')" ] && [ "$(ip link show eth0 | grep UP)" = "" ] && { From 67dc34ba251d53d589672204fa50b13cc20a995b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 09:55:06 +0100 Subject: [PATCH 1367/2059] Add more log on mptcp reload due to metrics --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index ff6033bbf..9786041c3 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -1062,7 +1062,7 @@ fi if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then metric="$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" if [ -z "$metric" ] || ([ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -z "$(ip route show table $metric | grep $OMR_TRACKER_DEVICE)" ]) || ([ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -z "$(ip -6 route show table 6${metric} | grep $OMR_TRACKER_DEVICE)" ]); then - _log "Routes not correctly set for $OMR_TRACKER_DEVICE (table $metric)" + _log "Routes not correctly set for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE table $metric) with IPs $OMR_TRACKER_DEVICE_IP $OMR_TRACKER_DEVICE_IP6" /etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" fi fi From 612607ec1e61804e1df3a86075a76abec368bd22 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 09:55:39 +0100 Subject: [PATCH 1368/2059] Resolve server IP in API --- openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index e0798e6f5..35948e9e6 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -889,7 +889,7 @@ function interfaces_status() local master = uci:get("openmptcprouter",s[".name"],"master") or "1" local current = uci:get("openmptcprouter",s[".name"],"current") or "0" for key, value in pairs(serverips) do - serverip = value + serverip = sys.exec('resolveip ' .. value .. ' | head -n 1') if serverip ~= "" and (current == "1" or mArray.openmptcprouter["wan_addr"] == serverip or mArray.openmptcprouter["wan_addr6"] == serverip) and mArray.openmptcprouter["vps_admin"] == false then mArray.openmptcprouter["vps_omr_version"] = uci:get("openmptcprouter", s[".name"], "omr_version") or "" mArray.openmptcprouter["vps_kernel"] = uci:get("openmptcprouter",s[".name"],"kernel") or "" From c5bacfc244bfe99259ee5004c54d5547e3adc8bd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 11:26:57 +0100 Subject: [PATCH 1369/2059] Fix Shadowsocks-libev nftables --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index 0abc4855d..97740176f 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -145,6 +145,20 @@ ss_rules_cb() { fi } +ss_redir_ports() { + port=$(uci -q get shadowsocks-libev.$1.local_port) + server=$(uci -q get shadowsocks-libev.$1.server) + disabled=$(uci -q get shadowsocks-libev.$1.disabled) + if [ "$disabled" != "1" ] && ([ "$server" = "$2" ] || [ "$2" = "" ]); then + if [ "$port" -lt "$min_ss_redir_ports" ]; then + min_ss_redir_ports=$port + fi + if [ "$port" -gt "$max_ss_redir_ports" ]; then + max_ss_redir_ports=$port + fi + fi +} + ss_rules_nft_gen() { local cfg="ss_rules" local cfgtype From aad8e632f1a19e44c317ea817ad0dd83fe31626a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 11:27:34 +0100 Subject: [PATCH 1370/2059] Fix find netmask via mptcp --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 360d757cb..8afcebff9 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -250,7 +250,7 @@ interface_multipath_settings() { network_get_subnet netmask $config [ -n "$netmask" ] && [ "$(echo $netmask | grep '/')" != "" ] && netmask="" [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep peer | awk '{print $4}' | cut -d/ -f2 | tr -d "\n") - [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep 'inet ' | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") [ -n "$ipaddr" ] && ipaddr=$(echo $ipaddr | cut -d/ -f1 | tr -d "\n") [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr/$netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr/$netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` From 9237ab003df46a80ebc5ab6e18f48db6db75886a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 14:01:33 +0100 Subject: [PATCH 1371/2059] Fix typo in MPTCP script and better awk usage --- mptcp/files/etc/init.d/mptcp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 8afcebff9..4342e2732 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -226,7 +226,7 @@ interface_multipath_settings() { [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr/$netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` elif [ "$proto" != "gre" ]; then network_get_ipaddr ipaddr $config - [ -z "$ipaddr" ] && ipaddr=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") + [ -z "$ipaddr" ] && ipaddr=$(ip -4 addr show dev $iface | awk '/inet / {print $2; exit}' | cut -d/ -f1 | tr -d "\n") network_get_gateway gateway $config true [ -z "$gateway" ] && gateway=$(ip -4 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") [ -z "$gateway" ] && gateway=$(uci -q get "network.$config.gateway") @@ -249,8 +249,8 @@ interface_multipath_settings() { fi network_get_subnet netmask $config [ -n "$netmask" ] && [ "$(echo $netmask | grep '/')" != "" ] && netmask="" - [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep peer | awk '{print $4}' | cut -d/ -f2 | tr -d "\n") - [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep 'inet ' | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | awk '/peer/ {print $4; exit}' | cut -d/ -f2 | tr -d "\n") + [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | awk '/inet / {print $2;exit}' | cut -d/ -f2 | tr -d "\n") [ -n "$ipaddr" ] && ipaddr=$(echo $ipaddr | cut -d/ -f1 | tr -d "\n") [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr/$netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr/$netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` @@ -331,9 +331,9 @@ interface_multipath_settings() { fi if [ -z "$ip6addr" ] || [ -z "$gateway6" ]; then [ -z "$ip6addr" ] && network_get_ipaddr6 ip6addr $config - [ -z "$ip6addr" ] && ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") + [ -z "$ip6addr" ] && ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | awk '/inet6/ {print $2; exit}' | cut -d/ -f1 | tr -d "\n") [ -z "$gateway6" ] && network_get_gateway6 gateway6 $config true - [ -z "$gateway6" ] && gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") + [ -z "$gateway6" ] && gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1; exit}' | tr -d "\n") [ -z "$gateway6" ] && gateway6=$(uci -q get "network.$config.ip6gw") [ -z "$gateway6" ] && gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") #if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then @@ -344,7 +344,7 @@ interface_multipath_settings() { # gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") #fi gateway6=$(echo $gateway6 | cut -d/ -f1 | tr -d "\n") - [ -n "$ip6addr" ] && netmask6=$(ip -6 addr show dev $iface | grep $ip6addr | grep -m 1 inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + [ -n "$ip6addr" ] && netmask6=$(ip -6 addr show dev $iface | grep $ip6addr | awk '/inet6/ {print $2; exit}' | cut -d/ -f2 | tr -d "\n") [ -n "$ip6addr" ] && [ -n "$netmask6" ] && network6=`/usr/sbin/ipcalc -n ${ip6addr}/${netmask6} | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then @@ -410,10 +410,10 @@ interface_multipath_settings() { if ([ "$mode" = "master" ] || [ "$mode" = "on" ]) && [ -z "$(multipath $iface | grep default)" ]; then logger -t "MPTCP" "Set $iface to $mode" multipath "$iface" "on" - elif [ "$mode" = "off" ] && [ -z "$(multipath $iface | grep deactivated)" ] + elif [ "$mode" = "off" ] && [ -z "$(multipath $iface | grep deactivated)" ]; then logger -t "MPTCP" "Set $iface to $mode" multipath "$iface" "$mode" - elif [ "$mode" = "backup" ] && [ -z "$(multipath $iface | grep backup)" ] + elif [ "$mode" = "backup" ] && [ -z "$(multipath $iface | grep backup)" ]; then logger -t "MPTCP" "Set $iface to $mode" multipath "$iface" "$mode" fi From 4f26897d1a672391be730f0bf920ad23e3abd47a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 15:30:38 +0100 Subject: [PATCH 1372/2059] Use -e on multipath binary --- mptcp/files/usr/bin/multipath | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 0e3d230ca..3735748b6 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -95,7 +95,7 @@ DEVICE="$1" TYPE="$2" #FLAG_PATH=`find /sys/devices/ -path "*/net/$DEVICE/flags"` -[ -d "/sys/class/net/$DEVICE/" ] || { +[ -e "/sys/class/net/$DEVICE/" ] || { #echo "Device '$DEVICE' can't found!" #echo "Use the hardware name like in ifconfig" exit 1 @@ -142,18 +142,18 @@ else } endpoint="$(ip mptcp endpoint show)" [ -z "$endpoint" ] && exit 0 - ID=$(echo "${endpoint}" | sort | grep "dev $DEVICE " | awk '{print $3}') - IFF=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') - #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') - if [ -f /usr/bin/jsonfilter ]; then + ID=$(echo "${endpoint}" | sort | grep "dev $DEVICE " | awk '{print $3}') + IFF=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') + #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') + if [ -f /usr/bin/jsonfilter ]; then IP=$(ip -j a show $DEVICE scope global | jsonfilter -e '@[0].addr_info[*].local') elif [ -f /usr/bin/jq ]; then IP=$(ip -j a show $DEVICE scope global | jq -r '.[0].addr_info[].local') fi - [ -z "$ID" ] && [ -n "$IP" ] && ID=$(echo "${endpoint}" show | grep "$IP " | awk '{print $3}') - RMID=$(echo "${endpoint}" | grep '::ffff' | awk '{ print $3 }') - [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null - case $TYPE in + [ -z "$ID" ] && [ -n "$IP" ] && ID=$(echo "${endpoint}" show | grep "$IP " | awk '{print $3}') + RMID=$(echo "${endpoint}" | grep '::ffff' | awk '{ print $3 }') + [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null + case $TYPE in "off") [ -n "$ID" ] && { for i in $ID; do From c68a5f0db89395802ee1055266aeeb00b6688e93 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 15:31:56 +0100 Subject: [PATCH 1373/2059] Add more check for IPv4/IPv6 in post tracking --- .../omr/post-tracking.d/001-post-tracking | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 9786041c3..e43a4618c 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -708,7 +708,7 @@ dns_flush() { # Get the current multipath status multipath_status="off" [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && multipath $OMR_TRACKER_DEVICE off 2>&1 >/dev/null -if [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then +if [ -e "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then case "$(multipath "$OMR_TRACKER_DEVICE")" in *default*) multipath_status="on" ;; *backup*) multipath_status="backup" ;; @@ -1102,10 +1102,10 @@ if [ "$multipath_config" = "master" ]; then ip -6 route flush cache 2>&1 >/dev/null fi #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then - if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && ([ "$(ip route show default | grep weight)" = "" ] || [ "$(ip -6 route show default | grep weight)" = "" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && (([ -n "$OMR_TRACKER_DEVICE_IP" ] && [ "$(ip route show default | grep weight)" = "" ]) || ([ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ "$(ip -6 route show default | grep weight)" = "" ])) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") - if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then + if [ -n "$omrvpn_intf" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then routesbalancing="" routesbalancingbackup="" nbintf=0 @@ -1141,7 +1141,7 @@ if [ "$multipath_config" = "master" ]; then # ip -6 route replace default scope global metric 999 $routesbalancingbackup6 2>&1 >/dev/null # } #} - elif [ -n "$omrvpn_intf" ] && [ "$(ip -6 route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then + elif [ -n "$omrvpn_intf" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ "$(ip -6 route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then routesbalancing6="" routesbalancingbackup6="" nbintf6=0 @@ -1161,16 +1161,16 @@ if [ "$multipath_config" = "master" ]; then } } fi - ip route flush cache 2>&1 >/dev/null - ip -6 route flush cache 2>&1 >/dev/null + #ip route flush cache 2>&1 >/dev/null + #ip -6 route flush cache 2>&1 >/dev/null fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE " ]; then ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE table 991337 $initcwrwnd 2>&1 >/dev/null - ip route flush cache 2>&1 >/dev/null + #ip route flush cache 2>&1 >/dev/null fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE " ]; then ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 991337 $initcwrwnd 2>&1 >/dev/null - ip -6 route flush cache 2>&1 >/dev/null + #ip -6 route flush cache 2>&1 >/dev/null fi if ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ]) || [ $(($(date +"%s") + $((10 + RANDOM % 31)) - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]; then [ "$(pgrep -f openmptcprouter-vps)" = "" ] && /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & @@ -1201,7 +1201,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; th config_foreach set_server_route6 server fi if [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then - ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 + ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric 6$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 ip -6 route flush cache 2>&1 >/dev/null fi fi From 56de8fc06def1ec854cc6317b8bb25f46ef4b412 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 15:32:32 +0100 Subject: [PATCH 1374/2059] Fix when there is multiple redir listener --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index 97740176f..f8121fe7c 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -202,8 +202,8 @@ ss_rules_nft_gen() { local tmp="/tmp/ssrules" json_init json_add_string o_remote_servers "$remote_servers" - json_add_int o_redir_tcp_port "$local_port_tcp" - json_add_int o_redir_udp_port "$local_port_udp" + json_add_string o_redir_tcp_port "$local_port_tcp" + json_add_string o_redir_udp_port "$local_port_udp" json_add_string o_ifnames "$ifnames" json_add_string o_local_default "$local_default" json_add_string o_src_bypass "$src_ips_bypass" From 7c40ecf71758700c80c3dfd4f4a31182d4ccac94 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 15:32:52 +0100 Subject: [PATCH 1375/2059] Add multiple redir listener in shadowsocks-rust --- .../files/shadowsocks-rust.init-nft | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index c5b77740e..7a48c152f 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -118,6 +118,20 @@ ss_rules_cb() { fi } +ss_redir_ports() { + port=$(uci -q get shadowsocks-rust.$1.local_port) + server=$(uci -q get shadowsocks-rust.$1.server) + disabled=$(uci -q get shadowsocks-rust.$1.disabled) + if [ "$disabled" != "1" ] && ([ "$server" = "$2" ] || [ "$2" = "" ]); then + if [ "$port" -lt "$min_ss_redir_ports" ]; then + min_ss_redir_ports=$port + fi + if [ "$port" -gt "$max_ss_redir_ports" ]; then + max_ss_redir_ports=$port + fi + fi +} + ss_rules_nft_gen() { local cfg="ss_rules" local cfgtype @@ -129,8 +143,26 @@ ss_rules_nft_gen() { eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)" validate_ss_rules_section "$cfg" || return 1 [ "$disabled" = 0 ] || return 2 - eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" - eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" + + if [ "$ss_rules_redir_tcp_$redir_tcp" = "all" ]; then + min_ss_redir_ports="65535" + max_ss_redir_ports="0" + config_load shadowsocks-rust + config_foreach ss_redir_ports ss_redir $cfgrulesserver + if [ "$min_ss_redir_ports" != "$max_ss_redir_ports" ]; then + all_ss_redir_ports=$min_ss_redir_ports-$max_ss_redir_ports + else + all_ss_redir_ports=$min_ss_redir_ports + fi + local_port_tcp="$all_ss_redir_ports" + if [ "$ss_rules_redir_udp_$redir_udp" = "all" ] || [ "$ss_rules_redir_udp_$redir_udp" = "hi1" ]; then + local_port_udp="$min_ss_redir_ports" + fi + else + eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" + eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" + fi + [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1 remote_servers="$(echo $ss_redir_servers \ | tr ' ' '\n' \ @@ -141,8 +173,8 @@ ss_rules_nft_gen() { local tmp="/tmp/ssrrules" json_init json_add_string o_remote_servers "$remote_servers" - json_add_int o_redir_tcp_port "$local_port_tcp" - json_add_int o_redir_udp_port "$local_port_udp" + json_add_string o_redir_tcp_port "$local_port_tcp" + json_add_string o_redir_udp_port "$local_port_udp" json_add_string o_ifnames "$ifnames" json_add_string o_local_default "$local_default" json_add_string o_src_bypass "$src_ips_bypass" @@ -326,8 +358,8 @@ validate_ss_redir_section() { validate_ss_rules_section() { "${2:-ss_validate}" ss_rules "$1" \ 'disabled:bool:0' \ - 'redir_tcp:uci("shadowsocks-rust", "@ss_redir")' \ - 'redir_udp:uci("shadowsocks-rust", "@ss_redir")' \ + 'redir_tcp:or(uci("shadowsocks-rust", "@ss_redir"),"all")' \ + 'redir_udp:or(uci("shadowsocks-rust", "@ss_redir"),"all")' \ 'src_ips_bypass:or(ipaddr,cidr)' \ 'src_ips_forward:or(ipaddr,cidr)' \ 'src_ips_checkdst:or(ipaddr,cidr)' \ From 398e81f0fed12ac990fb20076d1e0c1f2ad3f747 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 15:53:36 +0100 Subject: [PATCH 1376/2059] Fix multipath command --- mptcp/files/usr/bin/multipath | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/mptcp/files/usr/bin/multipath b/mptcp/files/usr/bin/multipath index 3735748b6..90f648a67 100755 --- a/mptcp/files/usr/bin/multipath +++ b/mptcp/files/usr/bin/multipath @@ -133,25 +133,28 @@ if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then else # Remove not needed if* interfaces in MPTCP endpoint="$(ip mptcp endpoint show)" - [ -z "$endpoint" ] && exit 0 - oldintfs=$(echo "${endpoint}" | grep "dev if" | awk '{ print $3 }') + [ -n "$endpoint" ] && oldintfs=$(echo "${endpoint}" | grep "dev if" | awk '{ print $3 }') [ -n "$oldintfs" ] && { for oldintf in $oldintfs; do ip mptcp endpoint delete id $oldintf 2>&1 >/dev/null done } endpoint="$(ip mptcp endpoint show)" - [ -z "$endpoint" ] && exit 0 - ID=$(echo "${endpoint}" | sort | grep "dev $DEVICE " | awk '{print $3}') - IFF=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4}') + if [ -n "$endpoint" ]; then + ID=$(echo "${endpoint}" | sort | grep "dev $DEVICE " | awk '{print $3}') + IFF=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4; exit}') + fi #IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') if [ -f /usr/bin/jsonfilter ]; then IP=$(ip -j a show $DEVICE scope global | jsonfilter -e '@[0].addr_info[*].local') elif [ -f /usr/bin/jq ]; then IP=$(ip -j a show $DEVICE scope global | jq -r '.[0].addr_info[].local') + else + echo "jsonfilter or jq are required" + exit 1 fi - [ -z "$ID" ] && [ -n "$IP" ] && ID=$(echo "${endpoint}" show | grep "$IP " | awk '{print $3}') - RMID=$(echo "${endpoint}" | grep '::ffff' | awk '{ print $3 }') + [ -z "$ID" ] && [ -n "$IP" ] && [ -n "$endpoint" ] && ID=$(echo "${endpoint}" show | grep "$IP " | awk '{print $3}') + [ -n "$endpoint" ] && RMID=$(echo "${endpoint}" | grep '::ffff' | awk '{ print $3 }') [ -n "$RMID" ] && ip mptcp endpoint delete id $RMID 2>&1 >/dev/null case $TYPE in "off") From f6584db4dc42467ae4dcb9851bd7e1a7cad525ad Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 20:08:20 +0100 Subject: [PATCH 1377/2059] Multiple Shadowsocks-Rust server IP management in wizard --- .../luasrc/controller/openmptcprouter.lua | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index b6dc76b0f..b38c1321f 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -257,6 +257,11 @@ function wizard_add() end end + -- Enable/disable IPv6 + local disableipv6 = luci.http.formvalue("enableipv6") or "1" + ucic:set("openmptcprouter","settings","disable_ipv6",disableipv6) + + -- Set interfaces settings local downloadmax = 0 local uploadmax = 0 @@ -393,6 +398,10 @@ function wizard_add() ucic:set("network",intf,"ip6addr",ip6addr:gsub("%s+", "")) ucic:set("network",intf,"ip6gw",ip6gw:gsub("%s+", "")) ucic:set("network",intf,"ipv6","1") + elseif proto ~= "static" and proto ~= "dhcp" and disableipv6 ~= "1" then + ucic:set("network",intf,"ip6addr","") + ucic:set("network",intf,"ip6gw","") + ucic:set("network",intf,"ipv6","1") else ucic:set("network",intf,"ip6addr","") ucic:set("network",intf,"ip6gw","") @@ -521,9 +530,6 @@ function wizard_add() ucic:save("network") ucic:commit("network") - -- Enable/disable IPv6 - local disableipv6 = luci.http.formvalue("enableipv6") or "1" - ucic:set("openmptcprouter","settings","disable_ipv6",disableipv6) --local ut = require "luci.util" --local result = ut.ubus("openmptcprouter", "set_ipv6_state", { disable_ipv6 = disableipv6 }) local ula = luci.http.formvalue("ula") or "" @@ -759,6 +765,7 @@ function wizard_add() ucic:set("openmptcprouter","settings","proxy",default_proxy) ucic:save("openmptcprouter") ucic:save("shadowsocks-libev") + ucic:save("shadowsocks-rust") ucic:save("v2ray") ucic:save("xray") @@ -770,6 +777,14 @@ function wizard_add() ucic:delete("openmptcprouter","omr","ss_" .. sectionname) end end) + ucic:foreach("shadowsocks-rust","server", function(s) + local sectionname = s[".name"] + if sectionname:match("^sss.*") then + ucic:delete("shadowsocks-rust",sectionname,"ip") + ucic:set("shadowsocks-rust",sectionname,"disabled","1") + ucic:delete("openmptcprouter","omr","ss_" .. sectionname) + end + end) local ss_servers_nginx = {} local ss_servers_ha = {} @@ -818,15 +833,21 @@ function wizard_add() if default_proxy == "shadowsocks" and serversnb > disablednb and ssip ~= "" then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end + ucic:set("shadowsocks-rust","sss" .. nbip,"server",ssip) + if default_proxy == "shadowsocks-rust" and serversnb > disablednb and ssip ~= "" then + ucic:set("shadowsocks-rust","sss" .. nbip,"disabled","0") + end nbip = nbip + 1 if disableipv6 == "1" and nbip > 0 then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","1") + ucic:set("shadowsocks-rust","sss" .. nbip,"disabled","1") break end end if nbip == 1 then --ucic:set("shadowsocks-libev","sss" .. nbip,"server",server_ip) ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","1") + ucic:set("shadowsocks-rust","sss" .. nbip,"disabled","1") end end k = k + 1 @@ -864,6 +885,10 @@ function wizard_add() if default_proxy == "shadowsocks" and serversnb > disablednb and ssip ~= "" then ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","0") end + ucic:set("shadowsocks-rust","sss" .. nbip,"server",ssip) + if default_proxy == "shadowsocks-rust" and serversnb > disablednb and ssip ~= "" then + ucic:set("shadowsocks-rust","sss" .. nbip,"disabled","0") + end nbip = nbip + 1 if disableipv6 == "1" and nbip > 0 then break @@ -872,6 +897,7 @@ function wizard_add() if nbip == 1 then -- ucic:set("shadowsocks-libev","sss" .. nbip,"server",server_ip) ucic:set("shadowsocks-libev","sss" .. nbip,"disabled","1") + ucic:set("shadowsocks-rust","sss" .. nbip,"disabled","1") end end end @@ -894,6 +920,7 @@ function wizard_add() ucic:save("glorytun-udp") --ucic:commit("glorytun") ucic:save("shadowsocks-libev") + ucic:save("shadowsocks-rust") --ucic:commit("shadowsocks-libev") @@ -1059,6 +1086,8 @@ function wizard_add() ucic:commit("xray") ucic:save("shadowsocks-libev") ucic:commit("shadowsocks-libev") + ucic:save("shadowsocks-rust") + ucic:commit("shadowsocks-rust") -- Set Glorytun settings @@ -1218,6 +1247,7 @@ function wizard_add() -- luci.sys.call("sleep 2") --end luci.sys.call("/etc/init.d/shadowsocks-libev restart >/dev/null 2>/dev/null") + luci.sys.call("/etc/init.d/shadowsocks-rust restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/glorytun restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/mlvpn restart >/dev/null 2>/dev/null") From 52380b373bac1bfddcd4bcd4f3c0f699d6c85ff1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 20:08:41 +0100 Subject: [PATCH 1378/2059] Fix OMR-Bypass issue with IPv6 --- omr-bypass/files/etc/init.d/omr-bypass-nft | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index a7ebdb39f..a6a8a01ec 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -584,7 +584,7 @@ _intf_rule() { uci batch <<-EOF set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" - set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_${ipv46}" set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' @@ -598,7 +598,7 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.mark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.name="omr_dst_bypass_${intf}_srcip" - set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_${ipv46}" set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' From 5a3150844b39077ff9cad592c4f076b319d37643 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 20:10:29 +0100 Subject: [PATCH 1379/2059] Multiple local test management for Shadowsocks-Rust --- omr-tracker/files/etc/init.d/omr-tracker | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 7614ed62c..73410f488 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -212,7 +212,7 @@ _initialize_shadowsocks_tracker() { set shadowsocks-libev.tracker_${server}=ss_local set shadowsocks-libev.tracker_${server}.server=$server set shadowsocks-libev.tracker_${server}.local_address="127.0.0.1" - set shadowsocks-libev.tracker_${server}.local_port=1111 + set shadowsocks-libev.tracker_${server}.local_port=${count} set shadowsocks-libev.tracker_${server}.mode=tcp_and_udp set shadowsocks-libev.tracker_${server}.timeout=600 set shadowsocks-libev.tracker_${server}.fast_open=1 @@ -233,6 +233,7 @@ _initialize_shadowsocks_tracker() { # EOF # /etc/init.d/shadowsocks-libev restart # } + count=$((count+1)) } _initialize_shadowsocks_rust_tracker() { @@ -252,7 +253,7 @@ _initialize_shadowsocks_rust_tracker() { set shadowsocks-rust.tracker_${server}=ss_local set shadowsocks-rust.tracker_${server}.server=$server set shadowsocks-rust.tracker_${server}.local_address="127.0.0.1" - set shadowsocks-rust.tracker_${server}.local_port=1111 + set shadowsocks-rust.tracker_${server}.local_port=${count) set shadowsocks-rust.tracker_${server}.mode=tcp_and_udp set shadowsocks-rust.tracker_${server}.timeout=600 set shadowsocks-rust.tracker_${server}.fast_open=0 @@ -265,6 +266,7 @@ _initialize_shadowsocks_rust_tracker() { logger -t "omr-tracker" "Restart ShadowSocks" /etc/init.d/shadowsocks-rust restart } + count=$((count+1)) } _launch_shadowsocks_tracker() { @@ -406,9 +408,11 @@ start_service() { local ss_enable=0 local ss_rust_enable=0 logger -t "omr-tracker" "Launching..." + count=1111 config_load shadowsocks-libev config_foreach _initialize_shadowsocks_tracker server + count=1111 config_load shadowsocks-rust config_foreach _initialize_shadowsocks_rust_tracker server From 546c06c785302ab106e8cba3e119cb770c446906 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 20:11:18 +0100 Subject: [PATCH 1380/2059] Check WAN to server test using multiple IPs and fix display bug --- .../files/usr/libexec/rpcd/openmptcprouter | 62 ++++++++++++------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index 35948e9e6..b680dce20 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -889,7 +889,7 @@ function interfaces_status() local master = uci:get("openmptcprouter",s[".name"],"master") or "1" local current = uci:get("openmptcprouter",s[".name"],"current") or "0" for key, value in pairs(serverips) do - serverip = sys.exec('resolveip ' .. value .. ' | head -n 1') + serverip = sys.exec('resolveip ' .. value .. ' | head -n 1 | tr -d "\n"') if serverip ~= "" and (current == "1" or mArray.openmptcprouter["wan_addr"] == serverip or mArray.openmptcprouter["wan_addr6"] == serverip) and mArray.openmptcprouter["vps_admin"] == false then mArray.openmptcprouter["vps_omr_version"] = uci:get("openmptcprouter", s[".name"], "omr_version") or "" mArray.openmptcprouter["vps_kernel"] = uci:get("openmptcprouter",s[".name"],"kernel") or "" @@ -904,8 +904,7 @@ function interfaces_status() local vpsinfo_json = "" if mArray.openmptcprouter["service_addr_ip"] ~= "" then vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://' .. serverip .. ':' .. adminport .. '/status') - end - if mArray.openmptcprouter["service_addr_ip6"] ~= "" then + elseif mArray.openmptcprouter["service_addr_ip6"] ~= "" then vpsinfo_json = sys.exec('curl --max-time ' .. timeout .. ' -s -k -H "Authorization: Bearer ' .. token .. '" https://[' .. serverip .. ']:' .. adminport .. '/status') end if vpsinfo_json ~= "" and vpsinfo_json ~= nil then @@ -991,7 +990,7 @@ function interfaces_status() mArray.openmptcprouter["vps_admin_error_msg"] = "No result" uci:set("openmptcprouter",s[".name"],"token_error","1") mArray.openmptcprouter["vps_admin_error"] = true - uci:delete("openmptcprouter",s[".name"],"token") + --uci:delete("openmptcprouter",s[".name"],"token") uci:save("openmptcprouter",s[".name"]) uci:commit("openmptcprouter",s[".name"]) end @@ -1477,26 +1476,41 @@ function interfaces_status() local server_ping = "" local server_http = "" --if connectivity ~= "ERROR" and ifname ~= "" and gateway ~= "" and gw_ping ~= "DOWN" and ifname ~= nil and mArray.openmptcprouter["service_addr"] ~= "" and ipaddr ~= "" then - if ifname ~= "" and (gateway ~= "" or gateway6 ~= "") and ifname ~= nil and mArray.openmptcprouter["service_addr"] ~= "" and (ipaddr ~= "" or ip6addr ~= "") and connectivity ~= "ERROR" then - local serverip = mArray.openmptcprouter["service_addr"] - if serverip == "127.0.0.1" then - serverip = mArray.openmptcprouter["wan_addr"] - end - if serverip ~= "" and uci:get("openmptcprouter", "settings", "disableserverping") ~= "1" then - local server_ping_test = sys.exec("ping -B -w 1 -c 1 -I " .. ifname .. " " .. serverip) - local server_ping_result = ut.trim(sys.exec("echo '" .. server_ping_test .. "' | grep '100% packet loss'")) - if server_ping_result ~= "" then - server_ping = "DOWN" - if connectivity == "OK" then - connectivity = "WARNING" - end - else - mArray.openmptcprouter["vps_status"] = "UP" - server_ping = "UP" - latency = ut.trim(sys.exec("echo '" .. server_ping_test .. "' | cut -d '/' -s -f5 | cut -d '.' -f1")) - end - end - + if ifname ~= "" and (gateway ~= "" or gateway6 ~= "") and ifname ~= nil and (ipaddr ~= "" or ip6addr ~= "") and connectivity ~= "ERROR" then + if uci:get("openmptcprouter", "settings", "disableserverping") ~= "1" then + uci:foreach("openmptcprouter", "server", function(s) + local serverips = uci:get("openmptcprouter",s[".name"],"ip") or { "" } + local master = uci:get("openmptcprouter",s[".name"],"master") or "1" + local current = uci:get("openmptcprouter",s[".name"],"current") or "0" + if current == "1" then + for key, value in pairs(serverips) do + local serverip = mArray.openmptcprouter["service_addr"] + if serverip == "127.0.0.1" then + serverip = mArray.openmptcprouter["wan_addr"] + end + if gateway ~= "" then + serverip = sys.exec('resolveip -4 ' .. value .. ' | head -n 1') + elseif gateway6 ~= "" then + serverip = sys.exec('resolveip -6 ' .. value .. ' | head -n 1') + end + if serverip ~= "" then + local server_ping_test = sys.exec("ping -B -w 1 -c 1 -I " .. ifname .. " " .. serverip) + local server_ping_result = ut.trim(sys.exec("echo '" .. server_ping_test .. "' | grep '100% packet loss'")) + if server_ping_result ~= "" then + server_ping = "DOWN" + if connectivity == "OK" then + connectivity = "WARNING" + end + else + mArray.openmptcprouter["vps_status"] = "UP" + server_ping = "UP" + latency = ut.trim(sys.exec("echo '" .. server_ping_test .. "' | cut -d '/' -s -f5 | cut -d '.' -f1")) + end + end + end + end + end) + end if adminport == "" then adminport = "65500" end From 5b5ed0acfe65a1852c03ad291fb2e4b103b81672 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 20:12:39 +0100 Subject: [PATCH 1381/2059] Update Shadowsocks-Rust default config with another server --- .../files/shadowsocks-rust.config | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/shadowsocks-rust/files/shadowsocks-rust.config b/shadowsocks-rust/files/shadowsocks-rust.config index 8dfa5197a..f488f9b60 100644 --- a/shadowsocks-rust/files/shadowsocks-rust.config +++ b/shadowsocks-rust/files/shadowsocks-rust.config @@ -12,6 +12,20 @@ config ss_redir hi1 option ipv6_first 1 option no_delay 0 +config ss_redir hi2 + option server 'sss1' + option local_address '::' + option local_port '1100' + option mode 'tcp_and_udp' + option timeout '1000' + option fast_open 0 + option verbose 0 + option syslog 1 + option reuse_port 0 + option mptcp 1 + option ipv6_first 1 + option no_delay 0 + config ss_rules 'ss_rules' option disabled 0 option redir_tcp 'hi1' @@ -28,6 +42,14 @@ config server 'sss0' option method '2022-blake3-aes-256-gcm' option obfs 0 +config server 'sss1' + option disabled 1 + option server '192.168.1.3' + option server_port '65280' + option password '' + option method '2022-blake3-aes-256-gcm' + option obfs 0 + config ss_tunnel 'dns' option disabled 1 option mode 'tcp_and_udp' From 24903788d1f16c1182caa4e55211b95bb6800948 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 24 Jan 2024 20:12:59 +0100 Subject: [PATCH 1382/2059] Update anonymous config script --- luci-app-openmptcprouter/root/bin/anonymous_config.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/luci-app-openmptcprouter/root/bin/anonymous_config.sh b/luci-app-openmptcprouter/root/bin/anonymous_config.sh index 65c0813a2..696e5c750 100755 --- a/luci-app-openmptcprouter/root/bin/anonymous_config.sh +++ b/luci-app-openmptcprouter/root/bin/anonymous_config.sh @@ -14,10 +14,15 @@ uci show | \ -e "/openvpn\.omr\.remote=/s/......$/xxxxxx'/" \ -e "/shadowsocks-libev\.sss.*\.server=/s/......$/xxxxxx'/" \ -e "/shadowsocks-libev\.sss.*\.key=/s/......$/xxxxxx'/" \ + -e "/shadowsocks-rust\.sss.*\.server=/s/......$/xxxxxx'/" \ + -e "/shadowsocks-rust\.sss.*\.key=/s/......$/xxxxxx'/" \ -e "/external_ip=/s/......$/xxxxxx'/" \ -e "/obfs_host=/s/..........$/xxxxxx'/" \ -e "/vmess_address=/s/......$/xxxxxx'/" \ -e "/vless_address=/s/......$/xxxxxx'/" \ + -e "/trojan_address=/s/......$/xxxxxx'/" \ + -e "/socks_address=/s/......$/xxxxxx'/" \ + -e "/vless_reality_address=/s/......$/xxxxxx'/" \ -e "/vpn\.key=/s/......$/xxxxxx'/" \ -e "/vps\.key=/s/......$/xxxxxx'/" \ -e "/wgkey=/s/......$/xxxxxx'/" \ From 6b57083bcc1714cb288f69114cb8ced54065c8ab Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 25 Jan 2024 09:25:35 +0100 Subject: [PATCH 1383/2059] Fix typo in omr-tracker init --- omr-tracker/files/etc/init.d/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 73410f488..ae9418ff2 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -253,7 +253,7 @@ _initialize_shadowsocks_rust_tracker() { set shadowsocks-rust.tracker_${server}=ss_local set shadowsocks-rust.tracker_${server}.server=$server set shadowsocks-rust.tracker_${server}.local_address="127.0.0.1" - set shadowsocks-rust.tracker_${server}.local_port=${count) + set shadowsocks-rust.tracker_${server}.local_port=${count} set shadowsocks-rust.tracker_${server}.mode=tcp_and_udp set shadowsocks-rust.tracker_${server}.timeout=600 set shadowsocks-rust.tracker_${server}.fast_open=0 From bbbe2fd45058ba95dc0d407cb96ec3815274d1dc Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 27 Jan 2024 07:55:11 +0100 Subject: [PATCH 1384/2059] Fix XRay --- xray-core/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xray-core/Makefile b/xray-core/Makefile index 262d926d0..369577d04 100644 --- a/xray-core/Makefile +++ b/xray-core/Makefile @@ -24,11 +24,11 @@ define Package/$(PKG_NAME)/template CATEGORY:=Extra packages TITLE:=Xray-core DEPENDS:=$(GO_ARCH_DEPENDS) - PROVIDES:=xray-core endef define Package/$(PKG_NAME)-core $(call Package/$(PKG_NAME)/template) + PROVIDES:=xray-core endef define Package/$(PKG_NAME)-config From e88ad9674f38ca1028b6c81f83ee5c11de32ebee Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 28 Jan 2024 17:18:00 +0100 Subject: [PATCH 1385/2059] Fix omt-test-speedv6 --- openmptcprouter/files/bin/omr-test-speedv6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index 07fa36c54..0302c5d6c 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -37,7 +37,7 @@ for pinghost in $HOSTLST; do HOST=$pinghost fi done -fi + [ -z "$HOST" ] && HOST="https://speed.hetzner.de/10GB.bin" From 730a904b850c761e06fecaa7cffe803b5c9d82e2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 29 Jan 2024 17:10:53 +0100 Subject: [PATCH 1386/2059] Set LAN with higher metric --- mptcp/files/etc/init.d/mptcp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 4342e2732..09a99bf73 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -125,6 +125,9 @@ interface_multipath_settings() { else metric="$(uci -q get openmptcprouter.${config}.metric)" fi + if [ "${config}" = "lan" ] || [ "$(uci -q get network.${config}.ip4table)" = "lan" ]; then + metric="9999" + fi config_set "$config" metric $metric uci -q set network.${config}.metric=$metric uci -q set openmptcprouter.${config}.metric=$metric From 2c02eb0c618f1f72b25fe4f4e84d190e9c8ff99b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 29 Jan 2024 17:11:31 +0100 Subject: [PATCH 1387/2059] Use always rtt line for latency* --- omr-tracker/files/bin/omr-tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index ff1e058ed..f75fd2a1a 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -177,7 +177,7 @@ _ping() { loss=$(echo "$ret" | grep 'packet loss' | cut -d " " -f6 | sed 's/%//' | tr -d '\n') if [ -n "$loss" ] && [ "$loss" -ne 100 ]; then if [ "$localip" = "yes" ]; then - latency=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') + latency=$(echo "$ret" | grep rtt | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n') [ -n "$latency" ] && { OMR_TRACKER_LATENCY="$latency" _update_rto "$OMR_TRACKER_LATENCY" From 11dc97bcecec366a9975e82ae93bac5e14fded5f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 29 Jan 2024 17:12:01 +0100 Subject: [PATCH 1388/2059] Add luci-app-ddns and jq --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 21baab06c..6ecfef576 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -87,7 +87,7 @@ MY_DEPENDS := \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ - luci-proto-external omr-schedule + luci-proto-external omr-schedule jq luci-app-ddns # keepalived disabled by default because it's running even with no configuration, would need a default OMR config with some changes # (TARGET_x86||TARGET_x86_64):keepalived (TARGET_x86||TARGET_x86_64):keepalived-sync From d930f7fefab1dfc7aad070073432bb426ecdca61 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 29 Jan 2024 17:13:12 +0100 Subject: [PATCH 1389/2059] Use openmptcprouter setting instead of shadowsocks for encryption --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 8b7afd374..544a4ff74 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2231,7 +2231,8 @@ _config_service() { vps_aes="$(echo "$vps_config" | jsonfilter -q -e '@.vps.aes')" if [ "$vps_aes" != "false" ] && [ "$user_permission" != "ro" ]; then logger -t "OMR-VPS" "CPU support AES, set it by default" - method="$(uci -q get shadowsocks-libev.sss0.method)" + #method="$(uci -q get shadowsocks-libev.sss0.method)" + method="$(uci -q get openmptcprouter.settings.encryption)" uci -q batch <<-EOF >/dev/null set openmptcprouter.settings.encryption="aes-256-gcm" commit openmptcprouter @@ -2281,7 +2282,7 @@ _config_service() { [ -z "$(_set_vpn_vps)" ] && error=1 [ -z "$(_set_proxy_vps)" ] && error=1 fi - [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && uci -q set openmptcprouter.${servername}.get_config=1 + [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" = "" ] && uci -q set openmptcprouter.${servername}.get_config=1 #_set_pihole [ -n "$wanips" ] && _set_wan_ip From a308a62814726aa6a6824155076fc3e5d896bfb6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 1 Feb 2024 13:58:37 +0100 Subject: [PATCH 1390/2059] Use gpiod-tools for z8102ax --- z8102/Makefile | 5 ++-- z8102/files/etc/init.d/z8102 | 47 ++++++++++++++++++------------- z8102/files/usr/lib/custom/wdg.sh | 12 ++++---- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/z8102/Makefile b/z8102/Makefile index 4d1c7dfb4..238edc0af 100644 --- a/z8102/Makefile +++ b/z8102/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=z8102 -PKG_VERSION:=0.1 -PKG_RELEASE:=2 +PKG_VERSION:=0.2 +PKG_RELEASE:=1 PKG_MAINTAINER:=Yannick Chabanois @@ -18,6 +18,7 @@ define Package/z8102 SECTION:=OMR CATEGORY:=OpenMPTCProuter TITLE:=Install scripts for z8102 + DEPENDS:=+gpiod-tools PKGARCH:=all endef diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index e08ee0b2d..8a5a615de 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -12,33 +12,40 @@ log() { start_service() { # sim 1 - i=461 - echo $i > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio${i}/direction - echo "0" > /sys/class/gpio/gpio${i}/value + #i=461 + #echo $i > /sys/class/gpio/export + #echo "out" > /sys/class/gpio/gpio${i}/direction + #echo "0" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "sim1"`=0 # sim 2 - i=462 - echo $i > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio${i}/direction - echo "0" > /sys/class/gpio/gpio${i}/value + #i=462 + #echo $i > /sys/class/gpio/export + #echo "out" > /sys/class/gpio/gpio${i}/direction + #echo "0" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "sim2"`=0 # stop modem 1 - i=459 - echo $i > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio${i}/direction - echo "0" > /sys/class/gpio/gpio${i}/value + #i=459 + #echo $i > /sys/class/gpio/export + #echo "out" > /sys/class/gpio/gpio${i}/direction + #echo "0" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "modem1"`=0 + # stop modem 2 - i=460 - echo $i > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio${i}/direction - echo "0" > /sys/class/gpio/gpio${i}/value + #i=460 + #echo $i > /sys/class/gpio/export + #echo "out" > /sys/class/gpio/gpio${i}/direction + #echo "0" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "modem2"`=0 sleep 1 # run modem 1 - i=459 - echo "1" > /sys/class/gpio/gpio${i}/value + #i=459 + #echo "1" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "modem1"`=1 sleep 3 # run modem 2 - i=460 - echo "1" > /sys/class/gpio/gpio${i}/value + #i=460 + #echo "1" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "modem2"`=1 } diff --git a/z8102/files/usr/lib/custom/wdg.sh b/z8102/files/usr/lib/custom/wdg.sh index c583dac72..95c4d6802 100755 --- a/z8102/files/usr/lib/custom/wdg.sh +++ b/z8102/files/usr/lib/custom/wdg.sh @@ -1,13 +1,15 @@ #!/bin/sh -i=457 -echo $i > /sys/class/gpio/export -echo "out" > /sys/class/gpio/gpio${i}/direction +#i=457 +#echo $i > /sys/class/gpio/export +#echo "out" > /sys/class/gpio/gpio${i}/direction while true do - echo "1" > /sys/class/gpio/gpio${i}/value + #echo "1" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "watchdog"`=1 sleep 1 - echo "0" > /sys/class/gpio/gpio${i}/value + #echo "0" > /sys/class/gpio/gpio${i}/value + gpioset `gpiofind "watchdog"`=0 sleep 1 done \ No newline at end of file From 99f2265b8dabb8236918796754c09626065c7671 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 1 Feb 2024 13:59:32 +0100 Subject: [PATCH 1391/2059] Possible to add server in wizard even if server config is empty --- .../luasrc/view/openmptcprouter/wizard.htm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 6a9c8c0e6..7fc7ad7b8 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -79,6 +79,9 @@ uci:foreach("openmptcprouter","server", function(s) nbserver=nbserver+1 end) + if nbserver == 0 then + uci:set("openmptcprouter","vps","server") + end uci:foreach("openmptcprouter","server", function(s) servername = s[".name"] %> From 6ecbf3930b67e718132bb35867936b6797999e1e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 2 Feb 2024 15:26:57 +0100 Subject: [PATCH 1392/2059] Move XRay package in Network category --- xray-core/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xray-core/Makefile b/xray-core/Makefile index 369577d04..d2ec1ee23 100644 --- a/xray-core/Makefile +++ b/xray-core/Makefile @@ -20,8 +20,8 @@ include $(INCLUDE_DIR)/package.mk include $(TOPDIR)/feeds/openmptcprouter/golang/golang-package.mk define Package/$(PKG_NAME)/template - SECTION:=Custom - CATEGORY:=Extra packages + SECTION:=net + CATEGORY:=Network TITLE:=Xray-core DEPENDS:=$(GO_ARCH_DEPENDS) endef From 91684da83b69bc7eaa0801db57eab530433c3bab Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Feb 2024 11:20:42 +0100 Subject: [PATCH 1393/2059] Back to /sys/... changes for z8102 --- z8102/files/etc/init.d/z8102 | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index 8a5a615de..67f2cc068 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -16,36 +16,42 @@ start_service() #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - gpioset `gpiofind "sim1"`=0 + echo "0" > /sys/class/gpio/sim1/value + #gpioset `gpiofind "sim1"`=0 # sim 2 #i=462 #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - gpioset `gpiofind "sim2"`=0 + echo "0" > /sys/class/gpio/sim2/value + #gpioset `gpiofind "sim2"`=0 # stop modem 1 #i=459 #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - gpioset `gpiofind "modem1"`=0 + echo "0" > /sys/class/gpio/modem1/value + #gpioset `gpiofind "modem1"`=0 # stop modem 2 #i=460 #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - gpioset `gpiofind "modem2"`=0 + echo "0" > /sys/class/gpio/modem2/value + #gpioset `gpiofind "modem2"`=0 sleep 1 # run modem 1 #i=459 #echo "1" > /sys/class/gpio/gpio${i}/value - gpioset `gpiofind "modem1"`=1 + echo "1" > /sys/class/gpio/modem1/value + #gpioset `gpiofind "modem1"`=1 sleep 3 # run modem 2 #i=460 #echo "1" > /sys/class/gpio/gpio${i}/value - gpioset `gpiofind "modem2"`=1 + echo "1" > /sys/class/gpio/modem2/value + #gpioset `gpiofind "modem2"`=1 } From f4cacab141eab7aafd61aa7de75bf96c8e5958e6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Feb 2024 11:22:11 +0100 Subject: [PATCH 1394/2059] Remove z8102ax config from uci defaults system --- .../files/etc/uci-defaults/2060-omr-system | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 01d8b66b2..af9b39058 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -128,28 +128,31 @@ elif [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep rutx)" EOF fi -if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep z8102ax)" ] && [ -z "$(uci show system | grep modem1)" ]; then - uci -q batch <<-EOF >/dev/null - add system led - set system.@led[-1].name='modem1' - set system.@led[-1].sysfs='4g:status' - set system.@led[-1].trigger='netdev' - set system.@led[-1].dev='wwan0' - add_list system.@led[-1].mode='link' - add_list system.@led[-1].mode='tx' - add_list system.@led[-1].mode='rx' - add system led - set system.@led[-1].name='modem2' - set system.@led[-1].sysfs='4g2:status' - set system.@led[-1].trigger='netdev' - set system.@led[-1].dev='wwan1' - add_list system.@led[-1].mode='link' - add_list system.@led[-1].mode='tx' - add_list system.@led[-1].mode='rx' - commit system - EOF -fi +#if [ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep z8102ax)" ] && [ -z "$(uci show system | grep modem1)" ]; then +# uci -q batch <<-EOF >/dev/null +# add system led +# set system.@led[-1].name='modem1' +# set system.@led[-1].sysfs='modem1:status' +# set system.@led[-1].trigger='netdev' +# set system.@led[-1].dev='wwan0' +# add_list system.@led[-1].mode='link' +# add_list system.@led[-1].mode='tx' +# add_list system.@led[-1].mode='rx' +# add system led +# set system.@led[-1].name='modem2' +# set system.@led[-1].sysfs='modem2:status' +# set system.@led[-1].trigger='netdev' +# set system.@led[-1].dev='wwan1' +# add_list system.@led[-1].mode='link' +# add_list system.@led[-1].mode='tx' +# add_list system.@led[-1].mode='rx' +# commit system +# EOF +#fi #sed -i 's/^\tlogger -t/\t[ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] \&\& logger -t/g' /usr/share/ModemManager/modemmanager.common +#service keepalived stop 2>&1 >/dev/null +#service keepalived disabled 2>&1 >/dev/null + exit 0 \ No newline at end of file From 41ec70a23269798985ed8dcbc0414ac751cc2606 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 7 Feb 2024 11:22:52 +0100 Subject: [PATCH 1395/2059] Fix typo in omr-schedule services --- omr-schedule/files/usr/share/omr/schedule.d/010-services | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-schedule/files/usr/share/omr/schedule.d/010-services b/omr-schedule/files/usr/share/omr/schedule.d/010-services index 44e82fe8b..acbbed0fb 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/010-services +++ b/omr-schedule/files/usr/share/omr/schedule.d/010-services @@ -165,12 +165,12 @@ multipath_fix() { config_load network config_foreach multipath_fix interface -if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then +if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.168.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-ss for Shadowsocks libev, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi -if [ -f /etc/init.d/shadowsocks-rust ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.rust.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then +if [ -f /etc/init.d/shadowsocks-rust ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.rust.server)" != "192.168.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-ss for Shadowsocks Rust, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null fi From 7199f9da25fefa130b94369ad247d468bbac3ba9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 8 Feb 2024 19:49:04 +0100 Subject: [PATCH 1396/2059] Update Golang to 1.22 --- golang/golang/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 55da6587b..a4978b636 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk -GO_VERSION_MAJOR_MINOR:=1.21 -GO_VERSION_PATCH:=4 +GO_VERSION_MAJOR_MINOR:=1.22 +GO_VERSION_PATCH:=0 PKG_NAME:=golang PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=47b26a83d2b65a3c1c1bcace273b69bee49a7a7b5168a7604ded3d26a37bd787 +PKG_HASH:=4d196c3d41a0d6c1dfc64d04e3cc1f608b0c436bd87b7060ce3e23234e1f4d5c PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause From 49002dd61d114a347181c325e79c16aecfe5845e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 8 Feb 2024 19:49:40 +0100 Subject: [PATCH 1397/2059] Fix on shadowsocks-rust init for kernel 5.4 --- shadowsocks-rust/files/shadowsocks-rust.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-rust/files/shadowsocks-rust.init b/shadowsocks-rust/files/shadowsocks-rust.init index a1689bba2..fbca7e408 100644 --- a/shadowsocks-rust/files/shadowsocks-rust.init +++ b/shadowsocks-rust/files/shadowsocks-rust.init @@ -365,7 +365,7 @@ rules_up() { rules_down() { rules_exist || return 0 enabled="0" - config_load shadowsocks-libev + config_load shadowsocks-rust config_foreach server_state server [ "$enabled" = "1" ] && return logger -t "Shadowsocks-rust" "Rules DOWN" From 0e5d941c9b605f218824713b4462b9564ea6130f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 8 Feb 2024 19:50:07 +0100 Subject: [PATCH 1398/2059] Update shadowsocks-rust --- shadowsocks-rust/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile index 410dfc772..3331f2c98 100644 --- a/shadowsocks-rust/Makefile +++ b/shadowsocks-rust/Makefile @@ -7,12 +7,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=shadowsocks-rust -PKG_VERSION:=1.17.1 +PKG_VERSION:=1.18.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/shadowsocks/shadowsocks-rust/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=97a1c8ebf7fd19de94cd6d0dfee398667e1f4e131ec8a37ecb7c3191af7cc75e +PKG_HASH:=e854743ecef9ab3b371fdcb139e6f4452831b487d449c97c2129abbf4f51e863 PKG_MAINTAINER:=Tianling Shen PKG_LICENSE:=MIT From 08993bc8c3321ea7875940e1ee1a8ac98892c4b0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 10 Feb 2024 12:11:02 +0100 Subject: [PATCH 1399/2059] Update Rust --- rust/Makefile | 62 ++++++----- .../0001-Update-xz2-and-use-it-static.patch | 14 +-- rust/patches/0002-Bumped-libc-version.patch | 35 ------ rust/patches/0002-rustc-bootstrap-cache.patch | 52 +++++++++ .../0003-bump-libc-deps-to-0.2.146.patch | 100 ++++++++++++++++++ rust/rust-values.mk | 79 +++++++++++--- 6 files changed, 255 insertions(+), 87 deletions(-) delete mode 100644 rust/patches/0002-Bumped-libc-version.patch create mode 100644 rust/patches/0002-rustc-bootstrap-cache.patch create mode 100644 rust/patches/0003-bump-libc-deps-to-0.2.146.patch diff --git a/rust/Makefile b/rust/Makefile index 5e3b91df9..46ee84e9d 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -3,26 +3,26 @@ # Copyright (C) 2023 Luca Barbato and Donald Hoskins include $(TOPDIR)/rules.mk -include ./rust-values.mk PKG_NAME:=rust -PKG_VERSION:=1.71.1 +PKG_VERSION:=1.75.0 PKG_RELEASE:=1 PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.gz PKG_SOURCE_URL:=https://static.rust-lang.org/dist/ -PKG_HASH:=6fa90d50d1d529a75f6cc349784de57d7ec0ba2419b09bde7d335c25bd4e472e -HOST_BUILD_DIR:=$(BUILD_DIR)/host/rust-$(RUSTC_TARGET_ARCH)/rustc-$(PKG_VERSION)-src +PKG_HASH:=5b739f45bc9d341e2d1c570d65d2375591e22c2d23ef5b8a37711a0386abc088 +HOST_BUILD_DIR:=$(BUILD_DIR)/host/rustc-$(PKG_VERSION)-src PKG_MAINTAINER:=Luca Barbato PKG_LICENSE:=Apache-2.0 MIT PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT -HOST_BUILD_DEPENDS:=python3/host PKG_HOST_ONLY:=1 +PKG_BUILD_FLAGS:=no-mips16 include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk +include ./rust-values.mk define Package/rust SECTION:=lang @@ -30,7 +30,7 @@ define Package/rust SUBMENU:=Rust TITLE:=Rust Programming Language Compiler URL:=https://www.rust-lang.org/ - DEPENDS:=$(RUST_ARCH_DEPENDS) @LINUX_5_4 + DEPENDS:=$(RUST_ARCH_DEPENDS) endef define Package/rust/description @@ -39,8 +39,12 @@ define Package/rust/description guarantee memory safety by using a borrow checker to validate references. endef +define Package/rust/config + source "$(SOURCE)/Config.in" +endef + # Rust-lang has an uninstall script -RUST_UNINSTALL:=$(CARGO_HOME)/lib/rustlib/uninstall.sh +RUST_UNINSTALL:=$(STAGING_DIR)/host/lib/rustlib/uninstall.sh # Target Flags TARGET_CONFIGURE_ARGS = \ @@ -49,28 +53,29 @@ TARGET_CONFIGURE_ARGS = \ --set=target.$(RUSTC_TARGET_ARCH).cxx=$(TARGET_CXX_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).linker=$(TARGET_CC_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).ranlib=$(TARGET_RANLIB) \ + --set=target.$(RUSTC_TARGET_ARCH).crt-static=false \ $(if $(CONFIG_USE_MUSL),--set=target.$(RUSTC_TARGET_ARCH).musl-root=$(TOOLCHAIN_DIR)) # CARGO_HOME is an environmental -HOST_CONFIGURE_OPTS += CARGO_HOME="$(CARGO_HOME)" +HOST_CONFIGURE_VARS += CARGO_HOME="$(CARGO_HOME)" # Rust Configuration Arguments HOST_CONFIGURE_ARGS = \ --build=$(RUSTC_HOST_ARCH) \ --target=$(RUSTC_TARGET_ARCH),$(RUSTC_HOST_ARCH) \ --host=$(RUSTC_HOST_ARCH) \ - --prefix=$(CARGO_HOME) \ - --bindir=$(CARGO_HOME)/bin \ - --libdir=$(CARGO_HOME)/lib \ - --sysconfdir=$(CARGO_HOME)/etc \ - --datadir=$(CARGO_HOME)/share \ - --mandir=$(CARGO_HOME)/man \ - --dist-compression-formats=xz \ + --prefix=$(STAGING_DIR)/host \ + --bindir=$(STAGING_DIR)/host/bin \ + --libdir=$(STAGING_DIR)/host/lib \ + --sysconfdir=$(STAGING_DIR)/host/etc \ + --datadir=$(STAGING_DIR)/host/share \ + --mandir=$(STAGING_DIR)/host/man \ + --dist-compression-formats=gz \ --enable-missing-tools \ --disable-sanitizers \ --release-channel=stable \ --enable-cargo-native-static \ - --set=llvm.download-ci-llvm=false \ + --set=llvm.download-ci-llvm=true \ $(TARGET_CONFIGURE_ARGS) define Host/Uninstall @@ -80,23 +85,24 @@ define Host/Uninstall endef define Host/Compile - ( \ - cd $(HOST_BUILD_DIR) ; \ - $(PYTHON) x.py --config ./config.toml dist build-manifest cargo llvm-tools \ - rustc rust-std rust-src ; \ - ) + $(RUST_SCCACHE_VARS) \ + CARGO_HOME=$(CARGO_HOME) \ + TARGET_CFLAGS="$(TARGET_CFLAGS)" \ + OPENWRT_RUSTC_BOOTSTRAP_CACHE=$(DL_DIR)/rustc \ + $(PYTHON) $(HOST_BUILD_DIR)/x.py \ + --build-dir $(HOST_BUILD_DIR)/build \ + --config $(HOST_BUILD_DIR)/config.toml \ + dist build-manifest cargo llvm-tools rustc rust-std rust-src endef define Host/Install ( \ cd $(HOST_BUILD_DIR)/build/dist ; \ - find -iname "*.xz" -exec tar -xJf {} \; ; \ - find ./* -type f -name install.sh -execdir sh {} --prefix=$(CARGO_HOME) --disable-ldconfig \; ; \ - \ - sed -e 's|@RUSTC_TARGET_ARCH@|$(RUSTC_TARGET_ARCH)|g' \ - -e 's|@TARGET_CC_NOCACHE@|$(TARGET_CC_NOCACHE)|g' \ - -e 's|@RUSTC_LDFLAGS@|$(RUSTC_LDFLAGS)|g' \ - $(CURDIR)/files/cargo-config > $(CARGO_HOME)/config ; \ + for targz in *.tar.gz; do \ + $(STAGING_DIR_HOST)/bin/libdeflate-gzip -dc "$$$$targz" | tar -xf - ; \ + done ; \ + find . -mindepth 2 -maxdepth 2 -type f -name install.sh \ + -execdir bash '{}' --prefix=$(STAGING_DIR)/host --disable-ldconfig \; ; \ ) endef diff --git a/rust/patches/0001-Update-xz2-and-use-it-static.patch b/rust/patches/0001-Update-xz2-and-use-it-static.patch index 8d0c4b042..2360136a7 100644 --- a/rust/patches/0001-Update-xz2-and-use-it-static.patch +++ b/rust/patches/0001-Update-xz2-and-use-it-static.patch @@ -11,7 +11,7 @@ Subject: [PATCH] Update xz2 and use it static --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock -@@ -443,9 +443,9 @@ dependencies = [ +@@ -391,9 +391,9 @@ dependencies = [ [[package]] name = "lzma-sys" @@ -23,7 +23,7 @@ Subject: [PATCH] Update xz2 and use it static dependencies = [ "cc", "libc", -@@ -912,9 +912,9 @@ dependencies = [ +@@ -834,9 +834,9 @@ dependencies = [ [[package]] name = "xz2" @@ -37,12 +37,12 @@ Subject: [PATCH] Update xz2 and use it static ] --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml -@@ -50,7 +50,7 @@ toml = "0.5" - ignore = "0.4.10" - opener = "0.5" - once_cell = "1.7.2" +@@ -57,7 +57,7 @@ tar = "0.4" + termcolor = "1.2.0" + toml = "0.5" + walkdir = "2" -xz2 = "0.1" +xz2 = { version = "0.1", features = ["static"] } - walkdir = "2" # Dependencies needed by the build-metrics feature + sysinfo = { version = "0.26.0", optional = true } diff --git a/rust/patches/0002-Bumped-libc-version.patch b/rust/patches/0002-Bumped-libc-version.patch deleted file mode 100644 index 52c8a245c..000000000 --- a/rust/patches/0002-Bumped-libc-version.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 032857e7e403f654129c45dc7e6718a9ad49e377 Mon Sep 17 00:00:00 2001 -From: Nikolay Arhipov -Date: Tue, 6 Jun 2023 16:09:05 +0300 -Subject: [PATCH] Bumped libc version - ---- - Cargo.lock | 4 ++-- - library/std/Cargo.toml | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -1988,9 +1988,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0e - - [[package]] - name = "libc" --version = "0.2.143" -+version = "0.2.146" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" -+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" - dependencies = [ - "rustc-std-workspace-core", - ] ---- a/library/std/Cargo.toml -+++ b/library/std/Cargo.toml -@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = [ - panic_unwind = { path = "../panic_unwind", optional = true } - panic_abort = { path = "../panic_abort" } - core = { path = "../core" } --libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } -+libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'] } - compiler_builtins = { version = "0.1.92" } - profiler_builtins = { path = "../profiler_builtins", optional = true } - unwind = { path = "../unwind" } diff --git a/rust/patches/0002-rustc-bootstrap-cache.patch b/rust/patches/0002-rustc-bootstrap-cache.patch new file mode 100644 index 000000000..959e23487 --- /dev/null +++ b/rust/patches/0002-rustc-bootstrap-cache.patch @@ -0,0 +1,52 @@ +--- a/src/bootstrap/bootstrap.py ++++ b/src/bootstrap/bootstrap.py +@@ -557,7 +557,7 @@ class RustBuild(object): + shutil.rmtree(bin_root) + + key = self.stage0_compiler.date +- cache_dst = os.path.join(self.build_dir, "cache") ++ cache_dst = os.getenv('OPENWRT_RUSTC_BOOTSTRAP_CACHE', os.path.join(self.build_dir, "cache")) + rustc_cache = os.path.join(cache_dst, key) + if not os.path.exists(rustc_cache): + os.makedirs(rustc_cache) +--- a/src/bootstrap/src/core/download.rs ++++ b/src/bootstrap/src/core/download.rs +@@ -208,7 +208,13 @@ impl Config { + Some(other) => panic!("unsupported protocol {other} in {url}"), + None => panic!("no protocol in {url}"), + } +- t!(std::fs::rename(&tempfile, dest_path)); ++ match std::fs::rename(&tempfile, dest_path) { ++ Ok(v) => v, ++ Err(_) => { ++ t!(std::fs::copy(&tempfile, dest_path)); ++ t!(std::fs::remove_file(&tempfile)); ++ } ++ } + } + + fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { +@@ -544,7 +550,10 @@ impl Config { + key: &str, + destination: &str, + ) { +- let cache_dst = self.out.join("cache"); ++ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { ++ Some(v) => PathBuf::from(v), ++ None => self.out.join("cache"), ++ }; + let cache_dir = cache_dst.join(key); + if !cache_dir.exists() { + t!(fs::create_dir_all(&cache_dir)); +@@ -671,7 +680,10 @@ download-rustc = false + let llvm_assertions = self.llvm_assertions; + + let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); +- let cache_dst = self.out.join("cache"); ++ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { ++ Some(v) => PathBuf::from(v), ++ None => self.out.join("cache"), ++ }; + let rustc_cache = cache_dst.join(cache_prefix); + if !rustc_cache.exists() { + t!(fs::create_dir_all(&rustc_cache)); diff --git a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch new file mode 100644 index 000000000..bb131d23f --- /dev/null +++ b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch @@ -0,0 +1,100 @@ +This patch bumps all libc dependencies and checksums to 0.2.147, which includes the fix for musl 1.2.4. + +--- a/vendor/addr2line-0.19.0/Cargo.lock ++++ b/vendor/addr2line-0.19.0/Cargo.lock +@@ -235,9 +235,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.126" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "memchr" +--- a/vendor/backtrace-0.3.67/Cargo.lock ++++ b/vendor/backtrace-0.3.67/Cargo.lock +@@ -64,9 +64,9 @@ checksum = "dec7af912d60cdbd3677c1af9352 + + [[package]] + name = "libc" +-version = "0.2.138" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "libloading" +--- a/vendor/crossbeam-channel/Cargo.lock ++++ b/vendor/crossbeam-channel/Cargo.lock +@@ -50,9 +50,9 @@ dependencies = [ + + [[package]] + name = "libc" +-version = "0.2.141" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "num_cpus" +--- a/vendor/elasticlunr-rs/Cargo.lock ++++ b/vendor/elasticlunr-rs/Cargo.lock +@@ -555,9 +555,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "lindera" +--- a/vendor/handlebars/Cargo.lock ++++ b/vendor/handlebars/Cargo.lock +@@ -550,9 +550,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "lock_api" +--- a/vendor/libffi/Cargo.lock ++++ b/vendor/libffi/Cargo.lock +@@ -10,9 +10,9 @@ checksum = "50d30906286121d95be3d479533b + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "libffi" +--- a/vendor/tracing-tree/Cargo.lock ++++ b/vendor/tracing-tree/Cargo.lock +@@ -296,9 +296,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.141" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "linux-raw-sys" diff --git a/rust/rust-values.mk b/rust/rust-values.mk index aaa520d57..534aaa02a 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -2,25 +2,32 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins +# Clear environment variables which should be handled internally, +# as users might configure their own env on the host + +# CCache +unexport RUSTC_WRAPPER + # Rust Environmental Vars -CONFIG_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) -RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(CONFIG_HOST_SUFFIX) -CARGO_HOME:=$(STAGING_DIR)/host/cargo -CARGO_VARS:= +RUSTC_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) +RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(RUSTC_HOST_SUFFIX) +CARGO_HOME:=$(DL_DIR)/cargo ifeq ($(CONFIG_USE_MUSL),y) -# Force linking of the SSP library for musl -ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR - ifeq ($(strip $(PKG_SSP)),1) - RUSTC_LDFLAGS += -lssp_nonshared + # Force linking of the SSP library for musl + ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS+=-lssp_nonshared + endif + endif + ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS+=-lssp_nonshared + endif endif endif -ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG - ifeq ($(strip $(PKG_SSP)),1) - TARGET_CFLAGS += -lssp_nonshared - endif -endif -endif + +CARGO_RUSTFLAGS+=-Ctarget-feature=-crt-static $(RUSTC_LDFLAGS) ifeq ($(HOST_OS),Darwin) ifeq ($(HOST_ARCH),arm64) @@ -51,9 +58,47 @@ ifeq ($(ARCH),arm) ifeq ($(CONFIG_HAS_FPU),y) RUSTC_TARGET_ARCH:=$(subst musleabi,musleabihf,$(RUSTC_TARGET_ARCH)) + RUSTC_TARGET_ARCH:=$(subst gnueabi,gnueabihf,$(RUSTC_TARGET_ARCH)) endif endif -#ifeq ($(ARCH),aarch64) -# RUST_CFLAGS:=-mno-outline-atomics -#endif +ifeq ($(ARCH),aarch64) + RUSTC_CFLAGS:=-mno-outline-atomics +endif + +# Support only a subset for now. +RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) + +ifneq ($(CONFIG_RUST_SCCACHE),) + RUST_SCCACHE_DIR:=$(if $(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(TOPDIR)/.sccache) + + RUST_SCCACHE_VARS:= \ + CARGO_INCREMENTAL=0 \ + RUSTC_WRAPPER=sccache \ + SCCACHE_DIR=$(RUST_SCCACHE_DIR) +endif + +CARGO_HOST_CONFIG_VARS= \ + $(RUST_SCCACHE_VARS) \ + CARGO_HOME=$(CARGO_HOME) + +CARGO_HOST_PROFILE:=release + +CARGO_PKG_CONFIG_VARS= \ + $(RUST_SCCACHE_VARS) \ + CARGO_BUILD_TARGET=$(RUSTC_TARGET_ARCH) \ + CARGO_HOME=$(CARGO_HOME) \ + CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ + CARGO_PROFILE_RELEASE_DEBUG=false \ + CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=false \ + CARGO_PROFILE_RELEASE_LTO=true \ + CARGO_PROFILE_RELEASE_OPT_LEVEL=z \ + CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS=true \ + CARGO_PROFILE_RELEASE_PANIC=unwind \ + CARGO_PROFILE_RELEASE_RPATH=false \ + CARGO_TARGET_$(subst -,_,$(call toupper,$(RUSTC_TARGET_ARCH)))_LINKER=$(TARGET_CC_NOCACHE) \ + RUSTFLAGS="$(CARGO_RUSTFLAGS)" \ + TARGET_CC=$(TARGET_CC_NOCACHE) \ + TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUSTC_CFLAGS)" + +CARGO_PKG_PROFILE:=$(if $(CONFIG_DEBUG),dev,release) From 55186758bcdaef892e9406acf83bb46eb284caa7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 10 Feb 2024 12:57:49 +0100 Subject: [PATCH 1400/2059] Add missing files for Rust --- rust/Config.in | 15 ++++++++++++++ rust/files/cargo-config | 8 -------- rust/rust-host-build.mk | 44 +++++++++++++++++++++++------------------ rust/rust-package.mk | 30 +++++++++++----------------- 4 files changed, 52 insertions(+), 45 deletions(-) create mode 100644 rust/Config.in delete mode 100644 rust/files/cargo-config diff --git a/rust/Config.in b/rust/Config.in new file mode 100644 index 000000000..62051af13 --- /dev/null +++ b/rust/Config.in @@ -0,0 +1,15 @@ +menu "Configuration options (for developers)" + +config RUST_SCCACHE + bool "Use sccache" + help + Shared compilation cache; see https://github.com/mozilla/sccache + +config RUST_SCCACHE_DIR + string "Set sccache directory" if RUST_SCCACHE + default "" + help + Store sccache in this directory. + If not set, uses './.sccache' + +endmenu diff --git a/rust/files/cargo-config b/rust/files/cargo-config deleted file mode 100644 index 2ed512931..000000000 --- a/rust/files/cargo-config +++ /dev/null @@ -1,8 +0,0 @@ -[target.@RUSTC_TARGET_ARCH@] -linker = "@TARGET_CC_NOCACHE@" -rustflags = ["-Ctarget-feature=-crt-static", "-Clink-args=@RUSTC_LDFLAGS@"] - -[profile.stripped] -inherits = "release" -opt-level = "s" -strip = true diff --git a/rust/rust-host-build.mk b/rust/rust-host-build.mk index 39cf1f23c..e56292937 100644 --- a/rust/rust-host-build.mk +++ b/rust/rust-host-build.mk @@ -2,36 +2,42 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins +# Variables (all optional) to be set in package Makefiles: +# +# RUST_HOST_FEATURES - list of options, default empty +# +# Space or comma separated list of features to activate +# +# e.g. RUST_HOST_FEATURES:=enable-foo,with-bar + ifeq ($(origin RUST_INCLUDE_DIR),undefined) RUST_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) endif include $(RUST_INCLUDE_DIR)/rust-values.mk +CARGO_HOST_VARS= \ + $(CARGO_HOST_CONFIG_VARS) \ + CC=$(HOSTCC_NOCACHE) \ + MAKEFLAGS="$(HOST_JOBS)" + # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Host/Compile/Cargo - ( \ - cd $(HOST_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - CC=$(HOSTCC_NOCACHE) \ - cargo install -v \ - --profile stripped \ - $(if $(RUST_PKG_FEATURES),--features "$(RUST_PKG_FEATURES)") \ - --root $(HOST_INSTALL_DIR) \ - --path "$(if $(strip $(1)),$(strip $(1)),.)" $(2) ; \ - ) + +$(CARGO_HOST_VARS) \ + cargo install -v \ + --profile $(CARGO_HOST_PROFILE) \ + $(if $(RUST_HOST_FEATURES),--features "$(RUST_HOST_FEATURES)") \ + --root $(HOST_INSTALL_DIR) \ + --path "$(HOST_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ + $(if $(filter --jobserver%,$(HOST_JOBS)),,-j1) \ + $(2) endef define Host/Uninstall/Cargo - ( \ - cd $(HOST_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - CC=$(HOSTCC_NOCACHE) \ - cargo uninstall -v \ - --root $(HOST_INSTALL_DIR) || true ; \ - ) + +$(CARGO_HOST_VARS) \ + cargo uninstall -v \ + --root $(HOST_INSTALL_DIR) \ + || true endef define RustBinHostBuild diff --git a/rust/rust-package.mk b/rust/rust-package.mk index 955b37c29..24341d706 100644 --- a/rust/rust-package.mk +++ b/rust/rust-package.mk @@ -15,28 +15,22 @@ ifeq ($(origin RUST_INCLUDE_DIR),undefined) endif include $(RUST_INCLUDE_DIR)/rust-values.mk -# Support only a subset for now. -RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) +CARGO_PKG_VARS= \ + $(CARGO_PKG_CONFIG_VARS) \ + CC=$(HOSTCC_NOCACHE) \ + MAKEFLAGS="$(PKG_JOBS)" # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Build/Compile/Cargo - ( \ - cd $(PKG_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUST_CFLAGS)" \ - TARGET_CC=$(TARGET_CC_NOCACHE) \ - CC=$(HOSTCC_NOCACHE) \ - $(CARGO_VARS) \ - cargo install -v \ - --profile stripped \ - --target $(RUSTC_TARGET_ARCH) \ - $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ - --root $(PKG_INSTALL_DIR) \ - --path "$(if $(strip $(1)),$(strip $(1)),.)" \ - $(2) ; \ - ) + +$(CARGO_PKG_VARS) \ + cargo install -v \ + --profile $(CARGO_PKG_PROFILE) \ + $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ + --root $(PKG_INSTALL_DIR) \ + --path "$(PKG_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ + $(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \ + $(2) endef define RustBinPackage From 28fd18c5f79ed7c8e53207b112184619bbe0a713 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 10 Feb 2024 14:09:04 +0100 Subject: [PATCH 1401/2059] Fix Golang update by adding 1.20.6 as boostrap --- golang/golang-package.mk | 2 +- golang/golang-values.mk | 1 - golang/golang/Makefile | 30 +++++++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/golang/golang-package.mk b/golang/golang-package.mk index 1b73d23b4..cc0050536 100644 --- a/golang/golang-package.mk +++ b/golang/golang-package.mk @@ -215,7 +215,7 @@ GO_PKG_BUILD_VARS= \ GOPATH="$(GO_PKG_BUILD_DIR)" \ GOCACHE="$(GO_BUILD_CACHE_DIR)" \ GOMODCACHE="$(GO_MOD_CACHE_DIR)" \ - GOENV=off GOPROXY="direct" \ + GOENV=off \ GOTOOLCHAIN=local GO_PKG_VARS= \ diff --git a/golang/golang-values.mk b/golang/golang-values.mk index 7ed58ac65..1584d22fc 100644 --- a/golang/golang-values.mk +++ b/golang/golang-values.mk @@ -31,7 +31,6 @@ unexport \ GOROOT \ GOTOOLCHAIN \ GOTMPDIR \ - GOPROXY \ GOWORK # Unmodified: # GOINSECURE diff --git a/golang/golang/Makefile b/golang/golang/Makefile index a4978b636..82bda52a0 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -95,6 +95,12 @@ BOOTSTRAP_1_17_HASH:=a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd BOOTSTRAP_1_17_BUILD_DIR:=$(HOST_BUILD_DIR)/.go_bootstrap_1.17 +BOOTSTRAP_1_20_SOURCE:=go1.20.6.src.tar.gz +BOOTSTRAP_1_20_SOURCE_URL:=$(GO_SOURCE_URLS) +BOOTSTRAP_1_20_HASH:=62ee5bc6fb55b8bae8f705e0cb8df86d6453626b4ecf93279e2867092e0b7f70 + +BOOTSTRAP_1_20_BUILD_DIR:=$(HOST_BUILD_DIR)/.go_bootstrap_1.20 + include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk include ../golang-compiler.mk @@ -104,6 +110,7 @@ PKG_UNPACK:=$(HOST_TAR) -C "$(PKG_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DI HOST_UNPACK:=$(HOST_TAR) -C "$(HOST_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" BOOTSTRAP_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_SOURCE)" BOOTSTRAP_1_17_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_1_17_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_1_17_SOURCE)" +BOOTSTRAP_1_20_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_1_20_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_1_20_SOURCE)" # don't strip ELF executables in test data RSTRIP:=: @@ -215,6 +222,22 @@ Hooks/HostPrepare/Post+=Bootstrap-1.17/Prepare $(eval $(call GoCompiler/AddProfile,Bootstrap-1.17,$(BOOTSTRAP_1_17_BUILD_DIR),,bootstrap-1.17,$(GO_HOST_OS_ARCH))) +# Bootstrap 1.20 + +define Download/golang-bootstrap-1.20 + FILE:=$(BOOTSTRAP_1_20_SOURCE) + URL:=$(BOOTSTRAP_1_20_SOURCE_URL) + HASH:=$(BOOTSTRAP_1_20_HASH) +endef +$(eval $(call Download,golang-bootstrap-1.20)) + +define Bootstrap-1.20/Prepare + mkdir -p "$(BOOTSTRAP_1_20_BUILD_DIR)" && $(BOOTSTRAP_1_20_UNPACK) ; +endef +Hooks/HostPrepare/Post+=Bootstrap-1.20/Prepare + +$(eval $(call GoCompiler/AddProfile,Bootstrap-1.20,$(BOOTSTRAP_1_20_BUILD_DIR),,bootstrap-1.20,$(GO_HOST_OS_ARCH))) + # Host @@ -251,8 +274,13 @@ define Host/Compile $(HOST_GO_VARS) \ ) - $(call GoCompiler/Host/Make, \ + $(call GoCompiler/Bootstrap-1.20/Make, \ GOROOT_BOOTSTRAP="$(BOOTSTRAP_1_17_BUILD_DIR)" \ + $(HOST_GO_VARS) \ + ) + + $(call GoCompiler/Host/Make, \ + GOROOT_BOOTSTRAP="$(BOOTSTRAP_1_20_BUILD_DIR)" \ $(if $(HOST_GO_ENABLE_PIE),GO_LDFLAGS="-buildmode pie") \ $(HOST_GO_VARS) \ ) From 9bdc22ba4ababe34b36ce5dfdcfff22202c2b087 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 10 Feb 2024 22:15:22 +0100 Subject: [PATCH 1402/2059] Revert Rust change for now, need some tweak for 5.4 support... --- rust/Config.in | 15 --- rust/Makefile | 62 +++++------ rust/files/cargo-config | 8 ++ .../0001-Update-xz2-and-use-it-static.patch | 14 +-- rust/patches/0002-Bumped-libc-version.patch | 35 ++++++ rust/patches/0002-rustc-bootstrap-cache.patch | 52 --------- .../0003-bump-libc-deps-to-0.2.146.patch | 100 ------------------ rust/rust-host-build.mk | 44 ++++---- rust/rust-package.mk | 30 +++--- rust/rust-values.mk | 79 +++----------- 10 files changed, 132 insertions(+), 307 deletions(-) delete mode 100644 rust/Config.in create mode 100644 rust/files/cargo-config create mode 100644 rust/patches/0002-Bumped-libc-version.patch delete mode 100644 rust/patches/0002-rustc-bootstrap-cache.patch delete mode 100644 rust/patches/0003-bump-libc-deps-to-0.2.146.patch diff --git a/rust/Config.in b/rust/Config.in deleted file mode 100644 index 62051af13..000000000 --- a/rust/Config.in +++ /dev/null @@ -1,15 +0,0 @@ -menu "Configuration options (for developers)" - -config RUST_SCCACHE - bool "Use sccache" - help - Shared compilation cache; see https://github.com/mozilla/sccache - -config RUST_SCCACHE_DIR - string "Set sccache directory" if RUST_SCCACHE - default "" - help - Store sccache in this directory. - If not set, uses './.sccache' - -endmenu diff --git a/rust/Makefile b/rust/Makefile index 46ee84e9d..5e3b91df9 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -3,26 +3,26 @@ # Copyright (C) 2023 Luca Barbato and Donald Hoskins include $(TOPDIR)/rules.mk +include ./rust-values.mk PKG_NAME:=rust -PKG_VERSION:=1.75.0 +PKG_VERSION:=1.71.1 PKG_RELEASE:=1 PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.gz PKG_SOURCE_URL:=https://static.rust-lang.org/dist/ -PKG_HASH:=5b739f45bc9d341e2d1c570d65d2375591e22c2d23ef5b8a37711a0386abc088 -HOST_BUILD_DIR:=$(BUILD_DIR)/host/rustc-$(PKG_VERSION)-src +PKG_HASH:=6fa90d50d1d529a75f6cc349784de57d7ec0ba2419b09bde7d335c25bd4e472e +HOST_BUILD_DIR:=$(BUILD_DIR)/host/rust-$(RUSTC_TARGET_ARCH)/rustc-$(PKG_VERSION)-src PKG_MAINTAINER:=Luca Barbato PKG_LICENSE:=Apache-2.0 MIT PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT +HOST_BUILD_DEPENDS:=python3/host PKG_HOST_ONLY:=1 -PKG_BUILD_FLAGS:=no-mips16 include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk -include ./rust-values.mk define Package/rust SECTION:=lang @@ -30,7 +30,7 @@ define Package/rust SUBMENU:=Rust TITLE:=Rust Programming Language Compiler URL:=https://www.rust-lang.org/ - DEPENDS:=$(RUST_ARCH_DEPENDS) + DEPENDS:=$(RUST_ARCH_DEPENDS) @LINUX_5_4 endef define Package/rust/description @@ -39,12 +39,8 @@ define Package/rust/description guarantee memory safety by using a borrow checker to validate references. endef -define Package/rust/config - source "$(SOURCE)/Config.in" -endef - # Rust-lang has an uninstall script -RUST_UNINSTALL:=$(STAGING_DIR)/host/lib/rustlib/uninstall.sh +RUST_UNINSTALL:=$(CARGO_HOME)/lib/rustlib/uninstall.sh # Target Flags TARGET_CONFIGURE_ARGS = \ @@ -53,29 +49,28 @@ TARGET_CONFIGURE_ARGS = \ --set=target.$(RUSTC_TARGET_ARCH).cxx=$(TARGET_CXX_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).linker=$(TARGET_CC_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).ranlib=$(TARGET_RANLIB) \ - --set=target.$(RUSTC_TARGET_ARCH).crt-static=false \ $(if $(CONFIG_USE_MUSL),--set=target.$(RUSTC_TARGET_ARCH).musl-root=$(TOOLCHAIN_DIR)) # CARGO_HOME is an environmental -HOST_CONFIGURE_VARS += CARGO_HOME="$(CARGO_HOME)" +HOST_CONFIGURE_OPTS += CARGO_HOME="$(CARGO_HOME)" # Rust Configuration Arguments HOST_CONFIGURE_ARGS = \ --build=$(RUSTC_HOST_ARCH) \ --target=$(RUSTC_TARGET_ARCH),$(RUSTC_HOST_ARCH) \ --host=$(RUSTC_HOST_ARCH) \ - --prefix=$(STAGING_DIR)/host \ - --bindir=$(STAGING_DIR)/host/bin \ - --libdir=$(STAGING_DIR)/host/lib \ - --sysconfdir=$(STAGING_DIR)/host/etc \ - --datadir=$(STAGING_DIR)/host/share \ - --mandir=$(STAGING_DIR)/host/man \ - --dist-compression-formats=gz \ + --prefix=$(CARGO_HOME) \ + --bindir=$(CARGO_HOME)/bin \ + --libdir=$(CARGO_HOME)/lib \ + --sysconfdir=$(CARGO_HOME)/etc \ + --datadir=$(CARGO_HOME)/share \ + --mandir=$(CARGO_HOME)/man \ + --dist-compression-formats=xz \ --enable-missing-tools \ --disable-sanitizers \ --release-channel=stable \ --enable-cargo-native-static \ - --set=llvm.download-ci-llvm=true \ + --set=llvm.download-ci-llvm=false \ $(TARGET_CONFIGURE_ARGS) define Host/Uninstall @@ -85,24 +80,23 @@ define Host/Uninstall endef define Host/Compile - $(RUST_SCCACHE_VARS) \ - CARGO_HOME=$(CARGO_HOME) \ - TARGET_CFLAGS="$(TARGET_CFLAGS)" \ - OPENWRT_RUSTC_BOOTSTRAP_CACHE=$(DL_DIR)/rustc \ - $(PYTHON) $(HOST_BUILD_DIR)/x.py \ - --build-dir $(HOST_BUILD_DIR)/build \ - --config $(HOST_BUILD_DIR)/config.toml \ - dist build-manifest cargo llvm-tools rustc rust-std rust-src + ( \ + cd $(HOST_BUILD_DIR) ; \ + $(PYTHON) x.py --config ./config.toml dist build-manifest cargo llvm-tools \ + rustc rust-std rust-src ; \ + ) endef define Host/Install ( \ cd $(HOST_BUILD_DIR)/build/dist ; \ - for targz in *.tar.gz; do \ - $(STAGING_DIR_HOST)/bin/libdeflate-gzip -dc "$$$$targz" | tar -xf - ; \ - done ; \ - find . -mindepth 2 -maxdepth 2 -type f -name install.sh \ - -execdir bash '{}' --prefix=$(STAGING_DIR)/host --disable-ldconfig \; ; \ + find -iname "*.xz" -exec tar -xJf {} \; ; \ + find ./* -type f -name install.sh -execdir sh {} --prefix=$(CARGO_HOME) --disable-ldconfig \; ; \ + \ + sed -e 's|@RUSTC_TARGET_ARCH@|$(RUSTC_TARGET_ARCH)|g' \ + -e 's|@TARGET_CC_NOCACHE@|$(TARGET_CC_NOCACHE)|g' \ + -e 's|@RUSTC_LDFLAGS@|$(RUSTC_LDFLAGS)|g' \ + $(CURDIR)/files/cargo-config > $(CARGO_HOME)/config ; \ ) endef diff --git a/rust/files/cargo-config b/rust/files/cargo-config new file mode 100644 index 000000000..2ed512931 --- /dev/null +++ b/rust/files/cargo-config @@ -0,0 +1,8 @@ +[target.@RUSTC_TARGET_ARCH@] +linker = "@TARGET_CC_NOCACHE@" +rustflags = ["-Ctarget-feature=-crt-static", "-Clink-args=@RUSTC_LDFLAGS@"] + +[profile.stripped] +inherits = "release" +opt-level = "s" +strip = true diff --git a/rust/patches/0001-Update-xz2-and-use-it-static.patch b/rust/patches/0001-Update-xz2-and-use-it-static.patch index 2360136a7..8d0c4b042 100644 --- a/rust/patches/0001-Update-xz2-and-use-it-static.patch +++ b/rust/patches/0001-Update-xz2-and-use-it-static.patch @@ -11,7 +11,7 @@ Subject: [PATCH] Update xz2 and use it static --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock -@@ -391,9 +391,9 @@ dependencies = [ +@@ -443,9 +443,9 @@ dependencies = [ [[package]] name = "lzma-sys" @@ -23,7 +23,7 @@ Subject: [PATCH] Update xz2 and use it static dependencies = [ "cc", "libc", -@@ -834,9 +834,9 @@ dependencies = [ +@@ -912,9 +912,9 @@ dependencies = [ [[package]] name = "xz2" @@ -37,12 +37,12 @@ Subject: [PATCH] Update xz2 and use it static ] --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml -@@ -57,7 +57,7 @@ tar = "0.4" - termcolor = "1.2.0" - toml = "0.5" - walkdir = "2" +@@ -50,7 +50,7 @@ toml = "0.5" + ignore = "0.4.10" + opener = "0.5" + once_cell = "1.7.2" -xz2 = "0.1" +xz2 = { version = "0.1", features = ["static"] } + walkdir = "2" # Dependencies needed by the build-metrics feature - sysinfo = { version = "0.26.0", optional = true } diff --git a/rust/patches/0002-Bumped-libc-version.patch b/rust/patches/0002-Bumped-libc-version.patch new file mode 100644 index 000000000..52c8a245c --- /dev/null +++ b/rust/patches/0002-Bumped-libc-version.patch @@ -0,0 +1,35 @@ +From 032857e7e403f654129c45dc7e6718a9ad49e377 Mon Sep 17 00:00:00 2001 +From: Nikolay Arhipov +Date: Tue, 6 Jun 2023 16:09:05 +0300 +Subject: [PATCH] Bumped libc version + +--- + Cargo.lock | 4 ++-- + library/std/Cargo.toml | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -1988,9 +1988,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0e + + [[package]] + name = "libc" +-version = "0.2.143" ++version = "0.2.146" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" ++checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" + dependencies = [ + "rustc-std-workspace-core", + ] +--- a/library/std/Cargo.toml ++++ b/library/std/Cargo.toml +@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = [ + panic_unwind = { path = "../panic_unwind", optional = true } + panic_abort = { path = "../panic_abort" } + core = { path = "../core" } +-libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } ++libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'] } + compiler_builtins = { version = "0.1.92" } + profiler_builtins = { path = "../profiler_builtins", optional = true } + unwind = { path = "../unwind" } diff --git a/rust/patches/0002-rustc-bootstrap-cache.patch b/rust/patches/0002-rustc-bootstrap-cache.patch deleted file mode 100644 index 959e23487..000000000 --- a/rust/patches/0002-rustc-bootstrap-cache.patch +++ /dev/null @@ -1,52 +0,0 @@ ---- a/src/bootstrap/bootstrap.py -+++ b/src/bootstrap/bootstrap.py -@@ -557,7 +557,7 @@ class RustBuild(object): - shutil.rmtree(bin_root) - - key = self.stage0_compiler.date -- cache_dst = os.path.join(self.build_dir, "cache") -+ cache_dst = os.getenv('OPENWRT_RUSTC_BOOTSTRAP_CACHE', os.path.join(self.build_dir, "cache")) - rustc_cache = os.path.join(cache_dst, key) - if not os.path.exists(rustc_cache): - os.makedirs(rustc_cache) ---- a/src/bootstrap/src/core/download.rs -+++ b/src/bootstrap/src/core/download.rs -@@ -208,7 +208,13 @@ impl Config { - Some(other) => panic!("unsupported protocol {other} in {url}"), - None => panic!("no protocol in {url}"), - } -- t!(std::fs::rename(&tempfile, dest_path)); -+ match std::fs::rename(&tempfile, dest_path) { -+ Ok(v) => v, -+ Err(_) => { -+ t!(std::fs::copy(&tempfile, dest_path)); -+ t!(std::fs::remove_file(&tempfile)); -+ } -+ } - } - - fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { -@@ -544,7 +550,10 @@ impl Config { - key: &str, - destination: &str, - ) { -- let cache_dst = self.out.join("cache"); -+ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { -+ Some(v) => PathBuf::from(v), -+ None => self.out.join("cache"), -+ }; - let cache_dir = cache_dst.join(key); - if !cache_dir.exists() { - t!(fs::create_dir_all(&cache_dir)); -@@ -671,7 +680,10 @@ download-rustc = false - let llvm_assertions = self.llvm_assertions; - - let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); -- let cache_dst = self.out.join("cache"); -+ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { -+ Some(v) => PathBuf::from(v), -+ None => self.out.join("cache"), -+ }; - let rustc_cache = cache_dst.join(cache_prefix); - if !rustc_cache.exists() { - t!(fs::create_dir_all(&rustc_cache)); diff --git a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch deleted file mode 100644 index bb131d23f..000000000 --- a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch +++ /dev/null @@ -1,100 +0,0 @@ -This patch bumps all libc dependencies and checksums to 0.2.147, which includes the fix for musl 1.2.4. - ---- a/vendor/addr2line-0.19.0/Cargo.lock -+++ b/vendor/addr2line-0.19.0/Cargo.lock -@@ -235,9 +235,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.126" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "memchr" ---- a/vendor/backtrace-0.3.67/Cargo.lock -+++ b/vendor/backtrace-0.3.67/Cargo.lock -@@ -64,9 +64,9 @@ checksum = "dec7af912d60cdbd3677c1af9352 - - [[package]] - name = "libc" --version = "0.2.138" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "libloading" ---- a/vendor/crossbeam-channel/Cargo.lock -+++ b/vendor/crossbeam-channel/Cargo.lock -@@ -50,9 +50,9 @@ dependencies = [ - - [[package]] - name = "libc" --version = "0.2.141" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "num_cpus" ---- a/vendor/elasticlunr-rs/Cargo.lock -+++ b/vendor/elasticlunr-rs/Cargo.lock -@@ -555,9 +555,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.140" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "lindera" ---- a/vendor/handlebars/Cargo.lock -+++ b/vendor/handlebars/Cargo.lock -@@ -550,9 +550,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.140" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "lock_api" ---- a/vendor/libffi/Cargo.lock -+++ b/vendor/libffi/Cargo.lock -@@ -10,9 +10,9 @@ checksum = "50d30906286121d95be3d479533b - - [[package]] - name = "libc" --version = "0.2.140" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "libffi" ---- a/vendor/tracing-tree/Cargo.lock -+++ b/vendor/tracing-tree/Cargo.lock -@@ -296,9 +296,9 @@ checksum = "e2abad23fbc42b3700f2f279844d - - [[package]] - name = "libc" --version = "0.2.141" -+version = "0.2.147" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - - [[package]] - name = "linux-raw-sys" diff --git a/rust/rust-host-build.mk b/rust/rust-host-build.mk index e56292937..39cf1f23c 100644 --- a/rust/rust-host-build.mk +++ b/rust/rust-host-build.mk @@ -2,42 +2,36 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins -# Variables (all optional) to be set in package Makefiles: -# -# RUST_HOST_FEATURES - list of options, default empty -# -# Space or comma separated list of features to activate -# -# e.g. RUST_HOST_FEATURES:=enable-foo,with-bar - ifeq ($(origin RUST_INCLUDE_DIR),undefined) RUST_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) endif include $(RUST_INCLUDE_DIR)/rust-values.mk -CARGO_HOST_VARS= \ - $(CARGO_HOST_CONFIG_VARS) \ - CC=$(HOSTCC_NOCACHE) \ - MAKEFLAGS="$(HOST_JOBS)" - # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Host/Compile/Cargo - +$(CARGO_HOST_VARS) \ - cargo install -v \ - --profile $(CARGO_HOST_PROFILE) \ - $(if $(RUST_HOST_FEATURES),--features "$(RUST_HOST_FEATURES)") \ - --root $(HOST_INSTALL_DIR) \ - --path "$(HOST_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ - $(if $(filter --jobserver%,$(HOST_JOBS)),,-j1) \ - $(2) + ( \ + cd $(HOST_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + CC=$(HOSTCC_NOCACHE) \ + cargo install -v \ + --profile stripped \ + $(if $(RUST_PKG_FEATURES),--features "$(RUST_PKG_FEATURES)") \ + --root $(HOST_INSTALL_DIR) \ + --path "$(if $(strip $(1)),$(strip $(1)),.)" $(2) ; \ + ) endef define Host/Uninstall/Cargo - +$(CARGO_HOST_VARS) \ - cargo uninstall -v \ - --root $(HOST_INSTALL_DIR) \ - || true + ( \ + cd $(HOST_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + CC=$(HOSTCC_NOCACHE) \ + cargo uninstall -v \ + --root $(HOST_INSTALL_DIR) || true ; \ + ) endef define RustBinHostBuild diff --git a/rust/rust-package.mk b/rust/rust-package.mk index 24341d706..955b37c29 100644 --- a/rust/rust-package.mk +++ b/rust/rust-package.mk @@ -15,22 +15,28 @@ ifeq ($(origin RUST_INCLUDE_DIR),undefined) endif include $(RUST_INCLUDE_DIR)/rust-values.mk -CARGO_PKG_VARS= \ - $(CARGO_PKG_CONFIG_VARS) \ - CC=$(HOSTCC_NOCACHE) \ - MAKEFLAGS="$(PKG_JOBS)" +# Support only a subset for now. +RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Build/Compile/Cargo - +$(CARGO_PKG_VARS) \ - cargo install -v \ - --profile $(CARGO_PKG_PROFILE) \ - $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ - --root $(PKG_INSTALL_DIR) \ - --path "$(PKG_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ - $(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \ - $(2) + ( \ + cd $(PKG_BUILD_DIR) ; \ + export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ + CARGO_HOME=$(CARGO_HOME) \ + TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUST_CFLAGS)" \ + TARGET_CC=$(TARGET_CC_NOCACHE) \ + CC=$(HOSTCC_NOCACHE) \ + $(CARGO_VARS) \ + cargo install -v \ + --profile stripped \ + --target $(RUSTC_TARGET_ARCH) \ + $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ + --root $(PKG_INSTALL_DIR) \ + --path "$(if $(strip $(1)),$(strip $(1)),.)" \ + $(2) ; \ + ) endef define RustBinPackage diff --git a/rust/rust-values.mk b/rust/rust-values.mk index 534aaa02a..aaa520d57 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -2,32 +2,25 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins -# Clear environment variables which should be handled internally, -# as users might configure their own env on the host - -# CCache -unexport RUSTC_WRAPPER - # Rust Environmental Vars -RUSTC_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) -RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(RUSTC_HOST_SUFFIX) -CARGO_HOME:=$(DL_DIR)/cargo +CONFIG_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) +RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(CONFIG_HOST_SUFFIX) +CARGO_HOME:=$(STAGING_DIR)/host/cargo +CARGO_VARS:= ifeq ($(CONFIG_USE_MUSL),y) - # Force linking of the SSP library for musl - ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR - ifeq ($(strip $(PKG_SSP)),1) - RUSTC_LDFLAGS+=-lssp_nonshared - endif - endif - ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG - ifeq ($(strip $(PKG_SSP)),1) - RUSTC_LDFLAGS+=-lssp_nonshared - endif +# Force linking of the SSP library for musl +ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS += -lssp_nonshared endif endif - -CARGO_RUSTFLAGS+=-Ctarget-feature=-crt-static $(RUSTC_LDFLAGS) +ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG + ifeq ($(strip $(PKG_SSP)),1) + TARGET_CFLAGS += -lssp_nonshared + endif +endif +endif ifeq ($(HOST_OS),Darwin) ifeq ($(HOST_ARCH),arm64) @@ -58,47 +51,9 @@ ifeq ($(ARCH),arm) ifeq ($(CONFIG_HAS_FPU),y) RUSTC_TARGET_ARCH:=$(subst musleabi,musleabihf,$(RUSTC_TARGET_ARCH)) - RUSTC_TARGET_ARCH:=$(subst gnueabi,gnueabihf,$(RUSTC_TARGET_ARCH)) endif endif -ifeq ($(ARCH),aarch64) - RUSTC_CFLAGS:=-mno-outline-atomics -endif - -# Support only a subset for now. -RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) - -ifneq ($(CONFIG_RUST_SCCACHE),) - RUST_SCCACHE_DIR:=$(if $(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(TOPDIR)/.sccache) - - RUST_SCCACHE_VARS:= \ - CARGO_INCREMENTAL=0 \ - RUSTC_WRAPPER=sccache \ - SCCACHE_DIR=$(RUST_SCCACHE_DIR) -endif - -CARGO_HOST_CONFIG_VARS= \ - $(RUST_SCCACHE_VARS) \ - CARGO_HOME=$(CARGO_HOME) - -CARGO_HOST_PROFILE:=release - -CARGO_PKG_CONFIG_VARS= \ - $(RUST_SCCACHE_VARS) \ - CARGO_BUILD_TARGET=$(RUSTC_TARGET_ARCH) \ - CARGO_HOME=$(CARGO_HOME) \ - CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ - CARGO_PROFILE_RELEASE_DEBUG=false \ - CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=false \ - CARGO_PROFILE_RELEASE_LTO=true \ - CARGO_PROFILE_RELEASE_OPT_LEVEL=z \ - CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS=true \ - CARGO_PROFILE_RELEASE_PANIC=unwind \ - CARGO_PROFILE_RELEASE_RPATH=false \ - CARGO_TARGET_$(subst -,_,$(call toupper,$(RUSTC_TARGET_ARCH)))_LINKER=$(TARGET_CC_NOCACHE) \ - RUSTFLAGS="$(CARGO_RUSTFLAGS)" \ - TARGET_CC=$(TARGET_CC_NOCACHE) \ - TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUSTC_CFLAGS)" - -CARGO_PKG_PROFILE:=$(if $(CONFIG_DEBUG),dev,release) +#ifeq ($(ARCH),aarch64) +# RUST_CFLAGS:=-mno-outline-atomics +#endif From 251ef8178d4f983639d922ca0e2bba21cf98f6f3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 11 Feb 2024 07:34:35 +0100 Subject: [PATCH 1403/2059] Revert to previous Shadowsocks-rust release only for kernel 5.4 --- shadowsocks-rust/Makefile | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile index 3331f2c98..519722921 100644 --- a/shadowsocks-rust/Makefile +++ b/shadowsocks-rust/Makefile @@ -2,19 +2,25 @@ # # Copyright (C) 2017-2020 Yousong Zhou # Copyright (C) 2021-2023 ImmortalWrt.org -# Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter +# Copyright (C) 2023-2024 Yannick Chabanois (Ycarus) for OpenMPTCProuter include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=shadowsocks-rust -PKG_VERSION:=1.18.0 +ifneq ($(word 1,$(subst ., ,$(LINUX_VERSION))),"5") + PKG_VERSION:=1.17.1 + PKG_HASH:=97a1c8ebf7fd19de94cd6d0dfee398667e1f4e131ec8a37ecb7c3191af7cc75e +else + PKG_VERSION:=1.18.0 + PKG_HASH:=e854743ecef9ab3b371fdcb139e6f4452831b487d449c97c2129abbf4f51e863 +endif PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/shadowsocks/shadowsocks-rust/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=e854743ecef9ab3b371fdcb139e6f4452831b487d449c97c2129abbf4f51e863 -PKG_MAINTAINER:=Tianling Shen +PKG_MAINTAINER:=Yannick Chabanois PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE @@ -23,8 +29,11 @@ PKG_BUILD_DEPENDS:=rust/host RUST_PKG_FEATURES:=local-redir include $(INCLUDE_DIR)/package.mk -#include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk +ifneq ($(word 1,$(subst ., ,$(LINUX_VERSION))),"5") include $(TOPDIR)/feeds/openmptcprouter/rust/rust-package.mk +else +include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk +endif define Package/shadowsocks-rust/Default define Package/shadowsocks-rust-$(1) From 1a3fa01cd0d0f24007f7c2b26908f053bd575c5d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 11 Feb 2024 19:24:14 +0100 Subject: [PATCH 1404/2059] Disable Shadowsocks-Rust on 5.4 for now... --- openmptcprouter-full/Makefile | 4 +- rust/Config.in | 15 +++ rust/Makefile | 64 ++++++----- rust/files/cargo-config | 8 -- .../0001-Update-xz2-and-use-it-static.patch | 14 +-- rust/patches/0002-Bumped-libc-version.patch | 35 ------ rust/patches/0002-rustc-bootstrap-cache.patch | 52 +++++++++ .../0003-bump-libc-deps-to-0.2.146.patch | 100 ++++++++++++++++++ rust/rust-host-build.mk | 44 ++++---- rust/rust-package.mk | 30 +++--- rust/rust-values.mk | 79 +++++++++++--- shadowsocks-rust/Makefile | 13 +-- 12 files changed, 314 insertions(+), 144 deletions(-) create mode 100644 rust/Config.in delete mode 100644 rust/files/cargo-config delete mode 100644 rust/patches/0002-Bumped-libc-version.patch create mode 100644 rust/patches/0002-rustc-bootstrap-cache.patch create mode 100644 rust/patches/0003-bump-libc-deps-to-0.2.146.patch diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 6ecfef576..a3aec2279 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -86,9 +86,11 @@ MY_DEPENDS := \ !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core LINUX_5_4:v2ray-config !LINUX_5_4:v2ray-config-nft syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ - xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ + xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ + !LINUX_5_4:shadowsocks-rust-sslocal !LINUX_5_4:shadowsocks-rust-ssservice !LINUX_5_4:shadowsocks-rust-config-nft !LINUX_5_4:luci-app-shadowsocks-rust \ luci-proto-external omr-schedule jq luci-app-ddns +# shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust \ # keepalived disabled by default because it's running even with no configuration, would need a default OMR config with some changes # (TARGET_x86||TARGET_x86_64):keepalived (TARGET_x86||TARGET_x86_64):keepalived-sync diff --git a/rust/Config.in b/rust/Config.in new file mode 100644 index 000000000..62051af13 --- /dev/null +++ b/rust/Config.in @@ -0,0 +1,15 @@ +menu "Configuration options (for developers)" + +config RUST_SCCACHE + bool "Use sccache" + help + Shared compilation cache; see https://github.com/mozilla/sccache + +config RUST_SCCACHE_DIR + string "Set sccache directory" if RUST_SCCACHE + default "" + help + Store sccache in this directory. + If not set, uses './.sccache' + +endmenu diff --git a/rust/Makefile b/rust/Makefile index 5e3b91df9..1555d10b7 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -3,26 +3,28 @@ # Copyright (C) 2023 Luca Barbato and Donald Hoskins include $(TOPDIR)/rules.mk -include ./rust-values.mk PKG_NAME:=rust -PKG_VERSION:=1.71.1 + +PKG_VERSION:=1.75.0 + PKG_RELEASE:=1 PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.gz PKG_SOURCE_URL:=https://static.rust-lang.org/dist/ -PKG_HASH:=6fa90d50d1d529a75f6cc349784de57d7ec0ba2419b09bde7d335c25bd4e472e -HOST_BUILD_DIR:=$(BUILD_DIR)/host/rust-$(RUSTC_TARGET_ARCH)/rustc-$(PKG_VERSION)-src +PKG_HASH:=5b739f45bc9d341e2d1c570d65d2375591e22c2d23ef5b8a37711a0386abc088 +HOST_BUILD_DIR:=$(BUILD_DIR)/host/rustc-$(PKG_VERSION)-src PKG_MAINTAINER:=Luca Barbato PKG_LICENSE:=Apache-2.0 MIT PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT -HOST_BUILD_DEPENDS:=python3/host PKG_HOST_ONLY:=1 +PKG_BUILD_FLAGS:=no-mips16 include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk +include ./rust-values.mk define Package/rust SECTION:=lang @@ -30,7 +32,7 @@ define Package/rust SUBMENU:=Rust TITLE:=Rust Programming Language Compiler URL:=https://www.rust-lang.org/ - DEPENDS:=$(RUST_ARCH_DEPENDS) @LINUX_5_4 + DEPENDS:=$(RUST_ARCH_DEPENDS) @!(LINUX_5_4) endef define Package/rust/description @@ -39,8 +41,12 @@ define Package/rust/description guarantee memory safety by using a borrow checker to validate references. endef +define Package/rust/config + source "$(SOURCE)/Config.in" +endef + # Rust-lang has an uninstall script -RUST_UNINSTALL:=$(CARGO_HOME)/lib/rustlib/uninstall.sh +RUST_UNINSTALL:=$(STAGING_DIR)/host/lib/rustlib/uninstall.sh # Target Flags TARGET_CONFIGURE_ARGS = \ @@ -49,28 +55,29 @@ TARGET_CONFIGURE_ARGS = \ --set=target.$(RUSTC_TARGET_ARCH).cxx=$(TARGET_CXX_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).linker=$(TARGET_CC_NOCACHE) \ --set=target.$(RUSTC_TARGET_ARCH).ranlib=$(TARGET_RANLIB) \ + --set=target.$(RUSTC_TARGET_ARCH).crt-static=false \ $(if $(CONFIG_USE_MUSL),--set=target.$(RUSTC_TARGET_ARCH).musl-root=$(TOOLCHAIN_DIR)) # CARGO_HOME is an environmental -HOST_CONFIGURE_OPTS += CARGO_HOME="$(CARGO_HOME)" +HOST_CONFIGURE_VARS += CARGO_HOME="$(CARGO_HOME)" # Rust Configuration Arguments HOST_CONFIGURE_ARGS = \ --build=$(RUSTC_HOST_ARCH) \ --target=$(RUSTC_TARGET_ARCH),$(RUSTC_HOST_ARCH) \ --host=$(RUSTC_HOST_ARCH) \ - --prefix=$(CARGO_HOME) \ - --bindir=$(CARGO_HOME)/bin \ - --libdir=$(CARGO_HOME)/lib \ - --sysconfdir=$(CARGO_HOME)/etc \ - --datadir=$(CARGO_HOME)/share \ - --mandir=$(CARGO_HOME)/man \ - --dist-compression-formats=xz \ + --prefix=$(STAGING_DIR)/host \ + --bindir=$(STAGING_DIR)/host/bin \ + --libdir=$(STAGING_DIR)/host/lib \ + --sysconfdir=$(STAGING_DIR)/host/etc \ + --datadir=$(STAGING_DIR)/host/share \ + --mandir=$(STAGING_DIR)/host/man \ + --dist-compression-formats=gz \ --enable-missing-tools \ --disable-sanitizers \ --release-channel=stable \ --enable-cargo-native-static \ - --set=llvm.download-ci-llvm=false \ + --set=llvm.download-ci-llvm=true \ $(TARGET_CONFIGURE_ARGS) define Host/Uninstall @@ -80,23 +87,24 @@ define Host/Uninstall endef define Host/Compile - ( \ - cd $(HOST_BUILD_DIR) ; \ - $(PYTHON) x.py --config ./config.toml dist build-manifest cargo llvm-tools \ - rustc rust-std rust-src ; \ - ) + $(RUST_SCCACHE_VARS) \ + CARGO_HOME=$(CARGO_HOME) \ + TARGET_CFLAGS="$(TARGET_CFLAGS)" \ + OPENWRT_RUSTC_BOOTSTRAP_CACHE=$(DL_DIR)/rustc \ + $(PYTHON) $(HOST_BUILD_DIR)/x.py \ + --build-dir $(HOST_BUILD_DIR)/build \ + --config $(HOST_BUILD_DIR)/config.toml \ + dist build-manifest cargo llvm-tools rustc rust-std rust-src endef define Host/Install ( \ cd $(HOST_BUILD_DIR)/build/dist ; \ - find -iname "*.xz" -exec tar -xJf {} \; ; \ - find ./* -type f -name install.sh -execdir sh {} --prefix=$(CARGO_HOME) --disable-ldconfig \; ; \ - \ - sed -e 's|@RUSTC_TARGET_ARCH@|$(RUSTC_TARGET_ARCH)|g' \ - -e 's|@TARGET_CC_NOCACHE@|$(TARGET_CC_NOCACHE)|g' \ - -e 's|@RUSTC_LDFLAGS@|$(RUSTC_LDFLAGS)|g' \ - $(CURDIR)/files/cargo-config > $(CARGO_HOME)/config ; \ + for targz in *.tar.gz; do \ + $(STAGING_DIR_HOST)/bin/libdeflate-gzip -dc "$$$$targz" | tar -xf - ; \ + done ; \ + find . -mindepth 2 -maxdepth 2 -type f -name install.sh \ + -execdir bash '{}' --prefix=$(STAGING_DIR)/host --disable-ldconfig \; ; \ ) endef diff --git a/rust/files/cargo-config b/rust/files/cargo-config deleted file mode 100644 index 2ed512931..000000000 --- a/rust/files/cargo-config +++ /dev/null @@ -1,8 +0,0 @@ -[target.@RUSTC_TARGET_ARCH@] -linker = "@TARGET_CC_NOCACHE@" -rustflags = ["-Ctarget-feature=-crt-static", "-Clink-args=@RUSTC_LDFLAGS@"] - -[profile.stripped] -inherits = "release" -opt-level = "s" -strip = true diff --git a/rust/patches/0001-Update-xz2-and-use-it-static.patch b/rust/patches/0001-Update-xz2-and-use-it-static.patch index 8d0c4b042..2360136a7 100644 --- a/rust/patches/0001-Update-xz2-and-use-it-static.patch +++ b/rust/patches/0001-Update-xz2-and-use-it-static.patch @@ -11,7 +11,7 @@ Subject: [PATCH] Update xz2 and use it static --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock -@@ -443,9 +443,9 @@ dependencies = [ +@@ -391,9 +391,9 @@ dependencies = [ [[package]] name = "lzma-sys" @@ -23,7 +23,7 @@ Subject: [PATCH] Update xz2 and use it static dependencies = [ "cc", "libc", -@@ -912,9 +912,9 @@ dependencies = [ +@@ -834,9 +834,9 @@ dependencies = [ [[package]] name = "xz2" @@ -37,12 +37,12 @@ Subject: [PATCH] Update xz2 and use it static ] --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml -@@ -50,7 +50,7 @@ toml = "0.5" - ignore = "0.4.10" - opener = "0.5" - once_cell = "1.7.2" +@@ -57,7 +57,7 @@ tar = "0.4" + termcolor = "1.2.0" + toml = "0.5" + walkdir = "2" -xz2 = "0.1" +xz2 = { version = "0.1", features = ["static"] } - walkdir = "2" # Dependencies needed by the build-metrics feature + sysinfo = { version = "0.26.0", optional = true } diff --git a/rust/patches/0002-Bumped-libc-version.patch b/rust/patches/0002-Bumped-libc-version.patch deleted file mode 100644 index 52c8a245c..000000000 --- a/rust/patches/0002-Bumped-libc-version.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 032857e7e403f654129c45dc7e6718a9ad49e377 Mon Sep 17 00:00:00 2001 -From: Nikolay Arhipov -Date: Tue, 6 Jun 2023 16:09:05 +0300 -Subject: [PATCH] Bumped libc version - ---- - Cargo.lock | 4 ++-- - library/std/Cargo.toml | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -1988,9 +1988,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0e - - [[package]] - name = "libc" --version = "0.2.143" -+version = "0.2.146" - source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" -+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" - dependencies = [ - "rustc-std-workspace-core", - ] ---- a/library/std/Cargo.toml -+++ b/library/std/Cargo.toml -@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = [ - panic_unwind = { path = "../panic_unwind", optional = true } - panic_abort = { path = "../panic_abort" } - core = { path = "../core" } --libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } -+libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'] } - compiler_builtins = { version = "0.1.92" } - profiler_builtins = { path = "../profiler_builtins", optional = true } - unwind = { path = "../unwind" } diff --git a/rust/patches/0002-rustc-bootstrap-cache.patch b/rust/patches/0002-rustc-bootstrap-cache.patch new file mode 100644 index 000000000..959e23487 --- /dev/null +++ b/rust/patches/0002-rustc-bootstrap-cache.patch @@ -0,0 +1,52 @@ +--- a/src/bootstrap/bootstrap.py ++++ b/src/bootstrap/bootstrap.py +@@ -557,7 +557,7 @@ class RustBuild(object): + shutil.rmtree(bin_root) + + key = self.stage0_compiler.date +- cache_dst = os.path.join(self.build_dir, "cache") ++ cache_dst = os.getenv('OPENWRT_RUSTC_BOOTSTRAP_CACHE', os.path.join(self.build_dir, "cache")) + rustc_cache = os.path.join(cache_dst, key) + if not os.path.exists(rustc_cache): + os.makedirs(rustc_cache) +--- a/src/bootstrap/src/core/download.rs ++++ b/src/bootstrap/src/core/download.rs +@@ -208,7 +208,13 @@ impl Config { + Some(other) => panic!("unsupported protocol {other} in {url}"), + None => panic!("no protocol in {url}"), + } +- t!(std::fs::rename(&tempfile, dest_path)); ++ match std::fs::rename(&tempfile, dest_path) { ++ Ok(v) => v, ++ Err(_) => { ++ t!(std::fs::copy(&tempfile, dest_path)); ++ t!(std::fs::remove_file(&tempfile)); ++ } ++ } + } + + fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { +@@ -544,7 +550,10 @@ impl Config { + key: &str, + destination: &str, + ) { +- let cache_dst = self.out.join("cache"); ++ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { ++ Some(v) => PathBuf::from(v), ++ None => self.out.join("cache"), ++ }; + let cache_dir = cache_dst.join(key); + if !cache_dir.exists() { + t!(fs::create_dir_all(&cache_dir)); +@@ -671,7 +680,10 @@ download-rustc = false + let llvm_assertions = self.llvm_assertions; + + let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); +- let cache_dst = self.out.join("cache"); ++ let cache_dst = match env::var_os("OPENWRT_RUSTC_BOOTSTRAP_CACHE") { ++ Some(v) => PathBuf::from(v), ++ None => self.out.join("cache"), ++ }; + let rustc_cache = cache_dst.join(cache_prefix); + if !rustc_cache.exists() { + t!(fs::create_dir_all(&rustc_cache)); diff --git a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch new file mode 100644 index 000000000..bb131d23f --- /dev/null +++ b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch @@ -0,0 +1,100 @@ +This patch bumps all libc dependencies and checksums to 0.2.147, which includes the fix for musl 1.2.4. + +--- a/vendor/addr2line-0.19.0/Cargo.lock ++++ b/vendor/addr2line-0.19.0/Cargo.lock +@@ -235,9 +235,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.126" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "memchr" +--- a/vendor/backtrace-0.3.67/Cargo.lock ++++ b/vendor/backtrace-0.3.67/Cargo.lock +@@ -64,9 +64,9 @@ checksum = "dec7af912d60cdbd3677c1af9352 + + [[package]] + name = "libc" +-version = "0.2.138" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "libloading" +--- a/vendor/crossbeam-channel/Cargo.lock ++++ b/vendor/crossbeam-channel/Cargo.lock +@@ -50,9 +50,9 @@ dependencies = [ + + [[package]] + name = "libc" +-version = "0.2.141" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "num_cpus" +--- a/vendor/elasticlunr-rs/Cargo.lock ++++ b/vendor/elasticlunr-rs/Cargo.lock +@@ -555,9 +555,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "lindera" +--- a/vendor/handlebars/Cargo.lock ++++ b/vendor/handlebars/Cargo.lock +@@ -550,9 +550,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "lock_api" +--- a/vendor/libffi/Cargo.lock ++++ b/vendor/libffi/Cargo.lock +@@ -10,9 +10,9 @@ checksum = "50d30906286121d95be3d479533b + + [[package]] + name = "libc" +-version = "0.2.140" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "libffi" +--- a/vendor/tracing-tree/Cargo.lock ++++ b/vendor/tracing-tree/Cargo.lock +@@ -296,9 +296,9 @@ checksum = "e2abad23fbc42b3700f2f279844d + + [[package]] + name = "libc" +-version = "0.2.141" ++version = "0.2.147" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" ++checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + + [[package]] + name = "linux-raw-sys" diff --git a/rust/rust-host-build.mk b/rust/rust-host-build.mk index 39cf1f23c..e56292937 100644 --- a/rust/rust-host-build.mk +++ b/rust/rust-host-build.mk @@ -2,36 +2,42 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins +# Variables (all optional) to be set in package Makefiles: +# +# RUST_HOST_FEATURES - list of options, default empty +# +# Space or comma separated list of features to activate +# +# e.g. RUST_HOST_FEATURES:=enable-foo,with-bar + ifeq ($(origin RUST_INCLUDE_DIR),undefined) RUST_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) endif include $(RUST_INCLUDE_DIR)/rust-values.mk +CARGO_HOST_VARS= \ + $(CARGO_HOST_CONFIG_VARS) \ + CC=$(HOSTCC_NOCACHE) \ + MAKEFLAGS="$(HOST_JOBS)" + # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Host/Compile/Cargo - ( \ - cd $(HOST_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - CC=$(HOSTCC_NOCACHE) \ - cargo install -v \ - --profile stripped \ - $(if $(RUST_PKG_FEATURES),--features "$(RUST_PKG_FEATURES)") \ - --root $(HOST_INSTALL_DIR) \ - --path "$(if $(strip $(1)),$(strip $(1)),.)" $(2) ; \ - ) + +$(CARGO_HOST_VARS) \ + cargo install -v \ + --profile $(CARGO_HOST_PROFILE) \ + $(if $(RUST_HOST_FEATURES),--features "$(RUST_HOST_FEATURES)") \ + --root $(HOST_INSTALL_DIR) \ + --path "$(HOST_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ + $(if $(filter --jobserver%,$(HOST_JOBS)),,-j1) \ + $(2) endef define Host/Uninstall/Cargo - ( \ - cd $(HOST_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - CC=$(HOSTCC_NOCACHE) \ - cargo uninstall -v \ - --root $(HOST_INSTALL_DIR) || true ; \ - ) + +$(CARGO_HOST_VARS) \ + cargo uninstall -v \ + --root $(HOST_INSTALL_DIR) \ + || true endef define RustBinHostBuild diff --git a/rust/rust-package.mk b/rust/rust-package.mk index 955b37c29..24341d706 100644 --- a/rust/rust-package.mk +++ b/rust/rust-package.mk @@ -15,28 +15,22 @@ ifeq ($(origin RUST_INCLUDE_DIR),undefined) endif include $(RUST_INCLUDE_DIR)/rust-values.mk -# Support only a subset for now. -RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) +CARGO_PKG_VARS= \ + $(CARGO_PKG_CONFIG_VARS) \ + CC=$(HOSTCC_NOCACHE) \ + MAKEFLAGS="$(PKG_JOBS)" # $(1) path to the package (optional) # $(2) additional arguments to cargo (optional) define Build/Compile/Cargo - ( \ - cd $(PKG_BUILD_DIR) ; \ - export PATH="$(CARGO_HOME)/bin:$(PATH)" ; \ - CARGO_HOME=$(CARGO_HOME) \ - TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUST_CFLAGS)" \ - TARGET_CC=$(TARGET_CC_NOCACHE) \ - CC=$(HOSTCC_NOCACHE) \ - $(CARGO_VARS) \ - cargo install -v \ - --profile stripped \ - --target $(RUSTC_TARGET_ARCH) \ - $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ - --root $(PKG_INSTALL_DIR) \ - --path "$(if $(strip $(1)),$(strip $(1)),.)" \ - $(2) ; \ - ) + +$(CARGO_PKG_VARS) \ + cargo install -v \ + --profile $(CARGO_PKG_PROFILE) \ + $(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \ + --root $(PKG_INSTALL_DIR) \ + --path "$(PKG_BUILD_DIR)/$(if $(strip $(1)),$(strip $(1)))" \ + $(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \ + $(2) endef define RustBinPackage diff --git a/rust/rust-values.mk b/rust/rust-values.mk index aaa520d57..534aaa02a 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -2,25 +2,32 @@ # # Copyright (C) 2023 Luca Barbato and Donald Hoskins +# Clear environment variables which should be handled internally, +# as users might configure their own env on the host + +# CCache +unexport RUSTC_WRAPPER + # Rust Environmental Vars -CONFIG_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) -RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(CONFIG_HOST_SUFFIX) -CARGO_HOME:=$(STAGING_DIR)/host/cargo -CARGO_VARS:= +RUSTC_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) +RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(RUSTC_HOST_SUFFIX) +CARGO_HOME:=$(DL_DIR)/cargo ifeq ($(CONFIG_USE_MUSL),y) -# Force linking of the SSP library for musl -ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR - ifeq ($(strip $(PKG_SSP)),1) - RUSTC_LDFLAGS += -lssp_nonshared + # Force linking of the SSP library for musl + ifdef CONFIG_PKG_CC_STACKPROTECTOR_REGULAR + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS+=-lssp_nonshared + endif + endif + ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG + ifeq ($(strip $(PKG_SSP)),1) + RUSTC_LDFLAGS+=-lssp_nonshared + endif endif endif -ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG - ifeq ($(strip $(PKG_SSP)),1) - TARGET_CFLAGS += -lssp_nonshared - endif -endif -endif + +CARGO_RUSTFLAGS+=-Ctarget-feature=-crt-static $(RUSTC_LDFLAGS) ifeq ($(HOST_OS),Darwin) ifeq ($(HOST_ARCH),arm64) @@ -51,9 +58,47 @@ ifeq ($(ARCH),arm) ifeq ($(CONFIG_HAS_FPU),y) RUSTC_TARGET_ARCH:=$(subst musleabi,musleabihf,$(RUSTC_TARGET_ARCH)) + RUSTC_TARGET_ARCH:=$(subst gnueabi,gnueabihf,$(RUSTC_TARGET_ARCH)) endif endif -#ifeq ($(ARCH),aarch64) -# RUST_CFLAGS:=-mno-outline-atomics -#endif +ifeq ($(ARCH),aarch64) + RUSTC_CFLAGS:=-mno-outline-atomics +endif + +# Support only a subset for now. +RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) + +ifneq ($(CONFIG_RUST_SCCACHE),) + RUST_SCCACHE_DIR:=$(if $(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(call qstrip,$(CONFIG_RUST_SCCACHE_DIR)),$(TOPDIR)/.sccache) + + RUST_SCCACHE_VARS:= \ + CARGO_INCREMENTAL=0 \ + RUSTC_WRAPPER=sccache \ + SCCACHE_DIR=$(RUST_SCCACHE_DIR) +endif + +CARGO_HOST_CONFIG_VARS= \ + $(RUST_SCCACHE_VARS) \ + CARGO_HOME=$(CARGO_HOME) + +CARGO_HOST_PROFILE:=release + +CARGO_PKG_CONFIG_VARS= \ + $(RUST_SCCACHE_VARS) \ + CARGO_BUILD_TARGET=$(RUSTC_TARGET_ARCH) \ + CARGO_HOME=$(CARGO_HOME) \ + CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ + CARGO_PROFILE_RELEASE_DEBUG=false \ + CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=false \ + CARGO_PROFILE_RELEASE_LTO=true \ + CARGO_PROFILE_RELEASE_OPT_LEVEL=z \ + CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS=true \ + CARGO_PROFILE_RELEASE_PANIC=unwind \ + CARGO_PROFILE_RELEASE_RPATH=false \ + CARGO_TARGET_$(subst -,_,$(call toupper,$(RUSTC_TARGET_ARCH)))_LINKER=$(TARGET_CC_NOCACHE) \ + RUSTFLAGS="$(CARGO_RUSTFLAGS)" \ + TARGET_CC=$(TARGET_CC_NOCACHE) \ + TARGET_CFLAGS="$(TARGET_CFLAGS) $(RUSTC_CFLAGS)" + +CARGO_PKG_PROFILE:=$(if $(CONFIG_DEBUG),dev,release) diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile index 519722921..10e6146a6 100644 --- a/shadowsocks-rust/Makefile +++ b/shadowsocks-rust/Makefile @@ -8,13 +8,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=shadowsocks-rust -ifneq ($(word 1,$(subst ., ,$(LINUX_VERSION))),"5") - PKG_VERSION:=1.17.1 - PKG_HASH:=97a1c8ebf7fd19de94cd6d0dfee398667e1f4e131ec8a37ecb7c3191af7cc75e -else - PKG_VERSION:=1.18.0 - PKG_HASH:=e854743ecef9ab3b371fdcb139e6f4452831b487d449c97c2129abbf4f51e863 -endif +PKG_VERSION:=1.18.0 +PKG_HASH:=e854743ecef9ab3b371fdcb139e6f4452831b487d449c97c2129abbf4f51e863 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz @@ -29,11 +24,7 @@ PKG_BUILD_DEPENDS:=rust/host RUST_PKG_FEATURES:=local-redir include $(INCLUDE_DIR)/package.mk -ifneq ($(word 1,$(subst ., ,$(LINUX_VERSION))),"5") include $(TOPDIR)/feeds/openmptcprouter/rust/rust-package.mk -else -include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk -endif define Package/shadowsocks-rust/Default define Package/shadowsocks-rust-$(1) From 9b6e4efe7f38eaca031495249480bb48755d40e6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 11 Feb 2024 19:24:52 +0100 Subject: [PATCH 1405/2059] Add image compilation of z8102ax and fix github action --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 89227b20e..e60c22d33 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w, rpi5] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w, rpi5, z8102ax-128m] OMR_KERNEL: [5.4, 6.1] runs-on: ubuntu-latest continue-on-error: true @@ -86,7 +86,7 @@ jobs: run: | make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source target/install -j$(nproc) || make IGNORE_ERRORS=m -C $OMR_TARGET/$OMR_KERNEL/source target/install -j1 V=s - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.OMR_TARGET }} path: /home/runner/work/omr/${{ matrix.OMR_TARGET }}/${{ matrix.OMR_KERNEL }}/source/bin From b8178a879e3274f3686de605ea43122e4665b963 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 12 Feb 2024 08:20:01 +0100 Subject: [PATCH 1406/2059] Fix Github upload artifact config --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e60c22d33..f539ae961 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -90,6 +90,7 @@ jobs: with: name: ${{ matrix.OMR_TARGET }} path: /home/runner/work/omr/${{ matrix.OMR_TARGET }}/${{ matrix.OMR_KERNEL }}/source/bin + overwrite: true - if: steps.branch_name.outputs.SOURCE_BRANCH == '' name: Deploy - Create directory uses: ysurac/ssh-action@master From 7935b10b24b2e98d8dcc5002edbeae7e2cb22a69 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 12 Feb 2024 15:31:36 +0100 Subject: [PATCH 1407/2059] Really fix Rust for kernel 5.4 --- openmptcprouter-full/Makefile | 2 +- rust/Makefile | 4 +-- .../0003-bump-libc-deps-to-0.2.146.patch | 28 +++++++++---------- rust/rust-values.mk | 3 +- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index a3aec2279..9422b75a6 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -87,7 +87,7 @@ MY_DEPENDS := \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ - !LINUX_5_4:shadowsocks-rust-sslocal !LINUX_5_4:shadowsocks-rust-ssservice !LINUX_5_4:shadowsocks-rust-config-nft !LINUX_5_4:luci-app-shadowsocks-rust \ + shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust \ luci-proto-external omr-schedule jq luci-app-ddns # shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust \ diff --git a/rust/Makefile b/rust/Makefile index 1555d10b7..1b400409e 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -100,9 +100,7 @@ endef define Host/Install ( \ cd $(HOST_BUILD_DIR)/build/dist ; \ - for targz in *.tar.gz; do \ - $(STAGING_DIR_HOST)/bin/libdeflate-gzip -dc "$$$$targz" | tar -xf - ; \ - done ; \ + find -iname "*.tar.gz" -exec tar -xzf {} \; ; \ find . -mindepth 2 -maxdepth 2 -type f -name install.sh \ -execdir bash '{}' --prefix=$(STAGING_DIR)/host --disable-ldconfig \; ; \ ) diff --git a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch index bb131d23f..a1a46ddfe 100644 --- a/rust/patches/0003-bump-libc-deps-to-0.2.146.patch +++ b/rust/patches/0003-bump-libc-deps-to-0.2.146.patch @@ -7,10 +7,10 @@ This patch bumps all libc dependencies and checksums to 0.2.147, which includes [[package]] name = "libc" -version = "0.2.126" -+version = "0.2.147" ++version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "memchr" @@ -21,10 +21,10 @@ This patch bumps all libc dependencies and checksums to 0.2.147, which includes [[package]] name = "libc" -version = "0.2.138" -+version = "0.2.147" ++version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -35,10 +35,10 @@ This patch bumps all libc dependencies and checksums to 0.2.147, which includes [[package]] name = "libc" -version = "0.2.141" -+version = "0.2.147" ++version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "num_cpus" @@ -49,10 +49,10 @@ This patch bumps all libc dependencies and checksums to 0.2.147, which includes [[package]] name = "libc" -version = "0.2.140" -+version = "0.2.147" ++version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "lindera" @@ -63,10 +63,10 @@ This patch bumps all libc dependencies and checksums to 0.2.147, which includes [[package]] name = "libc" -version = "0.2.140" -+version = "0.2.147" ++version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "lock_api" @@ -77,10 +77,10 @@ This patch bumps all libc dependencies and checksums to 0.2.147, which includes [[package]] name = "libc" -version = "0.2.140" -+version = "0.2.147" ++version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libffi" @@ -91,10 +91,10 @@ This patch bumps all libc dependencies and checksums to 0.2.147, which includes [[package]] name = "libc" -version = "0.2.141" -+version = "0.2.147" ++version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" -+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" ++checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" diff --git a/rust/rust-values.mk b/rust/rust-values.mk index 534aaa02a..749286776 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -11,7 +11,8 @@ unexport RUSTC_WRAPPER # Rust Environmental Vars RUSTC_HOST_SUFFIX:=$(word 4, $(subst -, ,$(GNU_HOST_NAME))) RUSTC_HOST_ARCH:=$(HOST_ARCH)-unknown-linux-$(RUSTC_HOST_SUFFIX) -CARGO_HOME:=$(DL_DIR)/cargo +#CARGO_HOME:=$(DL_DIR)/cargo +CARGO_HOME:=$(STAGING_DIR)/cargo ifeq ($(CONFIG_USE_MUSL),y) # Force linking of the SSP library for musl From ee768cc1540a4d3be6d36816cb6d5c61851cb71a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 12 Feb 2024 15:55:34 +0100 Subject: [PATCH 1408/2059] Fix compilation for z8102ax --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f539ae961..ada11f93c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w, rpi5, z8102ax-128m] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w, rpi5, z8102ax_128m] OMR_KERNEL: [5.4, 6.1] runs-on: ubuntu-latest continue-on-error: true From feb43aa21783abfca5c6d0a6e8c07151827e01ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 13 Feb 2024 15:00:26 +0100 Subject: [PATCH 1409/2059] Fix openmptcprouter-vps fix, and no need to get config for proxy/vpn not installed --- .../files/etc/init.d/openmptcprouter-vps | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 544a4ff74..ef12d21fd 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2261,15 +2261,15 @@ _config_service() { if [ "$user_permission" != "ro" ]; then #config_load shadowsocks-libev #config_foreach _set_ss_server_vps server - _set_ss_server_vps - _set_ssgo_server_vps - _set_v2ray_server_vps - _set_xray_server_vps - [ -z "$(_set_glorytun_vps)" ] && error=1 - [ -z "$(_set_openvpn_vps)" ] && error=1 - [ -z "$(_set_mlvpn_vps)" ] && error=1 + [ -n "$(uci -q get shadowsocks-libev)" ] && _set_ss_server_vps + [ -n "$(uci -q get shadowsocks-rust)" ] && _set_ssgo_server_vps + [ -n "$(uci -q get v2ray)" ] && _set_v2ray_server_vps + [ -n "$(uci -q get xray)" ] && _set_xray_server_vps + ([ -n "$(uci -q get glorytun)" ] || [ -n "$(uci -q get glorytun-udp)" ]) && [ -z "$(_set_glorytun_vps)" ] && error=1 + [ -n "$(uci -q get openvpn)" ] && [ -z "$(_set_openvpn_vps)" ] && error=1 + [ -n "$(uci -q get mlvpn)" ] && [ -z "$(_set_mlvpn_vps)" ] && error=1 _set_vps_firewall - [ -z "$(_set_wireguard_vps)" ] && error=1 + [ -n "$(uci -q get wireguard)" ] && [ -z "$(_set_wireguard_vps)" ] && error=1 fi _backup_list redirect_port="0" @@ -2341,7 +2341,7 @@ token() { } _fix_server() { - uci -q rename openmptcprouter.$1=server + uci -q set openmptcprouter.$1=server } start_service() { From 6cf9c5ca6040591be2d7f6eb0cc3d227e2db254e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 13 Feb 2024 15:15:38 +0100 Subject: [PATCH 1410/2059] Disable mno-outline-atomics for arm64 --- rust/rust-values.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/rust-values.mk b/rust/rust-values.mk index 749286776..da9bf695e 100644 --- a/rust/rust-values.mk +++ b/rust/rust-values.mk @@ -63,9 +63,9 @@ ifeq ($(ARCH),arm) endif endif -ifeq ($(ARCH),aarch64) - RUSTC_CFLAGS:=-mno-outline-atomics -endif +#ifeq ($(ARCH),aarch64) +# RUSTC_CFLAGS:=-mno-outline-atomics +#endif # Support only a subset for now. RUST_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||mips64||mips64el||mipsel||powerpc64||riscv64||x86_64) From 3ff67a3563cf333a61081f7dfac5e7804ec65fe7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 14 Feb 2024 09:27:29 +0100 Subject: [PATCH 1411/2059] Fix z8102ax GPIO set on all cases --- z8102/files/etc/init.d/z8102 | 42 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index 67f2cc068..fc8aad8f0 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -16,42 +16,60 @@ start_service() #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - echo "0" > /sys/class/gpio/sim1/value - #gpioset `gpiofind "sim1"`=0 + if [ -e /sys/class/gpio/sim1/value ]; then + echo "0" > /sys/class/gpio/sim1/value + else + gpioset `gpiofind "sim1"`=0 + fi # sim 2 #i=462 #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - echo "0" > /sys/class/gpio/sim2/value - #gpioset `gpiofind "sim2"`=0 + if [ -e /sys/class/gpio/sim2/value ]; then + echo "0" > /sys/class/gpio/sim2/value + else + gpioset `gpiofind "sim2"`=0 + fi # stop modem 1 #i=459 #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - echo "0" > /sys/class/gpio/modem1/value - #gpioset `gpiofind "modem1"`=0 + if [ -e /sys/class/gpio/modem1/value ]; then + echo "0" > /sys/class/gpio/modem1/value + else + gpioset `gpiofind "modem1"`=0 + fi # stop modem 2 #i=460 #echo $i > /sys/class/gpio/export #echo "out" > /sys/class/gpio/gpio${i}/direction #echo "0" > /sys/class/gpio/gpio${i}/value - echo "0" > /sys/class/gpio/modem2/value - #gpioset `gpiofind "modem2"`=0 + if [ -e /sys/class/gpio/modem2/value ]; then + echo "0" > /sys/class/gpio/modem2/value + else + gpioset `gpiofind "modem2"`=0 + fi sleep 1 # run modem 1 #i=459 #echo "1" > /sys/class/gpio/gpio${i}/value - echo "1" > /sys/class/gpio/modem1/value - #gpioset `gpiofind "modem1"`=1 + if [ -e /sys/class/gpio/modem1/value ]; then + echo "1" > /sys/class/gpio/modem1/value + else + gpioset `gpiofind "modem1"`=1 + fi sleep 3 # run modem 2 #i=460 #echo "1" > /sys/class/gpio/gpio${i}/value - echo "1" > /sys/class/gpio/modem2/value - #gpioset `gpiofind "modem2"`=1 + if [ -e /sys/class/gpio/modem2/value ]; then + echo "1" > /sys/class/gpio/modem2/value + else + gpioset `gpiofind "modem2"`=1 + fi } From 66146c3b2bcabf66049d16915fd2d3f964d6c716 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 18 Feb 2024 20:03:15 +0100 Subject: [PATCH 1412/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3171 --- omr-bypass/files/etc/init.d/omr-bypass-nft | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index a6a8a01ec..be97d353e 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -444,7 +444,7 @@ _bypass_proto_without_ndpi() { uci -q add_list firewall.bypass_$proto.entry=$ip else #ipset -q add omr_dst_bypass_$intf $ip - uci -q add_list firewall.omr_dst_bypass_$intf_4.entry=$ip + uci -q add_list firewall.omr_dst_bypass_${intf}_4.entry=$ip fi elif [ "$valid_ip6" = "ok" ]; then if [ "$vpn" != "1" ]; then @@ -452,7 +452,7 @@ _bypass_proto_without_ndpi() { uci -q add_list firewall.bypass6_$proto.entry=$ip else #ipset -q add omr6_dst_bypass_$intf $ip - uci -q add_list firewall.omr6_dst_bypass_$intf_4.entry=$ip + uci -q add_list firewall.omr_dst_bypass_${intf}_6.entry=$ip fi fi done @@ -572,6 +572,9 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_4=ipset set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' + set firewall.omr_dst_bypass_${intf}_6=ipset + set firewall.omr_dst_bypass_${intf}_6.name="omr_dst_bypass_${intf}_6" + set firewall.omr_dst_bypass_${intf}_6.match='dest_ip' EOF #echo "firewall omr_dst_bypass rules" if [ "$disableipv6" = "0" ]; then From 8dbeb84f9a446a80abcc9127c3e24b914f9805cb Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 18 Feb 2024 20:10:27 +0100 Subject: [PATCH 1413/2059] Enabled ipset by default in omr-bypass --- omr-bypass/files/etc/init.d/omr-bypass-nft | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index be97d353e..6c38601d2 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -572,9 +572,11 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_4=ipset set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' + set firewall.omr_dst_bypass_${intf}_4.enabled='1' set firewall.omr_dst_bypass_${intf}_6=ipset set firewall.omr_dst_bypass_${intf}_6.name="omr_dst_bypass_${intf}_6" set firewall.omr_dst_bypass_${intf}_6.match='dest_ip' + set firewall.omr_dst_bypass_${intf}_6.enabled='1' EOF #echo "firewall omr_dst_bypass rules" if [ "$disableipv6" = "0" ]; then @@ -689,8 +691,10 @@ _intf_rule() { _intf_rule_xray_rules fi - uci -q set omr-bypass.$intf=interface - uci -q set omr-bypass.$intf.id=$count + if [ "$intf" != "all" ]; then + uci -q set omr-bypass.$intf=interface + uci -q set omr-bypass.$intf.id=$count + fi } _bypass_ip_set() { From 72c8e134fdcb5540ff5a1a25626261dd2e895668 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sun, 18 Feb 2024 20:45:00 +0100 Subject: [PATCH 1414/2059] Maybe fix https://github.com/Ysurac/openmptcprouter/issues/3173 --- .../files/shadowsocks-libev.init-nft | 40 +++++++++++++------ .../files/shadowsocks-rust.init-nft | 18 ++++++++- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index f8121fe7c..c69eade3c 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -11,6 +11,8 @@ START=99 EXTRA_COMMANDS="rules_up rules_down rules_exist" +. /usr/lib/unbound/iptools.sh + ss_confdir=/var/etc/shadowsocks-libev ss_bindir=/usr/bin @@ -45,17 +47,17 @@ ss_mkjson_server_conf_() { [ -z "$plugin" ] || json_add_string plugin "$plugin" [ -z "$plugin_opts" ] || json_add_string plugin_opts "$plugin_opts" if [ "$obfs" = 1 ]; then - if [ "$obfs_plugin" = "obfs" ]; then - obfs_options="obfs=$obfs_type" - [ -z "$obfs_host" ] || obfs_options="$obfs_options;obfs-host=$obfs_host" - [ -z "$obfs_uri" ] || obfs_options="$obfs_options;obfs-uri=$obfs_uri" - [ "$fast_open" = 1 ] && obfs_options="$obfs_options;fast-open" - [ "$mptcp" = 1 ] && obfs_options="$obfs_options;mptcp" - [ -z "$timeout" ] || obfs_options="$obfs_options;t=$timeout" - json_add_string plugin "/usr/bin/obfs-local" - json_add_string plugin_opts "$obfs_options" - fi - if [ "$obfs_plugin" = "v2ray" ]; then + if [ "$obfs_plugin" = "obfs" ]; then + obfs_options="obfs=$obfs_type" + [ -z "$obfs_host" ] || obfs_options="$obfs_options;obfs-host=$obfs_host" + [ -z "$obfs_uri" ] || obfs_options="$obfs_options;obfs-uri=$obfs_uri" + [ "$fast_open" = 1 ] && obfs_options="$obfs_options;fast-open" + [ "$mptcp" = 1 ] && obfs_options="$obfs_options;mptcp" + [ -z "$timeout" ] || obfs_options="$obfs_options;t=$timeout" + json_add_string plugin "/usr/bin/obfs-local" + json_add_string plugin_opts "$obfs_options" + fi + if [ "$obfs_plugin" = "v2ray" ]; then obfs_options="loglevel=default" [ "$obfs_type" = "tls" ] && obfs_options="tls" [ -z "$obfs_host" ] || obfs_options="$obfs_options;host=$obfs_host" @@ -135,7 +137,11 @@ ss_rules_cb() { if [ "$cfgtype" = ss_redir ]; then config_get cfgserver "$cfg" server config_get server "$cfgserver" server - ss_redir_servers="$ss_redir_servers $server" + if [ -z "$ss_redir_servers" ]; then + ss_redir_servers="$server" + else + ss_redir_servers="$ss_redir_servers $server" + fi if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then eval "ss_rules_redir_tcp_$cfg=$local_port" fi @@ -193,7 +199,15 @@ ss_rules_nft_gen() { eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" fi [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1 - remote_servers="$(echo $ss_redir_servers \ + + if [ -z "$(echo $ss_redir_servers | grep ' ')" ]; then + valid_ip4=$( valid_subnet4 $ss_redir_servers) + valid_ip6=$( valid_subnet6 $ss_redir_servers) + if [ "$valid_ip4" = "ok" ] || [ "$valid_ip6" = "ok" ]; then + remote_servers=$ss_redir_servers + fi + fi + [ -z "$remote_servers" ] && remote_servers="$(echo $ss_redir_servers \ | tr ' ' '\n' \ | sort -u \ | xargs -n 1 resolveip \ diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index 7a48c152f..158df38f7 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -11,6 +11,8 @@ START=99 EXTRA_COMMANDS="rules_up rules_down rules_exist" +. /usr/lib/unbound/iptools.sh + ss_confdir=/var/etc/shadowsocks-rust ss_bindir=/usr/bin @@ -108,7 +110,11 @@ ss_rules_cb() { if [ "$cfgtype" = ss_redir ]; then config_get cfgserver "$cfg" server config_get server "$cfgserver" server - ss_redir_servers="$ss_redir_servers $server" + if [ -z "$ss_redir_servers" ]; then + ss_redir_servers="$server" + else + ss_redir_servers="$ss_redir_servers $server" + fi if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then eval "ss_rules_redir_tcp_$cfg=$local_port" fi @@ -164,7 +170,15 @@ ss_rules_nft_gen() { fi [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1 - remote_servers="$(echo $ss_redir_servers \ + + if [ -z "$(echo $ss_redir_servers | grep ' ')" ]; then + valid_ip4=$( valid_subnet4 $ss_redir_servers) + valid_ip6=$( valid_subnet6 $ss_redir_servers) + if [ "$valid_ip4" = "ok" ] || [ "$valid_ip6" = "ok" ]; then + remote_servers=$ss_redir_servers + fi + fi + [ -z "$remote_servers" ] && remote_servers="$(echo $ss_redir_servers \ | tr ' ' '\n' \ | sort -u \ | xargs -n 1 resolveip \ From 663ff604d4daddfbf99e1a0970fef09ad30573e4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Feb 2024 12:11:07 +0100 Subject: [PATCH 1415/2059] Fix Status server IP in some cases --- .../luasrc/view/openmptcprouter/wanstatus.htm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 074224fbc..8594dd5cb 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -260,9 +260,12 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm } else if (mArray.openmptcprouter.wan_addr6 != "" && mArray.openmptcprouter.service_addr == "127.0.0.1") { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr6); - } else if (mArray.openmptcprouter.direct_output == false) + } else if (mArray.openmptcprouter.wan_addr6 != "" && mArray.openmptcprouter.direct_output == false) { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr6); + } else if (mArray.openmptcprouter.wan_addr != "" && mArray.openmptcprouter.direct_output == false) + { + var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr); } else if (mArray.openmptcprouter.wan_addr != "" && mArray.openmptcprouter.direct_output == true) { var title = String.format("%s (%s)", _('Direct output'), mArray.openmptcprouter.wan_addr); From dad8e2cfe7b8667cd5d3ec6fb77386eaf3acbf31 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Feb 2024 14:17:15 +0100 Subject: [PATCH 1416/2059] Update luci-theme-argon --- luci-theme-argon/Makefile | 6 +- luci-theme-argon/README.md | 215 +- luci-theme-argon/README_ZH.md | 235 +- luci-theme-argon/RELEASE.md | 73 + luci-theme-argon/RELEASE_ZH.md | 71 + .../htdocs/luci-static/argon/css/cascade.css | 2 +- .../htdocs/luci-static/argon/css/dark.css | 2 +- .../htdocs/luci-static/argon/favicon.ico | Bin 15406 -> 0 bytes .../htdocs/luci-static/argon/favicon.png | Bin 0 -> 535 bytes .../argon/icon/android-icon-192x192.png | Bin 6411 -> 8300 bytes .../argon/icon/apple-icon-144x144.png | Bin 5222 -> 6568 bytes .../argon/icon/apple-icon-60x60.png | Bin 2561 -> 3590 bytes .../argon/icon/apple-icon-72x72.png | Bin 2877 -> 4003 bytes .../htdocs/luci-static/argon/icon/arrow.svg | 4 +- .../luci-static/argon/icon/favicon-16x16.png | Bin 1019 -> 2069 bytes .../luci-static/argon/icon/favicon-32x32.png | Bin 1720 -> 2604 bytes .../luci-static/argon/icon/favicon-96x96.png | Bin 3650 -> 4805 bytes .../htdocs/luci-static/argon/icon/favicon.png | Bin 0 -> 535 bytes .../luci-static/argon/icon/manifest.json | 78 +- .../argon/icon/ms-icon-144x144.png | Bin 5222 -> 6568 bytes .../htdocs/luci-static/argon/icon/spinner.svg | 4 +- .../htdocs/luci-static/argon/img/argon.svg | 98 +- .../luci-static/argon/img/volume_high.svg | 4 +- .../luci-static/argon/img/volume_off.svg | 4 +- .../luci-static/argon/less/cascade.less | 4063 --------------- .../luci-static/resources/menu-argon.js | 2 +- luci-theme-argon/less/cascade.less | 4616 +++++++++++++++++ .../luci-static/argon => }/less/dark.less | 1984 ++++--- .../luci-static/argon => }/less/fonts.less | 4 +- .../luci-static/argon => }/less/pure-min.less | 0 .../luasrc/view/themes/argon/footer.htm | 4 +- .../luasrc/view/themes/argon/footer_login.htm | 4 +- .../luasrc/view/themes/argon/header.htm | 108 +- .../luasrc/view/themes/argon/header_login.htm | 114 +- .../view/themes/argon/out_footer_login.htm | 27 - .../luasrc/view/themes/argon/sysauth.htm | 73 +- .../root/usr/libexec/argon/bing_wallpaper | 52 - .../root/usr/libexec/argon/online_wallpaper | 105 + 38 files changed, 6532 insertions(+), 5420 deletions(-) create mode 100644 luci-theme-argon/RELEASE.md create mode 100644 luci-theme-argon/RELEASE_ZH.md delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/favicon.ico create mode 100644 luci-theme-argon/htdocs/luci-static/argon/favicon.png create mode 100644 luci-theme-argon/htdocs/luci-static/argon/icon/favicon.png delete mode 100644 luci-theme-argon/htdocs/luci-static/argon/less/cascade.less create mode 100644 luci-theme-argon/less/cascade.less rename luci-theme-argon/{htdocs/luci-static/argon => }/less/dark.less (53%) rename luci-theme-argon/{htdocs/luci-static/argon => }/less/fonts.less (99%) rename luci-theme-argon/{htdocs/luci-static/argon => }/less/pure-min.less (100%) delete mode 100644 luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm delete mode 100755 luci-theme-argon/root/usr/libexec/argon/bing_wallpaper create mode 100755 luci-theme-argon/root/usr/libexec/argon/online_wallpaper diff --git a/luci-theme-argon/Makefile b/luci-theme-argon/Makefile index 44702ea88..89b7966ec 100644 --- a/luci-theme-argon/Makefile +++ b/luci-theme-argon/Makefile @@ -8,8 +8,10 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Argon Theme LUCI_DEPENDS:=+curl +jsonfilter -PKG_VERSION:=2.2.9.4 -PKG_RELEASE:=20220425 +PKG_VERSION:=2.3.1 +PKG_RELEASE:=20230420 + +CONFIG_LUCI_CSSTIDY:= include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-theme-argon/README.md b/luci-theme-argon/README.md index 5eb85b2c3..983703cda 100644 --- a/luci-theme-argon/README.md +++ b/luci-theme-argon/README.md @@ -1,114 +1,157 @@ + + +[license]: /LICENSE +[license-badge]: https://img.shields.io/github/license/jerrykuku/luci-theme-argon?style=flat-square&a=1 +[prs]: https://github.com/jerrykuku/luci-theme-argon/pulls +[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square +[issues]: https://github.com/jerrykuku/luci-theme-argon/issues/new +[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square +[release]: https://github.com/jerrykuku/luci-theme-argon/releases +[release-badge]: https://img.shields.io/github/v/release/jerrykuku/luci-theme-argon?include_prereleases&style=flat-square +[download]: https://github.com/jerrykuku/luci-theme-argon/releases +[download-badge]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total?style=flat-square +[contact]: https://t.me/jerryk6 +[contact-badge]: https://img.shields.io/badge/Contact-telegram-blue?style=flat-square +[en-us-link]: /README.md +[zh-cn-link]: /README_ZH.md +[en-us-release-log]: /RELEASE.md +[zh-cn-release-log]: /RELEASE_ZH.md +[config-link]: https://github.com/jerrykuku/luci-app-argon-config/releases +[lede]: https://github.com/coolsnowwolf/lede +[official]: https://github.com/openwrt/openwrt +[immortalwrt]: https://github.com/immortalwrt/immortalwrt +
    - -

    - A new LuCI theme for OpenWrt -

    -

    - Argon is a clean HTML5 theme for LuCI. Users may
    setup their own favorite logins, including beautiful
    pics and customized mp4 videos.

    -

    - - - - - - - - - - - - - - -
    -
    -
    - + + +# A brand new OpenWrt LuCI theme + +Argon is **a clean and tidy OpenWrt LuCI theme** that allows
    +users to customize their login interface with images or videos. +It also supports automatic and manual switching between light and dark modes. + +[![license][license-badge]][license] +[![prs][prs-badge]][prs] +[![issues][issues-badge]][issues] +[![release][release-badge]][release] +[![download][download-badge]][download] +[![contact][contact-badge]][contact] + +**English** | +[简体中文][zh-cn-link] + +[Key Features](#key-features) • +[Branch](#branch-introduction) • +[Version History](#version-history) • +[Getting started](#getting-started) • +[Screenshots](#screenshots) • +[Contributors](#contributors) • +[Credits](#credits) + +
    -
    English | [简体中文](README_ZH.md) +## Key Features -## Notice -It is strongly recommended to use the Chrome browser. Some new css3 features are used in the theme, and currently only Chrome has the best compatibility. -The mainline version of IE series currently has bugs to be resolved. -FireFox does not enable the backdrop-filter by default, see here for the opening method: https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter +- Clean Layout. +- Adapted to mobile display. +- Customizable theme colors. +- Support for using Bing images as login background. +- Support for custom uploading of images or videos as login background. +- Automatically switch between light and dark modes with the system, and can also be set to a fixed mode. +- Settings plugin with extensions [luci-app-argon-config][config-link] -v2.x.x Adapt to official mainline snapshot. -You can checkout branch 18.06 for OpenWRT 18.06 or lean 19.07. +## Branch Introduction -## Update Log 2021.10.16 v2.2.9 +There are currently two main branches that are adapted to different versions of the **OpenWrt** source code. +The table below will provide a detailed introduction: -- 【v2.2.9】Fix the problem that the menu could not pop up in mobile mode -- 【v2.2.9】Unify the settings of css spacing -- 【v2.2.9】Refactored the code of the login page -- 【v2.2.8】Fix the problem that the Minify Css option is turned on when compiling, which causes the frosted glass effect to be invalid and the logo font is lost. -- 【v2.2.5】New config app for argon theme. You can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.[Chrome is recommended] [Download](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) -- 【v2.2.5】Automatically set as the default theme when compiling. -- 【v2.2.5】Modify the file structure to adapt to luci-app-argon-config. The old method of turning on dark mode is no longer applicable, please use it with luci-app-argon-config. -- 【v2.2.5】Adapt to Koolshare lede 2.3.6。 -- 【v2.2.5】Fix some Bug。 -- 【v2.2.4】Fix the problem that the login background cannot be displayed on some phones. -- 【v2.2.4】Remove the dependency of luasocket. -- 【v2.2.3】Fix Firmware flash page display error in dark mode. -- 【v2.2.3】Update font icon, add a default icon of undefined menu. -- 【v2.2.2】Add custom login background,put your image (allow png jpg gif) or MP4 video into /www/luci-static/argon/background, random change. -- 【v2.2.2】Add force dark mode, login ssh and type "touch /etc/dark" to open dark mode. -- 【v2.2.2】Add a volume mute button for video background, default is muted. -- 【v2.2.2】fix login page when keyboard show the bottom text overlay the button on mobile. -- 【v2.2.2】fix select color in dark mode,and add a style for scrollbar. -- 【v2.2.2】jquery update to v3.5.1. -- 【v2.2.2】change request bing api method form wget to luasocket (DEPENDS). -- 【v2.2.1】Add blur effect for login form. -- 【v2.2.1】New login theme, Request background imge from bing.com, Auto change everyday. -- 【v2.2.1】New theme icon. -- 【v2.2.1】Add more menu category icon. -- 【v2.2.1】Fix font-size and padding margin. -- 【v2.2.1】Restructure css file. -- 【v2.2.1】Auto adapt to dark mode. +| Branch | Version | Description | Matching source | +| ------ | ------- | ---------------------------------- | --------------------------------------------------------- | +| master | v2.x.x | Support the latest version of LuCI | [Official OpenWrt][official] • [ImmortalWrt][immortalwrt] | +| 18.06 | v1.x.x | Support the 18.06 version of LuCI | [Lean's LEDE][lede] | -## How to build +## Version History -Enter in your openwrt/package/lean or other +The latest version is v2.3.1 [Click here][en-us-release-log] to view the full version history record. -### Lean lede +## Getting started -``` -cd lede/package/lean -rm -rf luci-theme-argon -git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s +### Build for Lean's LEDE project + +```bash +cd lede/package/lean +rm -rf luci-theme-argon +git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git luci-theme-argon +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s ``` -### Openwrt official SnapShots +### Build for OpenWrt official SnapShots and ImmortalWrt -``` +```bash cd openwrt/package -git clone https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s +git clone https://github.com/jerrykuku/luci-theme-argon.git +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s ``` -## How to Install +### Install for LuCI 18.06 ( Lean's LEDE ) -### For Lean openwrt 18.06 LuCI - -``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.3/luci-theme-argon-18.06_1.7.3-20220421_all.ipk +```bash +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.8.2/luci-theme-argon_1.8.2-20230609_all.ipk opkg install luci-theme-argon*.ipk ``` -### For openwrt official 19.07 Snapshots LuCI master +### Install for OpenWrt official SnapShots and ImmortalWrt -``` +```bash opkg install luci-compat opkg install luci-lib-ipkg -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.9/luci-theme-argon_2.2.9-20211016-1_all.ipk +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.3.1/luci-theme-argon_2.3.1_all.ipk opkg install luci-theme-argon*.ipk ``` -![](/Screenshots/screenshot_pc.jpg) -![](/Screenshots/screenshot_phone.jpg) -## Thanks to +### Install luci-app-argon-config -luci-theme-material: https://github.com/LuttyYang/luci-theme-material/ +```bash +wget --no-check-certificate https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.9/luci-app-argon-config_0.9_all.ipk +opkg install luci-app-argon-config*.ipk +``` + +## Notice + +- Chrome browser is highly recommended. There are some new css3 features used in this theme, currently only Chrome has the best compatibility. +- Microsoft has officially retired Internet Explorer, RIP IE🙏Currently, the mainline version of the IE series has bugs that need to be addressed. +- FireFox does not enable the backdrop-filter by default, [see here](https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter) for the opening method. + +## Screenshots + +![desktop](/Screenshots/screenshot_pc.jpg) +![mobile](/Screenshots/screenshot_phone.jpg) + +## Contributors + + + + + +Made with [contrib.rocks](https://contrib.rocks). + +## Related Projects + +- [luci-app-argon-config](https://github.com/jerrykuku/luci-app-argon-config): Argon theme config plugin +- [openwrt-package](https://github.com/jerrykuku/openwrt-package): My OpenWrt package +- [CasaOS](https://github.com/IceWhaleTech/CasaOS): A simple, easy-to-use, elegant open-source Personal Cloud system (My current main project) + +## Credits + +[luci-theme-material](https://github.com/LuttyYang/luci-theme-material/) diff --git a/luci-theme-argon/README_ZH.md b/luci-theme-argon/README_ZH.md index d66866711..fa1bd999a 100644 --- a/luci-theme-argon/README_ZH.md +++ b/luci-theme-argon/README_ZH.md @@ -1,110 +1,157 @@ -
    - -

    - 全新的 Openwrt 主题 -

    -

    - Argon 是一个干净整洁的Openwrt主题,用户可以自定义登录界面,
    包含图片或者视频,同时支持深色浅色的自动与手动切换 -

    + - - - - - - - - - - - - - +[license]: /LICENSE +[license-badge]: https://img.shields.io/github/license/jerrykuku/luci-theme-argon?style=flat-square&a=1 +[prs]: https://github.com/jerrykuku/luci-theme-argon/pulls +[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square +[issues]: https://github.com/jerrykuku/luci-theme-argon/issues/new +[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square +[release]: https://github.com/jerrykuku/luci-theme-argon/releases +[release-badge]: https://img.shields.io/github/v/release/jerrykuku/luci-theme-argon?include_prereleases&style=flat-square +[download]: https://github.com/jerrykuku/luci-theme-argon/releases +[download-badge]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argon/total?style=flat-square +[contact]: https://t.me/jerryk6 +[contact-badge]: https://img.shields.io/badge/Contact-telegram-blue?style=flat-square +[en-us-link]: /README.md +[zh-cn-link]: /README_ZH.md +[en-us-release-log]: /RELEASE.md +[zh-cn-release-log]: /RELEASE_ZH.md +[config-link]: https://github.com/jerrykuku/luci-app-argon-config/releases +[lede]: https://github.com/coolsnowwolf/lede +[official]: https://github.com/openwrt/openwrt +[immortalwrt]: https://github.com/immortalwrt/immortalwrt + +
    + + +# 一个全新的 OpenWrt 主题 + +Argon 是**一款干净整洁的 OpenWrt LuCI 主题**, +允许用户使用图片或视频自定义其登录界面。 +它还支持在浅色模式和深色模式之间自动或手动切换。 + +[![license][license-badge]][license] +[![prs][prs-badge]][prs] +[![issues][issues-badge]][issues] +[![release][release-badge]][release] +[![download][download-badge]][download] +[![contact][contact-badge]][contact] + +[English][en-us-link] | +**简体中文** + +[特色](#特色) • +[分支介绍](#分支介绍) • +[版本历史](#版本历史) • +[快速开始](#快速开始) • +[屏幕截图](#屏幕截图) • +[贡献者](#贡献者) • +[鸣谢](#鸣谢) + +
    -![](/Screenshots/screenshot_pc.jpg) -![](/Screenshots/screenshot_phone.jpg) +## 特色 +- 干净整洁的布局。 +- 适配移动端显示。 +- 可自定义主题颜色。 +- 支持使用 Bing 图片作为登录背景。 +- 支持自定义上传图片或视频作为登录背景。 +- 通过系统自动在明暗模式之间切换,也可设置为固定模式。 +- 带有扩展功能的设置插件 [luci-app-argon-config][config-link] + +## 分支介绍 + +目前有两个主要的分支,适应于不同版本的**OpenWrt**源代码。 +下表为详细的介绍: + +| 分支 | 版本 | 介绍 | 匹配源码 | +| ------ | ------ | --------------------------- | ----------------------------------------------------- | +| master | v2.x.x | 支持最新和比较新版本的 LuCI | [官方 OpenWrt][official] • [ImmortalWrt][immortalwrt] | +| 18.06 | v1.x.x | 支持 18.06 版本的 LuCI | [Lean's LEDE][lede] | + +## 版本历史 + +当前最新的版本为 v2.3.1 [点击这里][zh-cn-release-log]查看完整的版本历史日志. + +## 快速开始 + +### 使用 Lean's LEDE 构建 + +```bash +cd lede/package/lean +rm -rf luci-theme-argon +git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git luci-theme-argon +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s +``` + +### 使用官方 OpenWrt SnapShots 和 ImmortalWrt + +```bash +cd openwrt/package +git clone https://github.com/jerrykuku/luci-theme-argon.git +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s +``` + +### 在 18.06 的 LuCI 上安装 ( Lean's LEDE ) + +```bash +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.8.2/luci-theme-argon_1.8.2-20230609_all.ipk +opkg install luci-theme-argon*.ipk +``` + +### 在官方和 ImmortalWrt 上安装 + +```bash +opkg install luci-compat +opkg install luci-lib-ipkg +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.3.1/luci-theme-argon_2.3.1_all.ipk +opkg install luci-theme-argon*.ipk +``` + +### 安装 luci-app-argon-config + +```bash +wget --no-check-certificate https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.9/luci-app-argon-config_0.9_all.ipk +opkg install luci-app-argon-config*.ipk +``` ## 注意 -强烈建议使用Chrome 浏览器。主题中使用了一些新的css3特性,目前只有Chrome有最佳的兼容性。 -主线版本 IE 系列目前还有Bug有待解决。 -FireFox 默认不开启backdrop-filter,开启方法见这里:https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter -当前master版本基于官方 OpenWrt 19.07.1 稳定版固件进行移植适配。 -v2.x.x 适配主线快照版本。 -v1.x.x 适配18.06 和 Lean Openwrt [如果你是lean代码 请选择这个版本] +- 强烈建议使用 Chrome 浏览器。这个主题中使用了一些新的 css3 功能,目前只有 Chrome 浏览器有最好的兼容性。 +- 微软已正式退役 Internet Explorer,安息吧 IE🙏目前,IE 系列的主线版本有需要解决的错误。 +- FireFox 默认不启用 backdrop-filter,[见这里](https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter)的打开方法。 -## 更新日志 2021.10.16 v2.2.9 +## 屏幕截图 -- 【v2.2.9】修复了在手机模式下无法弹出菜单的bug -- 【v2.2.9】统一css间距的设置 -- 【v2.2.9】重构了登录页面的代码 -- 【v2.2.9】为导航菜单添加滑动效果 -- 【v2.2.8】修复编译时打开Minify Css选项,导致磨砂玻璃效果无效,logo字体丢失的问题 -- 【v2.2.5】全新的设置app.你可以设置argon 主题的登录页面的模糊和透明度,并管理背景图片与视频。[建议使用 Chrome][点击下载](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) -- 【v2.2.5】当编译固件时,将自动设置为默认主题。 -- 【v2.2.5】修改文件结构,以适应luci-app-argon-config,旧的开启暗色模式方法将不再适用,请搭配luci-app-argon-config使用。 -- 【v2.2.5】适配Koolshare lede 2.3.6。 -- 【v2.2.5】修复了一些Bug。 -- 【v2.2.4】修复了在某些手机下图片背景第一次加载不能显示的问题。 -- 【v2.2.4】取消 luasocket 的依赖,无需再担心依赖问题。 -- 【v2.2.3】修正了在暗色模式下,固件刷写弹窗内的显示错误。 -- 【v2.2.3】更新了图标库,为未定义的菜单增加了一个默认的图标。 -- 【v2.2.2】背景文件策略调整为,同时接受 jpg png gif mp4, 自行上传文件至 /www/luci-static/argon/background 图片和视频同时随机。 -- 【v2.2.2】增加强制暗色模式,进入ssh 输入 "touch /etc/dark" 进行开启。 -- 【v2.2.2】视频背景加了一个音量开关,喜欢带声音的可以自行点击开启,默认为静音模式。 -- 【v2.2.2】修复了手机模式下,登录页面出现键盘时,文字覆盖按钮的问题。 -- 【v2.2.2】修正了暗黑模式下下拉选项的背景颜色,同时修改了滚动条的样式。 -- 【v2.2.2】jquery 更新到 v3.5.1。 -- 【v2.2.2】获取Bing Api 的方法从wget 更新到luasocket 并添加依赖。 -- 【v2.2.1】登录背景添加毛玻璃效果。 -- 【v2.2.1】全新的登录界面,图片背景跟随Bing.com,每天自动切换。 -- 【v2.2.1】全新的主题icon。 -- 【v2.2.1】增加多个导航icon。 -- 【v2.2.1】细致的微调了 字号大小边距等等。 -- 【v2.2.1】重构了css文件。 -- 【v2.2.1】自动适应的暗黑模式。 +![desktop](/Screenshots/screenshot_pc.jpg) +![mobile](/Screenshots/screenshot_phone.jpg) -## 如何编译 +## 贡献者 -进入 openwrt/package/lean 或者其他目录 + + + -### Lean源码 +Made with [contrib.rocks](https://contrib.rocks). -``` -cd lede/package/lean -rm -rf luci-theme-argon -git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s -``` +## 相关项目 -### Openwrt 官方源码 +- [luci-app-argon-config](https://github.com/jerrykuku/luci-app-argon-config): Argon 主题的设置插件 +- [openwrt-package](https://github.com/jerrykuku/openwrt-package): 我的 OpenWrt Package +- [CasaOS](https://github.com/IceWhaleTech/CasaOS): 一个简单、易用且优雅的开源个人家庭云系统(我目前主要开发的项目) -``` -cd openwrt/package -git clone https://github.com/jerrykuku/luci-theme-argon.git -make menuconfig #choose LUCI->Theme->Luci-theme-argon -make -j1 V=s -``` +## 鸣谢 -## 如何安装 - -### Lean源码 - -``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.0/luci-theme-argon_1.7.0-20200909_all.ipk -opkg install luci-theme-argon*.ipk -``` - -### For openwrt official 19.07 Snapshots LuCI master - -``` -wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.5/luci-theme-argon_2.2.5-20200914_all.ipk -opkg install luci-theme-argon*.ipk -``` - -## 感谢 - -luci-theme-material: https://github.com/LuttyYang/luci-theme-material/ +[luci-theme-material](https://github.com/LuttyYang/luci-theme-material/) diff --git a/luci-theme-argon/RELEASE.md b/luci-theme-argon/RELEASE.md new file mode 100644 index 000000000..795eae7de --- /dev/null +++ b/luci-theme-argon/RELEASE.md @@ -0,0 +1,73 @@ +# Update log for master branch + +## v2.3.1 [ 2023.04.20 ] + +- Fixed the issue where the dropdown menu was being clipped. +- Fixed the problem where the exit icon was replaced with the app store icon. +- Fixed the issue where some colors were out of control in dark mode. +- Fixed the problem where the local startup script textarea could not be scrolled in the startup item. +- Fixed the problem where the Passwall node list button was misaligned. +- Fixed the text overflow problem in dynlist +- Support wallpaper from Unsplashargon +- Fix menu style mis-match on macOS+Chrome +- Fixed the issue of the login page icon becoming larger +- Support wallpaper from wallhaven + > open footer links in new tab +- Remake theme icon + +## v2.3 [ 2023.04.03 ] + +- Updated the style of Loading. +- Fixed a large number of CSS style errors and made the overall more uniform. +- Fixed the problem of uncontrolled individual colors in dark mode. + +## v2.2.9 + +- Unify the settings of css spacing +- Refactored the code of the login page +- Fix the problem that the Minify Css option is turned on when compiling, which causes the +- Fix the problem that the menu could not pop up in mobile mode +- Unify the settings of css spacing +- Refactored the code of the login page + +## v2.2.8 + +- Fix the problem that the Minify Css option is turned on when compiling, which causes the frosted glass effect to be invalid and the logo font is lost. + +## v2.2.5 + +- New config app for argon theme. You can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.[Chrome is recommended] [Download](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) +- Automatically set as the default theme when compiling. +- Modify the file structure to adapt to luci-app-argon-config. The old method of turning on dark mode is no longer applicable, please use it with luci-app-argon-config. +- Adapt to Koolshare lede 2.3.6。 +- Fix some Bug。 + +## v2.2.4 + +- Fix the problem that the login background cannot be displayed on some phones. +- Remove the dependency of luasocket. + +## v2.2.3 + +- Fix Firmware flash page display error in dark mode. +- Update font icon, add a default icon of undefined menu. + +## v2.2.2 + +- Add custom login background,put your image (allow png jpg gif) or MP4 video into /www/luci-static/argon/background, random change. +- Add force dark mode, login ssh and type "touch /etc/dark" to open dark mode. +- Add a volume mute button for video background, default is muted. +- fix login page when keyboard show the bottom text overlay the button on mobile. +- fix select color in dark mode,and add a style for scrollbar. +- jquery update to v3.5.1. +- change request bing api method form wget to luasocket (DEPENDS). + +## v2.2.1 + +- Add blur effect for login form. +- New login theme, Request background imge from bing.com, Auto change everyday. +- New theme icon. +- Add more menu category icon. +- Fix font-size and padding margin. +- Restructure css file. +- Auto adapt to dark mode. diff --git a/luci-theme-argon/RELEASE_ZH.md b/luci-theme-argon/RELEASE_ZH.md new file mode 100644 index 000000000..f3ff9a5ce --- /dev/null +++ b/luci-theme-argon/RELEASE_ZH.md @@ -0,0 +1,71 @@ +# Master 分支的更新日志 + +## v2.3.1 [ 2023.04.20 ] + +- 修复了下拉菜单被裁切的问题 +- 修复了退出图标变成了应用商店图标的问题 +- 修复了暗色模式下个别颜色不受控制的问题 +- 修复了启动项--本地启动脚本文本框不能滑动的问题 +- 修复了Passwall节点列表按钮错位的问题 +- 修复在dynlist中的文本溢出问题 +- 登录页面 支持自来 Unsplash 的在线壁纸 +- 修复在macOS的Chrome中,菜单的style异常 +- 修复在登录页面中,主题图标变大的问题 +- 登录页面 支持自来 wallhaven 的在线壁纸 + > 打开页脚链接时使用新标签页 +- 重制主题图标 + +## v2.3 [ 2023.04.03 ] + +- 更新了 Loading 的样式 +- 修复了大量的 CSS 样式错误,整体更加统一 +- 修复了暗色模式下个别颜色不受控制的问题 + +## v2.2.9 + +- 修复了在手机模式下无法弹出菜单的 bug +- 统一 css 间距的设置 +- 重构了登录页面的代码 +- 为导航菜单添加滑动效果 + +## v2.2.8 + +- 【v2.2.8】修复编译时打开 Minify Css 选项,导致磨砂玻璃效果无效,logo 字体丢失的问题 + +## v2.2.5 + +- 全新的设置 app.你可以设置 argon 主题的登录页面的模糊和透明度,并管理背景图片与视频。[建议使用 Chrome][点击下载](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) +- 当编译固件时,将自动设置为默认主题。 +- 修改文件结构,以适应 luci-app-argon-config,旧的开启暗色模式方法将不再适用,请搭配 luci-app-argon-config 使用。 +- 适配 Koolshare lede 2.3.6。 +- 修复了一些 Bug。 + +## v2.2.4 + +- 修复了在某些手机下图片背景第一次加载不能显示的问题。 +- 取消 luasocket 的依赖,无需再担心依赖问题。 + +## v2.2.3 + +- 修正了在暗色模式下,固件刷写弹窗内的显示错误。 +- 更新了图标库,为未定义的菜单增加了一个默认的图标。 + +## v2.2.2 + +- 背景文件策略调整为,同时接受 jpg png gif mp4, 自行上传文件至 /www/luci-static/argon/background 图片和视频同时随机。 +- 增加强制暗色模式,进入 ssh 输入 "touch /etc/dark" 进行开启。 +- 视频背景加了一个音量开关,喜欢带声音的可以自行点击开启,默认为静音模式。 +- 修复了手机模式下,登录页面出现键盘时,文字覆盖按钮的问题。 +- 修正了暗黑模式下下拉选项的背景颜色,同时修改了滚动条的样式。 +- jquery 更新到 v3.5.1。 +- 获取 Bing Api 的方法从 wget 更新到 luasocket 并添加依赖。 + +## v2.2.1 + +- 登录背景添加毛玻璃效果。 +- 全新的登录界面,图片背景跟随 Bing.com,每天自动切换。 +- 全新的主题 icon。 +- 增加多个导航 icon。 +- 细致的微调了 字号大小边距等等。 +- 重构了 css 文件。 +- 自动适应的暗黑模式。 diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css b/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css index 14644d1f4..afbc491fc 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css +++ b/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css @@ -6,4 +6,4 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md *//*! normalize.css v | MIT License | git.io/normalize Copyright (c) Nicolas Gallagher and Jonathan Neal -*//*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none !important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-0.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-0.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-0.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-0.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(40%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.1)));background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,0.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width:480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@font-face{font-family:'Google Sans';src:url('data:application/font-woff2;charset=utf-8;base64,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') format('woff2'),url('data:application/font-woff;charset=utf-8;base64,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') format('woff');font-weight:normal;font-style:normal}@font-face{font-family:'TypoGraphica';src:url('../fonts/TypoGraphica.eot?#iefix') format('embedded-opentype'),url('../fonts/TypoGraphica.woff') format('woff'),url('../fonts/TypoGraphica.ttf') format('truetype'),url('../fonts/TypoGraphica.svg#TypoGraphica') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'argon';src:url('../fonts/argon.eot?u6kthm');src:url('../fonts/argon.eot?u6kthm#iefix') format('embedded-opentype'),url('../fonts/argon.ttf?u6kthm') format('truetype'),url('../fonts/argon.woff?u6kthm') format('woff'),url('../fonts/argon.svg?u6kthm#argon') format('svg');font-weight:normal;font-style:normal;font-display:block}[class^="icon-"],[class*=" icon-"]{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-expand_more:before{content:"\e20b"}.icon-menu:before{content:"\e20e"}.icon-favorite:before{content:"\e291"}.icon-spinner:before{content:"\e603"}.icon-delete:before{content:"\e900"}.icon-edit:before{content:"\e901"}.icon-use:before{content:"\e902"}.icon-loading:before{content:"\e903"}.icon-switch:before{content:"\e904"}.icon-error:before{content:"\e905"}.icon-dashboard:before{content:"\e906"}.icon-logout:before{content:"\e907"}.icon-Network:before{content:"\e908"}.icon-services:before{content:"\e909"}.icon-system:before{content:"\e90a"}.icon-vpn:before{content:"\e90b"}.icon-storage:before{content:"\e90c"}.icon-statistics:before{content:"\e90d"}.icon-hello-world:before{content:"\e90e"}.icon-angle-right:before{content:"\e90f"}.icon-password:before{content:"\e910"}.icon-user:before{content:"\e971"}.icon-question:before{content:"\f059"}.icon-docker:before{content:"\e911"}.icon-control:before{content:"\e912"}.icon-statistics1:before{content:"\e913"}.icon-asterisk:before{content:"\e914"}.icon-app:before{content:"\e915"}:root{--primary:#5e72e4;--dark-primary:#483d8b;--main-color:#09c;--header-bg:#09c;--header-color:#fff;--bar-bg:#5e72e4;--menu-bg-color:#fff;--menu-color:#5f6368;--menu-color-hover:#202124;--main-menu-color:#202124;--submenu-bg-hover:#d4d4d4;--submenu-bg-hover-active:#09c;--blue:#5e72e4;--indigo:#5603ad;--purple:#8965e0;--pink:#f3a4b5;--red:#f5365c;--orange:#fb6340;--yellow:#ffd600;--green:#2dce89;--teal:#11cdef;--cyan:#2bffc6;--gray:#8898aa;--gray-dark:#32325d;--light:#ced4da;--lighter:#e9ecef;--secondary:#f7fafc;--success:#2dce89;--info:#11cdef;--warning:#fb6340;--danger:#f5365c;--light:#adb5bd;--dark:#212529;--default:#172b4d;--white:#fff;--neutral:#fff;--darker:black;--background-color:#f4f5f7;--login-form-bg-color:rgba(244,245,247,0.8);--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--blur-radius:10px;--blur-opacity:.5;--blur-radius-dark:10px;--blur-opacity-dark:.5;--font-family-sans-serif:"Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;--font-family-normal:Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif}html,body{margin:0px;padding:0px;height:100%;font-size:16px;font-family:"Google Sans","Microsoft Yahei","WenQuanYi Micro Hei","sans-serif","Helvetica Neue","Helvetica","Hiragino Sans GB";font-family:var(--font-family-sans-serif)}html{-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{font-size:.875rem;background-color:#f4f5f7;background-color:var(--background-color);color:#32325d;color:var(--gray-dark);-webkit-tap-highlight-color:transparent}*{margin:0;padding:0;box-sizing:border-box}::selection{background-color:#5e72e4;background-color:var(--primary);color:#ffffff;color:var(--white)}a:link,a:visited,a:active{color:#5e72e4;color:var(--primary);text-decoration:none}a:hover{text-decoration:underline}li{list-style-type:none}.table{position:relative;display:table}.tr{display:table-row}.thead{display:table-header-group}.tbody{display:table-row-group}.tfoot{display:table-footer-group}.td,.th{line-height:normal;display:table-cell;padding:.5em;text-align:center;vertical-align:middle}.th{font-weight:bold;white-space:nowrap}.tr.placeholder{height:4em}.tr.placeholder>.td{line-height:3;position:absolute;right:0;bottom:0;left:0;padding:.4rem 0 !important;text-align:center !important;background:inherit}.td[width="33%"]{padding:1.1em 1.5rem}.table[width="33%"],.th[width="33%"],.td[width="33%"]{width:33%}.table[width="100%"],.th[width="100%"],.td[width="100%"]{width:100%}.col-1{flex:1 1 30px !important}.col-2{flex:2 2 60px !important}.col-3{flex:3 3 90px !important}.col-4{flex:4 4 120px !important}.col-5{flex:5 5 150px !important}.col-6{flex:6 6 180px !important}.col-7{flex:7 7 210px !important}.col-8{flex:8 8 240px !important}.col-9{flex:9 9 270px !important}.col-10{flex:10 10 300px !important}*{box-sizing:border-box;margin:0;padding:0}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:normal;line-height:1.1 !important;color:inherit}select{padding:.36rem .8rem;color:#555;border:thin solid #ccc;background-color:#fff;background-image:none}.btn,button,select,input,.cbi-dropdown{line-height:1.5rem;padding:.5rem .75rem;margin:.25rem .1rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;transition:box-shadow .15s ease}select,.cbi-dropdown{width:inherit;cursor:default}select:not([multiple="multiple"]):focus,input:not(.cbi-button):focus,.cbi-dropdown:focus{border-color:#5e72e4;border-color:var(--primary);box-shadow:0 3px 9px rgba(50,50,9,0),3px 4px 8px rgba(94,114,228,0.1)}.cbi-dropdown,select[multiple="multiple"]{height:auto}pre{overflow:auto}code{font-size:1rem;font-size-adjust:.35;padding:1px 3px;color:#101010;border-radius:2px;background:#ddd}abbr{cursor:help;text-decoration:underline;color:#5e72e4;color:var(--primary)}hr{margin:1rem 0;opacity:.1;border-color:#eee}.login-page{height:100%}.login-page .video{position:absolute;width:100%;height:100%;display:flex;align-items:center;justify-content:center;background-color:#000;background-color:var(--darker);overflow:hidden}.login-page .video video{width:100%;height:auto}.login-page .volume-control{position:fixed;right:1rem;top:1rem;width:1.5rem;height:1.5rem;z-index:5000;cursor:pointer;background-size:contain;background-image:url(../img/volume_high.svg)}.login-page .volume-control.mute{background-image:url(../img/volume_off.svg)}.login-page .main-bg{position:absolute;width:100%;height:100%;left:0;top:0;background-image:url(../img/blank.png);background-repeat:no-repeat;background-position:center;background-size:cover;transition:all .5s}.login-page .login-container{height:100%;margin-left:4.5rem;position:absolute;top:0px;display:flex;flex-direction:column;-webkit-box-pack:center;justify-content:center;align-items:flex-start;min-height:100%;z-index:2;width:420px;box-shadow:rgba(0,0,0,0.75) 0 0 35px -5px;margin-left:5%;background:transparent}.login-page .login-container .login-form{display:flex;flex-direction:column;-webkit-box-align:center;align-items:center;position:absolute;top:0px;width:100%;min-height:100%;max-width:420px;background-color:#fff;background-color:var(--white);-webkit-backdrop-filter:blur(var(--blur-radius));backdrop-filter:blur(var(--blur-radius));background-color:rgba(244, 245, 247, var(--blur-opacity))}.login-page .login-container .login-form .brand{display:flex;-webkit-box-align:center;align-items:center;margin:50px auto 100px 50px;color:#525461;color:var(--default)}.login-page .login-container .login-form .brand .icon{width:50px;height:auto;margin-right:25px}.login-page .login-container .login-form .brand .brand-text{font-size:1.25rem;font-weight:700;font-family:"TypoGraphica"}.login-page .login-container .login-form .brand:hover{text-decoration:none}.login-page .login-container .login-form .form-login{width:100%;padding:20px 50px;box-sizing:border-box}.login-page .login-container .login-form .form-login .errorbox{text-align:center;color:#fb6340;color:var(--warning);padding-bottom:2rem}.login-page .login-container .login-form .form-login .input-group{margin-bottom:1.25rem;position:relative}.login-page .login-container .login-form .form-login .input-group::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#525461;color:var(--default);font-size:1.5rem;position:absolute;z-index:100;left:10px;top:10px}.login-page .login-container .login-form .form-login .input-group .border{position:absolute;width:100%;height:1px;bottom:0;border-bottom:1px #5e72e4 solid;border-bottom:1px var(--primary) solid;transform:scaleX(0);transition:transform .3s}.login-page .login-container .login-form .form-login .input-group input{font-size:1rem;line-height:1.5em;display:block;width:100%;padding:.5rem .75rem .5rem 3rem;margin:.825rem 0;box-sizing:border-box;transition:all .3s cubic-bezier(.68, -0.55, .265, 1.55);color:#525461;color:var(--default);border:0;border-radius:0;border-bottom:1px solid #fff;border-bottom:1px solid var(--white);background-color:transparent;background-clip:padding-box;box-shadow:0 3px 2px rgba(233,236,239,0.05);outline:none}.login-page .login-container .login-form .form-login .input-group input:focus+.border{transform:scaleX(1)}.login-page .login-container .login-form .form-login .input-group .cbi-input-password{margin-bottom:2rem;position:relative}.login-page .login-container .login-form .form-login .user-icon::before{content:"\e971"}.login-page .login-container .login-form .form-login .pass-icon::before{content:"\e910"}.login-page .login-container .login-form .cbi-button-apply{width:100% !important;box-shadow:rgba(0,0,0,0.1) 0 0 50px 0;font-weight:600;font-size:15px;color:#fff;color:var(--white);text-align:center;width:100%;cursor:pointer;min-height:50px;background-color:#5e72e4 !important;background-color:var(--primary) !important;border-radius:6px;outline:none;border-width:initial;border-style:none;border-color:initial;border-image:initial;padding:10px 0px;margin:30px 0px 100px;transition:all .3s !important;letter-spacing:.8rem}.login-page .login-container .login-form .cbi-button-apply:hover,.login-page .login-container .login-form .cbi-button-apply :focus{opacity:.9}.login-page .login-container footer{box-sizing:border-box;width:100%;text-align:center;line-height:1.6rem;display:flex;justify-content:space-evenly;margin-top:auto;padding:0px 0px 30px;z-index:10;color:#525461;color:var(--default);position:absolute;bottom:0}.login-page .login-container footer .ftc{position:absolute;bottom:30px;width:100%}.login-page .login-container footer .luci-link{display:block}header,.main{width:100%}footer{font-size:.8rem;overflow:hidden;padding:1rem;text-align:right;white-space:nowrap;color:#aaa}footer>a{text-decoration:none;color:#aaa}small{font-size:90%;line-height:1.42857143;white-space:normal}.main{position:relative;top:0;bottom:0;overflow-y:auto;height:100%}.main-left{top:0;float:left;width:15%;width:calc(0% + 15rem);height:100%;background-color:#fff;background-color:var(--menu-bg-color);box-shadow:rgba(0,0,0,0.75) 0 0 15px -5px;overflow-x:auto;position:fixed;z-index:100}.main-left .sidenav-header{padding:1.5rem .5rem;text-align:center}.main-left .sidenav-header .brand{font-size:1.8rem;color:#5e72e4;color:var(--primary);font-family:"TypoGraphica";text-decoration:none;text-align:center;cursor:default;vertical-align:text-bottom}.main-left::-webkit-scrollbar{width:5px;height:1px}.main-left::-webkit-scrollbar-thumb{background-color:#f6f9fc}.main-left::-webkit-scrollbar-track{background-color:#fff}.main-right{float:right;width:85%;width:calc(100% - 15rem);height:100%;transition:all .2s}.main-right>#maincontent{position:relative;z-index:50}.pull-right{float:right}.pull-left{float:left}.nowrap:not(.td){white-space:nowrap}[disabled="disabled"]{pointer-events:none}header{color:#fff;color:var(--header-color);padding:0;position:relative}header.bg-primary{background-color:#5e72e4 !important;background-color:var(--primary) !important}header::after{content:"";position:absolute;height:2rem;width:100%;background-color:#5e72e4 !important;background-color:var(--primary) !important}header .fill{padding:.8rem 0;border-bottom:0 solid rgba(255,255,255,0.08) !important;display:flex}header .fill .container{height:2rem;padding:0 1.25rem;display:flex;align-items:center;width:100%}header .fill .container .flex1{flex:1}header .fill .container .flex1 .showSide{display:none;color:#fff;font-size:1.4rem}header .fill .container .flex1 .showSide:hover{text-decoration:none}header .fill .container .flex1 .brand{font-size:1.5rem;color:#fff;font-family:"TypoGraphica";text-decoration:none;padding-left:1rem;cursor:default;vertical-align:text-bottom;display:none}header .fill .container .pull-right{float:right;margin-top:0rem;display:flex}header .fill .status span{display:inline-block;font-size:.8rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;text-shadow:none;border-radius:4px;cursor:pointer;transition:all .3s;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);margin:0 .25rem}header .fill .status span:last-child{margin-right:0}header .fill .status span[data-indicator="poll-status"]{color:#32325d;background-color:#fff}header .fill .status span[data-style="active"]{background-color:var(--green)}header .fill .status span[data-style="inactive"]{color:#ffffff !important;background-color:#32325d}#xhr_poll_status{display:flex;margin-left:.5rem}#xhr_poll_status *{color:#fff}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{border:0 !important}.danger{background-color:#ff7d60 !important}.warning{background-color:#f0e68c !important}.success{background-color:#5cb85c !important}.notice{background-color:#11cdef !important;color:#fff}.error{color:#f00}.alert,.alert-message{font-weight:bold;margin-bottom:1.25rem;padding:1rem 1.25rem;border:0;border-radius:.375rem !important;background-color:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);text-shadow:1px 1px rgba(0,0,0,0.1)}.alert.error,.alert-message.error{background-color:#ffd600}.alert h4,.alert-message h4{padding:.25rem 0;border-radius:4px;background-color:#ffd600}.alert .btn,.alert-message .btn{height:auto}.alert-message>h4{font-size:110%;font-weight:bold}.alert-message>*{margin:.5rem 0}.alert-message .btn{padding:.3rem .6rem}.container .alert,.container .alert-message{margin-top:0rem}.main .main-left{transition:all .2s}.main .main-left .nav{margin-top:.5rem}.main .main-left .nav>li>a:first-child{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.375rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav>li>a:first-child.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child.active::before{color:#fff !important}.main .main-left .nav>li>a:first-child.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav>li>a:first-child:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child:hover::before{color:#fff !important}.main .main-left .nav>li>a:first-child::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li{padding:.5rem 1rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:0}.main .main-left .nav li a{display:block;color:#5f6368;color:var(--menu-color)}.main .main-left .nav li.slide{padding:0}.main .main-left .nav li.slide ul{display:none;overflow:hidden}.main .main-left .nav li.slide:hover{background:none}.main .main-left .nav li.slide .slide-menu{margin:0 .5rem 0 2.5rem;padding:0 .5rem}.main .main-left .nav li.slide .slide-menu.active{display:block}.main .main-left .nav li.slide .slide-menu li{position:relative;border-radius:.375rem;margin:0;padding:.5rem 0;background:none;list-style:none}.main .main-left .nav li.slide .slide-menu li a{text-decoration:none}.main .main-left .nav li.slide .slide-menu li::after{content:"";position:absolute;left:0;bottom:0;width:0;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu li:hover{background:none}.main .main-left .nav li.slide .slide-menu li:hover::after{width:100%}.main .main-left .nav li.slide .slide-menu .active{background:none;color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active a{color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu .active:hover{background:none}.main .main-left .nav li.slide .slide-menu .active:hover::after{width:100%}.main .main-left .nav li .menu{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.375rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav li .menu.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu.active::before{color:#fff !important}.main .main-left .nav li .menu.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav li .menu:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu:hover::before{color:#fff !important}.main .main-left .nav li .menu::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu::after{position:absolute;right:.5rem;top:.8rem;font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-moz-osx-font-smoothing:grayscale;content:'\e90f';transition:all .15s ease;color:#ced4da;text-rendering:auto;-webkit-font-smoothing:antialiased;transition:all .3s}.main .main-left .nav li .menu[data-title=Status]:before{content:"\e906";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=System]:before{content:"\e90a";color:#fb6340}.main .main-left .nav li .menu[data-title=Services]:before{content:"\e909";color:#11cdef}.main .main-left .nav li .menu[data-title=NAS]:before{content:"\e90c";color:#f3a4b5}.main .main-left .nav li .menu[data-title=VPN]:before{content:"\e90b";color:#8965e0}.main .main-left .nav li .menu[data-title=Network]:before{content:"\e908";color:#8965e0}.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before{content:"\e90d";color:#2dce89}.main .main-left .nav li .menu[data-title=Docker]:before{content:"\e911";color:#6699ff}.main .main-left .nav li .menu[data-title=Statistics]:before{content:"\e913";color:#8965e0}.main .main-left .nav li .menu[data-title=Control]:before{content:"\e912";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=Asterisk]:before{content:"\e914";color:#fb6340}.main .main-left .nav li a[data-title=Logout]:before{content:"\e907";color:#adb5bd}.lg{margin:0;padding:0 !important}.logout{display:block;margin:.8rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.375rem;text-decoration:none;font-size:1rem;transition:all .2s;position:relative}.logout:before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e907";color:#32325d !important}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before{transition:transform .1s ease-in-out}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before{transition:transform .2s ease-in-out}.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before{display:none}#maincontent>.container{margin:0 1.25rem 1rem 1.25rem}ul{line-height:normal}li{list-style-type:none}h1{font-size:2rem;padding-bottom:10px;border-bottom:thin solid #eee}h2{margin:0 0 1rem 0;font-size:1.25rem;letter-spacing:.1rem;padding:1rem 1.25rem;color:#32325d;border-radius:.375rem;background:#fff;box-shadow:0 4px 8px rgba(0,0,0,0.03);font-weight:bold}h3{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark);border-radius:.375rem;background:#fff;font-weight:bold}h4{margin:0;padding:.75rem 1.25rem;font-size:.7rem;font-weight:600;color:#525f7f;background-color:#e9ecef;background-color:var(--lighter);font-weight:bold}h4 em{padding:0 .5rem}h5{font-size:1rem;margin:2rem 0 0 0;padding-bottom:10px}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{font-family:inherit;font-weight:normal;font-style:normal;line-height:normal;min-width:inherit;margin:1.25rem 0;padding:0rem;border:0;border-radius:.375rem;background-color:#fff;box-shadow:0 0 1rem 0 rgba(136,152,170,0.15)}.cbi-modal .cbi-section,.cbi-section .cbi-section{padding:0;box-shadow:none}.cbi-modal .cbi-tabmenu{margin-left:0}.cbi-map-descr{font-size:small;line-height:1.5;padding:0 1.25rem}.cbi-section-descr:not(:empty){font-size:small;line-height:1.5;padding:1rem 1.25rem 0 1.25rem}.cbi-map-descr+fieldset{margin-top:1rem}.cbi-map-descr>abbr{cursor:help;text-decoration:underline}.cbi-section>legend{display:none !important}fieldset>fieldset,.cbi-section>.cbi-section{margin:0;padding:0;border:0;box-shadow:none}.cbi-section>h3:first-child,.panel-title{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark)}.cbi-section>h3:first-child,.cbi-section>h4:first-child,.cbi-section>p:first-child,[data-tab-title]>h3:first-child,[data-tab-title]>h4:first-child,[data-tab-title]>p:first-child{padding:1rem 1.25rem}.cbi-section p{padding:1rem}.cbi-tblsection{overflow-x:scroll}table{border-spacing:0;border-collapse:collapse}table,.table{overflow-y:hidden;width:100%;font-size:90%}.table .table-titles th{background-color:#e9ecef;background-color:var(--lighter)}table>tbody>tr>td,table>tbody>tr>th,table>tfoot>tr>td,table>tfoot>tr>th,table>thead>tr>td,table>thead>tr>th,.table>.tbody>.tr>.td,.table>.tbody>.tr>.th,.table>.tfoot>.tr>.td,.table>.tfoot>.tr>.th,.table>.thead>.tr>.td,.table>.thead>.tr>.th,.table>.tr>.td.cbi-value-field,.table>.tr>.th.cbi-section-table-cell{padding:.5rem}.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td{padding:.6rem}.cbi-section-table-cell{line-height:1.1;align-self:flex-end;flex:1 1 auto}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:thin solid #ddd;padding:1.1em 1.25rem}#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{border-top:0 !important;background-color:#f6f9fc;padding:1.1em 1.25rem;line-height:1.3rem}.table[width="100%"]>.tr:first-child>.td{margin:auto 0}.cbi-section-table-row{margin-bottom:1rem;text-align:center !important;background:#f4f4f4}.cbi-section-table-row:last-child{margin-bottom:0}.cbi-section-table-row>.cbi-value-field .cbi-dropdown,.cbi-section-table-row>.cbi-value-field .cbi-input-select,.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{width:100%}.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{min-width:80px}.cbi-section-table-row>.cbi-value-field [data-dynlist]>input,.cbi-section-table-row>.cbi-value-field input.cbi-input-password{width:calc(100% - 1.5rem)}.cbi-section-table-row .td{text-align:center !important}.control-group{display:inline-flex;width:100%;flex-wrap:wrap;gap:2px}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n){background-color:#f9f9f9}table table,.table .table,.cbi-value-field table,.cbi-value-field .table,td>table>tbody>tr>td,.td>.table>.tbody>.tr>.td,.cbi-value-field>table>tbody>tr>td,.cbi-value-field>.table>.tbody>.tr>.td{border:0}.btn,.cbi-button,.item::after{font-size:.8rem;display:inline-block;width:auto !important;padding:.45rem .8rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition:all .2s ease-in-out;text-align:center;vertical-align:middle;white-space:nowrap;text-decoration:none;text-transform:uppercase;color:rgba(0,0,0,0.87);border:0;border-radius:.2rem;background-color:#f0f0f0;background-image:none;-webkit-appearance:none;-ms-touch-action:manipulation;touch-action:manipulation}.cbi-button-up,.cbi-button-down{font-size:1.2rem;display:inline-block;min-width:0;padding:.2rem 1rem;font-size:0;color:transparent !important;background:url(../icon/arrow.svg) no-repeat center;background-size:12px 20px}.cbi-button-up{transform:scaleY(-1)}.cbi-button:not(select){-webkit-appearance:none !important}.btn:hover,.btn:focus,.btn:active,.cbi-button:hover,.cbi-button:focus,.cbi-button:active,.item:hover::after,.item:focus::after,.item:active::after,.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover,.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus,.cbi-page-actions .cbi-button-apply+.cbi-button-save:active{text-decoration:none;outline:0}.btn:hover,.btn:focus,.cbi-button:hover,.cbi-button:focus,.item:hover::after,.item:focus::after{box-shadow:0 0 2px rgba(0,0,0,0.12),0 2px 2px rgba(0,0,0,0.2)}.btn:active,.cbi-button:active,.item:active::after{box-shadow:0 10px 20px rgba(0,0,0,0.19),0 6px 6px rgba(0,0,0,0.23)}.cbi-button-up:hover,.cbi-button-up:focus{box-shadow:0 0 2px rgba(0,0,0,0.12),0 -2px 2px rgba(0,0,0,0.2)}.cbi-button-up:active{box-shadow:0 -10px 20px rgba(0,0,0,0.19),0 -6px 6px rgba(0,0,0,0.23)}.btn:disabled,.cbi-button:disabled{cursor:not-allowed;pointer-events:none;opacity:.5;box-shadow:none}.alert-message [class="btn"],.modal div[class="btn"],.cbi-button-find,.cbi-button-link,.cbi-button-up,.cbi-button-down,.cbi-button-neutral,.cbi-button[name="zero"],.cbi-button[name="restart"],.cbi-button[onclick="hide_empty(this)"]{font-weight:bold;color:#fff;border:thin solid #8898aa;background-color:#8898aa}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"]{font-weight:normal;color:#fff;border:thin solid #f5365c;border:thin solid var(--red);background-color:#f5365c;background-color:var(--red)}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:normal;color:#fff;border:thin solid #eea236;background-color:#f0ad4e}.cbi-button-success,.cbi-button-download,.cbi-button[name="backup"],.cbi-button[value="Download"],.cbi-button[value="Save mtdblock"]{font-weight:normal;color:#fff;border:thin solid #4cae4c;background-color:#5cb85c}.cbi-page-actions .cbi-button-link:first-child{float:left}.a-to-btn{text-decoration:none}.cbi-value-field .cbi-button-add{font-weight:bold;margin:4px 0 4px 3px;padding:1px 6px;display:flex;align-items:center}.tabs{margin:0 0 1rem 0;padding:0 1rem;background-color:#FFFFFF;border-radius:.375rem;box-shadow:0 4px 8px rgba(0,0,0,0.03);white-space:nowrap;overflow-x:auto}.tabs::-webkit-scrollbar{width:1px;height:5px}.tabs::-webkit-scrollbar-thumb{background-color:#f6f9fc}.tabs::-webkit-scrollbar-track{background-color:#fff}.tabs li[class~="active"],.tabs li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#dce1fe;margin-bottom:0;border-radius:0}.tabs li[class~="active"] a,.tabs li:hover a{color:#5e72e4;color:var(--primary)}.tabs li{font-size:.875rem;display:inline-block;padding:.875rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0;transition:all .2s}.tabs li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.tabs li:hover{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary)}.cbi-tabmenu{color:white;padding:.5rem 1rem 0 1rem;white-space:nowrap;overflow-x:auto}.cbi-tabmenu::-webkit-scrollbar{width:1px;height:5px}.cbi-tabmenu::-webkit-scrollbar-thumb{background-color:#f6f9fc}.cbi-tabmenu::-webkit-scrollbar-track{background-color:#fff}.cbi-tabmenu li{background:#dce3e9;display:inline-block;font-size:.875rem;border-top-left-radius:.25rem;border-top-right-radius:.25rem;padding:.5rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0 .2rem}.cbi-tabmenu li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.cbi-tabmenu li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#dce1fe;margin-bottom:0}.cbi-tabmenu li:hover a{color:#525f7f}.cbi-tabmenu li[class~="cbi-tab"]{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#dce1fe;margin-bottom:0}.cbi-tabmenu li[class~="cbi-tab"] a{color:#5e72e4;color:var(--primary)}.cbi-tab-descr{padding:.5rem 1.5rem}.cbi-section-node{padding:1rem 0}.cbi-section .cbi-section-remove:nth-of-type(2n),.container>.cbi-section .cbi-section-node:nth-of-type(2n){background-color:#f9f9f9}[data-tab-title]{overflow:hidden;height:0;opacity:0;margin:0;padding:0rem 0rem !important}[data-tab-title] p{margin-left:1rem;margin-bottom:1rem}[data-tab-active="true"]{overflow:visible;height:auto;opacity:1;transition:opacity .25s ease-in;margin:inherit !important}.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3),.cbi-section[id] .cbi-section-node:nth-of-type(4n+4){background-color:#f9f9f9}.cbi-section-node-tabbed{margin-top:0;padding:0;border:0 solid #d4d4d4;border-radius:.375rem}.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#f9f9f9}.cbi-value-field,.cbi-value-description{line-height:1.25;display:table-cell}.cbi-value-field abbr,.cbi-value-description abbr{color:#32325d;color:var(--gray-dark)}.cbi-value-description{font-size:small;padding:.5rem;opacity:.5}.cbi-value-title{display:table-cell;float:left;width:23rem;padding-top:.25rem;padding-right:2rem;text-align:right;word-wrap:break-word}.cbi-value{display:inline-block;width:100%;padding:.35rem 1rem .2rem 1rem;line-height:2.4rem}.cbi-value ul{line-height:1.25}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:18rem}.cbi-value input[type="password"]{border-bottom-right-radius:0;border-top-right-radius:0;margin-right:0}.cbi-value input[type="password"]+.cbi-button-neutral{height:42px;border-bottom-left-radius:0;border-top-left-radius:0;margin-left:0;border:0}#cbi-firewall-zone .cbi-input-select,#cbi-network-switch_vlan .cbi-input-select{min-width:11rem}#cbi-network-switch_vlan .cbi-input-text{max-width:3rem}.cbi-input-invalid{color:#f5365c;border-bottom-color:#f5365c}.cbi-section-error{font-weight:bold;line-height:1.42857143;margin:18px;padding:6px;border:thin solid #f5365c;border-radius:3px;background-color:#fce6e6}.cbi-section-error ul{margin:0 0 0 20px}.cbi-section-error ul li{font-weight:bold;color:#f5365c}.td[data-title]::before{font-weight:bold;display:none;padding:.25rem 0;content:attr(data-title) ":\20";text-align:left;white-space:nowrap}.tr.placeholder .td[data-title]::before{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-weight:bold;display:table-cell;align-self:center;flex:1 1 5%;padding:.25rem;content:attr(data-title) "\20";text-align:center;vertical-align:middle;white-space:normal;word-wrap:break-word}.cbi-rowstyle-1{background-color:#f9f9f9}.cbi-rowstyle-2{background-color:#eee}.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#fff !important}.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{width:auto !important}.td.cbi-section-actions{text-align:right !important;vertical-align:middle}.td.cbi-section-actions>*{display:inline-flex}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:0 5px;display:flex;align-items:center}.td.cbi-section-actions>*>form{display:inline-flex;margin:0}.cbi-checkbox{margin:0 .25rem}.cbi-dynlist{line-height:1.3;flex-direction:column;min-height:30px;cursor:text}.cbi-dynlist>.item{position:relative;max-width:25rem;pointer-events:none;color:#8898aa;outline:0}.cbi-dynlist[name="sshkeys"]>.item{max-width:none}.cbi-dynlist>.item::after{position:absolute;width:2.2rem !important;height:calc(100% - .5rem - 2px);right:0;bottom:0;content:"\00D7";pointer-events:auto;background-color:var(--red);font-weight:normal;font-size:1.2rem;display:flex;align-items:center;justify-content:center;line-height:1.5rem;padding:0;margin:.25rem .1rem .25rem 0;color:#fff;border:1px solid #f5365c;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;border-top-left-radius:0;border-bottom-left-radius:0}.cbi-dynlist>.item>span{white-space:normal;word-break:break-word;line-height:1.5rem;padding:.5rem .5rem;margin:.25rem .1rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;display:block;transition:box-shadow .15s ease;box-sizing:border-box;min-width:15rem}.cbi-dynlist>.add-item{display:inline-flex;align-items:center;width:100%;min-width:16rem}.cbi-dynlist>.add-item input{border-top-right-radius:0;border-bottom-right-radius:0;margin-right:0;border-right:none}.cbi-dynlist>.add-item .cbi-button-add{font-weight:normal;font-size:1.2rem;display:flex;align-items:center;line-height:1.5rem;padding:.5rem .75rem;margin:.25rem .1rem .25rem 0;color:#fff;border:1px solid #5e72e4;border:1px solid var(--primary);border-radius:.25rem;outline:0;background-image:none;box-shadow:none;border-top-left-radius:0;border-bottom-left-radius:0}.cbi-dynlist>.add-item:not([ondrop])>input{overflow:hidden;width:100%;min-width:15rem;white-space:nowrap;text-overflow:ellipsis}.cbi-dynlist>.add-item[ondrop]>input{min-width:13rem}.cbi-dynlist,.cbi-dropdown{position:relative;display:inline-flex;padding:.2rem .2rem}.cbi-dropdown[placeholder*="select"]{max-width:25rem;height:auto;margin-top:-3px}.cbi-dropdown>ul{display:flex;overflow-x:hidden;overflow-y:auto;width:100%;margin:0 !important;padding:0;list-style:none;outline:0}.cbi-dropdown>ul.preview{display:none}.cbi-button-apply>ul.preview{display:none}.cbi-button-apply>ul.preview li{color:#fff}.cbi-button-apply>ul:first-child li{color:#fff}.cbi-dropdown>.open{flex-basis:15px}.cbi-dropdown>.open,.cbi-dropdown>.more{font-size:1rem;font-weight:900;line-height:2;display:flex;flex-direction:column;flex-grow:0;flex-shrink:0;justify-content:center;padding:0 .25em;cursor:default;text-align:center;outline:0}.cbi-dropdown>.more,.cbi-dropdown>ul>li[placeholder]{font-weight:bold;display:none;color:#777;text-shadow:1px 1px 0 #fff}.cbi-dropdown>ul>li{display:none;overflow:hidden;align-items:center;align-self:center;flex-grow:1;flex-shrink:1;min-height:20px;padding:.25em;white-space:nowrap;text-overflow:ellipsis}.cbi-dropdown>ul>li .hide-open{display:initial}.cbi-dropdown>ul>li .hide-close{display:none}.cbi-dropdown>ul>li[display]:not([display="0"]){border-left:thin solid #ccc}.cbi-dropdown[empty]>ul{max-width:1px}.cbi-dropdown>ul>li>form{display:none;margin:0;padding:0;pointer-events:none}.cbi-dropdown>ul>li img{margin-right:.25em;vertical-align:middle}.cbi-dropdown>ul>li>form>input[type="checkbox"]{height:auto;margin:0}.cbi-dropdown>ul>li input[type="text"]{height:20px}.cbi-dropdown[open]>ul.dropdown{position:absolute;z-index:1100;display:block;width:auto;min-width:100%;max-width:none;max-height:200px !important;border:0 solid #918e8c;background:#ffffff;box-shadow:0 0 4px #918e8c;border-bottom-left-radius:.35rem;border-bottom-right-radius:.35rem;color:var(--main-menu-color);margin-left:-0.2rem !important}.cbi-dropdown[open]>ul.dropdown li{color:#000}.cbi-dropdown>ul>li[display],.cbi-dropdown[open]>ul.preview,.cbi-dropdown[open]>ul.dropdown>li,.cbi-dropdown[multiple]>ul>li>label,.cbi-dropdown[multiple][open]>ul.dropdown>li,.cbi-dropdown[multiple][more]>.more,.cbi-dropdown[multiple][empty]>.more{display:flex;align-items:center;flex-grow:1}.cbi-dropdown[empty]>ul>li,.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder],.cbi-dropdown[multiple][open]>ul.dropdown>li>form{display:block}.cbi-dropdown[open]>ul.dropdown>li .hide-open{display:none}.cbi-dropdown[open]>ul.dropdown>li .hide-close{display:initial}.cbi-dropdown[open]>ul.dropdown>li{border-bottom:thin solid #ccc;padding:.5rem .8rem}.cbi-dropdown[open]>ul.dropdown>li label{margin-left:.5rem}.cbi-dropdown[open]>ul.dropdown>li[selected]{background:#dce1fe}.cbi-dropdown[open]>ul.dropdown>li.focus{background:#dce1fe;outline:none}.cbi-dropdown[open]>ul.dropdown>li:last-child{margin-bottom:0;border-bottom:0}.cbi-dropdown[open]>ul.dropdown>li[unselectable]{opacity:.7}.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child{width:100%}.cbi-dropdown[disabled]{pointer-events:none;opacity:.6}.cbi-dropdown .zonebadge{width:100%}.cbi-dropdown[open] .zonebadge{width:auto}.cbi-progressbar{position:relative;min-width:11rem;height:1.5rem;margin:0 0;border:thin solid #999;background:#eee;border-radius:4px;overflow:hidden}.cbi-progressbar>div{width:0;height:100%;transition:width .25s ease-in;background:#5bc0de;background:var(--bar-bg)}.cbi-progressbar::after{font-family:monospace;font-size:1em;font-weight:bold;font-size-adjust:.38;line-height:1.5rem;position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;content:attr(title);text-align:center;white-space:pre;text-overflow:ellipsis}#modal_overlay{position:fixed;z-index:900;top:0;right:10000px;bottom:0;left:-10000px;overflow-y:scroll;transition:opacity .125s ease-in;opacity:0;background:rgba(0,0,0,0.7);-webkit-overflow-scrolling:touch}.modal{display:flex;align-items:center;flex-wrap:wrap;width:90%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1em;border-radius:3px !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>*{line-height:normal;flex-basis:100%;margin-bottom:.5em;max-width:100%}.modal>pre,.modal>textarea{font-size:1rem;font-size-adjust:.35;overflow:auto;margin-bottom:.5em;padding:8.5px;cursor:auto;white-space:pre-wrap;color:#eee;outline:0;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>h4{margin:.5em 0}.modal ul{margin-left:2.2em}.modal li{list-style-type:square;color:#808080}.modal p{word-break:break-word}.modal .label{font-size:.6rem;font-weight:normal;padding:.1rem .3rem;padding-bottom:0;cursor:default;border-radius:0}.modal .label.warning{background-color:#f0ad4e !important}.modal .btn{padding:.45rem .8rem}.modal.cbi-modal{max-width:90%;max-height:none}body.modal-overlay-active{overflow:hidden;height:100vh}body.modal-overlay-active #modal_overlay{right:0;left:0;opacity:1}.spinning{position:relative;padding-left:32px !important}.spinning::before{position:absolute;top:0;bottom:0;left:.2em;width:32px;content:"";background:url(/luci-static/resources/icons/loading.gif) no-repeat center;background-size:16px}.hidden{display:none}.left,.left::before{text-align:left !important}.right,.right::before{text-align:right !important}.center,.center::before{text-align:center !important}.top{align-self:flex-start !important;vertical-align:top !important}.bottom{align-self:flex-end !important;vertical-align:bottom !important}.inline{display:inline}.cbi-page-actions{padding-top:1rem;text-align:right;justify-content:flex-end}.cbi-page-actions>form[method="post"]{display:inline-block}.th[data-type="button"],.td[data-type="button"],.th[data-type="fvalue"],.td[data-type="fvalue"]{flex:1 1 2em;text-align:center}.ifacebadge{display:inline-flex;gap:.2rem;padding:.5rem .8rem;border-bottom:thin solid #ccc;background:#eee;box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);border-radius:4px}td>.ifacebadge,.td>.ifacebadge{font-size:.8rem;background-color:#f0f0f0}.ifacebadge>em,.ifacebadge>img{display:inline-block;align-self:flex-start}.ifacebadge>img+img{margin:0 .2rem 0 0}.network-status-table{display:flex;flex-wrap:wrap}.network-status-table .ifacebox{flex-grow:1;border-radius:4px;overflow:hidden;margin:0 1.25rem 1rem 1.25rem}.network-status-table .ifacebox-body{display:flex;flex-direction:column;height:100%;gap:.5em}.network-status-table .ifacebox-body>span{flex:10 10 auto;height:100%}.network-status-table .ifacebox-body>div{display:flex;flex-wrap:wrap;gap:.5rem}.network-status-table .ifacebox-body .ifacebadge{align-items:center;flex:1 1 auto;min-width:220px;padding:.5em;background-color:#fff}.network-status-table .ifacebox-body .ifacebadge>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cbi-input-textarea{font-family:monospace;width:100%;font-size:.875rem;min-height:14rem;padding:.8rem;color:#000}#syslog{font-size:small;line-height:1.25;overflow-y:hidden;width:100%;min-height:15rem;padding:1rem;resize:none;color:#242424;border:0;border-radius:.375rem;background-color:#ffffff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}#syslog:focus{outline:0}.uci-change-list{font-family:monospace}.uci-change-list ins,.uci-change-legend-label ins{display:block;padding:2px;text-decoration:none;border:thin solid #0f0;background-color:#cfc}.uci-change-list del,.uci-change-legend-label del{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #f00;background-color:#fcc}.uci-change-list var,.uci-change-legend-label var{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #ccc;background-color:#eee}.uci-change-list var ins,.uci-change-list var del{font-style:normal;padding:0;white-space:pre;border:0}.uci-change-legend{padding:5px}.uci-change-legend-label{float:left;width:150px}.uci-change-legend-label>ins,.uci-change-legend-label>del,.uci-change-legend-label>var{display:block;float:left;width:10px;height:10px;margin-right:4px}.uci-change-legend-label var ins,.uci-change-legend-label var del{line-height:.4;border:0}.uci-change-list var,.uci-change-list del,.uci-change-list ins{padding:.5rem}#iwsvg,#iwsvg2,#bwsvg{border:thin solid #d4d4d4 !important}#iwsvg,[data-page="admin-status-realtime-bandwidth"] #bwsvg{border-top:0 !important}.ifacebox{line-height:1.25;display:inline-flex;overflow:hidden;flex-direction:column;border-radius:4px;min-width:100px;border-bottom:thin solid #ccc;background-color:#f9f9f9;box-shadow:inset 0 1px 0 rgba(255,255,255,0.4),0 1px 2px rgba(0,0,0,0.2)}.ifacebox-head{padding:.25em;background:#eee}.ifacebox-head.active{background:#5e72e4;background:var(--primary)}.ifacebox-head.active *{color:#fff;color:var(--white)}.ifacebox-body{padding:.875rem 1rem;line-height:1.6em}.cbi-image-button{margin-left:.5rem}.zonebadge{display:inline-block;padding:.2rem .5rem;border-radius:4px}.zonebadge .ifacebadge{margin:.1rem .2rem;padding:.2rem .3rem;border:thin solid #6c6c6c}.zonebadge>input[type="text"]{min-width:10rem;margin-top:.3rem;padding:.16rem 1rem}.zonebadge>em,.zonebadge>strong{display:inline-block;margin:0 .2rem}.cbi-value-field .cbi-input-checkbox,.cbi-value-field .cbi-input-radio{margin-top:.1rem}.cbi-value-field>ul>li{display:flex}.cbi-value-field>ul>li>label{margin-top:.5rem}.cbi-value-field>ul>li .ifacebadge{margin-top:-0.5rem;margin-left:.4rem;background-color:#eee}.cbi-section-table-row>.cbi-value-field .cbi-dropdown{min-width:3rem}.cbi-section-create{display:inline-flex;align-items:center;margin:.25rem 1.25rem}.cbi-section-create>*{margin:.5rem 0}.cbi-section-remove{padding:.5rem}div.cbi-value var,td.cbi-value-field var,.td.cbi-value-field var{font-style:italic;color:#0069d6}.cbi-optionals{padding:1rem 1rem 0 1rem;border-top:thin solid #ccc}.cbi-dropdown-container{position:relative}.cbi-tooltip-container,span[data-tooltip],span[data-tooltip] .label{cursor:help !important}.cbi-tooltip{position:absolute;z-index:1000;left:-1000px;padding:2px 5px;transition:opacity .25s ease-out;white-space:pre;pointer-events:none;opacity:0;border-radius:3px;background:#fff;box-shadow:0 0 2px #444}.cbi-tooltip-container:hover .cbi-tooltip{left:auto;transition:opacity .25s ease-in;opacity:1}.zonebadge .cbi-tooltip{margin:-1.5rem 0 0 -0.5rem;padding:.25rem;background:inherit}.zonebadge-empty{color:#404040;background:repeating-linear-gradient(45deg, rgba(204,204,204,0.5), rgba(204,204,204,0.5) 5px, rgba(255,255,255,0.5) 5px, rgba(255,255,255,0.5) 10px)}.zone-forwards{display:flex;min-width:10rem}.zone-forwards>*{flex:1 1 45%}.zone-forwards>span{flex-basis:10%;padding:0 .25rem;text-align:center}.zone-forwards .zone-src,.zone-forwards .zone-dest{display:flex;flex-direction:column}.label{font-size:.8rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;color:#fff !important;border-radius:3px;background-color:#bfbfbf;text-shadow:none}label>input[type="checkbox"],label>input[type="radio"]{position:relative;top:.4rem;right:.2rem;margin:0;vertical-align:bottom}label[data-index][data-depends]{padding-right:2em}.showSide{display:none}.darkMask{position:fixed;z-index:99;display:none;width:100%;height:100%;content:"";top:0;background-color:rgba(0,0,0,0.56);transition:all .2s}.darkMask.active{display:block}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1.2rem;font-size-adjust:.35;line-height:normal;display:block;overflow-y:hidden;width:100%;padding:8.5px;white-space:pre;color:#eee;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}[data-page="admin-network-diagnostics"] .table{box-shadow:none}input[name="ping"],input[name="traceroute"],input[name="nslookup"]{width:80%}.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2),.node-status-processes>.main .table .tr .td:nth-child(3){white-space:normal}[data-page="admin-system-reboot"] p{padding-left:1.5rem}[data-page="admin-system-reboot"] .cbi-button{background:#fb6340 !important}[data-page="admin-system-reboot"] p>span{position:relative;top:.1rem;left:1rem}[data-page="admin-vpn-passwall"] h4{background:transparent}#cbi-samba [data-tab="template"] .cbi-value-field{display:block}#cbi-samba [data-tab="template"] .cbi-value-title{width:auto;padding-bottom:.6rem}[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr{margin-left:0;color:#32325d;color:var(--gray-dark)}[data-page="admin-system-opkg"] h2{margin-left:0;color:#32325d;color:var(--gray-dark)}.controls{margin:.5em 1rem 1em 1rem !important}.controls>*>.btn:not([aria-label$="page"]){flex-grow:initial !important;margin-top:.25rem}.controls>#pager>.btn[aria-label$="page"]{font-size:1.4rem;font-weight:bold}.controls>*>label{margin-bottom:.2rem}[data-page="admin-system-opkg"] div.btn{line-height:3;display:inline;padding:.3rem .6rem}[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{margin-top:2rem;padding-top:.1rem}[data-page="admin-system-opkg"] #maincontent>.container{margin:0 1.25rem 1rem 1.25rem;margin-bottom:1rem}.td.version,.td.size{white-space:normal !important;word-break:break-word}.cbi-tabmenu+.cbi-section{margin-top:0}[data-page="admin-system-crontab"] #view p{margin-bottom:1rem}[data-page="admin-system-flash"] .cbi-value{padding:0}[data-page="admin-system-flash"] .cbi-section .cbi-section{margin-top:0}[data-page="admin-system-flash"] .cbi-map-tabbed{border-radius:.375rem}[data-page="admin-system-flash"] legend{display:block !important;font-size:1.2rem;width:100%;display:block;margin-bottom:0;padding:1rem 0 1rem 1.5rem;border-bottom:1px solid rgba(0,0,0,0.05);line-height:1.5;margin-bottom:0rem;letter-spacing:.1rem;color:#32325d;font-weight:bold}[data-page="admin-system-flash"] .cbi-section-descr{font-weight:600;padding:1rem 0 1rem 1.5rem;color:#525f7f}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.35rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal !important}#cbi-wireless>#wifi_assoclist_table>.tr{box-shadow:inset 1px -1px 0 #ddd,inset -1px -1px 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td{right:33px;bottom:33px;left:33px;border-top:thin solid #ddd !important}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles{box-shadow:inset 1px 0 0 #ddd,inset -1px 0 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th{border-bottom:thin solid #ddd;box-shadow:0 -1px 0 0 #ddd}#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"]{width:23rem}[data-page="admin-network-dhcp"] .cbi-value{padding:0}[data-page="admin-network-dhcp"] [data-tab-active="true"]{padding:1rem 0 !important}#iptables{margin:0}.Firewall form{margin:2rem 2rem 0 0;padding:0;box-shadow:none}#cbi-firewall-redirect table *,#cbi-network-switch_vlan table *,#cbi-firewall-zone table *{font-size:small}#cbi-firewall-redirect table input[type="text"],#cbi-network-switch_vlan table input[type="text"],#cbi-firewall-zone table input[type="text"]{width:5rem}#cbi-firewall-redirect table select,#cbi-network-switch_vlan table select,#cbi-firewall-zone table select{min-width:3.5rem}#cbi-network-switch_vlan .th,#cbi-network-switch_vlan .td{flex-basis:12%}#cbi-firewall-zone .table,#cbi-network-switch_vlan .table{display:block}#cbi-firewall-zone .td,#cbi-network-switch_vlan .td{width:100%}[data-page="admin-network-firewall-custom"] #view p,[data-page="admin-status-routes"] #view p{padding:0 1.5rem;margin-bottom:1rem}[data-page="admin-network-firewall-custom"] #view p textarea,[data-page="admin-status-routes"] #view p textarea{padding:1rem;border-radius:.375rem}#applyreboot-container{margin:2rem}#applyreboot-section{line-height:300%;margin:2rem}.OpenVPN a{line-height:initial !important}.commandbox{width:24% !important;margin:10px 0 0 10px !important;padding:.5rem 1rem;border-bottom:thin solid #ccc;background:#eee;box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.commandbox h3{line-height:normal !important;overflow:hidden;margin:6px 0 !important;white-space:nowrap;text-overflow:ellipsis}.commandbox div{left:auto !important}.commandbox code{position:absolute;overflow:hidden;max-width:60%;margin-left:4px;padding:2px 3px;white-space:nowrap;text-overflow:ellipsis}.commandbox code:hover{overflow-y:auto;max-height:50px;white-space:normal}.commandbox p:first-of-type{margin-top:-6px}.commandbox p:nth-of-type(2){margin-top:2px}[data-page^="admin-system-commands"] .panel-title,[data-page^="command-cfg"] .mobile-hide,[data-page^="command-cfg"] .showSide{display:none}#command-rc-output .alert-message{line-height:1.42857143;position:absolute;top:40px;right:32px;max-width:40%;margin:0;animation:anim-fade-in 1.5s forwards;word-break:break-word;opacity:0}@keyframes anim-fade-in{100%{opacity:1}}input[type="checkbox"]{appearance:none !important;-webkit-appearance:none !important;border:1px solid #dee2e6;width:16px !important;height:16px !important;padding:0;cursor:pointer;transition:all .2s;margin:1rem 0 0 0}input[type="checkbox"]:checked{border:1px solid #5e72e4;border:1px solid var(--primary);background-image:url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important;background-color:#5e72e4;background-color:var(--primary);background-size:70%;background-repeat:no-repeat;background-position:center}.fb-container .cbi-button{height:auto !important}#cbi-usb_printer-printer em{display:block;padding:1rem;text-align:center}pre.command-output{padding:1.5rem}[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"]{padding:1.5rem !important}[data-page="admin-nlbw-backup"] form{padding-left:1.5rem}[data-page="admin-status-iptables"] .right{margin-bottom:0 !important}@media all and (-ms-high-contrast:none){.main>.main-left>.nav>.slide>.menu::before{top:30.25%}.main>.main-left>.nav>li:last-child::before{top:20%}.showSide::before{top:-12px}}@media screen and (max-width:1600px){header>.fill>.container>#logo{margin:0 2.5rem 0 .5rem}.main-left{width:calc(0% + 13rem)}.main-right{width:calc(100% - 13rem)}.btn:not(button),.cbi-button{font-size:.8rem}.label{padding:.2rem .6rem}.cbi-value-title{width:15rem;padding-right:.6rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:18rem}#cbi-firewall-zone .cbi-input-select{min-width:9rem}.cbi-input-textarea{font-size:small}.node-admin-status>.main fieldset li>a{padding:.3rem .6rem}}@media screen and (max-width:1366px){header>.fill>.container{cursor:default}.main-left{width:calc(0% + 13rem)}.main-right{width:calc(100% - 13rem)}.tabs>li>a,.cbi-tabmenu>li>a{padding:.2rem .8rem}.panel-title{font-size:1.1rem;padding-bottom:1rem}table{font-size:.7rem !important;width:100% !important}.table .cbi-input-text{width:100%}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:16rem}#cbi-firewall-zone .cbi-input-select{min-width:4rem}.main>.main-left>.nav>li,.main>.main-left>.nav>li>a,.main .main-left .nav>li>a:first-child,.main>.main-left>.nav>.slide>.menu,.main>.main-left>.nav>li>[data-title="Logout"]{font-size:.9rem}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.7rem}#modal_overlay{top:0rem}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table){display:block}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table),[data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table),[data-page="admin-network-hosts"] .table,[data-page="admin-network-routes"] .table{overflow-y:visible}.commandbox{width:32% !important}.btn:not(button),.cbi-button{font-size:.8rem}}@media screen and (max-width:1152px){header>.fill>.container>#logo{display:none}header>.fill>.container>.brand{position:relative}html,.main{overflow-y:visible}.main>.loading>span{top:25%}.main-left{width:calc(0% + 13rem)}.main-right{width:calc(100% - 13rem)}body:not(.logged-in) .showSide{visibility:hidden;width:0;margin:0}.node-main-login>.main .cbi-value-title{text-align:left}.cbi-value-title{width:12rem;padding-right:1rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"]{width:16rem;min-width:16rem}.cbi-value input[name^="pw"],.cbi-value input[data-update="change"]:nth-child(2){width:13rem !important;min-width:13rem}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1rem}.table{display:block}.Interfaces .table{overflow-x:hidden}#packages.table{display:grid}.tr{display:flex;flex-direction:row;flex-wrap:wrap}.Overview .table[width="100%"]>.tr{flex-wrap:nowrap}.tr.placeholder{border-bottom:thin solid #ddd}.tr.placeholder>.td,#cbi-firewall .tr>.td,#cbi-network .tr:nth-child(2)>.td,.cbi-section #wifi_assoclist_table .tr>.td{border-top:0}.th,.td{display:inline-block;align-self:flex-start;flex:2 2 10%;text-overflow:ellipsis;word-wrap:break-word}.td select,.td input[type="text"]{width:100%;word-wrap:normal}.td [data-dynlist]>input,.td input.cbi-input-password{width:calc(100% - 1.5rem)}.td[data-type="button"],.td[data-type="fvalue"]{flex:1 1 12.5%;text-align:left}.th.cbi-value-field,.td.cbi-value-field,.th.cbi-section-table-cell,.td.cbi-section-table-cell{flex-basis:auto;padding-top:1rem}.cbi-section-table-row{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.td.cbi-value-field,.cbi-section-table-cell{display:inline-block;flex:10 10 auto;flex-basis:50%;text-align:center}.td.cbi-section-actions{vertical-align:bottom}.tr.table-titles,.tr.cbi-section-table-titles,.tr.cbi-section-table-descr{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-size:.9rem;display:block;flex:1 1 100%;border-bottom:thin solid rgba(0,0,0,0.26);background:#e9ecef}.td[data-title],[data-page^="admin-status-realtime"] .td[id]{text-align:left}.td[data-title]::before{display:block}.cbi-button+.cbi-button{margin-left:0}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:2.1px 3px}.Firewall form{position:static !important;margin:0 0 2rem 0;padding:2rem;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.Firewall form input{width:100% !important;margin:0;margin-top:1rem}.Firewall .center,.Firewall .center::before{text-align:left !important}.commandbox{width:100% !important;margin-left:0 !important}.btn:not(button),.cbi-button{font-size:.8rem}}@media screen and (max-width:768px){body{font-size:.8rem}.cbi-progressbar::after{font-size:.6rem}.main-left{position:fixed;z-index:100;width:0}.main-left.active{width:13rem}.main-right{width:100%}.main-right.active{overflow-y:hidden}.darkMask.active{display:block}.showSide{padding:.1rem;position:relative;z-index:99;display:inline-block !important}.showSide::before{font-family:'argon' !important;font-style:normal !important;font-weight:normal !important;font-variant:normal !important;text-transform:none !important;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\e20e";font-size:1.7rem}header>.fill>.container>.flex1>.brand{display:inline-block}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.8rem}}@media screen and (max-width:600px){.mobile-hide{display:none}#maincontent>.container{margin:0 1rem 1rem 1rem}.cbi-value-title{text-align:left}[data-page="admin-system-flash"] legend{padding:1rem 0 1rem 1rem}[data-page="admin-system-flash"] .cbi-section-descr{padding:1rem 0 1rem 1rem}[data-page="admin-system-flash"] .cbi-value{padding:0 1rem}[data-page="admin-network-dhcp"] [data-tab-active="true"]{padding:1rem 1rem !important}.cbi-dynlist p{padding:.5rem 1rem}body{overflow-x:hidden}.node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field{width:16rem}.node-main-login footer{display:none}.tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar{width:0px;height:0px}.cbi-value-field,.cbi-value-description{display:block !important;padding-left:0 !important;padding-right:0 !important}[data-page="admin-system-admin-password"] .cbi-value-field{display:table-cell !important}.modal.cbi-modal{max-width:100%;max-height:none}.modal{display:flex;align-items:center;flex-wrap:wrap;width:100%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1em;border-radius:3px !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.cbi-dropdown[open]>ul.dropdown{left:.2rem !important;right:0 !important;margin-bottom:1rem}.login-page .login-container footer{display:none}}@media screen and (min-width:600px){::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar,::-webkit-scrollbar-corner{background:transparent}::-webkit-scrollbar-thumb{background:#9e9e9e}::-webkit-scrollbar-thumb:hover{background:#757575}::-webkit-scrollbar-thumb:active{background:#424242}}@media screen and (max-width:480px){.mobile-hide{display:none}.login-page .login-container{margin-left:0rem !important;width:100%}.login-page .login-container .login-form .form-login .input-group::before{color:#525461}.login-page .login-container .login-form .form-login .input-group input{color:#525461;border-bottom:white 1px solid;border-bottom:var(--white) 1px solid;border-radius:0}} \ No newline at end of file +*//*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none !important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-0.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-0.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-0.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-0.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(40%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.1)));background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,0.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width:480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@font-face{font-family:'Google Sans';src:url('data:application/font-woff2;charset=utf-8;base64,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') format('woff2'),url('data:application/font-woff;charset=utf-8;base64,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') format('woff');font-weight:normal;font-style:normal}@font-face{font-family:'TypoGraphica';src:url('../fonts/TypoGraphica.eot?#iefix') format('embedded-opentype'),url('../fonts/TypoGraphica.woff') format('woff'),url('../fonts/TypoGraphica.ttf') format('truetype'),url('../fonts/TypoGraphica.svg#TypoGraphica') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'argon';src:url('../fonts/argon.eot?u6kthm');src:url('../fonts/argon.eot?u6kthm#iefix') format('embedded-opentype'),url('../fonts/argon.ttf?u6kthm') format('truetype'),url('../fonts/argon.woff?u6kthm') format('woff'),url('../fonts/argon.svg?u6kthm#argon') format('svg');font-weight:normal;font-style:normal;font-display:block}[class^="icon-"],[class*=" icon-"]{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-expand_more:before{content:"\e20b"}.icon-menu:before{content:"\e20e"}.icon-favorite:before{content:"\e291"}.icon-spinner:before{content:"\e603"}.icon-delete:before{content:"\e900"}.icon-edit:before{content:"\e901"}.icon-use:before{content:"\e902"}.icon-loading:before{content:"\e903"}.icon-switch:before{content:"\e904"}.icon-error:before{content:"\e905"}.icon-dashboard:before{content:"\e906"}.icon-logout:before{content:"\e907"}.icon-Network:before{content:"\e908"}.icon-services:before{content:"\e909"}.icon-system:before{content:"\e90a"}.icon-vpn:before{content:"\e90b"}.icon-storage:before{content:"\e90c"}.icon-statistics:before{content:"\e90d"}.icon-hello-world:before{content:"\e90e"}.icon-angle-right:before{content:"\e90f"}.icon-password:before{content:"\e910"}.icon-user:before{content:"\e971"}.icon-question:before{content:"\f059"}.icon-docker:before{content:"\e911"}.icon-control:before{content:"\e912"}.icon-statistics1:before{content:"\e913"}.icon-asterisk:before{content:"\e914"}.icon-app:before{content:"\e915"}:root{--primary:#5e72e4;--dark-primary:#483d8b;--main-color:#09c;--header-bg:#09c;--header-color:#fff;--bar-bg:#5e72e4;--menu-bg-color:#fff;--menu-color:#5f6368;--menu-color-hover:#202124;--main-menu-color:#202124;--submenu-bg-hover:#d4d4d4;--submenu-bg-hover-active:#09c;--blue:#5e72e4;--indigo:#5603ad;--purple:#8965e0;--pink:#f3a4b5;--red:#f5365c;--orange:#fb6340;--yellow:#ffd600;--green:#2dce89;--teal:#11cdef;--cyan:#2bffc6;--gray:#8898aa;--gray-dark:#32325d;--light:#ced4da;--lighter:#e9ecef;--secondary:#f7fafc;--success:#2dce89;--info:#11cdef;--warning:#fb6340;--danger:#f5365c;--light:#adb5bd;--dark:#212529;--default:#172b4d;--white:#fff;--neutral:#fff;--darker:black;--background-color:#f4f5f7;--login-form-bg-color:rgba(244,245,247,0.8);--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--blur-radius:10px;--blur-opacity:.5;--blur-radius-dark:10px;--blur-opacity-dark:.5;--font-family-sans-serif:"Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;--font-family-normal:Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif}*{margin:0px;padding:0px;box-sizing:border-box}html,body{margin:0px;padding:0px;height:100%;font-size:16px;font-family:"Google Sans","Microsoft Yahei","WenQuanYi Micro Hei","sans-serif","Helvetica Neue","Helvetica","Hiragino Sans GB";font-family:var(--font-family-sans-serif)}html{-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{font-size:.875rem;background-color:#f4f5f7;background-color:var(--background-color);color:#32325d;color:var(--gray-dark);-webkit-tap-highlight-color:transparent}textarea{padding:.2rem}textarea:focus-visible{outline:none;border:1px solid var(--primary)}::selection{background-color:#5e72e4;background-color:var(--primary);color:#ffffff;color:var(--white)}::placeholder{color:var(--lighter)}a:link,a:visited,a:active{color:#5e72e4;color:var(--primary);text-decoration:none}a:hover{text-decoration:underline}li{list-style-type:none}.table{position:relative;display:table}.tr{display:table-row}.thead{display:table-header-group}.tbody{display:table-row-group}.tfoot{display:table-footer-group}.td,.th{line-height:normal;display:table-cell;padding:.5em;text-align:center;vertical-align:middle}.th{font-weight:bold;white-space:nowrap}.tr.placeholder{height:4em}.tr.placeholder>.td{line-height:3;position:absolute;right:0;bottom:0;left:0;padding:.4rem 0 !important;text-align:center !important;background:inherit}.td[width="33%"]{padding:1.1em 1.5rem}.table[width="33%"],.th[width="33%"],.td[width="33%"]{width:33%}.table[width="100%"],.th[width="100%"],.td[width="100%"]{width:100%}.col-1{flex:1 1 30px !important}.col-2{flex:2 2 60px !important}.col-3{flex:3 3 90px !important}.col-4{flex:4 4 120px !important}.col-5{flex:5 5 150px !important}.col-6{flex:6 6 180px !important}.col-7{flex:7 7 210px !important}.col-8{flex:8 8 240px !important}.col-9{flex:9 9 270px !important}.col-10{flex:10 10 300px !important}*{box-sizing:border-box;margin:0;padding:0}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:normal;line-height:1.1 !important;color:inherit}select{padding:.36rem .8rem;color:#555;border:thin solid #ccc;background-color:#fff;background-image:none}.btn,button,select,input,.cbi-dropdown{line-height:1.5em;padding:.5rem .75rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;transition:box-shadow .15s ease}select,.cbi-dropdown{width:inherit;cursor:default}select:not([multiple="multiple"]):focus,input:not(.cbi-button):focus,.cbi-dropdown:focus{border-color:#5e72e4;border-color:var(--primary);box-shadow:0 3px 9px rgba(50,50,9,0),3px 4px 8px rgba(94,114,228,0.1)}.cbi-dropdown,select[multiple="multiple"]{height:auto}pre{overflow:auto}code{padding:1px 3px;color:#101010;border-radius:2px;background:#ddd;font-family:inherit;font-size:inherit}abbr{cursor:help;text-decoration:underline;color:#5e72e4;color:var(--primary)}hr{margin:1rem 0;opacity:.1;border-color:#eee}ul{line-height:normal}li{list-style-type:none}h1{font-size:2rem;padding-bottom:10px;border-bottom:thin solid #eee}h2{margin:0 0 1rem 0;font-size:1.25rem;letter-spacing:.1rem;padding:1rem 1.25rem;color:#32325d;border-radius:.25rem;background:#fff;box-shadow:0 4px 8px rgba(0,0,0,0.03);font-weight:bold}h3{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark);border-radius:.25rem;background:#fff;font-weight:bold}h4{margin:0;padding:.75rem 1.25rem;font-size:.875rem;font-weight:600;color:#525f7f;font-weight:bold}h4 em{padding:0 .5rem}h5{font-size:1rem;margin:2rem 0 0 0;padding-bottom:10px}.pull-right{float:right}.pull-left{float:left}.nowrap:not(.td){white-space:nowrap}[disabled="disabled"]{pointer-events:none}.login-page{height:100%}.login-page .video{position:absolute;width:100%;height:100%;display:flex;align-items:center;justify-content:center;background-color:#000;background-color:var(--darker);overflow:hidden}.login-page .video video{width:100%;height:auto}.login-page .volume-control{position:fixed;right:1rem;top:1rem;width:1.5rem;height:1.5rem;z-index:5000;cursor:pointer;background-size:contain;background-image:url(../img/volume_high.svg)}.login-page .volume-control.mute{background-image:url(../img/volume_off.svg)}.login-page .main-bg{position:absolute;width:100%;height:100%;left:0;top:0;background-image:url(../img/blank.png);background-repeat:no-repeat;background-position:center;background-size:cover;transition:all .5s}.login-page .login-container{height:100%;margin-left:4.5rem;position:absolute;top:0px;display:flex;flex-direction:column;-webkit-box-pack:center;justify-content:center;align-items:flex-start;min-height:100%;z-index:2;width:420px;box-shadow:rgba(0,0,0,0.75) 0 0 35px -5px;margin-left:5%;background:transparent}.login-page .login-container .login-form{display:flex;flex-direction:column;-webkit-box-align:center;align-items:center;position:absolute;top:0px;width:100%;min-height:100%;max-width:420px;background-color:#fff;background-color:var(--white);-webkit-backdrop-filter:blur(var(--blur-radius));backdrop-filter:blur(var(--blur-radius));background-color:rgba(244, 245, 247, var(--blur-opacity))}.login-page .login-container .login-form .brand{display:flex;-webkit-box-align:center;align-items:center;margin:50px auto 100px 50px;color:#525461;color:var(--default);justify-content:center}.login-page .login-container .login-form .brand .icon{width:50px;height:auto;margin-right:25px}.login-page .login-container .login-form .brand .brand-text{font-size:1.25rem;font-weight:700;font-family:"TypoGraphica"}.login-page .login-container .login-form .brand:hover{text-decoration:none}.login-page .login-container .login-form .form-login{width:100%;padding:20px 50px;box-sizing:border-box}.login-page .login-container .login-form .form-login .errorbox{text-align:center;color:#fb6340;color:var(--warning);padding-bottom:2rem}.login-page .login-container .login-form .form-login .input-group{margin-bottom:1.25rem;position:relative}.login-page .login-container .login-form .form-login .input-group::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#525461;color:var(--default);font-size:1.5rem;position:absolute;z-index:100;left:10px;top:10px}.login-page .login-container .login-form .form-login .input-group .border{position:absolute;width:100%;height:1px;bottom:0;border-bottom:1px #5e72e4 solid;border-bottom:1px var(--primary) solid;transform:scaleX(0);transition:transform .3s}.login-page .login-container .login-form .form-login .input-group input{font-size:1rem;line-height:1.5em;display:block;width:100%;padding:.5rem .75rem .5rem 3rem;margin:.825rem 0;box-sizing:border-box;transition:all .3s cubic-bezier(.68, -0.55, .265, 1.55);color:#525461;color:var(--default);border:0;border-radius:0;border-bottom:1px solid #fff;border-bottom:1px solid var(--white);background-color:transparent;background-clip:padding-box;box-shadow:0 3px 2px rgba(233,236,239,0.05);outline:none}.login-page .login-container .login-form .form-login .input-group input:focus+.border{transform:scaleX(1)}.login-page .login-container .login-form .form-login .input-group .cbi-input-password{margin-bottom:2rem;position:relative}.login-page .login-container .login-form .form-login .user-icon::before{content:"\e971"}.login-page .login-container .login-form .form-login .pass-icon::before{content:"\e910"}.login-page .login-container .login-form .cbi-button-apply{width:100% !important;box-shadow:rgba(0,0,0,0.1) 0 0 50px 0;font-weight:600;font-size:15px;color:#fff;color:var(--white);text-align:center;width:100%;cursor:pointer;min-height:50px;background-color:#5e72e4 !important;background-color:var(--primary) !important;border-radius:6px;outline:none;border-width:initial;border-style:none;border-color:initial;border-image:initial;padding:10px 0px;margin:30px 0px 100px;transition:all .3s !important;letter-spacing:.8rem}.login-page .login-container .login-form .cbi-button-apply:hover,.login-page .login-container .login-form .cbi-button-apply :focus{opacity:.9}.login-page .login-container footer{box-sizing:border-box;width:100%;text-align:center;line-height:1.6rem;display:flex;justify-content:space-evenly;margin-top:auto;padding:0px 0px 30px;z-index:10;color:#525461;color:var(--default);position:absolute;bottom:0}.login-page .login-container footer .ftc{position:absolute;bottom:30px;width:100%}.login-page .login-container footer .luci-link{display:block}header,.main{width:100%}footer{font-size:.875rem;overflow:hidden;padding:1rem;text-align:right;white-space:nowrap;color:#aaa}footer>a{text-decoration:none;color:#aaa}small{font-size:90%;line-height:1.42857143;white-space:normal}.main{position:relative;top:0;bottom:0;overflow-y:auto;height:100%;display:flex;flex-direction:row}.main-left{flex-shrink:0;width:15rem;height:100%;background-color:var(--menu-bg-color);box-shadow:rgba(0,0,0,0.75) 0 0 15px -5px;overflow-x:auto;z-index:100}.main-left .sidenav-header{padding:1.5rem .5rem;text-align:center}.main-left .sidenav-header .brand{display:block;font-size:1.8rem;color:#5e72e4;color:var(--primary);font-family:"TypoGraphica";text-decoration:none;text-align:center;cursor:default;margin:0 2rem}.main-left .sidenav-header .brand .logo{max-width:100%;height:auto}.main-left::-webkit-scrollbar{width:5px;height:1px}.main-left::-webkit-scrollbar-thumb{background-color:#f6f9fc}.main-left::-webkit-scrollbar-track{background-color:#fff}.main-right{flex-grow:1;height:100%;transition:all .2s;overflow-x:hidden;overflow-y:auto;display:flex;flex-direction:column}.main-right>#maincontent{position:relative;z-index:50;flex:1;display:flex;flex-direction:column}.main-right>#maincontent>.container{margin:0 1.25rem 1rem 1.25rem;flex-grow:1}.main-right>#maincontent .Dashboard{color:var(--gray-dark) !important}.main-right>#maincontent .Dashboard h3{color:var(--gray-dark)}.main-right>#maincontent .Dashboard p{margin-bottom:3px;margin-top:3px}.main-right>#maincontent .Dashboard hr{border-top:1px solid #000}.main-right>#maincontent .Dashboard .dashboard-bg{background-color:#fff}.main-right>#maincontent .Dashboard .settings-info{padding-top:1em;padding-bottom:1em}.main-right>#maincontent .Dashboard .settings-info p span:nth-child(2){max-height:18.5px;top:4px}.main-right>#maincontent .Dashboard .settings-info .label{font-size:.7rem;padding:.2rem .6rem}header{color:#fff;color:var(--header-color);padding:0;position:relative}header.bg-primary{background-color:#5e72e4 !important;background-color:var(--primary) !important}header::after{content:"";position:absolute;height:2rem;width:100%;background-color:#5e72e4 !important;background-color:var(--primary) !important}header .fill{padding:.8rem 0;border-bottom:0 solid rgba(255,255,255,0.08) !important;display:flex}header .fill .container{height:2rem;padding:0 1.25rem;display:flex;align-items:center;width:100%}header .fill .container .flex1{flex:1}header .fill .container .flex1 .showSide{display:none;color:#fff;font-size:1.4rem}header .fill .container .flex1 .showSide:hover{text-decoration:none}header .fill .container .flex1 .brand{font-size:1.5rem;color:#fff;font-family:"TypoGraphica";text-decoration:none;padding-left:1rem;cursor:default;vertical-align:text-bottom;display:none}header .fill .container .pull-right{float:right;margin-top:0rem;display:flex}header .fill .status span{display:inline-block;font-size:.875rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;text-shadow:none;border-radius:4px;cursor:pointer;transition:all .3s;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);margin:0 .25rem}header .fill .status span:last-child{margin-right:0}header .fill .status span[data-indicator="poll-status"]{color:#fff}header .fill .status span[data-style="active"]{background-color:var(--green)}header .fill .status span[data-style="inactive"]{color:#ffffff !important;background-color:#32325d}#xhr_poll_status{display:flex;margin-left:.5rem}#xhr_poll_status *{color:#fff}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{border:0 !important}.danger{background-color:#ff7d60 !important}.warning{background-color:#f0e68c !important}.success{background-color:#5cb85c !important}.notice{background-color:#11cdef !important;color:#fff}.error{color:#f00}.alert,.alert-message{font-weight:bold;margin-bottom:1.25rem;margin-left:1.25rem;margin-right:1.25rem;padding:1rem 1.25rem;border:0;border-radius:.25rem !important;background-color:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);text-shadow:none}.alert.error,.alert-message.error{background-color:#ffd600}.alert h4,.alert-message h4{padding:.25rem 0;border-radius:4px;background-color:#ffd600}.alert .btn,.alert-message .btn{height:auto}.alert-message>h4{font-size:110%;font-weight:bold}.alert-message>*{margin:.5rem 0}.alert-message .btn{padding:.3rem .6rem}.container .alert,.container .alert-message{margin-left:0;margin-right:0;margin-top:0rem}.main .main-left{transition:all .2s}.main .main-left .nav{margin-top:.5rem}.main .main-left .nav>li>a:first-child{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.25rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav>li>a:first-child.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child.active::before{color:#fff !important}.main .main-left .nav>li>a:first-child.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav>li>a:first-child:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child:hover::before{color:#fff !important}.main .main-left .nav>li>a:first-child::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li{padding:.5rem 1rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:0}.main .main-left .nav li a{display:block;color:#5f6368;color:var(--menu-color)}.main .main-left .nav li.slide{padding:0}.main .main-left .nav li.slide ul{display:none;overflow:hidden}.main .main-left .nav li.slide:hover{background:none}.main .main-left .nav li.slide .slide-menu{margin:0 .5rem 0 2.5rem;padding:0 .5rem}.main .main-left .nav li.slide .slide-menu.active{display:block}.main .main-left .nav li.slide .slide-menu li{position:relative;border-radius:.25rem;margin:0;background:none;list-style:none}.main .main-left .nav li.slide .slide-menu li a{text-decoration:none;padding:.5rem 0}.main .main-left .nav li.slide .slide-menu li::after{content:"";position:absolute;left:0;bottom:0;width:0;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu li:hover{background:none}.main .main-left .nav li.slide .slide-menu li:hover::after{width:100%}.main .main-left .nav li.slide .slide-menu .active{background:none;color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active a{color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu .active:hover{background:none}.main .main-left .nav li.slide .slide-menu .active:hover::after{width:100%}.main .main-left .nav li .menu{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.25rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav li .menu.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu.active::before{color:#fff !important}.main .main-left .nav li .menu.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav li .menu:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu:hover::before{color:#fff !important}.main .main-left .nav li .menu::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu::after{position:absolute;right:.5rem;top:.8rem;font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-moz-osx-font-smoothing:grayscale;content:'\e90f';transition:all .15s ease;color:#ced4da;text-rendering:auto;-webkit-font-smoothing:antialiased;transition:all .3s}.main .main-left .nav li .menu[data-title=Status]:before{content:"\e906";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=System]:before{content:"\e90a";color:#fb6340}.main .main-left .nav li .menu[data-title=Services]:before{content:"\e909";color:#11cdef}.main .main-left .nav li .menu[data-title=NAS]:before{content:"\e90c";color:#f3a4b5}.main .main-left .nav li .menu[data-title=VPN]:before{content:"\e90b";color:#8965e0}.main .main-left .nav li .menu[data-title=Network]:before{content:"\e908";color:#8965e0}.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before{content:"\e90d";color:#2dce89}.main .main-left .nav li .menu[data-title=Docker]:before{content:"\e911";color:#6699ff}.main .main-left .nav li .menu[data-title=Statistics]:before{content:"\e913";color:#8965e0}.main .main-left .nav li .menu[data-title=Control]:before{content:"\e912";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=Asterisk]:before{content:"\e914";color:#fb6340}.main .main-left .nav li a[data-title=Log_out]::before,.main .main-left .nav li .food[data-title=Log_out]::before{content:"\e907";color:#adb5bd}.lg{margin:0;padding:0 !important}.logout{display:block;margin:.8rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.25rem;text-decoration:none;font-size:1rem;transition:all .2s;position:relative}.logout:before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e907";color:#32325d !important}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before{transition:transform .1s ease-in-out}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before{transition:transform .2s ease-in-out}.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before{display:none}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{font-family:inherit;font-weight:normal;font-style:normal;line-height:normal;min-width:inherit;margin:1.25rem 0;padding:0;border:0;border-radius:.25rem;background-color:#fff;box-shadow:0 0 1rem 0 rgba(136,152,170,0.15)}.cbi-section:last-child,.cbi-section-error:last-child,#iptables:last-child,.Firewall form:last-child,#cbi-network>.cbi-section-node:last-child,#cbi-wireless>.cbi-section-node:last-child,#cbi-wireless>#wifi_assoclist_table:last-child,[data-tab-title]:last-child,[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear):last-child,[data-page="admin-system-opkg"] #maincontent>.container:last-child{margin:0;border:0}.cbi-modal .cbi-section,.cbi-section .cbi-section{padding:0;box-shadow:none}.cbi-modal .cbi-tabmenu{margin-left:0}.cbi-map:not(:first-child){margin-top:1rem}.cbi-map-descr{font-size:small;line-height:1.5;padding:0 1.25rem 1rem 1.25rem}.cbi-section>.cbi-section-descr{padding-top:1rem !important;padding-bottom:1rem !important}.cbi-section>.cbi-section-descr:empty{padding-top:0 !important;padding-bottom:0rem !important}.cbi-section-descr:not(:empty){font-size:small;line-height:1.5;padding:0rem 1rem}.cbi-map-descr+fieldset{margin-top:1rem}.cbi-map-descr>abbr{cursor:help;text-decoration:underline}.cbi-section>legend{display:none !important}fieldset>fieldset,.cbi-section>.cbi-section{margin:0;padding:0;border:0;box-shadow:none}.cbi-section>h3:first-child,.panel-title{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark)}.cbi-section>h3:first-child,.cbi-section>h4:first-child,.cbi-section>p:first-child,[data-tab-title]>h3:first-child,[data-tab-title]>h4:first-child,[data-tab-title]>p:first-child{padding:1rem 1.25rem}.cbi-section p{padding:1rem}.cbi-tblsection{overflow-x:auto}table{border-spacing:0;border-collapse:collapse}table,.table{overflow-y:hidden;width:100%;font-size:90%}.table .table-titles th{background-color:#e9ecef;background-color:var(--lighter)}table>tbody>tr>td,table>tbody>tr>th,table>tfoot>tr>td,table>tfoot>tr>th,table>thead>tr>td,table>thead>tr>th,.table>.tbody>.tr>.td,.table>.tbody>.tr>.th,.table>.tfoot>.tr>.td,.table>.tfoot>.tr>.th,.table>.thead>.tr>.td,.table>.thead>.tr>.th,.table>.tr>.td.cbi-value-field,.table>.tr>.th.cbi-section-table-cell{padding:.5rem}.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td{padding:.6rem}.cbi-section-table-cell{line-height:1.1;align-self:flex-end;flex:1 1 auto}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:thin solid #ddd;padding:1.1em 1.25rem}#cbi-wireless .td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{border-top:0 !important;background-color:#f6f9fc;padding:1.1em 1.25rem;line-height:1.3rem}[data-page="admin-network-network"] .cbi-value-field .cbi-dynlist{padding:0 !important}[data-page="admin-network-network"] .td>.ifacebadge>.cbi-tooltip-container{display:flex}[data-page="admin-network-network"] .td>.ifacebadge>.cbi-tooltip-container img{vertical-align:middle}#cbi-network .tr:first-child>.td{border-top:0}.table[width="100%"]>.tr:first-child>.td{margin:auto 0}.cbi-section-table-row{margin-bottom:1rem;text-align:center !important;background:#f4f4f4}.cbi-section-table-row:last-child{margin-bottom:0}.cbi-section-table-row>.cbi-value-field .cbi-dropdown,.cbi-section-table-row>.cbi-value-field .cbi-input-select,.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{width:100%}.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{min-width:80px}.cbi-section-table-row>.cbi-value-field [data-dynlist]>input,.cbi-section-table-row>.cbi-value-field input.cbi-input-password{width:calc(100% - 1.5rem)}.cbi-section-table-row .td{text-align:center !important}.cbi-section-table-row .td .cbi-checkbox input[type="checkbox"]{margin:0}.control-group{display:inline-flex;width:100%;flex-wrap:wrap;gap:0px}.control-group input{border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;margin-right:0}.control-group input+button{border-bottom-left-radius:0;border-top-left-radius:0;margin-left:0;border-left-width:0}.control-group>*{vertical-align:middle}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n){background-color:#f9f9f9}table table,.table .table,.cbi-value-field table,.cbi-value-field .table,td>table>tbody>tr>td,.td>.table>.tbody>.tr>.td,.cbi-value-field>table>tbody>tr>td,.cbi-value-field>.table>.tbody>.tr>.td{border:0}.btn,.cbi-button,.item::after{font-size:.875rem;display:inline-block;width:auto !important;padding:.5rem .75rem;margin-left:5px;margin-right:5px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition:all .2s ease-in-out;text-align:center;vertical-align:middle;white-space:nowrap;text-decoration:none;border:0;border-radius:.25rem;background-color:#f0f0f0;background-image:none;appearance:none;-ms-touch-action:manipulation;touch-action:manipulation}.btn:last-child,.cbi-button:last-child{margin-right:0 !important}.btn:first-child,.cbi-button:first-child{margin-left:0 !important}.btn:only-child,.cbi-button:only-child{margin-left:5px !important;margin-right:5px !important}.btn:not(button) ul:not(.dropdown) li{padding:0}.cbi-button-up,.cbi-button-down{display:inline-block;min-width:0;padding:.2rem 1rem;font-size:0;color:transparent !important;background:url(../icon/arrow.svg) no-repeat center;background-size:12px 20px}.cbi-button-up{transform:scaleY(-1)}.cbi-button:not(select){appearance:none !important}.btn:hover,.btn:focus,.btn:active,.cbi-button:hover,.cbi-button:focus,.cbi-button:active,.item:hover::after,.item:focus::after,.item:active::after,.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover,.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus,.cbi-page-actions .cbi-button-apply+.cbi-button-save:active{text-decoration:none;outline:0}.btn:hover,.btn:focus,.cbi-button:hover,.cbi-button:focus,.item:hover::after,.item:focus::after{box-shadow:0 0 2px rgba(0,0,0,0.12),0 2px 2px rgba(0,0,0,0.2)}.btn:active,.cbi-button:active,.item:active::after{box-shadow:0 10px 20px rgba(0,0,0,0.19),0 6px 6px rgba(0,0,0,0.23)}.cbi-button-up:hover,.cbi-button-up:focus{box-shadow:0 0 2px rgba(0,0,0,0.12),0 -2px 2px rgba(0,0,0,0.2)}.cbi-button-up:active{box-shadow:0 -10px 20px rgba(0,0,0,0.19),0 -6px 6px rgba(0,0,0,0.23)}.btn:disabled,.cbi-button:disabled{cursor:not-allowed;pointer-events:none;opacity:.5;box-shadow:none}.alert-message [class="btn"],.modal div[class="btn"],.cbi-button-find,.cbi-button-link,.cbi-button-up,.cbi-button-down,.cbi-button-neutral,.cbi-button[name="zero"],.cbi-button[name="restart"],.cbi-button[onclick="hide_empty(this)"]{color:#fff;border:thin solid #8898aa;background-color:#8898aa}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"]{font-weight:normal;color:#fff;border:thin solid #f5365c;border:thin solid var(--red);background-color:#f5365c;background-color:var(--red)}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:normal;color:#fff;border:thin solid #eea236;background-color:#f0ad4e}.cbi-button-success,.cbi-button-download{font-weight:normal;color:#fff;border:thin solid #4cae4c;background-color:#5cb85c}.cbi-page-actions .cbi-button-link:first-child{float:left}.a-to-btn{text-decoration:none}.cbi-value-field .cbi-button-add{font-weight:bold;padding:1px 6px;display:inline-block;align-items:center}.tabs{margin:0 0 1rem 0;padding:0 1rem;background-color:#FFFFFF;border-radius:.25rem;box-shadow:0 4px 8px rgba(0,0,0,0.03);white-space:nowrap;overflow-x:auto}.tabs::-webkit-scrollbar{width:1px;height:5px}.tabs::-webkit-scrollbar-thumb{background-color:#f6f9fc}.tabs::-webkit-scrollbar-track{background-color:#fff}.tabs li[class~="active"],.tabs li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#e4e9ee;margin-bottom:0;border-radius:0}.tabs li[class~="active"] a,.tabs li:hover a{color:#5e72e4;color:var(--primary)}.tabs li{font-size:.875rem;display:inline-block;padding:.875rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0;transition:all .2s}.tabs li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.tabs li:hover{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary)}.cbi-tabmenu{color:white;padding:.5rem 1rem 0 1rem;white-space:nowrap;overflow-x:auto}.cbi-tabmenu::-webkit-scrollbar{width:1px;height:5px}.cbi-tabmenu::-webkit-scrollbar-thumb{background-color:#f6f9fc}.cbi-tabmenu::-webkit-scrollbar-track{background-color:#fff}.cbi-tabmenu li{background:#dce3e9;display:inline-block;font-size:.875rem;border-top-left-radius:.25rem;border-top-right-radius:.25rem;padding:.5rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0 .2rem}.cbi-tabmenu li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.cbi-tabmenu li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#e4e9ee;margin-bottom:0}.cbi-tabmenu li:hover a{color:#525f7f}.cbi-tabmenu li[class~="cbi-tab"]{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#e4e9ee;margin-bottom:0}.cbi-tabmenu li[class~="cbi-tab"] a{color:#5e72e4;color:var(--primary)}.cbi-tab-descr{padding:.5rem 1.5rem}.cbi-section-node{padding:0}.cbi-section .cbi-section-remove:nth-of-type(2n),.container>.cbi-section .cbi-section-node:nth-of-type(2n){background-color:#f9f9f9}[data-tab-title]{overflow:hidden;height:0;opacity:0;margin:0;padding:0rem 0rem !important}[data-tab-title] p{margin-left:1rem;margin-bottom:1rem}[data-tab-active="true"]{overflow:visible;height:auto;opacity:1;transition:opacity .25s ease-in;margin:inherit !important}.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3),.cbi-section[id] .cbi-section-node:nth-of-type(4n+4){background-color:#f9f9f9}.cbi-section-node-tabbed{margin-top:0;padding:0;border:0 solid #d4d4d4;border-radius:.25rem}.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#f9f9f9}.cbi-value-field{display:table-cell}.cbi-value-description{line-height:1.25;display:table-cell}.cbi-value-description abbr{color:#32325d;color:var(--gray-dark)}.cbi-value-description{font-size:small;padding:.5rem;opacity:.5}.cbi-value-title{display:table-cell;float:left;width:23rem;padding-right:2rem;text-align:right;word-wrap:break-word}.cbi-value{display:inline-block;width:100%;padding:.35rem 1rem .2rem 1rem;line-height:2.4rem}.cbi-value:first-child{padding-top:1rem}.cbi-value:last-child{padding-bottom:1rem}.cbi-value ul{line-height:1.25}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"],.cbi-value textarea{min-width:18rem}.cbi-value input[type="password"]{border-bottom-right-radius:0;border-top-right-radius:0;font-size:.875rem;margin:.25rem 0 .25rem .1rem}.cbi-value input[type="password"]+.cbi-button-neutral{display:flex;align-items:center;justify-content:center;width:2.5rem !important;padding:.5rem 0;margin:.25rem 0;font-weight:normal;font-size:1.2rem;line-height:1.5rem;color:#fff;outline:0;background-color:#8898aa;box-shadow:none;border:1px solid #8898aa;border-radius:.25rem;border-top-left-radius:0;border-bottom-left-radius:0}#cbi-firewall-zone .cbi-input-select,#cbi-network-switch_vlan .cbi-input-select{min-width:11rem}#cbi-network-switch_vlan .cbi-input-text{max-width:3rem}.cbi-input-invalid{color:#f5365c !important;border-color:#f5365c !important}.cbi-section-error{font-weight:bold;line-height:1.42857143;margin:18px;padding:6px;border:thin solid #f5365c;border-radius:3px;background-color:#fce6e6}.cbi-section-error ul{margin:0 0 0 20px}.cbi-section-error ul li{font-weight:bold;color:#f5365c}.td[data-title]::before{font-weight:bold;display:none;padding:.25rem 0;content:attr(data-title) ":\20";text-align:left;white-space:nowrap}.tr.placeholder .td[data-title]::before{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-weight:bold;display:table-cell;align-self:center;flex:1 1 5%;padding:.25rem;content:attr(data-title) "\20";text-align:center;vertical-align:middle;white-space:normal;word-wrap:break-word}.cbi-rowstyle-1{background-color:#f9f9f9}.cbi-rowstyle-2{background-color:#eee}.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#fff !important}.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{width:auto !important}.td.cbi-section-actions{text-align:right !important;vertical-align:middle}.td.cbi-section-actions>*{display:inline-flex}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:0 5px;display:flex;align-items:center}.td.cbi-section-actions>*>form{display:inline-flex;margin:0}.cbi-checkbox{margin:0 .25rem}.cbi-dynlist{line-height:1.3;flex-direction:column;min-height:30px;cursor:text}.cbi-dynlist>.item{display:inline-flex;flex-wrap:nowrap;margin:.25rem 0;position:relative;max-width:25rem;pointer-events:none;color:#8898aa;outline:0}.cbi-dynlist>.item::after{content:"\00D7";pointer-events:auto;display:flex;align-items:center;justify-content:center;width:2.5rem !important;margin:0;font-weight:normal;font-size:1.2rem;line-height:1.5rem;color:#fff;border:1px solid #f5365c;border-radius:0 .25rem .25rem 0;outline:0;background-color:var(--red);background-image:none;box-shadow:none;box-sizing:border-box}.cbi-dynlist>.item>span{display:block;padding:.5rem .75rem;min-width:15.5rem;width:15.5rem;transition:box-shadow .15s ease;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-break:break-word;font-size:.875rem;line-height:24px;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem 0 0 .25rem;outline:0;background-image:none;box-shadow:none;box-sizing:border-box}.cbi-dynlist>.add-item{display:inline-flex;align-items:center;width:100%;min-width:16rem;margin:.25rem 0;gap:0;flex-wrap:nowrap}.cbi-dynlist>.add-item input{display:block;padding:.5rem .75rem;box-sizing:border-box;min-width:15.5rem;width:15.5rem;transition:box-shadow .15s ease;white-space:nowrap;word-break:break-word;font-size:.875rem;line-height:1.5rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem 0 0 .25rem;border-right-width:0;outline:0;background-image:none;box-shadow:none}.cbi-dynlist>.add-item .cbi-button{display:flex;width:auto !important;padding-left:.8rem;padding-right:.8rem;margin-left:0;align-items:center;justify-content:center;font-size:.875rem;line-height:1.5rem;outline:0;background-image:none;background-color:var(--gray);box-shadow:none;color:var(--white);border-color:var(--gray);border-radius:.25rem;border-top-left-radius:0;border-bottom-left-radius:0}.cbi-dynlist>.add-item .cbi-button-add{width:2.5rem !important;padding:.5rem 0 !important;font-weight:normal;font-size:1.2rem;color:#fff;background-color:var(--primary);border:1px solid var(--primary)}.cbi-dynlist>.add-item:not([ondrop])>input{overflow:hidden;min-width:15.5rem;width:15.5rem;white-space:nowrap;text-overflow:ellipsis}.cbi-dynlist[name="sshkeys"]>.item{max-width:none}.cbi-dynlist>.cbi-dynlist>.add-item[ondrop]>input{min-width:13rem}.cbi-dynlist,.cbi-dropdown{position:relative;display:inline-flex;min-height:2.1875rem}.cbi-dropdown[placeholder*="select"]{max-width:25rem;height:auto;margin-top:-3px}.cbi-dropdown>ul{display:flex;overflow-x:hidden;overflow-y:auto;width:100%;margin:0 !important;padding:0;list-style:none;outline:0}.cbi-dropdown>ul.preview{display:none}.cbi-button-apply>ul.preview{display:none}.cbi-button-apply>ul.preview li{color:#fff}.cbi-button-apply>ul:first-child li{color:#fff}.cbi-dropdown>.open{flex-basis:15px}.cbi-dropdown>.open,.cbi-dropdown>.more{font-size:1rem;font-weight:900;line-height:1em;display:flex;flex-direction:column;flex-grow:0;flex-shrink:0;justify-content:center;padding:0 .25em;cursor:default;text-align:center;outline:0}.cbi-dropdown>.more,.cbi-dropdown>ul>li[placeholder]{font-weight:bold;display:none;color:#777;text-shadow:none}.cbi-dropdown>ul>li{display:none;overflow:hidden;align-items:center;align-self:center;flex-grow:1;flex-shrink:1;min-height:20px;padding:.125rem .25em;white-space:nowrap;text-overflow:ellipsis}.cbi-dropdown>ul>li .hide-open{display:initial}.cbi-dropdown>ul>li .hide-close{display:none}.cbi-dropdown>ul>li[display]:not([display="0"]){border-left:thin solid #ccc}.cbi-dropdown[empty]>ul{max-width:1px}.cbi-dropdown>ul>li>form{display:none;margin:0;padding:0;pointer-events:none}.cbi-dropdown>ul>li img{margin-right:.25em;vertical-align:middle}.cbi-dropdown>ul>li>form>input[type="checkbox"]{height:auto;margin:0}.cbi-dropdown>ul>li input[type="text"]{height:20px}.cbi-dropdown[open]>ul.dropdown{position:absolute;z-index:1100;display:block;width:auto;min-width:100%;max-width:none;max-height:200px !important;border:0 solid #918e8c;background:#ffffff;box-shadow:0 0 4px #918e8c;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;color:var(--main-menu-color);margin-left:0 !important;left:0}.cbi-dropdown[open]>ul.dropdown li{color:#000}.cbi-dropdown>ul>li[display],.cbi-dropdown[open]>ul.preview,.cbi-dropdown[open]>ul.dropdown>li,.cbi-dropdown[multiple]>ul>li>label,.cbi-dropdown[multiple][open]>ul.dropdown>li,.cbi-dropdown[multiple][more]>.more,.cbi-dropdown[multiple][empty]>.more{display:flex;align-items:center;flex-grow:1}.cbi-dropdown[empty]>ul>li,.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder],.cbi-dropdown[multiple][open]>ul.dropdown>li>form{display:block}.cbi-dropdown[open]>ul.dropdown>li .hide-open{display:none}.cbi-dropdown[open]>ul.dropdown>li .hide-close{display:initial}.cbi-dropdown[open]>ul.dropdown>li{border-bottom:thin solid #ccc;padding:.5rem .8rem}.cbi-dropdown[open]>ul.dropdown>li label{margin-left:.5rem}.cbi-dropdown[open]>ul.dropdown>li[selected]{background:#e4e9ee}.cbi-dropdown[open]>ul.dropdown>li.focus{background:#e4e9ee;outline:none}.cbi-dropdown[open]>ul.dropdown>li:last-child{margin-bottom:0;border-bottom:0}.cbi-dropdown[open]>ul.dropdown>li[unselectable]{opacity:.7}.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child{width:100%}.cbi-dropdown[disabled]{pointer-events:none;opacity:.6}.cbi-dropdown .zonebadge{width:100%}.cbi-dropdown[open] .zonebadge{width:auto}.cbi-progressbar{position:relative;display:flex;width:100%;font-size:.75rem;background-color:#e9ecef;border-radius:.5rem;height:1rem;overflow:hidden}.cbi-progressbar>div{display:block;position:absolute;height:100%;background-color:var(--bar-bg);border-radius:.5rem;transition:width .3s}.cbi-progressbar::after{content:attr(title);position:absolute;font-size:.75rem;color:var(--bs-heading-color);width:100%;height:100%;text-align:center;line-height:1rem;z-index:2}#modal_overlay{position:fixed;z-index:900;top:0;right:10000px;bottom:0;left:-10000px;overflow-y:scroll;transition:opacity .125s ease-in;opacity:0;background:rgba(0,0,0,0.7);-webkit-overflow-scrolling:touch}.modal{display:flex;align-items:center;flex-wrap:wrap;width:90%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1rem;border-radius:.25rem !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>*{line-height:normal;flex-basis:100%;margin-bottom:.5em;max-width:100%}.modal>pre,.modal>textarea{font-size:1rem;font-size-adjust:.35;overflow:auto;margin-bottom:.5em;padding:8.5px;cursor:auto;white-space:pre-wrap;color:#eee;outline:0;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>h4{display:block;flex-grow:1;max-width:none;padding:1rem;margin:-1rem -1rem 0 -1rem;font-size:1rem;box-shadow:0 4px 8px rgba(0,0,0,0.03);border-radius:.25rem 0 0 .25rem}.modal h5{margin-top:1rem;font-weight:600}.modal label>input[type="checkbox"]{top:0}.modal ul{margin-left:2.2em}.modal ul:not(.cbi-tabmenu){margin-top:1rem}.modal ul li{list-style-type:square;color:#808080}.modal p{word-break:break-word;margin-top:1rem}.modal .label{font-size:.6rem;font-weight:normal;padding:.1rem .3rem;padding-bottom:0;cursor:default;border-radius:0}.modal .label.warning{background-color:#f0ad4e !important}.modal .btn{padding:.45rem .8rem}.modal.cbi-modal{max-width:90%;max-height:none}body.modal-overlay-active{overflow:hidden;height:100vh}body.modal-overlay-active #modal_overlay{right:0;left:0;opacity:1}.spinning{position:relative;padding-left:32px !important}.spinning::before{position:absolute;top:0;bottom:0;left:.2em;width:32px;content:"";background:url(/luci-static/resources/icons/loading.gif) no-repeat center;background-size:16px}#view{border-radius:.25rem;overflow:hidden}#view>.spinning{position:fixed;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);padding:1rem;border-radius:.5rem;background:#ffffff;box-shadow:0 0 1rem 0 rgba(136,152,170,0.15)}.hidden{display:none}.left,.left::before{text-align:left !important}.right,.right::before{text-align:right !important}.center,.center::before{text-align:center !important}.top{align-self:flex-start !important;vertical-align:top !important}.bottom{align-self:flex-end !important;vertical-align:bottom !important}.inline{display:inline}.cbi-page-actions{padding:1rem;text-align:right;justify-content:flex-end}.cbi-page-actions>form[method="post"]{display:inline-block}.th[data-type="button"],.td[data-type="button"],.th[data-type="fvalue"],.td[data-type="fvalue"]{flex:1 1 2em;text-align:center}.ifacebadge{display:inline-flex;align-items:center;gap:.2rem;padding:.25rem .8rem;background:#eee;border-radius:4px}td>.ifacebadge,.td>.ifacebadge{font-size:.875rem;background-color:#f0f0f0}.ifacebadge>em,.ifacebadge>img{display:inline-block;margin:0 .75rem}.ifacebadge>img+img{margin:0 .2rem 0 0}.network-status-table{display:flex;flex-wrap:wrap}.network-status-table .ifacebox{flex-grow:1;border-radius:.25rem;overflow:hidden;margin:1rem}.network-status-table .ifacebox-body{display:flex;flex-direction:column;height:100%;gap:.5em}.network-status-table .ifacebox-body>span{flex:10 10 auto}.network-status-table .ifacebox-body>div{display:flex;flex-wrap:wrap;gap:.5rem;height:100%}.network-status-table .ifacebox-body .ifacebadge{align-items:center;flex:1 1 auto;min-width:220px;padding:.5em;background-color:#fff}.network-status-table .ifacebox-body .ifacebadge>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cbi-input-textarea{font-family:inherit;width:100%;font-size:.875rem;min-height:14rem;padding:.8rem;color:#8898aa;border-radius:.25rem;border:1px solid #dee2e6;min-width:16rem}#content_syslog{box-shadow:0 4px 8px rgba(0,0,0,0.03)}#syslog{font-size:small;font-family:'Google Sans';line-height:1.25;overflow-y:hidden;width:100%;min-height:15rem;padding:1rem;resize:none;color:#242424;border:0;border-radius:.25rem;background-color:#ffffff}#syslog:focus{outline:0}.uci-change-list{font-family:inherit;overflow:scroll;width:100%;display:flex;flex-direction:column;flex-wrap:wrap}.uci-change-list ins,.uci-change-legend-label ins{display:block;padding:2px;text-decoration:none;border:thin solid #0f0;background-color:#cfc}.uci-change-list del,.uci-change-legend-label del{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #f00;background-color:#fcc}.uci-change-list var,.uci-change-legend-label var{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #ccc;background-color:#eee}.uci-change-list var ins,.uci-change-list var del{font-style:normal;padding:0;white-space:pre;border:0}.uci-change-legend{padding:5px}.uci-change-legend-label{float:left;width:150px}.uci-change-legend-label>ins,.uci-change-legend-label>del,.uci-change-legend-label>var{display:block;float:left;width:10px;height:10px;margin-right:4px}.uci-change-legend-label var ins,.uci-change-legend-label var del{line-height:.4;border:0}.uci-change-list var,.uci-change-list del,.uci-change-list ins{padding:.5rem}.uci-dialog .cbi-section{padding:.5rem}.uci-dialog .cbi-section .uci-change-legend{line-height:15px;padding:10px 20px 0 20px}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label{padding:0;margin:0;position:relative;float:none;display:inline-block;width:25%}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>ins,.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>del{width:14px;height:14px}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var{position:relative;width:14px;height:14px}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var ins,.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var del{position:absolute;left:2px;top:2px;right:2px;bottom:2px}.uci-dialog .cbi-section .uci-change-list{overflow:auto}.uci-dialog .cbi-section .uci-change-list+.right .btn{color:#333}.uci-dialog .cbi-section .uci-change-list+.right .cbi-dropdown ul:not(.dropdown) li{color:#fff}.uci-dialog .cbi-section .uci-change-list+.right .cbi-button{padding:.45rem .8rem}#iwsvg,#iwsvg2,#bwsvg{border:thin solid #d4d4d4 !important}#iwsvg,[data-page="admin-status-realtime-bandwidth"] #bwsvg{border-top:0 !important}.ifacebox{line-height:1.25;display:inline-flex;overflow:hidden;flex-direction:column;border-radius:4px;min-width:100px;background-color:#f9f9f9}.ifacebox-head{padding:.25em;background:#eee}.ifacebox-head.active{background:#5e72e4;background:var(--primary)}.ifacebox-head.active *{color:#fff;color:var(--white)}.ifacebox-body{padding:.875rem 1rem;line-height:1.6em}.cbi-image-button{margin-left:.5rem}.zonebadge{display:inline-block;padding:.2rem .5rem;border-radius:4px}.zonebadge .ifacebadge{margin:.1rem .2rem;padding:.2rem .3rem;border:thin solid #6c6c6c}.zonebadge>input[type="text"]{min-width:10rem;margin-top:.3rem;padding:.16rem 1rem}.zonebadge>em,.zonebadge>strong{display:inline-block;margin:0 .2rem}.cbi-value-field .cbi-input-checkbox,.cbi-value-field .cbi-input-radio{margin-top:.1rem}.cbi-value-field>ul>li{display:flex}.cbi-value-field>ul>li>label{margin-top:.5rem}.cbi-value-field>ul>li .ifacebadge{margin-top:-0.5rem;margin-left:.4rem;background-color:#eee}.cbi-section-table-row>.cbi-value-field .cbi-dropdown{min-width:3rem}.cbi-section-create{display:inline-flex;align-items:center;padding:.5rem 1rem}.cbi-section-remove{padding:.5rem 1rem}div.cbi-value var,td.cbi-value-field var,.td.cbi-value-field var{font-style:italic;color:#0069d6}.cbi-optionals{padding:1rem 1rem 0 1rem;border-top:thin solid #ccc}.cbi-dropdown-container{position:relative}.cbi-tooltip-container,span[data-tooltip],span[data-tooltip] .label{cursor:help !important}.cbi-tooltip{position:absolute;z-index:1000;left:-1000px;padding:2px 5px;transition:opacity .25s ease-out;white-space:pre;pointer-events:none;opacity:0;border-radius:3px;background:#fff;box-shadow:0 0 2px #444}.cbi-tooltip-container:hover .cbi-tooltip{left:auto;transition:opacity .25s ease-in;opacity:1}.zonebadge .cbi-tooltip{margin:-1.5rem 0 0 -0.5rem;padding:.25rem;background:inherit}.zonebadge-empty{color:#404040;background:repeating-linear-gradient(45deg, rgba(204,204,204,0.5), rgba(204,204,204,0.5) 5px, rgba(255,255,255,0.5) 5px, rgba(255,255,255,0.5) 10px)}.zone-forwards{display:flex;min-width:10rem}.zone-forwards>*{flex:1 1 45%}.zone-forwards>span{flex-basis:10%;padding:0 .25rem;text-align:center}.zone-forwards .zone-src,.zone-forwards .zone-dest{display:flex;flex-direction:column}.label{font-size:.875rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;color:#fff !important;border-radius:3px;background-color:#bfbfbf;text-shadow:none}label>input[type="checkbox"],label>input[type="radio"]{position:relative;top:.4rem;right:.2rem;margin:0;vertical-align:bottom}label[data-index][data-depends]{padding-right:2em}.showSide{display:none}.darkMask{position:fixed;z-index:99;display:none;width:100%;height:100%;content:"";top:0;background-color:rgba(0,0,0,0.56);transition:all .2s}.darkMask.active{display:block}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1.2rem;font-size-adjust:.35;line-height:normal;display:block;overflow-y:hidden;width:100%;padding:8.5px;white-space:pre;color:#eee;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}[data-page="admin-network-diagnostics"] .table{box-shadow:none}[data-page="admin-network-diagnostics"] .cbi-section{padding:1rem;font-family:monospace;background:#fff !important}[data-page="admin-network-diagnostics"] textarea{background:transparent;border-radius:.25rem;font-family:'Google Sans' !important;color:#8898aa;border:1px solid #dee2e6;padding:.5rem}[data-page="admin-network-diagnostics"] .tr>.td{background-color:#fff !important;border-bottom:1px solid #dee2e6 !important}input[name="ping"],input[name="traceroute"],input[name="nslookup"]{width:80%}.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2),.node-status-processes>.main .table .tr .td:nth-child(3){white-space:normal}div[style*="display:grid;grid-template-columns:repeat"]{display:flex !important;justify-content:space-evenly !important;padding-bottom:1rem;flex-wrap:wrap;font-family:'Google Sans'}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox{text-align:center;flex-basis:100px}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body{font-size:.7rem;padding:.875rem}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body .cbi-tooltip-container{font-size:inherit !important}@media screen and (max-width:484px){div[style*="display:grid;grid-template-columns:repeat"] .ifacebox{flex-basis:80px}div[style*="display:grid;grid-template-columns:repeat"] .ifacebox .ifacebox-body{padding:.875rem .5rem;font-size:.6rem}}[data-page="admin-system-attendedsysupgrade"] #view .cbi-button{margin-left:0 !important;margin-top:1rem !important}[data-page="admin-system-reboot"] p{padding-left:1.5rem}[data-page="admin-system-reboot"] p>span{position:relative;top:.1rem;left:1rem}[data-page="admin-system-reboot"] .cbi-button{background:#fb6340 !important;border-color:#fb6340 !important;margin-left:0 !important}[data-page="admin-system-reboot"] #view>h2:first-child+p{margin-bottom:1rem}[data-page="admin-system-poweroff"] .container h2+br+p{margin-bottom:1rem;padding-left:1.5rem}[data-page="admin-vpn-passwall"] h4{background:transparent}[data-page="admin-system-filetransfer"] #cbi-upload{margin-top:0}[data-page="admin-system-filetransfer"] .cbi-section-table{box-shadow:0 4px 8px rgba(0,0,0,0.03)}#cbi-samba [data-tab="template"] .cbi-value-field{display:block}#cbi-samba [data-tab="template"] .cbi-value-title{width:auto;padding-bottom:.6rem}[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr{margin-left:0;color:#32325d;color:var(--gray-dark)}[data-page="admin-system-admin-sshkeys"] .cbi-dynlist{margin-left:1rem}[data-page="admin-system-opkg"] h2{margin-left:0;color:#32325d;color:var(--gray-dark)}[data-page="admin-system-opkg"] input[name="filter_i18n"]{top:2px;vertical-align:text-top}.controls{margin:.5em 1rem 1em 1rem !important}.controls>*>.btn:not([aria-label$="page"]){flex-grow:initial !important;margin-top:.25rem}.controls>#pager>.btn[aria-label$="page"]{font-size:1.4rem;font-weight:bold}.controls>*>label{margin-bottom:.2rem}[data-page="admin-system-opkg"] div.btn{line-height:3;display:inline;padding:.3rem .6rem}[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{margin-top:1rem;padding-top:.01rem}[data-page="admin-system-opkg"] #maincontent>.container{margin:0 1.25rem 1rem 1.25rem;margin-bottom:1rem}.td.version,.td.size{white-space:normal !important;word-break:break-word}.cbi-tabmenu+.cbi-section{margin-top:0}[data-page="admin-system-system"] .control-group{margin-top:.5rem}[data-page="admin-system-system"] .cbi-dynlist{margin:.25rem 0}[data-page="admin-system-startup"] [data-tab-title] p{margin-left:0;margin-bottom:0;position:relative}[data-page="admin-system-startup"] textarea{line-height:1.25;overflow-y:auto;width:100%;min-height:15rem;padding:1rem;resize:none;color:#8898aa;border-radius:.25rem;border:1px solid #dee2e6}[data-page="admin-system-startup"] textarea:focus-visible{outline:none;box-shadow:none;border:1px solid var(--primary)}[data-page="admin-system-crontab"] #view p{margin-bottom:1rem}[data-page="admin-system-crontab"] #view p:last-child{margin-bottom:0}[data-page="admin-system-crontab"] #view p textarea{line-height:1.25;overflow-y:hidden;width:100%;min-height:15rem;padding:1rem;resize:none;background-color:transparent;background:var(--white);outline:none;color:#8898aa;border-radius:.25rem;border:1px solid #dee2e6}[data-page="admin-system-attendedsysupgrade-configuration"] .cbi-map .cbi-map-descr{padding-bottom:0}[data-page="admin-system-flash"] .cbi-value{padding:0 1rem}[data-page="admin-system-flash"] .cbi-section .cbi-section{margin-top:0}[data-page="admin-system-flash"] .cbi-map-tabbed{border-radius:.25rem}[data-page="admin-system-flash"] .cbi-section-node{padding-top:0;padding-bottom:.5rem}[data-page="admin-system-flash"] legend{font-size:1.2rem;width:100%;display:block;border-bottom:1px solid rgba(0,0,0,0.05);line-height:1.5;margin-bottom:0;letter-spacing:.1rem;color:#32325d;font-weight:bold;padding:1rem 0 1rem 1rem}[data-page="admin-system-flash"] .cbi-section-descr{font-weight:600;padding:1rem 0 1rem 1rem;color:#525f7f}[data-page="admin-system-flash"] .cbi-page-actions{padding:0rem 1rem 1rem 0rem}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.25rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal !important}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{vertical-align:text-top;top:auto}#cbi-wireless>#wifi_assoclist_table>.tr{box-shadow:inset 1px -1px 0 #ddd,inset -1px -1px 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td{right:33px;bottom:33px;left:33px;border-top:thin solid #ddd !important}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles{box-shadow:inset 1px 0 0 #ddd,inset -1px 0 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th{border-bottom:thin solid #ddd;box-shadow:0 -1px 0 0 #ddd}#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"]{width:23rem}[data-page="admin-network-dhcp"] .cbi-value{padding:0}[data-page="admin-network-dhcp"] [data-tab-active="true"]{padding:1rem 1rem !important}#iptables{margin:0}.Firewall form{margin:2rem 2rem 0 0;padding:0;box-shadow:none}#cbi-firewall-redirect table *,#cbi-network-switch_vlan table *,#cbi-firewall-zone table *{font-size:small}#cbi-firewall-redirect table input[type="text"],#cbi-network-switch_vlan table input[type="text"],#cbi-firewall-zone table input[type="text"]{width:5rem}#cbi-firewall-redirect table select,#cbi-network-switch_vlan table select,#cbi-firewall-zone table select{min-width:3.5rem}#cbi-network-switch_vlan .th,#cbi-network-switch_vlan .td{flex-basis:12%}#cbi-firewall-zone .table,#cbi-network-switch_vlan .table{display:block}#cbi-firewall-zone .td,#cbi-network-switch_vlan .td{width:100%}[data-page="admin-network-firewall-custom"] #view p,[data-page="admin-status-routes"] #view p{padding:0 1.5rem;margin-bottom:1rem}[data-page="admin-network-firewall-custom"] #view p textarea,[data-page="admin-status-routes"] #view p textarea{padding:1rem;border-radius:.25rem}[data-page="admin-network-firewall-custom"] #view>h3,[data-page="admin-status-routes"] #view>h3{border-radius:.25rem .25rem 0 0}#applyreboot-container{margin:2rem}#applyreboot-section{line-height:300%;margin:2rem}.OpenVPN a{line-height:initial !important}.commandbox{width:24% !important;margin:10px 0 0 10px !important;padding:.5rem 1rem;border-bottom:thin solid #ccc;background:#eee;box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.commandbox h3{line-height:normal !important;overflow:hidden;margin:6px 0 !important;white-space:nowrap;text-overflow:ellipsis}.commandbox div{left:auto !important}.commandbox code{position:absolute;overflow:hidden;max-width:60%;margin-left:4px;padding:2px 3px;white-space:nowrap;text-overflow:ellipsis}.commandbox code:hover{overflow-y:auto;max-height:50px;white-space:normal}.commandbox p:first-of-type{margin-top:-6px}.commandbox p:nth-of-type(2){margin-top:2px}[data-page^="admin-system-commands"] .panel-title,[data-page^="command-cfg"] .mobile-hide,[data-page^="command-cfg"] .showSide{display:none}#command-rc-output .alert-message{line-height:1.42857143;position:absolute;top:40px;right:32px;max-width:40%;margin:0;animation:anim-fade-in 1.5s forwards;word-break:break-word;opacity:0}@keyframes anim-fade-in{100%{opacity:1}}input[type="checkbox"]{appearance:none !important;-webkit-appearance:none !important;border:1px solid var(--primary);width:16px !important;height:16px !important;padding:0;cursor:pointer;transition:all .2s;margin:.75rem 0 0 0}input[type="checkbox"]:checked{border:1px solid #5e72e4;border:1px solid var(--primary);background-image:url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important;background-color:#5e72e4;background-color:var(--primary);background-size:70%;background-repeat:no-repeat;background-position:center}.fb-container .cbi-button{height:auto !important}#cbi-usb_printer-printer em{display:block;padding:1rem;text-align:center}pre.command-output{padding:1.5rem}[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"]{padding:1.5rem !important}[data-page="admin-nlbw-backup"] form{padding-left:1.5rem}[data-page="admin-status-iptables"] .right{margin-bottom:0 !important}[data-page="admin-services-ttyd"] .container{display:flex;flex-direction:column}[data-page="admin-services-ttyd"] #view{flex:1}[data-page="admin-services-ttyd"] #view iframe{height:100%}[data-page="admin-system-fileassistant"] .fb-container .panel-title{padding:.5rem .75rem !important}[data-page="admin-system-fileassistant"] .cbi-section.fb-container{padding:.5rem}[data-page="admin-system-fileassistant"] .fb-container .panel-container{border-bottom-color:#dee2e6}[data-page^="admin-services-openclash"] .cbi-tabmenu>li{border-right:none !important;margin:0 .4rem 0 0 !important}[data-page^="admin-services-openclash"] .cbi-tabmenu>li:last-child{margin-right:0 !important}[data-page^="admin-services-openclash"] #tab-content .dom{padding:0 1rem 1rem 1rem}[data-page^="admin-services-openclash"] .cbi-input-file{padding:.2813rem;box-sizing:content-box;width:15rem !important}[data-page^="admin-services-openclash"] [id="container.openclash.config.debug"] fieldset{border:none !important;padding:1rem !important}[data-page^="admin-services-openclash"] #diag-rc-output>pre,[data-page^="admin-services-openclash"] #dns-rc-output>pre{font-size:.875rem;color:#8898aa;border:1px solid #dee2e6;background-color:transparent;border-radius:.25rem;font-family:'Google Sans' !important;box-shadow:none}[data-page^="admin-services-openclash"] #debug-rc-output>textarea{font-family:'Google Sans' !important}[data-page^="admin-services-openclash"] .CodeMirror{font-size:inherit;font-family:'Google Sans' !important}[data-page^="admin-services-openclash"] .cbi-button-up,[data-page^="admin-services-openclash"] .cbi-button-down{padding:.8rem 1.5rem;background-color:#f1f1f1;font-size:0}[data-page^="admin-services-openclash"] select#CORE_VERSION,[data-page^="admin-services-openclash"] select#RELEASE_BRANCH{width:auto}@media all and (-ms-high-contrast:none){.main>.main-left>.nav>.slide>.menu::before{top:30.25%}.main>.main-left>.nav>li:last-child::before{top:20%}.showSide::before{top:-12px}}@media screen and (max-width:1600px){header>.fill>.container>#logo{margin:0 2.5rem 0 .5rem}.main-left{width:calc(0% + 13rem)}.btn:not(button),.label{padding:.5rem .75rem}.cbi-value-title{width:15rem;padding-right:.6rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"],.cbi-value textarea{min-width:18rem}#cbi-firewall-zone .cbi-input-select{min-width:9rem}.cbi-input-textarea{font-size:small}.node-admin-status>.main fieldset li>a{padding:.3rem .6rem}}@media screen and (max-width:1366px){header>.fill>.container{cursor:default}.main-left{width:calc(0% + 13rem)}.tabs>li>a,.cbi-tabmenu>li>a{padding:.2rem .8rem}.panel-title{font-size:1.1rem;padding-bottom:1rem}table{font-size:.875rem !important;width:100% !important}.table .cbi-input-text{width:100%}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:16rem}#cbi-firewall-zone .cbi-input-select{min-width:5.5rem}.main>.main-left>.nav>li,.main>.main-left>.nav>li>a,.main .main-left .nav>li>a:first-child,.main>.main-left>.nav>.slide>.menu,.main>.main-left>.nav>li>[data-title="Log_out"]{font-size:.9rem}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.875rem}#modal_overlay{top:0rem}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table){display:block}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table),[data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table),[data-page="admin-network-hosts"] .table,[data-page="admin-network-routes"] .table{overflow-y:visible}.commandbox{width:32% !important}.btn:not(button),.cbi-button{font-size:.875rem}}@media screen and (max-width:1152px){header>.fill>.container>#logo{display:none}header>.fill>.container>.brand{position:relative}html,.main{overflow-y:visible}.main>.loading>span{top:25%}.main-left{width:calc(0% + 13rem)}body:not(.logged-in) .showSide{visibility:hidden;width:0;margin:0}.node-main-login>.main .cbi-value-title{text-align:left}.cbi-value-title{width:12rem;padding-right:1rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"]{width:16rem;min-width:16rem}.cbi-value input[name^="pw"],.cbi-value input[data-update="change"]:nth-child(2){width:13rem !important;min-width:13rem}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1rem}.table{display:block}.Interfaces .table{overflow-x:hidden}#packages.table{display:grid}.tr{display:flex;flex-direction:row;flex-wrap:wrap}.Overview .table[width="100%"]>.tr{flex-wrap:nowrap}.tr.placeholder{border-bottom:thin solid #ddd}.tr.placeholder>.td,#cbi-firewall .tr>.td,#cbi-network .tr:nth-child(2)>.td,.cbi-section #wifi_assoclist_table .tr>.td{border-top:0}.th,.td{display:inline-block;align-self:flex-start;flex:2 2 10%;text-overflow:ellipsis;word-wrap:break-word}.td select,.td input[type="text"]{width:100%;word-wrap:normal}.td [data-dynlist]>input,.td input.cbi-input-password{width:calc(100% - 1.5rem)}.td[data-type="button"],.td[data-type="fvalue"]{flex:1 1 12.5%;text-align:left}.th.cbi-value-field,.td.cbi-value-field,.th.cbi-section-table-cell,.td.cbi-section-table-cell{flex-basis:auto;padding-top:1rem}.cbi-section-table-row{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.td.cbi-value-field,.cbi-section-table-cell{display:inline-block;flex:10 10 auto;flex-basis:50%;text-align:center}.td.cbi-section-actions{vertical-align:bottom}.tr.table-titles,.tr.cbi-section-table-titles,.tr.cbi-section-table-descr{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-size:.9rem;display:block;flex:1 1 100%;border-bottom:thin solid rgba(0,0,0,0.26);background:#e9ecef}.td[data-title],[data-page^="admin-status-realtime"] .td[id]{text-align:left}.td[data-title]::before{display:block}.cbi-button+.cbi-button{margin-left:0}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:2.1px 3px}.Firewall form{position:static !important;margin:0 0 2rem 0;padding:2rem;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.Firewall form input{width:100% !important;margin:0;margin-top:1rem}.Firewall .center,.Firewall .center::before{text-align:left !important}.commandbox{width:100% !important;margin-left:0 !important}.btn:not(button),.cbi-button{font-size:.875rem}}@media screen and (max-width:768px){body{font-size:.875rem}.cbi-progressbar::after{font-size:.6rem}.main-left{position:fixed;z-index:100;width:0}.main-left.active{width:13rem}.main-right{width:100%}.main-right.active{overflow-y:hidden}.darkMask.active{display:block}.showSide{padding:.1rem;position:relative;z-index:99;display:inline-block !important}.showSide::before{font-family:'argon' !important;font-style:normal !important;font-weight:normal !important;font-variant:normal !important;text-transform:none !important;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\e20e";font-size:1.7rem}header>.fill>.container>.flex1>.brand{display:inline-block}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.875rem}}@media screen and (max-width:600px){.mobile-hide{display:none}#maincontent>.container{margin:0 1rem 1rem 1rem}.cbi-value-title{text-align:left}.cbi-dynlist p{padding:.5rem 1rem}body{overflow-x:hidden}.node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field{width:16rem}.node-main-login footer{display:none}.tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar{width:0px;height:0px}.cbi-value-field,.cbi-value-description{display:block !important;padding-left:0 !important;padding-right:0 !important}[data-page="admin-system-admin-password"] .cbi-value-field{display:table-cell !important}.modal.cbi-modal{max-width:100%;max-height:none}.modal{display:flex;align-items:center;flex-wrap:wrap;width:100%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1em;border-radius:3px !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.cbi-dropdown[open]>ul.dropdown{margin-bottom:1rem}.login-page .login-container footer{display:none}}@media screen and (min-width:600px){::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar,::-webkit-scrollbar-corner{background:transparent}::-webkit-scrollbar-thumb{background:var(--primary);border-radius:10px}::-webkit-scrollbar-thumb:hover{background:var(--primary)}::-webkit-scrollbar-thumb:active{background:var(--primary)}}@media screen and (max-width:480px){.mobile-hide{display:none}.login-page .login-container{margin-left:0rem !important;width:100%}.login-page .login-container .login-form .form-login .input-group::before{color:#525461}.login-page .login-container .login-form .form-login .input-group input{color:#525461;border-bottom:white 1px solid;border-bottom:var(--white) 1px solid;border-radius:0}}/*# sourceMappingURL=cascade.css.map */ \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/dark.css b/luci-theme-argon/htdocs/luci-static/argon/css/dark.css index 0a5759093..df4b0f1ba 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/css/dark.css +++ b/luci-theme-argon/htdocs/luci-static/argon/css/dark.css @@ -1 +1 @@ -body{background:#1e1e1e;color:#cccccc}.login-page .login-container .login-form{background-color:#1e1e1e;-webkit-backdrop-filter:blur(var(--blur-radius-dark));backdrop-filter:blur(var(--blur-radius-dark));background-color:rgba(0, 0, 0, var(--blur-opacity-dark))}.login-page .login-container .login-form .brand{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent !important;color:#adb5bd;border-bottom:#adb5bd 1px solid !important;border-radius:0 !important;border-top:none !important;border-left:none !important;border-right:none !important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.login-page .login-container .login-form .form-login .cbi-button-apply:hover,.login-page .login-container .login-form .form-login .cbi-button-apply:focus{opacity:.9}header::after{background-color:#1e1e1e !important}.main .main-left{background-color:#333333 !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.15)}.main .main-left .sidenav-header .brand{color:#ccc}.main .main-left .nav .slide .slide-menu .active a{color:#cccccc}.main .main-left .nav .slide .slide-menu .active a::after{background-color:#cccccc !important}.main .main-left .nav .slide .slide-menu li a{color:#cccccc}.main .main-left .nav .slide .slide-menu li a:hover{background:none !important}.main .main-left .nav .slide .menu.active{background-color:#483d8b !important;background-color:var(--dark-primary) !important;color:#cccccc !important}.main .main-left .nav .slide .menu.active a::after{background-color:#cccccc !important}.main .main-left .nav li a{color:#cccccc !important}.main .main-left .nav li a:hover{background-color:#483d8b !important;background-color:var(--dark-primary) !important;color:#cccccc !important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526 !important}.main .main-left::-webkit-scrollbar-track{background-color:#333}.main .main-right{background-color:#1e1e1e}h2{color:#ccc;background:#333333}h3{color:#ccc;border-bottom:0;background:#333333}a:-webkit-any-link{color:-webkit-link;cursor:pointer;color:#483d8b;color:var(--dark-primary)}input:-webkit-autofill{background-color:#3c3c3c !important}.cbi-value-field .cbi-input-apply,.cbi-button-apply,.cbi-button-edit{color:#fff !important;background-color:#483d8b !important;background-color:var(--dark-primary) !important;border-color:#483d8b !important;border-color:var(--dark-primary) !important}.cbi-section em{color:#ccc}header.bg-primary{background-color:#1e1e1e !important}.cbi-map-descr{color:#ccc}.cbi-section{background:none;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.panel-title{color:#ccc;background-color:#333333;border-bottom:0px}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc}fieldset>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{border-top:1px solid #252526}#swaptotal>div>div,#swapfree>div>div,#memfree>div>div,#membuff>div>div,#conns>div>div,#memtotal>div>div{background-color:#32325d !important}#swaptotal>div>div>div>small,#swapfree>div>div>div>small,#memfree>div>div>div>small,#membuff>div>div>div>small,#conns>div>div>div>small,#memtotal>div>div>div>small{color:#ccc !important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999999 !important;background-color:transparent !important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div{background-color:#32325d !important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th{background-color:#252526;border-bottom:black 1px solid !important}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:0}.cbi-rowstyle-2{background-color:#1e1e1e}.cbi-rowstyle-1{background-color:#252526}.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#666 !important}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc;border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}h4{background-color:#1e1e1f}.cbi-progressbar{position:relative;min-width:170px;height:20px;margin:6px 0;border:thin solid #999;background:transparent;border-radius:.2rem;overflow:hidden}.cbi-progressbar div{background-color:#32325d !important}.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{background-color:#1e1e1f}.cbi-button{color:#ccc !important;background-color:#483d8b;background-color:var(--dark-primary)}.cbi-section-node{background:none;border-radius:0 0 .375rem .375rem;padding:0rem}abbr{color:#5e72e4}div>table>tbody>tr:nth-of-type(2n),div>.table>.tbody>.tr:nth-of-type(2n){background-color:#252526}#content_syslog{box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}#syslog{color:#ccc;background-color:#1e1e1e}#iwsvg,#iwsvg2,#bwsvg{overflow:hidden;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e !important}.tabs{background-color:#252526}.tabs>li[class~="active"]>a{color:#ccc}.tabs>li[class~="active"],.tabs>li:hover{border-bottom:.18751rem solid #483d8b;border-bottom:.18751rem solid var(--dark-primary);color:#ccc;background-color:#181819}.cbi-tabmenu>li>a,.tabs>li>a{color:#ccc}.cbi-tabmenu>li>a:hover,.tabs>li>a:hover{color:#ccc}.cbi-tabmenu>li{background:#2d2d2d}.cbi-tabmenu li[class~="cbi-tab"] a{color:#ccc}.cbi-tabmenu>li:hover{color:#ccc;background:#2d2d2d}.cbi-tabmenu>li[class~="cbi-tab"]{background-color:#181819}.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#252526}.cbi-value-title{color:#ccc}select,input{color:#ccc;background-color:transparent !important;border:1px solid #252526;box-shadow:none}select:not([multiple="multiple"]):focus,input:focus{border-color:#483d8b !important;border-color:var(--dark-primary) !important;outline:0}select{background-color:#1e1e1e !important}#cbi-dropbear h2,#cbi-dropbear .cbi-map-descr,#cbi-dropbear .cbi-map-descr abbr,#cbi-rc h2,#cbi-rc .cbi-map-descr,#cbi-distfeedconf h2,#cbi-distfeedconf .cbi-map-descr,#cbi-customfeedconf h2,#cbi-customfeedconf .cbi-map-descr,#cbi-download h2,#cbi-filelist h2{color:#ccc !important}.cbi-value-field>ul>li .ifacebadge{background-color:#3c3c3c}.cbi-section-descr{color:#ccc}.cbi-input-textarea{background-color:#1e1e1e;color:#ccc}.cbi-section-remove:nth-of-type(2n),.cbi-section-node:nth-of-type(2n){background-color:#1e1e1e}.node-system-packages>.main table tr td:nth-last-child(1){color:#ccc}.cbi-section-node .cbi-value{padding:1rem 1rem .3rem 1rem}.ifacebox{background-color:none;border:1px solid #1e1e1e}.ifacebox-head{color:#666}.ifacebox-body{background-color:#333}.zonebadge strong{color:#333}.zonebadge>.ifacebadge{background-color:#3c3c3c}div.cbi-value var,td.cbi-value-field var{color:#5e72e4}#diag-rc-output>pre{color:#ccc;background-color:#1e1e1e}.node-services-vssr .block{background-color:#3c3c3c !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.node-services-vssr .block h4{color:#ccc !important}.node-services-vssr .status-bar{color:#ccc;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e}.node-services-vssr .cbi-section-table-row{color:#ccc;background-color:#3c3c3c !important;box-shadow:0 0 5px 0 rgba(0,0,0,0.35)}.node-services-vssr .cbi-section-table-row.fast{background:#483d8b !important;background:var(--dark-primary) !important;color:#fff}.node-services-vssr .ssr-button{color:#ccc}.node-services-vssr .incon:nth-child(2){border-right:#1e1e1e 1px solid}#xhr_poll_status>.label.success{color:#ccc !important;background-color:darkolivegreen !important}.notice{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.cbi-input-find,.cbi-input-save,.cbi-button-add,.cbi-button-save,.cbi-button-find,.cbi-input-reload,.cbi-button-reload{color:#fff !important;background:darkolivegreen !important;border-color:darkolivegreen !important}.cbi-button-reset,.cbi-input-remove{color:#fff !important;background-color:darkorange !important;border-color:darkorange !important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit.important,.cbi-button-apply.important,.cbi-button-reload.important,.cbi-button-action.important{border:1px #483d8b solid !important;border:1px var(--dark-primary) solid !important}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:normal;color:#fff;border:thin solid darkorange !important;background-color:darkorange !important}fieldset[id^="cbi-apply-"]{background-color:#333333}#detail-bubble>div{border:1px solid #ccc;border-radius:2px;padding:5px;background:#252525}.ifacebox-head.active{background-color:#32325d !important}header .fill .status span[data-style="active"]{color:#ccc !important;background-color:darkolivegreen !important}#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{background-color:#252526;border-bottom:black 1px solid !important}.network-status-table .ifacebox-body .ifacebadge{background-color:#252526;border-bottom:0;box-shadow:none}td>.ifacebadge,.td>.ifacebadge{background-color:#483d8b;background-color:var(--dark-primary);border:0}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"]{border:thin solid darkorange !important;background-color:darkorange !important}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{background:#1e1e1e !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{background:transparent !important}[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr{color:#ccc}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.35rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal !important;background-color:darkseagreen}[data-page="admin-system-flash"] .modal .alert-message{background-color:transparent !important}[data-page="admin-system-flash"] .modal .danger{border:thin solid darkorange !important;background-color:darkorange !important}.cbi-value input[type="password"]+.cbi-button-neutral{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.btn,button,select,input,.cbi-dropdown{border:1px solid #3c3c3c !important}.cbi-dropdown .preview{color:#ccc}.cbi-section-table-row{background-color:#1e1e1e !important}.modal{background-color:#1e1e1e}.cbi-button-positive{color:#fff !important;background-color:darkolivegreen !important}[data-page="admin-system-flash"] legend{color:#ccc}.logout:before{color:#adb5bd !important}.cbi-dropdown[open]{border-color:#483d8b !important;border-color:var(--dark-primary) !important}.cbi-dropdown[open]>ul.dropdown{background:#252526 !important;color:#ccc !important;box-shadow:none;border:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown li{color:#ccc;border-bottom:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown>li[selected]{background-color:#483d8b !important;background-color:var(--dark-primary) !important;border-bottom:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown>li.focus{background:#483d8b;background:var(--dark-primary);outline:none}.ifacebadge{background-color:#333333}.cbi-dynlist>.item>span{border:1px solid #3c3c3c !important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{background:#483d8b !important;background:var(--dark-primary) !important}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{background:#483d8b;background:var(--dark-primary)}[data-page="admin-system-opkg"] h2{color:#ccc !important}@media screen and (max-width:480px){.node-status-iptables>.main div>.cbi-map>form{background-color:#1e1e1e;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}} \ No newline at end of file +body{background:#1e1e1e;color:#cccccc}.login-page .login-container .login-form{background-color:#1e1e1e;-webkit-backdrop-filter:blur(var(--blur-radius-dark));backdrop-filter:blur(var(--blur-radius-dark));background-color:rgba(0, 0, 0, var(--blur-opacity-dark))}.login-page .login-container .login-form .brand{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent !important;color:#adb5bd;border-bottom:#adb5bd 1px solid !important;border-radius:0 !important;border-top:none !important;border-left:none !important;border-right:none !important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.login-page .login-container .login-form .form-login .cbi-button-apply:hover,.login-page .login-container .login-form .form-login .cbi-button-apply:focus{opacity:.9}header::after{background-color:#1e1e1e !important}.main .main-left{background-color:#333333 !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.15)}.main .main-left .sidenav-header .brand{color:#cccccc}.main .main-left .nav .slide .slide-menu .active a{color:#cccccc}.main .main-left .nav .slide .slide-menu .active a::after{background-color:#cccccc !important}.main .main-left .nav .slide .slide-menu .active::after{background-color:var(--dark-primary) !important}.main .main-left .nav .slide .slide-menu li a{color:#cccccc}.main .main-left .nav .slide .slide-menu li a:hover{background:none !important}.main .main-left .nav .slide .slide-menu li::after{background-color:var(--dark-primary) !important}.main .main-left .nav .slide .menu.active{background-color:#483d8b !important;background-color:var(--dark-primary) !important;color:#ffffff !important}.main .main-left .nav .slide .menu.active a::after{background-color:#ffffff !important}.main .main-left .nav li a{color:#cccccc !important}.main .main-left .nav li a:hover{background-color:#483d8b !important;background-color:var(--dark-primary) !important;color:#ffffff !important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526 !important}.main .main-left::-webkit-scrollbar-track{background-color:#333}.main .main-right{background-color:#1e1e1e}h2{color:#ccc;background:#333333}h3{color:#ccc;border-bottom:0;background:#333333}h4{color:#8C6900}abbr{color:var(--dark-primary) !important}a:link,a:visited,a:active{color:#a5b2ff}input:-webkit-autofill{background-color:#3c3c3c !important}#channel_graph{background-color:transparent !important}.cbi-value-field .cbi-input-apply,.cbi-button-apply,.cbi-button-edit{color:#fff !important;background-color:#483d8b !important;background-color:var(--dark-primary) !important;border-color:#483d8b !important;border-color:var(--dark-primary) !important}.cbi-section em{color:#ccc}header.bg-primary{background-color:#1e1e1e !important}.cbi-map-descr{color:#ccc}.cbi-section{background:none;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.panel-title{color:#ccc;background-color:#333333}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#cccccc}fieldset>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{border-top:1px solid #252526}#swaptotal>div>div,#swapfree>div>div,#memfree>div>div,#membuff>div>div,#conns>div>div,#memtotal>div>div{background-color:var(--dark-primary) !important}#swaptotal>div>div>div>small,#swapfree>div>div>div>small,#memfree>div>div>div>small,#membuff>div>div>div>small,#conns>div>div>div>small,#memtotal>div>div>div>small{color:#ccc !important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999999 !important;background-color:transparent !important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div{background-color:#ba8b00 !important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th{background-color:#252526;border-bottom:black 1px solid !important}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:0}.cbi-rowstyle-2{background-color:#1e1e1e}.cbi-rowstyle-1{background-color:#252526}.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#666 !important}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc}h4{background-color:#1e1e1f}.cbi-progressbar{background:#282a2c}.cbi-progressbar div{background-color:var(--dark-primary) !important}.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{background-color:#1e1e1f}.cbi-button{color:#ffffff !important;background-color:#483d8b;background-color:var(--dark-primary)}.cbi-section-node{background:none}abbr{color:#5e72e4}div>table>tbody>tr:nth-of-type(2n),div>.table>.tbody>.tr:nth-of-type(2n){background-color:#252526}#content_syslog{box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}#syslog{color:#ccc;background-color:#1e1e1e}#iwsvg,#iwsvg2,#bwsvg{overflow:hidden;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e !important}.tabs{background-color:#252526}.tabs li[class~="active"],.tabs li:hover{cursor:pointer;color:#ccc !important}.tabs li[class~="active"] a,.tabs li:hover a{color:#ccc !important}.tabs>li[class~="active"]>a{color:#ccc}.tabs>li[class~="active"],.tabs>li:hover{border-bottom:.18751rem solid #483d8b;border-bottom:.18751rem solid var(--dark-primary);color:var(--dark-primary) !important;background-color:#181819}.cbi-tabmenu>li>a,.tabs>li>a{color:#ccc}.cbi-tabmenu>li>a:hover,.tabs>li>a:hover{color:#ccc}.cbi-tabmenu>li{background:#2d2d2d}.cbi-tabmenu li[class~="cbi-tab"] a{color:#ccc}.cbi-tabmenu>li:hover{color:#ccc;background:#2d2d2d;border-bottom:.18751rem solid var(--dark-primary) !important}.cbi-tabmenu>li[class~="cbi-tab"]{background-color:#181819;border-bottom:.18751rem solid var(--dark-primary) !important}.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#252526}.cbi-value-title{color:#ccc}select,input{color:#ccc;background-color:transparent !important;border:1px solid #252526;box-shadow:none}select:not([multiple="multiple"]):focus,input:focus{border-color:#483d8b !important;border-color:var(--dark-primary) !important;outline:0}select:not([multiple="multiple"]):focus,input:not(.cbi-button):focus,.cbi-dropdown:focus{border-color:#5e72e4;border-color:var(--dark-primary) !important}select{background-color:#1e1e1e !important}#cbi-dropbear h2,#cbi-dropbear .cbi-map-descr,#cbi-dropbear .cbi-map-descr abbr,#cbi-rc h2,#cbi-rc .cbi-map-descr,#cbi-distfeedconf h2,#cbi-distfeedconf .cbi-map-descr,#cbi-customfeedconf h2,#cbi-customfeedconf .cbi-map-descr,#cbi-download h2,#cbi-filelist h2{color:#ccc !important}.cbi-value-field>ul>li .ifacebadge{background-color:#3c3c3c}.cbi-section-descr{color:#ccc}.cbi-input-textarea{background-color:#1e1e1e;color:#ccc;border:1px solid #3c3c3c !important}textarea:focus-visible{border:1px solid var(--dark-primary)}.cbi-section-remove:nth-of-type(2n),.cbi-section-node:nth-of-type(2n){background-color:#1e1e1e}.node-system-packages>.main table tr td:nth-last-child(1){color:#ccc}.cbi-tooltip{background-color:var(--primary);color:#fff}.ifacebox{background-color:transparent !important;border:1px solid #1e1e1e}.ifacebox-head{color:#ccc;background:#666}.ifacebox-body{background-color:#333}.zonebadge strong{color:#333}.zonebadge>.ifacebadge{background-color:#3c3c3c}div.cbi-value var,td.cbi-value-field var{color:#5e72e4}#diag-rc-output>pre{color:#ccc;background-color:#1e1e1e}.node-services-vssr .block{background-color:#3c3c3c !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.node-services-vssr .block h4{color:#ccc !important}.node-services-vssr .status-bar{color:#ccc;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e}.node-services-vssr .cbi-section-table-row{color:#ccc;background-color:#3c3c3c !important;box-shadow:0 0 5px 0 rgba(0,0,0,0.35)}.node-services-vssr .cbi-section-table-row.fast{background:#483d8b !important;background:var(--dark-primary) !important;color:#fff}.node-services-vssr .ssr-button{color:#ccc}.node-services-vssr .incon:nth-child(2){border-right:#1e1e1e 1px solid}#xhr_poll_status>.label.success{color:#ccc !important;background-color:darkolivegreen !important}.notice{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.cbi-input-find,.cbi-input-save,.cbi-button-add,.cbi-button-save,.cbi-button-find,.cbi-input-reload,.cbi-button-reload{color:#fff !important;background:darkolivegreen !important;border-color:darkolivegreen !important}.cbi-button-reset,.cbi-input-remove{color:#fff !important;background-color:darkorange !important;border-color:darkorange !important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit.important,.cbi-button-apply.important,.cbi-button-reload.important,.cbi-button-action.important{border:1px #483d8b solid !important;border:1px var(--dark-primary) solid !important}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{color:#fff;border:thin solid darkorange !important;background-color:darkorange !important}fieldset[id^="cbi-apply-"]{background-color:#333333}#detail-bubble>div{border:1px solid #ccc;background:#252525}.ifacebox-head.active{background-color:var(--dark-primary) !important}header .fill .status span[data-style="active"]{color:#ccc !important;background-color:darkolivegreen !important}#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{background-color:#252526;border-bottom:black 1px solid !important}.network-status-table .ifacebox-body .ifacebadge{background-color:#252526;border-bottom:0;box-shadow:none}td>.ifacebadge,.td>.ifacebadge{color:#fff;background-color:#483d8b;background-color:var(--dark-primary);border:0}.alert,.alert-message{background-color:#333}.alert-message.warning{background-color:#986400 !important}.alert.error,.alert-message.error{background-color:#784f00}.alert h4,.alert-message h4{background-color:#784f00;color:#ffbf00}.alert-message [class="btn"]{background-color:#777777;color:#ccc}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>ins{border-color:#00ad00;background-color:#688668}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>del{border-color:#c60000;background-color:#896565}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var{background-color:#333;border-color:#666}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var ins{background-color:#688668}.uci-dialog .cbi-section .uci-change-legend .uci-change-legend-label>var del{background-color:#896565}.uci-dialog .cbi-section .uci-change-list>var{background-color:#333;border-color:#666}.uci-dialog .cbi-section .uci-change-list>var del{background-color:#896565}.uci-dialog .cbi-section .uci-change-list>var ins{background-color:#688668}.uci-dialog .cbi-section .uci-change-list>ins{border-color:#00ad00;background-color:#688668}.uci-dialog .cbi-section .uci-change-list>del{border-color:#c60000;background-color:#896565}.uci-dialog .cbi-section .uci-change-list+.right .btn{color:#ccc}.uci-dialog .cbi-section .uci-change-list+.right .cbi-button{border:1px solid #3c3c3c !important}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"]{border:thin solid darkorange !important;background-color:darkorange !important}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{background:#1e1e1e !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{background:transparent !important}[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr{color:#ccc}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.35rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal !important;background-color:darkseagreen}[data-page="admin-system-flash"] .modal .alert-message{background-color:transparent !important}[data-page="admin-system-flash"] .modal .danger{border:thin solid darkorange !important;background-color:darkorange !important}.cbi-value input[type="password"]+.cbi-button-neutral{background-color:#483d8b !important;background-color:var(--dark-primary) !important;border-color:var(--dark-primary) !important}.btn,button,select,input,.cbi-dropdown{border:1px solid #3c3c3c !important}.cbi-dropdown .preview{color:#ccc}.cbi-section-table-row{background-color:#1e1e1e !important}.modal{background-color:#1e1e1e}.cbi-button-positive{color:#fff !important;background-color:darkolivegreen !important}[data-page="admin-system-flash"] legend{color:#ccc}.logout:before{color:#adb5bd !important}.cbi-dropdown[open]{border-color:#483d8b !important;border-color:var(--dark-primary) !important}.cbi-dropdown[open]>ul.dropdown{background:#252526 !important;color:#ffffff !important;box-shadow:none;border:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown li{color:#ffffff;border-bottom:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown>li[selected]{background-color:#483d8b !important;background-color:var(--dark-primary) !important;border-bottom:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown>li.focus{background:#483d8b;background:var(--dark-primary);outline:none}.ifacebadge{background-color:#333333}.cbi-dynlist>.item>span{border:1px solid #3c3c3c !important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{background:#483d8b !important;background:var(--dark-primary) !important;border-color:var(--dark-primary) !important}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{background:#483d8b;background:var(--dark-primary)}[data-page="admin-system-opkg"] h2{color:#ccc !important}[data-page="admin-system-startup"] textarea{color:#ccc;background-color:transparent}[data-page="admin-system-startup"] textarea:focus-visible{border:1px solid var(--dark-primary)}[data-page="admin-network-firewall-custom"] #view p textarea,[data-page="admin-status-routes"] #view p textarea,[data-page="admin-system-crontab"] #view p textarea{color:#ccc;background-color:transparent}#view>.spinning{background:#333333 !important;box-shadow:0 4px 8px rgba(0,0,0,0.03) !important}@media screen and (min-width:600px){::-webkit-scrollbar-thumb{background:var(--dark-primary)}::-webkit-scrollbar-thumb:hover{background:var(--dark-primary)}::-webkit-scrollbar-thumb:active{background:var(--dark-primary)}}@media screen and (max-width:480px){.node-status-iptables>.main div>.cbi-map>form{background-color:#1e1e1e;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}}[data-page="admin-dashboard"] .main-right>#maincontent .Dashboard{color:#ccc !important}[data-page="admin-dashboard"] .main-right>#maincontent .Dashboard h3{color:#ccc}[data-page="admin-dashboard"] .main-right>#maincontent .Dashboard hr{border-top:1px solid #fff}[data-page="admin-dashboard"] .main-right>#maincontent .Dashboard .dashboard-bg{background-color:#333333}[data-page="admin-dashboard"] .main-right>#maincontent .router-status-info .title img,[data-page="admin-dashboard"] .main-right>#maincontent .lan-info .title img,[data-page="admin-dashboard"] .main-right>#maincontent .wifi-info .title img{filter:invert(90%)}[data-page="admin-dashboard"] .main-right>#maincontent tr{border-top:thin solid #4d4d4d}[data-page="admin-dashboard"] .main-right>#maincontent tr:last-child{border-bottom:thin solid #4d4d4d}[data-page="admin-system-fileassistant"] .fb-container .panel-container{border-bottom-color:#3c3c3c !important}[data-page="admin-system-fileassistant"] .fb-container td[class$="-icon"]::before{filter:invert(.7)}[data-page^="admin-services-openclash"] .cbi-tabmenu::-webkit-scrollbar-thumb{background-color:#5b5b5b}[data-page^="admin-services-openclash"] .cbi-tabmenu::-webkit-scrollbar-track{background-color:rgba(60,60,60,0.75)}[data-page^="admin-services-openclash"] #tab{border-color:#3c3c3c}[data-page^="admin-services-openclash"] #diag-rc-output>pre,[data-page^="admin-services-openclash"] #dns-rc-output>pre{color:#ccc;border:1px solid #3c3c3c !important;background-color:#1e1e1e}[data-page^="admin-services-openclash"] img[src$="arrow-clockwise-light.svg"],[data-page^="admin-services-openclash"] img[src$="wrench-light.svg"],[data-page^="admin-services-openclash"] img[src$="eye-light.svg"]{filter:invert(.9)}[data-page="admin-network-diagnostics"] .cbi-section{background:#252526 !important}[data-page="admin-network-diagnostics"] textarea{background:transparent;border-radius:.25rem;color:#ccc;border:1px solid #3c3c3c !important}[data-page="admin-network-diagnostics"] .tr>.td{background-color:#252526 !important}[data-page="admin-network-network"] .ifacebox-head[style*="--zone-color-rgb: 144, 240, 144"]{background-color:#497e49 !important;color:#ccc !important}[data-page="admin-network-network"] .ifacebox-head[style*="--zone-color-rgb: 240, 144, 144;"]{background-color:#9c4f4f !important;color:#ccc !important}[data-page="admin-network-network"] .ifacebox-head[style*="--zone-color-rgb: 238, 238, 238;"]{background-color:#666 !important}[data-page="admin-network-firewall-rules"] #cbi-firewall-rule .zonebadge[style*="--zone-color-rgb:240, 144, 144;"]{--zone-color-rgb:156, 79, 79 !important}[data-page="admin-network-firewall-rules"] #cbi-firewall-rule .zonebadge[style*="--zone-color-rgb:240, 144, 144;"] strong{color:#ccc !important}[data-page="admin-network-firewall-rules"] #cbi-firewall-rule .zonebadge[style*="--zone-color-rgb:238, 238, 238;"]{--zone-color-rgb:112, 112, 112 !important}[data-page="admin-network-firewall-rules"] #cbi-firewall-rule .zonebadge[style*="--zone-color-rgb:238, 238, 238;"] em{color:#ccc !important}[data-page="admin-network-firewall-rules"] #cbi-firewall-rule>table>.cbi-section-table-row[data-title]::before{background-color:#252526 !important}[data-page="admin-network-network"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:240, 144, 144;"],[data-page="admin-network-firewall-rules"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:240, 144, 144;"]{--zone-color-rgb:156, 79, 79 !important;color:#ccc !important}[data-page="admin-network-network"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:240, 144, 144;"] strong,[data-page="admin-network-firewall-rules"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:240, 144, 144;"] strong{color:#ccc !important}[data-page="admin-network-network"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:144, 240, 144;"],[data-page="admin-network-firewall-rules"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:144, 240, 144;"]{--zone-color-rgb:73, 126, 73 !important;color:#ccc !important}[data-page="admin-network-network"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:144, 240, 144;"] strong,[data-page="admin-network-firewall-rules"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:144, 240, 144;"] strong{color:#ccc !important}[data-page="admin-network-network"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:238, 238, 238;"],[data-page="admin-network-firewall-rules"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:238, 238, 238;"]{--zone-color-rgb:112, 112, 112 !important}[data-page="admin-network-network"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:238, 238, 238;"] strong,[data-page="admin-network-firewall-rules"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:238, 238, 238;"] strong{color:#ccc !important}[data-page="admin-network-network"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:238, 238, 238;"] strong+span,[data-page="admin-network-firewall-rules"] .cbi-dropdown .zonebadge[style*="--zone-color-rgb:238, 238, 238;"] strong+span{color:#ccc !important}.btn{background-color:#707070;color:#fff} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/favicon.ico b/luci-theme-argon/htdocs/luci-static/argon/favicon.ico deleted file mode 100644 index 4611336803d49af0896adf2698cfaec54e96b800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15406 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 BLQ((# diff --git a/luci-theme-argon/htdocs/luci-static/argon/favicon.png b/luci-theme-argon/htdocs/luci-static/argon/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7c3f3acb1f0c7c142d0dbd3f42a4926b07f8eb38 GIT binary patch literal 535 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 literal 6411 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 diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png index 5308d66b779b26d1828690516a4ab5dc01b7cec9..8d523df8b3def104ea6bc7e6fa1e41803aea18cb 100644 GIT binary patch literal 6568 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 aWS&p(fIu!(CjkFLSj>$d8r2y%$NwKzaNBSI diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png index f18dfa49cd35fa6d5cb882ea8ae703c852e313df..4c80656decdbf25e80ec485494b348c5149ee2ff 100644 GIT binary patch literal 3590 zcmcInc{o&iA0K2(?xiAoV}us78fIZqB1=ZyOj#?(%$YHa8D<7Ul%>#uq(xcMf_6kI zq%4u7#ge@)k`k3-O2m7n`E<}W1mp@0emY~&=WGLm`JC^OGU#ZK0|r1a0VE7N=PJ;bC*%oydH*Gj zx$U`V0?F(6ARy%NX*?e1XQ?**WP#)GC@g%rE1S#Ug$hVMAfT$5A~9x2 z9F~T|kTC=@j<^a#Bx5i?pj4<67=RG?H879CW`_L=lu9K#a0NnuO9vfnCNkkt42w)L#2A$00@dE&;PuKwf3q%KUSqS*Q z)vV)jczi040p;9O(#;S%6ooxo0F^Fm_W5uDgJ!QdZ20%4BLj3vuTv0oNs&QF?~i5n z-(>ICbpEgp^#vi)e<=PBn1II=h5~$WEep!@|7P`{s@jIjFJqma?l(jG1BPM5scTP;I7I|pR2<8}BmzB1{H1p%8 zI(fa$c;?F$ksp*ZLONIKW;om0$a*}`K%VjPP+a07y<$n_yff<$AL@FS<+)VMxz^Fc zm|>-QE6&6-9%WGmXJ&@8UW`n3-8lqWPDZ>H{^{U-BH@Ts?GyL4%f@@$lNQaax73?j z#jaa3)VQn*i~I7*q^(AlEw802zEgbVoIxhFX-yt1_^vv9S+&FT3m~<~aAWPflGv7! z_O0EiQd7g9t`tSfWg~)4S!kJ$pH$Cg)+yb)5}UvC#jstfig{Rt?D^-@RV{jrWx3pi z)qRDnQVE0E9>&p)N%PVz6QUnJv*cNJ08)yImKVZKv#wPe?QqWx3lejqWKTPl#U9>Y zSS79Tb!1Pg3?|3kfTNJ0l6Y%uj6@U%MBA#2?c0;-ajvkq$vY_Q(1bwvZiQktyIT2v z(4P&c_*JJoyl!%W#1R?KSBF}AOO5S|x{|i^oOq||F%ujP)*PQ(d2n;0W{zCLaV?^= z6cuR{pHy>G*r?^|28*-=SdA?c^`(fF4Y4mR@X8m}XoSQg&@12ZHaVW80`oMzK zP4rkbWj|N74=tV6(o(env}13l{2CTN-(~!u%#MEZUAy;fyKqiHoclkr_yEt z1!m=;&8*CTS-ePCNa!gCKpX9?dz9n%?%=Lu_LjpJQS{2K?Eg4jo3u@)rk}gL0OnCq zQ2N`QFKTz5uqqgAR}B!IyU4m1t3PlrBBJu; z(YDC~lktmn_}=7v?9bMz7HGpk5DuQ;vDA{sK*%zJ_eQs1-*wU&u7#n|fY@CH2b@=M&uY)wBBcDZRY8~69Z5C!3T zE5E*v$LZC-(>t!cgXk!Dl$N`qGTeCsHFl-K1_bDV_U66Q^WQ#Zq<#v^{ zcAOUHWV6<`z-F}(!mBN~3%~h=xO=ydNhdJXksh@LdOaVhg zZ+H+n3isN-$aJxP>diMRE5ln4pFGmpoVVWcb@%2p&#ufpZF+_Wua|Ub>Uo;I9ZEhk z&!Rg{@VZtv)35$+_fDC`YW0{Gyp9jGr(Y+u4O14^U2Cp#E&Oo(jo)2DnU`U^zV=p? z`mWAaodku;UrSO_XcS2-k&L zt;l-t7FD$hs8{q>bJ4emqy*PE&o^3DNoBQ4{Uypk=Q%z|wZ|qE5co zBFWyko;)v7Z3d=X$H`aClS}W369`9>G7_4fzWL(Oe%SVw>;>b#7 zXMuG?(>0(iU8X|a_~Ou+s-Gj zY8_R!U{r_U&;DM%q+eL%k+N&_Vy25D6?Wd`tfev>GC$GnjTBknrjL?<8%|ll=~ zct3?n2TnrTZ~<1eBmXw^HmmOXhCKnOri_ex<`{ISs&0NTe4$1z*M%>0b ddhm*9M#i7(E>P+$h?jh+IoLYeT($O&`4@?m+~WWM literal 2561 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 diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png index bb3e2423331068c72c5ad0e1bc49a51e1fdd71af..07753022e45a769c7a35fd2fb59b25577e4d9734 100644 GIT binary patch literal 4003 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 literal 2877 zcmYjSc{tSD8=r0}vX+WuN!ij(L|36)A(HGRB#dS3W{feIF_y*{)QDuu_ERKVCP@?$ zB}*himadx^%Ph>8efxcTe*gT=bIyCt`8?12p3nO^?|Dv^i<6z~UX{Hd5J>ily^R|% z+y5StI{^zewnhMx1jOo^6$nJkl@bi=&4v0EVJB1CblC z89e_uQdAlfl0*$oB*$e6pm#V3ya*h><_BMnNoU1pi^DPWkR(b(3Ox|H9-h4Q+hXWI zhh=bqemnM8Sn?)-0}Euf_;&0v;P}6Fe3l46klDX&L<%D^l>r2aOkn_92#O{aivh=| z)a`K0Rw$YV;6P;P9X2?A6@sG1W^jR+(P_*G3?1--VmSc_QXp~-pyVI70>g3uN&sOP zmIucP5O^WLJUX2fo52r5Zw4i-$J}8DC2T;FC}C(Ca5O+EJb4q~6Ou>{PS^-V(Lzzw z$W$gkDKLHwNES#WDvcF{Tn8goMIvzkVik_#0h$2%1jLcTF${rF3emkLMBVhV2YMVLV-Z+2VVilugBp9TMRLqBOadySaBw2g(1J?rIKmCr3g>n z{{BN4il+1UVxdrcx0DWumQl!wPG@%y@E4bbs~f_I6eev;H1bt|y2piKw`0;73qJ)> zY3#;!AYV@Zh+uGB2x$1clMP00)V^Scq5-Y8!jkFj?>H}egs6LhgsknAHPP5NVPp#P zO+T-whSl(jgSpQyuNS1{^QxPfkty_bvWUYK|J?v-&rjq%|b4B{I> zX`QgJhTqg7#6AQ9ZX&Zb8{3)T=#Bg;I<9cDs*w?#u--c;>K)=`77KDK1sDQ=P@bU) zQ@|VeGtSM)9rXVHTi;Ie_qtP|9Q9D$soJzOb55=LbZr_(eY!8Lc8WiDdRYnt+Vl8| zjg`mEzNVSPn~D$>(59=8&nbtkS8P_x0ON#&2j1JK&3m8z2JvU}Ou_6EZ>(11n-Im8 zyrWVlur2s`Nj>&)S-hm=AF)ZUP2{9hyWXAsHz-|E$nP;{j7yMmll8R9!C!30?zf(} zqo1Ja#?(aJGwQH@#WQQ=^Vs4t$}IvBprNC!?Q36uZTZ&?n+#PmEs63r%a?r(ODKd{?T@Z5)Y8AG z(sQdLYPJ?T___REWoXoPui=cTfqFLX#Af0isGj6DQE|~F$`S|TJI|iD|Llc8j#qXC zLY0(B>+akyVs%{QCO6JW7{ANus_eL^{D;%fb*Rj%%J&?hVUv^lO0vpX8CFZp-NqouQt3Kng0xwwO%WQ7@@ z-AVs~*1{Z@&ebeK^?b#;&=9aB)v_~g=4dcQe08T&&Tf`Za@)Rh%1L)y?bfmb>>hp~ zc^%fJdY^>EnL<_f|0D-?(!4ub4W}Kvltxmr4EAp`6*aarXg6V=

    l43o znrK}nG+gtc>gLx>3i3^0x2Jw8raK+QC7@P3yP)0$WkXdfo&(SJ7avZx7?9gye*=Fh z7^#U3mveCVTs5L%k>I3&;}DR@Gbl&OjgX3u6tH~ViyWGN=xhHJmXqb75p?YjBWI!7 zXQOk-o;;ew1%hU;dPQNyb1>nPku#Dsp8165-LI*cm;3`hb@pts4Q9lGd3wP*%H&|w z#Y>P2Qdtzn;Zr^Nrr-KTgP$9mN;J=My)3^EvJclURe zzxaz!|C)L*;B4u@+V+tfo@4yjLty;pzP;DbiSEZ!{C2@hNG7H+L8>yc0aV=!#xqsf_rp|b*a?=O zdkVxzBZ`Xxvy1NF!Of&k>bbv|?No7}*&6tlNnM-BoI~GLkBVxAjG^a7Bjs-?yuPT{ zaCZ9d049+>}fFM zCuM`!K6?G2=tfO`8%FKLCo0w-FIs3?#=UL&dYAFn92b2cl7NrqHomX5^lw6=lPxZ;uW0c%Ty}83g+jQYV9D~#HHw~lDUs=oH8a=Hj`uh= z!BzHhEOD6gYOc$2dw7sCJ#_5-L+xxIh_vkW9Hl+35F2w2p`x1c-S~PyU#40vro1qf z*QDd|-L1B<&Pe-a=&Hu+2vT?+eYlk`b3I7pU$^P^vQ=OUo=@of5wksfpx*xpfoHPg z!}gpIjQ$ldh4xh7F>6ZzF;idtxrrv>4EFQ(l?hCGu#Ysm{Jp zXJe*zQIKhfkM@M2hi6x1BfELj=@yOO&>qu%Go-mBjM(Vo_eJ%p|Htkl^Wku3@3Zi>ZKo#XAY5CTVcnVy;=;QYF>U;ju%hgvOoXWk7$Wk8E$eH zKVY6^yFDE_AM>65v32|SDW&Lg9*xEG9bJW#WJW69eso4uvF_WS$dy0c_5LCYUSYC@ zDDu<@1|K+ld`9`>$0d)uPr%!slyse{)ip#KSRIf?hg$kD@Xdp+*gDxXU-D1?FEo)L Ao&W#< diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg b/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg index ebeca958b..a20e7987d 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg +++ b/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg @@ -1 +1,3 @@ - + + + diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png index 308843a09261dc8c5d95f01a3b4e6592e1a83ff0..88bf329787747293b939c263e9d4b53e64b18238 100644 GIT binary patch literal 2069 zcmcIleN5D57%v7tVB&~32P$f<#7t(dz4kskPX>20Bvx-2ep%GffUA9IFfVum40Hg(fD=hr}V(JbiPl*GM-<7O6h{Ig4XecS%t z-}8HZ&(o)Mxj9*Ju~T9Z1c`HHJM-W`u_Y!q>6RS8 zCuCR2AipZd!&Q}XHXcizkIoA*kRSk577YdbL4^s~u|Zx2uC?0)h7Lm1QahHW1w;$n zxu`>w0cz8eI7gBsYM?E8o;9)-V490kBt;Ph13_7E(#FsxhNRK(4}BdPMMZ_ag4T<231P6=Yy?RW6oo?su2cq9HiQS2S;GuYpm4Gvse%|pHAc2r zEK}_m)H;+zK#I@?m9SCJG9tuEgh5YgNeu(t?q@>-fe2brGsg`Imi)lhyiAc$xK;_ah9ey++s5taI2Lw;ILh- zHj*N(lot%MEtCcL?y&yHSv6HWWHeGHBg^qd+-o*)xY=Oja9gp#h|?s+b0*Sg1srsX z=NPXj2UyrALVzs+gcK~n(0|l8M87DzMIL%iYuyalVHVkf0!vpJen0ZT%J9lBpo2}v zu$$`VNo=G2*oBxXCy4!Q-d2Jt4htAaQ?Y&5VOZLPwtOZxwQr$GSU!3}7=w8AvnPg+q4{@goYnyK!n>?+&Z-rxW?OVE- zEn5y>Tvc$gzwXRk^@OUQ)^YCZ-aFGzo}7JdO`=u#{@1?O>i5p*PT5~xw2MXc$fec3_M<&C-R!NRy1R(e58ogA z>cvS9?{{Kn_Xf7#N~uzgN7cmCHaNzt_2iwo+1h-#&G$;lh54TxShgNXwl-|;_kY## z^TSDRj~lgeprByxxT4iH@8}90`_Ejy)|A`R_W6#ZjaN^7288oenJvvrdj9NdS$Hrr zvAsHBy8Wa4l(9&%uJv-VZsziR(etWrXSG+QzxmSxowTYgedVX$wu~l@-mU8Bz10Z* zSa)i1-FwEHod>$(_Sg&iF1&a?NByEzWDdN3FO_VJ&CHw7(6nv)_21$THO5XnvIeK? Vx9%dQ?bJTpu8bUKTYAy@zX6*N(Zv7& delta 1008 zcmYjPYfO`86fPhki!zZJ2Z>qyu_eof6EZh13kEvbhCzlvoK6I>0&Su6Mkxi_uNMjw z*d`9FLKrp8q&TRB_nmbEh6#tl&uUadh(q%IJ}k|m)wB-Rrm9aaei ztJJVSjqn=%d}V;I3Y68YNug%yoP3odUp-g1R%-~?8W?$7Sl$)^SQ0%YZX&piex5Q= ztwDqULKPG@g{mO9QWbzYLy<@XM#GgV|9|ZPBDY}!umPRQ6|1E(4^QbYtMi1gaGAmf zprp-s6%@qqFd!k(V?iV=)ItboAW*~47UN_w%ec8<{dzfl%=${ozsKtRXL$@)p&MVTc167@U{+l)=gome` zv{+AG`VO6PQsdLO(F6-M>(KdL|8o~L{giy}qQ`#+a=l+)g+*HL)KikL-1v1Gmo`(A zPHJg|23GSLy;sa+i;NLO3}g8 zcZ4UNkeAJjtd+QELM$WnlAEEZ2w(Za*Bg+XR{iAh_PS5bkXi>XrBdi zWds^j(u7#=VB7}3^)4lC4h`R@NGc+3Li;Va^$vM?0K0XM6sUv!gQP?c->?zpVY0Ii zksE?n%-F~nVS7Lhj^d{8iLP(aYE95Gg7**NQ4{1KSg}1&O@3~H1Nr}f(JW9pU<7r% zNI(h_7(rn0&4GZ&;=N`&*v_Qv!Dhc<4mZzya5B+f6GV6+?JfL1-FP>B zp}4Qlm-6M7Pa8Cg*xClQGJ8)92_)R=pX1rlI_5)NwENJ0VT$vwhw#=dfdUsTdb=1n O%*xKnJv_udqx}~XcVXQC diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-32x32.png b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-32x32.png index bfcd09707aa32d6160decf61fee71602df9a404d..d524df3eaee3fc2b0e70a5abd14fa2c4f134deab 100644 GIT binary patch literal 2604 zcmcImc~ld39#17ekfSOHE3IxER$GP1OfEn9_X?P?1XFk_O-76?7TUCGxPa=zMtFq$+WaRL%eIA3 zCDMt?NEu4%c?d?Tah^p_F=!SmV6KHiP#sQl)wqT*$brW-#{n*Z$$`^dxRwad zGU9PrQ7SY`he|PE?i_A_MaB^5aT?)T^l1i@%pwPdcxBAm`WOPZLl9ag2Li1Qxrxdc zZZK)Yxl$esqA(0|`9eP)hKLY9TVi_#tj%)zq&xobUVilny z-k3W%prvU_20>=CnP(RANTUYgOQli>7C-_4$RI#drh!H*puyxd%AmkasF9#(f;4cg zjEI`dpydFgbvOt;HAZVNjU5DAD0rLZp|mZYkE@gZG|y@EtDtm(7b4>vAGq727ahM4~2^Kqdd6;z8Q zVo)j&2|+1_i9oTGkK=q)jrhUXC|k6VV7?tB?YFE}RT#r40}6M?R7bTT8oS`dWRnqzmvVU(>ZK!*5VB58;U;+Gm)vZ z88PC48Ya{Kv$>!@5^qA5yjl9&75@JyeI%`@7BOgWW^_V;H5kY`Vup(X{dc{F-u-4A zjl!83XI+ksSLSAHK;s66+Q^LGl9g~3i^b+dC<0Z94UMJB$mDpp=1(7-E1zZK2s}VzXid z(E|?$o!ZVVSKwI6yAqCmcHFbx6<*<$y(yki?3UJX#ctm0vfQPw#oc%J&y;Ww9oX~N z&I$gXI9@q2LxD*AJ3jx%>gMQ#_GQn4*KhxLshDEdB{>IpejL!NUEQ^7LSF^!b5OKa zOSq)(nS1ut*1weH9{}Dzab()ExHXNR>30@~x_y)1wTml`cPDE-H0qXC$1wKylWJ>y zPSj=Vax`8^Ky6RtM11FLD4A9A?q2o_`J$j5+U}k-#roA6v&XiRPGM~Cl!hDGVej-_ z+L(SvH+YzSc}5uU>$sTe)9R)3))lJHcU_LRzjEkOMRnWx+v5`Z4t3_dT$A53ub;R% z0H0fy73jZwpt0+b}u_Rq426SWy@v% zv;D%pwO`kj8X7j&ec`ZH(e9P}9i8&HR%26&y6pePx1o|pW)~#>-SyB#+bhcxVsbtx zoQ4*CW!JF@E}!}yZ(z6iKrFR5dV0Ce=j@{LpKX5mv|{nZLf50E3zHMpLPY)jzKeaC z?Zi=!Re_d&u5{j1J@=rO;zZ2AL1)czQy!JFGJq6Z=m?lIr$lu5!lCoEH`34KFMaA= z{%}eg$8UDQBkG37h0U)PL5;U}S5EcGIsVY^ha2~(?H#8bJKW%-q1n$v3X3#d9y-oR zyWX4`8_|#U+Hc)*K$_mUXrjyFZ`o}dw)FXi4DNIBPs+)Q&dSTHNxGFh^_e8SbJtV% z?KREFvX&ZNvZA0L>X$oR{4r<~ z182+6Ki$!K1U1V}_-}YWcA;Za-|JRk&4f-iq2S!wy~)M~pr=W99AORELemA2wM%FC QTmR=GLZTFVgBGv)H+k{kfB*mh literal 1720 zcmX|=d0bOh7RMh!QwCh1BCS&@OiO3{@S#$==?qn|Wf65KQpd5il`JF}wjc?FEhHfg zfgl1>KtTj5AWKE0PyqoI5JeG0peUA|1PE)^x8^aI{xSFS?z!i_&$++%edpYh=I`gT z)$*^F5Cm=YJ>nSvR>zHLVGgWknW7skn}QGj`!EFE&a@)vo59|U7vS?HRNH62072%E z|M8Pv^yqmSUlk-+WW+3R64%1T`f!PX9ly*=!6T(GQ=n$WEd?j61oBkp5?A?hB1(ou z{)hmn=u}fo8p%zDgJKuYM$HEDl;Ai|j&p=-Awo?^k~Sns6PlzIDAq$o8x{ngjZ*&k z%!Y|{0tE?P0t@{0^>rW);(@~X9}#-=98dr}00yXm;{XGE1*id3M$9}@umGse%TPeb zh@L-}uo5N1BP2#31>mD(C_8@jPiAFAvXPfU091DT3OjBoNT3dmU*^kA5y>!DiVVIY zBBdxRZY4~tm8+3B%VVm-NB$ zi#Wb+FarMN=u{)fL*hl95hnA?(f(nO1Wl|0Y3W4oJOF7#21bZbk-m43sBZeL532UNk z10zPAQ>q;u$5d)lQ0!85BXX-5zFdJsO4oAB;G9y!IZ#B2p|KqWC8%#j3M$cr41-or zcJ<<8(=V*F;4v40o~7cURL#%AV-y1T}z2KZ9(TGq8SjgHJN(M3uP zoW$k!Zum-tuD02Dx67D&UGww>+R_O>eSzea>03ID;o{XWktY6vo-apUPZGk5`f#x> zLZZnp19jBKq#EMWwfq!qK_!uP#nAQ;%P+@8*+gwKUQ`7aRv`%&^ieWh&2QM^GFjPx z7uT8oWN5IxULJ{96UEQHIwsG9^HmPJMoQ1-%$VYr~JCle{+NH z)YUZ_tSr_dhlYpueRe6ANw@y5S8j2#)2$o-sCn!taXR$ii}&4MyB!>V>+f7nMc;j^ z{MC@+*oBTV-?_f8TbH)w21CBAHdfSrL{5|HM>`CnH7k6!IkV%M%{Bdad*-hw) z4`rvg!T&j_MExY{ND3Qg>LaS~%3H(%$?>RT>4B{(ub2(Wt@e}e@g9)8*R8wuIPB@Y|Hjb0_NuDiU7VXKPOCeE zxZ6LSh~RZS`D|Qr&|@=(ePS7WU`w3w9N95f?jHEz*}CwV!Hmp(;qi6!#>~u23uzf= zz?Ai_Yr#>qb4~l+Gbd0XUO1AT7k0)l*^`$mIq3G@mKWaMY~J<4apCEAOxM4_e17=P z*rTmgXOct-t8GF<%jLIO)Lq}U#ko$@27Y&j6rp{t#p^4hCJtOHI<$^#s(sb6*ZZq9 ziI?BF%RimV8INw2JywU{llA^3c+s1Z6{}y;240+`Su;)yu~{q@leuH3a@N+?*4lb< lGHZJ7Ejv4#6Q>w96o|L|_<|kZ-V<~fZc! z3c{Nbpjbo-HH9OPa3m7ON5JTj6b3E=Mxkr|X0Qe5_z)6} zL84M1tBg2*YAC}3%GdhS2{P>uErtFoQ2da=BXBghfj(l@soy|H$G?Y?$$!vv#sfj5JK%)&{IAbJnbqW}o5{;2)BLgUefX5K2A!HoC zPDo^2005^^0-%upQDZ|5riM6D3H+F&R;!uM&iBHOMCYe2^4I&}1|0e|3MN5*6deYK zU#)cuD1J4`00H{zHt9b^@1N=XNgEyr@JatB`9EQFDv=S63jwSH_>ulUiwpkW#M5zM ze=q%?CI0_W`meC!196l9fZsad&{b#Pt1aedQsDnPUq7DxTRZv<=l8hP;h*-(pZsai z0EJH-!f(Is#`{7A1f;Ln+giIv^iAcFXbMe=O@poNlN%Cb*Q6O332iKC$e>-|N_!p+xpu6VD3q?vc5 z$DI`*fS>j`f#s*7Iq0b9i?Od}*hGmtIk#)?8kFihj+d7m$&rd z2)?&^1dpTwPMs3|PXkJfSf53~DjP`!O}fdM|ty!5`*5H zgr0y06CG38?2{?rUKhPZ`5^6>Vb--D6pYJC1%kb%?gmU%$eU@cV16u zeu9#4K&1A}>umzLXBBd17C%n7Txl%WN-q`)pWZ?%9+3JfBN1)9zxs){(`e)V@{pRHvnw zGzdu%`)V2>0Qi~acg>Ktx&(lM$B0?NUQzP)@QED!GpuX zH+Hs($HZhHMGp7dsb%RkrHzTzI%+v{dLAoW4m7YUXYu+DeELz{IK){cHX zFGHr4TN?=1Vl@M#mw3+2>}ubUPzR3S=htq@gFHPoNpQJ}5H@3Nw+1gm(38`qTbYrk zWff4aKcas4dx(1YAZfoP25GC+ill!DZI1ST8{IVEVKBF za$85?ts&QPUaY;aMN5g)QU(L<%druAi3mCas?{~3UzL8AqBPBJ1U7HttTlC(eoz~< z&~PevL*y1qcG77?$J4%xIJi<^V|K(~J&t(&Z!WZsyFp{mGQb#jnOS(MQms zu5rz6GM1qN&YU9kF~^o6-l*c*>^OS8jBkEOePzq~K(ZI!A+6+{khJbOzezh?l4yZ& zX6u7@llDmU+w-0E;Pvc7`A<>#SbSn0(InDmRHxPZQKs$zM@)8Ce__L`Op4EXO)tH4 z&ce=kCC(N*P)sm4zW4rmGc9|ev-@0>t z_>(fJN_#5mPVv#K;T3+>(!VE~FgWdlxmT{(3m(8%gxjSpQ%GuP^xRE};q4ClnAly< z4H}xvJJ|J}WAL8sImf9CooC0 z`GK6@!;|lYDkEZv@HYdVemnPweTnopN3iXsP%-_`dksySZ0tr_4l0*K6t%vI{?yEK zQ0{;HYyhmFe5{o{o8OFo?&G?l8Wc83c2>1aA6HUzK=8Pp*;Wp&SDqOcA?*z#gKO+O{>qFVTF&e}@%IG(?eUJmtC;;Gd4 zN^SQu-x5+fV8>i_%aksfwDhRqUCvFd$!4a#aDlO3MKSPidCH|xXN=5_kC_!M+7TPY z?BCeGSWJ@gs%ahH-|6U=2v(8^$}8yCI{rb>m=Y=9F!Q=)>n68?gPBduoj1y}%di!Z zxiy+$y}it|Cc$+#j@(cG>Yo!&G?XvOyRqXXNvntbaCm#Ogc*Ll^#u>5Y^Iy)OAL09 zh!3|y-h4MRJ8u@L?&6F-AwE*(x~Gj16rU$kTPljsPiG^I3hwD`?Eaq6uCH-C%K5}; zy*7rk_?hD%6(-jyadykSZSIXK)}C%V7n=ep9`X(4VyB8f>|1Zd*?L{lLD{l< za4J~VDsoQ-)n0{lpz2bbp;Yarb`?sg(88hPMspwbFw<^A_;FZ|zE^yd=j^?f%aJa zz`)(Z4c{~}+XN-QbGSH%EwP+>f_lqA+pLUlDq?2aGX!*XRXmBxj$?Ljrq%S2{TzadOz2UC3W2{Kj2Qs|Bw&hZPgAY3Bs-aHI9eE&s zIYAo4y*pm=>61qh)#U<9Y8D7wY*{&#e+VSE*W|5iW|MbiW0SoHYE$#R_Sq3rxH9Ju zq3BUGT>Vx^O6Uo_1t{s5QtN~7vQ6UP+`RF_fhhsR*@RPrvlI3yQcEgGckW3z4Y3?- znC}yBM9on=r~g1qu2`ft#V*e)E;vaC&uL3HbGu`O&wMEomn;oD`P|%oOqNN)@9?{i z>+YXy&DU>aTgPmYoH3mo6WsYckXDRI~I~h_7X_rD?jWEl)Eh=C;rFD#vhG!WGv|ZJ)?Y)nz0T3| zP0hNaqz;+lUD;AfVY_8qnUn{xF#6U}ohiY-f}nv1EV02BW;{MXp||S&HQkte5To{? zrhXZB{DxE16C+qy!S+|ezJ4^TZW27W_mg&)n=dDEjaTYi9<-!0y;TAb>k3Mz36ZmN z9O!%2l!)1tgL}h;S<%u7;2o)-P+0K$5ppz!30^srsQXO9mEU#@8|Bnd-9GW4?`q}I ze%$qPMSjw&nO@-@9NIO3tsRsd?9mpZk5ueHE!EYQI%&Uccv$Wc@eQQ>v3P!prpemT z>@rL_7*%{A0lR!h=F!>eAt$;1=w6L`L@RD$1xi^F+Z$*@ep1{3n#rnKaxJ;bezox$ zON_32U1-vBcxn6#I0|#EL3KzIK*B-|bFwYj>X-O0&@C}x literal 3650 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 aWS&p(fIu!(CjkFLSj>$d8r2y%$NwKzaNBSI diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg b/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg index 6ddd3b3ed..caef4b7ac 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg +++ b/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg b/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg index 654e2fe24..0c8aea07d 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg +++ b/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg @@ -1,61 +1,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg b/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg index f01ad5c79..ef84c3c6e 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg +++ b/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg b/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg index 0598d584e..5467d4d57 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg +++ b/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less b/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less deleted file mode 100644 index baf471520..000000000 --- a/luci-theme-argon/htdocs/luci-static/argon/less/cascade.less +++ /dev/null @@ -1,4063 +0,0 @@ -// out: ../css/cascade.css, compress: true , sourceMap: false -/** - * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template - * - * luci-theme-argon - * Copyright 2020 Jerrykuku - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-material: - * Copyright 2015 Lutty Yang - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * Font generate by Icomoon - * - * Licensed to the public under the Apache License 2.0 - */ - -/* - * Include base and custom css - */ -@import url("pure-min.less"); -@import url("fonts.less"); - - -:root { - --primary: #5e72e4; - --dark-primary: #483d8b; - --main-color: #09c; - --header-bg: #09c; - --header-color: #fff; - --bar-bg: #5e72e4; - --menu-bg-color: #fff; - --menu-color: #5f6368; - --menu-color-hover: #202124; - --main-menu-color: #202124; - --submenu-bg-hover: #d4d4d4; - --submenu-bg-hover-active: #09c; - --blue: #5e72e4; - --indigo: #5603ad; - --purple: #8965e0; - --pink: #f3a4b5; - --red: #f5365c; - --orange: #fb6340; - --yellow: #ffd600; - --green: #2dce89; - --teal: #11cdef; - --cyan: #2bffc6; - --white: #fff; - --gray: #8898aa; - --gray-dark: #32325d; - --light: #ced4da; - --lighter: #e9ecef; - --secondary: #f7fafc; - --success: #2dce89; - --info: #11cdef; - --warning: #fb6340; - --danger: #f5365c; - --light: #adb5bd; - --dark: #212529; - --default: #172b4d; - --white: #fff; - --neutral: #fff; - --darker: black; - --background-color: #f4f5f7; - --login-form-bg-color: rgba(244, 245, 247, 0.8); - --breakpoint-xs: 0; - --breakpoint-sm: 576px; - --breakpoint-md: 768px; - --breakpoint-lg: 992px; - --breakpoint-xl: 1200px; - --blur-radius: 10px; - --blur-opacity: 0.5; - --blur-radius-dark: 10px; - --blur-opacity-dark: 0.5; - --font-family-sans-serif: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; - --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; - --font-family-normal: Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif; -} - -html, -body { - margin: 0px; - padding: 0px; - height: 100%; - font-size: 16px; - font-family: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; - font-family: var(--font-family-sans-serif); -} - -html { - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -body { - font-size: 0.875rem; - background-color: #f4f5f7; - - background-color: var(--background-color); - color: #32325d; - color: var(--gray-dark); - -webkit-tap-highlight-color: transparent; -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -::selection { - background-color: #5e72e4; - background-color: var(--primary); - color: #ffffff; - color: var(--white); -} - -a:link, -a:visited, -a:active { - color: #5e72e4; - color: var(--primary); - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -li { - list-style-type: none; -} - - - -.table { - position: relative; - display: table; -} - -.tr { - display: table-row; -} - -.thead { - display: table-header-group; -} - -.tbody { - display: table-row-group; -} - -.tfoot { - display: table-footer-group; -} - -.td, -.th { - line-height: normal; - display: table-cell; - padding: .5em; - text-align: center; - vertical-align: middle; -} - -.th { - font-weight: bold; - white-space: nowrap; -} - -.tr.placeholder { - height: 4em; -} - -.tr.placeholder>.td { - line-height: 3; - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 0.4rem 0 !important; - text-align: center !important; - background: inherit; -} - -.td[width="33%"] { - padding: 1.1em 1.5rem; -} - -.table[width="33%"], -.th[width="33%"], -.td[width="33%"] { - width: 33%; -} - -.table[width="100%"], -.th[width="100%"], -.td[width="100%"] { - width: 100%; -} - -.col-1 { - flex: 1 1 30px !important; -} - -.col-2 { - flex: 2 2 60px !important; -} - -.col-3 { - flex: 3 3 90px !important; -} - -.col-4 { - flex: 4 4 120px !important; -} - -.col-5 { - flex: 5 5 150px !important; -} - -.col-6 { - flex: 6 6 180px !important; -} - -.col-7 { - flex: 7 7 210px !important; -} - -.col-8 { - flex: 8 8 240px !important; -} - -.col-9 { - flex: 9 9 270px !important; -} - -.col-10 { - flex: 10 10 300px !important; -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; - -} - -.h1, -.h2, -.h3, -.h4, -.h5, -.h6, -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: inherit; - font-weight: normal; - line-height: 1.1 !important; - color: inherit; -} - - - -select { - padding: .36rem .8rem; - color: #555; - border: thin solid #ccc; - background-color: #fff; - background-image: none; -} - -.btn, -button, -select, -input, -.cbi-dropdown { - line-height: 1.5rem; - padding: .5rem .75rem; - margin: 0.25rem 0.1rem; - color: #8898aa; - border: 1px solid #dee2e6; - - border-radius: .25rem; - outline: 0; - background-image: none; - box-shadow: none; - transition: box-shadow .15s ease; -} - -select, -.cbi-dropdown { - width: inherit; - cursor: default; -} - -select:not([multiple="multiple"]):focus, -input:not(.cbi-button):focus, -.cbi-dropdown:focus { - border-color: #5e72e4; - border-color: var(--primary); - box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, .1); -} - -.cbi-dropdown, -select[multiple="multiple"] { - height: auto; -} - -pre { - overflow: auto; -} - -code { - font-size: 1rem; - font-size-adjust: .35; - padding: 1px 3px; - color: #101010; - border-radius: 2px; - background: #ddd; -} - -abbr { - cursor: help; - text-decoration: underline; - color: #5e72e4; - color: var(--primary); -} - -hr { - margin: 1rem 0; - opacity: .1; - border-color: #eee; -} - - - - -/*********************** -* -* Login Page -* -***************************/ - -.login-page { - height: 100%; - - .video { - position: absolute; - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - background-color: #000; - background-color: var(--darker); - overflow: hidden; - - video { - width: 100%; - height: auto; - } - } - - .volume-control { - position: fixed; - right: 1rem; - top: 1rem; - width: 1.5rem; - height: 1.5rem; - z-index: 5000; - cursor: pointer; - background-size: contain; - background-image: url(../img/volume_high.svg); - - &.mute { - background-image: url(../img/volume_off.svg); - } - } - - .main-bg { - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - background-image: url(../img/blank.png); - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all 0.5s; - } - - .login-container { - height: 100%; - margin-left: 4.5rem; - position: absolute; - top: 0px; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 100%; - z-index: 2; - width: 420px; - box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 35px -5px; - margin-left: 5%; - background: transparent; - - .login-form { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: absolute; - top: 0px; - width: 100%; - min-height: 100%; - max-width: 420px; - background-color: #fff; - background-color: var(--white); - -webkit-backdrop-filter: blur(var(--blur-radius)); - backdrop-filter: blur(var(--blur-radius)); - background-color: rgba(244, 245, 247, var(--blur-opacity)); - - .brand { - display: flex; - -webkit-box-align: center; - align-items: center; - margin: 50px auto 100px 50px; - color: #525461; - color: var(--default); - - .icon { - width: 50px; - height: auto; - margin-right: 25px; - } - - .brand-text { - font-size: 1.25rem; - font-weight: 700; - font-family: "TypoGraphica"; - - } - - &:hover { - text-decoration: none; - } - } - - .form-login { - width: 100%; - padding: 20px 50px; - box-sizing: border-box; - - .errorbox { - text-align: center; - color: #fb6340; - color: var(--warning); - padding-bottom: 2rem; - } - - .input-group { - margin-bottom: 1.25rem; - position: relative; - - &::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - color: #525461; - color: var(--default); - font-size: 1.5rem; - position: absolute; - z-index: 100; - left: 10px; - top: 10px; - } - - .border { - position: absolute; - width: 100%; - height: 1px; - bottom: 0; - border-bottom: 1px #5e72e4 solid; - border-bottom: 1px var(--primary) solid; - transform: scaleX(0); - transition: transform 0.3s; - } - - input { - font-size: 1rem; - line-height: 1.5em; - display: block; - width: 100%; - padding: .5rem .75rem 0.5rem 3rem; - margin: 0.825rem 0; - box-sizing: border-box; - transition: all .3s cubic-bezier(.68, -.55, .265, 1.55); - color: #525461; - color: var(--default); - border: 0; - border-radius: 0; - border-bottom: 1px solid #fff; - border-bottom: 1px solid var(--white); - background-color: transparent; - background-clip: padding-box; - box-shadow: 0 3px 2px rgba(233, 236, 239, .05); - outline: none; - - &:focus+.border { - transform: scaleX(1); - } - } - - .cbi-input-password { - margin-bottom: 2rem; - position: relative; - } - } - - .user-icon::before { - content: "\e971"; - } - - .pass-icon::before { - content: "\e910"; - - } - } - - .cbi-button-apply { - width: 100% !important; - box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 50px 0px; - font-weight: 600; - font-size: 15px; - color: #fff; - color: var(--white); - text-align: center; - width: 100%; - cursor: pointer; - min-height: 50px; - background-color: #5e72e4 !important; - background-color: var(--primary) !important; - border-radius: 6px; - outline: none; - border-width: initial; - border-style: none; - border-color: initial; - border-image: initial; - padding: 10px 0px; - margin: 30px 0px 100px; - transition: all 0.3s !important; - letter-spacing: 0.8rem; - - &:hover, - :focus { - opacity: 0.9; - } - } - } - - footer { - box-sizing: border-box; - width: 100%; - text-align: center; - line-height: 1.6rem; - display: flex; - justify-content: space-evenly; - margin-top: auto; - padding: 0px 0px 30px; - z-index: 10; - color: #525461; - color: var(--default); - position: absolute; - bottom: 0; - - .ftc { - position: absolute; - bottom: 30px; - width: 100%; - } - - .luci-link { - display: block; - } - } - } -} - - -header, -.main { - width: 100%; -} - - -footer { - font-size: .8rem; - overflow: hidden; - padding: 1rem; - text-align: right; - white-space: nowrap; - color: #aaa; -} - -footer>a { - text-decoration: none; - color: #aaa; -} - -small { - font-size: 90%; - line-height: 1.42857143; - white-space: normal; -} - -.main { - position: relative; - top: 0; - bottom: 0; - overflow-y: auto; - height: 100%; -} - -.main-left { - position: fixed; - top: 0; - float: left; - overflow-x: auto; - width: 15%; - width: calc(0% + 15rem); - height: 100%; - background-color: #fff; - background-color: var(--menu-bg-color); - box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 15px -5px; - overflow-x: auto; - position: fixed; - z-index: 100; - - - .sidenav-header { - padding: 1.5rem .5rem; - text-align: center; - - .brand { - font-size: 1.8rem; - color: #5e72e4; - color: var(--primary); - font-family: "TypoGraphica"; - text-decoration: none; - text-align: center; - cursor: default; - vertical-align: text-bottom; - } - } - - &::-webkit-scrollbar { - width: 5px; - height: 1px; - } - - &::-webkit-scrollbar-thumb { - background-color: #f6f9fc - } - - &::-webkit-scrollbar-track { - background-color: #fff; - } -} - -.main-right { - float: right; - width: 85%; - width: calc(100% - 15rem); - height: 100%; - transition: all 0.2s; -} - -.main-right>#maincontent { - position: relative; - z-index: 50; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.nowrap:not(.td) { - white-space: nowrap; -} - -[disabled="disabled"] { - pointer-events: none; -} - -header { - color: #fff; - color: var(--header-color); - padding: 0; - position: relative; - - &.bg-primary { - background-color: #5e72e4 !important; - background-color: var(--primary) !important; - } - - &::after { - content: ""; - position: absolute; - height: 2rem; - width: 100%; - background-color: #5e72e4 !important; - background-color: var(--primary) !important; - } - - .fill { - padding: 0.8rem 0; - border-bottom: 0px solid rgba(255, 255, 255, .08) !important; - display: flex; - - .container { - height: 2rem; - padding: 0 1.25rem; - display: flex; - align-items: center; - width: 100%; - - .flex1 { - flex: 1; - - .showSide { - display: none; - color: #fff; - font-size: 1.4rem; - - &:hover { - text-decoration: none; - } - } - - .brand { - font-size: 1.5rem; - color: #fff; - font-family: "TypoGraphica"; - text-decoration: none; - padding-left: 1rem; - cursor: default; - vertical-align: text-bottom; - display: none; - } - } - - - .pull-right { - float: right; - margin-top: 0rem; - display: flex; - } - } - - .status { - span{ - display: inline-block; - font-size: 0.8rem; - font-weight: bold; - padding: 0.3rem 0.8rem; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - text-shadow: none; - border-radius: 4px; - cursor: pointer; - transition: all 0.3s; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); - margin: 0 0.25rem; - &:last-child{ - margin-right: 0; - } - } - - span[data-indicator="poll-status"] { - color: #32325d; - background-color: #fff; - } - - span[data-style="active"] { - - background-color: var(--green); - - } - - span[data-style="inactive"] { - color: #ffffff !important; - background-color: #32325d; - - } - } - } -} - - - -#xhr_poll_status { - display: flex; - margin-left: 0.5rem; - - * { - color: #fff; - } -} - -div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - border: 0 !important; -} - -.danger { - background-color: #ff7d60 !important; -} - -.warning { - background-color: #f0e68c !important; -} - -.success { - background-color: #5cb85c !important; -} - -.notice { - background-color: #11cdef !important; - color: #fff; -} - -.error { - color: #f00; -} - -.alert, -.alert-message { - font-weight: bold; - margin-bottom: 1.25rem; - padding: 1rem 1.25rem; - border: 0; - border-radius: 0.375rem !important; - background-color: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); - text-shadow: 1px 1px rgba(0, 0, 0, .1); - - &.error { - background-color: #ffd600; - } - - h4 { - padding: 0.25rem 0rem; - border-radius: 4px; - background-color: #ffd600; - } - - .btn { - height: auto; - } -} - -.alert-message>h4 { - font-size: 110%; - font-weight: bold; -} - -.alert-message>* { - margin: .5rem 0; -} - -.alert-message .btn { - padding: .3rem .6rem; -} - -.container .alert, -.container .alert-message { - margin-top: 0rem; -} - - -/* - * Main Menu - */ - -.main { - .main-left { - transition: all 0.2s; - - .nav { - margin-top: 0.5rem; - - >li>a:first-child { - display: block; - margin: 0.1rem .5rem 0.1rem .5rem; - padding: .675rem 0 .675rem 2.5rem; - border-radius: .375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; - - &.active { - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - - &::after { - transform: rotate(90deg); - color: #fff !important; - } - } - - &:hover { - cursor: pointer; - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - } - - &::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e915"; - color: #5e72e4; - color: var(--primary); - } - } - - li { - padding: 0.5rem 1rem; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - padding: 0; - - a { - display: block; - color: #5f6368; - color: var(--menu-color); - } - - &.slide { - padding: 0; - - ul { - display: none; - overflow: hidden; - } - - &:hover { - background: none; - } - - .slide-menu { - margin: 0 0.5rem 0 2.5rem; - padding: 0rem 0.5rem; - - &.active { - display: block; - - } - - - li { - position: relative; - border-radius: 0.375rem; - margin: 0; - padding: 0.5rem 0rem; - background: none; - list-style: none; - - a { - text-decoration: none; - } - - &::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 0; - height: 2px; - background-color: #5e72e4; - background-color: var(--primary); - transition: all 0.2s; - } - - &:hover { - background: none; - - &::after { - width: 100%; - } - } - - } - - .active { - background: none; - - color: var(--menu-color); - - a { - color: var(--menu-color); - } - - &::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 100%; - height: 2px; - background-color: #5e72e4; - background-color: var(--primary); - transition: all 0.2s; - } - - &:hover { - - background: none; - - &::after { - width: 100%; - } - } - } - } - - } - - - - .menu { - display: block; - margin: 0.1rem .5rem 0.1rem .5rem; - padding: .675rem 0 .675rem 2.5rem; - border-radius: .375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; - - &.active { - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - - &::after { - transform: rotate(90deg); - color: #fff !important; - } - } - - &:hover { - cursor: pointer; - color: #fff; - background: #5e72e4; - background: var(--primary); - - &::before { - color: #fff !important; - } - } - - &::before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e915"; - color: #5e72e4; - color: var(--primary); - } - - &::after { - position: absolute; - right: 0.5rem; - top: 0.8rem; - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: '\e90f'; - transition: all .15s ease; - color: #ced4da; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - transition: all 0.3s; - } - } - - - .menu[data-title=Status]:before { - content: "\e906"; - color: #5e72e4; - color: var(--primary); - } - - .menu[data-title=System]:before { - content: "\e90a"; - color: #fb6340; - } - - .menu[data-title=Services]:before { - content: "\e909"; - color: #11cdef; - } - - .menu[data-title=NAS]:before { - content: "\e90c"; - color: #f3a4b5; - } - - .menu[data-title=VPN]:before { - content: "\e90b"; - color: #8965e0; - } - - .menu[data-title=Network]:before { - content: "\e908"; - color: #8965e0; - } - - .menu[data-title=Bandwidth_Monitor]:before { - content: "\e90d"; - color: #2dce89; - } - - .menu[data-title=Docker]:before { - content: "\e911"; - color: #6699ff; - } - - .menu[data-title=Statistics]:before { - content: "\e913"; - color: #8965e0; - } - - .menu[data-title=Control]:before { - content: "\e912"; - color: #5e72e4; - color: var(--primary); - } - - .menu[data-title=Asterisk]:before { - content: "\e914"; - color: #fb6340; - } - - a[data-title=Logout]:before { - content: "\e907"; - color: #adb5bd; - } - } - } - } -} - -.lg { - margin: 0; - padding: 0 !important; -} - -.logout { - display: block; - margin: 0.8rem .5rem 0.1rem 0.5rem; - padding: .675rem 0 .675rem 2.5rem; - border-radius: .375rem; - text-decoration: none; - font-size: 1rem; - transition: all 0.2s; - position: relative; -} - -.logout:before { - font-family: 'argon' !important; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 0.8rem; - padding-top: 3px; - transition: all 0.3s; - content: "\e907"; - color: #32325d !important; -} - - -body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { - transition: transform .1s ease-in-out; -} - -body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { - transition: transform .2s ease-in-out; -} - -.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before { - display: none; -} - - - - -#maincontent>.container { - margin: 0 1.25rem 1rem 1.25rem; -} - -ul { - line-height: normal; -} - -li { - list-style-type: none; -} - -h1 { - font-size: 2rem; - padding-bottom: 10px; - border-bottom: thin solid #eee; -} - -h2 { - margin: 0 0 1rem 0; - font-size: 1.25rem; - letter-spacing: 0.1rem; - padding: 1rem 1.25rem; - color: #32325d; - border-radius: .375rem; - background: #fff; - box-shadow: 0 4px 8px rgba(0, 0, 0, .03); - font-weight: bold; - -} - -h3 { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - margin: 0; - margin-bottom: 0; - padding: 0.8755rem 1.25rem; - color: #32325d; - color: var(--gray-dark); - border-radius: .375rem; - background: #fff; - font-weight: bold; -} - -h4 { - margin: 0; - padding: 0.75rem 1.25rem; - font-size: 0.7rem; - font-weight: 600; - color: #525f7f; - background-color: #e9ecef; - background-color: var(--lighter); - font-weight: bold; - - em { - padding: 0 0.5rem; - } - -} - -h5 { - font-size: 1rem; - margin: 2rem 0 0 0; - padding-bottom: 10px; -} - -.cbi-section, -.cbi-section-error, -#iptables, -.Firewall form, -#cbi-network>.cbi-section-node, -#cbi-wireless>.cbi-section-node, -#cbi-wireless>#wifi_assoclist_table, -[data-tab-title], -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent>.container { - font-family: inherit; - font-weight: normal; - font-style: normal; - line-height: normal; - min-width: inherit; - margin: 1.25rem 0; - padding: 0rem; - border: 0; - - border-radius: 0.375rem; - background-color: #fff; - box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .15) -} - -.cbi-modal .cbi-section, -.cbi-section .cbi-section { - padding: 0; - box-shadow: none; -} - -.cbi-modal .cbi-tabmenu { - margin-left: 0; -} - -.cbi-map-descr { - font-size: small; - line-height: 1.5; - padding: 0 1.25rem; -} - -.cbi-section-descr:not(:empty) { - - font-size: small; - line-height: 1.5; - padding: 1rem 1.25rem 0 1.25rem; -} - -.cbi-map-descr+fieldset { - margin-top: 1rem; -} - -.cbi-map-descr>abbr { - cursor: help; - text-decoration: underline; -} - -.cbi-section>legend { - display: none !important; -} - -fieldset>fieldset, -.cbi-section>.cbi-section { - margin: 0; - padding: 0; - border: 0; - box-shadow: none; -} - -.cbi-section>h3:first-child, -.panel-title { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - margin: 0; - margin-bottom: 0; - padding: 0.8755rem 1.25rem; - color: #32325d; - color: var(--gray-dark); - -} - -.cbi-section>h3:first-child, -.cbi-section>h4:first-child, -.cbi-section>p:first-child, -[data-tab-title]>h3:first-child, -[data-tab-title]>h4:first-child, -[data-tab-title]>p:first-child { - padding: 1rem 1.25rem; -} - -.cbi-section p { - padding: 1rem; -} - -.cbi-tblsection { - overflow-x: scroll; -} - -table { - border-spacing: 0; - border-collapse: collapse; -} - -table, -.table { - overflow-y: hidden; - width: 100%; - font-size: 90%; -} - -.table .table-titles th { - background-color: #e9ecef; - background-color: var(--lighter); -} - -table>tbody>tr>td, -table>tbody>tr>th, -table>tfoot>tr>td, -table>tfoot>tr>th, -table>thead>tr>td, -table>thead>tr>th, -.table>.tbody>.tr>.td, -.table>.tbody>.tr>.th, -.table>.tfoot>.tr>.td, -.table>.tfoot>.tr>.th, -.table>.thead>.tr>.td, -.table>.thead>.tr>.th, -.table>.tr>.td.cbi-value-field, -.table>.tr>.th.cbi-section-table-cell { - padding: .5rem; -} - -.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { - padding: .6rem; -} - -.cbi-section-table-cell { - line-height: 1.1; - align-self: flex-end; - flex: 1 1 auto; -} - -tr>td, -tr>th, -.tr>.td, -.tr>.th, -.cbi-section-table-row::before, -#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { - border-top: thin solid #ddd; - padding: 1.1em 1.25rem; -} - -#cbi-wireless .td, -#cbi-network .tr:first-child>.td, -.table[width="100%"]>.tr:first-child>.td, -[data-page="admin-network-diagnostics"] .tr>.td, -.tr.table-titles>.th, -.tr.cbi-section-table-titles>.th { - border-top: 0 !important; - background-color: #f6f9fc; - padding: 1.1em 1.25rem; - line-height: 1.3rem; -} - -.table[width="100%"]>.tr:first-child>.td { - margin: auto 0; -} - -.cbi-section-table-row { - margin-bottom: 1rem; - text-align: center !important; - background: #f4f4f4; -} - -.cbi-section-table-row:last-child { - margin-bottom: 0; -} - -.cbi-section-table-row>.cbi-value-field .cbi-dropdown, -.cbi-section-table-row>.cbi-value-field .cbi-input-select, -.cbi-section-table-row>.cbi-value-field .cbi-input-text, -.cbi-section-table-row>.cbi-value-field .cbi-input-password { - width: 100%; -} - -.cbi-section-table-row>.cbi-value-field .cbi-input-text, -.cbi-section-table-row>.cbi-value-field .cbi-input-password { - min-width: 80px; -} - -.cbi-section-table-row>.cbi-value-field [data-dynlist]>input, -.cbi-section-table-row>.cbi-value-field input.cbi-input-password { - width: calc(100% - 1.5rem); -} - -.cbi-section-table-row .td { - text-align: center !important; -} - -.control-group { - display: inline-flex; - width: 100%; - flex-wrap: wrap; - gap: 2px; -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tr:nth-of-type(2n) { - background-color: #f9f9f9; -} - -/* fix multiple table */ -table table, -.table .table, -.cbi-value-field table, -.cbi-value-field .table, -td>table>tbody>tr>td, -.td>.table>.tbody>.tr>.td, -.cbi-value-field>table>tbody>tr>td, -.cbi-value-field>.table>.tbody>.tr>.td { - border: 0; -} - -/* button style */ -.btn, -.cbi-button, -.item::after { - font-size: .8rem; - display: inline-block; - width: auto !important; - padding: 0.45rem .8rem; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all .2s ease-in-out; - text-align: center; - vertical-align: middle; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: rgba(0, 0, 0, .87); - border: 0; - border-radius: .2rem; - background-color: #f0f0f0; - background-image: none; - -webkit-appearance: none; - -ms-touch-action: manipulation; - touch-action: manipulation; -} - -.cbi-button-up, -.cbi-button-down { - font-size: 1.2rem; - display: inline-block; - min-width: 0; - padding: .2rem 1rem; - font-size: 0; - color: transparent !important; - background: url(../icon/arrow.svg) no-repeat center; - background-size: 12px 20px; -} - -.cbi-button-up { - transform: scaleY(-1); -} - -.cbi-button:not(select) { - -webkit-appearance: none !important; -} - - -.btn:hover, -.btn:focus, -.btn:active, -.cbi-button:hover, -.cbi-button:focus, -.cbi-button:active, -.item:hover::after, -.item:focus::after, -.item:active::after, -.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover, -.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus, -.cbi-page-actions .cbi-button-apply+.cbi-button-save:active { - text-decoration: none; - outline: 0; -} - -.btn:hover, -.btn:focus, -.cbi-button:hover, -.cbi-button:focus, -.item:hover::after, -.item:focus::after { - box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 2px 2px rgba(0, 0, 0, .2); -} - -.btn:active, -.cbi-button:active, -.item:active::after { - box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23); -} - -.cbi-button-up:hover, -.cbi-button-up:focus { - box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 -2px 2px rgba(0, 0, 0, .2); -} - -.cbi-button-up:active { - box-shadow: 0 -10px 20px rgba(0, 0, 0, .19), 0 -6px 6px rgba(0, 0, 0, .23); -} - -.btn:disabled, -.cbi-button:disabled { - cursor: not-allowed; - pointer-events: none; - opacity: .5; - box-shadow: none; -} - -/* gray */ -.alert-message [class="btn"], -.modal div[class="btn"], -.cbi-button-find, -.cbi-button-link, -.cbi-button-up, -.cbi-button-down, -.cbi-button-neutral, -.cbi-button[name="zero"], -.cbi-button[name="restart"], -.cbi-button[onclick="hide_empty(this)"] { - font-weight: bold; - color: #fff; - border: thin solid #8898aa; - background-color: #8898aa; -} - -/* dark blue */ -.btn.primary, -.cbi-page-actions .cbi-button-save, -.cbi-page-actions .cbi-button-apply+.cbi-button-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-positive, -.cbi-button-link, -.cbi-button[value="Enable"], -.cbi-button[value="Scan"], -.cbi-button[value^="Back"], -.cbi-button-neutral[onclick="handleConfig(event)"] { - font-weight: normal; - color: #fff !important; - border: thin solid #5e72e4; - border: thin solid var(--primary); - background-color: #5e72e4; - background-color: var(--primary); - ; -} - -/* light blue */ -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-action, -.cbi-button[value="Submit"], -.cbi-button[value="Upload"], -.cbi-button[value$="Apply"], -.cbi-button[onclick="addKey(event)"] { - font-weight: normal; - color: #fff !important; - border: thin solid #5e72e4; - border: thin solid var(--primary); - - background-color: #5e72e4; - background-color: var(--primary); -} - -/* red */ -.btn.danger, -.cbi-section-remove>.cbi-button, -.cbi-button-remove, -.cbi-button-reset, -.cbi-button-negative, -.cbi-button[value="Stop"], -.cbi-button[value="Kill"], -.cbi-button[onclick="reboot(this)"], -.cbi-button-neutral[value="Restart"] { - font-weight: normal; - color: #fff; - border: thin solid #f5365c; - border: thin solid var(--red); - background-color: #f5365c; - background-color: var(--red); -} - -/* yellow */ -.btn[value="Dismiss"], -.cbi-button[value="Terminate"], -.cbi-button[value="Reset"], -.cbi-button[value="Disabled"], -.cbi-button[onclick^="iface_reconnect"], -.cbi-button[onclick="handleReset(event)"], -.cbi-button-neutral[value="Disable"] { - font-weight: normal; - color: #fff; - border: thin solid #eea236; - background-color: #f0ad4e; -} - -/* green */ -.cbi-button-success, -.cbi-button-download, -.cbi-button[name="backup"], -.cbi-button[value="Download"], -.cbi-button[value="Save mtdblock"] { - font-weight: normal; - color: #fff; - border: thin solid #4cae4c; - background-color: #5cb85c; -} - -.cbi-page-actions .cbi-button-link:first-child { - float: left; -} - -.a-to-btn { - text-decoration: none; -} - -.cbi-value-field .cbi-button-add { - font-weight: bold; - margin: 4px 0 4px 3px; - padding: 1px 6px; - display: flex; - align-items: center; -} - -.tabs { - margin: 0 0 1rem 0; - padding: 0 1rem; - background-color: #FFFFFF; - border-radius: 0.375rem; - box-shadow: 0 4px 8px rgba(0, 0, 0, .03); - white-space: nowrap; - overflow-x: auto; - - &::-webkit-scrollbar { - width: 1px; - height: 5px; - } - - &::-webkit-scrollbar-thumb { - background-color: #f6f9fc - } - - &::-webkit-scrollbar-track { - background-color: #fff; - } - - li[class~="active"], - li:hover { - cursor: pointer; - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - border-radius: 0; - - a { - color: #5e72e4; - color: var(--primary); - } - } - - li { - font-size: 0.875rem; - display: inline-block; - padding: 0.875rem 0rem; - border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); - margin: 0; - transition: all 0.2s; - - a { - text-decoration: none; - color: #404040; - padding: 0.5rem 0.8rem; - } - - &:hover { - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - } - } -} - - - - -.cbi-tabmenu { - color: white; - padding: 0.5rem 1rem 0 1rem; - white-space: nowrap; - overflow-x: auto; - - &::-webkit-scrollbar { - width: 1px; - height: 5px; - } - - &::-webkit-scrollbar-thumb { - background-color: #f6f9fc - } - - &::-webkit-scrollbar-track { - background-color: #fff; - } - - li { - background: #dce3e9; - display: inline-block; - font-size: 0.875rem; - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; - padding: 0.5rem 0rem; - border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); - margin: 0 0.2rem; - - a { - text-decoration: none; - color: #404040; - padding: 0.5rem 0.8rem; - } - - &:hover { - cursor: pointer; - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - - a { - color: #525f7f; - } - } - } - - li[class~="cbi-tab"] { - border-bottom: 0.18751rem solid #5e72e4; - border-bottom: 0.18751rem solid var(--primary); - color: #5e72e4; - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - - a { - color: #5e72e4; - color: var(--primary); - } - } -} - -.cbi-tab-descr { - padding: 0.5rem 1.5rem; -} - -.cbi-section-node { - padding: 1rem 0; -} - -.cbi-section .cbi-section-remove:nth-of-type(2n), -.container>.cbi-section .cbi-section-node:nth-of-type(2n) { - background-color: #f9f9f9; -} - -[data-tab-title] { - overflow: hidden; - height: 0; - opacity: 0; - margin: 0; - padding: 0rem 0rem !important; - - p { - margin-left: 1rem; - margin-bottom: 1rem; - } -} - - - -[data-tab-active="true"] { - overflow: visible; - height: auto; - opacity: 1; - transition: opacity .25s ease-in; - margin: inherit !important; -} - - -.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3), -.cbi-section[id] .cbi-section-node:nth-of-type(4n+4) { - background-color: #f9f9f9; -} - -.cbi-section-node-tabbed { - margin-top: 0; - padding: 0; - border: 0 solid #d4d4d4; - border-radius: 0.375rem; -} - -.cbi-tabcontainer>.cbi-value:nth-of-type(2n) { - background-color: #f9f9f9; -} - -.cbi-value-field, -.cbi-value-description { - line-height: 1.25; - display: table-cell; - - abbr { - color: #32325d; - color: var(--gray-dark); - } -} - -.cbi-value-description { - font-size: small; - padding: .5rem; - opacity: .5; -} - -.cbi-value-title { - display: table-cell; - float: left; - width: 23rem; - padding-top: .25rem; - padding-right: 2rem; - text-align: right; - word-wrap: break-word; -} - -.cbi-value { - display: inline-block; - width: 100%; - padding: .35rem 1rem .2rem 1rem; - line-height: 2.4rem; -} - -.cbi-value ul { - line-height: 1.25; -} - -.cbi-value-field .cbi-dropdown, -.cbi-value-field .cbi-input-select, -.cbi-value input[type="text"], -.cbi-value input[type="password"] { - min-width: 18rem; -} - -.cbi-value input[type="password"] { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - margin-right: 0; -} - -.cbi-value input[type="password"]+.cbi-button-neutral { - height: 42px; - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin-left: 0; - border: 0; -} - -#cbi-firewall-zone .cbi-input-select, -#cbi-network-switch_vlan .cbi-input-select { - min-width: 11rem; -} - -#cbi-network-switch_vlan .cbi-input-text { - max-width: 3rem; -} - -.cbi-input-invalid { - color: #f5365c; - border-bottom-color: #f5365c; -} - -.cbi-section-error { - font-weight: bold; - line-height: 1.42857143; - margin: 18px; - padding: 6px; - border: thin solid #f5365c; - border-radius: 3px; - background-color: #fce6e6; -} - -.cbi-section-error ul { - margin: 0 0 0 20px; -} - -.cbi-section-error ul li { - font-weight: bold; - color: #f5365c; -} - -.td[data-title]::before { - font-weight: bold; - display: none; - padding: .25rem 0; - content: attr(data-title) ":\20"; - text-align: left; - white-space: nowrap; -} - -.tr.placeholder .td[data-title]::before { - display: none; -} - -.tr[data-title]::before, -.tr.cbi-section-table-titles.named::before { - font-weight: bold; - display: table-cell; - align-self: center; - flex: 1 1 5%; - padding: .25rem; - content: attr(data-title) "\20"; - text-align: center; - vertical-align: middle; - white-space: normal; - word-wrap: break-word; -} - -.cbi-rowstyle-1 { - background-color: #f9f9f9; -} - -.cbi-rowstyle-2 { - background-color: #eee; -} - -.cbi-rowstyle-2 .cbi-button-up, -.cbi-rowstyle-2 .cbi-button-down, -body:not(.Interfaces) .cbi-rowstyle-2:first-child { - background-color: #fff !important; -} - -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - width: auto !important; -} - -.td.cbi-section-actions { - text-align: right !important; - vertical-align: middle; -} - -.td.cbi-section-actions>* { - display: inline-flex; -} - -.td.cbi-section-actions>*>*, -.td.cbi-section-actions>*>form>* { - margin: 0 5px; - display: flex; - align-items: center; -} - -.td.cbi-section-actions>*>form { - display: inline-flex; - margin: 0; -} - -.cbi-checkbox { - margin: 0 0.25rem; -} - -/* lists */ -.cbi-dynlist { - line-height: 1.3; - flex-direction: column; - min-height: 30px; - cursor: text; -} - -.cbi-dynlist>.item { - position: relative; - max-width: 25rem; - pointer-events: none; - color: #8898aa; - outline: 0; -} - -.cbi-dynlist[name="sshkeys"]>.item { - max-width: none; -} - -.cbi-dynlist>.item::after { - position: absolute; - width: 2.2rem !important; - height: calc(100% - 0.5rem - 2px); - right: 0; - bottom: 0; - content: "\00D7"; - pointer-events: auto; - background-color: var(--red); - font-weight: normal; - font-size: 1.2rem; - display: flex; - align-items: center; - justify-content: center; - line-height: 1.5rem; - padding: 0; - margin: 0.25rem 0.1rem 0.25rem 0; - color: #fff; - border: 1px solid #f5365c; - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.cbi-dynlist>.item>span { - white-space: normal; - word-break: break-word; - line-height: 1.5rem; - padding: 0.5rem 0.5rem; - margin: 0.25rem 0.1rem; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - display: block; - transition: box-shadow 0.15s ease; - box-sizing: border-box; - min-width: 15rem; -} - -.cbi-dynlist>.add-item { - display: inline-flex; - align-items: center; - width: 100%; - min-width: 16rem; -} - -.cbi-dynlist>.add-item input { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - margin-right: 0; - border-right: none; -} - -.cbi-dynlist>.add-item .cbi-button-add { - font-weight: normal; - font-size: 1.2rem; - display: flex; - align-items: center; - line-height: 1.5rem; - padding: 0.5rem 0.75rem; - margin: 0.25rem 0.1rem 0.25rem 0; - color: #fff; - border: 1px solid #5e72e4; - border: 1px solid var(--primary); - border-radius: 0.25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.cbi-dynlist>.add-item:not([ondrop])>input { - overflow: hidden; - width: 100%; - min-width: 15rem; - white-space: nowrap; - text-overflow: ellipsis; -} - -.cbi-dynlist>.add-item[ondrop]>input { - min-width: 13rem; -} - -.cbi-dynlist, -.cbi-dropdown { - position: relative; - display: inline-flex; - padding: 0.2rem 0.2rem; -} - -.cbi-dropdown[placeholder*="select"] { - max-width: 25rem; - height: auto; - margin-top: -3px; -} - -.cbi-dropdown>ul { - display: flex; - overflow-x: hidden; - overflow-y: auto; - width: 100%; - margin: 0 !important; - padding: 0; - list-style: none; - outline: 0; -} - - -.cbi-dropdown>ul.preview { - display: none; - -} - -.cbi-button-apply>ul.preview { - display: none; - - li { - color: #fff; - } - -} - -.cbi-button-apply>ul:first-child { - li { - color: #fff; - } - -} - -.cbi-dropdown>.open { - flex-basis: 15px; -} - -.cbi-dropdown>.open, -.cbi-dropdown>.more { - font-size: 1rem; - font-weight: 900; - line-height: 2; - display: flex; - flex-direction: column; - flex-grow: 0; - flex-shrink: 0; - justify-content: center; - padding: 0 .25em; - cursor: default; - text-align: center; - outline: 0; -} - -.cbi-dropdown>.more, -.cbi-dropdown>ul>li[placeholder] { - font-weight: bold; - display: none; - color: #777; - text-shadow: 1px 1px 0 #fff; -} - -.cbi-dropdown>ul>li { - display: none; - overflow: hidden; - align-items: center; - align-self: center; - flex-grow: 1; - flex-shrink: 1; - min-height: 20px; - padding: .25em; - white-space: nowrap; - text-overflow: ellipsis; - -} - -.cbi-dropdown>ul>li .hide-open { - display: initial; -} - -.cbi-dropdown>ul>li .hide-close { - display: none; -} - -.cbi-dropdown>ul>li[display]:not([display="0"]) { - border-left: thin solid #ccc; -} - -.cbi-dropdown[empty]>ul { - max-width: 1px; -} - -.cbi-dropdown>ul>li>form { - display: none; - margin: 0; - padding: 0; - pointer-events: none; -} - -.cbi-dropdown>ul>li img { - margin-right: .25em; - vertical-align: middle; -} - -.cbi-dropdown>ul>li>form>input[type="checkbox"] { - height: auto; - margin: 0; -} - -.cbi-dropdown>ul>li input[type="text"] { - height: 20px; -} - -.cbi-dropdown[open]>ul.dropdown { - position: absolute; - z-index: 1100; - display: block; - width: auto; - min-width: 100%; - max-width: none; - max-height: 200px !important; - border: 0 solid #918e8c; - background: #ffffff; - box-shadow: 0 0 4px #918e8c; - border-bottom-left-radius: 0.35rem; - border-bottom-right-radius: 0.35rem; - color: var(--main-menu-color); - margin-left: -0.2rem !important; - - li { - color: #000; - } -} - - -.cbi-dropdown>ul>li[display], -.cbi-dropdown[open]>ul.preview, -.cbi-dropdown[open]>ul.dropdown>li, -.cbi-dropdown[multiple]>ul>li>label, -.cbi-dropdown[multiple][open]>ul.dropdown>li, -.cbi-dropdown[multiple][more]>.more, -.cbi-dropdown[multiple][empty]>.more { - display: flex; - align-items: center; - flex-grow: 1; - -} - -.cbi-dropdown[empty]>ul>li, -.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], -.cbi-dropdown[multiple][open]>ul.dropdown>li>form { - display: block; -} - -.cbi-dropdown[open]>ul.dropdown>li .hide-open { - display: none; -} - -.cbi-dropdown[open]>ul.dropdown>li .hide-close { - display: initial; -} - -.cbi-dropdown[open]>ul.dropdown>li { - border-bottom: thin solid #ccc; - padding: 0.5rem 0.8rem; -} - -.cbi-dropdown[open]>ul.dropdown>li label { - margin-left: 0.5rem; -} - -.cbi-dropdown[open]>ul.dropdown>li[selected] { - background: #dce1fe; -} - -.cbi-dropdown[open]>ul.dropdown>li.focus { - background: #dce1fe; - outline: none; -} - -.cbi-dropdown[open]>ul.dropdown>li:last-child { - margin-bottom: 0; - border-bottom: 0; -} - -.cbi-dropdown[open]>ul.dropdown>li[unselectable] { - opacity: .7; -} - -.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child { - width: 100%; -} - -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: .6; -} - -.cbi-dropdown .zonebadge { - width: 100%; -} - -.cbi-dropdown[open] .zonebadge { - width: auto; -} - -/* progressbar */ -.cbi-progressbar { - position: relative; - min-width: 11rem; - height: 1.5rem; - margin: 0 0; - border: thin solid #999; - background: #eee; - border-radius: 4px; - overflow: hidden; -} - -.cbi-progressbar>div { - width: 0; - height: 100%; - transition: width .25s ease-in; - background: #5bc0de; - background: var(--bar-bg); -} - -.cbi-progressbar::after { - font-family: monospace; - font-size: 1em; - font-weight: bold; - font-size-adjust: .38; - line-height: 1.5rem; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - overflow: hidden; - content: attr(title); - text-align: center; - white-space: pre; - text-overflow: ellipsis; -} - -#modal_overlay { - position: fixed; - z-index: 900; - top: 0; - right: 10000px; - bottom: 0; - left: -10000px; - overflow-y: scroll; - transition: opacity .125s ease-in; - opacity: 0; - background: rgba(0, 0, 0, .7); - -webkit-overflow-scrolling: touch; -} - -.modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 90%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - margin: 5em auto; - padding: 1em; - border-radius: 3px !important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -.modal>* { - line-height: normal; - flex-basis: 100%; - margin-bottom: .5em; - max-width: 100%; -} - -.modal>pre, -.modal>textarea { - font-size: 1rem; - font-size-adjust: .35; - overflow: auto; - margin-bottom: .5em; - padding: 8.5px; - cursor: auto; - white-space: pre-wrap; - color: #eee; - outline: 0; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -.modal>h4 { - margin: .5em 0; -} - -.modal ul { - margin-left: 2.2em; -} - -.modal li { - list-style-type: square; - color: #808080; -} - -.modal p { - - word-break: break-word; -} - -.modal .label { - font-size: .6rem; - font-weight: normal; - padding: .1rem .3rem; - padding-bottom: 0; - cursor: default; - border-radius: 0; -} - -.modal .label.warning { - background-color: #f0ad4e !important; -} - -.modal .btn { - padding: 0.45rem 0.8rem; -} - -.modal.cbi-modal { - max-width: 90%; - max-height: none; -} - -body.modal-overlay-active { - overflow: hidden; - height: 100vh; -} - -body.modal-overlay-active #modal_overlay { - right: 0; - left: 0; - opacity: 1; -} - - - -.spinning { - position: relative; - padding-left: 32px !important; -} - -.spinning::before { - position: absolute; - top: 0; - bottom: 0; - left: .2em; - width: 32px; - content: ""; - background: url(/luci-static/resources/icons/loading.gif) no-repeat center; - background-size: 16px; -} - -/* luci */ -.hidden { - display: none; -} - -.left, -.left::before { - text-align: left !important; -} - -.right, -.right::before { - text-align: right !important; -} - -.center, -.center::before { - text-align: center !important; -} - -.top { - align-self: flex-start !important; - vertical-align: top !important; -} - -.bottom { - align-self: flex-end !important; - vertical-align: bottom !important; -} - -.inline { - display: inline; -} - -.cbi-page-actions { - padding-top: 1rem; - text-align: right; - justify-content: flex-end; -} - -.cbi-page-actions>form[method="post"] { - display: inline-block; -} - -.th[data-type="button"], -.td[data-type="button"], -.th[data-type="fvalue"], -.td[data-type="fvalue"] { - flex: 1 1 2em; - text-align: center; -} - -.ifacebadge { - display: inline-flex; - gap: .2rem; - padding: .5rem .8rem; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); - border-radius: 4px; -} - -td>.ifacebadge, -.td>.ifacebadge { - font-size: .8rem; - background-color: #f0f0f0; -} - -.ifacebadge>em, -.ifacebadge>img { - display: inline-block; - align-self: flex-start; -} - -.ifacebadge>img+img { - margin: 0 .2rem 0 0; -} - -.network-status-table { - display: flex; - flex-wrap: wrap; -} - -.network-status-table .ifacebox { - flex-grow: 1; - border-radius: 4px; - overflow: hidden; - margin: 0 1.25rem 1rem 1.25rem; -} - -.network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; - gap: 0.5em; -} - -.network-status-table .ifacebox-body>span { - flex: 10 10 auto; - height: 100%; -} - -.network-status-table .ifacebox-body>div { - display: flex; - flex-wrap: wrap; - gap: .5rem; -} - -.network-status-table .ifacebox-body .ifacebadge { - align-items: center; - flex: 1 1 auto; - min-width: 220px; - padding: .5em; - background-color: #fff; - - >span { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } -} - -/* textarea */ -.cbi-input-textarea { - font-family: monospace; - width: 100%; - font-size: 0.875rem; - min-height: 14rem; - padding: .8rem; - color: #000; -} - -#syslog { - font-size: small; - line-height: 1.25; - overflow-y: hidden; - width: 100%; - min-height: 15rem; - padding: 1rem; - resize: none; - color: #242424; - border: 0; - border-radius: 0.375rem; - background-color: #ffffff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -#syslog:focus { - outline: 0; -} - -/* config changes */ -.uci-change-list { - font-family: monospace; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #0f0; - background-color: #cfc; -} - -.uci-change-list del, -.uci-change-legend-label del { - font-style: normal; - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #f00; - background-color: #fcc; -} - -.uci-change-list var, -.uci-change-legend-label var { - font-style: normal; - display: block; - padding: 2px; - text-decoration: none; - border: thin solid #ccc; - background-color: #eee; -} - -.uci-change-list var ins, -.uci-change-list var del { - font-style: normal; - padding: 0; - white-space: pre; - border: 0; -} - -.uci-change-legend { - padding: 5px; -} - -.uci-change-legend-label { - float: left; - width: 150px; -} - -.uci-change-legend-label>ins, -.uci-change-legend-label>del, -.uci-change-legend-label>var { - display: block; - float: left; - width: 10px; - height: 10px; - margin-right: 4px; -} - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - line-height: .4; - border: 0; -} - -.uci-change-list var, -.uci-change-list del, -.uci-change-list ins { - padding: .5rem; -} - -/* other fix */ -#iwsvg, -#iwsvg2, -#bwsvg { - border: thin solid #d4d4d4 !important; -} - -#iwsvg, -[data-page="admin-status-realtime-bandwidth"] #bwsvg { - border-top: 0 !important; -} - -.ifacebox { - line-height: 1.25; - display: inline-flex; - overflow: hidden; - flex-direction: column; - border-radius: 4px; - min-width: 100px; - border-bottom: thin solid #ccc; - background-color: #f9f9f9; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 1px 2px rgba(0, 0, 0, .2); -} - -.ifacebox-head { - padding: .25em; - background: #eee; -} - -.ifacebox-head.active { - background: #5e72e4; - background: var(--primary); - - * { - color: #fff; - color: var(--white); - } - -} - -.ifacebox-body { - padding: 0.875rem 1rem; - line-height: 1.6em; -} - -.cbi-image-button { - margin-left: .5rem; -} - -.zonebadge { - display: inline-block; - padding: .2rem .5rem; - border-radius: 4px; -} - -.zonebadge .ifacebadge { - margin: .1rem .2rem; - padding: .2rem .3rem; - border: thin solid #6c6c6c; -} - -.zonebadge>input[type="text"] { - min-width: 10rem; - margin-top: .3rem; - padding: .16rem 1rem; -} - -.zonebadge>em, -.zonebadge>strong { - display: inline-block; - margin: 0 .2rem; -} - -.cbi-value-field .cbi-input-checkbox, -.cbi-value-field .cbi-input-radio { - margin-top: .1rem; -} - -.cbi-value-field>ul>li { - display: flex; -} - -.cbi-value-field>ul>li>label { - margin-top: .5rem; -} - -.cbi-value-field>ul>li .ifacebadge { - margin-top: -.5rem; - margin-left: .4rem; - background-color: #eee; -} - -.cbi-section-table-row>.cbi-value-field .cbi-dropdown { - min-width: 3rem; -} - -.cbi-section-create { - display: inline-flex; - align-items: center; - margin: 0.25rem 1.25rem; -} - -.cbi-section-create>* { - margin: .5rem 0; -} - -.cbi-section-remove { - padding: .5rem; -} - -div.cbi-value var, -td.cbi-value-field var, -.td.cbi-value-field var { - font-style: italic; - color: #0069d6; -} - -.cbi-optionals { - padding: 1rem 1rem 0 1rem; - border-top: thin solid #ccc; -} - -.cbi-dropdown-container { - position: relative; -} - -.cbi-tooltip-container, -span[data-tooltip], -span[data-tooltip] .label { - cursor: help !important; -} - -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - padding: 2px 5px; - transition: opacity .25s ease-out; - white-space: pre; - pointer-events: none; - opacity: 0; - border-radius: 3px; - background: #fff; - box-shadow: 0 0 2px #444; -} - -.cbi-tooltip-container:hover .cbi-tooltip { - left: auto; - transition: opacity .25s ease-in; - opacity: 1; -} - -.zonebadge .cbi-tooltip { - margin: -1.5rem 0 0 -.5rem; - padding: .25rem; - background: inherit; -} - -.zonebadge-empty { - color: #404040; - background: repeating-linear-gradient(45deg, rgba(204, 204, 204, .5), rgba(204, 204, 204, .5) 5px, rgba(255, 255, 255, .5) 5px, rgba(255, 255, 255, .5) 10px); -} - -.zone-forwards { - display: flex; - min-width: 10rem; -} - -.zone-forwards>* { - flex: 1 1 45%; -} - -.zone-forwards>span { - flex-basis: 10%; - padding: 0 .25rem; - text-align: center; -} - -.zone-forwards .zone-src, -.zone-forwards .zone-dest { - display: flex; - flex-direction: column; -} - -.label { - font-size: .8rem; - font-weight: bold; - padding: .3rem .8rem; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: #fff !important; - border-radius: 3px; - background-color: #bfbfbf; - text-shadow: none; -} - -label>input[type="checkbox"], -label>input[type="radio"] { - position: relative; - top: .4rem; - right: .2rem; - margin: 0; - vertical-align: bottom; -} - -label[data-index][data-depends] { - padding-right: 2em; -} - -.showSide { - display: none; -} - -.darkMask { - position: fixed; - z-index: 99; - display: none; - width: 100%; - height: 100%; - content: ""; - top: 0; - background-color: rgba(0, 0, 0, .56); - transition: all 0.2s; - - &.active { - display: block; - } -} - -/* diagnostics */ -#diag-rc-output>pre, -#command-rc-output>pre, -[data-page="admin-services-wol"] .notice code { - font-size: 1.2rem; - font-size-adjust: .35; - line-height: normal; - display: block; - overflow-y: hidden; - width: 100%; - padding: 8.5px; - white-space: pre; - color: #eee; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -[data-page="admin-network-diagnostics"] .table { - box-shadow: none; -} - -input[name="ping"], -input[name="traceroute"], -input[name="nslookup"] { - width: 80%; -} - - - -/* fix status */ -.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2), -.node-status-processes>.main .table .tr .td:nth-child(3) { - white-space: normal; -} - -/* fix system reboot */ -[data-page="admin-system-reboot"] p { - padding-left: 1.5rem; -} - -[data-page="admin-system-reboot"] .cbi-button { - background: #fb6340 !important; -} - -[data-page="admin-system-reboot"] p>span { - position: relative; - top: .1rem; - left: 1rem; -} - -[data-page="admin-vpn-passwall"] h4 { - background: transparent; -} - -/* samba */ -#cbi-samba [data-tab="template"] .cbi-value-field { - display: block; -} - -#cbi-samba [data-tab="template"] .cbi-value-title { - width: auto; - padding-bottom: .6rem; -} - -/* admin-system-admin-password */ -[data-page="admin-system-admin"] .cbi-map h2, -[data-page="admin-system-admin-password"] .cbi-map h2, -[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, -[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - margin-left: 0; - color: #32325d; - color: var(--gray-dark); -} - - -/* software */ -[data-page="admin-system-opkg"] h2 { - margin-left: 0; - color: #32325d; - color: var(--gray-dark); -} - -.controls { - margin: .5em 1rem 1em 1rem !important; -} - -.controls>*>.btn:not([aria-label$="page"]) { - flex-grow: initial !important; - margin-top: .25rem; -} - -.controls>#pager>.btn[aria-label$="page"] { - font-size: 1.4rem; - font-weight: bold; -} - -.controls>*>label { - margin-bottom: .2rem; -} - -[data-page="admin-system-opkg"] div.btn { - line-height: 3; - display: inline; - padding: .3rem .6rem; -} - -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent>.container { - margin-top: 2rem; - padding-top: .1rem; -} - -[data-page="admin-system-opkg"] #maincontent>.container { - margin: 0 1.25rem 1rem 1.25rem; - margin-bottom: 1rem; -} - -.td.version, -.td.size { - white-space: normal !important; - word-break: break-word; -} - -.cbi-tabmenu+.cbi-section { - margin-top: 0; -} - -/* admin-system-crontab*/ -[data-page="admin-system-crontab"] #view p { - margin-bottom: 1rem; -} - -/*admin-system-flash*/ - -[data-page="admin-system-flash"] { - .cbi-value { - padding: 0; - } - - .cbi-section { - .cbi-section { - margin-top: 0; - } - } - - .cbi-map-tabbed { - border-radius: 0.375rem; - } - - legend { - display: block !important; - font-size: 1.2rem; - width: 100%; - display: block; - margin-bottom: 0; - padding: 1rem 0 1rem 1.5rem; - border-bottom: 1px solid rgba(0, 0, 0, .05); - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: 0.1rem; - color: #32325d; - font-weight: bold; - } - - .cbi-section-descr { - font-weight: 600; - padding: 1rem 0 1rem 1.5rem; - color: #525f7f; - } - - .modal { - - - label>input[type="checkbox"] { - top: -0.35rem; - } - - .btn { - white-space: normal !important; - } - } -} - -/* wireless overview */ -#cbi-wireless>#wifi_assoclist_table>.tr { - box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { - right: 33px; - bottom: 33px; - left: 33px; - border-top: thin solid #ddd !important; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.table-titles { - box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { - border-bottom: thin solid #ddd; - box-shadow: 0 -1px 0 0 #ddd; -} - -#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { - width: 23rem; -} - -[data-page="admin-network-dhcp"] .cbi-value { - padding: 0; - -} - -[data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem 0 !important; -} - -/* firewall */ -#iptables { - margin: 0; -} - -.Firewall form { - margin: 2rem 2rem 0 0; - padding: 0; - box-shadow: none; -} - -#cbi-firewall-redirect table *, -#cbi-network-switch_vlan table *, -#cbi-firewall-zone table * { - font-size: small; -} - -#cbi-firewall-redirect table input[type="text"], -#cbi-network-switch_vlan table input[type="text"], -#cbi-firewall-zone table input[type="text"] { - width: 5rem; -} - -#cbi-firewall-redirect table select, -#cbi-network-switch_vlan table select, -#cbi-firewall-zone table select { - min-width: 3.5rem; -} - -#cbi-network-switch_vlan .th, -#cbi-network-switch_vlan .td { - flex-basis: 12%; -} - -#cbi-firewall-zone .table, -#cbi-network-switch_vlan .table { - display: block; -} - -#cbi-firewall-zone .td, -#cbi-network-switch_vlan .td { - width: 100%; -} - -[data-page="admin-network-firewall-custom"] #view p, -[data-page="admin-status-routes"] #view p { - padding: 0 1.5rem; - margin-bottom: 1rem; - - textarea { - padding: 1rem; - border-radius: 0.375rem; - } -} - -/* applyreboot fix */ -#applyreboot-container { - margin: 2rem; -} - -#applyreboot-section { - line-height: 300%; - margin: 2rem; -} - -/* openvpn bug fix */ -.OpenVPN a { - line-height: initial !important; -} - -/* custom commands */ -.commandbox { - width: 24% !important; - margin: 10px 0 0 10px !important; - padding: .5rem 1rem; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); -} - -.commandbox h3 { - line-height: normal !important; - overflow: hidden; - margin: 6px 0 !important; - white-space: nowrap; - text-overflow: ellipsis; -} - -.commandbox div { - left: auto !important; -} - -.commandbox code { - position: absolute; - overflow: hidden; - max-width: 60%; - margin-left: 4px; - padding: 2px 3px; - white-space: nowrap; - text-overflow: ellipsis; -} - -.commandbox code:hover { - overflow-y: auto; - max-height: 50px; - white-space: normal; -} - -.commandbox p:first-of-type { - margin-top: -6px; -} - -.commandbox p:nth-of-type(2) { - margin-top: 2px; -} - -[data-page^="admin-system-commands"] .panel-title, -[data-page^="command-cfg"] .mobile-hide, -[data-page^="command-cfg"] .showSide { - display: none; -} - -#command-rc-output .alert-message { - line-height: 1.42857143; - position: absolute; - top: 40px; - right: 32px; - max-width: 40%; - margin: 0; - animation: anim-fade-in 1.5s forwards; - word-break: break-word; - opacity: 0; -} - -@keyframes anim-fade-in { - 100% { - opacity: 1; - } -} - -/* other fix */ -input[type="checkbox"] { - appearance: none !important; - -webkit-appearance: none !important; - border: 1px solid #dee2e6; - - width: 16px !important; - height: 16px !important; - padding: 0; - cursor: pointer; - transition: all 0.2s; - margin: 1rem 0 0 0; -} - -input[type="checkbox"]:checked { - border: 1px solid #5e72e4; - border: 1px solid var(--primary); - background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; - background-color: #5e72e4; - background-color: var(--primary); - background-size: 70%; - background-repeat: no-repeat; - background-position: center; -} - -.fb-container .cbi-button { - height: auto !important; -} - -#cbi-usb_printer-printer em { - display: block; - padding: 1rem; - text-align: center; -} - -pre.command-output { - padding: 1.5rem; -} - -[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { - padding: 1.5rem !important; -} - -[data-page="admin-nlbw-backup"] form { - padding-left: 1.5rem; -} - -[data-page="admin-status-iptables"] .right { - margin-bottom: 0 !important; -} - -/* IE hacks */ -@media all and (-ms-high-contrast: none) { - .main>.main-left>.nav>.slide>.menu::before { - top: 30.25%; - } - - .main>.main-left>.nav>li:last-child::before { - top: 20%; - } - - .showSide::before { - top: -12px; - } -} - -@media screen and (max-width: 1600px) { - header>.fill>.container>#logo { - margin: 0 2.5rem 0 .5rem; - } - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - .btn:not(button), - .cbi-button { - font-size: .8rem; - } - - .label { - padding: .2rem .6rem; - } - - - .cbi-value-title { - width: 15rem; - padding-right: .6rem; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 18rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 9rem; - } - - .cbi-input-textarea { - font-size: small; - } - - .node-admin-status>.main fieldset li>a { - padding: .3rem .6rem; - } -} - -@media screen and (max-width: 1366px) { - - - header>.fill>.container { - - cursor: default; - } - - - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - - .tabs>li>a, - .cbi-tabmenu>li>a { - padding: .2rem .8rem; - } - - .panel-title { - font-size: 1.1rem; - padding-bottom: 1rem; - } - - table { - font-size: .7rem !important; - width: 100% !important; - } - - .table .cbi-input-text { - width: 100%; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 16rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 4rem; - } - - .main>.main-left>.nav>li, - .main>.main-left>.nav>li>a, - .main .main-left .nav>li>a:first-child, - .main>.main-left>.nav>.slide>.menu, - .main>.main-left>.nav>li>[data-title="Logout"] { - font-size: .9rem; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: .7rem; - } - - #modal_overlay { - top: 0rem; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { - display: block; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), - [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), - [data-page="admin-network-hosts"] .table, - [data-page="admin-network-routes"] .table { - overflow-y: visible; - } - - .commandbox { - width: 32% !important; - } - - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - - } -} - -@media screen and (max-width: 1152px) { - header>.fill>.container>#logo { - display: none; - } - - header>.fill>.container>.brand { - position: relative; - } - - html, - .main { - overflow-y: visible; - } - - .main>.loading>span { - top: 25%; - } - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - - - body:not(.logged-in) .showSide { - visibility: hidden; - width: 0; - margin: 0; - } - - .node-main-login>.main .cbi-value-title { - text-align: left; - } - - .cbi-value-title { - width: 12rem; - padding-right: 1rem; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"] { - width: 16rem; - min-width: 16rem; - } - - /*.cbi-value input[type="password"],*/ - .cbi-value input[name^="pw"], - .cbi-value input[data-update="change"]:nth-child(2) { - width: 13rem !important; - min-width: 13rem; - } - - #diag-rc-output>pre, - #command-rc-output>pre, - [data-page="admin-services-wol"] .notice code { - font-size: 1rem; - } - - .table { - display: block; - } - - .Interfaces .table { - overflow-x: hidden; - } - - #packages.table { - display: grid; - } - - .tr { - display: flex; - flex-direction: row; - flex-wrap: wrap; - } - - .Overview .table[width="100%"]>.tr { - flex-wrap: nowrap; - } - - .tr.placeholder { - border-bottom: thin solid #ddd; - } - - .tr.placeholder>.td, - #cbi-firewall .tr>.td, - #cbi-network .tr:nth-child(2)>.td, - .cbi-section #wifi_assoclist_table .tr>.td { - border-top: 0; - } - - .th, - .td { - display: inline-block; - align-self: flex-start; - flex: 2 2 10%; - text-overflow: ellipsis; - word-wrap: break-word; - } - - .td select, - .td input[type="text"] { - width: 100%; - word-wrap: normal; - } - - .td [data-dynlist]>input, - .td input.cbi-input-password { - width: calc(100% - 1.5rem); - } - - .td[data-type="button"], - .td[data-type="fvalue"] { - flex: 1 1 12.5%; - text-align: left; - } - - .th.cbi-value-field, - .td.cbi-value-field, - .th.cbi-section-table-cell, - .td.cbi-section-table-cell { - flex-basis: auto; - padding-top: 1rem; - } - - .cbi-section-table-row { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-between; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); - } - - .td.cbi-value-field, - .cbi-section-table-cell { - display: inline-block; - flex: 10 10 auto; - flex-basis: 50%; - text-align: center; - } - - .td.cbi-section-actions { - vertical-align: bottom; - } - - .tr.table-titles, - .tr.cbi-section-table-titles, - .tr.cbi-section-table-descr { - display: none; - } - - .tr[data-title]::before, - .tr.cbi-section-table-titles.named::before { - font-size: .9rem; - display: block; - flex: 1 1 100%; - border-bottom: thin solid rgba(0, 0, 0, .26); - background: #e9ecef; - } - - .td[data-title], - [data-page^="admin-status-realtime"] .td[id] { - text-align: left; - } - - .td[data-title]::before { - display: block; - } - - .cbi-button+.cbi-button { - margin-left: 0; - } - - .td.cbi-section-actions>*>*, - .td.cbi-section-actions>*>form>* { - margin: 2.1px 3px; - } - - .Firewall form { - position: static !important; - margin: 0 0 2rem 0; - padding: 2rem; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); - } - - .Firewall form input { - width: 100% !important; - margin: 0; - margin-top: 1rem; - } - - .Firewall .center, - .Firewall .center::before { - text-align: left !important; - } - - .commandbox { - width: 100% !important; - margin-left: 0 !important; - } - - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - } -} - - - - -@media screen and (max-width: 768px) { - body { - font-size: .8rem; - } - - .cbi-progressbar::after { - font-size: .6rem; - } - - - - .main-left { - position: fixed; - z-index: 100; - width: 0; - - &.active { - width: 13rem; - } - } - - .main-right { - width: 100%; - - &.active { - overflow-y: hidden; - } - } - - .darkMask.active { - display: block; - } - - .showSide { - padding: 0.1rem; - position: relative; - z-index: 99; - display: inline-block !important; - - &::before { - font-family: 'argon' !important; - font-style: normal !important; - font-weight: normal !important; - font-variant: normal !important; - text-transform: none !important; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: "\e20e"; - font-size: 1.7rem; - } - } - - - header>.fill>.container>.flex1>.brand { - display: inline-block; - } - - - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: 0.8rem; - } - - - -} - -@media screen and (max-width: 600px) { - .mobile-hide { - display: none; - } - - #maincontent>.container { - margin: 0 1rem 1rem 1rem; - } - - .cbi-value-title { - text-align: left; - } - - [data-page="admin-system-flash"] legend { - padding: 1rem 0 1rem 1rem; - - } - - [data-page="admin-system-flash"] .cbi-section-descr { - padding: 1rem 0 1rem 1rem; - - } - - [data-page="admin-system-flash"] .cbi-value { - padding: 0 1rem; - } - - [data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem 1rem !important; - } - - .cbi-dynlist p { - padding: 0.5rem 1rem; - } - - body { - overflow-x: hidden; - } - - .node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field { - width: 16rem; - } - - .node-main-login footer { - display: none; - } - - .tabs, - .cbi-tabmenu { - &::-webkit-scrollbar { - width: 0px; - height: 0px; - } - } - - .cbi-value-field, - .cbi-value-description { - display: block !important; - padding-left: 0 !important; - padding-right: 0 !important; - } - - [data-page="admin-system-admin-password"] .cbi-value-field { - display: table-cell !important; - } - - .modal.cbi-modal { - max-width: 100%; - max-height: none; - } - - .modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 100%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - margin: 5em auto; - padding: 1em; - border-radius: 3px !important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - } - - .cbi-dropdown[open]>ul.dropdown { - left: 0.2rem !important; - right: 0 !important; - margin-bottom: 1rem; - } - - .login-page .login-container footer { - display: none; - } -} - - - -@media screen and (min-width: 600px) { - ::-webkit-scrollbar { - width: 10px; - height: 10px; - } - - ::-webkit-scrollbar, - ::-webkit-scrollbar-corner { - background: transparent; - } - - ::-webkit-scrollbar-thumb { - background: #9e9e9e; - } - - ::-webkit-scrollbar-thumb:hover { - background: #757575; - } - - ::-webkit-scrollbar-thumb:active { - background: #424242; - } - - - - -} - - - -@media screen and (max-width: 480px) { - .mobile-hide { - display: none; - } - - .login-page .login-container { - margin-left: 0rem !important; - width: 100%; - - .login-form { - .form-login { - .input-group { - &::before { - color: #525461; - } - - input { - color: #525461; - border-bottom: white 1px solid; - border-bottom: var(--white) 1px solid; - border-radius: 0; - } - - } - } - } - - } - - -} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/resources/menu-argon.js b/luci-theme-argon/htdocs/luci-static/resources/menu-argon.js index cc8678f17..cc4d4b6b6 100644 --- a/luci-theme-argon/htdocs/luci-static/resources/menu-argon.js +++ b/luci-theme-argon/htdocs/luci-static/resources/menu-argon.js @@ -78,7 +78,7 @@ return baseclass.extend({ submenu = this.renderMainMenu(children[i], url + '/' + children[i].name, l), hasChildren = submenu.children.length, slideClass = hasChildren ? 'slide' : null, - menuClass = hasChildren ? 'menu' : null; + menuClass = hasChildren ? 'menu' : 'food'; if (isActive) { ul.classList.add('active'); slideClass += " active"; diff --git a/luci-theme-argon/less/cascade.less b/luci-theme-argon/less/cascade.less new file mode 100644 index 000000000..f80683639 --- /dev/null +++ b/luci-theme-argon/less/cascade.less @@ -0,0 +1,4616 @@ +// out: ../htdocs/luci-static/argon/css/cascade.css, compress: true , sourceMap: false +/** + * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template + * + * luci-theme-argon + * Copyright 2023 Jerrykuku + * + * Have a bug? Please create an issue here on GitHub! + * https://github.com/jerrykuku/luci-theme-argon/issues + * + * luci-theme-material: + * Copyright 2015 Lutty Yang + * https://github.com/LuttyYang/luci-theme-material/ + * + * Agron Theme + * https://demos.creative-tim.com/argon-dashboard/index.html + * + * Login background + * https://unsplash.com/ + * Font generate by Icomoon + * + * Licensed to the public under the Apache License 2.0 + */ + +/* + * Include base and custom css + */ +@import url("pure-min.less"); +@import url("fonts.less"); + + +:root { + --primary: #5e72e4; + --dark-primary: #483d8b; + --main-color: #09c; + --header-bg: #09c; + --header-color: #fff; + --bar-bg: #5e72e4; + --menu-bg-color: #fff; + --menu-color: #5f6368; + --menu-color-hover: #202124; + --main-menu-color: #202124; + --submenu-bg-hover: #d4d4d4; + --submenu-bg-hover-active: #09c; + --blue: #5e72e4; + --indigo: #5603ad; + --purple: #8965e0; + --pink: #f3a4b5; + --red: #f5365c; + --orange: #fb6340; + --yellow: #ffd600; + --green: #2dce89; + --teal: #11cdef; + --cyan: #2bffc6; + --white: #fff; + --gray: #8898aa; + --gray-dark: #32325d; + --light: #ced4da; + --lighter: #e9ecef; + --secondary: #f7fafc; + --success: #2dce89; + --info: #11cdef; + --warning: #fb6340; + --danger: #f5365c; + --light: #adb5bd; + --dark: #212529; + --default: #172b4d; + --white: #fff; + --neutral: #fff; + --darker: black; + --background-color: #f4f5f7; + --login-form-bg-color: rgba(244, 245, 247, 0.8); + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --blur-radius: 10px; + --blur-opacity: 0.5; + --blur-radius-dark: 10px; + --blur-opacity-dark: 0.5; + --font-family-sans-serif: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + --font-family-normal: Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif; +} + +* { + margin: 0px; + padding: 0px; + box-sizing: border-box; +} + +html, +body { + margin: 0px; + padding: 0px; + height: 100%; + font-size: 16px; + font-family: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; + font-family: var(--font-family-sans-serif); +} + +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +body { + font-size: 0.875rem; + background-color: #f4f5f7; + background-color: var(--background-color); + color: #32325d; + color: var(--gray-dark); + -webkit-tap-highlight-color: transparent; +} + + +textarea { + padding: 0.2rem; + + &:focus-visible { + outline: none; + border: 1px solid var(--primary); + } +} + +::selection { + background-color: #5e72e4; + background-color: var(--primary); + color: #ffffff; + color: var(--white); +} + +::placeholder { + color: var(--lighter); +} + +a:link, +a:visited, +a:active { + color: #5e72e4; + color: var(--primary); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +li { + list-style-type: none; +} + + +.table { + position: relative; + display: table; +} + +.tr { + display: table-row; +} + +.thead { + display: table-header-group; +} + +.tbody { + display: table-row-group; +} + +.tfoot { + display: table-footer-group; +} + +.td, +.th { + line-height: normal; + display: table-cell; + padding: .5em; + text-align: center; + vertical-align: middle; +} + +.th { + font-weight: bold; + white-space: nowrap; +} + +.tr.placeholder { + height: 4em; +} + +.tr.placeholder > .td { + line-height: 3; + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 0.4rem 0 !important; + text-align: center !important; + background: inherit; +} + +.td[width="33%"] { + padding: 1.1em 1.5rem; +} + +.table[width="33%"], +.th[width="33%"], +.td[width="33%"] { + width: 33%; +} + +.table[width="100%"], +.th[width="100%"], +.td[width="100%"] { + width: 100%; +} + +.col-1 { + flex: 1 1 30px !important; +} + +.col-2 { + flex: 2 2 60px !important; +} + +.col-3 { + flex: 3 3 90px !important; +} + +.col-4 { + flex: 4 4 120px !important; +} + +.col-5 { + flex: 5 5 150px !important; +} + +.col-6 { + flex: 6 6 180px !important; +} + +.col-7 { + flex: 7 7 210px !important; +} + +.col-8 { + flex: 8 8 240px !important; +} + +.col-9 { + flex: 9 9 270px !important; +} + +.col-10 { + flex: 10 10 300px !important; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; + +} + +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: inherit; + font-weight: normal; + line-height: 1.1 !important; + color: inherit; +} + + +select { + padding: .36rem .8rem; + color: #555; + border: thin solid #ccc; + background-color: #fff; + background-image: none; +} + +.btn, +button, +select, +input, +.cbi-dropdown { + line-height: 1.5em; + padding: .5rem .75rem; + + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: .25rem; + outline: 0; + background-image: none; + box-shadow: none; + transition: box-shadow .15s ease; +} + +select, +.cbi-dropdown { + width: inherit; + cursor: default; +} + +select:not([multiple="multiple"]):focus, +input:not(.cbi-button):focus, +.cbi-dropdown:focus { + border-color: #5e72e4; + border-color: var(--primary); + box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, .1); +} + +.cbi-dropdown, +select[multiple="multiple"] { + height: auto; +} + +pre { + overflow: auto; +} + +code { + padding: 1px 3px; + color: #101010; + border-radius: 2px; + background: #ddd; + font-family: inherit; + font-size: inherit; +} + +abbr { + cursor: help; + text-decoration: underline; + color: #5e72e4; + color: var(--primary); +} + +hr { + margin: 1rem 0; + opacity: .1; + border-color: #eee; +} + + +ul { + line-height: normal; +} + +li { + list-style-type: none; +} + +h1 { + font-size: 2rem; + padding-bottom: 10px; + border-bottom: thin solid #eee; +} + +h2 { + margin: 0 0 1rem 0; + font-size: 1.25rem; + letter-spacing: 0.1rem; + padding: 1rem 1.25rem; + color: #32325d; + border-radius: .25rem; + background: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, .03); + font-weight: bold; + +} + +h3 { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + margin: 0; + margin-bottom: 0; + padding: 0.8755rem 1.25rem; + color: #32325d; + color: var(--gray-dark); + border-radius: .25rem; + background: #fff; + font-weight: bold; +} + +h4 { + margin: 0; + padding: 0.75rem 1.25rem; + font-size: 0.875rem; + font-weight: 600; + color: #525f7f; + font-weight: bold; + + em { + padding: 0 0.5rem; + } + +} + +h5 { + font-size: 1rem; + margin: 2rem 0 0 0; + padding-bottom: 10px; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.nowrap:not(.td) { + white-space: nowrap; +} + +[disabled="disabled"] { + pointer-events: none; +} + + +/*********************** +* +* Login Page +* +***************************/ + +.login-page { + height: 100%; + + .video { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #000; + background-color: var(--darker); + overflow: hidden; + + video { + width: 100%; + height: auto; + } + } + + .volume-control { + position: fixed; + right: 1rem; + top: 1rem; + width: 1.5rem; + height: 1.5rem; + z-index: 5000; + cursor: pointer; + background-size: contain; + background-image: url(../img/volume_high.svg); + + &.mute { + background-image: url(../img/volume_off.svg); + } + } + + .main-bg { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + background-image: url(../img/blank.png); + background-repeat: no-repeat; + background-position: center; + background-size: cover; + transition: all 0.5s; + } + + .login-container { + height: 100%; + margin-left: 4.5rem; + position: absolute; + top: 0px; + display: flex; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + align-items: flex-start; + min-height: 100%; + z-index: 2; + width: 420px; + box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 35px -5px; + margin-left: 5%; + background: transparent; + + .login-form { + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: center; + position: absolute; + top: 0px; + width: 100%; + min-height: 100%; + max-width: 420px; + background-color: #fff; + background-color: var(--white); + -webkit-backdrop-filter: blur(var(--blur-radius)); + backdrop-filter: blur(var(--blur-radius)); + background-color: rgba(244, 245, 247, var(--blur-opacity)); + + .brand { + display: flex; + -webkit-box-align: center; + align-items: center; + margin: 50px auto 100px 50px; + color: #525461; + color: var(--default); + justify-content: center; + + .icon { + width: 50px; + height: auto; + margin-right: 25px; + } + + .brand-text { + font-size: 1.25rem; + font-weight: 700; + font-family: "TypoGraphica"; + + } + + &:hover { + text-decoration: none; + } + } + + .form-login { + width: 100%; + padding: 20px 50px; + box-sizing: border-box; + + .errorbox { + text-align: center; + color: #fb6340; + color: var(--warning); + padding-bottom: 2rem; + } + + .input-group { + margin-bottom: 1.25rem; + position: relative; + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #525461; + color: var(--default); + font-size: 1.5rem; + position: absolute; + z-index: 100; + left: 10px; + top: 10px; + } + + .border { + position: absolute; + width: 100%; + height: 1px; + bottom: 0; + border-bottom: 1px #5e72e4 solid; + border-bottom: 1px var(--primary) solid; + transform: scaleX(0); + transition: transform 0.3s; + } + + input { + font-size: 1rem; + line-height: 1.5em; + display: block; + width: 100%; + padding: .5rem .75rem 0.5rem 3rem; + margin: 0.825rem 0; + box-sizing: border-box; + transition: all .3s cubic-bezier(.68, -.55, .265, 1.55); + color: #525461; + color: var(--default); + border: 0; + border-radius: 0; + border-bottom: 1px solid #fff; + border-bottom: 1px solid var(--white); + background-color: transparent; + background-clip: padding-box; + box-shadow: 0 3px 2px rgba(233, 236, 239, .05); + outline: none; + + &:focus + .border { + transform: scaleX(1); + } + } + + .cbi-input-password { + margin-bottom: 2rem; + position: relative; + } + } + + .user-icon::before { + content: "\e971"; + } + + .pass-icon::before { + content: "\e910"; + + } + } + + .cbi-button-apply { + width: 100% !important; + box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 50px 0px; + font-weight: 600; + font-size: 15px; + color: #fff; + color: var(--white); + text-align: center; + width: 100%; + cursor: pointer; + min-height: 50px; + background-color: #5e72e4 !important; + background-color: var(--primary) !important; + border-radius: 6px; + outline: none; + border-width: initial; + border-style: none; + border-color: initial; + border-image: initial; + padding: 10px 0px; + margin: 30px 0px 100px; + transition: all 0.3s !important; + letter-spacing: 0.8rem; + + &:hover, + :focus { + opacity: 0.9; + } + } + } + + footer { + box-sizing: border-box; + width: 100%; + text-align: center; + line-height: 1.6rem; + display: flex; + justify-content: space-evenly; + margin-top: auto; + padding: 0px 0px 30px; + z-index: 10; + color: #525461; + color: var(--default); + position: absolute; + bottom: 0; + + .ftc { + position: absolute; + bottom: 30px; + width: 100%; + } + + .luci-link { + display: block; + } + } + } +} + + +header, +.main { + width: 100%; +} + + +footer { + font-size: .875rem; + overflow: hidden; + padding: 1rem; + text-align: right; + white-space: nowrap; + color: #aaa; +} + +footer > a { + text-decoration: none; + color: #aaa; +} + +small { + font-size: 90%; + line-height: 1.42857143; + white-space: normal; +} + +/*********************** +* +* Layout +* +***************************/ + +.main { + position: relative; + top: 0; + bottom: 0; + overflow-y: auto; + height: 100%; + display: flex; + flex-direction: row; + +} + +.main-left { + flex-shrink: 0; + width: 15rem; + height: 100%; + background-color: var(--menu-bg-color); + box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 15px -5px; + overflow-x: auto; + z-index: 100; + + + .sidenav-header { + padding: 1.5rem .5rem; + text-align: center; + + .brand { + display: block; + font-size: 1.8rem; + color: #5e72e4; + color: var(--primary); + font-family: "TypoGraphica"; + text-decoration: none; + text-align: center; + cursor: default; + margin: 0 2rem; + + .logo { + max-width: 100%; + height: auto; + } + } + } + + &::-webkit-scrollbar { + width: 5px; + height: 1px; + } + + &::-webkit-scrollbar-thumb { + background-color: #f6f9fc + } + + &::-webkit-scrollbar-track { + background-color: #fff; + } +} + +.main-right { + flex-grow: 1; + height: 100%; + transition: all 0.2s; + overflow-x: hidden; + overflow-y: auto; + display: flex; + flex-direction: column; + + & > #maincontent { + position: relative; + z-index: 50; + flex: 1; + display: flex; + flex-direction: column; + + & > .container { + margin: 0 1.25rem 1rem 1.25rem; + flex-grow: 1; + } + + .Dashboard { + color: var(--gray-dark) !important; + + h3 { + color: var(--gray-dark); + } + + p { + margin-bottom: 3px; + margin-top: 3px; + } + + hr { + border-top: 1px solid rgba(0, 0, 0, 1); + } + + .dashboard-bg { + background-color: #fff; + } + + .settings-info { + padding-top: 1em; + padding-bottom: 1em; + + p span:nth-child(2) { + max-height: 18.5px; + top: 4px; + } + + .label { + font-size: .7rem; + padding: 0.2rem 0.6rem; + } + } + } + } +} + + +header { + color: #fff; + color: var(--header-color); + padding: 0; + position: relative; + + &.bg-primary { + background-color: #5e72e4 !important; + background-color: var(--primary) !important; + } + + &::after { + content: ""; + position: absolute; + height: 2rem; + width: 100%; + background-color: #5e72e4 !important; + background-color: var(--primary) !important; + } + + .fill { + padding: 0.8rem 0; + border-bottom: 0px solid rgba(255, 255, 255, .08) !important; + display: flex; + + .container { + height: 2rem; + padding: 0 1.25rem; + display: flex; + align-items: center; + width: 100%; + + .flex1 { + flex: 1; + + .showSide { + display: none; + color: #fff; + font-size: 1.4rem; + + &:hover { + text-decoration: none; + } + } + + .brand { + font-size: 1.5rem; + color: #fff; + font-family: "TypoGraphica"; + text-decoration: none; + padding-left: 1rem; + cursor: default; + vertical-align: text-bottom; + display: none; + } + } + + + .pull-right { + float: right; + margin-top: 0rem; + display: flex; + } + } + + .status { + span { + display: inline-block; + font-size: 0.875rem; + font-weight: bold; + padding: 0.3rem 0.8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + text-shadow: none; + border-radius: 4px; + cursor: pointer; + transition: all 0.3s; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + margin: 0 0.25rem; + + &:last-child { + margin-right: 0; + } + } + + span[data-indicator="poll-status"] { + color: #fff; + + } + + span[data-style="active"] { + + background-color: var(--green); + + } + + span[data-style="inactive"] { + color: #ffffff !important; + background-color: #32325d; + + } + } + } +} + + +#xhr_poll_status { + display: flex; + margin-left: 0.5rem; + + * { + color: #fff; + } +} + +div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { + border: 0 !important; +} + +.danger { + background-color: #ff7d60 !important; +} + +.warning { + background-color: #f0e68c !important; +} + +.success { + background-color: #5cb85c !important; +} + +.notice { + background-color: #11cdef !important; + color: #fff; +} + +.error { + color: #f00; +} + +.alert, +.alert-message { + font-weight: bold; + margin-bottom: 1.25rem; + margin-left: 1.25rem; + margin-right: 1.25rem; + padding: 1rem 1.25rem; + border: 0; + border-radius: 0.25rem !important; + background-color: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + text-shadow: none; + + &.error { + background-color: #ffd600; + } + + h4 { + padding: 0.25rem 0rem; + border-radius: 4px; + background-color: #ffd600; + } + + .btn { + height: auto; + } +} + +.alert-message > h4 { + font-size: 110%; + font-weight: bold; +} + +.alert-message > * { + margin: .5rem 0; +} + +.alert-message .btn { + padding: .3rem .6rem; +} + +.container .alert, +.container .alert-message { + margin-left: 0; + margin-right: 0; + margin-top: 0rem; +} + + +/* + * Main Menu + */ + +.main { + .main-left { + transition: all 0.2s; + + .nav { + margin-top: 0.5rem; + + > li > a:first-child { + display: block; + margin: 0.1rem .5rem 0.1rem .5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .25rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; + + &.active { + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + + &::after { + transform: rotate(90deg); + color: #fff !important; + } + } + + &:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + } + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); + } + } + + li { + padding: 0.5rem 1rem; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0; + + a { + display: block; + color: #5f6368; + color: var(--menu-color); + } + + &.slide { + padding: 0; + + ul { + display: none; + overflow: hidden; + } + + &:hover { + background: none; + } + + .slide-menu { + margin: 0 0.5rem 0 2.5rem; + padding: 0rem 0.5rem; + + &.active { + display: block; + + } + + + li { + position: relative; + border-radius: 0.25rem; + margin: 0; + background: none; + list-style: none; + + a { + text-decoration: none; + padding: 0.5rem 0rem; + } + + &::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 0; + height: 2px; + background-color: #5e72e4; + background-color: var(--primary); + transition: all 0.2s; + } + + &:hover { + background: none; + + &::after { + width: 100%; + } + } + + } + + .active { + background: none; + + color: var(--menu-color); + + a { + color: var(--menu-color); + } + + &::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background-color: #5e72e4; + background-color: var(--primary); + transition: all 0.2s; + } + + &:hover { + + background: none; + + &::after { + width: 100%; + } + } + } + } + + } + + + .menu { + display: block; + margin: 0.1rem .5rem 0.1rem .5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .25rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; + + &.active { + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + + &::after { + transform: rotate(90deg); + color: #fff !important; + } + } + + &:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + } + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); + } + + &::after { + position: absolute; + right: 0.5rem; + top: 0.8rem; + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: '\e90f'; + transition: all .15s ease; + color: #ced4da; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; + } + } + + + .menu[data-title=Status]:before { + content: "\e906"; + color: #5e72e4; + color: var(--primary); + } + + .menu[data-title=System]:before { + content: "\e90a"; + color: #fb6340; + } + + .menu[data-title=Services]:before { + content: "\e909"; + color: #11cdef; + } + + .menu[data-title=NAS]:before { + content: "\e90c"; + color: #f3a4b5; + } + + .menu[data-title=VPN]:before { + content: "\e90b"; + color: #8965e0; + } + + .menu[data-title=Network]:before { + content: "\e908"; + color: #8965e0; + } + + .menu[data-title=Bandwidth_Monitor]:before { + content: "\e90d"; + color: #2dce89; + } + + .menu[data-title=Docker]:before { + content: "\e911"; + color: #6699ff; + } + + .menu[data-title=Statistics]:before { + content: "\e913"; + color: #8965e0; + } + + .menu[data-title=Control]:before { + content: "\e912"; + color: #5e72e4; + color: var(--primary); + } + + .menu[data-title=Asterisk]:before { + content: "\e914"; + color: #fb6340; + } + + a[data-title=Log_out], + .food[data-title=Log_out] { + &::before { + content: "\e907"; + color: #adb5bd; + } + } + + } + } + } +} + +.lg { + margin: 0; + padding: 0 !important; +} + +.logout { + display: block; + margin: 0.8rem .5rem 0.1rem 0.5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .25rem; + text-decoration: none; + font-size: 1rem; + transition: all 0.2s; + position: relative; +} + +.logout:before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e907"; + color: #32325d !important; +} + + +body[class*="node-"] > .main > .main-left > .nav > .slide > .menu::before { + transition: transform .1s ease-in-out; +} + +body[class*="node-"] > .main > .main-left > .nav > .slide > .menu.active::before { + transition: transform .2s ease-in-out; +} + +.main > .main-left[style*="overflow: hidden"] > .nav > .slide > .menu::before { + display: none; +} + + +.cbi-section, +.cbi-section-error, +#iptables, +.Firewall form, +#cbi-network > .cbi-section-node, +#cbi-wireless > .cbi-section-node, +#cbi-wireless > #wifi_assoclist_table, +[data-tab-title], +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent > .container { + font-family: inherit; + font-weight: normal; + font-style: normal; + line-height: normal; + min-width: inherit; + margin: 1.25rem 0; + padding: 0; + border: 0; + + border-radius: 0.25rem; + background-color: #fff; + box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .15); + + &:last-child { + margin: 0; + border: 0; + } + +} + +.cbi-modal .cbi-section, +.cbi-section .cbi-section { + padding: 0; + box-shadow: none; +} + +.cbi-modal .cbi-tabmenu { + margin-left: 0; +} + +.cbi-map:not(:first-child) { + margin-top: 1rem; +} + +.cbi-map-descr { + font-size: small; + line-height: 1.5; + padding: 0 1.25rem 1rem 1.25rem; +} + +.cbi-section { + & > .cbi-section-descr { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + + &:empty { + padding-top: 0 !important; + padding-bottom: 0rem !important; + } + } +} + +.cbi-section-descr:not(:empty) { + font-size: small; + line-height: 1.5; + padding: 0rem 1rem; +} + +.cbi-map-descr + fieldset { + margin-top: 1rem; +} + +.cbi-map-descr > abbr { + cursor: help; + text-decoration: underline; +} + +.cbi-section > legend { + display: none !important; +} + +fieldset > fieldset, +.cbi-section > .cbi-section { + margin: 0; + padding: 0; + border: 0; + box-shadow: none; +} + +.cbi-section > h3:first-child, +.panel-title { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + margin: 0; + margin-bottom: 0; + padding: 0.8755rem 1.25rem; + color: #32325d; + color: var(--gray-dark); + +} + +.cbi-section > h3:first-child, +.cbi-section > h4:first-child, +.cbi-section > p:first-child, +[data-tab-title] > h3:first-child, +[data-tab-title] > h4:first-child, +[data-tab-title] > p:first-child { + padding: 1rem 1.25rem; +} + +.cbi-section p { + padding: 1rem; +} + +.cbi-tblsection { + overflow-x: auto; +} + +table { + border-spacing: 0; + border-collapse: collapse; +} + +table, +.table { + overflow-y: hidden; + width: 100%; + font-size: 90%; +} + +.table .table-titles th { + background-color: #e9ecef; + background-color: var(--lighter); +} + +table > tbody > tr > td, +table > tbody > tr > th, +table > tfoot > tr > td, +table > tfoot > tr > th, +table > thead > tr > td, +table > thead > tr > th, +.table > .tbody > .tr > .td, +.table > .tbody > .tr > .th, +.table > .tfoot > .tr > .td, +.table > .tfoot > .tr > .th, +.table > .thead > .tr > .td, +.table > .thead > .tr > .th, +.table > .tr > .td.cbi-value-field, +.table > .tr > .th.cbi-section-table-cell { + padding: .5rem; +} + +.container > .cbi-section:first-of-type > .table[width="100%"] > .tr > .td { + padding: .6rem; +} + +.cbi-section-table-cell { + line-height: 1.1; + align-self: flex-end; + flex: 1 1 auto; +} + +tr > td, +tr > th, +.tr > .td, +.tr > .th, +.cbi-section-table-row::before, +#cbi-wireless > #wifi_assoclist_table > .tr:nth-child(2) { + border-top: thin solid #ddd; + padding: 1.1em 1.25rem; +} + +#cbi-wireless .td, +.table[width="100%"] > .tr:first-child > .td, +[data-page="admin-network-diagnostics"] .tr > .td, +.tr.table-titles > .th, +.tr.cbi-section-table-titles > .th { + border-top: 0 !important; + background-color: #f6f9fc; + padding: 1.1em 1.25rem; + line-height: 1.3rem; +} + +[data-page="admin-network-network"] { + .cbi-value-field { + .cbi-dynlist { + padding: 0 !important; + } + } + + .td > .ifacebadge > .cbi-tooltip-container { + display: flex; + + img { + vertical-align: middle; + } + } +} + +#cbi-network .tr:first-child > .td { + border-top: 0; +} + +.table[width="100%"] > .tr:first-child > .td { + margin: auto 0; +} + +.cbi-section-table-row { + margin-bottom: 1rem; + text-align: center !important; + background: #f4f4f4; +} + +.cbi-section-table-row:last-child { + margin-bottom: 0; +} + +.cbi-section-table-row > .cbi-value-field .cbi-dropdown, +.cbi-section-table-row > .cbi-value-field .cbi-input-select, +.cbi-section-table-row > .cbi-value-field .cbi-input-text, +.cbi-section-table-row > .cbi-value-field .cbi-input-password { + width: 100%; +} + +.cbi-section-table-row > .cbi-value-field .cbi-input-text, +.cbi-section-table-row > .cbi-value-field .cbi-input-password { + min-width: 80px; +} + +.cbi-section-table-row > .cbi-value-field [data-dynlist] > input, +.cbi-section-table-row > .cbi-value-field input.cbi-input-password { + width: calc(100% - 1.5rem); +} + +.cbi-section-table-row .td { + text-align: center !important; + + .cbi-checkbox { + input[type="checkbox"] { + margin: 0; + } + } +} + +.control-group { + display: inline-flex; + width: 100%; + flex-wrap: wrap; + gap: 0px; + + input { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-right-width: 0; + margin-right: 0; + } + + input + button { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin-left: 0; + border-left-width: 0; + } +} + +.control-group > * { + vertical-align: middle; +} + +div > table > tbody > tr:nth-of-type(2n), +div > .table > .tr:nth-of-type(2n) { + background-color: #f9f9f9; +} + +/* fix multiple table */ +table table, +.table .table, +.cbi-value-field table, +.cbi-value-field .table, +td > table > tbody > tr > td, +.td > .table > .tbody > .tr > .td, +.cbi-value-field > table > tbody > tr > td, +.cbi-value-field > .table > .tbody > .tr > .td { + border: 0; +} + +/* button style */ +.btn, +.cbi-button, +.item::after { + font-size: .875rem; + display: inline-block; + width: auto !important; + padding: 0.5rem .75rem; + margin-left: 5px; + margin-right: 5px; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all .2s ease-in-out; + text-align: center; + vertical-align: middle; + white-space: nowrap; + text-decoration: none; + border: 0; + border-radius: .25rem; + background-color: #f0f0f0; + background-image: none; + appearance: none; + -ms-touch-action: manipulation; + touch-action: manipulation; +} + +.btn, +.cbi-button { + &:last-child { + margin-right: 0 !important; + } + + &:first-child { + margin-left: 0 !important; + } + + &:only-child { + margin-left: 5px !important; + margin-right: 5px !important; + } +} + +.btn:not(button) ul:not(.dropdown) li { + padding: 0; +} + +.cbi-button-up, +.cbi-button-down { + display: inline-block; + min-width: 0; + padding: .2rem 1rem; + font-size: 0; + color: transparent !important; + background: url(../icon/arrow.svg) no-repeat center; + background-size: 12px 20px; +} + +.cbi-button-up { + transform: scaleY(-1); +} + +.cbi-button:not(select) { + appearance: none !important; +} + + +.btn:hover, +.btn:focus, +.btn:active, +.cbi-button:hover, +.cbi-button:focus, +.cbi-button:active, +.item:hover::after, +.item:focus::after, +.item:active::after, +.cbi-page-actions .cbi-button-apply + .cbi-button-save:hover, +.cbi-page-actions .cbi-button-apply + .cbi-button-save:focus, +.cbi-page-actions .cbi-button-apply + .cbi-button-save:active { + text-decoration: none; + outline: 0; +} + +.btn:hover, +.btn:focus, +.cbi-button:hover, +.cbi-button:focus, +.item:hover::after, +.item:focus::after { + box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 2px 2px rgba(0, 0, 0, .2); +} + +.btn:active, +.cbi-button:active, +.item:active::after { + box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23); +} + +.cbi-button-up:hover, +.cbi-button-up:focus { + box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 -2px 2px rgba(0, 0, 0, .2); +} + +.cbi-button-up:active { + box-shadow: 0 -10px 20px rgba(0, 0, 0, .19), 0 -6px 6px rgba(0, 0, 0, .23); +} + +.btn:disabled, +.cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: .5; + box-shadow: none; +} + +/* gray */ +.alert-message [class="btn"], +.modal div[class="btn"], +.cbi-button-find, +.cbi-button-link, +.cbi-button-up, +.cbi-button-down, +.cbi-button-neutral, +.cbi-button[name="zero"], +.cbi-button[name="restart"], +.cbi-button[onclick="hide_empty(this)"] { + color: #fff; + border: thin solid #8898aa; + background-color: #8898aa; +} + +/* dark blue */ +.btn.primary, +.cbi-page-actions .cbi-button-save, +.cbi-page-actions .cbi-button-apply + .cbi-button-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-positive, +.cbi-button-link, +.cbi-button[value="Enable"], +.cbi-button[value="Scan"], +.cbi-button[value^="Back"], +.cbi-button-neutral[onclick="handleConfig(event)"] { + font-weight: normal; + color: #fff !important; + border: thin solid #5e72e4; + border: thin solid var(--primary); + background-color: #5e72e4; + background-color: var(--primary);; +} + +/* light blue */ +.cbi-page-actions .cbi-button-apply, +.cbi-section-actions .cbi-button-edit, +.cbi-button-edit, +.cbi-button-apply, +.cbi-button-reload, +.cbi-button-action, +.cbi-button[value="Submit"], +.cbi-button[value="Upload"], +.cbi-button[value$="Apply"], +.cbi-button[onclick="addKey(event)"] { + font-weight: normal; + color: #fff !important; + border: thin solid #5e72e4; + border: thin solid var(--primary); + + background-color: #5e72e4; + background-color: var(--primary); +} + +/* red */ +.btn.danger, +.cbi-section-remove > .cbi-button, +.cbi-button-remove, +.cbi-button-reset, +.cbi-button-negative, +.cbi-button[value="Stop"], +.cbi-button[value="Kill"], +.cbi-button[onclick="reboot(this)"], +.cbi-button-neutral[value="Restart"] { + font-weight: normal; + color: #fff; + border: thin solid #f5365c; + border: thin solid var(--red); + background-color: #f5365c; + background-color: var(--red); +} + +/* yellow */ +.btn[value="Dismiss"], +.cbi-button[value="Terminate"], +.cbi-button[value="Reset"], +.cbi-button[value="Disabled"], +.cbi-button[onclick^="iface_reconnect"], +.cbi-button[onclick="handleReset(event)"], +.cbi-button-neutral[value="Disable"] { + font-weight: normal; + color: #fff; + border: thin solid #eea236; + background-color: #f0ad4e; +} + +/* green */ +.cbi-button-success, +.cbi-button-download { + font-weight: normal; + color: #fff; + border: thin solid #4cae4c; + background-color: #5cb85c; +} + +.cbi-page-actions .cbi-button-link:first-child { + float: left; +} + +.a-to-btn { + text-decoration: none; +} + +.cbi-value-field .cbi-button-add { + font-weight: bold; + padding: 1px 6px; + display: inline-block; + align-items: center; +} + +.tabs { + margin: 0 0 1rem 0; + padding: 0 1rem; + background-color: #FFFFFF; + border-radius: 0.25rem; + box-shadow: 0 4px 8px rgba(0, 0, 0, .03); + white-space: nowrap; + overflow-x: auto; + + &::-webkit-scrollbar { + width: 1px; + height: 5px; + } + + &::-webkit-scrollbar-thumb { + background-color: #f6f9fc + } + + &::-webkit-scrollbar-track { + background-color: #fff; + } + + li[class~="active"], + li:hover { + cursor: pointer; + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #e4e9ee; + margin-bottom: 0; + border-radius: 0; + + a { + color: #5e72e4; + color: var(--primary); + } + } + + li { + font-size: 0.875rem; + display: inline-block; + padding: 0.875rem 0rem; + border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); + margin: 0; + transition: all 0.2s; + + a { + text-decoration: none; + color: #404040; + padding: 0.5rem 0.8rem; + } + + &:hover { + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + } + } +} + + +.cbi-tabmenu { + color: white; + padding: 0.5rem 1rem 0 1rem; + white-space: nowrap; + overflow-x: auto; + + &::-webkit-scrollbar { + width: 1px; + height: 5px; + } + + &::-webkit-scrollbar-thumb { + background-color: #f6f9fc + } + + &::-webkit-scrollbar-track { + background-color: #fff; + } + + li { + background: #dce3e9; + display: inline-block; + font-size: 0.875rem; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + padding: 0.5rem 0rem; + border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); + margin: 0 0.2rem; + + a { + text-decoration: none; + color: #404040; + padding: 0.5rem 0.8rem; + } + + &:hover { + cursor: pointer; + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #e4e9ee; + margin-bottom: 0; + + a { + color: #525f7f; + } + } + } + + li[class~="cbi-tab"] { + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #e4e9ee; + margin-bottom: 0; + + a { + color: #5e72e4; + color: var(--primary); + } + } +} + +.cbi-tab-descr { + padding: 0.5rem 1.5rem; +} + +.cbi-section-node { + padding: 0; +} + +.cbi-section .cbi-section-remove:nth-of-type(2n), +.container > .cbi-section .cbi-section-node:nth-of-type(2n) { + background-color: #f9f9f9; +} + +[data-tab-title] { + overflow: hidden; + height: 0; + opacity: 0; + margin: 0; + padding: 0rem 0rem !important; + + p { + margin-left: 1rem; + margin-bottom: 1rem; + } +} + + +[data-tab-active="true"] { + overflow: visible; + height: auto; + opacity: 1; + transition: opacity .25s ease-in; + margin: inherit !important; +} + + +.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3), +.cbi-section[id] .cbi-section-node:nth-of-type(4n+4) { + background-color: #f9f9f9; +} + +.cbi-section-node-tabbed { + margin-top: 0; + padding: 0; + border: 0 solid #d4d4d4; + border-radius: 0.25rem; +} + +.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + background-color: #f9f9f9; +} + +.cbi-value-field { + display: table-cell; +} + +.cbi-value-description { + line-height: 1.25; + display: table-cell; + + abbr { + color: #32325d; + color: var(--gray-dark); + } +} + +.cbi-value-description { + font-size: small; + padding: .5rem; + opacity: .5; +} + +.cbi-value-title { + display: table-cell; + float: left; + width: 23rem; + + padding-right: 2rem; + text-align: right; + word-wrap: break-word; +} + +.cbi-value { + display: inline-block; + width: 100%; + padding: .35rem 1rem .2rem 1rem; + line-height: 2.4rem; + + &:first-child { + padding-top: 1rem; + } + + &:last-child { + padding-bottom: 1rem; + } + + ul { + line-height: 1.25; + } +} + + +.cbi-value-field .cbi-dropdown, +.cbi-value-field .cbi-input-select, +.cbi-value input[type="text"], +.cbi-value input[type="password"], +.cbi-value textarea { + min-width: 18rem; +} + +.cbi-value input[type="password"] { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + font-size: 0.875rem; + margin: .25rem 0 .25rem 0.1rem; +} + +.cbi-value input[type="password"] + .cbi-button-neutral { + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem !important; + padding: 0.5rem 0; + margin: 0.25rem 0; + font-weight: normal; + font-size: 1.2rem; + line-height: 1.5rem; + color: #fff; + outline: 0; + background-color: #8898aa; + box-shadow: none; + border: 1px solid #8898aa; + border-radius: 0.25rem; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +#cbi-firewall-zone .cbi-input-select, +#cbi-network-switch_vlan .cbi-input-select { + min-width: 11rem; +} + +#cbi-network-switch_vlan .cbi-input-text { + max-width: 3rem; +} + +.cbi-input-invalid { + color: #f5365c !important; + border-color: #f5365c !important; +} + +.cbi-section-error { + font-weight: bold; + line-height: 1.42857143; + margin: 18px; + padding: 6px; + border: thin solid #f5365c; + border-radius: 3px; + background-color: #fce6e6; +} + +.cbi-section-error ul { + margin: 0 0 0 20px; +} + +.cbi-section-error ul li { + font-weight: bold; + color: #f5365c; +} + +.td[data-title]::before { + font-weight: bold; + display: none; + padding: .25rem 0; + content: attr(data-title) ":\20"; + text-align: left; + white-space: nowrap; +} + +.tr.placeholder .td[data-title]::before { + display: none; +} + +.tr[data-title]::before, +.tr.cbi-section-table-titles.named::before { + font-weight: bold; + display: table-cell; + align-self: center; + flex: 1 1 5%; + padding: .25rem; + content: attr(data-title) "\20"; + text-align: center; + vertical-align: middle; + white-space: normal; + word-wrap: break-word; +} + +.cbi-rowstyle-1 { + background-color: #f9f9f9; +} + +.cbi-rowstyle-2 { + background-color: #eee; +} + +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down, +body:not(.Interfaces) .cbi-rowstyle-2:first-child { + background-color: #fff !important; +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; +} + +.td.cbi-section-actions { + text-align: right !important; + vertical-align: middle; +} + +.td.cbi-section-actions > * { + display: inline-flex; +} + +.td.cbi-section-actions > * > *, +.td.cbi-section-actions > * > form > * { + margin: 0 5px; + display: flex; + align-items: center; +} + +.td.cbi-section-actions > * > form { + display: inline-flex; + margin: 0; +} + +.cbi-checkbox { + margin: 0 0.25rem; +} + +/* lists */ +.cbi-dynlist { + + line-height: 1.3; + flex-direction: column; + min-height: 30px; + cursor: text; + + & > .item { + display: inline-flex; + flex-wrap: nowrap; + margin: 0.25rem 0; + position: relative; + max-width: 25rem; + pointer-events: none; + color: #8898aa; + outline: 0; + + &::after { + content: "\00D7"; + pointer-events: auto; + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem !important; + margin: 0; + font-weight: normal; + font-size: 1.2rem; + line-height: 1.5rem; + + color: #fff; + border: 1px solid #f5365c; + border-radius: 0 0.25rem 0.25rem 0; + outline: 0; + + background-color: var(--red); + background-image: none; + box-shadow: none; + box-sizing: border-box; + } + + & > span { + display: block; + padding: 0.5rem 0.75rem; + box-sizing: border-box; + min-width: 15.5rem; + width: 15.5rem; + transition: box-shadow 0.15s ease; + overflow: hidden; + text-overflow: ellipsis; + + white-space: nowrap; + word-break: break-word; + font-size: .875rem; + line-height: 24px; + + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: .25rem 0 0 .25rem; + outline: 0; + background-image: none; + box-shadow: none; + box-sizing: border-box; + } + } + + & > .add-item { + display: inline-flex; + align-items: center; + width: 100%; + min-width: 16rem; + margin: 0.25rem 0; + gap: 0; + flex-wrap: nowrap; + + input { + display: block; + padding: 0.5rem 0.75rem; + box-sizing: border-box; + min-width: 15.5rem; + width: 15.5rem; + transition: box-shadow 0.15s ease; + + white-space: nowrap; + word-break: break-word; + font-size: .875rem; + line-height: 1.5rem; + + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: .25rem 0 0 .25rem; + border-right-width: 0; + outline: 0; + background-image: none; + box-shadow: none; + } + + .cbi-button { + display: flex; + width: auto !important; + padding-left: 0.8rem; + padding-right: 0.8rem; + margin-left: 0; + align-items: center; + justify-content: center; + + font-size: 0.875rem; + line-height: 1.5rem; + + outline: 0; + background-image: none; + background-color: var(--gray); + box-shadow: none; + color: var(--white); + border-color: var(--gray); + border-radius: 0.25rem; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + .cbi-button-add { + width: 2.5rem !important; + padding: 0.5rem 0 !important; + + font-weight: normal; + font-size: 1.2rem; + + color: #fff; + background-color: var(--primary); + border: 1px solid var(--primary); + } + + + &:not([ondrop]) { + & > input { + overflow: hidden; + min-width: 15.5rem; + width: 15.5rem; + white-space: nowrap; + text-overflow: ellipsis; + } + } + } +} + + +.cbi-dynlist[name="sshkeys"] > .item { + max-width: none; +} + + +.cbi-dynlist > .cbi-dynlist > .add-item[ondrop] > input { + min-width: 13rem; +} + +.cbi-dynlist, +.cbi-dropdown { + position: relative; + display: inline-flex; + + min-height: 2.1875rem; +} + +.cbi-dropdown[placeholder*="select"] { + max-width: 25rem; + height: auto; + margin-top: -3px; +} + +.cbi-dropdown > ul { + display: flex; + overflow-x: hidden; + overflow-y: auto; + width: 100%; + margin: 0 !important; + padding: 0; + list-style: none; + outline: 0; +} + + +.cbi-dropdown > ul.preview { + display: none; + +} + +.cbi-button-apply > ul.preview { + display: none; + + li { + color: #fff; + } + +} + +.cbi-button-apply > ul:first-child { + li { + color: #fff; + } + +} + +.cbi-dropdown > .open { + flex-basis: 15px; +} + +.cbi-dropdown > .open, +.cbi-dropdown > .more { + font-size: 1rem; + font-weight: 900; + line-height: 1em; + display: flex; + flex-direction: column; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + padding: 0 .25em; + cursor: default; + text-align: center; + outline: 0; +} + +.cbi-dropdown > .more, +.cbi-dropdown > ul > li[placeholder] { + font-weight: bold; + display: none; + color: #777; + text-shadow: none; +} + +.cbi-dropdown > ul > li { + display: none; + overflow: hidden; + align-items: center; + align-self: center; + flex-grow: 1; + flex-shrink: 1; + min-height: 20px; + padding: 0.125rem .25em; + white-space: nowrap; + text-overflow: ellipsis; + +} + +.cbi-dropdown > ul > li .hide-open { + display: initial; +} + +.cbi-dropdown > ul > li .hide-close { + display: none; +} + +.cbi-dropdown > ul > li[display]:not([display="0"]) { + border-left: thin solid #ccc; +} + +.cbi-dropdown[empty] > ul { + max-width: 1px; +} + +.cbi-dropdown > ul > li > form { + display: none; + margin: 0; + padding: 0; + pointer-events: none; +} + +.cbi-dropdown > ul > li img { + margin-right: .25em; + vertical-align: middle; +} + +.cbi-dropdown > ul > li > form > input[type="checkbox"] { + height: auto; + margin: 0; +} + +.cbi-dropdown > ul > li input[type="text"] { + height: 20px; +} + +.cbi-dropdown[open] > ul.dropdown { + position: absolute; + z-index: 1100; + display: block; + width: auto; + min-width: 100%; + max-width: none; + max-height: 200px !important; + border: 0 solid #918e8c; + background: #ffffff; + box-shadow: 0 0 4px #918e8c; + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + color: var(--main-menu-color); + margin-left: -0 !important; + left: 0; + + li { + color: #000; + } +} + + +.cbi-dropdown > ul > li[display], +.cbi-dropdown[open] > ul.preview, +.cbi-dropdown[open] > ul.dropdown > li, +.cbi-dropdown[multiple] > ul > li > label, +.cbi-dropdown[multiple][open] > ul.dropdown > li, +.cbi-dropdown[multiple][more] > .more, +.cbi-dropdown[multiple][empty] > .more { + display: flex; + align-items: center; + flex-grow: 1; + +} + +.cbi-dropdown[empty] > ul > li, +.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], +.cbi-dropdown[multiple][open] > ul.dropdown > li > form { + display: block; +} + +.cbi-dropdown[open] > ul.dropdown > li .hide-open { + display: none; +} + +.cbi-dropdown[open] > ul.dropdown > li .hide-close { + display: initial; +} + +.cbi-dropdown[open] > ul.dropdown > li { + border-bottom: thin solid #ccc; + padding: 0.5rem 0.8rem; +} + +.cbi-dropdown[open] > ul.dropdown > li label { + margin-left: 0.5rem; +} + +.cbi-dropdown[open] > ul.dropdown > li[selected] { + background: #e4e9ee; +} + +.cbi-dropdown[open] > ul.dropdown > li.focus { + background: #e4e9ee; + outline: none; +} + +.cbi-dropdown[open] > ul.dropdown > li:last-child { + margin-bottom: 0; + border-bottom: 0; +} + +.cbi-dropdown[open] > ul.dropdown > li[unselectable] { + opacity: .7; +} + +.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child { + width: 100%; +} + +.cbi-dropdown[disabled] { + pointer-events: none; + opacity: .6; +} + +.cbi-dropdown .zonebadge { + width: 100%; +} + +.cbi-dropdown[open] .zonebadge { + width: auto; +} + +/* progressbar */ +.cbi-progressbar { + position: relative; + display: flex; + width: 100%; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.5rem; + height: 1rem; + overflow: hidden; + + & > div { + display: block; + position: absolute; + height: 100%; + background-color: var(--bar-bg); + border-radius: 0.5rem; + transition: width 0.3s; + } + + &::after { + content: attr(title); + position: absolute; + font-size: 0.75rem; + color: var(--bs-heading-color); + width: 100%; + height: 100%; + text-align: center; + line-height: 1rem; + z-index: 2; + } +} + +#modal_overlay { + position: fixed; + z-index: 900; + top: 0; + right: 10000px; + bottom: 0; + left: -10000px; + overflow-y: scroll; + transition: opacity .125s ease-in; + opacity: 0; + background: rgba(0, 0, 0, .7); + -webkit-overflow-scrolling: touch; +} + +.modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 90%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + margin: 5em auto; + padding: 1rem; + border-radius: 0.25rem !important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + + & > * { + line-height: normal; + flex-basis: 100%; + margin-bottom: .5em; + max-width: 100%; + } + + & > pre, + & > textarea { + font-size: 1rem; + font-size-adjust: .35; + overflow: auto; + margin-bottom: .5em; + padding: 8.5px; + cursor: auto; + white-space: pre-wrap; + color: #eee; + outline: 0; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + } + + & > h4 { + display: block; + flex-grow: 1; + max-width: none; + padding: 1rem; + margin: -1rem -1rem 0 -1rem; + font-size: 1rem; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); + border-radius: 0.25rem 0 0 0.25rem; + } + + h5 { + margin-top: 1rem; + font-weight: 600; + } + + label > input[type="checkbox"] { + top: 0; + } + + ul { + margin-left: 2.2em; + + &:not(.cbi-tabmenu) { + margin-top: 1rem; + } + + li { + list-style-type: square; + color: #808080; + } + } + + p { + word-break: break-word; + margin-top: 1rem; + } + + .label { + font-size: .6rem; + font-weight: normal; + padding: .1rem .3rem; + padding-bottom: 0; + cursor: default; + border-radius: 0; + } + + .label.warning { + background-color: #f0ad4e !important; + } + + .btn { + padding: 0.45rem 0.8rem; + } + + &.cbi-modal { + max-width: 90%; + max-height: none; + } +} + + +body.modal-overlay-active { + overflow: hidden; + height: 100vh; +} + +body.modal-overlay-active #modal_overlay { + right: 0; + left: 0; + opacity: 1; +} + + +.spinning { + position: relative; + padding-left: 32px !important; +} + +.spinning::before { + position: absolute; + top: 0; + bottom: 0; + + left: .2em; + width: 32px; + content: ""; + background: url(/luci-static/resources/icons/loading.gif) no-repeat center; + background-size: 16px; +} + +#view { + border-radius: 0.25rem; + overflow: hidden; + + & > .spinning { + position: fixed; + top: 50%; + left: 50%; + transform: translateX(-50%) translateY(-50%); + padding: 1rem; + border-radius: 0.5rem; + background: #ffffff; + box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .15); + } +} + +/* luci */ +.hidden { + display: none; +} + +.left, +.left::before { + text-align: left !important; +} + +.right, +.right::before { + text-align: right !important; +} + +.center, +.center::before { + text-align: center !important; +} + +.top { + align-self: flex-start !important; + vertical-align: top !important; +} + +.bottom { + align-self: flex-end !important; + vertical-align: bottom !important; +} + +.inline { + display: inline; +} + +.cbi-page-actions { + padding: 1rem; + text-align: right; + justify-content: flex-end; +} + +.cbi-page-actions > form[method="post"] { + display: inline-block; +} + +.th[data-type="button"], +.td[data-type="button"], +.th[data-type="fvalue"], +.td[data-type="fvalue"] { + flex: 1 1 2em; + text-align: center; +} + +.ifacebadge { + display: inline-flex; + align-items: center; + gap: .2rem; + padding: .25rem .8rem; + + background: #eee; + border-radius: 4px; +} + +td > .ifacebadge, +.td > .ifacebadge { + font-size: .875rem; + background-color: #f0f0f0; +} + +.ifacebadge > em, +.ifacebadge > img { + display: inline-block; + margin: 0 0.75rem; +} + +.ifacebadge > img + img { + margin: 0 .2rem 0 0; +} + +.network-status-table { + display: flex; + flex-wrap: wrap; + + .ifacebox { + flex-grow: 1; + border-radius: .25rem; + overflow: hidden; + margin: 1rem; + } + + .ifacebox-body { + display: flex; + flex-direction: column; + height: 100%; + gap: 0.5em; + + > span { + flex: 10 10 auto; + } + + > div { + display: flex; + flex-wrap: wrap; + gap: .5rem; + height: 100%; + } + + .ifacebadge { + align-items: center; + flex: 1 1 auto; + min-width: 220px; + padding: .5em; + background-color: #fff; + + > span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + } +} + +/* textarea */ +.cbi-input-textarea { + font-family: inherit; + width: 100%; + font-size: 0.875rem; + min-height: 14rem; + padding: .8rem; + color: #8898aa; + border-radius: 0.25rem; + border: 1px solid #dee2e6; + min-width: 16rem; +} + +#content_syslog { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); +} + +#syslog { + font-size: small; + font-family: 'Google Sans'; + line-height: 1.25; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + padding: 1rem; + resize: none; + color: #242424; + border: 0; + border-radius: 0.25rem; + background-color: #ffffff; + +} + +#syslog:focus { + outline: 0; +} + +/* config changes */ +.uci-change-list { + font-family: inherit; + overflow: scroll; + width: 100%; + display: flex; + flex-direction: column; + flex-wrap: wrap; +} + +.uci-change-list ins, +.uci-change-legend-label ins { + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #0f0; + background-color: #cfc; +} + +.uci-change-list del, +.uci-change-legend-label del { + font-style: normal; + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #f00; + background-color: #fcc; +} + +.uci-change-list var, +.uci-change-legend-label var { + font-style: normal; + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #ccc; + background-color: #eee; +} + +.uci-change-list var ins, +.uci-change-list var del { + font-style: normal; + padding: 0; + white-space: pre; + border: 0; +} + +.uci-change-legend { + padding: 5px; +} + +.uci-change-legend-label { + float: left; + width: 150px; +} + +.uci-change-legend-label > ins, +.uci-change-legend-label > del, +.uci-change-legend-label > var { + display: block; + float: left; + width: 10px; + height: 10px; + margin-right: 4px; +} + +.uci-change-legend-label var ins, +.uci-change-legend-label var del { + line-height: .4; + border: 0; +} + +.uci-change-list var, +.uci-change-list del, +.uci-change-list ins { + padding: .5rem; +} + +.uci-dialog { + .cbi-section { + padding: 0.5rem; + + .uci-change-legend { + line-height: 15px; + padding: 10px 20px 0 20px; + + .uci-change-legend-label { + padding: 0; + margin: 0; + position: relative; + float: none; + display: inline-block; + width: 25%; + + > ins, + > del { + width: 14px; + height: 14px; + } + + > var { + position: relative; + width: 14px; + height: 14px; + + ins, + del { + position: absolute; + left: 2px; + top: 2px; + right: 2px; + bottom: 2px; + } + } + } + } + + .uci-change-list { + overflow: auto; + } + + .uci-change-list + .right { + .btn { + color: #333; + } + + .cbi-dropdown ul:not(.dropdown) { + li { + color: #fff; + } + } + + .cbi-button { + padding: .45rem .8rem; + } + } + } +} + +/* other fix */ +#iwsvg, +#iwsvg2, +#bwsvg { + border: thin solid #d4d4d4 !important; +} + +#iwsvg, +[data-page="admin-status-realtime-bandwidth"] #bwsvg { + border-top: 0 !important; +} + +.ifacebox { + line-height: 1.25; + display: inline-flex; + overflow: hidden; + flex-direction: column; + border-radius: 4px; + min-width: 100px; + background-color: #f9f9f9; + // border-bottom: thin solid #ccc; + // box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 1px 2px rgba(0, 0, 0, .2); +} + +.ifacebox-head { + padding: .25em; + background: #eee; +} + +.ifacebox-head.active { + background: #5e72e4; + background: var(--primary); + + * { + color: #fff; + color: var(--white); + } + +} + +.ifacebox-body { + padding: 0.875rem 1rem; + line-height: 1.6em; +} + +.cbi-image-button { + margin-left: .5rem; +} + +.zonebadge { + display: inline-block; + padding: .2rem .5rem; + border-radius: 4px; +} + +.zonebadge .ifacebadge { + margin: .1rem .2rem; + padding: .2rem .3rem; + border: thin solid #6c6c6c; +} + +.zonebadge > input[type="text"] { + min-width: 10rem; + margin-top: .3rem; + padding: .16rem 1rem; +} + +.zonebadge > em, +.zonebadge > strong { + display: inline-block; + margin: 0 .2rem; +} + +.cbi-value-field .cbi-input-checkbox, +.cbi-value-field .cbi-input-radio { + margin-top: .1rem; +} + +.cbi-value-field > ul > li { + display: flex; +} + +.cbi-value-field > ul > li > label { + margin-top: .5rem; +} + +.cbi-value-field > ul > li .ifacebadge { + margin-top: -.5rem; + margin-left: .4rem; + background-color: #eee; +} + +.cbi-section-table-row > .cbi-value-field .cbi-dropdown { + min-width: 3rem; +} + +.cbi-section-create { + display: inline-flex; + align-items: center; + padding: .5rem 1rem; +} + + +.cbi-section-remove { + padding: .5rem 1rem; +} + +div.cbi-value var, +td.cbi-value-field var, +.td.cbi-value-field var { + font-style: italic; + color: #0069d6; +} + +.cbi-optionals { + padding: 1rem 1rem 0 1rem; + border-top: thin solid #ccc; +} + +.cbi-dropdown-container { + position: relative; +} + +.cbi-tooltip-container, +span[data-tooltip], +span[data-tooltip] .label { + cursor: help !important; +} + +.cbi-tooltip { + position: absolute; + z-index: 1000; + left: -1000px; + padding: 2px 5px; + transition: opacity .25s ease-out; + white-space: pre; + pointer-events: none; + opacity: 0; + border-radius: 3px; + background: #fff; + box-shadow: 0 0 2px #444; +} + +.cbi-tooltip-container:hover .cbi-tooltip { + left: auto; + transition: opacity .25s ease-in; + opacity: 1; +} + +.zonebadge .cbi-tooltip { + margin: -1.5rem 0 0 -.5rem; + padding: .25rem; + background: inherit; +} + +.zonebadge-empty { + color: #404040; + background: repeating-linear-gradient(45deg, rgba(204, 204, 204, .5), rgba(204, 204, 204, .5) 5px, rgba(255, 255, 255, .5) 5px, rgba(255, 255, 255, .5) 10px); +} + +.zone-forwards { + display: flex; + min-width: 10rem; +} + +.zone-forwards > * { + flex: 1 1 45%; +} + +.zone-forwards > span { + flex-basis: 10%; + padding: 0 .25rem; + text-align: center; +} + +.zone-forwards .zone-src, +.zone-forwards .zone-dest { + display: flex; + flex-direction: column; +} + +.label { + font-size: .875rem; + font-weight: bold; + padding: .3rem .8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: #fff !important; + border-radius: 3px; + background-color: #bfbfbf; + text-shadow: none; +} + +label > input[type="checkbox"], +label > input[type="radio"] { + position: relative; + top: .4rem; + right: .2rem; + margin: 0; + vertical-align: bottom; +} + +label[data-index][data-depends] { + padding-right: 2em; +} + +.showSide { + display: none; +} + +.darkMask { + position: fixed; + z-index: 99; + display: none; + width: 100%; + height: 100%; + content: ""; + top: 0; + background-color: rgba(0, 0, 0, .56); + transition: all 0.2s; + + &.active { + display: block; + } +} + +/* diagnostics */ +#diag-rc-output > pre, +#command-rc-output > pre, +[data-page="admin-services-wol"] .notice code { + font-size: 1.2rem; + font-size-adjust: .35; + line-height: normal; + display: block; + overflow-y: hidden; + width: 100%; + padding: 8.5px; + white-space: pre; + color: #eee; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +[data-page="admin-network-diagnostics"] { + .table { + box-shadow: none; + } + + .cbi-section { + padding: 1rem; + font-family: monospace; + background: #fff !important; + } + + textarea { + background: transparent; + border-radius: 0.25rem; + font-family: 'Google Sans' !important; + color: #8898aa; + border: 1px solid #dee2e6; + padding: 0.5rem; + } + + .tr > .td { + background-color: #fff !important; + border-bottom: 1px solid #dee2e6 !important; + } +} + +input[name="ping"], +input[name="traceroute"], +input[name="nslookup"] { + width: 80%; +} + +/* fix status */ +.node-status-overview > .main fieldset:nth-child(4) .td:nth-child(2), +.node-status-processes > .main .table .tr .td:nth-child(3) { + white-space: normal; +} + +div[style*="display:grid;grid-template-columns:repeat"] { + display: flex !important; + justify-content: space-evenly !important; + padding-bottom: 1rem; + flex-wrap: wrap; + font-family: 'Google Sans'; + + .ifacebox { + text-align: center; + flex-basis: 100px; + + .ifacebox-body { + font-size: 0.7rem; + padding: 0.875rem; + + .cbi-tooltip-container { + font-size: inherit !important; + } + } + } +} + +@media screen and (max-width: 484px) { + div[style*="display:grid;grid-template-columns:repeat"] { + .ifacebox { + flex-basis: 80px; + + .ifacebox-body { + padding: 0.875rem 0.5rem; + font-size: 0.6rem; + } + } + } +} + +[data-page="admin-system-attendedsysupgrade"] #view .cbi-button { + margin-left: 0 !important; + margin-top: 1rem !important; +} + +/* fix system reboot */ +[data-page="admin-system-reboot"] { + p { + padding-left: 1.5rem; + } + + p > span { + position: relative; + top: .1rem; + left: 1rem; + } + + .cbi-button { + background: #fb6340 !important; + border-color: #fb6340 !important; + margin-left: 0 !important; + } + + #view > h2:first-child + p { + margin-bottom: 1rem; + } +} + +[data-page="admin-system-poweroff"] { + .container { + h2 + br + p { + margin-bottom: 1rem; + padding-left: 1.5rem; + } + } +} + +[data-page="admin-vpn-passwall"] h4 { + background: transparent; +} + +[data-page="admin-system-filetransfer"] { + + #cbi-upload { + margin-top: 0; + } + + .cbi-section-table { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03); + } + +} + +/* samba */ +#cbi-samba [data-tab="template"] { + .cbi-value-field { + display: block; + } + + .cbi-value-title { + width: auto; + padding-bottom: .6rem; + } +} + +/* admin-system-admin-password */ +[data-page="admin-system-admin"] .cbi-map h2, +[data-page="admin-system-admin-password"] .cbi-map h2, +[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, +[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { + margin-left: 0; + color: #32325d; + color: var(--gray-dark); +} + +/* admin-system-admin-sshkeys */ +[data-page="admin-system-admin-sshkeys"] { + .cbi-dynlist { + margin-left: 1rem; + } +} + +/* software */ +[data-page="admin-system-opkg"] h2 { + margin-left: 0; + color: #32325d; + color: var(--gray-dark); +} + +[data-page="admin-system-opkg"] input[name="filter_i18n"] { + top: 2px; + vertical-align: text-top; +} + +.controls { + margin: .5em 1rem 1em 1rem !important; +} + +.controls > * > .btn:not([aria-label$="page"]) { + flex-grow: initial !important; + margin-top: .25rem; +} + +.controls > #pager > .btn[aria-label$="page"] { + font-size: 1.4rem; + font-weight: bold; +} + +.controls > * > label { + margin-bottom: .2rem; +} + +[data-page="admin-system-opkg"] div.btn { + line-height: 3; + display: inline; + padding: .3rem .6rem; +} + +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent > .container { + margin-top: 1rem; + padding-top: .01rem; +} + +[data-page="admin-system-opkg"] #maincontent > .container { + margin: 0 1.25rem 1rem 1.25rem; + margin-bottom: 1rem; +} + +.td.version, +.td.size { + white-space: normal !important; + word-break: break-word; +} + +.cbi-tabmenu + .cbi-section { + margin-top: 0; +} + +/* admin-system-system */ +[data-page="admin-system-system"] { + .control-group { + margin-top: 0.5rem; + } + + .cbi-dynlist { + margin: 0.25rem 0; + } +} + +/* admin-system-startup */ +[data-page="admin-system-startup"] { + [data-tab-title] p { + margin-left: 0; + margin-bottom: 0; + position: relative; + } + + textarea { + line-height: 1.25; + overflow-y: auto; + width: 100%; + min-height: 15rem; + padding: 1rem; + resize: none; + color: #8898aa; + border-radius: 0.25rem; + border: 1px solid #dee2e6; + + &:focus-visible { + outline: none; + box-shadow: none; + border: 1px solid var(--primary); + } + } +} + +/* admin-system-crontab*/ +[data-page="admin-system-crontab"] { + #view p { + margin-bottom: 1rem; + + &:last-child { + margin-bottom: 0; + } + + textarea { + line-height: 1.25; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + padding: 1rem; + resize: none; + background-color: transparent; + background: var(--white); + outline: none; + color: #8898aa; + border-radius: 0.25rem; + border: 1px solid #dee2e6; + } + } +} + +/*admin-system-attendedsysupgrade-configuration*/ +[data-page="admin-system-attendedsysupgrade-configuration"] { + .cbi-map { + .cbi-map-descr { + padding-bottom: 0; + } + } +} + +/*admin-system-flash*/ + +[data-page="admin-system-flash"] { + .cbi-value { + padding: 0 1rem; + } + + .cbi-section { + .cbi-section { + margin-top: 0; + } + } + + .cbi-map-tabbed { + border-radius: 0.25rem; + } + + .cbi-section-node { + padding-top: 0; + padding-bottom: 0.5rem; + } + + legend { + font-size: 1.2rem; + width: 100%; + display: block; + border-bottom: 1px solid rgba(0, 0, 0, .05); + line-height: 1.5; + margin-bottom: 0; + letter-spacing: 0.1rem; + color: #32325d; + font-weight: bold; + padding: 1rem 0 1rem 1rem; + } + + .cbi-section-descr { + font-weight: 600; + padding: 1rem 0 1rem 1rem; + color: #525f7f; + + } + + .cbi-page-actions { + padding: 0rem 1rem 1rem 0rem; + } + + .modal { + + + label > input[type="checkbox"] { + top: -0.25rem; + } + + .btn { + white-space: normal !important; + } + } + + .modal label > input[type="checkbox"] { + vertical-align: text-top; + top: auto; + } +} + +/* wireless overview */ +#cbi-wireless > #wifi_assoclist_table > .tr { + box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; +} + +#cbi-wireless > #wifi_assoclist_table > .tr.placeholder > .td { + right: 33px; + bottom: 33px; + left: 33px; + border-top: thin solid #ddd !important; +} + +#cbi-wireless > #wifi_assoclist_table > .tr.table-titles { + box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; +} + +#cbi-wireless > #wifi_assoclist_table > .tr.table-titles > .th { + border-bottom: thin solid #ddd; + box-shadow: 0 -1px 0 0 #ddd; +} + +#wifi_assoclist_table > .tr > .td[data-title="RX Rate / TX Rate"] { + width: 23rem; +} + +[data-page="admin-network-dhcp"] { + .cbi-value { + padding: 0; + + } + + [data-tab-active="true"] { + padding: 1rem 1rem !important; + } +} + +/* firewall */ +#iptables { + margin: 0; +} + +.Firewall form { + margin: 2rem 2rem 0 0; + padding: 0; + box-shadow: none; +} + +#cbi-firewall-redirect table *, +#cbi-network-switch_vlan table *, +#cbi-firewall-zone table * { + font-size: small; +} + +#cbi-firewall-redirect table input[type="text"], +#cbi-network-switch_vlan table input[type="text"], +#cbi-firewall-zone table input[type="text"] { + width: 5rem; +} + +#cbi-firewall-redirect table select, +#cbi-network-switch_vlan table select, +#cbi-firewall-zone table select { + min-width: 3.5rem; +} + +#cbi-network-switch_vlan .th, +#cbi-network-switch_vlan .td { + flex-basis: 12%; +} + +#cbi-firewall-zone .table, +#cbi-network-switch_vlan .table { + display: block; +} + +#cbi-firewall-zone .td, +#cbi-network-switch_vlan .td { + width: 100%; +} + +[data-page="admin-network-firewall-custom"], +[data-page="admin-status-routes"] { + #view { + p { + padding: 0 1.5rem; + margin-bottom: 1rem; + + textarea { + padding: 1rem; + border-radius: 0.25rem; + } + } + + & > h3 { + border-radius: 0.25rem 0.25rem 0 0; + } + } + +} + +/* applyreboot fix */ +#applyreboot-container { + margin: 2rem; +} + +#applyreboot-section { + line-height: 300%; + margin: 2rem; +} + +/* openvpn bug fix */ +.OpenVPN a { + line-height: initial !important; +} + +/* custom commands */ +.commandbox { + width: 24% !important; + margin: 10px 0 0 10px !important; + padding: .5rem 1rem; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); +} + +.commandbox h3 { + line-height: normal !important; + overflow: hidden; + margin: 6px 0 !important; + white-space: nowrap; + text-overflow: ellipsis; +} + +.commandbox div { + left: auto !important; +} + +.commandbox code { + position: absolute; + overflow: hidden; + max-width: 60%; + margin-left: 4px; + padding: 2px 3px; + white-space: nowrap; + text-overflow: ellipsis; +} + +.commandbox code:hover { + overflow-y: auto; + max-height: 50px; + white-space: normal; +} + +.commandbox p:first-of-type { + margin-top: -6px; +} + +.commandbox p:nth-of-type(2) { + margin-top: 2px; +} + +[data-page^="admin-system-commands"] .panel-title, +[data-page^="command-cfg"] .mobile-hide, +[data-page^="command-cfg"] .showSide { + display: none; +} + +#command-rc-output .alert-message { + line-height: 1.42857143; + position: absolute; + top: 40px; + right: 32px; + max-width: 40%; + margin: 0; + animation: anim-fade-in 1.5s forwards; + word-break: break-word; + opacity: 0; +} + +@keyframes anim-fade-in { + 100% { + opacity: 1; + } +} + +/* other fix */ +input[type="checkbox"] { + appearance: none !important; + -webkit-appearance: none !important; + border: 1px solid var(--primary); + + width: 16px !important; + height: 16px !important; + padding: 0; + cursor: pointer; + transition: all 0.2s; + margin: 0.75rem 0 0 0; +} + +input[type="checkbox"]:checked { + border: 1px solid #5e72e4; + border: 1px solid var(--primary); + background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; + background-color: #5e72e4; + background-color: var(--primary); + background-size: 70%; + background-repeat: no-repeat; + background-position: center; +} + +.fb-container .cbi-button { + height: auto !important; +} + +#cbi-usb_printer-printer em { + display: block; + padding: 1rem; + text-align: center; +} + +pre.command-output { + padding: 1.5rem; +} + +[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { + padding: 1.5rem !important; +} + +[data-page="admin-nlbw-backup"] form { + padding-left: 1.5rem; +} + +[data-page="admin-status-iptables"] .right { + margin-bottom: 0 !important; +} + +[data-page="admin-services-ttyd"] .container { + display: flex; + flex-direction: column; +} + +[data-page="admin-services-ttyd"] #view { + flex: 1; +} + +[data-page="admin-services-ttyd"] #view iframe { + height: 100%; +} + +[data-page="admin-system-fileassistant"] { + .fb-container .panel-title { + padding: .5rem .75rem !important; + } + + .cbi-section.fb-container { + padding: 0.5rem; + } + + .fb-container .panel-container { + border-bottom-color: #dee2e6; + } +} + +[data-page^="admin-services-openclash"] { + .cbi-tabmenu > li { + border-right: none !important; + margin: 0 0.4rem 0 0 !important; + + &:last-child { + margin-right: 0 !important; + } + } + + #tab-content .dom { + padding: 0 1rem 1rem 1rem; + } + + .cbi-input-file { + padding: 0.2813rem; + box-sizing: content-box; + width: 15rem !important; + } + + [id="container.openclash.config.debug"] fieldset { + border: none !important; + padding: 1rem !important; + } + + #diag-rc-output > pre, + #dns-rc-output > pre { + font-size: 0.875rem; + color: #8898aa; + border: 1px solid #dee2e6; + background-color: transparent; + border-radius: 0.25rem; + font-family: 'Google Sans' !important; + box-shadow: none; + } + + #debug-rc-output > textarea { + font-family: 'Google Sans' !important; + } + + .CodeMirror { + font-size: inherit; + font-family: 'Google Sans' !important; + } + + .cbi-button-up, .cbi-button-down { + padding: 0.8rem 1.5rem; + background-color: #f1f1f1; + font-size: 0; + } + + select#CORE_VERSION, + select#RELEASE_BRANCH { + width: auto; + } + + [id="container.openclash.config.version_update"] { + table tr:nth-of-type(n+1) { + + } + } +} + +/* IE hacks */ +@media all and (-ms-high-contrast: none) { + .main > .main-left > .nav > .slide > .menu::before { + top: 30.25%; + } + + .main > .main-left > .nav > li:last-child::before { + top: 20%; + } + + .showSide::before { + top: -12px; + } +} + +@media screen and (max-width: 1600px) { + header > .fill > .container > #logo { + margin: 0 2.5rem 0 .5rem; + } + + .main-left { + width: calc(0% + 13rem); + } + + + .btn:not(button), + .label { + padding: .5rem .75rem; + } + + + .cbi-value-title { + width: 15rem; + padding-right: .6rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"], + .cbi-value textarea { + min-width: 18rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 9rem; + } + + .cbi-input-textarea { + font-size: small; + } + + .node-admin-status > .main fieldset li > a { + padding: .3rem .6rem; + } +} + +@media screen and (max-width: 1366px) { + + + header > .fill > .container { + + cursor: default; + } + + + .main-left { + width: calc(0% + 13rem); + } + + + .tabs > li > a, + .cbi-tabmenu > li > a { + padding: .2rem .8rem; + } + + .panel-title { + font-size: 1.1rem; + padding-bottom: 1rem; + } + + table { + font-size: .875rem !important; + width: 100% !important; + } + + .table .cbi-input-text { + width: 100%; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 16rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 5.5rem; + } + + .main > .main-left > .nav > li, + .main > .main-left > .nav > li > a, + .main .main-left .nav > li > a:first-child, + .main > .main-left > .nav > .slide > .menu, + .main > .main-left > .nav > li > [data-title="Log_out"] { + font-size: .9rem; + } + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: .875rem; + } + + #modal_overlay { + top: 0rem; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { + display: block; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), + [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), + [data-page="admin-network-hosts"] .table, + [data-page="admin-network-routes"] .table { + overflow-y: visible; + } + + .commandbox { + width: 32% !important; + } + + .btn:not(button), + .cbi-button { + font-size: 0.875rem; + + } +} + +@media screen and (max-width: 1152px) { + header > .fill > .container > #logo { + display: none; + } + + header > .fill > .container > .brand { + position: relative; + } + + html, + .main { + overflow-y: visible; + } + + .main > .loading > span { + top: 25%; + } + + .main-left { + width: calc(0% + 13rem); + } + + + body:not(.logged-in) .showSide { + visibility: hidden; + width: 0; + margin: 0; + } + + .node-main-login > .main .cbi-value-title { + text-align: left; + } + + .cbi-value-title { + width: 12rem; + padding-right: 1rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"] { + width: 16rem; + min-width: 16rem; + } + + /*.cbi-value input[type="password"],*/ + .cbi-value input[name^="pw"], + .cbi-value input[data-update="change"]:nth-child(2) { + width: 13rem !important; + min-width: 13rem; + } + + #diag-rc-output > pre, + #command-rc-output > pre, + [data-page="admin-services-wol"] .notice code { + font-size: 1rem; + } + + .table { + display: block; + } + + .Interfaces .table { + overflow-x: hidden; + } + + #packages.table { + display: grid; + } + + .tr { + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + + .Overview .table[width="100%"] > .tr { + flex-wrap: nowrap; + } + + .tr.placeholder { + border-bottom: thin solid #ddd; + } + + .tr.placeholder > .td, + #cbi-firewall .tr > .td, + #cbi-network .tr:nth-child(2) > .td, + .cbi-section #wifi_assoclist_table .tr > .td { + border-top: 0; + } + + .th, + .td { + display: inline-block; + align-self: flex-start; + flex: 2 2 10%; + text-overflow: ellipsis; + word-wrap: break-word; + } + + .td select, + .td input[type="text"] { + width: 100%; + word-wrap: normal; + } + + .td [data-dynlist] > input, + .td input.cbi-input-password { + width: calc(100% - 1.5rem); + } + + .td[data-type="button"], + .td[data-type="fvalue"] { + flex: 1 1 12.5%; + text-align: left; + } + + .th.cbi-value-field, + .td.cbi-value-field, + .th.cbi-section-table-cell, + .td.cbi-section-table-cell { + flex-basis: auto; + padding-top: 1rem; + } + + .cbi-section-table-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + } + + .td.cbi-value-field, + .cbi-section-table-cell { + display: inline-block; + flex: 10 10 auto; + flex-basis: 50%; + text-align: center; + } + + .td.cbi-section-actions { + vertical-align: bottom; + } + + .tr.table-titles, + .tr.cbi-section-table-titles, + .tr.cbi-section-table-descr { + display: none; + } + + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-size: .9rem; + display: block; + flex: 1 1 100%; + border-bottom: thin solid rgba(0, 0, 0, .26); + background: #e9ecef; + } + + .td[data-title], + [data-page^="admin-status-realtime"] .td[id] { + text-align: left; + } + + .td[data-title]::before { + display: block; + } + + .cbi-button + .cbi-button { + margin-left: 0; + } + + .td.cbi-section-actions > * > *, + .td.cbi-section-actions > * > form > * { + margin: 2.1px 3px; + } + + .Firewall form { + position: static !important; + margin: 0 0 2rem 0; + padding: 2rem; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + } + + .Firewall form input { + width: 100% !important; + margin: 0; + margin-top: 1rem; + } + + .Firewall .center, + .Firewall .center::before { + text-align: left !important; + } + + .commandbox { + width: 100% !important; + margin-left: 0 !important; + } + + .btn:not(button), + .cbi-button { + font-size: 0.875rem; + } +} + + +@media screen and (max-width: 768px) { + body { + font-size: .875rem; + } + + .cbi-progressbar::after { + font-size: .6rem; + } + + + .main-left { + position: fixed; + z-index: 100; + width: 0; + + &.active { + width: 13rem; + } + } + + .main-right { + width: 100%; + + &.active { + overflow-y: hidden; + } + } + + .darkMask.active { + display: block; + } + + .showSide { + padding: 0.1rem; + position: relative; + z-index: 99; + display: inline-block !important; + + &::before { + font-family: 'argon' !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\e20e"; + font-size: 1.7rem; + } + } + + + header > .fill > .container > .flex1 > .brand { + display: inline-block; + } + + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: 0.875rem; + } + + +} + +@media screen and (max-width: 600px) { + .mobile-hide { + display: none; + } + + #maincontent > .container { + margin: 0 1rem 1rem 1rem; + } + + .cbi-value-title { + text-align: left; + } + + .cbi-dynlist p { + padding: 0.5rem 1rem; + } + + body { + overflow-x: hidden; + } + + .node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field { + width: 16rem; + } + + .node-main-login footer { + display: none; + } + + .tabs, + .cbi-tabmenu { + &::-webkit-scrollbar { + width: 0px; + height: 0px; + } + } + + .cbi-value-field, + .cbi-value-description { + display: block !important; + padding-left: 0 !important; + padding-right: 0 !important; + } + + [data-page="admin-system-admin-password"] .cbi-value-field { + display: table-cell !important; + } + + .modal.cbi-modal { + max-width: 100%; + max-height: none; + } + + .modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 100%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + margin: 5em auto; + padding: 1em; + border-radius: 3px !important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + } + + .cbi-dropdown[open] > ul.dropdown { + margin-bottom: 1rem; + } + + .login-page .login-container footer { + display: none; + } +} + + +@media screen and (min-width: 600px) { + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + ::-webkit-scrollbar, + ::-webkit-scrollbar-corner { + background: transparent; + } + + ::-webkit-scrollbar-thumb { + background: var(--primary); + border-radius: 10px; + } + + ::-webkit-scrollbar-thumb:hover { + background: var(--primary); + } + + ::-webkit-scrollbar-thumb:active { + background: var(--primary); + } +} + + +@media screen and (max-width: 480px) { + .mobile-hide { + display: none; + } + + .login-page .login-container { + margin-left: 0rem !important; + width: 100%; + + .login-form { + .form-login { + .input-group { + &::before { + color: #525461; + } + + input { + color: #525461; + border-bottom: white 1px solid; + border-bottom: var(--white) 1px solid; + border-radius: 0; + } + + } + } + } + + } + + +} diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/dark.less b/luci-theme-argon/less/dark.less similarity index 53% rename from luci-theme-argon/htdocs/luci-static/argon/less/dark.less rename to luci-theme-argon/less/dark.less index 1e0568ad6..0b666b359 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/less/dark.less +++ b/luci-theme-argon/less/dark.less @@ -1,830 +1,1154 @@ -// compress: true , sourceMap: false -/** - * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template - * - * luci-theme-argon - * Copyright 2020 Jerryk - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-bootstrap: - * Copyright 2008 Steven Barth - * Copyright 2008 Jo-Philipp Wich - * Copyright 2012 David Menting - * - * MUI: - * https://github.com/muicss/mui - * - * luci-theme-material: - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * - * Licensed to the public under the Apache License 2.0 - */ - -body { - background: #1e1e1e; - color: #cccccc; -} - -.login-page .login-container { - - .login-form { - background-color: #1e1e1e; - -webkit-backdrop-filter: blur(var(--blur-radius-dark)); - backdrop-filter: blur(var(--blur-radius-dark)); - background-color: rgba(0, 0, 0, var(--blur-opacity-dark)); - - .brand { - color: #adb5bd; - } - - .form-login { - .input-group { - &::before { - color: #adb5bd; - } - - input { - background-color: transparent !important; - color: #adb5bd; - border-bottom: #adb5bd 1px solid !important; - border-radius: 0 !important; - border-top: none !important; - border-left: none !important; - border-right: none !important; - box-shadow: none; - } - - } - - .cbi-button-apply { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - - &:hover, - &:focus { - opacity: 0.9; - } - } - } - } - -} - -header::after { - background-color: #1e1e1e !important; -} - - -.main { - .main-left { - - background-color: #333333 !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .15); - - .sidenav-header .brand { - color: #ccc; - } - - .nav { - .slide { - .slide-menu { - .active { - a { - color: #cccccc; - - &::after { - background-color: #cccccc !important; - } - } - } - - li { - a { - color: #cccccc; - } - - a:hover { - background: none !important; - } - } - } - - .menu.active { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - color: #cccccc !important; - - a::after { - background-color: #cccccc !important; - } - } - } - - li { - a { - color: #cccccc !important; - } - - a:hover { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - color: #cccccc !important; - } - } - } - - - &::-webkit-scrollbar-thumb { - background-color: #252526 !important; - } - - &::-webkit-scrollbar-track { - background-color: #333; - } - } - - .main-right { - background-color: #1e1e1e; - } -} - -h2 { - color: #ccc; - background: #333333; -} - -h3 { - color: #ccc; - border-bottom: 0; - background: #333333; -} - -a:-webkit-any-link { - color: -webkit-link; - cursor: pointer; - color: #483d8b; - color: var(--dark-primary); -} - - -input:-webkit-autofill { - background-color: #3c3c3c !important; -} - -.cbi-value-field .cbi-input-apply, -.cbi-button-apply, -.cbi-button-edit { - color: #fff !important; - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; -} - - -.cbi-section em { - color: #ccc; -} - -header.bg-primary { - background-color: #1e1e1e !important; -} - -.cbi-map-descr { - color: #ccc; -} - -.cbi-section { - background: none; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) -} - -.panel-title { - color: #ccc; - background-color: #333333; - border-bottom: 0px; -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tr:nth-of-type(2n) { - background-color: #252526; -} - -table>tbody>tr>td, -table>tfoot>tr>td, -table>thead>tr>td { - color: #ccc; -} - -fieldset>table>tbody>tr:nth-of-type(2n) { - background-color: #252526; -} - -table>tbody>tr>td, -table>tfoot>tr>td, -table>thead>tr>td { - border-top: 1px solid #252526; -} - -#swaptotal>div>div, -#swapfree>div>div, -#memfree>div>div, -#membuff>div>div, -#conns>div>div, -#memtotal>div>div { - background-color: #32325d !important; -} - -#swaptotal>div>div>div>small, -#swapfree>div>div>div>small, -#memfree>div>div>div>small, -#membuff>div>div>div>small, -#conns>div>div>div>small, -#memtotal>div>div>div>small { - - color: #ccc !important; -} - -.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last { - line-height: 1.8em; - - div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] { - border: 1px solid #999999 !important; - background-color: transparent !important; - - div { - background-color: #32325d !important; - } - } - -} - -table>tbody>tr>th, -table>tfoot>tr>th, -table>thead>tr>th { - - background-color: #252526; - border-bottom: black 1px solid !important; -} - -tr>td, -tr>th, -.tr>.td, -.tr>.th, -.cbi-section-table-row::before, -#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { - border-top: 0; -} - -.cbi-rowstyle-2 { - background-color: #1e1e1e; -} - -.cbi-rowstyle-1 { - background-color: #252526; -} - -.cbi-rowstyle-2 .cbi-button-up, -.cbi-rowstyle-2 .cbi-button-down, -body:not(.Interfaces) .cbi-rowstyle-2:first-child { - background-color: rgb(102, 102, 102) !important; -} - -.cbi-section>h3:first-child, -.panel-title, -h3 { - color: #ccc; - border-bottom: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} - -h4 { - background-color: #1e1e1f; -} - -.cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - margin: 6px 0; - border: thin solid #999; - background: transparent; - border-radius: 0.2rem; - overflow: hidden; - - div { - background-color: #32325d !important; - } -} - -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - background-color: #1e1e1f; -} - -.cbi-button { - color: #ccc !important; - background-color: #483d8b; - background-color: var(--dark-primary); -} - -.cbi-section-node { - background: none; - border-radius: 0 0 .375rem .375rem; - padding: 0rem; -} - -abbr { - color: #5e72e4; -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tbody>.tr:nth-of-type(2n) { - background-color: #252526; -} - -#content_syslog { - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) -} - -#syslog { - color: #ccc; - background-color: #1e1e1e; -} - -#iwsvg, -#iwsvg2, -#bwsvg { - overflow: hidden; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - background-color: #1e1e1e !important; -} - -.tabs { - background-color: #252526; -} - -.tabs>li[class~="active"]>a { - color: #ccc; -} - -.tabs>li[class~="active"], -.tabs>li:hover { - border-bottom: 0.18751rem solid #483d8b; - border-bottom: 0.18751rem solid var(--dark-primary); - color: #ccc; - background-color: #181819; -} - -.cbi-tabmenu>li>a, -.tabs>li>a { - color: #ccc; - - &:hover { - color: #ccc; - } -} - -.cbi-tabmenu>li { - background: #2d2d2d; -} - -.cbi-tabmenu li[class~="cbi-tab"] a { - color: #ccc; -} - -.cbi-tabmenu>li:hover { - color: #ccc; - background: #2d2d2d; -} - -.cbi-tabmenu>li[class~="cbi-tab"] { - background-color: #181819; -} - -.cbi-tabcontainer>.cbi-value:nth-of-type(2n) { - background-color: #252526; -} - -.cbi-value-title { - color: #ccc; -} - -select, -input { - color: #ccc; - background-color: transparent !important; - border: 1px solid #252526; - box-shadow: none; -} - -select:not([multiple="multiple"]):focus, -input:focus { - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; - outline: 0; - -} - -select { - background-color: #1e1e1e !important; -} - -#cbi-dropbear h2, -#cbi-dropbear .cbi-map-descr, -#cbi-dropbear .cbi-map-descr abbr, -#cbi-rc h2, -#cbi-rc .cbi-map-descr, -#cbi-distfeedconf h2, -#cbi-distfeedconf .cbi-map-descr, -#cbi-customfeedconf h2, -#cbi-customfeedconf .cbi-map-descr, -#cbi-download h2, -#cbi-filelist h2 { - color: #ccc !important; -} - -.cbi-value-field>ul>li .ifacebadge { - background-color: #3c3c3c; -} - -.cbi-section-descr { - color: #ccc; -} - -.cbi-input-textarea { - background-color: #1e1e1e; - color: #ccc; -} - - - -.cbi-section-remove:nth-of-type(2n), -.cbi-section-node:nth-of-type(2n) { - background-color: #1e1e1e; -} - -.node-system-packages>.main table tr td:nth-last-child(1) { - color: #ccc; - -} - -.cbi-section-node .cbi-value { - padding: 1rem 1rem 0.3rem 1rem; -} - -.ifacebox { - background-color: none; - border: 1px solid #1e1e1e; -} - -.ifacebox-head { - color: #666; -} - -.ifacebox-body { - background-color: #333; -} - -.zonebadge strong { - color: #333; -} - -.zonebadge>.ifacebadge { - background-color: #3c3c3c; -} - -div.cbi-value var, -td.cbi-value-field var { - color: #5e72e4; -} - -#diag-rc-output>pre { - color: #ccc; - background-color: #1e1e1e; -} - -.node-services-vssr .block { - background-color: #3c3c3c !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); -} - -.node-services-vssr .block h4 { - color: #ccc !important; -} - -.node-services-vssr .status-bar { - color: #ccc; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - background-color: #1e1e1e; -} - -.node-services-vssr .cbi-section-table-row { - color: #ccc; - background-color: #3c3c3c !important; - box-shadow: 0 0 5px 0 rgba(0, 0, 0, .35) -} - -.node-services-vssr .cbi-section-table-row.fast { - background: #483d8b !important; - background: var(--dark-primary) !important; - color: #fff; -} - -.node-services-vssr .ssr-button { - color: #ccc; - -} - -.node-services-vssr .incon:nth-child(2) { - border-right: #1e1e1e 1px solid; -} - -#xhr_poll_status>.label.success { - color: #ccc !important; - - background-color: darkolivegreen !important; -} - -.notice { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; -} - -.cbi-input-find, -.cbi-input-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-find, -.cbi-input-reload, -.cbi-button-reload { - color: #fff !important; - background: darkolivegreen !important; - border-color: darkolivegreen !important; -} - -.cbi-button-reset, -.cbi-input-remove { - color: #fff !important; - background-color: darkorange !important; - border-color: darkorange !important; -} - -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit.important, -.cbi-button-apply.important, -.cbi-button-reload.important, -.cbi-button-action.important { - border: 1px #483d8b solid !important; - border: 1px var(--dark-primary) solid !important; -} - -.btn[value="Dismiss"], -.cbi-button[value="Terminate"], -.cbi-button[value="Reset"], -.cbi-button[value="Disabled"], -.cbi-button[onclick^="iface_reconnect"], -.cbi-button[onclick="handleReset(event)"], -.cbi-button-neutral[value="Disable"] { - font-weight: normal; - color: #fff; - border: thin solid darkorange !important; - background-color: darkorange !important; -} - -fieldset[id^="cbi-apply-"] { - background-color: #333333; -} - -#detail-bubble>div { - border: 1px solid #ccc; - border-radius: 2px; - padding: 5px; - background: #252525; -} - -.ifacebox-head.active { - background-color: #32325d !important; -} - -header .fill .status span[data-style="active"] { - color: #ccc !important; - background-color: darkolivegreen !important; -} - -#cbi-wireless .td, -#cbi-network .tr:first-child>.td, -.table[width="100%"]>.tr:first-child>.td, -[data-page="admin-network-diagnostics"] .tr>.td, -.tr.table-titles>.th, -.tr.cbi-section-table-titles>.th { - background-color: #252526; - border-bottom: black 1px solid !important; - -} - -.network-status-table .ifacebox-body .ifacebadge { - background-color: #252526; - border-bottom: 0; - box-shadow: none; -} - -td>.ifacebadge, -.td>.ifacebadge { - - background-color: #483d8b; - background-color: var(--dark-primary); - border: 0; -} - -.btn.danger, -.cbi-section-remove>.cbi-button, -.cbi-button-remove, -.cbi-button-reset, -.cbi-button-negative, -.cbi-button[value="Stop"], -.cbi-button[value="Kill"], -.cbi-button[onclick="reboot(this)"], -.cbi-button-neutral[value="Restart"] { - border: thin solid darkorange !important; - background-color: darkorange !important; -} - -.cbi-section, -.cbi-section-error, -#iptables, -.Firewall form, -#cbi-network>.cbi-section-node, -#cbi-wireless>.cbi-section-node, -#cbi-wireless>#wifi_assoclist_table, -[data-tab-title], -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), -[data-page="admin-system-opkg"] #maincontent>.container { - background: #1e1e1e !important; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); -} - -div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - background: transparent !important; -} - -[data-page="admin-system-admin"] .cbi-map h2, -[data-page="admin-system-admin-password"] .cbi-map h2, -[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, -[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { - color: #ccc; -} - -[data-page="admin-system-flash"] { - .modal { - label>input[type="checkbox"] { - top: -0.35rem; - } - - .btn { - white-space: normal !important; - background-color: darkseagreen; - } - - .alert-message { - background-color: transparent !important; - } - - .danger { - border: thin solid darkorange !important; - background-color: darkorange !important; - } - } -} - -.cbi-value input[type="password"]+.cbi-button-neutral { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; -} - -.btn, -button, -select, -input, -.cbi-dropdown { - border: 1px solid #3c3c3c !important; -} - - -.cbi-dropdown .preview { - color: #ccc; -} - -.cbi-section-table-row { - background-color: #1e1e1e !important; -} - -.modal { - background-color: #1e1e1e; -} - -.cbi-button-positive { - color: #fff !important; - background-color: darkolivegreen !important; -} - -[data-page="admin-system-flash"] legend { - color: #ccc; -} - -.logout:before { - color: #adb5bd !important; -} - -.cbi-dropdown[open] { - border-color: #483d8b !important; - border-color: var(--dark-primary) !important; -} - -.cbi-dropdown[open]>ul.dropdown { - background: #252526 !important; - color: #ccc !important; - box-shadow: none; - border: 1px solid #3c3c3c !important; - - -} - -.cbi-dropdown[open]>ul.dropdown li { - color: #ccc; - border-bottom: 1px solid #3c3c3c !important; -} - -.cbi-dropdown[open]>ul.dropdown>li[selected] { - background-color: #483d8b !important; - background-color: var(--dark-primary) !important; - border-bottom: 1px solid #3c3c3c !important; -} - -.cbi-dropdown[open]>ul.dropdown>li.focus { - background: #483d8b; - background: var(--dark-primary); - outline: none; -} - -.ifacebadge { - background-color: #333333; -} - -.cbi-dynlist>.item>span { - border: 1px solid #3c3c3c !important; -} - -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-action, -.cbi-button[value="Submit"], -.cbi-button[value="Upload"], -.cbi-button[value$="Apply"], -.cbi-button[onclick="addKey(event)"] { - background: #483d8b !important; - background: var(--dark-primary) !important; -} - -.btn.primary, -.cbi-page-actions .cbi-button-save, -.cbi-page-actions .cbi-button-apply+.cbi-button-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-positive, -.cbi-button-link, -.cbi-button[value="Enable"], -.cbi-button[value="Scan"], -.cbi-button[value^="Back"], -.cbi-button-neutral[onclick="handleConfig(event)"] { - background: #483d8b; - background: var(--dark-primary); -} - -[data-page="admin-system-opkg"] h2 { - color: #ccc !important; -} - - - - -@media screen and (max-width: 480px) { - .node-status-iptables>.main div>.cbi-map>form { - background-color: #1e1e1e; - box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); - } - - -} +// out: ../htdocs/luci-static/argon/css/dark.css, compress: true , sourceMap: false +/** + * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template + * + * luci-theme-argon + * Copyright 2023 Jerryk + * + * Have a bug? Please create an issue here on GitHub! + * https://github.com/jerrykuku/luci-theme-argon/issues + * + * luci-theme-bootstrap: + * Copyright 2008 Steven Barth + * Copyright 2008 Jo-Philipp Wich + * Copyright 2012 David Menting + * + * MUI: + * https://github.com/muicss/mui + * + * luci-theme-material: + * https://github.com/LuttyYang/luci-theme-material/ + * + * Agron Theme + * https://demos.creative-tim.com/argon-dashboard/index.html + * + * Login background + * https://unsplash.com/ + * + * Licensed to the public under the Apache License 2.0 + */ + + +body { + background: #1e1e1e; + color: #cccccc; +} + +.login-page .login-container { + + .login-form { + background-color: #1e1e1e; + -webkit-backdrop-filter: blur(var(--blur-radius-dark)); + backdrop-filter: blur(var(--blur-radius-dark)); + background-color: rgba(0, 0, 0, var(--blur-opacity-dark)); + + .brand { + color: #adb5bd; + } + + .form-login { + .input-group { + &::before { + color: #adb5bd; + } + + input { + background-color: transparent !important; + color: #adb5bd; + border-bottom: #adb5bd 1px solid !important; + border-radius: 0 !important; + border-top: none !important; + border-left: none !important; + border-right: none !important; + box-shadow: none; + } + + } + + .cbi-button-apply { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + + &:hover, + &:focus { + opacity: 0.9; + } + } + } + } + +} + +header::after { + background-color: #1e1e1e !important; +} + + +.main { + .main-left { + + background-color: #333333 !important; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .15); + + .sidenav-header .brand { + color: #cccccc; + } + + .nav { + .slide { + .slide-menu { + .active { + a { + color: #cccccc; + + &::after { + background-color: #cccccc !important; + } + } + + &::after { + background-color: var(--dark-primary) !important; + } + } + + li { + a { + color: #cccccc; + } + + a:hover { + background: none !important; + } + + &::after { + background-color: var(--dark-primary) !important; + } + } + } + + .menu.active { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + color: #ffffff !important; + + a::after { + background-color: #ffffff !important; + } + } + } + + li { + a { + color: #cccccc !important; + } + + a:hover { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + color: #ffffff !important; + } + + } + } + + + &::-webkit-scrollbar-thumb { + background-color: #252526 !important; + } + + &::-webkit-scrollbar-track { + background-color: #333; + } + } + + .main-right { + background-color: #1e1e1e; + } +} + +h2 { + color: #ccc; + background: #333333; +} + +h3 { + color: #ccc; + border-bottom: 0; + background: #333333; +} + +h4 { + color: #8C6900; +} + +abbr { + color: var(--dark-primary) !important; +} + +a:link, a:visited, a:active { + color: #a5b2ff; +} + + +input:-webkit-autofill { + background-color: #3c3c3c !important; +} + +#channel_graph { + background-color: transparent !important; +} + +.cbi-value-field .cbi-input-apply, +.cbi-button-apply, +.cbi-button-edit { + color: #fff !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; +} + + +.cbi-section em { + color: #ccc; +} + +header.bg-primary { + background-color: #1e1e1e !important; +} + +.cbi-map-descr { + color: #ccc; +} + +.cbi-section { + background: none; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) +} + +.panel-title { + color: #ccc; + background-color: #333333; +} + +div > table > tbody > tr:nth-of-type(2n), +div > .table > .tr:nth-of-type(2n) { + background-color: #252526; +} + +table > tbody > tr > td, +table > tfoot > tr > td, +table > thead > tr > td { + color: #cccccc; +} + +fieldset > table > tbody > tr:nth-of-type(2n) { + background-color: #252526; +} + +table > tbody > tr > td, +table > tfoot > tr > td, +table > thead > tr > td { + border-top: 1px solid #252526; +} + +#swaptotal > div > div, +#swapfree > div > div, +#memfree > div > div, +#membuff > div > div, +#conns > div > div, +#memtotal > div > div { + background-color: var(--dark-primary) !important; +} + +#swaptotal > div > div > div > small, +#swapfree > div > div > div > small, +#memfree > div > div > div > small, +#membuff > div > div > div > small, +#conns > div > div > div > small, +#memtotal > div > div > div > small { + color: #ccc !important; +} + +.node-system-packages > .main .cbi-section-node:first-child .cbi-value-last { + line-height: 1.8em; + + div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] { + border: 1px solid #999999 !important; + background-color: transparent !important; + + div { + background-color: #ba8b00 !important; + } + } + +} + +table > tbody > tr > th, +table > tfoot > tr > th, +table > thead > tr > th { + background-color: #252526; + border-bottom: black 1px solid !important; +} + +tr > td, +tr > th, +.tr > .td, +.tr > .th, +.cbi-section-table-row::before, +#cbi-wireless > #wifi_assoclist_table > .tr:nth-child(2) { + border-top: 0; +} + +.cbi-rowstyle-2 { + background-color: #1e1e1e; +} + +.cbi-rowstyle-1 { + background-color: #252526; +} + +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down, +body:not(.Interfaces) .cbi-rowstyle-2:first-child { + background-color: rgb(102, 102, 102) !important; +} + +.cbi-section > h3:first-child, +.panel-title, +h3 { + color: #ccc; +} + +h4 { + background-color: #1e1e1f; +} + +.cbi-progressbar { + background: #282a2c; + + div { + background-color: var(--dark-primary) !important; + } +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + background-color: #1e1e1f; +} + +.cbi-button { + color: #ffffff !important; + background-color: #483d8b; + background-color: var(--dark-primary); +} + +.cbi-section-node { + background: none; +} + +abbr { + color: #5e72e4; +} + +div > table > tbody > tr:nth-of-type(2n), +div > .table > .tbody > .tr:nth-of-type(2n) { + background-color: #252526; +} + +#content_syslog { + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) +} + +#syslog { + color: #ccc; + background-color: #1e1e1e; +} + +#iwsvg, +#iwsvg2, +#bwsvg { + overflow: hidden; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); + background-color: #1e1e1e !important; +} + +.tabs { + background-color: #252526; + + li[class~="active"], + li:hover { + cursor: pointer; + color: #ccc !important; + + a { + color: #ccc !important; + } + } +} + +.tabs > li[class~="active"] > a { + color: #ccc; +} + +.tabs > li[class~="active"], +.tabs > li:hover { + border-bottom: 0.18751rem solid #483d8b; + border-bottom: 0.18751rem solid var(--dark-primary); + color: var(--dark-primary) !important; + background-color: #181819; +} + +.cbi-tabmenu > li > a, +.tabs > li > a { + color: #ccc; + + &:hover { + color: #ccc; + } +} + +.cbi-tabmenu > li { + background: #2d2d2d; +} + +.cbi-tabmenu li[class~="cbi-tab"] a { + color: #ccc; +} + +.cbi-tabmenu > li:hover { + color: #ccc; + background: #2d2d2d; + border-bottom: 0.18751rem solid var(--dark-primary) !important; +} + +.cbi-tabmenu > li[class~="cbi-tab"] { + background-color: #181819; + border-bottom: 0.18751rem solid var(--dark-primary) !important; +} + +.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + background-color: #252526; +} + +.cbi-value-title { + color: #ccc; +} + +select, +input { + color: #ccc; + background-color: transparent !important; + border: 1px solid #252526; + box-shadow: none; +} + + +select:not([multiple="multiple"]):focus, +input:focus { + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; + outline: 0; + +} + +select:not([multiple="multiple"]):focus, +input:not(.cbi-button):focus, +.cbi-dropdown:focus { + border-color: #5e72e4; + border-color: var(--dark-primary) !important; +} + +select { + background-color: #1e1e1e !important; +} + +#cbi-dropbear h2, +#cbi-dropbear .cbi-map-descr, +#cbi-dropbear .cbi-map-descr abbr, +#cbi-rc h2, +#cbi-rc .cbi-map-descr, +#cbi-distfeedconf h2, +#cbi-distfeedconf .cbi-map-descr, +#cbi-customfeedconf h2, +#cbi-customfeedconf .cbi-map-descr, +#cbi-download h2, +#cbi-filelist h2 { + color: #ccc !important; +} + +.cbi-value-field > ul > li .ifacebadge { + background-color: #3c3c3c; +} + +.cbi-section-descr { + color: #ccc; +} + +.cbi-input-textarea { + background-color: #1e1e1e; + color: #ccc; + border: 1px solid #3c3c3c !important; +} + +textarea { + &:focus-visible { + border: 1px solid var(--dark-primary); + } +} + + +.cbi-section-remove:nth-of-type(2n), +.cbi-section-node:nth-of-type(2n) { + background-color: #1e1e1e; +} + +.node-system-packages > .main table tr td:nth-last-child(1) { + color: #ccc; + +} + +.cbi-tooltip { + background-color: var(--primary); + color: #fff; +} + +.ifacebox { + background-color: transparent !important; + border: 1px solid #1e1e1e; +} + +.ifacebox-head { + color: #ccc; + background: #666; +} + +.ifacebox-body { + background-color: #333; +} + +.zonebadge strong { + color: #333; +} + +.zonebadge > .ifacebadge { + background-color: #3c3c3c; +} + +div.cbi-value var, +td.cbi-value-field var { + color: #5e72e4; +} + +#diag-rc-output > pre { + color: #ccc; + background-color: #1e1e1e; +} + +.node-services-vssr .block { + background-color: #3c3c3c !important; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); +} + +.node-services-vssr .block h4 { + color: #ccc !important; +} + +.node-services-vssr .status-bar { + color: #ccc; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); + background-color: #1e1e1e; +} + +.node-services-vssr .cbi-section-table-row { + color: #ccc; + background-color: #3c3c3c !important; + box-shadow: 0 0 5px 0 rgba(0, 0, 0, .35) +} + +.node-services-vssr .cbi-section-table-row.fast { + background: #483d8b !important; + background: var(--dark-primary) !important; + color: #fff; +} + +.node-services-vssr .ssr-button { + color: #ccc; + +} + +.node-services-vssr .incon:nth-child(2) { + border-right: #1e1e1e 1px solid; +} + +#xhr_poll_status > .label.success { + color: #ccc !important; + + background-color: darkolivegreen !important; +} + +.notice { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; +} + +.cbi-input-find, +.cbi-input-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-find, +.cbi-input-reload, +.cbi-button-reload { + color: #fff !important; + background: darkolivegreen !important; + border-color: darkolivegreen !important; +} + +.cbi-button-reset, +.cbi-input-remove { + color: #fff !important; + background-color: darkorange !important; + border-color: darkorange !important; +} + +.cbi-page-actions .cbi-button-apply, +.cbi-section-actions .cbi-button-edit, +.cbi-button-edit.important, +.cbi-button-apply.important, +.cbi-button-reload.important, +.cbi-button-action.important { + border: 1px #483d8b solid !important; + border: 1px var(--dark-primary) solid !important; +} + +.btn[value="Dismiss"], +.cbi-button[value="Terminate"], +.cbi-button[value="Reset"], +.cbi-button[value="Disabled"], +.cbi-button[onclick^="iface_reconnect"], +.cbi-button[onclick="handleReset(event)"], +.cbi-button-neutral[value="Disable"] { + color: #fff; + border: thin solid darkorange !important; + background-color: darkorange !important; +} + +fieldset[id^="cbi-apply-"] { + background-color: #333333; +} + +#detail-bubble > div { + border: 1px solid #ccc; + background: #252525; +} + +.ifacebox-head.active { + background-color: var(--dark-primary) !important; +} + +header .fill .status span[data-style="active"] { + color: #ccc !important; + background-color: darkolivegreen !important; +} + +#cbi-wireless .td, +#cbi-network .tr:first-child > .td, +.table[width="100%"] > .tr:first-child > .td, +[data-page="admin-network-diagnostics"] .tr > .td, +.tr.table-titles > .th, +.tr.cbi-section-table-titles > .th { + background-color: #252526; + border-bottom: black 1px solid !important; + +} + +.network-status-table .ifacebox-body .ifacebadge { + background-color: #252526; + border-bottom: 0; + box-shadow: none; +} + +td > .ifacebadge, +.td > .ifacebadge { + color: #fff; + background-color: #483d8b; + background-color: var(--dark-primary); + border: 0; +} + +.alert, .alert-message { + background-color: #333; +} + +.alert-message.warning { + background-color: #986400 !important; +} + +.alert.error, .alert-message.error { + background-color: #784f00; +} + +.alert h4, .alert-message h4 { + background-color: #784f00; + color: #ffbf00; +} + +.alert-message [class="btn"] { + background-color: #777777; + color: #ccc; +} + +.uci-dialog { + .cbi-section { + + .uci-change-legend { + + .uci-change-legend-label { + + > ins { + border-color: #00ad00; + background-color: #688668; + } + + > del { + border-color: #c60000; + background-color: #896565; + } + + > var { + background-color: #333; + border-color: #666; + + ins { + background-color: #688668; + } + + del { + background-color: #896565; + } + } + } + } + + .uci-change-list { + > var { + background-color: #333; + border-color: #666; + + del { + background-color: #896565; + } + + ins { + background-color: #688668; + } + } + + > ins { + border-color: #00ad00; + background-color: #688668; + } + + > del { + border-color: #c60000; + background-color: #896565; + } + } + + .uci-change-list + .right { + .btn { + color: #ccc; + } + + .cbi-button { + border: 1px solid #3c3c3c !important; + } + } + } +} + +.btn.danger, +.cbi-section-remove > .cbi-button, +.cbi-button-remove, +.cbi-button-reset, +.cbi-button-negative, +.cbi-button[value="Stop"], +.cbi-button[value="Kill"], +.cbi-button[onclick="reboot(this)"], +.cbi-button-neutral[value="Restart"] { + border: thin solid darkorange !important; + background-color: darkorange !important; +} + +.cbi-section, +.cbi-section-error, +#iptables, +.Firewall form, +#cbi-network > .cbi-section-node, +#cbi-wireless > .cbi-section-node, +#cbi-wireless > #wifi_assoclist_table, +[data-tab-title], +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent > .container { + background: #1e1e1e !important; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); +} + +div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { + background: transparent !important; +} + +[data-page="admin-system-admin"] .cbi-map h2, +[data-page="admin-system-admin-password"] .cbi-map h2, +[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, +[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { + color: #ccc; +} + +[data-page="admin-system-flash"] { + .modal { + label > input[type="checkbox"] { + top: -0.35rem; + } + + .btn { + white-space: normal !important; + background-color: darkseagreen; + } + + .alert-message { + background-color: transparent !important; + } + + .danger { + border: thin solid darkorange !important; + background-color: darkorange !important; + } + } +} + +.cbi-value input[type="password"] + .cbi-button-neutral { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + border-color: var(--dark-primary) !important; +} + +.btn, +button, +select, +input, +.cbi-dropdown { + border: 1px solid #3c3c3c !important; +} + + +.cbi-dropdown .preview { + color: #ccc; +} + +.cbi-section-table-row { + background-color: #1e1e1e !important; +} + +.modal { + background-color: #1e1e1e; +} + +.cbi-button-positive { + color: #fff !important; + background-color: darkolivegreen !important; +} + +[data-page="admin-system-flash"] legend { + color: #ccc; +} + +.logout:before { + color: #adb5bd !important; +} + +.cbi-dropdown[open] { + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; +} + +.cbi-dropdown[open] > ul.dropdown { + background: #252526 !important; + color: #ffffff !important; + box-shadow: none; + border: 1px solid #3c3c3c !important; + + +} + +.cbi-dropdown[open] > ul.dropdown li { + color: #ffffff; + border-bottom: 1px solid #3c3c3c !important; +} + +.cbi-dropdown[open] > ul.dropdown > li[selected] { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + border-bottom: 1px solid #3c3c3c !important; +} + +.cbi-dropdown[open] > ul.dropdown > li.focus { + background: #483d8b; + background: var(--dark-primary); + outline: none; +} + +.ifacebadge { + background-color: #333333; +} + +.cbi-dynlist > .item > span { + border: 1px solid #3c3c3c !important; +} + +.cbi-page-actions .cbi-button-apply, +.cbi-section-actions .cbi-button-edit, +.cbi-button-edit, +.cbi-button-apply, +.cbi-button-reload, +.cbi-button-action, +.cbi-button[value="Submit"], +.cbi-button[value="Upload"], +.cbi-button[value$="Apply"], +.cbi-button[onclick="addKey(event)"] { + background: #483d8b !important; + background: var(--dark-primary) !important; + border-color: var(--dark-primary) !important; +} + +.btn.primary, +.cbi-page-actions .cbi-button-save, +.cbi-page-actions .cbi-button-apply + .cbi-button-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-positive, +.cbi-button-link, +.cbi-button[value="Enable"], +.cbi-button[value="Scan"], +.cbi-button[value^="Back"], +.cbi-button-neutral[onclick="handleConfig(event)"] { + background: #483d8b; + background: var(--dark-primary); +} + +[data-page="admin-system-opkg"] h2 { + color: #ccc !important; +} + +[data-page="admin-system-startup"] textarea { + color: #ccc; + background-color: transparent; + + &:focus-visible { + border: 1px solid var(--dark-primary); + } +} + +[data-page="admin-network-firewall-custom"] #view p textarea, +[data-page="admin-status-routes"] #view p textarea, +[data-page="admin-system-crontab"] #view p textarea { + color: #ccc; + background-color: transparent; +} + +#view > .spinning { + background: #333333 !important; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03) !important; +} + +@media screen and (min-width: 600px) { + + ::-webkit-scrollbar-thumb { + background: var(--dark-primary); + } + + ::-webkit-scrollbar-thumb:hover { + background: var(--dark-primary); + } + + ::-webkit-scrollbar-thumb:active { + background: var(--dark-primary); + } +} + + +@media screen and (max-width: 480px) { + .node-status-iptables > .main div > .cbi-map > form { + background-color: #1e1e1e; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); + } + + +} + +[data-page="admin-dashboard"] { + .main-right > #maincontent { + .Dashboard { + color: #ccc !important; + + h3 { + color: #ccc; + } + + hr { + border-top: 1px solid rgba(255, 255, 255, 1); + } + + .dashboard-bg { + background-color: #333333; + } + } + + .router-status-info .title img, + .lan-info .title img, + .wifi-info .title img { + filter: invert(90%); + } + + tr { + border-top: thin solid #4d4d4d; + + &:last-child { + border-bottom: thin solid #4d4d4d; + } + } + } +} + +[data-page="admin-system-fileassistant"] { + .fb-container .panel-container { + border-bottom-color: #3c3c3c !important; + } + + .fb-container td[class$="-icon"]::before { + filter: invert(0.7); + } +} + +[data-page^="admin-services-openclash"] { + .cbi-tabmenu::-webkit-scrollbar-thumb { + background-color: #5b5b5b; + } + + .cbi-tabmenu::-webkit-scrollbar-track { + background-color: rgba(60, 60, 60, 0.75); + } + + #tab { + border-color: #3c3c3c; + } + + #diag-rc-output > pre, + #dns-rc-output > pre { + color: #ccc; + border: 1px solid #3c3c3c !important; + background-color: #1e1e1e; + } + + img[src$="arrow-clockwise-light.svg"], + img[src$="wrench-light.svg"], + img[src$="eye-light.svg"] { + filter: invert(0.9); + } +} + +[data-page="admin-network-diagnostics"] { + .cbi-section { + background: #252526 !important; + } + + textarea { + background: transparent; + border-radius: 0.25rem; + color: #ccc; + border: 1px solid #3c3c3c !important; + } + + .tr > .td { + background-color: #252526 !important; + } +} + +[data-page="admin-network-network"] { + .ifacebox-head[style*="--zone-color-rgb: 144, 240, 144"] { + background-color: rgb(73, 126, 73) !important; + color: #ccc !important; + } + + .ifacebox-head[style*="--zone-color-rgb: 240, 144, 144;"] { + background-color: rgb(156, 79, 79) !important; + color: #ccc !important; + } + + .ifacebox-head[style*="--zone-color-rgb: 238, 238, 238;"] { + background-color: #666 !important; + } +} + +[data-page="admin-network-firewall-rules"] { + #cbi-firewall-rule { + .zonebadge[style*="--zone-color-rgb:240, 144, 144;"] { + --zone-color-rgb: 156, 79, 79 !important; + + strong { + color: #ccc !important; + } + } + + .zonebadge[style*="--zone-color-rgb:238, 238, 238;"] { + --zone-color-rgb: 112, 112, 112 !important; + + em { + color: #ccc !important; + } + } + + > table > .cbi-section-table-row[data-title]::before { + background-color: #252526 !important; + } + } +} + +[data-page="admin-network-network"], +[data-page="admin-network-firewall-rules"] { + .cbi-dropdown { + .zonebadge[style*="--zone-color-rgb:240, 144, 144;"] { + --zone-color-rgb: 156, 79, 79 !important; + color: #ccc !important; + + strong { + color: #ccc !important; + } + } + + .zonebadge[style*="--zone-color-rgb:144, 240, 144;"] { + --zone-color-rgb: 73, 126, 73 !important; + color: #ccc !important; + + strong { + color: #ccc !important; + } + } + + .zonebadge[style*="--zone-color-rgb:238, 238, 238;"] { + --zone-color-rgb: 112, 112, 112 !important; + + strong { + color: #ccc !important; + + + span { + color: #ccc !important; + } + } + } + } +} + +.btn { + background-color: rgb(112, 112, 112); + color: #fff; +} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/fonts.less b/luci-theme-argon/less/fonts.less similarity index 99% rename from luci-theme-argon/htdocs/luci-static/argon/less/fonts.less rename to luci-theme-argon/less/fonts.less index 71dd0fed7..c264b8749 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/less/fonts.less +++ b/luci-theme-argon/less/fonts.less @@ -20,7 +20,7 @@ * https://github.com/LuttyYang/luci-theme-material/ * * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html + * https://demos.creative-tim.com/argon-dashboard/index.html * * Login background * https://unsplash.com/ @@ -29,7 +29,7 @@ */ - @font-face { +@font-face { font-family: 'Google Sans'; src: url('data:application/font-woff2;charset=utf-8;base64,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') format('woff2'), url('data:application/font-woff;charset=utf-8;base64,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') format('woff'); diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/pure-min.less b/luci-theme-argon/less/pure-min.less similarity index 100% rename from luci-theme-argon/htdocs/luci-static/argon/less/pure-min.less rename to luci-theme-argon/less/pure-min.less diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer.htm b/luci-theme-argon/luasrc/view/themes/argon/footer.htm index abb7bcd3e..a184ff111 100644 --- a/luci-theme-argon/luasrc/view/themes/argon/footer.htm +++ b/luci-theme-argon/luasrc/view/themes/argon/footer.htm @@ -20,8 +20,8 @@

    diff --git a/luci-theme-argon/luasrc/view/themes/argon/header.htm b/luci-theme-argon/luasrc/view/themes/argon/header.htm index 17717ff65..854392f0e 100644 --- a/luci-theme-argon/luasrc/view/themes/argon/header.htm +++ b/luci-theme-argon/luasrc/view/themes/argon/header.htm @@ -59,54 +59,66 @@ - - - <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - - LuCI - - - - - - - - - - - - LuCI"> - - LuCI"> - - - - - - - - - - - - - - + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + <% if node and node.css then %> <% end -%> diff --git a/luci-theme-argon/luasrc/view/themes/argon/header_login.htm b/luci-theme-argon/luasrc/view/themes/argon/header_login.htm index 568e0cecb..8605c3936 100644 --- a/luci-theme-argon/luasrc/view/themes/argon/header_login.htm +++ b/luci-theme-argon/luasrc/view/themes/argon/header_login.htm @@ -56,63 +56,63 @@ - - - <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - - LuCI - - - - - - - - - - - - LuCI"> - - LuCI"> - - - - - - - - - - - - - - - <% if node and node.css then %> - - <% end -%> - <% if css then %> - - <% end -%> - + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + + <% if node and node.css then %> + + <% end -%> + <% if css then %> + + <% end -%> + diff --git a/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm deleted file mode 100644 index 398314779..000000000 --- a/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm +++ /dev/null @@ -1,27 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008-2019 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<% - local is_rollback_pending, rollback_time_remaining, rollback_session, rollback_token = luci.model.uci:rollback_pending() - - if is_rollback_pending or trigger_apply or trigger_revert then -%> - -<% - end - - include("themes/" .. theme .. "/footer_login") -%> diff --git a/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm b/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm index 5b46f2fa3..1fb399beb 100644 --- a/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm +++ b/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm @@ -31,7 +31,7 @@ local uci = require 'luci.model.uci'.cursor() -- Fetch Local Background Media - + local function glob(...) local iter, code, msg = fs.glob(...) if iter then @@ -42,12 +42,12 @@ end - local imageTypes = " jpg png gif " + local imageTypes = " jpg png gif webp " local videoTypes = " mp4 webm " local allTypes = imageTypes .. videoTypes - local function fetchMedia(path,themeDir) - local backgroundTable = {} - local backgroundCount = 0 + local function fetchMedia(path, themeDir) + local backgroundTable = {} + local backgroundCount = 0 for i, f in ipairs(glob(path)) do attr = fs.stat(f) if attr then @@ -59,43 +59,44 @@ local bg = {} bg.type = ext bg.url = themeDir .. fs.basename(f) - table.insert(backgroundTable,bg) + table.insert(backgroundTable, bg) backgroundCount = backgroundCount + 1 end end end - return backgroundTable,backgroundCount + return backgroundTable, backgroundCount end local function selectBackground(themeDir) - local bgUrl = media .. "/img/bg1.jpg" - local backgroundType = "Image" - local mimeType = "" + local bgUrl = media .. "/img/bg1.jpg" + local backgroundType = "Image" + local mimeType = "" if fs.access("/etc/config/argon") then - if uci:get_first('argon', 'global', 'bing_background') == "1" then - local bing = sys.exec("/usr/libexec/argon/bing_wallpaper") - if (bing and bing ~= '') then - return bing, "Image", "" + local online_wallpaper = uci:get_first('argon', 'global', 'online_wallpaper') or (uci:get_first('argon', 'global', 'bing_background') == '1' and 'bing') + if (online_wallpaper and online_wallpaper ~= "none") then + local picurl = sys.exec("/usr/libexec/argon/online_wallpaper") + if (picurl and picurl ~= '') then + return picurl, "Image", "" end end end - local backgroundTable, backgroundCount = fetchMedia("/www" .. themeDir .. "*",themeDir) + local backgroundTable, backgroundCount = fetchMedia("/www" .. themeDir .. "*", themeDir) if ( backgroundCount > 0 ) then - local currentBg = backgroundTable[math.random(1,backgroundCount)] - bgUrl = currentBg.url + local currentBg = backgroundTable[math.random(1, backgroundCount)] + bgUrl = currentBg.url if (string.match(videoTypes, " "..currentBg.type.." ") ~= nil) then - backgroundType = "Video" - mimeType = "video/" .. currentBg.type + backgroundType = "Video" + mimeType = "video/" .. currentBg.type end end - return bgUrl,backgroundType,mimeType + return bgUrl, backgroundType, mimeType end local boardinfo = util.ubus("system", "board") local themeDir = media .. "/background/" - local bgUrl,backgroundType,mimeType = selectBackground(themeDir) + local bgUrl, backgroundType, mimeType = selectBackground(themeDir) %>
    - +
    @@ -159,28 +160,4 @@ if (input) input.focus(); //]]> - <% - local uci = require "luci.model.uci".cursor() - local fs = require "nixio.fs" - local https_key = uci:get("uhttpd", "main", "key") - local https_port = uci:get("uhttpd", "main", "listen_https") - if type(https_port) == "table" then - https_port = https_port[1] - end - - if https_port and fs.access(https_key) then - https_port = https_port:match("(%d+)$") - %> - - <% end %> -<%+themes/argon/out_footer_login%> +<%+themes/argon/footer_login%> diff --git a/luci-theme-argon/root/usr/libexec/argon/bing_wallpaper b/luci-theme-argon/root/usr/libexec/argon/bing_wallpaper deleted file mode 100755 index 89e015943..000000000 --- a/luci-theme-argon/root/usr/libexec/argon/bing_wallpaper +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh -# author jjm2473 - -BING_BASE=http://www.bing.com -CACHE=/var/run/argon_bing.url -WRLOCK=/var/lock/argon_bing.lock - -fetch_url_path() { - curl --fail --show-error --max-time 1 \ - "$BING_BASE/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US" 2>/dev/null \ - | jsonfilter -q -e '@.images[0].url' -} - -try_update() { - local lock="$WRLOCK" - exec 200>$lock - - if flock -n 200 >/dev/null 2>&1; then - local path=`fetch_url_path` - if [ -n "$path" ]; then - echo "${BING_BASE}${path}" | tee "$CACHE" - else - if [ -s "$CACHE" ]; then - cat "$CACHE" - else - touch "$CACHE" - fi - fi - flock -u 200 >/dev/null 2>&1 - elif [ -s "$CACHE" ]; then - cat "$CACHE" - fi -} - -get_url() { - if [ -f "$CACHE" ]; then - local idle_t=$((`date '+%s'` - `date -r "$CACHE" '+%s' 2>/dev/null || echo '0'`)) - if [ -s "$CACHE" ]; then - if [ $idle_t -le 43200 ]; then - cat "$CACHE" - return - fi - else - if [ $idle_t -le 120 ]; then - return - fi - fi - fi - try_update -} - -get_url diff --git a/luci-theme-argon/root/usr/libexec/argon/online_wallpaper b/luci-theme-argon/root/usr/libexec/argon/online_wallpaper new file mode 100755 index 000000000..01bcae230 --- /dev/null +++ b/luci-theme-argon/root/usr/libexec/argon/online_wallpaper @@ -0,0 +1,105 @@ +#!/bin/sh +# author jjm2473 + +# the script will be excuted when `argon.@global[0].bing_background == '1'` +# defaults to 'bing' to be compatible with old config +WEB_PIC_SRC=$(uci -q get argon.@global[0].online_wallpaper || echo 'bing') +# For now, the next two variables are used for wallhaven.cc with specified Tag ID +# API_KEY if user has an account with wallhaven and want to use their apikey to allow for more images +# EXACT_RESO is used for exact resolution by default, if not use 'atleast' instead of 'resolutions' +API_KEY=$(uci -q get argon.@global[0].use_api_key) +EXACT_RESO=$(uci -q get argon.@global[0].use_exact_resolution || echo '1') +CACHE=/var/run/argon_${WEB_PIC_SRC}.url +WRLOCK=/var/lock/argon_${WEB_PIC_SRC}.lock + +fetch_pic_url() { + case $WEB_PIC_SRC in + bing) + local picpath=$(curl -fks --max-time 3 \ + "https://www.bing.com/HPImageArchive.aspx?format=js&n=1" | + jsonfilter -qe '@.images[0].url') + [ -n "${picpath}" ] && echo "//www.bing.com${picpath}" + ;; + unsplash) + if [ -z "$API_KEY" ]; then + curl -fks --max-time 3 \ + "https://source.unsplash.com/1920x1080/daily?wallpapers" | + sed -E 's#^.*href="([^?]+)\?.*$#\1?fm=jpg\&fit=crop\&w=1920\&h=1080#' + else + curl -fks --max-time 3 \ + "https://api.unsplash.com/photos/random?client_id=${API_KEY}" | + jsonfilter -qe '@["urls"]["regular"]' + fi + ;; + unsplash_*) + local collection_id=${WEB_PIC_SRC#unsplash_} + if [ -z "$API_KEY" ]; then + curl -fks --max-time 3 \ + "https://source.unsplash.com/collection/${collection_id}/1920x1080" | + sed -E 's#^.*href="([^?]+)\?.*$#\1?fm=jpg\&fit=crop\&w=1920\&h=1080#' + else + curl -fks --max-time 3 \ + "https://api.unsplash.com/photos/random?client_id=${API_KEY}&collections=${collection_id}" | + jsonfilter -qe '@["urls"]["regular"]' + fi + ;; + wallhaven) + curl -fks --max-time 3 \ + "https://wallhaven.cc/api/v1/search?resolutions=1920x1080&sorting=random" | + jsonfilter -qe '@.data[0].path' + ;; + wallhaven_*) + local tag_id=${WEB_PIC_SRC#wallhaven_} + local has_api_key="" + [ -n "$API_KEY" ] && has_api_key="apikey=$API_KEY&" || has_api_key="" + local use_reso="resolutions" + [ "$EXACT_RESO" -eq "1" ] && use_reso='resolutions' || use_reso='atleast' + curl -fks --max-time 3 \ + "https://wallhaven.cc/api/v1/search?${has_api_key}q=id%3A${tag_id}&${use_reso}=1920x1080&sorting=random" | + jsonfilter -qe '@.data[0].path' + ;; + esac +} + +try_update() { + local lock="$WRLOCK" + exec 200>$lock + + if flock -n 200 >/dev/null 2>&1; then + local picurl=$(fetch_pic_url) + if [[ "$WEB_PIC_SRC" == wallhave* ]] ; then + curl -fks --max-time 3 --url "${picurl}" > /dev/null + fi + if [ -n "$picurl" ]; then + echo "${picurl}" | tee "$CACHE" + else + if [ -s "$CACHE" ]; then + cat "$CACHE" + else + touch "$CACHE" + fi + fi + flock -u 200 >/dev/null 2>&1 + elif [ -s "$CACHE" ]; then + cat "$CACHE" + fi +} + +get_url() { + if [ -f "$CACHE" ]; then + local idle_t=$(($(date '+%s') - $(date -r "$CACHE" '+%s' 2>/dev/null || echo '0'))) + if [ -s "$CACHE" ]; then + if [ $idle_t -le 43200 ]; then + cat "$CACHE" + return + fi + else + if [ $idle_t -le 120 ]; then + return + fi + fi + fi + try_update +} + +get_url From 6fa355afdb70fcced45dfd63128192c8cdeddf91 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 19 Feb 2024 20:09:43 +0100 Subject: [PATCH 1417/2059] Fix a bug when shadowsocks-libev or shadowsocks-rust are launched with ss-rules enabled but no server enabled --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 3 +++ shadowsocks-rust/files/shadowsocks-rust.init-nft | 3 +++ 2 files changed, 6 insertions(+) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index c69eade3c..e0d6ba774 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -180,6 +180,9 @@ ss_rules_nft_gen() { validate_ss_rules_section "$cfg" || return 1 [ "$disabled" = 0 ] || return 2 + config_get server "$cfg" server + [ "$(uci -q get shadowsocks-libev.${server}.disabled)" = "1" ] && return 2 + if [ "$ss_rules_redir_tcp_$redir_tcp" = "all" ]; then min_ss_redir_ports="65535" max_ss_redir_ports="0" diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index 158df38f7..9e708648f 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -150,6 +150,9 @@ ss_rules_nft_gen() { validate_ss_rules_section "$cfg" || return 1 [ "$disabled" = 0 ] || return 2 + config_get server "$cfg" server + [ "$(uci -q get shadowsocks-rust.${server}.disabled)" = "1" ] && return 2 + if [ "$ss_rules_redir_tcp_$redir_tcp" = "all" ]; then min_ss_redir_ports="65535" max_ss_redir_ports="0" From 048f373a2f7f79f29dddbcfd5e7669f2af2207ce Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 22 Feb 2024 15:53:04 +0100 Subject: [PATCH 1418/2059] Increase max width for status --- .../luci-static/resources/openmptcprouter/css/wanstatus.css | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css index 9dd88fd72..b475ce419 100644 --- a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css +++ b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css @@ -1,6 +1,6 @@ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */ - max-width: 1044px; + max-width: 1644px; } #interface_field { padding: 12px 20px 20px 20px; @@ -31,10 +31,6 @@ text-align: center; } /* Mwan3 ligthed CSS */ -.container { - /* container for entire page. fixes bootstrap theme's ridiculously small page width */ - max-width: 1044px; -} #interface_field { padding: 0px; } From e7126a5f6d6d4eb86b2a32cb930654a556249028 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 22 Feb 2024 18:33:27 +0100 Subject: [PATCH 1419/2059] Fix tracking for IPv6 and restart only OMR VPN with OpenVPN --- .../usr/share/omr/post-tracking.d/001-post-tracking | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index e43a4618c..f590d7de6 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -708,6 +708,7 @@ dns_flush() { # Get the current multipath status multipath_status="off" [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && multipath $OMR_TRACKER_DEVICE off 2>&1 >/dev/null +[ "$OMR_TRACKER_INTERFACE" = "omr6in4" ] && multipath $OMR_TRACKER_DEVICE off 2>&1 >/dev/null if [ -e "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then case "$(multipath "$OMR_TRACKER_DEVICE")" in *default*) multipath_status="on" ;; @@ -878,7 +879,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then ifup $OMR_TRACKER_INTERFACE 2>&1 >/dev/null } - if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ]; then + if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] || [ "$OMR_TRACKER_INTERFACE" = "omr6in4" ]; then if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then _log "$OMR_TRACKER_INTERFACE down" else @@ -917,7 +918,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi if [ "$(uci -q get openvpn.omr.enabled)" = "1" ]; then _log "OpenVPN down, restart it" - /etc/init.d/openvpn restart 2>&1 >/dev/null + /etc/init.d/openvpn restart omr 2>&1 >/dev/null fi config_load openmptcprouter config_foreach disable_pihole server @@ -944,7 +945,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then exit 0 fi -if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ]; then +if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] || [ "$OMR_TRACKER_INTERFACE" = "omr6in4" ]; then if [ "$(uci -q get openmptcprouter.settings.shadowsocksudp)" = "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ -n "$(uci -q get shadowsocks-libev.sss0)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "hi1" ]; then _log "Tunnel up disable use of ShadowSocks for UDP" uci -q delete shadowsocks-libev.ss_rules.redir_udp @@ -1149,7 +1150,7 @@ if [ "$multipath_config" = "master" ]; then config_load network config_foreach set_route_balancing6 interface [ -n "$routesbalancing6" ] && { - ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { + ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing6 " ] && [ "$(ip -6 r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default $routesbalancing6 " ]) || ([ "$nbintf6" = "1" ] && [ "$(ip -6 r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] && [ "$(ip -6 r show default metric 1 | grep omr6in4)" = "" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]) && { _log "Set ip -6 route replace default scope global metric 1 $routesbalancing6" ip -6 route replace default scope global metric 1 $routesbalancing6 2>&1 >/dev/null } From 621c9aa7f1f7294145f80f67d4489ab5fc6f7f77 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 22 Feb 2024 18:33:47 +0100 Subject: [PATCH 1420/2059] Fix omr-6in4 --- omr-6in4/files/bin/omr-6in4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-6in4/files/bin/omr-6in4 b/omr-6in4/files/bin/omr-6in4 index 8bf094a50..4af348f2f 100755 --- a/omr-6in4/files/bin/omr-6in4 +++ b/omr-6in4/files/bin/omr-6in4 @@ -26,7 +26,7 @@ while true; do [ -z "$peer" ] && peer=$(ip -4 r list dev $iface | grep via | grep -v default | grep -v metric | grep -v / | awk '{print $1; exit}' | tr -d "\n") [ -z "$peer" ] && peer=$(ip -4 r list dev $iface | grep kernel | awk '/proto kernel/ {print $1}' | grep -v / | tr -d "\n") [ -n "$addr" ] && [ -n "$peer" ] && { - if [ "$addr" != "$(uci -q get network.omr6in4.ipaddr)" ] || [ "$peer" != "$(uci -q get network.omr6in4.peeraddr)" ] || [ "$(ip -6 route show default | grep via)" = "" ]; then + if ([ "$addr" != "$(uci -q get network.omr6in4.ipaddr)" ] || [ "$peer" != "$(uci -q get network.omr6in4.peeraddr)" ]) && [ "$(ip -6 route show default dev 6in4-omr6in4 metric 1 | grep via)" = "" ]; then logger -t "omr6in4" "Set network for OMR 6in4 to local $addr peer $peer" uci -q batch <<-EOF set network.omr6in4.ipaddr=$addr From df025467e0673a6a17b70abcd3c33f8d4ebd381c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 22 Feb 2024 18:34:35 +0100 Subject: [PATCH 1421/2059] Use all defined IPs for VPS check and fix IPv6 support --- omr-tracker/files/bin/omr-tracker-server | 101 +++++++++++++++-------- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index f0236e4e9..999e95ff0 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -4,6 +4,8 @@ name=$0 basename="$(basename $0)" +. /usr/lib/unbound/iptools.sh + _log() { logger -p daemon.info -t "${basename}" "$@" } @@ -24,13 +26,23 @@ _check_server() { local host=$1 local port=$2 local k=0 + local valid_ip6=$(valid_subnet6 $host) while [ "$server_ping" = false ] && [ "$k" -le "$retry" ]; do - ret=$(curl \ - --max-time "$OMR_TRACKER_TIMEOUT" \ - -s \ - -k \ - "https://${host}:${port}/" - ) + if [ "$valid_ip6" != "ok" ]; then + ret=$(curl \ + --max-time "$OMR_TRACKER_TIMEOUT" \ + -s \ + -k \ + "https://${host}:${port}/" + ) + else + ret=$(curl \ + --max-time "$OMR_TRACKER_TIMEOUT" \ + -s \ + -k \ + "https://[${host}]:${port}/" + ) + fi [ -n "$ret" ] && server_ping=true k=$((k+1)) sleep "${intervaltries}" @@ -40,16 +52,26 @@ _check_server() { _check_server_intf() { local host=$1 local port=$2 + local valid_ip6=$(valid_subnet6 $host) for intf in $(multipath | awk '/default/ {print $1}'); do local k=0 while [ "$server_ping" = false ] && [ "$k" -le "$retry" ]; do - ret=$(curl \ - --max-time "$OMR_TRACKER_TIMEOUT" \ - -s \ - -k \ - --interface $intf \ - "https://${host}:${port}/" - ) + if [ "$valid_ip6" != "ok" ]; then + ret=$(curl \ + --max-time "$OMR_TRACKER_TIMEOUT" \ + -s \ + -k \ + --interface $intf \ + "https://${host}:${port}/" + ) + else + ret=$(curl \ + --max-time "$OMR_TRACKER_TIMEOUT" \ + -s \ + -k \ + "https://[${host}%${intf}]:${port}/" + ) + fi [ -n "$ret" ] && { server_ping=true } @@ -89,21 +111,26 @@ _check_master() { config_get ip $1 ip config_get port $1 port "65500" config_get disabled $1 disabled + serverip="" [ "$master" = "1" ] && [ -n "$ip" ] && [ "$disabled" != "1" ] && { - set_ip() { + check_ip() { local ipd=$1 - local ip="" ipresolve="$(resolveip -4 $ipd | head -n 1)" if [ -n "$ipresolve" ]; then - ip="$ipresolve" + serverip="$ipresolve" else ip6resolve="$(resolveip -6 $ipd | head -n 1)" - [ -n "$ip6resolve" ] && ip="$ip6resolve" + [ -n "$ip6resolve" ] && serverip="$ip6resolve" fi - [ -z "$ip" ] && return - #_ping_server $ip - #_check_server $ip $port - _check_server_intf $ip $port + [ -z "$serverip" ] && return + #_ping_server $serverip + #_check_server $serverip $port + _check_server_intf $serverip $port + [ "$server_ping" = true ] && return + countips=$((countips+1)) + } + set_ip() { + ip="$serverip" if [ "$server_ping" = true ]; then if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then logger -t "OMR-Tracker-Server" "Master server ${name} up ($ip), set it back" @@ -204,10 +231,10 @@ _check_master() { script_alert_down="$(uci -q get omr-tracker.proxy.script_alert_down)" [ -n "$script_alert_down" ] && eval $script_alert_down fi - countips=$((countips+1)) } config_load openmptcprouter - config_list_foreach $1 ip set_ip + config_list_foreach $1 ip check_ip + set_ip #if [ "$server_ping" = true ] && [ "$countips" = "1" ]; then # uci -q batch <<-EOF >/dev/null # set shadowsocks-libev.sss${count}.server=$ip @@ -233,19 +260,26 @@ _check_backup() { config_get ip $1 ip config_get port $1 port config_get disabled $1 disabled + serverip="" [ "$backup" = "1" ] && [ -n "$ip" ] && [ "$disabled" != "1" ] && { - set_ip() { - local ip=$1 - ipresolve="$(resolveip -4 $ip | head -n 1)" + check_ip() { + local ipd=$1 + ipresolve="$(resolveip -4 $ipd | head -n 1)" if [ -n "$ipresolve" ]; then - ip="$ipresolve" + serverip="$ipresolve" else - ip6resolve="$(resolveip -6 $ip | head -n 1)" - [ -n "$ip6resolve" ] && ip="$ip6resolve" + ip6resolve="$(resolveip -6 $ipd | head -n 1)" + [ -n "$ip6resolve" ] && serverip="$ip6resolve" fi - #_ping_server $ip - #_check_server $ip $port - _check_server_intf $ip $port + [ -z "$serverip" ] && return + #_ping_server $serverip + #_check_server $serverip $port + _check_server_intf $serverip $port + [ "$server_ping" = true ] && return + countips=$((countips+1)) + } + set_ip() { + ip="$serverip" #[ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" = "$ip" ] && break if [ "$server_ping" = true ]; then if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then @@ -349,7 +383,8 @@ _check_backup() { countips=$((countips+1)) } config_load openmptcprouter - config_list_foreach $1 ip set_ip + config_list_foreach $1 ip check_ip + set_ip #if [ "$server_ping" = true ] && [ "$countips" = "1" ]; then # uci -q batch <<-EOF >/dev/null # set shadowsocks-libev.sss${count}.server=$ip From 7e64ecd41dc68d82aa2e7a3ec24cf1a579518e02 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 22 Feb 2024 18:35:26 +0100 Subject: [PATCH 1422/2059] Fix issue when server disabled for Shadowsocks* and fix IPv6 support in OMR-Tracker --- omr-tracker/files/etc/init.d/omr-tracker | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index ae9418ff2..9f71c7b77 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -283,7 +283,7 @@ _launch_shadowsocks_tracker() { [ "$enabled" = "0" ] || [ "$disabled" = "1" ] || [ -z "$hosts" ] && return [ -z "$server" ] && return - [ "$server" = "192.168.1.3" ] || [ "$server" = "" ] && return + [ "$(uci -q get shadowsocks-libev.${server}.disabled)" = "1" ] && return procd_open_instance # shellcheck disable=SC2086 @@ -317,7 +317,7 @@ _launch_shadowsocks_rust_tracker() { [ "$enabled" = "0" ] || [ "$disabled" = "1" ] || [ -z "$hosts" ] && return [ -z "$server" ] && return - [ "$server" = "192.168.1.3" ] || [ "$server" = "" ] && return + [ "$(uci -q get shadowsocks-rust.${server}.disabled)" = "1" ] && return procd_open_instance # shellcheck disable=SC2086 @@ -385,12 +385,17 @@ _dns_server() { local ip=$1 resolv=$(resolveip -4 ${ip} | head -n 1) [ -n "${resolv}" ] && [ "${resolv}" != "${ip}" ] && multiserver=true + resolv=$(resolveip -6 ${ip} | head -n 1) + [ -n "${resolv}" ] && [ "${resolv}" != "${ip}" ] && multiserver=true + ipcount=$((ipcount+1)) } _multi_server() { + local ipcount=0 config_get backup $1 backup [ "$backup" = "1" ] && multiserver=true config_list_foreach $1 ip _dns_server + [ "$ipcount" != "0" ] && [ "$ipcount" != "1" ] && multiserver=true } _gre_tunnel() { From 22ca7a0131c748f38a07beb6a7db523242490733 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 23 Feb 2024 19:45:10 +0100 Subject: [PATCH 1423/2059] No data error for OMR6in4 --- .../files/usr/libexec/rpcd/openmptcprouter | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index b680dce20..213016384 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -1056,12 +1056,16 @@ function interfaces_status() mArray.openmptcprouter["tun_state"] = "DOWN" end if mArray.openmptcprouter["ipv6"] == "enabled" or mArray.openmptcprouter["service_addr_ip6"] ~= "" then - local tunnel_ipv6_gw = uci:get("network","omr6in4","gateway") - local tunnel_ping6_test = ut.trim(sys.exec("ping6 -w 1 -c 1 " .. tunnel_ipv6_gw .. "%6in4-omr6in4 | grep '100% packet loss'")) - if tunnel_ping6_test == "" then - mArray.openmptcprouter["tun6_state"] = "UP" + local tunnel_ipv6_gw = uci:get("network","omr6in4","gateway") or "" + if tunnel_ipv6_gw ~= "" then + local tunnel_ping6_test = ut.trim(sys.exec("ping6 -w 1 -c 1 " .. tunnel_ipv6_gw .. "%6in4-omr6in4 | grep '100% packet loss'")) + if tunnel_ping6_test == "" then + mArray.openmptcprouter["tun6_state"] = "UP" + else + mArray.openmptcprouter["tun6_state"] = "DOWN" + end else - mArray.openmptcprouter["tun6_state"] = "DOWN" + mArray.openmptcprouter["tun6_state"] = "UNKNOWN" end end else From 8488834cd9f6234d75f4ce1f3835a31c5b19b5e4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Feb 2024 20:47:33 +0100 Subject: [PATCH 1424/2059] No commit of firewall changes before all changes are done in omr-bypass --- omr-bypass/files/etc/init.d/omr-bypass-nft | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 6c38601d2..65bcb90f6 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -837,7 +837,6 @@ start_service() { set firewall.omr_bypass.type='script' set firewall.omr_bypass.path='/etc/firewall.omr-bypass' set firewall.omr_bypass.fw4_compatible='1' - commit firewall EOF #echo "intf_rule" config_load network @@ -865,7 +864,6 @@ start_service() { config_foreach _bypass_asn asns #echo "bypass domains" config_foreach _bypass_domains domains - uci -q commit dhcp # ip rule add prio 1 fwmark 0x4539 lookup 991337 > /dev/null 2>&1 # ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 @@ -893,6 +891,9 @@ start_service() { [ -d /proc/net/xt_ndpi/proto ] && config_foreach _bypass_proto dpis config_foreach _bypass_proto_without_ndpi dpis uci -q commit omr-bypass + uci -q commit dhcp + uci -q commit firewall + fw4 -q restart [ -z "$RELOAD" ] && [ "$add_domains" = "true" ] && { logger -t "omr-bypass" "Restart dnsmasq..." @@ -902,7 +903,6 @@ start_service() { logger -t "omr-bypass" "Reload dnsmasq..." /etc/init.d/dnsmasq reload } - fw4 -q restart # Create a protocol list for UI from a sqlite DB when NDPI is not available sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass From 0f1694301ce42a0c6956f25767e3307e1359f620 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 26 Feb 2024 11:10:23 +0100 Subject: [PATCH 1425/2059] Set dnsmasq config after nft set are created --- omr-bypass/files/etc/init.d/omr-bypass-nft | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 65bcb90f6..77c94eddc 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -560,13 +560,6 @@ _intf_rule() { [ -z "$intf" ] && return # [ -z "$RELOAD" ] || [ "$(uci show firewall.omr_dst_bypass_$intf_4)" = "" ] && { #unset RELOAD - #echo "$intf ip set dhcp" - uci batch <<-EOF - set dhcp.omr_dst_bypass_$intf=ipset - add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4" - add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_6" - commit dhcp - EOF #echo "firewall omr_dst_bypass ipset" uci -q batch <<-EOF set firewall.omr_dst_bypass_${intf}_4=ipset @@ -678,6 +671,12 @@ _intf_rule() { commit network EOF fi + uci batch <<-EOF + set dhcp.omr_dst_bypass_$intf=ipset + add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4" + add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_6" + commit dhcp + EOF if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then config_load shadowsocks-libev From dc729420c73b26d10e76851690ad6b0f48189f1a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 28 Feb 2024 14:51:26 +0100 Subject: [PATCH 1426/2059] Fix status page CSS --- .../luci-static/resources/openmptcprouter/css/wanstatus.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css index b475ce419..20019851b 100644 --- a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css +++ b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css @@ -1,6 +1,6 @@ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */ - max-width: 1644px; + max-width: 1600px; } #interface_field { padding: 12px 20px 20px 20px; From c2e937e8183ae88b9a9f7b5cd8de05602d804dca Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 28 Feb 2024 14:52:55 +0100 Subject: [PATCH 1427/2059] Add xray and shadowsocks-rust support to blocklan script for 5.4 kernel --- openmptcprouter/files/bin/blocklanfw | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/bin/blocklanfw b/openmptcprouter/files/bin/blocklanfw index 56f176c81..1ba1f3c8a 100755 --- a/openmptcprouter/files/bin/blocklanfw +++ b/openmptcprouter/files/bin/blocklanfw @@ -1,6 +1,6 @@ #!/bin/sh -if [ -f /usr/sbin/iptables-legacy ]; then +if [ -e /usr/sbin/iptables-legacy ]; then IPTABLES="/usr/sbin/iptables-legacy" IP6TABLES="/usr/sbin/ip6tables-legacy" IPTABLESSAVE="/usr/sbin/iptables-legacy-save" @@ -89,10 +89,10 @@ v2ray_rules6_fw_drop() { [ -n "$(pgrep blocklanfw)" ] && exit 0 [ -z "$($IPTABLESSAVE 2>/dev/null | grep zone_lan)" ] && exit 0 fw=0 -if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then +if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ] || [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks-rust" ]; then ss_rules6_fw_drop ss_rules_fw_drop -elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ]; then +elif [ -n "$(uci -q get openmptcprouter.settings.proxy | grep v2ray)" ] || [ -n "$(uci -q get openmptcprouter.settings.proxy | grep xray)" ]; then v2r_rules_fw_drop v2ray_rules6_fw_drop fi From 00a724f34a9041ca9f6d86517c08362bac7186e8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 28 Feb 2024 15:03:46 +0100 Subject: [PATCH 1428/2059] Set tracker config by default for Shadowsocks-* --- shadowsocks-libev/files/shadowsocks-libev.config | 16 ++++++++++++++-- shadowsocks-rust/files/shadowsocks-rust.config | 14 +++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/shadowsocks-libev/files/shadowsocks-libev.config b/shadowsocks-libev/files/shadowsocks-libev.config index 9423ef9bc..a425f7d62 100644 --- a/shadowsocks-libev/files/shadowsocks-libev.config +++ b/shadowsocks-libev/files/shadowsocks-libev.config @@ -14,7 +14,7 @@ config ss_redir hi1 config ss_redir hi2 option server 'sss0' - option local_address '0.0.0.0' + option local_address '::' option local_port '1100' option mode 'tcp_and_udp' option timeout '1000' @@ -47,4 +47,16 @@ config ss_tunnel 'dns' option mode 'tcp_and_udp' option server 'sss0' option local_port '5353' - option tunnel_address '8.8.8.8:53' \ No newline at end of file + option tunnel_address '8.8.8.8:53' + +config ss_local 'tracker_sss0' + option server 'sss0' + option local_address '127.0.0.1' + option local_port '1111' + option mode 'tcp_and_udp' + option timeout '600' + option fast_open '0' + option syslog '0' + option reuse_port '1' + option mptcp '1' + option verbose '0' diff --git a/shadowsocks-rust/files/shadowsocks-rust.config b/shadowsocks-rust/files/shadowsocks-rust.config index f488f9b60..b131b7a12 100644 --- a/shadowsocks-rust/files/shadowsocks-rust.config +++ b/shadowsocks-rust/files/shadowsocks-rust.config @@ -55,4 +55,16 @@ config ss_tunnel 'dns' option mode 'tcp_and_udp' option server 'sss0' option local_port '5353' - option tunnel_address '8.8.8.8:53' \ No newline at end of file + option tunnel_address '8.8.8.8:53' + +config ss_local 'tracker_sss0' + option server 'sss0' + option local_address '127.0.0.1' + option local_port '1111' + option mode 'tcp_and_udp' + option timeout '600' + option fast_open '0' + option syslog '0' + option reuse_port '1' + option mptcp '1' + option verbose '0' From 45b7fee19bcac0de0016997354dbc39b66b4f0c1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 28 Feb 2024 15:49:21 +0100 Subject: [PATCH 1429/2059] Change to limit token errors logs from openmptcprouter-vps --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index ef12d21fd..96747ac57 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1343,7 +1343,7 @@ _set_vps_firewall() { vps_config="" _login [ -z "$token" ] && { - logger -t "OMR-VPS" "Can't get ${fwservername} token, try later" + [ "$(logread | tail -n 3 | grep -c 'vps token')" -lt 3 ] && logger -t "OMR-VPS" "Can't get ${fwservername} token, try later" uci -q batch <<-EOF >/dev/null set openmptcprouter.${fwservername}.admin_error=1 EOF @@ -2018,7 +2018,7 @@ _backup_send() { vps_config="" _login [ -z "$token" ] && { - logger -t "OMR-VPS" "Can't get ${servername} token, try later" + [ "$(logread | tail -n 3 | grep -c 'vps token')" -lt 3 ] && logger -t "OMR-VPS" "Can't get ${servername} token, try later" uci -q batch <<-EOF >/dev/null set openmptcprouter.${servername}.admin_error=1 EOF @@ -2060,7 +2060,7 @@ _backup_get_and_apply() { vps_config="" _login [ -z "$token" ] && { - logger -t "OMR-VPS" "Can't get ${servername} token, try later" + [ "$(logread | tail -n 3 | grep -c 'vps token')" -lt 3 ] && logger -t "OMR-VPS" "Can't get ${servername} token, try later" uci -q batch <<-EOF >/dev/null set openmptcprouter.${servername}.admin_error=1 EOF @@ -2104,7 +2104,7 @@ _backup_list() { vps_config="" _login [ -z "$token" ] && { - logger -t "OMR-VPS" "Can't get ${servername} token, try later" + [ "$(logread | tail -n 3 | grep -c 'vps token')" -lt 3 ] && logger -t "OMR-VPS" "Can't get ${servername} token, try later" uci -q batch <<-EOF >/dev/null set openmptcprouter.${servername}.admin_error=1 EOF @@ -2186,7 +2186,7 @@ _get_token() { if [ "$(uci -q get openmptcprouter.${servername}.username)" != "openmptcprouter" ]; then reason="$reason, custom username" fi - logger -t "OMR-VPS" "Can't get ${servername} token, try later ($reason)" + [ "$(logread | tail -n 3 | grep -c 'vps token')" -lt 3 ] && logger -t "OMR-VPS" "Can't get ${servername} token, try later ($reason)" uci -q batch <<-EOF >/dev/null set openmptcprouter.${servername}.admin_error=1 EOF @@ -2321,7 +2321,7 @@ _set_pihole_server() { vps_config="" _login [ -z "$token" ] && { - logger -t "OMR-VPS" "Can't get token, try later" + [ "$(logread | tail -n 3 | grep -c 'vps token')" -lt 3 ] && logger -t "OMR-VPS" "Can't get token, try later" uci -q batch <<-EOF >/dev/null set openmptcprouter.${pservername}.admin_error=1 EOF From 9c55b0be85ba9053df6a51691fdb5bfd3cde909b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 28 Feb 2024 20:17:59 +0100 Subject: [PATCH 1430/2059] Increase timeout for VPS status --- .../root/etc/uci-defaults/openmptcprouter | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter index 647c23303..f8c681624 100755 --- a/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/uci-defaults/openmptcprouter @@ -86,9 +86,9 @@ if [ "$(uci -q get openmptcprouter.settings.check_ipv6_website)" = "" ]; then commit openmptcprouter EOF fi -if [ "$(uci -q get openmptcprouter.settings.status_vps_timeout)" = "" ]; then +if [ "$(uci -q get openmptcprouter.settings.status_vps_timeout)" = "" ] || [ "$(uci -q get openmptcprouter.settings.status_vps_timeout)" = "1" ]; then uci -q batch <<-EOF >/dev/null - set openmptcprouter.settings.status_vps_timeout=1 + set openmptcprouter.settings.status_vps_timeout=3 commit openmptcprouter EOF fi From 07b7ae39daa15af47d05317e32515dfa4aef6df7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Mar 2024 17:44:17 +0100 Subject: [PATCH 1431/2059] Fix Core Temp on some arch --- .../luasrc/view/openmptcprouter/wanstatus.htm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index 8594dd5cb..ee976c0d5 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -132,7 +132,12 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm } if (mArray.openmptcprouter.core_temp) { - content += '<%:Core temp:%>' + " " + (mArray.openmptcprouter.core_temp / 1000).toFixed(1) + " °"; + if (mArray.openmptcprouter.core_temp > 100000) + { + content += '<%:Core temp:%>' + " " + (mArray.openmptcprouter.core_temp / 10000).toFixed(1) + " °"; + } else { + content += '<%:Core temp:%>' + " " + (mArray.openmptcprouter.core_temp / 1000).toFixed(1) + " °"; + } content += "
    "; } if (mArray.openmptcprouter.uptime) From 23ce6c02e7ec26f96e4276a4b687f5d25a80f8f0 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 4 Mar 2024 17:44:46 +0100 Subject: [PATCH 1432/2059] Fix issue https://github.com/Ysurac/openmptcprouter/issues/3192 --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 09a99bf73..64a1cd662 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -80,7 +80,7 @@ interface_macaddr_count() { interface_max_metric() { local config="$1" - if [ "$1" != "omrvpn" ] && [ "$1" != "omr6in4" ]; then + if [ "$1" != "omrvpn" ] && [ "$1" != "omr6in4" ] && [ "$1" != "lan" ]; then config_get metric "$config" metric if [ "$metric" = "$count" ]; then count=$((count+1)) From f4ba68e319afa56fc81734c0a4dc92b23f7c4845 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Mar 2024 08:16:31 +0100 Subject: [PATCH 1433/2059] Force correction of MTU previous issue --- mptcp/files/etc/init.d/mptcp | 1 + 1 file changed, 1 insertion(+) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 64a1cd662..87e7bbe6a 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -125,6 +125,7 @@ interface_multipath_settings() { else metric="$(uci -q get openmptcprouter.${config}.metric)" fi + [ "$metric" -gt 9900 ] && metric=$((metric-9000)) if [ "${config}" = "lan" ] || [ "$(uci -q get network.${config}.ip4table)" = "lan" ]; then metric="9999" fi From 8f32c218aa16f1cde6f92147c8d922f68dcb3523 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Mar 2024 20:15:57 +0100 Subject: [PATCH 1434/2059] Force lower metric for multipath --- mptcp/files/etc/init.d/mptcp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 87e7bbe6a..2a0e25059 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -125,7 +125,7 @@ interface_multipath_settings() { else metric="$(uci -q get openmptcprouter.${config}.metric)" fi - [ "$metric" -gt 9900 ] && metric=$((metric-9000)) + [ "$metric" -gt 1000 ] && metric=$((metric-1000)) if [ "${config}" = "lan" ] || [ "$(uci -q get network.${config}.ip4table)" = "lan" ]; then metric="9999" fi From 201d976ecb606940dc95a7c4a1ffa280a15568f1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 5 Mar 2024 20:16:27 +0100 Subject: [PATCH 1435/2059] Some fixes for OMR-ByPass --- omr-bypass/files/etc/init.d/omr-bypass-nft | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 77c94eddc..63afb7b6e 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -166,6 +166,7 @@ _bypass_mac() { [ -z "$mac" ] && return uci -q batch <<-EOF add_list firewall.omr_dst_bypass_$intf_mac.src_mac="$mac" + set firewall.omr_dst_bypass_$intf_mac.enabled='1' EOF } @@ -250,14 +251,14 @@ _bypass_src_port() { [ -z "$proto" ] && return if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.src_port="$sport" - set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' + add_list firewall.omr_dst_bypass_${intf}_srcport_tcp.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_srcport_tcp.enabled='1' EOF fi if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_udp.src_port="$sport" - set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' + add_list firewall.omr_dst_bypass_${intf}_srcport_udp.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_srcport_udp.enabled='1' EOF fi } @@ -501,8 +502,8 @@ _bypass_proto_without_ndpi() { _intf_rule_ss_rules() { cat >> /etc/firewall.omr-bypass <<-EOF - nft insert rule inet fw4 ss_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 meta mark set 0x00004539 accept - nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 meta mark set 0x00004539 accept + nft insert rule inet fw4 ss_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept EOF if [ "$disableipv6" = "0" ]; then cat >> /etc/firewall.omr-bypass <<-EOF @@ -639,7 +640,6 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='0' set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="0x${ipv46}539${count}" - commit firewall EOF done if [ "$intf" = "all" ]; then @@ -654,7 +654,6 @@ _intf_rule() { set network.${intf}_fw_rule6.priority=1 set network.${intf}_fw_rule6.mark=0x6539 set network.${intf}_fw_rule6.lookup=6991337 - commit network EOF else uci -q batch <<-EOF >/dev/null @@ -668,14 +667,12 @@ _intf_rule() { set network.${intf}_fw_rule6.priority=1 set network.${intf}_fw_rule6.mark=0x6539${count} set network.${intf}_fw_rule6.lookup=${count} - commit network EOF fi uci batch <<-EOF set dhcp.omr_dst_bypass_$intf=ipset add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4" add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_6" - commit dhcp EOF if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then @@ -889,6 +886,10 @@ start_service() { config_load omr-bypass [ -d /proc/net/xt_ndpi/proto ] && config_foreach _bypass_proto dpis config_foreach _bypass_proto_without_ndpi dpis + [ -n "$(uci change network)" ] && { + uci -q commit network + /etc/init.d/network reload + } uci -q commit omr-bypass uci -q commit dhcp uci -q commit firewall From c4c2eeb3d3ffb52d084378930dd250b4dda72793 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 6 Mar 2024 21:11:04 +0100 Subject: [PATCH 1436/2059] Fix inconsistency reported in https://github.com/Ysurac/openmptcprouter/issues/3192#issuecomment-1981675868 --- omr-bypass/files/etc/init.d/omr-bypass-nft | 67 +++++++++++++++------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 63afb7b6e..13e2c5e32 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -164,10 +164,17 @@ _bypass_mac() { [ -z "$intf" ] && intf="all" [ -z "$mac" ] && return - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_$intf_mac.src_mac="$mac" - set firewall.omr_dst_bypass_$intf_mac.enabled='1' - EOF + if [ "$disableipv6" = "0" ]; then + protocol="4 6" + else + protocol="4" + fi + for ipv46 in $protocol; do + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src_mac="$mac" + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='1' + EOF + done } _bypass_lan_ip() { @@ -217,17 +224,27 @@ _bypass_dest_port() { [ -z "$dport" ] && return dport="$(echo $dport | sed 's/:/-/')" [ -z "$proto" ] && return + if [ "$disableipv6" = "0" ]; then + protocol="4 6" + else + protocol="4" + fi + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dest_port="$dport" - set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' - EOF + for ipv46 in $protocol; do + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='1' + EOF + done fi if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dest_port="$dport" - set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' - EOF + for ipv46 in $protocol; do + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='1' + EOF + done fi } @@ -249,17 +266,27 @@ _bypass_src_port() { [ -z "$sport" ] && return sport="$(echo $sport | sed 's/:/-/')" [ -z "$proto" ] && return + if [ "$disableipv6" = "0" ]; then + protocol="4 6" + else + protocol="4" + fi + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_srcport_tcp.src_port="$sport" - set firewall.omr_dst_bypass_${intf}_srcport_tcp.enabled='1' - EOF + for ipv46 in $protocol; do + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='1' + EOF + done fi if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then - uci -q batch <<-EOF - add_list firewall.omr_dst_bypass_${intf}_srcport_udp.src_port="$sport" - set firewall.omr_dst_bypass_${intf}_srcport_udp.enabled='1' - EOF + for ipv46 in $protocol; do + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='1' + EOF + done fi } From 78607d25e4fc2b00d65c9fb8f99fe391c13d9750 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 8 Mar 2024 11:54:27 +0100 Subject: [PATCH 1437/2059] Fix metric attribution --- mptcp/files/etc/init.d/mptcp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 2a0e25059..bf0f967e9 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -82,10 +82,6 @@ interface_max_metric() { local config="$1" if [ "$1" != "omrvpn" ] && [ "$1" != "omr6in4" ] && [ "$1" != "lan" ]; then config_get metric "$config" metric - if [ "$metric" = "$count" ]; then - count=$((count+1)) - config_set "$config" metric $count - fi if [ "$metric" -gt "$count" ]; then count=$metric fi @@ -119,15 +115,19 @@ interface_multipath_settings() { [ -z "$iface" ] && config_get iface "$config" ifname config_get txqueuelen "$config" txqueuelen [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$config" | jsonfilter -q -e '@["device"]') - if [ "$(uci -q get openmptcprouter.${config}.metric)" = "" ]; then + if [ "$(uci -q get openmptcprouter.${config}.metric)" = "" ] || [ "$(uci -q get openmptcprouter.${config}.metric)" = "1" ]; then count=$((count+1)) metric=$count else metric="$(uci -q get openmptcprouter.${config}.metric)" fi - [ "$metric" -gt 1000 ] && metric=$((metric-1000)) + [ "$metric" -gt 1000 ] && [ "${config}" != "omrvpn" ] && [ "${config}" != "omr6in4" ] && metric=$((metric-1000)) if [ "${config}" = "lan" ] || [ "$(uci -q get network.${config}.ip4table)" = "lan" ]; then metric="9999" + elif [ "${config}" = "omrvpn" ]; then + metric="1500" + elif [ "${config}" = "omr6in4" ]; then + metric="1201" fi config_set "$config" metric $metric uci -q set network.${config}.metric=$metric @@ -513,7 +513,7 @@ remove() { start_service() { local intf=$1 - local id count intfmaster + local id intfmaster . /lib/functions.sh . /lib/functions/network.sh #[ -n "$intf" ] && multipath "${intf}" off 2>&1 >/dev/null @@ -530,7 +530,7 @@ start_service() { mptcpintf="" mptcpmintf="" master="" - count="0" + count=0 config_load openmptcprouter config_foreach interface_max_metric interface From 30ce34c19a0e2e2da41eacf06733894e4516f6ff Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 8 Mar 2024 20:43:19 +0100 Subject: [PATCH 1438/2059] Should solve server master to backup failover --- omr-tracker/files/bin/omr-tracker-server | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 999e95ff0..444c1634a 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -168,9 +168,11 @@ _check_master() { add_list openvpn.omr.remote=$ip commit openvpn set openmptcprouter.${name}.current='1' + set openmptcprouter.${name}.get_config='1' commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null + /etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null /etc/init.d/xray restart >/dev/null 2>/dev/null /etc/init.d/glorytun restart >/dev/null 2>/dev/null @@ -317,9 +319,11 @@ _check_backup() { add_list openvpn.omr.remote=$ip commit openvpn set openmptcprouter.${name}.current='1' + set openmptcprouter.${name}.get_config='1' commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null + /etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null /etc/init.d/xray restart >/dev/null 2>/dev/null /etc/init.d/glorytun restart >/dev/null 2>/dev/null From 48328cdeb9bb17fd85bba4240113f5718a51f78f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 11 Mar 2024 08:30:32 +0100 Subject: [PATCH 1439/2059] OMR-ByPass IPP sets family. Fix https://github.com/Ysurac/openmptcprouter/issues/3201#issuecomment-1987347769 --- omr-bypass/files/etc/init.d/omr-bypass-nft | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 13e2c5e32..a0a98819f 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -59,11 +59,11 @@ _bypass_ip() { valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then - uci -q add_list firewall.omr_dst_bypass_${type}_4.entry=$ip + uci -q add_list firewall.omr_dst_bypass_${type}_4.entry="$ip" uci -q set firewall.omr_dst_bypass_${type}_4.enabled='1' uci -q set firewall.omr_dst_bypass_${type}_dstip_4.enabled='1' elif [ "$valid_ip6" = "ok" ]; then - uci -q add_list firewall.omr_dst_bypass_${type}_6.entry=$ip + uci -q add_list firewall.omr_dst_bypass_${type}_6.entry="$ip" uci -q set firewall.omr_dst_bypass_${type}_6.enabled='1' uci -q set firewall.omr_dst_bypass_${type}_dstip_6.enabled='1' fi @@ -141,7 +141,7 @@ _bypass_domain() { fi fi if [ "$(uci -q get dhcp.omr_dst_bypass_$intf | grep /$domain/)" = "" ]; then - uci -q add_list dhcp.omr_dst_bypass_$intf.domain=$domain + uci -q add_list dhcp.omr_dst_bypass_$intf.domain="$domain" add_domains="true" fi if [ "$(uci -q get dhcp.@dnsmasq[0].noipv6 | grep /$domain/)" = "" ] && [ "$noipv6" = "1" ]; then @@ -420,6 +420,7 @@ _bypass_proto_without_ndpi() { set firewall.bypass_$proto=ipset set firewall.bypass_$proto.name="bypass_$proto" set firewall.bypass_$proto.match='dest_ip' + set firewall.bypass_$proto.family='ipv4' set firewall.bypass_$proto_rule=rule set firewall.bypass_$proto_rule.name="bypass_$proto" set firewall.bypass_$proto_rule.src='lan' @@ -432,6 +433,7 @@ _bypass_proto_without_ndpi() { set firewall.bypass6_$proto=ipset set firewall.bypass6_$proto.name="bypas6s_$proto" set firewall.bypass6_$proto.match='dest_ip' + set firewall.bypass6_$proto.family='ipv6' set firewall.bypass6_$proto_rule=rule set firewall.bypass6_$proto_rule.name="bypass6_$proto" set firewall.bypass6_$proto_rule.src='lan' @@ -469,10 +471,10 @@ _bypass_proto_without_ndpi() { if [ "$valid_ip4" = "ok" ]; then if [ "$vpn" != "1" ]; then #ipset -q add bypass_$proto $ip - uci -q add_list firewall.bypass_$proto.entry=$ip + uci -q add_list firewall.bypass_$proto.entry="$ip" else #ipset -q add omr_dst_bypass_$intf $ip - uci -q add_list firewall.omr_dst_bypass_${intf}_4.entry=$ip + uci -q add_list firewall.omr_dst_bypass_${intf}_4.entry="$ip" fi elif [ "$valid_ip6" = "ok" ]; then if [ "$vpn" != "1" ]; then @@ -480,7 +482,7 @@ _bypass_proto_without_ndpi() { uci -q add_list firewall.bypass6_$proto.entry=$ip else #ipset -q add omr6_dst_bypass_$intf $ip - uci -q add_list firewall.omr_dst_bypass_${intf}_6.entry=$ip + uci -q add_list firewall.omr_dst_bypass_${intf}_6.entry="$ip" fi fi done @@ -593,10 +595,12 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_4=ipset set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' + set firewall.omr_dst_bypass_${intf}_4.family='ipv4' set firewall.omr_dst_bypass_${intf}_4.enabled='1' set firewall.omr_dst_bypass_${intf}_6=ipset set firewall.omr_dst_bypass_${intf}_6.name="omr_dst_bypass_${intf}_6" set firewall.omr_dst_bypass_${intf}_6.match='dest_ip' + set firewall.omr_dst_bypass_${intf}_6.family='ipv6' set firewall.omr_dst_bypass_${intf}_6.enabled='1' EOF #echo "firewall omr_dst_bypass rules" @@ -614,12 +618,14 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.family="ipv${ipv46}" set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_mark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept=rule set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.name="omr_dst_bypass_${intf}_rule_accept" set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.target='ACCEPT' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.dest='*' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.family="ipv${ipv46}" set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.enabled='0' set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.mark="0x${ipv46}539${count}" set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule @@ -627,6 +633,7 @@ _intf_rule() { set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_${ipv46}" set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.src='lan' set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.family="ipv${ipv46}" set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.enabled='0' set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="0x${ipv46}539${count}" From f6a11aad2a8957b2c78fdf46050f1e0e0580e10b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 11 Mar 2024 10:22:21 +0100 Subject: [PATCH 1440/2059] Fix Backup server sync keys --- .../files/etc/init.d/openmptcprouter-vps | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 96747ac57..a0a3b365a 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -2261,13 +2261,13 @@ _config_service() { if [ "$user_permission" != "ro" ]; then #config_load shadowsocks-libev #config_foreach _set_ss_server_vps server - [ -n "$(uci -q get shadowsocks-libev)" ] && _set_ss_server_vps - [ -n "$(uci -q get shadowsocks-rust)" ] && _set_ssgo_server_vps - [ -n "$(uci -q get v2ray)" ] && _set_v2ray_server_vps - [ -n "$(uci -q get xray)" ] && _set_xray_server_vps - ([ -n "$(uci -q get glorytun)" ] || [ -n "$(uci -q get glorytun-udp)" ]) && [ -z "$(_set_glorytun_vps)" ] && error=1 - [ -n "$(uci -q get openvpn)" ] && [ -z "$(_set_openvpn_vps)" ] && error=1 - [ -n "$(uci -q get mlvpn)" ] && [ -z "$(_set_mlvpn_vps)" ] && error=1 + [ -n "$(uci -q get shadowsocks-libev.sss0)" ] && _set_ss_server_vps + [ -n "$(uci -q get shadowsocks-rust.sss0)" ] && _set_ssgo_server_vps + [ -n "$(uci -q get v2ray.omr)" ] && _set_v2ray_server_vps + [ -n "$(uci -q get xray.omr)" ] && _set_xray_server_vps + ([ -n "$(uci -q get glorytun.vpn)" ] || [ -n "$(uci -q get glorytun-udp.vpn)" ]) && [ -z "$(_set_glorytun_vps)" ] && error=1 + [ -n "$(uci -q get openvpn.omr)" ] && [ -z "$(_set_openvpn_vps)" ] && error=1 + [ -n "$(uci -q get mlvpn.general)" ] && [ -z "$(_set_mlvpn_vps)" ] && error=1 _set_vps_firewall [ -n "$(uci -q get wireguard)" ] && [ -z "$(_set_wireguard_vps)" ] && error=1 fi From 94f1ff1efe081cd304b848885e37a642419b73f5 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 11 Mar 2024 10:22:48 +0100 Subject: [PATCH 1441/2059] Add netxen-nic firmware dependency --- netxen-nic/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netxen-nic/Makefile b/netxen-nic/Makefile index 399970c87..f0ebf3a6e 100644 --- a/netxen-nic/Makefile +++ b/netxen-nic/Makefile @@ -34,6 +34,6 @@ define KernelPackage/netxen-nic KCONFIG := CONFIG_NETXEN_NIC=m FILES := $(PKG_BUILD_DIR)/drivers/net/ethernet/qlogic/netxen/netxen_nic.ko AUTOLOAD := $(call AutoProbe,netxen_nic) - DEPENDS := @PCI_SUPPORT + DEPENDS := @PCI_SUPPORT +netxen-firmware endef $(eval $(call KernelPackage,netxen-nic)) From 0de6d0aaa2e0b248b42f0a0f0323f42af9c6f2c1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 12 Mar 2024 20:09:24 +0100 Subject: [PATCH 1442/2059] Restart of openmptcprouter-vps shouldn't be need with VPS synchro on master/backup failover --- omr-tracker/files/bin/omr-tracker-server | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 444c1634a..d90cee48c 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -172,7 +172,7 @@ _check_master() { commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null - /etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null + #/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null /etc/init.d/xray restart >/dev/null 2>/dev/null /etc/init.d/glorytun restart >/dev/null 2>/dev/null @@ -323,7 +323,7 @@ _check_backup() { commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null - /etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null + #/etc/init.d/openmptcprouter-vps restart >/dev/null 2>/dev/null /etc/init.d/v2ray restart >/dev/null 2>/dev/null /etc/init.d/xray restart >/dev/null 2>/dev/null /etc/init.d/glorytun restart >/dev/null 2>/dev/null From ec22b7e248880e7a60770ba34360889f73092fca Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 12 Mar 2024 20:09:57 +0100 Subject: [PATCH 1443/2059] Change sysctl settings --- openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf b/openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf index 584db2854..47cbcda11 100644 --- a/openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf +++ b/openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf @@ -22,9 +22,9 @@ net.ipv4.tcp_tw_reuse = 1 # turn off fast timewait sockets recycling #net.ipv4.tcp_tw_recycle = 0 # short FIN timeout -#net.ipv4.tcp_fin_timeout = 60 +#net.ipv4.tcp_fin_timeout = 40 # increase max orphans -net.ipv4.tcp_max_orphans = 16384 +net.ipv4.tcp_max_orphans = 32768 # short keepalive time #net.ipv4.tcp_keepalive_time = 2400 # outbound port range @@ -32,7 +32,7 @@ net.ipv4.ip_local_port_range = 9999 65000 # max SYN backlog net.ipv4.tcp_max_syn_backlog = 10240 # max timewait sockets held by system simultaneously -net.ipv4.tcp_max_tw_buckets = 10000 +net.ipv4.tcp_max_tw_buckets = 6000 # turn on TCP Fast Open on both client and server side #net.ipv4.tcp_fastopen = 3 # TCP receive buffer @@ -60,4 +60,4 @@ net.ipv4.tcp_ecn = 2 #net.ipv4.tcp_dsack = 0 #net.ipv4.tcp_fack = 0 net.ipv4.tcp_slow_start_after_idle = 0 -net.ipv4.route.gc_timeout = 150 \ No newline at end of file +net.ipv4.route.gc_timeout = 150 From 8c9688f82f1493112c5c91cba085268f53950b03 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Mar 2024 09:44:10 +0100 Subject: [PATCH 1444/2059] Update OpenVPN to 2.6.9 --- openvpn/Makefile | 6 +- openvpn/files/etc/hotplug.d/openvpn/01-user | 7 +- openvpn/files/openvpn.init | 110 +++++++++++++------- 3 files changed, 79 insertions(+), 44 deletions(-) diff --git a/openvpn/Makefile b/openvpn/Makefile index 752d38535..349c7e1cb 100644 --- a/openvpn/Makefile +++ b/openvpn/Makefile @@ -9,14 +9,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openvpn -PKG_VERSION:=2.6.5 -PKG_RELEASE:=1 +PKG_VERSION:=2.6.9 +PKG_RELEASE:=10 PKG_SOURCE_URL:=\ https://build.openvpn.net/downloads/releases/ \ https://swupdate.openvpn.net/community/releases/ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_HASH:=e34efdb9a3789a760cfc91d57349dfb1e31da169c98c06cb490c6a8a015638e2 +PKG_HASH:=e08d147e15b4508dfcd1d6618a1f21f1495f9817a8dadc1eddf0532fa116d7e3 PKG_MAINTAINER:=Magnus Kroken diff --git a/openvpn/files/etc/hotplug.d/openvpn/01-user b/openvpn/files/etc/hotplug.d/openvpn/01-user index 4c72f1c4b..f6ad8935e 100644 --- a/openvpn/files/etc/hotplug.d/openvpn/01-user +++ b/openvpn/files/etc/hotplug.d/openvpn/01-user @@ -7,10 +7,14 @@ $* } -# Wrap user defined scripts on up/down events +# Wrap user defined scripts on up/down/route-up/route-pre-down/ipchange events +# Scriptp set with up/down/route-up/route-pre-down/ipchange in the openvpn config are also executed with the command=user_xxxx case "$ACTION" in up) command=$user_up ;; down) command=$user_down ;; + route-up) command=$user_route_up ;; + route-pre-down) command=$user_route_pre_down ;; + ipchange) command=$user_ipchange ;; *) command= ;; esac @@ -20,3 +24,4 @@ if [ -n "$command" ]; then fi exit 0 + diff --git a/openvpn/files/openvpn.init b/openvpn/files/openvpn.init index 34c6f3511..5c1beb0e3 100644 --- a/openvpn/files/openvpn.init +++ b/openvpn/files/openvpn.init @@ -10,22 +10,13 @@ STOP=10 USE_PROCD=1 PROG=/usr/sbin/openvpn +PATH_INSTANCE_DIR="/etc/openvpn" LIST_SEP=" " UCI_STARTED= UCI_DISABLED= -version_over_5_4() { - MAJOR_VERSION=$(uname -r | awk -F '.' '{print $1}') - MINOR_VERSION=$(uname -r | awk -F '.' '{print $2}') - if [ $MAJOR_VERSION -ge 5 ] && [ $MINOR_VERSION -gt 13 ] || [ $MAJOR_VERSION -gt 5 ] ; then - return 0 - else - return 1 - fi -} - append_param() { local s="$1" local v="$2" @@ -154,6 +145,9 @@ openvpn_add_instance() { local security="$4" local up="$5" local down="$6" + local route_up="$7" + local route_pre_down="$8" + local ipchange="$9" local client=$(grep -qEx "client|tls-client" "$dir/$conf" && echo 1) procd_open_instance "$name" @@ -169,12 +163,12 @@ openvpn_add_instance() { ${client:+--ipchange "/usr/libexec/openvpn-hotplug ipchange $name"} \ ${up:+--setenv user_up "$up"} \ ${down:+--setenv user_down "$down"} \ + ${route_up:+--setenv user_route_up "$route_up"} \ + ${route_pre_down:+--setenv user_route_pre_down "$route_pre_down"} \ + ${client:+${ipchange:+--setenv user_ipchange "$ipchange"}} \ --script-security "${security:-2}" \ $(openvpn_get_dev "$name" "$conf") \ $(openvpn_get_credentials "$name" "$conf") - if version_over_5_4; then - procd_append_param command "--mptcp" - fi procd_set_param file "$dir/$conf" procd_set_param term_timeout 15 procd_set_param respawn @@ -184,7 +178,7 @@ openvpn_add_instance() { procd_close_instance } -start_instance() { +start_uci_instance() { local s="$1" config_get config "$s" config @@ -195,18 +189,25 @@ start_instance() { return 1 } - local up down script_security + local up down route_up route_pre_down ipchange script_security config_get up "$s" up config_get down "$s" down + config_get route_up "$s" route_up + config_get route_pre_down "$s" route_pre_down + config_get ipchange "$s" ipchange config_get script_security "$s" script_security [ ! -d "/var/run" ] && mkdir -p "/var/run" if [ ! -z "$config" ]; then append UCI_STARTED "$config" "$LIST_SEP" + [ -n "$script_security" ] || get_openvpn_option "$config" script_security script-security [ -n "$up" ] || get_openvpn_option "$config" up up [ -n "$down" ] || get_openvpn_option "$config" down down - openvpn_add_instance "$s" "${config%/*}" "$config" "$script_security" "$up" "$down" + [ -n "$route_up" ] || get_openvpn_option "$config" route_up route-up + [ -n "$route_pre_down" ] || get_openvpn_option "$config" route_pre_down route-pre-down + [ -n "$ipchange" ] || get_openvpn_option "$config" ipchange ipchange + openvpn_add_instance "$s" "${config%/*}" "$config" "$script_security" "$up" "$down" "$route_up" "$route_pre_down" "$ipchange" return fi @@ -216,7 +217,47 @@ start_instance() { append_params "$s" $OPENVPN_PARAMS append_list "$s" $OPENVPN_LIST - openvpn_add_instance "$s" "/var/etc" "openvpn-$s.conf" "$script_security" "$up" "$down" + openvpn_add_instance "$s" "/var/etc" "openvpn-$s.conf" "$script_security" "$up" "$down" "$route_up" "$route_pre_down" "$ipchange" +} + +start_path_instances() { + local path name + + for path in ${PATH_INSTANCE_DIR}/*.conf; do + [ -f "$path" ] && { + name="${path##*/}" + name="${name%.conf}" + start_path_instance "$name" + } + done +} + +start_path_instance() { + local name="$1" + + local path name up down route_up route_pre_down ipchange + + path="${PATH_INSTANCE_DIR}/${name}.conf" + + # don't start configs again that are already started by uci + if echo "$UCI_STARTED" | grep -qxF "$path"; then + logger -t openvpn "$name.conf already started" + return + fi + + # don't start configs which are set to disabled in uci + if echo "$UCI_DISABLED" | grep -qxF "$path"; then + logger -t openvpn "$name.conf is disabled in /etc/config/openvpn" + return + fi + + get_openvpn_option "$path" up up || up="" + get_openvpn_option "$path" down down || down="" + get_openvpn_option "$path" route_up route-up || route_up="" + get_openvpn_option "$path" route_pre_down route-pre-down || route_pre_down="" + get_openvpn_option "$path" ipchange ipchange || ipchange="" + + openvpn_add_instance "$name" "${path%/*}" "$path" "" "$up" "$down" "$route_up" "$route_pre_down" "$ipchange" } start_service() { @@ -238,31 +279,20 @@ start_service() { config_load 'openvpn' if [ -n "$instance" ]; then - [ "$instance_found" -gt 0 ] || return - start_instance "$instance" + if [ "$instance_found" -gt 0 ]; then + start_uci_instance "$instance" + elif [ -f "${PATH_INSTANCE_DIR}/${instance}.conf" ]; then + start_path_instance "$instance" + fi else - config_foreach start_instance 'openvpn' + config_foreach start_uci_instance 'openvpn' - local path name up down - for path in /etc/openvpn/*.conf; do - if [ -f "$path" ]; then - name="${path##*/}"; name="${name%.conf}" - - # don't start configs again that are already started by uci - if echo "$UCI_STARTED" | grep -qxF "$path"; then - continue - - # don't start configs which are set to disabled in uci - elif echo "$UCI_DISABLED" | grep -qxF "$path"; then - logger -t openvpn "$name.conf is disabled in /etc/config/openvpn" - continue - fi - - get_openvpn_option "$path" up up || up="" - get_openvpn_option "$path" down down || down="" - openvpn_add_instance "$name" "${path%/*}" "$path" "" "$up" "$down" - fi - done + auto="$(uci_get openvpn globals autostart 1)" + if [ "$auto" = "1" ]; then + start_path_instances + else + logger -t openvpn "Autostart for configs in '$PATH_INSTANCE_DIR/*.conf' disabled" + fi fi } From d6996f829bde528b877ad4cba63b56d1d471806d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Mar 2024 09:44:46 +0100 Subject: [PATCH 1445/2059] Fix typo in omr-bypass --- omr-bypass/files/etc/init.d/omr-bypass-nft | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index a0a98819f..12c8fbf28 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -422,24 +422,28 @@ _bypass_proto_without_ndpi() { set firewall.bypass_$proto.match='dest_ip' set firewall.bypass_$proto.family='ipv4' set firewall.bypass_$proto_rule=rule - set firewall.bypass_$proto_rule.name="bypass_$proto" + set firewall.bypass_$proto_rule.name="bypass_$proto_rule" set firewall.bypass_$proto_rule.src='lan' set firewall.bypass_$proto_rule.dest='*' + set firewall.bypass_$proto_rule.family='ipv4' set firewall.bypass_$proto_rule.target='MARK' + set firewall.bypass_$proto_rule.ipset="bypass_$proto" set firewall.bypass_$proto_rule.set_xmark="0x4539${intfid}" commit firewall EOF uci -q batch <<-EOF >/dev/null set firewall.bypass6_$proto=ipset - set firewall.bypass6_$proto.name="bypas6s_$proto" + set firewall.bypass6_$proto.name="bypass6_$proto" set firewall.bypass6_$proto.match='dest_ip' set firewall.bypass6_$proto.family='ipv6' set firewall.bypass6_$proto_rule=rule - set firewall.bypass6_$proto_rule.name="bypass6_$proto" + set firewall.bypass6_$proto_rule.name="bypass6_$proto_rule" set firewall.bypass6_$proto_rule.src='lan' + set firewall.bypass6_$proto_rule.family='ipv6' set firewall.bypass6_$proto_rule.dest='*' set firewall.bypass6_$proto_rule.target='MARK' set firewall.bypass6_$proto_rule.set_xmark="0x6539${intfid}" + set firewall.bypass6_$proto_rule.ipset="bypass6_$proto" commit firewall EOF #if [ "$intfid" != "" ]; then From 572a2ead4a5a12f0aac34d402a8bee7726a111f4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Mar 2024 09:45:25 +0100 Subject: [PATCH 1446/2059] Add all servers IP to bypass list in Shadowsocks-* --- shadowsocks-libev/files/shadowsocks-libev.init-nft | 12 ++++++++++++ shadowsocks-rust/files/shadowsocks-rust.init-nft | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft index e0d6ba774..cf344260b 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init-nft +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -131,6 +131,14 @@ ss_xxx() { ss_rules_cb } +ss_omr_servers() { + add_ip() { + local ip="$1" + [ -n "$ip" ] && [ -z "$(echo \"$ss_redir_servers\" | grep \"$ip\")" ] && ss_redir_servers="$ss_redir_servers $ip" + } + config_list_foreach "$1" ip add_ip +} + ss_rules_cb() { local cfgserver server @@ -296,6 +304,10 @@ start_service() { for cfgtype in ss_local ss_redir ss_server ss_tunnel; do config_foreach ss_xxx "$cfgtype" "$cfgtype" done + if [ -n "$(uci show openmptcprouter)" ]; then + config_load openmptcprouter + config_foreach ss_omr_servers server + fi ss_rules } diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft index 9e708648f..8b51253b9 100755 --- a/shadowsocks-rust/files/shadowsocks-rust.init-nft +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -104,6 +104,14 @@ ss_xxx() { ss_rules_cb } +ss_omr_servers() { + add_ip() { + local ip="$1" + [ -n "$ip" ] && [ -z "$(echo \"$ss_redir_servers\" | grep \"$ip\")" ] && ss_redir_servers="$ss_redir_servers $ip" + } + config_list_foreach "$1" ip add_ip +} + ss_rules_cb() { local cfgserver server @@ -269,6 +277,10 @@ start_service() { for cfgtype in ss_local ss_redir ss_server ss_tunnel; do config_foreach ss_xxx "$cfgtype" "$cfgtype" done + if [ -n "$(uci show openmptcprouter)" ]; then + config_load openmptcprouter + config_foreach ss_omr_servers server + fi ss_rules } From ca31571685249dec1ebe5921a78b875a44da9790 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Mar 2024 09:45:55 +0100 Subject: [PATCH 1447/2059] Update Shadowsocks-rust --- shadowsocks-rust/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile index 10e6146a6..8942c1e89 100644 --- a/shadowsocks-rust/Makefile +++ b/shadowsocks-rust/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=shadowsocks-rust -PKG_VERSION:=1.18.0 -PKG_HASH:=e854743ecef9ab3b371fdcb139e6f4452831b487d449c97c2129abbf4f51e863 +PKG_VERSION:=1.18.1 +PKG_HASH:=c2e1d8838e4578c0a6b0de6e1da00e9ece2d780dc452117fd109bb091e5d106f PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz @@ -48,7 +48,6 @@ define Package/shadowsocks-rust-config SUBMENU:=Web Servers/Proxies TITLE:=shadowsocks-rust config URL:=https://github.com/shadowsocks/shadowsocks-rust - DEPENDS:=$$(RUST_ARCH_DEPENDS) endef From 7437375a2cf96443a208e54ad0ea6994bc2249ce Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Mar 2024 20:37:07 +0100 Subject: [PATCH 1448/2059] Fix float to int --- omr-tracker/files/bin/omr-tracker | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index f75fd2a1a..d277709a8 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -61,11 +61,11 @@ _init_rto() { _update_rto() { if [ -z "$srtt" ]; then srtt=$1 - rttvar=$(($1 / 2)) + rttvar=$(echo "$(($1 / 2))" | cut -d. -f1) else diff=$((srtt - $1)) - rttvar=$(((75 * rttvar + 25 * (diff >= 0 ? diff : -diff)) / 100)) - srtt=$(((75 * srtt + 25 * $1) / 100)) + rttvar=$(echo "$(((75 * rttvar + 25 * (diff >= 0 ? diff : -diff)) / 100))" | cut -d. -f1) + srtt=$(echo "$(((75 * srtt + 25 * $1) / 100))" | cut -d. -f1) fi rto=$((tmp = srtt + 3 * rttvar, tmp > rto_init ? tmp : rto_init)) } From b83c9b985f6f0ca0f2ca92183d1565128de710b9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Mar 2024 20:37:54 +0100 Subject: [PATCH 1449/2059] Fix VPN routes in some case --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index f590d7de6..87d2958f0 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -731,7 +731,7 @@ interface_pending=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter - initcwrwnd="" # An interface in error will never be used in MPTCP -if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then +if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || ([ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$interface_up" != "true" ]); then #if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then #if [ "$interface_available" = "true" ] && ([ "$interface_pending" = "true" ] || [ "$interface_up" = "true" ]) && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then if [ "$interface_available" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then From 2d3eac400f55fcfe4306879edec1e1c0c6ca8442 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 13 Mar 2024 20:38:23 +0100 Subject: [PATCH 1450/2059] Fix metrics on imported backup --- .../files/etc/uci-defaults/1920-omr-network | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 5889afb48..8f15bcdaa 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -79,6 +79,18 @@ config_load network #config_foreach _setup_macvlan_update interface config_foreach _setup_mptcp_handover_to_on interface +_fix_metrics() { + uci -q batch <<-EOF + delete openmptcprouter.$1.metric + delete network.$1.metric + commit openmptcprouter + commit network + EOF +} + +config_load openmptcprouter +config_foreach _fix_metrics interface + if [ "$(uci -q show network.lan | grep multipath)" != "" ]; then exit 0 fi From e801d225ac9ea3d8d55e361188dabaacabf67e32 Mon Sep 17 00:00:00 2001 From: Henning Date: Sun, 17 Mar 2024 19:32:39 +0100 Subject: [PATCH 1451/2059] fix typo in cake autorate delay threshold (#304) --- sqm-autorate/files/usr/share/sqm-autorate/config_template.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh index dcc51c0db..4fe0d2822 100755 --- a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh +++ b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh @@ -79,7 +79,7 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # (adjustment significant at sub 12Mbit/s rates, else negligible) #logger -t "sqm-autorate" "ping for ${INTERFACE} (${ul_if}): $(echo $(/sbin/uci -q get sqm.${INTERFACE}.delay_thr_ms || echo '100'))" #dl_owd_delta_thr_ms=$(echo $(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(echo "$(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | tr -d '\n' 2>/dev/null)+30" | bc) || echo "100")) + "0.1" | bc) # (milliseconds) -dl_owd_delta_thr_mss=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "250") +dl_owd_delta_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "250") ul_owd_delta_thr_ms=${dl_owd_delta_thr_ms} # average owd delta threshold in ms at which maximum adjust_down_bufferbloat is applied From afca835bdc6fddda34415a7ee57fb2d7015d2081 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Mar 2024 15:14:23 +0100 Subject: [PATCH 1452/2059] Force reload OpenVPN OMR when errors --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 1 + 1 file changed, 1 insertion(+) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 87d2958f0..45044312b 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -812,6 +812,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || ([ "$OMR_TRACKER_INTERFACE" != "omrvpn commit openvpn EOF fi + [ -z "VPN_BASE_INTF" ] && VPN_BASE_INTF="omr" /etc/init.d/openvpn restart $VPN_BASE_INTF 2>&1 >/dev/null fi config_load openmptcprouter From 75c9e1e3171e56f2270d311ba5b6e316c6dfcf52 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Mar 2024 15:15:02 +0100 Subject: [PATCH 1453/2059] Faster OMR-Tracker OMRVPN problems detection --- omr-tracker/files/etc/uci-defaults/omr-tracker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/etc/uci-defaults/omr-tracker b/omr-tracker/files/etc/uci-defaults/omr-tracker index 4bfe538c6..1bc6f73d1 100755 --- a/omr-tracker/files/etc/uci-defaults/omr-tracker +++ b/omr-tracker/files/etc/uci-defaults/omr-tracker @@ -118,8 +118,8 @@ if [ "$(uci -q get omr-tracker.defaults.family)" = "" ]; then set omr-tracker.omrvpn.initial_state='online' set omr-tracker.omrvpn.family='ipv4' set omr-tracker.omrvpn.reliability='1' - set omr-tracker.omrvpn.failure_interval='5' - set omr-tracker.omrvpn.tries_up='5' + set omr-tracker.omrvpn.failure_interval='3' + set omr-tracker.omrvpn.tries_up='3' set omr-tracker.omrvpn.count='1' set omr-tracker.proxy.initial_state='online' set omr-tracker.proxy.family='ipv4ipv6' From 2bc7f78810453e0cb4dba7b0012db2dd5154875a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Mar 2024 15:15:56 +0100 Subject: [PATCH 1454/2059] Remove log when check on non existing interface --- omr-tracker/files/bin/omr-tracker-server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index d90cee48c..9792a944a 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -53,7 +53,7 @@ _check_server_intf() { local host=$1 local port=$2 local valid_ip6=$(valid_subnet6 $host) - for intf in $(multipath | awk '/default/ {print $1}'); do + for intf in $(multipath 2>/dev/null | awk '/default/ {print $1}'); do local k=0 while [ "$server_ping" = false ] && [ "$k" -le "$retry" ]; do if [ "$valid_ip6" != "ok" ]; then From ae8236032afa799bd8f4af29e633eb0561269590 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 15 Mar 2024 15:16:20 +0100 Subject: [PATCH 1455/2059] Faster OMR-Tracker OMRVPN problems detection --- openmptcprouter/files/etc/uci-defaults/1990-omr-tracker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker b/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker index 80f104be9..8db468f60 100755 --- a/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker +++ b/openmptcprouter/files/etc/uci-defaults/1990-omr-tracker @@ -19,8 +19,8 @@ if [ "$(uci -q get omr-tracker.omrvpn)" = "" ]; then set omr-tracker.omrvpn.family='ipv4' set omr-tracker.omrvpn.reliability='1' set omr-tracker.omrvpn.count='1' - set omr-tracker.omrvpn.failure_interval='5' - set omr-tracker.omrvpn.tries_up='5 + set omr-tracker.omrvpn.failure_interval='3' + set omr-tracker.omrvpn.tries_up='3 commit omr-tracker EOF fi From a67815595f2af57e15774ddf68bc3999950f9927 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 18 Mar 2024 19:41:49 +0100 Subject: [PATCH 1456/2059] Refresh VPS config shouldn't be need on Master/Backup server switch --- omr-tracker/files/bin/omr-tracker-server | 2 -- 1 file changed, 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 9792a944a..53c3ac4dd 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -168,7 +168,6 @@ _check_master() { add_list openvpn.omr.remote=$ip commit openvpn set openmptcprouter.${name}.current='1' - set openmptcprouter.${name}.get_config='1' commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null @@ -319,7 +318,6 @@ _check_backup() { add_list openvpn.omr.remote=$ip commit openvpn set openmptcprouter.${name}.current='1' - set openmptcprouter.${name}.get_config='1' commit openmptcprouter EOF /etc/init.d/openmptcprouter-vps get_openvpn_key $name >/dev/null 2>/dev/null From fcb98ece42269a4de4bf2d3812eec7feb07ba54a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 19 Mar 2024 14:47:47 +0100 Subject: [PATCH 1457/2059] Fix typo in omr-bypass --- omr-bypass/files/etc/init.d/omr-bypass-nft | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 12c8fbf28..eb8781451 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -615,7 +615,7 @@ _intf_rule() { fi for ipv46 in $protocol; do #echo "ipv46: $ipv46 for $intf" - uci batch <<-EOF + uci -q batch <<-EOF set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_${ipv46}" @@ -707,7 +707,7 @@ _intf_rule() { set network.${intf}_fw_rule6.lookup=${count} EOF fi - uci batch <<-EOF + uci -q batch <<-EOF set dhcp.omr_dst_bypass_$intf=ipset add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4" add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_6" @@ -924,7 +924,7 @@ start_service() { config_load omr-bypass [ -d /proc/net/xt_ndpi/proto ] && config_foreach _bypass_proto dpis config_foreach _bypass_proto_without_ndpi dpis - [ -n "$(uci change network)" ] && { + [ -n "$(uci changes network)" ] && { uci -q commit network /etc/init.d/network reload } From 37ac209817665e105ddfb20e58b3981a201bfde2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Mar 2024 14:02:44 +0100 Subject: [PATCH 1458/2059] Fix omr-bypass interfaces fw rules related to proxy --- omr-bypass/files/etc/init.d/omr-bypass-nft | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index eb8781451..cc8a32a2d 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -713,15 +713,15 @@ _intf_rule() { add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_6" EOF - if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then + if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ]; then config_load shadowsocks-libev config_foreach _intf_rule_ss_rules ss_rules - elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks-rust" ]; then + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks-rust" ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]; then config_load shadowsocks-rust config_foreach _intf_rule_ss_rules ss_rules - elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ]; then + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ] && [ "$(uci -q get v2ray.main.enabled)" = "1" ]; then _intf_rule_v2ray_rules - elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "xray" ]; then + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "xray" ] && [ "$(uci -q get xray.main.enabled)" = "1" ]; then _intf_rule_xray_rules fi From a2af208487457bbbe230869d9ae60751b07e533f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 20 Mar 2024 14:03:22 +0100 Subject: [PATCH 1459/2059] Add DSCP IPv6 rules only if IPv6 is enabled --- omr-dscp/files/etc/init.d/omr-dscp-nft | 60 +++++++++++++++++--------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/omr-dscp/files/etc/init.d/omr-dscp-nft b/omr-dscp/files/etc/init.d/omr-dscp-nft index b1da1b3c7..d31ad37f5 100755 --- a/omr-dscp/files/etc/init.d/omr-dscp-nft +++ b/omr-dscp/files/etc/init.d/omr-dscp-nft @@ -34,17 +34,26 @@ _add_dscp_domains_rules() { uci -q batch <<-EOF set dhcp.omr_dscp_${class}=ipset add_list dhcp.omr_dscp_${class}.name="omr_dscp_${class}_4" - add_list dhcp.omr_dscp_${class}.name="omr_dscp_${class}_6" commit dhcp EOF + if [ "$disableipv6" = "0" ]; then + uci -q batch <<-EOF + add_list dhcp.omr_dscp_${class}.name="omr_dscp_${class}_6" + commit dhcp + EOF + fi uci batch <<-EOF set firewall.omr_dscp_${class}_4=ipset set firewall.omr_dscp_${class}_4.name="omr_dscp_${class}_4" set firewall.omr_dscp_${class}_4.match='dest_ip' - set firewall.omr_dscp_${class}_6=ipset - set firewall.omr_dscp_${class}_6.name="omr_dscp_${class}_6" - set firewall.omr_dscp_${class}_6.match='dest_ip' EOF + if [ "$disableipv6" = "0" ]; then + uci -q batch <<-EOF + set firewall.omr_dscp_${class}_6=ipset + set firewall.omr_dscp_${class}_6.name="omr_dscp_${class}_6" + set firewall.omr_dscp_${class}_6.match='dest_ip' + EOF + fi uci -q batch <<-EOF set firewall.omr_dscp_rule_${class}_4=rule set firewall.omr_dscp_rule_${class}_4.name="omr_dscp_${class}_4" @@ -53,15 +62,20 @@ _add_dscp_domains_rules() { set firewall.omr_dscp_rule_${class}_4.target='DSCP' set firewall.omr_dscp_rule_${class}_4.src='lan' set firewall.omr_dscp_rule_${class}_4.dest='*' - set firewall.omr_dscp_rule_${class}_6=rule - set firewall.omr_dscp_rule_${class}_6.name="omr6_dscp_${class}_6" - set firewall.omr_dscp_rule_${class}_6.ipset="omr_dscp_${class}_6" - set firewall.omr_dscp_rule_${class}_6.target='DSCP' - set firewall.omr_dscp_rule_${class}_6.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" - set firewall.omr_dscp_rule_${class}_6.src='lan' - set firewall.omr_dscp_rule_${class}_6.dest='*' commit firewall EOF + if [ "$disableipv6" = "0" ]; then + uci -q batch <<-EOF + set firewall.omr_dscp_rule_${class}_6=rule + set firewall.omr_dscp_rule_${class}_6.name="omr6_dscp_${class}_6" + set firewall.omr_dscp_rule_${class}_6.ipset="omr_dscp_${class}_6" + set firewall.omr_dscp_rule_${class}_6.target='DSCP' + set firewall.omr_dscp_rule_${class}_6.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" + set firewall.omr_dscp_rule_${class}_6.src='lan' + set firewall.omr_dscp_rule_${class}_6.dest='*' + commit firewall + EOF + fi done } @@ -114,19 +128,23 @@ _add_fwmark_chain() { _ipt4 -N dscp_mark _ipt4 -A PREROUTING -i "$lan_device" -j dscp_mark _ipt4 -A POSTROUTING -j dscp_mark - _ipt6 -N dscp_mark - _ipt6 -A PREROUTING -i "$lan_device" -j dscp_mark - _ipt6 -A POSTROUTING -j dscp_mark + if [ "$disableipv6" = "0" ]; then + _ipt6 -N dscp_mark + _ipt6 -A PREROUTING -i "$lan_device" -j dscp_mark + _ipt6 -A POSTROUTING -j dscp_mark + fi for class in cs4 cs5 cs6 cs7; do # xtun (hex) -> 0x7874756e _ipt4 -A dscp_mark \ -m comment --comment "$class" \ -m dscp --dscp-class "$class" \ -j MARK --set-mark 0x7874756e - _ipt6 -A dscp_mark \ - -m comment --comment "$class" \ - -m dscp --dscp-class "$class" \ - -j MARK --set-mark 0x7874756e + if [ "$disableipv6" = "0" ]; then + _ipt6 -A dscp_mark \ + -m comment --comment "$class" \ + -m dscp --dscp-class "$class" \ + -j MARK --set-mark 0x7874756e + fi done } @@ -147,7 +165,9 @@ _setup_tunnel() { # tun0: cs0 (default) # xtun0: cs6 _ipt4 -A dscp_output -o "tun0" -j DSCP --set-dscp-class cs6 - _ipt6 -A dscp_output -o "tun0" -j DSCP --set-dscp-class cs6 + if [ "$disableipv6" = "0" ]; then + _ipt6 -A dscp_output -o "tun0" -j DSCP --set-dscp-class cs6 + fi } _cleanup() { @@ -165,7 +185,7 @@ _cleanup() { start_service() { # Cleanup _cleanup - + disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" config_load dscp # Add chains _add_dscp_domains_rules From a5ac3e4a0189f40ead62e2f40b4884d10dc04615 Mon Sep 17 00:00:00 2001 From: bdaylik Date: Fri, 22 Mar 2024 16:55:17 +0300 Subject: [PATCH 1460/2059] omr-quota does not work as expected due to a typo in checking json field "months" (#306) * Fix typo on omr-quota vnstat json does not contain a field named "months". The name of the field id "month". This causes this script to not manage quotas. * agree to contribution terms --- contributors/bdaylik.md | 9 +++++++++ omr-quota/files/bin/omr-quota | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 contributors/bdaylik.md diff --git a/contributors/bdaylik.md b/contributors/bdaylik.md new file mode 100644 index 000000000..f83ea7d7c --- /dev/null +++ b/contributors/bdaylik.md @@ -0,0 +1,9 @@ +2024-03-22 + +I hereby agree to the terms of the "OpenMPTCProuter Individual Contributor License Agreement", with MD5 checksum bc827a07eb93611d793ddb7c75083c00. + +I furthermore declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +Baris Daylik https://github.com/bdaylik diff --git a/omr-quota/files/bin/omr-quota b/omr-quota/files/bin/omr-quota index 6b3f11501..65c2a2693 100755 --- a/omr-quota/files/bin/omr-quota +++ b/omr-quota/files/bin/omr-quota @@ -11,8 +11,8 @@ shift # main loop while true; do OMR_QUOTA_REAL_INTERFACE="$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.l3_device')" - rx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.months[-1].rx' | tr -d "\n"` - tx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.months[-1].tx' | tr -d "\n"` + rx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.month[-1].rx' | tr -d "\n"` + tx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.month[-1].tx' | tr -d "\n"` tt=$((rx + tx)) if [ -n "$OMR_QUOTA_RX" ] && [ "$OMR_QUOTA_RX" -gt 0 ] && [ -n "$rx" ] && [ "$OMR_QUOTA_RX" -le "$rx" ]; then if [ "$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.up')" = "true" ]; then From 53183d60f71bfbfb77dd77d1b246953044b3a6d4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Mar 2024 17:46:06 +0100 Subject: [PATCH 1461/2059] Update ModemManager --- modemmanager/Makefile | 38 +- modemmanager/README.md | 19 + modemmanager/files/25-modemmanager-usb | 13 - .../hotplug.d/net}/25-modemmanager-net | 0 .../hotplug.d/tty}/25-modemmanager-tty | 0 .../hotplug.d/wwan}/25-modemmanager-wwan | 0 .../init.d/modemmanager} | 12 +- .../netifd/proto/modemmanager.sh} | 341 +++++++++++++----- .../ModemManager/connection.d}/10-report-down | 14 +- .../files/usr/sbin/ModemManager-monitor | 155 ++++++++ .../files/usr/sbin/ModemManager-wrapper | 5 +- .../share/ModemManager}/modemmanager.common | 242 +++++-------- .../100-ublox-remove-ID_MM_PROCESS-tags.patch | 13 + 13 files changed, 558 insertions(+), 294 deletions(-) delete mode 100644 modemmanager/files/25-modemmanager-usb rename modemmanager/files/{ => etc/hotplug.d/net}/25-modemmanager-net (100%) rename modemmanager/files/{ => etc/hotplug.d/tty}/25-modemmanager-tty (100%) rename modemmanager/files/{ => etc/hotplug.d/wwan}/25-modemmanager-wwan (100%) rename modemmanager/files/{modemmanager.init => etc/init.d/modemmanager} (67%) rename modemmanager/files/{modemmanager.proto => lib/netifd/proto/modemmanager.sh} (68%) rename modemmanager/files/{ => usr/lib/ModemManager/connection.d}/10-report-down (73%) create mode 100644 modemmanager/files/usr/sbin/ModemManager-monitor mode change 100755 => 100644 modemmanager/files/usr/sbin/ModemManager-wrapper rename modemmanager/files/{ => usr/share/ModemManager}/modemmanager.common (54%) create mode 100644 modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch diff --git a/modemmanager/Makefile b/modemmanager/Makefile index d422ec416..f02db006e 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_SOURCE_VERSION:=1.23.2-dev -PKG_RELEASE:=5 +PKG_SOURCE_VERSION:=1.23.4-dev +PKG_RELEASE:=20 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git @@ -64,6 +64,7 @@ MESON_ARGS += \ -Dintrospection=false \ -Dman=false \ -Dbash_completion=false \ + -Dbuiltin_plugins=true \ -Db_lto=true \ -Dmbim=$(if $(CONFIG_MODEMMANAGER_WITH_MBIM),true,false) \ -Dqmi=$(if $(CONFIG_MODEMMANAGER_WITH_QMI),true,false) \ @@ -80,6 +81,8 @@ define Build/InstallDev $(INSTALL_DIR) $(1)/usr/lib/pkgconfig $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ModemManager.pc $(1)/usr/lib/pkgconfig $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mm-glib.pc $(1)/usr/lib/pkgconfig + $(INSTALL_DIR) $(1)/usr/share/dbus-1/interfaces + $(CP) $(PKG_BUILD_DIR)/introspection/org.freedesktop.ModemManager1.* $(1)/usr/share/dbus-1/interfaces endef define Package/modemmanager/install @@ -89,6 +92,7 @@ define Package/modemmanager/install $(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin $(INSTALL_BIN) ./files/usr/sbin/ModemManager-wrapper $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/ModemManager-monitor $(1)/usr/sbin $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin @@ -96,12 +100,9 @@ define Package/modemmanager/install $(INSTALL_DIR) $(1)/usr/lib $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so.* $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/lib/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager - $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager - $(INSTALL_DIR) $(1)/usr/lib/ModemManager/connection.d - $(INSTALL_BIN) ./files/10-report-down $(1)/usr/lib/ModemManager/connection.d + $(INSTALL_BIN) ./files/usr/lib/ModemManager/connection.d/10-report-down \ + $(1)/usr/lib/ModemManager/connection.d $(INSTALL_DIR) $(1)/etc/dbus-1/system.d $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d @@ -110,29 +111,32 @@ define Package/modemmanager/install $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service $(1)/usr/share/dbus-1/system-services $(INSTALL_DIR) $(1)/usr/share/ModemManager - $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager - $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager + $$(if $$(wildcard $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf),$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager,) + $(INSTALL_DATA) ./files/usr/share/ModemManager/modemmanager.common \ + $(1)/usr/share/ModemManager $(INSTALL_DIR) $(1)/usr/share/ModemManager/fcc-unlock.available.d $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/fcc-unlock.available.d/* $(1)/usr/share/ModemManager/fcc-unlock.available.d $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager - - $(INSTALL_DIR) $(1)/etc/hotplug.d/usb - $(INSTALL_DATA) ./files/25-modemmanager-usb $(1)/etc/hotplug.d/usb + $(INSTALL_BIN) ./files/etc/init.d/modemmanager \ + $(1)/etc/init.d/modemmanager $(INSTALL_DIR) $(1)/etc/hotplug.d/net - $(INSTALL_DATA) ./files/25-modemmanager-net $(1)/etc/hotplug.d/net + $(INSTALL_DATA) ./files/etc/hotplug.d/net/25-modemmanager-net \ + $(1)/etc/hotplug.d/net $(INSTALL_DIR) $(1)/etc/hotplug.d/tty - $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty + $(INSTALL_DATA) ./files/etc/hotplug.d/tty/25-modemmanager-tty \ + $(1)/etc/hotplug.d/tty $(INSTALL_DIR) $(1)/etc/hotplug.d/wwan - $(INSTALL_DATA) ./files/25-modemmanager-wwan $(1)/etc/hotplug.d/wwan + $(INSTALL_DATA) ./files/etc/hotplug.d/wwan/25-modemmanager-wwan \ + $(1)/etc/hotplug.d/wwan $(INSTALL_DIR) $(1)/lib/netifd/proto - $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh + $(INSTALL_BIN) ./files/lib/netifd/proto/modemmanager.sh \ + $(1)/lib/netifd/proto endef $(eval $(call BuildPackage,modemmanager)) diff --git a/modemmanager/README.md b/modemmanager/README.md index c9d880ea4..1def1c354 100644 --- a/modemmanager/README.md +++ b/modemmanager/README.md @@ -22,8 +22,11 @@ Once installed, you can configure the 2G/3G/4G modem connections directly in option password 'vodafone' option pincode '7423' option iptype 'ipv4' + option plmn '214001' option lowpower '1' option signalrate '30' + option allow_roaming '1' + option init_epsbearer '' Only 'device' and 'proto' are mandatory options, the remaining ones are all optional. @@ -36,5 +39,21 @@ allowing all protocols. The 'iptype' option supports any of these values: 'ipv4', 'ipv6' or 'ipv4v6'. It will default to 'ipv4' if not given. +The 'plmn' option allows to set the network operator MCCMNC. + The 'signalrate' option set's the signal refresh rate (in seconds) for the device. You can call signal info with command: mmcli -m 0 --signal-get + +If there is no Circuit switch network available, then an initial EPS +bearer must be set, so this could be used during the network registration +process in 4G and 5G network. For this resaon a new configuration option +'init_epsbearer' was added, which could have the following values. +* none: Do not set an initial EPS bearer (default) +* default: Use the configuration option 'apn', 'iptype', 'allowedauth', + 'username' and 'password' for setting the initial EPS bearer. + These are the same options as when establishing a connection. +* custom: This could be used to use diffrent options when establishing a + connection. The options are prefixed with an 'init'. So we have + the following options 'init_apn', 'init_iptype', + 'init_allowedauth', 'init_username' and 'init_password' for + setting the initial EPS bearer. diff --git a/modemmanager/files/25-modemmanager-usb b/modemmanager/files/25-modemmanager-usb deleted file mode 100644 index 93d0bf70a..000000000 --- a/modemmanager/files/25-modemmanager-usb +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# Copyright (C) 2019 Aleksander Morgado - -# We need to process only full USB device removal events, we don't -# want to process specific interface removal events. -[ "$ACTION" = remove ] || exit -[ -z "${INTERFACE}" ] || exit - -# Load common utilities -. /usr/share/ModemManager/modemmanager.common - -mm_clear_modem_wait_status "/sys${DEVPATH}" -mm_cleanup_interface_by_sysfspath "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/etc/hotplug.d/net/25-modemmanager-net similarity index 100% rename from modemmanager/files/25-modemmanager-net rename to modemmanager/files/etc/hotplug.d/net/25-modemmanager-net diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/etc/hotplug.d/tty/25-modemmanager-tty similarity index 100% rename from modemmanager/files/25-modemmanager-tty rename to modemmanager/files/etc/hotplug.d/tty/25-modemmanager-tty diff --git a/modemmanager/files/25-modemmanager-wwan b/modemmanager/files/etc/hotplug.d/wwan/25-modemmanager-wwan similarity index 100% rename from modemmanager/files/25-modemmanager-wwan rename to modemmanager/files/etc/hotplug.d/wwan/25-modemmanager-wwan diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/etc/init.d/modemmanager similarity index 67% rename from modemmanager/files/modemmanager.init rename to modemmanager/files/etc/init.d/modemmanager index 16610bcd8..ccc1953ae 100644 --- a/modemmanager/files/modemmanager.init +++ b/modemmanager/files/etc/init.d/modemmanager @@ -4,6 +4,8 @@ USE_PROCD=1 START=70 +LOG_LEVEL="INFO" + start_service() { # Setup ModemManager service # @@ -19,9 +21,15 @@ start_service() { # wrapper script called '/usr/sbin/ModemManager-wrapper'. # . /usr/share/ModemManager/modemmanager.common - procd_open_instance - procd_set_param command /usr/sbin/ModemManager-wrapper --debug + procd_open_instance "service" + procd_set_param command /usr/sbin/ModemManager-wrapper + procd_append_param command --log-level="$LOG_LEVEL" + [ "$LOG_LEVEL" = "DEBUG" ] && procd_append_param command --debug procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" procd_close_instance + procd_open_instance "monitor" + procd_set_param command /usr/sbin/ModemManager-monitor + procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" + procd_close_instance } diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/lib/netifd/proto/modemmanager.sh similarity index 68% rename from modemmanager/files/modemmanager.proto rename to modemmanager/files/lib/netifd/proto/modemmanager.sh index b8ebce924..67545513d 100644 --- a/modemmanager/files/modemmanager.proto +++ b/modemmanager/files/lib/netifd/proto/modemmanager.sh @@ -8,6 +8,7 @@ . /lib/functions.sh . ../netifd-proto.sh . ./ppp.sh + . /usr/share/ModemManager/modemmanager.common init_proto "$@" } @@ -24,72 +25,6 @@ cdr2mask () echo "${1-0}"."${2-0}"."${3-0}"."${4-0}" } -# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue -# The second argument must be exactly the name of the field to read -# -# Sample output: -# $ mmcli -m 0 -K -# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 -# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 -# modem.generic.manufacturer : Dell Inc. -# modem.generic.model : DW5821e Snapdragon X20 LTE -# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 -# modem.generic.carrier-configuration : GCF -# modem.generic.carrier-configuration-revision : 08E00009 -# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE -# .... -modemmanager_get_field() { - local list=$1 - local field=$2 - local value="" - - [ -z "${list}" ] || [ -z "${field}" ] && return - - # there is always at least a whitespace after each key, and we use that as part of the - # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result - # when grepping for 'modem.generic.state'. - line=$(echo "${list}" | grep "${field} ") - value=$(echo ${line#*:}) - - # not found? - [ -n "${value}" ] || return 2 - - # only print value if set - [ "${value}" != "--" ] && echo "${value}" - return 0 -} - -# build a comma-separated list of values from the list -modemmanager_get_multivalue_field() { - local list=$1 - local field=$2 - local value="" - local length idx item - - [ -z "${list}" ] || [ -z "${field}" ] && return - - length=$(modemmanager_get_field "${list}" "${field}.length") - [ -n "${length}" ] || return 0 - [ "$length" -ge 1 ] || return 0 - - idx=1 - while [ $idx -le "$length" ]; do - item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") - [ -n "${item}" ] && [ "${item}" != "--" ] && { - [ -n "${value}" ] && value="${value}, " - value="${value}${item}" - } - idx=$((idx + 1)) - done - - # nothing built? - [ -n "${value}" ] || return 2 - - # only print value if set - echo "${value}" - return 0 -} - modemmanager_cleanup_connection() { local modemstatus="$1" @@ -323,30 +258,28 @@ modemmanager_connected_method_static_ipv6() { proto_send_update "${interface}" } -modemmanager_disconnected_method_common() { - local interface="$1" - - echo "running disconnection (common)" - proto_notify_error "${interface}" MM_DISCONNECT_IN_PROGRESS - - proto_init_update "*" 0 - proto_send_update "${interface}" -} - proto_modemmanager_init_config() { available=1 no_device=1 - proto_config_add_string device - proto_config_add_string apn - proto_config_add_string 'allowedauth:list(string)' - proto_config_add_string username - proto_config_add_string password - proto_config_add_string pincode - proto_config_add_string iptype - proto_config_add_string plmn - proto_config_add_int signalrate + proto_config_add_string device + proto_config_add_string apn + proto_config_add_string 'allowedauth:list(string)' + proto_config_add_string username + proto_config_add_string password + proto_config_add_string allowedmode + proto_config_add_string preferredmode + proto_config_add_string pincode + proto_config_add_string iptype + proto_config_add_string plmn + proto_config_add_int signalrate proto_config_add_boolean lowpower proto_config_add_boolean allow_roaming + proto_config_add_string init_epsbearer + proto_config_add_string init_iptype + proto_config_add_string 'init_allowedauth:list(string)' + proto_config_add_string init_password + proto_config_add_string init_user + proto_config_add_string init_apn proto_config_add_defaults } @@ -359,18 +292,149 @@ append_param() { connectargs="${connectargs}${param}" } +modemmanager_set_allowed_mode() { + local device="$1" + local interface="$2" + local allowedmode="$3" + + echo "setting allowed mode to '${allowedmode}'" + mmcli --modem="${device}" --set-allowed-modes="${allowedmode}" || { + proto_notify_error "${interface}" MM_INVALID_ALLOWED_MODES_LIST + proto_block_restart "${interface}" + return 1 + } +} + +modemmanager_check_state() { + local device="$1" + local modemstatus="$2" + local pincode="$3" + + local state reason + + state="$(modemmanager_get_field "${modemstatus}" "state")" + state="${state%% *}" + reason="$(modemmanager_get_field "${modemstatus}" "state-failed-reason")" + + case "$state" in + "failed") + case "$reason" in + "sim-missing") + echo "SIM missing" + proto_notify_error "${interface}" MM_FAILED_REASON_SIM_MISSING + proto_block_restart "${interface}" + return 1 + ;; + *) + proto_notify_error "${interface}" MM_FAILED_REASON_UNKNOWN + proto_block_restart "${interface}" + return 1 + ;; + esac + ;; + "locked") + if [ -n "$pincode" ]; then + mmcli --modem="${device}" -i any --pin=${pincode} || { + proto_notify_error "${interface}" MM_PINCODE_WRONG + proto_block_restart "${interface}" + return 1 + } + else + echo "PIN required" + proto_notify_error "${interface}" MM_PINCODE_REQUIRED + proto_block_restart "${interface}" + return 1 + fi + ;; + esac +} + +modemmanager_set_preferred_mode() { + local device="$1" + local interface="$2" + local allowedmode="$3" + local preferredmode="$4" + + [ -z "${preferredmode}" ] && { + echo "no preferred mode configured" + proto_notify_error "${interface}" MM_NO_PREFERRED_MODE_CONFIGURED + proto_block_restart "${interface}" + return 1 + } + + [ -z "${allowedmode}" ] && { + echo "no allowed mode configured" + proto_notify_error "${interface}" MM_NO_ALLOWED_MODE_CONFIGURED + proto_block_restart "${interface}" + return 1 + } + + echo "setting preferred mode to '${preferredmode}' (${allowedmode})" + mmcli --modem="${device}" \ + --set-preferred-mode="${preferredmode}" \ + --set-allowed-modes="${allowedmode}" || { + proto_notify_error "${interface}" MM_FAILED_SETTING_PREFERRED_MODE + proto_block_restart "${interface}" + return 1 + } +} + +modemmanager_init_epsbearer() { + local eps="$1" + local device="$2" + local connectargs="$3" + local apn="$4" + + [ "$eps" != 'none' ] && [ -z "${apn}" ] && { + echo "No '$eps' init eps bearer apn configured" + proto_notify_error "${interface}" MM_INIT_EPS_BEARER_APN_NOT_CONFIGURED + proto_block_restart "${interface}" + return 1 + } + + if [ "$eps" = "none" ]; then + echo "Deleting inital EPS bearer..." + else + echo "Setting '$eps' inital EPS bearer apn to '$apn'..." + fi + + mmcli --modem="${device}" \ + --timeout 120 \ + --3gpp-set-initial-eps-bearer-settings="${connectargs}" || { + proto_notify_error "${interface}" MM_INIT_EPS_BEARER_SET_FAILED + proto_block_restart "${interface}" + return 1 + } + + # Wait here so that the modem can set the init EPS bearer + # for registration + sleep 2 +} + proto_modemmanager_setup() { local interface="$1" local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface local bearermethod_ipv4 bearermethod_ipv6 auth cliauth local operatorname operatorid registration accesstech signalquality + local allowedmode preferredmode - local device apn allowedauth username password pincode iptype plmn metric signalrate allow_roaming + local device apn allowedauth username password pincode + local iptype plmn metric signalrate allow_roaming + + local init_epsbearer + local init_iptype init_allowedauth + local init_password init_user init_apn local address prefix gateway mtu dns1 dns2 - json_get_vars device apn allowedauth username password pincode iptype plmn metric signalrate allow_roaming + json_get_vars device apn allowedauth username password + json_get_vars pincode iptype plmn metric signalrate allow_roaming + json_get_vars allowedmode preferredmode + + json_get_vars init_epsbearer + json_get_vars init_iptype init_allowedauth + json_get_vars init_password init_user init_apn # validate sysfs path given in config [ -n "${device}" ] || { @@ -391,13 +455,97 @@ proto_modemmanager_setup() { } echo "modem available at ${modempath}" + modemmanager_check_state "$device" "${modemstatus}" "$pincode" + [ "$?" -ne "0" ] && return 1 + # always cleanup before attempting a new connection, just in case modemmanager_cleanup_connection "${modemstatus}" - # if allowedauth list given, build option string - for auth in $allowedauth; do - cliauth="${cliauth}${cliauth:+|}$auth" - done + mmcli --modem="${device}" --timeout 120 --enable || { + proto_notify_error "${interface}" MM_MODEM_DISABLED + return 1 + } + + [ -z "${plmn}" ] || { + echo "starting network registraion with plmn '${plmn}'..." + mmcli --modem="${device}" \ + --timeout 120 \ + --3gpp-register-in-operator="${plmn}" || { + proto_notify_error "${interface}" MM_3GPP_OPERATOR_REGISTRATION_FAILED + proto_block_restart "${interface}" + return 1 + } + } + + if [ -z "${allowedmode}" ]; then + modemmanager_set_allowed_mode "$device" "$interface" "any" + else + case "$allowedmode" in + "2g") + modemmanager_set_allowed_mode "$device" \ + "$interface" "2g" + ;; + "3g") + modemmanager_set_allowed_mode "$device" \ + "$interface" "3g" + ;; + "4g") + modemmanager_set_allowed_mode "$device" \ + "$interface" "4g" + ;; + "5g") + modemmanager_set_allowed_mode "$device" \ + "$interface" "5g" + ;; + *) + modemmanager_set_preferred_mode "$device" \ + "$interface" "${allowedmode}" "${preferredmode}" + ;; + esac + # check error for allowed_mode and preferred_mode function call + [ "$?" -ne "0" ] && return 1 + fi + + # set initial eps bearer settings + [ -z "${init_epsbearer}" ] || { + case "$init_epsbearer" in + "none") + connectargs="" + modemmanager_init_epsbearer "none" \ + "$device" "${connectargs}" "$apn" + ;; + "default") + cliauth="" + for auth in $allowedauth; do + cliauth="${cliauth}${cliauth:+|}$auth" + done + connectargs="" + append_param "apn=${apn}" + append_param "${iptype:+ip-type=${iptype}}" + append_param "${cliauth:+allowed-auth=${cliauth}}" + append_param "${username:+user=${username}}" + append_param "${password:+password=${password}}" + modemmanager_init_epsbearer "default" \ + "$device" "${connectargs}" "$apn" + ;; + "custom") + cliauth="" + for auth in $init_allowedauth; do + cliauth="${cliauth}${cliauth:+|}$auth" + done + connectargs="" + append_param "apn=${init_apn}" + append_param "${init_iptype:+ip-type=${init_iptype}}" + append_param "${cliauth:+allowed-auth=${cliauth}}" + append_param "${init_username:+user=${init_username}}" + append_param "${init_password:+password=${init_password}}" + modemmanager_init_epsbearer "custom" \ + "$device" "${connectargs}" "$init_apn" + ;; + esac + # check error for init_epsbearer function call + [ "$?" -ne "0" ] && return 1 + } # setup connect args; APN mandatory (even if it may be empty) echo "starting connection with apn '${apn}'..." @@ -411,7 +559,12 @@ proto_modemmanager_setup() { allow_roaming="yes" fi + cliauth="" + for auth in $allowedauth; do + cliauth="${cliauth}${cliauth:+|}$auth" + done # Append options to 'connectargs' variable + connectargs="" append_param "apn=${apn}" append_param "allow-roaming=${allow_roaming}" append_param "${iptype:+ip-type=${iptype}}" @@ -419,7 +572,6 @@ proto_modemmanager_setup() { append_param "${cliauth:+allowed-auth=${cliauth}}" append_param "${username:+user=${username}}" append_param "${password:+password=${password}}" - append_param "${pincode:+pin=${pincode}}" mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { proto_notify_error "${interface}" MM_CONNECT_FAILED @@ -553,7 +705,6 @@ proto_modemmanager_teardown() { # disconnection handling only requires special treatment in IPv4/PPP [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}" - modemmanager_disconnected_method_common "${interface}" # disconnect mmcli --modem="${device}" --simple-disconnect || @@ -561,14 +712,10 @@ proto_modemmanager_teardown() { # disable mmcli --modem="${device}" --disable - proto_notify_error "${interface}" MM_MODEM_DISABLED # low power, only if requested [ "${lowpower:-0}" -lt 1 ] || mmcli --modem="${device}" --set-power-state-low - - proto_init_update "*" 0 - proto_send_update "$interface" } [ -n "$INCLUDE_ONLY" ] || { diff --git a/modemmanager/files/10-report-down b/modemmanager/files/usr/lib/ModemManager/connection.d/10-report-down similarity index 73% rename from modemmanager/files/10-report-down rename to modemmanager/files/usr/lib/ModemManager/connection.d/10-report-down index a3e5fb4ba..b8feb2677 100644 --- a/modemmanager/files/10-report-down +++ b/modemmanager/files/usr/lib/ModemManager/connection.d/10-report-down @@ -16,9 +16,8 @@ STATE="$4" [ "${STATE}" = "disconnected" ] || exit 0 -. /usr/share/ModemManager/modemmanager.common . /lib/netifd/netifd-proto.sh -INCLUDE_ONLY=1 . /lib/netifd/proto/modemmanager.sh +. /usr/share/ModemManager/modemmanager.common MODEM_STATUS=$(mmcli --modem="${MODEM_PATH}" --output-keyvalue) [ -n "${MODEM_STATUS}" ] || exit 1 @@ -29,7 +28,12 @@ MODEM_DEVICE=$(modemmanager_get_field "${MODEM_STATUS}" "modem.generic.device") CFG=$(mm_get_modem_config "${MODEM_DEVICE}") [ -n "${CFG}" ] || exit 3 -logger -t "modemmanager" "interface ${CFG} (network device ${INTERFACE}) ${STATE}" -proto_init_update $INTERFACE 0 -proto_send_update $CFG +IFUP=$(ifstatus "${CFG}" | jsonfilter -e "@.up") + +[ "${IFUP}" = "true" ] && { + mm_log "info" "Reconnecting '${CFG}' on '${STATE}' event" + ubus call network.interface down "{ 'interface': '${CFG}'}" + ubus call network.interface up "{ 'interface': '${CFG}'}" +} + exit 0 diff --git a/modemmanager/files/usr/sbin/ModemManager-monitor b/modemmanager/files/usr/sbin/ModemManager-monitor new file mode 100644 index 000000000..8a88ab514 --- /dev/null +++ b/modemmanager/files/usr/sbin/ModemManager-monitor @@ -0,0 +1,155 @@ +#!/bin/sh + +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh +. /usr/share/ModemManager/modemmanager.common + +trap_with_arg() { + func="$1" ; shift + for sig ; do + # shellcheck disable=SC2064 + trap "$func $sig" "$sig" + done +} + +func_trap() { + local monitor_cache_line object + + logger "ModemManager-monitor[$$]" "Sending signal ${1} ..." + + # Set all configured logical interfaces to unavailable + while IFS= read -r monitor_cache_line; do + object=$(echo "${monitor_cache_line}" | awk '{print $1}') + mm_monitor_cache_remove "$object" + done < ${MODEMMANAGER_MONITOR_CACHE} + + kill "-${1}" "$CHILD" 2>/dev/null +} + +mm_monitor_get_sysfspath() { + local object="$1" + + # If no monitor cache file, we're done + [ -f "${MODEMMANAGER_MONITOR_CACHE}" ] || return + + awk -v object="${object}" '!/^#/ && $0 ~ object { print $2 }' "${MODEMMANAGER_MONITOR_CACHE}" +} + +mm_monitor_cache_remove() { + local object="$1" + + local device cfg + + device=$(mm_monitor_get_sysfspath "${object}") + + cfg=$(mm_get_modem_config "${device}") + if [ -n "${cfg}" ]; then + mm_log "debug" "interface '${cfg}' set '${device}' state unavailable" + proto_set_available "${cfg}" 0 + fi + + mm_log "debug" "delete object '$object' from monitore cache" + + # On monitor remove event, remove old events from cache + # Also substitute object path '/org/freedesktop/ModemManager1/Modem/' + # all '/' with '\/' to make sed happy with shell expansion + sed -i "/${object//\//\\/}/d" "${MODEMMANAGER_MONITOR_CACHE}" +} + +mm_monitor_cache_add() { + local object="$1" + local modemstatus device sysfspath cfg + + modemstatus="$(mmcli --modem="${object}" --output-keyvalue)" + + device=$(modemmanager_get_field "${modemstatus}" "modem.generic.device") + [ -n "${device}" ] || { + mm_log "err" "No 'device' for object '$object' not found..." + return 1 + } + + sysfspath=$(modemmanager_get_field "${modemstatus}" "modem.generic.physdev") + [ -n "${sysfspath}" ] || { + mm_log "err" "No 'sysfspath' for object '$object' not found..." + return 2 + } + + mm_log "debug" "add object '$object' to monitore cache (device=${device},sysfspath=${sysfspath})" + + # On monitor add event, store event details in cache (if not exists yet) + grep -qs "${sysfspath}" "${MODEMMANAGER_MONITOR_CACHE}" || \ + echo "${object} ${device} ${sysfspath}" >> "${MODEMMANAGER_MONITOR_CACHE}" + + cfg=$(mm_get_modem_config "${device}") + if [ -n "${cfg}" ]; then + mm_log "info" "interface '${cfg}' set '${device}' state available" + proto_set_available "${cfg}" 1 + fi +} + +mm_monitor_cache_del() { + local object="$1" + + mm_monitor_cache_remove "$object" +} + +mm_monitor_cache() { + local line="$1" + local event object modemstatus device pyhsdev + + event="$(echo "$line" | cut -d " " -f 1)" + object="$(echo "$line" | cut -d " " -f 2)" + + case "$event" in + "(+)") + mm_monitor_cache_add "$object" + ;; + "(-)") + mm_monitor_cache_del "$object" + ;; + esac +} + +main() { + + local n=60 + local step=1 + local mmrunning=0 + + trap_with_arg func_trap INT TERM KILL + + mkdir -p "${MODEMMANAGER_RUNDIR}" + chmod 0755 "${MODEMMANAGER_RUNDIR}" + + # Wait for ModemManager to be available in the bus + while [ $n -ge 0 ]; do + sleep $step + mm_log "info" "Checking if ModemManager is available..." + + if ! /usr/bin/mmcli -L >/dev/null 2>&1; then + mm_log "info" "ModemManager not yet available" + else + mmrunning=1 + break + fi + n=$((n-step)) + done + + [ ${mmrunning} -eq 1 ] || { + mm_log "error" "couldn't report initial kernel events: ModemManager not running" + return + } + + /usr/bin/mmcli -M | { + local line + while read -r line; do + mm_log "debug" "Monitor cache line: ${line}" + mm_monitor_cache "$line" + done + } & + CHILD="$!" + + wait $CHILD +} + +main "$@" diff --git a/modemmanager/files/usr/sbin/ModemManager-wrapper b/modemmanager/files/usr/sbin/ModemManager-wrapper old mode 100755 new mode 100644 index e06d943e9..b0f36c267 --- a/modemmanager/files/usr/sbin/ModemManager-wrapper +++ b/modemmanager/files/usr/sbin/ModemManager-wrapper @@ -1,5 +1,7 @@ #!/bin/sh +. /usr/share/ModemManager/modemmanager.common + trap_with_arg() { func="$1" ; shift for sig ; do @@ -14,8 +16,6 @@ func_trap() { } main() { - . /usr/share/ModemManager/modemmanager.common - trap_with_arg func_trap INT TERM KILL mkdir -p "${MODEMMANAGER_RUNDIR}" @@ -27,7 +27,6 @@ main() { mm_report_events_from_cache wait "$CHILD" - mm_cleanup_interfaces } main "$@" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/usr/share/ModemManager/modemmanager.common similarity index 54% rename from modemmanager/files/modemmanager.common rename to modemmanager/files/usr/share/ModemManager/modemmanager.common index e47e0e025..0315673d8 100644 --- a/modemmanager/files/modemmanager.common +++ b/modemmanager/files/usr/share/ModemManager/modemmanager.common @@ -6,7 +6,6 @@ . /lib/functions.sh . /lib/netifd/netifd-proto.sh -INCLUDE_ONLY=1 . /lib/netifd/proto/modemmanager.sh ################################################################################ # Runtime state @@ -14,7 +13,7 @@ INCLUDE_ONLY=1 . /lib/netifd/proto/modemmanager.sh MODEMMANAGER_RUNDIR="/var/run/modemmanager" MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid" MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache" -MODEMMANAGER_SYSFS_CACHE="${MODEMMANAGER_RUNDIR}/sysfs.cache" +MODEMMANAGER_MONITOR_CACHE="${MODEMMANAGER_RUNDIR}/monitor.cache" MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" ################################################################################ @@ -22,7 +21,9 @@ MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" mm_log() { local level="$1"; shift - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && logger -p "daemon.${level}" -t "ModemManager[$$]" "hotplug: $*" + + [ "${level}" = "debug" ] && return + logger -p "daemon.${level}" -t "ModemManager[$$]" "hotplug: $*" } ################################################################################ @@ -93,48 +94,6 @@ mm_untrack_cdcwdm() { echo "${cdcwdm}" } -################################################################################ -# ModemManager needs some time from the ports being added until a modem object -# is exposed in DBus. With the logic here we do an explicit wait of N seconds -# for ModemManager to expose the new modem object, making sure that the wait is -# unique per device (i.e. per physical device sysfs path). - -# Gets the modem wait status as retrieved from the cache -mm_get_modem_wait_status() { - local sysfspath="$1" - - # If no sysfs cache file, we're done - [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return - - # Get status of the sysfs path - awk -v sysfspath="${sysfspath}" '!/^#/ && $0 ~ sysfspath { print $2 }' "${MODEMMANAGER_SYSFS_CACHE}" -} - -# Clear the modem wait status from the cache, if any -mm_clear_modem_wait_status() { - local sysfspath="$1" - - local escaped_sysfspath - - [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] && { - # escape '/', '\' and '&' for sed... - escaped_sysfspath=$(echo "$sysfspath" | sed -e 's/[\/&]/\\&/g') - sed -i "/${escaped_sysfspath}/d" "${MODEMMANAGER_SYSFS_CACHE}" - } -} - -# Sets the modem wait status in the cache -mm_set_modem_wait_status() { - local sysfspath="$1" - local status="$2" - - # Remove sysfs line before adding the new one with the new state - mm_clear_modem_wait_status "${sysfspath}" - - # Add the new status - echo "${sysfspath} ${status}" >> "${MODEMMANAGER_SYSFS_CACHE}" -} - # Callback for config_foreach() mm_get_modem_config_foreach_cb() { local cfg="$1" @@ -156,112 +115,6 @@ mm_get_modem_config() { config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}" } -# Wait for a modem in the specified sysfspath -mm_wait_for_modem() { - local cfg="$1" - local sysfspath="$2" - - # TODO: config max wait - local n=45 - local step=5 - - while [ $n -ge 0 ]; do - [ -d "${sysfspath}" ] || { - mm_log "error" "ignoring modem detection request: no device at ${sysfspath}" - proto_set_available "${cfg}" 0 - return 1 - } - - # Check if the modem exists at the given sysfs path - if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 - then - mm_log "error" "modem not detected at sysfs path" - else - mm_log "info" "modem exported successfully at ${sysfspath}" - mm_log "info" "setting interface '${cfg}' as available" - proto_set_available "${cfg}" 1 - return 0 - fi - - sleep $step - n=$((n-step)) - done - - mm_log "error" "timed out waiting for the modem to get exported at ${sysfspath}" - proto_set_available "${cfg}" 0 - return 2 -} - -mm_report_modem_wait() { - local sysfspath=$1 - - local parent_sysfspath status - - parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") - [ -n "${parent_sysfspath}" ] || { - mm_log "error" "parent device sysfspath not found" - return - } - - status=$(mm_get_modem_wait_status "${parent_sysfspath}") - case "${status}" in - "") - local cfg - - cfg=$(mm_get_modem_config "${parent_sysfspath}") - if [ -n "${cfg}" ]; then - mm_log "info" "interface '${cfg}' is set to configure device '${parent_sysfspath}'" - mm_log "info" "now waiting for modem at sysfs path ${parent_sysfspath}" - mm_set_modem_wait_status "${parent_sysfspath}" "processed" - # Launch subshell for the explicit wait - ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & - else - mm_log "info" "no need to wait for modem at sysfs path ${parent_sysfspath}" - mm_set_modem_wait_status "${parent_sysfspath}" "ignored" - fi - ;; - "processed") - mm_log "info" "already waiting for modem at sysfs path ${parent_sysfspath}" - ;; - "ignored") - ;; - *) - mm_log "error" "unknown status read for device at sysfs path ${parent_sysfspath}" - ;; - esac -} - -################################################################################ -# Cleanup interfaces - -mm_cleanup_interfaces() { - local sysfs_path status - - # Do nothing if there is no sysfs cache - [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return - - while IFS= read -r sysfs_cache_line; do - sysfs_path=$(echo "${sysfs_cache_line}" | awk '{print $1}') - status=$(echo "${sysfs_cache_line}" | awk '{print $2}') - - if [ "${status}" = "processed" ]; then - mm_log "debug" "call cleanup for: ${sysfs_path}" - mm_cleanup_interface_by_sysfspath "${sysfs_path}" - fi - done < ${MODEMMANAGER_SYSFS_CACHE} -} - -mm_cleanup_interface_by_sysfspath() { - local dev="$1" - - local cfg - cfg=$(mm_get_modem_config "$dev") - [ -n "${cfg}" ] || return - - mm_log "info" "setting interface '$cfg' as unavailable" - proto_set_available "${cfg}" 0 -} - ################################################################################ # Event reporting @@ -277,7 +130,20 @@ mm_report_event() { virtual="$(echo "$sysfspath" | cut -d'/' -f4)" [ "$virtual" = "virtual" ] && { mm_log "debug" "sysfspath is a virtual device ($sysfspath)" - return + case "$name" in + "qmapmux"*) + mm_log "debug" "rmnet netdevice $name" + ;; + "qmimux"*) + mm_log "debug" "qmi_wwan qmap netdevice $name" + ;; + "mbimmux"*) + mm_log "debug" "mbim vlan netdevice $name" + ;; + *) + return + ;; + esac } # Track/untrack events in cache @@ -296,13 +162,9 @@ mm_report_event() { # Report the event mm_log "debug" "Report event: action=${action}, name=${name}, subsystem=${subsystem}" result=$(mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 2>&1) - if [ "$?" -eq "0" ]; then - # Wait for added modem if a sysfspath is given - [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" - else + if [ "$?" -ne "0" ]; then mm_log "error" "Couldn't report kernel event: ${result}" fi - } mm_report_event_from_cache_line() { @@ -351,3 +213,69 @@ mm_report_events_from_cache() { mm_report_event_from_cache_line "${event_line}" done < ${MODEMMANAGER_EVENTS_CACHE} } + +# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue +# The second argument must be exactly the name of the field to read +# +# Sample output: +# $ mmcli -m 0 -K +# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 +# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 +# modem.generic.manufacturer : Dell Inc. +# modem.generic.model : DW5821e Snapdragon X20 LTE +# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 +# modem.generic.carrier-configuration : GCF +# modem.generic.carrier-configuration-revision : 08E00009 +# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE +# .... +modemmanager_get_field() { + local list=$1 + local field=$2 + local value="" + + [ -z "${list}" ] || [ -z "${field}" ] && return + + # there is always at least a whitespace after each key, and we use that as part of the + # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result + # when grepping for 'modem.generic.state'. + line=$(echo "${list}" | grep "${field} ") + value=$(echo ${line#*:}) + + # not found? + [ -n "${value}" ] || return 2 + + # only print value if set + [ "${value}" != "--" ] && echo "${value}" + return 0 +} + +# build a comma-separated list of values from the list +modemmanager_get_multivalue_field() { + local list=$1 + local field=$2 + local value="" + local length idx item + + [ -z "${list}" ] || [ -z "${field}" ] && return + + length=$(modemmanager_get_field "${list}" "${field}.length") + [ -n "${length}" ] || return 0 + [ "$length" -ge 1 ] || return 0 + + idx=1 + while [ $idx -le "$length" ]; do + item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") + [ -n "${item}" ] && [ "${item}" != "--" ] && { + [ -n "${value}" ] && value="${value}, " + value="${value}${item}" + } + idx=$((idx + 1)) + done + + # nothing built? + [ -n "${value}" ] || return 2 + + # only print value if set + echo "${value}" + return 0 +} diff --git a/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch b/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch new file mode 100644 index 000000000..d1f67537b --- /dev/null +++ b/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch @@ -0,0 +1,13 @@ +--- a/src/plugins/ublox/77-mm-ublox-port-types.rules ++++ b/src/plugins/ublox/77-mm-ublox-port-types.rules +@@ -88,8 +88,8 @@ SUBSYSTEMS=="usb", ATTRS{bInterfaceNumbe + # ttyUSB2 (if #2): secondary + # ttyUSB3 (if #3): unused (ignore) + ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" +-ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" +-ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" ++ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" ++ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" + ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" + + LABEL="mm_ublox_port_types_end" From d05eb63a52c3ca7a8e82d7c0219340bf8c079f4c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Mar 2024 17:46:35 +0100 Subject: [PATCH 1462/2059] Delete old network rules in omr-bypass --- omr-bypass/files/etc/init.d/omr-bypass-nft | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index cc8a32a2d..014e1dabc 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -825,6 +825,12 @@ _delete_firewall_rules() { } } +_delete_network_rules() { + [ -n "$(echo $1 | grep fw_rule)" ] && { + uci -q delete network.$1 + } +} + boot() { BOOT=1 start "$@" @@ -841,6 +847,9 @@ start_service() { config_foreach _delete_firewall_rules rule config_foreach _delete_firewall_rules ipset #uci -q commit firewall + config_load network + config_foreach _delete_network_rules rule + #uci -q commit network add_domains="false" @@ -931,6 +940,8 @@ start_service() { uci -q commit omr-bypass uci -q commit dhcp uci -q commit firewall + uci -q commit network + /etc/init.d/network reload fw4 -q restart [ -z "$RELOAD" ] && [ "$add_domains" = "true" ] && { From ced4692b61aafc206524d9984f9d3533040b5cdf Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Mar 2024 17:48:48 +0100 Subject: [PATCH 1463/2059] Fix inital QNAP 301w network config --- .../files/etc/uci-defaults/1920-omr-network | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network index 8f15bcdaa..44354545c 100755 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ b/openmptcprouter/files/etc/uci-defaults/1920-omr-network @@ -104,8 +104,10 @@ elif [ -d /sys/class/net/lan0 -o -n "$(ip link | grep ' lan0')" ] && [ -d /sys/c lanif="wan" elif [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/class/net/wan -o -n "$(ip link | grep ' wan@')" -o -n "$(ip link | grep ' wan:')" ]; then lanif="wan" -elif [ -d /sys/class/net/lan ] || [ -n "$(ip link | grep ' lan')" ]; then +elif [ -d /sys/class/net/lan ] || [ -n "$(ip link | grep ' lan:')" ]; then lanif="lan" +elif [ -d /sys/class/net/lan1] || [ -n "$(ip link | grep ' lan1:')" ]; then + lanif="lan1" elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ "$(cat /etc/board.json | jsonfilter -q -e '@.model.platform' | tr -d '\n')" = "RUTX" ]; then lanif="eth1" uci -q batch <<-EOF @@ -288,7 +290,7 @@ if [ "$(uci -q show network.wan1 | grep multipath)" = "" ] && [ -z "$(uci -q get _setup_macvlan wan1 _setup_macvlan wan2 fi - elif [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/class/net/lan2 -o -n "$(ip link | grep ' lan2')" ] && [ -d /sys/class/net/lan3 -o -n "$(ip link | grep ' lan3')" ] && [ -d /sys/class/net/lan4 -o -n "$(ip link | grep ' lan4')" ]; then + elif [ "$lanif" != "lan1" ] && [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/class/net/lan2 -o -n "$(ip link | grep ' lan2')" ] && [ -d /sys/class/net/lan3 -o -n "$(ip link | grep ' lan3')" ] && [ -d /sys/class/net/lan4 -o -n "$(ip link | grep ' lan4')" ]; then _setup_wan_interface wan1 lan1 master _setup_wan_interface wan2 lan2 on _macaddr=$(uci -q get "network.lan1.macaddr") @@ -358,6 +360,14 @@ if [ "$(uci -q show network.wan1 | grep multipath)" = "" ] && [ -z "$(uci -q get elif [ -d /sys/class/net/eth0.1 ] && [ -d /sys/class/net/eth0.2 ]; then _setup_wan_interface wan1 eth0.1 master _setup_wan_interface wan2 eth0.2 on + elif [ "$lanif" = "lan1" ] && [ -d /sys/class/net/lan2 -o -n "$(ip link | grep ' lan2')" ] && [ -d /sys/class/net/lan3 -o -n "$(ip link | grep ' lan3')" ] && [ -d /sys/class/net/lan4 -o -n "$(ip link | grep ' lan4')" ]; then + _setup_wan_interface wan1 lan2 master + _setup_wan_interface wan2 lan3 on + _setup_wan_interface wan3 lan4 on + if [ -d /sys/class/net/10g-1 ] && [ -d /sys/class/net/10g-2 ]; then + _setup_wan_interface wan3 10g-1 on + _setup_wan_interface wan3 10g-2 on + fi else _setup_wan_interface wan1 eth0 master macvlan _setup_wan_interface wan2 eth0 on macvlan From 1de5ac37b8087fc1ede3d9802ad8d61f0ef2b67e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 21 Mar 2024 17:49:11 +0100 Subject: [PATCH 1464/2059] Remove modemamanger patch --- .../100-ublox-remove-ID_MM_PROCESS-tags.patch | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch diff --git a/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch b/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch deleted file mode 100644 index d1f67537b..000000000 --- a/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/src/plugins/ublox/77-mm-ublox-port-types.rules -+++ b/src/plugins/ublox/77-mm-ublox-port-types.rules -@@ -88,8 +88,8 @@ SUBSYSTEMS=="usb", ATTRS{bInterfaceNumbe - # ttyUSB2 (if #2): secondary - # ttyUSB3 (if #3): unused (ignore) - ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" --ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" --ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" -+ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -+ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" - - LABEL="mm_ublox_port_types_end" From a3f974749ef7575a9d90fe1047cb7d57fadbbf44 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 22 Mar 2024 14:57:22 +0100 Subject: [PATCH 1465/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3218 --- openmptcprouter/files/etc/init.d/vnstat_backup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/vnstat_backup b/openmptcprouter/files/etc/init.d/vnstat_backup index 3a1cf5112..02e9be314 100755 --- a/openmptcprouter/files/etc/init.d/vnstat_backup +++ b/openmptcprouter/files/etc/init.d/vnstat_backup @@ -10,7 +10,7 @@ START=98 STOP=10 vnstat_option() { - sed -ne "s/^[[:space:]]*$1[[:space:]]*['\"]\([^'\"]*\)['\"].*/\1/p" /etc/vnstat.conf + sed -ne "s/^[;]*$1[[:space:]]*['\"]\([^'\"]*\)['\"].*/\1/p" /etc/vnstat.conf } BACKUP_FILE=/etc/vnstat_backup.tar.gz From f44a31a46acf15e2b6feb3e03621176fa3bcfce3 Mon Sep 17 00:00:00 2001 From: bdaylik Date: Mon, 25 Mar 2024 13:11:43 +0300 Subject: [PATCH 1466/2059] update omr-quota to compare in kbits as mentioned in GUI (#308) vnstat by default reports the values in bits, however the OMR UI configuration asks values to be given in kbits. This commit fixes the omr-quota script by converting vnstat output to kbits. --- omr-quota/files/bin/omr-quota | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/omr-quota/files/bin/omr-quota b/omr-quota/files/bin/omr-quota index 65c2a2693..61198c9fb 100755 --- a/omr-quota/files/bin/omr-quota +++ b/omr-quota/files/bin/omr-quota @@ -11,8 +11,10 @@ shift # main loop while true; do OMR_QUOTA_REAL_INTERFACE="$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.l3_device')" - rx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.month[-1].rx' | tr -d "\n"` - tx=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.month[-1].tx' | tr -d "\n"` + rx_bits=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.month[-1].rx' | tr -d "\n"` + tx_bits=`vnstat -i $OMR_QUOTA_REAL_INTERFACE --json | jsonfilter -q -e '@.interfaces[0].traffic.month[-1].tx' | tr -d "\n"` + rx=$((rx_bits/1024)) + tx=$((tx_bits/1024)) tt=$((rx + tx)) if [ -n "$OMR_QUOTA_RX" ] && [ "$OMR_QUOTA_RX" -gt 0 ] && [ -n "$rx" ] && [ "$OMR_QUOTA_RX" -le "$rx" ]; then if [ "$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.up')" = "true" ]; then From 605be52f28247fe1d4db48a585c625fb014e7fc1 Mon Sep 17 00:00:00 2001 From: bdaylik Date: Mon, 25 Mar 2024 13:12:38 +0300 Subject: [PATCH 1467/2059] update vnstat_backup service to use default DatabaseDir if not specified (#307) --- openmptcprouter/files/etc/init.d/vnstat_backup | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/vnstat_backup b/openmptcprouter/files/etc/init.d/vnstat_backup index 02e9be314..37e2b4ebf 100755 --- a/openmptcprouter/files/etc/init.d/vnstat_backup +++ b/openmptcprouter/files/etc/init.d/vnstat_backup @@ -10,12 +10,13 @@ START=98 STOP=10 vnstat_option() { - sed -ne "s/^[;]*$1[[:space:]]*['\"]\([^'\"]*\)['\"].*/\1/p" /etc/vnstat.conf + sed -ne "s/^[[:space:]]*$1[[:space:]]*['\"]\([^'\"]*\)['\"].*/\1/p" /etc/vnstat.conf } BACKUP_FILE=/etc/vnstat_backup.tar.gz LOGGER_TAG=vnstat_backup VNSTAT_DIR="$(vnstat_option DatabaseDir)" +[ -n "$VNSTAT_DIR" ] || VNSTAT_DIR="/var/lib/vnstat" _chk_omrquota() { config_get enabled $1 enabled From bb483535fa8167c2b201b6ddeff4525a4787d3a3 Mon Sep 17 00:00:00 2001 From: bdaylik Date: Mon, 25 Mar 2024 14:14:55 +0300 Subject: [PATCH 1468/2059] update omr-quota to up the interface when its usage is below threshold (#309) Existing condition for the upping the interface asks for all 3 checks to have positive values (RX, TX and TT). However this is not necessary as some can be set to 0 to disable the check. This modification makes sure that if the above checks for RX, TX and TT values have failed, thus the usage is still below the set quota, the interface is set to be up. Thanks to this modification its possible to set only one check positive (e.g. TT) and let the script automatically down and up the interface as expected. --- omr-quota/files/bin/omr-quota | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-quota/files/bin/omr-quota b/omr-quota/files/bin/omr-quota index 61198c9fb..b615ea8f6 100755 --- a/omr-quota/files/bin/omr-quota +++ b/omr-quota/files/bin/omr-quota @@ -31,7 +31,7 @@ while true; do logger -t "OMR-QUOTA" "Set interface $OMR_QUOTA_INTERFACE down, RX+TX quota reached" ifdown $OMR_QUOTA_INTERFACE fi - elif [ -n "$OMR_QUOTA_RX" ] && [ "$OMR_QUOTA_RX" -gt 0 ] && [ -n "$OMR_QUOTA_TX" ] && [ "$OMR_QUOTA_TX" -gt 0 ] && [ -n "$OMR_QUOTA_TT" ] && [ "$OMR_QUOTA_TT" -gt 0 ] && [ "$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.up')" = "false" ]; then + elif [ "$(ifstatus $OMR_QUOTA_INTERFACE | jsonfilter -e '@.up')" = "false" ]; then logger -t "OMR-QUOTA" "Set interface $OMR_QUOTA_INTERFACE up" ifup $OMR_QUOTA_INTERFACE fi From 4be2308e8b1920a0884c81895dc7f84a9b5bba8c Mon Sep 17 00:00:00 2001 From: bdaylik Date: Mon, 25 Mar 2024 14:16:08 +0300 Subject: [PATCH 1469/2059] update vnstat_backup service to start before and end after the vnstat service (#310) Currently vnstat_backup service runs after vnstat runs and overwrites newly initialized database of vnstat causing it to crash and restart. Moving vnstat_backup service before vnstat lets it create the database before vnstat runs. This allows an error free operation. --- openmptcprouter/files/etc/init.d/vnstat_backup | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/vnstat_backup b/openmptcprouter/files/etc/init.d/vnstat_backup index 37e2b4ebf..1434285d3 100755 --- a/openmptcprouter/files/etc/init.d/vnstat_backup +++ b/openmptcprouter/files/etc/init.d/vnstat_backup @@ -6,8 +6,8 @@ EXTRA_HELP=< Date: Mon, 25 Mar 2024 11:13:21 +0100 Subject: [PATCH 1470/2059] Change proxy firewall priority --- shadowsocks-libev/files/nft-rules/chain.uc | 2 +- shadowsocks-rust/files/nft-rules/chain.uc | 2 +- v2ray-core/files/usr/share/v2ray-rules/chain.uc | 2 +- xray-core/files/usr/share/xray-rules/chain.uc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shadowsocks-libev/files/nft-rules/chain.uc b/shadowsocks-libev/files/nft-rules/chain.uc index 3b2cc0813..9da09f27a 100644 --- a/shadowsocks-libev/files/nft-rules/chain.uc +++ b/shadowsocks-libev/files/nft-rules/chain.uc @@ -43,7 +43,7 @@ let type, hook, priority, redir_port; if (proto == "tcp") { type = "nat"; hook = "prerouting"; - priority = -1; + priority = 1; redir_port = o_redir_tcp_port; } else if (proto == "udp") { type = "filter"; diff --git a/shadowsocks-rust/files/nft-rules/chain.uc b/shadowsocks-rust/files/nft-rules/chain.uc index 3b2cc0813..9da09f27a 100644 --- a/shadowsocks-rust/files/nft-rules/chain.uc +++ b/shadowsocks-rust/files/nft-rules/chain.uc @@ -43,7 +43,7 @@ let type, hook, priority, redir_port; if (proto == "tcp") { type = "nat"; hook = "prerouting"; - priority = -1; + priority = 1; redir_port = o_redir_tcp_port; } else if (proto == "udp") { type = "filter"; diff --git a/v2ray-core/files/usr/share/v2ray-rules/chain.uc b/v2ray-core/files/usr/share/v2ray-rules/chain.uc index c0855c674..34075d9c8 100644 --- a/v2ray-core/files/usr/share/v2ray-rules/chain.uc +++ b/v2ray-core/files/usr/share/v2ray-rules/chain.uc @@ -43,7 +43,7 @@ let type, hook, priority, redir_port; if (proto == "tcp") { type = "nat"; hook = "prerouting"; - priority = -1; + priority = 1; redir_port = o_redir_tcp_port; } else if (proto == "udp") { type = "filter"; diff --git a/xray-core/files/usr/share/xray-rules/chain.uc b/xray-core/files/usr/share/xray-rules/chain.uc index cb46ba5e8..be456b014 100644 --- a/xray-core/files/usr/share/xray-rules/chain.uc +++ b/xray-core/files/usr/share/xray-rules/chain.uc @@ -43,7 +43,7 @@ let type, hook, priority, redir_port; if (proto == "tcp") { type = "nat"; hook = "prerouting"; - priority = -1; + priority = 1; redir_port = o_redir_tcp_port; } else if (proto == "udp") { type = "filter"; From 40bcdb46a8da550c343fdb6e74f4d1e27d337c2e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 27 Mar 2024 19:28:10 +0100 Subject: [PATCH 1471/2059] Change max-width of status page --- .../luci-static/resources/openmptcprouter/css/wanstatus.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css index 20019851b..b4a8d7a02 100644 --- a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css +++ b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css @@ -1,6 +1,6 @@ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */ - max-width: 1600px; + max-width: 1500px; } #interface_field { padding: 12px 20px 20px 20px; @@ -33,6 +33,7 @@ /* Mwan3 ligthed CSS */ #interface_field { padding: 0px; + max-width: 1200px; } #interface_field td { padding: 0px; From 9f4251b59b2dfe9b33c55ac169cdfb35867e507b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 27 Mar 2024 19:50:24 +0100 Subject: [PATCH 1472/2059] Should speedup USB --- .../files/etc/hotplug.d/net/10-usb | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 openmptcprouter/files/etc/hotplug.d/net/10-usb diff --git a/openmptcprouter/files/etc/hotplug.d/net/10-usb b/openmptcprouter/files/etc/hotplug.d/net/10-usb new file mode 100755 index 000000000..e5de621ba --- /dev/null +++ b/openmptcprouter/files/etc/hotplug.d/net/10-usb @@ -0,0 +1,34 @@ +#!/bin/sh +# Come from https://github.com/ofmodemsandmen/RooterSource/blob/main/package/rooter/ext-rooter-basic/files/etc/hotplug.d/net/10-usb + +log() { + logger -t "NET" "$@" +} + +NP=$(grep -c ^processor /proc/cpuinfo ) +if [ "$NP" -gt 1 ]; then + log "hotplug (iface): action='$ACTION' interface='$INTERFACE'" + if [ "$ACTION" = "add" ]; then + IFACE=$(ls /sys/class/net) + for i in ${IFACE}; do + ethtool -K $i gro on 2>/dev/null + if [[ -e /sys/class/net/$i/queues/rx-0/rps_cpus ]]; then + echo f > /sys/class/net/$i/queues/rx-0/rps_cpus + fi + done + + INTERRUPT=$(ls /proc/irq/ | sed '/default/d') + USB3_NUMBER=$(grep xhci /proc/interrupts | awk -F: '{print $1}' | sed 's/^ //') + + for i in ${INTERRUPT}; do + if [[ $i = ${USB3_NUMBER} ]]; then + echo f > /proc/irq/$i/smp_affinity 2>/dev/null + else + echo e > /proc/irq/$i/smp_affinity 2>/dev/null + fi + done + + #inter=$(grep . /sys/class/net/$INTERFACE/queues/?x-0/?ps_cpus) + #log "$inter" + fi +fi \ No newline at end of file From b6bc58db145b34bcdc09020664fc7d673c27652b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Mar 2024 18:35:39 +0100 Subject: [PATCH 1473/2059] Fix MPTCP mode changes --- mptcp/files/etc/init.d/mptcp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index bf0f967e9..6a8acac52 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -410,15 +410,14 @@ interface_multipath_settings() { fi if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then - multipath "$iface" "off" if ([ "$mode" = "master" ] || [ "$mode" = "on" ]) && [ -z "$(multipath $iface | grep default)" ]; then - logger -t "MPTCP" "Set $iface to $mode" + logger -t "MPTCP" "Set $iface to $mode from $(multipath $iface)" multipath "$iface" "on" - elif [ "$mode" = "off" ] && [ -z "$(multipath $iface | grep deactivated)" ]; then - logger -t "MPTCP" "Set $iface to $mode" + elif ([ "$mode" = "off" ] || [ -z "$mode" ]) && [ -z "$(multipath $iface | grep deactivated)" ]; then + logger -t "MPTCP" "Set $iface to $mode from $(multipath $iface)" multipath "$iface" "$mode" elif [ "$mode" = "backup" ] && [ -z "$(multipath $iface | grep backup)" ]; then - logger -t "MPTCP" "Set $iface to $mode" + logger -t "MPTCP" "Set $iface to $mode from $(multipath $iface)" multipath "$iface" "$mode" fi fi From 5c48937caf57623c89b416a1517b756a92ef68e9 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Mar 2024 18:36:37 +0100 Subject: [PATCH 1474/2059] Add log on z8102 script start --- z8102/files/etc/init.d/z8102 | 1 + 1 file changed, 1 insertion(+) diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index fc8aad8f0..fd2e5d75e 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -11,6 +11,7 @@ log() { start_service() { + log "Enable SIMs and reboot modems..." # sim 1 #i=461 #echo $i > /sys/class/gpio/export From ac1632cc85d1028b2bbbe787df0f29a2743854ed Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Mar 2024 18:37:25 +0100 Subject: [PATCH 1475/2059] Start z8102 earlier --- z8102/files/etc/init.d/z8102 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index fd2e5d75e..a5ac27071 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -2,7 +2,7 @@ # Copyright (C) 2013 OpenWrt.org # Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter -START=58 +START=05 USE_PROCD=1 log() { From 71336e9527b1b401ddd46fc8901cd8f9eee7c1b4 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 28 Mar 2024 18:38:19 +0100 Subject: [PATCH 1476/2059] Add possibility to run script to all OMR-Tracker --- omr-tracker/files/bin/omr-tracker-server | 16 ++++++++++++++-- omr-tracker/files/bin/omr-tracker-ss | 18 ++++++++++++++++++ omr-tracker/files/bin/omr-tracker-v2ray | 17 +++++++++++++++++ omr-tracker/files/bin/omr-tracker-xray | 18 ++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 53c3ac4dd..d12b61604 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -10,6 +10,18 @@ _log() { logger -p daemon.info -t "${basename}" "$@" } +_post_tracking() { + [ ! -d /usr/share/omr/server-post-tracking.d/ ] && return + for tracker_bin in /usr/share/omr/server-post-tracking.d/*; do + [ -x "$tracker_bin" ] && ( + _log() { + logger -t "post-tracking-${tracker_bin##*/}" "$*" + } + . "$tracker_bin" 2>&1 + ) + done +} + _ping_server() { local host=$1 ret=$(ping \ @@ -132,7 +144,7 @@ _check_master() { set_ip() { ip="$serverip" if [ "$server_ping" = true ]; then - if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then + if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ] && [ "$(uci -q get shadowsocks-rust.sss${count}.server | tr -d '\n')" != "$ip" ]; then logger -t "OMR-Tracker-Server" "Master server ${name} up ($ip), set it back" changes="1" #logger -t "OMR-Tracker-Server" "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n') - $ip" @@ -283,7 +295,7 @@ _check_backup() { ip="$serverip" #[ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" = "$ip" ] && break if [ "$server_ping" = true ]; then - if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then + if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ] && [ "$(uci -q get shadowsocks-rust.sss${count}.server | tr -d '\n')" != "$ip" ]; then logger -t "OMR-Tracker-Server" "Use backup server $1 ($ip)" changes="1" uci -q batch <<-EOF >/dev/null diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index 829cf4dc5..058bd9d7f 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -18,6 +18,18 @@ _log() { logger -p daemon.info -t "${basename}" "$@" } +_post_tracking() { + [ ! -d /usr/share/omr/ss-post-tracking.d ] && return + for tracker_bin in /usr/share/omr/ss-post-tracking.d/*; do + [ -x "$tracker_bin" ] && ( + _log() { + logger -t "ss-post-tracking-${tracker_bin##*/}" "$*" + } + . "$tracker_bin" 2>&1 + ) + done +} + _ping_server() { local host=$1 ret=$(ping \ @@ -74,6 +86,8 @@ uci -q set openmptcprouter.omr=router uci -q delete openmptcprouter.omr.shadowsocks="" _get_ip +OMR_TRACKER_PREV_STATUS="" + while true; do host="${hosts%% *}" [ "$host" = "$hosts" ] || { @@ -116,6 +130,7 @@ while true; do fi [ "$(uci -q get openmptcprouter.omr.detected_public_ipv4)" = "" ] || ([ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.detected_public_ipv6)" = "" ]) && _get_ip last=0 + OMR_TRACKER_STATUS="OK" else last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" @@ -175,6 +190,9 @@ while true; do sleep $wait_test fi } + OMR_TRACKER_STATUS="ERROR" fi + _post_tracking + OMR_TRACKER_PREV_STATUS="$OMR_TRACKER_STATUS" sleep "${interval}" done diff --git a/omr-tracker/files/bin/omr-tracker-v2ray b/omr-tracker/files/bin/omr-tracker-v2ray index 519399ce8..0ea2542b4 100755 --- a/omr-tracker/files/bin/omr-tracker-v2ray +++ b/omr-tracker/files/bin/omr-tracker-v2ray @@ -15,6 +15,18 @@ _log() { logger -p daemon.info -t "${basename}" "$@" } +_post_tracking() { + [ ! -d /usr/share/omr/v2ray-post-tracking.d ] && return + for tracker_bin in /usr/share/omr/v2ray-post-tracking.d/*; do + [ -x "$tracker_bin" ] && ( + _log() { + logger -t "v2ray-post-tracking-${tracker_bin##*/}" "$*" + } + . "$tracker_bin" 2>&1 + ) + done +} + _ping_server() { local host=$1 ret=$(ping \ @@ -70,6 +82,7 @@ uci -q set openmptcprouter.omr=router uci -q delete openmptcprouter.omr.v2ray _get_ip +OMR_TRACKER_PREV_STATUS="" while true; do host="${hosts%% *}" [ "$host" = "$hosts" ] || { @@ -107,6 +120,7 @@ while true; do fi [ "$(uci -q get openmptcprouter.omr.detected_public_ipv4)" = "" ] || ([ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.detected_public_ipv6)" = "" ]) && _get_ip last=0 + OMR_TRACKER_STATUS="OK" else last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" @@ -145,6 +159,9 @@ while true; do sleep $wait_test fi } + OMR_TRACKER_STATUS="ERROR" fi + _post_tracking + OMR_TRACKER_PREV_STATUS="$OMR_TRACKER_STATUS" sleep "${interval}" done diff --git a/omr-tracker/files/bin/omr-tracker-xray b/omr-tracker/files/bin/omr-tracker-xray index 4aae08e76..fe5039a57 100755 --- a/omr-tracker/files/bin/omr-tracker-xray +++ b/omr-tracker/files/bin/omr-tracker-xray @@ -15,6 +15,19 @@ _log() { logger -p daemon.info -t "${basename}" "$@" } +_post_tracking() { + [ ! -d /usr/share/omr/xray-post-tracking.d ] && return + for tracker_bin in /usr/share/omr/xray-post-tracking.d/*; do + [ -x "$tracker_bin" ] && ( + _log() { + logger -t "xray-post-tracking-${tracker_bin##*/}" "$*" + } + . "$tracker_bin" 2>&1 + ) + done +} + + _ping_server() { local host=$1 ret=$(ping \ @@ -70,6 +83,7 @@ uci -q set openmptcprouter.omr=router uci -q delete openmptcprouter.omr.xray _get_ip +OMR_TRACKER_PREV_STATUS="" while true; do host="${hosts%% *}" [ "$host" = "$hosts" ] || { @@ -107,6 +121,7 @@ while true; do fi [ "$(uci -q get openmptcprouter.omr.detected_public_ipv4)" = "" ] || ([ "$(uci -q get openmptcprouter.settings.disable_ipv6)" != "1" ] && [ "$(uci -q get openmptcprouter.omr.detected_public_ipv6)" = "" ]) && _get_ip last=0 + OMR_TRACKER_STATUS="OK" else last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" @@ -145,6 +160,9 @@ while true; do sleep $wait_test fi } + OMR_TRACKER_STATUS="ERROR" fi + _post_tracking + OMR_TRACKER_PREV_STATUS="$OMR_TRACKER_STATUS" sleep "${interval}" done From 1fa7e6178556ca6d617f234591ca1daea5cd27c2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Mar 2024 09:51:44 +0100 Subject: [PATCH 1477/2059] Increase mod dashboard order --- .../root/usr/share/luci/menu.d/luci-mod-dashboard.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json b/luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json index 555884674..88c4a4c4d 100644 --- a/luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json +++ b/luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json @@ -1,7 +1,7 @@ { "admin/dashboard": { "title": "Dashboard", - "order": 1, + "order": 5, "action": { "type": "view", "path": "dashboard/index" From ec31556e171253d77ca0f83f0898bc66315c065e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Mar 2024 20:19:38 +0100 Subject: [PATCH 1478/2059] Update ModemManager --- libmbim/Makefile | 5 +++-- libqmi/Makefile | 5 +++-- modemmanager/Makefile | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libmbim/Makefile b/libmbim/Makefile index 85024008e..d50bde9a0 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -8,12 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_SOURCE_VERSION:=1.30.0 +PKG_SOURCE_VERSION:=1.31.2-dev +#PKG_SOURCE_VERSION:=1.30.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -PKG_MIRROR_HASH:=8fc4e2d78d6a1003bf89303d3ce779283b176d74e84a241ba8efb0d468605268 +#PKG_MIRROR_HASH:=8fc4e2d78d6a1003bf89303d3ce779283b176d74e84a241ba8efb0d468605268 PKG_BUILD_FLAGS:=gc-sections diff --git a/libqmi/Makefile b/libqmi/Makefile index 5652332fe..01e1103bc 100644 --- a/libqmi/Makefile +++ b/libqmi/Makefile @@ -8,12 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libqmi -PKG_SOURCE_VERSION:=1.34.0 +#PKG_SOURCE_VERSION:=1.34.0 +PKG_SOURCE_VERSION:=1.35.2-dev PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -PKG_MIRROR_HASH:=af3dc760d0c40ef8af1f8b424435daa12bff698ed45b1cc9a9e38ea62ed047f0 +#PKG_MIRROR_HASH:=af3dc760d0c40ef8af1f8b424435daa12bff698ed45b1cc9a9e38ea62ed047f0 PKG_BUILD_FLAGS:=gc-sections diff --git a/modemmanager/Makefile b/modemmanager/Makefile index f02db006e..853304ffb 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_SOURCE_VERSION:=1.23.4-dev +PKG_SOURCE_VERSION:=1.23.5-dev PKG_RELEASE:=20 PKG_SOURCE_PROTO:=git From b64a585a0a68522bc34a392808319fd5aa96dc2d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 29 Mar 2024 20:20:21 +0100 Subject: [PATCH 1479/2059] Update ndpi-netfilter --- ndpi-netfilter2/Makefile | 3 ++- ...003-fix-compilation-for-kernel-6.7.0.patch | 26 ------------------- 2 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 0d2466d7e..50ddd78ad 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -12,7 +12,8 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 #PKG_REV:=3deea541af037b663b1b83a055b80d9a06a0afd2 -PKG_REV:=5cf35a64c8296b69099d3bd4c8cb9222f3174901 +#PKG_REV:=5cf35a64c8296b69099d3bd4c8cb9222f3174901 +PKG_REV:=761993583265cf9a022be1ad2d701e446bb91d42 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git diff --git a/ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch b/ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch deleted file mode 100644 index aa7cab996..000000000 --- a/ndpi-netfilter2/patches/003-fix-compilation-for-kernel-6.7.0.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/ndpi-netfilter/src/main.c 2023-12-22 18:46:47.999596865 +0100 -+++ b/ndpi-netfilter/src/main.c 2023-12-22 18:48:52.981393673 +0100 -@@ -2840,7 +2840,11 @@ - #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) - net->ct.label_words = n->labels_word; - #endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) - net->ct.labels_used--; -+#else -+ atomic_dec_return_relaxed(&net->ct.labels_used); -+#endif - - #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) - struct nf_ct_iter_data iter_data = { -@@ -3138,7 +3142,11 @@ - n->labels_word = ACCESS_ONCE(net->ct.label_words); - net->ct.label_words = 2; - #endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) - net->ct.labels_used++; -+#else -+ atomic_inc_return_relaxed(&net->ct.labels_used); -+#endif - #endif - if( ndpi_enable_flow && - nf_register_net_hooks(net, nf_nat_ipv4_ops, From 2b042ee3521eb1a0e55ac8e8af99c14123748eab Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 2 Apr 2024 16:31:03 +0200 Subject: [PATCH 1480/2059] Start openmptcprouter-vps is never correctly run on VPS --- omr-schedule/files/usr/share/omr/schedule.d/010-services | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-schedule/files/usr/share/omr/schedule.d/010-services b/omr-schedule/files/usr/share/omr/schedule.d/010-services index acbbed0fb..dcb6c5ced 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/010-services +++ b/omr-schedule/files/usr/share/omr/schedule.d/010-services @@ -217,7 +217,7 @@ if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcproute /etc/init.d/openmptcprouter-vps token >/dev/null 2>&1 & sleep 5 fi -if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then +if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ -z "$(uci -q show openmptcprouter | grep get_config)" ] || [ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 & sleep 5 fi From 178481a7494ddc7ca72eeaa2982ff66c5d839710 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 2 Apr 2024 16:31:50 +0200 Subject: [PATCH 1481/2059] Check if proxy config exist or not before actions on openmptcprouter-vps --- .../files/etc/init.d/openmptcprouter-vps | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index a0a3b365a..e4c98e048 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -510,7 +510,7 @@ _get_vps_config() { ip6resolve="$(resolveip -6 $vpsip | head -n 1)" [ -n "$ip6resolve" ] && vpsip="$ip6resolve" fi - if [ "$(uci -q get shadowsocks-libev.sss0.server)" != "127.0.0.1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + if [ -n "$(uci -q get shadowsocks-libev.sss0)" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "127.0.0.1" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then config_foreach _set_ss_server server "server" $vpsip uci -q batch <<-EOF >/dev/null set shadowsocks-libev.sss0.server="$vpsip" @@ -521,7 +521,7 @@ _get_vps_config() { /etc/init.d/shadowsocks-libev restart fi fi - if [ "$(uci -q get shadowsocks-rust.sss0.server)" != "127.0.0.1" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + if [ -n "$(uci -q get shadowsocks-rust.sss0)" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "127.0.0.1" ] && [ "$(uci -q get shadowsocks-rust.sss0.server)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then config_foreach _set_ssrust_server server "server" $vpsip uci -q batch <<-EOF >/dev/null set shadowsocks-rust.sss0.server="$vpsip" @@ -532,7 +532,7 @@ _get_vps_config() { /etc/init.d/shadowsocks-rust restart fi fi - if [ "$(uci -q get v2ray.omrout.s_vmess_address)" != "127.0.0.1" ] && [ "$(uci -q get v2ray.omrout.s_vmess_address)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + if [ -n "$(uci -q get v2ray.omrout)" ] && [ "$(uci -q get v2ray.omrout.s_vmess_address)" != "127.0.0.1" ] && [ "$(uci -q get v2ray.omrout.s_vmess_address)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then uci -q batch <<-EOF >/dev/null set v2ray.omrout.s_vmess_address="$vpsip" set v2ray.omrout.s_vless_address="$vpsip" @@ -545,7 +545,7 @@ _get_vps_config() { /etc/init.d/v2ray restart fi fi - if [ "$(uci -q get xray.omrout.s_vmess_address)" != "127.0.0.1" ] && [ "$(uci -q get xray.omrout.s_vmess_address)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + if [ -n "$(uci -q get xray.omrout)" ] && [ "$(uci -q get xray.omrout.s_vmess_address)" != "127.0.0.1" ] && [ "$(uci -q get xray.omrout.s_vmess_address)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then uci -q batch <<-EOF >/dev/null set xray.omrout.s_vmess_address="$vpsip" set xray.omrout.s_vless_address="$vpsip" @@ -560,7 +560,7 @@ _get_vps_config() { /etc/init.d/xray restart fi fi - if [ "$(uci -q get openvpn.omr.remote)" != "127.0.0.1" ] && [ "$(uci -q get openvpn.omr.remote)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + if [ -n "$(uci -q get openvpn.omr)" ] && [ "$(uci -q get openvpn.omr.remote)" != "127.0.0.1" ] && [ "$(uci -q get openvpn.omr.remote)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then uci -q batch <<-EOF >/dev/null set openvpn.omr.remote="$vpsip" commit openvpn @@ -573,7 +573,7 @@ _get_vps_config() { port="$(echo "$vps_config" | jsonfilter -q -e '@.dsvpn.port')" localip="$(echo "$vps_config" | jsonfilter -q -e '@.dsvpn.client_ip')" remoteip="$(echo "$vps_config" | jsonfilter -q -e '@.dsvpn.host_ip')" - if ([ "$(uci -q get dsvpn.vpn.host)" != "127.0.0.1" ] && [ "$(uci -q get dsvpn.vpn.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]) || [ "$(uci -q get dsvpn.vpn.port)" != "$port" ] || [ "$(uci -q get dsvpn.vpn.localip)" != "$localip" ] || [ "$(uci -q get dsvpn.vpn.remoteip)" != "$remoteip" ]; then + if [ -n "$(uci -q get dsvpn.vpn)" ] && ([ "$(uci -q get dsvpn.vpn.host)" != "127.0.0.1" ] && [ "$(uci -q get dsvpn.vpn.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]) || [ "$(uci -q get dsvpn.vpn.port)" != "$port" ] || [ "$(uci -q get dsvpn.vpn.localip)" != "$localip" ] || [ "$(uci -q get dsvpn.vpn.remoteip)" != "$remoteip" ]; then uci -q batch <<-EOF >/dev/null set dsvpn.vpn.port=$port set dsvpn.vpn.localip=$localip @@ -587,7 +587,7 @@ _get_vps_config() { fi fi - if [ "$(uci -q get mlvpn.general.host)" != "127.0.0.1" ] && [ "$(uci -q get mlvpn.general.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ] && [ -f /etc/init.d/mlvpn ]; then + if [ -n "$(uci -q get mlvpn.general)" ] && [ "$(uci -q get mlvpn.general.host)" != "127.0.0.1" ] && [ "$(uci -q get mlvpn.general.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ] && [ -f /etc/init.d/mlvpn ]; then uci -q batch <<-EOF >/dev/null set mlvpn.general=mlvpn set mlvpn.general.host="$vpsip" @@ -598,13 +598,13 @@ _get_vps_config() { /etc/init.d/mlvpn restart fi fi - if [ "$(uci -q get glorytun.vpn.host)" != "127.0.0.1" ] && [ "$(uci -q get glorytun.vpn.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + if [ -n "$(uci -q get glorytun.vpn)" ] && [ "$(uci -q get glorytun.vpn.host)" != "127.0.0.1" ] && [ "$(uci -q get glorytun.vpn.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then uci -q batch <<-EOF >/dev/null set glorytun.vpn.host="$vpsip" EOF glorytun_change=1 fi - if [ "$(uci -q get glorytun-udp.vpn.host)" != "127.0.0.1" ] && [ "$(uci -q get glorytun-udp.vpn.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then + if [ -n "$(uci -q get glorytun-udp.vpn)" ] && [ "$(uci -q get glorytun-udp.vpn.host)" != "127.0.0.1" ] && [ "$(uci -q get glorytun-udp.vpn.host)" != "$vpsip" ] && [ "$(uci -q get openmptcprouter.settings.ha)" != "1" ]; then uci -q batch <<-EOF >/dev/null set glorytun-udp.vpn.host="$vpsip" EOF @@ -1572,7 +1572,7 @@ _set_config_from_vps() { #[ -z "$shadowsocks_disabled" ] && shadowsocks_disabled=0 ss_key="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.key')" ss_key="$(echo $ss_key | sed 's/-/+/g; s/_/\//g;')" - if [ -n "$ss_key" ] && [ "$ss_key" != "$(uci -q get shadowsocks-libev.sss0.key)" ]; then + if [ -n "$ss_key" ] && [ "$ss_key" != "$(uci -q get shadowsocks-libev.sss0.key)" ] && [ -n "$(uci -q get shadowsocks-libev.sss0)" ]; then ss_method="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.method')" ss_port="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.port')" ss_ebpf="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks.ebpf')" @@ -1630,7 +1630,7 @@ _set_config_from_vps() { #shadowsocks_disabled="$(uci -q get openmptcprouter.settings.shadowsocks_disable)" #[ -z "$shadowsocks_disabled" ] && shadowsocks_disabled=0 ssgo_sskey="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks_go.config.password')" - if [ -n "$ssgo_sskey" ] && [ "$ssgo_sskey" != "$(uci -q get shadowsocks-rust.sss0.password)" ]; then + if [ -n "$ssgo_sskey" ] && [ "$ssgo_sskey" != "$(uci -q get shadowsocks-rust.sss0.password)" ] && [ -n "$(uci -q get shadowsocks-rust.sss0)" ]; then ss_method="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks_go.config.protocol')" ss_port="65280" #ss_fast_open="$(echo "$vps_config" | jsonfilter -q -e '@.shadowsocks-rust.fast_open')" @@ -2282,7 +2282,7 @@ _config_service() { [ -z "$(_set_vpn_vps)" ] && error=1 [ -z "$(_set_proxy_vps)" ] && error=1 fi - [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" = "" ] && uci -q set openmptcprouter.${servername}.get_config=1 + ([ -n "$(uci -q get shadowsocks-libev.sss0)" ] || [ -n "$(uci -q get shadowsocks-rust.sss0)" ]) && [ "$(uci -q get shadowsocks-libev.sss0.key)" = "" ] && [ "$(uci -q get shadowsocks-rust.sss0.key)" = "" ] && uci -q set openmptcprouter.${servername}.get_config=1 #_set_pihole [ -n "$wanips" ] && _set_wan_ip From 4e01f6563ed9b569f86531ea9d866d190b59e01b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 2 Apr 2024 20:33:31 +0200 Subject: [PATCH 1482/2059] Disable ndpi for kernel 6.6 --- ndpi-netfilter2/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index 50ddd78ad..a06618785 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -41,7 +41,7 @@ define Package/iptables-mod-ndpi # DEPENDS:=+iptables +iptables-mod-conntrack-extra +kmod-ipt-ndpi +libpcap # DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) # DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @(LINUX_5_4||LINUX_5_15) @!TARGET_ramips - DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @!TARGET_ramips + DEPENDS:=+iptables +kmod-ipt-ndpi +libpcap @!TARGET_ramips @!LINUX_6_6 MAINTAINER:=Ycarus (Yannick Chabanois) endef @@ -83,7 +83,7 @@ define KernelPackage/ipt-ndpi TITLE:= nDPI net netfilter module # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15) @!TARGET_ramips - DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +(LINUX_5_4||LINUX_6_1):kmod-ipt-compat-xtables +libpcap @!TARGET_ramips + DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +(LINUX_5_4||LINUX_6_1):kmod-ipt-compat-xtables +libpcap @!TARGET_ramips @!LINUX_6_6 # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap KCONFIG:=CONFIG_NF_CONNTRACK_LABELS=y \ CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y From 1b182489c238159f626994fe3791810758377365 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 2 Apr 2024 20:34:37 +0200 Subject: [PATCH 1483/2059] Disable ndpi for kernel 6.6 --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 9422b75a6..dacbdf1bd 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -85,7 +85,7 @@ MY_DEPENDS := \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core LINUX_5_4:v2ray-config !LINUX_5_4:v2ray-config-nft syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ - !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ + !(TARGET_ips40xx||TARGET_ramips||KERNEL_6_6):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips||KERNEL_6_6):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust \ luci-proto-external omr-schedule jq luci-app-ddns From dc4248fa2e7c1225524709332e48cdec03c0e475 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 3 Apr 2024 09:36:38 +0200 Subject: [PATCH 1484/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/3245 --- .../htdocs/luci-static/resources/view/services/omr-bypass.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js index 5cdcaf7d9..ee91a690e 100644 --- a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js +++ b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js @@ -282,7 +282,7 @@ return L.view.extend({ o = s.option(form.ListValue, 'family', _('Restrict to address family')); o.value('ipv4ipv6', _('IPv4 and IPv6')); o.value('ipv4', _('IPv4 only')); - o.value('ipv4', _('IPv6 only')); + o.value('ipv6', _('IPv6 only')); o.default = 'ipv4ipv6'; o.modalonly = true From d0d6d7887157cdb752fb9f28b4d61d04c97d16db Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 3 Apr 2024 09:37:04 +0200 Subject: [PATCH 1485/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3243 --- luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index b38c1321f..c3a25e5e0 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1482,6 +1482,7 @@ function settings_add() -- Apply all settings luci.sys.call("/etc/init.d/openmptcprouter restart >/dev/null 2>/dev/null") + luci.sys.call("/etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") -- Done, redirect From 00d3bc31191f4c1a7b7dbff25c51b53b0b686a1a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 3 Apr 2024 09:37:27 +0200 Subject: [PATCH 1486/2059] Disable ndpi for more arch... --- openmptcprouter-full/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index dacbdf1bd..1c38d98c1 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -85,7 +85,7 @@ MY_DEPENDS := \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core LINUX_5_4:v2ray-config !LINUX_5_4:v2ray-config-nft syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ - !(TARGET_ips40xx||TARGET_ramips||KERNEL_6_6):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips||KERNEL_6_6):kmod-ipt-ndpi libip4tc libip6tc \ + !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6||TARGET_mvebu||TARGET_ipq806x||TARGET_mediatek):iptables-mod-ndpi !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6||TARGET_mvebu||TARGET_ipq806x||TARGET_mediatek):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust \ luci-proto-external omr-schedule jq luci-app-ddns From 7c6429e6112edce19aa4428362f14f250f87d518 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 3 Apr 2024 10:16:52 +0200 Subject: [PATCH 1487/2059] Fix omr-test-speed on 6.1/6.6 kernel with nft --- openmptcprouter/files/bin/omr-test-speed | 10 ++++++++++ openmptcprouter/files/bin/omr-test-speedv6 | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/openmptcprouter/files/bin/omr-test-speed b/openmptcprouter/files/bin/omr-test-speed index a1de53264..208e62e8f 100755 --- a/openmptcprouter/files/bin/omr-test-speed +++ b/openmptcprouter/files/bin/omr-test-speed @@ -57,6 +57,11 @@ else ipset add ss_rules_dst_bypass_all $ip done fi + if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_4 2>/dev/null)" ]; then + for ip in $hostip; do + nft add element inet fw4 omr_dst_bypass_all_4 { $ip } 2>&1 >/dev/null + done + fi if [ "$FASTTEST" = true ]; then avg_speed=$(curl -4 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE $HOST 2>/dev/null) echo "$avg_speed" @@ -68,5 +73,10 @@ else ipset del ss_rules_dst_bypass_all $ip done fi + if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_4 2>/dev/null)" ]; then + for ip in $hostip; do + nft delete element inet fw4 omr_dst_bypass_all_4 { $ip } 2>&1 >/dev/null + done + fi /etc/init.d/sqm start $INTERFACE fi diff --git a/openmptcprouter/files/bin/omr-test-speedv6 b/openmptcprouter/files/bin/omr-test-speedv6 index 0302c5d6c..2396ac709 100755 --- a/openmptcprouter/files/bin/omr-test-speedv6 +++ b/openmptcprouter/files/bin/omr-test-speedv6 @@ -54,6 +54,11 @@ else ipset add ss_rules6_dst_bypass_all $ip done fi + if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_6 2>/dev/null)" ]; then + for ip in $hostip; do + nft add element inet fw4 omr_dst_bypass_all_6 { $ip } 2>&1 >/dev/null + done + fi if [ "$FASTTEST" = true ]; then avg_speed=$(curl -6 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE $HOST 2>/dev/null) echo "$avg_speed" @@ -65,5 +70,10 @@ else ipset del ss_rules6_dst_bypass_all $ip done fi + if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_6 2>/dev/null)" ]; then + for ip in $hostip; do + nft delete element inet fw4 omr_dst_bypass_all_6 { $ip } 2>&1 >/dev/null + done + fi /etc/init.d/sqm start $INTERFACE fi From bb3a102671470a0aa3ef7d345284fb78cc481fef Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 3 Apr 2024 10:17:14 +0200 Subject: [PATCH 1488/2059] Add previous gw info in log --- mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking index 45044312b..bec1caa54 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/001-post-tracking @@ -956,7 +956,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om fi fi if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then - _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE (was $default_gw)" [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw : $default_gw - Current route: $(ip r)" ip route replace default scope global via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE $initcwrwnd 2>&1 >/dev/null if [ "$(pgrep -f openmptcprouter-vps)" = "" ]; then From 124b48253cd3a6e1199ba6393d7112888506b042 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 3 Apr 2024 14:06:33 +0200 Subject: [PATCH 1489/2059] Export Status for OMR-Tracker scripts --- omr-tracker/files/bin/omr-tracker-server | 5 +++++ omr-tracker/files/bin/omr-tracker-ss | 4 ++++ omr-tracker/files/bin/omr-tracker-v2ray | 4 ++++ omr-tracker/files/bin/omr-tracker-xray | 3 +++ 4 files changed, 16 insertions(+) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index d12b61604..dc23fc9c6 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -6,6 +6,9 @@ basename="$(basename $0)" . /usr/lib/unbound/iptools.sh +export OMR_TRACKER_STATUS +export OMR_TRACKER_STATUS_MSG + _log() { logger -p daemon.info -t "${basename}" "$@" } @@ -213,6 +216,7 @@ _check_master() { echo -e "Subject: $OMR_SYSNAME: Server ${name} (${ip}) is UP\n. The reason is \"$OMR_TRACKER_STATUS_MSG\"." | sendmail $(uci -q get mail.default.to) fi } + OMR_TRACKER_STATUS="OK" script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" [ -n "$script_alert_up" ] && eval $script_alert_up count=$((count+1)) @@ -241,6 +245,7 @@ _check_master() { echo -e "Subject: $OMR_SYSNAME: Server ${name} (${ip}) is down\n. The reason is \"$OMR_TRACKER_STATUS_MSG\"." | sendmail $(uci -q get mail.default.to) fi } + OMR_TRACKER_STATUS="ERROR" script_alert_down="$(uci -q get omr-tracker.proxy.script_alert_down)" [ -n "$script_alert_down" ] && eval $script_alert_down fi diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index 058bd9d7f..bf79db590 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -12,6 +12,10 @@ else IPTABLESSAVE="/usr/sbin/iptables-save" fi +export OMR_TRACKER_STATUS +export OMR_TRACKER_PREV_STATUS +export OMR_TRACKER_STATUS_MSG + _log() { diff --git a/omr-tracker/files/bin/omr-tracker-v2ray b/omr-tracker/files/bin/omr-tracker-v2ray index 0ea2542b4..ad07829f2 100755 --- a/omr-tracker/files/bin/omr-tracker-v2ray +++ b/omr-tracker/files/bin/omr-tracker-v2ray @@ -10,6 +10,10 @@ else IPTABLES="/usr/sbin/iptables" fi +export OMR_TRACKER_STATUS +export OMR_TRACKER_PREV_STATUS +export OMR_TRACKER_STATUS_MSG + _log() { logger -p daemon.info -t "${basename}" "$@" diff --git a/omr-tracker/files/bin/omr-tracker-xray b/omr-tracker/files/bin/omr-tracker-xray index fe5039a57..83b5d82c2 100755 --- a/omr-tracker/files/bin/omr-tracker-xray +++ b/omr-tracker/files/bin/omr-tracker-xray @@ -10,6 +10,9 @@ else IPTABLES="/usr/sbin/iptables" fi +export OMR_TRACKER_STATUS +export OMR_TRACKER_PREV_STATUS +export OMR_TRACKER_STATUS_MSG _log() { logger -p daemon.info -t "${basename}" "$@" From 71be9725130411bd8a29e290aa6ffeb36d901617 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Apr 2024 08:45:19 +0200 Subject: [PATCH 1490/2059] Revert ndpi-netfilter2 changes for 6.1 kernel --- ndpi-netfilter2/Makefile | 4 ++-- openmptcprouter-full/Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index a06618785..dca6daefa 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -12,8 +12,8 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ndpi-netfilter2 PKG_RELEASE:=4 #PKG_REV:=3deea541af037b663b1b83a055b80d9a06a0afd2 -#PKG_REV:=5cf35a64c8296b69099d3bd4c8cb9222f3174901 -PKG_REV:=761993583265cf9a022be1ad2d701e446bb91d42 +PKG_REV:=5cf35a64c8296b69099d3bd4c8cb9222f3174901 +#PKG_REV:=761993583265cf9a022be1ad2d701e446bb91d42 PKG_VERSION:=4-$(PKG_REV) PKG_SOURCE_PROTO:=git diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 1c38d98c1..e33b16805 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -85,7 +85,7 @@ MY_DEPENDS := \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core LINUX_5_4:v2ray-config !LINUX_5_4:v2ray-config-nft syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ - !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6||TARGET_mvebu||TARGET_ipq806x||TARGET_mediatek):iptables-mod-ndpi !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6||TARGET_mvebu||TARGET_ipq806x||TARGET_mediatek):kmod-ipt-ndpi libip4tc libip6tc \ + !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6):iptables-mod-ndpi !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust \ luci-proto-external omr-schedule jq luci-app-ddns From dfd37d31886ee6225395f56dd70c1bb60557baad Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Apr 2024 11:09:25 +0200 Subject: [PATCH 1491/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3244 --- .../luasrc/controller/openmptcprouter.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index c3a25e5e0..0303e6ed9 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -428,7 +428,8 @@ function wizard_add() local uploadspeed = luci.http.formvalue("cbid.sqm.%s.upload" % intf) or "0" local testspeed = luci.http.formvalue("cbid.sqm.%s.testspeed" % intf) or "0" - if not ucic:get("qos",intf) ~= "" then + local qos_settings = ucic:get("qos",intf) or "" + if qos_settings == "" then ucic:set("qos",intf,"interface") ucic:set("qos",intf,"classgroup","Default") ucic:set("qos",intf,"enabled","0") @@ -436,7 +437,8 @@ function wizard_add() ucic:set("qos",intf,"download","100000") end - if not ucic:get("sqm",intf) ~= "" then + local sqm_settings = ucic:get("sqm",intf) or "" + if sqm_settings == "" then local defif = get_device(intf) if defif == "" then defif = ucic:get("network",intf,"device") or "" From 205b3f6d201026f5bceecf9817f5c708b785c504 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Apr 2024 19:17:56 +0200 Subject: [PATCH 1492/2059] Fix KERNEL instead of LINUX in openmptcprouter-full --- ndpi-netfilter2/Makefile | 2 +- openmptcprouter-full/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ndpi-netfilter2/Makefile b/ndpi-netfilter2/Makefile index dca6daefa..74d517750 100644 --- a/ndpi-netfilter2/Makefile +++ b/ndpi-netfilter2/Makefile @@ -83,7 +83,7 @@ define KernelPackage/ipt-ndpi TITLE:= nDPI net netfilter module # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15||TARGET_x86_64) # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap @(LINUX_5_4||LINUX_5_15) @!TARGET_ramips - DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +(LINUX_5_4||LINUX_6_1):kmod-ipt-compat-xtables +libpcap @!TARGET_ramips @!LINUX_6_6 + DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +(LINUX_5_4||LINUX_6_1):kmod-ipt-compat-xtables +libpcap @!TARGET_ramips @!LINUX_6_6 # DEPENDS:=+kmod-nf-conntrack +kmod-nf-conntrack-netlink +kmod-ipt-compat-xtables +libpcap KCONFIG:=CONFIG_NF_CONNTRACK_LABELS=y \ CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index e33b16805..a19159885 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -85,7 +85,7 @@ MY_DEPENDS := \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core LINUX_5_4:v2ray-config !LINUX_5_4:v2ray-config-nft syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ - !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6):iptables-mod-ndpi !(TARGET_ipq40xx||TARGET_ramips||KERNEL_6_6):kmod-ipt-ndpi libip4tc libip6tc \ + !(TARGET_ipq40xx||TARGET_ramips||LINUX_6_6):iptables-mod-ndpi !(TARGET_ipq40xx||TARGET_ramips||LINUX_6_6):kmod-ipt-ndpi libip4tc libip6tc \ xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust \ luci-proto-external omr-schedule jq luci-app-ddns From 8b40968f6aa2a5e23babcac1eaaf74bddf0c9f60 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Apr 2024 16:45:33 +0200 Subject: [PATCH 1493/2059] Fix https://github.com/Ysurac/openmptcprouter/issues/3251 - Bypass MAC address --- omr-bypass/files/etc/init.d/omr-bypass-nft | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 014e1dabc..e7982eddf 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -536,12 +536,16 @@ _bypass_proto_without_ndpi() { _intf_rule_ss_rules() { cat >> /etc/firewall.omr-bypass <<-EOF nft insert rule inet fw4 ss_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_pre_tcp meta mark 0x4539${count} accept nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_local_out meta mark 0x4539${count} accept EOF if [ "$disableipv6" = "0" ]; then cat >> /etc/firewall.omr-bypass <<-EOF nft insert rule inet fw4 ss_rules_pre_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 ss_rules_pre_tcp meta mark 0x6539${count} accept nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 ss_rules_local_out meta mark 0x6539${count} accept EOF fi } @@ -549,12 +553,16 @@ _intf_rule_ss_rules() { _intf_rule_v2ray_rules() { cat >> /etc/firewall.omr-bypass <<-EOF nft insert rule inet fw4 v2r_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 v2r_rules_pre_tcp meta mark 0x4539${count} accept nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 v2r_rules_local_out meta mark 0x4539${count} accept EOF if [ "$disableipv6" = "0" ]; then cat >> /etc/firewall.omr-bypass <<-EOF nft insert rule inet fw4 v2r_rules_pre_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 v2r_rules_pre_tcp meta mark 0x6539${count} accept nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 v2r_rules_local_out meta mark 0x6539${count} accept EOF fi } @@ -562,12 +570,16 @@ _intf_rule_v2ray_rules() { _intf_rule_xray_rules() { cat >> /etc/firewall.omr-bypass <<-EOF nft insert rule inet fw4 xr_rules_pre_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 xr_rules_pre_tcp meta mark 0x4539${count} accept nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 xr_rules_local_out meta mark 0x4539${count} accept EOF if [ "$disableipv6" = "0" ]; then cat >> /etc/firewall.omr-bypass <<-EOF nft insert rule inet fw4 xr_rules_pre_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 xr_rules_pre_tcp meta mark 0x6539${count} accept nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 xr_rules_local_out meta mark 0x6539${count} accept EOF fi } @@ -714,11 +726,13 @@ _intf_rule() { EOF if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ]; then - config_load shadowsocks-libev - config_foreach _intf_rule_ss_rules ss_rules + #config_load shadowsocks-libev + #config_foreach _intf_rule_ss_rules ss_rules + _intf_rule_ss_rules elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks-rust" ] && [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]; then - config_load shadowsocks-rust - config_foreach _intf_rule_ss_rules ss_rules + #config_load shadowsocks-rust + #config_foreach _intf_rule_ss_rules ss_rules + _intf_rule_ss_rules elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ] && [ "$(uci -q get v2ray.main.enabled)" = "1" ]; then _intf_rule_v2ray_rules elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "xray" ] && [ "$(uci -q get xray.main.enabled)" = "1" ]; then From 57b8239787797077dd9d8d211f1793ae1dbf6a96 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 6 Apr 2024 17:12:32 +0200 Subject: [PATCH 1494/2059] Should fix https://github.com/Ysurac/openmptcprouter/issues/3252#issuecomment-2041038428 --- sqm-autorate/files/usr/share/sqm-autorate/config_template.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh index 4fe0d2822..64105e647 100755 --- a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh +++ b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh @@ -79,7 +79,7 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # (adjustment significant at sub 12Mbit/s rates, else negligible) #logger -t "sqm-autorate" "ping for ${INTERFACE} (${ul_if}): $(echo $(/sbin/uci -q get sqm.${INTERFACE}.delay_thr_ms || echo '100'))" #dl_owd_delta_thr_ms=$(echo $(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(echo "$(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | tr -d '\n' 2>/dev/null)+30" | bc) || echo "100")) + "0.1" | bc) # (milliseconds) -dl_owd_delta_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "250") +dl_owd_delta_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "250.0") ul_owd_delta_thr_ms=${dl_owd_delta_thr_ms} # average owd delta threshold in ms at which maximum adjust_down_bufferbloat is applied From 573d3a171b0a521abaa013de4cbc8ffd80048162 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Apr 2024 13:20:33 +0200 Subject: [PATCH 1495/2059] Upgrade OpenVPN to 2.6.10 --- openvpn/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvpn/Makefile b/openvpn/Makefile index 349c7e1cb..3bd46b9c6 100644 --- a/openvpn/Makefile +++ b/openvpn/Makefile @@ -9,14 +9,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openvpn -PKG_VERSION:=2.6.9 +PKG_VERSION:=2.6.10 PKG_RELEASE:=10 PKG_SOURCE_URL:=\ https://build.openvpn.net/downloads/releases/ \ https://swupdate.openvpn.net/community/releases/ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_HASH:=e08d147e15b4508dfcd1d6618a1f21f1495f9817a8dadc1eddf0532fa116d7e3 +PKG_HASH:=1993bbb7b9edb430626eaa24573f881fd3df642f427fcb824b1aed1fca1bcc9b PKG_MAINTAINER:=Magnus Kroken From c4bcee8a39d6d75fc76172791fa2066acff88266 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 9 Apr 2024 16:38:04 +0200 Subject: [PATCH 1496/2059] Run z8102 init a bit later --- z8102/files/etc/init.d/z8102 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/z8102/files/etc/init.d/z8102 b/z8102/files/etc/init.d/z8102 index a5ac27071..8b0a9d039 100755 --- a/z8102/files/etc/init.d/z8102 +++ b/z8102/files/etc/init.d/z8102 @@ -2,7 +2,7 @@ # Copyright (C) 2013 OpenWrt.org # Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter -START=05 +START=10 USE_PROCD=1 log() { From 94c0896c4a0f0c00811ab0c053651fafb8c4af53 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Apr 2024 17:40:35 +0200 Subject: [PATCH 1497/2059] Update bcm27xx-eeprom --- bcm27xx-eeprom/Makefile | 61 ++++++++++++++---- ...1-rpi-eeprom-update-OpenWrt-defaults.patch | 29 +++------ ...m-update-change-default-include-path.patch | 62 +++++++++++++++++++ ...m-update-change-default-include-path.patch | 26 -------- ...ate-chmod-silent-f-is-not-supported.patch} | 6 +- ...-replace-nano-with-vi-as-default-ed.patch} | 17 ++++- 6 files changed, 139 insertions(+), 62 deletions(-) create mode 100644 bcm27xx-eeprom/patches/0002-rpi-eeprom-update-change-default-include-path.patch delete mode 100644 bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch rename bcm27xx-eeprom/patches/{0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch => 0003-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch} (89%) rename bcm27xx-eeprom/patches/{0005-rpi-eeprom-config-change-default-text-editor.patch => 0004-rpi-eeprom-config-replace-nano-with-vi-as-default-ed.patch} (54%) diff --git a/bcm27xx-eeprom/Makefile b/bcm27xx-eeprom/Makefile index b114ee11a..2d2fac5c4 100644 --- a/bcm27xx-eeprom/Makefile +++ b/bcm27xx-eeprom/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-eeprom -PKG_VERSION:=v2022.04.26-138a1 -PKG_RELEASE:=$(AUTORELEASE) +PKG_VERSION:=v.2024.01.05-2712 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/rpi-eeprom/tar.gz/$(PKG_VERSION)? -PKG_HASH:=7c54839e68f226c5853fb63c8a1539b729d84b2e6bac311a51766c601d10a413 +PKG_HASH:=ae1d9f10e4383ee39b291b4b3be1be583f6f32f806f65a1431da65ca4ccffe39 PKG_LICENSE:=BSD-3-Clause Custom PKG_LICENSE_FILES:=LICENSE @@ -18,15 +18,39 @@ include $(INCLUDE_DIR)/package.mk TAR_OPTIONS:=--strip-components 1 $(TAR_OPTIONS) TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS) -define Package/bcm27xx-eeprom +define Package/bcm27xx-eeprom/Default SECTION:=utils CATEGORY:=Utilities - DEPENDS:=bcm27xx-userland +blkid +coreutils +coreutils-od +pciutils +python3-light +endef + +define Package/bcm27xx-eeprom +$(call Package/bcm27xx-eeprom/Default) TITLE:=BCM27xx EEPROM tools + DEPENDS:=bcm27xx-utils +blkid +coreutils +coreutils-od +mount-utils +pciutils +python3-light +endef + +define Package/bcm2711-eeprom +$(call Package/bcm27xx-eeprom/Default) + TITLE:=BCM2711 EEPROM tools + DEPENDS:=+bcm27xx-eeprom +endef + +define Package/bcm2712-eeprom +$(call Package/bcm27xx-eeprom/Default) + TITLE:=BCM2712 EEPROM tools + DEPENDS:=+bcm27xx-eeprom endef define Package/bcm27xx-eeprom/description - BCM27xx EEPROM tools. + BCM27xx EEPROM config and update tools. +endef + +define Package/bcm2711-eeprom/description + BCM2711 EEPROM config and update tools. +endef + +define Package/bcm2712-eeprom/description + BCM2712 EEPROM config and update tools. endef define Build/Compile @@ -45,15 +69,28 @@ define Package/bcm27xx-eeprom/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-config $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-digest $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-update $(1)/usr/bin +endef - $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader - $(CP) $(PKG_BUILD_DIR)/firmware/release-notes.md $(1)/lib/firmware/raspberrypi/bootloader +define Package/bcm2711-eeprom/install + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader-2711 + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader-2711/default + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader-2711/latest - $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader/critical - $(CP) $(PKG_BUILD_DIR)/firmware/critical/ $(1)/lib/firmware/raspberrypi/bootloader/ + $(CP) $(PKG_BUILD_DIR)/firmware-2711/release-notes.md $(1)/lib/firmware/raspberrypi/bootloader-2711 + $(CP) $(PKG_BUILD_DIR)/firmware-2711/default $(1)/lib/firmware/raspberrypi/bootloader-2711 + $(CP) $(PKG_BUILD_DIR)/firmware-2711/latest $(1)/lib/firmware/raspberrypi/bootloader-2711 +endef - $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader/stable - $(CP) $(PKG_BUILD_DIR)/firmware/stable/ $(1)/lib/firmware/raspberrypi/bootloader/ +define Package/bcm2712-eeprom/install + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader-2712 + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader-2712/default + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader-2712/latest + + $(CP) $(PKG_BUILD_DIR)/firmware-2712/release-notes.md $(1)/lib/firmware/raspberrypi/bootloader-2712 + $(CP) $(PKG_BUILD_DIR)/firmware-2712/default $(1)/lib/firmware/raspberrypi/bootloader-2712 + $(CP) $(PKG_BUILD_DIR)/firmware-2712/latest $(1)/lib/firmware/raspberrypi/bootloader-2712 endef $(eval $(call BuildPackage,bcm27xx-eeprom)) +$(eval $(call BuildPackage,bcm2711-eeprom)) +$(eval $(call BuildPackage,bcm2712-eeprom)) diff --git a/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch index 7fc10a8a5..4404fc3b6 100644 --- a/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch +++ b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch @@ -1,4 +1,4 @@ -From da37f7b051fe6833e25e78184cc9217dd4379187 Mon Sep 17 00:00:00 2001 +From a7c4e8f246dc58b4c83293b11f6443528065dc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 23 Mar 2020 10:10:55 +0100 Subject: [PATCH] rpi-eeprom-update: OpenWrt defaults @@ -8,38 +8,29 @@ Content-Transfer-Encoding: 8bit Signed-off-by: Álvaro Fernández Rojas --- - rpi-eeprom-update | 6 +++--- - rpi-eeprom-update-default | 5 +++-- - 2 files changed, 6 insertions(+), 5 deletions(-) + rpi-eeprom-update | 4 ++-- + rpi-eeprom-update-default | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) --- a/rpi-eeprom-update +++ b/rpi-eeprom-update -@@ -24,12 +24,12 @@ else - fi +@@ -25,7 +25,7 @@ fi # Selects the release sub-directory --FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-default} -+FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-stable} - FIRMWARE_IMAGE_DIR=${FIRMWARE_IMAGE_DIR:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}} + FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-default} -FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup} +FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-${FIRMWARE_ROOT}/backup} ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1} - RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}/recovery.bin} - BOOTFS=${BOOTFS:-/boot} CM4_ENABLE_RPI_EEPROM_UPDATE=${CM4_ENABLE_RPI_EEPROM_UPDATE:-0} RPI_EEPROM_UPDATE_CONFIG_TOOL="${RPI_EEPROM_UPDATE_CONFIG_TOOL:-raspi-config}" - --- a/rpi-eeprom-update-default +++ b/rpi-eeprom-update-default -@@ -1,8 +1,9 @@ +@@ -1,7 +1,7 @@ FIRMWARE_ROOT=/lib/firmware/raspberrypi/bootloader --FIRMWARE_RELEASE_STATUS="critical" -+FIRMWARE_RELEASE_STATUS="stable" - FIRMWARE_IMAGE_DIR="${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}" + FIRMWARE_RELEASE_STATUS="default" -FIRMWARE_BACKUP_DIR="/var/lib/raspberrypi/bootloader/backup" +FIRMWARE_BACKUP_DIR="${FIRMWARE_ROOT}/backup" - BOOTFS=/boot - USE_FLASHROM=0 EEPROM_CONFIG_HOOK= -+VCMAILBOX=/usr/bin/vcmailbox + + # BOOTFS can be set here to override auto-detection in rpi-eeprom-update diff --git a/bcm27xx-eeprom/patches/0002-rpi-eeprom-update-change-default-include-path.patch b/bcm27xx-eeprom/patches/0002-rpi-eeprom-update-change-default-include-path.patch new file mode 100644 index 000000000..840cd286f --- /dev/null +++ b/bcm27xx-eeprom/patches/0002-rpi-eeprom-update-change-default-include-path.patch @@ -0,0 +1,62 @@ +From fc552b1e5c503c530763e40d2b83df55c5c2e9a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 25 Mar 2020 20:58:35 +0100 +Subject: [PATCH] rpi-eeprom-update: change default include path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + rpi-eeprom-update | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/rpi-eeprom-update ++++ b/rpi-eeprom-update +@@ -6,8 +6,8 @@ set -e + + script_dir=$(cd "$(dirname "$0")" && pwd) + +-if [ -f /etc/default/rpi-eeprom-update ]; then +- . /etc/default/rpi-eeprom-update ++if [ -f /etc/bcm27xx-eeprom.conf ]; then ++ . /etc/bcm27xx-eeprom.conf + fi + + LOCAL_MODE=0 +@@ -423,7 +423,7 @@ checkDependencies() { + echo "Run with -h for more information." + echo + echo "To enable flashrom programming of the EEPROM" +- echo "Add these the following entries to /etc/default/rpi-eeprom-update" ++ echo "Add these the following entries to /etc/bcm27xx-eeprom.conf" + echo "RPI_EEPROM_USE_FLASHROM=1" + echo "CM4_ENABLE_RPI_EEPROM_UPDATE=1" + echo +@@ -514,7 +514,7 @@ The system should then boot normally. + + If /boot does not correspond to the boot partition and this + is not a NOOBS system, then the mount point for BOOTFS should be defined +-in /etc/default/rpi-eeprom-update by defining the BOOTFS variable. ++in /etc/bcm27xx-eeprom.conf by defining the BOOTFS variable. + + A backup of the current EEPROM config file is written to ${FIRMWARE_BACKUP_DIR} + before applying the update. +@@ -546,7 +546,7 @@ Options: + -u Install the specified VL805 (USB EEPROM) image file. + + Environment: +-Environment variables should be defined in /etc/default/rpi-eeprom-update ++Environment variables should be defined in /etc/bcm27xx-eeprom.conf + + EEPROM_CONFIG_HOOK + +@@ -618,7 +618,7 @@ must first be enabled by removing ENABLE + via usbboot. + + After enabling self-update set the CM4_ENABLE_RPI_EEPROM_UPDATE=1 environment +-variable or define it in /etc/default/rpi-eeprom-update. ++variable or define it in /etc/bcm27xx-eeprom.conf. + + N.B. If there is a power failure during SELF_UPDATE the EEPROM write may fail and + usbboot must be used to flash the bootloader EEPROM. SELF_UPDATE is not recommended diff --git a/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch b/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch deleted file mode 100644 index f24a9c3f1..000000000 --- a/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6674d49dea0104031b3f54df4c7a356dc4307bb2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 25 Mar 2020 20:58:35 +0100 -Subject: [PATCH] rpi-eeprom-update: change default include path -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - rpi-eeprom-update | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/rpi-eeprom-update -+++ b/rpi-eeprom-update -@@ -6,8 +6,8 @@ set -e - - script_dir=$(cd "$(dirname "$0")" && pwd) - --if [ -f /etc/default/rpi-eeprom-update ]; then -- . /etc/default/rpi-eeprom-update -+if [ -f /etc/bcm27xx-eeprom.conf ]; then -+ . /etc/bcm27xx-eeprom.conf - fi - - LOCAL_MODE=0 diff --git a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch b/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch similarity index 89% rename from bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch rename to bcm27xx-eeprom/patches/0003-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch index 5872f12da..344d001d8 100644 --- a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch +++ b/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch @@ -1,4 +1,4 @@ -From 8376ac74390af0ad736c88615e128b82a75eebc0 Mon Sep 17 00:00:00 2001 +From 62ec3384358bda60269c131d3880795bc8cdc3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 19 Feb 2021 10:54:23 +0100 Subject: [PATCH] rpi-eeprom-update: chmod silent (-f) is not supported @@ -13,7 +13,7 @@ Signed-off-by: Álvaro Fernández Rojas --- a/rpi-eeprom-update +++ b/rpi-eeprom-update -@@ -200,7 +200,7 @@ applyRecoveryUpdate() +@@ -216,7 +216,7 @@ applyRecoveryUpdate() || die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}" # For NFS mounts ensure that the files are readable to the TFTP user @@ -22,7 +22,7 @@ Signed-off-by: Álvaro Fernández Rojas || die "Failed to set permissions on eeprom update files" fi -@@ -211,7 +211,7 @@ applyRecoveryUpdate() +@@ -227,7 +227,7 @@ applyRecoveryUpdate() || die "Failed to copy ${VL805_UPDATE_IMAGE} to ${BOOTFS}/vl805.bin" # For NFS mounts ensure that the files are readable to the TFTP user diff --git a/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch b/bcm27xx-eeprom/patches/0004-rpi-eeprom-config-replace-nano-with-vi-as-default-ed.patch similarity index 54% rename from bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch rename to bcm27xx-eeprom/patches/0004-rpi-eeprom-config-replace-nano-with-vi-as-default-ed.patch index 6feb7602c..3cbdd7162 100644 --- a/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch +++ b/bcm27xx-eeprom/patches/0004-rpi-eeprom-config-replace-nano-with-vi-as-default-ed.patch @@ -1,6 +1,19 @@ +From 8d1e47c956ae10d1146114f7fcd4eb0d33187d08 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Tue, 16 Jan 2024 16:25:40 +0100 +Subject: [PATCH] rpi-eeprom-config: replace nano with vi as default editor +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + rpi-eeprom-config | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + --- a/rpi-eeprom-config +++ b/rpi-eeprom-config -@@ -166,8 +166,8 @@ def edit_config(eeprom=None): +@@ -184,8 +184,8 @@ def edit_config(eeprom=None): """ Implements something like 'git commit' for editing EEPROM configs. """ @@ -11,7 +24,7 @@ if 'EDITOR' in os.environ: editor = os.environ['EDITOR'] -@@ -428,7 +428,7 @@ Operating modes: +@@ -484,7 +484,7 @@ Operating modes: To cancel the pending update run 'sudo rpi-eeprom-update -r' From 013326d3eea1ffd0944edc9b7227fb7b04a84168 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Apr 2024 18:05:11 +0200 Subject: [PATCH 1498/2059] Update OpenVPN DCO --- ovpn-dco/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ovpn-dco/Makefile b/ovpn-dco/Makefile index 1f0181825..d41d0b8e3 100644 --- a/ovpn-dco/Makefile +++ b/ovpn-dco/Makefile @@ -10,13 +10,13 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ovpn-dco -PKG_VERSION:=0.2.20231127 +PKG_VERSION:=0.2.20240320 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/OpenVPN/ovpn-dco.git -PKG_SOURCE_VERSION:=c24380cdb8f5eef5a04059bbe82ad4ba4d3616c3 +PKG_SOURCE_VERSION:=2aa7f931803f81d2745b0cefafb63654a35cc3d5 PKG_MAINTAINER:=Yannick Chabanois PKG_LICENSE:=GPL-2.0-only From 8db8182adc91e39f6509fc6b9efc2573a166d3ec Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Apr 2024 18:05:31 +0200 Subject: [PATCH 1499/2059] Update Shadowsocks-Rust --- shadowsocks-rust/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile index 8942c1e89..ed6fe390b 100644 --- a/shadowsocks-rust/Makefile +++ b/shadowsocks-rust/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=shadowsocks-rust -PKG_VERSION:=1.18.1 -PKG_HASH:=c2e1d8838e4578c0a6b0de6e1da00e9ece2d780dc452117fd109bb091e5d106f +PKG_VERSION:=1.18.2 +PKG_HASH:=b772792e2d3f8ccc3a5d5255bfc65b85801b97e1139bbb0e50d39a91fb7d9e61 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz From b754f893e3a21c87abd53998509a5338fff8b053 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Apr 2024 18:05:47 +0200 Subject: [PATCH 1500/2059] Update XRay --- xray-core/Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/xray-core/Makefile b/xray-core/Makefile index d2ec1ee23..c8fbc231f 100644 --- a/xray-core/Makefile +++ b/xray-core/Makefile @@ -1,7 +1,14 @@ +# +# Copyright (C) 2023-2024 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + include $(TOPDIR)/rules.mk PKG_NAME:=xray -PKG_VERSION:=1.8.6 +PKG_VERSION:=1.8.10 PKG_RELEASE:=1 PKG_LICENSE:=MPLv2 @@ -9,7 +16,7 @@ PKG_LICENSE_FILES:=LICENSE PKG_MAINTAINER:=Yannick Chabanois PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/XTLS/Xray-core.git -PKG_SOURCE_VERSION:=5a5e615b46369579240dac1fdfe2b5e122c4c4ce +PKG_SOURCE_VERSION:=284316776148c5442fb25975d05cbbfd25b8c88d PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 From 3d76e089fed69363b8b978e2c6fe936a78a53045 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Apr 2024 18:06:05 +0200 Subject: [PATCH 1501/2059] Add compilation on kernel 6.6 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ada11f93c..9a308aa68 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, rutx12, rutx50, r5s, qnap-301w, rpi5, z8102ax_128m] - OMR_KERNEL: [5.4, 6.1] + OMR_KERNEL: [5.4, 6.1, 6.6] runs-on: ubuntu-latest continue-on-error: true From 6b592fe94d4817ea3edc0c6146d423442c08ad56 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Apr 2024 11:09:29 +0200 Subject: [PATCH 1502/2059] Update r8125 --- r8125/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/r8125/Makefile b/r8125/Makefile index b72462a66..827bca720 100644 --- a/r8125/Makefile +++ b/r8125/Makefile @@ -7,13 +7,13 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=r8125 -PKG_VERSION:=9.012.03-1 +PKG_VERSION:=9.012.04-1 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/awesometic/realtek-r8125-dkms/tar.gz/$(PKG_VERSION)? -PKG_HASH:=7964aacf4a2873cbe4133aeca830bd0725f819ea286bab162026ff283510144f +PKG_HASH:=470f02f1f3e9a12a0443128f5efd5e254e5e8e94487a5ab949724100fdca6ab4 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/realtek-$(PKG_NAME)-dkms-$(PKG_VERSION) PKG_LICENSE:=GPL-2.0-only PKG_LICENSE_FILES:=LICENSE From 9348ce096baf5915207c20e30a087484f0e59006 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Apr 2024 11:09:42 +0200 Subject: [PATCH 1503/2059] Update tsping --- tsping/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsping/Makefile b/tsping/Makefile index e26a2e642..a87152e56 100644 --- a/tsping/Makefile +++ b/tsping/Makefile @@ -6,7 +6,7 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/Lochnair/tsping -PKG_SOURCE_VERSION:=2560d79c95154d2e2c9aa6725135f6fc5cf091d7 +PKG_SOURCE_VERSION:=0b5884b1d20498a409ebd1fc529d8be97f6ef357 PKG_MAINTAINER:=Nils Andreas Svee PKG_LICENSE:=BSD-3-Clause From 9fcf5fd5b6b5087d3db40bb55b93c7064ba0ddee Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Apr 2024 11:10:03 +0200 Subject: [PATCH 1504/2059] Add luci-theme-alpha --- luci-theme-alpha/LICENSE | 201 + luci-theme-alpha/Makefile | 54 + luci-theme-alpha/README.md | 53 + luci-theme-alpha/js/menu-alpha.js | 179 + luci-theme-alpha/luasrc/app.js | 35 + .../luasrc/background/dashboard.png | Bin 0 -> 681498 bytes luci-theme-alpha/luasrc/background/login.png | Bin 0 -> 681498 bytes luci-theme-alpha/luasrc/brand.png | Bin 0 -> 50790 bytes luci-theme-alpha/luasrc/favicon.png | Bin 0 -> 535 bytes .../luasrc/fonts/Inter-Black.woff2 | Bin 0 -> 97120 bytes .../luasrc/fonts/Inter-Bold.woff2 | Bin 0 -> 100096 bytes .../luasrc/fonts/Inter-ExtraBold.woff2 | Bin 0 -> 100016 bytes .../luasrc/fonts/Inter-ExtraLight.woff2 | Bin 0 -> 98168 bytes .../luasrc/fonts/Inter-Light.woff2 | Bin 0 -> 97992 bytes .../luasrc/fonts/Inter-Medium.woff2 | Bin 0 -> 99020 bytes .../luasrc/fonts/Inter-Regular.woff2 | Bin 0 -> 91944 bytes .../luasrc/fonts/Inter-SemiBold.woff2 | Bin 0 -> 99748 bytes .../luasrc/fonts/Inter-Thin.woff2 | Bin 0 -> 92752 bytes .../luasrc/fonts/Quicksand-Bold.ttf | Bin 0 -> 78220 bytes .../luasrc/fonts/Quicksand-Light.ttf | Bin 0 -> 78384 bytes .../luasrc/fonts/Quicksand-Medium.ttf | Bin 0 -> 78620 bytes .../luasrc/fonts/Quicksand-Regular.ttf | Bin 0 -> 78628 bytes .../luasrc/fonts/Quicksand-SemiBold.ttf | Bin 0 -> 78500 bytes luci-theme-alpha/luasrc/fonts/stylesheet.css | 71 + luci-theme-alpha/luasrc/gaya/gaya.css | 3609 +++++++++++++++++ luci-theme-alpha/luasrc/gaya/icon/arrow.svg | 1 + luci-theme-alpha/luasrc/gaya/icon/loading.svg | 21 + luci-theme-alpha/luasrc/gaya/icon/logout.svg | 25 + .../luasrc/gaya/icon/menu_icon.svg | 1 + .../luasrc/gaya/icon/navbar/interface.png | Bin 0 -> 21524 bytes .../luasrc/gaya/icon/navbar/modem.png | Bin 0 -> 8995 bytes .../luasrc/gaya/icon/navbar/nas.png | Bin 0 -> 14997 bytes .../luasrc/gaya/icon/navbar/neko.png | Bin 0 -> 29160 bytes .../luasrc/gaya/icon/navbar/oc.png | Bin 0 -> 17668 bytes .../luasrc/gaya/icon/navbar/status.png | Bin 0 -> 14160 bytes .../luasrc/gaya/icon/navbar/terminal.png | Bin 0 -> 15047 bytes luci-theme-alpha/luasrc/gaya/icon/pause.svg | 24 + luci-theme-alpha/luasrc/gaya/icon/save.svg | 21 + .../luasrc/gaya/icon/sidebar-icon/app.svg | 22 + .../luasrc/gaya/icon/sidebar-icon/docker.svg | 33 + .../luasrc/gaya/icon/sidebar-icon/istore.svg | 12 + .../luasrc/gaya/icon/sidebar-icon/modem.svg | 22 + .../luasrc/gaya/icon/sidebar-icon/nas.svg | 22 + .../luasrc/gaya/icon/sidebar-icon/network.svg | 27 + .../gaya/icon/sidebar-icon/services.svg | 22 + .../luasrc/gaya/icon/sidebar-icon/status.svg | 22 + .../luasrc/gaya/icon/sidebar-icon/system.svg | 28 + .../luasrc/gaya/icon/sidebar-icon/vpn.svg | 22 + luci-theme-alpha/luasrc/style/brand.png | Bin 0 -> 103596 bytes luci-theme-alpha/luasrc/style/catatan.txt | 1 + luci-theme-alpha/luasrc/style/indo-wrt.png | Bin 0 -> 11475 bytes luci-theme-alpha/luasrc/style/style.css | 416 ++ luci-theme-alpha/mobileview1.png | Bin 0 -> 228381 bytes luci-theme-alpha/mobileview2.png | Bin 0 -> 243872 bytes luci-theme-alpha/mobileview3.png | Bin 0 -> 159272 bytes luci-theme-alpha/root/etc/config/alpha | 7 + luci-theme-alpha/ss1.png | Bin 0 -> 776425 bytes luci-theme-alpha/ss2.png | Bin 0 -> 561846 bytes luci-theme-alpha/ss3.png | Bin 0 -> 493495 bytes luci-theme-alpha/template/footer.htm | 108 + luci-theme-alpha/template/header.htm | 96 + luci-theme-alpha/template/sysauth.htm | 86 + 62 files changed, 5241 insertions(+) create mode 100644 luci-theme-alpha/LICENSE create mode 100644 luci-theme-alpha/Makefile create mode 100644 luci-theme-alpha/README.md create mode 100644 luci-theme-alpha/js/menu-alpha.js create mode 100644 luci-theme-alpha/luasrc/app.js create mode 100644 luci-theme-alpha/luasrc/background/dashboard.png create mode 100644 luci-theme-alpha/luasrc/background/login.png create mode 100644 luci-theme-alpha/luasrc/brand.png create mode 100644 luci-theme-alpha/luasrc/favicon.png create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-Black.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-Bold.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-ExtraBold.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-ExtraLight.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-Light.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-Medium.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-Regular.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-SemiBold.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Inter-Thin.woff2 create mode 100644 luci-theme-alpha/luasrc/fonts/Quicksand-Bold.ttf create mode 100644 luci-theme-alpha/luasrc/fonts/Quicksand-Light.ttf create mode 100644 luci-theme-alpha/luasrc/fonts/Quicksand-Medium.ttf create mode 100644 luci-theme-alpha/luasrc/fonts/Quicksand-Regular.ttf create mode 100644 luci-theme-alpha/luasrc/fonts/Quicksand-SemiBold.ttf create mode 100644 luci-theme-alpha/luasrc/fonts/stylesheet.css create mode 100755 luci-theme-alpha/luasrc/gaya/gaya.css create mode 100644 luci-theme-alpha/luasrc/gaya/icon/arrow.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/loading.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/logout.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/menu_icon.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/navbar/interface.png create mode 100644 luci-theme-alpha/luasrc/gaya/icon/navbar/modem.png create mode 100644 luci-theme-alpha/luasrc/gaya/icon/navbar/nas.png create mode 100644 luci-theme-alpha/luasrc/gaya/icon/navbar/neko.png create mode 100644 luci-theme-alpha/luasrc/gaya/icon/navbar/oc.png create mode 100644 luci-theme-alpha/luasrc/gaya/icon/navbar/status.png create mode 100644 luci-theme-alpha/luasrc/gaya/icon/navbar/terminal.png create mode 100644 luci-theme-alpha/luasrc/gaya/icon/pause.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/save.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/app.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/docker.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/istore.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/modem.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/nas.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/network.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/services.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/status.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/system.svg create mode 100644 luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/vpn.svg create mode 100644 luci-theme-alpha/luasrc/style/brand.png create mode 100644 luci-theme-alpha/luasrc/style/catatan.txt create mode 100644 luci-theme-alpha/luasrc/style/indo-wrt.png create mode 100644 luci-theme-alpha/luasrc/style/style.css create mode 100644 luci-theme-alpha/mobileview1.png create mode 100644 luci-theme-alpha/mobileview2.png create mode 100644 luci-theme-alpha/mobileview3.png create mode 100644 luci-theme-alpha/root/etc/config/alpha create mode 100644 luci-theme-alpha/ss1.png create mode 100644 luci-theme-alpha/ss2.png create mode 100644 luci-theme-alpha/ss3.png create mode 100644 luci-theme-alpha/template/footer.htm create mode 100644 luci-theme-alpha/template/header.htm create mode 100644 luci-theme-alpha/template/sysauth.htm diff --git a/luci-theme-alpha/LICENSE b/luci-theme-alpha/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/luci-theme-alpha/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/luci-theme-alpha/Makefile b/luci-theme-alpha/Makefile new file mode 100644 index 000000000..44174974a --- /dev/null +++ b/luci-theme-alpha/Makefile @@ -0,0 +1,54 @@ +# LuCI Alpha Theme +# Copyright 2024 derisamedia +# +# Licensed under the Apache License v2.0 +# http://www.apache.org/licenses/LICENSE-2.0 + +include $(TOPDIR)/rules.mk + +THEME_NAME:=alpha +THEME_TITLE:=Alpha + +PKG_NAME:=luci-theme-$(THEME_NAME) +PKG_VERSION:=3.9.4-beta +PKG_RELEASE:=9 + +include $(INCLUDE_DIR)/package.mk + +define Package/luci-theme-$(THEME_NAME) + SECTION:=luci + CATEGORY:=LuCI + SUBMENU:=9. Themes + DEPENDS:=+libc + TITLE:=LuCi Theme For OpenWrt And Alpha OS ONLY - $(THEME_TITLE) + URL:=http://facebook.com/derisamedia/ + PKGARCH:=all +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/luci-theme-$(THEME_NAME)/install + $(INSTALL_DIR) $(1)/etc/uci-defaults + echo "uci set luci.themes.$(THEME_TITLE)=/luci-static/$(THEME_NAME); uci commit luci" > $(1)/etc/uci-defaults/30-luci-theme-$(THEME_NAME) + $(INSTALL_DIR) $(1)/www/luci-static/$(THEME_NAME) + $(CP) -a ./luasrc/* $(1)/www/luci-static/$(THEME_NAME)/ 2>/dev/null || true + $(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/themes/$(THEME_NAME) + $(CP) -a ./template/* $(1)/usr/lib/lua/luci/view/themes/$(THEME_NAME)/ 2>/dev/null || true + $(INSTALL_DIR) $(1)/www/luci-static/resources + $(CP) -a ./js/* $(1)/www/luci-static/resources/ 2>/dev/null || true + $(INSTALL_DIR) $(1)/etc/config + $(CP) -a ./root/etc/config/* $(1)/etc/config/ 2>/dev/null || true +endef + +define Package/luci-theme-$(THEME_NAME)/postinst +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/30-luci-theme-$(THEME_NAME) ) && rm -f /etc/uci-defaults/30-luci-theme-$(THEME_NAME) +} +endef + +$(eval $(call BuildPackage,luci-theme-$(THEME_NAME))) diff --git a/luci-theme-alpha/README.md b/luci-theme-alpha/README.md new file mode 100644 index 000000000..0ee085099 --- /dev/null +++ b/luci-theme-alpha/README.md @@ -0,0 +1,53 @@ +[issues]: https://github.com/derisamedia/luci-theme-alpha/issues +[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square +[release]: https://github.com/derisamedia/luci-theme-alpha/releases +[release-badge]: https://img.shields.io/badge/download-check_releases-blue +[group]: https://facebook.com/groups/indowrt +[group-badge]: https://img.shields.io/badge/visit_Facebook-Comunity-cyan +[discord]: https://discord.gg/gdZwmDQGUm +[discord-badge]: https://img.shields.io/badge/visit_Discord-Comunity-blue + + + + + + + +# luci-theme-alpha (BETA) +
    + + +[![issues][issues-badge]][issues] +[![release][release-badge]][release] +[![group][group-badge]][group] +[![discord][discord-badge]][discord] + + +Luci theme for Official Openwrt and Alpha OS build ,based on bootstrap and material luCi theme refferences, +Preview Screenshoot +

    + +![image](https://raw.githubusercontent.com/derisamedia/luci-theme-alpha/master/ss1.png) + +![image](https://raw.githubusercontent.com/derisamedia/luci-theme-alpha/master/ss2.png) + +![image](https://raw.githubusercontent.com/derisamedia/luci-theme-alpha/master/ss3.png) + +![image](https://raw.githubusercontent.com/derisamedia/luci-theme-alpha/master/mobileview1.png) + +![image](https://raw.githubusercontent.com/derisamedia/luci-theme-alpha/master/mobileview2.png) + +![image](https://raw.githubusercontent.com/derisamedia/luci-theme-alpha/master/mobileview3.png) + +

    + +### FYI + +alpha os is my idea which wants to develop the OpenWrt community in Indonesia, even the world, thanks to friends who have supported this alpha-os theme, hopefully given health to all of us. + + +(old text) Mr. Sibondt once they said 'jalan ditempat komunitas indo', that's what moved my heart to make an innovation that I named alpha os (alpha = initial version, because it hasn't been perfect until now 😁) + +donate +buy me a padang rice or coffee +https://saweria.co/derisamedia diff --git a/luci-theme-alpha/js/menu-alpha.js b/luci-theme-alpha/js/menu-alpha.js new file mode 100644 index 000000000..62cae62e7 --- /dev/null +++ b/luci-theme-alpha/js/menu-alpha.js @@ -0,0 +1,179 @@ +"use strict"; +"require baseclass"; +"require ui"; +return baseclass.extend({ + __init__: function () { + ui.menu.load().then(L.bind(this.render, this)); + }, + render: function (tree) { + var node = tree, + url = ""; + this.renderModeMenu(node); + if (L.env.dispatchpath.length >= 3) { + for (var i = 0; i < 3 && node; i++) { + node = node.children[L.env.dispatchpath[i]]; + url = url + (url ? "/" : "") + L.env.dispatchpath[i]; + } + if (node) this.renderTabMenu(node, url); + } + document + .querySelector(".showSide") + .addEventListener( + "click", + ui.createHandlerFn(this, "handleSidebarToggle") + ); + document + .querySelector(".darkMask") + .addEventListener( + "click", + ui.createHandlerFn(this, "handleSidebarToggle") + ); + document.querySelector(".main > .loading").style.opacity = "0"; + document.querySelector(".main > .loading").style.visibility = "hidden"; + if (window.innerWidth <= 1152) + document.querySelector(".main-left").style.width = "0"; + window.addEventListener("resize", this.handleSidebarToggle, true); + }, + handleMenuExpand: function (ev) { + var a = ev.target, + ul1 = a.parentNode, + ul2 = a.nextElementSibling; + document.querySelectorAll("li.slide.active").forEach(function (li) { + if (li !== a.parentNode || li == ul1) { + li.classList.remove("active"); + li.childNodes[0].classList.remove("active"); + } + if (li == ul1) return; + }); + if (!ul2) return; + if ( + ul2.parentNode.offsetLeft + ul2.offsetWidth <= + ul1.offsetLeft + ul1.offsetWidth + ) + ul2.classList.add("align-left"); + ul1.classList.add("active"); + a.classList.add("active"); + a.blur(); + ev.preventDefault(); + ev.stopPropagation(); + }, + renderMainMenu: function (tree, url, level) { + var l = (level || 0) + 1, + ul = E("ul", { class: level ? "slide-menu" : "nav" }), + children = ui.menu.getChildren(tree); + if (children.length == 0 || l > 2) return E([]); + for (var i = 0; i < children.length; i++) { + var isActive = L.env.dispatchpath[l] == children[i].name, + submenu = this.renderMainMenu( + children[i], + url + "/" + children[i].name, + l + ), + hasChildren = submenu.children.length; + ul.appendChild( + E( + "li", + { + class: hasChildren + ? "slide" + (isActive ? " active" : "") + : isActive + ? " active" + : "", + }, + [ + E( + "a", + { + href: hasChildren ? "#" : L.url(url, children[i].name), + class: hasChildren + ? "menu" + (isActive ? " active" : "") + : null, + click: hasChildren + ? ui.createHandlerFn(this, "handleMenuExpand") + : null, + "data-title": hasChildren + ? children[i].title + : _(children[i].title), + }, + [_(children[i].title)] + ), + submenu, + ] + ) + ); + } + if (l == 1) { + var container = document.querySelector("#mainmenu"); + container.appendChild(ul); + container.style.display = ""; + } + return ul; + }, + renderModeMenu: function (tree) { + var ul = document.querySelector("#modemenu"), + children = ui.menu.getChildren(tree); + for (var i = 0; i < children.length; i++) { + var isActive = L.env.requestpath.length + ? children[i].name == L.env.requestpath[0] + : i == 0; + ul.appendChild( + E("li", {}, [ + E( + "a", + { + href: L.url(children[i].name), + class: isActive ? "active" : null, + }, + [_(children[i].title)] + ), + ]) + ); + if (isActive) this.renderMainMenu(children[i], children[i].name); + if (i > 0 && i < children.length) + ul.appendChild(E("li", { class: "divider" }, [E("span")])); + } + if (children.length > 1) ul.parentElement.style.display = ""; + }, + renderTabMenu: function (tree, url, level) { + var container = document.querySelector("#tabmenu"), + l = (level || 0) + 1, + ul = E("ul", { class: "tabs" }), + children = ui.menu.getChildren(tree), + activeNode = null; + if (children.length == 0) return E([]); + for (var i = 0; i < children.length; i++) { + var isActive = L.env.dispatchpath[l + 2] == children[i].name, + activeClass = isActive ? " active" : "", + className = "tabmenu-item-%s %s".format(children[i].name, activeClass); + ul.appendChild( + E("li", { class: className }, [ + E("a", { href: L.url(url, children[i].name) }, [ + _(children[i].title), + ]), + ]) + ); + if (isActive) activeNode = children[i]; + } + container.appendChild(ul); + container.style.display = ""; + if (activeNode) + container.appendChild( + this.renderTabMenu(activeNode, url + "/" + activeNode.name, l) + ); + return ul; + }, + handleSidebarToggle: function (ev) { + var width = window.innerWidth, + darkMask = document.querySelector(".darkMask"), + mainRight = document.querySelector(".main-right"), + mainLeft = document.querySelector(".main-left"), + open = mainLeft.style.width == ""; + if (width > 1152 || ev.type == "resize") open = true; + darkMask.style.visibility = open ? "" : "visible"; + darkMask.style.opacity = open ? "" : 1; + if (width <= 1152) mainLeft.style.width = open ? "0" : ""; + else mainLeft.style.width = ""; + mainLeft.style.visibility = open ? "" : "visible"; + mainRight.style["overflow-y"] = open ? "visible" : "hidden"; + }, +}); diff --git a/luci-theme-alpha/luasrc/app.js b/luci-theme-alpha/luasrc/app.js new file mode 100644 index 000000000..c61ad0834 --- /dev/null +++ b/luci-theme-alpha/luasrc/app.js @@ -0,0 +1,35 @@ +(function () { + // your page initialization code here + // the DOM will be available here + + const toggler = document.querySelector(".toggler"); + console.log(toggler); + toggler.addEventListener( + "click", + function (e) { + const element = document.querySelector(".navbar"); + element.classList.toggle("active"); + }, + false + ); + + // const isDark = localStorage.getItem("isDark"); + // if (isDark == 1) { + // const element = document.querySelector("body"); + // element.classList.add("dark"); + // } + // const themetoggler = document.querySelector(".themetoggler"); + // themetoggler.addEventListener( + // "click", + // function (e) { + // e.preventDefault(); + // const element = document.querySelector("body"); + // element.classList.toggle("dark"); + + // const isDark = localStorage.getItem("isDark"); + // localStorage.setItem("isDark", isDark == 1 ? 0 : 1); + // }, + // false + // ); + })(); + \ No newline at end of file diff --git a/luci-theme-alpha/luasrc/background/dashboard.png b/luci-theme-alpha/luasrc/background/dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..e8fff792586660e168e4ac009daa3001c5bbc9cb GIT binary patch literal 681498 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�Per13yE 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�Foy)= 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

    kEe6$t%^QJ=YV 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≀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 al>Y~>eXRt7IxSrQ0000 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/background/login.png b/luci-theme-alpha/luasrc/background/login.png new file mode 100644 index 0000000000000000000000000000000000000000..e8fff792586660e168e4ac009daa3001c5bbc9cb GIT binary patch literal 681498 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�Per13yE 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�Foy)= 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

    kEe6$t%^QJ=YV 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≀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 al>Y~>eXRt7IxSrQ0000 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/brand.png b/luci-theme-alpha/luasrc/brand.png new file mode 100644 index 0000000000000000000000000000000000000000..f8584ac11a5020cc2dfe049b6b87025ab7c35782 GIT binary patch literal 50790 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 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/favicon.png b/luci-theme-alpha/luasrc/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7c3f3acb1f0c7c142d0dbd3f42a4926b07f8eb38 GIT binary patch literal 535 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∓jK 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

    Y%OXJ}YWj*QexQBS+ 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

    V{38#V(R$NG@wp8Y894 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 From 5427b7a40cf8fb99075156af1ca90a61fee807b6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 30 Dec 2023 08:50:57 +0100 Subject: [PATCH 1255/2059] Add ByPass via server VPN support --- .../resources/view/services/omr-bypass.js | 14 +++++ omr-bypass/files/etc/init.d/omr-bypass | 63 +++++++++++++++---- .../files/etc/init.d/openmptcprouter-vps | 23 ++++++- 3 files changed, 84 insertions(+), 16 deletions(-) diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js index e76e1ac8d..62cbc973e 100644 --- a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js +++ b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js @@ -48,10 +48,13 @@ return L.view.extend({ o = s.option(form.Value, 'name', _('Domain')); o.rmempty = false; + o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); + o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used.')); o.noaliases = true; o.noinactive = true; o.nocreate = true; + o.depends('vpn', '0'); o = s.option(form.Value, 'note', _('Note')); o.rmempty = true; @@ -78,10 +81,13 @@ return L.view.extend({ o = s.option(form.Value, 'ip', _('IP')); o.rmempty = false; + o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); + o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used.')); o.noaliases = true; o.noinactive = true; o.nocreate = true; + o.depends('vpn', '0'); o = s.option(form.Value, 'note', _('Note')); o.rmempty = true; @@ -199,10 +205,14 @@ return L.view.extend({ o = s.option(form.Value, 'asn', _('ASN')); o.rmempty = false; + o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); + + o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used.')); o.noaliases = true; o.noinactive = true; o.nocreate = true; + o.depends('vpn', '0'); o = s.option(form.Value, 'note', _('Note')); o.rmempty = true; @@ -255,10 +265,13 @@ return L.view.extend({ },this)); }; + o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); + o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used (or an other interface if master is down).')); o.noaliases = true; o.noinactive = true; o.nocreate = true; + o.depends('vpn', '0'); o = s.option(form.Value, 'note', _('Note')); o.rmempty = true; @@ -278,6 +291,7 @@ return L.view.extend({ o = s.option(form.Flag, 'ndpi', _('Enable ndpi')); o.default = o.enabled; o.modalonly = true + o.depends('vpn', '0'); } return m.render(); diff --git a/omr-bypass/files/etc/init.d/omr-bypass b/omr-bypass/files/etc/init.d/omr-bypass index 413165173..1d292c55a 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass +++ b/omr-bypass/files/etc/init.d/omr-bypass @@ -73,8 +73,8 @@ _bypass_domains() { config_get enabled $1 enabled config_get noipv6 $1 noipv6 config_get family $1 family - config_get vpn $1 vpn [ -z "$intf" ] && intf="all" + config_get vpn $1 vpn [ "$vpn" = "1" ] && intf="srv_vpn1" [ "$enabled" = "0" ] && return [ -z "$domain" ] && return @@ -391,6 +391,9 @@ _bypass_proto() { config_get ndpi $1 ndpi config_get noipv6 $1 noipv6 config_get family $1 family + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + [ "$enabled" = "0" ] && return [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" @@ -400,7 +403,7 @@ _bypass_proto() { [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return - if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ] && [ "$ndpi" != "0" ]; then + if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ] && [ "$ndpi" != "0" ] && [ "$vpn" != "1" ]; then if [ "$intf" = "all" ]; then if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF @@ -487,6 +490,9 @@ _bypass_proto_without_ndpi() { config_get ndpi $1 ndpi "0" config_get noipv6 $1 noipv6 config_get family $1 family + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + [ "$enabled" = "0" ] && return [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" @@ -496,22 +502,32 @@ _bypass_proto_without_ndpi() { [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return - if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ]; then + if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ] || [ "$vpn" = "1" ]; then ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") if [ -n "$ALLIPS" ]; then - ipset -q flush bypass_$proto > /dev/null 2>&1 - ipset -q flush bypass6_$proto > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create bypass_$proto hash:net hashsize 64 - create bypass6_$proto hash:net family inet6 hashsize 64 - EOF + if [ "$vpn" != "1" ]; then + ipset -q flush bypass_$proto > /dev/null 2>&1 + ipset -q flush bypass6_$proto > /dev/null 2>&1 + ipset -q --exist restore <<-EOF + create bypass_$proto hash:net hashsize 64 + create bypass6_$proto hash:net family inet6 hashsize 64 + EOF + fi for ip in $ALLIPS; do valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then - ipset -q add bypass_$proto $ip + if [ "$vpn" != "1" ]; then + ipset -q add bypass_$proto $ip + else + ipset -q add omr_dst_bypass_$intf $ip + fi elif [ "$valid_ip6" = "ok" ]; then - ipset -q add bypass6_$proto $ip + if [ "$vpn" != "1" ]; then + ipset -q add bypass6_$proto $ip + else + ipset -q add omr6_dst_bypass_$intf $ip + fi fi done if [ "$intf" = "all" ]; then @@ -531,7 +547,7 @@ _bypass_proto_without_ndpi() { COMMIT EOF fi - else + elif [ "$vpn" != "1" ]; then if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle @@ -1025,6 +1041,12 @@ start_service() { -A PREROUTING -j omr-bypass6 COMMIT EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass6-local - + -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass6-local + COMMIT + EOF fi config_load network @@ -1080,7 +1102,22 @@ start_service() { COMMIT EOF fi - + if [ "$disableipv6" = "0" ]; then + if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass6 -m mark --mark 0x539 -j RETURN + COMMIT + EOF + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-local -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 + -A omr-bypass6-local -m mark --mark 0x539 -j RETURN + COMMIT + EOF + fi + fi config_load shadowsocks-libev config_foreach _ss_rules_config config_load shadowsocks-rust diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index f11cfe5fa..6b8c127c2 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1,12 +1,12 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) # Released under GPL 3. See LICENSE for the full terms. START=99 USE_PROCD=1 -EXTRA_COMMANDS="set_pihole backup_send backup_get backup_list set_vps_firewall get_openvpn_key set_gre_tunnel token" +EXTRA_COMMANDS="set_pihole backup_send backup_get backup_list set_vps_firewall get_openvpn_key set_gre_tunnel token set_bypass_ips" . /usr/lib/unbound/iptools.sh @@ -944,6 +944,22 @@ _set_lan_ip() { fi } +_set_bypass_ips() { + local settings + [ -z "$servername" ] && servername=$1 + bypassipv4s=$(ipset -q -o save list omr_dst_bypass_srv_vpn1 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + if [ "$bypassipv4s" != "" ] || [ "$bypassipv6s" != "" ]; then + settings='{"ipv4s" : ['$bypassipv4s'],"ipv6s" : ['$bypassipv6s'],"intf" : "vpn1"}' + result=$(_set_json "bypass" "$settings") + fi +} + +set_bypass_ips() { + config_load openmptcprouter + config_foreach _set_bypass_ips server +} + _set_vpn_ip() { local settings [ -z "$vps_config" ] && vps_config=$(_get_json "config") @@ -997,7 +1013,7 @@ _set_client2client() { c2cid=$((c2cid+1)) targetip=$(echo $lanip | awk -F '/' '{print $1}' | tr -d "\n") netmask=$(echo $lanip | awk -F '/' '{print $2}' | tr -d "\n") - target=$(ipcalc.sh $targetip $netmask | grep NETWORK | awk -F '=' '{print $2}' | tr -d "\n") + target=$(ipcalc.sh $targetip/$netmask | grep NETWORK | awk -F '=' '{print $2}' | tr -d "\n") uci -q batch <<-EOF >/dev/null set network.omr_client2client_${c2cid}=route set network.omr_client2client_${c2cid}.interface=omrvpn @@ -2264,6 +2280,7 @@ _config_service() { config_foreach _get_lan_ip interface _set_lan_ip _set_sipalg + _set_bypass_ips config_foreach _delete_client2client route if [ "$(uci -q get openmptcprouter.settings.vpn)" != "openvpn" ] && [ "$(echo "$vps_config" | jsonfilter -q -e '@.client2client.enabled')" == "true" ]; then _set_client2client From c7dc600f824f362c64b5162fb5a881fd13721861 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 30 Dec 2023 08:51:42 +0100 Subject: [PATCH 1256/2059] Fix status page info when backup VPS is used --- omr-tracker/files/bin/omr-tracker-server | 9 +++++++++ .../files/usr/libexec/rpcd/openmptcprouter | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index fcab8b2d4..7d39f48ea 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -37,6 +37,11 @@ _check_server() { done } +_disable_current() { + local serv=$1 + config_set $serv current "0" +} + _disable_redir() { local redir=$1 config_get server $redir server @@ -86,6 +91,8 @@ _check_master() { set shadowsocks-rust.sss${count}.server=$ip EOF if [ "$count" -eq "0" ]; then + config_load openmptcprouter + config_foreach _disable_current server uci -q batch <<-EOF >/dev/null set xray.omrout.s_vmess_address=$ip set xray.omrout.s_vless_address=$ip @@ -225,6 +232,8 @@ _check_backup() { set shadowsocks-rust.sss${count}.server=$ip EOF if [ "$count" -eq "0" ]; then + config_load openmptcprouter + config_foreach _disable_current server uci -q batch <<-EOF >/dev/null set xray.omrout.s_vmess_address=$ip set xray.omrout.s_vless_address=$ip diff --git a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter index 3dfda3661..2301d0c3a 100755 --- a/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter +++ b/openmptcprouter-api/files/usr/libexec/rpcd/openmptcprouter @@ -870,9 +870,10 @@ function interfaces_status() ucic:foreach("openmptcprouter", "server", function(s) local serverips = uci:get("openmptcprouter",s[".name"],"ip") or { "" } local master = uci:get("openmptcprouter",s[".name"],"master") or "1" + local current = uci:get("openmptcprouter",s[".name"],"current") or "0" for key, value in pairs(serverips) do serverip = value - if serverip ~= "" and (master == "1" or mArray.openmptcprouter["wan_addr"] == serverip or mArray.openmptcprouter["wan_addr6"] == serverip) and mArray.openmptcprouter["vps_admin"] == false then + if serverip ~= "" and (current == "1" or mArray.openmptcprouter["wan_addr"] == serverip or mArray.openmptcprouter["wan_addr6"] == serverip) and mArray.openmptcprouter["vps_admin"] == false then mArray.openmptcprouter["vps_omr_version"] = uci:get("openmptcprouter", s[".name"], "omr_version") or "" mArray.openmptcprouter["vps_kernel"] = uci:get("openmptcprouter",s[".name"],"kernel") or "" mArray.openmptcprouter["vps_machine"] = uci:get("openmptcprouter",s[".name"],"machine") or "" @@ -980,6 +981,7 @@ function interfaces_status() else mArray.openmptcprouter["vps_admin"] = false mArray.openmptcprouter["vps_admin_error_msg"] = "No token yet available" + uci:set("openmptcprouter",s[".name"],"token_error","1") end if mArray.openmptcprouter["vps_admin"] == false then if mArray.openmptcprouter["service_addr_ip"] ~= "" then From 544d69742e8cd8ab35d54cc23d365690defccc51 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 1 Jan 2024 21:01:18 +0100 Subject: [PATCH 1257/2059] Fix fw error --- omr-bypass/files/etc/firewall.omr-bypass | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-bypass/files/etc/firewall.omr-bypass b/omr-bypass/files/etc/firewall.omr-bypass index 6cbac141c..3e7432865 100644 --- a/omr-bypass/files/etc/firewall.omr-bypass +++ b/omr-bypass/files/etc/firewall.omr-bypass @@ -1,2 +1,2 @@ #!/bin/sh -[ -z "$(pgrep -f omr-bypass)" ] && logger -t "firewall.omr-bypass" "reload omr-bypass rules" && /etc/init.d/omr-bypass reload_rules +[ -z "$(pgrep -f omr-bypass 2>&1 >/dev/null)" ] && logger -t "firewall.omr-bypass" "reload omr-bypass rules" && /etc/init.d/omr-bypass reload_rules From e31af4e8ec691a14ae6e7f38a5db0e975d7f64a1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Jan 2024 17:25:45 +0100 Subject: [PATCH 1258/2059] Update ModemManager --- modemmanager/Makefile | 4 ++-- .../100-ublox-remove-ID_MM_PROCESS-tags.patch | 13 ------------- 2 files changed, 2 insertions(+), 15 deletions(-) delete mode 100644 modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch diff --git a/modemmanager/Makefile b/modemmanager/Makefile index d30b1a2e9..d422ec416 100644 --- a/modemmanager/Makefile +++ b/modemmanager/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=modemmanager -PKG_SOURCE_VERSION:=1.22.0 +PKG_SOURCE_VERSION:=1.23.2-dev PKG_RELEASE:=5 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git -PKG_MIRROR_HASH:=98daa1a15075c88afb3ed0de20dc83fe51d2ba3c66318ce3f731da4616a2e192 +#PKG_MIRROR_HASH:=98daa1a15075c88afb3ed0de20dc83fe51d2ba3c66318ce3f731da4616a2e192 PKG_MAINTAINER:=Nicholas Smith PKG_LICENSE:=GPL-2.0-or-later diff --git a/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch b/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch deleted file mode 100644 index d1f67537b..000000000 --- a/modemmanager/patches/100-ublox-remove-ID_MM_PROCESS-tags.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/src/plugins/ublox/77-mm-ublox-port-types.rules -+++ b/src/plugins/ublox/77-mm-ublox-port-types.rules -@@ -88,8 +88,8 @@ SUBSYSTEMS=="usb", ATTRS{bInterfaceNumbe - # ttyUSB2 (if #2): secondary - # ttyUSB3 (if #3): unused (ignore) - ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1" --ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" --ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1", ENV{ID_MM_DEVICE_PROCESS}="1" -+ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" -+ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" - ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="908b", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1" - - LABEL="mm_ublox_port_types_end" From a1c2c699a9e4edf8cbfa8a0b79d1d6440636b68a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Jan 2024 17:26:22 +0100 Subject: [PATCH 1259/2059] Fix Wizard display for OpenVPN --- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 24ead847c..4841cc622 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -451,7 +451,7 @@ <% if nixio.fs.access("/usr/sbin/dsvpn") then %><% end %> <% if nixio.fs.access("/usr/sbin/mlvpn") then %><% end %> <% if nixio.fs.access("/usr/sbin/ubond") then %><% end %> - <% if nixio.fs.access("/etc/init.d/openvpn") then %><% end %> + <% if nixio.fs.access("/etc/init.d/openvpn") then %><% end %> <% From 857f9f0ae17f76114ede8e5dbcef7a033aa318af Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 4 Jan 2024 17:32:13 +0100 Subject: [PATCH 1260/2059] Fix unbound restart loop when interfaces down --- .../share/omr/post-tracking.d/010-services | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index 7f2368b74..2a6a9ddc5 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -33,7 +33,7 @@ if [ "$(pgrep -f dnsmasq)" = "" ] && [ -f /etc/init.d/dnsmasq ]; then /etc/init.d/dnsmasq restart 2>&1 >/dev/null sleep 5 fi -if [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then +if [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ] && [ "$OMR_TRACKER_STATUS" != "ERROR" ]; then if [ "$(pgrep -f unbound)" = "" ]; then _log "Can't find unbound, restart it..." /etc/init.d/unbound restart 2>&1 >/dev/null @@ -41,7 +41,7 @@ if [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = elif [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ] && [ "$(uci -q get unbound.ub_main.listen_port)" = "5353" ] && [ -n "$(dig +timeout=4 +tries=1 openmptcprouter.com -p 5353 | grep 'ANSWER: 0')" ]; then _log "Can't resolve via unbound, restart it..." /etc/init.d/unbound restart 2>&1 >/dev/null - sleep 5 + sleep 20 fi fi @@ -137,8 +137,24 @@ restart_omrtracker() { sleep 10 } +set_lan_ips() { + config_get ip4table "$1" ip4table + config_get device "$1" device + config_get proto "$1" proto + if [ "$ip4table" = "lan" ] && [ -n "$device" ] && ([ "$proto" = "dhcp" ] || [ "$proto" = "static" ]); then + [ -z "$(uci -q get shadowsocks-libev.ss_rules.ifnames | grep $device)" ] && { + uci -q add_list shadowsocks-libev.ss_rules.ifnames="$device" + uci -q add_list shadowsocks-rust.ss_rules.ifnames="$device" + } + elif [ -n "$device" ] && [ -n "$(uci -q get shadowsocks-libev.ss_rules.ifnames | grep $device)" ]; then + uci -q del_list shadowsocks-libev.ss_rules.ifnames="$device" + uci -q del_list shadowsocks-rust.ss_rules.ifnames="$device" + fi +} + config_load network config_foreach restart_omrtracker interface +#config_foreach set_lan_ips interface mutlipath_fix() { config_get multipath "$1" multipath @@ -185,7 +201,7 @@ if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then echo 1 > /sys/bus/pci/rescan fi -if [ -f /etc/init.d/omr-bypass ] && (([ -f /usr/sbin/iptables-legacy-save ] && [ "$(iptables-legacy-save 2>/dev/null | grep omr-bypass)" = "" ]) || [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ]) && [ "$(pgrep -f omr-bypass)" = "" ]; then +if [ -f /etc/init.d/omr-bypass ] && [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ] && [ "$(pgrep -f omr-bypass)" = "" ]; then _log "Can't find omr-bypass rules, restart omr-bypass..." /etc/init.d/omr-bypass 2>&1 >/dev/null sleep 5 @@ -215,7 +231,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFAC fi fi -#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || (([ -f /usr/sbin/iptables-legacy-save ] && [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]) || [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ])); then +#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then check_server_fw() { [ "$(uci -q get openmptcprouter.$1.set_firewall)" = "1" ] && { From 2a0beebe74f49230efebae2642e3cba5dd9cb1a3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 5 Jan 2024 16:33:28 +0100 Subject: [PATCH 1261/2059] Remove auto disable of ModemManager if not used because modems are not visibles in interfaces directly and it's confusing, another solution must be found --- mptcp/files/usr/share/omr/post-tracking.d/010-services | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/mptcp/files/usr/share/omr/post-tracking.d/010-services index 2a6a9ddc5..050ad3bc4 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/mptcp/files/usr/share/omr/post-tracking.d/010-services @@ -101,10 +101,10 @@ if [ -z "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$( _log "Can't find ModemManager, restart it..." /etc/init.d/modemmanager restart 2>&1 >/dev/null sleep 5 -elif [ -n "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -z "$(uci -q show network | grep modemmanager)" ]; then - _log "ModemManager not used, stop it..." - /etc/init.d/modemmanager stop 2>&1 >/dev/null - sleep 5 +#elif [ -n "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -z "$(uci -q show network | grep modemmanager)" ]; then +# _log "ModemManager not used, stop it..." +# /etc/init.d/modemmanager stop 2>&1 >/dev/null +# sleep 5 fi if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ "$(pgrep -f omr-tracker-v2ray)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then From 80f2c3151a5cd64e068bb3bc86b72186b74ab02b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 8 Jan 2024 15:38:20 +0100 Subject: [PATCH 1262/2059] Move some script to cron instead of omr-tracker --- omr-schedule/Makefile | 38 +++++++++++++++++++ omr-schedule/files/bin/omr-schedule | 10 +++++ .../files/etc/uci-defaults/3000-omr-schedule | 4 ++ .../usr/share/omr/schedule.d}/010-services | 38 ++++++------------- .../files/usr/share/omr/schedule.d/030-bypass | 19 ++++++++++ .../files/usr/share/omr/schedule.d}/050-rutx | 0 6 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 omr-schedule/Makefile create mode 100755 omr-schedule/files/bin/omr-schedule create mode 100755 omr-schedule/files/etc/uci-defaults/3000-omr-schedule rename {mptcp/files/usr/share/omr/post-tracking.d => omr-schedule/files/usr/share/omr/schedule.d}/010-services (87%) create mode 100755 omr-schedule/files/usr/share/omr/schedule.d/030-bypass rename {mptcp/files/usr/share/omr/post-tracking.d => omr-schedule/files/usr/share/omr/schedule.d}/050-rutx (100%) diff --git a/omr-schedule/Makefile b/omr-schedule/Makefile new file mode 100644 index 000000000..80dbded52 --- /dev/null +++ b/omr-schedule/Makefile @@ -0,0 +1,38 @@ +# +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=omr-schedule +PKG_VERSION:=0.1 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) +SECTION:=OMR +CATEGORY:=OMR-Schedule +DEPENDS:=$(foreach p,$(MY_DEPENDS),+$(p)) +TITLE:=OpenMPTCProuter schedule scripts +endef + +define Package/$(PKG_NAME)/description +OpenMPTCProuter schedule scripts +endef + +define Package/$(PKG_NAME)/conffiles +/etc/contabs/root +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/omr-schedule/files/bin/omr-schedule b/omr-schedule/files/bin/omr-schedule new file mode 100755 index 000000000..5d319b6f7 --- /dev/null +++ b/omr-schedule/files/bin/omr-schedule @@ -0,0 +1,10 @@ +#!/bin/sh + +for schedule_bin in /usr/share/omr/schedule.d/*; do + [ -x "$schedule_bin" ] && ( + _log() { + logger -t "omr-schedule-${schedule_bin##*/}" "$*" + } + . "$schedule_bin" 2>&1 + ) +done diff --git a/omr-schedule/files/etc/uci-defaults/3000-omr-schedule b/omr-schedule/files/etc/uci-defaults/3000-omr-schedule new file mode 100755 index 000000000..bb5556c7a --- /dev/null +++ b/omr-schedule/files/etc/uci-defaults/3000-omr-schedule @@ -0,0 +1,4 @@ +#!/bin/sh +if [ ! -f /etc/crontabs/root ] || [ "$(cat /etc/crontabs/root | grep omr-schedule)" = "" ]; then + echo "*/5 * * * * /bin/omr-schedule" >> /etc/crontabs/root +fi diff --git a/mptcp/files/usr/share/omr/post-tracking.d/010-services b/omr-schedule/files/usr/share/omr/schedule.d/010-services similarity index 87% rename from mptcp/files/usr/share/omr/post-tracking.d/010-services rename to omr-schedule/files/usr/share/omr/schedule.d/010-services index 050ad3bc4..49282f329 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/010-services +++ b/omr-schedule/files/usr/share/omr/schedule.d/010-services @@ -33,15 +33,15 @@ if [ "$(pgrep -f dnsmasq)" = "" ] && [ -f /etc/init.d/dnsmasq ]; then /etc/init.d/dnsmasq restart 2>&1 >/dev/null sleep 5 fi -if [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ] && [ "$OMR_TRACKER_STATUS" != "ERROR" ]; then +if [ -f /etc/init.d/unbound ] && [ "$(uci -q get unbound.@unbound[0].enabled)" = "1" ]; then if [ "$(pgrep -f unbound)" = "" ]; then _log "Can't find unbound, restart it..." /etc/init.d/unbound restart 2>&1 >/dev/null sleep 5 - elif [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ] && [ "$(uci -q get unbound.ub_main.listen_port)" = "5353" ] && [ -n "$(dig +timeout=4 +tries=1 openmptcprouter.com -p 5353 | grep 'ANSWER: 0')" ]; then - _log "Can't resolve via unbound, restart it..." - /etc/init.d/unbound restart 2>&1 >/dev/null - sleep 20 +# elif [ "$(uci -q get openmptcprouter.settings.external_check)" != "0" ] && [ "$(uci -q get unbound.ub_main.listen_port)" = "5353" ] && [ -n "$(dig +timeout=4 +tries=1 openmptcprouter.com -p 5353 | grep 'ANSWER: 0')" ]; then +# _log "Can't resolve via unbound, restart it..." +# /etc/init.d/unbound restart 2>&1 >/dev/null +# sleep 5 fi fi @@ -101,10 +101,10 @@ if [ -z "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$( _log "Can't find ModemManager, restart it..." /etc/init.d/modemmanager restart 2>&1 >/dev/null sleep 5 -#elif [ -n "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -z "$(uci -q show network | grep modemmanager)" ]; then -# _log "ModemManager not used, stop it..." -# /etc/init.d/modemmanager stop 2>&1 >/dev/null -# sleep 5 +elif [ -n "$(pgrep ModemManager)" ] && [ -f /etc/init.d/modemmanager ] && [ -z "$(uci -q show network | grep modemmanager)" ]; then + _log "ModemManager not used, stop it..." + /etc/init.d/modemmanager stop 2>&1 >/dev/null + sleep 5 fi if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ "$(pgrep -f omr-tracker-v2ray)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then @@ -137,24 +137,8 @@ restart_omrtracker() { sleep 10 } -set_lan_ips() { - config_get ip4table "$1" ip4table - config_get device "$1" device - config_get proto "$1" proto - if [ "$ip4table" = "lan" ] && [ -n "$device" ] && ([ "$proto" = "dhcp" ] || [ "$proto" = "static" ]); then - [ -z "$(uci -q get shadowsocks-libev.ss_rules.ifnames | grep $device)" ] && { - uci -q add_list shadowsocks-libev.ss_rules.ifnames="$device" - uci -q add_list shadowsocks-rust.ss_rules.ifnames="$device" - } - elif [ -n "$device" ] && [ -n "$(uci -q get shadowsocks-libev.ss_rules.ifnames | grep $device)" ]; then - uci -q del_list shadowsocks-libev.ss_rules.ifnames="$device" - uci -q del_list shadowsocks-rust.ss_rules.ifnames="$device" - fi -} - config_load network config_foreach restart_omrtracker interface -#config_foreach set_lan_ips interface mutlipath_fix() { config_get multipath "$1" multipath @@ -201,7 +185,7 @@ if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then echo 1 > /sys/bus/pci/rescan fi -if [ -f /etc/init.d/omr-bypass ] && [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ] && [ "$(pgrep -f omr-bypass)" = "" ]; then +if [ -f /etc/init.d/omr-bypass ] && (([ -e /usr/sbin/iptables-nft-save ] && [ "$(iptables-nft-save 2>/dev/null | grep omr-bypass)" = "" ]) || [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ]) && [ "$(pgrep -f omr-bypass)" = "" ]; then _log "Can't find omr-bypass rules, restart omr-bypass..." /etc/init.d/omr-bypass 2>&1 >/dev/null sleep 5 @@ -231,7 +215,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFAC fi fi -#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +#if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || (([ -e /usr/sbin/iptables-nft-save ] && [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]) || [ -z "$(iptables-save 2>/dev/null | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ])); then if [ "$(pgrep -f set_vps_firewall)" = "" ] && [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(uci -q show openmptcprouter | grep password)" != "" ] && [ "$(pgrep -f openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && [ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ]; then check_server_fw() { [ "$(uci -q get openmptcprouter.$1.set_firewall)" = "1" ] && { diff --git a/omr-schedule/files/usr/share/omr/schedule.d/030-bypass b/omr-schedule/files/usr/share/omr/schedule.d/030-bypass new file mode 100755 index 000000000..19ff52437 --- /dev/null +++ b/omr-schedule/files/usr/share/omr/schedule.d/030-bypass @@ -0,0 +1,19 @@ +#!/bin/sh + +bypassipvs4s=$(ipset -o save list omr_dst_bypass_srv_vpn1_4) +[ -z "$bypassipvs4s" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') +bypassipvs6s=$(ipset -o save list omr_dst_bypass_srv_vpn1_6) +[ -z "$bypassipvs6s" ] && bypassipv6s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') +#" +vpnipv4md5=$(echo "${bypassipv4s}" | md5sum | awk '{print $1}' | tr -d "\n") +vpnipv6md5=$(echo "${bypassipv6s}" | md5sum | awk '{print $1}' | tr -d "\n") +if [ "$vpnipv4md5" != "$(uci -q get omr-bypass.global.vpn_ipv4_md5)" ] || [ "$vpnipv6md5" != "$(uci -q get omr-bypass.global.vpn_ipv6_md5)" ]; then + _log "Set bypass ip on servers" + /etc/init.d/openmptcprouter-vps set_bypass_ips + uci -q batch <<-EOF >/dev/null + set omr-bypass.global=global + set omr-bypass.global.vpn_ipv4_md5=${vpnipv4md5} + set omr-bypass.global.vpn_ipv6_md5=${vpnipv6md5} + commit omr-bypass + EOF +fi diff --git a/mptcp/files/usr/share/omr/post-tracking.d/050-rutx b/omr-schedule/files/usr/share/omr/schedule.d/050-rutx similarity index 100% rename from mptcp/files/usr/share/omr/post-tracking.d/050-rutx rename to omr-schedule/files/usr/share/omr/schedule.d/050-rutx From 703fe46dd124e237f993cbc6416b49332a630f3c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:33:00 +0100 Subject: [PATCH 1263/2059] Add nftables support to omr-bypass --- omr-bypass/Makefile | 22 +- omr-bypass/files/etc/init.d/omr-bypass | 751 +++++++---------- omr-bypass/files/etc/init.d/omr-bypass-nft | 926 +++++++++++++++++++++ 3 files changed, 1255 insertions(+), 444 deletions(-) create mode 100755 omr-bypass/files/etc/init.d/omr-bypass-nft diff --git a/omr-bypass/Makefile b/omr-bypass/Makefile index b75dcf46e..59de108fb 100644 --- a/omr-bypass/Makefile +++ b/omr-bypass/Makefile @@ -20,15 +20,33 @@ DEPENDS:=+curl +dnsmasq-full +sqlite3-cli +iptables +iptables-mod-extra +ipset TITLE:=OMR-ByPass endef +define Package/$(PKG_NAME)-nft +SECTION:=net +CATEGORY:=Network +DEPENDS:=+curl +dnsmasq-full +sqlite3-cli +firewall4 +TITLE:=OMR-ByPass NFT +endef + define Package/$(PKG_NAME)/description OMR-ByPass endef +define Package/$(PKG_NAME)/description +OMR-ByPass nft support +endef + define Build/Compile endef define Package/$(PKG_NAME)/install - $(CP) ./files/* $(1)/ + $(CP) ./files/* $(1)/ + rm -f $(1)/etc/init.d/omr-bypass-nft endef -$(eval $(call BuildPackage,$(PKG_NAME))) \ No newline at end of file +define Package/$(PKG_NAME)-nft/install + $(CP) ./files/* $(1)/ + mv $(1)/etc/init.d/omr-bypass-nft $(1)/etc/init.d/omr-bypass +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) +$(eval $(call BuildPackage,$(PKG_NAME)-nft)) \ No newline at end of file diff --git a/omr-bypass/files/etc/init.d/omr-bypass b/omr-bypass/files/etc/init.d/omr-bypass index 1d292c55a..8d2ef20c6 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass +++ b/omr-bypass/files/etc/init.d/omr-bypass @@ -1,5 +1,5 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter START=98 STOP=10 @@ -8,13 +8,14 @@ EXTRA_COMMANDS="reload_rules bypass_asn" . /usr/lib/unbound/iptools.sh -if [ -f /usr/sbin/iptables-legacy ]; then - IPTABLES="/usr/sbin/iptables-legacy" - IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" - IPTABLESSAVE="/usr/sbin/iptables-legacy-save" - IP6TABLES="/usr/sbin/ip6tables-legacy" - IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" - IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +# Still used by ndpi +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" + IPTABLESRESTORE="/usr/sbin/iptables-nft-restore" + IPTABLESSAVE="/usr/sbin/iptables-nft-save" + IP6TABLES="/usr/sbin/ip6tables-nft" + IP6TABLESRESTORE="/usr/sbin/ip6tables-nft-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-nft-save" else IPTABLES="/usr/sbin/iptables" IPTABLESRESTORE="/usr/sbin/iptables-restore" @@ -58,9 +59,13 @@ _bypass_ip() { valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then - ipset -q add omr_dst_bypass_$type $ip + uci -q add_list firewall.omr_dst_bypass_${type}_4.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_4.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_4.enabled='1' elif [ "$valid_ip6" = "ok" ]; then - ipset -q add omr6_dst_bypass_$type $ip + uci -q add_list firewall.omr_dst_bypass_${type}_6.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_6.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_6.enabled='1' fi } @@ -76,6 +81,7 @@ _bypass_domains() { [ -z "$intf" ] && intf="all" config_get vpn $1 vpn [ "$vpn" = "1" ] && intf="srv_vpn1" + #echo "bypass $domain $enabled $family $intf $vpn" [ "$enabled" = "0" ] && return [ -z "$domain" ] && return [ -z "$family" ] && family="ipv4ipv6" @@ -107,6 +113,7 @@ _bypass_domains() { _bypass_domain $validdomain $intf $family $noipv6 done else + #echo "_bypass_domain $domain $intf $family $noipv6" _bypass_domain $domain $intf $family $noipv6 fi } @@ -117,7 +124,6 @@ _bypass_domain() { local family=$3 local noipv6=$4 intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return [ -z "$intf" ] && intf="all" if [ -n "$domain" ]; then domain=$(echo $domain | sed 's:^\.::') @@ -134,35 +140,13 @@ _bypass_domain() { done fi fi - if [ "$(uci -q get dhcp.@dnsmasq[0].ipset | grep /$domain/)" = "" ]; then - if [ "$family" = "ipv4ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf,omr6_dst_bypass_$intf" - elif [ "$family" = "ipv4" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf" - elif [ "$family" = "ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr6_dst_bypass_$intf" - fi + if [ "$(uci -q get dhcp.omr_dst_bypass_$intf | grep /$domain/)" = "" ]; then + uci -q add_list dhcp.omr_dst_bypass_$intf.domain=$domain add_domains="true" - else - dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g') - for dnsipset in $dnsmasqipset; do - if [ "$(echo $dnsipset | cut -d/ -f2)" = "$domain" ]; then - uci -q del_list dhcp.@dnsmasq[0].ipset=$dnsipset - if [ "$family" = "ipv4ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf,omr6_dst_bypass_$intf" - elif [ "$family" = "ipv4" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf" - elif [ "$family" = "ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr6_dst_bypass_$intf" - fi - add_domains="true" - fi - done fi if [ "$(uci -q get dhcp.@dnsmasq[0].noipv6 | grep /$domain/)" = "" ] && [ "$noipv6" = "1" ]; then uci -q add_list dhcp.@dnsmasq[0].noipv6="$domain" fi - #logger -t "omr-bypass" "Get IPs of $domain... Done" fi } @@ -176,38 +160,13 @@ _bypass_mac() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$mac" ] && return - if [ "$intf" = "all" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539 - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi - fi + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_$intf_mac.src_mac="$mac" + EOF } _bypass_lan_ip() { @@ -226,44 +185,16 @@ _bypass_lan_ip() { [ -z "$ip" ] && return valid_ip4=$(valid_subnet4 $ip) valid_ip6=$(valid_subnet6 $ip) - if [ "$intf" = "all" ]; then - if [ "$valid_ip4" = "ok" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -s $ip -j MARK --set-mark 0x539 - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local -s $ip -j MARK --set-mark 0x539 - COMMIT - EOF - elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - if [ "$valid_ip4" = "ok" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -s $ip -j MARK --set-mark 0x539$intfid - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local -s $ip -j MARK --set-mark 0x539$intfid - COMMIT - EOF - elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi + if [ "$valid_ip4" = "ok" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_4.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_4.enabled='1' + EOF + elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_6.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_6.enabled='1' + EOF fi } @@ -278,49 +209,24 @@ _bypass_dest_port() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$dport" ] && return dport="$(echo $dport | sed 's/-/:/')" [ -z "$proto" ] && return - if [ "$intf" = "all" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 - COMMIT + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 - COMMIT + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi fi } @@ -335,49 +241,24 @@ _bypass_src_port() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$sport" ] && return sport="$(echo $sport | sed 's/-/:/')" [ -z "$proto" ] && return - if [ "$intf" = "all" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539 - COMMIT + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539 - COMMIT + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi fi } @@ -398,7 +279,7 @@ _bypass_proto() { [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" @@ -408,8 +289,8 @@ _bypass_proto() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 - -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539 + -A omr-bypass-dpi -m mark --mark 0x4539 -j RETURN COMMIT EOF fi @@ -425,8 +306,8 @@ _bypass_proto() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid - -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539$intfid + -A omr-bypass-dpi -m mark --mark 0x4539$intfid -j RETURN COMMIT EOF fi @@ -497,74 +378,84 @@ _bypass_proto_without_ndpi() { [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" + [ "$intf" = "all" ] && intfid="" [ -z "$proto" ] && return if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ] || [ "$vpn" = "1" ]; then ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") if [ -n "$ALLIPS" ]; then if [ "$vpn" != "1" ]; then - ipset -q flush bypass_$proto > /dev/null 2>&1 - ipset -q flush bypass6_$proto > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create bypass_$proto hash:net hashsize 64 - create bypass6_$proto hash:net family inet6 hashsize 64 + uci -q batch <<-EOF >/dev/null + set firewall.bypass_$proto=ipset + set firewall.bypass_$proto.name="bypass_$proto" + set firewall.bypass_$proto.match='dest_ip' + set firewall.bypass_$proto_rule=rule + set firewall.bypass_$proto_rule.name="bypass_$proto" + set firewall.bypass_$proto_rule.src='lan' + set firewall.bypass_$proto_rule.dest='*' + set firewall.bypass_$proto_rule.target='MARK' + set firewall.bypass_$proto_rule.set_xmark="4539${intfid}" + commit firewall EOF + uci -q batch <<-EOF >/dev/null + set firewall.bypass6_$proto=ipset + set firewall.bypass6_$proto.name="bypas6s_$proto" + set firewall.bypass6_$proto.match='dest_ip' + set firewall.bypass6_$proto_rule=rule + set firewall.bypass6_$proto_rule.name="bypass6_$proto" + set firewall.bypass6_$proto_rule.src='lan' + set firewall.bypass6_$proto_rule.dest='*' + set firewall.bypass6_$proto_rule.target='MARK' + set firewall.bypass6_$proto_rule.set_xmark="6539${intfid}" + commit firewall + EOF + #if [ "$intfid" != "" ]; then + # uci -q batch <<-EOF >/dev/null + # delete network.${1}_fw_rule=rule + # set network.${1}_fw_rule=rule + # set network.${1}_fw_rule.priority=1 + # set network.${1}_fw_rule.mark=0x539${intfid} + # set network.${1}_fw_rule.lookup=${intfid} + # delete network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6.priority=1 + # set network.${1}_fw_rule6.mark=0x6539${intfid} + # set network.${1}_fw_rule6.lookup=${intfid} + # commit network + # EOF + #fi + + #ipset -q flush bypass_$proto > /dev/null 2>&1 + #ipset -q flush bypass6_$proto > /dev/null 2>&1 + #ipset -q --exist restore <<-EOF + #create bypass_$proto hash:net hashsize 64 + #create bypass6_$proto hash:net family inet6 hashsize 64 + #EOF fi for ip in $ALLIPS; do valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then if [ "$vpn" != "1" ]; then - ipset -q add bypass_$proto $ip + #ipset -q add bypass_$proto $ip + uci -q add_list firewall.bypass_$proto.entry=$ip else - ipset -q add omr_dst_bypass_$intf $ip + #ipset -q add omr_dst_bypass_$intf $ip + uci -q add_list firewall.omr_dst_bypass_$intf_4.entry=$ip fi elif [ "$valid_ip6" = "ok" ]; then if [ "$vpn" != "1" ]; then - ipset -q add bypass6_$proto $ip + #ipset -q add bypass6_$proto $ip + uci -q add_list firewall.bypass6_$proto.entry=$ip else - ipset -q add omr6_dst_bypass_$intf $ip + #ipset -q add omr6_dst_bypass_$intf $ip + uci -q add_list firewall.omr6_dst_bypass_$intf_4.entry=$ip fi fi done - if [ "$intf" = "all" ]; then - if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539 - -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539 - -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN - COMMIT - EOF - fi - elif [ "$vpn" != "1" ]; then - if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539$intfid - -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539$intfid - -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN - COMMIT - EOF - fi - fi fi fi # Use dnsmasq ipset to bypass domains of the proto @@ -609,52 +500,15 @@ _bypass_proto_without_ndpi() { } _intf_rule_ss_rules() { - rule_name=$1 - [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I ssr_${rule_name}_dst 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF if [ "$disableipv6" = "0" ]; then - if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep omr6_dst_bypass_$intf)" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -I omr-bypass6 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - COMMIT - EOF - fi - if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLESSAVE 2>/dev/null | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - -I ssr6_${rule_name}_dst 2 -m mark --mark 0x6539$count -j RETURN - -I ssr6_${rule_name}_local_out 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - -I ssr6_${rule_name}_local_out 2 -m mark --mark 0x6539$count -j RETURN - -I ssr6_${rule_name}_pre_src 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - -I ssr6_${rule_name}_pre_src 2 -m mark --mark 0x6539$count -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF fi } @@ -766,56 +620,133 @@ _intf_rule_xray_rules() { _intf_rule() { local intf - intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ "$1" = "all" ] && intf="all" + [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') [ -z "$intf" ] && config_get intf $1 device [ -n "$(echo $intf | grep '/')" ] && return #count=$((count+1)) - config_get count $1 metric + [ "$intf" != "all" ] && config_get count $1 metric + [ "$intf" = "all" ] && count="" local mode #config_get mode $1 multipath "off" #[ "$mode" = "off" ] && return - [ -z "$count" ] && return + [ "$intf" != "all" ] && [ -z "$count" ] && return [ -z "$intf" ] && return intf=$(echo $intf | sed -e 's/\./_/') + intf=$(echo $intf | sed -e 's/-/_/') [ "$(echo $1 | grep _dev)" != "" ] && return - [ -z "$RELOAD" ] || [ "$(ipset --list | grep omr_dst_bypass_$intf)" = "" ] && { - unset RELOAD - ipset -q flush omr_dst_bypass_$intf > /dev/null 2>&1 - ipset -q flush omr6_dst_bypass_$intf > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create omr_dst_bypass_$intf hash:net hashsize 64 - create omr6_dst_bypass_$intf hash:net family inet6 hashsize 64 + [ "$intf" = "lo" ] && return + [ -z "$intf" ] && return +# [ -z "$RELOAD" ] || [ "$(uci show firewall.omr_dst_bypass_$intf_4)" = "" ] && { + #unset RELOAD + #echo "$intf ip set dhcp" + uci batch <<-EOF + set dhcp.omr_dst_bypass_$intf=ipset + set dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4,omr_dst_bypass_${intf}_6" + commit dhcp EOF - if [ "$(uci -q get openmptcprouter.settings.uci_rules)" = "1" ]; then + #echo "firewall omr_dst_bypass ipset" + uci -q batch <<-EOF + set firewall.omr_dst_bypass_${intf}_4=ipset + set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' + EOF + #echo "firewall omr_dst_bypass rules" + if [ "$disableipv6" = "0" ]; then + protocol="4 6" + else + protocol="4" + fi + for ipv46 in $protocol; do + echo "ipv46: $ipv46 for $intf" + uci batch <<-EOF + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.name="omr_dst_bypass_${intf}_srcip" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.name='omr_dst_bypass_${intf}_mac' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.proto='tcp' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.proto='udp' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + commit firewall + EOF + done + if [ "$intf" = "all" ]; then uci -q batch <<-EOF >/dev/null - delete network.${1}_fw_rule=rule - set network.${1}_fw_rule=rule - set network.${1}_fw_rule.priority=1 - set network.${1}_fw_rule.mark=0x539${count} - set network.${1}_fw_rule.lookup=${count} - delete network.${1}_fw_rule6=rule6 - set network.${1}_fw_rule6=rule6 - set network.${1}_fw_rule6.priority=1 - set network.${1}_fw_rule6.mark=0x6539${count} - set network.${1}_fw_rule6.lookup=${count} + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539 + set network.${intf}_fw_rule.lookup=991337 + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539 + set network.${intf}_fw_rule6.lookup=6991337 commit network EOF else - ip rule add prio 1 fwmark 0x539$count lookup $count pref 1 > /dev/null 2>&1 - ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count pref 1 > /dev/null 2>&1 + uci -q batch <<-EOF >/dev/null + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539${count} + set network.${intf}_fw_rule.lookup=${count} + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539${count} + set network.${intf}_fw_rule6.lookup=${count} + commit network + EOF fi - } - if [ "$($IPTABLESSAVE 2>/dev/null | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I omr-bypass 2 -m mark --mark 0x539$count -j RETURN - -I omr-bypass-local 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I omr-bypass-local 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi + if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then config_load shadowsocks-libev config_foreach _intf_rule_ss_rules ss_rules @@ -856,7 +787,6 @@ _bypass_asn() { for ip in $asnips; do _bypass_ip $ip $interface done - } bypass_asn() { @@ -872,40 +802,15 @@ _bypass_omr_server() { _ss_rules_config() { - rule_name=$1 - [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLES --wait=40 -t nat -L -n | grep omr_dst_bypass_all)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I ssr_${rule_name}_dst 2 -m mark --mark 0x539 -j RETURN - -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539 -j RETURN - -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF if [ "$disableipv6" = "0" ]; then - if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLES --wait=40 -t nat -L -n | grep omr6_dst_bypass_all)" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - -I ssr6_${rule_name}_dst 1 -m mark --mark 0x6539 -j RETURN - -I ssr6_${rule_name}_local_out 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - -I ssr6_${rule_name}_local_out 2 -m mark --mark 0x6539 -j RETURN - -I ssr6_${rule_name}_pre_src 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - -I ssr6_${rule_name}_pre_src 2 -m mark --mark 0x6539 -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF fi } @@ -987,6 +892,18 @@ _xray_rules_config() { fi } +_delete_dhcp_ipset() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete dhcp.$1 + } +} + +_delete_firewall_rules() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete firewall.$1 + } +} + boot() { BOOT=1 start "$@" @@ -995,6 +912,16 @@ boot() { start_service() { #local count logger -t "omr-bypass" "Starting OMR-ByPass..." + + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + #uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + #uci -q commit firewall + + add_domains="false" [ -d /proc/net/xt_ndpi ] && { config_load omr-bypass @@ -1003,128 +930,58 @@ start_service() { disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" #noipv6="$(uci -q get omr-bypass.global.noipv6)" - [ -n "$RELOAD" ] && [ "$(ipset --list | grep omr_dst_bypass_all)" = "" ] && { - unset RELOAD - } - [ -z "$RELOAD" ] && { - ipset -q flush omr_dst_bypass_all > /dev/null 2>&1 - ipset -q flush omr6_dst_bypass_all > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create omr_dst_bypass_all hash:net hashsize 64 - create omr6_dst_bypass_all hash:net family inet6 hashsize 64 - EOF - ipset -q flush omr_dst_bypass_srv_vpn1 > /dev/null 2>&1 - ipset -q flush omr6_dst_bypass_srv_vpn1 > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create omr_dst_bypass_srv_vpn1 hash:net hashsize 64 - create omr6_dst_bypass_srv_vpn1 hash:net family inet6 hashsize 64 - EOF - } - $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass - - -A PREROUTING -j omr-bypass - COMMIT + cat > /etc/firewall.omr-bypass <<-EOF + #!/bin/sh + #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all accept + #nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all accept EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass-local - - -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-local - COMMIT + uci batch <<-EOF + set firewall.omr_bypass=include + set firewall.omr_bypass.enabled='1' + set firewall.omr_bypass.type='script' + set firewall.omr_bypass.path='/etc/firewall.omr-bypass' + set firewall.omr_bypass.fw4_compatible='1' + commit firewall EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass6 - - -A PREROUTING -j omr-bypass6 - COMMIT - EOF - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass6-local - - -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass6-local - COMMIT - EOF - fi - + echo "intf_rule" config_load network config_foreach _intf_rule interface + _intf_rule all local ndpi_rules="" + echo "bypass server" if [ "$(uci -q get openmptcprouter.settings.bypass_servers)" = "1" ]; then config_load openmptcprouter config_foreach _bypass_omr_server server fi config_load omr-bypass + echo "bypass ip" config_foreach _bypass_ip_set ips + echo "bypass mac" config_foreach _bypass_mac macs + echo "bypass lan ip" config_foreach _bypass_lan_ip lan_ip + echo "bypass dest port" config_foreach _bypass_dest_port dest_port + echo "bypass src port" config_foreach _bypass_src_port src_port + echo "bypass asn" config_foreach _bypass_asn asns - dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g' | grep -v dst_bypass) - uci -q delete dhcp.@dnsmasq[0].ipset - uci -q delete dhcp.@dnsmasq[0].noipv6 - if [ -n "$dnsmasqipset" ]; then - for dnsipset in $dnsmasqipset; do - ipsets="" - allipsets=$(echo $dnsipset | cut -d/ -f3 | sed 's/,/\n/g') - for ipset in $allipsets; do - [ "$(echo $ipset | grep -v dst_bypass)" != "" ] && { - [ "$ipsets" != "" ] && ipsets="$ipsets,$ipset" - [ "$ipsets" = "" ] && ipsets="$ipset" - } - done - if [ "$ipsets" != "" ]; then - resultipset="/$(echo $dnsipset | cut -d/ -f2)/$ipsets" - [ -n "$resultipset" ] && uci -q add_list dhcp.@dnsmasq[0].ipset=$resultipset - fi - done - fi + echo "bypass domains" config_foreach _bypass_domains domains uci -q commit dhcp - ip rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 - ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 +# ip rule add prio 1 fwmark 0x4539 lookup 991337 > /dev/null 2>&1 +# ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 - if [ "$($IPTABLES --wait=40 -t mangle -L -n | grep 'match-set omr_dst_bypass_all dst MARK set')" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass -m mark --mark 0x539 -j RETURN - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass-local -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ]; then - if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass6 -m mark --mark 0x539 -j RETURN - COMMIT - EOF - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-local -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass6-local -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi - fi - config_load shadowsocks-libev - config_foreach _ss_rules_config - config_load shadowsocks-rust - config_foreach _ss_rules_config + #config_load shadowsocks-libev + #config_foreach _ss_rules_config ss_rules + ([ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] || [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]) && _ss_rules_config + #config_load shadowsocks-rust + #config_foreach _ss_rules_config ss_rules _v2ray_rules_config _xray_rules_config + # NDPI Netfilter is not available for nftables $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass-dpi | $IPTABLESRESTORE -w --counters 2>/dev/null $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle @@ -1156,7 +1013,7 @@ start_service() { logger -t "omr-bypass" "Reload dnsmasq..." /etc/init.d/dnsmasq reload } - + fw4 restart # Create a protocol list for UI from a sqlite DB when NDPI is not available sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass @@ -1168,15 +1025,25 @@ start_service() { stop_service() { $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null - $IPTABLESSAVE --counters 2>/dev/null | grep -v omr_dst | $IPTABLESRESTORE -w --counters 2>/dev/null +# $IPTABLESSAVE --counters 2>/dev/null | grep -v omr_dst | $IPTABLESRESTORE -w --counters 2>/dev/null $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null - $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr6_dst | $IP6TABLESRESTORE -w --counters 2>/dev/null - for setname in $(ipset -n list | grep "omr_"); do - ipset -q destroy "$setname" 2>/dev/null || true - done - for setname in $(ipset list | awk '/Name: bypass_/ {print $2}'); do - ipset -q destroy "$setname" 2>/dev/null || true - done +# $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr6_dst | $IP6TABLESRESTORE -w --counters 2>/dev/null + #for setname in $(ipset -n list | grep "omr_"); do + # ipset -q destroy "$setname" 2>/dev/null || true + #done + #for setname in $(ipset list | awk '/Name: bypass_/ {print $2}'); do + # ipset -q destroy "$setname" 2>/dev/null || true + #done + # disable all rules ? + uci -q set firewall.omr-bypass.enabled='0' + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + uci -q commit firewall + exit 0 } service_triggers() { diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft new file mode 100755 index 000000000..3bb187e8c --- /dev/null +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -0,0 +1,926 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter + +START=98 +STOP=10 +USE_PROCD=1 +EXTRA_COMMANDS="reload_rules bypass_asn" + +. /usr/lib/unbound/iptools.sh + +# Still used by ndpi +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" + IPTABLESRESTORE="/usr/sbin/iptables-nft-restore" + IPTABLESSAVE="/usr/sbin/iptables-nft-save" + IP6TABLES="/usr/sbin/ip6tables-nft" + IP6TABLESRESTORE="/usr/sbin/ip6tables-nft-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-nft-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESSAVE="/usr/sbin/iptables-save" + IP6TABLES="/usr/sbin/ip6tables" + IP6TABLESRESTORE="/usr/sbin/ip6tables-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + +_add_proto() { + protoname=$1 + [ -z "$protoname" ] && return + if [ "$(dd if=/proc/net/xt_ndpi/proto bs=4096 2> /dev/null | grep $protoname)" = "" ]; then + echo "add_custom $protoname" >/proc/net/xt_ndpi/proto + fi + allurls="$(dd if=/proc/net/xt_ndpi/host_proto bs=4096 2> /dev/null)" + hosts="$( uci -q get omr-bypass.$protoname.url )" + for url in $hosts; do + if [ "$(echo "$allurls" | grep -i ^${protoname}: | grep $url)" = "" ]; then + echo "$protoname:$url" >/proc/net/xt_ndpi/host_proto + fi + done + ip="$( uci -q get omr-bypass.$protoname.ip )" + for ip in $ips; do + if [ "$(echo "$allurls" | grep -i ^${protoname}: | grep $ip)" = "" ]; then + echo "$protoname:$ip" >/proc/net/xt_ndpi/ip_proto + fi + done +} + +_add_proto_without_ndpi() { + protoname=$1 + [ -z "$protoname" ] && return + echo "$protoname" >> /usr/share/omr-bypass/omr-bypass-proto.lst +} + +_bypass_ip() { + local ip=$1 + local type=$2 + [ -z "$type" ] && type="all" + valid_ip4=$( valid_subnet4 $ip) + valid_ip6=$( valid_subnet6 $ip) + if [ "$valid_ip4" = "ok" ]; then + uci -q add_list firewall.omr_dst_bypass_${type}_4.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_4.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_4.enabled='1' + elif [ "$valid_ip6" = "ok" ]; then + uci -q add_list firewall.omr_dst_bypass_${type}_6.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_6.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_6.enabled='1' + fi +} + +_bypass_domains() { + local domain + local intf + local enabled + config_get domain $1 name + config_get intf $1 interface + config_get enabled $1 enabled + config_get noipv6 $1 noipv6 + config_get family $1 family + [ -z "$intf" ] && intf="all" + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + #echo "bypass $domain $enabled $family $intf $vpn" + [ "$enabled" = "0" ] && return + [ -z "$domain" ] && return + [ -z "$family" ] && family="ipv4ipv6" + [ -z "$noipv6" ] && noipv6="0" + if [ "$(echo $domain | grep '\.$')" != "" ] || [ "$(echo $domain | grep '\.\*$')" != "" ]; then + tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` + domain="$(echo '"$domain"' | sed 's:*::')" + domainlist="" + # construct list of domains to query + i=0 + for tld in $tlds; do + i=$((i+1)) + # trim off header + if [ "$i" -lt "12" ] || [ "$i" -gt "50" ]; then + continue + fi + # add to command + domainlist="${domainlist} ${domain}${tld}" + done + domainlist="$(echo $domainlist `# Get the list of valid domains, pass it to awk` \ + | awk '{print tolower($0)}' `# awk lowercases the whole string and passes it to ` \ + | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ + dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ + | awk '{print $1}' `# awk, which outputs queried domain to` \ + | sed -e 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com)` to \ + | grep $domain `# grep, only keep wanted domain` \ + | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate + for validdomain in $domainlist; do + _bypass_domain $validdomain $intf $family $noipv6 + done + else + #echo "_bypass_domain $domain $intf $family $noipv6" + _bypass_domain $domain $intf $family $noipv6 + fi +} + +_bypass_domain() { + local domain=$1 + local intf=$2 + local family=$3 + local noipv6=$4 + intf=$(echo $intf | sed -e 's/\./_/') + [ -z "$intf" ] && intf="all" + if [ -n "$domain" ]; then + domain=$(echo $domain | sed 's:^\.::') + #logger -t "omr-bypass" "Get IPs of $domain..." + if [ -z $RELOAD ]; then + resolve=$(dig a +timeout=1 +tries=1 +nocmd +noall +answer $domain | grep -v CNAME | awk '{print $5}') + for ip in $resolve; do + _bypass_ip $ip $intf + done + if [ "$disableipv6" = "0" ]; then + resolve=$(dig aaaa +timeout=1 +tries=1 +nocmd +noall +answer $domain | grep AAAA | awk '{print $5}') + for ip in $resolve; do + _bypass_ip $ip $intf + done + fi + fi + if [ "$(uci -q get dhcp.omr_dst_bypass_$intf | grep /$domain/)" = "" ]; then + uci -q add_list dhcp.omr_dst_bypass_$intf.domain=$domain + add_domains="true" + fi + if [ "$(uci -q get dhcp.@dnsmasq[0].noipv6 | grep /$domain/)" = "" ] && [ "$noipv6" = "1" ]; then + uci -q add_list dhcp.@dnsmasq[0].noipv6="$domain" + fi + #logger -t "omr-bypass" "Get IPs of $domain... Done" + fi +} + +_bypass_mac() { + local mac + local intf + local enabled + config_get mac $1 mac + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$mac" ] && return + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_$intf_mac.src_mac="$mac" + EOF +} + +_bypass_lan_ip() { + local ip + local intf + local enabled + config_get ip $1 ip + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$ip" ] && return + valid_ip4=$(valid_subnet4 $ip) + valid_ip6=$(valid_subnet6 $ip) + if [ "$valid_ip4" = "ok" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_4.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_4.enabled='1' + EOF + elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_6.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_6.enabled='1' + EOF + fi +} + +_bypass_dest_port() { + local intf + local enabled + local dport + local proto + config_get dport $1 dport + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$dport" ] && return + dport="$(echo $dport | sed 's/:/-/')" + [ -z "$proto" ] && return + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dest_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' + EOF + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dest_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' + EOF + fi +} + +_bypass_src_port() { + local intf + local enabled + local sport + local proto + config_get sport $1 sport + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$sport" ] && return + sport="$(echo $sport | sed 's/:/-/')" + [ -z "$proto" ] && return + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' + EOF + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' + EOF + fi +} + +_bypass_proto() { + local proto + local intf + local enabled + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + config_get ndpi $1 ndpi + config_get noipv6 $1 noipv6 + config_get family $1 family + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + + [ "$enabled" = "0" ] && return + [ -z "$noipv6" ] && noipv6="0" + [ -z "$family" ] && family="ipv4ipv6" + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$proto" ] && return + if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ] && [ "$ndpi" != "0" ] && [ "$vpn" != "1" ]; then + if [ "$intf" = "all" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539 + -A omr-bypass-dpi -m mark --mark 0x4539 -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN + COMMIT + EOF + fi + else + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539$intfid + -A omr-bypass-dpi -m mark --mark 0x4539$intfid -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN + COMMIT + EOF + fi + fi + fi + # Use dnsmasq ipset to bypass domains of the proto + local domains + domains="$(cat /proc/net/xt_ndpi/host_proto | grep -i $proto: | sed -e "s/$proto://i" -e 's/*//' -e 's/,/ /g')" + if [ -n "$domains" ]; then + tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` + for domain in $domains; do + if [ -n "$domain" ]; then + domain="$(echo $domain | sed 's/^\.//')" + if [ "$(echo $domain | grep '\.$')" != "" ]; then + domainlist="" + # construct list of domains to query + i=0 + for tld in $tlds; do + i=$((i+1)) + # trim off header + if [ "$i" -lt "12" ] || [ "$i" -gt "50" ]; then + continue + fi + # add to command + domainlist="${domainlist} ${domain}${tld}" + done + domainlist="$(echo $domainlist `# Get the list of valid domains, pass it to awk` \ + | awk '{print tolower($0)}' `# awk lowercases the whole string and passes it to ` \ + | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ + dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ + | awk '{print $1}' `# awk, which outputs queried domain to` \ + | sed -e 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com)` to \ + | grep $domain `# grep, only keep wanted domain` \ + | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate + for validdomain in $domainlist; do + _bypass_domain $validdomain $intf $family $noipv6 + done + else + _bypass_domain $domain $intf $family $noipv6 + fi + fi + done + fi +} + +_bypass_proto_without_ndpi() { + local proto + local intf + local enabled + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + config_get ndpi $1 ndpi "0" + config_get noipv6 $1 noipv6 + config_get family $1 family + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + + [ "$enabled" = "0" ] && return + [ -z "$noipv6" ] && noipv6="0" + [ -z "$family" ] && family="ipv4ipv6" + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ "$intf" = "all" ] && intfid="" + [ -z "$proto" ] && return + if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ] || [ "$vpn" = "1" ]; then + ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") + if [ -n "$ALLIPS" ]; then + if [ "$vpn" != "1" ]; then + uci -q batch <<-EOF >/dev/null + set firewall.bypass_$proto=ipset + set firewall.bypass_$proto.name="bypass_$proto" + set firewall.bypass_$proto.match='dest_ip' + set firewall.bypass_$proto_rule=rule + set firewall.bypass_$proto_rule.name="bypass_$proto" + set firewall.bypass_$proto_rule.src='lan' + set firewall.bypass_$proto_rule.dest='*' + set firewall.bypass_$proto_rule.target='MARK' + set firewall.bypass_$proto_rule.set_xmark="4539${intfid}" + commit firewall + EOF + uci -q batch <<-EOF >/dev/null + set firewall.bypass6_$proto=ipset + set firewall.bypass6_$proto.name="bypas6s_$proto" + set firewall.bypass6_$proto.match='dest_ip' + set firewall.bypass6_$proto_rule=rule + set firewall.bypass6_$proto_rule.name="bypass6_$proto" + set firewall.bypass6_$proto_rule.src='lan' + set firewall.bypass6_$proto_rule.dest='*' + set firewall.bypass6_$proto_rule.target='MARK' + set firewall.bypass6_$proto_rule.set_xmark="6539${intfid}" + commit firewall + EOF + #if [ "$intfid" != "" ]; then + # uci -q batch <<-EOF >/dev/null + # delete network.${1}_fw_rule=rule + # set network.${1}_fw_rule=rule + # set network.${1}_fw_rule.priority=1 + # set network.${1}_fw_rule.mark=0x539${intfid} + # set network.${1}_fw_rule.lookup=${intfid} + # delete network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6.priority=1 + # set network.${1}_fw_rule6.mark=0x6539${intfid} + # set network.${1}_fw_rule6.lookup=${intfid} + # commit network + # EOF + #fi + + #ipset -q flush bypass_$proto > /dev/null 2>&1 + #ipset -q flush bypass6_$proto > /dev/null 2>&1 + #ipset -q --exist restore <<-EOF + #create bypass_$proto hash:net hashsize 64 + #create bypass6_$proto hash:net family inet6 hashsize 64 + #EOF + fi + for ip in $ALLIPS; do + valid_ip4=$( valid_subnet4 $ip) + valid_ip6=$( valid_subnet6 $ip) + if [ "$valid_ip4" = "ok" ]; then + if [ "$vpn" != "1" ]; then + #ipset -q add bypass_$proto $ip + uci -q add_list firewall.bypass_$proto.entry=$ip + else + #ipset -q add omr_dst_bypass_$intf $ip + uci -q add_list firewall.omr_dst_bypass_$intf_4.entry=$ip + fi + elif [ "$valid_ip6" = "ok" ]; then + if [ "$vpn" != "1" ]; then + #ipset -q add bypass6_$proto $ip + uci -q add_list firewall.bypass6_$proto.entry=$ip + else + #ipset -q add omr6_dst_bypass_$intf $ip + uci -q add_list firewall.omr6_dst_bypass_$intf_4.entry=$ip + fi + fi + done + fi + fi + # Use dnsmasq ipset to bypass domains of the proto + local domains + #domains="$(cat /proc/net/xt_ndpi/host_proto | grep -i $proto: | sed -e "s/$proto://i" -e 's/*//' -e 's/,/ /g')" + domains=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select host from hostproto where proto='"$proto"';" ".exit") + if [ -n "$domains" ]; then + tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` + for domain in $domains; do + if [ -n "$domain" ]; then + domain="$(echo $domain | sed 's/^\.//')" + if [ "$(echo $domain | grep '\.$')" != "" ]; then + domainlist="" + # construct list of domains to query + i=0 + for tld in $tlds; do + i=$((i+1)) + # trim off header + if [ "$i" -lt "2" ] || [ "${#tld}" -gt "3" ]; then + continue + fi + # add to command + domainlist="${domainlist} ${domain}${tld}" + done + domainlist="$(echo $domainlist `# Get the list of valid domains, pass it to awk` \ + | awk '{print tolower($0)}' `# awk lowercases the whole string and passes it to ` \ + | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ + dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ + | awk '{print $1}' `# awk, which outputs queried domain to` \ + | sed 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com) to` \ + | grep $domain `# grep, only keep wanted domain` \ + | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate + for validdomain in $domainlist; do + _bypass_domain $validdomain $intf $family $noipv6 + done + else + _bypass_domain $domain $intf $family $noipv6 + fi + fi + done + fi +} + +_intf_rule_ss_rules() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF + fi +} + +_intf_rule_v2ray_rules() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF + fi +} + +_intf_rule_xray_rules() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF + fi +} + +_intf_rule() { + local intf + [ "$1" = "all" ] && intf="all" + [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') + [ -z "$intf" ] && config_get intf $1 device + [ -n "$(echo $intf | grep '/')" ] && return + #count=$((count+1)) + [ "$intf" != "all" ] && config_get count $1 metric + [ "$intf" = "all" ] && count="" + local mode + #config_get mode $1 multipath "off" + #[ "$mode" = "off" ] && return + [ "$intf" != "all" ] && [ -z "$count" ] && return + [ -z "$intf" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + intf=$(echo $intf | sed -e 's/-/_/') + [ "$(echo $1 | grep _dev)" != "" ] && return + [ "$intf" = "lo" ] && return + [ -z "$intf" ] && return +# [ -z "$RELOAD" ] || [ "$(uci show firewall.omr_dst_bypass_$intf_4)" = "" ] && { + #unset RELOAD + #echo "$intf ip set dhcp" + uci batch <<-EOF + set dhcp.omr_dst_bypass_$intf=ipset + add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4" + add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_6" + commit dhcp + EOF + #echo "firewall omr_dst_bypass ipset" + uci -q batch <<-EOF + set firewall.omr_dst_bypass_${intf}_4=ipset + set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' + EOF + #echo "firewall omr_dst_bypass rules" + if [ "$disableipv6" = "0" ]; then + protocol="4 6" + else + protocol="4" + fi + for ipv46 in $protocol; do + echo "ipv46: $ipv46 for $intf" + uci batch <<-EOF + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.name="omr_dst_bypass_${intf}_srcip" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.name='omr_dst_bypass_${intf}_mac' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.proto='tcp' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.proto='udp' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + commit firewall + EOF + done + if [ "$intf" = "all" ]; then + uci -q batch <<-EOF >/dev/null + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539 + set network.${intf}_fw_rule.lookup=991337 + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539 + set network.${intf}_fw_rule6.lookup=6991337 + commit network + EOF + else + uci -q batch <<-EOF >/dev/null + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539${count} + set network.${intf}_fw_rule.lookup=${count} + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539${count} + set network.${intf}_fw_rule6.lookup=${count} + commit network + EOF + fi + + if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then + config_load shadowsocks-libev + config_foreach _intf_rule_ss_rules ss_rules + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks-rust" ]; then + config_load shadowsocks-rust + config_foreach _intf_rule_ss_rules ss_rules + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ]; then + _intf_rule_v2ray_rules + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "xray" ]; then + _intf_rule_xray_rules + fi + + uci -q set omr-bypass.$intf=interface + uci -q set omr-bypass.$intf.id=$count +} + +_bypass_ip_set() { + local ip + local interface + local enabled + config_get ip $1 ip + config_get interface $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + _bypass_ip $ip $interface +} + +_bypass_asn() { + local asn + local interface + local enabled + config_get asn $1 asn + config_get interface $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + local asnips + asnips=`curl --max-time 4 -s -k https://stat.ripe.net/data/announced-prefixes/data.json?resource=${asn} | jsonfilter -q -e '@.data.prefixes.*.prefix'` + for ip in $asnips; do + _bypass_ip $ip $interface + done +} + +bypass_asn() { + config_load omr-bypass + config_foreach _bypass_asn asns +} + +_bypass_omr_server() { + local ip + config_get ip $1 ip + _bypass_ip $ip +} + + +_ss_rules_config() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF + fi +} + +_v2ray_rules_config() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF + fi +} + +_xray_rules_config() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF + fi +} + +_delete_dhcp_ipset() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete dhcp.$1 + } +} + +_delete_firewall_rules() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete firewall.$1 + } +} + +boot() { + BOOT=1 + start "$@" +} + +start_service() { + #local count + logger -t "omr-bypass" "Starting OMR-ByPass..." + + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + #uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + #uci -q commit firewall + + + add_domains="false" + [ -d /proc/net/xt_ndpi ] && { + config_load omr-bypass + config_foreach _add_proto proto + } + disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" + #noipv6="$(uci -q get omr-bypass.global.noipv6)" + + cat > /etc/firewall.omr-bypass <<-EOF + #!/bin/sh + #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all accept + #nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all accept + EOF + uci batch <<-EOF + set firewall.omr_bypass=include + set firewall.omr_bypass.enabled='1' + set firewall.omr_bypass.type='script' + set firewall.omr_bypass.path='/etc/firewall.omr-bypass' + set firewall.omr_bypass.fw4_compatible='1' + commit firewall + EOF + echo "intf_rule" + config_load network + config_foreach _intf_rule interface + _intf_rule all + _intf_rule vpn1 + local ndpi_rules="" + echo "bypass server" + if [ "$(uci -q get openmptcprouter.settings.bypass_servers)" = "1" ]; then + config_load openmptcprouter + config_foreach _bypass_omr_server server + fi + config_load omr-bypass + echo "bypass ip" + config_foreach _bypass_ip_set ips + echo "bypass mac" + config_foreach _bypass_mac macs + echo "bypass lan ip" + config_foreach _bypass_lan_ip lan_ip + echo "bypass dest port" + config_foreach _bypass_dest_port dest_port + echo "bypass src port" + config_foreach _bypass_src_port src_port + echo "bypass asn" + config_foreach _bypass_asn asns + echo "bypass domains" + config_foreach _bypass_domains domains + uci -q commit dhcp + +# ip rule add prio 1 fwmark 0x4539 lookup 991337 > /dev/null 2>&1 +# ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 + + #config_load shadowsocks-libev + #config_foreach _ss_rules_config ss_rules + ([ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] || [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]) && _ss_rules_config + #config_load shadowsocks-rust + #config_foreach _ss_rules_config ss_rules + [ "$(uci -q get v2ray.main.enabled)" = "1" ] && _v2ray_rules_config + [ "$(uci -q get xray.main.enabled)" = "1" ] && _xray_rules_config + + # NDPI Netfilter is not available for nftables + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass-dpi | $IPTABLESRESTORE -w --counters 2>/dev/null + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass-dpi - + -A INPUT -j omr-bypass-dpi + -A FORWARD -j omr-bypass-dpi + COMMIT + EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESSAVE --counters | grep -v omr-bypass6-dpi | $IP6TABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass6-dpi - + -A INPUT -j omr-bypass6-dpi + -A FORWARD -j omr-bypass6-dpi + COMMIT + EOF + fi + config_load omr-bypass + [ -d /proc/net/xt_ndpi/proto ] && config_foreach _bypass_proto dpis + config_foreach _bypass_proto_without_ndpi dpis + uci -q commit omr-bypass + + [ -z "$RELOAD" ] && [ "$add_domains" = "true" ] && { + logger -t "omr-bypass" "Restart dnsmasq..." + /etc/init.d/dnsmasq restart + } + [ -n "$RELOAD" ] && [ "$add_domains" = "true" ] && { + logger -t "omr-bypass" "Reload dnsmasq..." + /etc/init.d/dnsmasq reload + } + fw4 restart + # Create a protocol list for UI from a sqlite DB when NDPI is not available + sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst + config_load omr-bypass + config_foreach _add_proto_without_ndpi proto + sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst.new + mv /usr/share/omr-bypass/omr-bypass-proto.lst.new /usr/share/omr-bypass/omr-bypass-proto.lst + logger -t "omr-bypass" "OMR-ByPass is running" +} + +stop_service() { + # Rules for ndpi + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null + # disable all rules + uci -q set firewall.omr_bypass.enabled='0' + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + uci -q commit firewall + fw4 restart + exit 0 +} + +service_triggers() { + procd_add_reload_trigger omr-bypass network firewall +} + +reload_service() { + RELOAD=1 + start +} + +reload_rules() { + #[ "$( ipset -n list | grep omr_ )" = "" ] && return 0 + RELOAD=1 + start +} From f2a1250cccafa0eb845d01c030e6c6648a764719 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:33:19 +0100 Subject: [PATCH 1264/2059] Use omr-bypass nft for kernel > 5.4 --- luci-app-omr-bypass/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index 9dcd62369..1ceb86669 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables -LUCI_DEPENDS:=+omr-bypass +LUCI_DEPENDS:=+LINUX_5_4:omr-bypass +!LINUX_5_4:omr-bypass-nft #ifneq ($(CONFIG_TARGET_ramips),y) # #LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi # LUCI_DEPENDS+=+iptables-mod-ndpi +kmod-ipt-ndpi From aecc558e9de4eb13a667f16203ecff2ce881fbd6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:34:13 +0100 Subject: [PATCH 1265/2059] Add nftables support to OMR-DSCP and separate interface and scripts --- luci-app-omr-dscp/Makefile | 2 +- omr-dscp/Makefile | 52 +++++ .../root => omr-dscp/files}/etc/config/dscp | 0 .../files}/etc/init.d/omr-dscp | 6 +- omr-dscp/files/etc/init.d/omr-dscp-nft | 183 ++++++++++++++++++ 5 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 omr-dscp/Makefile rename {luci-app-omr-dscp/root => omr-dscp/files}/etc/config/dscp (100%) rename {luci-app-omr-dscp/root => omr-dscp/files}/etc/init.d/omr-dscp (98%) create mode 100755 omr-dscp/files/etc/init.d/omr-dscp-nft diff --git a/luci-app-omr-dscp/Makefile b/luci-app-omr-dscp/Makefile index 152e91cf0..b099678d6 100644 --- a/luci-app-omr-dscp/Makefile +++ b/luci-app-omr-dscp/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to DSCP - +LUCI_DEPENDS:=+LINUX_5_4:omr-dscp +!LINUX_5_4:omr-dscp-nft PKG_LICENSE:=GPLv3 #include ../luci/luci.mk diff --git a/omr-dscp/Makefile b/omr-dscp/Makefile new file mode 100644 index 000000000..58d60117f --- /dev/null +++ b/omr-dscp/Makefile @@ -0,0 +1,52 @@ +# +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=omr-dscp +PKG_VERSION:=0.1 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) +SECTION:=net +CATEGORY:=Network +DEPENDS:= +dnsmasq-full +LINUX_5_4:iptables +LINUX_5_4:iptables-mod-extra +LINUX_5_4:ipset +TITLE:=OMR-DSCP +endef + +define Package/$(PKG_NAME)-nft +SECTION:=net +CATEGORY:=Network +DEPENDS:= +dnsmasq-full +TITLE:=OMR-DSCP nft +endef + +define Package/$(PKG_NAME)/description +OMR-ByPass +endef + +define Package/$(PKG_NAME)-nft/description +OMR-ByPass nft support +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(CP) ./files/* $(1)/ + rm -f $(1)/etc/init.d/omr-dscp-nft +endef + +define Package/$(PKG_NAME)-nft/install + $(CP) ./files/* $(1)/ + mv $(1)/etc/init.d/omr-dscp-nft $(1)/etc/init.d/omr-dscp +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) +$(eval $(call BuildPackage,$(PKG_NAME)-nft)) diff --git a/luci-app-omr-dscp/root/etc/config/dscp b/omr-dscp/files/etc/config/dscp similarity index 100% rename from luci-app-omr-dscp/root/etc/config/dscp rename to omr-dscp/files/etc/config/dscp diff --git a/luci-app-omr-dscp/root/etc/init.d/omr-dscp b/omr-dscp/files/etc/init.d/omr-dscp similarity index 98% rename from luci-app-omr-dscp/root/etc/init.d/omr-dscp rename to omr-dscp/files/etc/init.d/omr-dscp index bed7c3bad..d5b7467c0 100755 --- a/luci-app-omr-dscp/root/etc/init.d/omr-dscp +++ b/omr-dscp/files/etc/init.d/omr-dscp @@ -11,9 +11,9 @@ USE_PROCD=1 # shellcheck disable=SC1091 . /lib/functions.sh -if [ -f /usr/sbin/iptables-legacy ]; then - IPTABLES="/usr/sbin/iptables-legacy" - IP6TABLES="/usr/sbin/ip6tables-legacy" +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" + IP6TABLES="/usr/sbin/ip6tables-nft" else IPTABLES="/usr/sbin/iptables" IP6TABLES="/usr/sbin/ip6tables" diff --git a/omr-dscp/files/etc/init.d/omr-dscp-nft b/omr-dscp/files/etc/init.d/omr-dscp-nft new file mode 100755 index 000000000..689136171 --- /dev/null +++ b/omr-dscp/files/etc/init.d/omr-dscp-nft @@ -0,0 +1,183 @@ +#!/bin/sh /etc/rc.common +# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : + +# shellcheck disable=SC2034 +START=90 +# shellcheck disable=SC2034 +STOP=10 +# shellcheck disable=SC2034 +USE_PROCD=1 + +# shellcheck disable=SC1091 +. /lib/functions.sh + +# Get the lan interface name +lan_device= +config_load network +config_get lan_device lan ifname + +#config_load dscp + +_add_dscp_domain() { + domain=""; config_get domain "$1" name "" + class=""; config_get class "$1" class "" + [ -n "$domain" ] && [ -n "$class" ] && [ -z "$(uci -q get dhcp.omr_dscp-$class.domain | grep $domain)" ] && { + uci -q batch <<-EOF + add_list dhcp.omr_dscp_$class.domain="$domain" + commit dhcp + EOF + } +} + +_add_dscp_domains_rules() { + for class in cs0 cs1 cs2 cs3 cs4 cs5 cs6 cs7 ef; do + uci -q batch <<-EOF + set dhcp.omr_dscp_${class}=ipset + add_list dhcp.omr_dscp_${class}.name="omr_dscp_${class}_4" + add_list dhcp.omr_dscp_${class}.name="omr_dscp_${class}_6" + commit dhcp + set firewall.omr_dscp_${class}_4=ipset + set firewall.omr_dscp_${class}_4.name="omr_dscp_${class}_4" + set firewall.omr_dscp_${class}_4.match='dest_ip" + set firewall.omr_dscp_${class}_6=ipset + set firewall.omr_dscp_${class}_6.name="omr_dscp_${class}_6" + set firewall.omr_dscp_${class}_6.match='dest_ip" + set firewall.omr_dscp_${class}=rule + set firewall.omr_dscp_${class}.ipset="omr_dscp-${class}_4" + set firewall.omr_dscp_${class}.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" + set firewall.omr_dscp_${class}.target='DSCP' + set firewall.omr_dscp_${class}.src='lan' + set firewall.omr_dscp_${class}.dest='*' + set firewall.omr6_dscp_${class}=rule + set firewall.omr6_dscp_${class}.ipset="omr_dscp-${class}_6" + set firewall.omr6_dscp_${class}.target='DSCP' + set firewall.omr6_dscp_${class}.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" + set firewall.omr6_dscp_${class}.src='lan' + set firewall.omr6_dscp_${class}.dest='*' + commit firewall + EOF + done +} + +_add_dscp_rules() { + proto="" ; config_get proto "$1" proto all + src_ip="" ; config_get src_ip "$1" src_ip 0.0.0.0/0 + src_port="" ; config_get src_port "$1" src_port 0:65535 + dest_ip="" ; config_get dest_ip "$1" dest_ip 0.0.0.0/0 + dest_port="" ; config_get dest_port "$1" dest_port 0:65535 + class="" ; config_get class "$1" class + direction="" ; config_get direction "$1" direction "upload" + comment="" ; config_get comment "$1" comment "-" + + src_port="$(echo $src_port | sed 's/:/-/g')" + dest_port="$(echo $dest_port | sed 's/:/-/g')" + count=$((count + 1)) + [ "$proto" = "all" ] && proto="tcp udp" + case "$direction" in + upload|both) + # Apply the rule locally + uci -q batch <<-EOF + set firewall.omr_dscp_rule$count=rule + set firewall.omr_dscp_rule$count.name="omr_dscp_rule$count" + set firewall.omr_dscp_rule$count.target="DSCP" + set firewall.omr_dscp_rule$count.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" + set firewall.omr_dscp_rule$count.src="lan" + set firewall.omr_dscp_rule$count.src_ip="$src_ip" + set firewall.omr_dscp_rule$count.dest_ip="$dest_ip" + set firewall.omr_dscp_rule$count.proto="$proto" + EOF + src_port="$(echo $src_port | sed 's/,/ /g')" + dest_port="$(echo $dest_port | sed 's/,/ /g')" + for port in $src_port; do + uci -q set firewall.omr_dscp_rule$count.src_port="$src_port" + done + for port in $src_port; do + uci -q set firewall.omr_dscp_rule$count.dest_port="$dest_port" + done + #_add_dscp_rule -m multiport --sports "$src_port" -m multiport --dports "$dest_port" + ;; + download|both) + ;; + esac + uci -q commit firewall + +} + + +_add_fwmark_chain() { + _ipt4 -N dscp_mark + _ipt4 -A PREROUTING -i "$lan_device" -j dscp_mark + _ipt4 -A POSTROUTING -j dscp_mark + _ipt6 -N dscp_mark + _ipt6 -A PREROUTING -i "$lan_device" -j dscp_mark + _ipt6 -A POSTROUTING -j dscp_mark + for class in cs4 cs5 cs6 cs7; do + # xtun (hex) -> 0x7874756e + _ipt4 -A dscp_mark \ + -m comment --comment "$class" \ + -m dscp --dscp-class "$class" \ + -j MARK --set-mark 0x7874756e + _ipt6 -A dscp_mark \ + -m comment --comment "$class" \ + -m dscp --dscp-class "$class" \ + -j MARK --set-mark 0x7874756e + done +} + +_remove_ipset_dnsmasq() { + [ -n "$(echo $1 | grep omr_dscp)" ] && uci -q delete dhcp.$1 +} + +_remove_rules() { + [ -n "$(echo $1 | grep omr_dscp)" ] && uci -q delete firewall.$1 +} + +_setup_tunnel() { + # Mark the packets to route through xtun0 + _add_fwmark_chain + # tun0: cs0 (default) + # xtun0: cs6 + _ipt4 -A dscp_output -o "tun0" -j DSCP --set-dscp-class cs6 + _ipt6 -A dscp_output -o "tun0" -j DSCP --set-dscp-class cs6 +} + +_cleanup() { + config_load dhcp + config_foreach _remove_ipset_dnsmasq + config_load firewall + config_foreach _remove_rules + uci -q commit dhcp + uci -q commit firewall + fw4 restart +} + +start_service() { + # Cleanup + _cleanup + + config_load dscp + # Add chains + _add_dscp_domains_rules + + # Setup the tunnels dscp / marks + #_setup_tunnel + + # Add rules base on the user configuration + count=0 + config_foreach _add_dscp_rules classify + config_foreach _add_dscp_domain domains + uci -q commit dhcp + fw4 restart +} + +stop_service() { + _cleanup +} + +reload_service() { + start +} + +service_triggers() { + procd_add_reload_trigger dscp +} From 18e99ca95cc15843afaec389cc606e97fd3ecd4b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:34:45 +0100 Subject: [PATCH 1266/2059] Only display supported encryption in Shadowsocks-Rust --- .../luci-static/resources/shadowsocks-rust.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js index 86c6ab0f8..0e4c4e071 100644 --- a/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js +++ b/luci-app-shadowsocks-rust/htdocs/luci-static/resources/shadowsocks-rust.js @@ -41,13 +41,13 @@ var modes = [ var methods = [ 'none', // aead - 'aes-128-gcm', - 'aes-256-gcm', - 'chacha20-ietf-poly1305', - '2022-blake3-aes-128-gcm', +// 'aes-128-gcm', +// 'aes-256-gcm', +// 'chacha20-ietf-poly1305', +// '2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm', - '2022-blake3-chacha8-poly1305', - '2022-blake3-chacha20-poly1305', +// '2022-blake3-chacha8-poly1305', +// '2022-blake3-chacha20-poly1305', ]; function ucival_to_bool(val) { @@ -72,7 +72,7 @@ return L.Class.extend({ } }); o.value('', ''); - o.value('all', 'all'); + //o.value('all', 'all'); o.default = ''; }, values_serverlist: function(o) { @@ -133,7 +133,7 @@ return L.Class.extend({ o.datatype = 'port'; o.size = 5; - o = optfunc(form.ListValue, 'method', _('Method'),_('Only 2022-blake3-aes-256-gcm is supported by OpenMPTCProuter Shadowsocks-GO')); + o = optfunc(form.ListValue, 'method', _('Method')); methods.forEach(function(m) { o.value(m); }); From 0a31d4daf48d314ff5f50caa0b79d36e2dad2687 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:35:17 +0100 Subject: [PATCH 1267/2059] Check if server answer on all multipath interfaces --- omr-tracker/files/bin/omr-tracker-server | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-server b/omr-tracker/files/bin/omr-tracker-server index 7d39f48ea..8760427eb 100755 --- a/omr-tracker/files/bin/omr-tracker-server +++ b/omr-tracker/files/bin/omr-tracker-server @@ -37,6 +37,29 @@ _check_server() { done } +_check_server_intf() { + local host=$1 + local port=$2 + local k=0 + for intf in $(multipath | awk '/default/ {print $1}'); do + while [ "$server_ping" = false ] && [ "$k" -le "$retry" ]; do + ret=$(curl \ + --max-time "$OMR_TRACKER_TIMEOUT" \ + -s \ + -k \ + --interface $intf + "https://${host}:${port}/" + ) + [ -n "$ret" ] && { + server_ping=true + return + } + k=$((k+1)) + sleep "${intervaltries}" + done + done +} + _disable_current() { local serv=$1 config_set $serv current "0" @@ -80,7 +103,8 @@ _check_master() { fi [ -z "$ip" ] && return #_ping_server $ip - _check_server $ip $port + #_check_server $ip $port + _check_server_intf $ip $port if [ "$server_ping" = true ]; then if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then logger -t "OMR-Tracker-Server" "Master server ${name} up ($ip), set it back" @@ -221,7 +245,8 @@ _check_backup() { [ -n "$ip6resolve" ] && ip="$ip6resolve" fi #_ping_server $ip - _check_server $ip $port + #_check_server $ip $port + _check_server_intf $ip $port #[ "$server_ping" = true ] && [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" = "$ip" ] && break if [ "$server_ping" = true ]; then if [ "$(uci -q get shadowsocks-libev.sss${count}.server | tr -d '\n')" != "$ip" ]; then From eb879b00952397b894a49c65a461a87d3df49775 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:35:53 +0100 Subject: [PATCH 1268/2059] Do not display OMR internal rules in firewall view --- .../htdocs/luci-static/resources/view/firewall/rules.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js index bacbbd704..3c0cdc296 100644 --- a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js +++ b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js @@ -183,7 +183,8 @@ return view.extend({ s.tab('timed', _('Time Restrictions')); s.filter = function(section_id) { - return (uci.get('firewall', section_id, 'target') != 'SNAT'); + //return (uci.get('firewall', section_id, 'target') != 'SNAT'); + return (uci.get('firewall', section_id, 'target') != 'SNAT' && section_id.startsWith('omr_dst') == false && section_id.startsWith('omr_dscp') == false); }; s.sectiontitle = function(section_id) { From bde5555932bd083c7329abc6276b54451e3fb3d6 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:36:37 +0100 Subject: [PATCH 1269/2059] Add nftables support on omr-tracker proxy --- omr-tracker/files/bin/omr-tracker-ss | 10 +++++----- omr-tracker/files/bin/omr-tracker-v2ray | 8 ++++---- omr-tracker/files/bin/omr-tracker-xray | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index 82b7ad3ce..d26c260f2 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -4,9 +4,9 @@ name=$0 basename="$(basename $0)" -if [ -f /usr/sbin/iptables-legacy ]; then - IPTABLES="/usr/sbin/iptables-legacy" - IPTABLESSAVE="/usr/sbin/iptables-legacy-save" +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" + IPTABLESSAVE="/usr/sbin/iptables-nft-save" else IPTABLES="/usr/sbin/iptables" IPTABLESSAVE="/usr/sbin/iptables-save" @@ -103,7 +103,7 @@ while true; do script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" [ -n "$script_alert_up" ] && eval $script_alert_up } - if [ -z "$($IPTABLESSAVE 2>/dev/null | grep :ssr)" ]; then + if [ -z "$($IPTABLESSAVE 2>/dev/null | grep :ssr)" ] && [ -z "$(nft list ruleset | grep ss_r)" ] && [ -z "$(nft list ruleset | grep ssr_r)" ]; then if [ "$type" = "libev" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then _log "Reload Shadowsocks rules" /etc/init.d/shadowsocks-libev rules_up 2> /dev/null @@ -120,7 +120,7 @@ while true; do last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" [ "${last}" -ge "${retry}" ] && { - if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ssr)" ]; then + if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ssr)" ] || [ -n "$(nft list ruleset | grep ss_r)" ]; then _log "Shadowsocks ${server} is down (can't contact via http ${nocontact})" OMR_TRACKER_STATUS_MSG="Shadowsocks ${server} is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.ss_${server}="down" diff --git a/omr-tracker/files/bin/omr-tracker-v2ray b/omr-tracker/files/bin/omr-tracker-v2ray index 6ef18c429..519399ce8 100755 --- a/omr-tracker/files/bin/omr-tracker-v2ray +++ b/omr-tracker/files/bin/omr-tracker-v2ray @@ -4,8 +4,8 @@ name=$0 basename="$(basename $0)" -if [ -f /usr/sbin/iptables-legacy ]; then - IPTABLES="/usr/sbin/iptables-legacy" +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" else IPTABLES="/usr/sbin/iptables" fi @@ -100,7 +100,7 @@ while true; do script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" [ -n "$script_alert_up" ] && eval $script_alert_up } - if [ -z "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^v2r)" ]; then + if [ -z "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^v2r)" ] && [ -z "$(nft list ruleset 2>/dev/null | grep 'chain v2r')" ]; then _log "Reload V2Ray rules" /etc/init.d/v2ray rules_up 2> /dev/null _get_ip @@ -111,7 +111,7 @@ while true; do last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" [ "${last}" -ge "${retry}" ] && { - if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^v2r)" ]; then + if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^v2r)" ] || [ -n "$(nft list ruleset 2>/dev/null | grep 'chain v2r')" ]; then _log "V2Ray is down (can't contact via http ${nocontact})" OMR_TRACKER_STATUS_MSG="V2Ray is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.v2ray="down" diff --git a/omr-tracker/files/bin/omr-tracker-xray b/omr-tracker/files/bin/omr-tracker-xray index 21272b1e6..4aae08e76 100755 --- a/omr-tracker/files/bin/omr-tracker-xray +++ b/omr-tracker/files/bin/omr-tracker-xray @@ -4,8 +4,8 @@ name=$0 basename="$(basename $0)" -if [ -f /usr/sbin/iptables-legacy ]; then - IPTABLES="/usr/sbin/iptables-legacy" +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" else IPTABLES="/usr/sbin/iptables" fi @@ -100,7 +100,7 @@ while true; do script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" [ -n "$script_alert_up" ] && eval $script_alert_up } - if [ -z "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^xr)" ]; then + if [ -z "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^xr)" ] && [ -z "$(nft list ruleset 2>/dev/null | grep 'chain xr')" ]; then _log "Reload xray rules" /etc/init.d/xray rules_up 2> /dev/null _get_ip @@ -111,7 +111,7 @@ while true; do last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" [ "${last}" -ge "${retry}" ] && { - if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^xr)" ]; then + if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ^xr)" ] || [ -n "$(nft list ruleset 2>/dev/null | grep 'chain xr')" ]; then _log "xray is down (can't contact via http ${nocontact})" OMR_TRACKER_STATUS_MSG="xray is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.xray="down" From 1d4a964169c8298a4de962bee3f52a6930c8fb3a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:38:33 +0100 Subject: [PATCH 1270/2059] Add nftables support to Shadowsocks-libev --- shadowsocks-libev/Makefile | 37 +- shadowsocks-libev/files/nft-rules/chain.uc | 122 ++++++ shadowsocks-libev/files/nft-rules/set.uc | 114 ++++++ shadowsocks-libev/files/nft-rules/ss-rules.uc | 8 + .../files/shadowsocks-libev.init-nft | 363 ++++++++++++++++++ 5 files changed, 640 insertions(+), 4 deletions(-) create mode 100644 shadowsocks-libev/files/nft-rules/chain.uc create mode 100644 shadowsocks-libev/files/nft-rules/set.uc create mode 100644 shadowsocks-libev/files/nft-rules/ss-rules.uc create mode 100755 shadowsocks-libev/files/shadowsocks-libev.init-nft diff --git a/shadowsocks-libev/Makefile b/shadowsocks-libev/Makefile index 6eea8b25c..b352558a7 100644 --- a/shadowsocks-libev/Makefile +++ b/shadowsocks-libev/Makefile @@ -44,8 +44,6 @@ endef define Package/shadowsocks-libev-config/install $(INSTALL_DIR) $(1)/etc/config $(INSTALL_DATA) ./files/shadowsocks-libev.config $(1)/etc/config/shadowsocks-libev - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/shadowsocks-libev.init $(1)/etc/init.d/shadowsocks-libev endef @@ -92,8 +90,11 @@ define Package/shadowsocks-libev-ss-rules/install $(INSTALL_DATA) ./files/firewall.ss-rules $(1)/etc $(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_BIN) ./files/ss-rules.defaults $(1)/etc/uci-defaults - $(INSTALL_DIR) $(1)/etc/sysctl.d - $(INSTALL_DATA) ./files/shadowsocks.conf $(1)/etc/sysctl.d + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/shadowsocks-libev.init $(1)/etc/init.d/shadowsocks-libev + +# $(INSTALL_DIR) $(1)/etc/sysctl.d +# $(INSTALL_DATA) ./files/shadowsocks.conf $(1)/etc/sysctl.d # $(INSTALL_DIR) $(1)/usr/lib/shadowsocks-libev # $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/*.ebpf $(1)/usr/lib/shadowsocks-libev endef @@ -108,6 +109,33 @@ uci batch <<-EOF EOF endef +define Package/shadowsocks-libev-ss-rules-nft + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=shadowsocks-libev ss-rules NFT + URL:=https://github.com/shadowsocks/shadowsocks-libev + DEPENDS:=+firewall4 \ + +ip \ + +resolveip \ + +ucode \ + +ucode-mod-fs \ + +shadowsocks-libev-ss-redir \ + +shadowsocks-libev-config \ + +kmod-nft-tproxy +endef + + +define Package/shadowsocks-libev-ss-rules-nft/install + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/ss-rules.defaults $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/shadowsocks-libev.init-nft $(1)/etc/init.d/shadowsocks-libev + $(INSTALL_DIR) $(1)/usr/share/ss-rules + $(INSTALL_DATA) ./files/nft-rules/* $(1)/usr/share/ss-rules/ +endef + + define Build/Prepare $(call Build/Prepare/Default) $(FIND) $(PKG_BUILD_DIR) \ @@ -128,6 +156,7 @@ TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include $(eval $(call BuildPackage,shadowsocks-libev-config)) $(eval $(call BuildPackage,shadowsocks-libev-ss-rules)) +$(eval $(call BuildPackage,shadowsocks-libev-ss-rules-nft)) $(foreach component,$(SHADOWSOCKS_COMPONENTS), \ $(eval $(call BuildPackage,shadowsocks-libev-$(component))) \ ) diff --git a/shadowsocks-libev/files/nft-rules/chain.uc b/shadowsocks-libev/files/nft-rules/chain.uc new file mode 100644 index 000000000..3047f1663 --- /dev/null +++ b/shadowsocks-libev/files/nft-rules/chain.uc @@ -0,0 +1,122 @@ +{% +function get_local_verdict() { + let v = o_local_default; + if (v == "checkdst") { + return "goto ss_rules_dst_" + proto; + } else if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return null; + } +} + +function get_src_default_verdict() { + let v = o_src_default; + if (v == "checkdst") { + return "goto ss_rules_dst_" + proto; + } else if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_dst_default_verdict() { + let v = o_dst_default; + if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_ifnames() { + let res = []; + for (let ifname in split(o_ifnames, /[ \t\n]/)) { + ifname = trim(ifname); + if (ifname) push(res, ifname); + } + return res; +} + +let type, hook, priority, redir_port; +if (proto == "tcp") { + type = "nat"; + hook = "prerouting"; + priority = -1; + redir_port = o_redir_tcp_port; +} else if (proto == "udp") { + type = "filter"; + hook = "prerouting"; + priority = "mangle"; + redir_port = o_redir_udp_port; + if (system(" + set -o errexit + iprr() { + while ip $1 rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip $1 rule add fwmark 1 lookup 100 + ip $1 route flush table 100 2>/dev/null || true + ip $1 route add local default dev lo table 100 + } + iprr -4 + iprr -6 + ") != 0) { + return ; + } +} else { + return; +} + +%} +{% if (redir_port): %} + +chain ss_rules_pre_{{ proto }} { + type {{ type }} hook {{ hook }} priority {{ priority }}; + meta l4proto {{ proto }}{%- let ifnames=get_ifnames(); if (length(ifnames)): %} iifname { {{join(", ", ifnames)}} }{% endif %} goto ss_rules_pre_src_{{ proto }}; +} + +chain ss_rules_pre_src_{{ proto }} { + ip daddr @ss_rules_dst_bypass_ accept; + ip6 daddr @ss_rules6_dst_bypass_ accept; + goto ss_rules_src_{{ proto }}; +} + +chain ss_rules_src_{{ proto }} { + ip saddr @ss_rules_src_bypass accept; + ip saddr @ss_rules_src_forward goto ss_rules_forward_{{ proto }}; + ip saddr @ss_rules_src_checkdst goto ss_rules_dst_{{ proto }}; + ip6 saddr @ss_rules6_src_bypass accept; + ip6 saddr @ss_rules6_src_forward goto ss_rules_forward_{{ proto }}; + ip6 saddr @ss_rules6_src_checkdst goto ss_rules_dst_{{ proto }}; + {{ get_src_default_verdict() }}; +} + +chain ss_rules_dst_{{ proto }} { + ip daddr @ss_rules_dst_bypass accept; + ip daddr @ss_rules_dst_forward goto ss_rules_forward_{{ proto }}; + ip6 daddr @ss_rules6_dst_bypass accept; + ip6 daddr @ss_rules6_dst_forward goto ss_rules_forward_{{ proto }}; + {{ get_dst_default_verdict() }}; +} + +{% if (proto == "tcp"): %} +chain ss_rules_forward_{{ proto }} { + meta l4proto tcp {{ o_nft_tcp_extra }} redirect to :{{ redir_port }}; +} +{% let local_verdict = get_local_verdict(); if (local_verdict): %} +chain ss_rules_local_out { + type {{ type }} hook output priority -1; + meta l4proto != tcp accept; + ip daddr @ss_rules_dst_bypass_ accept; + ip daddr @ss_rules_dst_bypass accept; + ip6 daddr @ss_rules6_dst_bypass_ accept; + ip6 daddr @ss_rules6_dst_bypass accept; + {{ local_verdict }}; +} +{% endif %} +{% elif (proto == "udp"): %} +chain ss_rules_forward_{{ proto }} { + meta l4proto udp {{ o_nft_udp_extra }} meta mark set 1 tproxy to :{{ redir_port }}; +} +{% endif %} +{% endif %} diff --git a/shadowsocks-libev/files/nft-rules/set.uc b/shadowsocks-libev/files/nft-rules/set.uc new file mode 100644 index 000000000..38140e7e1 --- /dev/null +++ b/shadowsocks-libev/files/nft-rules/set.uc @@ -0,0 +1,114 @@ +{% +let fs = require("fs"); + +let o_dst_bypass4_ = " + 0.0.0.0/8 + 10.0.0.0/8 + 100.64.0.0/10 + 127.0.0.0/8 + 169.254.0.0/16 + 172.16.0.0/12 + 192.0.0.0/24 + 192.0.2.0/24 + 192.31.196.0/24 + 192.52.193.0/24 + 192.88.99.0/24 + 192.168.0.0/16 + 192.175.48.0/24 + 198.18.0.0/15 + 198.51.100.0/24 + 203.0.113.0/24 + 224.0.0.0/4 + 240.0.0.0/4 +"; +let o_dst_bypass6_ = " + ::1/128 + ::/128 + ::ffff:0:0/96 + 64:ff9b:1::/48 + 100::/64 + fe80::/10 + 2001::/23 + fc00::/7 +"; +let o_dst_bypass_ = o_dst_bypass4_ + " " + o_dst_bypass6_; + +let set_suffix = { + "src_bypass": { + str: o_src_bypass, + }, + "src_forward": { + str: o_src_forward, + }, + "src_checkdst": { + str: o_src_checkdst, + }, + "dst_bypass": { + str: o_dst_bypass, + file: o_dst_bypass_file, + }, + "dst_bypass_": { + str: o_dst_bypass_, + }, + "dst_forward": { + str: o_dst_forward, + file: o_dst_forward_file, + }, + "dst_forward_rrst_": {}, +}; + +function set_name(suf, af) { + if (af == 4) { + return "ss_rules_"+suf; + } else { + return "ss_rules6_"+suf; + } +} + +function set_elements_parse(res, str, af) { + for (let addr in split(str, /[ \t\n]/)) { + addr = trim(addr); + if (!addr) continue; + if (af == 4 && index(addr, ":") != -1) continue; + if (af == 6 && index(addr, ":") == -1) continue; + push(res, addr); + } +} + +function set_elements(suf, af) { + let obj = set_suffix[suf]; + let res = []; + let addr; + + let str = obj["str"]; + if (str) { + set_elements_parse(res, str, af); + } + + let file = obj["file"]; + if (file) { + let fd = fs.open(file); + if (fd) { + str = fd.read("all"); + set_elements_parse(res, str, af); + } + } + + return res; +} +%} + +{% for (let suf in set_suffix): for (let af in [4, 6]): %} +set {{ set_name(suf, af) }} { + type ipv{{af}}_addr; + flags interval; + auto-merge; +{% let elems = set_elements(suf, af); if (length(elems)): %} + elements = { +{% for (let i = 0; i < length(elems); i++): %} + {{ elems[i] }}{% if (i < length(elems) - 1): %},{% endif %}{% print("\n") %} +{% endfor %} + } +{% endif %} +} +{% endfor; endfor %} diff --git a/shadowsocks-libev/files/nft-rules/ss-rules.uc b/shadowsocks-libev/files/nft-rules/ss-rules.uc new file mode 100644 index 000000000..f3955b2ef --- /dev/null +++ b/shadowsocks-libev/files/nft-rules/ss-rules.uc @@ -0,0 +1,8 @@ +{% + +include("set.uc"); +include("chain.uc", {proto: "tcp"}); +include("chain.uc", {proto: "udp"}); + +%} + diff --git a/shadowsocks-libev/files/shadowsocks-libev.init-nft b/shadowsocks-libev/files/shadowsocks-libev.init-nft new file mode 100755 index 000000000..3db4bbc56 --- /dev/null +++ b/shadowsocks-libev/files/shadowsocks-libev.init-nft @@ -0,0 +1,363 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (C) 2017-2019 Yousong Zhou +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# + +USE_PROCD=1 +START=99 + +EXTRA_COMMANDS="rules_up rules_down rules_exist" + +ss_confdir=/var/etc/shadowsocks-libev +ss_bindir=/usr/bin + +ssrules_uc="/usr/share/ss-rules/ss-rules.uc" +ssrules_nft="/etc/nftables.d/90-ss-rules.nft" + +ss_mkjson_server_conf() { + local cfgserver + + config_get cfgserver "$cfg" server + [ -n "$cfgserver" ] || return 1 + eval "$(validate_server_section "$cfg" ss_validate_mklocal)" + validate_server_section "$cfgserver" || return 1 + [ "$disabled" = 0 ] || return 1 + ss_mkjson_server_conf_ "$cfgserver" +} + +ss_mkjson_server_conf_() { + [ -n "$server_port" ] || return 1 + [ -z "$server" ] || json_add_string server "$server" + json_add_int server_port "$server_port" + [ -z "$method" ] || json_add_string method "$method" + [ -z "$key" ] || json_add_string key "$key" + [ -z "$password" ] || json_add_string password "$password" + [ -z "$plugin" ] || json_add_string plugin "$plugin" + [ -z "$plugin_opts" ] || json_add_string plugin_opts "$plugin_opts" +} + +ss_mkjson_ss_local_conf() { + ss_mkjson_server_conf +} + +ss_mkjson_ss_redir_conf() { + ss_mkjson_server_conf +} + +ss_mkjson_ss_server_conf() { + ss_mkjson_server_conf_ +} + +ss_mkjson_ss_tunnel_conf() { + ss_mkjson_server_conf || return 1 + [ -n "$tunnel_address" ] || return 1 + json_add_string tunnel_address "$tunnel_address" +} + +ss_xxx() { + local cfg="$1" + local cfgtype="$2" + local bin="$ss_bindir/${cfgtype/_/-}" + local confjson="$ss_confdir/$cfgtype.$cfg.json" + + [ -x "$bin" ] || return + eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)" + "validate_${cfgtype}_section" "$cfg" || return + [ "$disabled" = 0 ] || return + + json_init + ss_mkjson_${cfgtype}_conf || return + json_add_boolean use_syslog 1 + json_add_boolean ipv6_first "$ipv6_first" + json_add_boolean fast_open "$fast_open" + json_add_boolean reuse_port "$reuse_port" + json_add_boolean no_delay "$no_delay" + json_add_boolean mptcp "$mptcp" + [ -z "$local_address" ] || json_add_string local_address "$local_address" + [ -z "$local_port" ] || json_add_int local_port "$local_port" + [ -z "$local_ipv4_address" ] || json_add_string local_ipv4_address "$local_ipv4_address" + [ -z "$local_ipv6_address" ] || json_add_string local_ipv6_address "$local_ipv6_address" + [ -z "$mode" ] || json_add_string mode "$mode" + [ -z "$mtu" ] || json_add_int mtu "$mtu" + [ -z "$timeout" ] || json_add_int timeout "$timeout" + [ -z "$user" ] || json_add_string user "$user" + [ -z "$acl" ] || json_add_string acl "$acl" + json_dump -i >"$confjson" + + procd_open_instance "$cfgtype.$cfg" + procd_set_param command "$bin" -c "$confjson" + [ "$verbose" = 0 ] || procd_append_param command -v + if [ -n "$bind_address" ]; then + echo "$cfgtype $cfg: uci option bind_address deprecated, please switch to local_address" >&2 + procd_append_param command -b "$bind_address" + fi + procd_set_param file "$confjson" + procd_set_param respawn + procd_close_instance + ss_rules_cb +} + +ss_rules_cb() { + local cfgserver server + + if [ "$cfgtype" = ss_redir ]; then + config_get cfgserver "$cfg" server + config_get server "$cfgserver" server + ss_redir_servers="$ss_redir_servers $server" + if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then + eval "ss_rules_redir_tcp_$cfg=$local_port" + fi + if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then + eval "ss_rules_redir_udp_$cfg=$local_port" + fi + fi +} + +ss_rules_nft_gen() { + local cfg="ss_rules" + local cfgtype + local local_port_tcp local_port_udp + local remote_servers + + [ -s "$ssrules_uc" ] || return 1 + + config_get cfgtype "$cfg" TYPE + [ "$cfgtype" = ss_rules ] || return 1 + + eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)" + validate_ss_rules_section "$cfg" || return 1 + [ "$disabled" = 0 ] || return 2 + + if [ "$ss_rules_redir_tcp_$redir_tcp" = "all" ]; then + min_ss_redir_ports="65535" + max_ss_redir_ports="0" + config_load shadowsocks-libev + config_foreach ss_redir_ports ss_redir $cfgrulesserver + if [ "$min_ss_redir_ports" != "$max_ss_redir_ports" ]; then + all_ss_redir_ports=$min_ss_redir_ports-$max_ss_redir_ports + else + all_ss_redir_ports=$min_ss_redir_ports + fi + local_port_tcp="$all_ss_redir_ports" + if [ "$ss_rules_redir_udp_$redir_udp" = "all" ] || [ "$ss_rules_redir_udp_$redir_udp" = "hi1" ]; then + local_port_udp="$min_ss_redir_ports" + fi + else + eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" + eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" + fi + [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1 + remote_servers="$(echo $ss_redir_servers \ + | tr ' ' '\n' \ + | sort -u \ + | xargs -n 1 resolveip \ + | sort -u)" + + local tmp="/tmp/ssrules" + json_init + json_add_string o_remote_servers "$remote_servers" + json_add_int o_redir_tcp_port "$local_port_tcp" + json_add_int o_redir_udp_port "$local_port_udp" + json_add_string o_ifnames "$ifnames" + json_add_string o_local_default "$local_default" + json_add_string o_src_bypass "$src_ips_bypass" + json_add_string o_src_forward "$src_ips_forward" + json_add_string o_src_checkdst "$src_ips_checkdst" + json_add_string o_src_default "$src_default" + json_add_string o_dst_bypass "$dst_ips_bypass" + json_add_string o_dst_forward "$dst_ips_forward" + json_add_string o_dst_bypass_file "$dst_ips_bypass_file" + json_add_string o_dst_forward_file "$dst_ips_forward_file" + json_add_string o_dst_default "$dst_default" + json_add_string o_nft_tcp_extra "$nft_tcp_extra" + json_add_string o_nft_udp_extra "$nft_udp_extra" + json_dump -i >"$tmp.json" + + if utpl -S -F "$tmp.json" "$ssrules_uc" >"$tmp.nft" \ + && ! cmp -s "$tmp.nft" "$ssrules_nft"; then + echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" + if nft -f "$tmp.nft.chk" -c; then + mv "$tmp.nft" "$ssrules_nft" + fw4 restart + fi + rm -f "$tmp.nft.chk" + fi + rm -f "$tmp.json" + rm -f "$tmp.nft" +} + +ss_rules_nft_reset() { + if [ -f "$ssrules_nft" ]; then + rm -f "$ssrules_nft" + fw4 restart + fi +} + +ss_rules() { + if ! ss_rules_nft_gen; then + ss_rules_nft_reset + fi +} + +rules_up() { + if [ -f "${ssrules_nft}.down" ]; then + mv -f "${ssrules_nft}.down" "$ssrules_nft" + fw4 restart + fi +} + +rules_down() { + if [ -f "${ssrules_nft}" ]; then + mv -f "$ssrules_nft" "${ssrules_nft}.down" + fw4 restart + fi +} + +rules_exist() { + if [ -f "$ssrules_nft" ]; then + return 0 + else + return 1 + fi +} + +start_service() { + local cfgtype + + mkdir -p "$ss_confdir" + config_load shadowsocks-libev + for cfgtype in ss_local ss_redir ss_server ss_tunnel; do + config_foreach ss_xxx "$cfgtype" "$cfgtype" + done + ss_rules +} + +stop_service() { + ss_rules_nft_reset + rm -rf "$ss_confdir" +} + +service_triggers() { + procd_add_reload_interface_trigger wan + procd_add_reload_trigger shadowsocks-libev + procd_open_validate + validate_server_section + validate_ss_local_section + validate_ss_redir_section + validate_ss_rules_section + validate_ss_server_section + validate_ss_tunnel_section + procd_close_validate +} + +ss_validate_mklocal() { + local tuple opts + + shift 2 + for tuple in "$@"; do + opts="${tuple%%:*} $opts" + done + [ -z "$opts" ] || echo "local $opts" +} + +ss_validate() { + uci_validate_section shadowsocks-libev "$@" +} + +validate_common_server_options_() { + local cfgtype="$1"; shift + local cfg="$1"; shift + local func="$1"; shift + local stream_methods='"none", "plain", "chacha20-ietf-poly1305"' + local aead_methods='"aes-128-gcm", "aes-256-gcm","2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "chacha20-ietf-poly1305", "2022-blake3-chacha20-poly1305","2022-blake3-chacha8-poly1305"' + + + "${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \ + 'disabled:bool:0' \ + 'server:host' \ + 'server_port:port' \ + 'password:string' \ + 'key:string' \ + "method:or($stream_methods, $aead_methods)" \ + 'plugin:string' \ + 'plugin_opts:string' +} + +validate_common_client_options_() { + validate_common_options_ "$@" \ + 'server:uci("shadowsocks-libev", "@server")' \ + 'local_address:ipaddr:0.0.0.0' \ + 'local_port:port' +} + +validate_common_options_() { + local cfgtype="$1"; shift + local cfg="$1"; shift + local func="$1"; shift + + "${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \ + 'disabled:bool:0' \ + 'fast_open:bool:0' \ + 'ipv6_first:bool:0' \ + 'no_delay:bool:0' \ + 'reuse_port:bool:0' \ + 'mptcp:bool:0' \ + 'verbose:bool:0' \ + 'mode:or("tcp_only", "udp_only", "tcp_and_udp"):tcp_only' \ + 'mtu:uinteger' \ + 'timeout:uinteger' \ + 'user:string' +} + +validate_server_section() { + validate_common_server_options_ server "$1" "$2" +} + +validate_ss_local_section() { + validate_common_client_options_ ss_local "$1" "$2" \ + 'acl:file' +} + +validate_ss_redir_section() { + validate_common_client_options_ ss_redir "$1" "$2" +} + +validate_ss_rules_section() { + "${2:-ss_validate}" ss_rules "$1" \ + 'disabled:bool:0' \ + 'redir_tcp:uci("shadowsocks-libev", "@ss_redir","all")' \ + 'redir_udp:uci("shadowsocks-libev", "@ss_redir","all")' \ + 'src_ips_bypass:or(ipaddr,cidr)' \ + 'src_ips_forward:or(ipaddr,cidr)' \ + 'src_ips_checkdst:or(ipaddr,cidr)' \ + 'dst_ips_bypass_file:file' \ + 'dst_ips_bypass:or(ipaddr,cidr)' \ + 'dst_ips_forward_file:file' \ + 'dst_ips_forward:or(ipaddr,cidr)' \ + 'src_default:or("bypass", "forward", "checkdst"):checkdst' \ + 'dst_default:or("bypass", "forward"):bypass' \ + 'local_default:or("bypass", "forward", "checkdst"):bypass' \ + 'nft_tcp_extra:string' \ + 'nft_udp_extra:string' \ + 'ifnames:maxlength(15)' +} + +validate_ss_server_section() { + validate_common_server_options_ ss_server "$1" \ + validate_common_options_ \ + "$2" \ + 'local_address:ipaddr' \ + 'local_ipv4_address:ip4addr' \ + 'local_ipv6_address:ip6addr' \ + 'bind_address:ipaddr' \ + 'acl:file' +} + +validate_ss_tunnel_section() { + validate_common_client_options_ ss_tunnel "$1" \ + "$2" \ + 'tunnel_address:regex(".+\:[0-9]+")' +} From e6bcc2951cd17c322205b798e5fecd3b74de1e30 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:39:04 +0100 Subject: [PATCH 1271/2059] Add nftables support to Shadowsocks-rust --- shadowsocks-rust/Makefile | 30 ++ shadowsocks-rust/files/nft-rules/chain.uc | 126 +++++++ shadowsocks-rust/files/nft-rules/set.uc | 117 ++++++ shadowsocks-rust/files/nft-rules/ss-rules.uc | 8 + .../files/shadowsocks-rust.init-nft | 347 ++++++++++++++++++ 5 files changed, 628 insertions(+) create mode 100644 shadowsocks-rust/files/nft-rules/chain.uc create mode 100644 shadowsocks-rust/files/nft-rules/set.uc create mode 100644 shadowsocks-rust/files/nft-rules/ss-rules.uc create mode 100755 shadowsocks-rust/files/shadowsocks-rust.init-nft diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile index 74bf8ebae..11fb4694b 100644 --- a/shadowsocks-rust/Makefile +++ b/shadowsocks-rust/Makefile @@ -2,6 +2,7 @@ # # Copyright (C) 2017-2020 Yousong Zhou # Copyright (C) 2021-2023 ImmortalWrt.org +# Copyright (C) 2023 Yannick Chabanois (Ycarus) for OpenMPTCProuter include $(TOPDIR)/rules.mk @@ -64,6 +65,34 @@ define Package/shadowsocks-rust-config/install $(INSTALL_BIN) ./files/shadowsocks-rust.init $(1)/etc/init.d/shadowsocks-rust endef +define Package/shadowsocks-rust-config-nft + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=shadowsocks-rust config + URL:=https://github.com/shadowsocks/shadowsocks-rust + DEPENDS:=+firewall4 \ + +ip \ + +resolveip \ + +ucode \ + +ucode-mod-fs \ + +kmod-nft-tproxy +endef + + +define Package/shadowsocks-rust-config-nft/install + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/ssr-rules.defaults $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) ./files/shadowsocks-rust.config $(1)/etc/config/shadowsocks-rust + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/shadowsocks-rust.init-nft $(1)/etc/init.d/shadowsocks-rust + $(INSTALL_DIR) $(1)/usr/share/ssr-rules + $(INSTALL_DATA) ./files/nft-rules/* $(1)/usr/share/ssr-rules/ +endef + + + SHADOWSOCKS_COMPONENTS:=sslocal ssmanager ssserver ssurl ssservice define shadowsocks-rust/templates $(foreach component,$(SHADOWSOCKS_COMPONENTS), @@ -73,6 +102,7 @@ endef $(eval $(call shadowsocks-rust/templates)) $(eval $(call BuildPackage,shadowsocks-rust-config)) +$(eval $(call BuildPackage,shadowsocks-rust-config-nft)) $(foreach component,$(SHADOWSOCKS_COMPONENTS), \ $(eval $(call BuildPackage,shadowsocks-rust-$(component))) \ ) diff --git a/shadowsocks-rust/files/nft-rules/chain.uc b/shadowsocks-rust/files/nft-rules/chain.uc new file mode 100644 index 000000000..3b2cc0813 --- /dev/null +++ b/shadowsocks-rust/files/nft-rules/chain.uc @@ -0,0 +1,126 @@ +{% +function get_local_verdict() { + let v = o_local_default; + if (v == "checkdst") { + return "goto ss_rules_dst_" + proto; + } else if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return null; + } +} + +function get_src_default_verdict() { + let v = o_src_default; + if (v == "checkdst") { + return "goto ss_rules_dst_" + proto; + } else if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_dst_default_verdict() { + let v = o_dst_default; + if (v == "forward") { + return "goto ss_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_ifnames() { + let res = []; + for (let ifname in split(o_ifnames, /[ \t\n]/)) { + ifname = trim(ifname); + if (ifname) push(res, ifname); + } + return res; +} + +let type, hook, priority, redir_port; +if (proto == "tcp") { + type = "nat"; + hook = "prerouting"; + priority = -1; + redir_port = o_redir_tcp_port; +} else if (proto == "udp") { + type = "filter"; + hook = "prerouting"; + priority = "mangle"; + redir_port = o_redir_udp_port; + if (system(" + set -o errexit + iprr() { + while ip $1 rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip $1 rule add fwmark 1 lookup 100 + ip $1 route flush table 100 2>/dev/null || true + ip $1 route add local default dev lo table 100 + } + iprr -4 + iprr -6 + ") != 0) { + return ; + } +} else { + return; +} + +%} +{% if (redir_port): %} + +chain ss_rules_pre_{{ proto }} { + type {{ type }} hook {{ hook }} priority {{ priority }}; + meta l4proto {{ proto }}{%- let ifnames=get_ifnames(); if (length(ifnames)): %} iifname { {{join(", ", ifnames)}} }{% endif %} goto ss_rules_pre_src_{{ proto }}; +} + +chain ss_rules_pre_src_{{ proto }} { + ip daddr @ss_rules_dst_bypass_ accept; + ip6 daddr @ss_rules6_dst_bypass_ accept; + goto ss_rules_src_{{ proto }}; +} + +chain ss_rules_src_{{ proto }} { + ip saddr @ss_rules_src_bypass accept; + ip saddr @ss_rules_src_forward goto ss_rules_forward_{{ proto }}; + ip saddr @ss_rules_src_checkdst goto ss_rules_dst_{{ proto }}; + ip6 saddr @ss_rules6_src_bypass accept; + ip6 saddr @ss_rules6_src_forward goto ss_rules_forward_{{ proto }}; + ip6 saddr @ss_rules6_src_checkdst goto ss_rules_dst_{{ proto }}; + {{ get_src_default_verdict() }}; +} + +chain ss_rules_dst_{{ proto }} { + ip daddr @ss_rules_dst_bypass accept; + ip daddr @ss_rules_remote_servers accept; + ip daddr @ss_rules_dst_forward goto ss_rules_forward_{{ proto }}; + ip6 daddr @ss_rules6_dst_bypass accept; + ip6 daddr @ss_rules6_remote_servers accept; + ip6 daddr @ss_rules6_dst_forward goto ss_rules_forward_{{ proto }}; + {{ get_dst_default_verdict() }}; +} + +{% if (proto == "tcp"): %} +chain ss_rules_forward_{{ proto }} { + meta l4proto tcp {{ o_nft_tcp_extra }} redirect to :{{ redir_port }}; +} +{% let local_verdict = get_local_verdict(); if (local_verdict): %} +chain ss_rules_local_out { + type {{ type }} hook output priority -1; + meta l4proto != tcp accept; + ip daddr @ss_rules_remote_servers accept; + ip daddr @ss_rules_dst_bypass_ accept; + ip daddr @ss_rules_dst_bypass accept; + ip6 daddr @ss_rules6_remote_servers accept; + ip6 daddr @ss_rules6_dst_bypass_ accept; + ip6 daddr @ss_rules6_dst_bypass accept; + {{ local_verdict }}; +} +{% endif %} +{% elif (proto == "udp"): %} +chain ss_rules_forward_{{ proto }} { + meta l4proto udp {{ o_nft_udp_extra }} meta mark set 1 tproxy to :{{ redir_port }}; +} +{% endif %} +{% endif %} diff --git a/shadowsocks-rust/files/nft-rules/set.uc b/shadowsocks-rust/files/nft-rules/set.uc new file mode 100644 index 000000000..2698d444a --- /dev/null +++ b/shadowsocks-rust/files/nft-rules/set.uc @@ -0,0 +1,117 @@ +{% +let fs = require("fs"); + +let o_dst_bypass4_ = " + 0.0.0.0/8 + 10.0.0.0/8 + 100.64.0.0/10 + 127.0.0.0/8 + 169.254.0.0/16 + 172.16.0.0/12 + 192.0.0.0/24 + 192.0.2.0/24 + 192.168.0.0/16 + 192.31.196.0/24 + 192.52.193.0/24 + 192.88.99.0/24 + 192.175.48.0/24 + 198.18.0.0/15 + 198.51.100.0/24 + 203.0.113.0/24 + 224.0.0.0/4 + 240.0.0.0/4 +"; +let o_dst_bypass6_ = " + ::1/128 + ::/128 + ::ffff:0:0/96 + 64:ff9b:1::/48 + 100::/64 + fe80::/10 + 2001::/23 + fc00::/7 +"; +let o_dst_bypass_ = o_dst_bypass4_ + " " + o_dst_bypass6_; + +let set_suffix = { + "src_bypass": { + str: o_src_bypass, + }, + "src_forward": { + str: o_src_forward, + }, + "src_checkdst": { + str: o_src_checkdst, + }, + "remote_servers": { + str: o_remote_servers + }, + "dst_bypass": { + str: o_dst_bypass, + file: o_dst_bypass_file, + }, + "dst_bypass_": { + str: o_dst_bypass_, + }, + "dst_forward": { + str: o_dst_forward, + file: o_dst_forward_file, + }, + "dst_forward_rrst_": {}, +}; + +function set_name(suf, af) { + if (af == 4) { + return "ss_rules_"+suf; + } else { + return "ss_rules6_"+suf; + } +} + +function set_elements_parse(res, str, af) { + for (let addr in split(str, /[ \t\n]/)) { + addr = trim(addr); + if (!addr) continue; + if (af == 4 && index(addr, ":") != -1) continue; + if (af == 6 && index(addr, ":") == -1) continue; + push(res, addr); + } +} + +function set_elements(suf, af) { + let obj = set_suffix[suf]; + let res = []; + let addr; + + let str = obj["str"]; + if (str) { + set_elements_parse(res, str, af); + } + + let file = obj["file"]; + if (file) { + let fd = fs.open(file); + if (fd) { + str = fd.read("all"); + set_elements_parse(res, str, af); + } + } + + return res; +} +%} + +{% for (let suf in set_suffix): for (let af in [4, 6]): %} +set {{ set_name(suf, af) }} { + type ipv{{af}}_addr; + flags interval; + auto-merge; +{% let elems = set_elements(suf, af); if (length(elems)): %} + elements = { +{% for (let i = 0; i < length(elems); i++): %} + {{ elems[i] }}{% if (i < length(elems) - 1): %},{% endif %}{% print("\n") %} +{% endfor %} + } +{% endif %} +} +{% endfor; endfor %} diff --git a/shadowsocks-rust/files/nft-rules/ss-rules.uc b/shadowsocks-rust/files/nft-rules/ss-rules.uc new file mode 100644 index 000000000..f3955b2ef --- /dev/null +++ b/shadowsocks-rust/files/nft-rules/ss-rules.uc @@ -0,0 +1,8 @@ +{% + +include("set.uc"); +include("chain.uc", {proto: "tcp"}); +include("chain.uc", {proto: "udp"}); + +%} + diff --git a/shadowsocks-rust/files/shadowsocks-rust.init-nft b/shadowsocks-rust/files/shadowsocks-rust.init-nft new file mode 100755 index 000000000..d895c822a --- /dev/null +++ b/shadowsocks-rust/files/shadowsocks-rust.init-nft @@ -0,0 +1,347 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (C) 2017-2019 Yousong Zhou +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# + +USE_PROCD=1 +START=99 + +EXTRA_COMMANDS="rules_up rules_down rules_exist" + +ss_confdir=/var/etc/shadowsocks-rust +ss_bindir=/usr/bin + +ssrules_uc="/usr/share/ssr-rules/ss-rules.uc" +ssrules_nft="/etc/nftables.d/90-ssr-rules.nft" + +ss_mkjson_server_conf() { + local cfgserver + + config_get cfgserver "$cfg" server + [ -n "$cfgserver" ] || return 1 + eval "$(validate_server_section "$cfg" ss_validate_mklocal)" + validate_server_section "$cfgserver" || return 1 + [ "$disabled" = 0 ] || return 1 + ss_mkjson_server_conf_ "$cfgserver" +} + +ss_mkjson_server_conf_() { + [ -n "$server_port" ] || return 1 + [ -z "$server" ] || json_add_string server "$server" + json_add_int server_port "$server_port" + [ -z "$method" ] || json_add_string method "$method" + [ -z "$key" ] || json_add_string key "$key" + [ -z "$password" ] || json_add_string password "$password" + [ -z "$plugin" ] || json_add_string plugin "$plugin" + [ -z "$plugin_opts" ] || json_add_string plugin_opts "$plugin_opts" +} + +ss_mkjson_ss_local_conf() { + ss_mkjson_server_conf +} + +ss_mkjson_ss_redir_conf() { + ss_mkjson_server_conf +} + +ss_mkjson_ss_server_conf() { + ss_mkjson_server_conf_ +} + +ss_mkjson_ss_tunnel_conf() { + ss_mkjson_server_conf || return 1 + [ -n "$tunnel_address" ] || return 1 + json_add_string tunnel_address "$tunnel_address" +} + +ss_xxx() { + local cfg="$1" + local cfgtype="$2" +# local bin="$ss_bindir/${cfgtype/_/-}" + local bin="$ss_bindir/sslocal" + local confjson="$ss_confdir/$cfgtype.$cfg.json" + + [ -x "$bin" ] || return + eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)" + "validate_${cfgtype}_section" "$cfg" || return + [ "$disabled" = 0 ] || return + + json_init + ss_mkjson_${cfgtype}_conf || return + json_add_boolean use_syslog 1 + json_add_boolean ipv6_first "$ipv6_first" + json_add_boolean fast_open "$fast_open" + json_add_boolean reuse_port "$reuse_port" + json_add_boolean no_delay "$no_delay" + json_add_boolean mptcp "$mptcp" + [ "$cfgtype" != "ss_local" ] && json_add_string protocol "${cfgtype/ss_/}" + [ -z "$local_address" ] || json_add_string local_address "$local_address" + [ -z "$local_port" ] || json_add_int local_port "$local_port" + [ -z "$local_ipv4_address" ] || json_add_string local_ipv4_address "$local_ipv4_address" + [ -z "$local_ipv6_address" ] || json_add_string local_ipv6_address "$local_ipv6_address" + [ -z "$mode" ] || json_add_string mode "$mode" + [ -z "$mtu" ] || json_add_int mtu "$mtu" + [ -z "$timeout" ] || json_add_int timeout "$timeout" + [ -z "$user" ] || json_add_string user "$user" + [ -z "$acl" ] || json_add_string acl "$acl" + json_dump -i >"$confjson" + + procd_open_instance "$cfgtype.$cfg" + procd_set_param command "$bin" -c "$confjson" + [ "$verbose" = 0 ] || procd_append_param command -v + if [ -n "$bind_address" ]; then + echo "$cfgtype $cfg: uci option bind_address deprecated, please switch to local_address" >&2 + procd_append_param command -b "$bind_address" + fi + procd_set_param file "$confjson" + procd_set_param respawn + procd_close_instance + ss_rules_cb +} + +ss_rules_cb() { + local cfgserver server + + if [ "$cfgtype" = ss_redir ]; then + config_get cfgserver "$cfg" server + config_get server "$cfgserver" server + ss_redir_servers="$ss_redir_servers $server" + if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then + eval "ss_rules_redir_tcp_$cfg=$local_port" + fi + if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then + eval "ss_rules_redir_udp_$cfg=$local_port" + fi + fi +} + +ss_rules_nft_gen() { + local cfg="ss_rules" + local cfgtype + local local_port_tcp local_port_udp + local remote_servers + [ -s "$ssrules_uc" ] || return 1 + config_get cfgtype "$cfg" TYPE + [ "$cfgtype" = ss_rules ] || return 1 + eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)" + validate_ss_rules_section "$cfg" || return 1 + [ "$disabled" = 0 ] || return 2 + eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" + eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" + [ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1 + remote_servers="$(echo $ss_redir_servers \ + | tr ' ' '\n' \ + | sort -u \ + | xargs -n 1 resolveip \ + | sort -u)" + + local tmp="/tmp/ssrrules" + json_init + json_add_string o_remote_servers "$remote_servers" + json_add_int o_redir_tcp_port "$local_port_tcp" + json_add_int o_redir_udp_port "$local_port_udp" + json_add_string o_ifnames "$ifnames" + json_add_string o_local_default "$local_default" + json_add_string o_src_bypass "$src_ips_bypass" + json_add_string o_src_forward "$src_ips_forward" + json_add_string o_src_checkdst "$src_ips_checkdst" + json_add_string o_src_default "$src_default" + json_add_string o_dst_bypass "$dst_ips_bypass" + json_add_string o_dst_forward "$dst_ips_forward" + json_add_string o_dst_bypass_file "$dst_ips_bypass_file" + json_add_string o_dst_forward_file "$dst_ips_forward_file" + json_add_string o_dst_default "$dst_default" + json_add_string o_nft_tcp_extra "$nft_tcp_extra" + json_add_string o_nft_udp_extra "$nft_udp_extra" + json_dump -i >"$tmp.json" + + if utpl -S -F "$tmp.json" "$ssrules_uc" >"$tmp.nft" \ + && ! cmp -s "$tmp.nft" "$ssrules_nft"; then + echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" + if nft -f "$tmp.nft.chk" -c; then + mv "$tmp.nft" "$ssrules_nft" + fw4 restart + fi + rm -f "$tmp.nft.chk" + fi + rm -f "$tmp.json" + rm -f "$tmp.nft" +} + +ss_rules_nft_reset() { + if [ -f "$ssrules_nft" ]; then + rm -f "$ssrules_nft" + fw4 restart + fi +} + +ss_rules() { + if ! ss_rules_nft_gen; then + ss_rules_nft_reset + fi +} + +rules_up() { + if [ -f "${ssrules_nft}.down" ]; then + mv -f "${ssrules_nft}.down" "$ssrules_nft" + fw4 restart + fi +} + +rules_down() { + if [ -f "${ssrules_nft}" ]; then + mv -f "$ssrules_nft" "${ssrules_nft}.down" + fw4 restart + fi +} + +rules_exist() { + if [ -f "$ssrules_nft" ]; then + return 0 + else + return 1 + fi +} + + + +start_service() { + local cfgtype + + mkdir -p "$ss_confdir" + config_load shadowsocks-rust + for cfgtype in ss_local ss_redir ss_server ss_tunnel; do + config_foreach ss_xxx "$cfgtype" "$cfgtype" + done + ss_rules +} + +stop_service() { + ss_rules_nft_reset + rm -rf "$ss_confdir" +} + +service_triggers() { + procd_add_reload_interface_trigger wan + procd_add_reload_trigger shadowsocks-rust + procd_open_validate + validate_server_section + validate_ss_local_section + validate_ss_redir_section + validate_ss_rules_section + validate_ss_server_section + validate_ss_tunnel_section + procd_close_validate +} + +ss_validate_mklocal() { + local tuple opts + + shift 2 + for tuple in "$@"; do + opts="${tuple%%:*} $opts" + done + [ -z "$opts" ] || echo "local $opts" +} + +ss_validate() { + uci_validate_section shadowsocks-rust "$@" +} + +validate_common_server_options_() { + local cfgtype="$1"; shift + local cfg="$1"; shift + local func="$1"; shift + local stream_methods='"none", "plain", "chacha20-ietf-poly1305"' + local aead_methods='"aes-128-gcm", "aes-256-gcm","2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "chacha20-ietf-poly1305", "2022-blake3-chacha20-poly1305","2022-blake3-chacha8-poly1305"' + + + "${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \ + 'disabled:bool:0' \ + 'server:host' \ + 'server_port:port' \ + 'password:string' \ + 'key:string' \ + "method:or($stream_methods, $aead_methods)" \ + 'plugin:string' \ + 'plugin_opts:string' +} + +validate_common_client_options_() { + validate_common_options_ "$@" \ + 'server:uci("shadowsocks-rust", "@server")' \ + 'local_address:ipaddr:0.0.0.0' \ + 'local_port:port' +} + +validate_common_options_() { + local cfgtype="$1"; shift + local cfg="$1"; shift + local func="$1"; shift + + "${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \ + 'disabled:bool:0' \ + 'fast_open:bool:0' \ + 'ipv6_first:bool:0' \ + 'no_delay:bool:0' \ + 'reuse_port:bool:0' \ + 'mptcp:bool:0' \ + 'verbose:bool:0' \ + 'mode:or("tcp_only", "udp_only", "tcp_and_udp"):tcp_only' \ + 'mtu:uinteger' \ + 'timeout:uinteger' \ + 'user:string' +} + +validate_server_section() { + validate_common_server_options_ server "$1" "$2" +} + +validate_ss_local_section() { + validate_common_client_options_ ss_local "$1" "$2" \ + 'acl:file' +} + +validate_ss_redir_section() { + validate_common_client_options_ ss_redir "$1" "$2" +} + +validate_ss_rules_section() { + "${2:-ss_validate}" ss_rules "$1" \ + 'disabled:bool:0' \ + 'redir_tcp:uci("shadowsocks-rust", "@ss_redir")' \ + 'redir_udp:uci("shadowsocks-rust", "@ss_redir")' \ + 'src_ips_bypass:or(ipaddr,cidr)' \ + 'src_ips_forward:or(ipaddr,cidr)' \ + 'src_ips_checkdst:or(ipaddr,cidr)' \ + 'dst_ips_bypass_file:file' \ + 'dst_ips_bypass:or(ipaddr,cidr)' \ + 'dst_ips_forward_file:file' \ + 'dst_ips_forward:or(ipaddr,cidr)' \ + 'src_default:or("bypass", "forward", "checkdst"):checkdst' \ + 'dst_default:or("bypass", "forward"):bypass' \ + 'local_default:or("bypass", "forward", "checkdst"):bypass' \ + 'nft_tcp_extra:string' \ + 'nft_udp_extra:string' \ + 'ifnames:maxlength(15)' +} + +validate_ss_server_section() { + validate_common_server_options_ ss_server "$1" \ + validate_common_options_ \ + "$2" \ + 'local_address:ipaddr' \ + 'local_ipv4_address:ip4addr' \ + 'local_ipv6_address:ip6addr' \ + 'bind_address:ipaddr' \ + 'acl:file' +} + +validate_ss_tunnel_section() { + validate_common_client_options_ ss_tunnel "$1" \ + "$2" \ + 'tunnel_address:regex(".+\:[0-9]+")' +} From 9a141a377ef6e9cc5f6c6b2ae225b42d47f3a11c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:39:45 +0100 Subject: [PATCH 1272/2059] Add nftables support to OpenMPTCProuter-VPS for server VPN --- .../files/etc/init.d/openmptcprouter-vps | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 6b8c127c2..b1af71ac8 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -10,13 +10,13 @@ EXTRA_COMMANDS="set_pihole backup_send backup_get backup_list set_vps_firewall g . /usr/lib/unbound/iptools.sh -if [ -f /usr/sbin/iptables-legacy ]; then - IPTABLES="/usr/sbin/iptables-legacy" - IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" - IPTABLESSAVE="/usr/sbin/iptables-legacy-save" - IP6TABLES="/usr/sbin/ip6tables-legacy" - IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" - IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" + IPTABLESRESTORE="/usr/sbin/iptables-nft-restore" + IPTABLESSAVE="/usr/sbin/iptables-nft-save" + IP6TABLES="/usr/sbin/ip6tables-nft" + IP6TABLESRESTORE="/usr/sbin/ip6tables-nft-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-nft-save" else IPTABLES="/usr/sbin/iptables" IPTABLESRESTORE="/usr/sbin/iptables-restore" @@ -947,8 +947,11 @@ _set_lan_ip() { _set_bypass_ips() { local settings [ -z "$servername" ] && servername=$1 - bypassipv4s=$(ipset -q -o save list omr_dst_bypass_srv_vpn1 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') - bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + bypassipv4s=$(ipset -q -o save list omr_dst_bypass_srv_vpn1_4 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs4" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1_6 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs6" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + # " if [ "$bypassipv4s" != "" ] || [ "$bypassipv6s" != "" ]; then settings='{"ipv4s" : ['$bypassipv4s'],"ipv6s" : ['$bypassipv6s'],"intf" : "vpn1"}' result=$(_set_json "bypass" "$settings") From 3f890976edca5d466b929f8219188ee26a5dc600 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:40:43 +0100 Subject: [PATCH 1273/2059] Add nftables support to v2ray --- v2ray-core/Makefile | 41 +- v2ray-core/files/etc/init.d/v2ray-nft | 2304 +++++++++++++++++ .../files/usr/share/v2ray-rules/chain.uc | 126 + v2ray-core/files/usr/share/v2ray-rules/set.uc | 117 + .../files/usr/share/v2ray-rules/v2r-rules.uc | 8 + 5 files changed, 2592 insertions(+), 4 deletions(-) create mode 100755 v2ray-core/files/etc/init.d/v2ray-nft create mode 100644 v2ray-core/files/usr/share/v2ray-rules/chain.uc create mode 100644 v2ray-core/files/usr/share/v2ray-rules/set.uc create mode 100644 v2ray-core/files/usr/share/v2ray-rules/v2r-rules.uc diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index f89c9d1bd..ebae7974c 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -59,6 +59,20 @@ define Package/v2ray-extra PKGARCH:=all endef +define Package/v2ray-config + $(call Package/v2ray/template) + TITLE+= (init script) + DEPENDS:=v2ray-core + PKGARCH:=all +endef + +define Package/v2ray-config-nft + $(call Package/v2ray/template) + TITLE+= (init script with nft) + DEPENDS:=v2ray-core + PKGARCH:=all +endef + define Package/v2ray/description Project V is a set of network tools that help you to build your own computer network. It secures your network connections and thus protects your privacy. @@ -80,6 +94,18 @@ define Package/v2ray-extra/description This includes extra resources for v2ray-core. endef +define Package/v2ray-config/description + $(call Package/v2ray/description) + + This includes init script +endef + +define Package/v2ray-config-nft/description + $(call Package/v2ray/description) + + This includes init script with nftables support +endef + define Package/v2ray-core/conffiles /etc/config/v2ray /etc/v2ray/ @@ -92,12 +118,17 @@ define Package/v2ray-core/install $(INSTALL_DIR) $(1)/etc/v2ray/ $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/config.json $(1)/etc/v2ray/ +endef + +define Package/v2ray-config/install $(CP) ./files/* $(1)/ -# $(INSTALL_DIR) $(1)/etc/config/ -# $(INSTALL_CONF) $(CURDIR)/files/v2ray.conf $(1)/etc/config/v2ray -# $(INSTALL_DIR) $(1)/etc/init.d/ -# $(INSTALL_BIN) $(CURDIR)/files/v2ray.init $(1)/etc/init.d/v2ray + rm $(1)/etc/init.d/v2ray-nft +endef + +define Package/v2ray-config-nft/install + $(CP) ./files/* $(1)/ + mv $(1)/etc/init.d/v2ray-nft $(1)/etc/init.d/v2ray endef define Package/v2ray-example/install @@ -112,5 +143,7 @@ define Package/v2ray-extra/install endef $(eval $(call BuildPackage,v2ray-core)) +$(eval $(call BuildPackage,v2ray-config)) +$(eval $(call BuildPackage,v2ray-config-nft)) $(eval $(call BuildPackage,v2ray-example)) $(eval $(call BuildPackage,v2ray-extra)) diff --git a/v2ray-core/files/etc/init.d/v2ray-nft b/v2ray-core/files/etc/init.d/v2ray-nft new file mode 100755 index 000000000..90d5732f8 --- /dev/null +++ b/v2ray-core/files/etc/init.d/v2ray-nft @@ -0,0 +1,2304 @@ +#!/bin/sh /etc/rc.common +# +# Copyright 2019-2020 Xingwang Liao +# Copyright 2020-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Licensed to the public under the MIT License. +# + +START=99 +USE_PROCD=1 +EXTRA_COMMANDS="rules_up rules_down rules_exist" + +NAME=v2ray +CONFIG_FOLDER=/var/etc/$NAME + +v2rrules_uc="/usr/share/v2ray-rules/v2r-rules.uc" +v2rrules_nft="/etc/nftables.d/90-v2r-rules.nft" + +FILE_V2RAY_DNSMASQ=/tmp/dnsmasq.d/$NAME +FILE_V2RAY_DNSMASQ_CACHE=/tmp/$NAME.dnsmasq.cache + +IPSET_SRC_IGNORE_V4=v2ray_src_ignore_v4 +IPSET_SRC_IGNORE_V6=v2ray_src_ignore_v6 +IPSET_DST_PROXY_V4=v2ray_dst_proxy_v4 +IPSET_DST_PROXY_V6=v2ray_dst_proxy_v6 +IPSET_SRC_DIRECT_V4=ss_rules_src_bypass +IPSET_DST_DIRECT_V4=ss_rules_dst_bypass +IPSET_DST_DIRECT_V6=ss_rules6_dst_bypass + +OUTBOUND_SERVERS= +OUTBOUND_SERVERS_V4= +OUTBOUND_SERVERS_V6= + +TRANSPARENT_PROXY_EXPECTED=0 +TRANSPARENT_PROXY_PORT= +TRANSPARENT_PROXY_USE_TPROXY= +TRANSPARENT_PROXY_ADDITION= + +DNSMASQ_RESTART_EXPECTED=0 + +. /usr/share/libubox/jshn.sh + +_log() { + local level="$1" ; shift + local msg="$@" + logger -p "daemon.$level" -t "$NAME" "$msg" + + echo "[$level] $msg" >&2 +} + +_info() { + _log "info" $@ +} + +_err() { + _log "err" $@ +} + +version_over_5_4() { + MAJOR_VERSION=$(uname -r | awk -F '.' '{print $1}') + MINOR_VERSION=$(uname -r | awk -F '.' '{print $2}') + if [ $MAJOR_VERSION -ge 5 ] && [ $MINOR_VERSION -gt 13 ] || [ $MAJOR_VERSION -gt 5 ] ; then + return 0 + else + return 1 + fi +} + + +get_value_from_json() { + local json="$1" + local key="$2" + + test -n "$json" || return + + local value="" + + local old_ns + json_set_namespace "json_key" old_ns + json_load "$json" + json_get_var "$key" value + json_cleanup + json_set_namespace "$old_ns" + + echo "$value" +} + +get_commands_from_json() { + local json="$1" + + test -n "$json" || return + + jshn -r "$json" 2>/dev/null | grep -v "json_init" +} + +get_file_content() { + local filename="$1" + + test -n "$filename" || return + test -r "/etc/v2ray/${filename}.txt" || return + + cat "/etc/v2ray/${filename}.txt" | grep -v "^$" | grep -v "^#" +} + +append_server_ipv4() { + local addr="$1" + + test -n "$addr" || return + + if [ -z "$OUTBOUND_SERVERS_V4" ] ; then + OUTBOUND_SERVERS_V4="$addr" + else + OUTBOUND_SERVERS_V4="$(cat >&1 <<-EOF + $OUTBOUND_SERVERS_V4 + $addr + EOF + )" + fi +} + +append_server_ipv6() { + local addr="$1" + + test -n "$addr" || return + + if [ -z "$OUTBOUND_SERVERS_V6" ] ; then + OUTBOUND_SERVERS_V6="$addr" + else + OUTBOUND_SERVERS_V6="$(cat >&1 <<-EOF + $OUTBOUND_SERVERS_V6 + $addr + EOF + )" + fi +} + +append_server_address() { + local addr="$1" + + test -n "$addr" || return + + local ipv4 + for ipv4 in $(resolveip -4 -t 5 "$addr") ; do + append_server_ipv4 "$ipv4" + OUTBOUND_SERVERS="$OUTBOUND_SERVERS $ipv4" + done + + local ipv6 + for ipv6 in $(resolveip -6 -t 5 "$addr") ; do + append_server_ipv6 "$ipv6" + OUTBOUND_SERVERS="$OUTBOUND_SERVERS $ipv6" + done +} + +v2ray_section_validate() { + uci_validate_section "$NAME" "v2ray" "$1" \ + 'enabled:bool:0' \ + 'v2ray_file:string' \ + 'asset_location:directory' \ + 'mem_percentage:and(uinteger, max(100)):80' \ + 'config_file:file' \ + 'loglevel:or("debug", "info", "warning", "error", "none")' \ + 'access_log:string' \ + 'error_log:string' \ + 'stats_enabled:bool:0' \ + 'transport_enabled:bool:0' \ + 'inbounds:list(uci("v2ray", "@inbound"))' \ + 'outbounds:list(uci("v2ray", "@outbound"))' +} + +dns_section_validate() { + uci_validate_section "$NAME" "dns" "$1" \ + 'enabled:bool:0' \ + 'tag:string' \ + 'client_ip:ipaddr' \ + 'hosts:list(string)' \ + 'servers:list(uci("v2ray", "@dns_server"))' +} + +dns_server_section_validate() { + uci_validate_section "$NAME" "dns_server" "$1" \ + 'address:string' \ + 'port:port' \ + 'domains:list(string)' \ + 'expect_ips:list(string)' +} + +routing_section_validate() { + uci_validate_section "$NAME" "routing" "$1" \ + 'enabled:bool:0' \ + 'domain_strategy:or("AsIs", "IPIfNonMatch", "IPOnDemand")' \ + 'rules:list(uci("v2ray", "@routing_rule"))' \ + 'balancers:list(uci("v2ray", "@routing_balancer"))' +} + +routing_rule_section_validate() { + uci_validate_section "$NAME" "routing_rule" "$1" \ + 'type:"field"' \ + 'domain:list(string)' \ + 'ip:list(string)' \ + 'port:or(port, portrange)' \ + 'network:list(or("tcp", "udp"))' \ + 'source:list(string)' \ + 'user:list(string)' \ + 'inbound_tag:list(string)' \ + 'protocol:list(or("http", "tls", "bittorrent"))' \ + 'attrs:string' \ + 'outbound_tag:string' \ + 'balancer_tag:string' +} + +routing_balancer_section_validate() { + uci_validate_section "$NAME" "routing_balancer" "$1" \ + 'tag:string' \ + 'selector:list(string)' +} + +policy_section_validate() { + uci_validate_section "$NAME" "policy" "$1" \ + 'enabled:bool:0' \ + 'levels:list(uci("v2ray", "@policy_level"))' \ + 'system_stats_inbound_uplink:bool:0' \ + 'system_stats_inbound_downlink:bool:0' +} + +policy_level_section_validate() { + uci_validate_section "$NAME" "policy_level" "$1" \ + 'level:uinteger' \ + 'handshake:uinteger:4' \ + 'conn_idle:uinteger:300' \ + 'uplink_only:uinteger:2' \ + 'downlink_only:uinteger:5' \ + 'stats_user_uplink:bool:0' \ + 'stats_user_downlink:bool:0' \ + 'buffer_size:uinteger' +} + +reverse_section_validate() { + uci_validate_section "$NAME" "reverse" "$1" \ + 'enabled:bool:0' \ + 'bridges:list(string)' \ + 'portals:list(string)' +} + +inbound_section_validate() { + uci_validate_section "$NAME" "inbound" "$1" \ + 'port:or(port, portrange, string)' \ + 'listen:ipaddr' \ + 'protocol:string' \ + 's_dokodemo_door_address:host' \ + 's_dokodemo_door_port:port' \ + 's_dokodemo_door_network:list(or("tcp", "udp"))' \ + 's_dokodemo_door_timeout:uinteger' \ + 's_dokodemo_door_follow_redirect:bool:0' \ + 's_dokodemo_door_user_level:uiterger' \ + 's_http_account_user:string' \ + 's_http_account_pass:string' \ + 's_http_allow_transparent:bool:0' \ + 's_http_timeout:uinteger' \ + 's_http_user_level:uinteger' \ + 's_mtproto_user_email:string' \ + 's_mtproto_user_secret:string' \ + 's_mtproto_user_level:uinteger' \ + 's_shadowsocks_email:string' \ + 's_shadowsocks_method:string' \ + 's_shadowsocks_password:string' \ + 's_shadowsocks_level:uinteger' \ + 's_shadowsocks_ota:bool:0' \ + 's_shadowsocks_network:list(or("tcp", "udp")):tcp' \ + 's_socks_auth:or("noauth", "password")' \ + 's_socks_account_user:string' \ + 's_socks_account_pass:string' \ + 's_socks_udp:bool:0' \ + 's_socks_ip:host' \ + 's_socks_user_level:uinteger' \ + 's_vmess_client_id:string' \ + 's_vmess_client_alter_id:and(uinteger, max(65535))' \ + 's_vmess_client_email:string' \ + 's_vmess_client_user_level:uinteger' \ + 's_vmess_default_alter_id:and(uinteger, max(65535))' \ + 's_vmess_default_user_level:uinteger' \ + 's_vmess_detour_to:string' \ + 's_vmess_disable_insecure_encryption:bool:0' \ + 's_vless_client_id:string' \ + 's_vless_client_alter_id:and(uinteger, max(65535))' \ + 's_vless_client_email:string' \ + 's_vless_client_user_level:uinteger' \ + 's_vless_default_alter_id:and(uinteger, max(65535))' \ + 's_vless_default_user_level:uinteger' \ + 's_vless_detour_to:string' \ + 's_vless_disable_insecure_encryption:bool:0' \ + 's_trojan_client_id:string' \ + 's_trojan_client_alter_id:and(uinteger, max(65535))' \ + 's_trojan_client_email:string' \ + 's_trojan_client_user_level:uinteger' \ + 's_trojan_default_alter_id:and(uinteger, max(65535))' \ + 's_trojan_default_user_level:uinteger' \ + 's_trojan_detour_to:string' \ + 's_trojan_disable_insecure_encryption:bool:0' \ + 's_socks_client_id:string' \ + 's_socks_client_email:string:"openmptcprouter"' \ + 'ss_network:or("tcp", "kcp", "ws", "http", "domainsocket", "quic")' \ + 'ss_security:or("none", "tls")' \ + 'ss_tls_server_name:host' \ + 'ss_tls_alpn:string' \ + 'ss_tls_allow_insecure:bool:0' \ + 'ss_tls_allow_insecure_ciphers:bool:0' \ + 'ss_tls_disable_system_root:bool:0' \ + 'ss_tls_cert_usage:or("encipherment", "verify", "issue")' \ + 'ss_tls_cert_file:string' \ + 'ss_tls_key_file:string' \ + 'ss_tcp_header_type:or("none", "http")' \ + 'ss_tcp_header_request_version:string' \ + 'ss_tcp_header_request_method:string:GET' \ + 'ss_tcp_header_request_path:string' \ + 'ss_tcp_header_request_headers:list(string)' \ + 'ss_tcp_header_response_version:string' \ + 'ss_tcp_header_response_status:string' \ + 'ss_tcp_header_response_reason:string' \ + 'ss_tcp_header_response_headers:list(string)' \ + 'ss_kcp_mtu:and(min(576), max(1460))' \ + 'ss_kcp_tti:and(min(10), max(100))' \ + 'ss_kcp_uplink_capacity:uinteger' \ + 'ss_kcp_downlink_capacity:uinteger' \ + 'ss_kcp_congestion:bool:0' \ + 'ss_kcp_read_buffer_size:uinteger' \ + 'ss_kcp_write_buffer_size:uinteger' \ + 'ss_kcp_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_websocket_path:string' \ + 'ss_websocket_headers:list(string)' \ + 'ss_http_host:list(host)' \ + 'ss_http_path:string' \ + 'ss_domainsocket_path:string' \ + 'ss_quic_security:or("aes-128-gcm", "chacha20-poly1305", "none")' \ + 'ss_quic_key:string' \ + 'ss_quic_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_sockopt_tcp_fast_open:or("0", "1")' \ + 'ss_sockopt_mptcp:or("0", "1")' \ + 'ss_sockopt_tproxy:or("redirect", "tproxy", "off")' \ + 'tag:string' \ + 'sniffing_enabled:bool:0' \ + 'sniffing_dest_override:list(or("http", "tls"))' \ + 'allocate_strategy:or("always", "random")' \ + 'allocate_refresh:uinteger' \ + 'allocate_concurrency:uinteger' +} + +outbound_section_validate() { + uci_validate_section "$NAME" "outbound" "$1" \ + 'send_through:ipaddr' \ + 'protocol:string' \ + 'tag:string' \ + 's_blackhole_reponse_type:or("none", "http")' \ + 's_dns_network:or("tcp", "udp")' \ + 's_dns_address:string' \ + 's_dns_port:port' \ + 's_freedom_domain_strategy:or("AsIs", "UseIP", "UseIPv4", "UseIPv6")' \ + 's_freedom_redirect:string' \ + 's_freedom_user_level:uinteger' \ + 's_http_server_address:host' \ + 's_http_server_port:port' \ + 's_http_account_user:string' \ + 's_http_account_pass:string' \ + 's_shadowsocks_email:string' \ + 's_shadowsocks_address:host' \ + 's_shadowsocks_port:port' \ + 's_shadowsocks_method:string' \ + 's_shadowsocks_password:string' \ + 's_shadowsocks_level:uinteger' \ + 's_shadowsocks_ota:bool:0' \ + 's_socks_server_address:host' \ + 's_socks_server_port:port' \ + 's_socks_account_user:string' \ + 's_socks_account_pass:string' \ + 's_socks_user_level:uinteger' \ + 's_vmess_address:host' \ + 's_vmess_port:port' \ + 's_vmess_user_id:string' \ + 's_vmess_user_alter_id:and(uinteger, max(65535))' \ + 's_vmess_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_vmess_user_level:uinteger' \ + 's_vless_address:host' \ + 's_vless_port:port' \ + 's_vless_user_id:string' \ + 's_vless_user_alter_id:and(uinteger, max(65535))' \ + 's_vless_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_vless_user_encryption:or("auto", "none")' \ + 's_vless_user_level:uinteger' \ + 's_trojan_address:host' \ + 's_trojan_port:port' \ + 's_trojan_user_id:string' \ + 's_trojan_user_alter_id:and(uinteger, max(65535))' \ + 's_trojan_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_trojan_user_encryption:or("auto", "none")' \ + 's_trojan_user_level:uinteger' \ + 's_socks_address:host' \ + 's_socks_port:port' \ + 's_socks_user_id:string' \ + 's_socks_email:string:openmptcprouter' \ + 'ss_network:or("tcp", "kcp", "ws", "http", "domainsocket", "quic")' \ + 'ss_security:or("none", "tls")' \ + 'ss_tls_server_name:host' \ + 'ss_tls_alpn:string' \ + 'ss_tls_allow_insecure:bool:0' \ + 'ss_tls_allow_insecure_ciphers:bool:0' \ + 'ss_tls_disable_system_root:bool:0' \ + 'ss_tls_cert_usage:or("encipherment", "verify", "issue")' \ + 'ss_tls_cert_file:string' \ + 'ss_tls_key_file:string' \ + 'ss_tcp_header_type:or("none", "http")' \ + 'ss_tcp_header_request_version:string' \ + 'ss_tcp_header_request_method:string' \ + 'ss_tcp_header_request_path:string' \ + 'ss_tcp_header_request_headers:list(string)' \ + 'ss_tcp_header_response_version:string' \ + 'ss_tcp_header_response_status:string' \ + 'ss_tcp_header_response_reason:string' \ + 'ss_tcp_header_response_headers:list(string)' \ + 'ss_kcp_mtu:and(min(576), max(1460))' \ + 'ss_kcp_tti:and(min(10), max(100))' \ + 'ss_kcp_uplink_capacity:uinteger' \ + 'ss_kcp_downlink_capacity:uinteger' \ + 'ss_kcp_congestion:bool:0' \ + 'ss_kcp_read_buffer_size:uinteger' \ + 'ss_kcp_write_buffer_size:uinteger' \ + 'ss_kcp_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_websocket_path:string' \ + 'ss_websocket_headers:list(string)' \ + 'ss_http_host:list(host)' \ + 'ss_http_path:string' \ + 'ss_domainsocket_path:string' \ + 'ss_quic_security:or("aes-128-gcm", "chacha20-poly1305", "none")' \ + 'ss_quic_key:string' \ + 'ss_quic_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_sockopt_mark:uinteger' \ + 'ss_sockopt_tcp_fast_open:or("0", "1")' \ + 'ss_sockopt_mptcp:or("0", "1")' \ + 'stream_settings:string' \ + 'proxy_settings_tag:string' \ + 'mux_enabled:bool:0' \ + 'mux_concurrency:uinteger:8' +} + +add_v2ray_redirect_rules() { + local ext_args="$1" + local lan_devices="$2" + local lan_ipaddrs="$3" + + local port="$TRANSPARENT_PROXY_PORT" + local addition="$TRANSPARENT_PROXY_ADDITION" + local ipset_src_direct="$IPSET_SRC_DIRECT_V4" + local ipset_dst_direct="$IPSET_DST_DIRECT_V4" + + test -n "$port" || return + + ## This part need a rewrite + #v2ray-rules -f + ##logger -t "v2ray" "v2ray-rules -l ${port} -L ${port} -s $OUTBOUND_SERVERS_V4 --rule-name def --src-default forward --dst-default forward --local-default forward" + #commandline="-l ${port} -s $OUTBOUND_SERVERS_V4 --rule-name def --src-default forward --dst-default forward --local-default forward" + #[ "$(uci -q get v2ray.main_transparent_proxy.redirect_udp)" = "1" ] && [ "$(uci -q get v2ray.omrout.protocol)" != "socks" ] && commandline="$commandline -L ${port}" + #v2ray-rules $commandline + #[ "$(uci -q get v2ray.main.inbounds | grep omr6)" != "" ] && [ -n "$OUTBOUND_SERVERS_V6" ] && { + # v2ray-rules6 -f + # commandline="-l $((port+1)) -L $((port+1)) -s $OUTBOUND_SERVERS_V6 --rule-name def --src-default forward --dst-default forward --local-default forward" + # [ "$(uci -q get v2ray.main_transparent_proxy.redirect_udp)" = "1" ] && ([ "$(uci -q get v2ray.omrout.protocol)" = "vless" ] || [ "$(uci -q get v2ray.omrout.protocol)" = "vmess" ]) && commandline="$commandline -L ${port+1}" + # v2ray-rules6 $commandline + #} + + remote_servers="$(echo $OUTBOUND_SERVERS \ + | tr ' ' '\n' \ + | sort -u \ + | xargs -n 1 resolveip \ + | sort -u)" + + [ "$(uci -q get v2ray.main_transparent_proxy.redirect_udp)" = "1" ] && [ "$(uci -q get v2ray.omrout.protocol)" != "socks" ] && portudp="$port" + + local tmp="/tmp/v2rrules" + json_init + json_add_string o_remote_servers "$remote_servers" + json_add_int o_redir_tcp_port "$port" + json_add_int o_redir_udp_port "$portudp" + json_add_string o_ifnames "$ifnames" + json_add_string o_local_default "forward" + json_add_string o_src_bypass "$src_ips_bypass" + json_add_string o_src_forward "$src_ips_forward" + json_add_string o_src_checkdst "$src_ips_checkdst" + json_add_string o_src_default "checkdst" + json_add_string o_dst_bypass "$dst_ips_bypass" + json_add_string o_dst_forward "$dst_ips_forward" + json_add_string o_dst_bypass_file "$dst_ips_bypass_file" + json_add_string o_dst_forward_file "$dst_ips_forward_file" + json_add_string o_dst_default "forward" + json_add_string o_nft_tcp_extra "$nft_tcp_extra" + json_add_string o_nft_udp_extra "$nft_udp_extra" + json_dump -i >"$tmp.json" + + if utpl -S -F "$tmp.json" "$v2rrules_uc" >"$tmp.nft" \ + && ! cmp -s "$tmp.nft" "$v2rrules_nft"; then + echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" + if nft -f "$tmp.nft.chk" -c; then + mv "$tmp.nft" "$v2rrules_nft" + fw4 restart + fi + rm -f "$tmp.nft.chk" + fi + rm -f "$tmp.json" + rm -f "$tmp.nft" + + [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { + logger -t "v2ray" "Reload omr-bypass rules" + /etc/init.d/omr-bypass reload_rules + } +} + +init_rules_for_listfile() { + local direct_list_dns="$1" + local proxy_list_dns="$2" + + echo "# AUTO-GENERATED FILE. DO NOT MODIFY." >"$FILE_V2RAY_DNSMASQ_CACHE" + + # For direct list + local direct_content + direct_content="$(get_file_content "directlist")" + + if [ -n "$direct_content" ] ; then + echo "$direct_content" | \ + grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_DIRECT_V4 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + echo "$direct_content" | \ + grep -oE "([0-9a-fA-F]{0,4}:){1,7}([0-9a-fA-F]){0,4}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_DIRECT_V6 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + if [ -n "$direct_list_dns" ] ; then + echo "$direct_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|server=/&/$direct_list_dns\nipset=/&/$IPSET_DST_DIRECT_V4,$IPSET_DST_DIRECT_V6|" \ + >>"$FILE_V2RAY_DNSMASQ_CACHE" + else + echo "$direct_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|ipset=/&/$IPSET_DST_DIRECT_V4,$IPSET_DST_DIRECT_V6|" \ + >>"$FILE_V2RAY_DNSMASQ_CACHE" + fi + fi + + # For proxy list + local proxy_content + proxy_content="$(get_file_content "proxylist")" + + if [ -n "$proxy_content" ] ; then + echo "$proxy_content" | \ + grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_PROXY_V4 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + echo "$proxy_content" | \ + grep -oE "([0-9a-fA-F]{0,4}:){1,7}([0-9a-fA-F]){0,4}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_PROXY_V6 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + if [ -n "$proxy_list_dns" ] ; then + echo "$proxy_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|server=/&/$proxy_list_dns\nipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >>"$FILE_V2RAY_DNSMASQ_CACHE" + else + echo "$proxy_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|ipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >>"$FILE_V2RAY_DNSMASQ_CACHE" + fi + fi + + # For local devices outbound list + local src_content + src_content="$(get_file_content "srcdirectlist")" + + if [ -n "$src_content" ] ; then + echo "$src_content" | \ + grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_SRC_DIRECT_V4 & timeout 0/" | \ + ipset -! restore 2>/dev/null + fi + +} + +gracefully_restart_dnsmasq() { + if [ "x$DNSMASQ_RESTART_EXPECTED" = "x1" ] && [ -x "/etc/init.d/dnsmasq" ] ; then + _info "Restarting dnsmasq..." + /etc/init.d/dnsmasq restart >/dev/null 2>&1 + DNSMASQ_RESTART_EXPECTED=0 + fi +} + +add_dns_settings() { + local section="${1}_dns" + + if ! dns_section_validate "$section" ; then + _err "Invalid DNS config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "DNS disabled: $section" + return 0 + fi + + json_add_object "dns" + + test -n "$tag" && \ + json_add_string "tag" "$tag" + test -n "$client_ip" && \ + json_add_string "clientIp" "$client_ip" + + if [ -n "$hosts" ] ; then + json_add_object "hosts" + + local h + for h in $hosts ; do + local domain="$(echo "$h" | cut -d'|' -f1)" + local ip="$(echo "$h" | cut -d'|' -f2)" + + if [ -n "$domain" ] && [ -n "$ip" ] ; then + json_add_string "$domain" "$ip" + fi + done + + json_close_object # hosts + fi + + if [ -n "$servers" ] ; then + json_add_array "servers" + + for ss in $servers ; do + if dns_server_section_validate "$ss" ; then + if [ -z "$address" ] ; then + continue + fi + + if [ -z "${port}${domains}${expect_ips}" ] ; then + json_add_string "" "$address" + else + json_add_object "" + json_add_string "address" "$address" + + if [ -n "$port" ] ; then + json_add_int "port" "$port" + else + json_add_int "port" "53" + fi + + if [ -n "$domains" ] ; then + json_add_array "domains" + + local d + for d in $domains ; do + json_add_string "" "$d" + done + + json_close_array # domains + fi + + if [ -n "$expect_ips" ] ; then + json_add_array "expectIPs" + + local e + for e in $expect_ips ; do + json_add_string "" "$e" + done + + json_close_array # expectIPs + fi + + json_close_object + fi + fi + done + + json_close_array # servers + fi + + json_close_object # dns +} + +add_routing_settings() { + local section="${1}_routing" + + if ! routing_section_validate "$section" ; then + _err "Invalid routing config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "Routing disabled: $section" + return 0 + fi + + json_add_object "routing" + + test -n "$domain_strategy" && \ + json_add_string "domainStrategy" "$domain_strategy" + + if [ -n "$rules" ] ; then + json_add_array "rules" + + local rs + for rs in $rules ; do + if routing_rule_section_validate "$rs" ; then + json_add_object "" + + json_add_string "type" "$type" + + if [ -n "$domain" ] ; then + json_add_array "domain" + + local d + for d in $domain ; do + json_add_string "" "$d" + done + + json_close_array # domain + fi + + if [ -n "$ip" ] ; then + json_add_array "ip" + + local i + for i in $ip ; do + json_add_string "" "$i" + done + + json_close_array # ip + fi + + if [ -n "$port" ] ; then + json_add_string "port" "$(echo "$port" | tr -s ' ' ',')" + fi + + if [ -n "$network" ] ; then + json_add_string "network" "$(echo "$network" | tr -s ' ' ',')" + fi + + if [ -n "$source" ] ; then + json_add_array "source" + + local s + for s in $source ; do + json_add_string "" "$s" + done + + json_close_array # source + fi + + if [ -n "$user" ] ; then + json_add_array "user" + + local u + for u in $user ; do + json_add_string "" "$u" + done + + json_close_array # user + fi + + if [ -n "$inbound_tag" ] ; then + json_add_array "inboundTag" + + local it + for it in $inbound_tag ; do + json_add_string "" "$it" + done + + json_close_array # inboundTag + fi + + if [ -n "$protocol" ] ; then + json_add_array "protocol" + local p + for p in $protocol ; do + json_add_string "" "$p" + done + json_close_array # protocol + fi + + test -n "$attrs" && \ + json_add_string "attrs" "$attrs" + test -n "$outbound_tag" && \ + json_add_string "outboundTag" "$outbound_tag" + test -n "$balancer_tag" && \ + json_add_string "balancerTag" "$balancer_tag" + + json_close_object + fi + done + + json_close_array # rules + fi + + if [ -n "$balancers" ] ; then + json_add_array "balancers" + + local bs + for bs in $balancers ; do + if routing_balancer_section_validate "$bs" ; then + json_add_object "" + json_add_string "tag" "$tag" + + json_add_array "selector" + + local s + for s in $selector ; do + json_add_string "" "$s" + done + + json_close_array # selector + json_close_object + fi + done + + json_close_array # balancers + fi + + json_close_object +} + +add_policy_settings() { + local section="${1}_policy" + + if ! policy_section_validate "$section" ; then + _err "Invalid policy config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "Policy disabled: $section" + return 0 + fi + + json_add_object "policy" + + if [ -n "$levels" ] ; then + json_add_object "levels" + + local l_s + for l_s in $levels ; do + if policy_level_section_validate "$l_s" ; then + json_add_object "$level" + json_add_int "handshake" "$handshake" + json_add_int "connIdle" "$conn_idle" + json_add_int "uplinkOnly" "$uplink_only" + json_add_int "downlinkOnly" "$downlink_only" + json_add_boolean "statsUserUplink" "$stats_user_uplink" + json_add_boolean "statsUserDownlink" "$stats_user_downlink" + test -n "$buffer_size" && \ + json_add_int "bufferSize" "$buffer_size" + json_close_object + fi + done + + json_close_object # levels + fi + + json_add_object "system" + json_add_boolean "statsInboundUplink" "$system_stats_inbound_uplink" + json_add_boolean "statsInboundDownlink" "$system_stats_inbound_downlink" + json_close_object # system + + json_close_object # policy +} + +add_reverse_settings() { + local section="${1}_reverse" + + if ! reverse_section_validate "$section" ; then + _err "Invalid reverse config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "Reverse disabled: $section" + return 0 + fi + + json_add_object "reverse" + + if [ -n "$bridges" ] ; then + json_add_array "bridges" + + local b + for b in $bridges ; do + local tag="$(echo "$b" | cut -d'|' -f1)" + local domain="$(echo "$b" | cut -d'|' -f2)" + if [ -n "$tag" ] && [ -n "$domain" ] ; then + json_add_object "" + json_add_string "tag" "$tag" + json_add_string "domain" "$domain" + json_close_object + fi + done + + json_close_array # bridges + fi + + if [ -n "$portals" ] ; then + json_add_array "portals" + + local p + for p in $portals ; do + local tag="$(echo "$p" | cut -d'|' -f1)" + local domain="$(echo "$p" | cut -d'|' -f2)" + if [ -n "$tag" ] && [ -n "$domain" ] ; then + json_add_object "" + json_add_string "tag" "$tag" + json_add_string "domain" "$domain" + json_close_object + fi + done + + json_close_array # portals + fi + + json_close_object # reverse +} + +add_transport_settings() { + local json + json="$(get_file_content "transport")" + + if [ -z "$json" ] ; then + _err "Invalid transport config: $key" + return 1 + fi + + json_add_object "transport" + eval "$(get_commands_from_json "$json")" + json_close_object # transport +} + +add_inbound_setting() { + local section="$1" + + if ! inbound_section_validate "$section" ; then + _err "Invalid inbound section: $section" + return 1 + fi + + json_add_object "" + + test -n "$listen" && \ + json_add_string "listen" "$listen" + json_add_int "port" "$port" + json_add_string "protocol" "$protocol" + + case "${protocol:-x}" in + "dokodemo-door") + json_add_object "settings" + + if [ -n "$port" ] && [ "x$port" = "x$TRANSPARENT_PROXY_PORT" ] ; then + local settings_network="tcp" + + test -n "$TRANSPARENT_PROXY_ADDITION" && \ + settings_network="$settings_network,udp" + + json_add_boolean "followRedirect" "1" + json_add_string "network" "$settings_network" + else + test -n "$s_dokodemo_door_address" && \ + json_add_string "address" "$s_dokodemo_door_address" + + test -n "$s_dokodemo_door_port" && \ + json_add_int "port" "$s_dokodemo_door_port" + + test -n "$s_dokodemo_door_follow_redirect" && \ + json_add_boolean "followRedirect" "$s_dokodemo_door_follow_redirect" + + test -n "$s_dokodemo_door_network" && \ + json_add_string "network" "$(echo "$s_dokodemo_door_network" | tr -s ' ' ',')" + fi + + test -n "$s_dokodemo_door_timeout" && \ + json_add_int "timeout" "$s_dokodemo_door_timeout" + + test -n "$s_dokodemo_door_user_level" && \ + json_add_int "userLevel" "$s_dokodemo_door_user_level" + + json_close_object # settings + ;; + "http") + json_add_object "settings" + + if [ -n "$s_http_account_user" ] ; then + json_add_array "accounts" + + json_add_object "" + json_add_string "user" "$s_http_account_user" + json_add_string "pass" "$s_http_account_pass" + json_close_object + + json_close_array # accounts + fi + + json_add_boolean "allowTransparent" "$s_http_allow_transparent" + + test -n "$s_http_timeout" && \ + json_add_int "timeout" "$s_http_timeout" + test -n "$s_http_user_level" && \ + json_add_int "userLevel" "$s_http_user_level" + + json_close_object # settings + ;; + "mtproto") + json_add_object "settings" + + if [ -n "$s_mtproto_user_email" ] ; then + json_add_array "users" + json_add_object "" + + json_add_string "email" "$s_mtproto_user_email" + json_add_string "secret" "$s_mtproto_user_secret" + + test -n "$s_mtproto_user_level" && \ + json_add_int "level" "$s_mtproto_user_level" + + json_close_object + json_close_array # users + fi + + json_close_object # settings + ;; + "shadowsocks") + json_add_object "settings" + + json_add_string "method" "$s_shadowsocks_method" + json_add_string "password" "$s_shadowsocks_password" + + test -n "$s_shadowsocks_email" && \ + json_add_string "email" "$s_shadowsocks_email" + test -n "$s_shadowsocks_level" && \ + json_add_int "level" "$s_shadowsocks_level" + + json_add_boolean "ota" "$s_shadowsocks_ota" + json_add_string "network" "$(echo "$s_shadowsocks_network" | tr -s ' ' ',')" + + json_close_object # settings + ;; + "socks") + json_add_object "settings" + + json_add_string "auth" "$s_socks_auth" + + if [ -n "$s_socks_account_user" ] ; then + json_add_array "accounts" + json_add_object "" + json_add_string "user" "$s_socks_account_user" + json_add_string "pass" "$s_socks_account_pass" + json_close_object + json_close_array # accounts + fi + if [ -n "$s_socks_client_id" ] ; then + json_add_array "accounts" + json_add_object "" + json_add_string "user" "$s_socks_email" + json_add_string "pass" "$s_socks_client_id" + json_close_object + json_close_array # accounts + fi + + json_add_boolean "udp" "$s_socks_udp" + + test -n "$s_socks_ip" && \ + json_add_string "ip" "$s_socks_ip" + test -n "$s_socks_user_level" && \ + json_add_int "userLevel" "$s_socks_user_level" + + json_close_object # settings + ;; + "vmess") + json_add_object "settings" + + if [ -n "$s_vmess_client_id" ] ; then + json_add_array "clients" + json_add_object "" + + json_add_string "id" "$s_vmess_client_id" + + test -n "$s_vmess_client_alter_id" && \ + json_add_int "alterId" "$s_vmess_client_alter_id" + test -n "$s_vmess_client_email" && \ + json_add_string "email" "$s_vmess_client_email" + test -n "$s_vmess_client_user_level" && \ + json_add_int "level" "$s_vmess_client_user_level" + + json_close_object + json_close_array # clients + fi + + json_add_object "default" + + test -n "$s_vmess_default_alter_id" && \ + json_add_int "alterId" "$s_vmess_default_alter_id" + test -n "$s_vmess_default_user_level" && \ + json_add_int "level" "$s_vmess_default_user_level" + + json_close_object # default + + if [ -n "$s_vmess_detour_to" ] ; then + json_add_object "detour" + json_add_string "to" "$s_vmess_detour_to" + json_close_object # detour + fi + + json_add_boolean "disableInsecureEncryption" "$s_vmess_disable_insecure_encryption" + + json_close_object # settings + ;; + "vless") + json_add_object "settings" + + if [ -n "$s_vless_client_id" ] ; then + json_add_array "clients" + json_add_object "" + + json_add_string "id" "$s_vless_client_id" + + test -n "$s_vless_client_alter_id" && \ + json_add_int "alterId" "$s_vless_client_alter_id" + test -n "$s_vless_client_email" && \ + json_add_string "email" "$s_vless_client_email" + test -n "$s_vless_client_user_level" && \ + json_add_int "level" "$s_vless_client_user_level" + + json_close_object + json_close_array # clients + fi + + json_add_object "default" + + test -n "$s_vless_default_alter_id" && \ + json_add_int "alterId" "$s_vless_default_alter_id" + test -n "$s_vless_default_user_level" && \ + json_add_int "level" "$s_vless_default_user_level" + + json_close_object # default + + if [ -n "$s_vless_detour_to" ] ; then + json_add_object "detour" + json_add_string "to" "$s_vless_detour_to" + json_close_object # detour + fi + + json_add_boolean "disableInsecureEncryption" "$s_vless_disable_insecure_encryption" + + json_close_object # settings + ;; + "trojan") + json_add_object "settings" + + if [ -n "$s_trojan_client_id" ] ; then + json_add_array "clients" + json_add_object "" + + json_add_string "password" "$s_trojan_client_id" + + test -n "$s_trojan_client_alter_id" && \ + json_add_int "alterId" "$s_trojan_client_alter_id" + test -n "$s_trojan_client_email" && \ + json_add_string "email" "$s_trojan_client_email" + test -n "$s_trojan_client_user_level" && \ + json_add_int "level" "$s_trojan_client_user_level" + + json_close_object + json_close_array # clients + fi + + json_add_object "default" + + test -n "$s_trojan_default_alter_id" && \ + json_add_int "alterId" "$s_trojan_default_alter_id" + test -n "$s_trojan_default_user_level" && \ + json_add_int "level" "$s_trojan_default_user_level" + + json_close_object # default + + if [ -n "$s_trojan_detour_to" ] ; then + json_add_object "detour" + json_add_string "to" "$s_trojan_detour_to" + json_close_object # detour + fi + + json_add_boolean "disableInsecureEncryption" "$s_trojan_disable_insecure_encryption" + + json_close_object # settings + ;; + esac + + json_add_object "streamSettings" + + test -n "$ss_network" && \ + json_add_string "network" "$ss_network" + + test -n "$ss_security" && \ + json_add_string "security" "$ss_security" + + if [ "x$ss_security" = "xtls" ] ; then + json_add_object "tlsSettings" + + test -n "$ss_tls_server_name" && \ + json_add_string "serverName" "$ss_tls_server_name" + + if [ -n "$ss_tls_alpn" ] ; then + json_add_array "alpn" + json_add_string "" "$ss_tls_alpn" + json_close_array # alpn + fi + + json_add_boolean "allowInsecure" "$ss_tls_allow_insecure" + json_add_boolean "allowInsecureCiphers" "$ss_tls_allow_insecure_ciphers" + json_add_boolean "disableSystemRoot" "$ss_tls_disable_system_root" + + json_add_array "certificates" + if [ -n "$ss_tls_cert_file" ] ; then + json_add_object "" + + json_add_string "certificateFile" "$ss_tls_cert_file" + json_add_string "keyFile" "$ss_tls_key_file" + test -n "$ss_tls_cert_usage" && \ + json_add_string "usage" "$ss_tls_cert_usage" + + json_close_object + fi + json_close_array # certificates + + json_close_object # tlsSettings + fi + + case "${ss_network:-x}" in + "tcp") + json_add_object "tcpSettings" + + if [ -n "$ss_tcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_tcp_header_type" + + if [ "$ss_tcp_header_type" = "http" ] ; then + json_add_object "request" + test -n "$ss_tcp_header_request_version" && \ + json_add_string "version" "$ss_tcp_header_request_version" + json_add_string "method" "$ss_tcp_header_request_method" + + if [ -n "$ss_tcp_header_request_path" ] ; then + json_add_array "path" + json_add_string "" "$ss_tcp_header_request_path" + json_close_array # path + fi + + if [ -n "$ss_tcp_header_request_headers" ] ; then + json_add_object "headers" + + handle_request_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_request_headers" handle_request_header + + json_close_object # headers + fi + + json_close_object # request + + json_add_object "response" + + test -n "$ss_tcp_header_response_version" && \ + json_add_string "version" "$ss_tcp_header_response_version" + test -n "$ss_tcp_header_response_status" && \ + json_add_string "status" "$ss_tcp_header_response_status" + test -n "$ss_tcp_header_response_reason" && \ + json_add_string "reason" "$ss_tcp_header_response_reason" + + if [ -n "$ss_tcp_header_response_headers" ] ; then + json_add_object "headers" + + handle_response_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_response_headers" handle_response_header + + json_close_object # headers + fi + + json_close_object # response + fi + json_close_object # header + fi + + json_close_object # tcpSettings + ;; + "kcp") + json_add_object "kcpSettings" + + test -n "$ss_kcp_mtu" && \ + json_add_int "mtu" "$ss_kcp_mtu" + test -n "$ss_kcp_tti" && \ + json_add_int "tti" "$ss_kcp_tti" + test -n "$ss_kcp_uplink_capacity" && \ + json_add_int "uplinkCapacity" "$ss_kcp_uplink_capacity" + test -n "$ss_kcp_downlink_capacity" && \ + json_add_int "downlinkCapacity" "$ss_kcp_downlink_capacity" + json_add_boolean "congestion" "$ss_kcp_congestion" + test -n "$ss_kcp_read_buffer_size" && \ + json_add_int "readBufferSize" "$ss_kcp_read_buffer_size" + test -n "$ss_kcp_write_buffer_size" && \ + json_add_int "writeBufferSize" "$ss_kcp_write_buffer_size" + + if [ -n "$ss_kcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_kcp_header_type" + json_close_object # header + fi + + json_close_object # kcpSettings + ;; + "ws") + json_add_object "wsSettings" + + test -n "$ss_websocket_path" && \ + json_add_string "path" "$ss_websocket_path" + + if [ -n "$ss_websocket_headers" ] ; then + json_add_object "headers" + + handle_websocket_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_string "$name" "$value" + fi + } + config_list_foreach "$section" "ss_websocket_headers" handle_websocket_header + + json_close_object # headers + fi + + json_close_object # wsSettings + ;; + "http") + json_add_object "httpSettings" + + if [ -n "$ss_http_host" ] ; then + json_add_array "host" + + local h + for h in $ss_http_host ; do + json_add_string "" "$h" + done + + json_close_array # host + fi + + test -n "$ss_http_path" && \ + json_add_string "path" "$ss_http_path" + + json_close_object # httpSettings + ;; + "domainsocket") + json_add_object "dsSettings" + + test -n "$ss_domainsocket_path" && \ + json_add_string "path" "$ss_domainsocket_path" + + json_close_object # dsSettings + ;; + "quic") + json_add_object "quicSettings" + + test -n "$ss_quic_security" && \ + json_add_string "security" "$ss_quic_security" + test -n "$ss_quic_key" && \ + json_add_string "key" "$ss_quic_key" + + if [ -n "$ss_quic_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_quic_header_type" + json_close_object # header + fi + + json_close_object # quicSettings + ;; + esac + + json_add_object "sockopt" + +# if [ -n "$port" ] && [ "x$port" = "x$TRANSPARENT_PROXY_PORT" ] ; then +# if [ "x$TRANSPARENT_PROXY_USE_TPROXY" = "x1" ] ; then +# json_add_string "tproxy" "tproxy" +# else +# json_add_string "tproxy" "redirect" +# fi +# else + test -n "$ss_sockopt_tcp_fast_open" && \ + json_add_boolean "tcpFastOpen" "$ss_sockopt_tcp_fast_open" + if version_over_5_4; then + test -n "$ss_sockopt_mptcp" && \ + json_add_boolean "mptcp" "$ss_sockopt_mptcp" + fi + test -n "$ss_sockopt_tproxy" && \ + json_add_string "tproxy" "$ss_sockopt_tproxy" +# fi + + json_close_object # sockopt + + json_close_object # streamSettings + + test -n "$tag" && \ + json_add_string "tag" "$tag" + + json_add_object "sniffing" + + json_add_boolean "enabled" "$sniffing_enabled" + + if [ -n "$sniffing_dest_override" ] ; then + json_add_array "destOverride" + local d + for d in $sniffing_dest_override ; do + json_add_string "" "$d" + done + json_close_array # destOverride + fi + + json_close_object # sniffing + + if [ -n "$allocate_strategy" ] ; then + json_add_object "allocate" + json_add_string "strategy" "$allocate_strategy" + test -n "$allocate_refresh" && \ + json_add_int "refresh" "$allocate_refresh" + test -n "$allocate_concurrency" && \ + json_add_int "concurrency" "$allocate_concurrency" + json_close_object # allocate + fi + + json_close_object +} + +add_outbound_setting() { + local section="$1" + + if ! outbound_section_validate "$section" ; then + _err "Invalid outbound section: $section" + return 1 + fi + + json_add_object "" + + test -n "$send_through" && \ + json_add_string "sendThrough" "$send_through" + json_add_string "protocol" "$protocol" + + case "${protocol:-x}" in + "blackhole") + json_add_object "settings" + + if [ -n "$s_blackhole_reponse_type" ] ; then + json_add_object "response" + json_add_string "type" "$s_blackhole_reponse_type" + json_close_object # response + fi + + json_close_object # settings + ;; + "dns") + json_add_object "settings" + + test -n "$s_dns_network" && \ + json_add_string "network" "$s_dns_network" + + if [ -n "$s_dns_address" ] ; then + json_add_string "address" "$s_dns_address" + append_server_address "$s_dns_address" + fi + + test -n "$s_dns_port" && \ + json_add_int "port" "$s_dns_port" + + json_close_object # settings + ;; + "freedom") + json_add_object "settings" + + test -n "$s_freedom_domain_strategy" && \ + json_add_string "domainStrategy" "$s_freedom_domain_strategy" + test -n "$s_freedom_redirect" && \ + json_add_string "redirect" "$s_freedom_redirect" + test -n "$s_freedom_user_level" && \ + json_add_int "userLevel" "$s_freedom_user_level" + + json_close_object # settings + ;; + "http") + json_add_object "settings" + json_add_array "servers" + + json_add_object "" + + json_add_string "address" "$s_http_server_address" + append_server_address "$s_http_server_address" + + test -n "$s_http_server_port" && \ + json_add_int "port" "$s_http_server_port" + + if [ -n "$s_http_account_user" ] ; then + json_add_array "users" + json_add_object "" + + json_add_string "user" "$s_http_account_user" + json_add_string "pass" "$s_http_account_pass" + + json_close_object + json_close_array # users + fi + json_close_object + + json_close_array # servers + json_close_object # settings + ;; + "mtproto") + json_add_object "settings" + json_close_object + ;; + "shadowsocks") + json_add_object "settings" + json_add_array "servers" + + json_add_object "" + test -n "$s_shadowsocks_email" && \ + json_add_string "email" "$s_shadowsocks_email" + json_add_string "address" "$s_shadowsocks_address" + append_server_address "$s_shadowsocks_address" + + json_add_int "port" "$s_shadowsocks_port" + json_add_string "method" "$s_shadowsocks_method" + json_add_string "password" "$s_shadowsocks_password" + + test -n "$s_shadowsocks_level" && \ + json_add_int "level" "$s_shadowsocks_level" + json_add_boolean "ota" "$s_shadowsocks_ota" + json_close_object + + json_close_array # servers + json_close_object # settings + ;; + "vmess") + json_add_object "settings" + + json_add_array "vnext" + json_add_object "" + + json_add_string "address" "$s_vmess_address" + append_server_address "$s_vmess_address" + + json_add_int "port" "$s_vmess_port" + + json_add_array "users" + json_add_object "" + json_add_string "id" "$s_vmess_user_id" + json_add_int "alterId" "$s_vmess_user_alter_id" + test -n "$s_vmess_user_security" && \ + json_add_string "security" "$s_vmess_user_security" + test -n "$s_vmess_user_level" && \ + json_add_int "level" "$s_vmess_user_level" + json_close_object + json_close_array # users + + json_close_object + + json_close_array # vnext + json_close_object # settings + ;; + "vless") + json_add_object "settings" + + json_add_array "vnext" + json_add_object "" + + json_add_string "address" "$s_vless_address" + append_server_address "$s_vless_address" + + json_add_int "port" "$s_vless_port" + + json_add_array "users" + json_add_object "" + json_add_string "id" "$s_vless_user_id" + json_add_int "alterId" "$s_vless_user_alter_id" + test -n "$s_vless_user_security" && \ + json_add_string "security" "$s_vless_user_security" + test -n "$s_vless_user_encryption" && \ + json_add_string "encryption" "$s_vless_user_encryption" + test -n "$s_vless_user_level" && \ + json_add_int "level" "$s_vless_user_level" + json_close_object + json_close_array # users + + json_close_object + + json_close_array # vnext + json_close_object # settings + ;; + "trojan") + json_add_object "settings" + + json_add_array "servers" + json_add_object "" + + json_add_string "address" "$s_trojan_address" + append_server_address "$s_trojan_address" + + json_add_int "port" "$s_trojan_port" + + json_add_string "password" "$s_trojan_user_id" + + json_close_object + + json_close_array # trojan + json_close_object # settings + ;; + "socks") + json_add_object "settings" + + json_add_array "servers" + json_add_object "" + + json_add_string "address" "$s_socks_address" + append_server_address "$s_socks_address" + + json_add_int "port" "$s_socks_port" + + json_add_array "users" + json_add_object "" + json_add_string "pass" "$s_socks_user_id" + json_add_string "user" "$s_socks_email" + json_close_object + json_close_array # users + + json_close_object + + json_close_array # socks + json_close_object # settings + ;; + esac + + json_add_object "streamSettings" + test -n "$ss_network" && \ + json_add_string "network" "$ss_network" + + test -n "$ss_security" && \ + json_add_string "security" "$ss_security" + + if [ "x$ss_security" = "xtls" ] ; then + json_add_object "tlsSettings" + + test -n "$ss_tls_server_name" && \ + json_add_string "serverName" "$ss_tls_server_name" + + if [ -n "$ss_tls_alpn" ] ; then + json_add_array "alpn" + json_add_string "" "$ss_tls_alpn" + json_close_array + fi + + json_add_boolean "allowInsecure" "$ss_tls_allow_insecure" + json_add_boolean "allowInsecureCiphers" "$ss_tls_allow_insecure_ciphers" + json_add_boolean "disableSystemRoot" "$ss_tls_disable_system_root" + + json_add_array "certificates" + if [ -n "$ss_tls_cert_file" ] ; then + json_add_object "" + json_add_string "certificateFile" "$ss_tls_cert_file" + json_add_string "keyFile" "$ss_tls_key_file" + test -n "$ss_tls_cert_usage" && \ + json_add_string "usage" "$ss_tls_cert_usage" + json_close_object + fi + json_close_array # certificates + + json_close_object # tlsSettings + fi + + case "${ss_network:-x}" in + "tcp") + json_add_object "tcpSettings" + + if [ -n "$ss_tcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_tcp_header_type" + + if [ "$ss_tcp_header_type" = "http" ] ; then + json_add_object "request" + test -n "$ss_tcp_header_request_version" && \ + json_add_string "version" "$ss_tcp_header_request_version" + json_add_string "method" "$ss_tcp_header_request_method" + + if [ -n "$ss_tcp_header_request_path" ] ; then + json_add_array "path" + json_add_string "" "$ss_tcp_header_request_path" + json_close_array + fi + + if [ -n "$ss_tcp_header_request_headers" ] ; then + json_add_object "headers" + + handle_request_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_request_headers" handle_request_header + + json_close_object # headers + fi + + json_close_object # request + + json_add_object "response" + test -n "$ss_tcp_header_response_version" && \ + json_add_string "version" "$ss_tcp_header_response_version" + test -n "$ss_tcp_header_response_status" && \ + json_add_string "status" "$ss_tcp_header_response_status" + test -n "$ss_tcp_header_response_reason" && \ + json_add_string "reason" "$ss_tcp_header_response_reason" + + if [ -n "$ss_tcp_header_response_headers" ] ; then + json_add_object "headers" + + handle_response_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_response_headers" handle_response_header + + json_close_object # headers + fi + + json_close_object # response + fi + + json_close_object # header + fi + + json_close_object # tcpSettings + ;; + "kcp") + json_add_object "kcpSettings" + + test -n "$ss_kcp_mtu" && \ + json_add_int "mtu" "$ss_kcp_mtu" + test -n "$ss_kcp_tti" && \ + json_add_int "tti" "$ss_kcp_tti" + test -n "$ss_kcp_uplink_capacity" && \ + json_add_int "uplinkCapacity" "$ss_kcp_uplink_capacity" + test -n "$ss_kcp_downlink_capacity" && \ + json_add_int "downlinkCapacity" "$ss_kcp_downlink_capacity" + + json_add_boolean "congestion" "$ss_kcp_congestion" + + test -n "$ss_kcp_read_buffer_size" && \ + json_add_int "readBufferSize" "$ss_kcp_read_buffer_size" + test -n "$ss_kcp_write_buffer_size" && \ + json_add_int "writeBufferSize" "$ss_kcp_write_buffer_size" + + if [ -n "$ss_kcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_kcp_header_type" + json_close_object + fi + + json_close_object # kcpSettings + ;; + "ws") + json_add_object "wsSettings" + + test -n "$ss_websocket_path" && \ + json_add_string "path" "$ss_websocket_path" + + if [ -n "$ss_websocket_headers" ] ; then + json_add_object "headers" + + handle_websocket_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_string "$name" "$value" + fi + } + config_list_foreach "$section" "ss_websocket_headers" handle_websocket_header + + json_close_object # headers + fi + + json_close_object # wsSettings + ;; + "http") + json_add_object "httpSettings" + + if [ -n "$ss_http_host" ] ; then + json_add_array "host" + + local h + for h in $ss_http_host ; do + json_add_string "" "$h" + done + + json_close_array # host + fi + + test -n "$ss_http_path" && \ + json_add_string "path" "$ss_http_path" + + json_close_object # httpSettings + ;; + "domainsocket") + json_add_object "dsSettings" + + test -n "$ss_domainsocket_path" && \ + json_add_string "path" "$ss_domainsocket_path" + + json_close_object # dsSettings + ;; + "quic") + json_add_object "quicSettings" + + test -n "$ss_quic_security" && \ + json_add_string "security" "$ss_quic_security" + test -n "$ss_quic_key" && \ + json_add_string "key" "$ss_quic_key" + + if [ -n "$ss_quic_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_quic_header_type" + json_close_object # header + fi + + json_close_object # quicSettings + ;; + esac + + json_add_object "sockopt" + + if [ -n "$TRANSPARENT_PROXY_PORT" ] ; then + json_add_int "mark" "255" + else + test -n "$ss_sockopt_mark" && \ + json_add_int "mark" "$ss_sockopt_mark" + fi + + test -n "$ss_sockopt_tcp_fast_open" && \ + json_add_boolean "tcpFastOpen" "$ss_sockopt_tcp_fast_open" + if version_over_5_4; then + test -n "$ss_sockopt_mptcp" && \ + json_add_boolean "mptcp" "$ss_sockopt_mptcp" + fi + + json_close_object # sockopt + + json_close_object # streamSettings + + test -n "$tag" && \ + json_add_string "tag" "$tag" + + if [ -n "$proxy_settings_tag" ] ; then + json_add_object "proxySettings" + json_add_string "tag" "$proxy_settings_tag" + json_close_object # proxySettings + fi + + if [ "x$mux_enabled" = "x1" ] ; then + json_add_object "mux" + json_add_boolean "enabled" "1" + json_add_int "concurrency" "$mux_concurrency" + json_close_object # mux + fi + + json_close_object +} + +init_transparent_proxy() { + local tp_cfg="main_transparent_proxy" + local redirect_port use_tproxy redirect_udp redirect_dns + + config_get redirect_port "$tp_cfg" "redirect_port" + config_get_bool use_tproxy "$tp_cfg" "use_tproxy" "0" + config_get_bool redirect_udp "$tp_cfg" "redirect_udp" "0" + config_get_bool redirect_dns "$tp_cfg" "redirect_dns" "0" + + if [ -n "$redirect_port" ] && \ + ! validate_data "port" "$redirect_port" 2>/dev/null ; then + _err "Transparent proxy redirect port is invalid: $redirect_port" + return 1 + fi + + TRANSPARENT_PROXY_PORT="$redirect_port" + TRANSPARENT_PROXY_USE_TPROXY="$use_tproxy" + + if [ "x$redirect_udp" = "x1" ] && [ "$(uci -q get v2ray.omrout.protocol)" != "socks" ]; then + TRANSPARENT_PROXY_ADDITION="udp" + elif [ "x$redirect_dns" = "x1" ] ; then + TRANSPARENT_PROXY_ADDITION="dns" + else + TRANSPARENT_PROXY_ADDITION= + fi +} + +setup_transparent_proxy() { + if [ -z "$TRANSPARENT_PROXY_PORT" ] ; then + #_info "Transparent proxy disabled." + return 0 + fi + + if [ "x$TRANSPARENT_PROXY_EXPECTED" != "x1" ] ; then + #_info "No v2ray instance enabled, skip transparent proxy." + return 0 + fi + + _info "Setting transparent proxy on port: $TRANSPARENT_PROXY_PORT" + + local tp_cfg="main_transparent_proxy" + local lan_ifaces only_privileged_ports proxy_mode direct_list_dns proxy_list_dns + + config_get lan_ifaces "$tp_cfg" "lan_ifaces" + config_get_bool only_privileged_ports "$tp_cfg" "only_privileged_ports" "0" + config_get proxy_mode "$tp_cfg" "proxy_mode" + config_get direct_list_dns "$tp_cfg" "direct_list_dns" + config_get proxy_list_dns "$tp_cfg" "proxy_list_dns" + + _info "Transparent proxy mode: $proxy_mode" + + #init_rules_for_listfile "$direct_list_dns" "$proxy_list_dns" + + local ext_args + case "${proxy_mode:-default}" in + "cn_direct") + local chnroute="$(get_file_content "chnroute")" + local chnroute6="$(get_file_content "chnroute6")" + + if [ -n "$chnroute" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute" | sed "s/.*/add $IPSET_DST_DIRECT_V4 & timeout 0/") + EOF + fi + + if [ -n "$chnroute6" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute6" | sed "s/.*/add $IPSET_DST_DIRECT_V6 & timeout 0/") + EOF + fi + + ext_args= + ;; + "cn_proxy") + local chnroute="$(get_file_content "chnroute")" + local chnroute6="$(get_file_content "chnroute6")" + + if [ -n "$chnroute" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute" | sed "s/.*/add $IPSET_DST_PROXY_V4 & timeout 0/") + EOF + fi + + if [ -n "$chnroute6" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute6" | sed "s/.*/add $IPSET_DST_PROXY_V6 & timeout 0/") + EOF + fi + + ext_args="-m set --match-set $IPSET_DST_PROXY_V4 dst" + ;; + "gfwlist_proxy") + local gfwlist="$(get_file_content "gfwlist")" + + if [ -n "$gfwlist" ] ; then + if [ -n "$proxy_list_dns" ] ; then + echo "$gfwlist" | \ + sed "s|.*|server=/&/$proxy_list_dns\nipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >> "$FILE_V2RAY_DNSMASQ_CACHE" + else + echo "$gfwlist" | \ + sed "s|.*|ipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >> "$FILE_V2RAY_DNSMASQ_CACHE" + fi + fi + + ext_args="-m set --match-set $IPSET_DST_PROXY_V4 dst" + ;; + *) + ext_args= + ;; + esac + + if [ "x$only_privileged_ports" = "x1" ] ; then + ext_args="--dport 0:1023 $ext_args" + fi + + if [ -f $FILE_V2RAY_DNSMASQ_CACHE ] && [ -n "$(cat "$FILE_V2RAY_DNSMASQ_CACHE" | grep -v "^$" | grep -v "^#")" ] ; then + local dir="$(dirname "$FILE_V2RAY_DNSMASQ")" + test -d "$dir" || mkdir -p "$dir" + cat "$FILE_V2RAY_DNSMASQ_CACHE" >"$FILE_V2RAY_DNSMASQ" 2>/dev/null + DNSMASQ_RESTART_EXPECTED=1 + fi + + rm -f "$FILE_V2RAY_DNSMASQ_CACHE" + + local lan_devices lan_ipaddrs + + if [ -n "$lan_ifaces" ] ; then + . /lib/functions/network.sh + + local lan + for lan in $lan_ifaces ; do + local device ipaddrs ipaddr + network_get_device device "$lan" + network_get_ipaddrs ipaddrs "$lan" + + if [ -n "$device" ] ; then + if [ -n "$lan_devices" ] ; then + lan_devices="$lan_devices $device" + else + lan_devices="$device" + fi + fi + + if [ -n "$ipaddrs" ] ; then + for ipaddr in $ipaddrs ; do + if [ -n "$lan_ipaddrs" ] ; then + lan_ipaddrs="$ipaddr" + else + lan_ipaddrs="$lan_ipaddrs $ipaddr" + fi + done + fi + done + fi + + logger -t "v2ray" "add rules" + add_v2ray_redirect_rules "$ext_args" "$lan_devices" "$lan_ipaddrs" +} + +clear_transparent_proxy() { + if [ -f "${v2rrules_nft}" ] || [ -f "${v2rrules_nft}.down" ]; then + rm -f "$v2rrules_nft" + rm -f "${v2rrules_nft}.down" + fw4 restart + fi + + v2ray-rules -f + + if [ -s "$FILE_V2RAY_DNSMASQ" ] ; then + rm -f "$FILE_V2RAY_DNSMASQ" + DNSMASQ_RESTART_EXPECTED=1 + fi +} + +start_instance() { + local section="$1" + + if ! v2ray_section_validate "$section" ; then + _err "Invalid config." + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + #_info "Service disabled: $section" + return 0 + fi + + if [ -z "$v2ray_file" ] || [ ! -s "$v2ray_file" ] ; then + _err "Invalid V2Ray file." + return 1 + fi + + test -x "$v2ray_file" || chmod 755 "$v2ray_file" + + local temp_config + + if [ -n "$config_file" ] ; then + if [ ! -s "$config_file" ] ; then + _err "Config file not found: $config_file" + return 1 + fi + + if ! ( eval "$v2ray_file test -config \"$config_file\" >/dev/null 2>&1" ) ; then + _err "Validate config file failed: $config_file" + return 1 + fi + + local file_content="$(cat "$config_file")" + local config_commands="$(get_commands_from_json "$file_content")" + + local addr + + for addr in $(echo "$config_commands" | sed -n "s/^json.*'address'[[:space:]]'\([^']*\)'.*/\1/p") ; do + append_server_address "$addr" + done + + temp_config="$config_file" + else + test -d "$CONFIG_FOLDER" || mkdir -p "$CONFIG_FOLDER" + + temp_config="$CONFIG_FOLDER/v2ray.${section}.json" + + local old_ns + json_set_namespace "$section" old_ns + json_init + + json_add_object "log" + + test -n "$access_log" && \ + json_add_string "access" "$access_log" + + if [ -n "$loglevel" ] && [ "$loglevel" != "none" ] ; then + json_add_string "loglevel" "$loglevel" + json_add_string "error" "$error_log" + fi + + json_close_object # log + + if [ "x$stats_enabled" = "x1" ] ; then + json_add_object "stats" + json_close_object # stats + fi + + add_dns_settings "$section" + add_routing_settings "$section" + add_policy_settings "$section" + add_reverse_settings "$section" + + if [ "x$transport_enabled" = "x1" ] ; then + add_transport_settings + fi + + if [ -n "$inbounds" ] ; then + json_add_array "inbounds" + + local is + for is in $inbounds ; do + add_inbound_setting "$is" + done + + json_close_array # inbounds + fi + + if [ -n "$outbounds" ] ; then + json_add_array "outbounds" + + local os + for os in $outbounds ; do + add_outbound_setting "$os" + done + + json_close_array # outbounds + fi + + json_dump -i >"$temp_config" + + json_cleanup + json_set_namespace "$old_ns" + + if [ ! -s "$temp_config" ] ; then + _err "Error when create config file: $temp_config" + return 1 + fi + fi + + PROG="$NAME.$section" + + TRANSPARENT_PROXY_EXPECTED=1 + procd_open_instance "$PROG" + procd_set_param command "$v2ray_file" + procd_append_param command run + procd_append_param command -config "$temp_config" + procd_set_param respawn + + if [ -n "$asset_location" ] && [ -d "$asset_location" ] ; then + procd_set_param env V2RAY_LOCATION_ASSET="$asset_location" + fi + + # cat /proc/PID/limits to see if limits works + procd_set_param limits nofile="102400 102400" + procd_append_param limits core="0 0" + + if [ "$mem_percentage" -gt "0" ] ; then + local mem_total="$(awk '/MemTotal/ {print $2}' /proc/meminfo)" + if [ -n "$mem_total" ] ; then + local use_mem="$(expr $mem_total \* $mem_percentage \* 10)" + procd_append_param limits as="$use_mem $use_mem" + fi + fi + + procd_set_param file "$temp_config" + procd_set_param stderr 1 # forward stderr of the command to logd + procd_set_param stdout 1 + procd_set_param pidfile "/var/run/${NAME}.${section}.pid" + procd_close_instance +} + +rules_exist() { + #[ -n "$(iptables -w -t nat -L -n 2>/dev/null | grep v2r_)" ] && return 0 + if [ -f "$v2rrules_nft" ]; then + return 0 + else + return 1 + fi +} + +rules_up() { + if [ -f "${v2rrules_nft}.down" ]; then + mv -f "${v2rrules_nft}.down" "$v2rrules_nft" + fw4 restart + fi +} + +rules_down() { + if [ -f "${v2rrules_nft}" ]; then + mv -f "$v2rrules_nft" "${v2rrules_nft}.down" + fw4 restart + fi +} + +start_service() { + clear_transparent_proxy + + config_load "$NAME" + + if ! init_transparent_proxy ; then + gracefully_restart_dnsmasq + return 1 + fi + + config_foreach start_instance "v2ray" + + setup_transparent_proxy + gracefully_restart_dnsmasq + rules_up + + unset OUTBOUND_SERVERS_V4 \ + OUTBOUND_SERVERS_V6 \ + TRANSPARENT_PROXY_EXPECTED \ + TRANSPARENT_PROXY_PORT \ + TRANSPARENT_PROXY_ADDITION \ + DNSMASQ_RESTART_EXPECTED +} + +stop_service() { + if [ "x$action" = "xrestart" ] ; then + # skip when restarting, start_service will do this + return 0 + fi + + clear_transparent_proxy + rules_down + gracefully_restart_dnsmasq + test -d "$CONFIG_FOLDER" && rm -rf "$CONFIG_FOLDER" +} + +service_triggers() { + procd_add_reload_trigger "$NAME" +} diff --git a/v2ray-core/files/usr/share/v2ray-rules/chain.uc b/v2ray-core/files/usr/share/v2ray-rules/chain.uc new file mode 100644 index 000000000..c0855c674 --- /dev/null +++ b/v2ray-core/files/usr/share/v2ray-rules/chain.uc @@ -0,0 +1,126 @@ +{% +function get_local_verdict() { + let v = o_local_default; + if (v == "checkdst") { + return "goto v2r_rules_dst_" + proto; + } else if (v == "forward") { + return "goto v2r_rules_forward_" + proto; + } else { + return null; + } +} + +function get_src_default_verdict() { + let v = o_src_default; + if (v == "checkdst") { + return "goto v2r_rules_dst_" + proto; + } else if (v == "forward") { + return "goto v2r_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_dst_default_verdict() { + let v = o_dst_default; + if (v == "forward") { + return "goto v2r_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_ifnames() { + let res = []; + for (let ifname in split(o_ifnames, /[ \t\n]/)) { + ifname = trim(ifname); + if (ifname) push(res, ifname); + } + return res; +} + +let type, hook, priority, redir_port; +if (proto == "tcp") { + type = "nat"; + hook = "prerouting"; + priority = -1; + redir_port = o_redir_tcp_port; +} else if (proto == "udp") { + type = "filter"; + hook = "prerouting"; + priority = "mangle"; + redir_port = o_redir_udp_port; + if (system(" + set -o errexit + iprr() { + while ip $1 rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip $1 rule add fwmark 1 lookup 100 + ip $1 route flush table 100 2>/dev/null || true + ip $1 route add local default dev lo table 100 + } + iprr -4 + iprr -6 + ") != 0) { + return ; + } +} else { + return; +} + +%} +{% if (redir_port): %} + +chain v2r_rules_pre_{{ proto }} { + type {{ type }} hook {{ hook }} priority {{ priority }}; + meta l4proto {{ proto }}{%- let ifnames=get_ifnames(); if (length(ifnames)): %} iifname { {{join(", ", ifnames)}} }{% endif %} goto v2r_rules_pre_src_{{ proto }}; +} + +chain v2r_rules_pre_src_{{ proto }} { + ip daddr @v2r_rules_dst_bypass_ accept; + ip6 daddr @v2r_rules6_dst_bypass_ accept; + goto v2r_rules_src_{{ proto }}; +} + +chain v2r_rules_src_{{ proto }} { + ip saddr @v2r_rules_src_bypass accept; + ip saddr @v2r_rules_src_forward goto v2r_rules_forward_{{ proto }}; + ip saddr @v2r_rules_src_checkdst goto v2r_rules_dst_{{ proto }}; + ip6 saddr @v2r_rules6_src_bypass accept; + ip6 saddr @v2r_rules6_src_forward goto v2r_rules_forward_{{ proto }}; + ip6 saddr @v2r_rules6_src_checkdst goto v2r_rules_dst_{{ proto }}; + {{ get_src_default_verdict() }}; +} + +chain v2r_rules_dst_{{ proto }} { + ip daddr @v2r_rules_dst_bypass accept; + ip daddr @v2r_rules_remote_servers accept; + ip daddr @v2r_rules_dst_forward goto v2r_rules_forward_{{ proto }}; + ip6 daddr @v2r_rules6_dst_bypass accept; + ip6 daddr @v2r_rules6_remote_servers accept; + ip6 daddr @v2r_rules6_dst_forward goto v2r_rules_forward_{{ proto }}; + {{ get_dst_default_verdict() }}; +} + +{% if (proto == "tcp"): %} +chain v2r_rules_forward_{{ proto }} { + meta l4proto tcp {{ o_nft_tcp_extra }} redirect to :{{ redir_port }}; +} +{% let local_verdict = get_local_verdict(); if (local_verdict): %} +chain v2r_rules_local_out { + type {{ type }} hook output priority -1; + meta l4proto != tcp accept; + ip daddr @v2r_rules_remote_servers accept; + ip daddr @v2r_rules_dst_bypass_ accept; + ip daddr @v2r_rules_dst_bypass accept; + ip6 daddr @v2r_rules6_remote_servers accept; + ip6 daddr @v2r_rules6_dst_bypass_ accept; + ip6 daddr @v2r_rules6_dst_bypass accept; + {{ local_verdict }}; +} +{% endif %} +{% elif (proto == "udp"): %} +chain v2r_rules_forward_{{ proto }} { + meta l4proto udp {{ o_nft_udp_extra }} meta mark set 1 tproxy to :{{ redir_port }}; +} +{% endif %} +{% endif %} diff --git a/v2ray-core/files/usr/share/v2ray-rules/set.uc b/v2ray-core/files/usr/share/v2ray-rules/set.uc new file mode 100644 index 000000000..a686829a6 --- /dev/null +++ b/v2ray-core/files/usr/share/v2ray-rules/set.uc @@ -0,0 +1,117 @@ +{% +let fs = require("fs"); + +let o_dst_bypass4_ = " + 0.0.0.0/8 + 10.0.0.0/8 + 100.64.0.0/10 + 127.0.0.0/8 + 169.254.0.0/16 + 172.16.0.0/12 + 192.0.0.0/24 + 192.0.2.0/24 + 192.168.0.0/16 + 192.31.196.0/24 + 192.52.193.0/24 + 192.88.99.0/24 + 192.175.48.0/24 + 198.18.0.0/15 + 198.51.100.0/24 + 203.0.113.0/24 + 224.0.0.0/4 + 240.0.0.0/4 +"; +let o_dst_bypass6_ = " + ::1/128 + ::/128 + ::ffff:0:0/96 + 64:ff9b:1::/48 + 100::/64 + fe80::/10 + 2001::/23 + fc00::/7 +"; +let o_dst_bypass_ = o_dst_bypass4_ + " " + o_dst_bypass6_; + +let set_suffix = { + "src_bypass": { + str: o_src_bypass, + }, + "src_forward": { + str: o_src_forward, + }, + "src_checkdst": { + str: o_src_checkdst, + }, + "remote_servers": { + str: o_remote_servers + }, + "dst_bypass": { + str: o_dst_bypass, + file: o_dst_bypass_file, + }, + "dst_bypass_": { + str: o_dst_bypass_, + }, + "dst_forward": { + str: o_dst_forward, + file: o_dst_forward_file, + }, + "dst_forward_rrst_": {}, +}; + +function set_name(suf, af) { + if (af == 4) { + return "v2r_rules_"+suf; + } else { + return "v2r_rules6_"+suf; + } +} + +function set_elements_parse(res, str, af) { + for (let addr in split(str, /[ \t\n]/)) { + addr = trim(addr); + if (!addr) continue; + if (af == 4 && index(addr, ":") != -1) continue; + if (af == 6 && index(addr, ":") == -1) continue; + push(res, addr); + } +} + +function set_elements(suf, af) { + let obj = set_suffix[suf]; + let res = []; + let addr; + + let str = obj["str"]; + if (str) { + set_elements_parse(res, str, af); + } + + let file = obj["file"]; + if (file) { + let fd = fs.open(file); + if (fd) { + str = fd.read("all"); + set_elements_parse(res, str, af); + } + } + + return res; +} +%} + +{% for (let suf in set_suffix): for (let af in [4, 6]): %} +set {{ set_name(suf, af) }} { + type ipv{{af}}_addr; + flags interval; + auto-merge; +{% let elems = set_elements(suf, af); if (length(elems)): %} + elements = { +{% for (let i = 0; i < length(elems); i++): %} + {{ elems[i] }}{% if (i < length(elems) - 1): %},{% endif %}{% print("\n") %} +{% endfor %} + } +{% endif %} +} +{% endfor; endfor %} diff --git a/v2ray-core/files/usr/share/v2ray-rules/v2r-rules.uc b/v2ray-core/files/usr/share/v2ray-rules/v2r-rules.uc new file mode 100644 index 000000000..f3955b2ef --- /dev/null +++ b/v2ray-core/files/usr/share/v2ray-rules/v2r-rules.uc @@ -0,0 +1,8 @@ +{% + +include("set.uc"); +include("chain.uc", {proto: "tcp"}); +include("chain.uc", {proto: "udp"}); + +%} + From d4eb02e5862991393cd1016091b9ae26624e4017 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:41:04 +0100 Subject: [PATCH 1274/2059] Add nftables support to xray --- xray-core/Makefile | 50 +- xray-core/files/etc/init.d/xray-nft | 2360 +++++++++++++++++ xray-core/files/usr/share/xray-rules/chain.uc | 126 + xray-core/files/usr/share/xray-rules/set.uc | 117 + .../files/usr/share/xray-rules/xr-rules.uc | 8 + 5 files changed, 2650 insertions(+), 11 deletions(-) create mode 100755 xray-core/files/etc/init.d/xray-nft create mode 100644 xray-core/files/usr/share/xray-rules/chain.uc create mode 100644 xray-core/files/usr/share/xray-rules/set.uc create mode 100644 xray-core/files/usr/share/xray-rules/xr-rules.uc diff --git a/xray-core/Makefile b/xray-core/Makefile index 8952c64e7..23f6786c2 100644 --- a/xray-core/Makefile +++ b/xray-core/Makefile @@ -1,6 +1,6 @@ include $(TOPDIR)/rules.mk -PKG_NAME:=xray-core +PKG_NAME:=xray PKG_VERSION:=1.8.6 PKG_RELEASE:=1 @@ -19,7 +19,7 @@ GO_PKG:=github.com/XTLS/Xray-core include $(INCLUDE_DIR)/package.mk include $(TOPDIR)/feeds/openmptcprouter/golang/golang-package.mk -define Package/$(PKG_NAME) +define Package/$(PKG_NAME)/template SECTION:=Custom CATEGORY:=Extra packages TITLE:=Xray-core @@ -27,13 +27,35 @@ define Package/$(PKG_NAME) PROVIDES:=xray-core endef +define Package/$(PKG_NAME)-core + $(call Package/$(PKG_NAME)/template) +endef + +define Package/$(PKG_NAME)-config + $(call Package/$(PKG_NAME)/template) + TITLE+= (init script) +endef + +define Package/$(PKG_NAME)-config-nft + $(call Package/$(PKG_NAME)/template) + TITLE+= (init script with nft) +endef + define Package/$(PKG_NAME)/description Xray-core bare bones binary (compiled without cgo) endef +define Package/$(PKG_NAME)-config/description + Xray-core init script +endef + +define Package/$(PKG_NAME)-config-nft/description + Xray-core init script with nft support +endef + define Package/$(PKG_NAME)/config menu "Xray Configuration" - depends on PACKAGE_$(PKG_NAME) + depends on PACKAGE_$(PKG_NAME)-core config PACKAGE_XRAY_ENABLE_GOPROXY_IO bool "Use goproxy.io to speed up module fetching (recommended for some network situations)" @@ -50,19 +72,25 @@ endif MAKE_PATH:=$(GO_PKG_WORK_DIR_NAME)/build/src/$(GO_PKG) MAKE_VARS += $(GO_PKG_VARS) -#define Build/Patch -# $(CP) $(PKG_BUILD_DIR)/../Xray-core-$(PKG_VERSION)/* $(PKG_BUILD_DIR) -# $(Build/Patch/Default) -#endef - define Build/Compile cd $(PKG_BUILD_DIR); $(GO_PKG_VARS) $(USE_GOPROXY) CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o $(PKG_INSTALL_DIR)/bin/xray ./main; endef -define Package/$(PKG_NAME)/install +define Package/$(PKG_NAME)-core/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/bin/xray $(1)/usr/bin/xray - $(CP) ./files/* $(1)/ endef -$(eval $(call BuildPackage,$(PKG_NAME))) +define Package/$(PKG_NAME)-config/install + $(CP) ./files/* $(1)/ + rm -f $(1)/etc/init.d/xray-nft +endef + +define Package/$(PKG_NAME)-config-nft/install + $(CP) ./files/* $(1)/ + mv $(1)/etc/init.d/xray-nft $(1)/etc/init.d/xray +endef + +$(eval $(call BuildPackage,$(PKG_NAME)-core)) +$(eval $(call BuildPackage,$(PKG_NAME)-config)) +$(eval $(call BuildPackage,$(PKG_NAME)-config-nft)) diff --git a/xray-core/files/etc/init.d/xray-nft b/xray-core/files/etc/init.d/xray-nft new file mode 100755 index 000000000..1c0e85af3 --- /dev/null +++ b/xray-core/files/etc/init.d/xray-nft @@ -0,0 +1,2360 @@ +#!/bin/sh /etc/rc.common +# +# Copyright 2019-2020 Xingwang Liao +# Copyright 2020-2022 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# Licensed to the public under the MIT License. +# + +START=99 +USE_PROCD=1 +EXTRA_COMMANDS="rules_up rules_down rules_exist" + +NAME=xray +CONFIG_FOLDER=/var/etc/$NAME + +xrrules_uc="/usr/share/xray-rules/xr-rules.uc" +xrrules_nft="/etc/nftables.d/90-xr-rules.nft" + +FILE_XRAY_DNSMASQ=/tmp/dnsmasq.d/$NAME +FILE_XRAY_DNSMASQ_CACHE=/tmp/$NAME.dnsmasq.cache + +IPSET_SRC_IGNORE_V4=xray_src_ignore_v4 +IPSET_SRC_IGNORE_V6=xray_src_ignore_v6 +IPSET_DST_PROXY_V4=xray_dst_proxy_v4 +IPSET_DST_PROXY_V6=xray_dst_proxy_v6 +IPSET_SRC_DIRECT_V4=ss_rules_src_bypass +IPSET_DST_DIRECT_V4=ss_rules_dst_bypass +IPSET_DST_DIRECT_V6=ss_rules6_dst_bypass + +OUTBOUND_SERVERS= +OUTBOUND_SERVERS_V4= +OUTBOUND_SERVERS_V6= + +TRANSPARENT_PROXY_EXPECTED=0 +TRANSPARENT_PROXY_PORT= +TRANSPARENT_PROXY_USE_TPROXY= +TRANSPARENT_PROXY_ADDITION= + +DNSMASQ_RESTART_EXPECTED=0 + +. /usr/share/libubox/jshn.sh + +_log() { + local level="$1" ; shift + local msg="$@" + logger -p "daemon.$level" -t "$NAME" "$msg" + + echo "[$level] $msg" >&2 +} + +_info() { + _log "info" $@ +} + +_err() { + _log "err" $@ +} + +version_over_5_4() { + MAJOR_VERSION=$(uname -r | awk -F '.' '{print $1}') + MINOR_VERSION=$(uname -r | awk -F '.' '{print $2}') + if [ $MAJOR_VERSION -ge 5 ] && [ $MINOR_VERSION -gt 13 ] || [ $MAJOR_VERSION -gt 5 ] ; then + return 0 + else + return 1 + fi +} + + +get_value_from_json() { + local json="$1" + local key="$2" + + test -n "$json" || return + + local value="" + + local old_ns + json_set_namespace "json_key" old_ns + json_load "$json" + json_get_var "$key" value + json_cleanup + json_set_namespace "$old_ns" + + echo "$value" +} + +get_commands_from_json() { + local json="$1" + + test -n "$json" || return + + jshn -r "$json" 2>/dev/null | grep -v "json_init" +} + +get_file_content() { + local filename="$1" + + test -n "$filename" || return + test -r "/etc/xray/${filename}.txt" || return + + cat "/etc/xray/${filename}.txt" | grep -v "^$" | grep -v "^#" +} + +append_server_ipv4() { + local addr="$1" + + test -n "$addr" || return + + if [ -z "$OUTBOUND_SERVERS_V4" ] ; then + OUTBOUND_SERVERS_V4="$addr" + else + OUTBOUND_SERVERS_V4="$(cat >&1 <<-EOF + $OUTBOUND_SERVERS_V4 + $addr + EOF + )" + fi +} + +append_server_ipv6() { + local addr="$1" + + test -n "$addr" || return + + if [ -z "$OUTBOUND_SERVERS_V6" ] ; then + OUTBOUND_SERVERS_V6="$addr" + else + OUTBOUND_SERVERS_V6="$(cat >&1 <<-EOF + $OUTBOUND_SERVERS_V6 + $addr + EOF + )" + fi +} + +append_server_address() { + local addr="$1" + + test -n "$addr" || return + + local ipv4 + for ipv4 in $(resolveip -4 -t 5 "$addr") ; do + append_server_ipv4 "$ipv4" + OUTBOUND_SERVERS="$OUTBOUND_SERVERS $ipv4" + done + + local ipv6 + for ipv6 in $(resolveip -6 -t 5 "$addr") ; do + append_server_ipv6 "$ipv6" + OUTBOUND_SERVERS="$OUTBOUND_SERVERS $ipv6" + done +} + +xray_section_validate() { + uci_validate_section "$NAME" "xray" "$1" \ + 'enabled:bool:0' \ + 'xray_file:string' \ + 'asset_location:directory' \ + 'mem_percentage:and(uinteger, max(100)):80' \ + 'config_file:file' \ + 'loglevel:or("debug", "info", "warning", "error", "none")' \ + 'access_log:string' \ + 'error_log:string' \ + 'stats_enabled:bool:0' \ + 'transport_enabled:bool:0' \ + 'inbounds:list(uci("xray", "@inbound"))' \ + 'outbounds:list(uci("xray", "@outbound"))' +} + +dns_section_validate() { + uci_validate_section "$NAME" "dns" "$1" \ + 'enabled:bool:0' \ + 'tag:string' \ + 'client_ip:ipaddr' \ + 'hosts:list(string)' \ + 'servers:list(uci("xray", "@dns_server"))' +} + +dns_server_section_validate() { + uci_validate_section "$NAME" "dns_server" "$1" \ + 'address:string' \ + 'port:port' \ + 'domains:list(string)' \ + 'expect_ips:list(string)' +} + +routing_section_validate() { + uci_validate_section "$NAME" "routing" "$1" \ + 'enabled:bool:0' \ + 'domain_strategy:or("AsIs", "IPIfNonMatch", "IPOnDemand")' \ + 'rules:list(uci("xray", "@routing_rule"))' \ + 'balancers:list(uci("xray", "@routing_balancer"))' +} + +routing_rule_section_validate() { + uci_validate_section "$NAME" "routing_rule" "$1" \ + 'type:"field"' \ + 'domain:list(string)' \ + 'ip:list(string)' \ + 'port:or(port, portrange)' \ + 'network:list(or("tcp", "udp"))' \ + 'source:list(string)' \ + 'user:list(string)' \ + 'inbound_tag:list(string)' \ + 'protocol:list(or("http", "tls", "bittorrent"))' \ + 'attrs:string' \ + 'outbound_tag:string' \ + 'balancer_tag:string' +} + +routing_balancer_section_validate() { + uci_validate_section "$NAME" "routing_balancer" "$1" \ + 'tag:string' \ + 'selector:list(string)' +} + +policy_section_validate() { + uci_validate_section "$NAME" "policy" "$1" \ + 'enabled:bool:0' \ + 'levels:list(uci("xray", "@policy_level"))' \ + 'system_stats_inbound_uplink:bool:0' \ + 'system_stats_inbound_downlink:bool:0' +} + +policy_level_section_validate() { + uci_validate_section "$NAME" "policy_level" "$1" \ + 'level:uinteger' \ + 'handshake:uinteger:4' \ + 'conn_idle:uinteger:300' \ + 'uplink_only:uinteger:2' \ + 'downlink_only:uinteger:5' \ + 'stats_user_uplink:bool:0' \ + 'stats_user_downlink:bool:0' \ + 'buffer_size:uinteger' +} + +reverse_section_validate() { + uci_validate_section "$NAME" "reverse" "$1" \ + 'enabled:bool:0' \ + 'bridges:list(string)' \ + 'portals:list(string)' +} + +inbound_section_validate() { + uci_validate_section "$NAME" "inbound" "$1" \ + 'port:or(port, portrange, string)' \ + 'listen:ipaddr' \ + 'protocol:string' \ + 's_dokodemo_door_address:host' \ + 's_dokodemo_door_port:port' \ + 's_dokodemo_door_network:list(or("tcp", "udp"))' \ + 's_dokodemo_door_timeout:uinteger' \ + 's_dokodemo_door_follow_redirect:bool:0' \ + 's_dokodemo_door_user_level:uiterger' \ + 's_http_account_user:string' \ + 's_http_account_pass:string' \ + 's_http_allow_transparent:bool:0' \ + 's_http_timeout:uinteger' \ + 's_http_user_level:uinteger' \ + 's_mtproto_user_email:string' \ + 's_mtproto_user_secret:string' \ + 's_mtproto_user_level:uinteger' \ + 's_shadowsocks_email:string' \ + 's_shadowsocks_method:string' \ + 's_shadowsocks_password:string' \ + 's_shadowsocks_level:uinteger' \ + 's_shadowsocks_ota:bool:0' \ + 's_shadowsocks_network:list(or("tcp", "udp")):tcp' \ + 's_socks_auth:or("noauth", "password")' \ + 's_socks_account_user:string' \ + 's_socks_account_pass:string' \ + 's_socks_udp:bool:0' \ + 's_socks_ip:host' \ + 's_socks_user_level:uinteger' \ + 's_vmess_client_id:string' \ + 's_vmess_client_alter_id:and(uinteger, max(65535))' \ + 's_vmess_client_email:string' \ + 's_vmess_client_user_level:uinteger' \ + 's_vmess_default_alter_id:and(uinteger, max(65535))' \ + 's_vmess_default_user_level:uinteger' \ + 's_vmess_detour_to:string' \ + 's_vmess_disable_insecure_encryption:bool:0' \ + 's_vless_client_id:string' \ + 's_vless_client_alter_id:and(uinteger, max(65535))' \ + 's_vless_client_email:string' \ + 's_vless_client_user_level:uinteger' \ + 's_vless_default_alter_id:and(uinteger, max(65535))' \ + 's_vless_default_user_level:uinteger' \ + 's_vless_detour_to:string' \ + 's_vless_disable_insecure_encryption:bool:0' \ + 's_trojan_client_id:string' \ + 's_trojan_client_alter_id:and(uinteger, max(65535))' \ + 's_trojan_client_email:string' \ + 's_trojan_client_user_level:uinteger' \ + 's_trojan_default_alter_id:and(uinteger, max(65535))' \ + 's_trojan_default_user_level:uinteger' \ + 's_trojan_detour_to:string' \ + 's_trojan_disable_insecure_encryption:bool:0' \ + 's_socks_client_id:string' \ + 's_socks_client_email:string:"openmptcprouter"' \ + 'ss_network:or("tcp", "kcp", "ws", "http", "domainsocket", "quic")' \ + 'ss_security:or("none", "tls")' \ + 'ss_tls_server_name:host' \ + 'ss_tls_alpn:string' \ + 'ss_tls_allow_insecure:bool:0' \ + 'ss_tls_allow_insecure_ciphers:bool:0' \ + 'ss_tls_disable_system_root:bool:0' \ + 'ss_tls_cert_usage:or("encipherment", "verify", "issue")' \ + 'ss_tls_cert_file:string' \ + 'ss_tls_key_file:string' \ + 'ss_tcp_header_type:or("none", "http")' \ + 'ss_tcp_header_request_version:string' \ + 'ss_tcp_header_request_method:string:GET' \ + 'ss_tcp_header_request_path:string' \ + 'ss_tcp_header_request_headers:list(string)' \ + 'ss_tcp_header_response_version:string' \ + 'ss_tcp_header_response_status:string' \ + 'ss_tcp_header_response_reason:string' \ + 'ss_tcp_header_response_headers:list(string)' \ + 'ss_kcp_mtu:and(min(576), max(1460))' \ + 'ss_kcp_tti:and(min(10), max(100))' \ + 'ss_kcp_uplink_capacity:uinteger' \ + 'ss_kcp_downlink_capacity:uinteger' \ + 'ss_kcp_congestion:bool:0' \ + 'ss_kcp_read_buffer_size:uinteger' \ + 'ss_kcp_write_buffer_size:uinteger' \ + 'ss_kcp_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_websocket_path:string' \ + 'ss_websocket_headers:list(string)' \ + 'ss_http_host:list(host)' \ + 'ss_http_path:string' \ + 'ss_domainsocket_path:string' \ + 'ss_quic_security:or("aes-128-gcm", "chacha20-poly1305", "none")' \ + 'ss_quic_key:string' \ + 'ss_quic_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_sockopt_tcp_fast_open:or("0", "1")' \ + 'ss_sockopt_mptcp:or("0", "1")' \ + 'ss_sockopt_tproxy:or("redirect", "tproxy", "off")' \ + 'tag:string' \ + 'sniffing_enabled:bool:0' \ + 'sniffing_dest_override:list(or("http", "tls"))' \ + 'allocate_strategy:or("always", "random")' \ + 'allocate_refresh:uinteger' \ + 'allocate_concurrency:uinteger' +} + +outbound_section_validate() { + uci_validate_section "$NAME" "outbound" "$1" \ + 'send_through:ipaddr' \ + 'protocol:string' \ + 'tag:string' \ + 's_blackhole_reponse_type:or("none", "http")' \ + 's_dns_network:or("tcp", "udp")' \ + 's_dns_address:string' \ + 's_dns_port:port' \ + 's_freedom_domain_strategy:or("AsIs", "UseIP", "UseIPv4", "UseIPv6")' \ + 's_freedom_redirect:string' \ + 's_freedom_user_level:uinteger' \ + 's_http_server_address:host' \ + 's_http_server_port:port' \ + 's_http_account_user:string' \ + 's_http_account_pass:string' \ + 's_shadowsocks_email:string' \ + 's_shadowsocks_address:host' \ + 's_shadowsocks_port:port' \ + 's_shadowsocks_method:string' \ + 's_shadowsocks_password:string' \ + 's_shadowsocks_level:uinteger' \ + 's_shadowsocks_ota:bool:0' \ + 's_socks_server_address:host' \ + 's_socks_server_port:port' \ + 's_socks_account_user:string' \ + 's_socks_account_pass:string' \ + 's_socks_user_level:uinteger' \ + 's_vmess_address:host' \ + 's_vmess_port:port' \ + 's_vmess_user_id:string' \ + 's_vmess_user_alter_id:and(uinteger, max(65535))' \ + 's_vmess_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_vmess_user_level:uinteger' \ + 's_vless_address:host' \ + 's_vless_port:port' \ + 's_vless_user_id:string' \ + 's_vless_user_alter_id:and(uinteger, max(65535))' \ + 's_vless_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_vless_user_encryption:or("auto", "none")' \ + 's_vless_user_level:uinteger' \ + 's_vless_reality_address:host' \ + 's_vless_reality_port:port' \ + 's_vless_reality_user_id:string' \ + 's_vless_reality_user_alter_id:and(uinteger, max(65535))' \ + 's_vless_reality_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_vless_reality_user_encryption:or("auto", "none")' \ + 's_vless_reality_flow:string' \ + 's_vless_reality_public_key:string' \ + 's_vless_reality_user_level:uinteger' \ + 's_trojan_address:host' \ + 's_trojan_port:port' \ + 's_trojan_user_id:string' \ + 's_trojan_user_alter_id:and(uinteger, max(65535))' \ + 's_trojan_user_security:or("auto", "aes-128-gcm", "chacha20-poly1305", "none")' \ + 's_trojan_user_encryption:or("auto", "none")' \ + 's_trojan_user_level:uinteger' \ + 's_socks_address:host' \ + 's_socks_port:port' \ + 's_socks_user_id:string' \ + 's_socks_email:string:openmptcprouter' \ + 'ss_network:or("tcp", "kcp", "ws", "http", "domainsocket", "quic")' \ + 'ss_security:or("none", "tls")' \ + 'ss_tls_server_name:host' \ + 'ss_tls_alpn:string' \ + 'ss_tls_allow_insecure:bool:0' \ + 'ss_tls_allow_insecure_ciphers:bool:0' \ + 'ss_tls_disable_system_root:bool:0' \ + 'ss_tls_cert_usage:or("encipherment", "verify", "issue")' \ + 'ss_tls_cert_file:string' \ + 'ss_tls_key_file:string' \ + 'ss_tcp_header_type:or("none", "http")' \ + 'ss_tcp_header_request_version:string' \ + 'ss_tcp_header_request_method:string' \ + 'ss_tcp_header_request_path:string' \ + 'ss_tcp_header_request_headers:list(string)' \ + 'ss_tcp_header_response_version:string' \ + 'ss_tcp_header_response_status:string' \ + 'ss_tcp_header_response_reason:string' \ + 'ss_tcp_header_response_headers:list(string)' \ + 'ss_kcp_mtu:and(min(576), max(1460))' \ + 'ss_kcp_tti:and(min(10), max(100))' \ + 'ss_kcp_uplink_capacity:uinteger' \ + 'ss_kcp_downlink_capacity:uinteger' \ + 'ss_kcp_congestion:bool:0' \ + 'ss_kcp_read_buffer_size:uinteger' \ + 'ss_kcp_write_buffer_size:uinteger' \ + 'ss_kcp_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_websocket_path:string' \ + 'ss_websocket_headers:list(string)' \ + 'ss_http_host:list(host)' \ + 'ss_http_path:string' \ + 'ss_domainsocket_path:string' \ + 'ss_quic_security:or("aes-128-gcm", "chacha20-poly1305", "none")' \ + 'ss_quic_key:string' \ + 'ss_quic_header_type:or("none", "srtp", "utp", "wechat-video", "dtls", "wireguard")' \ + 'ss_sockopt_mark:uinteger' \ + 'ss_sockopt_tcp_fast_open:or("0", "1")' \ + 'ss_sockopt_mptcp:or("0", "1")' \ + 'stream_settings:string' \ + 'proxy_settings_tag:string' \ + 'mux_enabled:bool:0' \ + 'mux_concurrency:uinteger:8' +} + +add_xray_redirect_rules() { + local ext_args="$1" + local lan_devices="$2" + local lan_ipaddrs="$3" + + local port="$TRANSPARENT_PROXY_PORT" + local addition="$TRANSPARENT_PROXY_ADDITION" + local ipset_src_direct="$IPSET_SRC_DIRECT_V4" + local ipset_dst_direct="$IPSET_DST_DIRECT_V4" + + test -n "$port" || return + +# # This part need a rewrite +# xray-rules -f +# #logger -t "xray" "xray-rules -l ${port} -L ${port} -s $OUTBOUND_SERVERS_V4 --rule-name def --src-default forward --dst-default forward --local-default forward" +# commandline="-l ${port} -s $OUTBOUND_SERVERS_V4 --rule-name def --src-default forward --dst-default forward --local-default forward" +# [ "$(uci -q get xray.main_transparent_proxy.redirect_udp)" = "1" ] && [ "$(uci -q get xray.omrout.protocol)" != "socks" ] && commandline="$commandline -L ${port}" +# xray-rules $commandline +# [ "$(uci -q get xray.main.inbounds | grep omr6)" != "" ] && [ -n "$OUTBOUND_SERVERS_V6" ] && { +# xray-rules6 -f +# commandline="-l $((port+1)) -L $((port+1)) -s $OUTBOUND_SERVERS_V6 --rule-name def --src-default forward --dst-default forward --local-default forward" +# [ "$(uci -q get xray.main_transparent_proxy.redirect_udp)" = "1" ] && ([ "$(uci -q get xray.omrout.protocol)" = "vless-reality" ] || [ "$(uci -q get xray.omrout.protocol)" = "vless" ] || [ "$(uci -q get xray.omrout.protocol)" = "vmess" ]) && commandline="$commandline -L ${port+1}" +# xray-rules6 $commandline +# } + + remote_servers="$(echo $OUTBOUND_SERVERS \ + | tr ' ' '\n' \ + | sort -u \ + | xargs -n 1 resolveip \ + | sort -u)" + + [ "$(uci -q get xray.main_transparent_proxy.redirect_udp)" = "1" ] && [ "$(uci -q get xray.omrout.protocol)" != "socks" ] && portudp="$port" + + local tmp="/tmp/xrrules" + json_init + json_add_string o_remote_servers "$remote_servers" + json_add_int o_redir_tcp_port "$port" + json_add_int o_redir_udp_port "$portudp" + json_add_string o_ifnames "$ifnames" + json_add_string o_local_default "forward" + json_add_string o_src_bypass "$src_ips_bypass" + json_add_string o_src_forward "$src_ips_forward" + json_add_string o_src_checkdst "$src_ips_checkdst" + json_add_string o_src_default "checkdst" + json_add_string o_dst_bypass "$dst_ips_bypass" + json_add_string o_dst_forward "$dst_ips_forward" + json_add_string o_dst_bypass_file "$dst_ips_bypass_file" + json_add_string o_dst_forward_file "$dst_ips_forward_file" + json_add_string o_dst_default "forward" + json_add_string o_nft_tcp_extra "$nft_tcp_extra" + json_add_string o_nft_udp_extra "$nft_udp_extra" + json_dump -i >"$tmp.json" + + if utpl -S -F "$tmp.json" "$xrrules_uc" >"$tmp.nft" \ + && ! cmp -s "$tmp.nft" "$xrrules_nft"; then + echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk" + if nft -f "$tmp.nft.chk" -c; then + mv "$tmp.nft" "$xrrules_nft" + fw4 restart + fi + rm -f "$tmp.nft.chk" + fi + rm -f "$tmp.json" + rm -f "$tmp.nft" + + [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && { + logger -t "xray" "Reload omr-bypass rules" + /etc/init.d/omr-bypass reload_rules + } +} + +init_rules_for_listfile() { + local direct_list_dns="$1" + local proxy_list_dns="$2" + + echo "# AUTO-GENERATED FILE. DO NOT MODIFY." >"$FILE_XRAY_DNSMASQ_CACHE" + + # For direct list + local direct_content + direct_content="$(get_file_content "directlist")" + + if [ -n "$direct_content" ] ; then + echo "$direct_content" | \ + grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_DIRECT_V4 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + echo "$direct_content" | \ + grep -oE "([0-9a-fA-F]{0,4}:){1,7}([0-9a-fA-F]){0,4}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_DIRECT_V6 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + if [ -n "$direct_list_dns" ] ; then + echo "$direct_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|server=/&/$direct_list_dns\nipset=/&/$IPSET_DST_DIRECT_V4,$IPSET_DST_DIRECT_V6|" \ + >>"$FILE_XRAY_DNSMASQ_CACHE" + else + echo "$direct_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|ipset=/&/$IPSET_DST_DIRECT_V4,$IPSET_DST_DIRECT_V6|" \ + >>"$FILE_XRAY_DNSMASQ_CACHE" + fi + fi + + # For proxy list + local proxy_content + proxy_content="$(get_file_content "proxylist")" + + if [ -n "$proxy_content" ] ; then + echo "$proxy_content" | \ + grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_PROXY_V4 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + echo "$proxy_content" | \ + grep -oE "([0-9a-fA-F]{0,4}:){1,7}([0-9a-fA-F]){0,4}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_DST_PROXY_V6 & timeout 0/" | \ + ipset -! restore 2>/dev/null + + if [ -n "$proxy_list_dns" ] ; then + echo "$proxy_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|server=/&/$proxy_list_dns\nipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >>"$FILE_XRAY_DNSMASQ_CACHE" + else + echo "$proxy_content" | \ + grep -oE "([0-9a-zA-Z_-]+\.)+[a-zA-Z]{2,}$" | \ + sed "s|.*|ipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >>"$FILE_XRAY_DNSMASQ_CACHE" + fi + fi + + # For local devices outbound list + local src_content + src_content="$(get_file_content "srcdirectlist")" + + if [ -n "$src_content" ] ; then + echo "$src_content" | \ + grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}(/[0-9]{1,2})?" | \ + sed "s/.*/add $IPSET_SRC_DIRECT_V4 & timeout 0/" | \ + ipset -! restore 2>/dev/null + fi + +} + +gracefully_restart_dnsmasq() { + if [ "x$DNSMASQ_RESTART_EXPECTED" = "x1" ] && [ -x "/etc/init.d/dnsmasq" ] ; then + _info "Restarting dnsmasq..." + /etc/init.d/dnsmasq restart >/dev/null 2>&1 + DNSMASQ_RESTART_EXPECTED=0 + fi +} + +add_dns_settings() { + local section="${1}_dns" + + if ! dns_section_validate "$section" ; then + _err "Invalid DNS config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "DNS disabled: $section" + return 0 + fi + + json_add_object "dns" + + test -n "$tag" && \ + json_add_string "tag" "$tag" + test -n "$client_ip" && \ + json_add_string "clientIp" "$client_ip" + + if [ -n "$hosts" ] ; then + json_add_object "hosts" + + local h + for h in $hosts ; do + local domain="$(echo "$h" | cut -d'|' -f1)" + local ip="$(echo "$h" | cut -d'|' -f2)" + + if [ -n "$domain" ] && [ -n "$ip" ] ; then + json_add_string "$domain" "$ip" + fi + done + + json_close_object # hosts + fi + + if [ -n "$servers" ] ; then + json_add_array "servers" + + for ss in $servers ; do + if dns_server_section_validate "$ss" ; then + if [ -z "$address" ] ; then + continue + fi + + if [ -z "${port}${domains}${expect_ips}" ] ; then + json_add_string "" "$address" + else + json_add_object "" + json_add_string "address" "$address" + + if [ -n "$port" ] ; then + json_add_int "port" "$port" + else + json_add_int "port" "53" + fi + + if [ -n "$domains" ] ; then + json_add_array "domains" + + local d + for d in $domains ; do + json_add_string "" "$d" + done + + json_close_array # domains + fi + + if [ -n "$expect_ips" ] ; then + json_add_array "expectIPs" + + local e + for e in $expect_ips ; do + json_add_string "" "$e" + done + + json_close_array # expectIPs + fi + + json_close_object + fi + fi + done + + json_close_array # servers + fi + + json_close_object # dns +} + +add_routing_settings() { + local section="${1}_routing" + + if ! routing_section_validate "$section" ; then + _err "Invalid routing config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "Routing disabled: $section" + return 0 + fi + + json_add_object "routing" + + test -n "$domain_strategy" && \ + json_add_string "domainStrategy" "$domain_strategy" + + if [ -n "$rules" ] ; then + json_add_array "rules" + + local rs + for rs in $rules ; do + if routing_rule_section_validate "$rs" ; then + json_add_object "" + + json_add_string "type" "$type" + + if [ -n "$domain" ] ; then + json_add_array "domain" + + local d + for d in $domain ; do + json_add_string "" "$d" + done + + json_close_array # domain + fi + + if [ -n "$ip" ] ; then + json_add_array "ip" + + local i + for i in $ip ; do + json_add_string "" "$i" + done + + json_close_array # ip + fi + + if [ -n "$port" ] ; then + json_add_string "port" "$(echo "$port" | tr -s ' ' ',')" + fi + + if [ -n "$network" ] ; then + json_add_string "network" "$(echo "$network" | tr -s ' ' ',')" + fi + + if [ -n "$source" ] ; then + json_add_array "source" + + local s + for s in $source ; do + json_add_string "" "$s" + done + + json_close_array # source + fi + + if [ -n "$user" ] ; then + json_add_array "user" + + local u + for u in $user ; do + json_add_string "" "$u" + done + + json_close_array # user + fi + + if [ -n "$inbound_tag" ] ; then + json_add_array "inboundTag" + + local it + for it in $inbound_tag ; do + json_add_string "" "$it" + done + + json_close_array # inboundTag + fi + + if [ -n "$protocol" ] ; then + json_add_array "protocol" + local p + for p in $protocol ; do + json_add_string "" "$p" + done + json_close_array # protocol + fi + + test -n "$attrs" && \ + json_add_string "attrs" "$attrs" + test -n "$outbound_tag" && \ + json_add_string "outboundTag" "$outbound_tag" + test -n "$balancer_tag" && \ + json_add_string "balancerTag" "$balancer_tag" + + json_close_object + fi + done + + json_close_array # rules + fi + + if [ -n "$balancers" ] ; then + json_add_array "balancers" + + local bs + for bs in $balancers ; do + if routing_balancer_section_validate "$bs" ; then + json_add_object "" + json_add_string "tag" "$tag" + + json_add_array "selector" + + local s + for s in $selector ; do + json_add_string "" "$s" + done + + json_close_array # selector + json_close_object + fi + done + + json_close_array # balancers + fi + + json_close_object +} + +add_policy_settings() { + local section="${1}_policy" + + if ! policy_section_validate "$section" ; then + _err "Invalid policy config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "Policy disabled: $section" + return 0 + fi + + json_add_object "policy" + + if [ -n "$levels" ] ; then + json_add_object "levels" + + local l_s + for l_s in $levels ; do + if policy_level_section_validate "$l_s" ; then + json_add_object "$level" + json_add_int "handshake" "$handshake" + json_add_int "connIdle" "$conn_idle" + json_add_int "uplinkOnly" "$uplink_only" + json_add_int "downlinkOnly" "$downlink_only" + json_add_boolean "statsUserUplink" "$stats_user_uplink" + json_add_boolean "statsUserDownlink" "$stats_user_downlink" + test -n "$buffer_size" && \ + json_add_int "bufferSize" "$buffer_size" + json_close_object + fi + done + + json_close_object # levels + fi + + json_add_object "system" + json_add_boolean "statsInboundUplink" "$system_stats_inbound_uplink" + json_add_boolean "statsInboundDownlink" "$system_stats_inbound_downlink" + json_close_object # system + + json_close_object # policy +} + +add_reverse_settings() { + local section="${1}_reverse" + + if ! reverse_section_validate "$section" ; then + _err "Invalid reverse config: $section, skip" + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + _info "Reverse disabled: $section" + return 0 + fi + + json_add_object "reverse" + + if [ -n "$bridges" ] ; then + json_add_array "bridges" + + local b + for b in $bridges ; do + local tag="$(echo "$b" | cut -d'|' -f1)" + local domain="$(echo "$b" | cut -d'|' -f2)" + if [ -n "$tag" ] && [ -n "$domain" ] ; then + json_add_object "" + json_add_string "tag" "$tag" + json_add_string "domain" "$domain" + json_close_object + fi + done + + json_close_array # bridges + fi + + if [ -n "$portals" ] ; then + json_add_array "portals" + + local p + for p in $portals ; do + local tag="$(echo "$p" | cut -d'|' -f1)" + local domain="$(echo "$p" | cut -d'|' -f2)" + if [ -n "$tag" ] && [ -n "$domain" ] ; then + json_add_object "" + json_add_string "tag" "$tag" + json_add_string "domain" "$domain" + json_close_object + fi + done + + json_close_array # portals + fi + + json_close_object # reverse +} + +add_transport_settings() { + local json + json="$(get_file_content "transport")" + + if [ -z "$json" ] ; then + _err "Invalid transport config: $key" + return 1 + fi + + json_add_object "transport" + eval "$(get_commands_from_json "$json")" + json_close_object # transport +} + +add_inbound_setting() { + local section="$1" + + if ! inbound_section_validate "$section" ; then + _err "Invalid inbound section: $section" + return 1 + fi + + json_add_object "" + + test -n "$listen" && \ + json_add_string "listen" "$listen" + json_add_int "port" "$port" + json_add_string "protocol" "$protocol" + + case "${protocol:-x}" in + "dokodemo-door") + json_add_object "settings" + + if [ -n "$port" ] && [ "x$port" = "x$TRANSPARENT_PROXY_PORT" ] ; then + local settings_network="tcp" + + test -n "$TRANSPARENT_PROXY_ADDITION" && \ + settings_network="$settings_network,udp" + + json_add_boolean "followRedirect" "1" + json_add_string "network" "$settings_network" + else + test -n "$s_dokodemo_door_address" && \ + json_add_string "address" "$s_dokodemo_door_address" + + test -n "$s_dokodemo_door_port" && \ + json_add_int "port" "$s_dokodemo_door_port" + + test -n "$s_dokodemo_door_follow_redirect" && \ + json_add_boolean "followRedirect" "$s_dokodemo_door_follow_redirect" + + test -n "$s_dokodemo_door_network" && \ + json_add_string "network" "$(echo "$s_dokodemo_door_network" | tr -s ' ' ',')" + fi + + test -n "$s_dokodemo_door_timeout" && \ + json_add_int "timeout" "$s_dokodemo_door_timeout" + + test -n "$s_dokodemo_door_user_level" && \ + json_add_int "userLevel" "$s_dokodemo_door_user_level" + + json_close_object # settings + ;; + "http") + json_add_object "settings" + + if [ -n "$s_http_account_user" ] ; then + json_add_array "accounts" + + json_add_object "" + json_add_string "user" "$s_http_account_user" + json_add_string "pass" "$s_http_account_pass" + json_close_object + + json_close_array # accounts + fi + + json_add_boolean "allowTransparent" "$s_http_allow_transparent" + + test -n "$s_http_timeout" && \ + json_add_int "timeout" "$s_http_timeout" + test -n "$s_http_user_level" && \ + json_add_int "userLevel" "$s_http_user_level" + + json_close_object # settings + ;; + "mtproto") + json_add_object "settings" + + if [ -n "$s_mtproto_user_email" ] ; then + json_add_array "users" + json_add_object "" + + json_add_string "email" "$s_mtproto_user_email" + json_add_string "secret" "$s_mtproto_user_secret" + + test -n "$s_mtproto_user_level" && \ + json_add_int "level" "$s_mtproto_user_level" + + json_close_object + json_close_array # users + fi + + json_close_object # settings + ;; + "shadowsocks") + json_add_object "settings" + + json_add_string "method" "$s_shadowsocks_method" + json_add_string "password" "$s_shadowsocks_password" + + test -n "$s_shadowsocks_email" && \ + json_add_string "email" "$s_shadowsocks_email" + test -n "$s_shadowsocks_level" && \ + json_add_int "level" "$s_shadowsocks_level" + + json_add_boolean "ota" "$s_shadowsocks_ota" + json_add_string "network" "$(echo "$s_shadowsocks_network" | tr -s ' ' ',')" + + json_close_object # settings + ;; + "socks") + json_add_object "settings" + + json_add_string "auth" "$s_socks_auth" + + if [ -n "$s_socks_account_user" ] ; then + json_add_array "accounts" + json_add_object "" + json_add_string "user" "$s_socks_account_user" + json_add_string "pass" "$s_socks_account_pass" + json_close_object + json_close_array # accounts + fi + if [ -n "$s_socks_client_id" ] ; then + json_add_array "accounts" + json_add_object "" + json_add_string "user" "$s_socks_email" + json_add_string "pass" "$s_socks_client_id" + json_close_object + json_close_array # accounts + fi + + json_add_boolean "udp" "$s_socks_udp" + + test -n "$s_socks_ip" && \ + json_add_string "ip" "$s_socks_ip" + test -n "$s_socks_user_level" && \ + json_add_int "userLevel" "$s_socks_user_level" + + json_close_object # settings + ;; + "vmess") + json_add_object "settings" + + if [ -n "$s_vmess_client_id" ] ; then + json_add_array "clients" + json_add_object "" + + json_add_string "id" "$s_vmess_client_id" + + test -n "$s_vmess_client_alter_id" && \ + json_add_int "alterId" "$s_vmess_client_alter_id" + test -n "$s_vmess_client_email" && \ + json_add_string "email" "$s_vmess_client_email" + test -n "$s_vmess_client_user_level" && \ + json_add_int "level" "$s_vmess_client_user_level" + + json_close_object + json_close_array # clients + fi + + json_add_object "default" + + test -n "$s_vmess_default_alter_id" && \ + json_add_int "alterId" "$s_vmess_default_alter_id" + test -n "$s_vmess_default_user_level" && \ + json_add_int "level" "$s_vmess_default_user_level" + + json_close_object # default + + if [ -n "$s_vmess_detour_to" ] ; then + json_add_object "detour" + json_add_string "to" "$s_vmess_detour_to" + json_close_object # detour + fi + + json_add_boolean "disableInsecureEncryption" "$s_vmess_disable_insecure_encryption" + + json_close_object # settings + ;; + "vless") + json_add_object "settings" + + if [ -n "$s_vless_client_id" ] ; then + json_add_array "clients" + json_add_object "" + + json_add_string "id" "$s_vless_client_id" + + test -n "$s_vless_client_alter_id" && \ + json_add_int "alterId" "$s_vless_client_alter_id" + test -n "$s_vless_client_email" && \ + json_add_string "email" "$s_vless_client_email" + test -n "$s_vless_client_user_level" && \ + json_add_int "level" "$s_vless_client_user_level" + + json_close_object + json_close_array # clients + fi + + json_add_object "default" + + test -n "$s_vless_default_alter_id" && \ + json_add_int "alterId" "$s_vless_default_alter_id" + test -n "$s_vless_default_user_level" && \ + json_add_int "level" "$s_vless_default_user_level" + + json_close_object # default + + if [ -n "$s_vless_detour_to" ] ; then + json_add_object "detour" + json_add_string "to" "$s_vless_detour_to" + json_close_object # detour + fi + + json_add_boolean "disableInsecureEncryption" "$s_vless_disable_insecure_encryption" + + json_close_object # settings + ;; + "trojan") + json_add_object "settings" + + if [ -n "$s_trojan_client_id" ] ; then + json_add_array "clients" + json_add_object "" + + json_add_string "password" "$s_trojan_client_id" + + test -n "$s_trojan_client_alter_id" && \ + json_add_int "alterId" "$s_trojan_client_alter_id" + test -n "$s_trojan_client_email" && \ + json_add_string "email" "$s_trojan_client_email" + test -n "$s_trojan_client_user_level" && \ + json_add_int "level" "$s_trojan_client_user_level" + + json_close_object + json_close_array # clients + fi + + json_add_object "default" + + test -n "$s_trojan_default_alter_id" && \ + json_add_int "alterId" "$s_trojan_default_alter_id" + test -n "$s_trojan_default_user_level" && \ + json_add_int "level" "$s_trojan_default_user_level" + + json_close_object # default + + if [ -n "$s_trojan_detour_to" ] ; then + json_add_object "detour" + json_add_string "to" "$s_trojan_detour_to" + json_close_object # detour + fi + + json_add_boolean "disableInsecureEncryption" "$s_trojan_disable_insecure_encryption" + + json_close_object # settings + ;; + esac + + json_add_object "streamSettings" + + test -n "$ss_network" && \ + json_add_string "network" "$ss_network" + + test -n "$ss_security" && \ + json_add_string "security" "$ss_security" + + if [ "x$ss_security" = "xtls" ] && [ "x$protocol" != "xshadowsocks" ]; then + json_add_object "tlsSettings" + + test -n "$ss_tls_server_name" && \ + json_add_string "serverName" "$ss_tls_server_name" + + if [ -n "$ss_tls_alpn" ] ; then + json_add_array "alpn" + json_add_string "" "$ss_tls_alpn" + json_close_array # alpn + fi + + json_add_boolean "allowInsecure" "$ss_tls_allow_insecure" + json_add_boolean "allowInsecureCiphers" "$ss_tls_allow_insecure_ciphers" + json_add_boolean "disableSystemRoot" "$ss_tls_disable_system_root" + + json_add_array "certificates" + if [ -n "$ss_tls_cert_file" ] ; then + json_add_object "" + + json_add_string "certificateFile" "$ss_tls_cert_file" + json_add_string "keyFile" "$ss_tls_key_file" + test -n "$ss_tls_cert_usage" && \ + json_add_string "usage" "$ss_tls_cert_usage" + + json_close_object + fi + json_close_array # certificates + + json_close_object # tlsSettings + fi + + case "${ss_network:-x}" in + "tcp") + json_add_object "tcpSettings" + + if [ -n "$ss_tcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_tcp_header_type" + + if [ "$ss_tcp_header_type" = "http" ] ; then + json_add_object "request" + test -n "$ss_tcp_header_request_version" && \ + json_add_string "version" "$ss_tcp_header_request_version" + json_add_string "method" "$ss_tcp_header_request_method" + + if [ -n "$ss_tcp_header_request_path" ] ; then + json_add_array "path" + json_add_string "" "$ss_tcp_header_request_path" + json_close_array # path + fi + + if [ -n "$ss_tcp_header_request_headers" ] ; then + json_add_object "headers" + + handle_request_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_request_headers" handle_request_header + + json_close_object # headers + fi + + json_close_object # request + + json_add_object "response" + + test -n "$ss_tcp_header_response_version" && \ + json_add_string "version" "$ss_tcp_header_response_version" + test -n "$ss_tcp_header_response_status" && \ + json_add_string "status" "$ss_tcp_header_response_status" + test -n "$ss_tcp_header_response_reason" && \ + json_add_string "reason" "$ss_tcp_header_response_reason" + + if [ -n "$ss_tcp_header_response_headers" ] ; then + json_add_object "headers" + + handle_response_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_response_headers" handle_response_header + + json_close_object # headers + fi + + json_close_object # response + fi + json_close_object # header + fi + + json_close_object # tcpSettings + ;; + "kcp") + json_add_object "kcpSettings" + + test -n "$ss_kcp_mtu" && \ + json_add_int "mtu" "$ss_kcp_mtu" + test -n "$ss_kcp_tti" && \ + json_add_int "tti" "$ss_kcp_tti" + test -n "$ss_kcp_uplink_capacity" && \ + json_add_int "uplinkCapacity" "$ss_kcp_uplink_capacity" + test -n "$ss_kcp_downlink_capacity" && \ + json_add_int "downlinkCapacity" "$ss_kcp_downlink_capacity" + json_add_boolean "congestion" "$ss_kcp_congestion" + test -n "$ss_kcp_read_buffer_size" && \ + json_add_int "readBufferSize" "$ss_kcp_read_buffer_size" + test -n "$ss_kcp_write_buffer_size" && \ + json_add_int "writeBufferSize" "$ss_kcp_write_buffer_size" + + if [ -n "$ss_kcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_kcp_header_type" + json_close_object # header + fi + + json_close_object # kcpSettings + ;; + "ws") + json_add_object "wsSettings" + + test -n "$ss_websocket_path" && \ + json_add_string "path" "$ss_websocket_path" + + if [ -n "$ss_websocket_headers" ] ; then + json_add_object "headers" + + handle_websocket_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_string "$name" "$value" + fi + } + config_list_foreach "$section" "ss_websocket_headers" handle_websocket_header + + json_close_object # headers + fi + + json_close_object # wsSettings + ;; + "http") + json_add_object "httpSettings" + + if [ -n "$ss_http_host" ] ; then + json_add_array "host" + + local h + for h in $ss_http_host ; do + json_add_string "" "$h" + done + + json_close_array # host + fi + + test -n "$ss_http_path" && \ + json_add_string "path" "$ss_http_path" + + json_close_object # httpSettings + ;; + "domainsocket") + json_add_object "dsSettings" + + test -n "$ss_domainsocket_path" && \ + json_add_string "path" "$ss_domainsocket_path" + + json_close_object # dsSettings + ;; + "quic") + json_add_object "quicSettings" + + test -n "$ss_quic_security" && \ + json_add_string "security" "$ss_quic_security" + test -n "$ss_quic_key" && \ + json_add_string "key" "$ss_quic_key" + + if [ -n "$ss_quic_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_quic_header_type" + json_close_object # header + fi + + json_close_object # quicSettings + ;; + esac + + json_add_object "sockopt" + +# if [ -n "$port" ] && [ "x$port" = "x$TRANSPARENT_PROXY_PORT" ] ; then +# if [ "x$TRANSPARENT_PROXY_USE_TPROXY" = "x1" ] ; then +# json_add_string "tproxy" "tproxy" +# else +# json_add_string "tproxy" "redirect" +# fi +# else + test -n "$ss_sockopt_tcp_fast_open" && \ + json_add_boolean "tcpFastOpen" "$ss_sockopt_tcp_fast_open" + if version_over_5_4; then + test -n "$ss_sockopt_mptcp" && \ + json_add_boolean "tcpMptcp" "$ss_sockopt_mptcp" + fi + test -n "$ss_sockopt_tproxy" && \ + json_add_string "tproxy" "$ss_sockopt_tproxy" +# fi + + json_close_object # sockopt + + json_close_object # streamSettings + + test -n "$tag" && \ + json_add_string "tag" "$tag" + + json_add_object "sniffing" + + json_add_boolean "enabled" "$sniffing_enabled" + + if [ -n "$sniffing_dest_override" ] ; then + json_add_array "destOverride" + local d + for d in $sniffing_dest_override ; do + json_add_string "" "$d" + done + json_close_array # destOverride + fi + + json_close_object # sniffing + + if [ -n "$allocate_strategy" ] ; then + json_add_object "allocate" + json_add_string "strategy" "$allocate_strategy" + test -n "$allocate_refresh" && \ + json_add_int "refresh" "$allocate_refresh" + test -n "$allocate_concurrency" && \ + json_add_int "concurrency" "$allocate_concurrency" + json_close_object # allocate + fi + + json_close_object +} + +add_outbound_setting() { + local section="$1" + + if ! outbound_section_validate "$section" ; then + _err "Invalid outbound section: $section" + return 1 + fi + + json_add_object "" + + test -n "$send_through" && \ + json_add_string "sendThrough" "$send_through" + if [ "$protocol" = "vless-reality" ]; then + json_add_string "protocol" "vless" + else + json_add_string "protocol" "$protocol" + fi + + case "${protocol:-x}" in + "blackhole") + json_add_object "settings" + + if [ -n "$s_blackhole_reponse_type" ] ; then + json_add_object "response" + json_add_string "type" "$s_blackhole_reponse_type" + json_close_object # response + fi + + json_close_object # settings + ;; + "dns") + json_add_object "settings" + + test -n "$s_dns_network" && \ + json_add_string "network" "$s_dns_network" + + if [ -n "$s_dns_address" ] ; then + json_add_string "address" "$s_dns_address" + append_server_address "$s_dns_address" + fi + + test -n "$s_dns_port" && \ + json_add_int "port" "$s_dns_port" + + json_close_object # settings + ;; + "freedom") + json_add_object "settings" + + test -n "$s_freedom_domain_strategy" && \ + json_add_string "domainStrategy" "$s_freedom_domain_strategy" + test -n "$s_freedom_redirect" && \ + json_add_string "redirect" "$s_freedom_redirect" + test -n "$s_freedom_user_level" && \ + json_add_int "userLevel" "$s_freedom_user_level" + + json_close_object # settings + ;; + "http") + json_add_object "settings" + json_add_array "servers" + + json_add_object "" + + json_add_string "address" "$s_http_server_address" + append_server_address "$s_http_server_address" + + test -n "$s_http_server_port" && \ + json_add_int "port" "$s_http_server_port" + + if [ -n "$s_http_account_user" ] ; then + json_add_array "users" + json_add_object "" + + json_add_string "user" "$s_http_account_user" + json_add_string "pass" "$s_http_account_pass" + + json_close_object + json_close_array # users + fi + json_close_object + + json_close_array # servers + json_close_object # settings + ;; + "mtproto") + json_add_object "settings" + json_close_object + ;; + "shadowsocks") + json_add_object "settings" + json_add_array "servers" + + json_add_object "" + test -n "$s_shadowsocks_email" && \ + json_add_string "email" "$s_shadowsocks_email" + json_add_string "address" "$s_shadowsocks_address" + append_server_address "$s_shadowsocks_address" + + json_add_int "port" "$s_shadowsocks_port" + json_add_string "method" "$s_shadowsocks_method" + json_add_string "password" "$s_shadowsocks_password" + + test -n "$s_shadowsocks_level" && \ + json_add_int "level" "$s_shadowsocks_level" + json_add_boolean "ota" "$s_shadowsocks_ota" + json_close_object + + json_close_array # servers + json_close_object # settings + ;; + "vmess") + json_add_object "settings" + + json_add_array "vnext" + json_add_object "" + + json_add_string "address" "$s_vmess_address" + append_server_address "$s_vmess_address" + + json_add_int "port" "$s_vmess_port" + + json_add_array "users" + json_add_object "" + json_add_string "id" "$s_vmess_user_id" + json_add_int "alterId" "$s_vmess_user_alter_id" + test -n "$s_vmess_user_security" && \ + json_add_string "security" "$s_vmess_user_security" + test -n "$s_vmess_user_level" && \ + json_add_int "level" "$s_vmess_user_level" + json_close_object + json_close_array # users + + json_close_object + + json_close_array # vnext + json_close_object # settings + ;; + "vless") + json_add_object "settings" + + json_add_array "vnext" + json_add_object "" + + json_add_string "address" "$s_vless_address" + append_server_address "$s_vless_address" + + json_add_int "port" "$s_vless_port" + + json_add_array "users" + json_add_object "" + json_add_string "id" "$s_vless_user_id" + json_add_int "alterId" "$s_vless_user_alter_id" + test -n "$s_vless_user_security" && \ + json_add_string "security" "$s_vless_user_security" + test -n "$s_vless_user_encryption" && \ + json_add_string "encryption" "$s_vless_user_encryption" + test -n "$s_vless_user_level" && \ + json_add_int "level" "$s_vless_user_level" + json_close_object + json_close_array # users + + json_close_object + + json_close_array # vnext + json_close_object # settings + ;; + "vless-reality") + json_add_object "settings" + + json_add_array "vnext" + json_add_object "" + + json_add_string "address" "$s_vless_reality_address" + append_server_address "$s_vless_reality_address" + + json_add_int "port" "$s_vless_reality_port" + + json_add_array "users" + json_add_object "" + json_add_string "id" "$s_vless_reality_user_id" + json_add_int "alterId" "$s_vless_reality_user_alter_id" + test -n "$s_vless_reality_user_security" && \ + json_add_string "security" "$s_vless_reality_user_security" + test -n "$s_vless_reality_user_encryption" && \ + json_add_string "encryption" "$s_vless_reality_user_encryption" + test -n "$s_vless_reality_user_level" && \ + json_add_int "level" "$s_vless_reality_user_level" + test -n "$s_vless_reality_flow" && \ + json_add_string "flow" "$s_vless_reality_flow" + json_close_object + json_close_array # users + + json_close_object + + json_close_array # vnext + json_close_object # settings + ;; + "trojan") + json_add_object "settings" + + json_add_array "servers" + json_add_object "" + + json_add_string "address" "$s_trojan_address" + append_server_address "$s_trojan_address" + + json_add_int "port" "$s_trojan_port" + + json_add_string "password" "$s_trojan_user_id" + + json_close_object + + json_close_array # trojan + json_close_object # settings + ;; + "socks") + json_add_object "settings" + + json_add_array "servers" + json_add_object "" + + json_add_string "address" "$s_socks_address" + append_server_address "$s_socks_address" + + json_add_int "port" "$s_socks_port" + + json_add_array "users" + json_add_object "" + json_add_string "pass" "$s_socks_user_id" + json_add_string "user" "$s_socks_email" + json_close_object + json_close_array # users + + json_close_object + + json_close_array # socks + json_close_object # settings + ;; + esac + + json_add_object "streamSettings" + test -n "$ss_network" && \ + json_add_string "network" "$ss_network" + + if [ "x$protocol" != "xshadowsocks" ]; then + test -n "$ss_security" && \ + json_add_string "security" "$ss_security" + + if [ "x$ss_security" = "xtls" ]; then + json_add_object "tlsSettings" + + test -n "$ss_tls_server_name" && \ + json_add_string "serverName" "$ss_tls_server_name" + + if [ -n "$ss_tls_alpn" ] ; then + json_add_array "alpn" + json_add_string "" "$ss_tls_alpn" + json_close_array + fi + + json_add_boolean "allowInsecure" "$ss_tls_allow_insecure" + json_add_boolean "allowInsecureCiphers" "$ss_tls_allow_insecure_ciphers" + json_add_boolean "disableSystemRoot" "$ss_tls_disable_system_root" + + json_add_array "certificates" + if [ -n "$ss_tls_cert_file" ] ; then + json_add_object "" + json_add_string "certificateFile" "$ss_tls_cert_file" + json_add_string "keyFile" "$ss_tls_key_file" + test -n "$ss_tls_cert_usage" && \ + json_add_string "usage" "$ss_tls_cert_usage" + json_close_object + fi + json_close_array # certificates + + json_close_object # tlsSettings + fi + fi + if [ "x$protocol" = "xvless-reality" ]; then + json_add_string "security" "reality" + json_add_object "realitySettings" + json_add_string "fingerprint" "chrome" + json_add_string "serverName" "" + json_add_string "publicKey" "$s_vless_reality_public_key" + json_add_string "spiderX" "" + json_add_string "shortId" "" + json_close_object + fi + + case "${ss_network:-x}" in + "tcp") + json_add_object "tcpSettings" + + if [ -n "$ss_tcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_tcp_header_type" + + if [ "$ss_tcp_header_type" = "http" ] ; then + json_add_object "request" + test -n "$ss_tcp_header_request_version" && \ + json_add_string "version" "$ss_tcp_header_request_version" + json_add_string "method" "$ss_tcp_header_request_method" + + if [ -n "$ss_tcp_header_request_path" ] ; then + json_add_array "path" + json_add_string "" "$ss_tcp_header_request_path" + json_close_array + fi + + if [ -n "$ss_tcp_header_request_headers" ] ; then + json_add_object "headers" + + handle_request_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_request_headers" handle_request_header + + json_close_object # headers + fi + + json_close_object # request + + json_add_object "response" + test -n "$ss_tcp_header_response_version" && \ + json_add_string "version" "$ss_tcp_header_response_version" + test -n "$ss_tcp_header_response_status" && \ + json_add_string "status" "$ss_tcp_header_response_status" + test -n "$ss_tcp_header_response_reason" && \ + json_add_string "reason" "$ss_tcp_header_response_reason" + + if [ -n "$ss_tcp_header_response_headers" ] ; then + json_add_object "headers" + + handle_response_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_array "$name" + json_add_string "" "$value" + json_close_array + fi + } + config_list_foreach "$section" "ss_tcp_header_response_headers" handle_response_header + + json_close_object # headers + fi + + json_close_object # response + fi + + json_close_object # header + fi + + json_close_object # tcpSettings + ;; + "kcp") + json_add_object "kcpSettings" + + test -n "$ss_kcp_mtu" && \ + json_add_int "mtu" "$ss_kcp_mtu" + test -n "$ss_kcp_tti" && \ + json_add_int "tti" "$ss_kcp_tti" + test -n "$ss_kcp_uplink_capacity" && \ + json_add_int "uplinkCapacity" "$ss_kcp_uplink_capacity" + test -n "$ss_kcp_downlink_capacity" && \ + json_add_int "downlinkCapacity" "$ss_kcp_downlink_capacity" + + json_add_boolean "congestion" "$ss_kcp_congestion" + + test -n "$ss_kcp_read_buffer_size" && \ + json_add_int "readBufferSize" "$ss_kcp_read_buffer_size" + test -n "$ss_kcp_write_buffer_size" && \ + json_add_int "writeBufferSize" "$ss_kcp_write_buffer_size" + + if [ -n "$ss_kcp_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_kcp_header_type" + json_close_object + fi + + json_close_object # kcpSettings + ;; + "ws") + json_add_object "wsSettings" + + test -n "$ss_websocket_path" && \ + json_add_string "path" "$ss_websocket_path" + + if [ -n "$ss_websocket_headers" ] ; then + json_add_object "headers" + + handle_websocket_header() { + local h="$1" + + local name="$(echo "$h" | cut -d'=' -f1)" + local value="$(echo "$h" | cut -d'=' -f2)" + + if [ -n "$name" ] && [ -n "$value" ] ; then + json_add_string "$name" "$value" + fi + } + config_list_foreach "$section" "ss_websocket_headers" handle_websocket_header + + json_close_object # headers + fi + + json_close_object # wsSettings + ;; + "http") + json_add_object "httpSettings" + + if [ -n "$ss_http_host" ] ; then + json_add_array "host" + + local h + for h in $ss_http_host ; do + json_add_string "" "$h" + done + + json_close_array # host + fi + + test -n "$ss_http_path" && \ + json_add_string "path" "$ss_http_path" + + json_close_object # httpSettings + ;; + "domainsocket") + json_add_object "dsSettings" + + test -n "$ss_domainsocket_path" && \ + json_add_string "path" "$ss_domainsocket_path" + + json_close_object # dsSettings + ;; + "quic") + json_add_object "quicSettings" + + test -n "$ss_quic_security" && \ + json_add_string "security" "$ss_quic_security" + test -n "$ss_quic_key" && \ + json_add_string "key" "$ss_quic_key" + + if [ -n "$ss_quic_header_type" ] ; then + json_add_object "header" + json_add_string "type" "$ss_quic_header_type" + json_close_object # header + fi + + json_close_object # quicSettings + ;; + esac + + json_add_object "sockopt" + + if [ -n "$TRANSPARENT_PROXY_PORT" ] ; then + json_add_int "mark" "255" + else + test -n "$ss_sockopt_mark" && \ + json_add_int "mark" "$ss_sockopt_mark" + fi + + test -n "$ss_sockopt_tcp_fast_open" && \ + json_add_boolean "tcpFastOpen" "$ss_sockopt_tcp_fast_open" + if version_over_5_4; then + test -n "$ss_sockopt_mptcp" && \ + json_add_boolean "tcpMptcp" "$ss_sockopt_mptcp" + fi + + json_close_object # sockopt + + json_close_object # streamSettings + + test -n "$tag" && \ + json_add_string "tag" "$tag" + + if [ -n "$proxy_settings_tag" ] ; then + json_add_object "proxySettings" + json_add_string "tag" "$proxy_settings_tag" + json_close_object # proxySettings + fi + + if [ "x$mux_enabled" = "x1" ] ; then + json_add_object "mux" + json_add_boolean "enabled" "1" + json_add_int "concurrency" "$mux_concurrency" + json_close_object # mux + fi + + json_close_object +} + +init_transparent_proxy() { + local tp_cfg="main_transparent_proxy" + local redirect_port use_tproxy redirect_udp redirect_dns + + config_get redirect_port "$tp_cfg" "redirect_port" + config_get_bool use_tproxy "$tp_cfg" "use_tproxy" "0" + config_get_bool redirect_udp "$tp_cfg" "redirect_udp" "0" + config_get_bool redirect_dns "$tp_cfg" "redirect_dns" "0" + + if [ -n "$redirect_port" ] && \ + ! validate_data "port" "$redirect_port" 2>/dev/null ; then + _err "Transparent proxy redirect port is invalid: $redirect_port" + return 1 + fi + + TRANSPARENT_PROXY_PORT="$redirect_port" + TRANSPARENT_PROXY_USE_TPROXY="$use_tproxy" + + if [ "x$redirect_udp" = "x1" ] && [ "$(uci -q get xray.omrout.protocol)" != "socks" ]; then + TRANSPARENT_PROXY_ADDITION="udp" + elif [ "x$redirect_dns" = "x1" ] ; then + TRANSPARENT_PROXY_ADDITION="dns" + else + TRANSPARENT_PROXY_ADDITION= + fi +} + +setup_transparent_proxy() { + if [ -z "$TRANSPARENT_PROXY_PORT" ] ; then + #_info "Transparent proxy disabled." + return 0 + fi + + if [ "x$TRANSPARENT_PROXY_EXPECTED" != "x1" ] ; then + #_info "No xray instance enabled, skip transparent proxy." + return 0 + fi + + _info "Setting transparent proxy on port: $TRANSPARENT_PROXY_PORT" + + local tp_cfg="main_transparent_proxy" + local lan_ifaces only_privileged_ports proxy_mode direct_list_dns proxy_list_dns + + config_get lan_ifaces "$tp_cfg" "lan_ifaces" + config_get_bool only_privileged_ports "$tp_cfg" "only_privileged_ports" "0" + config_get proxy_mode "$tp_cfg" "proxy_mode" + config_get direct_list_dns "$tp_cfg" "direct_list_dns" + config_get proxy_list_dns "$tp_cfg" "proxy_list_dns" + + _info "Transparent proxy mode: $proxy_mode" + + #init_rules_for_listfile "$direct_list_dns" "$proxy_list_dns" + + local ext_args + case "${proxy_mode:-default}" in + "cn_direct") + local chnroute="$(get_file_content "chnroute")" + local chnroute6="$(get_file_content "chnroute6")" + + if [ -n "$chnroute" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute" | sed "s/.*/add $IPSET_DST_DIRECT_V4 & timeout 0/") + EOF + fi + + if [ -n "$chnroute6" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute6" | sed "s/.*/add $IPSET_DST_DIRECT_V6 & timeout 0/") + EOF + fi + + ext_args= + ;; + "cn_proxy") + local chnroute="$(get_file_content "chnroute")" + local chnroute6="$(get_file_content "chnroute6")" + + if [ -n "$chnroute" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute" | sed "s/.*/add $IPSET_DST_PROXY_V4 & timeout 0/") + EOF + fi + + if [ -n "$chnroute6" ] ; then + ipset -! restore <<-EOF 2>/dev/null + $(echo "$chnroute6" | sed "s/.*/add $IPSET_DST_PROXY_V6 & timeout 0/") + EOF + fi + + ext_args="-m set --match-set $IPSET_DST_PROXY_V4 dst" + ;; + "gfwlist_proxy") + local gfwlist="$(get_file_content "gfwlist")" + + if [ -n "$gfwlist" ] ; then + if [ -n "$proxy_list_dns" ] ; then + echo "$gfwlist" | \ + sed "s|.*|server=/&/$proxy_list_dns\nipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >> "$FILE_XRAY_DNSMASQ_CACHE" + else + echo "$gfwlist" | \ + sed "s|.*|ipset=/&/$IPSET_DST_PROXY_V4,$IPSET_DST_PROXY_V6|" \ + >> "$FILE_XRAY_DNSMASQ_CACHE" + fi + fi + + ext_args="-m set --match-set $IPSET_DST_PROXY_V4 dst" + ;; + *) + ext_args= + ;; + esac + + if [ "x$only_privileged_ports" = "x1" ] ; then + ext_args="--dport 0:1023 $ext_args" + fi + + if [ -f $FILE_XRAY_DNSMASQ_CACHE ] && [ -n "$(cat "$FILE_XRAY_DNSMASQ_CACHE" | grep -v "^$" | grep -v "^#")" ] ; then + local dir="$(dirname "$FILE_XRAY_DNSMASQ")" + test -d "$dir" || mkdir -p "$dir" + cat "$FILE_XRAY_DNSMASQ_CACHE" >"$FILE_XRAY_DNSMASQ" 2>/dev/null + DNSMASQ_RESTART_EXPECTED=1 + fi + + rm -f "$FILE_XRAY_DNSMASQ_CACHE" + + local lan_devices lan_ipaddrs + + if [ -n "$lan_ifaces" ] ; then + . /lib/functions/network.sh + + local lan + for lan in $lan_ifaces ; do + local device ipaddrs ipaddr + network_get_device device "$lan" + network_get_ipaddrs ipaddrs "$lan" + + if [ -n "$device" ] ; then + if [ -n "$lan_devices" ] ; then + lan_devices="$lan_devices $device" + else + lan_devices="$device" + fi + fi + + if [ -n "$ipaddrs" ] ; then + for ipaddr in $ipaddrs ; do + if [ -n "$lan_ipaddrs" ] ; then + lan_ipaddrs="$ipaddr" + else + lan_ipaddrs="$lan_ipaddrs $ipaddr" + fi + done + fi + done + fi + + logger -t "xray" "add rules" + add_xray_redirect_rules "$ext_args" "$lan_devices" "$lan_ipaddrs" +} + +clear_transparent_proxy() { + if [ -f "${xrrules_nft}" ] || [ -f "${xrrules_nft}.down" ]; then + rm -f "$xrrules_nft" + rm -f "$xrrules_nft.down" + fw4 restart + fi + + + if [ -s "$FILE_XRAY_DNSMASQ" ] ; then + rm -f "$FILE_XRAY_DNSMASQ" + DNSMASQ_RESTART_EXPECTED=1 + fi +} + +start_instance() { + local section="$1" + + if ! xray_section_validate "$section" ; then + _err "Invalid config." + return 1 + fi + + if [ "x$enabled" != "x1" ] ; then + #_info "Service disabled: $section" + return 0 + fi + + if [ -z "$xray_file" ] || [ ! -s "$xray_file" ] ; then + _err "Invalid xRay file." + return 1 + fi + + test -x "$xray_file" || chmod 755 "$xray_file" + + local temp_config + + if [ -n "$config_file" ] ; then + if [ ! -s "$config_file" ] ; then + _err "Config file not found: $config_file" + return 1 + fi + + if ! ( eval "$xray_file test -config \"$config_file\" >/dev/null 2>&1" ) ; then + _err "Validate config file failed: $config_file" + return 1 + fi + + local file_content="$(cat "$config_file")" + local config_commands="$(get_commands_from_json "$file_content")" + + local addr + + for addr in $(echo "$config_commands" | sed -n "s/^json.*'address'[[:space:]]'\([^']*\)'.*/\1/p") ; do + append_server_address "$addr" + done + + temp_config="$config_file" + else + test -d "$CONFIG_FOLDER" || mkdir -p "$CONFIG_FOLDER" + + temp_config="$CONFIG_FOLDER/xray.${section}.json" + + local old_ns + json_set_namespace "$section" old_ns + json_init + + json_add_object "log" + + test -n "$access_log" && \ + json_add_string "access" "$access_log" + + if [ -n "$loglevel" ] && [ "$loglevel" != "none" ] ; then + json_add_string "loglevel" "$loglevel" + json_add_string "error" "$error_log" + fi + + json_close_object # log + + if [ "x$stats_enabled" = "x1" ] ; then + json_add_object "stats" + json_close_object # stats + fi + + add_dns_settings "$section" + add_routing_settings "$section" + add_policy_settings "$section" + add_reverse_settings "$section" + + if [ "x$transport_enabled" = "x1" ] ; then + add_transport_settings + fi + + if [ -n "$inbounds" ] ; then + json_add_array "inbounds" + + local is + for is in $inbounds ; do + add_inbound_setting "$is" + done + + json_close_array # inbounds + fi + + if [ -n "$outbounds" ] ; then + json_add_array "outbounds" + + local os + for os in $outbounds ; do + add_outbound_setting "$os" + done + + json_close_array # outbounds + fi + + json_dump -i >"$temp_config" + + json_cleanup + json_set_namespace "$old_ns" + + if [ ! -s "$temp_config" ] ; then + _err "Error when create config file: $temp_config" + return 1 + fi + fi + + PROG="$NAME.$section" + + TRANSPARENT_PROXY_EXPECTED=1 + procd_open_instance "$PROG" + procd_set_param command "$xray_file" + procd_append_param command run + procd_append_param command -config "$temp_config" + procd_set_param respawn + + if [ -n "$asset_location" ] && [ -d "$asset_location" ] ; then + procd_set_param env XRAY_LOCATION_ASSET="$asset_location" + fi + + # cat /proc/PID/limits to see if limits works + procd_set_param limits nofile="102400 102400" + procd_append_param limits core="0 0" + + if [ "$mem_percentage" -gt "0" ] ; then + local mem_total="$(awk '/MemTotal/ {print $2}' /proc/meminfo)" + if [ -n "$mem_total" ] ; then + local use_mem="$(expr $mem_total \* $mem_percentage \* 10)" + procd_append_param limits as="$use_mem $use_mem" + fi + fi + + procd_set_param file "$temp_config" + procd_set_param stderr 1 # forward stderr of the command to logd + procd_set_param stdout 1 + procd_set_param pidfile "/var/run/${NAME}.${section}.pid" + procd_close_instance +} + +rules_exist() { + #[ -n "$(iptables -w -t nat -L -n 2>/dev/null | grep xr_)" ] && return 0 + if [ -f "$xrrules_nft" ]; then + return 0 + else + return 1 + fi +} + +rules_up() { + if [ -f "${xrrules_nft}.down" ]; then + mv -f "${xrrules_nft}.down" "$xrrules_nft" + fw4 restart + fi +} + +rules_down() { + if [ -f "${xrrules_nft}" ]; then + mv -f "$xrrules_nft" "${xrrules_nft}.down" + fw4 restart + fi +} + + +start_service() { + clear_transparent_proxy + + config_load "$NAME" + + if ! init_transparent_proxy ; then + gracefully_restart_dnsmasq + return 1 + fi + + config_foreach start_instance "xray" + + setup_transparent_proxy + gracefully_restart_dnsmasq + rules_up + + unset OUTBOUND_SERVERS_V4 \ + OUTBOUND_SERVERS_V6 \ + TRANSPARENT_PROXY_EXPECTED \ + TRANSPARENT_PROXY_PORT \ + TRANSPARENT_PROXY_ADDITION \ + DNSMASQ_RESTART_EXPECTED +} + +stop_service() { + if [ "x$action" = "xrestart" ] ; then + # skip when restarting, start_service will do this + return 0 + fi + + clear_transparent_proxy + rules_down + gracefully_restart_dnsmasq + test -d "$CONFIG_FOLDER" && rm -rf "$CONFIG_FOLDER" +} + +service_triggers() { + procd_add_reload_trigger "$NAME" +} diff --git a/xray-core/files/usr/share/xray-rules/chain.uc b/xray-core/files/usr/share/xray-rules/chain.uc new file mode 100644 index 000000000..cb46ba5e8 --- /dev/null +++ b/xray-core/files/usr/share/xray-rules/chain.uc @@ -0,0 +1,126 @@ +{% +function get_local_verdict() { + let v = o_local_default; + if (v == "checkdst") { + return "goto xr_rules_dst_" + proto; + } else if (v == "forward") { + return "goto xr_rules_forward_" + proto; + } else { + return null; + } +} + +function get_src_default_verdict() { + let v = o_src_default; + if (v == "checkdst") { + return "goto xr_rules_dst_" + proto; + } else if (v == "forward") { + return "goto xr_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_dst_default_verdict() { + let v = o_dst_default; + if (v == "forward") { + return "goto xr_rules_forward_" + proto; + } else { + return "accept"; + } +} + +function get_ifnames() { + let res = []; + for (let ifname in split(o_ifnames, /[ \t\n]/)) { + ifname = trim(ifname); + if (ifname) push(res, ifname); + } + return res; +} + +let type, hook, priority, redir_port; +if (proto == "tcp") { + type = "nat"; + hook = "prerouting"; + priority = -1; + redir_port = o_redir_tcp_port; +} else if (proto == "udp") { + type = "filter"; + hook = "prerouting"; + priority = "mangle"; + redir_port = o_redir_udp_port; + if (system(" + set -o errexit + iprr() { + while ip $1 rule del fwmark 1 lookup 100 2>/dev/null; do true; done + ip $1 rule add fwmark 1 lookup 100 + ip $1 route flush table 100 2>/dev/null || true + ip $1 route add local default dev lo table 100 + } + iprr -4 + iprr -6 + ") != 0) { + return ; + } +} else { + return; +} + +%} +{% if (redir_port): %} + +chain xr_rules_pre_{{ proto }} { + type {{ type }} hook {{ hook }} priority {{ priority }}; + meta l4proto {{ proto }}{%- let ifnames=get_ifnames(); if (length(ifnames)): %} iifname { {{join(", ", ifnames)}} }{% endif %} goto xr_rules_pre_src_{{ proto }}; +} + +chain xr_rules_pre_src_{{ proto }} { + ip daddr @xr_rules_dst_bypass_ accept; + ip6 daddr @xr_rules6_dst_bypass_ accept; + goto xr_rules_src_{{ proto }}; +} + +chain xr_rules_src_{{ proto }} { + ip saddr @xr_rules_src_bypass accept; + ip saddr @xr_rules_src_forward goto xr_rules_forward_{{ proto }}; + ip saddr @xr_rules_src_checkdst goto xr_rules_dst_{{ proto }}; + ip6 saddr @xr_rules6_src_bypass accept; + ip6 saddr @xr_rules6_src_forward goto xr_rules_forward_{{ proto }}; + ip6 saddr @xr_rules6_src_checkdst goto xr_rules_dst_{{ proto }}; + {{ get_src_default_verdict() }}; +} + +chain xr_rules_dst_{{ proto }} { + ip daddr @xr_rules_dst_bypass accept; + ip daddr @xr_rules_remote_servers accept; + ip daddr @xr_rules_dst_forward goto xr_rules_forward_{{ proto }}; + ip6 daddr @xr_rules6_dst_bypass accept; + ip6 daddr @xr_rules6_remote_servers accept; + ip6 daddr @xr_rules6_dst_forward goto xr_rules_forward_{{ proto }}; + {{ get_dst_default_verdict() }}; +} + +{% if (proto == "tcp"): %} +chain xr_rules_forward_{{ proto }} { + meta l4proto tcp {{ o_nft_tcp_extra }} redirect to :{{ redir_port }}; +} +{% let local_verdict = get_local_verdict(); if (local_verdict): %} +chain xr_rules_local_out { + type {{ type }} hook output priority -1; + meta l4proto != tcp accept; + ip daddr @xr_rules_remote_servers accept; + ip daddr @xr_rules_dst_bypass_ accept; + ip daddr @xr_rules_dst_bypass accept; + ip6 daddr @xr_rules6_remote_servers accept; + ip6 daddr @xr_rules6_dst_bypass_ accept; + ip6 daddr @xr_rules6_dst_bypass accept; + {{ local_verdict }}; +} +{% endif %} +{% elif (proto == "udp"): %} +chain xr_rules_forward_{{ proto }} { + meta l4proto udp {{ o_nft_udp_extra }} meta mark set 1 tproxy to :{{ redir_port }}; +} +{% endif %} +{% endif %} diff --git a/xray-core/files/usr/share/xray-rules/set.uc b/xray-core/files/usr/share/xray-rules/set.uc new file mode 100644 index 000000000..7e36d3d88 --- /dev/null +++ b/xray-core/files/usr/share/xray-rules/set.uc @@ -0,0 +1,117 @@ +{% +let fs = require("fs"); + +let o_dst_bypass4_ = " + 0.0.0.0/8 + 10.0.0.0/8 + 100.64.0.0/10 + 127.0.0.0/8 + 169.254.0.0/16 + 172.16.0.0/12 + 192.0.0.0/24 + 192.0.2.0/24 + 192.168.0.0/16 + 192.31.196.0/24 + 192.52.193.0/24 + 192.88.99.0/24 + 192.175.48.0/24 + 198.18.0.0/15 + 198.51.100.0/24 + 203.0.113.0/24 + 224.0.0.0/4 + 240.0.0.0/4 +"; +let o_dst_bypass6_ = " + ::1/128 + ::/128 + ::ffff:0:0/96 + 64:ff9b:1::/48 + 100::/64 + fe80::/10 + 2001::/23 + fc00::/7 +"; +let o_dst_bypass_ = o_dst_bypass4_ + " " + o_dst_bypass6_; + +let set_suffix = { + "src_bypass": { + str: o_src_bypass, + }, + "src_forward": { + str: o_src_forward, + }, + "src_checkdst": { + str: o_src_checkdst, + }, + "remote_servers": { + str: o_remote_servers + }, + "dst_bypass": { + str: o_dst_bypass, + file: o_dst_bypass_file, + }, + "dst_bypass_": { + str: o_dst_bypass_, + }, + "dst_forward": { + str: o_dst_forward, + file: o_dst_forward_file, + }, + "dst_forward_rrst_": {}, +}; + +function set_name(suf, af) { + if (af == 4) { + return "xr_rules_"+suf; + } else { + return "xr_rules6_"+suf; + } +} + +function set_elements_parse(res, str, af) { + for (let addr in split(str, /[ \t\n]/)) { + addr = trim(addr); + if (!addr) continue; + if (af == 4 && index(addr, ":") != -1) continue; + if (af == 6 && index(addr, ":") == -1) continue; + push(res, addr); + } +} + +function set_elements(suf, af) { + let obj = set_suffix[suf]; + let res = []; + let addr; + + let str = obj["str"]; + if (str) { + set_elements_parse(res, str, af); + } + + let file = obj["file"]; + if (file) { + let fd = fs.open(file); + if (fd) { + str = fd.read("all"); + set_elements_parse(res, str, af); + } + } + + return res; +} +%} + +{% for (let suf in set_suffix): for (let af in [4, 6]): %} +set {{ set_name(suf, af) }} { + type ipv{{af}}_addr; + flags interval; + auto-merge; +{% let elems = set_elements(suf, af); if (length(elems)): %} + elements = { +{% for (let i = 0; i < length(elems); i++): %} + {{ elems[i] }}{% if (i < length(elems) - 1): %},{% endif %}{% print("\n") %} +{% endfor %} + } +{% endif %} +} +{% endfor; endfor %} diff --git a/xray-core/files/usr/share/xray-rules/xr-rules.uc b/xray-core/files/usr/share/xray-rules/xr-rules.uc new file mode 100644 index 000000000..f3955b2ef --- /dev/null +++ b/xray-core/files/usr/share/xray-rules/xr-rules.uc @@ -0,0 +1,8 @@ +{% + +include("set.uc"); +include("chain.uc", {proto: "tcp"}); +include("chain.uc", {proto: "udp"}); + +%} + From d1724fd915322b6e64e0720947124ed00c7ceb41 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:09:06 +0100 Subject: [PATCH 1275/2059] Do not display VPN in omr-bypass interface --- .../htdocs/luci-static/resources/view/services/omr-bypass.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js index 62cbc973e..5cdcaf7d9 100644 --- a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js +++ b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js @@ -49,6 +49,7 @@ return L.view.extend({ o.rmempty = false; o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); + o.modalonly = true o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used.')); o.noaliases = true; @@ -82,6 +83,7 @@ return L.view.extend({ o.rmempty = false; o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); + o.modalonly = true o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used.')); o.noaliases = true; @@ -206,7 +208,7 @@ return L.view.extend({ o.rmempty = false; o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); - + o.modalonly = true o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used.')); o.noaliases = true; @@ -266,6 +268,7 @@ return L.view.extend({ }; o = s.option(form.Flag, 'vpn', _('VPN on server'),_('Bypass using VPN configured on server.')); + o.modalonly = true o = s.option(widgets.DeviceSelect, 'interface', _('Interface'),_('When none selected, MPTCP master interface is used (or an other interface if master is down).')); o.noaliases = true; From 127415b542b924a27acea6246de59197138c3c37 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:09:39 +0100 Subject: [PATCH 1276/2059] Fix clean on omr-bypass nft --- omr-bypass/files/etc/init.d/omr-bypass-nft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index 3bb187e8c..d8d9d312d 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -768,7 +768,7 @@ _delete_dhcp_ipset() { } _delete_firewall_rules() { - [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + ([ -n "$(echo $1 | grep omr_dst_bypass)" ] || [ -n "$(echo $1 | grep omr6_dst_bypass)" ]) && { uci -q delete firewall.$1 } } From 2feffb2c1e604ad381d962ad8d06aff3d996c083 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:10:09 +0100 Subject: [PATCH 1277/2059] Various fix in OMR-DSCP --- omr-dscp/files/etc/init.d/omr-dscp-nft | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/omr-dscp/files/etc/init.d/omr-dscp-nft b/omr-dscp/files/etc/init.d/omr-dscp-nft index 689136171..69081ac7e 100755 --- a/omr-dscp/files/etc/init.d/omr-dscp-nft +++ b/omr-dscp/files/etc/init.d/omr-dscp-nft @@ -36,20 +36,24 @@ _add_dscp_domains_rules() { add_list dhcp.omr_dscp_${class}.name="omr_dscp_${class}_4" add_list dhcp.omr_dscp_${class}.name="omr_dscp_${class}_6" commit dhcp + EOF + uci batch <<-EOF set firewall.omr_dscp_${class}_4=ipset set firewall.omr_dscp_${class}_4.name="omr_dscp_${class}_4" - set firewall.omr_dscp_${class}_4.match='dest_ip" + set firewall.omr_dscp_${class}_4.match='dest_ip' set firewall.omr_dscp_${class}_6=ipset set firewall.omr_dscp_${class}_6.name="omr_dscp_${class}_6" - set firewall.omr_dscp_${class}_6.match='dest_ip" + set firewall.omr_dscp_${class}_6.match='dest_ip' + EOF + uci -q batch <<-EOF set firewall.omr_dscp_${class}=rule - set firewall.omr_dscp_${class}.ipset="omr_dscp-${class}_4" + set firewall.omr_dscp_${class}.ipset="omr_dscp_${class}_4" set firewall.omr_dscp_${class}.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" set firewall.omr_dscp_${class}.target='DSCP' set firewall.omr_dscp_${class}.src='lan' set firewall.omr_dscp_${class}.dest='*' set firewall.omr6_dscp_${class}=rule - set firewall.omr6_dscp_${class}.ipset="omr_dscp-${class}_6" + set firewall.omr6_dscp_${class}.ipset="omr_dscp_${class}_6" set firewall.omr6_dscp_${class}.target='DSCP' set firewall.omr6_dscp_${class}.set_dscp="$(echo ${class} | tr '[a-z'] '[A-Z]')" set firewall.omr6_dscp_${class}.src='lan' @@ -129,7 +133,7 @@ _remove_ipset_dnsmasq() { } _remove_rules() { - [ -n "$(echo $1 | grep omr_dscp)" ] && uci -q delete firewall.$1 + ([ -n "$(echo $1 | grep omr_dscp)" ] || [ -n "$(echo $1 | grep omr6_dscp)" ]) && uci -q delete firewall.$1 } _setup_tunnel() { From 79380e9c837975032c8eabc371535c8aa4c92f60 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:10:53 +0100 Subject: [PATCH 1278/2059] Fix and add automatic LAN as ifname source for proxy --- omr-schedule/files/bin/omr-schedule | 2 ++ .../usr/share/omr/schedule.d/010-services | 23 +++++++++++++++---- .../files/usr/share/omr/schedule.d/030-bypass | 14 +++++++---- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/omr-schedule/files/bin/omr-schedule b/omr-schedule/files/bin/omr-schedule index 5d319b6f7..846c92703 100755 --- a/omr-schedule/files/bin/omr-schedule +++ b/omr-schedule/files/bin/omr-schedule @@ -1,4 +1,6 @@ #!/bin/sh +. /lib/functions.sh +. /lib/functions/network.sh for schedule_bin in /usr/share/omr/schedule.d/*; do [ -x "$schedule_bin" ] && ( diff --git a/omr-schedule/files/usr/share/omr/schedule.d/010-services b/omr-schedule/files/usr/share/omr/schedule.d/010-services index 49282f329..d1cb77c22 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/010-services +++ b/omr-schedule/files/usr/share/omr/schedule.d/010-services @@ -137,19 +137,34 @@ restart_omrtracker() { sleep 10 } +set_lan_ips() { + config_get ip4table "$1" ip4table + config_get device "$1" device + config_get proto "$1" proto + if [ "$ip4table" = "lan" ] && [ -n "$device" ] && ([ "$proto" = "dhcp" ] || [ "$proto" = "static" ]); then + [ -z "$(uci -q get shadowsocks-libev.ss_rules.ifnames | grep $device)" ] && { + uci -q add_list shadowsocks-libev.ss_rules.ifnames="$device" + uci -q add_list shadowsocks-rust.ss_rules.ifnames="$device" + } + elif [ -n "$device" ] && [ -n "$(uci -q get shadowsocks-libev.ss_rules.ifnames | grep $device)" ]; then + uci -q del_list shadowsocks-libev.ss_rules.ifnames="$device" + uci -q del_list shadowsocks-rust.ss_rules.ifnames="$device" + fi +} config_load network config_foreach restart_omrtracker interface - -mutlipath_fix() { +config_foreach set_lan_ips interface +uci -q commit shadowsocks-libev.ss_rules +uci -q commit shadowsocks-rust.ss_rules +multipath_fix() { config_get multipath "$1" multipath [ "$multipath" != "off" ] && return interface="$(ifstatus $1 | jsonfilter -q -e '@.l3_device' | tr -d '\n')" - [ -n "$interface"] && [ -z "$(multipath $interface | grep deactivated)" ] && /etc/init.d/mptcp reload $interface 2>&1 >/dev/null + [ -n "$interface" ] && [ -z "$(multipath $interface | grep deactivated)" ] && /etc/init.d/mptcp reload $interface 2>&1 >/dev/null } config_load network config_foreach multipath_fix interface - if [ -f /etc/init.d/shadowsocks-libev ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.key)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "" ] && [ "$(uci -q get shadowsocks-libev.sss0.server)" != "192.18.1.3" ] && [ "$(pgrep -f omr-tracker-ss)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-ss for Shadowsocks libev, restart omr-tracker..." /etc/init.d/omr-tracker restart 2>&1 >/dev/null diff --git a/omr-schedule/files/usr/share/omr/schedule.d/030-bypass b/omr-schedule/files/usr/share/omr/schedule.d/030-bypass index 19ff52437..67b86e1c2 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/030-bypass +++ b/omr-schedule/files/usr/share/omr/schedule.d/030-bypass @@ -1,9 +1,15 @@ #!/bin/sh -bypassipvs4s=$(ipset -o save list omr_dst_bypass_srv_vpn1_4) -[ -z "$bypassipvs4s" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') -bypassipvs6s=$(ipset -o save list omr_dst_bypass_srv_vpn1_6) -[ -z "$bypassipvs6s" ] && bypassipv6s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') +bypassipvs4s=$(ipset -o save list omr_dst_bypass_vpn1_4 2>/dev/null) +[ -z "$bypassipvs4s" ] && { + ipv4set=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_4" 2>/dev/null) + [ -n "$ipv4set" ] && bypassipv4s=$(echo "$ipv4set" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') +} +bypassipvs6s=$(ipset -o save list omr_dst_bypass_vpn1_6 2>/dev/null) +[ -z "$bypassipvs6s" ] && { + ipv6set=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_6" 2>/dev/null) + [ -n "$ipv6set" ] && bypassipv6s=$(echo "$ipv6set" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') +} #" vpnipv4md5=$(echo "${bypassipv4s}" | md5sum | awk '{print $1}' | tr -d "\n") vpnipv6md5=$(echo "${bypassipv6s}" | md5sum | awk '{print $1}' | tr -d "\n") From 2f76e66e1549a8af3ec7471f7ba2de66037867c8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:11:14 +0100 Subject: [PATCH 1279/2059] Fix log error on omr-tracker-ss --- omr-tracker/files/bin/omr-tracker-ss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omr-tracker/files/bin/omr-tracker-ss b/omr-tracker/files/bin/omr-tracker-ss index d26c260f2..829cf4dc5 100755 --- a/omr-tracker/files/bin/omr-tracker-ss +++ b/omr-tracker/files/bin/omr-tracker-ss @@ -103,7 +103,7 @@ while true; do script_alert_up="$(uci -q get omr-tracker.proxy.script_alert_up)" [ -n "$script_alert_up" ] && eval $script_alert_up } - if [ -z "$($IPTABLESSAVE 2>/dev/null | grep :ssr)" ] && [ -z "$(nft list ruleset | grep ss_r)" ] && [ -z "$(nft list ruleset | grep ssr_r)" ]; then + if [ -z "$($IPTABLESSAVE 2>/dev/null | grep :ssr)" ] && [ -z "$(nft list ruleset 2>/dev/null | grep ss_r)" ] && [ -z "$(nft list ruleset 2>/dev/null | grep ssr_r)" ]; then if [ "$type" = "libev" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" != "1" ]; then _log "Reload Shadowsocks rules" /etc/init.d/shadowsocks-libev rules_up 2> /dev/null @@ -120,7 +120,7 @@ while true; do last=$((last + 1 )) [ -z "$nocontact" ] && nocontact="$host" || nocontact="$nocontact, $host" [ "${last}" -ge "${retry}" ] && { - if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ssr)" ] || [ -n "$(nft list ruleset | grep ss_r)" ]; then + if [ -n "$($IPTABLES -w -t nat -L -n 2>/dev/null | grep ssr)" ] || [ -n "$(nft list ruleset 2>/dev/null | grep ss_r)" ] || [ -n "$(nft list ruleset 2>/dev/null | grep ssr_r)" ]; then _log "Shadowsocks ${server} is down (can't contact via http ${nocontact})" OMR_TRACKER_STATUS_MSG="Shadowsocks ${server} is down (can't contact via http ${nocontact})" uci -q set openmptcprouter.omr.ss_${server}="down" From 26a5bcf8115d50bc64ad7456d420a73d71f1dab1 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:11:49 +0100 Subject: [PATCH 1280/2059] Fix server vpn list on openmptcprouter-vps --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index b1af71ac8..929f4703f 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -947,10 +947,10 @@ _set_lan_ip() { _set_bypass_ips() { local settings [ -z "$servername" ] && servername=$1 - bypassipv4s=$(ipset -q -o save list omr_dst_bypass_srv_vpn1_4 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') - [ -z "$bypassipvs4" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') - bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1_6 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') - [ -z "$bypassipvs6" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + bypassipv4s=$(ipset -q -o save list omr_dst_bypass_vpn1_4 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs4" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_vpn1_6 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs6" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') # " if [ "$bypassipv4s" != "" ] || [ "$bypassipv6s" != "" ]; then settings='{"ipv4s" : ['$bypassipv4s'],"ipv6s" : ['$bypassipv6s'],"intf" : "vpn1"}' From 5f4ad12d3af4146ce1da613704ee87838a235f98 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:13:02 +0100 Subject: [PATCH 1281/2059] Add sysctl.d conf in openmptcprouter package --- .../files/etc/sysctl.d/openmptcprouter.conf | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf diff --git a/openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf b/openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf new file mode 100644 index 000000000..584db2854 --- /dev/null +++ b/openmptcprouter/files/etc/sysctl.d/openmptcprouter.conf @@ -0,0 +1,63 @@ +# local sysctl settings can be stored in this directory +# max open files +fs.file-max = 512000 +# max read buffer +net.core.rmem_max = 16777216 +# max write buffer +net.core.wmem_max = 16777216 +#net.core.optmem_max = 33554432 +# default read buffer +net.core.rmem_default = 16777216 +# default write buffer +net.core.wmem_default = 16777216 +# max processor input queue +net.core.netdev_max_backlog = 8192 +# max backlog +net.core.somaxconn = 8192 + +# resist SYN flood attacks +net.ipv4.tcp_syncookies = 1 +# reuse timewait sockets when safe +net.ipv4.tcp_tw_reuse = 1 +# turn off fast timewait sockets recycling +#net.ipv4.tcp_tw_recycle = 0 +# short FIN timeout +#net.ipv4.tcp_fin_timeout = 60 +# increase max orphans +net.ipv4.tcp_max_orphans = 16384 +# short keepalive time +#net.ipv4.tcp_keepalive_time = 2400 +# outbound port range +net.ipv4.ip_local_port_range = 9999 65000 +# max SYN backlog +net.ipv4.tcp_max_syn_backlog = 10240 +# max timewait sockets held by system simultaneously +net.ipv4.tcp_max_tw_buckets = 10000 +# turn on TCP Fast Open on both client and server side +#net.ipv4.tcp_fastopen = 3 +# TCP receive buffer +net.ipv4.tcp_rmem = 4096 87380 16777216 +# TCP write buffer +net.ipv4.tcp_wmem = 4096 87380 16777216 +# TCP buffer +net.ipv4.tcp_mem = 1638400 1638400 1638400 +# UDP buffer +net.ipv4.udp_mem = 4096 131072 67108864 +# turn off path MTU discovery +net.ipv4.tcp_mtu_probing = 0 + +# for low-latency network, use cubic instead +# net.ipv4.tcp_congestion_control = balia + +# Default conntrack is too small +net.netfilter.nf_conntrack_max = 131072 + +net.ipv4.conf.all.ignore_routes_with_linkdown = 1 +net.ipv4.conf.default.ignore_routes_with_linkdown = 1 + +net.ipv4.tcp_ecn = 2 +#net.ipv4.tcp_sack = 0 +#net.ipv4.tcp_dsack = 0 +#net.ipv4.tcp_fack = 0 +net.ipv4.tcp_slow_start_after_idle = 0 +net.ipv4.route.gc_timeout = 150 \ No newline at end of file From 5a311410cda607e459564b9d104d24a27b635420 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:26:31 +0100 Subject: [PATCH 1282/2059] remove shadowsocks sysctl --- shadowsocks-libev/files/shadowsocks.conf | 62 ------------------------ 1 file changed, 62 deletions(-) delete mode 100644 shadowsocks-libev/files/shadowsocks.conf diff --git a/shadowsocks-libev/files/shadowsocks.conf b/shadowsocks-libev/files/shadowsocks.conf deleted file mode 100644 index f02474433..000000000 --- a/shadowsocks-libev/files/shadowsocks.conf +++ /dev/null @@ -1,62 +0,0 @@ -# local sysctl settings can be stored in this directory -# max open files -fs.file-max = 512000 -# max read buffer -net.core.rmem_max = 16777216 -# max write buffer -net.core.wmem_max = 16777216 -#net.core.optmem_max = 33554432 -# default read buffer -net.core.rmem_default = 16777216 -# default write buffer -net.core.wmem_default = 16777216 -# max processor input queue -net.core.netdev_max_backlog = 8192 -# max backlog -net.core.somaxconn = 8192 - -# resist SYN flood attacks -net.ipv4.tcp_syncookies = 1 -# reuse timewait sockets when safe -net.ipv4.tcp_tw_reuse = 1 -# turn off fast timewait sockets recycling -#net.ipv4.tcp_tw_recycle = 0 -# short FIN timeout -#net.ipv4.tcp_fin_timeout = 60 -# increase max orphans -net.ipv4.tcp_max_orphans = 16384 -# short keepalive time -#net.ipv4.tcp_keepalive_time = 2400 -# outbound port range -net.ipv4.ip_local_port_range = 9999 65000 -# max SYN backlog -net.ipv4.tcp_max_syn_backlog = 10240 -# max timewait sockets held by system simultaneously -net.ipv4.tcp_max_tw_buckets = 10000 -# turn on TCP Fast Open on both client and server side -#net.ipv4.tcp_fastopen = 3 -# TCP receive buffer -net.ipv4.tcp_rmem = 4096 87380 16777216 -# TCP write buffer -net.ipv4.tcp_wmem = 4096 87380 16777216 -# TCP buffer -net.ipv4.tcp_mem = 1638400 1638400 1638400 -# UDP buffer -net.ipv4.udp_mem = 4096 131072 67108864 -# turn off path MTU discovery -net.ipv4.tcp_mtu_probing = 0 - -# for low-latency network, use cubic instead -# net.ipv4.tcp_congestion_control = balia - -# Default conntrack is too small -net.netfilter.nf_conntrack_max = 131072 - -net.ipv4.conf.all.ignore_routes_with_linkdown = 1 -net.ipv4.conf.default.ignore_routes_with_linkdown = 1 - -net.ipv4.tcp_ecn = 2 -#net.ipv4.tcp_sack = 0 -#net.ipv4.tcp_dsack = 0 -#net.ipv4.tcp_fack = 0 -net.ipv4.tcp_slow_start_after_idle = 0 \ No newline at end of file From 6e33eae78b9117a080a6bfad28ff623d8b391ef2 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:27:05 +0100 Subject: [PATCH 1283/2059] Use nftables packages when kernel != 5.4 --- openmptcprouter-full/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index d598ef975..38a2872d7 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -44,7 +44,7 @@ MY_DEPENDS := \ luci-app-uhttpd \ luci-mod-rpc rpcd-mod-rpcsys rpcd-mod-file rpcd-mod-iwinfo \ luci-app-openvpn \ - shadowsocks-libev-ss-server shadowsocks-libev-ss-redir shadowsocks-libev-ss-rules shadowsocks-libev-ss-tunnel \ + shadowsocks-libev-ss-server shadowsocks-libev-ss-redir LINUX_5_4:shadowsocks-libev-ss-rules !LINUX_5_4:shadowsocks-libev-ss-rules-nft shadowsocks-libev-ss-tunnel \ omr-6in4 ip6tables-mod-nat luci-proto-ipv6 6to4 6in4 6rd ip6tables \ !TARGET_mvebu:speedtestcpp \ iftop \ @@ -82,10 +82,10 @@ MY_DEPENDS := \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-openssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf (TARGET_x86||TARGET_x86_64):kmod-igbvf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard kmod-crypto-lib-blake2s (TARGET_x86||TARGET_x86_64):kmod-r8125 \ - !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core syslogd \ + !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core LINUX_5_4:v2ray-config !LINUX_5_4:v2ray-config-nft syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ - xray-core shadowsocks-rust-sslocal shadowsocks-rust-ssservice shadowsocks-rust-config luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 + xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 keepalived # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From b30f1951e2ee2913a1cb6ef03fd8b43a867db305 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:31:34 +0100 Subject: [PATCH 1284/2059] Use srv_vpn1 instead of only vpn1 for VPN on server ByPass --- omr-bypass/files/etc/init.d/omr-bypass-nft | 2 +- omr-schedule/files/usr/share/omr/schedule.d/030-bypass | 8 ++++---- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft index d8d9d312d..3552b3c33 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass-nft +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -816,7 +816,7 @@ start_service() { config_load network config_foreach _intf_rule interface _intf_rule all - _intf_rule vpn1 + _intf_rule srv_vpn1 local ndpi_rules="" echo "bypass server" if [ "$(uci -q get openmptcprouter.settings.bypass_servers)" = "1" ]; then diff --git a/omr-schedule/files/usr/share/omr/schedule.d/030-bypass b/omr-schedule/files/usr/share/omr/schedule.d/030-bypass index 67b86e1c2..e00f41fc0 100755 --- a/omr-schedule/files/usr/share/omr/schedule.d/030-bypass +++ b/omr-schedule/files/usr/share/omr/schedule.d/030-bypass @@ -1,13 +1,13 @@ #!/bin/sh -bypassipvs4s=$(ipset -o save list omr_dst_bypass_vpn1_4 2>/dev/null) +bypassipvs4s=$(ipset -o save list omr_dst_bypass_srv_vpn1_4 2>/dev/null) [ -z "$bypassipvs4s" ] && { - ipv4set=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_4" 2>/dev/null) + ipv4set=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" 2>/dev/null) [ -n "$ipv4set" ] && bypassipv4s=$(echo "$ipv4set" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') } -bypassipvs6s=$(ipset -o save list omr_dst_bypass_vpn1_6 2>/dev/null) +bypassipvs6s=$(ipset -o save list omr_dst_bypass_srv_vpn1_6 2>/dev/null) [ -z "$bypassipvs6s" ] && { - ipv6set=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_6" 2>/dev/null) + ipv6set=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" 2>/dev/null) [ -n "$ipv6set" ] && bypassipv6s=$(echo "$ipv6set" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') } #" diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 929f4703f..b1af71ac8 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -947,10 +947,10 @@ _set_lan_ip() { _set_bypass_ips() { local settings [ -z "$servername" ] && servername=$1 - bypassipv4s=$(ipset -q -o save list omr_dst_bypass_vpn1_4 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') - [ -z "$bypassipvs4" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') - bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_vpn1_6 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') - [ -z "$bypassipvs6" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + bypassipv4s=$(ipset -q -o save list omr_dst_bypass_srv_vpn1_4 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs4" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_4" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') + bypassipv6s=$(ipset -q -o save list omr6_dst_bypass_srv_vpn1_6 | awk '/add/ NF {print "\""$3"\""}' | tr '\n' ',' | sed 's/,$//') + [ -z "$bypassipvs6" ] && bypassipv4s=$(nft -j list set inet fw4 "omr_dst_bypass_srv_vpn1_6" | jsonfilter -e @.nftables[1].set.elem[*].prefix | awk '{gsub(/"/,"",$3);gsub(/,/,"/",$3); print $3 $5}') # " if [ "$bypassipv4s" != "" ] || [ "$bypassipv6s" != "" ]; then settings='{"ipv4s" : ['$bypassipv4s'],"ipv6s" : ['$bypassipv6s'],"intf" : "vpn1"}' From 0a2f10068625ee01ae65e53e0f87c94dcf9a5eb8 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 11:59:20 +0100 Subject: [PATCH 1285/2059] Ignore DMARK and DSCP rules in openmptcprouter-vps --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index b1af71ac8..82fb17d08 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1044,6 +1044,8 @@ _vps_firewall_redirect_port() { config_get name $1 name config_get dmz $1 dmz "0" config_get target $1 target "REDIRECT" + [ "$target" = "MARK" ] && return + [ "$target" = "DSCP" ] && return if [ -z "$src_dport" ] && [ -n "$dest_port" ]; then src_dport=$dest_port fi From 84419a272e362c7366767660c8fbee229f4f55c3 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 14:38:53 +0100 Subject: [PATCH 1286/2059] Add nft dependencies --- openmptcprouter-full/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 38a2872d7..2db1335c8 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -21,7 +21,7 @@ MY_DEPENDS := \ mc \ f2fs-tools \ openmptcprouter \ - dnsmasq-full dnsmasq_full_ipset \ + dnsmasq-full LINUX_5_4:dnsmasq_full_ipset !LINUX_5_4:dnsmasq_full_nftset \ uhttpd \ uhttpd-mod-ubus \ curl \ @@ -29,9 +29,10 @@ MY_DEPENDS := \ arptables \ bind-dig \ libnetfilter-conntrack ip-full nstat \ - iptables-mod-iface iptables-mod-ipmark iptables-mod-hashlimit iptables-mod-condition iptables-mod-trace iptables-mod-conntrack-extra iptables-mod-account \ - kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra conntrack kmod-ipt-offload \ - iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 kmod-ipt-ipsec \ + LINUX_5_4:iptables-mod-iface LINUX_5_4:iptables-mod-ipmark LINUX_5_4:iptables-mod-hashlimit LINUX_5_4:iptables-mod-condition LINUX_5_4:iptables-mod-trace LINUX_5_4:iptables-mod-conntrack-extra LINUX_5_4:iptables-mod-account \ + kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra LINUX_5_4:iptables-mod-extra conntrack LINUX_5_4:kmod-ipt-offload \ + LINUX_5_4:iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 LINUX_5_4:kmod-ipt-ipsec \ + !LINUX_5_4:nftables-json !LINUX_5_4:iptables-nft !LINUX_5_4:kmod-nft-connlimit !LINUX_5_4:kmod-nft-offload wireless-tools \ libiwinfo-lua \ ca-bundle ca-certificates \ From 354157bbb098b983776cd6576eb36af9c0823a90 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Jan 2024 18:31:51 +0100 Subject: [PATCH 1287/2059] Fix save xray config in openmptcprouter-vps --- openmptcprouter/files/etc/init.d/openmptcprouter-vps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index 82fb17d08..30e4d73d0 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -1704,7 +1704,7 @@ _set_config_from_vps() { uci -q set xray.omrout.s_socks_address="$vpsip" uci -q set xray.omrout.s_shadowsocks_address="$vpsip" fi - uci -q commit v2ray + uci -q commit xray logger -t "OMR-VPS" "Xray restart..." /etc/init.d/xray restart >/dev/null 2>&1 fi From bb64827a1e96d609059f4de1cf891c95176b14ba Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 17:25:16 +0100 Subject: [PATCH 1288/2059] Fix openmptcprouter-full --- openmptcprouter-full/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index 2db1335c8..3edaa5f55 100644 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -32,7 +32,7 @@ MY_DEPENDS := \ LINUX_5_4:iptables-mod-iface LINUX_5_4:iptables-mod-ipmark LINUX_5_4:iptables-mod-hashlimit LINUX_5_4:iptables-mod-condition LINUX_5_4:iptables-mod-trace LINUX_5_4:iptables-mod-conntrack-extra LINUX_5_4:iptables-mod-account \ kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra LINUX_5_4:iptables-mod-extra conntrack LINUX_5_4:kmod-ipt-offload \ LINUX_5_4:iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 LINUX_5_4:kmod-ipt-ipsec \ - !LINUX_5_4:nftables-json !LINUX_5_4:iptables-nft !LINUX_5_4:kmod-nft-connlimit !LINUX_5_4:kmod-nft-offload + !LINUX_5_4:nftables-json !LINUX_5_4:iptables-nft !LINUX_5_4:kmod-nft-connlimit !LINUX_5_4:kmod-nft-offload \ wireless-tools \ libiwinfo-lua \ ca-bundle ca-certificates \ @@ -86,7 +86,10 @@ MY_DEPENDS := \ !(LINUX_5_4):mptcpd (TARGET_x86||TARGET_x86_64):kmod-igc !TARGET_mvebu:kmod-mmc-spi kmod-macsec usbutils v2ray-core LINUX_5_4:v2ray-config !LINUX_5_4:v2ray-config-nft syslogd \ (TARGET_x86||TARGET_x86_64):kmod-mlx4-core \ !(TARGET_ips40xx||TARGET_ramips):iptables-mod-ndpi !(TARGET_ips40xx||TARGET_ramips):kmod-ipt-ndpi libip4tc libip6tc \ - xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 keepalived + xray-core LINUX_5_4:xray-config !LINUX_5_4:xray-config-nft shadowsocks-rust-sslocal shadowsocks-rust-ssservice LINUX_5_4:shadowsocks-rust-config !LINUX_5_4:shadowsocks-rust-config-nft luci-app-shadowsocks-rust (LINUX_5_4&&(TARGET_x86_64||aarch64)):kmod-tcp-bbr2 kmod-ovpn-dco-v2 \ + (TARGET_x86||TARGET_x86_64):luci-app-keepalived luci-proto-external + + # !TARGET_mvebu:kmod-usb-net-smsc75xx # libnetfilter-conntrack ebtables ebtables-utils ip-full nstat \ From f5b3aa68313052c2f7b96b31ee6a220216d4ad4f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 12 Jan 2024 17:28:40 +0100 Subject: [PATCH 1289/2059] New version of OMR-Tracker --- luci-app-omr-tracker/Makefile | 2 +- .../view/omr-tracker/network/interface.js | 289 ++++++++++++++++++ .../view/omr-tracker/network/proxy.js | 186 +++++++++++ .../view/omr-tracker/network/server.js | 163 ++++++++++ .../luasrc/controller/omr-tracker.lua | 6 - .../luasrc/model/cbi/omr-tracker.lua | 254 --------------- .../view/omr-tracker/cbi-select-add.htm | 10 - .../luci/menu.d/luci-app-omr-tracker.json | 31 +- .../rpcd/acl.d/luci-app-omr-tracker.json | 8 +- omr-tracker/Makefile | 4 +- omr-tracker/files/bin/omr-tracker | 64 +++- omr-tracker/files/etc/config/omr-tracker | 63 ++-- omr-tracker/files/etc/init.d/omr-tracker | 41 ++- .../files/etc/uci-defaults/omr-tracker | 22 ++ .../files/etc/uci-defaults/1990-omr-tracker | 6 + 15 files changed, 831 insertions(+), 318 deletions(-) create mode 100644 luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js create mode 100644 luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/proxy.js create mode 100644 luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/server.js delete mode 100644 luci-app-omr-tracker/luasrc/controller/omr-tracker.lua delete mode 100644 luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua delete mode 100644 luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm diff --git a/luci-app-omr-tracker/Makefile b/luci-app-omr-tracker/Makefile index 410d1994a..03bf7e30e 100644 --- a/luci-app-omr-tracker/Makefile +++ b/luci-app-omr-tracker/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) # # diff --git a/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js new file mode 100644 index 000000000..2c11934e6 --- /dev/null +++ b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/interface.js @@ -0,0 +1,289 @@ +'use strict'; +'require form'; +'require fs'; +'require view'; +'require uci'; + +var cfgtypes = ['defaults','interface']; + +return view.extend({ + load: function() { + return Promise.all([ + L.resolveDefault(fs.stat('/usr/bin/httping'), {}), + L.resolveDefault(fs.stat('/usr/bin/dig'), {}), +// L.resolveDefault(fs.stat('/usr/bin/nping'), {}), +// L.resolveDefault(fs.stat('/usr/bin/arping'), {}), + uci.load('network') + ]); + }, + + render: function (stats) { + var m, s, o; + + m = new form.Map('omr-tracker', _('OMR-Tracker - Interfaces'), + _('Names must match the interface name found in /etc/config/network.') + '
    ' + + _('Names may contain characters A-Z, a-z, 0-9, _ and no spaces-')); + + //s = m.section(form.GridSection, 'defaults'); + s = m.section(form.GridSection); + s.addremove = true; + s.anonymous = false; + s.nodescriptions = true; + s.cfgsections = function() { + return this.map.data.sections(this.map.config) + .filter(function(s) { return cfgtypes.indexOf(s['.type']) !== -1; }) + .map(function(s) { return s['.name']; }); + }; + + o = s.option(form.Flag, 'enabled', _('Enabled')); + o.default = false; + + o = s.option(form.ListValue, 'initial_state', _('Initial state'), + _('Expect interface state on up event')); + o.default = 'online'; + o.value('online', _('Online')); + o.value('offline', _('Offline')); + o.modalonly = true; + + o = s.option(form.ListValue, 'family', _('Internet Protocol')); + o.default = 'ipv4'; + o.value('ipv4', _('IPv4')); + o.value('ipv6', _('IPv6')); + o.value('ipv4ipv6', _('IPv4 & IPv6')); + o.modalonly = true; + + o = s.option(form.DynamicList, 'hosts', _('Tracking hostname or IP address'), + _('This hostname or IP address will be pinged to determine if the link is up or down. Leave blank to use defaults settings.')); + o.datatype = 'hosts'; + o.modalonly = true; + o.rmempty = false; + + o = s.option(form.DynamicList, 'hosts6', _('Tracking hostname or IP address for IPv6'), + _('This hostname or IP address will be pinged to determine if the link is up or down. Leave blank to use defaults settings.')); + o.datatype = 'hosts'; + o.modalonly = true; + o.depends('family', 'ipv4ipv6'); + o.depends('family', 'ipv6'); + o.rmempty = false; + + o = s.option(form.ListValue, 'type', _('Tracking method')); + o.default = 'ping'; + o.value('none'); + o.value('ping'); + if (stats[0].type === 'file') { + o.value('httping'); + } + if (stats[1].type === 'file') { + o.value('dns'); + } + /* + if (stats[2].type === 'file') { + o.value('nping-tcp'); + o.value('nping-udp'); + o.value('nping-icmp'); + o.value('nping-arp'); + } + if (stats[3].type === 'file') { + o.value('arping'); + } + */ + o = s.option(form.Flag, 'server_http_test', _('Server http test'), + _('Check if connection work with http by sending a request to server')); + o.rmempty = false; + o.modalonly = true; + + o = s.option(form.Flag, 'mail_alert', _('Mail alert'), + _('Send a mail when connection status change. You need to configure e-mail settings here.')); + o.rmempty = false; + o.modalonly = true; + + /* + o = s.option(form.Flag, 'httping_ssl', _('Enable ssl tracking'), + _('Enables https tracking on ssl port 443')); + o.depends('type', 'httping'); + o.rmempty = false; + o.modalonly = true; + */ + + o = s.option(form.Value, 'reliability', _('Tracking reliability'), + _('Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up')); + o.datatype = 'range(1, 100)'; + o.default = '1'; + + o = s.option(form.ListValue, 'count', _('Ping count')); + o.default = '1'; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.modalonly = true; + + o = s.option(form.Value, 'size', _('Ping size')); + o.default = '56'; + o.depends('type', 'ping'); + o.value('8'); + o.value('24'); + o.value('56'); + o.value('120'); + o.value('248'); + o.value('504'); + o.value('1016'); + o.value('1472'); + o.value('2040'); + o.datatype = 'range(1, 65507)'; + o.modalonly = true; + + o =s.option(form.Value, 'max_ttl', _('Max TTL')); + o.default = '60'; + o.depends('type', 'ping'); + o.value('10'); + o.value('20'); + o.value('30'); + o.value('40'); + o.value('50'); + o.value('60'); + o.value('70'); + o.datatype = 'range(1, 255)'; + o.modalonly = true; + + o = s.option(form.Flag, 'check_quality', _('Check link quality')); + o.depends('type', 'ping'); + o.default = false; + o.modalonly = true; + + o = s.option(form.Value, 'failure_latency', _('Failure latency [ms]')); + o.depends('check_quality', '1'); + o.default = '1000'; + o.value('25'); + o.value('50'); + o.value('75'); + o.value('100'); + o.value('150'); + o.value('200'); + o.value('250'); + o.value('300'); + o.modalonly = true; + + o = s.option(form.Value, 'failure_loss', _('Failure packet loss [%]')); + o.depends('check_quality', '1'); + o.default = '40'; + o.value('2'); + o.value('5'); + o.value('10'); + o.value('20'); + o.value('25'); + o.modalonly = true; + + o = s.option(form.Value, 'recovery_latency', _('Recovery latency [ms]')); + o.depends('check_quality', '1'); + o.default = '500'; + o.value('25'); + o.value('50'); + o.value('75'); + o.value('100'); + o.value('150'); + o.value('200'); + o.value('250'); + o.value('300'); + o.modalonly = true; + + o = s.option(form.Value, 'recovery_loss', _('Recovery packet loss [%]')); + o.depends('check_quality', '1'); + o.default = '10'; + o.value('2'); + o.value('5'); + o.value('10'); + o.value('20'); + o.value('25'); + o.modalonly = true; + + o = s.option(form.ListValue, "timeout", _("Ping timeout")); + o.default = '4'; + o.value('1', _('%d second').format('1')); + for (var i = 2; i <= 10; i++) + o.value(String(i), _('%d seconds').format(i)); + o.modalonly = true; + + o = s.option(form.ListValue, 'interval', _('Ping interval')); + o.default = '10'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); + + o = s.option(form.Value, 'failure_interval', _('Failure interval'), + _('Ping interval during failure detection')); + o.default = '5'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); + o.modalonly = true; + + o = s.option(form.Flag, 'keep_failure_interval', _('Keep failure interval'), + _('Keep ping failure interval during failure state')); + o.default = false; + o.modalonly = true; + + o = s.option(form.ListValue, 'tries', _('Interface down'), + _('Interface will be deemed down after this many failed ping tests')); + o.default = '5'; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.value('6'); + o.value('7'); + o.value('8'); + o.value('9'); + o.value('10'); + + o = s.option(form.ListValue, 'tries_up', _('Interface up'), + _('Downed interface will be deemed up after this many successful ping tests')); + o.default = "5"; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.value('6'); + o.value('7'); + o.value('8'); + o.value('9'); + o.value('10'); + + o = s.option(form.Flag, 'restart_down', _('Restart if down'), + _('Restart interface if detected as down.')); + o.rmempty = false; + o.modalonly = true; + + + /* + o = s.option(form.DynamicList, 'flush_conntrack', _('Flush conntrack table'), + _('Flush global firewall conntrack table on interface events')); + o.value('ifup', _('ifup (netifd)')); + o.value('ifdown', _('ifdown (netifd)')); + o.modalonly = true; + */ + + return m.render(); + } +}) diff --git a/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/proxy.js b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/proxy.js new file mode 100644 index 000000000..0a4b80e86 --- /dev/null +++ b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/proxy.js @@ -0,0 +1,186 @@ +'use strict'; +'require form'; +'require fs'; +'require view'; +'require uci'; + +var cfgtypes = ['proxy']; + +return view.extend({ + load: function() { + return Promise.all([ + L.resolveDefault(fs.stat('/usr/bin/httping'), {}), + L.resolveDefault(fs.stat('/usr/bin/dig'), {}), +// L.resolveDefault(fs.stat('/usr/bin/nping'), {}), +// L.resolveDefault(fs.stat('/usr/bin/arping'), {}), + uci.load('network') + ]); + }, + + render: function (stats) { + var m, s, o; + + m = new form.Map('omr-tracker', _('OMR-Tracker - Proxy'), + _('Detect if proxy is down and stop redirection over it.')); + + //s = m.section(form.GridSection, 'defaults'); + s = m.section(form.GridSection); + //s.addremove = true; + s.anonymous = false; + s.nodescriptions = true; + s.cfgsections = function() { + return this.map.data.sections(this.map.config) + .filter(function(s) { return cfgtypes.indexOf(s['.type']) !== -1; }) + .map(function(s) { return s['.name']; }); + }; + + o = s.option(form.Flag, 'enabled', _('Enabled')); + o.default = false; + + o = s.option(form.ListValue, 'initial_state', _('Initial state'), + _('Expect interface state on up event')); + o.default = 'online'; + o.value('online', _('Online')); + o.value('offline', _('Offline')); + o.modalonly = true; + + o = s.option(form.ListValue, 'family', _('Internet Protocol')); + o.default = 'ipv4ipv6'; + //o.value('ipv4', _('IPv4')); + //o.value('ipv6', _('IPv6')); + o.value('ipv4ipv6', _('IPv4 & IPv6')); + o.modalonly = true; + + o = s.option(form.DynamicList, 'hosts', _('Tracking hostname or IP address'), + _('This hostname or IP address will be pinged to determine if the link is up or down. Leave blank to assume interface is always online')); + o.datatype = 'hosts'; + o.modalonly = true; + + o = s.option(form.DynamicList, 'hosts6', _('Tracking hostname or IP address for IPv6'), + _('This hostname or IP address will be pinged to determine if the link is up or down. Leave blank to assume interface is always online')); + o.datatype = 'hosts'; + o.modalonly = true; + o.depends('family', 'ipv4ipv6'); + o.depends('family', 'ipv6'); + + /* + o = s.option(form.Flag, 'httping_ssl', _('Enable ssl tracking'), + _('Enables https tracking on ssl port 443')); + o.depends('track_method', 'httping'); + o.rmempty = false; + o.modalonly = true; + */ + + o = s.option(form.Flag, 'mail_alert', _('Mail alert'), + _('Send a mail when connection status change. You need to configure e-mail settings here.')); + o.rmempty = false; + o.modalonly = true; + + +/* + o = s.option(form.Value, 'reliability', _('Tracking reliability'), + _('Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up')); + o.datatype = 'range(1, 100)'; + o.default = '1'; +*/ + o = s.option(form.ListValue, 'tries', _('Test count')); + o.default = '1'; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.modalonly = true; + + o = s.option(form.ListValue, "timeout", _("Test timeout")); + o.default = '4'; + o.value('1', _('%d second').format('1')); + for (var i = 2; i <= 10; i++) + o.value(String(i), _('%d seconds').format(i)); + o.modalonly = true; + + o = s.option(form.ListValue, 'interval', _('Test interval')); + o.default = '10'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); +/* + o = s.option(form.Value, 'failure_interval', _('Failure interval'), + _('Ping interval during failure detection')); + o.default = '5'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); + o.modalonly = true; + + o = s.option(form.Flag, 'keep_failure_interval', _('Keep failure interval'), + _('Keep ping failure interval during failure state')); + o.default = false; + o.modalonly = true; + + o = s.option(form.Value, 'recovery_interval', _('Recovery interval'), + _('Ping interval during failure recovering')); + o.default = '5'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); + o.modalonly = true; + + o = s.option(form.ListValue, 'tries', _('Proxy down'), + _('Proxy will be deemed down after this many failed tests')); + o.default = '5'; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.value('6'); + o.value('7'); + o.value('8'); + o.value('9'); + o.value('10'); + + o = s.option(form.ListValue, 'tries_up', _('Interface up'), + _('Downed interface will be deemed up after this many successful ping tests')); + o.default = "5"; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.value('6'); + o.value('7'); + o.value('8'); + o.value('9'); + o.value('10'); +*/ + return m.render(); + } +}) diff --git a/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/server.js b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/server.js new file mode 100644 index 000000000..b14cb2020 --- /dev/null +++ b/luci-app-omr-tracker/htdocs/luci-static/resources/view/omr-tracker/network/server.js @@ -0,0 +1,163 @@ +'use strict'; +'require form'; +'require fs'; +'require view'; +'require uci'; + +var cfgtypes = ['server']; + +return view.extend({ + load: function() { + return Promise.all([ + L.resolveDefault(fs.stat('/usr/bin/httping'), {}), + L.resolveDefault(fs.stat('/usr/bin/dig'), {}), +// L.resolveDefault(fs.stat('/usr/bin/nping'), {}), +// L.resolveDefault(fs.stat('/usr/bin/arping'), {}), + uci.load('network') + ]); + }, + + render: function (stats) { + var m, s, o; + + m = new form.Map('omr-tracker', _('OMR-Tracker - Server'), + _('Detect if server is down and use defined backup server in this case.')); + + //s = m.section(form.GridSection, 'defaults'); + s = m.section(form.GridSection); + //s.addremove = true; + s.anonymous = false; + s.nodescriptions = true; + s.cfgsections = function() { + return this.map.data.sections(this.map.config) + .filter(function(s) { return cfgtypes.indexOf(s['.type']) !== -1; }) + .map(function(s) { return s['.name']; }); + }; + + o = s.option(form.Flag, 'enabled', _('Enabled')); + o.default = false; + + o = s.option(form.ListValue, 'initial_state', _('Initial state'), + _('Expect interface state on up event')); + o.default = 'online'; + o.value('online', _('Online')); + o.value('offline', _('Offline')); + o.modalonly = true; + + o = s.option(form.Flag, 'mail_alert', _('Mail alert'), + _('Send a mail when connection status change. You need to configure e-mail settings here.')); + o.rmempty = false; + o.modalonly = true; +/* + o = s.option(form.Value, 'reliability', _('Tracking reliability'), + _('Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up')); + o.datatype = 'range(1, 100)'; + o.default = '1'; +*/ + o = s.option(form.ListValue, 'tries', _('Test count')); + o.default = '1'; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.modalonly = true; + +/* + o = s.option(form.Flag, 'check_quality', _('Check link quality')); + o.depends('track_method', 'ping'); + o.default = false; + o.modalonly = true; +*/ + o = s.option(form.ListValue, "timeout", _("Test timeout")); + o.default = '4'; + o.value('1', _('%d second').format('1')); + for (var i = 2; i <= 10; i++) + o.value(String(i), _('%d seconds').format(i)); + o.modalonly = true; + + o = s.option(form.ListValue, 'interval', _('Test interval')); + o.default = '10'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); +/* + o = s.option(form.Value, 'failure_interval', _('Failure interval'), + _('Ping interval during failure detection')); + o.default = '5'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); + o.modalonly = true; + + o = s.option(form.Flag, 'keep_failure_interval', _('Keep failure interval'), + _('Keep ping failure interval during failure state')); + o.default = false; + o.modalonly = true; + + o = s.option(form.Value, 'recovery_interval', _('Recovery interval'), + _('Ping interval during failure recovering')); + o.default = '5'; + o.value('1', _('%d second').format('1')); + o.value('3', _('%d seconds').format('3')); + o.value('5', _('%d seconds').format('5')); + o.value('10', _('%d seconds').format('10')); + o.value('20', _('%d seconds').format('20')); + o.value('30', _('%d seconds').format('30')); + o.value('60', _('%d minute').format('1')); + o.value('300', _('%d minutes').format('5')); + o.value('600', _('%d minutes').format('10')); + o.value('900', _('%d minutes').format('15')); + o.value('1800', _('%d minutes').format('30')); + o.value('3600', _('%d hour').format('1')); + o.modalonly = true; + + o = s.option(form.ListValue, 'down', _('Interface down'), + _('Interface will be deemed down after this many failed ping tests')); + o.default = '5'; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.value('6'); + o.value('7'); + o.value('8'); + o.value('9'); + o.value('10'); + + o = s.option(form.ListValue, 'up', _('Interface up'), + _('Downed interface will be deemed up after this many successful ping tests')); + o.default = "5"; + o.value('1'); + o.value('2'); + o.value('3'); + o.value('4'); + o.value('5'); + o.value('6'); + o.value('7'); + o.value('8'); + o.value('9'); + o.value('10'); +*/ + return m.render(); + } +}) diff --git a/luci-app-omr-tracker/luasrc/controller/omr-tracker.lua b/luci-app-omr-tracker/luasrc/controller/omr-tracker.lua deleted file mode 100644 index a4fcb23e7..000000000 --- a/luci-app-omr-tracker/luasrc/controller/omr-tracker.lua +++ /dev/null @@ -1,6 +0,0 @@ -module("luci.controller.omr-tracker", package.seeall) - -function index() - --entry({"admin", "openmptcprouter", "omr-tracker"}, cbi("omr-tracker"), _("OMR-Tracker")) - entry({"admin", "services", "omr-tracker"}, cbi("omr-tracker"), _("OMR-Tracker")) -end diff --git a/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua b/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua deleted file mode 100644 index 0e22a0e94..000000000 --- a/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua +++ /dev/null @@ -1,254 +0,0 @@ -local net = require "luci.model.network".init() -local sys = require "luci.sys" -local m, s, o - -m = Map("omr-tracker", translate("OMR-Tracker")) - -s = m:section(TypedSection, "proxy", translate("Proxy tracker Settings"), translate("Detect if Proxy is down and stop traffic redirection over it.")) -s.anonymous = true -s.addremove = false - -local sdata = m:get('proxy') -if not sdata then - m:set('proxy', nil, 'proxy') - m:set('proxy', 'enabled', "1") -end - -o = s:option(Flag, "enabled", translate("Enable"), translate("When tracker is disabled, connection failover is also disabled")) -o.rmempty = false - -o = s:option(Value, "timeout", translate("Timeout (s)")) -o.placeholder = "1" -o.default = "1" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "tries", translate("Tries")) -o.placeholder = "4" -o.default = "4" -o.datatype = "range(1, 10)" -o.rmempty = false - -o = s:option(Value, "interval", translate("Retry interval (s)")) -o.placeholder = "2" -o.default = "2" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "wait_test", translate("Wait after a failed test (s)")) -o.placeholder = "0" -o.default = "0" -o.datatype = "range(0, 100)" -o.rmempty = false - -o = s:option(Flag, "mail_alert", translate("Mail alert"), translate("Send a mail when connection state change")) -o.optional = false -o.rmempty = false -o.default = false -o.disabled = 0 -o.enabled = 1 - -o = s:option(DynamicList, "hosts", translate("Hosts"), translate("IPs or domains must be available over http")) -o.placeholder = "bing.com" -o.default = { "bing.com", "google.com" } -o.rmempty = false - - -s = m:section(TypedSection, "server", translate("Server tracker Settings"), translate("Detect if Server is down and use defined backup server in this case.")) -s.anonymous = true -s.addremove = false - -local sdata = m:get('server') -if not sdata then - m:set('server', nil, 'server') - m:set('server', 'enabled', "1") -end - -o = s:option(Flag, "enabled", translate("Enable"), translate("When tracker is disabled, server failover is also disabled")) -o.rmempty = false - -o = s:option(Value, "timeout", translate("Timeout (s)")) -o.placeholder = "1" -o.default = "1" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "tries", translate("Tries")) -o.placeholder = "4" -o.default = "4" -o.datatype = "range(1, 10)" -o.rmempty = false - -o = s:option(Value, "interval", translate("Retry interval (s)")) -o.placeholder = "2" -o.default = "2" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "wait_test", translate("Wait after a failed test (s)")) -o.placeholder = "0" -o.default = "0" -o.datatype = "range(0, 100)" -o.rmempty = false - -o = s:option(Flag, "mail_alert", translate("Mail alert"), translate("Send a mail when connection state change")) -o.optional = false -o.rmempty = false -o.default = false -o.disabled = 0 -o.enabled = 1 - -s = m:section(TypedSection, "defaults", translate("Defaults Settings"), translate("OMR-Tracker create needed routes and detect when a connection is down or up")) -s.anonymous = true - -o = s:option(Flag, "enabled", translate("Enable"), translate("When tracker is disabled, connection failover is also disabled")) -o.rmempty = false - -o = s:option(Value, "timeout", translate("Timeout (s)")) -o.placeholder = "1" -o.default = "1" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "tries", translate("Tries"), translate("How many times repeat test")) -o.placeholder = "4" -o.default = "4" -o.datatype = "range(1, 10)" -o.rmempty = false - -o = s:option(Value, "count", translate("Count"), translate("How many packets send on each test")) -o.placeholder = "2" -o.default = "2" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "interval", translate("Retry interval (s)")) -o.placeholder = "2" -o.default = "2" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "wait_test", translate("Wait after a failed test (s)")) -o.placeholder = "0" -o.default = "0" -o.datatype = "range(0, 100)" -o.rmempty = false - -o = s:option(ListValue, "type", translate("Type"), translate("Always ping gateway, then test connection by ping, httping or dns. None mode only ping gateway.")) -o:value("ping","ping") -o:value("httping","httping") -o:value("dns","dns") -o:value("none","none") - -o = s:option(Flag, "server_http_test", translate("Server http test"), translate("Check if connection work with http by sending a request to server")) -o.optional = false -o.rmempty = false -o.default = true -o.disabled = 0 -o.enabled = 1 - -o = s:option(Flag, "mail_alert", translate("Mail alert"), translate("Send a mail when connection state change")) -o.optional = false -o.rmempty = false -o.default = false -o.disabled = 0 -o.enabled = 1 - -o = s:option(Flag, "restart_down", translate("Restart if down"), translate("Restart interface if detected as down")) -o.optional = false -o.rmempty = false -o.default = false -o.disabled = 0 -o.enabled = 1 - -o = s:option(DynamicList, "hosts", translate("Hosts"), translate("Must be IPs and not domains")) -o.placeholder = "4.2.2.1" -o.default = { "4.2.2.1", "8.8.8.8" } -o.rmempty = false - -o = s:option(DynamicList, "hosts6", translate("Hosts IPv6"), translate("Must be IPs and not domains")) -o.placeholder = "2001:4860:4860::8844" -o.default = { "2001:4860:4860::8888", "2001:4860:4860::8844" } -o.rmempty = false - -s = m:section(TypedSection, "interface", translate("Interfaces")) -s.template_addremove = "omr-tracker/cbi-select-add" -s.addremove = true -s.add_select_options = { } -s.add_select_options[''] = '' -for _, iface in ipairs(net:get_networks()) do - if not (iface:name() == "loopback") then - s.add_select_options[iface:name()] = iface:name() - end -end - -o = s:option(Flag, "enabled", translate("Enable")) -o.rmempty = false - -o = s:option(Value, "timeout", translate("Timeout (s)")) -o.placeholder = "1" -o.default = "1" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "tries", translate("Tries")) -o.placeholder = "4" -o.default = "4" -o.datatype = "range(1, 10)" -o.rmempty = false - -o = s:option(Value, "count", translate("Count"), translate("How many packets send on each test, one wrong make test fail, one wrong make tail fail")) -o.placeholder = "2" -o.default = "2" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "interval", translate("Retry interval (s)")) -o.placeholder = "2" -o.default = "2" -o.datatype = "range(1, 100)" -o.rmempty = false - -o = s:option(Value, "wait_test", translate("Wait after a failed test (s)")) -o.placeholder = "0" -o.default = "0" -o.datatype = "range(0, 100)" -o.rmempty = false - -o = s:option(ListValue, "type", translate("Type"), translate("Always ping gateway, then test connection by ping, httping or dns. None mode only ping gateway.")) -o:value("ping","ping") -o:value("httping","httping") -o:value("dns","dns") -o:value("none","none") - -o = s:option(Flag, "server_http_test", translate("Server http test"), translate("Check if connection work with http by sending a request to server")) -o.optional = false -o.rmempty = false -o.default = true -o.disabled = 0 -o.enabled = 1 - -o = s:option(Flag, "mail_alert", translate("Mail alert"), translate("Send a mail when connection status change. You need to configure e-mail settings
    here.")) -o.optional = false -o.rmempty = false -o.default = false -o.disabled = 0 -o.enabled = 1 - -o = s:option(Flag, "restart_down", translate("Restart if down"), translate("Restart interface if detected as down")) -o.optional = false -o.rmempty = false -o.default = false -o.disabled = 0 -o.enabled = 1 - -o = s:option(DynamicList, "hosts", translate("Hosts"), translate("Must be IPs and not domains")) -o.placeholder = "4.2.2.1" -o.default = { "4.2.2.1", "8.8.8.8" } -o.rmempty = false - -o = s:option(DynamicList, "hosts6", translate("Hosts IPv6"), translate("Must be IPs and not domains")) -o.placeholder = "2001:4860:4860::8844" -o.rmempty = false - -return m diff --git a/luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm b/luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm deleted file mode 100644 index 97ee647d2..000000000 --- a/luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm +++ /dev/null @@ -1,10 +0,0 @@ -

    ~ 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
    \s*$/g,ra={option:[1,""],legend:[1,"",""],area:[1,"",""],param:[1,"",""],thead:[1,"
    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 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/fonts/Inter-ExtraLight.woff2 b/luci-theme-alpha/luasrc/fonts/Inter-ExtraLight.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..3ff561883c4807c59f43082867ebf9d55c73d77d GIT binary patch literal 98168 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 z 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

    -JJ7V3Zlv<-Hqtdi=<@O?m zn0=?s%WBV?dhk$YYvd@28to_XYPQduvf0CQI^t1Pbjv!EpPAJ1PL|p-zQ}s_R z0aI2wv^27?3rj9VM$LPR4i%od=f~j7x17q6$`LfW4u0%--f=^@MjYTEnYO8=Fdp=} zxUD=#*ECl;C1gaxr*8w7B06sMP6p0rw@^KgL~zLEm*g}pa|0}A$Da7s(H=IdT~7c^ zmSD{#!?*2>s1?AefD&sI5)O7el|AnCH1()_0~7s~dYrthyrY|Rs{dKfsp)6nUI5L2 z-6mi>DnpD{Ohp0XibH|Gryt^tmQ0s|O!}vXM^U6IRZ+E8<$xh@Pc}@SsnSp3zrg9N zljY)X*_;?o)!98-fz4CH4M3DnE(&0)m}^vA!#(5f*-($WY$^=)L@0^9R`k>rv9xj_ zC-3jZE5qR~S9rhG?t0+LtF1Ys;Z8Sr4?lIdIL^*vM?@Q9FATzFtcpm@@P|jjHL*F`b|&ubV@hSi z1o^pq@q$};j#lzi%H~{^)(;>j9+C5`eA*5$uA+m&eVJH z;pvIO8U^sthjhSlzB89_xCe;|xWy&^Y*qjCNwJiaJvDVH0%B?XxbrRc#WGF{@xc0_ zrbfvxIx@)NjvnOuAr0~u{7>!fVVR!#DzVyvdv7=L?yFqx9Xis;v`6Kh)r$#ocIB(# ziV>B5HTHjp}8(qn!>&86Cu=IQi9zgnadgm12XTbCo&>SLQ036O7r`{C~Rp*v>hC0u#`j2Dv=mR#|cVa~Th_p>VwZ zSfc?`F9{sdGX;hsV1NY}@FKx&NeHpAKrSFEGwOB`W*D3D{QSdSC?1i0oILS{dq zB}DK_)ehyX1E%jm;tM7uP9AyK)o7R%@%u92Ks|s<(3Ns2gn`Hg02%v`?K{2Cw;%yD zj`iWvlLq7_qLB2-Ptle6B+|7H?#0LB5tH5as-UX!RZ-g*c$Lw{ej(*S3SfO&)dUiM zGRJ$;nb73G2=G3gLGHinabEOshSkl>Q<*kW^KHpLqLbgp;v*7A`p~||7wbc`doQzt zRo80b?U5w}jI&Q5A0Te`(;9|CQoeLzoaOfXT{Cf8U0uf}%4vr{vNVEjGSUEis+nB? zIo80@+Z30_tdDD7N7f5xZM@D#Gf-z=+mt8*299?Bp^hgS)(BJg74uAe<9Cv~W)l}9 zmIU?N!9Rw$D~EyY3n!6Q#CH4-QM!I}u0DN{g*Uh{hC8#$%EXR6NU1;I(kPLY{`7NT zMyKdNn$z14Y0i?f?de}avgWC51wL=sA)E4fe62F#2ItZrX6sMUGGDh!1m>`jUfvt> z=NsUc=<{NLY5Vc}n}j$fTxPRMbE578R67VI#u{rGc|BcS%d_e3=*&uJtsSe43hc^b zPin}0)b-+BT375Hc11~GrCtQ23=*4Vh$??^*K6seEZcY~1M;=R!2nrdIH zjH}e7=9Wx(`Z3SDMl3*H9u=8GsQ-=rN>qBuG2l1S;4W9S&4IZdkAjA4gSeJ}DLp`) zE#g)=kW>>rYW#c*fiWgY^k;fE{g*c_h5KJ2;SJ|5x{t8hMiDuR1aHWY0;@lbSB)K2 zeZ8L#gr$;UQu|LnE_HjpQtCS1bdjHMxzFsUE>*v=8Eh+bbYyf!l-|wUQ%HVrf=8c^ zYNXdbBO=d5U_N1l;xppX(CcN+cN$BPwG$b$}vPb5gw7+cvnhi76yK( zTsw9mHFZrVJK1m}{RcfRfvF!iSN~WZHH~P^SC#eTWI!w7zsW^iLazNO1Lt-Uh}w*f zG<5$T9QHwxfSE@fpDygeN{Q{Y&)Pk6Db=F{YIzo4pWxsIn)0VyI`7)eE=`RXDaUe<_AR;#|ad%Zz%xyvjg(R7@YJd!5+OKwmjwAU)S@c2g++ebZU_9jC?q&9#H8t<%P+fvbRp_S_gOO?mXc(Z9U*n;G^J$s zy*IS|9is0axD3%5kDUwPFde*aN0xAIly}9^{mk$ozqbg-;%B99QQ)R$XQ-QF7)aI6@$I)RQ) zc#J_kul!l)xYB^JrZ5;OLzuvo!k?9>=Z`UoaT93NYH=LySZ{TEQC?Bs*pF^{2e63& zNblpF4Y^;PKOPONe%`V|yi&*w^m_sRS;jUU;j+Z+1{B5OV>05jxEqMdSs9zLe_$0g z;J|Cl`}Up;K3e(l%V1+-=L+F(0h1{9tCkg-a`X3f_Z-HtGf_85NhIJ5hYr{addehD zkuo4ny)HZhgi5PPJ3cskbvF1dzCQu{2_Ns3Qh;g)L$sgWnp@0n?>%?y1SuTirM@du zJ_)fSXwTK+eq4WVd3%0gLu)^z$lxy8@^L)8_9En9AF`v)?QWN6PDHmy=whBSRkn?*HN z<*`m$dc+rw(k}Q2JWr>pt%WQn-x2TTAk)b3ttB$R+mmRps5zCYFEP=c^OKse8W)C& z9q4jrR6H-n$nTP|lDf)vRy>wL_?_d8mS zSo{9nmW5cuB1(bJwK(lcvwfx2I04|UjRq+9CiPl%>>?UkjfPN-F9wgoA?uPlt(JD_ zLx4Fyz4sD~wR7yfZ2_T#x74ou+ZOA+WY~VXq`>`XjxtG|XHKHwSV*j|CRE$s(8#eQ zY4Q|Fz>fD+BJXT5)^xPUOY$jnDviuYwR&hLZ*MgkJ6q+F0y3ROCDH%-Vk_%ttvQl1 zNj^hqv%7YpQ)Qd6CQx3QPhn80SRnc0HCu%ftauDC1j)=4k6@{yv(;$qkk-;dzcP~P z&o?BpPSAl^r*$x1&SO&6)N~a{@;!A6{6SYdo4%uOYfDnZVD$)$OAFhVcKlJfarBLw6!KBCpRS7%S&H zxTl}!HVZ8ksbli44^9290Td258L=n+8vtf-V!em%D6zjM?C(>zNcUfM6clW<2l{-9 zo5EQ<{&qcbu@>VK~)pebvx4SjI=+V2ZqJGoQKdL#8-UsERRj`U{| z83WmN%2yfxui^?OpcrBiQAX*k?&s;j2mAVC!osQ(?#s;0tYzI(8XV{qZAvqKojB@x zcDURh5U2EFy}u=ikBEoYGtyx%{E!?ZJN@D>^L;wF@TBkZhEP6qN1B3#Qocn?* zVPkk&LU3$2Ss@`5_rd@&j(E6ph@b6@N3f!dL*au|fjcq>$+5e9RO3K4UOZBT^w_SF zWNTTt*lDasHH1ti{h|9&XN%7pu>IxtR_K$(vzFKc`uFYiN8WP>wmv)dG(B0q>IaG# z5F?Sjd;i%y4B=~rwc5xShc7(2iOSRT(pvx31pXZF1SqCcnNW2bZVsyVk58(yz|v}` z@NeWK8R&ArNTN0<2Y|(KRGIf5;)-z}Y_t9ij~HsuT?3GWyW4j_k|c3*P;q?^I7lnH zc2+ee?-DnM&wn6KBC7wEMb!L-0oXNvgR4#ijKsy$s6 zapV4|oT7uH0<|~4`!V+OJA$kXnR*;`E()9$XpvVe zh0;DFaHs-6gjQwQYGVYtb|klMz1#Jdxmo8|Ydr)`J5s3g#n^ree+EmxB{~k)kS;f# z-TytwVW^678SH)lqQAA9g1*xW6xY1olKJ zR5yiJ2=CH32&kO?#6PlJ85BsIqL7RQvx+cOyT>t^M%J+scQaxgO5t5tpY zJgu1Le2XuC-P2mSozxvZ-vg6`=F+#|N^C0^UwY4YJa>mvwrBWMi%JtVpe)#efFwX{ zBd@gKxJ^)Ok++ANhrp~<)z^&A*^gOe1wX9 zpOJz6FhUCtAExQqVf4m^eSnhXha=cZ$5Aq^p7^eXZ4*%ktFnvjt{X^NN)zV-hdg=NwAGpoaBbzN89pbAaXT)?0!mh z%vTq_#=!57k0m`#s)m1k;VVqcy~#1mk>fnp@4cG)a9Iuaw)a-clK@vhsK3UDt&Rou zeG+$a^w1oQM>HZnJ~9fP9v7efSMQ0)xCD4qWJY`(99V7qU&H!W5s?|wj8tbd>=mWjHXLzUoqq{tEJGKQ_GsQD14AmKw@eq!|2ADSN4Eu((#my&r+p>FVocK*@EZJ_V9jC)HptHHtE%|JIeN;z~iiuHL4u z)@FZw6+miE&}D?kF;$XPG6|JDq8df7#(^k7{D2QKuQTb@T#>(A)VwUF(C~x=^!67) z;vsP;7_WCI)k{mU|Jq5b<MST&%vRrSxV4n zE@A8R#S|GowKSTF%LlyPj{6f-!LVE*U)XP3KJ)2|K?3S>)9&MVT|x-IIcu%V;l{v1 zTnV~nY}!lL)1;5#xtCXO^!EUai% zp}MK+_J8_T4GRsZ(q^C7X)7MsJCKqRSl2zp>aG%b-TaVD4>C}OsmYxlJck?Qg4EvS za2buu7RZBW8%XC{TWiP3M?6_N9YZ@5B zv3R;zaIDew)c8bnF+oYpZ1-~SXU$bqwfB7m?I$V*w*Hb$LipRV%)WpG89MAr#-N=- zzK8sbB>}XyQ>Ach_J{oP*7{Ax8yO$i6+1iXND3$pWxZQ=`_`WVhI+J=ysQmA+B=)q zksilultJ(sDX;G=OcNlolynD-!XD2QPk_w>PB+!zoC)&1PcUyeqGa1-=N4R~CA&nT zecEc_{_zLAJd251?L#e&D%;89NPEY_2wh_y+8u{7WIedNqOW17^#PL9I1W9! z$QPWrCaZP-EXf9?a1; z9~UwOzs#qFi><^UZ7OK+_;{{!1MBoo4+*c4iJP-AQXviWIg5V2kZ0DwRcoP=_Bu9J zNzWQS?B3e6Q*@LoiIr}5Y3BJW>xxHOIvH~d*kqV6%2V#6V&42d26x21blP6R9qBXV z_Z^w6_c+=$6IU#+-ZdaHoVZ)g>C**pKKEz!Re{v3D{1?O)1V8CovzH#Y>E-^Tv09| zsBVEo*IEZEfX-4;oe={~JJ5{v->`RBrYm`>T_V0Dc6+I2 zw)cm*dR^&u<*=VSc@%LuAmT52U@)UNH|m!QVPQKh9A*?r@*-Y8)sL7!eIOM?7v~vj zjhoreEGi-14^?RVp`Hq(0>p=>Zy3Az1bVvJ{Cru5EwYaWw$G^(nt`11z zj~(OHJ*THDzpt(-YO6jSPg)NWj_ZlggYFsaiR~30o*ObeM2ARrE?1&Ls>v2pr^b^| z>%$G35XsHvNdWQ6>C5W$%*|ZeYyeRs*5%IN;|j=;Sut*#%ok#yy?ssWJWbCkJR zs@KlKu_x~AL^8in&H#T>IY;r)zQPuF#1Ob|XA+u^> z0S-QH&n)%*18D27-%xHTP0b#s(G9-5{{`qB#Y6P zLh_}79gs78N-kRfhoy45V#KdQ5DEpM)C6u=K0%7yr-bd%6V|4X1T|UeECNPBpj=UW zsOW%^MWQj;4h(IwuNfLjE$$_f!7gxJKBQRr_+c8?FR=BnyiU65@|D<^fBN!Om(O|4 zYh;9N)AMZ3d(8!c#`z@q$0Tu+2#%GF4?e@ZFX}e*FjpRL4}0wc5UB?0x64cIDR&}T`6}D zExJ)AWygzukYied$EuoW zQa{d@CcGx4uH3zJ-t>l{ZI{@-uI|&)zH^H2@{>2UFHN9Vu(xlPMFn0A^?Z_)75MFW zF+?tUmU7AIWXg(uMemz?b)5eB<$|qQ$gt_dm#GKz1$T{B{3c&Ux={NCaep0uHpf*e zJ^AVzhq)s?GSQG*9wfWi+W&Z-e&@5U(XJWv+VyoWy=hgi+yE5@&1z7C%@ojxBQybe z!=70Tr3p`LW;E=bg~0WBi5HuGszzwovWm;ADrzIXp)EQv&+YOB_2V46S-+vxtn2la z>uX;6sx^&f4OA8RK!w4}QWF}}GX6|m^ArYz`r7*PqlUd&$oZ(4OjJSj_9i+KOw`~@ z<;D4iyd+tmV~4K;e|6c>91A0dyc(&62|AX@L&${$1&BKIP@ZbOho|>wiMq{PJEa;P zPpNK@2yL4XASkgfQL%BED5j3?0+r}HO47)2FOjja$-o6UP=60f3&GO{`{UBG@{b~beao9qMHUm z8Ws;X=cGow2*eg-ef|L#DJoW9BHjc_Q~OUONycTN zS)F?=nim{!zAWDAW5O5;IY}eC=!6Iy6}3XX5q5bQ^ch$7=%2sRq(Z}}=)ny&9S`VV zkOsOuM@XM)?BH zh#NWr{wRk#0{DFH=!h9ee=!wC1}-R~9Ri)5mx{J?NX6vkq+tNPx`AF>yuReFQO~J` z*F+#D+?aDyYnD{S8#)07Q>*)#ft4`?;XUuuYenmO-BsE}wb&uLz+ZIJsOMFpjWTLI zRF0_{pjH&D9sV9yQ1JUBN*$8lreOXVYR!_m7?y)UslhZDkB(V>)D%QuGKqxK{lwG2 zyPM26Z&ii|u3vX{V6?*5UY~bX{7|aWf){i6alU8$gk(Zn?sz(#N}z-7MWfu*Bn8*KMjGyf>N7|EcPa92|5C?4$fSvFwDHZNRJ za5K^$mO*Owv`O+MGlP(Q&+{MlKk+W^iN#)V^g+iWM^cY_@}N{A>V@iG(|@x{&%~x# zFb7>3u9O~6%O%uh97|S;H?T4sK{vJDiNLETCM+-Y|5!47+P1}Q2fY}Zmp_xS9iL??cp7L9K5@goMeZB zHXUc?^5(yX6X@(E?Z>^zn!Z4n)42}|bFBoNPUxki=~Q;(TD0q62e@^lAlo#}Jm9~6 zSOk##2boVS&1Nx(Fo=mDF;P9%FC^Z^Ge(%0B#a1Q(y#^^PHwJbS9?|{ z2SPB5VK;_rVNB!E&V0P$d3=t}5UK|x=J2Ax+5J`XSn zuK>O+mO7dF_8O@v^Me^hTj;ld>YLZdDo-^fuLkP*p5WnCHYK{Nl%ms;__^7GCRk7u z=C0y?j7nt~&zBiKsH@eVzU%=aFs~mhpqmD9U+>XW~T+a^1(?* z8qV9)7^~LHwI>YviuI2?n*#d3C$(7`>m?Ng=xAUcaXy1a-$i*n=hOJoS_! z%|{tg=e`L$tGrVq+Kt1?`CQ|KJ4n6MI7jxQW5b6!z0&;;9WkO5 znxzj_P#%_9I1~$-NamJjK-dtD--UnN)Y%{y>?0+Gri22~yikWL4nv-fR~$j;+uTJ| zh0hi5JB-6}hKk84s>*i0cvDo=B)SUxN!iOj^{8?0+e!X1hDs^%DyM7%Y#O7Yr+n%t z6Ir4cYK zS(^0p_+}ld_My2Wn_%K|F8~Y|4te&&FXY6(O~OqKu8;KOX~D0YxnQBXfkq}Wj0w9P ze=re!y~*2Zvd$al%_Djg(4{0K`oEuNho}A|)?3IMLhZod2nY=#fUvU&KyQ57oBy!! zzbR>RGg;~di6mC z5Y`+BYR{{_+5A_(rInxdtGa}q+7E5Sp8fw$PLHQ)7F={}Biyg}a zB}IksrX=v?{M7qV8>g zRL61h6o{ypqXT6Pijo*Mo`v}Z5n2Y(N@qv;wyP!qX+>^Z>T7q(HZ|gWyGKgxOk+F~K_UE(EI|JV z*GWpUAcP87D8!t*Bh38@Mg*Sn7eglP0r?IqaD!qMCayjK$NQ>)>IfiL7Z!f02T^(x zSVa>6;RIch3O+bdXua$c!TvwXHMI!BuX}A!OnulMjSJ{kMbWoM%LZ4^p^*DeS$Chc zy{o>~Tp%flc-5az*|E+fTm4f-D}zM6s=gC>pTE3vMIhJ9?`MU4A(9V;gaRZhxQ_3} zYKbxr`Dz~sqtDjP-Vk}q=?-Q?`*kE%Uqs;UK8o9e3PtY$)g;;s9}#mbSBO`)bbWqq z>@e?gY>MESLw(7i&m{>^X`XAu1muI;$2Bf(Vi;hTgMWACeBH3-A0-Jszy?L^YPP0l zUoji&Y)H)?C?$K9dt_!uXSciOb7LzeJyNpqHKcGSI0UiDzSQWXLoxK0RDebM$?pTS z&8Lj}BCR#CO99O1rgGf^b4d?`hMQ{^$^Q!lFgv_=KGF-8v> zvzX6oy>*5lk^l?>?pS}A`(RM+r+nZyg+YUOO1>W*Ma$)iwl#fqoUom6UG$EBw4;so ziGFsyPO98XztKpso&ZQq3^SGV_S$OpkEBs_gLt+9Bzd1@c`;JkP_E-a*aOB@>082u z#y+3c*P+@p6AAwaNcbld5H=}&dk6`vdmV~wBqm|r`C#Ucn%X;LN|c!-T3?$aCYlF0 z{_CPyTX)#VzY&NbXv8SkAnlniQEoGIzJ?Ct+-p-m`Ox(80AGE??nLtZpTLgtE%)FF zik?okPTadtu{QS$Zk#FByHyJ{Kse7A#;=#{gS+(m-Oat@Bhi`pU!1%d63*l3vDI&}wHMaa#VP`)X!%t;x1#1k z*3Wlh*v;bMu6y-tKZyLI72WtREVC1GrJn)xZV=M>5bt@&zpbbUfXfWO0&Ytlmnufr z^WF3l(1o!;}jb!XNmlOgt$pC0b zl>waW=^0j##!!?!_a8`qdSQgUdy<)LEGBtARF%V@@__)J0wC^NRQ6jmx48FTfOK=7 zX>g&psD8*{5yRsTc}K?hc_q;jE+C899mR2s)|y1Gvik?>#S{{CSpGK~s&@~6-&w(f z1el&MhqlG)pMbQ!(~1w;-|iS=*B44`xM^j*F!N)yzZoCgG+LTpqycX)R6e!30~kmH48VLNgDIpub&iC47!!wkG#8l4S@V<0xFnLDw6Cfn zNk}B8vl%Hzz;Q4H$wcJ8Z0|=O4F*8`*1@zSw`{#Wmz20yg_x%%|sAjTEhQC-afhxz|?bplXvdhlJo5HUDF@HwQoQTVet zM2_qLh5`j169d7bB!S}W;oQ>#gshiv6rhy5@3+@ngEZPNiUfDP;Boy77)okP*Op7@ z>HQB*8C>nD0w^WN{q&jxUR(6PEhm1hA)SV#nQ5*Z$Lm*|%jRqcueyq^bEf&D(yZpL zx)e{@4PA8=U*pJuR59!NrFX|UK6Tg3r`Z-gbm|GP?X$3Nl3bmZ3OEqjB%l98+($8a znQm8N=@(d^`I4bAMRx{mz(MuxP%{z0nvw1mo<@&N8a=p_kEX^BYI7z7kkxFfD(vc1 z0D}Q{1F*|kRyEj_DI6VD*)dS#-`g>m4!hywezt#K_aMYSNq(c@!;WzY&5lP4n)B&7 z`rFtz`jVI8LYpNX_{5dAwyWLd?yJOHArvD=4~FVT6IV1NQHWg@_5Y9KMS|w|B>bvriPpM`n0O!=_%k*v=DYHGkS90YoLmpOhni&m! zzD^4s#YZ`l{p}C?gb^%6^zjbD79uvHKH;dl;8pCM2uV{5ym9*?KchRui1#~DdcZd^5j zQ@$`;GLJuN1V|@kuPi>`aD@;b!ZDYzBH9((J9~lCgV5VuzA5;vyA_6SdVd`%{mOW< z$XToeL;hnDp8StdGVLv1pNo^3oBo53Y*p&5GlaXG5?s6kni>~OqSJpFiJz!Rp$kR=suPo_4}CAg~OCDf0h<#WI&?*=5eaJpn|t}J6IIA)AVAbVGwpQXSrEk1@f;O`dPxO+%nRM782l=;l!4t|vQtF zF~U>4?XxciL1Lry2qzVuA1w_Mu?tU&PZ7TIw_e@87II}7zq+i}&GP0A!c?Lu6W^<0 z=X=onL`5~l1feVa_Hq}Fc)8(%Hl7q6B|OF1KL276B!jD-_EN%fIXvppo*-V&SjNBB zxySoKGqLNmZW!fCv?y-^R74*0D#S9o`Ejofp5Tqg0s29AcU_v+iUkU1S851E*pu8- zz#GCNFv>dNlr7N(PeKRc)+iL_?Kh47gM0Ywi*C?-zSn?LL3LsyHd-w;Z*m3 za@2udqrqsgT?tLVgmCAw35@5{O5?BVeACWg6xP2tm-KdnTt6cAD1ju#@;(`;H2LIz zF1+X`now7P+>zpm9qYx`>MMa+XRFQDHfE2Pf@jy)oLHoF`cf3~1k_NKVAs|Gd z!bOZEl)!7fF7m1A_`Lp$os6pkUeLqM4A2bej}+EfayQ$VORDEraKn3HDr;N%$TOz@ z{>|?xKy<9HhY&0UfO2~Ky9qNZ+=4J#;8zI}^LWJY>0Soi5>KMY$Mm*mv={(?4TCH_y|XqDU=l&owB@4p`(!KF0tZbvGP#c)v~e$ z+Yqu1DQwn=Vz_BFa=|QHt5dv0%0sB@aTmU!P?qU5%E~f@j{gXV{-BnVv*D&CTX}|w zOAruzM^5fNDHNlV5FrK$m}fr#6OjNfBuJ{rlnNs*s%WUZ4$VTsmbjpfd-h5z_ADy? z7$F{_OGJfE%IFM(H)3kbi1?52VEy}T#wd(JHa|w&4vub)6F67~a@UV}P=e{VIFsWi zC+D~K*$j*lY5}ApTKDJAg^Z3)it+Q;UhRvW4DFx4d>Evs7<}Lc(CP^1+)88m$-0mZ z9nLA<$1oas2UO*(2b7AdPQkhvY1^zuAw#giSiJyD)%%XDgl1G< zPxJ^~6|sfp?|oG)0Q=4($mwPoj9~F@eG=3y7`aDBp~kphrY&=fEg|3v1!o5rlibUX zPy*eH7(jlHh5fMNW#|IQufr>)gL5w)(F^o1B)68bAoc)!^{)wz!@(4rVazE1PfckE zNCf4mUk|6w%}=u->Z$wy0xp|~FGX#LU#*4zLP|x-CD-MY$&})=(?Ve6!ryCh8}sJX zy0z~W-&H5wCQnRuPToR3J)d0>Dgi`dW!c}z`|Q2K37Fq))i)4VR;cxM4Aw_;K+)&7 zTYS0y`=~0!XB?Ox>JV?vR9_GoNjWD{`54Pwhzs~vBEk+3eVLt_Kii7(`e1wZa7TQN z3EaDO8xuHl<~G{MRG?Uf_{A&yVQ7LSyu#9~4BJ-Fe@sBBGYaul2B8F3 z#%IL*BOnB1{K)ODNbLx#MWyRA&faACJ6@H*`OI_FD~yY2GghJmv20oYzV!PFT$@}h zqKE+PuPZU52Ib+m?hgLezY^aVko2RrI%**z>9vQPcp0`dp8ZjE@=E_?s7FI!l}bOq=zUL zq73O_xd-}IXk=n7NWZDv@sW#&en4L+OmOV*2_rBARq)PjSlYqClikq^6#!!^9y)|mS)}c@r7c22Mc_1 zeBJ>N0mpDy?|6)h69u;Sph2Ux2fs(PLzXfDKYHS+fK$3zEiT~g3cK0c(kI_%z2Q)R z)Mdd=%kJ>d{#5=c1=K^*fNItIz{YJsK7^+DO(+Zog%x)S zQyFwBi)BdZr64ksDOE`8Az4HuTZr0A5>J{^=nN_=+eTy$#WJOI7`LkXvb|T@q1%WZ z6Guq8($JTG9->0X6L87&G4BpQ9^_4PV&||2IRJnL^%hXL|2u?w_Y*@p>P3KcLTmyQ ziumQSgE}e5G7d><)e%$HF{Bs%ATV`q0#KH7M=JNC?LyR328IIg5~sD^Vz-saV$w0F zc@bHi9IC_jcG^|K+hIZSaNa@A46-9{nv;QiYyy5NGJ}yBUc+GIx4%?FUNCNX7jFwL z95+ESt{TDl`5#S0;f_S0J}#K~3Pc03wey=$wI#;y^5?|2rHstN zMukhrEW(>InZA1=5yQ2Ul7$5-N7 zWf2HLVr?2588{}|T;JS?WFVQ%=H5;!ImledL^2XoKt&}3*BBWi%?&>lq(IrCU~*Y` z83gsFR+T-uXLl`wdX%8TUJ3<6*(wx1`T&x11AKEY=46n`8R-BSFujKS{@+qt65aoj|9vyO98qC%c18|D1=w zfgp_|1FV9=2C!5Ti_fpB2e8GdO!L>@v;@e;p|#_}0sw=?a8O*v-Zano?NFI-$7^nB zJ*Pjwhq;F!V(=q;?O#1p05sXerhD_)?h7(aMd5}1E z!saU*DVuk$KaZ-rr1Va)jzElOXO>;CLxzQe7VM}f4VojxK8k3W!PjuhPS=v`odewY zjj3q=#+Z1NSFRQK1N&})2O@Z#pl#+;A>1dA2-urK8%K=hJKrBHZK47t7~(%jOld9@mVnLv5pCxuI-2 z85+#{6$w&L#5>cp_j^6oK=G)Hs@{v*ZcR6M&hVY40OjP4{~Ag9o7-bXTB;=|o!u7< zt?w@{mF(gdPZmoRQ-{ozzyoaZ0Fhv*Rg{}6m1boabkpTkjVf9~ucxXtXTWR>p;cvB zspLXv1x4=a=7I9lj-64P^f+9Q4-sA0lH_rIo1BUyH53`a+^#vKHsx_>iSbwc?%w90 zLQRvSA3*-eZ6SWz#cRXDC|qp?ADt9evvU4a<{7alU`7Vn-dzaWhg?qak6UC;&Q+MhPo=A7#Maw zx4e+2s5nnE&ut{a5MS9l^O=t?f_`T+JmR01{yYKmf>p-J5N z6)$wYgSh80T$B%|?rH$7V-v~sQMG)PQ@hQe*>>Q*v9?f>0UG~hAX|GsUiH|q_ib?V z7yUcp7UeruuIl(dINU?ZB=F1DtjXQ)1nYa89(Ntg5ei(Gst)Y!`YJIeKP&Q1S0>~? z{sm+Cc-jC+)n#bFj$U#-QYen{7%fupAY>Z@@>e8Qn&dZz@)bOep7ybiH6Am6FctRc zbxc3)HKYA=@&qzKbP=#|(@vz_R#1p(CN75yOQOPwqmrzGd2K56hGf9@DP{5&#ei;z-7sFq-vE?Bj}u_XT)CR(UrK ziWu^?gJiXOnJjB#h#CeZ-jGDko%MFy%D(ePMgg}wm!>EXAMFfc_2d?n7l;qF2fOH| zn|QowqfS3z}rJcW&)v}Sh+NfV|CE5jSfin+Q~r(#$Mke-LoVue<=sqJ+}WxuhU|f zWI)oNB^!_dhc6XR)7Y|Im3dO$xA8yMHYEJQ{W?!lDce=f1>3#j&LBXEK*Fzeb&0Qe z-{h7GW_O|HfpgzoLK^`%WnFB!35qL@SGz^j)x2?WPA_DGS`hIC1Y8;px;U;xKi7c> z4a7H6fs4H;yg{3P__)GOg}x{|UwiF#fr@&Jy52tKv&hW2I6NHh z(8~lazPX1EF`9|??^0oBX0P$3z7E-N0 z#5K+3eBB3V#V7^{cmh&TF?PP;g#q~VCRe?vO7ei?<6`k}_=9^ZA}V7sMMWhTc*7F5 zIqmEz9^y5cd57g;GbM0e@Z6?(bonm{_`TImyP&24UD4nGwva~r+JOmXh*Iff+?w)I zXnMNA_sY7Yx7*$}vy=8D%g+*~FrJD0@*^T(dXfAJKIh)EsH8IPwLoM97u zp5Ak+`r8TMro+9wEu|U|8^~z9YMDDkYm}|(xs4i4I3M}iev6}oIcqTJ3bYGA^c9^* z|FYD_c~~AT-2IeC9^s_TK&#W8A&&64wt80&m6}1p)RNhJ0iVPFrgb{NG9?XcuQq&Z zn6Wi{cN&h5jn9l6^th)Uo0*yGO8*PQE+s8(gu-P zSq%+?p&_9m1B`~~jld%+2tPd=cvhoyw!D2{uepR>UB-ohglnH7)iZsR$n+?TiNq4{ z`D}r7vB(X&sG^C56%;a%nJERdGP*OATiMDf)9K)rhT6oqTIeN(rbtp5g&_q$PA7koRX12`jdu}0p$+^Xw0aL*!Ya- z0#z<}7?A{B4K4yfgw+K5TbNh@G9FgCLK8#V#=!_sjKYkk1=Na!de=Z>-X&$k4upDy zcns#DDO9?PeMx5>CzBF$6&bq#d~$1%lS65HJu{UOgUrCjEQs+*AfEr&SUuGf8IeZ8 z7|AR?kH_LyNh-jy0Ky4(B&!m|cFZxbprR8rB%&>F_&TJdIC|2(6N$oO$YqG71WvlB zB9+eu%0A1Bwc@OyK)S)cS=tO~n}vXFeIF15_%LRKQfzjicROjT_OGIU&H_MXnRdLo zycVn9@2u@{rWcz>86U;~n6g5*GJwR)1y~bS$H!wS5*R>EZwBjb`jgU++X_jC&ob|= z6)tLk(1V9>kv?wwy!1{ws}0OYuI}6G2(Vbg{%DEqDZX^|q2v}Wuf#iwwWs+Dd~fb< zehv)$=qqu!BvK4h+ivY~qjmdNrSh;h#6EELo~Exby-_tbjj)Kxe8C|>V8Y6ic#>|* zMvuzq+hdG3Mh7N}fyo(Jg7gzdpEljv`V=p3z(xC83%7S&DsJg$%Wp4^%)mL-^IX_! zN{OXF zx=+#)K=N1F;^9HxdYVV?CBgs>9;E5@)RQiLsJW>`y+fR0;TcL596k z4F;qaxdEhC!HsN^xf)ebcxP1&08#*DH_@DPb_(MAJ;OQBc(++hS{4)l=?Pq2u|??D zQnsCqDko>(TG^XjosSaHW@e0mw;yo_xPUKre7_QPR1wSk z9yB8eSD4Nq`5c)JF3E9UnjX>c7O=(E?wPT*VZ$u?m`w(t)$;EXERabcC{s%COc~;w z>;G+wKQoA*@5X*Q&WjvF&7mYDn!yNThPuOahO%r#H{&Z{fq5h|k0Ikr&|pHhn973Z z2>hRZ2I4n|;wQCBatqD7amGgpK0eNk+BCrNLieL2R!x7pYdd?K)Vf_brx1J%@|ZtP zHL8dwZx5PrP)$KFWGP84e<1LZ|F65YL>c3>95kOFAKK^N%hHaWUw*v!eOl-y>trGL za>{4eYeJyZTdB2j$0Dt_V04WLdT6$$70>F0>B(uAf;8$Tt(DFIt1(37M2H;MP|a!R zYEI$~GvDl(W|<*k<^Yl7=Hahly81PsZ2dmBF!{|)W0A5aS_F_cVxR(lI3E-9$SwHkJ(9>qon zg{2rn|L3sbE+=^plxO^)R}qf8kTs&ML$!FzShOCS3~dAmB$tIrYiJKU5cJ$X`K$Fg zbAoqwPLjWyBfz-P1+cI>h_3@Jzc`uc7HQbVck;!WBum#4CzgnixoLGnlK^b9Wt_$ANJZ`4lZoob04Gv;7I9nT5rt)boLl#T1$i7ulGtO|s}?032Ns=@ zEonnh)doTe;z+v?9F<{`JUXak6Ad@UST;V5Ax`t8Q@j%sv7iCoh55Ue)@(Jh+mr!a z9|FqoMIUu4m-UMptAfR79M*9Ow3430L6=-ZHL9n~LVFsJ@45h@IL&k`I_nPOX|^yA zuAP}Wg_NUMH%oxECD`){Q_Bp;E<(77wcFylb5`SqHd5;4iM}(2P9ct#Ec0Pg9Sy)$ zBMztV3WJbLqVXvTL#dP)w)vtS3kCnT0J9ZwlrjrqpCxiv6^GMUY|PCw(-yxvEE5#K zxPIsu3yv}dlKy0T2h ze4lC!crG4t5U-6LWzd-zL2bzPz%WKF(C12f(Nye$l0B{Os&0ob``~$^PIG4eb>H3KuEVcf(&Zo<0ffo zyTwj`f0iCya*e@|0o}HDJ|dco_Ai{Al6_1||C88$MAUbL%U-kzj2-TvttBEit!~4LI;#<4`cRgI08< z)y!tDY@>K~XsdeN=1$EW7wy|Rfug13-eH_^lgyQdffxybos=27qzXx9kpNqK_;ntVbn?iif z7Ox2bZxkS~>B}OyZOucC&VzMml&z+%rtz?Ao(T;`;s%yRZBLyG9BY5$Y2kQifUH** z6?6O|vZ<4~rF~w!InzCu$yXleAp{E{eL%6Il10 zwus)#PPM1YZ*vRi!=ai>yO8~p_4F!3mdK@E{Sya^;RN5I(T8HuYyZijSq^nMefkw@ z@{~MY0l`=A3psud9b$n+1``&$T|z|+Dssragqgo>Bg(QI!6vGj)dBFN_?BL|nnw`) zrLxuEH{d%)T0^Y$6hqa_m1uS{bAKx^kV+(3tZ1Q98y0=5#icRK9nR?#N;~Oas=cdz z#2d27zC-Q3H5SSIz!$4)LgpKnk@fRjy_j4R)nOq|djt8zl$8niv-tJq8r-3S6~hK z_o!LKlD^1Fw(5pIF=_&>(?h`;J0_HT>%~fuk(Q5owxWEOK_FBM%{!krW!V!{VAc~B zb+~--8;?VMpHT$di){!=*e-m&>0Xo*W`MDwb|m| zp}^@8o3f?w&!tBb2l(B*K^`@BXN=O(*q(cNpWVBZHpA3kc&3HM#;VKmujNw= zhq~QN2B#|mWk#pHN}M(TX!dGxVi2&&^qMHVm1x92l@Co+?yohI!O4wS6xx2-AnLlq zdnWyJIRfj3W$Zd9LHwNCJbsV-RhK#Hc>e5!Mlc&xb+P`5V(<|&MYHh}boV)WHq}E1 zHX?)~TPCc_P!*ZWSfr80?HL}Y9>*M^_LuT)M{z8lyXc)f=7}q1f?y23LfG=cpWo>J zuC23Jmp_l@BH;tG1WzsPZE-T|=$|r?Ek2j~Ou$c!KY5lCBD35q$%11EoN?`+430E{ zTV~ya)Fg4OgBjzfBqjZJvYkN8It|k5sb5=i>qcFd z!&JW4MKEmkO$9!Y9OopK?Jl5}s(d`EgFCA_IC0hfZL!@y=>9-8q2srgPG^+s7i_wB z{Cf`Jeo5yMmW~sWK8rEj%~1jvqf{&XPETs#s44=ntMP}1KRRwcAfH-w39yT5MOp7X z?0EE+Z`g%#9!8G24+f1#FwE{JAJ>|z$k)z0F>888X1)vKH}Auit9p1^-W52Hr#;?j zM>c!h6Gv})stJ#tDOCR+`4rkCUoonK(@`B<71jO;9QUuA;Ad?+uGW#RwoQ6fF{f3< z=ui4b8!LlaqUw`HF0Yhr-UsB`ZlH*rbJKbFCf8VvGFoM#t6jF#|xiKi| z@wts=#3QXwlpUmx&DLwILMV$y70om}NR&Yvd&eLqF@LzRSuc2LqADU8dj*IhF+UHp z@FP*eoLMMYL<_TQfKV101~tLtM}0RzfEYp&mkH+=AtY(Y7i+ zBa!-ZoEHyw=wwr*P9;)j&Un8$SAT`wHFk59RZ162*G59>NX|r#*WSik<;%i=|BE_S zK;h#!8=xq5SL);f3S3P%CU^Go>8oDd0=DJ%AK$Hde@G#x4dk6XpcDqZd~@;9b^fz0 zE4|c%{TlK@%o3~eeFE6KT@ZMGwKy!c??pFNY0$UtN9vxHEFy`MjZgNzeZQP>zk5|X z=W&3LPF7Eo}$GJMFW66ZYvwatHJx#rPfBfA$#hZb$}J8~GK&=47(LJ|0ER#GCg;nK(+}-p zjKx&Dj1q$HU9}x=>)87D;mB!}It=p@U=V~7WfH|vlY?VfcTD!Tn-QPsOX|-p^i=oL zSu$fT*<&=~GF$Qsg;@)i?)zQ13@-d~Hk3aF2NFuDfJ#LhDFmhG{fcN1M0}NO2?MhV z+)MIZzf5n4E}`0rZib6&+k`Y83Uv9X>?`ESs(3YaUT>p-q0ka^EPwqs0>T+bSDw!9iO&O9!&&BNvHT_4b3cQqckJ;M+?8YQsriChPUztiZGLju zGm&hPT`67xWcz&D#9!Y3d=*tZO^r07DKiV!r4Z24?MRW_OHYJn|MVN;N(h~768^OI zoKImyzitUOt++kcZVo>-W07Y2wyEym!B_A9YWN=2ykdK7^ubTQg-46NP_g`~Sa^3| zGiyZ3?B`C=X02JW2=lF|hq$2d`?f#{k_!tfH#^T%A;V_1@0q<=EC?hJWL_dNKW|Yq z`5am&ZOgHoOUwJB_44sUL00_s%A7fmj(13Y_#|b@+FeO`x6ec2A;#uNi+DwguiI&X z98aXl*UF*Mw>@lIbaO8jZgJte>ArhYncRV@n0(d8x~VY4$p|5=z-iAr{Emf9Ut9Wz zZgVQ_btomDc&*>ZAFy&xf?+Pnlwj`U;BVsC!~QPG&=IF*WD!t54Z?~Ajv0OPdvDOT z$n(%(zV;4MneSnf@L>98`Qb4V|H%{h>M+-RJ;{L0O}v?SgK5)oe=35-Sap~jDH+$? z6c06dJc7q<*@{CqI^%P3)?mc8C!K(n=UyJt4^ook$jMC zZ}3U0gQIDm!usXi-8?c=Q+0ga<;4@roqPW+U3?kFigJm96~9GVa=GTPD>lC6!0w=@ z;W=E_xk58sX9)@Iau>_7vfqZo-r{=oJ5MyHtRth0A1)pbJB(;yb;@I{ZQbvl83XkS z8Z9%P+nkV<2A>P(7HpgQn@&8RG!3{5IUB(BUGQ=EmCl8_S9`OFdXhw+SlrDeweyx_ zjg8n&;<|w4@7bFw7y}XdLk13Mu5bKn4OT!Y$($>w-MsF?o$gWkA*}Axdwv5)UdP!6 z@g_Q%Dr|k7@BT1gd&EP_Arlf3h7XTi+eqna>Fy>U#v6SF=e@Td_hP9d4^js=R6V_? zEfb}r{cFK!8>>~_ydDi?skpE!CG4sa`V;Kgho4Mg*UzE_%UVz6RHMF%wjgsl3VC z6Zonh5^P6|*fnLZL1y5dfwu9MdWac(%kPV}hEB1!QYFS7vp;a~pr{m}tn^?+y z+b-StDFh<2+X&SoCdel7O8gBk9u_=uJ9qeY?=2vvGHtgesjERGjK!m3J&@oll9Y<@ zL`-G%G|uf^Kz_T4@P^h&-R%pZ(DyOefW>;^9=OxEth@FebCGC2^HoN9d2Sz0eH$fN z^E8}VdeYe0(OK>y7cOu(S_2sv0*4mS2(i~s3z>4lqEQrD254UAL>stx!oUN3#;r*= ztbWR@k~Eq`hT$>@?j+$!fr8pY!?Dx@KDj^%@>9*s980aoI4?Ej%jU}cQ;|X&5g}O< zgKMXQDIR-WUnxGW50Z*G4<4NDtWS@G@WoH!qJa(c1N|}T=KbZJ7N=;Pg_`Jv`s(ML zOQ^Z8J??(476uuoyYo@?-;gk+D+DKXRKp&T+3_vILf>j6DqxV&{cfK|bPaG(yKs|E z>c)>4#;)TbdXmlCtvv(!u(asC;ll|vvWj&ueNQ=SMhDqM+MH$c?l6jrS83vyb~deA zzkK$Y<(Jt6A;`AKkUHa15yoUUoHy2b6V9C1*I zJj2O&)5F%zdg(E4d)0Ey|2D6g=N9}dIhZRtxWNXl;~`j4KfI;7%jrEn%u zR5I5q$12*iw7IbgI{YiJQ*wbgW+S?tTjdTl#rtkOIZu%tkI_+wj)~PV~xXh*< z6K^VJbAIM6nX1BvhS@0LVOH`mmifMcncDt^5dGcpFp&oCs<5DrYS~ADIQxy_T__D% z4L~iuIyIUTu{=qifzuB7mXy8A1m&Z`aJEs}jD?-2B$af1wDNdlM@Ha1`7|d zw(3e`2SViy@1p33Q2!5yUE%l-c5hHYV^2h=uV12S)$&0RSgzXHaPNBL_Ra&4)H;3RX>zj9*EfVMtF9Ebm-{TE~ID^(` zaj@m5!_eb(WFoH#;OP@splkA<)+)~T&TpTZk&4Q1cNrS@(NihK2C}ySh!LaVEDSb- zNLxIr7)zQ;Iu%BIqkXO>SnO>-gzOoNLNdL+LJ;2N)^+bJ3m&5smg{KFL?aipD9mVa z!;lY3-`qO03ww#GZy4%W%j#H_>6)8+LCsQ6U2%UA%zMNAd(&NnRg7>kb}lT)GyU@q|;dpb%1|p zjyF8EZLI41NO@fX+&A3vwrsyn!3BTVBB4f-%TK%FBZY>!Pg{9=^Bpn4g$N1bNT~&o zIPm>ZIc=zM2>sMPfO}+qx_mTHv9ql+8yP-(bl}P~-OwxriyOTH=+3olX@P2a4p#Rf zoTbbA8$4&|?dKGfxZL5Vy!LF_2QM@AoZk57Df~>JeT}3jJM@*edVZOj%R`_{+mACY zlz6V;_t(lYYXIPz4^M;K{Y5;0Az~Bp=-3O~{F2o7qiDW-^rlzl>t%Wz&^ zkLE?j-J)e=X0-{XK%}7L#Q{nFWeLWb6f-O`<{Gfz8 zGz39C1*`elv>r5Cdp@b*G`bPw7!Lk56oePBYZ!fBEL9aN!!1R^LZAvfrvVWtvQoG<-FqA$j)EG&&SUS7$LG>E)@t={B3j2Dtf_{Snv2(gTM@d0NM@g2~bKH-HfkD zQ_JwW2x2RwT$N4moE|7fsjDb~rp&H0pyJ`4IWKkVzl7hNTdT*`oexNx5hL|iNA+v7NP?6@VlXtZxivllr>N$T_X8`d zoyI5Y%FXo;vZh8@^8EaV_({&Qr^Wkq{j|2BXj#4yg`%-L%+%Q)s`x)-(s6<9L%sNA zi9i5<25>%3ZlegpiT5w3;@yi{wesJG>03bpj2>{zInHH@gxSlmg29)%uVnq zh%TO!74inZ@3Chk1JwL#_Ok?F5Ru2Wo$7ZQ=XBgZk0ObbrNe($+yw=TA)~+HO`vtF zKIybNCwJG3G2drz6)gkb9qGeRhq#4MQ_5{BL^A(?q^4x5d^E>?KQV*I$G_KL;wP*H zR*xhKo|-LTelTs+*%;o|>OnJ<{c(B9s3aTK1`P>mdPK!O%VoC*V>&Gu-D`tQgKjU) z#O&mQQDLX;jk!Wt%>dprVdxLs7X?^pIkZltzXvvi6$YXdOc)4|#E>+9Gx)OKNCZR{ zG$n@WOGnkFLsZ|abcVGY*jd><>C#9NmcPe%@%9=^@lNI=th2)5NT2 zLHbpd9UAAEWVik^f8&p@pXAwDVr*Jg-+2Eu1*lWlzgACTM zEl0YF#3m7xXkUdrwgGXx2sWWIVGg96I%<+Do-fWi4I}H_j1seWcS@^lT7ORqaz$_A zue2c6<&FBV@{}7Y_X_*Q(<{0Dil+UUap^Nyl>eK_q@8<}d-#cr(;Aw#OU{=BVhgKh z8a6r1UK#-pNE!){8f;L+!H{B|V5k)$p&SWH!xVE>S#LHk5$FI)C4YKx{806m)-V1| zMvR-EpI;GjY1JcXs`dB<8`C1tq?hx<_-ppv;w92nW*B}dV&DuLG)NV;Ku)E0GE?*` z$k@H6Ux|Hl`WDH!-dSV+D{VBEYIflWco*cDzfi+`YZp7)R$_E8F6LBzeMkmZ*`-+A zEjQh&>YH;i8m0U%I5kqzmCsV~yk!PNFiszOwk`l;w0nnvuF#g=ms(u&vVJ&35zE=bJ95lrm330d3B zXsD*=`X&gI8)Z%(%-%*%xhfy`ML(jJLf3BJv*y3o?qQl@MqW=&!#%T`S|nHpYFfJu zND>@TvC2=DAEp$JJ>jbCD>~u;y@@DgJj(UzhJQ;7UY8qIsvxwGlZcWkk-5$wzqUng ze5${7L`|BH72T>Y^wA5{TQt(xTZ}Zq?zG!z*Nn*F6B_1WRD3iE2cJarFbfGO8b=Eq!3{$6&iotRZ*nl3J(Fdp;d`N1J^Z=M6)T}+pYu?-(=0@NTf zccYmJn~E}N)uT-HyfT&(QXN=UXy%ZGW=!719HWjr+b1)<@V)>5rn-z~X5P7)+W~6o zcsIrMm|{9^S|V*qg8G|_N7awRbK(13*nRoKYME9&2*irV#=z&3_EzHc(B!5JgVx-p zFovLIJic5H0$A9Ae62gk>j;8)`i$gr&9LhE%fYEsx@8N8CsnhM%6rVRHNe5Dr_V7U zsFE6}Mc&62Pail~u@ikRef z_9Tqk!_ckzOA@o*E;GFr{85huu)`bmNojcv&gAjt_0Xo!nO}`*tltgR#yhu2Jnj=; z#I#|LzDZ^)Om7m@=R{X51JS6r*-Ei%+^Wg8X4H*+dj5=BC*peG}pz>I626 zD+DG^1Q>V3fO?C5^R9lTKSutR4DQcnN?~OU?++2+LX~+DgCEf}G9>!bP{HB1CS@*Q zT_4X96v48g*DX=KfzpNu+O@=}`~kkrVc z;xh@u-5f_#oI%;(@<~6gZq!+ubY&-s5Ay9;b+|=F<4TCQndA5~60BuS7EmkHI*LeL zqQK3v=3MA`x)!SuVl?~gs{gVbT$R4m2@15|np=sPqELw+nj)IW>r9r|dFjj7u0O$W z`!Ev={c=+lxfUlY@eJb9(DNR*3$)k-RB+eLv~Sa9Af4;QItmekH6Y8|$GXW%n~s(!n6 z`$h+<#u?HfT$mrNk%H|2!_lz+N8}#`O}M~x%0Oe=c8xF?;7Ae>qGX7twv;a2TugRX zuH#{+d1e@g-)Nhz%$#PYJnWuexc)jj$Bo?vVzFgM7H9AnVCCUXc?6}Bfp#M2$H#^GKz{JwVa ze#CniQaFrR?t3yCXLH14p)Xc+if60sBz$G%ZbIq!H%WD*g%c<#HhzaOFuZZ1i({_Z zAgM{7JF%q_bk}0a#6R4YH~MwVcJ470lx2`@q?OslxD=E}l9JCw5i;6H;fUoo!0P&g z=$s?ggncr4>7W*RD)A9yo~+6Kl%;7ogp*)YV(hpCvR4Tb;ER9&1VgBbqlc0p^qy4x z<4=YF-w+*F3>09H8xC}7fW4(#)D}N zu(-T(G^Qq@Sk$o)t7juAm*kv3#dj-ZlTq|i9p#wvYwI5lrHzF+Q^>z}Xu42(n4j_b zi=pBHafp6W)^qu6xsoESvz%^`%xDE$)OF&xsxBB;W|YQ#g9DfZoIKm9fr~dOFz?mI zf^KU?^4);|S`a~^)FIPJHWSGP_5G&T5V1WJTKzBqu;mDf?_QX45!|UB%weE0VTxpf zB5YoV*;&GqGn}9e2HkV9b7-ieUUpi?td>=zi!+N8s}rX819I9XVjg3%_=@KPiXND+ zmlf{!^ErkPIEW|QR`M-q(KL`%qitqBFxZqO?qko|%1NSGi_+ zq5d^v4Rbse7+uRA_=3q{t3-8QnTs4M5JDoEu8a&R2~Q?m zk0CPV(cv{Ml$CU+4XVdqXDGC~eyi%oid*XB_=bbRcAT~MIyGeoCT+I|l+r)92yNJs zATL2af^C>Al?f9jmWxg`N?2}wBQx0e>Z-ch8nHhwMvJ597kzzT4~$Zq9$ufi0dm(y zTh7Di3e%}qCQLZEPI#Yikz&|5sXQj^8uzZR3arcd<*g52A^|yEh_grJySiQ?;8C2u zraT4Jo&mTQdcoRe!X0$7317K$!xaUmhSNEDrfq5V7iU&)yl1ndHUbDH&WV)>U#_#R z59_U}GHeg9Un%rQX)RT&(lT^L@i3cI3b6u7t49K|l*n(JQjo};voKX+AM`Wc5n}*H zPf)oYeo_pW0m2dUoafqyfBHBe&_r8{%f@m+Dc&owpZrE;G-6GM?=RI~4d122n@&HY zA~SygIXaPqsd?k)?*Kv4(%=7{!-Ve8l6Xfa;F*inZz~g)##Kg8iTV?h%YO(S+F)b> z&!kHOX}1`z&}BQrV_(nr4rqgydfmvE5%7Ez+{C)2cc*g&OvNoySMl+LAfPXw85Qa^ zDua7yvu+ngS)8(9iBrncgkQd5--4rqn$6_LiNV|ux@&&MBUKzCJL*eNVSj$~zG6?S zaOPQs>G#Ga8t)!om{i22<+U(I2;e}B(%HPJ2QXP={Ll2SzYqm7*v!b?`wb?u5;1YS zL~qV4Ac&J7h&eM7%##3i(4#Xaka6&t)Rk2*fjCT}iwDZ!>cKmcN7Y%FkiX!)AY(BZ z#F~Q#G!1b`h{`_~>ZQ*h@j3vAA*(#>gW|qbEBCMXBA&lW2O z+2AI-uhn~jvay|Gu-ITW)l`{@8~)@=+UimLA}T6-h^-JL!ghm}TRJNZGi4<7Dgm$3 z-aqG^&T8cOIjo#=;)Gz~d^F>JmpqGSLpm2gXHYg4EAgC_2)SsEJkLx`Y% z|3!B3rrCIj?gAol6ScroEuxJ^3-7B=QwBDwy)mzW0-b*1OoB!#SZ9zT94KJWe1%TW!_)(z+@9O?ak4O5=M0Z%g~y=eWg~|7Yb@o?$ZWFD2V-K}4pU?~LE~dOicB9V(-7LOwHp z{T|_BT=_sRKrujE1U8Mn_hgf*-qexrjie@lsuc&UnQp&1XkMi`29b2x>EU`UAB0P+ z0E22H4gjh>Vi|!H-2;LpzmEuQRNH2!2N|xShXFF)6xOEF^>f%) z&lCx%DC>+}CdVP3KSUw3^LsQPfY{kTZi$@ug>N+C2;l{Nfy4qq z5DFT#I>sFGy-*a=AJjo^kM_&I%2q<~&|%2ata z^_B3svQ9{~F5;A1#_+v}8s2*9AV{03&Bd)0F}|EO(4<~q^XTjz%t^Wqy?d*Z&Z)ma zTaJTy&>4@~@uhvrS9)3IEfA09h~o7V=Tkjl_TtDcFG+iY^pmDzz;g7z%OUv>u5?fN zMQkykjbEsrKn%H0@eX!Q&WGUWhqfZ91ZwZdk)G^vK>7k$!j%C6M6K($ED4%Q?cQ!R zXcUY2J3{?f#S7|JCiUVTL!Oz7rB_`s7+)tA5JGC|66{3vQ{)q5lU!j%uF*5pUDkoQv z^9QwhvtW5IGIG+G4*{78__3H!`*(g!7a|7n@7PUr8|^EcEPR&y5RJk20bs_0n5Mi7 z23HtMTnj)_ZD=(dg0jR9DT_^Rij&7-aUW%x`QrvoSgZbmT!Cug7Y22#fWPa51@{{Ddq0lP~Qfs=ne1? zqiM5RYlB!YoPp>b!oznqH&#@eblIDM>0R#|BM?bOqRF>vgS0x#A&|gIrubn!PH^By z^l?w{-sfwRn;V6=JLj!^jV+tp6a-mllDhi+4LM8)ng58Cn2Ih%TN8C)YPZwM6(zYU_g@iRF0-c%Hq5Wq>E z9I7JXx(6o@(Ymc$-PLt71Fj@R$4{jtN1jxA2Q5qp9qz{+Bd)*oI>Qx+$YWi85L*+! zljds^0|Ie7VO5j_byeQnR)UKT@sH9r@#rpc?Zex~+ig({;h_58N-V;ri3Hk}B(3`f zsxjG6wRERCR_ib07@2im)nyDW zyK^C({#?MvjNK!8?OCvx&NVX~(9T0~7Hh_BgHtHIvrKF=7LSryUpn!xRUdN}V|pVo zv-!=z9j(HyZw3Qk`aLXcm9zKI zuoT+~u({*r9ucEl|H$yJcos?FM%jI0f>OOb0tb?ua)BFAPuFuhg!G(;Y)jFSXmlCO z!!=WfZaTfI*x&}IRwzn%^ionyl!?pGWBep4>FunC0WTZP1waA!V>~1K7n;;v8!6>ScPmPv_ zv1l5)$v8tdzV^>qvzYlchqfoS%tA(O`L$)i6s9^01h#j>kj`BpeC9)h8|1N~)r^8_ zgNpp;HGTmu0+F9yR!^_Ec)XlM=-$pY2jx5YXZ@&6;74$pleGxwCyRY&eoC zC$Ff~t^rI!-{#nhgj>`nq}MWnr%WN5!Z2Z%IL<`n7vdGxt zilAn@r|oYsZ|97WVY_2RotGwA$7VEm$EZgQoZS-HBJrcSD7Xe-1Z0hch&RQy!(aKV z#|ZAIYq%~yzgd+9^zZm;MGXSD6ur}8xUq?*ZmRi*pe}3T^~~RmtvEZoB%il}aHA5^ zGs;ESbgP+3+b$;`9Pj1dq`izp9>-4S!cmB9usaQErY1OSgzGobL+?h81WZd#d1l9< zr;m4ZwCFuLt*pTjgjo5M^1OWyU(4EVn=}_nz^u)RQ;xrrfO01|?vEx2flG*HDjzwL zzmzuoEak&=tEyz9oO#!$>R8%?N~Vf-=;MUQC8}gUW~v(}>}K6sCniYi_588H46Vm6 zOxPy<^RT%4$8+u@xR1v;N-E>p_XI`q&@8IL9WFtnfjt z;;|&B%s(aHx4nA%V4O`pAO&TybQR?z2l0Pn1b8Q>-Ia``^1ywQqnyh21pgY5g64~U z(tAhf32eajKDQ@jf|Z=&1WTAmv2$wbv>_&{oQOM^Y5E!M8n3njjl=SlreD0134nH- zOpnHJLOc4)7iew|i}lZp23)}Bn#Z$IBEG15Qnn7mmngwnao!uvJX)p*rXN;=;=Bw^ z;hJR>9e(2~T@B!Nt-$?-2H}=(h-g#Ou?3NT=wbdVoY+52dKjof(82BCx%{X{lO@CM zJ*OK<8q%V|fM|b8**iMody%Tku+&{h0tQA%B-OiJT;CNE9zBw_jM!Ri{d;?CniLsb zyB`~I;?7RAqUjrD`FJDLbY~%%I|>wpJ>ePLIDdv;k)ErE$vDPj?M=n&C%kD{V1>gK z8OomQYt?N5Fq$qN`MB1KY@IG+>_u>^*UOk0q7Jxtx;Eahl-<`t z=XH2)8q56_OV+dJooUjH3h9-B)PB-75{gSD{K#+1AkOmYG-!5CNvCJd(f97FR&{R_ zNG*-v)nRs_?Rgy_iN1)wcWPfo_9?co z^TxvT=B@}QdRjyU3ChJG9;2M-ks?Y0tU}yjMRTg$w9%F;)T0OOn+AxV>au-56<79$o}}V&2Mnzj3;mgL#X3v&rXi zUbYgEz%%B5#yM4~rQFGS%R~(W6A%?)c8_V;udpADma8l}?{LMV*w9-GPz!$EmuTup z7!T3UBEt>Zf*9e8Z zxkE}!x=q7F)P!~U(a$B!Rtl1g5m2WGH+olRIS#r{14~4$0L-S0KeS zd%GQLm{&BS+)b~XbSf|Qo~-K7wA5JCqrw**%D`u4B}_x91spbnx!f{VjUev4Rmv`C zj>+vs?NOLMkHxWQxHyu#>E&=?H5NgA%F2TrX}ZV6&s@Z@??xhJmY#!{1g#w>2&1ae zdbBx~>3uVnz7xbs`7kIISAnz6f)uvt?0d4bzaq5;afuqVz^}eP9r?Y}nwwEC(X9IG zgCRg7_}*)++=%jIoE)nP&SGlTxyG=8y!&#!feHJjQ`OfG1=Lqc7Ffz|c8?*xA?1WO z-pBOdQ|eQ)r~@!o&Hk++rF}I_?{rej!3F)c`qIGizPWSknh_!#IrV7oYt=qh zk>k*y4g&1&Zzi8KpIs9x8P>NXYLvw?4aq58LL=7v^=s(mbPnkKZ#hu$&DQ8Irp0Jf zGWn@n!liXdF*4Jd?#Q|W79k5`JZGwM%hXb~+M~y#SG!j`cY?;{SdEv9{+>W&?WCFw zb8dBq9Xfe)`4A{w=JRHk^e6Ktj0hk^_;Y>(BX1hDj9VC2m!M$`E&PipW)eLE^<;5P zjY%TeHBQfv8m87<^u+;H_(%=}b;};iU3^qYU`*F%rBe~3yS~M4=L2(f#Q|HIe9EAQ z<4O2WtKP}<6-mXwO$p6xQBZ5<{*H49zZycUqWX?5R@jTOj6#HI zg_(kWr_xxM#B^^dBMt8e!)QqnD`Yjrx+A0zqk}xDg1l9At$pnc^zgfTGQc0>G|0_M zZDzjqnOgV_4JUSXEI9MSidt;cTuVkh;p6*RtD3n&0YiM0RwE1%BNk-p!J&kqVlXjt z<;a7GYj6T<>=J*0b}a|&wvZ^Lf!5_hHI^}d`7=<*WYIXvf=&F-X52caNfXmf59&2h zRgrRknOM4-1J~MVp)sQgQGye1prc1RNaK6u@>8+$)|Yx0a+%d<8YCPKCw?)Bcob}| zh`^xtVsypvwUUY9P^1y_BBllAp~Oe~(M;6ji2NZ4eXv?pBVAZ^k{`#nTDTr(;#wNk zjfnjPxT9wrE!)MSQ?yb9hC}wqggyws65@!2|cFJ`3&9OLs}NT z@k$=@o>_DuuXO>uX$B=Wt8i3Vhxs=}^poQ*ir)t@1)V_Yi+wg)#g4xC+y5*MZxVo<|oX~728 zEuN^|K>aH6zH+P)-$+Rel@0uc9M?&kfZj^v@>}EHkjzB9)y>T7u^*vf!q@zkQ!Cpt zhRMM)LF5SGtbYdB!Gpm)p5usWz6%+S@%NPaf-0khg^c5Sso+CGFKe&kzKkXJq;&mr zN~jxlM>LsVNE*4H67lL1-7A(^_EE|qU?z431hz zAL}fkyGU~74lm~5!?Z@AXua}&SO+N;!$th@xQ}=ghWs~bG2y?AKib(Cu=W6$lzkHP zPwR$9{CSIhBozSJ65ySOr>+U6f8(FXR=J5?_0DEZ-LFK$O9B2ov+*LH6aVC`Weh8m z<@rsMi3tC)i-hZyoZ)uKkX_@?&0?`+%#@gU2~_mOZ7v_A|CrbXW4CtysVmnO0Ws4A=6Dw01x^BGR4FL!UXLc>rjj=B0n9)L~>g)Rz!W;k! zI{+9Ajspw(&M`bxvdLdcFb983E7wotlhI*;vF_Jpw+!p~NJ!7NFHW;?18s+p=2K!O8piBTy}m-9%A6 zOccAiuCtyxyAY#^XD8HoeU*}ZR?kQyfY_*bBl(Hz1gg@g2uk8m@3~CtTO&uoQtTqn ze$r?hNmk`ijFX$0ZM}U#k{1y76%>qWr<*}jO$5@6aB{t~FNN?qJ1~|;znLM768drl z-`Fd$*y!`~)dF|gVV~-@wE`Dv!1NnBYSp15jVOF{I~FSmTs;o;iZ3K=8m-i~~y zv+O&fb)U~N@3%S^68eh4wBm-W>T`2=GN|zCl!>JJ{6gOA?u5C~-_bS8`wKO1bBQZ- zk2q_Jbo!GDgW_yx1_V!iY=yL(xrIBr1|l0aj`lE5sblbJ}=_$(=#y{b1_-I z84J^rFFc4iu&ziV)N-V^-evj=0EgE49iv=17byt@nM0W9ze*;~8i5T-n$_;kA5VG2 z-*6+jQrEVsVX42&x=*aCD=X~>5^(96Lt*btcHOl3LpUKLZ+ES?K?|u7HFhc-b4Q^t z4y*^kM{q%djIS)Q>&cX|j&-kUTlc2m_ugx1V3xnSiz(DhB##o(~R+h;v20cg= zs!s-T_R*~h2aeQmnoB>z6hne;CBxD5k_pkh7hk*x+K8zt>+IOByH+8ezH!^fO!S+o zz}xe)Y}dxC->&^6d=Ht-Oz>dQVe(?rqkhJL(fY$~`-LcW6${ej#XfBC?CfZ|%jVli z)%$?WyB?=C$e|Pekv2N1SrWRDGON`h{4Nu42wiRjbP3bY>7>(Y^lhsj;e-3bbk{@a zHvPmm5*?~+BAGa%iqy;mWo2nq{Z~@GWd=^Xbt{_eR27u)UP6!rp+Y+Py6VSvLedGX zX8Rxe6F*6-+OH?Tvp4tU2LhE=s7@R44uvTa4!Hpk{B0fwZv%5MWMWXptFdWA;>wHD ztW%QCn_rNC2#^?{DCQqk2fO-u2D(8(fCdsdWo^Yw)m()Pl^mtkbsk3=7MuFT)5^Wh z=DjulsXdiq)={nZjCTeAL^nj(Hi-B%%;>d0*>G6tagf<^)af%n#+UrQu=>38>U}Sp z_PCt-`Fm65;(L3NscJ$x3mx_9w&UZ~oxNKfyB4l4K1wLDLaJ8o*Sv^E=7t_qDj>?Mi@3M2CqW>2gx$&CU_GtG^JYdy-11`NV5PO!se99A@T zouI069S4$Z*H2_#aGNC2^b8UM|Jd0lCn%ppe2!9soM#KIa-~^ji>)F{x9r=ejQR>d zuGCk$1J6By$1yqO2C4=!#Y!|ualkM_Kf3E zYRWO83-1+>pCGIW8S8^{Z8L!w)r92l(`KY3N3O_QJDQw^rRlQ|I8TAHu{0MgX$){K zlH_Ac1~lc)gNBG7RuYOVnZGM z2GnVm+&~}jbqcGRO(3~mQd zo+E)j$@xG>mfN>%c;|h25ArY27(+1`PW?-^-g?Wy`#1cE9is7@yz-O6^Or9U5M#Y^ z8uL!1uW|~{JO1cYt6WGwxAtKpK&I1g*E7UX#7TxmCEE1Rv5PZylUGTc!&BjnXhsiR zEo$GCVRmBo+@jWG%b;l*JiT50|9Q|j06|8$Y@N0`g%uiH%T_zzo<`B-MaMj}{?0xN z6%wZ($Z!r3Ou+Rrb9*$9jh$|{mx=Zt%7F^l7CJ{tZ(zT>cAm8U=2446 z7ZO)dl4g|}b=JCMpgkuMwTtsUm!>IeeV*Vz!l8MXsXQf281RvQ{f9O$S5J3uH!lx7 z5wq>(tKJ!3q}gmxCGr_lsQ#}NsQXhW06qka zU(Xf<5maRN&J_qj=vlNO5Qcs(#wvGk`0W!=t{7G9L~_&^9N$&jhxqq@dS+xNfF!c7ST;Ol@Bps=!Zseta&HU73*ox?=lk72)5eEDHS9@^5k9pMRPT{a482 zKebCI{%a+Rj(^MlIf4KA^2z?OD(+X#(_*Nu;k}kwkXg(7Y@R!89d{Y#eYT4?lFEDq zAc53B^_0L`wF3AH|K^^5q$Eu`YaQdEMVID!z|P(*M^V1#@5nPd zR_SZ-tlAa$XmOPWT`)_Hns8R$$%cu}Pjv*DJzEYYewbYsW412RQD>hw&+t;>Dhobh z7Vg*KsJ-{ZApA|10(X^ux-;@R0xSG358hbG_DY1^>5ns;|;n zzbfKb)!=~rWgc7Gj|d243a%1IM$msO=P?rS)L{H|eu^{+FnB9cTve_6is0Uq$*?pXFeE|2)nD{IFB{;$WS|JP?5)BkEo2PXPA z>Cpc3wx!#^5%dMVp=T-GBmIY+HS19Sfi2PIE)wa^$>GsIIf42T?$J{1R;dAn)JmOG zOB0V(zPfeGCa`}iSXr{h`OkAT>tKJXwDd3S9hym+0Q9-FD}X|lO_T}QZv^-&)C6(o za*=(QF?SD3@#w(ua077+I##X?9f!CA?SFLAHvVa|WfSawOSovgNhSfv*VG?&s)LQO zD{0l{d^7@J!us-!syW>#DIW753?3d|#Fp_U8O-lOgUs%1%1&>wAiB$bh`N6DV*WJw ztn`Ll6#g$u|61pN2>buG{9|Fyd2U#qYFYnb>CS(-rp%bO;kzYy#%1pEvC@s#DL zfA?x%Q8@l;Y+H~r`{OqMBuBh?CgWU^|9OkotUfN;Sj{}@p4dTjVew3(;W}SKI1g)( ze}=nMv=dmPP3{2#1fzE@c(_}iM*yGeaJ$>g@GI+Ht1RaB+AP%APco5>;HCk|CKI<82?9=9m2GWG>S_=BHdbmmg(5hU^6Y2lp&p1^@s6 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/fonts/Inter-Light.woff2 b/luci-theme-alpha/luasrc/fonts/Inter-Light.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..c90308af021d3fdbb3bd9e807c4ca4ae08d041b1 GIT binary patch literal 97992 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 OnFh!o)G0oB|9=3Kqk=;K literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/fonts/Inter-Medium.woff2 b/luci-theme-alpha/luasrc/fonts/Inter-Medium.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..12454556b617bb8e3889f47d149fb1f73329b55b GIT binary patch literal 99020 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

    m~!shg-HW;kGcS6B5SJ*z#OIzfMO3`f% zeXb~57s&0UezVc_NXlMSEa(Gt%V-T32qsk(`#~>l)ns&wZfn|#JCemOLNe{8t$)ab zoz)W*LY!+4W2nh5TF#qvO_Mfj*+w5_~F*gVh(?tg5)X+c+W2opv6jU^^4jo;DSdR7Bj`J{tB}NjODoc*s&hLDY zAKTOR-d0*uKdP=iR9kfxRa{9`*4S5l_22tLxAf6*Y0Ss%C>UL1dz`lVZ%?=T?bV&H zo$b5-DVD#V)0XvKnmj5yJx|we{1de0mm!yA?#riezhc{h9qXWHJvwj%Ac;6qc@J^Hb89*p=#(KxC3sbR^GODSAjMk7Gs=aS5h&@JO z)Vyz}FaBHAR%4NiQh2fGe4js+7cSTLcH zH#T_|y*(o+ygYgR`}NP)djLPyUv9o!dwJ{S)t9|5%U_nf^xi*u^>KfD|L*>sebRow zzW9r0FFIe~UMTFv?~(U{_WbsI_b_`Nd+0sGJ*_?2J*np>JCB|}c;5P4_PN0B{_fUp z)~@NU!83+0CfoAc5?c#fcb;IM$On$0aQ+f9&N4U|3ywV+BK1_Ykp`&O>-Tm4VBe_= zfr0dB%;u1&B<6hj42k{Ud!5{HBp2VN<44%WE@fZ9Rf5YGL5Bw9a;oo=@Z{s`xKYBu7f1on^ zTTMWjC3|dO3ukQL`eCz_bEXXsx;knP4m`~Dzz1Laz~fH)!3fN^dB0Njm`0xkkT0FNNLJ^&5_&3;WOP1GE3I#*|XOO%TW^?oEC08wDRVyT@a!UZQAtc z(xul07xcN}tNZy=0^B(&0lu6pI5iRG5Ukjf=nSmD&)*r5idoGRcSV1$gm~nj9D>Z%9=SBJhg7!GxyxHWy6N&p4sujzL&PW z^2)9^-em6$Vd}Ku6$FIWkc|X@>R}yLdxL#A@D@LQ2ZRWDM~<9BR;;`iAixI%L?6{_ z%+VVtnzZ371cYz+@Hr+)+IMo~{8FgUZ>388amQLt-VhPThJONt`foaGg{1Pvn}ZiX zw2L_fKI0|`m^MSm+;YiP^N_AD%U0baY0a8z4jhp7(Z|TVAqLnW3js-vK79%T1yV#r zq@+t%uD>D9i4Dql@lxT&jVb~HHQ6aD#D5?6QAQnK{mPBEB(>8Csq=^wa)T}oob(71 z%&j-1)3L!omaHX^VRhv{6w-)g_!QEZi#rw4giHP_q$!svDx_Jm1Q|`i9Hlob>g)8) zX`)qpaIk=hwyvFtL;+;~{U2RG^*NKU(9N#67Os8@vBMGwRI2k?<^sSA9RPs-+W{5A z7#07|AtBE6ZY4*8V2d9YF(T3T%fVnS#00Kx)+&wZ2-86hK_-qM^H>uTv9?x zMov~~(HpwS$(PfKO65BE)v zU;qH%vgG5yg0Xf4W%1mz8V~x z;^;$piTFs?Lk}_^7%w|1{QL@+Ouqvk5-|av5zTZ7zL)?-F2=#~iNa3sIsTQ=@c~oU zMY8Z|j1zw9H_W~i5s?rwA6{kWUA+lK0fz~F(Y+v>@{?~(q?F?%*=L%tb2Z4UO9S!G zFV|WTKmvq~7xzZTRe96$$55+WK&eN`AyJIZ__3b^{V@@O)O|z*rc#niIVKuAlG5H> z9LBZDL>)6W2or}{C7(+}E_BsEBF^EGs?Y%sI%n-NG)a=?%w?*A4r+K7-h2qsl(sa2 zmOe;mQZo0O+I5t4Brppk&x}L)(h;ElkYg3L^R${8-w1v|vXJ*~%H%=Vrp&xn6eVer zcZeiiS#Cjdm|mn&wQ35jDN;(jnkGVgCM0dSTMteaW7ws zenv!?Hc4;cE2Q=&2Flm}3J)m5N3`l1;VC1RSkGIX)h_iY5vq03Rm0y8!&h_s9ByS7 z|1Z`ts%9%CnVJ{e^G-$AVs$qHtT4&y6Nz+98jk*5uKfLvL>kaPCKjOSHe?D6*T%@; z`smfc%*W(}{s>QVOj#Fk&?R@W#X*c{6{+OHJX2Rj(pY0xY&g4f`s9ZqhSF59gri^J zEs1aI11k+ymKjhKgmWkiL8C0_DR1R7*qWrt@hT-45M-SSnZk*e3gg1 z7jI7F#aqDM+AlPS)^1HB_9=+1rjW&$weY=3hR#|8bwg}E^PIWEZ_E`UM_P1fgZPG! z4W*Z108DOaH~Wl>qDS-g|MMcJ7*hrkB0&N;d}3-rL)YGBv0}CKvH2SoLfTip>h}Q9 z?VI+(+&4g=i`I5_B(m;VZDI3g*EEThe;2+)c}`2P_x`!%#MlO?qlz(zA!{<1YOBV^ zWnxs{y^^g*@IAaUHrf1k^7s38HBa2HxInGg@m#RZaq5_K$_(y8SMU29wtR(;LG?k$ zV3-U2Cc+seyp8pW8AwV&u;1CoiYS0ZzxfdS#@o2`nSJ8p5tfN29_D`Ie%2$o&w+LC zF$#9{ykQGPnx+IBZR^q}M8yyh`#3TwA^A7XnLFJw5Rm_n(XdwvURL}40V@u;E(`Yx zfRh~>`GxI%**%MYe|T(JDc#{db+!8sLkN_yL3b;=)Sfg=BI8J%>O{GvY7*x3 zzKxVG5a$$6iVjqyYC)w0ZW_@>yQ^HUnGO-%K^n?etwTV;+xxQCdswE6*bsqSm7DK? ze>_vzHeTMnKVqDr^=J3(Ibb|L!D~kC-p_abC+bq5)FD}phLBST+Y74vwJ7Vhp~*-v z=qwGKv|(Ng+9Ze;nqcl`4>m4&Ax?Q*a(C^r!!6%#Z3W!P?7+dSpachq z2;@6JQ^V?6)+$HV0}&*e!)C!7+01HT2FjQ<5cMjjG9B@yszaI9*WD+$je!MJ$7d8+}S-1a=6W=ecP~M zwqDCpzMqSl3}c;0HENdI<2RHFo|cK=@&-RE^tX@JXtky5oJujGdr%5j8NyuZ57x|TF4UvD=k-BHR=Eyz=?JDjU?S>uuy;4yc40T=H| z1R(m*A)7a*4)n{FL@!(0ExTqPb*^Y#wxBVzmkbluJ9 z#6-wojEI>(acQ-0b8_UuO=5g>s-+&b0BL&ZXhK!xR*e~<9Pgh*D!S~-x5)`racr(= z%B+kqjHk#o)P&bXs_WWAK>7G5(7B6_{f}s3e+5u0YxX2|93Bu#FcT59Eil!;uVPSY zY$(`+!4l_=gHb&KrIhjgzF?RT9ypZ^Hs`ph#Lf(b2bUAl9alGEk<`W+tB{LGR%Y5( zbT;bTtQe&>dtY3VlT%R;yXFaul2Nvq#m(q&0cS^9Cw}*D3n<0ln|Dhps~zRy&7uXB zWEqqyC-u%;Ur+0*HSM<8>4M?ynJz~0bdrp7nNFk8IGkjNU@S-WG_1s|5wCDtCdm4H zyeHW_XowEC=@fklziKEp68w#pFavHA;TFN zWJb~Eb}$h9AG`XksM=qS8j#cqODS6%B@>zqd&Cn2Q#_ij+rXI#4q5+Lwp@(1I5}y& zEBu?*2Bex!(o&Y&ST{B6q>`!U=~bkCj%*rIvhis%eB8`N-4IIPH|>&*P1S<>b*3H# zdeSt5Y{dAYn(-PBy^TEv1)}uzCZ~Lud}w0$mqMY;_yGN&2qWRx6>&+IlgpfW0_wPK}l)(ZH?aV8_qe7{Ks+pl=WXRf6Ii?Ns zxBeP(q*Xo9<`aDk?kFp~2Zunh>kI};BC@_S_%62>^sux^BJ%lwv|}IL9oGA;rT!V< z4LV>{$M{Ckx~V3m&xzTL^AwY{Q8sntC_i9JEr)1fNm;QmCS!+=;kA^NRs+3-{K6d2 z&<1I!;=Pl|p;)#vJ8JibouY9g$tn(Ot4NS{1{3Ec8#H5gURb& z8M&nZUR7;u2g+Uvf=cZ53v?rpG5-E~woi2)JKbDhwL^ELokI)R>#g!fFJAz`*iYk{ zIn(<*y&6^b@I=V^cMi2)L70{H^z2ok#Bm15f z;s+cxn%`*DH5Ms^9i-&l;SW-%5KIq`%7}p;1)hHJXN4`MB<*G%+b_%}^^G z@!`VMfRi7qfqAyUg|aN?!!%dO#-z_9IaTtD%aX=u@t&hf&eZWT(u-uSH^gp=W@HV5 zF1o5`$dT`(8}Jm$i#n(PNoni&tH%SWlRNSrZ&S$yX{kb)&)$*SHu)Mk$LPzBQ{XZh zzd-I-u?%Jo1!TS|nzh7g9=|nu;0HrwoboaWPZ=#_YsPwJjZCa%xNIIm6o^JIUhO8s z!?vUO>@abuz~Gd%;(2P3eNH=h5ixI6;hDu$1?U3EqRFD5lsP>R&N37Ec-|{^_dwYj z+F1(94<~)N2WuBH%xZ;*i^Qih-GeUDZ{TPNMAf*g4yfi;pTf}7-%~35F zbjjtDbOEyyyjKWNgxRuai)DXl6mah_k{iTU#+mE0R!6uRI;hBh%e#%PSQF>;W}m8RhH z_TZ>5ai;(YC9wxeAn6H62}+cr`JFJfe7!3ys1~24H>8$NTAe$lb&MLV3{I8z%4X^P z5+!vS$vr^}%*S*PrC7cII?hJ(Y6nm7(#%uHukXb=ivU`HfDhHgQUiU!ADQqvRjXWX z%zA2?L^D-qfIOnmh-3ZJXcK=e271)6MB8k4@mg~UR@!7IV>34GazZ~k(gAS=d=Atn z^F@y1!SwZ(Xfz5xMv>ze1ZXvrky|eVdg)#q#8WL*;&KYjGn4NTf*V3G#eWWbl#Yn$ z`P*LHfq!0&Rug0~-HHkUXvZph@7#h%jpQ1bKZB?!m@sV6@45j3mLo+v$m*b#Vi>d(p4py8zzjs9nXfcY=y8{y#hy^r>pV`sRoSAIs@enua7~;fpq;ZkAoHtRkVt^^b0QVd!rZNgHX-k*eHhyuCpekC%*g2V*BLRX@ z+EIh#F9CuUIK?ca=jAMc;aiBJ1@NF;F9nn+e_y(u4&Q(=kIIX)9|-KCKz-))mMx_X z;Du2$I$VcLN$o((g0XbN@@?!!kv-y9L;Xz}qRmA8%_@ z12MP;&-ru?Y=Xsqxu5HOjyZ0@5Oj=G%7~%OLe6WU)iE;aOIm%spj$oxTZ$SrMFt_l z#E>goO*^?AN1U39d{XQSgSuta7ng8%vAcP2N>%PpS&7kBN~N|i=O$-X@bHVigh+87 znK5eIsXc+NXqL?eGi2T(6Ck|XYOlyZ153E2$7(s77>y)q3)||KxiOL|K429vs8EOV zj^nZ-HEwvBy+u+jG9wnXu(5!DSuN_XdvynBS8Y17xux{WV@OsYe&&zSQu-y@P^H{z z+`^9+@n=!=p)yIJ#`voVzNJST*#)VUNi^&0>W_q)p`=$_1fGA%czF}zTb%yk^~w3q z&X8Ovy7Wz{npI>IqF$qZ#xv1Mjfw=@cUqsNd&g zBZN684f>vfNMfRycIot?P2+~Qq1^^ix$DXu;+2NW%M}q>RyXqER{{ zg+|1y^_tXqn0f8+g`5%DxnPAG%KQ-BM>^0ljA~cqh@$yp^>tq}*Kk}HL?ca}GLB-t z7UxO5PC{03jdkb=#_UPs;`vQb*QKh;8O~pxWH4^S5K2WMMxq)Ng6aI+$|C;k`XVMN zv6m^~cK3bo2xXesRw|a0V>yvZWQ>YPknXnT2?-XEnadi<*h<6A)#z;Tzz<)D?R%I|qt)#;wVGdeZ%} z7Phvu!Pvt3CO8FTUnCVB8FWO4<0DZkqCLApAt^E)C=yj^9Ms{5d|H!DG5X4kGia6I zQwPUUTaCPlJjeYu_ zR>0@X6>9&Pg>3I6!fni1eeh0fklS8g%83Oft~J%`Xj!DEyg`I6K`$p?kX||fGmv7< zef#8?1*Y8L_=9&@Uk@Ngb0CZa{1$$*OVs_}Lf7^U?YBmPRQniJZo|I@E5FxsIRbR| z0WdB&S1p2L(6}dLA?c>-f;*tBNjbKj4%IH(ms#gNyiU2-HvU z7L1B7=0zFR8kIeQOcqnO9Y1lwStFx&YZ}g3bf<_1`p^j8>qSE$S^9qf? zn+Sh#R*zLRF}n?DFqnsvdeZK{j_Vq3(!hj;C?*?w9&Fx%cKw$%O5B3y#^Y4tVxGdA-noWrfFk9pxJ18KoT5 zRgPvpU^X2ENe-~M55Eb?7e);t+Xjw|a?`W3SCj-5ZQLPW0FcSBshEiiwUt8X0slO- z*v2hSbKfU&E-6d%A2FucfQ%t&q`I0l=T`nf!G!J17Wh+ z$R&TegPm#M4~|HpGRQ@pG{ekvbaf3aC`!RBFZND3li{(jClOc78R)<7{4~}_W+L&a z^i*fa@vRh>9$OsaAVa$yTKwz+=SVhA+MtB$8MGhSo=JauD{xy z)<)4d33$H}#5!>-j62W+QeJUsI4wO6dX-GVKTo=dI?xsS_sOL860A<)9&}&IJNyc$ zmY`J+JShV#Dqz~Ug%f%9{k60@6~~)BElO&Ze`fdD*-#_jNxff;3XtLFsNfi)TG_cs z%QCd3qSY=D;U3b+5UIqJ6#33MC!AJV0j%DmC7jannLDM(?p<0szK@d!+-UxAO7Jw7 z<_Kkaj0Ki&0ZuYhbP02!VvG_XGqs@T2zQKG2&vG8%zmq_KQRr6e@27$ZdW=w+)xw{ ztgrke0{ZH{@!;wpIcS8BlUD)V(Iw3Mf-ifTKh!mz5^tm9 ztK<@iHj|MtHTJKjt4H?_D|iibUmcF8b1bt@;;WMdHYkSAv(9i%krzbD>7jySx%x-0 zvjSFgm8WXCMt;fa7Hm9@E5*TrSYW>J^X9)F(ole+@jwc5AL&F)BYlSSmvyFF8R;Ts z|9*W6e!iAjCW=C?9;ad>Px4%z&&T8eeK;D?hh{RN_aD*elw>21>F6zUV`p%ZM9M-s z9zl*WFi9x0{Zmv=Tu5J{7DUoV;&cH7SDSz1m8ZzO zV5yntyLp5+PWE>*{;#VjOCiRzWaYgP-9cV$oX587l=Tw?y-$?JOIqkM=eek;rV?}M zpO5vK=C19cims3?$v=1#7f9b+ERsadVk4H(Le4`iTsfm6jL0G(j_yVXdX^GgmB!@W zArJNeX+tD^O`XI^6w5S;!YGVGU5}`{NiO`zmfU~h)sze&6^TNqfb0;%H}xFmz+;Un zKNB_(IFBfUje6C$jG)0Cs#UXmn@sj>^)z|{^U!jc-aJSLYN@qGWN5v!{WB~sLkQ1f zKzs__D-baQu4{Gl4N#771SLPvH*xIgcx0;#xopQH=VW2!59CuABh!JpBkqRb8uY-x-A;$!@R zU`(F#{Ict&J|l`I(jnd*n>Sp@l{n2Zv9?hn(@eynC~{;+!gO$;dS={qs_#S4LymI$ zV5f(f<-f(TvHPi725BxVmb-`8)DM@kuYjwsk*xVK-7leAp>M8j)QwhVZeyE$MikXW z>Ai-$o3$_>(5#<`IcDs@3i;7c&^nzcZDhii876&UBv1wRfW%ibL@SDx0xB??j$LWG zXVDc=J=_YT9X}S!xnIqMz0>QKJ<5SL{;mEzhoP510<6zlPBuZu-iw%NoM{2cY@I<2 z0E>hKlg2njgHw*}O zp|gAg0xq)ab`7-nJBTb?;bSu(9f?si`$>vFP>y`CLWUNVA@Kgl`V(P=+8i9A*(i#xWqs-+OQVh?kC(< zErU%^S($s1@Om5Bg_BF{goluZyq*T;1f}_Ira7L*`3h}Q`#6Mc;gzxtXawg5$PV(| zbh(AXk0%^~T9M>-Hj8J=R{07dN2PtPjgf*U&8;)bms|5FUfQXJUSy$9Z;bXSl~|HU zOLtEO{u5CuK6sf9En+Qu8(tt^c4SC)nuP`rm5HwXl;w!~QU>UJ^QI$xu2o*4otbQN zJ0PK+r9Q4il&}=RzRC#+6N8}>s5eW>GUMeC%$CmZh&`4(%S+FEj-T(rth2M~Va_+g zA921pO6mE&u@(YvR+9gif0*?`;l6X7n2^FAd20rnpABUp;Rb|0bm8+jNt=aX7)bfS znbELkt>R)q6WiD9bE8~X{$+uGajfx$7hM@&n^L^d#`CfN{PdJI=G9Z?<5Ir}Q_FcC zq^~wu00P|@ucE7B0L$qoFHP$y6@Cb9pWbldY8^A3VMCn$;oomZubcVLqyHy5Z%6XO zpks^B?YZkXZQtT9J&QTg>|7IP6opU6q*7C)ud&DbeyVu8Vm+RBY5u#APTI$m6vb8? z)7Ld5CV$cimU6+IuFiPC5KUObaw%invoKwc@dKRV9gEY;ybYAUOmiRYP{}#y>$7?( zwED}SVyOfiXCa+ylaT*y%V}HUkom`N&Eg&m=td@Mrnp5E+{ZFxM;=CV`pn{3AmXSw zz<+#y7_i3H0a5+p9yrQPDZSCGBU^5_5RLQ{w+sj9A6H`H1{!T)+*fp7U*Az=FpwbD z9AO~*cBQ%@{>Y3|mxJ|*T{xMCPS(4ix`#{x1ot$t_XrnUcN&~fEaO9m*$Z7_u*Y{#Qiv3-SN!K6 zQH!ZJmB|GirmjM+3vq-A;aM|{`JLr=6=tsd^>V+pvtd^{iuc)B&{1I}Azs0``!bXp zxVY2li*S@HR)x27asIR%Nh}i!t$00ZiIihx6b)*m6$Ont$jwd~~XR*p-xJ$zlL6?+l6eiwGl^9vHMJp&3cbxkI#H-i74=xhl{i-)TZX|g# znA}tT8^(hK6w*O|mZF29ZQc$Tdqf8W>sx3Pu|mc%cdwk9-T`~6*=tPa3kS@1daoZk z`UJYW&ytAZe>h;~Y?tlzYt9#s>~uPZ6RP>Vne7Ig3O#CeOK0uW9b>J}pHFhse^&{M zDoSG$gzSjlrx_OP$=Op1*Q9R`xT|puufysmU(0;R(-gn?QVpW)%1rSU8)yg9cOoI9 z{;ukE5o$p?${F}amC;Mkyf7l0%p-x;U9Ak)ww_&(zEk!?K{}`yxzFYVbt3N)#klz} zciod0hN9#elWue!;@0n%DmP1R;G4D=JGfz-jJ?Y+L5sCX_4~N2wP`F-;Y({phmj&8 zj0=-&TXSDtYk9;lPpVgKTD{)NXKPpbTC;q5vI;YbNu}zk&be+*`;nXNWVP8ioTOqi zNybZTP{`Fdv_26<5KDXW<5sjmBB(t4GYN#vDTI+t<0J;#-%c=J*)-=Tuex4+xN%q2 zwX19Qr!1BqOa+P$71Gc@9TQ9bXrvf_cpB;G1EUy2ktZgRSxC*b1>TD~57+vB>UYOw zcokbur(+zvz5)AYt`4{xDC^dSu1WP*t|&Yer6*Ph9w=?T^7#L3*ucuDwQ|mI=r*AE z;F&?znA~ShqHHIsn9}m%c#(IpQLBvRSuOh&`}2O3VloV7SiuncVvVX+`mNhuWt!d_ z(BxKu=Zj&~t%4%t2eJ3UdT2W8Z(LzyePK#LTCRPJ*cH7iHS$GxqVrVEs86ld=$Oy2 zF?N?vmTPmTc*ODn-Dv~@?Dok)W|h^jSEOcgEapS+H0NK8YoC!HjBKkw!|WdAO?a2m zT;PpXcuuU5NPlT<&a?mffPh@byMkK2c!{7mp*?qLJ<`&HJD0+6vxe2lCbQ|p?lN-J zde4*Fm(NhS;u8mD@a~JTQc{@h!u8R66WiYKo=RFPfU~0BaArMY7Cc#cHlc)w2vKD~J}yK{8gSzY1A z5@rvY*TwkPn==OHLnxc}tEVE8(&98u`b6wn?(5{B>)#0Wu*F7?;xHM9mIevT>;j^I z*x7Rx+hsufaBnn$OvRs;g3Mk*GvUf9dEIj`aIX7qubohqcxY|Vr^6AU2?wVdGO~I? z(W+jm?Tf3|f_-N}{B@2~QQXJ$5e1@UIsg>P&X4kEfu6EGJjVAMib;MSz4h>d71Sh>cDRfypAfRZISY8j$EQbw|VnR*G&S2RepjKtxgrrFuUm=6Fc zBjLY*zXMfJ@k*wZC9wcZA?6>pJ@wp?z2vzXlppz`7uC9bmu?OvK_)k`>L##gk;3}r z9pLB0T{9Yu;;C&0=aO&kD)&1j;b*2&Ul>b<&H@rIPn1jYsZ>y4-+(aJubs!UFiw(_ zJegbB6_zM^=829ylUi6QJkc>7>3P2v3Ik$?!mEUq>cO?gL@W>G%KkufVCGD~XWl(C z<(YXiP7Y}2kY_)?IF*S1roIF!{(75)%n&JTr*-E^M(nPL3i2AXvWYI0L*nL&n8L9V zowkI{h2e8E?k`BN#HUYJf^MWBKD9_;2pH{^&j0Pdic3*IZYsAu>4g!AyEGRBLtW`@ zl;Ys16Uj?=WfjGlS1X!`?St1Ylh%J}K-6mg;T`e!=}{X*XU=6)+XrjX6P2u4yqigs zv}4~R9O?X|uVHJvh|=laCL3vUoXn4Tq9>E1*`RkGkpaId0gYo52&MONthFe4c6~xo z{X$D$Yio5%A=6ZxW)Wu|pXN9#4y$pdQUYsezXsYFJb zrT|h$=tP>5K8bzO;SQ|;-$#jypUTRx?4irfaLgdF)V@{?ki$Y?vIvK_eY)MRgKngm z^wXJ_??03W$sj{>^KpAp>ra}|{={)}vaseOluEi$@w~=!F^*-cuCCSU+ftzCm4#zC zNEq83YlA!AzO*+gQ(7W>P9S1IK^^>Rzh|aM3m~)ngC*-Z$kg?f>et7|4}Y0^RFVqM zh7Aez#BVF{OinK4`f2Kl@QZ3@BHuhVP(X@-y4kr1hA*Mr=?*c=zk3Gs(t{Kx^qEAE z3{!-D2iK}tR;=)Sp{K?6K9@U>QSW{s+Op<#mCgN~rPwvMtb1RjPygH#+8&DYqa@!A z6c!%O)JC2xVtI~gO<}WAbdzj=tSp=p^%N}eAvQ5~2Yp!nupJO~YMUSCA}5clEwqR) zCJ<#o|GoJjC$*~{!jOzATk2bD5ecQxc!$EqGoJjlxK7ToPY3B$ayjZqZ?cUp-XF|h ztfW<9k21wIb(o+H%NuTUe2C+??I^BcAQxF2^U=nZGb(z}otkFXhw{VbIjR$bzk9?h z&jNK)Je7o=!5~&pUN-9#YffH0-HHpFD_Nr!PL2>-j;q4)jY^&FNLm>iws&gg>DT66 zl^?sU{F^UUEkoClJ7_dy@6&^>MR#h7X+LE~2E&Laow9|}PD^y$Pd*zEKb7CEU7nt8 z!Y3`{bI`QZF>!i@3N=!n4u~G>TtHGD%EifeYk}UzxA|ZymJw?beaCKsb)25gYe{#c z_e6DX^${#y%R3`EExCA5qjf1L#Lrf(w4-`J#)tDBUv5_xbU=JkDm@s~kjdV-Y50=6 z)DSTK#*Dz22U-$33>&wcEvC=aGLMA{?%7MJJ<5-Y({E+d`Ma~PyjDSPQ4MFVM8kQE z`iLfqSZ=t=#ZkiK?B{5NM&`2Qh?*>BY&qr_{s88@ME5dmuvIZ-OZW__<5-tTU?k3y ze}2mv%HTddcFwR(&OA!saD9Sgzt$IN<}{mP=%R8)xVa&eQS{v7yFi;Yp{WurMQBb; zetmK2hX_21vc9c`gU3&gE0`m-fDV36sy8xU$iyXO2O7QN^3R(l&zW$2aik+Ua{fna z%x$QG(CrDixP&^T`2y^{M|!jKOZXtZKPk0^v9W$PTj<3@e2*bp`q7MB0j>*dl|#z| zw-wXeAV9AyX5#xqXSzBxWJgWv$u`b0nnspIieIdv^q1o>w$b4Rkt0MD1%w$-0~Q?d zp=n$cUfVz;nj{oGslOxIM{a$=u)LnS(yyejzFGgn@&o4f_vq-){>@@+?4Ro0uaS|T zyzA-k@Sm6NLNe0!Z**g1uySiLl6lt(l}@~;-l#%RMlyC+yTQJl!0xy5+dAQwWs#Xd zPps|sZ9E4Jr%`Fv#HHP;7$pWow|YM+Xkq{_lPxL~zx} zm5yA?tdJ|YpNTFI#eno>zcmd=MoBgR1U(R?0G{27c4Ban%o@ApNN8Myk*@L_lqt2} zQSAX)z#AgHGM%9Alt>~NY~;B(Jx(Z)Xe%$^N?s!I>0>KvH-?OJV?mK49!0NC*xJZ@ zbc*RB6eBkIxC_eIE-(=UcVAj{!zjhO-yjq=3|7TViahqiz!Ze%5DZk&;_Xe^zRe?L zk4PF>OeQ^GBh>l~m-Fe)vk6>}5=7vkOA9_u_&huWyvAko`f$+_)3yP zf`-`$&|hQ^KT=Klu8#E6V_M@`5>N_Ls9K7~c7_tuzZtfU0QP7Q}t6keLBo&IEj%r23c(9qsv zGs|)QF1?e?!Z~g)XAPT25!8cl;g@&u7Ga~xdm44RHjfjuk?}p-iNOmxaD}e#b5{J< z38?P|E?ivz9+0FDcs4lyF=e@umUsn8hg&( zmwB8gxdc4`0xyz$Hp?7d)4J72tBJBW#c@+HQ+FSj3jv$UkAU}{CiN{Jm|%SpAR2Au z2~#z0udKw{H;C47v-S+_hyDu_8r9Wh-~r{AuY)S4l7e@|4d&%v))Zbbb&>O@qe*}b zIXEHk;0$LI^kh`{9s<4&*)f_$USkWTDQ`^y9IXY`;N9PXXoCpp>O2$0W}So4iZZyS zpF|Z^d_X*Zp$`wDEc|8RvBt+xx9u3XA9>AE3o7TX&a5zEA_yc!eow-epp7TcyYBgAexwR zw#4ANXAQf&p2wT{OF_J>eS3}hvV=<%2#)NO zYA~KMwq@9>KBe#{E5uaw%==f{%SX$_%&gk5ZQ`0~VcXc^Y6Ll@t71`ECCfQF_F9Yc z^jzr!5Ah+>z)&rLLTO2qX-QvIIxx1)GgyBQbIR;9)EGJh(*tj|%%J@8C2>Y5kUaXs ztv|PZA&Kthhark5?7aZfnjEBk??NV6QIa<;CMi(R_6fA5B;t^yiG!z#uPO+{Le#%6 zGac!8-rRDPP=yI=9BO*F*U&Lk7B!6a+PGYBgv8i>uHh_yN(LBq9 z=IU#5T6b<SKlF2-LQ%VU`pNs7b=s=x3 zXb8PM<*!7HewrzyE7{#Rrre<~vC$1Jny7!2fZ4?&?9^f`AYB5OiUT(1!%1^dTe=eH{bkryJIj z2v-)=>;fboVpc8RyZW9FAnpOwm-;oR5&g7$Jl@$cK3?q9+cP)D%RnC=qzjk1QNWkk z*j{5(l+FPb2F%p0TnfDP|yK~#cjH%x#~W0pO$+P*s1IK5;19V zA08`__&4o`)9{O=$r(1Urtcs9YDWawhr( zsHaocS#LM2Ke1|fz(73;*hOMw5@GpCN=fF`^fWa9FZ>lQd%d3Ep#0mGT%Ff% zDLGFB6dPmIAY32(%K8P^btu(0LPn@vIi^-Fg9Kf=_`&IQb%lGYvYiD$_9!-!???gg#rKtae6_Xn9zw-16HWZ`OnHwKUKmc3y!Ue*M7 z!0GausI?h%FZ&Oozb!~Eik+cLgvS8d@;i|dG)TXsZjJ$JP{zin6)iD9Nn0%}um3^` zvxZb?Lpb28rC$g9YTYyj{=+rYkAv?n-&@y>OfGDqejO+bzK9Hb>0*1XA?DKaNGOGu z&i3aTATJmIKPU&ELWXB57Juu(Y1*Y(cWdVz%{`Vzc~9{zlV!vV8u2n-ZRf@wyg4Ud zJW4a_FMqy8w{!(%U6+mqD&`SSjq;wHLo^3_;moy@nl{Iq2KsJLg2tu4&$y+V>r}+3 zp1K1RATw&p)G_D|YZ~iUxmr9&+D{wREYFG;^-;6|b2A5Ze1T6m-%!G(<{^5Qy|5FX zgqCVw6&COhb|NmS*yEi4RCvu?X2R;LV4%}0yYDAlyXm*YH9LR=op9s6I_Jy_BzD%zd=ko_6m{aR zXQ`-H#a4nJ03q02PB!@f54pq(^haoGIM7hCUIpzXj+ZvKhfc#JGzC5x$`0GOu3h-; z6X=73?LRa!mq%qX$A5H?M@~w3*ClPdoE`KemOOmgZO?Pg;5Uu5J3tFY*WpIXQpc>N zX&8*4bsT6k_BEY!+IdUd2?~&#w&m#Rjk|S)Z6F7QSx2q`z|8XILWs*pd+~%Yzt}?y zoPvAK4~Z1coZ}iwnCW$(o*<&HX|iz7_9Ne(>Qm#K)fM~Bd6`ZII1GymLe*Akz!oP? z8-0OKnV_^K+)TVuRV_ZYvPFZSf_t*&aG*mFO@Hk@HeIAd|NQ7#=d<(oTRsI)wef%+R`>F3kLClk+G<&o#%UTTI2}Nv&VpPpB z8dZ<#D!8u1o-vp3b)zwR{u!tMl2yB=R$ukXCtPb+AddF`7?Fn8f47=id4}NCcvWLv zZL=n#(R5DE<(1-nhfvgG?%9`T|669uu&d|Vh;^4xjjX?zd^ev3wziriG&REf;4Tc= z1yA06lg`Q*Jto!tW{}vwf@X_XoI3prNVcIS#qKK)|G(@C=jayOeZo5Q=fTD{sRud z663wR7$dd{S^4*=_SR@?v?f=)Ptp&HZC< zq=EkXuxa)qJ^wG8YsKWSWYB(h?N6QtSOpZ2&{JqKpn&W#uLQW!L|`6bCr%qzogRXPOPB79tMqlNMH$qtlBjd4(#+VUGmVqW5T=);a;? zWPuhiHNcVp;uas+mjDF>K*Vs06H^$biqbg&5$6U8=X0=8b|tX`BKW)tJ7se+$2EsQ z)@iW)zBc%inR)Q{w>6tr@XMBL^Ew;zzp!LLAYbq62VJmlfxw3P*;>_w(LNQ^Gavp+ z-Ap~}?=pama_MXHDYXFP6zJp5nJiHx)VoY!UR@0;-TNB^drz&@_0fJ2)3*2G>YpdV z&ZTZ+*Oq&Z-#yVsUBVNU9m3*WfRpX^$84E7(wE+?!l%CGnC(Ql+ zJsD^1pSqfGEU{+?EYHT4XWWU6Sti2C6%ci^;}*5BYZ8-zRWUw*5Plh`a=pJw49=IWT{wtSP-h+VHHpi{*PhCJ@d3(VTaIULje5k3p{zgn{wJc zG=2Hf7x@2D%uZ!GDY=`7+s&?Y+OEn-A$LdMwm>7B>p=HL8{zf4iD0XhoeLsGO+Og> z?6{)a^7CQ_a6a3m?cTfOPuwic2hbw@ex+^)xMRi-4QbQ7Gmv#M~r)!CpaBJ|4WYG=^r50k;> zD_a$RyoLs1Bv$?3e#?ds>r-XEp)mvAKBEx4nizQb9w8B%CGYFbi*b?^&hJ>_js$%R z;45Qc(FB0!lxE+4Ow4zx=9IJK4K`L? zPtwY9_o~StW=cs22NVRI;n2w0Z8+EUK0lXgZYjK_v}3d~puxt zK*Izm2nQ5+eeFN`C(1boVpi~R;s6r2tV1|vNcUBp^e zBPBX7_f+m>{Ijr%43a~ZgKdR#f8e^kY}B*&8%I0e6@rEtaV+ULUFKh7hHEWM+vj?V zUHA_lCyAcgd4)uP=YAndppoN=CZDBen0#K76xlG5gxga_y2)p?iEvI0Ak_>0Wve`= zi9r#N#@`e$H4gu?k^bmNt?N)XI7u$Iw?s4q|d4e}9?*2{d@@$Fg4Hv)zvYWUf%vs4JUo z`@I^P%e?sH0%=i*x8_r^MpLDQ73VOLFft#hL6eH0%ST2Z&Vy zNxWzf#T;B27!qFzUh@b5Kg8z>^z3HX(jY2gJzKA;I~)x{7`<37ad@#nlo(J{!lOxQ z)}8-r63k?bWwMw5j|-XlHt9TAXTAi{E~Hwf5Ke59C!1NK2*IOX6h|f1(1%VcZ@J|I z{Rb*}JIrUW^FNft*XbDK0kN!qwy~h3{r?c=VNKFo@doC^42)tv#>!qTKZWp5L6P=j z!&}9kFqemS|FsvC44=LAPodaNE#JT@R571moT$5?=xE>wXofmq7IFk;AuuA@R2J|L zT*8b4>;gXR=fA)(0P|t>r%JR_-k%4PGXjT9q5@u;YG~N`k*O2KXeWI?KS@p{jF^Y} z80$Ews9Og_Qe}dGCYxt2(c3FG#?w1H#>+qtkJn{AJUm zqrgiYw6Jo}_?c6Q^RX2*jVFTQdKGU#M?k8%vnTUVy$D0D4swZ?wKsk8uC1|qNEhxU zi1e}|XKGs6WSZKQg7Fc@sCe${x7j){4b$1$FAo%Rnnx9KUcJuMhH042)!9E($Zh(T zy5ii~;JrgU-Oj_%TiwgpTh0TcFx<||*e5Z`H1U8}VDe?o3!1T-Dj2cnGtaSX@Fd;%00=5D zPU!^KG_~uT0O?sKZJo2BGT)S%&4#0Ll;amW=*wUp$(fe7)!iW@2*L!5vnI03~a zMJxY&+uG>zQjhv{L0NuS-70r5U;-q{c@h=AqUljkDa}%vx337`zdI7&KVwOg&-rzw ztsO^pHT)_}`AG9(OHqi;&r=!~%p{QnVUm}L-YQB|9=#%q$mfD6_#QT>j4O1P2t<`F-yfu&T9qm-o(EIdY$MA7m!- z_o57AH7z2rSnFuA4(5N%q_nY)j=r&yM7{%`+i9znS~oai?Z1+?^(;-apPVMT^-MIa ze`DJ>)63jh$GDWX?D(&dS^14;?A}H3bDDq z4l&iimr{&H07%dP6hQd7>#P`G=G>5IDE~jQNmCPCs0_y3LAv1#z)uS|&P!kYu0H#B z1{k&4yen}}pJvqW(6Bu8t_Xgzo?gF)WIi?wPfO{-Cy~4G;mHYok;%z@pw@rRD~IT9 z7QPl<_t2joCQLT*IW}5TE_&u}a=PII&Z#s$+y6ZC zr*9FGsF#vC-|KYWddKGU9)?gq21e1`4le8!2_!hm1=ZU41zc(pA%pWV-ILTU)~r8qH07s4%RWtqi#mSp~Y>4AY;k5`HmU(aOFyL&f?R&&k4FlG5{W&QK&B9p@hO;&=n zydgP4dLANw9Q9M59TJag^K!hNoNs@-l#~$D?BlqSR%o|e91Xs5WSvd{FY84z@J2?qO{dS~T8h3_QZ%uRh7Fa7d6=sJ(^9)P|5!z6){+}x91 z{(B;01BA;Y-o>qXhcg#O^i~EC+HWSFPkh@;$}b%3eR(4XDi5XHw*^2~MbhZa(Lhd^J3#(-km_SrZf{qxgXD(I430Q+uYs zJ{~zrf{owlMcH7^f{-0hwpU8RO^-<9g&^6UXxH2?MB>u=!R zq%2MZq}5*z)PD^hR&Qax#X7l&m^cUr?Sd&fOJ{3Al3|#`L{9qFVQL>W!yy0?*q;fM zQdE+6Q3I!6dFd0slcUHaCssgwKSz=V)v_hE@rY1D|LN3&h-*z{Z}cC zgsqs9NwA}KMabh%X>^SocWZ2Puk7sVP1otKa7^ZjAZ8o+=1o}jQlipG(UED4`znI5 z`b#-!S!vZ_#!DfB?P)t+nwFDn=}nR5H^HX?oO-`s(?nA6WZtXA9^no9E>P2v%X7T9 zl0H%X;8YYF^v^!-d5c?qw52`687D}WflyJU=A zPmJx-aZktQ7H2{Fm}m0HG$)V% z1vms~ok6;2xdemB)pdGNKrjsk9c(4FNqN%AaY}@^(eZjYCPFYEnBLKE6u=)o)ElEL zj<@1M`F#o@aS;%n2q~|F(h$7VDJ~cCau$tAik_&stGU_&W^p2B?zkjg>!x=QVTV;x z2_0&+xc}HSxi+cHq*HSaxv}>g(oaRJ>9nHmg#S~kD}5xYHDnWr)<1a5>VQ4gJRN0^&J?w@r4`mt zce^b3!sHL50Tj$fbhca$2gFaiHW!`!*;|!@wE;%??&0qfuxC?3Pa}PFf{;=IxMNng zJS{vJTPM)`0;fEiFXe64iT8b{LM*$qHmAzRNPL~8i&hh7;YU$RBv>Kj!s?YH@`S?q zHaOY?_)T22j9Ifa5Ii<%Opvu>0LbKEpj&aFn~0-X&#?I4+S~LzA)WOA5D5W*NC-D9 z!RTUgi=$00Dy-x3Pu)wmpq`sJwUb0<-3LTM@M%K7#KXP3k|@)Q@F6%c&-7es=vkzn zR2Vf60YT4B3ezSnXm_@$3S^`pjSlNZUGmM-lb1oAq5g~R zn`L24t)1&kZ=q7aizmjJufNB59(w1WieB`V-mN_wS9#S%t#E-v_9szq&v~j<@_HM(ofF<$&qL$eX}`hzAs=@@~rE2Bo9Sd*u4{mzB?Hpl zuqtMF2n1fbFQWB1y1MD2$?DK4Pf43t<-S|VJ%8r`Y?QO*`=OTT0T8D5FTF7dV$KJy zpKM;>tI1=PYpePffb{3A`0`jNY5Q;NO4^tg+oSfUn~UX=3@8+8Pr^El9m^a7?J6o9 z()|HhM)EK|5L@(W6zBF}2NCYu?lhzQ3|0-Bk8lkmtPNWds6V9r>rn!|+TNjn1$WQf z9;+1coEEwKYjI2(DlZ_N89AQEgs4A%UVI_pRQsUlmLn*s6x! z2RDgnL;SQ>LRf(qkbzh1;%ev&4(0%i=nUx;_@o2%uBDnSm0$3s5&czO{b2+cQnRln z`{*dUAn&*;=Lo7{SI+0JS$Vg=Rb+n_P?b~_l@wMNiHW+*Y%R5^~f5;NL?yYB#)h4AgQNy8z82jH9{JMSAYtiE;MH*V*+WSlci@hS94iGbi6veUiy;aAs6}bD0aMrQzj_wr?lUHbArJ{ZziHQU}Uv#>X@M zN;rNmp$vH)ZxND#Y`iSczJZKO;+ss)T|EB8;XD$7$&*MM%VWxhX16tGHn*X7PLw5y zB87P^JPYE(Ppd_U7}LHPl>Cw_RGb|m79~o6n9?x1#Qd(igrxe#_Q=1vJ*7W?X7w-e z1Zc7e8~A4fQ*$iWI1PL0gI#}t&dwz5okJbU&_Uw#o*Bdu%aH9Px))dELQfCrP+q=G z(w?~EFK}U-qqLooYc!V0KN}2$*#b0qmg;_0mj3LiiTu0RUY~T=t)L5;2%!NAbYr7P zqsrwix0X@%$^44{+;^wg*d(z`&H z&ZI`_#y$pe#TcXj(W<^MWI-#EXI?PPA4DI4=0!QRM~MNyEY_7_%YmFw`;J}|V0&CG z?@cvK@wt+?+g+V=z?;99_(FCzAnJ5jBo~cagF{LQF$01DpB$CzM%F~q$fM7QfXS0$ zeQPI@S*|fT)_NE+-{M|5TE)lPW|_phSr++Gif{3eFE5MKm=8BR zD0q)M&FD^AdO~c4qty_IyxIr4{ZDXiA5^7;4g)oW)v0nkw!iRcAnN=3%F%AFlsS7P z!=u9!uau&c%c=yQYWH;NJRhD4Ci#HVfN;Fpe`RoB^2${clF5s99n)@*l->XaL=Jvb zV|sK?>!)`7##iQKOrJrD{HjN7t5aU=<>0h&RJ`NE={qm*caB8x}kpm3`tIb2^s)=#U=2aLnoZJ9quOzW1;FYvW>}TV?DolQUl3 zd3S>lN%dhsN>TNVSZKlbxy+-|DAgQy6EOck|4QUHv7Zpy2?VfnCTCg2$Qs$vlFMsW z*`xYcY@WdewANGct|fJeaz=KibKD4vScYPFcLsB~h12CZ)G}{TaGW*GsBz@+SjHG8rKX8tZ9n{0o@7-=vKhC$};k|wUZ0Rz}`|@)6&+G z+89x;ZKq#pe|jriKg#u+ZPK%Ui^EZoU5g&gkDnI=Z4s{-n;B3yY zJ3T2hHGO8d@8;B&jza9Ha6pJ}Ai=|*M`n-`71{KB=}Qfqj`BsL7x{>Dy0a0cV}s^T0}dNqN?RQ>6ULL zYu-_!mtIK*|7!UaNw?JxZwA@dScp|jG?kMLXEJh2PGIed&Hr9nK6$GxKaM|YFfGd7 zcG}H42Ss4_S{lM8dY{+nPc&JE3g#IDN6H&MmU^FeU5;FoOQ3Ue@iKTx=E$bD^P-#j+0@BH-&%gUF$k%YS`Q5B9}C*CB&c9S-mcQnJ< z;qHmdT>*<~WdPrn70rwY2k;|_c}T=3sTQlRP%`Iyv&JkD8z%HN9CBS-**}lXd_=ui zW>xu;Hw6D6Eg`(R7sGfHVYp5k%Q>3mOqs@!%J7)=h^qwQM@eporOQ=!qbtW;=s25n zPHd-Qzdg7xk8DfA#e;Ab=5|I3IlkP*YKS&+gW;ZacUlmcTpDe-4xwJO8pBk-vRkP1 zhEAvQ(8n~zH-F+4j;S%nJ-6DGMtLbXknuaiF7UdULEl=gmd zDm*2m)+{#Hz1BZB2N$B_CyQQYKc53iUs85bqS|#JHGnlslSU5Sfk4S>p-GIPI!k5{ zuDkzQZ?($xZo{1}XZ;)R;;i)g6Z(M>eZIQ>A4_%T23JiY)j(<1&d>0kntM)RWUNxI zp^bb-lwDA8T1}V%I-w#I@(FcY1#IvX#TiLfCb4<&Yd>>Y=VHs!8juYlJQ&MbZUy%Z z1u2a1ruvAO^aeM0=+P?Lp!U%rgD_fWN_AvM;Wb4MXv8#}mJEQz;d8V+_-JtgJb_4k z;u#5wkM)_DQG{)i_}u&@-S#&pGjm_2xEyC0Mtv({vGWfz@_vN(A|hFJO>C6Rf2?%XgNp?kb>w>d?5SM(X-#pNMJO2XXZ; z#rUMdxU{q>7AiZ1Ihkn!?yC`>Aa39wgy+V%xQX0$_yn_;4jlFCm?~Tf;1U#o+eHly zxNAW zN5ubl(t4ddth{WH$@x3AhNIr7&g-jiSZmgKulXP^lkitCsBU17YK~jdR#k|3eiWQo z)M$HW@vEu5 zV3!YF91+(TC46D>>IL;_+u#nVOLkU%gwaEBf8C1%yM4fib&|ORpiyyCFVs>abGm^A zot+ahzHcYKQ|U@BSvVVO3e@jI4Hq^9ipgS4uas;hN9EXBYOW(+IE?LyK5V#>J(j6SXvz0_s#XEQ_y;uS?rvdOpM4%-oA1ty=SYm$~%4)oV-sl`X) zx^23eCPaLFNUP@Fg|^3{_`()!qx-0v?s1F5vPbm!E2jbuuxY+t)s%0^D7vQxPVVz= zlL;orQ!sN#UET$i5xMb%u&2$#%$`SKWKbe2**|dvVU@>0@+Q{CGfdKcpa+GF`b#i# z@wPF-{6WUx!T;$B93#MHS+ery=UhCIXApM3+!-3c3+R@;#M@uSCNTVI$hDzhtx4% z7(l7-8IyJdK1HEIiZ~-dG>~Wt1cBTx9_yHhb9DQyPt3c^pPwrG)1GIPCA$lIg=2$w zCcaW6bActBQr+P zfy3&1*}t;QF+a1S<)$%_Ugpsb#%FSoEN@y9LF>v&W z<2Rmf^NxX|pN52dH~JF<$=f^$`Xg8>%rzpXRt?KJT*TRg7#HqnMEQu4UNxfNa1&=) zh|>@dTyVj(74h6#Z-$Vs~pa}tf>gFfs!Ell1BN8`si`#cLNZ^0T z8FsTZpPS(i5oMSP&o!hM*8&&{aX7vno4d z7-B9!BpaH650=XmJ7S0-DDtXMV}PdLqUcVd1zYo_<_!lNr16$yROBbd3jX|%wK_^uIK*+D& z0qluOjge;oo>>)xToY@Tb3X z#pe(ndm{}!NGK-!`i zTf2|+;AIs-A8jJs7X2~AP%!W8zAxw5x^K^9=C1nG^NzjKvn<+y#izJRHMis|g`z)gMWQoYIbDh;QxxRo`YOSK&-Vn~ zCaW}-ZE7-3>USx+(6D99hN!5qRe7u?*@dTPc4PV__qw5DD#ZoEsz8>fQx2oz1&)la z3r~rp>~N!!P+hEoqEn)-Q3)h9g0HTp)k!xVX-3?Mo-6jHg-N z5~#Yd>ESfv-|j-%!SLXNsX5u0g}`UB6WGYUfHUXTo@YMP7;`h#*v6h3zaQpc@Wdy%DFnvfmpaMU_GYYPFCc9Q#JLP-U(8ZnLwx$8$VoWkB8HL>pIL znV(-+qPPyB&BlBk8hKGz-~W*53qq;yW+gFiWo{I?tT&rO(|?Aiq5^1|9FZ~QRe1$P zWy))wqrOV($wdag|Azhr>1qjwR9)*(YI8s8hK7%PrH#Su%4HpMr`Sb(6;^BAoOAxb-;zkMB&R0FzUD2NQlqO#R3-WiKv2*5eP=_bDoE% zYwuRjjtnW^UC;9RhIqsvDScFUVPC6<@5R<+Bv4WV(^p(DsUsaaSbtPAgdmR&e=!Z?eM6QLH|#X&t?S`iHBXO6$|u)xk2vqhK(Y!TUtg2IU&SK+tRd1 zG=OvV>Nir<+2|Wq`|QrDo|!p{0(EXI7wN&aZh=LQn!>^uM#U9YgR}AyM7ziJ^Vs>tdttIPM+j zn-Fza^Z}b$*yrxw?pavAEtos-%0}@h*}f?3&m@ZNzn%_+JnN55vm#5H*r>~&(z2?O zukf(2#5&ApzVR$ihnwigMW_L9mu9ddSxySJ@qUd=YtBinSYRNWf5Mesw*iGDw~UMo zQgVouhKXshcsM7s2LC;{26=6_#K^0;Y8pB@CGiP7wP8wm=hQqKlHB#bjSr`XAR-Wr zjz?S2e90vWzJ6zz&-^MC?NbHlvHv^M#8V$NZ#}{HaK^TpQd}a#h2hR=7E=keYvyS< zx-E~9vkMX{7L0f5m+eG1>95hwJCDg8%-CmfWVn~zIL(1DXIyh;FZuwC`NSTQ9`cK^ zizOp2DwlH``H%QT*hP}FcmUz{mR-{qX+Tu40UPW6()Q8Hz z#bdgiic!b>$F4K9qv4;D+;`HlAzi5 z!c6{)OYT_X#(Y*K@KP53HxBWr>5%v7)gFI46JVEgOv zDjd!idc2&^ZXN%&A%GTmOdI3Pk0x&H#4|ab`!N`QLKuIEfik8gY$ z&Fp&I-axKJ4{WpjL>lNy=3h7BR@w&d`796-gUhUfAQwpc6FMDt;89X^{L0% zYmPG*to}zdHgQF!(2&QJ7!_QnhtQ^Y-YXO6Nx$*x2CP1_u)OTZz1GaFkjwr4kJ%vQ zr|=))VY#@&ICykrKW=|O2mY5bT)s^>_`7|0E$%Q58qsGD`yhK3!EpBE(Z<@z2ArX@ zQaDTOsxlBN_P%wbTLjg)WwKf~B&v0T=*9t;LpGW{j#|y$3VWmRpuKvpqgK7A+{W;x zp3am<)>)W<>0Ch0)0@E+t=Q%y`m6x^%)@Ej?isH_eUJ_1eE4TF08jNx(Z_4mXdpF4_gaDB zmI>?%)dqH?!0OBrYd&`C<9gcxMRB=u({=_OUOnsOof)yPd8kv~sOtJ76 zPZAJ%C+IhsZH48%ihxr^0=zAP0F4D86z~0HEOTWENk(*5;>S7+)1tkCZxjXo<#9~-%!JRh=+2>rP7c%t4ZgcOIJi*_o7}-w>>!pC=Aruc#FXo_ zD@WEpG8BOBQ$39>GRTXIc0mo4JN5c2KZs144-0+@Rd9sx(evP})TbE2d1$bCi^CWJ z#tUk{S^>HhGSIE)pwEkl7H9`LXTw=*C39ZL%~-GR55WzM-lr%NDKvUOgkF4lo4gB{ zy>pUT=-Q3lgk4~tn!S1Zran_c{HyvrCa~y3?^f;VvfI3c zF*Y=&F0M92>Ae&hW1ysf(MPMi1AXP?=d7+y-I=~#X8z(1ia2p?H47{K9V!>6zN`Q* z9bXAIMNbKJb!#gSNXCeM7X`xuRp4979FHF#_HnJZtzDs;RFg$?2S;a1Ve<|@p z0(7Y=pXqF=iv9cbZxamA4(xlj9WEZMBz{SNBahi(#^Dc95l+SlpXECuTy47Z0UBUz zNI?^-jT4ZnoEikG|8B2t{Cy7R=&aPvk|KozWLn?2NO#4<(>=o<5t<_R8$bHbfjZE| zI|x<-p>Z-TA~@mx{Mx+8h27}@U%YC43A^a9X>6Q(lXa1X8DQ zVj#OuEqY}56`PCcB3FUlR9eX8mRNzV=e}skF-|qfi5p?itp{bJ# zB^r`(8UgUud3X0Wydep<+hMfE)ZEb6A;hq~A6y=BHABsM@7s9joynw*`j!LIAQcz8 zfWJD=y?Ws2-2VCdwrEr?UY}9o14QqlQ3O9gRQi#^BR*;P0dN=9l5g$jW`Xl`vu<#~ zHfMVT7PimtS2tL@x;a_;xmh>4;F_~MyaUT^?3=;hlt?L_OXA+_=4~{4Z8UTzvykH^ z7elI6|7CHdUa{ffJ|w8;N{w1WOConyY>nk()Gh3IxSiqu_C8 zU}@Odbi@FR#+e%`-8aCX3iaM!jzyN8qpM8vqG)(!1Qda*K$gf)5gC(hfzd=*(9zfaPb`n_Pu} z1KdEXN$a$Nn_z=2HW=N7fCrpFn@R7mfjIGRU((>jZCQqDsxFe32t{I%3vg!AJA49l z?CJFxKTMMrewXyEz`*V7UxX)xcw5Z@-09UjhLI%a7U~SnM5wT^MP{9o znd|f*HT~oZ$M=V1=JAgonVH{zfjRGBN8p{8fn^uM}j;fbYS({r_)1#hF)W#Tlr zyR;cYP3eY;*3NpUG!!-T=_@u>P($A>MSEv;c~D{^g_e?0lO+A;ewmt@K}$)bfn028zngG=rPtcD;`&MtbdnI@EiS7%c7yw*!3}=i35m02AcG^0 zo^8WsAC-OQRPf2v+~l^@BzfFgw{Mn~=zT)y9?5OGEJ|8@4LpSrv&@&>&@ zdUNFOAAd5mF#SQxKc{1Qt}Xiys2>CjkFCKV0+f$!G`0+H!XN?^4L@xr+c0Z&fqG_x zLdIzTItI|+ssZVDQYi2KY@zdKcy_;?yumPmy+w-k6t7FAbNJ5OIfT(^)BwzIUY zYq`rTTS!&Y9e^uz#`ONrM*0xu;oOCS@SV3|a%6D?Y?bJE6|4B3oi5m)wOkxNa2uwE z7f19Jm;@E06d+;`_(P%P4AtcKepaDGu3#QaTEbril4ayWa}}XyRvw72k>>h2w}SZ_ z!Jtyi=RrECTecJKZ_}Uj2LFk@uP#%1{tr;P5tzD7*gklc^eW-7;8p&s!&j8;Bp}Fi z$VjLo)ii-_g~D3|bb^$vp=+?1&IvBu4^LNmE#EPbN~QAk)=tRM%0g8A${&S4pHJlf z7=Drm6vUEwjm9a1u}{|08F5} z8f9X=X}Rm2>|~KOK!WP(ZPEQT1Zk~INiwP>u!>Y(?M-Dz&qN3&;_sWIj0~39Es^Up zw9nlDscG%%ix$^99%}=-yGa7sOn?qFPXh$m4B2oh(`x>FZ5G|8ha^@5(ES9oYQblc zG{~c&vi=$9PP=@U!1b#LU}Z5Z#7gFj7Tx-3wc;lo^3K1{tNI4NOyBv9LR1`oTno7M z>ZQu-*7EXSt=X!-ealw8q7LcbU zpP6hRZ-3VZwkrgJCK5E>lR|tn>W#pv5)q=0M!EQ%)n&RRIms(wydJH1%T9 z$IW;TB|GX%4@JqIXJuJ@T1<3T_oB>is2^pp3Q(gJWmura?ZT$Hc6ThgLq@>p@CrwL zB?4r_0+})5z_|Av4GZ}f``}?ZSY%Ud-)Ak|1#(bZ_vf4H_nsv;cE2-i%|+e7L3ip| zmd3vHA3xgcpSu4hvsvl)9mR$x$lK!G-kZ(ktr^a{ z%*6Xa=GMXU1CJg&h?x0ivG~Q+8R>zM6v$8q(&hP57jI5UJsc*v?yrMW#$V?I7~g0< zhpJ;Z%h2pN5Xk=ln8<($P&a_Vp2$jgBF(;>7|cBNZ1f#?n}k{hbc!E&TSGaXghfU*epq%d& zq_aFMK-i{9T-a6t>7mlY=ZF+5ipGkStwGG)+V=&#$emYkDj_ zNvR^gk-)!Wk;ae`xuHCGWnsKz$;9Vyghk&`ZmQn2Q^Xm1(z>vPA`bAJ=2D9^;n%V? z=;U%#I-jHtm2MuC`PQ0Dw7yk3Fn21c4V+dW%=I$x-v&Nl0v||o%+F7uutKxqUYiQs z!7;N=Z;rl$vFm^a^<%wu`pk{Cf2qBjhCI`P;B%hAhVxgNo|eY3CZ8V*U_|V-Y{NtP z>Yfj2}!@yXS?hR!wyKcM5Ee zJ!?@=zlsd_j`JzS8ktw}G-#x96k0@(1%Il*b*b?31^K%b7RcK$vd%MKtBb$1tD?@; z%J^Zfq>Dp=-==b0>QX^2Z|zsS0Pj zpncCxR$LZ5R$oiI0Elm+)yyT$4g}=ppDMFqL{qr!me%(^0}UC1215)BJ#=&?_jR#1$F+Q@JD;L37do>_7DKK;^$Uz*g$@CT^Xom}8*EEHH8>QPi5-F$2GuzJYA)AP#rAck)vkNrs_ zL4lFudvW8oo1A%Ku3xQqdw5Lz@W%2Qu6F)$y;0#$r1{$I{l2>0ko9ZO^Qa4qGatzI zj*G9gw;Tu@tR8?+elI3fYo2L7k8iQF&&=<$4JLkkpVhq2Dh3QDut*k{>zueDH%OMe z5J-rtYo2d*PI5GEf`|YJ(+V^*aq$K`55xz}zKH6w9%KWa4mR;gCu0Q_PP0H2$$2ME z?VMqX)f8htQ`?R1u2Z#Yc+QW~(s2@8Dke(${P=U#pcBA%#N~CT*A=#5>psrs_E$#P zV-BC&_i?ZV&+fZ<-#%tClm-TrD=?s_C%8-Kmuth{u7XJ8j1>Idi}2_ln-Bi-CHc`Yi*FT9Mmzdc2p%TVO?d{n?KVX? z4SM4d(L~PA8aP`A|&0# zo7a`Z<`K`NkUFRnnk#Y63mhsH$Rx7a(b&L*pHYAXC5SSLe|GamJMrz|7~X98#WO~p z8{WX1cB0vh=W>*~T)Un0QXu4|yqci|mOcn}W`b0*v0l8+^sIgA9H;OU!Na7p_wY*V z{>zcpyPvdjAO3Xid7#g}9K#T8f4T|ZShd{Xi-f^A7zxr^+Jd0~nBlrD7Yk#dqhqD=LPM5HYeSSw&&$*Zk!Q9QvvP zgHK}p)1{iK+G3qr^8=QV;LT6+)b8wmz8ko zbwP=VfRo3KdY4!yHVtS+PtYu93DG7ifv7}&0DFIg*6uIkoYxlDBwveV)I_}%yDDKC z{DA2psg$jOx2|09>FnUEvfSUiQ<~Sj8o`V*vfS8=I;7-`sVWiZ#%Ep6KR$1_XC8~X z&->A8s?xcAoZoBwe6Sua(TqB(p3?M-HwVehj5^|l2|n7yb$v@J+93{VWhvSmPsJ*@ zQVJ20E4gwscbzIMeaIlV0D0E+yr#^HphOoumvbJ%I)M@Vcq>G8FvfYJ1g`cge|p9_ z{7R_o#Ki0wmemB3=6WI%d2?A8Z&EPEU4KFev;Ir;{DNMdox03l@JWp|{>ILZQh%?; z9j?(l`S2ySq?+Bn`6s=iigTB%aSgS*gGm?tqYCp+=3)UtC~OKn^;&MY*k}bgS89}f zZJ#VWmD!KO+>AsPW!*|kFqW*n$OtypsmuW!{$>Qyj=G%@pHwS6@kVZ>#ON+^zSszT z^?>|5kZzU{@}CT_O>hztrT6{_T)n4g5Bz9xT+o{AWUhg;74ftw(z#~)9fup1$f0?2 zo-38LnQa!TN&2*Ah8x%9osR#c3ix)i1>%z+{$oqTxA4Py@{tlyd+HzJid&_Uqp(pTRjjmdA0(Wb)aEz6q5Zy~#4yS7s8p@0XM( zUbRmefe5((TdD*T+_023>f0){AvV=Zysv35*`?PUya^p~?ma+lFnz?p1-Q5rzW;}j zu#711gd77dP^;@M$IJGL_80W8ACQBLkIw8d~00D zG*Iv4g3IF7g=rZHjTz1fogpq$OJHh%SU`ku>T8hgGbMFIFuOjHWDOoiAcD^tjUkCa z)DKa{+ic3!_NuE}gSkviD6*u~#FIgcT71ZS7m_qL&8G;zp)*T7Py6^IWD95~V2KKb zu2%eJ3X8iG;eB0!I^9fpsRGG}tl62^UNE2&>^LILE|Y(KTaF^F9#woMPb^1${k=*i z-}$Ihvyw=9S>Hw8UL{rCslG>!e|D!Y{^e3qHHR^v!ijJZ^4K-0CfGvvvo&3fH30<# zK+ZH}u|og_z?_^X&W+He@oxh`glL{SgXkb^)rL zWT_Sy@9ee9X7W7ra0Nh|-9%4{guN?ctt;qKvNrtULvo~uDmrgN*)Pp4Z1mpj^_5)c zza1uix1_ap!q@X0ZE6DN@&g0c*}qiDZ|BZRT;^YGCLL1z)3!a)1mZT306FDS(&p&e zf{k*iYqKlA{CFFN+J?J66{^GEbCn)m|z)oj^55QOYF3%NEleCex-Utkk0Rpn@IUAWB;>Q}KOW8*Kh-RdOh4@&(&w8+>Hibll`mND7UzfakBcPK zztgb^Lu)x`VY6-HRl!yOWE<9l00|&_X+ITVoGUWU{){?O^n}~y$3wr%A1)WaN*N#G z{mOY{Y!7aHq!TI!)sx|F5#bRolisJq5BN+^jC4gfMutZ^PWu3%)|1w?(vg(V9R z;1{E2_m<*!961E*ni>`vS>Zx$N2JOxTV(JW>_SA859VgHR_BSadC^uoxVB@;t8Vc} zO}F!e_e=uMYXLG38Ia(2S;~bs0g&JebAW_!U&?I6q{3(MBbMn}lQB(jq>$Cnchbzn=A#YH&h^;Q#4e|w6 z8wM3i)hKEGqO~aJhwj0r2Li29bmPkj`ULFPLe=N9Q!+#OGQF2^>I5z+@B+M6Qn_42 z@!cth=%&cP)D;8#TGUxwix?0No%``t`b$$;rdQs@I&9k-7Ba z?U2|Q4t{_yBqUx3{$r*^DdUsy3L5Hu91`DkN7|o|zcVd@!u~s3$WpV5w6Z7rFE`Xa z!)5NutX23u5PeYYr@po`$yHNEch1nxGCSJd2~we<((IwH9NBEMpu{fvlim@iI+u#* zp@qnRga|-_D^6%Q2(}F!_=_AL#jz!qSC?nMlU8b>b2h%B~1`H zqV*^mzMysRumI?O395<%lLOTTK2~3g8(x4Y2!>sK$8b(@>(Jny3?Qq9#vw{U&s!Mm z)s=I?iq!+PA49RBPNCm0w;#(?Hwwdf^Et=4!rboA~?ZwAwNz1<|dk0 z8H-!I+L4(a3dYv>9dt<}vZ#O+j1y;$UmovXS(G$68O^gq&G`XcUHO@*lH8g^JhA~@ zFnACq&g1P{66@O`?$P&Fm)i8_MGmVuHziWY3`Qc z%ud#`L1u;V)wg)*rZe4M4yi(pIx(${Eg{Pdfkq+R$TRs@D<|+CT+&=iVY>#qpw`pD zLo<$-NO;S_F?GnJHXg6dE%D%xH}3cJZ&x2A3lgw=9vs>nZZy}Aqp;j~Cggs6%R(+A zoATeys*5}w)6I$kxV04Y!|12(XZ7PAmRDjbLY?zhomtj^e9opFNiKG@j>TvpH|#TX zJjr_kll{fBqp=;*&c(4o<{(5CiCd`>gJUjV)!t#RmgtJ&PpXu}rdtT3p`y#5P zGvfGZg}pB?;-3M@!d<}?0}4pzq4AHI1#-ir93itBT_ZcSeoES$9~qg>x?(J;1qOmT zV)w-U*8A)RXE#B15|P0+T<%waYo$9sk~g=4gfF0jV%1ull?o#$VlGzHW?a-zm*5w; zFT;y90up>d%!)gMdw{gW=Ahfi+)yJ=9E|mz+cQkuSlwKkZEqyU4W|rcj(Xqrt*3$C zbLWuSC39GB2RjCgrAL64WBl_3k@?i{6~ZbFW!EvHNyjO}3EI~>uiapB9e=sDyC%cZ z60=pF#R9CC)(MMZo+I5*3R%@{l0FN2vpbD>p-%RVHZ_FNs;5rL3tbhbmW9GDX%k)S z7+8%xJhhbL?)pkhC&ylb1UUbDY}2NuCK&5Cj_O~hw;Fu8wznq3(spb&!YvA@@)hr2 zoZuZ$7#F^OHb&wt!8p!$ft?V#Pc`Ps^mN5_%?msJ_l^7hZH6azJl+`DzTJJf;%_5o zW9lK~A-2R%gHJWm;)et6Sw`v?by=P1WGYeyN3H#o9hhd>rE9!|4NcsHz4^G5tH9<9 zP|0V0hOC~B=8V;%9@ z!@#qpZ%=$IcojNP`1b$fKL&EGhhZbY<<9hH?kAPyKgjzAX5)R*aWhg~YRyv4tsPa+ zpnin~tjtU>`Xy3*YD-dSa)AC$eaPHSP4mFH5ky1T4(RZ{PK}fg7y;o|eS5RttgtGP zMkP|g#tFtYd{<-&=euU3TcqNQ@G78xu+SCLnO$7eQ5DlBYlO44HE>p^nyiX%&nYVD zs*dkc(06vQ)^nzL)mcYaSR7ZooS~DQm5~#>DRsN3{Nln+FxupdTy3qHp_=okE53us z;+VZd&d}A)+Q3bmWpT$Qt4(HRr?smA;*Mg@xTUab0ry z2YKcW8nG_(Uz^ton0`k}0@##zS#xS6O z>OJOc&7DZH-by_qyXRAuAjUPA&aaV(^g|y@lCX)G2b4wa!jtvty@5jKyC`Qe&meGe z5_E<*MRGz{gmb^G0ty!Qi2O5voCJI8oJQwiiR`J-sIm8y(s^#zIxM?M5f}aE@Jf$L z;V(Cya)0Mqdr0!>8*on(T`2N6n9>@*UVlCKaT-t%>wb<+jW}_oc2j~PFvV_abW3d< z!>`IQqHFLo2Z^Oe!DLnwMcc6M@(>DUK$AxQ*j@>_wvBeQ2~~EsdAOXe84PGZi;V$v z#3aa?_-qLpmYJGAg26-3k^$r-Ihc#+PY}rP0NFs0Y4aN0{N2LrTC{A}yO4%ynJp9D z3xuihnsS+nKf!_(zIIg(R7pvFv(8z*HGciae>)e&amn*6=UKCz3wxoyneWQ9Jb8it zPDSK9mJydfzw}%k z^x3*IS0M$%BZ~EoUYaegoe3dZJ$VTQb7={;2?r^@L;AM9U9qp4&K_B0f;SbQT>vEO z1y(5v)D;JJ`fET>0ML6P@xAN(yVkQn-Hua5x~Jqd#5(;~qg;IJb3~{&j&F{@5SZ=fUdRQb6;+ zd;WAs?l&}8&-`y*cPIFx>9cPB|DPvJksOdejtKHea^KmAs*;xZGBQas_^VH7s*%V- z9|uov%QR`y|23ul0F!DWVynN7739hmS6zs3eAn0#`0YTbTkgiw#35^k8R-8L?inAp zQGn?7P$7Ep0w&$eL-xRyf_E+@HXZi0Jj~2$;n(O&nwwkZWO06(fhK*iBGY zUJQ49*A(`(%JEdmCjWndh;bM9OowxxYDn-_D|K~PaC!5h1n0Z*-RzXNRh_Btw*+n7YGrNRi4|f%^5oOu|)Pdq6*K`zhIV5cMMs7|ij33CpzA3b( z1a$yUpM-^+Ly77oFr4@YG@r_1)aJXdT+IPGegIept%z&2XLxX(JD)p~h+D5mOj+0X z&^h)jcYh}nCl8_nnZ7{Z)7{d75aJ#N;xFE}>{3$RRdl4h+orTM?NCxJV&u6SH>`tj zDiyX~DwQtIHnu^|(+IcoRH;DYfD{7=BKRzTiA zFXq;XO=x;#BZK>S$LVOD6#*s~;Gux3nu|pq?=a0g2l0jXtvmTi@5|bf-@nLjUO8T- zFF(a-;TPy^MzGc{alvbry4#prhPp7}XcPy3gd{muHNJu(h7jl@Hamx|$86VHbCJb9l^d_4iAHnnj-$p43DLL+n3Bwac z#!W|ttHPZ5@v<;-Z~(_^MhSI98*FxO#jh9})vbJi^m*(Yejcpflx|DmoiSgeaX_k2sQ%y1txqOpOQ8vhiYjDmdM-SZnb}~ zb}DWoZo`p%B57f}ej8Nth&vWua|;^IebG~+xZw11Icz{gU8 z*nq(CORn9Bz=24A9b#y#xW#^^iW#(cJzvfUVF zFxq7}V?w4reUiOaAm`*c8Yn;Vc})w)UTg-{xhUrX1KrAFHLmW8NjLeifWYa6jV7`p z9TQ{B3p8@-EWO{p@w+OsRSRvyW$#1XIt!kg>Uy zbq3NLZCv=8DB7D*hV&_SmS&xUCBRLnm54=k#&!O@I*{FmsejrByPIM6T3<~~R|-wm zt?`?pEQv%3v{@iDHR))a4eKIC^8?s^)8>G<{!sV6Zkw^7_GIt%gQZR5`+`4SIi=xQ z?}Og)_@e3}h?WRUchoEOsjtX@lAHF4elt@!YCmqT^UA1uGUA@<>JMZo&_6G?FCm(bLiU$0$~XnY1o34hy|;uBdbd8oz`-X+ zB*PeC4;9DF=VVG*e9n#=8k=dA+G%n^CGZ&gzud`i4cTMgwNsv$|Aj}ayZ9Xk~cRw_N z^eKoypXQndf>_~D{d_fj0(&Xlvp`jD%Q?mn9<@4#G!>*u8gu3s1$e-HeMHq_422kF z2V{CsX_ddk&QUQna;~GfP#Z0Y)asj{4h^_g6}k8Ca2(n}I5emj)GD5Z9& zYPpr6FK=_0Y(lF88U`@v)C<^<-rvO%U@z7Jyz(smNLNARU}r`7tzr3sS~EKc=@OfS zVgVq5!j8qDBPqKE(x4ft+OpDgiVzeUiIdHy=V8?>>8A@jzV16}bpV=!|lk#e2Z-!E$@&Bj8b#45fH{loSnCTDh$!rHak1wLazFSX zGyc(%`&&ukFHQNsR9CfSZ5Yf^+5b0=hMZ*fBuPFi!0Vrh4hHwl9FOD#58{Z3{6qBp>(!i#YxM?JV(RN5>*hzaIB9E^fs(3=;3Yy4SR@0Fcus>AwPl#7XXadUCNqnL-SiQ? zlejs{P({^8`q&-v`FRIXdxj~5zXI_f_LbkiAK?@gj|?EN*EYpItv*Vfs_Y%Uj{4iI zBrR;!c5?8)04?7c4W!3O^`wG3x4x7zH_QCQVePni{c@D&y7SkKd}D9%*aio%OVWOg z`vR+g(EXxT6Ls{-ZGPqYCcN$@vWLU3E%9&f<6b86;G);ApmRcD^dGH)(%FZ1^KG%U zYHn$geI5Ghx7bxpsWY~fbpwGpm&m|d7nJCTU*10lFNw`S4Dv2u@eBbl&WS^u!|K1R zrm=uxxLYTfb?89@Rr1+&7oHj14}^>#DuGwO@ruHS`G1V6pS0$_QkH3YJqM#V_878v zdsXv~Cq*3Y%8>eZQzotPu2k+LMN$*mS91@cNPi_b z$Mk<0Feq5VJ~h0lA`Fne>WReX;qx#@RUGA{;9e}f;q82vXl|$ zc07K6+=VpLz^4-dt~w>*onOGv=joxjW5y{jag;5 zm8w`5(FSsr*b%M9r#Mo((;Hp~f>6BkOI&nmcH3o0UKQuqJ0%i9IVB)z_$|;qtED^0 zVMDcFg76aSq7OWkV_m8$C6r!t#0(v1ZKuxpJ^n7A`QA3OH>KzO8s-Qtao6}J<1-wI z`^R8I@m1c0ytc_`rBTL!!%(b3nfjBBLQj zmlbTZGX}omsK&Al$QuCg1B+6@$N^dF%O*hmkoX*um|C%3vTh3i;}Th9!=4I|!)k8g za5p0&t8Ps4h}s)Cd1OS@P47azf79M$Si|Q9M1BslvCIKPAoedc8l9y;P(}0w<-X@e zu%yV7SkpNh1>COZrJ=SxcIJEj)_iegmiqjZE?A45LhI(CUdD! z>B4tXjoeUifES-6r~V_qPCtcv1?0gYZsqrHYUMe&5qK)^@-?6FWuFVJUSG|Q`T!R9 zOgqmyShZchy;v2j!@+1XKmb|iR+{1H{GZoKBqgTZZu8;7F2!EX@{~xqtS}9 zB-h_&GO}g&bzq7uG{iTjfa|mw4W%})2_uTMUgNtCq4~Vg!(epT0NFMagbH2vD0Rd; zCnENc!| z&_l{H`h*0WxG`DTl9$h9y(7KNU;0{Hny)T_JlW4VS_MxJBa>_E;3>yX(~dKou0|#{ z*1?m>L#AQJ_?OZw+Zy0$^QRFDY_pRjxxS$Vi`EBZ9b*`+66oxWikwA5TVY)^DQ}AI z+girej5~(c@J8V@4WZl$SkqM^oPkT_^x1>2hp*cB6F<7v(7}6lj(3fi+Nt^hC_u3R zMABjZh2FX|(~T4Iy_n;PU$9!>KU*cc6I5?sBVyiS+lDCkLiyUN#=d6Szps6UnO$U% zy_D}gyWo*XC?F8b#5Hp*jQlk9^%SmIJ)=S1d~sFRf6@pQbDzUu(j<_ zfRc}6N8~1ban7fvlZ15hBeC9&w4?1VKp^-~a)QVKKbtN6DYJp2$Y636ae3u7gU)Ho z^!(0?EHs+S3VD2Ip~+ZM1e_MkU9XL`e~itIcw#n+9W-+*KBCRRwtn)qd=Xd|uwpiZ zeQ2iBPiOuHZ45u8F`o+VfA1YG%5;y}~os)`Dtezq&a2Ce`V8x8J4$~|M?NU}5`x>I`l zW>YW$NV^Prx5&#^ZI!lCJ~lFl1ywq?Tgk&(jixnc$(OzWVT<(i81{cBD7_4L9RIJ? zu#CyM*^G%W+>VLane=I(vj89nKqiFdsN_VvQjwdZkP&kgQsCV+xyjcld_m4x^5uD1 zO8;5sJsxU*H{>mlJo=RO#5cQ+DuR{PB+bP$m=fgWRfr2UjFm_JOfxH2*fSRwXHY0p z_DGw@#7u`~WL@2j0%_7Gk3p5@bkA3JH;Sdcwe;WmzgE?R5Q@TJ3$m}nFoTlQj7@a% zC6B1_plrgm-KfTOlSoZNUtL{&pKuLRvj`0%UqfnZN(?Z#f%w7>efsY7fq3m3kaGT1 z^v1KGoEXv7n#+NT;LI-|`lr;bx)!BuxTe%Q5%UW|IZ?@M!_6_oqVjj14U^{Kvii2F zss{EE3Z`bE3i|e{Hd(%5LV8}(s%8r2F|MAvUQ%l2isob&keuBOxuV*X?)j>*!|rSL z;EG#%@mxSgA6+mz2PWFcDL-?0h(QrMZ4;Ax**$7JBs1gMUUc(Qvv5rVUtRay;9#>z zZ6hyg@JNaP5n7wXH#jrPS7oojj5+CL*-K#bAnu3n%jeXsCL%BjNd3z1%0EYI<{HI~ zF>R|hF^gg|!O`a5%kKsW3#qSpeFbM}&D^5cjZ8W#j7+0A&0J{<+VXnYkrJitq!o4V z@`!66x;ecd+}va4rUcHB-xbB5>d?cf|34gVIJHwuI;t#5-L&WOjfn|!40lkkaYq+c zw`V%%Yn|vMYuIc@fm)9*|8=_sLq$n}8Bs(V*X!bvSvQ6Z8LMCgG^2~bpQV0T03(MVTRI68YXfpHVl z6(2AA!|I|kvC7@9i^3zx5-j%^*la^$s;=Yo<4&G^6DH2>~yNKB{LPETw;@k5fF1NPx6Z}YgT<;XOUo-&*WjrF)v6#`3sGwAfr=eIc zMj0|i%}KbjlX$2m;t+F{%o0@ti`?b8e}@A7a534E=BCNUHaSz?>y%>{(YU*m;}AmL zRHMvn_NV^9Cdk=IFT-f;-d#>xK$c=r2Wq>vFtKXxiJ> zf{B0ctoW>>bt;_5+?K*JXz9NAzZfF?FDABaWey2BaE~{Mr92Q;Y{65`uGrWYKYbRE zO>C+4%028X${nnAZt1ikUVtR-8rHUPp1N2jl6$NsCxVuETvup<)AemOob(j3AY%uO zw&TVgGg|?+%d=dyR7d#aMsm-uxY}tBl1t_W8sFf|VlazSiJUCLk9u6QzYT*U7vl?N zLw6Of(8V7=y!2GvyTM8Q@3d?Vzqb?@F+@*t0>ncHn zRMkAPUApMQm+%P_tM_vP411gx+ouk^3Q))LTRUP)ADKprMX=Tbtk8k?m$mL|Bb4Sc z>J!X$@6czOUV0rU`|kb?_0GB@}!1 z%805jkBKUu72mcQ6sw|*WeD3fA=-V=^LuAaSMQ_s)D!4pEC3A&2iL<5fFS9~3rKK* zACwFNMuwaxq?r`#?7)sF{d2pu9 z2nUAU;QwJ7{^#e?uSU~I=Ot5L8^18xf8$zo%t>&9CnzA0FS>j!a9NXp*P6I@bl#$AAA#CSL*`} z3VdI$lRmT3{x4;oCZ8F>XSoJJ=P$QBEstYKIX4jiXp_*q-Mxz5h}>I{$N?f$KgvuC zcXh|9+zoW+xe>0`7W^gB_sE-BT*6ydiY&E?a;ZX5qcc-Kx#G5I;|<|(_#AgTBOEz+ zIF8D>!U&7wMYr-~@d%u32JW=DHkdNNN<*KPy62l0@oX=mqW(Dn`(8?-P5gzFWdGX{ z0Y@fC(Due*E3y)vMOMi@a;v&Je@Fi;s&QvcyINT@H6Ek6tj?c;zWQr0*(iPKa-$?? z5!ki>1i&}I0Eq<^_poHtR8EBO01mmbwCaFE`|o-2UcN5&by`BGXGpzoXTk@z_^lcC zz@cTR0ur*4Z}Cxe&LG;?gE+yhuG>Wj{24AnFHZQ=2U>O>@YM~e2C2<}qma8fb?d=U z=G~jp=Z(cg4Kd6V2eLF?TP}`v}20nR&lp;2kMNE3C03UtYN! z0v`j}Et|We?N`%T3#_OEy`pjA^H}pid2U1FAlLRru!*mkpM5rKV$Cy)k>mV{vDSmK z-1_`J51vl-X1=DrLD@Ccjp5r5RlYatUa4N4T%sbGEo`3Wjj#GTXdjskO>93VyG zSn*yam<>YM9}Ij6e6^V@5V%jEb4FH^Np3+Ow(ZjU&D zfnZvz^V>w~M^xM4zP)qG{9OIQEV7Yx6n1JsViza-^@@uuc+kp4v z0%X7-`5sGvk%|s|DyoxFG_dj2JwOIL`}gImlRy8Quo|iBIV(Z}kOBUL%x(QhVFu-V zkqc=xfDA}*q>LE2vLff*nCNvI6T!gZG{RndGHO$@^;%2xBc5qG>|c5Z;pynd;>{9G zghyA#>FvQZP}{}V(TP9lB)#sd_?t20^=$prVEP-suil7BdJV7i^An?>ftF+FV3lb}nT}Da<@KD-@g`5HT=WvqAiuNfUy@t( z`iXkh((<(Eeu*_bV+$#?*x{rTV?0}Q0u_!bs4a*B6lh2w^~-vGQo@KKVeosyZT9R? z4`LgR4Y}LDdtP~`c=7wl_hO};zWcwutU(mneOroIRWJR})!&uxQtDCqMWjHc;IY~+ z*;TC+Y%N8Uc8afmAN^jeyz^jKf4fwC7YBej%Y(b_q8k6yq3#<#j_`oj4-3UL<@vI;k z9Qnu-m?Z~Co9v%uHkR||;1v!9Hs`E7j#p4;M0O`i#jgA*{msa)wo|UWQ@17Yh@ZAO z?rd&jGt=#Pd4Zu8AOI^n1^5VXH9ejfvnM|p+bpb| zj9&0?N9($*Q&-F2jO0TfC&7XV!0ZlvWG1{aKO|4t(Y>oyNfgQ1Knpo9WkqQ(i#VlO z9A(+6Z{(2o!_T>00F&ZShO4Vq?5{M=cBNM=O(hM+eFz+w) zscoLDO}Wtd{`Dvb2f#y;|F=KZBm~_CI5LsPI@iET{E6Pf!%@+IM+tsk|ClAt7HG$x z`B^~Wf9iHIQ0!O#El&vOICb(2yNn~)xWR3l%&)HND?%$5y51k27XBf&|Mx#OB<_d8 zV8ZwjlM*_n+TC}}FfuKK2qow(tH?QiM*Ukz^hm2a?!yNP1XO~Mw1A|eE#Y2-%+I!Y ze<6R<6%q+}q+@^oV?|nGx`rURQjR6A=P|BnMkZodN-MI;UbGzu3xAz%V*H19lrHNj z8U8-Af0ZauD3Ddk3~+9+f|L7C9#Ka(rgwj!WTaKCa0zKS*c@+u4w_pDM4pd zZ9yhXRVT1y_>6XXRFhZwyri!cuM#EKDo#C|y~}w4$GLc4*J=7Ub;_IB5fEzv@f*$Y zhyQ&u)`%?oqgEg(05pxLk#r(tpgx3+VO(RC$29=ic~%zve>Endfx z5}{J73KxTSzBu=2|2qG8q0PSA%QP&<^wgKBFD#w!_eMnmME06{-if`?TtfPH2qy*^ zkH*=Y^IROn=E<*wPBT@Nh;M7_Sz1U%C@y#EyYR`IU}OV*ZG5N4mu^3}I4yf-dh#hm z2f!o3bynV3>Xx;uwS4VRG@iF27lM|v_1*Xs8Fv$4<2^Axe|sbGsmbja#icdB4&j6# zjG^GsRwpZZlZ+$D!b0M`X1Zwa;fqnx0O7rs&UgGZQ#Cg^XVS6zZZ8UL1;$6yO&{iZ z>B(VyfAS^kpjLwH%-V%JSC=Q$Tu-Q3TghVNO{|yoTd2O06L+lpO1;0_wb(8eXRqqf zUHN5EdNnx^x3q-}{VB}b!)B=zzz4SS_^Pv;oyK6a3y{jL6?%eM@P4kTurjMST%tJM zGCixH5Ooh;z{a89nfa>c;A;a2jkXXLXdD_x(T-aK09N^(Y3ZzjTp1;Rq0HE0$|(SZ zHX5^|583SW(^XPFGGMX0bFh312o@(N@VFvDM#Vo^`m+Kk6xdy@>Em;nvZkq9(($Jx z7R-(Xud$*LbbVdKXB6x$p0;D&_QJVljJ-Cs_M*(08JUaaUawmod=D$XIex~x#+jMf zg$4AY-aeE)J0p9cDtM(C=2bM0DV+1R+m5w(+KWdaRooLX-KU>^QPXy10RE}`uHwZR z9Sx@o$;1VK4Et9xKJ$HxBz@2BHMqGcEt0MXrLw;3waD;d6{a| z!8qL@LhytcL0&g^wc(2M*58xAf7QLjMWbRtEGizkav31gv@ zDpJf_d2b#%){gYPCk&V`@*f4VU>{5#7ZUAjX~oR}2!tdjL_8Am69F0UdxCR{IcYb4j^0j5to;=Q z7IceA0@9I)EGTgV$ke1|d}diPTw-~u8_?q+0-ejNVnWZ*-Jex{v^y1c+`=u|GK-QG|;1W zk7uk{E^(1sCT%c)e9kx0NxGODTwAj{<;EB3>AxNQ+cm(?IuXUj8yr41l=tx@ckO#m zBe*~Tj73Dex4|7bS@D)<$(H5`uTrt*f1S zqIT-my>npcoKms`01qfZbVNE@m6A6<{6s~Lc=bh4=o!lh$79*lS7^A>a5?^ocirdzIxbzl3RhH5;!E*2ZyERYW{XMr`~m0e|_VPY+kM-(MYP!BJn=) zm(Qo<=Zx5Ed5ui*ukwLfOE31nALShUZ*ucip5rqZ3Z1~G?d0USKS-bT?Si4FrjVtj zWkq1^awaVKe*Va}#xiDXl~6D$c$QF60i3)ZV?JLG21FXC3`$jG3_m4{ud#s&o;ut= zWyu$V=)WEZ2(<*$| zOh8Mzrc<2a*pAYYz|&_BYT0!xe^`=XX6t8(zy$!_ed~}&HXe6Sh35`?0S*Py|AzkA zW$pZ0I9(r`eTHj~BJi?n|1cIH^`#d2v8u>`7X9%}k!3XChOezJNC#tA<`rWTUi_uK zoc-37ny;)u`CiB<8MFvZW}^UCtJl>Nh>*)&4=g@bj&g}oEb$QmKmrP~!N-oqqMq=3 zXWIb1S^8x)J#By>qKiEMW>$60;dcg*PLcDxB2Sr$ z=0ZrFk2;u;au-#Q=+F0&0{pL%2!53M>9-?NZbxOL-12+UGj2t^0YZA}?dcR2ib=pG zYLuq2@a$Rib1szL9@u1GaCA^IRk>Ih&>7=L9h&nk#o#yUM&Luqakt&&L8z07GTEEZC$ie4i+q@@cT4|;9JyoKPh=8d@^-8T3(nRE%>iSxekR+5NZ`C)DJLtdlqer`Rr})!sbWh7_ao zNomK>^O#&Rc}{d*o<@O~5R*zdhMbk7km2A1C4US<;y4CK7Pp{1;mLWd(<$J#vYT}h zC86uPmBGb=xF3#QZQaPf^wW_^{b_hud-Tb;?yCwI6pjWI6CqdNXG=@LBNT|+)ivi9 z;##Z(&BF|dH)i=MbUPUF=05>+D}O&b+fTES0X3DCbm^OPw|3)lPiDra=Q5ZEttVWb zKIqL-i<@DWxiHo;*3#Lr1J_%|&?!1Q9(1wM@}}j{3`+r*g7yR_G_s;GfZ!?4Xpx%A z?Dzz}z)u+vINZmwSzk5Y8Xn1)t@@L?n#T(_-HM4%jU}I4R`tWc6AjmYiQ?;|f!6x+ zI&U`}UzQ6ZaTz?|)4=E0W>WWR?Z>>~y`Ov92VT530j+zFI{7TZxY?>_s`20dTx%-S z@VkkJw$X<1gN`c{IFlA!fvdVP?m){y69Pa@3Q@Wy5JCKW48rTp`}3vAE_t*#>PDLp z27=ulCu02*&R+cI;N%3g6)2hv>@yP!nnfC2YF%=&Kh}OA^Uemed+6Ymyi>+S(@H-jm}JRsU*P$4yQNFl<*I3R>cGAM1fxAvD? zZQU=o-n{f#cz!QJ)5R7Qo^(>^q;Ue~hK1Y-KB7?x^Ql3gnG-!JGAG;1*Xj@d^(kfnmcC6%;c(?N?&OtZ(RUz$mG9Q@~Lx%IH@_o3q+j zaQQNvc-$*>_7c3m{DyZCKqmiQeQQf%Cvt!T>o0&dd=E| zO2qBHGCRF5yE&>a-`5|`lsAO3H18s|0uHva1yl#*$+N;r{*^W#?VB`xYFCX;=8akZ z`lZk1e>quf@h%|ly7JR&UYKv@;VkRv0^A{loQggvx$C+{AwEH%;(Wq#p{%(~tnWVT{EYDYATcpB_2NC_)tK<&%)E z#MD0Z;K(8UfHHSqpQZt?x@pEaI;J2^=Kx^3ie+o0ISgs9!rt(o9AS5Bd3MjPauiwp zPkZIBzMe`CG}*4|`R)EWBH0xX0C_c3A)5EX-k~a1r_%o&T4R~e7x;(jcn+5bgoJiDdkg{U*fHI$Zg_fT$*g}+jp{yx$lnWl z=UlNmmGOUbp#wAeBL5Is4u6vzghY7``Nv+uia-;}WB9>91m*%}fBU2OG%GT*)jh-{ z+bVl&FK)jCWZ9X$FB@NWL2PG0B9gVAV0`)2SxIIFl;q1dC{YGhl+4S;i1c&ar_;~* zglC?)H<2+8p}Hu#p%46%Uob%G>-KRl@(eOCi?(xe4#(LZ)g51(zkaw>Wp9{E$_}+2 zk0*iD-|m6jg_1F=&^@3#%@a?SsH#|aLJg~^@AhP_~<3)Q| zR+oZd?sq+?o$fg-bMIjx{X)sKNo1d`W#qR1dX#%$d6$)>tnGF>lEmp8M?9XI5USYG;nZuBMZdBT(rmJ zdox6L3m!yy?G_dG9Xw*}`gi1_MXT99mvbI%Ic{9wn6)z<_Heo8=Uh_8m7Fs%0wlA- zswU}?*#ciG?QISaQF!Y2qu=x_8#*gsP+ZveK7(A?1Hq+hfyM6%E(60^mX+{ZHNBtp z)eD|pKb0GX1Y-3kEOrJ)4!ZK+3$k)_cj+)(N~p;SE;E(cjh4uVd@lQ;;mdx&<;JN1ZXM$anfe zjiptM&+7AQ+rYOT`{1S}%OF4Th@_Kdd)ANkH3*=g>6>xxq zDNrkUmq2!)rfV}oqJd=63rrGeLBX&F!(tFaRs(}!)k9*7eq`V!eQ+KtK@@#Ff0wu{ z20P~&H9@4}qQYt7rHkLVY$S^bC=D9_pPrjmMhs`XQVl#cY%2cD?I1Zkg!c@0M+U$Z01OcHk-(aU& ziodvZKv=+#qhy%p7>Hoa|3B72{FmZOdayV}NYzQj@!06+)L>KuT7}gXFGHfi=dFi3 zqdUMSes_Cp`>HtIY7#@-3p%Z!Kq9u9hc%cMquA9FwHhF?#Q_*@tQkUo04-QMq2B3HOKZTk8q<6DdbeEOSr)Pn? z@_|5VO{VBIVyQtxp&FH9iC$ewBHtXOB9od-HfWdf&W9~`3{t&|b9?1LrD|xC=Ibo2%|Pkr$|>miclPPilY429gVR-(8+Anb)G5|a zG=L{Q8bwQPHYbz;vWrF}*XsZY$j%zMSg-pDtjW7h&OH;irKq?~x@hVzpmve$iF-R= z_tOI1^ryW~dqZwM4^TxpLE?w`G7;b$ciW9?%v5CNBxC6wty0E@eIB{ibaMtF2~YX# zil$B@mY7vEvPmfw8I+|YKylSbAftvt)~lsrlM-YN(B$iH{$b+d#ATAzJ9*Qz-54*2 z*n~`TEYH88XDZA~R3@PK1Ny@TMfv}88>@fYpzlA^nWDmFl&5@BCJye$<+*Xp8H#jb zGJ%ZTFJo>l_DJW4KSzU4dLn@eQsc5&g({^_Rm#pk#K@TjV7S9jXy#9IL6+7qK zu5~3qkeoFe?l}Ymi7oj&HDB5|m@~RCGJl`8wBu^7k*|!sx}EI0yfKbt4FwF2U&sMV zM;S|XOBrQ#V=VXTgD*6z`hkxUYzc#120aD9N`6Kv=z@NipOvZM-BL ziykBr@0rLb0XMcz;mEot0c|{n$iC4Ybz7 zSykN6HwYAxu>aPt%BnpzsTw{A%R#p-Ug#Qk_Ai(Q&sbC#BYn5ZdY$vk(5}O$<@GhT z1NipmWf#74+}_`B?K!-6_dU@B2BxxTm;J(ksPHEYUEWZP~~4jCWbyN8921pWx#NO24(eW&7$Q1D+?)R(+zWwY9dX zCZi;QHs+1=x;M&a>$T2`N`0k)DI~4A@rJcAuX|2O{^t44EqyZ9UCn4=v6}tfi>C`} z_}Hz|s=p5GHtD-rpj7AYuw2nE3YL{OWtPzDKb1ON4cc=#e3VEV5%p>epV z{Q`)SL9gd$SD+JM40XpU@$U(?rAX$_R4Q9Uj<$687&=+vXT`^vre75n3WFB zo@O_+!Y=Pm#GeeHNSOlSFjbx9aln}1%z<_#oNfEv5fGzXD*%xDV__3-18UVak2QIB zuu!s-R!Z(g;d9#hek+j@%q^+}bITUNx-AdMVzh;ma+=fe8j}Ly!e$_dc z5xOlswyN#?6LVMlZ)PH!n1ee76!vTDi}H3tgrLg^g9PS)eIZ)W9L$oHpp+I2p^6~; zP=&%dJp&5+?UEwaCM!@&iowGJ3i};cgC|L&+KVH8)77z;`9s&e`4pHI<FH$~wBA{IuoYZ^r)wNFy?PFN$^gU9+^V2sKN zjJag!$Ea7CFtRb?ZX$?`!6?a{>@x=KDnG}S8RylrZ4mJDdBqwY3{=r=k*V0CLxdFe z>5K)Q73fy1r5mQGA7x0869F?Tj8o*@%n}In9R&diUp7~YRn-J-lP98cnrRHubw6UK zSfv~%e}>vq(VTt)PS%>&QNKpi7)!6Tj?upCshT7vui?BK#)52ft3y54d%!q%nL_XU ziE@^~9Z1@jLYFVlrmrr{(s$>LC*NFrek|00-S93XFNSq`g-5_|WWw_G4S*LRn-j?O zaU_W0mLE2AH;@ih=8?eZ2V^zVQ>^0g7l{&jjK()FIEiX+lVEBXyYz)95+H;hhobR= zs8|(Zq`30%cWJT1-kwiy_sU#an{HjGHtzX&Ylnd^%Jtno0MUFf9#)v%tMRE|%2bma zsojSYxoyi{fi88mj`Le-Mue77_L)AP-~Jm~lNi<&(G$(^(!1~T3&*kFE|ZcxBdCbX z*P^^vW=FK5o7&~fgBO6C5Er2gY0(!Ro$yOP$ezmHz?B8*Eax4 zxeRRE70nWvsA3XPLgAWK{c9N3zp{nF0Zuq%xsru{8V z4jQVAH?z^sB@{hHnZ78LV06uX$;cM zMx)r>*SqscXq?b})pShrjlIPLEcTOhMUQ9YZD3Rr*2O_`I*-B-DH`uJ^}wA$y* zeB98&9tSO!Qrb0G`ydQZR*{ro^KmnWo$%dC7jRuDsk-O}<>rOjyAGdPey0@CI}L4D z3Gb`k=)efTbkrcYt-WKxOE|(oNY)K!*{fQA7{*7WK`TW$4O^8c)~cz<>^J_};<{No zjy~Wz%p4_;9BaPP^dlLuUHc(xKbWzjo>RB#P?Jgb$0GRbXdE#JkhtwQvm1WIwjDqj z54TCTY8==OBpi)xeENE~b(J1Z+2ve8sb25$|6j%V%F=#ox+FK{&i-wv1DU&V+~nhy z$h}M5bp5|BZJFMk4Nh3k<+ZKVzmQYe``3@Pu1UnvwUozOcbd6y{q|$#f#YvLs0J2` zjuH>c2~_>BM>q#zyi?wzkJjI@w7c99h5siom%Guc=GeeiTX6v^f7mEDqp1*&5o@2&lZXmSlJDW_a8qh4_9R}; zRo@(7-uJZG=TMSBGC8CHBLg^DAV7kF2qEmMK~!d_xtK=l6BB5bJUnSrp3KUtg3+Hp zA!H0y-?HORs_(BXg|e5qNfr~rR)GE7CG3Vz8X}NE5qWk01?KZrVgwZL<1alnB;tPi z2D}D9mmkY3V4MyZ#bqS6@WdL}d7j_+gU&TR7o^qItdCp5+Wz*5-PA6&_v>V-ZBGoe zfkn5nFDa^~k2_-RmZh)lds@n}4l+q|{_4p(s6LYW5Q*|(F2aWJGq(r_wE_}}z_f&l z8cp~S07H>$`G0u?V3uzs+0uPENHFY>_ zc+H#bg}qzOSt%~`W2eNE95d@prlDftYA~$|l{uJJM7vHW1-A4}6m6`Rro)`So0@ZS zy0RY?>%|j-yU9h%dCv&h{LYiq6@ZQ(Ora~A`JLyHD}Y=@(C`jp$NhJhQisFu0_^&J z4%oXIZHur;W&L8lxdmj$oqNKf0gJX@pR7z-7t<3}neiJ$B)8vs4d4y=v1c8OQ?k6k zc`Kj|dpnwRLP>vBd!~b= zG$;5z9(tOgsgxBDTsR)w?*OlRGqr=+tc%eV5B~~|#Q<8RD+CqSIzMta} zg_PS8P?rn_D?X$GI)~WWHJ@b&7til6VTtEy6O)BV1OI+e6_<=H{D`L5PVNi8(S8w3GQ6O5V|5H`r%YL4b#lRjIf83VQ!WI1iLaGieb(i0P z%9fQ4HQ2=6d$We_sQ<=0%ZlT-u!H8<^>r-bi3$95E!_M1J03#huN*4St)<+9eR<8^ z#SaEb>l3i^42Ar@wrXDKevyeS=2xTu;p)}`gk(;TPW8eq4CRgU#B`JL+8a?0pI2~3kg&?VX7WamX2Z5=WX!o|S2ZMsHUQKbD!hG=&l zdV$DE4_`dMlQ_*TL^Z9z=mRpqEj*oKI#+q59jjd+ULFyk-D z8Ym~p2C{*h%laOdS>pE9{~XjRz?fHCPtOCt$U3CA0%&CvjP~oVU=V)%AOZ{c4QTx& zxTBkQIOAHfe$4pUc99I-R~xF*zN@pU-DvKe0goc2;47)lH$(2cyaoK=@+Q71RRa<2Vc zU-s=|ZET({nk3nr-;leTU<%1PDb!Nsj@sYB_3V!1zWl)*BZf0c;F;3&R_f`I^mbj( z%bg|DnDr$iF_BdVwqD`oZR8vv%P_n;XvMYYeF9NKsRcOyqXn%3^}VF(oE6I(8l1#gHeuEL6WmGWIclbiGAnIPgm!-O16Vc1*2bPQ zQ}Wy1eiQn&!y1Zv>pT%{ve(`|Lu!ZCrcH0#D@jFoT2F;iMjAm0buV4oDIN7KbQ>AJ zusj97Fj8WUfFJ|~baD=Xo5b|2eWElRgL#WgJy%@S_j5C2wC>~fl}Mw26U^1mXEn!G zxK7pPtGv>(_%u=Mpg33oaIpLcL2SD0pl4XXV2~r&7gq_(`+Kk#q(b#%9v-=7%`7Hu zrEvw4>7BI|@a}~kqqCs``r6G7N>M($K&4*9s zobV0maepUmP4;L-^~Z+p*B9v87a095{I(Cc_HXW>miL4|d9+U?yV5+8Y?J4SvAUG= zIr%Mxoyeyt)+&KfoA#=}R?FK_ZR|lh9`sL@Z<}+DtX;V43}an9yhTlZN*(p<=5^jJ zd^|s!@p5ToXO%kCr=RbxEgSfrdAt{iMOR#|lq_>=cifc@*z6^~*PpN^FLL^>N}S5v z|4h>5rG~w|x}@{jX?Fv*qlR(q5p6cc!1-vgmPH2!Ci!#n%neyh(zNxMV0 z`5AMRj~L)=fvb6Z0c&M!P;gWo4?&%I-ScKajz+BbYz+EoWN z)a6;wS5pXO`08Ru)t_YU9vP`qT9J?w6&ae#{Y4P--P3{67#GmMI+Z7x%5w6yCWo@Z z9j~0FMHB*Uf*{^RiooSfqsnx8tN5J;%ku?17>p)%e{5VD{Xi=>N6Cr!}dx-n4xZTib=xF3ge9SzF z3o8!3V_sBB^F(8_ojdwq$U@yIEk0?H|BTFF)fK-W>_{(6QjO&!{(x7e1aeizC!Yi`~sJ`$ONLnH%o*?h^I zm}8BBaVKtyEY#i1BX+EZT2S#RcZEavjU4hh>%<3~I|C?4@w&kB z{Q&#}gujq&Vi&WGpsfKt^rRzk1&@$*5$MMER?ke%gmOLkfuG`%P(P{GHX>E_gpYL% z{eF6wdSr&0Oi&VW1wR-j3zsY;(j$i-NV(^xLA|?!0T$iBsIvN;B#i`{4BgPD&yZzQ zU&Q@C_lii$nCUSU9F1_VjG`>Jx^KS#VF}jc6C2(B z0QP(Nc+gA21pO9_Ib*=7_?#lZ&awZY?L}Y=aVkp#3Hi;lZ$HaeR0Z|qgR_w>M}6Wb ziQMt4!?Pz(6s#Y;H}Ws`@v~wg*3XkFsb^#^NulncSzGJyC$~)qF-|gU>`D4M`t3}k z2_l*q5VZz{JWb-p(te*5wd9tfuuE`;(S1!lw>Mc1OUWQaJ8SeUxh0jf3x;kAqEv30so@tK2 zH%TXLCw#7i7jG~Sl|J^-t}uOB_4EM!dW+tCqk^<7u}4>C6fq4NyMGBN;ZDR{sq(bF zC#7O@e01dV@l~Z&(f$Zm{V=>MyIPCbdNqdjdZ35ZlP1QgzfWmRMN*Qhu}?tcJyhe9 zCN0x$UNVkti^Q=_$M7%y(l?#ERF-nr6cd>x1b!Mx@bYwCLE1-yTc1;)zF)*&DmE&k z_kt5co@HZ&p|w|*mc`(@w2AWxc%X{ZuUS(}CJ7(H3?=(YtX&XPJyQ`@AGEv?ifBPX z6+l}M2whE5CB$~_Zk~9|&a&^X30;j%SjraqFt?J2ItP#Z*!6s=Vjh@+F$Aj$hkBld z*c*RSmh4K75*NUR2}-z$8<`lur_+dM883RZLa`Q*ZBG2K^YcYD8J4%5AIwLj8w025 za1bVKrTK+(v#!dLuFv@4Z35T)U43o*?rlGDX##4pBMTNQVCc|DV6r3TK2WHL zIpzyIjxyLleDm2+`JD@0i90dUBfMW(^!F*})jVBQyesltW+-MY#uHSnOdDmrruisW zN}s#jXdkcYm3Q-K<4O;GUW>dewd&3&&1%j$Sq0ws;BewdQ`t0}tOmAX8}}q<2LcEG zK#_XtxLaWa680y?i+S2Xe*?hNGA1!v*e|s(sa5=Dj#@eSW9r5PFosxailcNXkGf7+ z$wX?;c$2yN7!4?FkWO4IIt?=3MR`%` z$S@}R0G_R0;acKXkzs_f<8sJCikBvN3hbSDJwD+xYNcKwYlTWp(&-@h86@a=3W2cUZQJ!o?v5KcrJ% zYmKX`7d^9q>X6-}@`a73zKcuUl$D=4ce|UiKKG|<$*Mn-IdHIi1chs#re-tS&w$7C ze-`#Efaz{<4L4qYGiUMzEsbWCZN>c+8vlly>3i{!U19SGK7Dv7ckyhK;a%{q-2PtM z&E%y|B6x!fssicx1dm`ElAB0DC$_wXTcH~Z6K0qmKbn(2JP3Js8y*%Seb^w z!CQEBppNlMvf9E&y6r0hep-^_>{AC|E6Of4E7P3~QwL1OlmX`-joD&m0M{8qt?stk$OK#R}+i{m)Zm!Y;3QY1(H{p8A^NF zlT@%fVBOB4D|?`jkRn!m3>rZD#TwVy{_RMEw^W-34PankghjVT7}gD3C*QTPvs?jq znOrmMyUAQIm!gZIfcr1~gYyI1lE(fe;ujdPSd^jVo@cgBu-!?z8{kE-IVvKSWp~hL zvrA&3@j>d?-6`&y>dk@bZ%VkAU%Eq_L;9&U!)>ZZ#hjF-iw#>^w9n<<>jSr$!N1-x zV*?)d>S~$R7j!ZV_cSn1uCsxfi4uP-go)+kq?pBBI!FG>d0qLgJ-!@iRzkT`5l=Q$ z-q{_xOgqyq?fx^&M07hfp*Bopba_hK2foG)YWu)5W0_YJ2>sB)wd{o+42t%+gfNJV z6aWA%S+{h~(Z6QvPc5;+p0tUH_yN2$?d;#6bpE^{?@+owaz4$EHzJ@3J7@{o-Q8`w zr@l6V2clrFo}Mp;k$#`0u#?T?yGn|2%mjFN@rL@MitNV7_gknG#Ki7G(r&{1di`#4 zS|Y|H9krs#=(okmqKK|as)1+4GwTZBCX#)kiu-R@@JEKN8Jpt$a?q{@!#5iZiYG9u zhDm}zCrfAaqtTtsR{?7P6oxe_#mv`z+04Yp=)=9X7Qzb9QA|QtyM<8_VM5}S#nrgT zQ-G{fAQdxjM}Sg+C))DhB+`#*sGW33@wV6}v&u!h06r@?0jnPnj3H{X>uBnO!< z!QfV+#&4A~uQfyp^7u|%T!u>3<&UJY7{68*zEhYVDv0u`x=0|IPGJoVhX=%1e7=t- zY0kP4J~b!Vx@%Kj?^5#W4M4hCrQ+MIUzh zCh)dkd%hq)D#A(~2zAdd8P0b@UeTWiiiSfO6h4HL9Y5mpHk&w6RQccgpXA>W2fH$U)*MnU#t%&ExJOakjUo8)1 zym8`*E^p@e=^qB(XbA_Kpzq=K3LT z*U>0TBR*5;^<(N|Yx#5MWKMTh0jF>Ij^S-R$2z#}G&7xVp}ZCywnYd(ubF6%Q|WzZjnqC&i)l$@l5hqpt9 zBxcpBrcuH!DuSX>w%X+#u~_A z3JR(`JPe(skqr(wO6Pf7WtyzoK{V_r51irsp{#$+?lnjhP&lFT$jInh(?oQG;CiW}2O!NKPD5~s)xoG=a1 ztA1f>-Rm?iBs^`>KB`6*#FI>+wDr5L@(+^rBw*)Y-``<+nDYY?i*7mPe4Ni>qq&I< z8x2b5k_l%(TWjKA0};NUX+hFJn)xvvbMAh%k$|{KF&gRdCX)Cn#~|1%c~f`${QQ-s9x-b#GQt48 zQp4sfgLF0>Qa0g0K*Rn{A8ED2b#<*_4jOgFrC0#c(RrB_Y!qQnwSygWdt^~VVcEs( z#q8K*qSFste1c#OpJG7cD~#M)DWXU|&Wl6o_NLW2ZBi4dqib_=J#xq9a;oVjKCWTs zhcl`hs$CJ1j8RvG0S>vMRp*7abEP+VN6l^2$qluMZ%_zozO|(IUjF)YRthzJFAYu; zJ!3K)l7n<~Jo*{TXoO@v#~riCAqo~+=!B+1-6A&5e4rHb##hguuofPl3yar#e6Ep9 zW~~9)0T-2tXMxiwWND+JCV^W`;+L+siyrNx*F(xZ{c%qs)@ArkzgDu&C9YYYBEF=&* zRVkJ~lr_)j-rjca<|pfat7Kxd=9bj(StTBbSBHfi)W%uxh#tqBJVy)v;$A6K-gmuJ zK8C{FsPof5i?6Jj!$^!=6$4A{A?f@mA=8C;8TlDWlzcI>&!Q8|$^}Co#?tt=gz<4c zDE4U(@MvlWF*pI0>6CV%jT1Z-Pe%a9DfM1q&n63kHLIPLda8AY z5MuNC(*>Hi7EqRs@}8a;Q4qd%bunF3Y$f8f7NM2Nei?8cR!gX1UQO-iF9L}n=8DF- z+)i1=iI;jK-iS~+`#r;2WWIfjWaZ|st4p=a*?J^n~n3jCZqMJ zS5KcJxnu@zr%#CG^Q?nZE`bGq6?G14^TVh`%gJL$Q_T=e{`@EGr3_~s%mRKCwZq$+ z%S@+@j1{3N-^x6lwIe4uk&V)bv#O*sje7RJmBC_z7*ecIQNI$j1;}|K?Q70T_EVP} zqQ>uLqu=)3R%+Xv59b#aUy4b5Euh!{DTZ1;vBQRm--i+6o(smrcj6 zz}~6OSJCHOg?D#sSnkF_W>$s!)Vv@%moQOUTXUd=Z!U^vX#nNSllJwmW)oRnxO9%8 zk$}3joihu@jt(%t6eYeT4f*h5@Mj8hVjbG6OhOV(>XY3{@8?$?dmH^IQg0|4i52X7 zi<`BTkJNqI$9si5xTJIh7dc}e>n3KM!}9sU{yL1)6tZ~mX6E=#nx@85fRw)O1j*o@SW#@J{sU`kw*qbwJLqglRy z|0fUa9Mr5o!Z>EkSJECiE;f&aast%k*YJp|u0xG-L*k13bRut+9G4+4p<(lJ;H>8o zoA`3L7|I8D<81|ZuUYf ziROH)RSVgO0M-*HZSu{^NE6Q`#wBE2BJG2kdGf1uD_$FZ#BCjS)*xJ~KA!3hn-glA za?EOP7+&}INz@&2L;dqSMr8@t^%XNSjn6T5ai^PV8O5UtW$SZsM^j7LW!{d1?r%Q{ z7;tF}0{qa@jTZ0Qq4k57JyRW+2fgF4+2@$%MFmMw?WD3>l4W>@b~vG$x*FaS#e6gg zKrhWUYYzmxo5@UF7AxeW#9mWC--Uznjj@6B5It2JMz~erIc2Hj3K}gkw8jX5kuG_2 z%%D1c&qI9ixwvqbds_{XWRT1~(>B>Gl|pBsl~e|8Ye!f{8bW5|QhwivL-obe8tL=H z%WKb;>W!tzhx;UjnUu2U0yq_?+)^Y76MBy2-2&pN1TMRKEeGVp@~Wk)eJH@$mO*&( zX)UhYdNGrNxzUZSfW6$(So7DWln99&K4JfvJ$?)Q%=!-GrH(7q$Dr{y*! z?_#H?^o+xDS;`O%c6+3#J(uq{=B#8gL^Z9=qy}z-=oYr1Szq10BkwpW`VVQ}wBu|^ z0k9b0j^c-geZVV*_F?e}7w|{bRW^7`K=BABo}tYQQ>{EbTTl$>Ix@|_ z^ld3CmM$l>H^p0I!3m#(Do{7h6%<8 zhhF2I5FsyRQw~x<&bx0~hy|mgyiM?eiJh9c#D1Ec#`qhRSbJ59Mr~1(3RTQ^2Vh2w))Xg0xb^z=1Y>y&4L-lZY zIsF46GoPywd@lU!*oE%lG^cz17dX@`iW@hfyV14)0#DEEg!%09Fw=vVr3Uj9#qtv3D;pw z2vGwc-g9w%IwimcZ9bm{4){jDQa$D+&(;q+b7O+sm zLaWS=PoGinq0$>ifzXzr_Nk$B1no3nHT&2IY-x1~;JQ&;mL6gQK2JQ}%x?eT5^ua2 zCCNI&`W9j}x8dPDEqLMDp0xWlZ@tsgxDlV}>HQ3$yOcP5~aOSaWp|rNjL7r@e8GzC2;f?mPU{uVG39iyAMI8m}Hn~t%dBzkI z0rujqovFcf?F?l+a~4EM-=LV)Iv6K$P=V*9I;3VEpE-^sLQaDS_~y_xSz1{*%G*64NA0*pxC0Sl~H260IqFj?T5A7V|p|Q2jCsdlqM-v*QiXtVruzL zbrS@MUhyNC&FhdB)YSVYq!KM(8yt&f;_n0s4n-Hia$Cwa&xSSo)~575eH)5&&eN)^ z?bU#bM;B~xxBF4fp54>Vfyn38`_|W?OQ6U4Clv=M&zPBtYIMAYYfESM!k;_I7SB=a zeh;G&V#6bhP;-w;9NR62b-d?`Vdd9})iB%bkS<3AY$fe1Y!`XPuVTOKa0{Bkn-b@X zI=*K%5<4E^P>bj8A6*o^)|X>rm!Qj7Nb=Ss0Zp=HiFJbj4CImwUYoQZ2FpL-#bv*} z!tS%~dLAXd<8*x?O=P15*1GhqVsx!F{dWJ8-fQ6fZM)9L4AJVnrq02y2{678v4(#Y z#};Nr@yudICS@Iig;)WztAo`psCqapT_iZI9PijeTsWs;fi~LRAR>{vV_jWyK@Ev6 zlEZh6RuJRe$SAeJqzwWe_!3EACX=wp7~H7Go+P`YQk&MVfq>=--1tNiK5Zj;h5$X68Y_^<0LxC2Fz9@Zf)*6}f}dmxkEOnW zfU{PlNBL+mL}(Hh-m|lox*SyzPC+n^W7gM0BT3Fwa#HzBAxhlAxhKVuGip37pRZY4 zq?|DANAewpdN{=a8hj1H5r;Lee5E!2P&+@kSwWK|}2xh}JPXPYEhahixxihsyM5&?<8ylm|H$ zL{CnN*0X3X`b$}&9;kDJN0+|v(oPR}xyNEq9`XYuny1qTlrty}T^fcH!804eg=&iM z7r2rjCxvb3$JgRi86Re2gze@#`UE6m9ygyV<~|6HLT;e_IKpkul+dl(u{ag*tE8`rnrF5i`z+0qE5XQZ-YTH&i0H zytLXph5IIu$RvuQJK<8|#>#>O~KA}3Ec=8~*l_-w^ znwXGSZUpmq7!DVGqZVn5)g&Zt3T^N1Y#%-4FaQYK`9^TwS-%If9LefcOgt+jp};1NP138&zmsmd_}3(`_8y7+z#&(VhMF;9}u*S|9T@(gEn zoXyxKlxLLYX3~KsX-F+hkY>s!GjwjIFAgS1j2EcT_A&H8 z%Pv*O_mlU%zuVw@S8c zBUvWJ_zEgFogtsD{HiMmIik^;F!;^9P;gp}sHM@6s6JMp;Q%f{Q#Kk>j};ohY^`2Q z{k15mUU$0~K^3Vl4n2q{e66J5fDTh`LVlRDVmFa%RCxm}5h+AifJdP*82=1ui~C-G z{dE)ruTOvd1(bdF!~VN~*E;hwm3PVd`SXDx%thhFEo9qRF)xk6vA0 zKtiAkSqPljg6bg-E5gwuDJj}PYz~DU%Hi-$XN1oP1$4^AjT_Qo-J5;AgC$eVQz0ui zcEoH;9tNUmlyjIEzT9?#F9rl)mvPEx+(ZaYYLTgj0vQ7DezBtpK7TYOoht|uSnK?W<4Fu$0zJzyYK@7uuU<4fdmx%W633K@I0WolykT(>kr!+LJF%rbxJO8-J^b1Xk}-XNX$cCYX}c!}1~Zpj_+ zB&G$QT&%)Mc=5H?&|Lm=Ery~4;*ufwO*@C0NHvZC6?M|Qj7K9rR%P6QzzoTT5O+9l z8)0a(G_$Hy@5?pRSy(GJ%a}$$Atie|xPFLl;jEn6(_zFLvfuB?>_kBmnLW`yqI7Tw z`)|mAdj=Pm6j+5)u~++5-&;MtvGUb-Jhhd|W9;AibkUI>(R9A)v*ydjCgL1{^T*bn z=S+P$1Y)}n8bQPMfq^`Urnf1h-fBe{CHg8hx+IDc(ztq{?1mUMt9}M<$8yv-Q8>b%Yj zS|pI2vPNpeTQym9$&dW3gMwfOwY(KtDRpmQbAzjGd)w2BoAi*v)y(~y^$6WAUSp6Q zv6lGf zu^8UmQB_vHc~~+lKbs4SQi^ij`}7K!mq*|)I1PSIVp_=Q74y=k3_$#RGM!RA-VbHZ zh@0=+$kwgq{Fvp`LzF*78X43kxQQ4F335|2rDl}Nn{w-3&kVvW@6;^J@wY;Zdf4qz zYUmzov_&>Uv6|DQoyF)gr`;uZC?Sro@OUe><42<&;(9~vvtxs#rYr=z3{P66v=A4< zgF+n3T%fslO)c#5K{o|Y{ab;ZqJD@s1Zh_S`L?iD z1lc?~!Y18dZB?L6Ta;RaU4`5sE#bvJ3q~n~ncvdt$TVF>$V;|`TxEL`IX~4V)G8)z z6G2keIu*PB!>C~af)xLAvS~q!!IGtH%N3RM6^xrl&aMp zj8U<~jD?*C0~Di;7NK1$=i+i_VI1DZWjNL<`n}xj@MTJoBm)@+$5%ccQL=J-Gwg$l zm^`$ls5W6(nWN172NCL>-Wc%&yMgG`OgWBsn}Rs}zL}Nb1}+h-r)P`=IkCquE`xQN zl^OM_14V3M#)$=CNrt^Dhn}Xg9Cdb^eLOPoc(QROH?W#jA_bP9^NVg?<&n{RzJk>OfiE+UG9S24n7NKf^LZU_83i;~hIB z4rQ1psna!CS*RDznN3r0KxbE-#gkfW){Ux6ZLgd63XPS?KijGhvcQ1{fjeBJc}1$tlSk(_Yq-HbqYc>|1^#)?Fa2=G(4h z2}N)KsZ?KFNxWL0bf6Uh(OD*U`zAB`F9r)R{8x^Ak`){oEjPKXP?;B6Ky4a*43)OkW9e z>rxq;ED?(R;49=&qlXZ(GpyM5nHH1NZ6XiiYT$#W=~?m3Xuv>`euPs$EpY?;1W$qs zkADBN<3`1BfsRrrJvkAZVs$zW(kL=l`{K>26?DE!K?587nd&J+Bx?y7Q}-fj&+pLE zbSeupxo}R&_J(<;t&^(hL5PWhVqyuF_x2DpWDij)0%m^#xskY0^`ft!U(wFCoF8!- zmmsd~VQt2yMN@eu7gQI#aXRuuzfnaQds4k3bA=XWj~|>{G{%)hJ+8?P5cge<0c)610;M5H`rH5-ZAGjRmwI4Z^{^LrKNf&xJrOOJ!Q{c+hcK@KzlH{t$k z`9G^I$2(jLHNVNR-gXO}<}C#q?8*hr1W(tuOswrF;Hf6NqSgZ=z_QgkwgybqSVe3Z zahPm}q~H^1Vr^{BB|j%fZ)__!t}yYJ4HlKW3I`MU_xP{n0I7tX4b}mFvpeO=pLjIB zNa{T~$Y*{cEXk!}<)_MhCaMS%Fl4zMPaK2(oo9y)_g$8uFbmAQUAmKQL(*&=E4gv2 zBCE5=A|6;ghPuN6S#{mpar8`)S=O!jfXGJ0viL`)Q#IbwR zYY;)h{!(*q1^$RrZ79*nw*0EUP8mCZ-{nIyzA z793ztFLd_2!~zM9S%u@foGLE`ulRI`iiLX4d#wV9YVpNk!Djx3#P_3E3bG1EsbC#h zf{^XX$EG`q!%5P;?uuiK@xw%d#ug=`_mnia^2bG_7Vq&>ps_NU`#oqH1ev5 z^6XvDNt*q#!$Q|BZzB8BTK5B3H!lf_=^bjFL^6v=%o9yA=!?v&({`_N-@U9jnuQJS zht^UW4rZod*(*$+H_iE)UExERk#X}fBBurJW%7wG#L}AMNpD0*fYw@WCZ&&>v41T$ zZKr!@gHQ+FW6grN_Vo*s8*_iLhcti(&`Un2ex(nsXx~IbLoBvq7il&=?V-|2A7Y>G zZ8Ce*PC6VcBe}eOzR|M<(}=#6#__I%W0>h)rEMG$^&ZmjJ1)Mz^1?QJkGX=1jEl}F z;7kDFGW^*~G5xVsd;aJS*oAW%nwnoO&t-pCrS$BVo4<-ZIWqZa z7A7FR{m2jmxVc+Z25**1b^u|xyw*`>eNk4NT!!qi|MIxp}meyie+E<3!NTv)3xW}H6ZDEz&{tp ztdT+1>9M-d4nprO!iZGH->vUqfsC(RB)ZC)=mRgy*FeM$p|Dr3<41An{NDUX?=W54 zrBqo$4XCA)$uNw$44K`A!@AojHDM053gMVmM_AX?OaP$6=a;(QFC2h`Z3C+fKOe%@ zU)p1z~^p&%tL%kF04$0IyJ3Xq4LU-59;S0eQ$78oho*J>JlK z*If)2&Kor3j5b{do|ngMd_JK1PH&YaC#!zgbL>pfvHIjFWiKXKOd)o%%rFb7%D+4g zQlU_3fDY(d(ccNkhGo9jGjVaYx3mP7o;H~s4~5H#*U8}^1NTxU5*c@lxc7o6C*oXC z4eL#Mz-qnU)ESa(E3(kXH{`_R6@2aG`No7%{}m^G9Njdft2Wp!TjkvnZ5ov|YF|3t zvTwcdYsf5;lQPFR0VsXn=3C_bRbsy#D_wLEUxwTX9#p*xxMX-_**yi6a(SeS_|B@s z)F4Y?M40zwE@?PKCN5*VxB*eEfRoVgN@Jt>sd))B$Qz1Awd2ZNiiepiQPwUJ8HuXE zwI6Q?V-ou5NwxHAU9qZz|@4Z{0$X41}PB-DZm8Tb2IFy z9^r8xL@Nj4tv%Mnt?AW`LpmdzYCwQPbR4~I<0t+{w+Q`^w$_nHyxs=_F^yQE!j{@* z6>!E--%IrU4h{8zen#QB%KJ9CyuFj-h*e2OEs*12NV3@i&7*M%Nh^gfBPsHHWU%Nt zUpN-{3HNib+*xL+0D8|#Zk~;iQsE#_X&Hktq|SnM9$_1$e5}4dw|IMeA7!7yZ|Wg| zP?MCZH&^K6C97IjIDPk0lk+Uv^fj7xJ$&GN+^;&8Bxb2-MXR@1q=aQ^ZHa6&J8XNm!6N%{+ingsP`zqrGK< z6??T^1;Q&R4*aSA(OC1)?*EN`UjftG>cw8?;YQ}BZsq(wWcS#sb#w9tA=;%~x`fg= zF}NtHDXJs&jRZjNTi_Kx4Fa*T*(7=79-izYYSxN8_i@z#~u7XV-xvR+neqprc;1=jQ!N z2o6ckPRvZ*nec_BzRuC%<{AX_3s^{CaFD2wi11MV;J{MfT|usAm$r&C*Mr8ScVxWJ znPbj*|UDef$_%u?)Zr<2;Ki@ zL(X$9Z*-p;u=!gRK0lXR9zhih6zWejtpN@P*RJ?+}T{6U)XjD4#Hy&lOI^ z(37zdF;Q_5Fi>!iu+Z?}(|=Oo7aRrjgCu-hlBMPckl+wB4}!Exyi|AGFOzty?j65+ zdi)w9FSBE#SWvjk-^TQ+a5JG{D4`AYp=l_g{q-YdDE1QzWK{!_!UO%pL=&d@)4aGU z^2(?6TKN_E#dv$ex|cPg9iomvk^;Jy%>sAq2HVJX^FBs$|N38u@39?=v|g z;}Nl~ZfWTd-OrVjPu$;Ji_fkvZ?EsK?#h)c??mbs&Ye8pdhD38q)cxH92z%4^^rnO z8LckJn%m!iOlZ_>nH+DXu1}4rd<0=R6;F*EpL!3Egv%mqHAcH2`B*)BP$cg&+V1G8 zbsNp(g%j^N+~wcSWF`SYXYS~p9dNmUZ&1%}=$n>X-TwP1kF54`Hxe*|n1BwA@3!O! zNPQ3r<#U)3B=rLp^_&@>rvpL%ug*>Ux_$)C6{CtB-GeNYsGK>u4eq#L?OMT>NnYE% zdjj&y(L4W=N#Mm6H0b2>6O$oGBA+pZiX~)h7b=jTb`O-(ToI~J;;k@!^|Prh_QSG1 zbC=nqidgGcR*O=pD!DR1qsU)k<~>{=T)41;R}Q?)*5a)4Y5y4c3z7{1c3VE%b{WU3+2+QVP)|V#gZ#w zWcC=Ph3H;w!f;6kvxpo2s zY`tGW!ILD|{}L~ZJR1c32a^1OMSq~lA9(O@DBTYFgDy7$N|wUfsu}nX{PG6^{efVA zAjrSr@7?zt+ugs(a#JujY{<E!`790000M-d|&9!R(;R(#hu~0KnF*`dJX{PeJa# z2kpzhib(!}lz*V5-&e)KAksvZrZs?2irnAu-k`E^QN!}D;55T=lKt>AXg$a5f%>;( zR;+*e#`>pku9ch7wg5nPPrL-?n)Vp@-y;1LY@huVigsZA6@7k`{>s`!`S$n4Ujdr~ zy69g<@fTNcqb-*OO&g77p7wxleib*Me@fYofdbePVgI@M++*|KOh=wo1p)t){GZ59 zPwQ{e{udV$2!Hd&RoYOy(WvvEDxU!MuNn7mww6vl+x7dI_!v}?r5a|FV&j_@ScG|| zPNu}W^(3XH-28u}$JON_Zd@XDvXV5LznnqGH^nG7=b!2RO+GFtpzJuoa?k%;V+$1U_avHC@mItDc-`Ony|RJ+SB}!^vJLPb z2>A!X#{A1_n>7Dpz-KuBc)-H{VxVXvf#obI92cAy9!yW%v^_fE9w;ddAf8% zd#`(kIAs4H^8TMZ{{I-rBF|9%DCPbSHPnBosr-{#`6t!-Ppb82s#%la=kKIXeSi7{ z{GTjs%lj#qe=G+8cni6!NIgXOH#H68Qya}j&p1oFUC?--gk-^pTyc5mE;2xH0q{tD zq3#-ka|*T)K|s&6tT=kjp4~;~H;NCU1W7v$rwze+X9Ag(Py-9@vS$PnU3I5clHMd& zdZ1l|cM6^DcIGnAAGdr*!e@&<3ksR1n)h!|V2Qdjb?@Y0#*mJ*>$Hsr(@7>+n`fIyVlVoNpnaOl@Kl60Q zU0#d{01yBG0MJSS0O8*m^j8M}(DM9$>i*sS|Ak*nOhpz4E6fQyq=*40B1Zwt0HBZx z5dtbA*C6c49eSPy0FVuc1bChTga9<&7(8$s0R~)~DX10w$G>Thm!JnKG=o!pFpC*A zx#TTL4wI~^SODC{X*NAaG==!|nm53xBrU$ScG$N!#mLya-dq9KdLAz!yJBvO2)Tc5 zY3Aqm|CVe`v_vlVv!7<~=WHl1Rqas?vDqfaVv3OfLJkr_#p>f8ct%vx*BT(!YAmui zt`*ZMqRttwZ$9Vi*p*C}nOsL{VJt>m`LJaM?km_6p4o0_s6oQQmg6ZD$l8TbZ4*lX z`thskIhVOzQ~X)v=ebndvaOxW+Klnf?HTs(1!SoogW872LVbN;Z=Hmf3=Jfbpddk! zDK(YXSeu_N*X7m9((ENxq0MZ4VpUM(F4bd|L@r$%jr418kM@Aqq<$pOjHB@KC?PjUXtbWdY+KDVSxx1sJ@Jaq6s3=q!W8p<2s8XU416YQB>RsR`E(M} zPoE)wp;Q^DWn7u=oe$XV<$(}&suG^f^BiO3d@PiU+6}s(aN*E?1wnjYJ5}YIG*<*ERY5c|rPbq~E=S1#sSU+C@83Y)WMe6I7t{PvU(@oI*B=okj2uX9 z=zNxHMTf03Z$ThT0w4>%>UFlhb&0p-Uru`HFL(m%xBsGMXkvwQ6DnZz#rljYkpO((@H8myG1A^z1HoO__ z3*pfJh&r+thZMh~RNwRXpl(gMFH%hyj6`6tjt$vYobkx#SWxF9peL>*Fo-PkHy`^ocv9q9`pDFkWIXdh&Q*SnaK`UA@SHTyW5MnlmbhzRCe_pObkA11E5{#x0g>w#@8JH+NaZC4oY<` zQHurNxy^KfUkMH_X8afi0x7AdhqW1G)e_=6oHF_fldK(UF{sArrp*3qliiP6Lpp|G zEK4{}7=i$V``A2b5RlCu@cZ!VKer366r(M7p2&jOeSU~w?rj^R*!k#EPs!IfVy~q{ z${XMAjqM}JE5mc5kSr*8)U}bYB@8JAyR(E#%{Rlnu42 zvbvgzn^a_4oE{34g595W*F`87HChh}&BKpcwCMt{f?d$*x)pJWNQFzaD$lzn05Vzt zZbXQN$T%hi+vn?$`X!N4Q`ONaB`=hhekqTu5pEt@ft^cqqvbS32TcSc{qrHHB; z7@LUcy);y)ObAb5G=WZ$jwbSD05y=R!=bN`7RDecjTd0a-DrI9FSB>+k`*cFOj$`%iSG9?H8H90*WcIS;pR8vak!bp^BSQOc2rcQ zB`f96gZ|&UoxglqoXtr~W3Pu8BoMU{hegH2l&Y^ECWZn?FZm>&ZF8!!p0jfSzw@`> zDJulq+#BeIdtxf2ok()@z7;?kLW#c3@6xM^c^)HGK8q2rB$*6Zt&?Z4y>HB)U5BGdhEXfYsM35L(v!~LB1PGZsu5gf2{5{Rd@1X@S=QY*WQr!5!VZyY0JtCjrP}_-U6N#R zScG$^>WQ&A_r`FvhPrE`ivai$tSMmYmjq7W9sNe6!Jyh;>q^RsLb_~QUm93;7HGR~ z_;6;;7SOp^27sU6&ez7?zrU}&&P$b8DN%$Lp%g)b1_8ps!OcGV(R=ac=5A`c(h*~O z79l2;Nu$)12t=?#D72Y1e(AqwcN-^<;g)hqVYYHfC8j>%XM6o;u-6di?EAnp27uHW zHd@~bRP=mbAa+WbCQNP6JQFG-73Sq zt4Nhn<&c=j$C&^dt|mG}VaHL6fYp$n#eFRSn&3j??|a4%An7alnj|7tfDFC+nhfV0m?fk8Lw1*~>{ z8)~b9zR(O*S(h#`$GlYuUVihvXN4G$vlx$5EQ;Nm+{-s^IDo<=f9sX6gwYd@5QqUv z8rV#51{s8>tZ$no{|_`T_Hk2o=h#rIL4R#WZycCXPDdj6d?s zKSFd^0`==eGFbTmA~G=^J!V>Fx;a|_(AkORkeYUy%O*J1LZebkcKNBg%Bs4?Ut|Vm zjv?#^=r}MO(*+bdc5m%4?>}QG0C~!>bU~0X5gyOo6`%?%M;iW0?L?#ZEk# z$7o72-kk;miJd0q)>O?{dy;_4QV;`JFq(*SCiW6UI7Uj3;EmW=@zOIOqKn3~^MNK^o zya(GleEky*=M8v@q^9X68g978HiCE)YdQgp{pj)Y`&aqqhCjZEo>dcXNrT_$EHEq* zyCKOKv_hdpI$M@x*g-c*fb|eOaTxiy{OtMox%9peSMA%JCG`RRW~ENPSH%d^6d7mz z&Hp8Oja^N(F--v}OdRrY4Z%#1iv3g(wF!r6tDaxC+PX*!k;wKl`$$GDWE} z1y-RIS_0+GkNeL(W!73{3KUY+VW~DpK%qzj(F^x7W9hvc4XVkXKQ7#~bb~>6W5BPn z-zCj2a=Yih_s@0KGy!2?Nvl?4)|z_hpG&Oy_0LleLsFzAz(^564h&ES_rJ`m?YX(1 zyNGV)_wWI_q7#5mh5IN`V@}W0u4WfyAmYsa64yMJ85$8xX(>;V;VA;-1Bgx`&6|7g z9Ti5VZ&SU?EoBL4h69r`wDGqC@7k}$84%K=LAah_fw1`;Lo;y%I}1Woe0YTrQ+H=5 zLg_5_Y}A(qQ*q($=y%{NXisUR8YH%rCOKwjE=A-M;QGv0l)VvST^(?uMoIBn86ps` zee-TOpOarxG2!q7{-xczA|w$$+e<+pkc1)aCr(X$=r6WR-aF5(^@^&h#6(1gky`z= zeZQB;i;wkLdnbv}L=-_HA|gnLh>#*8NhWR0m$|B{q}}94%AkrQvPvY9NFZYv#4!j% z7{noWBY0=d>bYT}>gP?r9>S2N83aL)LlDkBV%FgR0(*XpFGF%&Riv0BB>fa*oFfFo z#y7_YZ!t}b3U5J-){XfOozl{a-eHkR5fX?`Qq=nG>t+*O$i`LRc|xe3K60#@V<`Du z&UV_?t>S_Q;1UXL#vLx2l3SfV{hs$3!VTOUZGvr_AEU(#5s1Nxo{R(3iNEyhBX|DD z7<1q0!=AVB40LAw8a@9EIJ%>AaCkll2myuIAyPsLDW@kzMN$^l3af-Nvet)*0R%BK z6MJ|lsix-eSll)4{`oP7@m4Ii-p~tMTt9>XAQVs$Pz2Tp0EHL=vcL=h+#!wHHmqb> zW7jTV7b*o`^3=Rg1W;841gg3MDr-emT9uuEt1L?EE6!Wuuvl*7?=;?tW!9 z?1PW%RpH`ld6>EVw}*$f6<}bjb#?K56=YyTTszOhujEgsV8G1N;=(n1gg!4 zwT?syiL=m2DR$Gk3dt;?9cO8leKBPDXIy|0IW&TrmKp#X(QeObH$5U>4qsW;c_V_e zN<-uM9(@M~3{JveFa{SrGO@WM}G_L9V@#lMpXJXMt&rPt9J(<9%Ag)1;cinRBhl1$6DnT)Ni$k~$aA`dl2~ z!&xrawLKT`#GV^!1HMbMfh!IJLdU&jlzVpQENI~on`t`Ju-<*3I_!xQ(ZEtd?J(TC5z>9;dlTc1W+)sq6JQ# z0Ex1N3t0FxdISkmr&94Uwyat8&cQ*ngrd<%R62!bl}l#RiI9L0rBaPbCsb~a(CpU)5@j@gGI8;v;Z5XGDlO}!M=ofcjGm}R$i zejNG7cc)&%hBQF3V8HyvJj~P@l9-KTm{5}PmRO(d-a|TTtxb$&w5a9y}7BqPh zi;lI8&_bmDSUy9T@!ob6^E! zvva$Hi<8&ahnHo-<#hj1px{+_^ML}wVX?N)K#cmJ=(u=tpJCehlzElmm0QPU(6!8+fsvO`ecmwOV+K z*<$EME1*-l*SRp0rKH)>r|uC(Qpq$QG(RJ4{XT-45WJ3{UUC;|EWo=i`LokYEIn30$}#3kv~@tOISs3BVR^wJ>Ln2Cjm!Tf)5q zZ>==w$9oVLj;StmptKm_yn*3!fzCr(8NOO3WE-ED5B`QfNrZ-BFHgND!~{>nR4y(J zne?6QAVM1g;uo)uuu&lp*#PnK`htk)ah?#7$d(rl>XX(FoM8~Nc(l;OqXY%oPh)+_ zyn3)x)c_k=NHUi)*PlNo<^-&Vw!7*ioqXn^WoqOuJAyolY|ER!E=4HcZnR3%iX-=#6aJw%?I@(4h(2|AICg?5X+!2$VFgC!-t^z5PNY| zuDEtnO(d%H3Bsl{t4^O2EsrCoNEKmqh2ouufOKn+bKr-64nSm>knI~CtF-IUMR?=3 zsZ%F@9f!*Byc@ zvK)|Pte5fb;Jsf|N{elN=34Uq+yj*g&n6E`9@njHz!eFrKj^?eba=xoh|Sa=By&1R z>xkF5CCZ)j3cm0D^nCh=wJ?WyZ2_PdLig_isE--ub1tL$WscEu(<-{W5Aug4 zBc43c0De#K@zi5;Uc>#KlwBJo29rHyhvQWlwJ1Rv@9omn+Plug<4l$AA-H)8+RfORjEQm0@P?Quv zw6iuEG_7yNmy5Urmd-IrO2b97QcdC1XiobPTM$wvYhEg1>17FOMY++L)8QYY2hQWl z44nyZ;)w1BnL@8+2asXEH6pI7zR8{PZF2>Dl}U$I8!qdcs#qr{Nl6pP3lhyZe_rZw z32==`=4`2&SS_h$zCw{r<$}+j%u@?MrWAx3gF@dcRjBKEAJw{lBVH;WlJH$M$0C>@ zFY;@*_PYL-I$rwL#=D=bqq8F$>qK75jktacUd4E~TewCek^@R5p;$82rH<`^27kbB z)kfT&Qs{jB)(Po{0}#drl1Y;8ncHbj*De)*^b|u9e;ESo|D)dmN&%*k3<0XO;Yo5I z;$o)EQDV5^^Z1Ae*3>p(eOtuxdF?_vbl)D!5b(2#oymr~-Tk{dRseH7M}O8u#T~B{ zOa-9=_U8j(&Jf^E{ye#{m(oZY5R}xPQ>))nf%WJI#+Oh|Ll6bB`nS$@6NFu?VKCEi z1e$M$A1*hhfL3Ovqy#8H**{Dh_2_GZwkR6FBds6~K2nEekhJ6uWd$PzZ+Lse1~w-y znve083pgLb)(yq0 z(gLt5mGfDAEfrY0{@`^#(oA3Esm^xFf!Rz%Fd~=DWH8$=HmUl5-S`8nw{`n7(Kbmm z9t^AsNk<|OFQO^2@jSSo-E;hCKuW7c9fJo35hxR;)W4IF_ML%St(IGsa?)DJau34% z<16Z(wwKYZ1pvZR5ZAVqs!e=ths*po#_GOxRtOu5X<#5sOxOoE6`2~eSA`y!5 zhQCd@{r=#kp0R73edYZ4LMKPdGNTRh-OdT~9FA@&&-d&TOEe(R_rAzwIN*y;e>|q1 z!TF9nrJ1{3vBtAv6DHkM#i#Q*UJ|80-bw|W^_NskG#LJQRpHaPo7_h^ELEs~Fw1p+ z(5vx?)NO9ia=mnJxms6Mqyq&4VbyxVU^E_$^A-dR*}*-pbB|VO|*|nrBE%~etkCPy(F(%t$LL%HpA_DI{ybe6A+EbWHKF( z*CUn9=X5)4mNLgsofN?U2@Dd-l4N7SXt|z7B9Z|}C8Jm{rBW&tO2u+Hq0?$KnhmGp zs=0529M3Kq$$NO8XPoKZTK+D?_X7k54SF0Yxc&%+07-;a z3iGyr#g4_810|QW4Ie$tEB~Nlz_t?!0Aqs?Q-mRth%(cRLl>1)Xyxu2u=M^&c+ss* zLr+=6MEc{i;R6N`Fn~Y>6DLrxfJF}@{{yh0QpMWLHW~guGqZMoJ`r4+j-Hd%s{een z!?Hd!279rwVH`O@h|f6n6rhrFa=A{|(Gr4vL4a(rK|7AQpkm^!eJhyMIF0gFt=toX zq3-2laWn}_5Fi<($4mxN23CT0VR>g(0|2UJOl8hFwK=z8Z|V)K{MZ8uF-sROnN5MxRkfe~&GH?a&O>f3M-vmVe(l9}zNkMN7TmYMwY_K?} zZNCIMoAwpI=iT|v+GR;+`X^OqE(TgB-Vzuu+8e|QL3!-ul?JEDO^cRX;neHg4TMWr z455-Je2TXM7@y1qn|}&}20gXgD7T2ntas)v9nN|LKbu zu)qL;&-*<(fdWE@!8-yJL9ue7;qLQENFo2p&vHp1bfAN5v*1hBpQDmSHG(p0MY031)^xGniI_~W8BOgE`S zyOG67&}nS^d91p#5>fjEikk62dr_Z^7a;_K9(nzU#*UAhFm$%P_5pHbrylEkR2NCJ zKlcM1WevkA*u==Hi>U=oS_!M*3+@=X_Ylf{9Qi{(_>ZnY$zA{uK^gf^Kj`0?zbG*^ zRl{=Kh#KTPj~_tAd@myS@!k2%5H^9U`u&K{N>l)C^grg|v6_i0iv|sjwT8~sdH|ja z53nGc_|%@~7xw`9^ApLlktG=WRaT|dCiF_Cvp^;q*)>EtR(%=}Zh1!e6ha75?Ts#E zw_~K<)O0OK(4;1aIrFXc>-gEKh%K^Q5AqCUr(vEM`S^+CmO-t~-hhW3e;ZQmI*tiZ zL#H8zzfb4(VHx-`A`>S`l>y+WC8-;c*0Y1mUL-&>EggzS=e)V4-|wXF0_F)t{bU=I zmVkLG}fh=m+Hc_9@?5)jkYG}Hf-au%vvw6 zoA(0w;=2kAe~po>!+N#TS}qnY%$vaRT=k*pdw20QhS^vGSX|aY!DMD*j7H;{Jt^)H z-wH{yt`b9eM5k2J*Rp12dT`;gb2k5>-fgJ#&z$fnV_w~k-dTKp!>De1NtcH*3f7A> zO6@wL(J9p$s>aGVJCPc;V9c`d1eQcenR!vYh)mk8#&)?Pv0lR+hYOxyGd1L5re@R4pP8J_fcBG3sQusf ze?B&K9@DN((p%%fIi@%XXSti!kvd2)5=2LnuwoD~5J`r1(KXAMQZHF9x@IFVq1E!6 zMnlbUUXN-z&tuwq_Ng0&8Hh#6%}C;$h3ErA2swjWxAiDv}Midn%Y8kZpIu4vX17BOH+~)bqTF zZQrF-tdi;c%jI&pRIH9~BVTQEjrr;7!(3GI8XQ9pR5s7xRGuuuNp-mLz8I^pz@O}v zYQ<``S{eS2YY>wKvFMhm=Bcx-t>)dRRP;z_CVeD)E1?1meJ|9C!pamm8Jx2hU70R- zcMeTBD2MS2yodDVepkDAh&_lRd3%O5n-$N)*K;T(U*djR9bi*ScMOUD!FmhU?%6%@ z1Mv^k`?Ce#-}`imtjn?U$d9@!pqH!Y(>k#w@xUe1azc3X>1SpzqtnTrBYsjYWY+;6= z?t}|^^v@}LNfNwsG{FHG*~Z?657+FJ^Ucjba{9DLDhP+T0Ok(b{mLwmFqWNLKtGe| z?$?se8*JZTTsx#Es`OsDECfnX>YFoV&MkM5ht0G#Oxt;{K$!7<)O?P?vVWT_KYDQr zfa5r=BTlKD6E>w($%KAdwR%_#rO5MbwW#`oiR9(!h~8o|T`JDPRVlNCMkNze{=iw$ zMeqQTx&Vj8U_4HQP%h_XRfh^X&$=qvbx3Xs(ZXpl+nsQp(_g~*KQG@S_)eve^N&?r@i+bI89>iq<+WB+fBbpsyFT&;2OJQD5L195mxwac zh(i~VRBYwy9kkfISu{kU9kyNwb$4q#8*rqnPH+g-Npbv-hgxqq8i<5u$Lo2!Yp3|X zK=f4^!VtIXpQes4Z!cDze z;2b-GEHQdZaiXhg>(a6SET!7ZJp_zfM&;w1lG>IGV=|ct4hUH)(WrFNOBWqrK~17V zh<>sJ@c;L%-T8Dn8N{V&i>GjZk{4Di?J_Y6%^a^~A%Olq8Sxf|GU`TGKtzF@F`u8y zQ_`N#?HjP&@ILEMQdANk29 zGn>CfxQap`70U>*fK}rR*i^J|8Kx>Qo+tI zWAAc$9yu5+{t$8)!f_8pL{P|L8Mw&FIgwS{P4R%{qP?zHL;Md(H0FOD^GPXRVD5&E zUF1P~e!-tE)9&422wk0z-xI?hJLf`(NG20X$MHZ&P>4pQQi(hLTf#*E1O^Cwzb{Y- z6c9QMzW=~U_Rk{t*T=66x$wWlC%1HG2+cTmMmiwYux`(i(bQMB3^5sI z9YA?2%!UJoOwd?t>TCF_Dh2-BqHM{v0#}t&=a^__-*3%Xj}M*kRW5~y+b;i<)J=`5 z5cx|udy4HGC{_xb=}+&gc9m+&v=e(t*myNxBAV?Al{9~7`wONqqD9^}VqGGeP` zgzP~PVhZ7Z=9I++%vyN~#sc^jX9iSyR;&YI)Aqu_gx#NsJayy&#rcV)k} z@>s+$s-aHU-P-l0^Zpx&8WEA(CUW9t543FcHtM+f?ic^!3X8T71YrorgqQBjDSi#{7C2Jb z29`M~T$FE#6WtT(0R-YEYeMVgO8T6N&nSC?+fbVDR0^ zxPE|u;C|4FFhzjMdU*EvGP5Wg_J499|Bvho&@b3*v@rt@A1kjR5d8kTP8R0m%Fplu z07&_7FN3LoS)iS0UNg&(6bb-)sm^ajntU7harM~gw~M+>2-q+yJht;`qOMO|sS`YP zd$i=tnLcw}Gc#c9vUG3=dxnM6z|%6f@vjrOXe|5+J10=gMRU1FvCFVZ`&}0Owzuib zFiUJvwPZ3@PZk=yT3lwLlVu1~kVNFtSOUwk!nirE&;$IZE?!L)3;0YB{wyKLm!C{MWSDUu zwjm7TYu(r#Oyd~FF+YtjzKE6I_XebAGkGveE~}Sh4S|dxF(@XVx7pbC2SNJMJ69*{^SLewD)R?AJA9?&Z`1ezeG%BT1B?H?6w&V4T&1yHv6ja=W zC9q&HB$)-H`B2KB;u?+VoK~~Z^oS2Wr$a!1O08HXl#11Q`Mp%2*vxjrz~y?eXuZ&Y zXgnsnwgC|W223ZlVzJ;DO=w&;qZ#CQbP;*x0|N1&6+%HSm&@sX&@^!b7@$}v7!HVx zX2Wr}KN_A7@ITB5so4L}Se>_Enoh@*3MC?$P^?%j=L^OIIi%KY*PIcFMM9-itd|9> z7E4ODM{jq?1QHX9kb@BP2vH+Ql`|Jk-j~>-Ia0;0tNalEB1dZF>=?6X)w8z_U6(hG zHGBZfr3ecHDzT{msQ>gyr9o*xMhpZgRB{LZeDha4I7Eu(|_~ za@d@}>IeX%Drb3<^s-__txfpF1P(;-v~U|JM2+Z?r&9^g)rR6V0G#KKk-s3h>T!R>0l_P(3AeC$NoR~_6A^s9>6dxv?GUFL z3%S%O+NYw4_@=7T0r5)EqI&QIE<{1T9$dHr*+QNa@=tu&H~w5H`<03eqC2X}PyvfqG;%lr3G&e{uqEgayEuL0pdR`9=&#fc$ zfWPxMivJn5yLa3&uAh@jloPNb{24k(XEsD1vN-!E<4-StQa|;_&IQ(CKwGA9>+eS6 zCflV$$Fh|%r&>4t5Ki?@fbStS_=|}BRgmAGgVm?)8MJk-?!3*6PygBIx2gNiOj-|N zh9DyjK_!-9ryc^SsH)WqSg~cmv8i2_WXG}fzz&7<|2I&51?fK9xBfBS-zB%-r8pqP zy`}IzL^AvCR|M|Zw=9Wg)A|(YOQ-sDG|m zuD_0+&_W0Va%J~0{F!soNvt0iRvouVsGXbrSVV)o_IO5lG8KgN1vKxws_jRw>7 zZtFZEktifuv6_yNWaR&R{F=(RSsSlHTcZ3i;bMEL=8@Bp6W_Y<5qCPOXN=3LpB3T^ zo@5fqr2igpSX-N6e+>wz#`Mg@h>za z+)YqmLTa+{)Ept%g8(clwoViN{EC&3b;U`{?loi;h20VT7Qx|4e3%`YI4WtSvOyho zczu`rriK=OAUvZz8^Mt~*hBxVG%R8Ic}nM;RY)g1@=Sky3y7DkFp+~ETmE92`l-GO z<7@p;c&Q8tzJ5;rB|`%8P{w++Hd@~_%1|t)2_S)MpW~L(-~Z%3VQVy5qhdirrc1c2 z%)x%Y+fi{No8^rsoPHl|?YOmKrK)j2=g*j|X_6g@;|=5>si#j(N=!|bXG}TbfQL5u z2+*NXE>oRT&4d}4M3`o7RroF3GaYxFbG+EB^@f$L)wcmZPtWtaQsndbcscr`{|ygF zjNFWB{jzQz9V;AJQ|Gv(smz7E7&DJD58?m;@3BFB)(*-tfD2&uR2BmEmU16y5r8?5 zIosYTQHccl%p%F{;$jFq{Fp3+^v?tgr!Bb93`U%A*_ws!i0UIkR1zMJ(m!olp@h2iGoQhAXqN4GZw{hbXjZKz{YAGvc#1bVg?aJ0MX=* zs_Yp_3kV4*OY&SSo9#S9i_Z_ek^S`?m#$*Wi=HfOb|+&CN9=Ci+bDuGW$Rf%LL(FJ zO}kVe(@Sj@YfEy@(!@t04b4T$hDfaaRNTHeQpW6Sb6c)|OY{}(n0Q(hHHQe+{w*Y8_ND^jf}s-QQKh3LOhdieWZ zI7&*b`{%4?);PtJN*AwuD)Uzph%!h)M%Hg|u4Ez=eI;2wm`e6uE3d`zIY)s8>Di;q zsz*kv2Z=cnDW7EZpn9H;hdm0qI=+wUDK7|a7kWcT=ui*cUR*?pf-@GW={A~1I|*cp zGxeui#(ac)x|xxS$Cxu@XO-iY-*niL6L++E!in=3$RU_hRor%i2C^X43WVqvZWBgq zv_-_mt&S`C^t2ywl@94u+VhMLQ})T8@gXJ#3i`*SK9?AO#IhN2^QZ!u1k-jDf#cX@BwBS;Z?i*3qZs?TmD_fANmJ3uoPa7qIkK(UmE4HRs{3#Fk6i zYx`b@}s#a znj!|#dSRwmnzfN zsB9HL2)TQLL79A#t&mlxa!V)`nENu5~Hf zW6{8-i!FO(*?84n#A5ZerKBxul|N$kguFy%VM{akzyT!yz#UwAH z+Km~FPnKlDB%40S1a4TVOO*Sl3Y$=1Zpg5jGLcI+IVq8AHxYZwX5&mqI+39}t=?|l zmZG-dKnj8)B}G++NVQr~rT1C4s%T!S)Uqnlt|Dt$mxEcAm|01pS&_rIDxted^R7ty zBB^1wACv^H2oAFd6>q}CE{Cv4GH=p>J7UcZban)MmLE&$#9BMx`bA?q8QV?Gc9OQI zZe6)v=U(eRka{`aj`4P?_l5DF@$m$JJ9g~K%P)aHFnD_C4HkRE@W|y6h@XZ(s(<{x zQSu+1eFf<|CFQ^v3={yto(}+!H3Y!o>?85)gW|st0ti9~Vh|yOVvrDmT2Aa^)g6JE z5Q2MB2p~!+gh8zo0Mecdz=L&=!h|+5pq@5_u-X{HgL6;so!?V+~=MSy|@=w4%1dk>ZjeJ~3xGCT|N(g36DY2whKd2T`sgYL6s8&$9>aP|d zsa6Q$E?5X4Yb}7qoTKa%sT+XG!9*D{QjLw4WS}*VEqh?v9~t|^=HItNpe=4TNnGZC z=-+&kdlASB%ifo3N9zvs}i7mVCuV~F5O@K)Bd2w=$?TjJD~bhrf~ZPIqh zx}VeWF7|<q?tarSld z-?Qe2((D${H-y?=8??V%7Qi`%9N86RU)}Bav=5+Bexx|V_Zbt+L<+zJ{QE5q6mvod z?m;1h38oq=*fAr>vSJ`+W-4c9I*4W}sm1`+T4NlHt?}k>IM(I*U>?pyBF+&`ddC>; z?VRMjAa*sejpBmXgq?{D5R6X zJ)wJycNpqJs7R7ElH@^}NswYxDpE;gS`ti!#h@iEdNa`+@+sjMyb6ZduZ6OyJyN zfwACdD20Jl26%bU&M+*4(JU&{I1K~Fd6=h>eBF5l9C{##frFjjj>Ild10>o=eAE9r zCAZPpZIBK#6ZmQ1T(M9*7!TJA=A5x`JO~dv4tPBHX!QQz%@K%0Fb6>ngFFa%G?I`P z_`gWwKP7k?`h-Od=%_2{l?r=`ZN<8cEP>79j>)>3tMu#*Ug7J;!%7*l5}Nb4v*Ed=qQ%k-1m3LX4}?okdL3(d*X6!sbA?yg$k<^p~M|dPEC*)n2f^N2PHJ z<<-TjS84th1yqZCEyIYtxs8<$}j&U1ey({$A8JvX88^CO@GPz6FgZaG*Y9LNpC zE`7t5-~5JR>!I{~R`322Rtq9Dt^$E}iIsG;k(nfFV?$NI1Y=!Z31Z(o7mm*wGTOY6 zF$}Xug7#6?-182$ZL-DkZe}0Qjb)$kon{Z?9-?`M%%*t+4d)#!-}Mq8>`ANM(^fwI z=5?7qvu;L_QQZWeUS1c=UEYM#W!;wBY2DVxyKLssyO`q7{lQh!DWLznM+4>ziH-?a zwkSqqn8pDSjSvw@p%|fUgMp;35!jTnPDH$+KelZF72VPiSS5|*c-zq3{yOE0-%g7$ z$Iy$^(9jEIYtMfb(B_)(E{x|&Be3VnWH7uZpZXL@BIGGmc}vjR^tn}QkDMk0X6jnj zh3Za+6y===I>a-Rw2W^mrTL3fajj{ma-xp_?}eT@MkH0zx}tPJ-Rsg|nkMPLaS}w$ zPa<3>#Hgky8l$evi;U|!BU7Hs^vCmTU-&y7?{{h7DI2bC&kgdsPW|vGJK{cPTyxYr z&wRPj+oun=zd`zX%v8saOWjd5Q*XMkxhu|k=EbXy_4BH~4#(~-%&9Lk8`5p>mZARB zv)ps9zWe2gMMN~c4@vygStB=ss|xmQ=r%u2^?Zl$P?Q~T<}yscsEOlX)ZU*Fc&IxgDMT#joo zGRM72x$|7c+-alpQ24U{Hgr2U&sU|2A55_WnN*RAWlM|)^+%a>a4+s+{);(d7>BQ# zbN-}x_a@dKs=Iq*-Zq!$=?mEdpzrSUSJk#Pl<(V6&Y0vSwXj(Wrb#Y6ed`t{KqBfO zG7eBx7kdE{>ZHmkysK@<_WG|?En4c_NzLXH8DQS8AB(mf!)Y1GnGCt;^G}Yeo|K!s zy|c=tr(d2yu6*a+lLfEBN?~b*hP{ORBTdU5IhwK}Wcr5oza#)%gPBz4`U&kS*zb9eFGj-6ULj`o6REMsh^H|~^563#Aw zw(|c%C!=B~F1dZ3*whoVZT!QDo91SreOX;c*JU=SBga@oa{QrX3;R?>husqz)P7O1 zkCvj<)Gd{*i5hMqv~s$qCwKDxY)*M~Y?Gr~CnZx-^JU~58$!LlPRNikvb~d#abD)P zCf=kXkuORr*<}>-+ig?!WfAV#VjMEIejMvhg`Vcnb`-hQc0qFylPx-NWVZDEvAU+$ zG0#p()B-*ww{y-N66X6eHrs9Z%H|)B!U4Y0-RY@09zWywXf$Ec?D=DwxI3a~$L`#JP#%={a>8}UkHt8yGK!u^v0_TDLKmLy(gFS#>g^Ik7xM=fB#Caa|CQnjy> zjRWE$S0N@nvh$83+Y)(sDjZh4%Em9W`U#_wC0r5RfIA~$VHHWE| zJclvr8xh|mQOx;(TC}y&b-j7pva<77cWG~#>Dt3uy3Cm1jHlJAbzY8#A~Q@eeQSF0 zBO@tKs1DOloB99JHR8E#J_BsI9punQocXCi`^cPyCfA84c9jSEl-=q3v?lZ4PiB%S zVld1mI&`mSHL06fECY0Lv}50uoQ&&>_R`d{k)V1sxXx;WrgMGs3TPbjAJ<|f|39kU zF-VlAi`H!0wr$(Cb(*Jb+wMMX+qP}nwryLt-}}wP#N_W?KdLgLGIHly&uUQr@ZwMS zUeTbLo6m0Seu=Hwxs%a?CvyHf`OJJO$M%SlVNs?{@=TDnrjd#We#&V`AJO>v(Pkz7 z`Syr@glF#H{;XocvO()0uZfcmj?7=c3{UL&JZVjw_1P)`>YD0q+I`fFTg2q9BFhhh z4mZ)p5&TjYlAEddUHuIkv=&2i1AeR*uz>kH9b&<0%sSHnVN3FDO3ec|><8OvJ zA)Pw70K`DDCsH^@30np?%EGJeY=hDcZt27ao*0;51qlE`!yc=jH|{DI75kzM7E%zXTCDu)O-Ua-e@Og_j( zVFH&yo4+(nW8M>IrqQy=@H?z~d7&Wm%Sp1>dJvnngYzdXHtn!>LH7?oySV1_U*Rw! zFk9xsaG)fXk#Acj=wJwD=rC|I{C>A+fGGSWj}T_Zq!qAmNR=v~iDi*W?t{R0WX8tl zh?Ll_M0Tbo56+{P-^p5+bh}g$m3~@SN4<#N{&n!sKW0WW!v+&jA*y+ZXb%Q!5-Oi! zNn#wn5Cga{jBQe$V}Jjwyf#yo(I8PEDS)a%?0Kh=z~B=q%})(E$E2OV3jZ$bg{#{O zP|wZ`U^w?aNCEGlU4&~Tej4D+AOAkf?}(m0n1Wlj)X*X%MWPvoR`6h;gPFZ*mwn(k zQY-o?SS5`}z6(V(zecNOMGp~W{3xM5C89xFZiH&3S)W3M;fH|fPZakK%^0Jwt1eeh zcZLTpDd>Fi7jFYs#Li2|-i6&iO5<1ke$OxU1P7C_gE=6D^JR`b$cRf#KPGlZu2&J} zGjXusR_g(XyU|e_`YKLNki1Urz@YcV75U%ayw;rZQ!o}1W?D9A@1F7DU_uB!wu{8+ zv|q73N%5(Kj@@1FL5p?H+xi*01cQB}&Ad;lp+OsrW?uNZM1?h6k;ESjeFa?)g48O1 zRGj>~P6XZ%SM8Mv(O}dnnUq0lQCMTU+%`Zb6QB?hokAqSJ^gnvv{rfed{t4BtdqI?L(^+Rk!D_M3^9E1H#;uB(02D z9NFY0B+lH-{bGClBu>ch*6KNsq&ZZL@@L@vh}O`O{+U{D7c`31V>2W|C&*(s|3MRq z$W+LTv-5{T@CA<=*W5ctYIkP22jdbd2s|h;>f~}yDqdr7+9xA>1w=3tdTsT4u>4|5 zeZ*g?O#5-}u{9^FkjG&+4A~No3vhu|j-__r?$3ALEo7PSSb>JQ$;2Dqf_5ppp*U(& zM)(do&1MqCfbeq%m0Aoy-RUT4GnE;)KS$FLo&%>qsX4?KS8@h$mGaycayWfkn=V)- zE=;Zx3@Ale`A1U_y~f^KUxNPD(XW`om4;5!QUOG8FD^NlpH_(No^GT06@-y*zLs!} zrjk3H0cx#M>>336&bZ2xPOc-DSE{3qf9{;5od7NU2dD}*!$r4@Yj^)R6>QG5ChA~a zQckC*9T+u_6%SI6A0U%)^LAOP7j)Xig=x>%{xnl>kqI2@J8d)2$HD-H3X7OE$Y4T7 zzfc{U1^7xue6iqKe0|wqTLRtgRVcryG}wPrASJaAs@drr%IJJihov`!*ewxK_>~#& z-9W%P7Dl|lGn~PU*$4LO(4qt?<#uW^kG6qdlK?FIpEoZFoUwg2-}o<1+qf$ zw(9wAfX5|C)(@IWWASlh-fz=pnM$aa-a$n9s+y<_)GzCRg6gY%Li{u>h0g3=`EaVs zC_wd8&$hrznaQJ5NrCSdeDkH8#e1o2yI3|sqg~evMSQ+95A=kI6Zl;=Xh;~GbtzAc zSo;ktQt?+6v#Od_fnxCeSsEviVqGz9*qus?Dp1?;4+sBuCJ5B=ev$gM$3+%6-#jmM z=mBhS_rr3bu#a0Wr!XDpZUlhi^{qOCBBn!61aB z!E?>rd~1<5H+0PNBYLt_02KZ5l>P7sc#8n9Luf=1Bvt$j zA21S2sB7t&b8jTjHKWnmdV;0Rl8|;&0lvIoMeN_oh_z^eTOjkJcF=!rSNDb;-#je^sr)+kY4!dQ z$Dz!x>hzq1o`jar#L9SfJS&S%&84&*ad_)uIxS@Gc2*zeYa8dqQpQMwZ#~XR<7>Rb zmi&wW5Jxf%TVLM+!@t&jD`sJ(lh4W@HPKN2sPd1UlQ&%@To0U+CwQ+U$M6S#ld3!q z!Fbv#56Ur8?w4cmv(EbLv_U}c2R$@K(EpT@f!3)IUCCuqy^@-nObV9>9Yl(ud5j{3 z8HpU)bp<9wY^;2Ee&CpFzP| zn+jjKnwK&Tg5-nE$-%6glVNlDLT7IsqqT7i?btlvgLji)_fYzhi`mzxEv=C^vcS^h zYX34p8t`Bqosm9b8E_l>=a$B%iwNrDt;te`8YREX1OD^_3xWWd8PZFlE zmgYxPY1&O3qapccA+z&yJ8Q0=%P8s~>$FBZ_H; z1T{IV2VpTta3dPjpq3oa8OMb-_E#7mFymZyqy^*{65wS{>bDh@!*=q*Y>6&+=Ig8z-BrhdBS(6=O}jIg=Zo*1 zx38Gi5k9sfOmAZsOgEwIw}ZDp*{JHf9iiTe9=`04iPW9%p_1+k-yPT&SDvUA^ZhFR zOJzL5pvC>aLMmXGjgb)3o`&MB;sB(kYRTRaA zRhQ;8sIwlKW+4n^7{wEhmRF5RI7Ws(wDQ4|)d%cf#{m0xZ=uILGT{jPJmTtlMZ0#z z-gboKHD610jmo?%=eRwh+wQYD=}+61$99gpH+VjtIuq_g-lpff+MQ0U)m89D z_KZP}u^H@#vA>ev=brXm>xPi1t%-eUW<6CoG-(@*j?~p7V0{+mceJW*pjX^|rKlF8 zg`&^9#1b_u4fc3?w~BK{|-<#|GWBLeX8-!S^dc#(BrsHQ1<0I z(M##Hf8u8Ux~cZvblf5KushR2n))6U*_^xGZ7r{x$lm2F~!uqi< za{xa1`9Lw_*g51Qz=**&+7vz28u~l|g2=NAlXRdgs_IA*>hvCp#vb?sDrF_R2x zM>emoncRRKH9`)E-zXGud2&3Vu%=BON`^x-!qpnrAyDyv#$S@;7Dc9h2PsnfTtwnaSrp zdv6QoDX!mGuH%*PB}6V^%1WDbk-DmN;fIX;m~vIz+SXP`P9+RHO(6?0>oU;<%F^aY zLMTyb(FQT7jKVaJu)dI^1ha~!1G}|YHlnv!S>#A%{Gg*#cc!XWcptht!OtQi8nrOZ zE1~yQIWEcN!m#6<81|VZw&rO))RqX|9MtlZ16*(&wK}ZVp&fAeRJ0U1%z^1o=e&i+(3?)3y;!eUG*FWFs8v7?lEQ#Kl-;`6!w1cYP+ zh=Maio8w5hVwB;fY&GsIxa>)YZ_2B4CMWN)fNu33I3WPmfG8veK&&p{F&(X>3bZrb zSe!LN(9C?0Kr9G$cneni$!J_N39s&D&BrN6M7aeY5Fk+w8vW?3bW%#sxZIC@C5Tq% zw>D`5=a@dRdCXYzHfc);ZNM=Lc;(H_b$J7l_l{`C>?%H&ii5?;|3jt?Dwvrcq2&?T zhY~gDK^RA^=GJ{CHcVsako@8tp*gvq%&-`rT;FKyHC5j|bg;(GpkQvLvfw)PlQu3P#+-ad##S~aih=Fm5zQR(@7**o2CAV%xXGgUs@4idQi)$t$8DP)U-l#bHR|VUb)a9rY zw7xCeFExHxEDx++4>~=hncF6AiR}QuJnQVC;i>hX*hiZ6fcyT;G2hO?2k(t%pQ9Jv zI}2=|Sb(9*HGO6rL^L541lPM4T|9pE{oW?@5cUt?SSSP8a{4(j7K*shUy9eGjD|eq zQ9BZ-C;-1+gyeT(uSR1Ee+81{SCyD!Gg5GJ=xuw zb{1jr-S=YWY(j>^tH^=G&c>~*8CaiQqEWf`pvTaj?FbXm!^d*@IeEr(^=BQ?`*j8US52tc-koKoS(*npZ@fp34X|y zt;ebXOcvWdq5#?r7YSGPa(C`~MF_%h#q$L@f}SNqC|`d0=E3`$rk16^9`+9f`0uHD_IU_#xF0rqo~Zvyq9zA zqe(pW^(48Re%AIl<{NH07c}pku8y^5@|qri?oR?385%1bZ5}T^kOAc2TYdhNMe66T zmPDE9WzAGOL?X~ItXp5#AtSaYV8{nD`P$p=+W;@0*0_Qy`LkI}hFm0fO2B0P9cz3w z`XS&Qg_30+bLA_C@T81bR=w>+ZLWR4c~zVj!Mgc4N!$SZ=_}y62U7V!ILc*yz@IGL z8>H%wh1{X=*fslS`KuwlTSfWl&tX$;20neGwERqqG3wRRTv+EO%W{{~42 zp;;T}=gg308113u$4)*Flxc&>S4U%wxrC(C2EcW@t-JaKy8QfKCz0GQdP0Ww-OOSBjgv!3h!bU zEgW)Tb^CsSzb+P5Qi2$Bk?}s*6Db+Ay1r9d%JICxLJlKrMU%vmj=F465=RfH`Z8^Z znL{MUXdN|n!@GNwY}30zE|Wi6;rutz6S(bIHbA;`yi!6L*t#UsB8T#1-Kax_$c90Q zMrf8x-wx8&!XJPUBlto{e+1zPo%pLRRw>njUq^{G-+U09F%p?&>{alJ?8M{rt<21L z<;*fp6BGg0^C@aKkrK(r=Q{U?Wq0n3Z-)u*^@}tZP_rl7kH?a5=#7(!{m_fkTh{oM zi=w|6$@$sLb9~X(3z#9vKJ)mcO{=Tjr2e2QSVNDI^$n<@tpDqj9bAglRY3@^Xnxup zj;&c5;n*oFM(enS6Zn?f#|ABMFXmzqF$rsvP%2xW+VS7f=a5wc_CUVv0WOxcOpEN>r(j zQYF;bL|{--AjYiM0u5#G>m5PaUX^%}>Sar8~YF+xji1gB(Kd_FG*6SCo zDicN%4XR-m5^pQdSm;Jj@4!$6pe|H0N5aff6+0Iag#;xqiIIxC6wm?uI%itzXSJMY zdCMFB7DBY_weZ)fbuP=-ySHDyTDZ-cL76ItvgXtp(ZpFUQ0wOTPm=o=)jqOV322k#eC z?R}EdtnJ;K>B}wDsUsaO6M(-zaHC)%GDrg%Xmx}>gRdE#t%o7!AEA^?-J8B8>*H7f zz7YpcT}PpZF~W)d0&VSwb>-=?Jh4*=!ZJ}J;u=#G(-=5jxKd7)Tu8M~=O+D~A=xo` zp}F6|*`!`7r`OAZAHkaSqb{xOr^d0?bv-9Sch5lU$lU0xQ`JW8ccUDsY+3hMSh1Dt zeDulbdi#!iaqYR`zN?gl>2yrixzsiaEvPp0Zwbb6UM2I#S~GFN=qBUEp=mW`=} zPM!Um$RGmGEio7;PKq)7=RkxDCqENx-LfcV&g4&ZrDiwG_jwWJGJt8H9N<#TursAE zDx*u4y7rp8tgYjWu3(mT?r=rnBx~VjbEzHSo+_1k(!DkE3jfdxJ>-{`!B1S{Wl<7L-#@Kn|5a$9u!4&T+nZANt3x6|{j4!35C$)qF7~kFpYm0yaPxCGe(pW1SR2MD+F>rP!Rls4|3i6v(3yO6?0P5kW5eljY(Se zf=n~xlq4lFB}&p16!t$Dko!YnqNv20DBOg#0SHXSd3Pqxqx4%?>vhY;w^Mp zT#c5VT(2I1A0$02IM72acG}PbkKV+!5JC|_tTX=xy3SB*Tm$&R-pQ<=6!-ATUX@}cH5!#{f-R6GZJm+hqA^t+yj zR%IYaOs+W|O=t8d>?yFsO{0xBHJjx0VzEKm4tdZX(_O>5MBvGOM&m{`?`zu-z{)heX_zh)gv) z8Xv24%os8*SuU0M1gtbWQ*v1+QR>$4*ED})h#0}8JKFHL2en!$^AQT;)RMcNPbv2c z!fCKxv$#XEj{>ur62TP#_k1&SSw&*BB?=pit!*_pB#k%c02I3aF%J|_>Kb;6m7`u` zE6QXIp%J*&AWcgJ3c?PnVEO1cPNh*^qA;--Q)(Ln^Nw2)01OZunL%ZgjlDOqZHN`>1E4u=_1lWKbHKDq$Q~ z7oTltfiqq^cQl8Snf%kCkDRz>G0)0moXj0RFibG)xWwKtsv4_=X-U{lp5F{#&NQxL zWolK<&`~)KwVri;PK{M^&V|*gwC-do*ne?x9}DzM|2EJKM9@=;@)!AdthO9Cp$oRF zU*ie$?8yHj*KeW5NPmuTcL)Q&?uF3k$H;q{=34dgI&0W-!xA*s_=<>Zl2DdfcpjsAEFQjH&Lb_z=AMO& zkUWFoei#i#ZKd{|Vu1z!{5-4MP&!-hF3eN`t*62peU#ypUpv9wKEwwv@ejeOYvO4R z7jHMQnZ4qTRaKz?6DeXp1j5^;18gcox7!JB6`_*#5WVqa|C^0Xv7}pnqI%>AIKxyY z-zdFo27du{5j890j5asD1_keBeafhx4M7DenmcfxY%$LHTJglH4^`b-S7rl8PZII{ zcdm^co%N|v9b0%ztjm-=h6}r=*T~3IGGBbgPhc1YeD#cHg?_uLiO+SzeZFW5%uB;! z<|V8wCDw=8IiCm>9m#Fo80@E5U-lyw4a!R=a-PMc5tGa#Fv@Ck1UstTW<`yxq1|7* z#o0(-QxC5LR1>ldC3uLCy;oz9uOKfR z!FhISv!{}9$KTpA>^Fo*xZt(+A2H|+WM26!g#*kKf8~MnOyf9|6X+Q~=cv7gSh6#L zC)RPjqqs~^QTTL&@c;m#g9Nz>N5Jx(2huZ;t0@|_l>_k(>L^FJIBS=?FKV*zi=0Pn zbV-Jsok+W`hm0qqTW)-HYk`M&*5Av&E>QAox* z=Mv?TQqu?0AEU1yazJlLKW9`NvWDTBskk72@ai_;YkPS{o;~9-a_{p~N@+O77%d`} z{X8|Zke+O_kuteCTErBHY!i)BTc<+e!KG&nip%0{>!l6|+L2CFe^ZF1XFf)=b*Oye z(fk81QWA4YN%3I|i^3$jcS*Kk7Q|#t!-%fvaMvl^5sDuf(}gxtZZwxHuq^twB*)FW zxrnBlw86WC?)5*0(1khTtgNeaAUa5zV1xQ2~P?^=xy?kK&_PTzO*RSthLNE(Vf8t5}W z-yd!)m@+1{EJ{Q_bfhK^zFhbBT5CL8<^=K)ud?U8;$#ZcCL>vwN;AbB^OotJ&T%&~8WK?=B@{{EePg)DH#shpf=!Q&jN-1CEwV zCa?oA2O^2(p&--pAx(DFcjR27DUOZdxyN1GBn(?HfzNd%06>bEALgnti?T@AYX&1^ zZ}(P9y?6$0@+!PMKKM#v@AvqDgt~ZgMnHFy+`J228u0K=sLy(SK&QDvwmR_zqj7@( zq@YoBKY&J~mhF~;MKTgB^9%83Hizs3oDYf>f@5Us8O$7Lr?FJ*3k|ic#74Bd+U_f4 z3QBb-J1@R^53ed}PMf>J3cDY^<^x>EQc4+zE98<2P zsLI%|0RoI15|P?$i0G(sT-j50Y-vktZ)(##C&vG`5dJIDrui)z;>2#q?>CRR=(w-( zRsG*6|9=PI9t#SpTt_H`h|wYA_O*p0IHDZQU8Iun5=eCL_8`ASU;qNBlDVpuOPbC~BUo{X3-(Hn<_zC? zAWfBvAO4x=0*k>Yp^rT=oN;cgFhnD!Mfio4? zA0PzA-qGu0f5|L$*dI%EJ+wv?bu{F6dT&u{+Y(kfme-i&OF2GFriz!%oIQZKKd$-G zvUIe!oK71QvDxIUJYBC|@EoyvVx_sMI8jfA-T$$WrGiL(I3*-DR-c6&77~z_N&L39 z$+bg?XO#PsNMs=WvlAa^MYf_>UwJH7kZ07vw{tvA4EVYs7@^r zUVdt^g1wR8M5XlSMv5QGT~W<>!R3oV?xEi1!(R6Vm_%QlWybJ@t~`7G!_j_d>Q}IN zMU5c&xGqV2u$8fZJ*C#MaP@=?;!pUC5+w8&$z#+wzby29m7r2DZ~E;(9gV?j|La9y zn<-nJbIuyo>O)%bsQ!mSY{rWjH1|BY^aCfi7 zRPDA6m(6Z2ln)31b?5o_LnCFJMhCN`#QH8k)Jg(BS;I>_S#X%m3G&_-@7~JMlpMQDDS+s2@1sHoPN0i_Q z%Fb6%EctfC2@W1zpC)RE?`D`%4HTUs%L!56BWlcG)a3n1cPKb4!gOp?#|5>ZO@rop z2yH`~7^k8M{+l!yP~G0rpu8;L2&o~PeOthz=FObqazD$xl{W2C{W|TM7ol_Rpx&My z4{WESUyGGml0l=t9k&cyhhJmUTDD_;Ikl6ZZ!39BBH|QN!+cbHy{wxpu|+y(>8aKA zT)$d~BRmoFvD<93D&3oiWW)(l7o%)~qOu#z%bn*m|f7wvelzK=f73wu2xJrJ|yo`DgR zD0&#U{2NB_B-FtXkZA29)Y!B)a}n3nr7^(jh7j(_5sR5d;?v1!%A7n_v22g8$sW*u zHb>?cxsHZ-*N#{D_Xe-bXC}c8OAk@^TdA8AzXr%v-q(9_!KdU=Ag3tdUoJvo06{4T zQEH!Eq=HY}AHOZCACbx4;zso?)3?K~JGq5Ck(DdXau&NT=;m63lgWn6V@uFrBzXcN z;2fOvM&r6;B*d$NYm7CjjdcsahMZr;aV58yO}?ZSx&>X8F8vr@0pAa%NJ2B^h8JE7lplSL%E2^tsblW-Ije%+t@7=;)%~+l5%~?cMPxn!adv zHm<6!k!!Gb9)EooZ$4f|?9`l}sE2f3!EJ6H{?xPhVG#Vu#*6rPdUEf`->-NN|P(K)IYU*@6IHvk!MG+N=CuXMtso)Vox=NbY7?)N zT)tR5R!D0stFk;Y&tuw7ND`7Dw{=<+S4G(_JJi_0k-*#pv4VT@>=v))v-IxUt_k-s zI0AUoxwX-4z0ppqRcCzhp^S|${QeZ?9Q&bWQ+ejzwx6M%-NtD?S16c;^_N13XxIMp zb{v;o+p&-F!>VD3MOlVP4pQ{+AGN#$X_}eW?tp(Z+DaTqI7Orx%InpN&*j8A5NW-< zXT4`fougKRG4?#XN7(|p_oCvI`UX!<%>7@N1bHU1;CSk_ctZ1dqVIl0Q$@K#l#-an z6psWalEEGh#K8RCiuQr&CCcxpZ{F|cuXeZ|Vf)_@EfXgU(hIF&cjT>7Q%HbD2)!E1 zKhTD65;~_uqLJj&uUW#|X7OXisTS#HCaLDhYsVPZhgYnyP&YgjAxIQ~P^AGM3esf* z4g`4VWmUPz?Rn_$x%goE7-IT3cmpIn{+Ox3PoKcuyWrowf_@;FFy#uNWQ}>y@VH)Q zVQ;V>#52=|r4_r0=ay}X8MXetx7=UMXPLow z06+d@I8y{IaG+lcRuH~^6-|GP+?9dx09(}F9piLPPYnoCIttAyJ$~ViQ5ZE3>#EThKph@w{Jh3bK^kP7Ox?U_btr0vpD+GeS2@r@P^+sQY)0=3n z*Uj$t^~5?RS2}qJeESHj7UHkBoMfWIkbml@MZ=v4)heY2#KN7Dg7zVpT(>D^d71p8 z;SlX5XA5INKufWj3iG}kWEXU(BjFs{Z{Bxd6qpQx!ksTvuGVRrDp>r87ZnTg1Y_`M z;du+EBG7RqM(4Z6?e-yfJKfG4_k@bKMMO>qw_pU;?|q7qg7`mcFz}n54qy+utVDSN zaq{(PvN5UbH?_crs1-M#724&SN~2XSFu7n^ym?_*k>c3thatw1rysWiu2RWg0!awIt1RUc7ZS|+vwIkS@I`7(PV&b9sQ(@?kg{lZ zp@)dVWC+#ESuCoi|1zzwZ=_{q>a276^SHaOe%d>bhx7QaFRS#o7Lp9=yF7_{X?f!>jQLne|atcRO2wH*aTreEAKl?2DMe zXYYB}L*fCPF1RfLIIxuVlM!K7doe_@|=0BcKl`4P(lT=eS zWdr{O0;yd3%xRmT&TV0 z=_9t28(JI!hJdvT+m?n=bD-Qk^Q|4e8}R|S3XE&Hrz7ZxAR*R92adv~arKyfT;asA zjyoDB=`KBavTx@Bw{;cg<*}92a zXdhAEe6|mS07?1r--!W7YQQo!e6L#cLp02Z&j^@cxJlFBp_4hzh4#1FLXBy|u7xu* zN|3pZr7tcFq#PV)cY`UjSS7TV=O)mEM%S1ATUaA&nFZV&BDTyH{*pc$w()E-C@yPa z{Yl|xXdHdDAki@acaxv-;l$iAkuX7Uim3Adi=L)u21tHEl;+S>u4nrueVFk#{j-G) z?=$LRHI+#c^7k%tht*^WQgn=K<$kGvI4|ut6juuK$oOHiat)rb4!_oBe_pbU$%~2m z-%_3%2JYY9WrLfoko#nyJzZMt5=^fWMeZp7krhK!IG&IZ6=!3&(MitYie!_RoF^7y zm+b{DD4^_>Pl?xbqR5jvpCt467y#M>s{EbqvH& ztSt2S~Wt z+NBa(E5%3B$#HqtXRaH>*Om)(LR`!=zJJV)v}8_{R{c{HB;O5f5wK86aoewEG5Y$P z%5(-UvY0L82Wws{fgxB|OV6^BKMa-zJ2hZWtG)wK1D3^A+NJ8}}b#jt6iSVi+WfgL+Q+(9bW4TO`C>s-Js7M~q4fa}7hx^z0I0krke zceb??gTlE8XMjS;p)^VAI6kE4lq4A`*XiA_t;KPnA2qL7Qj)OsVyNnRNsaaoy1Es< zHB(40kCoKLgi!y69mhNvR?dw)keLbaN-{NXbD_F(7es_mp!NDvxNp=igul}9dAADN z%K-n)#Zh?X@?i|$D~mPBAu+Ha1tv<+lh3X-@IVtpdc^n^QLq*og0E5GF0Wbsk5We| z%WiD9a>*(*pfvi|btLq(MyP)c=)X!PhNrfYYTd)OC;A!E3Phpk!*HbaotA0FH!&8t zI7$Q2;mlcK5NcX!5az+ff<=y_ZtqsDiR$c+&`8>Zu87Bt>{nNKTcLLY%$DL#QS7r)uMd|8K?I961mvwpZ3vb_#0MqzU$QmOHZ_WR6eAz&=Y`Y}zb7|3NHQR4lZ%g;Rk%Xn*+u3W`z|*dzb)#0{8{s7DDDSIiVFZ7nLgef(7ToEmB)6gt|u zaGeOeecrc{7b|6%#;mk-0Jt5QcGYxx4`BpEa$Ecol`Lps9M^zOYdjb1v^mzr1_u|e zz)Yt=gsV~f{-(3MQrO_oTVbPFDYf_+HliaLrBVNVCl+DMt6)^^tGgIyiZSj4uuJV{hfG^aOT0^!bZ;4%3TsqZ z<=}|@o2GKeY2Fqc)y`tV_J!1&8jyis`3suTEY=rhus^8%a%5$A;pM2Ov^LFW z&|_nsV4N3)1S^CkC)SkrHv!3tgEN0Lq{7zRib!(JS=o%Wvm4+|X}rFXfPt6KpQ3#~ zHLgtNLG2&eTmx?A_5B#z;$q8v|2WM=Ksx4neTSIp^k03UcJ-uw#MIoiYRTx=H865c zbY&NnXpKvD`t9@#zgfKqb zYs5djU4dh6+Bz2>f&3NIJ=T})1hvA|I6cESW{SOoN#VL)dj%zML*3Owi&XpQ*=tvo zPoBZm6LP*y3p!_<@yCmR$9Xz1i$p{57vTW<(o)$Jbx|eb{Le?;s!}%+*jyJMBgcnl z8Lo#+eb=J6m!1@iFOfqKjYY#X0c555BgmBV5p!xtbQdCc>OrHDKHC_dUTm@SwqGa+r$0(E+0bzv&Bmc@+g{D#>K~59{ zmpo$K(y3Dg^NI*UGhsF|Kv@qvCOZ^T53!llgR}LSm38cve*%EIDhB0ElvoA%RRC^6 zGKpMf6nnR!#7zSSa5N_Ul_}Ww@&vs{#SM{?`b^+hSXGxBSRBhu{y1pHfsF?f-=8!O z8ZnKtkzdB9hgwt=6#sQ!&`Dl$WiJ6Y8U*Y?L0UGFIPxRs&iRdxCsxyagbhA3ol6-H zB54ppL}tZ{?V&5P#!ED zr6T9$?ZOG(!j)Q5psXifADl#<8B1a*l^(NEEn9rx#+4CT zvQLSnL?Ubw=smnsO(xFeycCm{m}O{L1B|18Pg)GG##3Rocm1SuzGX*6=j+QLCk(`5 zb3Y~skn}x0t%8z2Vm+2=J3Qe#marboh&|3qZ-JC(go65q1YY(Ipb4C(d=B%Gq@dV? z;8*tlqU6APt(&R?nex|U{r>geE23@!QAR0U@~v{LDQ6yMrh;0zq_9z&6!GDlENb`# z$I-r2svRKoP15I=fHoD)LLS>j62QZ}rxM3(xp&MDL(Nw~F+qz` zWH3f5{l{dZzQPMPDyzF!7-RL(LdGD}_6# z7MSIC*yZg!k9O-PLvb}rPss){5^T2g<3$m3Z#9zIIfIXM*byF#c{727IlEzU=)BW# z&PH(n?A+bVDAv62I*1iCIe$G3JDQ?2sg%1kg^ol=+5#}lNO7q3$`rTxy1#O|i720Z zIhP8+yRES*OpYfnTX~I7Op}kF$ z2x(^BH=G0D1}>%AQ;GOBsS{k4%Xbx9?hW;M<65Lgza*dl2BQ~;fOvEPN`azD$oN{l z(U!Tl19_a+es3H-3C#xb1{5H4@~tx=ph|c~7mbFNPJG6+)>a%s6_xu^TW+-xW7PA- z(M1{rJCjazb}-In`Kbe7sfG^JSwN3tjQuWEf%B7ievb!hX+;$#%^-Qw6>iM996?(u zd2mU&9x>;knOZDChm&!bO58~#meNQAJdlm(g-oPN?x)O5)_klhKkzOTw|+&acsFij zP>jRRok{O&7*Q%zHP9x|@XZ`a%BuUy@r%u40|_bsx}khxG06qIW=>EeTmZB`(I1AY z7|F|zE~ol>)5e?#ed8GQ{|>sTo$1OLeO@>kik6D48na_Zny`b=`>=_%qLa9&+?f6k z082o$zx{p;f@fAs_04C$)e< z9qQm4gGMXiy0UTuJ}&Df0eWPTL;UF5}1kyr~Ij6j6sWk zZrpS_lJQU-!?a=mP&0j4T6heSLC>DTJ#FzlR9`6;is^`NSi4VQD&-%=!V*RbJlaj~ zWk((`ytPI4zL3&0t^~5deXjn09~o|+rdUt($iR^K63^`OSIN$-N5G_JbKVpkl4jzl zSGBoys{UPF<=s6(9W3niYjCpq+SQLO33t}ipHn|^w0Z5D!Unli=kUr&z-@m!^Jg6% zhm$DMoIz}urVG%MS2N2Eqnnst${zPm>bE3!6O>#Q$eJQbV9Df58`UIx*uHck_mZ6W zom|_sym7+$!%I9m+|m(S6o}9A2{KYK9j6^GH0A06NWgWKZMMpN!oE4LGG`9OeU~I{ zSc9V&izop7lMrj!NbacuL_vSYPfcW!<>~udnoJw+(+cvW_-L5#K4IvA4IwNx%HhAK z5CO~){HWyxh^lMNdCHm2m~fbnNR5%*Q)VT2S?QRBc?P1QfTkCS3X_5MLvbubgedc* zk!axsztl!Ci#~**z~|kxj!z&Q&dyN0Ex~{3nP{J?vOSRDnxhh(HQ%d^A8p3>)37L$ znp9BPo$yo1_N@Qmij)|Rm5$3_{`&PbNikznJ^5*C;pD&kFmR-_^IR!EMkZ*@ThGP1d*`NlU3;bBqzRe zDO%izuUrGI^S9TgzpDqgI@LVJxRkF62TUo&%;F^Ny}x&&PB;ou0aZj>p+LCDSfRqD z=JD2%s8Fp>Nj#nV$BStr{3$CH!0ux4kxCul=mEHhbM!F>(=NIBmo`kN9ZX8ZXIV_^ z2!@2%H+;-cuEF5&lM}kEx@CZ)?&eRc@&cicR4&TUWTq~dL#MwYGH1KnwMR>zi2CSG z2va(+M>Q0x!g_={a(ItUV)#`+$O3{pyuV@jqz7%Khx#ZfxG9v@AxwmTMkhpA0jDH% zJ`wcTS84LMTPG>Ga-lT1rrS-Y4qvvB3Y2|ZVYSJ_mjj@1Sag{tkVFe^mi>0z_5r;B}g>WU-t(gD0~;Ya$h7V)K^tU)Z?XxU1fxVK@G#0lr6S) z$Cx=6v{!9w?o%~PZli9qdV_GZV?`2=fnbBMrPM|p94yX;zhD6xq#qV}Cka@DuF1G5q() z^N++9AchLw)^dJ7lf-;^qQ^y!9kfxOFZFVK>B?A4!_G3~Q3@}nNM|c-7 zzO7KyM z#E>1C;z4E^I;C0wP5lfi^`c%t_^Y7E^o;eRs&0&;MFBMo!j^qD;VvSvF(&blroyMF74&fCWjUeK$&0pK!9?Bs*{%5~W#YYM-?6`?E2? zo2|YU9*&%s^1uw7SZoiU45yXl3F$V(kZl=Z%3M2d)ZU3QLYBd?~P32EigR3|}>#@1w#jj%Wzv--da4Dp44I*5SDcEP!(!Bcwh zQ4hj>_(y4O+B}<;8|VlN@I8fuau)_Pdf$p{9Xa^Dr5(h`yLayKX)plAa6?p*Nushe zo?z*gA;Oa$1J#vz(|cSH7;SvT`0G!CdJfno3QOhSZT;%sTp%W_+u(%7smj1ljmel}+Uy<_>H>+%OwBYqn^^wLCUiaMt zA%9Nt#)R&|3!A}~x@~v8hnl1O=zrrOhgk>0f#C{3PFe;(Lb;3OF2RQdj;MZ1bTvYb zT`v5c5t(M~)DAf0UQ3>#=`Gw0RjB~Sx6c++a@7lCEHuCq^_~eP!KYg)fn2x>Fb+y1 z2AT%}G+o$K0Z?>!qZPVfPOlq_6oEYLkDM(;u;V@l<aurG?ZAnZ zSb~yygntNo=_b5m7-Z-qMOD8=q&tth$I}|Luw&WoQEhMBCe>+r3?f!M;ar2&EZ=<02{6) zYrjnf)&!VJ7PMV28FCSo)@4vL1irARRG3N*0Iz4^dQP~gq;jP% zfOSa-``iWSN!N8jL*XVqS;8LT6-iaN^zg#30Aj-;dlx;(*ldk`rRV|H*%M|w&k~2% z(<8Ic?nBdy*ZHS2@SEahn^Sjx3;aM!P7j;F^k`mLW^h!&cC4|_W`CpF+v`c zn?Ce%mrJEugXuo7z#RO#hnrYK%=`ZC8;-bEqDq4Y-74+!cD>Bo-6CFs6&PY^{~TTb z)2@KAZdk)|#5JLGSbBfR%whFF#AU<-9=A45Su>+py%>s$Nq2K>)iuz}Yaga(cD@X0 zbLWvR^`11f%RP+%)D0oVSf%A~;5sy|_V~^ruRMBD|syj0~ElW>mCN6Urzi-arb5 zsQ!=gN{IHr`^SUW>J+M#@r>!c0f#aLRMfD>=#^FU)7yX7h&Ud%bTF>{rR{KwF%RBG z6l2#xK&)_LGC!0?Ukk$fs_}p-qwNxnOs&Dy8r7@RsEaw>l!$aj{YLP0PT&{(nZY$+ z2Znidsl3kzY1hiZNA|N@RceSTTW>2j`}nPa#g8pD{>W{E_4R+|cDNmPn?M}E7`5$S z>is97?w95rw_yA5|h>ZeL$m#(i z77g->%DScLZ8(aaP`Ia)ErMy)0%;uI=LvIV+o6wttG)THfwF`TFK7rnAdGXZU$Pkr zn3l%PRzP7ICI3HzxC6k99NVr)fm+^Xm1!hzr0XgHf{9>w78Vglitq6n^k+t*JG)f` zGfaGE-GHDu|8ikJpFt|poaRIYcp-zoD2PPLRtZsHmdu4nsl@EFm*hlo9_SAaFW{~8 z#_~g+8eemi2ZagYX8Aoe<@y$B*;x5_jJ=dQcx)7t@4;Uw<=JSP-Bh=sCyohCPb;y7)w1UBvuxpz1wDj0BWtz$oN zTlrn&)+1+^h)B5jXyC|jfybK1oD_dFRq|AN`he=0-$Li7v#|$A}l#alFMOD2i)IA%Fy}M=kk2jlWpK8H&Gr2?V3QHcdgw zikWqq9h&mp&vF5p!fLeS7Uq<~yaPdN!h;0n+(tIhxffat&NG^*^WK9>qkcd{UiU?Z zTuiAs^=j^5zHlsg%?{bd+Re-DsG=1qrJ8VjADTH?W0nZ8p_*^#y^5(ImhhZWY#Vh z`hb6J~tAPgUX}S{LMRgaHm@IqLy5rUTc3LnGv@KTm zIH<5*V)w@ZHX$a5MU-C$v&W5U(eo8ZmGL-(h8pLy3S!h4|Kb~|)_Q1dGawEmaJI}Cj`REW^7Gk)HRuI*$DVtfR=wkI>}k3=OQ5bx2)&=WDE(Z@co3?MSu$1UHo=wVrN639K0nq$piwqTvme0LugmGpFkH%h_0$*FJmUn(GXC8K<3BiDUOi-(;6> zRMS`jw|kNq&1Xf0TWCI#6?bJViZXJCIE5rN)D~TrVeTZ`o#Zyr1*~(Ap~pBR^Lzxt z(2jT2AjY}-Kuv1Ego#e)-sLP*?hcV=eS_;^nOFfC6$M`SFum>9z#IwBsB}gK%2E93 z0jy~$wL~>z|MFK6sJv=~P~u{L8QPW+>eIAB%fuLv%o=4IAR2+oi(6R;NozA zwjup2d3nzEk8kPHoWUF*Kd8qnco68gOf!W9q5Bc_6o#&^ig#R}|# z>;+%Y48S6T?n-Y!<6fcrL2|ge$pWBXVe=K`xRgT;WNcD-n{tJVB~yGurOal$_2kSd zFf^E^Vfu^1{>7R&G!6$G4&H2h!8cb)=#~a+d~FK^jt@cEytTcdHg4M6l&x3S*3J5B z>RT2sL*2)E7Cw+0bave2LdCl2PzcU(;6H= zJ3J60uZKhK6)~eRvD%_)KmmlnJ?Vc*Im8+8%Bgr)!_&^oO;Yz+y()7YU~2Y@gSL;} z8K;a|-Ol&ESVP5UZ_T8}=#_gKnKP(1sV*2O!pmujQAyt!tzvv#h~S~2J~xN7QL^FYwAQQb5=z_o0HFP2!+ zFslbumf^r3mN{=>=-SX@2XZFz{v7%WKUyODYDgIM0E$UlACgS9`|*3eD=(_lsNoVt zWH4O)u9<4+(EabLFr@N`H<)j_6o97|HsmxQv8+CAs)i$*owYm*6VIkwi@$=w)Q($> z{5{v8m1r2AfdkiHS`5rXC$xXUUc=`&@i*Icqj3Dl+vNe34Oh>O7k<92_hHadd`VYm zqg=5v=>lxA)pZw*FJRiJGJe18v-jxUX4?cz_ntl@T$9-jmF_iTbtduHj0t;G8sX>@ z?qLQ!>k2#9YrNknRx17N-o0JJDKdb#o1ml_FR96L-8#t$<5$Jpbx^>f^7n-vi=qju z8HbWy8(Hk~+lD`W-P`_t>;a4`VCt{;Uk~sZei$-u_^zi8H&WxEy=Qn@f3ybjQKg%= zHiC*cc+180AELiV8*NO9u#b|XfjROM2?hwq1Hv&AAeus<@#g33OvW`En07r7wn=lM z*t*cNs$*Y{0ibJR$n3lyFO4-&Vf^UD`~ppFzcNqjSG6$-lLb`~c7 z{rezi8{ffw?=Am_4@z*d{_R5_ssuGqS&!GoQr17vu8b zVv!U3jgP#h@bTfzIDh*qrq*2=T&>bht%jstbdz14dfg1M2Tb?1hECA2%4b6dwB5e( z_Nit2z>XRIDG*65Ly~@!-4PENTO;FZfODB*#2XC&-iBH+Z3F% zNd;yYcid*F2&vjyEuuYH7W#xafhb+`bwN`t`1Ja_7RgH+ zA5z!I=%-C;=K`S<44sYizi?5`u)qa|Ba|EhSH=B5`TG4GJ=j>DYxZaGOJRT>G93*@ z7yI%0lSYn`Smul#PkvRzjT`^O4v+O##jg$?pQkaJmFrcmb1iw}xdvCS>IuT5*cE6D z9TfkJo5AX z6{QpN>7N!&i{lFNxNb598$?-HeJEO#T6#2$!(pD(4+o*)m!oUg;v;cp^@ONV zWhnigsMUk5YkNsfoIBjOy6W6dNMjMKGP%6~5EXS8rwzMnjUG7kOLCaDGJzqGnBcWZ zvys>gX-@Txkqi*^kZrt+>SUBE`PuKr(Rt}Jam*q@28G7`;GcrrJ&0m5Pu&B|vRolO zIYAHo4dC?`T|Ic?wNZkk`If`i3kV(>1%frv3D?%T?D0$mXGsJMfmA>lksxYpGRRsU z6mgYL=Ex+cf(7BNcf0JOJzV8KE`3avjsqg#(qR81(6*_h(&9FRd z`rO^N3d{jtKnr<~4yz@G5V9K*h)v5)UDD+>mp=rxx6I%GXwO;O^@ZOQjb|PoMgx0A z1oeu?%zX<`MOxxbPbUsw;c{}w7=qe$d8iHhFQMb`I#ZeHnNQ_G4;sYbijxlpLPHTm z!s}O#1NHq^aK#Wdo1jm;D#ArC^wOO0EFil|Suq8@GGA~}vF6xAj)j9`~+(KOW$QR6h@XsKV++Xq|J~U+vHpu z7~=)hO5(_MhoPSPMN%0soC9tL+a&i~Dpgv-Vr;~9YDX#;%R;tA#J9*Ubxz8FQNM2O zDeR|ZO0)V>MuDNWl$!#U_gHM*-eA3VD<9}pbWb<<@=R5&c6-(iGgq3>93Dti@Ttj)oI_tN8{U4BX1z&gp2G4E$$jD_` zcxvQ;ZY;Oq{Ue=d2-VKp) z|9DVPH$S(Q=5-LHL9BMes0B3oo&K%dgv7`!n0GdTRYZ=##4noxn=T19j$-V}e-F(Fh!wvwQ zBfQHY3vE5AO?A*Kx9GsMgAo*X!^RHWXb`1l&RiH#RqV>ONxzQ7damC9DyDYl<~n=0 zs2A3A#vOg}j%tm!9(5yi0B`OkMXx_+%5)dt-Hbt+$EbSWoIloj}N@K|&CN)rWe z)n0P{J0=B?(D$f`euw3~9HRCOdUnlGK!_GzDR` z`Bufp_$IlZ88hMD-$O??{Y=r3Ga=b*2BAmfQ>Wz-3yO2n*5^Kx}))8zZJ9I;-S>RFpM3 zgGeccXRxx6(jp921Kiodt`x0^GPv$O^$d){k`$SYOpUiT`y0y8hiKQ^>Z%YKWKg~a za#ap;qH|aEuT#*${?3)To#xzr)0EjSeCFJ=iLBOf?yAzaf6-JOjp#x8 zA9{4-Bb9Qen@)?6&+juCZcn9DQaosVK8%z1o4XBOV0@rDJ0#qpa*w-3s@iOge4r*- zA!bvCts$x%gg&m%I8!Bv?^FP6IOJx+mi^kH@eNLaTV2sq&>vB1Z%ULu8`nHt{Qbe< zwdeZ1j{dPsmYr*%<-+!~fc##R0Gooqz$)x2g4dYKiIoGTjzp6spwmDE9YI5ZmQwvX zqD?KRMFq_fUe=%o;mwBLQ@`^AE>8bm7w8-gZg9PEx|^sSL$oG5C<>4G3XAw%bW%Hy z0tHi_5R|!DUXUghA8!5r-XPbxCDDQ938;Lxx~KauS5ohS)f{YD>LNA z+<#Kx_lBF^bhBC4cdb*|N z>=sj0c|J;pBA5KXqen2oPTJtaKx;ke9R}b*BGFnWG*6qb;)f?|7>u(ef#IL*mSCI( zm{hr6nCYJY@m3Xx*u+62BjpRHP)$o;v$!@DF1CQsl)3a{tk0e9DmyRMJK4dV#4r6( zB`@6cWxG@CqjAd68ie61w#$7#KdLA*3dr2$+7z=*G}EhT8`mX(bC0)NyjVkX>7f`X zFl|FXnntX7>4RIgeb?P(@?x$g!d-|9m=agGC|#NYuYVCY)5tlOUk+t3RrFgoCBOje zkp}VlZV_8yz2g^DtsR;14{X``>l1uaUe%X<5N0`7gbFYw5od25pKjpKUymuYn@*}` z!^Vpm7@|g!>!sYdwn+nFDq-6+aXMYP{Gw8pE?qPXak~;p|v$_Er z*!euw&0=gatX$%Q@|N1>ucqvRP0rZ*2G;nzpR5HSlq*K%k>|3lEfN^mfF#nvx1*f= zHg9is&)FDJV%##?q%3lFm1ps7+Ki)T4A()x)eRqYOPEqg%qQDWvlge7A#8NNC;b@{-~zMTX5E+HMNH`Lke3{_e z=YGqVX~I0Qq);DKZ8=FumduU?Bb-(fO0^Z+5=X`kGVWLz7YB<(H*j!)$5ceM7DUYm z)_9Jjt0&sYU;fCWM%|`nwsB#HC;EsxcuSJdUj!*iiLUL$PqgsqCV&s9ptr>PFMCl* zsRI{taG&P@p5?-}DM@PApU?H|Cr^JrgY`N91_(%(+1mxxCr<#LYJtP{w$}Vmd}tRP zI5X!@O8@mn15PZ+VdjH!c&u>_gkc4)0-FlqlJscekb-<7M*UppCZW6ScA`a zpGRRXEJbA4$h!AgUh`CCpXaT(LjC( zA69s6f~`7@_6ZYLkcWxQ{ghrge(>H^Y>3Xa0=E}|x%dCzGVAfh4AHa|Dpi1JRZJC% zF`D%UZ~SUFbs>yQomwTu$E}gbEIEw2uoe!Ee2U~nD0uAt`{YJ;{GIKwuC8HRYvThXHr z)&1u_q<2UtovPp6dC(xCM1}s~_VoOa!CiV$0_(Qv%Ejd5_&3GThbk)s&)a)(aclRe zhbk&M`)l`LkZ@rgBL7vzwk9=TPd4;)pbkKQfw=ZZaKw5EN#%Mx)ruE$!_LImy-qHq zZ2S&yh{RLg9Q^wvDQx*wP$~sc652ydZUsJL{IY_eaD`0ZOwGB|+Pvdh@YH5)sY6!& zLA%YHrv*DMtxc|ToOW!Dtb(`w<41ze{|(u9Z~5lUd&?pFzO)_*S{(CShe$GDAkgjn zzAy~lz}=jv+7{PB5BL(_Pc?!qST0w4zunIc2rytH{NNZGE5;!}fPnxh57wgE706v7 zA9l#S+t&EYxp0H{-(ZiZ&|ay6eJ+)HEt#2bH>T7;M)VB?4E-#Q|z`aJ+ zQoGo9!e5AsSU5IlO-TC8)WVCgJt}YWh!_%LS)mCI#IRZ5vWuII0Rno10^fJXz4yzTnxIKLYWLw__VxpL ziy!^K9#Jl^PAA*1zD>1f{k|n|(k8o0Bn&GGC!!cDR&%Ip!ZwiZ7U5CY>kT*q<@))V za{IS$EA08dZ;f8_tR6RKIfSNBN@w=@z3TkJz3vCz9Fr!_ z+JhqzP$JsK1t4y^5RVn>n;Z9cO2_;<={=Pb4W>82p`IANOemlV+g=p7+v+!P)B6M4 zU&dmrNbRxvPxQQIS^HBB->xOwv)*b8er%K3CFbWdgGjj&3tQpCMa7@1BW^CnRhXNf z8(=#giv?|0`-Ht(_GfZY?nYG9MlKd%H}>{W)Kg#5Eud!=lbvw5*!g<@!#I`0QVk+4 zaawEBGbst^`eZYpbcN$z|7~gdr)#XdP z6^(U#F%x;6fO4LHy29b@YK6TEYHd9=QyIUMgBNbWmooHas!dO4sbXZMB@A>1g78Ah zumB`FU4T_%`(HowCktD3W)YTkXmT$Sutm{wiH1RyUdy64Cq4A$yW> zRJeWbbjhpQ_OYG8V*m8gbfK@(4d>cMQvyh{3$_VOU+Tavr-+}rqf0F7=s0kEwL^$t$c0EWXHyy*u&@&8HF0!Ss<0;rRfuTpjV8o_kvg1a zEVDp$6_$pzSpDN(EA?$zK(Wjsw66JQ;1_*lPiwCVvhd+65kWMaY?zeV7^VOZ(2YhC zHWp32JgAi+P?8`t1(lUk?5*}=#3*uMIs8{apu^Mz` zp9&0|0+a$R!nz?Q&DQK<*Ain|#QCz5t&1EiR3e(hhn32#_eXkA=!bKq(9b9Y_RiBGZLf z2S&a!s$pu|GXO}R5R#qk^+Bn!u>hNBg_n^l5hbby$}Q_Ljkqt84+i-}M4KF8Fx~7i zjAM~|Th&EA{dZy#ZnPe;+2Zy{U7YldhK|`VuV>&n$XAJrSlS@nxY$mTdhih!UU~m? zxKom(Zq$ujVNXX?q(@9aZm$XQG0yI|U3CrW&lb z75$>PPMHe_Fg}W0pBJYg!Kx(1xoaHXTBK=-KjG{;VoeV2dS;W5@Z3Fed|wn| z`|8tNZ{zo_a`|gH2mE91)L4^Mn*-f*9gA48AzeAzjsz@&S2|4cD_9)$j)>^@a9?E{ zlCrAp?hmwdzZDch8j{nj3aGl-wG!TJZ%sOV#iaynNxV8?I#kRwzQSN*3?oGc4h)p} z4e2LkpRwjURX)keO4~|G`kJ1WwB?wztPo;~pM@RR-R6EH2a1Xg2&Pm&3@sH97zu%g z@USf8wBg?2XU{`RaRS2%R4PLW5=PE z(FgXT!8uHse-=45E1Wg#59XA?`^ERN+hM5z_^Ks%_P+;QwhhR9uC57$a!9YN*dsUN zE0D)?sz^(m&@pc;E{?=xOy-V2AU+huB94qt5>dg*sQayqdWM@zGD0q*3=e@0B1eRW z`}l?jMf|Vij@o%O)iY{LOH37~gC0E(Iz3hqbb1h-4vOZ5ZxlbFF+8mKcw$(C@QKHo z!=QnI3jsE3BqT;)j(_3ZpP=XuIT|)UnuS z?9xngJB~#j&#Ukv?&4(?ALVEEHi)q$f{(sRwWU5|t_fI6;gL{!%)u z`#if)ktfjAK_gt4c;>@&LVTbjkkGckRMm`1h=o1PHjzyHdAN8k@F6TWB1aB%8lai| zvyc7Oumyf6_+9D}%3VU>cTQkNOM_zN)Ps zdI>hGyk(8Ym8=Tn86exKh`1$H_EkQ$<;#=6=38QJ+D5K#QuL)d!sA>t64-mdh9H)~ zhY$p>uqdZ!i9nK#;gw~|&4`8|YGYoB;_wn0CGo{)r@Ajea_LGqpXP)SlmqtH1`R&Y z00Wvlix$?-Mo!r%tw{W`KV%+@u#=yigKt77bcW7+ajU=r0wR7mWNS5&mbx71{{%W= ze(Z4Tb?nBKZ~LZ7Qn&U~S`$!y?gyXnDe8NJ14g?MWoRpu@;Y^7^-<_qI{Abf%X z8SaAu2m9fXY_*{an*-6SUiZgBvab&zO2@o4;z#j!<{6lhO^I{%Iury?ll49x_FD8% zwz=58^3D!I#-Clr*!&*{4t-2&PIS0VXXa_0w&+TS_mJwnv|Fx3 zrf@Ofw0=Gn23NBpX483ZBO;tSJE}DU5^7E#X{RCv(>dXwYKTl(&w^o*ZaL=$auowo zblpySEddb_5COC}8$j4VxLlUL{h2~dt=)`@8#}9>mzP+;s-alEeNXA2q%69PY$%#l z;{U9~`4XI74M9Etdg~^8grpIJ_#czE{Px4{?==TqF2*m)&R1z?9h{WLuK==e0HUrW? z`YCr`T*3|JP47Zy!xx~+N3=niWM!_U$cyJ25?gjsHE6%EaS3-3^{~Hstr&rFBbn2+ z;BEidks$I%9K1MQbxvotMq19@)}|eof~PibmfGcIA9UEPJuTRAZEbd)<+R0@F5@A+ zG{<^J*&x+};V3orAl}c$Ff}w3b-MH(wv5oP4p-~kZ$)Y`>rt8nS7t~?tszGM3jGvU zX_DZ(j)sII3*4J%$kts%+$O*bG{ya@$xnEP2{}d2;6;&mlB|~g;plf*hkpN;Z+(j) z3;_~jMQaXsJ+=)#&zeMyNi$+1;A<}$VU8c%tN@dV_ePH}#z}L7eWSMag{7U(6qmhN zzR!?id(hm>_8>!Q20KQ(#@qu`$ET*{XO*hzU<5q25P4!V|6cKC0p-L)mh4E* z^wQg$MQYT+?ZQ}I2*rS$`%~Cc#`nc+`(e)|Tmpc8v43ed^#53#zJ_>-|>Il?u!bMh0Q$#jSRH9iMlV!vK#LDcXV@0VycUhXYd&=t+ zEhe6|8dB36dfJ;Pl-ngudg8(-oDtVGPv&{?5)7Dvw7KMl*cgez=x<2LBIDM9>p&{J z9E?s1x~MRu%4`=^kOzAGS8Jd-CU(1Q+|oIJ06K58{kio%5_Y0UOIv(YcFJo*TJ9c#Lokq7tXNe5gJTeLQYTk*WK; zM_~Gr=)W$-mNe%hxLh#UCX9}X`1WIT|AuClW@BC_p{CgWdu%9@l*Y4?ioREZ32%Fe z%Nzo(A!B~yvhHJo@vrtmO*U>K55Qed(Rn*%)p{+(@+{Jzzq3JXduF#qlZ3^@uj zVxw`8nmk%=X_G!;NgRb#5G4h>g&l~-EUm^|$HHK`9uo}Jry9a^TC}vA^+L`xg1t<1 zM>H5a*;D^Kt{m@aR}n9_x*j;iO5#)SG04Hv$)GJRodTL%Wu#>*o%MUfc5bu?voYQ@ zj}sB8i0}qy*{DZ2<_hBVMCWKHS;S_DtT#Q!gm;)zsLLm#GS*#Qbo_p*~78k_>0uXfvTZ-GtzS&YU(Knzdf-77yRTr(UOhazpy24Tzv-)x-S(xKD%qpL1P4($*qDdwVpb6r2We zqr!#v#9sh`i-5qjLo`)xe}<(-r&D;ysU81A&no!S607fXE>~T?Gzjv15L%x5%p#(B zppGIQqV}niBk7o=!0biI1eyTSDzGUlJ@(b*d|*U}%T0myIh6%u{I`%%dY1DMQG4=E zA8vk_ugJtrr}^Fse|Mg`LBhVs3*p+UFlmjZdw2=MkERI^yHuY(dtnqk`Tu@1`b{ZhcDby<6_{d(+fu+mK89Ly_{qq{R*2-2CT8-X{YppAK)y)SRX3Xr}v$ zKf4|=O`v@H@0MSKGr>M1FXU@ws=(@v_EONn011#eKSTfFLG{-BonPNk$1O#7=GS*@ zp$Rh?FpmC^xuj9&9Smhz>^j;Sx3lcRH6O&Bk^>z=A7kRAeGMysA$ zR(U|9Iw{?+pEQQX+|}AiW{s+(Fu$s#y{*054n>t;si7~!P)?5Qseg9-f>FT0zM&$t zjzEq5E0D|)V2Un;3qRge+?&>*kcd;A*(;5|_=I~P^oHW!d*gySsJv*6eS)}ksyE=! zvy?*9x*H{apwTP@m@xv(80?#HkIt>8tnAeHZ5!ywz5r+Pl6G;z9rn73{YZKm347)3 zQ4c!D5(Ysh!ajtXVvWi?{+gVolBDkc4ov8<&Oh)Ow)lkB(b#(WF-!BY$5lLLdNS0UAY0LcPP->#Pnvrfc7uw zKjo|$;XT9&Oe$tvZ2SL;{UQBJ(1f7x{tw~A&fcTp+3%sJsOE~4+T^l9rl+l&v_f$y z3g!caw||(L({p07(k_fKuXr6i9U}K#C=C>{&>WXc&97bL6^yU^iP`qf=sEL%5lBZ+ z)k6R3mNWbB4a`Gh;?KWhT2bpl&sA@v^h@-4!Iv9)RoyB_nGWi0Ree&QikyBzh#^8i zvR8?@f(=_N_#kVJe*BXo-FVXK>G`xA?bF=kw?Mj!fOHpvAQ;(}j~4}#hEweAM^gfQ z@3c~v4dX5D?oa)=(NE2M)EZ%6+L5noB^op~@3%ZOpL6?QVb2b*e$VkwxNAI`KWw>`izgw zHELeoD^dSD;!j0=kG?7(8+8@=IBaK&PZZP3<6`^SY{8ygT>1P;M8W?(z2(@OZEsB9 z$i$Vi_V(oONrs!?E8RV|$l#~$67TA(4qs>(9DQNGciW4Co~pNnyz+ZBPe&NfB{k&# z5{-OX@>Dc3|5rn-*5d-Q7Z1DRRQh6bQQUJjuSHPe$<}A{Yl=)ri#&^nQ5HF|j{g7q zy%Pl1!P8&@MaOkb+YMPhJ3sLi z%Q)w1A3XLLD=`u%XWM<#yqRN_6Ia?paOtBTJ=X8kWU0rl0k!x16{=kJR&+elOAqtA z+5e-%*-j)P$w}tNht=5m^lO5QA3{U~>P^6|n@N#0aib}SMVWXM$%%&j5$h};WAFZY zSf!SJHcrd0(3U%LL8-K$RXgLX+Qct1Ayd+07EX!=WkgyVoiS0t850|OkCEOVq=Kh~#O z9dxd^w{|VHb?0(}KOTJQWqr7j2wEn`$`eJO#zCdCFj&Z6V@fLi)LF#_Kh+>{?*N*s^ zNmdc-%|?6}>|p9Tx81X(|H?#&oywOS%tDM?7v;qhOl=&3jeY!SVL_g_-z%uQl`7r7 zwQy`BYJhnk`~BU)1HBcHh%Ul_$(&>-;1Nl zPm_~+ZU_BxdTaj#Vm+F(#u9R>WiKO!cLX<)a^gtm2#~!fhyvSicbTgFHkU%P)1H#O zHp}igtc{T3f$Xgu2B&QAuBE42PPe*~M_>QPv{KrQcoEb#w4g8;_FkQ^VXh`dRoe3X_I%g@gd!kt3Fq($}C}`D&X6zw52BTm{ zGBd%zi?=H;fI>7>5t83`No2p~A=Q1_2nc_}eeFo^XI1WSEh2{n@9~V-Mo||~9Zz(L zZBBi(+#Tu>7GCbL+=V1VS`R|z$UM|2HN=Li<=BZLBt`?h75F^O?%jxTw(dP;VM^LT z2~XVlWF)Rxt6A2J&Jb4OEQQNB6@={)pYzCCPGNS_(21B$3_#gpK1w~Md&uRc-+JwI>_2+BhDKsQY{?5fR` z6Z-L`do}<8@e@iiY209Ie;oPu+9tu)dADsB4eJ z3)FunH$FBCTl)XmrD=KGQQGr&UK!n7ZQ1H?C0=CeViz8y?0Q!}1}7P=Ph_&n?!#K8 zy}+%``1hpTIqq1(sSDVZj!Nduju{%uvM_T9P_2}!knO>#E;nWc>l?FdI;u_>JB44jo zR!gvx-1J|+neMJVXh*8+-FB@F8z-cP-JRxeqM2Uad;9k#;{Y6mg0k^3lfWK?P|xr} zH6|NVu+{mv`F;JFZp7Ud`*5BZo4aNgdMVU|)e%Xgiw6S;8l283;O@Lnk8qIO!Thr` zVFh&}9{uHK6T)h4aEm8WpV_33-#)vFyl^?hgNufwV@{A&FfmFDry-ZU*KehGX&ko- zmG=B_*x$wN(rc+2J{EbSk7z*kO!vqOo7DH*t1w>=34{?gk%yO^(RICTT_2L7>hmYq z9=iS@c)==IPgI^CUg@h9xjZpk{>vw0ku6P@@A|&^mn}!K^H}RvTCxuvI?`eckEEMT zru^0ryfBo@bo2^yHq_4uyrNtv7S*IAxQGoxj? zrQUCg`TdSr$vATheB(DyzC5d1;LCGPrj;DK$M5}Ix73&};A9+Josy2~??t=wYxuj= zJ1iPhI!@;73pnV00|mF}l{x)l7(&#(+s^iW`88xEGlCIx1#38AA}a<4)$h((!M@Qs z+pYl`glVKD7NBX#v$a+PZ@#AT-3YVuh}+d_0;Ze|ghjj8Jk^}#DM1y0${HERSP$r$ zb{H5&wkPUp_!T<^#aUGQK=ty}41~z!F?o5M^s!VDT*t7D@P+b*ng*>Em!b2+@B8(z z_jU{(?xYp0e1d*5i+b=qBkWsZGY!Mh+JcbJ7S;#dl{}N8hIL`j9IQGrS(0|}&`@vO zCsQ3E)U!aL-|7p3fcFmC9NW}u78U4ruIsu_s1S=`auDUL7k7>{8y+{i>Ho7%)dAP!SmF3O7 zyW-39g6g;!Qmzt{go2f-w(TK!uJbgeN>5|wG7!(%!Lxp(=0ge!=z=X!NfgS{t`%$R1_(cjaKXIBbiG465~oFj*oIL3PdM1P*tblJe8A9P&b zJqZ?puVGx7vwpbE$$jIah1B1OUE#Z%wIRc;o>%3288*gM0;b^BA`ZTbH`tg;Oxc)7 zFo0XQ=>&s~iDaiP|D+i$4m5{LQu-DAu*AhI7Dk*y7LJ=Vm1;b4!krc=p}rTE ztzg~)9X15hcSArzp6t-~^r?uXKY(cHC3e3z|d_G-_K6Xn65G^g@&kwQaG&C}D$+qWW${s`T?b0>Ug$QIISt zL{?%z!o>4 zbZCbHuLl_q80?k?8SJ_r+**PHxpqyuU7}_f_^Aj&ThE#T3XCg z(!R_(VAq4-K-q7m_Hf||#a*8iA`zNP{^|H7Z`tVtN0OY{Q0z$&5!QsdC`%?Ih@%Tz zj~%~hCZV5;Y>0%7_=>q=I_IN8X!I6_t1P&U2CB!P<|xZ5JHG6QlFJJ-i&vI5edXQ7 zdd7_-O{Aft9vsZs>eMICD`e0hf*aKWCxorB-fSt|u1)d!e{7J&?T}NAWKc4rRljil zNr^_GbbY9;$Y9s8b0X51*FjEA4{Bpfty@~v0;QX_9gPkjB7S-^B;t{|kruW9es|bs zVS9DUzk#JzpWko8%Rb{$e%nhkIma*Td%f4(MRVYIZH`@*{1e#j%Q-%?G!nzRm)26p z9MZeSnvYm-oZk9e_BPz-ck5EB`eI(M!2XB9&`IqBg^K7|S+Y?`tQ(sXqN0FWXI!k{y zCaSzSz7!|_rwLA-DEsLU(-Ugte>}zO(XHTY)I%O4dQ7;$@qP5=eGEB;X!Z8luJLC! z*gM?8AQO)yDs-5@-kM8mb~&jpY%)ev&s;;>-so*n4$m8N8JY$GQ$l!7<~}FC3;}dj@uKeR z8y`R6=6jtv4#CvRh0f*|#W7~;wKI1!h1$<8xSIBQ)bq}L$VIu6-|NpZP2n357;&ze zMa)q}csX$R!!JaYJb9JH+Qa+i-9R3o0FgTiK2Lbm6eu+(?u8;su*w-8AI%lLgIz$} z!PqWwc}Ymeg))^-Rt85s?6B}-gme`(*}G>BOlhs+&&NBT>uP!*-5 zG(4uZ5>zuD10j+IgvdaHc)o?FYDvpBit;^5d$Ml^NA;_yRoB|zGgP#Tb}9L#{#J+V zbh|+b1Jvx57-h#QtiR5JCHiHEBIF6|?Y|wh4DY|!SG#{f2@gOU!QzA`%pHwetNckW z(F_`kZx#scUj)qrCM%AZ^1<)br zY5O{Uy1>AhsF}{z%+qeVup=^kKn>&xeo@m~2?kY!1;Gj$;}U*%a_0Exp0d+sCCU zxrjkSX=%kX=0*uY0&B)j_mI;DIM5`q|8>Bu%h!&R;t)&^b#P@Dg{gA3jv62KFhMa6 zLVC0V3doB9{j>x2^;-VZc0CjFlp98<4Zq)!+N>{sT@0gFLn;?FvYLYGm|gemYM;pJ zlXrbjK7aupw;fkT;9;xLG+9e)sf^#5w%Ut#j#b<;v2zS{CvTIpYr7nCqkzD}ppBpo z9^;+V0EU;hAA@R1yRP%{s2tNya*=#FlT&+_heKGj9jIK_`@<7_00c*#aqX^HiIrX9 zA#Wl-CL>E{K*VQPX|tJLWbJWfhmLy6@xTQxt2UpYy24;uIJ1_a`!CaMPNmmyZ4+%6itZZ5qZoQV~8AK>P2{wA%YteuB&dCGuDeHS_5yM-4sH_fmU~I8)L$(&1bOvlG%Zg z5iArIFJUzM2r-P>JO)b?o)s7s$zp`ZNq|5UBRaC6529kwBa#;}y(sMK2okiN5v`u) zK}71Abgd_#45TX^Lt`DdDFY@m15KfG^MBD_@RHHc7}BkcKGXT@Taj^gktb03=yRm% z5eXQs|Do=9=C7$}z>6h@4gL^Q99#thIdC8p(jmU6FrEZlKHlWB$R90io~K%#CkC#o zE7J8kV$=Em>NUUCgY_DpO*0EbT<5eD7tV=7+J<5J)} z%4LRiw$Uq;fZiuOHQ>$Ql=$-S=m8E`72-ukOH2q43fu=69px%=WZ?J-2_3dt0G0+E zunIx4FtY}uBhJH8C0+;Yzd30HEGWr~jB5y^Bg_JUFY@7~0}*Lb>55=KIOZjzTk26` z%L{Sz=Z{%>fxQ^pfyhB-3yG%r^5S*0exeddAU!BDZ zLL&lDOkuNyett!!k~#Zo8W_Bv9gp7D4qY*5$W5a)fA)_!#{}d;>M2A=>T>+aGRUzg zC{hLp)J*eTd3pib9uP9jqp&H>!U64?2mA_?ePkCh47^6J;$Zi@&Xy|*i46~le?UjR zQ-R%B*UL+43uhFacyucsI5i3LNBVo&S$hR~MR_`!GC_7j`Duj$TX__`abb33Igdn~xor^5e>Mc9uJAiIG-y$|$#7L47S^ zPxOv&wjGleVI1HPZHxjkyzx70%Iet`?6?xIbT5u?uHOzT0|x+bI*6E%erlvP@9XDh z3|vz}s(6u%EX@LXxGr5A=C=_SlE@jP*g4TZ8^r5}!7eT(qpBc2p(;NE1%&yr*%%=J zcCQ(yun*5UH3P)aPcKSo?4Qpi$-@aAh7GCD-`u|SOpQ?q;kLb!`?ac=xO^=2P4aUH zNQ#XRN-64^;?f6!hQcO_hGxm>DtsW7mXXe-d#5wKGTaiIlFe?VGrY5J$)K&WS4Nr{ zuwDNwuWO-~y62}Fz;*nuyaIp4|Fa(0h$9&<{$eoXr@&=$-51PX5Z;|}$5P*bfJ<@T7>i>?k?^M;P-X!5(SSfH?JYil!2RRjPsqdTVIIVWY610Jk(VKbnfS z(ji^#w2IQWgcb)cup|-_+YQx+JaHw$nRH9r)>3+-kUCN%r_~&B57<{v!=*>kNP1$$ z@uC}Q-MV0Ik^MK?<$rL3psN$AyE9xzmkZ{r#FQtGS~nVMte9~2OlNl!_(@M zxH3~~Lu2yW zxd(Gu?)f3Cduc?Y+T^Iff&f~l9WK$W(M?epS{bYo>aD6CoL1@tdQEF{vIJWb?fM7P z^;~TaCL?qcv`yRg>(A`hi)~BLF`_3P4?GqA=V^mpl4*K#Wjd4aeEv)m(1kU=9@9f1rj0$w^ivF~*l)Vzm^A0`9gm{C4Ir1L2Uq19X z>z&-`P}~KdPWO|r%O@CRqpoFikoruJbyiUJg)OI-OHeTEY_XBoeos(1cSic2wA?v@ zXMwGcXzl95j`};#pCRhE6ex8EJR68wzJ`t>%u-={w;g8+0RiYc{bnQ&cUqz3dX6gs zT~l(P^Ixn;4MB=@?l1bg1<&zwRm8}zks$yAv$YEjE*;4r8X&mLWrRnUW;fK|Y=D1i ztIWGN9t~P!1fID&-2E@1nD4eQK?DSI1O%-J6Xap|*CH=Bl#LSvCl0>qt^Kc^BGIW% zyYnNXVbUyQ`S%;)RsvsJ=G>}ZdJk_`?(IeOsmwcEE4?Y7eDWtD?|o-M9`|p(M~1WR zOsOx{KpoSQUJpm$*mVzr@cCbFhAaP+C!Bkv-bs=8ue~;O$~LZn$AhigkU#m!$KBX5 z6Lev~@=dUak`_-%-AGroQ55yF$jf;!E*dO z6U2**Q3eX87`y+l9EWB5e*)|3veb>2O9`xh+2XK^eID$u_qgotuDky?FTUO5j_ujeq&4?fbAREsxfC%%kqGD^QaZzr+!}B=mlt#aDe7>p z-OvA%5(1aihkDEU-9xI2^TTTTmzVUG^m~TY<`+iQ3@(cz;lu0A<(IlTt1n%fozEJt;FTiqq4&ibq^#)GEhcK{!y-DEwU{~^9zo) z3R`zS!~+}cyd@GxT2G|aqrs&=0bBd$v+c!KO?9c|Ll+Dgn1U0ctm4M@#6EHHmcd?-?R^?anfLd7mpg;sR<&_IAHJfcXI^luxK{4%Z{g0t#g-A}4@lJM_)ts2^)ya}LA-A}%Y>MEHEZZBj8{9K-Pyun`}ODTb!sige^*Abfz9wu z7t|9tX5u&Q1xJ|%UcB3TE8Qb=$SHa{J#36XuHAMG?2RdN`SWs#c-kIWuttU-AR0bx3RZhkG9bxWmUEmfYolC zD(Pu)L+#-|%oB*Snl*ixx#UdVh{qwyz$)#4$VZ5Bt3sH&^cRUE4j8sy4=?#U+u2Fr zsOu{fChG1g9JvHPkZ{Jc@%2E(?|-cw3GHxUr@T9)ctwFa5fBj6A_ZBV4yBX@@%LAa z@(y}In3&^Qpgp_PG@ZOG`zJl;j9o%@Gq2T-Dl!{02!ulC@DihBL(ZmDuDT1gOVx2U zkfLTd#&M|w$Ddjcmjt7MZ7|w^^&V~|hUM|Ah*#0!zQaf4AO-wL5C8piJdwZ6t8dGm z+UDD?`;4yzbvy>g!pW!54o$gF4+Kof1gIA3sT^@%NA!`iL1W)AjZhJ?_%N~HT+Erc zGv(?k(KHK#1a?+t6n^H|W7IC;Z_se2)5*I{vf7qj$EnZ-!K;9R#DKJb2ndM4M;}a1 zihRtNyVinav%WqZkXxS$zeoc??Nx~0m)^eQdFP~YW$sDr3Rw$tX)u2^IO_X>dhG+% z{tLn3_vKw?)~emE+{8Y0mD;R*Q2VCVRZ4CKRye?R<#XX?Q1pv*1XtnRW0?3}9&u%X z1Jh~q4O_4+oh(qVaVJCIXpqjyih4v);&lLmz=O8amp7$wW1$D-Z*#z_G_3=3aAcn8 z1cg^%`zNuWxJvJ z!SCjno7(br=q&;^5s(n!5fI3}J41pjO?|bV^HdugH4aZG$_I5*@CG9poN@j-KnjPi z;LocR4Y(I@R>OyApT@O{;44}hR-e>8J+QFipZJF7CK!X$5CT$cenoBmezwtC%k^eA zftyco?&m6wc&tsi;ovkJ*E-j+VJMpr!mYipjO}{;K;_!G$(IUE4N9+`(g>R!5yl#c zNkH<26uL29%5molQSmr#WIQ>{19>DD8-%Ajr`Nta&A7sEqoIR4Wf#Ybh~KG>rJ%5| zb?;6KK2QGDvg(avsC;4E&(q{?|Yg zr}^Z%c4h13sq?ED2(WepX|JZ0w2tUH!eSRetnO*MhxffTKeNA)${q1-6*lp?wdP~=0Y{a+iw zVsL-)+bm3zr4 z2&^>JKa3&DM*xPIubYX54mW=W!pEn{4 z@;^mJY~+`rvZ=rSCgYxX`QF6D0$T{DAJ7Ym>*@7O-9rKfqt9fml)?8Z@1VH2i0Njn zsU`oMaFyaOml*AmpYzdrThb#jQm~y9_UH)XAzQAyZ3@}Q{wh!r`Mbl{Zq*pV6L?so zFLm?DA>78HYd353pTD|qD0%D2;mc;An210zQ6c>v*Wr7SG7WW6H#qM+JtBVl2+Tb%c1xuB4T=!(o0r~vW>8iXy2{04$?I_B;)NwZVgY&xN&5UgXElf*kyCQT^V*E!#fS8=lpjX z7SmEWdJfzjPmkVq0#>4NB1&|5@uGufo>Wj1Ac6jQ{+SB;7fExoL z-yg>z!cYrcSH5Q9uLx|Z@%>xb>6A;0F}ZYI)^kbk?VVQs@lqPQxiYKxxNpcFyG+~r zucT@jTpyI@2t=>OoZV{AyVM>V#>)l#y1s*59b7z1Z>+x`x|DG6>G;HXb(Qq&)84lW>h5 zvJOey?+(2D6MM3aiLdi2-5}i>Tq+qVZ+OVr;uV}(m zHPQ01jZ3ih(@^{H@18a=*rrH~j!K?!+30wXHD5A_NxpLlsmN=M2;T(4D<)+4Rnd|4 z!P5?7-1kI2T!^DaeZ4qv?iR9y(c`Z;yxaX34@Pq_!5Z)eKU|LDk*_E1$PbWKUGdNL zn0>sG*{}^W{3ClvYK`cnXyl;rvEHI#PT2VJw%4eQ{7`78ynOlI1;vQ097Tpsz%m>m z5;$X>dpft@BF^rPI6Dm{G6EgVB3c*+Lh2K~>B<%k>0}C|34C&|8nseX`kQt3C+h?D zHQn=FozI;!1buW*C|E~W7vs9qUy!nw&!t)I=VJmc@m87w+gxiaTW6ZW6w_q7-2S;1 ze92~IgkTp-Pq^@ARjH|5RfKR4Q&)u0*DCnIkPB%&6v@pLUr~RReNnh?IV{ua{=J$JK5E;qP)^rD%f?l zr9}0`N;hw6(=l*nEA#is?A&y}ax6EG7v`Z!`&CxS6Qj_CK6ph9`3b`yXKy9%{WqR@ zFa=1D5qZoC_D0Zv%8N|+NUrk&Iz3nR|DVY6mx9kyg1!lDr-leVd{G9U>&ySgbs)Yg zO{e&d_kF^DD$QaL$CqZ|*FVwu3K~v=7P5|$THU=Zp-K7=gN^V5e**)-n)IKvY3{>n z8{g=W^MhhIBbBLrcL)uAR;8fQS#sYte+yPKV?fBs^{ zsoVp~>!8{|W$M2(kbey@Z~VIltHJVCvbz_f8t0;S*Nga5QyDy}Z$7sQ5X>Tm>_CRxrF4CAbkecaLUKzP`6kIb*tyFmnN9gaj3}YyW%?Iu_tA40`5RgG z|LN~NdA0H6$>R@~n#tJV6htC?Rp-t5Opf|kkRSEob6AcPa+|`YWHHq>WHDn8)*6W~ zo2vA_cy|K97z$GB=WSs$ApF42c0Yo;pI5{8g3ybH_Yb!fX@6YHGvbwX_w&|gYi;MN z$T_E~$Kod#;<@;wJJo;c;-qI6k|cjrxsG=`yF6B!*-KCJL28wA`nG)_f_-mkb6db!1*8lF83H1J>-1LA zHN~(&*{-uo`-ACgSRlyeworo(9cBu?b^$@0bR*{Iwznh9Tvh;k2}HkneQgD;T>J3a zI9S_(1+l+B!hHCJ@ffsk;M?e%CR55*2U|Ke$FPNnxu)Ua zbH~`^Sy!Khz<|9I_WUZ!Dy5m+6ISHV@pbRw>@~-ThY(2jY@`!`2nYzWowFJlu-Rkr zTF;hVBoe2?dis3@Vi6^~l<$0;3&Z*~!yuoBi6Z|HdCl6+&4n(cm_&j1podsW7$xkheBWD5EyA3k}f3jFvXT z2{@JSFg|Oa$NHGZzQd0O)l^r;*+D^Q6Sy5_UwMxda)Tf!LfaB&WXmluIej7Rh|2#l zdvc0JShq#XpiV~M-VIPUg_fLziz6UHIsnurqMe^bdm4}hN2XsYN)w<>^e1m_^YG+b zS`hu6apA5%SRFH)_s54Z6=vo@lO@tTlvr~%f@a;w&5kG`d^97pSJ`g*;6#qWwA5^# z>A_nM;xXP$_YMU~02P(O=rl4U|$yYyU3yQ8tK*XB-% zq~8_W=axpX;@#z0MK1KYHM9n%qXuUh4V27Qs!j>6R4r=8pxx%;m{Aa^p*bOB4ED^I zcp1bPiNmqx&8UtLzA8j;H{*`*72Y?KR^)&{jD855vDtkf?S)!e=Is}$KhTeTj2L#H zcFo7@KMlrFE2s$x4VRoz7*ZEq+T|8p+7*f{G2k{^+C4is#DUb{3nJfQ7uKKY+Ya|R zc!!M0f~$a^Vfug(;IC+*9(2M;Z8wg?S6?D^kZ(!q6idxjg?~xv!Y^xR4gB$JRE*?V zmpz^l0}Q+}v@wkk*Zw?LTAQ0|-1ClG$Sf}Wbb-8>f)dW& z`ZPbX|M|DM1A{L43U~D3JseNkJCs4k)>e5yE{{=|7tJ#MT}`ki)3;SGel~3YTf0RL zdkyxR3p2`618AHcs$A3b>4p5716|B^XYvv42X8M7L))wP zm7&)GRmV;(_eI6ff7{n%@85TaJTGcaPI9o-?}lPk1q`VwWjv=A%c$~oQ^jr(V;ReE z74B=lr6b(p$2CswP`XOcR`%3WE>x5}uF9vOe4U`9Na1$ufl+i$vx-1DyQtIib3U?k=av>VcMqn&C$+sD)-a z)#gBrYqvAGnd_3E)}LZ4XOB?Eep|K01eaWssdl@#n05!#o3s|x@~CFGp{06Y(y1$= z8-$z#D6i`6jKli)2YS!rPw#AyNP4?5&A>UgQ(t8!)-Kq6)LYk+f>3x-i2G=;U5iRX zn!a21L4(_8Vr-D;)#Fb+^zjet4l`A6ad*9#q~WJwI#Gai-DLtTp^49k*Z+!g-Z69@ zmny{F6NpY=%{z>P|2|UhF`lY(2o=}c-R(ewwkaDZzgHo;AOsp>$T^dPNDS0B8TGyL zvZMb2PL&CvhZ?=z-ki;cdc1V5th~H=zf!Oj-Amoa*Z&kYz-hWl?>F^th2f>?H%2HD z76sAZ-_8`ZXX=ZYx7jZ>W_^oDei@Gf_AbtOL=|sVQ_hX3kCQLFsw{_46bkg01G=tD zN7{#vitXZi(l4^LcOKBqInUPKen4a=-`#!XXglbndst4P&u1~|vcTX~D<>VfNR|$= zWyhwb#*z`4!9+Y}fo-|xk&BLMVEsntZWks7VLEPjf}!;N-Sj^?8#@AgZK| zZMtWnEtAJY3^F3erl-d9N^CPcQ*6PpX&srA7Vp_pS{#EIK>+~)K>-eRy)W_q^&f3q zjYT3>#XjlVWqzg{|D$MPnSXK14epp+`#yO_oViL}$W1I2@3!ksvUnIp1akAJd+2+8 zdiAiCNjb>PTD;}2`=b7^p{X)x51zc9llk(%OP-Q>?Eflk=qkJuFPolS&Shy+P>uixEEt8r(e7mTRX09KKxtYcO9jyG>z9fYEOj~ zC_;y)Q!5-ok!TP>=3tF~WRgq>i8$K+#AqXt;VM*dS`Vn)F^+z$S-MgTz8K-2R$Xo+ zgAF&)G^bVBO*bct&G`VuZPf9RPaR6=8LAl=4IgD?3GZo&`T(mV1FhV z&gTC1HhtVyQ24Ul+x# zm9S(>r(D5$?2huvG=d8=1Ec6Q{QXvW{`edDr3Y!e>bFhRXFmQ3EPl*68XtA4?FGsY zPUN9+39&B6ql3o-&#%lfc*{MIb7S=SDt=G|Wqc@t&V;a1Kv&^x84_F_CF78>i*1eg zB+*oh9(;y75!b&|-GhWD|Mb8R5{sgJTt zpg-d0$Amn{b8~}>SVr9rn+-LujV`88Zmz%{F`&2d+*wvZ4A(GS=aC{q@#AT>6>(u= zF8X{wlQ0UrEsw9G3`Lp<%xW#Z7;bz$oX7u$7gUutogLRP$6Fc(SZ&^W5f`6mMKP0% zf3>iD^L0)B32?^rK7I?CMi%VP3Rey*RGfyH`63R$2g=Pe+@>$(Dq8sWL>ubsDeUt& z^zH~DlS8W#dRezQj+mzYOB@^q_iJS2f#2zuP~0f5SALFay-A~4ZZ*dR8Z;`HmF)Dv zKFLVq#ybucx#Was-=k1;=N;pe382F-=(2t_NLJKuB;GKKi{u}Ya8dRlRcZK`n^Ox9 z#fCZ#nx7P&6LXNc`6l$)!k?SmPtQp$2Oi)Ov$ zM)H3!JRjkfj2Nm2UgHtkecdpZgQ$_@GxZVGW0OX6-|CMG^jiq?e3Eot-0g#p`PC8+ zyR;D!@kS_@{Ntx=Ek=P}f)EE+3j16VXl6+V9K@2VD8eCgQg2;JIhJXsUvg%Xlveq< zQ0tc-){nh{cx#d->h;2(@S{c zf3Dm4g8wM?xPSLuVqvS>@mS36EPZZXhjV(08c+izATN{>UmjX3(-0n57#^Bh5ncs` ztY3o%f>Lpht%11Uz{NQCEgH>zv!5DpJ$p3F>|O-LV!k}YDSJG`(G(AqFHD93K`iqF zd(0=Uq*1{j>O@<#&YR6tQj9NSezjDf?p>f@`|X5G_O=X1bY2`^1rR4Y?OsVEH(Z7c&fKI~Wqfi@ocW*m^gQ1Y2P6z8^?mF2cI zlt7M~uH#BThjS-Wyj)HOTHd8bn9o;*c@$13ANEID`)BIG5Chtj3@a0KyQhiFMgHt{=bavvM{#m>s0a)J{H+hmGafmTc__Po7vj|NZlSYEKq z$jhI}ws7LO#OQF;RS)>7rfl~!HMa6I5h?jAsL1#3H^n_sVQ4(8XJuyQrYNYxMrd7PbsYoPu*!xr|d z^7DGoz%lhaP8?K2MLDqzv5XcL0%2WLr;Z@XP!P&_2$MYi5!G2FfT6ithNQzr?u865 zl%8HRZGJai=nr%k^!efEyt^7q`%&Zl0mC46OwbEF`heh;J>f*Uw!Er7yND{HT3Puq zjTgS$Q1iF3an7J-QE9d!bEf(4Krt=+9 zR&ETo6C+U=Acr!b$&iTeAt%R2|)Y#+C^u?h$SF56q6)U%lW~ zR73TXsyL|9R%b93@F1^+6gv9A$E!b{B$}+j?Pn%w!%nFTipeVur^k6w6C4o|1k&k( zzz8}L6iO^^L^?ag(IBG($2YG++pMY*q}!_2_6^|;?KZCUmhe4lq?b}I&E&SYddbZj zPz+UB>42GdOOvYO=7fdN^W%0EM~F@>VE#~=qhb}de-?ITKZSZlCMAgS?4Q3kn3UTh z`LDUXO=M75>|uMyZUmh$G0m*P+g$@3bhC}kCIdLCaCc){q7VAv<_6RL3{Dh8_~0Mocn&M? z3ki&GHBudR$IaHyW{}dOSbb?k-KzAs_OQtPv891A#gW?ryj7F~(o0>z<(ue$65{lN z-A9HXl}2J;p`CeD*IlC#Pw()t1QRXC3XA+?W515%8 zD37hCa5=GeMm88Z$#r3JDl#2NL*?nJ$>*;<#v;BO(`6EY=Qlknh_4jrnXvYn*}5(7 z1fKDiT+IphH(=k|fd~k8t+t>Rbn>GlqJs76e-|2+xFwQYJC-C>w6+>+oFvo}@f!on zS_}9PBewG4WA1$*8P_J#5#K)Oe2J z-Uvf+3=#RwMc`F<4 z35|ys$mA+PD67bP;zn?yoG-*4cJ+toc3G`_KEek}Y#b9xe87h2gCh6ttx4Q|@655{ z+w5wgNwJ{Eokd*eFaNLYIMjvVM*kvkSS2PG=FgYrU?!~e;rBB7$J$wi^+w*7qX$bZ zFYF;+A9)4g%wAirmZajq(Tl;BHo7WT+%=t*&#Yef0jSA`;5~CF{R~e?yN+qwe!ZFf z`mt>Z+Pae3$u_R~+Ua0?MqNb?SAI;TgGnz*ApB2$gJXeUw?4sJ*`5wphT{4zfZIf|40A42*`*0o+R3NBuL$p1A!1$mXJ^?q52OYx`X!q zBsH)#O>8Y4>}cH{KBuO~4O7|Ckj?y_I;G3V)kDy&W8N74B$-aP0?KtABtw5*M$r}+ z`EXrL{iEHDrjz;4bnh|4F~JERW^970hBb5DIgV>`w)fVF`74&Uh(*R0lL3w9eHiOM z8oB@OlG-N?T&=ZJk>X>4{79goNrn^)za83gk0SBC2{j^(JO14SFD2xfluKtJL3Mm> zs>UnZZUt*)rgKU*a0zFdFC3c|yxh_4sls%SZO^oN9vX{!X862;j zC<#$hLWu|v5b-0SU)LiGtsY8MJ0st%mlFa3hdw`ONZwz1l8W28#XA=!2AbdJtfB=JH;o%@KcscQ>9LG4G zDO6QYg9093)7QEo{z<=UG5#(39wHAD10uCYk$ zz5EgB=K&3)aczE8sSRH z_mDcLT1R4V9wdg>1rcmEV)rML@hywjYf}&Q@pV(_A>576-GAGeY*y3cl3;N1wWlM7 zgQXWULV;;eb9 zO0$N|DLTgK=oOQDvicq;@s*B77bh*IP1*PM{fD&99MToz(xP&2zLiLAqQ>J>wfzK5@!!rkl(7a?* zRijM~mP3h`dgpJ9d}`40W@7(3OGKUSeawzHc~85t>xM;+l=`w-_;}1<8A4qCojKnt z#+L6K0>5DWxri*Dy6&c4eoP;Dhi*IR6QW(8oq=q5fQ<>vV6AWPEsyu!Z4-F?1<+-d zSNlB#ScbBzwvj>3jmFG`nu;*hgn>+OtH=G2`4OYbX6LDT&Q-!LseGwQ$*D@!jP_hwQ2XJtZ7cY8e@!te0t~BS}uEq?8HFGa@i0T8M%`lnk<2T1P}ko|z;3m_5>puf|%2;BhsUt@rZA6}@+6X@u|x);WtdG8$0csu}AK&rnMg_?IF$QuO( z1g?PQd;~p!5E+qSzu?~Rs1^xLczSzO4UGc#=#+UKwJ7pjOi~!v;#RG!^R|dWm~5T| zB%uJJtv;N6SVTG6xY2F;t7hsx52>kiToTiLPn(DoiBF-$Q0 znul-pIXmYW4~LYQMkim-#6w2<-NvR-hjWaGX#>PN#}Aw6bT*ZN@-mp?6PQ+HglOjY z6flx(1rFZzJYsHlq$~0`lf$n15^JOM_6Isn8K-p|+Kud*iX2Yj1GNWR+|3J)^xyUO z%otHMuL%f96ql*nWsIp4#hShwC584z2W}fw@bl&~D8^|D1|`1Pmy5s6k}-mczZN=B~E__(ccXUaw4Xgx+PEp^?o z3CIQ9vBP#4)&8VuXWV P**t#yDOPud8J1~3_$(ozbg=19cS?|n}7`@eys%JElGm-eG7c;=h3*Ttt3X;jEZ_elq=CYZaH$pDFi}!tZJeuYld4q_^MJ{FH zKpb)NvVA*2$J4wxl&NAg)hD|NvB&@o z!#Gqc2B3OOoT0qsmFdJvW0^9dgt&bh-cir<3!+|b_~Z)T6?}@BHie~R{cfns+Qm}b z<;Yti)=3S~@-S4*@2(X@#Mu<{;(5J6?#HDKQ_tKb*BlGj;&#bC zl%;N%GG*jA;HuIY6f(#Yo&}MC$IlA{rA>+?;bF&ad zfGur+EdoZihxROoU|vq~xJAoltCwbfhI<7BR(j3;tXb8G=b6c~7wl{la{K=aWWWDR zQu6+@K=wb2*t|g0potP?fXFYJ00RUV9G4kk?qCN@2o0TkV2)9|-Bz#cnQC-!mE2RJPf4ymGjt<`n<(&NR#&z}D z`lnS+zKv?kIsT!eoduMHb^5F_U9um(gRR zbBXM&%-mPLgiV#Q#=T>NY_1sD$^fp5R4gaCHV>%KI!3W32p?M3!FCaTz`DLzmlUkv>TEhP+SYf7yt&J0n@X=_n_mGXMVIBGQ@z? z%)bg1nd|Nr=`{RmNDHiI^W>k-&nrCbI$t>Z^7AeDspKxvGeVJB-BM{YA|enN6{B{< z*N`9{iV2tlik1OdII;*qulkesFrDEV3$Iqy7FuIL1$`-Z6JMEzZ^34%(i-yt^LHS~ z>iZ4IQz#Su1x^wQ9xbjAiJSchPhUjD%@rbA#4Gt_@l>1nX+6D-?hBGsfCCRg%gOY2!C-FMxzbo3D4o#U+xYK3N&aS^W$|K2!+iN+KDwvrIpnFO^}YkmjH# z)zyt>Ki6DS6l%u*-l#2Uaew&3C-K_J>UGOU&)V4l-^8mYcMXsPuLD-AFGj+j?^v<_ z@{Uv&>hhi6p@LRGhl~+;B#7poaQ*~>Xe4hi!XPAyGvuzmsCT!IZ*B_XaS&DUmoA?1 zZ+>?z&$GhGsbH)C2<&dP$y7%`fI&VdUA8}Qoc4ky5k1Hhox4Dt^7DC7itatxPyDIS z47b+!vl3LY^Gy54;A`H#eB?6r=2bOJ!i(qQF5_#jz$T^pt&CU2K1<7rPOr)OQ6@@F zYEJtk{Y^)PH30Mo0YU5mTDitIC5vSalms}1880+&*3g=u?msUT4p(VHXvTAy{S~io zKJu8U&%xaun@8oqsr`yC_+Wq&3djmePAm>kmJ8^SN!!g|7AqB!E9oOo=wRl3$+4h+# z`HH6#6qUc$g%AuT`Q^a~l+9p7qv#>gwn6YU!Fnm}#S#zxH6kOPr`xYJ$))aRyMSvW z8L6O)VaFtN?6D;};Y0)Qb=jcBhAMQ5X0is}t7xq*DuQo4bEgb=#+tmk{e22A!C4qG z;u)Bl^$x7avNET1xW}3^EKl$J`KAib9GdJclb{0bcojY|;u&f7>GJh06u2Qz-;}Ty zpwq_}E4|=#qWmz$j+hK#g%xOrxA#2-@3%GcF5mNdNBl$K_7(|scJeEU?~1*}Y?@&f zjDD!`fHx*2_6p0p*_%qQEfmd}^*PkT;``HRi7@%Cui3M&szK_m z!{^+1GTGmy9E*KEQF@;I!o&E%x2vJc9fIMvMcxwj1bsn)A#;W)V;hso1b@H&$=(~ z!t8VMlx#J{Pw;=}H*AyqxE#51<)ZzIImtBu(hLI9%vB+>gVE*lx{fJ#K^*-X{WzKe z(T%Pco|HO>U6?A3e|9qFF2AVqs!~Lp!bFTtt@rnNaz+AwT+NS^a1OeTh?UoNhzdhA zez?7C1=PNCrc8Z zoy)Lt7HzonZLSzDZRl$obanxhK~#KGZnAWcST~!FR1qOFH_Ic3(6)vXq zxdWi=L8OQRnbPgZ#p`HjzTl2IfL6W$Lq<~-$e5(+aPaiL98U!qo`M!M_flV|jQzP6Y9FIdQ`IiGdDzwuym4w`45%9K2K ze*j;#LyO^l$lf0#v{hR0U~@2tq?*VsJ(}I70^eTmvsQ9jkQm`D=MQ}NjC2ZyV3@@B zaEU))wB$s1#sQxBe<2t0w$Wb|Ac_1p)CFrz~%O4mlRS>3~0?##i*2XCt_ z!JZpW=wZ7)Jt9mr3W7mY-8B?92w9z$YtkJ2U7UibUW$Q_X5gn3%ffgCfJ3*Wq*+Qg zd3Vnq7iH_Q?P=D#mR+*(=mr9_QG(B$J}pJTz^(Bt3)?3L>aUUJ@ad3%AENCPPltq8 zs907l*_M>wwm9xuH!w7-Y&uZTMNv<96AqZOq1ag+q(C+Z9l0T3O$K z21xf6dg~xattLrWlg+ZLJz8nK@<_7MA0gKWe2Bm{CC~}jrHNI0@x*|bh!VN-k5#~- z@R{=Pk+N+z0v`fvQ6kcV5CI3acQ;R5QJ~s0bVJ;m2%021vI9UVCEH+pPtUlXb8Xv!d4dg1&6NtTX&pHw9me3<9*AfVl(xc=S2$qq&uJqVLckdoHQ5VDu>5Yo)yDtc&u12ikUkDl;j1^_T9 z69awZQ#a7y@k_ZizLyLje+lB+F~0F!0ncH&AYQV%k%|3e01Vp5D29|I@#LGrd5P*R zw|UWWYj|s$OBvdHB^$_dgP1~io}(um-Z9{!O8gW6YM0$dZ@E-khaMu(m72c1E?D?P zwuBpC3ty&ot8C^MwMj%`1oMLVWFjE&-U~!IWi3OhjE?kTWDtt9LSz7#97zlS*e<9V zP&xRV{0YTBT3VV91o3ZLBLE4FHeas`4XqhfBGKi>y4BR(;@MaGr zG%y1bBxXt?>3s$V(mM1bu;8=}rc{NL#`}0xn;c0#I#I#!3j07o?>Xc&1wtB;-lx8Z z(In6}@GmuoOag`n!)2fv8%SPsenOH?8zMtO|0qBx#;u2^XV@dZ?H<5k7jb!@i*Be0 z24Fiy91dNWmmm0zJYitIKt9CF)2hD<2>32Iq~gW^%-jedCL}ln5@fxrMMQ~9v)wf{ z-5d%HXr(4gJS14PG=`ehxG`cG$rZU}kMTvq62!`@d_2uLO!_HU%*jX+)Zm*~cbA&L zwx|EvuXjO@vEM#^{kY$O?_SU72Gg^q9UP{eodF`IGnK_mvmCyxa5PX58(&!|JB+y!#?o+_?8hrk!Qi@^NzWX-ez#oR8 zl-rbm@?C?K}vW)&i->os_w2P$cceU)FvST9rrCK6wjJnDu+G#<~Uj)Psxrm5z z!#S}na~)53oh^tcvEAKra4y%^P6{@wqDvlt;T57o7Yk(!bo3odHY)KDlwxL6!cTHgnNvc58rUU_@?`QWV09d!sYL z&`|`jC|)y;EhY2lc8;eJ)-a%N15}h7PTa`{B=IW-gRzzhf#BMjsu;5*bDwI7uu-G{ z2OdIxU$2CHQH46S!X~kk!VIi|wfekFJm`;-`buieVYDI@^m{=JYE3jDNRrf|Hpr8) zlBa$NNMcaHM0)oz8gT_JI-}blD`{=~y|Nzb-w_7UGpz9+fqM%nNZBKPSjgq7T=oT~ zp2(FGVCbmAseud)l`pW&jbj4sn`kzZLmagyBT>>%E6(LNb?=(q7B_LX?z*DUp=;D( zU>Ms`q-zD&G3Yvm1Y@c81YUj~leV{JfOHYr`dCy4#T7fvT)9&3qTYwHWSBHs(S;lo z1fOAhP{+w?&tfoGUZ+q74mGIg^}OjmGjOPZ&xY7mx-%hmfm~BkToIQ{X1a9rntiP{ z-C~xNeOxA>$D8TP~$gFB>C)Na??wDd~+!FWsnISktKcdce_`K zO}+I`v;&477Q=C4hyA(1v_Si22!>$af~0((-oTvUg~Em>81N;F#mX#utxL@h42Y%20v}Jl#Wa$qPRNb02(95Br{2Sh^)o{lbLIS?1UhlA>DR zq_9F3#;{8?+l82kPuHqF5?{2vu*$9)x72SmF0q8h2o<_zt!cRLR=C4?HeO)DN?eE* zygkBJTXedyp-8~tWu@%3eE8|2B&M%W;V;$pi3<$Ox6Zb-fMI6vd~MP>b*!JhG_qu6 z5%c8}`9k%VC2PF{M$j!DpB))(ou+BsNA?Zsp<1IFS#^5i!?GY5o17e}g=Itx{(uaq zs%DDElZWh~qUD89%LLqRT99W4VlJ2;Lkb9=UB;rzazC+aKcF`k*>A zrnfj0Uuo5)#>OMLxq;^Z_P+p8X4-_Y&7gx_(qOeIY#q{UxoKbJxfoM?n``oZT3llx z8yR6^CDB18)!fWjivNtIUGlJrc2JfbIpoFNG zE^WNy>KWgK^mEy1S5o7Q)8q~E*=b)V#`2TKV~E7@FjDz&7%_1y26iuN`4X@6T!@zD zo~%tvtSiY&hRwDk+^eXH2g?MCbJw!p$~@}WJqu^oaH*z7gBIy5XQQtwJ#f1i_p*V4 zp9_|%uGOcl%YYkE{I^O}__~&AqK7LleX|E7_fFUUI_-w?6ZRwZMF4ROF&}HxPMIU`RY&aoM z1%@YAHug;a?49gGWCTVQn}32v8+%91m|$87(^}5c3j086tGA$j#*~-nXcvL=YR|by zEoq5}TDQg2Ony(};Mh((MH|Ipf414>c%gG*W8?|CiN}XJdopq9*yK^Mofmi(cuWvh zl^+2rm{KjW*Gmk(?9H$v4Ow|Kh4?!ZlB?bM$vbSlLrkoFi4a+F3}|ac77c2>QbSh9 z7d7;MH6Y>pf0v}j?g!(laKAEH%Y?kshCw6vkEy-DhaPmtH+`voo`Hj|`C^;o} za{@9Wiw(k242}dm2<|B$)D8UmPQ05fD6tt7kO@`u3&m%SpVlg$U6Vz9TJ?QkwT}F2 zLv5o%-ITWZ;kgC+#lqp{FU}o0r-}t)fvN4ADH?HqiJ6MVxEX0_#-KB{l$0Z=bzTr0 zUK781Yi)VErdzj>YdD?M%CFVS54stil**HSwb0tSe(oB7md&aWpU(wGBu~h5cJdDH z&Suq2$`^3Mcz!(Uhg&*UPi!|-ir?7!=J>Ac&$>~GCrb>S4uTT@N*JKQ!2pO97Ujf| z!1B!_KP4u$)m2+mzSYEIqSId|QEx<-rzh9%#R1czFhy2Pz5v;;^ZAQ*{ZnXVAG0GA(lJk z{iik=4e7FknCkD!q{hO4AGF)5v62Kl5-4#8B`x&Yw8GUiFB-adoeDn>ifMx)kF}J) zjfbSypO`GI`tDUmGAkWo27;81?BV3a&@lfhWq)r)(}>PwhyH5-Br)<`yq4?`LQHvQ zVFz}hAs3KaqaiE;YtpX>FRiF00D_1%2a(~6V|snQ3Y-Iv?y1*ElLdfuE=55xf(&HY zA{nv}fs@j5XM^-Glw%T!&F&XZ{pw1TS+Cpy>!3led6`iAgIH}0ULzCi!VzOkHM+vf1q;i2yx=mAF3o*=KHFOjxut)&RYA zywn~y{)wEFH+~$%i!zC|AN@K&U041BU5|d#9N3`sJQc0HwkH636>2hXrHj7t*EkYVAklHlFN&tL)8`wHbfRD zNuYyjobG57I)=6WDIAQuv`*Jati-)PqK2B0N~)?8^s3qUs%8lsRy?`lO)3(vgrU5u zrmM%~aWjXScHhs;l9Fp9S;QAbG!n>N76dD+J-swb+Oq`VGJ#{HG~9@<80v2|7j| z9j@x4uE+zn3#-HGA5&Od`{&!J#&9Q23kPItIjt@A^FZGgGB0-TnZe3o-hrstK(lQL z=N+TTW`aJgfkun5D@O`$Befpyg3j$cpiC6Ejnh6dq8#vD8dr`NUcb1*UYPLKVJ7;BXi1h;nU25L~a28KKR1)z)|RNkT9uM$7=KCHVy? zzDknnwkTte>6c0>K@3+1xsg<|iQB6arum=O)4dzRj$ZS;2bB}Mj>^Y&;VL-^D-5qo zItnlv>anAYM`}YJVgBxnj0*Y44QIYzgUlihNd(hFDyltK|3HMSLu3^q3+S+ljtI7{ zT0t-OvgHecB&#YJuv_Z@m=(Asxysi{&cq11F6K1OsDY$AGuEF-p(rTPT=$_+n1zXR zZrOx=78AsKOgugD&v7S*Hw|}i6s8p16_`lWIWFvBBgKZk@<9_fi)X^SVl3R?hZ6&c zOKY}+bAm-;oUV3I1?#lkBrt6V^Jt%gSPln3ZLc3=_w5?>b4LF#3# z`$d+>MPYIsJ&7@V($3!VEZM1*j{qk!9z3PfowKSlm}_e|E#$SlkC6=xl;?#y>O#Q@ zo>R36ruq8bj|A1PocJu138s*hXF!dXvllIqIpyIqSJgdQ=#pH2YRsZf(=iFE>1;L1 zyjjB<-F0?J1dEJ>Fg{BoPPel?pt6D#L6a;kO;Q9+Dzr4o5i;W=Y?>rwh9PV^O)1k! z8kmYv%Ct-aQz8jw2vSWGB$!E%YC3V09ud;DWGLzgNd~ZJ)IleVTS*0bzprA2>bFR- zjA3MK%*c!=0#kxo5KkE6CeY^$+K-@qXORM^gz=iO&$Dk`^ch1Z(XdW4f9;ichyRLN zoe=JjZRO1mYp$_-7{1uZ`lorM8jQM&=y1=Bc((9YfAL z3Co7Q=#&gXAlt9Zjl+6IQr6v2B`V5aS?=^_gZodWd43Hf=JX{y+S#%4;iq`)G^WBU6|c+kGR{ zn(|`INzr=ES$9Zhpg+wRxVra~juji6V_mx;zeJeR7GC7lir{RxAGuJUC~4nyGNXok z8lY{=l^hg}onmpJ@U^B~!oQbYOKfk%A&_R({6r{(*^1h&sMl7<^83CjkDM!b=T=ck zbW2Ho@BJvA%GC8#Cw^%UX5c`J!+Xz9!QySA{^mSXKjJzw4h>q%$7xQbNKMi#OZugU z0Zo+U;@|0tlwrLcD1ZwgFercpL<}5wAS951h`fGq#!Zf-SA7A=7ttK?I=sRLWRhH^ z(-Z%!jSH;%c5?U&m#^UDFF@-`OvcP|b8tB1#Ryy?Q^$D~O~qF;(hpfHR*;=s_l1gX z89oS4<2Y!=?MpUwo*T6XGA(pRNp77*X@=07fAHdNpjqRj%v=+GHqon)&U>Jq)-`Rd zgo)NV)`s7jWpsE@TIW19mJ4g}OfYi-Ue?WUxXP7WBZC(r0a`KzwiT6r&M810e*X`| ze=k1<7(SHQ@-Nb#TO=Yuu9ax?^8f?D=;?}qSv?J%^`}3zJmKrOg~A(OrhJ#_tz_6L zG=Je8wCW$7NS2xCHbl(r$|aI0_9~9PWJXx8;v|l7kvgv-qrkBwfEMhX21pKNlG2WMD$etDpva{DlwP<$@7DAZq$(ArSz$)jqvMia!c7 z8GU;QSIHUrsl#iEne8v97i$p=M&?E)f#D0c0T;Gz-9k@cHR6@U} z{iZfG^Xw{@Yp9U9F{%+#_NUAZ(O!~SQH6^4DNAe)t3%<3YWk9t-p-%QTi>4$X9nm& zr0$jeK~R#9*kVo~QvF?%?8cgyN<`P-nOc=czYj zsqOLidY%rCPYS>e|VbJwbnL_#l_)O3;Qt>PwH)7smSZ(pdDU zb!xkG01bLyGwDp>#J5|jWEqi}==k7^w+kBF;@0G$C3l}H1Yo&FETsADCy#zT73%8_ zAl4gsavzXochYyg!ZJ0YEwxnMisyS|Gz*Rhp4NN^koz_DuLfAq8-@1(?vKn-VV7^v zjc)i#gZr7{4jtx-;YG>A3wYN?b)dnz!L>f_NyVPq1!cKT_Q)3IH=zHXG z!%%Jlt{v6u_T@*e`@$`_YWF$!NlHG@&WmpE$h}S35nkDNBuyl3uMf!@$HwJas^f;2 z4m+E)*YuvpNbWQ~0Lj&(?Cy#e@JrkWEOkzjB&vsfhC4^yDM}6@s@<(_cPAIV+SNqS zWyie=T~ImN9AfFNP-4OfQQ%ma0l7TFJ7u(>TbRYqd_x1Fzya0n5vtwIR=WnayUJP( zRGIp=m-qq3+1iiD_sMkQ%{Y51MC$a=MwX_oIn(4EU z@E)NCI7Pgn`3?pH=s1Py-2+L-2FpVUv6$ zV?EquG3$ERrP%A4v}iPdlx_wQxIC;M`*y47og#FB~YEHZ(qvGC%=ie0y@ksU8jR76=-LCxiQp_?g;0l?pzowXkZ^A!6l25~ zp~)B)BWi|J9oW+3Q_39OA1Lc)Qc$a9bi3tNxTZxwcyHB_^|*@aMnfVVA#)<=LUexz zCR`-l?4qJ6EODf%Kp)8r78U4Mn4!r9Fqt7m1#+lINY26mUJ>JHB4-wFRGkZwG86rw z#fg}Lc6XWSVvd-hoHMHjw$^%LE6(io>(?j`(?EsCKL(Dsw;Op{uUg1#U*r>1tz6#z zm|35NO=AJ}eJCTJ{P7gLjH4#;L?e%K{Rrywq#N<=aq@xL zX9G%X0I&ha*nlt_@DUrZzy>7QpyGB*&~Vp#_T4U{dXVrF824+Q_(iZ>{|rXuNnb>^ zNj@-@vtJs?GziGQpgx&y3qiTYG|Dw#lxyrHPA$2YR>Ba@K`nM_p3WVpj7^vJX+i=wp3j7!o8!lq<6p-CUkxNb~n zAmR8CFc%IAx9>Rzh!W=Fg}4!8SBl#@g8bApV~_;Do*p{o=bYL?;Whd}j{#YygXMK7 zu>osrzz*ehcEjU9IsEp>!HFz+4?H5Hkt9Y&lT0Q~k;z0Zm3piG>ivjBO~osi3&3PN zFdKmBcwjyN6Y{`}gj>Xv{A(*=6quA{%xc~t;Lq2|me>ekUp>QN@U+&zHwFQ)34mE7 zU>N}8$iO~;Gm(o&!gn{a#9pds!|H|?Y$aX|?b?e_VQogJ`0PfgFt!tDhLZj0-IZ+U zV&b+``U#+~0N-B#eFo5PJm@qnvO`%os<>drKDYB zReB{tjL2%JZ;4(1(n7lD2(MtlQfJ6LE|AaZd|>x6^ilGbEI(6VFnpTfKdYHXMhoih zdPk~t-%(HcZO-Vi3c~Qm$IyNUzBer5l9}<2VN5ggof=LO4r1LxAPsHFOq(LJ_b!>2 z+>^o<2g=H&oqoG>S4X1lPj`jK$BG`{rN@oL%eU|^xvlSbU7eP|fw7r+s7bg|V~34# zQMg2m@?t_)*~}^!RXGtk(L;%6@L9)v&L{8g zJCVaa?O;7#8-oB3|D@{A2!>%L7nY?Q8%3bKJh|k`In=$m5xbOf{*w3F-VShcZhCuw z+!2{v`!FGjYjWn~lRENw>7VmZo_=&%^-?UE6f~r(tcT2zw9iO(6E)?{5lQN&l|*d& z+RYP13gbh8T-B>ool&%l2j2+DD--0g}4fW%-?wgrp&d(!^}lh4Ro@1<|q z3{h_R2@*b4oBLe5|44^tI(?Tezo6W%Qa-_upCau}8g{abk8#__8FBTp&MeeqqrStK zdu!b1$jKvlmo0KtCVW;U&rJF0l_oPjS;3W=^$F(WmU*93VkirKj%lkKKHDD`uBs`O z#r-dwKs=48pr3E#f`_U>RBPBM%?=CCPd&nO9*giW#v|NeX)H?YM#YUR#w4t>?O-=s+mkSqn zJ~1`G&WR?5-YaJ=hE+obUKK$rVj?~|cc1X=(Z2l-Q$;-Lx*m3L;heJ^k8?STVn zyX9usPN1#FQHJYZoORp0BPi?_JePwOjj-u*tmS zvCVc=9)7Cn#cQIvqLr&GJ$0TC?q><$lS+P*1B$Lh zjvA8@gMXgvUlU{k?g_F(co1ga;R#s4+)Ul41(F+y96-m7&g$z8YB#Yfj<^2&>#ZS_ zqiNBc#fvSeSUO}`Yb~!_^v>;vK4%E@KL0;z(yxCWFZ`w>lmWQ02dLQFkfRMB3OcC*JuRT>S_CHtaw5Kd2vi)z71T81*Fj z)BhSYCVacC@B~e6Wdj`luV7YhpZgqq`pOi)lw5a-owNK;IzEIxIs^K_3-R}#g2CEb z)NF$J+U9jsfbOv9mS4!6lf2e@XnC4rHzxL;V*HvkQm}eM}^n#C`gnj zQQ|X``Ax|n$2!! zkY3L|xtZ?}eHIffSz?H-Lt=<^r5O?>hS+3@5+zEM7-IR(kSI~2M2Qk5N|e~qt#ftR zu?y`qp6G5L=*Q8{qceV{#hqp^~+X`+LL_Rv0wRk38cTy>e=Lb!`H;R z{3iwwP=r4)9{?xBe}^kC?V=10Dr3_|4-;E&KKkCk0HsI{XJ zsCck>-XI+-AnwtXhHRlQ$q%KOTgnm{WN9ndDX7__7%X3C5LBm8hOnU7m`kQpW!aEw zJKwnpY>wSZ_mcQh0o^Xr+t$2kec5T8B{E3IR`Oa~f>jzagoy!bpsc8U%83OZft`kRPo?k3Ir&dK)t0UCcxQn)G}_s{rFJL9b3Sf=VM2>{gvc zV-*o5jgWTY>SsFFLJu)8v>^cm^~e78$)ZDwxRa7Tn-%%!Ltz?i0sg6h>r~POv-{v(Cy0^5( zz}uA*Z>7Jskhz`d-nC#Apdxc3U1OA*bk~edqWF{Y5e?K=FoFvXO(4?G@yQ>OQ2DFo z_FLsopa-j(jiT~n;rZaH6qC&?0UTWsU=)47#;+mo{&rQXL?eN&R&-=4Eizd_CNf?k z)9&#A53I$z(JF_m$)#dlU1>as2ZVt}w93q?qs@85k5Hd@B_NYm6lvNcKk}mrnzb^m z(022lH-FvYXTMDTsMVwGttpfQJ#~Cm{u?{kvX$a@n^vNQBWHr)rJT0pvOvVR~jm)U?4^jjrwNajg^3IhW?ThA_Q=a%-F*u_5OSMec znL0k+oAI>h3@uMU*=}`a!c6lcjP0ghTMAxZvpXG0zo#Fq0Fzx8T{LH$9ZUgs3{2RA zHAIc*;>XQtowFs4hmGbsgbUMa4YRzXo9Pa3QA4er83z29f{N%IwUByu;orq0|>G{7p-F))jgc zYxLfpmMbN_!lYmMihflaIeU2FU|#)VU%TUecJ|h0x>4@C@X(9OU=S0P55`Uowzll+o znx1A9+r1yT*nuPv1tOY2=vG#}3)Ua^*zYf@CMEeZa68o;u1t%VZpC*MQd`Y=gHW$% zFOCJ#jAAJ7dDc@xFGE@B`$`8Vkkn8sJ#4#%MzCNlqS;POLE1DYnj#%)+0aD~ zwPa~EJuK!&dJm)0Qb{Fu_HY=nIuD;(M)6`bzFdm6{R8jS3flcM$k|f)6{@AU#MSb_ z=eLsR`$%7^WIy2UXocM~P#9siPkbf{sT)72L!wn5y}SsbSG~&$UB|_%iIGOWG%({# zZ)H#Ewnv$|h}?y%w@ay36f9zht-cvgZYW7C9Y!tCok^p7K3a-Us(>nPgpz2=Qkp>G z+W@zs{aAXh&NzPbHrR9NUM9KGGhn5cE}4Ldk#8ArQtlzMk<2``PtI803UoGY&qVD~ zv`6vW6*?MQXPc!3_9*7BS~f?N^;!OE!l-fYWGWu*LUZOTZSBWvFJnbm`{pIwF5g2X zL}hkveatyNIe(jeSMi?(kb{rss)mW(lXJ5sx?ee;Q5jWl@`ie|L{q4-KX-k`?#YF6 zj(hxq&2a0~&X?M=u*{C$0;k9AL%cVfE%J-wT}M!6yS=SbNRa;(UX^FWI0NJ7COTUD z8sJae)wQDBhN3sr9LPBB-K81Dp-vw;JgdhcNE33xc)hS1ddX`TaDT=nkX#|;!)D5d zTDOcgTo7hBgaKG77>9X#E3#Tjs=O74)Otp@QZtT(wO1{$Qe6#{JSOSIGb*p4j09Z1 zPfq-7hI2Hh2cNX$eItVsDpuh;en-XQ1v(cSa9oabT-{0ZndoK)|Z*q z`VhmpgR`v}T51a%IV={hzjoAxx+%Jrx-zsAatK3R?NmeLZ+*4seT%9-2byg29Fgqp zUNXcp_?DKQLR;~(hsWVJ#n7P=RikR{@-68|8(+%RZl)9;ne|;}vjJ4C%CCe&fmYL! znn3F%7RuX|p~@A=<(noKgwg-w40LxR8gHnK^UUt zWO3bo%-wtsog-T{)J$-r(Kdo{pYkuwy5%!H~{`DIPL zEFH0}NsAO@d&Qn9-wwAONt!why8yDoZ z0Pwuc(aQ{Y3Czk4W!tE$-gCz`sdRH}Nhd1s2&)T}UPB_@%9kvKCMuyEarPwM%BPot zKHD3^$^(fGAsUJbXsBcYsz%isbA;SVim}jJW5H_n)FQMt^_gR_SIH~GGrq^^tc_U2 zWFx#1+76F7SI>}Z3JW*45aYhRcxb+fjaP(#!0l&#ZEfdnqnr!H;95RW)gxi$S*j1L z*%;^B&Xzq?-y{4fYlrQ+7MxAZ4R!V*oITt^D2~T?to$Z!6p`6fK0n$6kl#Ni-qcD( z&AAad8|t2GuuPwt(!50YYHx>I&ej=o5XwheIFXtPXcAfhT8{be+|t)LC`oE;Jc#e) z1`hI2^WUk`S02ojmeZ9JVhwDwdi|Dy6#PB&F(f~*wkvO&mQ8P*szk*v^$e{DQ38pE zstTw*;#ChU&jsEXZ+q#oIh`IlBSrndYT(Dfjh$swT+g$vaSQJ5F2P-b1lQmiAh`SB z5G1&}6Wrb1f;$8W?lw3XAm}AO33r`y&;6hIFzZ=+_wHTQ^;UI%nCULhw3E!-DD}w5rYr)Vc8wpQc#}x#K@E6lhufjcH9RD zaX`pkDYc~}N+{TXN^g%}i;RNU;bJKr!$Om52HfQP#Z(fRHTXMyJ%_ty6*NU&rzM|g zNolCP)oemZ9Ab#VTI%fcDRe;YU}LAcqpcz%nNMt~5hDucRn7=z15wT+>fXFyrmm-e z$3@aKY=UOx7FcDi@Z^+Df&?|WnS47Uxfww0!MqnGS)3J19O^J9hBWO6)%Oc6#hiWV z9~~vAyM&s<(khM01Da|? zCt`P%8;)Ys9pDHdg1gD=;n)QD#BOKkU+z+n73@{oYy5S6h(&7(8W|<}-Z1B*S5(Ef zS)JtLTy4$Fn~ja}CIlEq=}K!U{);%rqHnVVmUJ0<)Rw5JdMi@Pe2d&eriU0*Jg3rvta65Ud~c{Z&&5&;j}NSo2JlB^AF4B7SJbBOIns0u$X8{jj)Jmp3Cb> zJ^<$xy6-Y72Ywh5GB64YZdh^hZ-3E|z#5Z*vIh^O&=gTMkSO|E%Y$vOcq9jy5F{vv za4?iBq7rY9ON=4>;eVJnADrT+S8;wBZS9J?%KEAH{BwHB}0dvKq>72$!7vOfB}=CBjZ)n|O|Dqa$R( z^JwCgL}$oX5as7Sx0?|A%RyV@ZS>wA?}12GH?K1;x)P5Zbr@s}U0Rzx%%nPVs%hT! zhal-S&IntvbJC~NXS!eDnok-RR=kUTm{NsHZ=lW<{HY{os}QmCo$O4hI7H1qBL_TM zF5cP>HgC2yaMBAZlEdt9DBgMbcKKaFuP~)LZ(?$r1Y^8O3l~oumzfg12ZPzOt@Qqb z3zr^8|8VNt7}zo$r5hX=`LD30Dq{)0UTGp6>Wji^S)bJNhTh{I(iGL0!M7j=Pl zW#t$OyZ}nzk8omkezIop;6q8uFEHK^;?FuDp_eP^oL#WO1LqWS9LqXkEpd7&Ni2Ag& znE5gt^3;Yi0##Y}hE0_0vTxwPZ~Emh;pkt8+7mNen6Buga<@OEtehM=Z~8Dk?$$N zW|LzwFF$MG-GV>GCd-L- zxg=ggD9{I_#CxDuyf@j-VfLPn+@0=>(@+vEmuJ|7WdPxcAX|Nt-r0TV1NA&m)a9`b z5!QY#=BV5RWm4PzT>K@-nf0?=QQIkul?P^CfhyQKRYlO@uI$8A1vZ3K8vHg#=7=3G ztPY{DZe5&a0u{fZcDs&3+=pjRQm?@<)-|ZiUzHxAXL6M(4tl!YFlPhHCE#X`AuuL3 zy=46;4KgJ>&d+KyV&Z_wC;Y4E~|134sG~#=7uI2@uGW~&=*7vCFJWPHz z1sJv7P*N%2)b}&Ik~6z){c$j3@||ET=)4H{PvPlamws28J(p z@^h(J#YD+zV846@J9qEg)sV0<1h{>$$MX`8t|0mo_njA>FURVt!JyDD{h|gs^i!6D z&F78+X2vRW#+_%l&bueQVd7{fQit@d^L5V}be^%#$kXMA3EiK9Hl4dKLW$e?pg6(% zwsByjbk+$jh#2B9IoPXu0H~RWr8wrSM;dZK2f`-hxu@<1D`!M%zu}F`sU0k`tQ2yB z)4WweZAf_+u}Q>lJ+_0G#2zU*Ri#ZoibEorlmhH>I7*0AC6@#_EX4O4>?r`U8H7oN z!D{sZD4yj!XOAVOX(`;Ea66K%v0J4MZ& zNX05I@8aCYaIVmLN9vNF?r=Y$!X`!-Td;+>sBm$V)@^KEHMJ>E@cJ$xp1xeeO^bD~ zJ`?p>8U;jh4~>&1VX8t1vqyPnLMLLXbw@YgA(V!vemsl3<^iKILyWd1U1jO2t7(;W zD88$s8l@u-!ZX!PBPi4wrn9)GEN@*6Crv~L*Uv%|BU!G$h`inRGM{WR=JiQGqY`nN z0A(3VED1mtXjn_cNSs5lH$Lo1#GUI-!KBB?m@EeUG>GsD8Z24rDDO^(P1%q^^Ffxu zU$-b~(;l=CNJS$Gw9j<73Ja#B4b>fi+~S+#>Ip~j)(&#(#v%33*fV7b;Zj86%A)jG zV~f@V*$P{F2}&)3QJRyBy49J)1K~dfCYLY{W(%mK2&4RRbsKP896*yo9B_#bl10F( z?cfoD*V>vsXhz4V5NiHoLtQ4IW;>49+D1;<0ppvlSMs{pufY}jbba7 zG!TR++n)aPOI7MRFXU&XPfln>C5gbIgWmY~DIMnBolJF4V-HY<|Es?9yBQ0Li;6LG zwr|Da@()tF?)Y7J96r-&%=_x86sFM|(tZ2xWsyPp^B{eZnMQ5K#htDzSe3Pgp%RnWxx!LC%HGLF;o_YjlN=@}1!UHwxYj}%AZ#GxU(Txz`q&PXL8faV`q z``S`955;e*(}8hgI*W4q@z5}xWq#MVxM3c0G*lA>#d?L}NxA*W_}15sofXgMS;Yos z;m#7EW7*~oQvR^-%ip|5Dcg#udVrQ}_o5$&aT@CB%k*!gqzU4J-x;-t5?1ltfV^lA zcDQc0iMP1G12(SUGZ|E^uU#rOLbt*nr~|Uigq45R-jlCbjV$63G#zf7Q;a^a0lwWW zdz$&uX0!wFD$G2PmpwyvQS<2WCJno7QWF<|OVd;PmDYq#J&3NbI@)t<@exo>>HrR5@2A3&PXyS*DY-PHAGinBvU>oS*%Z!Ov}Vq2ca%gd zHMIE+pJkmReThHiq)gEq;9agwwl<8cI%S^H4YL%t(1%~cF(N8BB8v~S&btUwQ=Wh^ zgk1Z}MPQ;7_BDT+D;QPF)YH%<^O=gIjZ7Z|T~sSx${P-_;Q^1vNg6swcqs$igKK;b zePpCjy7S9i{E{)&w#=T{X)eG(5o3<-2`#IHFkmz7$*C)%+n$q|Kxy2<` zO)`i)=*dvm$fM=t9A6zQwyY8~223)IV!^mWps~Ch(^@GN@ih9VO<%-36D0{7d?6$I z{&cg1u%z>o&t9QgpYTL zW6^xf_rCS{gfWf2EMRHsPw}i_NJiktbysW)kvKdgB(O1+h~xauQsS`@-s@vYN6Xc4 zn^yd$wb5OoQt|LP)^?E8$aoHKg&t4uV*Q|DXd}7}doqp-5qPrTCY~}r^#nR2UGRX` zrYs$dnOn-j4Mp#pr0OjptrN*@HI(_SDz9ierOQOXh<9tUm%K`|I&BV&IAqdqckk* zgg|ZaLw{2Zz&gx6+81c;mMb;L??YBr->TeVAK@|q*Q--l@ZOIh1n%YOYD#G0bNJf4 z4c_n_XLwOv1=wdd)hmSBKrX*duc(K(c2SRS`eK$`Vlp*R2RaT$Oxy*Q{6$p~XAaW% z48}gocjh}nF4%22Sr-{-{YDR~k%K&e+!$#(5*W@@IBcIJmSIvvEDEXYQSN%W#znlD zRfk+e6>)0{$uL@Epv_*k_(-!99J66KYum>pP;4I80-9MB-?fHa=cbW_LTc=K1H=)a zTUJi_;2N>ZsqvVWOX92Ugpr!SXRgnGsORq)%BRJ^f^7&YA>V$-E)H)O;b^EL8*N4R zj&`QEL||}BxT{gLT4REb;iqi+R>#G_v~(MifS33tZVs7F&3_<91=8skqS~|en^u=m&V7Z(K4ZW-0n!ipaA&zI*GBqoR7w~I?5|* z9TR;laIJ~y{hp3X!vw zT0c3B9IT4eH8WzA98<%w1!`O1B|Z5hMYwp1J{k|4|Gkaa;9R6N8y3tp>so{K{b#(- ztjEEa`V_!s;gi11GpE~41@Lq$n=Ofjn`W_%XlfE&AWw{>KVNsCK)&$DzFfjh+M4YU ziDm8#9d8Mb0D)SKb$U(`7)XOPx@~JxP`&T^8{ROd*g@&PB2wL9v zx`i=62L7mEhqkK5wlK9q>a1RtF#(0>UQ z!h2M*`NsKXB1~uLgTleKSkdRX8HhFvAIW$76ojrPB-(j}MVBbRz=N(6T_=eLjzq!vpmQd&H3XAU+vgJ=2^~RFU~I&d`?BeSlo`mH^wiqEX41N zZCU8hTadzozN6)L+-(;(e3%$*kIt1KzBt}kC-Fm0nNDbA@pyY7KIys{sE^R_#B7|6 z$Hr~%qPO>Jo4P8q*~jS_$a8$XF=Qqix1*rh7=x(dI;oZwp`+x8vJK=>H;Iy>hB zr;n{GAW52NYExfU*S^-g?TEWL3^@=cO>pl+_?R3?twt{z_$a&&mkQrGZoT?2pI|%? zK;cO}>0NG0{mwgkWDGn5=X0N^`36Sq(_)u@k?fa4IVq0OFz>X^Qs@Ry$8K?1`wx_Z zr{Sn^e9mN=t;zehVJV8H{`_kJEGXnteJ~?l2jy;}053k532fCwqhAkV8w9eNQ`w_u zN!jbb<2O`hACk!w;VF9+2!-v$LS{z_d#*%3pO?&Pvuqty(5Mso+$zlLRVDN~WRLe71-nDWFk&WrqDqB0 zX<86%o-#{^aN-VFk){}t@lgh1AXh$Ah;?KUck`WVm@Ea|Ty`(&;I7%znc0J7ne_aE z*318Suq^<=-K~`#3F{gsFEg0beyO=leLii=`%wL4yamf5V`j14W+(2{JwDIgJzAZs zt|shHX$m+yPzu{_!8a+(oqOCi{mU}$YYvB%A(u^}yMY5A#NT&ZfrGsp#X~B2`(6PK zIdXlx%vPM6_(yupT2s&SOepb#Z{}Spd$$!$MA-Jzq#7|#F|c9@6V%3EtT`uNUNpni z4fAyM?n5faWS)Y7gzU4GanRzjPVn=F-14dCaca!MH_M&dWd4y@9Kr7@jkv^5<|#o_ zwd}Ezu{kg9l6qRtt+0HGcfCDD+5pGh@y_y^Q-4R714WV#;ZPpOrzy+_Qo`4XhtV7$ z!A5uzjI3_SP{43ofVY6*)M6gl2v)M-r9APwc(B&~Qt(7tVd(WxN3aKpw_dVQrVe$8 zTe{7heb!r;bATFXEXiW~IbkaJSqi!|rU;p>P!hvM#6clH#aIy=;J}k>3z0?x=#+C!8l;YP46J(wvm(CrE#IVGMNJ3#K zH7yRKMtvrlyvLXa4!bJ3YJ^bXqs3oYzNm>XUEQg;1rSDt*qTm=1XwnX-B{jqT7O0$ z7CBDh>aSfkzQ*l#AK&`rD&{uANJ+zQyd1>dc_nOwI-JG>p-NzA>Yah$7^+*6G13+P zU6}6Rf_l-{Mky#r1q0-l?us}b%9+n^^OLwhvlycB;#rFK2D}D$zUJ_$dYK?-Cq5m} zX#3s5(m;ha#5iuugzA)T4WKLywDrW_NdXFsTocGsJ?`Z}V;f_^~{Dv|Kt7pDmsxatoa>GIY*(uasrITWKv< z&{%5F2@o^%P>Zli&+Y`fBWibRmdwq*M|zvR1WpR|9Cy>@4=VbsTrh9$;t?=y+^A^- z2%g=&278~PH1I`rDcr0O1zp}lg&h@9ygv#Q z=^Ab*5s(ZG2>qlA%{I1H0`cCcTQ53n+*KwzkR@`>gZg;JM_W$@-6J(b+g-s(p(tpB zFet^@83*6wQZkel5)_*7SMI|a=A(kAtE5dBfW_Zi3p4G z3ymzh`%W7K`Yy;k@-XLgd$jC>TXcea64T%`rr4@$mu8!ibka=x84hElImQQ7!XeJo z{e!y8EZ~tv;i}g5-r?g7Bq4YXs(R?%pt|6*GO3t+3X^*J>ZWsx;Ky(mBd74{A4Cet z%iEw|kj60x(}t$}y}jm)6Bo3xas}+7T*)|Z`YF)C;2^}lvhYBJiW*h(2>3~ns}yta z1q^?3Y8L1erbU;{XKN8HQMRh*>*z6O(<$d_>pOJxbn|d$P|sCOb;P3gPKuEAq$1DD zH8S|Ly@i1uAE%-`JHuXUG8vothTB=rTKD%GHvZgT`#lsoUO;DaLqpM(%*@k&>e$C(Bl2s&_IJ#LC=O>{c&aGQmya@{&F3k$XQ z8qo2PI^ibz$be%`VY%fjS~Q-~kEr6+D4JyK2%X+FY?W?yt7bp~yos=G)kEJ>GHXeAVHj_^5&} zFTKr6fGaMedml0U_Qg&4KiPs;%l-WPrni(X=0aIt$}@9yQNM42RI;`rr{)UC|U zHV%vd00)=6X*@aX^uFDfg!oHc`lOhlnW`+$_zeXz6~oMDyC9gnVe6VD@^`+PO|Wum zlw}LJkY#A#tr3b{+m$K7MafOkRV3S@^qK!?#`Ceqo+C@n?5f`}(K~C+@v!g0xwF~( zDx0~@ZhZZGDqJ^$tWTyRwU8;pEP6{cK>H#XTuMssI%3 zn`hhhl1J`ZO^-ZP_u%N^X_D%b+-EhUGPSvud_fjJqJaOQc=@cMfI<0@Dd7_Oz0YCQ zB+L?~jHOe>&+IX-;ngMn9SJJsRNWla5>D;RH3N>+e{)WtqaFOeIr(bx7UlTgmFZ-O?tLfsqnsELzsc$*`YMBfjD)#Qb+nR4VG-CFmuWfZ++x{1eO?0IS1dZB|gahIKL8ezE z`h%0J2NfP*|9oEdUqdRXH?!t`^^NA@pK|eU;n4wt#iZ{#3#E{oHRizWkoqvQCozJaVEA z#`@Q!`VtA4R|{ZK4Mp*Alr1I~Z6ROr%_cHwZy?*-{F$tpeOs;6KvYpUvj6+*vUkxI z>a{)MD?+>?!YjhOBJwMOzasoUSf%wp2Iybw|D&W73z#v1R)H-sh3OEVbicFrQhM)s zVwbo5?{xX%aV7Mt`2LrYjQO28{~=ul0B>IVm3>8qSG0OX&)3lXXE_kPik;xM*k4qX zhW1CZZLF^d|AJV`7FDT#kLky$*h=n&*H`goCKhM(s zQg3*}-)VgPx5xA+c*`AjzkHc!alJXzSFEnV*eacy8k~~Br>OeRt@;iw3c7e5`%74B zV2@w2-VRF*Q}Ty_9;Ipfe%AIS@3YK7E@PErSIW&p-{X-_o!*}UMfUGt7`6S+!TzV1 z(Y?0Cdqv(?{4=sfZB(yUv0jn$6@SP4WeNFP^8~M`^MYw7f3K<8uUEc+y~g>!hWzh} z^B>BFz%}srqT$~%W2eQw?y3*!1sw#E;UY-p*0_6D}TQIbs83|EyF92#_yMCZROGZD5g2qh>ROXHu}dQxn?KW4%gS9r?jd8$W8{4dn`qB~eh$#z&#ygh-S`Kte?XF6=#-?9d*;`jID7DO>)s}@ z!U0KgTyfmGp8o5uIO#8v^sRBU-@0!7%=$}jJ$t#t`nKYC`x$$-?OT4!>A%4B+a<|r zKWp3h`vCW%e`;?%>zqr^-23Cf7bS@~CFx7w*tuid_Q<ko9M>=pM&?lJuijBq_Rl-+4Rs?KHpZ23-Fv+FK+=YLz58 zE#EIWq>z-7q;-P>nf{P3n9F2`0$GizSm z*__K3hXyNwa#`zFwSXE55~QRkm5jz#{oIo9#iGjV)=a>kvi!Lv7xE{pPu*T&?tq-C zngXGuYO~8H1ywl|IDC)G5lgE9_NVIg=btatYGN$qI&)DX;#d^7^arT{zuAEMr9INu z>+MbBI=rNCxPG6wzDK@Lsoz&pqSB9fzl-mmKI(p#^q!{vFFNYFD*YQf&lvyc`-9Rc zjr)~r^!v?<@2bXZ>QIZ~m9CTS)qA^1`Kd7)htq7>holqub(&56zQ$~t@4wLGIqH5F z%SboXu~q(d)OD3@kzT7`H+39!oo4f?`gP?a`gOCSozrr(-SUXA;EAN!9e4;AO^4PH)#(!0xo!A{Ku% zGgQ4S54L_{u+mn^Yu0wB>@^dIMTNcAU^{i#HMa+&H21w%of`iXx`LQN4+o;011(A$n$SF;j41{c|~dtwXVTLt5tB2mGPxef~%wCo@QaBjIJ;(OfQC z{hQtP6n*)*-OgG#ab%*AlzbIDiQIy}inJ1}bQW-qN(HG8t0H(KSLsj6p`csNk^1uumIpLKcYv>v()e0r z*Kgg@y=m5zTD!8ZW7*om>xA8Nce$MZk?8J--D9&q*j>)|%lB_Oxo5uA7Z+EWxtPs4BR&R0LDFflN}y@RhQv zsb&ih%XZ7e@gSx=6tx9hZK3c`qI}|bDmS^lFIJ9(+T1}$Bw86xEWCZk=+L(7*L1Fz z|3BBT<~P|L&g|4lgA<#^6Ly!~?2imNT|Qg)rW-e|zV@`CAgIN$;M9T@;5sS6acHXHpprN03WnXlF-v06T|f-`)L zV4>=36zDHQhPtt66<>*6ys&R|Y1s|iUZy4a-PGDbsB^C8OLnt-e|g*03)}A4B39w> zS7*+i>N#JWI`U6hIm9?EsaI=y=TgTJ%A^CnCPYe5< z{FrDBb@O5QxjO!UbNuB)3eW|IVHR=_G|WRv>+<)eQVG_-i5~Kqa5Vx-@|F>mY%8O2sl}40ryL%a{bS7<5VO#Ea2aJB&#c+p%V?LsZ)m* z6+nrmSl7?h$2IjHan&VVC4G)K4;Gs^Z@S4|XLSAgR-6cRccksUsc*h8wj^n-K17^& zY!1ytliksP(=gyL-PwU+#5yblKNAgQecuA#2J_(CR4fuTTf#}7-(NS~_4zc>F}SKO zL3YdoI`I6rLO*D}IZoIu<iX>?BipZE)pK&e<4H%XK5Jw+1syka z_Dpg?v-$QC5}%4@1J3R}_Te+GUAgkwGlqjfYs?)knoJJo%%0hqb7!3PsQajHj#V>t{^N)a&RS1p z_)*==9<0vF_vfOAA0(oX)@uG<{muFC+$i=stdG(rbzvN=IXnWLV+)JMIeOI1Y9gV^ zd$o96JN&}2F<{Rn)DW(R;y-B~zWF<$Li|`;Dr3f=#2UT=De0et9srKlb6qCjUdS8S zQPOeE?W59bxR2Wa=}|r>>0*Oo#6*vB3dO^Pi3UN)?qcO7-o69#Uvx(R(IBS>!b6qV zl44QrV}ttUAJ+R@GIDy#SqgX(&R{75$CcpI=ddvvhRt!hU)C^i1*nL=SYIWCe*%499jD-;Au_|(c1SYwf+mBNdpQ? zQTqW=sdf`@O_7dht$l@BKM!b^LYi1W9bY$~rsX=cr~u0K--PrXqBpR3Tp_|ySHm1;B6olx ze=BYv%`(loVLPXin;|;`>Jhw;udsl7rQb^T>YCzh@TzT6K*~tcwrokM@R&*g&j&56 z#L7(9vN$5fprK3b2b}Nki{|nWL-j)V zRT-n_-}z{kkVcb-dw#p9XKB0KZ)gEKrwYL#BZIs(bc0=f1$gk*^6#bBMQiw`z(a?d z<=2F#Q5$W7T9kN`hCyq1m7MKR@TPlH{>Vu_9eEFaFi_aeiOtjmLAP@7rQ-SIqWMG!0w|@&g`c^=6q}5X;66KR~#!r)<^l zIlPQ{9jtq(Y9^SxB$C&uhtaVHaA_g!QPzgPf=6xz9e9*ew__#Nganke#w;L$yd|8> zMO`sV_2OtMLf_p<3%k;nl`#Jvw}}84hlO)-(Dc zJt_KeN;SRxo<;4W1cydDSQ{g_1nO+yX_LyNteY7@1+raYg*cVmN-~^^M8m-rog8W= z5=Jh7lPQ_(?9P3gWwcb>VoA2D@|jIkX`@T$iPt zi||gvvu@1uMq{2q>1LV_BzRc2tKz*5RwQ$7Jt zGe9yoLzxc4-%QGu!9|W{S$?8_^OY-BT(P;ofAbY9R$RHc|Jw4F$;mB4L-bi@TgZj1 zyOQ*G$)4%ybLQxC4_2GB@)Mk!t|O{}o8UzmaEby2+z-Ew^0=Zs`I7?flfKr}z5(}2 z59t0R_5YOKo+3TK`8ZEX>v?~BaJ_yXB0c8dcr3c#WI5`77dub7rjC!vTE8wIgeJco ztN$W<2QwMh^Y!b-_(ACo>7(`QJkk^M(WE<@=0hHafIHx|8FVqZjQ%(r^9i9p@-jGm zcw|cVl@zBwAG-csejW4W{^{n+?4t}n*xpN|?pi0q2j!0$5#-X7^EP4grlO3Wur zafH!+-hdMw4LFZ=#XLD&pC?7TVjU>jU3{J9@i}-Mt%!F?#^O?MbIhyh;VhDQ!nPq7 z{dWYAeMq=yYFl?8;50i-dQO@}-cm5hdmC$uT4x-I6arhbSx-vKU2h?<6j`;_o(ASG zBF|QkhIB8Ir*X+)v9Q07@UB4GDHp9FdoblZ{7Xwn-u#w`rV=5)NB$SPEsnp3HzCb? zOWjD(;)~t!ggVJpcxakyQtvFm?%U>94S?7V0Qol~J*SMZO>VD#h zUywcp+3tWwFH-iq;n#8RyB;bYk^IgfMJ`gih?|ttxqg0i>pPZ}R_|Mo-So5iyuozK?%1|)^|ms74gIHw{sbSkdD%<;{M7oMsa=y4wL#Gj z0H=_Y<(X}AHjyo@kk6^RoFZikZBIFEcFy4D;o;4LU$c`ZlZze*93CN?MgJWCAqKg- z=KuyD**x%yh&*@m`M)jE8^`~bh|vXS4l7Q`R315!1z1mFNMXDvGs4p$m5OGe{5_>e z%H_b{5iR-2P`+(?X?$`;Z+kMJ#lr9ppV;)xk=#)4Kqgjj`(n(fp9K~0$?P9sYtDQozjZvqrclnmmTZ7g0u zCn@E*|0&)H4>JwgrG_#rUI@u1#pY5SK1Vj|@MS|zHLE@5iMyZmXVsqAL8n-~%C@QE z!l+mCwDrUy#i+&A7jRiDW_xLN(3c1~v|mJX?99wawsS09{T-x(W6GuN^SZRzxKs%^ zSyln}Nw@0oQJR?nkLwy(w5Ld$+G9`gO475GrD$#)h5Zq5(1*voqW3WAS>Ar2*_e%TuJ-cL3M!#yoKFr%2V;Ox> z?))4hL)Y9sE`7SGJ^AedXD9qDF_%4y`j0llc|JtUg~N5cgdhB8`J3|3q~rODAxR*X z%*Z71HRJnS6|Gyg6k$0Pp}YcO?~AV^?S~;jtk#$CxA_wmROU%Utr4p>pUrlvZBx0- zL@__QEVB^n9O=u?mD6$|5zou*YtNgXJ3TWM?}(%ZlF_bcVr(!qbCx|&jLWH@)^4>$ z+B}IsDi?9P+ot;l<~zg6xF_gfOzmFQTYU#sRX4x&5c=k}sB%vDN_LEp=%@%VOv*#Xx*m-2vPhGlgvZW_3k2ns$ zYHu5zFLke-$mS-F@990IBhcj!D(dLf$HN9x%3H6pcN~A=ib$bwNpY$tnws1+KC@{! z8qRvWzQI6$sqUIXQzK_BuZPaDN-E_+ka!qC%%M=IZKO2Wa6Er);jesd_tPho#@u0i zlb5HX(G>jyPw73Git=Bt?2ygUL!1*hlyek*6L(%n{E@8fqEW#&1SS4^uV{@pr~yX~ z;%d=)vi%mI`(sVLDCsi=Z~aZa2$6k?+dhg8$viYNEnpa~M=6FL zkEZ9ZIN^jV=ksx`&@tcIv7$REKL7)K+q!EO7Oq*xggLsce|c-`@_zb7c&YucwXs=1{XzHKh1_5{I zRTZR1F=GQBl~7M);CZ6~chOFl0dKTdrSBVfKCAQ??IY~>BD)DZpEc%7emUS+O*f0` z{q4c^`hAV-JnO8F_bm6#2=B&qmvpy*&$B!ZS$tiU{<8_M`aBx<2MxPG^!ki}w@3P_ z(eFjvjtF{%u^x^2&l~MSVs}=ot4Y)0CB$9V^YtY<*Y~lAvnILL68Y8an=+T4n$VTh zq6(C+3$K2!J!t2=7f%b`%c{|IsJAWCr7qsSYMbs&Teq=eG9)o;Y2$G*wX<}@9v0`W z$BbD95FIyWU#BK&I4(D!+)pN26$#2$*bgt4ahbnKen^T4nF?B{Pz82XsoUCsB~X^3 zh|I6qGCpt8`kErQ2a3L5<-X^WAIwBt?!ylT11#W|=gcm1B2_wkn90ZyGOE6V|NIcI zd*DF^dbUuZ8Lx%mLvU*@Qgmevbr3XGS=pksE8jM!e7=nBR@(E zV@(DENz1j~kD9acL%F2Qarl0JfB}WI=IT9xAjiaEOXh-sYLc-N{UOGX(7o5rejT7X z2#yu!_}_94aI<%E+6g#Gtblu2giEY|lVl3GgS9lZCt3@*i{;UuB6VSHPRFcmpeQ`& z88P!xrCjJoRiAKC7^!CLvQQPCW--g{TE_Lgxvzw(TM|L`HD_xu5v(q_N-j0+d3^Ri zg7O3TV8B;>?bPQJa`f<5y`gwIDlhj2qq)Q5nIOvV0^9x=C;jMyC0L5Fp|Sb6W|U6V z(@$DsL6H!ZZCatl{EQ!a`#I~+?bdcR9{NW7DW}FcQnRr@pc*u#klZh*fdG5S ztXoyyKd09#I=%kHXDZ-CF9G*S*EGS2G6L?Do)mD{0^n)DqXefo72f55oIym`FJ_=G z`H;rrBreBrn&E?3FbjoO)F5`#cb(a5(JXBWtMT5M;?jLHGv_YpSQtv=vtRC4-q>o4+HhTValyJ=GZ7qVz^%3M>8SrN$p)Cbo zCIkMW^fAt(V$2teF<)-1u>2JR`oc+qZ%c9oeCwgC#*QP{l50oWlWD9_iW0$ zbv5zr!@?TRAI02Ycn9AVZ6w~dH#2ed5xpq1vhNrS4`CRpZ<-nzxH`2I)u76A()$}! zQJ&P{C7Hvy<~*Qt2+76E27R6fCvv$~E&_dG(itSzkY5sDA-NXvO(4zKWB{e;8(e+M z5XBuLa3VjrB65)+68DmMWh#2X&rGA_q+CJrl6ecOXIjtC_lI)5S#Ka3NSm#pv31_A z4Wk{Wt(MJxxll2pf2*Kn>Kc$| zTlnrrb7BmZI8;K6sWnZW=*do6ws&S`&s^)Wp+t&QA^r2kd#8eelR9S#g&8>`qKUfB z%f{pjxD^0<6vF3ruI%ku-PyUir*~y1*%ZhDdlhTf&NZ?y`|x-gYFA{kh>hz(43>xW zjGWjL*1RFF!`@~em@k%=c17||x2i_t!<&bWyI^X`#d0RxkqqW+Za7n&EBi2>*=+S^ z!jZPf@~hTBD+@YdbfOcY7t%!1f7kUd;Lt=I4xM(Mko{eRtI_&Ty3gENBY3@+lFZ?6 z(c8g`b^U_7o-lgbFFgnx>Q<_;M)gXbW5_qcxBoXQbpZRbw;j_;F(;g*YnmloWFG%4 zXF;7jGQ7(~zCtg+Rkad=c&r!M{eCTJqGduoHx+anrc*IvMaxqPFW~jatg!6-xwfV2 zJ1T2?tu4O(s>naB3fY(LxJd_Ju1} zjhwNfy?;ZcZS=UIoXeb1gGG~X`lMZ#OrLV?+$F6`J38lDTjx4EmbS7_n4FU42y({I4v}26#VY3mWaY#pUol zO>ndPx^6lCY?`IoR6c46wW)mHTRtRX=SxU}T!bW`;t&=6LQ|10BP~>V3zfwtpj?(; zR97z5Ym;oRdTcdhZ`K*xgRx_&6+s_hLi~*FQqIRetxE;q@Jcuwp2ga_oh))$q1KR< zow}?vwI!MO6u)}xdk*qv9f;0jY5*D)0{KS9c2UVAk*siZZ+deihz9Yh%_8T0DJ114=S2D7Rnw z51q5N(%Kquj=MqWUm1NrV|YnL1wMn`%Zt+c4C`2w;WOx%yxc^8_zXJqg#`l><#Rd| zcVWYT^xIFR_tnQ$-g(5;XQa!eFG{47`v_aq>gt?G?!_@|W1TCFs?53}JyyK`@k}{G zl~%_G+Ji?i?0FGl*w*QyVK$?2hdsDxGPDe%WnCR!|u_&5{?A19X22X$YnsSjZ0T+t-PP(Elb21)uxhh$G zzpCU7)1U9EoBq>a4=-E2@fzJwL+Ii?+?H2Xlw4l3EfpYJPI@1)DEl&2D2#nHim!BA z$it6%Y&u9!qETq92U={s+8$2?Yjj`9ss?aKxdQNm&6 zWy^xoqn@N@v9+r9?n-Fof-}}Lou5B%c6Q&%U310aTvs=J%9)0fP+hWNSC8Foc9qmb z$g21~<3k&o9LjS=$RzBN;BUg6)M8Dvs_bFHNbj8`IB$vG4~!9S zVNB-Z{34(Sk@yj{@;*qY3l+v0$=Gd%CWUM=QmCkctsu`>DpmNV+KoaWvn;P=!__BS zeivws`oF&UKLTyYUvW7k?^)K0{&1-J{LQ}!9DXkNt@YmuMxq&7-<8!L%NP&5a0*}1 zjnb{PO$Ht$KmQAO2q~+c@n(2{BatnT9^vyoLS7#c6?D-|Q@sJ<)FN-JRco7c>^~qM zfK*Xyi@Z&Gn){6lkmc_f?IFb~Un6kJV@7L89|q`LtH{~>_f-J9|st%BrcTt)Vf+A|17=)vs5U=~ccnwQ(iMwKZW6 zd63t0y6uk^ zkFoGH$>u^|wzkRzvwAm``ifl20%+{vJK;?UBpULlO5cU$m#09193vub+(i-bcR2>lcQ5dmxcTm9 zm}bPp3p^&)uU;i$;#ngmUf?mYe)Vz@6Q5|r#0%U5qpOIC#~O1ZpIktn-eEu$>>h9^ z{4aRT7WoBfv-EhK9?F&a)e^iPF$cQ-eSUo_s7o?PeUgWY>-GD%7bf7(=yd>`zT6KJ z@E0YxdwTojGIq4|e*T9oLuH0okLAYdm1GXbI0vL(>#Mj`ZrsY#bK^Sqotp1A%g@i(v0jj0HL(7jk#QuRqf7wZWtLxV;w_3#1oVZ? zMjt#AKu}}?Hgg_=ms!sQEbvS~^Hrke7a>16WCE6O`5A{Ts@omCdW1YndcKNpR_pmH z5ktcg9{JGfNHPHQL%as=15@R+*zo%Bm+1Pjt_8#%=N8xFLl@ zTjoPrdrH&l&#c13YOTEhy7Y2+M;?vqRn+c6+Ii_N`#T!o95vx$AM$9yl&iYa!@m8d z`XHF{2i@$y{ZzVJ&G=dBP1J*+KjB2#v=4F)UaTKTcZ$_|eqCd=exXB)GN7Cr4@uvs zbG`C~Bd$Iz?U4Sju7XzYqoegR$#iY|>U zagh}GU)mF>z8=kCQ(y;q^0Y~M|-3G=6FW;8z@7RMfM##T=;sWh-NH~TxWkI z*_I6kQbB(q6~MD#!fb9?5-voXSuK-r`|?Bi7e$2^Y&%9EzP&@|+jnw}DBxtl2o7H< zPJHXC{+RGFT5qiV4|zqDc>tWUr=s;szoyn>wXIF9;gj14+RNLLRugSsrst1pPrwsz z^bF4fj~6j1jD4erFn{D2E-oVcP&JgaiBw&q(v^S~+Is*kM3Pc3lLU3Lb~)nB`x4W= zo_s9XmrTu+v%?$vQgf3bhbiP~b@@gLC@oJ8B$AVZ>G4fHV;8M+cY5uLFOg=JNK}pb ztu{3`+S$LX=*h%9?LMdCM3|~Yw3yFoRr4dA0}F*VnwP+pDES$kl6P`Sa=7wQ9bSUX z0UXl4U%E^Bp>ZEkn(hOo`7@2;u6uN7k)ZsZYovqxo?S#2R!2Pb4=(>oG@F?`xiYtPATtnGI*uPI zZlR%U4k0%D>8WQG98JKpNU;oc8+{A zV&oFyLT+xv(JY9Jd71&t*)PlxBonF?5#s!dl%%DP>+mQ*z~KzK+}cDgG|-jI$*y!* zOVPh8k$_p^2CGH2c-|5l?qlDK=CIECh*+b4=e+S(+Y>tUK4n~oVrNU*FRdatb|`_L z(fUuk+Q5VOx*7UfiMYZ8u4q7sD^BKI!ADfq8ht-q`!DHQ-uKp~_K;;BC3zsV?`j(H zbrVS~?LXU*{fY6&mXs4Dv5}r4BGE7Q!)W%Ry?ZaD2#0p(v$6&xP8#iLJl9XVQ8VyCiD$-|D^9b=(qOaO>x{od>P^TKGHPe_Y`FCQjfby06ne+|JHHoKUf^rxqa)~FhQROK% zd{AskhD?+uZVaTY|D@jL%STcz%6;BkAZNQ*Zb{1;>gv91XB%7PlxFc-s@wCj5)851 zTf7c`PVap`DA^{Y4}?OYX$ife&Q$ac*#iynBsi~#(KM=P{hXGSo^94*!D!H^>7S%Os$VDwOs-R^LPi~eBsYw~M_ zfFGriD~d!1n(2Pd)5zKr1z0baTLC8t74U;bojbKBxfAfG^*V0Ro_JfppP|#Y5D9o{ zRrYht)r0ENJW=ylHKll1O5}gd77M1l3Pq)BTty8m;2xGLY+y z3Z=N=ls&z6yVx~r2}Q;RmV`4MYTt%omM2vS1vwNODl%*+3GO4zNL&6&P~Fg$1ShH! z+$;+XNRfe^(_BF7x{jb^?L{B^4P7@Z-@tXCfWJyB!nGH*rxg;t)O8@BT<3_^4IN0W zNkfR%bqzsKk|hBpsbN%y%6=%jD7Vvi>JT)p1T3T;z{{C__O)48dzmd^VCXAfWs;%P_y?A5BK(tjL0Kv+b6dTOr6wq@@O$W7e=jG!R&J5d9Lx( zMwrE9_PFf+$<9KjIqe*r+tgMlwzU-tZQFa+bWa@LR$kYA;;DT-2yk<%U2}PIk+u!< zzpy!MzEG}fAZ?HK^1P|Qo@n!&PMdFV+6XvFE5TuXjr>rN>Q_0mC_mdK>Q}#L)US%_ z61s=H$Opu|Twm}W71XcR?`;+JtLu#V)uMv>)%w+(s9!z9s9!B|`$9cq+z!$>&%+C; z*RP7Y5`pU>BMxtd9z2;=S71REDx#-@aA-+)%^CT)#yyQ0G~Y`VD$VykBfV^7<3xpu ze)S}gjf)!DI8mXZUtK4%aa}wcm*zY~o(f$>HZEY`%B5F8pQclTFoSv}3PCBK1}fKQ z#-&uWe&$RA%B565Uo^6nq7FqsUv8`}ms|mTVL`BW3j%@@HLRI}t5JT^pd@(-f;!J}ACvQwiFS<% z3f@7oopO)gke)ZzgtVTx=Xvn036`^8#x@8nTTB|K=YVH~eK9g{$ZHD~0z*TOk(4L| zX|y2&uNxsynM^&|d{UF_rHNg$v%4n5=Ot5peN*)Ba(B4JfBd^YvgYQ^b7xi}Y9#CR z4CjW{^_EV$XmqnxwW~O@)M{nNPnwl^>;CC9WUnp@X9ETlzPjG}}gN?Aexon^^$CNVQB>~4C$-J_g%g}yh zuV_~rZ;{`$9dg^$j`mhe!{R>E2}b{2N8M*(r&0f$4&%z|rt9;B7c}I4cCYA9zE1Qf zf3)78y!)v3m_4d3GNloUpc&5E#B-v=)o;ns?6~&j-CYaq?F(Jq%iB-OrIOifGL@4HUGr^i^IhEw z9UTkZnU0Q3s;vz^LJ)K9log80MdpE@m?~TY3O{q%dM*#Ah>IULhhi;wbSNHT_t2-e zB_0Cg8!ZGmhyUP!>aD!ZIV~;pt!~RF`5fSpG-^0SPW;H4ST=Cd#gmg4pCmrpC$iaz z_O{7vcGAB2le^FU#OBSPID7XeH(xSz_S)lj4-M@;e(l*qFV$}^Q49p~~CMkEq= zwsn1~f5M**d94}Mm-a=9p`mTFl^e(2XCo}21KA7mSLw<1ix;UT%Gn7&4yPJ496Ac{ zEG4eA>S_(HH8^yiE#&g`q*9f9Y9OH|Vty^+aC|xTXYT6tr&4bFS7MHmYivW$>?Lap z3sKdRdAHf-3Z_O{i~UinEv>p$*L|As|6CFKgV`4A#J1rT=ZyM2&V)-t*u*3|Xh!Es zK!&!#a``mN5zj!0kdq2aZougj54W(>Ik8rTN**?Dje2qP1J>hbEidyFPd1|Z*>w(= zz9>wZhAlUN8qg5fy$};y^c=rVl_Fno__xHw8Juy~$f*5KVSUWy!TeEY80=kE%#CDH z-NisAZIx3doLryb2vr?1m$`K?vSjzf+~synb>zIhWWestO|}=y$zUka>it6~M#Qi^ zUbOpNFbXU8O+ZrnfuR}C&hgVx^piRj9xu|$xD|nlNa`KM^ojC@iHxT>w`-Ntp%oJ0 z?2?f-93j>=)>>LURh-&2lO9MW2h#l0-nHiR!R*%E+t-Gaa9Yh+?4{xPHs&iO@>3`F zPVb&PH$9xqRnqB7E<2nie#R4pPWc{^4YBhRs6UX#=|pF@Jc`FN|KzCtH|L2{q9t?n zbxW!x6LGub0H16oisv*R_Cw70n+Mn%SZk`u26xUhGL_ucRxC*5)m;{7#8UmKYHoi6 zTtAW}CU2fyD;I~8Q@dwoc2AYY64ppha`cSxiEX3V-h+|OI3B^Tw6#~Z_3Eda&$2T# zUwJw^a@q*~?_SdFiQ5aKrQyxx^5)@=(d-Se_DG~X);cs)J#nlZ<*%{sMEe-&Ah9~% z!?SvDzr-ogSdzLNVYjZy*E*_(Gj_!4bZ?jjm*5zk*=^;i-P2f=_&}Dgjr_f?HQR== zr|&uIgpd+RX=#gl=F|%FwkAe)Et}dsb#A7TEmV?Xf$IJbbR#Toh})`dczT+ui;x>; zJ8-rV*ZWvC!;1kk(Q^bwJoL@(6`k!Xdi$2QbuRBtX42668T;VL<;ux}gC|$YCl78M z@9G+-f230|#w%=JT}uu@O9~P|YRHg5JRb=}Eo~N`RaGNf19mkYi3Xn!$6L%9PsClZ z#{Y^WmWCF&g#xiuKI+g8R(L7!8zTD(?OYafqw zk3`jcXo>l4eoga712}hlX>>3WMA?(ICF0eJYGF93b+rda?V8UACT7w&s56F>xa!(K z*kR$m3CbL)Ao=)<^y8OOy>31&zqK$kDwDAuls1S2_Fmf`80pff`eU9NtjE-eG$Js?v{Ou-}R}0rUgEj zbLGALnZ!V*d$rB!^2dBWli6gCh5bpJJ>&X--K~24;n9jLF1V1oh z^;lceX?hVuI#;l|Jp&2A{}6KffPPTckHfWR3M5OCxU=v9t0 zKVr{g8Gbe3F37a16lE&VK`haK452b188CGa#TdyA+Udb^&mH1rWmdDt_1Hz?u3X zoG%BYm+b-0zXODDz6g*cdmBclHiR>c)dih3BtHWP;Y@A%+4;cvbwCK`tNC5$1mkk!K&{E&9OCmSd5c2rFKiVbt{Y3WgqC_f{aM1@#C4BT3A9PQ=b}>%Z zIFF*fi=jDnb5;*Pgg!zizc^MAvGv%M!_XkhfY0Ny7nooWM6!!;QI7b1t$`ayP+)mu z1I_BCjqm7t92mdO`xa61qP_!fF^AiYan>GdHmrHbw;ywA;1$qVu1Ghde)VL`v4qbD z`5K+ft9oQ<7Qem+pVh%BinE@JJiCJpo+D=cj;xZ93&~_ri7TxJX1^)2eW~{LRP}wu z-z=K-Y;7C*O^AN6n-WmD1rG52ZCYVkIa=`>j@d7pE>_=19kYFlItD$l@@zkHUhP!N zv5pcAeD#a)oMF~V`oT~_;R8@lLTE?K=k{#0ZMKvd$;bPG-YzX{3gx#|mhPQRR+e|j z3hkOyj9IdAyh3NVJ3E+!>2dk|{h>nJ)b1tyt1B4`ljQ>KoV?OBePEfWwXp-(Yv5S! zzvlsPy7Wv;_EY1{5)A+ws zntrk{U22;y6sFrs)1+LbEW3)WfJU6*5(Zza2sfliH5`@lU`ec-2D^=~oCPgr6<1Vx zg^$G?#1$eLE}HSxe7D=jY|Nz0I1z|DT+0<@x!Y>7Mx8T?2^ahxw_g_5W0v}Lo7EB% z*X01aD(E>*k>ws+i_05s$uJYkn4>ONi?vslmE%0YzjGORRoD=IA|bs|p^b7Q@b~H6 zZ_qxpPfA*&kv77wrfY>o*Y1oaOgof#AeL;wpR$%pY3$eZ`L6;JjM9Zz^)`OxH}qMG z%WH!8JbYIm%)Xk^)HwaCE^mh4SqFpmsoG_7Ov%uxF7QKZQRG1}?s{L|%x<%U zUA~;TdbUM-M_hF}l_|G3hEmBl9(H?a^%CeIf*$-lQ&nQz@k1A4o0J`Jg)P;y6(#3$ zYZi8!x%dvRTbaTcs#?tJe&b=MGfYq6NS&x9{tElJ$&9Bh+VETFC9_#Rom&hYPh8)@ zf9s>-_nGt?d$g0%b?m!z|4-K9_Yj+`-HYFNdZT8O)&kFd={2^Aor}sEZc}uV0{P>w z^7tZ2>T3{goTrIG9AKcg2L^kf3F-dV*-ua}-MC-Rneh8rkve$YsN~`8mAN-)QIh^VJrs+D*c%fg4->~81Hx5|yUd`9F_o^jJuG!n+iTJbV+k?L6 zMc;z!^m;ok7w9#ZSEk7jhO#d>2R-;{?gh6(HpHhdYcgeJ-7DMDL=-S&zfmRbtm5+3%&7sy+8R!qCfC(vUUY{ z^d(6BC5We}I_(PdPronazwNc1;DuN4`!fCdF3_E>U(SE8t?kC_4&e6{@SSVGZ#V9z z-&gYAx=)GU8@UW7YZtSBlg@+Bv{5F1btBHyBU$yZhuG)jdjY@c53d7$lk}t7>ww4E zci89UhXEHJ@;mvvG~uhV@8H?Xhsk4spCS}4`6#^By<8y|g?xbcV(-r3rU%~S-s~(M zb5rf~n48_Nm`q;&nA_rB-@izJlrsq@6C#!YcD^0L~~DoGiqrc5m2ovCVd=JM7E3PTyf}DfEXv z?RI;dp9;n_pZ^BWO%}g35?|aGJVlaDSbQ$Y6`ZupEzR;H`a)qx=+iC_brx57XLxrL z-W3DSE5+W==%io=;kJ%5GVcz~1TnSv-rv%bKpJVznM^A$@b5PMU4B<@D*EG0+fVqP zcA6>rlfKIPThtqRNX1p$l}ao1yNE}mYuTf6hfc?}oQ|+mpyRdhS_w{cB>1}>1oz;4 z#TVou@ZP)Lpr^u;`29Ej``wOBm`$MeH+Bd-l%;BC-2(Kh@OgE2LXf&tM1h<6Xt!g% z)*cPm0_H%VWtn^J@t&wV8j1!%s$9`J=RPq;*$yVt`<7Zl>8NVzin8lgu9cORxG$7o zEZdcw_h&|vW~6;8vzfxuj>61_{*GBwEF?!` zIjyC&B^pQ$m9*JQPuTkDE0<-K?K`frW-{rEnw>oz`_}Jx&&Kw3|Mbm$=iPo>e%Tq- zUq(C9sww2?OeFhqejFSzoa;)L$JEvp13f!VE{~UIZgNLc@i(%`?p0fQm+c-OIrn2b z%4eO{>RyCOVTNIJ0#_m)GAOA3y)piq&kI+_km8b$X)Ecj8cYk!hYl+-Xi|y_wWR zIh0vBKM{0>eJ)Cd;OU-+hN`6vC#uO&kfd0R4Y_>sObJi2Yo1-w>8X-Q@e6+1S~ zt=!V3`44|2f~^3GtS*pM`TL;rX|OLSL#Pk|1rG{5h^R^9Bo3}Xz*`m(Y=N-c{+F`2 zAfhsUa(IiT@;H(r3|a))XFmVzQ~C#eo$KdXH?9U9nViwAQI9)Y?(k=#?w+;1YuDIP zQ)N%3)Uouq{Me?nC6%^VqO-YJs~TDLbbiPNsWp;psqcv)-tIJ~XY)YECxP%dFfApa2v#DgwV zV8gjF=8F1#nmKK@L^XQ``B|!%e+k?dz`pew;y-faNF2$>qP!=0UiCA~l5)k^Hvu&$ zs;X0hFQ6WD;e79RthkQeRdU^m`romg$8~ldw{vXltmC@ycUAe!neiRtm9C)KX-~Ud z32%NZUmVYP5^i_e?zZ{E19)rRbt~#eyHhtS=>GAusGqaOslSDRtxHhv5w>-BT_zxt z9nO}96Ij<4m%q*CgtakALBwZ2!~BZ;>=6`EHRouAXUEqyXyH$9Q1+Q0-LDrN(1HD$ zF=sAsN1Zu!x5MMKofvP&)}EU&#cVa(0v0PW%_XaQ)Ex-8`^~0~$+O1C&zi*H{u5_T zcCYNF|5tT&tzu_;Tn}1Z?P*`yYO-k#r?JNv@+3mN7GY?BYt&+?G~nZT z1u7FA_i38%5pUS1ZTCkvhkp=?*sou9wI}ZlsZ???c9|&@@cNYNS14gsjYZ|tak5MR z+X1oa8=8+LtNZa*;w?`9FMk=f$P5*^hp4~WFDwqH`RVHG^n-;1A<}*9?d)u<4&Rf* z$_Ux#Id||@(+0q|dRKOItnBTh&%RuHdoJ7F&fea&qN8g?XXlEpjul;N2U3~--dt*c zd=K4{BUX72kIklQ*GXSP3`(&O_nhj*uwSb`DL+l&mclDpf!9*Be}K0q4{XsLP)g)r zkfRF^6{lCzo340N$p5k@sUzm2&o_SE_)hw#OZq*#Q~o8e5PltXpm$di(T5%}ex8y@ z^lt?>vu-l8GC%7?oQ3`vOe&dGy%yw;><{w4U>6qo5!8YpA%rF6>|DlLSFo`;$WL}Yx{!2Q-6mh4 z&!=YCOSC^Q_#FR3SQn>XcV(aP@6<8kLDgza|p> z+W01aoG4%2PM@_pvEEhxLTf?wa2w?{{G2(Wn!$NU5z+gzQ5LJKG(I}W6u^;1MWOGA zh9x$A;#EtRUUlNy%a*q=x1+knB(wDD?y0RstHa`H=|1~p8=;`Izer)}R4S#IK4B%TwGtnnhrOh%@|3h1)=F4Q z1Ir_yC}$9D{-Ux5Pc3?p8C%3(rq569nx5D(KE7jOde_t?$$?b7JC6TxIR6_b@fVvd zdXpD_tCxJYno6l`g_cZe?8zl(j*gzWWXV~hqh~G24Q;yBc-?rZ?2{yzb~}lt-Tr}p^wr%X#4zjUWM}7k`nJ$__`tAy#Xs^oZ{jK1EqYP@ z5%8aehkH!?!NbNHiWp93Dek=qsTAyPW~Veyp~6p^T#dshqj6WjYx9;8rOAA8wl!UF zIU@WpN`BJGU?+QDrH7F3Z>#R;%!mUh>3qt91<|0nb8V%3e7Do>@aO4#N=RU;cD?*% zrGN}y4$*~(6c%OqVE>ND`>}s;71jmQX7)}!KX{2H{2}^%gZ}#pOBgSn{|DcxzB3U- zX0fPe7JupX;5=>sB0Aup+oP!e&@!2Emhc)`l6|_yso-t58=!X(JtAvD(P+8c!VQoG zMK>r}rL%hA19H#L3=f=WQGwrQF*kgnWBUcysG+6qWWqCt0EVsdCPSflcOv0g7SuxO zoF|cVF9`;c)qi(m>w4akNVw-iw+x;%FmTe~5dYMYUT;#vd8^*E>EKFoY5Gq6E)H8i+kU~ed|YWYwouc0sm7P7T= zo!q71=}kNVN|}m}N%WKue-AJFFKC`LqQ*%H=ki_L#Iagk6m_eGbK1C>UVH@SB2`1q zM?-1fo15$CTv|%^p{#Fx1axm%hC4<4Z%N5^8Ssd0&pSO`d{~CRKymL+ez?#l@ zxfDA<&vaLJ5{LKMd_!%gt2tjVr>eQ2FQ-m1)7; zflh5^du43YO~jYuWK<587RJ zvp+KAL=_Kw8+z+5o=~|TD@S{eX8Es=-pJSU-FRzs2cYx%dOm{+!j{@gXng@@ZiRfu zP)SF%T0+5e)R%_+-S@Pzv%gO>{QmDZ(VtE1vv2;|R`yAHP?aWCJ@p@Xg)8x#qxQUf z3cNsCojK{;w_YC$gtJ*s(h7Aev zizlXOS-aJy%xKnZU#fNG(&@z1w&8%+lSempi{GE>jjH2IX5*z9lqt~@XMdKbAfqw7 z(`s61Y~39VP`n1mj;}DHHzEh#?J9mFE&{CzwTOtvkhu-;GY5@2LkoH1$Opi)Y4WGZPr+OWVZ#e-K81>XwC-?M58-Vx{LK4Y0&kO9)<$oW zVY6HkKf&?Ble}#A`l}Zfu3lf|M-a2!;>|Mj3wY2OTc~89H@BhSnc_lHR5*-N$Oqn} zhCN!tMPKAj5leA*tBppQYG-#3;H9s*=&FJ0(meayo4hNQb&y=x?Ia<1`QH1F=^_~p z6zQ$!f#G|BA-(YpSv(y_U2oy7%G{$D0c)Lzf%>L4g|4lHl-y3Azkjp0&ape|Du~6# z-{SpqCXUVJoL(J>HIOYhHqAJT9Yskz8uAZeduo)mcdQ_cSCpzhigAr|T9oBF`5PWq zbX1>8KKG_mxk8Kh!fv+@Z+Z^~&-Fzj{$MZwsk7UE@>WxW4q~7*Ra;w;N9~}!p^Jqs z85jTy{5`}Kop(f>aweyGD>J_tnitaS_=aMYNY7Tj1#Z#v1B>hi5Dh{khryVSyys$$mjF4cWd+xJZluu zEcv zb+kt1qP(hOfWEDss9MJ4NB+@w`3QX#43fSI2HCCumv8pL+M;TJzx{?RJN7c)((mHJ zbM)JBU<&yA!pooH{KmJ@t3PjipP{$r{Mw&S#0%CZ?N%-0P6qCef5{dyiklM za(Na^hr>xaV)>DLoV_ES&&R8m#q%@=7L-TWwdnPTKKDej*$8`oG?R%!m^BgzErUhE ztgmE`$Zno-5c6)TJFM`xBVi%*wn>`dgd~fTv5+zFaVLWmZ+` zVjhs{)BZ*~G{>VXs0fzk%`-(^F2kDl@2UV!e!@b9`6(P?q0JDu+8N~gQ)e=l#E zNR7a$?(XW{_(L)L6R}k-{XPYh6JDm2c*Aa2ErB3`;z0aktFNGX_%lEcF zX$d*P1()?93tqz*vD{~|qyLDsz@SjR=kxAeOhg$kUd}wMw~Y(ErX8O2n~V!AJ-6XG6g8Sra0~WI6IAPw^VO& zxxztr(#tlwoK9EuGwwv8v37?tzKr|YlW%AVyMj5p`BGC1XYsUL-D3TOv6M|1h;wHb zjRGz_a?X|(eae?M#tFKTzUpTP0k+YN2e^W%>g^VGq1zc=Rv+jS7`_EZ0mV!hKI6+d zftD%k4#E?q=YN($3tY;%iL#)JaG-hXk^w!imq{%YAT)BEX{!WT#Ei%5!6pd16REbWGsMO_`-28@2p7Dfa1@yPPk(>|xu zWR3XMOm;XES+-)*>vFbO!hS8C9LVtNE{C|D94_$dNjtwh#@0vD5uaO)mD1Uv6u$di zTC}a07)bt-+G?Y3jkLQh{B6Tcqf+ zeAL+^Wtg#{$Yp>u9 zodM`@{!G>e!mnA28<~yz-kwqZ%CnEBsOb>9TaAR$!RpHJ<3n3lcC@Y7RvFy7sJFhV|X??HUoblCF6LNZIt+&TUsG+jHqp*Jt`}t+Nf+T6^ z3Ee)S)fqi_K&`DzEA5f#iLu+0Qo_c>O|5p8_Dpjo;L8w+X2a;%hIQsNM_TWQA{XDk zXodxyFVmFTEB;iaO4ympQbPa@^CkBLz2h>!6gO z_~7yY!OyN-FwW~LC{9eCo9uEW-x}jI8LEaBO(-s!Sd=~>&tP)K+$sYWx)VyhZtu8u z@k;)f1vTFD>IbLvl8@t3)8e8Gqi-BpGT!SQUsBZARBXV5R{Cr}Uh3d+Q@qs+>ak=O z*nP>wM)4x_RUD#fO2Ergd?z9+Q$99MOn{9aJX*tka8J0nC(K~Z_W!*Zs)@J`)hb{yg^aWl9OQ%=2cpaCCGjCvL&D43%W`G z{c>uLOS0%`p%@}x1T9a=xFmCXMw zEN3Tw9=kWWG|PeGRi>R$8McqG2`xd|=z*dr)`+KMJ8Hl_LnY)KHR>@j5ubjPssSon zYV~{pj`7{@9&IrtrnqNVqs;N)7ncRef`xaAvij7*ppr9O_=iRxN9D*;mu_U~Z+N#wqi z*ta7i-@-?$V&v779BnY%AjA#uIgd!@={9SWg{P;aochudWwo8!ZM7~p7?g7dB=HNCi*)=~_y(l>W~G|WD8iGq zANG=J?MD=0#9b`$nW~*1##T$MP)y{VVu!kBs+9dP&|66}4Bqh~m&4^uPji0jayZj^ zq&daJ#8jB7NpQqC;{Z7l;?n@h`4nlg&G?>(wk8dxF<<){h?p4s)(7aZjT&EH_*9-7 zKs!d|$R>#%3Y`IC!b8|-&=?cjGuoDH8gEM!6^c@9azrJjSR+SRZFb7B2rZ~_U-AsncBTeRTTUXdx$F`mdsuPyOzY|_e!h>wZQh%ouU>o~hP zDt?g7o{$m|6VbU7S%zAKoB- zkn=p+E49^bizm510o8}))zpOaegji-dbsqZM}jXWJ~yYQx-=0Zd%E3ac#C9)7SO{L zo#P@H>IBu|M7~=517EX7KE*|-JRF2?^!bkX(8GG?<@E-QTNJZ{3Y|2n*QYg9xmv^E zE!dWzaA%ej*?Xqu^hV=1+2U;0_{i{xC|u(r!?AhMB)+lQ9lc`g$yQ5DgvAbPZm}kF zQiRoJHimJlP44ZrqW1qPepP!3#*6N~m6}zc)v6ts&+6KP-|BiRCU)!4-EO5M@{sFt z*!P$112ea}Y*pXzsm&XwCO*g7R}R(VZ(<04 zQmLlCr|JZ&PsGj}P*k=DnGKSQDwHS!fmX0Ae!{J;u{>{h!H*rSl9Gqg9B-@_98DF?|O4~H*ny9oC`v*Hr zt|ZII!KId4%<;CUsOFn6&2rY$@8x#9sepdHn1*ciRFITmU`$YlpaJ63e1pY~_Y0xl zh;ou?wSne{NPN~eBGC~Y@>M9+P8#u3#s~P{kR#dzwaR7N{trg9`DY%`q$Py0IQe}* zwk=uG|8VSiFrn9JLywf+JiglhitM=)y7k-}sN>2Ku~U3fms4SCI|(_3c1nLEL^C_h z)HnsOhfbPkvn=lS(!Dl|;{GeT*XBgr@1uKde#8COT6~%#a4$6rIcpE)?_njT&Dv;0 z+SAgIQ*B~s;0>a-_fnpEKngfn4i2@M0r%?Z?=+l>cnsl#5x$eLZCLh#N*n7z^{vJS zjncT+POht?EAH`5R4X?|LEPglF13XJyk(-9%ASR#b7_|b8f>3yHT!;n=Ba-)LVmfd zv}a;OX!F#+4k725|4|E>O1>`HSwJ!#GZt~Ao4#Br!jq(6mvYEA58o0W3| zHPLlEaP@RJ#lDaMfwLIc97#Mx!xU)qLw;8JX6k$vh`!T-ag@9C_V7x=s zpEA*g4l9?+Ctm7|rahOD;~{$6=-9;Y@bTtkE1vboG#V{pZ=4-*M?_jv5~I>0iw)Rj z#e9l|uT<`%-DNaibxorX{h%vmq{GrHA~8CFR42#X4ropZ(a~9vkv^M4u_W7L2jTT@ z94StgBs=L%iKbYnQ5Lj`i#*-ABN$jHGoTlQuJ2pDWWQ{RK4zxPr?AUlTFwz)p zGbKfj6$`v3i#;;JVj6<6%r?YiiHNjYOkU~>`}jm<1?f+E8;I*W^Zmckadu<9uu86@0y+*oz*G5^ z(-|a@sp~l9C7udzOyKD%9<60mmBi4)SFt+_8ji~)6`V||;7Bl_-+a$kD}&Fd-+Zs@ zHx>V_ev=p-8T;?_8#A_Bb=PnFABn@fO}Q<&3ZRXGLAAM*>c2||TimsSJ>B(I9PZZN zOx^Bfo5(}oS+1=6FZCN`-I?{9|3(v;2TeqN)sV)^t|O1sL~aNfcx0dV&x9uOnL7IY zN1Di*Gif4_M2)|KeF6^9ud#n$RU4!N1!bbR2+d6@IHccv0`p|aiP&8g9bvYa!i`u7 zW;#8+XD8&QCE!>|Sd`TonGlAg@!HkSKMblWYANd%~DZTx*&;dUFFLi*Y z|3C+r4ISWxGwA@gQsV|6+POjSq0XS%X;92{tBKDp;gC);R@M(HMKmtSC7izPP3@4H z>YDJNJvyP6JJwZ{W{b5&33Hq^8A~v1Z%&MMW+z}#6K9KwQX*q)(Ft)Osp1K*YAb^* zGX<1*(p@2TnFN+bA_{3@A30V^(RQ)S7AIFmN>q$3PF*SCKqZI8L7c*1YCEE(WMJ{8pB4zR>SLtPYeeQKZh}FqDugO#vm(!l zY>w=Vd?@lzncyx4rH`C9Xx=1u13 z&2O8(G=FFQ#S(5wwDhp_vGlbJwoI_hvMjc&vfN@>Z`ovd+VY0wQ)`*^3hPbQyR84P zzF>XVmTDVqyWI9&)S##lQ4^yYquQb_h*}kOL)5{jV|JrG+U~aJ*~{!T_R;pq_7?k> z(HYUhqQ^x~i*AWt9DQl@wb5&$--!Mw`m5+4qJN7CkBNWN$cWd1GxJ_|e z<6e&YIiAN`Mi(u>$4Uz}W-d{*)~$&JaK z$xkJ}ocvDmr^yGCe@-!^#NwL{-jqQp!&AnmOiyV|IX~s{lf4TA#Fvv>|ErX;adg z)0U;JN_#i$v$SuVW@myk-Fc3)$$7i;G3Pet@2&_}oXhRXb@g@Cxz2a(bnSMhy0hFq zcYpT~_gMEdcZ>TG_dne`+#jbq(?_RIPM?+Dp1wT&FX^|ZKbZb>`s?W*r0-7uA>HpW zdlEf8JbgR^J)=BRJ#C)lo+~{!dDeM0d7kT$&|_MUmL7|Htn6`9j}1LG_xQDERnMz> zKGSo1&-Z(N+4Eq}pEFp7Iin$CUdDwPt21uNxI5#ajHfbQ&UiOtPv)4+t1@rSygT!u z%qKHn%6upD)6D%@QCX>3nOWYfep!RF#$-*&YR+1ib#c~Tv+m0JN7f5j?___yr4WPg|aOE0BYRIk)t=k&U_*Op$-_S)WSXRqD8zU%c%j>xg*49Xdi zGa+Y2PFv27oKJGT&N-T^%E}&#l8R5`+?q%_5LZ}l|L?jRsKWy zhx-ifv$)Upg7|{|1-BG@Rq%s1#XHcu-20aIgs;|jv2UaA*TUk$0fmDLM;D$`IK6Og zVQ1lmg)0lMExfhxuELFlj}$&r_;TTn!jB4f7k*oKr0};QLy@&8p~zK~UF0pQD5@@M zC|Xc-Nzn~O>x&*Odb#L>)BZmcrxXtG!3_O8sStWv;T)vQcFd%BGghD!Zs`RoS&=x0JnH_EULn`I_<<%D*lDvHaHx zUJ+RlU6EXoUeUXvyrQ;Ze#LDS_f#L_!W< zW^B!)HOFg*)?Qb8s_yK%rw3OKeqe|)BzZ{1kftHahdeUmyP*j~Ck?%F=+i?_4(mT` z>99|SM-A^YeA@7bMud;(H{zxdFOT@;tlYC2&)Rg>Pb1G8d1zF|DDSBLqlS(eH>zRO zyiw2!$8Q+_*7)NS*o24)z6muGMobtxVe*7k z6E;uSK4CZJ7dgu){0jT)X@;p${eEVOf;BEzsJ1Xpm-C5DR*J-q z;QReYF8@EG_aW^k!Q&sfx7l!EQ=K zmk8WfaC>-?e?P7}V2v+ZcT!H$ffvIh^(tZAIaOGx)o|yt9!eqjf)igthT-Z}!lyg` zH_DL^{7-;?LEitb-B-v{x^DR@uL5^2c#`fXz?*RWcWxYL{;WF)8AX7;ojL!ldjWa= zZ@PP#Q`yAq-5u(@w;0Q!|CC$JdO#QN>N-)j|4rAXrmx(=vZX^_l|st%kDTOX7~D%l z+l4p7MBqmL?>f2LM=VDkf8>UN|6%@rfk%1$R$kd5ypKNw>wM(=JJ=!rzu*qTt%UnP zbwmR?tjrE!R6XQ>i|>&*JO@_kpF*EL6zW7d+LY$F4P$|HXUi+>-P%|R{|n)UVDFT~ zeFk?(S;H!&Lwiu&0{@3P9KgxzME~c?tPnbhgN3aBr*0Z63x3J0( zXXRV`-{QV6Tmj&>u~Rnb&pL4%PVoN?){Xuz4&!s>8C=O3aA%_XzvF!9)9iG|zhO~- zHV=-c3*8;wqGkUNoO}y+=J*xe@PpA;{=g}7nA0$xIm3qIx&&ps8MJr7{S&gEjxT9U zK^aG~IM}(%=9lAI&Pqix(jNgGU=SMwyRtsms4a!%+H6qkBs=&yX{5osR1QT!(}-oc|;9nWO_!~)!#S(S7GwkF`xu=dYGS<~@7d5?IE^@MC(a5`SU zzr=qEPhE=n)yNkP-*@pTi-K3eZR;8a+s;n7D7@*wF)v(iVWZ*Vbo{lzUkm(l;Fkk0 zdEJ6IuLAcfV0kaye%${Ed>o4<_b_(D?Zoq;0N#Xf6T-h?v5Fk$Uq-uFg0Y|vOH(Ys zAA}rDNdF4JGVXCUh{L)C-+{T#i8^14>k5`__zZKij4yRV1@Su|i)uDN&h1=|A07T* zh0lM2^s;OH-(##XW4Ce?&C_4vOW5b)1SdJzjO_(_gv$fw(??FYfoE+zPYuFjmB$WM0^LrglVic|P*qiLqxR`kidsuS4craSem( zFKvbDd0;0DldWFzl&f6>`GoL@cfcx-q5Rco^fEm)j%-J0W0D8-g=BJQANbR{MmgX& zV!K?uzwy+9uyk7KARzElvY0`n;n`dmdg7I2A$YiY#dzf7`2jk4U5D;7h`G-V;6{!b zSqr4~H=*WXxRdvBGk${%=f5CL#@yHgD&J$sUCoTe!IvwoIA#c!PiD8X6S5&lQ7WQKFO>B~|IE zWGnfKS1DGuIU}7>&O~P#p0s2*bDe#hrOy7&dgr;$X6FLu16z*I z=~FzyWAsFMVm$Gl6pz!B>lxyi=4r}!{WpQc@-Wz(7pL|}Nd2Aat6u${Q(yWyn-jpxtN%;?7yb|N_3a)0 z*Ztf5FP|D48u~}@SDwAt&dJ!`83BsDC42ANJ7;hGUc;Up_;1`Bj!^4fyA0p+Bl*|t zxn|G#dmh-caQBb9-(zg|i*WbBZQ8wl_ln)q8T;H8F85zCd@}@*xyGmBRy=4iHA)>C zWSz2FxkjcYf6CR$HOh6$TIF8lVHFeVEB7lKmCedlIWagun6IA6>V&!Sh%6B9)fY$BX1UJ@^ee~PKF!6LtN>0}w`Rdv`EJCaFD zeY03I>tu`Y)cij70NV&_5zn(%*_UiL`}MX$V>mWQ;=5%P zu;5?EC*pbfRNl_>25A zj67ek1kA$<`vuPy%rvg{;EAj!bP_k_?QEXPa(Ei_?m~?HJ)m#pvl?E4ak3{HhB1B! z@5@H;fmnMCU}y6hHi}oV8ThtB10To6^Py}yAI~Q9!8qwPmd(UFk=gt_jIwk2G}a33 zt%WzRHr~iO_-wWW8r=naK0BYc@_DcuxtOhm{&6|Jzp)1T#=ZPD_IJLHJ;d*35AwU% zBm92$BL(Bj(pEH)3?_d<*i%lHDEoor_-@Fk9=yp65rx3Udb5#50q?RI`W+r&4( za`nAzE8oPP=9}50`~mhj|2unz|AW1Znf?|2H2Wuif_=f?XP@x5**^X;+rvL(U-4b+ zApepb<=?UxZiE&W!OYALErK%}w74i}6c!9s255Cgc7laNCy8JuF(d!V`tv?)AooJk zD`mwziTda-Pddcs85L$FTG8#gD)8mFxz-nytpSb*_X~aur{}uI3lBE1;F$ z#IIzxK)byatK+}%YuL^Ba>fq+PxcOfnY{-sbtiv~eE@CcL;eQrx^HKPunPZhT9yus<8`&c=%|VuDy8+QfX!!>e)1eO@9dFh)i@%Ep#U}BXcvw6k z{vo!A$1zjCBi_S2_q2E)bKT1fjnsenX2W0Ppk~L&3~j)GH@2klt1x!E;7)}Fi$FbU?_SUGuVOaC8&|o9*Ycx0lE#Ywujtqg#YyfIQO~(=fTe(LhXm}edQOYzJ zdyWJApoT0;tBQwCCwZ&JTT1j%){e1t7MqRn)eW7l0QzS+ps~O-;d(Y(i0~PBXW79T zU=^hixY3ByhW^zAyo^-|noiKS0pEf9Y)Y*Ysdqq|=!3sHe$NKobe4};ZEPN}YI^NR zXEC(F`M96OT98{Spv4s0=M4GRA!Ht?TEKh0mU1s>!*0Zpv&3vbV~}PCTs!8BCgQmc zdA1U_BPqTto97Ivp9xomxGhMf5cw70UxE>RBC9_H4=#uI-X z;8}9!4oUs=Siux4sSZ?`$(lG_X0j%w>{ZDxhEx`V?@(EvNz#E@k@en8wHTCGJvf|+ zG-aL0oZT9Qtg9KgZzWmFma&kylX7>1UTs13Y$z-^xgoFlMC-=99;k~ET~d&B*j*}K z@GhO&B2~`1<{RLq0d?Jg^jhFghcEdIwulDY)uE-HjcWsVtH3oNsX#03Kxt%en2+!d z1y|XwXQ920LJA}P%UBb@PoSR(RWI_dr8Sg#6XGj!71a}Sp5O}XhK6w?567tc zD!vP0;$~0FlL~5=uMfJ>-?;dC-6k{{w$u%zJ=b9${qMf zy%W~;W&dn~cI4qb*mmBNXF$Wq;@KFRU&sD~T=oXfgT|51`#}5fV%+M5Z-5-!Q$=>Ew_>xi$_A%69EjgGE!E8K~_2I*y z!Hj?oGm?+O4u`Y(7_3JNcs+EHv3wjK&nG}nI|sW?&xN*j9yAQB;4sQhg?{laZ{XAU z4Bm(@=gnlZ_$=&>z&=Yp2O3=qzJS!q+xUEZ_oyA;HR{CIjuv4?S&SKP2{fgpY%_Y+ zzo3N`^9!IiU5ItsMSKOn7&Fi%c(Sw)v-fZOa=sFJ)oOkPc3fPAdFpEZ7k&*^LD#_+ z_w}p{v&;?97CzuNLF>60bImRMR{l4>hTjH#@^;cF*J0gvH($>;Ktm{p4skDZ%=Ek)&b6JthWT$WX6ZNho1F8v_zuk9 zL!cqN!{3Ge)Xv{0P4`3o5oV7L{xSaqn$f4w7(eG<@Gtppz6W#VP&`NYm4C(e@vpJs z`vzLz0sbvke&3!SQT{VOhG#Qp@#Fkgeu9nU zzwwjM9DnDhxE~uY@o^bgnKZDk*k}<38xuyH9*V$srA)$%FIQTHO+>LJ!jAF!d=V{T z*agt0<3zkj5Q!p*EfdKiMWnK&!hu!3Q@Dg%qzjMeA$p1oktwo7HoHsoVi#g|!yPU4*?iL!sRd7bC=3Vx$-)Mnj_*1D#?l)(Yd;o0=pfjs&2!IBMz3M z5?CTu9LZRDq%sHABUg*RV8wN(A%(%xg9H>JE8yF z1r2Du*dXo^_hRL9KUO{)Nf&wun$RZbMN$`f1XlTuvY**8@hCK;$DtuTiKiJ`#nX77 z`wZ4`&tbhIpJh7P-=PPt$Gmzs_BE}-^8_RIDh|X`k8N1py@>VQOL!XhGFESoK%;t9 zY{zrZ*RZyF0~)0TYouvdFAaj;^_JKn-iG$|F3yL&%pPTrvB%jHwC;Nj>%K5NQGO3P z*-m`9`Ciroy8UXll3m5Fgys25#fPw}eE?_VKVmP6UE*W$3C?a^CO*Sg-^0b{;tTeR z_)_eK&b^nk@UO*wXyOOh<>Fg*GqmvUn2r5_FW^0i+2LBO-(2h_b|ZFb-G@121Ku7S z!s=};^!4xA8umAK54#m7Z6crxJ|zx|AH@;zlQ=4V7RSUd;<)%#oWT0=r1%}HML$*p zawVW(Ef9uvK)4d2L}E2y#*-kcV#6~OyAsW=VV^-O`wP~!yYO@fpn}ndSJzofpta}o+$NFa+F*p56@%r6`Xii zyvEAu?M;iC!WXtSduuCe)oWFWb}i7ZKJ8j0uLa)f8uh-C?h&tAyVv4XmTC8uMDHum z(y0twDZK(;fiJvrUc-#`w$|{<3^?ai&T8fGl)YznWeRjas@Ax#)}&FbO2b!BWUB4Lj<>c-6F^l!043qIT0vF*v?RSn z;k9bPRlcjLjf063^Wb1%)e`!Aror8E@f8?`OmApcqxve%L%PQC*7}OX&|$`*dJUuI z>L@i|fySUOP)1_ZTU$+d)J$dgP>tcCDuc$Moy{$cO=j5u3W_QV3JbjEVO=vU@D@_J zkWHy^1XZ4KM2KJuNwA=*GK@e`RKE2n8b^g1Cq;oesx*#NlNuS4RFNuJZ&9(DN)gqC zx3)-QpqyGL7^%|2%aq#IS;kQzqNwqzK{Z;n)@TgWXw_SzC0U~;=~Ej~fzPMaXyh`ly^RA@UX)?yb^ zUIplB=20Cj4IQ&XdPb3!a*^7&eZFer7*$|nbb%Fki?vdCHLi=bQg{P7)EetU5-rgR zkMjWa-74AV)dW?dB~_v&QKI3?RYtsJb%wEMp2o2uYy@aa)dKmvnwUzoLX^}R$A#8W zp{%0S(jFZk5ij^*f==| z8OKqBS2HdxGfp7!m?s3q5jml;xv9OWqq)O4VOD#?q9*e>!9X=$nO5C(MaFZ8L`BzW zwNa>vuCB~DiIO)>>ek20eZ~e|AgF)pzZhUj)r6|FMqEXL0-pK<+P#)xmH)s9R!tP3tP;(0!ke`sG;4!%v))zvIM6n&-C4UlqRC@WW*&;i>* z1*P>Aebm;NsL@(Ljh1AMmZaLgFj{NXUKnUGT8pZ#3u_CGAT?T1Y6GchR5e<=tMyvj zP9H(gcH2Um59sRT_HZ4ZSH0y(!jjS%7YA4FQSiVMtF6GdGZcLIZ-_A_eV6n>181ZRVgG6HOlk zMg?aQx;HmaRT6BRrJ`m9MTqfND)@xAhm6I9kn)uSGTlT4M`b+_Bd=NjW#-hGVQ^EM zjpWavn-&8Qb0U{EwYTL6P@Il=v1BwRCy*s;#oo}&zkmDP(@w3prA?} zzYA0?#8*(N@m#9$T&nS0s_|T^@myLS3F%Tkvn?c5749(41ZNs-A(pfoQ9VXwp+HLt z3l$Qhx}Yg2P?wlkaT05|R>jV5YHx09lxsyOYmNCc8akTH(-*e1G<6beq9K|<+w_JR zbAz`D-D1jlxw>*}>Y34$f@B6v)R<;A&svDwpsK6jITEhL+~`1`VlIbQS3cSfG{|=QnjAz80)?pDLP7 zpe1SbuPVAeZ5qV2IHGCZ{Lb?clOlS3YTNV`s496uRWWH#g#{(F#Fh1_!UZAt@({RC zgE97D{8#BE9H5tQfL_AXuW_Y5fNN`(6cnlpKwPUVnAD~>wX`h`68oql z7vL1Dnu$-H5et19^FER`!qp{Tp{ivS6c$p)FYpDF)@rIe+*i>+jlxrt*KSJb#-@uw zz13wAN?H|q;|sm14!tP}y{V)dn=YNuup+vN=_04l@Vby2uQ&8Y>(W+A~oHDR@Y zzEF02YH78QP&xQ&LlP)dGb6G4)HYw>3#?(Zao49Vi-1?f?^E?>h`CI@Gs4$zv3E=E z77}=Nss7diP6Q?iE(PzdINoPn4F6I*$K~vKybVj#J)(5cjuenKO&xhk7vU0KNer(x$rmQ z1U5jJ6}Non3@6{2tNQ_~z?}ilN`J=Ix?fPC!Z1uYGot#~JE#9LYH`(T6c9%C$1<~FsrveEMz+UK(I z^XAT*i>J$SKbL`0n2cx0GNozAEdp*ec77PaAIA#7MZs&ZhFRq`Y^p@ zdXVwxcH*tve8haj;)%M|l9zK`REqVTsG6MX%=@ESE!UY3*__s4wtm(P<|EdFmJ;h^ z^Kr`{+fnl=YpZ3LWvsnQh%_Ggus!c8kNh!eY<4GUrOmGRszSE3MZf zMExhoD-$t~%Dm%j(Jk1|36oc$Kb&sRfBtv;-}-;_ANI@Lk6nI#xet{Q-bB|p3F9OL zlV7)>u;=~zPLD?+N9DINljebs_+Pnh3=aEZ>m- z2ftwMDCzHkh-k~l{U`iK)%)&wsdOmUkNEG_0KInf5p;{~SuSIXz+m%M%A;klfrpyOD0Z#4`)mxJPF)dC6xRJFS5l9hm z6zE8ffDJOXOal&MMu1Aj3f7*M*1x%&F0s=wq0v#U)%fqA9Oc+`$p4c6c~D5}V!=|p zPa$iuV?*|Z)!=D0pr6p1j`_a`q=z2xlm9hvuE&!hRGOb~)!R6g@fW0VEI7KL^uNn- z?hJAD_8Q0sY0(&r_|&TWm@PxoSLx(=k-!f<{0ANG(gwP=hX76J^~@Aq##r=U@Y1Da zg{JTy!Qp>EP5Y<+Anf0wWvkU@A$ejU@au=OdOrFGFzQu74agZD^9kzY5PA;PoAlK- z8Cp(lETQ@iwAil6b-z1PAL>pMxbL3gX>p|%)9r`ed@#TvxYy>UZbZ0MX#$ji@IWo1 zK7&$Y7_atf5|lBI1;z@rSd3(WxWQ{E4m@ZhNHDxRY|JpdNpM^msS+Q-orJ+Wo&<4_I9rU7KBxyLP*t zalPo;?%DxsBcI@Izv~cE3lCi@(3&EV))c9Ff zIGlNKZG{Vjy#n}64Zn+JxbAm7?0VF-)wK=(S6pwp-gE78eS!Zz*Fo1|$mOJ4xFg(? z-8OfeJH;)}vE;dZ?lSiPca6K%J8g@gQwDh!cx?E8Sv zQ&5+j-;SA)iv;uv>F>e{Y@&ZH;$v+mV~S4D3Y@THIH4w?1e|}v9YH%pGU5q75%Nj! zZ-tz)u$Gaj3#9%H-zg!9(^5`GdQP+^A!)EXOs;Rfg!T5BAd~sv4)_%RUW%#R;p`w$ zBCnT3s-6N?iCCL4T6ZR4-MNS@U`yC?Kr65Yy@1xB7t$K^3AqNvNe!$)vDXl5Q0xF) zh<$dmeniVP^_UXg;bIB=Ea1V+1q^dVDVv=V*+xkpeb1DIp-PMnWA3F9)2 z2Dm0TDVv*7PGJ4Jabo$Xq>~a6P5uqcNYFIYNdtB(&G7#S>{p`G|2kwY>+D&$=is)% zZHIdeDNzj}wS!3Qgr3?=q!zBn`Ot}Z&WU;0*$4*- z5+1G3>4C!t<;;gGf~$ZV1Xl+q&Sta27q-=|+ zsHchkt*Dv3kRD>`rIXU1u9Z-h?j|_Y0#1NK=Y$+gsK0)Y!4T9>D_X*Gv;^$+$1c59 zxW9%?2j!wJlnzji2jv`4HiEJWlp{eo0F;w(vH`N8x;&3Ki4$s_CW8wD>h(9gmt zAz8QLHrNQjyyU2X8wNKTZamy%&4F{rY`9i9aPL?Ow*qb@+|_W`!=Vlwx5C{4w*d}y z;MfQ!@tYY>h5g%9JgrHsf*S%i60QYqEW%O04%Dv$_3J?WI#9O`@b5s~Qhd~{19j^_ z-BP-!TL+#==xI&^JX1@r9r_VV1&68NFclo8g2PmBNDdsPg2PmBmoA{C*54=)Nh}!QBtH1a3J~92K};26s2ymCWE61X^&M z3XW4DiB!q40nP-6mMGJ5IN&^RXn`^hM-k{cyQP0K(p!u4>$J4-{EC%hue3Z*c0YC& zKF_|SJ<{^TSOe|n-GV*2JNYNtUR2tLs_jCRyFIntonkt6cFKL7^Jph$Cw6a!?$eZe zF0nfjyC3D=$L;9l0#B*%#17+)0qq~(oW-*y1NKP9z?b_t4On+L5i%J6NSrum1jVKJ zM}o%(;BUd-0&btjZ1yTnj)mdu*cqPTtj3+TX1~Wx6Pllh4=Y#@dbUDs`!*mnQ z|5Rd+cLeroPsC}d$$T>4sW_z{0l786Z^q7S6ZU1#g};QOUa>=ZEzYIgfo~%ToV>de z`1|;Mu^0kn=o8;aDJN{>37k)GTvYlMYGSODlRKA7)cc zpA6|&VBfZs`$C*%tiwKRDgDJH{Us#*^GW(kN%|L%^q0xAjyMs9(~j(JlK2La_&ty~ z_RT`dd)PLT?{<2&`x;61bx0N?3;uuHLZxIaB-u!kY#2#4j3gUIk_{uthLL2$NU~v& zY%N-19sX8o-8PbP6iL}mQjXSIx|DK^*4{Tl*0Ch(IFfZd$=XP=Hj=E3Bx@td+DNiC zlC0%y`X%;7%T}LAtv-obeFVupg5;j8wR+j!Q%LR(lDnDYu28E_qgL-E>6=LUE|R{R zq@PaG_mK3>UE02E?>(r!_ay0Okn}UDy$fpZS=8RMslE52_8w04kwf(nN%fH`%!xic zn_ZNMIVIs09ePiP-qa!B661(&myY{FhxX~v;WI!7LvdOv$8_Au0F)?nC_;y9Is{JD zxQQt`&aFe4I+UkFdf5`obldd=ba?X zQ;B!z5N1vd_qYxLm$;GWg1F6kC~%4UDfAf~_o5DM*P$Icgqc^%1M{y2ffp^6Lptt= z4jtDa%(QBZB!doN*41!!9ZCp5o}Q3t4qSn!1b#nR{v?kMWuFd7x+Kil@G)m=F)DOu z3g&TyCN(Avf?o$WA_=&pF@&3_he|qd0lJsqzmxPK{5f#*lNP~WrsFQrq19)AuF-Kf z>d+b;TBk!Yk9#SP2X)*Q9ePrSp3|WqSFh{1&j5W-CEu$<2Lez?8?OTHsH97dNluc| zO@@?{lL*r@=|lh*43&^v1}66;$QXdsxP-HGO@(kyqAP%pJm5vY`BIAjN!#eI!9Xb=I|31c6J#LVLS9IK)I`p0n z?b4xOZu`L1VJhW89Xh7doeV%JLWl5$YgMKxnOKbHk?c_yo@sD1Q+&XcNnFYRxEg|5 zG49SMXqXO-)**zZjHl4aU2xM0H@ge2Q{p^mr5>~^#9OLED|G039a%nDTW?O zxLXN#M;E#c0bGg-?LgekaG#_Ep^aT|kL#h&=+KKgv|WdGN+@+i>YUX1sTe_0cI(i7 z9XfP6lv5#-F5YD0FJUW!ELwath6~Gavse^Q= zPKQRMj?qFV>bNO7)Tl$tz{Mp}rk-}VB@#+qtwY!7(2Y8T(NU!f8LyTDcNxW9r$hJZ z(1SX(B>;I4BlSs&@mv6x`jQU4u0!wW(D#UOfMR^8L!ar;ULBHjMA-lC zdLjThj5-7gHB{mpk4id+MaRYH&`2HXsY7V7T3n|N0jH%B#06tueAQwU=un9cfm1DR zm5v*tLqQJ425>G&TT2hUTZ5+Q&`cddtvZ%FKKu#XW8uz0yb}k}lybev)q3Jp_TZdY8s8ffoMoKH;ZcXb7EhXHFE}_>G zZU_83oCf$u;7$>=L5DW#&}JQaT!)^~p%-;%yAH{e)$}B^lT!Xf$L-dk{Q*dp9(ttY z;^}6fU7<1Z@HI5f&}u-}5bj1DC+XJcG1d`u zZ;(;O-~f!(DLO2zLy)!vwveLvQNPdpfjBhh&T|D8{}nxPyc{8H#g@08WMI zt(6;nWWXOn5qhXihvEoI!5gn&+)O>RjG$BQ4epKZ&4BmoP>l`^)1gB;G+Kv_=#Wfh zyi6s1OaPZ|3P5<8DBW3D-22cz^FY3^C9onHoJ9P-7qkA{SIEC^#2->eh7!x(z5gj_NLo$Xz z#z-F%z@?jX$gV>PI#dCuh+=qjC|if}bx6_;B07vbo@wbA#nS6^XoLQug$F0$!AP4vAxM10~=(s0! z=s6vF9Vs6rX}qIDAL`I&ItS1p%?;`We!M|q@B16zUvUaMh}l+uU-%#R z$HM>IKM(!_^56I4JrihNhkq%)<|t`u;lJ<4TXIivj7t0t9EfV5xyKKl#rSeyhMc1hz-K3IBb3%@wJ^c0Y%u2pQ{9@}DP~XUYFS zTnGH!iUt1HVh{Y!@wHRDqt|jl`h1d-2h97*CGZ#E3w20MSx^22@HZ0tyx0f$CD=;m zY=d$D{(eQ;IQ(2`g1<^J!2gseKTy^I{s5LoIeQIq=j@;4zfHcM{O8HvO8!^mzfb-G z@;8z{TBIZHqXa)m{nlTk0O5~`Ogc1G+!e41ESwR z@P6_?C;ukGe=1>Yb2fqg8D0qgSqbBN(2xmVXefeTr7VPRH(-x7FET8W7z5s8iWKE7 z3WcordP6S!ua(~@6mNSF3$ld|Y4a-CinyIHMar{;hx8B%sq!k~p-LG;7)V=GOCDge z1-yw>#L26&&G0)3K1a4d-XiM={-yAX2p%9?FCRdZ11QHLN_haa(v`4K#Ca2?;FBd{ zzsPh%qVgK>K1$(6Lk{4chC3z3fOmhu%ToBL6h6w!M`=1KeMX@@sYE{69zZEe)MV%h zpBYBLPbYexY(@M5lI>+A&&w#sn`EEjmr=@>QQRAd{st<=4aDq01%zppotQYHH_K z%aj3wXIN>0BguI`-p~UhQxHo@w)I3=PZ%@hzKb~A zMI7EsxtvG%9Kz=iK8Iw|$KQf>ew=6=#95Uua&bK?6MfN!C zp+d?R%GsP}5D$w5<`;Gm;qRB_Vv9&;SR_*erSvCCK7p6|#{J4#f{{MEh*B6yp|eQ` zSR_jUN~vQkk{rSZ=h&?z^W7;qXIGKNautO>OF3Rox!fmdc$(@{>C#C1dRn$Uwo29r zTSb^vlmB-ltoJ#@Z5ib|N7*E4ln2Sb7HuG3N)p!CWE-fHnv%f!M21q?%Lrda zm=yjK@F@iMCwzZ`%_RAcN%BioIa56@CE0#V^+@9_`&hTY)0=2Ai6)a;RHmd6b;Mf|ag|9m zo+)_~briR!jLVLY43Ch+jz~N(Qiew;ZWX0(ryhEW>gzXxf2Z}rZ&a>C%H2*SwG(WU zZ4&AH01oZMRlZD(9Uu%WI}={ELpyP0r}ElKGF8eagqM8wAU+M$q6}gM@CG46&Ey*t z2VtHk|1S6@qA$U|D%oq!gDa zf`<@1pJ1%3L6c7~*87Nc73>Kj7OXsTzKig?h$e^NJ~)HJ*}EjqcO@RS2xYyjl(1rx zGFPaN!ww^0QA9NT(#iwhH4}&D#Yi9;_!siTKi^0GLGllie~kQ-(iejK2=Z;@ z$4Ns8BBiapu~pRJr2I_bmZm{OX2-(m9U`w|;rtHalSU>)8LVqE>?n<_oK));n_*kP zEp}Fqfq#5>f(9WdMy4>!)b! zVhdX5debg6mSoBQW|PgomHRbtA6Zm@qtScoKKmSBviex4>VC{F?YAKpU`QIR^Gs;czk} zz^{6a`E-6Ig*=-lPc{ci6w$3rXQGMx6EvnjL1X?CG?qU>WBn5}wm(4=^(ScT-DuPv zi=U=N32 z5FcmmxiXE?ktfu-vYVWmGGSl=l`A{6SO(C@STEr*-~AZBW&UVW%1g|G9n0Hcg>@(F zr|yQ0)I&I1b6lK~^PTb{vx-B?99S$(fz8o;^wlb5gfd>4hVNq>K}vI2LRY({(w3Z(nfDPSy{zLvM*txK1+=Slt6uuMjKjafOvnPpISdV`4bQ{Q`7pw};fkk1} zg7E*GcaHJ94y}O;toh+%e1hMAy2t3K+^B4TZ=$v^9=K_8M1zH8sU1rwUXX^5mh=R^ z)`#c5KV#px%y9_CTO%M$BYM zgI&B5o=bi?$}V@jPlbOFH7H;Mx*4$qtOkFL#HC$|Fr03iC9ODv`*i3$#bO{JkH`}x zVi2Gnus~fZDgpI`CF(L!1t-`B_+nIl zF_?vsz3UuE7SDZHgl1n@S{EkU!r;iDbMynKe-y`leTZ{zcr) zXYx*Am$p10<)86qR8y!|)T|k&7@80VrKCO440_lgh9~~mgD-cSGurdaDL(-T{D6~X zGCw=zmjF5o(wUAlaT)@Wnk(jlyLnYOYRdND`2?}873CPQkeuHS-S8r==u2lAGe#C{{R30 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/fonts/Quicksand-Light.ttf b/luci-theme-alpha/luasrc/fonts/Quicksand-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d4b8dbf389eff952739a105fff38d23ce955278d GIT binary patch literal 78384 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�TP6qcsU{dab$uuvtO6V2m%Uf7v(k%;Brd!x#(k%;h@%AkX6{+koVc$rspEm7U2`5=D`}p#1$a0f@ z@3WyVY_h4Uo@_#4p>CobtH*Kk!1n~_ObO2EGgp)p_adE7whz?e9-3s}ENc%6YC#%* zSX*9DGY}}L$}7u>1hTjbzL18xg6dFhkw3@bgijQf=bfF6W%Z>&E$UE@XFAvie;rsC z@)SnPE2|BM8Qx;|4ACv-SU;z{FKeu=(F4^s*>q6%+C2tTjOZ7Yd(mU;1A(Sa@-WZh zECIQF2=h!$=pC$uO<0`@}W!>iPPcSN44bxx#HN(f)ClKZ8)jytdm1yfW z?saKy{^7uN;^)WmZ*p?nqR4cfs?l^GJIR^)l4u%tUm)T%)ya0?XX?}J7vh9C`UpI3 z1_gd6XD(CW;Z0ND0soW@Ka7*1kK6E@Z2052#prn({z)7Dr1F>a3-G$urr&1YV=1f! ziYStIcF`D9T*jvfZ!kh(8D1qg%$z}U`66| zmv-$KT3S@zR@Sz@mvswq`QX&rrs){{kg|?2BX0b&q&n@)3+^R2$v}c@{P0030|`pf zPC_4FC#4-hN$1Nto>1-+Ho|N=%Ke<|4+%fYK9c^ST{p=e34c<#G^-k3!j$=8$sLw^}`uAm4xGAYEpYS>$_!%`!dK9C29)V@|w<9lw8 z%GszhB`%|23B$uwp1LO|Mk+VQiMxf^eb@kiayJ~hni_Tjf7uGP{j^E5n+5(0;m{_h z5hW#*s3UVfLAPxY92OLCwc$q*hbebsU*}%*!9)8}hqCWiB<7H(x!?#EW{{>6AIZ%V z2n3RKB>ALlKuSF6=SN3p*NzUYU*FKNtgd@~6Ks5+Yqqa>Q&`5W<@Ya%wXepNe!e{1 z@z4@3iWqr;&Z*LoWcT1;clU6tVY)6c8N>ChzMJ~Go2q17T6sgbbfhPBq^Qu33n_xt zg+-MO!d{>isaM3DJ!jJ9BZ|4_4mkOT2oC+b){1@gsyj?*j6XX!A*9~t#7R{0v}DSV zE%{YY=!9jrO``0R%7x0;L0y4|dQzt5ZMZEIaiFu%Mpo*fOzMsVQlD4W+8&ThA25z* zWP0!;y9bAN6EDbiC|ZR21&`cT((6y*MqcR^qaIjgGCjyH8_SekCvAeiD(BfXH)T@i zyrKtBC~NK1#!TvNqU!U@F0|74VKWWBxOGVz`W+kk_(YC?5{ATua=ZkM?c9hhH^=MA z{TUiOZ9`w&PS&R!^G9sx%WEx<6i!gt&=;nYu#E@P1MCgK-E+rrx9}Z>!O!4YFz-TU zkI{zGJ8-+D;xiil&B5iCuX!s-{rwWK&`)7N`sdZc4P}X3dVm z;lb1+ArB07H-c7*s~6tACMkB*rp*B5RQqgwC@p3--;flX`ki>XM(a zty5DcoisJI_0F6^him$x_fB81ba+jz*JT8B-^xZr2)3NMTZd9{8##u-rjm4tXEM32 zwRK(3waa#%oVC3~Zg!x9etV&;CK zhV)A*td1)XITK?DPlb1^hvCLC30G@ucwEAR6dE2b(UQALoaR7YU557#A2qy05) z6S=gnNUOHos-Du8{$yiqUlV(O)6%BK$-0rjx&*1;dCJjQR@4!VjrDa8j3qjjLPiv^ ztJoOYCZ2vrer99w@rL@bczmqBVLToiXixO_C)x*iP196e-BeTabVI{*bLZq_XJT>^ z)&X4yg8*<^mCOBqb5U-c1C3VMKD-VX4)o*0E|0U1FlEouXTOs=_yV8)*O;TN$)P(=v zTweFbG^fkw`I-|33?a!c)ON#$^k@fE#>{)0sJ4E5&{=X&Dcg2R;;fk*T!`Oe@R9`wFWxWtcj!d>p#`D|Ld&Y_{r}kDvRNSrYCz>Iyp8W-

    T#woGlKs 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 NAUI18j$LT!{C_jZ+@$~j literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/fonts/Quicksand-Medium.ttf b/luci-theme-alpha/luasrc/fonts/Quicksand-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bd7d2bdb87fafaceb707447f96a83670df36a8cd GIT binary patch literal 78620 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

    e%`GM{bSH19>!B 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 z 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

    %dSzwbWAI==ZmnyzyO+&9a;7!TLm8qsfZzMc75y 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 M07*qoM6N<$g0(Pgo&W#< literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/mobileview2.png b/luci-theme-alpha/mobileview2.png new file mode 100644 index 0000000000000000000000000000000000000000..cc7a2e59c3f4b2a17804edcc6bf2dc1abd733444 GIT binary patch literal 243872 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 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/root/etc/config/alpha b/luci-theme-alpha/root/etc/config/alpha new file mode 100644 index 000000000..4e9a19522 --- /dev/null +++ b/luci-theme-alpha/root/etc/config/alpha @@ -0,0 +1,7 @@ + +config alpha 'config' + option nav_01 '/cgi-bin/luci/admin/status/overview' + option nav_02 '/cgi-bin/luci/admin/services/ttyd' + option nav_03 '/cgi-bin/luci/admin/network/network' + option blur '20' + option color '#2222359a' diff --git a/luci-theme-alpha/ss1.png b/luci-theme-alpha/ss1.png new file mode 100644 index 0000000000000000000000000000000000000000..075f22d11428ab6a44625faf14e8049e228c88fc GIT binary patch literal 776425 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 Nw94lx2c62!kSpvsJ66dk(WNwphs~idnIm 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

  • 2wXg&Fc};+QGa0MM0;^fdzYhw-@wsSFaOD|5;o8cS?W(H0m94 zd&YiRI(`eG)7=IkL~R**tU|4{L8>$$S!ePzFI#X;p==ywqVj!2FB*r(WUnm&h2PRvD?cuk&RuO$a+h z_vNTih?pA6n5G39n=nf(ouO5{*6NEc(^RiGs4R+dZOy5ZHc{?qdd)pDEo(A`Ne_=4 zv+;r5Sw-Q28MckFwiBo#l`z|NvPa!!H>IC zwD3AsXBe>T!We@%*`x1kv3Pfm)0}-y+)p9lw^~H!;hSpRGW<*xOdJjkWj^26on8)s zUJd3kZyGP$R{J#Y?;m_YF}w;%j+Ry*``L8QfR`a|vOeo_89m(*do*Q9pF)6yR$*EH zFI{^uAgXdKmSAmVIR*+_wCLB5lImEk5r;KpWZM$SapEEv^DV-sJm$!Y#N9(A)ByJ5 zLJvzRt)l;UB3C_u8^`_^$mRXmy+^;YW#)s-MZ7lt!~+9J$cp~ugOVBh`7ffrib3&6 zaFXgDG33>dnfH;Y8F!==awc?v$8@zo@Jv617!K^(CeXAcX{$T>S!FSG8(L@htaU)e z#?0qT0bj+Jy~@u8IhvRbY(49zsWGy%6e^t?0;l=o8*IbZ5M`7xmX(50&jK;T-g=4-oHil zaC&Cg{9e;}xB(7!P|~#<_+}sgXUr%N36U=e&x|krm5XWEqUv>vI$es-({23Tt*+7S z8g%E>vZI<*{w$TL5+YtR}Uk^+s>R$-stOI4-4qD;ixAAuQXCT)R z4`Lk&tyQl5a-wgj(03p0v~9U|hU#VLV)u30*jW>$R$E^p|aVC6d0? za>dN%{GSEt`Jy4kkbDIi)2EbhPG7JkG%>dm3Wa6Ho-!O!A2JHh3N*yDCj~oUUvh1tq3f?GU0J z2o#Ptve2E3DzWeI8}M94f5kE6DgfftAAf8!^J*3>t~1WA;pPP#iGt#r&S$N`zYTQ zbNdvxWeS&Xpm|Htbq)SrR#PmxjiT4^Xr1xT-@6kM?qzEiKf9aq-N3UFW35!Z>Y`%z zj>ZxDI%WmHp=3~0Nhvy3^T|tGLIE7Qw`!&I!6a*rer6!eG?T_Ov(X2n#j$BY=`R?G zk4rze(>9phWXxzjMtx~yBBVw>Y z=Thi^I)D(!7p^}zDsh2NL5oGY!la`+&_8?|qPe@Gu6LGw6Xyg?=`m(-A71T$2N4D> z9VF~|ebrily8%0YG3AjQQW82UIVN;=mO!-1ssAyYw*n`(#SI8o=`!e=c1ZQGg*CTJ zR-uQ@ynJ+B*6g#x&Y3tp%_~EA(=z(`@xW&?5UAqh*4BeIDhRBQVT(}cCQumex!N~u z!SOh?AcZ1=%h&y6b6r{qGbx|2IQTb4k!_uVQOI&h4fmtGt)7{`UKfaH3%av$;JLZ= ztBUTr^o#;4aX}2l9*=ax-C~xA_%sYKT0Lq%A3NGo>qi?O7v;)7w_=Qi& zI;n??-CReAA0>e7Id75u;b-&j&t{9`b0Bhy@iTv9OQTz;z}8Ez>t20JJ0ga*%OxZ9 zSsHjG?BLgFhIZyhRBPH@R+o%O5@3oTbu13B!)|$yI7|#X^6G_8XyLi&{jhd%`dAYI zaQJM-bo|(ujkQsour+WRv>lW`d}m71s1lE`Hg*aJA4SmhdmG+F8rSVuyUdM@*ugUXEm zFpN;K>%0GJlsDK5xJi0_|A_oMsLhzspdeKWH1~xMc8fOJx{}SNQKX4Db(H2YXj0S}Av^DDBpj?0N*OuR;DlLc=U1C=mGsI0tV z_#UjVW0kz)>Y_c2qwX<$6wJz*My}WvST-@e~i975VDiv#gRw* zYI5&Sd-#;QP}gp1#Ao*(p{`?3Lm_ONoB92o*K=QtUu;p=UB5nc7-xry1tc@7y(7(? z6DU50-^CDcoDGd!Xby`}I~-la68gPyuC3<33PKuuzX{~E%-^Ab!tXos23lG=Q4%i$ zdN1GRa<*u4(D#~z^UtP7Q%-y?#{$v(&fz1*Fe?rEclwhJczuqm6^0EMdO$#B(R)RL zMX-5>#smhl!I2*oib>kdW7A}Rc)~8G>@p%IGwxGxW*KwxE0Q0F)EuUEbqJn9yI4puGQqOdP>IwmRo-J1ZS@} z4RrX9`SF?capK;S7{3fdB~K*#1{)Gaun!r1K*yY+m<7Cv_5Y31OM_fNGeDVu(uIA= zWx{Yrs7A08Hhtuy>|ypKv^RB(`5z+lo^Fb2Xn&Qx-~Im$HNXdJ-X`d0*>3xD5|ekx zC>-c-{Idno8n4TCDJ1cw_ee7H!MlOhE2fhtcZ;)A%F=g-b8Z*N2JeU_ixxHgcrqVB z9Y1;s<><0YLHJtwHB*rDM)P>>6|QdEF%_c#1Wf7ex*PY1cIO0lOkwMK^tsxmu|{&v zTEJz1JjtG|`Ws~O{Cx!fH9Q>*IRJjZm+h(hm&1ii?Z(ULkMH_8o_)A?#hS9C z9SJ`hKX;q(5R&`dU!DZRc5G}+V*X`_d8w{j>#{`Ow%UQMvsG@x_T2K3{6>i5m>4L0 zT&c#H`VG{R^R_`99Uf=k(b8y7Rfj_Y=~(>(*Y|_ZGcx80nYCON;3g(5yfK;mM+| zS#tl9-hKFTH-VDvcbe6%Nj#!+wI&*tq0tfsU^Ye%R&zOe)Hr)Cb>AF@$#p?|t>G7u zBhAD=Q4tQCNt;|W`a>38YcWcVDa##xB1pFHF|eq$fZI^sVX95ae;fl9krUkZammh% zdi~)k9b~yRge^Fj3}>d`vycvgh=8pC&D;s4vMBS*4CL|agO*7iRK7|Hj!RAlzy_tl z(cm4|3l?mXX}Us(-LAfML_?n;o^%g}?x2|wFa2CyH7qs5P(4|;uUZCUyP|PF`e{c8!g49t+=^p&kZ7$cZy}EF|2?bAMrYfk%(RSTHy_Z_c=8N<@RhFQ{uraM7nT$6;1zJmSLW zfn-NO|L9EOy+`~^)%{u%f*DM9N}&Pgq%|cd!O!AHZJe*!=MwYGeq--mg&12n!Q{FU zRszQ9-|8VL$s0&5LYfEZF4erwEh94;Bs`gXZu;iwcwRhK|3%aSGsh{N)PJxeQ<`wg zOjji8(e){4EurI~qyO1QYSHDZYy6;!GevuiT|EKf=QF8Wy7Me$t`mLAG6ixiza1>y zseM5 zyvo9nDnWvcyeae zc{#JI<+ojpae6Hk$CkZgj9t4p5$iyF6G8T($v4P*EcpgaHmOovo5{QTerKMO(-=!@ zaLu%1u2!}tDk>jGlMcqFI8AsVpqE99)v8)8o5^XP=o4~`!Y65%&DFTv;f9yFW{ITE zsC`w(q}XJx{^Suh;JhTKQa^(;tWF=QdHyYGoM zdJGKB;VytInWT_PD^K$Y)~THnA0uo-DeS!%O_SB^`3s^FU1Xo6FK)%m*yMV{*V%c) zQ(puyLnni+`YDg#a(Z(MzSjQEaM|_9zV^PRVg8+EJG0yA$u`t(Cizr5WNAs)#T9X# z@F=czG4GtnF%ixWf!EHxOEPqxrnjEj-_)K4Uy4^tLb>L?mCi_58t#g9eZ2-I-=9x6 zkfh?bqQF6PgpcgtfjfPRtni_7!L!-nJ*N5efbkkN`0FAb9b9Omhn`J<4w~k$y;c#z zvB!CbkadU;^M!Bbzu5I=AU3KWj9oyE4CVgElFRo($``I*zSnh+@%VwAT!`m;Ca@6m z3Hn%XMpfNtH1{W$N7bC~o^@*VwKHYd#Tl~`Jn%RwqDe7gNg+msaf|~k##;U{qffwu zkFiQ0UA=$$j|YCdbD3xZ)PF-5`aqdLHkns;eb_IGYY|}N`cykIDFB~*VMHpD-yyu= zix&kb14FUJv&D#seS>8nJ}eL@XSKiIwbuOOzx0I!l0AsNCQbh2PZ7>6#pywHrX(*>0A9P@V|DyM^tbM zgNiK|+3VEmCq7S$Yl_SED-ZDhr~$VgE?b}L6ak(TwpQY1i`ZXrJ-Vqq(rE8nAcmjk z0$5vuT=5^LHrzczd!Eux2tWnmQ-M=j;T#RTsWE&<>Ec@ZD?_{|2v1J_LtFXZWyTnmXPia>wF**M{>ZHznB`vGAHcfcXXEG6xeU^@L_y=DJ>}s;$p& zRC^qUgS;g#hShy{zjuHbCbV@{AyTitZo(v3gfY!#d-qJr_ zznh|17QuYHa|XYKc90vxHToGBE{4LGwjTrf|6E4JdSSE4m&wq*yc(k75GHQ~Q>Snu zrevWXWd#T`r}+b-0RN)V;<%NQey!d0ZKG}5FBL=owf(tsFum6A?frbgYdiat;uH4N z{YH+n{VufaALKfr-!@Pu-O#1b5a2qw)@OwyTBk8@lLM(xdlghR74u7>Iz60&@~#qM zBKYn-V}$}^7`Dy>_Q8`_swQ$YwaAOUcxH%Loa2w`o^E8CaxX;)Q{0q8`o#!+z{dv# zmo>>|l|nt;{k*CV^XSZ0Y8xLsTVsLz6!_Yj{lF9cbxq4R!+MZx?uSx{Xc%eAae!vY zpr9QP?OKt$OVEh);ggaV=J@i%BAx(_)VAjnB!^D<&ab7ze@IXqA8+PIL_;9)<1M1? zOSX4~4{P5u^7Kq6nP5QlF{a1~2LU_9}A zCP5q?wG^u3u$W~i0!w-G#RS=j0;s9&kh*s9TizxUveHNt&t;U#0Pg!AZr=>=^hlm+ zTm55SkiNA7sY40Z&HX{W`SOn zW|6nyKFOenvipY7;-mNdj=$*6yT1ITYn8nTDl$vbe-*G$Q)doaUgLNWp-4Bv3pk;r8l==+`h&|XCIlo^tY z<2Y$`l-i1PS?R)k-Ns*1k2Rf!W_@WA|sQ zG=gC2kG{uhiVktR1q7!=7T_2t#MX4jbdq=Vfk`BPBxxWUnTMXNg z$ZgpcB%0U6qae~e7R2@3oP^<4YP7Wu#%T~xzZ31Z(5)gkh3u*B$OwMULTJzD+>&}D zzWnngYQuPwr1zYAO_G`OS=6F>cFP6xpZ9JQfG4ki6MwD!8T7IPc)os~rJUYux?0q= z%c^*7U!3vG+9l=qXlMrO4t*EyubGk{l6-C)HW*!Eg6a~2!*aIsGh2#RO8bY_E{QOA zQ=OAAfio_Ietp+J6WY~TX?Rn06jA1Q?Q?UQ=>hWo{&f)gDg8s5LkTj08Pde(t7dZl z_0`|k=i2DqX#bk^sor;qb;YpeXH%RohA@@?UotY{uyQ&*Y0gZ~tI=b*tDDMin09qF z4QGw%hlz)Yg>JJ&eb359(aX-KD!s>MnekR@R^H6e#LfFS4>{5N&Y!9-hiw>5y%^DXgbmcl=MfTN7ieQ@9;jG)cG>{ zkQ2!E*+RQjgy-%0vAjBW; zj2vgPfH99gT*f#5z(>S^4rZmCoKrlet3fAum|aEpIYqKGguK5+5%-eI!~I*RgUYf7 z6WP;VF{aJN_Q|7OS_jn|)$b?!ie4^?=lm;<9M48I$FTvA!rP|`nLS?`UGG616|~Ig zG!+9CUbeyCB2W`F;wE?TiRPGuMv$B z$6G$<+r^<58j}w02zYHiuFO72dLPQDlwLOz4$i!gXy^;K-Q)8gf4PRzH3m!J)Y@p? z6N%;w|7s`c)`^gf4X%`yFp0I+EBi5_h~s_IWH3S3D0M;-Xv{&iQ=rO}^`vIi`~(lf z`zts}FDd{DXVZ(~si1hV<)CUwfpYt|DdCBCk6Zn=N8cvm%c$1bFuLbjjnlj)C$^nK zs{>&GF2pcLR)>{PjxE*l29kcOaPW8K1pi=%*2XS#ONYd!tcJxOi>#ueW3E*;gX^1? zIMmxW8IC{f$^P@|OA-lc=g;J4S(V!ft-_aW2SP1g(dv_Xhb9mC|NeS8Li7bD zaeWT)I8O;GoEyB6G!lCMZPQ?^Z?ME|Sjo&X61AFGJF+5~1{Cic<3eY|ife%m(x|Js zLn)AdZ;*+}l+l-XaKW`oBEul2iMOq|S+GK-ox^ZoOpXvF2!An_>K$Jt(r$lTt^qd?RNkj8^qjl#U1Zm`g7aVe9g%#_exf%7Qi zV!}Rl=d&mG?>3=qI{@Sd0*F8 ztQ@L~w-D(i7mKPUI9@qK)zptH8^di|lxQrFFnBYe|6o*z zVo0(PEIWb(SE3jQ*&gr}(KbAn3d0f-&6;4h0~?h%^z&Oz|shvKE&%H}!!nO-!Op?wvomwbBY)XVewg%nb2(WJ!{_ugt)k+J+V}q0A-r zlxtTwB=Lpt9Ah(=b>`)ty*kp|gtk#(iiAA%j&l5uF)b z<1&Vx5fAc%)elIK30ygo8@>snS@ZFO9it{b$KQ>}HbA{qz9|*tbnu=l24)QxJ_>8$ zpS2k0z{BdQCkaqiv#fyy|F&=x2W~KA2YDKh{QQ;)8>9mdGd>Uj1o8>uc`u;9n=C(q zGb)kaW$|l~yNz{V5u-kFTZ0%YY>2tdEz{(M7rkyBq~%kY}27-4CPPoX#~;u(ic3+qEp;vV_OGcL>?g& zdhA<`kr(fU-bqHYL}_5d&4w6sA9zt7Cp(CK>kBq42sRj{i8S?ZFjFz^*=o zF9aR|#yAGE(}-opY7TPbK&8OfD)P7lxCUW5?d}0c`;>+=5PHKn=e2f*OT#lYZ2x#d ziBc5Fz?!Sa5N{mbuTX*i4faLT-ozOfxtcc)1d-GwUjg0)s`UF=_qiw?*BajEeknaW zuN0Ni{A`36ee8&UGumo_MOsw6EMR&3r~luPX=vMS;{tZ&b@M>ybGe_~*`fP-l+mtS z7d7}ktgheTv-ci)T{E-;? zra1gNbLI37hi!$urar`Sb!8@n{0INW*$vJ(C0DY45*5Mavw8ZmWc|5ydRI961dROj zQ(be zeiPui7MN#(_=kc|FvuEje~`P!46e49Q}#Azy&onc^;3x8jZgN-nsj*P%^f1h&*%vo z@}CG_^X(X0RP3*k7u#iH*w)iniL*;*vsQbs_Z+m3ku~LzLI32w3Ay>K_k}h=GKs z>Gg@nC>J?P`PbDdFD0NOjLfUo49Pz0G|G`DIbT2D;C8_^Nysf$iETA;R}$-+<@~Z! z3F_-dg@}9@mmg<6@&;MyrB-X(hjWcvgKH^vPAm3ucDPtBHl7le%z&)dD&=&`H?Ng{ zAA_pLCF*p_Hq6~IQAdmERPUlu;|wKEn?zFl6WPKjK%R?aHZi*26mm;yFFF#n zMZWG(;3^@AY1k7aZ2&6_nkvB>IpZ|@_tYwOZHQ>o{hn zHTx7^mlnz&$v|hm$hu=n;x9|YAR(S=!z759+GS#iF~v9)eOnJ z(kr6&T2DsVis9yuLM+pO2O_I6W73$?aXt>?TSz(%LyhFH~3R|rb;b^QJ_IO^=6wjjR(7rjlU`9>-qQEJ{>v2Xog6isU*vu7CKLer8tCuF^ zMn8jw%-U4g>bLTi&LAJxyehK{cAVikoNse8t;>c;$JGFkR_XlOwljzgDrzRlq}r5S z5~!Td@$eLo7MlVBp{~DjW8SrvaD1&uT*!<5ooW^0)?m2SRBYq8q&ZpQHumo(|3nS) zD3ud*OTf6@2(CP-R}4k`Q~sn-muA_~|4L=aREl-28*Ajy0pi2QEaVs|vM;napf2VV zG}#`6$u`AmK4Z9nb&=!H%NBl;Aj^>kKO`R)?#?B~FyI2A%$Unf<@OL5rYew(V*v* zHUGgUkIy|-G~Wijwq*!zLv~TW6nw~d%99SY6|UC^zlz?09#Ku!B?c6^4;h;j_e z5e(Ei`kKzm+u|asIfrzbPUsfwU4qSxqEBXw@<}N}qxHv~_-AWzL!%wt_IUF9B^wYt zvDv-qmn15IpJ%I&PMSitV?f2w4gwVgcAap!*(24Ji~zTDsI0cm+s-}7=jRinnuFdE;kyR*e_<1`dK&bt(8DG&E5vx+=3`c%* zLxm$1?cfS?2(&dP6Ax{eO7XlEVWEb)wp?zS#k;6XNw~C9VA!dwt`{R9llbZH&^O6wNyRSnZx~XzF3D_=quB8j)h=!Lt;@w2;8VurfS*;g!7cP;gUW{`?#A&}$ zVn@q`|GcU-`{V>VUsN*m2=noBb(MR{B-uP2I%C2UatRYqvRgpft+Wo695MFrlZ=q` zbUZR22FhKQgA(rGG#-vgK-^>_C~^Q&E1J9hoz^#a-O^M8FiM8c(-9b_4#q_e zc*>eU2s+I6a?P2*3L%o{bI*KcRK()DB2~ep6k@`ok5mQoE9 zXxdp?NB+tgQmv5?mGYiZyb3XQJ*2v%3~5OU(6@HVM<3Nmo=7(M~O2Oe+c z3RCa+{;WAA{Gt}-)F1yDns=v$+jv#%TnZyPED?yex1k&|1Tl)3CqcVwNl?tPP`kR_ zBh71%TXXICZhYR@e;bvCtmcFVk&g1DDV!4FQoVvdtEs6^fb`tOyp zMOPFLRg1?91W)JbF6u^?$e0x`?dY9MS1Z%5nU0KSedh2S)`wCrdr!J6oNgP0H!rh7 zI8bk>%686JhzpcjE^zSyix10+WSk=y5;=CSrn>eeq9^rn=5<$!Tn6|m%|&*K7$JSN zFpjUtssuVwsob%NXec_C$zUxQZ^%u&|D6&hvsCfO+2J9tm%oxYJkCLnK-`CX74n(R zXm!wrJyNm~GED?-qk>Q*Vm?Vnb|7%s2v`-h4$Tg*-*ctnRuzCxYAqI$90z(m)^3g zMiPr5(d^*H<+rG)?p#K^smN^{`z?zQvG1avSZJdfSwCeoGp{0m5e~ zg{u7PcVmG}ac}9WAnQL{0bX;pDp%U&nX|O@k7t$$|6UhHJ8VQSi6gx*ev({M zB>?=o)m}EZbnRnW9RneuFw{^7*|uFL6jUq`EHMb?1d7snht7fRP8Hg7F*61vJ?(#| zr=o1Ej;V{Ra$mY2l81_s2|cW0<`o4OK9X_=`cnB&XssA@;#r>J4FD?#>vbV^q-*(e zWxd3IhuttV_0D~Q`n21*!hL_=#O&pG0AISrQ;QsG?qt|to)i>6;tG5DD~39w0n_T` zcaqvtpHzPMW=GQ^M2p@8on0g9^uvee5n5q?cj#0RwVSgFr_6 z8Psl-K9nhU@}B-SMbAlE(M?MkJVXU}4p5t>N!{T%iYcWGlF2_r>F{f_z494;PxHu@ zocdV^m3plr=i{^s7W?N>t5Q6HX)YO3U$E=Aon^PH1pAfjl?K9*&BnFV?RKH&Ho}0r zq=6>rh*+Ts%u)@Jx^Q{gRTMD34at%}S0GL*A`E>ar{Tm{5lq##V*wg-ZgFtbmB@RY z3{X=U8&1^KnRvc9G$g(tv5w1|Pn%hEf(A#>A z#MfoS`q#pMVO>o^&%rKgD4dFbVJi!-yow|1LITvYB9`;(*z(of&>{JmzIIXR6`ef2 z{s%nKB|4iae)rOKW&F4Y)#2aSku3ajXn1QgU3O~2Cf7IRanYtRTqm0qj5 z&zl3dBH3~hGQ!V`?6%+QY^ihyUwMv%;AYs+p=JUPtFa{$(?NIcpny|H7Bj7*(+*v) z5A2lb-a&V+)#Uh7qv9i!Ge~;h7NOP+JL)g=;kWks6~9H!-{M1mCpCBDvZc4n8r|Y8 z2|kK{0?O$ufN_Cyk6AN5fPoMyC>9<~HB<{%4g#07=QUqmED_xq5Sp;Gq*&Yl3C|)H z6Xv56H0i0SHddh;Ihda%>y>!~;>pQmPC&sTkcWhhX6@jo@TlKhSL;z@GlOFVy;n~Z zhDGhwn88|8Rx zzCQ*yb6G*LZQHZfv}&oUIxeMy89 zT*uZfZQ{rI>Blg_?<*abIU_=}?t}i*gt_ps3&BbvbIF>7Q3k|ahp(7bXPF#DeowZ4 zArfL$J)Ki;I#`j$+%nO(0{K8U7-hIAP)2rAC0LH<0@WHdNj*0blI&9BFbvU~rQipa zHKcPwD=t_ZBLr^fHk4aK>aXx)l5mj*;Xp`KxJV7J@)5jhU(*EjK?}V5Os3AQyhcaN z()JF8dDal~qZxL(9J52Zkj$Q9&!JqR6ngOOq%{*0KPy$zanSex0m(YK`PJA zsljApjN^Yo0bku#L|6A=;G~0whaVHZYux_{{fUoloqx5G3M|TWjcW>l@D+`IhN@y1WNNwfSk!~n2O`F>OZ#{><6Gz zt7wxjUvhu)ys|kz=I#0@8x>hv*wA zyfKU0KZJ-6hY9Oc>2f61j!*~m`jZ=warb!+)T@x9KBBT-0Ae!cQF|g1S z@mL)iw(1I_jHNNSoo7+ZY7AMA1!Jk#PMl0x89^p&iZfGYzg?(s)%qBgkoB9+yFr5n z;{gU?)j*6B4%^_Br1=^7%42MdYAU{~;fv!mFQ?|$I@CFHfqE-#nw>pFv-9|>V|iT8 z14ia=$>IY4Fpd^UT|Rp+^^n|PMU zORpF`d1F@N_69A8W&SnAh^OD5g-qgR7xGB(-(+YnF7d4#ed3!Vpo$J1-;EWt#T8A3sk!$)alDa3s1QJAL!B7$!flq3U z$G2y5Uu(>I*~B$o$-f@kU+uBr1yoMF*0~sz?S{u*YfH1m->8en1ADriyEks9nbpi_(FaK2170P0v7G2EX3-Jk^! zMjAI_zIxRv`gwyfftxh;@uUIs{4lt;l+n15%h!CdND&?@${jJE?EspsNM4luw`{jV zy_Ku9_V^iUUtOUdelr$t&(6*h&CC!jEbv_$hwFHoc8xPY4uI!Ygq)F*6jVhG#)4cI zWRbF-$-r7S@cvBw%3xj}E2;(kOM;|rAXajLX+#JH!<;&~L~0c9@dRDv?IKH|fs zh|?AUS($t=Jk=(tv~r++bxbytwv4h&nPP>iDi!4jvX~|lJ}8_Yh6=NxsRy{Eph`c2 zYd2`nV7I{oG+oE+ACf%olLSIM@t&Wh?sO}6|Bbtu`R)`QUh7ip%sHa9j{IhSkJnnf zDht^;17vqz0z^cRn8anV2IY{(RkkKZU88#mv7}Vu*t(`rg5;Y@*)^nl8m9*P9;v_g zAaWz7hTrPBg3&mDJWAVu<0*gBm!%gO3w)Lz`pi}`&7K`-YCQAC-j3zOHvU4N$l1m> zXYKo~l%Qvski^vvd8-^bYh3bV8%O{godj&tV6Om9G?@i7Dc+*Ww? z5Mn^cKw(}9JO&Duamoc@+De7_c-;sZK9c3CH$5ezM2>tw0OIt z)6q>@g!14J`9$~`72x6$Rf91h*B4nN-$fQfAS@q}fisY0ys&!Eu!Qt&T1g-x;S=$} z39ulCoGuuE%|$&@6$XsxYuoOcV;KVj636@pQ6&Z{w;7@ASl2pL>az(6qmKEUsYi0c zYSc6{l=$OF*lPL)4H|3@O2(#K--MB9f-G8@usJ(BL){kc@w15s>X~+rX0NQ$)Va&N zu43!idFr)vlNN8%7H6KadB{o;6xYewHM2oEV(Zm|ul+Z(ZugQ>iKAyx0Ourbg3xHh z^Vx2sw%SB{HE6Jt@X?bSK?8g@^KC?wQd*YByvoKvl36;j<+#XGrYzT>AC^8@OB5Ta zi0j_aG(wiiUJ=Wuh1Yxk+?%u_Q<5*+hg?E^;wNNwntv!4AFiaw8|*c>m%0~vd>qKU zq&{r|oGjKFe!8P5o`MV%3o+P)=R+D;Il}LbmB}+g`XV)Gu+u2@J05vua`n?pqZc-n z5Ay3A;b6Q%E;q*K<=Ig~l$YrPSYCBe^*ZJNSrixJf=p1F2ctNxR$kZ}>@$>gbWvt; z32<=ghxk#YkGZ^D-=M*`!S@KYQ01B9@YI;cX7fww!q}>s%f|uaT%>T&W2Zyit4p+g z{v5ThUZoy3XJ_a5;%O^J`3+gNTv*f#>c%S38WWHnPBxebP32XEv1L>fq4JwK zkD`4pUXmHlW0^GSnfH0PB-v;v`f7#m`dFw?56z}3U4sSWyNLIFaa zi||l;y+a%4E>Z8w3iVoZ)SF+VuKZ@d+DI`Yj&(0Z(99Dxu!%g%hqK zawTy&AHtP|<9M1EDW=gfJ+5!jR&CH464PLBV*GQ#<}so(m6*d=t?vqOXflu4p z;owa#{>*99Z`Hbv86Pjgn>`M$Q=aoPf%18s$dL{(IW|Rcu`O1tq`os0`@O ze`m4Vl?Ij`7*7azewG7muUVF(aanhV3Sr-DJ|mbk6GT{AX-`GIT&B>*I?pMHC}RZ zi@40LrM|r?3fBp5WYIE88?HureJ;dZ=5h|TL?^)Ijwl}#8sM&if;@+0lstS_;DwhG zA97S?!!&kmOQt2@ayEM&Wob&|CM@WRrj97Dve^`>Tv6nFkg+fTt{!5R!zi{58Z@X0 z46NedDw{3X#;a!zeYG=f$MlE!gA?KXdGe#2#)GE?`hWp{TA@j_H z_U|Z2<5Oac0q2$O>G>~>Wg$E}E3~!SF$;p3%QRvTnF&2K11&E~6wZsB581vCWIav8 z7Z(kcPtU`JbWT%y|7adDu67bHF3o>bg99Hyh&hj_!N*-r$k4ij;XfXTnOz2znJpW-x0aE^7y7b5 z*vE+Hd~gsuRehqL%Ax*Nv^5Gky|QQ+N$hg8^T@_WF>J6WPAHZr=+h$#D}DcJR>~>E^e+G1w9aphD_2xm{+KEb})Du z%J%`TnPB>ytQ_k9YML{T!ZO-4$}+1%yNR;;Fkv1T8*!GS0%^+94b01w$%YyIQ@(&G z>DQK^#5EI&x2tRf)tRvx(_|Bx8bonGKMaYv_3o z0`hFIUlBWZw2m(GF^BuD6Hv$3b{{w=rv{S-=^1vUNTXmgX&hC_M$Jyn0duiNCkm-< zf%uSJ11zpOk223HS@%(wrh9Fo_7ZJeew@}XpQA3~hmWuUHfZfFT1lAYCmXnPb41+@ zqSe*CGFcoi? z@-rz1s>8Ey)0;hz^d54-LY9Y;m?mg?r3MYQ8{*6S7nen8>=>|q8aq&yl!pNU-a|h4 z*Bd8djc-ojks3(iY>N=-T%VDpvAo0vd2@l_g}6}IfCp4=v0^JQN<a`MPznLdN$ek^0KSw zpdkC&#Qg+x;2;9ZWO=v`Me2hkcb{<|b866F%h=`V}(c2ZG~xJ)A|)~kpR z)^#kDu-9Q)qwdlL+Bkoj+RImnW@dB)R^FfmEK|VeTf9v>Gf&iE-O3VCxA>LEAx(qb zhjg3vN$x>RVv7Tn<01;71=X9V0iuFWn2lenb7^ctHtI~D$`E9Hl;>>#=Zo?oK(jcF zf|za)>0vTZtlOxx)2LJaDD@IsOAvX+DB0w!M{u=GqgEMXtjL64^BOc5AK2Hc{N0BX zLb*112>VDSNNJ6M*$l71=4P-D%W)P+xh!jUse5&WdXHbCsp&;(%`Woti`QZDqz-1j zcH;=*8Ze|{$}(iF>PibUZN@dIi+uZz1M!}`>fXXj-OmJgDDbwZXp`**N_7ItY7uQB z0UqvY_*}IeK)>!%-)<+OFAHzy=yBHz3g^!=0E=uM;6HhWD+-l)TKSz?y=hN*WO*a5 za@80_oaG^K12Gqa6vsh6mXB)qXgWC}n#wVIEz336flR~EWlY_*QPE|s&Wpa(wpur|l z^rQX>Kl4M4ng1HEWHubhs1S#p~B%}YoJ>!||Z=`u?D`a^!7z`P0b;i;J zfxB1xH&<^+K@67r)oj|{qMd55Q1|j#>Rdig-Cjq3bGBt~&}wcO5Jgtgte;;Xnwuxu zSYcW(*{E$WS;+dba--Je5+EKz=W&Fc$AwqYe3fuax*!v|b4Zhv^nC#R;fJW?W3|fj6x-O=00pw{3KgRZwPE3hUy9iG2bGhD>^U! zk5Gdgl8uE9#LMh=1blvj&apv*eGT}24gZ%hYPM;tS~`zQXfg!TE$Yqk%1cCUG$os~ z?d3J1t7|khe}rfTKPNHG8hw9O%q^P?QUT$xi3?=c-#oHwWWTOK6}&B-wg-9*E9u?? zf?UgbTOh1KTY3Nd)^+aQ^A&$YNEg8Z_7`h;JJ&9x1+@C-^@0c*X`~n@4_7sEDUnI*h5wXMA24I5@*unnW7m>L*Ng;_6>4QF$Cqdr9M~$ zo9v&K!@tA%0-v;*r3HmZKqANvP{$szfD^xuRNm$I|lSe3#*+B z{r~LZ$jh^sah6UV{3azBBj}A%8K%m~olKP=GNpcPlmpILSoFJGJVS-J1obVq7n4$t znm~28p~|@|EAp3VJL!T^wD-BaAd_f5gFGt44pFO%R->r%cvYI5yq3|{Ag7Nf0}UD+ zG{ga380;8gxnX8{kwv}$8BaztJg(+usLPjPG3CP){ts!rO&eF1X{z0$nZ=_tHM_ve zENs$Rz6g7WWfB3>2SL;!eNA}eJuLgUPAUC<9o68lYxR;l#(~G z@CO8P?p0%HFCf(&H&l94CB$OHx>H>qKOO32IVVQ58@Gz7`pqw5?g9m8(SUHm6CY1!}PS;0}|wqw~mZqB@+HkPq^wq4qC;I7_|1 zEpRr1Jx-3*gs0S&m*?jc9#+wu_Jat2!j%6HmD#A?)~ZGdDusEi=bsWBf$ zK~4$u2^1!FZM-DJ6cwoz(KUf$ycD&J@(6C93pWM6b1IoD8Z_7!koh2u>JS!b6tKPD zp!bbE7Wl)886I1+v((}8-F%uaf31~u+PH9;rn>ffwD>6rd4ge2F)RxS<&$NpAwK$3 z77-ppnAhadY|z$$w_>C*f_-9h_Z^;QGifIW-kK8n7_C9+*$1cw+zMe#A>#j9PwXqO7 zRD|telirRsLOfBB`-$jAmGb)Ge7Rh?FtH54(TRm()u6$+;NFz;Glo7`HkeTKER>KB ziCiag_E0AAYxpt?^&b;5&(-k*!q@`2+>dUVLB~ixygZN?$N*Cv09JH4m^~w%V?dgK z8uVfR+*FEZ6lgG_uQ^qMRcNUq?FTdu7Dj{niTDgRT`iInjL0*{~LAw$k=an>5LpjUPSTwDTyzAvrj60INn7ELjD*cwhCyKAK z-_!{=Xs`z$*C4=r+eo=Bw#`F9ATWWzSPzY;rQV9^rPK}xb5EV z?AWT2h63$nVHqHG0-}}3tq`=ikE{I0MjG2mS_@-7MYwK|O@jk~A>%lXbN6?Ud2|9| zac)r3?1kTyr%A3t{xrPD7YsZp&)qHYH4}9bmPOrk4J`rd{Tv$X2c(|2a5rFn$RT`P ze9T0-T0sRp!#x&J-`g24IDZ{@Qm#-!lH+5;i3bhVeRu?uHflvD=DJA*l5}h@ybVj{ zkzRNvfJM2Z6X0Qk2IEAjU!@VK-VXouH^1SxZs7i@7cN+4`AtuAI+l5wyx#0hp8i?E zWH8F&{UkY9=wOY6sp>$mNokp26YVhZI5j9odf>Y!fsS=@L|IXnN72_3iph;~zGbwZ z;I7bY*p|axLFTm(`W)nXCz)T35C>cb=ZX9z0@aFDEAk#M+Bqu6*B*piL->5~KoA?V zLVVWpCM|QV-UiLImx-3o(~%R4bluH2()^)CT3ubyH)#jLJOK|K7Zw6#sDej2z zD6au?U!iRU7l8JTN|lzeKrAQVzD(8%oCDLxou2V#n(oa%Z}*E z;{%@s{)t02h#EB5r$}Sm2AW)JsxWAf7IkIuAe(N{)Z7eB&&|>l9>(F1)wAs$&0bz2 zdi0Epz1Hj^O--{6ufnlH_YEWfHJ6PdQ1}c($fCj6;H`>qds;Z%r^RbmCETWt?c~B+ zGqz~0*7de(@wjoC%2UfI#wBE1;jQg(%#)5rPcN2MDNRuh*A22cs1Tp7<=1;3!^Usv z7)SH)bwaKcjNF(gnC5g0k4Jf5oEh2iaRGSASY;q=#zHM7fd_SaU7_N$YO!sw&)~i4 zy}$F2Ih)5q^f%N5av+W&f7;+fN-ee(B@M%c0Ce`?4tI;>m++-BuvmSnpB$0jKZxzY=*0!nDTW2#456w_(o>zk1Hg#9m*q}~}G0Y1%|>&d)b^rQvs~O}&?$ z>??M6s`xztZVdd^WQ+T&2sD`<3Se2(CBKMr@aks*6D7hyCTD!jc2sy8=mJG~fscfv zBG31S#={qKlb73!6H-W^?MAV@aZ*3}q{Sp76Ca#LL8-Z9nB`Szqfid^SFL?>lW)*qzaq^S9QL_B1Xbg~$8eDx$S+Wf*V!}E)S8>I2k&^!Ml{>$ z((KX-(YcF6i-+{L{^c6Y_Pl;lOQl@)0iqiNq@0Q}8k8aS`}Q`R->VIV>&N90yNlSO zn`ve7=K%yr$eHGJ*4Bw&1G$Guu9B2aVtJ%A7EU^L@*m#49r<9A{fp!?1I{(-a=z{l zstuy!c+SS-l1DIRxE-E5NA%aAY%IYSb)0D&{Pt|pS_#$fbjRG08MhzNl3g&n2d+<}?b1nrx<)is?X6s=#SP?p+f4gy} zWk8R>q>|RsBs))Q0=LP5C`AJ0CIB<%P^RRZ?SI`ra zFgte~`L?UOL7k1Ow6S)HXrVf;zBbe8()7|Q(WNWAjyg&-J4ZeIGga>Co+INi^dk*I z%wZsgWz=8*>h#3c;n!lh9+$%9wR?S{;jKDq>-s+%l(hzU8M2nCuWeG>ij~>1fvQ!W zQSrkVQbDnqbjX5y2Vre4jeI~L=UV~y!G2g9x!x&VCoB-TM!hG+%~`Jhx{Pp&IuhbL zwN#%rVnK+r)bFrlbJlpxi-~2f*IT&|547X{)L86q^+bRGwom-Fz@0UNPX z+h$XCbnM*?+WN@((lD5*x5)l(nb9!1n`C2iuR&_gep6NZGI^ODox#TJ+1R9_Uicyv~uwhQ3tnZb-)?R zfAw+Vg++Y}3md$vt6T=>kp>~#Y}@1%GWP3({97>2GuC0hViV^l8!|IW7~GDORWZ+s zG9Z@rHNCXIhf29yc9)w(p*pb(dLYRVO3ZaGQ>a|ynGImPKZ#4oTM5t%Lx~T4vigLe z90kKfn?PAM&)lXDqk@*NHxd3UD`+BS&(!#rRHxYc++r zz~0`A^Ff0K4Gb73AmbATjF;kdXJ&?`=I5xzTl>szbcrPk^?(efJ6;$iB|U=tUQ z6`8_#1XngZ{o!PxG)1Yf!S-Sj8r&VF#9p2=GP!>Ip`Hx; z3hbGo7}nuC1$p*WHo+ZG^gRniG>C*vZDzzgdQOO=xzGrA_rpmyZ-qFKY|vUL#1ZHq z!`+ndOnS(GXhGCq&%=9k`+K(RdAOEp{%$CN zR_TbK2Pb(!#v@wdk+?|b2cc?1w%Mp{FbwV?5*FM=e3NC#{}9)p59+7bpmk-;Otqj) z4=|6LBFLOf4$fowh{E&9RheZT7k$dpY&B>w0`|uSZRP`6m?7_zLtv)fB741Mwgd2) z(XKtQfA$8X#smDOOye?18_1m~%Ir~*?!|FAxo_EE8Ehs6n5|K_9GR{Pb!_$u;(3&v zm0XqND~XqB{o-S^cIgaFADgFzXMYvZvEwYeMC}Wg!emls>~J}<={HR@x4?0}UE5e; z;&QeX;ruYhu^|g;cXXq8ZJh{T+q{9_$lb4~(?1nJpW(MB@%9|vtc{RtEpIQv=Fv2t z7UxyOMO2hSB?l!Da6d7hlY3m!1exTQk=lTO$OFp9<3PZLoVFQKL@X~6ANpilpuL8& za{!Hkn5LLk;z5{LW+Lxlk^#l|D5&9oMGQ*G)IEBbK58tHK`!dZ-{wLb_0Tx9mu_WguJ>D=117E5Z!SQg1ZWa+1CPU z#^W1r%+6r52pdA!Fv6Huiv|rE1Yi+d3D(J^V%JPDEeur1a1CM;T9~8WB9FP*>>ncV zb;q66b=tsNv{--5&T;@_NoWM0vay*Kl(XYRa^D9snU0Sh-y7LIp%IL6-vriWxinxb?to2;?}0S^9tO`F z(#FO0%ML)=Zm+lB2yox3g7_3{z^h36Mp=Pg3v8x0BZ;#ws@!ex6u>rCIZxf7)vrG8 za9l#xf%L17^{bJ)d`-fJEqLT7GUUPO0p!i11_uhM_buFBag4o>F~D&d2RhpzGDp()#Au{FaX{{I~$a?V%vOi0Ti|49hMa{M6+ z$OoDXRAyvwa=artm8JizFnbJM3|RRvkM!Atn`)F#L@q1SZ6{)Fht<5nP61wkdm0Hv z0-v_q3zxGWB_9WYFUY-5-RCq^Uc>Cdr57Hg;E??oYWTX##MWi-bLMe@(-IWI!xZU- zN2I}4A^qWPI9Yjc+jcWs^L~oBc{*gWi=BS^Tl%fX2R@rzBFF!!7GVQqzEy;a7^9?x2qt} zNr)?PT)t+ViNhY>FoQ%UafB?xTXT?G*wY(riK~5q_z&eckL-o~*entsHInMEP^#u~ z5#dP&SBB$~#-MUA_>)6}9fLTFvSUWseb``ZrQ>(rX=1BYwV)4A*DIf`;xw-Jz#8`u zz&RDq%f=f6W5q30#Hm=B#re|A74Uv=84&r2hqsN-e>(_iyOI5P@1r<&(ekPFP37~p z%Tvg5Tyo&o2$gU>fIaqzbOgvHN)l*V=oDT+;v__s5c*OSz`hW2?D#WaJPWhxDH0~?L@vA z3!TYQ2(9`)4lYwjOyb)69>TZtmnnF2Zu6Ftx^0nfusx9Z5;Sor>vWg(>yrB=R5(qE z*w20vTVXFDn*)YHMzyjN2R#SOaQXAmIv39{#=#?<@;dXm3|U3nDtOEIwO-~yX25H% z&Z|vCl3Tb{czx^l>pq4xfnSTHNw6RkaEr^vC9mju>(pI6Ps^YEFm=|?(!$g3q-$RD zayoweI(q28y_1&S`C;mQ`8?YmB074Femx&DD_-Qh&2xRsJT^_QTqat+s^xROG>5O! zgguC_+O_&C`z+0 z<>MrEg$@2Rt-^G|TKzl@|B;NL7K5 zi;f#N*;qs4#$WV^oe;iDJ6j$G#?jtyAdJ>fs_DigWfM6)e6Rv=3o zv#Q5Uw%E8_ZnBN^23*UNkgLFEnm;0_lF6NLkkC*iABItE_bbo_$!`p4o&b!Opdc^G zit|fR557+ZxEv_xO6`F%86zjIu-WhE>xU5LnuI&wH(nj!#SUaTA?J~XL!?6}59oNn z9^&=(lW(P&mp_H3pMMXnUpFhy(GIQmX!g@zruP4MH!Z#G1JruzE9uB}ck}Y)7$=}->k3FBSIJ>uX^j!BGVs4l7?AuG~b{ATByv?5BO-8Y1IgPnvpjk4Q-?d{K)_s;u` zw^~)}#o-BHy@w$g?PV!yb=MW42pHjf(qO@#ruIz(s4`2uU8r&Z!xAy?gCw_b&%ox# z-MH75w)6HsK#1cuwtC`CEpf92@1z^E8miCh^+5GJ4!AFMe8h5;&peo|ISpb+iDHz8 zPb)9}&Uv}t%QJJVfjKEINm=>^`y22qN94B#pK}Io(sGcdCWK7xbFhI3V_+yYbFuVt zy+8po%447ysaOUEYO8Sz)i}YUF`XkegI!?^UX$%Ws*!~|ft@U?K^^2gEJXSj1|`0j zM9QFdWh|7Sn4Jz`KSpG+TwZyj2HOOgFN>4cM4-$8T-L8s|1DApO2mHl&1}^ma}W;u z=0u>vuNcr^hC_(ON?l6-0A{55F!4dic@6=IJC)XPyx55{_6(#gtUdag1*^dhwYuxH ze&Gytm(J7l@p+oP=T@4!={mZwbcI%zR;W8Q%N@<+o1oYxS9B8?d2etWHu#OVLx+hDA2nir@etFZ*5$y$+OLRo zZH=VJbyegManod^_aDkak9goEjR;HzL)*a8C(X)BsBs}NG?D5d5b5R!DUP`$Ax&FiULPb-cNlJK8!}3M;VRtQ^=bSeN^^g#inT3N9?@p7X+q>3D$`n&p-P_fD`$&g5moXsjAGlML4yprd7%JT<;E8aQ<9k0}^BLd*?l8lvdOAi$xe1VZK2NaZ+I%1(^^ZRHg*vbs1dl z&{a#6>_NyH8^QMZX%*6%^MIjh+@>CY+D!_!un|vXv3o2+{pw=XJBbW7Vy~gv z7$0n79MJrga>rfpmj=6q?e6R7<9UAvV(HFDD?Gm(Kl&UTMLKCk@?@6~j^t%Ln1T$z zWGiw$YG^t$@}ey;WMyv#gBJ^4Qoh9T1Nm=v84b1q_Y&=?%x9$6;6o^k&r1C!4*W+Y%h<^hv8{Yl2W$dm>D2}#A5H@|*Oi8r=V5LC z-vqWZ?>zx&V5Qtw@8{YDoujv0t!|s9)|Y7g%tO@cF4OF7H_+TYw^DniMVB6XoH`e; z@{);uKMg3s~s#oZcc)7EE(Iqo0qG zZG^jD=7!ZMv#FD=L4$*i+QZof6znApADoYbLyAY9)AKrO`tTx6AHwfIV@0jN+fCiI zb?U6Fu_>>sXXm)Iu%2TmkE4<2Dc32r))XKXTiLQcmkUimA=(GFcN2ue%o~gYS>J63 zw)b8s<~=!{<24X6pU!H;<3(gyn@gMxQW_)g8;SEl$;O!zWFpD;p~@5}Eynj8WG!x? z^E(9bU(f-AkK0zKFgNDKfToF}r6eNX8#k>-3>oO)z?{z{b zk1d$V9$$cXP+=e$L6>{H0XcXcg-EL;8s%9x2vU=(^I+7wJb5X@O4}-szf*%rf_jN~ z6O%q>I{kv*R);52Yk(q%6v1nMblF)l{3w- zjr@#)*!J7|1}*ZGd|A(CS}z;7hzI$8AUb@EXaNsC z*&AcEob+%2fi~Sd(j_=C0Qv<1!ek)4#9WTJt63x0^qAJufH!hpzUmb#EyOKt(n+9l z-LM5%E`c1u)tfBf20j6j>DH*Wp=SMZike zl>Eu1X|TPh?vrs~d;2oxUB&M(tSQx(ttKqP(>>hNx`F7-M($_D#^pRdnE~%W`Y01S zkjeVXQyHL|Jq%fcXOz}6I{;}zYsZ5G@u$Lhqt(k=-eu_-w(Y|<28#|73t5=z2I7MZGLdJtZl7$Rhn$Tuy!7o_-_%tZAojvl zqwIV{HsCb#@DhfVG%D)UzQJxI^^o74h(DRXn%_I*Isvk{K$7vn(m5Y5BuIn*B=WRQ z0x84Ch{|OYLLSmY_~fxG@JbG%J%Zg>_>B&BfE?v9bWSe-{v@FW4R#%qGian1^M%Q@(oq@RM~JvXuQ82i%>Ufu}SN3q8W~Z#13hVWb+m>)_HzfCT32CHKFhfgwBrx zIHOU<*nWhx0e^sUZ-ow>04)}FZR)OGrIkm&NWImIM0ejrt$S{z*8Dtm&tD;W=y9Uu z4ZSc<&)J)>oD^Rxj7?Gb%3|c}C@)ojzL}ZTOje8mIgqU%Kn}N65{)g|MAGLUs_PHyAj>SeUy(ADX^r5^ zmE>kY7SrxD#d-`NUmsNwAC&6k8_Nd*t32n45A&{4F{B2`$H1&;Oe8@T6-3@qCQFE} zQ{`60&{6c`KD~tv8Z@X6AM+AAA>dHhs)6NpIQZB!TgZesp2*_<6*aTGmR_8r)&j4u zu!t7eQwjVd+S)o-p+&Q;8D3|*K3|(Ka~U|!wlb%Ak*Y}0^d^-+4e>=MNaRJ~IvB5o zp$ZLl4Ct-cTss`@~ae=(9)yNe z5A#qqIv6I${9FOgN=Y`FN+{`rEe4|uz@%4*4P;!l*A1Z#B8^KJcp>mcA~&7#Jm@$} zPnXimCxgVb=t`sul+oz$+_eVdAt3S%CIj#fCHH*|!E(qX<3s#N<=Ts|EALT_TRxUP zqw4gcha5J{Yk45&lrKWY=ng{`jv(;ED4yhmB73;H8z^nH3UVmFmATISX2QGX0Acij zqH{$?<3?5^WL`A`W$-xx4|(*Xi<2tSH)eZ6@&>KTCDgA)_IOdIa^0wfPRr#G49Myt zkos&LI?gO|K#}Gd4%}N2W^HXGQoY6Mc2;R^={&Vhf0=qGW@+}xcT(@x8)>!Ep^e8c z5j}pHsErQe-o(Z#e#aG|JUqm2(}uTci{x{+%-g)TVR+DLt<` z@msh{OSU=7w6x5pz;fT5J&Lb1K1wvp^~2X0%endqGl7rsL=A=_*DYB@xKbU$pfEPM zf%K`1jTa@N2qECUb-CS`C=W5>VvK{v69)t6A=6O59|)nza-t`XA&ME9vh zd@#PA3ziB;z*f_50`Ytz)j&!~A5^LWN!*Bl<} zvf;DF>#P-CBXI_J3en>AldtpqT9Q`K7N|r&%Im*m${LwJ0BTVM(P`3#LnAI?}J_A zd8lp1<$EdXHMgpwJp!z~jdlXwCwwr;!GpB)fHrU+1L+G%wgHO}-_pRmQ~yRS?2%S^ zA&x_*`MI6lafz+I+@~-2A>L078jJ(7yefk_qJTLij%%pTElU8kLkEN<5k41}!B*6v zOzJB^82V_ zNbj*s#(`1FBWH^^@-bVEYo7TF6Y}@}B$Bb6Y^|)4P_hZobQakqp!i_~2+t?tG$}}n zJJ7bF*dj%8cwCp>{gkCi3&kpArlsV5GeKQ(z%hDH>{#E~+@!2IP6ePA0&l56?!mqZ zE5r&9u}Rxv!ltc$-Ldi>dRj@(V|AMI&hpY*(=607^)Nojm^1!B0w>P|zmsc^2!kJ* zUK@$$RZR4~4$t>^i}nhwpFd5#1N7^_I}|rwluGteTWup%aS@WUC}qHe5J(BMa8g)DtS&(X*5vPpuvHH zObUiLK?oakfXFa-N(N9g6}v#b_)VL*d~KR$nqmIhL)1M!Pn~%@cfd6ZWC%s!nwMn- zPO~&N4?7RB!ym^*!ewWts5<2}w4(B;I^PDn0Pl-&(Ezw_6v&@(6lrsanODJe(KgbE zh)FDq5|I+l4MKy*qaMiH7{iFE^YSu4>Kf-U+I{jU>h=I^O)l&6odEg=4ILZ%fFZTC zw*#7jNuDi&7(V*t4vB5_88?&hUG_P@5@iHA$a&$Eb;L%UVk_V@aKo| z)CZxi-A*G-zWGUImr%czHh-g{m_(my08CN&sLsRWl>RviaolB>Qj!o0- zbDl`OJ8q=4nJHSmc!fHTo+nyr>woT{XYn=wH$lk0EjC#3b;a1I?XnJU)Z&fUx^p$= zNNl9~rmE!OUwdqM_=2*HH*HzBbcJY{X@hyB_qS&c9p<{=&0hArv^fjd$)$(Eh{6agb4@I~T7Eh+%WTkK(jk*Z$%GKE1Axek zfIglNDb8uZ%OaWiX{N;%P2YHe=$gaSox_9ia6Mw%9@aOD3nJt=o_^TTtkX}qB0%%iCCuml)Vv~-5Es^ zIoql}>>F9!?SPn0%Jgb@*x-P}J!SLgn^QQN+>3QNS7V)bb{9PhhpgPMpqIe&-6Yw&%_VuA>o?$oY z9-$9jjdldy0#yV=z8|ttRA)iRCOE4q0z7Om35Y$jH=#3F=Dq64_=*pn-FUDoj}2B0 zg&=3cjL$Y~A&0NyYm?{d#5O<8q}u`XzPXWgTcpgYtp@+*_m9 z7TZT|mRKuab-Z$gI_DoFTDwS7Pr8ZbpLIWVt~o;MYpc{bdx3hV&$EurJ5q?2Gd)eT zut2nUh_m5Up}YyZo-Ga?#eyS{556)Po4tU)O&fokw#_S0d=>K5D@0sRYO`*3p6JjK zrA7N)TjV8m)4|Uw)OJq!(vn@#14ks*{dHF)e7HRIL>u8$SUA;M8mCKv7fL@EH zjvk`ciDNA9(Zqq};nB!azmui*#JTwnEvRtowiZZSY$gb9XZ-ZR~`mhd- z2XargZ9Y-VS3FSJ#20PyP;Im+q>1Cj2+;Eala~V$59!oU(WfgQrcqu}2v?0dHWLV* zx6-Nza2Q*VHqAx_zyk{ zaa=ZDc|<|))Ma7z)yBwUO6|aN$bUlms6&@^Y%Za~r41SkgLriyz{7s%A}O;KF3AE^ z;fzqah*+2|B#AOTpmDQh2S+GSwZJbzNw+xe$7U=BK6JW4i>QCS zvBnc|ipSdd@l17w}Stu4o z8Q{8%S9s`%@hToIT}-!0pv!jCy~kMoww*@E*rx}PV4aX2aa6ir= z$V!v5P~@h}*%T5Kq751}r~n3a9OPvXn}SigakkL&0bzmc<{qEr!;RO{^r`D*v$i{f zOkEf3wqPc61Qm@sa4!%(YKmXums5dEnR z4Ts-*j2~rQT9g&_3Ll>3RvJrj)IXfVu+tGW#vPNikfaBLfEjDH*m`|!g!IZ76;URy zvYk-KdR%EIAZ=W1=K}(?a3u9f^-qoCkhjs_sSPsbU8WndO0p;9yy)yjK(lk5f(3!5 z@QqyHrC;h$gZ&5hq-_Fcojix zosWqGq-T{=8W%$0pB11pk~~3y2V~JVE(aPc+&2^?}?(7QDqu3zjt74BmMCNAjHZD*u zzU~;m35(yU-C%q9t=M1#Dyu`Bpam-Oq6+iR*nip^PkwK2XT zc{-eP%)jb<_X1G&ZKyxmztRszl~*J8z$LI5SO~f6B!tY?O-L_?+o~Kg&bj=c0!OV}(re!q?kE^#eap|oU-b0rc;W7z>nyrm%u>W9wSDS_d{!`{( z+lyG2Ebw#LLo*Lx|V@ldSFP}>PwKR+X4;wV7M&De*(W-eB&lcPso>+o1 zH}6Nhz+u1?%aVb?1>v!S#90r{H)Mrp8F-MsMe7v5<~VzsR)}?CZ|P(ZvmE&;@j$aU zfQ6-h8Z_vKJ8z`n$QF5-y~M(}aOe-7J8#6iY_3KUeXuQ%+OytmixlLJ9MAf3LGITK z$aW9`G4!?*a#;o8=(ZZm5bH2DVD2yiKYqlsbBY+G>ql&xJ`}Sm62s4MJI=Jh=F#7$ z=pm=Q4>>zNmEejTmdpp{-}riBY|P5n8?)RuL(xoXiz`0>8^|^8dK?mOZCE*O1pA|% zcLLr=+Tbb!Mr%RzZK>b=si)pet=mshn{TLQmfAG)*cGBPSBW;* z3;e&6ia=fPwa55vS-jn`%=UO2RyM=TCMJ|R7c#={$l`6>)+{eJIo-+%(G@Nmc_B~a zjW=f(7l~$P)ZYCGfw6%Z9iGolQz^;}owk6=F*rzGB=ntAKSY|lmOEdtcN+vkSO*x7 zgZ_zJbsCCPHf`ZwE(fb}e8f(O?}$XEZ_;KyDF?Md3dog{qmbwT%QNvBW@NwuDG}l> zbAAx<0bw89K;f}S31!MHl2j{Fxmh1op^i;0#Egn$Kz$RUyhwZ~<&AQE3?6+Npf-SC z6AMUwWGF-hkU1sv3Gx`AN=mmGXuC;lN1hEDOgiGkA`^zih37$0Iti4(?Ko`BPSgDH zBQ$+zo_fqo^qfVIMEoxH8K3wrOo$J%EbkXqT>gUQ{{pKar=NO^k>ULbGBES<&`VxVawh4S1? zpDqo9+tjgbur~oO+9q(;@Enl-5(c#1XuVJ*4SR5FRAoB}`_$jk~fk22H zGQGJ8Tc8E zc4h-_E^1`uXSvg7+h8#I`*r{H6wWMvb}G@4t;q8k>HNVI<^iRweGr$BnY2-B@}!e6 zqF>^u)-*ulh_9lN3Jq1yV>JTqzS6xei~omIm1V9nm3 z#Re_jnw8(4J*4^;-k`-uEo#&YH#dY1-#2|FSp~$C@178yu>AK2!F;Fs@ zZp^~Z5F(BZS;=CHi?figXe`n*bv`o>_(Xl8tesN zzHkB}?~phj5aQcNrdu>KKTA{c4`?P2kQXc#=c#w{I-*-oQLnv9?W>olyRpW$d_9w= zjBJRclGZb@(AMSxFiGutBZJ%_gm^#7l>?JB*r&k7V6+Ruz-K9A$L7jPXH+<~UXSl^ zD^Ay2BC2)GX#ihQolFdFv+WbpZ8ncxgtb+!&9(u0AH4_LXUynpWor}2<1=pIS%*6! zr%cX_@zLcZZ)s{*ECY#F6<2#dtk%8Fnao^TZqE&Ef+ z!%=Z!5cEp9hXzs_C<7{o4Oh`{QVB(-k5@r)u*q-Gvarj>8fJvIYjr^Cg$XhM0SIr^ zVsQC}mjE&ZM$LF?kca!UQyKIoA@lzXB8mQHaG4y9cmES#^iX){bvq%+n3pjkc2TYn z9=ec^BTfj=?=$2Z3+yioF_SazQ3jIZ)uG88nvZOfFR5 zOA+MB)+h@qF-$)y#+~2TP@`hwnHH-0sV+FZ_*g`Y8=o@?kz&#WC`y!-_6-^|7%NK0 z8Vh}%7l2_(>y)JEhpFYN!Fl-eg$!6px2QcgL!BG1p_zMcXIYzim(NpgeTndUwY|bk zycUat$ppw%N!RW{WpH^8WwJerxO8=DFb=qH6;UOx@U>k+Uk&Zr?X{OBB0{UO#34u{ zC_5LC^Fj3)G%71YV{N$b^#k947iN&sKUt}yDCXOe6YM#&Y_%fK-pgr{kKx@x}((M{+hYGPVEODrOu=0?e}P>IiXx(@+22L5Cd<+`bKSw(_F=G z*)9`x+H7aO;bA1mu$hLhIriVOMP7J&_Q)~K6Tf#WzQ*KXLgcps&vzF{`WRHM&QU@x zG8)Rt8wvFipojGkLI>i>FH9i5;38w#B_Nl$*=N5|%h9+2>$alvG$NExCHR=1fjE}* zF&+q?j0fx}iy`IHLwX54O+?YINI@Qu+`WnnWh$ppFsl7P6e}{6_%Mjd6D88?5okns zl3Y^sm-m?l8BCr-nanXjCo0p6PbyoQCW^p|zcy&lU}wPN&8L_|CW~;LL*g#5F`Lry zm4eqj8|^l=yB&E>XM{|Gl`^aUY`U)b{Zy?<~w;a|A>_kIWx;0$Dl58Up1tj6ixO%SJBMGJaHm zH*C{V)NO5i=`qL)i1}D2y-4a#curoFXZC4K2N~dU z(HYWssQ3-&qJ0LJmFXJnUAVVI&)Eie_Dt{~xmV|T23}YS_#hTlAgrx&IV2hYPU9BQ z5);3F#g_~!COoddB2eF+#c$4%5+^MCU0UQ9smu8ZVSyRsu#`>UAZySd4>-3tcm*&a z`(&NB!$d8=i&!#YN15=JT%I5EfO6l@%XmS>e58(eaR%{YmM2ni-iCc%LJ-?*2W+Sn zS|kJHdfwbVZ0q-ak>riI3KG4gLpaTn7L&(?U}v^~ms1MN16W+`I{fVGLC%k!0qF-o zbKGp|eE_uS$S1FTElH*E!~?SHSg%8!_6n^pU!d;kFY|=IK?_g5i{_quFVW#enqTeF z>L(wh&KDjfy12p@M#;pe1nO1_d=)V^X%8J|IllJz64CN9^LDc>KFGZLBjm^cZ``gd zDZ%70r$2g(XbxX*%;kDJ^i{zHeTw~y+^KH$yhHl!XhORuP@umNAk3u6Ky)AzAg$X% z)J0t7h|AX%u8Map4hVxye)xSQ_E|$f5XkKV(fP#8$cX zEw@i{OP5Phg&Ib+@?q4qtA(*IONNLe8#eQ}^%78&}=2O%e3ybokF4zHq zO(-#I(4fJ%5C>R+Fi%vi)kFuIXa}-gRe-NG?e;pgJJ_Vf6FIvkIoPbt=IzB9YMnYk z^z?g(u9>IqOq;q>8+>iyG*jK|S$D`jt=%P}xyl-!*Hv*{@4P&N$;6S(qf#+>kae%| zML?d`#zqY`3u(;)0g>+qe9vinVELvFmb+BGw3gRNYAd>E3k`J4dv+}A@_I7cOH_N1 z{!5_d1wb!ph4(e2BFW?VZ@DeJE)A+6{F#MF}Q{USDbkJ|6g z+EqzUsDuCy_XBF4OU`VJ=U;Ul92Mx|fZP-jA+8_?OM}o!buN|z;(F7eQ5U0S#Ifsvp!T#`!z|0@fZ+!hWTF#O`mcom;+H%qV7W-n+6RUi~=52 z>87`0gcWb3ffyGVA8@V3KcL~C#`)9fcBs?CCarJpIM_y_d^Kt@EzHpTNnT&wc#OJ> zE!m{S25rhaS3VAQ&tvrlpYmru-2>wjdH$q-&Q65t7G-%FrXNNVfeER`{sMe1`gJ+B z%Ln91m*gGukGzfwuOULbc%&;ljpK5SHKW`Mb5eQkC&UMuyt&OWdh| z^18UJOxIxVB98UQZxhT}dF^7(3V(`Z@T!bjrDV@}71JWFq!XQAbi$(tjk7%e7A<%s zwbxBqTxk63VA)KGd57~7j^W%I><1JaJ%{SWd6c`h%oZ01kwr1bi@t{VFp_b>PVM8R zlFS~Ei_z9^j z_0tbg@AHolU0fq-qw{cuV8ndgZ=_h*pj;!oO*=PFbmTbE42SEhByZGWBevUNTTUdK zVN7^~7H`@v;|*Gt%hx3z;q-HymtC2}Nh1Np_w=y#1#JLF5C@7?nyv7f475QkW z5`(iTG`$3DohB2NYn&;)DGM=t3Ot9hK?^-ZkipLMwqcunl^S$lafoF=k0^(#P|!2t<_W6vii!%Ee4zI%6GyEg;hfS8dp!L4zW)fmaQgBYdKW zlL!#gGcWVF5dd?aA8m71i2q>I;p0`u2DBWAn#BiK`}nzkoL|KWI|(t zw8%F2-2O#LTd@e^wyamG#&e$>ai;>x=LL`V+c((Dh+Z_laXtw8q^rV@yb7aKrSudy z|6(49E7=E=9DnqoU6K4^GlV$9vT{-w&NC-(aKJEV;`9kOZzB?$h@-ZDGFK|feZk|1 z(W0&l@Y6^@^xYgkJiDDiu^t?U$jLWi5e}kgo5d3ld#P^M?-U=-BzPF)Q+=SL1Xkhq5;MW_vlIMxEm#>Rgn96i4b#dw3wBWqpp z?*TsUtGn*{GPN(Cr_Ry^q8pCT-2Jz6c!JuzsOy}$NE@H{BK1z=_hdQeE?*6b7demi zb!)+HagpfoQKIP?{cT$Ljaqzta+~wzx@_1Rw0P6D(;=Fl*RM)ODF4}Pl)EAUg>nuY zD$YMA-b@>XG~=8sF*!)6frLyd27|zb##>ZiaosCr#%?~c-=*a-ARDgGa|k(nokQQ4 z)rUGzYbbUieASMm^6# z_EA@>jnO~FK2n+Xr0U`^gX>K$Y~Tf&Pl^i1Bm#t{v7j88vd?T_x&{pzj0{{KF?UqW zA4R#ukp_fyjqzclR)?t%)-Y&&{Ie03Sa{pEy>yv+m(Edl`4S7(I1AmRjaf^c7Gen{ z_rCZu0xVE8^F%2o<{8hv0UWKKv(5^Nj#T>g@q7D`$;D_x$ta)ByDNFOgP7I zo{+_`K?6nkf67571YSjgXzRYsLM4Ovn8n>65sy3|U)Rm-KoU!Zr%(A9V7Hs-D;@%- zto`!ssLR1}@<-vAq*5QGd^Ar063-7vd8Y=7EwqhD6_Z#FsA@*xTp*|eHuJMcr&U1> zCLP*Kb-RAt*w$hz9ZWdaq6G)vL66Jj-Z0OD} zXgZuwIw>c>!v>|uHP05?YO9lG(MQTqW+NdVvdKh4W+Z^XuC2|g-gxoe}b!Jlzf1;C^hNfWzJ1wA(a8$(fK&FY1-x42&{XQhN?flBx zHZO}Y<#8;taXFI+RGQ;c2$abJOq^+zlcV@w2&?j_gE3^$puxceCZ-{ilbD#DuW3MO zbJpX0=RM7YwNDvf!+G?kTGX4Jrl})~L~UM2tz4$5jb&E1nRtDN>jko~yyc!(lNzZ! zJ-g7Ts2Wsbx1aUwKj4B>@1ir(vzq}ZFU|8s817k}hsr{|kBuukw`VysDg)Wdj-4jv zqcYV=SqR}Dq#1NFOzQ$2}Oxu?a{FP}d`PYHuUl{4PmdW#SV%Z=RPdS={SF+nlxtVksr$n6R0KXYUDF2|vI;?YW^Vt;}O{f37 z1-aU*OywTea=`VYT-u-v-kyMma-A!7cmYtiu<6uZqxSLz+E}?jy<;;p^UV8cqr3rj>_e2nO^%S3COpv`k>SN%b9kTT>DLWT^m5EmZAHJqN--=kO2Jx*xTSatU=fOxEp$T0l za**km#6%DFr(t?4R_xf9%#eZjvg<{_ZFnx z@m2Bm51Cs<fUE}j>^C795QQvC z#cx=NyV5*9O+)07<;}56Jbea+P zY%`YQ#wSX8=#(Hs`W!*Way=-Vb(?Jm7l=|&nwHMw-|@6rgse30274Xq$LQ33(wlx7 z0~{1*i*Z~;(H!d&U!-Vu_#hpRU>5ML4$pDMi>=!0jVZovP32Camk-hgIp?QgMtWn* zyo4FAwQo=tXfYsN=PCd_Ofa|4p?8)qQTy^4>Q1lH^gTDz;=Q-h^s&Q48>~BhiRjCZ zvrU^jS*{Am!6?GxK_`9};sWL&pPkiB*rV4nzeu#c&ShNXGVuoO9MR!p`W466(3SJ? zJYrt^6k|Qbip)}bj)F1e<&FwO9?*#+lRKY?4^DtjHXO>F(HGY=na&>A_y()l^DJg* z5F$;sx$B#_iAQ==M*fsnIkO(OP(`64Q;#_2QT%xe&KqMX`g`6ecZ20GWQ`M1^h8Srz^@}XPh!AmLW6Es0>x|1`QhYqt<-FMzUtXTFK&N zfY?cHw2cRle!4}i*%^78HpwHzo)4gfSvqpZ&D6T(241IksD0%kwbzz7+YYPkTd`#6 z273gWPJZesk;*y9(KsLv<~NCP)}s&GHUDi}g%1MaMa!ugdOwrVXwdxSiYgDvv@9I4 zV#B?uL^xZ0&ZqaldimDta3nzPW1SE;lKenP?`d=#!rE=4|ESG&0EG;r{Q+rj->fZC zU5sLTKrn3Fp~YO+XTjG5=wK6D7UN9wDLMw`855H#@nvE1`&39v~sh zyiVH&F34-GUCReywota@nWqMO6TV0@mtgF#-n4tlQs{8dnKYe#B{U=PcRuKt3OAM@ zR&+T(=n)s2WUF7Ct9G7dN;YrR-tq&_m5~rS* zTHGts-3^+$a-L}QB2Ar`qq!&DPE$9YkWJLi#bxR|a)Ekht`e>DRiHbqos}z~igy(C z7DokUX7!EQMSG*R*Cv`~W?@l(yB5D&3%i8K?{kdxR4X#ewe1$+dDYFbIJkA-3xvbL zMM>ZRA7tWjS*DZ6Txnvl8!iyb#LRdNd6wc(Y(&p-(WzWEY9&Oj#-oI^Q5(|dtZ_kriweoCorAx%-DIgI%6)usNhYC=egaq8eh?pb}MM4Xq|RCb#eq zzMjTuNH6oF#Pf3G5KUv=gP?VDo58jX_8Q{29M2d{^8zDn(t6h8DI$;U$a6E8lzKGS zPSlwI)kY`I3=-o*HkBJpkz3eSOv))w4w6NZAxzStsPflbJthoZXFpRX-)PM?XF*tI za%huLCNB^l5CT!2&kNAwj)9BQGjQ~mKk}R-c{bReI5<6vkx-mp%MfooV(ah{MdD7l z`RpL%2>2AYFcD9V%IgNL>UHzh?KKZA0eJ%mmB$UMFmetJ`cc^~slTQ76Gb<0pU}C# zL*3QO)VXq&dNUg|b=x&Gb^oo@K7NSW+)16sS@*~#qD$-CVKbb{uOb$d`d5`K$}Nsp zJ7zdvY}P`Aw`S)SbdwfxTwoF+zmu@K?gpWK3!+LIiV7p?!%;FS+J`iKc@?Q9c>Mc( zpcDi^3={DI#1o9#D~}L+r;zHVD_9oDW~|C|gBJE~10ES^C^u}bLx>V$dg#GR$tVoG z$-%o0f#}sz?VJGRJ*IrrMf6(LFMg715 zhxn5)68om5%hqIif~y`S7z(NQXNpKXwaZR5t|(@abA+mASRI^1o8C& z)M9>Sidys2G&RHPq%@ZStm8k0&K_Mh*;t&T`8#i+nd^`9)Ui&TrHj0dTjR96^0xft z_i4Qjed~*$6C|bptR9P~vK=4d{mj@)>p!9G$M!ebK7n^m?4)9cRd-=R6T+$m@X^>iupe13Vt{uEHSQ&R`!qtF?bxZale zrq3A2Cr~?XTzO4J<%xHFUn08#4)Y=RxVEj;GHBYLg5FY%wO@~E7D$rS2=CUmJv@zk+8 zXq-Q014R9%!I>2MKo`l(SRY59074b=$eZPXd^spmgS`cx3o@VB-#v-5?4vLqhMl># zj@rx62g@ODU9hDf#BqI7wwE?rbu%^)+jLB?yr;1|5`}!3P^8|d7H@pB^C?5o_8_1* z&jHd#@OOv|KZ$|E2?IEgI8c~bEWFipa9i%c}oVbj%lBipEjOwuv$q1b6+k>PDw(P0)7 zo#~-NVP>PSxP^%0h_rylRFZ{&+X0r|_&oAy97U@fw%An@i^}sF&>92V0_mIp?*}Fk z<@uyD&J-599^g>ed|ceaq8U`D2k;gqazuU*+^%RJ;&roX(4fI!^vy32n9y~yF$&^q zf^4QDWWxW$&9!KX*JASRB4S?{oFR%$+V$BM&7QoDW^TTL=+HE^moM_#?lPOTIX~pd z39y7Sk}^P6E!kIJwtcL(3C+Oa9e}=^~X@iDgOOVB(SU z)dJk2?uHZNff>Hq%Z;SoO!@{bhpfcSr@t}lo3f%e-oNhHNp4s} zex9eSDQp1B(t=6OjmZ&tGdWn`29SO&HVhE^JNSV50s2(aX%vl%mfxUu=PIpUKF!=R z^=>{+y(ipC>(?IPIQQ4373w~Ek?8RyqP6fu51GhUC`e|30xP-!@D7ASY^-zsE1c&v z(E`5u_>jI)+aO>_dya&PymI2rls9Ucf_>?LHlYN3Kv=x@kVz`&0x$O|AbCp0ahY(O zH(gF|Aq<&MUtcUXd0zAO4O`_UjqsLMDx&E`o_GLySeRVGJg;_ur&m6Y7%%D$2nM*` z@D?d+SMW{>ZGVq*==~0j@WLfo(jgSqc|O8Eq*sDSL$y&BI$=$ak_nheJdlg@MH@6| zFeVh|9ISaD8!#6sf>FAW#+=WTHfUKk%{0&JAf_G%y|jZ^2<-s{{%N_*>$3KdMVh|- z6t!+RPVJ4Ww0`+4U#`|zkBwSRgC(4=-@GcmQOgJ9DmhCWA?!SofmfF-hCC92e%pir zs$qzwB;vBNb#5l#3S@a)My4M(IBW01216mOWwbeDK4XHK@DinTz6i@t|1htF%~mDd zOtNvrHWG4KdT(7MMKN?pT4np-KEM6&a$Z`dvm>@*pWfJH zV>*e0l{k+ZlXGe}$-n~FmjNm*Gm<0n4fZDBEl!x7o!>mLJepWE6H|l1D4Xaae4=Kq zFmd`kDSAsU-loR7&|y{>^a3mksi2FEf?B$B|CK+66~%CgDYjxN{28 zSwjhLYT=a~+>nlBJOVgP>H`-rNgbVP0_h_G!XxiUCT}pg@bO;s)oSd|UXATgwwo_WZ{s3uta1dTUtf$b%gt}XDyiJ{*$phxVUrhmW#vhptjAIVaiDBG zCY^-`2BELHnff5|1hW&vNPvg9;p|YSvr21A=V^WUJoTF*=`dpEpfO;G`E<2&9R&-@^EU9 zwM7{j2B`9=Fv{8IA~jJbO(-+CLPCFF`r3U%2r}jMBSvyW=y8~cT$nt$l?NJn#F0}P zz&kZ)&|osalT~g=azy4~TnF^u8q-GY4BIZuP;Y)(zQhD`e||K_c~E)0p|{TVt(&i> z*;}q9n&)&^&r`R(!s&VC&G||`C{vbmVO<$0E%797bp)G}djwJaD7QQCHL{S&#tLhO zJ~H)Ik(SR!4Ymv1X*QDFUy2ZINgrsc42Waog6vW+gymq81)VP=g@@b-h+&iuLiG9V zh3Aj3Nd6xlPWuGhNwSt}uw_I)g@+V6$OfH@Sl;xTPR_FSGMcPjs@qV?w+$ucp zGHNin=o|AxvHyA%Z6E|*MO%in5@)85g#BYTlnBK}=g@dVDmS9cl#}Y2O=(hE&dWD# z#m@4M;~x-Npo4_e&q5HWd@$6$64tidJJjuN(8lT&+PHXzdY!8@d-DmJyXzFSu06&! zEt*o{c8){jVoWL^;hi80JSG-IES`I77IC*pJkLg= z)3EMFZ7*)rB9t=CmdBacAf776GCqn8bHd9^=rJdNLp%i*O(q-LMy;U2ZZqA!tthJy z%SNbY|Czd^*lyn1QSan%3l4?N_mPw8jf_{H$l@wPOb#h-LJlONay4K=U||)adWdO* z1`WoA;$XuhK>Y>UhcQ~9iC^lNrHcD-7C;exAxTX9X?0J;U1%m;Ps_^$ch&boi*yL zT%q=*$EmkSG=2MZ)Vk$bnmRmBE$;NGvsZ{7I!APInW)XJ?oag)N=H}-q_C{AE|Wz3 zXU1?WY|t)q{@pgw{9&TGd0q|Auo7vUfUFi+DyJxX)5IILyi~^e9p{$ zDTYN}NCeC>lQvrO@x%-9Y=lkMq~o~QXENDjMTpFOqZT3TAWM3LU^!HV31bjZl?iV% zpvJ(Py=eir%B$gm% zAMJanaIjEV5rWCZC5;L)xTqi&RLKP;ib~rC4H}G&IG{=fSDde++BP^7;Vs%0ufgVL zsCE1((cwkvO}9c4WK^8|OvZos!jlbN$MtTyj;3$EjxSxSw0`vhwc9H^JGFV4#@8P% zQ9YdGm0TnsCqp?-C8+H0Lb~{@V0++she8L!?dsSzI4FRRM*nv>@7JO}uL-`5G2!_D zrL(@6TL~>pg}nXO~uvQ-UJIwoEZ#v9m`I zFK9#2fIkvaJ`0`SDsb^E>r-@5e;ImlZqNWI^_zhhm)A}P;`wjau<)_o zPqvB52i$Br*%!0bCdtD>AwG<{LA$5G9VK%fn9X35$%^fi+Eg9{GVpMYd#~GGrS{4t z>aAU-sguX3d*_YRx&A2iW?MA9&b|BaIikn#7HvE0paia5%Gkn$8Wl$xyhXdZO0>o_ zGfQ;naP~FF$RqiDjr%1H#W#TQN#c|Y7#<4#cE`35= zupbE6RM>5y%Qg@96{ix^s#p1WxfE?v#{1DV+6Nlo4&Ukrn&ae8c0g1!w70 z#sQFti~%eZ`z)G6nXHI9HVqmysD_WB0n?PAs875xxd#$9s9XFuKTEU6k5cRKA=#uI zSVlmXO*`|vmb&gZP2YS2bq~)_d+7qTS16 zKb4)rzQDdcvCUwZ|GB>0F1ydpd$RB&wlmTc^N8^(B)eE1^PaZv*`?{q@*e%U$v9A_ z%-yJ0gGoo352tHV5k=n)@u7ZSp^oD}!;rih90)XzMFkuazv}8eCm?R~Y$g+pl zx)5QW|FH0I61zfrAeSdtA=ru}Axp0dEuZ*f8G9A6?xhzrhdt2gvk7u}#={5UMQU;! zAvaw_zwKy{-siq?(tZkXnaG_Q9AxCi{g@HGtcrFUe*QaAA0N{)PjZMo25c)NvUrE} z+3(DbLYyz>fj4uzAj=n!a*cKpaXuP1@hJUKNST3)BAuRKn40h_3t7T?)bhJl?0Wuyp>udg$4{@@pn5-lw7 zO4yge)^Ou$hy#y`cC2jPD*GMk4|f*{qwg?}XwoB&wF-EP12WM#@gb4MWkbv-BMvnV zz3W7%AvR&Li7NISnmkM6HcYTbA<$_89{yD6Cd}2Ay-24szEyAL7;r*-=B6ppRV^H6rJ<($}%SArszY0u9wKgj15V zD#_roK1G8D4R#zDhfYArxGc_HepBxu0?;(C1sCUN=GYNlAI)cP(iYQKpf|&7sbhzz zg|}&Mx|TX?m#DLRfw~*ZoCmJ~@pZ~l79X5|LjFlrq>Qnn=I7Z=8f0y4{I;Q_yLSW= z+UC0hbV3yY9+pGyzYNh*c&MBP!EC%#r$O+0Zinz8p9q;MN^~hrz_{-zGgt*G$>DsI z0nxTd4Gs$2KYiR4eO*!E6P|_xaQJ#-qz9k*eYOuE#3H;LP@SbKq5*iP2Kxu)-d2WY zleWPgLiuDhh2OE0-=NFu#2OQ(@dCtKJbALfhe?`L3vjvEdM2=faDK@{3tRu(|88Al~5!mQcA2O#Q)aZ`D$FR@0*gDX!EM{KfOl*Kq-lhd#lk{tou|aG3b9%tT zGC(&-zggh=ll=zQHc$~|HdQnV;ux{?#Wq7*L*7NN;Q?KDjk>E>sJnKV=-529?!K9( zZa7Z8*%|7rwQ1wr73w^6mU@@hh&Dn7k~!xbHw^6hQ4ZFHqzQP7c4e7py-hT?$aOeQ zG(D|4w;hyigB?KZuz($$llxHS6Oh@u#Cc)dN25$89*s*1Ok&tHm=_D0+*MsMo z5cX+<)tYKK~>Oyqo2-s}UpHsg)(hExt3&ulh{ z9qIN_3)#&1c$%2j+a~Jzdy1JY+9dz zq_jE8lG;IYo}Z(c8?U9qck%j;)~UO6k$US(tZOrIJ=ipzg77%#y|}KAA#=jLh<${Y z5;!cPUotLeiFq0Yem}LH=<6CM=+tDa;H;H6^GF99sZ~m7IN73MI5 z##IvKWhkZ%a9?p6D@M(5(0NqpTpsk&hE4$-)n?{)3vI1)DCF9oO6b!}CiYnd<_99- zFxoiW*7A0Z$dr{($Qeb(0UUF+*o_f&vKw=e4H`@qc#bN0){#dVfD+5VahaEm&*=-3 zDgtcMF3eMRk;%X6IGGgF7oqp*U0z>xk1opkj;=dQ?TxFnzI2h=?Pb13bd>m$vNdEg z6X(MUi4}JmIrL=!^tfAzcPx{7-@R+~@+RFW;4~+*3-$z}o1p6=0TOx}2P)b`0wi=> zga+3GF^yA1l|F`14hV1M`SXSCgPmZGfXEL*UAqSR4epnGz56@U{~teIsZ>IxQi&xw zCH4v-hb>XcX_ZQdRZfX4A;)b=qMVW>Im}t*uu$Z*Rmz!RnB(TW&1vjl=k2ri=X+h> zpT5`k@(=8CJ@5C&?S8x8?zh_|@s7VbwgRKB|4R4KATlUtkg*=GR^dddsK(qQ?elMy z*rc@*&(>?9rjNYc0K9rRVcm34Ucce$^8{{TWzbXmR$YTJ z!uqoy4%ccsJ>GVUiMriB6%j}GQ(}nP$S(bY6AJonoqcvaCqk_rZvWf3w%t~EdN?#* z2Y>I>U(Ceu$>pxIZxj!%E)|dM`Rly@Q3&DM$P4|v#~%AJNq3;ddj9jVoP#ED@hNvf zmpvtBG>Gwh-NI3i$WkL{H|=fc=Lwgh!h(S9gUlK)O69QSP2bn@BhJ#kOwf?C#lb_G1xlblv=WX>FrXAz1&eiuJbl~&1Wh0Wy_VHr5<>+UTgLFEb}X0FZspSMoZ8Y zMXO&c{PBIOUX2IIMJ&&;ot2wsCyp+Jyd!$|m)l3YOn9?Ht-F1p?a28g$m{|4?_+^0 z)<-3`O6Tw0d%rg&MEIQxnRQIcI=ZB*SL`sJhg`PXW@Em5Wvja*UScbioUZvfjBbKE zQ$FOk{hT3jY`sd>tXn2CgiDn>d##vvPWg~@!PRvv=kOV;=zfF-`o}o zW4zE4oqs2`GUNL7a+eSnGEn*M7H1^Pm0ad<_0*X+5&vpV?JfJB?RhPxCUGHC(!jK~ zqmo1`gkpVEa*Y?>S8=u!Sl`_b{m@>HHypL==uOFZXym74Z!-IGJBBwa7lFF`ZoR<# zb-p21YmX#(zSXeDw#MYGRu=5UjjnO~Jn<3pDx+yu!F6y}PVH-@x(gb(U87XQ(fRB( z16d7)TX1K|FuVYp9uPx-Lrsm<@emsvi+o=~- z;~HkZzNu?*uETomw(`;s=g+~cZJ`A80r%hpS2oGA(m(Zve_%@K$k?KUJO$>e|8Z8X zPpeqpE`Mt5>KE4Zzt-JGCV1ICC0KkHle-u5I@xGU&8dO@)@5>G zG&)xJJlXY!CGl80ZMbWN68YCemPvo6u_d=NJrDfH3f6pJx)G7pQ4)1`Eg?eIN;caT zHKs95-RxL5JgXb7DQ~!@JKx-9IE1;8Vs<0t7~O`Ku71%n{wM$Cu5&#BszcYjzoo^# zYLk$6r$>sqGJ1b|-{R>`4>$@&rw$Xy$IcV|wDws3dBZ>j&|iLs!mwwzVU5k~anJ;7)CjHSD= zZGB+8OnBZ|T293iTd8(xU4CFhlc}lFipDFBR~GKFOXD-k!}f3@ZcEGc9lUOOc&J3- zzT4ZtN5#p8$i&|AS27$u^mn&b_Iq1R8~N^#Gl|(DPnd2|w+eu`aeu#g1< z(`DN2Ju9zW7-YS%xiVaC?c8^u7a*~czDp|J z;d*-~9bne1m-K7#dg;BR2ymF^zghn74B0fNsb}5Vya5_lE|OTAcmKeSHi24dZUIzS zSwA=-qD(O-eL=}YIt>vMXc}SBLdJ=5L_{zTOH~6Pe^nT74U3&8?ZECrpzEUdfzr#5 zBwaEwm#mRn=sR#_w1_$5felZap|)?07)Kh9k=hUDmWWS@O?85I3T}kIOsFkj9Pg@! z);QEGTthA&3(|1R4;p>wTFo;5xzqGE_w&v_cBb2p6XEpByw|XB-Kl>wiVeL;ZZ54P zHG0PG0smz-WB}4KqeS_n7Eg^qn_m>qq>`*qV4=x@H!8)rDfQYd+PD79e7>I^TxJ>( zxUDYcTFU9%?sLtFLPk53ZQDp5No*$0uHEFWNh#8x3Tc zMa&+7lM|s=fKgrPe#eBl{Y4D(dLco+ITgVW(uTGBjUT2#0`Z4W;&*4A3E0$hm(J$> zXZg@n-t3qy>(ouR7nAff6X^%Af(vw;hvxSzLG!WgGCvu0ZWLcpAE}rYJ-19*;mR<9 zqA6rCauY3%^;6o_{|s&g-1Gl9UEeU3NsL^F>;GD~VCnow{(a|>^FeXF2&;gw^@KK% zz44^#_W!WmteC6wG3`Kej#~u>d@dD7f1W#cuD#dh3#%gP;bI9cpQub&=k0|$^gIpH z+UI-Yndjq6W(NO^YIT%`cpYVaLV0mgqc7p%CTI0~cx#KHS#VBiW3b_Hp3f|wE2p3c zWF+?J=4?&Rk;C6SCaPn!ky*4Jb%L@ryY}ISN>=}f0JM+gKMqxQo+$H& zjLhq-nxxdLes1d4c3T4i?mar5xFPm`U_P}Ir+mR`la$KUp*M}8XJ z-zM=CD)_TAdzYQvDcmvg;RK(C1E7{5HdhSrsp^XBGY8)zs&nOUd_iplGod2N;Ws6E8%eoS64&7Jv2 zlV}5J5gtzQw6~O&I2PW|JYRfscYM*S!kW#gG<#ypGZgk1Q+ zY(q!LwX9!d?{1mbX5;H?fZ`*3`qb#pLr#HF+!Jr)r1vck3Rd<`h2b40iI8GN3+mOF zJbS3P$9I6lZ6o02o9V*=Yr?%35gjkA7|Hh1FZyh^(^Nwa;P*WV-KTv6bgY-Ei)#KR zQ7KMH<$c>(bsnB?dg)^l9`eI==;Ft`sH8n`J%fLQRH_oX?2A&>!Z}59?W=R6r^~B1 zx*1A~x65nx-FR_y``K-(m8H^e!p=qAU)6oQy@unccJBVeuAq^)+MEQkL6maT@67nE znCbhc!c3H<)1Tyhwn{s8+~j7`d8FZWBMmqR$Nf3>BJ*EPevyP~v9$?fXE{_|V+5$6J!!(g zC>u5O8uw#kIJXrck{w5I0xH%cjw=1oE&W2=8A|x@ncz|~QoZ97hIMM7V8_yTPN`Rs zT?pd!|CFlE#tEhmjXgeXT1bvqpN?|8T44K5tUUX;eycs$zV`DGos;K29y!=3um7$Gole+4QWh2SFcJCIeYvxW+GjCU}$(dHN8g$0MQPuVx!|i~mZ$ zTi)%X?WoQ^?V@+-&;ErI_UxeB(UW(GI&8D2m^Rw!=GX1XEd#O&vdRikO{!BZg^9aU z@!MwVQd_6Y?9f*vMz0mWF|SODJbb&N>mS)4_LewJtaCKA1`h2apuZ-MM`QZzQo4*r zi`I$K<~I$YVUzbVuY-P5yl(0Nvs38lnOpTmiE==Qn4Bh6e#0#)A^ys)bC04oC7U7rTB)x*?ZxU_@3}Ws`hAV)_bPr@ zU5rMfC+gM?o$bb~v~M4(3Y0C8Gg>^hvgKz%JWiUw{b`;#;pDx+YknS$;l_^rNg#}`n3>+iJpiM8ox|oxS z%i0y3-ndct$}uU~_^`xut>$9L%-OwzbSz(8{1f$#X4A zMe$x^&}MD0VNnl6q?Ow|6WK{y8upHyFe5sMd6@_Y1fCv+S(Rn}0CJCg%4=g=JOGy4 zp^)o3Od4WAmsx=2Y$myB~nyv@#ul(W>xnI}dwCtt;9F2hE2@v70DtFnxc76dMpdQ9tm* zCUwxIFF3coy;FhE9|h)K<#9<|TaIMxg{YlI2HDE z)<3R^`70Ap0F7+tQv@06k*mRZwrHftz%Lf31jQv8Kc}4!m8yLFoeBYQBY0C_v58P< zjQJF3ju`Sn6+t-wq*ufKsec&89BF;eRVgncWJfinwU7O?7cv0mFOzJcy&!G@4xUD& zmjUvz8==55vr%J`Xdo4j4PTz1#Geq&$CsOnTZBb` zLL`5)zUH${7^?ZT2uu>_hLC#e6Lv>a1{h=t7|W2S0I{4MJSB9Lg#}HddDWGIgJP@! zVgZ>dnxN$?m?JTX@D(zGn@N3LKjkRq%ZpC9hpm{vS87ouP$2+TGy%yiq;VHv@6ld} zi6)|*c+r`3u|CiADwtOaD(@s+j~rpS#0!Zw-+B;?VWldEQ`H(sIVs+q~?QX^bc zs(IwAz-E!_Ml6W~fR%x{(>7EaEO~+&fs1UcKsh@T9zJ{a%7b?f_ZTB7<%ho6u?OZq zk^l2}@uFGFj(XmQ1M~?q4jfX?V{6J!Hg}t)BX=c8vdDi-^*ArJ~hvtpNG2 zT0vq=7C>n{T6#VY=BQkfg>FogYkAo|-eNr1WuI;8q}06fhwyewK>W6SS1eTzW?ig0 znKLzOn;i)dovOsrJcr<%)4jPra~G?y>E+QMOPhj+mU`BC-_)T6dSc_34;phmMNBm< z*k`S?I%}F^lT@4chwM^K=ZlMP22k@R=#$!4dc(dok5g!~4h75zNbI)$QBYmi*))*; z$*#WtcrOSZjBPC9gDQPR{~ zpUC$=iIm*x3y;o75|_{Z;^u6T&zj4Yg?Hq39xpTi6>_ebFI@jmZ`=~K^7OO=^gEjh zWG8W+w`La}*^{2=)&K0K%Oj`rHD`)r?dPAV(|@+>d!!M9KLVe*^^=`Sc4-dZJ9%vi zHc)gqo@}b!qMPU3ZKIU54GVfd;BnDKsFtBh{XO?NX}?_GTylb(1K!jD?Ou@44uUwz zC>gScCj2(XAf>VbJ@QT^1lK$iym4p=v9@>MQuEb`!OjVlW^V;k1HW+B^V&(Tl0N!K zWq-G`Ud~~s68?W3T;SWv9FfeNWR1`ruWMHR@de8zz3)&bn9ZZKaC()6Q zYGT%U#)6rm)aWG9Vi?j)ILdB$o!9GaiBudU1({7D7}}8n!496}yveaFHmK%5Fa#1c z3uo3y$~xsZ$l7=+T&iWw8(4}J@nFTU=rOxd^)kv}Mmf_Mvx@F#phPzt8H?EzKQ_?{ z*DT&0Lg+Qd=NeC0Yo@4_*h$)CcOL6ZWM6uo*4(#$nCO-D`;Cho`x~Du?6Fv_YNFU+ zso4}4HqkCD&-7AQp1C$`oQM$0hHMV1FNHKQ=PHn<6I0!EO=6_Z6rz>IG+8F{e#@6g zOLg$)H$0h*zTj-fJQGLXpYlX*rhLC5ASx%+qLKQ^pCXHkN{L?Gup;;2eN`+RNW2&1 zfou=KxezcxxVem;i$)hI#LEqo0nR(f2WJZ^32+2dN+j(rT*Ncv;r0el0P_A`y~ zbHmlN&pUc;z<{1H2ff@0SeF_G&%b4)Op zuE?as1;4v3l1+mjCUYLFG0G+pX1ZuJUK+%AiJaDf7G{DLzA(GWz*c?2YCAZx8i~DMf=FD_Pd3Bjp}-4|Kwnq@s~?+B z2rJvZD(OtcuNLjhFqnx&4S3}Mx_~1RUUcXlso<}C@PU+R*X_uE-lvz|$=huyH@}5-=DiXa*#TBW58T^LwL+{F8M8*alpo<&y6Au zE^hu~Rj+uH=>+}cP>3r#y|t;aPPR^ILAVn(`qjp(#r*&F;t7b--W|pz-^&aGcCV@q zZOGJHQr^er7%xWqS z_^OnwNy$6WbQE9THgV5n{E9X0y%IY(vs*d9;V2ogC8&S=*Z}>2%;;g*Kwlpv_9|}T z#cQc0M81)q^0+GID*t5@t@vNuj}agOlSsSY2d8scy#&!h}RXKN-XE=6!$( zc;Bz`J8{u@#PxA>2>~;!9whV*9Z|2&}*@(DW+gy|MXg(YzF(AWYE7ry3*3 zkD1-#1#FkI7Qo`^$2DK!fSL_uX|N`sd6o^U4&nijb67k{Xd^ZjmXQR?JYkqvJJ;k{ zk|-0vR~>uEON1a^Ar?{MlR}~dtV0%po(y!XNeh>1&PYfz6x8BBIt~ zfFLc2<+$uLpZ3!VW6BK^%|j@fVivZb9q3UE;FiMPIgF)(IVXfgP%ebIDGyJ`6aUp5 z==85DFi_MR^i@H86m`i!uV`}2t2Z`3utmFtu~6Y5UTZ2msn5OPB#WgQMCSxWP6hwb zSk)B0!-OyH^)IC?`aAY3<+YRlz!@3AWJ+)u1n-Yx?QL9cQ=-bGS~z0YN9yrl7NkTQAGb~CIPVI4t97ta)%C0)^sI)5ALQY2&Nnm9dULg>q4V&oev&Uxwzz`(; z3vM7DEcWJAvf&>Qs}_J_w)y&b(|>;7W*Yx9)`XE&KB4CH*WUN80&@^|SJsWr8b!+k zd+`{>vLpZw|`-;dB_}0MVMcq;0D_Bkx(%wc<0!pI&a=pgc<=== zcZ!w|jUWI9CEZ**a;=5kJuyhBPjp82hhgS3LX`RI(C7^YGZnF#Nl_F{!1`g$$JPKvkldSao4Va;MGW+;$%jF$onPyWtEid(^@0Din!S~z9{(vTeK zz1o}(T3?8V;C0I!yL?twdXkdnkegzG^wIkGh>GZTB@a6Z_^^O~Xy@UC<;D_PWQ~S* zwpe(rZ*#B0DEs@N^_Z0ocWmy|9;v98*!|C z_-aRDtzoF(Kh|O2&)swtqesCKd+!CE|1b}w&Jy1(EZfi|ZCba|$$vx30e9v}+Ga*q zGjX|d@yxpkgY7TRmj7jEzV@v4i8_jSwPCNh)2(92IuCE{8J@_R%3QtQk+rUxH!z<= z68VvLW?%R%&u`wkO{3{WMk~u_`3WFwf56SZ@#7*Wq3XAn+OiF_=A6m5U)FEaOxvHy zGw-B)$jHczzjEC;Sz~_L|H5Qp!;Yp=@3&;EkBr%mLj?<2Ha&KOD)%}F`kYqSx@dnx z-L3O8Mdl}(i#OV@*@m07U1eI9z0cgLZ5TD9!~62lr&f!RzB4^JpigTX@!PG`kLHFd zrW*OG$$ycXmaQrJ$XjEPZV4YEgb(lThF+JLS)&KWOBm+3dWn6c>k={ABJ{A&mx+Z4 z(I5R#m6i)F5?Sf(@kUFXFGuyy#P^I=L410O4fjTSKZ(lqRVp z(z#>uY^9^gTT(F`hZ^h_kIN5sW0&J8Xc320BBn>d+P7V?Umxz~G|q`d?Xa6%8aKc3U?r7xENU3pz*^+8 z6ZQmr5-m8Z6hI@`r~zp(|579+CouX!U--O0J#qqt%n>o2P(@e)UG0X7ky-W8H?nh? z7Ayp>lYq6w)NmxN=_J?nfk31{42etjeC!zu5|zYLu^6%1-I1cn6lGVJiD|k@F%(Xa zezzC9Kh9xVEpa8bK4P6n?q2Y_JNQNM&uo*{==uq}w6d-GRA`7FX9DY{q3o55w2 z0g6!J40OM|U=~{zCR`}n1-&nrLr0wxPKLpiCftFm>@{hSIuvpSyFUqZAu1TzLEGb& zjSCVJL+Ph1XuH|?N`i+CGQ@eS5jXt&ml>dlVZ7jIenA^?!OO`wh zBJD~gQRnoUTVR1EF+#dBumWG?i|aCpSZZMpb}m{TXR$zx@)G1>!_$b2 z7t4b9B#jBDg|H||6O z%a9DT(5Ph@4k%2uSog~#3U%)MPY@>OF;B5d-FLB1I@j@tC6+i7I_5ndzJA|TJli_d z^wZi&X`@_Gq4kN%{S#+LzO@cnJWHUo`9ECR9CoKo$LtJj^dsD#99Tu~Ja?k9WM!+>fQ^Q) zpinOM^KZ;$Wxzq_j){fEV1i7;zUxhne(z_DP9z^r8~mkF@b{ZUWN1V-&i*bf2O2#4 z*)1+6SC-Qg$WP12+L)=^`n9(U^E>j+r|oJctk2;f)x)S95*J zch<5iaKG8YA+7c=d#Wakpvf7ddmQvDQV@?vm*+5R5u5~yX4IY1arXL#8-`R)7|c(8_3HGqIAeUd*)# z;q}ZtP>3PHT12i>>#a&ZM<<0#z90vqu#MrboXTzjeAUj|b29@dIyTlU?2!bnV>#WB z&NlTY8-v~v{+pV}P1GRQE^|KFC16NYNsCfw;gZE?TUPuruEcdK1jnM+7cA6fR+L$| zUC!d58em)R^)E5+Hs9EP~>6@yDK|0+-iUJcg`EnEm+nY zV_yI$EQQgkaf0r7QR#}vJ;Iaz=N7z`)j!!BP&0e#+t};+i;6zJ-bF{a&HNb1AP}=E zPcarTrE2`RLldwPXXG%RLc@s8F|o}Xp&^VPn)Ak9)mss2^k_wob~Am4WD7W@1M5dn7|?g5 zTwSYpT#(=6WIc367p?20()Z4ig+rz|a+1U3=-e99M&q9luEm3FCD>Gal@>9LAJl`wNftF@Ts}Z} zL^#k6>eCKYPL@BNwse1nTkb4@VC#G)3(Ut3_=^U>#WZdv7=qob3QG{Rd$1jtmB7f| zaF)UvIrvVQm@QAdocUqhVcVX7zoJQ)$X9}(5eX^Erq;Ly8X{6C<6#eGl+ub|(L@=F zB7(2WM3FY6XMqqb-y?F00lgxgZo*_DDA~jd0KvS}N@912V12)YYeCu9=bEa+aI=+T zetGzfiQ4)+^Q+yHr6|#C=HD=g2U1yY4}GVh;K(mppI)r*dC}Qzo+H&5jAJTj)5QHA zsXe@rRhmvuRk#ux6cN*|79KGEV2YIgTO_@>wZ-U`l;_rGm*LaPUlMx_$21yipVs9yCs%P(3*viq+1FL7K#ug7hf2`l~V3Zg3?s=oB!^ zvQ0^a(wUyK!eWitu~MqWJ$9dhx13u03HMkFc?LE{O+n*6blW~`=+pmzs1u3NT>$a# zQ!kksIv4P_u1oH#Syevio4+n-#$1VgTdzdeLc^7vL8jdtLPM(Bx@_K$ZM@8K`26nL z=dWk#b=|a%A6ZXUGV%?U->&m^T*mLBom4{1eD;}DDPpI$ke+WBq~4(XzUE+|?^Eju zFV7jD>kB#(g%<_A1WL?1tCC+lwYd+7w8JcE-nd9Coy&huD^|@RBQ6X_aCWUiYNYO5au2qzJK^d~NWd_)2CRHv z>!J6}l)N$NoSP;n@0OBnRw>xIH^As|#qwocmH+yt{Zm#oq>X$=?$yNPdAPV|7}JQ{ zGC*+{R&2#oL~{MOpYZx2jmoY*Q5CW(AmPWrHOvNDrezk5018JTV$a5qg*{Ud{7U9% zRxOi;WEoR??REV9YhrfYQ=rV)0E+6HS*y%fG~rp^8kXh6{GE!pOU#3dYEi1t+BdR2 z$;n1SZaW|!z>5M~0mUC^hay?ohy(-=C9sPeGJZQ#K3lf~b!igiH|DPY>rG_~hNW?d8jfo)5ow8n=aW_OAUN4V0=YsP>x-ggkyYA^UOB zKzAQX_WP7!Tbt2NrI;>o!5kL z$B>snst{Hl1oOsloyc{PAdFrvE)rWKCfMTL4YBCt5u;XEHT{A! z{@)B4I%veV5eda*cv>cMmMy%`jYW#2@91rbhf$<-UuqxTg1LMoz5qvR)<6lDqUiA= zfqWN=KLMT@DUy=@DPJFAaeewNhmV|&Ux*U7fUi+d;#j1;Xp+Qh`tH_HCMedzbRAVi z7#x1gnRPM_KM}a~0W}8p{`^w$SZK4~4S+xSw2g~v;rWv4(&0nfUAPYW0M1*uf z`Cm})0YWB@Uhf0*z?>v8f6E)7vGjDXo_G_*nR8v#Z98ipngjD|24s>%Hlloir+5vk zjum5tc)_F9RLmxVJIV*00Mk2BX-G1b1LBro=jyw#9F)jI)VCoGjktxGQ-Ep`(04N+ zNN%_JP2n#);6~U(Ne6bLw}M3qrZ)B5TkSv)e=jn7QxnA1?wbHokN@Q~6s)ed`J=xb zbOu5fVfey8lb>*M%fyfrB`V489;7vj4e0PPPqR}5cEo!i0b=e})SY&Ma#7yaQ4vG3 zL+wC`6_9rjWGplLuGzg`M|UnFGy~wT^OZ*JV(#vJc|52A^Yg&g4_WTsDil}t0^5tu zt-nNU0T!*kE=}O8896>`N6sG#S%1Pvb#+`{xx|Lk#}jKdCmpgVc~4dgN*kIgeWqle zx|M>=^Djl)sWBuPxT?e|U!(csJqEKoNRA~dp156wDF&hL`>oTXoPgVZj^F}zGGi*e zS3oBIo=x)CComh;jV$Y|N5`J5eWP$cU-KMz;Q6G)YsPP?JO@b_AN?sRMuKfLS+&VN-s6HiF_z0 zv{n~kg(nnqoy;EAJhtfIn#TfgQsQR@Is5l$^2knrIHWOKh$6=~M9W2$D{#IJL*n218ll#G!=BYvY-ay;5uIOt6L0N^Ym zoe)du;C9GX2?{~Zq0>o>3DG6)lz2&OiI_ukZ<+ozUid8)9eH+VdA!Qq=J4wXYM3yZ z8w2Lr%u9>9!6%V3sY2{LTi8cB4P}VfZkCSoJV7{1 zOQZ3@Vma=wL|_*LzFB*Qpd=YGpy(Z*Dtw&TJkjs7GW9s*zmidni2_isPUn_~nxF zVO))viz6?vg|%2qQ9pJa*NNq(!qEZ)l2B%TF{9i3+F#h9Xbj5=o0p+Alc8aPPl6OE zL+1)s7=?T-cmv}`2)qJ}T{CDqK*Q132_INL(wdn=vJzNYKzlEqfN?xT9xM7!-1v-m zFxRhv{jeLm#!;i2iK?NFJYDQ;6z5PMbfnsM;YY5{te_tkZHwWo>3&!>18<(Ai$%Iv z7tth^JFy@ySVUe1(dl-WXH}j2yr|m=`nig+J+RcVPGFCu` z@#Pu{=QgTSO6;-~=h@;9$Xgg%y;zTn71d&05DYZOL*?%*;J|vuIGDl3b)~|W(pPk% zTQ>4GS4rG2SfF?rA~+?FL}7wrQD=~}K6h?SN+Pg@b&IPYo)T-(CL48elg--VNwjd7 zo+%z;cLKQb$ke`U_QvvGoq482BVyE$8`8)-Aa;rI!fae3-JP^iNiP%i zBTtdoVoun65dhKBL-2P-ue0-!Trks}E-!pRyT_>{t?wS+x!1(_SG4a#OUnw`OK8T) zdHV~x3VPSjLG8Aq=`CSU4HU1?9waQSXklL%3AKwSC9NVtJ}THZH_id77P@x0NM_xm zE$iP)v6XIrqV&h6Za}6`l~i6_tSd(T8?uyqdmkfvSxxEyjWvCaa&bOM3Tk#v5>LAe zcXAeVeV1w3tv{A>k7RCF9?;osxH6lp#BQri(ua|6s^ebcrMup07ugw4pOH8-&*}O2 zlpY>sO~G+Nc7^@x_wBU&oJe)v-{)8xQhnQAS&awpwIABtw(p>+8Y4*QEq7bM9^dye z`37gZ4XD}$XEf^evA#K&9o*%9yZTImeeH{{a?kKgejujOJX>6}l6 z6*7P3e%cTDAR=T2J3n<>2&gpw&(OA_ z)>2b;F=~_!lp)HI4;?YHyr5#YabfRYqg{KvT8a`*?YimzUj}OdM@|kNqbrKderw{afv6FIYSwl z1KsDRD?IDeHqQM)a#F?4^mvRI(%ILiC#jSsECX;t7)#nrHt**$kW_RRlskh}S2Qx_ zhPI|IUodOU~O?HQq;Zx5sry1MN?v? ze79KOj7&i7`%6$p*7HP#G|ue>?CrdUh*)Y*lCLz#f;-5-b%jY}Ht#UY6PQbw8Bai( zzjM{k_}{NUdfKYDX7O=ImW{Yd(4Q(k+Q&uL%SY>A@N;9@|gcmXDUjL29u zM$W5AKHGI!x;s?NqW3}>_al~;Zb63dbAp;ymw?gPFv#45)B4qMtUy8XLwNu`f;#{~ ze!`yP%V0O>=#>E83HePC9U^)!C`U5+3pPWq(0pN=#JCtcJqJ*S&n*L{VU40V0RJjC zRonyyB3H}6>f%16(09QG%!oh~G8Ll*{#QucYWZ$Li})7ez@}C>zt4h;2Mg5bo+$oF zJg=i1NY{A}W{fng1sP7`Ymu|k;!?pHnCmMEL=d#;VQwE~t^&CE%`qg^P0WL+B>-qY zPoh&bxD8W=a(HtOi&9%Q-w0S(@m20E@tW8jF#!gKrOQdhm z!qh_2E@t|E!8C)4Zr1)E2r{6rwKR=8L%IoAk);ZT*oY*}CEUe^xL_o*mrN*=fw_(l z5k%(PPtG3c{8T_ElI1K?h(HNBcql?TFgaA>Sd?$^cE-q;fUQUS? zRn~K^hDMicwzj*`FJ+J-*%sWMOiT|l`qy#Zyf0W2EDT1a=~m+91?!~uNFi8|x?lhm zylbW{C@wT%=O*T}K^s94v`uBM6iKYPKoa9byRaioG9R(xX>cqjDW3IhfJ&6D%Gd{^I%AT*OK=(kb%72 zaTl`xhcwPvxGP2#T-9x(wj{iOzaQAgvd9EXH`kmj7Uxg3HJi(4c zd!3k}LozeZ*C7A(-^g0@EZAt7O>k{{XCQx8^Y9Z3Rcr0rW!6$3WKwV`5k>}f=ePHu zDF^=n%eE5#>6coT)^M0tgHBr?&otl8o6EVCf4RHxR_pi=BN5tLjTFf6hSR7YKIPo;DO3%_a`s=rAm+msC-7+22 z#joJ~{UTi!Fm^`kTOBM=*MZ;XKmMVY-!)ru_EXwPFNXf3eIJc|Hl=5cHdgOXJohdd zwrUZ^)j(31HF#i7K9PrpH*6*0+}4y$ZM z6!NkMl2k5u+`9#|KY@ghfONMtVKZkcq(5A6+wrWG(D-DFXeMGv! zevaEFZSfjHMJ&od-%W(USGGPPjoxu4kvZqk*{-+oZqLKR*1&Jk5;)`m-?-Ee$=ZYD zGYp`S>G1&xjM-XT*IGCP!yK028W>hL6X^b4zIl((pr+LOpXP0>pwEn+lERm7Ug2>f zVZx}NE$S%vvM%B=jerp~-nEYM%Pold*5UvjY3=0f2Tz4?3pfAS0Xy*obhd|rbyRZ{ z4HLbj!_l2O*YJ$`E_y!0`G`K|5nIEFyObM6KZ;=03aeI?fFL05ZcC~D&BjbZ$U60A z^qxbg5jbnCEMlEgS4Scf+qN!$x;tDaTJHv~ud`-0B~@Kc^J`k6lMlIZ>>8$#yTKY4KOO>k#5dclNoE0#{R{a^xg1B z>PAyN=h1Z78ZiR`=h|Jdbl2Pq{IV*Ecpw*uMn$v{$|lU2J}I6|8TeSd=ad<4+1ZLu~gaq5fA%H zYszUtW0)_ROR0q|*uq8#a!uxm`Z`XA-;QiMTMhYg2r2 zug$c3n}7^T(?{I4vhw`W>e``r=y_=wPwT*2ZW~N)Xouh7Gy4`!U4PTsh?bM%?On}} zZ-VIYE(aSQJ~pS5lr^q*LmADW63jDCaPYw4=bpcEB5q5Lo&H9zd}{c14)f%h$H4hi zD!u^naMl~k4eHzDGxEx+usrVe)>hTk^V?Ml|02EDk7cu8ULGD0eyyp@GmUFl_+b2t zu`kPz+b)&2rKFFpo?CM!d3hEitql_e75$;KI~P`>IQ>*`;Rxn`Zv2Di?x1Vx9KeW?EfqJhq7D-_OdCD;{h_U z`7q%i6Z5z_vUecy62B_Ywu|-gs^4m6;Ajxa@US1%j{9Y$b1}qjWDTpE3g)xt`xKEE zjS!uLZWf8t?Y*3==;a?}GXi3z*o*(9cFxnHJ?8tYy%eRttJ&>~YjryJYtPcq4o=z^tmtaBk7ljRnb#BjZ&Ev9x0K@h*hA=hx-Vkcu=G%%N5~#`o~uuzeTH z*t>Crfd685EB{eHJ~+~^75^q|+l4Q;O9J8}QtJAH3%2flIR8&6@>cum$x;dPj^Tp45vR{zxnY;CNn+n z#(etQ(2X9W5Y}I6GIZ#AeIV&VR`Jr)kI4%z+Ydk1o6K_DH!u>s8{x=!yQ=AyxK&d& z8&{o|Blk9V-xF8$`%3w`cR~A(u)=Ng$d46QrOPvAG+*M6L!@_fjo%_x)yWO+inA5S zx#tFs_?nIQ&Q&LWH#~WV5Qdwpw5buU=h*`*y65L$9V1T8Uh>ixQ`ug!*wD=kvy-W9 zn?E8We#?91UE}ZFy7ckVbG89eza63==Qb4_(};o`_q(X$^&`Z3p+|GrVZls z{!Cxj+;w3+!+!r`ulwbXTjL!lbr0>BG82$qRJ}dvBjQuUury^y>|Iy0?Fsy zE`DvhXVwzpvEU1^izs1{SgWr`Vfbwl(n;fd_|!rDa#rY3cZ^n%65-}(dS|!|p}^wD zrGg<6JI!JA;J+>Kl}ipi-z>gpd!moc4CZ&bi0mB0E-aC^CaP+LmLhsmCb**VmyNHE z>tr4NMeUu)@m(*wp0c$)<%s97iH?Enqfe`tkNZ7qH{yyIZ>lyXG9&@+De9)+zSAdd zEv#I@g6%RM{oium`@~NeER-;7euKwy*yZIZ(SPkd%$4uH*M%!8!=4%<4d9s1b4$4dn6_nPEQ3{yq`tcNagj!(xrN>b}gZiQaFs~i@+7x?&5(lAEq*bR`>tP|mr;r5!vpFvl z-B^xg{P=e1ebb5#M!;gEZr?FML?`CY~lj9qr($%cQ;< znjT;Z3=P4Xwn3KKmRUJ4`=9C!X5-8sR^eZlBgzjbSL&-*v_Yz;p=pz_F(g^rAS9dn z!~4pT@ie?Yz_V|#z7{`(aCJYDC+~L3(Cc5(ld+(a2xVF_&=O7-!`eRJJR@(mdQtnR zjC~d7Y0OOxsSCaCi(>!9uMkcId)WB#mGH^A#E0-ICEBa!8L5QAYR{WM0=I z1lW&V*c7>Om7m%jk9U-G6X@mRHqt3RCg(95(B@PFan(OerP>|7w$`a>p|ziNmQ=NcbmtXTa|dT{0ZfgyMAIjOG1GD2D^87fbjVNI+X`RX;t2P8e>`HhL zs}gLP;7@|h(*PQM(s_8ANIR?nXBQY;3<_G4-g)W@*}_1gO__=qsEq*QWIE5Yg>cd< z{Fp|g3s5r~xupYdixb7N2=&D)wqow~t-(AH?(cdoP#(^dcQ4C_^@GzPkxK`DQ5tZ5 zvB-SxNB;;xszLjq_FE**vXIAlw8dfb*VWOv<)Loj%m-?F9cKn8W+K%4Xyf2)qOab$ z4Koq&N4&%v+nrYEOMC_Wf*||Fe3Qv8ufcsZFR|bA z#OOuk6e7aB=L$aC^+L5>bo@4YhCEDjeejes?>2sl)@?j!ZTKAW02ZILrEkQ6&2>u9 z*+H#QvxhXla)^t}p-1|Z!_U$Po^|ocQBSzP89mH$pqA(3P`zKu)P-z|@`X-A#x>dM zR*~wWEyCXVl(NfaG8qC7%c1l>YaN!u&HKmVxgXY6?+YWdMLNX>xQz_6h0XQ2wEUdx zazIo)!u!U60RxVN*1YtPa~KpdNaq{Eav1Bnaxk0tEaQ-NMTEYmN1RrcPzCF_sJ zvR?LX@YR5Dxu6*AIm?Fb$?)6U7dB+9Yu0!&R*xx{0@|I*mJ$p?fFUcA$YAa+(=Q^q zP17Nniagdr5c4`Ln7Fa41n%8e0ZkVj9xK?stBu+D(GQG&dp~#9kZTz=&1*<6l0DXi zlS9rc_$W|K1I`UF#+2&u3UK^&j6se~=fU9LkFr}Hw@j}mos8MB4tai@RX~)Iq;)7% z^hu{w4sMlrXq(8=0GSVU+JN@i#U>sQ;b{S78*tXa5!HUU3QY6AvH7U88<;Cy*P;Mr zy>#l0ZG@K65ptt1o{@h-(V0WTJG$ZkEq!6TeQVV1b*|xWM);=fxS)N({^;qe!{Ge% z(J{CEIY;08UkqsX?zXQ}JxDIg8|C{WN{>7v-;>OLKh&)|Z=`qG=J~ha4Pfhx%jX<@ zV?Vc9tNrRVIPraHwe(;~dMSKEbOjOifGc(%RO`NDXK!0}9^cm;=2+yl=Va~1Wf`rH zWaII!tiSs}rf=U7+15Dt9a_XH@2tDfqi?OJ;6v819MWoB9MVSp`mz{s4v;#x)z3@p z^gQHx(c{D+nry+h+_6tXz>AJy4O)k02%RqnaPEVHIhE~fPn9l*pB?Nqa!Vfvf8_ws z_#jKSIUMA{EO=xL8#0X$1wwr1@nRh4qOi1^Z2MBM!8dY4Di?&%QYs)fI=uZcgubR4 zszY9#sN=XCYEsq}WkafqgKTRPy+%92AAibQvw0h_&6Qw;E$R8GX!=_k(SPQrJbYc| z_)vfIflUcO5Hiz+F4?FL9?E^fphZxo<(&Ds#Hl-Az?ntNNg(EG@By$vKv!7oItld?5xGRFMJ^t)lvUdBCtl{7meuUa*2#8PtcZe4+$eQj4C%Q&WCirg> zMcHqv6Ik6E#$L0vJ&X_teX?6J_AFwgiP$68fTexj5moHl@1Herh&=)Qc04E(v;y>P z+c_C7O|81>lXZzd*}2kFhymvxed7#j*lM%t@_4QfYG=SSoO&=j)*<)%pEjaoxs<{4 zUeA{uXdZ+jPLr0BHg=>30wO#OpnL<)0a~|OA6=Y>aZpP#rEPe@hrTAn(Lw6|Eni$h zhU9)hFyL#K&B2`%l!{LqMHhjFEMuS}4v^LGw>B_kS3ViJy;^ylL+}Axeq(nGD1Ez6 zyY~Sl%LE)>X-@%KnR8X2GlM*$+BnLzKj|fd`T6|fT%&e1kXyIEwc7~4I_|O7Ec#1HjsdTuD8m4Yemr!`l_1hm5cssySZ{-c(LsXG|X)@G*4W5BBVLYL#04 z7V?vvv|F53Iw@@)7<#;{r;Mlj6fM58N=U=>^fL#Nc>uvTa-mQWEun(0L1CWfR-@Oq zHb7RQI&7vhDc3R8$$WVaRB+Zb)fwl|;XztY~`C$uF$+VBTE$z=EzpYT(&*+K3T zApm>$hmLk*_r;=q1=ak_;u5FsfB|O~F%N6B^q4F`iZCIpDf@u9CV*6reOQFSgSORv z=aEc4_oj@$a!aNURRMh~-M-p*+97=?cxuRN#?u`4a;f_l(hhJOFk21>@#X}OzH z8jq{}JC@0Os-%AFDwHjR6XZf{NsEv6h=1vd`0;66!2FC(5-7`na|1je)j)}1fI1t5 zLHLxd@#YJHpMCn)1|~N|$!Npb0FOL?14t9r3~H#KMbT?u<;jZ?l`b@(U%h$P3l4`P zjd>{PE6)3-uRNGJMzFp2Y4dq#^+%%9#(v}IAXtU^oJA}$pZn22l5&dRyW}ncB0N!` z9T1pw>WG%jt=rww`{Sr-#27i!d_Bd6EoBetK(uuyA^u43eV{6Sqz!H169vdar}x!j zb3z{BGfRHJN(cN+Wi%bj?&AltH{O!9n^$E0{V&THUvY=uFuS`Y^3HvJZ63eoc;*HS zxsMc4>A6q`9Ma+d3h}g@If(%SmWsT;YK_evJ@}UFLg*OcPz?burYo{y=73Gf5AVtW zTRDughvDWMeAty|7zchT`_~^ge((vM$~-J|Iq}M903CcxMrenV;iIw@&}7${A9w&h zu6N0JB~vBLC^}X9qU2p8^f^?bXu4e1QXdd_m!odvQkMA{8z86fDSn|3 zn-bT7Al2hA7XMhcrHZfImc1{%BjdY|WNqeYyt9V7 zh75foWIa&$s+uQPcQ4osWpwEVoMm9#VSLr&F~G6sT^{!EC)CD&VshlM+Den@G`1S; zF&=!s|EWXE+mx>1dAC;q6o;!L>?^b(aPZnicGTrO)3Epm0opZ;bFR<>nLlm}hqUJs zWr`9UP#kftSB3ppwQh-(4+=d-1vkA=;R3|yb-7W8GLwN500X=vVt^cE3e#oOasYak zSNVo!^XP-OKvU;)3p|+7+SYGUmJA#WXyd!IKbk&k2*~`o!!h^4dBvi0x*G={QOIo( zI&mDS9lBv_g9`^lM2i*w>1KL1NC+iK6jm!@JiL9@U<>K0&jBdXzvUg85U%V<;Uw)p?_QpF?*?Q-J>?p~W zMxCr%8l{4DP5YpJ^VU?@#(SDRd{8jlqlT^S`2fb;3L=lkzM+}*Tz_*M$OseZg)Vk! z^bs!(*g}^H&%Sv$XFPPxr(>1((0rRP4*cR!5Mdk?=EGa~6(1D9c~z zygfvm6M!Q#?MS!UI>|a~6Ml?qg|y_vb*i@iZOcXHboFu=is`q)ak7 zP|F8{ty)0b_37_@d3tF;-i15J8F`wnpQCPx7nLO7qMB^|Uhc?ylvxPsQ5Z9XdSo zT1VYrccR`2wsqAu{_dmu1svQ0aj!yJl%0SGj~gi4fO74l}l9M^tyKBh{Sp@_KpsU>huP9A;SBF6@J@R_$)x zqvJ^FqCRZ0W_{Y1PWXT}@~x5EH`*Y0`X?%BfD-Do8`xQ)Fu^YdhDWy~ED-R6g3>`vd)H2eg_T z_3l@ELC~AM*n$Y-=>t`S)CZqKdjLX|G>!qSseOpKzJg1`fB{QKo`YS}v9?1FUGOuc zwpa%;aScJJlPf+=`_^rdckYU8H$X`a&>$I9bx*JsZGnpd1h2%EdiyL-ZlR!_erA7QsP$Pa7*!PK=Rd;cPVh8A5bU zcPE{t@eXh~swgnScU0?i>WVyvfqmYAF^BOL<1&v&fMd^xLD(2#4#I%HYJ5V5rj;Jk zY5UdK$9(!I1@yXW?f5BJ)$@Q>Rk+22FNdz7gO3v1rto2NUr!6YK^yZ>y*45^#-YaK z93CfzL)vqPGA#`lMI>xfeMo75!5HA+3>)A!1n`SR0iHJTT?cryNP!e-YfzQO(<0mU z1rnd*g%9`r!OyBpS zjIUp|hkN&TL~cJ4d7$CM(_n@r*EY(7LnkW@O}(HC{Ku(?yg2rWKVZNjSY#OW`D8u# zmY)lur-*$W0#}4SWFFiFuR$Ej#lc-Vcm=gTeHlFBfd{FmVL6~h98ZrrkJF@M@n}P2 zgpgb5Ye?CB5Ei*2w;7TiX!!?%&$^=^rB{*!6QtKv4%aB5&R|VL8+fI1VBM;_`XgSn zBP4IP(!S&^G(C8Th+|>!<-i?&_=C=QhU^yS z7$)jMpMDV>CGLO$XAV9&Tjb!J27z}u5IS6_cLHD55>S|Q-!{chS7?ZzuDJbB_d8R6StXmpT;#`dw;Z#H{c+c$C#>N>o@8~MI6+n|9BlIs}y z;jsDB$#{~%{2J5csT)pN#hc5Kv=9U$PQ+K@0ucHdR8l!b zDb7Ma9Hf2&mWMLW4+V^@gN?3L?qRgWvCowSGRQ8+UY>J;gO20QcGWZ@9c~GGlFWI5 zBO$KyO*~~nnF&G3$3dH3GEwhk^3Yxhd~(l|0(o%vmh3*-61jO(#_xMkwl>$*q+|N- zW0~@y9=?j$zv?(rsT*SEepWloLHILylo=rm0|qP+iwwy=pRD)c+USz8=&{GsARWS$ zLpEHXYuR$Bq`r2*>O2qjK+sR@K(N@MMBF$qbQ|r#BQ$$CSj2&$+L*S-qrH?5dgxGO z4MQKqOpO{FMCU0)kYpnGtUEZEuX9aOV1o3T%IX^ZL*2ldMk{N6N^#g~?E({cqtfQ? zSK_2LG+Xfc7a{E+P1EC991Wa``QP0_4sAFr6Lk4l-a6Sm;%U;08tli&|5e{z)^2BrA_m2FB zKh0yZyCc)_ln1oI@- zxzF`IB}9owwimGw%8ZUZRZfr%f-( zZYtgh8_=hvsSx+Tc|IqPC=p2;i=kflFIE~BTL;gBTataefN?^niSck&6`^mDUJw$| zNl;dp)hrJv*MM`6vIHpFlQ!RU`ffmNecRvuUjc&U5;+wfah+y1QH(ze=#X~Fw~nVU zTZf@SPXAnP;`Gf^JlG)}BiQEAC;K2uf-vYzV8Qw=iev7QGl`hnnc5>IXb~L5*RaaV z0NUbUwK*h^k2XZKUKa&2KcE}UINl$18|U^d={UtbEA*KH;6lf=U<)5oV-GSn3zccx zDw#U^nJ*q{wQTl;UkMNR_T>KUcVuU}CGz}D*?Z|Z*_upbZEqxFeAO{NNsF(?<0mpS zZcvSb+|PR5P&OwQ2Mky$78#;_K3N}p(J2GIMY`8xV0%9BJbVMie2GIj7#U{LztCZ- zDqju;$t&SgxA19w{W0wDGacjbpb+}8`KyibOIj?H#baFMSpe4|M0%<-J`oF_3DA(X z;4LUb1XC0Tf|jIkO%mXP5WrxBtLagX%I0y{W?_Q~b*J6i&qK)c@wQ}$HiQkIkfjbH zE)c`c#Eqv8B0?pE`e$MA9i(w!U(=8eKtQT0cA$gT)!$^Ik5?oSaUdGu{-GhrjE=&z z*w$LUC=Td8V8EF|o|izGqs}laN+$#whFA!?4&wUYgbVg-(Ba!r9`4BK{v)}-pRT}U zt0o-c8&g8w4<0|(_!Az`;?uM?ubpsctFrAoA?qLHc!kZ$erC(EpRw`dGR?j?>>%i( z$R!Tl+J3ab$uVo|fUA4$r-&%g%9JgJ#xk&a&3(pE&);t3`LK#(ei6*nw5J+pwSEIu z8_l@$dsCu-&aT$Dgbm}7KG1_tcCslw0^=9di6gvJVqXW8#2VlX;@d2|pK7DA?H#%3)g`|1-b-ZA| zmp4-TqqMt+X9aoO9UVw3(mQX1@8IAVa+(E3N*~R`B0gsW(KaVtn`ps#G@u{-W4ar; zJzMRIbgDHr((Xzh8_J-t7hi~^cKqP8P8kL)hqC#1ilY<{xU3#{O=NGpE7QC0 zid^0kdGV^q&FefrxVWuleea=tMIJtZ(REYKjdK)u`N~7aR>D=D0|qP;ePehL{fv(* z5EKfXhDvxD4;>9AUfw78GBO8 z$MQ42iKlWYv&TW0bcI+Uw>g^qZeu5kOSUhLCJzmBTBRJg2Jhaqp}t@no7FjV2(6CL zGbZF{3)RD3+BbOjX?VEmrTiAH>Fg_xVPr<;Pg1$X&mopg!wi-2mN57N^357LyPAeZ z!))Z5+`)%msA|2lN5WC#4;Zkrz=TxlnxhQez&V~M0G8wo*PEJP^7Mj`K7O*|F%D_B zWOFb4U<*bG|M_8yjE742DGD6Y?(GRa-Lkf}j;rrysWClY$O(@rmFM0RmXI3{Jj#Rx zU=jR^wML^@=mZ|fduW2mH1-UOYx&lQbTgU32nWTXqaAVwbtHXkh^$IkPZ@mt==@QD zUO#uw`c54_ms(+_S+wTC8A7fhF^r`FCx|km`sR+Rb!N5ZmiaevVasbE*qONqxi1d_ zdDQp2dH%~sl< zTqDvumm4KiR#n@5YG>6O*P z{PtNsY)&7f^-dmjFQ0Z<>oVA~c(8tp_)JUVB0dggNuCyUP8pEmKo-<04}76xU_6PY z+4N>~;8_OS4rY7H2P`i7XL&(JXtwEeEIWH!GQD$4kf z3W+de*WpDQIO@S741E)TF*a<)kkHt|n{sglZ+4S{cki&7&=Bg#ay50PZ-i(Uv;jJb zD(GN$U$#%9vv>%?KYWn9+rg`@w0$8fQlU;HLx+Dks3r3H8N9Cj&J|sk8&Mf*ze?3o zWCL$J2gD(w3>dI-z`Sk&1G{H%a~`XWaZ)_8df^(u#iNlCmi47EnH>Q_CF(WY+L5)# zTQb5uz#QfhORMRxJ>Jp#2KJmAy05iE+NcE{#70q~ZgB(~R1S2x_cX$~5WIbbF=A>W z(2Z=*TtK@M#U^e!ICWcw`Pg2$c^);3oSrH44^M{m4{JWj*KE5Vbi_GkAQ#dJ<~bLw z4jQmph|WQn35akOD>JqZfLtr`9mPLubsBI6k;YgViy5skheC*)>OPz)# z9Y#n_9ne&HZ4mPOc*{baGcGNiRwl^)*~$-I>0~@_yGlHiRpM71Lx=c$sm&XOI$RuF zzYqq&4}^QR$2o2chqO-wVu-cJ6*t0!+qpSzk32}BA`ixrQrN;U4;x=YB-Iyhxo3pd+xkuli`|VBdI~AEw>4BIh2=Smd z{1B4BEAh=FNOgrb;`txrD&Zd|co2v~M)!q{pVU<1*B`?l7sQ2Leeuc8a&Slo^4$M0 zH2<*S)AnYAA56+KJ@X4$FBT?(mU^X-D2Km`Mo5bqM=>}VEUI2erXynpmxA|P!=_=e zF}}B5=%el)whnCd&qC;-Q$iauv^FXSvuqof%%48w%?`Ph26dVAQfyA4)4xsvJdEWX ztG(VKOi466ZV|L2^!tTt+HBZ7C}Bd0PN>l3YZkSF_jGaA^?Oj>JT2!1nDB@^3YkNvtds>xEkv#pg)imIY!aARQ9w^Uc z0M$2R6~6qV4sq=H4Qv+J*hxUT^mE@DFk8%ufC!HdQSUlu)DSffvJWtrKSS#2*7gft z@3l;izJ@G!l3oxJE#Y`E9MYasV3Kn3`V7W~7Zh@UIx?WPv2r!&;I!f00OPd_d11-u z(zkSl1rrO@Y@9B1miauu`-Tr=P5^A}zK-oclheYDExoBIvWMngO8 z-%iT|^U}Yw*6O*uCtddL{0`G+*7nA><9CgL(BVohn4<8o@WCir=~d3KIcq!^1QrsB zt%MoGPZjVw*_GXUw`ID!BNtzIMmC>$O7&{lnaJ)tcV&9}J|E~=qvmv>P{O)-khQbr zi?|3QU4))qb{jC@q|h373k<^S0zPDhE`**GjPW)d^b+c@mxDPK@hrVOa94pLy+CyGton0~2a4&9G!q;hFLl{GBwN;B*cLIInT{xQug1Jr|{ zbA3=C>uMW7S=Z27uds(U87?z0-u4>dm+YjFlRm=AWKf~QhiLgNfP?xE7_jp2Ns75% z-~+v=^1!bqb%+S_!ECG@v9>T&(xr$8w2<*h+J{@RwmbGuqwwMYA2J?{YOptz$=0q+ z9`48#2ej)-qYX9K0WEzzUpug~)y6*g;!;{$$~x21Ijfhv4jB(7lj{KYE6Dy8TKi>n zfE?5r!BOIcn^QYIMc7Ud%no&+bc(FDM!w_bE7Bk~~g)viuo}w?aPTgs# z4r03IoxU|!ohbXESm+1VjkW~j8J%MjljG~W@4QOX?Z?^dY z?H-6y9b@TM6lkM19cv$*0rbt;*_N86<3gl;oOv7ui>z%+fo5ZK`s~ipT<(*qL*&Dd z?dNnLz~AD<%hWbcVhqr$(m}~*W{?xX4t?y`0y(80mkNx*(5!nHr6ig3buc-@Eml8U9 zdv0_-Ll+RVDD>DPx{MGH)8hdMXUmPeZw(FV0sp*km)kq)=Ib0 znY;0nlg-Ku(aY|2hfEjp`bS^)b35AzevnHWfrr`R7d?I4PQBNo$U!QQk`DIp34S3| zYpJtX@hSK{q8I?^++)UWCes7%Ym``}VhSw6FM@;m4;Zj2z+CS_=v!tCbXCkmQN3*} z6R#}E`FiajuQr6`+ZB}XwZ->!U$?dEzxxK~pn&rFH=2%QP4|Ce-3N{}&f5B>tZiP9 zwb8oH^^tuV#@#cZ28yhyZ*(T zC`D7v)zJU||MW>jK~(TKLFMO=_)30CK!gL%9?;Ko0N&Q!2Uyp(8Yl*Y*DR3(1qRpGt7ms`5b~85dap& zc_Q=2hb0}-4me$K^f;_fIP5}A!Q?_zG`0-9@wbN%2KI3Fsr>6PFguw|*QYNatCt?% zF3c1~5u5BY1+=-7b&%Dp=#CNW8xPU;2SJqVcuTm7V2c^+IPQL0WpE7jj2*U=+u?%W z1+Xx57LR`9mWO4hw=6`Rj}6|KrG51;kIu6=Qc>n8_i>j$=ac&?m!TWp@J`nDAXDMM zm3@-ETvtH_m;>r zo3i=x)3Sc;ipbtX)*tN1+MDl*JlwTUU@#R$X~>=yjr-uC)>SX9XEk8JN??(p%<z>PAl~c}Gz>wc!dH!svWBmxx-%Y%AsSIw@Hllwd*~ z5yRW0)n2)6LZ%Nw=#gx+6?~kSWaG>HT}J{K;Nq0nApG`YA-rmtuUJVN*)FsCe4lUy zW!^A~(t{wN%kE)T6X28m&^Sum0RvVMnAf;)epBc`OrVN%&hv2~qQzlstSRJO$4}5E z+8)dF;WiIz<9FShyktwXfjMh9Zup1t!n9)Yv?UdJq+15QAavIA>Z&`@;iq=^A$YJ_Ex4q&ykEQ2# zUg6`hM((#X%2hJoGLDsaKZ+!%Gtv6S{ZwY3K$jlIuIPhrk^Yt6;6hNvQM7cP zFRYZ44Z0b?$1QrNlF4{a#*ZI}+`T38%2P6V_PR_rFUWLjBICF3%Jhrxh&}6zG2MkydEHbvU5BQMDCu7(`PZRczE}Q7&3=a0<(2oz>!7CF7iRA#+ zY9TpZBCzr+pSCNAwv&+X8Y@ModPMz+UtLJ+(O9#%5r^db3| zw1K3@HRa24fuKX#5ul+cdwsy8O`MN|+R`?tYuIz!Kt|icpHZUCV2coX_+;613|szT zb9+EpzP}3_kjw?t`5NkLJwo0Q8c_){8LALwG43bDmrCc04BkV^4N>Fjf{^R*AUI5% z0RvVRU6UDu+y{DjK!Ol*Ce?AhsBAc#4Oia#T)uKcE?l}M>!S;5UstlvzVM~%0M`xWu_oBd(h14T7B)P{4sZ*ck2LwJ z?S*<|-%InKEK3~yOZ)YZTWJ@BzKaZ{e4X*zb`oCj?RGyhm^3b@35>x3XBb>WJPc}( z$MY(qtMuei>`Vw!ow{fq%o_s?s<*#pKL$C2}8JhH3x(&}>`15kxp z<$Q|=>hw&HcovEN#uD^*n<4nDJ6<$7wn|Lab`dT|S#heHe2e7oiy}Rs#C2FYWDU-@ z+u-;x9MYZx*f48AIVt)6J&`GOkadua+=e0!erTC|m~?;^UMYZKYm>qjg90-cWn_JA zbL4zxs5{DPLko_@f#qkrf;(B1g?3K6Ke<4A>_-hwqyJU`xV3lPsMtb!X@-`zPgz{r zpvIF3j~JV-J}?k3$31L1$APZ)S{hQjc6L3;crx&iL6b=rqGZ~&XaL6PF3^*0k z`-&{qV;M4adhyVv5e3u5Lw5Qo@!1)8*HafZjb9E_!E5Lb=k0({8N|WCqsKv5Y>WpV z984-9E_^~y-u+U@{V?OX9w>GrywpK?h_0s&2tMhGy@z_@n>xt|As0emWo6w{IfE}c zwgYU|UJ=i1o)2B2hirb-(}qy>h+Fhtv|@9)lbUtcR`>+yyO7<;IlgU+#&j z3VneF5^IkTuLQKpB5-%Lus+2MjpRz}!CwV*bYjVRV;i3#w%$euB0l_yxbG z!SVE~o*Pxba?zW`?XAvB4 z=vVLCnX#w(X7m6sz~6ltw^0K&?`puW(Q

    1eEzopYV(D_+cf^d3QkfN_^ni@E0ZGZ(aY9_rDoAUPDvprZT zMbd?QBGBl-1P%(&7t~>^z^oCLI2D~iG;JQWJ6Uj1O>NGi7~6~Rsp;$>51K9tblGZZ zU~}ZjgN-2<5^QM2M$;4ucz@8-%E!r~G``fkZXQLv zTIZ1yx!QedDgX<)McPtp6WQB&B-{7i6Xj&>1Fy>7%^NbAj%0LqTc%%nr}?U5KIGFd zC_q^+S$9xq(hVY^qa-+Bz$wG`;01+MrrvuLSJ*7H=#Z%}eH;qTP_5TL8~{4m0iu%H zOb^+@*1@X#+97Y2BOQ;+JXG(Y#aBDa?S3GDq09UW+4-;+1n>GV7YZFN0XM47l0(X- zD`iQ<_FxDvuaDQ&^jYU2Rp2dsP_!NWsjm)bNve-@LUvu@?a~6jG89A}OJrIkvpdtE zSDU#0*E|B3@u@YulrO4aT+b-3Z)99d-;(Kwz(asC{*tZ_``HH!I1j)Yuphd7IL{N+ zsO@>JDWsDu!pTS`+q&y}xUJhj=({E$XRb_l$1=YAP$st?h-_RDxp+myKM5QX?&P*-9;laJ8^$ z6DFhWfZv<-M-1_(z-)!=HH+DH?D86LPT-x(KCk+{H5RhHsLbAu<$ms4#(LYS#HD|g z!f~L?wVWRmk##eLlyC1XvMCU$M0A5mGyX-<_C78QhqUJf9E5o|bqt^|XFtX>wjjwo z=ye3gX`Cjm0kQ=FPTERWP~vwP4W+pKE@uvW$kN&9Cj;w~ra^Nl4pXAjsl`FD=m3J> z;)Bil^2vkUjAy~2<$OU`lZI}Fa7j>+H-8roio?b`4)nFzGSHXyQRntiQI`sG=#H;7 z4u}3R-JwsqE_-={<`irV#AS3hGOa2-^D!M=!zVsLn{^c;UJF?T-sMi;8HA7hV+H@H z8p~wsf$ZJCC30g!)?a;5#@DXOcxNKhTMtFvRQ-;Q!0{q^91*1+81X*p6FXqQnL|Bx zvs~{%%2?Nnhjy?BmKWz;Mwkx-aYz_)93B=~1Mp7epq4hs%E#CB@{_Z1Fze|+4qs2- z%I1D34E@0)U8p>L2n+$U@nF;#{evwikmYR86liqRGA~Qt_IXMvv~pX>a(KDpu(owT z>vsA=58q;Uf3^{l_qOo37NRH?pE}C$RUSY{0$)*pvaXF?damoSZU&Eim%nsPwfloo zgg~&_Mnd4c3gq#mfuidvo1J>deEO(i=;#X>yb;P%bU?NTGCyFzc}2|sjIt(JPyjjW z$m=Ea*%k<0_9>(jcA}(vx~cB%CXaS_NXz-zF#+)$Y4UJOcHg}t#__u^-_C)9rgAFFhse&psv73m0Yg(XQ;_tL@%V{hm6P z1powSN^wtI=6V{*NBU9fCv?p|pEv`3S;pZKP>)?7(gf#^^FY|BHv`{x7C#TmL7!3_ z{1uyro<=#G#UDeH8Ql+IO^y(Ujc#Ka;nN({Mn3dY!P0eq=#U0{7@v&AEjkTNNIEAo zIzrAA0ME?y59xz79latggiclluLt6?+@_1VTV1mba`E3jr1V6X=%vWb8~iE)yVqQ)ttlQ#3a>aexzpQN=Y zHFTRO(>wQN?c;guvUA(GEZ0Itm`( z)IoruI$%|S4z8&|9_yzv{uV@6>B)2ARJ0H1hWeT~1L(PRqGX7*v9y(mjxODRbAhfo z0hJOh9riqrx(;f)#t#Vk*7$Ba5teq)5z*SeWWGro+OWhyY@rG(!g;Z0TytIPWaEp_==e>O3y8nY~TX>E%Th*G3hIqt-iI) z!m~P88>{k=Wkpch*h3)eG64~u9boX}0koXKWOL!{wZ<~gKd*yn+9kgBJjM`jZYsl< z{*0ryRE8B?SyE%1{Z^jSL#%mS6lmIEIVkBPi>hIA9tX{@Be?@3;_sK%GV(esy80({ z)~-&Kp0)%?MW1{^2BHsIdYFS3RdjWRUlE;`t=F8HW>)Vau>2SWNHS%l7OXz98P&>x{v#7V^A7cx-~Mw9g} z;P(NgxE~Z()5nW;l9|dqgzKz^ei%zTE95S0;jqED}2l8CGG9mGlF{GPJg_$>?1i@wGZ%C9Sp z9y}Debyt1&_;2@yC!;fohFB7@+xn_mt6klt%K>gJ2?SNOH9Mpnn%YZ-D?g8fxJ>$jh zEudL@o=5dTEigNN0E-jxfUdD@_MjsmN#Z^Nq|!tg?k5x|Cs@3nf}Xzg zw~)rjFXE6~a8Qa2P5{GdN)S`^MWgO43y#=(^}^pQ{ei_hQ=m)tq@jCm1MN}5Ylp9mKW#%N zE=DB%)1_f1N*b${CRAOU1_Sg#Cjpkl>7-$83C83Mwv{9Eiy$X=*jh!rMdQP-rg`YI z$2i%K2yMTX&ij!YHnwfkw{`!rjM)};vWfQxHn4{u^2!f#0+AM9G${qIc|&fc5jrcM+0p@QDtA*>)s?nzdxY91h>NzNzv?Y*X5zlan;kmH$ToO{ zU^+m%u|&(w)?K_BJ~Z+2Pt@uw*3;(Yn>7&cGhh+=0SE4RApI*o@zxK1w7DI6$N+V& zFS3VOCU1n&6kXngiVeIIKRs*2xy`gwWKDlf zX|%g1qx+9V9&D+8Lq-=a$#_Jmx9N)=U0VB>kP4Wv6e`}eL+mKLlUJASja$esy(Tpu<7 z>&XafN=rN7%maPxV`m1c?z4qHo_!hlSXDm8Py>55ReTj)YbxW>Uef`P_AlTd@;M#D zh5&>-l+`?`*Gt&Bx4>I6@LGhT1Gx{=B`L3y2rp=PMY`k+47cj1Xvg)I={0v*ZF8T z{XSd`^v}hnZRWK&qsPus5$QpL8y`dZK%0>AJxDLq$t)9#u1!|AhL#29-IIOJ=b(8; zk_a<@5F8~Q$s4Q49TdoXUGJI#)^<6j>ohg{l&ZCIS(kY0wv;@sWPf9n;vW zr%}wStOs8Rdm2}|Y}D9E<|)uW-EuWp?97k$*gXAsran{>*ucsDz-4cY=(xl&6L=I4w`euoXXusXXwDx?v5Z9(8eDsi%_Ht2wCk zG!P$P8z7$Y)FZC(anMbKogp=b%qwE0ZV>|K<3*k(TpTR=8{6=D2_2B_fy@sWFrZmSNIF3}-+(Eg z_w~qR3(Pl>&T-@2AvW_$8;F1Jk?g&DS0)d3W#i%v8C|%hJ{xKtsfVS3Z+FAX(g8Ul zZ$+bRbZvx3<7sIc%6jJHN~46@kG}dBO*Qp3YsQap?GkYUGrnEKbj?>U4VkiApFn#C z-8|kB!JLmF-99is?Q)XKM?vYwqb4-qm=N>3Z=N?esWEsWU|n=xRU^ENeYKbEkyD_| zNBnuS(Z|~-d`k%bA`LhXK)081P=RY5$A?ow_#?ipi}0a}fsK_Kv@~&N9TZ{D#!kmh za2Tiif5=e9wgfto^E{}9tl5~Kz2}Ng)sn)V;#zv@ry+UTVFf%*5S%^kNdWVGz2v0VZd}UL;ne9&~stmfs42v)`w+^CydFue#k-*1sstNtf#6fO^+; zA8PY@*r+Ovn{1Z5IxK znYsY3!d-4{O}D>$+amXGiR?a<(X-d(%F8dv`sM|h+~1N3K1GXz+Ocjkxr49LTk8EW z()KiQNDIQ@%6MGVB^)qd4q~*R-_*A)pP1jB%KVgG$ENOZcjuX{W=-2*I`vDc!gAiB-21pAzz|x64qNjXF{UE{C7{ zP#ZeefTP{XDg#}V5guO0u(Qm`?saDx!AE;|8!--YD{bTH(a-pj9%R@VS3`3s0ij`Y zzyY*Jpjq^VgA|Ta)8XxZIaH;L07fVG$rR(9cBsgcQ8o@^BQK?L=<2#+N4(%Y3D`of ze@1$tO$mz712tcxOE+M^lLo9K1-^C=K7rCYGJ{xyGR;8Kh)<7sgW=y>mw< zZ@wq;a4Z+EJR=($*VMA9KI^)6>AJ!Fp?dp1F|vuGbG^)E_BqpP5DwPs$q9NK>rG=3pYzM1f%Amc~UA_nP_NGr|&K^=^ha!sXD*o zM(XyZ;Dn1mU{ORz@897kJ_b(#WxhFe!E9y?AL^?1DN-Q5Wg+=9Ei1b26L4el-p?u`U@cWAV+s?i~X3hCb z6wHXC_JDd(5a(D%he z5Q%R{R9ODw^ufI?0+b3(`AD^&E|o<(EjiL`zIJ0S)_mCZ#z7WPzRjuXRr8kAr<@ee zb;QwHngm+GW%a7;sv>R6g$LrEe6r<;-d4a@wr2g?PQFf}UsehN3L_oYW0%t%dGC5yc5Z|%k(^?@pi@Hxdr zVcZ2X_66KV`_5~4Nd^^;eHr|oZ^qrrHa4^i34ER^)@3++ZVHt8ePtn!p6_Iw%5xNh zGq}DsV&ud@JUp$03aiyO*Sb1)h@vK9yuPwlJ9$}xE5~aYalJR__@;G0vWav~0<&y6foa*fp|l zZstyo3U(9tza_-AOS2jJ=yh0S{^_28U&oHxCRUy3ztj0A_R}dZM zRG`KfYkx5FEN8GtIufRoV+Kd6`g9)Kfzt#Jn~bcqbKpSLAHCo+pBFYA+_~OjL_4Tr zQpDp;?W6(Lio&M?;dmB>dnPWLg&9cn+}TQJLYWu=uGnZhE~$h3I7dn^|w0Hv)_Gq zIZQoH`-wA*tvDyD1*efB0EbLEs@4_5mmoqbSoLyI+?MMr#kXFJ#ITQZk=;h?W24%) z>~-WhAK@<~H4~+)0>^&Zy{RyhGG9e(`zXlplcAK9tJ1?{Z2p*>PZ7>&bz>c*wys9s*ibz^X=dN+$@Ig2Bd;r-7jEbD74|(I>817H;nz0( z_nie$w`UaZ6{UGLqFe{qMn2eL4oHKjEC&!uoN!3ob*qFW49ME~R*->hcyo`4BHL9= zE2CmZOR)eyxju6deLrRBBoA|st4zd`FiysoTHQ=Upg7Hi*AXo85FK{YpCE{=H7d-8 z*9%+n(<9G#D%yH!RQDvq;z;sA-02}YDW+a_P0+uMua8q?%7sVtYW|FgJ{cVPCMGIr ztI_-hNLj-2jUVC&qws#;yY-BaC1uBvfD8rqeuBaCf$)mo#*xUes87Ko38BbcNa-q~ zP7d2JEaQJV1ksbMu&#vi{aBgf0K*64j=ajO@c@^lwnzOG6k9<~}P>&pT(>s(^1)U>A; zmWKp9qenT&P4Z|6xNAPl_xA7B8Ml>N*xf~*FQMxq8O1N82yqb*dgQ>5ntNHq^@_O2 z)Vk52fM46yRU{Uqg`Ah#G^;(x$|IopKRhQ*eFd7s)7CRd{2%()@+dw+Y3`a<{g#P- z)<_o5XZn(?D$v+=ix`ny_m92TI0ElK%3Q+a-3!|g9;Z?k;4KJoM3ftkZ2xop8If#5 z=VycqAEcP=p#zCtJlpy2V)F?--td?a6$EB*Ymr98A1vHOX+4^YRrLF&STu+>kL8&y zGyWz-M|}7u``;1yJcXW`gRp4igoSo5R2yTnU=9$*3T zE+5VJ0XY8N2~yuw2i9WWC*%vBSR{U@Jc9K!yzwhl#-W2|R5A#9z~ysAu*|@?NC{tg zju8pYmCe9E(u0Yb1KOhbSBNUbLE5u!3st|l>3W(@SA|K%ZN5BX~wO6qwizjpAM z?2ojMxKX8RqdulZI;xY)G-kjM=T%ZRQnM$?eS45+km&;bsbR4*Mv;RIkdQv@yupsMG-hAOYC#< zdvu{bSoi{D=MUJkq7{qrWr8Dl0c^8A6jX{@7lVN`z-Rg|H@_lPf_?ZGpw^!bi<2uT zRfaF)>{u(?NG-?y7KV4Bm7lasOkl}Q?UJaQL@QM5*UEOD4`Tfnyv_`taRDiE;xtRS zVXjTyW${tzGzEZh%9Q_Y4OLaz!cncPhymvi`t;PUiYIkj?S)!DO?rnz*2z+ z3+pJ}9}{kvPpOxN3bo%p&zT#E6v1c76BsmjEEV$N<45ST7{cu&*P zSl{`)X~h>HdL|GZGHQ&Lv760L)mhSBafIN3fo=O=LR|emW!nF977ay6mjV8fdOZ?KV4ahsR*1f(^(_-dvU@mtOI}3nSHvV!yAZ!5 z@CYV2gzKQ1P74U-5O|!VF#-ivEp7qddoUUg_ zCl*!#w23=i%zjSWpSqrPygIzGGMV@Hn$WL*8bKxxFy7hf?x4Tv1KL17qE$Yd#0=X@ z_u>LxEHqZE0r<$+Hkdn|xuO07c&zG$*xb&_@&f1`4bq69(doXSQv!|vxz2Au@pbx8 zLzpEn;9{|MPf}Q-v0ej~{XlsEd2|sVB=M7U?;;ageK<}cgF({(U8qSL7sxHzlDhwA z&7Lu3Uo`dQS3S}&v_TUT6PCb%_Z{11E<-BT-lt%jAUIf>fID>wLR*XGu-=j&-{cuq zof)MH`w`xBChV~4vVJb&%hmn2f=j|Mzt;IDR&*n3qRPLro^bPM_j`wLl>% zCxOsAUxb*-TxisXzHrv8lh;j_==QwF>!#nn&repW!z4G;DaN4lr~JS;)S zacxrhX$_ALpo=zIvk^%_eKhkdAv_+fjZ-QmUiC>EbQEc!seEd5{wIcE^K1#`!BWVhZYaohsx1PwfzBkV`c~>N# zF@v$-C6OHpCtD3j5kl4K{i_zn#6K=lJ}0QOo2PEyoHhl1#V^Dkd=g1IOK zMx8*_rIpCum0MQRZ3e_&NzTH}uQ(Ht@(^1`6&`M2)#g$y<2p&xpaQx&u__wXdlqqZ zHbCBr*I=2sor+dVBU7Fi{g$y18U(c?Cayec2;-9LL`W(xS!KvaziqEXWJgPWfvt)0 z{et*)j#Wtf6Fzw`*$ZOPK7z+Kw!B-Bmz2KNt$5r$yb8$|=UEVpo@wofHp6t>t+Z_K zOg!6-cW56L=I(kV4ZTa&qpRo=GzC~-p8-Mu6yO0SI2W$bPE3paEkA{nR17nHsd{D2 z{@@AImVk8RTaNQ&BioU%VZIIr5ZX6eEcr&!CTg?A7V{RGiMQ@Z$)q;Ld3Kn;Z*OoE z2xY`)7No~E^s$u2$3hopor*#~#lvN@WW)GifJ?9i`gM4*&wXkufzs05U5AaCu)sX@ zX4b*v5`PlCIztdyOpJ$cg#vp@u{r|NHNlJi)+BnGIYd@YbmvBfw4!vkM~8`J$*Ye} z0ND3t9?&EyyXK(cIbQwaT5*669i!*Oh9`_}F_DQl&f2OdOHFPKc(8F(VO)?qg@^1X;O7*B6GJ^@5;|;-Zj-VXnB{|TDSigF;3Op~Jm@h2J z%#6eV@p6d&CsBz?JkI71FI#Ra)iZ1`V}dazAePVw$sXFuQ(_GOi5A$x}*Gn%CY(s za~yYqHoJ9SL-2-XtLpehfjR-hyADV$&$L;<;VLtic@>**^vP7Z(7&$)G|{EV^&tLy zylD{=QwJ5I?X2P6Q7JP&Z%ZtX3mVGbuv0LV%(=Ls|5<;@>Uc?QH~}2TS6~!c9;{W6 zBIcA1PPXu+PwK<7P!zP+MbB)t#U_Lp_}&_(CEp9mZ6~Xc&B8Av`pL9P(}OLl91wR~ zL^g1fT!nh4L8ma=p%NxM>P%l?4LSpV zmyblk^qayysPmr zE^x2FqIipxfHL_-0P8sUJBLwPr&^+tB+m9evkS(UDWe2r*O|w=?d?~Mk^NR!!Lta| zo)V;WV55WS;p1#)6FIYNq&S6XtChG@BrPX;%aCKFhIu;;Pkr~uN8D(ey^FTw8#(Ig zI2c4v_@~!831f}w%#4ibjTeJzOpok>V7Zq&K)WOQUn|Tsg`0DL_SJK{`3B@Mxre(L%;&v%GoP{iT#fEbG znxPj8%`8Dt%A6E1u?YHgHeU+Gr;Mu0GSd@zl-^V6-4O90`|d}@id zbSwo3wTMpo!RIAhg`|9;g0=k3(f710y5G0=4^R}nM<5nj*UL}KHozR#L}+5GlH&sO z>rkcBTm*|{XnB|V$PZ3(yfJxf@=9RSZG5b6`l{@3?oAJ}D{|rzoA}9J?&5mq^q}9` z1sa^X6KeFxzaNj}B?yZfQc$yckp|}%3*)d6FZF#Snb0fY45#Qf6}FUNo$= zPz?PZ!f;U{XeW&nkS#PqWECVZ)Fu=NAY1a=Hhe<5x3@w+sbW&azq8+>xF5T}OH$O# ztYVa>sA$u3P5-$dw*-${5E|qPMkUHo}8gE4voXm$7A=Or<6&k zrA748{LdMs=?jx^hQyKo0xrhksM6sCQh$MeJ66X$1TtiWh~!qJa=;RrN_K+@!89EN z!<$tS8N+8JJ_(I=8ZE3|D^wKl<|(!a>-&=OB>wi%Hr1tpJ8LA%Ge%`mk6`dg6M?L) z=LtR4*s1Z&tj~iWFMfxwk%#m!`Qmkxt|CSt4RA_n^9wWWlb{}cy6l*;+ z1x~8&J%-G*{_OsTyi0q> zs_S5-fd{Q**&fJ>v@*g+l^8X>4@La3RA)b1bMQ{N*6u|@lSaonze=M4d;-O#pTXw~ zQaVp~GtNuW%YZbU6r-n7m{keKsi!b!LC<0TxIN^kswj+@ja!9>9O-o>yVAw^janXf3qZXd|OlW*65 zJUS76wRR;|y~)q_eYmz<6}q&eN#t!05`f=R+dUz~Hqxg8lToF^-O_TS7QoPk`AUk< zyYdp#*+lMVess8+S*b9~>;a2B>js(e%mg2%jOcdF^%XN)O$MC-#>?A1G$a?f%|0(N zwQlT4m6nP2QCS2-b~IQleFmR*Mj5+0AkxXthf#$#@R_NItIEOxgFmT8kzoR_b#6{aXZ?b9 z{NTX$vq7J$#EoQWX6l=ljvSJW#Qf1JIDii6LmRcx*UB6tu^h(8TBSEDbpF7o%sy%6 zvgmu^g1g}9LWEYbQkN1U@KTeK^1i9deDQO+~`aO=B-^9U2rPAR-w!lgHD=lia{d6Bf887clsKkb8 zH4XZef^DV~qs7(W*C`{@GmGt$f}r;h9nM#67m%?+?@A|%EBRdcCJ4`U;Ncb~5Sw?* z$yCP5^?Gx);57t-a78S_{bem3ybQk<;H+4oy=-y+ zhrs+QJGZ$;a6SK-eEeZ%gBs`}cac0bR){Y)@m?iXEUZdOXb+LB%qL?Vz>l+2nzgqf z0`jpI^(=no)5gIwH-c@Vo<7nMWa$R8(T?GIsuwLSl;zAfkflt4sxTmO4 zZiSaZoQ#8>{C1lPs)t<>?mGYxw! z3FfopoipNW?@A0J$C>gC(uGCeD~-g3B`V!Q-L$gr6SC^=tHk4u>cPEApS5R7SfZ1J zr>8i+iI>px?l!StuR`?pS)Z}s>ivAu7%7DXx!zVa?g6yxvmush#RKoQ{f=(82AlC@(JXAZHc zlW5Jz$*wx<@zav+&dWpA^>!rB^rVP4fN9(RDNAlj& zjsn=L^~C%;jy##K1Hib76p2$I_{`@E_8Mc&JX@*YS(-Ips0Eo~2jAy!gnjQ_-uR6_Cxd|TUQDMX)d5j%CUgB=%!@R``qS(1pT^OaRD{1Q|)rLi40meS6-^l3? z!?Z_HK?JaU@7M%M{0~yAWQK1f6t|Ftw`FCs(V*6|GF7Ub;gn(%CDf{ehsfXK`<>`$ zaN{mn^4Pw{yeYE`5W2Vr8WrZm+oSS%-5^DQyz<<;BT!a2N6*_bpmmou;T|2EtapT) z0--mlCB1!V|?@iB03n;*GY>)BHpGXJW< z=wDKY+Wv+)jRmVPdeVb^*?Jm#Faa&+-)#mXnso@llR}}GMd&2nOhO13O3C?f*>k6h z|6?=(JRUA^W4gQ0mR=B8ghsZumz=X?%zHDH$_h3=Z419yrpKdk^f{}?Uv$5pnMarz zy*1LwyspXgNv_cnS>i^Jd!WTahKbz{`+TKT&(hl1s*oO!7bis@&{K@&85avBh6GK3 z$)*M=K=pExs(Tu&KFLClt?GPXXY~BcNg-?<>*Yf7JKxHnFe@NB+7;*SCPfsVSXi*V z9ZjVuJ$pS_z!PXLT69-4`K|v}_`<)21V^-GR>S^pG7JOxp1w2+>2VPc=%-?$Sz7g! zQoihEGkn170n!dCSVI{Zd^gItIH#DA%W@B&0KZJat-FH&i~m*Qbp|&3&{bjuVcdEn z|3(e=c8k3)9f_{u6U88(=x%2)I0c1o$jmw%>%NI@2%P9JUA&MQ;Kq2YTS1(jP}u$F z&dZxEtUQsU)kXpR2vq=+rEU{#pW)GZbc3|&ssr;J>b-qsd za`L;+R{bgOaT+o_Ntf}n5y*7z9Uki43eMDQ#L-y!N8u$FVFXaMFq+|2Qa@nQ3e&WH z>%>dyl4s=zW11^t_I-^LUYQ>|NO9ld8fawR%SC~BjPBWiv)R1;sWT#*h&d=)Rt6;P zd^?)ZDK!yA6sl;=Gv=j?LMl}y{+l%sg`#-jyRqF8oFjl39_${vD^ZnfQ|o`w-ow#0 zxa>M>F3vw>o8SHjPS*JE#f*>s$9-nRvMg4v!-n=7sfub?M<%+gF!JNFuWC7?zfWM{ zB*%XLubM0*!y}XFgcBOQ$+jLP-k}mC7DO~)xum>Dw7YTH4^TVJO8Dd^f<5W_jV=)6*YBg9SE&KPeMqe?LFc_o$BLBawZK1&8*i_#>WL-Beig*_FW_LF|@Cb6;WktJqG#{My z?w6gI(esf$O4vd=u_HER_bR_el23+)UWGhP9?=93;hkk8lQ!$1(KLTw9wjGnHN^bN zZnqzBjdE-*H4jrZXKvKx4g&A$3Ppk$ib;FKI^Lsn!_0UdMm`_>vr6 zKr@#a;bV&fPq3_P3AdG0udC`hH}`}Tq#A+FF_KCKCT_x*{65}jL?RC@AWZx8eM(#k z4~(8q1Anvp72r95hOGS~8h3ng04OWka5Wb+S>pOP#=PPHw>Kh#{3jZb*6@hWDO^3> zpVI{kT))j55t zwVkG{yBRMC8qPPhcjT5+zifvyzz;R+3GShKEO!K8hTK{i7@{SlVJ_E7Rpk7Et$RiT z(f7orU3iPJ_Oz%|g8B26>O4{r$Ot2+G{3m_^rX2fxpD-cF-5Q&PmufGsVGWbPeaeo zLHONB(epWM_Tp1ghghKW^a}%|0QZ#DSAt0WE6I8y1v?9w@wR?pwDiPiT@AqZgbsDt z+AH{Puq_8-!EO9?D@4mHCR~o4OZ{<)SU>ugnRSgu^@|7q4op0AMcv6`PINGCzaD?*eJzFFin8zaz z{)$6C4r>_Wl~U!TCoA0*%*wx&DxSul8IbIor?SI+5T$DL34@R6dwmA~CQ5?4nJP@) z*W~<2_3qDqaD#T_@Kymd`4W~QpGyogzN{+#Vd&J(PrdkFz{&+ z=8Yc@jitTQ?ll9drl75F1u|?rJ560flE-6tEe_%dEPSt0;wYS^4)dWUGB?l;ozX)! z!B2|OY$5R7H$Y{q!m>W^U!FY&P5o%28z$0S&+NjBu!=)e-&VhQJw324Iqv(%@lSk) z(0;!h7S{l#x6$Angm2@pE?Mde1@V!Amh$vDCjHeAVjGv~n}V5!zB#UAVRZ%v8+kX{ za5%hLaS$F%jQpzNwDQ&pX(pHzOFp^|xvoZI5Ob2&{dnu~mj%yy?K%{tb z{)1iN7zbRQf~RV?)&_JQeQ3790!Rk;mU0-7B~}Qr&?#aU={R8EHKFjuDyH@1yJN0Y zF439=bSHTAswmW`ET%w9sVDu}ov@T*ST>3H8$w7Uc4)YudB~S<;hxr+TwL;0NFV9= zr>JAIx*rO-qxtFps<3mfMrzv$8lu)~Zs4wo-rFrYt`SFn0Dbwx#AZ>cQ#)aYh1M|w zt97bg$ldDbi(McuwdO|FePQ+(KPz~aF#Uq5ga5t%2KW%5OdtCpBetCR(iPT4bk!oq zdZO*J~xv&%Q)ZUZ{*2es)n07vQ`_vF!pGUVV)S7u1s>UAnWODk3U43m6Pq&buH$ z7om;fScy-3QT(<;lmU{a}cGL;A7 zT>zpgBd;yDu=ol$-h;`|o{;dL(wvCQKPaGm6pFwl*aoWc8@cyN+yLq=Slmd5EQ?=q z<3d;7wI)bQ*XX^=6e(IH8_=sE(niS*e~Fx^%quh=c0+aYBb=!UC5leR)$qhoo~7N# zp-w~U?^LM2OYjf7{bRI_(>HE+T36U6A+P_f{nDm*%jvGL+q2exj(Tpl@O^8tx8GLl zF46GNn0e}DOu;OOmK+txPRg7?>c5^9Z=buDPEWWhs)ui{_heV|M;e1WD<3Lncl7(P zuaZZL8#?+Xz_yWt-lu*@&>&N34@toyoJ;DDkQ+jvaZ~n{JzZZv0K5*QZUz!sKRmt7 z!JeRBnwt5kjk z2e8Y8r3XGh)1v;`h3aDgz05(hX${BU$k#o0G$c_C53|SYwEGQ%epJM*f7{T;E46O4 zW-5Yu>;;+I^lT0@3L=G)NTiG{%tg`dW#m81<=i18D{pNd!-@A2%K0Ka3a829F)qg+_Z7U6mQ?M+AsV;uART>;t%d@^(&% zrD2$YTqraB<^|HanM*`p4_?VjlFm@O`eh)1adA(kb`YX%Pl-y+#J0aY?o0!-<1#Gn z#!n&;VnUSD&#tO_K9s{();!UlWx})nsz)lVpUJ0Yhc-C2``BF%LgI{m=vK^aFZp~) zIlBT-LvXKnFx|MR>Clp8FpfPb@9ANeh>U%Nx+$AG=$m7Q4&U*;2W=@w6)OTw(njQH zUc>jNi>47#9o>0^{kaO0^$rlZ-J@@hxyGRohGESocV+j{YRD&KDnT^dZM?OL#-&8q zyh4@xV^+ie9r9$Erp(xI6JgAoH_e{ywAt^*SOQ^zIzL0M2nILy#P%46=6>T#ueQMF2(5_lPZu<64z4jqfFqjaP-0 zI6~;S$e>m4E8+VG`HgZ=w#Y0qAI4qCp^%3m2xX|N!qa~X+^zEGBGck(6mLy`F(CaK zr%9y#D&FGNL~*o(B3h_m@^nF&sIG?MuRJD-HxELyWRXvVE&lYJ@=XR6~~-Hiio&>!}z$Bng0n4LhWhV&jW{6|dknqmJH0#^+Mb z6(Zq3^@`h-@O78fnWlqH!Dd%U=BrLxHfo9Y#Qb=7*Tno`!f)KC^A(q_#4yKpVTZaR zKNHYt&8jn&;@u5r{~?(AwA&1x7YjRr99jaTQMzkqMdA*?p+BMDY4RHfN%>%7gz1Sh z`|npTJCGlY0a*Wz@MGwPbHAo~KfYS-z{XMoGx~!U`%GM51Sw9Td)`!lhC6YR9b4EM zNmn@TbJ={`p2+8Yj6seCJ$b3IB~y4Iq3CseJ5n$GhfIsXz4@G*{PB-&>VrNeSHqv* zjlQ~+#wT#yadCXp$G0iGqd-bNOrGqdEa{ES=pi@rAhNr-Oj1H6d~BHQu_K*3RQz%# z;n*`X-13&T!)&!sOU>Nv-nH|#&RQv&`r+3sNM z4sxx1xJMAE=jpYL_i}pQ3{HIaCklAS$lj)y+6I2KUVi*3OgXD`j26-($Y!9T!U8gj zZO0(@Tn~*n!ZyVnfA{rW+raB`(?0}DCNpbG*BcUa1?^Nz)2U32J0Vp|bUCuR6SV^C zh3H8r-ox2|S+NEExf|spopNI}bJUL9dWIW88-GO3`8q#(Fg+m0@<v0&em-zySbuDTVU>4uWj&z92! z&Es#AshfE`#Lfay^)Xmkx-D8^^$=P?5BDOupnNhXHmkno8MW$n>u4@= zHQHRPqB)oGL3Wxb9h0@PvE1#ju~ZSdM8C;E%I0l8Xkvw|oVh}Hl9_L1rzZ53axOF5 z<3#*Gf4SqbCPyRH|^<3{(_hS-KCvAKPk>l?@z{^pqc|+c*Z% zs4hl#2IOv*QZI8V9^d>fY_N&;I$f^HrKNwORFThWbbuX{FoK$Hu zUk!U5WqWiPTKa3{tvI$YK9|;zjzvq~qlqrJED;EbzjI(<+IX3F`x%q>zA*Yc9M44w z_0bUo{-QVkp!mx}B>LQX83=B_{5UF1ngIT*9VeiOv3EL^F*QdCzN2zbBaoo5#AWUw zZ-2>(FrqU{mQ9qt?q_c9XLP-a82?lAbejyXc-H7ME&WrfUKPzSqB_p87y9?x4H=Jh zZ}lXfO$MQw$g$ba=gzIMn~Ce4zw8DF)>mkGR%&N5ZN6x~J^ugE!1P+FxlXL84IhBl2ElYZJ4pjsCI-IK=>xzC&%d^TOTiq08%Q ztG}bMcs0iHvLVXc^8-9~_-hu# zz~dE&iid>WKNB}0o*c)i?E`(+8>@fy_FHeg29R}vqdWFD%w(sRPJ5@?DQH=`?&y!R zF^g9(5&ApKeg(qF)*QM|aAeT#s+crGf|>;uY7Boo#=zL8tqv*A);tL9)l4q+#YIj# z1rr5NVwYU{_@hnn)NW*}@pE4@_%`7J37znN=I|xU(SCAvwr?-#skg)_k>HihPcid} z)SCtg2WXnk=r}p7of}V#-R7tg{9Ggr;fj#lNkvO%3QOM23+!8-mA(8#=`-##J9o?4cAv@y3nk8TFC4?!{$otrUBHR zD&=nh!V5a~&f%HihWrnd>8aanD_=J5{#vZh!F#^Rr@+>P)nhNVRhZ=sgHZIJrY`(+ z^;7F%-S<`t|NR{oiG?&E-PU}rUf2$@mNUfK2V1QcGYhd*|Dq-Z0b1462wEKk2~69{ zJOP&Pn$rTWg4rPo2RQ#bTfY63BI+zWXQbzTl>gjf7acEb(Zzg_226pHhp@+0Kc{Fb|u1K{O|NY9dmiu!){4kbCR2*I4ZZ~u8M>_c%7mV z3&A%WNDe>eF4!l-6Z?#pjXJ4%F7OH7Mld{jS_Ly^{1TuyMy<{`jzyfd5i4l%A#piW;X3$i_a~ z{iJP5n6+x%FB$!8*Sq%Y5O45qbyuS0;7zgC>jh7(f^^g#6D0EE@#1fg69E~z;ei9T zGddaFevp~8cBWcn;B_&~`+C?P49x7~Qt}%j>^Dlr<$i85{4c!mn#Yjgl%NkNKQIQI}nn5p11$;kE zwA^vv`75HdqVZkDocZl*;qfEe0x&KTpT6@PRDNIfsL*&+D4QB5J5?wx;2Mh#CGR9( z`Z4H2IjZ!WMeOX%b>9m7a$Oh)PRxkn+54DWiWSd4IG!c(r|K)?5vk9JBhAT6z)a)D zX|#ShNn}P`Cs=BcZ|7M;n{cOUi8uTMSv`)cXFK7L8i;VLzlQ}B5`NyYbb?UuPqtk%_}q;n;5Fyc=HcvG=Ma;8)FJlL`o>jF z$KVrr{Tj{}Z9i{Y(4Ap7OS8*7v^MIrIHKogB1eJe%m2TkKud0ew);#jUA`h~7l?Hx zxW>9vkqyZE$*-*#r%g=pTDW>>RJb4oi=q=2 zX#rnGW%m_di-K*>SRHYe<(F(84yxYnOGmaTs^krGXE|zqDgq7F;xovLrQl$;1=<6y9cFRLKX?w7u=*b_jaqFxAdSz9}cj2+&`h;n4FWY%)#_8>pJG;Em6{wi57ju{H#^&t`t@85<9C~Fk$SEGWN!c z3k0@)rPs}lTnc)y>#jn4dV0S)CX<0u z55Zer7R~+4rBE;5daUZy;ax=>y+*ds`VqZNCD2Ri*1@Z5PrN4RD-}Cv1dTegKC1S@ z(d(^gd z_R182E5r_nRSA!OS}M#BxcG}f$s02ss*j2lmhrEIPqPeXgrWbMFb!y{U&b1Qm1WZt zwtuh}^a1LFII9U#Sib~Y$Y#}(KOm;hE}Y(KxT~b$j22^B0|`$i277sQJ^e;H`9Hw- z=CB_S^SBR=-w}9s%=YJCW$s86}o|dS||I6eoQe!&n zmelqIeJS719iP|6yq9msA}Y)&|1}Acw!-6yS?A6gckg9B7<;yOyM}(t)lZ$KTbaK? z&tC^YZmL($|nxyUn3+ui%oAq^s9_g^(g*?XSEj>0`pO)~tZYNtfx_re)-*M|wDkgv)_E(cn z`W@!a&@2B=cSD{AQJPfsd#$nC)>z2{^QNFzT}AD-;`1k-4c)PRkH!kE1;xF5RFnJA zD^$*#>MWJq>7gA8y0Fc(`GX_}|6l3Pp1aDX=vv5)qO^W3|x8%RaW|GvP`m}7)ctDGY#=Jv~9pOTH1Up)j3E$;<+ zu8D29tFJKdu~3&Ul8LI4=kyERFwk6nwo8+l;Pq);Wvcax6o2r(enI9e3Cw;P658>x zQBz%L?xdJP@T&SqZN80mT{#OU4J=}@67)ckmJKN>X8ZSnW|AI=psuBTeJmx|q^ zPYt|@5$dKPnKMr1CS4HmNO!XhP<@W)D;j}5=4~9J8dr`xt~4heW;F(im#|qziyxO! z_Po5(w}Lho#44=`iLIDs1so(g%c(4@|Mz9rd3XUl*HVfdAn5Z*;r%K^!2YWM$vIFi zuOVrEI&W$Id+DLuQ}iah3Sp56pvNH+Uietj-cD`n(RT$eV08H(ML5E*AQrZS$Nu{0 zdmpC@oeRyIYqXMbh_xa9cZ-~Z_N`@hOP#*e>HED4h}QNW^_<_oy+@lq?fHS#m{27G zp8sUQs>oY`{ZuV+YNYf?K^D#I5{^Lq(`$4}8T_urt`8`ANIcALPvkzmru+-@6Yuu(`ANtID?? zZJq3owL!Mkupfhzi{;g?d;XN`0`OPU@rn0e#Nb=)vT{YnU|Cf1T~AdB0K$1>jTGOx zra#Fj#ATE|`tVv^&(t)M4seR68xg_-fxH3rUDF5 zclv#W!O#8>&4W3aH6N_~-7t?`>fZkUqwB5T+KietTqrHjQV3L_XpmyXT8c}6;ts_f zin|nt;1st)ai_RD1PQLiU4y&3B{})d-rqhyo&Vsy-fOLyHP6gEHwl`HLOwYI*S%|R zT1a<~7A;xXQT~j8T%B3WB4e~gJYGWy`wWHSo2y0rL{z1>y158}3v9BJb0 zD>+MX9DZcAoUZCaElED4p?v3>(+wX8<@&~>-3TjabD9}?5Izj81oes73Sb|(Q=%+9 z|L0s(O=_APb_vFvMnG;X(4LWv+gSu8IcGgRacUv^Vuoh_;5aV&wEN)?`%1J&!@&xtsX2 zWtH#!zuf8CvDdJW==3qml3Nq@3QwwqcnNTZyuTv*b$*@CwF#-)Qvb1nDrF)9@Q@;}TnqhRfi|;>@X?QGWrLNCqxK?*_S)Yiw z>hes61$2Y;h6$G#9!*%nt+99|`YsC!U2UnS^1eijp^4hXK};c7L>vtkDJ+57-Tu z{Oq=Ci*XZMZD(<^9|l<3&doo2N@l(qbk)8+(Y=kreY9PSn5z@uiS;SE9_P#HU^aM# z^*@y*%8>fy<8l7Y641$db~n#6^9O^TlIKoMB~z0Fm*z}+GAi2fi~rwC`s z*yCw|ZTPM;vCN>EigYfEz&qR(Vut0#32_p4*%+iT@J@C)v)9&n7a~pc1&@TO|7Cm3 zj{gnD$vsAB@U2tmSjcKvvY8}A@AL~~Rmcq5#oy~C8v1WIJ(7%|a5@I~LwaAymfhv0 z9s~_GHlCovGc{42u8PS_x_3jFy+hpBbgu9^i*@7c1IK89HOETm-Eg;4zkO8u#jj{r zdz{~dG#d`>mZ1%=a*w9(JiJ^7r2t#(_*BBAiWQh;pN0meLC=8+$~$lP1#hcz=HHu^ zz1Q0z;nzhT2w5#?A$v&PN)psN@7 zi=r9#Es&IC?*i>quHVJ6CVz-$4;91 zwVkpj*_tFqFjO?Z@eK=CJo+5ty9TAOe+C8Iyzt(+bK9pf1)tqbTQ3uR(|ATtv3u%yjEs-;={CXrW8XZ#r6^QXtS4j)>ly0cHTNL*T(9_ zrkgY<-U_JV39YGM)o8rBXy!IOM!A%?I;pVgw-hhLnB;ni3J6|J?@%8t=PQrPE(8X1 zUJherez_LR;}{mha|=KM#P z4F@j7c^HFTALNwsc+k^;vwCRf89Rc4Wrzr*=i}~5N?4Oj?9h&;t)2dTH83qM#0U#s z24JWIK%C>se=Al$fkP>uz7-lG>4AUe=DTO_<_0W}V^AmL84~D^Rij;zOh!qzNT_AY z;2PoW^ekt%Xqz6V`DTKzmgSo*jPgKb4)KXl?~8Kr+>l1~UUt;TbNYqfj`JAWcC!G| zTj{<4aJvw7hG{-`HqHoHR5ijR%3~TaKoc2OHp?^8Hb0jqd+az3TkRh8Ynr=_Bj#n*0_YFgM72j-51g~__adYsviae)VcoO&wyQ`vRs+@2_Iea2VYTJff9b!GLYA{jB$p{b8V#{UKGu zK)1PkjW>HeFs+r*OkZ?>=d zo2V*=u!_3kpCJ4nu0ot;--t6m_vo5VxxIcCjcdG1{iMCw^6D$Z*&H3bJ?dh+!k51B zuZXtPc(1!pi5TbDuwh~;^&KRexP$Gw+wZ-kqQM`K+|H^`hI0RhqSt~GW7HCd+9Hpq zm~!uEGu)^5YcNyZN^r}VHR^EFkvHlc=qUb8ZW0bs#LRuc?ui*2puI>E^e^ho;!5$d z;V0jZ-^k(eFMgeqh{|+b9;ky7_=BS!EnI7<~kSFtzBonI2zAaq0VtODO8a z*N@<`{Fd;kV~TG?#e!KH0&mYBxe$g=5#>ayyGz^jd>0_cs@I+(EjBjcx-E7F;K=R; zNkF~A%;{9X!vV???th;SR(p$IzwdgbbQueo_{SaGeO9`4OX74tCSJH(lV$fjNtNR= z>K3}BqR7Ok7_=~F_A+Q@xwsLG@=>0xSdOia!m%Q^)XuA+ef~xAr0{j82$7abn)jlV zV@eSYedqwYIc_^0WtXx44NQ5`+{>EeqsslIWUT)3FMFj|A!lp^@1iP{zq>jwghz{+ zc4M$|n?-cH7f_|7Xa6{7qO+#$^NX6?_oL+_P9T=p>QSexX;K!+`&w>OJWcQfz`5wd5gMV))H13 zm(9vyJL-^3XTL7b^y!5cH>51jo`VYfSS);l#;Dur1C_md&mp6jG;$PVLyI3V&c_Mg z${Cb*>$H~j3h-jkCtfNNDjgOz*DDk4sV(VNU>VM#Tu8C94-D-s6fy-pDJQKb#kGg~ z3yRt+{a(dafBK>9NZ=s5i17nId zzL*^&7{mkKvY0a)^2h0d#b+o_pq@OGBeY5*sIp|pq~e(UdC||+6OlMP_YxurjR$k` zkn)(`+NOEnRrD8^YHm#wPq;MNe%Spsr%cFAe%8QOt1pSmBw&Pclodsixys-lIi0wO zoxKdh-y{83I?l};psz&leSBV@MrgIN-9C$pRUdzl-7x-tG2#{V4fl(7`y3gMpkNKU zbGLV|5&9GrdfMiRmn9^&mj7QA*|v5fquVd8DCILoR_)a)%v zSCdn`>8HL)>4pF74-4TH$uDxlqNEp@*Xgt9wv;sznwKewQG9UIR+y2!JKsl@xBoC+ zUnu=ZQl7heYX_(a)VtNVkh=oNz1VYR?qn;JRh;jLO?8$QQ%rqT;4kR&?63NRWQS3f zOYJGg56d)kdW z*-v>!(CY!By6BpSYi!5ZjJ}z?Io4jeG#7pTP|a{Iq68aT#XB71{Ga z{3I!MYEN?h_L84?ji~P|_#+~%F4rKN+18hTI~}jKzT?mMAYCD z-5ds$7a{34d=gFM=WHi|*LAbm-_}42W8?W>ulD^v{1bkCQl>+Q2ksb(x^ocrLK(yI z_Ye4~eRD(h@CcP|3LYeMdzg$*SXE*~Yu#aGnExxMxl;HFs=yJf_&8@YrHi%-V~BUl zn%@&6i)E5?B{h8-YCA-QO<~!wkGh#I$6|Np+IZ@wh#ayMya)>-oU{?9RWjPtXj2GW zYHNa=*!E~>$9in2S0giSkj^!X#L|u030XZ*9zuOrvU%ZEr@*NWZ;#r@nZHXo+b*Rh zVvCS-t&euA_gTa<-oAf7e!vr@7{if8P5fVVLX)Kj(Ia~F^8z);IY5H4o*==q=!XC& z&$iQQZijFeTB;f2aph%i!z2zu40DqtTWYSGEB6o%AJa54e^2CFv#VpB5YO0*hQE=w zUH%GDxW9;LxiY|~Fl7|hmN}>B%H$nklheGt6#yl){)ADyS$%F3xaL0)sMq7T(Hdw= zc#pD1zk>gT$J@;dICw>=^PxR`_}IqyL4xFiVw|EmWJZJqP5v&v@WyXkN_PKN)D*NP zJh1tVzx?Eqoe)w~nCGGJ?a{^)y}~6UaYiD6C-G6ZqBL$+VF}GJ`+2h+5xS=Pgw{Q?`^rjKv!PH^v1hZ$aB3{@yOzc;2x z#Zb)`r#TLh`c81lQkGnC)aiXVn4Qr1=t_JVwIN9OJym+-5}oQ)9l_#G@=>VFW#|-M z1W?M7W;;`!{dN~9PBIiJ02*jbw-3asueBj=`)v}F8oS87vNLs%rx9Gdj*QA zg+amex`Ri;K{L~z^8f{LjI%PG$yxD|Zx~HD%Jtizz>2_3k z?~xjy$>`9AAzoFkcO4}vY#npTIQ_tW%R|Yc01whEo#vM0pAo$Jj4ry(Ax1$=KNoJ zh}2E$@!>)FDA+C*TNqx{EYA1=Gz@&a&>+i(dwXA zKr};;RkcmUBIWQ?(H%V`SSmd8nU2}NEE0N>}6chEmey^Y5XY#q@au(eE>$`2W4{SeofEig{+ zAL85nwxBBMl9)C|OGUYUsQQ~BvO>RFop3^xx2Fal+jXLSr^%rmr&fK(!UpT&=Y>a| zOmcBfBe`{nc$DcJhgp>{FshaPx@^|R#_e#F zqb^#TPN2Q=7p}cYbS;DXs~c%`EP%n&wb*|5`OV|O2-Fn}&~7M-X*(lxwRWKsiU`MTSoP;#s*J*wSZ6_AT2Rss}MFPdmWQ8ny&=7)aNO3WUX1Z z#EQgZF*2mu3$jV#6)X77?h_#8;lM>N>ZKU98^!5F#rXe9B$#EC-VqXpzzX&-*};|^s%dDsiwh0 zZI|7yZHTxkl|#=Jbu-_B=`$9mSVG-*IBif2-IJR! zz~UctgZugoUIU70uO|t)F_o2ZvYjp>ffw$?7OuR-Uq1w%tK&0im#GPJ$ghYUDH?}W z+)og38(JpB)dK#t0I)n7+Fp%y=5c-eSE@wEanl#{c{E;X6hq5y-}}Yzl>ND@hI`MS z3@C=##Ega@eC~T-3}WZ~4=3z)dX{Y8^s9c$s?f0szkB15s-d;RNa<8Z?|MhF={{c( z{F2(h#qouA8`cWO>6p13*t>t2m(0Msy{@ zwE6ikgS=%#_UlGdc9(%6dMI`vC3g_Cf%S2RC-}C`dI-@AK&uSm9>(3@`xSAqp7!G^ zmpdk(dS}(@AN2lu#8fYG{)DwY&ijfp? zT*X)0*`^v%k5sZk#R>K=-OGZdh}hUXmIlMZoUsYi_DF zOdhVpQ|!9N0G9Uv-&Z9ZaVU1!B_1NqmN_qC&Ux%FqIz8eX!r6@EcyCGL^}Q$*zhn< z%N>*D6$1?DNVNs$F&G6tR}Nz3W376Rr#VW}EG}}~ASDb6+Ypo-269b7Y+S9eU(u<^ zIpQbsINRM5W)`fu0LMP};`|`1DzVRB!sGxq2qUsW-u8x>yEk<1bfHz?gGoo4HET~c zdplvLKaUV5k#KNXqPasBnVK$SP)1|1l8K*BP1ftx>VRj^WbYukQ%`i5+_8?q{&Ek;AON zHf%p}kZUM(^qQT#>pPh_{yTCb%kpQr?;;ZE4!+0d%yQVOxP9)GQ8d84+@Zy!#&0jb z7VItj?c{1PnOAPh_l5ZsGk4!YyBq!Z$6B&wRGeKlXCP*}zy+U!I>F(b(ZC5k1s!<2 zOKDflV%YSLpY6ePn2jQcSK+MQCV;>vqHvpN=cx2^T71Bv_+sPGr9Ps{Xn<&!Mf+C7QKD9{1=bPGJS_yv$Y)gQ}If z?6l0L{(lX5^o&QAIY*sMF9OgDMK7{vd{0G36adS)OepiA0TQHzjINB^m&}Y`Ii%hk z5lo4m#_}RBSl?&l>ZfUTu$Sz!Uq$Vj>apsB!?XTwQ4%N3Xo&o0o}+vwP$Cc?ekU{HMWKDu8(=51@{JG&_lHHc?rYj178s&tpX-jrq+ci~Kn< zlKH;vd^P+N_ZYg_`S{t*{iYLwMNC6mckELjn)ayHc7nAQik|KFTQLO9Ha6u+%A*NWS{wzJW>N zWN79fY_~rxlphy%KYgxLThabs2JOFp$6v9d zxp%+*cxPy86%yvW_6I{7*V>EpL%tx5T82h3%j4l^pp9&y2LtFtqkmX{fL#?;Vug>p z?9%JKg_r zvMW2bi&#c!xekgZ=8}ixA@w#vczn#!Z`}S@uyNp0=CTO!>oayfqUzvBKR?6C3h!NK zvJmBV=bkgYTHiH2Hbx2h^`tdmOXm1%y_K;|zu8-AiuWBFXDwM^y|iyC~MqAU!}qz1hVwc9(0E;IHe@#49X$jmxu_G%ybb;W1>x$@?Z z^%8fgX&+k0{FEK|vKr^iC6zx3tL*u>(2*VGF*OsU;Am{Vmh1B*c0E0ex_2jadAXqw1Rr{YN zI$hIMLaK;_Zdsf4;DWaS(l-(Yb9=%Y*KFuv} zUvt*A!Q^2rI+C?=ct>_@;GtG=@Wb|`LI%n;;ciqkWh3^603;q>RHgN41P!~F7Y!nI z2=%zH(e>Ro^*AvG#_zV@Y&zY~XqX1UN>_Y7I-MpCthkBS9h_odN z%fCe;b+3gt_Vn=%cd$i8tN(Pu=Q_G<#a*4NawTEn*Gbe~VCYSzozQ$OFqUfL3?39O zD6N`XSweFAf`CAPTuFoapTIqua`yA~+MEceeN@Boncj=+BJk%>F8Jc%b0x!g@iX!n)N#puNb~)9I|w z^9_Z1p(l3o1wmAm`jQ038P zcMrJ(b%)a45%4DCGW@8U=QHFLI^zQg6-z-NS?Id9Hz4SDNl1veLjM5tghx!M$abGy z>xC?58+Fu*g)&)x&hqjTe~r%H*7fd(TW9?nMr_y*xioBXX&m&sGbTUQdmcQHUt)~u z?TUjiKNcA&s0MHTRkGQ1KYntXZ`)U z4)a^y6-Mk;i+fhMF$>3Vjk?Ye>-1XR`|Hm7wGY0&+F5!=!@qQ=<5_!t$f0u`V-hg! z#ue5W^% zEmNnQ^FISgYeAovT}RP(jtGpAq4+lV!mBTyd(-@yQX?BZ=x8bkC#t;gbG_sT(OCn1 zv*a>csN-?T^w<2^%rwQzRO($|9nTcg3v{>A*5~UDVA_jWIn`HF1A@dFJ^{_DM7Zgc92chuDYHAP99ky zH)8Y|-mJ#npBd7}B2m4FicB_S8Ez&~+kq}u2J9n~bCh(8F&atdCI^?Kr1m4aqwEuH zZYhJ_{Z;gfxy!|Mm42KQ4~F4Y$E1HmMaZ&}$#)A6j6*Pu9aeBcVNX;QeG~{q3TYlc zA9`|mojD2K<2j6}J1%^40HIP`sVe@INcq=o#?qQEDj_7mWrsF1}~49qfYeeZ|xCl%Ob{e>Xx45T&Z zh%~g;Kfw=G{p zOI8x_p_py>hILiTbu;BKX)DQRnDpXO=sdjj>7QD2U2`YnFRi*3?zk2}zfpUc>ib5t-X zH8*!Y+i+xiIuL9tfA{rta1?+LTzFhp9O})wUAZ{IIZc}AGbL7>H3_&-bb;3W@|~Iq z;tRL8xLIZR^zMI`@}U><@(n!_y+Oul~QbKNa-R&+*o|y!t%0 zI) z4QQ54QZ`{`hjiBUV#>yssz~Lw^*A+KVhl8=V!@d@t{&x)HR`jT$Fvz!? zTm_8H*XvW?D?aD?DEG4_z})3Q8RyF(BtbNdDl2E`@$uij*N$lrHFaBsueR$~EHd^}C?9RQS}QsAe2 z``rn+8J;b8Qfbgm3Ek2GQ6l>);aFR9h_0A{M(`Hx{Xps1z#+*k2HP@aTZJWfZ@X}7 z#=LSc3D&|U^zhRlLuZwVhLM=p1 zx~ui$OocGo>1A(-8xx*CqwG=Dl~ zhtXXd3;l;l$(OHmG3arkdePL@#6z<0&D=nte4;E^M*=U8Us9wG9el7|2$ITXdLbUd zw=p7WZj~yj$cmx%1)*R*xZol$UY4JG$T=5ReR{+1_B^Sku> z2#dSC(<$B~TdUTuU^=(u z1$WSsd#4wvggeXV_NcsqR(%!B59A`<$b5d2QCqd?FblBjf=16xt^=~hF`8wM0VaB9 z-tPG43_7b3WxSilTk5+5s$&kO&8;(yN z*AwB!12KM5{yKOzIW${}*M@HE26s;a36%tc+t3Ah~R zdaoRg4GLXH2(coEgdRpNCgw5=$lV_vXzyKM*97+&$ezZ_Y{HOg4K~}0`0B)P^jjM5 zAGZ&GaGb6;3akOY0t#Xh zCZ=YlW@;-*1~bw^K2LX!x0@6c6zjxs3IQhc1FtEVWOaU=3j^MH8To1WYydNK{H}QE zr8LEZBUv@}uIsXus^-M^7(b9|rM0QOI>++0fDFyhR}_BS#k%BN+l^p88L){7Oom31 z#f_o&SHNg=HoU2>q>qHM>}z=i;(L9>GXGjTRvYt;9?Ar6k|it%;OvoaIx00h`<6HU z;Ype&l6}FFKu_&}i}l^b50VzG3|q#058~fM??W{C13kJU;&3M1UlhNd09H|f?>lYz86a-IWwB20kkZ0#=n2~yhBagj@ zV66DtGTq_u^emX~7`)u7#SyD6IM zJgQ8eiK%*#EYCLM1B#P3#{#*FW@(F!72kh)q3G9C6T1R2fa1#?!2_6a1_t&T5H*B$ z^+M&nbf=oL0_DgCppe7({9n&yUTb*RA5SvZ=G8X!2u#w$^ihk(um)BFy=IX*a8yxs z2~@G=Hg@kETp)SW0tWNVfeH9&?sMcCdfpJdP2yJHzV7oqHwV#G()AU5(trCT32Tw` zMQt(C!F!<(vR9YBm%~>}FmJ^zss6(-WCmNSlC>4CtzFh%1g?uuY$U@vh6_K6D9pEJLhR8P!;R}5fggiQAL7Eu3UpQ>pSC)?} zf**Jvn%UY)x@Z%dLOTpGSsWGC$lplKl8S#B(;LO<(xqcZ#NyD?^@wN9nYnX2mdj2b z;p=VG4;R|29PauA%_2g4f6pQ%eZv=h5%iYVir(RnEQq`$_niC6_dk!y2%Yn8~Py3094mh+u2Lj2$<2`aK8)VK48=HhvMP;wlE^R^x@y2>x|sAg!j!o>MWb zBX3PrxRs{K;574K;VKbiD6ILYaOSyX^X?Fn)W0V?Napw4=C2~AoL6tzsBTRo1Fuek zx~87@?U=ldp<*t`c=4BF*T^peW3LH+mMqVPpvFT}gdkL08lRot-YK7|SAYr;2=c&thEBNyoH736MbrdEd9hr;bp*E=dfs!3FH1 z-)wIjYtjjS7-PC-O6<8~b6_wF3L0dO_3?8}ycOru$)5f0yNi(&N4@z@nx;<3wmslZ z^n~1jUwrf#?cc-6NJTyp2y2U2X7+o2BS)N+_~B$fM>deIFU1E=Oef1ez&PIz9*>kIS0Tj0H^gE$$0lfs;IVnww?P53jbR#gR3YdIU0piodw&fBb$_7%=$D9@%bpC5Bh}S}xSN zyxV^jLj}=lq(0{=eD-65TwlRbi}|8X7qmxsu}A(q{$=s9%Ng-C`pn2M4V$$G-94@x zo%|$33QXw$2I%%7eWbS-5}^+7GLTduH^vU(E{YTKB}s*$>ZzY#{skTzrF%+PO&}B>Y!;gMWT= zv%`QfNdb34zORRS>vSUJ4#{l5$A)gj$;ClpCtGs%Zd%p5A5DD`{U33*zdQKorDsl# zPGLvNUV+7tiV^vRyAdUu*Cy%UvFx4uhX}C+vRAbLjTKIs{rskb16ohYcIxQ!npSV= z%I+*iwlS$K+6w;RsKv=IXv8Xf1;(v@A4LuS-ZQiMe~BEr!2h^9{Aq$kq>fmR*rO41 z<-9Cf!jgaV{f>^19*vxSU$Q8ed5@QTcpSuOC3pZlnV1;GD5-x?_1(w2=32bashigz zKXNPfy(PdsIekNZquJ+VuotOUtTpSCsRYHoPwgdaPPQfyAm%*uCcE--Zn_M@qW~Gg z$ZM(?oAV9M`7USP=Z>)C%4+bm%GEXGI6bK!ufEM)>3>i?c9b*-w1HEJ<1lBwOw`=y zGOAt41^QeU2*4ND&SMG;SH$ZLD=5TEOq)m*O_fQbqrRPfQh9l;8RBDUwYUutI0 zSPYzYBj)?Y?Iip})5DCyE-g8Q!?f1O8E%?h#~l4<68cNMQkpDhD(`8kA7disOT<{*(u zBZ+pD%t`7(M4K$jwJ0-`y=~&B8fZi^5H~G8tRK+Dt~zLrYcKM8C9q2;;CbkLG8WVR z`{$~?=j)`VnOuM#rw}w)9?P)top(-&5T)xUk$qj8+#e(xAVkR#%PSW>)qTqM6mK;@ zKD|_QiX)#Av+$72`G@`$OXHb(o~fL@zPef%>)7thhYPcJQ^dKyr4<&l|9F8Z!+2{R zaC2nZg{6R5&w3qe#4v#xyE$3(-66GXZO~6KbKg5O;zkLJJlYY|%3N4>g~1nts402+ zke+)C-tT-kPmBvB=CjUiLAS&13*Ot$sh)^W6;}dC2*b&@aIPIf%Yt@ZPXEMK_m!@_ zdIxYIF4=2UkxOcNVgi7vilkEyN}0F5xC;!SiA7v&u@cf|Dw`T>{~H>8TE9-W1y8tb zU?gV*ct?F9UHfpPV%*{Er$H|CchNIrk!^)a+hALjwXEBUUvk=O7ev6N7+r16KP8i{ za;My3+k3Yw^iMB!A`9S|jvZy}`X+3A`4TOAkGRjjtj%p#`Hb zL?Ibc&cgoPpRSVjCU<=UD!g|hoUi{VPCi_l7q6}s_}KpO z3?v+jV$rYQX#R8;K;jy9OfFTFFEZ=*LTz87R23A0j}XlEzpJ4y1HnLlqN z9}X23It%GdtcPE_x4D!6LlbXJ!beaq-9#a$D7IDJ& zFmCGdJhM!Fi+|7Fgb^N{{0^024F8j18dVFt&HMy@Lw|qWRO|nVx0|H6PM$mRastbW zCWe7YTEX>W@kcPhxU{pXeP*OT%tn_QaK&Obo#=vKtmd)zb$?Kc?hSi*)gI;yTDz3N zjAPJwC0}_?%vku6^z5akU8Wd;6WJ|}31X|tC}&c5N0r{DeF)P=I`!`**0*X~pJ|_Q zC*grZ?>Mx!`Aim>{%0oM0xiofx%$e#N(N7fU#Rp7`1Qzd?Mwgiv+b$z|EnTQH&#f? zT|IyA463`cR8}jzj9QqR6D*FjK(p=ef4OwK1gorgj*%O88-oR)J>~MBa&S1tqQ|2i zpF14)V5Oy!wEEaZ-J+{Hoeh5@TRpkdBV>)dKn{!I36 zh3#bR9JghCK3A1=g#0wj3l8@9PLx&%JxlV9Mw}xb#jZ8@KCcUTHf4MQ#G)3O$oFQExaxKqlojw>hs3j`5NGulOOlzv}mb zF0ysTC0i}Jm1(m`33Zn}ME9FMOOc%XwC1=Ux>Qx}De~I-oD@1^Cd1GX%S1n3*3p~) zSyESuI@%bCebP}tm=#ylPp}~QhFs9Bszeg`Nv0Hx44~kapT4yT5fhC5J)z;BM8LbyBy$yYQ zj2*i!&nr}Z*I}o-{v?dWUHt0j#WC6Z?Dp6)#{W~#rlU{j?5@tFN5>ZUz1RBFo#alL zu1-k|o^kD$(?M#^Hy*ek@a(Ga1FL_dkZ0r~3@t%O8w-1j1r% z?tfkg|LFRss?QMPm&6|qI>HC0R|9K&V)f0}8i5`xbAknkb99Qgw4Nt)GZl8^XKvqoAlGZn_e7Ex3Tee zA8hKi0E!8p0Z#5&yP@0jRVxq~=Y773J}#iM029UWTfuh4x=S%`>+M19C$nRf&2d^# zP)B+oEcQ?JSjQjZ!lgnu%~RF&XNRaTXWf`*PE8z#7mMo_7>er~Ege7Z0*ALw~)<{9qx<_PGr*VukdfzmJ9ShveAyzds0DyMvrg&-O3N@fGE|2K=h z(hPCPCX$kKEvy)w-l&&ukti>Jzo>0JIkbs&b;s=!(T;ROfZ8szkmP(1OUMKg=mU#3 z*k1T}X4m5Ser#f>&?kM?_epW$Pu7Fm{$i3(VuR2Hua%xhq6M4}cTuAVwwz00WZW=v zdG?7-p< zq9Eq-E#sE#N3LOMKS;1=rYcODvH_nYhLfMm$TSQ4NSD^&vphKas~Pat{kA=}n1yZJ8dJZ}8g&|@nU zSxh84XS@73LaQ&{|Dy8y#XA>##sh3!_1_%!16y9HFDEXthWZ%s^)Nw`DWadgPwb*D znD>`Vp)`aZ2i<9D?@gEVIF$z1&PVZuH|{di!Vy18mjmW^-?f{(6c`N)j?z|F|4uQd z{f08~sbpOqHXJtilo7(ZX9n0N(@Vp}aZF-yao z*X-<0Z;_mSL{s!~@=VeQLaq1MVDH{-c&u)Vr%!mUO|MxEi*tSD^bL1)i@AY$Mns>& zXuO-_)aOD|OUrC(^#ta7fO2cSbB6aAL>?oAyL$AC^VExrbXN9fCIg6mv-?%!Ne!yg zH!efmwW#`u8jV{&8q(%0@0X^K#HGG}e<*Mw>nA^VeEr@d9@DSTEbHjfG33c=LyWW* zExhH?Fa`lNK)C)tES-a2<^S{cv$eIkPPXlnwYkl;wb`!C_J)(O*{;pDjgxI|w(q{5 z-~BJVA2Y9cU)MZm#`EmTGz-`7K1@I7V-nPEqw}Bsse_~Dr)f)yZn7Ir=i>dh9ZfCW z&i#`gxaZmnxI6a|`LrfPmEJE;>tF5`j~_GPIeBeVo!_{Bcy8CZ>>3M8H36TnTz2z? zziH|}qu6e|BQ#VADczl!mo)lDmozAJ3{u~nKH4sG=^tDX#Oes52fF_V)FgOGnf}W* zW}O*@~lVi>gcRV3`QWgKb7w*kBn>kba@AF`Wvg8z^qE{wvI?*~t zDMHsTOm=*X{j4o+wNUJ~WeL4RwME+im~cYAHK`p`J|VQfY*e0#7|y9+2U)3lgF=85X*(=J4&Dk~|iC{qf4&Ry`CZv(V^%8g$IUSJ$QO z{qk-Lm(+)UCI?9MUEqnB;FW)uGeTjl(U$o3IFZqdm|yx$>ir}AD}zps@J*nGG`$12 zJiu1~+eFNaP|-X*&-@F^)qSAKe;MLcqc6M)%;NdXkht6MGv6E^Z>sw`BVr|)AUCFm=+dT8-Z{L0gg`SJf=@n7Ou@~Y@(yh1vuygHb-F%?-^;81 zVdJI#BZ#Ne%RvIV{lL9&A|Y{HN4{s7kEglLRO&lGMUc3;b<}rrn#PJJP2=zOSU0NH zt0F76ZHm@T;Lc^Uoc-qJK89vWE27uo3Y^bg3j-#o+d8D$uHm@QoO#59gm>$8v+X5y z!{@K`(E2!>zTa!a=WxpRs;=8~`)R*NO}~iu+o=zqXV6ETpXjECv>*7s{^<7kw&7y4 zxa)4JOX|Xb@UP?RYc$jI@>GY2b@?Ol;HURy6rtU_sO&_eSUQDV&0O6T*IvDv*={|cmd~*;8d;6C30oTH<(-h1qEzwd6uN~{UrnhKH;dIJ()i& z?RY|I(5P0f>>N2wZ^Yy_wJsNXTR~dPp`+9^sg)hOsfp7M<4Y2)hK&r5FUv6Hz3ZTp zN(*tU_{JcIUG9wD5Un0|9+7N%809p<+RHazI7w36u^~`;j?FBKM^9W;cBxrmJtzl9 zfd!eIWlgd~no`pL+p`GEU0U%1Mn12t|F(o6D0a#yiw>#-Y1T^{;Vf&3v;S#bpS+5_ zSC-9E_lLkiAZmY@%-;JRBe&6=&B2~0ra2rxoqZhAT_PS2FALZBC7#nu;l6}Jn$tgK z(B@6hG;YhgIFDgP^a;IE0)`Jm4NPWn7;3>4X1p0+@hLS^xE#IR^e8pckYmL#4@EZz zk6JC-Ie;s7?#vZOB*i|kx2Wv$w z8G2CUt&L#>QN}_uJ0HQe>jJwpusQv_VxL*Y=|rp!-$RwA}omT zW`AfQLviZ(#37X^+^)3Kdv*B4+*Hj`@f>`$K?oX?XH!nPqKOB?UYB?LbHaxFM(WHT zWjOh)rDl#B=isYztP{Y$k&Eet^R)sBAYKhzh3hk?ySGe-mr^*Idr0_ZCtgc$#}-C0 zLIQG4{V_2K_&q4>b`RcucBbRyA4%5wbI>K$hQTa&HT-$doLHiL*>2b(B;P&&7;YA)aCBCX!~}#u4id`@P*GI^BI6B za)Z%-5%6)}w2|+3y}F6rxo$NI$Cg$0pBJ5qrZvGf^5d7j?Gr=PRXw9G2q5h0Ph)mP zcz4~;=nJ*&zi1MsX3kfY_J_e%XSwy;DNj~m<)N_HYPIhlZsB{6mB&YP@QSps^jV6q z;+ZZBhV75y-34mm`IWgs?v!5VMgK)Y=nA$=dSjcxMt8};hA7){q!DbQu{y5EYe|#Z z`rKm$@eJ7uqB66z5J^Zm4w?vSR!r4HRY@!zin~@GYjZTlby`rARpxCr}VNtwh)? zMf}7U{_nbNO ztUC<n;ts@W{E8?$ZRWm^d-6O*liLCROgW;GE z1hGDxORB{I4hZ^URXK`;(*eo7d}^EtlW;Yq^AiV&TZ!~SCE?IL8|ff}@@XukcdEmorsB&6XovI#B-wGM!!ElM!3vFgxfuH*gF`G4BKw^>V7HJJlqYr&YIr|Chy3_A?V1eo zB+(Od4=dN_4*i1)Ev8(8 zAU%-F$ut|XfC-z^t2;e`crjrSwzURzpxvWouBb#6s-lZ>uDhF|(WOatb>Y;_!k>n_ zElh3I>if-#>B+)VM$EvbXqXi`-`RT%P?DjV{}($Jlo_U9K->abjU!R*RLtin(#QE{ z1zK30ySPNs=C;t}onYyRjwcDMh?*`IBZ8F}CvmUENpH|iiQr~-Y%3PVb^a!G z*wqB@ntqqmJ}+ls|MhJDZ7cVj#{AdV`PlQj{C<1rdreWh-PXC1II(&^`Y+3AAo21% z=*RPb!3*`#ex3lqT?w!sTgR30$bl0)Ad#vTAJf zNNbb|I^e&vDsT6;R&kpy$a*beoC1lV9(Vxc3Lfqg+3{sQ+E-%nv%8Ni(6kE58=(>` z6d$}r$|C*-4)!^qbs;&kP_mn4oCf{#-0FjT(7!E8=vzzi-rbOOe2o0?aYvFrcbo@L zN73;G^XLN1d+n!pe47rMUZCTNTp&R-X@?^&f&f#=j6@)|naw#lSqw!Eo|_2pH&GnO zKQgkvuH-rc(VILAH?pA1FkMA4JNhRjLn(?e+?c5d^@K8YI(GX%m3@Id_sl!C&-(YbGyLsP#K7>Mwn_7* zAT#8_r#EAA;|wH=PQZKv=Qy4@`@L3grN#z@ihnJD$KVN;OF-2waOO(|yoyA^XDAYH zrQ!;OgcS$yuyEJKhu!Q=?F>p2i)7k-kzyl`ZOk<4_{=W z_drhEx{oH$rfA_NRLYW?yLGN9=$177S)pmaa?wW_F zZDefQGE;=zcJvgQdiI6$DfLpeVm(UFwO3`?yKInwhs|xiIKE-?u_&2vRh+cW32YSR zH|ZDKT_Da2dxmNFoz%Ik*-ht+4fU=Q6L`Pb=2dq{){m77u@OZFUFndTTpvlo;-HlV z5bYe$`97Te1i^*9w0cC-{MhF)Nv{A^CuyzjL%=d-A<&NMO~#faMWFQx25%PIa+fZ2 zN<<4}=Xy$Klj|8p-1v_XmfwQ2ePe)kv#uVftoov_z0tPMU<2>8_u1@6i9Ejx8vXov zjiC2|iw}R`doNe3kE{4C&!WargMj8yG4PJ@?UQdN0GHnuf;NjzSFLLS-PZ9}F8>TZ znFW#Ru9xt8G=bZnhyK9(wRsch^cI$ll_HX-BaU11&PSxTr|kFCL{RjKMji7a^@Z?C zvBCRjdd35*ra`;!6T{}4$VrI8x>AR`!t7@*)_!@7<{_D8d0QZy)p)(X?OUf<5&Aa^ z^4?3f!4UY}`f2*xDcdVod&#`Hbs9m5+p!t8!@zo|BwuT5$-@g%LhGS@o&9zfz>ZHr z^Lfdh>43-!hld$>@*kg!rPHP+Eyg6bTA(|FOuqcDXeylALutAaXa8reohJJfbaW~s%(xi5_c)}+c z!_jX>Nn#)S4yQzt%Z|S^St0*JLao6^3r#le>ntwLL_u0|{A4R&sDk#Bca_dADmIP& z$rGx=+<&T#Mwyq44V2#dGRs61QpSc?$cGv;>~djJ47tpq+K4IRmYG-ej}H6(>s~VS zC~ZzzhRP7w@(WW+68ltbN-9*Y@Te!;F8xTP4~?THZFZ0}fG2AnV%>5`+A|*KAv^ex zqHqZQHwJ^hgWQxK3V|mn5f#5JD`K`Zn=du(bMWqnN(fRb76-xP`ID%m2)SihftYBB zZ-k9Xs;4vda%$`cBag+v;^=`G)m@Vf0_+Y*PtW8@k4P$FHiEXMyzvnF;d$BP;~4T` zF43nURX=>!frvoLb(B}8ab0>%@99k&Lt52>a`Vwly`*@|^-|1J{&}ZHj!N7n?nn~}J^rmVLQi-fk{sQ=RYhfU zH)jq_DKrbC=?i!blP@k>t%h9ouYm-Y79hOeXk%}1xHW)2E^%>hq() zAZGbhdAIg^XgV4*@R8=`u2J#ya83eV^>Qs|NQOrnRG|Mt=dbm6_Irfy zlJmP9d@=ec0b>z<4EbH!@81nwOE8@p<=-cnGtYp0Z}C0oanqaMy=t5uui^F6y>+(K zhq`Vm-Hx+AHXe?*5S)83-XgM_Gns$DNSfj|DF_|VR)!E63+SwnBP@6qxOBc}00o=gwyh-$qhsHAG z?>UCPe4|j5>=-XTSG%e@ZCP`P*O!lchMWKXt-a4gl-%K^j}A@FoS(_t#t(1XcxWUp zDG(>q%Qm`!0>;486~6}%q~obFx-9zwCTjCciT#pRSgTZ*R~#-^r7%6neOKM6tt zG;&XTJ6~YJ+bIeiA>-|S=`D_c=2a;9L-^fwzL?gAYZK9!hVN_4i;iY}f0C1j6aYkC z?s86siSJ6~c~d&4`o>g2OeBnC?)Ei(1xHP^+KsLZGNKDn`2^y$+l<%dVHN?1bF_)o zegTv>h>^~|Du(@zt23RP3Uc;*hX6(FuES{|GAc!!<=Mo&Go(ii1)9{2c zBxOQneHX7!il7+DW7Dq>?iHVsmDCg0mpBn)|1w4PZA)QL3d5*RV`ZS7C25xjYrV4| zLZoMQWNROW0T}TUWBSEAWSi{7gf#rrrW7p-;%@_$ zxV0-yj1ksfuPK~xJss`t4H~9cq5p~yS^7KAP!dbhPIx!HA3AKnnR8Mi>`RE&g&fuv z`}nqe|0h(unlDRIcLE0r!gS~1D7j0ntsi#iT_xo|(Bfm?@5=Of^OJbb-SqoxX7S@J zCPQ$mUe%wbbls!9HFQ1besYDUW4Gy>?wZ`@#M2+RU7sGwnBT6ZX&qRI)u$n!zF%4A-8L$d;wFe{Z7~n zS3;H%14o`q61$-A*hY>0j6RJFWXi0Qw zup%SYdR)R3899#NLB7q>|3p!ZI}0fbdvQ#yM4JE^Unl`^P<_@)4Tva)bQFBjQl91A z%H>xeP8ne@z2y*7yw%p?vEYcG&`3TFLTW@L6tg)nBdllEjDN-1*$(f;rcFq)-*W(t zmTftE+4-9HYXPYuU#_SGZAeYBdAH^EB{7K?S&}1MipW**rPNbL9909g%+#OQag^UP zPX6`>$NJ)(BMX~RsBZG5DmcPy8T0qu6m+RTC&bkW!&$Ms6@Fl+tCfE;usyroJ(yq` z=KVV52=HFcp710x{?@kT_C&&KgIHrx%CVZc0-BkOwZzE zgKsF93d>cdCS{_;PSQlLYjVclD^xNNXv9V&JaHU0B}oF6-uzUtnexlA=h2_pm9^W*{HP%ON zd$U6X)g`c4t zEFz*vAh$uezn~`fs_H$?s>Np$djaAnJYgsN(2p8O-K8U@1)c?D*H%YMrVeWSrwbuq zj(x|Qax~l)-MVI0%lLlv?@X2d{c9$7r|mzE2+Tb_vy^tn3H*#s$suJKRRtnP9&d%2 z_>TpM>68MMsg3vgvH8uR+}lJ{h0sjvG7zh|&Rr-gc>c_3{U|*6WC~eq!6);dz)1VV zX(Urwb)8M2f@=kvi4nM*p6Unu(E;O43ri#wlQ72(9dH^E-DNmEnLX6_h%^APQanF@&PqBK_{vmnpZXEWQcuBthYnUSLHIOFzTA)On@U~((F~x`DBnyU~I&9YLo~h)nCJWcxBeA2eBRn zDaVh2lVDL*yHNv(vACTlBJswCIxsZSnW5+%LXJyU%pM>1pI>7{$;d6uaTkx=}sawPBjBvVExEH$^$OaWkL z{D_)Ktl(G-n<=#FIyIZ4+%XGNaa0{BXD9+tCc+ID7p4K(h;E*Z6c%-dR?~Rbo$Fb7Pioxsm+sk_#R8KA|pF`l?`@Uw$3*jbp ztC#$o5-;V zD2`Jhg70uk|0w1jCLWP6f5Ed#riSlhm)u13DYe0WIIdB|4BlCHMzdVj30 zIUb9ssD5IhHx3TC2Ym!01v;c&)h9=Oa5#d&Wl&6TGsd{s-4`yFC95mVWWu;M00|rVoTg= zdcA86i}<*UEGzpCs}vGV)(r=rg|nF7XFXwvT$NdM`3)H#U1x(1CGqE+=dwy6nUl3f zdt>;Ra7sBsHW}N`xjS)2>F&V1dynM;*ukq~ZHfi9MYl`xkG`%N{Ib3wjVjxaQ>H^c z+7ru_%e%DxpbE|oe|GIJyGKz$N9pJ+tOTJTr4);jm}||Jm!k4^uz!MynOQ(PUyOKm z;T;*=Ja#;%g3|Cr3$1KYPQb*{Mh;7E?64z9-gVzMHFgsH8$P-_FWpW?k|VyJ#@x5; zc;UI;K^t|S(LG6R^$q&*6W)l+drvJ`Ixn<+me14@t^v^>>b$euo6a#E^j!fdp=%gr zk&kzCEb6MNWqW!i$VlYh%Z$?yw9s6m(OtxT0@%q)<$cK^$b}i?Z8trKPgAc~`mt;c z*)eBjMsdlok_)lpX1{IyTF+W6wD8lX{q?#eLZX!Jh8DgNB0XQtxKDooo;!R;Qm2^# znLK5%cbC2IyH9f1OV|gw@%!;+Hct`P$6v|B1{vSsBzg{w4tn<)r6Jw)9=uWHYnrjq`f2xU4KXU%pWaVm_YL4VZf?YTB zD~*_ZpLRw6m8rFYGfn-X$`pfwBto8&#v0L}Bz1kAic5mZf#MJ9YEc3)S8p<#Zfi7s z`z^)LcxFs**g&1aVFax+jz^s!IvVr-(|*I?sDJ_~@sM#q{wcSRk+l;mB(pKaZ^xf2 z1hPN|`1TK`d<>6Tv=6Q__25NB9&;uZs?^eId40tKF5_F=+vpNk?4C( z^Ia4JNoW-7L~8WaW3SEB4lu!F_e$Cy)+DG8#{UaukGydlWXYJX4Z3+8P?G7cZ>Ty# z7B0pM=*&W?wVNL;o>DaXLuBshMMUx9j?TFTJNZ`((gwY>pk>4|TjW z#XYVnj{=48HoZv_4EpXOZ+acP_AFfNolOqAz~{fMn7hx-I#XvL(Z6IcUALu+7t`+> z%y%*95zO|=AJ0@L4e5EG=VrdV{7iuZ-G`$Iz?v7ur3ZHF>E(FLO4yD0YxaK*Y>_y= zM67nT68J`P(@nw~t&DDY*iQ51ZLD8RZ@H5o{zpK3TId9CfV&40)sGPY>c`mb6dLib z6ft<9V-+-*G@I@nJN%L{!C_y5Trc_HyE#C1If)Q?>jUIW(1U9bPFH0|uQft@bbgJP zPs{`V5AI@3>6S&@pcDKNt|*m~2$9EnvsA#$hPL>HdUREU9v1!t@(g>G>zgO86Aft* zBz+hu0`#k|9^I9DERP)Q4h-2Mq!F>1DA*|LJ)5c^Gh|m!hy(|$Y}z7#^IfSWOu*?1Z`T&9+l65w3BdLC#){B`{|nFb{`__q37NO zX^XgRHKK8AKArH}w(kr%C8nBFEvN3gllSvcaNB_|z_ofjepg(?>uC_Od>R^#%tlx8 z+c!%16$4`W9AQOtbl1l*CAgLV-m|Nn@H;~FLvTucfBofq_?zm&1CZK#!|iu#)h_#y zR9Xafcr(#M7V?9;bk7;IE0LOIP@~B6hO^pA_?>%c4l>-xBwpP#m^5i1e4n2LES>v} z#aYHCiXT@o<`V5IfJBz2`p_SBKH+G|H4|1!p^OH~XYC?;a*(K}BmWJn?63pEV<&nP zV?TcAT6V2hlHBvz+w;wc?2Znc7l3)F!aO)|RI^R68#lSXMLaIokUyULC*DW_>>f{T zQR^P?oinQ7kXWFab>CN9{2(JweUe7Ij`hA8%MYb6LY|3o?~bdAurQ=O)JSiO{fif% z>*(4Yh`y5VF>Mz^$k$z@;DgQdb>KOR#>9BrV)?>ee?74&*j$!`0>AY7E>;&JI8DIFv^Wj zkb8tO{4m#%O(9FNXMwu8C_E9u7o``D={#|y$R=zN!9C=PxjF%Wxo!SM1ayIQCP=!n z8n>C4vUz2HwPJXKIkSL`*0ikd%I{e#9tI-$ei&=}_hOcT-XoLhVf7#PD=T_Dqxd3f zl65^I1TuKmqM1axuli*YS<&k7=yqgPwde;m1A`mEC)KN(ad_^*6_ahh;q&J(45G zpeWs>CCBPrQm_EE5WUZK?z3|$Mr{uxvr|#*^wK9fdL>Dboc1UtFjT5JBp zO2WiR<*G9-yjGi^gPB7ui-J;~gv=!I0P-piieKGD-|=7w z3D1rwRcBeBy&2JkV6Jbq_ynP5c$Gnsap!2?)r!Es>7Sp&rFcpa4rwD-re`}StX^Np zCRF@}k#Gs?-NlN$3cAEs1r}&5L@TlN>C97lz7V>c_MG-Btuygi?j#=&#s=ZA!OIX8T5Ar9-C(B~3iH zJpV*bbtSBchQRfAaIO#cM@KWp{2Qyqkf-@66)g|e!9^6uk2gC zuWfoFH**~H!^cK^H#5NBb*AO+{l$DEQ^-cKK>T$=!uM~@8r*Qk(MA{vkAt)$FpQ5gk(2&r~J7`4d&H)l?Oxv8tb#P3YXJ$+_)K}g+!tzCasrHTO!hk_8=}|7? ziX01Dozb9bXb)6gMAOQ5R^;Q6bTPy=gpkJY`JFEY+Q z0t!Tj!eKE<$wt0fMIs8=5bZolmZexq^_ZNrB)i(S2lN;+g>wP72WHAt{6 zN^F=jV7JoA^I%>roIsgE)Iw5&uq*gv`{Sh*REnVw(*IJ*He{TO=}2X2A)>=}nR7}A za~q?japZ^_E$4j*|EXpJV>wz@mUgW0w%6(_QfX5L=(LVs$xTAsO8qzVgKk05$91YC?UoEkXusWx^z^vIlib?Kz>N*UOMtgISQ()EaqfZDo4> zHR1Ohv5%};7HKhR5gQ_B5V271c^`>Z@Bgp9D9~L78$ORe%>It>!X3CH31AKLtxsM! z#_bfJ>*>HAhah5cTX_6%aLG}c+~F~M0G#M@|GjE;jrc6b(O1cKb32uU3`|c>Nqc?I zBAr_Uxmed%Iy>%eAT)qr&PI=DYe2Q@A-$FY<(^-2{hB%au z`xia-IGX8%jr8K9`G_sk!RtXLfrEjD2(aKq$T(8ropD@KPbTRb&6UF|*@TOOo)tiF z@#qZhScyb5rex)oGm^#~xE)wUUY(x%O&{iV5R8(_+b0S4z&NGr+s=<@0*v%G9_Py_ zVnfqLwJ≀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 uo|2bcnuIl)C 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 z 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 &Q;Cw5#{KY^Sr<9wQtq_DZzl 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

    Yk0O?Og^?;wwH_OUjeWzx7KU&mJi#9F$PI-eOd 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

    Z;{Muje>c*Y&+v_*VJ6qa^ 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

    b^zmhX$w>&@Rz7K>w!x zf+l66aoblUneX!mqgNyM<%S=5Vod>I;02c6GJv=^W*%DJfCsdk>&KdDfT)Ar=_(>QhZA(|)v1 zJ!)E&4|&XGq9i@Tj_q)tv zM7#3~^;MxnGG9`}-M;cS7d6_VDl+kYdKKMCeqO2T=QVxpQ}fm9plSy`!>qGyyKQD* zN|saS9#zhw+7dQ9;wi_iTGL8S7YL_Ff;GCd25U6p$xfX$BQ_y)Ct#uPklKIVHzg{u zpLnuUy<9p8B}~BL=qDCWx9_Vi$Ohj<{kp}InvO^|BToYBYxcDIx~K!quY{hV`%rwf zXjWMP`p4&Y`G)Lu2?pXDvfsF*c~xt-ii-=Y<$IUTYx+mWs`Sq8M)}$8%jysGnW}eb zZ?pX3_LZ`}H?$3}g8m-mU38lcHV^aq-VWnk_ko^urQ5T2f$ z^EJOh>xO>LL#)TQQ0tt%0$m~Z1N!(i@`F%y3Rsrt^qY-}^};iu<$3F)*@ zknhfC8P{wIk-1(GPkq`T(p#O8g?`NwWv5P?$I4cd1$tW@axOc2UOYp;(`)q#&<2%P zn)%S_=Jw7nS-WN;&b-`xX5dHHRh9=I`O|KVSM2sWN^AD~mNCMbUj4zh^eaNgQzm3T z&OY5C{}j=2rEqi{iSk%$a@n;$VetKNZD=zE$A2!=vdGZxKL}o+6?pwHKWgW`0}H2K zP!(95<%w5bN6e4Ic`}xTSiXVFkL9`FU?5ZZ*yG3U+>_yc%u}c9eTx^))zAyHEY8X< zKRoxs?9qD9gEyja4}|+R$8|2?^_+gyvFx^c7}PPtS@lhMulo?hKB)LtROumYlH#U9 zW2=Ap2~&X;Ext{%C3Zs!yl(fNuJP_jaBH)^n)n8xz-xK$==i!Toi*vNNgoiu1C(}K zdA*1$T)!U+xKj24?(MqZ%Xe9M`j#hZ`93SJXyvKXyWDS<4es44XbZJQ@KBR!)A)eg zXosH>`79U1aSt?})^Sd9^FrQ7W?_rPSr)JFY?QrRoCRJKlRRH@Jc9Cgp{$FyMOdM| zz8DanLi%lCR>-lvje%JYfx3SsG(8>h}?KpgytSxOZo*?A^Lo_HOVr zsBm5V0G@BH-c>vEdS2S2o#UcixCg!hA3O;Mc0w?oSeo)9$t6r#8 zn&yIaERH(iSDpj1o!v)5hX2XC-IY&lZU2Dl*a2DJq>Np@kFJnIj`5w>8S|QFKS|3t zD)>`=0&;w(4oezaeGf*2AJm_|k_-F$7W;+P$Iw?8^Q+p13bA8fWz+TPolQbEk!PL} z?Gt>JX_l}1seY4|1&)4l%}&oy|0co_v}qlF20bY4QOJ$nLz}iUI$3tg9`1=PZl-Z$O;X=#EFU>)>+wK34Z$6~ERfdSI{H_FL&vCqBVBw|+q zWw_5MFZpv}7JIosYx|TJI_Tn$2TE)N@EUp6TsBsgp3=q5bLUI>z{OHtda9HUK3U3( z7j)61iyxlA<@G?v@KrWk=WH(^ACh-lDo&Vfz9+xile9uE(6-}KpxPf)FE_dc z!4rY%t&7?Q)W3$ve1jz7-d7P07~0tTU=p7V*@=DBZvMb)Y_2zw&Cw*c^s5js!pRnew<*FUpIYqjXwL0s+wh4`v6cNd3+rIyd`%$Fz`3a3G z%VEN@D6{reiFBCPn^quvN*^6oxLx5XZE>m0@k`G13ON@}YZ_0;pT3Mj7%0OTR1c&H z2Kl@$vX%}XDT}&DkwkE>v&mY7e02FCJdiLtgHo)}ixZSyl7=lKufMkQ}fpt1IJ{$r8W)87fX#`axM z`mi8Uc`wlFJmkE{oNFK!1Ggz(dUf%&>N~&WUi@*K5SyJ{mnS2Mtka|vm+dmB9e>nx zS7qx@<8B?JDzOymS0CG!jU7z3`-liyPzn2phr;r992qgG^qWu@HJJn8jazH@v1eZl8;ZmABM zmrTo>;B&jT%dhQ>7imAdaJ+nCL368#?!~#4@&{R@4WIem@0WJ(%Ele{(IggGU*BCT zpWeRZ*C9iEtM@yW&K90e9+uL%$Gup7VEJM>Ghe@P3-P4(Pj6kS-(b%2-F}tbhXaV$ zW?!H6ed7bE_Wx>En}=Z*AvVxa$o$gB_5hcWq~mmcS#82iF3l15*7?C7KgkgJ7ycY) z*4!UL5AvfY;>{<)KOR+$?H}P7p2G`XlqHTlUkU0(-ADsEb?vc0%S|p8Y11c{3AC{& z0F%=s1iRnH0iyG;Tv0vY?Mi(4d^ zB2wLwy^IsZrwC^e(x#z0wmFeN>@ z*ZQPiUT}4Km6=D+_a+9t%vZ}A^auH%XE`$bn5K2={DJ(cz`YS{$2q0d$Mt&l<>}9RLcWq09{IZT{OwdiAwyjjmJNZBcrN1J z1JdUezbxMJeby^Hse7}OcWwy0x>a!&L0ROae8xv#B=mLY;vBmU11XDR+T)SOSd}?i z_*7yWuh0|t{;VP1i?kB5NXrw7_>`}b<>^@#U%eP6J%6WG$VD>Rh_tq7CL6hE##oOZ zES~lEsX>3w+T*wQJO^f-^gpUA?eJcxjXRG(s6DE#2|vTve!t;A^`iaP?-#zUx_9kX z*?ad|*?s3q*?a49*?aqPDQ{g-pU|A2SNQTRRodU*|Bd!(4`B(uU$0RAo_8_FJET6n zs{VXLW0w~@0WytO?HjMupFBePYyT41??Nt|s0-z&$kx9U)cry{We7WRIiX`j#+bkP z{<5F;#dm=>5ipjrpxi$N%sm+Yh*W7D6Zql2Ex13;f|QJiyMGC8GlBk}{zDNsoYo`h z0P#cVAbanL9?h1n)aevzEZ=k?6teRtPndiXtP%2FFKwkhL9j!f8hvDPg9B|6+CQU# zj<{tJTGq+w5KSi7Mu*(l4wZpU&<`$Cc!x#Ud;*k1zAmrRC*@mSO$zW98 z-;gP@yd$Cs(*b#=`FbMhp!8nsecsvcDf`1L+GksFWUa0Gwp8*|W;u|oA>!!u@^o0; zwE5d^h&g2lZKJb|tvvBO2s!Z5mne?>_7h%EvIl7vWEs5q_&u)x;8!>Pg_B?zCwl4l zmq|bw+evx`GR=!z6ZjV?gv7<$hMdX%p6%J!nRugYt7x2TuZWr~OQbBq0||vh1pRp9 zc!as{AlL@^p8IFIpUKC`WRxK&_vNk`!_&4;o-A|ET__9kbK#|@ z$~^wQAb+2hzvo%7)r5j4bn(;v$%fkxsEpS61>adnnc$Td!9Tzda>14T>0=4d{`6f< zj(EbBr)m}M2wN=HZf!|T7qroLeRC$T+sC^;o-##(N1U?#>a_agORia3)6iU4; z^=o&eF#XFPm*@H-sPF}O$~rl`FUs@$)I)i=Nnw2**Id}ww3=^poG0{;-CQ)A`ui^n zx$X7GjSAP1x_0&T&5q#NC;d$hw?m-b5FvEJxGiTP+CFa_Rrzousp`Z&YKWUMA#V$g z#5L(|3$#vGpKs>?*#+ooY#*LhNL~0S!}7{kebN=$AGJgCPjbP>4bXoJA%$)`;Rn|8tAWx}N8Sts0E><|W@L zyXzW5))~u{PyaOxU@v(Se6TY~iP@Q|G5znBd0l8N9bPR9OG}ba_qYLP+e5Zm&d^fr zxQhVl+YxF%0?7nILz_q=uz3~Iz@Oy1N^H|fHA}mX(8Z0~WP=WWK0i~y100-1sgrpP z1PZaKi@AC&$wuX{KbgC*?-v)^YeMmHM9x!vMTb`=v#`3OIPik2{f@ko{HkTr(=5LSI799?vrlU=O{jepwYnor+BeXKNP>%7s+om5#nk9P_l0M%;JtF&unDg!< zmG8b8fbdcB`|^>+z5LcL3$(nl*RR)o0KL7tUVeP@_43cRuar-3-z@*r*5&fg?!QyN z)#^Ls2h*~4!s)p~ZeoaK-MhRxxcBc7iG|{y-MUo%#>UI<3;xdiFZ-Lk52H7C*UIl~ z-|}~lbN}*P-H$FFFX!f#Jv~xo%5m-Q7v_(Yk1ZV6)Tv6pyu(85O)u8goNVdKyO#aj z_PgbVLWutI!G&YxgY!qrs`u@lrhIedyxQ*%ES@bV=9mC#m{;DbyBp;fw=b7lQ^5Vl7XTlyL>kc+d{;auD4_xbC!a+P^bYoIubbPiSRHQ87V^R#` zL9YXG0D>e~;_X;g86K}BVj7oh(=6F6dQ`oC3CJga;FF;* zYxfwWbFNxiE^{mDJS!~JawAJJ9U8vh>4ilA-ys)#a^cYnm4VGb#=UqO`5c$+T)6dO zt*#+?wKCss<(0=Q+VV6l3!yAF-N$c*E_CwSy3ldi`=@q}LZRD=b=yhrR; z=t>@ArN>0y&y9F4c%kD3TIuHk?R9*UpS;SLMP$+e?T`zx`MP5BLOwKvJ^K^zePkd$ z;W2yy#wGoa_8S-tG>L-<10D6_&cn#2A44C?;vA;`+R)bCFRC~94tQPfb?x)Zyhi(a zDevlf;9VB#d74)3+%Jgp0|Ayz)7St2|MW>jK~&l`+s^G5ZI*4s*yg8aHAo#+e`bDq zNPU_`PA_x{`LK@H?idh7T2EWq8I@%SjI-?ECEV)IIyE!{i0pCgrY=(D$p}_dL%T#D#qoc?daQW}YBz zLkH@nbuBO{JSn0C#FePknaWx;2@eNY-iXoRfs4?(j#)mI!E z$vQYKa3HB&589dR=SLxzp-tZov?Fcmc1>A_sh{aa4j%No26Z|neZD9c^xr0|Eu+Zx z#P@xrFPr_``{n%(x_J7Qc_cPS^WdZrhLdkD%=-HP0e*SI2i{5Nr0mxr#K6@CE9?j! zj1_O_b%5fdFwp!Z?CU5(;HSs*AlXQOHHZLZ8(WAWWNm$unG55H@6R~_dmS3tKmL3-; zyecR!eprfnTlSHw(Cge5;pN z4&e{_zuG4%;^GYkEdvP#SrQGZ?>p&)TLn*PlESo(4o^|pDiww`FQe)g<1btL}dV8 zbJvD95OMS5cbQ4b6I^Dnq$)<(QM$uGH43Gzan`3seA0Qg-9*>93EoejI!*3Sjt8HCvhk(z*VaE@{-)wr_Eg`Qd$JPCmnY@x#raiDoiL^; z^6pl-s&;y8Qa#?@+bI8J``z-_H^2D4;K%O2UVeS&;fu6)_O{EbyLY_Un)UTJWap2R zk1w3`6p8-#tm^r-izmtn?Hg)~=4W?qmEZ7FxWvX-)7A!O_lyg-ZZ9SS~sSH}Lbzl1f~h_NJhs|!dz(}Y;)nfIV9 zaIKX$0Lh~Li~sp!mwo71n2T{$&WXQ*tz=iq}udM+S(9@Y2(%(?0UsgQXhzrp+^;Dtfk2%sCXsxNoD zy!{+;3NP@6ox1R;(DS_N>#XwXe5uMT55Ma?vV+rVNId6^S=TntG}5MQHQgSAuKfu8 zv7Tg&A5i_Sc4ws#`WnbKu_4etnI60^-)XaiMBYbE12u15cnx0mDwG*n_;39vtA7Qy z^EDrchhL5>kKk)nhsh7=zFxo%^DX2~qs-c`(nbZ{ntF&2)H$`lA(5e>c@@VZV@MpE z^;PQPeZ8J?<*^=+!1rTpARwKdXhesRMm~N}&KtwHH^I}ZJUM$-<1J6m^0uy1lJf>H z?p3gO>em^oef?u{$_J9i*kRiv9{}m8E3_Z4D{KqB6Ie&+^MQQ}wC^|dwx{Jhth~q3 zdk}sfP;*xsBl(nTrze=#_=iR6M}Q8aF61%B3zmVN_hL}+Ua(aL?yu(JZ9~cwwuM^p zehL?e=c!W`Liv^}uT;LN>q-_u+taGjqa3DM4a5V!1*dvgP8i@89c8ny*A`O+WL|s= zU_0;odQnTTzXEx`$O5u_^pn2m;~)9MM&3ux1+$DNTrS~MCNOp}9(ueY zR2|qyc~Ql|D)Hk{pFupw{A1DM>Ib=4Z3q+8hx*a}v>gvvaj!n_-?JE=-|yvB(zLOm zIQzkiwZU_5-}m>mk7#GwjxwmO(=mbe#)kJx?6-d35_&&L z-9TR4kb@n)01J_6Vg6qWnXIjFZc%P5y-yP!*&3sRiIc? zjunqhpBSKBzqO!F|;EtRh^-w5`~`>Dz$_ z-D!RgOfukCE^3g!r-A*h2Ke>_Ed#jH@|QO`fO%l;(Umje1NO5+JCO$P17yDRFM0bN z_1AwL2x*%H)bl}YzdO@x^jT~|8{Z_zu|oTZ6BVyCVG_oU!WaDI*Il%oPjU)rOX@Z~ z-tD_!$~0|yAS7rMvJ_fRhNgKu=*p&j7wAXHLn$*9as8Ahp=#A9Sf#K!U-o!vl~*RW zSMUfdc9QN_1x1((v@DwP9hEaj>%#66r~I_5k>6e6g2)#_*rpuHRM`t^FJ9f8XKY{L zBUe4`pTxiyGzw$Eb`Qwh-XUG~`87iVuS-4(&2ZHbApY}=5H4v_1Rglvi+^d1F0 z%}O6bzO`@+75*Net$c2w(Nt})@n;`ob11W#?6!t(y2FC zlzCse?Du&+{z@;#<$BX+kYQ&S!|Qj>>eJ>sRaawV3)_!#REBJ{yp$XH`ux@Y;LAS$ zsDHFekGgLjpK6}D+P)C>MD>P~7`aw`seTXbj9F-~9!VB@} zJUPEozIXAwrd7i}dV6=R{QUO2W!r;JZ}ag}X zJ$_6LbVN>Tj(B&?KjQIqhQF7kkS5A}rieVKpIIez8mf$WC~r-md|x(6oa1S|jFKE) zs6U9wFc)XLG$0qbce}^y?zqln3{o&2i*jEAD8l|cl0;wRe9z}aybEQ3W0@b;1MEqM zan*~o61CSacc}C93GizYr!JOve3Lc*CChqE1`F*0s-DpOnS^Sf2GKo^Q3W55z;y{f2T{91LZ)H1oAD zrHpciw2G`py*3fl^K%aFAt8F??a?Lm)(aU zZy?_11!}9b)52a)>A5hQFlG4FpjoybR_^2agZ>o1PpG-9jS=yjp!-2p6B8=zmX93j&p94+1oUJMoTJFYCyv0%%>Z9c8)Cv@fe zmg;anp*SJ3EpDiJQ4r}y$i%iVF_U_QDU!tZW`UaCgDb3&uo`$ zcQ2w73jTg?Lh;-O^il5XvtZj6Z3W-I7C3KU8={`+dxO%ZvZS25a9q%@-3PE8_Ot)w zagyr_x&N~dbmycNf_5AdO2EF*^emSegt~nI)uS182OfQ z`y@1S;bR)5_mpzNgYbTk>>TLBe&WMK^`w=dPk_N2id)tpg2f?BFq!N!>|J$g$}Bq+fg>A$(A1g@7&<09gK3Et_>X^J4$wr$)u^q<3P(i3Yxz8 zfTB&_^QmuHFP}jFEuX{GP5uCkbbI~aIao&NLbd~;{%aWgd!bqRQbq`RA821(sv}vJ0dvQXt9(>3Fl)e)}jt7!5-C(1TyOTI35{{G2Z3`E#YbaK6mFc&^O7aJI}nf2NdYbwTu$ z`o0%!)%W>DD~rH9$?FRvLCsr{W3%{#{fl(z=OQf&%YI_l-?UW%zn1mWyy96v<|$t< zFbjmd;u)X0AOoa(F;{k5y$M5>b@%y1q0|kTa$ia4-y1@?YK$m_nV^f}jHf8$`zYm^ z*6SRkKPGpTS*nox5@G1k&m51CzG?JvF^)$#6Vg+9UFeFq;A>C-1@EYI`lLn@)I9rA zDv=)S`%78g>~g=7GF=@Ibsmuft<6OBx;^4XBx#djZENX`+F!yEKMPa62{fGfK6;K- z8pnLYC-QT1sEuuT6XyY_HxWY*8=028L-iS#A93?h&wyXS)+XsfZB5~EXvi}xM9#JT z=@7~?@IlBQF4P-qRhE8ob2RHzZ>9;p*~JaB?Xu0BL3;Dl5uOVe*PAjZ3&00vlH}R> z4pIr4*LiE{`0+A-i0{#I(>@kx)4ce)PJ)2AHuhx*U6eNTRQ?*J4?dp+p~u*Whz9ie zMSMbIr=OS*UvJRC&pFJeY5ht~c-hS-o_udaXiBI8kvTSH1x?drO4+r@lDG-1k)qv z0P%iOVz1Nb^2%6Votuko)cy4QA%CBgg*Vd!Z9f_<%I^2b=EVhmtu>4AG0>c?U|RKS z@{!l}LM-%t$I`iSVQxjIYBl^rNJnMEzV@F{9^Y;Kjz!I9f-dc@moM+Gl^b3p-mgF4 zUp#tuZ@v7&)@8pgn)*ZM=U2*ivVYafX}=H6A1`0KsCit_XLfFvmv`^_Te`CdD_h$B z>h^Un@IyQu{f&#K%G2|!g>TdHTIKIn8Tm?TTAtT0^P1#+i>nW!eLL&``n_s?mpdt( zDC0~V_j9@~oR9C)mbEpV2exas<2umYSMAaIz9@oybti5FlX?8cA9#rs@}%yL27JFg z0nHd&+9Is%aLpc1YkyN_?M}o7HK= zPbR5A$EAcHJ}-oiN>1<%U4KUxbwhaw8M1(7(us73O|B9m>~%9O-5K#cC@Xn_2qCK0 z&sLu`mX!5J35Dm`nZl0A7?%$HI^u> z3$x-il<>W4Ute?oVHC=M7iq=kF=z_oIo3fTs!)FP$;&nV3C%TlOPCjEPy6#u<}XOr zzb%Y%`>|xEZEc!7_yZwZqwoQ6$58v4;J?~5tBjOQ)B5;V;@ek}_jieKu}aF^OC<~C>Ph~9g@g2qwtZ`V_M7&fA>R8=$bLw>niMjg z?;}-;c4%*xq>|DjALkIy=O{y+%nyDE`F73`NJB^PngjXdgX#~){z|Jh1Ay0qzQ3_`!zBh7N2jDSizTW&+ zraUnks$AEGl^2s}X~ZL)6FCOGmvn+ruL;euXqL~$xvUgOM z3AG2c#WZ~s$DSe{XcW?cy2+9|jBiwdjHgUtuj~BSngJ#6>vVnmL9h+!gMH~KBka<% z!`ruzrF8?$8v#|N#Kc6&T2wcxQQlc~Uo7Cr~cwjaTc!;IpW_iauQs-)FfTIvO@V03T>MTSa#G>}o4m3y z8bBo*^`)K<=-)6kW0xft=RJxhgxNu$h>tQ_00Bnb6iEk2ZmpFaq7jy!vNbw6bi_#ZJ=;)I~?w znr=v?C(E+`3qB>!gf{vI_iORPIFfeiQX<Jos(oN7;cmkL zbVxh)>G{LuyO+cklZ9y}j-}{0l=_XTCSglhSv~Z*Sjd z-*8=3`#r1u@%0O*%EyJ57LJwE-4o8gwtc;PNqIDig=9aG^2^&-%d0z@1B*CvcwI8~ zu=~OJB9juD~Y<)5pY6?QtWJ(-9T7@uVB7V@a zt8s@M0}`%EP(CJmzY>EF&%8%R1GoUSmu^Uh+_;V0X}0 zX!{6S+f;dTnYP34480{BDb+t2$X#BCDCS``Lh(5V%Y`+!SI(tUJ^|O0ZQ+z_%LaL& z^kLCeGV+8S_#s_>kSFBLe%S5fwiEJpT^@W*uVK}%b3%WoU)RWU3Z0hVl-|dUs#9&^ zR}GupNFQ_rd>}n^GG6N(^=fSiRBn__{d=2z{%oJ2odRLYHe|lRcEe_qcRc%SNU}8w zXAx3QF?L2@JF{k>5y)P;;i zIi7&!Y0A68z3no$rt5JQYFU8wBCO=MbnVH)>(#YVuB?^0EBDIWrMqSB9o6A2)$5Jx zW$(+X6A)kC;ajIla zhh+Om`5s7_iSR*qOnO+ck4jTFXdCwtVbs2Y`v74NWNO^Jzn@4M`z8CI{*B&w+BFjx z^L(#UV`|^tZ*qm}y5hv`dPZ1YQLaFhw4CW0*3^5pC>O$<*6=7oIiF^ju? zax?u@xf9nK;a`I`BTUl|f{bVVTvvg5_9x986f-^b#a3wZpfa-pna_EZfKAHq30-Xo zyf{m{W~esx_iqy^S02JXpAq|~NA9!iKj}lGXyn#6sQscrkwL&%>mZpY9z{#1sxP=84An!4e2b%Pvum+q4$4yJlh zy`S=eJ8ux!b({01hQNJJ>5_tBaZh!KG|=o3Ctaak4zfICQy{m#R2+X43VYR;*+@T9 zH*ME4XW#(peS&{KV81#-<}m$*7izmu4@YXgkk#=+a_XuvuRbkNVc8TRuQz=L?9;Pt z>?stiL*5Z;+Bn{a`_bQ2GUR{W#Hw+HQFdzw>Zp*o5j%@^Fz_=l+Lz#gRF#??!P4Ms zU(_Bz9%(*4CB0Q zoiDhl?wjm_ubqNNugWFFo-Y7d5FjqOQ0L|~-9Lb#49@TLg?;Dl2hrHqfkF-_%imk% z1Sd7sd0Q8p>vwb^$-dErofndwIw9F~eT8Asqqkn;52iu8`p70SS**=N(Uf7vG^_l` zcV~C2{QB1Q^5)K3`^G2VW96w=zFT^d6EC{&ktq7y{7U)b%TJY$E}SSw{ms$|*}v+~ zEb!#z7k6%#-`>7e-r3!-`r-M-@@Eb`Rckpqc^vp=wSwtV;E`SQ&C zVYei0^2zP1<+CdPp+ts%5n!qevxr-JTYk;(^>`AQ#m3|Fd_(p^`6Ejg%Lf*YYKo;k zt~8#g{?(mp<+WIRZ8Wl7>C-zm%gfSRi^X5;e(Ta%*}PD`e(|Kgf154->h4|Z^UCUx znY23#k4v*`%mkYU)0SG!i^(1F3h+mHa@&VsM_y4~OsS$~GyE~2}HyEZ@@@yTkdAVJFjEU!9XQ|Md?Z$!0&~pTMH*?t=D>hU)gp zRHH5kSywv9Sj5eI6-vYX2-B_?Z>3M2=6r1=-u5I4eYM+$`QEkt5T&dN^-u?+9LK3*PBQ#GOZZeU1-=ohFZK{W`yke0dK* z*QG32*82k5PYM&&K4nKf>&Q-oye(vq59x&SBU#Gj_e550Rn&T^EgYg7d5}3wotlO% z`x^4I8xN01rc$6yhb`vv|KlHfOKDfGQyrK95pmOgV$01;3Y@xIL5M~_UYKPz7^ zdtAFc+1biA{y}&U&GPqAe0x;?-%CBo^Iq~nsxMjHQ75ojrMm-XJYXHA>Co^!K%P+L zp5J8_GOw2M<`sp)rR$|!)x40jw$P+JOoy=R<51vu&11^8dmtk{;xU#Cf-CGmrHs1QYl|}tL%OD z%fjnM0iP2-|7E4WDZO`;NA3y(>CF>637|x_CjgOqpND<=1P?NCkDRB=y)Y~A#5r(Wa-Krx`^mn4 z9t-}ihitXQXZ%z#24xVcJVU(umf$)A=>VA;@zREK-bA{B1Zhr} zeAG^Td;%Za0{MS8$mi_$udsNMRuzdGH0>m*XoI2-qfazAE+%i}^CT7vuq&K^bz*6DM+UfaO@j#w5e4vBQM;{cKuA{?)c<45HCsQy=8`+=8Tz=$H(Ap})nH2k|?XMts z?4+%}uAamy^dP{&&tRyKUx{q!B*hI@cm^f%Vc-2naDP<4VgbkfQZkS~BA}nLAmv{q zi_g9XAP2!iqkh)mfptEBvX8WVPkoaQ`7AiE(Cb=1-`b?1pa=YErQ1W(SK`4c()m$TJgouJ|ND8;OUhz|HR3%_<;*$ z{=-j~@{wms`S4Svym+pDvxZ;Xo=`zYv8{5va4W39V^=ovtqk(XH;C+`E}~UDK6{~7 zJH(5!yF2QNJ7s%&TU~QYxL?DqEp^-bWqp0UtlhgO+!ep3F1)F3q6=>A|JHrA0{|qe z-X4s{BdjLe=VYTU&JdLka>7wHL49qi;)&1+Ci-JVUF@L_17C{>9(4NdX2Ms4(zflV ze}s=oeOo;k!ybDW+z!z;-hKF{xNq77&~uyRm@U5T17ncade;0?kiXsRQC2o zc(Rtp^}3WT^iU5%2N1^p)fl@h#dn_twfU z-M>=a-POECw5%QT%;J&qLx-L#U$b~Zr`hOBj|2Hbbx+JMm2X}Ec0h^0I$eHv^(8;0 zI@8VUy9a>tDBnT-x%-#OuWw(|b@;BP0`ukD7SEI)Tz;~A!{SLzGt}7G4v8tvaFgSM zCzP13e4rdI|JKs8o&4o@s4!9uzkx5 z{7HP<7Mna#o5T_PS?PUh>pGG5kFbSL?}?nb!ofd)oO_ zdqwvSYw~z#S;Na#*}k_{=GCUhj~^?CjvTJng80ynRSzWT*=<7hO~5w1_1IH?P$S+p zonZ{8!4uY?>36XI8ow5omo!c*lH(`Ha*ZT12Bp}(CNI#ZxK88R&L+rHpH;Sk^u2f- zF=qz4~mSLh6cJnGC) z7l&xfy9Ljdd>uFS>i}VjU`0x8qTMq1Tf3CvC0IL>l91reXI0 zN}OxtgZ}yf6(+;>!i#acAuBv>S02(WJf7-l6&0t2?ppMlCces0!`fZ*_Jh1yr`RyN zyQliD##qUDz`^mPi_vvj{J>nFmj^jP(oG~@NA*;6OaV)0&xaxQV0~zvPDUnbSay8{XpL{WFk(q zg+QBsuRtLl2M>eC)vX=oVc`eUO?(uz^&QaLZ8QYi{W<%JSfjd8Kgz!yzU@a`_I^1T zcuV&JoSeltd+om5oC?$$iSMoY6~G$o*!%MsrgRuj+v$mQdJRp!E!R(jij>!8>)I`8 z3mIp<-^d&)B!6_dvszBSzIij^m8;SH&f5{+1~I^je&?Ntm#;>=dM)C$>&0OEmdb?j z79;M}m53W!>r%eE97dshN}KP~>ekgCrw8kN(UjHY9VkOnr}Aic!Vp$z;D$HK-ELpv zC)mG+eb11Iyf2A;u+UZ!9;E)LH|9dmxvF^2xuSKh?3;7(qyJ=k5!bZk)_;3UFYQn< z`>F?FA@_nHGSbXEvLCWf&nuPLC&#GIUb(UI$o!33h0BK;-a;l;_Zd+ez=WKTWz)ZHq%~?0!0APhSIy4I4Z*jME`+t-S?(cifWLt{1Jf;lRWd!4fD1o$^aM+u6&V0M2x>rRpN`}; zy?a8!FqxtTeKPx{x>Z4?>AM1GMR=q98?5f~Q}j%LABy^UFWA)OBQV3YVKB_0sPc$3 zNS$Z9=V03yYM~Wf-we#ub*t_%#&VLGNx*zXpKz8xacQrn-zX3AZ4iAbX62_Jx~06_ zrT5Tx`l2jOm@L{8$WQ~V!epOD2lo>)5ki}~m&iaqBIp1n@BFJCaW}akpaL{CEtOJ8ytEWt*=}woz3w47eCp z2ghB~7U^9d@Ku&*zobGoS)8_HPFH9HDkymyePgIZ{G{$^bajK+T^f(hiJ9nf()UT- z4DveW=bwncX#4#6h^Ge(wsVTlO(r|J7=6hb^k$E4LdW)FU)TA*ZY0^TDY{biT{U$_ zT@nNBPVDY%#qRcI>~0A+H)3yNJ@z*%Zf(Rq{tCCR@Z5x#n|h^H!K_q)9t9r;xna=T zIH*t~TUN1b{s`5ljZOcp{uu`MFldDZ-0cnt`rU*qdq1YC!~Bkl505_-TK?3J!ySgy zf9)SVH+)TpwrH?y%9M?n8lEufmziIY5x2xQ61Eke@vPajazBu~j}|QRb_t)@_IH?? zHdr>2>V}f?^@imDHaY?#3<;(G@Kfc63{&Ft%2&M_ta3w}7A$^6UeaisrSF1yT&Phe*3+7ps3cF+X%kOd2(O0ZwY;l#^ag%AZVM=DsgF`_mp$_z%=7&OceKRneixbXI^qA%_FM7N-h-yyF@pZH z)0g7UOkRlRY{YAo$tcL|hM~ext$f?|U!QqCUL0Sv@%JFqwEEH>!~(yvdn0~z=SJM# zFa3ZGuZ2Ji?lrp7y?1;j7Tejv6NQsUbpx!D0EefV%npy}Q+=Wz*PPe177TPtqprD6Mbp-H&ewkFNg!4nkW-n(qn@ zk9V`PrS{ht-GWbzA8YEW4+fLT>(JMMyw&ZynghBs(;8p)qoZ+!R~}DKO~x3nLH2`_ zBqF3NHJ-s~*95ROYf10qunl|b6(pMbZrb5+0;nR=s$VI^nBi@uh^TJYyLgklTqJ*jPHdLp_U)M*A z>c33r6*X5kYpG%AFp4I=Ka4yo-xxtb-$xcd8%!<7-3xEO>W?ATMp|PltoKifEdA3M zYgv=-AY~m>!k0L`wPogAPRXKkF(MYfq%9r1PRg>SyUM6fVc)tB2%4x(e z(P5Nk#S&h5B}xF6fYKLKV&;@k`BPl_gcsPNk~l-;{Q27MA#T@!#*(J)&G zffcc_UaRHWPgEKy_ch&$*M>}QnBTjC(v}DDdlcO6(8Ewa4Yu6_eh0t-DkcmIHw@Gk zWng_cs=NBy?!zjpV@We!c)ZaylKYT0bP0Wp)Nt%6ZfL#9p$uNr>QjJ1j6WEj*0e^z z=wt&GY1DLyD`M=^n?5yw&7_g2fLWjD4ex7Ow5=O^k?c99krrbVuOzJ6 zL5WKl+o+$^dyu!ghV!0f7T;iX zGB1t`+(sd*Zo2p5IA^Hi&;kPTsBwxt0cv zs~BDV9b5UeU$N~p39r7+E0lRKffMbwR!ZOJ#QRO$!aTvt>yV_}}wB^}qekU@{aWdl`lL4||YCnOJtPN7?Q=Eo% zU!$Li^7>+*u9LsBCr(X^fq(&wQ@9uy)2P@?=n79b{U5--asiD;i#`I}?+<~8`2lVp z!K10uAtip-yrK!B3?gucU?lb7r;_cKA?Z)Y& zaoUkK6^>Wr6%VA%6Fp20`O$MP%9M6aj5&F^3<{sR0GY4zhN!PJCsq?PoS+%&^g}q0 zZ&L-)4PDz$KDmydxLaUv{bV|(!jxscK=Mfyyo3`&{VQWAb*So3 zKD{OM_(J^sD?zEkC9Me3EpxY;^3@}YZ{@C|bSe0iq#A=vZRPaofp zE*pL==#_WCqpv3VYNfb_)OV4aJpesFeg^ZBw4EN_DwKx>}; zOh0i((?cgZ>l?9u`DX0DbzL_Vx^eK+$r`IbZxU!6;0D5Ph+uxvJhKCGV}V<^n3u%@t_;C=-Q1AnK_^=;Gm5oQl``KxcPU1WFU6&q<@lkQ z)A8)Y0;wCmwtFwWymvRQbaVr#Wcy&i&1-}|J9#30X!3NGM7*`X9$(qL8(+tO)c_F( z6B~eRj|Ph4XC|MBPmLdM45F*u-T3c!u0Ha0y}T0lg!DT%HrsqRc2sFx8k>uAa&K#q z%J)ax)oUGw0MgSV)A5(5pNW5A`q}u*#L0RZ_aN+OuKpW4@7UOPIFx+U3;eoV45pu( zIH9H-)pC3!&X3K+b7PARbGftO)4_c(TusBNn2H~tJQM%c+{faFMURh8YC0eBsnfr+ zb0z-M?bqVU{-&h$P=LwDPA$o*tWzCxxfgo>U3z3+j({#(l55 z6aW6^%kho<6@Sb2p-}5|NB!c==uG_h#90-oj5DN5+teU7;!>AiQ@TehGBJC|_j5n3 z_NHGaVDSCjy*u$%N8^D(VKc)9`qLQ_pu$1FW9kQ=96J`zj`gl}u8+5s-|M;#IB7c! z7|K2}zU0(O7|jckjk0ld=U#MIR%1l>jB{ts#>D<;Y+t?+J2!RhYnX3NsN`6d_YzGz zRvmL3^Mj6Z8x>|utvtFP(=R?7-808xe|EyJ8+A0|0FcV|!Jy1}lDE8+EDsk=-rtP9 z*WZbKHqaP6^WjjBzZD&?CI$ghU+XM?#$NR0yO0+&79L;pXG6v`=Z)UD6WwdKV*L1W zj6MBC?9EJho?%VwA&ovpdZ74pH{a3C`LGZ5(}b@wyQ^Q)nm$N+B`wnL$@No+q2#4s zLm49UqdG8e@9JxJ^~*MOeFMMR)0df2HWbyvzKTxF@~+oobCY zU}sz*G#qrbRO<33s~HuD6R`d)k%Smq!DCuyvDV_dux+%z)*QTLi#Uu6e4>uGR`DP> z;~Rr0KwTzg1t&Cq3QMJXoKPA@c=;KtAK)@Wg&q^Y>ITbC4|*5>A3vy7(ex$5V0rOt z`)B*e447%e^y^v&(h=#yLCCW8K}(iw#mYlU ztUVIbnC#cX60U_d`U(}yyp7jF+^!?hEE~MYP;5Xt_Vpz}Ul=jzKN#*^L)Oc~;4$;c zG2y+y`!#O3o~T#&0aO#&-|nOXn1DX)-P(4hvDT=C8FIq;IubV5iyAx+RQYfe_6xav z9f5=uy5Co9`bx`X` zjwZw)YePn*-c*;|MuZxV%4m!|Y8CTU*6!28I+)eWf7N@ z{$}H>1~g7=W5BTyM|^(kSpP*8;)zgZ(qfSFs{k}W_*AHPZ_LWiVM>$+`=FNXeT5Gq z&4)qer^0!0)hcAN?yuF6_2%{(M0w_-D(lW+MIFAn8;V~==ilPV(x@MgDQaIPtZ}vL z#AJ+&k86!TUT#X6pqMZi@Oi3-#ZKSkq%e&hV3tR;#g=Q3z9NLTtjgOIfLbrcG5VM= z->sh!$(OX7{3XL}AdJA{Xi}l`KnGEs>VX4K|3*edLz;^cRvd0idXx*y0;`dKz^9>tcY_eYD7R`ui45enlckUM+9H!6Du zS@jz~{81@oc3Qg0$H=039wQChluuxyb}epES3(QREl@S0kE9;S=mq2ckk`B#ndYHR~<)=kkKs-{-{?kqe zBkk_)X6&qEq}8>4Y(BagXSVL%j-4ylV(+bM5m)b)r$qC{-Zvc@3z%PQoMn9=ns4pE zD4T}be2WJUc(likTInN`lQD7bY)mdLc$_LmT6sykQvdK3(Axzm&P>M}g>~$5NnJ1z zBa!eEb@(E4RXAP=%ci62#o^_aUo&M@SubqKBd0C){hgK)FwqTF_xhdKd-G~^*(C9< zrU-NH;2Ho*|8hj})>G*5S#I;9pr!%O1IOoLq51a#{H4!pH@3A z#ii+`_~8Ra+F~rSk+uy=b`X|FC*!jd@6kx>N^SWK1beqeS`3>QK>3d7v*Yvrb}UIR zXzhbh@8Z~;4Yso*W2*9QY^(3JPnQywR~tV+wrGPLCtQDi>Oy>c;#e#xEjD^z-COlZ zP7H$+Rlmka%j<*>1yV10Vfb3<>;zvseQIpp#$Ub_iedT5(K)}m*WajB@J-!$4;pMq zXmT9y0a}lOK)^ zD82U$T4`}Q`orT(Mt~Wo{At)xJG{QX8vowLcjD$gCizDwfwyo+Yw;7KQ#P6}ss1v( zc6t8B_T~8Hof~nLS13DK`MM7uhCq*}T|Yf>e85P%QjD~^ehhg{WOSIkRuUfuj2T%d z;dW;~J~@8O2G{JXv+8FHLi*dT`UJ1wrtNWaZT!IaNxvfe7bc#F`|6`_?XCG*;blq_ z8mC4u(%!l2dx`lA7ezHMT)7#$Jo(SC#t}8fFii!`SY|5Jf2k7vpiYiwpq8Y)H@ob| z)CoIMtM7->D`2{WG45DtaR1PVf=xAYj*bTf5-D|TObJN7xjK&EM=^*AgM`exM3 zgFKt@R~~i?;du!1tlISCQjD_h)f_i+<8E}W-Hfqg%Q5=Qh1j2&Dz7e98lFosy}@=B z@jO?Zfahn+6iIwByvptP(2P^(x|V;&HOc%W@E@$8FF&GJnrLtORl2E5BW~n9zkI2t9g)Vhh zxJnCHS}U4A=7BDTO!YN?qtz&0*DDWDbV13=x0W&BCM8ax`8sX>N}-^xU}Jf>lDsN3 zVQRQ^3rm=mzbX_Rt*Etc{kT)g9Gk1q<>?at%#hl zBro7fnlzkd3M&ja5BUF42KNtWMZh%WDl4?t)mo^Zq*+OAzeWcC2*@gJuBkRu9gHpB z*L>18BCB%WSAm+G`cRWu^7(LVhHdXF%F9L|_WC#t$VpXB{rME2Jh^{Mw1KwfNqqhH z>aDs5p|8B~gYHUOZ23tX0Lq*c-90Z0y+?{HO?dz;WqmvT8T z=>TbC%7#I^FF5>R0SAGy9yRO-03H`A|6bv}j2}&XWgU}N#ldSQgSzhx_+@##f2#qO zeO)MW!eblrwZWbPRGr7hS-IJt$UTbob(8&rzR|vZpmH{T*@v=^kv>LKA7D!)4`k#g zByX_kkBXmtvN0T|exk(b!&Z6@M;zr%{;8|$30lz=)TTq=C~f)3K7NEW{*YiSKJ)Qk zth@>$MXhU6STRhjDKoZs^{=w<7sJMU8fg>V0r9VKXbCR_)j;lqG!Sm6DpI7^Ky7g3 zgK(4vdOx9^-J{ywK!k^&^-mNWCCw(z5IE4ufmWg|_5e5zKdFoOOm7gH?A5+~ZIFQ_ zV<5;hJUFOvlc%k@$SsG@K9KzYL?+r+fc{25!}!B1vw3xPzCs&gP-CQ3{-~8vb74WA zo*b1n1Cu94VKcxHwuKF}%Qy)5J;D#O}D3g}x=-7CSkBHKKv>Q+3zZ zKi$?UU`5IZDwxwqsxn}t<=bCly1{I0_`(K~w=l6M?lC>cP>0m4A;UZjGRzo8;E)o ztYeNZiJLf`dMVVLXy)Ih`3q56P?qb_({ee)*Qkdmp!J4 zRhXFzPsGIBtdbrJpLVS^=Z#u)R9J69BZHEqJwzFcToCU*Y5Xk5PHLT1^v#>l z7fVHe{4;Nm@g2&z4?m?mPRz&Ha~I14JsNaJ*0*Bh>Mga`4UP4)G4kPOV`O1@Pb-+I#qFO0r3BUHYYRB5C=#E9&-NvLeKd#jl{@u0io z)2$eVF??fCo)eED8Kc@0((l~pOk5CsQssDRbk4dyFI_*bGJJ0QMEr#He8R6c{=~$w zs?UgD3H-}D*WHNP<;Gw;nC4-?%BC18=WYBQYxPmCXwv$RH(s?twRbvKVYq$|5K3e)t^p{PQ??_ z>qV9MGrFdKc;a+?NqyR=@&3S;TN}l@`3ShNGX*#bLLAmL=U_D7Y@u8<<t3IuESJX*+#EyQ@fQz+bx~StAmMCsMD>~<*oj>Gi*r%UJT(Bx5Ot< z3G2MouRMl1Y{6cdLjL9Nv}^tupK_J@D*kOqc@G8x2#TcE7cK;(Rb`EiLL_BP1p{BG zQR_jj!Ts@0?5Vr&PL9N$mT>!8cXXz7R|pT<@ClC$UT8zEWa|Gm+$xVW*7}viRROXo zfEzV?%DMgw3SE`%{Z#{SH3;Vk*jjpV0raF z;5i7yKdf$R+8}v0y2vp|y$@CqH%27;R~dVC?ETp=ThZa6mDhhM8)XzK3Gdr--+`f) z*RJxq)#mgpDF0?35F`yzpppY%d6v0dcKAWLXcMGi1TEfm4T{hFv%S#Y^#O`UPxI74 z@^H4a_X{3(ENQMKfVeGeuD_He z3{+-@@t9b{<|ZRR+j1T7K)6rKRrT@@p6wiIFrjh+cq{x)M`;HLm zew9dmpwdgbNMe(|D0#SV4#o!wI|Q9xO|v;cE_6Q^ifwd+f(_LA`L4ltGq0n;SbX*q z#YpSQY1NSHrdCiTO(#k|J6ReG+9zp!(h0fvx_Rz+Kx4QOVytyTDPIsBXe`j`@RJb_ zfycej-YbwDYQ3NEIBB|G4#7jKLZ0}yA?vMAE?L(3V0gfO&_WE2OceB@zs2VS-SEhT zDQmaC{i@s(kuVFT?&O6d{fkq07;pI2@w_lk*zu|W`egQ9kip4R36Pw|wlZKa;0c-J zJzz-Q3~UNdSTOTH05#o1{f`0}w^G+z(g8FK;%CZl2TomJ{1+SEm*)TiC>`e|df zpW9j2wjac34am(xtfEgOsp8FxW_ZUXy^Pl>-|vC<(>OcP<@E`E+DGx2NaWQwb{Hr} zMP!trEi=d?!#D9N(;i#09ngshl!?+$9PuiL&G5VSH^iq-OhimlP5meh(4cgkg{W1b zb603?TtwRzLW1O&+rIH>WJJcD@mt7Grek*nbjZHd$ZPzE0s#^MQ9EngG_dmE1P@cN z@t)rz$FOSSvcjRWslqcyG-Xmc>6aT|%q>1)I}@Xeb1||sUvP20Jg8w~3F+zvwjy2C zPftrPZi2fbY7a_HR?gxSa|Pn)cgP&fuQd@sw@M=v3wxEKCnPP<-aewd43WV!fiHy?N_@M zOuwGHYe2R8&VV!FS-Ucp z2rxb8(7Cj{pmT>S6rk~>NI1Z}(?JjA1)7yNJxf9npqmkF}HB$|fU7y_Ad;3~+ z-n?4YOeF3B7F1Xdtx6~7JN;+;qMyQpHWc8NKh^HBeKaOcF2?+GPsYCH46DSOGOpi_ z?$ui{qIw*8;o0aeEyPpPiyw@U_OO$*lp}F4QD2{CDgxd3naT6eFIT`8iC@U?DZ;PW7@saW6_|eI;@sm^MZRq^5$ul;{{?pT!;uoea z#t*7&7;{@(W0_;)wH6EBP}#m6R&`BWl+k@jzGzvJ)W)>0eM9&~$% z0_n%;*z5b7jTzquSPf@cfA%t?k{8_egYn zcscaH(b==n5yRrCF|Au#@aq19_%Ao#h;Q!R*Cq7mlf!LYXrF2Q{>1dTKI8AM^5rz? zf4uQZyeitn(Vs7SVU`)%#vG^k^GVwAsnKb_e)&u4Pdt!7zxttx)9%|m(7=NT_c}XqS=aU}yQ?0< z{4Mf(E3tR;c8qAPzIgGe=!{Low#Jz~UU$s*-?$I-y@!x-tv#NVAE_?g8N*n!vexA? z0#R>_wdH<{f9NTnq}`vJw2`NYqkkiStbv+#9~D9vZn^)_xI2DpHFjQkJ374j(I0_T z8XkKqwZ1jFLGt!^OQWMR4Fa9!%{5~&{mhdZhsR@dtBkw**KWqB#@o@Si;;F8UG;BN zdO1%OBs1w}nc5r~5;wdUyQ|RdfjLM&4R5)A%$Iyd)Rq>dT*-PxPPq_NF(UWY>Ms2k zo@=>W&+ccfIyiL-fvr)38ox@dH0thWEiBmFm&!>=$snS^*A0~jFpR^)@>L%+bI8H z%oNUPEi$irP7In;T1V-AkQ3!TC) zx9Vn;AGFb5bQrjjD-e$IJC1(x0(4q!clr|^z7WR+?5;e}_`?tnNl^F$=}xueHv7U_S?LK zxUpB{Y1Z6Z&TEG?tNS@L5jSa;q?>E2LFG9p=ehy=`X?y2A2O(J>)8rpcSZcIThfYY zu=O54VdYL8sRwuzs>F5Tx~xbQWqp4j@Ij{i?qMvxzh$IN@Wp__NekPf$Sd!g6b+&n z&ioD979s<^aW3?NTHuZ&bmyux8yvYCu7-mifSOJlQqS)ekln-ZdkU&Thw0VSU5jSD zLlL*zp^=G!&kL<-yNb<4%*6<=uz4XjZC)|s8Z&KS0(~d@8pfI_tu!&p+E6RR_>)E& z_cI~UNiXwNUmMXtGs2S`O!WByZ4Z8R;2>|8K{RnF)I5y9AUzD)@!DYr;|&Ry*JK+8 zoR0^s$W1w`EEi>cAX!r<$@5eBY`2Cc(!Ro`y{YR&)x8Js%KNDuArq7hp@}=u1vhu1 zv#}jr-f_PsWFwdM^Q3|f%1{4I|7pqrZSxfzW`M##QvdV=pdfPVt-P%ti$BbLK0&@1D%T(p~XE>)N9`qP69;3ScM`x#FbcP2sGzKvLw7y5}*LMoJ z8SYMq_YJAqz=qk1x*0B;Yq-UOxRnR{U!|BGHJPxpudZ7tvNmwKgR<+_;A&NgK@sAFjTR}hsP?zK%PxpG2UD&>?6^jiti;iyf97Jp-_BFOnynP&;w8!xd#q5 zBwQ1}<(Jo;dF3iBeX13v14_=e6@5k5$f@@fcZ}iQSF0=&Y_qJW%`aZNyu5V`Oq57IN_jl+N!kNOT29ig*!`$9nPF~qw&EY| zTz7MDDwWsSy6szl;g-{@7)UwI%1PArDN0~p^^GCzKiqgF{_pGGj(gGt<1Vj2ZX0R; z=2kJ%y7>pNEu(@`#yEx{?8`g1Z6L=0j&ax<<@gKG2OTj;o*kQs)1nw<(LKWeyh8b# zyDRZ;uYM!`+UA?qg{H`>W!N7n9Q^C)+J{Q4jU--pmFIv=I2bS8jjR{%Fzin+byIz) z-udqECnkHZ4(=$u-`}|t|Nh!b@t~tMWsNcTH%yLfOKWUSOaJ+qOYR3=lL#KDz5mA6 z<@nX@8*VG4THQ#ee*J-lZ^@myDBq<0jQR{GfD>$_RolO<>nFo`d=t9Q$lY!uFZn7u z55frH`>+MKJKHV;uj{7IlFm_qS7h@I=igDi+Q82G?SaOZ+Zt2uug1*j^Ua}- zv7K&=-&~Eo*DgngleB511<}*{DMEDBe*+{%gIEt}b#rn~_tPVDx*jh*5#8yD80Ef8 zWA6Tq+cwgUJo`j+bbsAZ9KV@C*fxZ@7+{Yn^Ow8~;tLi(L-LKghHuNwr@P0O`A>aU zgnaa0BlIBqmw8Zpk?BVWvD@uh{p)>M>AzJbEXy)6Lfo)U8@EUi4CG&F@hk2Ii%7KO zLlB3rd`VmX(x=e@v~I|uFvwIE!XdMsU~!i;ki*pQLZ@e0;hQyfx-A=^LZ_Ru8sAX; zvkV1`XOZj2<Ss(3hM~arV(cx%n!vTR#Pzxlh0D>iXQD8P&C@wcgTnjPT0e_UnHK zPoVk~s=_S`wI&%^6kSjl-D7rjkLi0u4Q9SC)Iebqt@869c?#{XYpg*oRiRJx3OUhh zL+qsFQ=_rZ=~x?NrEH#bMPD0ULEYnW8kSE5;fA*%w&JwnfII|kW312zWu%Nz^&ziv zp9>Yr+bHicIE#UQ6cDZr?q6Var#Cdyw5)nm(%&Uo@%tbHXI!WP4(jkn0qS+pK-L@A zEBi_85!FKoep8&k;|MRAjgl?uQ*}bW?vyl0i!@1?x~cVJchYtkXx3qd6;1!dwlRk} z(Ns9-&bcRPqTMQ+-3s5xQ&y2WATL99%oY+CLlI?PRh_sFB=qZnD{>D)I$}$GfZ`tt znJ3WZ+c1y_!LlDVka4Rly|RAVWj9j(!8(8vuEsOMD{Zk&*}%bk68idB)v1YN#bFA4 zoNMSYf|jr~{Xu-U;P{pQ!vNP|)@@ZJoqc|7AY2Wb?6CT1t~>p>52&HNCl1QZwUTJL zXuI!-?duzN_*t`vX$H;S3mxDBoFUK)(3M@Ic5B51n@@lpQo8r%9*JQ8HUfykuU zK${0LoPhc_w%n#-;Iqwq(FyYc^gu$JDok@xrr&_uNSc{0jDRfZI=&$mL*HT{Y9p<1 zR_NCc($`pd3W!VJ@_W*m%vsp%#0U!>f71X%T3rC)hY`*FP-q>4k|S6L4UcEx4TlKeg?5=clt%;v!58{X0c^s zEep}wMi^(?hERAGtc1yU`tRkHIt(c%@-`4Yg^<*XyIgz0g9M3yRe%N1KD3ndY3|o@fG7NuX5s* zPTa&cuX+-4L+l$``4djg#A58gK&zYZj&PrE+U^!!^~N7MmJKVgsA+KdDqBb&AREMl zHs6NBPPvvm4~sPb2iki8|FEFu-(L@puMl0}-^l4M%bsN-qxJIBvvAjYN3)Nc?I}fnt>YIu!yPwlk27Nh6S#^|$`qB}nmmnIhuH`4k< zU!(a@;9IE&jI?_gY3~d%(o!+t!=N3Z@INy>#7MhUUw8a)^%`K~7bDZ_`)l!4P6>B5 zVp0vnD_%KGomv$Q^REDL*Hpj1v2!c_9~-auRO)Z;-innj_1%px4KdRG?XAo4^6pAA zJ$t&Y=;^FtpG;|y=dRXr*H!nwuR8qAotriWj>!jOA*Xp$$F{*v(bbLi;w9zz_f$9k z+1jh|pRT_gUsXHa<9nO=Id+)!(mfUyr}Ld0A_WI$|{O3Odb0WR!s~7=L79InIsGG_SJe z_1XX4>bK(+^*z4v>Uh!}qh&GF7EE`k3y^esewRjPtM?Vb!M_2g1ZR_Y044(9vEukNqL&Hb%7ss6t(I_ZI@Eh1xbaiOk-Zpu=3ZjjS@YE=Ko9Vq!;i zcTMx!>sO-lAYXT^{H?D7C0bv{?t$k7P#)G5lzT$;t~Kz;rSn=7Yi!}$>lkTo-ieX< z=@@zDLUbhOmHo^W?X_-VVUianSl(8ogiE%e#`IJAF#OwHpgr%I*slo8R>(M+twV^n z7#Y`=+R|@4p?xibN}kkxvGBz$tWJlwtWtdNX#9lwX^MS-*78*#Z9Ki!Y|<(5ky&?8 zx;f2k+e)pod7&tz?RFf}A%2xx0|zXAMK@$652O7m3W`iWDRaD94*aUTgaKG z%x@5Dh<4oo8LwY@&<%L~XQt$bp_Fg9?oH{k;56#|M0D#bfV&uG^AxI$pSl4A>j_$) zqOH`g1lRpy*KZ2c^~TVuw7aTQKU}H&sEYFaT2Te#n&(Rzo$--Ec}=nIGdojbJ{{ZD zy=O=FqFvJEUNrM+P&&2w_B|_TqpUKsF;MIYluGc1b@-;{Uj@A~|2#u(nh`{>dDcTZ$SD{be$ApXu1sSthL$fEjs&Rc~ zU2EU9i2GX4_Mzk;Z&3gV%U&3JOYA{$eY>h^rS#>apS<=6lzz$Ad8TI&gbF>U$bEoT zzRxg&U&RAFX^MjIjSQ@LSr>I!-k9N=6Hz*FxwuqD#o=4De3O>FKa8~8i=?48b;^A7 zUw<9}!^NK6dsL@dTD}NX?b&8|%2~AvNk4orW zKxWs*_Y6wpeMx5sw5uTVXv^AlI4Gwrjtn&o_n)LKASw3?HGJ-C(+9G@aIGcpK2zfu zl@_#5CIrk^N6MT2CO*?^r#pB(nXmCOOv4KseW4YtZG_ zy#XWful*&hVzM%&Bo&v9hR*P&!ZfNh0)ZF#8c2P*Q7eNsVx+CFfODmiCV62H!)U>T z#72weNMAM%iQ$P%P5{Lf7!jr`)1{D^}JW05u zMK(`E9$(O+yMCjRzDPVyYV4>_v2kbvnW*1~E^8@s&LcVX1{Vo?4^i@!-pJY{0llSn^U_Zmvj=bhFM# z+j-$YUMbM7^Fhe^$bRj<&NwUdgelBP-q7Nq-ef0C5%uz|0@s6N`HK5AUI6ITcfD60 zSzBQ{tDmv*fb~{bqta&4E;_O|5?%TL#&BLa{eYVnA#(~(qM@h1E2;WLx76ExhW?|m zAYUy)fAZ6q3PXO1?$_uT36C;LYjh&U#wL{9q?&g^MU@`t;$~&L?TFudE#m8MN31FS zjw0pvj1rr5fKdN^RZL!q9*Y$}$7GBka*i!6#==KmjPd1#=uS>Vr!}u}GM0H{1k~IB z^>`^iHuQL?i=8ijGdkbCta_7&H%$~czcb^tRvkkbTRnCwLG<>6oWi^> zU@a#SaI*??Vmd}H9oO8bGS1AZ9wwuE_d$%_Ux~5Lekw*k^J45CTZr@1^YQtq z6YDCJA3}d>MMJzCBS1r(fJbJ-kezU_h+9RoA)D) zuOH?co_F`R<9cT^-rigHDZ+27Zm!DBtArDNbn=W}3(M~rIb*6|!CXGdq^xaLW}vRVFU!RwdrcXn)ayS86+<#o)w>iBWsfSzuK zvOy2DRO9d^5VY*zlGDS~`|BpYrE*ir$14k`6j~OcUnbhnAKxDfy)Q#}sjNJ0^be zi!uJ056Ax5rP$#iL7JI(`tMssw9 z<6R|;zW#)d(DN6`C?4vP0doU$3J)Xl+JE$c2N`=$&BWMG{6LIdJQ?G=+p+)h>#_5V zmtyqfQjC7-hhqQqamZ*|b0N?g@O!NR%CRUS+D0rAU*?UTV*c|t8Osr9BS^$ldc zV2ivwOi;s6HGy)WM{`I0{qi!UZZnJ>u(v`Xai1lwd6)o+VrjV@N;eL!RlZOlD-SwyYi1 zo&z93lSN@%Hd4v3Vq6mboBXOfS=Eb2G5h!8Iz>6Ev-%TaI20Wc9}T43q*bGp2lWbK zEZv#t#_qy+>@NVZKu*7DJ+UmrIJ=B-R&(I`Ln57h*1$2!mZ2`DAG*LljwRLJ$1_xXv0H7b1aee#qkfcc`L0k?VSfxIXV zQz(9x3*5J$^(W&&)6bCcffnC{L6&mjgJSV_9f(i8(w)4a#!aXFDgupLKMmSPv=z5W z@4E!q!QTxKHKTjX60(26UN~=$xxZHSFW8r4uROv}7kVrdBG2*Bh=271Dlr3ZH+*#yH+g=t zee3;EjOkh#RRKWs*%e|dxTX5JaxdcQ-H4kQvUMGf6Ef}0|ipnK%b)r2lPupCLqkHjo(9nAa2J51l8Ttdj(Hy&_Q|IAvj9D zkAmzU?*?2A?J~Vja1@m?j43~d)a6hhfUvE<$3^;i<(q!*K>DwV*5HP`=GuMRe8onW zq(h*YCn{BzrN3H;qsVc$(`u)kGQeRA`%uU*j$Y$iXN2S>1~*Vifx*P(e&6~)X4KBG zFY`Zi7>WPIUoJ*kqm;{rcB9u&=xkZ-90pP9i4MhN;8$#DP~{thxe6GJWEqT`7yCU#Hm^f}3!#fA`_phpG; z&Vlt|kPD!MhqfDj)qk*`4>%2dld|A2eKOop^c@CmT@L7lJ9Vz;x`7G?X)`H_xV`IS z#pL113&dS{Ajc@i6UGQnUKRE4AJc>yZ%}WiS^1Q~rX0w8ZG4n4CsGi({u^BzUg&YJ zQv5OwH)ehcR(%-5Y#M48)t`B#61-pEo%yLCq(@qHL%rk$$^$oGH-+vicma#$pWdMB zZlM0sFT>_FKscZN6%rOe2Y|L9U#V-IIn~Y_fbLl*01Lq!)3W_YzZanRQH~4;z?*{j zB`SRzYsI4<3v>(xX{_aS)12ZW9yiB+C9>*wQna49=gIP}4Yk7N^t0k9tr6xajTv3W z3C0e8@Lu^~oEVu<)lU{9t@!bgF;zj`=BRa7__B#$9;ij>LF1#K2R!=#|JIg7ftnAS zKHe01L>j%^4u^+@d4z`kJuLpCbQ=Vxa}i%7@^Ujr95D*QH@BUyXc-RmgAVeuzu2N96sC+HW+{i|t#I^rQQi{ZsX*guM|Ci! zp>KR+KX$(QQtbTBH>30F)v%FvPYJL_w}CdtN1>nSr{a_tb;DTedxUy#;0KW;m(zv~ zj2esMF>>)(j68qdbKv;IWbChQMCZzl7~k58=^y=K>^*%hcIG*ihO)GSl2_X08@;7; z0Iwi4N3cP7%rU4}IgbL$n?N2%iBsSxAyW&k0ZzX@H8$th<(?Rsig~$!4j7$s8W&4zmE<^G8{;$7r(Fv0K*!FOeseNA2?^+i#D#@**}I5c@z3bdm(yaKfOo@>O0+Bwyau4qg4 zq{p^uV#i10dMUS~xjPO(J72sxZB4!B3Eh3A%Smp+^`al_7i}2y^O&yxLHWbdDB0H> zdl@%CT*t5J_S&g1{TfzYVVO7R`xtD`kI(rv$b7SuhY)Uex8rT~drl4S($kb^^J-SV zwM*kO_k-VgBRaqK6^&J6aq35YBsQS_3K*4M~lW)~GgNT=Qn8+>Et0 zvS?gOBQ2lQz(_l;h$GuE{!e@%CO-Q@?4PSfS_N}F5K#15NiJ7YMpuN8#)c(JWz8@- zyRsAOzw!ss`K@n6+*LWcTF=@*3o0OEF#6_w5phYp(O1ZWG3d(}jFDDJ#PO*Z`QoQy z;?n6DS7!TfUXJaTUW-xPUyuCc7o&6TM07QF=Q@*HlG-IIv^nwU4OVbF*sZxL<)$eI zi09anRiTLe?Zl7vEdGt0GSbHN9>xaRiqso&47M0*vu;MHAGK-6?b?$Ou8X_IDd{SV zD9^a~(nPnaA0*3#qe}g2ZF|*{MX`|YomTh-q&H}vHH?K*sHXW zmQ#(o&%{k%;$GB-Sx{kH>poK(X(eZk$2x{}9e(I5wg*ZJw^2Vy6|_+G9?OX<86bD* zZzx)VHBdT8ua9NDWgyG-)6kTsUQpt+<0YT+mLJ|8>#EzdV#*8|r;tMR12xLulybJ@ zK%*Nxe(CrC;b!lc)=$=%valYEi#hJmS&*k6I>RUR-jR?vwhiDXG>|rg z#!hHF3)>iJLAlX|KGR$;Tt7k^X|+mHRmA#Uboorp_4^Um?nT^CUENc?@%m%mgD6ek zyMg4Rg!}Yr!7$n5K=#KbAyJnZv`2wK_W_XKP+i(WCsN2!f#_vGI0#wi30~Jgt1$i2 zoiONrH$W2aC7q_;2jG2Bt%1Yzv$&P{k;~$MHEK(L&l7TRnKXQQ3SiSoJ~WfB&6XQS zUZ1Ip`NFoC0)zFJebXfUl2#yzc6yl)&<>X{kmbQJq)|xuQGnFBopuv(Ac2QoPmc?k zUpwFL9TzT%#z|frfc^C2#X<%Y49h>uk#U+Zl{YrR3N<`~m%5Sr7&n#q z-3^SiJPGM+@Phe`G%}y zf9T}?P&i72R(-YMKpiAhd0#X+>~6*Bt-xDwSehAbz(3PGELt1-uBR3ZUK^RF7xRL) zKdezd&}O27R=*rS>_$+*?V~hlGm`eWRb>WfhKE+(L_bi{%t_HYRJr|<*AKjJvKZ5< zyU#!4D^I5hMJ`8%MV>ci?$e?+YHF*)8;fTT{3$orC#TsLr2DLN zXAa1^!k>j;Gq;cge5D7Vrrq{(92m-he?{{mqy<`E>FEbAMA@8k8&Q|cO_MR=r!=Ln z>rc@s67hET{LN}(J%!(0+lub0kf%6(QcU4=vp&)ti}CKba7_33W4g!JjdRs8PXOS^ zZVzC{ZJgO2(myv{n#~tM-v&fNhN+Ngd-Kd(J5Hv5H0WtF9NHpFRU z!7Ra1O5&LQsiDR9(k`@wN!cJ2IXx_cl+&R?UB+b?kS`l; zGtvF%rRebeE?vGh(thRDh;MKrRBkN|ybfRuzy@4BSFwP0|@37iO43M>H;CY)u2L4X#keOK+r)M%M;fg<+mRP8i1}jT%R+d2|wA zXqAiaP)Fjk&ZwhOiXv~yAuQii!>8LU_t~%+<29Qbd$Ild--&IEw69&)IH-_*pPwR9 zXN-xgqr91Wvm<#JtI7Qm*5S3gVMz8mCXs$H>Pn#n@+Fi0`{>O%R`|x z?hS+L)eb?5oPgzZ#u(8CfmgY5>U2{RQ>JZAnuctFyxY>l_y(Mu>Zz5j)2`U3XbbRL z9-WBI&c07AQqxWPuJ;Ou#2*eS-C^OI#D@dk<7yvH?qay!sfORwgv-XS{Ke^Z?0TPb zPr7fbUP~xmh9Nt-kdh1%AGVFt80;07$K5j{*+Xws_JI=Z8)4a8mq^{0o<^wUWpkvWNr zF_cr=1qQV%kZCmCbx6M@j4{2MKBP9$@09A6`lX(Bx_dP&uh1^_y{qtha&t|fA4YG+ zJM`mK*`;F%vx9k^+lg_l>qcIBJNEzKZ$;<+R-FB*FU9)Z`?2v#5}@zPVNymm1akIPvIS zuQ>ztR#|AWF#Y}0v77LP&oHDbM&&7Pc z)e$FZOMR6%JjjJXpoyRNM+#EzUBHrk9}d6)5ruJq{9~Z`9j@^c&^PdqfV$4BqDfHs z7n#s}VI96n1X?1fRHlS2T=lDBXVr#G&_R?wZvPZe z1F;5`8kCXHKw>E2x)TM*ijj7gZ@r$HiP19)(LFI2d&`rtum0YdRbULXTn}KMkybxh zG0sLj{h5!^?kgVG87CigUl-7@($+PW$V}h(P|1r=N`D_(@X+R{k&;^d{??{Q(#j_OT!nXhk$DIqeF1 zOcBy=*qh{3Hbz=L#d23SCf;vg-$i|aF^lm>q|~SCLrv7|Bk{lidq*c03NFrQvd{vX z{UzGe>L@b#rfRM)A!%~I!`==Lsk6sH|8B;=7P^lrJn5v{ROp0-r0f1)^LBq1x<6KE z>Ok?$OXhflBaY&FuZ?sxPpP1zstQiAckiu7_vT9ZT+L1DO7+II=S5&v}xr=vS9P-LOoyj%4ez=wr(!cz) zsGyyHLdyEQ(vfki`>-;%;~o;Ez(9JqQ#3T~KBWp+G(`TM;Gs(Yp+PayGC+e&0)qo_ z>TQ|OGK9j$NUMPq!z=~`PEq+ZZ4R(?aL!J~0LlcwqUKN|tfWx)Q*8~#--&e2gaBaSZF{ykSx>zW(Ny!Z*{fci&^5hsN507bK!bw_; zS}aPq31-5yx$R?-t%= zq4Sy;ghs7_G%eFlM$79msmF{;lg~VGC%CQjW2!t3Ri8A3__gCRG4|yxLS}K4XrAgahO`W|BO+saBQd@=TJG^3k331Iw;|!D@1czjsVAz5R#nO- z2EyV_u&fP)t8CtuH?M>1i(C^sObS^;g$4$-Y8#Ud zq?Ki8 z#@n|ee)pAPq}B2ubbs%Mwixq_O2_MAQBeQ2!3wr@$nl+d0XIfkt$Qa04{dX_O=V`%fLV_{b~qPbxN_Yfm3hF<5dIRWE^(fU-> zKi^1med83C66jAna%2Yl>|gu8#xG9MvK|`WAB~Ci-Przv@5J_(zZv_lUf1}?L?ngT zu%y0>weHeLOXAcG$UKMsP|7nU)bwB@?S$r+vx_nEiDzQuvmcJG=DgY6{n-81E3x@5 z=k+}pauC|%`1r_Zd~xzrytcm`&21mF`)9D-pjjd@h$0}hUSxF)A6aP6LD&M zT3vL+`tv&GYr7lq^{qQLv=Xvi*5ofv%*PjJ&p6%R-nZrpHw zm>4-p{KKFnjTPJ9pz|M}vBf1<*vTKgYGE z9ed?+?EVkG8J*i}aq1`kbZo3`#>ThajP9G78`hN%U5NWa<_nK)l6fu=0(A5ot8;zM zc!rU7T#-jH(*8h9eeNSR(r)8N9L8^t%|hJm3hAo}cve#KSH7%AC#1{Fz0FwtZ+|5^ zUw=dQwGwo+=H60R?rRg-Kk=tK#50cpjKLU_xqn6%DEl?sd!Vy!JN%%`(qxS2-nzT1 z8eY@5bZRk1f8qyY2eq#P(QYg~n^ zDb+zG<)HjTnWvyO(5e_dWvgO0Mq2ieR0r_LX-^w!sTXhPOW&4}mb%7BTV9W>@EB-G z$JE&tU7*&X=;SL3*~7pE83%qpWPaGf>|0a^OZO+xw#*BX14>|Jt? ztf*d$**FC%oQ;dbvtmNh6D2HtinmkoSuU z^y4h`lR6|Gh(uUFBPX2rCflO0`Lx#e8uFUnLoVUK-I&t zN&#qH&-TfjZxy8cFzEAdIjR~BZR^#B#{Xf^jsy=5iAdXI`!f!)Zsu)%82s;P%(anL zG*4*L&v*b*#Qli6;9de$(|8PDQ2)kA%je(N6J>9d2mgJqAhasz($=Tyh#vGizHQ5a z7Tz?$zP#UxQ}shn!g>EjaX|M=WVJk`<#rRMkre~0bhv(kybKv$bTI0nS>ka-eI5o! z(e;l3jK$}_?-!dvHtWreUU{Ie0}KEiiow`7ETTR=CB8Axf~|%mFE36QP+6cb0l_EA z&jYN2H##XE)X8L8K;^TsAbmWjAI3%yH;W9YWn#SXRS~z5u$9+;Us{$+nGD;G+fFNG z!}2){n{b2q^HV9T>!Qj&NXRT6H!rst&@dI61Pcy&H}2|RNvTIwq$hj1ZPZdfOpDv!IJ+V zwm~5p(P3c(67>~r7__33W@GSd$$L7h?>79qLx}SdF<1^wEN%}EHBK)~+ug!pAh~_` zIVuX+wteqV)3APpJuxW0H&-;Z zZ^pzE$7B4dv$4NC8y$@m-dg50b=U4j+qD zgCiQd$LAMf?)b50sP$ODA5=dC^^ZD|Pq5~=0g|qfz&+}5AjcBtUD2M&S1R;)RBI>; z!Y`8I0&2c+7V5`=^y7LMi7^fFV_Unicl}Q6U%eIG`&hO$=y6Js$V^8d#}tVJl!8i6 zDe5(CQlak;K=B@n6^9L`Cr%o>Gvl`1cCTHJ&dr-KIyn&&AAT-o=jP&nbL`{s8{4o5TeR^%#0^p}q~C|i13lW|&W+B* zC&riK*|B*Wv^;&tCvi&k_irzMCKgqPxAwQ=!G1A#CVpY+RQ#!_Gx2MiH=2BM3UXHg zRYxz3FUIF4PUseDKejq$9`-{)l^%xdMQ0i|Xf*tAB>bc%!k?UZBChYO+ki=)=|7=5 z{ps0@@g?DxH*QJR&R=C#`t+;f?)lMga9f|0slT<|y>JE75Bf#b(bC9d{GRgs`w!lU zTRU6P)tY`(X?|p4IsVrtKM_AV|3v)Y?AiFj?3wuD+}ZfC+4J%F>CKlSJ|63PyKzHxwYIzKKJkA(`?+{}VjM|MA$T;tP|fV^ev5d#f0_|H9nU@z2gaWux-1ZCwx4vsyOCS=ai(MJduoZ%|Vx z6c=HD$n__(rUDdKIP&y`n7DAtZ^Yrv@I>;ksJ|SuTt}9a-$Id#$B*QUywO0*>a9*} z|K7KwduyfK%d&27Z=~BODa=i3>!-}wEa%>sdt}zYxo1z@V#2ka7n?Ry|7G^euixmO$GT?%=woreUHV z{g<{bGRvX0ujjb!Iw60k>Zm+a*~0X59L?p`?e(?(Yqo;wPN@E={{hqw6i8|yjdnT$ zlFIb_W4`ob^Vts%$g7?xU)REoag;w*08LY<M3q z+7!$h9@DfyTxFK5ehfs z5`Jy;c$GZeyBM!E?{)8J?xWA<8xqk!=f51!8Dos9E5opMd5_Q@)D1WW^6|h{F$cK= zkYNU4h%D1PkoPb+EI?B!6$aghKn6Qf@WDWjRJI?6%n^szUkirCdmLy-AC{f{<$j< z9O$G6D(k&LlV3aIA#kLDaUhMsD8rI)*@f+Tq@MirvicfN_+gyINQ+U3r~c@7gku52 zA|#EpNwc51ugPD|zP>h0kM9{!nGUqUFxh*BOz&~heK$JPI8EJW<%_~HAyuc*ZIym4 zIS4fI57FPwmS4jTgiAq8UVxHfZu0$ESu2;1QJF#f4f`L-wl8R%*f1I_WF!Rp_P=PjCJuVq59 zWv5YS{{gvmS9u*qvNZB~%pUQ5Db?B;?Ud@38-tMLnJ@8#Ki7`9RMD4@PdyNP)(Xh;VgO;lLBn4tPumcl9%Hab*j_lEv{ zfvbkiJksrai+2z8a|o7n#S8oT0x~?kA;&e!Cf#1_VWb`3i_s^J$H;|KvA;0wYm%>b zvH{h-dbhkPOGBLvv|e*6tu{Iz@@RqcYN4-fAv`}Cn=#UkEiAgVbY?ono_{u`XJ+HCEL&&IX=jd*=; zt*KgL)z4wgkxt8hn2a=4Cx!O-W_lRlpBR~m=f@Z0_~>MObLU!>%mFmB=@O+#Z zn~Al(9iL>}?o=b7!hB}(gpG{9wDykTl=6A{$uvN<&5Pqp@v(_xabR$i52SS{{CN4b_LPt~D~ytM-S{LE>W_iO8S;+2j2(cM>^n#S{!OYs*^ zJnxgVzqfuXzOiv9?(A*F%;_W3(HT%hi8`KD+>43joWc!mp&fx z>Dg0pdTcuG?QF$co2${aPFb#QoEV*sPb#e+UOXRPUA+~Tx7Hl~pIm-Aer)jx)yH1E zx%nXOZ*RrNr;f+JbowI-vl_pktd25+582|jzrTCepi}9=Xuf!Fl=kmDR zB}`tI!_aT@XzHofJ@wTf;gXg*T2Q;K>~2>hZ3*|WsbleH7oUosUVPI1>bKW##7kTE zeNB9H`nXTHzNs-5t@_?G|4jha8x{H!^zI6-EPcpcVqo`z7`z} zEX-R>Fn&0u@-~tPnKZbc@M$Ei$9*!cZsO+yi#FOST=LR$?DUD4Iddw;bw9ngsX9^H zkDfghqsNzgkIf-MgXbg4ASH47Pf(nqb{UFX9{APpK!5n^7C^K7?eGp`S#biHe@Rs9fZzTD zH5Peo{UU5bbz3FVLjnkx$Jw>o}Fz8^M)g_YmavtD7R6!rpHu6&`tS%eJ^V>n>$P=fyou(-1p{fmH8aueB z#`t;Xe#C7IP8dtq%j<4^l2QJCYg5HEj+v%hJjO5^%Y+#AaNEF_r~$%;E}{KfG!1F? zuVEYG8hJ_wbm1*@pmnRrC&X;DRk+*};DHhEr>V?t3@WGcP)PY1fEtGS0if<98Ap(Q zjXN1Yp6PC|3P`CeHb>%wRLMja{*M;*yFLr``u6>##r`Q+(uAg8fkr~ zq{frjdRkW@d3x`dKF3(DKFCAJsVp=A}Da5YZ$Q*@!v`2hnVl)gy+r0@EavGVeM zl=7!e!ED0@2HK_1?_EGM4is_#?B5Rau<)(02Vg+{sC@h2D1qK5=G&wYCNkKMFO&>YL`L(E2D2uO(p2$SeFEJNXxv0wUq>-CtpuC#$IxgiE z&6^y{s=w37@GT@v!&h{8;-+7vzR`jzoj#xrs_=l{`wXP-`aJ~PA07pY?_iIqtn(H& zZ6|ac3)4vJQ+sKo&BclQ$&WsiPl_?|dod}u`*qJ3{d zDwm2L6$L}5{ zgZU4tV_o%=v;ople=R%l1@UI=!yxPNQHxOwwf?@UWcd3b4)t}Pwk2)?@muLYsXJqf zCyd8f+@g6MaBZ-F<^~MotQW%QAbI=Y2I7&1>qhx=-7)t2X=1KPp`YkPPlZ*m19gjj zU>`VOVG{3Yg$}D9r-iIi#%acS#u&dcu2PNtdE(X^ zAmTgX`COwnK%`3=YyC=7+#-!GBi%-QkS&G=2$$H%(G|XIM>JyMHvOvjJB&s8ao_79 zVGl$790;4#d`a1V!=RB8zOqGHu-R~te{QlJmbd-ER-EFj@@_|@=#pu?7u3&@aajDL z;*mi?YjaoB&wD`t(uew~eocKhvL0XbNO|&*mP`OwM3lAq4?xyK6ZbGo5byBjD_S8a zr~wJLuH}v<_ub70(U}>EktdEvoIM_$*-2k_bNdv9GWMp`y+u&jCx z0Tn*$Fzc;dKOT>zys0qPa7G257>Uu7i!plXY>b>*@++UG_V%N5V~W-i3N{he6VoH?g< zU+wJ1yyz2Sv+=~}tWVu>8jmt#sG1uYiy5VHa%3u&6p^FpfaA94%5-d+N_z z7AIp$f1|OzuYBY_rg)R;nB+5|u+-fJm4UKw3UxI=I{8)Ng`olT$0obOJ!9!}KuIU~LIw6-7)>xXgWKQDibedKde;dt%t zye7)c-JPDX6&)4UZ8kRN`ov(ht93m({lNTbx8s`PpmRrhbjU;HczSXnzI5zT+}z!a z|Lpp=b>i2*3*bA|%Yw5SvZ^Ubx z_v87o1)s)0JHmA<6#apz)A6&5PsQfeX56@TCH8OL))b(5f^lQ;=$EP3p z{!uavw9+T`Mb*#C!;%b)8Uz^Aw7zTBl0KE!i7`&np2bKzso_y$sp^tfVf%Zox~3Dk z_S^21f%IdpfpPWuscp5r*5Rwa^#{?xn9Mz_7oAWc*S+f2=*dJ%jcJ@77v}mr_hyW( zvDii?&0EJ7Vq$(){a`n?@84J7)VN|J?J++L?bqq+-}8{vV=ZT=kv~z%6D*+|$S4~! z@l+GC#_h0RFO1Ux%a7%S!%wc7o`vGc20r7Ns_q=Fp{gkT+bt{Sx@v9-}Xa}k+y?XUh{vsc6AM_fBORBTJ!eEyt zE0el7qKaaQyDc~0#zWG9+R&!@B7gP**atv&8*4dTn+D~I7-lluy~I5Xj+~?dw)1y=x8MU%tp_At(ft?1nY3a;>X|fk zO?T5y?MROakBZt<56nPaB@9iYhBY}P-cez&js6(ISbXLaJtJ*aXm*SQ_(Xo1jv?Bf z6ui(8vQY8ne5(Q-Uq9UZV31|e;#X!0^CYbYT7_vQpc=1%c7wF|WTDJUIiSI_SdvPG z*H7M2bBsiZVX4Xs=t@uX;qJUWssv0jms3*T(M)ht(t+08`hx~|xdh{du z6-YnxQ&;pe$(h{6HVYOecTey_AQxoAfb_Fp^kMoP1^KD`_bl`&{0K})eo%f?P^DAv zu6xDL{*!J4^2!2Pmkr2$K-3asTeYE)RqF7{#I(vxD;l6}Hz2;fFidyqJ4l=Ogpm+A zH{AR5(~9uikmFBS472q0=7~uz4AKxd-O6(lLZ8m@)O}o(bf8Mo*8$^h`V-bSXu4kf zXPFkVh!tpp;ZQ- ze&)fNCvszTql?}8$@q>Znqx8JI^zwmv7&suW_^|u!*cWO7s{%+q$}E;7%3=mZj!Jm zg7MY{TqTE`O%n2Gn$MWJR0OPN)wRmXb{Ju68q%Fj5KF1k1lMon9|PJ^;QQR|^dAaE zpVSH3hOGW}ddc;|9`s}Lr3dM1%l`O4)={aCUJbl!IM8;uYungw0QDy}@o6Cj!HxZ0zn&Ol(?^u|4=Nx0Pbuu${*Dc2pPN4E@0@a~5<~B-CWHHX zJF&L6>yv$cJ@DMc_#f8Z(e%0>KQw(dzP)j`7>)Nk@zJScHp2b=2bXPF`=s>!!u09* zxbnde$7^sgczu56l)o2>5%$c;Y@AVbeC9;Fp=;~r_J)nHFHSDI zjH|mlHq?D+YRM-~pP5{U=hQwgNViW+pYX{{jD!!iw*mw6qVz#;43{67J{B)dACG61 z2ZrJ|*H^UcQ9CO9bZ68Cxi8L3$C;CHabnJ|eO=qxwoYGMI2Y$9W_>F5xaxmpYb!Q% zKZ!y3De3UjCoaYP-R=0hw=j&}iCfb9?ac>1UHi#}Q(E5a#rp1Uyf}9}j*m~re|6)P z_}YWpac6te2G@Iv`~KXdw7Ez!DhZDY-+YyY`( z9}bL$$0nxZ6^y&v+wrC2m*Sb(rTA-CzoXmVz4#&N{-+kt`x}@)d;F>R@bpqVHMJ1m zzo7P-nDX^UKja#Fef7TUgM6QwP?)*X@p*;2G&!d-Z>!9^?iZg@`o!1+&dvKA zI-ZFr>w;Jz&!3KoGbg-GWVt-1G>r1XyBGlr;%=koeYK0*TyxX-4o2Ee%xvt&%9pm^*mDpEXqsZ9llQDks zSd7f_Hj0`wBdZvtQuQx$3P=D`LHZZtbLABPYJX8w$hZY1#2-J}K@xreuLr0%9OA7y zP|NJl_^a-69?N+>=d?y{KM9g=`4uCrWcs(RM%+c#rm2hF<>vt4eZWu7j`Faod)8UoAqWYtIbeN_mHGfYDq3W_7 zjIrbLpXf>^H$x2HZPh)C4YnF&_B9arkFI1=!5<>Z7R_p~MXWZFgH{D#qhL1>~fO9BLlSbcf{84#!~3O?Xpx653z1 z&1alM$E|XBz?A$3Ap=y%{_nV?QIY%@gQ#cfH&2h+AX)cd(nw2tIJ_|9yKaO4eJ}T6 zaxawr>AI*i>m|$Nej+6QG?4oAtc3JM?vK)#O8+p5&%TDcp~#a~KGVnTc;Zc~yGd8n z`?M|eLkeKaO_+8Z?_Y^hhfUiF#rC(+01T52Uhjk8>eG*@CBwn#9D;4XhCc)jO(#Ko z<7~;>Z9NRyWpCFL(8pItTQ&?b-1izhw%&h8<@jE#zoV$s*Y^(TYlniuKW>y^;A`ZM zH;lz+KK_f%#6iO(8dL#oSrZ1DLWN<$p9aRH$npju!)rlVULOQ%lm-2ys*nlYgKfpk z%Q^^~7Dd>03z8)-crToUc_U)|Dsn@WPtN6uDEPLal}QfF1(?_#PdW-~10htaTnrMp zZ79q%6c}`Va)X(l`I-iCNGHQ&Tu-pdFBh_|i*}txv2Jk3A zy=B;})4{SI1yYCaMX+v(=^m7~aA-j!>$~oOxege6 zb5RTRb-_5yH6hf$Z(i`{TH$8PH(cVI>jiWU0)_QB1(E;sT(kP`D>E$V zWLW`wSH7vt0dP8nExdjh8?vs@qv4@)Tb9_$%Y55i*dCQ%%1NVd>=814+eoXnz+gKE z!Xv|PJi5~uZbyX5DW70xgM^I`ps*U+}+UFrucL@#1jy9ar_g-5mA;L%`!T9}rlx1CWtqkZUtY~?Xr)&+CM9TvqfFQWihqxq zC$cHfuDMd{P2#RwjW42kjS$w?q1|SBGTe3J$JMIha5`~ZbH~n&yRrM`wdipASW|+Z zK+&|&x6zeU|Gjd66b2NZ^MS`wr~*%`Ud}AX$dhNHvpnlpG0rNT{dca$-o2F=TUv_A zr=HZbf|2%__?v5&ZIJzi*^BXWa~I+(Tesu#-bVcB^jRB({$Tr#`z%J%Z|>ZWuWsLs zmHi!m2liiCcp>iXZ^yTHR%}T6tBcS38>&x_&BssAUWgx?KIeVg*SA-Edi77wo{t}$ zITydZaU*W-Zpr;boKd`QZrqKh6z5-FdLeF0{?hinI5j#G|NP>I{C!kT4|2j1gYK8t zZ^g}>&A6j*eEX8ke@-9%{Nknf^4d+OMc6+h_wTRXw9)XRlgH!9iG}!wEAPb5E?kUH zPoInjdpq&k)=GRr<$6Yb7_KPOvh?9Z;agj)HUeYBdvd|$)C)Ewo*bWw8{6yg z_Qq;_YVKsbx$!{#q!XW=J#FLSKe+RD+}_!UFDUG%=T60M-Mbo}0MI}$znM7|f8q4= zaePd5wR$I3c6Z{hp8IILz5XDsZ?48il+VBZ#3$lc?_RdS`RS>}IHUZ3_0DDGwGo^Q z#bEgS^m6>m=RdCHNhiMf;C4*t!uX_gxG*tmWA4T2c^kGdguc14qO{jyL-mBQ`KjrJ z_^A_5#j4!@==R$-pr)aQQ`bMRd``=vjtz~3Jux{GfA_}g(s89+2SQGC{^ZF^F*`aQ zuPKjjuH3fajPU~Mlfk;cf9&{$I6F1#IL9ZZ<6{da;~(F7Cr*gxyR?gAlkvj}1OH!L zdC8|yf8q2q@pEUMi634*AD@#hoUokKg#W_)@tD@dk0EkO?%QgsKe%_p`7NuT{M^Z> z;<=fn_|;pN1sf{OqZx;%DXm%IZD0G3ELvj$Mp@bnBgXapqY3#IXyp zth|5y?iCxVfA-|lz64)V8(mfVQa|U$=i(=hKWRhpFRR|ZcK=pzB9?l?NHozMi!Z58 zcxCUs?d`ZUwGe;t+zav9`BSklHWANEFS?&Rp*H#lx892X?S=1)fBNKe@ub4dD9@ih zeo5(R?IXmH{8!X3zOZoC{%3#2_0?B`+Ppc5YSbbw*WrBsk2N^25pLh_dk;k8 zAM3g^r(){N$rzi{JfN|ValSc4OFtC#DO&hGET_nMn1k_jO!YLO_4<_Ns>$`;Soz&= zM2F3MET)XPtmSi^&bpnoK7CaGWgM!0w7$17k*_oAb@vctXxWmBC` zoH`K`r%!5aJEQD0$B>@OQIcVrQp(bqH<`^y@+ES z6Z`!!&~gpzX}sUnb+o&s`C)52_QWUdLnYta+?3y@DX*d4gEz|0VHI~vILFs>-^7Uz7 zwd=l-H&hfXhUy+Vh7Gcy8jyU+iw?^IhcyTWS{}OPUXFF5*LI-70OkiUJC6xBc2Ed8T8m za;UM&+d5zr!w+3-R8s_W#-K+T*HtdRjX;>ML(XxDYt4=AkwUzPX`-Cu-^eR(ca7sc z4Y0~7gK3q!!$2h@%phhNy!Ro58YOGWD0do{+nD2k%OR@&`ZENOOOG}nO0?cWB~|KE z4EbV&%vVigsHKnCFeyKDvmV5+=>VidpZ0oM*Shy!)Q`PK#QdeY%YAs)A#o~ZTC^uf zUvygvp+32-fUYxPvq#^Glf3H*|HK;JGI+v?W_`EQMdrOIsLfh2#sB zS3&Xm@72#hI{@i72zf0Z2Cl+KgaLdbIs}HrJuJD0=F|3rPj{O?1P&`Z{iqG;9t__O zHyCFS+WzhGJSyJ11=1zy#7Dvhq{mU=gQ|xQ8V+=`BlNpr@GhbpfTLWGf5c%dK8=x9 zorM7|J9l>WwyX(*A6Vto5fg#2-mK)ty(^GF5K#}_8m(ElG*mb^F*bR%8o`1nN@!3A?rV(;giYm9{@ND(tjL0B2dmmyIV51L%Uvu z)OEHOhVwM6qa*!?1p*VipT=UrBjhGF7Y*6pyttEl*n~a|tW)J53o=qGKGZz2LvR>m zzp#IcABKOZK>n$NsQb^uU?6-SpOi#I?OiD_Sk^u#;o1V+$yVO93j1W4p9Ph|R=0V6 z6t3-O7MgquoFu|Q4*_!bb+GpF_PFE+5;UIB-&qin7Gox3sZqR$DK|)b2ZS3azB3E& z?}0$&-jIA#Hw1+9HK6pMjLBRpey~Bj$7S-V`jThriAbawchM8WrN>k0h&<~6OZu8H?^zG2DhkJiU&+gQwohYsn-V>-xlPIc;0>0^51_l?}Z_RhRrV zdgE?nI6J!6EVAORywReD4mc~|5|W=N8&f6iBck)|M?|PzV8Fi#KM1WbfJx!2j9fe!acr)PK?*#&HxixeccOdkZUm>MG!!;Z zf#=$jb%WOh)m`hs;0ogcgfFCwHKKJ>cw}laCNR>@OqU@w>(TlZD27>cg&GxZkO!Ku zq|=hSa@sw%aQ@AoN^=w0Nh86HNZ4#lBZJEA4QsKSejMA{kDaTxWAB|C(PgvIC%7~) z2hKfW9^SG zJQ3egJYK_#0q}Po+>BS&@B1~xPfgCpb5lz`1xdK$KIyuvseCUs75>MUF2r}%?%B9? zYJ58W%j>Vi<;~T2TZo~Q)0|(vcRl{}u_tXX{mpyV;&<=g@GFJCuz1#|aG#!BjK$H3 z_!~D=SL+Y_%H5C8ov_jH*KWTPADUkBw_m@uayx$Q&egcRwHY6pU5=}p>*ZC&%Je|%jEu+Mx&C_Wux3{sQ5Vms92h+Ro2#$J%Mb3w<+TUymp^j+Lj3(} zZ^U_(mD7}8zpwJI-uG$GJvQ+a|Ea0P_^C5byUza6jd$Ye`kMPG26FuV)Cu(m`CZ#s zji+apY^41=S6`2}R?D|yd6hBk|1)QvalgK@zUn^lQztIP4=$av@o-v`_f3`QS(WYi z`D1Z@dOprg&gnAh#=rB@@5G1akH@8%1>s_xo|=u{zH=>p<@#l}$@edxiHoy~F4y0< z@=E--@4OOkt*ylQnfW-Su>ZH0e>eX6+b_j8?%$48t=G_rYi@04H?Aws?cF^a95L$N z+}N-Y^Lgn(J^cFZtMT&6J=f_+IYtH#HyMT)7ipy?fKfB#((&4jxy3`)8l{uno>{s_ijgQ_jDC>&^I2E`P)Q z5JUBI(&d`c{in`+NLTAfe0}wHyehwost*jsH#aw8PJM_I&A)cYWRlQBNegD3LTSm;^%VGW36Rv zEMo+eyg0c%p?06x-jA`>t$6U&Z%2oFS~AP^y4yzRhby(VS3CO?DfuA0#v|+Qf(YBX zgXlgx5o1qXi23KAjfD&6bxS=SJGXDfeb8-D_VMQB3jqvHt@_-nf zE03RP!BPh$JgOvRK5AqlcDqhm;cFe0xl3~KMJ|W>P}U*gsiSn`$AbdQZ%zGWAI~;! z!WK%pMIZeL`{q#bu9fNr(Ajz$YS_a0m;Cp24ec^!ZEeNAu)DP#UA0|zyYiL^8(HP? z)3}$|*^wN6PpCPp%js9$S9EpXF?M`D#!k$~$g$ao#YxHJu^?R1y~*;7F6g-!1;vl} zUZvcp#I!mE`)AD4JanMJv#SAu&$jpzFT(ts3)6flF!kW#)gSsxrLI6435r`%bsjD? zzqK1grmP#ca9?5kU0KDcW>+;?G0t*w7~?D_iNVr#qAI^1K5!qeh+^)rVz^G(Lt;PB z_h{4Q-i>=X!X*MO+yGdlpA45+ehMX9?wxsEFs}#p=~?c%xke?offgz~ZI}|KflI7W z&O#+~U#zk=roaAs;pAby6|N66OiSi#0NUbH-qtCRAqYPk%@mNb=J&iIDt34bBDr`E7XcHGdI!%@3DOvPG@6^k$@kKWw22k^&eq)$0Pikfx zxXc5HUZhPvO<6#(24vOYFwlxX9Xonu6mLVM9PCfFPtw{@s?5AUPMjJ~q@?Gc+MiVi z?6vs8arI;NlzGU;Z(6H*7!;?SKV<>QgZ#*!{_58X%boi_X+UKzv4K@Q^^~-Y)RXHE zUTG_drY^Hy6K!-=xHP;bKMb3Al!e)X7G{gWB`s8;$u9`!g`AAy z>AE}-#$wfJD=+xmoNu4VMbXE1O&|-NRoEwh#FAC8wbs!DW_ktNz*+mTQ z@Pqh1!v~b?!yyZ(jN5rPfEfb{IP}I*LwgKluQ9pes*>@dkrjVh?PeKYSWP7x!$D`tWPwmy0uYhz5 zQ~8G^-u7?WvpD-Bmh5i)%K~@9Soe zZ^!V&E;olfy~_!KoA(Rez87&v?z_T!s|q83jJSMzi}4>L1P?v%O1FI2rd>X+B~aNG zorNr%S-^uH_Z6_I%ZC6}(e9H;OXZX_60;r~Drm=RP(L|;w6PrqFjZRVHl!O0sw~a! zQsvn-Zz;@+Gfd>FL-&FaTvzVZiI(@suAS8Hg0 z^KfjmSGB}dScYEeQ!eE#4<9 z{SE23x#7H@A76-1&YbWG)SH`Y@%h=)N_#op+K`UQb4+=Y#^tq@c%XP!S65<1W#qNE zQ~T6;H(p!47vH{rJ8rD4#m*M5-t5Mw=TF5G6LU5we&g<~*xcOFHKjg6f1xkIt9;ki z*W&VnmAJjS7I)Uy|Ni$=pdoi@zeXGe%yYc*9W-J9rx>ihPraqpXgI>t*`ij1;!lu|AwxouiUvFzj5eqx%$bf*2|#!VQk2a zA=GmoIWjsa!89hQ9!GV}jH&L&xbD5dtv*OyR`ggP|1u_&aUuC8oMceqZm(^Y@tQTd zU%L#lH=yxiN^8!^sj_ybKU;6Lt?DM!9-;aP`nvjr%flR~_OQ;J7@nGmkz>bW=E8-T zzjz_0j%mG0o2h?~sh@G}a-I6Y9qU{#x#wzF2z} zarJBB7924WK6%Nl2YPCqu4|`b!z%{ZmJzn?9z^xK1E{&Gt3GVB(U!iVd1qAP_O!J+J!_jYSuaM_f3j$whP6nc3*-9;AD6D!Qj^9$7Shr`F6xxw|e-t z-0w(!U14r1Ec)|(a?0aV&PpqhI*?cFDqpQ#icuIIO52GlSc5q(&_;u@Y^U@S@tW7` z>_qw|v=z@-!#8a&N*dWWn)F)XK)a!p&p7mr?2qg(fj;0;Wl#*c2TQQ zS>=IYVcso}OoKJu1_%8I5I7JgJ%+%run)t81M-$%!eE%hKMp`QJPZ#7%6?Q#X!Cyp z!$7Mcjcy*ip~=gKx=VQzMmWgl;0`iyCfbdk($V-@22oJ0Ox$*7_Qs4bsZWqfF18=} zseFQ0$x!_eC*xxv#dyjIR*amyf)YciPc&&o$tforW--b_h0Vz)paihTXbOt6L{4hH5l0AnmBUGh+}*2Rz% zfN#71IDpFIn;TL0Jz;xMk&6iyzB!?@sDwwBebRkV6(_b6 zI2G_7#K(aH@%1w(`(6NF-)&_o-(I-%b!+-WpWwYgrsc`Du%>OkO@X#QknUmF2P%{0 zwQSB)NWaXnm5mAC(6M0N)=dXb;R^FatZ(iVj&T;=PweW(=*|P(AnAt42roni@?D&} zx>4e(UJSUzVKHvwDmqZz=p;-kS%cOOl!Lh;$9`|3kcN2IBba5YbP$}pe%jc`VU&i) zx5NRc!F%B=ZEl<^-*+S3^6!Io`s7<#s8KSH?TIR<=K$fj$~__Xq;N`ZO(`*}0eW5o z^^(SJjJ78uRQ!&E&FCT2vzrXFq!zj5yP25~lSl@IjT{icO z@Ku&!jHsnVp@3=02i_aR4%Z34!ZOoCca533p^VJbc_zv&UD?R)ZG;zD8@n2}+Z*GV zp53HV<9VYWUh{?HcvG+!wrp~j_|{GSBSITzSU)lEu$E%&L;+pyii%pg34Ty8D@C$q z?5+L~kToo0sMfb#p8n^_f60i6k%|+m1=N=CIX{Wgw>Yhe5jN|L@0jkZ4jG!Mdy;m% zJ@pMCC+jAqBeGrb7>e%fY{mWEEiDoEeNyz=mgZ0Dg1m$nWH&J0)cV;~9E`fOCnr<+ z<}2Yi9g4B^*3O2FUKq=GmWQc(o$`x|$!#MRAJe`}R*xl#_+ zuzQ3-AH~^M*pBecwFj}riIuuZHNH1uV-NXUU0?O9eSduEqF*=s%F5liv$+v3%q+(b zE}V;R-n$hyIaR8-e$I$^%4b~50CeWmr1h14w>CE7p4J<7gYxIq!x(}0Rc5|UgF*ruvi{eW-WEU*Fu0S5&rp+gtIOV`t(gR9~N*Jry5Qz3^)0 zpE~uF_50eLTXA)j@7Sszjf}>L(J4Qyz&B@k4e_q75&AXPmS5#8MA!RDmy^7FKbZc) z>$Y#MZ^W+d-+1U?oAFA;MaO%p-*?p4IbF`{pWo5-fnoU%?%ePzof$_K$0y_4t9Na@ z_w}W227LX&t@zH$t+=i0VORZdUuiSuE=@?!`QveBayst6@p{~U>7`hE`IXqYaZPz* zuoh~aWW)%~X)qpQv~iQRt78tC+fb@C9;kj+zGEw7oWw}0bvXuF>Yx5={e;B;Tk4x} zxfo}`VyMmW+UPJE52gQx>YG=Ad!Y0KltLS7g}i=wW?E}ctuy%^`m}gnTg;vTE=qY)XFmV|t>tq1qGfK%JcV)- z&i;K^baGtBEAl36OXm6$^&C~P$jdxvRDbKutMUU?-sbhkpk!V@i1!-SsA~Y(Al0OU zU$YMLVYQZF^ET7AMt5;Fl(%J3ktoxsm8Bj7E1^VNPPK)ji6S$0MFO74f07 z5g$HR=u;<)aaUowOPtIdb=rI5nyWCrY7*HuR<|aZJq_?S%3^HQ{R&3e9pSFJ+}a%5U3b*uP92e_+<#gCYWL%r312`Bq zk@OnBN=e^X{o!>j_v8xbYf3V%HRgq+jH}5rmKnukurm`96yYzAnvOQbLD=-WsUc5-zkWp^-2wYlRXbkDocTtT^oN#R)qJJ_Z^Mb zH%WQX|=BIHltdko%f zqx?x@9tE^AQ$^*%1@yqzLc8Uki(OCb13UwJGq7s(O!Ocx^q@*Q%2C9Six)P}FmT$K zsmX~~cyd$W&2@zX*&xr&dWj8|RUSFv(pZX76yqwVTWzG(BFx_m6rIzelvkU8X_Un% zYJ(|Zi9=kap@pG0;ccK*`rh?vp>;zJO?h<_7V7v_22G=_vMPK_rmXug!$XbYowlg{ zou4bT<_k8Eet(3aT^@?!K3V%+_Bj>^Jjs=>F7azjs+(7Kv|nSw1n)jeS~WfW4^-UI z!0{di*&vC7Feo1u<^zPh{@VDx0H|SI9#gLa;U3vQ1)9Y{bsq-J;-P|_gL$U=VLHpN z(Y4Yh+3NPVOFtL-W=?(Bi(vI~qir{KC)w}-<*vqBe~XHz*VVXw?U^?<+Q?>Q;dxzHIo&G#RG;3Al8XK&l>WTs z1W$R>Kj{%sKL=!OIkX_8CqD`jsn1=p@OTgRABH7NY2snf7(QEZK4?sxQ@1R~VW=OW z`dh;vj+E!9Wh!9_THL+-N?!Q4b?Bwr(Ds@wv0;DrQuTNB zV@{>;Py(-7?`qB0@9L@Oha0Xv>o#fRr4yRd`PFHmB!j;li7$qLh=)iNN;b3?@Ip$XqyVpp#rW#)1J?R7l8&6TLt})ntepD%+Ujke@_cno>8)HB zz30=k>zbcIjKRwzlW`&@V|H&e#;Mb4Y_!3KGPz9(ax(P){m!?2Dw5NRyy}&9;pE}# ztM}tu_wU5--Mtwv-@mIaO55$nuJqu+1HLbNGB}w!64zEA#EtdU__zsyDdYmAAMd`e8|Gt(Ld;V7K#nCy(y*M^!eQj`7c) ze17R%d~xY~oE({oF?EfywpRIS|DkN|gNhH$vhod6zCZf4+c)C#$Iiv4m(SSP`HwHZ zRSdMXepc5veM0!`sMn{eVaZtH8y6W?7#Yl89#CE zQoQ!yUi|u%x8t1^tuK`)hSEQyy8AO{pNl_t{zLJx#gl$D^)J8kX1t;L<3R_?g$_$& zlW|LR^+4@wU8x7gBi6KB%ZwkAb#))NuX{M^mNYPO|Msn`inkS4R&-6M5Av#O=74YA zzwHMPTu-DSSeKtq)~Z~b&R*SEkFDM9`0$DI@iQO&eEh_P7h?6L@5I_Sz7gB6z8W3X zXKZaq2kC+Fhj}1RzA?672%W+Js)g9Xl2Ge5jG>%fTWXB%l5)I{l5YM*j?Uj5P6 zMH!d#ng`3+Qu=U%j1^o%v2np4m*sBCioe$@%s=`qYnL{b@DSp9T~g6>|^57{Rp2q2F9kLIK*L{tz(=^m#plusz-ENh7ZGfA4 z5>Ve<&zwL9G1%HjD|u7Dj{}O=z78|K^HI87Um)vH!2MOaxi2a#!6hoqi4N6mS#>vl zgYM)j4#sghVw9D6t_9rY6Y*~$W6vNDH7cU7PhpNv%r!=(g~3)+oRO2ZoRYn-Hsgfq z)fF2{yKml(?i)8EUcDai%C(4>uM~U34F*4S53U&OHJI#cnNlglt<%yK?xa;n>~M_W$iGE^HBF75f7AEC zsuK@FDR{38awl*12LzAGBkMkK81#in8Q7M$G5y=9pEkOUAA)UvAZbGSwZ(^qd7tnA z3<=Z5w*Q~N_Yl;!c`W=BI0}r#$6okFcX%e@_JC);%8e30k>#MD7d_y~1S&*^xJ_Yl zk>q$10j5N1(ezIpGHeF3pgJI))WrCe#KL^VvA+YGywImuwIE|t$lrk#?^hKIF@QQr zrH!6x9I>Gy7lD#{5+yIC=Y^Nzrcs&rpqxD_hD91-+F{!USBC>BaLp%gCcJSb%n6JI zQd2+46Zv8ADF5$KaGeykpQ_CE(~pfj)ssn^KFXrOui((4iOoeDrQ}XyZBF*oovP4v z2|g}lyhQ6!b!q5BfE%lfLj1;Y2tqz6a2DiI(fL8&Z>VWM3J=TM`au(MC#Edxm7fIs zTkZ^>(8RAoyAzA3=U0F17BWWl$y(5)0j3)|z-)?n;n&nNH1%16{l-)CN`Zq)eV4Ks8*uy+HI-cz-9esi)#*!-!CX>unwpJvXTA zvb(sd#O{8`bc}YCu;sUaQy54)`2)z$L*SqW{qYkHPbO2SI`<(^bo*{XUw%i-ywR98 zg${vs+ddWy#-k5XFB0QZd{cvz_uLP|{2P=zO|j7OZ8I^ouXjX8bS-p8IOVt*d%J7i zMC?9&Cb}o*%e4jY?JAy(zkH)?%B<_UurZ^KkszlN8S_@xU{Wv{tioYAVJT7h`;E+{+7O_>X98#e7R?EUUkiBa;GLeq9gcdLv%VQR_lt^H2r; z1s%b>!!t%(Mcjqj&3dw~8yOzT=^ers>hR)y;#clbh38b)7#rgoyRq};mDs*Ze31~O)Hyje0%ervwE(6C-wH;W?b1?i%-p* zh|kTOj?c}W_BU+*yL)fMPc1zeKQwnPeq!N?`0VT{zbg5w>$jBFR4j~4#J$~Zzp8aq z<>4Ec$3`b(P3`{X#sim=*SAiq{I9LwkKccAGk*H`rTD>xvp%)@>A6#Jb#pDgwsOm- zDnFvIf9~{iK9z~_m)9k4Vl+}ZoDTijQ_sXV@87lo%IzTB(;ENQ)<#T?jK#v(Wc<># zH{#~Tdi>~#3-Pn3pNh{fosBP@x)i^4>#7Z9yjJ<#ft9&U-GMTU%7WjU2{LCN5^A%Vmf~5%IiMiNL=#xSDyX8_|)R*_~|oGYpJ{wfBWrM z{QBS@Q~Z||_nik1tQR`}(5WZ<3fkYgaWyWluEdX?c`}}vUGgc$C#L7(%=CQx+LgEC z*|}wxfmaFNSY3+=tvkN&_*uV_c~jTfvB~N9z7uES&gP~rJ9Q!zAHy@R_O%g8*irx6 z)w%_P{a^afC*lWAo{t|rdnry%&cuK5ov+6g^^K1%pLE}QNAY;ov-@JjOVaCSpZZW7 zpPr42^NaD!;&Pmrnu*(+8}Z+~`knZHDUEO5x*2Du=Ho}6cv4}O9PZi0V{v9?PD`iV z_y=#l5&zNGe=ojr{hIaT`pULS#LY?V=a-Jh+1dGc^TGZ2&%gOqp9qm~Aj0^J% z@#X7R6pDS00}_bvBMot1Msts$W}7TAb46vjbl|e=$C+cvHF-uB!fDzI~@G zCsdE0J#{Yr^o6J6Lkq{_De3&&(lIXuIPp8DYvl6EO59oBa6T7j7vdw!C*n8Wxg2lY zyB{A_nm_;KbMd*8=i+BY=f)>&Tz*S!dPVt^ThOlC>Bic+PnUn}_^Eh7_59)GgszMlTlXDAkZe~9I!y&s~b;<0s><-FYQK`G?97qgrqA9X>XNb=`ZRr7^)LOfk-a>bK>! z!pJoadhH2nJOe$}3G3Q#=KPtMSYFaRHR`bnz>7ZP)0B*xxJAs@ahmZbPmlUUKKHAu zTe14aJJG#*TVa$3<~`Q)%xg-|(pRSxu1c1A_9QIk9=llh9)sqlqn8Ba?e>g7dc*?yDB=4)4(9CK&sE2Eb?=+=1Z70e&MO!7M znwvRKQ2dl94)$@1XM^^KC%jR~YHa3J`2GX~`#nuO0Gd32pP(eqxp&N3;>`qksQo zouaSxv`0_xygupg=WKbdaj4H=*U;`FNhrZH&do>YG8lQ$it zfzuDy5J%Wf!!+{{rX1+wRY1ohOhu|j_rKm z2}jwe2Oh#4dNod z4Jypt_2{NQYkj@}4E2dv)xBTKD}^v5%NaY;mDd)lX^N3qe)tp42S0?g8E?OMp#0Fi zp~_=b=x^_;T+HE=6KL;CR?^g+>rB{;JMvT1@{pMr`UwY3s4t%+6*6|YK1oMNq8{Is zPwp+Z4<&*5fGYW?4lu-b8c^JFFcy-Z_f3WD8*y*MT!@ZsL#fBdM5SS!NJq%LByqti zYurOH<2z0Gq!od|u<-n(yp6qrzI(`aI|{V(C7SsG$o2+-cKR6}n*1gtDdn~6#^jk4a@2E`*wc^YvE?+rG^Mtlj`Oivzb=i@s~f zx=vbQu$}FO7E!tO9tMPcPl~-iFjzkiQ~Ui^m%Oq+^dT}(yn&2`?K;P^?d}UNNOy*@ zJNb$pD_WRiN9KhaFb}Ob7|*g+I50PN=-b)988^9^ZN@Ljd~>OBhi_IdFNhcAI$+$| z)Xl;@-Kad!jSFKIV?>UdMmjqAC{1tB=vwiZDLMr&WK)M51#Uk0RxKxRNym$IMfdem z6ZG{cmJN5tw^^mhX22=wb^2JuvAOb44F10PhbnvxkYk#Am^g;Q|b)Jx+guS znv5BbUCY!G@cuP|e`_ zW}ISfG)l-g*31jITYibOq2~(5Joz!^WnR946poL_h~}~p^@mZldodx6C>VhV$4})& zvP3qxIjthe@J+l5_N|*G`0?sVq{T#)sTHm{WpG63A1)8ZJ1nKXXa_*P>N5`y^WBHO zVc(9U*Asv-_Pvy8(3qRK7x}@IZTJ_Ia7WX%KNaaaca=0I(FPx9=XP@)8)w&v&=zF6(>fu*cV*hu(6CIw=zs)9#t`pVpIrA8b?qY1MSQcPsD`Qh+U0CBW$GT8sj?Sy6Xx@ z7@z8xkIj=YziYn8MwkPjjL)nU?apv2tKx%f(v&!&)P;2OcU{Go%Prk1k7Vdh-Qve3 z=e_~ov=ikn8{2-hrRrq+)=F%C};kA@#)>U51=xT{91S|p+i$deB{X(`IOq~>9f&Arm<-5?ndnW#+PIFoog}i?6WcdneU6P=B!W5 zor-U6-c>TAHpr6GwcQQVljBo1YOQs4ZESsZYBA1^&!{+^xVpU&@9eC_bJL4)d~8}O zjKsF&d}EeZ950Mb*oevZG4J!5NWrnOshE*$yR#Q}cQp^HUO3f>q3Zt5c5LqN#&fgF z{04~Ld^E^E{ zX9L=|R_?^C>hQ@~>8-pu8A=*&tv&Gfa>v!Er>17&xrJl8RoaV}9^8vtlxKW0UR*pL zuglG=VkcCm$0w&_S@@FD&0o5ITk*SbZf;)Xo%HG2uiU(@DNEOyfY%2vPff+8`6Vs&$8}lm`!&38Jy4%i znDd+%RJHL6U0xkb{pHwkTsnO8#3?Otc-gM{y#6p&V@$-Te0_aQm;GKWQGd(FM5i6M zqsG{mPTOkVJ6l_Eb!}Bst=3Z&+*E>+OAnq}T8`7Rb2dtT>-J5jL%z=}FUOhL`M9U` z*{k>N>Qd>%shPRBu&}6G)QR}*t5c7j=)A5N@XH2iJtvSw(jdkZcuR6Z4 zxD+R5W)x>%ZMzfm>L(aeHJ3s)Gp)*4I{7;_ElA$BNQ9H8~@l7UJbQH+=&6{L-;Fzqk-P>Kk9V z^0tQ5eJyp>N0rYx)#K}HE1|0^IvN*`VSJZv7`lJ|uF_LKpOVfeY=Hm9r`S{(@wV2cZJg$4|jc>jY_rLs23aN2TrQKEwdlO#; zr#mvXsb4hX8y%pIy&j)g=dwm;d>c`uiTybK1K$_3FFq5U`Kj2{0=lDdusjH-6ol@p z!mdzU1^SJ8tMa1FMmr<^rf~PxgSh?WuSWOfx2225U@TeIOUO73MOWr7&}#Nlbq3zl z7sFhV`f?AAj1!e7)XpEi5M$4t(;U=^ov(jACUq|{|NOHt`P9Ye%uUBOx+!|mpM;f$ z6Gz$)T?ML3zzR4@$g-}f4uhC-83;;xy?6pSoL!BFpVySQjq)eH`hD{d678jS%ZDp4 z?)ro>^&^VCvCLfx3)NcNr+D#md&?g`r%N8nk2D*1!J-#B$$`vJ82bS=oI;t$*vz-m zw{`99tgCl$|He3@zG`fMbZTTOtyEl(QvF5+pg+=<>K<;-c`>JTKX&O<#4~3jo;blE zB7gZcZvm?Ddzuz-SwP7#zED4`jkw?7z60YGhA&PKuBqdJte*(0xxsynYr{M;rP-i< zIOyO#G3ldmzKq-Cp|rPmqszl_7{GW~*bmAn{oJ=X&;~UwKsv4`@szKwn@WF|10(UG z?n_V1M4VCGoLwp>g_k6ok*-|7JOoQRa+;DhWvE#g%;Se#4(lUI-!he)>ylUH^19zE zcgrhxIibm^Oz-C@5(Y#1A=fW)ofcGXr!Rman+pk0TL1MenYJ4##a!KBh}aC{hq?0bVSEG#f69~z7_4~hRl!FM~q zKY{OEc(>Q%A0Zft|H+@_jAx?W>bUo%t_OeCHX543>iG7=hqyI;%*Eb zpky{2D?D+Tm|adKjDgfo?p0mVP>Z3D#UpiNBkh#Z6#6uq(#i#cfwYtk3nkLV&y&5v zVH^Q-fkG#1;t41pI#6cUMMb}+wCaPAmPwOvIdO|LcmS05A4Q;kC=hi-5pY7OJ0tZe zfj0na-Lmj^y(%32#C559!)QUB)*G?1Aco3KI1l`a)q7^b@GvcmhNGWq0yY#!7P)cpi^Ath5`-vCb7fpBgA#*c8r+%>%eh+pD>OkJ{( zHP<>Qx%;yiFZ^*=p1#b&KF2bDSDWz$Ua~aOaucwm8_ap#6wv3n3E?Ek%BoNcY`$Ad zf2VKf7@jw7+`!~Gls6w9zvagGz%{{m!_%VB<_4jr&A zT3K%L zwzj?CQB_sE%Z6@Y(YF{A3&=w}Zl{Xe*SYAJ`kjWJPKR%SuEfsBT1=RGK*u;blseTB8H6zztZdm&IQ~AioYLM`2CpFe{dTVTZKQ^!3 zj;*i06#F+;G@ejDQesz$*+@&B37H$bM#o>2>zA}$H=rDz(?qpo_6D-1E*oh-`E0?9 zC(1k`edg|M#@_$<<=DA;BPO1EE@nUR@z_^dJj22`PbU-t=U%sbmlwJ7a2S{Z|3CKrbVsrz z$@j$6%zO`zEi)oBYp>hY+wEm8mrG*6I|RW2<|7|~Z^DoDAbbDsT~6%$^Nui2U?VT~`|Z5!H3CeAIH~fAfpKDF6QBAC~{)ul}P? zwPHm7H@EMWfBWG*=`t<ii#rop(SF|jRK$1k3iC;#{>&42SU{n?Mo z@~{4+oZdQA*sLtSepX)nxBpmP{eS+xlqb>$Hs-aet>#k-T5~5e++2&~GI6sJj zKkLL%x%EH&n{xPX|FleQACwom2wN&H^EVPm&)XHOzkXU@lkUWzpE4YMl2+@|;>(BS zoB#X&t1N&2Pzf{#W2E&1MM~%E!=QPcuK!vw0mx_WkM+g+GT(Bafl-Rr-`?IU(?9(| z+4}Pzm+76oa`dbJp-eyjs_gybCuR5NKPl7OhvifG-?cAug97F#k>5fJk^DHA@x}A`{j0haax~tRUG0ml;q}h%Jnoq z6xqr}=<8=8#&hR|8^CQnC@&uVF<956D{rOY#QeORoSc-Sms;zD%OhR4^Pq`^2wS2= zfsLw!g&RtnCejyaU)q+>uH2COgM(6j^g$^<|EQFo-mk9|W*w#vGo1K;7>|74A?nXeiSj_G>xF(TL?_D(xwV3-oBL4iUEwWXX_*f=5b;uj&lo)WH|)RJ zNQ*v!h_gt92SuLCB&SrUV^j`be+V(sV!Xbq`)IzsixK;yL%CH?7_fO2w1R8>AWzhC zMVwax9zyG&A83v}%7dPq(&QTRk=mBm=<+>PzIpl$#%Gl$zh%leCVopVbX}$V$Ria9 zvI?_n1zFE$XeEtFcjjdXnqld^iX2qHHL%-Oey(@?aEnrZac$b_(&0T%Tp|Z=kSz4U zX|MDT$h?elBPVIfAk1?gvLO5<$e*B$6LauDhIJS9J|k{WfrLXHCJNd}s(yo!RP($I zq<7Vy{D3-fk&PamF05_dYZhfZv7d{Pmeaw#k(P%b(n#yRp?m>|^OtbuZ~8P3$n(l@ z=PyJbbaPppN`L}N43S9pGu93A=VWkiq@~Z2cQeuoy%!|RKI(poTx5oBR|ThsHYTWG zAhLIi<3t$VgEVJ6Re34{sD%Uc zVi&wCTbS}vzU7Fr0GL|Z3Y-j?!dytbDI~-&Y~vk>f1o#xM02qfsSCaMY;-R;!d{=u zn~Tdda&VD}+j2k&N;yX2>xaBrzM`!z0{b-1S43Gh0s087o5F|-ZUkh02O;Ys z)wero@YyG_zi=UMgRHPWRc3>>;<$f;q!mJ2hdJpMlXX^MZ0Q5<` z2>Q6|@G{`IUF38_bKC-56g$qi*TfshO+MpwVdLs|ze~iOehv*0`ay=}bbL6?d+dw% zoG2#eB+nNySNLLFeo)VAx*^~J5fGjYfBH0iKaFzv00;9JeLVX;`n4Mq!WcJ-3lfeW zaeVV2IXPzVL(aI264T~#-!Mp@ecm##S0>xr%7zF6>mXD%jpl2f61f4ffh73U-E%Q= zpnF zx4$Ushc^O+e)vgso(2%&?Bw3PvUQ}@W%8}3l~adL95HO${b#9xRTLzBOUm@>3h)~OR&mHPXNxFa2T zS9hhZUs2@ERad<7w#vbu{8SXVPZbWWC%8z9{6PDWE@V1w#d@-9fK2f1ddD$9Fk-u6Y0Pi?6It)w{|?#}kZ-($O-7z2PLwXdUbh9oL}a5Z`IV z2j(}89Z$6B9C@_v99Yu}ds!(v(Dg9z@AB_y$_ZS^kG7s;z$AT#wY}$l{c=r*uIMz3 z*UTJ~CwkM?hrzrFu)`NiG4<-hs$KbPM;eB|#R zdn`z1mK8VOT;_Ycub#auC(mA#rC$??5k}Xn`PPpf^Zt!;YM!S4G4k^o`R$pmEtx#6 zd)1Zl`=q4%YDL1P!Y%Pfj~|zpUw&SWH1C}J_5ynZ3Cm#w3yWecHs&1@Zo(8SacWDNs-?;+Iv z1@rLq!&_x`=Vm#5_OvX&eo!VmyJbsd;Z^s!lEQKFeAC|Ar2uK&hYe}7Llc$XJ9 z{t?GW82t{)cuzmaCvK%HtTG+$xX}9T+A2S2%HiHdZu*Mn<<8%_g`AvAnUi{CeKMt@ zy$&bxUulnd#ni6hNUzS!gEFT)7;~(Ca{Nkpsn2Hv(osm}fh|6-y;(Ogs3&Fp^g61@ zJ^G$NVHn{#;m50vG2n2zjt6IngAB_R4IPKP!VVP|keAa@ zPVPG~%wnK^{-XHQEXb!OI6aHOmN_8Wu#OSZg>I=L^$(=Zh<6@>%rE;mZkJuM{0SQI zt}_L2Kb3Wpj~n#RSLcJd)3}W9Z`oc|p3dY(4Gjp!ZH4Kma1;JoHVTJ`lvXQ$W@i;aN{k7qlT607WB)Vt9FX3F@C|Vj9DG5XcLAHqa1H-D;mo@H{exNg>%aVE zoq#nFw~OE4?d~ual!o$S(Ddj<3|^DF2b7R{%nKyn5G2a&O)jF5PBioM!XO#slM5q= zJj(@0ADHsn(?wdee8DJpVhiukHz^WjU4$vqN(;#wJjWgL9#W>EG2bze-o5H>7ic9e^Pt~F-DLkU zM!n?)2KDJQnO>Lz^TOq=L9hHJphX`jw}M{Wd3s(k+qVwck1vCc-(f=Um+^p>7Cw=m z;0+OA|HLHt+f|{L4K%lC)^Vc|mN!iFx$J+5ME1B>Ta~@|h;ybm>Z#X@U zBxF!d`GbIx*Evk-tTTFYbG}n17&9od()#sbY`Xf!Ni=Voaud!^X@-B^NP%{vgAiT% zwIG3f2XzYKhUp-62F$Ms?-9s&_Dh<6fk5wXNGfQoBUHezp?(H*9V)GgSuuDvXy8@l zbzKt$)1O^49|HhYVeQpsnMR15+>r3vq$Hv)R)!1Rb>Xdxe)z}F?utDRdb0{p09-Rv zwK(aHcmV#Ff-cQ~zZ~>g0__A#f}NLE=3MY;7-)4G(yvz9#ZdK43B9BWxd~{vjL1vo zo3Ji6BBBL1gX47io>jd;w#i1-m8e`@s#L zT=FL1qi1FLyD!Vh-~E&5SM>>XHsaecQ#yb0C?RTPggF41YjQsJgLxqS#E~wd)kwQn zwr?IPiQG*_<)y9vpbcD}EFB@0Cq^~Ug7_paWDaC*&AHk0;tDyvwldl%k;jGw=hs=lDDUP7r*;`HPYVwuHh%TI6JF8`-r{k^|oyHNkDWva4k`V~#SxfQSW3H++A>#>GsTpL~oVJlfHR2cE1 zjA09mk1H0lI$*ZR28>=U}Hsw3Br+$TL zoRITIu&`|i2g+INojFH&>cV8IId^+|N0-68usq77Fh8IXI;U|huNl#IOY_qa-?Dx5 zjZZtxe)fYh*PO%ahZmZJmVD3fQ>_a;yffFNgn`y$InenCB{rsKfoCMoSrx+z3Y;F7 zxvtl@v=;0h-cXfEH>Gu3c#OhVIv!)@83QWARLj>?*TKuj&&$hS|5pAA!$@mGtyFq=AGJxE4NX8Ek68!R{t!2@Ae$KCjKf6KJt^>eHog2CYB{ieG2_>PNb=? zKgJzMJju=e-zeqNWRYXRmF+c8vgLB!Q}Olx9H?n{jWs7}PqjwQPfnzh8rf^5qKvQ6 zllMt&F@94V2rtACn{Qgm&k5`ZIT4D1mXme&ZVPYLlYSU;xb8l*|pK)LNFntdy;iRe%IuQDPnVV3(EU>g#M( zCSED~n1@s3nXiwfFJ|A%{^c@SSf#-lk~dXe84non?Wd7J_!tPvd)jj$Wkg&%lb0id zRh%jlq)x;nQfBuB_@vR!+13p+PV#|il%?J>JdLkL+#Px^A@j&^(UhBg%ZUEy9QvEe z?fMbs{lHXxg-_n)L-Xv*_%nEnF^$RWcL|oIpQQ8;@<%rtNriqhmc~YY)(*XhN1E0? zqR6)~SJVIi*v&~qK~(mhi}dh=+sf15q!so?V*0!j2T61pg|166D1Q3v}D01CbGFNp4U?Uj&A(UM#`L&*hiDQ9sTX5X~~OFw+ih7jzK1 zt*96I`(i?<|MM5f^TNKx(AOu_bwpuBU1pH-;})g5ec=;GpKWf!gd}pj%7);|w|@0) z2J{u2tE=Kfv~N9R-|vy4weckEA^o$AMt+h8_Pi00;1;)%=I){Q%W8HXgM#{5iwYwt z=~IU17V#$d2X#4=pv?<`-Y@}`Ad$I@IgOh~zpg!Q3ZR_u0+=s(-7!xi^NJ{6+^dt* z@6j#iY;?@R!`siElBGN>Qy2KeY4aX&NH6b*T0wDKjzoFk7DLgjgKoH&yndG_h}R*n z*f9qGIBwSA`7SPL+l@OnF1mqfb8+UWI;ze8SK-RNd=ZtdWC)R6FZb;zHH0DDF zT}bikYgdaH=^uxpESANFO4N`xgVqBi;VPjPb3xqh1+&0qg@0RVuYNW-#)?HxZD^#wI z9gMRrg#6{G-AewAvSGY1&H2WcnMQ?=uwGY-YQFUJA*W^JdZ4g+`mFM~5kA$m(@fW! zlNZP3_=~T~{F_H*$$U;dv8E6|?+M!Vsp^&2)Pj6l&##7-Kh>C(o64q@Nb}9~)q~wuyv0eZaaV=_yu#hO+%m@d|m!;zy6oZ_bW&(H_tZ&jvd1f=f=-^wl7=Alha_$j!$>-ABh$8ZaawCd|D+gYxLTJW5H zfTMVpRsGi@Wp4R_HP2>%8t@wLijzpZj6=DB5u*?)^;@*Vx-kY2zu5N^fj&9fOhg2 zt>toEs;ypq{dGBh@ubY|-!0oe`%#(Sy;&B%KG$0C)uU2A`>K?$pGl6^1RH53E5{@< z$wU7YLNBwTMg`hiKg|6YqBNiF-o9COZ{4aYGIv{EqT+Y%I=58nu_$C-;h~v@u8m** z<}=AvTwklW$phWAAgkW`TC4m#$thK{}-6z%!lX_?%)Q6_h9mFbb%>a)+wmg;-w z<}JS^f>YiY+^ddtt#FypJ+Qi~ztM5w2_sJLU;SE|E?t#Zc}_$VcU4yzzxq{omk)0A zbbh!i%{2>St@FU0NE-Pu#;bw0RvFX}*SQZ!z6e$5u?t~s!jb*~$*=q*13CJ$p?1#c z^tt5H(UjQTQ9s_ZQiJ4Ma?*f!b5CufYYU9%yi%2KQ1Woo4TT*j4n|wPPYK2E1I78l z2NgfMQ;oFTE6~;=t9}a=`d$ic!<}F@+%76*m76-EPTjfj@6r$tKgK6b6}L)n7n8ki;3wUaa;N|nBmZ@ z*8xfghrtt0--s3wE@ylS zImzpX=QDreLo=;V|Fv%5p>F}!_1Vk7nLfQqPWr!QKHo*Ss7?pL;dtG4xGKD_e6Hd9 z3Foe5-w&9TzfB{pkOjdLF(}@&bLYe?)|3I(C=4Jz*Z;370out{EUF)Ig37@ z?+Ca$QtvEJLioF=`T?^pdQ??a|A^WPclD8&}_9pd9PK zWehrY+i!#!4`^{VK^I2TkCC73XU5(iV#g|CUo?h!xF4Y);fzREc>FS_$4 zAa4kW&lA|(+~!ls@Sd-v6F0T!=JBBHt*6oe5br<;lubPayIU#oISrL_pVNZ+aS|t9 z>5dbB<}7Zoc@i3fF-F%%&q{gtw3Kgz4|J2tjp{d#D{^w->xaTe;=?b)ABqwmii}61 z+|*M>Zs^esJ;@k7a&AQ#^Z~M6+RY7oB7Q>VdRrhP4oG=H=8s$(LFVB+32dVTlrT}& ztu~iPmNE6g4-lok0M}cG%@10gwSGmLKj}gE2xm?64VvtX?{RKCue&i?b ziLdkxC;rUYa%(AEm@X1$6@74nYJy4!jJkHCPot8nf2y+Sh?j9{!xcs={s0#{%NCJq zNQMOtK=~w)r|Ft#YkV#Pt&0b&Gf=*cQFarYXH+HRN~KWb^W?oQWNC-8`#OMM);8+^ zXOAt7D>=|mL(i(Nex^3YpN&oX1dso8sxTq1I$oSSS3h2qouAwAYaRcD>D!f#^iW`frLg1v@u=-n{P->7wzKlP?4X<+d@&wOuxA@i`WS5+|i=gB@(%ch#!mM>nF6O6PEpOqyWNj3@ysW0Y5^74GIwdaNEmsb>WDu@E*+Laqe zTr0P0a3OQngx3zgEQ=RUh0mP-jp!G|iE;-|iGZ_qaL z19P)~;7{Dsm0ubG>=#(evnK8+4OsJsR`=kD>wV>>kN_hN4JrGVjUYpy?VLBxE)$1NZC@)j90^YzZTDBQXG-= z-()~_dg2ME#A#`&AK2?U(C-W?GUI$hnCAfNn;7x~SNZ9uA$~QkWk5Y9MWgMUKFXf) zvhEg|Q%+wUmy?&T%G|FqRVOE1^qUnTS7?wdc;+>(A9QWHrEAokt!+)atF{2i!_T9U zA96`!e_hY$TJ7kYFUyJkwtjH0Z2kC?a(cM0=^q)IlfHORPtrcpwdGuE1LIQDSk9M;yK8t`Pw6{ucX;Tk`ug$WaHxLrVJpz!Fv&BOKA`^i7B_}k ze-~PRbxl-5a2=ly=0cl+mRA_R&?b?AE~?n^QJ=-PmLwF?A-8fY=j-ctSC6mrkx zdr5^mO{6^o>E9`ptox5B{fY;RdEl7)+pmROhvw^!`%{X#Iw7zF)DLYKW2#-p<(O+o7;)g0Ze92Q!@utl~E*19Z;Qv_>h3ffPUDi8TETqr9P> zzm=co4#v4?L^F`oa^wLbmwd^eafe~pui_T+pg($8H^sBQLf4)AEJx@unHgLXNOL8) zOnl;?OXA9_VlY=!^$Z~9B6#CGE|bY?K+0`(6ga4;cLbUDHC)5ngsZG^-%*&AzxlWI zb;q8JMcZU7>=#R@{@dc!26qo~Q)i%WRG|9t=1eRcHqwe`F(G1Ba!&frPlyhwN9sbJ zsR!T-FY*y`vE>B{Bp>DB%^}?6E!u8K66J4$X~;kyWTOXpvhnTnS%S&>h~Bk#zrrs)zAy{`jw@Wq_+=gHi>c%{9vUeH&>IDp6?FDAaLVAc6i z0b3cPJa&hF-#-#vKY{5-+T=;&zTCsu{f5x=e~<8eoV;?pXVIX>@LyNQ>D9tF;RWD+ z0v+*&NS}E?`#GigS7I=)pNwZ@P7-bN6myJdyJ;6SipS6Lr3CX5H^Uf4ebO}M2rj14 zaWFrSMmWx!{CIUTukPXD6W(gz?*R$@>PjW<%dI4qVGK9^gEm` z5IlLG$c7Eysp2X8!`=E6zL9j2u`k4!D-ky0+ITDU>078up_@_M*tgSoi!Mv)VPl@# zL%hN$gZ+d)g)7$OG8HD+iy!~CaOG0@@TyS#2(uqQ4I_R0UJaB6-QE)n4WC0G?Xzt@Bk5a*yEZ`4fMbW~~f)Ik()DNXx=(Q5L-Fc=57K4yI-QhaZ;d&ZHcF_Gvl& z=iij&SC2H6s-NGutMRSQ{7Q*AjijO4HWnH8c|E0n&j(GX;OWokWejipfY28s?R00i zY~Ror(_F-Z2_68gJnEOo4@hJGYGYS4{0Ot3_0bRRK=d>v44%1*FqNT(hkup{|44&T zjrk3CmV0H4tDD`%TTlD771^eQ2Mt{u*8GIz)rH~L>)GOUehn3Uj2=GIv3>Jq*|~jN z%fQrQruHcXfpXTdMt%>OF!bYG!E-9(}=G|+lWiQW33>Z{xYD7E57!9x!tdm zMsGCH+hw@uHTn@XBOm? ztkzOr-`i+=GbqMKg=3)QS{|8I$)NgiKN&%W^}u-am=rQbY*2Cm zvfLxxR^8na^{Zk@r*O-PjMmjr52+9Ost6v7)Dh+NDOz3MJa}5`z-3pM=b4Bv(#p3M z!v8!yNdMO0g7RJlTA4uofQ&EdrqLe5kNP-+nN|pIclwKNOxGcC6urh5lRPl!XUVG$ z%tON;X#PsfWX^txPs7ViwRt~9orvpUw-+cNIr+w1R1seOtPS*wJWqr#Kes>S^ud^gH$5GL4Ek^ z0y5UfStmM*xe>>(ZX6BDv8PpS5>x7He1APx9~Qtrjl-yval@<|^g{ZhV<1;PGQ_p#OW0 z2>nfknP)HCuk6{a{@iqU&JpHKbARF0$|*j}K%t1k{Fn2T=PoEHf8U5Jj&bZxlqe;u zHwQu`t@9zM__;QCZWWR@bADS_gaiSKHbis`KINLqKi%kMgRm6ghGl?9brS-fC&Ag2 zNTV?u4(R2)r30rO(8Y}n3F`JwUeI};3%Oa~^eeVe&}|_~J+SW4ru#dk9I}yvVfIGd z$T6~kBlN}&$R#m)EBG8(2b4;`;kHK{2lQ0Vx$*P8({YKQv>kc)$8J z-RWmuKaH9ZfdUy;U8~KK4qHR7AfqF%^3CUxp!lTSfNvYllS#;xaE+Cg%sjd6{xDt0z0ef(QqzvcCJzbpn6}`e}m>vLcN9RCc<(Q)Y)ZH1uQq6V}!p zK>bL+WK*GT`VK(u<`>sBcAIC8QEm7-5vQnmsKWH`4e#*t_gN{M+%{z7+-b_@IN=H- z4St$my{WFbd;aWYIr;LNvgE-O>ION?zxmMMiICSC16*t8x6+w+eC-XY9+;aORh_^y ze`rqG`uPva>_;D!<&E94oS&%8UX{h;C*}0PW9PB8vsVs2`b3x1$~Sd1Md!-b&3VcK ztzm7g2>*;%%NX&X;qOiUM8~77HBLq3$d54GA*ag4Kk~`=;T{-cq759cZwsSj*sr47 z3cpC-!raC+%=u=RsrrNch}-pz2&?O}sO5y8(E8aw!n6irfSqgopQ{b#^aZWq3$;6j zrn&A#Ft`zi*AtTm2E-|STglzIbFDQGt?t&3?YBbf(9u5ZEOxSm7sV&LRes^2f9Ho^ zgr%DyMwvJ@XjD0?v0C+V8s(-gB0TG}8gZ(;q1;+8^>xM7uSe^*hCd%Q2L#`zX*!%i z{Xm;eBmeO8ECtOnq<`|M|DYU7)%y#x4&7fxFw)IcXY?sf)cV@c^%j_Y5`Cb6*jhM1 zbvNBAvv}R{l=+yTmXA;}+Ut*%j=ETAK+KPi%JGv&WxhN03B>6~cgm@*i+J7fgzHUS zb&QeriS*)$vmC=QzNt%y#$c=6}wwya{Hic ze|W3x?CzCQ&Hsy|V_nY5Uvu$P7k22$8wA>`j+K8tz<}FxG4ldtGQ~gma8tMWP)(LO z=iXWmHBO74?g&r0c1OAWF%HrAW*>?x)1h^dLXy!3G^JN_J&9r>tv% z_&o|zC)W!IA2=v8sGk-`>6?G&&i;^TW1OzsBgAivYyFWQd7yirKVV)z8E!~7R6_Bl zU-{aW@h0^Cum^IDOWw4(`#V(VJrJRdvqJ7q@|DLJZJVJ~NP3Z)Zvg8cd3Y{Ye!j+5 zABNAeFrG-y{tEK^P=&^!QTfnE`TP_QSNIcC@I==?z29BVQ zdzEyr30bap3GXA1_YL32GF`*BAI@8kzb8;%cgzCe3tLcw%@;@tm9s4hNxe|PgxgdM zb!F5K=nH-=8Y~#SffmHL$p)6=#sZd$2@62eMd*b=*e}G+moyM$2=fMmi!SoCVHg^` z7ch``Q286hlOFJem8kP(aTKP379KzJaDJJdvLHk0(2E;H>q}fH@fA*-#J=3lJCMAQ zLH+vzHg!<`=mGV`tM1qwrY|{Y6#;4WPy812;u}i{N6s zhql<1&wI%Foq@*9iH)s%<^8x@(|DO7W zQSsXR1jf8%e}(6ql{c3eABrIK^L(ZGfz9*0>Ghl`L{%d{0^jU+ay>^1nVbDR9{C}| z8)=$%;M+JMt%%DIh#clK`~l`8-xP=eeIt%LQQ>*RAko!LnnVdghB0}B3mLPnH|0k? z^*2PUGhSO1Cec*~33T0r9?lbgA%4uK+>H3uLh>VypJr9LF}~U`E7~?0#M^)?B(3XQ z)b)*u%6p0qtU1yRT~c4DvM?P(??s$5AkXyAxKQe2;1NXGxv$vxEmB`uplY;LeIv`ZT(AM$dal3HSIq!o`Yb-816Dpl5x z{VHp)f4CC?`fEb(e-5-L5?1+3Bx<0zq-%=3Tln@GX~!M0x{-gG95(AQmP@>0+%sv@ zNnfDfuz4o*Y3}7onV&w_W!Fo&k2O^sm-&mw4x8S)SGIrjlQO&YL79K^v@H4N;B&^T zWca}hP(1Si;}^{NzUdX24|EdW1yxEq<*933jI=Y&MVy|hkdgcTNG27lpTP6%%I&FI z1I9x@VLsVoDtFH9InNvA_H`i}%)NgX=IhgiWQewF>)=%nOCHeCe73|8_v}SE{rW*! zF#l0U#9@tL&hzO3xhW%WV94*Jr!lszT|z&|p?JPN7f&2sxxP0oTYvu3GWpY=l;tNM zl;zEXGEv$E-zI(WvP_iEOmpcT-=tMmtqjb!LF=Zz+^JuLv2kDd*pzoWN0{9e>#5u7 zHHK`gr)& z{vGj~-b&N^pNlo_Wzj}!#!tA%@~I2rfYiaM%6xi!Tux7zV<<1>$Hw>;?ec*?M_aoKy!vd|u;K!nxsP36#! z&~FHEdxGJwxdP+1>$JUfM1k3NGmZZJ12w`^YTNg(3Tj| z)sLS(E{mN>ncc6ij6K!$%YqA&BkAzz7p46EK`BqA6DMhzCm7o?UwAB6aRI@wCWLA$ z)Q{(VrBy>scX!L|Kk#cg3EpUkhKjh*tF=vsC0^hJ63yWcC3Wb*(Z znJIe1P-zG#lr$n(NAc}m0xCb;h~3sWKHMu?cW;*c+qcX7!K1Qx{M35ScK2M4YM=$H zo;HTM&H~Zj*Zo!hRxXDJ?aG*Zk9DpUI$SEJKe8Mq*`gV*&A+(mS58+k4alv(5npWb zwGKN!_oeE$s#hvbfIIz&A8y`)VW^$5^3AW38iH|Ff6B}c5cq-q>%f|P zt^%I3p`CKcnr3*Sei{!deBka;KYci0{=78fF#V)Ix-=e0zdkGwus1(|sOM5)?xXn4 zF+%o-iAVd=&e`{k^aCN|g8c{fAu!NBQ-ATEgF1)}rNmQw&t;g^YBm$Q@iY{8EXT5BO)X}>n1-IHKY6}SLQ>W zX&l8!k%n3}`_Yel$tMl8$OX{N`gU>g%RG!-o*=Tg5U?>qah0r=9~~qI9avxoMp}gt zhxj6`jn+cs;k>@DKm`bc7%zfBykNZ8Tqg1B!X?_^UA9v%`@7g3JZ6I0orr%rE`UMv zu4!xc0W(1b<7lm)WPX`HEPT=q8{me7zovpVhoo^f=c+`<1BpjCsJQUVC5(OMEzgI{-~*|&+^foCAXgIzg7j@gh8G(Rz_s@9*N zQmt)H28JP3mIa%8A8?*gm5?iG(p0}vsx^?c zdbV~iYorB+Wkc4w)*{YO;#nhYq*dQx3NTfd4u`m>*w=?C}9@|EKK%OA?};Y*Ea#;yd+g^c0BI2P}$Qm0OjUZ-SR6erTZglOE) z4iEiWPM`MjAZ!s$bN>)9OOW!;VkY*Y?MA=UGp{d2{c7Z#H}&5({mrL;rGD*X_<8eM z)N;jRxUHM*%!4Q8MO#Vj6l~dJaI^i?410_eRM54iUwJ&+7HaO`FXNEjY0?7-C3H`Yk#@eNx#ZsMGX0p7w7Wh@ z>+8PXeo@LF9*I|5dRU@0IfSNjdrI>#|f|-`Y7S+uOSSQ#H+)&s0aui3{o2451+Nuj_B+ z=WzM82VG1nHiPU4TikR*o9s3I@~aOYRX)R4sB+8Oh&$`KVXPzi@9R{xQZfAjg0jvH zeIQk;GMkAIsHX%Bv`b~@bF`wmx3G~`vDyR(%B}c~r;U8glVL*KtfxGn>bKhn{pL8u zWx4FvTX?rI>4k=5n#X3K02pn!C&J+P^^-8tVw}am!@X48M{z=r{i}v5mkmuq+KKuX zS=)DWuGt6*r!JCabbEDfAo(manD;`i8@YKq5U-Bro`!oK?ulGiQik{q`3ZnWSAJ4& z07{ua?sX|M^?~8~At#H)W2E&1!GZ2?A+N`c(CGneitBlB4Q%ue+F+E=WnrT}$fKN5 zRzvdofwq1S{tZdn!zdica`pa+z!^XNn8JqqKHmh(?J+@d=?6LAdoE?{sZ%9#eM~%t zH*=PTLY=>aj0x{G1g3$OF$AUGun$2T(z>sRw)rWk#BwgU5R zu-{{tm4Ej)tJfVHH7Gq9E0pnR8Uq!wb|R*-vcmM^i=bSvxNy{Bl|}#z0{G{~z7vVh zyjTouZ0HcZ&`E4vBt${L$s0l%I0t^v4m}-+$&C`vSGa}t@2Gjgxq%F1 zZq50Jd7#agF+a4qL9{P7GIL(e(@*(|N;cdT?C;QGp!I2oE-itCH@%d9QtKile$HoL z&T;*ND7gDL>1Ul2<+kohN2bn0l(M5Mr+)Xju@<5~Cq=n2LJuYL9LlS<+Rcg3-;@<{ zGs4XZn+<#?2p&I-wK?DVgl*2dQl>Y~HVikqQuaJWOa0C`Nryh6e~&JgSirP*!zbeI zFu`u*q`c(&NOF_6+e%Kilc-c1Ql;^R4;b#;Uw~2j@9!_ ztP0E4UiuZk4&OCo9xF{Yfa@-4E!W%8FYD+mIJ-B_BkM8c4CS4XFDHJyHoHzUqS0^X zr!UL=_=)6cH+;$Obd80T6}>D$91@IuCK z&N)EqP#yF-B@0C#!Wge?@@fv69^TMYs&Rs{P8ZZX7!cK*j~YZ1))?@TiP)8~g@A|$ z=3E(J_7AuBd(%Beh3APu+!$1Bpw+tJlUthCmYN4opFJ=0hpJl}Ra8;Au3#kKflKCL zpBj)m9?Tf5WzA?S%KT$LA#;P0@qowTC-=(&1MMO5re%8jW|`eMaCw$bo*Nejhh=Mb zU-?dTiH*K>GkxmoV7WzC#%D!q>q>0GQzp@|KW>Z%HiU$q!^}%g%IalA9QsWfaBIF* z7pE7o9>(ei*7{zx3E|baAtu~4k4WpjS>rk#aeH^i*EAXz_{)nvV_D|qZ`z^b*YK3% zw4&4{r$mqWeyDIMeyMAM`pRFZB9c!1d8YMv%Z9U=niw-BdHJ{MVK;e_N9tCo^GrVc zdu)DUr;N!iY+am-prwOPw4Z+TpRzbjesX+bBkie>Il4=n zCpP0K7m$zmG8ep*J3^Gb`NgIDNl()t=e9d&+(V@vBw4ZN)NwMSl6C5(tfTr%xj9~+pHrHFdvS- z{=DXx@&5|-<7>hWV}7ni+8gEYCU*GiwFLa-@?LQUj6*(bqyMI+jvmzTm4mSqSWJXzS0UU z3SSMg6;}@>R2~+{W!?`Zf@(6}qP^gHMQ%_vC$*G8e~Q-Wk|yd0>h_TksQm-wRSmJa z*!ElN)Hi5HuCa;BdYkP_+`c~y=o%o%g%U$u(1sXkIWhZ9oS^kXu5rKQdnO_GN_o$e z#vanUUxMQ8P9&o)EYUymBe(%>Jc4GJ`E)yRHAMM3UW@}X24Y31oU%XDDK zvqNBK$Agq7%M?vojkKyS3}DpRGxie|fPcI8l$=3b1U6_&1a>fp*8% zx*x_(zO=R592Ad{KF5n+aV*cL>KhnnpMV-u>{IZtL)-UNg|W9|6rb~*`SAB1kkW9y z{ydDXx_&mY$H5-R(=^DEN8|(g<9phEq(K4w0dq?@pZvHM#DS+>^! z=9q62yh&NE;TpcR5OeSM9IBC)$=}FCuK~>kFB7qmXi*bq27CB>Qli2@v0kjim zv|*G*Di*6W(1JG7N*5L@(prCk7k+tIM}_->G%y!X{kOWz{Bq%QIw56k#$ogbT@t-; zDm?3>wGlc5HbA#TAnCUlvOdp)jf+iR-ivSyS$UgezbRZshc^KC=?>o-ATQW&1B}at zGrg`-Zu*cBenYwpzYI8UVXOa+ZzykMLIG%E&QCcfCM7KO!;J?Q{Ou+{2+zYJgfW-o z1-hw_IbvKEM3D#cqfbByz0odt`2Y>jKWu`4)WN!SX#EqV3w|W=yry(H&q-9B`-Fs> z2H%Xh;jjPd4!(infvzv1Hzt&)pCCtnQR>7xC?WGD^Efvn?FJ=oOdjhd1?+ED^4m#9 z)_|n_91Kdi+b=IQFgxh*Etu46J@NyfNunUh+Vl8s{asdoRzl?_|YdP>Wj-M#+2u3%cC;+@Sx28;wNSD zH-B1|Kl(_052N0!ET12j<>!y;HwQUIdm=%6SIu)0sQSx!iK=wRSOZNj6sg3J{!S|) znwzJGheIQ+kaE?(Rnmm!$M_8%!>u=rgI_f>8^&@dtGY=nM)AB!jG+~Omj}b8qGQk` zEpad;I$p@`c&8V7(_3@a;^k49KYCIYkN7sM<~Sv_X3VkqMjWq4Dx62;EsDF* z2#2Pj_NL~CpWH9y<2!0EWU6e_g_e?8+17e8eg3k{zj{!n+k0jE@TS6MTADaLEoG$V z6kWyht;dDSMs?`NWmCRT$5C7b*G>Jp!H-`W3wmU;-eIE2Bd49fr5+-#4YLYsMhCl< z4{=DF=(xnI@v9*fnKex{u7OIc{?`nsjaFp(t#QCe6LG5CN*k~LitsD!WjHQ+;17?V z+`QfwLnX$^y0!_CnV>e}mEP507O$UG<7Yo#<*j_0TR+yT=7Tf)VefCC9>f~utkjYW zP5*?5n{+KII1zwSr^#EMka2RVb^XLAhgE(aTJwon>OdH2NX0A7x3*LVss~PZVyLYK z+N$eWS|Rx}ey#&C=nFRgRais$Gu+^-PWs6(Vc%bpcRcur-ea9la74PG_G*YnPtT(3 zvGq%N$z2WqC*=ggH{bB5UbF2J?G8Cr!%7>g9>xO!^f}dawwKchG0@g|Oqn|4N-?O{ zleDUb`*+Ip-rX|a+g6AKvpN3hSEYRUROzs%KMM-LyDg|30OW;pEA=e+=!*FfF1E}1)9I9XQz$p)!x~>%Fw88}I*?G1y z!H1i&x!;MWF4)WSgTdTSiuWm6#qooJ#8>{V5BXb0B0mZTVBZxuFY<}JE(7bLo~NVb z2ROgVR#2GT8RrUmjNyz9$l4&U#qHu`RO_f8Q=!-Va0BV@pGeQ#p8FtE9?)jc%b&dg zuAjZ9EX-F9r$Lr|h%Xem2t)1gVLpu7G!Q?jCqdh(Efx664(34%C8}AzLiL#LcraLEh=OJV`fUIom)@bsC%{AEl0JnYy8#jrB38C5E z%};Kq(~7d$;gfMfjJ7t)3fb(y@M2?a7;V`M;kBr|k}VCkA=B!|j(L48Tog(9pwd7; zlo8FXPLuG1u8gx|jCc*;dpEGo?<}k{CSDzCc~|r-tj#6cWKFuaqu2RR4KZ&9>-Ai^ znFb(tZBOwrSFuO!R~?t*a&r8nEDxm5&+e7UU;eaAetcigC@KQVHb3 zL#t2KHQb=*=;~+VB4IAm(BFH()oFBa@^aYFsd;I6a#H5cUzXE{kIVAu^BR$P)$0c1 zSK}LGEc;D4Le>HdwxIn8Q+)ihu%0vI&iR4|I(~ewl#lMz2RydOhj`PIciGh;JO`xB0?V-NF3Bj4##0J_yUw6cy6+B!3P3rlV`MHjT7~88K=3dee zM|Fp85xJlGs?X~Ka++Qt5I5!LHOBr9t*>K*)InEAPEC2$pM8?pM%tO`qMo8{ajLeF zEd9@dLtIWXkWWh3jA(-r_~t_0VNH27*+E>|5!k?ie4O&gOfx zHqvIlindp!*Z78HLW@+!{Vt5O%s)gUzl<-w_7!AlY~znyjI__6*jP5Zcc;wmW2D`6 zkT=PH_f;uhJ<<9g4{uV7#<;DzfzDwC=#&VIDL_9Utro1w{y{Y?;~jsgzvl+mQKdC+ zsE|2ExKN!PefgylFfu$kTujTij_`r&V4&9sElv!bM%Q3dUB_+Tx>0WY;3Mnv>e;h$ z%EOBq22)OnF@~83vyP1EmaIk-<(7^a-sV#Dw;TUJ$|AawO+BPv7-vWRT^N}uz6 zx+|3%-c%^IcY7?EGOkoU+|lmIx~-t{agg~6JU~VwrYug(R^#lnEOf2AjBmp(wdO6v z)&~)l8Ex%OmaWBF*g-%AQ&{PqFUJdaI-hEmPmTvmF zQGQ?=QN8z|@sY0@#t3W7Z#awcJ!f7QZX<1+aP_HH-K6-H;gXT#Dseo%ps80MMqJWn z`s{b6@`D=Ti4*b0`G8^@B`@j@GH3^T1oZqn0PAoK*KiHj5YS&ce2-vO{`#+fSvU4s z41`S7TsSZXf}WVgz_&UWRR+%f!Vfkt4nh1(b>U;V`e8vKFY-)dr45uqZ*b!dy>heP zi=)!#Vv!)xl}27omrAPsLKaYDc|$$(%zW9j&yD-onD005Tipn)N9f{(EoBlf;^yM$ zJR^?%pu$$>4tsqXjkqm;$`N^kVuuS>tBeu7hGC~kSm*aPf%*^3emRCs{%;CzMJ{>= z`^Sd0gaI;bBTmR$vH4#po{o)LydNXf4J?}LF$m07x|tSHU8Pe^4Qlr0H5|@?cs6Nrjwa0WC36n4M4K!j;TZe8*{&PhJW+)| zX~-X)(J6J#xyu*-5|cLp4dtgO6~iz2^lxS9snGg>p$C*ZY-FMXH^>8{tlZ42o?8{} zx)Y)kH!()J9Uk@Rcyjl1J7pS_L-|4Rx1m~jVW>@HjWN;f7OjQQSu7HZPT zP{frX8z^ZH-og!T47EF-n{t*1Se zss5$zD|9i#fw7Iv`(_A**Lq}{^Dmff-*}}D-u38sHU0wBn#ikL7no#Mt=>xh78bZ~xaOwq{8E~`SFVtnU2w;0z1^5>xePPAey zg-=~=ysfdCT2}_rRdE6_!8;4r0Y-SWo9Y3bY8_-wkw0Zqc{%w#Q=JS>(YoA(XZ%WA zmg}Go%p_u};V7Jj&S8BM^`rmnQ>|~UL!fhy<2w7sr!sgXGzBZvii`N+PE>zlUa2Q( z`KIqHUBl3?YM2MC)31Zb2SVSXp110Wvh!+hz$C~?rz!L-(QUv z;wi`vlUQ#s@@0;~-*XN;M%trt^i`gujdev)tQ*+ZU(eT^Dm48Rp88o76u*j-ZPoGN zUfH^Pr<@!gmsgJ-ms4InFP=|$Offq9AwubFl#JBFC^=bwfjRFr^!mGU*YZ|$ozR|L zICE!Bmwu!l(T>k?;WoS;Rb0<8=4@BiOFCEZ{K>ycpJ3ykT?$lD{R0?ov zd#P*SC2yJ0nmFNeEZgd{TFQLVTm94(N1KOy3)ut&Wt-s$Qh~IRL;KO5zNS`2%+v7s z3S`jf15#F$wL%vTIEXkx#s>EvJ{gKZN!JE8Cdtp&RSFk7Xd~BO$gmvvH9)XwGJ=k^ zqYtyYlEx=c52j#*CCz&9b%^SQcHsmq23oFJxPI}yh*1AcZk7Ssqsu6U^14q8eLttT zQ05dK{-B=H_|{G?DxCB&&Rd^MfH$H<1PsD^hhXeJ4=fW}$r-qUsI@@)UPiim9j~JA z+lK5*sY0s{d05ZHaOa$nm~F;d!5)dOQ`%lG_xL>2lCK-?4YU|zd*mS@zs*Zysr3)Z z^WKm0@p?plsY9<@=!}2*SvS#4!&rp(o&_|p_jBApW#7iJ^AfNBI*wuBE2-3hFabUP z4&aa3XRhHIuHoAWgKLBD56sG+|K-X^3$ozkLg0xXtdV_zvaTZ150V!`rXA+ROQAbZERwDBU^eoj^g$gFh+g^mJJQed=iL9Iu=pT3m=p+lMf4GS+i;2CZk{+OE*BTn;^oAg|C zd+xRpD`a!0*V7xVi3)=Po->gpnb6!s^Cp1eKwsq6GlV0dLAm0vCw%c3CT%RX*K~Dbq^e>bfxX#VZpHKIK zl9la^ZW6W9K~$uzm9$&m_SybpzaDEPkNoAPxk30%=s03%8^4yCzOr47HhfQ5IN9GV z6Va((yRGotOmf<#H?)x9leN&0Z38YWaiFP}e&Cll20A;C;QX-MgIJl-^yp`KYDwcJ>LIh~*S0PPL(O2)5_Spl`=Nc=Lr|50G$42vNZUNZU z>e%Lu`Dt13O>({+NgB{ zgNI_k#n8x!R89a_gP-KNZNO+V^4WmI1u4t0eT9N1BmCC!c2ln8$7oO+SWQNc08zJMAaJ?3;!Qj8B|+o+-SVX={JyPeIjLUOrd%pO=Z|s_E^+GTqxNTgrO&@MT$i`c+x5PWU9PFvh#@^^>NK z10@p!+;IE=K^1J3H8<_uP`;cx=P#4eKGahp^&!f*Ps1ce+WFC|^6Kl}NGovqK=@XN zP#7S1Bjq4+fb|853o4BH7bBIf#pb%MfA#oLIr-*6Sv+}CmKvW+t*f(XJx%NR#Pw5? zuC77R9sk5}c*pmCeO$3sj@0Y@TRfr4d>l-8sn;_3H9Y~j_N+n208BG)>3G3OqMFz;TpE#<%{#k73;RFAcAoZUh#yNjH!%VYZPmc(4%=NVY%_nPq9ec~Ff;TrzcL4Q5)J%U;JlRx`qGZwPI#7#k45C#i5m9U{A z1{X-z@#MZ%X@G5VGF+z(zhd)fePL_+?djTRM;BP`_^?+i833;M}%T z+)?z+fR4fTa7J(3fzDb#O@&e1H|ba8OY+P=vNV|Lhp>Tu;z^U}F)d_X@L12eAm*jU z3t#D?9&D#Fg+BQ&WbPzR&K1Z`g~rBNd+Ub{Z9i44n^jJras$i7KQ|z3qH&65E<_k< zxN*%VkkjzSrac?@gp&?kZCH*ujPfw2Q5JMNGp}{LG2+?a8`$Pf@$9U)&P3g3DT8#u zILir($yV9Y(l(PCe9wz{eaTHwz9GSND*wDmfy!CG4@4P6&3C9ME9(G=U$`lFy3L1Q z*16+%=!(K$NdB}LYacgqYn^P23yIXj*5AB^B75KRin5q0a1e!be^fL{tg=?hN35=-Y3cW!>dkNKVFwV~Qcgyr(zf3UZ zuwlZJ?cQWkTsBhFw4}EG5-%B0Kl)GgSFy%`oL~cL z(oFewpc)@G=&@Njr+e3sy1fZ((({aebXhN>^aUZ`EuAlq%kjz6Qf{fw{K+S!{Oo=y zH+L0}{(+fft4v;K4DcFDzDN65V}{K$4UsnXJ*J@@Cbac1^hv#JMC{^qQAp3XsHXe- zWoNHDNlRK|O-b!#|24pSqdX)>+y=oDrKKaH*RJS~={6PW$KLX@5d}vWHQBVCXzVR_ zx65*e*D%W8^SQ#da<#opxX=7|#S)zIk5z2FU`?hr5u0~ktv6MczDMQs!<>6J#lntY; z3oM{6r~_YjW0(~+DnOWqSQ{1GCvc-`xXGS&70>q$ZFJQd>~CudF`i&_TF7sOxcQ!` zc)~E!+EBZYTsGSOg+T}v)i4(2D-A*2qAwqTS*U$=Q8l;#fGeQ12rXyFdam8g4QJwh2-qDc_vwkfu zhBf@C=QPp^sv)$VShaj8`8y9lH1esw8MdN{%}sm{ED)Xt6;uZ{0G_DbSxe~@1ZEtt zX2kCV>ReoBkV+HX#!@fax*DZ~^tI@3yuP~P z!gWdcY=nl|UpxjUPNGs)(piT3J#O(hTYiDnuQJ&`Yuvy{Z(}MCFL+GoT8!(U z31hyMN%GK_K63oZ z(o$}PEmV%YlLLxvCJ#(%$bb#K^c*{T@9l zCl9|ai>HrOFIqoIx8&sbw)^|UPxYvWk_@Wgst<$dIf7-%MxGvYhdRmV!zghl}Ywxj~%1NP4Y2*<_pagsyEPYia1a|yPVKRnYPKZ3%$qJAQJiwN&EvaXX}tGQqEJzmIg{EMKA zglOuA>n84>Ff`?>SqDa1;w2@WWIzFzr-PBxZqJuJbnZSZd6VGJr0+85&l=|`K zS=3Nzq~)50w}E(Vvp|s!xnAu1c3vN-3VdDJ;pA9-_Gn%v&*b3V&9AoA^(vp=;DO<0 zkVA%q8O4(=vfU@b-Pc{mUJTL~aGFerALXg80bD3s5mKk~U>u%f5a`PS^v-d*jX=ap zM;<~{$r;$BNAk{6KUw~Meo3S+fV64ud4Sp080LFCB94&pGoVVJ_bARI^3QfNW*h1U zorq(^Et+Y2q@O0=>udd?!Rx;wJWNzt`VSyI&IDWxmVFJ^a1Gb+hH&QE;rjuz^3z|` zleAngdShIZ=3tU`yZ|a;Lq()_Pn|YAa`Fdr@yQJs&-h z3XPIsBn)>K=CXj|LHyWEYJTE#qsjikdy@l?W?zCvGv=a^o+=fNSHe=u5f15lZ1gAKDRptP6U9gw-h3-625x_t3{3 z0B)f-GL(ombUh_rDvoiU??K0&Q?I#%e7+;Emp=7yLCeMz` z^7BXab;oQdYUtFy8PsE1{mElrH0NT^(dg1C1CO)wGT3MfC_wWW<(ls8m!16s>FkcD zu#6)}nL!-_D@;D?#`O&5AO7{fL2m3P66Wx5XSmZcHZWrDZmi}|F;;oF!YAbw#`maME81xkA^B3j`Optzn0C6c zQzk$8sFZuRs*x7IOha3Ez87U(xN}=;j`BhW)*X0^z``YbtVC7${HW zr!a5!t6}^=m*PX+4z#rp!;^4ZYa2$|RiBLvoQECCrk0PeT2B3|PRQ%{)hpHOD|HiI ziOWf3)iFBI4;0S^Q0Y>?fh+l1S2;25oD>cvo9Z+CTkjj`B*S1CYI3#HiSnhLX>Ye7 zeFouU6rjfx1GVbFsCsCxeU7?tyhhg}^2~=^+9YA+U)!57_g$!Yc@kfGQlFe6&F>1I zs0_!dQ%)qqb7C1I=J9borEI^5hf&(6P%%8w-^KgHDstuL*L{n6-A=@a6=MbJQ-$cD zG&T%NMmJ@a{K2zw`o$yR!)kQ$!)~-U^A2qe6{4qgr5{r1@PV#(=mVfn`HrH0xO*(Sjud*63q;lQI_1}x<6<-D( zfs|48fYH{Ok%weqRP4*fg1A&2^6^*mC8xZfYCeONQRHYiVYjl3&pq}we> zuSUfr5A>4;Kb|DO@bkPK2=8m-jNbu^y+={j z80s#OdK=SC*aOZUd$6C%qW=LjIp?7OJuU;5*HNI?v-e*IecW-Ma8REZ{*vf?;RR>< zn!wQ_97xvwif@!7`|!X&+`g|6<9m$`TbnD6Y4|72duDjCPOolJ+n#)qCZF!4VCn#h zNj-c`y9QGZ@tYjU0N}Hu*xw$4@N1C%SAZt#8m{3QuHh}gx;gzj43qL7{;OrZAptc@ z`yxRhp0GRW`IN#7*G;ZjFHmnxL51F^5klE$^(Hal1SUwH7m1+g&@NVzf;DPegc8UL zkG%LKzlP)|O2dIEp*fL!|fTb7?~I+ivs&~eNldI zyWEItBKy44^9uQq{4(`L8O{?+Se7&Anw~P}w0Q?~%t{-EC;BvuIS3iK;cY&sPZ>fL zzzukAn0h0fjZ^ux`BrI&Yr|}$vC&oWytys(jXZIcC&t#cp-x)jhfLxi6F;mbY=(0q z!Nvmy!f$jV%C}ayiRWhC2F5@(!SZ1k<}#3m(0>EUOr8ML^(bonMXkTk-!)VKMu7wA zpT+{pv%6C!+uJ_f#sN2q@Oo$*tTVS}>b z9?w;rX_;=R-FElA5sy+BHI@p)AYx;PHzT36qxvRBfBN2hBAMtTDpg!HPzCwdI@U1Q zZ1Wl}uqW;s2cU@bofc;UWO&lHF?azuN~pFDs-Yv~W+W?jzHl4k-Z7+ZZvsO-Ynjfd zj+?yHuRR>MmSwRuFUONtYWk<;^z>1g{g3{%O#j`#DT^Q9Epr=bl}K$pJ)V}y?;n@N zfB(C({O^8K%2(=ZM+$qTypDuym@p5p!N|2Qm~(;qx8hnK|5TElt46BGI12rFaKztC z{NRIfgzxHwfWoaXUs z7d0O&Z|#+Z_*2arb9v7hywo%5a)RCbKVcS2r&YvtmWp7QtsT+JfpdV zF-tzK4*?l7cQHmu`%Gy__ex`!jcndE`r&?={O5mF%3uAoEbnM;!jJdVllVk)!b9os z**9hR=@+Hk|3q`A@?$RX+!L8)9g$3kUBRz0W=_$(Kh?T3eQ{D|FV!|$kEZgQA)9zH zUy#n<9t48AI?YvJIX*qDujIwBHRnWH8a&)@0@2+>sS)5dk)EEXRY%N$n)|o3=5BBA z2>HII=01#@%*8+>RYrB%)%Xdp11>{U;@dwXS%Q|dcA%9{F8IDy#*0w~s{!IfYsRVOtxuctmbdRdNM zzVIncuQil=9Y{y6HF&^iZ-37^(x!f`t@Ns6yO!6{<+n~hm%st~A+B|yhE{%dnGM60 z>a7~7)Hy{lDpfy~0pq9*N<18ZQMEoKfE+_)h-*?iM)gyj)`v?(UH5oa>Nf+pOtpQd zDjRX?tDf=m&5z_HTL(M%zOEY>trE@^rWDdP=^z>Ef1Bq zYe7{;1<_V70@@ElE4umGRJ^GoB<=|Jg|{`ve)M74{j;By?YpM zdb(5g4({kOa!=P?lA&v_Wn6z%?K=on>}#GfL0eFx#A$wFYG1M|{Owse^{a$cj#+nR z*MjGsCPe?rAjgo$5ALWxQ~EFC&HbQ`H~ol*DiWEg=%&1`UzhjpUmxBq<=&lA?jE|Y z*`WUPc`1*DT=Qbw^u18XN_jx!Uup1JY1!Ag&hfpF{Ak17K(2ufmEUd6&-b-9gC9r- z-ZDbC#{+T#4aiPMP-iC|N>yuk_}b~2^#0;;DW5(p8zxIG7m&$3cqjK#cnq%LTu+Xt?r$;Wrf^xn-fIovCA)u-1z z*EzZi>2It7Q2GMx$#sp(%s9kP2=z6OkT&K)TJD7&s-7^=J|~^zQJ;RZOQdUk08|)| z^fJ)u1DgCA$iB4+`uxwpIbrti0{eL8Lnrr#5nQCx86bY*TZC4HbeaJBML-J|(wE%N z;KQAM<};2c0PV}3>bu>e{c+ovihsu8CwL19H;}SdjGzlQDD2$&B`m^CdRYSZhd%u% z{7im=E4Sx0T*Eb7!&`>7CjOCu`S3M$nUw$8f62#x;-bG>D7;7n4;sis*xVzC;I?pq zxp1*yR=ryJLMF83_T2T9CJf#sC=wLDOfHu^R^NqalgrJA{aF2Dc+{hEYQM~zy z_y*hwy}zJ2yEx9TvevD6D2}6LV7Sldpm1m(ZfDRz27-)RnSh?ZhP9A=;;lfoNyvPw zvd;sxb8G+Cg-huA&dak#|CVJRmY!G8=dx9Ep2#de1l~^lczg?(ZyW~d$KFAE?7`zb zl!NB{xsGz<>6>+Vq|w!Dk-wb^6w2==K z&wS2}1t&duMeo;7>Z_f2O)uZy!BFd)c%h%V=7v`BJ-*2xe5)&L+xl=4t6BfK!%8DN7Zok5p^darmn3APAHyR?5jKSL1eR~uM*23r1>^_1UFC;3*NKo#2)>1dk=EacjMsT# zB+j-55oK`_>~cB-k)U4p65umD5<=aULaFRmH$PJQ^Yr+m=haBBBDi1f?3Ky(uBv!i zcy;K~uXa{kP6eON<*&Ng+xP2_>#4b&vfNTVxgC*D8*&mRjkcij^XsIP37bP0Xhd>< zg-tnhtOgk&dPaXEEaPRd@T=vjn{^Hs z+1Qv!5A23)kKyu=T&3`$oF8d+7OF7j1 z!h=4{d*tW2fHBF~6z1IKhc@I!=(gf~pt;~b|C?&0y{oy26G&mC0eHG*KSnvM!ir!qiRFYl9*!K8*1gp zD{|dn0onGI)Yk1nJ30)h>^X)&enYn7n63Sa3e>EuCHl0yIz849Ik91%jceAgB}X?g z)OtPBe6Dg~_nK-PZD~#4nNP~ja#psOXA#^osQFcQ^hniHqiQ=&TE2MxqP%+XqAXee zq$97bwlP*b5AI-`-O;+xjI@-)WvTKl?~)K2t$@VRg_FdbDt-ClxpaBy*X4RGW*uG! zLh?u8P`FqbKe)T8g=iCYcdypk0IY5Ebz2=tl4r+y}(x7iqLtqhe`w#H*UUm0onN&OP#3*|b8 zwnZoOz~A~f)j2?(9VPRIBe!JpV=M2}X~+rnMh!m5}+u@)MMK2EbTH9pv?MUNd5(-4ou`-2C&8 z%l_Z~dD*#l$ET8y{?ljW_`mygnZ8)6ucwh#>j@_fG1OWIA&|u|qdwwap`0#fgjZ5a zPAsTV<#sYZ2|gM-n6Ovswm;`29=2F zq+q`G7E*_|bnW`l-HLY(>wL+>9uK)D*7YuLzTukHZHHWBDlLF$+{jE_dLTdND{S{b zLhd!l8^ri{Qyu-D^5%Q*_q9gf;T}%@w7JJc6=Q695N40iqq06lO1I8aMc&oRd$J+r8_ERiTTR&R`BU&-T=9$&1=X+>VfM^>V)eizZprqUvaDamCW-+ z))jq9LC&*>sDiUV!2+_)4DiCrd7{y?_%I8^`vKul7|BYvK@Q}bjqnCt#K!jFV<1vS z6lI(a#C7s|XxFIL0?(Jzg3v zi2TmVLSG&C*T~CcU0+UJF3{<14TF|lmtVUPRVE(OJ<8kTy2Cc-B!+tsuTPgev_pAS zs{E}3H2f`7*yq(hfu9@cY&x@%{!BOBoO)tYf%u%t<$IyLde*0I<;J+ksVp08g*Kuo zFK%4fh-XtiZ`i?h^QuVD)Jbeb@uUZVoLjRT0F=06cOtSWQ{Fh+pddYXl9^YX`W3jyfQ{9B4>Am%HVk9X^@gLOw@#dp?$EFPbTlF3L50~~ln1>r>XY?5 zwsN@~WFO!cf;kR_JfT1z(YELj3e=0<}*KCzOB=de<2cM<3({ic2uYRT*TNkpa^o34+w8VhV_1c<_On~ z#@qJc4e5-bM*6rM5hoMH`fLL5sh8g$GnHUKET zH#bQm8OSnKdL95m7KRh@;+2rR?wD`V@d41n;Pr;o&(wg zI8i@YwoF?=4B|Y$s$F8un@FZn?G8GL)XBNo(1qJg$3E3dpWP&$ z)aWE#dDZcj-xi^I>9XxLI4h?5FlMO(jIx|K_3Mc>&R)HISx%0GQ1Hcza?A-|;i=r< zT-R;$BcbB+T3ifje)X>(_+l)puTl=E%Oa$Y=Xiu>U&ige9mpJ+X&FQCLJaAAUlY1e z9t-JPzrhUF?=kx|#N-b~I?GX6U2Ib`u7kDUNzTlQw&o18!S@=KgeQ_!QVtvrT<54qpro<t+XCY` z{C&fCo_q~`X64?`e!03p=rAuB8mwCo`h_9lp3y=6$cf+@Y3NDvzqmr=*bE~~d9 zpQo?IY>;)vyYonyIc9N>(eq5qJ&DBa-OP(ABi$LM|LTr7mgmYD4@TNAc@VfMntB%V5NtczxX9`#G#{GxXwgE2jn6%z`Pv zf`1c8eJdGCY-Nfz`bJQISp`Bv=gJ2rAW!b8`s9|4w0YW(z#2J|Ti#g!*@HOD~9W;`dS$kPT= z>O*7DMp_}|VUyZxg~p`6rzeV$7Q+q?fcOmytPPT-JPe2m)_SE81D@+`<`z!1VVF%L zEvH&?e3DEh;I+il2T#k%Z+=_K!J+U#V_W0gGKJ2AG(j8D50o~}bw~3&uTF>3H*BPp zcYW=#;)=Ikrj@mf^cULjp#HLuJYMB$x%8cko0yPuVr>a~)j37H<|hob7-((OQ@Hy| zg44>^G62dzHNW+91|5l?pn(eG4@ovI3kN689H-JWkkTfkAr3*fc>VRIc{hvKN6CgNvu&eX{;)>5~Y9da!=s7q<@%pc>-yquiG31#}0+PA)TSHY6) z@1QCkb!4M9;jOw5PE^XB=o$^W25S;QjSHA6kGb+YJ~^qc=ViU8oDp^gqAzmlceb^y zOC(W``&C{*U)F}!yJ9^hOW)EAr}6hnW9?XoVb+G&qnBkNng&?EHXKYtY#Nk&eS*%R z_qsgKxFNk?^zO_(1cSSLB;{=k<}1c)czmleyrs;EIge%!Wr!{pn91)B zH7^>fTDGoPCi@3vOV`u%muiSrZ`Iss-x~5#t zv|KQDS0fHJc7Uf{uqfiY#bkw+1gT=08c+_M)!J6+&%--`eWo5Ym7Z}ow6T1(791X)nsEM4^{f% zON_MCIpt88uc;DA-$Tj_aK0CT()8s^uujk(^-^x`2DR=6y^*TBL!X=lb+?Eit+@m9)lJA?jF9Q-~j>*w`_8;fg-x( zyM<~8UP*?rmTx>xc2&NE-7@7Bte|*rv|?1ipn%l?W38MEQz0sYR0&MFHP*eM*tvb` z7I2t}A!{d`W*nCI8nAXV6X?7*#(59m4cFk`1hNe4ic;$zlw*bwM0Gt~Xb2puyKA1= znV0ELKPuCof8y8nE;UtogA!09PZ%o?pO*CaG~MZ) zIsxfNFTfw8mdKP>p58bt6E@{FUsmaL13Pl6y0SqpwBdDY=8buy%6d9m)NjRZE$eq< z)s>BGl!M7Gi{G0tM7O{1IBNPoZTUV|?;tJ%C} z^Bdz?8iVlXlosQR(`6WH+1$_ihq6`>#~a10A41j+>KgfsN4}repQO#rZh?vBkmXko z%HlV_Q(iZPhmxsz&22zl#3y!5Q;B|{AnmKUkyop;7Wv!cHqtKqnqFt8Am$rWO$hD^ zo)1BI%@ff-mXe2Y7DEEYG|x|70|OncOKasof!%=Iw2A5h#GqHd>8ZMLXrv|2bI^uY zBHF!*@7Llso&ea&SInr5v78oHxS+47FU%KeZ-2*A?F7=sShe}4FoyiL9?DO3!?$T? z(x2(J$*y88Kl4aXZJI9h$2U}8VSqf*Tu=W}9l09C=SepVKlo$R&aOs11RME9o@;o= zO@9Tza~{{-Nj@nDk8t+@`^EM*W#tuSw<;ODcZT>2r5>Cn(^8LiAgw~kY?$F^{8vF0qZY<~gZLdaAGAlrKs_#mfWv~C zxguD#(60fyiCDIfK}~(wElOPxf%%B**_kknw19&Z4$!|b(B9IV#`pZWhTv7-oQS-o z`CRjzuQTX;l*|2|ywE9->np}GalmMQc-DjI;f*rWe29_O580^S%rt*a4|v#2>zJ-t zc!*}fYsSUT_Jv$~3r=}RhQ5Hhq4I!t{z02Q!d?#mV*Q}{!H@{z*4p3)cX%L!SLFWi zUYSrI#DDs-EI)rxX1aEp&Gu9UQ>nvi;F)vk-09P^%#j#cb?usCmT{2d;*2f=ia=b( zoafflQNQ=KEhygoKitj~0nYradlO{-K&&}Vh&Sju3qHfWU?k!pN}V}f@T{kY`#yy{ z&j9N$G|`XSQ;6Z6b=MCts{i^^HPVCo zIL1ItAbFrzpzpt#SAx{^#f7Tf_a9uZW1RI#S{}xwED8fDkINM4EGuOPxICSE6F4nQ zr_(yjIz&HHA$6O`81+3A6kXv7!yVzY2j$B974Bo+d=9+Ec+5;RE$wvF8ID^mTVmJ!T);gkxx7@YTz(F79PuZ9eD7 za@@pqa9-GJLO%yw2C_VvF4gJXF1P5QJvX7!js3E}`zQ5Fx(NvH)4dK{l*ct(!!=yP zHM~!ll@EXR%eL@9dK^Pu6gGe#N0eViY4L?#xIl-9;wS2bEc}}uojc?8knzrgjA9v^ zknl?&Fm?|-0x4=M{07*Vca$?Rfw->)smJT4zlJMcz^w&j2$7ZeJ|MFhWQQX?F6tNW zNzba@M|*q+4kMi+C#DhA^_%`(oNR;4 zOKd~R3%HD`Qz-fP+l_%36B4OQf6pk;aR`Ir7W$+cZq+|0qSFt=SgN=a>sep(+3IVI z*{0Sxc!T1n-Uf6R;FW6^07VYzsULJ=qr*?z>sCzq94d{KYoq=k=NBBlK9MZ;CkQZa9&j(ky+#Mu-8x z23F!p|J($3xjZ18-iD2Ql_n>-c)NlhhF}92!v``H*Hq|@e^JX;d<3#dYNHdAf%4$n zc|ZAhWu!${>XF!}z#RAJX<2;whx)qXG}5MCp;`mVZ4|HcZd>MI&3#MF9ZTjTQNDNU z@6nP6@tmcEIe9fUG+7<+>dsTm?{gjyVea=_FKl^68Y9Yuf`kF7uXOiGQ1uU9-)n;{ z-ZiwzNQ0uQL|AF{tJu4PmlSsaafTK?#>h`UbsQ=mi1ea=o-R*SG|jd23+B$8KeLZe zZW~F+Z>AwIEt+}Dj@(-ksus$oL?bm>^#d3O`K%C;)H+&9Pt-MDY6z)~LJw2wH0zk? z)Y;aSjoauw!@w=<=cEuD08=qXVb+1&&~T?AnNz*>w6rK;K++zlFi`z`rgevJ(Qb=w z#VeX!pH_;rOX-P&e8b!R;zayf^5AW(jeb@QR8R#_7p;#)dfc5v`#Wp|_Sa8_H^eUx z=-mUX!Gm-_qhr)hqrn4?AAYX|ksfq?jv(`+pE4h3#>^SaL(r&a&k;8MsgCiW&oM9Z zYGY2%f_~@=Lzm_qj9=tQont`cdW7p7XCt|-!9m4I{Za+>+3j1m%J$yAU*+w$CTRYx z50};Jl%?jug~l3mqWO6yzp3Zfi4FI@{y{ziXe8gjph|y8uqzFs>u!IjLrUc>5)0SorryH z{viGxT809APYVrf_g2afirX0O^lyA3aY&zXg38-G<+EWm&?jFz>`%htCO&++`>-Az z4r?+wDR*w zP-GGh9vPy@@Xe{h3|Y@p`H8l6Z4oN0E4xJ5-!$CH+WMuAJ_LVq_`n1)&#Wh1UBa=Y}-FZ`X45Cex_ z9sE+VUzGOES6*31K5Q5v%Y8%Tavf2|s7uiGftz~3ois7(E757hKG{tsGr~<0e;DEf;3#Ng)Zpa zc<&f`gUIVbRliCZ7sX}cKiXiTcCxFP*# z>PzYiis$aDetEj244fTY))TON2k>C0EIF|yoF8I@#b~R*gY8mosGK+V%H-C*kvL2F z**NO{yi=y?-)!V_ny(uCl%dq|8D5t|bqArp^BP3I!jtqG2WfmG+;xGbLfqc$6;6pG zw1HL>0|C@;S&%H^5I^fj&OyE5$(n(YficSlK7$$~@sB<#<=$=SB)z;j4nme?sySk+ z`EdUAH>KRUtGc+U{G>B_WnO>_2jvG|h#&KY=a_{bQfa8UiHB8unl_5-Q=U*#H#s3v zKlPQn^^_w<2#gY*@0n``YuP11;#cDcebpl*tL8IrXv0TG^Lve^^Q0Xr>=b|Etie<1 zZbP%vsw_%_Q4-#Hs}G;fPc+58QkdF_Q+0=`bJ_}{gDXeq_EjI4)i*S7igxO2fm%Np zX)rRLw!Ar6w{q7!L>H%8w#1+C4N0v_G(wJLDu@0^9n(H;b3E}^pH{suD2MW?WjiUS z>SHHR^T<6Gf2=r_p5YbWafO)dbo7I`pYRbjUhzKTWEJzk|B4 zb#Z|{&SfC`!2nW*Xy)A@<_y4L(WbO*x|z3ls05=d2HG}1%8!NxsC&kJUSn}BqW@Y> z8o$ef&H)L1FjVf`xm{)$%`|6Xq~#moe#NrppqZtop@nJfM1UgQOd+PGgVr~or+udbO0ykKhPTX!~3d>1NXt@!zVV<^5ES< zix+Peu<_Q{ZNlsiR0w>`<*YeVA%PIF5dFMdZ?L5a!DIVp;AwZ)}zN?_>0u? zLmLwmAOa*P0NZ3JZj+5$=s74b{W4tt!!$yF)17oee?~wRNgR#s_Q0gC+l6_Z%f)6@ zByIayFp6?V_|3>trDe~Hh zlciiw@yg>g((2#g8PDmE5j+UkjX%5)*|?!V`jNI_xbt4s{cVKpz7oVQ(}HsMazOpB z@(OfX(Y!uHCif@}35#&^;ostSNIgS)d9EALK2O($>V(DoEW5s$WhYk&^H zCRnE{!t11Y9eA5X2VSQxUDU3;gR#2~8I!@kuX?%=(B~Si;To>t8on(sDZltH`jzGF zEEun~$bDNDsvdF?t*!yQ^Ytt<{WjLizY@5pA7^+UukXj{-!9nR6QILI*>UsiO{ecL zterEm;Oi=&_ap5k>d8Q)L?H8prr%gl%8q<8$we?0(}TnGlX0N*vF0BUV+BneLw z{cwMf;R(3CNfY60#xV)hFR$hJt0~tw2o_6+rAtTsI6`uLn z6E^{*>%zdMgD`oh>sH7{U)C`^h7k-V`GmVS8mJd2bp!1Xw>KP=4zTK>k981Dxlp&E zWm2u{cp8cLVW2J9(Fw`e*-gUsfLB#I*{O zf8`9w?P0UwHHEDbe3y;1RrQsGK~copZB#z=J@x73)}kz?r)sJvX4)ga>yY{pfdqPl&f zOzzw$OU<$K9ZuLHQ}HN|%0AgHDqZ}L$Yae3&xD+qysNSLKmV&z{_1CypGh`#s(y|Ub*A!c zeg3c<{eS~%*dIkTt7W%B4{nLIu!)8{8; zOMPHQ6${f)TV;ei$z|B$#k|Xj%2UnHCz>zjyq1>@Z5z;(FvmC0v8kFFc?&-PRyjGDDE-WO301XoO@4Dtf=j+f ztG-h1-!A2*DAxp8Q4k_8XJw+goN&7C;dAvr(PQ;RH6?9Ov&;M=Z#iwGVLjB`&9^rf z3*~pBzDFQ>KHMx{ zU3Z1O5LccedU3#*R=-8dDPPacnK9sW89#*d`KDlHY(u^JlnvE zSmU(<1$zBBH_`}t9o1IpY!LEVv{3}>8GHl$&Ug;tg5WcH5dVyB(NA;Dq)%~e+{`8D02+gGK3rDroRBpqs*&9PFwH) z^v6C;yA;o>>rYq%cmRh}tGc%4p`E$rVvRuc15W+(V2RrP>5DS|T-Q;beWm=Fdz268 ze3egPsA_DG7o%u8KAvd%Ks8tEUR%xwno`uF|8uGYkzT|Y3#X<7sNQAesD`aBPqV2Jh!TwbM4 zf2S@}_tx)&_gby=u50mG_xQDOLc&O&`WS;p74(&gl?MqBw76i%%6^*^Pgu_ZqNHbC z=T+GsYR=>}(OjFdR=m{3hYh0Q^DRTPSFW)hJHqi80$P3n&MV@&KT`(LxMue?KMy_e zkQejzEg|=9e$a;a=&Ss#cOdDwN8mny2N`*gfH!B55ACbw@O2a4X8n|FdiBFEp49KN z`jn~SFn!Y>iJR@MBt z_+!AC`rHJ>J1_1f<%9Yp1QcG zZ3s^UNZaS%hXGv}^?a52trv3!BG3exV$Aasd_&xkukJysX8^2kM#BLmK7Pd2eR?w> z`iXE+8^E}E7h<%<*vG51*q~>lo`h_cVC?c~P~Et5vX%{fZtU6EO5-dW7WlJCkvHNw zM)F2CVO)1aGl(&tw6cxgG;bSHW+xjq`$3ak|6tNryb2h!Bb$fb|xoZJ(>1A3QJRvu{fI?N`-c`&50x8=AyX+}zmAO^t-U zEx_!X?zdq2E0L*wTKOm!8&cq&jkQzoV6QCkXX8n_+jyq_<=2)TAD5+17epVWf2z;c z*P<#5>FCXT#m~Jh%DJL!u2)qI_#5>DHB^3VV98;6zR@)!Rr<#?&;oB_q+O|AnOc@C zU+0G4j&`+?c6M5hjvtqk*-_d0*`2cUU;g{@^4?xq9MC6ge2ZGB4?NTy^gn!B%76dc zQa*jG`AC6B3iNy=w1HOcd|1TeO>Pm(aC?K|0c3+Uup;eYgDNuAsU>5wzh7qe?w5Tw z;wRI>D~RQ*p}bHOPR1!7orQAoP{a-O(GL!VihoOel+9IjQOnKKIgB~R8;C^>y=;h7 zJe6UBk@jd_W-m_5l+!IwUY5zTqcS@_Ei=j_U2UY*7{*9j?i`fGhX>{4kk=-wZpkZ8 z{ZI~!Lb-WFUdV7=$&JAPBQ2+5nY)-Xax<5<%LYygFupw}@GU!xv`=b2>x{InPbF8L zTa@Xm$K~kn{=Ss^pOkWNsJb98euJRtIr*EGH;6U{?2 zjI^46Ce)wXzoLhyMM;Jn80zW?Q;h7V<@6ONK2>(+jhw52Hm;MRSO-}*cqi|94UDo7 zG)h;^j3|`()cP3$X);}>2VS(Fp_7}k(o5O5_EQ&g8)&NZLp=9yRwFGBX|Z;A!V^L6 zM16^qQy3kn+b=k^F3LPQ9!rMMiE%@}rtk2u5D(WdcN6Y)MG8@`%*DJ}0^)R9V37AcUsgCX(r(@H33_jWG0Crvm|`Mo{xkJm77zA zxV=sifjE_14l=T6W_@YsbRCo(KyEK{UHAx6|4nc~@TI_Ngl>uG&K%eGb>h(%jjCUs z%HpjIKlq@Ok3THs=6>y`q(^VsgKJp~ZI9J2dFAV)mvOzIX!K9o$n7S~vf4Uf0g2n%9qYO|`tKF>w2!Of<%r|NVxA#YtK602#=9%V$Ks(K_~(=1#^# z8pDjzk?{tSWshgt1W*9=;OiwZz9y90*ZZO>cDXI)Pd_QsfA{BgZF=#dEPnmFQvQFx z)^(lqSrSp>pQkNqrPg|7>>7jT{(!fcV4&r}3j74V4)UqZYK#UsfnPAvvJScah#C63 zJoc!((<+W1V3Y@SZyI&)u@Y%hMz*acxBTHNyPA(94RW~l z{P3>US0dZ;3_Ig-R4Ux}Gl`>Bw@fXk6cT?_O29>nPC2QmY> z#@Bxx2cUS$PCxKNoC;*l_v^idym1C2JK0mee3O;={Zn1jb6xLiditosY@~%MuKQxN zLAGN<{Go)2W&k9?e1s?8w|x(r`~j&{fj}YdoWuIQkpAXXDYU<#lMNEbe0V^B><@P9 z$9)gJI#)VIdhTduU=e)R=kt0}pJ@?0g zY`5=l`(48|T*EbdPheK={$%yK<7*fJi|m?(_L6Jwo5Op{=o;3+x{EdZdb|`6@3L{< z7G$11c7W5@VI%+V0$l0_U`?6VLLXddm^6D4KS_?qK`3QT^MB>_o4pgxrg*~x|_KPsMX8 zTK@S8Ya201iwtFAy+W>n29$6%@5$p?Y);uYpXs2IL)`3tBF3H{`w=(Y$)`JI+K@z^ zFIB#mW%=x7S%_cA52Ngaz9-=H(*#4=PJJCR2I>h013!GAI-7CIP@<<5*}Q>bIN=q2 zRfycewj@OVw6W1{J2OzIbWU3XGEECk9DqE+?~iSu1>Vd^OUhO1-refVj=(7={lrYE zdrsUOmF3pFY~8Y`@M3N44%Gy{j)CazPQa80Z?J=hjqs+Ko0t0zfVzADNA>@$UMC;Ph4-cJKHgi?|Mz^Ag`sAeMU4M@hgX~GX zvNtHN$@NJu>X-T1Wy`#h3CQxF0dyiAC>a$OP?ewSShVF! zKBDw78^x3sg9azh{Q7P27;Tx0IbBSDKric=GUT>#Ch{QfEJF*AxUFtF%=8WWxTFua z=Za`k%1b9oihpbGbVqvY6}mOqf$0x*A4-h2bvt+dsju6s%QLgSH1r8BnRw8DlP7Ja zAJcVk$-ELaMt8+;z{`N*<(TWiWegcP$1~sZs$=>+*8%iVM^Rceg=MHY+_!C7@L5 z)j0+{jIg}+KHtj1iA^5pU_5h*lX~=9cvP2KbC&zF`mm6ki*3!hnwXbUm6xaCct{6B zxx&h>bl|nmjRtQ+vM4$#YwIhvVidlORZu^mlC^adOarw~4~Oi`$L{0_SGu+y2ReOF z^e_cU!@PMzWmef|;%P6hed;UR8~M6kX=p=`u`MsRUGl6;UYq1-a~1xgj+0@e!B31S zejxo))cqy$MF-|-pXL?Pe~BYep39ljvt2#63z6?@d8Ox`k83F&zT~^K+&g#-NQMox z^Z@z%xf!v*W2v^c$PZ}WmY z<*&nlb=l!ZeKneVhumNe{DMh;sBcIEx$(|ZvE1nU$#C7MW2ntr+k}mSte}S5XOmGjKFE6bzdN^Fw2)48Sv2h)A>cX zG0Nt!-oJAbj%>>2{z`eI1K)G=H+h9@R-K%d$#PMq%THN?=+1D#w+LdxpRM8*@Zie-Fp`l?dq+o{HbZOBm$zPWrV zx$|9Kd(1{ThFc;qV1#L)ZF8s6c}$TXQS`&y#HR0y7uD^JdLenFe((mUFw^ioT7Q#P z;}Lju1yNN~%@Gr=FY|96DSTh~C{Ayr%>>prAa!;92=(ui@RGHV ztcBL7g&#OM@#|z4$ERfus{Z_aQq2{-()jcUUQ~WHUcTa3NS$XrC0d^mtn*8~P%P7q zWo^VRp3__4%CE_R64b}XoqS+;H$dI&Z_IlbW-(at+E@A|eT9Z`v7#NQZ`#)n{Ag`p z{m6M8`OZ_6G$8VwhmdiLao$E8At$-Wm;A|x@?fm&Pc9=5+1VGfOo;%**!eqbpnQ!!-~_ zEZPizQ_u-2c+6<7MGl`}&~=85w90O-aj?u&j9LRcAG`0XzYp49k(p~*KDc(`+Q!#| zawi3?Y|!k(iRl-?E*s@G#<&xq9ws+-%Iy9JW&6XsWrm^g>5H=X;z3z*TAuRGR8KrK z!vhsJRabX!mU8D%sJiQs*EsXK-CG!LG2%+rfl%vDGq_>|#YlP}zr&ahZpjn8DI^`I zjg6fjZAHD&Zj{C4k*vN(6|lNY5p*9q=_Gu0FHG=$^e=x{mXh+{|=}+6@r(nu@@-W3uJnjK*@=w%H@~eS5g7C|}4`dpTt>lI1lDd(v^-dc8 zjRra%>EVSvP0a8=HoT4weZ2t|@hvFJyMS?72asW7dI`8vy=UAj$iIebxQ1)EhVK^Bu?;W^MTX(T`?giW$@Ll@=xh;4ytxIvDUsO45ixl4D;>z}-9XP@1wy|8 zv`m9WoHJ3=KLa9uAJ4q}Gft!NgB!m2cX6A%aA$e@8~g;=oKN6W1Q6Z^WM%u&J{UE! z{oI!LW!M-;;qXo?$_AHTCA?jH!UW0&8HPe|Q#P#HYu?Zm_ z>YIo_cnZ#%LRVoG#_l1Ix*0&%!1%SxxHiTPIh&=8p_A=Iz4U5~T}iACyK`PmZ?zd{ z=Y_rL!4<;C6YGT&2VDn9F%Q?rlNPXF*(DZl!(ls~Bd z@j5;>v)Op`$qzMFZWwyAO@7%YJ#PuKqv^jv_9xegBC#3DDVF0S2bWuiW%}{`GP`}- zYWUPOIsxS26H(GF)6rSziyz*qCra<$P(M`vWAobctKsNCqxW+*4Qd_qUE zUYwN4^OG`tc2Z`d+q}}3ER;2Gr973qSCTttll$&|Swi{#U^5IvdDvXdx}+X3dQ&gd z4}JgT%Tk_dJo9Q=PFWssVhH_0SA(e2lTPydpakijE4}7{rR02a%ila){@IU8xufx? zYH(fa+GL`16U`r!FTN@B|Mc5ZZu5;uPSa}M$+~C_6BM1%x9Kg!pzvzxS3xhnd{WBi zkK+5-%tOk@o6Cx$wpj-C+?8`M!c6#qDm>Ua9|x>DbqDyRZk3pUw>Ny?D#CimvC&|h zAC8a%>wXe^Lh7;(2=ZL7bo4z=b<+<&zEjFayzW@Ms@{57jKb+z)G-g@Fu(u)L7n5- zxcA&Hq&`KePBn>tm_ImC$SYrYpbbM6{yB#<DGU z52J0%e^=}7-MupV*(YV^NB6aMXw7)^sGR=(%d+@F^CuI*mgWP#TgqwCTZ~_=Tbv+8 zj=zm6L>^M zJVb~wv9&=^RZ#`Sm)JV@=m$M{dj&>UPW$@AFAwK!>smu$KhQ)VDbR;;licb+Kh0m* z{1eGn*r*6Fh=WIf)5`sCITOk9P)&WGv4uN&j$2)x=dm? zP2deE>FsZZ3FDLj-$)}3-$eB*k$FX-PuK4Fge`tcHp18#%MC?mt$g5dD%jo;R;TsK z_z#NHaq7k%n`4AkND9=@6`l`{RWn=*HSdZL+UV z$WOFp;2#sq=RfOK={QL{U%V;{ERS~%%H(Gsms2*mF*4G=0DX!!#=yhoD273T4i1V> zM{z1JA247;61Ts>#-_9UXiw*-9~-RXhd&$koc6R)Ux*Ci8pvOLij8SDdq2e3dRUfh zx|7Z)cGP!#LR39-#d+4^5eiUc4$xe~0mb^i-Ym zYE8>WI3NmZ3|?Xzbzcx7>v&$4Y?SjhfTx;|e5&cxo6x)h-QTA6Yi6Zyo&fTzZ=u4h zXJk49AgKVg1`zddCO~eNL6D-d{d#$0*cddDpIOpRGOzUO`351_VM6)>X>BkO(%0SJ zRrl_X5f>mSbxYfNEuda$U+PL>S^qe)j3jj)ax-2q1S6mRNEaZU`*!fuKZXLIViw=l zjff*J196>4&;dr<8N0aa(CI~T^0KbDM`%#QbQE7li(`=2pD|8HsJ5wD-MVe*;A7;mp( zUUi9No@?aWHuqki&eZvF!OzsJVXe=t)`p{;M+o!`EfWwHyyf@bCg_5p%ZJ zP>o;4G3yD2LDsH@5)EPiXN<>s=-2yGZu~e|%d3&Krk4*6g*WTNN?JoJ4L(oi3a5wr zWx^Va-uaqvc#$% zy_Qb{t>2_WA5q?Z=#4T3=9<~cAhCH}&X3*j0X;u}jREU{@`FIn_t56XHG!$udB~6J z9lkm%WQM}#w+-wgc(DT=D4cBlDe>}K0(q0IE%nAGYg6h4&_=0`YMf`=(r#UCR<#&8K21y2v zcL3k#{?*m#yM}Z7$yIgOr1xe0fb>sUiJKt8vO7Szq1HXNc_@ti!);za{U(F%*9Ww1 zLPQ$hv`0Gq8x5&j^AK#(xsP)hNEug^bzV9k(*}hMHphbRqxl9|n41-AF~Uf1Di~9s z=YbX{7>Mg!jCrUKN}HG}LTj@`+(Oze+mF33^H3p%TQ-^4l)>O?gY8M(wBeO*X|zql zE#I`|>HFNIY8zCNg^pqe2$=8c(EfeB>4&r}ea3}GybLoHlRRaIx@=->e3o8pOtG={ z@>N+Ly%b`sRaw{oWb;yT`G)OuXWOqUoMNcmWutD(o0ZEMo3F~7jaO8Njn?XiTOtgN zF>4n;o%hNy@EpPBFo$SfIxlqs)iTcSGU;qYZFHD|vSZ)yrnG70)9zv3$@G&+?XE1e z8EK&*!{4M`9#Al-* z1mCQiu^3_5;7p?&8?ZLe@6<3hmHoY9MIs(?=o@KlWn&ci_wJO*2RF--&1)N8g$KL! zRfx!=Z*Y3ZCy11eO=IGCGd1#JvpY`|nM$_nGs>FiN`lN(SL&Y6WP&j-($DfPjn@k9pN8#xe}x)G?=8+1T~Tb1M^|_)eoZoS^mT zb5QAQY?D9v-Mv$`KKiiCZtT}A$-@tU9G3}m%A*%$`PIWx9z0SWs+&ATTMHig>8FkF zK`I@&zPCR`xskQ10O4Grej4rhK8`RUdGvH$2(1_H z@Fx$Z*g%^|isWFPp)p@{zumah|+Q z@jBTSr=O(RzVu1vLi#zc?`1y5pyzl(z*Ikoqu=vD0tQp&7W$=#+bic!Ak#o|{HYK5 zQwelpWmk=t%I}PkmUMx-fS7RI^!QmFYtB<~24jsxg4M;wdT4!&G(BeD6-pitt}Jv- zw|J`SA-?g>yO}vb%Xdp%cPb0x*59LzHH)<@k+Oj4W6?HZr>V)h1rz!^z z^=jEaABMdqPbibStr?sK)M|k*b;THNl#OB>LZXI_dsYs z^1WYxqptDqVUW)?ycZa>i5sc11Gu2wHbS=NMeRE7U$2|rCb&r6+s^M@LF)Oo^!=`s z`x>s{8veDwwUPE3t^pWdFy{sRTEIWT$C&=-E%*+HR?^^{B<}{k&o==Vw80w#br+)yK7;nx39rt)5U zGur8W2G+%22fd7|$jWq^()7^9&FF(;ybZR(G}y9nVI&{LIgHhHeWRAS~R=;11(e~Ki{hTQO>1cv$NVOxkHy$z8N+z4IsggHjtD%fn{Q-kzK;d3O?5+mPiaoy$*N4|15&y0S zbm?iv9;ewPqZ(&d6rhwO@CK)iF+q)r5bk<9HvEEZ83k{-L8&t8bTM0$`Q)_Bx7BEe zJ7xLFhh^DLJSlSaYc>oy&BEp?r+zRp-MLi_vU!@8%}ETZw{LiZ)`lWBa*<&}qSCWj zjzJc~EXGwfK+%uQY@aw%JT^6Lq?I2VpX9--138W3(?#-&4Q5W>xWn;%xZ_vSQIvG# zVSR*bq++DS_@A4u-R6G7sGsU4Y$kT<1G+B%@!YTD_GfS91#pskS5}jHf7kjfN;Uhn`K+bX{5zVjjufE z%EmA!cQ{20vhjUGZA4z2*iC42LL%-!#xwbNV_nF+!~-K3YI$v=PxME;R^~wc4{!h~ zXqMF-H=yTRh4y}eK2GZ1_%j)WU!Nv$3>gKQ{ev-K!-Ob(hMtH=q$8Pr+|Pvc3+mKHTGcaknsKO4i8DYY!u^%Lodz-FV>lp;IIbt5`=40) zTlPEh#LsOd%J?BOmn8r;amAd4LA(z7dI0T~zjg1hpWg@vfmXL2kJA|bEz=fIF};Dc zaW{c7cW^2ZI&A{i@i}lo@cRQ487XtF?tNJBt{44eJ7#*%t)e{H!nA^s76TXkF;5*j zK9K{mPcnBfFVXLr(>#~R-}6VHArh0P`%2`A5b|aIWxj7lTDeKWID@gSLh@uT!$_Ma zY1`bTFlVQDra+`y2dSTR6lS!hA9I8-t*8^}H)H&(PHdo!dZGT(xN807b}|Ke&Pj@Y z@Scwp$N7@Kl(#JXu*QPSJH*w08-MV`OJylP^+0{FW?)$4TC_d|CM1op&3h>mKTte* z@pcqGaj~~sujy1LT>D|Sy?`MT9yx=`0WnMheF&6U*`8_K_2+?dZ%*H zCzv07eH?!FmwF&Go! zr*LAJ`5hTt&*b$lr)e?H(#J8<^FZeKmCckfDeGmFZOG{1 zf@JRo-oj15w-#K{m3`N+vCUJ5tLV|kze>7I4H#eMQgojfewHw$)A0>|NpWB)YLx?EyyfSrl=Mrfcn66NQxS}%l~l0LACg5rj+LEcnTdY`17Ey`kBeg|7+ z$;ntY)G<5(0of`h)$ZeJKsFlb$0WwUsmw zK|dJbya6rDldyzioZXTfHoVvK=TSCT_{b(QYoN!jUg~r$N0k1WFSjv|V zO8Fd`-(Gy7vMV1>Leq}EO{K}SG74I;CFUqA$H1o9=^S?UL*zc41~SAKv*)VvVGI&pm3 zNl2cVuB8{!rWiJOc!54idU@F>Np++Mq0_{ zp$W!`;}Ks!#HY_VFUfS9(Rbv|wgO2*J_hl4HAwfsa|OM(d1qcp)L z(*VSS7Sua{e(sOL)Dbk{C!yy%i0H%c4RI5ws{us(vG*7#=T+c}(cc_0!%@bY^ltUr zhvO&g)4<|}(rjuz8xrYhJhF0Q;@|Fg_9YX!tuQKj%#<&;d z8_j;5bI7C|tfQQE^&2BZbFFKLJM!@w28y?if}Be{2g&VkK$EBBwlyu#<HEf1g82XA=uf~rRX6akbBDCJ_#^TR3lNsbZSYF@r((VR8ml?>~q?xWBi(=Tb~Pdzj$-b;o3-h4c7pS7raf2;Drn01>ppLTNYRA@?E$XdmV7$D*LWsV|%6!SJ9)7 zf0c9>fn-@UbcBYa9oQ@52D@-q+;4P9AO5Xz*?GDEPL~o~U?pFvF71q&C+y*c8Rk3`SETkAAr9QZ)_$_4E{ytt0%O|hG~zT$n1C|aPiP&I57hraw+zd2 zvN2_&?NM1i7h&Qy*9;ZW_3pkr4T8wqtDN z6@z?Zk4<+@OJyF%l6@rEoTMc`HmOO+20bTQFw(N&jq%j_DrxFWIrLwVALPOZ%jU4g z*u?!*vX4&72v{=r4a{(`Gn=H0XJUS#dfnOKa{I3A0 zK1O7iUIGUF_X4;=)VBj`GF+#_nRf znZC{ZL7(i6wD^O>ai8nJdG-AXw~##DpX4BK44pP4k;Xql0dmO)BQ1F{m(u^8pW-;r zKp-hHQdZW3<>RJ&qDB-FwJarOp0`m^`S?1HGLomz>z1OkhVYOD4{cn%UGlLvPwo6DqYDCsZ}OTK>4i2UPCEt8k0Wy%8~PhQ%XYQrf;T26RkEJd-2 z>Jx)(7-5^y*X2??=chTvZ+eg{uIaSqFCIVFS`;$94oNPCV1L3xbQz7Ib9nd}3PCx9&+@-vH4NREgcwJ0d*&!${?c!+Az=5Cg!`=5``Yi22ALez( zT!-N1l(R^spyK62TK*;iWf66|pm){{G~0(VDZHJWmAstmU9LcR8Inq^OG95)<2rxb zLa9FB-S0YVeNl>Jn5iOX9Ka;_1|xTtWi4b}=vdAg$Z{l5@4fqN!n>0DeFWE4k8cys z?LZsgO?23l-(_XKj=t|3-gX-SZ>ikxW87Vj?Q6J(?=@T-X|LfLfbn97d))$f;i7m! zcnd~;umINu7m0oska=c#FD&181zN#^zD*ci#BHoI{I8n-x-?gnu?bT4Ivm3qf0wf> zJFGF{rQ0CCx^Znj1qj43|u^aUY17~Y)_O_akpoF4f6KhZrS3MdYrJGVSp4&Fq!#$t=+B` z)b0BLY>yDpnxc6Hq-*4>1Zm)1@peRv6;!De;CnZaDVl%CusngAZ7RxMr8l0dF?GHp z+@2a2pxg^Kqj$G##Ldk!%9VLcauXdtd4d>eG5BK8T<&j|1*h=XXmm8ypbaBJHW=N9 zyArS&mxA=)HjHUt;$tvnQ8EfY_3~!5C_slGE>V!tjK{I*%LX?x z;MoYqz-L38;xWGRq!=>yshh)U7^B_*=M#CgJcZ;5W}e8xh{(n|o9t}3`_-5VYY&bH zGc7c+hs?v}3_f9<-)Jm0NV%pPGF#(yM%>t)o6hI~r4PAZs;$%D&p7b|3G@q5+PNPm z$V^mn_YL|ZoBWJb{N0b0#`PzjI)t)`PuoJNQ^cld@^D|40Q9h~q8NTL0{2GR26E6I z$VM)&Hl?p*zauRBUzQ=rY7I$`fYwIPL1q;)JloUbGz!;}) zZO}?xg{We6LZ=`@kc_qdZwRg27r z-bkDCF#Rn19sS%!S|PleeAU*V+`TT&GxEzk8Dp`gxj#YaTZ~tExAs5`^BMi06P!Lt z8{J;%ZOH+OkPb6zk-x$7LxjUj{ySqB>E0UdL-gIe7+B z7O!9A#k!-m;=z)J_z9t&V}!J)Pe=>BE}^6JrS83Mp*!UuFUmz;lvOA%hjH@XYZxdw zEsc;gP6sG$&MgCwAp1qQ+i1)yn082mBmL?B-`<%pw~_2fm^v+c9kH?h|0nK7?0YdY zJNDS3Hot6S32ZeliLxz=X@PYEDAdt(fkhHBhk1YHuQO(BG)CN<%~w&oO{-5@!34>r z4}QL9oD}C-JwA9zsI-cvIj6>MGc|vl`-7>V40PUy)FCkGWl+)zt#gaJA0n?QWn^uQ z{EE9w2|o`-$}%5Etn_{ieLD4g;-RE_NTlK&^Yp3kT6}*;*jAyAQ`qpp`E|zcf%CdM z$SWGwnY92ogdZDJh0 z5Z4Ro98k@}98&u5khn6F*59Mt3PBFklb-9_l6&{1!E+V@;v3ZDc6&hSXUKV#&*2pP z;h@S6+i%lB9}Zg%Pq|sk%?#yV+}}?l!S99M+?f2kq*r_$a@{(;c$oZIBE;m(YxK3k zI77RmHSsB#@R62a-ZR(~DzJQPF(s$Ch_KT@39>AaZ^d#T#)077^=kc5r0`z!aCfD+ z3W$xW&oWCHgjw+H%0h?KvFppFXZG@9tI)xlPAGb#Acake>rX zAMy)~cbvQMjB|%NIIH6HArD!x0kExGJYZgCeW?oX~uwlBm~$89+sgzJ84-Z^GYeXo z*%oi3*K4qjMOlaFg}%heL)YA%Wj>M*`aYEP;WgCspz>Vjz}aDTLb%@tVqe{%yXw7y zs;`gI8}d9y`as1@=+qlm$=xyoZWdUv|=JEyPKy>}lUpeUsvbBCwcV8Y=BMK1Da`(0)#d zP%Z1idTah$Z=PGSmHwvwiOgRFhV7&%>%wb9W-~ST* zdx|?9QXZji(c+-h{=m&v_J-IZcC*7&xDkm#&ZMPlzrw%QEWK~S%h24{A?F7Z<)uu2if>4 zYT7m4gir^np&z;qq7Uke?NxcaVKt?Vh&~Q<#){A7ETPZI%(H|e-pXQ!yr+Tadu|Jp zrc8nJ{k{uQocD9Fr~cdl!gQf`C9r2it-8GuKZOmK zCe#@N+qRCkiu1ZV-j4VW=*O`bZ>Xgk@m*x>=)+=>8tz+b9a*m%ME(K|4CQ9nsPs&f zux%oK28J$)Y*B7xm;R=T=RhV0O*yD?oup^PfevM+R@Ydv5w;WN`IY?y^L)1}zTpvh z$=fIs(T8L>t(S!9YxM6naQ_r?2*)8FP6Td-aPY|2=5osx=PieJs(X2PvAV!1d2_wG z;IOC;mZsmXy^xt7%-VhiQ#w~+rDwT?&D0X$9VBjf`saJS>f>5^KCIUYmE-W<@kg5K z1(U;AJk$rAt$eld`hy}LuU8NMal3l>{9y{Y&B5=YaS+Y#p%MD#5Qk;xE}r5K@f)fW z+ewaP!24?Y%H;bGH>))V+uS}HZ8;DX5t1g`OdJta+EDozQ)JR!*-#E8iSwIwHwfhv`OachY)%#gD^xk9+a5V^nj4kV9^qJ}EP# z3k@e@6jd1^`lBa=-W;NS#X&ncwI1SZR@sAO@Q<;!)5#867%4t%P*f%~eBiCn{8fN+ zf*VQ9dCG9i+TkqXusZc~`0aH8u{OR*mLkAZ0K@FSTB{_(97uQ&JcMOI!JmC zh8$k10W!ydvq)yM?XVYfkh-i32sy(s4~-5_`Lw4#gsnO7#v$psthk*K%4eK1#&)>K zn09_EBtP~H(Z{`uuY(f<6L9kwry)ZM&ay1IEK6zktd=U1`ZEFgr5*k=H(7-tLt$rq|Pg-dO9o^ z-1_Q;(DP6c#t>p$acHr3Gbh=L4e`lXX5M>Gsr@7lyv)fl=Nr7PAjR#VB~*fWpBt%! z?4@4E@DndP{luSj#fKI68hGSp|3nOwPkDi*aq1X(3uVDzQ3CuS1=Yt+=!dQH!6ZM& zm9{-a)T2)L!(!M^dSgFyr%(RyjQaGye@!2v;dfpM`3mEIkuM_tZ=AX0sSNV(i>odB z`d4fuevCl|mgkW7CzWSULN;=(i>f(~P<6?N?0~18Lbn&$Ijef3tw?_+o_TygiTxL3 z%u)vsrX4(zZ6!#J=peJg4J;C7pTd{T@=?#QQvEZ{@uR#QPHVao2@Z#~@4` zlw!;ub-^ICU6_MV*@Jwl6DIC?uh5wD7G}vOh+f#h(F(~oRhh%e-{`aY$t_~SP(G-{ zT=i{r5kCRoG7&uBWuQMDsEpBY`89x&|Pv6Oc#o->i&Io|rT zJ+Hen&N$tv}SbC@)`=IsdIykYd_Wh^(xmaRFp7ZsR z@JA7SJDO-Z&x4+_KP~a{nuwqufkWj)r_h0W<~H_Q^Q+(x8;|imkc`*b>%%``Fi-y= zZ0)8B`kvA;Y%~LV8%>^&UZ5O8`M{>~lCQsw`W>_6$zeSbFG>bM4w!(;^%9*&e~Qw# z9(LkT52siTRB_Vs+qHlGwR-r!zgFunUsr1m@Gkky*6YNnwsTlXEmk8gX{*Mt%mJA<>w3sqPvTuaXP>xxyW-$tfvy{V!@$nc{T5>P$ zKG;EvJl}}s5IasM9Ev`0hc5)Hk_8Wd6XzdpM2YCP4;s-ym0g!MkY3!LMue1Af&pNT z=71SzsOOz{^1Hge<@If~mQB}^Vf)^HQ#;l3p*swU9Oxx;AAy*FIES)1r1gy?g`_F> zEh5>5-{hli4s>zaLELZ}zgfzmx(D$&tFpvS`iNMc9Kv_m`Wrkz(jfNEAoMW+j*{opW*G>d$H=3cpeN_;=b+eQSD-$2 zF)5ARSR))nGjFLIXKdy$u+xHZEM8qMyr}ELZmkR78pZxK8L_eLsP@c{e%+L5U;WQ`k*B{O6wAF}L58z7xL$}4IVGcS1+5c)Z*IL}?2 zf7pv#n{fitp1zrv$Sm|iIMxE8%5eB$zdyBa{HcBs_f1wv{rf_wx+bOh+F?IWsvNu9 znF??Cil?9B(g*oCOj(D7R!qcufIN3Rmgpit#&YMb+xdHMOP-arx{V5_&KKdsg2R1}s{b3^J zBmIR~!wQ+3%u(XJhsb*g-n)5yt39$auIU7N9|JcFkB0QMhjU8b=ydXe%6_CO>veYF z(0XUgY?b(P?YGn}b7M9~&UlKqK5ftI?u;|ecp-K>X%Bji^at4z6%N_3cFI%X5(~FE zfOoK1HJL~7c^AMQB5eE~9ym|>Sp5$UGC?XGRQWJ$d(;17bX|84@_t#8ioY#>ROce+ zx$<^y+y&~05YcHH%(5!Y$2|X`?exo_bg}+=aR`X)B4JxU#=*g{^g@Kq(5v$n`Jicm zz(`M3CnB8#Dl!CEA4+bsK=XX+_H@wYI!L_b^#eGgLh^GE)#FZw$QN;NMSBh*eK4mC zzG4rD?H_-N{;=bgo3=PVFRrfqmATiqx6{`l*H^}luNKZ6PcYK?s^beSiOVWiTH+~I z%gGc1@xbv^5=i5ubrZqnYZ zR-YB(l;yCHLo?s(;LuQ{_3WFoveSc|f8SS^5`%VL>I&(e&8hJIdirhK>GrDl;E>|* z5nevHL>EGMLrT+EADW8b=yVatfhvwh1eJr`2jqZukR4q@$$F5ioMT$iao{fUA)wl* z>SISB)rJqw(r=OjahukTHMI}XMp-_Lw4MnC1e)~XLu3&Lz}Szk!o)$#?WDg%UzO&! zb_p#@b!hAZPV^Ib{=i!yd_9lhDZ&}RVK|4hI60AF2dqNMVMkp%X4NO;bCVpWnt#_% zWM>9(h5a@p?L4OlAyiXnNFQu&o643xoK{+YCKMg^P@HD8Hy=gNi?K8*PTEdd$>*>c zeJwwva(Eac@`y246ebQv{uE3h?PolCa`aJ1d{%uYkkM3_=1OHaE(0+~wXcl11klyD zo|R`C$qpM%i~`Z{v}1rnei3^U>ja%WFKQkzrWt4E2X>8ZLHdS#uTO={KgQHwmx`X^ zOS#8N4bThz9xvvwLeic)#XEdEf0QS5H1SGLnM6jg2v=+MLd-jKXYXQtb32RvU?<8^ z1Y727*X;y{&=nC`}!#fkqhBA(RUYLFMA@kM4Q#*Q)d zoYYt{4{`J`=SjzAo|iSA*%v)G8Ef(>r=H3XH^#fD*ck9+-oT%^6o(S?$ud>P&j{9l zC|}d-{ax#f^@dC>harThx^1j zu09wuo{&_x-t>okgJ%T}TH8_;urGZ}sO;&6E2PG8&ccHqTJH~G_BIIli~)qb<1nQU z6ng&>V~?q_&@&tog_9>cdX)qmoVnKJ94kOKCze0Za(7_=GoRUG?u zXCpSowh*>vue38?b+ES~1?}V&<(BrX_`xUNRKWW##teB7=y9VJ5T)PPfam7e-<2M7 zPjTwlCWNB!aM~FYh8!Z5KlY=f8)1*EOFuKn6A@miK2F);yjC4MYMYJxK?~Vwd@xYy z|EQm#u#;BxY(MeZc+abJ2=qRHUfwBv0Q4)AG+^%aG6)@d8jQ3PmG4B!D!{L&mk^!< zso(SW@OUp6CTaG57M9w_#y`r|OXGYDUSpmVuSGVq%qMCe*pEY0e6C53!IO1&#u;av zaU4!?lQtXCwhf7V(Mk5J`R=<<_5!w6?YvGz{v_U8rl8_I>vzPqhicE?Wdl#oR5+2b zw!Hy=@f(0c-pRZXoZk$+0NCzS_B&)wRh?a9wu{Z19O^@rrsGR=Ld*{n4#8-mejH)< zE1X!|vi*DY@CAqM!|L+tdUbPqySf$K+}=3NEz(IF`e>u+z54^#mWL5vsMq`)ieOV8++Z-CeI9KJrz^94ac$jzQ`d zL&nC=+3&K+bVz&g_512dw%{BN(a0e{*L$_|O`U#_1A}h)T53&QeonP=chudaM1hl zZlXANX&arX1IBz-$h_i^*$2)d4pTYA=T_1mIBEZuO_in}-yxNwKm9=-a^keJgIa7M zJ0V2A)ueVfSL1wzH;3xEHObgnE(h(BM>$_vX(z4Xan5qUYv+R63`ZN?P{$OV;za0Z z^%om6Z|o@KkXi9QrX8`1ZCbps&*+Qf;t0rLGkSPkR$aF<2Z2cE-{rOZxeiX!HdJWQ z4RoE40dl(N%n#4YB5cL@;%xFkuw+n=wSiqZl=jVPg>gW{S+BnV^HV;Vc0j5=_Vaj) zh~xCO175bZ!%Doua{#`@JGZzQQyf&R7xV(O;n3WU5{1ZP{xZircPLlAjWL61!XEF~ zl0UBo$cwIt+YX9*?Z~EH<09L(2%t0jJL`h@m}6E{fG!P&rdsPkw-l$ zstkv)9k!#8{@2K|RAyyB$g zeU`t?L_GXe+G_9jBTZi5XwnMN51knY-aqinWSsmQS3j~3+x7~FeQ3W2O{|f0*NeE< zh~jooEAI8Fe1?#;^NaG{(!VLKelj29jOD#2dF<8f*;!-QjsfO_N{kKR8mjRzRlfqK zd&UBu*tXJH6AmT6*K?dOamrmXrMuD6&iO69O|R5@g5=X~PoLfkY!Y6!+3XN(YyTtd zJePB9e|G6PE8A6di0$&X*`|kuC+(NoJ_9FWvlCm_-5F<`amHad@z)*iz^m<72gvT& zSv9;~NI41pZK%+qzb&>sSe<={0aB;JeQ)Sr1AE^bNT+c?@q_7%UkpESP?qNDzUA^} z=8!t#zWhQ8Tc3Rf4i@xwmR_FKrIH&SgFwnE{WJE=E^;Ft9V_H43{c0UmyNh6hgNlN zX6o&TbGVhm*K$ri__o;B)x$sktRC*ytBcFa)um`+Io))%6ZQ(Hs_0VjOO-+7U#PC? z*p8@MDm%~%zjq6GH7UmEwzHkIO8Zuf2tJl0ndaXbV_*6g2M+q74OmfzruPd}HpAt|;j7 z(TPCmc~%E9pETLoV3IeNkA7p$s1EkQR?I;<=rt>N9f+6{+$6Ijk@Bf{(gz}5X_{g$ zJBXNDMZ-y3E8+x10qr#0jdQ zi)Uu$6ObtLLbgPh{2>z&&ncISvPKiv-vk(iSwq*&7!4k?+*B_PMX{BZtkdi**a#;r zA1vZ|m)o6b0|nMmgq>Iy*b)2LNvnOtPFfMR^9*F3;#7n$dpXK_UllQ*a9;9L6aUHYxodp<9t?d-9`N`U zO&OD35PC8``7lmCY(*Y+8~Yj|?TZI(mw;{#r(hsWO?trwes)P$@3Ybyy5m_P!a<9D zu!p~$rR-y8E#=jQynFyCWe~j4g>kZjR(%SwzH!nHM=dX^zpYPmY}isrI^;FP7__wh zrhTX4AwXUdRz-2=9f7U&kL2?nFzo#j+iYvQG>HzKSkFOtKesPS?PvNPqW);UPme9k z4sL%04r28}dB?8PGtM~Uj2TYkr0tk*Ottam4cfCn+imTUcf@A++WY29y7{Z)Jv?*V z$1NQ_b`HDxPnr;;3-i99kLYKO<B7c&&f-XZe7)9HLi6isNjJ(-z{;Cw?!UTfU1*y2vV+huZk7 z;;vQ~9DH#zX3))Jd>n4Ukp83tf)ASb>SLuLPFm%ghwAx|O!WPJbx}9v zxJ7&M4_|kT43VKwtZY8?<-pB{bVcYE2QY*_i8H>|PYgWPPyzN$#AFl^>t$C1P#AP2#*3B=*24+l%9IB7Y!)t?d34)x--RGHWUhZRmA%Te5VS9t{!l)yH& z-DE!>cyAnhbEx`d>PH-Bv1j@W&&)-5;B4@LIft=oZyt(6z8zcq;P2Z`VnkcchvARi zai8(S*3ZPP%2kJl7(Mc4zflTUivnV3E( z5Bpgc+7XAx#A-t0-J%;vzTY2iG!~Mc=NEdvgQdI;sC@Lh>Uy5H5W+s#4#Jj02gOO^ zFks!qaiBlL@~iH!jR+?#^?jR4b0dyO+fu|HHXPrrZGcP&5K1kt53idVSI_s7*T*mp zG33Ot0&7B}7+YL~fF9q0rE1AzTw_xxYuz`|S>viW^hRIl$clj5)?gfgd)=k=;II%OSrpBEvA4@a;Dk#Bj_6J@d~$-LoaL;JF=G9Km3g0S;L;9Jo@G5h1x*M8u9ei{S|c} z%660<*wIefs^sS|d8&lXaL9Sj5~I$~p&};5d2uMXE0xHe0N=64Qb2v`sIr~37%DO) zZ|t?yfeM)u=BYUR^0mg;mG?ZJAFAN}Ms4}F0rx}pBhGt>j1l#5VB(THc$` z)_N-32EWk~AI2&l%*lI${@nE5ruwZLQ~xV!w1h<}Jr_+nWE-dsdg6>lXWxp|{E9=? zzq2bMZ`=~*y+PT>w`>(>ZqgoGFfVL3@n?{I`&g8pn;74GAoBYF>3|JTf6N6iBFjiW zcyXMt(HQ57J1_Mrbh_v1^@s6ZAALi00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&|D{PpK~#8N?41Xo zBt`M?>xIi1I1V^+l$KtcwdS|w0`nCs+fYKy-teF7}+JikqF#_r7 zVYAoKvEAz9eso|vI}FAe?Q(IE$#y&pyC!1XBWy}I5^{@1yBbOiZT*V<~O=NO35PwUZG_ zcrKMr(r8xLg4y)ZHfF^wPQfSw$l-C_6$Zia0S zRVEx0!F@{Xc%w6rpV%dQ=qrQ`71+pv!Ne_XNk*EaQZ;~5Y9jqt^3JT7`~{GhWYnYA z&N-4^JeWNN;}#v;@!A&*{c404MYy)`3#CJ{d81jza)7#Fn*n^p+6QyT_$ zGAY&QdB*sm9+To^BH5uL&FzH}vR0)r`1&9+PBOwB9*#k!DNv(}#7WYJP&b>dj;G_g zt13@29PdI%7#;6Z+(z>@!en%KT69L4~d^M+<4VQQIrsOLUu4URnuOF zGIsso^(S0M+!e)_MZRpq&}@?n??li)w(gRPPcLkDuCD`~AvE1QlJkqlBdB<;n~1wR z4$t|=Xo62I0bxke`&!1Mb5%A0+SsU>%Hk?*O+AC52_#(y)&nK!6|oRzCF9|4Rgs}D z!7R~fVdGjQ+hbxZn22@oh9!zIS;KCV2nk{Q#T8n7*tAo_GyrNBk|19yM|e+$FfKGP zjJxIs8@^aa*)x%NA{54K#=C!l2_<1eBoqptzru8lpRpUgkyI+iWSBxIZHTWLaVZ07 zWsx~kr3<5&#B|fQbR_j+W$&A5Y%tT^juN}5$G z2_+LWd21%tuZ-wi@xbbsAD1N|eAh$cTcqr`Wi3*o)(Wx?A2$rI9o8PFB-jTJ63P{-YjCQx_8>Vc?vxNU;j^0y`0zYzK1f8vy0*~X@smrb zijDy#i40>Sa_yQBp48$cc2@{7({RHphTue^C`!ZW#`P!j5)(E~MKc9yR4(G|LVtIY zj�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�=+JWZiy@Vvm~MVg@MYSW(s4ER7sBJ)K))+8_Bj##v!|5X(uvKFaF^yMe? z-pXxYev})VpgVEmCS0R}XpgU#A!r0j@0i2Czvs#nV#CR8Yve4qT-iq@fM>ky5Cg0D zg~7~>U?otc&Sr7c`da+N=}%5_)EGq zZ)mth9|m4t2nz%0dK&~D)SwGrG~+B<{xolaHX_{74@cG=pAGwi%^v~U+|4nj_`?Gl zTiqtVdY1LnlSJDnthsdah_$EHY9#gH;cWFs9DPtSy|*n(y%4b0NG0U+J9Q%O1`dXV z)*pGvrg*X8bgJ}&xneI*q1P?A*7)~`cB{Oljv^p6ClGvIj2gynF5(cB595Kf>{#M%CuozK8smF-T#X8# zlAVptov1C#EDtprt$`EzcU4a4w$4aJlft42C-&yf6PfA;V$k?Z>D10M@D|(g(`Nxl z8aT9Dkm(%O}BA=8h0qfGkN*L;yfFxbw~e0%`n>npUM)mE^)7bLyOk*$YU&AZ1_%Re=t6a8*3$35#y_eAbHw;+ znC)MBqbg(bej)vmkmfPyS+c`stfWY}_G@yv7O)mavUJEY{7A}3-jZe$W;#@HVy7mH z7nGr>YIU}Vn4MLTc}ux1ri$%OKwb})hQ8|qmv8ews>QaW610)4QVGO~$ei5j`102@ z8^kPXrD75ODS3djB>qSQH)|?7U^t{^GSW@YHjnN}i03{1RU?=IR;T|IvRZBO>84;k z_ID$b1!j{<#qCdPy69@2cMY`S9J$N-4n@n2|+#e$CLuR(<0e6X@dOBlEb-> z)FUD@U_Y?;^DEuxFYsLD-qp7F)BmNa1i`0RBYAq_tK(c{Aq*FPMNCqgX2AGGDr_~q z0LfpWcN;^*68Gv~UHVJz6Gi`lVN9z85uts)W4kv;FAT@lk_?gsG3eIT*nF6X(8-@8 zlR-Gb>pRcJLS*tYGtCc@e@`NgZ|XwYC0O-TFKu433g3r9A6Z^Fn2?~Ydf^|I;dBi0|2M!7I=9QR`&E~>2eqp*D-{Jol zK!6D9kZU%j!;{sMrI~b>BO)i7(Zi~M7@@*P@^Fu+r zBg4@-81dL9-0dZKMed>~oO;&e9>MQh~&xVh3gYJ(_7rXImlMZaO@^(D|FU!`vv?}ZKlbI+?PM zA(nGc<7RL`0JwXO%=5AphGmj3w5)twFFZzwhDVc%n?+@Ilg>kE3BlQ#tE%$YD@77w)f91uJ6|>ha$79^sI+FqgAsuT9K6 zt8fh*lG5UEw}+D?lu*jp6eJq_I3^L3s9tQuyKsOKHjYb*>iWM0DvSQHECf6=Ejt-l z;z_X59d@ioBUn=Fw*xFH^oL*iYoJn&u)#z~9B(3dHC#%X3@Ci8!9_ePAUitbwPtCWqIM!Ak;<%X4@awQ3 z42C|H$J?4cyneV7{7<38pNQzq|0$3DWAl1kAZv-*TsRO(MZ?`_6F%J+k>fOEwAkz_ zpjNRG9s~pq6n2`~?HmTnJ?|5XL(J$ZK)t5jMh%x2Z)u-+!CP3=}NG~#p^ zwJLM1?2xqTr;9hihuTol+a7vMSrJGA{Ue$v2y8BN~nEYX1;47HoX7X2%r8rWy#Cz$XSc}YP3fR?E@wE9TpuDjv?SUTGOa=3 zdMWFcE&a!#^O88hXbd&|Vwk>E^wNMMMaMZwPPZwgMyb&bMKGe_qs_m5o7k;cn{aT> zr)Y`m>kwtvf=_B>b2`ABT@KM5UGd=Du|xDIWGMENd!7!bzm?QKIosRlnpP&8ffTo+ z<IRM zF9p*6SImx0=`k{*g^3uqFS!lA<U44~RHR=`01kLasVYhhcIF zgQrddf^3z?k0C880%@5_^G?U{bcqE52_3fFu5_!S@ao8>g#>H)44DT7F&^W02_0Aid@nsY0?^X(iaPoji?cgQTgB}@ z+XpS;u>d0WbNR1XvnRrjbl}uHZ#)-F_wP&ru%`V$&X(Kvr3|8Bxk3LVrw^S^h_>EL z(M#f_g{5qpT%K+6&tf}ji96cTd{Eb|g*E6C6AWQ?K3lt4K(i|8AX{`klzbu%JLN25 zp2m-HEhQY`(h4&X$()M$-M1}0CPD}O%WIOKwVh;}S!)`QH*Jelc$sSf8t`4|Xhj=^ z6Nu|F{|Z^TtL=n@E%4QzadbP>4C@_~0!8_8;W2tBo@5Rfx2bmyg^#Vzjs}uGQc+zGS+)(>Ku=;hSdx%Y~F1ZotRse zq;>`$ey*)#=RfcLGnLGi@9-u^*3&7C>Xawf-TpZdg=kd?KQMDt@&=ZIu$&`JrLHMX-pwSfkLzn2)0P;rc&>F&+fgSg5 z6LAfHQ9PgSIas62^(-*iL$y|&MIXMxmCVG8o}(rF_QUy#Bg$Hq332QO z-<~+HKqqDQT|oj*$EuOU6>HJkdhP8a!J6u~E%Eo?DAJkL>&n0tv1n$6sSX~lV^(Ii z#_C!y0pfdi5bQ`8;FBQ9TLhft8X>upKY~am4gvGh^w@8^z@V5E1s}9!-M-IQh?_>W zYO#y;y4R$gPl<^zB40*I!8*Q!PKBw8E^E+~fmYQ>OI|o}LdSP;Zp;u*lpmTfxf(vl;=6~LDJr!_@v<#T3^FdT8RX~dPSo!uE?Legf2x<_{mtZ9& zAum@Fmo(~q;1?iVUj8`)JzMt|0oe~|Oe@gazY|Je9YbnZe!i7Uj-0~yeEK6*hVP!u zQUM+aPYK^mtbGiatp_xpvhqO2IoY$bWlVbh#Xf^}RHxbKUKDV|i1)<;CO|+SdGF9n zepVk1MzMjg@qDo&CgSnz-xgWzYWov8kg{{7fU^J)DipFp=pEOb$e;}e?%^UvJ}o|T zK--%UG*YKPOS;R`Xc@*_AZ0N2Jhs?m0*(4ZDp~Ji?+vaKJjwVVX@Uuk8t&zqxXZ%(-}+ z3P z{$l;bZ&~nNIQg?X^q3O@YXFytc(~rdHS&PtjI36%F?#Khn4B#w+tU>Gk?T`VU8Gx% z_UvR4rC&JOAErDcLnxb%Ni*hnzsqBvda#NTr9J)MmdNJYQ!g{OQjUbjSqPxK%^P3% zD%9@N!OH%4R9qgEq}2M2Senk#(2D9n8gnYz1QALr&dkXo$G~pJ&RNmK@B}2%1p9Vw z9MIXH#7m;)b?=v}70p%v`VdS5b!X(u%k4gH^oK#E>Qjfuo#LwF8Y63&Zh-77 z(#ZlQgF*@s1$>)XJs`f*t5ma1BP(kLM zB%sefsx4MgALi5hd;RgSFJ!V&THC=}2|wV)Nf40CR6DGJ@c4YB8kd6aFQQ}geK6D! z@qfbYNdYvaA3ErpOVBob(lP5{g6%Ea7(XuB$Z49PiZsia&zpZ>+@A`B`U07ub1C|f z6YD-$e64lDGk}zG>9>#hRQ~5b;~62WJ?y#Y9Ty$9oWV$^BcO}}I<0Xwv>H!@sD0xq zW7>NT_-d6d(e!@13?^KZ@9ZUMb5}CjMeemSJpJJV>~u7Phh~hpY$G=v^3PEGI-9HO z*1MORHLCm-B2M?v5LR#uF=$BRueazDDQ&$#2a7?6X z<~H}o_pQEOC$O+&4Xka7^jLvyqv{D)k>g_fC_jJT%Regd1e8-dd?ir|J#+e16UB>i z;*uamnX1bvVt5<36wbWEp1fpP3 z{h5E~#a&sM-k%lLQ=QVrC5V%=C@yY*P>4{w|hZqs4=iJEjTU*+Vxdn_^6CW8B*ArHFWR|J*V-*Cemy z@$zLuvG5`3&~pu()90GCqP>oACW6;tB+2b9ZY9=%9aCIBV_PYR2Ku32bZup)^5{mP z_GQo9V~P!!g_8y+u)A8!1up5hE{Oufh}(}P9{5kiQS1nvO|7l1%5_aMSX5fn3VCur zq;(JVkEL{rXjGSlioxl$R@c@tcQ%n;%s>gJWNF_Mtme+g|>??^2&Iu*2Tz$*Om+Sqjmqg0&#kZ&s>g~>{Rp=_lI(rg?qpux-Y$9xk3 z5MwxUK3%R>3}!>X4dZ!_|LviRBhR8X%k84pcCzLNxDLmz1NpbjKZXICR?lfp6<0qG z@JU-dRh;ZrOtX`x&Up`|G2biUC%z6{h@^<{ z4Ntl>+y3Gm)~2UfHMy?Tv*eugo^;QzV)*?a?sgg*OBCbeD_GPqX47Pg|8%|fiqKvM`WZ9PY{@_ZIpeh=5r zMvTi&CVD8&V!r-0h?McLVN%hDMT5`K38l+;%zn-?v-CiNOyNPL)XwD-Q6*C4RN;bIe)xo zzQTTH@B3NzTI;&q;1@)!B+OMC;r{#n{t{X=nzqT%ALzlITdsKn`YLeuxLbL=YI8cX zNiz>|2Pq18eu#<=tSeq090JuKEm0>p8Ao{$4a9MysoE?BTAsM`UZQ2Sto{VYvud18 zuGZATzO>(5jRD>fezLv1aRy{IjaE_UMS`%Z+eGmdqhjsr1zyVzN9NtpbXcPe{dx$W zaG!=O_99-zvoqf zd_mUFtQV!F_SfV^yF;&BJdXH>1oCc9MErr`095W>4!WQ()yJguaRA?r`f->PsP9ZK z15hZ}n+;6dmFdF8Nt{L}?{m{Z0mX4FmDPja#L==PChu>z$GoG{y#g(bB;H(SCE^{| zUp(lRaP<~pIEZ~SBBGs}-};FcO}QGgb-Rah6SiTn&Mo7u!7hcm@a{b=_th89Q?l2u z%|4u!n*u|wcfmLjNx^A9P58p^Ubd6>t+SitvreZ4{FbpVUvcfFxE*|ij)SLjDNow> zWyQ% z`^eJcyV;VAI}-k8XPsN?HZPaY7YbI7FvUJ6b??xH67?}~2m^rv^4^s@vfrJVWDs(` z)1PW(?CD_pP_k7YtYEwDR|3(v&gpgny_DCjvNJ%s2(!zhJ&d}Aus%XDVqKHf8zSHEMg z;(`aY*d(dqzsZvBdR2MyMRFX@JEp6_Zi%u<4E_ZG=c@gp>ZZfsXaVv%U;ttb>X&)G zO~C0`d{YO@ds@Y?eyD0tz7$)dU8$7FXj8M7K3w9?cKkjF#Y}HZ>4e-mSj_eP`pNp;005*Xe;M~ZO#2UQv*3Dk2>>!TI(Uz)Iy9VzfLB0Kni8Y;9Bct9S zx$k(3Oql+{t^9Xjk>O@B3UfyF1TeG92bC_G+fV#)_`F&u9b)T@Jo^`H;ZU2=IF< z=U73;;Xi`3dSQ>9ZqqTi3Wq}P-gOWrxy<54kvE5syU($3mge(+wscafd20}9pCKzT zOzQQam53H2(Q;Y=v`4JIoS+`-8~xg^4alPP;I=E6eel#K@_eXv4Jpkch7+uMQ(8Vf zVNkW6zDp^5ScGv@OF0(RTCTj7W$+Gf=v(S$&jl*p1F2TLFc3QmJ#$i0mA^Ka^jbn& zFTDCJbKqNw7?(I(`>QP>tvxphxO!^~uQS>n7;8K~Ie(mGBtE>H&^j#eih!?r;oFFO z!g%(2M0Kyd3^sWD7Ir(B1JTDVO1W=)K0>}lT&SI0Cn~ytd+L_DlY?wp-)fn8gt1Mw z_vS#bwl&q3NtE&Hbgb3eO&AhV#f?C^PQ*{CSr3HXaCTy&SM&7yYhIsGsYl5mEjMN1 zl{RQ!@S1-$u6&IFmu!s0J^kJzc-oCLq7u+0nV5J@J0kiA)H*CZZl2w#u-k=+N-Q+> zm0q~!2HP*OTZJ-6v{_VNQ+0|JhoH}mdTXVVi5ZxNpvhS$f z_d5SdT|YdIs9kr~+$;|o1IIdw;aDW#6=T1J#xA2+-- zi22PK1<8ke9@VMFkmwJ%?mtA$)aiYog77q2cz{};AQzeQ4y@iez%P4eV zga-CN%5l8D>0F*xW?IHXvBcu#_3YZvthFf!v?dGRYS}qI=}%)}09-I5K*-8W#9fZq zlX&v*85(x?HcRA-_TMTx^D!o(8cR5mb@avBh+0*cYxC$TnF!uk%j3&Q7}zL$66yWQ zA6C^wS=IiVW+2J6-WR0z<#~~^yQkfZ+P%KiW%Dc=Ff8-lpnuieXknopOi%n2g^px! zR%<{zKV$r}ycbdt94uHs<@q*(j;2xG5`7%IFhKNj`iq~u+7_@<4vaAiO6Bm{@_d1k=SOO;I!U5trSx*6QVnTZxHDm_7%q1#?smKE6uL%kA!f$B z=dygTylQ)6qqNZQ-Ss!#2?o|QAqY|XSYnij>8KHMyHr%hm%Qq{@nS`*sS;hl3Zd6= z?vye|lYpkT5WTDc-R%&4xSf@|{%O>n8Re7?upQX<$MGlIJ+K|x+%acyTiyW3g$+tK z%9cABZJF|y&j7^N#`7+Av)lQp#dY2?eD7gBVWoRqQ6X#BDd+UC_S4={KB*hTyt`ac zYMCE}a44=5{`?SBMdcL{my3I^_m?y$5L00ZpHmH9D*A0sr=_XVaoVl?m16AWvr&$< z!FiaCXAhNO1UgwE=DO?b{mKC_i$NWqBC}3==q|e7h4<+r*>(^wyo+JKN2`I?zIMRQ9 z>AjzTVOr?v2iQ~}@sR}hlU@qBUz4v;6W2j+D8!D73GK$P)ojCr8gx8A4aPD5YLZpU znT^2B?2dy}hYSL)K2tbG+i~(x5U82lSO_^-Extx({Uk$uT<(m-q zoj<2@g(C}cH>#?rvPUu(C+-fQ6WOb5#-F_VnjCh=b96AZ9bEZ#IFw3lk$6ews#iz$ z>_?Ux@6#DVRNFKrkXE%SPKJy@YltrXZACq;YIlyopxT;ctTsm`|Bllf`H)E z5#tv}B@hP6cGR>F5Jyt(Tx;~xUPJvenTbDw07x87imv=*_ z>j0{>PfE9srotmwTq-iwvL)ikdf9i&tz0~;k5R1|rHM!|^5qu7B`mORJm*;AsI|rM z-EDH)@E=kvi%sh&8G8t>vM*yY=7;WS)p6< z$h_2^6~Fsmt7K@pg9o<&ghUW@ja=^3R~j%hU$+aSLHp~r7DeK z?rfL_lJ#?4%w?y}E)nFwJ~;{fQ$g_;7j3{zyV(#M^=khYfCGGQIaB&CM!Hbf9K0+2 zz2&G_5f&sV;r4J%UXCJJpf#eA)HmV`ccRJ?$eC4V_`(hOaXP-1t0jpk$R=gT?jfl` z7a~0lMM6qPccvf+nWI}-pp6P0Iqz*C);Mmis1oZuO%pOe^<+|h*7ApYrG(aae7;dz3i%^xv;2fT-j9(Vtw8>J zd9f?L3F09{&H}VAaAthlDwA2{(NA?~vf(>X;^~S3)WiCdrJ-Z?}Oav%AJ48MVj*JP5~@j92o%eXc_BbJ?e z8#|^q1W3)XiGwHvFk z**tL1=p?Z52u<2*{$?_gZ*}Ae-5pJnO3A^#FCijqi zz<)_MR4mwJaS^ElmcJN>f|V6AOlK>B>JEL7*&JfJM27-;bJU%0m8G^Z4*jj?eNX+d zP#M{16+uqmb(f;`N5D@ujxjWOYvD0sm$FxjBfJk8vJ%`CfU(xhf>yE>fK;WdmZH%>%8_p~MTz3x+?op&Ua95jMe9RF^8VxmDgSck__;9&cIIn)WVA z;oA>WG~LVc<=P1B zBY@JEw4eMtY;|yZa1Fp6CkorVf)X@3Uxk)hzb(=x_tVa_G2G@Q=Fx{^=6hXIC^B#0 zKQtH<@eF))DsG~$ z^D1GYIor(Oo=X)DT_n90*i<8UHgvc*Qpf?Fz$wv#xk;^%qwquaf1Q_?nC!%C<4N7Ofi#Z91;JstQ`3K!XARz6NMfhvW2kXr%XynJy{D>(L%GHu7H=!AL-fZh;`LE%{?hkad09+`C4ro!yKYwdkNaYZ>1?a7iIP7z(T7%im@f@P@mLU#h zue~%)Fr(?59_Z5yt$gRp;rHMegCxRe8$GMKVP`MSuLN)H$&a$^UPciKFW4T(2 z4$+PU!I4xy`%Qb|Viz z65mWVY4wJ>CEPvI{`r70K=aGGOW3N#V`SLV^}2^&4mG}P+z-_~;`p=gb38=l<;T1|w06+8TxorQQ%jZopmGN2 z3!D_5E!-5rbsNJ;H6$YD8175lCgXGzXMzl^$EQ{eOJYser8l()_q@|&aqHs zs>C*vc$hPIJWW!$+~(bIo$Mp*G~Scg$;0+7vWGOEvm1Cy-J4!BFc z1Psbt_QQwy4}X41W(2UD4$?Gi77H)WAres|ZmDjtxGK%ih{Vy{_jO>v4ZKR~ciDU+ zc0+{M%fkSemQ;kC@E&5=v%3x!8HI4ePj|cEUhbN7nrw1Xt_5qO0j$e-R;Eg1l^mw28r0Cw zK=2XGbaI5WNAFVEL<$5VJ|Hl?2cefT-X|U>_mK>7B4ncv%2JWHPFn}|i}g%0;c+q({RtTRK#+v>t60kH2-NkVPs z5sIyQeiclk7qQcy(#&6El)RwZDln)`F$*No=?rJrL%IFahd&05r5+z>v%;XpNR!_w zx%USTuFFi96q*=}njUB)#vL^&L3Xj(TQBoftqxMVUTRpUQT5tlsVN$%V3`cXP!G$g zqsg{N1xmHy(&3*6x>{IwvF9j!sZ!2v!ZtP5uE1w|mt#|!^q(FiIlLOJPalfoOtGri zJe6%kU>~ySlPM zK`f@}_SwkgnXcJby11XFN^sc+_nz~OxWjoLj)3|woR7PsNdyuYJ7yr7X_h!6xUEo{ zGphSF3j{eRpy3ASlyccQ9y>b?+XSLF22 zI`1dhk0GxB^q6Iae8lgml#8Sq*uKK9`-IY^aoS%0)S9Wg$z6#6Yo z1($nl13*6+s2)rjoLB7zSD;Cd|4^`$nzo{s&p6=jD zV0{7B{D+3H=#&W$OK9D*T=sqYEUV!9Q)`eo3P=tgh@6<@?| zTl9?drd2*VbP``jS5r;wy-i}l4*k)G`!9b$bU6^Mk9NxtQ8P3Y6k3u&gMp2;H-1L( z2xc)hq5^dT9koj>JOtz(YY5Z~Vk%QYqnM1wb zns`w>R~3WeBj%SAtTo!4xku9lqGrAw#@>h3K=>x82pKQ&^ra#*0KWD1oVz!0cDT|8 zYn#HVo=@@KF#pE2O5xkmM6#dIt}rF!J#8>wln2@}g2+no_+H-6t^=VSSnV^>CRDGW z3ibu^a~>Uc*^TEW_(hUOM}oc8b2?bqq0@fper`xk_3k)_*lyWJRuPCcs-`zMV)uDn zmhn!AZU7ow6+|nd*^aY~96_ID(%o@F~?rn>b#MKM_54ORQG@9nq}KjIB2htFJS5yA9UU&AC8}@jJ~SvNfzI*lPxFcNzvo zTus&EP$T#Kwsqs@cf!OTD^al)6EghQ|K}i5DhgNOwfey)*<8y(k2j%w|DCe=5v)! z457qK{)^=&Fw`K46X?E-2OylAdR!1Kyz;Bql@1z*eB2(03&ZXjNUU*ri9;b2XhAqs z-8^fv^6T3ogqzIs;e%(p&3sHR@ZkbNEZOcKd0ICiquFt}s~nk9(D;8|iH6txy*J$r zx+4qXt7L+nD@xXtedU-L-f$MVUJZYZDZ9#S3c*G^Sv+r+*ocgThP;f`tdav2~rD1_D)JY@UptL>t$yQ58A5chw4^DQ) z&x4hMJBz_`d*Wne_WitHaz+RGl6%F;%yn@Ed{>d%l?3bA-u*(K(G$Zfjr8#$S%;|w z{wKTP$?BljF6e7vRK+^u&+?WcGX@oDdZ>bau=5EdN(h5K9Z zpQ%Zg$5^=C+9?-rFz9$__N;eq!ezHe5uACmL){w9W=X{BBfDBsGSlohf(mTD{tLj| zfnDG(h3@yqX$BypVbF3a z|Irv|x>c56a|}}$NRfEpkH&oWiYuYv;b`lv<<5)CraJ>(^mcOu`_@n_nK%dh*ATQ$ z9EdQ@Q;~cxe4Lr6;B=k7X9LSOxqjuiMnh*%NbB<#F|)P$+!gIZ=9LW(OS)5!zHHQW zm9DS%1Y5Hv2u_|TA0b%pzVBM&i3|E4`hquw=%TPR^JbaMsUsS+P}5e{jKib1*FZ_q z})MlQs^N!i!>9Cy}p|Dc8BHSi-d-gF5kp{QO`Goru?qerNrjl2=o zx)s&aOIXmVo-h*Wz%cNU^KZL>Y$eWCdK}a9?#;JaaRcjFB%lDXBP6!qbOO@8G0LF3 zxq<;iR89SC$Qq8tetEbi+Dy9DHS(Z%re4fD?AjiE!5})55-9nHG6!_obw^Fm4u@WM zT^3y~oTK@$XqL-vkkxo3`DIzkOm~MYC>v13hOhViMNa#N;M}WUp@}H2u!2@A$A&4OaV)BF1EN-?-jltk?wtmqdB@ol0dcm-cixz&c(BkC<0 z6o!n_BDDsHv1;SZT;kL+bLh z>b#L%3hT7CTnve{)qUd^Vj8bBz~?`yMEP)}30jg{r=S*`;wvSnr(8V#h?^E5oU@l* z8Q#65Xvu@9{1u(afhlvE%!pZ65myk~W~;O~KF=e^FiEHRbjf~yj1!M06U&cgadv*$79oXXRdR10!= z{kadb#&vIERD`x)RQR&|nEw@t{VfC(s!8+%M5U-oEg_Nf>V~^vs>V_HU!6O`+#{Ni2ocoMzlk<)c3Yq=uv?5FbQ8Vmc=+Wb)*cu)Oe) zAt0IsxX~RSg7i7>etYT`Y`)BqX9;_9Ykd!$WU^ppj4?H;8P`_4_#hEGpsnm6x-0cu zVxl@ubN@C%OcAf_*c2S`gjaH`3|#G;)l_1R5sEz*s(a@1+@FK)!Vf8{u+Z;$4bHB< zQ{`MpPK9(`zdd^KD&)%Itg;I%_MrLLRzFMkU@;Q^m{)=ayD;8p`;l)~S~^U&Ej_00 z*H-Q@kJ>n7x?cw6AKz?l^)i~MZ){-sMLN^YklqTXr+>cP#qxL@dh^iWkL!a!CAwO$ z@(@0cOa5u_vH@$~Zvvtl#^L>hiQAgHwElRIL&LfEH&RaC9~dS}MD-T2>Fye`UD$uc zHpf;4l_~I2r{41Sj%mLF*cDfbKaZ>(6MwJ&F;cjdkNnWqjt`>rL zl~F!0J@aU=1sJO+aN*FN;-WQ=e-`~(ka_Tlo~o0vc)vhji4&2`c@>R(bTF{@Qy^N; zonVYcR?0C{)9|Ag@l2?;KDPu;6MkpbFzV|cY4M+@UpWX*qLLf8b;(Ty{V0ygr$(=q zSExK!=DL@~J7Bmxn0o8ktR0@ipma8X+n!}K)c12W8xPT~Hn=}&t`3Ye`J+17h$r&M zP!k!0?_)RsS@eB%v~~)>-&XJj2;NsIO+i9;=R2LPTLNx?Y+bqAVIcT0h&E?*YovED zndM4zwBY^U&2RITQGowOj;_Fgds-Z$5UYONo3*tH@uo{|SHF#D43I!SS_#T{ejo-Gb3d@U&LW<;NT`PpdlkJzdV9?&Q^Wt5;^x3@`=s=R^qVl zFHkZu72P^4$d%F@c5)lW=7hxRCQ*&>NT#>j-cpef4Lx1H z(yJF#7)tX`BQybmXjY%c+g}A$1l{qcaeKgak3Y^G5xhN|-ZbcKLO*NPxLwdq@F%-9 z@oU?%Mw}{o#TT3c#ot87RaXurk#F=)etrLR-?vMgMb=UmznpwGj&n!0e zKz(uIM>Sn(u-oAB49kr(v?03sT+b)LQKU`zN9%Rg$eUksgWlg%WvPMgdwi2|wc3(B zjQs4tq9|~sqf<0ZPKPt2$Tc%{5UtLhWku)D2VvHWP2qfU3k~kyO*`V>H-EGak7Z(F zzhN|y__Oy>Ly_@4pT!e1ksDob2*&!+hd0mzr`^gY61#8S|6s{REB9Cl&OZa%bQa!e z@jj9TC@Ez0LE0a~c2}sPVv7ozROQnw;yCXkvwkktBDp8W4jx1-o_3+>86BkdY8#CZ z&{TBuctQ=Is_TH>m4-`qNJ`k-wJRxjhsZ_z#uM?%re;7f;owFq16*|ZAnx>P%e?Vf z!kPhkR7i$uaGN>wo7>Ep*C$Cx%ULcJM0O*1QNKZR`q!^vZBSRoh3U(EQjN=QNr=mS zj?Fkw4I^l`>r|*-|K{)Cv3F{tBBbX&N=Ay+xDeE>Fv2r@j8Gi3)`n zZY@LyM&~ab+Ztc?EkRhA<2b@%>j2ai zvma}17D=6m(N&-P{VVNmzteO7P0Q|3D9UJA(nSAeyMVHX@R7au4s&H86eBS!J z+Df;X-gEy^`NRU5N!M{aJuOoFClo(cIcJZFqMmBd?I0dzap``4YRExq_AHY{tNe7} zITO|Y{r}YdzVfTfF7-tJU9Fhc$*r+q(rAC3pl$`_Duj6w3iC3nKJL-9Svi#_2)z|b(%8to zCqeTZs}a?^6Yw;$%LvmG~6 z_kYKX@-C>C0Zv5ynm%y;W1%)p!D4!1v-IKnsb=kD+_5!m7PNV`zXw&}+A| zjbrv{)@Jz^Zu>K~-s1;CV4)~EO8&{#JSe^~*HiYyV5Ecccp}@tiu{w;3wUHkPd;EO zs)AY~e#7T3PgbRDpr}SvO%xQGA9obp&bJ35a$riQ*J=bpp71sUeFa{0S+o*~z0YSV zt<9AJ-egylk;%(}2InHrS%&3!@YbV@*h?HwLmZ@Aq-}oG0$GB?EnSolhj}Xb< z>>2n0e&_k6$>gie)<_x|pWwp_3#azLx(0C3M&o1gP|`ArfM8JMgrmwECQ;0ayGY(23LfVXSb)?wy;iJ8}K- zLKx8P_hs_FE=hr3a>bVJd}qM#@Psnrz{<_2hi0tWGWS<&bJb3S+Xmeq>$z8XWaC9N zDQzjYXd2gVN>^)N-YkKzl)Y}z)vnsZx81!i86U1k-2VX&lRp;v4Q#H8H$)QuL-7t< z=PEunA4OrRmM!-WHmrVKh~>i#T)uu+%zNT1mErY|M$#3WQekkNrFJO_Pft5rT%A;` zn9kdCzH^$Zu@SMRv8%KAVIYj8J5EKgluAkX)rTl&FjP$W@OzzoiSIB>IECDA`lJM} zZhk&*ZkAF7NJ1i46?XFg$Cx@{Ecup~Zve!C`v1-_@{1SvxQ8^#mr)wJ7Qr^|I#YJP zZUGa@kF1^pG|wXWWMv-y46$cp)o0tZFl?8FZ>Fql9}}jHf7SI$86V>@ApbC$L7fvt z^GdlUjXWpD?I_F9+tCzSgutZ$Tcu)+y=(cauk;%(^AxXNQ|jR^bdq+2wQN z#XJl&js#0xt)XYA|GvUIR>|ImXhyG@y{)rdRrf?;3iw71Dy(j0cPwb$lj4g1B*(UZ zwjAD3*MALg41b_qawVaPcJ73(*`J5E%iFC$|o_qo$ zcF8=>HoAY#7qYtxUQPjmRo$4E{vX$*IT_teTD#R3_)W5%jxEvgd%cgdBm^~B z3^yYlZ5S*etlsCF8Ho>L+Nr{6ql0xNs)opu)rUx+pG%Q)VQNUZMP$#E>%&R2tl;`B0)n$vSRsd|VlGF9DnSAn)?Ck!aGUS;xLE`dXj zQqXQ}B=M{pP5slhfZW4RRyT+hOdbtrc!I^KSe{MHiWn>$-3@zh=sj62X(dak_4r^kzJ9I%*(!CX*sw)KL7>a@pn%H7g zd$7wM6=?_WTJxf=#mrs^IvI?^C+PN80Y$E-yMZP)=!@<_KGzv2nK`GJs4_4bcbT6m z;Vxl(JhQ@tQr3^|gr;S^nR39#jK360hlB`FU8~knv{9xvJqMg-u8)skAO3frqzA*U zXc_qFKXuH?%T!ZFNjq%E^%NAmFPr}65gyOEFx}%OA>omo`O3Ej`w&_0K89w1uuiwW zCGJ~Af_ssswg0YNx$JQHCdfr(N!HY?8))4}msEo|hwl_OZ29SJ|&3 zX+6uc*j;;gvmX$lPAO-nLz}0|6_e^oVrU5tyMqC29vv6g&#k_pRtNyfEJB;d3jQ7^ zyurVn+XlBM@XR|mNqo3g#@%S{Y_0UX(Up5}N0oWQ;`_YpfVseH<12)~F&Hk{JRLR5 zvP?HXcF!?Bdp}p1BqG1iv9=-v%uhHEmy2(lm)eeh6?`vOWDvZ5ARAtR>`@dh)sn3| z-jWUL)M7ydPicwRV%yP@+n^1aaTw|~UYPDdwtme#(SDbko!wGrS3wnPs{~!o#Rphn8E$Tf&GZ86rV8i0LsaRn>7<`8Ry<@^7)%$lwvq6unbP z&gZrku&wiR7EOPw05O?IE@UX3;gDHt1`M`!?BM~5R@R0%9oFr!+AOg^*kl1W?T-?l zuF)p}wswS53S{ka|D(qzbBvWoxA&;mdp;lN!q)2)ygQDKbYa+0E#Xwp=^^Cv4!_^M zm3lGY$WWA{8!>omzwzc8-IPWGgHRtnLh-3qM7|)e=GOtz@}j{J4dk6(+fuVLNmi8m z$y|1{a{@=6`np(ux)9k(_Wow^TrdF$JRC~UurVR%^jkxfhwGK!^Q$m# zXg-hdOqM&bqkqWNguH!`u>3;iUYhZAOKyrKV^ocH2#U_T?w+VHkPa=u5Ch-cFV-^t zfoNAy5^euds@y;%IH^lsi7ut(G1f#WA1e%OP#5Ac_l=aK*-VYJGPX#FZY)^hW}Y z{(#5bVB33_P2yQV(&%(q!Ehis;^<@z=w!?RieFoZcK>kb_%7o$|C~lGM}nrruhf-@ zIour1;9#ni8b#&DN3)pWT+i)60E1*^v_j>+ADlkNV5FF2rU7tLkwhvZyVV*Yw}>bJ z{NTKCkAU;tUVtn#VZJBSxW2w?H>+&p8wtf}Z9yZODpRc@mrs-L4z|2skC>pD|ALl* z8U2(Q6{z~1Ii*RT)GI?67kYgHTay(qnu-w5g$+eXr$FEWK2q>ToSHVOpe7OT@MIO1 z4PYI-gnYXnBLWJAgRPIX42C@$ z9Atxmyeo}VB=|OZWt*jYN>V!KW%9>j80B<}$F`>GXdE{&2H|j2fUH{fF`b&hTp8|K zBqHOBYRr!2-xJ&1Jf^4}d5pdCUB?@uGyKgrDNClYg(0M{8f;A=>a-ViIG=zXC8K&0R(CP61TA%E@d>(_i4_M^{SSLK1JSH1m1!un?;W9X z{#M*XR+Z)5?F&LC)##xT?p9eaJ3FO6{T4cax468~IxdJH(JA3JaYzBkn;`xBDbn)C z44oC|;a5O5m$T6iZgTc5B73yBkQ6&NcI~LVc_0~sI}{NhKXu#hVVx38F$(lwH|UsI zw#t2HigECWuQWvAb7>7=w)`QG(DKeTaQ~-5PSSfN(-}*r+yr*P57Ed@y%xZ)@U03`^idQKgLJcwZ#JiaHzD2)2 z5gA6UR59hy4XC|z{85%ENTh)#;xz&F*v~xgB0S`>li919K;TgJR{i-gqrg15!`=sY zQWcxD&Hua`lA-FALu)xyttkC=X}xz0y{YQ7i{1rBahePdY)>0k^hM`mQTQk^P5XKp z?2nUH{pPtAWsd{gYZNtA1hLL1cy}L^3m>cO)Cai26{~Kjo2wqE09oZr){DDJ<7rUp z2Apl?-H;U3nczm%?!@6jbYiPM6R5%Jmor<6J=$-3*;?}n6wLV2uCewYN>M9UFvND) z20%_|;G%IkoQSFBpI2=%-9lyrfnIh9!kTtSBQNIMdV7;WKGXPYLrygd!afNTo4g`^ zr!R=wANlIjO`@(h%yv%ddb(`}L&B+K3BU|UNHaZ#&;R?FQHVzEJ|tS( z6;vQldkyilXV-W2e`e#9(px}Zd|)DVKg4jKpnCl}a_v8G->mS!9>tN z{-LPz>5YdN`Y7#a)m}-Z&R%X5A=Sv_Io_By2MN@9p@r1MoFe|b3c?PFS>)?GkY zL;a-akbAm2ncC_NR=UfD^7U8KIG&VxgMnmhe#nX7!pAb$iQ{smCvkk)qQ4Lt&N|>+ z?N6c+AY02DmwHFc_QOZWnV;ky@7sZxQP}z zN|lHXQO8#2Kh_7HL*0oV%&5yxCb0=t-HE#IucmN%nTiVRF27&^Q9yv=bkgR<`E-Az zqCF2KyKp_r!gGNqp`G27-jRITA#AyPO8EI53UZ$UXdEfyMOP9(zn6ge6dsVv5Gy`y z-SFP*?UDhLLM2hy%n0ZHrkWj`Ohq!W*cLfTchz&B>uKVw1e{qO)!9Furi+N|!!{&r z9~$j%&I3mlzgK_Z!rG%~rh)cKM5r&$lrHx3Nc&GN3y9jTXbUJHSVL7V6-|;xaptKW zNO^31z7zG0XQi3U!_5QERidiR_e$urr zsJ;Kz`g7ZjT+sfH_JVO|QSC=o%_<~dBhU%FK`LWfFZeL;ovr+4si3jg*?(^q^D~6} z=m3Q0ay-RXAR!DqNZY-ByHr{S_v%W>+Fw<@$p*5)Ka8P3zt7siicYkE8GCQQxa(Xi zmK}w_0l@+yx}S6xMLKo( z?o@Uo%!3s9=TMJ0zh#@rT|>mlV`D1o;cs1?Irkvo0;PJ51B6>-fq=qfYSfBwcwEX% zNk~yfdni*zgv7j3@7(84SM7G+IULuJM<6;PudyvvV1W2r2`vAoO0|*dN+z6DOs@fv zEL$R{xp5o#RLZZhARMJut&f4SS;+?;Bg#lhkNY0mTZLvoc@%cYkeWRDKS0B^ncn@g~D#mR#8ZvZa}wp>n%ieZ}d3)m$yKBdk`K^ieIUL&Q=q-F;V3W zuU3fUjZiOh`e6~rO+$HzW@%aZ>jQ_tAUB;^gMe@Ndglz(NsdkPhKS~)bK@kZn(E$e zn?2IBOsVV;h23Vk&!($5WeKb8>1Q=jMiaU~Dq0}u7cbMy2!2)BA}lt>gg)ihbmF_R zVCK!Ga-aVQI%kMkd@H1+gDap?sPnVrXe0(vJKB&YY4xh_;2YK{;N{S3YxK&%b8#$Ht>=8Nw4AG<+&7f` zzCfWH*WK!Yial9fk1hKtGbbXxFBEIlc|CCWmcQD{eex~38iO`vRiiAf(WK6cG^ zdf5KF9x=winNgMD5!7xv0*gTA=$-Ly@9u$Qh(`O~ol$#oz@NHHEBd@1*r4LKC2EpJ zv#A-J2Z7W_Tnm?g1<=JEK~Rxt2z_#SsKeD5g|sL8h?os`uML5W9&6!e8{!cCi)$U1 z>tlta=hBx$oB@{(v-ND17K4z)^D8KjZ%p{mAs@Lsb+gYWYz&w7a=jFqgBoM#x_Z31 zrV{im(4~N(ZZnDBU;a2bfAnN#30u1EP-dKMB%pME!d5*I0HZMT9S1^0sx%66twH>$ zG7DA4q!j&Xj64cE8ZQQoHq0**;Ot4~kFaIXg*3)Kq$ zRqxyXGFlNY24X`C^xTM3>cM8hq?o&i93kGQrkhaqtjQz!hc{H7VJaH=+=kZ%kp1R> zzQh$|uujQ~x&?Rs!0C$M^)vMX&7hLz@HrH>(S0oMNkk%B=n%y=`;~wBw>IAI>8yB& zcPF%WFEu`DW+V!2Ox{sj)4C&!q_W}BRTddeLQi!aPV^~0g$=U?$*gqAH&x4v9u|=d z;KR{cX^;w<`0-~GhThv+0CP6WEyWO6>VSQ?!SMBc? z_ND7ljs9xi#L+H$ty%hsYt>tmC0L(2yZ`zvMN#@!)KSi=_N`NgU9=;H}vvJBd985ze9xU6LEh371d^GuC)#|z4||Fy<>dbUDT-Erm=0? zHXA36t%=>(Ml-R|B#muP?8dfj+fLuPpXdFZ^W}V=Z?pG*?Y-7s>$+^vx4u0ekaRlK z^+K^VIPjR%gis8rE&I3xyjaGvA0OkowBH>}#2`-)>?}tlQIEDml<0bPh=(pM&n+sx*2*plFiJUHyLjq6e_$`ZCHfirI9G63GVVHZ9a z8e+md&`-21pUe`UIpC=Bv3gF_ea3S)L}eq4qg-s})L^BK0)B(C024KFo#!ic;oNN0 zdrluR>g?|{CkhGQ)I~n?CSS%~5xJKi*bgA613rksH2~x7Mvpqsu~eBxC%jMGRb?we zLZaB43afLQn{A)-_`3rcTgF9f1nE3ZrH8`TiVs~0lj$-U(U+;6#A4JKXo3s|C`t8; z@^8OJBNMQ=ba+bgy)m(DZHp&gU~&wJNQlybk(& ztFIKfj}bCiUqq`HuCvF@Ig8L~hZt|UeDBxSyM*!M*h;~PqH8tyX(exh;PCEBXW;a6~1te(|-WrmS z1LIibHH^)cy)_TefB=uh$B-6^W+Q7A!HL}TKW=?F*->DG+3olfm# zFE!^rf?E0eD|hZ^)14aONPv0uUnrf-$vDzO6|y$vk?k6kLzkeUIIIrjvWg^6kqAvc z;Y&~BSejyzLc5RF*a=7h76yEkDf5eEGurwzBh!D$t;Ib1upc+5X*T&PG~+Mwbhn_$ z6uq};i~F0YxD6iyiz&V6W|8;ElZLKc4x}nuP8rsw9y;Pa-@cpTNg}2XD(I|8%wXqZ z?c#CV)w(e9=lWJvWeI!Kd-)QEJCuUhq4e0e!OY&w2*gf;a8-l=QObr*QTR7r8$(%j!N9L(%e%d{>vfDQ<$_H zKBoV>#((romP}l^&5Pr(%p%L=|J9>>HDGOF=gb?G`#`E~M=;K!lL{nuLe z&%6vZ6%5EmYT8m^TWVZ&m9e~B=Dg$4=}{>lRA@)+HR>)yERVnJ(j!I^kPCa!wPYji8`4otQJsVd=fm;UZyfqf|gd4 zW1nqUx9<(a%FVS9JX?Ez|dZlJ)6u?8Lk66R7+Vx0WHvhwX&(Q#%Y?wdQnaX#zAoed-EF!k%JA|^7rx36gPLVP{U2yQqT(3* zln0-d>wL7+eb^}e^`&#PvB=6btokOX=kK*m><~R#Wy7$qEDwu}+4GiW(3t>)(8#;A71UJp*3k7X7&j5iQHa!-zhj zj45o!XSJ}P$%B0CD3Sq?Y9p^CfvI0x1o!Mu=dTY<(eVeGG;q#UQ`0}RKMrMIXzC#; zi9wB&ieJB`WfZ`p_#5T-D-YYFH+)pfP$2o{&h&yu-8EiKGuLdS}1KQ?jG-WvJv)MyxTGTa&#NVU=5~|yd8m@DIE<`te88e z`I(9C9bLg^=y~t2JK_q%!lGy2efT<#kM zVZG&UW0)kF^M`ZEk4knP2+!tFs}OS8uII!vD3iQ1L%tryPaRo?5oN~rb)Y<}Yu?xw zn2}Vd$bfuQvMkgoKIs;&5g68{kN$zbizEc`;)&_(qkq1fC2;zV)H4f^pgYyjnZr9* zMMN$p#O6IlX!A3Fw_{vvxlq|<31wX=WHp7oi*>|o#3SThEM_Si_UlU)rvm2et4w;A zZqRG-&M&i~x$?kwGlcYbRR9W_ra&>o_#`*C-Zb1AG+H^O{Z(+x46#pt9Uv;phn;Fk zEnGsiZ+TflfG%S4;i3fS#%zA1rnV24;REb?OFM=a)f_WlqDT!_ZCdOjSHQ2L7=HNY zMavfO(7xaDrNEyU1Kz%X)Vyq)zjLSD+?Vzd8ndzjwwEBrI$pjZzu>9qD-;9jja&Y# z{OB=y!RArS{rwUQB`&Am+PZR-I<^tICODLPvNQ>6wpIj8>FE_}@j)X!@Ry~p0^ta) zGC}jAi0sWuR1uBQsQ1)3G&h&II`1RDho3!jbIS;e_7wRI>%N=OcrANHnZkM?duW;h z2GIYAyf~r{`PnwpnG(}@aS%AI(LG?D{V3*+fY;#WW82pim^UrgC{%GUET%G7y)__R z%hW}V!>`(=6pI7GwxLLXNNS~p<|0xHewo`h-Y`?|dARIhN?JW0FMe0Cabg>J73CS} zW26adag9SZX*W;$deA0zSgJTf^~%)`YucP3yRmN8#443ja*XzY-@Eh4xQo)TNxMV@ zq&E?LZ$=|gdD3&si%x<}%iw^&Q&&$%r+1anMhdk|sGy(rN;6;xN3#C^O*|iS`TQyLOwvrIM7N%Yzsc^%X8c z{K@^*(r&P4R)d(kWML(^H7X;)Q_`gAikTfI(GR~Ff}pMPOprAmQ?%An$gMOF2jYZg z{)nd}oh^@dDb_Cx8d|C%i~`=wf_@g1f=bnDmvAd%Np>oqT)400$ozecl9BP-`;3V= zYc?>ki~KH40NWnI3?|n?BAQXVB+Po}e}$}H|K{f{Uc`MSQYmb;{=H!zFx%mH<#+Yo zyoth{$2pUXM92HNwU{Nxlrnw*@wOte>D(H1t1kVA^d~kA(XKz~8*`tV3dw!4I#F*4 zi;n-|j#3n%(M?CJlf9*}0|W}{2MttVaBZeF%-!0` z=Il!^!L`bIxtRo>qUlPf|w2FA91fAzM+3&Avl0g2BFDfO1|Ob4{i z#OqN2A8v}NVvTilJUWe2C)prJ#F6fmoL6@AL~&b*mWd;e5C83hee|fB$P~Ah%YNK@ zZ}Mtwy>}Z&0FDr}$d{EpewXrFOoP4`lP~T9Ke!HA)R7R-(6l5H_iiD(vvP_@B%7 zr!1=@lrR#3>O_j)vcqL^4y938lKL{pL`TnnBb(`y*oblkAq?eq@MvdmEq0X3g*xJk zm2w)ESLSQaAz^_?)`>_%8YwMqWE)_|aZk?aT|&#Z0xhK>{;#W}ZK(pJp}8TMQ9n%~B^nQF3LE~XywC?>IY2fg2Q+Q?_b5s#}e zl1Ozub4{p8A#pwY(QmP+7tsAilIFjOe#N^EN#d<~Fye7Dj2(F2yEOWY9Walo5itWF zQ>sLTWl^IFTD`=bP(pYc$-w~c%`@q+JUbFRswi8_?EfsX7=JZY{?8@O;CK@8-;I2~!e0+C z%|f*;CeaIjK&f@1&WfTKM!5UaNVMJ2-{did`nKiIP^SzaN-Rc}SJFQN7VzvkDhm(2 zFL(*kU1WdGP0$6!%I2Zi4MJ)hev&0oI~6Gx<3{rTb8NXOYH@ucTFMYasg1#iW)~?| zLrhPXDJ*H1aed^h~`|ck%Fd{CK`ZCpX3eeSVe+ zW5qGnt0_y4o=J4$Uv~mTy@<@(wMGSl?#Br2b3OYf4-|=d=r|i5L}Fb=xCq6y{Ae@2 zb03Oy8=ln_)375uGHN2!gCE1aLmom>E=tioiRQnv0+W6ZNmA^3u+w2POdPb``z*9i z;Q(P%zpm!8giJCAL;Ix3AG%I2-R)&fVY5W_`8kOFxMS`Kbol-~Gw*HtCW?ROuldrR zeBCU7ApX2X@Us08WxM5b5DQpi)eu?uN_`AILfV$^qimL0YU;?-FC5eK4vCpVW|%)| z8S>Q#fQ+>==7YwN={9T0c{pW!7~s0jeW0b_ znqm;MpPDA4FNH*!=MX4_P!00=m^L5jy z8%0k_21&}iRG#XNOjf-VBw>lmSxogo(gHq<3xe;xqZl>&bH~W<@^C@yA`FHUi~c{c zHzXdBHq36>mY2WxDZI0?aR352G0U$3#kA-^dUl>&cY68Ly78aRP!G+2 z%v#-&1jpkdic?P-Wh2K`GVg~4qm$suW}`P_elJ77T|>DF9s4wS;t`(l^Lko>_iK>Y z(?nkujCb3fmY|!S!q>VXyKc+2hyCmR(jm2Y0TbmAp8T!aXXZA^3%GXS%%qxCMc2dh_R_$u2w;vI%TfNr>k(b-LIA%UWdj9q8 zm^NjNH%%0ghN6mk#-nRvOc|PtH*i3c8^n#&Af^CSYIaFwzRKplh4EWI^Igl;4IdtL zometAYcCQ_Nm0=YKSsolg1N`lXk(*$tL4#3z3w#~#yyLup|FY`UlnVYAuxXSMcbR& z*87yN`k}_4(u4vzb?VKi)UeHMGof5W>8@MD1pMNfPp}Z5p&==GT}gyiPtgsWk%emb z(;!UZ*8EWxlZZy)Sj+o!;Tvw>6F&{H@{FF-e%< z9;EU=bdECLxUp5w-!;wgl)+l!Lbs*4Av12*+N?FQsU_`I1AOOYZ0eA25nW|=CVT~I zjuf-HS&|{2id5xs${Lgl8e(R8MN`o3H7LoI?=i|EZjq?3f2_x(RrS7m zP&K!!Nv(V^rc&^B{kf@8VxQa*SXRvcG2Qv~D_;2V)%54$wjp=B3o%#Ox9-DV8_GtS zhsTaTkf7rsAQB^gdo#7}BYIE6UWcNjuEjd)DOIkTQ&K;8uL6?0Ln7&W>@jH=`GvJf z7I{wz7-*{FS^{JtxWZBa#-=U6LmKE~U|%sjta8LNr8N4mb1DDYJ39?C0gNpbGnqWR zr6(f7bx>GAqDJ_cI^|!L=xxhe98C9C#yupN3*(^Pg9eJkWwYKHVY{8eG9qH!%6EmG zpk6CebCt4DGy8iiwDn`@VGT=E)G_<3=f*L~=_aOfl$H5JRXrIJ;^t2a?FI*6H#cA5 zC-F6f^!M+aa7{Dd@ET0O!=4B8U%vi+LGbN)`M2n1`_| z%3j5%w>nP7v0fS3w}{zzx3>uELdvkwb~I0GIhk?B8Q~LIT*EcsyL z!WlLIvM8CKWsNZDKKV1eN$K~UZ{6uX95}??q)5_825e37UyseX6M_mNBsHi;;3pBMW4>+^w~ zuI!(45M~}<_2Lbx@l(N!oy3R+c8%73$eS-{+fXQ}!`Y5{VXM{J^7gqRCcOX1#Qziy z6At_rnW5RTY$NGGV3f&B-xhv9Hv+~#Ra2pnK6YkdmfQ+;&B=0uhA~%WN20?#Vp&)X z9gACK$?woZr~OBd!NZPd`@b8heZZ+MSI(q?6Vl*{HzMqB8G1%oxGyNtKS@?E9Aoq&c-bJw$d4*EOaM%VV3b~q; zWK$(EO%=(3#Tp&)@M@ldDpd{yx!7WnVhI?$CpoxWyC6DYmH+tLnw;bkWrYNLzsv|60|aMW=>jpXb3qWXN-~Og{W3!fxp3}pM=1)Tjv#VM3>P5~!jenkf zw||5?bXXupnCJHtQXzS61jlTO9*};->b69`xFMCv)2cl}&m$^MkUh#Ut64`3-|Dw+ zckRVN}XfN(lA1l*K8K$KXMVWzX(@YbAO<@GV2A}n8>~O z^4;hRjcRk(G7Dd+r`ddi*qv&9kLbLzFk1&C`he@s5g0^0*QSas z><#Si`FuXa|J2$;q{hFs0hPK&lqib}WRfz=1&S?iY}V`r#SgiLG1JLaBs`b7WXUo` z{m{U6uW~g8w39vx1^7IBM zL2#{6w|=^}+8WVn@nM%N+0+lX4<7g&;!NdMpjz$6Z|S$lmsf#eUs~aUfe@Oaby=t! z?#Nwj(Vr;~Dkfb%86N-5!f6_$eh7P!oQ>f|FWZ3y0_x97;u*9V>MR%7Eg9A zQf~7!1_NwJyqpiFuLAJCcz5w7yF(8t78+gk6fA>mNWdeH5mYwZd!9e&pJp+VxJ*}Vz7uwY9$k~$;m3w)7_$(n{2hJqf(97L=pXK`{CJ2AZ zY$9@=amA6*2bpj(0l~-RaIiYl%ZZ*rXUd6``z>fp7u^Y_k!;r6g}#RU}ux@+X2-4R028PeIqZ~dAk#5Dmn%Wu#2RrCO8`l-gsF=kJau8 zuKHo{_t?*T`Ax#oCqGtP?08RbB7Z}Xax`JaCrz`E>##1s#kN!)Pz4(K{U<8Bb~)gr zQKUHITvuhDz=o8ncw2X(6ke+R@O$nNp7~__i}hzvjlE*R39O)|2Q$ZuQ%~U$Y@O~0 z`F}pV@sw~o=g6@5;J&4gG)k9bCC8Kj>$dm=aPAHzY6ewRIqc2Bg6Avd66?M}bxJ{a zzhD6<{%_xM5rv?bSh3NIt(XM5%rLr9xX}Up?t2#m?YRR@& z{_XRQg{$$&-etU12nkvK5E5rCem!59pK zpF9}wraIl}E4n|Kja9?E71py5nX6LQF`UeW&{SNwH^lU#8ipWsP-7t~-*%I5S?WHg zN+g&^>+*<+n#L+|Z-=@_rCElUkk<`6$ALE(M@FBXXOTHp?-Wxy8KSi|q`_%D9r$c@ zA!<=@QCRoEfFs2QLad0*?8PWlY_t9PRVqky>ly9r<gj1jFrbs>$l<-ey`vEBA*@ zvO@8HfqL*0q2_~a!)z%se^dJ#9a~85Lh=h>9_}b*+ADP2TsTMwQwmZS6d2M&>RVW!|-0z~Knt5hw5HE@u|`ageK-aCujC4~Nt981hXqXsXcbhJE%d`@K^z)vO0NMK4!9g@qwh8aUS z$mPEuPIc*F1;z%^$Enn$i~#=YPr3Y4$Y09+Aa1xwgrW0GzC&g#Qb)}(gTI6v2hjyv zRt2u*!CFD3+c&U}g%} z^jhmeo+uGZg^9xymWgJmo_wi{o#oVwct|+Jn+rzR)XGgcoDm!DRp1;_=jiA=%fM*$ zai8Q_f~UYrEEh?0BicX5mx4x;0hfObeIWfAo9pdtJFrQK0h8`ejtzuFETK}5lG#1j{Nh#k%B&Cujtsl;hphqLi)my5PD zEf&u_eXPfthQy_<4x6bG{Fy)hcfjxc*QjTa%?8BmpPI-%YEvekzmm?gdbHG;f_`%x z>3G?m!P^@7%=DB)~XdDCYMZX8i{3_yTHB<7QQ3Zf#mJ+@J;9;c& zCo`OcwB|;sFbK|zlHhtq9xx?+6&!4v*;hW)e9;lSvrP=K0_CbNo5^oNd9vPWz?k16xy7A9B7ZpK0OjOHf4Hm02#3!kB4DZ8*!)< zyY%QZ+R*!FVva^uPGYGrXfG60^qpg%kA&rFSt7E99S#|TYsc&@l&@CWD}|E~nvaf7 z>?oq*1CDgAkB*a4l^V{(?9&p( zZIF1o%APB{^YEu9b9#RZKZUCoLt#<=V%eSy)!BjLBVZk!sH2Lk8GHP=r(e^18U5TNX}1vGn+M+%K8)0VJ%!Jj+o#L35Lvosk&4JZROZ2fyOC-HWbIm(pOwzRi4~VZC z%)QW~Cq_T7euS`^FF65T-=yB__ISC8luTVtlPGMkUEkck5eODPa z3Q;Q6M24*7UhH2CU8~=LXcHL(s?*z`94gnRE+MK7DNzXSi(U+@bdUvWt249Cvb(C&N2E}LK5s^5<))Tzyx76T((H4If(`Hqq|i0_N3 zay@U>qd0wuTz|V@u@9VD$S*}Oo<2Fxk0rkk(H7~Wmm0{Oj--~ZW;@&1laA%xE?)`a zz*-nV806I0{DjM7puCNFvFs+B^|xZ?wB+5Y$bQc$Y)85U2x z2P==6+1PqaA#kapa#b+?5@w-lt|HC)I;XV2JSK zu%pNIxvQ%Pv#>vE>j{O4scaCE;l6MH@q$tj>DG(Oa=HM?(yNlKqA0UXghD}nP zE6Cz(F%~om<-BvJm<%3`(>*a_UMM3}K=>E_jUV;xX%fS;)XDmNxf4IzMg=*<#r&IW zTzZIef#%M-wmWU|hIys)LIV>nr#T0I%EZ(riabiALvz*NRna3akfpgdz7mXA1JjDsC*NP{!qqe3eN*A0Y+zO^_%ZuZMjRt##4z5>b z-+!+d&pR<}&zFt=b|!|TOsuvpX*GG9t|lXY`+D7NcYz5aG*d!>1keV(jf?wZ83bUk zO$2jQhI7o9tz-O!>QI0EwR~_#Ze%YOCEQDnh#|465(B6Eov?^*cgs!`=ofoYWS&Fw zqt#j^+R`8EwGKAstIdRG>?8bd+%F2;0$XO3Cn-Y%H-8`U#NnnxPA)0gsWC^(OYd-m z!YLni*fZdS$t;Dn{_EZR8iO#4+c`F zN*2sETZlEnoSC*!b!XjoUU%e;;y#&WfHWI)f>p)UO@zXYPvd}G2G2`GXu{=KZ<;t~ z1w<#W(Qv8;5v%U$PdFLkccH5GvBNU^IHbjHVToTqOVbqqDRKT5s>eRgE*29(x*;xg z9{00gNZR_c6T3c-=XtP_faYLjSL5actc~4pWEd`;SbhWLH zPUb2y|BQfVbGD3lUgip`$)o$afCo)%Vb(zMLezH6*w5`LIh)#LaK-e?kMSg@ zLZ^dRBg7Bk(&dE_7l%6ttzDo1?(GJf(%f8sF5o`cs9OO4x^sdl%u2Bx$TcF|5Fc%g z2f9JEOv3&{jh+X2YcnM-1l3MTd#ejK^TPy=3OScQ?9VWo@n#lq2gh)Dtiw}@J21eE zm<+}MJGD>noHQ6%D7{T(0%l;4;5OL={lxGs)FZ54qk;#{O~aNu$}^tU_Ksav5^z35 z`o-3Al_JkJIcAMe-I9IAY9WwE1p1yg!`gr9R(V?Ac5Ju~B1%n^ut(j<{6AkjQ4*0ZqRGuW{*WeW{$;@H~4 z`1#%keWTG?kJF3IpXhg^eOzJh=sf-6MI3WV{!GHef4q_4k4dypb&Jg4kN%fMx-O6?%iZeR>4#)xT(B}|Kx^OZ^Psy${L z6LvjQk{_pbsfB}=qpXt+?PI|!nVn^II<@tE{&09UJ@h3M^d{tD(E6L3O{82bp>lbU z37)pkl}Hf#Pew)%tzZU!Fh$U|rnS6zOw`p_E^#6a&P)0%zYSk|HWCP6RHLB)1 zewb&i=854&kvMEL^h_>QC`dJYa6oYjbd6J<%6}_@w7b@LVZs2IX=0m09b_8SvlQ@hl=slsF9=l^|8|tEFIE z-;?lMc>Ze!MSAsowPjJm1-61j20iTG<4M4gd!nu|#hktgx5xqw*@Kmf`;9i~YMW@b ziBS*;h@gPiFFk71?m_1~~W!?ZkBj z%Yvt$)?e;QwTm&cTkiO6(;m4N-#_sd|2^<=E4;w}BXDAB7kDgb&gnnh5*|1#+hh9} zTe{v>5T7o0((icd-#DJmM*~@og@VxxJKYXjy16aAYb>SLbU0!2`?-D5!INmEcxswY5HoD`E5q+z9_5$+6|^6R)vwr*DG($bv<)*Y#gLi*4_!Xed1V1xn)PDvU^ zK04>m@xe6)W@2JtQrznphz2DReBt=i{JuUOr19FbSY{mkE-R-tue(B`YYpRX-4hu% zi6qA;t{cc#aL~R)Vle*J0p{=~&a*MXpV^BW=6CANN=O#px>vUyus?EHGze&t8Oq&WwMMc`FXRwcgYsN0*ni5{TkBsMo>A&UMb3aSy{-~5>` zduWDX)f?jwsPBLUzPTeIUkP~r+4yjJYWxQN80@%tp2z&AM<40q@UgF#v+>jCH(K2mQs%2w=qCUVDj2yrP}{Y^>N{-?P6L-C zFwuP?H|%`gH2lI1^`cu2odHhPG{2cuFnu0L%seog9X3%5s!75_8}F~i?Oas+0JB|u ztBGDy?h}k8PaPI>?j~bVa;qWGp&9d4JWx()rpu5YHZ;s^>zE zf98c?SwuV;&f0YgH&`}3I99oA!vCdI_7@YiJG$lA(`u8t(hQ>}?p4ir+!4w-3La3N zjEUmzfaZyY{X%brXs2IWpwFG1m5XfP+? zeTIYRw=T$AXf%~BBlK5YwkH04rb~rDDpH<3$35)hW*IqdW{G zQXi|>0&c)u$3|=+8NaK}TS^}o=N&O9l@bds#Livk!c6&r?)sy>FDs#pBhl?%%Lp*3 zTG;vRq-rX3&Quu@ApYhVr-sCsIPPb9uN(U*g!g?%lYX?Qx>sCNX24_!eKAvf9rtm3W3}ajXEljJT^b<^+t2^8U%c?^f z#2E{OY)E&BtH+Aq0+A?C!Q<7L@4sqXPOeGIdP(`xP{{h|Moq+U3dRX;y9tT#RxYCV zXZ;&wwq9H6ghuK6EXYsW{~43PK`=XXN%MRN{9JcEQA{B(Z3nIu#Oe5`T`x^yv^ZQU zM(eo*b}FT=T20EX#j+Wq>0Sv`pj@M~`YFNt?B6Demt60x0vS<=rZr5hh51?EPuj$_ zU0IVGZSH$FmVcxGowx6GeCu{tscrd!yxx>{B~1d%dYBh2Mia%$JVW;Ny}!4n1ArT)?F z57muqC{#pg40cZnpB;VDpVA*{^?O-p)g0+!qHTB>^7IP3KY+l=YC3WEAZJF4Aoh~* zuGMJY>sH-;60^Z0MDjD+RT$|;1}mRpW*AAPvrMS_PcHgoX|T5WKeE=iej9$2R@D%A zTH49&iW!U)6-lXF2}~+cEN}-~lIwg#h>736W)nSOt@1boFDjgx%sp;+9w(z*FKUV8 ziJhSL*N}rOr$Uwd-!UW+u)cfczq!2%t_!|mJtA)iXR%lSdun`dg`}drFud;erTTO= zl*>I;GWmS4^>ulSfkXA!HNB-rn|+4$IQgOz^ykQ1>#ffDIv?q_*N%nBktUd(O37@!1i`># zPu1#@tJ)O2bAJ^Pb-L7>Q;(esrb%fxxnmqM>V(WR8v@_GTuk>l9Fol6 zi7-CXfAKHS=lRu#YInQQcsJO^MrCmSt;q2YE7|-&$0(T;8_AcHX}2+bD6X>gB5rYl zy*-?iT>Z!1^?u;sd$-1E(OqhwAa7Xvd%q$Y8_8y`ed}M(2TP|yiYcQj;`fB zHtgoCyB>Tt<8fB%6M>;YqRgO6{>Bbi4s1rz184JL_M-u%fRC}1n@MA>TtHdkpH5G{ zpGh76CiTM?2%1Q378%X-YX`wM3-T~8C>Q6ul9QBI z_7$?`c{++%Bf~Xa@Z`3RngYyjrREvJk%-b4`eHtQmuN#u#Nj88nhb3MmzylRK^MUp zgwuIme(TF3E|u-+mH&{92wsqnVJydz#dU@5Fq9M1?m`eK&LS{uZ-J*Js*X1|+fM+N z--0gqVJ?ULJLjz}g96AXFlf8tOm)^)^Nvo(Zh`3&E10h|^}6!qsG%IT=YxX$O5!JK zX0%kGA|ODOkK*W;yfcG<p>E?Wo7rz z?Tt+nriy{|yVNAmrxi1vmhzoMkxz*2_!<*a-`7EvHZN&DMHsDVOlJd46MdV7&5%eF z3%zr#i8X+YmXZM-jD}@)YU<>#{5zJHSAh&yB*9jm({ z3*94qdPylg2t>x5mFB+6yb&@8I9F7s*TN@gy6AuEp87kYexL~aCLQ~q(wbJIGW;=i zxyXjc`16))x&9xk1v3ClI8@5_+zF!9?|`kZ0E;NX4#vUYO>XBlNEApZ@9>&Rm~*ZRtq6#Js+c;LT2R!5`u^wrDhQ zNOaCNd+-BWI`(`;$6$2O?munj)plfiPCv`s=bkRdeQ(AggJByb!FBPpfSbqVM%;hc zaQ2W*4ZSXPxc_uE8yXcLFu%);=3(}$LppFXtxcwOO1}wyNcHzwKN!&rHcUI86OB?- zUxx7z6OB;we>W&K@>j1=kA2A!@W_4!^A7G6t@%rTT={C|odqFx%zi5Kx$zSrXjY2$ zt#X0s%p9C$dKh3&Y|m{Yf#ZFPW0f5D4P1bHU-?7E^?YaZUR0gZUNHkqyjv2&3Mk~2 z1&rNUbl4o-PrJj}dyYsNmR`g#?{!eCb>5H?{P>&oyjz9ic*g~7cs|vj&o}z@t}T07 zMN>42;jbxv7jG@>InDZtk)!?xcTGTU5M;Ft6n;3Gbr{;>n)So*v13#2KAsq z-H||*DL*?U9Y1+nPYsvV?uSIo z!OJToazEZ1MDi(v{Yq+nRBvRofm^82fM7F!df()X04rVp+y9I8@(H`sN(-{v*k zt%JU91=hA~NZ7ttDU?gzJF39=PN6ur3qkBXPwt+8D}OXMhNnCakiqV+q8gYeL}~*)6D!3Y)pvCkU@cMztB%i`T1AjCX2d-M#sAU6M!GuiV#gY_W z?FKrR!+QVInJ%nVF0IWg0k=sAdyU+yyN}0-qw5EPsXU+mkEgQ=h+_%2ZV16WcwlgM zcL@Y{3GSW*cZUGM9fAc0cXu1y-QC^Yo!jUB@;VQ^P~BZs-`;CM)M><)T1;oPrz-Y@ zl0??`pHDrRw^LmWB<`bdYdVj5>D4VSXVS?fxzebPr2}dOBhidi5pn6hdO2je0Mr=` z2y9AmP3M|5zsn|tK?78kSpBNBlUN?g%P*EZs$T~yfBbpShsEj$r-Em8zNsQr^K=yN zsaj*{fwKKXhfQfYIB}h9ax=qos+H!%#F;(*d2yP0q-2Dkn=HMbnqZfpD`xRpMU(f; zciKyI_szFC3vK3?A@pq!S^M8V^r0`!1F?ziyaBwGcrVETQ{e8#V0_@2xy)Q%cOa=z zkvj6zlh3+SwO8!aP0!|rU>k<$`uQ?P?_L546qL$}cahzZe1(1F{1nzLw^4sUTN8Kr z*SYCVah0!M*+lLa1ya>7x?hmLZ6`Oa0C!f2`f zolezX&?80k{Lg3xGqD1guMA~K<%i|r#>wP1t(8(dKrQ_kn)98i>c5Ndb3`G#2RzTe zPHh5BfU@45%TU_;5Hw)W^1$L5;qa8g4xH3}-!bVtJ^b(pX5JMWqD>Pd@USgo3}Vu) z_JGDI)r=0RE6%n};^L8i3PAl7KEeMFjYzQX>;OCKoH&2t{@!NY@k1cu1k|dG49K)t zJ@zjAN@&xa0_1-Vwz@wYSs2Q%+))O8OK=-_)8Lgonn1JVP7yZIhIm8;c7%M&3 zp!mwH`&`X;V3JNSR}@;|^DhD?Nk3Gm z`>dnOEbC!(*@a|xhju3OwWs^=tDW8^czD_MOhnt`OS-2wA>SRoOuo_5&6EzYBQx3n z4(YUs{pt@D$H2mdmK_RMSpspEU)ks;Es3*3Gm@38$~V|%h|D#3Y=^o{V-)o4bbpGs zT*^i;w(9$@J`N!C4mwB&t1f7-I9scUm7CeKIPOzmq$=Ub>Wn}(ZW74Xq@L;u8LAw9d2?(&WN>== zj--brHp!X2Q!;GQX0xIQ2rI6{q7Q*awbMk2cjbtW<%oq>ilz1L(wFzoA@~8zhrb1y z9E<^poF>GbAL7YlnOItAP=hF;#|fMC0w{cr%Ue&B2j=h3MYe1^pt-;wF zoY3cH&Qi0 z5w|+i&~umRV5$ncqo@k`aK5a5L*@GY^PSN&I>km4LiGl2*Mwkd?+#pIO35lpR*?n9 z2;1t(&gAjk7>WeC0GKaL9+iigy#b9JpcLCUG?1v z)#%j>U50A4t`|Jo+!wHEbn+>#_Q!#<`4jQn=ricslipD4#}iTw+9>AlX?$N^DeSfD zvgK6~e<6WklQ@YxB}^x$f2i&a$)UrGaba-=O6O1b8RRjEiwphq8C5Wpxa$lQx*x#j^T6mpuDvbI!1Q(mK5bomy9*Zfv^+XKYgpKQ|B~=#f1ua=gO3 zLR<%kqw)7Eyfe~*eX=Q^27e0Sho1jj^*$Yg^LYfd2Ym<*Xp>QD+jWc~k8fS(CLz(v zdj92yJ$H^5kFl~#;Q2Yfe>KAwKHWb%yh7d~QSLU|aTwlU8Cz720QrFm&t4NWRL5 zg}jc02xX-^r_X&l6K%I@c^`KA*C#8@IbZHa`5z8PskMZjh>R1eGJJ*|R(Lj4tiVqo zs_IY!DxfotQ zSShE}$Ma^ENn-G8e*=$}b=a!rZ_T@!t9HMiCh_p5CzMIumom+W;b*)$4VOB)9eMU@BaEPaW8Dn zC(X1!7)Vh9Y5zH=Uz5LOQCY2Y%C`Yynzo0*TMf3T??XZ?ua1cOQ#kIgG`_LC55k4^ zVQoH?@ub4o)SydX>|3!qd2T@0qv5sVm^j7w6r^SSbYc;n)R{FLv?+Q=sEY|~J%5<; zdcyYlzJKIJJ>C6cL0F+34cL2EPR?Q{p~mcdAMT-+WwxitJiV+{kQ2vMu@M%|p~j?R zW(&NUYM#R^DpPdLs>BM4zPX5RnQ_Grs6YT_ky`7Wh&V7>uS7Ia00bNk(QzmAxgoy6YcxGzZ`K!ZguM1(9j<}u}hGc06 zvXzbrTQE(a98CG?|7-YuNyY0FEf2}tDaR>jC%U9NTrORf1F+a(d_Hoc;}C^TyN`tD8T_=sP0m6 z`Vfi13Ske76l_MPf7;kspyAH%alEe-{R7pM;W=hGPYcbC+=->y1q)97dfMuHOPgvn z@eeAL6V=ktR;yJ=vg)O?H&{<=8y{h=OzziS1>i2;=uIZFrN6CstiQ9kPO_D^|F!`w zSKbr8^IHK!QkuVrcSwP%pmh!|mx!gQiRhKJA%bBm{lVD{KfiDfgG>Is5r% zHWqC*Kd~-_%rcy&ri3euwIYn_vj`n#G6Nm_h&bS9n;cilXGzen7&a42>>kTll3OkV zxBudNSg?7n=Cd+vyW;w>^yAEOa^w^m=6b*Po_T#-c5|`GkviRd58rC7CB^ba*JaVH zaW_#XCVX9l*XPB}>u%9PE^)F{i(TMhBY;M;l4SnFbiRBy5_3z3Y)9R^et1cFb68SW zgI{)i0GrJU&&$(sg&fyjcB5XtT8X;ROrf$|y{LLLcEFi8M!)Jx8_uPF^_jkVOcL1f z<-vZg9SN7obhlWoWNT8ASp4xSt5c+5_=m0qR)D7bqRVnXRR);t$ILa4PnX_1 zcsv1msjqN=c&XkcN|ch{Qi`ptHRNj*eIG&eV+vsD#mBULTS z+FGi$*e%b}@uks);Oxb*+^lrq#@cgoA41!LmF{KwJRX-mCObCZct&Wm0*OsZvp+;q z%$|&SYss}(qW4XUSSNztMgQqq zu@xWb#eg^~hi3u%-O95n&9LA+#6d7Z(^nfWD z3&FzGkC>ONv*8p>?T|L!HOUlt({B?dj!rLY{72yFZ!Sq<3Iok|3wg>!K&5Q)-sC?@ z!4|kb(@L*)Gszh_`O*4XYtE#Fi2BCxEC{KK2+~HDZ3VP!U23=~S$9d>n2t z_!X_qm}CW(0k0hy**eDma>>!B>aGG+ zUmaN=WWI%}%&==I;aTOIWdA5AJjJ~IUXTEjGU_f;X&L^bIv#CSg7vU5^BMz@FJ)ZZ zg6s&^(o6_T{qG?SX)782%lDr8ADRzr$n{7rZHQsPtWo26=my-+aMuY9-=-xTeZ%+L z2!l{Zk2YgBq1|Z(Y+!W{H^9px28$b{;)I4y(?QU1s0UtV0V6g^gXbda7Qzoi)40v= zWf5hNR9N8j7y;cz*XL(YFwA4v@nJQy8NDuoHQc+%z~7|C%10< zjAeeAvMJ&wT3uU?nraG(fgDBJ%h^LymyfDC3p7;mkrhEl+dUe4y9`V|JyqUSg?#^< zHFpya#lh2DhcCz?eS`{*+81X9K;M7O+wG_`cA;g1S-@*v-m1fOME2Yc4NYtzKO#DS z9&5CBgB~SMCP#!ORmBb_H5TnMm?`LoMwX8*mKj$8v40f2w#;bx*g&vmM!pH_S9+2>|b^5J@1xGprY$Y=B)r&XoeA5`?Pwj(h(omnUmJ`!H% zqwiGHexkpK`CS<3$J2P@QN~mbI(8uEZNn$=RPx5qfmobD3IJ2z6gv2LzQQ7)X(kx; z>s03$h~I_9ms}yKNWazN-|O>vyM;S#ZCUZ!;cwwIgC=jgl1 z2z>U&q-(P@7Nd^@7o2zCCEMEa!FcK#O^ofk%yNsxdQ4R2SG)2b%1pgD9iE5J;|F?$`K_M1!yjhs5v%N9pt0b4w0}{&)iq_w*a@^Nr_J{NIv^ z@=3PT!f;bRaE}A=teSS6JP`rrH&9*t9wGsQ*B1obRFMlu*4F{EgzgF`1E?ak0uHz2 zkEJKYhKM2P?)nD5E+IwrJ+*9tRfS6qI=2|w;tRjJcnZz=x#=@lisX}DuzOEnWbFnM z8nV6OqiD1$80k39B80x3cVwG&t*RN9mg+ZHBak%Wt2l1ZH~*;4{4SmnX>`N6pa#yz zF-?hr-}5u*WCA_RMhxZR(2n$Bf9L8|ZH&IkNczSOqm6zmnvxw#>ODaBpv-|QzX6OP zBm`;s@m@H4m3@cts2@LBIby8r41N7hYw>!Z(lF7voGl(+4b@}PA7x+0Et5dkyEj{+ zF%L_*x+f6lVlsG^{y-ryFQGx3%eu;rBP{f*b{ zg5;RJU_!)=4^I)F)%efZ<;3@VSJY`g1N)A(Fhp#+N-+Jeu8m6!K(PmDe_fPKf!89zvZ7<^C7`%3(PY-fC z2Ike(NOIF+4As)2Z@Z34zg{%4Qr_6FtTg>jB+)AShhaZ`5<_c_p7drs@582Hb0m}T zz5aq&`Vg%H{jtl?UZ8=s2iG7KJHSkC!Uj2n454+*+a}GLufZ7*w`VJWsHoY8y*`0n zZRkhL){K-Ll>{i2l$Wzd1mcyMs(XBZ98!f^lJ;JGiK;m{pZ)S=lhlj#sj=2)*$K;C zp)9kS>gy)TO~NiJcv+eNweo@E0hXR-`XAn<3i?%61{lttYohF2P>>|mtP}d}-#*a# zq%o)MRbJIZB;oIjg(Z3wo97VFBe{f0QxC9#Fr2mJnez8mr7XVO~I}lTwv( zj)a^dv7X#Hor`Gh@XntpqIth0=Yl(C;Pk1OAympd1M!%J##a$)p2?Nnf;vYFh+I>pvc&)>l3>N@O=V1n4m!m-7q%v!o|+ zE3h?2pDkNqbN4^fY2%`Y9X@Cd`*eE$VV~lG4%r*6>REzp!N~@P^+Zw@dpEcjy@le5 zMVT?aNt0_&#hQ&+UXp6Jo$B~_+W`;!2I|84j}uiwHdt`YhT~+0VN+Qf+-aGX@lds@ zgF5u3>T;VZKG@7g#MUXc4;`dosh*RWK$~l5X5pAcGD$DL0Sg}4r)w$o%wWD%3zrZ~ zMc^Z&r&I<=O^%(WH0Tj7GE!O6axAU78taWaB(Q`Sqby~}j zyf$J@Z$*Y%wRHiz3bH$&<<(B;%02Fy!n- z&{FLg#IF9dwF6yUyJaf62T(B)qOIyeRi`%cs&H6inYhFEr3H55KDiH=ye&@4e^x}9 z-{yjO)o1oE`(-X}BbNhdM*eaoH$ z6E&AO*`Bg?#x^QhFJmV+i-Du6QXQ5b**z&G2XfCjjA1mEAui5LPZ(N^mcK+KGo2?s zt5r2+B6-Jzj^l~87;l>?mxX6lk4do{6v|N*PkO2d;)<7yNl#cxIaK)A94XSX?O1fup#@t3R$tS#CebW|q! zn7?jZanm;ddtcyPvl+-suXK>dEFaIeks9Krr4RhB5B&9UwPM?U`bEoeC=bnM{~gYn z!YG1`*ieu70_zmx&J*}@y_w*=XseFq2kbrdM_V+Be{My(5jw4PHKILfbI(4CQn2Bh z&}RQGh(hpSC+WZ$)}s))2mS9y#Ys=x|IYKbBijmHtu{#mlFUnY5YOn({eq<(p)mEW zoFd?u7M;nA@P~i`DO|55cqMWE*A+28IdvFraMbhMn&Pjz5$hyb^KCvhb{&{Vs(-Cc z2TNuVNh{9u#=2B09G==eLl-lWuoUIrcgX@QJzQ-f71KRG06{UhFEgcGbzk3Fn(W7& zp;_J%BriMUHDVlyZ0u1Zvv}X0cEnpQ7vN_~joYB5Mf6086KBZ8bCzZ=HZDjTw~L3B zYpUBoK(fUwUgOJrd6eHOe`OPP=*q8?-&KUknOFsaNlKP7;04;nnBCA?~ z@qlJVvP`zOaNGSxAC}lWk1r3)|CsY{^;jgf(-;4$((In&O8ina1_@uGq)nHNq}{lF zF@Tv6w-Ze3%<@+VM-!Bp7f_>qZjvW7GtV;#5jLCX6#j(^M_r%*K5|o1@vdbLT#H=F zkwoJva!nZ`x;$}7iNklc)6-S=Xt?Q%BuF{=bgMl1e0LgOj$52_j*v*YOjKGA)314^ zIupagueJ*rbr#;>2{~Ps#5^gYnxEk; zUl~wpr-toL@Sv*sT4r?s4U+Ckt&lcHVPJM3k^`f+t)aq9nLdJbNSVlJF-?r{OQ!9# z2j|6UNzUc?z6ooo0a_e6+|g`d#F83awaENuakKL|_IiH*w;Fiwx3$#EZ30DOK>BP4 ztR7asf%%)mv9gYw2HkEd=I>=nILxcQ{A+GIOvtCJ0hS1&I>qV?;Yq}en6?5gXqSgY zG`;oz?pU)%#IB5-HU-?rtsi!CxG(xJ(YCJ6vWNrt4OTw;`mmx_2>1w>pUop}19OV? zwr94hlJnA<0gECuyP%|Q$TFVBn|}=xkgWle7T9bg;YYst>lI+$wlEal*t7A!jyubZ z!%)#@=c|g>ji@2kGSEa==Y#-W0@Rn!h0zK>8A|XH;&eX~TOxBc06>z)w(TUc=s^bP z_JS!g-}ar~P|yqHKD4&2w>X}<)wl;=89>Q-(GKcxriU9lAsFPzC$LYbT9AIuX-Vwq zLB#gNK?MDIzhxdic-iy4Ja0MT(NZ#|5`qJW>)}`4Q^_X#tv8G)@1= zMmAb!-GMEPZmarDTCdo;`nCwl`NvJie+TpwqsN$7#utQ0P>O}l#K!&8zj%I-P)jd6zHqzxO7YK<0O7CI?@i?=1p6oid&KBJfwXQ0>u`K{0vI2{)()+!J`WlVdlr zoqhZ=v-~ z9MkZ_=tQ^iuO%C`&%LFUoxMJal*bm^fu;9KJ`Pezv_Ynq+-{iLY%0q_slFwfcLj{8 z=nFpz+_Rz={FC6};NKD@%^wBBtq%yz9u-RRH>`0C z=f{8aAI;uwS~7KJ+mID68$j~cBF&vB$Zeyth$_T2mCvoxoq3Flb2rgIKmNQkA=qhZ z1Ft+JK?wve9|pP@R0ffmbWKFBVe448OXe$o4kabu-V#`~ZJv)`J_nDR{8+a+m@i{o z`y%*pmOjBOI>_fDpEUXIk-pLKhwzGLx8aIIuUX?(TvYPquH^!swLqf$%kPo)E{VA9 zWewtPg6LI0am=+&^SJwHw2bbJbdXl-e{G8E`?Wvr>#e<8>hf=R8SNM7+FYfhCjru9 z=lY(6Ikp60#$Dhcx*LUEKw!HWEL^Z{dPMu*pbN8LR3ugu#wpqTph3{*V)k$Q>Y%S zWpN&TuLxTdd+)zll)LZiH!vEG0yj3gW2)yPAI(C?x4XevTFCcB0L6*2dDP9s-^t`4 zG2~#3vehs(g?RkG5aFTIvdVpjT z7QWL5yNOH@x%_A)t~TGKqZvtt@M-IY)%;a)dQ`IFXw$Rlf@m(1#XMPDE<5}vJJ)2c zUo#=2z_U&bG2Cpq-qy-hsgM+T#|o;x$Ll!fcPidUvOpL0~;1xA8xpjAt9O?9wZ#Hr0)9zM)h+arEEBCMOl zs1~tmF9&C?_Mceq25>7f8U$JXmNAp9@vvaf4QdUJ+GzF>w0lSS_E!j(8WptA*0v5T z|2Y4Qg3&E)!I6UZyb+77nUpY<0p-A%_57dYfX^9^UAlF#+Pu4!TQ@QlXb1$AEmyfr zs{<7%BD7VqcK-Xj$??r`d`CB0vB#-Asq)eVF^58+PSkaTlB$%giBW60i1q5>(x-|R z^%YR1UtG=$Zw^duH$LxK+MRB+36PQORf>q?vbYAbN*L(j0n0uob%`mjL#$Ppao}c2 zQYvw&NuLqvH8VuFpvXNXob(g%UIjZH7qIX})Q!mIt5O`sndb}X-m*kZwQvX2xz$^nPtFoyZVjQX;uWr@OY;YoWJR)BmMRC(%8u3Y*H zl6d%H)@6-))ECoX1!>`hGgYma*=^5%j&bMC zX!K{<>LZoo`sS%sJr z9ibg`3+@OVIUR;8Ixz27-bp)59_AN4-SKYPp`QDG*xW+KqxAYE@`6io)N@%&#QMMY zE_5XWdIg$po(GGj+V}t$z4G+IRGU5}bz2SW{m9hF%jb)qQdA{?OtlC+U5?w0Cy8p* zi%;+@@q_AFFOZ;FZuC%n)j{KsF+((We5>rzF=v;u%)u>?5g##Ej+t5c$ajJaRl?)H z(J^80#SBkH16LRv(#WyB>^+2DHi2VAV~e&7E_lq(vAZ9v;g36&5ZX{4g6xDghK;g2 zrDsx1`N%&eMb;~w#puU=C(YGR8piS9n|GR#pD1Bboiv;8?(8({no` zTp}hfKMejR8MU=pMQrrswJTX~ERMMK=oy^jnYx!;Wyjn0Zo+p4F=8qH%N+ThSl*{< z>l@k?c(pyLQy~g2PGA9M%n!R6ylw~iB}#xnvgLJFtmSc6(QPlCz)r1#Nwe7;y6y4S zfa|Mnn-jwSHAH_-Cv;~7lK6gV1Pxo88bV)(C7f9ueh8<@367o(oURsOhhfo$DEdA@ z+xlE$^40(N^IxbRXv}Zjj#F2PZ27D%8I9(bxp}^bo$%Tv*BO{C6;y0=Y?3z`C= zth_!yk(0CdK5DPL?O66$FaZ0ysAFPpzf}Y|IFoj_H;j`N*AE&i{6UgMH2q=0K?ae) zk+HiZ!#fx-qQ-lXFLqpcGq;WkGHq<8mXitzvfNGEHjb|Xg(k9<=dRR|ZODAO#A$JY z{W?;`c7@h8%TD##N%=a0uR=Gu$-0r6{PULH6mHRh_qE_lWq-6K+dTqN<1L>qcO^5C@2<7i`>{b7v(d@+eU4->7ar#x3`emJ95?b|xKdZi(1#E2 zH_~Dv-&sx8yXS@9!hR(T<#hLsvRbYgmo7I3KC-(xH=8h3B#{YsPA7E(@gR2QHCL1X*P;f)slPj>v?nExWk}k-mkl0{kh$wC{c9w z|A%oTL;}y9Xvu984`Cq}{}EN9SFlPU7VGb8&hKDG4b*~v4I7l)6kDOZ0!{nll6QI# zV8S-52>v?W4RNRSlNwXYyp*hBTS(S%uW+Q`;i>6`BGySrMmqQ>wxp|iun>9nFL=Pz zxIMzY$)$e#ZT(PoJ`ZwxxV|(_vaAeCu1OCCRlh*QQB#Q-Zbzf2Yn9Xu+}}7xk3PXm zIe6&>9=ZIBtw$QHUSJ|({c@6cR_{*Z5B)wl{jgj>i@@w)dq*o-TT~59hQD!#A!$TY z^e%R==fBk)D_!?>BIL}ce1oA2RH=^pfl4|zEEW)77{6c*=fw#;V-z*|B8--ZQB|de zx9n{R?f#1roGuuoY3}0Tsy}}wL!405OV=Y(kP=NUk0N;#nSKu^GKBd*UfDByPK~Ga zt_1|!Z<*4mC>F#&T%Sz#2S;c0bdvXnydpd7jVL(ad;=OW3%^fdWciKyk}9?iA+}#b zv&Cb$U77wet9>+hV}pT~cteYBeGC2B!AyGqmzV66OK#+Z1{ssD&%UX@l1lBrr8)lGjf;b_K z%&`tKVB|rN^MkFq=+w9-X2b`2yE?z15IA!=`4fxNe-^pHcoh?5rXgddr$c2#LZmw$ zaxx|kE2SySBsp4$7$yU{=E+^Z*UIlTviMll_e^@0f-R6X=b836Bn4b8+7o9x;_AAH zyFT>>G1*=>>Y|PM;g=?(+ehivY!3@ z-!Ca-3eF0*jx#GNkTTNx*GHr)%Rhc>F@l^QMB;A{9>y#XDpkkT7?huUO+Ud^BB55I z!BwK*&M0I6GaclsK`-|>v(;1EQ)#VJ4v5Xw*hAF^| z97rPA5_wr8Vc7~Xp+B0ZW#Akqvap(_4s6t=NQ9>BvP|Vn02e9>0Rcz-Wvu<#i~9uR z{cv??u_hLpiP|FSWG5{>!Ar6E_jQkCU|7NQv^#>7tgOY|$zoA^JIZJ}W62ckm6^P^ zC{$UvkhaHqXZJ~L?7cox$(X zT{g&&KBanvh|b`j{(>w-_=K1_6G>DYx@n1H7NLP>$gtf+rYEH**%O|!3Pmdg{6$B^ zjmT~>OtEtS;6zOJ?zAe$joD)db6}r?@{!3z;G&t_?ZV^pqmO|M>@qmIAlLZvpWy|I zJ_D(@;=CWOzcXC@i~bWc{bPC3>+gBVRO)#Vl4U>W0ns*srd_N@{RTk|mWyNRWyk$q z+AHu9vzHL$F(jH%b|uhBoDIb3MR0RlKY^o66h}Fq#RqM)eA%gu0DmD7cgin4rOP*w zO3kmtf~!OW7n9^AISgh*s*b;Vep?9t9f9^ZCDTCA{JKN6{CPF~z(p-a&Iz5z9ricK zn0JCo^8Az}v1#CyqwFZhF}|P0N{-LeopbSL9Qqk~T8v0}9EH^La51Jg{spJuVTth! zrpOYih()Dkcb*m1(phW_IPw3~;#`_uWR%ziha_~Q zH;u;wJnnQLK#)t`AGKZN+9o#r*06bn@!s9g{vLk*_J9j??m7j_78|X(fjUHKD|_-( zi;wlrKst(LgVpvI*Y9*XVXY<)hq2t7k&4`K{b`E}G1OQ6d<2(v^~ms*y-Dj$tspYSYyk?{^lwhE z-PPMgr2psJb|x(Sr(!g64B#;QgL!nIfp&1Ri+Vu|`2tYV2@XFtgC|cJ4P3MpW`wGK zB`x2Dy#*~uCF(_@B#~QT_xL>)K0X8&ZXd{gln7YJ4_Qt+=sCJlJy8{MjUb)FvyEr2 zeQGqk;yel^xvpBIx`7VQ&baGTHdXFsu{Hq!ut_r}5ge9(st2_y;4@@<#`XdkG@D(> z=WN!3x?rxh=SW*w?lzYf$p2=v?Rx+*-9Qw?ah+xf2qX#h!o_kLc|4*S<3G#sRxRWmaUu*$>ovMl}Rd=~feoZAcGVD*N8t$X#_w z_Z=wEO#hJ~E?){$EBEFVSr5Sli-zT~wC{|4O+Y!a))tMUOeelIr_o^Eh2mahL^BiF z=L^F8Fu1&(V3!YNL)BN;{`|f2euLEObs5X4*@oi!&}|h=vwZ2mc561hp`25-|KalS zmf5N04t38Yyb5D;=wl5IL!ZAH{UneUrf(=(p zFyJV{W3&(xTbNHdh4ydgU|8V@hsa~5WBJs?EG^Fuz<+3lEx+RuWJpZ|-R`eY8lKfa ze>%%+Ck7s2>NuOIyN+EbjRI|=di^S|^!aGxg_+jA$IuzOoh5k=*8{t>?>nYHBD?kw z-eWQ6ESZ$b)UM%RwI0OqbBOrWo%|B*qt?_^j7e&P@WqMx;fs15Ad&?qbovZO8ol25Am@ed&|7Z9l^>_2n z&o*73gj}QV2O=WSG%RpH$Hnb+x0Zf`a#(!eHPXLPNFMAWGt+2ngI*k{RCV(Q zQ+wpLT=Mecb!gn#l0hQ4hsAN<&1d0!c7p`b$7`dn_bvysRoDa@;3h*#$g|7#-Ku7* z^y6l!TFz4A)>ITtVO#VZH2>XMKQ88bUzFgpa*cyK^6@gtE2PdO+9Dm|#EDa`30!uC zk@>Ez(C9akAmXyMt3E`hT(h1*1`Cyo7zps*4i2AVJdQZhJ$(f{T`SJrw6K*ocJGC| z!+`GLI^(?Ybm{s8#1ii1Vi~LDW{rB}ZOmfbaC+|4?dlC`!Nf*KPkJa$7CUy9|Yk*dwN z5Y^}Y4&{nC>vo#^E7QkI|8*vN%)Bfvg-52eE*vqf8bE&uRNNnUId$L}JZ zMLgIa=`z9eAhtgV)RaSr3tsvu&vzDTLuK`)PXfM1MG`dafb$;19cV?Qrnb+fUY_Qw zOi@>S;3_-&zeC-b(k@?J(Kt2qrXM>5k9}Q-x86gW{=b}dOPDNFd8lEA zY+>uveBVR6DL_hh%49t8iG=@#fwZ%ZV3%*ZTBgif`(?A$IKgUsgLI}kJrOK*0unQRmN`$r!iN%wrK$GNT z-^SH_j~J0H*fCO1e>#)4moAFNiLdn=4L0tL`A6l(Th{*$1e9EN_)kieBO<1H%C;tX z6T$lGRm0R+Z{ut3AEe}+>|cEQCq2(w@7Fvfv0}3`3kx$tWK_jUHEHMyy|4&EV6equ zM80~QgL3cJ_$8b8&(2caQ%tEBO_xv4PKh2x*lgE4RoQ>?CyB+1>8c*5Ve2k(=q`@f z-7zck2&W${e8HB%5jQQC(rxwtvE!6?WpnBbtW}y*MtIb5w_ds5P1Ow~(eqE`D@4Ad z67?$9;B5D#T<`Q#8$Iq=HGLMZJRd+vYjT5ux!&n1y2h=tSthFer4+A^(rVT1Vzugs zewsQXo>1Lue{$nKqSb~9lWe=(=X}6ih+AEKPbB2mS4X!!=_0SW)?~*`1$$h7-g*Ac z)V*uTtyHEf%~7I?O+BvHV^G?*NAv7H{KR<}y346krtkbifJmxe3dMpL4t3E!it`~p zo$;SGyqscOnu79=tnMC|EL^Svo>xV&#jReYdNF0IwI%|K1+ED;44+y0#2nlAvn5yf zXEb7LbIR7BB89L4k0=~m|4Ey`w1R?%7>YtSh-I^=tChXqn7o)S<*b!l<<&HZUA$1# z-bDM+jW&?5q($ylbmB2Ip_IKRq0}@`Q<|=;NG`rHpKXa}&n1qK9;S(*YlHdO!3n6H z5N1uELVE~Hj!?87wspVgo~Z_TC09s~?S1kzKv8lR_L_+vbL8^dXMp&)?Sbvd5}kbT z*52EeTxNW2-xYh}B%D&`q((NLi7#nCJ(Fythv+oK*l&tr$bL}-^ZS=x4p}IOhD{v1 zsFq9S_06>OijTazd6mm>y=Zn%*p^Zb3hL%Ou0);@1rJ(fK{!a0WSz;;o~>TxI7d= zQ-6xMGZ510o$;;rD$o9$sGXLzBx#$$)Rnbr}ETKsD^N9*r=oJzXhK)W;{SJ3U9hjdE0c3f~5VC zTtVM@KUuJUQ(zXQA2=JMO|HB=KF#ufNf6tU4xFPiC?L+_Wt!4_ftQcN!S+9qVF{Ea z&WS>Rg|xYWV@V&8QumBX8}}EZDZU?GC8q?=z9ZP~LKJ`4GQr5k~Ji z{TqNW=kB?6!H6sTli#n+h($kIUW!$dyPtfN8&bOe!=4oHRDHnRBMePC4#xMCPN82A z(}_u?hpuRHJuidhi?^J0P-DKv#M|%w%=x9l>6(!E49%Y&q=okMf|zN|${P8m-^KMl zE@~JW7u1>LZG2~uyqbUfMeoN@!UCQa+PIi5V9DiPbsf2iXWi+%c!(i9@#g%x%Lz=y zY;Vu#jJfCdVdYNL?CGjIE z?4*`+r2~I?*>%`R9TP_eV#(ovJBv`O#cER3e7U7KRukA<`FIIa^regQS96(BrXD#6 ze;%4#lXo%0Aw#OI@x*tz3oayCYC+?tk&n!5Hfs1X}V^CDbc0d^!0crQCm&&7N$~fUHR?@UX;S3kq3W~7sq*wBiqumb88e%=?n~p zIkwD%m{woa3ebBe1inc0^k>@}c<3p*6RI9$}RB#&=v= z61kIFm(owwrDTu%i-Jx*PE^jvADw1T|b|DUe^`K3z%M z(|8UP+EwnjyPm=^S_C)EnLukCGJu`1Z%lgA9Xucw|_YvsfX7o8N;e>v}dotKp3O6EmP zh>`PhYOH~{#$5Exr;t;RZzTC98cy9bEwmi}o(RJ5JD@w;ADSQ8lNVgsv|i-eMAM6R z_cW5w@F|Z!v|5?(N}2KM^=@P^`nheNg>H^ACCh~^KdSDa*T^7_Evzl=!6a+1rO1Wh zI3#O3|A|*YNHo6@9f3%LTt>>WUxxWu$;lk&9#8c#G2B1;=XuTcXrsYfXF55x_(*3`(7KDv`{>=XPm0YlS8lU|R?kO~3sj0&jdBu3%jkBkL`LSZ zd}(T9Qi%|v0(W1=;Y7(EtGJ9@-EX;{1eTRm%$UBPd6QB@=_iZ(>7P}$ovq`u=Sv<- z)G6m03K5!dKbr$l5=4|=-?NEh9vc!&zswa!44KJpjr0zOghQxnJ%E{RV7lH?mP*R! zkkIh%$8e25y~2P61MgPrHQRQzZ&b(ikGdk~To6D>*0l6-KvlGUPbgHRSk0b z(fcH1@>I*?dRRR16wTI)w0Vo$OfH)rvEcd8II)(|V|sr=k$86`PP+I*^Nj0lIm5r& z;;AlX10?%^+18nU;azTpK}w0HikgP5qJpsIa`k6m0N!*k1{OePh@9#2F7Wabg(8G% zwi#ph$)|<%$|i1&twLzjOYx=(6eX{58*Ie47ed*Ae{JRf<;|wAGj6YX6++hRJ8Da5 zQYa+hXWK_X;r!p)&Y4WqnoUkSw0T5^&$G{weY zIMR<{Z%PV;3MJ=K9~&DWOabDi5W>8WFPK?4&Tfa+9$I%(%g#8k;RIk5dv8RH>AxQI zn?n+shh-O2>l;Mgh$LSNUX1szFagrAx^mZ^r_;^#^nl51praU~RoS)ZC@s22rB z*Zxva)>riqzZUOqQn9PDt2WD+*D9}2_~je>hiWA$)TbVB*8G~r`pC;f>>1f_#5nW` zEUiE;Dtbwtz+_;Z2SXvn^i&<$hCEvS2Y63lMch(<_cfZ;_hxK?oiy_-Ca`L-Q6X)Lm-67H~-A6xed7q z>$S7@KF^s|t;y$Zcj4Ska<*u&-GVXCls~1h7vmBT0{#I-`On6-98TqRz<%%gwM2BLz}UKT^@Vl(*$vAN@0F|Q9v7BbkU#~AVgl6#z*2-h{i`Eur<_7I z35vPe;MsYz&4(Y;0k&Jrwi&xUX7@pZgM+^qA1l7E?Lf3Qwwtm5eM<$11{t*?o?a<> zBek~PEX?nP-}s1I?1ySCuwsb${b8w_49=o-lzRl{7V>`Jo22SAnvYGYXT~ z2ZK{OQORr^lEQ~V6igq1W*%j*rd0etvsNFLbUm&`BY8kYP~v@UHya zWc=&Tsq@YaC(6qSce+W#HQGtgWiZ21@L&$lCpg;dTEBY+3fJ!_oZKL8b+$PfF6J+Im@eb?=EEkp3&Y9{ zwnBwamXgW-ROz`Oc#rn6k9aq|ds10^NNaASKOX&JLUX`#EttYS*u3>-gU2JlotBkI z%lyallpK*Iw~6oGBLpZUtV$l

    =x(0H~vSikk=E3=6^u2%bK{zg_%gpFmju7~yXb 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⪚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ⅈFr7g6b0P)7we>rA-xtGj4m=Q?A10KNQP|o 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

    r~cG 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

    J`&#?pqui#!p)D5$$*W%uM{qE0=Kpbkg_0$xew# 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%0D0Qq8vk>znq;6QVQCnHuI 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

    WD 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

      IdXNs&73LirIWtgMuyphXS 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 z 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

      $_%v>`>q#M=i_mf4Z=csKLz2Yrf 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 + Have a bug? Please create an issue here on GitHub! + + luci-theme-material + Copyright 2015 Lutty Yang + + luci-theme-bootstrap: + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Copyright 2012 David Menting + + MUI: + https://github.com/muicss/mui + + Licensed to the public under the Apache License 2.0 +-%> +<% +local ver = require "luci.version" +local uci = require "luci.model.uci".cursor() +local config = uci:get_all("alpha", "config") +local icon = { + ['/cgi-bin/luci/admin/status/overview'] = '/gaya/icon/navbar/status.png', + ['/cgi-bin/luci/admin/services/ttyd'] = '/gaya/icon/navbar/terminal.png', + ['/cgi-bin/luci/admin/services/openclash'] = '/gaya/icon/navbar/oc.png', + ['/cgi-bin/luci/admin/nas/tinyfm'] = '/gaya/icon/navbar/nas.png', + ['/cgi-bin/luci/admin/modem/main'] = '/gaya/icon/navbar/modem.png', + ['/cgi-bin/luci/admin/network/network'] = '/gaya/icon/navbar/interface.png', + ['/cgi-bin/luci/admin/services/neko'] = '/gaya/icon/navbar/neko.png' +} + +local function getLink(nav) + local link = config[nav] + return (link and link ~= "none") and link or nil +end + +local num_links = 0 +for i = 1, 6 do + local nav_key = 'nav_0' .. i + local link = getLink(nav_key) + if link then + num_links = num_links + 1 + end +end + +local link_width = string.format("calc(100%% / %d)", num_links) +local blur_value = tonumber(config.blur) +local link_blur = string.format("blur(%dpx)", blur_value) +local background_color = config.color +%> + + + + +

      + + + + + + + + diff --git a/luci-theme-alpha/template/header.htm b/luci-theme-alpha/template/header.htm new file mode 100644 index 000000000..53e5aac9f --- /dev/null +++ b/luci-theme-alpha/template/header.htm @@ -0,0 +1,96 @@ +<%# + Alpha os is made from me for all .. especially for indo wrt members and fan of OpenWrt or DBAI Community + luci-theme-alpha + Copyright 2022 derisamedia + Have a bug? Please create an issue here on GitHub! + + luci-theme-material + Copyright 2015-2017 Lutty Yang + + luci-theme-bootstrap: + Copyright 2008 Steven Barth + Copyright 2008-2016 Jo-Philipp Wich + Copyright 2012 David Menting + + MUI: + https://github.com/muicss/mui + + Licensed to the public under the Apache License 2.0 +-%> + +<% + local sys = require "luci.sys" + local util = require "luci.util" + local http = require "luci.http" + local disp = require "luci.dispatcher" + local ver = require "luci.version" + + local boardinfo = util.ubus("system", "board") or { } + + local node = disp.context.dispatched + local path = table.concat(disp.context.path, "-") + + http.prepare_content("text/html; charset=UTF-8") +-%> + + + + + + + + + + + - LuCI"> + - LuCI"> + + +<% if node and node.css then %> + +<% end -%> + + +<%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - LuCI +<% if css then %> +<% end -%> + +node-<%= path %><% else %>node-main-login<% end %>" data-page="<%= pcdata(path) %>" style="background-image:url('/luci-static/alpha/background/dashboard.png')"> +
      +
      +
      + +
      +
      + Keluar +
      +
      + +
      +
      +
      +
      +
      +
      + +
      + +
      +
      +
      + <%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") and path ~= "admin-system-admin-password" then -%> + <%- end -%> + + + diff --git a/luci-theme-alpha/template/sysauth.htm b/luci-theme-alpha/template/sysauth.htm new file mode 100644 index 000000000..44bda4740 --- /dev/null +++ b/luci-theme-alpha/template/sysauth.htm @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + +Alpha - Login Dulu + + + +
      +
      +
      + + + + +
      +
      +
      + + + + +
      +
      +
      + + + +
      +
      + + + + + \ No newline at end of file From 94f19376e90575d3c28540aae4912a7b2292edca Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 11 Apr 2024 11:10:17 +0200 Subject: [PATCH 1505/2059] Add luci-theme-design --- luci-theme-design/LICENSE | 201 + luci-theme-design/Makefile | 15 + luci-theme-design/README.md | 71 + .../luci-static/design/css/style copy.css | 3353 +++++++++++++++ .../htdocs/luci-static/design/css/style.css | 3611 +++++++++++++++++ .../htdocs/luci-static/design/favicon.png | Bin 0 -> 535 bytes .../design/fonts/Cocon-Regular-Font.otf | Bin 0 -> 27972 bytes .../htdocs/luci-static/design/fonts/font.eot | Bin 0 -> 1912 bytes .../htdocs/luci-static/design/fonts/font.svg | 16 + .../htdocs/luci-static/design/fonts/font.ttf | Bin 0 -> 1748 bytes .../htdocs/luci-static/design/fonts/font.woff | Bin 0 -> 1824 bytes .../design/fonts/iconfont-Regular.ttf | Bin 0 -> 10032 bytes .../design/fonts/iconfont-Regular.woff | Bin 0 -> 6372 bytes .../design/fonts/iconfont-Regular.woff2 | Bin 0 -> 5464 bytes .../htdocs/luci-static/design/images/add.png | Bin 0 -> 3163 bytes .../luci-static/design/images/bridge.png | Bin 0 -> 3410 bytes .../design/images/bridge_disabled.png | Bin 0 -> 4306 bytes .../luci-static/design/images/ethernet.png | Bin 0 -> 1973 bytes .../design/images/ethernet_disabled.png | Bin 0 -> 2023 bytes .../htdocs/luci-static/design/images/home.png | Bin 0 -> 7725 bytes .../htdocs/luci-static/design/images/icon.png | Bin 0 -> 7473 bytes .../htdocs/luci-static/design/images/link.png | Bin 0 -> 12758 bytes .../luci-static/design/images/loading.gif | Bin 0 -> 37037 bytes .../luci-static/design/images/openclash.png | Bin 0 -> 34578 bytes .../luci-static/design/images/port_down.png | Bin 0 -> 3608 bytes .../luci-static/design/images/port_up.png | Bin 0 -> 3702 bytes .../htdocs/luci-static/design/images/rank.png | Bin 0 -> 3503 bytes .../luci-static/design/images/reload.png | Bin 0 -> 4152 bytes .../luci-static/design/images/remove.png | Bin 0 -> 3404 bytes .../luci-static/design/images/signal-0-25.png | Bin 0 -> 2040 bytes .../luci-static/design/images/signal-0.png | Bin 0 -> 1978 bytes .../design/images/signal-25-50.png | Bin 0 -> 2045 bytes .../design/images/signal-50-75.png | Bin 0 -> 2050 bytes .../design/images/signal-75-100.png | Bin 0 -> 2003 bytes .../luci-static/design/images/signal-none.png | Bin 0 -> 3030 bytes .../htdocs/luci-static/design/images/ssr.png | Bin 0 -> 14832 bytes .../luci-static/design/images/tunnel.png | Bin 0 -> 3076 bytes .../design/images/tunnel_disabled.png | Bin 0 -> 3258 bytes .../htdocs/luci-static/design/images/user.png | Bin 0 -> 9313 bytes .../htdocs/luci-static/design/images/vlan.png | Bin 0 -> 2110 bytes .../design/images/vlan_disabled.png | Bin 0 -> 3034 bytes .../htdocs/luci-static/design/images/wifi.png | Bin 0 -> 14517 bytes .../luci-static/design/images/wifi_big.png | Bin 0 -> 2673 bytes .../design/images/wifi_big_disabled.png | Bin 0 -> 4070 bytes .../design/images/wifi_disabled.png | Bin 0 -> 15519 bytes .../luci-static/design/js/jquery.min.js | 6 + .../htdocs/luci-static/design/js/style.js | 28 + .../htdocs/luci-static/design/manifest.json | 25 + .../luci-static/resources/menu-design.js | 200 + .../luasrc/view/themes/design/footer.htm | 32 + .../luasrc/view/themes/design/header.htm | 116 + luci-theme-design/preview/IMG_0328.PNG | Bin 0 -> 263594 bytes luci-theme-design/preview/IMG_0329.PNG | Bin 0 -> 382369 bytes luci-theme-design/preview/home.png | Bin 0 -> 317085 bytes luci-theme-design/preview/home1.png | Bin 0 -> 299873 bytes luci-theme-design/preview/iface.png | Bin 0 -> 472918 bytes luci-theme-design/preview/light.png | Bin 0 -> 333872 bytes luci-theme-design/preview/login.png | Bin 0 -> 125389 bytes luci-theme-design/preview/webapp_home.PNG | Bin 0 -> 424590 bytes luci-theme-design/preview/webapp_vssr.PNG | Bin 0 -> 574373 bytes luci-theme-design/preview/wifi.png | Bin 0 -> 360878 bytes 61 files changed, 7674 insertions(+) create mode 100644 luci-theme-design/LICENSE create mode 100644 luci-theme-design/Makefile create mode 100644 luci-theme-design/README.md create mode 100644 luci-theme-design/htdocs/luci-static/design/css/style copy.css create mode 100644 luci-theme-design/htdocs/luci-static/design/css/style.css create mode 100644 luci-theme-design/htdocs/luci-static/design/favicon.png create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/Cocon-Regular-Font.otf create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/font.eot create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/font.svg create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/font.ttf create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/font.woff create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/iconfont-Regular.ttf create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/iconfont-Regular.woff create mode 100644 luci-theme-design/htdocs/luci-static/design/fonts/iconfont-Regular.woff2 create mode 100644 luci-theme-design/htdocs/luci-static/design/images/add.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/bridge.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/bridge_disabled.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/ethernet.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/ethernet_disabled.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/home.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/icon.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/link.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/loading.gif create mode 100644 luci-theme-design/htdocs/luci-static/design/images/openclash.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/port_down.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/port_up.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/rank.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/reload.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/remove.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/signal-0-25.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/signal-0.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/signal-25-50.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/signal-50-75.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/signal-75-100.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/signal-none.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/ssr.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/tunnel.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/tunnel_disabled.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/user.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/vlan.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/vlan_disabled.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/wifi.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/wifi_big.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/wifi_big_disabled.png create mode 100644 luci-theme-design/htdocs/luci-static/design/images/wifi_disabled.png create mode 100644 luci-theme-design/htdocs/luci-static/design/js/jquery.min.js create mode 100644 luci-theme-design/htdocs/luci-static/design/js/style.js create mode 100644 luci-theme-design/htdocs/luci-static/design/manifest.json create mode 100644 luci-theme-design/htdocs/luci-static/resources/menu-design.js create mode 100644 luci-theme-design/luasrc/view/themes/design/footer.htm create mode 100644 luci-theme-design/luasrc/view/themes/design/header.htm create mode 100644 luci-theme-design/preview/IMG_0328.PNG create mode 100644 luci-theme-design/preview/IMG_0329.PNG create mode 100644 luci-theme-design/preview/home.png create mode 100644 luci-theme-design/preview/home1.png create mode 100644 luci-theme-design/preview/iface.png create mode 100644 luci-theme-design/preview/light.png create mode 100644 luci-theme-design/preview/login.png create mode 100644 luci-theme-design/preview/webapp_home.PNG create mode 100644 luci-theme-design/preview/webapp_vssr.PNG create mode 100644 luci-theme-design/preview/wifi.png diff --git a/luci-theme-design/LICENSE b/luci-theme-design/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/luci-theme-design/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/luci-theme-design/Makefile b/luci-theme-design/Makefile new file mode 100644 index 000000000..a7bf07c24 --- /dev/null +++ b/luci-theme-design/Makefile @@ -0,0 +1,15 @@ +# 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. + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Design Theme +LUCI_DEPENDS:= +PKG_VERSION:=6.0 +PKG_RELEASE:=20230224 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-theme-design/README.md b/luci-theme-design/README.md new file mode 100644 index 000000000..2381e7409 --- /dev/null +++ b/luci-theme-design/README.md @@ -0,0 +1,71 @@ + + +# luci-theme-design + +**luci-theme-design**基于[luci-theme-neobird](https://github.com/thinktip/luci-theme-neobird)二次开发, 适用于lede For Lean's OpenWRT Only [lede](https://github.com/coolsnowwolf/lede) + +- 修复安装package提示信息背景泛白 +- 优化菜单缩放 +- 优化显示网口down状态显示图标 +- 优化logo显示 +- 新增各设备状态图标显示 +- 更换logo显示为字体"OpenWrt",支持以主机名显示logo +- 修复部分插件显示bug +- 修复vssr状态bar +- 修复诸多bug +- 修复兼容部分插件样式 +- 修复aliyundrive-webdav样式 +- 修复vssr在iOS/iPadOS WebApp模式下显示异常 +- 修复openclash插件在iOS/iPadOS WebApp 模式下env(safe-area-inset-bottom) = 0 +- 优化菜单hover action状态分辨 +- 支持luci-app-wizard向导菜单 +- Update header box-shadow style +- Update uci-change overflow +- Fix nlbw component +- Added QSDK/QWRT wizard and iStore menu icon fonts + +## 主要特点 + +- 针对移动端优化,特别适合手机端做为webapp使用 +- 修改和优化了很多插件显示,完善的icon图标,尽量视觉统一 +- 简洁的登录界面,底部导航栏,类App的沉浸式体验; +- 适配深色模式,适配系统自动切换; + +## 体验Webapp方法 + +- 在移动端(iOS/iPadOS)浏览器打开管理界面,添加到主屏幕即可。 +- 想要实现完全的沉浸式(无浏览器导航、无地址栏等)体验,需要使用SSL证书,请自行申请域名、证书、安装并启用。 +- 如果不使用SSL证书,基于安全原因,iOS/iPadOS 在打开新的页面后,将会显示浏览器顶部菜单栏。 + +## PS + +- 资源接口icon未完善,如果有能力画图的欢迎pr,但请确保跟现有icon颜色风格一致 +- 有bug欢迎提issue +- 主题个人配色可能会不符合大众胃口,欢迎提配色建议 + +## 自行编译 + +``` +git clone https://github.com/gngpp/luci-theme-design.git package/luci-theme-design +make menuconfig # choose LUCI->Theme->Luci-theme-design +make V=s +``` + +## 预览(ps: 下面PC端普通字体为苹果浏览器字体,只有移动端是正常显示的) + +
      iOS + + +
      + +
      iPadOS + + +
      + + + + + + + diff --git a/luci-theme-design/htdocs/luci-static/design/css/style copy.css b/luci-theme-design/htdocs/luci-static/design/css/style copy.css new file mode 100644 index 000000000..0d8879cb4 --- /dev/null +++ b/luci-theme-design/htdocs/luci-static/design/css/style copy.css @@ -0,0 +1,3353 @@ +/** + * Design is a clean HTML5 theme for LuCI. It is based on luci-theme-material and luci-theme-neobird + * + * luci-theme-material + * Copyright 2015 Lutty Yang + * + * luci-theme-Neobird + * Copyright 2021 2smile + * + * Licensed to the public under the Apache License 2.0 + */ + + :root { + --bg: #f1f4f5; + --mainbg: #fff; + --bgwhite: #fff; + --activeColor: #5ea69b; + --activeBottom: #51c291 2px solid; + --textColor: rgb(132,119,116); + --borderColor: rgba(0,0,0,.15); + --navbgColor: rgba(255, 255, 255, .7); + --navBorder: 1px solid #f2f2f2; + --sectionbgColor: #fff; + --sectionbgColor2: #fff; + --sectionShaddow: 3px 3px 3px rgba(0,0,0,.05); + --sectionBorder: none; + --sectiontabBorder: none; + --tabmenuBorderLR: none; + --tabmenubgColor: none; + --tabmenuBottom: #e4eaec 1px solid; + --tabmenuRadius: 0; + --sectionnodeBorder: #f7f7f7 1px solid; + --cbilineColor: #f7f7f7 1px solid; + --tabbgColor: #fff; + --inputbgColor: #f8f8f8; + --inputtextColor: #76838f; + --inputBorder: 1px solid #e4eaec; + --mainleftbgColor: rgb(255,255,255); + --bttextColor: #fff; + --badgebgColor: #f7f7f7; + --badgeBorder: #e4eaec 1px solid; + --progressbarColor: #c8c8c8; + --progressbar: #5ea69b; + --progressbartxtColor: #fff; + /* --logo: url('/luci-static/design/images/logo.png'); + --mlogo: url('/luci-static/design/images/mlogo.png'); */ + --logo_color: #222b36; + --alertColor: #000000; + --alertBackground: rgb(230 230 230); + --scrollbarColor:#d0d0d0; +} + +@media (prefers-color-scheme: dark) { + :root { + --bg: #000; + --bgwhite: #000; + --textColor: #fefefe; + --activeColor: #5ea69b; + --activeBottom: #51c291 2px solid; + --borderColor: #2C2C3A; + --navbgColor: hsla(0, 0%, 7%, .8); + --navBorder: 1px solid #1c1c1e; + --sectionbgColor: #1c1c1e; + --sectionbgColor2: #1c1c1e; + --sectionShaddow: 3px 3px 3px rgba(0,0,0,.05); + --sectionBorder: none; + --sectiontabBorder: none; + --sectionnodeBorder: #3d3d41 1px solid; + --cbilineColor: #2d2d2d 1px solid; + --tabbgColor: #1c1c1e; + --tabmenuBorderLR: none; + --tabmenubgColor: none; + --tabmenuBottom: #2d2d2d 1px solid; + --tabmenuRadius: 6px 6px 0 0; + --inputbgColor: #2f2f2f; + --inputtextColor: #fefefe; + --inputBorder: 1px solid #4d4d4d; + --mainleftbgColor: #000; + --bttextColor: #fefefe; + --badgebgColor: #fefefe; + --badgeBorder: #3d3d40 1px solid; + --progressbarColor: #6d6d6d; + --progressbar: #5ea69b; + --progressbartxtColor: #fefefe; + /* --logo: url('/luci-static/design/images/logod.png'); + --mlogo: url('/luci-static/design/images/mlogod.png'); */ + --logo_color: #fefefe; + --alertColor: #ffffff; + --alertBackground: rgb(30 30 30); + --scrollbarColor:#222; + } +} + +@font-face { + font-family: 'icomoon'; + src: url('../fonts/font.eot'); + src: url('../fonts/font.eot') format('embedded-opentype'), + url('../fonts/font.ttf') format('truetype'), + url('../fonts/font.woff') format('woff'), + url('../fonts/font.svg') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'design'; + src: url(''); + src: url('?#iefix') format('embedded-opentype'), + url('../fonts/iconfont-Regular.woff2') format('woff2'), + url('../fonts/iconfont-Regular.woff') format('woff'), + url('../fonts/iconfont-Regular.ttf') format('truetype'), + url('#iconfont') format('svg'); +} + +@font-face{ + font-family: 'Cocon-Regular-Font'; + src : url('../fonts/Cocon-Regular-Font.otf') format('opentype'); +} +div{ + font-family: 'HYk2gj'; +} + +::-webkit-scrollbar { + width: 4px; +} +::-webkit-scrollbar-thumb { + background: var(--scrollbarColor) ; + border-radius: 2px; +} + + +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +html, body { + margin: 0px; + padding: 0px; + height: 100%; + font-family: -apple-system, 'Microsoft Yahei' !important; + font-size: 0.92rem; + line-height: 150%; + background-color: var(--bg); + color:var(--textColor); +} + +body div { + line-height:150%; +} + +a { + color: var(--textColor); + text-decoration: none; +} + +em { + font-style:normal !important; + line-height: 1.5; + padding-left: 10px; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + } + +select { + overflow: hidden !important; + width: 100%; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + padding: 0 25px 0 10px !important; + background-size: 24px 16px; + background-repeat: no-repeat; + background-position: right center; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABGCAYAAAA6hjFpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDcuMS1jMDAwIDc5LmRhYmFjYmIsIDIwMjEvMDQvMTQtMDA6Mzk6NDQgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjhDNzA0QUE0NjE2QTExRUNCMjJFQkQyRkIyNURDNjE3IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjhDNzA0QUEzNjE2QTExRUNCMjJFQkQyRkIyNURDNjE3IiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCAyMi41IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QzNBNTYzNTY2MTUxMTFFQ0IyMkVCRDJGQjI1REM2MTciIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QzNBNTYzNTc2MTUxMTFFQ0IyMkVCRDJGQjI1REM2MTciLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6YjzxlAAACsklEQVR42uyaXUsVURSG51T0U/obfUvhhYF0U0HQhZQVIWVJCAkiSUXfRRcaBFbXQVBBRCASFCJBpQQipw+RREkpCa9aG95gs0DMOp6Z7TwvvAxnzczaa6/nzDnzVTndfSVDxdE6WgAQBBCAIIAABAEEIAggAEEAQQABCAIIQBBAAIIAAhAEEAQQgCCAAAStGSAbzA/N+wvSiwPmB6or16bkoY2afLN5r+q4l2MfDpr7zetV2z7zYpmOkAHByNSE0IxDOdUSxr2rOjLVNVC2n6z77hsYmtFnbqlzHS0aN+7DouorFZBH+ibGUCrmO+YjdaqhVeNVHIxm1Ve6P/XH5ibzLwfllvn4Ko8d8t90MEIde1RXaU97n6oJCw7KNXPbKo3ZpvwxjAXV8YTrkCx7piPFQ7lsbq/xWO3K62E0qQ4uDKXn5kbzTxe/YO6o0Rgdypc5GI0anyt1p5fm3eYfLn7e3PmfuTuVJ1YYZ5fG5Up9CQ2qSfMu3m3u+secXdo/1rzGGeTWyfIaUrPmXPycuWeFuXq0X6w55R8q4NwLe3PxlXmn+buLnzX3/mWOXm0fK+RrUP4MICvTG/MO86yLnzFfWmbfi9ou1qzyvS7wnAt/+31YTZxx8ZPmq+709c/pcoifcvEZ5Rku+HyTeB4yYt5unnbxE+YbEZSwvK54rGntP5LAXJN5QPXWvNX8zcWPmm9rHmF5zK0P22/T/hlAaqv35i3mKRc/bB7VMtaUIL5LaI7JPcIdVZMnXXyT+zyp7T4kNr8kn6mPqdlfllj/VevHEpxbsi85fNTP1ycX/2zerPUZQOqrcUGp6nNVMMYTnlPyrwFNCMILLScSn0++r7zUSFVdZ6wJ8aIcQBBAAIIAAhAEEIAggAAEAQQBBCAIIABBAAEIAghAEEAQQJLQbwEGAK/reX2gh5gQAAAAAElFTkSuQmCC'); +} + +select, +input { + color: var(--inputtextColor); + padding: 5px 10px; + font-size: 0.92rem; + font-family: -apple-system, 'Microsoft Yahei', sans-serif, Helvetica, Arial, sans-serif; + border: var(--inputBorder); + background-color: var(--inputbgColor); + transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + -webkit-transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + outline-style: none; + vertical-align: middle; + border-radius: 8px; + margin: 3px 3px 3px 0; + height: 2.8rem; + line-height: 2.8rem; + max-width: 550px; + +} + +select:not([multiple="multiple"]):focus, +input:focus { + border-color: #948FE1; + box-shadow:0 0 6px #948FE1; + -webkit-box-shadow:0 0 6px #948FE1; + -moz-box-shadow:0 0 6px #948FE1; +} + +input[type='file'] { + border: none; + background: none; + height: auto; + line-height: 1rem; +} + +input[type='checkbox'] { + height: 1.2rem; + width: 1.2rem; + +} +input[type='radio'] { + height: 1.2rem; + width: 1.2rem; +} + +select[multiple="multiple"] { + height: auto; +} + +input[type='text'],input[type='password'] { + width: 100%; +} +code { + color: #0099CC; +} + +/* img[src*="/images/logo.png"] + { + height: 60px; + background-image: var(--logo); + background-size: 220px; + background-repeat: no-repeat; + padding: 0 0 0 250px; + width: 0; + background-position-x: 10px; + background-position-y: 10px; + background-color: var(--mainleftbgColor); +} */ + +abbr { + text-decoration: underline; + cursor: help; +} + +br { + display: block; + margin-bottom: 0.2px; + content: ''; +} + +hr{ + margin: 1rem 0; + border-color: #EEE; + opacity: 0.1; +} + +.cbi-section-table-cell br, #cbi-system br, #cbi-dropbear br, .node-status-routes br { + display: none; +} + +header, .main { + width: 100%; + position: absolute; +} + +header { + background-color: var(--bgwhite); + box-shadow: 17rem 2px 4px rgba(0, 0, 0, 0.08); + transition: box-shadow 0.2s; + height: 55px; + float: left; + position: fixed; + z-index: 101; +} + +footer { + text-align: right; + padding: 1rem; + color: #aaa; + font-size: 11px; + height: 80px; + visibility:hidden; + /*text-shadow: 0px 0px 2px #BBB;*/ +} + +footer > a { + color: rgb(154,37,143); + text-decoration: none; +} + +text, line { + font-family: Verdana !important; +} + +.cbi-button-up, +.cbi-button-down, +.cbi-value-helpicon, +.showSide, +.main > .loading > span { + font-family: 'icomoon' !important; + font-size:10px; + speak: none; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +input.cbi-button.cbi-button-add { + /* margin-left: 10px; */ +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: -apple-system, 'Microsoft Yahei'; + font-weight: 600; + line-height: 1.1; + color: inherit; + clear:both; + text-transform: capitalize; +} + +label.zonebadge{ + border-radius: 5px; + padding: 2px 5px 2px 5px !important; + background-color: #5bdeae !important; + display: inline-block; + cursor: pointer; + color: #fefefe; +} +.zonebadge { + background-color: var(--tabmenubgColor) !important; + border-radius: 6px; + padding: 5px; +} + +.zonebadge em { + padding:3px; +} + +svg { + background-color: var(--sectionbgColor); +} + +/* fix p#aliyundrive-webdav_status b */ + +/* p#aliyundrive-webdav_status b { + color: #ff6666 !important; + text-transform:capitalize; +} */ + +/* fix .cbi-section .cbi-section */ + +.cbi-section .cbi-section { + margin: 10px; +} + +/* fix node-services-vssr */ + +.node-services-vssr .status-bar { + bottom:calc(50px + constant(safe-area-inset-bottom)); + bottom:calc(50px + env(safe-area-inset-bottom)); + /* display: none; */ +} + +.node-services-vssr .ssr-button { + min-width: 30px; +} +.node-services-vssr #cbi-vssr .panel-title { + padding: 10px 0 10px 10px !important; + letter-spacing: 0 !important; +} + +.node-services-vssr .status .block { + border-radius: 10px !important; + box-shadow: none !important; + background-color: var(--sectionbgColor) !important; +} + +.node-services-vssr button { + border-radius: 10px !important; + } + +#cbi-vssr-servers .cbi-section-table-row { + position: relative; + margin: 10px !important; + padding: 8px 15px 8px 70px; + box-shadow: none !important; + border-radius: 10px !important; + border: 0; + color: var(--textColor) !important; + text-align: left; + line-height: 1.7em; + overflow: hidden; + letter-spacing: normal; + background-color: var(--inputbgColor) !important; +} +.cbi-section-table-row.fast { + background-color: #add8e6 !important; +} +.incon .tp { + text-transform: uppercase; + color: var(--bg) !important; +} + +/** img retina **/ + +img[src*="/luci-static/resources/icons/port_up.png"] { + background-image: url(../images/port_up.png); + background-size: 32px 32px; + height: 32px; + padding: 0 0 0 32px; + width: 0; +} + +img[src*="/luci-static/resources/icons/port_down.png"] { + background-image: url(../images/port_down.png); + background-size: 32px 32px; + height: 32px; + padding: 0 0 0 32px; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/ethernet.png"], +#wan6_i img[src*="/luci-static/resources/icons/ethernet.png"], +img[src*="/luci-static/resources/icons/ethernet.png"] { + background-image: url(../images/ethernet.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +#cbi-network-lan-ifname_multi img[src*="/luci-static/resources/icons/ethernet.png"], +#cbi-network-1-_ifname img[src*="/luci-static/resources/icons/ethernet.png"], +.ifacebadge img[src*="/luci-static/resources/icons/ethernet.png"], +li img[src*="/luci-static/resources/icons/ethernet.png"] + { + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/ethernet.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/ethernet_disabled.png"], +#wan6_i img[src*="/luci-static/resources/icons/ethernet_disabled.png"], +img[src*="/luci-static/resources/icons/ethernet_disabled.png"] { + background-image: url(../images/ethernet_disabled.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +#cbi-network-lan-ifname_multi img[src*="/luci-static/resources/icons/ethernet_disabled.png"], +#cbi-network-1-_ifname img[src*="/luci-static/resources/icons/ethernet_disabled.png"], +.ifacebadge img[src*="/luci-static/resources/icons/ethernet_disabled.png"], +li img[src*="/luci-static/resources/icons/ethernet_disabled.png"] +{ + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/ethernet_disabled.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/wifi.png"], +#wan6_i img[src*="/luci-static/resources/icons/wifi.png"], +img[src*="/luci-static/resources/icons/wifi.png"] { + background-image: url(../images/wifi.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +#cbi-network-lan-ifname_multi img[src*="/luci-static/resources/icons/wifi.png"], +#cbi-network-1-_ifname img[src*="/luci-static/resources/icons/wifi.png"], +.ifacebadge img[src*="/luci-static/resources/icons/wifi.png"], +li img[src*="/luci-static/resources/icons/wifi.png"] +{ + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/wifi.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/wifi_disabled.png"], +#wan6_i img[src*="/luci-static/resources/icons/wifi_disabled.png"], +img[src*="/luci-static/resources/icons/wifi_disabled.png"] { + background-image: url(../images/wifi_disabled.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +#cbi-network-lan-ifname_multi img[src*="/luci-static/resources/icons/wifi_disabled.png"], +#cbi-network-1-_ifname img[src*="/luci-static/resources/icons/wifi_disabled.png"], +.ifacebadge img[src*="/luci-static/resources/icons/wifi_disabled.png"], +li img[src*="/luci-static/resources/icons/wifi_disabled.png"] +{ + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/wifi_disabled.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/vlan.png"], +#wan6_i img[src*="/luci-static/resources/icons/vlan.png"], +img[src*="/luci-static/resources/icons/vlan.png"] { + background-image: url(../images/vlan.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +.ifacebadge img[src*="/luci-static/resources/icons/vlan.png"], +li img[src*="/luci-static/resources/icons/vlan.png"] +{ + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/vlan.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/vlan_disabled.png"], +#wan6_i img[src*="/luci-static/resources/icons/vlan_disabled.png"], +img[src*="/luci-static/resources/icons/vlan_disabled.png"] { + background-image: url(../images/vlan_disabled.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +.ifacebadge img[src*="/luci-static/resources/icons/vlan_disabled.png"], +li img[src*="/luci-static/resources/icons/vlan_disabled.png"] +{ + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/vlan_disabled.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/bridge.png"], +#wan6_i img[src*="/luci-static/resources/icons/bridge.png"], +img[src*="/luci-static/resources/icons/bridge.png"] { + background-image: url(../images/bridge.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +.ifacebadge img[src*="/luci-static/resources/icons/bridge.png"], +li img[src*="/luci-static/resources/icons/bridge.png"] { + background-image: url(../images/bridge.png); + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; + width: 0; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/bridge.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/bridge_disabled.png"], +#wan6_i img[src*="/luci-static/resources/icons/bridge_disabled.png"], +img[src*="/luci-static/resources/icons/bridge_disabled.png"] { + background-image: url(../images/bridge_disabled.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +.ifacebadge img[src*="/luci-static/resources/icons/bridge_disabled.png"], +li img[src*="/luci-static/resources/icons/bridge_disabled.png"] { + background-image: url(../images/bridge_disabled.png); + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; + width: 0; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/bridge_disabled.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/tunnel.png"], +#wan6_i img[src*="/luci-static/resources/icons/tunnel.png"], +img[src*="/luci-static/resources/icons/tunnel.png"] { + background-image: url(../images/tunnel.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +.ifacebadge img[src*="/luci-static/resources/icons/tunnel.png"], +li img[src*="/luci-static/resources/icons/tunnel.png"] +{ + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/tunnel.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +#wan4_i img[src*="/luci-static/resources/icons/tunnel_disabled.png"], +#wan6_i img[src*="/luci-static/resources/icons/tunnel_disabled.png"], +img[src*="/luci-static/resources/icons/tunnel_disabled.png"] { + background-image: url(../images/tunnel_disabled.png); + background-size: 32px 32px; + height: 32px; + width: 32px; + padding: 0 0 0 32px; + width: 0; +} +.ifacebadge img[src*="/luci-static/resources/icons/tunnel_disabled.png"], +li img[src*="/luci-static/resources/icons/tunnel_disabled.png"] +{ + background-size: 16px 16px; + height: 16px; + width: 16px; + padding: 0 0 0 16px; +} +#__status-ifc-signal img[src*="/luci-static/resources/icons/tunnel_disabled.png"] +{ + background-size: 32px 32px!important; + height: 32px !important; + width: 32px!important; + padding: 0 0 0 32px!important; + width: 0; +} + +img[src*="/luci-static/resources/icons/wifi_big.png"] { + background-image: url(../images/wifi_big.png); + background-size: 64px 64px; + height: 64px; + padding: 0 0 0 64px; + width: 0; +} + +img[src*="/luci-static/resources/icons/wifi_big_disabled.png"] { + background-image: url(../images/wifi_big_disabled.png); + background-size: 64px 64px; + height: 64px; + padding: 0 0 0 64px; + width: 0; +} + +img[src*="/luci-static/resources/icons/loading.gif"] { + background-image: url(../images/loading.gif); + background-size: 20px 20px; + height: 20px; + width: 20px; + padding: 0 0 0 20px; + width: 0; +} + +.ifacebox-body img { + background-size: 22px 22px; + padding: 0 0 0 22px; + width:22px !important; + height:22px !important; + padding: 0 0 0 22px !important; +} +.ifacebox-head { + background-color: #1096db !important; + border-radius: 4px 4px 0 0; +} + + +img[src*="/luci-static/resources/cbi/add.gif"] { + background-image: url(../images/add.png); + background-size: 20px 20px; + height: 20px; + padding: 0 0 0 20px; + width: 0; + z-index: 2; + +} +img[src*="/luci-static/resources/cbi/remove.gif"] { + background-image: url(../images/remove.png); + background-size: 20px 20px; + height: 20px; + padding: 0 0 0 20px; + width: 0; + z-index: 2; +} + +img[src*="/luci-static/resources/cbi/reload.gif"] { + background-image: url(../images/reload.png); + background-size: 20px 20px; + height: 20px; + padding: 0 0 0 20px; + width: 0; + z-index: 2; +} + +img[src*="/luci-static/resources/icons/signal-75-100.png"] +{ + background-image: url(../images/signal-75-100.png); + image-rendering: pixelated; + background-size: 24px 24px; + height: 24px; + width: 24px; + padding: 0 0 0 24px; + z-index: 2; +} + +img[src*="/luci-static/resources/icons/signal-50-75.png"] +{ + background-image: url(../images/signal-50-75.png); + image-rendering: pixelated; + background-size: 24px 24px; + height: 24px; + width: 24px; + padding: 0 0 0 24px; + z-index: 2; +} + +img[src*="/luci-static/resources/icons/signal-25-50.png"] +{ + background-image: url(../images/signal-25-50.png); + image-rendering: pixelated; + background-size: 24px 24px; + height: 24px; + width: 24px; + padding: 0 0 0 24px; + z-index: 2; +} + +img[src*="/luci-static/resources/icons/signal-0-25.png"] +{ + background-image: url(../images/signal-0-25.png); + image-rendering: pixelated; + background-size: 24px 24px; + height: 24px; + width: 24px; + padding: 0 0 0 24px; + z-index: 2; +} + +img[src*="/luci-static/resources/icons/signal-0.png"] +{ + background-image: url(../images/signal-0.png); + image-rendering: pixelated; + background-size: 24px 24px; + height: 24px; + width: 24px; + padding: 0 0 0 24px; + z-index: 2; +} + +img[src*="/luci-static/resources/icons/signal-none.png"] +{ + background-image: url(../images/signal-none.png); + image-rendering: pixelated; + background-size: 24px 24px; + height: 24px; + width: 24px; + padding: 0 0 0 24px; + z-index: 2; +} + + +.myIcon{ + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + text-transform: none !important; +} + +.myIcon-logout:after{ + content: "\e005"; +} + +.myIcon-reboot:after{ + content: "\e02a"; +} + +.myIcon-wifi:after{ + content: "\e00c"; +} + +.main { + top: 50px; + bottom: 0rem; + position: relative; + height: 100%; + height: calc(100% - 4rem); +} + +.main > .loading { + position: fixed; + width: 100%; + height: 100%; + z-index: 1000; + display: block; + background-color: rgb(240, 240, 240); + top: 0; +} + +.main > .loading > span { + display: block; + text-align: center; + margin-top: 2rem; + color: #888; + font-size: 1rem; +} + +.main > .loading > span > .loading-img:before { + content: "\e603"; +} + +.main > .loading > span > .loading-img { + animation: anim-rotate 2s infinite linear; + margin-right: 0.2rem; + display: inline-block; +} + +.navbar { + overflow: hidden; + position: fixed; + bottom: 0; + width: 100%; + border-top: var(--navBorder); + text-align: center; + height:calc(50px + constant(safe-area-inset-bottom)); + height:calc(50px + env(safe-area-inset-bottom)); + background-color: var(--navbgColor); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); +} + +.navbar a { + float: left; + text-align: center; + padding: 8px 0; + width: 20%; + text-decoration: none; + max-width: 100px; +} + +.cbi-map { + margin-top: 10px; +} + +#cbi-shadowsocksr .cbi-map-descr { + display: none; +} + +.navbar a img { + width: 28px; +} + +@keyframes anim-rotate { + 0% { + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + } + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg) + } +} + + +.main-left { + float: left; + width: 17rem; + background-color: var(--mainleftbgColor); + overflow-x: auto; + height: calc(100% - 3.5rem); + position: fixed; + padding-top: 15px; + box-shadow: 0 0px 4px rgb(0 0 0 / 8%); +} + +.main-right { + width: 85%; + width: calc(100% - 17rem); + float: right; + height: 100%; + border-left: var(--sectionBorder); +} + +.main-right > #maincontent { +} + +.pull-right { + position: absolute; + top: -2px; + right: 30px; + cursor: pointer; +} + +.pull-left { + float: left; +} + + +header > .container { +margin:0; +padding:0; +} + +header > .container > .brand { + font-size: 25px; + font-family: "Cocon-Regular-Font"; + /*font-weight:bold;*/ + line-height:60px; + /*color: white;*/ + color: var(--logo_color); + cursor: default; + /*background: #51c291;*/ + display:block; + width:17rem; + /* padding-left: 30px; */ + height:60px; + text-align:center; + float:left; + font-weight:900; + letter-spacing:1px; +} +header > .container > a[class="brand"]:after { + content:""; + font-size:14px; + font-family:Tahoma; + position: absolute; + top:-10px; + font-weight:normal !important; +} + +header > .container > .brand-hostname { + font-size: 14px; + line-height:60px; + color: #555555; + cursor: default; + display:block; + width:17rem; + padding-right: 10px; + height:60px; + text-align:left; + float:left; + margin-top: 7px; + font-weight:300; + margin-left: -15px; +} + +.warning { + background-color: #FF7D60 !important; + color: #FFF; +} + +.errorbox, +.alert-message { + font-weight: bold; + margin-bottom: 1em; + padding: 1rem; + border: 0; + border-radius: 3px !important; + color: var(--alertColor); + background-color: #5c5c5c; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + text-shadow: 1px 1px rgba(0, 0, 0, .1); + background-color: var(--alertBackground); +} + +.errorbox { + color: #fff; + background-color: #ff6767; + border-radius: 10px; +} + +.error { + color: red; +} +p#shadowsocksr_status { + padding: 3px; +} + + +#maincontent > .container > div:nth-child(1).alert-message.warning > a { + font: inherit; + overflow: visible; + text-transform: none; + display: inline-block; + margin-bottom: 0; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + min-width: 6rem; + padding: 0.5rem 1rem; + font-size: 14px; + line-height: 1.42857143; + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; + margin-top: 2rem; + text-decoration: inherit; +} + +.main > .main-left > .nav { + overflow-y: visible !important; + font-size: 1rem; + width: 90%; + margin: auto; + margin-bottom: 90px; +} + +.main > .main-left > .nav > li a { + color: var(--activeColor); + display: block; + border-radius: 6px; + cursor: pointer; + font-weight: bold; + font-size: 1.1rem; + transition: all 0.2s; +} + +/* +.main > .main-left > .nav > li:nth-last-child(1) { + font-size: 11pt; + height:40px; + padding-top:6px; +} +*/ + +.main > .main-left > .nav > li { + cursor: pointer; + padding-top:6px; +} + + + +.main > .main-left > .nav > .slide { + padding: 0; + padding-top:8px; +} + +.main > .main-left > .nav > .slide > a:before { + display: inline-block; + left:-10px; + top: 1px; + position: relative; + font-family: "design" !important; + font-weight: bold !important; + text-transform: none !important; + speak: none; + font-size: 1.2rem !important; + -webkit-font-smoothing: antialiased; +} + +.main .main-left .nav li.slide .menu.active::after { + transform: rotate(90deg); +} + +.main > .main-left > .nav > .slide > a[data-title="Status"]:before { + content: "\e6b8"; +} + +.main > .main-left > .nav > .slide > a[data-title="Status"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a[data-title="System"]:before { + content: "\e645"; +} + +.main > .main-left > .nav > .slide > a[data-title="System"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a[data-title="Services"]:before { + content: "\e6cb"; +} + +.main > .main-left > .nav > .slide > a[data-title="Services"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a[data-title="Docker"]:before { + content: "\44"; +} + +.main > .main-left > .nav > .slide > a[data-title="Docker"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a[data-title="NAS"]:before { + content: "\eb04"; +} + +.main > .main-left > .nav > .slide > a[data-title="NAS"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a[data-title="VPN"]:before { + content: "\56"; +} + +.main > .main-left > .nav > .slide > a[data-title="VPN"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a[data-title="Network"]:before { + content: "\72"; +} + +.main > .main-left > .nav > .slide > a[data-title="Network"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a[data-title="Bandwidth Monitor"]:before { + content: "\e764"; +} + +.main > .main-left > .nav > .slide > a[data-title="Bandwidth Monitor"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main .main-left .nav li.slide .menu[data-title="Statistics"]:before { + content: "\e604"; +} + +.main > .main-left > .nav > .slide > a[data-title="Statistics"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main .main-left .nav li.slide .menu[data-title="Control"]:before { + content: "\e67a"; +} + +.main > .main-left > .nav > .slide > a[data-title="Control"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main .main-left .nav li.slide .menu[data-title="Asterisk"]:before { + content: "\e7dd"; +} + +.main > .main-left > .nav > .slide > a[data-title="Asterisk"]:after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > li > a[data-title="Inital Setup"]:before { + content: "\e67e"; +} + +.main > .main-left > .nav > li > a[href="/cgi-bin/luci//admin/wizard"]:before { + content: "\e67e"; +} + +.main > .main-left > .nav > li > a[data-title="iStore"]:before { + content: "\e676"; +} + + +.main > .main-left > .nav > li > a[data-title="Logout"] { + padding: 0.675rem 0 0.675rem 2.5rem; +} + +.main > .main-left > .nav > li > a[data-title="Logout"]:before { + content: "\e641"; +} + +.main > .main-left > .nav > li > a[data-title="Reboot"] { + padding: 6px 25px; +} +.main > .main-left > .nav > li > a[data-title="Reboot"]:before { + content: "\e004"; +} + +.main > .main-left > .nav > .slide > ul { + display: none; + list-style:dotted; +} + +.main > .main-left > .nav > .slide > .menu { + display: block; + padding: 0.675rem 0 0.675rem 2.5rem; + text-decoration: none; + cursor: pointer;; +} + +.main > .main-left > .nav > .slide > .menu2 { + display: block; + padding: 0.675rem 0 0.675rem 2.5rem; + text-decoration: none; + cursor: pointer;; +} +.main > .main-left > .nav > li:hover, +.main > .main-left > .nav > .slide > .menu:hover { + background: var(--activeColor); + color:white; +} +.main > .main-left > .nav > .slide > .menu2:hover { + background: var(--activeColor); + color:white; +} + +.main > .main-left > .nav > .slide:hover { + background: none; +} +.slide-menu { + overflow:hidden; + } +.main > .main-left > .nav > .slide > .slide-menu > li { + margin-top: 8px; + border-radius: 6px; +} + + + +.main > .main-left > .nav > .slide > .slide-menu > .active { + background-color: var(--activeColor); +} + +.main > .main-left > .nav > .slide > .slide-menu > li > a { + position: relative; + display: block; + color: var(--textColor); + vertical-align: middle; + background:none !important; + border: none !important; + text-transform: capitalize; + font-size: 1rem; + margin: 0.1rem 0.5rem 0.1rem 0.5rem; + padding: 0.675rem 0 0.675rem 2.5rem; +} +.main .main-left .nav li.slide .slide-menu .active a { + color: #000; + z} + +.main > .main-left > .nav > .slide > .slide-menu > li > a:hover { + color:white; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active > a { + color: white; +} + +.main > .main-left > .nav > .slide > .slide-menu > li:hover { + background: var(--activeColor); + color:white !important; + transition: all 0.2s; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active:hover { + background-color: var(--activeColor); + cursor: pointer; +} + +.cbi-tab-descr { + padding:10px; +} + +li { + list-style-type: none; +} + +#maincontent > .container { + margin:30px 30px 50px 30px; +} + +h1 { + color: var(--activeColor); + font-size: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +h2 { + color: var(--activeColor); + padding: 0 12px 6px 12px; + text-transform: capitalize; +} + +h3 { + font-size: 1.2rem; + color: var(--activeColor); + font-weight:bold; + padding: 0 12px 10px 12px; +} + +h4 { + +} + +label { + display: inline-block; + vertical-align: middle; +} +div.cbi-section, +.node-admin-status-routes #view { + /* margin: 10px 0 0 0; */ + padding: 10px; + border: 1px; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + text-align: left; + min-width: inherit; + overflow-x: auto; + overflow-y: hidden; + background-color: var(--sectionbgColor); + /* box-shadow: var(--sectionShaddow); */ + -webkit-overflow-scrolling: touch; +} + +div.cbi-section > legend { + display: none !important; +} + +div.cbi-section > div.cbi-section { + /* margin: 0; */ + padding: 0; + /* border: none; */ + /* box-shadow: none; */ +} + +.panel-title { + width: 100%; + display: block; + padding: 10px; + font-weight: bold; + font-size: 1rem; +} + +table { + border-spacing: 0; + border-collapse: collapse; + width: 100%; + border: 0px solid #eee; +} + +table tr th:empty { + display: none; +} +strong { + font-weight: bold; + padding: 2px; +} + +#lb_load01_cur, +#lb_load01_peak, +#lb_load05_cur, +#lb_load15_cur{ + text-align:right !important; +} + +#lb_load01_peak { + text-align:left !important; + } +#lb_load01_cur { + +} + +table > tbody > tr > td, table > tbody > tr > th, table > tfoot > tr > td, table > tfoot > tr > th, table > thead > tr > td, table > thead > tr > th { + padding: 12px; + white-space: nowrap; + line-height:1.5; + vertical-align: middle !important; +} + +table > tbody > tr { + border-bottom: var(--cbilineColor) !important; +} + +table > tbody > tr:last-child { + border-bottom: none !important; +} + +.cbi-section-table-cell { + text-align: center; +} + +.cbi-section-table-row { + text-align: center; +} + +.cbi-section-remove{ + margin-bottom: 2px; +} +.cbi-section-remove > input { + background-color: #cc0066; +} +div.cbi-section > table > tbody > tr:nth-of-type(odd) { + background-color: var(--sectionbgColor2); +} + +/* fix progress bar */ +#swaptotal > div, +#swapfree > div, +#swapcache > div, +#memfree > div, +#membuff > div, +#conns > div, +#memcache > div, +#memtotal > div { + width: 100% !important; + border-color: var(--progressbarColor) !important; + background-color:var(--progressbarColor) !important; +} + +#swaptotal > div > div, +#swapfree > div > div, +#swapcache > div > div, +#memfree > div > div, +#membuff > div > div, +#conns > div > div, +#memcache > div > div, +#memtotal > div > div { + background-color: var(--progressbar) !important; + color: var(--progressbartxtColor) !important; +} + +#swaptotal div div, +#swapfree div div, +#swapcache div div, +#memfree div div, +#membuff div div, +#conns div div, +#memcache div div, +#memtotal div div { + align-items: center; + align-content: center; + justify-content: center; + display: flex; +} + +#swaptotal div div small, +#swapfree div div small, +#swapcache div div small, +#memfree div div small, +#membuff div div small, +#conns div div small, +#memcache div div small, +#memtotal div div small{ + font-size: 0.75rem !important; + line-height: 130%; + color: var(--progressbartxtColor) !important; +} + +.cbi-value-field { + width: 65%; +} +/* fix node-system-admin */ +.node-system-admin .cbi-value-field li div { + padding: 0 !important; +} + +.node-system-admin em { + padding: 0 !important; +} + +/* fix node-nlbw-display */ +.node-nlbw-display hr { + display: none; +} + +.node-nlbw-display p { + line-height: 1.5; + padding: 0 10px 5px 10px; +} + + +/* fix node-network-network */ + +/* #cbi-network-lan-__status table { + width: auto; +} + +#cbi-network-lan-__status table td { + width: 0; + padding: 0; + +} +#cbi-network-lan-__status table td small { + font-size: 11px; + white-space: nowrap; +} */ + +div [id*="cbi-network-"] [id*="-__status"] table { + width: auto; +} + +div [id*="cbi-network-"] [id*="-__status"] table td { + width: 0; + padding: 0; + +} +div [id*="cbi-network-"] [id*="-__status"] table td small { + width: auto; +} + +div [id*="cbi-wireless"] [id*="-__status"] table { + width: auto; +} + +div [id*="cbi-wireless"] [id*="-__status"] table td { + width: 0; + padding: 0; + +} +div [id*="cbi-wireless"] [id*="-__status"] table td small { + width: auto; +} + +/* fix node-status-routes */ + +.node-status-routes .cbi-section-node{ + max-height: 500px; + overflow-y: auto; + overflow-x: hidden; +} + +/* fix multiple table */ + +table table { + border: none; +} + +.cbi-value-field table { + border: none; +} +.cbi-value-field label { + padding: 0 ; +} +td > table > tbody > tr > td { + border: none; +} + +.cbi-value-field > table > tbody > tr > td { + border: none; +} + +div#container\.nlbw\.traffic { + /* overflow: auto; */ +} +div#container\.nlbw\.traffic #host-data { + display: block; + overflow: auto; +} + +td#__status-ifc-signal { + width: 60px !important; +} + +/* button style */ + +.cbi-button { + -webkit-appearance: none; + text-transform: uppercase; + color: #fff; + background-color: #337ab7; + transition: all 0.2s ease-in-out; + display: inline-block; + border: none; + cursor: pointer; + -ms-touch-action: manipulation; + touch-action: manipulation; + background-image: none; + text-align: center; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + width: auto !important; + min-width: 80px; + padding: 0px 8px 0px 8px; + max-width: 160px; + height: 35px; + line-height: 35px; +} + +.cbi-button:hover, +.cbi-button:focus, +.cbi-button:active { + color: #fff; + outline: 0; + text-decoration: none; + background-color: rgb(106,101,214); +} + +.cbi-button:hover, +.cbi-button:focus { + box-shadow: 0 1px 1px rgba(0,0,0,.05); +} + +.cbi-button:active { + box-shadow: 0 1px 1px rgba(0,0,0,.05); +} + +.cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: 0.60; + box-shadow: none; +} + +form.inline + form.inline, +.cbi-button + .cbi-button { +} + +.cbi-button-reset, +.cbi-input-remove { + color: #fff !important; + background-color: #617486 !important; +} + +.cbi-button-reset:hover, +.cbi-input-remove:hover, +.cbi-button-remove:hover{ + color: #fff !important; + background-color: rgb(83,100,115) !important; +} + +.cbi-button-link, +.cbi-input-find, +.cbi-input-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-find, +.cbi-input-reload, +.cbi-button-reload { + color: var(--bttextColor); + background-color: rgb(0,171,232) !important; + border-color: rgb(0,171,232) !important; +} + +.cbi-button-link:hover, +.cbi-input-find:hover, +.cbi-input-save:hover, +.cbi-button-add:hover, +.cbi-button-save:hover, +.cbi-button-find:hover, +.cbi-input-reload:hover, +.cbi-button-reload:hover{ + color: #fff !important; + background-color: #337ab7 !important; + border-color: #337ab7 !important; +} + +.cbi-input-apply, +.cbi-button-apply, +.cbi-button-edit { + color: #fff !important; + background-color: var(--activeColor); +} + +.cbi-input-reset, +.cbi-button-remove { + color: #fff !important; + background: #617486; +} + + +.a-to-btn { + text-decoration: none; +} + +/* table */ + +.tabs { + margin: 15px 0; + overflow-x: auto; +} + +.cbi-tabmenu > li, +.tabs > li { + display: table-cell; +} + +.cbi-tabmenu > li { + border-radius: var(--tabmenuRadius); +} + +.tabs > li > a { + text-decoration: none; + padding: 0 6px 0 6px; + float: left; + display: block; + white-space: nowrap; + height: 2.5rem; + line-height: 2.5rem; + font-size: 0.92rem; +} + +.cbi-tabmenu > li > a { + text-decoration: none; + float: left; + display: block; + white-space: nowrap; + height: 2.5rem; + line-height: 2.5rem; + font-size: 0.92rem; + margin: 0 10px; +} + +.tabs > li[class~="active"], +.tabs > li:hover{ + cursor: pointer; + +} + +.tabs > li[class~="active"] > a { + color: var(--activeColor) !important; + padding-bottom: 8px; + border-bottom: var(--activeColor) 2px solid; +} + +.tabs > li:hover { + /*border-bottom: 0.18751rem solid rgb(133,129,216);*/ +} + +.cbi-tabmenu { + border-top: var(--sectiontabBorder); + border-left: var(--tabmenuBorderLR); + border-right: var(--tabmenuBorderLR); + border-bottom: var(--tabmenuBottom); + background-color: var(--tabmenubgColor); + width: 100%; + overflow-x: auto; + margin-top: 5px; + margin-bottom: 10px; +} + +.cbi-tabmenu > li:hover { + background-color: none; +} + +.cbi-tabmenu > li[class~="cbi-tab"] { + background-color: none; +} + +.cbi-tabmenu > li[class~="cbi-tab"] a { + color: var(--activeColor) ; + border-bottom: 2px solid var(--activeColor); +} + +.cbi-section-node-tabbed { + margin-top: 0; + border-bottom: var(--sectiontabBorder); + border-left: var(--sectiontabBorder); + border-right: var(--sectiontabBorder); + border-radius: 0 0; +} + + +.cbi-tabcontainer { + clear:both; +} +.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor2); +} + +.cbi-section-node > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor2); +} +div > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor2); +} + +.cbi-value-field, +.cbi-value-description { + display: table-cell; +} + +.cbi-value-field { + /* padding: 10px 10px 10px 0; */ +} + +.cbi-value-helpicon > img { + display: none; +} + +.cbi-value-helpicon:before { + content: "\f059"; +} + +.cbi-value-description { + opacity: 0.6; + padding-left: 4px; +} + +.cbi-value-title { + word-wrap: break-word; + display: table-cell; + width: 35%; + float: left; + padding: 13px 10px 5px 3px; +} + +.cbi-value { + display: flex; + width: 100%; + align-items: center; + align-content: center; + justify-content: flex-start; + min-height: 40px; + padding: 8px 10px; + flex-flow:row wrap; + border-bottom: var(--cbilineColor); +} + +.cbi-value:last-child { + border-bottom: none; +} + +.cbi-value strong { + font-weight: normal; +} + +.cbi-section-table-descr > .cbi-section-table-cell, +.cbi-section-table-titles > .cbi-section-table-cell { + border: none; +} + +.cbi-rowstyle-2 { + background-color: var(--sectionbgColor2); +} + +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down{ +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; +} +.cbi-section-table tr .cbi-value-field { + text-align: center ; + width: 20% !important; + padding: 10px !important; +} +.cbi-section-table tr .cbi-value-field input { + width: auto; +} +.cbi-section-table tr .cbi-value-field .ifacebox { + margin: auto; + width: fit-content; + min-width: 60px; +} + +/* desc */ +.cbi-section-descr { + padding: 3px 10px; +} + +.cbi-map-descr { + padding: 5px 5px 5px 12px; +} + +.cbi-map-descr h3 { + font-size: 0.92rem; + font-weight: normal; + color: #666; +} + +#cbi-vsftpd .cbi-map-descr { + color: var(--activeColor); + padding: 0 12px 0px 12px; + font-size: 1.2rem; + font-weight: bold; +} + + +/* luci */ + +.hidden { + display: none +} + +.left { + text-align: left !important; +} + +.right { + text-align: right !important; +} + +.right .cbi-button { + height: 20px; + line-height: 20px; + min-width: 60px; + padding: 0; + margin: 0; +} + +.inline { + display: inline; +} + +.cbi-page-actions { + text-align: center; +} + +/* input */ +.cbi-value input[type="password"], +.cbi-value input[type="text"] { + +} + +/* select */ + + +.ifacebadge { + display: inline-flex; + padding: 5px; + background-color: var(--badgebgColor); + align-content: center; + align-items: center; + border-radius: 5px; + border: var(--badgeBorder); + color: rgb(132,119,116); +} + +#content_syslog { + padding: 5px; + margin-top:10px; + border-radius: 10px; + background-color: var(--sectionbgColor); + box-shadow: 3px 3px 3px rgb(0 0 0 / 5%); +} + +.ifacebadge > img { + float: right; + margin-left: 0.3rem; +} + +img.cbi-image-button { + vertical-align: middle; + +} + +div.cbi-section{ + border: var(--sectionBorder); + margin-bottom: 20px; + border-radius: 10px; + margin-top: 5px; +} + +/*textarea*/ + +.cbi-input-textarea, textarea { + color: var(--inputtextColor); + padding: 10px; + line-height: normal; + border: var(--sectionBorder); + background-color: var(--inputbgColor); + transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + -webkit-transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + outline-style: none; + vertical-align: baseline; + border-radius: 10px; + font-family: Menlo, Mono; + font-size: 0.9rem; + white-space: pre; + margin-bottom: 5px; +} + +#syslog { + width: 100%; + min-height: 15rem; + padding: 10px; + margin-bottom: 20px; + border-radius: 0; + background-color: var(--sectionbgColor); + border: none; +} + +/* change */ +#wan4_i, #wan6_i { +width:50px !important; +} + +.uci-change-list { + font-family: monospace; +} + +.uci-change-list ins, +.uci-change-legend-label ins { + text-decoration: none; + border: 1px solid #00FF00; + background-color: #CCFFCC; + display: block; + padding: 2px; + color: black; + /* border-radius: 5px; */ + overflow-x: auto; +} + +.uci-change-list del, +.uci-change-legend-label del { + text-decoration: none; + border: 1px solid #FF0000; + background-color: #FFCCCC; + display: block; + font-style: normal; + padding: 2px; + color:black; + /* border-radius: 5px; */ + overflow-x: auto; +} + +.uci-change-list var, +.uci-change-legend-label var { + text-decoration: none; + border: 1px solid #CCCCCC; + background-color: #EEEEEE; + display: block; + font-style: normal; + padding: 2px; + color:black; + /* border-radius: 5px; */ + overflow-x: auto; +} + +.uci-change-list var ins, +.uci-change-list var del { + border: none; + white-space: pre; + font-style: normal; + padding: 0px; + color:black; + /* border-radius: 5px; */ + overflow-x: auto; +} + +.uci-change-legend { + padding: 5px; +} + +.uci-change-legend-label { + width: 150px; + float: left; + display: flex; + /* align-content: center; */ + align-items: center; +} + +.uci-change-legend-label > ins, +.uci-change-legend-label > del, +.uci-change-legend-label > var { + float: left; + margin-right: 4px; + width: 10px; + height: 10px; + display: block; +} + +.uci-change-legend-label var ins, +.uci-change-legend-label var del { + border: none; + height: 10px; + width: 10px; +} + +.uci-change-list var, +.uci-change-list del, +.uci-change-list ins { + padding: 0.5rem; +} + +/* other fix */ +#iwsvg, +#iwsvg2, +#bwsvg { + border: var(--sectionBorder) !important; + font-family: -apple-system; + background: none !important; +} + +.ifacebox { + border: #1096db 1px solid; + border-radius: 5px; + font-size:0.92rem; + font-weight:normal; +} +.ifacebox-head { + color:#fff; +} +.ifacebox-body small { + font-size:0.8rem !important; + padding: 5px +} + +.ifacebox-body strong { + color:#f7f7f7; + font-size: 0px !important; +} + +.cbi-image-button { + +} + + +.zonebadge > .ifacebadge { + padding: 3px 5px; + margin: 5px; +} + +.zonebadge > input[type="text"] { + padding: 0.16rem 1rem; + min-width: 10rem; + margin-top: 0.3rem; +} + +.cbi-value-field .cbi-input-checkbox, +.cbi-value-field .cbi-input-radio { + vertical-align: middle; +} + +.cbi-section-table-row > .cbi-value-field .cbi-input-select { + min-width: 7rem; +} + +.cbi-section-create { + padding: 0 10px; +} +.cbi-section-create > .cbi-button-add { + margin: 10px 0 10px 0 +} + +div.cbi-value var, td.cbi-value-field var { + font-style: italic; + color: #0069D6; +} + +small { + font-size: small; + font-weight: normal !important; + white-space: normal; +} + +.cbi-button-up, +.cbi-button-down { + display: inline-block; + min-width: 0; + font-size: 0.9rem; +} + +.cbi-optionals { + padding: 1rem 1rem 0 1rem; + border-top: 1px solid #CCC; +} + +#diag-rc-output > pre { + display: block; + padding: 10px; + line-height: 1.5rem; + -moz-border-radius: 3px; + white-space: pre-wrap; + word-wrap: break-word; + color: #76838f; +} + +input[name="ping"], +input[name="traceroute"], +input[name="nslookup"] { + width: 80%; +} + +table.cbi-section-table select { + width: auto !important; +} + +header > .container > .pull-right > * { + +} + +#xhr_poll_status > .label.success { + padding: 10px 10px; + border-radius: 20px; +} + +#xhr_poll_status_off { + padding: 10px 10px; + border-radius: 20px; +} + +.label { + padding: 0 3px 0 3px; + white-space: nowrap; + border-radius: 3px; + position: absolute; + right: 5px; + top: 15px; + line-height: 150%; +} + +.notice { + background-color: var(--activeColor); + color: #fff; + font-size: 0.8rem; + padding: 3px 10px; + border-radius: 20px; + z-index: 10; + top: 22px; +} + +#refresh_on, #refresh_off { + font-size: 1.5rem; + font-family: design; +} + +#refresh_on { + color: var(--activeColor); +} +#refresh_off { + color: var(--progressbarColor); +} + +.darkMask { + width: 100%; + height: 100%; + position: fixed; + background-color: rgba(0, 0, 0, 0.56); + content: ""; + z-index: 99; + display: none; +} + +/* fix Main Login*/ + +.node-main-login { + text-align: center; + background-color: var(--bgwhite) !important; +} +.node-main-login .cbi-section-node > .cbi-value:nth-of-type(2n) { + background: none; +} +.node-main-login h2 { + font-size: 1.5rem; +} + +.node-main-login header { + display: none; +} +.node-main-login > .main > .main-left { + display: none; +} + +.node-main-login > .main > .main-right { + width: 100%; +} + +.node-main-login > .main div.cbi-section { + padding: 0px !important; + margin-bottom: 1rem; + display: inline; + background: none; + border: none; + box-shadow: none; + overflow: hidden; +} + +.node-main-login > .main label.cbi-value-title { + display: none !important; +} + +.node-main-login > .main .cbi-section { + margin-top: 10px !important; +} + +.node-main-login > .main .cbi-map { +} + +.node-main-login > .main div.cbi-section .cbi-value { +} + +.node-main-login > .main div.cbi-section .cbi-value-title { + padding: 10px 0 10px 5px !important; +} + +.node-main-login > .main .cbi-value { + border: none; +} + +.node-main-login > .main .cbi-value-title { + width: 7rem; +} + +.node-main-login > .main #maincontent { + display: flex; + height: 100%; + text-align: center; + align-items: center; + align-content: center; + justify-content: center; +} + +/* .node-main-login > .main .container { + background-image: var(--logo); + background-repeat: no-repeat; + background-size: 300px auto; + width: 300px; + padding: 80px 0 0 0; +} */ + +.node-main-login > .main form > div:nth-last-child(1) { +} + + +.node-main-login > .main .cbi-value > * { + display: inline-block !important; +} + +/* .node-main-login > .main .cbi-input-user, +.node-main-login > .main .cbi-input-password { + min-width: 15rem; +} */ + +.node-main-login > .main .cbi-input-text { + min-width: 15rem; +} + +.node-main-login footer { + bottom: 0; + position: absolute; + width: 100%; +} + +/* fix node-services-shadowsocksr */ + +.node-services-shadowsocksr .cbi-input-textarea, +.node-nlbw-config .cbi-input-textarea { + /* margin: 10px; */ +} + +.node-services-shadowsocksr #cbi-logview .cbi-section { + padding: 0; +} + +/* fix node-network-diagnostics */ +.node-network-diagnostics .cbi-section { + border-radius: 10px; +} + + +/* fix status overview */ + +.node-status-overview > .main div.cbi-section:nth-child(4) td:nth-child(2) { + white-space: normal; +} + +/* fix status processes */ + +.node-status-processes > .main table tr td:nth-child(3) { + white-space: normal; +} + +.cbi-map div.cbi-section h3 { + } + +.cbi-map div.cbi-section ul li { + margin-right:0 !important; +} +/* fix system reboot */ + +.node-system-reboot > .main > .main-right p, +.node-system-reboot > .main > .main-right h3 { + margin-left: 12px; +} + +.node-system-reboot #maincontent { +} + +/* fix Services Network Shares*/ +.node-services-samba > .main .cbi-tabcontainer:nth-child(3) .cbi-value-title { + margin-bottom: 1rem; +} + +.node-services-samba > .main .cbi-tabcontainer:nth-child(3) .cbi-value-field { + display: list-item; +} + +.node-services-samba > .main .cbi-tabcontainer:nth-child(3) .cbi-value-description { + padding-top: 1rem; + line-height:150%; +} + +/* fix System Software*/ +.node-system-packages > .main table tr td:nth-child(1) { + width: auto !important; +} + +.node-system-packages .cbi-section-node .cbi-value-last { + /* padding: 8px 12px; */ +} + +.node-system-packages .cbi-section-node .cbi-value-last > div { + border: none !important; +} + + + +.node-system-packages .cbi-section-node .cbi-value-last > div > div { + border: none !important; +} + +.node-system-packages .cbi-section-node .cbi-value-last:nth-last-child(1) { + padding: auto; +} + +.node-system-packages > .main table tr td:nth-last-child(1) { + white-space: normal; + font-size: small; + color: #76838f; +} + +.node-system-packages > .main .cbi-value > pre { + /* background-color: var(--inputbgColor); */ + padding: 10px; + overflow: auto; + /* border: var(--inputBorder); */ + border-radius: 10px; +} + +.node-system-packages #cbi-distfeedconf .cbi-section, +.node-system-packages #cbi-customfeedconf .cbi-section { + border-radius: 10px; +} + +.node-system-packages .cbi-value-field { + width: 58%; +} + +#container\.nlbw\.traffic, #container\.nlbw\.layer7, #container\.nlbw\.ipv6, #container\.nlbw\.export { + margin-top: 0; + margin-top: 0; + padding: 10px; + text-align: center; + border-bottom: var(--sectionBorder); + border-left: var(--sectionBorder); + border-right: var(--sectionBorder); + background-color: var(--sectionbgColor); + border-radius: 10px; +} + +#container\.nlbw\.export ul li { + + padding: 5px; + width: 150px; + margin: 10px; + border-radius: 5px; + border: #ccc 1px solid; + +} + +#container\.nlbw\.traffic table, +#container\.nlbw\.layer7 table, +#container\.nlbw\.ipv6 table, +#container\.nlbw\.export table { + border: #ccc 1px solid; +} + +#container\.nlbw\.traffic th, +#container\.nlbw\.traffic td, +#container\.nlbw\.layer7 th, +#container\.nlbw\.layer7 td, +#container\.nlbw\.ipv6 th, +#container\.nlbw\.ipv6 td, +#container\.nlbw\.export th, +#container\.nlbw\.export td { + padding: 3px; + border-top: none; + border-left: #ccc 1px solid; + border-right: #ccc 1px solid; + border-bottom: #ccc 1px solid; + } + +.cbi-tabmenu + .cbi-section ul { + text-align: left; +} + +/* fix network firewall*/ +.node-network-firewall > .main .cbi-section-table-row > .cbi-value-field .cbi-input-select { + min-width: 4rem; +} + +.node-status-iptables > .main div > .cbi-map > form { + position: static !important; + margin: 10px 0 20px 0; + padding: 12px; + border: 0; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + min-width: inherit; + overflow-x: auto; + overflow-y: hidden; + box-shadow: 3px 3px 3px rgb(0 0 0 / 5%); + border-radius: 10px; + background-color: var(--bgwhite); + -webkit-overflow-scrolling: touch; +} + + + +/** fix system packages +.node-system-packages .cbi-section { + border-radius: 0 0 10px 10px; +} + + +#cbi-ipkgconf .cbi-section { + border-radius: 0 0 10px 10px; +} + +**/ + + +.node-system-flashops div.cbi-section div.cbi-section { + border: none; +} +.node-system-flashops br { + display: none; +} + +.node-system-flashops .cbi-section { + padding: 0; +} +.node-system-flashops .cbi-section-descr { + padding: 12px; + line-height: 1.5; + border-radius: 6px; + /* border: var(--sectiontabBorder); + background-color: var(--sectionbgColor2); */ +} + + +.node-status-iptables .cbi-tabmenu, +.node-system-packages .cbi-tabmenu, +.node-system-flashops .cbi-tabmenu { + /* border: none; **/ +} + +#cbi-firewall-redirect table *, +#cbi-network-switch_vlan table *, +#cbi-firewall-zone table *{ + font-size: small; +} + +#cbi-firewall-redirect table input[type="text"], +#cbi-network-switch_vlan table input[type="text"], +#cbi-firewall-zone table input[type="text"]{ + width: 5rem; +} + +#cbi-firewall-redirect table select, +#cbi-network-switch_vlan table select, +#cbi-firewall-zone table select{ + min-width: 3.5rem; +} + +/** fix node-status-realtime **/ + +.node-status-realtime table > tbody > tr > td { + text-align: left !important; + padding: 10px 3px 10px 3px; +} + +.node-status-realtime table { + table-layout: auto !important; +} + + +select#cbi\.combobox\.cbid\.shadowsocksr\.cfg013fd6\.tunnel_forward { + overflow: hidden; + +} + +/* language fix */ +body.lang_pl.node-main-login .cbi-value-title { + width: 12rem; +} + +/* fix nlbw component */ +#detail-bubble { + /* left: unset !important; */ + width: unset!important; +} +#detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: 19rem !important; + width: calc(100vw - 21.25rem)!important; +} +#detail-bubble .head { + display: block; + overflow: auto; +} +#detail-bubble #bubble-table { + display: inline-table; + overflow: auto; +} + +@media screen and (max-width: 1280px) { + header { + /*height: 3.5rem;*/ + } + + header > .container { + /*margin-top: 0.25rem;*/ + } + + .main { + height: calc(100% - 3.5rem); + } + + .main-left { + width: calc(0% + 17rem); + top: 50px; + } + + .main-right { + width: calc(100% - 17rem); + } + + + table { + font-size: 0.9rem !important; + width: 100% !important; + } + + .main > .main-left > .nav > li, + .main > .main-left > .nav > li a, + .main > .main-left > .nav > .slide > .menu { + font-size: 1.1rem; + } + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: 1rem; + text-transform: capitalize; + } + + img[src*="/luci-static/resources/cbi/add.gif"] { + right: 55px; + display: block; + position: absolute; + margin-top: -34px; + } + img[src*="/luci-static/resources/cbi/remove.gif"] { + right: 55px; + display: block; + position: absolute; + margin-top: -34px; + } + + img[src*="/luci-static/resources/cbi/reload.gif"] { + right: 55px; + display: block; + position: absolute; + margin-top: -34px; + } + /* fix nlbw component */ + #detail-bubble { + /* left: unset !important; */ + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: 19rem !important; + width: calc(100vw - 21.25rem)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + } + #detail-bubble #bubble-table { + display: inline-table; + overflow: auto; + } + .node-nlbw-usage table { + display: block; + overflow: auto; + } +} + +@media screen and (max-width: 992px) { + + /* img[src*="/images/logo.png"] { + background-color: var(--mainleftbgColor); + height: 50px; + background-image: var(--mlogo); + background-size: 310px; + background-repeat: no-repeat; + padding: 0 0 0 310px; + width: 0; + margin: 0; + background-position: 0; + } */ + + .main-left { + width: 0; + position: fixed; + z-index: 100; + } + + .main-right { + width: 100%; + } + + .showSide { + margin: 0; + padding: 0; + display: inline-block; + position: absolute; + width: 300px; + height: 50px; + padding: 17px 27px; + } + + .showSide:before { + content: "\e20e"; + font-size: 1.7rem; + } + + #maincontent > .container { + margin: 20px 20px; + } + + .node-main-login .showSide { + display: none !important; + } + + .cbi-value-title { + width:35%; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div * { + width: 100% !important; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div input[type="text"] { + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div:nth-child(4) input[type="text"] { + margin: 0 !important; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div select, + .node-network-diagnostics > .main .cbi-map div.cbi-section > div input[type="button"] { + margin: 1rem 0 0 0; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div { + width: 100% !important; + } + + .node-main-login > .main .cbi-value-title { + text-align: left; + } + + img[src*="/luci-static/resources/cbi/add.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + img[src*="/luci-static/resources/cbi/remove.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + + img[src*="/luci-static/resources/cbi/reload.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: inline-table; + overflow: auto; + } +} + +@media screen and (max-width: 700px) { + + #cbi-vssr-servers .cbi-button-add { + position: static !important; + width: auto !important; + height: 2rem !important; + line-height: 2rem !important; + color: #fff; + display: block; + padding: 0 !important; + font-size: 0.92rem; + border-radius: 10px !important; + box-shadow: none ; + background-image: none; + } + #cbi-vssr-servers .cbi-section-table-row { + margin:10px 0 !important; + } + #cbi-vssr-servers .p-in5 { + padding-bottom: 10px !important; + margin: 0 !important; + } + + #cbi-vssr-servers .cbi-page-actions { + padding-bottom: 10px !important; + } + + #maincontent > .container { + margin: 20px 20px; + } + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: inline-table; + overflow: auto; + } +} + +@media screen and (max-width: 470px) { + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: block; + overflow: auto; + } +} + +@media screen and (max-width: 370px) { + + div.cbi-section { + /* overflow-x: auto; */ + } + + select { + width: 100%; + } + .label { + position: absolute; + right: 5px; + top: -70px; + } + + header { + height: 55px; + } + + h3 { + padding: 0 10px 10px 10px; + } + + /* img[src*="/images/logo.png"] + { + height: 45px; + background-image: var(--mlogo); + background-size: 310px; + background-repeat: no-repeat; + padding: 0 0 0 310px; + width: 0; + margin: 0; + background-position: 0; + } */ + + .showSide { + height: 45px; + } + + #maincontent > .container { + margin: 20px 20px; + } + + .main { + top: 45px; + } + + .main-left{ + top: 45px; + } + .main > .main-left > .nav > .slide > .menu { + } + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + } + + .cbi-value { + margin-bottom: 20px; + display: table; + padding: 0px; + border-bottom: none; + } + + .cbi-value-title { + width: 100%; + font-weight: 700; + float: left; + padding: 0; + margin: 0; + margin-bottom: .25rem; + } + + .cbi-section-node { + padding: 10px !important; + } + + .cbi-value-description { + width: 100%; + display: block; + } + + .cbi-value > .cbi-value-field { + display: block; + float: left; + width: 100%; + } + img[src*="/luci-static/resources/cbi/add.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + img[src*="/luci-static/resources/cbi/remove.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + + img[src*="/luci-static/resources/cbi/reload.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + .cbi-section-node > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor); + } + + .cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor); + } + + div > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor); + } + + .node-main-login > .main .cbi-value { + padding: 0; + } + + .node-main-login > .main form > div:nth-last-child(1) { + margin-top: 2rem; + } + + .node-main-login > .main div.cbi-section { + margin: 0; + padding: 0.5rem; + } + + #container\.network\.lan\.physical .cbi-value-title, + #cbi-network-1-_ifname .cbi-value-title + { + width: 35%; + } + #cbi-network-1-_ifname .cbi-value-field + { + width: 65%; + } + + + h2 { + font-size: 1.2rem; + text-transform: capitalize; + } + + select, + input { + /* max-width: 200px; */ + } + + input[type='checkbox'] { + height: 1.2rem !important; + width: 1.2rem !important; + } + + #swaptotal div div small, + #swapfree div div small, + #swapcache div div small, + #memfree div div small, + #membuff div div small, + #conns div div small, + #memcache div div small, + #memtotal div div small{ + } + #swaptotal div div, + #swapfree div div, + #swapcache div div, + #memfree div div, + #membuff div div, + #conns div div, + #memcache div div, + #memtotal div div{ + } + + + .node-status-iptables > .main div > .cbi-map > form input[type="submit"]{ + margin: 0; + } + + #cbi-samba-cfg010f89-_tmpl .cbi-value-title{ + width: 15%; + + } + #cbi-samba-cfg010f89-_tmpl .cbi-value-field{ + width: 95%; + } + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: block; + overflow: auto; + } +} + + +/* fix http://192.168.2.1/cgi-bin/luci/admin/nlbw/usage */ +#intervalSelect { + height: 40px !important; +} + +/* fix luci-app-commands */ +.commandbox div { + position: unset !important; +} + +/* fix luci-app-netspeedtest */ +#cbi-netspeedtest-homebox- { + display: unset !important; +} + +.node-nlbw-usage table { + display: block; + overflow: auto; +} +/* document.getElementById("container.nlbw.traffic").offsetWidth */ diff --git a/luci-theme-design/htdocs/luci-static/design/css/style.css b/luci-theme-design/htdocs/luci-static/design/css/style.css new file mode 100644 index 000000000..2cabe112e --- /dev/null +++ b/luci-theme-design/htdocs/luci-static/design/css/style.css @@ -0,0 +1,3611 @@ +/** + * Design is a clean HTML5 theme for LuCI. It is based on luci-theme-material and luci-theme-neobird + * + * luci-theme-material + * Copyright 2015 Lutty Yang + * + * luci-theme-Neobird + * Copyright 2021 2smile + * + * Licensed to the public under the Apache License 2.0 + */ + + :root { + --bg: #f1f4f5; + --mainbg: #fff; + --bgwhite: #fff; + --activeColor: #5ea69b; + --activeBottom: #51c291 2px solid; + --textColor: rgb(132,119,116); + --borderColor: rgba(0,0,0,.15); + --navbgColor: rgba(255, 255, 255, .7); + --navBorder: 1px solid #f2f2f2; + --sectionbgColor: #fff; + --sectionbgColor2: #fff; + --sectionShaddow: 3px 3px 3px rgba(0,0,0,.05); + --sectionBorder: none; + --sectiontabBorder: none; + --tabmenuBorderLR: none; + --tabmenubgColor: none; + --tabmenuBottom: #e4eaec 1px solid; + --tabmenuRadius: 0; + --sectionnodeBorder: #f7f7f7 1px solid; + --cbilineColor: #f7f7f7 1px solid; + --tabbgColor: #fff; + --inputbgColor: #f8f8f8; + --inputtextColor: #76838f; + --inputBorder: 1px solid #e4eaec; + --mainleftbgColor: rgb(255,255,255); + --bttextColor: #fff; + --badgebgColor: #f7f7f7; + --badgeBorder: #e4eaec 1px solid; + --progressbarColor: #c8c8c8; + --progressbar: #5ea69b; + --progressbartxtColor: #fff; + /* --logo: url('/luci-static/design/images/logo.png'); + --mlogo: url('/luci-static/design/images/mlogo.png'); */ + --logo_color: #222b36; + --alertColor: #000000; + --alertBackground: rgb(230 230 230); + --modelBackground: #d4d4d4; + --scrollbarColor:#d0d0d0; +} + +@media (prefers-color-scheme: dark) { + :root { + --bg: #000; + --bgwhite: #000; + --textColor: #fefefe; + --activeColor: #5ea69b; + --activeBottom: #51c291 2px solid; + --borderColor: #2C2C3A; + --navbgColor: hsla(0, 0%, 7%, .8); + --navBorder: 1px solid #1c1c1e; + --sectionbgColor: #1c1c1e; + --sectionbgColor2: #1c1c1e; + --sectionShaddow: 3px 3px 3px rgba(0,0,0,.05); + --sectionBorder: none; + --sectiontabBorder: none; + --sectionnodeBorder: #3d3d41 1px solid; + --cbilineColor: #2d2d2d 1px solid; + --tabbgColor: #1c1c1e; + --tabmenuBorderLR: none; + --tabmenubgColor: none; + --tabmenuBottom: #2d2d2d 1px solid; + --tabmenuRadius: 6px 6px 0 0; + --inputbgColor: #2f2f2f; + --inputtextColor: #fefefe; + --inputBorder: 1px solid #4d4d4d; + --mainleftbgColor: #000; + --bttextColor: #fefefe; + --badgebgColor: #fefefe; + --badgeBorder: #3d3d40 1px solid; + --progressbarColor: #6d6d6d; + --progressbar: #5ea69b; + --progressbartxtColor: #fefefe; + /* --logo: url('/luci-static/design/images/logod.png'); + --mlogo: url('/luci-static/design/images/mlogod.png'); */ + --logo_color: #fefefe; + --alertColor: #ffffff; + --alertBackground: rgb(30 30 30); + --modelBackground: #1c1c1e; + --scrollbarColor:#4a4a4a; + } +} + +@font-face { + font-family: 'icomoon'; + src: url('../fonts/font.eot'); + src: url('../fonts/font.eot') format('embedded-opentype'), + url('../fonts/font.ttf') format('truetype'), + url('../fonts/font.woff') format('woff'), + url('../fonts/font.svg') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'design'; + src: url(''); + src: url('?#iefix') format('embedded-opentype'), + url('../fonts/iconfont-Regular.woff2') format('woff2'), + url('../fonts/iconfont-Regular.woff') format('woff'), + url('../fonts/iconfont-Regular.ttf') format('truetype'), + url('#iconfont') format('svg'); +} + +@font-face{ + font-family: 'Cocon-Regular-Font'; + src : url('../fonts/Cocon-Regular-Font.otf') format('opentype'); +} +div{ + font-family: 'HYk2gj'; +} + +::-webkit-scrollbar { + width: 4px; +} + +::-webkit-scrollbar-track { + box-shadow: inset 0 0 0px rgba(240, 240, 240, .5); + background-color: rgb(255 255 255 / 0%); +} + +::-webkit-scrollbar-thumb { + background: var(--scrollbarColor) ; + border-radius: 10px; +} + +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a { + color: var(--textColor); + text-decoration: none; +} + +em { + font-style:normal !important; + line-height: 1.5; + padding-left: 10px; +} + +body div { + line-height:150%; +} + +.table { + position: relative; + display: table; +} + +.thead { + display: table-header-group; +} + +.tbody { + display: table-row-group; +} + +.tfoot { + display: table-footer-group; +} + +.td, +.th { + line-height: normal; + display: table-cell; + padding: .5em; + text-align: center; + vertical-align: middle; + white-space: nowrap; +} + +.th { + font-weight: bold; + white-space: nowrap; +} + +.tr.placeholder { + height: 4em; +} + +.tr.placeholder > .td { + line-height: 3; + position: absolute; + right: 0; + bottom: 0; + left: 0; + text-align: center !important; + background: inherit; +} + +.td[width="33%"], +.td[width="33%"]~.td { + padding: 12px; +} + +.table[width="33%"], +.th[width="33%"], +.td[width="33%"] { + width: 33%; +} + +.table[width="100%"], +.th[width="100%"], +.td[width="100%"] { + width: 100%; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: -apple-system, 'Microsoft Yahei'; + font-weight: 600; + line-height: 1.1; + color: inherit; + clear:both; + text-transform: capitalize; +} + +html { + overflow-y: hidden; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +html, body { + margin: 0px; + padding: 0px; + height: 100%; + font-family: -apple-system, 'Microsoft Yahei' !important; + font-size: 0.92rem; + line-height: 150%; + background-color: var(--bg); + color:var(--textColor); +} + +select { + overflow: hidden !important; + width: 100%; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + padding: 0 25px 0 10px !important; + background-size: 24px 16px; + background-repeat: no-repeat; + background-position: right center; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABGCAYAAAA6hjFpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDcuMS1jMDAwIDc5LmRhYmFjYmIsIDIwMjEvMDQvMTQtMDA6Mzk6NDQgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjhDNzA0QUE0NjE2QTExRUNCMjJFQkQyRkIyNURDNjE3IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjhDNzA0QUEzNjE2QTExRUNCMjJFQkQyRkIyNURDNjE3IiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCAyMi41IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QzNBNTYzNTY2MTUxMTFFQ0IyMkVCRDJGQjI1REM2MTciIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QzNBNTYzNTc2MTUxMTFFQ0IyMkVCRDJGQjI1REM2MTciLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6YjzxlAAACsklEQVR42uyaXUsVURSG51T0U/obfUvhhYF0U0HQhZQVIWVJCAkiSUXfRRcaBFbXQVBBRCASFCJBpQQipw+RREkpCa9aG95gs0DMOp6Z7TwvvAxnzczaa6/nzDnzVTndfSVDxdE6WgAQBBCAIIAABAEEIAggAEEAQQABCAIIQBBAAIIAAhAEEAQQgCCAAAStGSAbzA/N+wvSiwPmB6or16bkoY2afLN5r+q4l2MfDpr7zetV2z7zYpmOkAHByNSE0IxDOdUSxr2rOjLVNVC2n6z77hsYmtFnbqlzHS0aN+7DouorFZBH+ibGUCrmO+YjdaqhVeNVHIxm1Ve6P/XH5ibzLwfllvn4Ko8d8t90MEIde1RXaU97n6oJCw7KNXPbKo3ZpvwxjAXV8YTrkCx7piPFQ7lsbq/xWO3K62E0qQ4uDKXn5kbzTxe/YO6o0Rgdypc5GI0anyt1p5fm3eYfLn7e3PmfuTuVJ1YYZ5fG5Up9CQ2qSfMu3m3u+secXdo/1rzGGeTWyfIaUrPmXPycuWeFuXq0X6w55R8q4NwLe3PxlXmn+buLnzX3/mWOXm0fK+RrUP4MICvTG/MO86yLnzFfWmbfi9ou1qzyvS7wnAt/+31YTZxx8ZPmq+709c/pcoifcvEZ5Rku+HyTeB4yYt5unnbxE+YbEZSwvK54rGntP5LAXJN5QPXWvNX8zcWPmm9rHmF5zK0P22/T/hlAaqv35i3mKRc/bB7VMtaUIL5LaI7JPcIdVZMnXXyT+zyp7T4kNr8kn6mPqdlfllj/VevHEpxbsi85fNTP1ycX/2zerPUZQOqrcUGp6nNVMMYTnlPyrwFNCMILLScSn0++r7zUSFVdZ6wJ8aIcQBBAAIIAAhAEEIAggAAEAQQBBCAIIABBAAEIAghAEEAQQJLQbwEGAK/reX2gh5gQAAAAAElFTkSuQmCC'); +} + +select, +input { + color: var(--inputtextColor); + padding: 5px 10px; + font-size: 0.92rem; + font-family: -apple-system, 'Microsoft Yahei', sans-serif, Helvetica, Arial, sans-serif; + border: var(--inputBorder); + background-color: var(--inputbgColor); + transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + -webkit-transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + outline-style: none; + vertical-align: middle; + border-radius: 8px; + margin: 3px 3px 3px 0; + height: 2.8rem; + line-height: 2.8rem; + max-width: 550px; + +} + +select:not([multiple="multiple"]):focus, +input:focus { + border-color: #948FE1; + box-shadow:0 0 6px #948FE1; + -webkit-box-shadow:0 0 6px #948FE1; + -moz-box-shadow:0 0 6px #948FE1; +} + +select, +.cbi-dropdown { + width: inherit; + cursor: default; +} + +select:not([multiple="multiple"]):focus, +input:not(.cbi-button):focus, +.cbi-dropdown:focus { + border-color: #948FE1; + box-shadow:0 0 6px #948FE1; + -webkit-box-shadow:0 0 6px #948FE1; + -moz-box-shadow:0 0 6px #948FE1; +} + +.cbi-dropdown, +select[multiple="multiple"] { + height: auto; +} + +pre { + overflow: auto; +} + +code { + font-size: 1rem; + font-size-adjust: .35; + padding: 1px 3px; + color: #101010; + border-radius: 2px; + background: #ddd; +} + +abbr { + cursor: help; + text-decoration: underline; + color: #005470; +} + +hr { + margin: 1rem 0; + opacity: .1; + border-color: #eee; +} + +header, .main { + width: 100%; + position: absolute; +} + +header { + background-color: var(--bgwhite); + box-shadow: 17rem 2px 4px rgba(0, 0, 0, 0.08); + transition: box-shadow 0.2s; + height: 55px; + float: left; + position: fixed; + z-index: 101; +} + +footer { + text-align: right; + padding: 1rem; + color: #aaa; + font-size: 11px; + height: 80px; + visibility:hidden; + /*text-shadow: 0px 0px 2px #BBB;*/ +} + +footer > a { + color: rgb(154,37,143); + text-decoration: none; +} + +small { + font-size: 90%; + line-height: 1.42857143; + white-space: normal; +} + +.cbi-button-up, +.cbi-button-down, +.cbi-value-helpicon, +.showSide, +.main > .loading > span { + /* font-family: 'icomoon' !important; */ + /* font-size:10px; */ + speak: none; + /* font-style: normal !important; */ + /* font-weight: normal !important; */ + /* font-variant: normal !important; */ + /* text-transform: none !important; */ + /* line-height: 1; */ + + /* -webkit-font-smoothing: antialiased; */ + /* -moz-osx-font-smoothing: grayscale; */ +} + +.main { + top: 50px; + bottom: 0rem; + position: relative; + height: 100%; + height: calc(100% - 4rem); +} + +.main > .loading { + position: fixed; + width: 100%; + height: 100%; + z-index: 1000; + display: block; + background-color: var(--bgwhite); + top: 0; +} + +.main > .loading > span { + display: block; + text-align: center; + margin-top: 2rem; + color: var(--textColor); + font-size: 1rem; +} + +.main > .loading > span > .loading-img:before { + content: "\e603"; +} + +.main > .loading > span > .loading-img { + animation: anim-rotate 2s infinite linear; + margin-right: 0.2rem; + display: inline-block; +} + +@keyframes anim-rotate { + 0% { + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + } + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.main-left { + float: left; + width: 17rem; + background-color: var(--mainleftbgColor); + overflow-x: auto; + height: calc(100% - 3.5rem); + position: fixed; + padding-top: 15px; + box-shadow: 0 0px 4px rgb(0 0 0 / 8%); + /* transition: visibility 150ms, width 150ms; */ +} + +.main-right { + width: 85%; + width: calc(100% - 17rem); + float: right; + height: 100%; + border-left: var(--sectionBorder); +} + +.main-right > #maincontent { + position: relative; + z-index: 50; +} + + + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.nowrap:not(.td) { + white-space: nowrap; +} + +[disabled="disabled"] { + pointer-events: none; +} + +header > .fill > .container { + /* margin-top: .5rem; */ + /* padding: .5rem 1rem 0 1rem; */ + margin:0; + padding:0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +header > .fill > .container > #logo { + margin: 0 3.5rem 0 1.5rem; +} + +header > .fill > .container > #logo > img { + width: calc(0% + 10rem); + margin-top: -.5rem; +} + +header > .fill > .container > .brand { + font-size: 25px; + font-family: "Cocon-Regular-Font"; + /*font-weight:bold;*/ + line-height:60px; + /*color: white;*/ + color: var(--logo_color); + cursor: default; + /*background: #51c291;*/ + display:block; + width:17rem; + /* padding-left: 30px; */ + height:60px; + text-align:center; + float:left; + font-weight:900; + letter-spacing:1px; + margin-left: 10px; +} + +header > .fill > .container > a[class="brand"]:after { + content:""; + font-size:14px; + font-family:Tahoma; + position: absolute; + top:-10px; + font-weight:normal !important; +} + +header > .fill > .container > .brand-hostname { + font-size: 14px; + line-height:60px; + color: #555555; + cursor: default; + display:block; + width:17rem; + padding-right: 10px; + height:60px; + text-align:left; + float:left; + margin-top: 7px; + font-weight:300; + margin-left: -15px; +} + +header > .fill > .container > .status { + position: absolute; + top: 25%; + right: 1em; + float: right; + font-size: 1.5rem; + font-family: 'design'; + line-height: unset !important; +} + +header > .fill > .container > .status > * { + position: relative; + top: .2rem; + float: left; + margin-left: .3rem; + cursor: pointer; +} + +/* .modemenu-buttons { + display: flex; + flex-wrap: wrap; + align-items: center; + color: #fff; + color: var(--header-color); + background: #09c; + background: var(--header-bg); + padding: .5rem; + transition: box-shadow .2s; + box-shadow: 0 2px 5px rgb(0 0 0 / 26%); +} */ + +/* #modemenu { + margin: 0.25rem; + display: flex; + align-items: center; + flex-wrap: wrap; +} + +#modemenu > li > a { + font-size: .8rem; + font-weight: bold; + padding: .3rem .8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: #fff !important; + border-radius: 3px; + background-color: #bfbfbf; + text-shadow: none; +} + +#modemenu > li > a.active { + background-color: #002B49 !important; +} + +#modemenu > li.divider { + margin-left: .25rem; + margin-right: .25rem; + border: .5rem solid var(--submenu-bg-hover); + border-left: 1px solid var(--submenu-bg-hover); + border-right: 1px solid var(--submenu-bg-hover); + border-radius: 1rem; +} */ + +#xhr_poll_status { + display: flex; +} + +.danger { + background-color: #ff7d60 !important; +} + +.warning { + /*background-color: #FF7D60 !important;*/ + color: #FFF; +} + +.success { + background-color: #5cb85c !important; +} + +.notice, +[data-indicator]:not([data-style="inactive"]) { + color: var(--activeColor); +} + +.notice, +[data-indicator]:not([data-style="active"]) { + color: var(--progressbarColor); +} + +span[data-indicator="uci-changes"] { + font-size: .8rem; + transition: all .3s; +} + +.error { + color: red; +} + +.alert, +.alert-message { + font-weight: bold; + margin-bottom: 1em; + padding: 1rem; + border: 0; + border-radius: 3px !important; + color: #ffffff; + background-color: #5c5c5c; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + text-shadow: 1px 1px rgba(0, 0, 0, .1); + background-color: var(--alertBackground); +} + +.alert-message > h4 { + font-size: 110%; + font-weight: bold; +} + +.alert-message > * { + margin: .5rem 0; +} + +/*.alert-message .btn { + padding: .3rem .6rem; +}*/ + +.container .alert, +.container .alert-message { + margin-top: 1rem; +} + +.main > .main-left > .nav { + overflow-y: visible !important; + font-size: 1rem; + width: 90%; + margin: auto; + margin-bottom: 90px; +} + +.main > .main-left > .nav > li { + cursor: pointer; + padding-top:6px; +} + +.main > .main-left > .nav > li a { + color: var(--activeColor); + display: block; + border-radius: 6px; + cursor: pointer; + font-weight: bold; + font-size: 1.1rem; + transition: all 0.2s; +} + +.main > .main-left > .nav > .slide, +.main > .main-left > .nav > li:last-child a +{ + padding: 0; + padding-top:8px; +} + +.main > .main-left > .nav > .slide > ul { + display: none; + list-style:dotted; +} + +.main > .main-left > .nav > .slide.active > ul { + display: block; +} + +.main > .main-left > .nav > .slide > .slide-menu > li { + margin-top: 8px; + border-radius: 6px; +} + +.main > .main-left > .nav > .slide > .menu::after { + right: 0.5rem; + top: 0.8rem; + font-family: "design" !important; + font-style: normal !important; + font-variant: normal !important; + content: "\eb03"; + float: right; + padding-right: 5px; + line-height: 1.6; + /* Better Font Rendering =========== */ + -moz-osx-font-smoothing: grayscale; + transition: all 0.15s ease; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; +} + +.main > .main-left > .nav > .slide > a:before, +.main > .main-left > .nav > li > a:before { + display: inline-block; + left:-10px; + top: 1px; + position: relative; + font-family: "design" !important; + font-weight: bold !important; + text-transform: none !important; + speak: none; + font-size: 1.2rem !important; + -webkit-font-smoothing: antialiased; +} + +.main > .main-left > .nav > .slide > a[data-title="Status"]:before { + content: "\e6b8"; +} + +.main > .main-left > .nav > .slide > a[data-title="System"]:before { + content: "\e645"; +} + +.main > .main-left > .nav > .slide > a[data-title="Services"]:before { + content: "\e6cb"; +} + +.main > .main-left > .nav > .slide > a[data-title="Docker"]:before { + content: "\44"; +} + +.main > .main-left > .nav > .slide > a[data-title="NAS"]:before { + content: "\eb04"; +} + +.main > .main-left > .nav > .slide > a[data-title="VPN"]:before { + content: "\56"; +} + +.main > .main-left > .nav > .slide > a[data-title="Network"]:before { + content: "\72"; +} + +.main > .main-left > .nav > .slide > a[data-title="Bandwidth Monitor"]:before { + content: "\e764"; +} + +.main .main-left .nav li.slide .menu[data-title="Statistics"]:before { + content: "\e604"; +} + +.main .main-left .nav li.slide .menu[data-title="Control"]:before { + content: "\e67a"; +} + +.main .main-left .nav li.slide .menu[data-title="Asterisk"]:before { + content: "\e7dd"; +} + +.main > .main-left > .nav > li > a[data-title="Inital Setup"]:before { + content: "\e67e"; +} + +.main > .main-left > .nav > li > a[href="/cgi-bin/luci//admin/wizard"]:before { + content: "\e67e"; +} + +.main > .main-left > .nav > li > a[data-title="iStore"]:before { + content: "\e676"; +} + +.main > .main-left > .nav > li > a[data-title="Logout"] { + padding: 0.675rem 0 0.675rem 2.5rem; +} + +.main > .main-left > .nav > li > a[data-title="Logout"]:before { + content: "\e641"; +} + +.main > .main-left > .nav > li > a[data-title="Reboot"] { + padding: 6px 25px; +} +.main > .main-left > .nav > li > a[data-title="Reboot"]:before { + content: "\e004"; +} + +.main > .main-left > .nav > .slide > .menu.active::after { + transform: rotate(90deg); +} + +body[class*="node-"] > .main > .main-left > .nav > .slide > .menu::before { + transition: transform .1s ease-in-out; +} + +body[class*="node-"] > .main > .main-left > .nav > .slide > .menu.active::before { + transition: transform .2s ease-in-out; +} + +.main > .main-left[style*="overflow: hidden"] > .nav > .slide > .menu::before { + display: none; +} + +.main > .main-left > .nav > li:last-child::before { + position: absolute; + left: 14px; + width: 24px; + height: 24px; + /* content: url(./icons/logout.svg); */ +} + +.main > .main-left > .nav > li:last-child a:hover, +.main > .main-left > .nav > .slide > .menu:hover { + background: var(--activeColor); + color:white; +} +.main > .main-left > .nav > .slide:hover { + background: none; +} + +.slide-menu { + overflow:hidden; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active { + background-color: var(--activeColor); +} + +.main > .main-left > .nav > .slide > .slide-menu > li > a { + position: relative; + display: block; + color: var(--textColor); + vertical-align: middle; + background:none !important; + border: none !important; + text-transform: capitalize; + font-size: 1rem; + margin: 0.1rem 0.5rem 0.1rem 0.5rem; + padding: 0.675rem 0 0.675rem 2.5rem; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active > a { + color: white; +} + +.main > .main-left > .nav > .slide > .slide-menu > li:hover { + background: var(--activeColor); + color:white !important; + transition: all 0.2s; +} +.main .main-left .nav li.slide .slide-menu .active a { + color: #000; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active:hover { + background-color: var(--activeColor); + cursor: pointer; +} + +/* ripple effect */ +.main > .main-left > .nav > .slide > .menu, +.main > .main-left > .nav > li:last-child a +{ + display: block; + padding: 0.675rem 0 0.675rem 2.5rem; + text-decoration: none; + cursor: pointer;; +} + +img[src*="/luci-static/resources/icons/loading.gif"] { + background-image: url(../images/loading.gif); + background-size: 20px 20px; + height: 20px; + width: 20px; + padding: 0 0 0 20px; + width: 0; +} + +#maincontent > .container { + margin:30px 30px 50px 30px; +} + + +li { + list-style-type: none; +} + + +h1 { + color: var(--activeColor); + font-size: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +h2 { + color: var(--activeColor); + padding: 0 12px 6px 12px; + text-transform: capitalize; +} + +h3 { + font-size: 1.2rem; + color: var(--activeColor); + font-weight:bold; + padding: 0 12px 10px 12px; +} + +h4 { + +} + + div.cbi-section{ + border: var(--sectionBorder); + margin-bottom: 20px; + border-radius: 8px; + margin-top: 5px; + } + +.cbi-section, +.cbi-section-error, +#iptables, +.Firewall form, +#cbi-network > .cbi-section-node, +#cbi-wireless > .cbi-section-node, +#cbi-wireless > #wifi_assoclist_table, +[data-tab-title], +/* [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), */ +[data-page="admin-system-opkg"] #maincontent > .container { + /* margin: 10px 0 0 0; */ + padding: 10px; + border: 1px; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + text-align: left; + min-width: inherit; + overflow-x: auto; + overflow-y: hidden; + background-color: var(--sectionbgColor); + border-radius: 8px; + /* box-shadow: var(--sectionShaddow); */ + -webkit-overflow-scrolling: touch; +} + +#maincontent > .container > div:nth-child(1).alert-message.warning > a { + font: inherit; + overflow: visible; + text-transform: none; + display: inline-block; + margin-bottom: 0; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + min-width: 6rem; + padding: 0.5rem 1rem; + font-size: 14px; + line-height: 1.42857143; + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; + margin-top: 2rem; + text-decoration: inherit; +} + +.cbi-modal .cbi-section, +.cbi-section .cbi-section { + padding: 0; + box-shadow: none; +} + +.cbi-modal .cbi-tabmenu { + margin-left: 0; +} + +/* desc */ +.cbi-section-descr { + padding: 3px 10px; +} + +.cbi-map-descr { + padding: 5px 5px 5px 12px; +} + +.cbi-map-descr h3 { + font-size: 0.92rem; + font-weight: normal; + color: #666; +} + +#cbi-vsftpd .cbi-map-descr { + color: var(--activeColor); + padding: 0 12px 0px 12px; + font-size: 1.2rem; + font-weight: bold; +} + +.cbi-map-descr + fieldset { + margin-top: 1rem; +} + +.cbi-section > legend { + display: none !important; +} + +fieldset > fieldset, +.cbi-section > .cbi-section { + margin: 0; + padding: 0; + border: 0; + box-shadow: none; +} + +.cbi-section > h3:first-child, +.panel-title { + width: 100%; + display: block; + padding: 10px; + font-weight: bold; + font-size: 1rem; +} + +.cbi-section > h4:first-child, +.cbi-section > p:first-child, +[data-tab-title] > h3:first-child, +[data-tab-title] > h4:first-child, +[data-tab-title] > p:first-child { + padding-top: 1rem; +} + +table, +.table { + border-spacing: 0; + border-collapse: collapse; + width: 100%; + border: 0px solid #eee; +} + +table > tbody > tr > td, +table > tbody > tr > th, +table > tfoot > tr > td, +table > tfoot > tr > th, +table > thead > tr > td, +table > thead > tr > th, +.table > .tbody > .tr > .td, +.table > .tbody > .tr > .th, +.table > .tfoot > .tr > .td, +.table > .tfoot > .tr > .th, +.table > .thead > .tr > .td, +.table > .thead > .tr > .th, +.table > .tr > .td.cbi-value-field, +.table > .tr > .th.cbi-section-table-cell { + padding: 12px; + white-space: nowrap; + line-height:1.5; + vertical-align: middle !important; +} + +.container > .cbi-section:first-of-type > .table[width="100%"] > .tr > .td { + padding: .6rem; +} + + +.cbi-section-table-cell { + line-height: 1.1; + align-self: flex-end; + flex: 1 1 auto; +} + +table > tr { + border-bottom: var(--cbilineColor) !important; +} + +table > tr:last-child { + border-bottom: none !important; +} + +#cbi-wireless .td, +#cbi-network .tr:first-child > .td, +.table[width="100%"] > .tr:first-child > .td, +[data-page="admin-network-diagnostics"] .tr > .td, +.tr.table-titles > .th, +.tr.cbi-section-table-titles > .th { + border-top: 0 !important; +} + +.table[width="100%"] > .tr:first-child > .td { + margin: auto 0; +} + +.cbi-section-table-row { + text-align: center; +} + +.cbi-section-table-row:last-child { + margin-bottom: 0; +} + +.cbi-section-table-row > .cbi-value-field .cbi-dropdown, +.cbi-section-table-row > .cbi-value-field .cbi-input-select, +.cbi-section-table-row > .cbi-value-field .cbi-input-text, +.cbi-section-table-row > .cbi-value-field .cbi-input-password { + width: 100%; +} + +.cbi-section-table-row > .cbi-value-field [data-dynlist] > input, +.cbi-section-table-row > .cbi-value-field input.cbi-input-password { + width: calc(100% - 1.5rem); +} + +.cbi-section-table-row .td { + text-align: center !important; +} + +/* div > table > tbody > tr:nth-of-type(2n), +div > .table > .tr:nth-of-type(2n) { + background-color: #f9f9f9; +} */ + +/* fix multiple table */ +table table, +.table .table, +.cbi-value-field table, +.cbi-value-field .table, +td > table > tbody > tr > td, +.td > .table > .tbody > .tr > .td, +.cbi-value-field > table > tbody > tr > td, +.cbi-value-field > .table > .tbody > .tr > .td { + border: 0; +} + +/* button style */ + +.cbi-button, .btn { + -webkit-appearance: none; + text-transform: uppercase; + color: #fff; + background-color: #337ab7; + transition: all 0.2s ease-in-out; + display: inline-block; + border: none; + cursor: pointer; + -ms-touch-action: manipulation; + touch-action: manipulation; + background-image: none; + text-align: center; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + width: auto !important; + min-width: 80px; + padding: 0px 8px 0px 8px; + /* max-width: 160px; */ + height: 35px; + line-height: 35px; + border-radius: 8px; +} + + + +.cbi-button:hover, +.cbi-button:focus, +.cbi-button:active { + color: #fff; + outline: 0; + text-decoration: none; + background-color: rgb(106,101,214); +} + +.cbi-button:hover, +.cbi-button:focus { + box-shadow: 0 1px 1px rgba(0,0,0,.05); +} + +.cbi-button:active { + box-shadow: 0 1px 1px rgba(0,0,0,.05); +} + +.cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: 0.60; + box-shadow: none; +} + +form.inline + form.inline, +.cbi-button + .cbi-button { +} + +.cbi-button-reset, +.cbi-input-remove { + color: #fff !important; + background-color: #617486 !important; +} + +.cbi-button-reset:hover, +.cbi-input-remove:hover, +.cbi-button-remove:hover{ + color: #fff !important; + background-color: rgb(83,100,115) !important; +} + +.cbi-button-link, +.cbi-input-find, +.cbi-input-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-find, +.cbi-input-reload, +.cbi-button-reload { + color: var(--bttextColor); + background-color: rgb(0,171,232) !important; + border-color: rgb(0,171,232) !important; +} + +.cbi-button-link:hover, +.cbi-input-find:hover, +.cbi-input-save:hover, +.cbi-button-add:hover, +.cbi-button-save:hover, +.cbi-button-find:hover, +.cbi-input-reload:hover, +.cbi-button-reload:hover{ + color: #fff !important; + background-color: #337ab7 !important; + border-color: #337ab7 !important; +} + +.cbi-input-apply, +.cbi-button-apply, +.cbi-button-edit { + color: #fff !important; + background-color: var(--activeColor); +} + +[data-page="admin-status-iptables"] .right { + margin-bottom: 10px !important; + margin-top: 10px !important; +} +.cbi-button:not(select) { + -webkit-appearance: none !important; +} + +.cbi-input-reset, +.cbi-button-remove, +.cbi-button-neutral.down{ + color: #fff !important; + background: #617486; +} + + +.a-to-btn { + text-decoration: none; +} + +.cbi-page-actions .cbi-button-link:first-child { + float: left; +} + +.a-to-btn { + text-decoration: none; +} + +.cbi-value-field .cbi-button-add { + font-weight: bold; + margin: 4px 3px; + padding: 1px 6px; +} + +.tabs { + margin: 15px 0; + overflow-x: auto; +} + +.tabs > li, +.cbi-tabmenu > li { + display: inline-block; + padding: .55rem 0; + cursor: pointer; +} + +.tabs > li { + padding-bottom: .4rem; + border-bottom: .2rem solid transparent; +} + +.tabs > li:hover { + cursor: pointer; + border-bottom-color: #c9c9c9; +} + +.tabs > li > a { + text-decoration: none; + padding: 0 6px 0 6px; + float: left; + display: block; + white-space: nowrap; + height: 2.5rem; + line-height: 2.5rem; + font-size: 0.92rem; +} + +.cbi-tabmenu > li > a { + text-decoration: none; + float: left; + display: block; + white-space: nowrap; + height: 2.5rem; + line-height: 2.5rem; + font-size: 0.92rem; + margin: 0 10px; +} + +.cbi-tabmenu > li { + border-radius: var(--tabmenuRadius); +} + +.cbi-tabmenu > li, .tabs > li { + display: table-cell; +} + +.tabs > li[class~="active"] > a { + color: var(--activeColor) !important; + padding-bottom: 8px; + border-bottom: var(--activeColor) 2px solid; +} + +.tabs > li[class~="active"], +.tabs > li:hover{ + cursor: pointer; +} + +.cbi-tabmenu { + border-top: var(--sectiontabBorder); + border-left: var(--tabmenuBorderLR); + border-right: var(--tabmenuBorderLR); + border-bottom: var(--tabmenuBottom); + background-color: var(--tabmenubgColor); + width: 100%; + overflow-x: auto; + margin-top: 5px; + margin-bottom: 10px; +} + +.cbi-tabmenu > li:hover { + background-color: none; +} + +.cbi-tabmenu > li[class~="cbi-tab"] a { + color: var(--activeColor); + border-bottom: 2px solid var(--activeColor); +} + +.cbi-section .cbi-section-remove:nth-of-type(2n), +.container > .cbi-section .cbi-section-node:nth-of-type(2n) { + background-color: var(--cbilineColor); +} + +[data-tab-title] { + overflow: hidden; + height: 0; + opacity: 0; + margin: 0; + padding: 0rem 1rem !important; +} + +[data-tab-active="true"] { + overflow: auto; + height: auto; + opacity: 1; + transition: opacity .25s ease-in; + margin: inherit !important; + display: block; + /* padding: 12px; */ + border-radius: 8px; + /* box-shadow: 3px 3px 3px rgb(0 0 0 / 5%); */ + /* background-color: var(--bgwhite); */ +} + +.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3), +.cbi-section[id] .cbi-section-node:nth-of-type(4n+4) { + /* background-color: #f9f9f9; */ +} + +.cbi-section-node-tabbed { + margin-top: 0; + border-bottom: var(--sectiontabBorder); + border-left: var(--sectiontabBorder); + border-right: var(--sectiontabBorder); + border-radius: 0 0; +} + +.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + /* background-color: #f9f9f9; */ +} + +.cbi-value-field { + width: 65%; +} + +.cbi-value-field, +.cbi-value-description { + display: table-cell; +} + +.cbi-value-description { + font-size: small; + padding-top: .4rem; + opacity: .5; +} + +.cbi-value-title { + word-wrap: break-word; + display: table-cell; + width: 35%; + float: left; + padding: 13px 10px 5px 3px; +} + +.cbi-value { + display: flex; + width: 100%; + align-items: center; + align-content: center; + justify-content: flex-start; + min-height: 40px; + padding: 8px 10px; + flex-flow:row wrap; + border-bottom: var(--cbilineColor); +} + +.cbi-value:last-child { + border-bottom: none; +} + +.cbi-value ul { + line-height: 1.25; +} + +.cbi-value strong { + font-weight: normal; +} + +.cbi-value-field .cbi-dropdown, +.cbi-value-field .cbi-input-select, +.cbi-value input[type="text"], +.cbi-value input[type="password"] { + width: 100%; +} + +#cbi-firewall-zone .cbi-input-select, +#cbi-network-switch_vlan .cbi-input-select { + min-width: 11rem; +} + +#cbi-network-switch_vlan .cbi-input-text { + max-width: 3rem; +} + +.cbi-input-invalid { + color: #f00; + border-bottom-color: #f00; +} + +.cbi-section-error { + font-weight: bold; + line-height: 1.42857143; + margin: 18px; + padding: 6px; + border: thin solid #f00; + border-radius: 3px; + background-color: #fce6e6; +} + +.cbi-section-error ul { + margin: 0 0 0 20px; +} + +.cbi-section-error ul li { + font-weight: bold; + color: #f00; +} + +.td[data-title]::before { + font-weight: bold; + display: none; + padding: .25rem 0; + content: attr(data-title) ":\20"; + text-align: left; + white-space: nowrap; +} + +.tr.placeholder .td[data-title]::before { + display: none; +} + +.tr[data-title]::before, +.tr.cbi-section-table-titles.named::before { + font-weight: bold; + display: table-cell; + align-self: center; + flex: 1 1 5%; + padding: .25rem; + content: attr(data-title) "\20"; + text-align: center; + vertical-align: middle; + white-space: normal; + word-wrap: break-word; +} + +.cbi-rowstyle-2 { + background-color: var(--sectionbgColor2); +} + +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down{ +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; +} + +.td.cbi-section-actions { + text-align: right !important; + vertical-align: middle; +} + +.td.cbi-section-actions > * { + /* display: inline-flex; */ +} + +.td.cbi-section-actions > * > *, +.td.cbi-section-actions > * > form > * { + margin: 0 5px; +} + +.td.cbi-section-actions > * > form { + display: inline-flex; + margin: 0; +} + +/* lists */ +.cbi-dynlist { + line-height: 1.3; + flex-direction: column; + min-height: 30px; + cursor: text; +} + +.cbi-dynlist > .item { + position: relative; + max-width: 25rem; + margin-right: 2em; + padding: .5em .25em .25em 0; + pointer-events: none; + color: #666; + border-bottom: 2px solid rgba(0, 0, 0, .26); + outline: 0; +} + +.cbi-dynlist[name="sshkeys"] > .item { + max-width: none; +} + +.cbi-dynlist > .item::after { + font-weight: bold; + position: absolute; + right: -2em; + bottom: 0; + display: inline-flex; + min-height: 17px; + padding: 0 6px; + content: "\00D7"; + pointer-events: auto; + color: #fff; + border: thin solid #d43f3a; + background-color: #d9534f; +} + +.cbi-dynlist > .item > span { + white-space: normal; + word-break: break-word; +} + +.cbi-dynlist > .add-item { + display: inline-flex; + align-items: center; + width: 100%; + min-width: 16rem; +} + +.cbi-dynlist > .add-item:not([ondrop]) > input { + overflow: hidden; + width: 100%; + min-width: 15rem; + white-space: nowrap; + text-overflow: ellipsis; +} + +.cbi-dynlist > .add-item[ondrop] > input { + min-width: 13rem; +} + +.cbi-dynlist, +.cbi-dropdown { + position: relative; + display: inline-flex; + padding: 0; +} + +.cbi-dropdown[placeholder*="select"] { + max-width: 25rem; + height: auto; + margin-top: -3px; +} + +.cbi-dropdown > ul { + display: flex; + overflow-x: hidden; + overflow-y: auto; + width: 100%; + margin: 0 !important; + padding: 0; + list-style: none; + outline: 0; +} + +.cbi-dropdown > ul.preview { + display: none; +} + +.cbi-dropdown > .open { + flex-basis: 15px; +} + +.cbi-dropdown > .open, +.cbi-dropdown > .more { + font-size: 1rem; + font-weight: 900; + line-height: 2; + display: flex; + flex-direction: column; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + padding: 0 .25em; + cursor: default; + text-align: center; + outline: 0; +} + +.cbi-dropdown.btn { + min-height: 1.8rem; + padding-top: 0px; + padding-bottom: 0px; + padding-right: 0px; +} + +.cbi-dropdown.btn > .open { + font-size: 0.8rem; + padding: 0px; + margin: 0 5px; +} + +.cbi-dropdown.btn > div { + margin: 0px; +} + +.cbi-dropdown > .more, +.cbi-dropdown > ul > li[placeholder] { + font-weight: bold; + display: none; + color: #777; + text-shadow: 1px 1px 0 #fff; +} + +.cbi-dropdown > ul > li { + display: none; + overflow: hidden; + align-items: center; + align-self: center; + flex-grow: 1; + flex-shrink: 1; + min-height: 20px; + padding: .25em; + white-space: nowrap; + text-overflow: ellipsis; +} + +.cbi-dropdown > ul > li .hide-open { + display: initial; +} + +.cbi-dropdown > ul > li .hide-close { + display: none; +} + +.cbi-dropdown > ul > li[display]:not([display="0"]) { + border-left: thin solid #ccc; +} + +.cbi-dropdown > ul > li[data-value*="1"] { + padding-left: 15px !important; +} + +.cbi-dropdown[empty] > ul { + max-width: 1px; +} + +.cbi-dropdown > ul > li > form { + display: none; + margin: 0; + padding: 0; + pointer-events: none; +} + +.cbi-dropdown > ul > li img { + margin-right: .25em; + vertical-align: middle; +} + +.cbi-dropdown > ul > li > form > input[type="checkbox"] { + height: auto; + margin: 0; +} + +.cbi-dropdown > ul > li input[type="text"] { + height: 20px; +} + +.cbi-dropdown[open] > ul.dropdown { + position: absolute; + z-index: 1100; + display: block; + width: auto; + max-height: 200px !important; + /* border: thin solid #918e8c; */ + background: var(--activeColor); + /* box-shadow: 0 0 4px #918e8c; */ + /* color: var(--main-menu-color); */ + text-align: center; +} + +.cbi-dropdown > ul > li[display], +.cbi-dropdown[open] > ul.preview, +.cbi-dropdown[open] > ul.dropdown > li, +.cbi-dropdown[multiple] > ul > li > label, +.cbi-dropdown[multiple][open] > ul.dropdown > li, +.cbi-dropdown[multiple][more] > .more, +.cbi-dropdown[multiple][empty] > .more { + display: flex; + align-items: center; + flex-grow: 1; +} + +.cbi-dropdown[empty] > ul > li, +.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], +.cbi-dropdown[multiple][open] > ul.dropdown > li > form { + display: block; +} + +.cbi-dropdown[open] > ul.dropdown > li .hide-open { + display: none; +} + +.cbi-dropdown[open] > ul.dropdown > li .hide-close { + display: initial; +} + +/* .cbi-dropdown[open] > ul.dropdown > li { + border-bottom: thin solid #ccc; +} */ + +.cbi-dropdown[open] > ul.dropdown > li[selected] { + background: var(--activeColor); +} + +.cbi-dropdown[open] > ul.dropdown > li.focus { + background: linear-gradient(90deg, #a3c2e8 0%, #84aad9 100%); +} + +.cbi-dropdown[open] > ul.dropdown > li:last-child { + margin-bottom: 0; + border-bottom: 0; + background: #627486; +} + +.cbi-dropdown[open] > ul.dropdown > li[unselectable] { + opacity: .7; +} + +.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child { + width: 100%; +} + +.cbi-dropdown[disabled] { + pointer-events: none; + opacity: .6; +} + +.cbi-dropdown .zonebadge { + width: 100%; +} + +.cbi-dropdown[open] .zonebadge { + width: auto; +} + +/* progressbar */ +/* progressbar */ +.cbi-progressbar { + position: relative !important; + min-width: 11rem !important; + height: 1.5rem !important; + margin: 0 0 !important; + /* border-color: var(--progressbarColor) !important; */ + background-color:var(--progressbarColor) !important; + border-radius: 5px !important; + overflow: hidden !important; +} + +.cbi-progressbar>div { + width: 0; + height: 100% !important; + transition: width .25s ease-in !important; + color: var(--progressbartxtColor) !important; + background: var(--progressbar) !important; +} + +.cbi-progressbar::after { + /* font-weight: bold; */ + /* font-family: monospace; */ + font-size: 0.75rem !important; + font-size-adjust: .38 !important; + line-height: 1.5rem !important; + position: absolute !important; + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + left: 0 !important; + overflow: hidden !important; + content: attr(title) !important; + text-align: center !important; + white-space: pre !important; + text-overflow: ellipsis !important; +} + +#modal_overlay { + position: fixed; + z-index: 900; + top: 4rem; + right: 10000px; + bottom: 0; + left: -10000px; + overflow-y: scroll; + transition: opacity .125s ease-in; + opacity: 0; + background: rgba(0, 0, 0, .7); + -webkit-overflow-scrolling: touch; +} + +.modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 90%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + margin: 5em auto; + padding: 1em; + border-radius: 5px !important; + background: var(--modelBackground); + box-shadow: 0 2px 2px 0 rgb(0 0 0 / 16%), 0 0 2px 0 rgb(0 0 0 / 12%); +} + + +.modal > * { + line-height: normal; + flex-basis: 100%; + margin-bottom: .5em; + max-width: 100%; +} + +.modal > pre, +.modal > textarea { + font-size: 1rem; + font-size-adjust: .35; + overflow: auto; + margin-bottom: .5em; + padding: 8.5px; + cursor: auto; + white-space: pre-wrap; + color: #eee; + outline: 0; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +.modal > h4 { + margin: .5em 0; +} + +.modal ul { + margin-left: 2.2em; + word-break: break-word; +} + +.modal li { + list-style-type: square; + color: #808080; +} + +.modal p { + padding-left: .25rem; + word-break: break-word; + color: #fff; +} + +.modal label.btn { + display: flex; + align-items: center; + white-space: normal; + text-align: left; + text-transform: none; + padding-bottom: 0.2rem; + padding-top: 0.2rem; +} + +.modal label.warning { + background-color: #f0ad4e !important; +} + +.modal.cbi-modal { + max-width: 90%; + max-height: none; +} + +body.modal-overlay-active { + overflow: hidden; + height: 100vh; +} + +body.modal-overlay-active #modal_overlay { + right: 0; + left: 0; + opacity: 1; +} + +.spinning { + position: relative; + padding-left: 32px !important; +} + +.spinning::before { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + width: 32px; + content: ""; + /* background: url(../resources/icons/loading.gif) no-repeat center; */ + background-size: 16px; +} + +/* luci */ +.hidden { + display: none; +} + +.left, +.left::before { + text-align: left !important; +} + +.right .cbi-button { + /* height: 20px; */ + line-height: 20px; +/* min-width: 100px; */ + margin: 0; +} + +.right, +.right::before { + text-align: right !important; +} + +.center, +.center::before { + text-align: center !important; +} + +.top { + align-self: flex-start !important; + /* vertical-align: top !important; */ +} + +.bottom { + align-self: flex-end !important; + vertical-align: bottom !important; +} + +.inline { + display: inline; +} + +.cbi-page-actions { + text-align: center; +} +.cbi-page-actions > form[method="post"] { + display: inline-block; +} + +.th[data-type="button"], +.td[data-type="button"], +.th[data-type="fvalue"], +.td[data-type="fvalue"] { + flex: 1 1 2em; + text-align: center; +} + +.ifacebadge { + display: inline-flex; + gap: .2rem; + padding: .5rem .8rem; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); +} + +td > .ifacebadge, +.td > .ifacebadge { + font-size: .8rem; + background-color: var(--activeColor); + color: white; + border-radius: 8px; +} + +.ifacebadge > em, +.ifacebadge > img { + display: inline-block; + align-self: flex-start; +} + +.network-status-table { + display: flex; + flex-wrap: wrap; +} + +.network-status-table .ifacebox { + flex-grow: 1; + margin: .5em; +} + +.network-status-table .ifacebox-body { + display: flex; + flex-direction: column; + height: 100%; +} + +.network-status-table .ifacebox-body > span { + flex: 10 10 auto; + height: 100%; +} + +.network-status-table .ifacebox-body > div { + display: flex; + flex-wrap: wrap; +} + +.network-status-table .ifacebox-body .ifacebadge { + align-items: center; + flex: 1 1 auto; + min-width: 220px; + margin: .5em .25em 0 .25em; + padding: .5em; +} + +/* textarea */ +#content_syslog { + padding: 5px; + margin-top:10px; + border-radius: 8px; + background-color: var(--sectionbgColor); + box-shadow: 3px 3px 3px rgb(0 0 0 / 5%); +} + + +/*textarea*/ +.cbi-input-textarea, textarea { + color: var(--inputtextColor); + padding: 10px; + line-height: normal; + border: var(--sectionBorder); + background-color: var(--inputbgColor); + transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + -webkit-transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + outline-style: none; + vertical-align: baseline; + border-radius: 8px; + font-family: Menlo, Mono; + font-size: 0.9rem; + white-space: pre; + margin-bottom: 5px; +} + +/* fix .cbi-input-textarea, textarea { */ +.node-admin-system-system .cbi-input-textarea { + max-width: 550px; +} + +#syslog { + width: 100%; + min-height: 15rem; + padding: 10px; + margin-bottom: 20px; + border-radius: 0; + background-color: var(--sectionbgColor); + border: none; +} + +#syslog:focus { + outline: 0; +} + +/* config changes */ +.uci-change-list { + font-family: monospace; +} + +.uci-change-list ins, +.uci-change-legend-label ins { + text-decoration: none; + border: 1px solid #00FF00; + background-color: #CCFFCC; + display: block; + padding: 2px; + color: black; + /* border-radius: 8px; */ + overflow-x: auto; +} + +.uci-change-list del, +.uci-change-legend-label del { + text-decoration: none; + border: 1px solid #FF0000; + background-color: #FFCCCC; + display: block; + font-style: normal; + padding: 2px; + color:black; + /* border-radius: 8px; */ + overflow-x: auto; +} + +.uci-change-list var, +.uci-change-legend-label var { + text-decoration: none; + border: 1px solid #CCCCCC; + background-color: #EEEEEE; + display: block; + font-style: normal; + padding: 2px; + color:black; + /* border-radius: 8px; */ + overflow-x: auto; +} + +.uci-change-list var ins, +.uci-change-list var del { + border: none; + white-space: pre; + font-style: normal; + padding: 0px; + color:black; + /* border-radius: 8px; */ + overflow-x: auto; +} + +.uci-change-legend { + padding: 5px; +} + +.uci-change-legend-label { + float: left; + width: 150px; +} + +.uci-change-legend-label > ins, +.uci-change-legend-label > del, +.uci-change-legend-label > var { + display: block; + float: left; + width: 10px; + height: 10px; + margin-right: 4px; +} + +.uci-change-legend-label var ins, +.uci-change-legend-label var del { + line-height: .4; + border: 0; +} + +.uci-change-list var, +.uci-change-list del, +.uci-change-list ins { + padding: 0.5rem; +} + +/* other fix */ +#iwsvg, +#iwsvg2, +#bwsvg { + border: thin solid #d4d4d4 !important; +} + +#iwsvg, +[data-page="admin-status-realtime-bandwidth"] #bwsvg { + border-top: 0 !important; +} + +.ifacebox { + line-height: 1.25; + display: inline-flex; + flex-direction: column; + min-width: 100px; + /* border-bottom: thin solid #666; */ + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 1px 2px rgba(0, 0, 0, .2); +} + +.ifacebox-head { + padding: .25em; + background: #eee; +} + +.ifacebox-head.active { + background: #5bc0de; + background: var(--bar-bg); +} + +.ifacebox-body { + padding: .25em; +} + +.cbi-image-button { + margin-left: .5rem; +} + +.zonebadge { + display: inline-block; + padding: .2rem .5rem; +} + +.zonebadge .ifacebadge { + margin: .1rem .2rem; + padding: .2rem .3rem; + border: thin solid #6c6c6c; +} + +.zonebadge > input[type="text"] { + min-width: 10rem; + margin-top: .3rem; + padding: .16rem 1rem; +} + +.zonebadge > em, +.zonebadge > strong { + display: inline-block; + margin: 0 .2rem; +} + +.cbi-value-field .cbi-input-checkbox, +.cbi-value-field .cbi-input-radio { + margin-top: .1rem; +} + +.cbi-value-field > ul > li { + display: flex; +} + +.cbi-value-field > ul > li > label { + margin-top: .5rem; +} + +.cbi-value-field > ul > li .ifacebadge { + margin-top: -.5rem; + margin-left: .4rem; + background-color: #eee; +} + +.cbi-section-table-row > .cbi-value-field .cbi-dropdown { + min-width: 7rem; +} + +.cbi-section-create { + display: inline-flex; + align-items: center; + margin: .5rem -3px; +} + +.cbi-section-create > * { + margin: .5rem; +} + +.cbi-section-remove { + padding: .5rem; +} + +div.cbi-value var, +td.cbi-value-field var, +.td.cbi-value-field var { + font-style: italic; + color: #0069d6; +} + +.cbi-optionals { + padding: 1rem 1rem 0 1rem; + border-top: thin solid #ccc; +} + +.cbi-dropdown-container { + position: relative; +} + +.cbi-tooltip-container, +span[data-tooltip], +span[data-tooltip] .label { + cursor: help !important; +} + +.cbi-tooltip { + position: absolute; + z-index: 1000; + left: -1000px; + padding: 2px 5px; + transition: opacity .25s ease-out; + white-space: pre; + pointer-events: none; + opacity: 0; + border-radius: 3px; + background: #fff; + box-shadow: 0 0 2px #444; +} + +.cbi-tooltip-container:hover .cbi-tooltip { + left: auto; + transition: opacity .25s ease-in; + opacity: 1; +} + +.zonebadge .cbi-tooltip { + margin: -1.5rem 0 0 -.5rem; + padding: .25rem; + background: inherit; +} + +.zonebadge-empty { + color: #404040; + background: repeating-linear-gradient(45deg, rgba(204, 204, 204, .5), rgba(204, 204, 204, .5) 5px, rgba(255, 255, 255, .5) 5px, rgba(255, 255, 255, .5) 10px); +} + +.zone-forwards { + display: flex; + min-width: 10rem; +} + +.zone-forwards > * { + flex: 1 1 45%; +} + +.zone-forwards > span { + flex-basis: 10%; + padding: 0 .25rem; + text-align: center; +} + +.zone-forwards .zone-src, +.zone-forwards .zone-dest { + display: flex; + flex-direction: column; +} + +.label, +[data-indicator] { + /* font-size: .8rem; */ + font-weight: bold; + padding: .3rem .8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + /* color: #fff !important; */ + border-radius: 3px; + background-color: var(--bgwhite); + text-shadow: none; +} + +label > input[type="checkbox"], +label > input[type="radio"] { + margin-right: 0.8rem; +} + +label[data-index][data-depends] { + padding-right: 2em; +} + +.showSide { + display: none; +} + +.darkMask { + position: fixed; + z-index: 99; + width: 100%; + height: 100%; + content: ""; + background-color: rgba(0, 0, 0, .56); + transition: opacity 400ms, visibility 400ms; + visibility: hidden; + opacity: 0; +} + +/* diagnostics */ +#diag-rc-output > pre, +#command-rc-output > pre, +[data-page="admin-services-wol"] .notice code { + font-size: 1.2rem; + font-size-adjust: .35; + line-height: normal; + display: block; + overflow-y: hidden; + width: 100%; + padding: 8.5px; + white-space: pre; + color: #eee; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +[data-page="admin-network-diagnostics"] .table { + box-shadow: none; +} + +input[name="ping"], +input[name="traceroute"], +input[name="nslookup"] { + width: 80%; +} + +/* fix Main Login */ + +.node-main-login { + text-align: center; + background-color: var(--bgwhite) !important; +} +.node-main-login .cbi-section-node > .cbi-value:nth-of-type(2n) { + background: none; +} +.node-main-login h2 { + font-size: 1.5rem; +} + +.node-main-login header { + display: none; +} +.node-main-login .navbar { + display: none; +} +.node-main-login > .main > .main-left { + display: none; +} + +.node-main-login > .main > .main-right { + width: 100%; +} + +.node-main-login > .main div.cbi-section { + /* padding: 0px !important; */ + margin-bottom: 1rem; + display: inline; + background: none; + border: none; + box-shadow: none; + overflow: hidden; +} + +.node-main-login > .main label.cbi-value-title { + display: none !important; +} + +.node-main-login > .main .cbi-section { + margin-top: 10px !important; +} + +.node-main-login > .main .cbi-map { +} + +.node-main-login > .main div.cbi-section .cbi-value { +} + +.node-main-login > .main div.cbi-section .cbi-value-title { + padding: 10px 0 10px 5px !important; +} + +.node-main-login > .main .cbi-value { + border: none; +} + +.node-main-login > .main .cbi-value-title { + width: 7rem; +} + +.node-main-login > .main #maincontent { + display: flex; + height: 100%; + text-align: center; + align-items: center; + align-content: center; + justify-content: center; +} + +/* .node-main-login > .main .container { + background-image: var(--logo); + background-repeat: no-repeat; + background-size: 300px auto; + width: 300px; + padding: 80px 0 0 0; +} */ + +.node-main-login > .main form > div:nth-last-child(1) { +} + + +.node-main-login > .main .cbi-value > * { + display: inline-block !important; +} + +/* .node-main-login > .main .cbi-input-user, +.node-main-login > .main .cbi-input-password { + min-width: 15rem; +} */ + +.node-main-login > .main .cbi-input-text { + min-width: 15rem; +} + +.node-main-login footer { + bottom: 0; + position: absolute; + width: 100%; +} + +/* fix system reboot */ + +.node-system-reboot > .main > .main-right p, +.node-system-reboot > .main > .main-right h3 { + margin-left: 12px; +} + +.node-main-login > .main .cbi-section { + margin-top: 10px !important; +} + +.node-main-login > .main .cbi-map { +} + +.node-main-login > .main div.cbi-section .cbi-value { +} + +.node-main-login > .main div.cbi-section .cbi-value-title { + padding: 10px 0 10px 5px !important; +} + +.node-main-login > .main .cbi-value { + border: none; +} + +.node-main-login > .main .cbi-value-title { + width: 7rem; +} + +.node-main-login > .main #maincontent { + display: flex; + height: 100%; + text-align: center; + align-items: center; + align-content: center; + justify-content: center; +} + +/* .node-main-login > .main .container { + background-image: var(--logo); + background-repeat: no-repeat; + background-size: 300px auto; + width: 300px; + padding: 80px 0 0 0; +} */ + +.node-main-login > .main form > div:nth-last-child(1) { +} + + +.node-main-login > .main .cbi-value > * { + display: inline-block !important; +} + +/* .node-main-login > .main .cbi-input-user, +.node-main-login > .main .cbi-input-password { + min-width: 15rem; +} */ + +.node-main-login > .main .cbi-input-text { + min-width: 15rem; +} + +.node-main-login footer { + bottom: 0; + position: absolute; + width: 100%; +} + + + +/* fix status */ +.node-status-overview > .main fieldset:nth-child(4) .td:nth-child(2), +.node-status-processes > .main .table .tr .td:nth-child(3) { + white-space: normal; +} + +/* fix system reboot */ +[data-page="admin-system-reboot"] p { + padding-left: 2rem; +} + +[data-page="admin-system-reboot"] p > span { + position: relative; + top: .1rem; + left: 1rem; +} + +/* samba */ +#cbi-samba [data-tab="template"] .cbi-value-field { + display: block; +} + +#cbi-samba [data-tab="template"] .cbi-value-title { + width: auto; + padding-bottom: .6rem; +} + +/* software */ +.controls > * > .btn:not([aria-label$="page"]) { + flex-grow: initial !important; + margin-top: .1rem; +} + +.controls > #pager > .btn[aria-label$="page"] { + font-size: 1.4rem; + font-weight: bold; +} + +.controls > * > label { + margin-bottom: .2rem; +} + +.control-group { + /* display: flex; */ + flex-wrap: wrap; + gap: 8px; +} + +[data-page="admin-system-opkg"] div.btn { + line-height: 3; + display: inline; + padding: .3rem .6rem; +} +/* +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent > .container { + margin-top: 2rem; + padding-top: .1rem; +} */ + +[data-page="admin-system-opkg"] #maincontent > .container { + margin: 2rem; + margin-bottom: 1rem; + border-radius: 8px; +} + +.td.version, +.td.size { + white-space: normal !important; + word-break: break-word; +} + +.cbi-tabmenu + .cbi-section { + margin-top: 0; +} + +/* wireless overview */ +#cbi-wireless > #wifi_assoclist_table > .tr { + box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; +} + +#cbi-wireless > #wifi_assoclist_table > .tr.placeholder > .td { + right: 33px; + bottom: 33px; + left: 33px; + border-top: thin solid #ddd !important; +} + +#cbi-wireless > #wifi_assoclist_table > .tr.table-titles { + box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; +} + +#cbi-wireless > #wifi_assoclist_table > .tr.table-titles > .th { + border-bottom: thin solid #ddd; + box-shadow: 0 -1px 0 0 #ddd; +} + +#wifi_assoclist_table > .tr > .td[data-title="RX Rate / TX Rate"] { + width: 23rem; +} + +/* firewall */ +#iptables { + margin: 0; +} + +.Firewall form { + margin: 2rem 2rem 0 0; + padding: 0; + box-shadow: none; +} + +#cbi-firewall-redirect table *, +#cbi-network-switch_vlan table *, +#cbi-firewall-zone table * { + font-size: small; +} + +#cbi-firewall-redirect table input[type="text"], +#cbi-network-switch_vlan table input[type="text"], +#cbi-firewall-zone table input[type="text"] { + width: 5rem; +} + +#cbi-firewall-redirect table select, +#cbi-network-switch_vlan table select, +#cbi-firewall-zone table select { + min-width: 3.5rem; +} + +#cbi-network-switch_vlan .th, +#cbi-network-switch_vlan .td { + flex-basis: 12%; +} + +#cbi-firewall-zone .table, +#cbi-network-switch_vlan .table { + display: block; +} + +#cbi-firewall-zone .td, +#cbi-network-switch_vlan .td { + width: 100%; +} + +/* applyreboot fix */ +#applyreboot-container { + margin: 2rem; +} + +#applyreboot-section { + line-height: 300%; + margin: 2rem; +} + +/* openvpn bug fix */ +.OpenVPN a { + line-height: initial !important; +} + +/* custom commands */ +.commandbox { + width: 24% !important; + margin: 10px 0 0 10px !important; + padding: .5rem 1rem; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); +} + +.commandbox h3 { + line-height: normal !important; + overflow: hidden; + margin: 6px 0 !important; + white-space: nowrap; + text-overflow: ellipsis; +} + +.commandbox div { + left: auto !important; +} + +.commandbox code { + position: absolute; + overflow: hidden; + max-width: 60%; + margin-left: 4px; + padding: 2px 3px; + white-space: nowrap; + text-overflow: ellipsis; +} + +.commandbox code:hover { + overflow-y: auto; + max-height: 50px; + white-space: normal; +} + +.commandbox p:first-of-type { + margin-top: -6px; +} + +.commandbox p:nth-of-type(2) { + margin-top: 2px; +} + +[data-page^="admin-system-commands"] .panel-title, +[data-page^="command-cfg"] .mobile-hide, +[data-page^="command-cfg"] .showSide { + display: none; +} + +#command-rc-output .alert-message { + line-height: 1.42857143; + position: absolute; + top: 40px; + right: 32px; + max-width: 40%; + margin: 0; + animation: anim-fade-in 1.5s forwards; + word-break: break-word; + opacity: 0; +} + +@keyframes anim-fade-in { + 100% { + opacity: 1; + } +} + +/* IE hacks */ +/* @media all and (-ms-high-contrast: none) { + .main > .main-left > .nav > .slide > .menu::before { + top: 30.25%; + } + + .main > .main-left > .nav > li:last-child::before { + top: 20%; + } + + .showSide::before { + top: -12px; + } +} */ + +@media screen and (max-width: 1280px) { + header { + /*height: 3.5rem;*/ + } + + header > .container { + /*margin-top: 0.25rem;*/ + } + + .main { + height: calc(100% - 3.5rem); + } + + .main-left { + width: calc(0% + 17rem); + top: 50px; + } + + .main-right { + width: calc(100% - 17rem); + } + + + table { + font-size: 0.9rem !important; + width: 100% !important; + } + + .main > .main-left > .nav > li, + .main > .main-left > .nav > li a, + .main > .main-left > .nav > .slide > .menu { + font-size: 1.1rem; + } + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: 1rem; + text-transform: capitalize; + } + + img[src*="/luci-static/resources/cbi/add.gif"] { + right: 55px; + display: block; + position: absolute; + margin-top: -34px; + } + img[src*="/luci-static/resources/cbi/remove.gif"] { + right: 55px; + display: block; + position: absolute; + margin-top: -34px; + } + + img[src*="/luci-static/resources/cbi/reload.gif"] { + right: 55px; + display: block; + position: absolute; + margin-top: -34px; + } + /* fix nlbw component */ + #detail-bubble { + /* left: unset !important; */ + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: 19rem !important; + width: calc(100vw - 21.25rem)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + } + #detail-bubble #bubble-table { + display: inline-table; + overflow: auto; + } + .node-nlbw-usage table { + display: block; + overflow: auto; + } +} + +@media screen and (max-width: 992px) { + + /* img[src*="/images/logo.png"] { + background-color: var(--mainleftbgColor); + height: 50px; + background-image: var(--mlogo); + background-size: 310px; + background-repeat: no-repeat; + padding: 0 0 0 310px; + width: 0; + margin: 0; + background-position: 0; + } */ + + .main-left { + width: 17rem; + position: fixed; + z-index: 100; + } + + .main-right { + width: 100%; + } + + .showSide { + margin: 0; + padding: 0; + display: inline-block; + position: absolute; + width: 300px; + height: 50px; + padding: 17px 27px; + } + + .showSide:before { + content: "\e20e"; + font-size: 1.7rem; + font-family: 'icomoon'; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + #maincontent > .container { + margin: 20px 20px; + } + + .node-main-login .showSide { + display: none !important; + } + + .cbi-value-title { + width:35%; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div * { + width: 100% !important; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div input[type="text"] { + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div:nth-child(4) input[type="text"] { + margin: 0 !important; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div select, + .node-network-diagnostics > .main .cbi-map div.cbi-section > div input[type="button"] { + margin: 1rem 0 0 0; + } + + .node-network-diagnostics > .main .cbi-map div.cbi-section > div { + width: 100% !important; + } + + .node-main-login > .main .cbi-value-title { + text-align: left; + } + + img[src*="/luci-static/resources/cbi/add.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + img[src*="/luci-static/resources/cbi/remove.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + + img[src*="/luci-static/resources/cbi/reload.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: inline-table; + overflow: auto; + } +} + +@media screen and (max-width: 700px) { + + #cbi-vssr-servers .cbi-button-add { + position: static !important; + width: auto !important; + height: 2rem !important; + line-height: 2rem !important; + color: #fff; + display: block; + padding: 0 !important; + font-size: 0.92rem; + border-radius: 10px !important; + box-shadow: none ; + background-image: none; + } + #cbi-vssr-servers .cbi-section-table-row { + margin:10px 0 !important; + } + #cbi-vssr-servers .p-in5 { + padding-bottom: 10px !important; + margin: 0 !important; + } + + #cbi-vssr-servers .cbi-page-actions { + padding-bottom: 10px !important; + } + + #maincontent > .container { + margin: 20px 20px; + } + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: inline-table; + overflow: auto; + } +} + +@media screen and (max-width: 470px) { + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: block; + overflow: auto; + } + .node-admin-status-routes #view table, + .node-admin-status-processes #view table, + .node-admin-status-realtime-connections #view table[id*=connections] { + display: block; + white-space: nowrap; + } + +} + + +@media screen and (max-width: 400px) { + .node-admin-status-overview .cbi-section.fade-in:first-child table:first-child td:first-child { + width: 40%; + } +} + +@media screen and (max-width: 370px) { + + div.cbi-section { + /* overflow-x: auto; */ + } + + select { + width: 100%; + } + .label { + position: absolute; + right: 5px; + top: -70px; + } + + header { + height: 55px; + } + + h3 { + padding: 0 10px 10px 10px; + } + + /* img[src*="/images/logo.png"] + { + height: 45px; + background-image: var(--mlogo); + background-size: 310px; + background-repeat: no-repeat; + padding: 0 0 0 310px; + width: 0; + margin: 0; + background-position: 0; + } */ + + .showSide { + height: 45px; + } + + #maincontent > .container { + margin: 20px 20px; + } + + .main { + top: 45px; + } + + .main-left{ + top: 45px; + } + .main > .main-left > .nav > .slide > .menu { + } + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + } + + .cbi-value { + margin-bottom: 20px; + display: table; + padding: 0px; + border-bottom: none; + } + + .cbi-value-title { + width: 100%; + font-weight: 700; + float: left; + padding: 0; + margin: 0; + margin-bottom: .25rem; + } + + .cbi-section-node { + padding: 10px !important; + } + + .cbi-value-description { + width: 100%; + display: block; + } + + .cbi-value > .cbi-value-field { + display: block; + float: left; + width: 100%; + } + img[src*="/luci-static/resources/cbi/add.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + img[src*="/luci-static/resources/cbi/remove.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + + img[src*="/luci-static/resources/cbi/reload.gif"] { + right: 45px; + display: block; + position: absolute; + margin-top: -34px; + } + .cbi-section-node > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor); + } + + .cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor); + } + + div > .cbi-value:nth-of-type(2n) { + background-color: var(--sectionbgColor); + } + + .node-main-login > .main .cbi-value { + padding: 0; + } + + .node-main-login > .main form > div:nth-last-child(1) { + margin-top: 2rem; + } + + .node-main-login > .main div.cbi-section { + margin: 0; + padding: 0.5rem; + } + + #container\.network\.lan\.physical .cbi-value-title, + #cbi-network-1-_ifname .cbi-value-title + { + width: 35%; + } + #cbi-network-1-_ifname .cbi-value-field + { + width: 65%; + } + + + h2 { + font-size: 1.2rem; + text-transform: capitalize; + } + + select, + input { + /* max-width: 200px; */ + } + + input[type='checkbox'] { + height: 1.2rem !important; + width: 1.2rem !important; + } + + #swaptotal div div small, + #swapfree div div small, + #swapcache div div small, + #memfree div div small, + #membuff div div small, + #conns div div small, + #memcache div div small, + #memtotal div div small{ + } + #swaptotal div div, + #swapfree div div, + #swapcache div div, + #memfree div div, + #membuff div div, + #conns div div, + #memcache div div, + #memtotal div div{ + } + + + .node-status-iptables > .main div > .cbi-map > form input[type="submit"]{ + margin: 0; + } + + #cbi-samba-cfg010f89-_tmpl .cbi-value-title{ + width: 15%; + + } + #cbi-samba-cfg010f89-_tmpl .cbi-value-field{ + width: 95%; + } + /* fix nlbw component */ + #detail-bubble { + left: unset !important; + width: unset!important; + } + #detail-bubble.in { + color: #000; + padding-bottom: calc(60px + env(safe-area-inset-bottom)); + left: unset !important; + width: calc(100vw)!important; + } + #detail-bubble .head { + display: block; + overflow: auto; + /* text-align: unset !important; */ + } + #detail-bubble #bubble-table { + display: block; + overflow: auto; + } + .node-admin-status-routes #view table, + .node-admin-status-processes #view table, + .node-admin-status-realtime-connections #view table[id*=connections] { + display: block; + } + .node-admin-status-overview .cbi-section.fade-in:first-child table:first-child td:first-child { + width: 43%; + } +} + + +.navbar { + z-index: 200; + overflow: hidden; + position: fixed; + bottom: 0; + width: 100%; + border-top: var(--navBorder); + text-align: center; + height:calc(50px + constant(safe-area-inset-bottom)); + height:calc(50px + env(safe-area-inset-bottom)); + background-color: var(--navbgColor); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + } + + .navbar a { + float: left; + text-align: center; + padding: 8px 0; + width: 20%; + text-decoration: none; + max-width: 100px; + } + + .navbar a img { + width: 28px; + } + + .cbi-input-apply, + .cbi-button-apply, + .cbi-button.cbi-button-positive, + .cbi-button-edit { + color: #fff !important; + background-color: var(--activeColor); + } + +td.cbi-button, .cbi-button-apply, +.right .cbi-button { + font-size: 0.92rem; + font-family: -apple-system, 'Microsoft Yahei', sans-serif, Helvetica, Arial, sans-serif; + border: var(--inputBorder); + transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + -webkit-transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + outline-style: none; + vertical-align: middle; + border-radius: 8px; + max-width: 550px; +} +/* fix iptables */ +.node-admin-status-iptables .right { + padding: 12px; + border-radius: 8px; + box-shadow: 3px 3px 3px rgb(0 0 0 / 5%); + /* background-color: var(--bgwhite); */ +} + +.node-admin-status-iptables h3 { + padding: 0; + padding-top: 10px; + padding-bottom: 10px; +} + +/* fix routes */ +.node-admin-status-routes #view p { + padding: 5px 5px 5px 12px; +} + +.node-admin-status-routes #view h3 { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + margin: 0; + margin-bottom: 0; + padding: 0.8755rem 1.25rem; + color: var(--gray-dark); + border-radius: 0.375rem; + padding-bottom: unset; + font-weight: bold; +} + +/* fix tables */ +.node-admin-status-routes #view table, +.node-admin-status-processes #view table, +.node-admin-status-realtime-connections #view table[id*=connections] { + /* margin: 10px 0 0 0; */ + padding: 10px; + border: 1px; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + text-align: left; + min-width: inherit; + overflow-x: auto; + overflow-y: hidden; + background-color: var(--sectionbgColor); + /* box-shadow: var(--sectionShaddow); */ + -webkit-overflow-scrolling: touch; + border: var(--sectionBorder); + margin-bottom: 20px; + border-radius: 8px; + margin-top: 5px; + /* display: block; */ +} + +.node-admin-status-realtime-connections #view table[id*=connections] { + white-space: nowrap; +} + +/* fix node-admin-status-processe */ +.node-admin-status-processe button.btn.cbi-button-action { + color: var(--bttextColor); + background-color: rgb(0,171,232) !important; + border-color: rgb(0,171,232) !important; +} + +/* fix node-admin-system-opkg cbi-button-positive */ +.node-admin-system-opkg button.btn.cbi-button-positive { + color: var(--bttextColor); + background-color: var(--activeColor) !important; + border-color: var(--activeColor) !important; +} + +.node-admin-status-processe, button.btn.cbi-button-negative { + color: #fff !important; + background-color: #617486 !important; +} + +/* fix node-admin-status-realtime-load */ +.node-admin-status-realtime-load #view div, +.node-admin-status-realtime-bandwidth #view div, +.node-admin-status-realtime-connections #view div{ + border: var(--sectionBorder) !important; + font-family: -apple-system; + background: none !important; +} + +/* fix */ +.cbi-dropdown.btn.cbi-button.cbi-button-apply.important, +.cbi-dropdown.btn.cbi-button.cbi-button-negative.important { + line-height: unset; + min-width: 105px; + padding-left: 5px; +} +.cbi-dropdown.btn.cbi-button.cbi-button-action { + line-height: unset; + min-width: 110px; + padding-left: 5px; +} + +.node-admin-system-ttyd-ttyd iframe { + border-radius: 5px !important; +} + +/* fix node-admin-status-realtime-load */ +.node-admin-status-realtime-load table { + table-layout: auto !important; +} +.node-admin-status-realtime-load table > tr > td { + text-align: left !important; + padding: 10px 3px 10px 3px; + white-space: nowrap; +} +/* fix node-admin-status-realtime-bandwidth */ +.node-admin-status-realtime-bandwidth table { + table-layout: auto !important; +} +.node-admin-status-realtime-bandwidth table > tr > td { + text-align: left !important; + padding: 10px 3px 10px 3px; + white-space: nowrap; +} + +/* fix node-admin-status-overview color */ +.node-admin-status-overview h3 { + color: unset !important; +} +/* fix node-admin-status-overview */ +.node-admin-status-overview > .main #view td:nth-child(2) { + white-space: normal; +} diff --git a/luci-theme-design/htdocs/luci-static/design/favicon.png b/luci-theme-design/htdocs/luci-static/design/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7c3f3acb1f0c7c142d0dbd3f42a4926b07f8eb38 GIT binary patch literal 535 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 V3WJ?~+oQUz`(G^Om}Gzc`+o(J82JDI literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/fonts/font.eot b/luci-theme-design/htdocs/luci-static/design/fonts/font.eot new file mode 100644 index 0000000000000000000000000000000000000000..9e6ffc9b826cb39a58e56359d6b8b922a4b07364 GIT binary patch literal 1912 zcmah~Ur1Y582`?_x%Vc~T>r!*OpT4P8o`m;m_K$==`c84Z6{8{+A(HKZlhvuY>cgr zKFA)%(1*FfM*FnUZZIZ{J&ZBvpfZF#Y)@lIVSRG2hwi1Y4#u`F`<;8QXe6-ja?bgE zzwN>ij! zo>pmzGE@TNr8Jlltw75)0Xj=z>Nm6}M}y=6>u7^S>VN6wGm(a7S2vh%P-e4*%<|74 z-T45bcKGFdW@Q;|Bm8Z&_WaWN)fd`ZeusaHNO&->WpYaP$#+CHu8YruP`(wvhyN-3 z)ANP$nqL?8;r{@?cd3}o2=nYs_)p+_3z@ZLe9%0RR1ZI(XA0Ww7af1Ye-<&`S}v}X zF;AHMCGRIuyn~rYh<#h&Z+ypW*>5z!99(zI7^Yoq=ZPL)7I!PVbY4V3=V9`>F2E}z z8jskHKC=}KRXf?}74Xf-hKS{56ga3mP!HbyReXH8^0ZRngTXngI9B<^|Cj$y|Mga> z;R}pA9?uwniV?%;hGTu$Jc)CL^hp0d9A5GarZvNJ<6ufi3Gpco?d=T-GZmvH1`UH| zm}{8N!4f`UZ>U1NTNno5ddx?}-q;a0gdKdb1FJ*sPETj7DTdm^s|}H!LSzj^@e}6Xo3K zXf!%Jyy+jD4Tn>yMB=%*RO-r=RBGa)o-oe4%#d}+m|4=Q~$QQ44QKuG~z>i4Xv1q8Lj|COk&su!m zB#R{CF*mpnCZx!x7-pM@8!0(V$8jZ+b@ar1M!vd&d^FFaIShFeNRsTjU4j|Sd#3{Z zXChnUcGm@);*d_c-5qUSPhEZ6>5dLdQtxVZJDg384u_&VOeQt$##&BG!nEAl4Grj% zf?bkj$zHI_k|f*NMx?LL=UZ2u=WI$ybv3ANugm3X>D=4hK9vL(>`jZV6X?ab{kvf)^jN}pSC8R2xdumC)3 zVG%fPVH@zOg(aM_9t+FhFId=#{kw^X%;o^2qQ}GnaNfcq@UVq#z&9-{;jj-_SO!03 zVJAiDPgt_+pY=D^L-I_h!b%DZS?d0}MTT%Y6XQicBm D*A6pu literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/fonts/font.svg b/luci-theme-design/htdocs/luci-static/design/fonts/font.svg new file mode 100644 index 000000000..d38d057da --- /dev/null +++ b/luci-theme-design/htdocs/luci-static/design/fonts/font.svg @@ -0,0 +1,16 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + \ No newline at end of file diff --git a/luci-theme-design/htdocs/luci-static/design/fonts/font.ttf b/luci-theme-design/htdocs/luci-static/design/fonts/font.ttf new file mode 100644 index 0000000000000000000000000000000000000000..84669323e9ddfdca80c91416b6d4fe31ea1829ab GIT binary patch literal 1748 zcmah}U1%d!6h3n&Gn1cY`jbCwn>0i)RYHn=Nd(_}VjX(rt? z-ECzbiVq^~gR7wIJ}Ik$SP&mXgcU4O@Ijw^C=2dW1t0Wf!4*VZ<9BDKw5tWraPR%j zch0@%%sF?41R`?L28k4Z?)j66)(&?+m@hHriq*pM5AWT1he+s#-Y6GVma(=$zlqge zURuBMOt<$}=(mX2y^2;SDaD815ZSn2x&lJ^TKpFJN6=4Hs*Sav&i0^x2YqmLYKX+Z zh4)?i>i(NQi4QI{A2plC?(n|zF-~ay82lsnd+=JP)cPs*9gSyfz$B1>-K|G#j3{&3 za6R<@9}b5+fwX3MZ5)CURiZq_(cRrqHrq5-65u1iXN>y@0f&$Yu-(xnaWfkO;Qq)* z#NF5yH`q4b*n#elr`Ok;YENPI@o7V(M{qI++s^0z-kX`(%jfy~2$ZLw_^~)dT}1uS z0rN>EGwI<(fDgaVtH^j5jW5RI*{t6`F;QxqJJ%>pOeB+IW1GQ|xmYZh%VeIK&*d&( z&gJGW%*>3B-$2WWnmaZ^=Q=5cP!W|W1*=Ev4Ne;?! z)Dy)zd{P0UUVRb1o7d6YhB`8mB)e{xAja}mPdI)uu{C9PpS39tsmJ39b@_d+maY?_ zkmb_i?(jIA?QIT+qTJ7BHSPLZNy|dC(%N+m=)h}3M^?w~_ggCg@Q$N?gdbxG{B zx-Tq&<|jJo3a&GkgUE(rO)7n2#T7^aXXe0w=PWD&r!8y)UbV1p!rv)lfjj9+m((_t< zWuc~rPsQT+HZ`i#3LId-Ij1N_@nd%#OHOO$)ulomK{X`0N=sCr`mvsqHN6ooYr0l1 zG_+E9emy)@ter=0F`6`DHxRvyV{{{<0yVIfz|GS-<|*R^&YLfQ9MQz1E%`702g#=) A_5c6? literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/fonts/font.woff b/luci-theme-design/htdocs/luci-static/design/fonts/font.woff new file mode 100644 index 0000000000000000000000000000000000000000..00cf84ea037c9748eba8fced0acff7dd29c12b2f GIT binary patch literal 1824 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 OE|tT7jotRy*!aH&>CNE) literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/fonts/iconfont-Regular.woff b/luci-theme-design/htdocs/luci-static/design/fonts/iconfont-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..45714f9e963de69ca8e3754650e4b7be8565336b GIT binary patch literal 6372 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

      B9A(_Qo~iMyYH-;0SpLS4Dx z=)A+B{C_x-_XjWX@cX=G#iEA`o>~jvl$>nhTgC)}5K#WHOOys7W$b)6glt)0r?=#mJ+ArlVNGtyIr^9Mb49Z}%@NR| z`Ewsq%RY3ca$BbYJxJ(*T)#j6q6t*b_tU>%e^)v+pTsV1gG%a>nr9{fOP$zd{<60C z=w<#1>y@eSFbo}Y=z1M0`Tlo=yVLIeQ(XIHm-)n+S&^3~gcFw|XRSG*L;vKr6TZ7o zruO59g->0vp5R|T8vXRnL^v*d;?AcUL0MYU89W@%DXrCz=#9*0Shc#ijg?*-^f845 zyO%Y+Fu{=%Q`EU5P!S?8vz<_w^*4A`ZmhhA*2+NUd%yoECL=mJBL>N8^YUrVYsqin zA}|ERVsg`f8xM#6-dz1t0O1Y$p_ZbF(CsuMQ`9qOYACvhol;E+0eKPWJ2D?$qj|)B zLkRe(dUL5hYJWyHr4?^q5hk^cmT9j^@h$t;8<5vh4 zG*`@=C9bFtRZAKdmO8pC%9HC*oA}Gc6Sj(|uCx*n`}Kyr`W_y_0-;8|h~Z9pl6>0?7<=4l#M`sO7${z#;S(6yX}- z-$wL4tuloIuGp~HFX}F@InlZ^N{ooiI9*hl7LHb3_e2%$AZy{LG0 zE#I1CG9_90wbnfLao36VVZF2)$h$3ggdbga^`iRs$!R^r7l9FaAX7+~E`weX<;*xhGONdUc zXy*%FRg+Ec7v$F>O;x-XJ4IY)QjWYUx{2S4hWn`-*kBlNctJZ5lu(mFX!b3)w{g$mn+cnmE3~$GC>#ZcnrBnlya_Ha|92C&&0g+HXjYX6 zXvd|_KXm=In|_}kJ|Zmd#((6B=~^i0(bO+Y?utonYj2LN4y#_2lCt93g|R?<;1>K) zTsv_~wDmgkJw4Gco-Wb1+i!n!lq7T@b%-O0YChy=$HaNaFC~#U1kXGOOw?tz`zNhy zPv3teBt5g6Obd5qWa5Q{Ac8mk;Hj3|^<+AgCZruX(;fstt{tuj+PZGnkz)y&dKZ~a zZg;Pnu*!|ZclO<=sI~G0%DcNp7Vp- zjydA-k9sT%XnlxXR5gzeRNqb&AN6MPc2QhPBd`|H!5Ja3Rf)Y?IF8|APLfGTHRx ziF%#weZ4pF(dD^!SGL{64M7zsIV!3fo|HHlJtT&hMl)GJ0Cc6+9FxgQ*GFeWA24tc z0+MEJs=)}pg=V6O8KfSc6klzVM$@Ph_Dl^w<;{r`lZ|AjmEt%+eF{(ReL|s%y0d^!X?Pds^llmk5<1L_Bi>AFjw~MG{sXzYZPTs1*dU^L2Xpt^kU1OJ@OhwH$Y~9Do()X(c)co-0F;ooF=D@r;?LRQ^`J-yO~79Iw8CT2i_h?JG7kFS%1%nrB^TNh50ML)T&$czQmp z`|8o-N6n9x4q0a&^KJ&c#O?}FhlnEjQnX6kQQ0B>dK|ii-0J!>I| z%zya(3;cWkGUEB*k%pO&Z2%}iG_8L-c_rRZVYv2n@KZ)?r5{H>%o8{Vs&7Ju=L2Z0 z_gR5^fUb#SP{Au8M@w%%wqbwnN9X~+pFjsT;4RtXo$TcLWiWt>lk>ix!4*u@=V1ep z2x_PYJ5)lW3~B=^RKcP#>!2Fu!CY`4PX!XzKoiWa&R;L#Nx`JZb#8#VY$_x{JS09J z?d8cpr&Oh)$#ObwPXMtVB@3oVk+NbrIHj14>ji(XU&CY&fh0nX3Bx$3g1Tx--$iq6 z{`wq-4bTiVJE?Ic2a%(0=RBAL)HuO3d!>1(n9rw~MAf;fc&G(UOiv04>qQ)(BjQVE O!yG`u)9eiZ0000e-eD{N literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/add.png b/luci-theme-design/htdocs/luci-static/design/images/add.png new file mode 100644 index 0000000000000000000000000000000000000000..9f53666d48ee561dfdde568ed4045e3a5d654691 GIT binary patch literal 3163 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 K+cN8)WBvnpm49gf literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/bridge_disabled.png b/luci-theme-design/htdocs/luci-static/design/images/bridge_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..c603b970e22c1a474ee0060255939ee380374ce8 GIT binary patch literal 4306 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/ethernet_disabled.png b/luci-theme-design/htdocs/luci-static/design/images/ethernet_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..6624680987b972049f8966d701f073cf3b690a66 GIT binary patch literal 2023 zcmaJ?3s4hR6b%8C5vA0zh={mEQ3R9S1cGcNKSCn0gwlY5Q$d#O0z0_7A=#LKR!Ox| zMUlcdMFnjY@l%U3Dq843{qQSR$4|vUovLX;M-&7ir<9tV%xem*OraC0OxlbXFqRypGB7|*AX%6e zL(sh3b}Wj;a-E4MrO+vwIFXJbc!)iRXCd?qn#GEeTJ(r62cv-uEDI;aoW6!84uGR# zPO?w~Y4i##8;{L5V2SzhNxJ+T9gK3M5+KSVVhRu#jQ|#6IcXGG#GK)}BIes3206fR z3Y{b7jF3vvBmfG^fC2M(e69|HAYdNMLy-(bmyt0S5I_Px2!(_Ea4rOi!eCK&IN-QA z%ytGeQ>2YiIW}WfVoo+q>qQ`FHk*0oFdk*d0{JiugOC6e2)IlJ*O*7rh=ofUXE-aw zU`Cw**V8yf0``hX24$kf9ER$M212jVj20%14yPE;KntP=`8)_D2)nT1Y$L73-q3h& zwlOJBkAYguNSO>erXiU#oM6Vh4{u~oWY~yeD4mJGNLn2u<}eW+ilZWVj4E0VL*YV| z9OCnp3b~3Op%O+ag^)5r0Y}brV%4OPMo1mz#NuzTVIRbb6b1~TDMJ!PEqAsrA)BHp zV>YD+1OlEA2u{XHlrkIV*u8a7#SHig3{@E@0vI+&gujP?a$bZ2ij+eULgg@dSPq9p zt0I(w$Y>Z=2?QJm7JZL!2bTZ8SdbwD+B^GJr=1~YeC(g2gUc*NM;{}Zc{ebF{jK}h zV=R{25_OC`$%+PC21MIV=7w+fdjzE}YVYP=f~%D(1-rka-cyZj~#cFj71 z-fB;;J3uUYfP5WPk5?ByJNPQ(MLPe?tk z7RXr4Jra6+A^3@BltfbfauD~obj&(0CrL7XYMTr1%#Ffr&C)ZHB8Vv82bmvTSbH-= zbNc19OrDoyNMj1_}o8l3My;(fv8=v7-?*%oB2;br#9@EEUlyIX;r1GIk0oDnX}I#ZcD7l zvkit@midA~(}nTV+SZ&{8rr!_GWZ`o-X2b_Y-@n%@B8xZ&6DFEt-RiSE)5cT8o}|B zq2K9?FJBn0@1_D5c`xgy>fQ}FIBR3@$#aykdo`r zcQv8gmbM6m<+9A0IgEbU-A_Cz}%qqJbxsdVE-fX)Qqi&4!Uj`J& z(sz9x)CzkYJ=ZVPa)&+7&IR-J{+^$<_;|k4B=1-s>CHc`oUC5xK5)z4$B<9jLe5B+0~6?!%AMcOFAOWS zeOcR$G@cCoabVS~p67eitIF>CTQ`Z9U(bA!G%!D*E5rJMla)~1xpwZ3!RP5ONT4Sd zxwq2I#X9NfW!Pig3323DYk%FMa-zAliJ183SsC#1ys5nIw2idY&M4W_cl&TiQPt+w z-sgp~jmm*JWOCQe!rG0kA;qqnZn&$9`f@7p%T3R=cbyG9#T@d7?nj#0qbGXAv$syc d{#Ge_JWJQGv-+%J!8QA@SFMbXsfkYi>R+m);FkaZ literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/home.png b/luci-theme-design/htdocs/luci-static/design/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e900a93775cbac3af5d625636c37f9b4091f55 GIT binary patch literal 7725 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/icon.png b/luci-theme-design/htdocs/luci-static/design/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..aa990fa4366b6d076a796ffe7a64de5a3c17049a GIT binary patch literal 7473 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 HGwpu>oHS;I literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/link.png b/luci-theme-design/htdocs/luci-static/design/images/link.png new file mode 100644 index 0000000000000000000000000000000000000000..e5307d9bcced3c2c42e94ea5c37591f7be65608f GIT binary patch literal 12758 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 CBd5&( literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/openclash.png b/luci-theme-design/htdocs/luci-static/design/images/openclash.png new file mode 100644 index 0000000000000000000000000000000000000000..8aed32abd05f9e6d6f1178f4a061d238563f0d1f GIT binary patch literal 34578 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/port_down.png b/luci-theme-design/htdocs/luci-static/design/images/port_down.png new file mode 100644 index 0000000000000000000000000000000000000000..7e9edacba5ebba13576c3859f3cdb764aea49092 GIT binary patch literal 3608 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/port_up.png b/luci-theme-design/htdocs/luci-static/design/images/port_up.png new file mode 100644 index 0000000000000000000000000000000000000000..f093102d2e33ee59a2dccda0345deda282260a2a GIT binary patch literal 3702 zcmc&%3s6&M7EZc|%Ckx-LMg<6^-=P=%g97&@&x=|0Ew!3Hs zjb^{X5EW~QRV|fhF%ug`Fb&F1G2uX(Mhlju;IK9UwJv|KKiAriAiun2|%g#iqR3-LJIAPx^=ak&ymAc44y@gEbI zBM_ZrnPTy{F)))d^%e^*;c%>0E87~##)xCTJ=LH< zNiAW(Ee6cYpfti7EXg8e0;pp?nD7a;W^z1EAYz;p80YZVT*{|WK}0(thbIxnQR9e~ zgBnp2YPOI-mNy}b>oE&P>amxop4k400T5f2YQn|~v6xH~CP+(2GH_!&ATN|Aqf&8{ zvkWD%BtnaZBmsT-4~Ha@SF zLWKa0LXAeCK@o%{;BrMQ5ueXv!F(;k;v<0&D$w!;5Cl=QA7zpx%s_%1r;ZoWax`&# zWHc~F$s>WaR8dHoT8a%Q!W>^VydWOG$nyAks~!bPU%`?w>m;VLSYZNP7!P9iS{8C% z3LY~jqr`LYahQNXGeQYc%G42ud(V&GXUpdKUWW2;Dvcs@ojAx{JsT~qdeszd` z8D++Ne@Td*RmcAlqVe!+^{_b}1+ARJq@3YUJ#Q@eoS*Yzbnm(T_*5J;U1~Vd?!jc@ z!a&VHH36=J2)|Fa&}frSDisT(Qi|?&v?Q)<^E};^@9ADMy})59wsYSthm%cq2@Bop z-wpd`jqQVbUU75Wr>w9qEVKJ-woAdJYuiHm6qEERFC;mf-cyes zXVAPJ8Elhi>*v<7-j;a1CHr;2083Lf0| zD7=`ISK{Bc%Vk5jRry0@ciQ~!ox{V!b7c#Z1P}RYOHPv0H>Nz_ypEy=bzO;-OAf30 z@0cr2%dp69VPeOIPpNwe)x?kU~F zd5x8u-J80>3ry~JI1XL9TvWC_KN}+kZ~5XrojrJadzQ^{Z_}(UUUcub;(0-#R%Pa+ zRYyOqpY?fc?d8hmuIYV5Pg0X_>1KESv1a&S^SV|wOIRYB_P#zbqvObtPgnrdI(OHc zMTHj=dz&>M7up(%+eUWXAo{y%zPP(<{Yc;Pz8ypV7%trGe)M<~?CL5CrrZ#AmeKB- zx2LD>7l+5j4?GCCr^@Z^{=8PwSz75Ob}MMQ_}x4A{vHuKG9%cvp!K{|8W7u1zH!Zt z-IJYw-7E5K!LZaf$Zj(_TrV z(?=>iYI3SNS#1Y<)+lmDBYn1_t+t#z`G4Ue;C+g4;0@hTRez=}q^Ks@HtDU)%~jcM zLo*xCb!;uDTkg_2e3f{-&KAOLHdl1^Oj9HrimN)~=KS%JMZZ(M{GPS>T3b{C?-c+d z|0%CzOM}sR_F?iFI-uoyjpzOn`0Yro$D5@FY0HCm{FVQ5%X*^9%Xe!Ddn6ll%HQ~# z_LNuP_81r#*yTEORK^~jSR&27){U$w_Ao^;22-dpWs^~>Gn(3(jNho{NG z>f_JEHNm;xC+2UgncMNv3}{~Lm4#$>sxj2bb9(7jqAH?4xjsOBth_4 z=zly`yy=tc)~Rb7ssi-oElx2@>vEC;4lj{^_e0u)Tl17`TW@c%FOk^SSPgP#Rhr-P zbt!63E?+e=*eBbrZ!9{PpE@l+_q=XzUFV)t##)KbY}prly!DB&Vc#`Om+|3$K;J#P z?MwR;XSM>^dr10`>O@QVs)K$jaN8R1f!n1z*J$Pnyr-EN-MCFQ>yaPegru?3Ki`c# zc@P@*w#AvMZ*27)j+iP-{CDxgn<-guH<=1=3|I8VWqe;69$Q_0sWkJC{ZRNy?u7-L zHZ95;YR9}UkEKSp_Awx``y8xf?el0C_o ue`?8qkE)Co-c{<8KpV{ZRjG`XBj037yoJp)w>~abS^p!+!yj@^C2t literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/rank.png b/luci-theme-design/htdocs/luci-static/design/images/rank.png new file mode 100644 index 0000000000000000000000000000000000000000..eccc5c10538b8254649218fdba2beb80cc00db8d GIT binary patch literal 3503 zcmd51MvYRmic4gSZbdLp!Xv>5c~N2ol&4gz43i1OG!K%2gvTn4Qd;rV z^;qI63R_!sMX~jfMZjngA4}A@B3MNMp%@XdDg}{OClYY~uwB{Xp6;BPGjs2`zk7e* zeSBZ?`Lc-jC*x+}005XQ4C6-ufL*usahZT=YU`UeVlQ`8umX)%h*1rsLI93Pk&J*s z8I*!VA&@9D?GmyG036J9gfC^m3KtKL~LTbUpO^f$wN{lVOc69Ix8Xu&XU4R5ixi%xJb*w9LNw90=2S_H> zg?(Gq6e9T21eLOhBcxV@F9UfB6#@p3X(X6RrGf!WvIt6s;N;|mAe~C5QK$?GjX|PP zS-wmbg8|wuA{I_160@TCp|)U{#3rVqsFFpYXfztK#+R&6rBG;0CX+&?Q|NROWOc@?N=2)(_WeUp~MGGk@G%}SU zlUWz`(prs1A+Kn>)><8tsYEDIh+2`Zg0X^#=Z=E0oM`Z@^m;s@oe*U9ap zR0xDBR51$0$D`$2ma0G%>Qsdiq|?cMpjS8qOXOC~0&8|{WD%7l0}+L)6f*E-dRUUz zP{2s~bC{tReTKkFpUG!ZIRd6XmqGUr4d8N#HmvA1OSfSKzlx<`WGL3!{#&g_RagUA zKgU`Z6ULe!kz*aN!diPuQ0X540Ou*>b7Hi&I&WWF-WoS87y2U2t_!?{ubf_bAW7(? zpJ61gwA*Lje1j6=9O0DVeTLACHsg06QeFy4I`;0#BMTq&i?3`bB;12n8t3i$>auvd z9q_29U^;UNSfC~!%E!O*$JfgD6Vgnw?Q@LJoqAX3H z>CyiVntOhS;f81O#e+va>;L1*ykZ9i;sLke)V)4Ew*y^RAy4%aw-w=7Aq6`OKa`c0 zoIJ4gFvn~c-t+oG?1#nqfyFqID?8((m?zS&+`m+{1i+C1OhthZvmL;3w%%j1O*JCFGQs3AleY~4XRbI~ z|1>Z!b^s=b-BV-)K)2T7>Y2~n9Q^Dwy(0h;-@}_H85)~x70S~O*Lj&_jSc1LfXjDuKI9q0V}t7KT2#r5z02;08XSU zfo50@a1`Z-OeyW@KHu%%$^fQzf7r&|ZpxbuxSYBem}wtkUS~P?0eG-14jX~~xFP0_ zt5>djmtsk)`FilvoyHHGr*_Y}r>k-pZ+DJ1bma*bbzSrCF<)fXD$XNa*mt0?94JZBx=Z*>ve09wq+Ki)qDOT)yw`xX)$ z32T(eP8oO|{!woYuG7PjaEoHF4|3+@_xO~axq{8EZ5H0R*NbJ?pdCKC@%n~Ec+hfY zOILNGe|JS~Q+CUO-0Jo(gT}pejW);Vo;#kY|4-ZU|8$#vGoo+1^WH4#uTH4-lzY94 zpFACWQqOsr8fP77W|#^;U8|7~9wi<`7b~Ta z#;W+^KXw054sWWO_@X5t>(1?LfluV#qM-BGp6}Vd)97nCE+!2R4_}W?z0c0RYq#R7lX#2L5&rUGK6EYVT?xbA&Ixvm(u>T#$!3V`p z?#!yZ=22V(oKmJ9e!SDjb?vs0@jq8yJ2le?FE1mtUm*NBk?i4NbYi!-AD@v|B$tvp zPSjK$ivLct^Y-@{-WH)lTm8+hIB0Qiv*QD1$LYS)6$uyMA$rJOUqgQHleqy>(-OD`q=a5SLucp!{%EFjR~HQm8GrOKSt*~4s;*rJKgn>N8zJ~g!gw{ z{-)6SOCWA=zCgcRUs8Da&^C%w=c?)%W$qv4=d{f0TlH07d2A)F@0nCA-F}I0w#&`< me>)(tGkLtna`U3#uM4x|kL literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/reload.png b/luci-theme-design/htdocs/luci-static/design/images/reload.png new file mode 100644 index 0000000000000000000000000000000000000000..1cff5fed8107b61ac7ec89674c0ede1076dce266 GIT binary patch literal 4152 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/remove.png b/luci-theme-design/htdocs/luci-static/design/images/remove.png new file mode 100644 index 0000000000000000000000000000000000000000..fce54d92aa3213c69f1da846059fb8531325ddbe GIT binary patch literal 3404 zcmaJ^2UJtp7L7D%LO`j4K9ZoIffNFg7|N4G2^gdo9f6R94uK?8K_PJzl@dY`kfO9N zf`Hh*3RZ+r6?6ndP!SXrMk$J-3_m#H{I&f4x7NGo-m~`J=iGD8U2nZ3jt)Ck$!p6) zAdpoQTavTbik4nk8S!}5v$j}lw76tXt_#bb8$)9=As~b0#{?*0v;d|vlg5aPY-183 z5J^Okt0&i!x|2X>g&EV9FvhWA5n?t3LbQsFpwUB^T)>YR5EO0!dw1;y3F$e<$Thbp&i!Y$mY97-K|7qtUv|K$5Wg*mQq5loablf#N))5Ry}4_^uuL9k&nX83fU26D*F5F(c!axg-`nDvTMWu1Tin>I zNGtIWh}?Aw33QEpJWRL}tD`6eAQO;0Wun$&2v;&~k{hL;w9geOccChQ}W(>OEJRn6{k8~*0U*6uNLF?ID4j+_cicIc(e9rk58-BS>fjmr=wQiitBE^TLrw3I3Lyr6*(DL}V$&xWsb zgBT;Y2CUVqdxPcg0GSn&!M4Rm9oAV1T0Ypikb0~_q*!X=Dm0yMj#O1IplaJ8U+^5A znMPL}$`A^6$ZPt4LQgbW>LKuYp(t zc70+wlJR(M(sHd%{>#0$Tkc?Azv=HSe>aeAQnbf7@h$b*fU5oFvrkoQX5q8I;&Gea zcOG`tXXZ0sgk3Is_=Nuiwj*jGrOhyb!yE4*7Fs&5hwJW(7nEeXV=D&X-e=0?I;x(g z*`3w4uTdC1T~OQt(PEH4jt9||A{yHy{KB*jCc66?tM8O84Ou5SB9WckBE>T(yr8s! z4!Z_0le5G#E+**Y?%EU2eLwt)7I%7f zX5Rr_6u$FpB!cotv+a`7i0=@6lGdr@AUM7e+*{W+T%^NO+aJR#-7#JP{c$e^A-0{KVUH@>j5;`_qA;U!ah*rIur6OeXspoi zMJg`(=sn=&*nO={DB;BB*1BRu6(~5xPwu}mOhvYNv&}nS-YJ!i!~w6a`DY#!UT|`6 zb646m_t!?$dFKE@a#nII;bCaWE%SQBzK&Dpw`ts3&lgJLBXQ7O%KI?}ls)X&CUCNx z0XBAddu5eJ@fD9ls=WKCi4;yhrRODrkby%t04hiCr;S<*?M}?f;LUO+DT;E!>8X{|<9uUwXrk5O-*=$$ zHrI{3n!0+Sbv;r*|JR8k5kiY@SOLt5&dqc=*a{7EMZm`~u>w}4ga0T)QEhd`f?Qwi zQM5kgg=4yZiJU@*7AY_8^C9g1_V_)*ojUSD+#zR$kqW09803x_#7U*al=)hl!P-ccxG@K)r!Mlt4N zJ;)gzogcfh%e|5I^%gsop+;IO!eby-zSo0=rz#a;zp1SBH8pEc*rvXsdf<+ojNY-N zfjqRHtd|thU)f$NKk$R_WDQ75qcSH_n=nh*(rPju)HT!lnPFr#X=pLXlFvq17 zx^^(rjV6n+qM3zfp>MrU=33$2TVpPwYzI_+#i{UW*&=7 z&$$r$+#eC$Gbi^8sGocH&Ed0WepC2_I%d#1xOXw4XO175wg2^wqmx@ZkN3Qk?jghH zGpEfjUI51NeBvBDlx(;XkAHeM|E4agxCnS(RYwgx&?@Jl3MW8ohHR>KPHOyk*cOr!N<#^CyWpxv4Cg|4Jz0KnAQd)#gfwK|?Oa4WrFstrOoxm{3uneUs40GLAr80VbsMx>1Pj z(+IL>ajADRm>}!tqyE~%!8Nz|+~xk$YvyR5J8z6Q{EGxFxjpMvu>bZjnRnn67HOv@ z0k&sXE*2qKvmZXc8mxCz8IAwsaFo0XyJoX&QUD=A3L-0!1pGYw>{&)FTUiO;q#M$j Y5R_M->4HzeA4~r?6tV-UcAGEnKh4^Q=>Px# literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/signal-0-25.png b/luci-theme-design/htdocs/luci-static/design/images/signal-0-25.png new file mode 100644 index 0000000000000000000000000000000000000000..4b9f9e104799d4d9c7f46415e30236147f7ed979 GIT binary patch literal 2040 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/signal-50-75.png b/luci-theme-design/htdocs/luci-static/design/images/signal-50-75.png new file mode 100644 index 0000000000000000000000000000000000000000..c0e90699039c031dd8a480bb9188511c9855fd49 GIT binary patch literal 2050 zcmcJQ`&$!N9>#~jaLJ`)k~rQ#Ax21RK!Ua?auJL|xS4iY9q0nnV-;G8lu85|ZVyds zGJ$3n>q%>U5+;e4L+ec$(- zIp>EtU$ZVPLBwCf$1qH!P1L-EVQvC$czYsc;E%0HzeS5{$W7TQ+JOD z&tAo)A6}hN90=?5*0+keVx@g8B@z7X=OkrihT*T-X8ekjIcUOnNtp=~enr9@G~>G@%mmU2MvruYSwOm& z(IZ{VEST}TQl`L!XGxi96Mk316qxZW2{Vm!f{E;_x!}D!8pK5yTS8fzApXT>$`J+g z-k}^@Vcs#yp@Ml9%AtUHR?6WA^Nv#v8O%FLIfO8;k#cyzyk<(*q??aZol8>w5=f?R zkW~WO5gZ0_1l*}A{Xq9;6K)mrXH594 zLiSaX>e5Nw&q3^XNPKTaU(K*LJ}W1`Qpln-szkXgDorKkGbX#!So0E4t0BD}sGo&& z4p0ZeaWPP@hT}S*CgAugp!R{|6i~ZC+6Sn&LHb#s4uiB7sFjd@4X6VkEduIQkPZQA zF{D$0+8fdZK#f6K0B&uE^d@i%?Vk*8q5bp0tw3n=WFOS(bQY>uqdccoMFz^g3nKl+ z{LBEdPRh>=Bt?jFvQEO!+(3#D6=WU3&)i6g5QE4%lnf?CV*c9!}%mcTLNI!(6%42=u^3XC7`VYu;}<6fDMPV46t%YD*!8j^j5&~Aguu`x==b` z(N$grEV@K7VA1hCL6HK|Bq;KLbPy;)?hBv@>3aYh4C#G<^@8*v@M5B}p^1`-`C?0g z4?ZTbczNUHyHx0>7}tX$Us&B~wy!nvW`fC!Vt#1^J3{bF8z_y^);G_J`N}PNm63Nn zb*%ta|C+LzW9mx8D=8~Drb-e2lR|J5tw%g4^hcZ!a`}TIE|8}buQYg_|Wwxd$2a9Ey{h~ zX&+kpej(G+>1W9qUWY}_4V~iV&D{L0rqu^nL$=!ohJQ?kB>pQ;RUh?9G*;}4>|dFm zb7qJt&oE#QzPa5|vO?R+UW$x;^7lod!#ssv<@VX<>h~OA=gOwtY(>M`<&GhH=KJ=X zd|yoTWt!`IvU7b2s_&t??y|sc3E4dQhU(~G$a1>jnY@$}I)&&Om>PWih&L0p*JWJ; z6YIGav}U-%(cj;Hqj~S<&}PL_Zuws0#M7Ams@HwlV-LsHS;?li&o6vLm)j}D z=I#iWw!V4eQg4vE`c$`~Y@fjt5j8j+d!elIQPG2R78||&bc?_y`W^b7tLmQRP#R<1 RQG%K}rrn*Uxe!m+{143ZMri;5 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/signal-75-100.png b/luci-theme-design/htdocs/luci-static/design/images/signal-75-100.png new file mode 100644 index 0000000000000000000000000000000000000000..dc2b7507957c551b22bd839992367b098d85404f GIT binary patch literal 2003 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/ssr.png b/luci-theme-design/htdocs/luci-static/design/images/ssr.png new file mode 100644 index 0000000000000000000000000000000000000000..ee9dfd71929d8ac7ffe4df7121b5dfc035ee8153 GIT binary patch literal 14832 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 E0sTZFL;wH) literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/tunnel.png b/luci-theme-design/htdocs/luci-static/design/images/tunnel.png new file mode 100644 index 0000000000000000000000000000000000000000..3aafc571cb651aeb55bd4f87c3b93bfabdd3a8c3 GIT binary patch literal 3076 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 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/user.png b/luci-theme-design/htdocs/luci-static/design/images/user.png new file mode 100644 index 0000000000000000000000000000000000000000..a0ffe2b489b40c72141ded49f50fd281cba7f194 GIT binary patch literal 9313 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 BRb2o8 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/vlan.png b/luci-theme-design/htdocs/luci-static/design/images/vlan.png new file mode 100644 index 0000000000000000000000000000000000000000..27255e16cae9ca0ade22fd33ef7f074ef8c47f35 GIT binary patch literal 2110 zcmb_eX;4#H8hr_nD6$S)6ode74biX~P?pHP2@)hMfdPS5c42HlkS2*BDA*)m2azaU zAYu?~1=(Z`BS?@{CW0W5AP5?pB_K_(W9UowR839Q)YSZ#s(0UaCsJMTO9efM5F z<>@RhyGIs+AbD382Lgzk?Y08}?hpNcE(Kv{f=j>!2->Bx-C$73Z4?9{S6m%VoW6K_ zkr&L`>$f{ccrYr~T)ym<6Fs`V(lhMA$=q^P>|~mE{RzY9Do2NhgRinEgnO5-Rz~ z&W-hszM-Gm&katlUEb$f_`h8*x^lVl7$SF2hRviLW>-_pqmC0C4pQye;p|6m9;6>g zw0*Y2#aqW;#xNeTkq$z(?MrlbTUK2$<;SCJUlW-_6_I+W_}rGKJDXLSF-h1xHJR+i zINuCx@=OHm8^KxY#~RHxzKSK5itwgJ-_(7?u6=->m*t-cwa@)h5{0BTHTiDdMD>&- zD_G1p4;zwtZH%F&7vu-%@sTU#2td12reQa`YpOBU3PG=k?_bg#iP=Ho&0K5RBk84{ z1eOky+G?k9O$v$64>y%k(b^tSg!1ZUe!*3Hn88!~9qxDn#p@h1>NM zCG3FOWT1ay>eVaZ(h;PrJ)>hvdCzxnV)VH5%TpnF%Jc^1XqRex%pQHTh7(IyMtRw@ z#VnI}FFv%k(csdXv?GGbrq=3(Nxz@W8Kui;0#ZsZ$>{$QP*dUL>@Tlxm;HM0aXPZ# z7)q%s6ZX&GeZ)yu{Rd@wI1tzShd5__E?ptV-^>YLvctRry)_&rJ-4A89ocaQAwh-B zpkSMp{NTtdpCd_(;VgfPi}=Y0>9Qin564PkHgWwzVPUQkLlMrqMAjl{4;bf{IA*5MHGQPrys9KBjv z$uIB>m8X@fpFcJlkpI%+a^AFW*w-8PsW|p)d|ohVLgYqb=;V1H`f{eH(SQc|N!jKG zlT6P`ryCG0&@ZFj0+KdVI-!sb7p3HCn_Z9~g2sv8j^wTOl#{yyYgkNq_Bo0o9P2if zpS@tTvY%gFwp5hjs!d-|OgjPOzJ zDNU-MlmF=I5o{$iFO zZPB)(>b}mIU9vV5%oF%$`N3=kJ5RreEGycdpmTkr;Z>!na?H6t%IAm~&4LhV8|e1U z=Do#MeXFx^zDw>r4#pI1eMm5$7K(jrlZ16|-X#JC-zVTq^5i%sYDsGueC_P^nOeo> zmvoQw9ISv3I4Aybxvgp89rm~n&Nwd}nMzepW=Z5?-FW?~$@RXQi`uwH*yNe z7p%0WFGMU|axEF1g48s+pm0WK7K$(uogc9dnL7jbP^X))yoQCm4gRxdrEb`Zi z_;T!oOje&igK~G+oSH5xhxz<5rd0rI1vC*KjsHLDIB9%L52|n=I9A=E+(J}B{ z2Ce^5_|cT;Qt8sg#C8?7F5i#Mi}RJ-?QOWxe+;b)vWwt1$<2OhSP-~|h96m|2;(g2 z6EWZsn8;3GQ~6!%OmRLeAX|8`joDW<6OeG8#JB`(hyiwC(wAor@C&%@VjUWEoB+H5 zyT;xy>(&$o4XAw=5Gi!$fHd zU|^AjB-9nW!fp(e2*i^A6pO=-UYY}1QFN#hMIO=U i)p7Z+TWVCn7R2;|42~@g2Y~|tM literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/vlan_disabled.png b/luci-theme-design/htdocs/luci-static/design/images/vlan_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..c0cef94f27a963ef4fdff39df8a0eda189cdf0ce GIT binary patch literal 3034 zcma)8X*d*Y7bYPYl}7d@6iSw1kbQ~K$WX%&BiWgdJv&*NG8j8!8DfwTGg%T@dXwzy z*m`BjzRZglLkOR)@BjOKKhAxgb6xlI=iK)>*NMAtV#slx|2zW&0|)f3KKwKn{)uxe zr$~MyGk#Vnrxb?B(!x!}8|5;!<-V80$$&W!>b1eq(-1I7sMH_{p?XTNZ-fh{PsJp1DhxOjGQh;A(>&d+x)d=~3 zz(5gY@g5}aXHvolcgz)Oi-d)h221s;K#Pq$gdousAikkffaO{iI1{1H@=x5x?|OVS z=0>8+0zF#~(05iNV|w#7$2V)Z)|Xe*(2$U6?$v$~oEL!6izfI^sYF$5F=FZExPCW{ z)v)UWS6S%iu~ACNy-|VVaspvqC}sEer7TBfUyD5crcr*3$x;cN=pS6HrG05K2%FqI z3v9+LDp3~RoY&SH^EWXj2C*0Mx`gpRRSdzIv)m$0lRgY zT;<57j{658Z3m{Kj+wu{twzV>-RE?$0EhLY&=4t=4t1L<52vW!($(?88A1X zi)`+oM6Zo~xp_eP~_jjza{ZciXXKSxBa3VIlN1~QZG3(!n2!G&4!iRBY`frjg z5dO?SiFoNdUD-b1W(6Cazq#+}PRgl0;@3Fo8vKFK@!}x6M#;*4{Wkhh2w)m}N&;@R z+@asBY!4KN-AB2$gR19H(Pw&^_I+;w6;<2(N215 z_}`j=3HuRtz`B>Mu~gUoylgq($I7eCcg-0?Q!Q^)EY{`x=CyI2y<4;~h4JsuR0rFTKy z?-gjJEElNwUi|BI>kuek=kZq4JEbc^y>A!xds4Q;T5SrYB}hbdhbv~?Z?-XvoBdN( zKG*Sh{4(cHar&g2-J+$Bm5X$P5D&3mWe1&AxW2)Oykq~@)WSA<%ACV_cNBQyk~I6<8IHyv3U{Gk~qIXWgZ`rHW1|E+M;M2v=@NDG#<*GLP}^cp)+Z&( z*vA#+t6+@Tu^;B@S0mr28C?g8MaPeuuWllV0S|@EtW2l%O#@{$f2>&5xZpX7pkNjP zj7*8eS7AVX%!Ix&N-WLsienBtq=pSvX9vz5bo$pP$;$%O3Op_<10jZohJ3cm5pSof z?Z2SS=qiv#q7m@fYJ1|JMN`|drfO3NVv36Em&@uIw=Yt~t(kNyxe4`X6Pn_;$wz$h zDYnbard1UI{)Be5TJ*_@sB?q)P1x$jhOj^`cUj%N&cxX_(aBru|u(?oc>i=*QP*RuB6JMwn1JWA@R;x z_VrRmf0;z|l=Zrj8ugWvUU#I=k0qM)Bu1ZT&QBIs_xj>GUGg9%-&^}21YAPo;rEGN zidMGw#O$hd+8hWBrI*^e_4y7%PL8A2pEr&VCRt)G^lQYFwLOdsKHz`x+$y(%bbo(zunz? zo%T*nu4eKD+>r#Y85-&D@85%@Woz82mH_!5sZ*&*YmD>23rDvTQIh^t&A3mRAl)2Y z7UV=-h+`@L#Z^MrxxQMUeVYRM8@UFWT||+JDRC0+*gY{$3iF9|nz)kS%>)V3D^2Dz z^=HXOl?}MJlw@%X5Wu-HWTn%|kr|cE9xy`~@fm4P=WcltJJ|e{%WrR#R znAT~0cr1Qh+s`P@BU$L^+6}ouQ(i2OnMp^PmVk0cbc3wE zG^k@nzU%YnuwR-Xlu8dTKAQ1Ngx7^giSYNvqA{!6T{@bN2&coKq<1_W%_j+wDi!+t ze0=b5UFbXwaT6q75@8SyKW!3Q>WOGb;c~!tvm7YeNI}fU!%~AYr%OE#m2cdN9*$WZ zPwgimKAOB~G`<^VDl8n4<=}QKQ@X^N{LmP+Bt?DhKa+qr=7i6aAR}8E6TRDly+Kb;-NCZM<(iszn3~24?Mal9 zV=*ocI(3GZ?}PtQ z7MjXP^rXwtF*t7(zpwWQH(<^Ffq{p!dup-!=4-(~?cdW<;3AO-@|_{uh+oZogSdIO z&Tta%G4d(<`)|4GQm7`PIthM9dbK;^o2K{yw>0K1wqq7h1t)F$Yj%jM1Q+i zCl}})(Q8r85p^e*KFaGUte=;t=VsE9bp+D@P4F(Z3|W<}J(IfcFt0F+So;Z~DaX4P zOJ<-$G0+3e`SD+?%tkr-pMta$Q4j$D>f_-*O`re(I2kK3 zF=ZE3DN$k>2{BF<9!^dMRz?;8KsqX0%|ko+1xs-E#T;2vbnUJ_)iww~N>&9khN4q| zk_0dbML`oD4vU1-#K1(&lGYdsUWSv-jy%YtZnG4Lj?|6O(C5A(+A3}K^S-^l{#gC! zI?X!$obj4P4n#$xOgt&D2Jonc@$;?`#Vbh4B0|0jrUY`E0 zbwZzDwGIGqfa5YFIojy{zmN`PN-Y3!B4Cdc?Gzp?K@~8@s6K`P7{dnCsWqCx0a5?} zTQ6TxQa}YF;Oei8AQWJ&Jb4QUSS!FUhXMQs1Ef<+k%J3&0*p0+RO!L{1^{_g!laCl zeKlZ#IxVbH;DOyx0QWfU1Y}`jKw!Ek{S<(h8yp};h&~NLEDw>#ywJN>ZsZu&CJhGY zn*>d#$}O;Aw1MVuJs$4%4oD6LZ0ki$fHWu;ut%g>shMQx(x(veGY9|x?%RC-H@8s2 z>B-UliN&ey?cd>oZ<{*@QbCgY-S4hga7X}(;_U5)(ed#LgySe!om;O>xgKCc6Yy*I z&46taHcuCB&igIKi~CcUFehJmjGq7>4j%rR;%9z0^I?qOKel~`y%_)J|GeLu-gf|} z4B_p*klhxKvlR>pJEGi^Q3K`{|y*;43hSOJ3!d~ks%frJ`sRo$F}6y5qP<%b)tbZ*#m zhEz!CM#<9TNaIOIif|+p39K^kGB(ni(hNmvMS=?`R$20tmkD;`J4Y}LfmOt*iLD99 z2}(&HcM z@G!}|aOpyI)7BB3-y~QgtmgOHqASjt5SR2eX$n8}8s4tt-Jw44+?jmj)x=yXEUGLL zEwWFXrooU#>i6z=*0W@1NM;acd>9}Ygc#~qtg9`m{j0e)yf=C_eqK9YV_jcv+`2ht z3un`3Kk?e}zPQ15aCWG4gmrAX&0YvDnqGRH!#+(sA)Rl}OFh~BEqnrA+^*ct6LB%K z!*C|x*s^e&-c2Q#p4p^Xwawp!?w6rX{_02^`c*hDQ%KcDc@trI$l(bTw5W2x|5?Sp zW4>j>Z}QWMb+c%wX!xjyW;(?t!=hupY0-6RYK(rXYOQMgDvoD4%O=O9XT59l^LJRW zMAoou3}?*fpN&7hlTd#Y{=8JBX$oq3X+CMLR>`dBU(#RNt!UXQ<7s6gWb$TCwv<(8 zRu8#n+U;T-V8qib&^)QxZ?If_Ucp^uT>ZG_c{X{bc(!|`J3c?Q^{+LC3f^9ShBiPlcJC znOoKCc1zn+0>gfl9}0|_c;g0x0=FW6?_RVIoTd)5OEXIc9urQP4BZWN3_rRFl^U}s zb5@w`#x{ra_PQs1jClnG%-?6uAp}PR!E?QHBYH}DNOuK#$oyCQ)BT}8b3XXqC%@uf zd-uH_uf*gKPf^MfuAs(+&%*4Y_&b!m$)8WPz(npz*+#YzS>dDu-~2FW zXjv;5FI1Y;T%BBB=vS(abUrM*%D%yfPBVHx$ zQ_)<}$ziXfj)vBT1fmXIz)x*6*s_i?)c?4e)*NpYv;$AhXC`wz_;omR5`4MC($G>H zgpNaqMU|Pbm5xj86$sEDLNmjZBzg*d7pT;?w#o7*on&i*p1HUA{KVdWg)2$Ajj+Kg zsnU5R;v}_`Jt}C5uk2LKt~;$W@T6p=WEH9+TK#FFTV-ygZdJ0Nqf16S@;b4bz)Oyp zcsU|_b9vmvv<;J=FKkk+QAWa&XDXxf)Wg>EY?JPm)?H%TwfMexBZCjd^6gHjQ*Ntk zTx;{xx!)u0mFUDGi%|o5FtQk^c9?lu-7WY{{+ev~^QC;Ct*Y^0?X~p~ry8d144?&qjH(=~%4%NgB->67v=oh&eV@GSHa2!- zTPLnBr7w#v?Wg;~Ck>?zrZATR+83H%(7WLvWaIT zRBb-wa~3{(X9pNeYJOE$w)U)3Zmjffd-yyeg%Du!?cAnZbv4s@YT0y4_&wP#+yrmO zv)_Q=&+G_o#D~! zs7s49AadMKwOiurbEtflKQp*BIK7)5(E0>(DeXnKz}xFq#ZYLMCy?KLdlp-mO<+hM z)zkXV|CZ&@)NPa_UMnXrn_A%h?I<|;u+*$HCtFcSU@3je>qY)E-Nr!0pxaVxHb)5P zdL!Rz^fLaqa~f}O*X8(^^yTL!MXOx3K#hQuzvI`wbgiDlrTNR`wHAMk>tBUSzWLk5 zfOqS@WtY|0RYrqcukPECE4)^F%5D5MijJpO_vdS%2i%SPmVtM?XYFUt#@7Y(JMu+9 z(|5gjpWWW8ai8(*pbqja5^O}ycgnxTi2VhrDXC>LNwVMZ*+fKmh`8MkW;4nAr46O% zvlITB|GX|;Do=O64nE{&wLjPH;NN0qduzPPADwS2%WHW@$wrB~X1oOMOFpY-HvMkf zZaa2IyNS}NKZU=QALrjqM@#3FUIb5lzdxB?LLWaEq_}7QOEQT~rBxLG0B=eFATSgF zc>k{}@C*QOV+H^&i~#`NGynkTnAM@e|DOZaQCi0Z0DwpTUjYMTWMKmU3@b9?BI=%5 z*WF%Oc3K7}Uw$h)mSy`$;|k7fiNeys>CD2oqQP@kc+IFR)X7Ywd8pzYI2d^6TJ=!k zx{d(deX&X=2RbqGvApX@VGJ-Fa#nGYgdlRWj&Xv@3k09q(tp|?>dW2jtrzOcJf-12 zIkT4A6}&H3-K#qvI=xSNy;kF#rm^)Js4JZirm-yYv9N+8e@4>wOl__H-LgouB_gMcDZibJ1G4WX{jK+uV^)&`kkeYALZGhZEuFRLe?VIL)PK(0lH)t|FAPL3Q5}9qO+vn4;lGD5I@$rE6FXH zDg*u!@$Y+upk0Zk=g1*(d z9*YmGsLr5nvi4aPPJBsGM<^myEX#VzLU1_HcXX2AuZ3F*V=9Bi<$n-n=Ug6vicdPk z=PkdIwvr(gOZBp;u!q3bUsB9p*}QSLWe7} zmA}phd-?vA0(&ArKcwU#B$hX1u_}hI#al+lyei&gQl@@xLvKaC;@@HJ$@NW#bg#2; zqDdBqq(Xw=5su3Ep|zPk@Sphc-Ohy^c*?)&1MQ_(!VO1}>Pi&I?O%9ujcWlmhNh$+O90n@i&EA9~n|vcD2AJA9?A~F6 zAZIx#JAwH?&|>3K%0Q!6!^{$bb2e^jrJ1oUfwuxI1)a&a z*Mb`r%jXtX#&;Z%MdGcN4w~Xe)kEF_1sYy*wDpw3G3KFvu^P^}`W8}to=$k8pL{-D zUSSKwM(^#oE_`TnC!K+M2rZMRx7~zdONoK?tirMNfwn zHLm)CO+UDy1;jl`8rua;n^wV@Vwx+%(9^Sb6y?>aCJei%$J9D8_^0*FLRePW2*tDg zw+6*%%(SPIv@qTltj0+klgWmI(@aEAZvU0;sy`tWHfBH2rg{_^OUAV|jI3;ba_kF< z)hOmked=V4V6zAt^PID%&{7)(6ruhou4SRV`VziHB-s@+=27jz)k-VbKDNago}!Uo zS}2uAaF>;LBJbuuA@M3VSUJAtmK7b8Zz2wvs+#kL{kP$etSz$wocd0=Wt1x{{Vr&3 z1%0J6Mi2JCBUog$s2#aTIIh9P=uL-KI%EwTX&*ls(9kJIM*EcOn|ZoETIu@*W5_!v zfw8=s2-PWDYnK(cF;7Z%etMm9eYB@G_T}C1TDn)c(&>{)K&GlPU>~ehV6wz)&1l^{ z>s%_z_o%}qWhG$S95grC%h{;@kL$*J+f{}$X9ap46kzu1v$@L;H}+gB{@ zZ*!Vl>ySVkb|DQOs+VbZV!+aaPWIPvtTRuBmFzWjzKo+WXx?cmUJ86blj`~dK zL{aGiVtJ@I+p$s`%(w&+zjW_z)k>scFFY}vg05|h&>0G2NwE>>!|3ID_jI^Q*rb1r zHLQjSQ7c3}Cb2lpA|%JH`gG^ka?wUc)B5$86-lVt822Vi4ih)LZvm_MjpjHEhbp%g z6^|MWul|68Bv7px<#!_(D9@W;@8D&7hA`ZV?x4@x!->t%6VJJm!{X*jaQZG}j0e;LIDjwW=NHUGl z5O~@^r~e?=2V8BBz$3&Hs`SsN7sqQuZ~O1ot1)bniNQM$RhsC;5+pSbdul2qs>3gZ zQ$8aLCa}F-d;&jckJ~Vti2>1~GJ^~Nc1~8Z+#1~8*qPb-1`{E|580CRs5LWz{}VEx zjP&-bx;Gn-FIj?O1tzg2PM~PTEEQCwH|P|Yoj|mO+T``6TMzxaR^-kdyW}wpUe}DA zmboh?K0z@Wey=!|e@?%-P@OYRqYI=f9}W*zjx0l|?=0Kdmy~p1{-Xg_SJF6l^&NfM zAh$Jc2YI_#vz6@#k~2W1bWLQ-$j5S`+1h~=H>%QX z24@#ZzL#2BNvG(-ZZpaDZXu~(hV|zjGN^bHYkHk*K%I>{*v}Xz1eQ!xj=PGa#c^~{ zVriHyNw)Ig@l&Nh^N*W~Nd?Gj)k1!|cXzg^)FqlPJ0?hPlHR!u8KHP}^X*@7m*%=j zX+hqk?4jUbjU+VHJ-(Y3Vbtx&#vEvxQJsLwAo5uGrvZ*2vVc88vExm zYAw#Qorkw}!nD#VhauC$k*t+55B&km%#<8BB;OYxZttR+utRdCFsQYZMSE)HTIS(W zQx%KTw`dTZhZ|K?J?uFGUOlNj)29~gc23GNi>)2)U*8mm)&Y*zE!Ce2tcIozXFR{o zuodWKLuUjRc@ip?I?J+{IAD@Bx@2z1seLqzdAW9<=^#KD@+bVP2wQ^BummM46>_X2H3|o}*n<8uP(Xkx%rQMFT z-x_pJTO{#?a^ywU$0H3;!BLah=Tld!hH>OnX zoW%ycOtRfx*jD6J+t1NyI_Y=*@azHv>F%$MVj z6Rmp%aIBe;LU@*q5ExyQpgO>6eoJ@J8qq?I1PK~)=+pHJZvB%+ifR66d)0=HPDDV@ z9~W>V*YWsvOhZM~8?s7uEN!D&JEo{2I9mA4Nh9*dN}$|TbxA>Nl`CGNf%wcQKY|PA ziTspI8l~hT=e=978GZE*MXz-4Eh4tm&WWlJ!e@x~5u$-ZlAI@}U3pHndRO9>(9KVP z?M5K>vSeLvMM-W^>^7qnJe;z~IYgv@G<4l*O5?60^a@1qSDIds9!qwjLUPSWdYJ9| zcF&5+d0*JDE-vkZWu5<6VrqzCjfGbM8FMOH*{b>bt;_=i&i)YVk)`{t&X#WHEJZ*! zQa28*WU_|Q3)^7mEHpJzNoBOGE^W!~CChLL28!MV8b@W8gJ}T4B^a;+_=ZZA(XQYZB3R(6Sy3D7xumZ!morUR) zDc?9B_TlwuDCK!LcRQP&W2S}mPu|aGRM+C7fSA4P?%t!LWB6tk$v@d6fa?g&l7p$A zs8k1j5=>VT_2&?3_C)2NzEzqP zTjz~@pbuOB<8f+6HDs_p^Ew)Ax&A(&siG|@b{ETsaqxwrsK*~eRN^5O1fsVFg$xK} zx+$AmyC~pT(mk$^X`u|d=$|o??n3r}`}SDxf^R^acb*tLS)okW#MmNi5g?oWD{kca z=k2cgwmbOzGjo#!aqlVNh(}r2ix{QkaPX&=gUdKP#_I_0UyHr}@)5qHi@9RjFSPkolmMx(AjyoF*qdVj*C zbgJ#>d{lcHeOJGmPH-iUKJue4bk{_jP06_5tphj+YkxQt?NK0jYwAPC%1XehDxuW$ zsXA4q8YH=zNy9fsJHq8a&bZ8ZO}w&@wi175#9jt58TT}w_yj@Gjp0fw0^kCM?6zb7 zx`Qj}I$TD>D-(`WzNyTHZR+1y>+=M2md~(GFv$OSiS&j%Pv0`$iP{&ns;7+^<1s1l zjiUS#bT%l>2td5o{*efohp~7wtm;vGlp_2MM=@JaC{#fE++hC)Ge}QoL+w|CFUtWg zc)7IoZ#OHO;Yj}Uxbok7(@{+tk?8ldRN?A$Oo+)nO9TS5244(`$j0AbERF9rI2|OY z#PLJvb-d$@H&8YGTS)$(;ENkj3SqI~&ZP&RvDZYpzXW1W)-AP=K}(|o&9GDp>Q!V- z@?7#AxCh8x^-Rd$taJ zFbhrSqJfjrT-$T#2nyJ!(q@0UL;L@5ZN*h|xf+u(F|v+Rl@?9qV2YO;~!VN@GtluQP7oL;}S;R5xFqGlKcN&mSCj1*=TZcaj*J~CiVV%E3 zsZ5qt;SL>tmBb(l(5C<5Ub6nI#NtU|Zet^oYe<%Q8i>(Qshk~L6k<2si#m#`7=lR7Vsw+94fXk$p2X` z(V)8-zd)@>1Gx*M`^H;;zdgmi>(fYDNUUREl^9a-p;$s0(8&+qdi+KPa{!;wf8#-v zkY-s+gr<;wSu8aU;J=wRR3@CbnKP^6k0;AO_hB=D{}oc=hv?>S+{hgud2+VyNIRig zHlXb%{c0@SPo;VYL?Iejo-}~cSLefjd0eXW4#BW89unJ6zOi6RS+5MQe9c;ZG988y zc2qsIzCuv*C#chV@bybGX%=zy!&t*d^JRgYsSK>uDK;+KN-dvhHv0rO%r7opu#D;U zf`ibz7>8%KYsi-5lWSTuqmpvptPEz}YL#@eRRJln_SJ-27ABXPN4w&)Sr81uy80AW9(f zr{UO}$?<3U&`Zskz5v@X$-WMO9+gp50Y-$5SAu7z?2fp4#)uRHuPiF=j!4KV+MtX! zLUlE2VWmPFjwbn}$vpeDs`6u4M)c~2KaCUA7J(c~7Yy$0a{Sj&H#LGuOgWZBDGf07_xZ`}kFQFs+X z_u_M$iJl>e{LnHs(D_6d_H+FUm%5L~P8%E_e7gL!jkUz1pwN5t>b~s3el9xw7Pww0 z@%xG2GZQwbC{?N=3B{i>$OAm}uOAbp$>DdP-ej`A8w|&pMvKPG>REWMScZzr5V-?< zhbZ5KrP?Dh7`)Sah_%hoFBnGmu-NN~zJ8hu#@dFn%8vbu_ONpQ5%VrzJXpo~8|}GR zC8XrzTZq)^r2$r@2h1|MicC+3SE23Nr2rK~potHDIYzt-*pPZl<7aJ!S0^jmSc_)t zM6|QRRVWTn)UD7PlW&_|rBQy~b(1WEG08ro80ev`kTh*<7E9wP_w>5PjQNl2ZVi;g zaHGdFUY^;;^s#+V^XVZ*CYn5-zz+d8s2|?)0hcrfl~cTSihT3(=w9H)~Id z&Xdz!S(#g-+0&XGaVpe0L((MmetbgY39VxwoBmDO+CoqtowJ0IDUYszjUAN<?Fci2;rQ5sy$Lo zBc8^e53Zpi@7RQcniGXona!kOsQQynFil{4XjTOjK1sQFLDLeavetk*WTGYU!1!3i zcv~qeuRcl>cq;BioOdo=_Q8tlOTOgmZEM3mTMCIQ>2|n&r-$+WCW2V=Vf1{*K_FC7 z^&XZBKi!A$vm{kObbR%CqSC;EXPzpoV^-q?-jq*2+^fK421p}iB%-~;d>nO(D&071 zD~vvT-WTC3Jv-#v!8D+u%CkcRgHJLJj|HRTZF@wyYw#D1x<~lP&Fq_C*{XvLJPA5a zjUmCN3+3Yr12`UeGv|A3IiCd&lEQ=~PhG)fLpuSk0QuN0dc%Zsx zJ%kKErbvL-Y7XO!gj3U$K~gw$e;(#8wP}cY_|X&^-GHr8L)ASLIn1X{59N}0;Va$j zX_$om265x2{Y=6l>m^vbt~nMTzA$(8yE znif0`r)ShAT~RBrq;aR1fqi(zzW7$ytLllr+PYEGLRtP9WZb_2k@Z7u1zgzVmN=+EJD(SNduO`{MA?J#@kd8 zOO;pspVmYQJgQa8P@M$6vyhK+Q`=|SRXR5i?V|)?9Zw8@xf?m^{lns0uQjK7SV_=x zO4Gzl#$HA|C*=DqZ4>(NX!@J}qziAy0sCzniM+x88%ap1TrZ`41J2j4!&Dlwj1HM^ zVpr`B>M{1ZkcQGIaC+f4ZB7@w_|CcJD>dQF! z@}}4BY|u`q*w0v)B+u`h&5#@^X2TKA6i7GGc=^EiTaSI2K%-_jH7#^;g}8!?C+2E@ z+oH@iFFdFCaa1f!x2Nxx-2Gy>ozB`DbLiN+QRlH4i@o%6L6m>Rfpo8I|1|cU+rt;; zT0xeoppFqzORAYyc4v3Y)(NVmJuKax#~bHKQvgN0m|`S2(e0_Gw+yc)d~|;B)x6_` zvHfxIvWB!TnscD@Q17n7+7Rp5H>4J6_|7Wb+HIxfF#o-VA2W49a1>ksUmXV%Lfo|` zHqPYXQ2V7$KWJytA#W3=lGp`=^<>^FVOnzarTAG<3uOti72%^_duNN=et6rh75moW zpe=l@qwoTzwAcKY9b^ypsfRXoLGeW;r#7t+bJ8Y#wBAjQ%z-6xl$)hm{GG3(qkXh5 z(>e_Es2az-e@YuOtH|=ut^G!^VHRc0vL1_U=IQR$>6|q`JxuWA5k~WK%pjdI!ZTMh z!)nMh@D^t$EG}-^23qS_{VcKG?8zhf@9pLG!lV8jk~P0(eXAsPP(Odd&kDSwjK6gH zcQku=UqepRTp6$_FB)9EzOirOy!05cVXiI7SUm^tmi2*mU;=)0Xi8{xm&I^Wfq8Y8)brPRH6&i@-CmvXNPTdqjt zvljVT1ujc{I~Mr?ejh}!(If1n<*xK0_ap>Il}d1o+W{}6F^n2XMVh-=I~{=HY@UqX z6%5Fnt47VBDmZZ;nE5dg1Cpa~LWdGMaeswoRkcvT4>B}tZ#RHj{#1*+&CKQhGe5kI zx=sTnNFAN&Jh9ne+N#HPaLsev{g&%?J0l2Gq)n35L>M2WQ3X|qQa`@Iecn;S|Fbp3 zJQiVQFHt6&`z{qKYCBb7C;XspNWM{eJ^=~$gs9HCN)f3KYSGqq1rN3y(zX!ML42ux;Q9kPR)$zbC0jvFxW+W7X$ z3XIxKI~2K1X-2kDC1k54Wos5#723%)T}!G_62cMP;1|5PU5|^PyVj4Mi|wEGM6A98y1FU}LCE2lQGw{Zf;~n*20I7i z9_HEce^uu%PLd=+icfDw?fXzaX~pJg4*Y`Ip*E_--K|WT+GeddXU&6&V{DFBZH3sS z9Cq7<*+STYyE1y>K&&XvSc#~~wz#ljJL-(VOxE|hJ~>#y`zM$7+}XIu)Yi7ONnl@+ z5XfrhRd)UWH+@0n$Nb6rwFDC-OgSJfW8|}4!U_yH(ey00?&<3e;v+Zc+K@n+LJwRF z;tO{y9%RnYPMPvrp})*0WGk>nQy5Q1TZGFhXEztn3*zFwqng*Zc|@A344h<{)-dX{ z@FiycsF(Sv1QgnUSBC_3Q~VQ!-}`wJwnKGSxU zOi*(R)D5?Vh%Od4244hM!^UH>0sOU~^&*gtcaUEdz^3nwzp8VkhV5UJzaX^Oht6WM z#{2qTHRCbXIwxDp060ocPpPY89$pxx8`eIXhnlOD{i5>d1FKKg=z@9D8=6)UP*!6k zATygCYN-@Zl zL|207{iZa^4hH?clcRsxPme(MEqPBU7bgjt*21Cq8hWX zq2O14U&*)YT22#FrID=TMs1?+fELK0hpOeTRG%KpzlMSt^?RZm6;e;gtr%He&C!$2 z-qbQJv@e$BLs+_&`dUa4E00D=@=Y8gb^HlI;RwIU=wdYbL;?ECTFCk!i&t0vwKpl< zZ7Kx4t8z#^J{W$P;##7UW=Zk8rbAgHx(~8?>53Qiv;v5uBb`O2*!h2njJ2bmV04KB z-9;fV`;cPSL1tds4KbK+a$jtX`>V~>uZXyc=ArTGtv{ej-9oM=n|@RM6zte?ONsK# zo1AjXCKx|H<_Dd$CQIVnJ^VU zNbFhGFqxTHSLhqG`N?3o(OFJBP$QfM)=C$w&&0;em>GP2O|FlPhwzVUc+CvsweZWUQrvJz@XFB8&4KN` zv1rTU-ArSnll8a-F6YTvgNT&MZ!OZTo8!Ve%7mQpNM==u{e)Iw-_4w~-jLUuatU3k z&rqL#=LF@$C_BS(FoO8mgX1SOYJ+;;b1p<_gRoA)ty6$u<*$Sa_C8qhMSb@meU9h# z3T*2^s)MQ>ybM%Cx|H6I*)^mgBVPgr&ky8F@}dp?^v1PbWGQUY^J zn;e&TM6oOIIU_lngfivH()+j&qbo3}VP;(JGEPQF>*tHfN_M@CUgzJyc2MzNagPd4glT|6 zV(lNcedH|KO4byNI^hh6WLbCAgYmB&xSuAOX;rn)8gSc7nl%SHHVAhOdEMl3%xLpo8WGEZQ&IdKHMFPW?NtV+4nqXpjT( zBl!UwtPJR;RsE8}{_o{V3UB>bFUBNFgauB;*tPqQGj;G(?UP@2)z}96xhe)!Y}RJ3 zx3&x2WM=3}ynkCxKra83vh?x~i6eR@@Y#PmKPz7#o6@K;{fBUD&pX8Bh@Hv~NqiA< z=JL%s3Xy)D=d6Sy7Oo4!j~?ySG*9-`c-h`#^h zMvoJK^5{n@Htu)nz-(3iQ>`rzfnF7lt+7uedX`3K5y zN7i5+7pS}>!)T6CNAt;Bnr9ie`uNvY(zZCREZ8YltfnCv?sU< z9t+~C{A%XD)~7Fwj0(F4D__oT;-I+qm65e8AT zRfe6pF$a1@-EvEHH!A(dHI?8cB~B_$=vO0sf4t4rwZbTU#JrnUV{bB>>fIYU}}omqj^$w9DP*E1II)IUY z>!aX?Dn|_e7aRWp4cNEd5-=#p7NK@Kf3g?+s{gw^{nhsj+$&aCC0*9jfr-$^Jz0eG zylalRyuYG~F-8Ag#oYbLpY-@X20xUajQz{a!)>%!zuDwdV$E^A&^1RBpG+g^Lve-AtI!L^lt zZ~Dh|&?x0#{GEb!h)B6k4DRZ~J7hSW^3KAK9fnezG;@`=nN->AU-YHDAM?az9O~q; z2gkDoo?Nz9THkqk!9#VgHucN;3|t2w72) zqFm`NhoLisuKHj1#Rc@iouWbKtcN)N1q;-&PDgUEa)#%>2ZuG(&ZS+NM|i6tyD3c_ zju3CBZtVLe%<*(aSG0qfp15l}nKdONQWRgy;~q3cmeHQsP) z*LXn!PK>!~=TZ4*`yjsHUocq`(^P$wxzohW?%I6wlL>vK%61Pj*aQt6?{R zjzLqxq=!gCU%s1h+~{rjwTD9kJuhFrTo;@hJ;|{ynA$S@asg-CQVqYduiV$dUZ3+6 z1GXxtX)YzsVIxZ`=Aez!FMMVD75&0|Ga(@TWW3(YE))reMe2e_7I*2!vD}AJt)%cWn)<<8?F$F8rgw&#b@;F8J`x;b~J&o&h zPD_uqawESkAQtH&)MaTbV3uIX z@9%a;=&fRt*hu3FZnb%9I!Ld+sXKBZTG_Iin5lj$J8Z%a@pQ1jJ&D6T* zx1>f&k9L9YqqVU&d+jbUIVGboS!i^Uezv3qNIS7)nWT=r{wJ#KI)#KIpQS;7e#X2u#|0ptIP>3@a;6@~8GA1YZv@JtnW?zDn`tBhY`! zJPL*Ze7H{z?Pb7GP5*|Ru1QeZgu>f%biO(-WlF%&5_w9mOuu0eYSC{tVbVB-c49;l zO;OG7rD<2dW$1fNBWCP5sPh7d(TmI6USRr>t%L|kBzon6qZbC_@W(&w(26x&%F|@}KSD4Zn#x_n zQz{LobxW-z!X%=~A*}3)QEwaYQ?cQD^H16xCv9V0E&XO41jG&S^_l*`e&PX{Z#^)tK~T{sM@M2KiNpbIDA0=m4!u1RSv~PHEwUD zBl?3mjQ!@w4EN+oPr-NfpRwm}3s@j%6t24uSLRlCnn{*r#``$PxM^;=$XER=s2F^W zg3A+Z{Iifk_aeGqF5a{`8JEXZ8(wf(NMQ+kE5*6vS*1evvo{dn37$AzsSzDL58%>F8OSa zv8{z4rAB#bk}{<@c?Bz@{POH}vAo$`=eyNxU4nC3oi18ub0< z)JYbA%D2x7_iO?R#TYyb>(F_W>nYqiJn(UR+V6_$XIQqHk0tP{F&*xKs2PAmI}bH@ z$Z-yEr?h}`nS*+&*gY<2m!b2r6t3Fo7OuZ?4u-#3ExJ7)-l)RV<;8JgUVDmj;G|9; z$sqSo**+c+?_~azYDP2o?DF~18fb;OHtGzu>5bf*+hC#cAI&eL#pgxrpkej?DA{wN z_tl9Bd=bnh0i+LoaW>Ks+xy9TpIak1KK@=C6*^ZPB{RlYO z!pwPytcefa`;U1xt|ISNNlH9}1Q zFG%lD#6|xPXPKdXN|p&0x3~YQx31$I+`b1Vgi);Y_OmSv!MB8r*;RV!p2yQxpgRO_ zN(g+nBJVp0bDxx8M14kva%O{x2SBUiRU4E(Wtp7JmlW?f@li!2 zi`4*W7_Z33KZGMp-2%GPwz2BN!a=~%u`fjpir%YNb@1{3QiiTKSA*mJF~?aii)d?B zQw!tjUxDL}eY&PUmCe|-%e@CT9*j6xLLoatX%ocD7Wk~{b>&Jn(m?CfWDxdFb@g+5 zXkg0nwy$VBPJ`w3H5Uz6iMV~TnLb6SgtWY6a?Dx)y}eZw-;wsgD77oN&pEAmKeQ5Z zZl1}3VY;8)N-JHZap*6%%afGc|F|CFHwmn3>&MOw1tnnBBW_Rh{>CVWpIxy2!bxua z!{$w4L%)TiPzB6ZdVcwQnerXm{R>jrZ3F#cm{Frfq;3sS;>4y^dSf1N(}m>Pnf{xi z{hVtzL8pg3va>uu`5n19lc7kZ3WF$k@+_uf^$2;MIM{;uSrsHd*@W&$lJ3SG$|=KJS58Nm5m~JB7-;K(G5Z#)7xmE|bX)SQtKs=ryA4ZD>bL<{|DC%yUbPy~X98{WLw;8K(GOL_eV&1rYAG`QI z@aa0N#91Ddq=H4Qsc`UNdklCg2UM?xgSBYviUx9qbBDPMe;JO;Z{7HRzc<3W(omFPJ~- zFLW#>l&>?F%QaXmlV#5HV*U9NMiEC2VOsc=^E_w?$sCs$dOAhTEAiZWUfr*mA2p3< zi>oEy+4a!CA1rC*u%p<30KvKN2lm@zh;HAB{zBDeXi;!YpRL&an?m7;SCDIRV9kmL zB@WPC(ApmhF)rFAxd%j5WW9`u{XyNjVr*q?LA0b^Sykn#Ie(24aC5pSQ>SsadakDP zGrAja^s5lCtyNl%Lod?)^4YLEfCsJrQVmw~HdFnq{U~J1A-qD+wun}AVIe^s-^Nz% za^yWWI=~2<-A79XBn4lBe)@fRTS;Xu)wL~Ab#!KBl-p{45zJon=Z;$SJNa${)yeiy zg|kM9jDm=H=X{fkqchP#2FOQnSvh5@wJY}^=oqK=XIFp1tU2gwg(j_$t1iKCI>?oW z@B>;PY&~AMP{!!d>)sDlMwVwak&-Cf3@fw%A&X4|&GL}tf*QYhZ)!U}L4qyB&Z ztNd#FK2CNfsM}UEW&%q+R1A-iZ7)|Fq}Z3P3KeVStvcnxC}sMz+>JfQHS)k{+0_QI zeXa&yj98DcB1Kg=_MePr4E3geHgMNs(N`!ZDd=x?YD5vhcSKvp?-#w>Yh}@6*OTHOmr=vQT#$AO-$-pHdW#H-ReLq(}M*s2ovOjq669X9`|Y#f(OfJaYpjOQBJ6V@(&O?gwk6BT#W%+gUAiBb_4 zc`VMKX3NiGsgMFj0^8dc>vmyCXTcboCFjLQ=j$!_wD46sQvC?bG+Z)C`<}Y^@tsVlYd$z9d0PoJ!26r{ zS~FcpLCrl;k45k6fU6ktlygh#c%y-xTkHvnH>CW_)^Ix&&tQjP9Q267-0{{* zc%Qp@^c8AL3sub(qYwl4zbr4G&+;|uPkd*a8X$2&5%Q7qT%S^}5E`b@M87<3rSLE( z37x)@z)M3*w=P`GS3Sj@d-;%k0%o33Az*A7VgBd2i=z^U$66J$<)+0OHHj&_cf;cpx() z9nSz>_vMkmIayI~!28L@rK_^KZdWY-hm|+|fVxBG W^2W|VZ*c#RAUmtemJJqucmD&W0tVdx literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/images/wifi_big_disabled.png b/luci-theme-design/htdocs/luci-static/design/images/wifi_big_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..c0556b9a57c99a5155c05d6cb988416cfff1effd GIT binary patch literal 4070 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 d^;P%5fRRICy|9M7eE+3)o&-$u4P+2Xi z_dc8|pH5_{2{2;-I4oY6iOmwfHzxTNc##kw`A_kF{)eYOWSJOANJ)1%tUt61uO`Uf ziY>b>C4`=WM{i~W_W_R_#q9E~!pLh6D_7qNy(H`azOsnx8J6v)FFNcxiDz_0yxNqX zI{x5AT+>syc3(iVUJ8P>KYiuiR+#7kbH+7ssvkK}7NgVkq=B%0z_}}Q7Y8?i;>DOR zpcr~2kVsFO0zmA=MFY+NAhq)%S&4gPMU@f6VYZT;lr)e#NUP&v23BJbm2WeJd1Ek zm7P+|)YuLMJgKB!n<`$unf<{c8vif8O;sfARgEs*1g?)_^CxEd_}=$kqu%0o&B8MZ zkfZc<_vOMH3Q9&bH+{T;koY8<@KF&8yTspCrirmCmT@oWIs0gA)?Y{%Bum&Zy?E$L z&Cr!^wMWE`n-EUNhVQmvQd0-e=9{Fz2G6v`AHBr|5sX_Jo9${GMmrbE&N(Urg&>4dViKHeG6%>MCQcuJHZ+dk`VmYeXe`N(xuZ4(nHg+pP%b{=_^bId?tPVMgQ&>bAynNkM(Pxu9gx{(0rLJWzugg zeNZv1=ckwabVS#pu*2dy;?jn^CMNpv`xv#t=QfSKbgx-ydPQvyUMOQc4e+-4ky+Z- zCN&p-wS4bfG587vX+3-7_1Uh>F2ycy!(#}CqPKc!U+OnnW0-ZAd^kt|Pe4JS8sk)M zR~}maa3*l3W5#;NbBAVUduGqaJx?)@Kkr1^Mf%K#xaC2MZcB8_tk1|F`Ei@=fGy&a zpC=Ss^P{RKF2{u@w14(6d!x(`g~f>;yrFXzk+j(#d}FhT%yMiR-H%%S1RZc_N$GYd z991vmYU13DwO^I+rtvY_U&Hj5GU95uc(MWiZ(3dfj5j=1wLp$TFEXzRNAi&_nV5&?V zW4g`1?Se6Me#&5&OO`90JJ9f{Jh!~tH`is6YK1D9XN>3Mnd^+m-+zBe{^tB8*pWK5 zI^{TZIUQjdWW2|Ok@1!Z_Vo4{^mTS`+b&ub|6bZ%`hCmLp27ZuSKg5X?MKZw1NSn0 zGijf>l*E^~z6%^kU#H(~8LJ;ZDa>unoh$$CGBH0W*Aw#PN?S0Oq2KJg+@8|${@IHa zkHOWvlH8JSM{lq~=Dy}e=2z|ab!yR^`50lBAG6&iOYH+emeTTawwJ?Oc=EmSxbFhr z#ddt`fG^5*u!UkmvqK60XC0^g75%GPJR}}7el~tF zp~RincUlRA$mFS&$%x5~m_1Y7x@Zp>E^Nf+?D=y>secmXQ5!Q{3J-E>-N!(aVn&D- zA)#&`FSND>8;DR#s?Mk;W=Fbg+KUh>9$wMUf`4@Do_TwCpYdbL){L&~+mjBGOB0)A zW}O;5eeKJfob{Y-{^mA?H+^n;{Ve}?gGCJ#CW{tvnB#ZJ>A(+m3iK{jfc%Dw*|!^c2I;4g^D-fiE*)ZY9{co)5$ovj1*FiuZDu>tHb7t&%0_;B{1%W(L#Lq& z^~fDF>iDLF8@U^G?D+Un$=3olTz)d7#{N88W4rJ=nx%G*)*3CW)2nz&L8B$~iO=5z zX5!zZ)~;qeA+~6D^XGz%G=e6${Y}-=rmEWMCV!)YC3vSwD-B!1Gg?1E5i`A(m;R3X zV<7_$12q}fPgh>(=^r`;%pE4_MUE90KjMop6i+Wr>mP8fI5uv!p|(nYslVrxIcZ`L z#!H)SQRZIusp7oqanr_%;S-C=;FAECnVAKR#-BUeYTHHIu4QLNos}BxPD+!%V)n_) z84g~rGg!E2EO>tibUH~IsvG(_gePGov12mWP&Rw`;X&bPU|yKnfWdY7m&T6YoHLlt zdB30|iby7EnT5Tyzist={)WhQm5>wHvE7LIWO{3cmd=gP`6g9Aou2&UpyD9HQU>Jj>|H?nUhiLqMpw>x z#wL!IlXKtG9a=wP+9H6@fIKSK>}1Gc@sU>C1ft~5tp{F~k< zy+|18tOzJQ^4$AUS}EPf*2mm793Xe_@n8AyY{*{IUdv)%J99SoKgFA;N28ZEeI>ti z&g8MdH~)mrqK>WvR3%41lF4GDrl$=6ft&yk9t8lG;7j3~0N^7G0Dmk2KspNmXx-5* zy0YK_Vs|woF90Cg{_lZ9^X3N=0El#{Bb1)|qjy4rn%GqW&aMpf7wt9%o83|Xij1!Z`I{N*Oc zi%Qa8s>~tqzlGRMN-JhL)ptZ!n^KpEY1NTYu5a>zN%GLsQLp2;s^t7aov4sw#{ZkQ zT31`R&-+Z3+axmG1;$LrjUU2nygK$`l~K)s?dG}p`57pf?Ddw;-EYE)5RtcfxLC&E z#n^)bj~De$)GTm>E&C5ZSDJG{z;A$ZX(tQY{md3y0;GG2f#Xh=~(| zz11%3(YRkV{JA0<2;DV^ZmI*sL%6>l08m6Qn<1gO8h*>fA>#}Q1K#uob)H7(s4r{x zDzN`)RWg~B)t9%J6Nkn4Z_9DDfCkbt6o0!byNK zn?xLV#Hyqs;zX~sE&&C87_)LWA!^ecI2V8?v06`K-w+bEC`G-}i+8`Ti1-1+1Eyn@ z$#m~Q9m>^_?X<5r-`OOlqa2ukvRap`iSumY@)NuAlfAgjOkJvL5+L+7s+FcSKZKt# z;Yk$glg)}FT-~|f=2CY!;2DBpm>8f^(e6)(N$oW~gbZJ>Dx)YN2g>CqXw0Qm`N;^d zWB_kbMYd;)a9){uZds1TK}03ZX>jbAQnA1h+v!{)CDaLx?BOu<}I^iF>V-d`#`YE4$*`o=B-bjhPBEZw%J|2@PSp@m-a zuV~#&89y9=sz8N%qafDp*nsVNOl4AmgBX0_31ZPUah|?4;&Ss|i&a**o>L`KMcV2z zjK=EYNW!6($u>XH+ z)$v}IvPn4MA@G$TPa*j4)06>8+sV)Rw<6-=$1aFqIq2)-hHf2lerf2(a+~nz3*y@2 zR$oc8oM-e@9siU?d-t?b7=p!A<(OP2( zHRd3j(Kun3p^aw4nlX-XtkH;(V9s%C{K7N#v7Yap3>Uh0p zA!Eit4K5b^QRhy@dI8^K$QfkCOsD%&L4+tHVHK`EC!p+jq~+@@8=UdiSq$evs_^)w z#XY0$)Z)GDwgi6c%N&EPdr`@{R4EwxXvm1<m2v#QF3^BRb&&F8W3EW2kXt+BT-#)&Tpl+( zfSC=d1dDlJZwKD-=j8@EnR@0Q(=I&&YxbCVY4V7oA-DfwC!y(-zAlyHln{Qe#F1W zpVzR7LP1oZP^fW6{fy7NkYl-yfri<~`ikoh30T*%hFMuTxpq1zD-kZl`X)W*s^^vo zQCITu<6K-^TuM5h;eF01$>$o)F(STotCHI&2M%cY3OW-+Wx5GnDkUlv#UqC#_aYV7 z%eGB(^A=fJJsDL5qL_-iSdHjavEEj>E)~H6t7mW0qaGAE2R-%AO!(YFc7jZxGa&qX`(L&$^(HS?cRPDA&*HiTzp7IzrBw~d@ ztw0FH`?0ndui3K)gopI_-apg2bxZeq%ZDr%xpC;KDHAiBYG);i-~*P70V0avZJ`kF zXrkFWHe~z*8YZ7ZsZ>m$9(?c{(WI;;)|DR<6BG2a4e$7(B=10z?}Se#R=>418d{bJ z$0Y65ahMiS(m>4%2D2aQ=(z}os<3uT_j$jPtdM{9Mc)%~%@I5uTp zVY81Bvyg)@J3G6I27csgm)X9+e80B6s}hmk2Q3vQNh+3N;*WD!j)rT!zpVv8Sw9~A zI1;)yG_t>e2A6ARPfZ!yH{mu@WQaX&j!*y6d-0L6ihJ-JjsimG*_%J5CHa?6;DJ6= zDsChZOU69wLa{M1b}_NBXL0Le8eD@%nu2MRoJTsL&oy{zPuKbTJUURQupHY91$~dF z_pBJENdSwug3Z_HBZcdWk+9HZwq)5uqmiSAG!2d=bfk#u*c{3GX`^`!LamPjUTn5z zQ^t{dSNMQxK>is=?{v>r@=j@d2``j>b98jnWy;KN-Y@LmDsyMgQJdGFlgq0#J->i_ zLsi5Q`jKpI4hl79T1I)6sFc!?ovykPs|0ZX*XydJ1w`2tvwr%AxJC38tCX{SMK*=7 zF3nirqIDV`bgy!1J2TeGf4ISA*1V+t#tq1_O?>4t`vdlnDjB}g+E7sxRdE_s z46FO_ZEwTQ2(o-YM}M?!6R~+EPew)-Zfm6d4KM5N)yMi6keH!}^fcVfXfb6*c)C=t zAh@3=|ClpQoKu{|+RztNyD(UW(qaANMuOT`CBx`rmJJ~uoaQc5!JI=lwWiXJc{S+^ zS^SzgHuR&6Do_xl8(eOCy1Ke(As#&ud>v8Mn;;z#W23)vr$RU<1w)2Z`IzqCCxGJ) z2c&xCtQIEAlW6crz7f-{!&n++_?n%?B93E($t>t%mNV-y;~BORlhI{0_8%ydvh1aD zgFI$+wNRDd+q?kxiC3S_^uE0n(b9^|LYb(0IGgg-*48Q_Aow^@Rzwxs5otAaSMIDU zKV@l?pIsSmn}BC#K{?7$l(zV|yJc0<#Y5U_Buydv!HBSk<6)Weu#{6d2q;zj+on@K z3OK;XW>bMCOf!aPR>^ZZ8I@y-@iDVZ{JJreYvt?PkRAF#kb9`ST(P4X{=jGC5pgkjsW_>yz;wF z=wa%HoS6AM4{OdbLOdEZt=824rGQpo%jhA}Zo!2MV+s22>TOsmj6j)8OC4QAEBwGj}pgJ&D`)qlKcFWPHQ39mjdGK!}wWp#qtvN|T+Te4bAZ>I*E_pX*&b~Qn&VISvEHH*Gb zEZ~E}-kQQMd~%6DC-CS=VxNAQWFdQ$m79x)i1KWnJ683LXhOeAI~+%N=VLB8hXcm* z9v!ct29)zA9rJ`W&%~pq9mKmDb_~JA8vGVj7O5}pXQQ`0Kxcym!W&#ndV;bBd5Sp& z248*ssFWa=?NCSj@uZ|bh`=&**8SAYrND z-ww-WN&@l|byg*l9(Tv2dB&jZq98Uv)o-79u5ZF~%7|P#n`H1B-5b?{TV6(39e-P1 zw)$oKa9$?wUNCwDL8Zc+pOe#4Yg``M?SaO2e@#V+#2A_K56GpiFZ6qzuqSf@j)kMZ zl+R+dbx(Z%!NEb8NUK8jRmYx?V_r4G0de2GXZu4EUb&;e?nk0F&eS%4xe>Aw_lKV9 zQcXrdW}_j=zZ zYmr39$TfmYESSU%G`JC3WYAI~c0+nPM*VUdKO<%bU z@)$Yx76y$hkQp+nj3&f6U_p)+3RM}^0hWRg$1K1n-=^eO9`1W1QN#l^me}FEhb$|n z)O-fPgEeKTLx&M%N@w!+%j%PZejz24p^t zj0dRkX!}2~Oe}wy*seu%VAbbQfkj)WBTAyI9B9{5?-U+0xPtl9Y=evcN*vd27P!FF zkk|S)>{OFtUl!DH1p*&vmmPfinGg-xgDUSgkS?(COLJ*Cmk|LyrW}sc4Y|GEX=ydh zVfO)NP@6NLHdg}MZywDybaun8^7TIN02%7L$i%F*K&-(?FYgaKz&~N{%BEtwgB&_! z{5I)NmSKaeehf-YBW}{^L?{~4IbUtl*B88K@jUD=RF$!M$(}ZkXsDx`Kt+(yt8>%b zAV*T6b~A59<@ARXvo9kyc*@6uCT3ZnV%vNGc6HxoaBqTS1N{gVL;CwypeRv9r){Ek zK)xRxfI9x!=^eyA`#D{PD`dV-g-Qi<96)#Cri8(*?I6<%w$PH5>(P0=<7Tm6YxY}< zYalF#%X}=*>d@g$I;Y3oXb8k)&5k^-Pb%zUe}6xrDDC0M@NlRG&k0*Cv487{@J-_r znS0Pee;)gGQ^7Drjs8d$mSHKo5X&u_j9ku;{7FtF$Qx`xY?*QWpTeNizX1WTnAuG0 zf4QLI6Nrr1cgwkyo(5+)iDvKsf*(t z?e_xSZ=YPo!fZa93f?k6J$N{>t2pAkqZzC78Zu07Sw%#8gzxW(*Bhna4x<J!SL|tW^UUA_2$DlqW;r%_HiwF5#%9 ztDAJxCy-UbeZTybXqD9t?!RpCJX+g~wcG0MLHTE5E^Bu%wI-YW@|*$P)?+1c{K-o- zW7O*|!$VJLfiiH)7A96#-W$#CKWu;tis4QOLOI7{tjO zJjFL=L>~(?F?D2f}zkQU5+wx>46mrlY#It z36f1QaA7>vs2{qZWk?t%uBC4ruaxQMiSPE5v6kBo5h;PuD4Y7OrKpA$>y@H0{V&sw zWoDF|H-nqZD=i$2Xl%9LzaZiobhH<@&i1+?>7BOVoZVOacS<;4m86c;27=r^jwe0I z(n1d7#M|fBtwa%Q1#w!JfpdTt+#|t@w-Bfq9v~2spl(g0?5&(wR3B;qi;2vzZRe0% zZZLb2H6`CKZfDgA!F8GKc+OL=jtn__m6cuBx%qSYK-uTp%bB$R-S1eYS?D(6CFY_6 z+y|+8Kgsoep5b*NzG%P;jG$A;JTndCNvn#mm?8f-yL)8;jkZQOHhMHz3?jkj~-Hgm2e_)lr)S(I~8r(<$5)I9-c)=Em_ z^>o!DP9`j4aavJ*@3e!FMdj3DH>|b%Q$-9zg?T&u6ZwmmO*;*zc zfcr4B)Y_Xzg4D{vlMOrHBUq;Ue8%Hu^d{u1XS(Pvx5RlZjH^?Cf3I&aH2b#d z>_U3ho|jm`aX ztK@s0--6@ej}T7IVDRwi<3bOkX48%s)L#}NHKLR`Pqx}8TMZiK15S5`n~kc^2A%3J z4N>R$1=0c!T9ykA23NepFG4g2S4!5PmgWIkykiFvsUtWdTJhZ;mvmxlux-EZ$|#}p zj!ra6{&&If)5@v;=XA;*AeydrTa}RWiR>w7WN>9F6^k)r=H-Beb&p`AD8q3bTat``57EmV=d2u~;t95WO! z2z42#S>P*PLmVq{vmn9)u8|jq>s6uGf&SYjizFaxf6ALKy68411DeSvwIlLZW_zJ$ zt;tLb3_*6Vn4sn+3jD#V;g7Eg95(m4biSxw!tD`ul=mU<7{`{ zkf(T;B*JodQ11zWszxVY$e{E{OJZ{o^P3t)pYHkIu$OcSbBnhHah>Vo1$C4}>vIPtv$1 z-N>(Bzh23oHIK}n*K3pEi5C~eRFl!xNM|Y|bRmWSuGxU7xP$K>8uv1D% z6j-^1jlldsl&DPeqzB}uK0j&o+l#>}++Mg(>KlITlRp)C(d=n!H?y_n_@XmZuG=+7 zM}x=0(g>qDC_2VJqGTTOc27saCdsbh44kqI_I7rzXwVeltJ%0Kp1}_NsDuEO0_HWt zL-X56=6_2Jpvl6F|JA5sJKxO+^LRX~-{VhN($CtYq1)qHM?8)ptD-cPC~l(+pXfAC zE+F{Jr~8Q_(>1oFjA8!{{);UnRQ1M$KWO&$_P&44J9J0MT?#7qjHp_a?0fqL%SN+x z%|seMT%~)1h9+qhZ7P^~3u>bgYNJC!dcr%w+e_lGvxJAfjylKs4geAeH_H;uU_n^vttx)wKOi& z`#f%_Jr;h)$HmtCNgaN;&7?kH#G~^1F`nw<$AZh~FioENT9YV$;d`ts1s+Yi>;+$< zAh*;p%PQbJOA+z)meuDS@4n-pQ62hHEaBnCa6 zV%MaC&2QZCH(>vY^NdsdVesMawG-JdEhxxqp>dyiKhNRY!L?LXQ{aen9UM!f=^Dk& zLys{d9*l4FlnY0j43O9FeHuMuAkA1RDF+<=OEpvp1W()sgI% zDh(b`l-FUZe0Pjr)Y_5Hxql~L3Rs9(qB5Cp*llmf~3eUd33o%jNW%J*o;DJ={r zS;`7Uq#654pYx^<)ML(~t!l1SAbG4Mex z;-LIzawL%XC25zTR<9_4mYTKNP0jw5$DCw)%2L*%ox)^pNO5|sQN{^QpNAmD_cz4_ zVYcygW!qcgMygrNS1NrTNnfV6_bR5g-9kaeL|=Ytu7pm`hQ;;_sI=|<%mhV!Gx~^@ zy>WzFv~6a2gHu~J&Cr7pJ6Bp-%8aAfltu9K?HDmRiYN*KiD8vpr5g$V@Zp1Uqb9?& z5+Y2XxNY#LO_=6F8o4PX5L1ir#=)UCd%Z$8SlQ@urQiF(HHM)!RF~@O`MH1UGwd}0 zr0Lm!vtWvdmBoDXU8_xLsYNR@6rSVY&;^q*A@b1j9B6D?ys_*z?nB^%cYi<0uMH3M zEG=DKDH>eoXWFK=GUHGwX@~LL@gHSJuDIb8;`HR&2T`-K%Hn6zOHtvHoe%RMxJ-Qk z*m!EbP|o7uPx{%bukV9S3@t_ov?$Q%f2Y5G{c4oNVjt@wjFJ2+fAidxdttq)5*ToI zWG26UeeD!htOw2DhvE(ptEcL z`0?Z6xPl+?1)rpF9&m+xsK^zJ6``TCv45SE1P-D^9}LNkjXI^(JrohhaxWC}NvEnc zxqRVaj&^pOFc|Ed44y=wRAtCA0^c2tC*3IOM0wrh&A0k3`rlrk(Mp#Tr-5o1*q*8s z`uA()&c8<9V%I8{t4R$WEw^=(?nx7OPXKtU2Zzfe{r%6$fToVZm|cL79BTK~XFi0! znW>u*i#!R;BOoA`tT;D3Tt$1w}hEgPCb-6Uy6KIvAvNobQU7Hf?``b zUrmnP+S)R8g)z7;4-O7y#>B)7Q!6(ew5%vkY0IogVhBYZL}*yS@_VFiIc=PEF|ns; zB3j-<6n8T+$O~0wW+rkPXJ+wb@!$A|7Lp_5rx_`5owW+tyT z`=K;bJ|8BzRUZFVM246_@bN0PLyeI;?6DVPd1LVjFMTR5?kHJSf}&B|{$0rFneXmg zb8))bsq9^+dSlJX@VzVY;S0n6ZuVmY*S5{(gs{4K!ow<4O$66f$2-lat4J`Z9yu~! zlN??ItyM5wFN*v0p+5hqh6^(jQ%KfE?Cfr)-om1TcmvBy#B>KX0D`a7cg0FMO8ZTi zv6_FI1eiv)NzLnmi})EqEwfp@u^dQ7&xJs-MQH3}XKjMYi279D(Q|g)Dupd!SBNsO zMfMO6>GG^MRRqoSzGk?sgec#4&}?Q{@z;Uit0R*|dVe15IU>24mL)|=6(j5>i+($DjQ{uhd$Y-4L; zF`x>T1|7b(KffN`z1Ax?2r5HC>M=_#f@uTm8N8%WZ4I8zot9mmgWEx0k+YfgD1rmk zebAasrek7i_frUIxOxwMt(eXJ3%7&JJGxXHHd=Ua3bEcNb^P0i;fo%`v4RyWloD{A zFm`kFJ9zCO)IIA08r)9x^b<}JY&2&iSIAz?IIvw1tOH({VV`+gc0Z+`l=^ovY(Iul z@5u(DU1qU3UHavcr+@!CdqtZwM4kJ9f)UK5SY7l>dOTav!YL0y{S|}CpK=i2mHQ== z>BAw;*wulDJ&OI zJ!|?eYP_487(u_=>`%+?LxF)nV^9A|%2oDchqw*A97Eppgp!hy&Ib|__2npr;o;$L zNAGTfU$puPXlZLxS42=M%hrTko$f_hHL)fz?A_&>Fph+L11HTfXeEw($2~rSdq)z9 z>j^&|;rx>rqzkuD03*Lzl?J zY8~NT^xCP7ijUfjj@Lu4p|UT&jP`}t08qipn<1iy;O=7iRL;{2>6D^_N4a0&c zfZ$iC3YG#Fm4d;wXcU-&cl8q>U|s@jJ`^g%mxh6*0h@+cs(61Kl74H#@GcNy# z+We_eeE8oA+z;uLN@%9^K(otx&AU_2Ht67lkJn)yZltRt$sav>RON+zG7UP_nn`~H z7Sdd1Z^?lXo5Z-a_UL$9M^DdG_ zESUlO2L=JTlEORZP4`HPcXc&F7Cg{l36X3&VtJvg!g+kfbNE(#r>FN^VX*V&$+};Sm3{m-Pqw20uf5}3Hi>fDQ#04 zh>c?ri+Erv309baJ6U&S=K6aT0!~DBd0D%e zRdnkjL>k&x$;5u88j0t%JdEep1_QMY@XV6YN9sK5=_-4D0q>Zc=Ub>hmXwgn$df$+ z)!O<;(0ZOLOAB=LEVa#GO&9dLG{5ITwyh5uJ03grQwtqIXS?5gYh4%?PAdHB=lbQy zz8~xbV`ad$lBN_k>)2<*=zzdz>g~>5aEB-;Yg~92PkhykG9tHnIuQ`C5+M?!r!fQr zO<{BJQW?N6HBxxHq+%c4m7`+p!>J7xB|W%Yl1oiZwWxT`Dm-w=JLWm&j<74`1tr`{v93h&fWh;v9O3p3R0ktnWKAI%}x@lUmLBu(3hu*x^tU} z)1?czD<-Dq|A{h6cYCPaVg<9|_f-eU*%%?noN>DF>}D(Yg?rzd3W6Dimf%AKdNJdR z!IybiVc~tT-syfv4*6u#4WE`*tYC4-gVxM@GzEPmW3n}p`@qEssnZS$=S2aFj(@Cx zB#!kvWX44QXE*bA-IpvZaQERUrcaw>nsz4DMd=xn0UJ_Ya@jg7jH^4f7~_l+c|=>6 z2YSw2CD^lX*dT8NHVfvn4_#*Ee`^&D(Z>pYesqZ^>VyNY$jQ$SB>?7rf0hH~;eY5a zOb%6QH)m!mxPlx+y`+=AaHtuBz2k%5U%k2kpgU)$FXgEF%9B*2Z8GjS<)`RHfNo@_ zUI!=xdkSiVduMWLX-yUt^fY!9yY*Gz0y@bqLw*0-*)y7C1fr5_z8ffTUV2M!4 zy>nGkTSr-DC!as8W_P2LReAU#MWa+-qjW}@ET28lF00PV`Aqg&!IeALD|BmVY02f? zHG4ByWx7qR}tJrTX zE=HE4Sq+g}2vtCxx2z9jhWUUd(W^%kQtXY1e)B%G&NFqy=7(=HyCx={>xP7WtY1h% z#n$W59sbM-^=nhyatHju8<=s;=$enU@yJgx0FqLNk$mu=;q>3pNas=nsi6ORwM5ooA=!6X zS=?(daoB&yR%lhF$2J;g=`cC8Ij7 zZA}?oyEuxw(mIqu8y|CBop?@Hd7Mq&GHZ@ezHz;6Lzc=bqg1UVv9VK5^)-4=xosH6$<{)&2&&c0zrz?JaN$~*>d7du7Xb!U-CbSbB2S1!gJXVsnDUoe= z>-mvsA_jlOoL+HoBqbcTt$A$)lN=)0YX0Nc&DW>1ou^BYcQFY+uh3Xo!VCeE42BT# z4bHoSN>vG7^6%>x>=&DT2lC{d%J1TZQv+3OmBF0ldL$rQXMOlwL#g!njHsw+4TzC! ztoJ2EMnKEb*2ed`3VjDlF7z7q-9XW$01Vfu2T1RoFzjQm!DFxA3m^xN@fSO2BP{Z z!nt}DC!{UO+OVq!t5|cS(5!MKfFw1)wBA<=8%o2PLpNfdAHYd=_b&Dl zbdg?}xV4{DgRQG@k&Ubx&=v_0+FsQ#tBrybf~+L^vXWS{4eUqw9xKP8T5D0f+gbef zE%F<4YA}Si6qYaJUxRf(Pymd|$H1UP+)!%~d64b~ghLU7c@b%3&`d77l_xN^0tkRE zOXf_DRL}+h-zS}@acDYdni7%j=% z!A|ylnJeGFfXVEx>68m{(1fV^yH<-@TG&@KWTk^0jw<*R*h^>c?jW*Z7Uc?I#eJ!& zH1uncgn?ZLfn9e@icyoq4y5TJ<2EY_a2r<^L{6t0fg`cMCQNUuV6r?{$C1amcXg_%}v+fzNb?-xV#3G3invZm+ z2y81rC~{+w|NxT|hh0=qw5{DYM)3-K0Ix=fn0FBC`aQR0N^4sYyYzem*c% zdK`}WFCCIK&QJ-+V~GkUWDbS|FADuxlEwxn6Hn^0cg#@t0RY;|5NXzyj4*u%0_k^< zf&b>^ab9Q(um;nmXZhIja9qJG{f)LD#L<&L_~+?{`57%CMX)EDF{z|tVRYZhwwSLa zGfKS=#vuRaQ(@C~OZ3X>E5iHXEJX1%%6F7efeWe``orG8$MTpgjv&=l&%i|&7f0N5 zv5~u+Ws`(c%PCEI06TOplm2_6Tkq6ZkUUQoBHF6~dX85rs$h7cQTiDpJ^V0p>kz$~bn>Y@%c)@>NO9dRYa@f%z^0lLRScdpY{po5qT)u| z-r3FzK~jDTY*m5l$Qpr^Gkcy7T4UetJO#SwZ1Qc51g3BrpEbPb#4Vn1pi(I;KV*Yf z@som`xY>T@-?FEdmbAtOc(V;)A#lB1(vJ_!Ut+BMzhDBNYW%iLgu*@HV*m>jT90A0 zlnwo*78EzErH+t4$IbO|yb_k%Z@&r+#Y#H%CVO{&2 literal 0 HcmV?d00001 diff --git a/luci-theme-design/htdocs/luci-static/design/js/jquery.min.js b/luci-theme-design/htdocs/luci-static/design/js/jquery.min.js new file mode 100644 index 000000000..fb8e4b919 --- /dev/null +++ b/luci-theme-design/htdocs/luci-static/design/js/jquery.min.js @@ -0,0 +1,6 @@ +/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; + +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
      a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/

      okx?Ee^$_ zCtP8R|K`L z7;Q5Xx@GQ2Wbo4$5d7HXD&9UYt?ctt^lprO2ZOlzRr>d);xS!=lS@`3H*|k%5O+ea zCkl$3F$uifWOC1KKA}NbkmBz&CVsM}c_AH*7Ut4^`? zO_hd`8eT+8J5`)uwJ5|zN+?i1arcoO`&LkdHiB^U?I+b$_#rT%+M+ol zY}-La_WhEetSY^_udXFUU{q(S-DPg}u$5cyB5+tS7Vp3Cc6qT5q)D|{F9AUDz(Ah# z{eSay&o9x9(!7aCw%OB)--y`x%OE8ZMbb7S8?~3-+7(y8YYb59mcU-_c2Mxz7um;( z+C>Lhpl_OD{3iBrTHL;@+hT-XS_AgK2CX$^wxW>Url`uK7 zU-ywqeqzy@6m!2|n7&R7{S*D49`Yu6%TnH{3~2*z%DC?7M~ji@Uz({J(=PSsbquM@!6Bgbb`pE#4{2p8(N+yDBB*zd9ym|a5jS1833yC_?nh5!Fu zlb)R`OtjhoYJ=cJ3t0c+*KMyi&7j^;T9+?f4kkNq>8w(-AT;^bLFxByabU=M=wXBM zCaL|Ma1weL^IJeOV~-6os{7X;^r1w!qQX{N)6OC~?xKB*s7o54&w}!{0vnbbLv9qN zAhV+|28qX8AriOADBPAKpE%f%g1?#7Pq?cY3~c(dHx#>QE}xfpA6$A8Pqm5g5+r6yOFlB5<(I#}yt;%&PU0(PvC|pCYbEyos!Kbi;XsVOw$P~i09@MJ2X~66F28+# zg#nT#P%7vvXEBUf|8@t^pBaHJnAN*IabpQq7GJDyc)8v$eQ5QJ+}5i=X<~G0SaF8+ zoaz;2B*5BH~Evni94X-qGzfQg7*?Y{Q?-Ci2+xL&i7ej zWy9t@?H5%_ygo*4u5R~Q=fc%ulCP+8?&WI0$&o@Kc2=)e<`=TAY}fJ*^+b*4sJAyB zh#l5d?LgWIPu!uLYNg@nwfjQX$itzcqPVPHt#sT)#vX(aAt<(uF;;F5Z}qzQ$6RYD zD61`7#|KJ2BC+-^_|s#L2-(((__X>a^cQrmuSRDFENzt zb&X^9gu%EEdZRq7R8+d8G|_Zwqk^NiSo+$ zU8n8lL$yF;m6Y8AWHGzF!X?imdy{Hvo_0ouWuz*WhWc0<<_?$C!m z4;#dUN*jCGOezOy%Pwi^E@d4t%TeZ!pCUhnByQ;ZxJ+WC`R4MUdG4g38^vXgD}jbp z!dn_&%_*SoVkgxRjn%aJEmM*++h31HR}{T2Y%+n>!u0|;@oGQG>DXD3tZ`!-A09*4 zHL4TN-C+ag4G5Uk3fIQ+06w3cy1=+&I>^aP^Pg#uMQa=%t!ky(DhzgswW;EtU^JHs z+u@FbO>n0|Pl|&NEm`X{Efu3o9ccS_+=P?M3jL04wl}eL6#0ghLLrjAp+XE~ug@51 z^CXS4Go!=)CcIec;_7e4V>wDhL`3ZgA@0c*z`dga#xZiK4!rP~+I^yOL@=9t^L$!F zlltTZ1x&QO>aO&v=*a+JU&(hpHLmC${`A%5#tOQSEP!}pDw?A{#4SU;n_U)I(FSBH zzIEQ{JRo8uBQ)EGuF5B{t#Is?O$=An42<2`q(R=BcDM9e>`^vTev z8nrt77~(L$b|gOM-#8A!zzmrKLg6)+{BBKF@8yS43f?Yr?FM+M=jw(7y@-w$D(cL7 z;h;mzna0niLRU$A!-_mj)O$xfTlG?e53&O0+)?)}EH0LJ0d0OESU6UIuNS=Q4Q&YQ zEdmf9B;^v~hn~zI>O@0kByr+1;5>0pI}5&0*L<>B;#t`=Yh9rO<4VnE;8`~Tdk^zI zNgPxeq&(a{BbriT+HzhiZXs=7ZEH(MXM|bWjX&X4yD0v3L8a33E8>0haqyr%c76JR_rQ zfBB%EZdFRN2$&TQY&l^NeZ-pSDFHZ&(3(H=ai3FpsCNNl#A^O9JMCn>pAS8R^sh#?n(Ic|fKPZD@@h$IO#Rn|1YtXJsQI9p}m5z8hb3CG1U_pWq;4zR>fH=H03! zwUts;$}DGpo_?Yw5eP+A?WOnZ3HvL%y`fcQ-zms_K=Y}zXn=SC#ht#X1&aD#q7 zz@Sk9Fd@tS*pF{qpOs<)E~_?vRsCP$>t7j(tzlFQJXj61!#g0U-!b-9jucz`F4Ia+ zmk9I?U0ISjYmA-d=@T91XJEcLuLtvXlC6x~Bqj@^blcDVawA+`L!xiR~tYLR4)eH-&3i zR_vEZb+DwAg|E+HD2?M24VdEOhW3+?KZN3c|3FZL*9tt(9({k59u$o+a~ptuRz)18 z%jX(mlz*jXcy=?H`|Fd8%ED?v?+fnZW7#v7l2S*bffclfBzXy;XC?Tuv&ycOiBk6& zZN*m!bU+Pci#e1q(>j=>>^~byGmoP?8rzf~$+X|fL?$BVgR!oOSva(&v|DhOgsMFv z8oF?IM6!&TEoB-;l{F70Wqa}co>`f=u28J(Szc@E9y|3UURD>YiWbAOswc!g_*!qJ z()o^TMTQ*e5eX-oSl5qB7-%rA$ZAx3A*IHz*8x;p_>PiJl6N8b$ewpxnZOo0+OF4 z4Q3p_?0D3!v-oUNG$c&j;b>VVKThhTv^8ES2jm3LHvn~+T?IG9e+@mdJ#5}@20odh zCF7md)0FH_sw6a>V_V#56T7MID0p2nK3r563bcU>R-6B+EYyk(In#GfFSJ@<3}~vr zo-Q_encgPX+D;zM^Rx20sIXd-0q~|tW#HS~+=V#up&rEJC#o)mj~k9(^>4=S196`Sj*gD`KnHo|Y- zfsD%HzO!XMv2A}$M0tWrdTz8;$Gr(kn>=x7y9K+avs>_=MGzl{u`u`OISE*$jik4O z6K%~B_y1NqGE5ADA(kwzL)wiG0ql6EjMn)@Mem-DCT)MJQ;yuz=yTpJ_atR`J0{2=(T^Z1 zz?LWXh?%B`orn~(crCYREm`61gO28CqLFW$K-jUW<|Cy^Dne1nupA)--*-p{T8cUI zT05$*gjL?qI^+e`jE^oAGVgD2nm-P-FJkb042(E{J-Wc`^W>3cW)l}nXA1&XzRhsa4O1`L0a$vP9h`Er&< zt8`*PEZ+9=8yU>T-HUFxD@l*|{79uZp8=v%G&n8noWB8MS+Lmu)vo2@Ud4-FEBluho1(<6IOu>30pbTLMmk5a|1xCxEEVcZnH=&U(-II=Y*0JQ9O+MN>2g*hW4nlxz?H~GZA zRq}OStG|Q|5>S9_&83_iSytMBpEwJw?Q4Oe4PCj*D-cSDS! z<&7dTy}8wcN_-chOw;MrzDj+8aksrW{(Gia^)u>CkY{GBY#Znx_$&aCU8CnWQSkoQ z@+N*Z^soU!>nLWQLh2-G_g2ce_MWRp0aUF|uzJ)kdyv-0oOw?Fa-La1>Reya%a-Z8 z{&PN)tPfvH5Z=`jz$wB_NB|Hcn?IeSV@}i#$t=@?0sFXZoJKk!WO>b2(>)dJ!yWU zdjDhOiWesDrLW|zA5}+aa`dMg{EMg{%6Z@&T~!X0rpdt+&#&+EQT`40+ziA0(R1+% zpVv7rUMo2jrC`z={8DmP8S04ul)P6rcU97iMuuIB(?qbN&nn7J5qmsIMIXrcsc67G z)kb9-w4qTa$At;GO0cRw{^=$yC(Bx%pMss%m}{pq1@((z7;IlFy>ok*eCBM zbyUW*UwiPipn!)KAUmTS>ICd=;chD$<~U;@oAF^jOxDB?b9mQs)+YuLalbH zLykv#4(d`@Yx-}2DK$5(>{iqAPGkX6b{sG&a3c-g(QmT3;(O&_e17t7bS1=KNCG1I zU~=2)_T@?MU8j-NM)%3UcF3@7P$Mn0`JN%~7J({I9m4!Jzlu;0z0kStV{9gm+GH%m zs`rx~1y1bm<%K!E1@0`U`>=s8lj}Ziw5I?YIw(=y9k(W|4<3LWnh(v1`}CfO0kG}G z2qBt7g$~E=_^EgBvc6>!8|}Nt;QEtdQ7Dk`(h|;_F6CUmXNIN#&|WU)NZ)qK>E7e4 z=^))!kHTCR?`KbM56GHtK_C7iI1J-xR-UO6)Ky5tg%NJSDxDnt%ClV_Y*-Cggd4gR5Sbh|1)Ru&2pRB|m$4COxUvU-b#S*_dU>X@O2F%#J6S1Kd4dH3I%kHD-&POt z&zpk_rVGM<^#@9U+q3$qws zniBk||NjFMLF~Q~D6}|+ zl87icfW>JvJ#6Ty)q`psB~BUB^|COf79#UElBd?LVVSk&VkKVx%dAPY7A@#3^fK0e zYK=*LWnRX7HK^uF6duw4(D!il>z#{vG2zX(^~FMBidVw)0NInfsh~R7ia7NcYkpH( z;@F6ov#cA^>^jT5Blds~eCnFbSz`}Ns6~I%w`1vcUvnMz5EIvW(Nk08E23E+4BAu6 z>HWsR{ALC=nTPk1r#%N5hkL~%kjrA;V@LaFKkO1Hu4xEIm#Aq8!qnxjVc`OVc~v-T zDX-Uj2F>{_>mJdn(=$%;aHp1|HRJ0)9ed&9y@jN4$Ma6*JJEmb^gCyxIz)T?!m;R- zYx%vkg>N`j>V!?6WBo#yemPhf#-yxynsWy-<8=&3aj6ZrcqWyWAUzRTm><*hHHj!Q zC)M)ik1)TsDo77?4O61Hqf-b*9zxP|V2*Dhs7mib%|AISjODC_jmAMwU6a*VLvxG; z243+w^8k~^X`2g2B9!9s5{_qhTjAts&GKd;1UimTX$0ad0l|DjUKMyR&%`SOh0N*P z?E4DkksN}(zU88&LjdRtLn|V}%mtO#k+A9vLDB~V-u{cGX)k>N& z=^9-yjv=Dpnb5rFLll|@7@8hN>-bpjE!T(2{D@bg4CVJt9*>A2?X4W>a9^k@Kq#Wn z6?(20&!hP)7D3g=Ag+>wkeq%`8KLPc7D3hLfIL0M4y5zaI6+!&{T$w_8$<89Lu3*J zrpBEZOAjK}@AmV?<0WL6`hryUBG#~KM6_~yQLUrIIb$|+*f6zr;cpa}THix=on;Lu z(fQh5(k;NnO4na$Og%M)f5y38=H;-A`Ao$0hrYE*n)3xx^QI5b`XW<9;bWpVe`BLM z&&EMaJ;s{9&?@F-j*D344QO($6~6mf*LDjtQd}&v78F|>wjR2TW!pW-hrR;d8|fP6 zo+2|(k*(T#zMh|WA!=WYO&@FomG?PFobYO&j%h#a2(e!rli@{B3>(cyWPHU}gPSv_ z*i`sqEN}Fgm5kTz(r4RyZ)p11pnbKx+Bb$0%%>wXeN1YtQ8Pp0yd(#X-TP&OE~@sK z=XVO6A>8AbJEdA)PfhmNzkUWVXIk&1B^nDcKEW?x(e+*&gRS?0Vv zEOWjd=6qjcfbQefQbKfnUX6iFQs%L81fjL!csX|H0a|2uYv<4-nuZCe+y^WvaZ03+ zIVr{aYD-6OKfe`2kYd@7U_yEX3VRQ{<<-39D?CoIL>s!3;-RqXgZ37o@U5v2-CM_l zS3L2`p#53g@FG!gO9CISS-y8IB5LYGm1KfF{2>puEqNTEcDh{1nwyTp?12Ymiag+a)HoXj1w;m(o20N3SJ;y zyBQBbj0=C-}I_ggDi7iZmne>e2M;tzK6+A`l^X}^K{=_Xn>$K*DGLpnC!`4 z6e~VP#{g63Q1fS6#kkBdr((_xX;RJ-?|5|F6AylwYlT>9y|LKZ4gBk!vv1mYFW^4( zO@O31OWv8YVVkYP`aNzM*57!yuzr_a!ulPy4`J(V!-g&4#upFAdXwKmPl{L9%T2s6 zRJ{$KKJ=GMQnid+W*SYDxffN0jPR!&Qcb4B{6ZWOw2gQsVS?mj+4h&(xj?o9C68WE!5_N zkcgTu*HT0sFAsPv<%t3{FG7oeMAbA8%Fy(8pm_OJUXNO$Sdo&GQuaNf?8kkn(>BrE zkz~>$1R;Hl!md$UPpw&AdA(I@DY52lpqgqOu(t@nXSFh)k>u5x1Q@Y)09vEiNJx~> z3|k-i6Eo*B)`JQ*#+R~r9WkfN#JI>2v5}MB{c4R+$?ZY!npr+C*L;sG0fgq|UYLnNR=hZi1gj<(U=z?hFE`pV;J+=6pxzuv3^Ptf^CL8C>u?u{+TjZv< zQa8*w$Gq%ynpAJ%;B2Q~?<^7DaI1A~KlD{F&r8S2QkEO`-Z!kf_1fFf2dGBJ zSQ0&U{mlr%%gcBXSpLLur|Mx?b3tUZ2poGtRj-Jxx|4 zEM{_~TG>l@!U&7rcg%byz1kMv^a?{)T?jZXRzv4|^)z~YvoXwc%Jq?f5@%=oP$ioq zOr3(~Z`7Ieck7x^CztaFcIJtvG?@!U=gyflWpFu$)^)e*>p+R>x))GuR}GaI(KQ~J zJYUZb0>y5C#g!Oj!-Q0JIE_LY&QcISn^bG$nk`H!LoCe%2+Sj&ovm1C?r)R6Mj2vG!98n~Ybn+25ds5kbZ))U=4+Yo_MYTGPu0 z&zJa$PjeI-#%6A3jzmkB=s5?7!lwwWTd$eIlQsjSp872v0YQvC9+7DP_qCw%5HZ$1 zu}jb~qIezhz6vmP`2fAXDVSQ*I_HznalFeq&aOHQ)3WBW2&TN&GjQVU{QqUh&SmAq zuJ$>1$6LLL%zNltn_utEu;+`2M$%{GdT{gR7F=P>nO5r&-pZ$$3t~YOS>zr+Da#FxG7MHP>@*2HbPtpPcItIyl^L+XKReZMS7+22%OXi=f9w z9%c0MGF}9h-|{wn0PBY}2&*2#u@~s|WoRVLs<|;ypK$l#@M~_(b=QO~&OAMA`O}{a zgn(IVCGQEf+O2W5Zu*(*@*+U!@d8(@m0Oe1(lw^~Er?0x^XDerkJ zHE5Y@V@w&Jz$Z@Rji++alZyEr6KWohFr=LsH`0#5LS=3w zdb)M21;s?hD^s(KVbEwD?v&-|@lL3>dgxfErJ&>BS89Fc)Lr<8Y!lHO&M?f$ao{>h z@KoS?hk*4gt;|$wSYudR1PhkleNHPiEcE(nXuS-RZWuMC@3Aq?Xb55~{nC@wS);?a z8KB2RB+AenkkdSOytg1V>KkTFnf3S@HMNPT9CGnLYf)?@ST!nj2`wGbb9|Wx0xzfc zXN|A!7*o|@S-7!~pGW`#I z4>dmNn*fqlYsWG9=E-}@*vhrw=FBO!f>?Aq)qECv#&A7K=&7|LP`EjS=7 zA42oi4^9wP%?Piyg(==DmR4vJz`SGG?5ZomR;Tu&>k75E_7m__J${`qaOSsN+R2paD@`ivQh+(v-d?N4;EAi@& zpjiHbW1`EuMCipR)&>a86&?hWrZ!+h_rfcz=ST5X4yX zVn@hy0L6w61Jlc(zA_ZL29Qk;!@IB4a(a;E&nUL&_!g+RcwQ zN9J>qdTVVgRBvW0c&BsMWyXRnYmJvwr~jd^{`JmFSZ`J0y1U#h+_3L{90@Gz)E0Fb zg^ku;|{U)IKlI^f~5?hQP5+0vuye##s(~y&aGy3^i{z#7wPY&o~YwSLBFSyw+CZ z0l=&^;dxc32V!wNya%LiJjRj8b~1+o8B<>ng%-g<#vv3@=nkf=ndc?m5M93#s&xgj zxKX3HCn)>h!Y`yWS z`gxxqh+3Y;YP{iFg&`)PHJ>SKlB`b7rgrR$p!H_07u7YHxM0g%-zA@`wHvnN9-y*z zyRUKnrtcEgd&BnIhii|#M_9kx9?Upc*4HYtj#IofW~OuCsZTvTQ6&I=%)b)nfBT8Nb80lzB}(Mqz~R^eI#_l9YS0$noS*nrQ{n<0VXwgjWaA zOwKXUo}ueCEKHdn0xMr~*?m{|vpmfUQO0SP$0LBSxVf;_)m!U~hrsn2g6Exxtc*VF z+A?Gs1fJL8Yjt~I9XoN2b;@M#VJ`$(JOS}MEqZ*jz+>yV8^@A;S~+!9zQO<+v4Z?dQz$J7h6wwC`}*2@Ik zz^2~An(Hxl?U#fVIA7UAUkUlmK3sFnU++Bg;qUsLcMjLy>)v6*4m&Z^z}&A(7Tj8f zP#d?7KiX9s8ddo$h@;ZNAkkcRUd&z4lnKW_{>*TJ4X06==;@Oh5ZmGTU;Bs#37~ z_1DlB>(jo5rJGWB(p>T{Z4)rBa#0A{l@4m2V>fKA`Rns%X%Hhn>AQ(4~Jk3lz1fnq*T6}Vt#%Q7sZ3I6Fb40v^yDq3P?g%#q!TGm(6tM@SLREp0vw#RI9 zYMW@L>aL|?jx=?9IZiTD)seqc24f|Gq@rsrvn=i{DFTTmbgUfqCGSm28{671I|1yH zFYbgUktZF|Req+nu3o(P`&z-N{a#H?Q5S;YkZcJZt3G6B3CcPZv}$;DHRfc6(~4^! z_D5$7=|=2VKwYa?(R$1-Vq9+unV%eTx7dtuGrFiD`>{=MUuwiI((-j&gJeVrOV^ym zlkHldMKO`YM90lhfl_Tvk9I3iJ)R(#ygn+ir%sJ!YOTu)*ak4i`p$Wd3LF@A zQma7t!g}x8QR-AEp3^jlpYVO{_qIRq)y#GMxOI#`Y0NAZ9G>3vJ9@W<6DZd3iV>Bt zk4l_eXS1_{1KYi4IC}Ou!>%tqHmn_<>33%Hk$#^Mi?rXO4 zyVDE-9dot)Uivex{I$3#I>qnyP$k|1n2)TCTZ@5LMbf!Y0f1o~2r8*g5q z%|Y+FcqDZiiq17I&|Iq^gizOxp@L3#W`*?@iGa8fH5n{bFa=6F!lbDbZo%w@^C|I&SKN)AGBu9esgBUOQC19-dzN zU7Zuq?$Yr}Je~AoTixBULyaV8(DTh%kb1|T&{4C7S&E!87TVeC9CxFe8nPeTfvhbY zNlbPWZm5v6EbcieoGdS7O*3j$lBsnHmkz%$%?RWl55i@a5$gy`aEe>*Qm%|)+bED} z1Tx1+tv*MP`HW79eG!nFM6Z%n7qNUy79&R~r<+2tImelG&VpFCbAVONXPX5ruTPtW z&2T+z(QER+u!CA<(uck#VFj#3C@oBk2~kPktRq@9Tal*Y3ZmZQPxLCex0Ym?+!nUd zi$B?hHE4S18`!&cj9QH}oJ)M*d-@BhwPIEC~g1h$&$If`+uQYK zL5J{W0!aw!cv0U@dfby%A<&ywIqvGQks#Am6Z;T{WmdKhyS5Zw4*6$3f(>NKk<=DX z(If9H?b2L_gs@wBY^OkPU7kypSNUlPCQe4NkO@nKML0EHvS+|@!k6H+GO z-ENs*IAqNFngv~96GPPCe)I!Mm&6D;1~yYso}%=zwQ^(Y3XTWfoJ|@PLsFc$~?KP~InadS1$Lg5Cdd_v5lvTVA zEyHHJ7H~dW^8zhC^cAl+{zG5yMaf%_=vM+y9|?k*rdneQ(|l|V>!iu_!qHocnVL5T zo9zY5W0^JD$n_1h{%?`)hrWz+4iA0z)x*&XE~FkX)5%`8jGM0lwQ;Pt_W;Or2d6hi z(eDJk943j^#DNCM{A|deD`s&_$De=lFg)*h!_F^1Mjj7i9aix=f;FAOmGN+fTGRS9 zhF9D2qt8oFG|Ft+uDznF=>afM)+Nze$u6-VlLklEScI3;qXk0DJbjQ8^GXF4jCIINgi!Fb10JWdLlnquOD*6EWjsandlV$tU$ zmg+4{<9Y-VWqVpg9!5-```DJPm*h7T1Ie7nF!dXPJP#w?ujoYlgn%KOO2CCl&*B>I&=cFo-2)P7SZpm=q@EeE96AGg1#_1R==dtfcRaKPHKIZS@&%ZS=XFWNU8e&rR^ zn?mEo&?qx8a}8%{3@_$=Q)4!L+}IRCkxbK)RA9;UdDs+_D01xdGlredJ~QlihJL^A zdQy6A>UrIAzUh;#zOHGG5u8mrhnlvhRt6oBIc^=4S=Ci1D>BW8H&LKO1!;fem5 z4i>Z-Ud+w00<)a>HemQB3v)94WP-NYtE5(HX~ul|5XrrDciL3FFW_5;{dI*IvOuk#IR z%S&-HUFRl!qcFLWYuJ!Yrm_SH**S5DF=_~{IdxsD>G^vA33x?={p+0%u`O;&1#TC`>~&i9bJhaur$@YK-9E|9hOL43E6xmPH?5i zRVcpM))ScXzMr?)7NhgzZpLe2h2TTqhOdiu?mZhG`WnJou2sA`UJ!ViYVMM(y8dLG ziA|lanHQW>>P?-)W?}Bv$2r$yldf&~q3>eSdzb&Emyv_lzjhe*oJ754=s4k1uMIQL zaC-Gi<9h!XaclMJ75$c zOG)VqmrP50kCtx^HAqILtZ~R0|8~%w5HNlZ9#E>|#*BcaO?*>w1lnKFWv2_Yo?gN_ zGW$m?n$C7a{b(j4VCsUy%@v@=5VqvHG~W;lTJAHC-nn|mEXl$X7Q{QGia!~tT0;mt zEmMoH3~@vgmT?NzVWzA_Q;rh#jsyBBbMuI`>P1n(;}_-iT1b;jiFjGSS|L_>RoI#ycrsi4+cxd;Wkxan6;x3)vCewB31r6At0V{!)G zOlw@CbKJ+az9>8AM&+xu;_!ZxZpY)xVj)_e@hGHHCOByeR zeka(QFJNvp0%`}szt_l-D@F$tS3j7p_1r58(A>X^C0*`yD&>H^urLzZtH}5Gf_at zGq-ev%_1^m`l<2vT~0gf?=#>ru(#=M|; z87XJ&QmawR&*B{eqO_ndt_jgGT$Psb7*k75D;9l5(5w}ZIaN&{(NIU{SsJFOm4tvB z3uG}vT*?P(@r`2Ayqu&BKgP{EuL;cdIxy!8%4TH3$=!Ul%&m~+E>mn1FxT{B9aV5j{blCl=C%|yUc^q6*R^HVbRAhd^o51z#m^_7eA0J` zb9Ct1*9^n%-PD_##)(axe>IN;C7l;*{9oD$F{VVN9LCGFXsI_hlg8YLiB6$D&ts>( zVA%cH`=|$Oz_GQyhM79y)N%8rBsi@)mJjg!Of5be_4Be&gjUaKL~UC_*BI53B+xoH zuT$TsOCI<_+pEV!O)kXCf#ary4Vo1r>n0@0x*G7I-wFz%PC|}Ks!hku5v4sh)YO}A z$}vq`ho&ipqNo#MFE99$DHL=ILdVlt^k_?%Yt_4etEFo;t?Safeui+$+81*=3X-%r z!xeUn$+SFxaad%AR#Ta&V-@mZsJ(VwIrlvIYM)wH;@ml0t`fT-UVj04*FaOXN7qI7MqktO^lwuxP&XgjXj5!aX^aa_fm#SEQj={wX z+E#sSTlG1ZnfTCGeuo{K>48*#ymQ0(I&#U2hocvNGxZefa=wj0ri@$6p$)20j@=t(oRo#VRlLYlJo07J(X{|8Uy~G4RlQ@De(OC9UF7#_08+=e`ck1f#q8RcW;{5h z-_r2f=$KryEEYE-u^Ad#3s^o+yAjl`!Rj>{1eT`d+6EF`Ym%Zlt+&29Nwst4ool8m zKXg33_Q$>om^$qY7_QW(1eP8!{f)UyExrsb^II=AXjq#tnN2mH8JYN!k~3SOO+@EO zKT)rd7U+(e#)uTb6A(tXbduC++q#|OByeReka&eZ$hpn z(e@&29ZULoKAr}zp7eVf0Aht2$D1CCPK3wS=HY6bBvUIW z#g--BBbA$_RVOGatH&e+1??hK5P1_RO;8`NrPaPnW9PPhdF7(>t7}nUB(z?dj zvWp++Em720in-xJUhn)AV>%USuGKlHDQ~HfYx+j+oM(|aYs~=O#>Tyzxr9T;Vw)Pc z8{662tBCO~?-Nq1nd5!CbQ-LfsV8Sst&*rfJXCee&JyJR8LpD&)Uo}+DgC82VOrP5 z(v==)GU!*qB+W}yG|IXt{`-SsQljP97tTcM_yIRBG_)2-e2zxbqA{@&)y3vrlO?>I z=30)hB|p(r5+<)(BTzpZqcCX8e5`t2p5;fM5zwwy9gz5D$^jgAq!yn_vF-{6UDa_U z%s9xp%y)~@{2F%x@m#nbmORGRhrVlPU4BhIRB><$mNdPSkNU>M-uhdD%0cxU^OW^5 zbDTm`>aQo=FN&QBoBjBg;E92M)H19|I8gZRBm9Fy{e$MLwPV!kgqHgFNhb|o|G_to zofgz7y6s2bFkFAh1;c$$JT+YTtM4W6f_wkjj|`Wcbq4ho>_2pP_~{ScHQf4%&yZ&r zZn^%uhqqnx%3;q=c;KCK$LAj%Zv5>JP|xO;>%VJw+pAwWJowZz!bouebIEUZ-Eelcd(7;|`Gp=9o-Rjk>n1Snv66BE0wS=oWD)b>qfQEFnJj(6>6M5Lnu-Ne6M4KG3V*QWOquJ=V$1aRO7u z*fK2h3aS@oYrYykG3=oh5RM5S`a+YBZ`@CQ=t~^kw{JLj&1 z#&h@PZ-43V%dfw7c;uP=!|3t65+B5V=ZC-# zKK*QbSll!AY8V&qq>p`g*!k!eu|0*!uS$IT*J#mYn&2qqSus~{1cEC)?#ZjrKx6Gh zmgkrrue9gaflMbHH7TH-v0q8HilJ|9akg9yQHyIt%)L~yd{@~|X>Kkmsqy$`CtC*P zFqf%)?Pgr%k>Xk`g0a;)0ZW(p$RYhLc~%`O4^aM9p86Cq()tbBkGF0uwB|pI z@Ea~4SJRSQpfm}qv^=gPP965?TDu)|8*#lewQJD2rY*d1>otx9@ho-L z8TY)>-W3p57=2EjcK2L!nN&H%=y4#!?}Cbjx`uRJrn z^@^7b*Ij%8c{O9PTR(CC@GBqv_hko-D~%qN0DK;^o$n_dv@*^9{TFDc3t-2xM3qS@X1{G zWN(73A=`lNw*WcPBr5jKyY9sYzVKif9=2xxc!=*O!bE{LzWmbR%;%pp-1F#{heJoh zHFEyhkd*)ra;*o#(7yFAKR2#P&}kG4*pMCPwg>8k z0hW(DSdY4ZYy;en7B+DXqK&4t!X%*&#}SXkwNcw;86s$o;aQrxaw}oZPZ$)i{Mt%` z$#7<2W7V?!iHRB-8AA&jZO3Ha$}tRqS7jBDb;;FcVdL5y`jUC~h^1u<8!$U4tOF~3 zJ*n2yRosraE-pO(H6zpI*F-a zBkPK0v`FYg{n#Dj)W8_~#2!Gu3ZNta8~4tsWge@GYO*F3p2p= z*iLAS12tS#rsM!_juT+FnRBAja=@*Nveg%EHQ!}Ec834sjcZ(W;W@*T2fi`9?^B<{ zPvO4wtTXV_zevMr`NO|@03RB|!{ZT3$nuU4@BGl8;*V{9-HZ2yG0rd6{^%DU$A_+O zkv|4F(Ob#E2d|Mv?Cysj!v~h|qm`L!E;@HOY1hu-6OTWM{d4h0Baiu4UvM_+?|%48 z7$bL;&p-VPerou2mtKgUkad%|9)^X+k&nk!pc00M*RY2h4EXf~j z{Lci2oUvjeKQ}{fI@zX@*J`V#^9b#pVjIn*IRz1)Hzu~BL7glv9HANi(|~Xz*e54R zL}P@z!iChXtCBIEpB-GEgQ97|@kFPc4JMBbeGVX@rYS=oY(QuU0@@wNEa)qe5h2jp z*jE9qiG&WW2Xz5#!$vv-Ak#X`#Rj^j!TDrdQ(BCRCUsLNfO(^5p`}Lb6Iow5uuFXv zTEv1$KS1u$PYs+G82AcA9a$`7Sp_Slxppwa6)DA#;E-dXjqbz%&mRentX9EX{TQkm z(^^AgX~2NYuN|UE-E4dd@UsEBkB~ziN2C-pC~1oMPLSPhUIVhmGIchLj!AFXV|)&? z%5%1TJ=ko}n(V-lYcJXW#Mny2T43bUfM1%67B*Tk2gj_ubuq$lRhg0_iFvXRo5FEF zw~*_jt%qLyiO;c9PN7yG@G060PCI3||B0uDJ3s#je%cov;9h(2;?uAx`Px75m9OF_ zg!i3(DtXF0{>*{lw3BuZ=bc6mU!BX~GfzG>eB|NBhgV&64*tmJI-&s9ON%}h#(n1C z;o+(a7N2C^_kvT0N1plG@N<81FYaaRoKyCq@77PHKW>@h9tV#e8-D9A?!!;U{>-ah zNqU{+6k!*KwM6=*A+cey@3d3#A@&1LKSQ22-u$gE87??=?{NQu8GGS`6Pn*J$ENRE~o*ed}(e)mdl6zVaHAOQsNfJvs z3*#muLWy5eiXpNS5(5QN1e~4t6~y7$-;v9PHb2os;KF{3e7ELzyG z*@E!5V3{s;nO4Kfi550;T<%+ABib3v(<_TjXp_l!yFd`#VdI+AwOH6xEzJQ}>LaJN zRRZNpmOC2IIi5K*$}lM7iIzH9TsT5=?8U|c=*zXoe$rULF6B-G6-&;yVHl$>qx+f| z=Y}-VESU$!ZSkT-WR8IJC3OTkFZLaM5uvwITjmhkq|>ojLqM+R#XdQE;1tMBOvZv~ zYH>i<0%DsQu}@@u&T#b4dAx4 z1VbQev|0@-2Q6%RtOSHTW3pK0$hv4i%RE>wB}rcjf^k!W3Lz_&o%qb8}{tlfuE`c?tbVoe1QA? zFTWJ~CNQJ`AEq8UM7=r>eN{emRK-;HzkT8}_@MHw-vK{9`h4;VNDmJkZ~xIZ4Ez7x zPbBu0pS@|g<+>|T1HbS0{wJTp-;WEmz+QUh8N=hxehuru9%K8)82k?7$M=UA4#MUj zL!k|yc75=vXNOl^c+POkwd42+v0Q8j*tdwm?+L#B%{L7D-+ohKU-_AT9O{2(wFLZL z-B(?BHvWEMe2C34MrgHNbK$x83E_`E8m^JhhfnRoIr;v}E{PiW^e|`;@|h-p-`V{3 zSAWN_|KEgTQFhy#ZU_piK#O&-=lRqKSfxx08)f_>LMNO4V`;#`pD-X9Azi|q^);bh zw4{JC)F`*;;2)TqYe8k0C{aKNT)pWuUEm!5EV9tTh9g;wEXVey)HQO9#MTU7Fc<4# zru0?f-gx+6nN8#QB{F{*Yh{_-xqyX>hz>7m#JS$WX1pe~E%cF8;G2mh3}z2LnkM*o zz9mf(OZwE1V*;^F4IV`5z!>d|{jdR(f}~d2;vZ;R{hFmCw_DhxX4Ib9!YBnJtPmSu z`L&q{0nA01HCHtLW5skCtZe*2Ett}SL5}uCTjWOPnBkk@8ZB(J#b7ToSDTHc3`d54 z@`!^amDY__#Iei;zMAPA&$Pp#7!CofLnK;iNFVNnBkaa0!}Z2(VZnhG`(z7GFoAUU zn1>ZF<-`fHNC>4%xIIu7Hi@xc#$$i{gFOgHR2PxH*oFq%Vi(bUp)da-RoE;tz`~#4 zOnqcwleYPfjtRfCu;DfWjz!N06P2Zve5AA_PihmKBgf+=ll4I(9Rci;UxgMiZVO@` z;-sPBi~0i5Sa+_(%Vf#E75^*woASc9y$8C1gCZ1bEz-UmIlfsEhv?wSyZ z@I`s_n2;=5MlrZR%A}ph%ypdcjkBRxgQTCvu@R|l(LV=SYH2ptx*p%Xi(2i#k5_)( zOD@9S$@|U^eGGl@dw1`B^vn3^U;JIV9?9V^yAJ+Z-ulV=hu{Cp&*4MepSku5@)9ED zv1bnqH~jVohEx9Ie@^U$|LHx$JMRd`M)xlKh~x27#wX+N_J#IG9~mEb!yfwJzxJXK z+Y@5&Fg%$accNnfzBUk{`L6%_@$rH6D=)(b$q|{Fl?om92|xU}=o^0L_TiLY`1QnI z_=~?W{y1eJhTom59}d6$)mIE33CD8ddp}63k@3On6`B6FA9+2-uiGboZ1ebgdf}ll zJUoU^|H7w$6U3ZN#IYSZdUW`O5C3^Mj`w7C<9lyUw24)*l59J^YiHPnwrghE>a74w z%hV?Rq_Z%2Y!)O-%%VjT(c;m@Z$A+_oS}lI&TyJKz|kVYZ#M0 z(pQUHhvu4d8PuO|@!wSphz$TFi)x=I>9Cp63sCj zn?BHL;3=WWjzJ+b9v`)V*cMK1!XDc?MgifD#PuVn3!d@aM#PqZOX-r9PdfGd7$F&v zj@;xQE4~;9j8NT3qJ=hkQ=~78bDj#2TcWx)QA7oBexoNt`mN(dLPO6DNaUokbO38v znj z#=<5uiZR^Rh6smQ%d<2!S_@VlTG(jwfRHvI_QNLDU=v8U4o6?u)bb_Cm=2t0Nn|XE zyMd8H$fQ?4iFFyIpG`WgZMNAEw&;Cef6_OD?sR-nrmlp2(p(AxnO~5dkj!?>p+N1; zQ!>k#3>TZDsIKMNHhoN3vrY1i>1!`O4}X;NWoMl+?0?5kM!Wu!3x-op+KrzAt`ZI( zeoXUed-lYB4fv7DHgpZD8aIF7&f&f%pX&HA&pz-;X5gBO&comB3qS7pu7}3o*$aE< zUwy$j@%R2d@RayeGEGmj&^ty7*(Br=ZKqIan6B?{A(SPWky?N4x2^ zJBIy-4&y`PU;M~lkZ56x2e0YFWPIov;_&brew4F*kbM2c=MSgs3D*eyh-X+Qc)-0b zq=&Ga0hTYKgW6VzH5?f4upc(@{Ye_(xHHTeWO9s>F0nT9Z`u)#dqf0qKIjy1T##uP zPiNE!m}PK1YP4upNZ~!lote(5JyiAL?4QF{g*6u2WJ>3Jyz&!Fd2sSI&bFx#6QkFL z_z+3?vCB{>`jQ-iyUIQG!zQsY6oEd+pp$6HmzZc~7B;P>lVdCol`U*!P1#?S$q9r$ zelo0PY1U|AYlqEfX_hd;3V|_JEHTp={({+|`rOEhHIy;Y7dEa*-Bf+}Yxokg zuyopTM;|(ULWz|U=M^?_5fzRboiZnCgjh7kHf+cln_(l|32|No>ChejG(x$FNfN*8 zL}$`WKtBhirIe!uP^_}iXAu3MF+|ek)_?#TL0zk40_sT2`Cg8YU_%$jE{Rl#-6Ie; zGz@BSL*^hQ6=_Dy2^)DF(JwoM>gN5>k+lHSkdStf*ssOFpsmp3K~q{QI*;qt>L(U9 ziIKkr)_MkbeiIU8a}tK}h19enRzfgqENxaE8exUd!baARed$LNNVgGQ_`{~P1`-;{ z*bWe4lSsdg`GJv2I34j-XbJ6B(L4*n?ToBrT` z52w82*P`96>w zd;HYw_rLs-(P6=tZsFYW@AZWT&sSY=c4!~OANvfz9{Mmp{$0QDNn;Zng9ow(94B(~ z?eM_*>EX)rzG*n?Wamc-OT1DOx%E@`55MxKpTY;X@A|%1+v7@~va8QO8`u4&+ddQ@ zB!j`Hj^RP__&bn~hjsnh@XR6jeaUBIU)yyToj2V7Q*RmWz3GQX9}YlB?K*?^O&ps{ z&L`R;oLbnd%H%*s-2Jv4xY1%GH&rVFO>I-q_2n3fGy**~f#V(tPP4vBP~8P?AQ1d2 zWGhQGm|9#A-y1@X^*$keOT=+TE%}y)(Q)o;|3;zbV_At7O@=zxN!Pe@EeGB=)GY#{ zIjj>eJ+$$5)P4Yc6u{#nVHbm^ixizBR@AKu}>NuXS_K9?3PxqeCFwF+?3X9}kjd8qXgo1gp7NleeuO1Y}hu^}+TBg&Iz()bd-bv#3ws2)pQY7porIGD{>Tn%i8{okX&hkoccH_Gp6|^%E3DM%q=POm`p@9d6rp@baX3z zT-Bn4nB5=l)qCx6(dSIbG4Bq$x^eDm&wFwDN*?d2#zls7q%Jp`<2I~a#w4x`91KbI zl$@|)KlUn)hB|Z!#ksocA^*|mTx;1gz zRl190^Kqg*EoKM23SAwf-C+7`I(%YbeR96yWNqRHAF3k z>uzNz?aSJR@n!7hAlAOlm~xhtbPMyw*XdPz$YR<$8Cjn~i=KK#puVt-o1U}eN9P4s zG;`6Y;FzcCrMFjn=9)gOwtMTF4*2nYw2HQVD14_&sg^BcPxyt>Agw!CR2fd{dSy+z z_`EY-Q}rV&+m%c2#U{9SJ3HO| zb_%%xE4GKEo8iwc!8xsefBn`%5BYsQkxx~EOZ&6-?=E_VEN_`U30FJkBIO{w0L+#u z@Tt>twJjV>nX%*tRL0A#B(GL@UB5SKnoOh!QY&UJ5NL2`KQuIEzUw9^J5Dh<=G?O*ZZXx%tfF;Pe_rj7 z!X;+t{r#@Xu$Z3<(C$cZhMA=%ba0u61tE+lfBI2FD zMH@P|8^;v`<6!8n>{yFi=A{(`-)UX#h2S|@;}r`%-B|$ z_IP~JL>(#-pJ*s_A;S<~$Ukvz@I+5+R}7RoYM}c{{)$d*p=n=Y%Js45ou5*d^&WB> zy|(cYr=3kM~0o@+TK{|7IIhg0Pof8L;<$0AcoudZQ_JjNxOl6uhOm>TC z`ow|vCf8REGj;c7b0y;6=))*miTNIZ`W)DjLb3(Z?z=PKY{Z7@)J%vHca5H=8Mx-S z8$pdCLT*yGhyHY30~akDxTZK7^ac%G5hw|Gm%T5&cI&vi#g&$hHGC45l4kJ&R#MAI z9Kj5Zbi|p80yP-7KI9xiU?SnTau#^q$$X^eTuCI!w4Dwn)^dhB_t-fJuY^(ELIwZ# zuTAMSHLl>sd+GG*#}L5}DBR%7i1W&Glbz2_Kw{(x*qC{L*!ba zgO*%sLnGIIb@u)oZ&(#;4AA=`|I4M87;@GS=bI5%%uhE#id3UOen_I@&RkC@htt>) zK_;@y<~C3x>f7s~_{OS{!y7mxA8JW3U@`@-^Q;{^C8PLaTvwl0!u*l(3kAoA7LTF^ zQ@-LqpsV9}Y8R)!u!n!Bi?Hl5&EQuU@X|u@h7;fVUDSoTN$YEU0LlQhFx5XsMeg@x z>;1<~io;xzAdhf>#B@qMYzlOLkj0-|97UH|mv_p#^;BXU?3ikeDPnhTee3%EPgK`F zH~g-mVG(RafGd}A!f@(Zyqw#=+tFIB_rEK!Qg}Ub8Qx3jPEFazuIcYyPr9V4i$EUq zen#aX#w;S@3}~Prtu5FNEaLg{N;98LY#JY5$10A4CmVieT6IRsA1ke2#pKv)epM{>+-$Y$3(4ZXml*DDhIk}TlG>He58%MK8Vj-Q z*C{%Ci9N?2PDl0Mj_hgea506cad={=aqV%mhAXshCK`HAz+?YYwB@p@F;vRx40eFs z9apto6&@6@ax71Z(K_y%1h2Su+>49tcq)o8D0dZUcA53snq2+#jV-X^c4%hkgl8?l zp*g8T9dmd6p{S|TLJy|*|Jvg%u? z?PfzT$W)#B21Fpo`H=<}9L97;E57*e<(Q_mh=Endabx5kDPjWGyXaI>AITyYZbuWh zAK6}NzVvjp?Y&1oca{XS7I>mvonieV*V*9Vt4dz9n*>JE$ICwb4t*xH<)UgW zG5fb#;Zk8XOkyqgYQ?ldtyDCsJPn(Q2MG=D^rkN0XMXf6USk>p?^06n;W*N4%HmedJ1z%tBUmOk^-+ zG}yTEB_|l$U)^k58Zrn?CAJt{HRe$J{MeZ?b6YMHP#52K<3QG@279tL_%GA6k_1O% z*cXBN*#gP0cuP?se+~el=@J**h*-%P5_>vUs$LdG7Vb>VY-OAKYXiuYHVOd zi3@)_S@TyA-MgKi#82Lm)#qu`yOeO%GEtTL>QR%cBif_8mTz560br*?^r{H@!?SvE zt;=HxTvNfv9}5DKXqu~dgM}qt)hAa`+R#7$z8#g^zCSQ{MQ@f^wlB10CBHL#*mh~I z-Lm{*;ku!pC%Dsd`jvAdMN+T&@$bZ(qjVjAKlop``$A!-Y1$88hs*ubV!k#{m=+Cm zbK@Fp`x@4=Wz%M}bCy79mOhp^IUY2zt50J!n%cv&0Cc+&@e%Ahr1yVeXNg9Is)ZO5SqKjKIULB{|$_#q2Tq`-ko-)_C7~lKuf72}d&L}s2tu`WWwziaIudj-c zBDSM)WN7^VU50)9lUq(E-!T##3Y6ZNrJQFKsH}gUMiI_6+fQOw1guIm&}uOnKiOl$ zxb+cx>cPIy1H-34oUsaX@CS@QlUBZK!s8}eM^s`E4Qux?TR%T4LTnch{xjVstvk*?vj}$_|$-($5S()d zoySYQx3@HvSLM4g>Fafa7RiK^^6mq_*CT)M0qbR+$9XLaXtRJf)9}bM={jf5-d~iW zw5>jAyWDScf7F%Mgpz)Qi;dDl5kBreA)5oCX8>#<^!$_(Jt4B`R;Ojx{++_6w@C9^ zmTK}w(_@jUc2&-r$L4BBiKOH3y_0CatSTg?a{CQ|w#X#ybVqSxvbuX!#v$w)r}ydT z`h3z%)qkWSIo0y>qTv+NZiRP+^m?;z6n_;KKH{$UfSMXU?I11Csj_H7l%x~s-*fteQAd)YtsuIp59%;>Fciu zmS@ta(dMT01tr$2&O?us2UnIXB-jT$r4^jY#7Z6(l-`L)s~9SUnFzRkc^Z*9H0}u4 z^jT{#h`N*i*y|;zF*k&tlYB=fB_sW1o#m_d6<1}OfsBpX#aChvaM+A0P#N<;=+KRC z(%8gFdk5>dPgxu?O7~y#pBQl=k6}%IpVaRfcZ|!EJF@1PUSsd!3TD|=_a^$R=Tory zrU`)mClmQ1HBmHS4lKJ?omrB*@@L*Ff_)6HQ0b@MG9On-JHWfNFMXW%DBNilmEK=} z+OG1JhI0OV=4K};p?@0qRO^sIS;8&99`0-Bnlox3W$9G0wmSv$7 zZqASd>oOeOab9avmpB0e2|8vS5BN)$n!hpZdkOSAvu7*Mo!a`6aO8EDTv0Oi|E}?7teE_g<89iHD8E8>ScR-+;Y8&59Ap z(q?TaoqC0Jc`H9GcQ7yyXlajZaGcuX9$iR@&XE0z)N)!4RL*QvzMYjyNq_dyDSrV(lGa2dVKX#BF3&$LF<#{{@obLgTWi8+FO=3tWLj6wOi48J)+LQ7UE(G9ybdJL zUAytIx#LCkvps8g-q%9y+=h?ooBH%iN}{e#Q~?1O+fvcY*$h8EYz>}`z;~q{VHkC3Z!gQZ-=I9HyKRMN!9$oTNY~gN@7$zFLM%2{KxDc|FK)g zAQu>+-x^`lz-N&x|F!q0?V+mVAGC4eI=ZNbeyZbYy8C)lrZpDEt-1woxFe$O??$}m z`4$go1FTI|Ukl~*fgJ>_PsNAfy%SNtU-4Hk!b@eUPv@fK2@}XEl($C}fSUT@LG1K* ze^MTW4Vwo!`8{H>^`xip#!6C{xBoOX`ktIZ_e{| zfvcQH5lTH#+npiu5d@Bv=O(P5hLP{+hGt##r4fI&K*Gr()?;3 z-9@k>D(K1(x(@^Omu~jFoKOC1njp%XnyeauZnyoa@}vXT4I&22Qc2kkmsu<$R=tHe zT3TMHC$qA+Yqu0{%QK*4JTx{O!b}YtSso_;f_Ws2SU0d7wV5-rY#o!mFLQYr22vvr zmPByf694@c+*Gkk0=7Z%lt#Ku`k|+Z9{TgE;*6GXBkbl6e_|9QiD#3#Wr=H;qa0TQ zDg5U?;5K=p)A0BMt5SAEw29m+Ax>RST8|Q$fYeQ=ng4^9PFU2>AEAWE7-TdbDOAzLxwV1SX`mc7hB|XkoKmM1_HH9B8*2dYnfG zNoEY$>I5rt46`OVHDTxALXQW zMlb<$!B)5fe2UyEi<>3T;Ufg*f~OWwAisQ1k$C6JkY_thNZ^v?|8Zpk^KOI+hUQKd z4#iKLENzxsxpa8OCg+E-IOaBhmrT-jUUDXm0=IimKn67dp!rITf2%&Z;eHNpF literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/ss3.png b/luci-theme-alpha/ss3.png new file mode 100644 index 0000000000000000000000000000000000000000..542ec2e5e2c3c91e9aca9b94f88dcd9d423bdfa6 GIT binary patch literal 493495 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 !Fev3OJ%Of zPa&k{2X8dD*w}V00Jps5D-WyfT0k~`t)y!Pn+^nSOjV+ToBnYcGF9-LPaeJ>r6ayE z#2&GJuxp2P6r11tg&oDg<}a@?oE>leQkwjbkB|1=mb{!k{*!YNeh|vXM~cZ#B#t=IM~cC+91Gq}+| z(moU!Ek!RaX;FQJWQgqY)sf3#}b{_|}ge%sDPkR_twTk33N+ehF_ zKw8cTWNyv;M<%k6ej)oD+%H&%zTmGD>4Q^*#^KV;W*ixpMH#vQ>=E@^P-1OfTO~{v z4Y)}jG223Rcp8nels4>Y-vG8Ya@OP{Cw#tOXp;etAIOu#4vIM1fiWFsVU?rGDFvcc z2D8IR2~05g)5Z*#;M~q;a09^l?ag3f6ueyN^-V*QtVv}j(p*fL2tg>(Nk>i@_3E8! z!a#j{6omQLh?8bVR>wyhz-|CnHg2{+`E(OVpYeMPwwEwN?W!e{z$K~~M`;fpUU7tE zHh@#fJj|uGXTQqPEz(JFP3eH<#>m2(KWV{^@rCCZQY1H?m}@A+&NcR-lGP)g8?|7M zWAbOyWN~>lhY~^yJR1NNa@`k;Cm#Eo?W(v#@|N8Xeo z;Z0u%Ed+4HMlT;}0U&Dz{?B7h&+7?yl(&TWtqw}dt|eUBlqcLFD2N5fnnp^;-ay1; zoh%WRDWT~F4Y#gzeMp4bkrM&ybJ3xV+0``sbVQhIcWIpTZax9+9S3&fANrQ{bDu!C z@AriQxWDip{Mm5eyV+nEuo)<10aem#8|mA9rVsTr6`&qTxH{|BX~2F!m9{1B&lGMq zc(Ad())AU&k>6#>Ze2U zS3*#wakY+6d2QFbyX?a$Xcq%`31-r^k-62QeN#KL|Dh0qwV<~VOm5pd;HEg_uzoiW z4lM`zfwXwlzhUI4C*_3vQ`%& zr%!$4%0&?`A1PiE?9#BGQrm!B_MfK%6xUNEPCv~6$wR6Vs@Mo@TismgA+oN;WlVpI z1vj7RF?pj0I*O1k(rp{yxK3=xv5BH3+i?Wem`BnFv39<}Ca|4jy|Od z9s&DpW)=ykg)Liq*iw%TTpN50qk>5-=#=?Njq%hKMNt$V4D{(>FSAoRs|KJTi3P!Y zFY5w%SSOph>87u20M9aW$w2<|7{{eBb|b#iV+o10aFmkR4JrFTPTuleM~eeKlC6AO zh#Xlcp4|k-I>J8SU? zvFmi;hh;#bl_{~Ul}?K^ZVw&NmwK95y!uO=D=ak;m4 zb0+C!zLlxPZiuD+0l28PAKJOj_E9to%!i^!pSJhj_P#rrEBVhJEpqe-W~>aSq~f@m zD^zUTbsxCg^>K-CS)DtRu008E_tcQNy^|zIr{i|-gr7C}I_I}@AzbVkK;|&Ce{S~> zxG4cXlHa!dbbXlEaOwb`)|G$+K_JhlMKE!InR+2nN0js#!Q!B-T3scr(Dyyq{G7(*|3?% zI(ro1@I;(FiKHVNJ;{R_C&-f}Q#N;;b~4u>jMNWcH+_gs1hAU|#SgOK)@ALoVS-(y0?c7)d!-tJl9A&YbE}HR>)jepHFtU`d(2+3fb~fzyH+s{w zWuXrECe#aOKZgV;44C1#df|GNo0SkT>yOgnD-|O@%U`+{y@W z9rxj4&v5h-#6kWCjSQd=9^lA92R(KPa%vj*3BX0sz8tI1bpv-f2_^LMkx;9EX zO&4F^27fwP&Z35ZucAqyxXh$pDlRvj1nOD@I-HmIeSA9?hR^gS*-4R}#YVLPE3r*= zEQ#Ka>*?jw>GJq-${4V*$rcLR!mUg^p>7MEh~3z=Gl_kJS2lL(2=R1QtWNyNS2eQO zHx2AYF!_--xn+YF!wU2`I*t1aV1xOgYg3ta{Bz8odq|{Cn@A=NMNt%`ckpoCbnV7t zJ1+p;deN>sS?D8qP{+sg-cxkAFZDNptuBp=&0XAIh}()wLu|y2G&ybi$4a(L$@=Pp zGpIeC>HIh0*tVUyA8JgRmh>0DRc69GN%YQ+@xq-V*$Bol6AnFD6t-V7u^%pP=T72_ zhTKvPeDa^O7gG^{1HaJ-u_}vi2q^{O1vW_<&Oa`Aooj2jmkh0Ar5x0s6RFE8?UtLv zFguI%C0L8#_f2_@qjcC0z08B~BMd^J@Tbq|Qn7Y2&)R2sHXVf9c$_xE$(7`jlVY3& zFCxk?Q!&(~;M`ND9YR zpoF=otz|Gq+@aaf1{lOS^D`Rwk}g_~t98gA7Bax%B9+H3@IfP$JR} z5Mqy3k{q~U5LGf92VAaP;ariKOi<3wnE-7m?PD0j>@wlil2oPvYL3Yw*lS~0MDtfUl6wwrPFe33)xI5lK%cg2H$Je}jVbhj zql_K)D|hTz0U4M83@pLRgmMk$}7D2k%QfaX@3v-2}j z=^RQyGE2((AlbkrKZ|qErFj~X`46aM$X^MKH3TI9;kcx;Z}QqzGnNu|IYD#1E06qK zg#GGg`?b%>*FclVe=fss0$W z{uGn7k+~A7K?LONA1RETzKs$GSI1nnQr`s(3GST2=8y)U-OJ`}(*DTh@{beyKgMWDjset(9YEoR-rhLC4)vT2u56q7MKI{uBcK7UwK0wo z=8U=-M7xDf45vj4GpW@qq(kLHINS>VQ9NwG@Ef{tQwYAk84pnS2)*;m1S(&xW^Gf! z8^QcmFogWp-afdo4{=gk(Mz5XyKtqFkq%``p!E6)%0+^D=lb^qpxj(`C$s46MCZis zN51f8eBu}Lyx;aW?sMel#f!5^7BNwf=MERONu6-O2=mZGpozDBgews;mitA(I{M%>C#8fi|BVbQ_CA8$ zlmLr_xrD6VUtfFcWfo^h_-^2bXG4eq#UNs0)2S3C1Fuag)U(nrr0um!+Nz{o=f%F+ zOEzrg{N!XIT`IXS5+HWcaK)aHbn(IQ5oXg6xD0UEn^k9O-F`VCv&qKZ2Rl<|YyA@D zY$3B}Cw^b(BP+=Xky`}%ATF#hyd${ZJLwfYsGCVg+E=A^hHw!FJE^VXkK#)*GB5J8 zSm@}FpRtk0{%5P%W{#UJt7C>3^y4b3hj^&zCa&lS?A`T7NRHQrorRR#KPs zrAI*Sq>n0babpNqJ-H#G%Tu5p8->k*PsWJ_?b;sw5DCY5TNe)8o=M&0)%?ah=v<%KmsY&c>Bu!`0ZaInM8xsBrwlHx}{Ne7rVXBrvo+sva2r1o;+-;tG)+Sn^+ zCox|5(NQ*N?Z&Rv^M);5sJT>k>E^BIt)v^jsgC1__;D#rHhkyMf>7Fph@DiaY;wuE zfby#?MWxHw2wA^f6gYuDuk-X=7l{fv}tPE-eunJdg(cV}J6@gdFyv z)ZpeX+af$M9u=e$D=nWk(o_^hQIw|Gd8x`ODKmrd`YKEk;zfXtg+A;NfmYnsl10Lu z-ny}#7Ck;_eaCM5XZ;-FG}i57bD~eTR*>8SrUQsck!gh_7|s{#lq7RS$%EFE6Yext zY>!BhrevFwwf8rHfp5dTip->U!A|1wfslAMzZAZ&!XHdIo{f^+bNPP*I?v8Ya*s@5 zvQZ^|-#!6u-!ByDg|e_N;lA%lALvWnOgh8bAS2;8rnafpx+K&J`hcDP?6WrS*(?R{ zhE)Xa zu@h_#P`ZHRe zTU6J6hAo5gD>aCDO^{UkmpBfSR90cq%G)->>cd{+z{C!r4;(?Nx3=jZSR{5}w7%HT zD9Xw9Vdffzg1Yf0yK= z-0d-i{bZQek523qe)0Lo zBC&4-oxya(U3+|VJzv%a8rsq zol4?1azUzt;6FyBIw5Q0`AMw3|I9XZgH)fVpi+m`H44xoIG-6y-KvdwDcZfP?J=q4 zR)&u?2*>rM@zTAaDSysSgOT-N;Bb2Su(uB+949NlS*BxIv_Z{f$oWq)bP`;JIOe1Z zT%S%{m0)1EVmE)`PBwt)V&a(J%oX=M_*w9VFOK#%xrD{9UR*_^GKXNfpMTnx}H>(QEriVgn(CedC>MA)FxG z*1)DgxcoRhm#M8z7mtmsjXkDzjX|Q4aAeTWXC!s2lkFp2gLW=ucT9Tul``Dm2yufK zt~dK>v1yM`Se=huxZ8n{Nd`+RadC;`IML8a@F|Q^Lup*TK6K=T9(k}CYZr8O6E@lS zrHd$=xBL~(;%1Sre0H0@lmKt~I`M5~qgTELIWE)aB1)Gv5-4mL|76Vr{l#n{t~^5E0X9*oX#f`?reNSKM+7<;=!f{ zNt}Aoa%A&wDz*@1(gaG|xs>4)byK_H>K-mph4NdxC zSw`4CB{ajyJthKdxN~p_oGv#v$@8WtEdX$^^SirKg`e%6p2gYwVI;tJBYpYH@0zhM zHDsU@0ht&sVZPUKZe_aRHr6wwMER1XdTO=gLD7?M(-Cpu1Hug*Za!F$4BRB>^FHiz zIyQ0R!oUV@UO0xtp?hY0h~J5SpDppAvzu4eJ|XWLAh#l~(xIE*CmBMrD^L3H^FovaO~Ni5twhDOx1qTDN(AvjaYdgAqxvO3 zFPPbf;M5OzLBN7=n+e=<{tzLxwc-O`x(Lta;Zqb}C<_A|PK7IzV8#QGEw#yFsg%h0 z;PQzmrBD?~_sN3?VjDJYutF9rRJXG6Yk%w4ZunZA-T1{OZ~B|S8`+0a^p|DzcBpp!L-{2|PO#RDS2&I$jKDt{7C5`MWw+Jwu* zCl8O+DGHD#;foLZse$I(ve^0duo)(dJ91py7v>1vYZmFs?q{=Mb|VW($dQHgIQnp0 zcg*C;5pu==CsGt9`l9f@;l{E=l>SrNtPto4E-4AOaq5ss2y}F0C=7qe^CAvIKM|dM z{>Dd7#0JlLI39_G5}>w(Z~!fW_{e|ahTi%!*l0@caE*p9Siwaa*R>mHM0Lp~U{5pG zR$0)lJ$RjJ`$slBYsX!K#J2Y|-9|L6WA21b8sc^jW(I{9Ndf{gLfsA!F{xhQRnve} zClos`N>^}uAEegM8>n!S={vZ_cdF-KddUrbhb->dbZpQ2IkbHn7Xv26S@cC=)p(bEC>S z&!6a=(1))BzOCTvSfF!~$F~bn7M4K4i5*ObnLFDeNfQ~8Q16j87@;jrGgLjY;pz)- z%oYhn!-FFc@#8@fHh=le9%?`QyS@-|%PlE~=i;$Dm%fkq^ZIV^a}NoSqoOE^qD&_I zpEpC2A-6sxC(qjyndf*CUJFo=o#$tn^$@b*{{TkmahP+9U)+gsob;PU(r*|+Tv<~f zF4hfFOj|bV7Q}}b^|1D7{FtE5A}6Utgs)Ev7f4d|rHs4{yV2)D;=*GKlete!@$Vlc z44;Yk;RRv9*V+GA?&+a}Eo-b_!pV^pkQCY>`VjfJlLC()BZ?9SZaQB3DQimH)|}e` zFIu-f7Q{jiWA2((*22XT;94JgvGpbzK|N zNv{7l!rnAcN)-}|k>7N|m1mDWqcm?<$()2+pu_D;W@DB#vdIe_e`Pa-X0ti7-Pb`= zfE@FJ&0pRy_H;HaeBCtVM{fF;JWQcm5&drU1KnD;v7_`3SeEO9uEUiFIVNj@;ReU&zMfrzZHDL?nH(vtJ{f<_{qg zccedxW3lD5p`sf`8n+G7vMIHZ%b1sFpzYXWEQY027Vd|I?4YBrV2>4qzjepCGsrz< zL-O~o@FhZFzF+X;SiAHH*bQ;B^69bO6CrCy zDP#=`PW@;7F>3r3mHz?(6D6p{pd44B-lYy9=iMgdzx?5$zyM#;kGx?>nRlOb(EQe z^H+8u5=sC^wJ~at(Em`H2you+=u@X2@~1s(HrFNAbw~!k^NZi#ol8FZRxdVS-DWO? z+`K89=||o=h-);+fhlH1Tw;E%)U%ypL0X&URr_A06XNLhIM{9d_PMsT$@C4_ay;o{l!N5g74AHI4qvjyxu__kZUC>m*Zs_@ zLyj>U7A|%gMNztD_NtX;(S^S^i_bs9X^JTue-`hyFE0*!{K1e1G}bvkZm3013RyTL zH{i~mbtE>a5eGtEEO0^-1kTwVeVWvPf9in^VEHO%+3>XsMK?)0y)+;@7B-?& zMn+m$sI{>!(@(QrApZCzQxru}6s0UHGIt^lxd%3YtB^cHlcUlP=o<1RDY=$4E^{N2CV`C5hSLpTZsXL} z(9Zo0V7Sq`*-vi%DFCcDDNJSsQt>g(!1@GeDQP~UeWQQawoWPV(e)2X$m(sM=+y?W zfP5YP2JoE4JMH&&=dQ)NZFe$DA9}J`z2Bi`Ai*f?*VS+nzAX7z6SnfbTg zU}mpe?m`AB8-M0)zKwJF*dbFkcj3lxV%^S94y;!sEIpDP20)4nx5bs9(LhM4jAH<; z4GQTApM0+1Id5eoSq2GXa_#e6$lIZ~VGRFtw4*U+1Sp;K%=#!UGt7 zXv0SlJHaA9!JZl>x%3J%Y~!~BcXVR)=|h`LqMkDWx}e^V7cfBL(2KAab><1_>>|Os z0bH|bp>1_m&qDsB4#b#%U(yrcl63QkZ9Yz(yxmY+E}T;g0S_n2(wkhUW$~hiTb5FS zttU8g(h{Yu4S`OIiqK-w6h%=KMX7{L*k#~ukgVv#9%+s078!}3b!j@hB+X6q(Aik* zqvLG4r?3y5`K?|uz`X<>#w9{_ys7Ki*<-pf%sProY7Ube0(UfAM(pP$W%fjVgH)t5 zP{<-7IxR~dpz}`Fv`z8qkgg^^MnDp4ek~BIjuhdCmD!DiJ=IDKs}Jc*Av39RoxosHcT^#WT zcN%7aPuv9z30B64G?+RUsg>(#6O}fMqqMT5&EpSlYP`}%ps?*9957>txFzQu2@LA)z>7Z;{$EjiOgDDtQeoIlGM8pc z)?xD(He}43!*moI2qsnNWYbrUSTrURZE`KFU&>=A%=Ajhe*myY>z0XAMB*}@lgayq zOq`rs#E(pV{{{~(*`Vb=aVI)!lhtu)$(@xv5-*RWQ$&)_5IbZrU|V7i2JDALm^i3S z@#V4CsLzc2kSZ2Et*ZWCK}As%MVYA#TSMAeT&!r-X|3r48>Y#osnhX+jvOne#C-#> z_YZOpVK;AiQx|@^$+R24*6nZhrhXERo4V=Xj{d_xSB@O6v>669LMVmtVb}aqh^uD4 zdM#IZtU9ck4y>w56@0s@aq1B2A7ya=uTU37cC5+iZ5gN`(7}ed(Zfqa(u3rijOY{K z_9aiE4}|3@OGk+Z>bGbt@UMX{a{VM8tNd_>=Zr=^FE0-ca>CE6=nv2M#4K?;KkJ;| zwtXAGUXVEKsj|4|5&TIXIP#nbH;K%X{I(-0;Lgv*sSZbc`gob}?kR$B~(7mjVi;`RhCX5b`v zMHZ5#*tn8{q-G~WH#x#h9(I!hN7>-DU$bW2{^l=l3L`8LyHU*I!jmJyI3A9aK8wwh z{yFidRT2u62^`3=5V`FB2h9Z*!F8pw@H!+YN;uV$4>G{VhJ)x(?QWQl|6eUQt+1k$Q_P!7wIHvcH zZgZCW{D9dV<>zA7k%BjN>An*Jzx|mRtHW>mTAlrxzV)!D1g+nFC8Y~P+APlPKhP6g zDGTve&c&VW3#j1C9&2k+QtKn^BrF&l@ zcwY_4>63eS`rsq|&E_L?Hq=^(U+hu}%T%NXWnp>h*edlXXr^-2MSQHTI6NUvcg<0p zYnoje&N}x&(;ow`ozr}`doD`~(PzU+C@}Fmx79oG{o>9@S|&)C;t-|p#JYCz+5lRq zw6|2Ux^TO9Hq>blo)@uWH#yKB61Nwgm&5>0dq|F9%0o-x?lwYv2j;_CEIalj-TYOQ zp2M5K_dCh?s>6dL4K5oJk(*--f)MhPf^}pFw;eRon`j;|VMFl~9f|$GQ5+#CEE(KF z(s$fR+mpzG#eSKL2vT67{Bh%w-0YCZ|A>N)^>D++9sLbleSva=wT zvlDUlzW9W6LQxzh$sm=ov_h1o-+OGo=bMrWGB#{63uU03&?^Jv>q$gW6h%>#K2mLt z##9bVkz^B=kJ(LN{`zJdS+JQao59w-mJG4!yLP?PbC?yxNpzeZHi?n8y*Ewr^#yB< z#7!TCSS#G|dUw46=^<3CsaR9_)$Gox6C^+Ujhv@V!Qc2o0 z_AStMJzcuaOvQ#-JKKL;-#|S0DBPC8t^yN1RD>K;d=1>A2*E>wae4 zb~`zrq9}a^Z|ko(^jPOhDH}5Epom2Q**UQT8x3;g$uA_}=G$P{!tKI+w~+B+mol}q z!aJAb^z9}JnSl5t2Jsh<15j9Lcy(l?rx{Jc1ScgzAC8=8jXZ9Hry&O`YAM31A>I~{At&5L?SqC=>2L%eVS zHd#A4H&1ME5QK-2xC7Ws__utM^gXGAwXYXvJh(9+Co<-Yox!4I1qWBwkcf>ECaI?a z%EA;yQ4~e#8h>7{Hb=t>!uOE0KIPx&g`XtZ^d&dm-c5x4#;hgxS~_ModBqOyS#HDE z>iF&74QZNk^zUzJKPEQ|J1YZa7E0pa#DZ8Zkbd++W9!u&A zSB_scAlu|Q7j$F~NndhEb$rbeTWimcECGcD^DDZhF>q<)$(lX-e>Ru};|7_eI{R$a z{!9X%>so;>*$BfX7u?XX-y38l$A=3#Zr5n%uD!BQ7z?>!L;n)Lh_vxUGGR8{rXxqRe{xg1g@3Tm+5Q1Um%xL_ zfVKfHey~3w3^E*yZIxMd$T7~PD9R+T@{s#FSC*pT0fV0W?-#yVc5XX(VqkTf!}OQ@ zZ!yHf0EmH*+$=I6!rr+piA9M_G8mBqKF?!EK*o+OUa)L=QJSH3 zrznb|D3gdke~UXir^ClW%Tdht{ICvwKH7Ukc{q)GO1|%;aNe|qkRKbo@)gk7DCW&x zr{^$=kosL38)vgEZ!)`hoF3)J8^I8=qkk5ZhlHK{ImO_-UH$Vpf4=3nvu|bS~7l#b+XSO=1r@^e3lW4j3I>Qx!otX`K-Q4~c{ z6lJXVYb0@J*G=%T(AqQ+^5dS7-_)grux!xU`%XM)v%>eEup^PTfm3_C8N62XUKIj0vsd3*jvA~v1j<(DZ(AE9C;b<`5s^T)AF29b7L zCS~-c>dWqt^LjonXU{_Z^jQYNoKT%5|Cyb`tZfp{mz-Ykb!=nRg!92xBoFIyVMKj( zSkv$KzNnyxfOLaWBHfcN=@O9cZjf$JDQOS{#z<*t>70V}#*l8LHo8WQ!T8Ph_j6sp z>)PLYy`JZFp7We@pZlD3rI?0GMthOY$6)nyCEqO$aCGUbtU*Cl3G+w@tlzS_S}9r+|sL+a|kve=G| zwOI|a&X#ZLf09WPQtv4a-M3l2pa9eDa|q(e-k<;zJNMLjAADnYO2*Hx$soB9taW`{ zO6hk1ip)K2U!#mcB;mAvr~a|nxWYpPzv zZ?Rng6HqM4Dy+6(UstZ+zADX7)omP)xp+a4U2?Fb0VdmFmfauHgPQ{vng#&D}X z!t7BEMX3yVm8Dn5R*i7HCnamayByJA67v!zIo>N(+3r(geGSb&$4-bxq%!hS;%|U6 zgo&1HKxEsbrdTM|jgI&W z_-Khn^^A@z4e$c1JVu0V_fxmM8`2C)&lz#M&73ObFz#ykML3lHq_AddRkroOa-o9E zd$A=+lqY<)b{HnE{o8XC4mka2SNM^$j;s?Q& z)9p%e`M5K2e$d-_+TjcJC_3Q9(TmQ(m3-or)r8fRoJCEAZ6hPB#`0;X9L8#+J}trBN}v=RO6H$WT^mbFF=V)8`?F`b8sT6hzVsTNkP{(1{tZ2VNcUIHzx(EIR&3 z`E_9E>u>(*K;jS8=Vn#F$JjUqn%|m3)B-c@8K-b>yU`C`)ueQy%MCR-wC~Rr3%XN_&R}>q(y6Dry?aFNzNc4SJ66-+%Cu z;a1Lo^06RwLOz%>3Xfik>H!n|N1O`Nw;wX24C8Q|<@=nZE9}8#$nc-y9io+=HC=|q zLqCHUt_rkf@<=#a{W{5xVa0!Q_m!N2BQsW{ap)ZO{!B{9@QsL3D_c6*_*^H>%|%|P zzBc{4r*O5VC|Ve=Dfymld(ynKEzq6)@+ImbsiaGxU-50QA|OmjC!?d#afU=u$3gUm zu3eFw+#y}fUu(KUk>wa(^g*{nxGf+kJBc60=XKE6BTQI*WW=E@&Tn)nfUT(J6Cb%W(YRo}du9aR30y_ajeuxKj=3mVC z2@t%t>U8e*VA$ho!BKfkR5dm#xh;m2*!g}>t+|}>$rA1hVz}r#MSsj0{Ef6nQ@9}g zRm;=zR#-rdl-q>x64DZ;b^7ya9lf^lxivz-!`FyyMB~$f0rT0;0(+>cMATaejV1Ez z7QJd*g^qWD2dXycEJyXcWTMDVJt{;eEJQL7wBfKG*{!v3U?#za5u4~(9>VMvJ~?>c zF&1PCZ+-s!PXixe`mtnRZy2eBOr+M|syEZFdjY;~CZgR&&PpHRnYTDe z4Jo$1B}Q9^Rj4uPk(bih(URfl2UmFRC4A!$A~yCuxqhnrGPEGhj}GJX;inYts;BPr zL%riv4~Clk*#tN86UOyFIXIS&I4&zOxA?2YSFQ@OEn}s>?|t22t=u5JG8yl$v5{y9 zJYOT&GwpYP7^6^>sWAy>1>%=$Jv>+<5D8r_W8R9#!v(|>e+3fewbv%CNkWTp347~n zG|`@1y?=jxp{^HKPg_|VqySQWf~M`JNFRuJ`DyU>7}yb?)Zu*ZTL_+wBBgA_%0T_r zc2DIU3~(+zaa*}yQC2s9G%UYq&md9W&VpNAerk=`Ks^iRr1#waG8D>zbXIz!tlVI( zyko+UgzuYtN-=o@$x0sf%$LsvsnW*_K6RGs8=ChjX!N0|+flI#b6hMtU^-=bZiH~F zDI{E!w(0v}b8h!Qg7h>vctktu?AddVy>e|{Tb##S1fIBt?BD4g57bw#Eh`_m<+mIe zz{_Ws>@RM1Eg@fExAT(gFCze>vmX3+UT0%)l1`69?oPz^5eDjpj7CBO>bfSK$x9=S z?X*AL;j%M#Y`R;~z8M;gtl*{%{7|A8yCiu``0!z5Qd@$P`?Cy^OxEEZYX@JC2Vb}! zti`;Enq>OIzF6{fhQBubQW^fbES(j_@ufSQ_00OEOlzCZeNeTGW@MLvQOX{l$F_hM za}&MATfO=B;;QaHR(TiZwVCPKeN?LHg7;e1*S$ksM}y1BPIqE@kYgVA$Kf6X$tRyf39g|BxlD_9Eu2o4_Zx$ zEy`HKdwNPl(-rg3(Kola(n45Y!Y6Cnr%Q(>e@yp_Hxcs%LBe`rjB6*_z8u3}{*^86 zh!snfEqGoT)$2`OCh&1{440QAgl9>J*=2Ochplt|mrkX#scF>WUIrr;X(7?_-&dA2 zvrJC$RYXLcHW*Gt3V9#uoJ_8HsQR#8bGGk?zVu;&2H7R>0|7xSbMvh7Ef?AGT`16; zxK#e7wSw_FcI4hEGDe7D*marJjCo`>lj?<-&2+4wqDlzPN73{T^=5%(HS?HzsxzUR zYohzC&XaL-(t;W#VLmq{P}4QZojz>K00w97In_jZ55MDy7P@=6UEMh7_k+Bu0{Z3y z8)OTMzi<|hxqJTAC>NwAz*a>Fe%fgO+B2*cNm;QaXq@j7gD>8-O@^LaNkJPg78h== zb~_=oO{DiN|J)Rz_iYZ#bPjtL4S@*8`XtnuS0^w+CfE^K(%rI|fJT@a{x}F=>}Ua99bQ zBZ7xZa0?jnn%dTu{^%)K?}~SWb=a4-yPu0Ahn7VFmW6^$OYB}-ryRByMipqd-Y=f95?ZC0QD1n)&AX1W6Zp2(Fdh1?X*~*H zWsuGr8)%hhs$7LOAQ{bCEDaBIw~<^6RaGVFPpZI>bz!#PdGR+h4EiMKQ2L8FX?$&%W_5bo1(QY|5u@nI*~~AO zmIgJ|$Vify;wXam2~YnpFO>N=W{J0f(hu_< z3uo&;b10B7Zbd);)$uiD9AA~jE%fRjG^2resG#nS`h74~2xNVzzy68caG}}eN6V2x znD=~vbR=2pc{yy4l_>wn{`|Fkil)_GEWd7O8(X?CLFab(zigFR|3sD9Hczkq+Kr0lC0cLJsPcQ#n72w;We>GPSW0x zS_g*dN$omg7fJ{aO4mO38yD@_^Hb6zg$L3D^0W!}J1~bctA!Zlgm|`K)odsUUPYL0 ztp*NRbbSo{b5I3&HOmJWbOZmsIeKvUca_gVk;Ya5-LuH&u(%PhFh#FwAF<5~@uN`PV#>?%U2D#a>3B(yq}vArr=ygfON{gtGw!T2P>+5K5bl-M2~&GRSP zoMJRozkYmv$}Ey>%jw^{9!(F`ZNm=dyi5tr8_vTJ2b1a!-C;HeSH$J*6*~lhPso4I z>8VmJ`+Io+umi98743c{Yr21K{y4|?SC#VC4RI5yA$QFz?>(tV`i-0W%|K6ZQ?lHF zo_49LDZ9o6Secg!1{K~`aP6w;roxct?mUNsLdr5Lh$ z5?d;n<=8mN@EFYxAqoC0zGkkkhrPVfhnbKAhROoAY1H0F*?lDi@Dm7D`eV!JojPZ(b5TI@IO3$N7o{4CUvW z#?C=X_|2k0PVDXG5gZ8ao}fqHs$XfYM=XS>w>%2$yTS)|ElKWWa6vEYx*CO{>RBsL z@wG~{n?2F0LmH|8yzIh=P8fyig@;84O*7RBn7RwjO8Tr~CH6c_tY>sg1`pbz4vw17 znR#V;nR@mdxEFb|2mRwo$s|r<6-7fP>0D4qJelW_-ZV8lPwZH0vp;fwO0dg)9zqG0 zOqIKFO>G+{AN1}0;bF%3cxi7Z@_fCVS`bxg*^s##sQZSV^aA-uE8kzRNm;^pp;Vw! za7#4}w^QQFTt5JRXQH_Kg&O55}(o*|D(R$Q-_wyRZ^6SDh)8b^62jBki=*Gk)1L3!MySw#7Z|Ry3{VzLzNHM?-?!=DLZ!S%}azvatpQQeQ?_Z~D8IZ5`Z0eye^} z3mhfj4AVQC3q+(z0I8VTYJzT=>Vyh9Hx0@)Q45im>j2*Z)M7;Tsu>uPd$D~BH2^^b z21AcXF;C!#eK4VC@A|`*D-_ZvPHGbFRgINBhk#dgt0v7yiMAF3=)_73|MG&JE0hP;cqSoTj~kM4ruwLx82s)8w968d)Oa#_L2H5$BV#Y4YB%= zQ4KVmliz~i<26)lpH|QNV~*j-lSAX|Z^FpuDX2zA;BD(1t11(yZ#Gq`M~(IdHKT8a z7n*eTt-UeGmf90%!?pZGiGKn!FLH7Dfr5>;tM9eOV{W`4x$TkxIG<=36<=qcThOGR zLlvk_1jO4t&28qD1#E?TJTY~2SUaDHAMUrAg05oTzQ+!~*)PiY^S#GH%0CqNHD=rI zzcMNoTYKd=WxDR%UTTo>Pp@hTb_9kjNN|FVXs2jt<7gU4v9tiuM05r-hL!EVp zs)aeYFFC=hEeFx`b4NdW1`Pm~wk=&dCXIpf2VHyY`x$n{N+V zw^moBHU_q|Y$4jU7A~1J%RfCg)~m2;+mlbi(U&<}u2(f?B>~&5ykkT7GMG-Wz0CDG zb6zzeVo}c{3-GVd-F4GPr-5rbh7E)(SN#f?|8n4VAE@}set+5VFH>G&v|CRc3hB-j z>C82v@^pE}3ol#DWsDIyQ!NNu4j1yg<~8vz2X=-h5zz3ZW8>>?vq;3RH9{> ze8mny9OlKds{et@iaKSv!`*BK8F4Qh0F#=3ovB+!V1+ZN^LoMSw;HUe|5-FcYtVsB-#Sb@Xp`^p=DP?Vr%4`H+s2i zKIDRj3o=6hKb_Sm@KFy)dZVLj*HOXm{xiz%BIev-Qo>WfbjiPXe)BN=*5iB%jG`;d zBkT@7pM#dImzbL_yZmb>_z!FU1k7CA^D1tQ*(j>N9dMl!=u~;RTvHB%TpNEsnQRRP z;?KUC5px0M8(T#@M6-fcyc&Vsj9|zz?^nPF$E3CM&5nQH57LPVeGoy2Y-Q>IcrIYT zeF4J%!g`Anv@4`PV6HBXGCUk=?r;#3^k4c>V3F=I)3cGg2Ni3rBr)%2J;50Dg-+EO)H^$Uh?1pNAbb`Vnf z;$3+W`X~EkjQ;vN?N;4lRVQCQx}k46;^q_R`$UdYt6{_ZxaURxYEtpvqOxP6SDso_ z&vfR|Y3-kpvk5|ToVsEdcuI{Mn>sZmw+!oN&iw`i7JdsiRr8KL_h(Euf;R}Tz5H}b z+C|c3rPwKh6n9-@(fZyr(S57RC%V_#QEgz7KzSDZ~A zf6{@f;)oYCKC`{prV_v9P@C1*RS}LXJ$&R#3`yf+fH>} z@@FX13A?XPwjS0Pf=g#C{#F?B7>vfJtNC>}F{Mj~`G;wm*v8Y&e(whXw?Lj7p~XH| z>u1qFN9cZzGG4v*xeSjL$JVdYdwbPk08rkw6oTvJ{5`y{N_c`JgyD@Ut@G{xAc`S8 zD=f8FPK@xgn8&PY)sScf?3JFUXd#E@L-J^f0acC`YDR$ifml0h|bJDgka8R+jNnnOSJ-yGqd=sqE9G*1kTzwg1UiHy|2&oU)mD(o z(l_Cl=q%kYeqJVCyCoE~`tq41#VJZrr(FNp7`6}Wg;bA}4Ynv^Kk&Bm)p~#z%dM!# zl*ik*WoEe?K9f*z^Q)Cn! zc>AWs>JsmlTUp}r&Gwg^;vKU`fPX?PrpIQVbHz^(H5%3k6YzG9qg=+{=g#k6&_TOI z=2sUEGidmIC~o-*f2fP@dlSXX)~S@NsoSdk;MEF{=MC+Pr>T_w$7BEZ0~%|Lgq@UR z=mCQV=E;lU%cGiBRxFAB&)l?Pd@-@ z2+(9HqNx18YW;S0q}kD$a4b2C40)$--R=H z{BviCOhDtk2__N)EN)kr;&IW*)Idk4VlT+qI9mr$KkR^_2HrsD`Qe*1e$2cY+;neu zI&ddw8ToeSr;4BNoeIXX^gGSg=r(-lmLdM%*U`D|qxM87+31eeXfQx?Y`XC1dDyf# za!tA>NSnzLazeNgi=&2o_*bvlDrs$-eCT=nHEc3VWE?5Vj<)m`aL_#1XZ!TPr?Aqh zrqQ6=b=MC3Y7QyfFdw94_%fvX9IqT3R%n*>k9r6-ih8{75qSHWfZ2+lA6`P^cb``( zW%u};JC3wx<+Bw_lKo^uVOPJs>ge7BbVCLhUw7{QFS-A-B5bh7v9?$|Y%?)hr$Gqq z(EIO2rPJQKoT#a1uns8JYo%1QE88!z(N)*ULHRqxVm-WHu^8a*&K_T7XLxg-WH);i z8;8ywjLqgQ(EYT+G-rW$!mq&Be&g{ILdQ(PEhRm1(k8KXjra))mhtb`{)G$#20T6^ zBy#>Dc9dH%-7CPeXg12Ei4m%pXzAx`vS0Xr5%!*P;Lo>3k~~`(#!9Ct?q+8u9U<3qu`+;>l-m*3H2jang^URbP!%OnJti(AJlbe_0q3 zD$kumIBzDtI3xK|FAya?LinVFVL`K7I&zCdQw0y-weelUtMb=()GE7*q>)BDzN!$U zA$uflRVFB?%23==h}QkygB7Ri6-UUr%a}SOnIXwd@RE_U@kF>==czXPIxyD{a8@F8z2@l0LrpL>cEZQzKxy?E6(OQ8v=p zHJ9#ZlJ}URTKC%2?q=E?C0r+}xgy6gV4qw`MCo4OlX4Ru^DoOs$y z3tvUxn*lNXv#&ceP~R>CayHqik1`H6B!lb>@QnPobL4xE-mth36(PdS|2*F_CV@%A zw+#U`9gaF4Ohi118~1lJah?uT7O3eYR_K}Hm~Z~U)vPrq5t!6nSi3mz7uj>&Z)NOx zeT!OgqWc-`J6Dxsr~gtb?ObRTnGitK>EKflN8RizUzVwV=vT#-&y;mX9CsuHxyJ=P48UY0IJ zkd#i)3Gz@>Kjd&V3SOhIpP)v(`(s#U%Sz{O@7HCJL8Jb^<*_lW|F=B#MJF`jYZoH2 zANX#{Rj=)nL{5`(w3Zw37pcm1spWC}ka&JbVjVjMKNqgT1j&wX!{-DfTnwdB1|A*J z#tl0LV*vVy2W=;Yvc$OE&N;#F@CC&2Cpf-z2qziFwoImIQu$3N79YVSzYFjU7=mZ3 zYk~DBQ_!c9kwsP7N{^5)q8z$(S?5DL8YJCPcffG#vK(vMx4#9{bTYKYUxd*9X)w~s z;QcH$^F~8ER<86VxoH1{D0Z-VGN_MQ!mPhqukp{QxZ0D?d!rRonlIfW#1V@IpUPpKS0C)X}}xMx5%Jx>R;z$KBt~61S=)Amm=lpA>Y?+Fk*o)_fzB zP}Xm{`iJw}P4gSclm*on^1pBJn-nca=2VOg8`R@0S9)~1dBsas6m{8?zlXVWp!2_J zu!#F=llcw&ceI`5K^w}yoBTfO17@sP=Mu`?SBv4S+n8Y(u2qN4PU-;pd3Sc`% z)#y8RwbM@jypY|&FV$=iE?mar7KWI>XLU!4(JKUXnA61uHDqP^6bQEnEaj@2sTZxcBllv zlPTf_pNJFs#wF`57x~q26i@oe#Ag=};izeIxW$*c`$}R>xt1s2GNd`Z%?r8W@G85Ms@iDYohF2+km>_!svLRk{nqvOSKEqwk`@PzL(QZi*__ zJ5nIFOkb!`dOH1^hJ2$s$)GGGK&_!b#^l`ZgK^Nq8UD#3>nYbtiw)4^)hV|5&e+1NZ z#Ea`Ylj@k1pkg*Q%Tp@dW&;6V<6m)39{)&2x?LNkPim)|%yNm)KzJ8YXnL#NQ(ika zp*I+tQ_B=9$?Cql7n$=GIs@r8YA-mb!i<)(iOrNWxg3mt_=azB3b<5ytOQviI2}QB zynsegxA)S@&hRx^OLX;Mp4G*Cn4^E4Y3mqP5{v-)Dnh*A*8Oc~?Q8i1qh_0o1OW3z{R&l!>C){v;8jM47yqIu+MM-P7-MKNl_TF5R{$9Zbw}LWjy%PM-Lj zNnJW#F8J+15MZ=Aa=7j$^|rzIhttRQ%c4tu0#V=~rqi%aBtr78&Y^##b6(~iRf{py zAW7fFklM%|Jv&iy_POz~pC9Z2guS-bptzRz3S?~j&akkgtKqYVlCNUMDN$9AY882@ z{rY+9ZsNq_s!T(=j&H)&^jOCIwnJ3*t7b9$?c73$tP8PR7+oXtg(<`R|9SlFE86!{ zxuCpI1dCpdrC0kWd)ig|C%Oi?Yl@mYoTWmNa%DNj{l87hJcVpbg=-GN&Dcs4P5l=} z+efheC^iE3Ok;;8jb_2x8}GPfX4tH^22PT8lI8V-E(~z4>=(7#OR*+C8h=X=ZAA0D zA~9hz?5}huXjbY-6~1b5;zrpAHY)|BtULstjc= zBUQ;|HRkV&ro1#@#G)p-B4n7uWFMi{=wPO*1 z3F3<)#&b$UhT#mH8}Ex!Lgi~dPcWV3a0q?wh4bPlP5|VwBtASstb?N?7gfZ6{6u=7 zPgaLhEj9H8LD)mPOtMpQmBpx2?zEEqwZ9d*9|arNR7)to{)p6J>*G|hQ52ky8XL+| z#SR^+dRH9!z^E=TRkWb7HO=2JVp^kL0=;y~3|Ss*p1@aQiw*U+%?`J0{fjd8y}Ul|Lj%z@rd zKv%*ow|EcQ|JilLGP%8vm%Oa1@+)_C4{Q02%9OQs|F^aA#y_ivga?A28a+)R{ir4A z9L>pA(9{T8sw#@&Sh<(~lWY0RI>eNCC$`Mg>YiV_xhDFcD(xAE9 zWZ{(1zklFuEW}<58QJy=;jUS;50XVwULUG7&elq_rIJ2*@_ycm zEP=|yhS9em1W3m8o}6i|?!n4Z*z5kVhr=i2OqNIVxB=mU{`xdrWnq$kPIPzj@y*(j zAoV_shIx?Ru0>~=v`~S(&Vkv09B9D;g1qoR7O30gY^boOx`V$!?)uiqIIN~0z9p|= z`J^&UF>U9VwOTQ$+JzQSny&FpxBPdyzkhmwNCtC!#DhTjI`2svK%60)R;e$SgGFni zxhG~|gx98lu4KA|?JTRqQSTP;fzPLwyLf7)dDXtujuM84 zjxb?GL_OSzB;I>IDX_=Lo!sqE9If+z&|I4Z{~dNXk?)klDjnYC!*=3`vGb|ihM8wR zc4pQIuU?~^vEo-K9p`14gFnQg+R`UDT{<3MmqG8#T@iRL*vv)xqW=gOVdhgjSr&RA zvubm(RN7YCbJcAL)Gn@lB18;crf*ES{EAH~)e1Q1a2)OzF#-<7|L9<^`Q}dffK?4r z8{2~(JzbN77@=p~+au(XFnY=qFz=%G_HP?Pz^nNiNB2u?prII6J*=d#cu}hIk?Vtik^4$%VyJJ=z`WM0XMU_*)Fzc}_?`b~(aI~)dSG7et zMw_~=sB?dJ56aWZ=Vvl%(YgQAbKIjDRkp9p2v`j-7dxmXfUMSaj8(7Je>@K~rK0Os zUY+dehxqBf6$m+MVezEjI9L;Lo%AO6+I)cq;({O>KEKT5l0J7VSfL=wi=f`V zWFg|7BkSQZk&$4m;1OsN){{Dh9AnKh_n#ZUZs*DVg`BxLNd?z7FZdeI$F;Ur7f-wE zKy;4EVI+t%%qE`FGii8M&T{unU6P;@t%wYrGrfHPn)NI}}9%;$P- z_+~qaYDqb>sv*tBJX@Rw_4o_Z9HIZtzKb2R@MqluEkP{RK>@33RvK1y_#jbqfAHiP z8=l{YR3+kd`sbh|ezU6y(W1~}Q7+LpGMLgM5IXNh4LKeWUW}UGaYUAVufMF7$a!$N z{9qui>msZ`;OMTvGpBUa@HJQ8A#vyh2)3Bh1D`AJ;zXXq zG{)!=X9op$WAv9(h9In}?=(DN^-kYmgWB_Q1yLXJ+HyqUC?E7;@yn=)aVfQO`fOVcy@|jp+C6xjGLgIYylm^w=68st2qFNFv?`QeA@K&~H*4)P;U-q=y!9m|9 z5!=Gw`+8M`&f<@q9bw%}B06C5XaP=EeLLN5^7GNX^f)OKT`?s-!>M(Sk%xjICgM0N z-V!@z_PSrcKrqSspF&37sa#>SVAkc)g+me6Wy*QRsIT3sgI z6{mZUsga@bH1_Hp{+6fwN?|c}0??$%?xg<@wjqPGl?miYE0^mqP%7mV8AfR@=7%iP zI+@r`uTN`t^D9k$B6pXUv(?y!M<4i2gZ>8ZSlIV-AJGD=3oQZz6a)@dk)cjw zS6z5f(}ocBeAGin{gm;@TNWbepErYhmQIWpAJDIp1hgej^BAtd~=c%ncOB;$>Mf02!cizzjLf-x2tO<4ODn- zc^FLqr^9r(3?|PF&3F`Y5dIk}<`DW+xw9+o@ajK2{On^})eoAEf#S(S1aOv5-#YPy zDh2K=m)z|sC8_sokJ6=35X`J}I;cnN0 z+jIXq%Q4qA+iV!lSEf@>Xbd&F3h{(V&T?BcjnjwKh17eLAG8WEg`le-1rcXKlx;<1n9EyF8xm}k zVTnxA?i%g7zE{7E6D4&DxNsIJ|W=D9eXN$Z^aKiI%anTe<#ohukEfLH$Ma*w^-8D5-2im;4bwHZQ|) zRx-m^BO;c&4rK25SUfK`vHr2N(IBQMLGs@&4Lsya#{+&(k4rFsMt$QF!cxlF!+NIYUkU$ zirYiZO&TvfB(UE5m8=hDfK9_r4N}LVr zLVo3S>%y)AY#+`Nl*P~@01Ms6A9D=aAkY>C-@%okuPiaCsA;MdPm7Dh!H!g$w%V?` zu6$>!t|>(jmS^+S)+N*Ubs9~VLv_5tpQxh$?J%hJza8dk?tPr33nDUEdFYWD+_%%&*CUq@g4G-8Okxbo5IVN#>8cg(>u<~Y8>THWd2==;lQUg4dkP-` zN30X@vJ!+7pOu$meo5|$90|hMQEPSKj{b{5AwD+(v7ndI>vHha2N$B2m=&1VzU9i9 zH1gyQoe7i*kra{kc~pq+x>nkMfM_p#=g0c^(L}5Y+5JBr9p^-i!B7)~kOPPZAjEV% zOO=D2l_~@2I}Bj8R~)5(DN`mLaSLs2WVpEsTlEY-y8~W=F}QG_JB$l5262}@A3E9Z zkd8tc@%G$sw(yj%wPy%s!#y$YElw$qZ-S5zA*O&&sFBzeyA|XDBF8iIj0Y}2EEY4! zbwhdl4-AOT!bEbXX>kHpGi$19Dr=>WW2mwVZZ12a_=AjVO+pXM>tBVvTnriHQcJ-% z=l|*rq?V7qRIJpfxc>fm;>GoAO`VJ#c46q%gtGirHM3ggTLzS%><|aZHOCiccHbVF zkD8;Ttaco_>2FDy|2$?pRL`uR(V-rHI9yrFF#@sOwb@TTHVnPMD)k82~n17zlT}@7X#{3BL+qaye|jvlw3d zc~$nYk*{m&<`NJ-f{{KxFUYkC_Zpb*YA2|l?}Qyn03R{Lo6ciaXYcz}hmN>TmBN-6)|8EfFXGGVSS=g;6 zJh^lf3e%EG?`xS0jWcd=`HC84GpuL&>zaFH(LI3m({Yo+R-ddj}5P z=y+os=jQgcXIuxvOXR@%OooOw^W2~VNt=Ajq$cSr@T#E9-LjYibfJlF3?wnTzkkc# zc6@7D;EXwsED(xlKVuqp`2Hcu(v2u$OBpQUdG*uLIk9~)I#Iq$E$H$k*aovVDzjNv zuWTGvUm1d$o&{ar!2r;5@I`Si=4K5RF?z%N)=@a!{3-t9X z;}|&;)GH^+lOFv26zc*ec3lRYWaI^Gdzzx>Q<}|eYq7ms4;ot}PD_dcwA0^*L<1sZ zFc*fv(b|p~$+dn@>tzWGlo_&mP-ZFgbaWMPbbFQs39-17N6wKkTCE)CYiBdvTt98W zVh|~!Ou?h0Q0?%LvY_RN(50L0#v>sRkFnd~-DcMNs|SZ+*;pBJOXqOEfqA&d(RFsv zdfXr=pl25aN3LGS1u>Q4_nccE35Fc?Bm~Vb%D5edT)n{Nf?-W4h+%kY6c`h&4S$yB!ftz=|C-XT{II^aM6gbv) zVH|u;?6)k}_7@{f4~<;LI*xVyW4G5ez8h@hckWwVEZS0G2rb<(7QtJ7H!(i>-_9u4 zmX1^rJ#jTvV4}(@XKPZpY$>s?kViDN<=B?fD!#yg$&Ran4s#(@Yu5JjIZ~5`k*CG) zKNsNJMnEyrY<+zi1=D^Rby`y$Bi;P`&Qk{fWArX!r6NM~`+{4^ch!dnD#mQ#K2M90AMC!oZ~;lUTAI7W$mbYU2#U6&BYh#_@oJZao4E16G1# zgO>UZVPO2wg#upwJwP=87TU`K(OUHEJH08F%mL$_Un1t}q`ToUAXRWp&;hc*2AfPj zL*^jz+*+1h2#CmzL%K~pdgf5OA6wJvI(I0MUFDJ^T{)++#uk{|mpO`uu6D{edEVK- znH@~L(q>Fp$sXSEbqQ7~N$tU>#)|pnsY*-DmhQaG8eE!DP#^+Wkn2A)4z>Kds1V$V zqPqv`#vYb=c=%z&%nu6S3 z%i)^^gv@j(I{gSzIrzEH}2`Y zV`aMHa{>C8+l&;9EhI`uj5CYBeJF zXF{~*PEW0KI4eed{&?BDaCBt|ta~B9XJ*G{R^?=~M!OXN5sSqe zP|HGsdx|tkz&4bGNR!t=lN1L{lN=bW*9 zW^eOS40PM~fG&iTMVWn%-a=VhR-%^?J(u2OfKC1oH-iqAWg^+hN#pCp zVP(SUkc%kVfc(}A#CPm%u9**DcN-dCF=ohPUo7>%%~W!_a}n8*Xt*}@5+{L4q)r`A z)hMPdf9R28?CX6rKlfYXqoTUNPEs zdT?qoJ6hGH#9o%9w8TKoRysjwRhJk|_tSQ13(G%V^%!eN^eVV(%g$`qat6I8rtxWI zkkFfqu*v)EagU3};p$$I-Ji7=gH7*Ln8p+abK=U5PoYtJCXII*bM-}1jpE{pE$YSB zJc(17X_turoAcIFU*`M}-b$BORGw{k=OV}ogBWg-)(@^!&kw2TP9#mr=KXZpqfO|3 z(j9zd*x@QHw{Q6Ly<%~Ea9W_G+I(x(-r`(#5A=nS+AE;2nYL1QKw#hdxpF4a=^edniGoPIdV$YNt@J^Nyr5qiwSHYD_`LB{Ipf6_o%>i+Df{jWFqu zUH*u3VLu^S4Br~$`x2<4Ub$cricZzQnWL#_m-ss?t71~5MkBGXbqo_3Ziwt!gjqjk znD(StPbRo^V9%=(e6og_FZPfycuT0KM^T*nx#f|f&i6uF+&{Av*-J0bf^iysVjOD8 z_^u=3Q(R#sI-T5!Q(9aFi9KWu866J-EBOYjJmXcXx;4 z?y!gF-TksZ;GD_Kok=pul`EMU@s%Zs48UZu>{9C}vyU@g1Paw-9G5sLyGCZwTEL<2|pR)$U!?#D4<_}bW-kDJGCuO1!57U5IMD|fHmf6Uj`Hi zmp!H(vW|F%j8s{!gvJ@?LJBX^!2AyrHDAX(7$ba=CM3~KWQvZNvgtT zNIx(A4G>z;d$c;HiSj6QCq0a|2gsXEDdhOp=e1pfa{2@Fl{cC~oskz0f`L1`@pSdQ z>e&=O1~Zh`+*xu*a0RqNP(_C42+KFYP6)TD0-}}zoLz=^s(QnE3v}Vjz645AgR!U> zr8pse4Te|!@p{;kpYg=26WoWhzmu^QfA^^JX$E(KYK5lY_o%!w`-4_q{8;)3SuaqU z=@t|_~?C>n;WyKs!4F+6#gUS_+q{iPn2v0Ga3G#K~e|q;H`DlN4 z3Bb{bPrNPDjwD6qZ2oy)XC_yIIGLZ~%ox4$;nyFh_D^jfARf+(a87) z`?N$ObW&2SHg~G> z8?8K=WJ$8yo+7=Hya>PO4`F%Y?`avUaTJcgVQ<5t^F;F0xve9TRsx|R6eJAF3&&02 zF%%LhC36WV5P)YnRmP{O*?*&0A$%G;+>pj3gqCs!1hiHA#v?*isZOZ>OorBfK>9Y;e(wtWr}*t6V?w3o08(s5gYxKJ1iiI zWL{F7bEj9E(WG7O!nPs%4+Chq7ggn zLN&78_4DXw7O)!lDVeZ3yc8KDu7f%!kZGjb4xd^6M)`@!HEDI&)tSX;j2)@U+>aYJ zvSfx9W4E-PC};63vhw;m&hV2}p<4X!$EeHZ)wvg_PHwtN1Q3g+$9vgGJLb zA5nq8-2O$&KQ8KiKaAH|^JIlE+qwz{dQ<#v#4}-560zb;&GJx5qTkXHoWGkFw$Bhch5RMxI^r2VScKR9_O~ zwch=L5U>JRlsKJoBndAud+UFr5RQymf@N&jqnq|y+U_%+FF#ynz%k#1#w|!lp1WS0 zB1|EXVe^VDv*+JXsasU!-+~_sPz$(h;gC)XJse57idl?kopcm~NWjYu?KngEI(I$9 z{VggUW{ttD_4(KB`kyHT%(pyAXSpA-)z1N>IJy1m$N5qgAg7GL*9=N-XBzUd5rl;> zcGRXd@I7yYy@yXXPhw056Okfke#iXon9n9 zAa-Q?`L~XqqN0VI>9PfHe;_O+aEyz#46pXDw>&v{9ueXMM|2p}+B?$U!%_vLj-!eq zWY0+XiwMcqAfkEUlN=wQIRnU*mwF26Kh{~Tcqm{ENNwJ0M_ZoXyj-+^4TCxK@vbc{ z_5@*ha;9ZlYxMxC1*}gCNg%hiZp5`rligwng#t34gqWWMvgALi;=kII-VdSE!Nb4x zPz6q&X3@0|3-4e%?!xlwMf}OZS@M;zfjwRh{wHW?th@fm=}JF(Lfn{h)gM?48*HP1 zUpPP3hJRA_5d!E<^^f&(5`3Sb(i=mr3u*?%p6wao7@Ehr^Ft6o~ zu=rfegs%OL7~&K)j#WV^#c0CZ9>ahCS`=+7`9zA@t7py%I!6J&ztDy44f{4%nVt8aEsa5fpt6K&uW!7}9 z0vxd<;!L>|`F0dXXW$BR*!pks3HFWS%E#@dVVJz9x*;(AKm{9I=&f;T_qVpIS*1z-^ENpc zyRpeU|HD$~x=>MqDN;3Ua!OL(go-8_Fe)XiDm~gf!&-6|nQ|__>JsU!Gg5BhZXl|_ zB7v-<;LW-6^H!u!_(MQHbhyZ=){W;|h)!An7V|K9=q$ZA>8gZF-2VhN01AvzVe@|l zHZsB6`mQRs9d}!z`O9kqJn5_qGvCDbUCM%SnE;2ZfCBr^SlmM)P-@0ber@c?YsALD z7MJR0Up&{_hI~Z|h{VYPb z%dV8LPw;aE;u5%RC=p>uWD}r%mX>`pPkrI|A(9FXUGlylF4mi{pG(oOQi9uUrMRBD zR_sZix`P&#zlX0E9=;&o66ZN>Kg;HmYn*Fq7o9jOFi*F!JS8e$6gvB%j(MIbflg-E zkpHW`SxVB&qD`(fC)`|qUlxVPz zrq0#wpNN$ZaL9Q-y!NZi4e9MPSF(4`68}k-p9-6JWX*ny!^WJM zd~_xJn!d(AWng)fOuN1+%`G8~#CG}z-hg?Ze3-sRs1lofh^IzP0b~z_;4BpktRmO9 zo!$A!#Sj_B(1^`cDhcX(Hp&kDIGlXzZ%YL^?FCUyu&MQ&@-M^X=h57yj#JIFdm1Km z>h;sySG>XLz#1l(^r*3_j^&5v_146xj%{r!ur%d1RorNpd4<)S9xSC_5`7G` zSQYFQJ>QE<6M3+gYUzk2h)LuO%PCkUAZx2;=#`qdBNX@^Z#t{T z)E4`ch)eGPns~5a!dBZzMVpi?gzdd3&Uw$b^D0Iz>!yae0?+5yE_&Uk$*J+;t#{6c zuB(a5Bk3i(AE=Y@GTfW(M+kI`Tb~CfhYP?2Fvt06w%+@D_8SUsBmeD4<-2)pytAS! z&IUDD7zM4$<3TTE^@P)2_aNQ(jb&CJ$+7|+uZ21lU<-*nm-0Hn-*+#@k}eFarN4Ew z@d}fvLR+E`_zelHX7m`!VT`?4$)OrF_?8DNDq)8ae~ouajJ4L<6B?J41m~LgUi+A7 zB?Ck9O%;4u=c2^@?PW$wNzokRQoKyZrPfJP?TbpxDUpvW0nS{D%F>O_5560DMa6P_ zm-~hS!$~aH!aRX9sObeb%3+inASN9=zz#9RNA&69Y^TnZixN@eedWs+ESo2S_h!uM z2+Lc{<}p1wpFWqS&}D(r7 zLEPR4RAsd75-b@0mcnubu zi;#fO^Jz1K-;DDZt`B_?w?%^EmZ%bhvmw8UIWB+bXz%eW*LaYteCt6ci zUo13K0gH%ta`Z(_^z*8jJ2(>o$l0JvGNB~(a{3jqNi2#>a-v+3GbsOFEyT=|vF~xa zvjLy!YTZyD_l1X_yjLc-Gff?{T6ec}X^-t6f#rN3z zuO)a};?gzby{}y2%x0MK?hQRW%KnUTJ7LP+W)AA(d(C32eGTzP0_sk;=C~W*3pd>6 z?@d6}277tP1(#9Jj|I@oeYQjCvDq5$a$~q78sT1*>OU_*tp1vyCrRQ8=|m$awO7LO zqc9CPx+XtzEv`t#hO5IU=AaMX7_omE9Y}@;)Jg{M0%O%;p@djyG!w`p)4mpjk7vax{{jm=Y98BJo=}TkG2{e2m5np)Q-Q zs|(?q}Pvi)Yyd`JYaYlppfNBZwpXQ%4Q?KB`z?T0pl1 z;nOMw1n8WN{qWKTrQBf5XZ3m9v@*r0KC0wOf!chfcNo`)N@betoX&8$J~%9m=I!yk z+0wCW+%!)9jOx*ykn7^xA$hK>>fNg3BOiLf8;XP@K(4d zTr+yC;`I5xo|(%${~JPiUL@Z%{=!9IrWqgnT{y%id~bK_N#8Q zTyR}>yWzPDJ+{cn7>aBe^sOBsM^$FdUF9kr3gftt6`j*U^hPqP#EF5tcG!Fgys018FZ$&a#nbahR|5|2 ze^>YCpv5V(a{ufiR-B@+SJDxQO+B;QkdDqez=NxXD5fu;u<$R9em(zswCIh(j{B&S zau1m{N|^L;r%EhQItjdJk{K0KTiJYUblsC%j%NWsZ<@xc7+q*|PXy|=BR31jlIn1A z+h5N*!_}Q0Hx3V`-1DCMxpXFK7ckOOX;?K49##xZ9agg^nOrs-*752uvkv)(@T`HT zpFc8ur`&b6J!FSh{*O$L>j0ZNg9R#w3td{4r7g#@=Uo?oh(6qS@YW6EZQrMNcFQF) z)a^2}&4t!vU4;2XNoK|x7P;?i#tLBuRzF(kDLB)emR{LzbD+b5y?xnT1RmrP%oG$0-{SMRSGBdRl_$D*e-o)g*GIn!y{L6|1x zMF~Yx=^9Aqb<*0Cm1b;{=W*A>fvWD2K=_LDDb3UQ1`X@RJYM})R;ZrCg&sf<_$w$Cq`W_d8@o1`i7pT@?DxhPP8gmF-bo81CT{tSp#s=dg`j zJKmxx18|sWs$H*pht1?&{oL;hm&`8I+JpK|!yAZBQTv3Fc|M>ua#u67VCwEDK>`Lz zaOMy~tX6$~t`NIK51HQ?vZEx*rD*c&fAnYeVw7Y`oMf1l1-#fUepm<>7&0Oq1dHoJ zCstG{6=yjm$?sz9We1B<8x$2%DBGP^^553UUs1*pD707WCs+Zg`hRi@nfTZKASgS@ z53|C4F6pf2kK^?+8rA-7u)8JzI}EN`O#}Bhtl@T&BvO_1U~5pw1WD$eS;>YC%pC@Q zM7==l8OZQRJR3%}7n(14PU6;SF=R6=6>=W|waXbt%*@j%?+$JQU6qzd-z> zGBk_sxvsxf@$}R$if02fNWN#*z2I9}{e`w?|4j7CvcU#I)XV)~D&CoFKt?slSbUsP zfemKIqxZrF-zA!$Q2u!+|4hILpT)>s#Yjc0j-!l+4u~_(jb_x(pNUcWD|sA!cQ>Q7 z3aMUClG_!taU3vvM~cXx7_P}EOgYrh;73MYVJG*dqd8b@>w6Xk*~o%q$F_~D8vBYC+uEczviiKH>y z6l>`3R9lFE4|DV2*;3>3fI)#c^}2BpF^Y&n&U-^N#k8nTElN6ZN`)FgZVV*azJ8(h zsKfPGY%*}xsL5C6NX`*#c@H>vDeQTr6u>+M7!^Nk<@20+d#bx+(X?*t_dG1)+upi^ zcpJP_UP?p%b*`ab?!*2;g3WtTNtUj zM^vE?RIkr=X~5Gvko0^~_kgQc-DUi_WbF{0t~fs5S_WoZBwz(UQJzy8xIl{h8-=-_ zwr2%GI=3nwvfs@=L^_urlvX}8y?_V>l#fFsN<1U5kiefkJ1 z;@mt)lrVOY37RCl?QeKH72IH{{$NH)9)+QS6bZm8&K?6X{C;RmjpR?hqeYhJ9=9Jd zZlOy0OAA^*1$Q*r*V+9xv2xiLpBd~B$NnAc+vIiWb?ke%$dz;xbV-5dyxnOMt?kSV z?04EVLUlvibzXuweG3GV6?5Ype78fbFPqpx_rO2XI-qXZrJF?m%?3z>cSj!*I9ZPbZluumG7Opmt{OYPge7h zcu~rA5#uGEU^@*Q;piG7?Na>SBfV(G4B3UbY+ z|C&+d(=0(|;`W$0dU<}T@TZ7Bad5t)!-YiK7o@_G^4(J0`e7G3n1|rMch5A!w)oFU za29>Zx!&DI070a^ncHnsMIC_~nA-o_Gx`7a-1^u+`oBG&srofa>0@lntJu+M?-Ndv z9HJDwQNOI#g_WpoHk)GpY7j4TFy@}e24qR!9*I!cCn&BbFLz=T2M3qtKB~V%5V&gVlh0fYSu;zSTdotHrV2HH^Q&;< zZ6!b5Q=LRImcj;2h^Fmx zA7;#vxn!z<-Gx~C+C##`9dR*{nnIe^QF5WBXG*4IPOA#*HtJKZf}w3iO7Y|9$L8P0$Z;v0jdZZ)Oo`7Z?G-G}= zVp_!0M3p~3zdvseRVFwopdv(U6?bU3Wo;d2I_G-7J^x-VM5WMI4}pWx%KGdnw3;_j zj}9?!ZrEp~2-iG%M)}9pJ|KD0rvnobw$Fie1hTLgilb_v=^lPr^Sg=&uf%{^lAMw3 zTclR(Xft%J?`gZgm=CJmp?(MWA;Pzp_E5qsCg~9>e==_zeps-VzUtS5)b@H>?xj>E z7@(8!he_e7O+XCa!)3xf&~i8nZgl2lxeXD2$CEIamnwg+QzQ$G1>z%iAx9_+HHt6H zm*}Wf-fx`kgOJ%cpd`-R+Srrj2*%QZaE@qJZ_^4O!Bkbp+PF^F;Sme7uPli?XV4Fym?ysB|>4OJ4Lrj&mz31J^$+T#Y1tzfLil`BXeyo zH3CER4rwX+0?Y>gsnZAc_IN+w)p>7{ne=6}Oy=l10&yf6KC^H^y5U)y;OH1--fmnR zeaq=xVw0G`M}Hz?Z?}79#6ir`#ZaqHxNHtGO*ZkHQl4ElOb#nG^i8VN4NWR^O~)bG zuD+5$5>`~>LTPyo*X$sDg z4gGD>hV|jxHkZeSMzInwXiNAz>~9qd8)2BMobM`uc?=N+xdt|8)#p9;R@rN>Kf| z4hw)%D)QU2yoFG@T3&`_g3w@hL89u{n#6MhecOl>e36tK;)Rdn>P?f>8g|90E|0Lq zCv;7fb!(kX6`2*d-E$&UHg@y`m{BA5kf*Z+2D$$ez-{bud+Tul*X?U@0^i`pJRCAF zVx>;1y!sH8T1IIlv#AcV3x!F@z)&UcE^zJ9VIgq}4RcO|xY55~RXLjJ0l}UBxBTay z_2Dkmb|5v3%#3WMCex5swLxWz^*P=KNS4T;vt&?Bqm*9&*t;1~C?u;%_)nBN3Yr3y zpH9#NRmA*MxQM0!C4#BK6>jmyP3bF^i|qdmZdU5iL=K%(oWL@kcssboA+GV3z5 z*(JHFL(YSZ>kk=;5UOXqBad|!4_msm2iD;!B-ZMmw;KgVWep`{6jGrN%e5^rc7ElO z>t&V#(@avu6IC-VPa(3fSd7 z?aDE{j}ycTd*LWB6>`QXCm!h)TU9?Hy&;nZmRJ%xk*N%o#j)g=i6n@DD+7x%(jWTP zI%ENIGm0>l6%-O$CP2f0L3{a0Rt?1M7#fU&Rat+?fCDq)`oKGQj!+&{$Nn)Xx9S`xqPt=b@v`e_}4$2T#;t zuzYu~vlZ^@LeyaMDb9%0hPOtpJ2s+NoY)El>3S}+`S?1MK1x^niYfO!MY#nD=n4vB zl#*$gq1l9V1Xesl>Vr(r=D~F3wxMB|ua6qWC_{GKVuw9Y3?$?#xr1$oSwGqWuj~LV zAA1(h^XIRS$Ji0egzvGk`XE*(Z++(CbWovL+Istd96RwX-;AJZC ziYm-zn_`~SEQeLy8FpI9509l3ksU4gT1ny*jSn(A2Wo$`-)9Rv%jHqx=oGVo)yJuY zTilU8g=Lf&uQWcF?eLH;?q)zAVEF^_T7fu^Y?1MlEv2RGg+uRaYhF3qJ@&pD=E$YD z;_)&k+=9Z`nKJ3;$C>eLfFVEK2i8K(I6TowZy@OyP(UrbS}| zNWhKW#x>o@z5a#d12?jNtx~Xi2ZR#Mx~0!R{=JKgV_i{qh@3-i+jvW49HR7ax_J(( z7bUxot+VKAFYM>R{xTS;-Y?f7?65nEsd=bMFJK!ff9xL_k4}(AAggKpi+w}yv&{SK9v{<>97 z^PadEX>PPL8-S^W;{-RCQD8SlJdsz8TiYvbAgmV)m;(kHxKQxuv@s(;XiPSMfSY{6 z%a`#0nn}*}0s}EHS1`4u-nrj>7~k{c6?VjsB^Tf~-ZCi;@9x@efW|h#?z?M$dALd; z!Z+y({Cdz|dnRJIe>y@jOyz!^9v=w#xuqIua3j%;n3OgtRZ{(2iJ}Djw`DT2Gdsuk zU74v{=R(cHiq5r`m!3b`FEVT!@X9>+-;0fJF+mG`=X%P4eFA4rFAraPRJgMJ+Txnn z+^;waAxSZL3&w);hE3*hrjkUb1bbp+-J(>C$vMftZhw)-6oVOz|MMS;BLO@~mAdOE zZWon~LmBtWduo@Sd*rvc-J=C41Q9q0@(m>DqFATjvGw~fD61npZku8r#ui8&mZ)85 zzx2e!uecUM*5ux|Virmw&5Wm>|ChGn>|tKRDPtH@Nyh!~K?1mlgi&v(8k7#>XLiRe zi0ys}%7bDGcO6%H$Lam5&e5N}5UXyzKJ01+Y*a+{+1Nf=_Fm-iScgL~sG%Nxc1B1k zMo9SOL5?GBn@Rnf2$5OcOJ(J6hq)s8TmC4YEBkP|@aOD1EdgKA2>5tIk(A)4hyWYmnrwNAARNO6y`ZG{ zFtRdFXCmiXv>;rX5mu0XN>m|&jl8H!3)p2J69Op{Ta`jZFq@Ae5-mM{E>0UW2tX0^ zsR@5YNvQ<+dKZ&eK=$b+FyOc3q8_?IHEiUx`t%ZCvLw|IP%zd@ddH3Qhi{7x;4z^%mX`O}L|FYL$kC zWcTW9#z6&U1?Oq~f0UF%)y95!Pb}BxhzIFo1)Zo}IXh=e3;ek_)*I>y&~M*AG*$lF za0O{=VczS9QU>EuSVRq&7qh3iKD2Qk#&|x>#tzbN4aafO=GrZycJ765I0>;P5At~X z+Z5m=2IJHcm*-8t!QWS;b$-jJG#C3`wqdPpc57nBN^?ylA}GMqX(@e@kZupR`t?b$ ziUcHV0$?%v{4k9l{nQoL?)cM{)bWdZ!$2zdFel?zK+M4u-zLAI-^jCAW}*oM?;B~+?R zziFVj=T50rb&-f!Hi}E90GM=BKoBkYOvKP9^kzRx4a_6V*M|v$;g_fydE59`A1+45 z(0_lh-#b7R56`7qiLN-A;Xo{{9>I`nfG@<$R{wAKF;}9Po|_#+)}z;OTQ}?3NX=o} ze!0;SDMD7Jbe7qNklN2LT{P31IK%Z$zuI_+Hsx1y7hAiA<_^mVg36yTPNh9v6tK5y zbTne0)lMRDP46D6em!&?qHm4=So{biH0kdTMUumXtX>|@l}e3z$qxW?!!ppFc-^7Pg0Z#0f|8NYGaxc*M0mm>GW%;E({D-3_Zw@R;Ugt_m? zXWMcAp@Qm}*~=W$kD0p)3C1GuI+wFh$8Vx2+Lx4g6?EcYN}X0uHs}%qJPG}jpW-K) zwOyK?2t7}V$Amx$QgGA@6n0KZ5Vnta4z91ZvRyH?Zk`-=h8v)Io=vl1r@HoG?piKh zG%u4RoNP~oF+*&5xq;ZYvkkt=0{xzWA1{7aCjbBq_i1Q!VESb{66>E8ncClyvFRZf zs{3SqVpskuIfWtT{Wqgc3ie(R7O)HXO6D7oR|OKJNW9PC>0La1?-ITAC&WwX!MO{P z`X)!-Sh~@&eN0m1GZ!vPW$%|s?|#nYtE7s4OBSresW#PgQpqtF}fdA#loP<8^R5 zPPH9%k@s-L_5*Gc`mtgSgwAa-etUi|S|#n8<96S0d-rzASNT^GmH22#`=XF;28#Bi z>n$4&vNY+ky{5nJ>v(#X)M^h$>%+>?U%Wm?SfY#C;u{fe&O-lmrPeXEQ0MZqAua}- zKUw+$u}^sLtXOI|qnJt(%O?R74fqIH3gYbfl{RH?(oKZS|Jg5vt3hWuGh|j(qiRWG zy_Cfn2HbATrEr7*2Fs(8i6U z{T_Xal*9Yr?se;qvH4<1H;@Z(%Xf7y`_VS`(Zu^9^EBV4gQV;J`RU&Vc*TF}bKymp z^4xX1dQj~I`FQA~>yz$!YAyLxz#_nrWAUq@!JcZ{zqUO908lPIHe7Z_ZM;yj9uvq* zP+$(_qYn69|A}tj(|KdO-TfjA8p`%an}rt58$-AG5Fz1L+<*iQ>+P!t<5o?b%-gVD z&gTc8sVdi*Zb)9%ubV+O()##Dz;6;;!Im+&x;NlpZvwj+?&3|@*r})2kO_iQJAFhj+9t@OOX%eyQ$?=f1?wKP*73sI%RkGLCJ#cdLGgs4sz~1Je@LtE0EGpa_FbQq_S9UKub}^~A%y*Ly4U-nY%g z_m0qhH9_d3+J0+zbs_7OnT6v05Kl->J%Z}7wG7^V*pcn0+VL8HwUPaf$e0>Y@(DHC z^?AGH$MZV4Q|+%BTS?eR`Yju$bKlQlhiK;UsQsejN@E6c&}IGcyA_ZZ(j@WfnxR_s z?)l*I2`iEBxzNV{b;-uhlef5ho^0lz)RGkte`>0vvBdaw96!!&P1)L`5!(24Wc7%V z0mC@V+bq&I{3ffYTdBAf66D;M>GnAKBqn08RoY!KATViv<<|7>q__Js{|gp^%%MLX z51%V}<~%w7+2s>{yhPg$&gpzh~=zPcpT7S5vm655T(5R$5@-`g>G^a6&f6a3K33B&{jNtSZ%C+)GTgsWtJllj zoq(pKq>*6*&!-6y1I{DbYoA1KAWk?>7xx6lSRB&2^OpC92tJfnQoH6k9HNF=1+`B} zfaWWhladnH%&}VW()z>hxfi=WU(^@iUb6xZE0x(d9p<|aHdKK83GB*JaG=T;=)L99 zcR;VNLb&34D*83UB)X9>2>T6dEIwWYJClzH~M01InHPWRW1vgCfS*MU7WiFvjnrMrJ(;MTE~NWKZ6`vz9@J5pO$ z>nZk4AI@(Dnji{5!L!d@KTXb>$ZiR(3X+(ZiK1Nb)m#KK#fd43$KZ(m7Y~L?&9Xh9 z2(&5VpUq0>r5GKjAZ$l!x^(A4Rrs-ejMeSbnDY1;$#P!CUag1IpKWQycGZz^>77O2Bql;hkoS$AfBC^#Hj=a+v!t-NzN% zG8Zc-o#zYc4luSLTLHEl8#I6Zz3f@jx#k{aiv!+lLhIIBUiQ;{!yV(PmJlPXy}5~| zt=At~9%I^9>0Mf~T@Y^zNF4}3Hww2Mf9Xz>;Wk?%N1Y_b$KbhCcnp`+RqEQ9w{+99 z#eh!k6I}|fsYkv2WMTqWeR)&1{m}$~A^Wr?F%rlk!Om4#Z6Q2ly8ur~m0YMH)-5{H z^X`+OfF)!?wy~IQ4zZ(H??85bU!vRTVFM6ccx)8w&53rw#j9?BrJk(ag5;1UK-06t;bcV~;c8`!pBbYCuHOJwlcUo(Cs)Ai9qAPsZqTA)V)P*8^+ifa+L(O}W+}M1&(eh`8Dpw=n;CENA*QOylGrRJbSadI%415J#^<16O7-7$-@(f zQlF>N^*+&kAmZ{maqP366KS&c;>Eg0rBzs~JjHD^!?Ak4c+fweo)Xb{BCJ9FGlmsT z`Phi8{EXvpg9C$jd?AEGFK|3d~R zc?(u8G+vymg;aiq?bmLWzp~duUs{;!;yUAc4k^&`eNrj&SmaHhP49LC8Ur~HBR&Fd z;#dq8GTaU2-(o!K9cOS5w|Ht$!-3H7~{Lj<6f zOL)-#dFz`+GLlv9*ev+Yi^Vp*v4;%_0{rZb{4_kLV;uH}5W(%r*QLIW)B34dEMCyJ z?I4;2khVz{JDA-rc_Y5MoCl%mJaR9$c!IzhXP`DbF9cpHQwEts^^RL0G5if6$=LZ_5%g>_ zn;^1^r=eVSjl3kuXmVPQ^4HxT(&yxd=VEeea;62CFPUYdYLj5xunCGqlVM0r(R>4Z zU>V*;K7eFNP`@qq5SYZl3NlBuay~h_q}A& zI(}T%`)uVZDOnfxD{k6J=L12)#_fx}zGrh6eUm0N`-KSeFp~_TIC1g*w7NI{Ef<{E z5!kpHrO`=&aiFUWg`~f)YseVpZ?e6!&)qAR5p#SI=p_o9=ap|GQyP6m6 zn@$}PFkkXsei|U`n~xd=yd3McLL<6Q%n>zNV52o%`fl)bK|ZY8VkR2ja;Uk@w9tF@ zm?va)9)K=i>GB144!{MTyQOT@5h8l7r%t;pOQ?NrsdjgRO6F=&_sj#QumEN#MSEt8 zc_3?lVT5L=bsvS(d%g2i-Q$c;6_8qv3o0s`8?nU_1!ASwKE~euyl8w4Iuj*YdcjeKgPM@9fF?j}L<+kelkS zu>nrFiu_FpNDxIJAKq^+tIt&d{(++S@N=3jJ?kGZ=BG8qJ;#Bj0@!T+5d7~`_|13{ zsfjqX%(e5gzB4LE(r9%!qek8M@e(zqX2 z|M)28kuK~+wvL#+sv$;#Xx4T@1d;qqbzBMBpN*4y_XwRh|E$#D^1dBhb|W-xYht~5BdZk3(P#bL{uX1g+ zzAW6^9WV_ug-qvKF7fP-n5#kV((Shg62717;b`1DizP!ag1)+r9YN`t4!! z{s(*{eBW-Nq@MjBydr{C`0!*pf8T{)dMlgi%l3Vl^lgA|IrK=Div+O2_zq~)I65G> zHtnb;4`;!%^YGLt=i^ecb0){zQpiD3IwVo@7$%?gTz{J1n&dK41HllrAPN;=ik!~_ zvv}gG@0R=Yol22l+aCIsJH6=HnZbkcJ($aRF3g5$34*lwT5%dbt_kUt#=E;~paeNo zpM`zet2erw;90eu@bT=Q^y%F-4;er(xo@=C&*o9}{|H5l zol&2?&SdMIURL>g(n9@GtqMvVpba(3&E2=@ zk8L1zpH+IrpbnY18iAV>73nENY~;_Z>{yKSWd*}Bnk6foE*q^7tDShWHc539I zhN@yH=k+cEvVm(tJOV#-(@f}ie>Vz!6wK}tQUwG3O*6|a&x>-sx$glyBc z!#nDAZOKO&MS;vOU!Z=+=;tBp)0CB_b+=-TfLHa+gj5gCH{dN);$5)*&R-PLZ;~(i zpVg(cddRu}THTELUx6R|Kz%Aj_N1W3(QW{Z=sJ2$ynM&|xCH=U+13dRZtGykRhyC6 zbb3`+J6zzs-_rT|OuL=|cOKo@FN2ReYkZw31fH&Sv(Vj5smC&}>0vA&MpL*b{t=`W zHLz#Sca?05Tcg45=>-A^oCUa5HdgzKQ17hc~Nv%FFElV}1)(g}S!xLkVRbRSS$ z2i7*hKkpL4f2dA&XEtp@{!*4?_gY$q zP5*Fa(z=T%?m7K@KezoL#q2pT%>ZrMaAe{MZ3SwUp4ne$+z&h4a-KJO*EOh3s3Y$8 zk!goxs^u;#^77B23fp6SfsdZY9>vdR1@`;;x$TR!OCM}I89J^Ltl{zTo<>4#1QLJ2 ztH!ZSu;liumfkLMumlO)vFs1X@MLN~!%03U8P0v^=JQoRH+D2PT-HaB>TkOV#+0$7 zotRGfCi^A~}f zmK0Nc^LhjiNGAGxXgMLc60_$MhNgU znnJQXmm4i>E>gjWT;FSvtb!w5wveK|dLgco9=o7uJrC#fCjKqhu1&D@$+04l3=tx( zc*R$r4}rex)Aw9`Yjveu_dLI^wzb8I0?fME z&aRU17}ldXTW=ty100oe-hI&}_0E!kA$g|9&Vr2>D)%Q#l@FW{AStAF&87t%i1Bv? zOVMWz-3qQ^#cB=h_nKiIr$%7~$>?!VgqSf9c3nSYN4~=^*e)&MqCap?s1kA5`>E`O3Z z`1p_(pCPx7$1l%tXOMOFEeNF{>?*H)pn3g!*Qoxe3M4vfZ$AQhX+6Ewape0G1Uq)6 zzP)?-_uEk7FXV&XL3VoZy#(xn82Fu`$Nlu!bM;0CoI~dk`<3<(2lG!w>Axt9sK7tP z0)GKMewYq9&@r>C4=`(jZJG|I%qDe!yX#+1lEL544+A58AM*Lx?bGu_R|db2JRLnH z&8#jWxfH_JwQ;}-g-#owCUJ26QvJK#jWSB;RJiP~baCtIWZ1-Du?uI1-`qT@+@~|^ zFCzZ%4od{DA@FH>f*{YM;v?x^a3Pwhh*CfA)^utcN^4Ui;hCXfm~x@s5|RrC^Ds(Z zw^9TrQv`(P^bdegbyCvI5)nd(J|L4`@@z^9{J_P*@j-%@I1J|?Nf4(ZHuOVoE0!R~ zA>Ahbo40h5x&*)f{mR|E8{l%%4>|LeAorY_j1)t>(4Fgi0&v^hfJM3 z&QZ&&byzp^NxNCat%5H%yn9`gh=?d4I>#MF_?C{n0Nk0@Nn{NEI>9n_IS0uTbZZRyWm^ez*;uMj1zhGY`q#{cU|%9w)uk-FGA?$<)wuo zwIV}mMVNc^n@>!UbB|e0%!`0EKw2@aci5XUV7pm_pG!+%68F9R1`?LZjR|{VXDMu_LIfnat2!XeReas+nM*&ZM9=XE*R#XjtrZDDLOk@zP{ ziK)!`M$MybD4;Y`S|ko1DQcPD;iq^ia~I#@XRaA`-^=Mkn-wkGDh zHFCWp;Xmki+5Cu;ntO}9q?Z%=yX{*#*{Gm*FwyEsrn3tr&MK*K{aZvtq<3O7NJyd( zoX`H(p_YKL=PuHJF9_85}Ok%^!bS`$lllnYq{uuW&e+PqC8)6sii~ z4BwoDvO;a>&W*B!P9qSXz)SJVL7NNBgu^O^EQJ$om9Y~Hi(Xe^PWo@Zk*DvB6Cj`I ziRpo<4$6?_4B}7jGl4MQ+FtOP zpi^!;XFX}Tb^BTKYyhUx{-%o(p4gllk>VUySfu2r{L*L}$qH{SM=T9K5`O^V-ALNm zzoTeG@mc;=JfrM^FY%pJ-wirZt6i}-5C!$xf&$*4F8GZfbU3$WxSSeY?HevF3y^b= zb_A?R0Zx~UR1lT|tt;V^1b3apj)EIki)X0kkn)ENzT9E%!_^ke;zTMjk#dbOmq9d& zN{#1DylUU?p=-gbrk7n<{Zysd$QfVIOi%V6OwC`2sst~k(n${Ky8606br#tY`nU@@6#yX{2Ae0T55xRh1~nZzh)yy zR;Ec>jvKe`w)^+`daOyCboji$WA#o#{n4|hRSXVjU_4r-hd2<5e$slOvee?jm%O(> z)OQ?s@=@&MWq!kKAk9xnb?=6PCC+<+e}P(FwTHqL`Q)1;ja}=p=+eXDYJR61R&w)c zsBcdXEXDIcQ=Q$Av*%+pd#FhCgXzU4@=5oD_$QBX^6$%HZ_Im170qB;0-oIP+InfERaPG`fJjaj1!$WHhu)Rs_u9M`C@_jm2y%1MZ*@WD(e=$bUqLzNd>a9A#}@zO>&2#$Xk z{5q%6W|`?0@IJhq)X!@Mn7PImE=I@&QJ#%znD3FSUt-Hq{@RqU1RDvt1x9e{O?)vs z)hq3-n6KQ*w*`dRi#_2@oGzhtL0yDsc3=ABz393#zQx{blV@0A+U?gkQq^}E&CII& zQ=Kmozvu2S#_UrU%)aoY`6urkoVtfT4996ce^ig?I>3OA=XOI5;)oc8<$bh3j!8Z8 zl;=sI*+$K8@TTfB%n<2WcxW*?3mGujxgI%sc;5`!xj!X}>yDP?*%+J}D&Vkx$0 z1HoH*EG0E{bcA8U{d)*6W2)mD>w-U=z7RA_rcm(mgTt+n({SxynBt!JDUevN)P%h=V5D(ZePNx zhYgbf$jbxygo@HHnI>0$sZyd6&2n$ZD#jeQfo_M-lslnkr*GW1kLsG6<)d?w9n-m) z&!w%w2bp|Jb%$nhbW~)D)#v|I33+-(E(ne~^~)Nh($1)pF4 zGkjDp_|J0Gm!c+BX(FZt6PnR@if2P&j^C&PF2h3fniWCAyV-An0d=eHz)|H=gA} zF2$@4kj9htyjw?l2b}IZ8d&VV3H-3e!8lyT4_}zd>E+1{&-@U!RRr_!u)lAreU6=# zV*vMXriUcd>`)5D06>;3tY|%^qb`UugE4j)A*W{3)}MEE3A=TRiRkS^GWsaYwaQIv z4MCqzc#oY^4~cf%(ywhMn9vm`es<3vIYYsHF>Y07bgWA-DTozwTOTJY+?E^=VqF>B zO1+T7sUOG;0~KsnV%EyUP}UhtUmf_8VEJV_Yiu)rpLqG4F=<68^vs>Ylm8=1d@1tP zOak({@aeABU!xzeYgy5E2f6qK4=Glv1@&oX&6@f6f9* z8!QU}a+G6Vo_V;+D$KCo&1dJjs;@9I&Run1{SZqOF6&st-tFiu8K)O8n5zTKYE%y} z`WxSG@bbx%dOs}-lPw9MGkb@d7W|8)Lj7RF8bs>aJrFPtpv9K-_kRlPKx_Ob*f*%V z)XVzRD}xwXtOFa%M#;w>WA(A?b_6=eLQ4xb{j|$R_}%&JNRhk*$URPlu3ybESBRLW zegW?HLZ+;`DKXCsV4e!%4Wx}4BkkD<-Rc2CArsBw@;$fAE9C0!ibI}PUtAj1yWAY$ z+^1DR{3(NE;yvL~{<^4?y0@_r&3`$VA;H~wXGJrT{!T1G!>+1kGIy(J0|jEOfw3cS z`Cd(YhM+l|FSB*IJtP~8Q-xFzkO)cY*bcdjkeJGOI$eF|Mf8{rkLmC&!Xs` z)+!t~!U(@j&NWs@z(uE3EQBpid#N^H55ttcD+D-zi8KFuiFuKmxN@?c?2BMxzzf5v zfm(DrK78en`|HVHSDh9Ack+X-c{seJ(ha}mq0Qt65=Q+NYCe(#+9Z%RX?9Tk^ZAM7 zf3hjt_5pjVsV*=!=WXEAc|G3j;sRh4N&ImreepQjRU>bx3kCvLxyaQ>Zi;R8w|rI=puo}cNHZO z=I>ca#OLXRN4(p59}X3C1xw}H~oa#~w#sIa>M*9_3$%X{U{h@zLRFv9El!n4P3N;wlQ zFmLkMaNGCWq${H;9)3?9?Q-e@`@@{HcM~N3p#4CsVC3Vi{_QLo&9|5xvNE1-J@q)? zYFY3I(J@V#Su-9YG^_nf{!ZWoyD)0dm@~O;)PC6ggD9)j2X5!cFUUUO7gRU=LsjXW zG)f}{1nKRI87qi$UlOt0_%{uj&Q$1RD~;rb%1s6$)NZO@W+uYjhn;+CSdigqLx1mQm`3x@@* zAO6Xl0;+;GbDG-2M5`;M4GesU=JNMuVVsPJex^tY7*IVCfpn3sHJr=IxM2oZWC zp>(AN>&4@n9o6>F;(Wh06__5&wm#Cn{NgD4&;D^*H5{J>yzEUhqBR17#VHl>kxsrf zS-~$|G@|7DIX(tSaG&6-k-VigNH+bPx9S038Ddvb{xV`lT$np;BsLz9k*kqT9stK6fNd{SrUcY*$mJoi53jd))%RiYL5=I%w}H@4A`*6mfI|gi?zp03*nj`HkEXMH_c;G1 zFjQL#6c??^%t-<$?_n%45*vsIEahvUCpmc5eE6++Eu>U-n>C|=(i3c*gaW)Cv72G1 zjhyV}8|<}|3D?5gG;Q!veInwFp&$ONy!t5PzjBdftJ@RV?3VSKZ6J~fYJmhx{OnaW zeM8-jGjcF>95J#Mu2xiKFMRp-{@o@N5d;NiH!q9F|fjc zorWC&SB8?CrF&T)UD^L_3z~H6Kg=lcbM5#1@b8pp#iIaK#}6-pMJvk=NPMi!NDA1F zRdc$0Jl627Kn7(z2*pxJ7e|intPM~8eqZBSpgS$i0-_<=)eB6bT17tPCaFhVv!Sn$ z-SYrzC(1+-K^Bl-w&nT4oz5)Xq5o+Q7gAkPV%`tXkIa;`Sf8<8f*cT1V>jr3Xe^pV zWp&6gBatB4a~oesMg%4Mg<9p|LDL5RS?9ivtG#X*yrj>$9M`2XT#xuO1c^et&tcGe z(`!sr81*i5WVZ3Rue6v5lY4rf_oJ_x$8gas`#&3cUo_yS zq_dJdd@fKk3(-NRA%2zR<>{M1g3OB5EZ)S3dQ95AyTLLItRKX=!_*JolR?Ty!cfA3 zC&YDtaZcWMhc5p0o6_A&CV446@mf_#>Nf&;D>2bfUCZcSLG2`-#J`P`iik}fVrUnX z@~FJ?0Vzbyj}awCSfZ@bu6YjrG^AGR$kJa(R+9{D#KAGcEpn zADxVMUzfPT{_}y;H6_ZtNCz&(;?9-^hYRKY*Y#khgH7*lDmSqyzXp(#tWhV@Ec{R{ zhNrY4k$nM)SrkCYKW{T3t1NkeMI?f8!Hu)rF7#Z@T1pi?)Dec`^ zN$!&5V%T?mFiQwnG}=BdwcW_U__Si=0tVC;tS^GBQMWx0-;Mr6TayXBp@NRNYpGpV zi}ja>DUsKOQbW{YjhG^=$Jx2buF~L2So?yNhtOjJJsK8&+^-@l2t0p)gKi`4-LSVz z5mVq#lrFP*dqfP{9Wj`G9FXj{8=Hyo{4MP+K;2#?G=9fi85gY5Xlw4#UufTFLx zq+_Q(r)9BWyuvFi@Gw7t&!YHLjunB4VaL|Uvd&q;j|29=2~%L5YQ6x+l;ffqox~b= z2&4Zr#?X&oziW85cUh+GyWbT3@9qu9cB7mVY9IpOWJ}Y>qjk>%tMP5HH71LWq2sVl z{AK8M@VZk93@%@hA(k^S!SmOfMB{W_8HGkihq{cfuBCz8nV%zE>Wq{fmz%cb5&g~` zgKIhyJub&Ew6aiy+`aK%*;hes>kA5WmBJ-ZsfN0oUrdJ=Jpa0%d85J@FV64Go^k~H z;$-(rKKz-<*$=TsZL}Yh+gdULox70~h@T~11>H=474p!U$W4h~>?M}EiL!sHQ#08*)t zfnFiDgb3a~i)_sQ-5$>De(J-qqL&EGTzqg#NVjpytMi;*H+SESUn!`wEi`jTH+WHg ziT!u>Yr5bjUc^5MhMBDptRbk}W6F**-p*gTr18k`ZEt$)B66J3$!x&K>QMdo1}&Mm z+CG=yHqNs^X;0P%51hLt_6WMepSwNeieJ~5q8omQ2BZjXR8s4Xpt?1WaVKDpFeOMH zS>&l}7OT4xmw>ihN+pa515FI(kAy-X`w4Cy6?|JoC(``K%92GFOwdLAgo{8h`X@w|5Psf0vqDdE=1WXvdlcLp9Vj z^Nj|9nmYb6j|4AK8Nn|ZEt1d8r}D02$ktUQnMQqdO%)+_8(0;_r5OJ$?XGW-{{rcTE|G6Co5MY7OW_&fE|Tm%!( z4N|k+zjO-J%k|#uKHJA>1O6`uiwfIx8PSiQbfCNpT-Mv=_y~(!%V8`5o#LR#7FaT8 z;V9{Y)gDD!L33+!C`QPFx@O?NjTzw6K)&Gi$(AIQJ1OIC;Z9W_X>ulaA;(hdTu1Px zV-9{AFlYY?i?5wvMDsZ~(1yxhDj$|!C~7b@_IsF3#WKF3My0~&jXl5iaa|wu&2ylG zlvYki7S9~Qjmo}$;OH{tOm^Aob`?-L_n?R(?WJqFj~4HoTY@>ustwRtJo3LEsjhpB zDOK~_R$NEzxQ*>QHn~FQzrHIh3X1;B2DZ@Kn%t0UT>Dz`ZO55Itk>ktBy@@E%_bXs z9W#C#o$3KzP!lbmt>-f*$^d2F>uq{{9$eN9w!R%5?@zO^SY4jr^ZERb;Q-_Z7{;g? zC$eAdU>+utfM>0Qeiz|A{i8G3S#Cd_z;`Yx;kkah1K{&oU!2Ehe^K~XvdCstQhccP zcv|oN#;r{2J>iQqET~eaHJ8@!nJzw@x#wEG^}%B!pXd^qH`YYVcbU`#&j01YzyDPC zna}4K?>t17h;+*8_!X_X2EMEv{~OBfJP!Q}Z} zmdnwFR+#DU>7H8*M-Y2AEMF8@Ai>!B&V3!4!Q0LCrChrQz6AC>fyK5&YQ5{3F2t(! zQ31~%sNQ47d@OJI>-H~^2>N7W$jL=66Zdfb(K3QqmqVT!@DM3jnQ$M)O_L0H@Pa~fILKU< z`oPnwPYh5*e3+P#2ijQA)0ltw<+Lb%P0uMCDq)rj$tzSp5K8nYfB?QNyKKV0oPUvM zL8^hQ#(qBk!PouP7;?g(d9N#W#p}6FryB4|PH5>u z&2jE)1IHVjhvh!suscHJM|zRgA3v--`Yzf&6B|1nYMMTkRD-jjkO7@qL&O)V6+xR* z@ww*~v1c~VEHK9Ly5BTBI7BuZ)&vTCwFVLMWr#rlwINLs=MTDubSwTu#_u3Eak||B zkAKbM)Ccn5aj{wQxZiX9mN)an`KTKI^VP2ea=va0Ckzr`@qI=9Ii10Py| zfKmp}%eJaI5%e@;A5otdLjM51=aK!g=Vl}CQNpU1eg8F7fX`UN7L*#aDGhkSe!N%# znt>Kh9dF^W2C8p`-#>OBL>2!4?|*1L0`T=c9l!qa_Cd*4Xw!aw@4-tAl(4z?wUoUN zJz&kEK^0#i?Q@->@gBrlZ`+ z7kBHgbOl5U`3r-y1p)PvsbH={4rXVgEKNciZoix|en*g^jW)_`Go{MBpxu8Ly%Da{ z2L;tW$h9SwOegvBTe@DI-0n8cu9`CICl(TIV6Pyy4B|M(uP1~$)#+fwoeAiRN2=}4 z>UR^nNBxIcUWoU@@V{GCR)B|+sEQO|tBe|O>FGa+Q1AN3f|5%uW;>GEsiEMwY)oUW_c3cL&-`sN&O$!dzVPkj- z=d-8j@q0K`?H4k>_E~CmLwY>m^Dp@UrQL){V(FvwJPwaQIcmOdCJ3X!T_%q?D}rYc zl5+bvBa|q){^z8O!rQGhd9^LFjV*8#E3Np$3?-Yz({0GzPmvydin&j;ck}c9&<>tn z0Y}!E&PT4td+Z>!pXR9(tcLxna8L=mikzV>$ss_sDI182+Zr>(h91SlQ-!NKNbL7N z{t1*@QPHb-#oMk_>r)AUkdH9@H#8gqA{bEE^7q8ek`wy$jO^h2K2ahHvXGpdtWiR(a^O}U z?7`{SfEf}c@(6_!a_9h-0Cw}q(i;mr=feB>^LtvK=N^A4RfL`$J;J`}o*VVMHShJ0 zMn3x^J*a8EH^8EYxe+l`wwDv{t-sS<@!i|RJwHhJ(k?2Cnofgts{=5AEq%%0`x2q^ zU?@RK({VSq2G70*n)Dso;Pu-AJx8uc|MJQ#dbs-X3&8k6; zcxH|DTOy=eVcvm+EKHu!heRfPB<4RiP#*Tomu4b^ihL9BtP&qX?}uX45Dqysj&c3N zlVugZ0mECygWTZq=B~%YM0ty$=LrppTQo>n`erp?`3X8_*cYR5FAJpdN=7t&8ny?| z3{PHhvpLjd8akdGLVp|SVO7p?pK zfEQWq!N9&j6;^y;Nb1O{-I(O&F#S zX6+g}Z_Op=k>7KbIR{DC{~Ya#bYPSUsX8RETNDy?EEAK0|9rGh0uJA#WyFl>J?Sr2 z+pZ0PUadoF!Mm`wpeHAi*+ zq$qt}hkKd<2xl!m-MH?PNZtaq;o`3xG~01#I}$zjm7&8n1T22{XXzh1P-juDC*h%Y z0Jxb^`weTX6Us~8?~{E#O#wG-7(vZ)u!)*R0Mz*4dY+=?!bTIusZrz>JoWp(5dEWz zJSNyK_J(gjP+$2t)}QK!YyoX(>lYWb{l3S%ydj-4#bKbFK$U=U#3uW;6l1=4xoa@FRH9A9vTJ1Y?W6>t)gr>Hy8q^ZMcQJhOox zL@!Mo=Qo&pzO8XkJ3PyP9B3rmszkiR{6_2lKfxY#EKc0rfy9|h^LuuSzladjTx+u9 zu;JKNwBr|)%Yp}J>-3d?^0V7}n&M3Cv2a;Yo3&ck<=8(}kc%^!@=44E38ty>zD=T( zXFlj`8LA^iuG3Oghd+!Sp46}snIl6)R0 z@$zwgT9dck4fvGJjD`2+Q-Q)bUCLW_x`bh(aX0MyJphbsXGyBq#@5g^0BRiuj`0`v! z@sNRT=r~nAv$%@p-+pGf!hN&N%4Z<@cP4nVl?E%+jkKkg)k7q&2xIW;pOy<*redih z&vx1JY~BE#jC;79efo=s4XWs93aEsVu%Qxy*RDjf)puuh-BW8 zKB%@k*Gys=d08z_AK_~T=3v8;l(9D)6Or`1{{NAX{*k_@gjQU=ds~rC3ijzrnf*Uj zGEvFp!S~}`=U_pNpF1#+ziJ2MK^n$IzE;B=nf9X?rfXO88aNie63o_-sW;XzHX{~6 zlWUK$2-;CPAl;7N-4Ypm{*{qy_g8T`LJly%O-sjS4*2EmPGsr&;mD8P{gVcJP<1UB zj%@oi&&JJ6d7Ld2*)RQ0C)&D}LVxD-YC`6CA&e|FgvcL{|FdME4NmqKLGFzvb54qezuC8KHW* zjGoM;2hHKAP3-2)fv}2wj2Y)j)PXa+?p21BIal)$&Gq+Mb}%EYsVdNvfOdq=ICLAl z{y6I}HT2H=AR+zJZrCi^YQd_eiAK=-;cqVTe=*7h01is{fk}r6m!}2O7f?9m(1#6PV_mvu=if4>|7an}Z5b%T1lGp85D_`Q=Eubh)`B=*O zp(Q7Z^PCnVBWjfS=h272c*>MfoT#D%-d#4Wji;!{JPE}N<*rIqG{yZCIT`WbKN?yQ zF-d%A!p z?Ml4oaKVJo2v;`KdT~ zO#Ijk`$$)mOKSeyo|t!k^|WmHITz^nsk;LQZK?EGO-?JY2%D@QBj$QXpedsv4swZV zm&j?JlCCY{wbaJ#x-FgxVkA>-r;uh1y24Q- z+fR+GMEcvU+KV{2l~kHF#~D!z3KZz%*^OFg7L0Cp)s&C!GYG=LWbPBTWL#1GD;2;J zo;jn&aq~n1G5D#-B{rFy75QwmXZK$MtOeIX&jZ6sAnc0%-IbzHN!>x1WAQ)|nplcB%ZzEu-SXZ*XOJ?z~m8{nCj z;%kKOaQgxkSVX48P-N0zTnE3oGytPfo&2F-yu$6IDacM*d_{gxzj`;nns7=6mz$%a zs-_;4B5gRXQZ`+!Fv4j&hoYGcejip7E~Q~vMcd@Zor&-mBWUz^^+%;6{o4F`t);qk zswE2H$-brLA;C&a@Qd0CI)ytlNr=4B)lN|RWfqtw!YN5(^|)U0gK}$KvlYYC<#Pc7 zGp{rm$$i?}c~-3;d|&|{m`=ER1=c;Qgyl6^mm1I$C<&|05@==vdc#GR&*uJDPWq6v zmeoEA8fXXc3RZ9$?g{{DogAE?O;=czeiym=Y))?MZJ{?!r*{nU#6<(@TR!eoyZfT^ z58XJo%#DPhjpXGURT>j@xNpyEHTAQ_bOu1MznJzPFl9Fju!&~7YsBgHc4svnFW`fQ zf&%1;v|}PuHU-{>-ca;_|LJfdMdIiU9J5rzUS%w>LR9L8Pu}Ozrd(ACDS+#JzFv`X zF%RuW2}@kMzB3%_6B-L~%DWly&Y6b@lh;ll{jWmm%u4ca{&ANt-B@QWPvfwJxKvc2 zze^w1TdSW4?6Im$g2TvUos$=#A7v+1a3GMi9?|HMAd=i7MO#1zjD&t={m8uV?&_ej zpcrDQF znlOT(tQYKwf?5vmtMFcp@>IHBlDY04M<{|&@a#-&<7>9-chPusrG2|VC}>*xz}r;Y zfBT8%J#vZ_74>YTCuy?y3!U_k`L)T1kQTg7*et``H|`dZyi^f(>~#{{w%sfI%f1mO zfW*7Id5zq3%y)gnb8nJ3V~x0d6@K-w@n@YX@4zSjqRA{XaJPs({-!X}m>uEL(pv11 zE^_Cf)Xdp!q>xwpxql>1(GJA>7Mm3(yMo_)dy+MTa zDk6KdyF{#FNFU8S3B%!V zJ;XF*zt7!iww~R7IubvX^(anKzO|brRqDK-1G!^D<47&MZv$MzD``8<8Ec5uVw2GE z)F%KKzKl^x!cSD0JSL}&4$mLZLCz~*Fywxz8sBOtl#-=OJ(%$=+~wQM_E~u~D7X3Q zQE9nIlq*bQ-!048fSU36{CT>K6!WIV=?%Y747G|LnnxKCW9{kkJg6HKrm7I3MVjd` zJg%zFG!U>xR}a;KP_SgGEh~NoujqaeXZl3+i6X2WgTp@1Q1Zwa_NhDN-4u6}29g_1 z3r@F05Ob9nw3T2}Rmt1m@ozlMKI}&B?YGFl`{Q8fCog~#_c81N^DFtr0L56 z-7lZS7CxYJCAVmH=Y8eHsX3f)EvMgeG3>Qef+mTbD7Kz9X&J9pLWtGiifT`+B`b#6 zqBQGM*$poB7#(Zu+`O2!Kuqk+DJ|z_KVrtL6SjQg$ee8S)T!lGra8u$ZBmJgX51&B zJ)G<>=02n$goS0rznAiXgO9(G6c`BK{b$%^}ubrp%>HR5>2W=w5 z36hHBbgcqzu2F~Cr7mc+CQMKU7W3}t+cCnDqvLT%xjI$5FRc%0NlAjkEvWsp4&Adb zPCUgZH>_$Kru6FTPneX$pFkc8O*ZH4vX|c`N zryWP$&~$U2rV%Gn%NwAB43CVS4CI9#rsm?;Sz|uN3<Fq`}X&^iisZbP;zuq}Q!FAx43CGARYI!ogsO{b|)1Yi5Gp7!iADqK-~ z>Qxl#5Kc|H;je2pAsA`Os$?OBcrqD>Om>?6G?m5=xCQDUoYP?xin?QFpCSj%)J=t8$`M0^DY2Igwg@qi)XXp|0)_efznKVL(r%{CAbL zZ+K0{Ywq8@j+%prZl@Cq1XvlC6oSbdmiXta`3rui8of zs7-LK7+q*DCH92(j+t}z=n&a#F?Hj%DT0gJG_t~-lzQ6g9>;(U5yaLQ>#hB3LEJ#lA zLM1<=lUOv*USh#`dsUH4n4_m;@0rS-J_^6KP4g>xPw30S(5Y;QS0uVN294Qjgp)4_ zJMnSir|NSU!_BAAat1dt<%a5jqZ(=>hL0v1)oP07e0mM}BzJSQ$J~{Rr3iA)8FFKZ zcqqVWCy2P4)==iP?fa#uYcFF^bD-|xM0gWku?W4>kqK20%V7OkdD7ftggL{Qz}Te_ z_at!zg25r!0=RH?!8pVrpA*jBRsL2J>(rfbE~+Vbu`)u6qK+WmQ8P1sJtmIO9|q>- zN?uA_OU`4mL(tn6T9;6Mlc{2wjK`6`6<@+gcLe9Frz!TqU6b@EUfG{W}w@G2_u;|X8sd+y?d??q#2Qw7VF;+49& zgS-at6Hs%F5A2oR0DNxxxM)Zn(F)BFG0&&sEV%~}#&@UstXQq2eM|LAxL-Zv<{(p4M4zz4Z6DuU*dsF5!DilHt zZ1#eVw8z!VLFh7b5soTDwlq{T)1Ug7s&J^WD-@)F-FM5JJ0(%NB2lE`?klNrhjOT8 z#!!b7!$}7lkWIqdPq7yPqN>w2G5GX-rV~_B5TdhXI06Yl3|a`5_^`whjzM9^L}%_+VxjMSGLg{BD za5A2QiqWPPLRGJ=O*KU)S7$QDwa7;_+30my-3Gg+0QZoz8Jb^9m&==I+lGikYLjWA zw5a*>R)RC$1b(uCjdA7lFLJz(5cyMFc6lIDL1>psl>HJt#|XJ*AWOHIF*A|RER11&qmIKA%N0mOHYHK^wQ5oy!wdl zY-gExg~o+xe88uoRrE#%)MM-TBl=TEvYBx1y95b4G@XMaBPRL=UW8APz6a)Bd)8Rh zT6zkXt_qa^>$q`v%SC#Ox(A}X*}+@7<>JiKOM9VDl! zS_IEFb?b2lm2hw8oby#PbpclT!WLJYWCSj4U29UR?Ai9@@b}7F~qxkO~!?qTx zmt{NlLblghO~d$OeWQxLKtKXtV4);yh`r36g)WB0yG)g0x&~t+QhJSzo>cYzeLW0w zbhRqZ>&myk(v?{&DA}IsQfv>)|LW%+5AcpOVrbh2pL535MJ?HVS6YH*rF+|UJt>xC z;K?H-6xPZLLZR4Y2IGxNo2L7>173o6q>+{)na#8+*?ZrOr}dR_X+X)d_CJT5HA&RD z8>(+gR;Si!A4u((Gg3ztq%@z8#_mEUFb)6~u?`?;aZ2EJdu!ECf-uO6&W3cXkqpj% zL~8=ty_G|_LPLoUj7+?Kfxz$xtr?CRX zEZN1cJ~`XftJx0@s>hWxLa_E5*;P;KTds@q$sG*9lVn}O^6lAcrU&|gQkXi((l zA^6R&?YKc}iestDMLB!TW!VG3wf{QWu{DFI-054F-oZj4)eMPP2*D(aR( zrn`B?RnBIJ1#V;viWFX0fw2i$E2rGJv4{~|n4x-W-+UkatK@!|_TxTz zb$>q{(~v8TPxd@DTv{SQ4Ob*@c2>PsP3NS0)JpWKRnU}92C9Wn6De#R!MzR2D<=Z#Qb?US6`XHzy@_9urN~Y=!r=3?t2uWexf2Dxqgl=dze7v2#={sh=0_{EL?OH+k<#NjnGr$rC+y3@5@|8g_ki2`G?|w_Yre|g z-K|8Db&`Z|iv{K|s?RHlYJ(G22nKEGNM<{h&}-Af5>H4gv0|YLj=T=kUy|WT+h%^h zs!)^Cnnv|$5uB%pr3wZW4fZO&)o3C^D1+h5@uEXIUyn3652J zm=}LuR!F}x6H>4|5Z-%0%+DjFDyiH&t|Hj#NN#k@mVbTIbVoXgjX%rzp=G-IF=gUn z3~^Q=Z8r5fe9KzIyl^M~AbYqN)_JU&%SalcAoi~tE!z`wmEF%k-hOe2FECEn<) z-2K_jMSF5@EMf{R7#-~jn+aulQdP2jwOXr*1bU#!Ofp3a6S%WQp5O&cdB@`fA6pIC z0&cutm8aO3o~r%UYLZPKb~j|o zg#HQarW4((IdRKvyLF#t1#-7&KUSB7nyJdXTB8C)AS(lRdOI+}_MMVQbR2=QURabd z1nIuCamc#wYmuQ+8jt44sg|y zM;mp#iEhLzCBI>eefnXf8;+t9-bp3gykcp^GS7-A##9g-8c;wRVcyQh=PFhOC8y#Q z>vR$nY`Kn*4n}uH>jzsKfLTk1S9Nv!EM}h%zKr2MF8(+mvJ~lKs}2Ewubr*9!#zm@ zI@6=!p`}J?xn$+{H(?71l4`< zAb}%ei^g+d>7F41(c9V9Df;UWY5;|CcAU#-tYD3fU9%iPExWyV)`cQX_mf;r@FZCU z*#3XSRDG;Vx!NQ)9(D=YN z1HpCHt19Wt6O|ePXj20C3pILgpuHh0XdMzS-Xnx28?t_w*}`zds%Cm&GGt zcvPW?sQy2?&M7+5u8Y>O(NV`q$F^;DY?~e1ww+Yav7L0>728I~w(Xqy{&CLb8KW-i zy{J)pziY3(=A2Jqlm>Br)`c!+@*~d-QNXVn($SlQ*O%TZhZ@Gv@SIP}T1~~Zf{_xr zWiga^1M$pgeLKEacWsI&_}^$Nr)c5pk*h&A{{$v&bb`XG^<*O$uI| zF)f_z()g6e1=P8UK2@&BV%Lr&@}WU(Vjzxl9m0WtsCik3w3(c-x{mlNES0-KrMaYm zAV-ij)=y(M10XkPMgBg(6)-^-_kACP55`;~wGD()x@& z-!U_%-4c6F53am!CctFZ5sm+Q`(Da0_!8`GtH{{I44Kl=~`mKQq#8pF|zc zdvv?iEiIcPOX0H`H~PTHcnRgFPJ?-8tn6PL7qHaa5*%^l5#t_t?%Br*Qpv~9@TSV= zNwsC7>V6cCq)FGON}CHVWxp$mFb?%pckMx(2f+3$0t%iM5xW%&L@ z=cv^3;$=?^)B$x2##KJpyTZgPPHGEgQfnz@r7;NPE2BzdtwqV5t=?n*zyEaZl7;Ns zfJ&5!lsGGuX|cLo5=9N#D^^rR+08Lx<$cw4N?9zY(;rItW2rykwBCGz9O%y6(U}%; z%52uwdA|5p14$@S$pQ{9)b3Zt=T^L*^+U(`UQtWb$+m^KEr+jCMkb@QtE+CV_rhMV zv5n6r|KK#Tdyqd6tP=R_(Rn*c(^|VvU#?>jiIFuwJ}9~Otm^{%iQe=)H}SVnP4`l+ z4>R;-@k>R>_mts$Ux}JOr1G3t>2ZjHH*n=gY}; z#Fa11<@03gf1&6Q2Dj%_Rp@~ZzV}<(7+1c?i{0uAU*k{RU=DA~M-?i*2rufzcSOb* zcBaqA-JJ;G5imJjd&~R*mjZPW`2LR^ZOTw`b(oFRIqo18(995nB55+Fg9Wn=>l6w)S%}lC()UIp)wu6i>=zx!ICiOI%nV~14 z09^jvXR&js}SDRRXSF)^;;xC%A}X8C6x=jG2VubIQ&T~ql} z;l*UA`WIs6Bs{|D$9oeM4Do!y&((+vZS zy>#8b33Ez$t+&;zLM ztU=L}1o%;8sEi&MqFEP+5wG{3ibZ3k%LWzrjH?*h+9hhg>wnF_gne?B@OAglD%zkH8sK-Sy4}p=%bP~r_zLzqxpqhFMXMKZ zwoxy?5-=r^5aQ8w3a#e9l9hH{15#rXy^ToymmUcEy#4r3KDQH-(TNKZcgd7}#}>Fu zavUhA+BxLA!uIPT{LZ8UmcaXArcUd}ebj_;(i&RVeL*xF;Q>5-QS%?&n+{{rd!*!k z?m4(#>wbs4^s|B#5cp3NE_y%-l8<5g31Cini66lKvi+I~x%NnHO{^K;yhnfSJox&Y zO{@3#f&yMjOa}(|uL>nGeoC^yK&=J5xG;u4WViHs1U%|;TOF`^e&HL+cJt)mC1;ls z#`rt5z^p?F8X-@_i@%{FTT49AfzH?&8uv`{rdhO(A2<3TS@ql}k9NJ-*^L2-0WIjb zcnAi3P%sM(p$cU*ezwA7@iM=q8{tC$G-FpxDpl{IsV}v+~?%h}q zo=L|E_Xm+ckt~W9WFuo#I_9*5{W_mB+Fg)A`omZI!+?5aOk5g`^QkXf($wZp?l*Yf z@yfdku0>bpEvSZgFEf(~#y`A3`^91y;!~_RM+e0kgYDPSfbDCP4}DlPcT2x~Ajt z8`q~#z6b^Z|17tWuf7OuH`-wpgl?#5-}((5LKXe?-mcfV^kA-D?zy&83_-+#67>Ic zx#a}Cb!q;SK0?rSK3kUCTS5=WD_nx$ASq@OEf#EzQecALgOBLZyqV=kDTBgG$`l{I zMvWFs-pe8Cw))j4CUD=5IEcybsH~~rEf#T_?6=Nwop0A+_}X@5_l9)$;v0aC4!uRmMx8rpMBstbwfr8S{PAGJCnC86S8+2tUwF2c_g z1Eef~@RRXobII;AW+S9nfUj#dUV}O&6fwf^Lys8|oZ<^V|7?KL=Es_gnP!Ee*rz5>z-mcZvxWU+-lH1AgG_p5b&^uAg| z1~=E%p=G3p)OmwBowCCcPpj-YdJosI44gW|wq`BNNBOZ@O#vTU&y$sti3$j3qLHeaiIo`Q_4M3ILMD2spy+sTiP!AFWc8#JH1um&UYUnND9kgLW zg##NDJrQ$}ZPh-@T;JGhA2vOw#jTzHbkBc@*TIH~og&X{vKkak_r@Ydtus(po{06m zI0!o3k(&bsxddgi|7f$E0JoplotHlf--TZZ4?vh7bOERLr|ir8+qb0{r*AQje+}+L zpQllQ&9Q$BB+Puve*HOOiiZpTx?=} z()?ZY4VesM;MS6i`9RQn-SO!zp?A# zy#IREtxOens1XHrJT$Fzh3XmNwIgw?yNe>T_f1Pa{+59=y{K{no(kr|*NG~>TZ7ig z$&mtvpenm1++MRu&4FoUuD{WS_vzXUXAw~!w?FxXkMpx#l4d8RVBaca3kSn>E|2ne`#(&a~;F_CNGibSa=ly)5DTp-feQUZC zX#R8i(Pz1LWuTZgF0$mS2vIVhDlY;=R|zsj6$h?FUQse)%5?TzBXB)jhOEtU>0%|0~^oa{zn`b5=x^V=_cmtwIUvn}MJ( zpNrnQiSu3$k)G2~)A{HAqwA-P&N5(1=M4a-M(E9OjS2Y2Jzt^$nwHy~4BW)XP&r{g z6>nlfoP*k%waSwG@sN94bK}zz;()6c@p$p_9a$r}$>|>6(TGa1$i{SWeGmFG^*Aao zx)OH*nuiACDVeqR`>|v|zb{df5d6j-QeRz|nXbZ&j%ewOT%%tTMsu9S^TOoyv*eFw zh6camRDb3ZvfW^Gn~$3c%s~xfE2vUUB8aeqs)C$pRsGJFm^RLku*fl)+OY*iuljAc^{O(&&FvL&%1~&xHVAV_#a{?;2Z)Bmt|S0CCGx}E!6xL?ctx} zd%LHp`9;X-uqLBOl;?Yn=D7TU+Ar_1UM369X}bZ=lB*8-etnaxR05R`ag!Er4EUnqkwPMa`0HkfMIzL2p9+nx+r0?VU+x z4mQY`@9{mASU;`$Z?zS@>FITttJ!JQ+;{1w+EJ3x*a4q=&0J#bdf^!YZzfvpzASzv zcSl=qFl~EWU&tVjm1#*KYMY4PYLwLM)s_Fltzl0>?K=kaJKh1lLpSOYQPbS(ehui^ z;p3=HNKN{p_bS6{HSXIPj?|VQ!&%?{i>IC&soJo?BE;>}GkawUu>Vj3eN0`CXr3p3 z^5kAX&xH9hO4$Lbb-Kil{ct`(*1giY%Ap4R4l5GO7>bqV<(h1Jpj5L9^O18A^}~JN zc_9{a`=R41($E%sE}^y@q9M&PNU&X5vb&qQ z&6aEE&f^pB=A2ys1*x}G-H-q4T30_7H~Vz9Z6 zUHW~&BOh@r!Y#Da;}!*}R|S43@75EU=2b=rPeS6<^akKFYgelQvpzAH%ynjJlGd^2 zJofvANFECN%fhPgAMGr+<$reX%LarVWWGzG8FJs0ot5XQeV6^l@RkNICi zD%1rs$*slRa@o{v-yY68aK+?Of*qez`bKBDbpYjDc3={=&=h zks!3e$FyQmoH;)j$U|Yb|G6ghg^~MT^ZK8IOu*|s9n~-Do}g2{UbW9OpISMdGZBOnN5Ji|SPv`6p0LjDremIO#0w%J+)4ar?P35i zz8pTcu}?e#oov4~`J4W<#bTv zUCdu9Zzc_!(ZVMTM`G@5ysU?Csjy6+EiyGq3b5@X-F9a#=!|b9y0-#5R_Yb~`QKks|GTc)FF!_ugqw z#mJT4HM2&@lExkRDHjjQ(#@Fzu$@FgaRF=X;D=mWhzFmz$2@OVI9^jiz4uuX%xhG? z4#f#8vm&}q`0ow6!7coq$R;*Aw1GTP!74#L z5NFVfi{_Y7UYaE_59-Nd>a28gm;=RESV!YlD6A3mLFY6!1xNQ}U?>JqVIuE_Jru{; zw8GP+AIxt@YsQCMTp|`8FyWG@;RTROqFz?u6QU^5|A5>~e|Eiv7YbZJAd6Ev^3)go zh{Xb}bTUorvXyU<0=JK{2aDhXynwNJw%_F8Qom#jhfMg%LE_l7~An^nj?a@07t-x?- zOQoM%$}8uOd9!=wd|EPTdRgMgtXn*{qI3bC4w-TsdsBLOfgLGt+=a3n9_tQfG^?z) zj>_QF7z63tH)QFk*MWl5Q;xN!-G<|sUqSUtEWGMxok7+puiTl#bQ29u?5Xxf$m++< zF?QZZ@VRWb1!dD#PSAz-vaT4qdW%Y#f`~4KN;zqX*bUrd2bnTgKS@chyHE>JkDYv^5@Q0ywO6FF8wu{n-DmuU1P4Q^$IOtL_~LcP z)BvXImw*U}Bk)6k2&uzCrIB0N3eALgh`3B0uC(CvlnLQqta9GHG}TA#3fY!Hf>hG+ z)-2QJnOb>^FQIBR4WLj0UYlIhTmC*Q!g5$LMhW#O&xQ6LR0}{BWn9YAUtgaNb2&b%@byM! zfUaA-yjx@luDF}3rU1~r_%?_y7@e%q!ykxRK0(DcxN}hyDS4W{(g^1dcdJ1fJ9rPbi`^OroVy$I*-WzD5Iq+b@Q0oX0Lx zVl`(Hr@?|!@HGiejvLojYmvu@adk9o-%RF1+y_6k7dT5v6}iSs1k-uln&I&3eeHm|eDNn0Y#}So6NHseilH1C+>S{?vf|tGbN9T?Zp7L%`x{`pH{YAS1as z!e20_pigC7EU*9wkc)1ZGDa+ybeWwQCjYbq5H+-I2ZZvN;F?WyBe7amhs{NkP@^7@ zkd1--t|RB!q30cTO2AKh>P`2&wp^SDIeQ$|7!7bF#vr-rANzNHGbvXQn|j1%e>#=u zj|Qv9qfR8IHIzcQ7p+=w{gu#{&G?7+Maxpj@1vv-PVllW-8IbMC{CcqStP~fZNJqO zEf6d}(0muE(imeAlfkSErO$9<-lHW|i^704)<9m+j9c&yFv3gl%CQ}$pI~uj54F#4 zQ7-2=xzAS%tF9NbOr!2$=u3B^Ee7oQ#>$G0mVjfD<{;t#ECIQN7&)aN6WD zdrmh6KCuUMe2s;m82;MV;^2fx^^z)4E9KK_R0{Iq|D*)mEtvz@MO+M_bE;qYlSJNm zjv|1cR00z*p+%M>8*B!$%A(nSY2%c1R*I`glag%8pUE-@qUeVHA`)P~sD#@lnCd$Er-?5>Q#J529&3f33;2hZ0%b}a- z2O0W7KH#-9@n9;EA(E63xssb4wKRKx*Z0j2pkphG8QW-iFpT>nFJw92_iq{1+Y582nShsC+m0oU4ltA`%u zwF^b}$KXs5;|RY9FfxCY#c|AJyQMBv?nq1(2G#Q-gznM71v8?=e9Z!sKNF$W@I zZ~=Mikb`z-V3Lh9E~`m1E|2ice{FH1pSNCqmk#{oLF7TZRiyxIb)ZJCJ%PvWz%Xyz z&PL~kNsQu9%ILZ9K{OdGmD{B2y2W|OX|hF5ZEYL{a5OGd zg)rcJRN>nhc513OTYghoP*}k8z*rcpD4cbp;hZ#DYWnFF>y#cD#o0`Z;M3CQ>xJ-| z>rIK75eK&KO~R)fI?=JA1UwPB5ecSMa^rgStYVGLp)opLJ6$zHm^Uo_fOC0Qk~rgO zK)W7V0s`_}pnQ%?g?VY{z3TB<$))Ld7=tIg99zTP}E9k2(ml_|AbVTNmh46p`Z< zH^rLsu~vyU%G)Zw^OVI2=PgfpogJ&%gwoG9hw5SDaCgu?LXNw^LE*Fb8tKG%5deon z52Ni=aExf6-SqsFquH4V|Ed_4?H|@~cZ*AoQ^N&yjV&wYSrd9?RXF<*?dHv;=OEO6sq~A3^JKY<;QEq+;|GJv;Go_JazwJZD+P zF_s|fm*7Y!4tnUR(pt~iCr(*ei6ffttP6|BcWC1TYUpc&-k)mkWW=Uo8fJ4MGO$aA|OLs6B$;L+; zCVf>gR=8a%vcO}OMX{=bdzkVWDeyrwu0RQ_MlGQ(3wlD1UKIzc?=2xS$oy@_Y`zz7 znmwA`Pl#WYx2(^g*lk(eL=w5ANh$SYaFkoA|r1R;*WS&3lk!v4I=6dTU#*G z`jw1^Bo;Sm`$K_etae*wJE_S%shEmQtYKhnTNwn85*1YM+ z2UT{`TD$#e-I3CUSO~uehF3B-g4A53;vdPR-@lG!4AG4Y(%UsCF=f=Lp7!cs}Bv8hW(0Bvin!=S)fvE6Rrbw z5?aADn-#=SpNKgSqu?Wkz_L-syV1I{5TFubz?~#Qq(7RjQQ88OCp#kWYftz5Gv0wiH zyJ6whmdRQeAGV1r(_L9J9km$ak>~(Q4!IdA&p;D+BWJv^y*6-_K)nE={qM2DEP0SP z=OuBd?_+a)A*f=;{Td@k@xt~--&kMxkGC9?TNd9?{-H?Cyuqd=2}~qX^Q6|9E#LIc zMSeRmFWkt8$!~Cf&?j%MtwNzxH%NfCC_$kpR?3%X1J}!1mofxLe$m!?o{;JvkY-8+ z{Zb%Yy**c|K7NmXBr829Q$E43MG4V;6+M;W<39K^S+`Y`auEoKLUD83dknpE;0-e1$bZvc^Y!l z5fiaQKFcMP2UZfbY^>+8Lu@w>l9SaTx<>G;^HR$R9NsH{!S~7;rz6r!890?3QH51&rmJ91)%S0r)cfSOH6c<4u%UBW62r7) zch9t@M+xFMCi(=@1UYU^o)2bA-jqW^%g;tn90^$`;C5(t4bg$Ppr=wQ~gu zgr`6;oEcH%UkrJvlf)a!!J>P%@dYpzyFj)D>oGp;T8NAs+)~au$izbPq>@Hvd^^h_ zl6f^UTT=CUYHNiYyU7}Pp$w>#?*3OOoJNcLm^oIibz&^HrAuL|i8rpksUJ~I+m0qJ zaXOQiycp9m%8Z_a=sXqn8{0r&0_1ud#XKpswzlQMY!O5%nPa~fI8?(Ce9$`9W|bwT z|Gp1vWQAh1lS>158=qwMT0~az_vA~J^v-t}1Wyd1pSW5uzx&Gzk>~t8ES1DTX{mhM&;Qf@=)vTT!-(Y7=NZl z3iBv<(+f2o#z0kVLo&jvvym;- zfS)HFTH95V6j{ySz!Ft!cVlEujucgy%_!3KCLSp^CmaMPiQ5^ z91;47`$AvxTzQm&&Csv1p=fE#kCo#j44rmg{$Etu%Lx=e>^)HZCClf( zJ0xtA>ZvRyPg)Y9#u>-}b0)%7D)s~1Zn-)etjms^pHdG0o975$fMBs7Bu+w*Ai@-> zCDe-~8OyvJGyyFaNYXH|A3^ExV<2!GKS;-L>1Ox1jOa_yGl|QCcANW{%W}ie8(k^$MZ z2iYH`(3eanz`tg!Ll1|t?3(duZuoEw2CB1z25agof{6Br*4~xLr=9^f58<0l1~3c> zYNpem^HWHY`8BH3coE}0#=uVK*+6awGcr<6jqEYe5)<%ghf;&&95F^+@4jf9BNp>P z#EseFSO{}k>kzdxh~KD{jGG$+Tm1yt!Mh9e`!H`LZ2Vw@K}6K3_kF<>h{hIQ_S9Q{ zi4Mbbtj%y5KRTHcO0CEw>>>$rCCaUx8fSjbbaTkWn#I;_y=mH)rGd?N9Fq8PS{Y~^KtnUd+Y0iX219oERvpgh}x$n|Hj=DGB z2Q`66g_DLPJ(GqxJAhJWl8jfaa4)R-_~atN6Y6$&P8q={;k+~G()d)Uy~`BrU%eRY z7MrQCrt=GeJ~is24S6`#8d-?m+nxo(Gm%YsI*NyMpsnfXM)jLDt^D+F#Sw!U05fEM z0p1m*NUelrNa)TNjVY~3Exj(ym!l&bmL$0>=5MTqRW^;#9fQQZoB$ZP3u$DN?{tA& zdH%2#6R`p=g*m+nEvGO?!n!+wlBhFnzXv1yD2;Iw z&6H+hKq(!bKhgO@_Zh_xEp>>(s$%`#&%Vk!x5)}MuMFA0(%W8es84|#$@W`KZqX5v zTQzuY0Sfc+Ja~6g-&M#R)FqEz{5870gf)Im_c1=?M7#9-X5r9*e|WVCSMLF1WCrI< zMT{UIMF?}y3l7-g1HZ$60z1!wpgyEUL?7fe<;B}?n&A?fJnLcR#B0#trTm%36YGIb zQ*=}s4WHz`5j2;tHyEl6du6oSnmRQF85<|&)dhCYWf0gaID&K^Jp2jXwK{B0F2Z3P2i zU9Bu3x%pU7Gar1`@q1RoArWQ(3U6p?--Rc6Mw*a+8Fb9tsbDMPnadt$w%!MWfVXjQ zY$hx@xmXQw5=m20XK?R!_e5w_6i{5DvhDPkgB-FAh7)JAB7r4jiQ3JWtgwu*S`9d? zh_56mbRzBS3`-gfwNrA!70eW7eX->+%lyxiRL{P~>EDf!JS|4=q+e-1as6g3>jX6? zwW}ZYVK8fv$z5I3ginUlH&ziOIBn~fx>46-%`?kq`A^7vwGJUy~ZCq*AdMd zv?chl*Hc0phd_LKofpJ59p^30I%}(ayDv?3WNb*!qWx$^A`3&Ta^mHuR8?Z~Tv&|RvT z_cW#dgK6p1FKGe)t_Y{@8J@$Qiuc`ku3Fu^K(>eZL~Pm=!Lzp9OP9xCzg_QlIxpUD zR`W>UxqHj^4LE(8rv;G;UA11tP4s=wA5D}-cyHopT}nw{55*Hg<^De(5NP9gX-iBX zNzlKmNtI%)TMPX(bxv3AZ!{SZ7rtrJ}R!0&O}b|--%Dw8K&ixx4$2k&Abl)Elg zaypu01PKziW*wJ!Dai#L)`@@)tQRqt5v@XiI$(jurdCOAN?m2CSuq`nfazVvsY))w zB4s_JJ34LL*8n0#4rb8crB()WMM!N2I=7%z#02}9mMLE&LzaPYmfQVAb}T8wu8J{H zG}|AgECx|YJ)iGGmid9*Cx4BpCQMfvVWatm@`0AD>>Bw^-G4ti{BBmmVz)t;m%4E`y^c2q37X#N*!*U zTKno@w5cL}im>pscfI_unUBMne_^P_8W;d znSfTo`$<}Krxxyo!2Kk>Til$Bu1R9qlH=q3sjRawJWn*=_CnYFs9hY^kxD~&(^W9O z?;K=pu9`YO#8_&+A8e*2b@C0cBofGL(ZE%QCa;{g7xVz4%D5ue)iM4YV<#lh6me0S z#5l|Z&s~n3p2i9xWj};UblBHpj}~@BAUo zyd*NlqFzyVV-NP1y>d}E)D`OO>RuE%o(O%+B+DdC*^4b7=k5IXuW*5^I=03S4j-OH zHbF>hhS*8GeMpL9_-!-Jz)2WUw3*S77L#u)k~82&yct>ll^F>>J20|MG8OGlz;$T$ za*%_ZUC3ofD-$czn-xryzi9^XeJpEom6k|{XVGv}*f$4CV|ugV$~hg>vza``vK;YO zHSj;KEW6a@02$OK<&cIubX3hn3qmVfsY#(sq;Sr1Wtm6qrIZJAUPRn=*HgkkTYIo$ z_)RYoy2r@M4^j0or@e|+!{VEh>|TQV93TFBqDF-1PA|X~2TY0EUog&uQNBO73UQXb zWlNYAtKn6o{m*;a0af*O{EHx!owru28s?E0xRE=Ik%f*u#9nEAmtR!rb%4S#yke>P zs<;CRpS-FBt|JCcH;kJJ9xHUx$*72RF)_?{q$n4AI9a|YQR6%J*-!p^20hxTWdmj8 zX|_9fqhUv^=Dg45A`M(w38@9;GdYIJ&OfbZes%H!`}T1~MX%&kjFfDmm;;xzZn}ifSvIKp{@QH0mx~D zeh(f4)CL|_!K#MKAjlpLNY231_j^TV_dK&-uk)KZl4%v+2z3af1Q6)!Wo(-Qr??Q5 zpuOTYvqL5viOsN4#rzl1M+n+5jRr}Rh=b3S4D{kL^Vx;q?_5loh5iuB{@Lq$#7vE0 zQ=*@Or=w^{Meu35$xh4e#u*W~Pr$1dW+gioR8lEpAp;h}-LcM5<C~QOi|bP<^XVW{)`$x{Mm{_vf{)$*le|+MmByZ@Rn$&Pyi>JsEHzCx0UzS! z#_!zqgLCkj$4dJKP<-db?^d7>t}HW;jF%_KbR9%EiFB@u?nID%@S>X^Mc>NR{xcT+ z?UmPqf+C*`z?DXX0=@UdbK@CDD2< z1nMd>Y_tA^dIo-|PWtb>Mm7L84(B5{%^cUg0iSRu@%f-K_9;rz(x!7mxAA5_>Usa_&v2_$DV1C#t_qdYg9%UTOC91bbBz@IqUDgbG~64KVy|Z)0BPb z1+~(u%Ux7#12|W&$6Vh$yS52uPqe8M_ELVaB@&*52xHx8d%S1Wxu;1uM7GSER5Sq!{f0}@38%(UhBZWcLRt$BF94yRI-^IRbdWo@K&|GGwE)#Z_ELJ|HwjkN(rSo!9tw6O(}W%^M{ z%(W+xjjDC&w0bo@f?-pSXSA%iscR9wcLPxRT-x+W*ppJ%&^N&@CHp4N#WdJDp$>PNJiV-_b33 zSP5C?Ic;qK#wo_^oA5*twD`1&_(0OqCuFn?1kwrc35DpG2AX!3So~g`>k6ay4I2*|kUh4f3(WpXNfDo^Mqo=b|$xI_f9KiNWVu{p+(}6Q@ z2wg#DXa;{81-GR*(v`YrX}GHLBNOVV5~*#L&O{j$`%_M1vI;fSL9S_CkdQr+CXYx{ zlz(5WH>6HNFKhU;hP09{tzIxJ14BVxOwV6l6*81v7bm}#YAiIPJj}Hb$}liceG2I3 zl-Mh^zIs+dd7v&+!eS=fqAArr5FREp#Z|UV_sKE_EEJTsvuUynv5A0=Wr9p*K_POL ztnxjf8F{eg?OwSvue2!;NppF~N{e^6b7>g3Wo};<_^=P^oN{OI`q@!h(B_OwM$XBXuAaM|ZB)o;+o6i%hg|ygY z-os^P_^ALEDaYhz?@@jDJsWUSHoj$Wxm(WKTyFdhdKEqQ)0=r?rFDPTleV)f5kez# zn&8KjP`||GbQ@$P!x!YU#}4Zd!gFJbV_i=q)~bHEu@}l!jMFMa%RttOB`xsGO_%obxl#zF;^h?o<4tFEP}NtkHrNbGgo;|q)e zLw^AMR21`1u3M6b7t)^d>NaT%=l4~soNBFUcq^r7I=c$iqe*kQQ2+Gum_ab2B~H4wt&C*Ii`8JppD=cRSp2N0!^aD; zQy(tEs`6Rmn-+G~RYnRDy#(mn6io3TKjW>55R_KB#q7bDsQZsq7h&oFd7aQK@~v^b z=M1P2vD4*V(o6KzuNPQr7kz+ftci z8pnqkgwtZ$8Jr8YAYNoz>1nWtVi^&Yw4slRYJy^A&lWA0X}KXR(pVqU zsvMU9)X|U(v(!#S9)#0Jh0dcbFE)#ETtrD=bJC^`S{9#r>Pmtvn7&p8)fY0LLr6?j zCrvh0QpafDz|=MI?!Q!{|D%COics~R9^K{`CUvN(OVISkDXh)|I&&zgG}O6dl&V(= zR(1U+86CunUTf(^Rgq}*3uM|v%bapq zSHAJ1NT+2WA>K1`)RkQMLP?DwccF${?|oG?w7^n_X+DV`25qpJ$5+o=mG!}^BjV*rR@5QU_%K z&6ZbVIE4;(|}tKgTo78aAXwln@Pv-dr*{>p?6>b zWc!E2X_gme<$t=+COU!2`)?ce%5WKvN?-T)X0S{I6wQlOa8^vF z9AS0ZqvP08a%`K_RNh8F5z_@2)5V3JGu35M;=IF&fAS2L8wd0slqe_5F{b}qDuSBz zQYK>j?-kyS3vq^tSp1O#7%F81iKRU`zwJR|=Fx^#N5xf8GeQ^tP+$C`w@;b0pl!>v zpH?+dbZcW;(&MIOzO5)1%yIEou12dmu^KOz9LI)o{@BX(@pl5gC`C*XBCn4P;>gLO-okOn9zsh;2Vl6l3zD(#~N1q3HZkXqUBga3r8EKZA_{kC1deLx1Te>|F z(|^QPY06{3KM`Yp9p5n00V6CEG5!Zy5>;L(rvBSF&U&t@tOe(s(UHyzTxkjwT}sKTPzj|ml*C190g5x@P@LEcy*YsXQ;vkf;$fJZ zo`uquy-?n`7ho1Qyo43=6FA|Qwqc%08nmgB3}eHX*RgTg5NRhbV%lF2F>WN}@Fu?a z(AblM{#7fXZ_#4N4~;;kZ;-y8Ig7t(De9E*tD$iNV}4$oLL%U%Fg_uSo4h!o@%*B5 z3^x>v362}bbMsJ|oPnIM*FU-#`WKAAdhugm|A2e~IFB2^ z+wm))*8%LC64Om>l*zjzMy!naVwM^6)r-vp$%1S%ZHF^y4b0=Li&4)>tC-LkTn8~$ zdKlETI)VRz2EPJ&YDRuFv{)B2Q?rnn!wuOUvF;9tH90S)v97G`DOCGqVY5t|!94&& zeNY-10$4N**<}kMyF{#~L%on2$k8TmxjYA@!ZeidcY-m@iFQk(eZY<2dAc6L4Poag zU|P$uDLgOK))x6tIY;qamZ74j*L~7KRDz^VMJMA#MnZr(m2$JhovEmKA+cW})A8sd zZ<_(e)N;jkZA9L9N7O7As2l16b#_p!u7u>dD-u#(3Dkxt({<{_W`oX2l@3DdptiOX ze9FjkT@t2+4LO4N;0FY-Oxp`u~YWm-qwhXW1hV3NRbHcbbaQ*+l3SD8wh zGFMtDpiIikBCcG7BJ%cSN&FR|h+mC3J_fnD8R$8AEfkk8gn4n%THHAf<;{BlCh)6q z#W_MJmI~SwW(gYG7<=L7|j#?4>+O3~gNlxL=(XTbvK zU$PW>#r0W!(Nf5dEP~wN2z_OACM)#t5BstRW`!`budP z(;QP7oUij@jhra}OyJYNQ}VZgiy8SJVtRVTNg&oj{Hg@&WjYGv#tr`N=saH0;7_Oz zigkJvH-Q&HcKIU6FJBC~r3(QT;(xNiCyenw?94)`FbQQ0bK)9kep-YXD3#{OQrY=B zXd?(eDx1QxdAY`^Jb~WGSd^$#MIVD)S7e#4r)yCiB_q3(pscbX+joP0sU#sYr0(RH zZo@q8wmG2ZOm&%%7()4ZK_kvLF@aH5ndx+;L$MQt@ygR@xG9Wzk&%;F>F9iXWD62A zjnMn72=W}Q1e7`GECsV1VYDo|@BdT=0 z$5i7dPX*YCsvurO&~wl_&vang8t-9rdIS`;Cq zE0e~WEB^?x=j2@2WSWY9jR$}JLnbIA{;6{WJtUcwyJHa?WKXDyDn^MOZD(Z>5e`vB zUO{O@g8ZbKrX>m46OCzili2{K9#&(QHV-|ZRiL=l&M}Q6(PP_P69qSb^@7bX>BL;X zb=n>(Z`y9C)Kf;YUKUh>!lkQqG^C3$Ch5hIk(zjsG5u3=N)h^Ot4K7eM4ykwX=x-y zz3Q4w3#t2X2m|^`+n6VAVl;wgRZ?R$PxIB^epQ*unsRv_U`!cGO995hiws`=;;++@ zK!6`4%0OGd_(aU)et_{kkUj1oD6d`&<-Q&$jmx} zym))=%_GVl!!#0kQmCL26OXcL0+vgV9q5DH=n#k#0t)-~L#}@a@(UJ2&w?e8Tet-B zi52`sXunOTu6L4NT9 zIN+cIVc)|K!yNt|X09JHBa0!M>lMoCea!GX&DV-F!qQ#5vyp==edJ_hKb znt21J5{xSdRKkq<4{HvX79oclz%5!3292aZn zzDX!g%!q3ad=glG#d9W~Q#Qp5*)`B+NG{9KTq!56ar*LN?H-2AvQfycTnhPB%b<7V z66jgJ5Hbq}pwv^M4dCMBKKd4v`I&Jj6{h4yuvo)O_@8;Q_&dS)R4~SJn~OGqaoxw} zM4;1`g1p(M(br{;Zvwwl5)+uj?#MMpbxb6+8LX?jOLEL%fx>JX3oz>vFvCrN#2bInFd0Q!tV=Co#}pr9P!ej-NF|1_P#L!i^GP9ZRV%x-G;^oA}xj9mn&G z`mcit$;69yfLv%BhApeHsAwDBkTA;cD45#Sb#-3Yby5|~bk*@P1X_=-cg;!)zhm8M za5&uafdn#8M=XKLF=^DpKUG9!Ok1H3nG>sob13N;YjmL}Rs_v;SD83hFi$eq^_4)F zbm=N=G8dvAdFpnlA<(%(3CgHgCM#(?FECS)Y3Q7Bgz7zqUJNyr@P4xvjsr^E(g=u( ze)XkHj&y_#U~SG5bmu+TrOBcPxavxdRrib)NT4oBrk z(j7dEJr{#=qIg3@Xdb$QoYyjz^VA4F$T}XVid*isi2@Re=`H3l-IT;~6iYpt-9nCA zz%V}xFtra#`?f&#sFjdAbOmG=i~!6OA+vc8l(z4a-;jvA4meiMcwwy06TBg+(Zz)O zJaU7!RFYvD1x|cDDRG`skXdK`iS-`8Nuqan02Usw912^uLScFavV$X#Tet{HxgMC$ z;>!ga+yvCsPW~64RK6ehZXaNK&PGc6w67XPz#pt z+@MJ)Bf72-G5!acIk8U86remYEy5I(@wb7oEGyQ-yjX+vW-x+sigiL@G^hWQ8~y*a z9#L%-`j;jvXoE!FF$gQ|owTOic6k0YnG*eO-=N?ubfu_Nc9 z$}|vXo@1oO0c9jsL7x+ZmSd#lPLOh)Fh`nDou^0@VdT+@230m%a;`}$*MlK9fGuvI zNQrgQ42`C005#2MoM}8QJ&xTwiDnlqQz?dNCV0--gM8EV22o^yGO1sIBuXDEP+G|m zEtf&OE$RY=Q&&StsY{45eNjL*M1hKA-Y@NdZ^SB(hV(@M#rW~m&=oTGCNP$2qfDx( zc}VneGZej(uTJ#b)j_+F|FZ#2Kf%7%!2HK|n%0l^q=Mcu?BLUs0 zEJL<52f69}P}sc@de$z3-osZzZtK*Xg>lsWU~W9P$=hwYEB69 za+9~GkA9~zH#h{jp%K~u&MjC7xsg%mSs=pjh|uW~R(1Qr*z~kGukh)%f;gYV`Bj(` z=U*8X501dZ#w{>AJ_R|^R(`<}(NU@QUjX7@q{#KLIc` z3s5T26T#VDd?FavMm3RX-imr;L)+9bBIWp7!KGXliaj|f_T`~8)Jwk=3`-Y62EQWu zfW^?WbQH3qLr@;*5p~4+JUb5M$-T50T%5xvgQw+_!R2{z4&oER;v7_83oWm+FfNI1 zl&D$hn&Fq>mh@hh;h!uNLHv_)%xam|5oMH>IrY{h^Gc@k6jP|AneN6m2fQ-MdxSKP zjaVb|;#KI=<}c-Rtkcz-8fIRn(*gM51%fy%)2Q z6hr+N|D4`XUXO=7_EJX&63cRzOnyGcEZRa5BFC4B4h^ai5L;}9WH2r1v_6bZnGjU; zbYVqOg;{2tJ5GvZD(9$H^fX#hU1CAl37&sgrbB$3HprA57kS=jnaoRp%46ibRB(m{ zqi)J>>0-?bHEvwc-!@0cfr%YreaRfDq83llMpRGhTS`f#?~IE zQq3V-n1lSx1Y~AsAwM?*nLM{Bhqe{oar>`U> zbHjc({0>sU!80x%D+rk*mI?FKRmVx|GUvrtPbNJ&rXBhxW1W`-$UJRPuJTezt84|2 zOxbZn)d{!0gA!WHB9erSMo{b$9gRP=nythySnj#tZ5$H{u+fke^u!_SX6 z_?)0MZC2N-EwQy_*D+ruIxS*HtkaG_EP0sLazv+$~0PEW7F{ptvVryTd!5rGxuF}eGGZUPF^L8shP90T7X$)pwCCogf4Y?NS1ZAW|M~)rBQzoc-PjF`xURkw{bMMSG2R(XJ zR*|{xw^hwuQD&2Ayk&ZaSYT*L9NnPy{4nhL)d_8@4w}&hlMb9?-ME8ZpXC^}n=yYw zwBgyJX9V3bB0jzBn9f(d>s3)(BjvPx2OKepy5h46{r^3cb_!~tKjRQ0O;z!86{bZH?UeDGzf``)2C%(%u4~mMBb)YdpoM-h z3DNRn*xi$;85_X3>Dx207xEM1ki*}nV_Hk(Dc_`X#HX3S{{R$~DpN6RH)%N9ih!$% zwxrFEvHfra9VDMJ*9E3V$tbFntK0e2bttdPoEMLtNUJg__UJgeB9{M@OlJ_MAXuhs zIVNp74j!4VORs|Jgj?T139V%jNy0`Wh<(n8ilOTUE80J+7(!RMpIlL8Oy+I(?p+2< z8Ku2tT8@#EP_dJ6MWjjTYPl0TGJ(~OPFEDAxRNJ{nRPOT&`GKUMMk-USze)%wbXG$ zmNF}0^=hH)Bx26z1g&Yix?W9*b@#)NQBvm3SBXxG*b(crBM?g-rd8f7(+jAGrMOyN z6{{pAM4qzvQl%@Ss=P=@k$7=r0;^1AOqoXOYiv4Rp;adYaqG2;dd~r;zKFCHI*!~c6ED^@#wxGV6w9bmR*`EJnbAo{sANW2CE*sEa(97&N5@3W zJ^SY;C3DTqik?%)Hg}CpU5SzR>IZEABaVK64J&Sat8FBdtpsRRJ51{ceT?HzhGeEu zL@UjhyEWS24d80JV?=y<*)g5>eP^m7yk^R1TgU65jy@NA`k^>H0)+*Oq14kS=eqi= zf@Txl0LD-%iCl>`gDqd)r>X7{O3Z84W+R*SaiE2MF`WWWqDGRRnS_Du8)10k{m{2} z7jOQifyh(7N#}^~GM`}ke7ZAX=-7GE*p5}K+uBhwigdY6PfP7()r8fn##%GJIVKij zz(bFDu%i95iXn8B*J!lLn9PT7LnJ6|DO0giVyL(<6|6dj&@6YHbO}{lfg~=m$awQ! z9Fe80UK(jT3@vIlHevh?+b2`cTBn}DG3wT1rq#5w@9hfS(5i_?iLy4Cik-AdI5P3# zq*d&sRhdpxETf8^A=hP?&}m%{p`oi*#|0;i0G0w*D;E?57}!h_QD!Cpt> zEi>}obHw-YTtyP+l(6C3O0&*cUK<#PR!@eA?Ki_+K0g>HkQ(olOq!_UVC4!k(7Sgh z3_W}=^lx2H--y~!#M&#rx*8yh>u`0Dx7ocxzO)9}w2uQV^ovQ5mL5l*M2!N!)_GvZ zCK%kZ9(pFnl$2>XX`S-E%Y1?k^Xblnf#-=E>yDS-Ak}lm)~XrCa>&-Tnuwhml<=wV zBWCKwJOH%_Rt&!}i+Gg1b*qfYyj|=SA{Ln=k_q$G!QP3gx-v3#ed=jksxng%>6F)o ztCET>P?4=%$$YB@*lYzUbEhUz{H?cd%^aI{I}S`WwQi1i%bk3PyJ}j+RJF+vm)u*Z z@sU?;)?zFYPTGu>oPsKF@+zamRd&7lj-mmziviOlz!!;@`IReN8@i637q?J8i4vA5 zx;BjZG1mZJ4|q*snogTdx@Ne`=OM!cQt!Jc(_Y~I$iU`@pnvB^$j%p(v@zh_xh&lP zs0vhC9U6?SNf~s?f{!>Vm9~-zOax*LnmO7@1f~)6j_-lt&G$pk#C|1V+LtDrCwwY0 zX`!p{TpD_aYZ-57<6S_UH!D@AW>v3(Cr?>JhDn|Ergcnd@uFp}v_{K}vZ}mF*vcuW zw1)CZU@Ld1rDF%hL;P* zMJp#nN++YQTYT~`ok)cDNv6F>@X+>*?}Ncj_d$Mqw~{o5fUkgVF8<5CPYH?>dXH$t zTTO!QbvBU)iAT0w=-agw`gd-H4F145lP+SNcMT?>iA10N^(AH-JiVE=rM2g^i@IG2 zW1wCgPnpU((lF+eqHEV3pFu{k2-T%ZqRK0HG^;9l1u}2l{IzbL;)@7QTH(#>v_<3= znwWJA9aG)rXsvRMtH@Q!6}cdptw7-^s$_i&A`q*Rodiw!60?n}YW4V9t8TsH&`96v zp^>&bkwo8Te2fLQ;VJa$>bxnp$q-lGQ|Q!D35+NyUaVO>6igYu*f8Z5ovM09-c=N!SA{GK(x@t}dEN$FtD+g}0IxNjOB0T5 zvQ0#^)~vbf+fK6_NIwx*Hl~AUyJO$YlQqGUgeQ8zy5FY%_q+Ei*Z5yC(Y>yH!sUq@u*Mt)_povs({%ZINy>q~+(2Ob9Y0#L(9k@94 zJaud)v@EV$NXWYNG!dD!t~WRcaRwr2GcpXSdbJf>0cJd!RTYJxs*ZTA(i7N)Dh|L; z#j&SiM^7Xu?Fc;7kehV_$2+J@;3}@6OH}Ll){1N!39A=^1Wox;XB$rSBz$c~e>L8= zs@jg=Of&s<(XxhHOQP>LA&gb22tmC*P<_J=#(Hy8%WP1Ycp-gn8e=oB(kdzQN=9wz zG?rnk69UrnlJa>U*`-n<_^dUP7eGOLE)X;$;}Gps3H zl=yhjoYT1(Z7{7N^0AFR8Iqko5v?_A?)tXVEC3!bFS;CKC+(?Av3S9_Dvg+VBTae4 zlqsQ^H#c!9kFg4sgv2b@RLRUj#8oKpmLo!@)l7dJJhCu4NZ{!r^=+19y{PsOt2G~~ zpc$t#w$Y4snC7F8tzW3Zreua{Y+CU{@Lv_WVxy@z=n3K_DA+5B(B9yB<-2Av9e_T< z;X*LkrKJfTsP6n&EGQ+Q2t$ru}H)Dbo4GS_DE8WI&ghIw~Ei z-B3zZ$XfC02I9N6G-}ZaVHdmEfUbJ+y*Xt?6jYVfs*f43j?B|*RgqU9FlF9K-h8z| zL!=TES<+S1kehYAe!G13l$mzDMK0SFs?@^ZXS*3Rqp2j@Fl;q(l-vY0+%l)?AhOTx z*vW*5^HyW6V-cF7s$wCq+KB+wH|*%V29r*iN*KjXh9dETu~Tm5l~CukOo?4LI!&1) zR%usIGD0PsG9%;2%(P8rrd5zH3Nx)yGN&j&$HAr}a84mv?xQ8Jl+--^R2`3=e;ZAr zicFhsN#{{+dJ+b}55vCw-Fk>24;pCpq^+u7OK-TWYvm-k*?GMP-a zTIf)VY>ZVEGQbVAbk1%vv1Upz#=i#-lzOkJ*;-FcNz(iamM` z&dMe&m=quUo4<9IEMz4|(I~h3$I`sLR~huz^yYoqlz7-3F{tWmWjpya2BnY~hPp(B z4rz4Fgoqo|Mo8n#9O9)C#o795CX1Ij0UeBWq838d<5-)&IF`|-DV3sB5F!=GQSn8X z`l~zYKD_Mn!~g9zQD*gpRm4ZRP$HCeWgC}eJ1WWkN?i;q`}7#36KX2>y<{I9W-!{V zl_aA0gb>!ZG)OU&DOM`sZ9&oquEz*#D{h-<^f3`7Yd9aIcAYeXT=dmJiXb~*r-WYe zmwmCUuW5Q+kxPEMj%2#sUlt*BJC?PgP{=Yys4aFG<=jj@R3{%*%=L*xo^F`!9=gut zqeFcZPkSL+NQ;wC8!48{SleJjrbz-DC6tw91K55su*G5xxq<`x^@3Y3JrxexeFxZW__ieNxARaq z{@~q-{i`uQksOnBGVHSbK)C6WQ=wknI`Gy;;Qm`J(-jK8P8-hz3oh=T+wD=J#hz5ISMHk-AA zMpVB5g8G&gX@yF$OS!_0Pk9n|yaW9;qg?dWLkgRn$huuB$a>k2a*}*(k)xLupSoFgH!-D+^>jk`*_(SEl+}UG~1AxlUMpjKN1y(Spy*;3M!k z>mUb%PiVDbQqsm9w}``$jEcH&yn@qrsU}0(=&mXJeejY@G_S<*e>czGJ;54$JKgSAS;+%B-ATOR&BZtA1EeC zl{vc3fd74Kbii$yTbV> zCf?*e`HI^}A2ImT$ZOZFgB?*{G5FKDkD`9qYBmD+2>c?M6J^aby!}b~p{d#qU+b=sEPC0xZr9XT;rq7xOCmg&dT!qFA zfBJaY@|7@d!W0q%pU>529S?s#{{+(3z|DIR8}F+lUnKbiaQ*qSpw`M2tmG&PG1fwl zM3vGZplQ1)!~W`T(iejg4!ZM#xmVWeFCy4ep<6 z-wYHxzKK$_S#BhqFGe(@?yHnpLDuPFZs~ijK*O z8!CvhXZKt@iHdp|Bk2?wBd_1O4P&lLCEY))KE~w3N$Zc2ILuFTk6OE^)CzTPv2?z&jiXsi>JwPA0uGs+6&*v3@;DYhX>o#!M3j_P!CyQvU=n9^iO` zT--}it7a`&j|OYS%2m+0eH-}uZI{6ggSH@F3H|-g6JVzyTf<+kJ0BW0tWP$7@4x;$ z*lP1$@X=SJ;nQz_Aime0dpwKgfxq5);cS~hC}eYwPRbj>a1f$JzM`8q5kRg?9u@m)~}EHIaX|7 zbDsG3YtUol5pcnu?;~X#d)HyxLZ|kv;iIp|z|Rw>!k;fZ5iUIGFj%%?1-$V32c%Eu zpKu5qy4Ofjr(?TTFnFuY$;R+EKm0=agEy@2K>e5dgTH!u#i~{C{ukfD#*G`n6{jBw zL$=(E*lxV=6xeIzcI13sdixVJwmsqc^G+bY+3YBPYOh!d8@S*7EgZgZ8k12OA(aSA z)AnAKxW5jS3i%`ZK-`qe5H!$<$2xw+OfIYZrmd+#p({pj@C{n3n>6jV&Etc$)S}r< z?#dhJGLqisQiD{(YMSUoDoDLV0M9%+GN1 z15YuFO0AkT;eYRb3a4Ii8yt7>O)zcNJed3YA8`0N*THG153j!W8En#YBk0MC8%WuJEJvuA>`Q)21D8_Yg=CyaigHOE#_3GAzL0j}C zwhnDu!kC{Xz!}%xMcTOh_J`ov|Gf)Kmbp)iRstI=RDb8%k$}Lpu8f|T;;ve{Yd?!J zI=^awKRc?VXG%J5%2_DYz(i>`<-SD?SJWX%5@D*^oJu} z_UR3EF^ro0?Vw-lP53{9q4~nRs<%Z11nNk zS+?1U2pSCNR<0IulGFems^jjkBYhGmJNV z__;*9=MyPE`zRS3EGlgOCAAIUWJ{-|RsrkqkgYa{>7Ts-?>>DuTzk%OP`h?bxb2~T z!l)m9f!^IZ5}z&lbcegIIftYHeY%maJ?_w^1F~mXH^QI+ zeaQPR8`Q2%>c$0cs4iczipWcsE{Aofym0XnQpWuD`$DK$vnFiVuz}LQdr;qS;{9un z`e%alZ3C}wx1)Z~K)b`0%Um$X7GtuZX_vv?HK#qlQqc zmNzXHE?x>h{4$Z1fP9Vi>eXwYd#AQcLwz`lmM(*J_{9aG227bT2L|@*1+V}8Hn`-J z!(sZYx$vJiKVo)AIa71>D%fDD`zr5(2wdw5SO~KwpsRLM8J%A>P$|!ff^btVB}@Y; z>uduZ=3}cTTbLviNRX?cCq;5G5R;=EH&^8C1}&gJmZ7zdxXmDKl6nMRH{;iEa)gNq zK3AkrbhzwuQgym0%1DrG6sC~s6G?AF6p-^Uj5)A$`3myY%kTc*U2xMy zC&QL~d%&W_OT};5X2C`Q{ac3mr!!^d95RdXCzLrC-grN>Md#mR$0NwsP6u(p$_q+EMzqlW3*R3VLAsl?Is1biE_`ZMq2feUZ z562z2JG}U}o5)vSJIbF8mMmbBBYhGqggL~17L{>+6;CC-$Ks}30@50^h;f9Q<}Vj* zKE67--3Id`nXOLLSSAXoTY*@H!#YZ_hEH?Wi@rI*$~Y4yNvEJIP}$@ox8d8kI3`*p$-<})Jxiii8N!SOr)+cr?{t4$Z5-U zZE*^TUn>cPb~KL8^RKL?Jz z=+E%SBJb0>#b%n+za3GZB)s+Um$2jDEn&|QgP7G(uGC(#m`RRAm~R(^)sRohth?$P>JEn^w~$-a zyI&LEx#FIeBbcLE+t3a2Iuf>~gqW*_SmS`4gZzDCu9batL;ML$XR9mpNHF;*cGbb# zd{*@Y!(5V&6ebH55{NAOV5Bk=bq|w9bvD>#v&pVH7_b?v6^ct1&1Q6JNt%gOr_l4r zXdE)9QqLv`8IU>_#c-vIVVXSK)fg)GC*{`Vc2^V>%%?Qo(tc<@dO;S#|Zdi;Zib-@Wv@-|6PZ{ zHvQD!{?(~jqXuleQA1WL47q=8Q2+4e>%FLdKcM~{jQXcDaq3KX?v?jo)7CBFuh*Rm z`|UE6)WKireAdwiz~UuK;kEa_VBRYD)4}-Dyc=)Sh_=mFgAbm$2kyM`Y*HVmCL1*-o7{ga%x+`dkv{lq z2WqWe$x4pcSQoZJR=g6BsJkURN9|2{N0s0%dl4`VYTSY5{!!}1i5<5eDqiiv;y4N* zXz0V%ai6({Rz)fZkqL&nL`U>YAhL|C^V@x!zlvS5F+X9}1-UF_3Hc=TSfUQocm{;5 zQw$U(mch=knlwW|h+q;|R7ojJo=9>^snv-asF3k5q^_g1Sl^|K`1YOR#tM4Xurdd4 zZjzj41R-lS?u)@9De68vp@SS-E@QaJbmYi=aDl23nvVG6#1KVvkY%2cB$v^F6)AE- z_M?JlmHdbu9Y`+83}q8o5>;dak`4E>wQ3qfSwBj-#<=yZ`mkQ}a+?hC`>WT;{ERDR z>?;8`=4nvW$Il9*+{X&mPg$4?OiE z^z70eK7Zjs82iSPu-mY0;FWhjgXdp)7hZn*W0*937F>S%kudSYXW^DhPK9Z+=dx&i zUjOJz81vHvIA;Id;Pd}H2>p6@WtL>T7SO-vQ2$K)^&c<5Z4W;KEt)ogd#^bMet!EY z@>{#JfBPLSy6JxS`0MYPr^=G0%i(`0Znut`!e{?}5Po?5N$B3GJ^a2<{cD2X7A%BT z&6^UR7azORqSePyf=IwpkqX!g*}UsC3|WVY550z#4%H7$55*{Gvb zWVwVdmI-9FIt0}Wj#?D5XcD)P_fuoezB(!Ny9B51C>N~nxM73AsH>DRD+Kx=*xMV%5V(^%| zaW9nQkG$mtKF>nWHH{dhq*lWHm>O-i**C@W4!CJ!-p|Fp{YMVo3hLI`06zHgJ6O7O zInz?`MsCNpt>DYi<6zd@`AnNWK?A=d>R%nyzYkIW@Mdik@YgzbK>hv-^?PQNexpIg zpZpy+dDydUfl-+n;_z-~+YSrpQ^&Q!< zsB<4C1ylF8Sx|S;@2uodur6N3UeywkYPZy2*`BebwNedxsoG77?Exvtd1Uo$O5NG1 zVuA-e-sLcPYdTRh_!1S@Yj17}kn9;)#&dC?xe&3y;_-u5pt+`}A<4mK<7%&8CLLCp z^#r-B+Yp`#34Sv|uFrBChWI5X?)|5@t94aVKwO_qDr+XZ`O5@`&w+si&7|s>p!n!I zBxrW8tGX|S`}3STrc}$86}~jvZ%#<_LwqY>9XuM~Rg1lBhgWtGp&6uMriBNY@q zJIFc=E_0id8RMAzFkG+bg8e+TR1iug$Yn+4l{EuG2uPGA2u3pP^uH- z1Ah>)EBGipLiVg`+zeK3(hA)t@{NLITtqtZDhb<2T1RX(keJN|aLf@c#|w~z6bC*& zfrCtq@&>T`#BOyEbpyEJ%t=sd#WGfM2(0&2PFJ;5yX6m--C0{&D&?@3vh5_;9*~lp zM-~rm`kPo)kA2YNT@I7CrV~YjFHv#5*e3AlJp+c9nNmEF<$5eqfj*g~62a%|>8XjA z*+JKt+EQff!V1EdL5kca4g$|z_K}ekKAVQ#b{>d(4=V0zT~P{(X|yq&W)g233%$>Q zq5EM_A>TU$ zGU$oQ<{yQGb*5BnlxCHkti4(OR^7FMTt-Az07AupC%JNZNYp{%xP*GX5U|JiI zEY?g6mW3ZX$T_pc+5jdw>xHhz1nDrcof{+9CO-J^!XQCw{ISeQQP zy=kvUEZ!jiWDj$}2p`#Bt>~#$y(0#N4xO<+Q))Kx*0azXDqNd~skvqzM2<=UNuf!yhsXi20C&?JSjv`A~?+1h47qi01*{Kz~J7MuF_)0s{ z0>43JMKkKYN?9rd#guJES*y&8`X3IEH_~X4mU-fWml24J4vJ3l<9Z_FKb~MRKA76# z3R0G3DtdO5a~-h@2L!VzDyCDE82*PAED7X-r4B*2VGMPRiw3osA{0cN1%=36tUFcfWui$4?=; zTw%R!a(X|d+AVXiY|h-$N~wpv)a}Q`b~`6Ik77T#SvMZ49rM7)yBs!eO)rXJdg+Zo z`3*?Zn~~g8mSr2ud6DXfKp`?KGdne-15YpPQ->CELC2(@SN|L^gmGozH<`@gtcmbHeRjH+8$AO#f3^WK6~g5ed2t zBaaD^RV%N9VS-*J$bJYS%dupmgzY*JG@B>})d?eE-N0&v^hd)QD&~zV;zX>6|CHMY z)p-`(M=G;LO09u%;erLNOk}agmkEIz*enJ=E ztC&!Mm$fRMUNe~VK{`yBK14@V=pb}{AEgas(2D%v<-(2xS(Y-jER+oXxPXp|i5GN# zuLec88_L%ELw|f@DE^X%P0t{jO1N+H+Al}pB)YccHX$tiE%j-{ZaUO7*ZOc zavJC~2^siwi8aX8dPN*jH-H;Y9LuD1X;{B5TyoMOFk;(&P-g?W@vF0H^=f$c^U-k2 zBhSLpWhr{R72B=Vwhgr2;j&v0hNhL$_c!TMJ(_){n^1Qpp4~` zo~pPVCngIYEC%T)_OF5FdU5bTMXHf~WF&>pCWDND_7V~2Ui7(n3Lz=)U`r6SZewL% z74401-9Z$QVDclGEOWx`o=LaMWlyG(!G@8`x(yTb=0EloWhUr$j$Bc=%Faqf3Q-yK z1WhlBHvgz3tZ%JWXn!=U;bPvnB2I*Q#Mk6Ub)H4{k;>9~=B?By7iui90?D|IufyEN zatx9A+KWXb=yp?ZS)^mt1#7BWSg!)Ou@y$DF-a^(` znnCwd$^pK*A1`ZFJiTU6{8>S`AVJ6oE*sWX0+E?Q=#ju>*~DXTn_|QuLC9EC%U&N? zE^M-&5SS>JB^l|xlC6&H&r4<-Mb;tNdVi>oN&>}S^6HR7x=R<#zQlL4Mxms4k2T`Zi)Yhmvlz;8Cg{szh!SQX>^?Rer^A_? z%g2AaR{oSdEyk*IvDn1(aJ5CQ_I|>gO-AWGpXoF+YkEr*F^JuUFbK7IiN9I8RxvnO zdmhUVD)8{k0EI@tf1zQ2GZV`>)i&sn3XTyZ_U6Oku(>HkC3hG`(A9d$?q zDrCg3d+IA+9(t4-L?#@aeOzfUu2@zNp4{wTNt zdYa%N$YqA+?EtfxbI0X`(!LR#_qBb;IK+O%agZ68=7A)Xp7xvGf`uyrC;-5Ri<+Q7 z884)x-T$*Pu0unT&UlWq-6i{f3ZbCl9 z&XAzZd{tMVY_gsrWbFL)s*vKxA)`@TmvL>#tF>@$vJ1ZWoybFX+F9{%-qCSs!81)z z65m_{EzD-uXTyD%A;q>*Uh9JHKHxBQTtTk~7o{Jlr5C%dR3FJ2Ln znU{kh^VCcrWm?Zx7);};&rJJ`T!J)J{7>B85bD#H7E$DxwqtS{8QJsDLO%u27t|l) z65&^ZiQt)#t9oHN%|2+eE2q8s(Nqxy-4`$B6A8}k2%fF=$eS z7YH9l98In!Z^-jsIi9Pcu&#GkINHel?tD50oz7~D@glX+@IAfz%0DBaI$&VSr{i-z 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

  • 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 PMpKfWwS$k)F8=-i%ui-4 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/fonts/stylesheet.css b/luci-theme-alpha/luasrc/fonts/stylesheet.css new file mode 100644 index 000000000..126a5101a --- /dev/null +++ b/luci-theme-alpha/luasrc/fonts/stylesheet.css @@ -0,0 +1,71 @@ +@font-face { + font-family: 'Inter'; + src: url('Inter-Thin.woff2') format('woff2'); + font-weight: 100; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-ExtraLight.woff2') format('woff2'); + font-weight: 200; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-Light.woff2') format('woff2'); + font-weight: 300; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-Regular.woff2') format('woff2'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-Medium.woff2') format('woff2'); + font-weight: 500; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-SemiBold.woff2') format('woff2'); + font-weight: 600; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-Bold.woff2') format('woff2'); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-ExtraBold.woff2') format('woff2'); + font-weight: 800; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('Inter-Black.woff2') format('woff2'); + font-weight: 900; + font-style: normal; + font-display: swap; +} \ No newline at end of file diff --git a/luci-theme-alpha/luasrc/gaya/gaya.css b/luci-theme-alpha/luasrc/gaya/gaya.css new file mode 100755 index 000000000..0bdbaa1be --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/gaya.css @@ -0,0 +1,3609 @@ + /* Base */ + @font-face { + font-family: "Inter-Regular"; + src: url('/luci-static/alpha/fonts/Inter-Regular.woff2'); + } + + @font-face { + font-family: "Inter-Medium"; + src: url('/luci-static/alpha/fonts/Inter-Medium.woff2'); + } + + @font-face { + font-family: "Inter-Black"; + src: url('/luci-static/alpha/fonts/Inter-Black.woff2'); + } + + @font-face { + font-family: "Inter-Bold"; + src: url('/luci-static/alpha/fonts/Inter-Bold.woff2'); + } + + @font-face { + font-family: "Quicksand-Bold"; + src: url('/luci-static/alpha/fonts/Quicksand-Bold.ttf'); + } + + @font-face { + font-family: argon; + src: url('/luci-static/alpha/fonts/argon.woff'); + + } + + [class^="icon-"], + [class*=" icon-"] { + font-family: argon !important; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + a { + color: #5a8dee; + text-decoration: none; + background-color: transparent; + } + + b { + color: #5a8dee; + text-decoration: none; + background-color: transparent; + font-family: "Quicksand-Bold"; + + } + + ::-webkit-scrollbar:hover { + background-color: rgba(100, 100, 100, 0.09); + } + + ::-webkit-scrollbar-thumb:vertical { + background: rgba(100, 100, 100, 0.5); + -webkit-border-radius: 100px; + } + + ::-webkit-scrollbar-thumb:vertical:active { + background: rgba(100, 100, 100, 0.61); + -webkit-border-radius: 100px; + } + + ::-webkit-scrollbar { + width: 0.2em !important; + overflow: visible; + border-radius: 4px; + -webkit-border-radius: 4px; + } + + ::-webkit-scrollbar-track { + opacity: 0; + -webkit-transition: all 0.5s; + } + + ::-webkit-scrollbar-thumb { + overflow: visible; + border-radius: 4px; + background: rgba(100, 100, 100, 0.2); + } + + .icon-hello-world:before { + content: "\e90e"; + } + + .icon-expand_more:before { + content: "\e20b"; + } + + .icon-menu:before { + content: "\e20e"; + } + + .icon-favorite:before { + content: "\e291"; + } + + .icon-spinner:before { + content: "\e603"; + } + + .icon-delete:before { + content: "\e900"; + } + + .icon-edit:before { + content: "\e901"; + } + + .icon-use:before { + content: "\e902"; + } + + .icon-loading:before { + content: "\e903"; + } + + .icon-switch:before { + content: "\e904"; + } + + .icon-error:before { + content: "\e905"; + } + + .icon-dashboard:before { + content: "\e906"; + } + + .icon-logout:before { + content: "\e907"; + } + + .icon-Network:before { + content: "\e908"; + } + + .icon-services:before { + content: "\e909"; + } + + .icon-system:before { + content: "\e90a"; + } + + .icon-vpn:before { + content: "\e90b"; + } + + .icon-storage:before { + content: "\e90c"; + } + + .icon-statistics:before { + content: "\e90d"; + } + + .icon-angle-right:before { + content: "\e90f"; + } + + .icon-user:before { + content: "\e971"; + } + + .icon-question:before { + content: "\f059"; + } + + :root { + --main-color: #09c; + --header-bg: #161624; + --header-color: rgb(10, 10, 10); + --bar-bg: #3f3f3f69; + --menu-bg-color: #fff; + --menu-color: #5f6368; + --menu-color-hover: #202124; + --main-menu-color: #202124; + --submenu-bg-hover: #4d5ca5; + --submenu-bg-hover-active: #09c; + --font-body: 'Inter-Regular'; + } + + tt { + font-family: "Quicksand-Bold"; + color: #09c; + } + + em { + font-style: italic; + color: #fff + } + + p { + display: block; + margin-block-start: 1em; + margin-block-end: 1em; + margin-inline-start: 0px; + margin-inline-end: 0px; + color: #ffffff; + } + + li { + display: block; + list-style-type: disc; + margin-block-start: 5px; + margin-block-end: 5px; + margin-inline-start: 0px; + margin-inline-end: 0px; + color: #ffffff; + } + + small { + font-size: smaller; + color: #ffff; + } + + label { + cursor: default; + color: #ffffff; + } + + .table { + position: relative; + display: table; + } + + .tr { + display: table-row; + } + + .thead { + display: table-header-group; + } + + .tbody { + display: table-row-group; + } + + .tfoot { + display: table-footer-group; + } + + .td, + .th { + line-height: normal; + display: table-cell; + vertical-align: middle; + padding: 0.5em; + } + + .th { + font-weight: 700; + } + + .tr.placeholder { + height: 4em; + } + + .tr.placeholder>.td { + line-height: 3; + position: absolute; + right: 0; + bottom: 0; + left: 0; + text-align: center !important; + background: inherit; + } + + .table[width="33%"], + .th[width="33%"], + .td[width="33%"] { + width: 33%; + } + + .col-1 { + flex: 1 1 30px !important; + } + + .col-2 { + flex: 2 2 60px !important; + } + + .col-3 { + flex: 3 3 90px !important; + } + + .col-4 { + flex: 4 4 120px !important; + } + + .col-5 { + flex: 5 5 150px !important; + } + + .col-6 { + flex: 6 6 180px !important; + } + + .col-7 { + flex: 7 7 210px !important; + } + + .col-8 { + flex: 8 8 240px !important; + } + + .col-9 { + flex: 9 9 270px !important; + } + + .col-10 { + flex: 10 10 300px !important; + } + + * { + box-sizing: border-box; + padding: 0; + } + + .h1, + .h2, + .h3, + .h4, + .h5, + .h6, + h1, + h2, + h3, + h4, + h5, + h6 { + font-family: inherit; + font-weight: 400; + line-height: 1.1 !important; + color: #fff; + } + + html { + overflow-y: hidden; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + } + + body { + font-size: 0.8rem; + height: 100%; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + background-attachment: fixed; + background-color: rgb(10, 10, 10); + } + + .text { + font-style: italic; + color: #fff; + } + + html, + body { + font-family: var(--font-body); + height: 100%; + margin: 0; + padding: 0; + } + + select { + color: #555; + border: thin solid #ccc; + background-color: #fff; + background-image: none; + padding: 0.36rem 0.8rem; + } + + .btn, + button, + select, + input, + .cbi-dropdown { + height: 2.3rem; + color: rgba(255, 255, 255, 0.87); + border: 0; + border-bottom: 2px solid #30304b; + border-radius: 10px; + border-radius: 20px; + outline: 0; + background-color: #222235; + background-image: none; + box-shadow: none; + padding: 0.5rem; + } + + select, + .cbi-dropdown { + width: inherit; + cursor: default; + } + + select:not([multiple="multiple"]):focus, + input:not(.cbi-button):focus, + .cbi-dropdown:focus { + border-color: var(--main-color); + } + + .cbi-dropdown, + select[multiple="multiple"] { + height: auto; + } + + pre { + overflow: auto; + color: #fff; + } + + code { + font-size: 1rem; + font-size-adjust: 0.35; + color: #101010; + border-radius: 0px; + background: #ddd; + padding: 1px 3px; + } + + abbr { + cursor: help; + text-decoration: underline; + color: #84d0ea; + } + + hr { + opacity: 0.1; + border-color: #eee; + margin: 1rem 0; + } + + /* End Base */ + + /* Header */ + header, + .main { + position: absolute; + width: 100%; + } + + header { + position: fixed; + z-index: 2000; + float: left; + height: 4rem; + transition: box-shadow 0.2s; + color: var(--header-color); + background: #2222359a; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + } + + header>.fill>.container { + margin-top: 0.5rem; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0.5rem 1rem 0; + } + + header>.fill>.container>#logo { + padding: 0; + margin: 0 !important; + position: absolute; + left: 0; + top: 50%; + height: 100%; + transform: translateY(-50%); + padding: 1rem; + display: flex; + justify-content: center; + width: calc(16rem); + } + + header>.fill>.container>#logo>img { + width: auto; + height: 100%; + margin-top: -0.1rem; + } + + header>.fill>.container>.brand { + font-size: 1.4rem; + position: absolute; + cursor: default; + vertical-align: text-bottom; + text-decoration: none; + color: var(--header-color); + } + + header>.fill>.container>.status { + position: fixed; + top: 9px; + right: 1em; + float: right; + } + + header>.fill>.container>.status>* { + position: relative; + top: 0.2rem; + float: left; + left: -2.5rem; + margin-left: 0.3rem; + cursor: pointer; + } + + header>.fill>.container>.logout { + position: fixed; + top: 9px; + right: 1em; + float: right; + } + + header>.fill>.container>.logout>* { + position: relative; + top: 0.2rem; + float: left; + right: 0rem; + margin-left: 0.3rem; + cursor: pointer; + content: ""; + } + + .logout a { + position: absolute; + right: 14px; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/logout.svg) no-repeat; + text-indent: -9999px; + background-size: 32px; + } + + /* End Header */ + + /* Footer */ + footer { + font-size: 0.8rem; + overflow: hidden; + text-align: center; + white-space: nowrap; + color: #000000; + padding: 1rem; + } + + footer>a { + text-decoration: none; + align-items: center; + color: #e6e6e696; + border-bottom: 0; + background-color: #2222359a; + border-radius: 10px; + padding: 9px; + padding-bottom: 3px; + padding-top: 3px; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + } + + small { + font-size: 90%; + line-height: 1.42857143; + white-space: normal; + } + + /* End Footer */ + + /* Navbar */ + @media screen and (min-width: 720px) { + .navbar { + position: fixed; + bottom: 50%; + transform: translateY(50%); + transition-duration: 200ms; + right: 30px; + border-top: var(--navBorder); + text-align: center; + background-color: #000000da; + box-shadow: 0 0 10px 0px #0000002d; + box-sizing: content-box; + border-radius: 10px; + } + + .navbar--hidden { + transform: translateY(60px); + box-shadow: none; + } + + .navbar .toggler { + transition-duration: 100ms; + position: absolute; + background: #ffffffb0; + box-shadow: 0 0 10px 0 #0000000f; + transform: translateY(50%); + bottom: 50%; + right: calc(100% + 10px); + width: 32px; + height: 32px; + padding: 8px; + border-radius: 100%; + content: ""; + box-sizing: border-box; + cursor: pointer; + } + + .navbar .toggler img { + transform: rotate(270deg); + } + + .navbar .dropdown { + display: flex; + flex-direction: column; + overflow: hidden; + width: 64px; + padding: 0.25rem; + } + + .navbar .dropdown a { + display: block; + text-align: center; + padding: 8px; + text-decoration: none; + max-width: 100px; + width: 100%; + } + + .navbar .dropdown a img { + width: 100%; + } + + .navbar.active { + right: -64px; + } + + .navbar.active .toggler { + right: calc(100% + 10px); + } + + .navbar.active .toggler img { + transform: rotate(90deg); + } + } + + @media screen and (max-width: 720px) { + .navbar { + + overflow: hidden; + position: fixed; + bottom: 5px; + top: auto; + left: 10px; + right: auto; + width: 95%; + align: center; + transition: transform 0.5s; + border-top: var(--navBorder); + text-align: center; + height: calc(50px + constant(safe-area-inset-bottom)); + height: calc(50px + env(safe-area-inset-bottom)); + background-color: #00000079; + border-radius: 20px; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + + } + + .navbar--hidden { + transform: translateY(60px); + box-shadow: none; + } + + .navbar a { + float: left; + text-align: center; + padding: 8px 0; + text-decoration: none; + } + + .navbar a img { + width: 28px; + } + } + + /* End Navbar */ + + .main { + position: relative; + top: 4rem; + bottom: 0; + overflow-y: auto; + height: calc(100% - 4rem); + } + + .main>.loading { + position: fixed; + z-index: 1000; + top: 0; + opacity: 1; + visibility: visible; + width: 100%; + height: 100%; + pointer-events: none; + background-color: rgba(0, 0, 0, 0.781); + transition: .4s ease-in-out; + border-radius: 10px; + } + + .main>.loading>span { + font-family: monospace; + font-size: 2rem; + font-size-adjust: 0.35; + position: relative; + top: 12.5%; + display: block; + text-align: center; + color: #888; + } + + .main>.loading>span>.loading-img { + display: inline-flex; + gap: 10px; + } + + .main>.loading>span>.loading-img:before, + .loading-img:after { + content: ""; + height: 20px; + aspect-ratio: 1; + border-radius: 50%; + background: + linear-gradient(#222 0 0) top/100% 0% no-repeat, + radial-gradient(farthest-side, #000 95%, #0000) 50%/8px 8px no-repeat #ffffff; + animation: l9 4s infinite ease-in; + } + + @keyframes l9 { + 0% { + background-size: 100% 0%, 8px 8px; + background-position: top, 50% 50% + } + + 80% { + background-size: 100% 70%, 8px 8px; + background-position: top, 50% 70% + } + + 84%, + 100% { + background-size: 100% 0%, 8px 8px; + background-position: top, 50% 50% + } + } + + .cbi-map { + margin-top: 10px; + } + + #cbi-shadowsocksr .cbi-map-descr { + display: none; + } + + strong { + font-weight: bold; + color: rgb(255, 255, 255); + } + + .main-right { + float: right; + width: calc(100% - 16rem); + height: 100%; + } + + .nowrap:not(.td) { + white-space: nowrap; + color: #ffffff; + } + + [disabled="disabled"] { + pointer-events: none; + } + + /* Sidebar */ + .main>.main-left { + position: fixed; + top: 4.8rem; + width: calc(0% + 16rem); + float: left; + overflow-x: auto; + background-color: #2222359a; + transition: visibility 400ms, width 400ms; + border-top-left-radius: 0px; + border-top-right-radius: 20px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 20px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + height: calc(100% - 3.5rem); + + } + + .main>.main-left>.nav { + padding: 0.5rem 0.5rem 2rem; + } + + .main>.main-left>.nav>li { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .main>.main-left>.nav>li>[data-title="Logout"] { + display: flex; + padding: 0.5rem 1rem; + } + + .main>.main-left>.nav>li a { + display: block; + color: #cbcbcb; + } + + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"] { + font-size: 1rem; + color: #fff; + } + + .main>.main-left>.nav>li.slide.active { + background-color: unset; + } + + .main>.main-left>.nav>.slide { + padding: 0; + } + + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"], + .main>.main-left>.nav>li>[data-title="Dashboard"] { + font-size: 1rem; + font-weight: 500; + display: flex; + align-items: center; + width: 100%; + text-decoration: none; + color: #fff; + padding: 0.5rem 1rem; + transition-duration: 200ms; + margin-bottom: 5px; + } + + .main>.main-left>.nav>.slide>.menu::before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/app.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>.menu.active::before {} + + .main>.main-left>.nav>.slide>[data-title="Status"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/status.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="System"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/system.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Services"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/services.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="NAS"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/nas.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Modem"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/modem.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Network"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/network.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="VPN"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/vpn.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide>[data-title="Docker"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/docker.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>li>[data-title="iStore"]:before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/sidebar-icon/istore.svg) no-repeat; + background-size: 25px; + } + + /* End Sidebar */ + + .modemenu-buttons { + display: flex; + flex-wrap: wrap; + align-items: center; + color: var(--header-color); + background: var(--header-bg); + transition: box-shadow 0.2s; + box-shadow: 0 2px 5px rgb(0 0 0 / 26%); + padding: 0.5rem; + } + + #modemenu { + display: flex; + align-items: center; + flex-wrap: wrap; + margin: 0.25rem; + } + + #modemenu>li.divider { + margin-left: 0.25rem; + margin-right: 0.25rem; + border: 0.5rem solid var(--submenu-bg-hover); + border-left: 1px solid var(--submenu-bg-hover); + border-right: 1px solid var(--submenu-bg-hover); + border-radius: 1rem; + } + + .danger { + background-color: #ff7d60 !important; + } + + .warning { + background-color: #bebebe87 !important; + border-radius: 10px; + color: #fff; + } + + .success { + background-color: #5cb85c !important; + } + + .error { + color: red; + } + + .alert, + .alert-message { + font-weight: 700; + margin-bottom: 1em; + border: 0; + border-radius: 20px; + background-color: #2222359a; + padding: 1rem; + margin: 1rem; + } + + .alert-message>h4 { + font-size: 110%; + font-weight: 700; + } + + .alert-message>* { + margin: 0.5rem 0; + } + + body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { + transition: transform 0.1s ease-in-out; + } + + body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { + transition: transform 0.2s ease-in-out; + } + + .main>.main-left>.nav>li>[data-title="Logout"]::before { + position: absolute; + right: 14px; + width: 25px; + height: 25px; + content: ""; + background: url(./icon/logout.svg) no-repeat; + background-size: 25px; + } + + .main>.main-left>.nav>.slide:hover { + background: none; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a { + white-space: nowrap; + text-decoration: none; + padding: 0.4rem 2rem; + } + + .main>.main-left>.nav>.slide>.slide-menu>li:not(.active):hover>a { + color: #fff; + } + + .main>.main-left>.nav>.slide>.slide-menu>.active:hover { + background-color: var(--main-color); + } + + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>.slide>.slide-menu>li, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"] { + position: relative; + overflow: hidden; + transform: translate3d(0, 0, 0); + } + + .main>.main-left>.nav>.slide>.menu::after, + .main>.main-left>.nav>.slide>.slide-menu>li::after, + .main>.main-left>.nav>li>[data-title="Logout"]::after, + .main>.main-left>.nav>li>[data-title="iStore"]::after { + position: absolute; + top: 0; + left: 0; + display: block; + width: 100%; + height: 100%; + content: ""; + transition: transform 0.5s, opacity 1s; + transform: scale(10, 10); + pointer-events: none; + opacity: 0; + background-image: radial-gradient(circle, #000 10%, transparent 10.01%); + background-repeat: no-repeat; + background-position: 50%; + } + + .main>.main-left>.nav>.slide>.menu:active::after, + .main>.main-left>.nav>.slide>.slide-menu>li:active::after, + .main>.main-left>.nav>li>[data-title="Logout"]:active::after, + .main>.main-left>.nav>li>[data-title="iStore"]:active::after { + transition: 0s; + transform: scale(0, 0); + opacity: 0.2; + } + + #maincontent>.container { + margin: 0 2rem 1rem; + } + + ul { + line-height: normal; + } + + li { + list-style-type: none; + } + + h1 { + font-size: 2rem; + padding-bottom: 10px; + border-bottom: thin solid #eee; + } + + h2 { + font-size: 1.8rem; + font-family: "Quicksand-Bold"; + letter-spacing: 5px; + text-align: center; + padding-bottom: 10px; + margin: 2rem 0 0; + color: #ffffff; + animation-duration: 1s; + animation-name: down; + } + + h3 { + font-size: 1.2rem; + font-family: 'Inter-Bold'; + letter-spacing: 2px; + padding-bottom: 10px; + margin: 2rem 0 0; + color: #ffffff; + } + + h4 { + font-size: 1.2rem; + color: #fff; + padding-bottom: 10px; + margin: 2rem 0 0; + } + + h5 { + font-size: 1rem; + padding-bottom: 10px; + margin: 2rem 0 0; + } + + .cbi-tab-descr { + color: #09c; + margin: 1em; + padding: 1rem; + } + + #tabmenu { + padding: 0; + } + + .cbi-section, + .cbi-section-error, + #iptables, + .Firewall form, + #cbi-network>.cbi-section-node, + #cbi-wireless>.cbi-section-node, + #cbi-wireless>#wifi_assoclist_table, + [data-tab-title], + [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), + [data-page="admin-system-opkg"] #maincontent>.container { + font-family: inherit; + font-weight: 400; + font-style: normal; + line-height: normal; + min-width: inherit; + border: 0; + border-radius: 0; + background-color: #2222359a; + margin: 1rem 0 0; + padding: 2rem; + border-radius: 20px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + } + + .cbi-modal .cbi-section, + .cbi-section .cbi-section {} + + .cbi-modal .cbi-tabmenu { + margin-left: 0; + } + + .cbi-map-descr, + .cbi-section-descr { + font-size: small; + text-align: center; + line-height: 1.42857143; + color: #999; + padding: 0.5rem; + } + + .cbi-section>legend { + display: none !important; + } + + fieldset>fieldset, + .cbi-section>.cbi-section { + border: 0; + box-shadow: none; + margin: 0; + padding: 0; + } + + .cbi-section>h3:first-child, + .panel-title { + font-size: 1.4rem; + line-height: 1; + display: block; + width: 100%; + padding-bottom: 1rem; + color: #e4e4e4; + border-bottom: thin solid #eeeeee00; + margin: 0 0 0.5rem; + } + + .cbi-section>h4:first-child, + .cbi-section>p:first-child, + [data-tab-title]>h3:first-child, + [data-tab-title]>h4:first-child, + [data-tab-title]>p:first-child { + padding-top: 1rem; + } + + table { + border-spacing: 0; + border-collapse: collapse; + } + + table, + .table { + overflow-y: hidden; + width: 100%; + border-radius: 10px; + } + + .container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { + padding: 0.6rem; + } + + .cbi-section-table-cell { + line-height: 1.1; + align-self: flex-end; + flex: 1 1 auto; + } + + tr>td, + tr>th, + .tr>.td, + .tr>.th, + .cbi-section-table-row::before, + #cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { + color: #ffffff; + border-top: thin solid rgba(255, 255, 255, 0); + } + + .table[width="100%"]>.tr:first-child>.td { + margin: auto 0; + } + + .cbi-section-table-row { + margin-bottom: 1rem; + text-align: center !important; + } + + .cbi-section-table-row:last-child { + margin-bottom: 0; + } + + .cbi-section-table-row>.cbi-value-field [data-dynlist]>input, + .cbi-section-table-row>.cbi-value-field input.cbi-input-password { + width: calc(100% - 1.5rem); + } + + table table, + .table .table, + .cbi-value-field table, + .cbi-value-field .table, + td>table>tbody>tr>td, + .td>.table>.tbody>.tr>.td, + .cbi-value-field>table>tbody>tr>td, + .cbi-value-field>.table>.tbody>.tr>.td { + border: 0; + } + + .btn, + .cbi-button, + .item::after { + font-size: 0.8rem; + display: inline-block; + width: auto !important; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all 0.2s ease-in-out; + text-align: center; + vertical-align: middle; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: rgba(0, 0, 0, 0.87); + border: 0; + background-color: #f0f0f0; + background-image: none; + -webkit-appearance: none; + -ms-touch-action: manipulation; + touch-action: manipulation; + padding: 0 0.8rem; + } + + .cbi-button-up { + transform: scaleY(-1); + } + + .cbi-button:not(select) { + -webkit-appearance: none !important; + } + + .cbi-button+.cbi-button { + margin-left: 0.6rem; + } + + .btn:hover, + .btn:focus, + .btn:active, + .cbi-button:hover, + .cbi-button:focus, + .cbi-button:active, + .item:hover::after, + .item:focus::after, + .item:active::after, + .cbi-page-actions .cbi-button-apply+.cbi-button-save:hover, + .cbi-page-actions .cbi-button-apply+.cbi-button-save:focus, + .cbi-page-actions .cbi-button-apply+.cbi-button-save:active { + text-decoration: none; + outline: 0; + } + + .btn:hover, + .btn:focus, + .cbi-button:hover, + .cbi-button:focus, + .item:hover::after, + .item:focus::after { + box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 2px rgba(0, 0, 0, 0.2); + } + + .btn:active, + .cbi-button:active, + .item:active::after { + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); + } + + .cbi-button-up:hover, + .cbi-button-up:focus { + box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 -2px 2px rgba(0, 0, 0, 0.2); + } + + .cbi-button-up:active { + box-shadow: 0 -10px 20px rgba(0, 0, 0, 0.19), 0 -6px 6px rgba(0, 0, 0, 0.23); + } + + .btn:disabled, + .cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: 0.5; + box-shadow: none; + } + + .alert-message [class="btn"], + .modal div[class="btn"], + .cbi-button-find, + .cbi-button-link, + .cbi-button-up, + .cbi-button-down, + .cbi-button-neutral, + .cbi-button[name="zero"], + .cbi-button[name="restart"], + .cbi-button[onclick="hide_empty(this)"] { + font-weight: 700; + background-color: #d4d4d4; + } + + .btn.primary, + .cbi-page-actions .cbi-button-save, + .cbi-page-actions .cbi-button-apply+.cbi-button-save, + .cbi-button-add, + .cbi-button-save, + .cbi-button-positive, + .cbi-button-link, + .cbi-button[value="Enable"], + .cbi-button[value="Scan"], + .cbi-button[value^="Back"], + .cbi-button-neutral[onclick="handleConfig(event)"] { + font-weight: 400; + color: #fff; + background-color: rgba(0, 229, 255, 0.47); + border-radius: 20px; + } + + .cbi-page-actions .cbi-button-apply, + .cbi-section-actions .cbi-button-edit, + .cbi-button-edit, + .cbi-button-apply, + .cbi-button-reload, + .cbi-button-action, + .cbi-button[value="Submit"], + .cbi-button[value="Upload"], + .cbi-button[value$="Apply"], + .cbi-button[onclick="addKey(event)"] { + font-weight: 400; + color: #fff; + background-color: rgba(0, 229, 255, 0.47); + border-radius: 20px; + } + + .btn.danger, + .cbi-section-remove>.cbi-button, + .cbi-button-remove, + .cbi-button-reset, + .cbi-button-negative, + .cbi-button[value="Stop"], + .cbi-button[value="Kill"], + .cbi-button[onclick="reboot(this)"], + .cbi-button-neutral[value="Restart"] { + font-weight: 400; + color: #fff; + background-color: rgba(255, 0, 0, 0.47); + border-radius: 20px; + } + + .btn[value="Dismiss"], + .cbi-button[value="Terminate"], + .cbi-button[value="Reset"], + .cbi-button[value="Disabled"], + .cbi-button[onclick^="iface_reconnect"], + .cbi-button[onclick="handleReset(event)"], + .cbi-button-neutral[value="Disable"] { + font-weight: 400; + color: #fff; + border: thin solid #eea236; + background-color: #f0ad4e; + } + + .cbi-button-success, + .cbi-button-download, + .cbi-button[name="backup"], + .cbi-button[value="Download"], + .cbi-button[value="Save mtdblock"] { + font-weight: 400; + color: #fff; + border: thin solid #4cae4c; + background-color: #5cb85c; + } + + .a-to-btn { + text-decoration: none; + } + + .cbi-value-field .cbi-button-add { + font-weight: 700; + margin: 9px 0 4px 3px; + padding: 1px 6px; + } + + .tabs { + border-bottom: 0; + background-color: #2222359a; + border-radius: 20px; + padding: 9px; + padding-bottom: 3px; + padding-top: 3px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + } + + .tabs>li, + .cbi-tabmenu>li { + display: inline-block; + cursor: pointer; + padding: 0.4rem; + margin: 0.3rem; + align-items: center; + + } + + .tool_label_span { + color: aqua; + } + + .tabs>li { + padding-bottom: 0.4rem; + } + + .tabs>li[class~="active"], + .tabs>li:hover { + border-bottom-color: var(--main-color); + } + + .tabs>li:hover { + cursor: pointer; + border-bottom-color: #c9c9c9; + } + + .tabs>li>a, + .cbi-tabmenu>li>a { + text-decoration: none; + color: #ffffff; + padding: 0.6rem 0.9rem; + + } + + .tabs>li[class~="active"]>a { + color: var(--main-color); + } + + .cbi-tabmenu { + border-bottom: 0; + background-color: #2222359a; + border-radius: 20px; + padding: 9px; + padding-bottom: 3px; + padding-top: 3px; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + } + + .cbi-tabmenu>li:hover { + background-color: #474747; + border-radius: 20px; + + + } + + .cbi-tabmenu>li[class~="cbi-tab"] { + background-color: #ff94946a; + border-radius: 20px; + } + + .cbi-tabmenu>li[class~=data-tab=] { + color: #ffffff; + } + + [data-tab-title] { + overflow: hidden; + height: 0; + opacity: 0; + margin: 0; + padding: 0rem 1rem !important; + } + + [data-tab-active="true"] { + overflow: visible; + height: auto; + opacity: 1; + transition: opacity 0.25s ease-in; + margin: inherit !important; + } + + .cbi-section-node-tabbed { + margin-top: 0; + border-top: 0; + padding: 0; + } + + .cbi-value-field, + .cbi-value-description { + line-height: 1.25; + display: table-cell; + } + + .cbi-value-description { + font-size: small; + padding-top: 0.4rem; + opacity: 0.5; + color: #fff; + } + + .cbi-value-title { + display: table-cell; + float: left; + width: 23rem; + padding-top: 0.35rem; + padding-right: 2rem; + text-align: right; + word-wrap: break-word; + } + + .cbi-value { + display: inline-block; + width: 100%; + padding: 0.35rem 1rem 0.2rem; + } + + .cbi-value ul { + line-height: 1.25; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 25rem; + } + + #cbi-firewall-zone .cbi-input-select, + #cbi-network-switch_vlan .cbi-input-select { + min-width: 11rem; + } + + #cbi-network-switch_vlan .cbi-input-text { + max-width: 3rem; + } + + .cbi-input-invalid { + color: red; + border-bottom-color: red; + } + + .cbi-section-error { + font-weight: 700; + line-height: 1.42857143; + border: thin solid red; + border-radius: 3px; + background-color: #fce6e6; + margin: 18px; + padding: 6px; + } + + .cbi-section-error ul { + margin: 0 0 0 20px; + } + + .cbi-section-error ul li { + font-weight: 700; + color: red; + } + + .td[data-title]::before { + font-weight: 700; + display: none; + content: attr(data-title) ":\20"; + text-align: left; + white-space: nowrap; + padding: 0.25rem 0; + } + + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-weight: 700; + display: table-cell; + align-self: center; + flex: 1 1 5%; + content: attr(data-title) "\20"; + text-align: center; + vertical-align: middle; + white-space: normal; + word-wrap: break-word; + padding: 0.25rem; + } + + .cbi-rowstyle-2 .cbi-button-up, + .cbi-rowstyle-2 .cbi-button-down, + body:not(.Interfaces) .cbi-rowstyle-2:first-child {} + + .cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; + } + + .td.cbi-section-actions { + text-align: right !important; + vertical-align: middle; + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 5px; + } + + .td.cbi-section-actions>* { + display: inline-flex; + } + + .td.cbi-section-actions>button { + display: block; + } + + .td.cbi-section-actions>*>*, + .td.cbi-section-actions>*>form>* { + margin: 0 5px; + } + + .td.cbi-section-actions>*>form { + display: inline-flex; + margin: 0; + } + + .cbi-dynlist { + line-height: 1.3; + flex-direction: column; + min-height: 30px; + cursor: text; + } + + .cbi-dynlist>.item { + position: relative; + max-width: 25rem; + margin-right: 2em; + pointer-events: none; + color: #666; + border-bottom: 2px solid rgba(0, 0, 0, 0.26); + outline: 0; + padding: 0.5em 0.25em 0.25em 0; + } + + .cbi-dynlist[name="sshkeys"]>.item { + max-width: none; + } + + .cbi-dynlist>.item::after { + font-weight: 700; + position: absolute; + right: -2em; + bottom: 0; + display: inline-flex; + min-height: 17px; + content: "\00D7"; + pointer-events: auto; + color: #fff; + border: thin solid #d43f3a; + background-color: #d9534f; + padding: 0 6px; + border-radius: 5px; + } + + .cbi-dynlist>.item>span { + white-space: normal; + word-break: break-word; + } + + .cbi-dynlist>.add-item { + display: inline-flex; + align-items: center; + width: 100%; + min-width: 16rem; + } + + .cbi-dynlist>.add-item:not([ondrop])>input { + overflow: hidden; + width: 100%; + min-width: 15rem; + white-space: nowrap; + text-overflow: ellipsis; + } + + .cbi-dynlist>.add-item[ondrop]>input { + min-width: 13rem; + } + + .cbi-dynlist, + .cbi-dropdown { + position: relative; + display: inline-flex; + padding: 0; + } + + .cbi-dropdown[placeholder*="select"] { + max-width: 25rem; + height: auto; + margin-top: -3px; + } + + .cbi-dropdown>ul { + display: flex; + overflow-x: hidden; + overflow-y: auto; + width: 100%; + list-style: none; + outline: 0; + margin: 0 !important; + padding: 0; + } + + .cbi-dropdown>.open { + flex-basis: 15px; + } + + .cbi-dropdown>.open, + .cbi-dropdown>.more { + font-size: 1rem; + font-weight: 900; + line-height: 2; + display: flex; + flex-direction: column; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + cursor: default; + text-align: center; + outline: 0; + padding: 0 0.25em; + } + + .cbi-dropdown.btn { + min-height: 1.8rem; + padding-top: 0px; + padding-bottom: 0px; + padding-right: 0px; + } + + .cbi-dropdown.btn>.open { + font-size: 0.8rem; + margin: 0 5px; + padding: 0px; + } + + .cbi-dropdown.btn>div { + margin: 0px; + } + + .cbi-dropdown>.more, + .cbi-dropdown>ul>li[placeholder] { + font-weight: 700; + display: none; + color: #777; + } + + .cbi-dropdown>ul>li { + display: none; + overflow: hidden; + align-items: center; + align-self: center; + flex-grow: 1; + flex-shrink: 1; + min-height: 20px; + white-space: nowrap; + text-overflow: ellipsis; + padding: 0.3rem; + } + + .cbi-dropdown>ul>li[display]:not([display="0"]) { + border-left: thin solid #ccc; + } + + .cbi-dropdown[empty]>ul { + max-width: 1px; + } + + .cbi-dropdown>ul>li>form { + display: none; + pointer-events: none; + margin: 0; + padding: 0; + } + + .cbi-dropdown>ul>li img { + margin-right: 0.25em; + vertical-align: middle; + } + + .cbi-dropdown>ul>li>form>input[type="checkbox"] { + height: auto; + margin: 0; + } + + .cbi-dropdown>ul>li input[type="text"] { + height: 20px; + } + + .cbi-dropdown[open]>ul.dropdown { + position: absolute; + z-index: 1100; + display: block; + width: auto; + min-width: 100%; + max-width: none; + max-height: 200px !important; + border: thin solid #918e8c; + background: #787878a8; + box-shadow: 0 0 4px #918e8c; + color: var(--main-menu-color); + } + + .cbi-dropdown>ul>li[display], + .cbi-dropdown[open]>ul.preview, + .cbi-dropdown[open]>ul.dropdown>li, + .cbi-dropdown[multiple]>ul>li>label, + .cbi-dropdown[multiple][open]>ul.dropdown>li, + .cbi-dropdown[multiple][more]>.more, + .cbi-dropdown[multiple][empty]>.more { + display: flex; + align-items: center; + flex-grow: 1; + justify-content: space-around; + } + + .cbi-dropdown[open]>ul.dropdown>li {} + + .cbi-dropdown[open]>ul.dropdown>li[selected] { + background: #b0d0f0; + } + + .cbi-dropdown[open]>ul.dropdown>li.focus { + background: linear-gradient(90deg, #a3c2e8 0%, #84aad9 100%); + } + + .cbi-dropdown[open]>ul.dropdown>li:last-child { + margin-bottom: 0; + } + + .cbi-dropdown[open]>ul.dropdown>li[unselectable] { + opacity: 0.7; + } + + .cbi-dropdown[disabled] { + pointer-events: none; + opacity: 0.6; + } + + .cbi-dropdown[open] .zonebadge { + width: auto; + } + + .cbi-progressbar { + border-radius: 15px; + overflow: hidden; + position: relative; + min-width: 170px; + height: 30px; + background: #11111d61; + margin: 6px 0; + } + + .cbi-progressbar title { + font-family: "Quicksand-Bold"; + letter-spacing: 5px; + text-align: center; + padding-bottom: 10px; + margin: 2rem 0 0; + color: #ffffff; + } + + .cbi-progressbar>div { + width: 0; + height: 100%; + transition: width 2s ease-in; + background: #0099cc; + padding: 0.5rem; + } + + .cbi-progressbar::after { + font-family: monospace; + font-size: 1.2em; + font-weight: 700; + font-size-adjust: 0.38; + line-height: normal; + position: absolute; + top: 50%; + transform: translateY(-50%); + right: 0; + left: 0; + overflow: hidden; + content: attr(title); + text-align: center; + white-space: pre; + text-overflow: ellipsis; + text-shadow: 0 0 2px #eee; + } + + #modal_overlay { + position: fixed; + z-index: 900; + top: 4rem; + right: 10000px; + bottom: 0; + left: -10000px; + overflow-y: scroll; + transition: opacity 0.125s ease-in; + opacity: 0; + background: rgba(0, 0, 0, 0.7); + -webkit-overflow-scrolling: touch; + } + + .modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 90%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + border-radius: 20px !important; + background: #8f8f8f75; + margin: 5em auto; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + padding: 1em; + + } + + .modal>* { + line-height: normal; + flex-basis: 100%; + margin-bottom: 0.5em; + max-width: 100%; + } + + .modal>pre, + .modal>textarea { + font-size: 1rem; + font-size-adjust: 0.35; + overflow: auto; + margin-bottom: 0.5em; + cursor: auto; + white-space: pre-wrap; + color: #eee; + outline: 0; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 8.5px; + } + + .modal>h4 { + margin: 0.5em 0; + } + + .modal ul { + margin-left: 2.2em; + } + + .modal li { + list-style-type: square; + color: rgb(216, 216, 216); + } + + .modal p { + padding-left: 0.25rem; + word-break: break-word; + } + + .modal .label { + font-size: 0.6rem; + font-weight: 400; + cursor: default; + border-radius: 0; + padding: 0.1rem 0.3rem 0; + } + + .modal .label.warning { + background-color: #f0ad4e !important; + } + + .modal.cbi-modal { + max-width: 90%; + max-height: none; + } + + body.modal-overlay-active { + overflow: hidden; + height: 100vh; + } + + body.modal-overlay-active #modal_overlay { + right: 0; + left: 0; + opacity: 1; + } + + .spinning { + position: relative; + padding-left: 32px !important; + color: #fff; + } + + .spinning::before { + position: absolute; + font-size: medium; + font-style: "Quicksand-Bold"; + left: 8px; + width: 20px; + height: 20px; + content: ""; + animation: anim-rotate 2s infinite cubic-bezier(0.18, 0.89, 0.32, 1.28); + background: url(./icon/loading.svg) no-repeat center; + background-size: 20px; + } + } + + .left, + .left::before { + text-align: left !important; + } + + .right, + .right::before { + text-align: right !important; + } + + .top { + align-self: flex-start !important; + vertical-align: top !important; + } + + .bottom { + align-self: flex-end !important; + vertical-align: bottom !important; + } + + .inline { + display: inline; + } + + .cbi-page-actions { + padding-top: 1rem; + text-align: center; + } + + .cbi-page-actions>form[method="post"] { + display: inline-block; + } + + .th[data-type="button"], + .td[data-type="button"], + .th[data-type="fvalue"], + .td[data-type="fvalue"] { + flex: 1 1 2em; + text-align: center; + } + + .ifacebadge { + display: inline-flex; + background: #ffffff33; + padding: 0.5rem 0.8rem; + border-radius: 10px; + } + + td>.ifacebadge, + .td>.ifacebadge { + font-size: 0.8rem; + background-color: #000000; + border-radius: 10px; + } + + .ifacebadge>em, + .ifacebadge>img { + display: inline-block; + align-self: flex-start; + margin: 0 0.2rem; + } + + .ifacebadge>img+img { + margin: 0 0.2rem 0 0; + } + + .network-status-table .ifacebox { + flex-grow: 1; + margin: 0.5em; + } + + .network-status-table .ifacebox-body { + display: flex; + flex-direction: column; + height: 100%; + } + + .network-status-table .ifacebox-body>span { + flex: 10 10 auto; + height: 100%; + } + + .network-status-table .ifacebox-body .ifacebadge { + align-items: center; + flex: 1 1 auto; + min-width: 220px; + background-color: #11111d; + margin: 0.5em 0.25em 0; + padding: 0.5em; + border-radius: 10px; + } + + .cbi-input-textarea { + font-family: monospace; + width: 100%; + min-height: 14rem; + color: #000; + padding: 0.8rem; + } + + #syslog { + font-size: small; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + resize: none; + color: #eee; + border: 0; + border-radius: 20px; + background-color: #10101057; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 1rem; + } + + #syslog:focus { + outline: 0; + } + + .uci-change-list { + font-family: monospace; + } + + .uci-change-list ins, + .uci-change-legend-label ins { + display: block; + text-decoration: none; + border: thin solid #0f0; + background-color: #cfc; + padding: 2px; + } + + .uci-change-list del, + .uci-change-legend-label del { + font-style: normal; + display: block; + text-decoration: none; + border: thin solid red; + background-color: #fcc; + padding: 2px; + } + + .uci-change-list var, + .uci-change-legend-label var { + font-style: normal; + display: block; + text-decoration: none; + border: thin solid #ccc; + background-color: #eee; + padding: 2px; + } + + .uci-change-list var ins, + .uci-change-list var del { + font-style: normal; + white-space: pre; + border: 0; + padding: 0; + } + + .uci-change-legend { + padding: 5px; + } + + .uci-change-legend-label { + float: left; + width: 150px; + color: #fff; + } + + .uci-change-legend-label>ins, + .uci-change-legend-label>del, + .uci-change-legend-label>var { + display: block; + float: left; + width: 10px; + height: 10px; + margin-right: 4px; + } + + .uci-change-legend-label var ins, + .uci-change-legend-label var del { + line-height: 0.4; + border: 0; + } + + #iwsvg, + #iwsvg2, + #bwsvg { + border: thin solid #d4d4d4 !important; + } + + .ifacebox { + line-height: 1.25; + display: inline-flex; + flex-direction: column; + min-width: 100px; + background-color: #54545450; + border-radius: 20px; + flex-wrap: nowrap; + align-content: center; + justify-content: flex-start; + align-items: center; + } + + div.ifacebox-head { + --zone-color-rgb: 144, 240, 144; + background-color: rgb(43, 79, 43); + } + + style attribute { + --zone-color-rgb: 144, 240, 144; + background-color: rgb(43, 79, 43); + } + + .ifacebox-head { + background: #939393; + padding: 0.25em; + color: #fff; + } + + .ifacebox-head.active { + background: var(--bar-bg); + } + + .ifacebox-body { + padding: 0.25em; + } + + .cbi-image-button { + margin-left: 0.5rem; + } + + .zonebadge { + display: inline-block; + padding: 0.2rem 0.5rem; + } + + .zonebadge .ifacebadge { + border: thin solid #6c6c6c; + margin: 0.1rem 0.2rem; + padding: 0.2rem 0.3rem; + } + + .zonebadge>input[type="text"] { + min-width: 10rem; + margin-top: 0.3rem; + padding: 0.16rem 1rem; + } + + .zonebadge>em, + .zonebadge>strong { + display: inline-block; + margin: 0 0.2rem; + } + + .cbi-value-field .cbi-input-checkbox, + .cbi-value-field .cbi-input-radio { + margin-top: 0.1rem; + } + + .cbi-value-field>ul>li .ifacebadge { + margin-top: -0.5rem; + margin-left: 0.4rem; + background-color: #eee; + } + + .cbi-section-table-row>.cbi-value-field .cbi-dropdown { + min-width: 7rem; + } + + .cbi-section-create { + display: inline-flex; + align-items: center; + margin: 0.5rem -3px; + } + + .cbi-section-create>* { + margin: 0.5rem; + } + + div.cbi-value var, + td.cbi-value-field var, + .td.cbi-value-field var { + font-style: italic; + color: #0069d6; + } + + .cbi-optionals { + border-top: thin solid #ccc; + padding: 1rem 1rem 0; + } + + .cbi-dropdown-container { + position: relative; + } + + .cbi-tooltip-container, + span[data-tooltip], + span[data-tooltip] .label { + cursor: help !important; + text-align: left !important; + font-size: 80% !important; + color: #fff !important; + } + + .cbi-tooltip { + position: absolute; + z-index: 1000; + left: -1000px; + transition: opacity 0.25s ease-out; + white-space: pre; + pointer-events: none; + opacity: 0; + border-radius: 20px; + background: #54545450; + box-shadow: 0 0 2px #444; + padding: 2px 5px; + -webkit-backdrop-filter: blur(20px); + backdrop-filter: blur(20px); + + } + + .cbi-tooltip-container:hover .cbi-tooltip { + left: auto; + transition: opacity 0.25s ease-in; + opacity: 1; + } + + .zonebadge .cbi-tooltip { + background: inherit; + margin: -1.5rem 0 0 -0.5rem; + padding: 0.25rem; + } + + .zonebadge-empty { + color: #404040; + background: repeating-linear-gradient(45deg, + rgba(204, 204, 204, 0.5), + rgba(204, 204, 204, 0.5) 5px, + rgba(255, 255, 255, 0.5) 5px, + rgba(255, 255, 255, 0.5) 10px); + } + + .zone-forwards { + display: flex; + min-width: 10rem; + } + + .zone-forwards>* { + flex: 1 1 45%; + } + + .zone-forwards>span { + flex-basis: 10%; + text-align: center; + padding: 0 0.25rem; + } + + .zone-forwards .zone-src, + .zone-forwards .zone-dest { + display: flex; + flex-direction: column; + } + + label>input[type="checkbox"], + label>input[type="radio"] { + position: relative; + top: 0.4rem; + right: 0.2rem; + vertical-align: bottom; + margin: 0; + } + + label[data-index][data-depends] { + padding-right: 2em; + } + + .darkMask { + position: fixed; + z-index: 99; + width: 100%; + height: 100%; + content: ""; + transition: opacity 400ms, visibility 400ms; + visibility: hidden; + opacity: 0; + background-color: #2222359a; + } + + #diag-rc-output>pre, + #command-rc-output>pre, + [data-page="admin-services-wol"] .notice code { + font-size: 1.2rem; + font-size-adjust: 0.35; + line-height: normal; + display: block; + overflow-y: hidden; + width: 100%; + white-space: pre; + color: #eee; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 8.5px; + } + + input[name="ping"], + input[name="traceroute"], + input[name="nslookup"] { + width: 80%; + } + + .node-main-login>.main fieldset { + display: inline; + overflow: hidden; + margin-bottom: 1rem; + border: 0; + background: none; + box-shadow: none; + padding: 0.5rem; + } + + .node-main-login>.main .cbi-value-title { + width: 9.5rem; + } + + .node-main-login>.main #maincontent { + text-align: center; + } + + .node-main-login>.main .container { + display: inline-block; + margin-top: 2rem !important; + text-align: left; + background-color: #2e2b2b00; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + padding: 1rem 3.5rem 2rem; + } + + .node-main-login>.main .cbi-value>* { + display: inline-block !important; + } + + .node-main-login>.main .cbi-input-text { + width: 100% !important; + min-width: 15rem; + } + + .node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2), + .node-status-processes>.main .table .tr .td:nth-child(3) { + white-space: normal; + } + + [data-page="admin-system-reboot"] p { + padding-left: 2rem; + } + + [data-page="admin-system-reboot"] p>span { + position: relative; + top: 0.1rem; + left: 1rem; + } + + #cbi-samba [data-tab="template"] .cbi-value-title { + width: auto; + padding-bottom: 0.6rem; + } + + .controls>*>.btn:not([aria-label$="page"]) { + flex-grow: initial !important; + margin-top: 0.1rem; + } + + .controls>#pager>.btn[aria-label$="page"] { + font-size: 1.4rem; + font-weight: 700; + } + + .controls>*>label { + margin-bottom: 0.2rem; + } + + [data-page="admin-system-opkg"] div.btn { + display: inline; + padding: 0.3rem 0.6rem; + } + + [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), + [data-page="admin-system-opkg"] #maincontent>.container { + margin-top: 2rem; + padding-top: 0.1rem; + } + + [data-page="admin-system-opkg"] #maincontent>.container { + margin: 2rem 2rem 1rem; + } + + .td.version, + .td.size { + white-space: normal !important; + word-break: break-word; + } + + .cbi-tabmenu+.cbi-section { + margin-top: 0; + } + + #cbi-wireless>#wifi_assoclist_table>.tr { + box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; + } + + #cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { + right: 33px; + bottom: 33px; + left: 33px; + border-top: thin solid #ddd !important; + } + + #cbi-wireless>#wifi_assoclist_table>.tr.table-titles { + box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; + } + + #cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { + border-bottom: thin solid #ddd; + box-shadow: 0 -1px 0 0 #ddd; + } + + #wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { + width: 23rem; + } + + #iptables { + margin: 0; + } + + .Firewall form { + box-shadow: none; + margin: 2rem 2rem 0 0; + padding: 0; + } + + #cbi-firewall-redirect table *, + #cbi-network-switch_vlan table *, + #cbi-firewall-zone table * { + font-size: small; + } + + #cbi-firewall-redirect table input[type="text"], + #cbi-network-switch_vlan table input[type="text"], + #cbi-firewall-zone table input[type="text"] { + width: 5rem; + } + + #cbi-firewall-redirect table select, + #cbi-network-switch_vlan table select, + #cbi-firewall-zone table select { + min-width: 3.5rem; + } + + #cbi-network-switch_vlan .th, + #cbi-network-switch_vlan .td { + flex-basis: 12%; + } + + #applyreboot-container { + margin: 2rem; + } + + #applyreboot-section { + line-height: 300%; + margin: 2rem; + } + + .OpenVPN a { + line-height: initial !important; + } + + .commandbox { + width: 24% !important; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), + 0 1px 2px rgba(0, 0, 0, 0.05); + margin: 10px 0 0 10px !important; + padding: 0.5rem 1rem; + } + + .commandbox h3 { + line-height: normal !important; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin: 6px 0 !important; + } + + .commandbox div { + left: auto !important; + } + + .commandbox code { + position: absolute; + overflow: hidden; + max-width: 60%; + margin-left: 4px; + white-space: nowrap; + text-overflow: ellipsis; + padding: 2px 3px; + } + + .commandbox code:hover { + overflow-y: auto; + max-height: 50px; + white-space: normal; + } + + .commandbox p:first-of-type { + margin-top: -6px; + } + + .commandbox p:nth-of-type(2) { + margin-top: 2px; + } + + #command-rc-output .alert-message { + line-height: 1.42857143; + position: absolute; + top: 40px; + right: 32px; + max-width: 40%; + animation: anim-fade-in 1.5s forwards; + word-break: break-word; + opacity: 0; + margin: 0; + } + + .table[width="100%"], + .th[width="100%"], + .td[width="100%"], + .cbi-section-table-row>.cbi-value-field .cbi-dropdown, + .cbi-section-table-row>.cbi-value-field .cbi-input-select, + .cbi-section-table-row>.cbi-value-field .cbi-input-text, + .cbi-section-table-row>.cbi-value-field .cbi-input-password, + .cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child, + .cbi-dropdown .zonebadge, + .node-main-login>.main>.main-right, + #cbi-firewall-zone .td, + #cbi-network-switch_vlan .td { + width: 100%; + min-width: 60px; + } + + .cbi-rowstyle-2 { + background-color: ; + } + + .pull-right, + .node-main-login>.main form>div:last-child { + float: right; + } + + .pull-left, + .cbi-page-actions .cbi-button-link:first-child { + float: left; + } + + #modemenu>li>a, + .label { + background-color: rgb(104, 104, 104); + color: #fff !important; + font-size: 0.8rem; + font-weight: 700; + text-decoration: none; + text-shadow: none; + text-transform: uppercase; + white-space: nowrap; + padding: 0.3rem 0.8rem; + border-radius: 10px; + } + + [data-indicator="poll-status"][data-style="active"] { + position: absolute; + right: 14px; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/loading.svg) no-repeat; + text-indent: -9999px; + animation: anim-rotate 5s infinite ease-in-out; + background-size: 32px; + } + + [data-indicator="poll-status"][data-style="inactive"] { + position: absolute; + right: 14px; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/pause.svg) no-repeat; + text-indent: -9999px; + background-size: 32px; + } + + + [data-indicator="uci-changes"][data-style="active"] { + position: absolute; + width: 32px; + height: 32px; + content: ""; + background: url(./icon/save.svg) no-repeat; + text-indent: -9999px; + background-size: 32px; + } + + #modemenu>li>a.active, + .notice { + background-color: rgb(66, 66, 66) !important; + } + + #xhr_poll_status, + .cbi-value-field>ul>li { + display: flex; + } + + .alert-message .btn, + .modal .btn { + padding: 0.3rem 0.6rem; + } + + .container .alert, + .container .alert-message, + .cbi-map-descr+fieldset { + margin-top: 1rem; + } + + .main>.main-left>.nav, + .cbi-value-field>ul>li>label { + margin-top: 0.5rem; + } + + .main>.main-left>.nav>li.active>a, + .main>.main-left>.nav>.slide>.slide-menu>.active>a { + color: #fff; + } + + .main>.main-left>.nav>li.active, + .main>.main-left>.nav>.slide>.slide-menu>.active { + + background-color: var(--submenu-bg-hover-active); + border-radius: 10px; + } + + .main>.main-left>.nav>.slide>ul, + .main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before, + .tr.placeholder .td[data-title]::before, + .cbi-dropdown>ul.preview, + .cbi-dropdown>ul>li .hide-close, + .cbi-dropdown[open]>ul.dropdown>li .hide-open, + .hidden, + .showSide, + .node-main-login>.main>.main-left, + [data-page^="admin-system-commands"] .panel-title, + [data-page^="command-cfg"] .mobile-hide, + [data-page^="command-cfg"] .showSide { + display: none; + } + + .main>.main-left>.nav>.slide.active>ul, + .cbi-dropdown[empty]>ul>li, + .cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], + .cbi-dropdown[multiple][open]>ul.dropdown>li>form, + .node-main-login>.main .cbi-value, + #cbi-samba [data-tab="template"] .cbi-value-field, + #cbi-firewall-zone .table, + #cbi-network-switch_vlan .table { + display: block; + } + + .main>.main-left>.nav>li:hover, + .main>.main-left>.nav>.slide>.menu:hover, + .main>.main-left>.nav>.slide>.slide-menu>li:hover { + background: var(--submenu-bg-hover); + border-radius: 10px; + } + + table>tbody>tr>td, + table>tbody>tr>th, + table>tfoot>tr>td, + table>tfoot>tr>th, + table>thead>tr>td, + table>thead>tr>th, + .table>.tbody>.tr>.td, + .table>.tbody>.tr>.th, + .table>.tfoot>.tr>.td, + .table>.tfoot>.tr>.th, + .table>.thead>.tr>.td, + .table>.thead>.tr>.th, + .table>.tr>.td.cbi-value-field, + .table>.tr>.th.cbi-section-table-cell, + .uci-change-list var, + .uci-change-list del, + .uci-change-list ins, + .cbi-section-remove { + padding: 0.5rem; + } + + #cbi-wireless .td, + #cbi-network .tr:first-child>.td, + .table[width="100%"]>.tr:first-child>.td, + [data-page="admin-network-diagnostics"] .tr>.td, + .tr.table-titles>.th, + .tr.cbi-section-table-titles>.th, + #iwsvg, + [data-page="admin-status-realtime-bandwidth"] #bwsvg { + border-top: 0 !important; + } + + .cbi-section-table-row .td, + .center, + .center::before { + text-align: center !important; + } + + div>table>tbody>tr:nth-of-type(2n), + div>.table>.tr:nth-of-type(2n), + .cbi-section .cbi-section-remove:nth-of-type(2n), + .container>.cbi-section .cbi-section-node:nth-of-type(2n), + .cbi-section[id] .cbi-section-remove:nth-of-type(4n + 3), + .cbi-section[id] .cbi-section-node:nth-of-type(4n + 4), + .cbi-tabcontainer>.cbi-value:nth-of-type(2n), + .cbi-rowstyle-1 {} + + .cbi-dropdown>ul>li .hide-open, + .cbi-dropdown[open]>ul.dropdown>li .hide-close { + display: initial; + } + + .network-status-table, + .network-status-table .ifacebox-body>div { + display: flex; + flex-wrap: wrap; + } + + [data-page="admin-network-diagnostics"] .table, + .node-main-login .cbi-section { + box-shadow: none; + } + + @keyframes down { + from { + margin-left: 50%; + opacity: 0; + } + + to { + margin-left: 0%; + opacity: 1; + } + } + + @keyframes anim-rotate { + 0% { + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + @media screen and (min-height: 585px) { + .node-main-login footer { + position: absolute; + bottom: 0; + width: 100%; + } + } + + @keyframes anim-fade-in { + 100% { + opacity: 1; + } + } + + @media all and (-ms-high-contrast: none) { + .main>.main-left>.nav>.slide>.menu::before { + top: 30.25%; + } + + .main>.main-left>.nav>li:last-child::before { + top: 20%; + } + + .showSide::before { + top: -12px; + } + } + + @media screen and (max-width: 1600px) { + header>.fill>.container { + display: flex; + align-items: center; + margin-top: 0; + } + + header>.fill>.container>#logo { + width: calc(13rem); + } + + .main>.main-left { + width: calc(0% + 13rem); + } + + .main>.main-right { + width: calc(100% - 13rem); + } + + .btn:not(button), + .cbi-button { + font-size: 0.8rem; + padding: 0.3rem 0.6rem; + position: relative; + /*bottom: -0.5rem;*/ + } + + .label, + [data-indicator] { + padding: 0.2rem 0.6rem; + } + + fieldset, + .cbi-section { + padding: 1rem; + } + + .cbi-value-title { + width: 15rem; + padding-right: 0.6rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 22rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 9rem; + } + + .cbi-input-textarea { + font-size: small; + } + + .node-admin-status>.main fieldset li>a { + padding: 0.3rem 0.6rem; + } + } + + @media screen and (max-width: 2000000000px) { + header { + height: 3.5rem; + } + + header>.fill>.container { + margin-top: 0.25rem; + cursor: default; + padding: 0.5rem 1rem; + } + + .main { + top: 3.5rem; + height: calc(100% - 3.5rem); + } + + .main>.main-left { + top: 4.3rem; + width: calc(0% + 13rem); + height: calc(100% - 3.5rem); + } + + .main>.main-right { + width: calc(100% - 13rem); + } + + .tabs>li>a, + .cbi-tabmenu>li>a { + padding: 0.2rem 0.5rem; + } + + .cbi-section>h3:first-child, + .panel-title { + font-size: 1.1rem; + padding-bottom: 1rem; + } + + table { + font-size: 0.7rem !important; + width: 100% !important; + } + + .table .cbi-input-text { + width: 100%; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 19rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 4rem; + } + + .main>.main-left>.nav>li, + .main>.main-left>.nav>li a, + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"] { + font-size: 1rem; + color: #fff; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a { + font-size: 0.7rem; + color: #fff; + } + + #modal_overlay { + top: 3.5rem; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { + display: block; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), + [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), + [data-page="admin-network-hosts"] .table, + [data-page="admin-network-routes"] .table { + overflow-y: visible; + } + + .commandbox { + width: 32% !important; + } + } + + @media screen and (max-width: 1152px) { + header>.fill>.container>.brand { + position: relative; + } + + html, + .main { + overflow-y: visible; + } + + .main>.loading>span { + top: 25%; + } + + .main>.main-left { + position: fixed; + z-index: 100; + visibility: hidden; + } + + .main>.main-right { + width: 100%; + } + + .showSide { + position: -webkit-sticky; + position: sticky; + top: 0rem; + display: inline-flex; + align-items: center; + height: 100%; + margin-right: 0.7rem; + cursor: pointer; + } + + body:not(.logged-in) .showSide { + visibility: hidden; + width: 0; + margin: 0; + } + + .cbi-value-title { + width: 12rem; + padding-right: 1rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"] { + width: 16rem; + min-width: 16rem; + color: rgb(255, 255, 255); + } + + .cbi-value input[type="password"], + .cbi-value input[name^="pw"], + .cbi-value input[data-update="change"]:nth-child(2) { + width: 13rem !important; + min-width: 13rem; + color: #fff; + } + + #diag-rc-output>pre, + #command-rc-output>pre, + [data-page="admin-services-wol"] .notice code { + font-size: 1rem; + } + + .Interfaces .table { + overflow-x: hidden; + } + + #packages.table { + display: grid; + } + + .tr { + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + + .Overview .table[width="100%"]>.tr { + flex-wrap: nowrap; + } + + .tr.placeholder { + border-bottom: thin solid #ddd; + } + + .tr.placeholder>.td, + #cbi-firewall .tr>.td, + #cbi-network .tr:nth-child(2)>.td, + .cbi-section #wifi_assoclist_table .tr>.td { + border-top: 0; + } + + .th, + .td { + display: inline-block; + align-self: flex-start; + flex: 2 2 25%; + text-overflow: ellipsis; + word-wrap: break-word; + } + + .td select, + .td input[type="text"] { + width: 100%; + word-wrap: normal; + } + + .td [data-dynlist]>input, + .td input.cbi-input-password { + width: calc(100% - 1.5rem); + } + + .td[data-type="button"], + .td[data-type="fvalue"] { + flex: 1 1 12.5%; + text-align: left; + } + + .th.cbi-value-field, + .td.cbi-value-field, + .th.cbi-section-table-cell, + .td.cbi-section-table-cell { + flex-basis: auto; + padding-top: 1rem; + } + + .cbi-section-table-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + } + + .td.cbi-value-field, + .cbi-section-table-cell { + display: inline-block; + flex: 10 10 auto; + flex-basis: 50%; + text-align: center; + } + + .td.cbi-section-actions { + vertical-align: bottom; + } + + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-size: 0.9rem; + display: block; + flex: 1 1 100%; + border-bottom: thin solid rgba(0, 0, 0, 0.26); + background: #90c0e0; + } + + .cbi-button+.cbi-button { + margin-left: 0; + } + + .td.cbi-section-actions>*>*, + .td.cbi-section-actions>*>form>* { + margin: 2.1px 3px; + } + + .Firewall form { + position: static !important; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + margin: 0 0 2rem; + padding: 2rem; + } + + .Firewall form input { + width: 100% !important; + margin: 1rem 0 0; + } + + .Firewall .center, + .Firewall .center::before { + text-align: left !important; + } + + .commandbox { + width: 100% !important; + margin-left: 0 !important; + } + + .tr.table-titles, + .tr.cbi-section-table-titles, + .tr.cbi-section-table-descr { + display: none; + } + + .node-main-login>.main .cbi-value-title, + .td[data-title], + [data-page^="admin-status-realtime"] .td[id] { + text-align: left; + color: #ffffff; + } + + .table, + .td[data-title]::before { + display: block; + } + } + + @media screen and (max-width: 600px) { + header>.fill>.container>#logo { + padding: 1rem; + margin: 0; + position: absolute; + left: 50%; + top: 0; + width: 100px; + transform: translateX(-50%); + } + + header>.fill>.container>#logo>img { + width: 100%; + margin-top: 0; + } + + .cbi-progressbar::after { + font-size: 0.95em; + line-height: 1.5; + } + + fieldset, + .cbi-section { + margin: 1rem 0 0; + } + + } + + #maincontent>.container { + margin: 0 0.5rem 1.5rem; + } + + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>li>[data-title="Logout"], + .main>.main-left>.nav>li>[data-title="iStore"] { + font-size: 1.1rem; + } + + .cbi-value-title { + display: block; + min-width: 0 !important; + text-align: left; + margin: 0.5rem 0; + } + + .cbi-value>.cbi-value-field { + display: inline-block; + } + + .tabs>li>a, + .cbi-tabmenu>li>a { + padding: 0.2rem 0.3rem; + } + + .cbi-page-actions>.cbi-button { + margin-top: 0.2rem; + } + + .node-main-login>.main .container { + margin: 2rem 1.2rem 1.5rem !important; + padding: 0.3rem 1.7rem 2rem 1.6rem; + } + + .node-main-login>.main .cbi-value { + padding: 0; + } + + .node-main-login>.main form>div:last-child { + margin-top: 2rem; + } + + .node-main-login>.main .cbi-value-title { + font-size: 1.2rem; + width: 100% !important; + } + + .node-main-login>.main fieldset { + margin: 0; + padding: 0.5rem; + } + + .commandbox p:first-of-type { + margin-top: -8px; + } + + #syslog, + #diag-rc-output>pre, + #command-rc-output>pre, + [data-page="admin-services-wol"] .notice code { + font-size: 0.8rem !important; + } + + h2 {} + + .cbi-section>h3:first-child, + .panel-title { + font-size: 1.2rem; + padding-bottom: 1rem; + } + + .node-system-packages>.main .cbi-value.cbi-value-last>div { + width: 100% !important; + } + + .th, + .td { + flex-basis: 50%; + color: #fff; + } + + .tr>.td[data-title="Sensor"] { + text-align: center; + } + + .tr>.td[data-title="Temperature"] { + text-align: center; + } + + .tr>.td[data-title="Hostname"] { + text-align: center; + } + + .tr>.td[data-title="IPv4 address"] { + text-align: center; + } + + .tr>.td[data-title="MAC address"] { + text-align: center; + } + + .tr>.td[data-title="Lease time remaining"] { + text-align: center; + } + + + .td.cbi-value-field { + flex-basis: 100%; + } + + .td.cbi-value-field[data-type="button"], + .td.cbi-value-field[data-type="fvalue"] { + flex-basis: 25%; + text-align: left; + } + + td>.ifacebadge, + .td>.ifacebadge { + font-size: 0.62rem; + } + + #cbi-wireless>#wifi_assoclist_table .td { + overflow: hidden; + } + + #cbi-wireless>.cbi-section-node .td, + .Interfaces .td.cbi-section-actions { + text-align: center !important; + } + + .cbi-modal { + padding: 0.5rem; + } + + .cbi-modal .cbi-value { + padding: 0 0 0.25rem; + } + + .cbi-modal [data-tab-title] { + padding: 0 0.25rem !important; + } + + [data-tab-title] { + padding: 0 0.5rem !important; + } + + body, + code { + font-size: 0.8rem; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a, + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-size: + } + + .cbi-value-title, + .cbi-value-description, + .cbi-value-field, + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .node-system-packages>.main .cbi-value .cbi-value-field input { + width: 30%; + color: #fff; + } + + .cbi-page-actions>div>input, + .mobile-hide, + [data-page="admin-status-processes"] .td[data-title="Hang Up"]::before, + [data-page="admin-status-processes"] .td[data-title="Terminate"]::before, + [data-page="admin-status-processes"] .td[data-title="Kill"]::before, + .hide-sm, + .hide-xs:not([data-title="MAC-Address"]) { + display: none; + } + + .tabs>li>a, + select, + input { + font-size: 0.9rem; + } + + @media screen and (min-width: 600px) { + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + ::-webkit-scrollbar, + ::-webkit-scrollbar-corner { + background: transparent; + } + + ::-webkit-scrollbar-thumb { + background: #9e9e9e; + } + + ::-webkit-scrollbar-thumb:hover { + background: #757575; + } + + ::-webkit-scrollbar-thumb:active { + background: #424242; + } + } diff --git a/luci-theme-alpha/luasrc/gaya/icon/arrow.svg b/luci-theme-alpha/luasrc/gaya/icon/arrow.svg new file mode 100644 index 000000000..be864c5ac --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-theme-alpha/luasrc/gaya/icon/loading.svg b/luci-theme-alpha/luasrc/gaya/icon/loading.svg new file mode 100644 index 000000000..0112b31a4 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/loading.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/logout.svg b/luci-theme-alpha/luasrc/gaya/icon/logout.svg new file mode 100644 index 000000000..78c0fe42b --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/logout.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/menu_icon.svg b/luci-theme-alpha/luasrc/gaya/icon/menu_icon.svg new file mode 100644 index 000000000..1833cee96 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/menu_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-theme-alpha/luasrc/gaya/icon/navbar/interface.png b/luci-theme-alpha/luasrc/gaya/icon/navbar/interface.png new file mode 100644 index 0000000000000000000000000000000000000000..d5888cca97b149d4b8e676d8df83e71c3d183f63 GIT binary patch literal 21524 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 ZJiOYALLG-Ha7Pp5hMtLT>2*88{{TXL(R%;@ literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/gaya/icon/navbar/modem.png b/luci-theme-alpha/luasrc/gaya/icon/navbar/modem.png new file mode 100644 index 0000000000000000000000000000000000000000..aa2d96a61913e71f9ac71d8a273d299aadfd88a5 GIT binary patch literal 8995 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 TpID(jSpcevS_+kNkl_CVaB!)k literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/gaya/icon/navbar/nas.png b/luci-theme-alpha/luasrc/gaya/icon/navbar/nas.png new file mode 100644 index 0000000000000000000000000000000000000000..de168033e83d4675efa11e7f11cb87372ead5190 GIT binary patch literal 14997 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 Lm8EJVjD!CRf6Xi@@54ZTQ_E-Enz5K6$1 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 DzmdS{ literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/gaya/icon/navbar/oc.png b/luci-theme-alpha/luasrc/gaya/icon/navbar/oc.png new file mode 100644 index 0000000000000000000000000000000000000000..7a7ded8b8d9f73537a541ab1a9eebb4c04f99128 GIT binary patch literal 17668 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 a{6~GJ`}BPKgkvoXK;Y@>=d#Wzp$PzP$eP3e literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/gaya/icon/navbar/status.png b/luci-theme-alpha/luasrc/gaya/icon/navbar/status.png new file mode 100644 index 0000000000000000000000000000000000000000..1da03903e340aa8f9704c4affe9ecc7a357d4f03 GIT binary patch literal 14160 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 V{;t=6{;U9ylTwzfmM{tW-vAthcu)WU literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/gaya/icon/pause.svg b/luci-theme-alpha/luasrc/gaya/icon/pause.svg new file mode 100644 index 000000000..862a712db --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/pause.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/save.svg b/luci-theme-alpha/luasrc/gaya/icon/save.svg new file mode 100644 index 000000000..690905dbd --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/save.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/app.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/app.svg new file mode 100644 index 000000000..366ace333 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/app.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/docker.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/docker.svg new file mode 100644 index 000000000..c28d199d9 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/docker.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/istore.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/istore.svg new file mode 100644 index 000000000..289c42094 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/istore.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/modem.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/modem.svg new file mode 100644 index 000000000..c270cbfe3 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/modem.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/nas.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/nas.svg new file mode 100644 index 000000000..273fadb71 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/nas.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/network.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/network.svg new file mode 100644 index 000000000..5131c1704 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/network.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/services.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/services.svg new file mode 100644 index 000000000..5280c990c --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/services.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/status.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/status.svg new file mode 100644 index 000000000..f1e3c2c8f --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/status.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/system.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/system.svg new file mode 100644 index 000000000..ba932d479 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/system.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/vpn.svg b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/vpn.svg new file mode 100644 index 000000000..0f48cba43 --- /dev/null +++ b/luci-theme-alpha/luasrc/gaya/icon/sidebar-icon/vpn.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/luci-theme-alpha/luasrc/style/brand.png b/luci-theme-alpha/luasrc/style/brand.png new file mode 100644 index 0000000000000000000000000000000000000000..243457d8c4dd49acddf1f413dd4f448cb200efc6 GIT binary patch literal 103596 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 YQEHyUwUxLnlK)y&NlOu-U={j*0Dj8l2LJ#7 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/style/catatan.txt b/luci-theme-alpha/luasrc/style/catatan.txt new file mode 100644 index 000000000..c74e132ee --- /dev/null +++ b/luci-theme-alpha/luasrc/style/catatan.txt @@ -0,0 +1 @@ +buat tambah login page disini diff --git a/luci-theme-alpha/luasrc/style/indo-wrt.png b/luci-theme-alpha/luasrc/style/indo-wrt.png new file mode 100644 index 0000000000000000000000000000000000000000..fde99ef1743367309fcb7145db8463d275825fce GIT binary patch literal 11475 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 literal 0 HcmV?d00001 diff --git a/luci-theme-alpha/luasrc/style/style.css b/luci-theme-alpha/luasrc/style/style.css new file mode 100644 index 000000000..a162c1051 --- /dev/null +++ b/luci-theme-alpha/luasrc/style/style.css @@ -0,0 +1,416 @@ +/*-------------------- +catatan usahakan untuk mengganti bg pakai format png, kalo jpg ganti aja di bagian body, sesuaikan aja nama formatnya +---------------------*/ +*, +*::before, +*::after { + box-sizing: border-box; +} + +body, +html { + height: 100%; + font-family: 'Segoe UI', Arial, Helvetica, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + height: 100%; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + background-attachment: fixed; +} + + +/*-------------------- +Text +---------------------*/ + +h2, +h3 { + font-size: 16px; + letter-spacing: -1px; + line-height: 20px; +} + +h2 { + color: #fff; + text-align: center; +} + +h3 { + color: #032942; + text-align: right; +} + +/*-------------------- +Icons +---------------------*/ +.i { + width: 20px; + height: 20px; +} + +.i-login { + margin: 13px 0px 0px 15px; + position: relative; + float: left; + background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDQxNi4yMjkgNDE2LjIyOSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDE2LjIyOSA0MTYuMjI5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnPgoJPGc+CgkJPHBhdGggZD0iTTQwMy43MjksMjkuNjVINzEuODAyYy02LjkwMywwLTEyLjUsNS41OTctMTIuNSwxMi41djg2LjM2M2MwLDYuOTAzLDUuNTk3LDEyLjUsMTIuNSwxMi41czEyLjUtNS41OTcsMTIuNS0xMi41VjU0LjY1ICAgIGgzMDYuOTI3djMwNi45MjhIODQuMzAydi03My44NjFjMC02LjkwMy01LjU5Ny0xMi41LTEyLjUtMTIuNXMtMTIuNSw1LjU5Ny0xMi41LDEyLjV2ODYuMzYxYzAsNi45MDMsNS41OTcsMTIuNSwxMi41LDEyLjUgICAgaDMzMS45MjdjNi45MDIsMCwxMi41LTUuNTk3LDEyLjUtMTIuNVY0Mi4xNUM0MTYuMjI5LDM1LjI0Nyw0MTAuNjMxLDI5LjY1LDQwMy43MjksMjkuNjV6IiBmaWxsPSIjODczMTRlIi8+CgkJPHBhdGggZD0iTTE4NS40MTcsMjg3LjgxMWMwLDUuMDU3LDMuMDQ1LDkuNjEzLDcuNzE2LDExLjU1YzEuNTQ3LDAuNjQyLDMuMTcsMC45NSw0Ljc4MSwwLjk1YzMuMjUzLDAsNi40NTEtMS4yNyw4Ljg0Mi0zLjY2ICAgIGw3OS42OTctNzkuNjk3YzIuMzQ0LTIuMzQ0LDMuNjYtNS41MjMsMy42Ni04LjgzOWMwLTMuMzE2LTEuMzE2LTYuNDk1LTMuNjYtOC44MzlsLTc5LjY5Ny03OS42OTcgICAgYy0zLjU3NS0zLjU3NS04Ljk1MS00LjY0Ni0xMy42MjMtMi43MWMtNC42NzEsMS45MzYtNy43MTYsNi40OTMtNy43MTYsMTEuNTQ5djY3LjE5N0gxMi41Yy02LjkwMywwLTEyLjUsNS41OTctMTIuNSwxMi41ICAgIGMwLDYuOTAzLDUuNTk3LDEyLjUsMTIuNSwxMi41aDE3Mi45MTdWMjg3LjgxMUwxODUuNDE3LDI4Ny44MTF6IE0yMTAuNDE3LDE1OC41OTRsNDkuNTIxLDQ5LjUybC00OS41MjEsNDkuNTIxVjE1OC41OTR6IiBmaWxsPSIjODczMTRlIi8+Cgk8L2c+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+Cg==); + background-size: 18px 18px; + background-repeat: no-repeat; + background-position: center; +} + +.i-more { + background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDYxMiA2MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDYxMiA2MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGc+Cgk8ZyBpZD0ibW9yZSI+CgkJPGc+CgkJCTxwYXRoIGQ9Ik03Ni41LDIyOS41QzM0LjMsMjI5LjUsMCwyNjMuOCwwLDMwNnMzNC4zLDc2LjUsNzYuNSw3Ni41UzE1MywzNDguMiwxNTMsMzA2UzExOC43LDIyOS41LDc2LjUsMjI5LjV6IE03Ni41LDM0NC4yICAgICBjLTIxLjEsMC0zOC4yLTE3LjEwMS0zOC4yLTM4LjJjMC0yMS4xLDE3LjEtMzguMiwzOC4yLTM4LjJzMzguMiwxNy4xLDM4LjIsMzguMkMxMTQuNywzMjcuMSw5Ny42LDM0NC4yLDc2LjUsMzQ0LjJ6ICAgICAgTTUzNS41LDIyOS41Yy00Mi4yLDAtNzYuNSwzNC4zLTc2LjUsNzYuNXMzNC4zLDc2LjUsNzYuNSw3Ni41UzYxMiwzNDguMiw2MTIsMzA2UzU3Ny43LDIyOS41LDUzNS41LDIyOS41eiBNNTM1LjUsMzQ0LjIgICAgIGMtMjEuMSwwLTM4LjItMTcuMTAxLTM4LjItMzguMmMwLTIxLjEsMTcuMTAxLTM4LjIsMzguMi0zOC4yczM4LjIsMTcuMSwzOC4yLDM4LjJDNTczLjcsMzI3LjEsNTU2LjYsMzQ0LjIsNTM1LjUsMzQ0LjJ6ICAgICAgTTMwNiwyMjkuNWMtNDIuMiwwLTc2LjUsMzQuMy03Ni41LDc2LjVzMzQuMyw3Ni41LDc2LjUsNzYuNXM3Ni41LTM0LjMsNzYuNS03Ni41UzM0OC4yLDIyOS41LDMwNiwyMjkuNXogTTMwNiwzNDQuMiAgICAgYy0yMS4xLDAtMzguMi0xNy4xMDEtMzguMi0zOC4yYzAtMjEuMSwxNy4xLTM4LjIsMzguMi0zOC4yYzIxLjEsMCwzOC4yLDE3LjEsMzguMiwzOC4yQzM0NC4yLDMyNy4xLDMyNy4xLDM0NC4yLDMwNiwzNDQuMnoiIGZpbGw9IiNkZjQwNWEiLz4KCQk8L2c+Cgk8L2c+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+Cg==); + background-size: 20px 20px; + background-repeat: no-repeat; + background-position: center; +} + +.i-save { + background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDYxMiA2MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDYxMiA2MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGc+Cgk8ZyBpZD0idGljayI+CgkJPGc+CgkJCTxwYXRoIGQ9Ik00MzYuNywxOTYuNzAxTDI1OC4xODgsMzc1LjIxM2wtODIuODY5LTgyLjg4N2MtNy4yODctNy4yODctMTkuMTI1LTcuMjg3LTI2LjQxMiwwcy03LjI4NywxOS4xMjUsMCwyNi40MTIgICAgIGw5My44MDgsOTMuODA4YzAuNjMxLDAuODk5LDEuMDE0LDEuOTMyLDEuODE3LDIuNzM1YzMuNzY4LDMuNzY4LDguNzIxLDUuNTA4LDEzLjY1NSw1LjM3NGM0LjkzNCwwLjExNSw5LjkwNy0xLjYwNiwxMy42NzQtNS4zNzQgICAgIGMwLjgwMy0wLjgwNCwxLjE4Ni0xLjgzNiwxLjgxNy0yLjczNWwxODkuNDM0LTE4OS40MzNjNy4yODYtNy4yODcsNy4yODYtMTkuMTI1LDAtMjYuNDEyICAgICBDNDU1LjgwNiwxODkuNDE0LDQ0My45ODcsMTg5LjQxNCw0MzYuNywxOTYuNzAxeiBNMzA2LDBDMTM2Ljk5MiwwLDAsMTM2Ljk5MiwwLDMwNnMxMzYuOTkyLDMwNiwzMDYsMzA2ICAgICBjMTY4Ljk4OCwwLDMwNi0xMzYuOTkyLDMwNi0zMDZTNDc1LjAwOCwwLDMwNiwweiBNMzA2LDU3My43NUMxNTguMTI1LDU3My43NSwzOC4yNSw0NTMuODc1LDM4LjI1LDMwNiAgICAgQzM4LjI1LDE1OC4xMjUsMTU4LjEyNSwzOC4yNSwzMDYsMzguMjVjMTQ3Ljg3NSwwLDI2Ny43NSwxMTkuODc1LDI2Ny43NSwyNjcuNzVDNTczLjc1LDQ1My44NzUsNDUzLjg3NSw1NzMuNzUsMzA2LDU3My43NXoiIGZpbGw9IiMyMGMxOTgiLz4KCQk8L2c+Cgk8L2c+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+Cg==); + background-size: 20px 20px; + background-repeat: no-repeat; + background-position: center; +} + +.i-warning { + background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTguMS4xLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDYxMi44MTYgNjEyLjgxNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjEyLjgxNiA2MTIuODE2OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCI+CjxnPgoJPHBhdGggZD0iTTMwNi40MDgsMEMxMzcuMzY4LDAsMC4zNzEsMTM2Ljk5NywwLjM3MSwzMDYuMDM3czEzNi45OTcsMzA2Ljc3OSwzMDYuMDM3LDMwNi43NzlzMzA2LjAzNy0xMzcuODEzLDMwNi4wMzctMzA2LjAzNyAgIEM2MTIuNDQ1LDEzNy43MzksNDc1LjQ0OCwwLDMwNi40MDgsMHogTTMwNi40MDgsNTgzLjE0N2MtMTUyLjIwMywwLTI3Ni4zNjgtMTI0LjE2NS0yNzYuMzY4LTI3Ni4zNjggICBTMTU0LjIwNSwyOS41OTUsMzA2LjQwOCwyOS41OTVTNTgyLjc3NiwxNTMuNzYsNTgyLjc3NiwzMDYuNzc5UzQ1OC42MTEsNTgzLjE0NywzMDYuNDA4LDU4My4xNDd6IE0zMjEuNjEzLDQzMS43NiAgIGMwLDguODI3LTcuMTk1LDE2LjAyMS0xNi4wMjEsMTYuMDIxYy04LjgyNywwLTE2LjAyMS03LjE5NS0xNi4wMjEtMTYuMDIxYzAtOC44MjcsNy4xOTUtMTYuMDIxLDE2LjAyMS0xNi4wMjEgICBTMzIxLjYxMyw0MjIuOTM0LDMyMS42MTMsNDMxLjc2eiBNMjkwLjM4NywzNTMuMjExdi0xODAuMjRjMC04LjAxMSw2LjM3OS0xNC4zOSwxNC4zOS0xNC4zOWM4LjAxMSwwLDE0LjM5LDYuMzc5LDE0LjM5LDE0LjM5ICAgdjE4MC4yNGMwLDguMDExLTYuMzc5LDE0LjM5LTE0LjM5LDE0LjM5QzI5Ni43NjYsMzY4LjQ5MSwyOTAuMzg3LDM2MS4yMjIsMjkwLjM4NywzNTMuMjExeiIgZmlsbD0iI2Y1ZDg3OCIvPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+Cjwvc3ZnPgo=); + background-size: 20px 20px; + background-repeat: no-repeat; + background-position: center; +} + +.i-close { + background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTguMS4xLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDYxMi40NDUgNjEyLjQ0NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjEyLjQ0NSA2MTIuNDQ1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCI+CjxnPgoJPHBhdGggZD0iTTUyMi42NDIsODkuODA0QzQ2NC45LDMyLjA2MiwzODguMDExLDAsMzA2LjIyMywwUzE0Ny41NDUsMzIuMDYyLDg5LjgwNCw4OS44MDQgICBjLTExOS40MTYsMTE5LjQxNi0xMTkuNDE2LDMxMy40MjIsMCw0MzIuODM4YzU3Ljc0MSw1Ny43NDEsMTM0LjYzMSw4OS44MDQsMjE2LjQxOSw4OS44MDRzMTU4LjY3OC0zMi4wNjIsMjE2LjQxOS04OS44MDQgICBDNjQyLjA1OCw0MDMuMjI1LDY0Mi4wNTgsMjA5LjIyLDUyMi42NDIsODkuODA0eiBNNTAxLjc4Nyw1MDEuNzg3Yy01Mi4xMDEsNTIuMTAxLTEyMS43OTEsODAuOTcyLTE5NS41NjQsODAuOTcyICAgcy0xNDMuNDYzLTI4Ljg3MS0xOTUuNTY0LTgwLjk3MlMyOS42ODcsMzc5Ljk5NSwyOS42ODcsMzA2LjIyM3MyOC44NzEtMTQzLjQ2Myw4MC45NzItMTk1LjU2NHMxMjEuODY2LTgwLjk3MiwxOTUuNTY0LTgwLjk3MiAgIHMxNDMuNDYzLDI4Ljg3MSwxOTUuNTY0LDgwLjk3MnM4MC45NzIsMTIxLjg2Niw4MC45NzIsMTk1LjU2NFM1NTMuODg3LDQ0OS42ODYsNTAxLjc4Nyw1MDEuNzg3eiBNMzk5LjIxOCwyMzQuODk5bC03NC41MTUsNzQuNTE1ICAgbDc0LjUxNSw3NC41MTVjNS42NDEsNS42NDEsNS42NDEsMTUuMjE1LDAsMjAuODU1Yy0zLjE5MSwzLjE5MS02LjM4Myw0LjAwOC0xMC4zOTEsNC4wMDhjLTQuMDA4LDAtNy4xOTktMS42MzMtMTAuMzktNC4wMDggICBsLTc0LjU4OS03NC41MTVsLTc0LjU4OSw3NC41MTVjLTMuMTkxLDMuMTkxLTYuMzgzLDQuMDA4LTEwLjM5LDQuMDA4cy03LjE5OS0xLjYzMy0xMC4zOS00LjAwOCAgIGMtNS42NDEtNS42NDEtNS42NDEtMTUuMjE1LDAtMjAuODU1bDc0LjUxNS03NC41MTVsLTc0LjUxNS03NC41MTVjLTUuNjQxLTUuNjQxLTUuNjQxLTE1LjIxNSwwLTIwLjg1NSAgIGM1LjY0MS01LjY0MSwxNS4yMTUtNS42NDEsMjAuODU1LDBsNzQuNTE1LDc0LjUxNWw3NC41MTUtNzQuNTE1YzUuNjQxLTUuNjQxLDE1LjIxNS01LjY0MSwyMC44NTUsMCAgIEM0MDQuODU4LDIxOS42ODUsNDA0Ljg1OCwyMjguNDQyLDM5OS4yMTgsMjM0Ljg5OXoiIGZpbGw9IiNmNTVhNGUiLz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8L3N2Zz4K); + background-size: 20px 20px; + background-repeat: no-repeat; + background-position: center; +} + +.i-left { + background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDQxNC4yOTggNDE0LjI5OSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDE0LjI5OCA0MTQuMjk5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnPgoJPHBhdGggZD0iTTMuNjYzLDQxMC42MzdjMi40NDEsMi40NCw1LjY0LDMuNjYxLDguODM5LDMuNjYxYzMuMTk5LDAsNi4zOTgtMS4yMjEsOC44MzktMy42NjFsMTg1LjgwOS0xODUuODFsMTg1LjgxLDE4NS44MTEgICBjMi40NCwyLjQ0LDUuNjQxLDMuNjYxLDguODQsMy42NjFjMy4xOTgsMCw2LjM5Ny0xLjIyMSw4LjgzOS0zLjY2MWM0Ljg4MS00Ljg4MSw0Ljg4MS0xMi43OTYsMC0xNy42NzlsLTE4NS44MTEtMTg1LjgxICAgbDE4NS44MTEtMTg1LjgxYzQuODgxLTQuODgyLDQuODgxLTEyLjc5NiwwLTE3LjY3OGMtNC44ODItNC44ODItMTIuNzk2LTQuODgyLTE3LjY3OSwwbC0xODUuODEsMTg1LjgxTDIxLjM0LDMuNjYzICAgYy00Ljg4Mi00Ljg4Mi0xMi43OTYtNC44ODItMTcuNjc4LDBjLTQuODgyLDQuODgxLTQuODgyLDEyLjc5NiwwLDE3LjY3OGwxODUuODEsMTg1LjgwOUwzLjY2MywzOTIuOTU5ICAgQy0xLjIxOSwzOTcuODQxLTEuMjE5LDQwNS43NTYsMy42NjMsNDEwLjYzN3oiIGZpbGw9IiM4NzMxNGUiLz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8L3N2Zz4K); + background-size: 16px 16px; + background-repeat: no-repeat; + background-position: center; +} + +/*-------------------- +Login Box +---------------------*/ + +.box { + width: 330px; + position: absolute; + top: 50%; + left: 50%; + + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.box-form { + width: 320px; + position: relative; + z-index: 1; +} + +.box-login-tab { + width: 50%; + height: 40px; + background: #00000044; + position: relative; + float: left; + z-index: 1; + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; + + -webkit-transform: perspective(5px) rotateX(0.93deg) translateZ(-1px); + transform: perspective(5px) rotateX(0.93deg) translateZ(-1px); + -webkit-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + + -webkit-box-shadow: 15px -15px 30px rgba(0, 0, 0, 0.32); + -moz-box-shadow: 15px -15px 30px rgba(0, 0, 0, 0.32); + box-shadow: 15px -15px 30px rgba(0, 0, 0, 0.32); +} + +.box-login-title { + width: 35%; + height: 40px; + position: absolute; + float: left; + z-index: 2; +} + +.box-login { + position: relative; + top: -4px; + width: 320px; + background: #00000044; + text-align: center; + overflow: hidden; + z-index: 2; + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + -webkit-border-radius: 20px: -moz-border-radius=20px; + border-radius: 20px; + -moz-box-shadow: 15px 30px 30px rgba(0, 0, 0, 0.32); + box-shadow: 15px 30px 30px rgba(0, 0, 0, 0.32); +} + +.box-info { + width: 260px; + top: 60px; + position: absolute; + right: -5px; + padding: 15px 15px 15px 30px; + background-color: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(255, 255, 255, 0.2); + z-index: 0; + + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + + -webkit-box-shadow: 15px 30px 30px rgba(0, 0, 0, 0.32); + -moz-box-shadow: 15px 30px 30px rgba(0, 0, 0, 0.32); + box-shadow: 15px 30px 30px rgba(0, 0, 0, 0.32); +} + +.line-wh { + width: 100%; + height: 1px; + top: 0px; + margin: 12px auto; + position: relative; + border-top: 1px solid rgba(255, 255, 255, 0.3); +} + +/*-------------------- +Form +---------------------*/ + +a { + text-decoration: none; +} + +button:focus { + outline: 0; +} + +.b { + height: 24px; + line-height: 24px; + background-color: transparent; + border: none; + cursor: pointer; +} + +.b-form { + opacity: 0.5; + margin: 10px 20px; + float: right; +} + +.b-info { + opacity: 0.5; + float: left; +} + +.b-form:hover, +.b-info:hover { + opacity: 1; +} + +.b-support, +.b-cta { + width: 100%; + padding: 0px 15px; + font-family: 'Quicksand', sans-serif; + font-weight: 700; + letter-spacing: -1px; + font-size: 16px; + line-height: 32px; + cursor: pointer; + + -webkit-border-radius: 16px; + -moz-border-radius: 16px; + border-radius: 16px; +} + +.b-support { + border: #87314e 1px solid; + background-color: transparent; + color: #87314e; + margin: 6px 0; +} + +.b-cta { + border: #df405a 1px solid; + background-color: #df405a; + color: #fff; +} + +.b-support:hover, +.b-cta:hover { + color: #fff; + background-color: #87314e; + border: #87314e 1px solid; +} + +.fieldset-body { + display: table; +} + +.fieldset-body p { + width: 100%; + display: inline-table; + padding: 5px 20px; + margin-bottom: 2px; +} + +label { + float: left; + width: 100%; + top: 0px; + color: #fff; + font-size: 13px; + font-weight: 700; + text-align: center; + line-height: 2.5; +} + +label.checkbox { + float: left; + padding: 5px 20px; + line-height: 1.7; +} + +input[type=text], +input[type=password] { + width: auto; + height: 32px; + padding: 0px 10px; + background-color: rgb(0 0 0 / 28%); + border: none; + display: inline; + color: #bdbdbd; + font-size: 16px; + font-weight: 400; + float: none; + border-radius: 10px; +} + +input[type=text]:focus, +input[type=password]:focus { + background-color: #f8f8c6; + outline: none; +} + +input[type=submit] { + width: 100%; + height: 48px; + margin-top: 24px; + padding: 0px 20px; + font-family: 'Segoe UI', Arial, Helvetica, sans-serif; + font-weight: 700; + font-size: 18px; + color: #fff; + line-height: 40px; + text-align: center; + background-color: #0c5091; + border: 1px #075fa7 solid; + opacity: 1; + cursor: pointer; +} + +input[type=submit]:hover { + background-color: #df405a; + border: 1px #df405a solid; +} + +input[type=submit]:focus { + outline: none; +} + +p.field span.i { + width: 24px; + height: 24px; + float: right; + position: relative; + margin-top: -26px; + right: 2px; + z-index: 2; + display: none; + + -webkit-animation: bounceIn 0.6s linear; + -moz-animation: bounceIn 0.6s linear; + -o-animation: bounceIn 0.6s linear; + animation: bounceIn 0.6s linear; +} + +/*-------------------- +Transitions +---------------------*/ + +.box-form, +.box-info, +.b, +.b-support, +.b-cta, +input[type=submit], +p.field span.i { + + -webkit-transition: all 0.3s; + -moz-transition: all 0.3s; + -ms-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; +} + +/*-------------------- +Credits +---------------------*/ + +.icon-credits { + width: 100%; + position: absolute; + bottom: 4px; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, sans-serif; + font-size: 12px; + color: rgba(255, 255, 255, 0.1); + text-align: center; + z-index: -1; +} + +img.tengah { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; + padding: 20px; + text-decoration: none; + width: 200px; +} + +img.bawah { + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + padding: 2rem; +} + +.icon-credits a { + text-decoration: none; + color: rgba(255, 255, 255, 0.2); +} \ No newline at end of file diff --git a/luci-theme-alpha/mobileview1.png b/luci-theme-alpha/mobileview1.png new file mode 100644 index 0000000000000000000000000000000000000000..b4027a2a509ce70f4bced02b9f5153606a7d7cd7 GIT binary patch literal 228381 zcmV*WKv}Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&|D{PpK~#8N?41Xo zBu8*e<@=b%$Ko$@K82$D!5OXQ3|WH8ZSf(Zr#HpYN4{0?A@F$N5XoP|LMfsjB# z63SVpa5?An@?TZmHPbWOlXhq0tM9IMx~r?JdwP0$>dkEET6D%mlaQMNri!Ap7hQHM zxcP3%pmcT7e*-6QO$hRsle94DtQnld7c!zWl}WMWi3zjmD0p1rgHr?NhUJEl_P ztEMPQ$8cotHr{qEJoA})x=$JOP%9pSKqEFkL@$8>1#gs=XpT2lXOm_d^TS!Iqm2|x z&=v{mY+CY6B$I-4pjB}ClhrjEQ#bIfg~D!1YFAN|hO?q)3vavmRZ*0wOK>d@qA^DV zCmjSGj?Og=>binU4d1pC2{#d4#}M0}NW3Kb>k5He4wzkiTr#LCF3aIpQIwWOgSjb# z{`IXS;aypQ&i9`alT5$dNq*`jJt0--b zcfBIw=U3~VCmPHt%9O?~P8Exo5MRI&7Bf*N`SI#KzJfbbaY&aYt%kG1-u*%1-FM9* zW#r2h5BzxASLW8s5=Bu$+!M0((O_;$pbNE2_8m_%!ND2lO zMJb;)U4Jx~>p0|U=!&A`ATm`v^TwS{K^k8~7bpXTA)>;Bq!aHX5gNec#ygIRqEro^ zQfcc`>!HD%q9_T_!X=BBvxrIXKwD1I)}{lo3E47~m!wSu#ZDRFrrRCaSC_J4RiAG~ zQHqgxKDN)Iq`_RLLG!JhMQH-gz`Mtw;&`A!bQQsvhln0Cl6UJeQidyP@WF_nurr7R zT~+K`+WYPlrCMkz78Ms?IY~Q0=aMS{?XgoD%qfbJK*g$N@U3fE>z$Ov1Gyl`@wC(S z#0G@-RrWttmWQMdhNKQ%CyuL93W-yY=1j`Gk$Oq>b;>mb4dxU@@sMXlrqvuJ5~P?- zfE1C91TbR5TWp8##yRC3gB?Q(!bGaY9lr`{^sRI@G;Mqmf##2uU@AGfxJ14)Qp8f> zTWJIu%qfcEA!*fj@@^5ET6+mRToEK0-v*F9ZJmol+hTXl-G7%PeJ0h`Qxq2)gz+C5 zVU}_8xdmV3j|!Tit|)a!gE>V}l97ctvLIu|)w^Yq&#M=FI=(`52&D&fF6blCPZ|D| z&cmKt?kPr7B@jtCkS@@B$_3wD;sjHrJT#b76eS&Ah;e}qKAd2;?gH&w+eIgOx7^h; z*J37tFqnwv>7vlFb2e$e+zXss7#)!@awUnhvIy~ZlqrGC z4++BL(3760g6K^_7yq+Gk^H1bY9RN#Rf?d&T)RUTLlH$OgUD2pWgEBgDMtA~Cz+T8 z^Aod-=*b_YW>C< z?Mx?~FM94biHw2wULQ6frxXm> z;zWtt5b?Z$=BT5=hI_iZVW7Vc`uqBzn<7c2RJs-@O0DEvR4X2p)H3&6 zU)E2eyLO)A31eI9W2d?WbL~9VQ=Isr<0(cjRAA}yumn^Cc>tSrK=a| z?dgG;Gp51f`E%j$Ll(oL1#@9+Y#jCX-Tsx2T6vsVu@ly=vo2Y1O9*~9=jLw3IAT1`WFd4TQ zddo%l;dV@8VsNk@jyQBFoO9XvYN&+x@$M=zVm*V92>KmPNHsyO_@>zOLq!5*9rt6-Cf<#)7uL@-94P2n3#m| zi820*d~$Mvb=lK5|NN%*2KonK!JI{~XxVh0Po>xI8c$L}a26C(q z=HVoCu^PADxfz`sloKzsrE_rpyg6|CiO0gl7d{5gK5b>L0O`QNVOY0mD?GGjJ^bL8 zSEKySmeil)k2(Ur`MJM^Ws4VBO@2Q9?_Yy|`Rey(Wl9oXynS=a+W6La%izEe9JAt7IO@ogVE)`CFl**KzAzlX zz-s%BO|WkLLvY8v*Tc@8TWt-2+H)P7_Ge@LUJT5(VO<|xcmX+l$#Qt~$rr$}M;r(9 zW-YMq>7fgg2_V;QS`BwSbO&5>#~)zV-kqjm4tg<&d*X?YftQ_sG4x4J^Tlf>Rg9H8e2i87*4?AQL+faV% zj$Lr`UH8Kq|K`&$JUqhsdh)hcJ|F((Ew8k>;vDt(7sKBD2W+l+)IFG+d&ViSx7=xSokCp>o1!ETUEUc-HEYIPc**ns5)NIu0=n%Txj1xJZWI^xUtIYO zxapRw_)cAP9*e_C7#f-m?|jwAFc91a|N8a6!^OVxkFj%3JP)3K;fwh$8egEu7yjq8 zY*8jBCSm)ot?-ZE{tWCnu*cS}Wai)u*n@$mKzAFSi~-#%&VMFfh{W$-eD&k7^FYyH zj_{13OFY19SP&;Py1jNJ;~2IO)Klqg7|7XaM&}1^rQDn=lJ?`y4oXX&?#O-mgKvck z&p(UvW8>p+_XCf>o%i7%ZzzAh^FDZZ?MD2AZWjy=4REkW@1&N!Lt z5u+H?-FEi_@X~jD6n5>Y?|bRK`cEH(r(y6ZJohg?0QWw$2LE{6WisW%o(->;4v?F6RcXj&gPnj1am#p4>|55oGO_?JYX}AInw5u%f9;`f`c0y z|2$q%ItO=&mu0+*1GnRkc@(_zrGE_z<}JkwMDhpZ>25$zPY)ck{6rY+AB2b3+=~I- zxGfDiWYOX9x);0y7R^}%v!>62Q_=s!Yaf6;_HG!p`MA@b2rqupOQ9eA(S@iR1D|ep zi$ZtjdN>U*V{iyAJmmtof88qBwr2B^#`WA`2T>9LnMeZX0<;VUXKlXJQ z$Nkx}Z$E6@x*eW~f!xZYm)jD6pZ(?!O?jVRoVnfmd0V$&Zgj^^n04Z@{J6E5jBMWl z8-MjXn8d#p+815el~$w+mMuLBp8w1@!ps?StS*EXVH9%#Fn7s%D8Rxi$>E0_g@2td zfxB1T776HPO`i>~eg4~F$-E^Tkde$9nt>OMLAd+jJ8^Lxhtn~*d+~)YhTiUO6TD4M zz$EG)TK^DSe%;UEY7DkEZruorXU&5d7&J;?N5R-3a~H!MtM7pWBL{7Z0E=hOhu1y+ z1+Zx5Y&hl6qv8IIt6}TjFyLFYc`e+x@e#P`;k)6F58MuqY~KhI^4`Cya4&~Sd(j@p z&YW{1_zx2j$ceZ?ocX>u`QAAC7qul!T3(IzGavp-IP26C@DHqR4ur11`A+!aH+~FP zUUMUC#Ta0CWE9Unf?i#32zF@wrY&&S0}sO={(L)}anf-xf6gpacfq4DcAz_aba#(F z0b37VeDQ^mVD6v3^evn6bIz$N;Y=H}65syWmEK_P-LHQs?#~@ISAQg!tNRBaX01F1 zdS}hFn#MA^b2se1s}nu|p~0Nedh~Sn!Yf|#UO4*5ldJ}3Dh5?+);|ch-2QvG_0B)Q z_}C~Mw(Mv)=kzDQvCB__X+zV^l1_mh{?&W^tyjU1e{&g(kB`A23lD?8c;P!?<}_R{ zI0!@=+^*ZS8ovC~FT%E6TltROtDp87IOV95Y&pR0y*uHXzxfW_^5AXM1MUYw?|Xah zInRKnopu2Re&*3HwfmK;z6)2~bsgu4#~*(tyy5ZBH;+=eTjTJi|NTeUxj*@lZ0$G~ zwU!|qJHd?7EU?-C=TczTC)M(kN&Q? z@irK(!!`T|U-)?B5%1!&pJh{iC`fw`ia?KL<3XF)eExrb2p|2IuUKt;(XS?HEA$Yx zHtrHQb&l1E$Da)^dEQ_0!b^)Xy(jLP>n=z6IqZwQr;I+?di+tR!b>lDJqKjGv}4e8 z-ECK6F!ya(GJh#tdeQ4((cHyc#v_XU?pSp@eCyZWfZhAd`&bUcfbV@Tc^3v}y?n=Q z6obW2eeeIl!p9zGD#q5A%VsVHipHR4WCKLw)_|lj@l{F@pYv$47CTC?E5uC?z5D zTmrdnoNjcAy1^U~+7UGOO?gNx{K7($?}DRO;CcAgSHXE_p9+1wy>Rt)H^WE%`AhJ? zBkO|sE%&Y|H;Ek}J=ZtIF(#p}uNN+U!eihquXrw;c+8P}x9>l{^%MBd%YIUq$C+gZ zbMf-8e*YKn-cNqP=IVz8bIEUTQIxhPT&k)=>RaJIH)B%aUv#lDUeQv7aq6%h(}9T2 zktRa#jeE>lPd7crpo@Z_haS2U7xkZ31absD9=-GaKf@Ql^(i>856dwKy8D4!;fKHe zCd`>J2j2X=x5JXTi=YQD0X^uidvY8eTKfQ8cI7vNK#n+K(V;MaffCu#AP&o6)fC-~0Kuj22aBhEhc1UTu~6`XE2Uiti| z!^htFI-9FM8q6sjio0TXSC0%lbx0K#FA{CV7O*s7qz)>gtEV5weWRH%eHJX7yO0AQ z3WU1GM&X|OZ-fH}(m#Q=X46CP)t`I;e)hZX!~fv+=);bMzkK04VHO5AJrqz`x%Iw3 z!+&4?<%+KpId%C;EFWiE3J4!qpZ#s@J1`i0V8cTg$c?ja3h0hoayXYw9~gvw9Ba~% z&$Zh&!fxjit%M0KO}W^S&_yi?y35DGBiflU!aigEnA!8;LQE*%_T@jrrsEVIspc`WCQDHDl*FoK}%{JFE?_@kG@!ufMq_sid22e;mJKc@-P z9trxf>3np-{sY5s>piRB{zulbhQ9LTA3>Muw-^**`p^tqJaDnbfU1ig9bz!Ic}u>J z=|8aM9=PhpU&7p3^Wb&Qcn!>-F`EM)4wz8r(dyT)_$KW1d@tO*X=G~xq%I7QCNWsb zf*$WojFa!MjRn)p7nu+A_60inr0T(ugD@8J**#(I=!uXWw~zkPpu3Cgn}R>I4eDe1 z$mz4;btjz-fB)#G!nD3VTSHN*M^=W&Qeihnf|4M`dYj>N5QrHh?aHA`7r~K-AHu)0 zx_aG4`2F=a!y{`p*m84DP}*#bLkSQ?p9cMO)*bgg#OWE+hxn7Oy}kagJ8C2pthwU* zkb^Ivqerjre*H^qPRKJ7#i(mAM<0Nged-CY;IZd4MX2pA{mWMgDC-2G1|;=A4pmIQY{pm(48l9$BFJd(R*C-K#yTgTz(?F|E2FW??(%QoN>72{#)Q1 zzxfsiRX#Rt-w*^vz1Ro(4ah9$QRxuch3!nhx*g^{IJ*w)!=P|1C_BP_0@h_@Y#4^I zKf|LW!!R;}f?MC$st6c9!szITkukHSN4P;B?BnFeEj=9Ge9}31NSl2;l};g8B5>K@ zWx|A?u`}ZG!&6~Fc_37NE_vw*ie%wl1S-%)J z?Ptrjop9|<=0gv3ejkN_N2o3@_P8(C+;ts%>vunZMYHC^^Ui$+ z{Od3NJNS@-aOR4W;GIvq)ZRgugc~2a6F&2Q>A#b>Z1w{9_%mM%b1`t_;lj3F{MAqJ z2N;O&z2dK7T5mt!X(T>%^^f5eBT`1@tZe*fvR(S z=tC6GJn{s1_3@`izJz!TgV+yV_iOmo+Sd93Z>3!@lZ@|_Qx0Ev8wh>nNK{8iFc;Oy zOAIoEF@-W!3dk;MRrEll&ddo$g29O_o;qPM~fOxh|8R%}>V;+_KzSumt{)wl) z@?CJt-4ECtk+ZWY)cpexvras&>46;4KYuRFT6wI^wF9*uT%`(V*z*iMuYR;Vn&6EW zNmAjWMftc;xlep{5}>dSU$_l!D+UE|B%HR=VD{|a1Dm(3SMrm!@W1b_pkXW%$q(NUh{+(!WkI!eE4~9g}In_p)d6v z9zMu-wMfoB;y5_th~wF}kG}36c-rx2z`Vhsps#CoY=VR1;g^G6dEYJOZkhG@{_`$^ z)0ZB>0T;1(-)`8jcZVZ8S&{-dVt8y6HtgF4>-L7S2J3wO_CLZaulyct!ZPU(eG})~ zPdpQ5U;wBnWngBmS*3hu2IFc5=mO< zn}b|^lZ5c;l!m~!!vz1*;|<1mu`*>osj&A67SJ}ZqW}>PKQFp=F>DD zg9XPdI~rd2*cW)uH`1Mb%%k9~7rz!}(ii!nJ%1Ph<*M7RhX4KT_h8ZN1@NwmUIWK0 zI+V+fUbqb2{^U!7po-YCX9wK;&>bcaLYrP3pZ8q&5_r+09?w6p?{e6jh4AhtJP)3G z;4=oeJv+9*m+!ubzsOw1 zZt>tCoH{@Ho0f`F2s%$l?A-RQ7Niuh1X+ABYNyb`_tQ{4HZ}%BL*d&HhKEOC_+YUw z^{w>o=NG@b9zO9O{|le^!vFI3*cBpgBMoM#;ztyyqqT~mu8&!deErLyZ+6DB?m9!i z0P)b5FN28&{BUnR>N4C)1>q#G#B&T-g>@p;C==RJPKxCYnn{yLP6*4>i1viM8V$eN zKFQng2)-#73wbAxbiaCxo;=;mx8hLSDpjUc+?Xy zO%EF>NX5OtAm(>>T@T;5=EpEHHUdj$FN6<1=Z!FrAKltJlxVkO?=E=n_x=TTA2ffR zA2Dw!eB`26!JMIK+@AQON3!d7Zh?)vw!_NBhr`T)e(14*Abse7`0c7Y;Ir5MoWJkQ zMuYv zoVpFSQbE#+;5i1Yimzs7p`lk%hv`sn#ArikF{O>@E8DEp&}BUg)yx)knBX+JqAlmy zHz_T&f;WM~7ab0-zvwlvXx0MmJ#~wM8Tta@iE%vdFil^eOFzpRo}1y{@41yr6{Qe3fy_^F(cDW8=0to!9lcmJ zW9BW*&JapJ{`|AxL+^S69I|8)jEs)LC4cb&xaH3K@Z29Du9<_nE?fq)i?eLjvFUO0CDf2-Wzn5V!_l8p*4So0*br^`@MUQ)&6aX4~qceI+)A4=%wZDWvYz~9D|9bS3;Bku&wRsBWZh?P8QIx{qM5`&7vw6F* zn7JJ1s1=99-@WfGaGL#{(!c-bFY%WK@7lAEYnYjDYKyevow;ghWFSXKFju!9+Ex#N2H_MO+kI9*LLxMS-ExO&Y4FflO+Bj|U*zz~0_FzpZT6T09u26E;&oBc96 zyRS~#E&IuuRj_8C`MuYfz5Vdcm8ZjW+!8bvzuB|~ZrN@=nWiYI(1H^q2;T68h5yl( z&P7QZp%>m#k`g$tO&ynLj-WG$=IUuD9|y-CwVZXEx9)(u?|%q(?2_LyHf_0QTSYo> zUD-xJN>LfS_~IwVerP{E*t+1XQ~77c9(B^Om_7w=yJuC!8s-b+uDb4K_^Xfqo6VKa z+-~z^L+{MBBzj01PB7%Sg4jibHpzkuBqn5$B;>@nm1o1_PB;q#tA6f11vC$CUJF0E={IoC#)o0= z@P58imBkDUr06^1b~%q>lNjjfgX#SPFuiYp?+}iRkHfx^VU&X~X78XCfdceF^f?24 z4t8UJC|5irI>dPV9R(jP&#sZl`UCr5|Co8N-t&(*7XJRU$3U;Gyl;FI-hTaW;cEMy zIz>r^=1uGz;y)@;75!m-6Ugx&7OvonqzTD$+HRwSYg2bmH@xWCPleaN;`wmMl7(>B zy{q8!|MOk=_0@lZk+Csuk!)G;h29bptXufPXCpO2iZJ2F?M#Z9x6^6%NYOiU@j&gk zCtU(NcZa_g;|t_&z54-p$}8VxbM-+Vv$iyPNE!|gIj#uKqCiQKiiMB_Uu2;)x^Mv{ z_|+t36JVA_)Z#{tbVVR%h3qD5!2~(NbaY{~g+jcsCPD9$8=xPW$AO{+o<8897-r$P zeDY9D~eL){LEk_7$v=qv`5bfsc3WZ%3N2ywX-ydhege;VC z5j!`4Gm9nt#sKBR1(tEzR$3Ff=$<-v5q#;~3t@Ku03W}%U4Iq)a>FCWKvA-w^@P`v zkRX`DbReX2^CT+0=L}V2(m>`X|CODJ8jkdJlk+lSH ztY;e$dZmOZw>gATM#r!Aldfig!!#=CP8*epP@N!(1uIrQ9S&Lk7#Kdd2kyQ3GT6PtALJZ$;>ECi z^L?;m%l%mA8L;7zKf!^0DepPMgS7IjOX2Pt|CfKUqFTDTy1Bij%O8#7KMCs}yapb* z?~25q_gb*@WH|AxSHi*lTjBQWz5@IAZbEGrET1t8zVzrP!5_D*hY#O!oiSFFDhdCv zBscY6gg4ZZ}I`al!=FguCZ@l#R@T!+Qll2D<4#V%S zyBR+D`LDqP53fZNvs%)BUaxFL+OVEevTZy?gSn4j;QFRZLYpUF`d9qExj0|?hxfwk zKkzA=t3MLVnd4pu^cNs%g(kU(Qg&be*UR!F*@|+(%rB zQUOg?XO4u+4J~05m>GrWjX1#=<|W{gK&;1>8=n}%IoJ#hAg?}O#XJq31bxzB1V>F()=<;On_R-Sn& zELwJ|)%xk~?u8T2eidw5dlSr=zrt#(oN)AVm^EWM zca^q1&QF3h3-`kdd6*ju=2pcXu{N8!K4#TlfGCT)93q8~p`~C5(-IfamhY-zg6_hx z-flSnvo?~KIxL(vcjU~A2iq=fXrZLX5R~9N3O$nGG&+;=pv;!@7B!+bFGy0Gb%gH9 z9d**PVdk7eVdUT*7@DyFZv5?Muusyd5DI8cKmV=prz`)_Y8-HXk3Q)+uw~sXuxtCn zsHm(j9RH}7z}5|Spxg<^pZ;Q4v+B37Z}&!98io2ccj3{nf6o?JeApRq^-tad z3CEoJ0=#Gqz`eJAm-8o{{Yu#I@E^G^J}8jeyK^1(;aMB^u|4P(0;UFm;h|Ht# zk3f1gp_225AuUR@o&sPeFyjl`UeO5`B5yr&+M~b{tn!|YBh}V``N`yV|ne1E`on}_Zw`k7nkahDTQ_6?I9IcJCb%Q$5$(>;HYPVL$ zjhg?GjioABmtZW=8V1A21rv4q^EZfPCoZFaL-NOf{~HEaQqoB zgKg{Y;5%V)D409<$sdG)!C6>-Gu(B<*TTRG_m_gX&1?Uh_+B|7Z!kx93r~LZ>*3aG z{sSf^MqtH>&xC=Y*>LBd{>NGrgYF!jeC}&u-lF56tGgFAtiBHJyZL+Q+yB1Y3(r3bUjDqN!Lch2hlTU!!T`nqg4mMZfBo7I;7gbN6gF+8w;f1HV>$V_74Xw9 z{iEmiQnRV&mjD+0YE_#&!%>;1qJO*}>cl1F}hbty;QRs!Y7D~I# za~fZ0YXUY5&TKxoGsk+f==rW_=t!=YIvGfM(GTAv7d(qR8vF>^Mwm)GRE zEG4w{rZI8sQHR5$PC6b=IA%GlIN}gkdCZZpaNZni0kCJ^e)#7ve+Rzt<11j--hHN0 zlX&Axp9O#O)=T-$VP3Ai>2`S2hdyHi(dMJUTw9=rrfLcg9WG+#zX{HahJ&;q&09|} z7i`VqNoo2km`HuUCN5&s&B;l#tnzOgVnPBmlg2XKa=Dct&E-~SeK9FbDy@PZB&AGf zKGE7^)*z#yf3$V)&>74honmJ&)`YPSzznTHgsd^{Hb`TFo+Oy`B+Q#To4>YX0dDCL zYd8LJM;{uXUyAtio%g}UE!(IgreYJBkNtbrh3CO>D-MIDix$Al=|i?8WZ!{HI53*@ey*t1pGtkSaRK~l=Z%qN*uv~`0xLed!_RsgESUn7i?o`dXaRXi@dt}1j60$ zlU1%LO4|{f*0eZahVriPdvaOAfY0P@IzjjefC%~~d&;==i11HMdi#f6O~pWrlv2@P zPMO-ck&v54D6kSt(kgJ{nnnXKvrf&Vt7IY>CZf?bvW2NUc8XFv;Yn|TDwCHxXi{p*NZeNxvXeBvqy}~P zLLztS2vbJEqWMQT^NP@vcc;Cc0;QwDoT4NltCWLTlcFmT=V&Fgr9zOx1P5+bjAO^S zQBuODjYQj#e5ea8Q37>Xt~7(lQArR*sTbk8Vgf5O-`qfrFlj6&y_DgL*aSj4N2EZK zgrnwHH$O>FDyR#haAAi^S!gh)bRK5?sx#Dx2);UPx@j-A+=OQ)M2i#GaXwi4l4=QQ zWlB0UcD0D2G@CGTqF4FEJ0W+?#3Fd_9HmKc3I_pRT*L;2(ve`1U!AS3V=~4%fb<&3 zm5v5;N@qd~Mv@3_I)U6vPK9CU+`f$tF**~7r8lliU8Bi9CW_Kt$SM-MTV^#9)CIvA zPX8c}i3&kIL0eNN^g+b8OptNTEpn!mjs|ne)FbD0J88-B>C=`cQzi{&G@NstBeS?D zilQXpTQj_ZFLDRYCuBpobwn>^(Ts~%sg!^Qb8SJ6$U~`(#37~vBfytB#t)D%48izAK8--c+s?!DCYr%8THOvrM6cci!R>1aH2Bz7+^EB2?bxVqWO6) zvlXlc|Cw9_szzIxCV8iePAf&3TF^ovV&N>V1yRAZi^b-7Ei=Mz49LrUGy zU`|mIFiVhG^@1RZUt%9W2m&uo+H|PH4gI%5|8UFYw6%K5Q-ab~2(x%nnP?2APG}eD zP@XkbQ54067nKxo3G}qscq9n+;uV#8p}|~RK_`b&I?i91zIDsRl$$_|pn!@WIpCIb z?x(}(B@(m+GHHG!pUaGr_4Lo$aCP1qok#78aoVQy= zQIwkD#Rgv@3kxe_qO=kk%qdeG-(Q?j+@;H1$~YK{Uhz?Jn?X?&rK8YbPMN~^FYt2Di(dK7zE(`y>hXoG>^2^RQD7DXbdq-@w6l*~ zt&Z~MuAAwF2w~FpP00M76r(4^Mv3DLlA~Up zf-(-`tc~O)urtyX)1zP7(m&oxJ<}rPMc9grC}lQQ@4&{Lx){@b6%j>Il+H(kxwbxE0B}B6|GK0h!b{Kf7ZBJqhZhJqg^n-(9G) z`9SRw#4$zYid1TKQ4~c{;%G3}mgt48o=AX1TN9*313U?|B!J_9%nDfsk4i_Oo1o4Off$_2PXh~-^4rro&h!7NEHZ%w|pYckOHV7eRKk$n%^a~hq| zmg~nK~3=?v+tdgJ96W^rQog$#&JvUnPVOLp&)M@ZP-o(bra}M>Y7~$T8bnU zMNyQ_cK6wLN&n?xMp;S8kDZ$K4l?M6#4GC^-loaiX{ZlnI=|{1^pZC}U_p z7L;Kcb)%T3ZCqH7j!ZdiNl(7X7wXs#26EU}3gkGAJ)yQ)$QA{w1$|T$MNy_M8q9SH zZm>dPBAu8t8eboBNPJ)7(ufGgHe()_ikJY-1YMy}fF|itEDHj+i7-upn+WNRoz0_9 zV}m}(H?@QN$$=e;3F2(~K_10P$L{|rilQh}2o2^s5*ze1U8pN@T@J}2u*+ea7jfsf z#8@c|oKQ@VW$&D!a1h3Mx{GGEW0NG9CZTfNnmce9yrFXn*i7D(vrp^G+|jePxFx-5 z*9LetPlCk}Q4~c{rY;)HO(`T=X{59p(LPh46a;c4sGz_t$fI!3=Ex`obd*M0xf@41 z5fiYvWh4~rp&o-&+KOMd9lj$N$)^Nz?Kt#`q9{sLXfUTJ0^jkoX$K0J1>Zd@oc6julI{I1?^Z8dQrz-e5DNdqcSD>|i zgP-RjK^<9h+Un_UoP2$WX`L{y6}Sy4ijq!njw(ufqF+s-v()Fuad(l6gQ zcvOm#8=6zCAdSS=ezQbTYC!MIO$BJ3Xx35ggheW4?0D~RA9;&*vbSa{70uQiiD-#| z12x*34I*CLnhqG`RS-ATi-a=O@tr5_K)d!^X()1MPJ_8lN3P|y9Aym%DoGem|48K@ zd=t=FFV!3~x4xp}L8ePH&vTyZ_)_(pZxQMdfQip)j*kX}9gjX{Rq~;MoS%eYp`|k_ z=4ZC@O7!*|zZ67|mr@X(X00%9I$-YBW4$Dw)%w--d&;1}TqnUNy-nvu7K$X9isapI zGK-6ZWs;7JC+P@E#KgUza+ zoiF?3&l=0N9_#i-@60s=4dfb+?4P@zN$DhfHl#|eY750K)z$;I=@HrxqKbp{d_|&D zQE6525$J6q$<9ljbGv0}vA$=GWm}JRXP|fH>PNv{yCDnpy@2XdQt}Ed2(olJ5XsSv)jG6U73B)>#G&U ztHaUnnQIh9gQmE>@90d`D|0O~mBy9EP2RvP<4lW9cgBDQ?YbSHIw|$2$hVM@Dr-(e z%Bcd1r;hvC2>$u71f(RRRb>ie=1+5Gh?&Ndc)FOc@u`(E1HxvJxevZW<*QQ0ACzB-KefGL2k!tJx{ z5y+0}*}CSAiK*w>Q&pKpen5R#9{Lo7dR}rY~s-{&HZB0Qmn5%{|f}$)RR9@tWxbC=~Q@M=(wi(-UD+mEg)y!&df&hAH+$Kow!AUhNv$E1c* z#yd*sJq^j-ht5Mk&03V$#kV>#d=zaXZXU^((ccasHm;S!Cjb19-biQ{2)(3&24ZYp zDk_;G^ot1!%y?_{5y2NJqZ5~f^U=q!lvYv6FJ?|R6X`?Vez5o4j^akh>3^i{6OK(?{I~i9 ztfhOhZ@#~neEXeq7P>Wke}T&am`2>jES=RsJ)lsEdy?qJ^fM@~XkWHy=k5~PnKD#j zBCs>rM0{hAX0Isjv}-)k*;(W!3)Re;+v3i3TlN0h&iU$_eo%?r!OPo<>_NCUvbN>+ zRAkUBz8a;q6POk4S5f;Esu+`Yr1KxM%3cL$dXVswQCyq^he^RklHR4rI8ogWN|%G-b=_c^f+|xM?wo0^vONjpBJZ~$AMsDxk_~P| zDoEIQzgAHU&a7)6xYMz_(x_v#JrDfvAoUY3&wtKPqo#K7AU18y^+K(=_t=dme$C}7 z*(m5!4Aurk_7Bojj75cAYQRZmua!p&p+kttT|A-5w{+@-RrrfXq1I9|zY%axjPBIF>Pz;v@Q} zoo_!VfHPaSmXFXbj(ayS9p1aZMch}^hm_`>Tjk6_>m$=u8EvId%D&{M^*#WRb>Yb> zPa8kIs8xmBxpGC`R2-MMonPn;#QrxChlr*8i`s>{cv(De`-TbAW++llRHX4mba4?R z@9u|;gDZg^6ZEERu}zXV?j1OvT|Doift-?;c9|JXu`Q*o}2tl0;k@Jj%ZYTSFY^FTL%IR;imDx*owe|0(=x8fxTereoe1@+suK##xg|)XY zIf>VeAJC%I(iaBn*XklhV;{46E<{!1^A+C%uZ?3=pg&20ReZAN4b;*o!-wE{GJjE( z=Q}U8wdsy;_7pYyXfsHWmgD`TV=Ml+Wqgqyr0o*hc*^6wXA@K=xpMoH(ww4nG`_h{ zI@ZTestAEqgrq9wNvxDs|EM%ipjVW<9&2yA3ntJ<@*`LBAGTrIBXR8|?HT*Y37ZNL zZ;n^Av&jNbYk{vk4r(4NM0T+ZUqY3>>KDwVUG2&s?%(Zw9onuoAW5oKR#27KPi?J5 z1ElhxP>J@z9Tf9jsttfWZoXTAN(K>)VH$chN5%=ayA58IY02+ ziI;^`mbm9+kd9O|S~rZ7RP8}h^_0~%`N`ucIgqpC5%kCJ&DY(mb}4`iansShh7+2yvix()ezdd+SVjbAG0jDJjIW<#Ig64dv&Z#uNPPP zt)s_UO0veH)Z$=l~VR(X7hMTMm^z7<5ul8z|a1nq~%R7mn2 z@3Yq~$A0A|%~yQaYHatM4cG9NKE#tj(xBFf%nMk0d7eO_kf1-WK1GV)?{3_qk)&O7 zt$euUxuxKK%O^P9Plb6U<@m&HvxwVqI@a%YMFTlyD&wBRawfQ+U^Q!v`w8{*f8n}h z(k5@}y2!ehMmwIHdHZa}C_|j%kR(ah0jyl13yw!nMz6`3eGwb74*!|?5c*`lB(eP$ z4-sw5rY4H`Dyd!now>O4B5mafGSfQm7LhNprH#)wmgni7Ym+pw^Y}4HN5UGR&pZQ= zY!jWR*^s?!&7LvRr!DJqj!za@K9a_?DCDK6FWG0>SE8JrR7Y9kpeR!nIfG~$r18A! zc9u=Pbfd25*(NT6Ev=PZ(Yr;IHXjDaChr}uP9g99ij~->)skb#$3oI}EBM=WXNU{g zhW1o7s)YhT?8O+o)&`}hvJSo<)Td-l8hEjIGP6>m$j(laV|O{`v2?g>mO*Hkbz zzLFwP!=~|iU)ar}Wz%+B7o2v|$lHf9#--k4t0+qALT7&{W_@DewJKb%!oTZNK8G3k z1qhSo;ElGNF#+3zHRF)ZUL?iF)3u_sv&}Y((!n?%tMAY4mO> z)eb$FwkvD9n#xi`(PNU^p1Mc2DJ)%eSkv#ioLb5Vn!|`| z%(23ayDm&IK3uM5s5%wc$e3NZmsRoxPK}{I{8i3zXkaJQb}7C9P9eRh`S^;}iP66r zvh4Vzk7q0oPI9-T_1-tu_z?Us)Y@t%e&xpnY=kK&@1f8nN$pNS)R#u~qf5e_k;`1pZ zXifR1j7iysniavZu;;VGiyZsL9nCJHvjHP1!a7%-N^9kgM{%Bq@s5}qFv97_*%TLu z|8IMMdB}KYj683Jf6HpQpLzT{#uI))hxry?f~u7|8AXCmZ=LwxHyf66swzLW?%wqG z*l`@hEQS%_lpQi2re!s}d|89>A$(zPlq=u4qC(p^PSIJ^Vdkm9{f*N|*8J8{mMTRr zgd#&RQ>*;u?5fUi1gm+ZWbUyPCX$jBNEp>*QyuKqRYkW$o))qLMk6y1XO&zQBSpKt zgif(YCU{ChPJLVW{I6nX*Iu!}57A@}sJ8l!rQM=Xku^e|m<170`XqQYdJ}eI0KWjda8pXD|9* z74LV_tWmDI>6JQW9$Y4b|DX(Zb2m)RhMk&!ROD68Xj|w2Mr$-QpZ)R-%YAeuzG3fV zWi)D-a2H~~#vgNCauSjv3&3pg_?W`Y4-NwTM@3q9%=1b@m1AF-0Rosp48eD_I?Bfv{b7%Fo&D?dv-YBAE}h6HaR4 zK#8o5)682=l8)My9fW+ZA%WtyF<$mvS73We#LXy4DleMX3M2iNeI^}RuA?a^Rq^(- zw=CF51SJxks>oe-PkTju&#*sbkEql&&a!uwCr~>Q5ijT1QoQSx)62~?<1+6cU?ekJ*2{T;KqOK!Z=ZI*+}DLVUs66!Iw65KyR3pntv6|qv=edmBK9OAq0IS5IRG+;CBn~>dvzu z2|PiSD5wwIu*xwfGt%=2ZF9BYP5vZR+{qCqyT-VW{zsE_I}J}HxWx%UhlC`V?jjEF z0qr#A^Zi&}j`w*a?`xako-e_G(WD(%k8&Zq`+;R`OGuJYo(YJHT^QgP2T+ zOQ^Rt)U!Dvp;xSbMrs=yM$TdweFe3R9hoXXl8gl- zL@23-B@Iv2n+0O84wv;#9T53Rl_ySVc$V~vpzN&SQ+9S?e_8xfc#D`nW6mp%cgAkI z$0w<+E;-^zArhqnIrR}A16k+*8*MOm{D+tvePu>2E0;IjS1Cll%}jyf?{j#PINa>6 zZf|~Tsr&=Yh@lZq=D_K#`1PB<8!dY*p~ep7FiBo-wt)^Pa2k&AO6e=Xr`Z8DkkKdt)y2D8$H&l zr&$iUs{V}h=mlNPf~*RuCt9IR85cP3vI|{)q-(=B4Fcr;KDLhwABC6_opA>y++JmS zfE0d7hMI4SZp~KUv$R;AjGJi}#4i^@dm!Ry&Z}ufe?D&T8_Jf0_7!Bc$~Vl+Udge> z{J#D;8@xX_It-f8BZp@toQ%j_^=X;g+m3Pe6Gx8U2bGNif*5nX-Z!rzEUc`Wdfzi8 zJPw+5;hUbfDuC=1DB(3ko&^`%ZKzgmpvd<5vzbGrNt5E*YjGI?G_o~Fah70Z@BSDzA6%sv3Q;iBK|+_X7t z|A;X5vc5yyyNDAf(KVQK6VtL6uaDe z?R<1oOM$H+!(k}puVQA1e;4#%J8r{6xW)w?Zpa>@@+Sv6=TZG1QD*MD zD>VeU>#d(QE4J~PJ!KD4Himx+I>|8?SJgQEKnx~js?Z^)Dv&-x+n^%C)chJEA;`Tdz+Ufql5tSjszESDm_6*sZs-(Q-(wo+B z^9<*T_Vy?IHu(j3vvrEH6gr7?R+4mOdbD~$i1emgW;J$MOfOspYDzI0&g^w^hxSy7 z7%`n4;_jifTFB!Dz*_;)+QBcn_kbtgJC7Zs_XYGhD(0FHy``z_!te3qoq6w{lUg9mGW4ug5e|q|h~GJQL~6XAcRw z4d`Sc=1>NMD?a8Y$b@cGjsLT>2)y{;4Zc$@s4Qhrjg|s<)6Bz1tKd*vi%J8Fz;7m= z@K$(#F3WcGKAxUxiAaS|CCMM7^W&kN8Z+Owzpqoqj-ORrxFQOC^BSq-Enn=4kpzx| z&chKL15ivycAV)7^C#Q~F(^0)-9RWc7pU!|N|(A%y1Hd_#Q-+AQyGPq&&A2eNLW{E zO)^kRcF00p=azfwA7fwR+6%?I$5b%_b#Y6(Jrkja#$#_z{io5_hq}3){cPgo&iljo zAi0LpuS9Jjg;vlG5nWKA={e)wzMk1zh4)#b4Up9CZawZ5z8XA%%|rpF9&2Ty;vzSc-{SrE(eEy5oNJ4J0`CSi zf?LG5MFUj*%|GFbKPIjBNxV>-86hHdQ3c-5Y=p%NrO${TOg*pxsv_b8&y-s)no%m7 zuk&ctq!naep!*mU?4f%z75Z_=ox5&++;nyw>Tcp#zIoer>=?M6>A&Ne)4(yYD|Hx% z826;1cELwK+*KP_+Z|AfEA#TX(z@ltmy{S!F;*=+F^___#Zh06W^XW* z=OyU&!>S`B1gHqywWm#lgy3Ylgy1eC>x%u@olK{3$VNUz6?jmq?2R>+x%pn>P3{2D zc6>XP6ESiUoS!h+h>jg0_TsaEa{EfjNE;uF&0<&NnF&m?4V> zG6*gY(Z?M|H33@&E?3h?WkKXpCzIJ+h&4bM!im>L%6oo7VspqG`0F%DLo8)RN%UC@ zeEEVc^X%_3MFMsg2Jo6*ZN}<}ZGP{UjLUn;^1aH3t~>kVblxc07&so`^n7xK$iWem zI!am(ByX{HLsAfUCT2{8GOeRf+&+i-YIQBS%C-C0mURfYLL=yx($U9mmf(MHM%W3=xT~yt-IM#D9w_$62si_*K4{v>r zM`+!t@X*=U1E%iz#3rf)+{Up6j3H{Iw|ID2C2ZX;nuEKzd7E<~SNfDV?<-I@paVNH zTrFE;J`Ay6bV4ExLDiQ&AKzJj8wr(P{4Nk!p7zM_%ws1+sN~W^(|;K&H9y!&r(OVm z_cSO6t9B#VVj|wko z=X9o-Ye*)=g@dz@rL}NdzmAs-707%0t$9uPLQ6GzFxQ@s!RL=5E&6?T|R)P)^kr#`DK0T{*?f1E*;ss52+(^pc&Fv5w694s(pJ!H=i zFJt)JUhwd)%enDk8zu{l`M!feq)uv*3e%1)48N_6aO<1A$VK(ZF2HsdD&mLLaLoR6 zze?eG1859D zM(`>csm%YuLNa1SL^9=_^%#L)tHHxf>Y+S3D1n+Ci6g5GL3y6H>XsNvr}c6PVyJnWzIt(?x&m0lrxu?L)eUT}8+SLk!x$p3POcBL=-g$6OO=lp6+RJ^v(-WGGY( zV|=ap_Lw!}$+J;+g<{t>rV#v^~6ExJ-yOW7RZyF$$`C0wboSeYLUXNS_eZGLOyC9ISj z7ZKd>+P?MBkHNdzl`ddKx<2mPr!x_h3*7iv`=CPgjiYBbjO|J1)yO>xVqv zb+uB4c}L^0N>PtokrecLb*)V$DcZGGa|NGS(jAznT=X`P+_6j)wY@SSXC{qP8kDW% zUMp|(Uchoqh6vf80s9jU#oQ)0KKX|c6-h>Ems~cB@;(rSC%}bLOBnB=ard$N2IGaf zygw!}Y!9w${d>3g_5zi^Sm*1#MlJn#&{~#;1PTMB^ka|vNfj`a1??g9!1Gqz(p@KB zP2|>Gli$*PPX_DiS4Ld%SsylUN?>cL|KO;xO!gbr3sQ6x7Z^@c{xgH-Wfa8HrhaJ#D=F1BOVM5T{F@W~XgZSxX7y<4LH&mEi{T#_r%ysC9097ZI`7H)uH`e_l< zB+5^1eS+1cJPbSr;z9ryaW>k{0oNDayrTg(+{-(B1l~-nv;Oq%p=>eq6{d0TT_1ZS zM*~IhYcl#L&0~JS2~ig`=~la9wmb#ftF^Mrwb!%SyE&>5aNvQ&M)vD7-W|x(`*%oY z^X23I76gUiK&R-+lVY6uC2DdN1#8bwW1TkB`!^_&D>KvY=?E4Mwx4u3vWLd)4=cP6 z>glC^j?V>R^l-$BW6xkgcBi{OWpqwKSjSEM-j5hP*@#2Fz1C`;<`J9dPsHnL4f@(& z88f`-A5`be^0<(CDqC%+#FBq|dv2EUtG2uG0f_oaHxc8WSc-{a#KeHg<9jJCh>NyJ zE`^YE+WSrYn9cm7k3unX}6o#xblQ|d=5p% zgXbR}-f`W>_ZNV!X2;XnKlaULoEh62F^CI{Xd?%G=rs7Pu|_Z@aZ??7-1${~hbM*< zg)=2t{iz;|7m-aLNslXg{G-TegT3*hGq0|Ux~;<}sHLW}iIy>5dN}?5kR7iwOv;$} zcN<(bq7wrfE;8;NEYp+x`6n9@!hF(1GE39eTPvUU+OjVeOCPw&ikt49VP1?!;)USu zJohyEy|RY@<4c42xaG~2RHm}cR2B(m;qTi;Pa6Cole^8=P?gv9md%UI)1d4}EFTVj z57Qj)CmiUoo;d9_Mz|5&p%}`C#?M@aewYY6nerrHe=LtX+{gn+`lCgpWF^2ZCXX#X zzuKZ0r<-jA=&JhR7==!${X3K~#ZkBiA}X*oNK4}(s3KG($Y;oxSNL3sc-szRoXiV; zml!*DNxh}wQi?fBr-^|egtk>QMvhp=6R#I*-{5%>1Vb@!Q0z8N`_P~u2>ARqo<|cBdE5EMZQZxFLGH}B*xK`l*R}kZN&7GM+3mpaW~U|k96i$SU*9-n$T*8}dWHlzysWQ5$?xvy zHCRtDg2{#vV5FqCMQE3>YOm6)louX-5AUe%g>e|ih_%d_S)s;O`8(=E-Oc20aL+B-;t4Qp6e3AQ-cs4r!>b=@#zL=QgoF1hy{c1SqR51+ z9U_y4&KK^pMqi~`MtAnZ*@`Xv2aU&x_hq#yooPxaqK9mT$vYQm7s&-_ypTaUoVI6& z2QsX5rSs3i_`rNN058LsqYiq%Y-P?dIal+1&XK+=(9LK*=Ry`Z>cUWJ$TE?qO}&R4u1$J`e+HqcWb_#OPLLG0}%95eV*yo&c`q| zHeZ1f4$n&p8_Q?ibmvotr2%(Ft-G6;{5FCfYYv%T{DY5*OcV}s40fmpcb*xkTmUG{{CHrjhn7*v^tYLzQb4cAsQX~O)DEqoz(A^Tb}38Z6k zwFn$g^Wi*8D1qqypjfhGT)CnP*lsO6$mEv{NSJPLZFb<*S|zFzzwRR`GKIGo|E}A} zMKR}BLmzJ&A!NYoOZfgp<|;EJ=CYhI2d(E}=xF1dv6>UyCk>kQysc_(bC3rgvh8VM z8F6-$3oOo%-Pg1|ZVnYF_MAeg0?$Q#E@!B$_>j>J4~Q_=g8lA;9t`sUSdgz3#s}w) zO=qkfR@V%90y7v_p6{;8rW@kK$G*HJ%65hCJRRPby$KQ@bG3gDy^zWkF43=h`8tBTULmb8Rl1dy2S0fV!r8x}x{LY~++8bP3kE zC;iAJqltn=x4y4Di_vHzMx$^$Y3^4tVF;1&Q_bweQ7(`lcwDTZ_9XSVImLz58QGmfNeo4l z#D@U)mzFnT&F;GAU_4K`K-MguMaxVc@W*bJ&;ZVt6qJR&0jgK!YBTaYSo-z%My&Y9 zBWZE(QxQ}$uj6nhV@0e?3C3&iW6TRa(R1ix>iR>$(6-%|BzRWCJLbiQd$rr&qc8WF z&Ab%tnRj6V;xI^ljs+jGFcz5?gy$*rxe~nABPKTU1heROI1-U_dlQQ8XW?!3>cpXSgX6ouLeF}<>7R}!Yj%Mmkg?Ck zsb!Xsx(f=9`Azc?s)VO#4t%l=G@GNv*4|Gnd4m064YsUby7!hF?Scw1@e2XRisVLr zQsj7?46~rWYkZb@Tt>FVd&>~VYSYw5bZN{;ef;Q@10T=7?%Yje9aOncBzYbEPz)9| zIumT&qjs79s}JoFI@V@K87&Ii*a&4Q4oko@EX$UVXvIq5$UtG``W20Wf@sqJ`1Py7 z3dbISt=8kJ3BZE-He~2={z5W0uIQU|9HZl--&cJmHK~PiwdD==x7zhSpGL6+1%=V$ z#ZM!LR#`51X4g?LxC9M3?fqbPe{Lva*%}@;G2(OSseDG>Af8EMv6DP!4ar8WA5LX^BW9;tD`ov?F!E1~=(+=E?x;LGrw%dR6pUya)% z>!5W291ZW8f#R`nR!o#NXvQbwea?i+@N0taR`e~^!(I(KmA%|B!g%AsShKI_$3x?S zM&nl@%G&!#L9c2E^R_a!QNqTG*XY53&pZ7f|5{QlBg;S2E(^te4K9x?Yq|tuQzHlaVw~kNZk@)`j60YzUpN2xMnv67{t$=8v4yV7$xi2MWs0iz-lbXoRpu+N$gHd5rydL z#Hk?eW1k-u!*!ZW7-kbpS*V?daSeF!5&5p6da>O^BJ&KyddO376sR`Dpt@Us4bgbn zX!*EaYye9ut~7q3=;?9H@3NQQ7eF!;kZ8nOyS+C14NF{T7^I*3)eGDweE+C;>e9JiuBcLF0ex85!yHtAErRn zLvD?A(+4|!LTP6ksWzPD4rJchkT-olE0_v6UiAJJc$IUy@zGs@H_AuEqw`R}>GFv; zqu|4qspO@xDy?&Hy&aZaB}7N`J4J2U1v#E3#k7{tzFMcGQE-dCq)|Peb5(*if{D!C z9@dgpSrnWD?An^cZ!Lp3s3#`j^3yilsEJt1G2hjUoXDRyJ7VtXAY;M1pCIyQEPD=X zKSxdlVdcwI@Y4`~d%Y4#jGln{_M z>|WFm@pdcyRa!Y853Tg@LBnY52TD6g=FG9M_4gBx#^un&Y$0*q>^qCr?|&}|vOh}2 zRZ}z$mX9TUjkm zI1^}Pson-M-I*chszB0V;TNSbt~QIKf}jL!2+4cf)gyCN5c0fDKB2ces;2Nl=)%2Z z;wF;u244*htg%xpuw{3%Y$!^U6s|epQ3nvCf+&~sI?wHb$u8&UXNgwiEde2D3~CY$ zc}sFmxO@++D%>G$s-n+L=QYFn1yaV5Q<?^qwVTDZ>ad4J+N@4}# zXt97?r}AO&4?DP(f!6jgAxd&rQjSG==d;fI=}w6WWZN{x&6Y2JB*%)hYT+FpHP^vL zIOuoZ#ZbP@15l!g88ta=;YFs?MZ#xMeA{hb?l%|vn2UV+%unB4(3-FiDbZFMdw&7! zp&oOBKQSCe7NL^AQKB&p=J+H7_rBC%cmS?|M&xo5d!0Y7vaobVK0+H-!GPpKw7o=V zU9Kh#3JX;Y!ZH(#?5k=kl()RpW%NFfJ@CIL|2?dGH9vtEsIF;4-zpQ~ckhD4z}3pz zO5j4obn zI$JSngQxpeQY6*4b{R}U9QkG#jwO0Jn$E2BuKh@nra3{H0li>|HVUnr6XMoP$6$+r zARGV?7d|}Ur>gZ>Po-Kb<1s4Z@RVDWXt4_soW*Ixu?X%SiFvoE0epwXB`^OOLAcbE zC;xe@{}>Kdub4FW&8C0DL=c7~s<1SMI!WNk(4iU(b?d_LRt0-}XS+JO$OE~DSdbg9-o zXEY_O8~}mVZX3oa!p3MDbMvV`los6Q{QU^wF(rF%Uf<+xX#n+s{)36+o!U>YOct*( zSwoytJ$o-TE&R{QGAa#i0n3@J7n3Es;TS=BybVo9ZNSzbX^P8iH-_VPB6to{j7E(5 ze#gyZM%&ai%PT*5ytg^yuLW!SqWzhG-f;sPv_%I z&wWvh4jr2s-uCjLZDA673m$LnBbnBfs-)@G8qYn4h&MRY}UsiIlCB8nR?T z^Kd}m=sF4!w1Ok7gT#<1szQTU@xGd?gg;J7+X>`q^eZrY+EUb9pTnzn^Pn3GoLv(wTTx6V}vrJqv3@=BtR*+*TUI%tJ7CvlR7+-0jG<@x`^2>=}o0D#8(6{ zrnwLXf1KP3r3L@uJF-QCu$d$5sVROXVC~w2C)c(NT01Xnpi)YtueOq`Toaq_HkFiy=v=VpgciWw42m1SwQ&T;f`vZJT)GL4#&b0E61^t(v zp&4$sVLT;@Bc0m(2T9<3%I<%dw+kpDqc{t@BVk$Gc?w!Je7-{Ag}9JAQ9L|Hl0dH% z1?lDEp$i!*vekv)yl6FMh|q-;h`e|llhVBd#t85s4!N={)bm4D@cG{o)i_igEtZ<+ zU72meZ?!T~E@2|-Mp%PcCxUU2WJ9hbhNSOIjxmCm$9?zNDV&t(@(OuD`H?zKGI$bE zNIK*q?6@oR+Ix5T9OBxaAN~R6ltWT%+N*7l_=eM>$$6&canJ=}xNs@bFo_@*I0_U8 z>ruGurq5)@*=QTmVvo{^)N#j56gaaudtz=`sK55y`mJQO^W3@+gh^vQ0LM{8f-Qr2 z@g6fo>~V`WQ~IY!xP*t}UE7k=J3JYF^@-jOHX_>d5*C$K%`FB}s&WC$o2Cz2ABoq! zbBEG&X>q9j!P!PZqfK}R_`wTa(OCymEJCj0rr$WoT`ZOym@R8R>w?YbgQe}zcfPY% z+EW&0bT}u9xW)yd+X||Q|7p1gD>uK5+KaY2y(K7$Tj&`xkGm1HU1zYBu@tXUKIB9# z%zOX#Z)IK*XJpLZ#WvXdbpR`84%arcE+zepct2B&h7ci##gp=7fU?dy9cq%~_uvMuj-Tr~ zKP5R>@F9Pyn)syhF%N1jur@SNd9Z%ii?hdm|ljuumj!-O2xyJyUkS;GalEm$dZ_Z^cfOF|ry z*;opCtmbb*>RnyuY2rpiKR+%Dk}kLCOJhquh7(J}UOh5a#UsiY7%kl}Zv;m8aj-CeC(RpS@TDfXTP5HdU5=y+R$g!zQ#~Xd1us_H0eMF4#S?$ zq_gy9Exij?IR8vOUCYm0?wU}Mqlkb0 z3905xWE#65toII94P=MRGmeHd;nr8s?(I(T5epT+^<( znHI&(*38Gl+-Sip#wF7Xw)lMVZ4o{Ca>QM=%SBo;x@w!63mUzn{SD0|92WAMMy>_# z$J(D44$jx_=hxU|-mUQ7rv|RXA?!=bgnQ7)7KMANYD9*V_Ny^GPLQ8UX`9)-VdSK? zlENSqZN=?Rza32fCn(qoa7K5O?NQXflD;K49R41r)t&ALGWNk{UQi6C)E}01xL9QQ zr`0?lR%e%}J|cWPr;oU3PN*6mWcX>M()lo|H?tV>OP#Gp?YMacq#Sd!lu1_+;7kvUL zw)PHfN-M-DxZbii-<1)z9)F;U{B(`{S{CaA)Ct`&$MRQ(?x3R>C&V^}V&>*A|*PI4|$XMMK$#99x%aY2 zDAu@R7N+p6)U8(8XiInJEW*6LZ3s39!pqf-U=W?NOue-5ZMV^dSgQwBY|$o&9Mpm- z_TSGcv;H_ERZDfN$47%_S(8T)zT~6jk447qJb&DCVLeMFqiFGC=aKe=r+DP?KD+bx zY25W_;L&0E!C}U7!i)_ZXlJ3>;c>9=xOEFgwe)KJ- zcw9u6w7uLr{7um=Dkp9q4P)ZkD2ie(TUrTSu=g&5bZ&idbKMZ?a~~pufpB6tk~`_I ze-r@9B3q_C^b}nsI&sAqNHw=tLrIsN1EPQXZX41!MiIR&u;oD+qSileA?a@>QY^wa zo&8n48rV?2H&Z_L-3b1ol@fV!&U?vo`C%p!QX&c~?EmMdvR!1Tloa~jjnrvM!dehu zEpdMPk*9K+r3IzOT``bJ?C{9%LOYh1i??GIkjf?)>wu#{O6Zi6x;#*$f1ebq*39>> zH63iGKM=5@$jkcK_`Ej{)QNZ1@;+bTn`>b!9CBjwNRc|K;z`m@u_P{jJmLR(?5p?kEA6!ks)X1i_LB@sMp&DArmaT9`l(4hL7uq0v40d$f zMv{E$xYMye8{aP(uwzi{aPwT#lTzEC(g=@Y09ad!wQ4JzpzV(e3YtsfEj+L`K=tr^ zumb90&%A~y0-8yZzf0`}OfcdXN>wH3r*83nAZKteJKD}278yE{wH0yB_ZUb7xxOl7 zFoI^aNSAmv3@#mW9^yu>^G(w+M__>S#dyi*}_-u{7`BsuOHH5MdXcj40%j9nx5a2m|W~wdkl8Sfjc5 zPy;nUk-n2zE1nJBf0%x6H=-hYaN%S|<|$y|YK_gmc3_4&h+zI}au~IN+3JGCTStoI zI9MVL9T;@`zWO1dNDseQCo1RK>D%XiM6*o_VcLs;)}q^i#D4$c#E)we9^=5nbzYCx zcCdWj{)YGgr8ufsVIPD~7~TYL8xn@&tq|W>kQ|CE6X0>LnXH>npjY-o4;2PIt9D8| zJ`Eb~4j?`w`xX@>MNE~2h1c~w|Ldg^2t{Axr%Nk*Q|&y7b?~Pp0zps?)+8ZB=wBlY z<>pT2DE#GS z68|kgv^EdEj+VnmHW*Um!65pg8#^taN9~^~qfK3FX_esO8-0A7F$)W6>ozfREZ5z_ zNM_fEjSAU>ir_Pgw&VAYOle1yWM!AmReytvnMOV+EJ(?vmur5PtJBp&M{@W7I`W{# zWl{+X@(nLV#xqA}iSbMXV2^65RsMUFdAB-?T`^i4)&VcfV_yGLReXB@i*l)sTIElX zw8G^8m{jrWv9)6}!f9g|OW!VPM!B(RiQcu90(~G$&^Kgy|byz#IO6 z$nW;D5c2n#pFdJ3BZd;?^OtEcAf)7C6Vd$?O~?1*>N{mEGt3es4k8MDE+DdlttXY- z`g}OZ_=$t+6@Hmd_=^sVyiB}`#Fp>0I&0eSfJ>`{(4=r6C)^9BC=u>e@jR4mc3M*U;EMc zQ^!V7YBn4ve-Fn$qLy+KFSh+D8QI3<=tiaVzF~G5!x=Rnuuw67-aB#Grnt3Iy2to? zWf$V|Lc$0_W5wFO!7^$`ZFX2kD=eIQt#vFdu$p`M5QyAl%~=?fWeKq=QpId{nIlVY z7~1<`(7G+Pw)gVo$Kb1!ETf}u{lzcZjnx`oap2WSYQ1KLhxjsZx~)?5ugj!9g_Fup zuW#ylH5;?^=jw;-z%mG*e36;bRz=_QHPHuV<*#{Q<#c#Ru*tV4P!_HX5q|NwONoO= zwyhJVj>~xc;tPMvk@5@#p@xawk!*}DM*<}WxK_Av7%zr5A+ar6Q3Y@^(&*ZFD|i7J zXfC?5bekUr7vwhFaamIyB<|x)h{Ya3QZD55eXnqgTb3S_BR0~@=a95^wRNar2$llQ zHi2rr&g&x}OfF%5WV6?)pHQmQ=d8;w3u7fc5YsBtLNbbFp zztRok+J*yEt)iMep8tf#tUnKbDNGBHVE*MTw8Um02vC>UWIFi!ck6*801R&Xo@aj4 zRTGG#O2rMD*9f>&Sd4zW3NAH$(_pP?MN#+lEZ}a9BM|Uj6G1tV9T|zpS9}4E|kMtJ5~j>c14jHHTmLT#5VG#b=kLb5@$5kEAjClVPc*SD}j33Yssw#J{>W z8v%LqSpc;YC$Ub9-tW~;)wizT<#pdiFdar7^TOC*w zvxbkpXItg4=l5rM2Eir=`2NbA({p13b^UWehZ{VSu!i6xZzhKCr&VhomvLlbO0*u< z_~{~}CO-s+KXs#DFt3QOKNCsd?2YFP`+f-#AHRPjbB;ivGyrVl;Z>G)*iQOwwYk8A z##KDF5X)#pih6a9Z1_CezcDui!M`)UvF0@3=JpzdWRrdD|LNfgwgW`s4_DN0io3OQ z%g!1BTl)}tj177siJ%$wKUPi4Uw$@IgVC11Kax)IUskdR>E&9pYr?FdT0yypdwnH? zQdeGwD*g)ag-jw0-1W2yy;=yw4)7gUBd3Nbq8U7Ed|bfAMOW?%$K6<9AeGk{X5i8H z>7tISuH0%L-pB9YY=j6ZOL1IP&?IKdItqs$7`$ondPnc`r{e{u`(>N;K9RQ0WzFGj z4%4@>wa0bSKr+!sHL9RX7>{wHLZ!HEZue`2{YG7CC&uly$w~;)6*g%Kc@xTpdG{{kCO*$e|I4EMWS=d&`IU)&&LH&NtKA8n)h;?crWn04%BmdD^ZUn z{%~d%p|-5r^?vB}GmOY~91ggP(i4hl)Vxf7YU2#Jx|O4PoqhxWOt{zg-cTAhpmjsX zp4ZJ7;? z$tYt#u_wjYn+Ug4r&clR2hJ@>P$ae(UpNE+RUq46mL%wrx}e?+e#QiHhtx}_2-w?r z+x&CH2NTPUAh_=3eRL%0-tTrHpi;LaK~Cdi1^3n4p^q4=Z85iBZEGbi@*|5e`tm;f zbJNK;h1D?jrl)h2c!R*_h|EnQz4Zhpy_fU(m3R%ZVcH`B-^Zho>y|ags-Ngrr)oBZ z;1+~m&+(>mhlqazY^o_1Mjb_N7x7`OFa@4A_c}J5Uw4n9E+)V`_44+V@owp{@m_mH z{T`bMZo7)Swj;_yn<>R~$?eFrJbZho25K z8{hpKfJ$FAWV{;)vC_QlnAw}m9x%&#jNy0|d;O3)x(jRO!tcPJOJ01NI`z2Oec1-+ zEnT}5zN?Av3F&$7b2E0x30Vib-ImWeETcc|wHpO%R7~GanLK1M_6bN_2Hb(Ydyu;? zU&T=;1Eve_p98MegdY5UikyB;b3}krJ1#ZPNa(&^yOLM%^oIP2n%2GZqK;=GxC<}S z)%yDe$rUz0<*e{^C%bu4g?On~;6nM3_p}x@zx^Js;9qF5u9c7N3B%pr_<(_UHZ=4D z!ih|Tc!_;{!QEDZCn@+~@gm9ff~*alm`_XYJnl0SpKB9Y#G<0M*m6-bUOb6&5^gP_Q8SRrmGfdheseUXJG*igwm2KKYdT0<@~08m0y1f)3^+b8BuyW0T&|mp@dQ{z&21B**&%x^G4Sy zgkKtdWN%RpAOJ0Iv z-9v!sa$(>%ScO4&#jnA*hUyjtcb*8 z=`$rp9BGjI)Xg%Q3F6Oo+A+@Q674 zE|}Q6qqd{Di_>r;#3)t!i`VX!Wb@62ln4TwQhu)7vFsBR6C9STQ;gGI7r8HRXFn-t z#r1q)otv)HDg0xfSNg1Ol0jClkuB(QqH&i-5U-IM`B5pMIF(9{89^*5`K_>1H1A`t z1QJ4g`0)ik`2t~SW;|MSM>sF*x1&l=RmKk3Nh#gBI_Rc%PbPKm2PDXW{%*n;{LHoJ z;ql}D0PjE$zblGTCAuKjKt>QZRhH(4?dMb((AKA0?!vjE)PhcKMNw*`?HA%kt%KB# zE0(z0DVj1gY@es%;I2_Qxru}lth{y$hCT~B$V9GQg^u>#;<)zf6U4; z9H%IuRG^bnQIs~M@RHuFwGP{DcpyjZ#iiXSaUW`^T1lzS6o*JKC+9bZZyd>K5SNTj zN<~rHnB2>IBiA}=%aOV^9cwF)6ny6OlG5=tLXv}=X89=9nPTB!&JEi*-9_rD9>}?q z-6x8oC~Z#WGT(@`E@53QwQ08vkpkqXGFipH(6LAO)4DMoOWEY~TWZtNrcab=h<32oHewCleHXQ|ag|0XaiPOe(gOn@jV3Th;Wzp|V3 z(vU_vjv#U~fn4;A4t}e3N{y>dB1KWAAi?rqk2R2dx{^ZG&FAzlxaLXXRf-tGRCVO8 z?=~F~d@1!Vp3jdf;ikScq>+vxc+6^E!(eV|1#p5+9z{{6Fwwu~OMuqY0_$p3OK=r! zB$`WMs!>3;MLx>%Q`v1%R20-enZA^=2p+R0efvl>#H%klJrqSznn{_fa6w;%%*j}! z0D-w%-<9T3YU_!+BLyY27TgJ}C-wHwOGa1#Wc|?^De(r3_MimCzVhtG?%t*iIdDt#D$wllNKV8U~O53RUzV^J~%`iw}w4PdbGgQ3}9!<_H<) z_)ym?pesf@On{^jRO*L2=1HO`QHf_%%CX6=f>@&{pZEA+&#W$j~%@h^Pm3?u9f_Nbtp7Eb@v{6TTsJr5HXB zt|&^oQsx{k?nhdWin+d+f4*{8qIOIq>WI+DAvGhC(4QfKe^0ZBb4eRoq~8AxY=spfG*2{ zW0Pg-#Z*eI8YxJ%%t0-68%41Itq8F%4aR}zgB%V^g(4->fL-e}nm1&6 zu#|S9%=uc2FRJU*&vX^DCp@YUDYOO^c1~FqVj2l-(!@#HY}L4ak|Y(!&Wc z6s%1(?PU3{C@S25LoIddP5lBnqPudKn;FnGt|dPWXusLJ*x{5ryn3*dDTZD9i(qQd zYpiafE3x$$cNtLO7sNwxLrLHz?c!n|iLC7>&7Q0T-D zPyVo~swh$~BKX2>rby6kg81qbC8+B95Q!$E zBo-JVMPi#^AGDoL)WWIbtzMzXiPu>Jp&+g?fgBNj03sovGk51|8<5C}Ukio0BE}`P zjpXy>wp(7?dEi5pgU0tP4e3qedsSX*W%j%APMx}+-R1{?UN~V^&MQMB>N5sCG1c?Q7BGpi8AeZQ>mL8TtS?!CT z+I{gknm~T<<@KleG-^LOVXTzarNsGF$W@jxmFIPcb{s6(Y=GmVqRb`9E~bx^#SsHX zBAS>P1LvJnFFB%{E9bBsr2h}i^G80Ns%Nozxi5PX_7f)mhHOZ@{m zQkK|83SleKrYm{y)r(8Xc-&Usia0A<8cieGZN`2nN?y|EXJu)UJ?aw!03X)A!aU}q zqMQ<Nosh^e(QAW8hI$Dn%T8#brn)zDg)@RfJffcl;gL%-VSkJ^Bijqwwk@%79dD zMWNq1n`-N|2YhGFyNeXiIZ})g2Q6?#30LY#*p3NGt7)^^dgTzbYP(Qq-EA1sDOVan zz1wQkeke*_oH?H`JwvtF`V3K*6%<6Uek$y(UWjE49wld!^ezcDEI}eB9x_bg#pa4p z#XlL-xMUKmzTYVo(Tdq1`-Lw0UdsonqZeewG!$eOHN-s?G4Z&n@uPH8t^2T+~kt=N~neiY0 zGjAhz=4k7R5BW=?u5bsE+n@lhZ~rdn+p!h;cW;N@1N)(SWQ2n`m`Lk=5;^LKNnDf; zKo6!e)yZ)Vw8be>#knk1s;Jr&O6zNBj+%(=d+uF8Ly8eFR-l-HVu$|S+c1{cf-%KT zjx9=o;<+-U0Ko?!Xe>koH%&C=Zd~wELD$GZ=)>TR0=Vvj!_ZB4;c9}~@w6psSCa7A zmL*Dq(ZN@yB01)J%byYj&s#AsX}?@|MWrT6aYB^Vqb6YcTtn9>mY|q|13Q#%j5VsJ zU=UUom7ius+%akVq4l&lJ^_7uc0m8$-Oyc1Xsm*>q@=Qfmb@2cAVE$o|9En$)aR;<#bV;l+w9U zoi%`R`$;j!z^<(vgXE^GNw?*Y#9)r7{~>fHi>I-^y*v4tcJ)0Wzal1^DD8r;?|DS2 z5gkmWlgKfTTV}dTN2=&d71i9<(xhIL)<&rvE!9~aDZ7u87=!G?SY(IIr_jVejz|sW zh;oNUCWMG3)<_pB2KMaWHz*b+2;NAnPBCMl<53bim`Xd7WA3)Z^seDND^OKT3sh+s zrSz?42QH;Ksw3t1k7AL5J=-}p@zUf#j>rt=h;oL;HJQ7f$sFqTk)R8*$4`Y&kj7=f| z9R+bM5Xcd^g1Or93~a(!_wU(hzG5U5sw`qj@TVl;4xvw!oakUF?Lv;Z+O+9h+rq;& zo7VT%r($So8*WP}PU=V<`Zhj>F^YZU+K?cQ+Qk3@>`5tIY?1w}=tlYd>K++} zp8b1lt~ID*FqbfZKK1yx{nTn4GWJwRP%Cvt#=V`SDKxENMX8R4PT3MpPORQKft>75 zk`O+9mehyD7D{Qh6eqRg-MMn%m}M;MEn$tLPQhHlz$K{r_U*DMfefv&BwbOIyfkgj z=tNaofmWJ_C7g`bMPv3#`kN*7!q*l_d3e3^ORWUnnn&H6pX8qaYZdAc%q5Iqf|`D! zEBsXlX974$MX8yl%qN||N*mCSY3gr8PRmTe7xz=Daaf^cg4Mz+^3?{x#^yRzPE^#Lsx-M%$69;6(6y#u`%c#k9~TziN{=- zLdg1(CZ$lCBSk5fx=zjXlPFiy=`N~39G2>|MJah-W3H<6T2f!CA!xe%K6He2bAv@IEvx2|(L-FdF2OX(juab>Df z;utt?s`FMtA6k&!;e9sMSlocF#$Ybxz+@gXG#Hlm$|0S3jB`Re-wrYbDP`BE@c1dM zM_s34y7SDYYd%%PK}}A|!R?AGO{Juc*y`1Jsj=;9sb{mpRs8g5$7n3cg`Tqz876hAtM(?`<4~gbEILc_ z{)^UYX=?6d%kQDmsnm7qr901Ty6V1B#k%fT*hD>>aoebOTNTvMpsiY6?JC=BQMyMC z+EjC>BA81!0QR8z2-RVVKlqSf-@eEoWbatV?RrhPR;dp9VCMinJe>x=}*|SgpF6b={##>eyWOxbwELCQvY#OBjii0WwAO8a3*g zn6RmKMfS;+eB`&By7wX~|!fGXAD{1LaVv?_J)UzH7D zmFl`x*PUq?-4o^i8pLE*wg?4+x#9yJ-eHM>s;T6Ct@{N^yOhlSM z;bxoEPo;xt^qfj>FSWF)^QGkd6PG2sZ5Va$e-+Nryty7biQtGn~rm*rhJMyk9`eVPU^Y?25zDr z?R3HL{KYn14!c*JY*Wch{P5GfEjhxWGbH6K;UZgJ=Rj`do1XzEz4e(e>&PV<$SExY z%|)7%C%)xkSox->TdkthN`2SUDCun_mKN$F8P{Q->g2X%sO$a}bKJ6b=vria%BI99 z$Lt8bdUuJBY-4to?#L~>@HFU~F=#c4(pu2mq&a#B&Q(RJ8>KI~=?)W13-zN8*9mf2 z2e&Ot-S)Sb<2v87nZnSWMG-?u!JIi_$;Yj+N0c6|Y9ObyIy6UDyy$$JQbC#+ofZ%18gRfmCdw=|m@|Xo9~#o4Gs{Qm0e8v&7O|eITP!J6ji*=}3dMNCT)#bNQX=BiCX?Lp4LFsVu8G>hT{R zN2>==Q52<3NngMdOLMLJC0`uKUCA!}NJC{d824G0-vml+BEO?z0bQNPpzi+5A-oG` z0=TY8OkvkWgc^c5>!o5mDikrOJj+H=rXqS?C`IwinbM|Fx}(I>T zUouI0{GVq8s<<=fxDAp;2D{7yL%yo>*VWYpvw8>Nh&c~j_SUdmAA zY!^-PHCIZfno9EZApJ_gdyXbqBal0oOLmmjM7%7kJ9!~LwfpKG=!3^x@;vyvuY3WH zd(!y;J>9{hGJaepk6_2?5v&<-3It|g&^I41-gLoU+&2vdx_W|gdhMn+D(*eVckjAJ z#)2|}%kh-*^ z;{h1^!#&VD&VMs7>~nb3>@RNPErk1pC7v-QC>_{LOd6Y!N?!!&eEaW0dC~)pEsdp& zBT3pA5qbTS4fV78;0W}hrU!dZ{qIFzrZq+BaOfOMCDR~3gJqE+ucfqnJo&y6%Ero}_`ZE|>vVeb#egC@6Tz~HA$H9W%psWEHw+uU z^7F(oop#O%crdzP=gqhi%HmIXH^q#WTC|Ot?(^ zPAasSZI#j)Lm^isw%d^uSX)Y2hO(XDB_IcNTodzkAd}(wOKd8N-+OkOyH=cPQ^`#H z@E>_w;4!Q31W7t+;`&&=s&kDhWmnAWn(mwob@#%;z9CL8>6;FV`lexi8jKH*z^=O< zglPkVFm3uY7}>oSHhupp=y_lh95Q`2tUPfg3=IvjpF@v098Nm*WLP$HF7$2P4O_l) zIR|pnXU>4dhb-m5Y!e14aPxyO*wqV%4b0>_I0rUvgE91b#L+9@m_rVQzi;(M z7{;=B3l{L>+Z{LG3kQDjC+Isk0zKoCF!K95V9o#jAB{>Dd z?mDm?HjeINx$D3-STnB|UjO00hUdTKbueqzEa*8n2D^Xod)V;vYq0MC%Wy1uyL({c zFaHR;zjrnC9vFpry@RP^+Kpp6vwHvz>z|1SZxVLh^Dw}{QJ6hv4or-WagaEE{k_mT zfql%_|DN3kcnl}+T?=c!^kWX>XdLG+TmXCMG4U6F1bx`v@ym|zj?paWgVEpLnc=?+ zChuAeYybPF9LUXIv=C;`oC#~MzZEvG-@ra21FI-)MOBM)eaYRWeAfu2z&MpMoH?9y z=wYKvLA8NgQF{7MdE7^AI+cMPn`}zRJNkaR-h&5hDi8VE602ih@kEus=f=~9?;>alR% zS?9p;rfsl&+ctRBJKhS%Kkc!w2}WS&HMhdrKimu#KmWP#_P==_T=?vZ;jFXIhTHyp zGY1w6Rvrb@_m9Ks8*YOY7%;u}?>_?PJ?|puJMs|NwQ&nPe8a79q_($M5uXqWZ zapswD_w9GU!5zC{;i)G;7Y1}2zyDj9Ic++;_oE+%XJ7hK?B7KgnoqzjzxxBsn?Dy$ zxbQqUb@?%H+jTd<*^fRKp7)n;fbqi@!btZd28?rH*Sbw`#)XfCkwfOf$m9f%8BMFc zu5OsIX%DQypk(>V<6z{(!(hkc2#li*S&iZA-pMi8Kdl#bP3wkTFbd=Mu7TA*y&6u$ zVCemy_&d1pdC!CkpZXLIY96}z4p_AOaG1VuF5ivZv1ME0m`*=x8FW9m3D(?wKRn?n zPl9)U?8ET17d#gZKlD(z?dF?dItJY{PdXa9cVb}qgOvTBI~N8Q&x1XeUk7{EZHCvq z^-b`~cf1)ceC9J?!Mp`<^L2lM+0$mgNzZsZoVw!J*cdH+rEpLD);r`6WvfFRD6{bxag2m^a0{d{B%;;uw|NmZPQ*ksZRN9q% zb3c<@Zc1uvN|JMpsd*_%cfh5&+NilBeoDGCH;&gAA=zX8wua~W@ASD$-g6Ca3*4E@ zi+f^uPBK;%Ir;M07V+rf4y&YR&YTGo%NM~9cCUh;?OzQujyVhlhX(l*i@Qe;!cF@& z!hwk~e$;;Nf$i|S-D_dzzCCd8fwj=z-w#{&?}5+%;9Kz7Z~YJa^pC%V9(ugGZ6^%v z84f-@62&ndiY^5vi|@~A0CJP zjk{p)mhF7E=<+{Z!~Q@2{cpmC?OXXS-q_l0@bI4P@ZiCnJRbWdM&asRYvK0&TVN-K zWAn~E3EuuMpMZJioQR=VG}NGd@1ggqVc;^+(~bLw!5UhK%>?f3zVT6bcz74A9^MV3 zW1}$n@Mahv9fcDfeHL6bxdpzp^=`Owd=nh|=rizuVBLo{@}q1DoRh}18^^Q{8=>}l zdwXHQu}8xH4X=am@46rME}H{$=g)`ny$4|0_$2ggO5cB2zXPW4H~@QAZ-AqZKNcoe z9uD8xaUXnl=lw8v_VMtZ&-?>C`r@a+n(_S=V|4faZ7{K6doKUGS8s$B#~lNEmd}T8 zZ@(A5hyHs{I2@K8x-2rLiqcRTIr&oCDxo9fBGXMSBPErb<5%-A=Wx(Lhf-pRN|H-z zrOIF~Y1H!^jUq=ZpKY0QfWnuq?k?DZ7yOMQ`(QoFw#gAJ>4F|=2!oXU7|2m@Lkv%j zV}2BRMV`X^)tBXH@}Ao z48mX-%O}RUPsBL-+%qx4{o6A(0ypp53_srS0NlE7iwQ<;UpU-C|AW(~L2q9l?A^Hw z#>b2g7qTaxB=p#mK3vd0FaRTShG5<3Uf6B;WNQP_aKHjeCv4Y>dO7ZdG2^g`d>;ne-74`1}}ALZb8+MHSNFqlWg>qqv&trI)o z&Uurtc1|}2wj(f%<3!ND?8Pw}#rm24>AimY$6)l}K^UAh1J=L+-XCgXZP!5?&*P*C!GW@dDW#s8<*HN9`%Itp$~(x z5aXMCkYBpnwiAO#+EPBm^rLU?ESS4sKCHR-0T|!7okBcYPP^U(6PtFzBOm>5c<@7C z-Slp{SgqwI%d2ktlBRosAq-3az09CI^5fIru_GT_@_pMDDL-o69Y|MY6;*}2brCmVX` zpTJ=6&NckujAM^E77ks!1m+*Ql<#D1y5oNS$`KCC#>QaF-K${u;6Ye;*fM}#6U@0J zjcFxOs~Jn?r|$o5-2eXh7?94N50Bh)KO9)Sk-vU~#%^@YW?1*7pTLeQZiGqfGj-M- zBWfvYd|m(RAAA^wH*7OsTY|Fpq4lugku|2HG!Tl?K?G-FknoXOm`!H&8vQFd$r$IV z4?}Xr{4VP;2kO0EH|Ba!@BPup>TKNzs^@MX|@!V!G;W^mmOSathd z9K?(akMLKD96o(6-211S;g0KXgf-i@!Xvx3z@1lL2e9DLDtlug^R7gjrZ`oO~AL>G+Q{t)ckycG^R_f(jE=pyJ^zXNW${sy@3 zj=T8L=KT*m05|{O|KQ#~+{j;{(RKJjm@(P~n{T=kc5c}Q6Bt~zI z|A6n9^&hbqBT#3OVUq7k9kv{{uUZ4E@463mTzflAZrBbJ8+X9YU*8CiTzMTVT)YUL z{HmA0_IU#^Z`w@QhJo8dx7-0;^nGlj+!82jSvB$u+Rjc8iulxw^M%lS~ z13dkO&xMm7doE0NbwTgqxp4Lq9t%6SZi7`AWQ^ZeI6xqHT7I)BMV z*crM*Mena$Kf4EB_}16MiKm_dqx%oQmOtJGYkznZY`x`P{<@Ioz4lVramWnVI(h*1 zEtm!uz5K;6W7bSqf6bp^)qnmF*8T2A{zT`+s6Vh|CJft0r4=}1ngx$JhDN*kC*d(E z`+wpE=fb|;NjUPtbKx1!dp5s^@!`vU2@n16R$B<|&u+M63sye%s)D zqAte8M_#+8)0~dA>~K^?!o{A{c_ou@#4^4#IP^C2!CUdwnnr3k8BWICVLniW>A{^l zOd=p!FPcjr!RVr2Wq)ZfJvyA#-3KQPPlI^}Ct>{zfUSMwaQwbLzzy6peGFE2?Pt5A zCZ@rPeciCPzYA^~#2^O7;OPE2u<}4ZtiS7i=$btp)-D->gF`)V+O&l*XY+nob>}_& z2y*tkxp2ry$HARF`}k9!hmZBc;d{Ga=ODms0|#LD_z3iO_rP)3#u0nF1O46!tlQlW zrym%Cq0vdWf5teh?-_w3`e(su-E&~m9rwZ3&0CMF97&hn+ij!pNcXVe`B`IALNsj6J*&CJtKwH}~#^U1RhyjBpSsxTEjhJ8Eza zoH?`*V9Rb;`{2W{Yu7GVv~&q9Id%oy)3uL39ZR2VrJt@kd1wKwIM53Z-g+nO-@gxr zhNi)hC!GLmW&zxOU@Ht@5P8ahLFi8z(^b>P;P3-Ie8+3;j7hk+=K#N7ZfVy5oV2$e z&;{HvV+3~KxF0z%8%|Hze|k?K{kp>$(-*_sz2or6y$|r0H6MEP3fMF>2{-P;F&aMz zb39}8$eb=%IxquHP4T~LYy=MJpAKjB%!i%#JOrCJY~n|=$FDqrM{?URj?eTFSUtI) z->a8r9$)@c`=!B&CvUE^TA6YLzD1Ca7F4BV-^epS20ZZ}1zSn+b#~uv8W?+DLX#Y(95@PzfuRU0{c4QB1 zMt}5y2J$r@+oWJfbo9QoxjlmsJ+;x_-Hn0CbZ%?Y=sxzgEn*McV`D?!65GA2CPdyscrgVWZJjQsPhFI{Qfv>mww`kZ0YB&1~Ay9 zpp!m4ux;!>@M&J^_jKG}`YqB!2WIk@BGV^nsV`)^5ACSGG!|)Nx_uObtKNS8nKTMU z=~&R6!fEz*PN|nP?guBvxo>&)p90N=z1V*oQ`$%Rq%Ge~qz`{2jL|ymGu^6Qkl~*m ztw$6U-_n53ds(*B-4MD9Z0QKrO$fO z=q@$=)X&j@!hOuHz!s@yg&R!)eU;=c4CXuzt7yXnbCaH`G7%?X{D+_BlqZ;zYF&}& zc*d$fn?z(XI~h(!3K7f)sxVEPp&*zG447yxfefQO!5l%mM;CPpVCXR(#hvs^2n0Qf zldlV*poM-}fG*DTNlf}jcd;l~qkxd~bRnkz$LPB`cp+C4=z=fu?8^i|p)Yf}rxyKs z(*_at2kp4sZr+lLzR;I~4k{Oa^rruQ>>H&iXrq3Ut`B7t(-hE8OQDp$lD9 z7biZu<9U~`%%mhAt&`>~CUOV(6w@?i_2=ekxa{?hiJAbT2jvLm6i z_#h}1A0zUR$3JbU-(o}iPJJhF`&yVPt0_ud$()xRJaK8)T4DE^+K;juZiNAL@P#*J zQ)L@ncr}sn;y@1lP-sT(=*9;96M|rlf;U%+;X62}V|7>-wMxq+kjtnzu3Jj`n(^t4 zF1*MKp}w+=Fy)o_^y#+AZ4gq|El;xb5!O#`g9vTpUlj2ZC$7(9BN)BEJ(r~Vf|SQ? zj4s`O+(x86)X%e`G@R7w+yZmGz9)0_v~s`7rWNVlh zAE|};DalQVj;1J{Ntl-!swNS-OmUvO-6}emSfvVIN(bVsH#IFiDV4D(-F1P6GffNl zs)jndZz<}!MC5RuyZvOtpu}sEyMc7rO-a6bdtqeGLYpavgGZTPfH2=RXL`y39c?kL zqV2Blf0ByqCtE%HB7q#a2+o1X$q+v?;(1Gg*@XL<+9VQO8d3}MK`v@`BTh=_&y>d< z%Yx%sMU_%$Mw^PF6l1ELr_J8qDY!09boba)dGK905=zGfUuY}v`{!JRxs7Ku!SM(T z@*E+wiJ1B8WbSxsQ+fK4K}{~GvWQYY+;Pr1)&HqQJeAJew!*vp0+Zm+67fCp?#%FWc+g;hn!~lD9urRn$V=81a!*$o66^r zt|1L$vVYK~Qb-7;k_zZoAA%sx3Wsd;h}Gr=_mizmU_fF6y-IS<5YGo643jX~(~Ykc z%^T`90m*MwzN@aN)D<}{8ONrELzla1F2fo+q9}?|4b571%4)X_md%N-9+=F!Gv^DX zn8X4Tk4YMZ@5tF0jql8Hi2?PdAP`&Nx+i_U5lym*>1}qhKOvY)q=utfRaL4~Lz_wi z$v94>9LiRi3pyv28190tgy^YaD196{U|>r;XSxQ<59A1m%S;ewtSL&9yLBXjH=5!K zQV|oOc@FF`PCnF9G6|!7p4*a%6>FG0RaLE_J*7$HIA&EG*4$Nc8S1=Jlqh;mGz1;y zx-m8|!=^kW22k0N6@+-W{j;26*c9}*w2CZ3}C&Rvec zFb;F?#L<@nb8Lp4u662`U04sufLyfi)#EC>6vv$dYScHyql4O(g^Ib6< zBTA0<^}$4sy*uZ1kgs(wxvP?44ecl`NRH!K@Q{b*DHU`1EZDH3D8;V|<^F4E}_pGb8f2H~4IK~C0L1>y%NvD<4Fp90! zQvyBzlm;+1G!39P_TvYopN?iSvs(`2C?&6?3LDJ)^g;T0k@Kv{VKz1}026&B{TxQF zZsqK|(gEZ+)(xKyI{%dRAiP{C9fK}EH8IhT@yfJWHfO2RiNbCB9^$cc0los>X5eJia=dB;5T)S!8!(^bh!eDSV@GJQ1) zJy#k?8H3%12du9T#%9g68B3kc6~6Q4#$+78VV-p+EpRZ$1tP3YBG15!jcaSu9#xb{ zI5;>6(39SaRJ?v&G7XfDCF9taIW-zK&2&C1ic$qrdFiM&#OUpXk=gTX#!^GLl0^`- z+4#&V@z7CP#L#UD%yAW|ijpPw}Rw^KqIv=S!VW9h%aU9K?0O1PkRk8*Byso;janlg}y_;>vDmb6{`~CW;1hsa-0u zzhyyPY6s~!Qg*7${mt~%k%Ox=9A`zZ6ZLOFQ5sGDSxxVe8=mb3a=2~4Ng?fpR|<3U zje|NXLgoh`vdOq0d5cBq7RGeA86Fsf(Y{{nf32hDw$o&&Dz@rxX82|dJ0yDj$1kydyGw+4xN6RK=#!qElKSiYXuK2 zJito3Q{6SF@w7`nry^~(JWcfW!syJ|FiIbEDCK+Ps-K)RbRrXz=2y1(4jm>az#|dz z1#>l>DAatoVcc{9CVF}>s2hZX^c^p~-MAwydG5h zT=W#BO`s=x-Q6(R(~ALHKmUru$n1GAI&T4tPM-~vy}i~jjlAbtf*q;7f-f=Q%ZF?c z+C~C8)*8BIz4jm6d?mKRj645`3CA=@+aK5uiZJ1`b99qV-Jr5;1&`iTi|S+(X_Ihm z2ydRS3EViPh|e|!w#j3tWP)?fzN8Z|F_}OWPeg2qP#=7|Vqg=?(}`sg5uHg!bv9u) z)+T&$(kNDC>e&o$q@EZMn3il@&l^{V#PdPrD8Y9ZC6ZL0RZrpdAYn-e)hTO6d`)9q zpRsaxU9}s#Iy+^E$Bthd8?#2o%YzJV!mUjqj*V=2BU`hfM9@@_AmVmNq+CFqqYjdl z2|r$+RZ^m>L<*m3SRu2HW8ky3>q1zBDc3GoHykA=ja{gfjH{%y%}5z<;_D@fEsC_q z$=Dhh?@y2o^_&V{%vO>CRuQp7B6ikSCLXKAivEJpdBUGew20j z9<$bkl(T?~qUAN6Gl`XLK}ETv$ZD9%*(S?S$qkPwzGN-Bkz$hxRPjW_mT(nun+oG} z#Jr-Kd!dUHFR}T^#+uT*Bo!30i z1WlZ?$&;D>sG?C2alewpyl0M5hU{PtZJT!9a6iM&CgZb->+<*^^4cMRX@NRQF{%jY z67dzIE~A!%V{A{dXzl!-(y8>EP24(P?dp46ea$IFaA%;AWL-#-`jpYvTs~ZK*kqaH zX+~*0!RhZ=2XZY9Wv?IN54Q<(rlQ40&aEojqCOijk6KCSL!c~}9!C-K-I=Qxg(kp# zz?U-m;_=~io7Pqt{ZR5zD4=r)^w|f?dk;-iS?yQg+UE)SlKuNj(tIURv<;;+s=a7< z13}aU>S`V5#rjWeCQlzcHi615%i~MQMUj)b_9eujw$-HGYf;pHLTmA97|B;LM{Atc zbonuN=*$CG%G3MiD4;XH4q<5GW7b;8I^<3{Cw=x-hnuj}XXhbema~ph8@U6jm|eV@ z@7P5*mUu-!`K%n=3bIeBPTVjvtF?G}hP|`MWO?>eU9BlejSG4{u#r6N1U4~aH=D;# zUc^^kpJleKv;mD>M;h8%jdPj$O2Us+DS!)fU7R0xu8R#1=1LvN8l9OzNg%19%pITu z(P~DxK_~``RdmOwc!<9kb>UZ_EF#O_!%`sh}bR?*fJ9R>v-kB?c|DacDtC<`%OsL?Z-(k>h#l^goLz=6gEM`_#fwn?ZNkuECm!ffoOl+cWN$UJ6Q{(*uq7$Fe--xCI!LP*FU!$J zqT3vGUA*rNbSUUfu@pHa^V*hpnx|2ynP$$9I=4;ZAY$s`Xv#KD9Ar?t7A}K%ciQYv(nODr4C& z9Hm_mx~W61!a%)@OSmyeCZbf*n96~iP|6rs9|^7!TgcmXl37-DTb^c?eP=Bn#!FFO z<+R-pI&N9<>`;+?Otg&`#PWITN!D(8lUP^CG(ciDZZ=Q#d`3#kO#ca)FZnRAE87@~8!?Hw0JwjNT7Qpw@EC2$8Sn#qR-av^1oh0hi0 zj5?vP0;}Uqyd3ksDqcdvFlbAwoX4@xk4Y!j&hT6KT+8rRFIs&~CTt1UH#2q!gysV_b`vwar%gFq%reASKBb zaiW$<^<2HrCVzVkht`5LDGQ(PJW_~+3VHqb>$&3Ffe7N+37c)nijtlI*&J!NHD>x8lNM zQ||$aP5Hz&T^*)i(b`~QNIkz@*}wZ;=YsG z61`I%y(A=6bU~XuW^o#E6G5qgMxFm*J0?|9yG5s0ntc&pWE&Urk_p9J?%rpOMD9%;M&H6wkY|%ie=PyF|0kG zk45V$sT5k{@+_JuRK1=iRIJ)x7G*jv;Hz%?qqG&lJZREdNA1@*7bWJRJ;<{c`GdK> zew$Kqp^sMcQ^r`Ox=1OE6h-YadnNtmO`0{9B@|bx#WtZr3dL)<#A>(OMX{Rxw%R^c z+n+-9YTRkAjxRO3Q92mnkk>v)VjR-#J`)*LsXg`=#%)%nT|rX;!Ci~P=NPRM(~78(QXL!x+<8B&0h zDy5EB{O(f0ZW{7dO0%n~VL!QDmDMKsDY5@;N7ihtwLETNb5#$yzrD;}q_tP$;itB} zKdMjyV?#4+Dj)fSxq<00)<0--4taJ&Y_e>N_-Z(rQ>MP~tTD-k(9GTC0K-5$zkseD z9SD6!yeBplEhzLrG}Sa-80HJKkb?0-ujTklrx9(`4lNwjE*@3Xi&bgKF$($^>#PKd zRqS@Dxb2tSmx#Y+?`S8GFvD?ZxulFCPVo_Gz1p@a>N#FBe3pHFkM|G3ME`)zf^6WXoq%sNqnYCe7t*1!~JTpu2PiI0xs`Y<2% z%e6`J<4|$R#P=}EUye4~j#3w;LL`r7QC}YWGIpyPA5tf)ZeHJ2?MGFWGN^}7MMz$U zl0X~pA@S6$uybv4w3T+~3rveVdzFWgne%NbKZSz1NqW>e)83uq9hALv_cp%gNh6V@ zFN&wVKvh;7O4BHGc9eB0r7Z-Q_cfEJX$-DI-7l+#MNl)VNtU`?sH z32{)*zQ%p0wB;5>x|USOr}x|XXIzqBr5eI9Zs7TC4`FJH!C^L5?rVOksb#I}G|k3l z&MEwel_(U<5u*zZv8jT{j=KYpXE4ehusR)p2u0^ptJCcLskQxz`c*nCbsXZ({LZtR zOtPrdXZz|j8ga5GlRe%k{ma#LkCCsQtIOpVv38S<{u+;Xb18kFdh@w?)Nicod=v{z zU(=IVf0F7K@LQCTxeINo7=?qm@#%A6bXM#ZV9h&L!pJmX(5DnM$E%UD$nC2@qh_VBl$-Yt?xOuI7GZSuTo@lL_9<4Oa4<)VELoA`w_0(Ji|lkB zTc1rG2UaNoIy=f*1@ihS++IqBOkX|&(Ir<7-$oa=@z<%;`t1C5<9f=4nxs1I3M~lr zUlh!!HK47C`?R()`r#JGeI`_m&Wr@3M87GBU4?zNgXr8<>Q8jE>pK1kzZ_9Ydlgg5 z@fs^jZ7+L@R?TF04-79@R&^Uy1#^@A12DYgFq`w>?M$8?qD?NdD)&}t9(7v*e0UnG zP-S(4QFkJN6ZdHTf zR!VZ<(dTKas{SZVrL40xPQCo5lJ-ecL3G7FJW)GM8IYF8KPvTDNF1M8?&IZ=yz3{; zQM4@iS1O2jS(UoCyhEM8%4YCkJJB(U5Q3`u`S`#5e4tM z1;#$#NhFt-dC#vrPeo{@6V^i+-OKV3FE84r*jLlnM%5`yLmE+XAuEGtg@_*}&ta>m zRbhh`NryYlzpqZ3eGZb>z*q_TrP%4fvZFCjqq0yc|AoZ71aL4%H_9*$WJO^xGCX+X zsT^I_jC3KbD|u|PsH$!)4OW31*G{DHepN9TRkabv)%hJ3ZYG5?eP!dchEu!Dy=&}# z)c?Gs{i%7MQoGsUwWXfOuDH9zX?*FR-E0p^nYjh1wygs7N}WUX8=FkexF2IPX2XHQ zj>WXusq_by*#TWmk6Aegq}zc#Juq_AsW3Wsku8an=LjU&Bv#GglTCbfIqEi(`pvP{ zp{jkfl^Q)h-u6OeMsWsc7_pU%$3fgQ5!cG5b4>YszVku8%9KiIhl-uYKEHXSG>UgQ zN><(Y)xc-(>T>rbuVHS7^{0ip(tJvt#RVw0UE?i}Pqb-);~#mSTTDjgEQEuH9gPtf zW}Hv)nwW}&_Q4e@tqkbgeAU5RxNd|lN0%QD2M=A&AF+)P*dmhl>6l0+BtaeE^P2~@ zFIuUNxJRecscK)t`PNFL_sA{HZy6$5pC6yDdTRGjAE;kp--@5FEwx|X?w7O%)#66# zx;}h5MX4L{GZpjB+zU%{p3y;FvCpU%pXXK0`=mZ&8e^k_ha3STha7HfSnwrChdTK% zgb`Ait!rZxh8ph7iIYk6$Dh4mnOL+84xDf*jLx1DngmoRD)E}QN=!>Ohr6~S=ltv_ zT4|r-eJRv8`K!sTl;$9#G0CR6D1+b}3LA>qxpn zSB+!D=PwV5_Eq+y<7of$I2G?<_UyB3SFfqz@k>1!ojnisAAKT>&0QG%get*-S||k7 z5n<>KT|^Tpt?e-@IpPjclG~ra_QnAQdSLjd<*@IFLttdEj|z&z{$x)}phQ&i#yh0UMc%e!sf|Xo-2qg4zPHRe z(ZG&)o2s$>mKn!3qNXv!b%E=<>qEj?QPED?ni4Gwa&aGS-nSoV_G$co_O1g!iXv;j zjqH+hMkFXADk4S{Bj%jLnZucL_Vmo*%%0gh)A^sCdS_0jo*5GYqM)Kk&N;Je{NH;O zx~jUmrzh;f!hBF&?|m;+cTacqo9>xe@^gG^nv_9Rr!KIn-xg50;YLu?T>j#R*%YL% z?$Xivvy6>PEy)uU&;HB=C~C6R9yf^M%!r6VP{_$t{NX(Dh_wz2Iou5Nse-CiOQ3rG zRH$7w7obxK6dXPX3NG3iR_@vpDm#=xU3n?`V=c+`AKlS&SIq-+6_xB;?PQx0AYK3Z z#M-nj4T-d0vxEVzUnq>;?MRW}^_N^ord|mMX%`eOTp!)bg%wLOaZ=TCzy)%^S$?{c zvhERjEQ2GM>)_bpv;gVy*@3rrT|(NMldJ8I$fIb}thp@4_T^0*Sp_#PkwXwyYd#TDF1e_8p+ATMwx2+zo15v;rt8rpid9P>rB_6jWo~@kL(OXUYe` z)e=($P&?*R<_cPzep{V#PEbzC!~`tBcwj2vsF0&ouExF!TLo0kn+nx4#zS3M1(Xcg z1X>)uH>}#A4Xkd0kwqB8p~cW-RWX!)I~6M490`?UW&kWhLv1k^dHlOw+;|AV(H0~r z{0J)EMbh{@)*l!rN?M?}xL9T54v)K#FU3od?NTg6nHwJTrFg!yE`ov$+d<)=-cYj5 zMgTqAKvmNMD8!SZ$;v7ynZ5*8fA%9({C5--EGU3xt$RW<`Wwp4TEc25f|^2{ROkmM z@vR-Dq@n8YJiyKZadcYyK(;uDO~j>kQ-a%P1HH2lB&*5J17lTkG4h&3cpGVp+^v$j zd;uwjB#t%1rOYX@u{Zf*TtPuCl-5;3!J_FzuMX zwX2|J4(`;|^8tFdgQ8srLg~QXu(A}Z$RhF;D}t96z)}uMmR3Xcw1rSJZyCVKYD|qU zrd(GG%%xt>Jn~2zNhcc@e3r+=DjRpSaGQi73fUm2_^QN$Zbb!7P%EIWsu~KLH-n;P zW%$mo0BZ1@Dl997@-}VooU4SIX|thv{vteG@ce38j;9mm!eS0^@>0cC0bX?7VF=-( zAvriQ@*MS@(3!x@ZMf=uie+T%J_rNEvqM#P(GWejmx`UB9Dl?8L4 zs%AM997lJ%-ER!I6YRHKjSsWpHZ1iSG z>EgU2L2xQGh>-$w#a2)1d`kElQzqc?}nHHKU@6If8na#4P|H(D*e zv#rMCvl5FsdXr1{l1lN7Dz-Z6%Zj0}6~57J+X4$dEOaVXLEYj-01M|s-J%6p++n{A z=fzdapcV_eBCKDEig7N%CZ?`CNNqVA?e;8dfbc(wRkQ8sbjut>cW^z6zyt~&JucA(y91n$M$MlO8XNL|>( zn9_|wrrPhbF6Klcu_0KXQ88Cj0X54PLG`RjP}{r!%C^}AN(XNOwVhkzlt5o{D1g${ zHBdNhF2I!8P_(KFikmiv;#%DKi&j7l7IQUN)ZxCyHI(Z_TV$>q>j-CE^2j4AWP3ct z#mCxYPf&iELxE)a*a6$HQ87jZ-Kq+_;NrW^8a(fC!YZW4sbx5s;k(l&&6`1CQ2|sh zUJTWfrr>#32u00X;n`lo;dBadXi`&!>Kh}H zzAg-MmF`v?^Nvm(am))siCoOBSPYd|%+(dFf)+;(g;gz^@aHZImRAEz!Z+Qcjbe_P zC%@hXI;4F4(5`%RFB>h?i8}l z-Jxq<4h1doO>E0DsB2vY(6u#`Y}g4(y0(LYX2nobi8aTP1yHkMDb!Zud|Fq{Llzeo z;QWb$U~NNp&bSD}MmBC(@QL*iJ{r|9|1?%axHuzKzcsGdI^3j1|~@*$f;VV`bLg*&&Pun0=9XluC?tKx6R zLgkm=1I%9rMeW)^NfX@ZE9lYCLa3Ux2w){{g(~I<=BEb@F^@cQ2J6_)5K%dpj><0& zXcen_(Xl`>yOAK@GS*;OwgQW}Wi**pK~Y&56t!#tHO2VGsA(xrV)R&`>h~#7HFXvg zG;IMz<@ipuxEKpMde12H;dpdj^Q4my_B>!iOg=JO@|4LS*Ol|?b?^*=l$s_Q`*abv zudQuIQTbXiBuZWF3sQv-3xY%_ii){fEavDjD-^GWR!8g%%UhH}EfsUiYOt7F0CiR| z7X`GDS>KW{kt&uDVK>$}k46md>xi7<-JYT5KkVpp#49U-i#q!FNmVV^8FYuPuCxdX zx)M>yb#4uH8+HWPv?r8p(HF`$-T;a_w?!XJvvP@e^oj*tO(o8!byZM^O?+?+-_-Cx zIM;FkM@4ex;3r3O#Mbhl2yoRPV(lk34NkZj%a$RifHI*zP7 z)`6=JTQAHw5-nd;T%A%^Q$dICD3{S^=&GQ&WlJb())Xr7&1qqaCQ#P8B~;@~Q1i`C zP_=qB6gO)I#m$=|N1qG9si08a<&wEs&Kj7-xOnIE^rUsR_LGujPaQV3*Ui1ZHbZR_ z^=|WlZK_A1P=2OI!HPqX_k(3usunm#ylnI^9xr3d@s0JO*-%il8d_2@M|U#lOEfe$ zPo!dQa=4h2@eDnP>_abxv_(SMB7Ed}=h27}_ZpH(*{N4LHF{D(L@oC8s9{wVz+!w; zy9f)j6)X7*Uxhdi(%rebGA!zvW7XEK89;}YP}jB@)+8;UtW#Sk?a~fbw?@C3)lj!; zDb(RHUxPJF-;2#NI0SR&9Q_?yt!)lmv9kAHbam*?%__jMM62wW-2X>VX zd_Krnn#}0)BTHA}yUf*4)U*r=nwLXOIle0`FNK!vT0zAUy!eiv4AtmX+oCyt^R=2% z@uVmUI`uCJ;(ww9bKv&t$tqdO)KEEHC{Ffj&EnQ@O~c#{C40Bc09mQg8)KGb&ya%J zW-Awp_IOH{oU%!ZE)XSD%&ovT){AhCE~$hThYf{gvY0DaS`7u0=0n|>DF9V8M>~6( z^YK-W6xkafU2~4j1(~B{-XxS|2ycCL6txq2sLveO9dIc@UPb z;(4*KNeL8`HGzUASkTeeRxuCVajUGWfyyFuY1tH-^ym!L8+L}ePAvhN`FB|L{dlPO0o&N$VfCn=q59`(Sg=(9v}guJTlRvIetn>>X*pCcTFyUF0`u_& zp|8Hu8WXrzin*e3D@{97#_)>DmPZ~w=z}|l&?#|dQOB?@#MH4Vdj`tpF{?qm>={N3 z6?60?V0AT4WXqrqD>nMNJ~YKi42!vf@+MH!suk4yIvHwb&%^YEP}H`acpL$EaW0@f zDCkll)o;z2E3PFJIEsi2nwYa_0*!!t?L2!2A#7_4)I_c(@T6c*ieb$JGRV_I8wHV; z7J{Swp~vN=dIUs`3GVsAfyW;`h_7C@5GohU!Z+Df(DJaIbum}C9E-Wh3+-Y~<61j!R`?nK(&0$1N|Yn4>2Z6*w8L!lJGMTMf!ZSVz!jiA%7T zQwSAJwOEwZV2x5!hR1d5rU30*Ktb2`P|&R-K&Q4)&=TJi7u7;tEf$8WabB%h4z*P) z`PZEaF;@I68+}%<7SqxsOpVSgaUO~F#Q(;&sIym{tL9Ox{J4-KPjbP9KCcBKd{`n` zWT?}3=F%wU*oXbpWFTeiYpbfUf?W-@t8oKs3!rLQ1ys>z;HJ)lYHBkVLe1QzP`7Xe z6s$xax@F(C1r+Z(5SsMs1-0d6P_q*9L0nQS7w2P`4P*zveBVq)Br;y|9?0LJqe@{mV6ijM?PI*d+TK zVeBo0iV4T^Hm`w}DO9YTfi!G7uk>MEaZ;l3EjxnmY9Oe?rf9k|SG9CL7IQP9u(TRl zAF&H8ZB_&|1;tRbq6P}5E{57Mld+hS0U^kQj3^&MoGk+RLT=rHK6VWdN3=4rEEVpR zEIL^MiF%5Dw3@ygL5)6FjBf%9i%ao1#)7W680zp%tbAU|4<@+Gpr0kdH^0yZ3py<1 zim;$7>DdvAy0!yoT@HYufJI$h1=cUCv8cmFPa^B8SK{o6b1fEj;uk%{$5+Jfdg9qe zk9&D2>}kDu-3j6tCSK5zXGQf=riH0fDD~7BINm6EXRZv3IolWky1-CEwIaL_(}R%l zqCgjr(sHa^%Wy~HPOC<)rUXN=$}J$ioG&7!Whhfs+_VTvcG?U|H|z>ErNvM^e<{>X z!eVa5Qn8oSizJ4W;L#*Z*#|2yk36Em$94>S7m-vk42j-X^r&I^Dk!Kz1>cRjal6~b%hA6HMFjRm~ADPA49 zO=8=Wm+6f%tC)v;xKT%WrHwhdGgkxEOXfk7#-P!|mYJ+++C~QW5L8l68t5-mE zmS9o040Gd~XZjV7no7)q1s#1+f{QpTBB_w0#;Zr`#{&jn&S+{ISX448xR%_JE;@C> zk-2W9D&_|7DT=ui;2+F0rb}}|q{*PLs0fOiltXdzmQd6hcSP&<*g8OA>yFquL1CMY zP~55ml(%RD<@6Qe%9XGhtKH%O-Jy7cPF&2@EWm1a;yeI+=a;);&I+a#4^esKp-vhv zQWY_gvBvRNN5x#FDCAbqH&E#@02X(|^BW~q)M3x#$)-~qW4N3epUxNh7Wk^w{4Lj7 zEF9^J5GBpZp>?ZPP*+t2l{4o+-K1GigvA`4t2DXMr(S8YBX)x& z<@n|suT1otpv5znLFJf9c%0EOi=ab8rU?XWX>Q9&o>Oi{*&&$-b6 zT$o{_;TdY(6{mGpf;kg)&LLIZ>tb%J1jQWMIj@0WQlwrqx`iq3&XqxNSyLz}!yVD2 z8On4wt~u&0pp@$#YtJ9CS%m}`c`++n-IlClDvlChY>>s8ULWw83k$#{IxacdqM zoX}|0$zJIel#l3in9ntjbrbsdFdz<0Z0gvOvgxbLild$z%^k#HqdRo`Sz>$xy+Oy5pSLy*(6mZViQP$^n|x z;C zq%Uy@it?Z^!hOsd19kG7P!ol)$%al;Me+v>v59YI6rwEFmhJ%H9>%@18me*Qt5+?A zvUW|Oe6zk#-Moyy08uxIin)d2F)f#{2-+gCRS3y3OxXt=WB_A)bRK!|@tP%kIf&wh z3p&e7v4FxiJY3w-x1{hL9iNo=ZjL`!w;HdQmB`bhSvpuLPB%&@=wK{qfa{gWYmWLGDKmK_)}lv4xP#wK%MKk22Vzwrfj)^ z%2_|#P_Hmn8MlJf$gQvp!G7eaj*cw}u`7hGb_>nZBvYf${S*Vf*p!FfL zn8V|<6yJvw&0Y$tzyBSJxe9q4ayCyRs9r+T4)21^z8opy@@QP}9tX%VuNp!2S~YkU zsh6^TgMkW(SaJY;?1T!rMN6z_lroqCGe(t28 zWm71|!mhYSXDI5?1&X?0ao4697Is+kREsZ6RM%8M<*KDng>TqvtMEL*H}3`XW*t`s z&mwsK!^(lO(y8a74d1BHpP8XXCpVrGMJ-xDNr!fLLSm6eG4$bGD(tH03lrFr&gTxD zL&8NYuyKASbjLmUS5-sps#Q3B05omh5}LNaca#{v>^Hm^SJgpjc}plPYlf#;F{Tx7 zpj3)=0b-6)t&zc4<#dWU_wZBiiN&r^iqWWJ84nEXi=i577SF+gj*7VgXnl}zXATd? z!r9AU^$(K(mf(epjzu+ql~i(MS1`v`_Bigv?3G8M}`QMjOjuN3EP`i5+?awu%w z5(~R_P|&FjK)V*=Td-yH{npj|WeNKIy4saXu-*|ral$`LOiyO0pev#uImS5}3pu)r zM+F`?8j)ohR}^==0kRjoDC9^?T+Hc$O?65~STeW3mnE7U6j-KKi$z@(ZrC#Z(_f`{ z{U{r>F;ul}j+N|csGYe8i@8O(lj-7xS$Lw5c^Of%561W!lv9d%>ra2ULXa$8>)IqaSC@L@Ff~~Hu5^Cvh!OCyK)?z^iwKzUdQCH3N z5EXa&?i|nMG!&f|bY7};2+mPDmqo)=->714FcxzW&?i4ZiY8~t(m@Tv1Iv|B5UWDp z`KW;!y8XCpDHK&!K*^T9p{8Ri{$=`_dCQ<~#zKJQ^!N#PmM-S7sZ^vgv=D({>;Oid zJo1QwI<_GrCyTr~Y+TS`N2^Z1zeFGUU9k#ks%rV?O3FI4$J(t7 zR*wG-s#jyKvKCO-tR=?KokAW3`^E(|@0d+moPO#GFW=s>_;?-S;U z5VGZupgVKbi)TaC(wR`$x(Hewu(P}~R{$lIIE&9-3YB9g11zFDbLJdPFlB<2=~y&D zgX(k3H4@Am9;7hm(MX{WMgq#LO3t*As8oYysQHy;+4C_b6*^w|H|em5q8}JuvQm7O zuBJe|xh)YtW5SOx zgbR-;%8#cf+c=MB2S;>lB?l0H9Dgp*B+woq6^Kd2-o33I)3_63M~0PkV3 z!VyrmIG;5S^F6B%);7lYlAHS8oaKiG?M_al@Er?5F-XQ%M8(`9EasNX!iy6YbNh>8 zj&8yg(;I?0%YtH#-*D3vk06tUs!_#@P9t<&DP68e9_t^hb6LuYvup%BUbKy5>Pc~r zD*|$SyeS(Ux9D7n6XPUhYZSI0a>9 z7<>qnONx2qQD2|~UmcV@(NGhrKK^iWp)Wp^HZO-(ojXF+%vn&issak>kK$tiS6ftq z?`MkmaV!0i{1PnYim9k;O+{XNC~AWR82!9R85MZ+P7==*dW=wklhR6jr%6A9q8`Q4 z=k##kI{D4n=B-*oX>}b`%$S39U^V7x1;ypf(1ZMplW8qHS9nh0xrGJE#zFZc@m)hm zv1+`nDL@`PO=6=r&0PHdX&wB1p6e9#s+*%t(TQ_gHW=bPsz@Vgq*Mu&snT`YavU=y&O`sMCcVfq3qffG~zrH>~(x6#eCire#pr z8sCW1UzX^K^LDomP}He4K#NkG#H_T-4+xJD&(lgiwW{%E3B=AqE$5Y|Z-|kS<7B>)gV%@9-P)&E|=&`c?i4rxA?772*q6sY18W=k{1ayis=aEM)K<5P= zkLK}7P`W&x>8(w1X)(0u&;gp1l|ki#g*>-VaaD-LRaIRPy5fXDe=&s$HZ1Jua~(xZ zn?X@CoFM3T9b2}7q86>81Pi^A=Ju zmrt7stCy|BVv+6$w!^XLixA>ucUOH)LlX(N$2 zAKV@6^#> zkSL(PAfXOqK5j9NbEurECkUQCTgQJo42!y&CdE+Otdu`n2kl!y0X>H8+!jjOx5i=* z-$<92U<}UB^ykA?EaJkhrjqX1trBZ~= zeZfO)h(ItY*#5!;F9-CznMK?nYC^#a%Q7fhHXjP<^KvV3hpom73nrq^0_n#&ZclOI zzvPrc(1w5u#gnKw(Xqg?>J3O=Wez(aED9BmONjLPBtWKd^#T9kkpW^7S*Fwj`VU!y zjLR2_MZ(9?(&Sk-2rZ&u%0_3}K*+@*Vsp7j;*$YVtz$~WoTQPdQk~f5jH@6S%BhX6SD=S8pw5)Rt2tExb)n&s z1!>cBsO*s!p@Gh>tdcBwtp~jjX{i(;YF%+sXH}1b5QOX{LUso#M#1Nk(w-36#5N>y zbvmUwe_XqzOU2}TGWVu0E-ahsC9gTDv#k0Ej(gc?p=Gxhwz`r+sBMZxUYjzg?$!#b z`n7?oZMs9vChgc&`{MCH@2g4WR*i)iJrP;48f&3d_y&o7HU*2gd5fTC_5!G$yAWy@ zF6F0_1@xD+3aFTD1_fo!p}4FW7MD%&{e4p?DlUVndmf=d5*Bkv5v@*fUC0SV3If6- zDCX$=Dp-Z@{O8YxqQwiKXf=IkmQ4s0SQfpWc-%=q7^NEM0@@Jftdm=2cYPG0d4v%s zMAIl?QK)!aLZsIx0WyutCG3|uOGG5|((wcP4p%ECWKUqTcv+a3T!=uJoHm(yAX}x5 zvZ-Fd-~}sfisw%D1Zzi_z62Clc8e^fDZ7Hf8=Zj5Sw@C4ia*{2Qy$)nq<(3@n=;*T zVouV?RH;tvz-~!qJ~p^{Oz#MrIX4pLn=6@@J$FuzJd1|TuB?(Qd94S%5NW9tAx7y! zR0f0+EzV;%!CVTTl=g(kCbprGt5eF#<4NjLT9<-p_sQHlzSbNl8-aM&N9%Gyy~&xp z6t!+~W-kSYuWsKIss?v~RR{ME3OjvFpcBeeBGE6C6xP&2Q5Ck;RZy^e6&G>UbLh{S z&V||qOQ3fCGN`35X{@Zq#0C7>=0f^?(6Sa#RNev#9)DeAO;XH>;*Cylx~)gDHb^0W zNG6K8!ljF#X!cAf#$M25#imD8vgid(f{?T=Fk&ZVec~#c>IqWzoag~1eHf-puyyYT zz+?Pvn2BVcE;5bF6~Zrb7KljZrQ-+o9DWFcwCs*^C{_|q467y=A`n_d!IX_o*`fMW~X z3MS7oE=*487H9TSP&&czsT|M&Rvxt(RPEGD9v8;JfyXSl(!5EC_2OI(;e>(w#U9;TVO$;`(@EqSFLO6&9JpHiRxv>l<>q`4P#ybo9WULl0q) zmfdj<#Y(~x6B@@Qw2Fc$E3hbZ5h`uk1qG8QNZs-$SUUDvG<+1PDd86`vXn0D0Zb*r zra8+fHJh_l$3|ev!$%?=-xP>V)llQ4fv7w=T-8Ky$E)x08+!ZJSL9+p>l_iuT-xbAf#9{cO{g4JQ<3AoDEf*bb`9p<-$N9A8hoo zJ^Icnec!XDxDaZ}ilMqiQ>bg(5{kQafbtEyLDSwnps+_L{sRmA{B^}rs9U-aN+!{l z3sMwwJdWb9(?uQYLLknJE1EY0$|jA+%5sHd;t<4H&|}Cx7I997&Df6Iqh6A(J;>SS zMI`dlF}~QsR)evOj%O$k3F164yfk^^IM* ztVka9f?T{5I!8n@m$r1ND9*H5vZ1hu3q?_Hm~ERBv@RFaD^9_*Nl`0`Q*d>H=}$nh zc-C?#f9Dsdt*L|RExIFFXUCF^jlYk9O%!$oP*YL}Rplj6)1n-T+O>wJJ-R@%4ZA~8 zw@y&orUevzJc+}_*VYn16l~N2m_;1PB~yQcCNm~M0sl=&WwT@aK%XRT438sICZ8l( z;sF`ydFPQB>FikP8xAoHmeKJH1tQ_&)Y7z>6NrN88$-+D15ADaS= zmfcWdbDjl>s6Ks*5oeABxkCa`dClG+OqwP6~@!Q?2$<_C&pBh zrXxSsSLxpdA!+`J z6DsJ60IIN{Tivu6D%zAoMYlGvdXpYdw{3qY+HJ55iYexJ2z8+l3X9yk7Z5DonoJlA zr3>duLc($L5MIiLbjW3{5Ri|HWt)3vuJF-R(Gi845ZYo}v4B8HcyE#pEC z1+Pu&u8o1ZhYCoKogqon#Z4zCrGebt11SlXi^BPT9iU% zm)20bG2P)4(8Zj2myLlsGq}*}fik(7p7b{(sgNsLwwQI(7J@RyUQl8)L?GAs5E1K0 zY=#+g0CiO4vNaTpy%w_*>8Mj?-Eg5~8&L*_aP8jLHW=6T_xPGl;Q$Hbd~{Ttt6Ope z^me$usC&ar()E#wHx8lsz`=Hn3M3dd%PlUZk%BfUSDVFoGDwy*B+f6R92u-@9%~#~#aq3!Nm2AtFnO~PQs^a<7elK{--g1mv!H0!awu9{ z3B{}Ehq()&sJ0La=!YHYoYM2WS=iMmo_Pio;b;yHnS%RugJ`7sXS5g`%ZPq^2OwE^`_51XDKQ@=<<-I9obMH;?U~tF=gts8=9YsPFu# zkyat64(t#d(o&;iG);o3`25Xc&@BvEH96B)FR(Lx5T?z9OPRXP5f$g~-Z2$S#qlF( zN(f;Og9#aH=BaPmn^D;7BBw<)$e@?tKR<_R(|;dRQ`g6-GUWRTu}#w z)mWzSpEad&4G%^$mw`mZoPv45EuKFcN*6evk;^5LoIvgc$_LYhWn6f}e5BX0VG;4d zHA+P6&a?|TFASbU%MBH8m=mKB;ct%ZEsi8-$^;bkHYSV)v zIT%Rb(m1fTZ%C^3Gwf-&CW7)$H!hDn)Ws~_YntmH8IOiI-?R!kYJsYo5?B_Z?m0#_ zWiUi7D_tq*U$&$Un*6d7>VB94wO{`XwO{-QRp0&s1(W7N(ZW?ww5k>gYVf4vFHHDP zzO;%touhI!l+Kze6@_%qZjZk&1#?MqD<9L>$Hl;P^QDSH!XeTEzv%jvZ^Xcz6S;rV z*l|ew`_XB5US~buvAlV z{Tv+;$%G9EgS6~kXAhG4Wq^82z1AVy-JK*poBf&X`sLC1;k(S4ocA(_WXQ+h+@27! zNx|!jilrNk7Rs(U+3RK~>?@nr12eVe3yYv|b|t{X1yDD3D%6e`4>hBHgW6xFL*0x; zP_VcH3M=ZcsH3}dbTZf{M0&-XMCq(4^5;i#gwRPEb=JmQ79$O*ka1xBf?i;;X#9xS z#q?@=O+M0FKoJZ+Fnm6zT=TkW{DpgtBS$D5j({A|K@+2LqlE@4%3wkA3chVIIYTDNau3CZ z;{wJCls&?vmBL+EmW%3^dVi-vbmQQ3r{e!lNw=1fxr>KujS2^QyugAN5 zokgxMTV_5tx9>WsR8^o6G$(r{7%r&`I%-OH8i8e8sHO}`lxj#YkbW^YZx${yISZYbv{Tpt{_vzp z(-}Ms-*nPOfnQ|zm2RZ)6$yyg-Q+WR^ThA$aEL)zHdMT+9NxDMCTGYj1q<7cfx4!I z;HVO&A3-UyH*G8nLeuWJjv9@?F}mnRK5@Ra0KV66eM5d1Ao4q5t%2_{XK_+Vc{xM} z(?`i%R7q$qq9-VS(`NbMA}%L^WZiJV{<5)d+NlvIn?%#<67fsH)!0_y@j8DMz{I&w z_x(hu{pKgA!5${fgTh4>P*@qnB`W6BADS;%y%LI-iry)m4 zJt25q8b2Z~o`Q|o-#*%#$KhPnS3D_LCRAKkCQP2>kdw{1c2*VV#-gq%A=@5Ga}3`7 zK=4P~G%BvHVHpG@<*`UaTLcWd<(ewaL^{4H5V`NxWi;S6=V~Z7PolgT1?90eBknrr z+O+N%lxh@7whJoSNA?8eZ*fM?4Hu@L*%Vw}H$&k(rcJcc)pbx*S1cZ*@-GGBF})HE zRMh=G58#{eQ1{I*P&aN06wC^KO@xa%Rjj#i*&_EZJb01hWNIKEHseC|MyGohYkV0z zvd91c|MW>jK~&=RzZUh69F7~Y4Y`*HU*b+bp?YjuccxRPZIhDt19TQ zmV?Dr0FxI0{4|a4)WOfwDUzY@%((@fufQu>vPepVRA*y^-J(rJ$l>dj6%a-e9|yua zVN8K0V)vJ8bo5ZHFPY>l6Dm=;HBCNJ)F93vog7?FY0mK_Xq9Y+ zN-*P$&i3-yST=nSk>fh>@ln1SDIEe>u4%;O5)CnIF2~66`i9aa%&*;);Ejt&7B@zm zEf-jmW9Jbd@=}t?H71Q1*Ohf#_;}43cGFK4bf(RfxfzNQ2?niUa=s=}Qi%&)%u&Nq zjlT4-8u_JI(9K!~b-&Jm+OgBvpP-95ALvg}ar=xZKC(6I=|q{x!?AepRH9*qi-my%4bF;0w| zLhBKJs#sIdyzB|yf=(`c#hHTA&Bj1M7k1PHWi<^{4Bry^Ejj+f``DnO_z zvAZG8XjeN3Lw8J0DPzMjp%QYH1b2o}izHw(buA0<_>p$UMoX{VA`yxw7&gWr&O9=Q zagFg^Zjx|OIu%5w(c}#};AKxxv9e=mnRrDaG%sQ5N;d7J@H)t50Qf)$zv)6%D4`;b zi#O_#&^k8y(_U2ItqKBAi-D1t9IR7ax?>?g5#1V88C?tLb`>#L&by(#~!bS zk1PRG$@vpPl%_63${z6Au^O6)f9ZZl#6R|VHI)IJ2E|fm549q2y%de$|@mP z2ol*)yzE`KP*_x+6qabCL@I~C9_yKMoOK!M2uqHPUluPfNynDFkVCk-2W0_~elP$NSwH!a;<5&n^BJceAZeo7=6 ztU*@@(a_`NkpS`~6#T;xgBgyIzM>Iw#5K!0S5 ziZv?Q_;D+iYjj6WJ$_Z3L_v!)?$GIc@6d@MzWnF!prEcA69_&463jUU+$h0F-txg- zi$dtty)zuK_b#w$-(FDGq=dQZ>RK2#VIsWo!51*@w~5R#WQ@wgn%bePkf?>AbK-=k z1W75~;2FXwdxFnS5JC{{_$frtp>fv+BrO)CTd3G@5tWZ=*QS$N;4v)DP)t6mSmDkW zV{)diLN7n`P)U~n8G6ke(vIv4gNqAr*~SE}F)-N>QL zys&(vASq=Noxu|v9}QD?OpH`^AL;drLAw5HJF-2E62(g=*Vh~C@r{eKCprN|S@Wyx z32sPYKiM;+;`*3~uu-ixpNy(rBR^UP`nzA;YSC5)O~3nIm{S#V1mc_h^bJbr8ahZ# z&M@K$BQ(jmKJtWWR^9}zJmWanV~4Gvv_uqfE-I_4;D29^ggYL44pyvOrDHjlPUmt) zuRDX2w0U9+lhh5KA&e|qvP84;GT46WEp;Kfs-hCU9ytb9tXRo<2u^wdB)$9^M#OOu zf^>^5=Av>j?b;08GQ|`jE^p}s#Tf=Inw;OxVz97mW~YQ8jcM1UfO3kn5m2_RsA)n9 zuFf$16jBs&1g1Q^1+=HilNK_Fj}6IoeH=ul%izT2TnXZ6;ts*)Vv9NI4RfO`=9H{> zg5#rM>W+z#%I+h*elbYbe{DxDPNPIQq?7CGjrI7(#-S2r=iV@ye%=^dxI7^)&Ln)X z3WjYSDWof|Q0aJp$<}n#C^i)}89eL;mJm_J9HDgn3|vOrqY)iL1<;+BpAEZgGZ2c4 ziX<0b&YzXgs@)fP9v;;`P1VEcI$82*v?6^UjZvxj|dL|sW_pY$}(CuJL z)W`lj0cOmaBRv{1lI$bHCFjMQMWZ7A8;JI^p*X{!MU(T}Sqv7IE$C<=^dOCEH(-qw zZKHG3wxXs9DY!br^b?>=_E3%kfhiAf0qr4|R55YLAT~0D4B4zp1ag@&Nv>Rt7s^u) z`zDWdAK4r>iDS{x=j)A^q-l$dMZvWz-Sja!MpO*JowuW4xj8WrDa5THH2U5g@VEs~ zGJ7VgsXsH9F(TH^z>)jx3S0K?!xt(7-CdhDYc9P1#RzUBt2=Jwvqk^DaO8fwu`Ymd z#xVX7P1f(>MbZ~2XUOKQ9L1(;^@zl~D#FoACr#?}LoP&n{4^EVRMEr@7ebbWRIt#U zt!vUaeEfEXd5pQoo1x3m4WOfqlKNn~ZxulATL9nwEHeB#NifVbJ zgx*b_{greVM)_s?5@Z{nNBy7yE+;&IZw&9)k}&zGSOyBAJGn;BvLv)FdnFSr8w#qK zP(F&bbW_1*=FqvY(H9`3$Q*wmLiLiD(0AtI?#dCwojD)UJ?oTz0i1T^e$caPXQ=}W zA2k+Ez3LA5=&Moi(U&9P#kW6#UOl=(?;c%v{Yr|9VdbjT@V_s=lMx2w`t!vq-BmJy zd3yKk2HOwb0{Zpo2^;tB32j=ngc-Bx$N8cYck9v-b{o1KG;3PUIz0~l`15ZQ-I;6F zvzI5ynf5-u1NkoTFGa}9>BMHHkgI-d_A@Dq>!`0Wg9EXPK^k_sQs+MpJGJHg2-G+b)hw%e*>vtZ^h5f>AK(DtW7hU4S{ zxg0uGu3T?sL+rLS_|oLjfXL)^PCEtzqGCe4Buw5HYuP;xp?HG`*&MiB)Vvl!`}mdg z!8v8HF7<(P$sBQKjz2S(s*ocz|M^=Xa6-F)5LF}#vPYn3eU3x>5ZDNhTz?U4vw1&e zs;aBux!2x@N1uO+Y7_JiQ0L-&EQCZ(+Z@XPOT+au4iOg_gPuqT{*;^9zU)`Y2P zSUg>L!#yx%`fS$8=fGh@;qtRi(1q5lx%1(w+a83mzx>AQ!9c%*_t_0jKKdZ&(X|u4 z4#7U5yMqfCFNNp-^A6f|9%^ud+`m)+BoO5W8viE4uKLZ*mw-wZyRpV4R+mW8|DZ# zH8n8&o6&I1P4~ind+h>eoOmR(Z`Vd|8x?b}zw;5?{ovEAMfiEi(BuIrjvI$+N$|ifZi(XKHE_xD4mWpXZPN{-p zLE4lcJ82U%E~SZ~WEHPq>W+z#%I+h*elbYbzcHdgPF)$`iwkiPzA1HwFjbaQ**$Ri zRP$Vfc^-X}m15bB2bJ>EpPd6}I#%4=Dk|H0PyLy>I7Hu>GoeO8@K}cK!T!5$58XPo zXSt}b5Lz^A3gahDgSiV9VX%muJbf0t{^95F?{`0ef4}!Jd_F>ab3>ZFYp`|N+!-dsH!Nf%K;3 zWw7D&=M9X>)@0&KI@=KQ%l`aB_xK{1rm%vFf{v`4qj&<%^zgZJCR zD&z>IrKQksqh4I}eUJMj63+gx;4wuOa}l(FYm~Zc*PY>S`WUo;4p0kQM!2uHYqz#P z#wJ9+O~cCN+EJHOzL1MThGXRdu|uc1UfMk-t|2xx-7#{pPH{OJVw>~G4KjVL(u$ML zz8G(w2>(>^EIUqV+auuGlFWP3WhE7Jr0|;qDKk_LP%^LHKQk8xu_8ZBm;%*UNGQ;k z9Ga- z{kUIQR@k6>XV`tGZS}WlsW|%K=U?G%EF!=9?g#!hEupBW5Qc8Q73{d}AlB8oOrAOu zexE#zb1RTc+ypF6=TUKLfbI~Uc+9~#ZWqY_ELpl7KKpVc{P@$aP$_@YkM6MTvC9r{ z$o{*t9tA4k2I0PM}GWe@w+ z$rLh+o6JYY4rm61gGn@00n?XYo_H}fA^L3^Rxa0$x}*{nau$4?fUw{)+QmSeQ_>ts zkx8Wp5!10Id4clzq9~LcL#$Sl=fxZ>H&A|R#j8PscW?p~)Gq&xr{UF$H zw;lCk*jaPt!DG+;n~Nuf9R_a!d+)jfe^!k!W%?{Q{gNBuzn^>w?|k?fv}@A}Htf-r zi@Nz(m{IZe^RL10-o1~0Q;-|7?Uwpc?!rY&;Fh}|hrd4YPxxv41m+YD-G2`_XrJA& zSQB^Ae*1k2oPX6V@WOxIhF9PEkk@U{7Mt*$vnEYSxrlrh3(Ej?)}1-pW-8+DdH5N) z?7F|exL+o)U9AfhbR$NMg+H8e89esXzo04d^!YrBB~bA?X6!G~pVQ-)#(Dh|3_1{f zzQ{$;VT05y8Wr(h$O>B2MgxkI25mR)>sbYs?6rT4je5&XJ0Jp^hLtO1)c%o$93ggn zBn+Rx#q@Ff2~2r-4YWm?yvg^2IJ%kiH9b~6wY3=hfF+XF5wKiM%E#ZMuTjR zk3{i?Q;pNxfgWo4jlN#`6;d){* z8N8BV{DRx{@7LdBdH6S@VA7PJ_@*(w8Zlb@Mjzs<5#L+IEd4BuD*Q45ZJqD+%_Y3o z|JXsD04*mh}IN9=3O0pEXL^3DcxZrv}x4>25+$m%NzIVq3?jv5BZKBHy$N>O+Nd26il8b zo;wrh4&NdB?hY^i{ciZ;&1c}1r|*TEuR0I59=NIWK-ekL0u_tuP9%->$CHnOFW&v9 zXzz(e1)l;v3hmUfoz(o8F-v~o!-MMT8kjdfc+^Y#N$sm_k$5+xyT1&7qx?en61iNo zzt+4(g~5gFrp@TwV#!nqrrnoQQi%&W4U;1|(6!{Qn-5G!*a$JE6vi;T+mQ;H#N-HB z4V`Xq!)<5EmthU=@;ufv7{y2;#QBG8l5ly_eR*7-b%#`{qAcA|3{k`6Ox}d+!v&n% zq)ioc67}?%Id?Wtx_w!8@!sbn;F^2?1_zyaH5`oXiGRHbi{o`f$eadv)SHa$)f{VWR zuwjpGu>Y{3@X#ICz;&0N>D zN!BNXOk#3`oD6LwNhjYL-0VE^XmA(>Ng~AghipV(lbr=0M{s%86=@h8)z+1Q%@DaM zxV&jI5#?vfh%Ab^>}H(JHtGe}ocRa1>4KBtrVCGj6A#&2S_lO&XTc))+e>f4-(Gx^ z@2DxXZ`%rsv`#|dRS@g(-lt!~%-QoQ%N;b%DN zjLYHH2cCpazZwbCXU(;~&_JNOXb0@MGn{nvL6XTH^koP7J-WBw|1`3__u=O-)p<0$ z-XojC&nztB^0+n`$ID=0^aiXke0H&Dm_p9g5x#XY5osqrMXZZdV|kHDOpdSyht3?0 za;5WV%rFXxtPzR(?bFLFn)r5d`Lyyc3W=B-)bxm_7toN5mCZWQsJ$#6_Z^V%8COH$CFWt{DWz-9B#g!dn$wuaPC-%{tOsXbJw0Ykjh}y? z3JVr3l^Q^&_HE&!la7GF1N!ONVYlrD!BP9}2IXbq2ZIUo7cPM*Gw81>I8z9!Uym9K zi{%IVsfgQQtAYGYPQuJN^Wd{@MzbuS;tSyHla7Rs|MNHa@~vlJ1d>d#I@iK4YeSsw57Dg$4Z0Tpz~%{40Oyf!c>ATt;F}L$ z;?K{${LBNeQJ)Q^bv=XiGE2pI=~LL>M?v{mad?)Sx`BEu=H%33&M+(sV#=(!@WrSf_3zBl zXU7I^(gz;B@nZP=`3K>Pe?1I$UU@cu?oDBJWfcq``J-pj63l1cj)v*-&u38)*R)*R zm7}|LKm0U-zbN6un4f-ws;X-Kq5)yZ)&t@H9=RQEzVaOS>up!T;Rg)kp9djOA@?Kt zyO=X?KCE87T59w-xDDKQ+m-OaD}RH1cHc>|0&lk7veWQ{eGu zUSvHx7_WL($W@*Qq;p8cB1IzC94bBnT}vz|4g0_aVd@^6?DUbV?S`Yf4y>BTI!V|Z zH(iNnxDE)WJbWUgh$FMvBK-ZVLcFzJQ4d3>l`@fY@{DU@Pp*kE>j(8bzpcw?kX;uu zNR%lu#4z}Lh>OeVvoq&2NGOxpO!(~FXd$6=Ws|6fJ9EiTYx-G|i*J7f9(mz)m^F8S z_vbQ*qd(7e+oR9HjenJYLsSkCF6j!eX#2(b4K)H4S|5C_{v?)X{g8V2nU~<8qsoW*$@Ov*Kf+*8CO)KAESV9}-$?Vo)i z7jzmiMW_Z-9-d&)5k5YUt7;bfIpQ!968|Vo3Q=*Y{;K`BhX)b7&rcRVU%tRb8H0^n>8(i?YADtcNjVL z7y1hj!p95`lsXu?!`9HUMKjixVlhfZUH~hq9uYBRhiE})I>N5Os*h7J6tg%%(Jt7T z2;eJZH08*&RQ?X{j;VMaTbT@=dnGEtv}+qdC{|Hu`V!pjkoJI;lH=yxeitDh1C}Yu z&zDp7A@~iE?u>YAy`mw8#xeYV1YaVw4sqwYYm3%}r1Y?#n7Rz!oy+um81Pn%X_vgV zOOvok#j+`15{Z+F$#EaZykuWi1(dA(6-?bRF=28(yAKg`B+~U?*O1F|D>7G#L88oF z-b1Dp??JZlhVM-~eknRn!WR#hmda369UKm?M}mLKdndxl^+287M28 z>bXQ>c6wPV9^q|@xH&q@bAX3Kf}qv@N%Lfn-FoS zID%eZgVdrF9Nq8?`w}b%1ut1o@EmC&N)VckuxqgD;}i_VC_aQ}I-+c;rb007w#=gP zH+{I%grppQg5(+2xF~DYlnFu+?$V&`hGW$D8mQR>!sS8^NO?GgRIv-V#sK)7?6o(}__C6}jO7$l{15=oYdWmCQ+5+@at z<35mi$-b-#2-4;VDxTolTz{Y4hX^_n>H4p0$o2W<&6i-1IG3b3)6U@_3!iya#b|Sk zRFH8mI#ta1AG5lNV^=2D=pY?m7tyhFC+tt>o&;|{eGi;;_D<7P2eS zXiD@U&ZeMz;(T2n)d=RB6N34TRs*48PWhQ|^_+qy3pHb8GIJEb4udv>c5PZqU4RO? z36rP86VJa|fAf(}TyG<+A-D&R?4yv$0TL6Flf5aEq<)EPL!d%?iOwxYuTo zp?6#yB^3e_4qPte;H4P8Twa8ET2*4hO{{TL^CQ~gg_|_nR^RZ9A@)=BzDgUuB&y{C zxyqBr`U{%lGr2ZI!JA7B64in(5{9cE(jm@I*`n+wOy9&Ysh#X%E@vmOnaD}1)l`E; z*~5J24(<4xsPx%7YV#K@f!9Cy3@*I!KA1FB{LNK6D$}v^s87&d&&{3}SrX-naLy=wjyR+llgSWk5*e;9g(VJ+ zbd-jKiK1WEJo3mPk`yaRk#;T_KwYZXls?jd3M=JH%|#R+2Q#15Xb}O&9(-m_p4d^L zEq;>U2K6RKE<_uI6Jvd8L3c_ve3cyX$DT#!a~uSgm7PRe=LnVqE|7g3iE|!6;+QD@-T`WlJ>`g0hP~u-d$U6pS3f zmlO;??mfH`lwI>ADqWJ=W;z)%BK)mc)J@7~ccCfA7IO8(GHjl;DA#C14AP9rWQaA1 z#Oo{1XOF*{Y5YK&731?YI6ZF>OkX9VUDGH83c}F2lesi!^vW)Kp_53mR4kh@Zpepv zLzgly*_TxTK^mMCLOv!;e}vEOLj)a(bp6){x6o^X7^hGq{ z-4v|bWKhUSxG@B$Fbmabp&YJ5D8Qf`TgcTD%ZSVABGM3pG-EOuVof4P>l>RU-7y;5 zKFnj?MlLT2Y3K3;5EYjvmED4Lj*C$?x1|eygA+cv{a=8HMba4}+OI+97#=M95gT-! z*G5T1EsAt(p&Uwh*LqIx))EY$o`Qv_tBGE;z@znB$)=p`Mfm zLU=62m=@P7Y7L`!0|{JGAyJAPjMG@)9&@os;jGQ>L7UzvYZyshe8VTo-Q-iT1rSqRftJ7FNvM&|j1%}Ki%KJR64!KA)q^a<*GXh` z=r~B6E5$pNjGk|Iv5ta{m$Z(V1OZ9&r9C!51sP2jdekIsLfK3h zdIq1FO9$pm6g?|tH($BYQrC1;c86DLl)DM^N#e#x?ASdARMWgnDG)L z7q3Ce9MU1Ju}tSwfrj03jp7M5p*2-#B|?N_Y<%M6jT4z{UPHyKwNU4-aSo?*I%jz5 z$D%%R=CNi$uc_N&k-{NS4hiL()ISyxiQHn&Ks^_8$&q~C%Ha%`IF;X#*&MD;qX!;m zxjBwSmYn2DfVdlADG`cw2~YB<@k~ByrIN%lY(i^kZES>ZY>IU9H$r5xdES_Hd_TpZ zK2Pkp+zmCMvUiWNYdzB+;9@9T*Oj6X=O2J0rVlF)O|osM|J&D={_X! zL74k6-4|zFK!a~{x&y8SFG_+#DdEu;kEG*dQ^=93S_qMbbqkqnVivn4*~^vMDOH|y zRxyjs5m+DR$~0=;r{0vu&!qN>@F>x&ksF*Vfy0jm&W_?13keiITU#}b?=?k;2 zAl>cN{xN~BDbm$2pcs?UMqrncSJJcu#H z7}7^LRSuI&z66rJpF{X@>;JRrQbM$Au(m{5UKz<5YXOWWw zIAM~=gIw_DGL(~5+e5(dbCJcND?-f#PO?yL-(bl3XbEjfw~&hk+0)3k)*)uywJF*5 znO>oYWGT`@J)}$xbqb_76>OyCoJStfXsAPp#xYyQhzZU~eng6bj*B_|+pHPR7~!yn zn0lheNN@CdSl4V{u*QO1Zl}(bgQT7V-k&v>8;}C>F!LU5CK+`&COS-olXlH{A=j7@ zv;HAd{I>e6nu`xj4o{w3rH(><=g%XLw9$Z5v<8i-TG~huWaf`+QHUw%xR{Ijb6&YQ z!5dg?Y;(rD zDJn3`2TXc{rBm1E7D>*X49>4S)*r0N!y}`ybF{*gCMs3L^)q

    ","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("